/******************************************************************************* ** ** Function gatt_process_prep_write_rsp ** ** Description This function is called to handle the read response ** ** ** Returns void ** *******************************************************************************/ void gatt_process_prep_write_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, UINT16 len, UINT8 *p_data) { tGATT_VALUE value = {0}; UINT8 *p= p_data; GATT_TRACE_ERROR2("value resp op_code = %s len = %d", gatt_dbg_op_name(op_code), len); STREAM_TO_UINT16 (value.handle, p); STREAM_TO_UINT16 (value.offset, p); value.len = len - 4; memcpy (value.value, p, value.len); if (p_clcb->op_subtype == GATT_WRITE_PREPARE) { p_clcb->status = GATT_SUCCESS; /* application should verify handle offset and value are matched or not */ gatt_end_operation(p_clcb, p_clcb->status, &value); } else if (p_clcb->op_subtype == GATT_WRITE ) { if (!gatt_check_write_long_terminate(p_tcb, p_clcb, &value)) gatt_send_prepare_write(p_tcb, p_clcb); } }
//***************************************************************************** // //! hci_event_unsol_flowcontrol_handler //! //! @param pEvent pointer to the string contains parameters for IPERF //! @return ESUCCESS if successful, EFAIL if an error occurred //! //! @brief Called in case unsolicited event from type //! HCI_EVNT_DATA_UNSOL_FREE_BUFF has received. //! Keep track on the number of packets transmitted and update the //! number of free buffer in the SL device. // //***************************************************************************** INT32 hci_event_unsol_flowcontrol_handler(CHAR *pEvent) { INT32 temp, value; UINT16 i; UINT16 pusNumberOfHandles=0; CHAR *pReadPayload; STREAM_TO_UINT16((CHAR *)pEvent,HCI_EVENT_HEADER_SIZE,pusNumberOfHandles); pReadPayload = ((CHAR *)pEvent + HCI_EVENT_HEADER_SIZE + sizeof(pusNumberOfHandles)); temp = 0; for(i = 0; i < pusNumberOfHandles ; i++) { STREAM_TO_UINT16(pReadPayload, FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET, value); temp += value; pReadPayload += FLOW_CONTROL_EVENT_SIZE; } tSLInformation.usNumberOfFreeBuffers += temp; tSLInformation.NumberOfReleasedPackets += temp; return(ESUCCESS); }
/******************************************************************************* ** ** Function gatt_process_find_type_value_rsp ** ** Description This function is called to handle find by type value response. ** ** ** Returns void ** *******************************************************************************/ void gatt_process_find_type_value_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data) { tGATT_DISC_RES result; tGATT_DISC_VALUE record_value; UINT8 *p = p_data; GATT_TRACE_DEBUG0("gatt_process_find_type_value_rsp "); /* unexpected response */ if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_SRVC_BY_UUID) return; memset (&record_value, 0, sizeof(tGATT_DISC_VALUE)); result.type.len = 2; result.type.uu.uuid16 = GATT_UUID_PRI_SERVICE; /* returns a series of handle ranges */ while (len >= 4) { STREAM_TO_UINT16 (result.handle, p); STREAM_TO_UINT16 (record_value.handle, p); len -= 4; memcpy (&result.value, &record_value, sizeof (result.value));; if (p_clcb->p_reg->app_cb.p_disc_res_cb) (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result); } /* last handle + 1 */ p_clcb->s_handle = (record_value.handle == 0) ? 0 : (record_value.handle + 1); /* initiate another request */ gatt_act_discovery(p_clcb) ; }
// 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; uint8_t event_code; command_opcode_t opcode; STREAM_TO_UINT8(event_code, stream); STREAM_SKIP_UINT8(stream); // Skip the parameter total length field if (event_code == HCI_COMMAND_COMPLETE_EVT) { STREAM_TO_UINT8(command_credits, stream); STREAM_TO_UINT16(opcode, stream); wait_entry = get_waiting_command(opcode); if (!wait_entry) LOG_WARN(LOG_TAG, "%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(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) LOG_WARN(LOG_TAG, "%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:; non_repeating_timer_restart_if(command_response_timer, !list_is_empty(commands_pending_response)); 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)) buffer_allocator->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) buffer_allocator->free(wait_entry->command); osi_free(wait_entry); } else { buffer_allocator->free(packet); } return true; }
/******************************************************************************* ** ** Function gap_ble_c_cmpl_cback ** ** Description Client operation complete callback. ** ** Returns void ** *******************************************************************************/ static void gap_ble_c_cmpl_cback (UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, tGATT_CL_COMPLETE *p_data) { tGAP_CLCB *p_clcb = gap_ble_find_clcb_by_conn_id(conn_id); UINT16 op_type; UINT16 min, max, latency, tout; UINT16 len; UINT8 *pp; if (p_clcb == NULL) return; op_type = p_clcb->cl_op_uuid; GAP_TRACE_EVENT ("gap_ble_c_cmpl_cback() - op_code: 0x%02x status: 0x%02x read_type: 0x%04x", op, status, op_type); /* Currently we only issue read commands */ if (op != GATTC_OPTYPE_READ) return; if (status != GATT_SUCCESS) { gap_ble_cl_op_cmpl(p_clcb, FALSE, 0, NULL); return; } pp = p_data->att_value.value; switch (op_type) { case GATT_UUID_GAP_PREF_CONN_PARAM: GAP_TRACE_EVENT ("GATT_UUID_GAP_PREF_CONN_PARAM"); /* Extract the peripheral preferred connection parameters and save them */ STREAM_TO_UINT16 (min, pp); STREAM_TO_UINT16 (max, pp); STREAM_TO_UINT16 (latency, pp); STREAM_TO_UINT16 (tout, pp); BTM_BleSetPrefConnParams (p_clcb->bda, min, max, latency, tout); /* release the connection here */ gap_ble_cl_op_cmpl(p_clcb, TRUE, 0, NULL); break; case GATT_UUID_GAP_DEVICE_NAME: GAP_TRACE_EVENT ("GATT_UUID_GAP_DEVICE_NAME"); len = (UINT16)strlen((char *)pp); if (len > GAP_CHAR_DEV_NAME_SIZE) len = GAP_CHAR_DEV_NAME_SIZE; gap_ble_cl_op_cmpl(p_clcb, TRUE, len, pp); break; case GATT_UUID_GAP_ICON: break; } }
/******************************************************************************* ** ** Function nfc_enabled ** ** Description NFCC enabled, proceed with stack start up. ** ** Returns void ** *******************************************************************************/ void nfc_enabled (tNFC_STATUS nfc_status, BT_HDR *p_init_rsp_msg) { tNFC_RESPONSE evt_data; tNFC_CONN_CB *p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID]; UINT8 *p; UINT8 num_interfaces = 0, xx; int yy = 0; memset (&evt_data, 0, sizeof (tNFC_RESPONSE)); if (nfc_status == NCI_STATUS_OK) { nfc_set_state (NFC_STATE_IDLE); p = (UINT8 *) (p_init_rsp_msg + 1) + p_init_rsp_msg->offset + NCI_MSG_HDR_SIZE + 1; /* we currently only support NCI of the same version. * We may need to change this, when we support multiple version of NFCC */ evt_data.enable.nci_version = NCI_VERSION; STREAM_TO_UINT32 (evt_data.enable.nci_features, p); STREAM_TO_UINT8 (num_interfaces, p); evt_data.enable.nci_interfaces = 0; for (xx = 0; xx < num_interfaces; xx++) { if ((*p) <= NCI_INTERFACE_MAX) evt_data.enable.nci_interfaces |= (1 << (*p)); #if(NFC_NXP_NOT_OPEN_INCLUDED == TRUE) else if (((*p) >= NCI_INTERFACE_FIRST_VS) && (yy < NFC_NFCC_MAX_NUM_VS_INTERFACE)) #else else if (((*p) > NCI_INTERFACE_FIRST_VS) && (yy < NFC_NFCC_MAX_NUM_VS_INTERFACE)) #endif { /* save the VS RF interface in control block, if there's still room */ nfc_cb.vs_interface[yy++] = *p; } p++; } nfc_cb.nci_interfaces = evt_data.enable.nci_interfaces; memcpy (evt_data.enable.vs_interface, nfc_cb.vs_interface, NFC_NFCC_MAX_NUM_VS_INTERFACE); evt_data.enable.max_conn = *p++; STREAM_TO_UINT16 (evt_data.enable.max_ce_table, p); #if (NFC_RW_ONLY == FALSE) nfc_cb.max_ce_table = evt_data.enable.max_ce_table; nfc_cb.nci_features = evt_data.enable.nci_features; nfc_cb.max_conn = evt_data.enable.max_conn; #endif nfc_cb.nci_ctrl_size = *p++; /* Max Control Packet Payload Length */ p_cb->init_credits = p_cb->num_buff = 0; STREAM_TO_UINT16 (evt_data.enable.max_param_size, p); nfc_set_conn_id (p_cb, NFC_RF_CONN_ID); evt_data.enable.manufacture_id = *p++; STREAM_TO_ARRAY (evt_data.enable.nfcc_info, p, NFC_NFCC_INFO_LEN); NFC_DiscoveryMap (nfc_cb.num_disc_maps, (tNCI_DISCOVER_MAPS *) nfc_cb.p_disc_maps, NULL); }
/******************************************************************************* ** ** Function smp_rand_back ** ** Description This function is to process the rand command finished, ** process the random/encrypted number for further action. ** ** Returns void ** *******************************************************************************/ static void smp_rand_back(tBTM_RAND_ENC *p) { tSMP_CB *p_cb = &smp_cb; UINT8 *pp = p->param_buf; UINT8 failure = SMP_PAIR_FAIL_UNKNOWN; UINT8 state = p_cb->rand_enc_proc & ~0x80; SMP_TRACE_DEBUG1 ("smp_rand_back state=0x%x", state); if (p && p->status == HCI_SUCCESS) { switch (state) { case SMP_GEN_SRAND_MRAND: memcpy((void *)p_cb->rand, p->param_buf, p->param_len); smp_genenrate_rand_cont(p_cb, NULL); break; case SMP_GEN_SRAND_MRAND_CONT: memcpy((void *)&p_cb->rand[8], p->param_buf, p->param_len); smp_genenrate_confirm(p_cb, NULL); break; case SMP_GEN_DIV_LTK: STREAM_TO_UINT16(p_cb->div, pp); smp_genenrate_ltk_cont(p_cb, NULL); break; case SMP_GEN_DIV_CSRK: STREAM_TO_UINT16(p_cb->div, pp); smp_compute_csrk(p_cb, NULL); break; case SMP_GEN_TK: smp_proc_passkey(p_cb, p); break; case SMP_GEN_RAND_V: memcpy(p_cb->enc_rand, p->param_buf, BT_OCTET8_LEN); smp_generate_y(p_cb, NULL); break; } return; } SMP_TRACE_ERROR1("smp_rand_back Key generation failed: (%d)", p_cb->rand_enc_proc); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure); }
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) { LOG_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; LOG_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(); }
//***************************************************************************** // //! SpiReadDataCont //! //! @param None //! //! @return None //! //! @brief This function processes received SPI Header and in accordance with //! it - continues reading the packet // //***************************************************************************** long SpiReadDataCont(void) { long data_to_recv; unsigned char *evnt_buff, type; //determine what type of packet we have evnt_buff = sSpiInformation.pRxPacket; data_to_recv = 0; STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_PACKET_TYPE_OFFSET, type); switch(type) { case HCI_TYPE_DATA: { // We need to read the rest of data.. STREAM_TO_UINT16((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_DATA_LENGTH_OFFSET, data_to_recv); if (!((HEADERS_SIZE_EVNT + data_to_recv) & 1)) { data_to_recv++; } if (data_to_recv) { SpiReadDataSynchronous(evnt_buff + 10, data_to_recv); } break; } case HCI_TYPE_EVNT: { // Calculate the rest length of the data STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_EVENT_LENGTH_OFFSET, data_to_recv); data_to_recv -= 1; // Add padding byte if needed if ((HEADERS_SIZE_EVNT + data_to_recv) & 1) { data_to_recv++; } if (data_to_recv) { SpiReadDataSynchronous(evnt_buff + 10, data_to_recv); } sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT; break; } } return (0); }
/******************************************************************************* ** ** Function gatt_process_mtu_rsp ** ** Description This function is called to process the configure MTU response. ** ** ** Returns void ** *******************************************************************************/ void gatt_process_mtu_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data) { UINT16 mtu; STREAM_TO_UINT16(mtu, p_data); if (mtu < p_tcb->payload_size && mtu >= GATT_DEF_BLE_MTU_SIZE) p_tcb->payload_size = mtu; gatt_end_operation(p_clcb, p_clcb->status, NULL); }
void SpiReceiveHandler(void *pvBuffer) { tSLInformation.pucReceivedData = (uint8_t *)pvBuffer; tSLInformation.usEventOrDataReceived = 1; uint16_t event_type; STREAM_TO_UINT16((char *)tSLInformation.pucReceivedData, HCI_EVENT_OPCODE_OFFSET,event_type); nllvdbg("Evtn:0x%x\n", event_type); hci_unsolicited_event_handler(); }
/******************************************************************************* ** ** Function gatt_process_handle_rsp ** ** Description This function is called to handle the write response ** ** ** Returns void ** *******************************************************************************/ void gatt_process_handle_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, UINT16 len, UINT8 *p_data) { UINT16 handle; UINT8 * p= p_data; STREAM_TO_UINT16(handle, p); len -= 2; if (op_code == GATT_RSP_WRITE) gatt_end_operation(p_clcb, GATT_SUCCESS, NULL); }
int32_t cc3000_event::hci_event_unsol_flowcontrol_handler(uint8_t *event) { int32_t temp, value; uint16_t i; uint16_t pusNumberOfHandles=0; uint8_t *pReadPayload; STREAM_TO_UINT16((uint8_t *)event,HCI_EVENT_HEADER_SIZE,pusNumberOfHandles); pReadPayload = ((uint8_t *)event + HCI_EVENT_HEADER_SIZE + sizeof(pusNumberOfHandles)); temp = 0; for(i = 0; i < pusNumberOfHandles; i++) { STREAM_TO_UINT16(pReadPayload, FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET, value); temp += value; pReadPayload += FLOW_CONTROL_EVENT_SIZE; } _simple_link.set_number_free_buffers(_simple_link.get_number_free_buffers() + temp); _simple_link.set_number_of_released_packets(_simple_link.get_released_packets() + temp); return(ESUCCESS); }
/******************************************************************************* ** ** Function hw_sco_cfg_cback ** ** Description Callback function for SCO configuration rquest ** ** Returns None ** *******************************************************************************/ void hw_sco_cfg_cback(void *p_mem) { #if 0 HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem; uint8_t *p; uint16_t opcode; HC_BT_HDR *p_buf=NULL; p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE; STREAM_TO_UINT16(opcode,p); /* Free the RX event buffer */ if (bt_vendor_cbacks) bt_vendor_cbacks->dealloc(p_evt_buf); #if (!defined(SCO_USE_I2S_INTERFACE) || (SCO_USE_I2S_INTERFACE == FALSE)) if (opcode == HCI_VSC_WRITE_SCO_PCM_INT_PARAM) { uint8_t ret = FALSE; /* Ask a new buffer to hold WRITE_PCM_DATA_FORMAT_PARAM command */ if (bt_vendor_cbacks) p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \ HCI_CMD_PREAMBLE_SIZE + \ PCM_DATA_FORMAT_PARAM_SIZE); if (p_buf) { p_buf->event = MSG_STACK_TO_HC_HCI_CMD; p_buf->offset = 0; p_buf->layer_specific = 0; p_buf->len = HCI_CMD_PREAMBLE_SIZE + PCM_DATA_FORMAT_PARAM_SIZE; p = (uint8_t *) (p_buf + 1); UINT16_TO_STREAM(p, HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM); *p++ = PCM_DATA_FORMAT_PARAM_SIZE; memcpy(p, &bt_pcm_data_fmt_param, PCM_DATA_FORMAT_PARAM_SIZE); if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM,\ p_buf, hw_sco_cfg_cback)) == FALSE) { bt_vendor_cbacks->dealloc(p_buf); } else return; } } #endif // !SCO_USE_I2S_INTERFACE if (bt_vendor_cbacks) bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_SUCCESS); #endif }
uint16_t get_uuid16(tBT_UUID *p_uuid) { if (p_uuid->len == LEN_UUID_16) { return p_uuid->uu.uuid16; } else if (p_uuid->len == LEN_UUID_128) { UINT16 u16; UINT8 *p = &p_uuid->uu.uuid128[LEN_UUID_128 - 4]; STREAM_TO_UINT16(u16, p); return u16; } else { /* p_uuid->len == LEN_UUID_32 */ return (UINT16) p_uuid->uu.uuid32; } }
static void fragment_and_dispatch(BT_HDR *packet) { uint16_t continuation_handle; uint16_t max_data_size, max_packet_size, remaining_length; uint16_t event = packet->event & MSG_EVT_MASK; uint8_t *stream = packet->data + packet->offset; assert(packet != NULL); // We only fragment ACL packets if (event != MSG_STACK_TO_HC_HCI_ACL) { callbacks->fragmented(packet, true); return; } max_data_size = SUB_EVENT(packet->event) == LOCAL_BR_EDR_CONTROLLER_ID ? controller->get_acl_data_size_classic() : controller->get_acl_data_size_ble(); max_packet_size = max_data_size + HCI_ACL_PREAMBLE_SIZE; remaining_length = packet->len; STREAM_TO_UINT16(continuation_handle, stream); continuation_handle = APPLY_CONTINUATION_FLAG(continuation_handle); if (remaining_length > max_packet_size) { current_fragment_packet = packet; UINT16_TO_STREAM(stream, max_data_size); packet->len = max_packet_size; callbacks->fragmented(packet, false); packet->offset += max_data_size; remaining_length -= max_data_size; packet->len = remaining_length; // Write the ACL header for the next fragment stream = packet->data + packet->offset; UINT16_TO_STREAM(stream, continuation_handle); UINT16_TO_STREAM(stream, remaining_length - HCI_ACL_PREAMBLE_SIZE); // Apparently L2CAP can set layer_specific to a max number of segments to transmit if (packet->layer_specific) { packet->layer_specific--; if (packet->layer_specific == 0) { packet->event = MSG_HC_TO_STACK_L2C_SEG_XMIT; callbacks->transmit_finished(packet, false); return; } } } else { current_fragment_packet = NULL; callbacks->fragmented(packet, true); } }
/******************************************************************************* ** ** Function gatt_process_read_info_rsp ** ** Description This function is called to handle the read information ** response. ** ** ** Returns void ** *******************************************************************************/ void gatt_process_read_info_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, UINT16 len, UINT8 *p_data) { tGATT_DISC_RES result; UINT8 *p = p_data, uuid_len = 0, type; UNUSED(p_tcb); UNUSED(op_code); if (len < GATT_INFO_RSP_MIN_LEN) { GATT_TRACE_ERROR("invalid Info Response PDU received, discard."); gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL); return; } /* unexpected response */ if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_CHAR_DSCPT) { return; } STREAM_TO_UINT8(type, p); len -= 1; if (type == GATT_INFO_TYPE_PAIR_16) { uuid_len = LEN_UUID_16; } else if (type == GATT_INFO_TYPE_PAIR_128) { uuid_len = LEN_UUID_128; } while (len >= uuid_len + 2) { STREAM_TO_UINT16 (result.handle, p); if (uuid_len > 0) { if (!gatt_parse_uuid_from_cmd(&result.type, uuid_len, &p)) { break; } } else { memcpy (&result.type, &p_clcb->uuid, sizeof(tBT_UUID)); } len -= (uuid_len + 2); if (p_clcb->p_reg->app_cb.p_disc_res_cb) { (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result); } } p_clcb->s_handle = (result.handle == 0) ? 0 : (result.handle + 1); /* initiate another request */ gatt_act_discovery(p_clcb) ; }
/******************************************************************************* ** ** Function btusb_isoc_check_hdr ** ** Description Check the packet header ** ** Parameters p_dev: device instance control block ** ** Returns void ** *******************************************************************************/ static bool btusb_isoc_check_hdr(struct btusb *p_dev) { unsigned char *p_data = p_dev->voice_rx.hdr; int idx; unsigned short sco_handle; unsigned char size; struct btusb_voice_pkt *p_pkt; BT_HDR *p_hdr; struct btusb_voice_channel *p_chan; STREAM_TO_UINT16(sco_handle, p_data); sco_handle &= 0x0fff; STREAM_TO_UINT8(size, p_data); for (idx = 0; idx < ARRAY_SIZE(p_dev->voice_rx.channels); idx++) { p_chan = &p_dev->voice_rx.channels[idx]; if ((p_chan->used) && (sco_handle == p_chan->handle) && (size <= (2 * p_chan->burst))) { /* check if there is already a message being consolidated */ if (unlikely(!p_chan->p_pkt)) { if (!btusb_cq_get(&p_dev->voice_rx_list, &p_pkt)) { BTUSB_ERR("No buffer available for SCO defragmentation\n"); return false; } p_hdr = &p_pkt->bt_hdr; p_hdr->len = BTUSB_VOICE_HEADER_SIZE; p_hdr->offset = 0; p_hdr->layer_specific = 0; p_data = (unsigned char *) (p_hdr + 1); /* add sco handle and buffer size */ UINT16_TO_STREAM(p_data, sco_handle); UINT8_TO_STREAM(p_data, BTUSB_SCO_RX_LEN); p_chan->p_pkt = p_pkt; } p_dev->voice_rx.remaining = size; p_dev->voice_rx.pp_pkt = &p_chan->p_pkt; return true; } } return false; }
/******************************************************************************* ** ** Function l2c_ucd_check_pending_in_sec_q ** ** Description check incoming security ** ** Return TRUE if any UCD packet for security ** *******************************************************************************/ BOOLEAN l2c_ucd_check_pending_in_sec_q(tL2C_CCB *p_ccb) { BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q); if (p_buf != NULL) { UINT16 psm; UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset; STREAM_TO_UINT16(psm, p) p_ccb->chnl_state = CST_TERM_W4_SEC_COMP; btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, psm, p_ccb->p_lcb->handle, CONNLESS_TERM, &l2c_link_sec_comp, p_ccb); return (TRUE); } return (FALSE); }
/******************************************************************************* ** ** Function smp_genenrate_smp_process_edivltk_cont ** ** Description This function is to calculate EDIV = Y xor DIV ** ** Returns void ** *******************************************************************************/ static void smp_process_ediv(tSMP_CB *p_cb, tSMP_ENC *p) { tSMP_KEY key; UINT8 *pp= p->param_buf; UINT16 y; SMP_TRACE_DEBUG0 ("smp_process_ediv "); STREAM_TO_UINT16(y, pp); /* EDIV = Y xor DIV */ p_cb->ediv = p_cb->div ^ y; /* send LTK ready */ SMP_TRACE_ERROR0("LTK ready"); key.key_type = SMP_KEY_TYPE_LTK; key.p_data = p->param_buf; smp_sm_event(p_cb, SMP_KEY_READY_EVT, &key); }
/******************************************************************************* ** ** Function bta_av_co_cp_is_scmst ** ** Description Check if a content protection service is SCMS-T ** ** Returns TRUE if this CP is SCMS-T, FALSE otherwise ** *******************************************************************************/ static BOOLEAN bta_av_co_cp_is_scmst(const UINT8 *p_protectinfo) { UINT16 cp_id; FUNC_TRACE(); if (*p_protectinfo >= BTA_AV_CP_LOSC) { p_protectinfo++; STREAM_TO_UINT16(cp_id, p_protectinfo); if (cp_id == BTA_AV_CP_SCMS_T_ID) { APPL_TRACE_DEBUG0("bta_av_co_cp_is_scmst: SCMS-T found"); return TRUE; } } return FALSE; }
static future_t *transmit_command_futured(BT_HDR *command) { waiting_command_t *wait_entry = osi_calloc(sizeof(waiting_command_t)); assert(wait_entry != NULL); 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; // 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(command_queue, wait_entry); return future; }
/******************************************************************************* ** ** Function bta_gattc_pack_attr_uuid ** ** Description pack UUID into a stream. ** ** Returns ** *******************************************************************************/ void bta_gattc_pack_attr_uuid(tBTA_GATTC_CACHE_ATTR *p_attr, tBT_UUID *p_uuid) { UINT8 *pp = (UINT8 *)p_attr->p_uuid; memset(p_uuid, 0, sizeof(tBT_UUID)); p_uuid->len = p_attr->uuid_len; if (p_attr->uuid_len == LEN_UUID_16) { STREAM_TO_UINT16(p_uuid->uu.uuid16, pp); } else { memcpy(p_uuid->uu.uuid128, pp, LEN_UUID_128); } return; }
/******************************************************************************* ** ** Function gatt_process_mtu_rsp ** ** Description This function is called to process the configure MTU response. ** ** ** Returns void ** *******************************************************************************/ void gatt_process_mtu_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data) { UINT16 mtu; tGATT_STATUS status = GATT_SUCCESS; if (len < GATT_MTU_RSP_MIN_LEN) { GATT_TRACE_ERROR("invalid MTU response PDU received, discard."); status = GATT_INVALID_PDU; } else { STREAM_TO_UINT16(mtu, p_data); if (mtu < p_tcb->payload_size && mtu >= GATT_DEF_BLE_MTU_SIZE) { p_tcb->payload_size = mtu; } } l2cble_set_fixed_channel_tx_data_length(p_tcb->peer_bda, L2CAP_ATT_CID, p_tcb->payload_size); gatt_end_operation(p_clcb, status, NULL); }
/******************************************************************************* ** ** Function gatt_process_error_rsp ** ** Description This function is called to handle the error response ** ** ** Returns void ** *******************************************************************************/ void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, UINT16 len, UINT8 *p_data) { UINT8 opcode, reason, * p= p_data; UINT16 handle; tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf; UNUSED(op_code); UNUSED(len); GATT_TRACE_DEBUG("gatt_process_error_rsp "); STREAM_TO_UINT8(opcode, p); STREAM_TO_UINT16(handle, p); STREAM_TO_UINT8(reason, p); if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY) { gatt_proc_disc_error_rsp(p_tcb, p_clcb, opcode, handle, reason); } else { if ( (p_clcb->operation == GATTC_OPTYPE_WRITE) && (p_clcb->op_subtype == GATT_WRITE) && (opcode == GATT_REQ_PREPARE_WRITE) && (p_attr) && (handle == p_attr->handle) ) { p_clcb->status = reason; gatt_send_queue_write_cancel(p_tcb, p_clcb, GATT_PREP_WRITE_CANCEL); } else if ((p_clcb->operation == GATTC_OPTYPE_READ) && ((p_clcb->op_subtype == GATT_READ_CHAR_VALUE_HDL) || (p_clcb->op_subtype == GATT_READ_BY_HANDLE)) && (opcode == GATT_REQ_READ_BLOB) && p_clcb->first_read_blob_after_read && (reason == GATT_NOT_LONG)) { gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf); } else gatt_end_operation(p_clcb, reason, NULL); } }
void SimpleLinkWaitData(uint8_t *pBuf, uint8_t *from, uint8_t *fromlen) { /* In the blocking implementation the control to caller will be returned only * after the end of current transaction, i.e. only after data will be received */ nllvdbg("Looking for Data\n"); uint16_t event_type; uint16_t opcode = tSLInformation.usRxEventOpcode; do { tSLInformation.pucReceivedData = cc3000_wait(); tSLInformation.usEventOrDataReceived = 1; if (*tSLInformation.pucReceivedData == HCI_TYPE_DATA) { tSLInformation.usRxDataPending = 1; hci_event_handler(pBuf, from, fromlen); break; } else { STREAM_TO_UINT16((char *)tSLInformation.pucReceivedData, HCI_EVENT_OPCODE_OFFSET, event_type); nllvdbg("Evtn:0x%x\n", event_type); if (hci_unsolicited_event_handler() == 1) { nllvdbg("Processed Event 0x%x want Data! Opcode 0x%x\n", event_type, opcode); } else { nllvdbg("!!!!!opcode 0x%x\n", opcode); } UNUSED(event_type); } } while (*tSLInformation.pucReceivedData == HCI_TYPE_EVNT); nllvdbg("Done for Data 0x%x\n", opcode); UNUSED(opcode); }
/******************************************************************************* ** ** Function hw_epilog_cback ** ** Description Callback function for Command Complete Events from HCI ** commands sent in epilog process. ** ** Returns None ** *******************************************************************************/ void hw_epilog_cback(void *p_mem) { HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem; char *p_name, *p_tmp; uint8_t *p, status; uint16_t opcode; status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE); p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE; STREAM_TO_UINT16(opcode,p); ALOGI("%s Opcode:0x%04X Status: %d", __FUNCTION__, opcode, status); /* Must free the RX event buffer */ q.cb->dealloc(p_evt_buf); /* Once epilog process is done, must call callback to notify caller */ q.cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS); }
/******************************************************************************* ** ** Function btm_delete_stored_link_key_complete ** ** Description This function is called when the command complete message ** is received from the HCI for the delete stored link key command. ** ** Returns void ** *******************************************************************************/ void btm_delete_stored_link_key_complete (UINT8 *p) { tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_stored_link_key_cmpl_cb; tBTM_DELETE_STORED_LINK_KEY_COMPLETE result; /* If there was a callback registered for read stored link key, call it */ btm_cb.devcb.p_stored_link_key_cmpl_cb = NULL; if (p_cb) { /* Set the call back event to indicate command complete */ result.event = BTM_CB_EVT_DELETE_STORED_LINK_KEYS; /* Extract the result fields from the HCI event */ STREAM_TO_UINT8 (result.status, p); STREAM_TO_UINT16 (result.num_keys, p); /* Call the call back and pass the result */ (*p_cb)(&result); } }
/******************************************************************************* ** ** Function l2c_ucd_data_ind_cback ** ** Description UCD Data callback ** ** Returns void ** *******************************************************************************/ static void l2c_ucd_data_ind_cback (BD_ADDR rem_bda, BT_HDR *p_buf) { UINT8 *p; UINT16 psm; tL2C_RCB *p_rcb; L2CAP_TRACE_DEBUG ("L2CAP - l2c_ucd_data_ind_cback"); p = (UINT8 *)(p_buf + 1) + p_buf->offset; STREAM_TO_UINT16(psm, p) p_buf->offset += L2CAP_UCD_OVERHEAD; p_buf->len -= L2CAP_UCD_OVERHEAD; if ((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL) { L2CAP_TRACE_ERROR ("L2CAP - no RCB for l2c_ucd_data_ind_cback, PSM: 0x%04x", psm); osi_free (p_buf); } else { p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb(rem_bda, p_buf); } }
/******************************************************************************* ** ** Function gatt_process_read_info_rsp ** ** Description This function is called to handle the read information ** response. ** ** ** Returns void ** *******************************************************************************/ void gatt_process_read_info_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, UINT16 len, UINT8 *p_data) { tGATT_DISC_RES result; UINT8 *p = p_data, uuid_len = 0, type; /* unexpected response */ if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_CHAR_DSCPT) return; STREAM_TO_UINT8(type, p); len -= 1; if (type == GATT_INFO_TYPE_PAIR_16) uuid_len = LEN_UUID_16; else if (type == GATT_INFO_TYPE_PAIR_128) uuid_len = LEN_UUID_128; while (len >= uuid_len + 2) { STREAM_TO_UINT16 (result.handle, p); if (uuid_len > 0) { if (!gatt_parse_uuid_from_cmd(&result.type, uuid_len, &p)) break; } else memcpy (&result.type, &p_clcb->uuid, sizeof(tBT_UUID)); len -= (uuid_len + 2); if (p_clcb->p_reg->app_cb.p_disc_res_cb) (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result); } p_clcb->s_handle = (result.handle == 0) ? 0 :(result.handle + 1); /* initiate another request */ gatt_act_discovery(p_clcb) ; }