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