hci: extract handle_command_complete_event

This commit is contained in:
Matthias Ringwald 2020-07-07 17:51:03 +02:00
parent 2c31d7721e
commit 4f7810264d

302
src/hci.c
View File

@ -1979,6 +1979,158 @@ static void hci_handle_read_encryption_key_size_complete(hci_connection_t * conn
}
#endif
static void handle_command_complete_event(uint8_t * packet, uint16_t size){
hci_con_handle_t handle;
hci_connection_t * conn;
// get num cmd packets - limit to 1 to reduce complexity
hci_stack->num_cmd_packets = packet[2] ? 1 : 0;
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_name)){
if (packet[5]) return;
// terminate, name 248 chars
packet[6+248] = 0;
log_info("local name: %s", &packet[6]);
}
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_buffer_size)){
// "The HC_ACL_Data_Packet_Length return parameter will be used to determine the size of the L2CAP segments contained in ACL Data Packets"
if (hci_stack->state == HCI_STATE_INITIALIZING){
uint16_t acl_len = little_endian_read_16(packet, 6);
uint16_t sco_len = packet[8];
// determine usable ACL/SCO payload size
hci_stack->acl_data_packet_length = btstack_min(acl_len, HCI_ACL_PAYLOAD_SIZE);
hci_stack->sco_data_packet_length = btstack_min(sco_len, HCI_ACL_PAYLOAD_SIZE);
hci_stack->acl_packets_total_num = little_endian_read_16(packet, 9);
hci_stack->sco_packets_total_num = little_endian_read_16(packet, 11);
log_info("hci_read_buffer_size: ACL size module %u -> used %u, count %u / SCO size %u, count %u",
acl_len, hci_stack->acl_data_packet_length, hci_stack->acl_packets_total_num,
hci_stack->sco_data_packet_length, hci_stack->sco_packets_total_num);
}
}
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_rssi)){
if (packet[5]) return;
uint8_t event[5];
event[0] = GAP_EVENT_RSSI_MEASUREMENT;
event[1] = 3;
(void)memcpy(&event[2], &packet[6], 3);
hci_emit_event(event, sizeof(event), 1);
}
#ifdef ENABLE_BLE
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_le_read_buffer_size)){
hci_stack->le_data_packets_length = little_endian_read_16(packet, 6);
hci_stack->le_acl_packets_total_num = packet[8];
// determine usable ACL payload size
if (HCI_ACL_PAYLOAD_SIZE < hci_stack->le_data_packets_length){
hci_stack->le_data_packets_length = HCI_ACL_PAYLOAD_SIZE;
}
log_info("hci_le_read_buffer_size: size %u, count %u", hci_stack->le_data_packets_length, hci_stack->le_acl_packets_total_num);
}
#endif
#ifdef ENABLE_LE_DATA_LENGTH_EXTENSION
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_le_read_maximum_data_length)){
hci_stack->le_supported_max_tx_octets = little_endian_read_16(packet, 6);
hci_stack->le_supported_max_tx_time = little_endian_read_16(packet, 8);
log_info("hci_le_read_maximum_data_length: tx octets %u, tx time %u us", hci_stack->le_supported_max_tx_octets, hci_stack->le_supported_max_tx_time);
}
#endif
#ifdef ENABLE_LE_CENTRAL
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_le_read_white_list_size)){
hci_stack->le_whitelist_capacity = packet[6];
log_info("hci_le_read_white_list_size: size %u", hci_stack->le_whitelist_capacity);
}
#endif
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_bd_addr)) {
reverse_bd_addr(&packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE + 1],
hci_stack->local_bd_addr);
log_info("Local Address, Status: 0x%02x: Addr: %s",
packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE], bd_addr_to_str(hci_stack->local_bd_addr));
#ifdef ENABLE_CLASSIC
if (hci_stack->link_key_db){
hci_stack->link_key_db->set_local_bd_addr(hci_stack->local_bd_addr);
}
#endif
}
#ifdef ENABLE_CLASSIC
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_write_scan_enable)){
hci_emit_discoverable_enabled(hci_stack->discoverable);
}
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_inquiry_cancel)){
if (hci_stack->inquiry_state == GAP_INQUIRY_STATE_W4_CANCELLED){
hci_stack->inquiry_state = GAP_INQUIRY_STATE_IDLE;
uint8_t event[] = { GAP_EVENT_INQUIRY_COMPLETE, 1, 0};
hci_emit_event(event, sizeof(event), 1);
}
}
#endif
// Note: HCI init checks
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_supported_features)){
(void)memcpy(hci_stack->local_supported_features, &packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE + 1], 8);
#ifdef ENABLE_CLASSIC
// determine usable ACL packet types based on host buffer size and supported features
hci_stack->packet_types = hci_acl_packet_types_for_buffer_size_and_local_features(HCI_ACL_PAYLOAD_SIZE, &hci_stack->local_supported_features[0]);
log_info("Packet types %04x, eSCO %u", hci_stack->packet_types, hci_extended_sco_link_supported());
#endif
// Classic/LE
log_info("BR/EDR support %u, LE support %u", hci_classic_supported(), hci_le_supported());
}
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information)){
// hci_stack->hci_version = little_endian_read_16(packet, 4);
// hci_stack->hci_revision = little_endian_read_16(packet, 6);
uint16_t manufacturer = little_endian_read_16(packet, 10);
// map Cypress to Broadcom
if (manufacturer == BLUETOOTH_COMPANY_ID_CYPRESS_SEMICONDUCTOR){
log_info("Treat Cypress as Broadcom");
manufacturer = BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION;
little_endian_store_16(packet, 10, manufacturer);
}
hci_stack->manufacturer = manufacturer;
// hci_stack->lmp_version = little_endian_read_16(packet, 8);
// hci_stack->lmp_subversion = little_endian_read_16(packet, 12);
log_info("Manufacturer: 0x%04x", hci_stack->manufacturer);
}
else 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) | // bit 0 = Octet 14, bit 7 / Read Buffer Size
((packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+24] & 0x40) >> 5) | // bit 1 = Octet 24, bit 6 / Write Le Host Supported
((packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+10] & 0x10) >> 2) | // bit 2 = Octet 10, bit 4 / Write Synchronous Flow Control Enable
((packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+18] & 0x08) ) | // bit 3 = Octet 18, bit 3 / Write Default Erroneous Data Reporting
((packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+34] & 0x01) << 4) | // bit 4 = Octet 34, bit 0 / LE Write Suggested Default Data Length
((packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+35] & 0x08) << 2) | // bit 5 = Octet 35, bit 3 / LE Read Maximum Data Length
((packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+35] & 0x20) << 1) | // bit 6 = Octet 35, bit 5 / LE Set Default PHY
((packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+20] & 0x10) << 3); // bit 7 = Octet 20, bit 4 / Read Encryption Key Size
hci_stack->local_supported_commands[1] =
((packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+ 2] & 0x40) >> 6) | // bit 8 = Octet 2, bit 6 / Read Remote Extended Features
((packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+32] & 0x08) >> 2); // bit 9 = Octet 32, bit 3 / Write Secure Connections Host
log_info("Local supported commands summary %02x - %02x", hci_stack->local_supported_commands[0], hci_stack->local_supported_commands[1]);
}
#ifdef ENABLE_CLASSIC
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_write_synchronous_flow_control_enable)){
if (packet[5]) return;
hci_stack->synchronous_flow_control_enabled = 1;
}
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_encryption_key_size)){
uint8_t status = packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE];
handle = little_endian_read_16(packet, OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1);
conn = hci_connection_for_handle(handle);
if (!conn) return;
uint8_t key_size = 0;
if (status == 0){
key_size = packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+3];
log_info("Handle %x04x key Size: %u", handle, key_size);
} else {
log_info("Read Encryption Key Size failed 0x%02x-> assuming insecure connection with key size of 1", status);
}
hci_handle_read_encryption_key_size_complete(conn, key_size);
}
#endif
}
static void event_handler(uint8_t *packet, int size){
uint16_t event_length = packet[1];
@ -2005,155 +2157,7 @@ static void event_handler(uint8_t *packet, int size){
switch (hci_event_packet_get_type(packet)) {
case HCI_EVENT_COMMAND_COMPLETE:
// get num cmd packets - limit to 1 to reduce complexity
hci_stack->num_cmd_packets = packet[2] ? 1 : 0;
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_name)){
if (packet[5]) break;
// terminate, name 248 chars
packet[6+248] = 0;
log_info("local name: %s", &packet[6]);
}
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_buffer_size)){
// "The HC_ACL_Data_Packet_Length return parameter will be used to determine the size of the L2CAP segments contained in ACL Data Packets"
if (hci_stack->state == HCI_STATE_INITIALIZING){
uint16_t acl_len = little_endian_read_16(packet, 6);
uint16_t sco_len = packet[8];
// determine usable ACL/SCO payload size
hci_stack->acl_data_packet_length = btstack_min(acl_len, HCI_ACL_PAYLOAD_SIZE);
hci_stack->sco_data_packet_length = btstack_min(sco_len, HCI_ACL_PAYLOAD_SIZE);
hci_stack->acl_packets_total_num = little_endian_read_16(packet, 9);
hci_stack->sco_packets_total_num = little_endian_read_16(packet, 11);
log_info("hci_read_buffer_size: ACL size module %u -> used %u, count %u / SCO size %u, count %u",
acl_len, hci_stack->acl_data_packet_length, hci_stack->acl_packets_total_num,
hci_stack->sco_data_packet_length, hci_stack->sco_packets_total_num);
}
}
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_rssi)){
if (packet[5] == 0){
uint8_t event[5];
event[0] = GAP_EVENT_RSSI_MEASUREMENT;
event[1] = 3;
(void)memcpy(&event[2], &packet[6], 3);
hci_emit_event(event, sizeof(event), 1);
}
}
#ifdef ENABLE_BLE
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_le_read_buffer_size)){
hci_stack->le_data_packets_length = little_endian_read_16(packet, 6);
hci_stack->le_acl_packets_total_num = packet[8];
// determine usable ACL payload size
if (HCI_ACL_PAYLOAD_SIZE < hci_stack->le_data_packets_length){
hci_stack->le_data_packets_length = HCI_ACL_PAYLOAD_SIZE;
}
log_info("hci_le_read_buffer_size: size %u, count %u", hci_stack->le_data_packets_length, hci_stack->le_acl_packets_total_num);
}
#endif
#ifdef ENABLE_LE_DATA_LENGTH_EXTENSION
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_le_read_maximum_data_length)){
hci_stack->le_supported_max_tx_octets = little_endian_read_16(packet, 6);
hci_stack->le_supported_max_tx_time = little_endian_read_16(packet, 8);
log_info("hci_le_read_maximum_data_length: tx octets %u, tx time %u us", hci_stack->le_supported_max_tx_octets, hci_stack->le_supported_max_tx_time);
}
#endif
#ifdef ENABLE_LE_CENTRAL
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_le_read_white_list_size)){
hci_stack->le_whitelist_capacity = packet[6];
log_info("hci_le_read_white_list_size: size %u", hci_stack->le_whitelist_capacity);
}
#endif
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_bd_addr)) {
reverse_bd_addr(&packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE + 1],
hci_stack->local_bd_addr);
log_info("Local Address, Status: 0x%02x: Addr: %s",
packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE], bd_addr_to_str(hci_stack->local_bd_addr));
#ifdef ENABLE_CLASSIC
if (hci_stack->link_key_db){
hci_stack->link_key_db->set_local_bd_addr(hci_stack->local_bd_addr);
}
#endif
}
#ifdef ENABLE_CLASSIC
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_write_scan_enable)){
hci_emit_discoverable_enabled(hci_stack->discoverable);
}
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_inquiry_cancel)){
if (hci_stack->inquiry_state == GAP_INQUIRY_STATE_W4_CANCELLED){
hci_stack->inquiry_state = GAP_INQUIRY_STATE_IDLE;
uint8_t event[] = { GAP_EVENT_INQUIRY_COMPLETE, 1, 0};
hci_emit_event(event, sizeof(event), 1);
}
}
#endif
// Note: HCI init checks
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_supported_features)){
(void)memcpy(hci_stack->local_supported_features,
&packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE + 1],
8);
#ifdef ENABLE_CLASSIC
// determine usable ACL packet types based on host buffer size and supported features
hci_stack->packet_types = hci_acl_packet_types_for_buffer_size_and_local_features(HCI_ACL_PAYLOAD_SIZE, &hci_stack->local_supported_features[0]);
log_info("Packet types %04x, eSCO %u", hci_stack->packet_types, hci_extended_sco_link_supported());
#endif
// Classic/LE
log_info("BR/EDR support %u, LE support %u", hci_classic_supported(), hci_le_supported());
}
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information)){
// hci_stack->hci_version = little_endian_read_16(packet, 4);
// hci_stack->hci_revision = little_endian_read_16(packet, 6);
uint16_t manufacturer = little_endian_read_16(packet, 10);
// map Cypress to Broadcom
if (manufacturer == BLUETOOTH_COMPANY_ID_CYPRESS_SEMICONDUCTOR){
log_info("Treat Cypress as Broadcom");
manufacturer = BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION;
little_endian_store_16(packet, 10, manufacturer);
}
hci_stack->manufacturer = manufacturer;
// hci_stack->lmp_version = little_endian_read_16(packet, 8);
// hci_stack->lmp_subversion = little_endian_read_16(packet, 12);
log_info("Manufacturer: 0x%04x", hci_stack->manufacturer);
}
else 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) | // bit 0 = Octet 14, bit 7 / Read Buffer Size
((packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+24] & 0x40) >> 5) | // bit 1 = Octet 24, bit 6 / Write Le Host Supported
((packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+10] & 0x10) >> 2) | // bit 2 = Octet 10, bit 4 / Write Synchronous Flow Control Enable
((packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+18] & 0x08) ) | // bit 3 = Octet 18, bit 3 / Write Default Erroneous Data Reporting
((packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+34] & 0x01) << 4) | // bit 4 = Octet 34, bit 0 / LE Write Suggested Default Data Length
((packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+35] & 0x08) << 2) | // bit 5 = Octet 35, bit 3 / LE Read Maximum Data Length
((packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+35] & 0x20) << 1) | // bit 6 = Octet 35, bit 5 / LE Set Default PHY
((packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+20] & 0x10) << 3); // bit 7 = Octet 20, bit 4 / Read Encryption Key Size
hci_stack->local_supported_commands[1] =
((packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+ 2] & 0x40) >> 6) | // bit 8 = Octet 2, bit 6 / Read Remote Extended Features
((packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+32] & 0x08) >> 2); // bit 9 = Octet 32, bit 3 / Write Secure Connections Host
log_info("Local supported commands summary %02x - %02x", hci_stack->local_supported_commands[0], hci_stack->local_supported_commands[1]);
}
#ifdef ENABLE_CLASSIC
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_write_synchronous_flow_control_enable)){
if (packet[5] == 0){
hci_stack->synchronous_flow_control_enabled = 1;
}
}
else if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_encryption_key_size)){
uint8_t status = packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE];
handle = little_endian_read_16(packet, OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1);
conn = hci_connection_for_handle(handle);
if (!conn) break;
uint8_t key_size = 0;
if (status == 0){
key_size = packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+3];
log_info("Handle %x04x key Size: %u", handle, key_size);
} else {
log_info("Read Encryption Key Size failed 0x%02x-> assuming insecure connection with key size of 1", status);
}
hci_handle_read_encryption_key_size_complete(conn, key_size);
}
#endif
handle_command_complete_event(packet, size);
break;
case HCI_EVENT_COMMAND_STATUS: