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