From d6b06661159f27ddc0293fa2a7eaba2d8924e39f Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Wed, 3 Feb 2016 12:23:16 +0100 Subject: [PATCH] hci: add hci_add_event_handler, tunnel events through hci_emit_event and acl packets through hci_emit_acl_packet --- src/hci.c | 77 ++++++++++++++++++++++++++++++------------------------- src/hci.h | 14 +++++++--- 2 files changed, 52 insertions(+), 39 deletions(-) diff --git a/src/hci.c b/src/hci.c index a4ef70475..d0ea69315 100644 --- a/src/hci.c +++ b/src/hci.c @@ -87,6 +87,10 @@ void le_handle_advertisement_report(uint8_t *packet, int size); static void hci_remove_from_whitelist(bd_addr_type_t address_type, bd_addr_t address); #endif +// prototypes +static void hci_emit_event(uint8_t * event, uint16_t size, int dump); +static void hci_emit_acl_packet(uint8_t * packet, uint16_t size); + // the STACK is here #ifndef HAVE_MALLOC static hci_stack_t hci_stack_static; @@ -509,7 +513,7 @@ static int hci_send_acl_packet_fragments(hci_connection_t *connection){ hci_release_packet_buffer(); // notify upper stack that iit might be possible to send again uint8_t event[] = { DAEMON_EVENT_HCI_PACKET_SENT, 0}; - hci_stack->packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event)); + hci_emit_event(&event[0], sizeof(event), 0); // don't dump } return err; @@ -592,7 +596,7 @@ int hci_send_sco_packet_buffer(int size){ hci_release_packet_buffer(); // notify upper stack that iit might be possible to send again uint8_t event[] = { DAEMON_EVENT_HCI_PACKET_SENT, 0}; - hci_stack->packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event)); + hci_emit_event(&event[0], sizeof(event), 0); // don't dump } return err; @@ -649,8 +653,7 @@ static void acl_handler(uint8_t *packet, int size){ // forward complete L2CAP packet if complete. if (conn->acl_recombination_pos >= conn->acl_recombination_length + 4 + 4){ // pos already incl. ACL header - - hci_stack->packet_handler(HCI_ACL_DATA_PACKET, &conn->acl_recombination_buffer[HCI_INCOMING_PRE_BUFFER_SIZE], conn->acl_recombination_pos); + hci_emit_acl_packet(&conn->acl_recombination_buffer[HCI_INCOMING_PRE_BUFFER_SIZE], conn->acl_recombination_pos); // reset recombination buffer conn->acl_recombination_length = 0; conn->acl_recombination_pos = 0; @@ -672,10 +675,8 @@ static void acl_handler(uint8_t *packet, int size){ // compare fragment size to L2CAP packet size if (acl_length >= l2cap_length + 4){ - // forward fragment as L2CAP packet - hci_stack->packet_handler(HCI_ACL_DATA_PACKET, packet, acl_length + 4); - + hci_emit_acl_packet(packet, acl_length + 4); } else { if (acl_length > HCI_ACL_BUFFER_SIZE){ @@ -830,8 +831,7 @@ void le_handle_advertisement_report(uint8_t *packet, int size){ memcpy(&event[pos], &packet[offset], data_length); pos += data_length; offset += data_length + 1; // rssi - hci_dump_packet( HCI_EVENT_PACKET, 0, event, pos); - hci_stack->packet_handler(HCI_EVENT_PACKET, event, pos); + hci_emit_event(event, pos, 1); } } #endif @@ -1759,8 +1759,8 @@ static void event_handler(uint8_t *packet, int size){ } // notify upper stack - hci_stack->packet_handler(HCI_EVENT_PACKET, packet, size); - + hci_emit_event(packet, size, 0); // don't dump, already happened in packet handler + // moved here to give upper stack a chance to close down everything with hci_connection_t intact if (packet[0] == HCI_EVENT_DISCONNECTION_COMPLETE){ if (!packet[2]){ @@ -1805,6 +1805,14 @@ static void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){ } } +/** + * @brief Add event packet handler. + */ +void hci_add_event_handler(btstack_packet_callback_registration_t * callback_handler){ + btstack_linked_list_add_tail(&hci_stack->event_handlers, (btstack_linked_item_t*) callback_handler); +} + + /** Register HCI packet handlers */ void hci_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){ hci_stack->packet_handler = handler; @@ -2870,14 +2878,24 @@ int hci_send_cmd(const hci_cmd_t *cmd, ...){ // Create various non-HCI events. // TODO: generalize, use table similar to hci_create_command +static void hci_emit_event(uint8_t * event, uint16_t size, int dump){ + if (dump) { + hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); + } + hci_stack->packet_handler(HCI_EVENT_PACKET, event, sizeof(event)); +} + +static void hci_emit_acl_packet(uint8_t * packet, uint16_t size){ + hci_stack->packet_handler(HCI_ACL_DATA_PACKET, packet, size); +} + void hci_emit_state(void){ log_info("BTSTACK_EVENT_STATE %u", hci_stack->state); uint8_t event[3]; event[0] = BTSTACK_EVENT_STATE; event[1] = sizeof(event) - 2; event[2] = hci_stack->state; - hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); - hci_stack->packet_handler(HCI_EVENT_PACKET, event, sizeof(event)); + hci_emit_event(event, sizeof(event), 1); } void hci_emit_connection_complete(hci_connection_t *conn, uint8_t status){ @@ -2889,8 +2907,7 @@ void hci_emit_connection_complete(hci_connection_t *conn, uint8_t status){ bt_flip_addr(&event[5], conn->address); event[11] = 1; // ACL connection event[12] = 0; // encryption disabled - hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event)); - hci_stack->packet_handler(HCI_EVENT_PACKET, event, sizeof(event)); + hci_emit_event(event, sizeof(event), 1); } static void hci_emit_le_connection_complete(uint8_t address_type, bd_addr_t address, uint16_t conn_handle, uint8_t status){ @@ -2907,8 +2924,7 @@ static void hci_emit_le_connection_complete(uint8_t address_type, bd_addr_t addr little_endian_store_16(event, 16, 0); // latency little_endian_store_16(event, 18, 0); // supervision timeout event[20] = 0; // master clock accuracy - hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event)); - hci_stack->packet_handler(HCI_EVENT_PACKET, event, sizeof(event)); + hci_emit_event(event, sizeof(event), 1); } void hci_emit_disconnection_complete(uint16_t handle, uint8_t reason){ @@ -2918,8 +2934,7 @@ void hci_emit_disconnection_complete(uint16_t handle, uint8_t reason){ event[2] = 0; // status = OK little_endian_store_16(event, 3, handle); event[5] = reason; - hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event)); - hci_stack->packet_handler(HCI_EVENT_PACKET, event, sizeof(event)); + hci_emit_event(event, sizeof(event), 1); } void hci_emit_l2cap_check_timeout(hci_connection_t *conn){ @@ -2929,8 +2944,7 @@ void hci_emit_l2cap_check_timeout(hci_connection_t *conn){ event[0] = L2CAP_EVENT_TIMEOUT_CHECK; event[1] = sizeof(event) - 2; little_endian_store_16(event, 2, conn->con_handle); - hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event)); - hci_stack->packet_handler(HCI_EVENT_PACKET, event, sizeof(event)); + hci_emit_event(event, sizeof(event), 1); } void hci_emit_nr_connections_changed(void){ @@ -2939,8 +2953,7 @@ void hci_emit_nr_connections_changed(void){ event[0] = BTSTACK_EVENT_NR_CONNECTIONS_CHANGED; event[1] = sizeof(event) - 2; event[2] = nr_hci_connections(); - hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); - hci_stack->packet_handler(HCI_EVENT_PACKET, event, sizeof(event)); + hci_emit_event(event, sizeof(event), 1); } void hci_emit_hci_open_failed(void){ @@ -2948,8 +2961,7 @@ void hci_emit_hci_open_failed(void){ uint8_t event[2]; event[0] = BTSTACK_EVENT_POWERON_FAILED; event[1] = sizeof(event) - 2; - hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); - hci_stack->packet_handler(HCI_EVENT_PACKET, event, sizeof(event)); + hci_emit_event(event, sizeof(event), 1); } void hci_emit_system_bluetooth_enabled(uint8_t enabled){ @@ -2958,8 +2970,7 @@ void hci_emit_system_bluetooth_enabled(uint8_t enabled){ event[0] = BTSTACK_EVENT_SYSTEM_BLUETOOTH_ENABLED; event[1] = sizeof(event) - 2; event[2] = enabled; - hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); - hci_stack->packet_handler(HCI_EVENT_PACKET, event, sizeof(event)); + hci_emit_event(event, sizeof(event), 1); } void hci_emit_remote_name_cached(bd_addr_t addr, device_name_t *name){ @@ -2973,8 +2984,7 @@ void hci_emit_remote_name_cached(bd_addr_t addr, device_name_t *name){ event[9+248] = 0; // assert \0 for log_info log_info("BTSTACK_EVENT_REMOTE_NAME_CACHED %s = '%s'", bd_addr_to_str(addr), &event[9]); - hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event)-1); - hci_stack->packet_handler(HCI_EVENT_PACKET, event, sizeof(event)-1); + hci_emit_event(event, sizeof(event), 1); } void hci_emit_discoverable_enabled(uint8_t enabled){ @@ -2983,8 +2993,7 @@ void hci_emit_discoverable_enabled(uint8_t enabled){ event[0] = BTSTACK_EVENT_DISCOVERABLE_ENABLED; event[1] = sizeof(event) - 2; event[2] = enabled; - hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); - hci_stack->packet_handler(HCI_EVENT_PACKET, event, sizeof(event)); + hci_emit_event(event, sizeof(event), 1); } void hci_emit_security_level(hci_con_handle_t con_handle, gap_security_level_t level){ @@ -2996,8 +3005,7 @@ void hci_emit_security_level(hci_con_handle_t con_handle, gap_security_level_t l little_endian_store_16(event, 2, con_handle); pos += 2; event[pos++] = level; - hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); - hci_stack->packet_handler(HCI_EVENT_PACKET, event, sizeof(event)); + hci_emit_event(event, sizeof(event), 1); } void hci_emit_dedicated_bonding_result(bd_addr_t address, uint8_t status){ @@ -3009,8 +3017,7 @@ void hci_emit_dedicated_bonding_result(bd_addr_t address, uint8_t status){ event[pos++] = status; bt_flip_addr( &event[pos], address); pos += 6; - hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); - hci_stack->packet_handler(HCI_EVENT_PACKET, event, sizeof(event)); + hci_emit_event(event, sizeof(event), 1); } // query if remote side supports eSCO diff --git a/src/hci.h b/src/hci.h index 9a568f8e6..f85dc7537 100644 --- a/src/hci.h +++ b/src/hci.h @@ -101,7 +101,6 @@ extern "C" { // #define IS_COMMAND(packet, command) (little_endian_read_16(packet,0) == command.opcode) - /** * LE connection parameter update state */ @@ -523,6 +522,9 @@ typedef struct { // hardware power controller const btstack_control_t * control; + /* link key db */ + const btstack_link_key_db_t * link_key_db; + // basic configuration const char * local_name; uint32_t class_of_device; @@ -531,7 +533,6 @@ typedef struct { uint8_t ssp_io_capability; uint8_t ssp_authentication_requirement; uint8_t ssp_auto_accept; - // list of existing baseband connections btstack_linked_list_t connections; @@ -577,8 +578,8 @@ typedef struct { /* callback for SCO data */ void (*sco_packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size); - /* link key db */ - btstack_link_key_db_t const * link_key_db; + /* callbacks for events */ + btstack_linked_list_t event_handlers; /* hci state machine */ HCI_STATE state; @@ -784,6 +785,11 @@ void hci_set_class_of_device(uint32_t class_of_device); */ void hci_set_bd_addr(bd_addr_t addr); +/** + * @brief Add event packet handler. + */ +void hci_add_event_handler(btstack_packet_callback_registration_t * callback_handler); + /** * @brief Registers a packet handler. Used if L2CAP is not used (rarely). */