2929#include "pybricks_service_server.h"
3030#endif // PBDRV_CONFIG_BLUETOOTH_BTSTACK_LE
3131
32+ #if PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX
33+
34+ #include <errno.h>
35+ #include <poll.h>
36+
37+ #endif
38+
3239#ifdef PBDRV_CONFIG_BLUETOOTH_BTSTACK_HUB_KIND
3340#define HUB_KIND PBDRV_CONFIG_BLUETOOTH_BTSTACK_HUB_KIND
3441#else
3542#error "PBDRV_CONFIG_BLUETOOTH_BTSTACK_HUB_KIND is required"
3643#endif
3744
45+ #ifndef PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX
46+ #define PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX 0
47+ #endif
48+
3849// location of product variant in bootloader flash memory of Technic Large hubs
3950#if PBDRV_CONFIG_BLUETOOTH_BTSTACK_HUB_VARIANT_ADDR
4051#define HUB_VARIANT (*(const uint16_t *)PBDRV_CONFIG_BLUETOOTH_BTSTACK_HUB_VARIANT_ADDR)
@@ -222,23 +233,39 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
222233 pbdrv_bluetooth_peripheral_t * peri = & peripheral_singleton ;
223234 #endif // PBDRV_CONFIG_BLUETOOTH_BTSTACK_LE
224235
236+ static pbdrv_bluetooth_btstack_device_discriminator device_info ;
237+
225238 switch (hci_event_packet_get_type (packet )) {
239+ case HCI_EVENT_TRANSPORT_USB_INFO : {
240+ // Store USB vendor and product IDs for later use
241+ device_info .usb_vendor_id = hci_event_transport_usb_info_get_vendor_id (packet );
242+ device_info .usb_product_id = hci_event_transport_usb_info_get_product_id (packet );
243+ break ;
244+ }
226245 case HCI_EVENT_COMMAND_COMPLETE : {
227246 const uint8_t * rp = hci_event_command_complete_get_return_parameters (packet );
228247 switch (hci_event_command_complete_get_command_opcode (packet )) {
229248 case HCI_OPCODE_HCI_READ_LOCAL_VERSION_INFORMATION : {
230- uint16_t lmp_pal_subversion = pbio_get_uint16_le (& rp [7 ]);
231- pbdrv_bluetooth_btstack_set_chipset (lmp_pal_subversion );
249+ device_info .hci_version = rp [0 ];
250+ device_info .hci_revision = pbio_get_uint16_le (& rp [1 ]);
251+ device_info .lmp_pal_version = rp [3 ];
252+ device_info .manufacturer = pbio_get_uint16_le (& rp [4 ]);
253+ device_info .lmp_pal_subversion = pbio_get_uint16_le (& rp [6 ]);
254+ pbdrv_bluetooth_btstack_set_chipset (& device_info );
232255
233256 #if DEBUG
234257 // Show version in ev3dev format.
258+ uint16_t lmp_pal_subversion = device_info .lmp_pal_subversion ;
235259 uint16_t chip = (lmp_pal_subversion & 0x7C00 ) >> 10 ;
236260 uint16_t min_ver = (lmp_pal_subversion & 0x007F );
237261 uint16_t maj_ver = (lmp_pal_subversion & 0x0380 ) >> 7 ;
238262 if (lmp_pal_subversion & 0x8000 ) {
239263 maj_ver |= 0x0008 ;
240264 }
241265 DEBUG_PRINT ("LMP %04x: TIInit_%d.%d.%d.bts\n" , lmp_pal_subversion , chip , maj_ver , min_ver );
266+ (void )maj_ver ; // In lib/pbio/test, this variable appears unused even though it's not.
267+ (void )min_ver ;
268+ (void )chip ;
242269 #endif
243270 break ;
244271 }
@@ -1054,6 +1081,13 @@ static void bluetooth_btstack_run_loop_dump_timer(void) {
10541081 // not used
10551082}
10561083
1084+ static bool do_poll_handler ;
1085+
1086+ void pbdrv_bluetooth_btstack_run_loop_trigger (void ) {
1087+ do_poll_handler = true;
1088+ pbio_os_request_poll ();
1089+ }
1090+
10571091static const btstack_run_loop_t bluetooth_btstack_run_loop = {
10581092 .init = bluetooth_btstack_run_loop_init ,
10591093 .add_data_source = bluetooth_btstack_run_loop_add_data_source ,
@@ -1066,14 +1100,10 @@ static const btstack_run_loop_t bluetooth_btstack_run_loop = {
10661100 .execute = bluetooth_btstack_run_loop_execute ,
10671101 .dump_timer = bluetooth_btstack_run_loop_dump_timer ,
10681102 .get_time_ms = pbdrv_clock_get_ms ,
1103+ .poll_data_sources_from_irq = pbdrv_bluetooth_btstack_run_loop_trigger ,
10691104};
10701105
1071- static bool do_poll_handler ;
10721106
1073- void pbdrv_bluetooth_btstack_run_loop_trigger (void ) {
1074- do_poll_handler = true;
1075- pbio_os_request_poll ();
1076- }
10771107
10781108static pbio_os_process_t pbdrv_bluetooth_hci_process ;
10791109
@@ -1083,17 +1113,61 @@ static pbio_os_process_t pbdrv_bluetooth_hci_process;
10831113 */
10841114static pbio_error_t pbdrv_bluetooth_hci_process_thread (pbio_os_state_t * state , void * context ) {
10851115
1086- if (do_poll_handler ) {
1116+ #if PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX
1117+ int nfds = btstack_linked_list_count (& data_sources );
1118+ struct pollfd fds [nfds ];
1119+ #endif
1120+
1121+ if (do_poll_handler || PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX ) {
10871122 do_poll_handler = false;
10881123
10891124 btstack_data_source_t * ds , * next ;
1090- for (ds = (void * )data_sources ; ds != NULL ; ds = next ) {
1125+ int i ;
1126+ for (i = 0 , ds = (void * )data_sources ; ds != NULL ; ++ i , ds = next ) {
10911127 // cache pointer to next data_source to allow data source to remove itself
10921128 next = (void * )ds -> item .next ;
10931129 if (ds -> flags & DATA_SOURCE_CALLBACK_POLL ) {
10941130 ds -> process (ds , DATA_SOURCE_CALLBACK_POLL );
10951131 }
1132+
1133+ #if PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX
1134+ // In POSIX mode we must additionally identify data source FDs that
1135+ // are ready for reading or writing.
1136+ struct pollfd * pfd = & fds [i ];
1137+ pfd -> fd = ds -> source .fd ;
1138+ pfd -> events = 0 ;
1139+ if (ds -> flags & DATA_SOURCE_CALLBACK_READ ) {
1140+ pfd -> events |= POLLIN ;
1141+ }
1142+ if (ds -> flags & DATA_SOURCE_CALLBACK_WRITE ) {
1143+ pfd -> events |= POLLOUT ;
1144+ }
1145+ #endif
1146+ }
1147+
1148+ #if PBDRV_CONFIG_BLUETOOTH_BTSTACK_POSIX
1149+ int err = poll (fds , nfds , 0 );
1150+ if (err < 0 ) {
1151+ DEBUG_PRINT ("btstack: poll() returned %d, ignoring\n" , errno );
1152+ } else if (err > 0 ) {
1153+ // Some fd was ready.
1154+ btstack_linked_list_iterator_t it ;
1155+ int i ;
1156+ for (i = 0 , btstack_linked_list_iterator_init (& it , & data_sources );
1157+ btstack_linked_list_iterator_has_next (& it ); ++ i ) {
1158+ btstack_data_source_t * ds = (void * )btstack_linked_list_iterator_next (& it );
1159+ struct pollfd * pfd = & fds [i ];
1160+ if (pfd -> revents & POLLIN ) {
1161+ ds -> process (ds , DATA_SOURCE_CALLBACK_READ );
1162+ } else if (pfd -> revents & POLLOUT ) {
1163+ ds -> process (ds , DATA_SOURCE_CALLBACK_WRITE );
1164+ } else if (pfd -> revents & POLLERR ) {
1165+ DEBUG_PRINT ("btstack: poll() error on fd %d\n" , pfd -> fd );
1166+ }
1167+ }
1168+
10961169 }
1170+ #endif
10971171 }
10981172
10991173 static pbio_os_timer_t btstack_timer = {
@@ -1139,9 +1213,12 @@ void pbdrv_bluetooth_init_hci(void) {
11391213 btstack_run_loop_init (& bluetooth_btstack_run_loop );
11401214
11411215 hci_init (pdata -> transport_instance (), pdata -> transport_config ());
1142- hci_set_chipset (pdata -> chipset_instance ());
1216+ if (pdata -> chipset_instance != NULL ) {
1217+ hci_set_chipset (pdata -> chipset_instance ());
1218+ }
11431219 hci_set_control (pdata -> control_instance ());
11441220
1221+
11451222 // REVISIT: do we need to call btstack_chipset_cc256x_set_power() or btstack_chipset_cc256x_set_power_vector()?
11461223
11471224 hci_event_callback_registration .callback = & packet_handler ;
0 commit comments