]> sigrok.org Git - libsigrok.git/blob - src/serial_bt.c
korad-kaxxxxp: use ID text prefix with optional version for RND models
[libsigrok.git] / src / serial_bt.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2018-2019 Gerhard Sittig <gerhard.sittig@gmx.net>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <glib.h>
22 #include <libsigrok/libsigrok.h>
23 #include "libsigrok-internal.h"
24 #include <string.h>
25 #include <memory.h>
26
27 #define LOG_PREFIX "serial-bt"
28
29 #ifdef HAVE_SERIAL_COMM
30 #ifdef HAVE_BLUETOOTH
31
32 #define SER_BT_CONN_PREFIX      "bt"
33 #define SER_BT_CHUNK_SIZE       1200
34
35 /**
36  * @file
37  *
38  * Serial port handling, wraps the external BT/BLE dependencies.
39  */
40
41 /**
42  * @defgroup grp_serial_bt Serial port handling, BT/BLE group
43  *
44  * Make serial-over-BT communication appear like a regular serial port.
45  *
46  * @{
47  */
48
49 /* {{{ support for serial-over-BT channels */
50
51 static const struct scan_supported_item {
52         const char *name;
53         enum ser_bt_conn_t type;
54 } scan_supported_items[] = {
55         /* Guess connection types from device names (useful for scans). */
56         { "121GW", SER_BT_CONN_BLE122, },
57         { "Adafruit Bluefruit LE 8134", SER_BT_CONN_NRF51, },
58         { "HC-05", SER_BT_CONN_RFCOMM, },
59         { NULL, SER_BT_CONN_UNKNOWN, },
60 };
61
62 static const char *ser_bt_conn_names[SER_BT_CONN_MAX] = {
63         [SER_BT_CONN_UNKNOWN] = "<type>",
64         [SER_BT_CONN_RFCOMM] = "rfcomm",
65         [SER_BT_CONN_BLE122] = "ble122",
66         [SER_BT_CONN_NRF51] = "nrf51",
67         [SER_BT_CONN_CC254x] = "cc254x",
68 };
69
70 static enum ser_bt_conn_t lookup_conn_name(const char *name)
71 {
72         size_t idx;
73         const char *item;
74
75         if (!name || !*name)
76                 return SER_BT_CONN_UNKNOWN;
77         idx = ARRAY_SIZE(ser_bt_conn_names);
78         while (idx-- > 0) {
79                 item = ser_bt_conn_names[idx];
80                 if (strcmp(item, name) == 0)
81                         return idx;
82         }
83
84         return SER_BT_CONN_UNKNOWN;
85 }
86
87 static const char *conn_name_text(enum ser_bt_conn_t type)
88 {
89         if (type >= ARRAY_SIZE(ser_bt_conn_names))
90                 type = SER_BT_CONN_UNKNOWN;
91
92         return ser_bt_conn_names[type];
93 }
94
95 /**
96  * Parse conn= specs for serial over Bluetooth communication.
97  *
98  * @param[in] serial The serial port that is about to get opened.
99  * @param[in] spec The caller provided conn= specification.
100  * @param[out] conn_type The type of BT comm (BT RFCOMM, BLE notify).
101  * @param[out] remote_addr The remote device address.
102  * @param[out] rfcomm_channel The RFCOMM channel (if applicable).
103  * @param[out] read_hdl The BLE notify read handle (if applicable).
104  * @param[out] write_hdl The BLE notify write handle (if applicable).
105  * @param[out] cccd_hdl The BLE notify CCCD handle (if applicable).
106  * @param[out] cccd_val The BLE notify CCCD value (if applicable).
107  *
108  * @return 0 upon success, non-zero upon failure.
109  *
110  * Summary of parsing rules as they are implemented:
111  * - Implementor's note: Automatic scan for available devices is not
112  *   yet implemented. So strictly speaking some parts of the input
113  *   spec are optional, but fallbacks may not take effect ATM.
114  * - Insist on the "bt" prefix. Accept "bt" alone without any other
115  *   additional field.
116  * - The first field that follows is the connection type. Supported
117  *   types are 'rfcomm', 'ble122', 'cc254x', and potentially others
118  *   in a future implementation.
119  * - The next field is the remote device's address, either separated
120  *   by colons or dashes or spaces, or not separated at all.
121  * - Other parameters (RFCOMM channel, notify handles and write values)
122  *   get derived from the connection type. A future implementation may
123  *   accept more fields, but the syntax is yet to get developed.
124  *
125  * Supported formats resulting from these rules:
126  *   bt/<conn>/<addr>
127  *
128  * Examples:
129  *   bt/rfcomm/11-22-33-44-55-66
130  *   bt/ble122/88:6b:12:34:56:78
131  *   bt/cc254x/0123456789ab
132  *
133  * It's assumed that users easily can create those conn= specs from
134  * available information, or that scan routines will create such specs
135  * that copy'n'paste results (or GUI choices from previous scan results)
136  * can get processed here.
137  */
138 static int ser_bt_parse_conn_spec(
139         struct sr_serial_dev_inst *serial, const char *spec,
140         enum ser_bt_conn_t *conn_type, const char **remote_addr,
141         size_t *rfcomm_channel,
142         uint16_t *read_hdl, uint16_t *write_hdl,
143         uint16_t *cccd_hdl, uint16_t *cccd_val)
144 {
145         char **fields, *field;
146         enum ser_bt_conn_t type;
147         const char *addr;
148
149         if (conn_type)
150                 *conn_type = SER_BT_CONN_UNKNOWN;
151         if (remote_addr)
152                 *remote_addr = NULL;
153         if (rfcomm_channel)
154                 *rfcomm_channel = 0;
155         if (read_hdl)
156                 *read_hdl = 0;
157         if (write_hdl)
158                 *write_hdl = 0;
159         if (cccd_hdl)
160                 *cccd_hdl = 0;
161         if (cccd_val)
162                 *cccd_val = 0;
163
164         if (!serial || !spec || !spec[0])
165                 return SR_ERR_ARG;
166
167         /* Evaluate the mandatory first three fields. */
168         fields = g_strsplit_set(spec, "/", 0);
169         if (!fields)
170                 return SR_ERR_ARG;
171         if (g_strv_length(fields) < 3) {
172                 g_strfreev(fields);
173                 return SR_ERR_ARG;
174         }
175         field = fields[0];
176         if (strcmp(field, SER_BT_CONN_PREFIX) != 0) {
177                 g_strfreev(fields);
178                 return SR_ERR_ARG;
179         }
180         field = fields[1];
181         type = lookup_conn_name(field);
182         if (!type) {
183                 g_strfreev(fields);
184                 return SR_ERR_ARG;
185         }
186         if (conn_type)
187                 *conn_type = type;
188         field = fields[2];
189         if (!field || !*field) {
190                 g_strfreev(fields);
191                 return SR_ERR_ARG;
192         }
193         addr = g_strdup(field);
194         if (remote_addr)
195                 *remote_addr = addr;
196
197         /* Derive default parameters that match the connection type. */
198         /* TODO Lookup defaults from a table? */
199         switch (type) {
200         case SER_BT_CONN_RFCOMM:
201                 if (rfcomm_channel)
202                         *rfcomm_channel = 1;
203                 break;
204         case SER_BT_CONN_BLE122:
205                 if (read_hdl)
206                         *read_hdl = 8;
207                 if (write_hdl)
208                         *write_hdl = 0;
209                 if (cccd_hdl)
210                         *cccd_hdl = 9;
211                 if (cccd_val)
212                         *cccd_val = 0x0003;
213                 break;
214         case SER_BT_CONN_NRF51:
215                 /* TODO
216                  * Are these values appropriate? Check the learn article at
217                  * https://learn.adafruit.com/introducing-the-adafruit-bluefruit-le-uart-friend?view=all
218                  */
219                 if (read_hdl)
220                         *read_hdl = 13;
221                 if (write_hdl)
222                         *write_hdl = 11;
223                 if (cccd_hdl)
224                         *cccd_hdl = 14;
225                 if (cccd_val)
226                         *cccd_val = 0x0001;
227                 /* TODO 'random' type, sec-level=high */
228                 break;
229         case SER_BT_CONN_CC254x:
230                 /* TODO Are these values appropriate? Just guessing here. */
231                 if (read_hdl)
232                         *read_hdl = 20;
233                 if (write_hdl)
234                         *write_hdl = 0;
235                 if (cccd_hdl)
236                         *cccd_hdl = 21;
237                 if (cccd_val)
238                         *cccd_val = 0x0001;
239                 break;
240         default:
241                 return SR_ERR_ARG;
242         }
243
244         /* TODO Evaluate optionally trailing fields, override defaults? */
245
246         g_strfreev(fields);
247         return SR_OK;
248 }
249
250 static void ser_bt_mask_databits(struct sr_serial_dev_inst *serial,
251         uint8_t *data, size_t len)
252 {
253         uint32_t mask32;
254         uint8_t mask;
255         size_t idx;
256
257         if ((serial->comm_params.data_bits % 8) == 0)
258                 return;
259
260         mask32 = (1UL << serial->comm_params.data_bits) - 1;
261         mask = mask32 & 0xff;
262         for (idx = 0; idx < len; idx++)
263                 data[idx] &= mask;
264 }
265
266 static int ser_bt_data_cb(void *cb_data, uint8_t *data, size_t dlen)
267 {
268         struct sr_serial_dev_inst *serial;
269
270         serial = cb_data;
271         if (!serial)
272                 return -1;
273
274         ser_bt_mask_databits(serial, data, dlen);
275         sr_ser_queue_rx_data(serial, data, dlen);
276
277         return 0;
278 }
279
280 /* }}} */
281 /* {{{ wrap serial-over-BT operations in a common serial.c API */
282
283 /* See if a serial port's name refers to a BT type. */
284 SR_PRIV int ser_name_is_bt(struct sr_serial_dev_inst *serial)
285 {
286         size_t off;
287         char sep;
288
289         if (!serial)
290                 return 0;
291         if (!serial->port || !*serial->port)
292                 return 0;
293
294         /* Accept either "bt" alone, or "bt/" as a prefix. */
295         if (!g_str_has_prefix(serial->port, SER_BT_CONN_PREFIX))
296                 return 0;
297         off = strlen(SER_BT_CONN_PREFIX);
298         sep = serial->port[off];
299         if (sep != '\0' && sep != '/')
300                 return 0;
301
302         return 1;
303 }
304
305 /* The open() wrapper for BT ports. */
306 static int ser_bt_open(struct sr_serial_dev_inst *serial, int flags)
307 {
308         enum ser_bt_conn_t conn_type;
309         const char *remote_addr;
310         size_t rfcomm_channel;
311         uint16_t read_hdl, write_hdl, cccd_hdl, cccd_val;
312         int rc;
313         struct sr_bt_desc *desc;
314
315         (void)flags;
316
317         /* Derive BT specific parameters from the port spec. */
318         rc = ser_bt_parse_conn_spec(serial, serial->port,
319                         &conn_type, &remote_addr,
320                         &rfcomm_channel,
321                         &read_hdl, &write_hdl,
322                         &cccd_hdl, &cccd_val);
323         if (rc != SR_OK)
324                 return SR_ERR_ARG;
325
326         if (!conn_type || !remote_addr || !remote_addr[0]) {
327                 /* TODO Auto-search for available connections? */
328                 return SR_ERR_NA;
329         }
330
331         /* Create the connection. Only store params after successful use. */
332         desc = sr_bt_desc_new();
333         if (!desc)
334                 return SR_ERR;
335         serial->bt_desc = desc;
336         rc = sr_bt_config_addr_remote(desc, remote_addr);
337         if (rc < 0)
338                 return SR_ERR;
339         serial->bt_addr_remote = g_strdup(remote_addr);
340         switch (conn_type) {
341         case SER_BT_CONN_RFCOMM:
342                 rc = sr_bt_config_rfcomm(desc, rfcomm_channel);
343                 if (rc < 0)
344                         return SR_ERR;
345                 serial->bt_rfcomm_channel = rfcomm_channel;
346                 break;
347         case SER_BT_CONN_BLE122:
348         case SER_BT_CONN_NRF51:
349         case SER_BT_CONN_CC254x:
350                 rc = sr_bt_config_notify(desc,
351                         read_hdl, write_hdl, cccd_hdl, cccd_val);
352                 if (rc < 0)
353                         return SR_ERR;
354                 serial->bt_notify_handle_read = read_hdl;
355                 serial->bt_notify_handle_write = write_hdl;
356                 serial->bt_notify_handle_cccd = cccd_hdl;
357                 serial->bt_notify_value_cccd = cccd_val;
358                 break;
359         default:
360                 /* Unsupported type, or incomplete implementation. */
361                 return SR_ERR_ARG;
362         }
363         serial->bt_conn_type = conn_type;
364
365         /* Make sure the receive buffer can accept input data. */
366         if (!serial->rcv_buffer)
367                 serial->rcv_buffer = g_string_sized_new(SER_BT_CHUNK_SIZE);
368         rc = sr_bt_config_cb_data(desc, ser_bt_data_cb, serial);
369         if (rc < 0)
370                 return SR_ERR;
371
372         /* Open the connection. */
373         switch (conn_type) {
374         case SER_BT_CONN_RFCOMM:
375                 rc = sr_bt_connect_rfcomm(desc);
376                 if (rc < 0)
377                         return SR_ERR;
378                 break;
379         case SER_BT_CONN_BLE122:
380         case SER_BT_CONN_NRF51:
381         case SER_BT_CONN_CC254x:
382                 rc = sr_bt_connect_ble(desc);
383                 if (rc < 0)
384                         return SR_ERR;
385                 rc = sr_bt_start_notify(desc);
386                 if (rc < 0)
387                         return SR_ERR;
388                 break;
389         default:
390                 return SR_ERR_ARG;
391         }
392
393         return SR_OK;
394 }
395
396 static int ser_bt_close(struct sr_serial_dev_inst *serial)
397 {
398         if (!serial)
399                 return SR_ERR_ARG;
400
401         if (!serial->bt_desc)
402                 return SR_OK;
403
404         sr_bt_disconnect(serial->bt_desc);
405         sr_bt_desc_free(serial->bt_desc);
406         serial->bt_desc = NULL;
407
408         g_free(serial->bt_addr_local);
409         serial->bt_addr_local = NULL;
410         g_free(serial->bt_addr_remote);
411         serial->bt_addr_remote = NULL;
412         g_slist_free_full(serial->bt_source_args, g_free);
413         serial->bt_source_args = NULL;
414
415         return SR_OK;
416 }
417
418 /* Flush, discards pending RX data, empties buffers. */
419 static int ser_bt_flush(struct sr_serial_dev_inst *serial)
420 {
421         (void)serial;
422         /* EMPTY */
423
424         return SR_OK;
425 }
426
427 /* Drain, waits for completion of pending TX data. */
428 static int ser_bt_drain(struct sr_serial_dev_inst *serial)
429 {
430         (void)serial;
431         /* EMPTY */     /* TODO? */
432
433         return SR_ERR_BUG;
434 }
435
436 static int ser_bt_write(struct sr_serial_dev_inst *serial,
437                 const void *buf, size_t count,
438                 int nonblocking, unsigned int timeout_ms)
439 {
440         ssize_t wrlen;
441
442         /*
443          * TODO Support chunked transmission when callers' requests
444          * exceed the BT channel's capacity? See ser_hid_write().
445          */
446
447         switch (serial->bt_conn_type) {
448         case SER_BT_CONN_RFCOMM:
449                 (void)nonblocking;
450                 (void)timeout_ms;
451                 wrlen = sr_bt_write(serial->bt_desc, buf, count);
452                 if (wrlen < 0)
453                         return SR_ERR_IO;
454                 return wrlen;
455         case SER_BT_CONN_BLE122:
456         case SER_BT_CONN_NRF51:
457         case SER_BT_CONN_CC254x:
458                 /*
459                  * Assume that when applications call the serial layer's
460                  * write routine, then the BLE chip/module does support
461                  * a TX handle. Just call the serial-BT library's write
462                  * routine.
463                  */
464                 (void)nonblocking;
465                 (void)timeout_ms;
466                 wrlen = sr_bt_write(serial->bt_desc, buf, count);
467                 if (wrlen < 0)
468                         return SR_ERR_IO;
469                 return wrlen;
470         default:
471                 return SR_ERR_ARG;
472         }
473         /* UNREACH */
474 }
475
476 static int ser_bt_read(struct sr_serial_dev_inst *serial,
477                 void *buf, size_t count,
478                 int nonblocking, unsigned int timeout_ms)
479 {
480         gint64 deadline_us, now_us;
481         uint8_t buffer[SER_BT_CHUNK_SIZE];
482         ssize_t rdlen;
483         int rc;
484         size_t dlen;
485
486         /*
487          * Immediately satisfy the caller's request from the RX buffer
488          * if the requested amount of data is available already.
489          */
490         if (sr_ser_has_queued_data(serial) >= count)
491                 return sr_ser_unqueue_rx_data(serial, buf, count);
492
493         /*
494          * When a timeout was specified, then determine the deadline
495          * where to stop reception.
496          */
497         deadline_us = 0;
498         if (timeout_ms) {
499                 now_us = g_get_monotonic_time();
500                 deadline_us = now_us + timeout_ms * 1000;
501         }
502
503         /*
504          * Keep receiving from the port until the caller's requested
505          * amount of data has become available, or the timeout has
506          * expired. In the absence of a timeout, stop reading when an
507          * attempt no longer yields receive data.
508          */
509         while (TRUE) {
510                 /* Run another attempt to receive data. */
511                 switch (serial->bt_conn_type) {
512                 case SER_BT_CONN_RFCOMM:
513                         rdlen = sr_bt_read(serial->bt_desc, buffer, sizeof(buffer));
514                         if (rdlen <= 0)
515                                 break;
516                         rc = ser_bt_data_cb(serial, buffer, rdlen);
517                         if (rc < 0)
518                                 rdlen = -1;
519                         break;
520                 case SER_BT_CONN_BLE122:
521                 case SER_BT_CONN_NRF51:
522                 case SER_BT_CONN_CC254x:
523                         dlen = sr_ser_has_queued_data(serial);
524                         rc = sr_bt_check_notify(serial->bt_desc);
525                         if (rc < 0)
526                                 rdlen = -1;
527                         else if (sr_ser_has_queued_data(serial) != dlen)
528                                 rdlen = +1;
529                         else
530                                 rdlen = 0;
531                         break;
532                 default:
533                         rdlen = -1;
534                         break;
535                 }
536
537                 /*
538                  * Stop upon receive errors, or timeout expiration. Only
539                  * stop upon empty reception in the absence of a timeout.
540                  */
541                 if (rdlen < 0)
542                         break;
543                 if (nonblocking && !rdlen)
544                         break;
545                 if (deadline_us) {
546                         now_us = g_get_monotonic_time();
547                         if (now_us > deadline_us)
548                                 break;
549                 }
550
551                 /* Also stop when sufficient data has become available. */
552                 if (sr_ser_has_queued_data(serial) >= count)
553                         break;
554         }
555
556         /*
557          * Satisfy the caller's demand for receive data from previously
558          * queued incoming data.
559          */
560         dlen = sr_ser_has_queued_data(serial);
561         if (dlen > count)
562                 dlen = count;
563         if (!dlen)
564                 return 0;
565
566         return sr_ser_unqueue_rx_data(serial, buf, dlen);
567 }
568
569 struct bt_source_args_t {
570         /* The application callback. */
571         sr_receive_data_callback cb;
572         void *cb_data;
573         /* The serial device, to store RX data. */
574         struct sr_serial_dev_inst *serial;
575 };
576
577 /*
578  * Gets periodically invoked by the glib main loop. "Drives" (checks)
579  * progress of BT communication, and invokes the application's callback
580  * which processes RX data (when some has become available), as well as
581  * handles application level timeouts.
582  */
583 static int bt_source_cb(int fd, int revents, void *cb_data)
584 {
585         struct bt_source_args_t *args;
586         struct sr_serial_dev_inst *serial;
587         uint8_t rx_buf[SER_BT_CHUNK_SIZE];
588         ssize_t rdlen;
589         size_t dlen;
590         int rc;
591
592         args = cb_data;
593         if (!args)
594                 return -1;
595         serial = args->serial;
596         if (!serial)
597                 return -1;
598         if (!serial->bt_conn_type)
599                 return -1;
600
601         /*
602          * Drain receive data which the channel might have pending.
603          * This is "a copy" of the "background part" of ser_bt_read(),
604          * without the timeout support code, and not knowing how much
605          * data the application is expecting.
606          */
607         do {
608                 switch (serial->bt_conn_type) {
609                 case SER_BT_CONN_RFCOMM:
610                         rdlen = sr_bt_read(serial->bt_desc, rx_buf, sizeof(rx_buf));
611                         if (rdlen <= 0)
612                                 break;
613                         rc = ser_bt_data_cb(serial, rx_buf, rdlen);
614                         if (rc < 0)
615                                 rdlen = -1;
616                         break;
617                 case SER_BT_CONN_BLE122:
618                 case SER_BT_CONN_NRF51:
619                 case SER_BT_CONN_CC254x:
620                         dlen = sr_ser_has_queued_data(serial);
621                         rc = sr_bt_check_notify(serial->bt_desc);
622                         if (rc < 0)
623                                 rdlen = -1;
624                         else if (sr_ser_has_queued_data(serial) != dlen)
625                                 rdlen = +1;
626                         else
627                                 rdlen = 0;
628                         break;
629                 default:
630                         rdlen = -1;
631                         break;
632                 }
633         } while (rdlen > 0);
634
635         /*
636          * When RX data became available (now or earlier), pass this
637          * condition to the application callback. Always periodically
638          * run the application callback, since it handles timeouts and
639          * might carry out other tasks as well like signalling progress.
640          */
641         if (sr_ser_has_queued_data(args->serial))
642                 revents |= G_IO_IN;
643         rc = args->cb(fd, revents, args->cb_data);
644
645         return rc;
646 }
647
648 /* TODO Can we use the Bluetooth socket's file descriptor? Probably not portably. */
649 #define WITH_MAXIMUM_TIMEOUT_VALUE      0
650 static int ser_bt_setup_source_add(struct sr_session *session,
651                 struct sr_serial_dev_inst *serial,
652                 int events, int timeout,
653                 sr_receive_data_callback cb, void *cb_data)
654 {
655         struct bt_source_args_t *args;
656         int rc;
657
658         (void)events;
659
660         /* Optionally enforce a minimum poll period. */
661         if (WITH_MAXIMUM_TIMEOUT_VALUE && timeout > WITH_MAXIMUM_TIMEOUT_VALUE)
662                 timeout = WITH_MAXIMUM_TIMEOUT_VALUE;
663
664         /* Allocate status container for background data reception. */
665         args = g_malloc0(sizeof(*args));
666         args->cb = cb;
667         args->cb_data = cb_data;
668         args->serial = serial;
669
670         /*
671          * Have a periodic timer installed. Register the allocated block
672          * with the serial device, since the GSource's finalizer won't
673          * free the memory, and we haven't bothered to create a custom
674          * BT specific GSource.
675          */
676         rc = sr_session_source_add(session, -1, events, timeout, bt_source_cb, args);
677         if (rc != SR_OK) {
678                 g_free(args);
679                 return rc;
680         }
681         serial->bt_source_args = g_slist_append(serial->bt_source_args, args);
682
683         return SR_OK;
684 }
685
686 static int ser_bt_setup_source_remove(struct sr_session *session,
687                 struct sr_serial_dev_inst *serial)
688 {
689         (void)serial;
690
691         (void)sr_session_source_remove(session, -1);
692         /* Release callback args here already? */
693
694         return SR_OK;
695 }
696
697 static enum ser_bt_conn_t scan_is_supported(const char *name)
698 {
699         size_t idx;
700         const struct scan_supported_item *item;
701
702         for (idx = 0; idx < ARRAY_SIZE(scan_supported_items); idx++) {
703                 item = &scan_supported_items[idx];
704                 if (!item->name)
705                         break;
706                 if (strcmp(name, item->name) != 0)
707                         continue;
708                 return item->type;
709         }
710
711         return SER_BT_CONN_UNKNOWN;
712 }
713
714 struct bt_scan_args_t {
715         GSList *port_list;
716         sr_ser_list_append_t append;
717         GSList *addr_list;
718         const char *bt_type;
719 };
720
721 static void scan_cb(void *cb_args, const char *addr, const char *name)
722 {
723         struct bt_scan_args_t *scan_args;
724         GSList *l;
725         char addr_text[20];
726         enum ser_bt_conn_t type;
727         char *port_name, *port_desc;
728         char *addr_copy;
729
730         scan_args = cb_args;
731         if (!scan_args)
732                 return;
733         sr_info("BT scan, found: %s - %s\n", addr, name);
734
735         /* Check whether the device was seen before. */
736         for (l = scan_args->addr_list; l; l = l->next) {
737                 if (strcmp(addr, l->data) == 0)
738                         return;
739         }
740
741         /* Substitute colons in the address by dashes. */
742         if (!addr || !*addr)
743                 return;
744         snprintf(addr_text, sizeof(addr_text), "%s", addr);
745         g_strcanon(addr_text, "0123456789abcdefABCDEF", '-');
746
747         /* Create a port name, and a description. */
748         type = scan_is_supported(name);
749         port_name = g_strdup_printf("%s/%s/%s",
750                 SER_BT_CONN_PREFIX, conn_name_text(type), addr_text);
751         port_desc = g_strdup_printf("%s (%s)", name, scan_args->bt_type);
752
753         scan_args->port_list = scan_args->append(scan_args->port_list, port_name, port_desc);
754         g_free(port_name);
755         g_free(port_desc);
756
757         /* Keep track of the handled address. */
758         addr_copy = g_strdup(addr);
759         scan_args->addr_list = g_slist_append(scan_args->addr_list, addr_copy);
760 }
761
762 static GSList *ser_bt_list(GSList *list, sr_ser_list_append_t append)
763 {
764         static const int scan_duration = 2;
765
766         struct bt_scan_args_t scan_args;
767         struct sr_bt_desc *desc;
768
769         /*
770          * Implementor's note: This "list" routine is best-effort. We
771          * assume that registering callbacks always succeeds. Silently
772          * ignore failure to scan for devices. Just return those which
773          * we happen to find.
774          */
775
776         desc = sr_bt_desc_new();
777         if (!desc)
778                 return list;
779
780         memset(&scan_args, 0, sizeof(scan_args));
781         scan_args.port_list = list;
782         scan_args.append = append;
783
784         scan_args.addr_list = NULL;
785         scan_args.bt_type = "BT";
786         (void)sr_bt_config_cb_scan(desc, scan_cb, &scan_args);
787         (void)sr_bt_scan_bt(desc, scan_duration);
788         g_slist_free_full(scan_args.addr_list, g_free);
789
790         scan_args.addr_list = NULL;
791         scan_args.bt_type = "BLE";
792         (void)sr_bt_config_cb_scan(desc, scan_cb, &scan_args);
793         (void)sr_bt_scan_le(desc, scan_duration);
794         g_slist_free_full(scan_args.addr_list, g_free);
795
796         sr_bt_desc_free(desc);
797
798         return scan_args.port_list;
799 }
800
801 static struct ser_lib_functions serlib_bt = {
802         .open = ser_bt_open,
803         .close = ser_bt_close,
804         .flush = ser_bt_flush,
805         .drain = ser_bt_drain,
806         .write = ser_bt_write,
807         .read = ser_bt_read,
808         /*
809          * Bluetooth communication has no concept of bitrate, so ignore
810          * these arguments silently. Neither need we pass the frame format
811          * down to internal BT comm routines, nor need we keep the values
812          * here, since the caller will cache/register them already.
813          */
814         .set_params = std_dummy_set_params,
815         .set_handshake = std_dummy_set_handshake,
816         .setup_source_add = ser_bt_setup_source_add,
817         .setup_source_remove = ser_bt_setup_source_remove,
818         .list = ser_bt_list,
819         .get_frame_format = NULL,
820 };
821 SR_PRIV struct ser_lib_functions *ser_lib_funcs_bt = &serlib_bt;
822
823 /* }}} */
824 #else
825
826 SR_PRIV int ser_name_is_bt(struct sr_serial_dev_inst *serial)
827 {
828         (void)serial;
829
830         return 0;
831 }
832
833 SR_PRIV struct ser_lib_functions *ser_lib_funcs_bt = NULL;
834
835 #endif
836 #endif
837
838 /** @} */