//***************************************************************************** // //! HCI data command builder. //! //! \param usOpcode command operation code //! \param ucPayload pointer to the data buffer //! \param usLength buffer length //! //! \return none //! //! \brief Initiate an HCI data write operation // //***************************************************************************** long hci_data_send(unsigned char ucOpcode, unsigned char *ucArgs, unsigned short usArgsLength, unsigned short usDataLength, const unsigned char *ucTail, unsigned short usTailLength) { unsigned char *stream; stream = ((ucArgs) + SPI_HEADER_SIZE); UINT8_TO_STREAM(stream, HCI_TYPE_DATA); UINT8_TO_STREAM(stream, ucOpcode); UINT8_TO_STREAM(stream, usArgsLength); stream = UINT16_TO_STREAM(stream, usArgsLength + usDataLength + usTailLength); // // Send the packet over the SPI // SpiWrite(ucArgs, SIMPLE_LINK_HCI_DATA_HEADER_SIZE + usArgsLength + usDataLength + usTailLength); return(ESUCCESS); }
/******************************************************************************* ** ** Function HAL_NfcSetSnoozeMode ** ** Description Set snooze mode ** snooze_mode ** NFC_HAL_LP_SNOOZE_MODE_NONE - Snooze mode disabled ** NFC_HAL_LP_SNOOZE_MODE_UART - Snooze mode for UART ** NFC_HAL_LP_SNOOZE_MODE_SPI_I2C - Snooze mode for SPI/I2C ** ** idle_threshold_dh/idle_threshold_nfcc ** Idle Threshold Host in 100ms unit ** ** nfc_wake_active_mode/dh_wake_active_mode ** NFC_HAL_LP_ACTIVE_LOW - high to low voltage is asserting ** NFC_HAL_LP_ACTIVE_HIGH - low to high voltage is asserting ** ** p_snooze_cback ** Notify status of operation ** ** Returns tHAL_NFC_STATUS ** *******************************************************************************/ tHAL_NFC_STATUS HAL_NfcSetSnoozeMode (UINT8 snooze_mode, UINT8 idle_threshold_dh, UINT8 idle_threshold_nfcc, UINT8 nfc_wake_active_mode, UINT8 dh_wake_active_mode, tHAL_NFC_STATUS_CBACK *p_snooze_cback) { UINT8 cmd[NFC_HAL_BT_HCI_CMD_HDR_SIZE + HCI_BRCM_WRITE_SLEEP_MODE_LENGTH]; UINT8 *p; HAL_TRACE_API1 ("HAL_NfcSetSnoozeMode (): snooze_mode = %d", snooze_mode); nfc_hal_cb.dev_cb.new_snooze_mode = snooze_mode; nfc_hal_cb.dev_cb.nfc_wake_active_mode = nfc_wake_active_mode; nfc_hal_cb.dev_cb.p_prop_cback = p_snooze_cback; p = cmd; /* Add the HCI command */ UINT16_TO_STREAM (p, HCI_BRCM_WRITE_SLEEP_MODE); UINT8_TO_STREAM (p, HCI_BRCM_WRITE_SLEEP_MODE_LENGTH); memset (p, 0x00, HCI_BRCM_WRITE_SLEEP_MODE_LENGTH); UINT8_TO_STREAM (p, snooze_mode); /* Sleep Mode */ UINT8_TO_STREAM (p, idle_threshold_dh); /* Idle Threshold Host */ UINT8_TO_STREAM (p, idle_threshold_nfcc); /* Idle Threshold HC */ UINT8_TO_STREAM (p, nfc_wake_active_mode); /* BT Wake Active Mode */ UINT8_TO_STREAM (p, dh_wake_active_mode); /* Host Wake Active Mode */ nfc_hal_dm_send_bt_cmd (cmd, NFC_HAL_BT_HCI_CMD_HDR_SIZE + HCI_BRCM_WRITE_SLEEP_MODE_LENGTH, nfc_hal_dm_set_snooze_mode_cback); return (NCI_STATUS_OK); }
/******************************************************************************* ** ** Function l2c_bcst_msg ** ** Description ** ** Returns void ** *******************************************************************************/ void l2c_bcst_msg( BT_HDR *p_buf, UINT16 psm ) { UINT8 *p; /* Ensure we have enough space in the buffer for the L2CAP and HCI headers */ if (p_buf->offset < L2CAP_BCST_MIN_OFFSET) { L2CAP_TRACE_ERROR ("L2CAP - cannot send buffer, offset: %d", p_buf->offset); GKI_freebuf (p_buf); return; } /* Step back some bytes to add the headers */ p_buf->offset -= (HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_BCST_OVERHEAD); p_buf->len += L2CAP_PKT_OVERHEAD + L2CAP_BCST_OVERHEAD; /* Set the pointer to the beginning of the data */ p = (UINT8 *)(p_buf + 1) + p_buf->offset; /* First, the HCI transport header */ UINT16_TO_STREAM (p, 0x0050 | (L2CAP_PKT_START << 12) | (2 << 14)); uint16_t acl_data_size = controller_get_interface()->get_acl_data_size_classic(); /* The HCI transport will segment the buffers. */ if (p_buf->len > acl_data_size) { UINT16_TO_STREAM (p, acl_data_size); } else { UINT16_TO_STREAM (p, p_buf->len); } /* Now the L2CAP header */ UINT16_TO_STREAM (p, p_buf->len - L2CAP_PKT_OVERHEAD); UINT16_TO_STREAM (p, L2CAP_CONNECTIONLESS_CID); UINT16_TO_STREAM (p, psm); p_buf->len += HCI_DATA_PREAMBLE_SIZE; if (p_buf->len <= controller_get_interface()->get_acl_packet_size_classic()) { //counter_add("l2cap.ch2.tx.bytes", p_buf->len); //counter_add("l2cap.ch2.tx.pkts", 1); bte_main_hci_send(p_buf, BT_EVT_TO_LM_HCI_ACL); } }
/******************************************************************************* ** ** Function L2CA_UcdDataWrite ** ** Description Send UCD to remote device ** ** Parameters: PSM ** BD Address of remote ** Pointer to buffer of type BT_HDR ** flags : L2CAP_FLUSHABLE_CH_BASED ** L2CAP_FLUSHABLE_PKT ** L2CAP_NON_FLUSHABLE_PKT ** ** Return value L2CAP_DW_SUCCESS, if data accepted ** L2CAP_DW_FAILED, if error ** *******************************************************************************/ UINT16 L2CA_UcdDataWrite (UINT16 psm, BD_ADDR rem_bda, BT_HDR *p_buf, UINT16 flags) { tL2C_LCB *p_lcb; tL2C_CCB *p_ccb; tL2C_RCB *p_rcb; UINT8 *p; L2CAP_TRACE_API ("L2CA_UcdDataWrite() PSM: 0x%04x BDA: %08x%04x", psm, (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3], (rem_bda[4] << 8) + rem_bda[5]); /* Fail if the PSM is not registered */ if (((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL) || ( p_rcb->ucd.state == L2C_UCD_STATE_UNUSED )) { L2CAP_TRACE_WARNING ("L2CAP - no RCB for L2CA_UcdDataWrite, PSM: 0x%04x", psm); osi_free (p_buf); return (L2CAP_DW_FAILED); } /* First, see if we already have a link to the remote */ /* then find the channel control block for UCD */ if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL) || ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL)) { if ( l2c_ucd_connect (rem_bda) == FALSE ) { osi_free (p_buf); return (L2CAP_DW_FAILED); } /* If we still don't have lcb and ccb after connect attempt, then can't proceed */ if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL) || ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL)) { osi_free (p_buf); return (L2CAP_DW_FAILED); } } /* write PSM */ p_buf->offset -= L2CAP_UCD_OVERHEAD; p_buf->len += L2CAP_UCD_OVERHEAD; p = (UINT8 *)(p_buf + 1) + p_buf->offset; UINT16_TO_STREAM (p, psm); /* UCD MTU check */ if ((p_lcb->ucd_mtu) && (p_buf->len > p_lcb->ucd_mtu)) { L2CAP_TRACE_WARNING ("L2CAP - Handle: 0x%04x UCD bigger than peer's UCD mtu size cannot be sent", p_lcb->handle); osi_free (p_buf); return (L2CAP_DW_FAILED); } /* If already congested, do not accept any more packets */ if (p_ccb->cong_sent) { L2CAP_TRACE_ERROR ("L2CAP - Handle: 0x%04x UCD cannot be sent, already congested count: %u buff_quota: %u", p_lcb->handle, (fixed_queue_length(p_ccb->xmit_hold_q) + fixed_queue_length(p_lcb->ucd_out_sec_pending_q)), p_ccb->buff_quota); osi_free (p_buf); return (L2CAP_DW_FAILED); } /* channel based, packet based flushable or non-flushable */ p_buf->layer_specific = flags; l2c_csm_execute (p_ccb, L2CEVT_L2CA_DATA_WRITE, p_buf); if (p_ccb->cong_sent) { return (L2CAP_DW_CONGESTED); } else { return (L2CAP_DW_SUCCESS); } }
long wlan_add_profile(unsigned long ulSecType, unsigned char* ucSsid, unsigned long ulSsidLen, unsigned char *ucBssid, unsigned long ulPriority, unsigned long ulPairwiseCipher_Or_TxKeyLen, unsigned long ulGroupCipher_TxKeyIndex, unsigned long ulKeyMgmt, unsigned char* ucPf_OrKey, unsigned long ulPassPhraseLen) { unsigned short arg_len; long ret; unsigned char *ptr; long i = 0; unsigned char *args; unsigned char bssid_zero[] = {0, 0, 0, 0, 0, 0}; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); args = UINT32_TO_STREAM(args, ulSecType); // Setup arguments in accordance with the security type switch (ulSecType) { //OPEN case WLAN_SEC_UNSEC: { args = UINT32_TO_STREAM(args, 0x00000014); args = UINT32_TO_STREAM(args, ulSsidLen); args = UINT16_TO_STREAM(args, 0); if(ucBssid) { ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN); } else { ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); } args = UINT32_TO_STREAM(args, ulPriority); ARRAY_TO_STREAM(args, ucSsid, ulSsidLen); arg_len = WLAN_ADD_PROFILE_NOSEC_PARAM_LEN + ulSsidLen; } break; //WEP case WLAN_SEC_WEP: { args = UINT32_TO_STREAM(args, 0x00000020); args = UINT32_TO_STREAM(args, ulSsidLen); args = UINT16_TO_STREAM(args, 0); if(ucBssid) { ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN); } else { ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); } args = UINT32_TO_STREAM(args, ulPriority); args = UINT32_TO_STREAM(args, 0x0000000C + ulSsidLen); args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen); args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex); ARRAY_TO_STREAM(args, ucSsid, ulSsidLen); for(i = 0; i < 4; i++) { unsigned char *p = &ucPf_OrKey[i * ulPairwiseCipher_Or_TxKeyLen]; ARRAY_TO_STREAM(args, p, ulPairwiseCipher_Or_TxKeyLen); } arg_len = WLAN_ADD_PROFILE_WEP_PARAM_LEN + ulSsidLen + ulPairwiseCipher_Or_TxKeyLen * 4; } break; //WPA //WPA2 case WLAN_SEC_WPA: case WLAN_SEC_WPA2: { args = UINT32_TO_STREAM(args, 0x00000028); args = UINT32_TO_STREAM(args, ulSsidLen); args = UINT16_TO_STREAM(args, 0); if(ucBssid) { ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN); } else { ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); } args = UINT32_TO_STREAM(args, ulPriority); args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen); args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex); args = UINT32_TO_STREAM(args, ulKeyMgmt); args = UINT32_TO_STREAM(args, 0x00000008 + ulSsidLen); args = UINT32_TO_STREAM(args, ulPassPhraseLen); ARRAY_TO_STREAM(args, ucSsid, ulSsidLen); ARRAY_TO_STREAM(args, ucPf_OrKey, ulPassPhraseLen); arg_len = WLAN_ADD_PROFILE_WPA_PARAM_LEN + ulSsidLen + ulPassPhraseLen; } break; } // Initiate a HCI command hci_command_send(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, ptr, arg_len); // Wait for command complete event SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, &ret); return(ret); }
/******************************************************************************* ** ** Function hw_config_cback ** ** Description Callback function for controller configuration ** ** Returns None ** *******************************************************************************/ void hw_config_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; HC_BT_HDR *p_buf=NULL; uint8_t is_proceeding = FALSE; int i; #if (USE_CONTROLLER_BDADDR == TRUE) const uint8_t null_bdaddr[BD_ADDR_LEN] = {0,0,0,0,0,0}; #endif 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); /* Ask a new buffer big enough to hold any HCI commands sent in here */ if ((status == 0) && bt_vendor_cbacks) p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \ HCI_CMD_MAX_LEN); ALOGI("[Atmel %s] rcvd cb with state: %d!!,status:%d,op_code:%x",__func__, hw_cfg_cb.state,status,opcode); if (p_buf != NULL) { p_buf->event = MSG_STACK_TO_HC_HCI_CMD; p_buf->offset = 0; p_buf->len = 0; p_buf->layer_specific = 0; p = (uint8_t *) (p_buf + 1); switch (hw_cfg_cb.state) { case HW_CFG_SET_UART_BAUD_1: /* update baud rate of host's UART port */ ALOGI("bt vendor lib: set UART baud %i", UART_TARGET_BAUD_RATE); userial_vendor_set_baud( \ line_speed_to_userial_baud(UART_TARGET_BAUD_RATE) \ ); /* read local name */ UINT16_TO_STREAM(p, HCI_READ_LOCAL_NAME); *p = 0; /* parameter length */ p_buf->len = HCI_CMD_PREAMBLE_SIZE; hw_cfg_cb.state = HW_CFG_READ_LOCAL_NAME; is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_READ_LOCAL_NAME, \ p_buf, hw_config_cback); break; case HW_CFG_READ_LOCAL_NAME: p_tmp = p_name = (char *) (p_evt_buf + 1) + \ HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING; for (i=0; (i < LOCAL_NAME_BUFFER_LEN)||(*(p_name+i) != 0); i++) *(p_name+i) = toupper(*(p_name+i)); if ((p_name = strstr(p_name, "BCM")) != NULL) { strncpy(hw_cfg_cb.local_chip_name, p_name, \ LOCAL_NAME_BUFFER_LEN-1); } else { strncpy(hw_cfg_cb.local_chip_name, "UNKNOWN", \ LOCAL_NAME_BUFFER_LEN-1); p_name = p_tmp; } hw_cfg_cb.local_chip_name[LOCAL_NAME_BUFFER_LEN-1] = 0; BTHWDBG("Chipset %s", hw_cfg_cb.local_chip_name); if ((status = hw_config_findpatch(p_name)) == TRUE) { if ((hw_cfg_cb.fw_fd = open(p_name, O_RDONLY)) == -1) { ALOGE("vendor lib preload failed to open [%s]", p_name); } else { #if 0 /* vsc_download_minidriver */ UINT16_TO_STREAM(p, HCI_VSC_DOWNLOAD_MINIDRV); *p = 0; /* parameter length */ p_buf->len = HCI_CMD_PREAMBLE_SIZE; hw_cfg_cb.state = HW_CFG_DL_MINIDRIVER; is_proceeding = bt_vendor_cbacks->xmit_cb( \ HCI_VSC_DOWNLOAD_MINIDRV, p_buf, \ hw_config_cback); #endif } } else { ALOGE( \ "vendor lib preload failed to locate firmware patch file" \ ); } if (is_proceeding == FALSE) { //is_proceeding = hw_config_set_bdaddr(p_buf); } break; case HW_CFG_DL_MINIDRIVER: /* give time for placing firmware in download mode */ ms_delay(50); hw_cfg_cb.state = HW_CFG_DL_FW_PATCH; /* fall through intentionally */ case HW_CFG_DL_FW_PATCH: p_buf->len = read(hw_cfg_cb.fw_fd, p, HCI_CMD_PREAMBLE_SIZE); if (p_buf->len > 0) { #if 0 if ((p_buf->len < HCI_CMD_PREAMBLE_SIZE) || \ (opcode == HCI_VSC_LAUNCH_RAM)) { ALOGW("firmware patch file might be altered!"); } else { p_buf->len += read(hw_cfg_cb.fw_fd, \ p+HCI_CMD_PREAMBLE_SIZE,\ *(p+HCD_REC_PAYLOAD_LEN_BYTE)); STREAM_TO_UINT16(opcode,p); is_proceeding = bt_vendor_cbacks->xmit_cb(opcode, \ p_buf, hw_config_cback); break; } #endif } close(hw_cfg_cb.fw_fd); hw_cfg_cb.fw_fd = -1; /* Normally the firmware patch configuration file * sets the new starting baud rate at 115200. * So, we need update host's baud rate accordingly. */ ALOGI("bt vendor lib: set UART baud 115200"); userial_vendor_set_baud(USERIAL_BAUD_115200); /* Next, we would like to boost baud rate up again * to desired working speed. */ hw_cfg_cb.f_set_baud_2 = TRUE; /* Check if we need to pause a few hundred milliseconds * before sending down any HCI command. */ ms_delay(look_up_fw_settlement_delay()); /* fall through intentionally */ case HW_CFG_START: if (UART_TARGET_BAUD_RATE > 3000000) { #if 1 /* set UART clock to 48MHz */ UINT16_TO_STREAM(p, HCI_VSC_WRITE_UART_CLOCK_SETTING); *p++ = 1; /* parameter length */ *p = 1; /* (1,"UART CLOCK 48 MHz")(2,"UART CLOCK 24 MHz") */ p_buf->len = HCI_CMD_PREAMBLE_SIZE + 1; hw_cfg_cb.state = HW_CFG_SET_UART_CLOCK; is_proceeding = bt_vendor_cbacks->xmit_cb( \ HCI_VSC_WRITE_UART_CLOCK_SETTING, \ p_buf, hw_config_cback); break; #endif } /* fall through intentionally */ case HW_CFG_SET_UART_CLOCK: /* set controller's UART baud rate to 3M */ UINT16_TO_STREAM(p, HCI_VSC_UPDATE_BAUDRATE); *p++ = UPDATE_BAUDRATE_CMD_PARAM_SIZE; /* parameter length */ *p++ = 0; /* encoded baud rate */ *p++ = 0; /* use encoded form */ UINT32_TO_STREAM(p, UART_TARGET_BAUD_RATE); p_buf->len = HCI_CMD_PREAMBLE_SIZE + \ UPDATE_BAUDRATE_CMD_PARAM_SIZE; hw_cfg_cb.state = (hw_cfg_cb.f_set_baud_2) ? \ HW_CFG_SET_UART_BAUD_2 : HW_CFG_SET_UART_BAUD_1; is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_VSC_UPDATE_BAUDRATE, \ p_buf, hw_config_cback); break; case HW_CFG_SET_UART_BAUD_2: /* update baud rate of host's UART port */ ALOGI("bt vendor lib: set UART baud %i", UART_TARGET_BAUD_RATE); userial_vendor_set_baud( \ line_speed_to_userial_baud(UART_TARGET_BAUD_RATE) \ ); #if (USE_CONTROLLER_BDADDR == TRUE) if ((is_proceeding = hw_config_read_bdaddr(p_buf)) == TRUE) break; #else // if ((is_proceeding = hw_config_set_bdaddr(p_buf)) == TRUE) // break; #endif /* fall through intentionally */ case HW_CFG_SET_BD_ADDR: ALOGI("vendor lib fwcfg completed"); bt_vendor_cbacks->dealloc(p_buf); bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS); hw_cfg_cb.state = 0; if (hw_cfg_cb.fw_fd != -1) { close(hw_cfg_cb.fw_fd); hw_cfg_cb.fw_fd = -1; } is_proceeding = TRUE; break; #if (USE_CONTROLLER_BDADDR == TRUE) case HW_CFG_READ_BD_ADDR: p_tmp = (char *) (p_evt_buf + 1) + \ HCI_EVT_CMD_CMPL_LOCAL_BDADDR_ARRAY; if (memcmp(p_tmp, null_bdaddr, BD_ADDR_LEN) == 0) { // Controller does not have a valid OTP BDADDR! // Set the BTIF initial BDADDR instead. // if ((is_proceeding = hw_config_set_bdaddr(p_buf)) == TRUE) // break; } else { ALOGI("Controller OTP bdaddr %02X:%02X:%02X:%02X:%02X:%02X", *(p_tmp+5), *(p_tmp+4), *(p_tmp+3), *(p_tmp+2), *(p_tmp+1), *p_tmp); } ALOGI("vendor lib fwcfg completed"); bt_vendor_cbacks->dealloc(p_buf); bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS); hw_cfg_cb.state = 0; if (hw_cfg_cb.fw_fd != -1) { close(hw_cfg_cb.fw_fd); hw_cfg_cb.fw_fd = -1; } is_proceeding = TRUE; break; #endif // (USE_CONTROLLER_BDADDR == TRUE) } // switch(hw_cfg_cb.state) } // if (p_buf != NULL) /* Free the RX event buffer */ if (bt_vendor_cbacks) bt_vendor_cbacks->dealloc(p_evt_buf); if (is_proceeding == FALSE) { ALOGE("vendor lib fwcfg aborted!!!"); if (bt_vendor_cbacks) { if (p_buf != NULL) bt_vendor_cbacks->dealloc(p_buf); bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL); } if (hw_cfg_cb.fw_fd != -1) { close(hw_cfg_cb.fw_fd); hw_cfg_cb.fw_fd = -1; } hw_cfg_cb.state = 0; } }
static void reassemble_and_dispatch(BT_HDR *packet) { LOG_DEBUG("reassemble_and_dispatch\n"); if ((packet->event & MSG_EVT_MASK) == MSG_HC_TO_STACK_HCI_ACL) { uint8_t *stream = packet->data + packet->offset; uint16_t handle; uint16_t l2cap_length; uint16_t acl_length; STREAM_TO_UINT16(handle, stream); STREAM_TO_UINT16(acl_length, stream); STREAM_TO_UINT16(l2cap_length, stream); assert(acl_length == packet->len - HCI_ACL_PREAMBLE_SIZE); uint8_t boundary_flag = GET_BOUNDARY_FLAG(handle); handle = handle & HANDLE_MASK; BT_HDR *partial_packet = (BT_HDR *)hash_map_get(partial_packets, (void *)(uintptr_t)handle); if (boundary_flag == START_PACKET_BOUNDARY) { if (partial_packet) { LOG_WARN("%s found unfinished packet for handle with start packet. Dropping old.\n", __func__); hash_map_erase(partial_packets, (void *)(uintptr_t)handle); buffer_allocator->free(partial_packet); } uint16_t full_length = l2cap_length + L2CAP_HEADER_SIZE + HCI_ACL_PREAMBLE_SIZE; if (full_length <= packet->len) { if (full_length < packet->len) { LOG_WARN("%s found l2cap full length %d less than the hci length %d.\n", __func__, l2cap_length, packet->len); } callbacks->reassembled(packet); return; } partial_packet = (BT_HDR *)buffer_allocator->alloc(full_length + sizeof(BT_HDR)); partial_packet->event = packet->event; partial_packet->len = full_length; partial_packet->offset = packet->len; memcpy(partial_packet->data, packet->data + packet->offset, packet->len); // Update the ACL data size to indicate the full expected length stream = partial_packet->data; STREAM_SKIP_UINT16(stream); // skip the handle UINT16_TO_STREAM(stream, full_length - HCI_ACL_PREAMBLE_SIZE); hash_map_set(partial_packets, (void *)(uintptr_t)handle, partial_packet); // Free the old packet buffer, since we don't need it anymore buffer_allocator->free(packet); } else { if (!partial_packet) { LOG_ERROR("%s got continuation for unknown packet. Dropping it.\n", __func__); buffer_allocator->free(packet); return; } packet->offset += HCI_ACL_PREAMBLE_SIZE; // skip ACL preamble packet->len -= HCI_ACL_PREAMBLE_SIZE; uint16_t projected_offset = partial_packet->offset + packet->len; if (projected_offset > partial_packet->len) { // len stores the expected length LOG_ERROR("%s got packet which would exceed expected length of %d. Truncating.\n", __func__, partial_packet->len); packet->len = partial_packet->len - partial_packet->offset; projected_offset = partial_packet->len; } memcpy( partial_packet->data + partial_packet->offset, packet->data + packet->offset, packet->len ); // Free the old packet buffer, since we don't need it anymore buffer_allocator->free(packet); partial_packet->offset = projected_offset; if (partial_packet->offset == partial_packet->len) { hash_map_erase(partial_packets, (void *)(uintptr_t)handle); partial_packet->offset = 0; callbacks->reassembled(partial_packet); } } } else { callbacks->reassembled(packet); } }
/******************************************************************************* ** ** Function btusb_lite_hci_write_acl_header ** ** Description Write HCI ACL Header (HCI_Type, Connection Handle, Length) ** ** Returns New buffer location ** *******************************************************************************/ static UINT8 *btusb_lite_hci_write_acl_header(UINT8 *p_data, UINT16 con_hdl, UINT16 length) { UINT16_TO_STREAM(p_data, con_hdl); /* Connection Handle */ UINT16_TO_STREAM(p_data, length); /* Length */ return p_data; }
/******************************************************************************* ** ** Function btusb_lite_hci_nocp_event_hdlr ** ** Description Check if the received HCI Event is A NumberOfdComplete Evt ** sub opcode for a Started BAV stream. ** ** Returns status: <> 0 if the event must be send to user space (BSA) ** 0 if the event is handled ** *******************************************************************************/ static int btusb_lite_hci_nocp_event_hdlr(struct btusb *p_dev, UINT8 *p_data, int length) { UINT8 nb_handle; UINT16 con_hdl; UINT16 num_cplt_pck; UINT8 byte; UINT8 *p_save; int send_to_user; UINT16 num_cplt_pck_caugth; /* We are waiting for an Event of, at least, 7 bytes */ if (length < BTUSB_LITE_HCI_NOCP_HCI_LEN) { return 1; /* This is not a NOCP. Send this event to user space */ } /* Extract Event */ STREAM_TO_UINT8(byte, p_data); /* Check if it's a NumberOfCompletePacket Event */ if (byte != HCI_NUM_COMPL_DATA_PKTS_EVT) { return 1; /* This is not a NOCP. Send this event to user space */ } /* Extract Parameter Length */ STREAM_TO_UINT8(byte, p_data); /* Extract Number Of Handle */ STREAM_TO_UINT8(nb_handle, p_data); /* Sanity */ if (byte != (1 + (2 + 2) * nb_handle)) { BTUSB_ERR("Unexpected Evt Size=%d vs.NumberOfHandle=%d\n", byte, nb_handle); return 1; /* This is not a NOCP. Send this event to user space */ } send_to_user = 0; /* For the moment, no Complete Packet sent to user */ /* For every Handle */ while(nb_handle--) { /* Extract the Connection Handle */ STREAM_TO_UINT16(con_hdl, p_data); /* Save the current pointer position (to overwrite number of packet) */ p_save = p_data; /* Extract the Number Of Complete Packet */ STREAM_TO_UINT16(num_cplt_pck, p_data); /* Call the L2CAP NumberOfcompletePacket Handler */ num_cplt_pck_caugth = btusb_lite_l2c_nocp_hdlr(p_dev, con_hdl, num_cplt_pck); /* If L2CAP "caught"at least one nocp packet */ if (num_cplt_pck_caugth) { /* Overwrite the Number Of Complete Packet */ UINT16_TO_STREAM(p_save, num_cplt_pck - num_cplt_pck_caugth); /* If at least one Number Of Complete Packet remains */ if (num_cplt_pck - num_cplt_pck_caugth) { /* Send the event to user space */ send_to_user = 1; } } else { /* Don't update the number but send the event to user space */ send_to_user = 1; } } return send_to_user; }
/******************************************************************************* ** ** Function btusb_lite_hci_event_filter ** ** Description Filter HCI Events received from BT Controller. ** ** Returns status: <> 0 if the event must be send to user space (BSA) ** 0 if the event is handled ** *******************************************************************************/ int btusb_lite_hci_event_filter(struct btusb *p_dev, UINT8 *p_data, int length) { #if 0 BT_HDR *p_msg; UINT8 *p; UINT16 size; #endif /* Check if HCI is over IPC */ if (btusb_lite_is_hci_over_ipc(p_dev) == 0) { /* If it is not, the event have to be sent through regular HCI */ return 1; } /* Check if the Event is a NumberOfCompletePacket Event */ if (btusb_lite_hci_nocp_event_hdlr(p_dev, p_data, length) == 0) { return 0; /* Do not Send this event to user space (we handled it) */ } /* TODO: check if CSB VSE */ return 1; #if 0 /* Add size of both UIPC Length and Event header */ size = length + sizeof(UINT16) + sizeof(UINT16); /* Get a buffer from the pool */ p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + size); if(unlikely(p_msg == NULL)) { BTUSB_ERR("Unable to get GKI buffer\n"); return 0; } if (unlikely(dbgflags & BTUSB_GKI_CHK_MSG) && unlikely(GKI_buffer_status(p_msg) != BUF_STATUS_UNLINKED)) { BTUSB_ERR("buffer != BUF_STATUS_UNLINKED 0x%p\n", p_msg); return; } p_msg->offset = 0; p_msg->event = 0; p_msg->len = size; p = (UINT8 *)(p_msg + 1) + p_msg->offset; UINT16_TO_STREAM(p, length + sizeof(UINT16)); /* UIPC Length */ UINT16_TO_STREAM(p, BT_EVT_TO_BTU_HCI_EVT); /* UIPC Event */ UINT8_TO_STREAM(p, hci_event); /* Write back the HCI Event (we already read it) */ ARRAY_TO_STREAM(p, p_data, length - 1); /* Copy Event data */ /* Send message to User Space */ btusb_lite_ipc_sent_to_user(p_dev, p_msg); return 0; /* Event handled by the Stack Lite. No need to send it to HCI */ #endif }
int32_t cc3000_wlan::add_profile(uint32_t sec_type, uint8_t* ssid, uint32_t ssid_length, uint8_t *b_ssid, uint32_t priority, uint32_t pairwise_cipher_or_tx_key_len, uint32_t group_cipher_tx_key_index, uint32_t key_mgmt, uint8_t* pf_or_key, uint32_t pass_phrase_len) { uint16_t arg_len = 0x00; int32_t ret; uint8_t *ptr; int32_t i = 0; uint8_t *args; uint8_t bssid_zero[] = {0, 0, 0, 0, 0, 0}; ptr = _simple_link.get_transmit_buffer(); args = (ptr + HEADERS_SIZE_CMD); args = UINT32_TO_STREAM(args, sec_type); // Setup arguments in accordance with the security type switch (sec_type) { //OPEN case WLAN_SEC_UNSEC: { args = UINT32_TO_STREAM(args, 0x00000014); args = UINT32_TO_STREAM(args, ssid_length); args = UINT16_TO_STREAM(args, 0); if(b_ssid) { ARRAY_TO_STREAM(args, b_ssid, ETH_ALEN); } else { ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); } args = UINT32_TO_STREAM(args, priority); ARRAY_TO_STREAM(args, ssid, ssid_length); arg_len = WLAN_ADD_PROFILE_NOSEC_PARAM_LEN + ssid_length; } break; //WEP case WLAN_SEC_WEP: { args = UINT32_TO_STREAM(args, 0x00000020); args = UINT32_TO_STREAM(args, ssid_length); args = UINT16_TO_STREAM(args, 0); if(b_ssid) { ARRAY_TO_STREAM(args, b_ssid, ETH_ALEN); } else { ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); } args = UINT32_TO_STREAM(args, priority); args = UINT32_TO_STREAM(args, 0x0000000C + ssid_length); args = UINT32_TO_STREAM(args, pairwise_cipher_or_tx_key_len); args = UINT32_TO_STREAM(args, group_cipher_tx_key_index); ARRAY_TO_STREAM(args, ssid, ssid_length); for(i = 0; i < 4; i++) { uint8_t *p = &pf_or_key[i * pairwise_cipher_or_tx_key_len]; ARRAY_TO_STREAM(args, p, pairwise_cipher_or_tx_key_len); } arg_len = WLAN_ADD_PROFILE_WEP_PARAM_LEN + ssid_length + pairwise_cipher_or_tx_key_len * 4; } break; //WPA //WPA2 case WLAN_SEC_WPA: case WLAN_SEC_WPA2: { args = UINT32_TO_STREAM(args, 0x00000028); args = UINT32_TO_STREAM(args, ssid_length); args = UINT16_TO_STREAM(args, 0); if(b_ssid) { ARRAY_TO_STREAM(args, b_ssid, ETH_ALEN); } else { ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); } args = UINT32_TO_STREAM(args, priority); args = UINT32_TO_STREAM(args, pairwise_cipher_or_tx_key_len); args = UINT32_TO_STREAM(args, group_cipher_tx_key_index); args = UINT32_TO_STREAM(args, key_mgmt); args = UINT32_TO_STREAM(args, 0x00000008 + ssid_length); args = UINT32_TO_STREAM(args, pass_phrase_len); ARRAY_TO_STREAM(args, ssid, ssid_length); ARRAY_TO_STREAM(args, pf_or_key, pass_phrase_len); arg_len = WLAN_ADD_PROFILE_WPA_PARAM_LEN + ssid_length + pass_phrase_len; } break; } // Initiate a HCI command _hci.command_send(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, ptr, arg_len); // Wait for command complete event _event.simplelink_wait_event(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, &ret); return(ret); }
//***************************************************************************** // //! Initiate an HCI Patch Transfer. //! //! \param usOpcode command operation code //! \param ucArgs pointer to the command's arguments buffer //! \param ucArgsLength length of the arguments //! //! \return ESUCCESS if command transfer complete,EFAIL otherwise. //! //! \brief Initiate an HCI cmnd. // //***************************************************************************** void hci_patch_send(unsigned char ucOpcode, unsigned char *pucBuff, char *patch, unsigned short usDataLength) { unsigned char *data_ptr = (pucBuff + SPI_HEADER_SIZE); unsigned short usTransLength; unsigned char *stream = (pucBuff + SPI_HEADER_SIZE); UINT8_TO_STREAM(stream, HCI_TYPE_PATCH); UINT8_TO_STREAM(stream, ucOpcode); stream = UINT16_TO_STREAM(stream, usDataLength + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE); if (usDataLength <= SL_PATCH_PORTION_SIZE) { UINT16_TO_STREAM(stream, usDataLength); stream = UINT16_TO_STREAM(stream, usDataLength); memcpy((pucBuff + SPI_HEADER_SIZE) + HCI_PATCH_HEADER_SIZE, patch, usDataLength); // // Update the opcode of the event we will be waiting for // SpiWrite(pucBuff, usDataLength + HCI_PATCH_HEADER_SIZE); } else { usTransLength = (usDataLength/SL_PATCH_PORTION_SIZE); UINT16_TO_STREAM(stream, usDataLength + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE + usTransLength*SIMPLE_LINK_HCI_PATCH_HEADER_SIZE); stream = UINT16_TO_STREAM(stream, SL_PATCH_PORTION_SIZE); memcpy(pucBuff + SPI_HEADER_SIZE + HCI_PATCH_HEADER_SIZE, patch, SL_PATCH_PORTION_SIZE); usDataLength -= SL_PATCH_PORTION_SIZE; patch += SL_PATCH_PORTION_SIZE; // // Update the opcode of the event we will be waiting for // SpiWrite(pucBuff, SL_PATCH_PORTION_SIZE + HCI_PATCH_HEADER_SIZE); while (usDataLength) { if (usDataLength <= SL_PATCH_PORTION_SIZE) { usTransLength = usDataLength; usDataLength = 0; } else { usTransLength = SL_PATCH_PORTION_SIZE; usDataLength -= usTransLength; } *(unsigned short *)data_ptr = usTransLength; memcpy(data_ptr + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE, patch, usTransLength); patch += usTransLength; // // Update the opcode of the event we will be waiting for // SpiWrite((unsigned char *)data_ptr, usTransLength + sizeof(usTransLength)); } } }
/******************************************************************************* ** ** Function app_3dtv_set_beacon ** ** Description Configure 3DTV Beacon parameters (Broadcasted) ** ** Parameters p_req: pointer to the tAPP_3DTV_SET_BEACON ** ** Returns 0 if successful, -1 in case of error ** *******************************************************************************/ int app_3dtv_set_beacon(tAPP_3DTV_SET_BEACON *p_req) { tBSA_TM_VSC bsa_vsc; tBSA_STATUS bsa_status; UINT8 *p_data; if (p_req == NULL) { APP_ERROR0("Null p_req parameter"); return -1; } APP_DEBUG1("LeftOpen:%d LeftClose:%d RightOpen:%d RightClose:%d Delay:%d", p_req->left_open, p_req->left_close, p_req->right_open, p_req->right_close, p_req->delay); /* Prepare VSC Parameters */ bsa_status = BSA_TmVscInit(&bsa_vsc); bsa_vsc.opcode = BRCM_HCI_VSC_3D_SET_OFFSET; /* 3D Offset and Delay */ p_data = bsa_vsc.data; #ifdef APP_3DTV_OLD_OFFSET_VSC bsa_vsc.length = sizeof(UINT16) * 5; /* 5 words of 16 bits */ UINT16_TO_STREAM(p_data, p_req->left_open); UINT16_TO_STREAM(p_data, p_req->left_close); UINT16_TO_STREAM(p_data, p_req->right_open); UINT16_TO_STREAM(p_data, p_req->right_close); UINT16_TO_STREAM(p_data, p_req->delay); #else APP_DEBUG1("DisplayId:%d DualView:%d", p_req->display_id, p_req->dual_view_mode); bsa_vsc.length = 12; /* DisplayId */ UINT8_TO_STREAM(p_data, p_req->display_id); /* Left Open Offset */ UINT16_TO_STREAM(p_data, p_req->left_open); /* Left Close Offset */ UINT16_TO_STREAM(p_data, p_req->left_close); /* Right Open Offset */ UINT16_TO_STREAM(p_data, p_req->right_open); /* Right Close Offset */ UINT16_TO_STREAM(p_data, p_req->right_close); /* Delay */ UINT16_TO_STREAM(p_data, p_req->delay); /* DualView */ UINT8_TO_STREAM(p_data, p_req->dual_view_mode); #endif bsa_status = BSA_TmVsc(&bsa_vsc); if (bsa_status != BSA_SUCCESS) { APP_ERROR1("BSA_TmVsc failed status:%d", bsa_status); return(-1); } if ((bsa_vsc.status != BSA_SUCCESS) || (bsa_vsc.data[0] != HCI_SUCCESS)) { APP_ERROR1("Unable to Set 3D offsets status:%d hic_status:%d", bsa_vsc.status, bsa_vsc.data[0]); return -1; } return 0; }
/******************************************************************************* ** DIS Attributes Database Server Request callback *******************************************************************************/ UINT8 dis_read_attr_value (UINT8 clcb_idx, UINT16 handle, tGATT_VALUE *p_value, BOOLEAN is_long, tGATT_STATUS *p_status) { tDIS_DB_ENTRY *p_db_attr = dis_cb.dis_attr; UINT8 *p = p_value->value, i, *pp; UINT16 offset = p_value->offset; UINT8 act = SRVC_ACT_RSP; tGATT_STATUS st = GATT_NOT_FOUND; UNUSED(clcb_idx); for (i = 0; i < DIS_MAX_CHAR_NUM; i ++, p_db_attr ++) { if (handle == p_db_attr->handle) { if ((p_db_attr->uuid == GATT_UUID_PNP_ID || p_db_attr->uuid == GATT_UUID_SYSTEM_ID)&& is_long == TRUE) { st = GATT_NOT_LONG; break; } st = GATT_SUCCESS; switch (p_db_attr->uuid) { case GATT_UUID_MANU_NAME: case GATT_UUID_MODEL_NUMBER_STR: case GATT_UUID_SERIAL_NUMBER_STR: case GATT_UUID_FW_VERSION_STR: case GATT_UUID_HW_VERSION_STR: case GATT_UUID_SW_VERSION_STR: case GATT_UUID_IEEE_DATA: pp = dis_cb.dis_value.data_string[p_db_attr->uuid - GATT_UUID_MODEL_NUMBER_STR]; if (pp != NULL) { if (strlen ((char *)pp) > GATT_MAX_ATTR_LEN) p_value->len = GATT_MAX_ATTR_LEN; else p_value->len = (UINT16)strlen ((char *)pp); } else p_value->len = 0; if (offset > p_value->len) { st = GATT_INVALID_OFFSET; break; } else { p_value->len -= offset; pp += offset; ARRAY_TO_STREAM(p, pp, p_value->len); GATT_TRACE_EVENT("GATT_UUID_MANU_NAME len=0x%04x", p_value->len); } break; case GATT_UUID_SYSTEM_ID: UINT64_TO_STREAM(p, dis_cb.dis_value.system_id); /* int_min */ p_value->len = DIS_SYSTEM_ID_SIZE; break; case GATT_UUID_PNP_ID: UINT8_TO_STREAM(p, dis_cb.dis_value.pnp_id.vendor_id_src); UINT16_TO_STREAM(p, dis_cb.dis_value.pnp_id.vendor_id); UINT16_TO_STREAM(p, dis_cb.dis_value.pnp_id.product_id); UINT16_TO_STREAM(p, dis_cb.dis_value.pnp_id.product_version); p_value->len = DIS_PNP_ID_SIZE; break; } break; } } *p_status = st; return act; }