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