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