diff --git a/3rd-party/bluedroid/encoder/include/sbc_encoder.h b/3rd-party/bluedroid/encoder/include/sbc_encoder.h index 19cc6ee68..20cbd9ab5 100644 --- a/3rd-party/bluedroid/encoder/include/sbc_encoder.h +++ b/3rd-party/bluedroid/encoder/include/sbc_encoder.h @@ -40,6 +40,11 @@ #define TRUE (!FALSE) #endif +/* BK4BTSTACK_CHANGE START */ +#define SBC_NO_PCM_CPY_OPTION TRUE +/* BK4BTSTACK_CHANGE END */ + + #define SBC_MAX_NUM_OF_SUBBANDS 8 #define SBC_MAX_NUM_OF_CHANNELS 2 #define SBC_MAX_NUM_OF_BLOCKS 16 diff --git a/README.md b/README.md index 676b67992..1a461e94f 100644 --- a/README.md +++ b/README.md @@ -77,14 +77,14 @@ Status | Platform ## Supported Chipsets Chipsets | Status -------------- | ------ -TI CC256x, WL183x | complete incl. eHCIll support and SCO-over-HCI (chipset/cc256x) -CSR 8x10, 8x11 | H4 only (chipset-csr), SCO-over-HCI missing (chipset/csr) +TI CC256x, WL183x | H4 incl. eHCIll support and SCO-over-HCI (chipset/cc256x) +CSR 8x10, 8x11 | H4 + H5 supported, SCO-over-HCI missing (chipset/csr) STM STLC2500D | working, no support for custom deep sleep management (chipset/stlc2500d) TC35661 | working, BLE patches missing (chipset/tc3566x) EM 9301 (LE-only) | working, used on Arduino Shield (chipset/em9301) CSR USB Dongles | complete, incl. SCO-over-HCI -Broadcom USB Dongles | complete, SCO-over-HCI not missing -Broadcom BCM43438 | complete. UART baudrate limited to 3 mbps, SCO-over-HCI not missing +Broadcom USB Dongles | complete, SCO-over-HCI missing +Broadcom BCM43438 | complete. UART baudrate limited to 3 mbps, SCO-over-HCI missing ## Source Tree Overview Path | Description diff --git a/doc/manual/update_apis.py b/doc/manual/update_apis.py index 1d0a4d2d3..6c134e1c4 100755 --- a/doc/manual/update_apis.py +++ b/doc/manual/update_apis.py @@ -8,7 +8,6 @@ class State: # [file_name, api_title, api_label] apis = [ - ["src/ble/ad_parser.h", "BLE Advertisements Parser", "advParser"], ["src/ble/ancs_client.h", "BLE ANCS Client", "ancsClient"], ["src/ble/att_db_util.h", "BLE ATT Database", "attDb"], ["src/ble/att_server.h", "BLE ATT Server", "attServer"], @@ -29,6 +28,7 @@ apis = [ ["src/classic/sdp_server.h", "SDP Server", "sdpSrv"], ["src/classic/sdp_util.h","SDP Utils", "sdpUtil"], + ["src/ad_parser.h", "BLE Advertisements Parser", "advParser"], ["src/btstack_chipset.h","BTstack Chipset","btMemory"], ["src/btstack_control.h","BTstack Hardware Control","btControl"], ["src/btstack_event.h","HCI Event Getter","btEvent"], diff --git a/example/Makefile.inc b/example/Makefile.inc index f737b86b5..a684fd6e4 100644 --- a/example/Makefile.inc +++ b/example/Makefile.inc @@ -4,21 +4,18 @@ VPATH += ${BTSTACK_ROOT}/src/ble VPATH += ${BTSTACK_ROOT}/src/classic VPATH += ${BTSTACK_ROOT}/example VPATH += ${BTSTACK_ROOT}/3rd-party/mbedtls/library -VPATH += ${SBC_DECODER_ROOT}/srce -VPATH += ${SBC_ENCODER_ROOT}/srce +VPATH += ${BTSTACK_ROOT}/3rd-party/bluedroid/decoder/srce +VPATH += ${BTSTACK_ROOT}/3rd-party/bluedroid/encoder//srce CFLAGS += -I. CFLAGS += -I${BTSTACK_ROOT}/src/ble CFLAGS += -I${BTSTACK_ROOT}/src/classic CFLAGS += -I${BTSTACK_ROOT}/src CFLAGS += -I${BTSTACK_ROOT}/3rd-party/mbedtls/include -CFLAGS += -I${BTSTACK_ROOT}/test/security_manager +CFLAGS += -I${BTSTACK_ROOT}/3rd-party/bluedroid/decoder/include +CFLAGS += -I${BTSTACK_ROOT}/3rd-party/bluedroid/encoder/include -# for SBC -SBC_DECODER_ROOT = ${BTSTACK_ROOT}/3rd-party/bluedroid/decoder -SBC_ENCODER_ROOT = ${BTSTACK_ROOT}/3rd-party/bluedroid/encoder -CFLAGS += -I${SBC_DECODER_ROOT}/include -D OI_DEBUG # -D PRINT_SAMPLES -D PRINT_SCALEFACTORS -CFLAGS += -I${SBC_ENCODER_ROOT}/include -D SBC_NO_PCM_CPY_OPTION +CFLAGS += -I${BTSTACK_ROOT}/test/security_manager # for CVSD/SBC PLC LDFLAGS += -lm @@ -72,9 +69,9 @@ MBEDTLS = \ memory_buffer_alloc.c \ platform.c \ -# -include ${SBC_DECODER_ROOT}/Makefile.inc -include ${SBC_ENCODER_ROOT}/Makefile.inc +# List of files for Bluedroid SBC codec +include ${BTSTACK_ROOT}/3rd-party/bluedroid/decoder/Makefile.inc +include ${BTSTACK_ROOT}/3rd-party/bluedroid/encoder/Makefile.inc SBC_DECODER += \ ${BTSTACK_ROOT}/src/classic/btstack_sbc_plc.c \ @@ -170,7 +167,7 @@ sm_pairing_peripheral: sm_pairing_peripheral.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_O ${CC} $(filter-out sm_pairing_peripheral.h,$^) ${CFLAGS} ${LDFLAGS} -o $@ sm_pairing_central: ${CORE_OBJ} ${COMMON_OBJ} ${SM_REAL_OBJ} ad_parser.o sm_pairing_central.o - ${CC} ${CFLAGS} ${LDFLAGS} $^ -o $@ + ${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@ le_streamer: le_streamer.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} ${SM_REAL_OBJ} le_streamer.c ${CC} $(filter-out le_streamer.h,$^) ${CFLAGS} ${LDFLAGS} -o $@ @@ -187,7 +184,7 @@ spp_streamer: ${CORE_OBJ} ${COMMON_OBJ} ${SDP_CLIENT} spp_streamer.c gap_dedicated_bonding: ${CORE_OBJ} ${COMMON_OBJ} gap_dedicated_bonding.c ${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@ -gap_inquiry: ${CORE_OBJ} ${COMMON_OBJ} gap_inquiry.c +gap_inquiry: ${CORE_OBJ} ${COMMON_OBJ} ad_parser.o gap_inquiry.c ${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@ panu_demo: ${CORE_OBJ} ${COMMON_OBJ} ${SDP_CLIENT} panu_demo.c diff --git a/example/gap_inquiry.c b/example/gap_inquiry.c index 0071c9bbf..86ff85e77 100644 --- a/example/gap_inquiry.c +++ b/example/gap_inquiry.c @@ -170,6 +170,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe switch(event){ case HCI_EVENT_INQUIRY_RESULT: case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI: + case HCI_EVENT_EXTENDED_INQUIRY_RESPONSE: numResponses = hci_event_inquiry_result_get_num_responses(packet); for (i=0; i= HCI_EVENT_INQUIRY_RESULT_WITH_RSSI){ + printf(", rssi 0x%02x: ", devices[deviceCount].rssi); + } + if (devices[deviceCount].state == REMOTE_NAME_FETCHED){ + printf(", name '%s'", name_buffer); + } + printf("\n"); deviceCount++; } break; @@ -246,6 +276,9 @@ int btstack_main(int argc, const char * argv[]) { hci_event_callback_registration.callback = &packet_handler; hci_add_event_handler(&hci_event_callback_registration); + // enabled EIR + hci_set_inquiry_mode(INQUIRY_MODE_RSSI_AND_EIR); + // turn on! hci_power_control(HCI_POWER_ON); diff --git a/example/hfp_ag_demo.c b/example/hfp_ag_demo.c index d95c86704..cd1e61b0a 100644 --- a/example/hfp_ag_demo.c +++ b/example/hfp_ag_demo.c @@ -81,6 +81,7 @@ static uint8_t negotiated_codec = HFP_CODEC_CVSD; static hci_con_handle_t acl_handle = -1; static hci_con_handle_t sco_handle; static int memory_1_enabled = 1; +static btstack_packet_callback_registration_t hci_event_callback_registration; static int ag_indicators_nr = 7; static hfp_ag_indicator_t ag_indicators[] = { @@ -710,6 +711,11 @@ int btstack_main(int argc, const char * argv[]){ sco_demo_init(); + // register for HCI events + hci_event_callback_registration.callback = &packet_handler; + hci_add_event_handler(&hci_event_callback_registration); + hci_register_sco_packet_handler(&packet_handler); + gap_discoverable_control(1); // L2CAP diff --git a/example/hfp_hf_demo.c b/example/hfp_hf_demo.c index 682834acc..44bc24b8e 100644 --- a/example/hfp_hf_demo.c +++ b/example/hfp_hf_demo.c @@ -80,6 +80,7 @@ static hci_con_handle_t sco_handle; static uint8_t codecs[] = {HFP_CODEC_CVSD, HFP_CODEC_MSBC}; static uint16_t indicators[1] = {0x01}; static uint8_t negotiated_codec = HFP_CODEC_CVSD; +static btstack_packet_callback_registration_t hci_event_callback_registration; char cmd; @@ -561,14 +562,19 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * even /* LISTING_START(MainConfiguration): Setup HFP Hands-Free unit */ int btstack_main(int argc, const char * argv[]); int btstack_main(int argc, const char * argv[]){ - sco_demo_init(); - gap_discoverable_control(1); - // HFP AG address is hardcoded, please change it + sco_demo_init(); + + // register for HCI events + hci_event_callback_registration.callback = &packet_handler; + hci_add_event_handler(&hci_event_callback_registration); + hci_register_sco_packet_handler(&packet_handler); + + gap_discoverable_control(1); + gap_set_class_of_device(0x200408); + // init L2CAP l2cap_init(); - rfcomm_init(); - sdp_init(); uint16_t hf_supported_features = (1< - ../../../src/ble/ad_parser.h + ../../../src/ad_parser.h ../../../src/ble/ancs_client.h ../../../src/ble/att_db.h ../../../src/ble/att_dispatch.h @@ -108,7 +108,7 @@ - ../../../src/ble/ad_parser.c + ../../../src/ad_parser.c ../../../src/ble/att_db.c ../../../src/ble/att_dispatch.c ../../../src/ble/att_server.c diff --git a/port/wiced/wiced.mk b/port/wiced/wiced.mk index 290cb291b..b36d41dd7 100644 --- a/port/wiced/wiced.mk +++ b/port/wiced/wiced.mk @@ -12,7 +12,7 @@ GLOBAL_INCLUDES += . ../../src ../../platform/embedded ../../chipset/bcm ../../. # core BTstack sources $(NAME)_SOURCES += \ - ../../src/ble/ad_parser.c \ + ../../src/ad_parser.c \ ../../src/ble/att_db.c \ ../../src/ble/att_dispatch.c \ ../../src/ble/att_server.c \ diff --git a/src/ble/ad_parser.c b/src/ad_parser.c similarity index 99% rename from src/ble/ad_parser.c rename to src/ad_parser.c index 6a2c9a824..f18d6eea4 100644 --- a/src/ble/ad_parser.c +++ b/src/ad_parser.c @@ -52,7 +52,7 @@ #include "hci_cmd.h" #include "hci.h" -#include "ble/ad_parser.h" +#include "ad_parser.h" typedef enum { IncompleteList16 = 0x02, diff --git a/src/ble/ad_parser.h b/src/ad_parser.h similarity index 100% rename from src/ble/ad_parser.h rename to src/ad_parser.h diff --git a/src/ble/gatt_client.c b/src/ble/gatt_client.c index b1009b070..c8d76eb29 100644 --- a/src/ble/gatt_client.c +++ b/src/ble/gatt_client.c @@ -43,7 +43,7 @@ #include "btstack_config.h" #include "att_dispatch.h" -#include "ble/ad_parser.h" +#include "ad_parser.h" #include "ble/att_db.h" #include "ble/core.h" #include "ble/gatt_client.h" diff --git a/src/ble/sm.c b/src/ble/sm.c index 1e75dffeb..4c17116d0 100644 --- a/src/ble/sm.c +++ b/src/ble/sm.c @@ -1908,6 +1908,35 @@ static void sm_run(void){ } } + // handle basic actions that don't requires the full context + hci_connections_get_iterator(&it); + while(!sm_active_connection && btstack_linked_list_iterator_has_next(&it)){ + hci_connection_t * hci_connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it); + sm_connection_t * sm_connection = &hci_connection->sm_connection; + switch(sm_connection->sm_engine_state){ + // responder side + case SM_RESPONDER_PH0_SEND_LTK_REQUESTED_NEGATIVE_REPLY: + sm_connection->sm_engine_state = SM_RESPONDER_IDLE; + hci_send_cmd(&hci_le_long_term_key_negative_reply, sm_connection->sm_handle); + return; + +#ifdef ENABLE_LE_SECURE_CONNECTIONS + case SM_SC_RECEIVED_LTK_REQUEST: + switch (sm_connection->sm_irk_lookup_state){ + case IRK_LOOKUP_FAILED: + log_info("LTK Request: ediv & random are empty, but no stored LTK (IRK Lookup Failed)"); + sm_connection->sm_engine_state = SM_RESPONDER_IDLE; + hci_send_cmd(&hci_le_long_term_key_negative_reply, sm_connection->sm_handle); + return; + default: + break; + } + break; +#endif + default: + break; + } + } // // active connection handling @@ -1976,6 +2005,7 @@ static void sm_run(void){ switch (sm_connection->sm_irk_lookup_state){ case IRK_LOOKUP_SUCCEEDED: // assuming Secure Connection, we have a stored LTK and the EDIV/RAND are null + // start using context by loading security info sm_reset_setup(); sm_load_security_info(sm_connection); if (setup->sm_peer_ediv == 0 && sm_is_null_random(setup->sm_peer_rand) && !sm_is_null_key(setup->sm_peer_ltk)){ @@ -1984,16 +2014,10 @@ static void sm_run(void){ break; } log_info("LTK Request: ediv & random are empty, but no stored LTK (IRK Lookup Succeeded)"); - sm_connection->sm_engine_state = SM_RESPONDER_PH0_SEND_LTK_REQUESTED_NEGATIVE_REPLY; + sm_connection->sm_engine_state = SM_RESPONDER_IDLE; + hci_send_cmd(&hci_le_long_term_key_negative_reply, sm_connection->sm_handle); // don't lock setup context yet - done = 0; - break; - case IRK_LOOKUP_FAILED: - log_info("LTK Request: ediv & random are empty, but no stored LTK (IRK Lookup Failed)"); - sm_connection->sm_engine_state = SM_RESPONDER_PH0_SEND_LTK_REQUESTED_NEGATIVE_REPLY; - // don't lock setup context yet - done = 0; - break; + return; default: // just wait until IRK lookup is completed // don't lock setup context yet @@ -2042,7 +2066,6 @@ static void sm_run(void){ log_info("sm_run: state %u", connection->sm_engine_state); - // responding state switch (connection->sm_engine_state){ // general @@ -2056,6 +2079,7 @@ static void sm_run(void){ break; } + // responding state #ifdef ENABLE_LE_SECURE_CONNECTIONS case SM_SC_W2_GET_RANDOM_A: sm_random_start(connection); @@ -2115,8 +2139,8 @@ static void sm_run(void){ connection->sm_engine_state = SM_SC_W4_CALCULATE_H6_BR_EDR_LINK_KEY; h6_calculate_br_edr_link_key(connection); break; - #endif + // initiator side case SM_INITIATOR_PH0_SEND_START_ENCRYPTION: { sm_key_t peer_ltk_flipped; @@ -2136,14 +2160,8 @@ static void sm_run(void){ sm_timeout_reset(connection); break; - // responder side - case SM_RESPONDER_PH0_SEND_LTK_REQUESTED_NEGATIVE_REPLY: - connection->sm_engine_state = SM_RESPONDER_IDLE; - hci_send_cmd(&hci_le_long_term_key_negative_reply, connection->sm_handle); - sm_done_for_handle(connection->sm_handle); - return; - #ifdef ENABLE_LE_SECURE_CONNECTIONS + case SM_SC_SEND_PUBLIC_KEY_COMMAND: { uint8_t buffer[65]; buffer[0] = SM_CODE_PAIRING_PUBLIC_KEY; diff --git a/src/bluetooth.h b/src/bluetooth.h index bbf8bd455..8f7423e2c 100644 --- a/src/bluetooth.h +++ b/src/bluetooth.h @@ -95,6 +95,15 @@ typedef enum { AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256, // SSP Passkey, Number confirm, OOB } link_key_type_t; +/** + * @brief Inquiry modes + */ +typedef enum { + INQUIRY_MODE_STANDARD = 0, + INQUIRY_MODE_RSSI, + INQUIRY_MODE_RSSI_AND_EIR, +} inquiry_mode_t; + /** * HCI Transport */ @@ -267,7 +276,6 @@ typedef enum { * @param status */ #define HCI_EVENT_INQUIRY_COMPLETE 0x01 -// no format yet, can contain multiple results /** * @format 1B11132 @@ -337,8 +345,11 @@ typedef enum { * @param key_flag */ #define HCI_EVENT_MASTER_LINK_KEY_COMPLETE 0x0A + #define HCI_EVENT_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE 0x0B + #define HCI_EVENT_READ_REMOTE_VERSION_INFORMATION_COMPLETE 0x0C + #define HCI_EVENT_QOS_SETUP_COMPLETE 0x0D /** @@ -362,7 +373,7 @@ typedef enum { */ #define HCI_EVENT_HARDWARE_ERROR 0x10 -#define HCI_EVENT_FLUSH_OCCURED 0x11 +#define HCI_EVENT_FLUSH_OCCURRED 0x11 /** * @format 1B1 @@ -480,9 +491,31 @@ typedef enum { #define HCI_EVENT_IO_CAPABILITY_REQUEST 0x31 #define HCI_EVENT_IO_CAPABILITY_RESPONSE 0x32 + +/** + * @format B4 + * @param bd_addr + * @param numeric_value + */ #define HCI_EVENT_USER_CONFIRMATION_REQUEST 0x33 + +/** + * @format B + * @param bd_addr + */ #define HCI_EVENT_USER_PASSKEY_REQUEST 0x34 + +/** + * @format B + * @param bd_addr + */ #define HCI_EVENT_REMOTE_OOB_DATA_REQUEST 0x35 + +/** + * @format 1B + * @param status + * @param bd_addr + */ #define HCI_EVENT_SIMPLE_PAIRING_COMPLETE 0x36 #define HCI_EVENT_LE_META 0x3E diff --git a/src/btstack.h b/src/btstack.h index 3b5675d57..f325a71ed 100644 --- a/src/btstack.h +++ b/src/btstack.h @@ -47,7 +47,7 @@ #include "btstack_config.h" #include "bluetooth.h" -#include "btstack.h" +#include "ad_parser.h" #include "btstack_control.h" #include "btstack_debug.h" #include "btstack_event.h" @@ -66,7 +66,6 @@ #include "l2cap_signaling.h" #ifdef ENABLE_BLE -#include "ble/ad_parser.h" #include "ble/ancs_client.h" #include "ble/att_db.h" #include "ble/att_db_util.h" diff --git a/src/btstack_event.h b/src/btstack_event.h index b8eefc5d2..018689650 100644 --- a/src/btstack_event.h +++ b/src/btstack_event.h @@ -864,6 +864,64 @@ static inline hci_con_handle_t hci_event_encryption_key_refresh_complete_get_han return little_endian_read_16(event, 3); } +/** + * @brief Get field bd_addr from event HCI_EVENT_USER_CONFIRMATION_REQUEST + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ +static inline void hci_event_user_confirmation_request_get_bd_addr(const uint8_t * event, bd_addr_t bd_addr){ + reverse_bd_addr(&event[2], bd_addr); +} +/** + * @brief Get field numeric_value from event HCI_EVENT_USER_CONFIRMATION_REQUEST + * @param event packet + * @return numeric_value + * @note: btstack_type 4 + */ +static inline uint32_t hci_event_user_confirmation_request_get_numeric_value(const uint8_t * event){ + return little_endian_read_32(event, 8); +} + +/** + * @brief Get field bd_addr from event HCI_EVENT_USER_PASSKEY_REQUEST + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ +static inline void hci_event_user_passkey_request_get_bd_addr(const uint8_t * event, bd_addr_t bd_addr){ + reverse_bd_addr(&event[2], bd_addr); +} + +/** + * @brief Get field bd_addr from event HCI_EVENT_REMOTE_OOB_DATA_REQUEST + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ +static inline void hci_event_remote_oob_data_request_get_bd_addr(const uint8_t * event, bd_addr_t bd_addr){ + reverse_bd_addr(&event[2], bd_addr); +} + +/** + * @brief Get field status from event HCI_EVENT_SIMPLE_PAIRING_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ +static inline uint8_t hci_event_simple_pairing_complete_get_status(const uint8_t * event){ + return event[2]; +} +/** + * @brief Get field bd_addr from event HCI_EVENT_SIMPLE_PAIRING_COMPLETE + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ +static inline void hci_event_simple_pairing_complete_get_bd_addr(const uint8_t * event, bd_addr_t bd_addr){ + reverse_bd_addr(&event[3], bd_addr); +} + /** * @brief Get field state from event BTSTACK_EVENT_STATE * @param event packet diff --git a/src/classic/rfcomm.c b/src/classic/rfcomm.c index 59b9a2746..55cb602c4 100644 --- a/src/classic/rfcomm.c +++ b/src/classic/rfcomm.c @@ -844,42 +844,40 @@ static void rfcomm_multiplexer_opened(rfcomm_multiplexer_t *multiplexer){ static void rfcomm_handle_can_send_now(uint16_t l2cap_cid){ - btstack_linked_list_iterator_t it; + log_debug("rfcomm_handle_can_send_now enter: %u", l2cap_cid); - // find multiplexer ready for this cid + btstack_linked_list_iterator_t it; + int token_consumed = 0; + + // forward token to multiplexer btstack_linked_list_iterator_init(&it, &rfcomm_multiplexers); - while (btstack_linked_list_iterator_has_next(&it)){ + while (!token_consumed && btstack_linked_list_iterator_has_next(&it)){ rfcomm_multiplexer_t * multiplexer = (rfcomm_multiplexer_t *) btstack_linked_list_iterator_next(&it); if (multiplexer->l2cap_cid != l2cap_cid) continue; if (rfcomm_multiplexer_ready_to_send(multiplexer)){ + log_debug("rfcomm_handle_can_send_now enter: multiplexer token"); + token_consumed = 1; rfcomm_multiplexer_state_machine(multiplexer, MULT_EV_READY_TO_SEND); - // more to send? - if (rfcomm_multiplexer_ready_to_send(multiplexer)){ - l2cap_request_can_send_now_event(l2cap_cid); - } - return; } } - // find channels ready for this cid + // forward token to channel state machine btstack_linked_list_iterator_init(&it, &rfcomm_channels); - while (btstack_linked_list_iterator_has_next(&it)){ + while (!token_consumed && btstack_linked_list_iterator_has_next(&it)){ rfcomm_channel_t * channel = (rfcomm_channel_t *) btstack_linked_list_iterator_next(&it); if (channel->multiplexer->l2cap_cid != l2cap_cid) continue; // channel state machine if (rfcomm_channel_ready_to_send(channel)){ + log_debug("rfcomm_handle_can_send_now enter: channel token"); + token_consumed = 1; const rfcomm_channel_event_t event = { CH_EVT_READY_TO_SEND }; rfcomm_channel_state_machine_with_channel(channel, &event); - if (rfcomm_channel_ready_to_send(channel)){ - l2cap_request_can_send_now_event(l2cap_cid); - } - return; } } - // inform clients if waiting + // forward token to client btstack_linked_list_iterator_init(&it, &rfcomm_channels); - while (btstack_linked_list_iterator_has_next(&it)){ + while (!token_consumed && btstack_linked_list_iterator_has_next(&it)){ rfcomm_channel_t * channel = (rfcomm_channel_t *) btstack_linked_list_iterator_next(&it); if (channel->multiplexer->l2cap_cid != l2cap_cid) continue; // client waiting for can send now @@ -887,17 +885,18 @@ static void rfcomm_handle_can_send_now(uint16_t l2cap_cid){ if (!channel->credits_outgoing) continue; if ((channel->multiplexer->fcon & 1) == 0) continue; + log_debug("rfcomm_handle_can_send_now enter: client token"); + token_consumed = 1; channel->waiting_for_can_send_now = 0; rfcomm_emit_can_send_now(channel); - - // note: if client wants to send more, it will call rfcomm_request_can_send_now which in turn will - // call l2cap_request_can_send_now -> nothing to do for us here. - - // check if we can still send - if (!l2cap_can_send_packet_now(l2cap_cid)) { - return; - } } + + // if token was consumed, request another one + if (token_consumed) { + l2cap_request_can_send_now_event(l2cap_cid); + } + + log_debug("rfcomm_handle_can_send_now exit"); } static void rfcomm_multiplexer_set_state_and_request_can_send_now_event(rfcomm_multiplexer_t * multiplexer, RFCOMM_MULTIPLEXER_STATE state){ @@ -1232,8 +1231,8 @@ static void rfcomm_multiplexer_state_machine(rfcomm_multiplexer_t * multiplexer, // MARK: RFCOMM CHANNEL static void rfcomm_channel_send_credits(rfcomm_channel_t *channel, uint8_t credits){ - rfcomm_send_uih_credits(channel->multiplexer, channel->dlci, credits); channel->credits_incoming += credits; + rfcomm_send_uih_credits(channel->multiplexer, channel->dlci, credits); } static int rfcomm_channel_can_send(rfcomm_channel_t * channel){ diff --git a/src/gap.h b/src/gap.h index 00313dc3b..0b627ee25 100644 --- a/src/gap.h +++ b/src/gap.h @@ -128,6 +128,13 @@ gap_connection_type_t gap_get_connection_type(hci_con_handle_t connection_handle */ void gap_set_local_name(const char * local_name); +/** + * @brief Set Extended Inquiry Response data + * @param eir_data size 240 bytes, is not copied make sure memory is accessible during stack startup + * @note has to be done before stack starts up + */ +void gap_set_extended_inquiry_response(const uint8_t * data); + /** * @brief Set class of device that will be set during Bluetooth init. * @note has to be done before stack starts up diff --git a/src/hci.c b/src/hci.c index 1887864f5..b322d4dca 100644 --- a/src/hci.c +++ b/src/hci.c @@ -913,7 +913,7 @@ static void hci_initializing_next_state(void){ // assumption: hci_can_send_command_packet_now() == true static void hci_initializing_run(void){ - log_info("hci_initializing_run: substate %u, can send %u", hci_stack->substate, hci_can_send_command_packet_now()); + log_debug("hci_initializing_run: substate %u, can send %u", hci_stack->substate, hci_can_send_command_packet_now()); switch (hci_stack->substate){ case HCI_INIT_SEND_RESET: hci_state_reset(); @@ -970,7 +970,6 @@ static void hci_initializing_run(void){ break; } case HCI_INIT_CUSTOM_INIT: - log_info("Custom init"); // Custom initialization if (hci_stack->chipset && hci_stack->chipset->next_command){ int valid_cmd = (*hci_stack->chipset->next_command)(hci_stack->hci_packet_buffer); @@ -1003,7 +1002,7 @@ static void hci_initializing_run(void){ hci_stack->hci_transport->send_packet(HCI_COMMAND_DATA_PACKET, hci_stack->hci_packet_buffer, size); break; } - log_info("hci_run: init script done"); + log_info("Init script done"); // Init script download causes baud rate to reset on Broadcom chipsets, restore UART baud rate if needed if (hci_stack->manufacturer == COMPANY_ID_BROADCOM_CORPORATION){ @@ -1082,6 +1081,14 @@ static void hci_initializing_run(void){ hci_send_cmd(&hci_write_local_name, local_name); } break; + case HCI_INIT_WRITE_EIR_DATA: + hci_stack->substate = HCI_INIT_W4_WRITE_EIR_DATA; + hci_send_cmd(&hci_write_extended_inquiry_response, 0, hci_stack->eir_data); + break; + case HCI_INIT_WRITE_INQUIRY_MODE: + hci_stack->substate = HCI_INIT_W4_WRITE_INQUIRY_MODE; + hci_send_cmd(&hci_write_inquiry_mode, (int) hci_stack->inquiry_mode); + break; case HCI_INIT_WRITE_SCAN_ENABLE: hci_send_cmd(&hci_write_scan_enable, (hci_stack->connectable << 1) | hci_stack->discoverable); // page scan hci_stack->substate = HCI_INIT_W4_WRITE_SCAN_ENABLE; @@ -1136,7 +1143,7 @@ static void hci_initializing_event_handler(uint8_t * packet, uint16_t size){ uint16_t opcode = little_endian_read_16(packet,3); if (opcode == hci_stack->last_cmd_opcode){ command_completed = 1; - log_info("Command complete for expected opcode %04x at substate %u", opcode, hci_stack->substate); + log_debug("Command complete for expected opcode %04x at substate %u", opcode, hci_stack->substate); } else { log_info("Command complete for different opcode %04x, expected %04x, at substate %u", opcode, hci_stack->last_cmd_opcode, hci_stack->substate); } @@ -1148,12 +1155,12 @@ static void hci_initializing_event_handler(uint8_t * packet, uint16_t size){ if (opcode == hci_stack->last_cmd_opcode){ if (status){ command_completed = 1; - log_error("Command status error 0x%02x for expected opcode %04x at substate %u", status, opcode, hci_stack->substate); + log_debug("Command status error 0x%02x for expected opcode %04x at substate %u", status, opcode, hci_stack->substate); } else { log_info("Command status OK for expected opcode %04x, waiting for command complete", opcode); } } else { - log_info("Command status for opcode %04x, expected %04x", opcode, hci_stack->last_cmd_opcode); + log_debug("Command status for opcode %04x, expected %04x", opcode, hci_stack->last_cmd_opcode); } } @@ -1338,12 +1345,26 @@ static void hci_initializing_event_handler(uint8_t * packet, uint16_t size){ if (hci_stack->local_supported_commands[0] & 0x02) break; hci_stack->substate = HCI_INIT_LE_SET_SCAN_PARAMETERS; return; + case HCI_INIT_W4_WRITE_LOCAL_NAME: + // skip write eir data if no eir data set + if (hci_stack->eir_data) break; + hci_stack->substate = HCI_INIT_WRITE_INQUIRY_MODE; + return; #ifdef ENABLE_SCO_OVER_HCI case HCI_INIT_W4_WRITE_SCAN_ENABLE: + // skip write synchronous flow control if not supported + if (hci_stack->local_supported_commands[0] & 0x04) break; + hci_stack->substate = HCI_INIT_W4_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE; + // explicit fall through to reduce repetitions + case HCI_INIT_W4_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE: - break; - case HCI_INIT_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING: + // skip write default erroneous data reporting if not supported + if (hci_stack->local_supported_commands[0] & 0x08) break; + hci_stack->substate = HCI_INIT_W4_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING; + // explicit fall through to reduce repetitions + + case HCI_INIT_W4_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING: if (!hci_le_supported()){ // SKIP LE init for Classic only configuration hci_init_done(); @@ -1468,8 +1489,11 @@ static void event_handler(uint8_t *packet, int size){ } if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_supported_commands)){ hci_stack->local_supported_commands[0] = - (packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+14] & 0X80) >> 7 | // Octet 14, bit 7 - (packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+24] & 0x40) >> 5; // Octet 24, bit 6 + (packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+14] & 0x80) >> 7 | // bit 0 = Octet 14, bit 7 + (packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+24] & 0x40) >> 5 | // bit 1 = Octet 24, bit 6 + (packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+10] & 0x10) >> 2 | // bit 2 = Octet 10, bit 4 + (packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+18] & 0x08); // bit 3 = Octet 18, bit 3 + log_info("Local supported commands summary 0x%02x", hci_stack->local_supported_commands[0]); } if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_write_synchronous_flow_control_enable)){ if (packet[5] == 0){ @@ -3586,6 +3610,23 @@ void gap_auto_connection_stop_all(void){ #endif +/** + * @brief Set Extended Inquiry Response data + * @param eir_data size 240 bytes, is not copied make sure memory is accessible during stack startup + * @note has to be done before stack starts up + */ +void gap_set_extended_inquiry_response(const uint8_t * data){ + hci_stack->eir_data = data; +} + +/** + * @brief Set inquiry mode: standard, with RSSI, with RSSI + Extended Inquiry Results. Has to be called before power on. + * @param inquriy_mode see bluetooth_defines.h + */ +void hci_set_inquiry_mode(inquiry_mode_t mode){ + hci_stack->inquiry_mode = mode; +} + /** * @brief Configure Voice Setting for use with SCO data in HSP/HFP */ diff --git a/src/hci.h b/src/hci.h index 678624caa..5de837c2b 100644 --- a/src/hci.h +++ b/src/hci.h @@ -488,9 +488,14 @@ typedef enum hci_init_state{ HCI_INIT_W4_WRITE_CLASS_OF_DEVICE, HCI_INIT_WRITE_LOCAL_NAME, HCI_INIT_W4_WRITE_LOCAL_NAME, + HCI_INIT_WRITE_EIR_DATA, + HCI_INIT_W4_WRITE_EIR_DATA, + HCI_INIT_WRITE_INQUIRY_MODE, + HCI_INIT_W4_WRITE_INQUIRY_MODE, HCI_INIT_WRITE_SCAN_ENABLE, HCI_INIT_W4_WRITE_SCAN_ENABLE, + // SCO over HCI HCI_INIT_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE, HCI_INIT_W4_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE, HCI_INIT_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING, @@ -574,13 +579,15 @@ typedef struct { // basic configuration const char * local_name; + const uint8_t * eir_data; uint32_t class_of_device; bd_addr_t local_bd_addr; uint8_t ssp_enable; uint8_t ssp_io_capability; uint8_t ssp_authentication_requirement; uint8_t ssp_auto_accept; - + inquiry_mode_t inquiry_mode; + // single buffer for HCI packet assembly + additional prebuffer for H4 drivers uint8_t * hci_packet_buffer; uint8_t hci_packet_buffer_data[HCI_OUTGOING_PRE_BUFFER_SIZE + HCI_PACKET_BUFFER_SIZE]; @@ -605,6 +612,8 @@ typedef struct { /* local supported commands summary - complete info is 64 bytes */ /* 0 - read buffer size */ /* 1 - write le host supported */ + /* 2 - Write Synchronous Flow Control Enable (Octet 10/bit 4) */ + /* 3 - Write Default Erroneous Data Reporting (Octect 18/bit 3) */ uint8_t local_supported_commands[1]; /* bluetooth device information from hci read local version information */ @@ -737,6 +746,12 @@ void hci_set_sco_voice_setting(uint16_t voice_setting); */ uint16_t hci_get_sco_voice_setting(void); +/** + * @brief Set inquiry mode: standard, with RSSI, with RSSI + Extended Inquiry Results. Has to be called before power on. + * @param inquriy_mode see bluetooth_defines.h + */ +void hci_set_inquiry_mode(inquiry_mode_t mode); + /** * @brief Requests the change of BTstack power mode. */ diff --git a/src/hci_dump.c b/src/hci_dump.c index 995f7f271..9af2b12b5 100644 --- a/src/hci_dump.c +++ b/src/hci_dump.c @@ -150,6 +150,20 @@ static void printf_packet(uint8_t packet_type, uint8_t in, uint8_t * packet, uin printf_hexdump(packet, len); } +#ifndef HAVE_POSIX_FILE_IO +static void printf_timestamp(void){ + uint32_t time_ms = btstack_run_loop_get_time_ms(); + int seconds = time_ms / 1000; + int minutes = seconds / 60; + int hours = minutes / 60; + + int p_ms = time_ms - (seconds * 1000); + int p_seconds = seconds - (minutes * 60); + int p_minutes = minutes - (hours * 60); + printf("[%02u:%02u:%02u.%03u] ", hours, p_minutes, p_seconds, p_ms); +} +#endif + void hci_dump_packet(uint8_t packet_type, uint8_t in, uint8_t *packet, uint16_t len) { if (dump_file < 0) return; // not activated yet @@ -239,10 +253,7 @@ void hci_dump_packet(uint8_t packet_type, uint8_t in, uint8_t *packet, uint16_t } #else -// #ifdef HAVE_EMBEDDED_TICK -// uint32_t time_ms = btstack_run_loop_embedded_get_time_ms(); -// printf("[%06u] ", time_ms); -// #endif + printf_timestamp(); printf_packet(packet_type, in, packet, len); #endif @@ -262,6 +273,7 @@ void hci_dump_log(int log_level, const char * format, ...){ int len = vsnprintf(log_message_buffer, sizeof(log_message_buffer), format, argptr); hci_dump_packet(LOG_MESSAGE_PACKET, 0, (uint8_t*) log_message_buffer, len); #else + printf_timestamp(); printf("LOG -- "); vprintf(format, argptr); printf("\n"); diff --git a/test/ble_client/advertising_data_parser.c b/test/ble_client/advertising_data_parser.c index d37ce55c6..11916f6c8 100644 --- a/test/ble_client/advertising_data_parser.c +++ b/test/ble_client/advertising_data_parser.c @@ -54,7 +54,7 @@ #include "btstack_memory.h" #include "hci.h" -#include "ble/ad_parser.h" +#include "ad_parser.h" #include "l2cap.h" void le_handle_advertisement_report(uint8_t *packet, int size); diff --git a/test/btstack_config.h b/test/btstack_config.h index 47a5deb40..752dd358a 100644 --- a/test/btstack_config.h +++ b/test/btstack_config.h @@ -6,8 +6,10 @@ #define __BTSTACK_CONFIG // Port related features -#define HAVE_POSIX_TIME #define HAVE_MALLOC +#define HAVE_POSIX_TIME +#define HAVE_POSIX_FILE_IO +#define HAVE_POSIX_STDIN // BTstack features that can be enabled #define ENABLE_BLE diff --git a/test/btstack_link_key_db/btstack_link_key_db_fs_test.c b/test/btstack_link_key_db/btstack_link_key_db_fs_test.c index df6bcfaec..005a50a3c 100644 --- a/test/btstack_link_key_db/btstack_link_key_db_fs_test.c +++ b/test/btstack_link_key_db/btstack_link_key_db_fs_test.c @@ -9,6 +9,9 @@ #include "btstack_util.h" #include "btstack_config.h" + +extern "C" uint32_t btstack_run_loop_get_time_ms(void) { return 0; } + TEST_GROUP(RemoteDeviceDB){ bd_addr_t bd_addr; link_key_t link_key; diff --git a/test/btstack_link_key_db/btstack_link_key_db_memory_test.c b/test/btstack_link_key_db/btstack_link_key_db_memory_test.c index 2f0af67b6..ae8314f6e 100644 --- a/test/btstack_link_key_db/btstack_link_key_db_memory_test.c +++ b/test/btstack_link_key_db/btstack_link_key_db_memory_test.c @@ -14,6 +14,8 @@ extern btstack_linked_list_t db_mem_names ; // const extern "C" db_mem_device_name_t * btstack_memory_db_mem_device_name_get(void); // const extern "C" void btstack_memory_init(void); +extern "C" uint32_t btstack_run_loop_get_time_ms(void) { return 0; } + void dump(btstack_linked_list_t list){ printf("dump:\n"); diff --git a/test/pts/ble_central_test.c b/test/pts/ble_central_test.c index 61f56dd0a..1ab5e78ca 100644 --- a/test/pts/ble_central_test.c +++ b/test/pts/ble_central_test.c @@ -49,7 +49,7 @@ #include "btstack_config.h" -#include "ble/ad_parser.h" +#include "ad_parser.h" #include "ble/att_db.h" #include "ble/att_server.h" #include "ble/le_device_db.h" diff --git a/tool/create_packet_log.py b/tool/create_packet_log.py index 7e54639c7..090dea736 100755 --- a/tool/create_packet_log.py +++ b/tool/create_packet_log.py @@ -17,8 +17,10 @@ import sys import time import os +default_date="2001-01-01" +default_hours = 12 packet_counter = 0 -last_time = None +last_time = default_date + " " + str(default_hours) + ":00:00.000" def chop(line, prefix): if line.startswith(prefix): @@ -42,17 +44,30 @@ def generateTimestamp(t): t = last_time if t: last_time = t + + # check for date + parts = t.split(' ') + have_date = True + if len(parts) == 1: + # only time, prepend fixed date + have_date = False + t = "2000-01-01 " + t; + # handle ms try: (t1, t2) = t.split('.') if t1 and t2: - t_obj = time.strptime(t1, "%Y-%m-%d %H:%M:%S") + t_obj = time.strptime(t1, "%Y-%m-%d %H:%M:%S") tv_sec = int(time.mktime(t_obj)) + if not have_date: + # start at 12:00 + tv_sec += 12*60*60 tv_usec = int(t2) * 1000 return (tv_sec, tv_usec) except ValueError: # print 'Cannot parse time', t pass + packet_counter += 1 return (packet_counter, 0) @@ -91,7 +106,7 @@ with open (outfile, 'wb') as fout: packet_counter = 0 for line in fin: timestamp = None - parts = parts = re.match('\[(.*)\] (.*)', line) + parts = re.match('\[(.*)\] (.*)', line) if parts and len(parts.groups()) == 2: (timestamp, line) = parts.groups() rest = chop(line,'CMD => ')