static void transmit_command( BT_HDR *command, command_complete_cb complete_callback, 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; // 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); BTTRC_DUMP_BUFFER(NULL, command->data + command->offset, command->len); fixed_queue_enqueue(hci_host_env.command_queue, wait_entry); hci_host_task_post(TASK_POST_BLOCKING); }
void btu_free_quick_timer(TIMER_LIST_ENT *p_tle) { assert(p_tle != NULL); p_tle->in_use = FALSE; // Get the alarm for the timer list entry. osi_alarm_t *alarm = hash_map_get(btu_l2cap_alarm_hash_map, p_tle); if (alarm == NULL) { HCI_TRACE_DEBUG("%s Unable to find expected alarm in hashmap", __func__); return; } osi_alarm_cancel(alarm); hash_map_erase(btu_l2cap_alarm_hash_map, p_tle); }
BOOLEAN btsnd_hcic_ble_set_adv_data (UINT8 data_len, UINT8 *p_data) { BT_HDR *p; UINT8 *pp; for (int i = 0; i < data_len; i++) { HCI_TRACE_DEBUG("p_data[%d] = %x\n", i, p_data[i]); } if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1)) == NULL) { return (FALSE); } pp = (UINT8 *)(p + 1); p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1; p->offset = 0; UINT16_TO_STREAM (pp, HCI_BLE_WRITE_ADV_DATA); UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1); memset(pp, 0, HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA); if (p_data != NULL && data_len > 0) { if (data_len > HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA) { data_len = HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA; } UINT8_TO_STREAM (pp, data_len); ARRAY_TO_STREAM (pp, p_data, data_len); } btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p); return (TRUE); }
// Returns true if the event was intercepted and should not proceed to // higher layers. Also inspects an incoming event for interesting // 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; uint8_t *stream = packet->data + packet->offset; uint8_t event_code; command_opcode_t opcode; STREAM_TO_UINT8(event_code, stream); STREAM_SKIP_UINT8(stream); // Skip the parameter total length field HCI_TRACE_DEBUG("Receive packet event_code=0x%x\n", event_code); if (event_code == HCI_COMMAND_COMPLETE_EVT) { STREAM_TO_UINT8(hci_host_env.command_credits, stream); STREAM_TO_UINT16(opcode, stream); wait_entry = get_waiting_command(opcode); 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 (wait_entry->complete_future) { future_ready(wait_entry->complete_future, packet); } goto intercepted; } else if (event_code == HCI_COMMAND_STATUS_EVT) { uint8_t status; STREAM_TO_UINT8(status, stream); STREAM_TO_UINT8(hci_host_env.command_credits, stream); STREAM_TO_UINT16(opcode, stream); // If a command generates a command status event, it won't be getting a command complete event wait_entry = get_waiting_command(opcode); 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); } goto intercepted; } return false; intercepted: restart_command_waiting_response_timer(&hci_host_env.cmd_waiting_q); /*Tell HCI Host Task to continue TX Pending commands*/ if (hci_host_env.command_credits && !fixed_queue_is_empty(hci_host_env.command_queue)) { hci_host_task_post(TASK_POST_BLOCKING); } 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)) { 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); } osi_free(wait_entry); } else { osi_free(packet); } return true; }