diff options
| author | ailurux <ailuruxx@gmail.com> | 2024-04-02 11:13:50 +1100 |
|---|---|---|
| committer | ailurux <ailuruxx@gmail.com> | 2024-04-02 11:13:50 +1100 |
| commit | e20ebe7574db5aedc73f07b7bb3a0a01eae93c84 (patch) | |
| tree | 34c93ec8a80e282f3ce3e47dd60c41e46de0f8b3 /lib/bt/host/bluedroid/device | |
| parent | a750af35aa6afda40aadca8f7cf8db75f41a43b2 (diff) | |
| parent | 0d0c4b2307cac8436fea7276956f293262b265ed (diff) | |
| download | tangara-fw-e20ebe7574db5aedc73f07b7bb3a0a01eae93c84.tar.gz | |
Merge branch 'main' into lua-volume
Diffstat (limited to 'lib/bt/host/bluedroid/device')
| -rw-r--r-- | lib/bt/host/bluedroid/device/bdaddr.c | 126 | ||||
| -rw-r--r-- | lib/bt/host/bluedroid/device/controller.c | 600 | ||||
| -rw-r--r-- | lib/bt/host/bluedroid/device/include/device/bdaddr.h | 63 | ||||
| -rw-r--r-- | lib/bt/host/bluedroid/device/include/device/controller.h | 96 | ||||
| -rw-r--r-- | lib/bt/host/bluedroid/device/include/device/device_features.h | 29 | ||||
| -rw-r--r-- | lib/bt/host/bluedroid/device/include/device/event_mask.h | 30 | ||||
| -rw-r--r-- | lib/bt/host/bluedroid/device/include/device/interop.h | 45 | ||||
| -rw-r--r-- | lib/bt/host/bluedroid/device/include/device/interop_database.h | 50 | ||||
| -rw-r--r-- | lib/bt/host/bluedroid/device/include/device/version.h | 31 | ||||
| -rw-r--r-- | lib/bt/host/bluedroid/device/interop.c | 62 |
10 files changed, 1132 insertions, 0 deletions
diff --git a/lib/bt/host/bluedroid/device/bdaddr.c b/lib/bt/host/bluedroid/device/bdaddr.c new file mode 100644 index 00000000..6317979a --- /dev/null +++ b/lib/bt/host/bluedroid/device/bdaddr.c @@ -0,0 +1,126 @@ +/****************************************************************************** + * + * Copyright (C) 2014 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#include <stdio.h> +#include <string.h> +#include "common/bt_trace.h" +#include "device/bdaddr.h" + +static inline bool ets_isxdigit(char c) +{ + if ((c >= '0') && (c <= '9')) { + return true; + } + if ((c >= 'a') && (c <= 'f')) { + return true; + } + return ((c >= 'A') && (c <= 'F')); +} + +bool bdaddr_is_empty(const bt_bdaddr_t *addr) +{ + assert(addr != NULL); + + uint8_t zero[sizeof(bt_bdaddr_t)] = { 0 }; + return memcmp(addr, &zero, sizeof(bt_bdaddr_t)) == 0; +} + +bool bdaddr_equals(const bt_bdaddr_t *first, const bt_bdaddr_t *second) +{ + assert(first != NULL); + assert(second != NULL); + + return memcmp(first, second, sizeof(bt_bdaddr_t)) == 0; +} + +bt_bdaddr_t *bdaddr_copy(bt_bdaddr_t *dest, const bt_bdaddr_t *src) +{ + assert(dest != NULL); + assert(src != NULL); + + return (bt_bdaddr_t *)memcpy(dest, src, sizeof(bt_bdaddr_t)); +} + +const char *bdaddr_to_string(const bt_bdaddr_t *addr, char *string, size_t size) +{ + assert(addr != NULL); + assert(string != NULL); + + if (size < 18) { + return NULL; + } + + const uint8_t *ptr = addr->address; + sprintf(string, "%02x:%02x:%02x:%02x:%02x:%02x", + ptr[0], ptr[1], ptr[2], + ptr[3], ptr[4], ptr[5]); + return string; +} + +bool string_is_bdaddr(const char *string) +{ + assert(string != NULL); + + size_t len = strlen(string); + if (len != 17) { + return false; + } + + for (size_t i = 0; i < len; ++i) { + // Every 3rd char must be ':'. + if (((i + 1) % 3) == 0 && string[i] != ':') { + return false; + } + + // All other chars must be a hex digit. + if (((i + 1) % 3) != 0 && !ets_isxdigit(string[i])) { + return false; + } + } + return true; +} + +bool string_to_bdaddr(const char *string, bt_bdaddr_t *addr) +{ + assert(string != NULL); + assert(addr != NULL); + + bt_bdaddr_t new_addr; + uint8_t *ptr = new_addr.address; + uint32_t ptr_32[6]; + bool ret = sscanf(string, "%02x:%02x:%02x:%02x:%02x:%02x", + &ptr_32[0], &ptr_32[1], &ptr_32[2], &ptr_32[3], &ptr_32[4], &ptr_32[5]) == 6; + if (ret) { + for (uint8_t i = 0; i < 6; i++){ + ptr[i] = (uint8_t) ptr_32[i]; + } + memcpy(addr, &new_addr, sizeof(bt_bdaddr_t)); + } + + return ret; +} + +hash_index_t hash_function_bdaddr(const void *key) +{ + hash_index_t hash = 5381; + const char *bytes = (const char *)key; + for (size_t i = 0; i < sizeof(bt_bdaddr_t); ++i) { + hash = ((hash << 5) + hash) + bytes[i]; + } + return hash; +} diff --git a/lib/bt/host/bluedroid/device/controller.c b/lib/bt/host/bluedroid/device/controller.c new file mode 100644 index 00000000..beb7d676 --- /dev/null +++ b/lib/bt/host/bluedroid/device/controller.c @@ -0,0 +1,600 @@ +/****************************************************************************** + * + * Copyright (C) 2014 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ +#include <stdbool.h> +#include "common/bt_target.h" +#include "common/bt_trace.h" +#include "device/bdaddr.h" +#include "stack/bt_types.h" +#include "device/controller.h" +#include "device/event_mask.h" +#include "stack/hcimsgs.h" +#include "hci/hci_layer.h" +#include "hci/hci_packet_factory.h" +#include "hci/hci_packet_parser.h" +#include "stack/btm_ble_api.h" +#include "device/version.h" +#include "osi/future.h" +#include "config/stack_config.h" +#if (BLE_50_FEATURE_SUPPORT == TRUE) +const bt_event_mask_t BLE_EVENT_MASK = { "\x00\x00\x00\x00\x00\xff\xff\xff" }; +#else +const bt_event_mask_t BLE_EVENT_MASK = { "\x00\x00\x00\x00\x00\x00\x06\x7f" }; +#endif + +#if (BLE_INCLUDED) +const bt_event_mask_t CLASSIC_EVENT_MASK = { HCI_DUMO_EVENT_MASK_EXT }; +#else +const bt_event_mask_t CLASSIC_EVENT_MASK = { HCI_LISBON_EVENT_MASK_EXT }; +#endif + +// TODO(zachoverflow): factor out into common module +const uint8_t SCO_HOST_BUFFER_SIZE = 0xff; + +#define HCI_SUPPORTED_COMMANDS_ARRAY_SIZE 64 +#define MAX_FEATURES_CLASSIC_PAGE_COUNT 3 +#define BLE_SUPPORTED_STATES_SIZE 8 +#define BLE_SUPPORTED_FEATURES_SIZE 8 +#define BLE_EXT_ADV_DATA_LEN_MAX 1650 + +typedef struct { + const hci_t *hci; + const hci_packet_factory_t *packet_factory; + const hci_packet_parser_t *packet_parser; + + bt_version_t bt_version; + bt_bdaddr_t address; + + uint8_t supported_commands[HCI_SUPPORTED_COMMANDS_ARRAY_SIZE]; + uint8_t last_features_classic_page_index; + bt_device_features_t features_classic[MAX_FEATURES_CLASSIC_PAGE_COUNT]; + + uint16_t acl_data_size_classic; + uint16_t acl_data_size_ble; + uint16_t acl_buffer_count_classic; + uint8_t acl_buffer_count_ble; + + uint8_t sco_data_size; + uint16_t sco_buffer_count; + + uint8_t ble_white_list_size; + uint8_t ble_resolving_list_max_size; + uint8_t ble_supported_states[BLE_SUPPORTED_STATES_SIZE]; + bt_device_features_t features_ble; + uint16_t ble_suggested_default_data_length; + uint16_t ble_suggested_default_data_txtime; + + bool readable; + bool ble_supported; + bool simple_pairing_supported; + bool secure_connections_supported; +#if (BLE_50_FEATURE_SUPPORT == TRUE) + uint16_t ble_ext_adv_data_max_len; +#endif //#if (BLE_50_FEATURE_SUPPORT == TRUE) +} controller_local_param_t; + +#if BT_BLE_DYNAMIC_ENV_MEMORY == FALSE +static controller_local_param_t controller_param; +#else +static controller_local_param_t *controller_param_ptr; +#define controller_param (*controller_param_ptr) +#endif + +#define AWAIT_COMMAND(command) future_await(controller_param.hci->transmit_command_futured(command)) + +// Module lifecycle functions + +static void start_up(void) +{ + BT_HDR *response; + + // Send the initial reset command + response = AWAIT_COMMAND(controller_param.packet_factory->make_reset()); + controller_param.packet_parser->parse_generic_command_complete(response); + +#if (CLASSIC_BT_INCLUDED) + // Request the classic buffer size next + response = AWAIT_COMMAND(controller_param.packet_factory->make_read_buffer_size()); + controller_param.packet_parser->parse_read_buffer_size_response( + response, &controller_param.acl_data_size_classic, &controller_param.acl_buffer_count_classic, + &controller_param.sco_data_size, &controller_param.sco_buffer_count); +#endif + +#if (C2H_FLOW_CONTROL_INCLUDED == TRUE) + // Enable controller to host flow control + response = AWAIT_COMMAND(controller_param.packet_factory->make_set_c2h_flow_control(HCI_HOST_FLOW_CTRL_ACL_ON)); + controller_param.packet_parser->parse_generic_command_complete(response); +#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE +#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) + // Enable adv flow control + response = AWAIT_COMMAND(controller_param.packet_factory->make_set_adv_report_flow_control(HCI_HOST_FLOW_CTRL_ADV_REPORT_ON, (uint16_t)BLE_ADV_REPORT_FLOW_CONTROL_NUM, (uint16_t)BLE_ADV_REPORT_DISCARD_THRSHOLD)); + controller_param.packet_parser->parse_generic_command_complete(response); +#endif + // Tell the controller about our buffer sizes and buffer counts next + // TODO(zachoverflow): factor this out. eww l2cap contamination. And why just a hardcoded 10? + response = AWAIT_COMMAND( + controller_param.packet_factory->make_host_buffer_size( + L2CAP_MTU_SIZE, + SCO_HOST_BUFFER_SIZE, + L2CAP_HOST_FC_ACL_BUFS, + 10 + ) + ); + + controller_param.packet_parser->parse_generic_command_complete(response); + + // Read the local version info off the controller next, including + // information such as manufacturer and supported HCI version + response = AWAIT_COMMAND(controller_param.packet_factory->make_read_local_version_info()); + controller_param.packet_parser->parse_read_local_version_info_response(response, &controller_param.bt_version); + + // Read the bluetooth address off the controller next + response = AWAIT_COMMAND(controller_param.packet_factory->make_read_bd_addr()); + controller_param.packet_parser->parse_read_bd_addr_response(response, &controller_param.address); + + // Request the controller's supported commands next + response = AWAIT_COMMAND(controller_param.packet_factory->make_read_local_supported_commands()); + controller_param.packet_parser->parse_read_local_supported_commands_response( + response, + controller_param.supported_commands, + HCI_SUPPORTED_COMMANDS_ARRAY_SIZE + ); + +#if (CLASSIC_BT_INCLUDED) + // Read page 0 of the controller features next + uint8_t page_number = 0; + response = AWAIT_COMMAND(controller_param.packet_factory->make_read_local_extended_features(page_number)); + controller_param.packet_parser->parse_read_local_extended_features_response( + response, + &page_number, + &controller_param.last_features_classic_page_index, + controller_param.features_classic, + MAX_FEATURES_CLASSIC_PAGE_COUNT + ); + + assert(page_number == 0); + page_number++; +#endif + + // Inform the controller what page 0 features we support, based on what + // it told us it supports. We need to do this first before we request the + // next page, because the controller's response for page 1 may be + // dependent on what we configure from page 0 and host SSP configuration + controller_param.simple_pairing_supported = HCI_SIMPLE_PAIRING_SUPPORTED( + controller_param.features_classic[0].as_array) && + (bluedriod_config_get()->get_ssp_enabled()); + if (controller_param.simple_pairing_supported) { + response = AWAIT_COMMAND(controller_param.packet_factory->make_write_simple_pairing_mode(HCI_SP_MODE_ENABLED)); + controller_param.packet_parser->parse_generic_command_complete(response); + } + +#if (BLE_INCLUDED == TRUE) + if (HCI_LE_SPT_SUPPORTED(controller_param.features_classic[0].as_array)) { + uint8_t simultaneous_le_host = HCI_SIMUL_LE_BREDR_SUPPORTED(controller_param.features_classic[0].as_array) ? BTM_BLE_SIMULTANEOUS_HOST : 0; + response = AWAIT_COMMAND( + controller_param.packet_factory->make_ble_write_host_support(BTM_BLE_HOST_SUPPORT, simultaneous_le_host) + ); + + controller_param.packet_parser->parse_generic_command_complete(response); + } +#endif + +#if (CLASSIC_BT_INCLUDED) + // Done telling the controller about what page 0 features we support + // Request the remaining feature pages + while (page_number <= controller_param.last_features_classic_page_index && + page_number < MAX_FEATURES_CLASSIC_PAGE_COUNT) { + response = AWAIT_COMMAND(controller_param.packet_factory->make_read_local_extended_features(page_number)); + controller_param.packet_parser->parse_read_local_extended_features_response( + response, + &page_number, + &controller_param.last_features_classic_page_index, + controller_param.features_classic, + MAX_FEATURES_CLASSIC_PAGE_COUNT + ); + + page_number++; + } +#endif + +#if (SC_MODE_INCLUDED == TRUE) + controller_param.secure_connections_supported = HCI_SC_CTRLR_SUPPORTED(controller_param.features_classic[2].as_array); + if (controller_param.secure_connections_supported) { + response = AWAIT_COMMAND(controller_param.packet_factory->make_write_secure_connections_host_support(HCI_SC_MODE_ENABLED)); + controller_param.packet_parser->parse_generic_command_complete(response); + } +#endif + +#if (BLE_INCLUDED == TRUE) +#if (CLASSIC_BT_INCLUDED) + controller_param.ble_supported = controller_param.last_features_classic_page_index >= 1 && HCI_LE_HOST_SUPPORTED(controller_param.features_classic[1].as_array); +#else + controller_param.ble_supported = true; +#endif + if (controller_param.ble_supported) { + // Request the ble white list size next + response = AWAIT_COMMAND(controller_param.packet_factory->make_ble_read_white_list_size()); + controller_param.packet_parser->parse_ble_read_white_list_size_response(response, &controller_param.ble_white_list_size); + + // Request the ble buffer size next + response = AWAIT_COMMAND(controller_param.packet_factory->make_ble_read_buffer_size()); + controller_param.packet_parser->parse_ble_read_buffer_size_response( + response, + &controller_param.acl_data_size_ble, + &controller_param.acl_buffer_count_ble + ); + + // Response of 0 indicates ble has the same buffer size as classic + if (controller_param.acl_data_size_ble == 0) { + controller_param.acl_data_size_ble = controller_param.acl_data_size_classic; + } + + // Request the ble supported states next + response = AWAIT_COMMAND(controller_param.packet_factory->make_ble_read_supported_states()); + controller_param.packet_parser->parse_ble_read_supported_states_response( + response, + controller_param.ble_supported_states, + sizeof(controller_param.ble_supported_states) + ); + + // Request the ble supported features next + response = AWAIT_COMMAND(controller_param.packet_factory->make_ble_read_local_supported_features()); + controller_param.packet_parser->parse_ble_read_local_supported_features_response( + response, + &controller_param.features_ble + ); + + if (HCI_LE_ENHANCED_PRIVACY_SUPPORTED(controller_param.features_ble.as_array)) { + response = AWAIT_COMMAND(controller_param.packet_factory->make_ble_read_resolving_list_size()); + controller_param.packet_parser->parse_ble_read_resolving_list_size_response( + response, + &controller_param.ble_resolving_list_max_size); + } +#if BLE_50_FEATURE_SUPPORT == TRUE + controller_param.ble_ext_adv_data_max_len = BLE_EXT_ADV_DATA_LEN_MAX; +#endif //#if (BLE_50_FEATURE_SUPPORT == TRUE) + +#if (BLE_50_FEATURE_SUPPORT == TRUE && BLE_42_FEATURE_SUPPORT == FALSE) + if (HCI_LE_ENHANCED_PRIVACY_SUPPORTED(controller_param.features_ble.as_array)) { + response = AWAIT_COMMAND(controller_param.packet_factory->make_read_max_adv_data_len()); + controller_param.packet_parser->parse_ble_read_adv_max_len_response( + response, + &controller_param.ble_ext_adv_data_max_len); + } +#endif // (BLE_50_FEATURE_SUPPORT == TRUE && BLE_42_FEATURE_SUPPORT == FALSE) + + if (HCI_LE_DATA_LEN_EXT_SUPPORTED(controller_param.features_ble.as_array)) { + /* set default tx data length to MAX 251 */ + response = AWAIT_COMMAND(controller_param.packet_factory->make_ble_write_suggested_default_data_length(BTM_BLE_DATA_SIZE_MAX, BTM_BLE_DATA_TX_TIME_MAX)); + controller_param.packet_parser->parse_generic_command_complete(response); + + response = AWAIT_COMMAND(controller_param.packet_factory->make_ble_read_suggested_default_data_length()); + controller_param.packet_parser->parse_ble_read_suggested_default_data_length_response( + response, + &controller_param.ble_suggested_default_data_length, + &controller_param.ble_suggested_default_data_txtime); + } + + // Set the ble event mask next + response = AWAIT_COMMAND(controller_param.packet_factory->make_ble_set_event_mask(&BLE_EVENT_MASK)); + controller_param.packet_parser->parse_generic_command_complete(response); + } +#endif + + response = AWAIT_COMMAND(controller_param.packet_factory->make_set_event_mask(&CLASSIC_EVENT_MASK)); + controller_param.packet_parser->parse_generic_command_complete(response); + +#if (BTM_SCO_HCI_INCLUDED == TRUE) + response = AWAIT_COMMAND(controller_param.packet_factory->make_write_sync_flow_control_enable(1)); + controller_param.packet_parser->parse_generic_command_complete(response); + + response = AWAIT_COMMAND(controller_param.packet_factory->make_write_default_erroneous_data_report(1)); + controller_param.packet_parser->parse_generic_command_complete(response); +#endif + controller_param.readable = true; + // return future_new_immediate(FUTURE_SUCCESS); + return; +} + +static void shut_down(void) +{ + controller_param.readable = false; +} + +static bool get_is_ready(void) +{ + return controller_param.readable; +} + +static const bt_bdaddr_t *get_address(void) +{ + assert(controller_param.readable); + return &controller_param.address; +} + +static const bt_version_t *get_bt_version(void) +{ + assert(controller_param.readable); + return &controller_param.bt_version; +} + +// TODO(zachoverflow): hide inside, move decoder inside too +static const bt_device_features_t *get_features_classic(int index) +{ + assert(controller_param.readable); + assert(index < MAX_FEATURES_CLASSIC_PAGE_COUNT); + return &controller_param.features_classic[index]; +} + +static uint8_t get_last_features_classic_index(void) +{ + assert(controller_param.readable); + return controller_param.last_features_classic_page_index; +} + +static const bt_device_features_t *get_features_ble(void) +{ + assert(controller_param.readable); + assert(controller_param.ble_supported); + return &controller_param.features_ble; +} + +static const uint8_t *get_ble_supported_states(void) +{ + assert(controller_param.readable); + assert(controller_param.ble_supported); + return controller_param.ble_supported_states; +} + +static bool supports_simple_pairing(void) +{ + assert(controller_param.readable); + return controller_param.simple_pairing_supported; +} + +static bool supports_secure_connections(void) +{ + assert(controller_param.readable); + return controller_param.secure_connections_supported; +} + +static bool supports_simultaneous_le_bredr(void) +{ + assert(controller_param.readable); + return HCI_SIMUL_LE_BREDR_SUPPORTED(controller_param.features_classic[0].as_array); +} + +static bool supports_reading_remote_extended_features(void) +{ + assert(controller_param.readable); + return HCI_READ_REMOTE_EXT_FEATURES_SUPPORTED(controller_param.supported_commands); +} + +static bool supports_interlaced_inquiry_scan(void) +{ + assert(controller_param.readable); + return HCI_LMP_INTERLACED_INQ_SCAN_SUPPORTED(controller_param.features_classic[0].as_array); +} + +static bool supports_rssi_with_inquiry_results(void) +{ + assert(controller_param.readable); + return HCI_LMP_INQ_RSSI_SUPPORTED(controller_param.features_classic[0].as_array); +} + +static bool supports_extended_inquiry_response(void) +{ + assert(controller_param.readable); + return HCI_EXT_INQ_RSP_SUPPORTED(controller_param.features_classic[0].as_array); +} + +static bool supports_master_slave_role_switch(void) +{ + assert(controller_param.readable); + return HCI_SWITCH_SUPPORTED(controller_param.features_classic[0].as_array); +} + +static bool supports_ble(void) +{ + assert(controller_param.readable); + return controller_param.ble_supported; +} + +static bool supports_ble_privacy(void) +{ + assert(controller_param.readable); + assert(controller_param.ble_supported); + return HCI_LE_ENHANCED_PRIVACY_SUPPORTED(controller_param.features_ble.as_array); +} + +static bool supports_ble_packet_extension(void) +{ + assert(controller_param.readable); + assert(controller_param.ble_supported); + return HCI_LE_DATA_LEN_EXT_SUPPORTED(controller_param.features_ble.as_array); +} + +static bool supports_ble_connection_parameters_request(void) +{ + assert(controller_param.readable); + assert(controller_param.ble_supported); + return HCI_LE_CONN_PARAM_REQ_SUPPORTED(controller_param.features_ble.as_array); +} + +static uint16_t get_acl_data_size_classic(void) +{ + assert(controller_param.readable); + return controller_param.acl_data_size_classic; +} + +static uint16_t get_acl_data_size_ble(void) +{ + assert(controller_param.readable); + assert(controller_param.ble_supported); + return controller_param.acl_data_size_ble; +} + +static uint16_t get_acl_packet_size_classic(void) +{ + assert(controller_param.readable); + return controller_param.acl_data_size_classic + HCI_DATA_PREAMBLE_SIZE; +} + +static uint16_t get_acl_packet_size_ble(void) +{ + assert(controller_param.readable); + return controller_param.acl_data_size_ble + HCI_DATA_PREAMBLE_SIZE; +} + +static uint16_t get_ble_suggested_default_data_length(void) +{ + assert(controller_param.readable); + assert(controller_param.ble_supported); + return controller_param.ble_suggested_default_data_length; +} + +static uint16_t get_ble_suggested_default_data_txtime(void) +{ + assert(controller_param.readable); + assert(controller_param.ble_supported); + return controller_param.ble_suggested_default_data_txtime; +} + +static uint16_t get_acl_buffer_count_classic(void) +{ + assert(controller_param.readable); + return controller_param.acl_buffer_count_classic; +} + +static uint8_t get_acl_buffer_count_ble(void) +{ + assert(controller_param.readable); + assert(controller_param.ble_supported); + return controller_param.acl_buffer_count_ble; +} + +static uint8_t get_ble_white_list_size(void) +{ + assert(controller_param.readable); + assert(controller_param.ble_supported); + return controller_param.ble_white_list_size; +} + +static uint8_t get_ble_resolving_list_max_size(void) +{ + assert(controller_param.readable); + assert(controller_param.ble_supported); + return controller_param.ble_resolving_list_max_size; +} + +static void set_ble_resolving_list_max_size(int resolving_list_max_size) +{ + assert(controller_param.readable); + assert(controller_param.ble_supported); + controller_param.ble_resolving_list_max_size = resolving_list_max_size; +} +#if (BLE_50_FEATURE_SUPPORT == TRUE) +static uint16_t ble_get_ext_adv_data_max_len(void) +{ + assert(controller_param.readable); + assert(controller_param.ble_supported); + + return controller_param.ble_ext_adv_data_max_len; +} +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BTM_SCO_HCI_INCLUDED == TRUE) +static uint8_t get_sco_data_size(void) +{ + assert(controller_param.readable); + return controller_param.sco_data_size; +} + +static uint8_t get_sco_buffer_count(void) +{ + assert(controller_param.readable); + return controller_param.sco_buffer_count; +} +#endif /* (BTM_SCO_HCI_INCLUDED == TRUE) */ + +static const controller_t interface = { + start_up, + shut_down, + get_is_ready, + + get_address, + get_bt_version, + + get_features_classic, + get_last_features_classic_index, + + get_features_ble, + get_ble_supported_states, + + supports_simple_pairing, + supports_secure_connections, + supports_simultaneous_le_bredr, + supports_reading_remote_extended_features, + supports_interlaced_inquiry_scan, + supports_rssi_with_inquiry_results, + supports_extended_inquiry_response, + supports_master_slave_role_switch, + + supports_ble, + supports_ble_packet_extension, + supports_ble_connection_parameters_request, + supports_ble_privacy, + + get_acl_data_size_classic, + get_acl_data_size_ble, + + get_acl_packet_size_classic, + get_acl_packet_size_ble, + get_ble_suggested_default_data_length, + get_ble_suggested_default_data_txtime, + + get_acl_buffer_count_classic, + get_acl_buffer_count_ble, + + get_ble_white_list_size, + + get_ble_resolving_list_max_size, + set_ble_resolving_list_max_size, +#if (BLE_50_FEATURE_SUPPORT == TRUE) + ble_get_ext_adv_data_max_len, +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BTM_SCO_HCI_INCLUDED == TRUE) + get_sco_data_size, + get_sco_buffer_count, +#endif /* (BTM_SCO_HCI_INCLUDED == TRUE) */ +}; + +const controller_t *controller_get_interface(void) +{ + static bool loaded = false; + if (!loaded) { + loaded = true; +#if (BT_BLE_DYNAMIC_ENV_MEMORY == TRUE) + controller_param_ptr = (controller_local_param_t *)osi_calloc(sizeof(controller_local_param_t)); + assert(controller_param_ptr); +#endif + controller_param.hci = hci_layer_get_interface(); + controller_param.packet_factory = hci_packet_factory_get_interface(); + controller_param.packet_parser = hci_packet_parser_get_interface(); + } + + return &interface; +} diff --git a/lib/bt/host/bluedroid/device/include/device/bdaddr.h b/lib/bt/host/bluedroid/device/include/device/bdaddr.h new file mode 100644 index 00000000..611fcf0e --- /dev/null +++ b/lib/bt/host/bluedroid/device/include/device/bdaddr.h @@ -0,0 +1,63 @@ +/****************************************************************************** + * + * Copyright (C) 2014 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#ifndef _BDADDR_H_ +#define _BDADDR_H_ + +#include <stdbool.h> +#include <stddef.h> + +#include "common/bt_defs.h" +#include "osi/hash_map.h" + +// Note: the string representation of a bdaddr is expected to have the format +// xx:xx:xx:xx:xx:xx +// where each 'x' is a hex digit. The API presented in this header will accept +// both uppercase and lowercase digits but will only ever produce lowercase +// digits. + +// Returns true if |addr| is the empty address (00:00:00:00:00:00). +// |addr| may not be NULL. +bool bdaddr_is_empty(const bt_bdaddr_t *addr); + +// Returns true if |first| and |second| refer to the same address. Neither +// may be NULL. +bool bdaddr_equals(const bt_bdaddr_t *first, const bt_bdaddr_t *second); + +// Returns destination bdaddr |dest| after copying |src| to |dest|. +// |dest| and |src| must not be NULL. +bt_bdaddr_t *bdaddr_copy(bt_bdaddr_t *dest, const bt_bdaddr_t *src); + +// Makes a string representation of |addr| and places it into |string|. |size| +// refers to the size of |string|'s buffer and must be >= 18. On success, this +// function returns |string|, otherwise it returns NULL. Neither |addr| nor |string| +// may be NULL. +const char *bdaddr_to_string(const bt_bdaddr_t *addr, char *string, size_t size); + +// Returns true if |string| represents a Bluetooth address. |string| may not be NULL. +bool string_is_bdaddr(const char *string); + +// Converts |string| to bt_bdaddr_t and places it in |addr|. If |string| does not +// represent a Bluetooth address, |addr| is not modified and this function returns +// false. Otherwise, it returns true. Neither |string| nor |addr| may be NULL. +bool string_to_bdaddr(const char *string, bt_bdaddr_t *addr); + +// A hash function tailored for bdaddrs. +hash_index_t hash_function_bdaddr(const void *key); + +#endif diff --git a/lib/bt/host/bluedroid/device/include/device/controller.h b/lib/bt/host/bluedroid/device/include/device/controller.h new file mode 100644 index 00000000..6fc766f3 --- /dev/null +++ b/lib/bt/host/bluedroid/device/include/device/controller.h @@ -0,0 +1,96 @@ +/****************************************************************************** + * + * Copyright (C) 2014 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#ifndef _CONTROLLER_H_ +#define _CONTROLLER_H_ + +#include <stdbool.h> +#include <stdint.h> + +#include "common/bt_target.h" +#include "device/bdaddr.h" +#include "device/device_features.h" +#include "hci/hci_layer.h" +#include "hci/hci_packet_factory.h" +#include "hci/hci_packet_parser.h" + +typedef struct controller_t { + void (*start_up)(void); + void (*shut_down)(void); + bool (*get_is_ready)(void); + + const bt_bdaddr_t *(*get_address)(void); + const bt_version_t *(*get_bt_version)(void); + + const bt_device_features_t *(*get_features_classic)(int index); + + uint8_t (*get_last_features_classic_index)(void); + + const bt_device_features_t *(*get_features_ble)(void); + const uint8_t *(*get_ble_supported_states)(void); + + bool (*supports_simple_pairing)(void); + bool (*supports_secure_connections)(void); + bool (*supports_simultaneous_le_bredr)(void); + bool (*supports_reading_remote_extended_features)(void); + bool (*supports_interlaced_inquiry_scan)(void); + bool (*supports_rssi_with_inquiry_results)(void); + bool (*supports_extended_inquiry_response)(void); + bool (*supports_master_slave_role_switch)(void); + + bool (*supports_ble)(void); + bool (*supports_ble_packet_extension)(void); + bool (*supports_ble_connection_parameters_request)(void); + bool (*supports_ble_privacy)(void); + + // Get the cached acl data sizes for the controller. + uint16_t (*get_acl_data_size_classic)(void); + uint16_t (*get_acl_data_size_ble)(void); + + // Get the cached acl packet sizes for the controller. + // This is a convenience function for the respective + // acl data size + size of the acl header. + uint16_t (*get_acl_packet_size_classic)(void); + uint16_t (*get_acl_packet_size_ble)(void); + + uint16_t (*get_ble_default_data_packet_length)(void); + uint16_t (*get_ble_default_data_packet_txtime)(void); + + // Get the number of acl packets the controller can buffer. + uint16_t (*get_acl_buffer_count_classic)(void); + uint8_t (*get_acl_buffer_count_ble)(void); + + uint8_t (*get_ble_white_list_size)(void); + + uint8_t (*get_ble_resolving_list_max_size)(void); + void (*set_ble_resolving_list_max_size)(int resolving_list_max_size); + +#if (BLE_50_FEATURE_SUPPORT == TRUE) + uint16_t (*ble_get_ext_adv_data_max_len)(void); +#endif // BLE_50_FEATURE_SUPPORT + +#if (BTM_SCO_HCI_INCLUDED == TRUE) + // Get the number of sco packets the controller can buffer + uint8_t (*get_sco_data_size)(void); + uint8_t (*get_sco_buffer_count)(void); +#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE) */ +} controller_t; + +const controller_t *controller_get_interface(void); + +#endif /*_CONTROLLER_H_*/ diff --git a/lib/bt/host/bluedroid/device/include/device/device_features.h b/lib/bt/host/bluedroid/device/include/device/device_features.h new file mode 100644 index 00000000..360d3768 --- /dev/null +++ b/lib/bt/host/bluedroid/device/include/device/device_features.h @@ -0,0 +1,29 @@ +/****************************************************************************** + * + * Copyright (C) 2014 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ +#ifndef _DEVICE_FEATURES_H_ +#define _DEVICE_FEATURES_H_ + +#include <stdint.h> + +// Represents a page of device feature enabled/disabled bits returned +// by the local controller. See the bluetooth spec for bit indexes. +typedef struct { + uint8_t as_array[8]; +} bt_device_features_t; + +#endif /*_DEVICE_FEATURES_H_*/ diff --git a/lib/bt/host/bluedroid/device/include/device/event_mask.h b/lib/bt/host/bluedroid/device/include/device/event_mask.h new file mode 100644 index 00000000..d4d036d5 --- /dev/null +++ b/lib/bt/host/bluedroid/device/include/device/event_mask.h @@ -0,0 +1,30 @@ +/****************************************************************************** + * + * Copyright (C) 2014 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ +#ifndef _EVENT_MASK_H_ +#define _EVENT_MASK_H_ + +#include <stdint.h> + +// Represents a mask which can be used to tell the controller which +// HCI events the stack wishes to be informed about. See the bluetooth +// spec for more information on what each bit means. +typedef struct { + uint8_t as_array[8]; +} bt_event_mask_t; + +#endif /*_EVENT_MASK_H_*/ diff --git a/lib/bt/host/bluedroid/device/include/device/interop.h b/lib/bt/host/bluedroid/device/include/device/interop.h new file mode 100644 index 00000000..64f27adb --- /dev/null +++ b/lib/bt/host/bluedroid/device/include/device/interop.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * + * Copyright (C) 2015 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#ifndef _INTEROP_H_ +#define _INTEROP_H_ + +#include <stdbool.h> +#include "common/bt_defs.h" +#include "common/bt_target.h" + +typedef enum { + // Disable secure connections + // This is for pre BT 4.1/2 devices that do not handle secure mode + // very well. + INTEROP_DISABLE_LE_SECURE_CONNECTIONS, + + // Some devices have proven problematic during the pairing process, often + // requiring multiple retries to complete pairing. To avoid degrading the user + // experience for those devices, automatically re-try pairing if page + // timeouts are received during pairing. + INTEROP_AUTO_RETRY_PAIRING +} interop_feature_t; + +// Check if a given |addr| matches a known interoperability workaround as identified +// by the |interop_feature_t| enum. This API is used for simple address based lookups +// where more information is not available. No look-ups or random address resolution +// is performed on |addr|. +bool interop_match(const interop_feature_t feature, const bt_bdaddr_t *addr); + +#endif /*_INTEROP_H_*/ diff --git a/lib/bt/host/bluedroid/device/include/device/interop_database.h b/lib/bt/host/bluedroid/device/include/device/interop_database.h new file mode 100644 index 00000000..71224905 --- /dev/null +++ b/lib/bt/host/bluedroid/device/include/device/interop_database.h @@ -0,0 +1,50 @@ +/****************************************************************************** + * + * Copyright (C) 2015 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#ifndef _INTEROP_DATABASE_H_ +#define _INTEROP_DATABASE_H_ + +#include "device/interop.h" + +typedef struct { + bt_bdaddr_t addr; + uint8_t len; + interop_feature_t feature; +} interop_entry_t; + +static const interop_entry_t interop_database[] = { + // Nexus Remote (Spike) + // Note: May affect other Asus brand devices + {{{0x08, 0x62, 0x66, 0, 0, 0}}, 3, INTEROP_DISABLE_LE_SECURE_CONNECTIONS}, + {{{0x38, 0x2c, 0x4a, 0xc9, 0, 0}}, 4, INTEROP_DISABLE_LE_SECURE_CONNECTIONS}, + {{{0x38, 0x2c, 0x4a, 0xe6, 0, 0}}, 4, INTEROP_DISABLE_LE_SECURE_CONNECTIONS}, + {{{0x54, 0xa0, 0x50, 0xd9, 0, 0}}, 4, INTEROP_DISABLE_LE_SECURE_CONNECTIONS}, + {{{0xac, 0x9e, 0x17, 0, 0, 0}}, 3, INTEROP_DISABLE_LE_SECURE_CONNECTIONS}, + {{{0xf0, 0x79, 0x59, 0, 0, 0}}, 3, INTEROP_DISABLE_LE_SECURE_CONNECTIONS}, + + // Motorola Key Link + {{{0x1c, 0x96, 0x5a, 0, 0, 0}}, 3, INTEROP_DISABLE_LE_SECURE_CONNECTIONS}, + + // Flic smart button + {{{0x80, 0xe4, 0xda, 0x70, 0, 0}}, 4, INTEROP_DISABLE_LE_SECURE_CONNECTIONS}, + + // BMW car kits (Harman/Becker) + {{{0x9c, 0xdf, 0x03, 0, 0, 0}}, 3, INTEROP_AUTO_RETRY_PAIRING} +}; + +#endif /*_INTEROP_DATABASE_H_*/ diff --git a/lib/bt/host/bluedroid/device/include/device/version.h b/lib/bt/host/bluedroid/device/include/device/version.h new file mode 100644 index 00000000..c63b03bd --- /dev/null +++ b/lib/bt/host/bluedroid/device/include/device/version.h @@ -0,0 +1,31 @@ +/****************************************************************************** + * + * Copyright (C) 2014 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ +#ifndef _VERSION_H_ +#define _VERSION_H_ + +#include <stdint.h> + +typedef struct { + uint8_t hci_version; + uint16_t hci_revision; + uint8_t lmp_version; + uint16_t manufacturer; + uint16_t lmp_subversion; +} bt_version_t; + +#endif /*_VERSION_H_*/ diff --git a/lib/bt/host/bluedroid/device/interop.c b/lib/bt/host/bluedroid/device/interop.c new file mode 100644 index 00000000..f5601354 --- /dev/null +++ b/lib/bt/host/bluedroid/device/interop.c @@ -0,0 +1,62 @@ +/****************************************************************************** + * + * Copyright (C) 2015 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ +/* +#define LOG_TAG "bt_device_interop" +*/ +#include <string.h> // For memcmp +#include "common/bt_trace.h" +#include "device/bdaddr.h" +#include "device/interop.h" +#include "device/interop_database.h" + +#define CASE_RETURN_STR(const) case const: return #const; + +#if (SMP_INCLUDED == TRUE) +#if (!CONFIG_BT_STACK_NO_LOG) +static const char *interop_feature_string(const interop_feature_t feature) +{ + switch (feature) { + CASE_RETURN_STR(INTEROP_DISABLE_LE_SECURE_CONNECTIONS) + CASE_RETURN_STR(INTEROP_AUTO_RETRY_PAIRING) + } + + return "UNKNOWN"; +} +#endif // (!CONFIG_BT_STACK_NO_LOG) +// Interface functions +bool interop_match(const interop_feature_t feature, const bt_bdaddr_t *addr) +{ + assert(addr); + + const size_t db_size = sizeof(interop_database) / sizeof(interop_entry_t); + + for (size_t i = 0; i != db_size; ++i) { + if (feature == interop_database[i].feature && + memcmp(addr, &interop_database[i].addr, interop_database[i].len) == 0) { +#if (!CONFIG_BT_STACK_NO_LOG) + char bdstr[20] = {0}; +#endif + LOG_WARN("%s() Device %s is a match for interop workaround %s", __func__, + bdaddr_to_string(addr, bdstr, sizeof(bdstr)), interop_feature_string(feature)); + return true; + } + } + + return false; +} +#endif ///SMP_INCLUDED == TRUE |
