Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,7 @@ Pipfile.lock
# Jupyter Notebook
######################
.ipynb_checkpoints

# BT Patches fetched by tools/collect_bt_patches.py
##########################################
.bt_firmware/
5 changes: 5 additions & 0 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,11 @@
"${workspaceFolder}/bricks/virtualhub",
"${workspaceFolder}/bricks/virtualhub/build",
"${workspaceFolder}/bricks/virtualhub/build-debug",
"${workspaceFolder}/lib/btstack/chipset/bcm",
"${workspaceFolder}/lib/btstack/chipset/realtek",
"${workspaceFolder}/lib/btstack/platform/libusb",
"${workspaceFolder}/lib/btstack/platform/posix",
"${workspaceFolder}/lib/btstack/src",
"${workspaceFolder}/lib/lego",
"${workspaceFolder}/lib/lwrb/src/include",
"${workspaceFolder}/lib/pbio",
Expand Down
48 changes: 48 additions & 0 deletions bricks/_common/common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,18 @@ endif
ifneq ($(strip $(PB_LIB_BTSTACK)),)
INC += -I$(PBTOP)/lib/btstack/chipset/cc256x
INC += -I$(PBTOP)/lib/btstack/src
ifeq ($(PBIO_PLATFORM),virtual_hub)
INC += -I$(PBTOP)/lib/btstack/platform/posix
INC += -I$(PBTOP)/lib/btstack/platform/embedded
INC += -I$(PBTOP)/lib/btstack/3rd-party/tinydir
INC += -I$(PBTOP)/lib/btstack/3rd-party/rijndael
INC += -I$(PBTOP)/lib/btstack/3rd-party/micro-ecc
INC += -I$(PBTOP)/lib/btstack/chipset/bcm
INC += -I$(PBTOP)/lib/btstack/chipset/intel
INC += -I$(PBTOP)/lib/btstack/chipset/realtek
INC += -I$(PBTOP)/lib/btstack/chipset/zephyr
INC += $(shell pkg-config libusb-1.0 --cflags)
endif
endif
ifeq ($(PB_LIB_LSM6DS3TR_C),1)
INC += -I$(PBTOP)/lib/lsm6ds3tr_c_STdC/driver
Expand Down Expand Up @@ -162,6 +174,9 @@ else ifeq ($(UNAME_S),Darwin)
LDFLAGS += -Wl,-map,$@.map -Wl,-dead_strip
endif
LIBS = -lm
ifeq ($(PB_LIB_BTSTACK),lowenergy)
LIBS += $(shell pkg-config libusb-1.0 --libs)
endif
else # end native, begin embedded
CROSS_COMPILE ?= arm-none-eabi-
ifeq ($(PB_MCU_FAMILY),STM32)
Expand Down Expand Up @@ -395,6 +410,37 @@ BTSTACK_SRC_C += $(addprefix lib/btstack/chipset/cc256x/,\
btstack_chipset_cc256x.c \
)

# libusb-specific BTStack sources for virtual_hub
ifeq ($(PBIO_PLATFORM),virtual_hub)
BTSTACK_SRC_C += $(addprefix lib/btstack/platform/libusb/,\
hci_transport_h2_libusb.c \
)
BTSTACK_SRC_C += $(addprefix lib/btstack/platform/posix/,\
hci_dump_posix_stdout.c \
)
BTSTACK_SRC_C += $(addprefix lib/btstack/src/ble/,\
le_device_db_tlv.c \
)
BTSTACK_SRC_C += $(addprefix lib/btstack/chipset/zephyr/,\
btstack_chipset_zephyr.c \
)
BTSTACK_SRC_C += $(addprefix lib/btstack/chipset/realtek/,\
btstack_chipset_realtek.c \
)
BTSTACK_SRC_C += $(addprefix lib/btstack/chipset/bcm/,\
btstack_chipset_bcm.c \
)
BTSTACK_SRC_C += $(addprefix lib/btstack/chipset/intel/,\
btstack_chipset_intel_firmware.c \
)
BTSTACK_SRC_C += $(addprefix lib/btstack/3rd-party/rijndael/,\
rijndael.c \
)
BTSTACK_SRC_C += $(addprefix lib/btstack/3rd-party/micro-ecc/,\
uECC.c \
)
endif

