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