]> sigrok.org Git - libsigrok.git/blob - src/bt/bt_bluez.c
bt: apply 20s timeout to BLE connect(2) attempts
[libsigrok.git] / src / bt / bt_bluez.c
1 /*
2  * This file is part of the sigrok 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 /*
21  * Scan support for Bluetooth LE devices is modelled after the MIT licensed
22  * https://github.com/carsonmcdonald/bluez-experiments experiments/scantest.c
23  * example source code which is:
24  *
25  * The MIT License (MIT)
26  *
27  * Copyright (c) 2013 Carson McDonald
28  *
29  * Permission is hereby granted, free of charge, to any person obtaining a copy of
30  * this software and associated documentation files (the "Software"), to deal in
31  * the Software without restriction, including without limitation the rights to
32  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
33  * the Software, and to permit persons to whom the Software is furnished to do so,
34  * subject to the following conditions:
35  *
36  * The above copyright notice and this permission notice shall be included in all
37  * copies or substantial portions of the Software.
38  *
39  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
41  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
42  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
43  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
44  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
45  */
46
47 /*
48  * This file implements an internal platform agnostic API of libsigrok
49  * for Bluetooth communication, as well as the first implementation on a
50  * specific platform which is based on the BlueZ library and got tested
51  * on Linux.
52  *
53  * TODO
54  * - Separate the "common" from the "bluez specific" parts. The current
55  *   implementation uses the fact that HAVE_BLUETOOTH exclusively depends
56  *   on HAVE_LIBBLUEZ, and thus both are identical.
57  * - Add missing features to the Linux platform support: Scan without
58  *   root privileges, UUID to handle translation.
59  * - Add support for other platforms.
60  */
61
62 #include "config.h"
63
64 /* Unconditionally compile the source, optionally end up empty. */
65 #ifdef HAVE_BLUETOOTH
66
67 #ifdef HAVE_LIBBLUEZ
68 #include <bluetooth/bluetooth.h>
69 #include <bluetooth/hci.h>
70 #include <bluetooth/hci_lib.h>
71 #include <bluetooth/l2cap.h>
72 #include <bluetooth/rfcomm.h>
73 #endif
74 #include <ctype.h>
75 #include <errno.h>
76 #include <glib.h>
77 #include <poll.h>
78 #include <stdarg.h>
79 #include <stdio.h>
80 #include <stdlib.h>
81 #include <string.h>
82 #include <sys/uio.h>
83 #include <sys/socket.h>
84 #include <time.h>
85 #include <unistd.h>
86
87 #include <libsigrok/libsigrok.h>
88 #include "libsigrok-internal.h"
89
90 /** @cond PRIVATE */
91 #define LOG_PREFIX "bt-bluez"
92 /** @endcond */
93
94 #define CONNECT_BLE_TIMEOUT     20      /* Connect timeout in seconds. */
95 #define STORE_MAC_REVERSE       1
96 #define ACCEPT_NONSEP_MAC       1
97
98 /* Silence warning about (currently) unused routine. */
99 #define WITH_WRITE_TYPE_HANDLE  0
100
101 /* {{{ compat decls */
102 /*
103  * The availability of conversion helpers in <bluetooth/bluetooth.h>
104  * appears to be version dependent. Let's provide the helper here if
105  * the header doesn't.
106  */
107
108 #if !defined HAVE_BT_PUT_LE16
109 static inline void bt_put_le16(uint16_t v, uint8_t *p)
110 {
111         p[0] = (v >> 0) & 0xff;
112         p[1] = (v >> 8) & 0xff;
113 }
114 #endif
115
116 /* }}} compat decls */
117 /* {{{ Linux socket specific decls */
118
119 #define BLE_ATT_ERROR_RESP              0x01
120 #define BLE_ATT_EXCHANGE_MTU_REQ        0x02
121 #define BLE_ATT_EXCHANGE_MTU_RESP       0x03
122 #define BLE_ATT_FIND_INFORMATION_REQ    0x04
123 #define BLE_ATT_FIND_INFORMATION_RESP   0x05
124 #define BLE_ATT_FIND_BY_TYPE_REQ        0x06
125 #define BLE_ATT_FIND_BY_TYPE_RESP       0x07
126 #define BLE_ATT_READ_BY_TYPE_REQ        0x08
127 #define BLE_ATT_READ_BY_TYPE_RESP       0x09
128 #define BLE_ATT_READ_REQ                0x0a
129 #define BLE_ATT_READ_RESP               0x0b
130 #define BLE_ATT_READ_BLOB_REQ           0x0c
131 #define BLE_ATT_READ_BLOB_RESP          0x0d
132 #define BLE_ATT_READ_MULTIPLE_REQ       0x0e
133 #define BLE_ATT_READ_MULTIPLE_RESP      0x0f
134 #define BLE_ATT_READ_BY_GROUP_REQ       0x10
135 #define BLE_ATT_READ_BY_GROUP_RESP      0x11
136 #define BLE_ATT_WRITE_REQ               0x12
137 #define BLE_ATT_WRITE_RESP              0x13
138 #define BLE_ATT_WRITE_CMD               0x16
139 #define BLE_ATT_HANDLE_NOTIFICATION     0x1b
140 #define BLE_ATT_HANDLE_INDICATION       0x1d
141 #define BLE_ATT_HANDLE_CONFIRMATION     0x1e
142 #define BLE_ATT_SIGNED_WRITE_CMD        0x52
143
144 /* }}} Linux socket specific decls */
145 /* {{{ conversion */
146
147 /*
148  * Convert textual MAC presentation to array of bytes. In contrast to
149  * BlueZ conversion, accept colon or dash separated input as well as a
150  * dense format without separators (001122334455). We expect to use the
151  * library in an environment where colons are not always available as a
152  * separator in user provided specs, while users do want to use some
153  * separator for readability.
154  *
155  * TODO Instead of doing the actual conversion here (and dealing with
156  * BlueZ' internal byte order for device address bytes), we might as
157  * well just transform the input string to an output string, and always
158  * use the officially provided str2ba() conversion routine.
159  */
160 static int sr_bt_mac_text_to_bytes(const char *text, uint8_t *buf)
161 {
162         size_t len;
163         long v;
164         char *endp;
165         char numbuf[3];
166
167         len = 6;
168         if (STORE_MAC_REVERSE)
169                 buf += len;
170         endp = (char *)text;
171         while (len && endp && *endp) {
172                 text = endp;
173                 if (ACCEPT_NONSEP_MAC) {
174                         numbuf[0] = endp[0];
175                         numbuf[1] = endp[0] ? endp[1] : '\0';
176                         numbuf[2] = '\0';
177                 }
178                 endp = NULL;
179                 v = strtol(ACCEPT_NONSEP_MAC ? numbuf : text, &endp, 16);
180                 if (!endp)
181                         break;
182                 if (*endp != ':' && *endp != '-' && *endp != '\0')
183                         break;
184                 if (v < 0 || v > 255)
185                         break;
186                 if (STORE_MAC_REVERSE)
187                         *(--buf) = v;
188                 else
189                         *buf++ = v;
190                 len--;
191                 if (ACCEPT_NONSEP_MAC)
192                         endp = (char *)text + (endp - numbuf);
193                 if (*endp == ':' || *endp == '-')
194                         endp++;
195         }
196
197         if (len) {
198                 sr_err("Failed to parse MAC, too few bytes in '%s'", text);
199                 return -1;
200         }
201         while (isspace(*endp))
202                 endp++;
203         if (*endp) {
204                 sr_err("Failed to parse MAC, excess data in '%s'", text);
205                 return -1;
206         }
207
208         return 0;
209 }
210
211 /* }}} conversion */
212 /* {{{ helpers */
213
214 SR_PRIV const char *sr_bt_adapter_get_address(size_t idx)
215 {
216         int rc;
217         struct hci_dev_info info;
218         char addr[20];
219
220         rc = hci_devinfo(idx, &info);
221         sr_spew("DIAG: hci_devinfo(%zu) => rc %d", idx, rc);
222         if (rc < 0)
223                 return NULL;
224
225         rc = ba2str(&info.bdaddr, addr);
226         sr_spew("DIAG: ba2str() => rc %d", rc);
227         if (rc < 0)
228                 return NULL;
229
230         return g_strdup(addr);
231 }
232
233 /* }}} helpers */
234 /* {{{ descriptor */
235
236 struct sr_bt_desc {
237         /* User servicable options. */
238         sr_bt_scan_cb scan_cb;
239         void *scan_cb_data;
240         sr_bt_data_cb data_cb;
241         void *data_cb_data;
242         char local_addr[20];
243         char remote_addr[20];
244         size_t rfcomm_channel;
245         uint16_t read_handle;
246         uint16_t write_handle;
247         uint16_t cccd_handle;
248         uint16_t cccd_value;
249         /* Internal state. */
250         int devid;
251         int fd;
252         struct hci_filter orig_filter;
253 };
254
255 static int sr_bt_desc_open(struct sr_bt_desc *desc, int *id_ref);
256 static void sr_bt_desc_close(struct sr_bt_desc *desc);
257 static int sr_bt_check_socket_usable(struct sr_bt_desc *desc);
258 static ssize_t sr_bt_write_type(struct sr_bt_desc *desc, uint8_t type);
259 #if WITH_WRITE_TYPE_HANDLE
260 static ssize_t sr_bt_write_type_handle(struct sr_bt_desc *desc,
261         uint8_t type, uint16_t handle);
262 #endif
263 static ssize_t sr_bt_write_type_handle_bytes(struct sr_bt_desc *desc,
264         uint8_t type, uint16_t handle, const uint8_t *data, size_t len);
265 static ssize_t sr_bt_char_write_req(struct sr_bt_desc *desc,
266         uint16_t handle, const void *data, size_t len);
267
268 SR_PRIV struct sr_bt_desc *sr_bt_desc_new(void)
269 {
270         struct sr_bt_desc *desc;
271
272         desc = g_malloc0(sizeof(*desc));
273         if (!desc)
274                 return NULL;
275
276         desc->devid = -1;
277         desc->fd = -1;
278
279         return desc;
280 }
281
282 SR_PRIV void sr_bt_desc_free(struct sr_bt_desc *desc)
283 {
284         if (!desc)
285                 return;
286
287         sr_bt_desc_close(desc);
288         g_free(desc);
289 }
290
291 SR_PRIV int sr_bt_config_cb_scan(struct sr_bt_desc *desc,
292         sr_bt_scan_cb cb, void *cb_data)
293 {
294         if (!desc)
295                 return -1;
296
297         desc->scan_cb = cb;
298         desc->scan_cb_data = cb_data;
299
300         return 0;
301 }
302
303 SR_PRIV int sr_bt_config_cb_data(struct sr_bt_desc *desc,
304         sr_bt_data_cb cb, void *cb_data)
305 {
306         if (!desc)
307                 return -1;
308
309         desc->data_cb = cb;
310         desc->data_cb_data = cb_data;
311
312         return 0;
313 }
314
315 SR_PRIV int sr_bt_config_addr_local(struct sr_bt_desc *desc, const char *addr)
316 {
317         bdaddr_t mac_bytes;
318         int rc;
319
320         if (!desc)
321                 return -1;
322
323         if (!addr || !addr[0]) {
324                 desc->local_addr[0] = '\0';
325                 return 0;
326         }
327
328         rc = sr_bt_mac_text_to_bytes(addr, &mac_bytes.b[0]);
329         if (rc < 0)
330                 return -1;
331
332         rc = ba2str(&mac_bytes, desc->local_addr);
333         if (rc < 0)
334                 return -1;
335
336         return 0;
337 }
338
339 SR_PRIV int sr_bt_config_addr_remote(struct sr_bt_desc *desc, const char *addr)
340 {
341         bdaddr_t mac_bytes;
342         int rc;
343
344         if (!desc)
345                 return -1;
346
347         if (!addr || !addr[0]) {
348                 desc->remote_addr[0] = '\0';
349                 return 0;
350         }
351
352         rc = sr_bt_mac_text_to_bytes(addr, &mac_bytes.b[0]);
353         if (rc < 0)
354                 return -1;
355
356         rc = ba2str(&mac_bytes, desc->remote_addr);
357         if (rc < 0)
358                 return -1;
359
360         return 0;
361 }
362
363 SR_PRIV int sr_bt_config_rfcomm(struct sr_bt_desc *desc, size_t channel)
364 {
365         if (!desc)
366                 return -1;
367
368         desc->rfcomm_channel = channel;
369
370         return 0;
371 }
372
373 SR_PRIV int sr_bt_config_notify(struct sr_bt_desc *desc,
374         uint16_t read_handle, uint16_t write_handle,
375         uint16_t cccd_handle, uint16_t cccd_value)
376 {
377
378         if (!desc)
379                 return -1;
380
381         desc->read_handle = read_handle;
382         desc->write_handle = write_handle;
383         desc->cccd_handle = cccd_handle;
384         desc->cccd_value = cccd_value;
385
386         return 0;
387 }
388
389 static int sr_bt_desc_open(struct sr_bt_desc *desc, int *id_ref)
390 {
391         int id, sock;
392         bdaddr_t mac;
393
394         if (!desc)
395                 return -1;
396         sr_dbg("BLE open");
397
398         if (desc->local_addr[0]) {
399                 id = hci_devid(desc->local_addr);
400         } else if (desc->remote_addr[0]) {
401                 str2ba(desc->remote_addr, &mac);
402                 id = hci_get_route(&mac);
403         } else {
404                 id = hci_get_route(NULL);
405         }
406         if (id < 0) {
407                 sr_err("devid failed");
408                 return -1;
409         }
410         desc->devid = id;
411         if (id_ref)
412                 *id_ref = id;
413
414         sock = hci_open_dev(id);
415         if (sock < 0) {
416                 perror("open HCI socket");
417                 return -1;
418         }
419         desc->fd = sock;
420
421         return sock;
422 }
423
424 static void sr_bt_desc_close(struct sr_bt_desc *desc)
425 {
426         if (!desc)
427                 return;
428
429         sr_dbg("BLE close");
430         if (desc->fd >= 0) {
431                 hci_close_dev(desc->fd);
432                 desc->fd = -1;
433         }
434         desc->devid = -1;
435 }
436
437 /* }}} descriptor */
438 /* {{{ scan */
439
440 #define EIR_NAME_COMPLETE       9
441
442 static int sr_bt_scan_prep(struct sr_bt_desc *desc)
443 {
444         int rc;
445         uint8_t type, owntype, filter;
446         uint16_t ival, window;
447         int timeout;
448         uint8_t enable, dup;
449         socklen_t slen;
450         struct hci_filter scan_filter;
451
452         if (!desc)
453                 return -1;
454
455         /* TODO Replace magic values with symbolic identifiers. */
456         type = 0x01;    /* LE public? */
457         ival = htobs(0x0010);
458         window = htobs(0x0010);
459         owntype = 0x00; /* any? */
460         filter = 0x00;
461         timeout = 1000;
462         rc = hci_le_set_scan_parameters(desc->fd,
463                 type, ival, window, owntype, filter, timeout);
464         if (rc < 0) {
465                 perror("set LE scan params");
466                 return -1;
467         }
468
469         enable = 1;
470         dup = 1;
471         timeout = 1000;
472         rc = hci_le_set_scan_enable(desc->fd, enable, dup, timeout);
473         if (rc < 0) {
474                 perror("set LE scan enable");
475                 return -1;
476         }
477
478         /* Save the current filter. For later restoration. */
479         slen = sizeof(desc->orig_filter);
480         rc = getsockopt(desc->fd, SOL_HCI, HCI_FILTER,
481                 &desc->orig_filter, &slen);
482         if (rc < 0) {
483                 perror("getsockopt(HCI_FILTER)");
484                 return -1;
485         }
486
487         hci_filter_clear(&scan_filter);
488         hci_filter_set_ptype(HCI_EVENT_PKT, &scan_filter);
489         hci_filter_set_event(EVT_LE_META_EVENT, &scan_filter);
490         rc = setsockopt(desc->fd, SOL_HCI, HCI_FILTER,
491                 &scan_filter, sizeof(scan_filter));
492         if (rc < 0) {
493                 perror("setsockopt(HCI_FILTER)");
494                 return -1;
495         }
496
497         return 0;
498 }
499
500 static int sr_bt_scan_post(struct sr_bt_desc *desc)
501 {
502         int rc;
503         uint8_t enable, dup;
504         int timeout;
505
506         if (!desc)
507                 return -1;
508
509         /* Restore previous HCI filter. */
510         rc = setsockopt(desc->fd, SOL_HCI, HCI_FILTER,
511                 &desc->orig_filter, sizeof(desc->orig_filter));
512         if (rc < 0) {
513                 perror("setsockopt(HCI_FILTER)");
514                 return -1;
515         }
516
517         enable = 0;
518         dup = 1;
519         timeout = 1000;
520         rc = hci_le_set_scan_enable(desc->fd, enable, dup, timeout);
521         if (rc < 0)
522                 return -1;
523
524         return 0;
525 }
526
527 static int sr_bt_scan_proc(struct sr_bt_desc *desc,
528         sr_bt_scan_cb scan_cb, void *cb_data,
529         uint8_t *data, size_t dlen, le_advertising_info *info)
530 {
531         uint8_t type;
532         char addr[20];
533         const char *name;
534
535         (void)desc;
536
537         type = data[0];
538         if (type == EIR_NAME_COMPLETE) {
539                 ba2str(&info->bdaddr, addr);
540                 name = g_strndup((const char *)&data[1], dlen - 1);
541                 if (scan_cb)
542                         scan_cb(cb_data, addr, name);
543                 free((void *)name);
544                 return 0;
545         }
546
547         /* Unknown or unsupported type, ignore silently. */
548         return 0;
549 }
550
551 SR_PRIV int sr_bt_scan_le(struct sr_bt_desc *desc, int duration)
552 {
553         int rc;
554         time_t deadline;
555         uint8_t buf[HCI_MAX_EVENT_SIZE];
556         ssize_t rdlen, rdpos;
557         evt_le_meta_event *meta;
558         le_advertising_info *info;
559         uint8_t *dataptr;
560         size_t datalen;
561
562         if (!desc)
563                 return -1;
564         sr_dbg("BLE scan (LE)");
565
566         rc = sr_bt_desc_open(desc, NULL);
567         if (rc < 0)
568                 return -1;
569
570         rc = sr_bt_scan_prep(desc);
571         if (rc < 0)
572                 return -1;
573
574         deadline = time(NULL);
575         deadline += duration;
576         while (time(NULL) <= deadline) {
577
578                 if (sr_bt_check_socket_usable(desc) < 0)
579                         break;
580                 rdlen = sr_bt_read(desc, buf, sizeof(buf));
581                 if (rdlen < 0)
582                         break;
583                 if (!rdlen) {
584                         g_usleep(50000);
585                         continue;
586                 }
587                 if (rdlen < 1 + HCI_EVENT_HDR_SIZE)
588                         continue;
589                 meta = (void *)&buf[1 + HCI_EVENT_HDR_SIZE];
590                 rdlen -= 1 + HCI_EVENT_HDR_SIZE;
591                 if (meta->subevent != EVT_LE_ADVERTISING_REPORT)
592                         continue;
593                 info = (void *)&meta->data[1];
594                 sr_spew("evt: type %d, len %d", info->evt_type, info->length);
595                 if (!info->length)
596                         continue;
597
598                 rdpos = 0;
599                 while (rdpos < rdlen) {
600                         datalen = info->data[rdpos];
601                         dataptr = &info->data[1 + rdpos];
602                         if (rdpos + 1 + datalen > info->length)
603                                 break;
604                         rdpos += 1 + datalen;
605                         rc = sr_bt_scan_proc(desc,
606                                 desc->scan_cb, desc->scan_cb_data,
607                                 dataptr, datalen, info);
608                         if (rc < 0)
609                                 break;
610                 }
611         }
612
613         rc = sr_bt_scan_post(desc);
614         if (rc < 0)
615                 return -1;
616
617         sr_bt_desc_close(desc);
618
619         return 0;
620 }
621
622 SR_PRIV int sr_bt_scan_bt(struct sr_bt_desc *desc, int duration)
623 {
624         int dev_id, sock, rsp_max;
625         long flags;
626         inquiry_info *info;
627         int inq_rc;
628         size_t rsp_count, idx;
629         char addr[20];
630         char name[256];
631
632         if (!desc)
633                 return -1;
634         sr_dbg("BLE scan (BT)");
635
636         sock = sr_bt_desc_open(desc, &dev_id);
637         if (sock < 0)
638                 return -1;
639
640         rsp_max = 255;
641         info = g_malloc0(rsp_max * sizeof(*info));
642         flags = 0 /* | IREQ_CACHE_FLUSH */;
643         inq_rc = hci_inquiry(dev_id, duration, rsp_max, NULL, &info, flags);
644         if (inq_rc < 0)
645                 perror("hci_inquiry");
646         rsp_count = inq_rc;
647
648         for (idx = 0; idx < rsp_count; idx++) {
649                 memset(addr, 0, sizeof(addr));
650                 ba2str(&info[idx].bdaddr, addr);
651                 memset(name, 0, sizeof(name));
652                 if (hci_read_remote_name(sock, &info[idx].bdaddr, sizeof(name), name, 0) < 0)
653                         snprintf(name, sizeof(name), "[unknown]");
654                 if (desc->scan_cb)
655                         desc->scan_cb(desc->scan_cb_data, addr, name);
656         }
657         g_free(info);
658
659         sr_bt_desc_close(desc);
660
661         return 0;
662 }
663
664 /* }}} scan */
665 /* {{{ connect/disconnect */
666
667 SR_PRIV int sr_bt_connect_ble(struct sr_bt_desc *desc)
668 {
669         struct sockaddr_l2 sl2;
670         bdaddr_t mac;
671         int s, ret;
672         gint64 deadline;
673
674         if (!desc)
675                 return -1;
676         if (!desc->remote_addr[0])
677                 return -1;
678         sr_dbg("BLE connect, remote addr %s", desc->remote_addr);
679
680         s = socket(AF_BLUETOOTH, SOCK_SEQPACKET, 0);
681         if (s < 0) {
682                 perror("socket create");
683                 return s;
684         }
685         desc->fd = s;
686
687         memset(&sl2, 0, sizeof(sl2));
688         sl2.l2_family = AF_BLUETOOTH;
689         sl2.l2_psm = 0;
690         if (desc->local_addr[0])
691                 str2ba(desc->local_addr, &mac);
692         else
693                 mac = *BDADDR_ANY;
694         memcpy(&sl2.l2_bdaddr, &mac, sizeof(sl2.l2_bdaddr));
695         sl2.l2_cid = L2CAP_FC_CONNLESS;
696         sl2.l2_bdaddr_type = BDADDR_LE_PUBLIC;
697         ret = bind(s, (void *)&sl2, sizeof(sl2));
698         if (ret < 0) {
699                 perror("bind");
700                 return ret;
701         }
702
703         if (0) {
704                 struct bt_security buf = {
705                         .level = BT_SECURITY_LOW,
706                         .key_size = 0,
707                 };
708                 ret = setsockopt(s, SOL_BLUETOOTH, BT_SECURITY, &buf, sizeof(buf));
709                 if (ret < 0) {
710                         perror("setsockopt");
711                         return ret;
712                 }
713         }
714
715         deadline = g_get_monotonic_time();
716         deadline += CONNECT_BLE_TIMEOUT * 1000 * 1000;
717         str2ba(desc->remote_addr, &mac);
718         memcpy(&sl2.l2_bdaddr, &mac, sizeof(sl2.l2_bdaddr));
719         sl2.l2_bdaddr_type = BDADDR_LE_PUBLIC;
720         ret = connect(s, (void *)&sl2, sizeof(sl2));
721         /*
722          * Cope with "in progress" condition. Keep polling the status
723          * until connect() completes, then get the error by means of
724          * getsockopt(). See the connect(2) manpage for details.
725          */
726         if (ret < 0 && errno == EINPROGRESS) {
727                 struct pollfd fds[1];
728                 uint32_t soerror;
729                 socklen_t solen;
730
731                 /* TODO
732                  * We seem to get here ("connect in progress") even when
733                  * the specified peer is not around at all. Which results
734                  * in extended periods of time where nothing happens, and
735                  * an application timeout seems to be required.
736                  */
737                 sr_spew("in progress ...");
738
739                 do {
740                         memset(fds, 0, sizeof(fds));
741                         fds[0].fd = s;
742                         fds[0].events = POLLOUT;
743                         ret = poll(fds, ARRAY_SIZE(fds), -1);
744                         if (ret < 0) {
745                                 perror("poll(OUT)");
746                                 return ret;
747                         }
748                         if (!ret)
749                                 continue;
750                         if (!(fds[0].revents & POLLOUT))
751                                 continue;
752                         if (g_get_monotonic_time() >= deadline) {
753                                 sr_warn("Connect attempt timed out");
754                                 return SR_ERR_IO;
755                         }
756                 } while (1);
757                 memset(fds, 0, sizeof(fds));
758                 fds[0].fd = s;
759                 fds[0].events = POLLNVAL;
760                 ret = poll(fds, 1, 0);
761                 if (ret < 0) {
762                         perror("poll(INVAL)");
763                         return ret;
764                 }
765                 if (ret) {
766                         /* socket fd is invalid(?) */
767                         desc->fd = -1;
768                         close(s);
769                         return -1;
770                 }
771                 solen = sizeof(soerror);
772                 ret = getsockopt(s, SOL_SOCKET, SO_ERROR, &soerror, &solen);
773                 if (ret < 0) {
774                         perror("getsockopt(SO_ERROR)");
775                         return ret;
776                 }
777                 if (soerror) {
778                         /* connect(2) failed, SO_ERROR has the error code. */
779                         errno = soerror;
780                         perror("connect(PROGRESS)");
781                         return soerror;
782                 }
783
784                 /*
785                  * TODO Get the receive MTU here?
786                  * getsockopt(SOL_BLUETOOTH, BT_RCVMTU, u16);
787                  */
788         }
789         if (ret < 0) {
790                 perror("connect");
791                 return ret;
792         }
793
794         return 0;
795 }
796
797 SR_PRIV int sr_bt_connect_rfcomm(struct sr_bt_desc *desc)
798 {
799         struct sockaddr_rc addr;
800         int fd, rc;
801
802         if (!desc)
803                 return -1;
804         if (!desc->remote_addr[0])
805                 return -1;
806         sr_dbg("RFCOMM connect, remote addr %s, channel %zu",
807                 desc->remote_addr, desc->rfcomm_channel);
808
809         if (!desc->rfcomm_channel)
810                 desc->rfcomm_channel = 1;
811
812         fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
813         if (fd < 0) {
814                 perror("socket");
815                 return -1;
816         }
817         desc->fd = fd;
818
819         memset(&addr, 0, sizeof(addr));
820         addr.rc_family = AF_BLUETOOTH;
821         str2ba(desc->remote_addr, &addr.rc_bdaddr);
822         addr.rc_channel = desc->rfcomm_channel;
823         rc = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
824         if (rc < 0) {
825                 perror("connect");
826                 return -2;
827         }
828         sr_spew("connected");
829
830         return 0;
831 }
832
833 SR_PRIV void sr_bt_disconnect(struct sr_bt_desc *desc)
834 {
835         sr_dbg("BLE disconnect");
836
837         if (!desc)
838                 return;
839         sr_bt_desc_close(desc);
840 }
841
842 static int sr_bt_check_socket_usable(struct sr_bt_desc *desc)
843 {
844         struct pollfd fds[1];
845         int ret;
846
847         if (!desc)
848                 return -1;
849         if (desc->fd < 0)
850                 return -1;
851
852         memset(fds, 0, sizeof(fds));
853         fds[0].fd = desc->fd;
854         fds[0].events = POLLERR | POLLHUP;
855         ret = poll(fds, ARRAY_SIZE(fds), 0);
856         if (ret < 0)
857                 return ret;
858         if (!ret)
859                 return 0;
860         if (fds[0].revents & POLLHUP)
861                 return -1;
862         if (fds[0].revents & POLLERR)
863                 return -2;
864         if (fds[0].revents & POLLNVAL)
865                 return -3;
866
867         return 0;
868 }
869
870 /* }}} connect/disconnect */
871 /* {{{ indication/notification */
872
873 SR_PRIV int sr_bt_start_notify(struct sr_bt_desc *desc)
874 {
875         uint8_t buf[sizeof(desc->cccd_value)];
876         ssize_t wrlen;
877
878         if (!desc)
879                 return -1;
880         sr_dbg("BLE start notify");
881
882         if (sr_bt_check_socket_usable(desc) < 0)
883                 return -2;
884
885         bt_put_le16(desc->cccd_value, buf);
886         wrlen = sr_bt_char_write_req(desc, desc->cccd_handle, buf, sizeof(buf));
887         if (wrlen != sizeof(buf))
888                 return -2;
889
890         return 0;
891 }
892
893 SR_PRIV int sr_bt_check_notify(struct sr_bt_desc *desc)
894 {
895         uint8_t buf[1024];
896         ssize_t rdlen;
897         uint8_t packet_type;
898         uint16_t packet_handle;
899         uint8_t *packet_data;
900         size_t packet_dlen;
901
902         if (!desc)
903                 return -1;
904
905         if (sr_bt_check_socket_usable(desc) < 0)
906                 return -2;
907
908         /* Get another message from the Bluetooth socket. */
909         rdlen = sr_bt_read(desc, buf, sizeof(buf));
910         if (rdlen < 0)
911                 return -2;
912         if (!rdlen)
913                 return 0;
914
915         /* Get header fields and references to the payload data. */
916         packet_type = 0x00;
917         packet_handle = 0x0000;
918         packet_data = NULL;
919         packet_dlen = 0;
920         if (rdlen >= 1)
921                 packet_type = buf[0];
922         if (rdlen >= 3) {
923                 packet_handle = bt_get_le16(&buf[1]);
924                 packet_data = &buf[3];
925                 packet_dlen = rdlen - 3;
926         }
927
928         /* Dispatch according to the message type. */
929         switch (packet_type) {
930         case BLE_ATT_ERROR_RESP:
931                 sr_spew("read() len %zd, type 0x%02x (%s)", rdlen, buf[0], "error response");
932                 /* EMPTY */
933                 break;
934         case BLE_ATT_WRITE_RESP:
935                 sr_spew("read() len %zd, type 0x%02x (%s)", rdlen, buf[0], "write response");
936                 /* EMPTY */
937                 break;
938         case BLE_ATT_HANDLE_INDICATION:
939                 sr_spew("read() len %zd, type 0x%02x (%s)", rdlen, buf[0], "handle indication");
940                 sr_bt_write_type(desc, BLE_ATT_HANDLE_CONFIRMATION);
941                 if (packet_handle != desc->read_handle)
942                         return -4;
943                 if (!packet_data)
944                         return -4;
945                 if (!desc->data_cb)
946                         return 0;
947                 return desc->data_cb(desc->data_cb_data, packet_data, packet_dlen);
948         case BLE_ATT_HANDLE_NOTIFICATION:
949                 sr_spew("read() len %zd, type 0x%02x (%s)", rdlen, buf[0], "handle notification");
950                 if (packet_handle != desc->read_handle)
951                         return -4;
952                 if (!packet_data)
953                         return -4;
954                 if (!desc->data_cb)
955                         return 0;
956                 return desc->data_cb(desc->data_cb_data, packet_data, packet_dlen);
957         default:
958                 sr_spew("unsupported type 0x%02x", packet_type);
959                 return -3;
960         }
961
962         return 0;
963 }
964
965 /* }}} indication/notification */
966 /* {{{ read/write */
967
968 SR_PRIV ssize_t sr_bt_write(struct sr_bt_desc *desc,
969         const void *data, size_t len)
970 {
971         if (!desc)
972                 return -1;
973         if (desc->fd < 0)
974                 return -1;
975
976         if (sr_bt_check_socket_usable(desc) < 0)
977                 return -2;
978
979         /* Send TX data to the writable characteristics for BLE UART services. */
980         if (desc->write_handle)
981                 return sr_bt_char_write_req(desc, desc->write_handle, data, len);
982
983         /* Send raw TX data to the RFCOMM socket for BT Classic channels. */
984         return write(desc->fd, data, len);
985 }
986
987 static ssize_t sr_bt_write_type(struct sr_bt_desc *desc, uint8_t type)
988 {
989         ssize_t wrlen;
990
991         if (!desc)
992                 return -1;
993         if (desc->fd < 0)
994                 return -1;
995
996         if (sr_bt_check_socket_usable(desc) < 0)
997                 return -2;
998
999         wrlen = write(desc->fd, &type, sizeof(type));
1000         if (wrlen < 0)
1001                 return wrlen;
1002         if (wrlen < (ssize_t)sizeof(type))
1003                 return -1;
1004
1005         return 0;
1006 }
1007
1008 #if WITH_WRITE_TYPE_HANDLE
1009 static ssize_t sr_bt_write_type_handle(struct sr_bt_desc *desc,
1010         uint8_t type, uint16_t handle)
1011 {
1012         return sr_bt_write_type_handle_bytes(desc, type, handle, NULL, 0);
1013 }
1014 #endif
1015
1016 static ssize_t sr_bt_write_type_handle_bytes(struct sr_bt_desc *desc,
1017         uint8_t type, uint16_t handle, const uint8_t *data, size_t len)
1018 {
1019         uint8_t header[sizeof(uint8_t) + sizeof(uint16_t)];
1020         struct iovec iov[2] = {
1021                 { .iov_base = header, .iov_len = sizeof(header), },
1022                 { .iov_base = (void *)data, .iov_len = len, },
1023         };
1024         ssize_t wrlen;
1025
1026         if (!desc)
1027                 return -1;
1028         if (desc->fd < 0)
1029                 return -1;
1030
1031         if (sr_bt_check_socket_usable(desc) < 0)
1032                 return -2;
1033
1034         header[0] = type;
1035         bt_put_le16(handle, &header[1]);
1036
1037         if (data && len)
1038                 wrlen = writev(desc->fd, iov, ARRAY_SIZE(iov));
1039         else
1040                 wrlen = write(desc->fd, header, sizeof(header));
1041
1042         if (wrlen < 0)
1043                 return wrlen;
1044         if (wrlen < (ssize_t)sizeof(header))
1045                 return -1;
1046         wrlen -= sizeof(header);
1047
1048         return wrlen;
1049 }
1050
1051 /* Returns negative upon error, or returns the number of _payload_ bytes written. */
1052 static ssize_t sr_bt_char_write_req(struct sr_bt_desc *desc,
1053         uint16_t handle, const void *data, size_t len)
1054 {
1055         return sr_bt_write_type_handle_bytes(desc, BLE_ATT_WRITE_REQ,
1056                 handle, data, len);
1057 }
1058
1059 SR_PRIV ssize_t sr_bt_read(struct sr_bt_desc *desc, void *data, size_t len)
1060 {
1061         struct pollfd fds[1];
1062         int ret;
1063         ssize_t rdlen;
1064
1065         if (!desc)
1066                 return -1;
1067         if (desc->fd < 0)
1068                 return -1;
1069
1070         if (sr_bt_check_socket_usable(desc) < 0)
1071                 return -2;
1072
1073         memset(fds, 0, sizeof(fds));
1074         fds[0].fd = desc->fd;
1075         fds[0].events = POLLIN;
1076         ret = poll(fds, ARRAY_SIZE(fds), 0);
1077         if (ret < 0)
1078                 return ret;
1079         if (!ret)
1080                 return 0;
1081         if (!(fds[0].revents & POLLIN))
1082                 return 0;
1083
1084         rdlen = read(desc->fd, data, len);
1085
1086         return rdlen;
1087 }
1088
1089 /* }}} indication/notification */
1090
1091 #endif