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