2 * This file is part of the sigrok project.
4 * Copyright (C) 2018-2019 Gerhard Sittig <gerhard.sittig@gmx.net>
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.
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.
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/>.
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:
25 * The MIT License (MIT)
27 * Copyright (c) 2013 Carson McDonald
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:
36 * The above copyright notice and this permission notice shall be included in all
37 * copies or substantial portions of the Software.
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.
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
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.
64 /* Unconditionally compile the source, optionally end up empty. */
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>
84 #include <sys/socket.h>
88 #include <libsigrok/libsigrok.h>
89 #include "libsigrok-internal.h"
91 #define LOG_PREFIX "bt-bluez"
93 #define CONNECT_BLE_TIMEOUT 20 /* Connect timeout in seconds. */
94 #define STORE_MAC_REVERSE 1
95 #define ACCEPT_NONSEP_MAC 1
97 #define CONNECT_RFCOMM_TRIES 3
98 #define CONNECT_RFCOMM_RETRY_MS 100
100 /* {{{ compat decls */
102 * The availability of conversion helpers in <bluetooth/bluetooth.h>
103 * appears to be version dependent. Let's provide the helper here if
104 * the header doesn't.
107 /* }}} compat decls */
108 /* {{{ Linux socket specific decls */
110 #define BLE_ATT_ERROR_RESP 0x01
111 #define BLE_ATT_EXCHANGE_MTU_REQ 0x02
112 #define BLE_ATT_EXCHANGE_MTU_RESP 0x03
113 #define BLE_ATT_FIND_INFORMATION_REQ 0x04
114 #define BLE_ATT_FIND_INFORMATION_RESP 0x05
115 #define BLE_ATT_FIND_BY_TYPE_REQ 0x06
116 #define BLE_ATT_FIND_BY_TYPE_RESP 0x07
117 #define BLE_ATT_READ_BY_TYPE_REQ 0x08
118 #define BLE_ATT_READ_BY_TYPE_RESP 0x09
119 #define BLE_ATT_READ_REQ 0x0a
120 #define BLE_ATT_READ_RESP 0x0b
121 #define BLE_ATT_READ_BLOB_REQ 0x0c
122 #define BLE_ATT_READ_BLOB_RESP 0x0d
123 #define BLE_ATT_READ_MULTIPLE_REQ 0x0e
124 #define BLE_ATT_READ_MULTIPLE_RESP 0x0f
125 #define BLE_ATT_READ_BY_GROUP_REQ 0x10
126 #define BLE_ATT_READ_BY_GROUP_RESP 0x11
127 #define BLE_ATT_WRITE_REQ 0x12
128 #define BLE_ATT_WRITE_RESP 0x13
129 #define BLE_ATT_WRITE_CMD 0x16
130 #define BLE_ATT_HANDLE_NOTIFICATION 0x1b
131 #define BLE_ATT_HANDLE_INDICATION 0x1d
132 #define BLE_ATT_HANDLE_CONFIRMATION 0x1e
133 #define BLE_ATT_SIGNED_WRITE_CMD 0x52
135 /* }}} Linux socket specific decls */
139 * Convert textual MAC presentation to array of bytes. In contrast to
140 * BlueZ conversion, accept colon or dash separated input as well as a
141 * dense format without separators (001122334455). We expect to use the
142 * library in an environment where colons are not always available as a
143 * separator in user provided specs, while users do want to use some
144 * separator for readability.
146 * TODO Instead of doing the actual conversion here (and dealing with
147 * BlueZ' internal byte order for device address bytes), we might as
148 * well just transform the input string to an output string, and always
149 * use the officially provided str2ba() conversion routine.
151 static int sr_bt_mac_text_to_bytes(const char *text, uint8_t *buf)
159 if (STORE_MAC_REVERSE)
162 while (len && endp && *endp) {
164 if (ACCEPT_NONSEP_MAC) {
166 numbuf[1] = endp[0] ? endp[1] : '\0';
170 v = strtol(ACCEPT_NONSEP_MAC ? numbuf : text, &endp, 16);
173 if (*endp != ':' && *endp != '-' && *endp != '\0')
175 if (v < 0 || v > 255)
177 if (STORE_MAC_REVERSE)
182 if (ACCEPT_NONSEP_MAC)
183 endp = (char *)text + (endp - numbuf);
184 if (*endp == ':' || *endp == '-')
189 sr_err("Failed to parse MAC, too few bytes in '%s'", text);
192 while (isspace(*endp))
195 sr_err("Failed to parse MAC, excess data in '%s'", text);
205 SR_PRIV const char *sr_bt_adapter_get_address(size_t idx)
208 struct hci_dev_info info;
211 rc = hci_devinfo(idx, &info);
212 sr_spew("DIAG: hci_devinfo(%zu) => rc %d", idx, rc);
216 rc = ba2str(&info.bdaddr, addr);
217 sr_spew("DIAG: ba2str() => rc %d", rc);
221 return g_strdup(addr);
228 /* User servicable options. */
229 sr_bt_scan_cb scan_cb;
231 sr_bt_data_cb data_cb;
234 char remote_addr[20];
235 size_t rfcomm_channel;
236 uint16_t read_handle;
237 uint16_t write_handle;
238 uint16_t cccd_handle;
241 /* Internal state. */
244 struct hci_filter orig_filter;
247 static int sr_bt_desc_open(struct sr_bt_desc *desc, int *id_ref);
248 static void sr_bt_desc_close(struct sr_bt_desc *desc);
249 static int sr_bt_check_socket_usable(struct sr_bt_desc *desc);
250 static ssize_t sr_bt_write_type(struct sr_bt_desc *desc, uint8_t type);
251 static ssize_t sr_bt_write_type_handle(struct sr_bt_desc *desc,
252 uint8_t type, uint16_t handle);
253 static ssize_t sr_bt_write_type_handle_bytes(struct sr_bt_desc *desc,
254 uint8_t type, uint16_t handle, const uint8_t *data, size_t len);
255 static ssize_t sr_bt_char_write_req(struct sr_bt_desc *desc,
256 uint16_t handle, const void *data, size_t len);
258 SR_PRIV struct sr_bt_desc *sr_bt_desc_new(void)
260 struct sr_bt_desc *desc;
262 desc = g_malloc0(sizeof(*desc));
272 SR_PRIV void sr_bt_desc_free(struct sr_bt_desc *desc)
277 sr_bt_desc_close(desc);
281 SR_PRIV int sr_bt_config_cb_scan(struct sr_bt_desc *desc,
282 sr_bt_scan_cb cb, void *cb_data)
288 desc->scan_cb_data = cb_data;
293 SR_PRIV int sr_bt_config_cb_data(struct sr_bt_desc *desc,
294 sr_bt_data_cb cb, void *cb_data)
300 desc->data_cb_data = cb_data;
305 SR_PRIV int sr_bt_config_addr_local(struct sr_bt_desc *desc, const char *addr)
313 if (!addr || !addr[0]) {
314 desc->local_addr[0] = '\0';
318 rc = sr_bt_mac_text_to_bytes(addr, &mac_bytes.b[0]);
322 rc = ba2str(&mac_bytes, desc->local_addr);
329 SR_PRIV int sr_bt_config_addr_remote(struct sr_bt_desc *desc, const char *addr)
337 if (!addr || !addr[0]) {
338 desc->remote_addr[0] = '\0';
342 rc = sr_bt_mac_text_to_bytes(addr, &mac_bytes.b[0]);
346 rc = ba2str(&mac_bytes, desc->remote_addr);
353 SR_PRIV int sr_bt_config_rfcomm(struct sr_bt_desc *desc, size_t channel)
358 desc->rfcomm_channel = channel;
363 SR_PRIV int sr_bt_config_notify(struct sr_bt_desc *desc,
364 uint16_t read_handle, uint16_t write_handle,
365 uint16_t cccd_handle, uint16_t cccd_value,
372 desc->read_handle = read_handle;
373 desc->write_handle = write_handle;
374 desc->cccd_handle = cccd_handle;
375 desc->cccd_value = cccd_value;
376 desc->ble_mtu = ble_mtu;
381 static int sr_bt_desc_open(struct sr_bt_desc *desc, int *id_ref)
390 if (desc->local_addr[0]) {
391 id = hci_devid(desc->local_addr);
392 } else if (desc->remote_addr[0]) {
393 str2ba(desc->remote_addr, &mac);
394 id = hci_get_route(&mac);
396 id = hci_get_route(NULL);
399 sr_err("devid failed");
406 sock = hci_open_dev(id);
408 perror("open HCI socket");
416 static void sr_bt_desc_close(struct sr_bt_desc *desc)
423 hci_close_dev(desc->fd);
432 #define EIR_NAME_COMPLETE 9
434 static int sr_bt_scan_prep(struct sr_bt_desc *desc)
437 uint8_t type, owntype, filter;
438 uint16_t ival, window;
442 struct hci_filter scan_filter;
447 /* TODO Replace magic values with symbolic identifiers. */
448 type = 0x01; /* LE public? */
449 ival = htobs(0x0010);
450 window = htobs(0x0010);
451 owntype = 0x00; /* any? */
454 rc = hci_le_set_scan_parameters(desc->fd,
455 type, ival, window, owntype, filter, timeout);
457 perror("set LE scan params");
464 rc = hci_le_set_scan_enable(desc->fd, enable, dup, timeout);
466 perror("set LE scan enable");
470 /* Save the current filter. For later restoration. */
471 slen = sizeof(desc->orig_filter);
472 rc = getsockopt(desc->fd, SOL_HCI, HCI_FILTER,
473 &desc->orig_filter, &slen);
475 perror("getsockopt(HCI_FILTER)");
479 hci_filter_clear(&scan_filter);
480 hci_filter_set_ptype(HCI_EVENT_PKT, &scan_filter);
481 hci_filter_set_event(EVT_LE_META_EVENT, &scan_filter);
482 rc = setsockopt(desc->fd, SOL_HCI, HCI_FILTER,
483 &scan_filter, sizeof(scan_filter));
485 perror("setsockopt(HCI_FILTER)");
492 static int sr_bt_scan_post(struct sr_bt_desc *desc)
501 /* Restore previous HCI filter. */
502 rc = setsockopt(desc->fd, SOL_HCI, HCI_FILTER,
503 &desc->orig_filter, sizeof(desc->orig_filter));
505 perror("setsockopt(HCI_FILTER)");
512 rc = hci_le_set_scan_enable(desc->fd, enable, dup, timeout);
519 static int sr_bt_scan_proc(struct sr_bt_desc *desc,
520 sr_bt_scan_cb scan_cb, void *cb_data,
521 uint8_t *data, size_t dlen, le_advertising_info *info)
530 if (type == EIR_NAME_COMPLETE) {
531 ba2str(&info->bdaddr, addr);
532 name = g_strndup((const char *)&data[1], dlen - 1);
534 scan_cb(cb_data, addr, name);
539 /* Unknown or unsupported type, ignore silently. */
543 SR_PRIV int sr_bt_scan_le(struct sr_bt_desc *desc, int duration)
547 uint8_t buf[HCI_MAX_EVENT_SIZE];
548 ssize_t rdlen, rdpos;
549 evt_le_meta_event *meta;
550 le_advertising_info *info;
556 sr_dbg("BLE scan (LE)");
558 rc = sr_bt_desc_open(desc, NULL);
562 rc = sr_bt_scan_prep(desc);
566 deadline = time(NULL);
567 deadline += duration;
568 while (time(NULL) <= deadline) {
570 if (sr_bt_check_socket_usable(desc) < 0)
572 rdlen = sr_bt_read(desc, buf, sizeof(buf));
579 if (rdlen < 1 + HCI_EVENT_HDR_SIZE)
581 meta = (void *)&buf[1 + HCI_EVENT_HDR_SIZE];
582 rdlen -= 1 + HCI_EVENT_HDR_SIZE;
583 if (meta->subevent != EVT_LE_ADVERTISING_REPORT)
585 info = (void *)&meta->data[1];
586 sr_spew("evt: type %d, len %d", info->evt_type, info->length);
591 while (rdpos < rdlen) {
592 datalen = info->data[rdpos];
593 dataptr = &info->data[1 + rdpos];
594 if (rdpos + 1 + datalen > info->length)
596 rdpos += 1 + datalen;
597 rc = sr_bt_scan_proc(desc,
598 desc->scan_cb, desc->scan_cb_data,
599 dataptr, datalen, info);
605 rc = sr_bt_scan_post(desc);
609 sr_bt_desc_close(desc);
614 SR_PRIV int sr_bt_scan_bt(struct sr_bt_desc *desc, int duration)
616 int dev_id, sock, rsp_max;
620 size_t rsp_count, idx;
626 sr_dbg("BLE scan (BT)");
628 sock = sr_bt_desc_open(desc, &dev_id);
633 info = g_malloc0(rsp_max * sizeof(*info));
634 flags = 0 /* | IREQ_CACHE_FLUSH */;
635 inq_rc = hci_inquiry(dev_id, duration, rsp_max, NULL, &info, flags);
637 perror("hci_inquiry");
640 for (idx = 0; idx < rsp_count; idx++) {
641 memset(addr, 0, sizeof(addr));
642 ba2str(&info[idx].bdaddr, addr);
643 memset(name, 0, sizeof(name));
644 if (hci_read_remote_name(sock, &info[idx].bdaddr, sizeof(name), name, 0) < 0)
645 snprintf(name, sizeof(name), "[unknown]");
647 desc->scan_cb(desc->scan_cb_data, addr, name);
651 sr_bt_desc_close(desc);
657 /* {{{ connect/disconnect */
659 SR_PRIV int sr_bt_connect_ble(struct sr_bt_desc *desc)
661 struct sockaddr_l2 sl2;
668 if (!desc->remote_addr[0])
670 sr_dbg("BLE connect, remote addr %s", desc->remote_addr);
672 s = socket(AF_BLUETOOTH, SOCK_SEQPACKET, 0);
674 perror("socket create");
679 memset(&sl2, 0, sizeof(sl2));
680 sl2.l2_family = AF_BLUETOOTH;
682 if (desc->local_addr[0])
683 str2ba(desc->local_addr, &mac);
686 memcpy(&sl2.l2_bdaddr, &mac, sizeof(sl2.l2_bdaddr));
687 sl2.l2_cid = L2CAP_FC_CONNLESS;
688 sl2.l2_bdaddr_type = BDADDR_LE_PUBLIC;
689 ret = bind(s, (void *)&sl2, sizeof(sl2));
696 struct bt_security buf = {
697 .level = BT_SECURITY_LOW,
700 ret = setsockopt(s, SOL_BLUETOOTH, BT_SECURITY, &buf, sizeof(buf));
702 perror("setsockopt");
707 deadline = g_get_monotonic_time();
708 deadline += CONNECT_BLE_TIMEOUT * 1000 * 1000;
709 str2ba(desc->remote_addr, &mac);
710 memcpy(&sl2.l2_bdaddr, &mac, sizeof(sl2.l2_bdaddr));
711 sl2.l2_bdaddr_type = BDADDR_LE_PUBLIC;
712 ret = connect(s, (void *)&sl2, sizeof(sl2));
714 * Cope with "in progress" condition. Keep polling the status
715 * until connect() completes, then get the error by means of
716 * getsockopt(). See the connect(2) manpage for details.
718 if (ret < 0 && errno == EINPROGRESS) {
719 struct pollfd fds[1];
724 * We seem to get here ("connect in progress") even when
725 * the specified peer is not around at all. Which results
726 * in extended periods of time where nothing happens, and
727 * an application timeout seems to be required.
729 sr_spew("in progress ...");
732 memset(fds, 0, sizeof(fds));
734 fds[0].events = POLLOUT;
735 ret = poll(fds, ARRAY_SIZE(fds), -1);
742 if (!(fds[0].revents & POLLOUT))
744 if (g_get_monotonic_time() >= deadline) {
745 sr_warn("Connect attempt timed out");
749 memset(fds, 0, sizeof(fds));
751 fds[0].events = POLLNVAL;
752 ret = poll(fds, 1, 0);
754 perror("poll(INVAL)");
758 /* socket fd is invalid(?) */
763 solen = sizeof(soerror);
764 ret = getsockopt(s, SOL_SOCKET, SO_ERROR, &soerror, &solen);
766 perror("getsockopt(SO_ERROR)");
770 /* connect(2) failed, SO_ERROR has the error code. */
772 perror("connect(PROGRESS)");
777 * TODO Get the receive MTU here?
778 * getsockopt(SOL_BLUETOOTH, BT_RCVMTU, u16);
789 SR_PRIV int sr_bt_connect_rfcomm(struct sr_bt_desc *desc)
791 struct sockaddr_rc addr;
796 if (!desc->remote_addr[0])
798 sr_dbg("RFCOMM connect, remote addr %s, channel %zu",
799 desc->remote_addr, desc->rfcomm_channel);
801 if (!desc->rfcomm_channel)
802 desc->rfcomm_channel = 1;
804 memset(&addr, 0, sizeof(addr));
805 addr.rc_family = AF_BLUETOOTH;
806 str2ba(desc->remote_addr, &addr.rc_bdaddr);
807 addr.rc_channel = desc->rfcomm_channel;
810 * There are cases where connect returns EBUSY if we are re-connecting
811 * to a device. Try multiple times to work around this issue.
813 for (i = 0; i < CONNECT_RFCOMM_TRIES; i++) {
814 fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
820 rc = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
822 sr_spew("connected");
825 } else if (rc < 0 && errno == EBUSY) {
827 g_usleep(CONNECT_RFCOMM_RETRY_MS * 1000);
835 sr_err("Connect failed, device busy.");
840 SR_PRIV void sr_bt_disconnect(struct sr_bt_desc *desc)
842 sr_dbg("BLE disconnect");
846 sr_bt_desc_close(desc);
849 static int sr_bt_check_socket_usable(struct sr_bt_desc *desc)
851 struct pollfd fds[1];
859 memset(fds, 0, sizeof(fds));
860 fds[0].fd = desc->fd;
861 fds[0].events = POLLERR | POLLHUP;
862 ret = poll(fds, ARRAY_SIZE(fds), 0);
867 if (fds[0].revents & POLLHUP)
869 if (fds[0].revents & POLLERR)
871 if (fds[0].revents & POLLNVAL)
877 /* }}} connect/disconnect */
878 /* {{{ indication/notification */
880 SR_PRIV int sr_bt_start_notify(struct sr_bt_desc *desc)
882 uint8_t buf[sizeof(desc->cccd_value)];
887 sr_dbg("BLE start notify");
889 if (sr_bt_check_socket_usable(desc) < 0)
892 write_u16le(buf, desc->cccd_value);
893 wrlen = sr_bt_char_write_req(desc, desc->cccd_handle, buf, sizeof(buf));
894 if (wrlen != sizeof(buf))
900 SR_PRIV int sr_bt_check_notify(struct sr_bt_desc *desc)
904 const uint8_t *bufptr;
907 uint16_t packet_handle;
908 uint8_t *packet_data;
910 const char *type_text;
917 if (sr_bt_check_socket_usable(desc) < 0)
921 * Get another message from the Bluetooth socket.
923 * TODO Can we assume that every "message" comes in a separate
924 * read(2) call, or can data combine at the caller's? Need we
925 * loop over the received content until all was consumed?
927 rdlen = sr_bt_read(desc, buf, sizeof(buf));
929 sr_dbg("check notifiy, read error, %zd", rdlen);
933 if (0) sr_spew("check notifiy, empty read");
937 buflen = (size_t)rdlen;
938 if (sr_log_loglevel_get() >= SR_LOG_SPEW) {
940 txt = sr_hexdump_new(bufptr, buflen);
941 sr_spew("check notifiy, read succes, length %zd, data: %s",
943 sr_hexdump_free(txt);
947 * Get header fields and references to the payload data. Notice
948 * that the first 16bit item after the packet type often is the
949 * handle, but need not always be. That is why the read position
950 * is kept, so that individual packet type handlers can either
951 * read _their_ layout strictly sequentially, or can conveniently
952 * access what a common preparation step has provided to them.
954 packet_handle = 0x0000;
957 packet_type = read_u8_inc_len(&bufptr, &buflen);
958 if (buflen >= sizeof(uint16_t)) {
959 packet_handle = read_u16le(bufptr);
960 packet_data = (void *)&bufptr[sizeof(uint16_t)];
961 packet_dlen = buflen - sizeof(uint16_t);
965 if (0) sr_spew("check notifiy, prep, hdl %" PRIu16 ", data %p len %zu",
966 packet_handle, packet_data, packet_dlen);
968 /* Dispatch according to the message type. */
969 switch (packet_type) {
970 case BLE_ATT_EXCHANGE_MTU_REQ:
971 type_text = "MTU exchange request";
972 if (buflen < sizeof(uint16_t)) {
973 sr_dbg("%s, invalid (size)", type_text);
976 mtu = read_u16le_inc_len(&bufptr, &buflen);
977 sr_dbg("%s, peripheral value %" PRIu16, type_text, mtu);
980 sr_dbg("%s, central value %" PRIu16, type_text, mtu);
981 sr_bt_write_type_handle(desc,
982 BLE_ATT_EXCHANGE_MTU_RESP, mtu);
985 sr_warn("Unhandled BLE %s.", type_text);
987 case BLE_ATT_ERROR_RESP:
988 type_text = "error response";
990 sr_dbg("%s, no payload", type_text);
994 sr_dbg("%s, not handled here", type_text);
996 case BLE_ATT_WRITE_RESP:
997 type_text = "write response";
998 sr_dbg("%s, note taken", type_text);
1000 case BLE_ATT_HANDLE_INDICATION:
1001 type_text = "handle indication";
1002 sr_dbg("%s, data len %zu", type_text, packet_dlen);
1003 sr_bt_write_type(desc, BLE_ATT_HANDLE_CONFIRMATION);
1004 sr_spew("%s, confirmation sent", type_text);
1005 if (packet_handle != desc->read_handle)
1009 ret = desc->data_cb(desc->data_cb_data,
1010 packet_data, packet_dlen);
1011 sr_spew("%s, data cb ret %d", type_text, ret);
1013 case BLE_ATT_HANDLE_NOTIFICATION:
1014 type_text = "handle notification";
1015 sr_dbg("%s, data len %zu", type_text, packet_dlen);
1016 if (packet_handle != desc->read_handle)
1020 ret = desc->data_cb(desc->data_cb_data,
1021 packet_data, packet_dlen);
1022 sr_spew("%s, data cb ret %d", type_text, ret);
1025 sr_dbg("unhandled type 0x%02x, len %zu",
1026 packet_type, buflen);
1033 /* }}} indication/notification */
1034 /* {{{ read/write */
1036 SR_PRIV ssize_t sr_bt_write(struct sr_bt_desc *desc,
1037 const void *data, size_t len)
1044 if (sr_bt_check_socket_usable(desc) < 0)
1047 /* Send TX data to the writable characteristics for BLE UART services. */
1048 if (desc->write_handle)
1049 return sr_bt_char_write_req(desc, desc->write_handle, data, len);
1051 /* Send raw TX data to the RFCOMM socket for BT Classic channels. */
1052 return write(desc->fd, data, len);
1055 static ssize_t sr_bt_write_type(struct sr_bt_desc *desc, uint8_t type)
1064 if (sr_bt_check_socket_usable(desc) < 0)
1067 wrlen = write(desc->fd, &type, sizeof(type));
1070 if (wrlen < (ssize_t)sizeof(type))
1076 static ssize_t sr_bt_write_type_handle(struct sr_bt_desc *desc,
1077 uint8_t type, uint16_t handle)
1079 return sr_bt_write_type_handle_bytes(desc, type, handle, NULL, 0);
1082 static ssize_t sr_bt_write_type_handle_bytes(struct sr_bt_desc *desc,
1083 uint8_t type, uint16_t handle, const uint8_t *data, size_t len)
1085 uint8_t header[sizeof(uint8_t) + sizeof(uint16_t)];
1086 struct iovec iov[2] = {
1087 { .iov_base = header, .iov_len = sizeof(header), },
1088 { .iov_base = (void *)data, .iov_len = len, },
1097 if (sr_bt_check_socket_usable(desc) < 0)
1101 write_u16le(&header[1], handle);
1104 wrlen = writev(desc->fd, iov, ARRAY_SIZE(iov));
1106 wrlen = write(desc->fd, header, sizeof(header));
1110 if (wrlen < (ssize_t)sizeof(header))
1112 wrlen -= sizeof(header);
1117 /* Returns negative upon error, or returns the number of _payload_ bytes written. */
1118 static ssize_t sr_bt_char_write_req(struct sr_bt_desc *desc,
1119 uint16_t handle, const void *data, size_t len)
1121 return sr_bt_write_type_handle_bytes(desc, BLE_ATT_WRITE_REQ,
1125 SR_PRIV ssize_t sr_bt_read(struct sr_bt_desc *desc, void *data, size_t len)
1127 struct pollfd fds[1];
1136 if (sr_bt_check_socket_usable(desc) < 0)
1139 memset(fds, 0, sizeof(fds));
1140 fds[0].fd = desc->fd;
1141 fds[0].events = POLLIN;
1142 ret = poll(fds, ARRAY_SIZE(fds), 0);
1147 if (!(fds[0].revents & POLLIN))
1150 rdlen = read(desc->fd, data, len);
1155 /* }}} indication/notification */