Skip to content

Commit 7459f9f

Browse files
committed
pbdrv/bluetooth: Add POSIX btstack for virtualhub.
- Changes pbdrv_bluetooth_btstack_set_chipset to convey all necessary information to set the correct chipset both from the read local version information command as well as events from the USB subsystem. - Adds a POSIX implementation for pbdrv_bluetooth_btstack_set_chipset. This supports the most common Realtek and Broadcom chipsets, which comprise the vast majority of USB dongles. - Sets up the virtualhub platform to use this chipset. - Adjusts the runloop to check for readability and writability of file descriptors, which is required for the libusb transport.
1 parent a314eba commit 7459f9f

File tree

14 files changed

+453
-16
lines changed

14 files changed

+453
-16
lines changed

.vscode/c_cpp_properties.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,11 @@
386386
"${workspaceFolder}/bricks/virtualhub",
387387
"${workspaceFolder}/bricks/virtualhub/build",
388388
"${workspaceFolder}/bricks/virtualhub/build-debug",
389+
"${workspaceFolder}/lib/btstack/chipset/bcm",
390+
"${workspaceFolder}/lib/btstack/chipset/realtek",
391+
"${workspaceFolder}/lib/btstack/platform/libusb",
392+
"${workspaceFolder}/lib/btstack/platform/posix",
393+
"${workspaceFolder}/lib/btstack/src",
389394
"${workspaceFolder}/lib/lego",
390395
"${workspaceFolder}/lib/lwrb/src/include",
391396
"${workspaceFolder}/lib/pbio",

bricks/_common/common.mk

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,18 @@ endif
124124
ifneq ($(strip $(PB_LIB_BTSTACK)),)
125125
INC += -I$(PBTOP)/lib/btstack/chipset/cc256x
126126
INC += -I$(PBTOP)/lib/btstack/src
127+
ifeq ($(PBIO_PLATFORM),virtual_hub)
128+
INC += -I$(PBTOP)/lib/btstack/platform/posix
129+
INC += -I$(PBTOP)/lib/btstack/platform/embedded
130+
INC += -I$(PBTOP)/lib/btstack/3rd-party/tinydir
131+
INC += -I$(PBTOP)/lib/btstack/3rd-party/rijndael
132+
INC += -I$(PBTOP)/lib/btstack/3rd-party/micro-ecc
133+
INC += -I$(PBTOP)/lib/btstack/chipset/bcm
134+
INC += -I$(PBTOP)/lib/btstack/chipset/intel
135+
INC += -I$(PBTOP)/lib/btstack/chipset/realtek
136+
INC += -I$(PBTOP)/lib/btstack/chipset/zephyr
137+
INC += $(shell pkg-config libusb-1.0 --cflags)
138+
endif
127139
endif
128140
ifeq ($(PB_LIB_LSM6DS3TR_C),1)
129141
INC += -I$(PBTOP)/lib/lsm6ds3tr_c_STdC/driver
@@ -162,6 +174,9 @@ else ifeq ($(UNAME_S),Darwin)
162174
LDFLAGS += -Wl,-map,$@.map -Wl,-dead_strip
163175
endif
164176
LIBS = -lm
177+
ifeq ($(PB_LIB_BTSTACK),lowenergy)
178+
LIBS += $(shell pkg-config libusb-1.0 --libs)
179+
endif
165180
else # end native, begin embedded
166181
CROSS_COMPILE ?= arm-none-eabi-
167182
ifeq ($(PB_MCU_FAMILY),STM32)
@@ -395,6 +410,37 @@ BTSTACK_SRC_C += $(addprefix lib/btstack/chipset/cc256x/,\
395410
btstack_chipset_cc256x.c \
396411
)
397412

