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