/** * SNP_executeHCIcmd */ uint8_t SNP_executeHCIcmd(snpHciCmdReq_t *pReq, uint16_t dataLen) { bStatus_t stat; uint16_t opcode = pReq->opcode; uint8_t *pData = (uint8_t*)&pReq->pData; uint8_t status = blePending; if(snp_HCIstore.validity) { return SNP_CMD_ALREADY_IN_PROGRESS; } switch (opcode) { case SNP_HCI_OPCODE_EXT_RESET_SYSTEM: { stat = HCI_EXT_ResetSystemCmd(LL_EXT_RESET_SYSTEM_HARD); if(stat == SUCCESS) { status = SNP_SUCCESS; } else { status = bleIncorrectMode; } } break; case SNP_HCI_OPCODE_READ_BDADDR: { stat = HCI_ReadBDADDRCmd(); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_EXT_SET_BDADDR: { if(dataLen != B_ADDR_LEN) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_SetBDADDRCmd(pData); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } } break; case SNP_HCI_OPCODE_EXT_SET_TX_POWER: { if(dataLen != sizeof(uint8_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_SetTxPowerCmd(pData[0]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } } break; case SNP_HCI_OPCODE_EXT_SET_SCA: if(dataLen != sizeof(uint16_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_SetSCACmd((pData[0] &0xFF) + (pData[1] << 8)); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_EXT_MODEM_TEST_TX: if(dataLen != 2*sizeof(uint8_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_ModemTestTxCmd(pData[0], pData[1]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_EXT_MODEM_HOP_TEST_TX: stat = HCI_EXT_ModemHopTestTxCmd(); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } break; case SNP_HCI_OPCODE_EXT_MODEM_TEST_RX: if(dataLen != sizeof(uint8_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_ModemTestRxCmd(pData[0]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_EXT_END_MODEM_TEST: stat = HCI_EXT_EndModemTestCmd(); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } break; case SNP_HCI_OPCODE_EXT_ENABLE_PTM: stat = HCI_EXT_EnablePTMCmd(); if(stat == SUCCESS) { status = SNP_SUCCESS; } else { status = stat; } break; case SNP_HCI_OPCODE_EXT_SET_MAX_DTM_TX_POWER: if(dataLen != sizeof(uint8_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_SetMaxDtmTxPowerCmd(pData[0]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_READ_RSSI: if(dataLen != sizeof(uint16_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_ReadRssiCmd((pData[0] &0xFF) + (pData[1] << 8)); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_LE_RECEIVER_TEST: if(dataLen != sizeof(uint8_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_LE_ReceiverTestCmd(pData[0]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_LE_TRANSMITTER_TEST: if(dataLen != 3 * sizeof(uint8_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_LE_TransmitterTestCmd(pData[0], pData[1], pData[2]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_LE_TEST_END: stat = HCI_LE_TestEndCmd(); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } break; case SNP_HCI_OPCODE_EXT_PER: if(dataLen != (sizeof(uint8_t) + sizeof(uint16_t))) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_PacketErrorRateCmd(pData[0] + (pData[1] << 8), pData[2]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_EXT_DECRYPT: if(dataLen != (KEYLEN + KEYLEN)) { status = SNP_INVALID_PARAMS; } else { // reverse byte order of key (MSB..LSB required) SNP_ReverseBytes(&pData[0], KEYLEN); // reverse byte order of encText (MSB..LSB required) SNP_ReverseBytes(&pData[KEYLEN], KEYLEN); stat = HCI_EXT_DecryptCmd(&pData[0], &pData[KEYLEN]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_LE_ENCRYPT: if(dataLen != (KEYLEN + KEYLEN)) { status = SNP_INVALID_PARAMS; } else { // reverse byte order of key (MSB..LSB required) SNP_ReverseBytes(&pData[0], KEYLEN); // reverse byte order of encText (MSB..LSB required) SNP_ReverseBytes(&pData[KEYLEN], KEYLEN); stat = HCI_LE_EncryptCmd(&pData[0], &pData[KEYLEN]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_EXT_OVERRIDE_SL: if(dataLen != sizeof(uint8_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_SetSlaveLatencyOverrideCmd(pData[0]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_EXT_SET_FAST_TX_RESP_TIME: if(dataLen != sizeof(uint8_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_SetFastTxResponseTimeCmd(pData[0]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_EXT_ONE_PKT_PER_EVT: if(dataLen != sizeof(uint8_t)) { status = SNP_INVALID_PARAMS; } else { stat = HCI_EXT_OnePktPerEvtCmd(pData[0]); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } } break; case SNP_HCI_OPCODE_EXT_GET_CONNECTION_INFO: stat = HCI_EXT_GetConnInfoCmd(NULL, NULL, NULL); if(stat == SUCCESS) { // Set state to wait for the HCI event with the address snp_HCIstore.validity = TRUE; snp_HCIstore.opcode = opcode; status = blePending; } else { status = stat; } break; default: status = SNP_HCI_CMD_UNKNOWN; break; } return status; }
/********************************************************************* * @fn hidappCentralEventCB * * @brief Notification from the profile of a state change. * * @param pEvent - new role event * * @return none */ static void hidappCentralEventCB( gapCentralRoleEvent_t *pEvent ) { static uint8 addrType; static uint8 peerDeviceFound = FALSE; switch( pEvent->gap.opcode ) { case GAP_DEVICE_INIT_DONE_EVENT: { gapDeviceInitDoneEvent_t *pEvt = (gapDeviceInitDoneEvent_t *)pEvent; // See if device has a valid BD Address if ( osal_isbufset( pEvt->devAddr, 0xFF, B_ADDR_LEN ) == FALSE ) { #if defined ( NANO_DONGLE ) if ( hidappBondCount() > 0 ) { // Initiate connection hidappEstablishLink( TRUE, addrType, remoteAddr ); } else { // Sit idle till ask to scan hidappSetIdle(); } #endif // #if defined ( NANO_DONGLE ) } else { uint8 ownBDaddr[] = OWN_ADDR; // An old CC2540 USB Dongle has all 0xFF's for its BD Address so // just use the hard-coded address in that case. HCI_EXT_SetBDADDRCmd( ownBDaddr ); // Re-initialize the device with the new address osal_set_event( hidappTaskId, HIDAPP_EVT_START ); } } break; case GAP_DEVICE_INFO_EVENT: // Goes here before entering GAP_DEVICE_DISCOVERY_EVENT // Read advertising/scan response data // if it contains HID remote, end service discovery if ( hidappFindSvcUuid( HID_SERVICE_UUID, pEvent->deviceInfo.pEvtData, pEvent->deviceInfo.dataLen ) ) { // Record peer devices address data addrType = pEvent->deviceInfo.addrType; osal_memcpy( remoteAddr, pEvent->deviceInfo.addr, B_ADDR_LEN ); peerDeviceFound = TRUE; } if ( ( peerDeviceFound == TRUE ) && ( pEvent->deviceInfo.eventType == GAP_ADTYPE_SCAN_RSP_IND ) && hidappFindHIDRemote( pEvent->deviceInfo.pEvtData, pEvent->deviceInfo.dataLen ) ) { // End device discovery VOID GAPCentralRole_CancelDiscovery(); } break; case GAP_DEVICE_DISCOVERY_EVENT: // If we have found a connectable device, establish a connection if ( peerDeviceFound == TRUE ) { hidappEstablishLink( FALSE, addrType, remoteAddr ); peerDeviceFound = FALSE; numScans = 0; } else if ( numScans > 0 ) { numScans--; // Scan again hidappDiscoverDevices(); } else { // Go idle hidappSetIdle(); } break; case GAP_LINK_ESTABLISHED_EVENT: // Cancel initiate connection timer VOID osal_stop_timerEx( hidappTaskId, HIDAPP_EVT_INIT_CONNECT ); if ( pEvent->gap.hdr.status == SUCCESS ) { hidappBLEState = BLE_STATE_CONNECTED; HalLedSet( HAL_LED_1, HAL_LED_MODE_ON ); // green led connHandle = ((gapEstLinkReqEvent_t*)pEvent)->connectionHandle; } else if ( hidappBondCount() > 0 ) { // Re-initiate connection hidappEstablishLink( TRUE, addrType, remoteAddr ); } else { // Go idle hidappSetIdle(); } break; case GAP_LINK_TERMINATED_EVENT: // Cancel initiate connection timer VOID osal_stop_timerEx( hidappTaskId, HIDAPP_EVT_INIT_CONNECT ); HalLedSet( HAL_LED_1, HAL_LED_MODE_OFF ); // green led hidappBLEState = BLE_STATE_IDLE; gapBondMgrState = UNPAIRED_STATE; connHandle = INVALID_CONNHANDLE; if ( serviceDiscComplete == TRUE ) { // Remember the address of the last connected remote osal_memcpy( remoteHandles.lastRemoteAddr, remoteAddr, B_ADDR_LEN ); // Save handle information hidappSaveHandles(); } // Invalidate service discovery variables. serviceDiscComplete = FALSE; mouseCharHandle = GATT_INVALID_HANDLE; keyCharHandle = GATT_INVALID_HANDLE; consumerCtrlCharHandle = GATT_INVALID_HANDLE; mouseCCCHandle = GATT_INVALID_HANDLE; keyCCCHandle = GATT_INVALID_HANDLE; consumerCtrlCCCHandle = GATT_INVALID_HANDLE; serviceChangeHandle = GATT_INVALID_HANDLE; serviceToDiscover = GATT_INVALID_HANDLE; enableCCCDs = TRUE; if ( hidappBondCount() > 0 ) { // Re-initiate connection hidappEstablishLink( TRUE, addrType, remoteAddr ); } else { // Go idle hidappSetIdle(); } break; default: break; } }
/********************************************************************* * @fn DualImageConcept_init * * @brief Called during initialization and contains application * specific initialization (ie. hardware initialization/setup, * table initialization, power up notification, etc), and * profile initialization/setup. * * @param None. * * @return None. */ static void DualImageConcept_init(void) { // For CC1350LP Set DIO1 High for 2.4 GHz Radio usage. // Set DIO30 High to power radio. // ****************************************************************** // N0 STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp // ****************************************************************** // Register the current thread as an ICall dispatcher application // so that the application can send and receive messages. ICall_registerApp(&selfEntity, &sem); // Hard code the BD Address till CC2650 board gets its own IEEE address uint8 bdAddress[B_ADDR_LEN] = { 0x1C, 0xCD, 0xD1, 0x1C, 0xCD, 0xD1 }; HCI_EXT_SetBDADDRCmd(bdAddress); // Set device's Sleep Clock Accuracy //HCI_EXT_SetSCACmd(40); // Create an RTOS queue for message from profile to be sent to app. appMsgQueue = Util_constructQueue(&appMsg); Board_initKeys(DualImageConcept_keyChangeHandler); dispHandle = Display_open(Display_Type_LCD, NULL); // Setup the GAP GAP_SetParamValue(TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL); // Setup the GAP Peripheral Role Profile { // For all hardware platforms, device starts advertising upon initialization uint8_t initialAdvertEnable = TRUE; // By setting this to zero, the device will go into the waiting state after // being discoverable for 30.72 second, and will not being advertising again // until the enabler is set back to TRUE uint16_t advertOffTime = 0; uint8_t enableUpdateRequest = DEFAULT_ENABLE_UPDATE_REQUEST; uint16_t desiredMinInterval = DEFAULT_DESIRED_MIN_CONN_INTERVAL; uint16_t desiredMaxInterval = DEFAULT_DESIRED_MAX_CONN_INTERVAL; uint16_t desiredSlaveLatency = DEFAULT_DESIRED_SLAVE_LATENCY; uint16_t desiredConnTimeout = DEFAULT_DESIRED_CONN_TIMEOUT; // Set the GAP Role Parameters GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initialAdvertEnable); GAPRole_SetParameter(GAPROLE_ADVERT_OFF_TIME, sizeof(uint16_t), &advertOffTime); GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData), scanRspData); GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData); GAPRole_SetParameter(GAPROLE_PARAM_UPDATE_ENABLE, sizeof(uint8_t), &enableUpdateRequest); GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16_t), &desiredMinInterval); GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16_t), &desiredMaxInterval); GAPRole_SetParameter(GAPROLE_SLAVE_LATENCY, sizeof(uint16_t), &desiredSlaveLatency); GAPRole_SetParameter(GAPROLE_TIMEOUT_MULTIPLIER, sizeof(uint16_t), &desiredConnTimeout); } // Set the GAP Characteristics GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName); // Set advertising interval { uint16_t advInt = DEFAULT_ADVERTISING_INTERVAL; GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MIN, advInt); GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MAX, advInt); GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, advInt); GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, advInt); } // Initialize GATT attributes GGS_AddService(GATT_ALL_SERVICES); // GAP GATTServApp_AddService(GATT_ALL_SERVICES); // GATT attributes // Start the Device VOID GAPRole_StartDevice(&DualImageConcept_gapRoleCBs); Display_print0(dispHandle, 0, 0, "CC1350 BLE Image A"); // Check for shared data osal_snv_read(0x80, sizeof(uint8_t), &sharedData); // Write the shared data to the LCD. Display_print1(dispHandle, 6, 0, "Shared Data: %d", sharedData); }