diff --git a/components/bt/host/bluedroid/hci/hci_layer.c b/components/bt/host/bluedroid/hci/hci_layer.c index 0365c45f93..8d79043dd4 100644 --- a/components/bt/host/bluedroid/hci/hci_layer.c +++ b/components/bt/host/bluedroid/hci/hci_layer.c @@ -35,6 +35,7 @@ #include "osi/thread.h" #include "osi/mutex.h" #include "osi/fixed_queue.h" +#include "osi/fixed_pkt_queue.h" #define HCI_HOST_TASK_PINNED_TO_CORE (TASK_PINNED_TO_CORE) #define HCI_HOST_TASK_STACK_SIZE (2048 + BT_TASK_EXTRA_STACK_SIZE) @@ -44,15 +45,6 @@ #define HCI_HOST_TASK_WORKQUEUE0_LEN (0) #define HCI_HOST_TASK_WORKQUEUE1_LEN (5) -typedef struct { - uint16_t opcode; - future_t *complete_future; - command_complete_cb complete_callback; - command_status_cb status_callback; - void *context; - BT_HDR *command; -} waiting_command_t; - typedef struct { bool timer_is_set; osi_alarm_t *command_response_timer; @@ -62,7 +54,7 @@ typedef struct { typedef struct { int command_credits; - fixed_queue_t *command_queue; + fixed_pkt_queue_t *command_queue; fixed_queue_t *packet_queue; command_waiting_response_t cmd_waiting_q; @@ -93,14 +85,14 @@ static const packet_fragmenter_callbacks_t packet_fragmenter_callbacks; static int hci_layer_init_env(void); static void hci_layer_deinit_env(void); static void hci_host_thread_handler(void *arg); -static void event_command_ready(fixed_queue_t *queue); +static void event_command_ready(fixed_pkt_queue_t *queue); static void event_packet_ready(fixed_queue_t *queue); static void restart_command_waiting_response_timer(command_waiting_response_t *cmd_wait_q); static void command_timed_out(void *context); static void hal_says_packet_ready(BT_HDR *packet); static bool filter_incoming_event(BT_HDR *packet); static serial_data_type_t event_to_data_type(uint16_t event); -static waiting_command_t *get_waiting_command(command_opcode_t opcode); +static pkt_linked_item_t *get_waiting_command(command_opcode_t opcode); static void dispatch_reassembled(BT_HDR *packet); static void dispatch_adv_report(pkt_linked_item_t *linked_pkt); @@ -156,9 +148,9 @@ static int hci_layer_init_env(void) // as per the Bluetooth spec, Volume 2, Part E, 4.4 (Command Flow Control) // This value can change when you get a command complete or command status event. hci_host_env.command_credits = 1; - hci_host_env.command_queue = fixed_queue_new(QUEUE_SIZE_MAX); + hci_host_env.command_queue = fixed_pkt_queue_new(QUEUE_SIZE_MAX); if (hci_host_env.command_queue) { - fixed_queue_register_dequeue(hci_host_env.command_queue, event_command_ready); + fixed_pkt_queue_register_dequeue(hci_host_env.command_queue, event_command_ready); } else { HCI_TRACE_ERROR("%s unable to create pending command queue.", __func__); return -1; @@ -198,7 +190,7 @@ static void hci_layer_deinit_env(void) command_waiting_response_t *cmd_wait_q; if (hci_host_env.command_queue) { - fixed_queue_free(hci_host_env.command_queue, osi_free_func); + fixed_pkt_queue_free(hci_host_env.command_queue, (fixed_pkt_queue_free_cb)osi_free_func); } if (hci_host_env.packet_queue) { fixed_queue_free(hci_host_env.packet_queue, osi_free_func); @@ -230,9 +222,9 @@ static void hci_host_thread_handler(void *arg) if (pkt != NULL) { packet_fragmenter->fragment_and_dispatch(pkt); } else { - if (!fixed_queue_is_empty(hci_host_env.command_queue) && + if (!fixed_pkt_queue_is_empty(hci_host_env.command_queue) && hci_host_env.command_credits > 0) { - fixed_queue_process(hci_host_env.command_queue); + fixed_pkt_queue_process(hci_host_env.command_queue); } else if (!fixed_queue_is_empty(hci_host_env.packet_queue)) { fixed_queue_process(hci_host_env.packet_queue); } @@ -246,48 +238,38 @@ static void transmit_command( command_status_cb status_callback, void *context) { - uint8_t *stream; - waiting_command_t *wait_entry = osi_calloc(sizeof(waiting_command_t)); - if (!wait_entry) { - HCI_TRACE_ERROR("%s couldn't allocate space for wait entry.", __func__); - return; - } - - stream = command->data + command->offset; - STREAM_TO_UINT16(wait_entry->opcode, stream); - wait_entry->complete_callback = complete_callback; - wait_entry->status_callback = status_callback; - wait_entry->command = command; - wait_entry->context = context; + hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(command); + pkt_linked_item_t *linked_pkt = HCI_GET_CMD_LINKED_STRUCT(metadata); + assert(command->layer_specific == HCI_CMD_BUF_TYPE_METADATA); // Store the command message type in the event field // in case the upper layer didn't already command->event = MSG_STACK_TO_HC_HCI_CMD; - HCI_TRACE_DEBUG("HCI Enqueue Comamnd opcode=0x%x\n", wait_entry->opcode); + HCI_TRACE_DEBUG("HCI Enqueue Comamnd opcode=0x%x\n", metadata->opcode); BTTRC_DUMP_BUFFER(NULL, command->data + command->offset, command->len); - fixed_queue_enqueue(hci_host_env.command_queue, wait_entry, FIXED_QUEUE_MAX_TIMEOUT); + fixed_pkt_queue_enqueue(hci_host_env.command_queue, linked_pkt, FIXED_PKT_QUEUE_MAX_TIMEOUT); hci_host_task_post(OSI_THREAD_MAX_TIMEOUT); } static future_t *transmit_command_futured(BT_HDR *command) { - waiting_command_t *wait_entry = osi_calloc(sizeof(waiting_command_t)); - assert(wait_entry != NULL); + hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(command); + pkt_linked_item_t *linked_pkt = HCI_GET_CMD_LINKED_STRUCT(metadata); + + assert(command->layer_specific == HCI_CMD_BUF_TYPE_METADATA); + metadata->flags_vnd |= HCI_CMD_MSG_F_VND_FUTURE; future_t *future = future_new(); - uint8_t *stream = command->data + command->offset; - STREAM_TO_UINT16(wait_entry->opcode, stream); - wait_entry->complete_future = future; - wait_entry->command = command; + metadata->complete_future = future; // Store the command message type in the event field // in case the upper layer didn't already command->event = MSG_STACK_TO_HC_HCI_CMD; - fixed_queue_enqueue(hci_host_env.command_queue, wait_entry, FIXED_QUEUE_MAX_TIMEOUT); + fixed_pkt_queue_enqueue(hci_host_env.command_queue, linked_pkt, FIXED_PKT_QUEUE_MAX_TIMEOUT); hci_host_task_post(OSI_THREAD_MAX_TIMEOUT); return future; } @@ -295,8 +277,8 @@ static future_t *transmit_command_futured(BT_HDR *command) static void transmit_downward(uint16_t type, void *data) { if (type == MSG_STACK_TO_HC_HCI_CMD) { - transmit_command((BT_HDR *)data, NULL, NULL, NULL); - HCI_TRACE_WARNING("%s legacy transmit of command. Use transmit_command instead.\n", __func__); + HCI_TRACE_ERROR("%s legacy transmit of command. Use transmit_command instead.\n", __func__); + assert(0); } else { fixed_queue_enqueue(hci_host_env.packet_queue, data, FIXED_QUEUE_MAX_TIMEOUT); } @@ -306,21 +288,18 @@ static void transmit_downward(uint16_t type, void *data) // Command/packet transmitting functions -static void event_command_ready(fixed_queue_t *queue) +static void event_command_ready(fixed_pkt_queue_t *queue) { - waiting_command_t *wait_entry = NULL; + pkt_linked_item_t *wait_entry = NULL; command_waiting_response_t *cmd_wait_q = &hci_host_env.cmd_waiting_q; - wait_entry = fixed_queue_dequeue(queue, FIXED_QUEUE_MAX_TIMEOUT); + wait_entry = fixed_pkt_queue_dequeue(queue, FIXED_QUEUE_MAX_TIMEOUT); - if(wait_entry->opcode == HCI_HOST_NUM_PACKETS_DONE -#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) - || wait_entry->opcode == HCI_VENDOR_BLE_ADV_REPORT_FLOW_CONTROL -#endif - ){ - packet_fragmenter->fragment_and_dispatch(wait_entry->command); - osi_free(wait_entry->command); - osi_free(wait_entry); + hci_cmd_metadata_t *metadata = (hci_cmd_metadata_t *)(wait_entry->data); + if (metadata->flags_src & HCI_CMD_MSG_F_SRC_NOACK) { + packet_fragmenter->fragment_and_dispatch(&metadata->command); + hci_cmd_free_cb free_func = metadata->command_free_cb ? metadata->command_free_cb : (hci_cmd_free_cb) osi_free_func; + free_func(wait_entry); return; } hci_host_env.command_credits--; @@ -330,7 +309,7 @@ static void event_command_ready(fixed_queue_t *queue) osi_mutex_unlock(&cmd_wait_q->commands_pending_response_lock); // Send it off - packet_fragmenter->fragment_and_dispatch(wait_entry->command); + packet_fragmenter->fragment_and_dispatch(&metadata->command); restart_command_waiting_response_timer(cmd_wait_q); } @@ -395,7 +374,7 @@ static void restart_command_waiting_response_timer(command_waiting_response_t *c static void command_timed_out(void *context) { command_waiting_response_t *cmd_wait_q = (command_waiting_response_t *)context; - waiting_command_t *wait_entry; + pkt_linked_item_t *wait_entry; osi_mutex_lock(&cmd_wait_q->commands_pending_response_lock, OSI_MUTEX_MAX_TIMEOUT); wait_entry = (list_is_empty(cmd_wait_q->commands_pending_response) ? @@ -408,7 +387,8 @@ static void command_timed_out(void *context) // We shouldn't try to recover the stack from this command timeout. // If it's caused by a software bug, fix it. If it's a hardware bug, fix it. { - HCI_TRACE_ERROR("%s hci layer timeout waiting for response to a command. opcode: 0x%x", __func__, wait_entry->opcode); + hci_cmd_metadata_t *metadata = (hci_cmd_metadata_t *)(wait_entry->data); + HCI_TRACE_ERROR("%s hci layer timeout waiting for response to a command. opcode: 0x%x", __func__, metadata->opcode); } } @@ -432,7 +412,8 @@ static void hal_says_adv_rpt_ready(pkt_linked_item_t *linked_pkt) // information, like how many commands are now able to be sent. static bool filter_incoming_event(BT_HDR *packet) { - waiting_command_t *wait_entry = NULL; + pkt_linked_item_t *wait_entry = NULL; + hci_cmd_metadata_t *metadata = NULL; uint8_t *stream = packet->data + packet->offset; uint8_t event_code; command_opcode_t opcode; @@ -446,10 +427,11 @@ static bool filter_incoming_event(BT_HDR *packet) STREAM_TO_UINT8(hci_host_env.command_credits, stream); STREAM_TO_UINT16(opcode, stream); wait_entry = get_waiting_command(opcode); + metadata = (hci_cmd_metadata_t *)(wait_entry->data); if (!wait_entry) { HCI_TRACE_WARNING("%s command complete event with no matching command. opcode: 0x%x.", __func__, opcode); - } else if (wait_entry->complete_callback) { - wait_entry->complete_callback(packet, wait_entry->context); + } else if (metadata->command_complete_cb) { + metadata->command_complete_cb(packet, metadata->context); #if (BLE_50_FEATURE_SUPPORT == TRUE) BlE_SYNC *sync_info = btsnd_hcic_ble_get_sync_info(); if(!sync_info) { @@ -461,8 +443,8 @@ static bool filter_incoming_event(BT_HDR *packet) } } #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) - } else if (wait_entry->complete_future) { - future_ready(wait_entry->complete_future, packet); + } else if (metadata->flags_vnd & HCI_CMD_MSG_F_VND_FUTURE) { + future_ready((future_t *)(metadata->complete_future), packet); } goto intercepted; @@ -475,10 +457,11 @@ static bool filter_incoming_event(BT_HDR *packet) // If a command generates a command status event, it won't be getting a command complete event wait_entry = get_waiting_command(opcode); + metadata = (hci_cmd_metadata_t *)(wait_entry->data); if (!wait_entry) { HCI_TRACE_WARNING("%s command status event with no matching command. opcode: 0x%x", __func__, opcode); - } else if (wait_entry->status_callback) { - wait_entry->status_callback(status, wait_entry->command, wait_entry->context); + } else if (metadata->command_status_cb) { + metadata->command_status_cb(status, &metadata->command, metadata->context); } goto intercepted; @@ -490,23 +473,22 @@ intercepted: /*Tell HCI Host Task to continue TX Pending commands*/ if (hci_host_env.command_credits && - !fixed_queue_is_empty(hci_host_env.command_queue)) { + !fixed_pkt_queue_is_empty(hci_host_env.command_queue)) { hci_host_task_post(OSI_THREAD_MAX_TIMEOUT); } if (wait_entry) { // If it has a callback, it's responsible for freeing the packet if (event_code == HCI_COMMAND_STATUS_EVT || - (!wait_entry->complete_callback && !wait_entry->complete_future)) { + (!metadata->command_complete_cb && !metadata->complete_future)) { osi_free(packet); } // If it has a callback, it's responsible for freeing the command - if (event_code == HCI_COMMAND_COMPLETE_EVT || !wait_entry->status_callback) { - osi_free(wait_entry->command); + if (event_code == HCI_COMMAND_COMPLETE_EVT || !metadata->command_status_cb) { + hci_cmd_free_cb free_func = metadata->command_free_cb ? metadata->command_free_cb : (hci_cmd_free_cb) osi_free_func; + free_func(wait_entry); } - - osi_free(wait_entry); } else { osi_free(packet); } @@ -553,7 +535,7 @@ static serial_data_type_t event_to_data_type(uint16_t event) return 0; } -static waiting_command_t *get_waiting_command(command_opcode_t opcode) +static pkt_linked_item_t *get_waiting_command(command_opcode_t opcode) { command_waiting_response_t *cmd_wait_q = &hci_host_env.cmd_waiting_q; osi_mutex_lock(&cmd_wait_q->commands_pending_response_lock, OSI_MUTEX_MAX_TIMEOUT); @@ -561,15 +543,15 @@ static waiting_command_t *get_waiting_command(command_opcode_t opcode) for (const list_node_t *node = list_begin(cmd_wait_q->commands_pending_response); node != list_end(cmd_wait_q->commands_pending_response); node = list_next(node)) { - waiting_command_t *wait_entry = list_node(node); - if (!wait_entry || wait_entry->opcode != opcode) { - continue; + pkt_linked_item_t *wait_entry = list_node(node); + if (wait_entry) { + hci_cmd_metadata_t *metadata = (hci_cmd_metadata_t *)(wait_entry->data); + if (metadata->opcode == opcode) { + list_remove(cmd_wait_q->commands_pending_response, wait_entry); + osi_mutex_unlock(&cmd_wait_q->commands_pending_response_lock); + return wait_entry; + } } - - list_remove(cmd_wait_q->commands_pending_response, wait_entry); - - osi_mutex_unlock(&cmd_wait_q->commands_pending_response_lock); - return wait_entry; } osi_mutex_unlock(&cmd_wait_q->commands_pending_response_lock); diff --git a/components/bt/host/bluedroid/hci/hci_packet_factory.c b/components/bt/host/bluedroid/hci/hci_packet_factory.c index 7fd7f0ddb9..5010e99d2f 100644 --- a/components/bt/host/bluedroid/hci/hci_packet_factory.c +++ b/components/bt/host/bluedroid/hci/hci_packet_factory.c @@ -27,7 +27,6 @@ #include "hci/hci_packet_factory.h" -static BT_HDR *make_packet(size_t data_size); static BT_HDR *make_command_no_params(uint16_t opcode); static BT_HDR *make_command(uint16_t opcode, size_t parameter_size, uint8_t **stream_out); @@ -234,7 +233,9 @@ static BT_HDR *make_command_no_params(uint16_t opcode) static BT_HDR *make_command(uint16_t opcode, size_t parameter_size, uint8_t **stream_out) { - BT_HDR *packet = make_packet(HCI_COMMAND_PREAMBLE_SIZE + parameter_size); + BT_HDR *packet = HCI_GET_CMD_BUF(parameter_size); + hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(packet); + metadata->opcode = opcode; uint8_t *stream = packet->data; UINT16_TO_STREAM(stream, opcode); @@ -247,17 +248,6 @@ static BT_HDR *make_command(uint16_t opcode, size_t parameter_size, uint8_t **st return packet; } -static BT_HDR *make_packet(size_t data_size) -{ - BT_HDR *ret = (BT_HDR *)osi_calloc(sizeof(BT_HDR) + data_size); - assert(ret); - ret->event = 0; - ret->offset = 0; - ret->layer_specific = 0; - ret->len = data_size; - return ret; -} - static const hci_packet_factory_t interface = { make_reset, make_read_buffer_size, diff --git a/components/bt/host/bluedroid/hci/include/hci/hci_layer.h b/components/bt/host/bluedroid/hci/include/hci/hci_layer.h index 6ba4ccd18c..728c4997a8 100644 --- a/components/bt/host/bluedroid/hci/include/hci/hci_layer.h +++ b/components/bt/host/bluedroid/hci/include/hci/hci_layer.h @@ -25,6 +25,7 @@ #include "osi/osi.h" #include "osi/future.h" #include "osi/thread.h" +#include "osi/pkt_queue.h" ///// LEGACY DEFINITIONS ///// @@ -47,6 +48,7 @@ /* Local Bluetooth Controller ID for BR/EDR */ #define LOCAL_BR_EDR_CONTROLLER_ID 0 +#define HCI_CMD_MSG_F_VND_FUTURE (0x01) ///// END LEGACY DEFINITIONS ///// typedef struct hci_hal_t hci_hal_t; diff --git a/components/bt/host/bluedroid/stack/btm/btm_devctl.c b/components/bt/host/bluedroid/stack/btm/btm_devctl.c index 04af26e926..e00bff2b00 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_devctl.c +++ b/components/bt/host/bluedroid/stack/btm/btm_devctl.c @@ -662,14 +662,13 @@ tBTM_DEV_STATUS_CB *BTM_RegisterForDeviceStatusNotif (tBTM_DEV_STATUS_CB *p_cb) tBTM_STATUS BTM_VendorSpecificCommand(UINT16 opcode, UINT8 param_len, UINT8 *p_param_buf, tBTM_VSC_CMPL_CB *p_cb) { - void *p_buf; + BT_HDR *p_buf; BTM_TRACE_EVENT ("BTM: BTM_VendorSpecificCommand: Opcode: 0x%04X, ParamLen: %i.", opcode, param_len); /* Allocate a buffer to hold HCI command plus the callback function */ - if ((p_buf = osi_malloc((UINT16)(sizeof(BT_HDR) + sizeof (tBTM_CMPL_CB *) + - param_len + HCIC_PREAMBLE_SIZE))) != NULL) { + if ((p_buf = HCI_GET_CMD_BUF(param_len)) != NULL) { /* Send the HCI command (opcode will be OR'd with HCI_GRP_VENDOR_SPECIFIC) */ btsnd_hcic_vendor_spec_cmd (p_buf, opcode, param_len, p_param_buf, (void *)p_cb); diff --git a/components/bt/host/bluedroid/stack/btm/btm_inq.c b/components/bt/host/bluedroid/stack/btm/btm_inq.c index 154b9e1e04..598ca13ffc 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_inq.c +++ b/components/bt/host/bluedroid/stack/btm/btm_inq.c @@ -2395,6 +2395,7 @@ tBTM_STATUS BTM_WriteEIR( BT_HDR *p_buff, BOOLEAN fec_required) if (controller_get_interface()->supports_extended_inquiry_response()) { BTM_TRACE_API("Write Extended Inquiry Response to controller\n"); btsnd_hcic_write_ext_inquiry_response (p_buff, fec_required); + osi_free(p_buff); return BTM_SUCCESS; } else { osi_free(p_buff); diff --git a/components/bt/host/bluedroid/stack/btu/btu_hcif.c b/components/bt/host/bluedroid/stack/btu/btu_hcif.c index d9130bd254..2ce46ec1bf 100644 --- a/components/bt/host/bluedroid/stack/btu/btu_hcif.c +++ b/components/bt/host/bluedroid/stack/btu/btu_hcif.c @@ -43,6 +43,7 @@ #include "common/bt_trace.h" #include "osi/thread.h" +#include "osi/pkt_queue.h" //#include "osi/mutex.h" // TODO(zachoverflow): remove this horrible hack #include "stack/btu.h" @@ -451,15 +452,21 @@ void btu_hcif_send_cmd (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_buf) STREAM_TO_UINT16(opcode, stream); - // Eww...horrible hackery here - /* If command was a VSC, then extract command_complete callback */ - if ((opcode & HCI_GRP_VENDOR_SPECIFIC) == HCI_GRP_VENDOR_SPECIFIC + assert (p_buf->layer_specific == HCI_CMD_BUF_TYPE_METADATA); + hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p_buf); + metadata->command_complete_cb = btu_hcif_command_complete_evt; + metadata->command_status_cb = btu_hcif_command_status_evt; + metadata->opcode = opcode; + + vsc_callback = metadata->context; + /* If command is not a VSC, then the context field should be empty */ + if ((opcode & HCI_GRP_VENDOR_SPECIFIC) != HCI_GRP_VENDOR_SPECIFIC #if BLE_INCLUDED == TRUE - || (opcode == HCI_BLE_RAND) - || (opcode == HCI_BLE_ENCRYPT) + && (opcode != HCI_BLE_RAND) + && (opcode != HCI_BLE_ENCRYPT) #endif - ) { - vsc_callback = *((void **)(p_buf + 1)); + ) { + assert (vsc_callback == NULL); } hci_layer_get_interface()->transmit_command( @@ -472,6 +479,7 @@ void btu_hcif_send_cmd (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_buf) btu_check_bt_sleep (); #endif } + #if (BLE_50_FEATURE_SUPPORT == TRUE) UINT8 btu_hcif_send_cmd_sync (UINT8 controller_id, BT_HDR *p_buf) { @@ -492,15 +500,22 @@ UINT8 btu_hcif_send_cmd_sync (UINT8 controller_id, BT_HDR *p_buf) sync_info->opcode = opcode; - // Eww...horrible hackery here - /* If command was a VSC, then extract command_complete callback */ - if ((opcode & HCI_GRP_VENDOR_SPECIFIC) == HCI_GRP_VENDOR_SPECIFIC + assert (p_buf->layer_specific == HCI_CMD_BUF_TYPE_METADATA); + hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p_buf); + metadata->command_complete_cb = btu_hcif_command_complete_evt; + metadata->command_status_cb = btu_hcif_command_status_evt; + metadata->command_free_cb = NULL; + metadata->opcode = opcode; + + vsc_callback = metadata->context; + /* If command is not a VSC, then the context field should be empty */ + if ((opcode & HCI_GRP_VENDOR_SPECIFIC) != HCI_GRP_VENDOR_SPECIFIC #if BLE_INCLUDED == TRUE - || (opcode == HCI_BLE_RAND) - || (opcode == HCI_BLE_ENCRYPT) + && (opcode != HCI_BLE_RAND) + && (opcode != HCI_BLE_ENCRYPT) #endif - ) { - vsc_callback = *((void **)(p_buf + 1)); + ) { + assert (vsc_callback == NULL); } hci_layer_get_interface()->transmit_command( @@ -1434,7 +1449,11 @@ static void btu_hcif_command_status_evt_on_task(BT_HDR *event) stream, hack->context); - osi_free(hack->command); + // check the HCI command integrity: opcode + hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(hack->command); + assert(metadata->opcode == opcode); + + HCI_FREE_CMD_BUF(hack->command); osi_free(event); } diff --git a/components/bt/host/bluedroid/stack/hcic/hciblecmds.c b/components/bt/host/bluedroid/stack/hcic/hciblecmds.c index 50935f3be6..b816d0227b 100644 --- a/components/bt/host/bluedroid/stack/hcic/hciblecmds.c +++ b/components/bt/host/bluedroid/stack/hcic/hciblecmds.c @@ -33,7 +33,6 @@ #include #include -#define HCI_GET_CMD_BUF(paramlen) ((BT_HDR *)osi_malloc(HCIC_PREAMBLE_SIZE + sizeof(BT_HDR) + paramlen)) #if (BLE_50_FEATURE_SUPPORT == TRUE) static BlE_SYNC ble_sync_info; @@ -557,19 +556,17 @@ BOOLEAN btsnd_hcic_ble_encrypt (UINT8 *key, UINT8 key_len, BT_HDR *p; UINT8 *pp; - if ((p = HCI_GET_CMD_BUF(sizeof (void *) + - HCIC_PARAM_SIZE_BLE_ENCRYPT)) == NULL) { + if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_BLE_ENCRYPT)) == NULL) { return (FALSE); } pp = (UINT8 *)(p + 1); p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_ENCRYPT; - p->offset = sizeof(void *); - - *((void **)pp) = p_cmd_cplt_cback; /* Store command complete callback in buffer */ - pp += sizeof(void *); /* Skip over callback pointer */ + p->offset = 0; + hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p); + metadata->context = p_cmd_cplt_cback; UINT16_TO_STREAM (pp, HCI_BLE_ENCRYPT); UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_ENCRYPT); @@ -596,18 +593,17 @@ BOOLEAN btsnd_hcic_ble_rand (void *p_cmd_cplt_cback) BT_HDR *p; UINT8 *pp; - if ((p = HCI_GET_CMD_BUF(sizeof (void *) + - HCIC_PARAM_SIZE_BLE_RAND)) == NULL) { + if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_BLE_RAND)) == NULL) { return (FALSE); } pp = (UINT8 *)(p + 1); p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_RAND; - p->offset = sizeof(void *); + p->offset = 0; - *((void **)pp) = p_cmd_cplt_cback; /* Store command complete callback in buffer */ - pp += sizeof(void *); /* Skip over callback pointer */ + hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p); + metadata->context = p_cmd_cplt_cback; UINT16_TO_STREAM (pp, HCI_BLE_RAND); UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_RAND); @@ -1046,6 +1042,9 @@ BOOLEAN btsnd_hcic_ble_update_adv_report_flow_control (UINT16 num) p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL; p->offset = 0; + hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p); + metadata->flags_src |= HCI_CMD_MSG_F_SRC_NOACK; + UINT16_TO_STREAM (pp, HCI_VENDOR_BLE_ADV_REPORT_FLOW_CONTROL); UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL); UINT16_TO_STREAM (pp, num); diff --git a/components/bt/host/bluedroid/stack/hcic/hcicmds.c b/components/bt/host/bluedroid/stack/hcic/hcicmds.c index 3b52804408..0763937c9f 100644 --- a/components/bt/host/bluedroid/stack/hcic/hcicmds.c +++ b/components/bt/host/bluedroid/stack/hcic/hcicmds.c @@ -35,8 +35,6 @@ #include "btm_int.h" /* Included for UIPC_* macro definitions */ -#define HCI_GET_CMD_BUF(paramlen) ((BT_HDR *)osi_malloc(HCIC_PREAMBLE_SIZE + sizeof(BT_HDR) + paramlen)) - BOOLEAN btsnd_hcic_inquiry(const LAP inq_lap, UINT8 duration, UINT8 response_cnt) { BT_HDR *p; @@ -1331,6 +1329,9 @@ BOOLEAN btsnd_hcic_host_num_xmitted_pkts (UINT8 num_handles, UINT16 *handle, p->len = HCIC_PREAMBLE_SIZE + 1 + (num_handles * 4); p->offset = 0; + hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p); + metadata->flags_src |= HCI_CMD_MSG_F_SRC_NOACK; + UINT16_TO_STREAM (pp, HCI_HOST_NUM_PACKETS_DONE); UINT8_TO_STREAM (pp, p->len - HCIC_PREAMBLE_SIZE); @@ -1431,9 +1432,13 @@ BOOLEAN btsnd_hcic_sniff_sub_rate(UINT16 handle, UINT16 max_lat, #endif /* BTM_SSR_INCLUDED */ /**** Extended Inquiry Response Commands ****/ -void btsnd_hcic_write_ext_inquiry_response (void *buffer, UINT8 fec_req) +void btsnd_hcic_write_ext_inquiry_response (BT_HDR *buffer, UINT8 fec_req) { - BT_HDR *p = (BT_HDR *)buffer; + BT_HDR *p; + if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_EXT_INQ_RESP)) == NULL) { + return; + } + UINT8 *pp = (UINT8 *)(p + 1); p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_EXT_INQ_RESP; @@ -1441,9 +1446,10 @@ void btsnd_hcic_write_ext_inquiry_response (void *buffer, UINT8 fec_req) UINT16_TO_STREAM (pp, HCI_WRITE_EXT_INQ_RESPONSE); UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_EXT_INQ_RESP); - UINT8_TO_STREAM (pp, fec_req); + memcpy(pp, buffer->data + 4, p->len - 4); + btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p); } @@ -1862,17 +1868,17 @@ BOOLEAN btsnd_hcic_write_pagescan_type (UINT8 type) #error "HCI_CMD_POOL_BUF_SIZE must be larger than 268" #endif -void btsnd_hcic_vendor_spec_cmd (void *buffer, UINT16 opcode, UINT8 len, +void btsnd_hcic_vendor_spec_cmd (BT_HDR *buffer, UINT16 opcode, UINT8 len, UINT8 *p_data, void *p_cmd_cplt_cback) { - BT_HDR *p = (BT_HDR *)buffer; + BT_HDR *p = buffer; UINT8 *pp = (UINT8 *)(p + 1); p->len = HCIC_PREAMBLE_SIZE + len; - p->offset = sizeof(void *); + p->offset = 0; - *((void **)pp) = p_cmd_cplt_cback; /* Store command complete callback in buffer */ - pp += sizeof(void *); /* Skip over callback pointer */ + hci_cmd_metadata_t * metadata = HCI_GET_CMD_METAMSG(p); + metadata->context = p_cmd_cplt_cback; UINT16_TO_STREAM (pp, HCI_GRP_VENDOR_SPECIFIC | opcode); UINT8_TO_STREAM (pp, len); diff --git a/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h b/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h index 8f85582869..9e4eda774f 100644 --- a/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h +++ b/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h @@ -19,9 +19,66 @@ #ifndef HCIMSGS_H #define HCIMSGS_H +#include #include "common/bt_target.h" #include "stack/hcidefs.h" #include "stack/bt_types.h" +#include "osi/pkt_queue.h" +#include "osi/allocator.h" + +#define HCI_CMD_BUF_TYPE_METADATA (0xa56e) + +#define HCI_CMD_MSG_F_SRC_NOACK (0x01) + +typedef void (*hci_cmd_cmpl_cb)(BT_HDR *response, void *context); +typedef void (*hci_cmd_stat_cb)(uint8_t status, BT_HDR *command, void *context); +typedef void (*hci_cmd_free_cb)(pkt_linked_item_t *linked_pkt); + +typedef struct { + uint8_t flags_src; + uint8_t flags_vnd; // used for downstream layer + uint16_t opcode; + hci_cmd_cmpl_cb command_complete_cb; + hci_cmd_stat_cb command_status_cb; + void *context; + void *complete_future; + hci_cmd_free_cb command_free_cb; + BT_HDR command; +} hci_cmd_metadata_t; + +#define HCI_CMD_METADATA_HDR_SIZE (sizeof(hci_cmd_metadata_t)) + +#define HCI_CMD_LINKED_BUF_SIZE(paramlen) (BT_PKT_LINKED_HDR_SIZE + HCI_CMD_METADATA_HDR_SIZE + HCIC_PREAMBLE_SIZE + (paramlen)) + +#define HCI_GET_CMD_METAMSG(cmd_ptr) (hci_cmd_metadata_t *)((void *)(cmd_ptr) - offsetof(hci_cmd_metadata_t, command)) +#define HCI_GET_CMD_LINKED_STRUCT(metadata_ptr) (pkt_linked_item_t *)((void *)(metadata_ptr) - offsetof(pkt_linked_item_t, data)) + +static inline BT_HDR *hci_get_cmd_buf(size_t param_len) +{ + pkt_linked_item_t *linked_pkt = osi_calloc(HCI_CMD_LINKED_BUF_SIZE(param_len)); + if (linked_pkt == NULL) { + return NULL; + } + hci_cmd_metadata_t *metadata = (hci_cmd_metadata_t *)linked_pkt->data; + BT_HDR *command = &metadata->command; + + command->layer_specific = HCI_CMD_BUF_TYPE_METADATA; + command->len = HCIC_PREAMBLE_SIZE + param_len; + command->offset = 0; + + return command; +} + +static inline void hci_free_cmd_buf(BT_HDR *buf) +{ + assert(buf->layer_specific == HCI_CMD_BUF_TYPE_METADATA); + hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(buf); + pkt_linked_item_t *linked_pkt = HCI_GET_CMD_LINKED_STRUCT(metadata); + osi_free(linked_pkt); +} + +#define HCI_GET_CMD_BUF(param_len) hci_get_cmd_buf(param_len) +#define HCI_FREE_CMD_BUF(buf) hci_free_cmd_buf(buf) void bte_main_hci_send(BT_HDR *p_msg, UINT16 event); void bte_main_lpm_allow_bt_device_sleep(void); @@ -378,7 +435,7 @@ BOOLEAN btsnd_hcic_sniff_sub_rate(UINT16 handle, UINT16 max_lat, #endif /* BTM_SSR_INCLUDED */ /* Extended Inquiry Response */ -void btsnd_hcic_write_ext_inquiry_response(void *buffer, UINT8 fec_req); +void btsnd_hcic_write_ext_inquiry_response(BT_HDR *buffer, UINT8 fec_req); #define HCIC_PARAM_SIZE_EXT_INQ_RESP 241 @@ -641,7 +698,7 @@ BOOLEAN btsnd_hcic_write_inquiry_mode(UINT8 type); /* Write Inquiry #define HCID_GET_SCO_LEN(p) (*((UINT8 *)((p) + 1) + p->offset + 2)) -void btsnd_hcic_vendor_spec_cmd (void *buffer, UINT16 opcode, +void btsnd_hcic_vendor_spec_cmd (BT_HDR *buffer, UINT16 opcode, UINT8 len, UINT8 *p_data, void *p_cmd_cplt_cback);