23 #include "libsigrok-internal.h"
28 #define LOG_PREFIX "serial-bt"
31 #ifdef HAVE_SERIAL_COMM
34 #define SER_BT_CONN_PREFIX "bt"
35 #define SER_BT_CHUNK_SIZE 1200
53 static const struct scan_supported_item {
55 enum ser_bt_conn_t type;
56 } scan_supported_items[] = {
58 {
"121GW", SER_BT_CONN_BLE122, },
59 {
"Adafruit Bluefruit LE 8134", SER_BT_CONN_NRF51, },
60 {
"HC-05", SER_BT_CONN_RFCOMM, },
61 { NULL, SER_BT_CONN_UNKNOWN, },
64 static const char *ser_bt_conn_names[SER_BT_CONN_MAX] = {
65 [SER_BT_CONN_UNKNOWN] =
"<type>",
66 [SER_BT_CONN_RFCOMM] =
"rfcomm",
67 [SER_BT_CONN_BLE122] =
"ble122",
68 [SER_BT_CONN_NRF51] =
"nrf51",
69 [SER_BT_CONN_CC254x] =
"cc254x",
72 static enum ser_bt_conn_t lookup_conn_name(
const char *name)
78 return SER_BT_CONN_UNKNOWN;
79 idx = ARRAY_SIZE(ser_bt_conn_names);
81 item = ser_bt_conn_names[idx];
82 if (strcmp(item, name) == 0)
86 return SER_BT_CONN_UNKNOWN;
89 static const char *conn_name_text(
enum ser_bt_conn_t type)
91 if (type >= ARRAY_SIZE(ser_bt_conn_names))
92 type = SER_BT_CONN_UNKNOWN;
94 return ser_bt_conn_names[type];
142 static int ser_bt_parse_conn_spec(
143 struct sr_serial_dev_inst *serial,
const char *spec,
144 enum ser_bt_conn_t *conn_type,
const char **remote_addr,
145 size_t *rfcomm_channel,
146 uint16_t *read_hdl, uint16_t *write_hdl,
147 uint16_t *cccd_hdl, uint16_t *cccd_val)
149 enum ser_bt_conn_t type;
151 char **fields, *field;
154 *conn_type = SER_BT_CONN_UNKNOWN;
168 type = SER_BT_CONN_UNKNOWN;
171 if (!serial || !spec || !spec[0])
175 fields = g_strsplit_set(spec,
"/", 0);
178 if (g_strv_length(fields) < 3) {
183 if (strcmp(field, SER_BT_CONN_PREFIX) != 0) {
188 type = lookup_conn_name(field);
196 if (!field || !*field) {
200 addr = g_strdup(field);
207 case SER_BT_CONN_RFCOMM:
211 case SER_BT_CONN_BLE122:
221 case SER_BT_CONN_NRF51:
236 case SER_BT_CONN_CC254x:
257 static void ser_bt_mask_databits(
struct sr_serial_dev_inst *serial,
258 uint8_t *data,
size_t len)
264 if ((serial->comm_params.data_bits % 8) == 0)
267 mask32 = (1UL << serial->comm_params.data_bits) - 1;
268 mask = mask32 & 0xff;
269 for (idx = 0; idx < len; idx++)
273 static int ser_bt_data_cb(
void *cb_data, uint8_t *data,
size_t dlen)
275 struct sr_serial_dev_inst *serial;
281 ser_bt_mask_databits(serial, data, dlen);
282 sr_ser_queue_rx_data(serial, data, dlen);
291 SR_PRIV int ser_name_is_bt(
struct sr_serial_dev_inst *serial)
298 if (!serial->port || !*serial->port)
302 if (!g_str_has_prefix(serial->port, SER_BT_CONN_PREFIX))
304 off = strlen(SER_BT_CONN_PREFIX);
305 sep = serial->port[off];
306 if (sep !=
'\0' && sep !=
'/')
313 static int ser_bt_open(
struct sr_serial_dev_inst *serial,
int flags)
315 enum ser_bt_conn_t conn_type;
316 const char *remote_addr;
317 size_t rfcomm_channel;
318 uint16_t read_hdl, write_hdl, cccd_hdl, cccd_val;
320 struct sr_bt_desc *desc;
325 rc = ser_bt_parse_conn_spec(serial, serial->port,
326 &conn_type, &remote_addr,
328 &read_hdl, &write_hdl,
329 &cccd_hdl, &cccd_val);
333 if (!conn_type || !remote_addr || !remote_addr[0]) {
339 desc = sr_bt_desc_new();
342 serial->bt_desc = desc;
343 rc = sr_bt_config_addr_remote(desc, remote_addr);
346 serial->bt_addr_remote = g_strdup(remote_addr);
348 case SER_BT_CONN_RFCOMM:
349 rc = sr_bt_config_rfcomm(desc, rfcomm_channel);
352 serial->bt_rfcomm_channel = rfcomm_channel;
354 case SER_BT_CONN_BLE122:
355 case SER_BT_CONN_NRF51:
356 case SER_BT_CONN_CC254x:
357 rc = sr_bt_config_notify(desc,
358 read_hdl, write_hdl, cccd_hdl, cccd_val);
361 serial->bt_notify_handle_read = read_hdl;
362 serial->bt_notify_handle_write = write_hdl;
363 serial->bt_notify_handle_cccd = cccd_hdl;
364 serial->bt_notify_value_cccd = cccd_val;
370 serial->bt_conn_type = conn_type;
373 if (!serial->rcv_buffer)
374 serial->rcv_buffer = g_string_sized_new(SER_BT_CHUNK_SIZE);
375 rc = sr_bt_config_cb_data(desc, ser_bt_data_cb, serial);
381 case SER_BT_CONN_RFCOMM:
382 rc = sr_bt_connect_rfcomm(desc);
386 case SER_BT_CONN_BLE122:
387 case SER_BT_CONN_NRF51:
388 case SER_BT_CONN_CC254x:
389 rc = sr_bt_connect_ble(desc);
392 rc = sr_bt_start_notify(desc);
403 static int ser_bt_close(
struct sr_serial_dev_inst *serial)
408 if (!serial->bt_desc)
411 sr_bt_disconnect(serial->bt_desc);
412 sr_bt_desc_free(serial->bt_desc);
413 serial->bt_desc = NULL;
415 g_free(serial->bt_addr_local);
416 serial->bt_addr_local = NULL;
417 g_free(serial->bt_addr_remote);
418 serial->bt_addr_remote = NULL;
419 g_slist_free_full(serial->bt_source_args, g_free);
420 serial->bt_source_args = NULL;
426 static int ser_bt_flush(
struct sr_serial_dev_inst *serial)
435 static int ser_bt_drain(
struct sr_serial_dev_inst *serial)
443 static int ser_bt_write(
struct sr_serial_dev_inst *serial,
444 const void *buf,
size_t count,
445 int nonblocking,
unsigned int timeout_ms)
454 switch (serial->bt_conn_type) {
455 case SER_BT_CONN_RFCOMM:
458 wrlen = sr_bt_write(serial->bt_desc, buf, count);
462 case SER_BT_CONN_BLE122:
463 case SER_BT_CONN_NRF51:
464 case SER_BT_CONN_CC254x:
473 wrlen = sr_bt_write(serial->bt_desc, buf, count);
483 static int ser_bt_read(
struct sr_serial_dev_inst *serial,
484 void *buf,
size_t count,
485 int nonblocking,
unsigned int timeout_ms)
487 gint64 deadline_us, now_us;
488 uint8_t buffer[SER_BT_CHUNK_SIZE];
497 if (sr_ser_has_queued_data(serial) >= count)
498 return sr_ser_unqueue_rx_data(serial, buf, count);
507 now_us = g_get_monotonic_time();
508 deadline_us = now_us + timeout_ms * 1000;
519 switch (serial->bt_conn_type) {
520 case SER_BT_CONN_RFCOMM:
521 rdlen = sr_bt_read(serial->bt_desc, buffer,
sizeof(buffer));
524 rc = ser_bt_data_cb(serial, buffer, rdlen);
528 case SER_BT_CONN_BLE122:
529 case SER_BT_CONN_NRF51:
530 case SER_BT_CONN_CC254x:
531 dlen = sr_ser_has_queued_data(serial);
532 rc = sr_bt_check_notify(serial->bt_desc);
535 else if (sr_ser_has_queued_data(serial) != dlen)
551 if (nonblocking && !rdlen)
554 now_us = g_get_monotonic_time();
555 if (now_us > deadline_us)
560 if (sr_ser_has_queued_data(serial) >= count)
568 dlen = sr_ser_has_queued_data(serial);
574 return sr_ser_unqueue_rx_data(serial, buf, dlen);
577 struct bt_source_args_t {
582 struct sr_serial_dev_inst *serial;
591 static int bt_source_cb(
int fd,
int revents,
void *cb_data)
593 struct bt_source_args_t *args;
594 struct sr_serial_dev_inst *serial;
595 uint8_t rx_buf[SER_BT_CHUNK_SIZE];
603 serial = args->serial;
606 if (!serial->bt_conn_type)
616 switch (serial->bt_conn_type) {
617 case SER_BT_CONN_RFCOMM:
618 rdlen = sr_bt_read(serial->bt_desc, rx_buf,
sizeof(rx_buf));
621 rc = ser_bt_data_cb(serial, rx_buf, rdlen);
625 case SER_BT_CONN_BLE122:
626 case SER_BT_CONN_NRF51:
627 case SER_BT_CONN_CC254x:
628 dlen = sr_ser_has_queued_data(serial);
629 rc = sr_bt_check_notify(serial->bt_desc);
632 else if (sr_ser_has_queued_data(serial) != dlen)
649 if (sr_ser_has_queued_data(args->serial))
651 rc = args->cb(fd, revents, args->cb_data);
657 #define WITH_MAXIMUM_TIMEOUT_VALUE 0
658 static int ser_bt_setup_source_add(
struct sr_session *session,
659 struct sr_serial_dev_inst *serial,
660 int events,
int timeout,
663 struct bt_source_args_t *args;
669 if (WITH_MAXIMUM_TIMEOUT_VALUE && timeout > WITH_MAXIMUM_TIMEOUT_VALUE)
670 timeout = WITH_MAXIMUM_TIMEOUT_VALUE;
673 args = g_malloc0(
sizeof(*args));
675 args->cb_data = cb_data;
676 args->serial = serial;
684 rc = sr_session_source_add(session, -1, events, timeout, bt_source_cb, args);
689 serial->bt_source_args = g_slist_append(serial->bt_source_args, args);
694 static int ser_bt_setup_source_remove(
struct sr_session *session,
695 struct sr_serial_dev_inst *serial)
699 (void)sr_session_source_remove(session, -1);
705 static enum ser_bt_conn_t scan_is_supported(
const char *name)
708 const struct scan_supported_item *item;
710 for (idx = 0; idx < ARRAY_SIZE(scan_supported_items); idx++) {
711 item = &scan_supported_items[idx];
714 if (strcmp(name, item->name) != 0)
719 return SER_BT_CONN_UNKNOWN;
722 struct bt_scan_args_t {
724 sr_ser_list_append_t append;
729 static void scan_cb(
void *cb_args,
const char *addr,
const char *name)
731 struct bt_scan_args_t *scan_args;
734 enum ser_bt_conn_t type;
735 char *port_name, *port_desc;
741 sr_info(
"BT scan, found: %s - %s\n", addr, name);
744 for (l = scan_args->addr_list; l; l = l->next) {
745 if (strcmp(addr, l->data) == 0)
752 snprintf(addr_text,
sizeof(addr_text),
"%s", addr);
753 g_strcanon(addr_text,
"0123456789abcdefABCDEF",
'-');
756 type = scan_is_supported(name);
757 port_name = g_strdup_printf(
"%s/%s/%s",
758 SER_BT_CONN_PREFIX, conn_name_text(type), addr_text);
759 port_desc = g_strdup_printf(
"%s (%s)", name, scan_args->bt_type);
761 scan_args->port_list = scan_args->append(scan_args->port_list, port_name, port_desc);
766 addr_copy = g_strdup(addr);
767 scan_args->addr_list = g_slist_append(scan_args->addr_list, addr_copy);
770 static GSList *ser_bt_list(GSList *list, sr_ser_list_append_t append)
772 static const int scan_duration = 2;
774 struct bt_scan_args_t scan_args;
775 struct sr_bt_desc *desc;
784 desc = sr_bt_desc_new();
788 memset(&scan_args, 0,
sizeof(scan_args));
789 scan_args.port_list = list;
790 scan_args.append = append;
792 scan_args.addr_list = NULL;
793 scan_args.bt_type =
"BT";
794 (void)sr_bt_config_cb_scan(desc, scan_cb, &scan_args);
795 (void)sr_bt_scan_bt(desc, scan_duration);
796 g_slist_free_full(scan_args.addr_list, g_free);
798 scan_args.addr_list = NULL;
799 scan_args.bt_type =
"BLE";
800 (void)sr_bt_config_cb_scan(desc, scan_cb, &scan_args);
801 (void)sr_bt_scan_le(desc, scan_duration);
802 g_slist_free_full(scan_args.addr_list, g_free);
804 sr_bt_desc_free(desc);
806 return scan_args.port_list;
809 static struct ser_lib_functions serlib_bt = {
811 .close = ser_bt_close,
812 .flush = ser_bt_flush,
813 .drain = ser_bt_drain,
814 .write = ser_bt_write,
822 .set_params = std_dummy_set_params,
823 .setup_source_add = ser_bt_setup_source_add,
824 .setup_source_remove = ser_bt_setup_source_remove,
826 .get_frame_format = NULL,
828 SR_PRIV struct ser_lib_functions *ser_lib_funcs_bt = &serlib_bt;
833 SR_PRIV int ser_name_is_bt(
struct sr_serial_dev_inst *serial)
840 SR_PRIV struct ser_lib_functions *ser_lib_funcs_bt = NULL;
Generic/unspecified error.
The public libsigrok header file to be used by frontends.
int(* sr_receive_data_callback)(int fd, int revents, void *cb_data)
Type definition for callback function for data reception.
Errors hinting at internal bugs.
Opaque structure representing a libsigrok session.