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