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