413+
# libusb-specific BTStack sources for virtual_hub
414+
ifeq ($(PBIO_PLATFORM),virtual_hub)
415+
BTSTACK_SRC_C += $(addprefix lib/btstack/platform/libusb/,\
416+
hci_transport_h2_libusb.c \
417+
)
418+
BTSTACK_SRC_C += $(addprefix lib/btstack/platform/posix/,\
419+
hci_dump_posix_stdout.c \
420+
)
421+
BTSTACK_SRC_C += $(addprefix lib/btstack/src/ble/,\
422+
le_device_db_tlv.c \
423+
)
424+
BTSTACK_SRC_C += $(addprefix lib/btstack/chipset/zephyr/,\
425+
btstack_chipset_zephyr.c \
426+
)
427+
BTSTACK_SRC_C += $(addprefix lib/btstack/chipset/realtek/,\
428+
btstack_chipset_realtek.c \
429+
)
430+
BTSTACK_SRC_C += $(addprefix lib/btstack/chipset/bcm/,\
431+
btstack_chipset_bcm.c \
432+
)
433+
BTSTACK_SRC_C += $(addprefix lib/btstack/chipset/intel/,\
434+
btstack_chipset_intel_firmware.c \
435+
)
436+
BTSTACK_SRC_C += $(addprefix lib/btstack/3rd-party/rijndael/,\
437+
rijndael.c \
438+
)
439+
BTSTACK_SRC_C += $(addprefix lib/btstack/3rd-party/micro-ecc/,\
440+
uECC.c \
441+
)
442+
endif
443+
398444
# STM32 HAL
399445

400446
COPT += -DUSE_FULL_LL_DRIVER
@@ -530,11 +576,13 @@ endif
530576

531577
ifeq ($(PB_LIB_BTSTACK),classic)
532578
OBJ += $(addprefix $(BUILD)/, $(BTSTACK_SRC_C:.c=.o))
579+
$(BUILD)/lib/btstack/%.o: CFLAGS += -Wno-error
533580
endif
534581

535582
ifeq ($(PB_LIB_BTSTACK),lowenergy)
536583
OBJ += $(addprefix $(BUILD)/, $(BTSTACK_SRC_C:.c=.o))
537584
OBJ += $(addprefix $(BUILD)/, $(BTSTACK_BLE_SRC_C:.c=.o))
585+
$(BUILD)/lib/btstack/%.o: CFLAGS += -Wno-error
538586
endif
539587

540588
ifeq ($(PB_LIB_STM32_HAL),1)