# STM32 HAL

COPT += -DUSE_FULL_LL_DRIVER
Expand Down Expand Up @@ -530,11 +576,13 @@ endif

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

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

ifeq ($(PB_LIB_STM32_HAL),1)
Expand Down
3 changes: 2 additions & 1 deletion bricks/_common/sources.mk
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,10 @@ PBIO_SRC_C = $(addprefix lib/pbio/,\
drv/block_device/block_device_test.c \
drv/block_device/block_device_w25qxx_stm32.c \
drv/bluetooth/bluetooth.c \
drv/bluetooth/bluetooth_btstack_stm32_hal.c \
drv/bluetooth/bluetooth_btstack.c \
drv/bluetooth/bluetooth_btstack_ev3.c \
drv/bluetooth/bluetooth_btstack_posix.c \
drv/bluetooth/bluetooth_btstack_stm32_hal.c \
drv/bluetooth/bluetooth_simulation.c \
drv/bluetooth/bluetooth_stm32_bluenrg.c \
drv/bluetooth/bluetooth_stm32_cc2640.c \
Expand Down
1 change: 1 addition & 0 deletions bricks/virtualhub/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ PB_MCU_FAMILY = native
PB_FROZEN_MODULES = 1
MICROPY_ROM_TEXT_COMPRESSION = 1
PB_LIB_UMM_MALLOC = 1
PB_LIB_BTSTACK = lowenergy

include ../_common/common.mk
126 changes: 116 additions & 10 deletions lib/pbio/drv/bluetooth/bluetooth_btstack.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,51 @@
#include "pybricks_service_server.h"
#endif // PBDRV_CONFIG_BLUETOOTH_BTSTACK_LE

#if PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX

#include <errno.h>
#include <poll.h>

#endif

#ifdef PBDRV_CONFIG_BLUETOOTH_BTSTACK_HUB_KIND
#define HUB_KIND PBDRV_CONFIG_BLUETOOTH_BTSTACK_HUB_KIND
#else
#error "PBDRV_CONFIG_BLUETOOTH_BTSTACK_HUB_KIND is required"
#endif

#ifndef PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX
#define PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX 0
#endif

// location of product variant in bootloader flash memory of Technic Large hubs
#if PBDRV_CONFIG_BLUETOOTH_BTSTACK_HUB_VARIANT_ADDR
#define HUB_VARIANT (*(const uint16_t *)PBDRV_CONFIG_BLUETOOTH_BTSTACK_HUB_VARIANT_ADDR)
#else
#define HUB_VARIANT 0x0000
#endif

#define DEBUG 0
#define DEBUG 1

#if DEBUG
#include <pbdrv/../../drv/uart/uart_debug_first_port.h>
#define DEBUG_PRINT pbdrv_uart_debug_printf
#include <pbdrv/../../drv/uart/uart_debug_first_port.h>
#define DEBUG_PRINT pbdrv_uart_debug_printf
static void pbdrv_hci_dump_reset(void) {
}
static void pbdrv_hci_dump_log_packet(uint8_t packet_type, uint8_t in, uint8_t *packet, uint16_t len) {
pbdrv_uart_debug_printf("HCI %s packet type: %02x, len: %u\n", in ? "in" : "out", packet_type, len);
}
static void pbdrv_hci_dump_log_message(int log_level, const char *format, va_list argptr) {
pbdrv_uart_debug_vprintf(format, argptr);
pbdrv_uart_debug_printf("\n");
}
static const hci_dump_t bluetooth_btstack_classic_hci_dump = {
.reset = pbdrv_hci_dump_reset,
.log_packet = pbdrv_hci_dump_log_packet,
.log_message = pbdrv_hci_dump_log_message,
};
#else
#define DEBUG_PRINT(...)
#endif
Expand Down Expand Up @@ -223,23 +250,39 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
pbdrv_bluetooth_peripheral_t *peri = &peripheral_singleton;
#endif // PBDRV_CONFIG_BLUETOOTH_BTSTACK_LE

static pbdrv_bluetooth_btstack_device_discriminator device_info;

switch (hci_event_packet_get_type(packet)) {
case HCI_EVENT_TRANSPORT_USB_INFO: {
// Store USB vendor and product IDs for later use
device_info.usb_vendor_id = hci_event_transport_usb_info_get_vendor_id(packet);
device_info.usb_product_id = hci_event_transport_usb_info_get_product_id(packet);
break;
}
case HCI_EVENT_COMMAND_COMPLETE: {
const uint8_t *rp = hci_event_command_complete_get_return_parameters(packet);
switch (hci_event_command_complete_get_command_opcode(packet)) {
case HCI_OPCODE_HCI_READ_LOCAL_VERSION_INFORMATION: {
uint16_t lmp_pal_subversion = pbio_get_uint16_le(&rp[7]);
pbdrv_bluetooth_btstack_set_chipset(lmp_pal_subversion);
device_info.hci_version = rp[0];
device_info.hci_revision = pbio_get_uint16_le(&rp[1]);
device_info.lmp_pal_version = rp[3];
device_info.manufacturer = pbio_get_uint16_le(&rp[4]);
device_info.lmp_pal_subversion = pbio_get_uint16_le(&rp[6]);
pbdrv_bluetooth_btstack_set_chipset(&device_info);

#if DEBUG
// Show version in ev3dev format.
uint16_t lmp_pal_subversion = device_info.lmp_pal_subversion;
uint16_t chip = (lmp_pal_subversion & 0x7C00) >> 10;
uint16_t min_ver = (lmp_pal_subversion & 0x007F);
uint16_t maj_ver = (lmp_pal_subversion & 0x0380) >> 7;
if (lmp_pal_subversion & 0x8000) {
maj_ver |= 0x0008;
}
DEBUG_PRINT("LMP %04x: TIInit_%d.%d.%d.bts\n", lmp_pal_subversion, chip, maj_ver, min_ver);
(void)maj_ver; // In lib/pbio/test, this variable appears unused even though it's not.
(void)min_ver;
(void)chip;
#endif
break;
}
Expand Down Expand Up @@ -999,6 +1042,13 @@ static void bluetooth_btstack_run_loop_execute(void) {
// not used
}

static bool do_poll_handler;

void pbdrv_bluetooth_btstack_run_loop_trigger(void) {
do_poll_handler = true;
pbio_os_request_poll();
}

static const btstack_run_loop_t bluetooth_btstack_run_loop = {
.init = btstack_run_loop_base_init,
.add_data_source = btstack_run_loop_base_add_data_source,
Expand All @@ -1011,14 +1061,10 @@ static const btstack_run_loop_t bluetooth_btstack_run_loop = {
.execute = bluetooth_btstack_run_loop_execute,
.dump_timer = btstack_run_loop_base_dump_timer,
.get_time_ms = pbdrv_clock_get_ms,
.poll_data_sources_from_irq = pbdrv_bluetooth_btstack_run_loop_trigger,
};

static bool do_poll_handler;

void pbdrv_bluetooth_btstack_run_loop_trigger(void) {
do_poll_handler = true;
pbio_os_request_poll();
}

static pbio_os_process_t pbdrv_bluetooth_hci_process;

Expand All @@ -1028,9 +1074,57 @@ static pbio_os_process_t pbdrv_bluetooth_hci_process;
*/
static pbio_error_t pbdrv_bluetooth_hci_process_thread(pbio_os_state_t *state, void *context) {

if (do_poll_handler) {
#if PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX
int nfds = btstack_linked_list_count(&btstack_run_loop_base_data_sources);
struct pollfd fds[nfds];
#endif

if (do_poll_handler || PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX) {
do_poll_handler = false;
btstack_run_loop_base_poll_data_sources();

#if PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX
btstack_linked_list_iterator_t it;
int i;
for (i = 0, btstack_linked_list_iterator_init(&it, &btstack_run_loop_base_data_sources);
btstack_linked_list_iterator_has_next(&it); ++i) {
// cache pointer to next data_source to allow data source to remove itself
btstack_data_source_t *ds = (void *)btstack_linked_list_iterator_next(&it);

// In POSIX mode we must additionally identify data source FDs that
// are ready for reading or writing.
struct pollfd *pfd = &fds[i];
pfd->fd = ds->source.fd;
pfd->events = 0;
if (ds->flags & DATA_SOURCE_CALLBACK_READ) {
pfd->events |= POLLIN;
}
if (ds->flags & DATA_SOURCE_CALLBACK_WRITE) {
pfd->events |= POLLOUT;
}

}

int err = poll(fds, nfds, 0);
if (err < 0) {
DEBUG_PRINT("btstack: poll() returned %d, ignoring\n", errno);
} else if (err > 0) {
// Some fd was ready.
for (i = 0, btstack_linked_list_iterator_init(&it, &btstack_run_loop_base_data_sources);
btstack_linked_list_iterator_has_next(&it); ++i) {
btstack_data_source_t *ds = (void *)btstack_linked_list_iterator_next(&it);
struct pollfd *pfd = &fds[i];
if (pfd->revents & POLLIN) {
ds->process(ds, DATA_SOURCE_CALLBACK_READ);
} else if (pfd->revents & POLLOUT) {
ds->process(ds, DATA_SOURCE_CALLBACK_WRITE);
} else if (pfd->revents & POLLERR) {
DEBUG_PRINT("btstack: poll() error on fd %d\n", pfd->fd);
}
}

}
#endif
}

static pbio_os_timer_t btstack_timer = {
Expand Down Expand Up @@ -1065,9 +1159,21 @@ void pbdrv_bluetooth_init_hci(void) {
btstack_run_loop_init(&bluetooth_btstack_run_loop);

hci_init(pdata->transport_instance(), pdata->transport_config());
hci_set_chipset(pdata->chipset_instance());

#if DEBUG
hci_dump_init(&bluetooth_btstack_classic_hci_dump);
hci_dump_enable_log_level(HCI_DUMP_LOG_LEVEL_INFO, true);
hci_dump_enable_log_level(HCI_DUMP_LOG_LEVEL_ERROR, true);
hci_dump_enable_log_level(HCI_DUMP_LOG_LEVEL_DEBUG, true);
hci_dump_enable_packet_log(true);
#endif

if (pdata->chipset_instance != NULL) {
hci_set_chipset(pdata->chipset_instance());
}
hci_set_control(pdata->control_instance());


// REVISIT: do we need to call btstack_chipset_cc256x_set_power() or btstack_chipset_cc256x_set_power_vector()?

hci_event_callback_registration.callback = &packet_handler;
Expand Down
18 changes: 17 additions & 1 deletion lib/pbio/drv/bluetooth/bluetooth_btstack.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,29 @@ typedef struct {

void pbdrv_bluetooth_btstack_run_loop_trigger(void);

typedef struct {
// Only set on POSIX -- these data come from the USB device descriptor.
uint16_t usb_vendor_id;
uint16_t usb_product_id;

// Set on all platforms -- these data come from the
// HCI_OPCODE_HCI_READ_LOCAL_VERSION_INFORMATION response.
uint8_t hci_version;
uint16_t hci_revision;
uint8_t lmp_pal_version;
uint16_t manufacturer;
uint16_t lmp_pal_subversion;

} pbdrv_bluetooth_btstack_device_discriminator;

/**
* Hook called when BTstack reads the local version information.
*
* This is called _after_ hci_set_chipset but _before_ the init script is sent
* over the wire, so this can be used to dynamically select the init script.
*/
void pbdrv_bluetooth_btstack_set_chipset(uint16_t lmp_pal_subversion);
void pbdrv_bluetooth_btstack_set_chipset(
pbdrv_bluetooth_btstack_device_discriminator *device_info);

typedef struct {
const hci_transport_t *(*transport_instance)(void);
Expand Down
5 changes: 3 additions & 2 deletions lib/pbio/drv/bluetooth/bluetooth_btstack_ev3.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,13 @@ static const hci_dump_t bluetooth_btstack_classic_hci_dump = {
.log_packet = pbdrv_hci_dump_log_packet,
.log_message = pbdrv_hci_dump_log_message,
};

#else
#define DEBUG_PRINT(...)
#endif

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

Expand Down
Loading
Loading