bricks/_common/sources.mk

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,10 @@ PBIO_SRC_C = $(addprefix lib/pbio/,\
114114
drv/block_device/block_device_test.c \
115115
drv/block_device/block_device_w25qxx_stm32.c \
116116
drv/bluetooth/bluetooth.c \
117-
drv/bluetooth/bluetooth_btstack_stm32_hal.c \
118117
drv/bluetooth/bluetooth_btstack.c \
119118
drv/bluetooth/bluetooth_btstack_ev3.c \
119+
drv/bluetooth/bluetooth_btstack_posix.c \
120+
drv/bluetooth/bluetooth_btstack_stm32_hal.c \
120121
drv/bluetooth/bluetooth_simulation.c \
121122
drv/bluetooth/bluetooth_stm32_bluenrg.c \
122123
drv/bluetooth/bluetooth_stm32_cc2640.c \

bricks/virtualhub/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ PB_MCU_FAMILY = native
66
PB_FROZEN_MODULES = 1
77
MICROPY_ROM_TEXT_COMPRESSION = 1
88
PB_LIB_UMM_MALLOC = 1
9+
PB_LIB_BTSTACK = lowenergy
910

1011
include ../_common/common.mk

lib/pbio/drv/bluetooth/bluetooth_btstack.c

Lines changed: 112 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,23 @@
3030
#include "pybricks_service_server.h"
3131
#endif // PBDRV_CONFIG_BLUETOOTH_BTSTACK_LE
3232

33+
#if PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX
34+
35+
#include <errno.h>
36+
#include <poll.h>
37+
38+
#endif
39+
3340
#ifdef PBDRV_CONFIG_BLUETOOTH_BTSTACK_HUB_KIND
3441
#define HUB_KIND PBDRV_CONFIG_BLUETOOTH_BTSTACK_HUB_KIND
3542
#else
3643
#error "PBDRV_CONFIG_BLUETOOTH_BTSTACK_HUB_KIND is required"
3744
#endif
3845

46+
#ifndef PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX
47+
#define PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX 0
48+
#endif
49+
3950
// location of product variant in bootloader flash memory of Technic Large hubs
4051
#if PBDRV_CONFIG_BLUETOOTH_BTSTACK_HUB_VARIANT_ADDR
4152
#define HUB_VARIANT (*(const uint16_t *)PBDRV_CONFIG_BLUETOOTH_BTSTACK_HUB_VARIANT_ADDR)
@@ -223,23 +234,39 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
223234
pbdrv_bluetooth_peripheral_t *peri = &peripheral_singleton;
224235
#endif // PBDRV_CONFIG_BLUETOOTH_BTSTACK_LE
225236

237+
static pbdrv_bluetooth_btstack_device_discriminator device_info;
238+
226239
switch (hci_event_packet_get_type(packet)) {
240+
case HCI_EVENT_TRANSPORT_USB_INFO: {
241+
// Store USB vendor and product IDs for later use
242+
device_info.usb_vendor_id = hci_event_transport_usb_info_get_vendor_id(packet);
243+
device_info.usb_product_id = hci_event_transport_usb_info_get_product_id(packet);
244+
break;
245+
}
227246
case HCI_EVENT_COMMAND_COMPLETE: {
228247
const uint8_t *rp = hci_event_command_complete_get_return_parameters(packet);
229248
switch (hci_event_command_complete_get_command_opcode(packet)) {
230249
case HCI_OPCODE_HCI_READ_LOCAL_VERSION_INFORMATION: {
231-
uint16_t lmp_pal_subversion = pbio_get_uint16_le(&rp[7]);
232-
pbdrv_bluetooth_btstack_set_chipset(lmp_pal_subversion);
250+
device_info.hci_version = rp[0];
251+
device_info.hci_revision = pbio_get_uint16_le(&rp[1]);
252+
device_info.lmp_pal_version = rp[3];
253+
device_info.manufacturer = pbio_get_uint16_le(&rp[4]);
254+
device_info.lmp_pal_subversion = pbio_get_uint16_le(&rp[6]);
255+
pbdrv_bluetooth_btstack_set_chipset(&device_info);
233256

234257
#if DEBUG
235258
// Show version in ev3dev format.
259+
uint16_t lmp_pal_subversion = device_info.lmp_pal_subversion;
236260
uint16_t chip = (lmp_pal_subversion & 0x7C00) >> 10;
237261
uint16_t min_ver = (lmp_pal_subversion & 0x007F);
238262
uint16_t maj_ver = (lmp_pal_subversion & 0x0380) >> 7;
239263
if (lmp_pal_subversion & 0x8000) {
240264
maj_ver |= 0x0008;
241265
}
242266
DEBUG_PRINT("LMP %04x: TIInit_%d.%d.%d.bts\n", lmp_pal_subversion, chip, maj_ver, min_ver);
267+
(void)maj_ver; // In lib/pbio/test, this variable appears unused even though it's not.
268+
(void)min_ver;
269+
(void)chip;
243270
#endif
244271
break;
245272
}
@@ -999,6 +1026,21 @@ static void bluetooth_btstack_run_loop_execute(void) {
9991026
// not used
10001027
}
10011028

1029+
static void bluetooth_btstack_run_loop_dump_timer(void) {
1030+
// not used
1031+
}
1032+
1033+
static void bluetooth_btstack_run_loop_dump_timer(void) {
1034+
// not used
1035+
}
1036+
1037+
static bool do_poll_handler;
1038+
1039+
void pbdrv_bluetooth_btstack_run_loop_trigger(void) {
1040+
do_poll_handler = true;
1041+
pbio_os_request_poll();
1042+
}
1043+
10021044
static const btstack_run_loop_t bluetooth_btstack_run_loop = {
10031045
.init = btstack_run_loop_base_init,
10041046
.add_data_source = btstack_run_loop_base_add_data_source,
@@ -1011,14 +1053,10 @@ static const btstack_run_loop_t bluetooth_btstack_run_loop = {
10111053
.execute = bluetooth_btstack_run_loop_execute,
10121054
.dump_timer = btstack_run_loop_base_dump_timer,
10131055
.get_time_ms = pbdrv_clock_get_ms,
1056+
.poll_data_sources_from_irq = pbdrv_bluetooth_btstack_run_loop_trigger,
10141057
};
10151058

1016-
static bool do_poll_handler;
10171059

1018-
void pbdrv_bluetooth_btstack_run_loop_trigger(void) {
1019-
do_poll_handler = true;
1020-
pbio_os_request_poll();
1021-
}
10221060

10231061
static pbio_os_process_t pbdrv_bluetooth_hci_process;
10241062

@@ -1028,9 +1066,71 @@ static pbio_os_process_t pbdrv_bluetooth_hci_process;
10281066
*/
10291067
static pbio_error_t pbdrv_bluetooth_hci_process_thread(pbio_os_state_t *state, void *context) {
10301068

1031-
if (do_poll_handler) {
1069+
#if PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX
1070+
int nfds = btstack_linked_list_count(&data_sources);
1071+
struct pollfd fds[nfds];
1072+
#endif
1073+
1074+
if (do_poll_handler || PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX) {
10321075
do_poll_handler = false;
10331076
btstack_run_loop_base_poll_data_sources();
1077+
1078+
btstack_data_source_t *ds, *next;
1079+
for (ds = (void *)data_sources; ds != NULL; ds = next) {
1080+
// cache pointer to next data_source to allow data source to remove itself
1081+
next = (void *)ds->item.next;
1082+
if (ds->flags & DATA_SOURCE_CALLBACK_POLL) {
1083+
ds->process(ds, DATA_SOURCE_CALLBACK_POLL);
1084+
}
1085+
}
1086+
1087+
btstack_data_source_t *ds, *next;
1088+
int i;
1089+
for (i = 0, ds = (void *)data_sources; ds != NULL; ++i, ds = next) {
1090+
// cache pointer to next data_source to allow data source to remove itself
1091+
next = (void *)ds->item.next;
1092+
if (ds->flags & DATA_SOURCE_CALLBACK_POLL) {
1093+
ds->process(ds, DATA_SOURCE_CALLBACK_POLL);
1094+
}
1095+
1096+
#if PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX
1097+
// In POSIX mode we must additionally identify data source FDs that
1098+
// are ready for reading or writing.
1099+
struct pollfd *pfd = &fds[i];
1100+
pfd->fd = ds->source.fd;
1101+
pfd->events = 0;
1102+
if (ds->flags & DATA_SOURCE_CALLBACK_READ) {
1103+
pfd->events |= POLLIN;
1104+
}
1105+
if (ds->flags & DATA_SOURCE_CALLBACK_WRITE) {
1106+
pfd->events |= POLLOUT;
1107+
}
1108+
#endif
1109+
}
1110+
1111+
#if PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX
1112+
int err = poll(fds, nfds, 0);
1113+
if (err < 0) {
1114+
DEBUG_PRINT("btstack: poll() returned %d, ignoring\n", errno);
1115+
} else if (err > 0) {
1116+
// Some fd was ready.
1117+
btstack_linked_list_iterator_t it;
1118+
int i;
1119+
for (i = 0, btstack_linked_list_iterator_init(&it, &data_sources);
1120+
btstack_linked_list_iterator_has_next(&it); ++i) {
1121+
btstack_data_source_t *ds = (void *)btstack_linked_list_iterator_next(&it);
1122+
struct pollfd *pfd = &fds[i];
1123+
if (pfd->revents & POLLIN) {
1124+
ds->process(ds, DATA_SOURCE_CALLBACK_READ);
1125+
} else if (pfd->revents & POLLOUT) {
1126+
ds->process(ds, DATA_SOURCE_CALLBACK_WRITE);
1127+
} else if (pfd->revents & POLLERR) {
1128+
DEBUG_PRINT("btstack: poll() error on fd %d\n", pfd->fd);
1129+
}
1130+
}
1131+
1132+
}
1133+
#endif
10341134
}
10351135

10361136
static pbio_os_timer_t btstack_timer = {
@@ -1065,9 +1165,12 @@ void pbdrv_bluetooth_init_hci(void) {
10651165
btstack_run_loop_init(&bluetooth_btstack_run_loop);
10661166

10671167
hci_init(pdata->transport_instance(), pdata->transport_config());
1068-
hci_set_chipset(pdata->chipset_instance());
1168+
if (pdata->chipset_instance != NULL) {
1169+
hci_set_chipset(pdata->chipset_instance());
1170+
}
10691171
hci_set_control(pdata->control_instance());
10701172

1173+
10711174
// REVISIT: do we need to call btstack_chipset_cc256x_set_power() or btstack_chipset_cc256x_set_power_vector()?
10721175

10731176
hci_event_callback_registration.callback = &packet_handler;

lib/pbio/drv/bluetooth/bluetooth_btstack.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,29 @@ typedef struct {
2323

2424
void pbdrv_bluetooth_btstack_run_loop_trigger(void);
2525

26+
typedef struct {
27+
// Only set on POSIX -- these data come from the USB device descriptor.
28+
uint16_t usb_vendor_id;
29+
uint16_t usb_product_id;
30+
31+
// Set on all platforms -- these data come from the
32+
// HCI_OPCODE_HCI_READ_LOCAL_VERSION_INFORMATION response.
33+
uint8_t hci_version;
34+
uint16_t hci_revision;
35+
uint8_t lmp_pal_version;
36+
uint16_t manufacturer;
37+
uint16_t lmp_pal_subversion;
38+
39+
} pbdrv_bluetooth_btstack_device_discriminator;
40+
2641
/**
2742
* Hook called when BTstack reads the local version information.
2843
*
2944
* This is called _after_ hci_set_chipset but _before_ the init script is sent
3045
* over the wire, so this can be used to dynamically select the init script.
3146
*/
32-
void pbdrv_bluetooth_btstack_set_chipset(uint16_t lmp_pal_subversion);
47+
void pbdrv_bluetooth_btstack_set_chipset(
48+
pbdrv_bluetooth_btstack_device_discriminator *device_info);
3349

3450
typedef struct {
3551
const hci_transport_t *(*transport_instance)(void);

lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,13 @@ static const hci_dump_t bluetooth_btstack_classic_hci_dump = {
6262
.log_packet = pbdrv_hci_dump_log_packet,
6363
.log_message = pbdrv_hci_dump_log_message,
6464
};
65+
6566
#else
6667
#define DEBUG_PRINT(...)
6768
#endif
6869

69-
void pbdrv_bluetooth_btstack_set_chipset(uint16_t lmp_pal_subversion) {
70-
const pbdrv_bluetooth_btstack_chipset_info_t *info = lmp_pal_subversion == cc2560_info.lmp_version ?
70+
void pbdrv_bluetooth_btstack_set_chipset(pbdrv_bluetooth_btstack_device_discriminator *device_info) {
71+
const pbdrv_bluetooth_btstack_chipset_info_t *info = device_info->lmp_pal_subversion == cc2560_info.lmp_version ?
7172
&cc2560_info : &cc2560a_info;
7273
btstack_chipset_cc256x_set_init_script((uint8_t *)info->init_script, info->init_script_size);
7374

0 commit comments

Comments
 (0)