/** * ¸Ä±äµÆ¹âµÄº¯Êý£¬phoneStatus ÊÖ»ú״̬£¬isChange ÊÇ·ñ²¥·ÅÇл»Ð§¹û¡£ * phoneStatus = -2 ±íʾ¶ÁÈ¡µ½ÁËcharacteristic1 µÄÊý×éÖµ¡£ * phoneStatus = -1 ±íʾ¶ÁÈ¡µ½ÁËcharacteristic2 µÄÊý×éÖµ¡£ */ static void dataChange(int8 phoneStatus,uint8 isChange){ HalLcdWriteStringValue( "phoneStatus +£º", phoneStatus, 10, HAL_LCD_LINE_7 ); uint8 newValueBuf[20]={0}; SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR1, newValueBuf ); //Ö»¶ÁÈ¡µ½Êý×é1µÄÊý¾Ý£¬ÏȲ»¸Ä±äµÆ¹âÖ»¼Ç¼ÏÂÀ´£¬µÈÊý×é2µÄÊý¾Ý±»¶Áµ½ºó²Å½øÐеƹâ¸Ä±äµÄ²Ù×÷¡£ if(phoneStatus == -2){ //HalLcdWriteStringValue( "Char 1:", newValueBuf[0], 10, HAL_LCD_LINE_3 ); init_QI_Switch(newValueBuf[1]); return; } uint8 newValueBuf2[20]={0}; SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR2, newValueBuf2 ); //newValueBuf[0] = 1; if(phoneStatus >=0){ newValueBuf[0] = phoneStatus; //HalLcdWriteStringValue( "change:", newValueBuf[13], 10, HAL_LCD_LINE_4 ); //HalLcdWriteStringValue( "change:", newValueBuf[16], 10, HAL_LCD_LINE_5 ); } HalLcdWriteStringValue( "status:", newValueBuf[0], 10, HAL_LCD_LINE_6 ); if(newValueBuf[0] != 16){ //дÈëµ½flashÖÐ osal_snv_write(0x80,20,newValueBuf); osal_snv_write(0x95,20,newValueBuf2); } //¸Ä±äµÈÑÕÉ« setValus(newValueBuf,newValueBuf2,isChange); LedChange(); }
/********************************************************************* * @fn gapCentralRole_ProcessGAPMsg * * @brief Process an incoming task message from GAP. * * @param pMsg - message to process * * @return none */ static void gapCentralRole_ProcessGAPMsg( gapEventHdr_t *pMsg ) { switch ( pMsg->opcode ) { case GAP_DEVICE_INIT_DONE_EVENT: { gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *) pMsg; if ( pPkt->hdr.status == SUCCESS ) { // Save off the generated keys VOID osal_snv_write( BLE_NVID_IRK, KEYLEN, gapCentralRoleIRK ); VOID osal_snv_write( BLE_NVID_CSRK, KEYLEN, gapCentralRoleSRK ); // Save off the information VOID osal_memcpy( gapCentralRoleBdAddr, pPkt->devAddr, B_ADDR_LEN ); } } break; case GAP_LINK_ESTABLISHED_EVENT: { gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *) pMsg; if (pPkt->hdr.status == SUCCESS) { // Notify the Bond Manager of the connection VOID GAPBondMgr_LinkEst( pPkt->devAddrType, pPkt->devAddr, pPkt->connectionHandle, GAP_PROFILE_CENTRAL ); } } break; case GAP_LINK_TERMINATED_EVENT: { uint16 connHandle = ((gapTerminateLinkEvent_t *) pMsg)->connectionHandle; GAPBondMgr_ProcessGAPMsg( (gapEventHdr_t *)pMsg ); // Cancel RSSI reads GAPCentralRole_CancelRssi( connHandle ); } break; // temporary workaround case GAP_SLAVE_REQUESTED_SECURITY_EVENT: GAPBondMgr_ProcessGAPMsg( pMsg ); break; default: break; } // Pass event to app if ( pGapCentralRoleCB && pGapCentralRoleCB->eventCB ) { pGapCentralRoleCB->eventCB( (gapCentralRoleEvent_t *) pMsg ); } }
/********************************************************************* * @fn simpleProfileChangeCB * * @brief Callback from SimpleBLEProfile indicating a value change * * @param paramID - parameter ID of the value that was changed. * * @return none */ static void simpleProfileChangeCB( uint8 paramID ) { uint8 newValue; switch( paramID ) { case SIMPLEPROFILE_CHAR1: SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR1, &newValue ); //存储mp,校准是需要重新写入measured power osal_snv_write(0xfe,1,&newValue); //通知重启 osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD ); #if (defined HAL_LCD) && (HAL_LCD == TRUE) HalLcdWriteStringValue( "Char 1:", (uint16)(newValue), 10, HAL_LCD_LINE_3 ); #endif // (defined HAL_LCD) && (HAL_LCD == TRUE) break; case SIMPLEPROFILE_CHAR3: SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR3, &newValue ); #if (defined HAL_LCD) && (HAL_LCD == TRUE) HalLcdWriteStringValue( "Char 3:", (uint16)(newValue), 10, HAL_LCD_LINE_3 ); #endif // (defined HAL_LCD) && (HAL_LCD == TRUE) break; default: // should not reach here! break; } }
/** * @brief Central Profile Task event processing function. * * @param taskId - Task ID * @param events - Events. * * @return events not processed */ uint16 GAPCentralRole_ProcessEvent( uint8 taskId, uint16 events ) { if ( events & SYS_EVENT_MSG ) { uint8 *pMsg; if ( (pMsg = osal_msg_receive( gapCentralRoleTaskId )) != NULL ) { gapCentralRole_ProcessOSALMsg( (osal_event_hdr_t *) pMsg ); // Release the OSAL message VOID osal_msg_deallocate( pMsg ); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } if ( events & GAP_EVENT_SIGN_COUNTER_CHANGED ) { // Sign counter changed, save it to NV VOID osal_snv_write( BLE_NVID_SIGNCOUNTER, sizeof( uint32 ), &gapCentralRoleSignCounter ); return ( events ^ GAP_EVENT_SIGN_COUNTER_CHANGED ); } // Discard unknown events return 0; }
void Init_Para(void) { int8 ret8 = osal_snv_read(0x80, sizeof(SYS_CONFIG), &sys_config); // 如果该段内存未曾写入过数据, 直接读,会返回 NV_OPER_FAILED , // 我们利用这个特点作为第一次烧录后的运行, 从而设置参数的出厂设置 if(NV_OPER_FAILED == ret8) { // 未初始化 osal_memset(&sys_config, 0, sizeof(SYS_CONFIG)); sys_config.update_time_ms = TEMP_DEFAULT_UPDATE_TIME_MS; sprintf((char*)sys_config.name, DEFAULT_DEVICE_NAME); // 默认设备名称 // 最高温度报警 sys_config.tempeature_hight = DEFAULT_TEMP_HIGHT_ALERT; // 最低温度报警 sys_config.tempeature_low = DEFAULT_TEMP_LOW_ALERT; // 4路 pwm 设置, 相对于0xFF 的占空比 sys_config.pwm[0] = 0; sys_config.pwm[1] = 0; sys_config.pwm[2] = 255; sys_config.pwm[3] = 0; g_initFlag = FALSE; osal_snv_write(0x80, sizeof(SYS_CONFIG), &sys_config); // 写所有参数 } else { g_initFlag = TRUE; } }
/********************************************************************* * @fn gapBondMgrChangeState * * @brief Change a state flag in the stateFlags field of the bond record. * * @param idx - Bond NV index * @param state - state flag to set or clear * @param set - TRUE to set the flag, FALSE to clear the flag * * @return TRUE if NV Record exists, FALSE if NV Record is empty */ static uint8 gapBondMgrChangeState( uint8 idx, uint16 state, uint8 set ) { gapBondRec_t bondRec; // Space to read a Bond record from NV // Look for public address that is used (not all 0xFF's) if ( (osal_snv_read( mainRecordNvID(idx), sizeof ( gapBondRec_t ), &bondRec ) == SUCCESS) && (osal_isbufset( bondRec.publicAddr, 0xFF, B_ADDR_LEN ) == FALSE) ) { // Update the state of the bonded device. uint8 stateFlags = bondRec.stateFlags; if ( set ) { stateFlags |= state; } else { stateFlags &= ~(state); } if ( stateFlags != bondRec.stateFlags ) { bondRec.stateFlags = stateFlags; VOID osal_snv_write( mainRecordNvID(idx), sizeof ( gapBondRec_t ), &bondRec ); } return ( TRUE ); } return ( FALSE ); }
/** * @brief Central Profile Task event processing function. * * @param taskId - Task ID * @param events - Events. * * @return events not processed */ uint16 GAPCentralRole_ProcessEvent( uint8 taskId, uint16 events ) { if ( events & SYS_EVENT_MSG ) { uint8 *pMsg; if ( (pMsg = osal_msg_receive( gapCentralRoleTaskId )) != NULL ) { gapCentralRole_ProcessOSALMsg( (osal_event_hdr_t *) pMsg ); // Release the OSAL message VOID osal_msg_deallocate( pMsg ); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } if ( events & GAP_EVENT_SIGN_COUNTER_CHANGED ) { // Sign counter changed, save it to NV VOID osal_snv_write( BLE_NVID_SIGNCOUNTER, sizeof( uint32 ), &gapCentralRoleSignCounter ); return ( events ^ GAP_EVENT_SIGN_COUNTER_CHANGED ); } if ( events & START_ADVERTISING_EVT ) { if ( gapRole_AdvEnabled ) { gapAdvertisingParams_t params; // Setup advertisement parameters params.eventType = gapRole_AdvEventType; params.initiatorAddrType = gapRole_AdvDirectType; VOID osal_memcpy( params.initiatorAddr, gapRole_AdvDirectAddr, B_ADDR_LEN ); params.channelMap = gapRole_AdvChanMap; params.filterPolicy = gapRole_AdvFilterPolicy; if ( GAP_MakeDiscoverable( gapRole_TaskID, ¶ms ) != SUCCESS ) { gapRole_state = GAPROLE_ERROR; // Notify the application if ( pGapCentralRoleCB && pGapCentralRoleCB->broadcastCB ) { pGapCentralRoleCB->broadcastCB( gapRole_state ); } } } return ( events ^ START_ADVERTISING_EVT ); } // Discard unknown events return 0; }
/********************************************************************* * @fn switchImage * * @brief Write to BIM's ledger page to signal the other image should be * executed after reset. * * @param none * * @return VIMS state */ static void switchImage(void) { uint8_t id; // Write Image B's ID so that it will be loaded on reset. id = LOAD_IMG_B; osal_snv_write(NV_ID_IMAGE_EXECUTE, sizeof(uint8_t), &id); }
/** * @brief Task entry point for the GAP Peripheral Role. * * @param a0 - first argument * @param a1 - second argument * * @return none */ static void gapCentralRole_taskFxn(UArg a0, UArg a1) { // Initialize profile gapCentralRole_init(); // Profile main loop for (;;) { // Waits for a signal to the semaphore associated with the calling thread. // Note that the semaphore associated with a thread is signaled when a // message is queued to the message receive queue of the thread or when // ICall_signal() function is called onto the semaphore. ICall_Errno errno = ICall_wait(ICALL_TIMEOUT_FOREVER); if (errno == ICALL_ERRNO_SUCCESS) { ICall_EntityID dest; ICall_ServiceEnum src; ICall_HciExtEvt *pMsg = NULL; if (ICall_fetchServiceMsg(&src, &dest, (void **)&pMsg) == ICALL_ERRNO_SUCCESS) { uint8_t safeToDealloc = TRUE; if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == selfEntity)) { ICall_Event *pEvt = (ICall_Event *)pMsg; // Check for BLE stack events first if (pEvt->signature == 0xffff) { if (pEvt->event_flag & GAP_EVENT_SIGN_COUNTER_CHANGED) { // Sign counter changed, save it to NV VOID osal_snv_write(BLE_NVID_SIGNCOUNTER, sizeof(uint32_t), &gapCentralRoleSignCounter); } } else { // Process inter-task message safeToDealloc = gapCentralRole_processStackMsg((ICall_Hdr *)pMsg); } } if (pMsg && safeToDealloc) { ICall_freeMsg(pMsg); } } } } }
/********************************************************************* * @fn gapBondMgrAddBond * * @brief Save a bond from a GAP Auth Complete Event * * @param pBondRec - basic bond record * @param pLocalLTK - LTK used by this device during pairing * @param pDevLTK - LTK used by the connected device during pairing * @param pIRK - IRK used by the connected device during pairing * @param pSRK - SRK used by the connected device during pairing * @param signCounter - Sign counter used by the connected device during pairing * * @return bond index */ static uint8 gapBondMgrAddBond( gapBondRec_t *pBondRec, gapBondLTK_t *pLocalLTK, gapBondLTK_t *pDevLTK, uint8 *pIRK, uint8 *pSRK, uint32 signCounter ) { uint8 idx; if ( pBondRec == NULL ) { return ( GAP_BONDINGS_MAX ); } // First see if we already have an existing bond for this device idx = gapBondMgrFindAddr( pBondRec->publicAddr ); if ( idx >= GAP_BONDINGS_MAX ) { idx = gapBondMgrFindEmpty(); } if ( idx < GAP_BONDINGS_MAX ) { // Save the main information VOID osal_snv_write( mainRecordNvID(idx), sizeof ( gapBondRec_t ), pBondRec ); // If available, save the LTK information if ( pLocalLTK ) { VOID osal_snv_write( localLTKNvID(idx), sizeof ( gapBondLTK_t ), pLocalLTK ); } // If available, save the connected device's LTK information if ( pDevLTK ) { VOID osal_snv_write( devLTKNvID(idx), sizeof ( gapBondLTK_t ), pDevLTK ); } // If available, save the connected device's IRK if ( pIRK ) { VOID osal_snv_write( devIRKNvID(idx), KEYLEN, pIRK ); } // If available, save the connected device's Signature information if ( pSRK ) { VOID osal_snv_write( devCSRKNvID(idx), KEYLEN, pSRK ); VOID osal_snv_write( devSignCounterNvID(idx), sizeof ( uint32 ), &signCounter ); } } // Update the GAP Privacy Flag Properties gapBondSetupPrivFlag(); return ( idx ); }
/********************************************************************* * @fn DualImageConcept_handleKeys * * @brief Handles all key events for this device. * * @param shift - true if in shift/alt. * @param keys - bit field for key events. Valid entries: * HAL_KEY_SW_2 * HAL_KEY_SW_1 * * @return none */ static void DualImageConcept_handleKeys(uint8_t shift, uint8_t keys) { (void)shift; // Intentionally unreferenced parameter if (keys & DIC_SWITCH_IMAGE_BUTTON) { // Increment and write shared data sharedData++; osal_snv_write(NV_ID_SHARED_DATA, sizeof(uint8_t), &sharedData); // Signal a change in images to run. switchImage(); // Reset. HAL_SYSTEM_RESET(); // Should never get here. } }
void lock_init(void) { uint8 read_tmp[6] = {0}; uint8 use_lock_times[2] = {0}; uint8 ret8; osal_memset(read_tmp, '0', sizeof(read_tmp)); ret8 = osal_snv_write(admin_flash_start_addr, sizeof(read_tmp), read_tmp); if(ret8 == NV_OPER_FAILED) return; osal_memset(read_tmp, '1', sizeof(read_tmp)); ret8 = osal_snv_write(user_flash_start_addr, sizeof(read_tmp), read_tmp); if(ret8 == NV_OPER_FAILED) return; osal_memcpy(read_tmp, ssid, 6); ret8 = osal_snv_write(ssid_flash_start_addr, sizeof(read_tmp), read_tmp); if(ret8 == NV_OPER_FAILED) return; osal_memcpy(scanRspData + 2, read_tmp, 6); osal_memcpy(attDeviceName, read_tmp, 6); GAP_UpdateAdvertisingData( simpleBLEPeripheral_TaskID, FALSE, sizeof( scanRspData ), scanRspData ); GGS_SetParameter( GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName ); osal_memset(read_tmp, '0', sizeof(read_tmp)); ret8 = osal_snv_write(dead_date_flash_start_addr, sizeof(read_tmp), read_tmp); if(ret8 == NV_OPER_FAILED) return; osal_memset(read_tmp, '0', sizeof(read_tmp)); ret8 = osal_snv_write(carlock_id_flash_start_addr, sizeof(read_tmp), read_tmp); if(ret8 == NV_OPER_FAILED) return; osal_memset(use_lock_times, 0, sizeof(use_lock_times)); ret8 = osal_snv_write(use_lock_times_start_addr, sizeof(use_lock_times), use_lock_times); if(ret8 == NV_OPER_FAILED) return; HAL_SYSTEM_RESET();//reset }
/********************************************************************* * @fn gapBondMgrEraseBonding * * @brief Write all 0xFF's to the complete bonding record * * @param idx - bonding index * * @return SUCCESS if successful. * Otherwise, NV_OPER_FAILED for failure. */ static bStatus_t gapBondMgrEraseBonding( uint8 idx ) { bStatus_t ret; gapBondRec_t bondRec; gapBondLTK_t ltk; VOID osal_memset( &bondRec, 0xFF, sizeof ( gapBondRec_t ) ); VOID osal_memset( <k, 0xFF, sizeof ( gapBondLTK_t ) ); // Write out FF's over the entire bond entry. ret = osal_snv_write( mainRecordNvID(idx), sizeof ( gapBondRec_t ), &bondRec ); ret |= osal_snv_write( localLTKNvID(idx), sizeof ( gapBondLTK_t ), <k ); ret |= osal_snv_write( devLTKNvID(idx), sizeof ( gapBondLTK_t ), <k ); ret |= osal_snv_write( devIRKNvID(idx), KEYLEN, ltk.LTK ); ret |= osal_snv_write( devCSRKNvID(idx), KEYLEN, ltk.LTK ); ret |= osal_snv_write( devSignCounterNvID(idx), sizeof ( uint32 ), ltk.LTK ); // Update the GAP Privacy Flag Properties gapBondSetupPrivFlag(); return ( ret ); }
/********************************************************************* * @fn gapRole_ProcessGAPMsg * * @brief Process an incoming task message. * * @param pMsg - message to process * * @return none */ void gapBondMgr_ProcessGAPMsg( gapEventHdr_t *pMsg ) { switch ( pMsg->opcode ) { case GAP_PASSKEY_NEEDED_EVENT: { gapPasskeyNeededEvent_t *pPkt = (gapPasskeyNeededEvent_t *)pMsg; if ( pGapBondCB && pGapBondCB->passcodeCB ) { // Ask app for a passcode pGapBondCB->passcodeCB( pPkt->deviceAddr, pPkt->connectionHandle, pPkt->uiInputs, pPkt->uiOutputs ); } else { // No app support, use the default passcode if ( GAP_PasscodeUpdate( gapBond_Passcode, pPkt->connectionHandle ) != SUCCESS ) { VOID GAP_TerminateAuth( pPkt->connectionHandle, SMP_PAIRING_FAILED_PASSKEY_ENTRY_FAILED ); } } } break; case GAP_AUTHENTICATION_COMPLETE_EVENT: { gapAuthCompleteEvent_t *pPkt = (gapAuthCompleteEvent_t *)pMsg; // Should we save bonding information if ( (pPkt->hdr.status == SUCCESS) && (pPkt->authState & SM_AUTH_STATE_BONDING) ) { gapBondRec_t bondRec; VOID osal_memset( &bondRec, 0, sizeof ( gapBondRec_t ) ) ; // Do we have a public address in the data? if ( pPkt->pIdentityInfo ) { VOID osal_memcpy( bondRec.publicAddr, pPkt->pIdentityInfo->bd_addr, B_ADDR_LEN ); } else { linkDBItem_t *pLinkItem = linkDB_Find( pPkt->connectionHandle ); if ( pLinkItem ) { VOID osal_memcpy( bondRec.publicAddr, pLinkItem->addr, B_ADDR_LEN ); } else { // We don't have an address, so ignore the message. break; } } // Save off of the authentication state bondRec.stateFlags |= (pPkt->authState & SM_AUTH_STATE_AUTHENTICATED) ? GAP_BONDED_STATE_AUTHENTICATED : 0; VOID gapBondMgrAddBond( &bondRec, (gapBondLTK_t *)pPkt->pSecurityInfo, (gapBondLTK_t *)pPkt->pDevSecInfo, ((uint8 *)((pPkt->pIdentityInfo) ? pPkt->pIdentityInfo->irk : NULL )), ((uint8 *)((pPkt->pSigningInfo) ? pPkt->pSigningInfo->srk : NULL )), ((uint32)((pPkt->pSigningInfo) ? pPkt->pSigningInfo->signCounter : GAP_INIT_SIGN_COUNTER )) ); } // Call app state callback if ( pGapBondCB && pGapBondCB->pairStateCB ) { pGapBondCB->pairStateCB( GAPBOND_PAIRING_STATE_COMPLETE, pPkt->hdr.status ); } } break; case GAP_BOND_COMPLETE_EVENT: // This message is received when the bonding is complete. If hdr.status is SUCCESS // then call app state callback. If hdr.status is NOT SUCCESS, the connection will be // dropped at the LL because of a MIC failure, so again nothing to do. if ( pGapBondCB && pGapBondCB->pairStateCB && pMsg->hdr.status == SUCCESS ) { pGapBondCB->pairStateCB( GAPBOND_PAIRING_STATE_BONDED, pMsg->hdr.status ); } break; case GAP_SIGNATURE_UPDATED_EVENT: { uint8 idx; gapSignUpdateEvent_t *pPkt = (gapSignUpdateEvent_t *)pMsg; idx = GAPBondMgr_ResolveAddr( pPkt->addrType, pPkt->devAddr, NULL ); if ( idx < GAP_BONDINGS_MAX ) { // Save the sign counter VOID osal_snv_write( devSignCounterNvID(idx), sizeof ( uint32 ), &(pPkt->signCounter) ); } } break; case GAP_PAIRING_REQ_EVENT: { gapPairingReqEvent_t *pPkt = (gapPairingReqEvent_t *)pMsg; if ( gapBond_AutoFail != FALSE ) { // Auto Fail TEST MODE (DON'T USE THIS) - Sends pre-setup reason VOID GAP_TerminateAuth( pPkt->connectionHandle, gapBond_AutoFailReason ); } else if ( gapBond_PairingMode == GAPBOND_PAIRING_MODE_NO_PAIRING ) { // No Pairing - Send error VOID GAP_TerminateAuth( pPkt->connectionHandle, SMP_PAIRING_FAILED_NOT_SUPPORTED ); } else { gapAuthParams_t params; linkDBItem_t *pLinkItem = linkDB_Find( pPkt->connectionHandle ); // Requesting bonding? if ( pPkt->pairReq.authReq & SM_AUTH_STATE_BONDING ) { if ( pLinkItem ) { if ( (pLinkItem->addrType != ADDRTYPE_PUBLIC) && (pPkt->pairReq.keyDist.mIdKey == FALSE) ) { uint8 publicAddr[B_ADDR_LEN]; // Check if we already have the public address in NV if ( GAPBondMgr_ResolveAddr(pLinkItem->addrType, pLinkItem->addr, publicAddr ) == FALSE ) { // Can't bond to a non-public address if we don't know the public address VOID GAP_TerminateAuth( pPkt->connectionHandle, SMP_PAIRING_FAILED_AUTH_REQ ); break; } } } else { // Can't find the connection, ignore the message break; } } VOID osal_memset( ¶ms, 0, sizeof ( gapAuthParams_t ) ); // Setup the pairing parameters params.connectionHandle = pPkt->connectionHandle; params.secReqs.ioCaps = gapBond_IOCap; params.secReqs.oobAvailable = gapBond_OOBDataFlag; params.secReqs.maxEncKeySize = gapBond_KeySize; // TBD - Should we distribute keys if bonding is turned off??? params.secReqs.keyDist.sEncKey = (gapBond_KeyDistList | GAPBOND_KEYDIST_SENCKEY) ? TRUE : FALSE; params.secReqs.keyDist.sIdKey = (gapBond_KeyDistList | GAPBOND_KEYDIST_SIDKEY) ? TRUE : FALSE; params.secReqs.keyDist.mEncKey = (gapBond_KeyDistList | GAPBOND_KEYDIST_MENCKEY) ? TRUE : FALSE; params.secReqs.keyDist.mIdKey = (gapBond_KeyDistList | GAPBOND_KEYDIST_MIDKEY) ? TRUE : FALSE; params.secReqs.keyDist.mSign = (gapBond_KeyDistList | GAPBOND_KEYDIST_MSIGN) ? TRUE : FALSE; params.secReqs.keyDist.sSign = (gapBond_KeyDistList | GAPBOND_KEYDIST_SSIGN) ? TRUE : FALSE; // Is bond manager setup for OOB data? if ( gapBond_OOBDataFlag ) { VOID osal_memcpy( params.secReqs.oob, gapBond_OOBData, KEYLEN ); } if ( (pPkt->pairReq.authReq & SM_AUTH_STATE_BONDING) && (gapBond_Bonding) ) { params.secReqs.authReq |= SM_AUTH_STATE_BONDING; if ( pLinkItem->addrType != ADDRTYPE_PUBLIC ) { // Force a master ID key params.secReqs.keyDist.mIdKey = TRUE; } } // Is Bond Manager setup for passkey protection? if ( gapBond_MITM ) { params.secReqs.authReq |= SM_AUTH_STATE_AUTHENTICATED; } VOID GAP_Authenticate( ¶ms, &(pPkt->pairReq) ); } // Call app state callback if ( pGapBondCB && pGapBondCB->pairStateCB ) { pGapBondCB->pairStateCB( GAPBOND_PAIRING_STATE_STARTED, pPkt->hdr.status ); } } break; default: break; } }
/********************************************************************* * @fn SimpleBLEPeripheral_Init * * @brief Initialization function for the Simple BLE Peripheral App Task. * This is called during initialization and should contain * any application specific initialization (ie. hardware * initialization/setup, table initialization, power up * notificaiton ... ). * * @param task_id - the ID assigned by OSAL. This ID should be * used to send messages and set timers. * * @return none */ void SimpleBLEPeripheral_Init( uint8 task_id ) { simpleBLEPeripheral_TaskID = task_id; // Setup the GAP VOID GAP_SetParamValue( TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL ); // Setup the GAP Peripheral Role Profile { #if defined( CC2540_MINIDK ) // For the CC2540DK-MINI keyfob, device doesn't start advertising until button is pressed uint8 initial_advertising_enable = FALSE; #else // For other hardware platforms, device starts advertising upon initialization uint8 initial_advertising_enable = TRUE; #endif // 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 gapRole_AdvertOffTime = 0; uint8 enable_update_request = DEFAULT_ENABLE_UPDATE_REQUEST; uint16 desired_min_interval = DEFAULT_DESIRED_MIN_CONN_INTERVAL; uint16 desired_max_interval = DEFAULT_DESIRED_MAX_CONN_INTERVAL; uint16 desired_slave_latency = DEFAULT_DESIRED_SLAVE_LATENCY; uint16 desired_conn_timeout = DEFAULT_DESIRED_CONN_TIMEOUT; // Set the GAP Role Parameters GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &initial_advertising_enable ); GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_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 ), &enable_update_request ); GAPRole_SetParameter( GAPROLE_MIN_CONN_INTERVAL, sizeof( uint16 ), &desired_min_interval ); GAPRole_SetParameter( GAPROLE_MAX_CONN_INTERVAL, sizeof( uint16 ), &desired_max_interval ); GAPRole_SetParameter( GAPROLE_SLAVE_LATENCY, sizeof( uint16 ), &desired_slave_latency ); GAPRole_SetParameter( GAPROLE_TIMEOUT_MULTIPLIER, sizeof( uint16 ), &desired_conn_timeout ); //ÉèÖÃRSSI »ñÈ¡ËÙÂÊ uint16 rssi_rate = RSSI_RATE; GAPRole_SetParameter(GAPROLE_RSSI_READ_RATE,sizeof(uint16),&rssi_rate); } // Set the GAP Characteristics GGS_SetParameter( GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName ); // Set advertising interval { uint16 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 ); } // Setup the GAP Bond Manager { uint32 passkey = 0; // passkey "000000" uint8 pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ; uint8 mitm = TRUE; uint8 ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY; uint8 bonding = TRUE; GAPBondMgr_SetParameter( GAPBOND_DEFAULT_PASSCODE, sizeof ( uint32 ), &passkey ); GAPBondMgr_SetParameter( GAPBOND_PAIRING_MODE, sizeof ( uint8 ), &pairMode ); GAPBondMgr_SetParameter( GAPBOND_MITM_PROTECTION, sizeof ( uint8 ), &mitm ); GAPBondMgr_SetParameter( GAPBOND_IO_CAPABILITIES, sizeof ( uint8 ), &ioCap ); GAPBondMgr_SetParameter( GAPBOND_BONDING_ENABLED, sizeof ( uint8 ), &bonding ); } // Initialize GATT attributes Ìí¼ÓÁË4¸öService ·þÎñ GGS_AddService( GATT_ALL_SERVICES ); // GAP GATTServApp_AddService( GATT_ALL_SERVICES ); // GATT attributes DevInfo_AddService(); // Device Information Service SimpleProfile_AddService( GATT_ALL_SERVICES ); // Simple GATT Profile ankiÐèÒªÐ޸ĵķþÎñ #if defined FEATURE_OAD VOID OADTarget_AddService(); // OAD Profile #endif // Setup the SimpleProfile Characteristic Values { //³õʼ»¯±àÒë½øÈ¥µÄµÆ¹âÑÕÉ« uint8 charValue1[20] = {0, 1,255,100,100,255,255,255, 20,1,1,255,1,200, 20,100,100,20,100,10}; uint8 charValue2[20] = {20,1,1,20,1,1,20,1,250,20,1,250,20,1,250,20,1,250,1}; uint8 charValue3 = 3; uint8 charValue4 = 4; uint8 charValue5[SIMPLEPROFILE_CHAR5_LEN] = { 1, 2, 3, 4, 5 }; #if (defined HAL_LCD) && (HAL_LCD == TRUE) //´ÓÎļþÖжÁÈ¡ uint8 wirteTag = osal_snv_read(0x80,20,charValue1); osal_snv_read(0x95,20,charValue2); if( wirteTag == SUCCESS){ HalLcdWriteStringValue("read Ok",(uint16)wirteTag,10, HAL_LCD_LINE_6 ); }else{ HalLcdWriteStringValue("read failed",(uint16)wirteTag,10, HAL_LCD_LINE_6 ); //½øÐгõʼ»¯ wirteTag = osal_snv_write(0x80,20,charValue1); osal_snv_write(0x95,20,charValue1); if(wirteTag == SUCCESS){ HalLcdWriteStringValue( "init", (uint16)wirteTag, 10, HAL_LCD_LINE_7 ); }else{ HalLcdWriteStringValue("init failed", (uint16)wirteTag,10, HAL_LCD_LINE_7 ); } } #else if( osal_snv_read(0x80,20,charValue1) != SUCCESS){ //½øÐгõʼ»¯ //osal_snv_write(0x80,20,charValue1); //HalLcdWriteStringValue( "rece:", osal_snv_write(0x80,20,charValue1), 10, HAL_LCD_LINE_8 ); osal_snv_write(0x95,20,charValue2); } #endif // (defined HAL_LCD) && (HAL_LCD == TRUE) SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR1, 20, &charValue1 ); SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR2, 20, &charValue2 ); SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR3, sizeof ( uint8 ), &charValue3 ); //Ç°Ãæ3¾äÖ»ÊǶԶÔÏóÖµµÄÉèÖã¬Õâ¾ä´úÂë ½øÐÐÁË£¬ServiceµÄcharacteristicÉèÖã¬Process Client Characteristis Configuration Change SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR4, sizeof ( uint8 ), &charValue4 ); SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR5, SIMPLEPROFILE_CHAR5_LEN, charValue5 ); } #if defined( CC2540_MINIDK ) SK_AddService( GATT_ALL_SERVICES ); // Simple Keys Profile // Register for all key events - This app will handle all key events¡£ ×¢²á°´Å¥Ê¼þ£¬OSAL´¦Àí°´Å¥Ê¼þ RegisterForKeys( simpleBLEPeripheral_TaskID ); // makes sure LEDs are off HalLedSet( (HAL_LED_1 | HAL_LED_2), HAL_LED_MODE_OFF ); #endif // #if defined( CC2540_MINIDK ) #if (defined HAL_LCD) && (HAL_LCD == TRUE) #if defined FEATURE_OAD #if defined (HAL_IMAGE_A) HalLcdWriteStringValue( "BLE Peri-A", OAD_VER_NUM( _imgHdr.ver ), 16, HAL_LCD_LINE_1 ); #else HalLcdWriteStringValue( "BLE Peri-B", OAD_VER_NUM( _imgHdr.ver ), 16, HAL_LCD_LINE_1 ); #endif // HAL_IMAGE_A #else HalLcdWriteString( "BLE Peripheral", HAL_LCD_LINE_1 ); #endif // FEATURE_OAD #endif // (defined HAL_LCD) && (HAL_LCD == TRUE) // Register callback with SimpleGATTprofile // ¸Ã»Øµ÷±» simpleProfile_WriteAttrCB ·½·¨´¥·¢£¬simpleProfileCBs °üº¬´Ë·½·¨£¬ÔÚSimpleProfile_AddService µÄʱºò×¢²áµ½GATTÐÒéÕ»·þÎñÖÐ //Öµ¸Ä±äÖ®ºó£¬Í¨Öª PROFILES--->SimpleProfileCBs.simpleProfile_WriteAttrCB È»ºóÔÙ֪ͨAPP--->simpleBLEPeripheral_SimpleProfileCBs VOID SimpleProfile_RegisterAppCBs( &simpleBLEPeripheral_SimpleProfileCBs ); // Enable clock divide on halt // This reduces active current while radio is active and CC254x MCU // is halted //²»É¾³ý PWM²»Îȶ¨ //HCI_EXT_ClkDivOnHaltCmd( HCI_EXT_ENABLE_CLK_DIVIDE_ON_HALT ); #if defined ( DC_DC_P0_7 ) // Enable stack to toggle bypass control on TPS62730 (DC/DC converter) HCI_EXT_MapPmIoPortCmd( HCI_EXT_PM_IO_PORT_P0, HCI_EXT_PM_IO_PORT_PIN7 ); #endif // defined ( DC_DC_P0_7 ) // Setup a delayed profile startup ·¢ÆðBLEÁ¬½Ó³õʼ»¯Ïà¹Ø·þÎñ¡£ÏÂÃæ·½·¨¶Ô SBP_START_DEVICE_EVT ʼþ½øÐд¦Àí osal_set_event( simpleBLEPeripheral_TaskID, SBP_START_DEVICE_EVT ); }
/********************************************************************* * @brief Task Event Processor function. * * Internal function defined in peripheral.h. */ uint16 GAPRole_ProcessEvent( uint8 task_id, uint16 events ) { VOID task_id; // OSAL required parameter that isn't used in this function if ( events & SYS_EVENT_MSG ) { uint8 *pMsg; if ( (pMsg = osal_msg_receive( gapRole_TaskID )) != NULL ) { gapRole_ProcessOSALMsg( (osal_event_hdr_t *)pMsg ); // Release the OSAL message VOID osal_msg_deallocate( pMsg ); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } if ( events & GAP_EVENT_SIGN_COUNTER_CHANGED ) { // Sign counter changed, save it to NV VOID osal_snv_write( BLE_NVID_SIGNCOUNTER, sizeof( uint32 ), &gapRole_signCounter ); return ( events ^ GAP_EVENT_SIGN_COUNTER_CHANGED ); } if ( events & START_ADVERTISING_EVT ) { if ( gapRole_AdvEnabled ) { gapAdvertisingParams_t params; // Setup advertisement parameters if ( gapRole_state == GAPROLE_CONNECTED ) { // While in a connection, we can only advertise non-connectable undirected. params.eventType = GAP_ADTYPE_ADV_NONCONN_IND; } else { params.eventType = gapRole_AdvEventType; params.initiatorAddrType = gapRole_AdvDirectType; VOID osal_memcpy( params.initiatorAddr, gapRole_AdvDirectAddr, B_ADDR_LEN ); } params.channelMap = gapRole_AdvChanMap; params.filterPolicy = gapRole_AdvFilterPolicy; if ( GAP_MakeDiscoverable( gapRole_TaskID, ¶ms ) != SUCCESS ) { gapRole_state = GAPROLE_ERROR; if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange ) { pGapRoles_AppCGs->pfnStateChange( gapRole_state ); } } } return ( events ^ START_ADVERTISING_EVT ); } if ( events & RSSI_READ_EVT ) { // Only get RSSI when in a connection if ( (gapRole_state == GAPROLE_CONNECTED) || (gapRole_state == GAPROLE_CONNECTED_ADV) ) { // Ask for RSSI VOID HCI_ReadRssiCmd( gapRole_ConnectionHandle ); // Setup next event if ( gapRole_RSSIReadRate ) { VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate ); } } return ( events ^ RSSI_READ_EVT ); } if ( events & UPDATE_PARAMS_TIMEOUT_EVT ) { // Clear an existing timeout if ( osal_get_timeoutEx( gapRole_TaskID, UPDATE_PARAMS_TIMEOUT_EVT ) ) { VOID osal_stop_timerEx( gapRole_TaskID, UPDATE_PARAMS_TIMEOUT_EVT ); } // The Update Parameters Timeout occurred - Terminate connection VOID GAP_TerminateLinkReq( gapRole_TaskID, gapRole_ConnectionHandle, HCI_DISCONNECT_REMOTE_USER_TERM ); return ( events ^ UPDATE_PARAMS_TIMEOUT_EVT ); } // Discard unknown events return 0; }
/********************************************************************* * @fn gapRole_ProcessGAPMsg * * @brief Process an incoming task message. * * @param pMsg - message to process * * @return none */ static void gapRole_ProcessGAPMsg( gapEventHdr_t *pMsg ) { uint8 notify = FALSE; // State changed notify the app? (default no) switch ( pMsg->opcode ) { case GAP_DEVICE_INIT_DONE_EVENT: { gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *)pMsg; bStatus_t stat = pPkt->hdr.status; if ( stat == SUCCESS ) { // Save off the generated keys VOID osal_snv_write( BLE_NVID_IRK, KEYLEN, gapRole_IRK ); VOID osal_snv_write( BLE_NVID_CSRK, KEYLEN, gapRole_SRK ); // Save off the information VOID osal_memcpy( gapRole_bdAddr, pPkt->devAddr, B_ADDR_LEN ); gapRole_state = GAPROLE_STARTED; // Update the advertising data stat = GAP_UpdateAdvertisingData( gapRole_TaskID, TRUE, gapRole_AdvertDataLen, gapRole_AdvertData ); } if ( stat != SUCCESS ) { gapRole_state = GAPROLE_ERROR; } notify = TRUE; } break; case GAP_ADV_DATA_UPDATE_DONE_EVENT: { gapAdvDataUpdateEvent_t *pPkt = (gapAdvDataUpdateEvent_t *)pMsg; if ( pPkt->hdr.status == SUCCESS ) { if ( pPkt->adType ) { // Setup the Response Data pPkt->hdr.status = GAP_UpdateAdvertisingData( gapRole_TaskID, FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData ); } else { // Start advertising VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT ); } } if ( pPkt->hdr.status != SUCCESS ) { // Set into Error state gapRole_state = GAPROLE_ERROR; notify = TRUE; } } break; case GAP_MAKE_DISCOVERABLE_DONE_EVENT: case GAP_END_DISCOVERABLE_DONE_EVENT: { gapMakeDiscoverableRspEvent_t *pPkt = (gapMakeDiscoverableRspEvent_t *)pMsg; if ( pPkt->hdr.status == SUCCESS ) { if ( pMsg->opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT ) { if ( gapRole_state == GAPROLE_CONNECTED ) { gapRole_state = GAPROLE_CONNECTED_ADV; } else { gapRole_state = GAPROLE_ADVERTISING; } } else // GAP_END_DISCOVERABLE_DONE_EVENT { if ( gapRole_AdvertOffTime != 0 ) { if ( ( gapRole_AdvEnabled ) ) { VOID osal_start_timerEx( gapRole_TaskID, START_ADVERTISING_EVT, gapRole_AdvertOffTime ); } } else { // Since gapRole_AdvertOffTime is set to 0, the device should not // automatically become discoverable again after a period of time. // Set enabler to FALSE; device will become discoverable again when // this value gets set to TRUE gapRole_AdvEnabled = FALSE; } // In the Advertising Off period gapRole_state = GAPROLE_WAITING; } } else { gapRole_state = GAPROLE_ERROR; } notify = TRUE; } break; case GAP_LINK_ESTABLISHED_EVENT: { gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *)pMsg; if ( pPkt->hdr.status == SUCCESS ) { VOID osal_memcpy( gapRole_ConnectedDevAddr, pPkt->devAddr, B_ADDR_LEN ); gapRole_ConnectionHandle = pPkt->connectionHandle; gapRole_state = GAPROLE_CONNECTED; if ( gapRole_RSSIReadRate ) { // Start the RSSI Reads VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate ); } // Check whether update parameter request is enabled, and check the connection parameters if ( ( gapRole_ParamUpdateEnable == TRUE ) && ( (pPkt->connInterval < gapRole_MinConnInterval) || (pPkt->connInterval > gapRole_MaxConnInterval) || (pPkt->connLatency != gapRole_SlaveLatency) || (pPkt->connTimeout != gapRole_TimeoutMultiplier) )) { gapRole_SendUpdateParam( pPkt->connInterval, pPkt->connLatency ); } // Notify the Bond Manager to the connection VOID GAPBondMgr_LinkEst( pPkt->devAddrType, pPkt->devAddr, pPkt->connectionHandle, GAP_PROFILE_PERIPHERAL ); } else { gapRole_state = GAPROLE_ERROR; } notify = TRUE; } break; case GAP_LINK_TERMINATED_EVENT: { VOID GAPBondMgr_ProcessGAPMsg( (gapEventHdr_t *)pMsg ); osal_memset( gapRole_ConnectedDevAddr, 0, B_ADDR_LEN ); if ( gapRole_state == GAPROLE_CONNECTED_ADV ) { // End the non-connectable advertising GAP_EndDiscoverable( gapRole_TaskID ); gapRole_state = GAPROLE_CONNECTED; } else { gapTerminateLinkEvent_t *pPkt = (gapTerminateLinkEvent_t *)pMsg; if( pPkt->reason == LL_SUPERVISION_TIMEOUT_TERM ) { gapRole_state = GAPROLE_WAITING_AFTER_TIMEOUT; } else { gapRole_state = GAPROLE_WAITING; } notify = TRUE; VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT ); } gapRole_ConnectionHandle = INVALID_CONNHANDLE; } break; case GAP_LINK_PARAM_UPDATE_EVENT: { gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsg; if ( (pPkt->hdr.status != SUCCESS) || (pPkt->connInterval < gapRole_MinConnInterval) || (pPkt->connInterval > gapRole_MaxConnInterval) ) { // Ask to change the interval gapRole_SendUpdateParam( pPkt->connInterval, pPkt->connLatency ); } else { // All is good stop Update Parameters timeout VOID osal_stop_timerEx( gapRole_TaskID, UPDATE_PARAMS_TIMEOUT_EVT ); } } break; default: break; } if ( notify == TRUE ) { // Notify the application if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange ) { pGapRoles_AppCGs->pfnStateChange( gapRole_state ); } } }
/********************************************************************* * @fn gapRole_processGAPMsg * * @brief Process an incoming task message. * * @param pMsg - message to process * * @return none */ static uint8_t gapRole_processGAPMsg(gapEventHdr_t *pMsg) { uint8_t notify = FALSE; // State changed notify the app? (default no) switch (pMsg->opcode) { case GAP_DEVICE_INIT_DONE_EVENT: { gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *) pMsg; bStatus_t stat = pPkt->hdr.status; if (stat == SUCCESS) { // Save off the generated keys VOID osal_snv_write(BLE_NVID_IRK, KEYLEN, gapRole_IRK); VOID osal_snv_write(BLE_NVID_CSRK, KEYLEN, gapRole_SRK); // Save off the information VOID memcpy(gapRole_bdAddr, pPkt->devAddr, B_ADDR_LEN); gapRole_peripheralState = GAPROLE_STARTED; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); // Update the advertising data stat = GAP_UpdateAdvertisingData(selfEntity, TRUE, gapRole_AdvertDataLen, gapRole_AdvertData); } if (stat != SUCCESS) { gapRole_peripheralState = GAPROLE_ERROR; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); //gapRole_abort(); } notify = TRUE; } break; case GAP_ADV_DATA_UPDATE_DONE_EVENT: { gapAdvDataUpdateEvent_t *pPkt = (gapAdvDataUpdateEvent_t *) pMsg; if (pPkt->hdr.status == SUCCESS) { if (pPkt->adType) { // Setup the Response Data pPkt->hdr.status = GAP_UpdateAdvertisingData(selfEntity, FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData); } else if ((gapRole_peripheralState != GAPROLE_ADVERTISING) && (gapRole_peripheralState != GAPROLE_CONNECTED_ADV) && (gapRole_peripheralState != GAPROLE_CONNECTED || gapRole_AdvNonConnEnabled == TRUE) && (Util_isActive(&startAdvClock) == FALSE)) { // Start advertising gapRole_setEvent(START_ADVERTISING_EVT); } notify = FALSE; }else { // Set into Error state gapRole_peripheralState = GAPROLE_ERROR; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); //gapRole_abort(); notify = TRUE; } } break; case GAP_MAKE_DISCOVERABLE_DONE_EVENT: case GAP_END_DISCOVERABLE_DONE_EVENT: { gapMakeDiscoverableRspEvent_t *pPkt = (gapMakeDiscoverableRspEvent_t *) pMsg; if (pPkt->hdr.status == SUCCESS) { if (pMsg->opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT) { if (gapRole_peripheralState == GAPROLE_CONNECTED) { gapRole_peripheralState = GAPROLE_CONNECTED_ADV; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } else if (gapRole_AdvEnabled) { gapRole_peripheralState = GAPROLE_ADVERTISING; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } else { gapRole_peripheralState = GAPROLE_ADVERTISING_NONCONN; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } } else // GAP_END_DISCOVERABLE_DONE_EVENT { if (gapRole_AdvertOffTime != 0) //restart advertising if param is set { if ((gapRole_AdvEnabled) || (gapRole_AdvNonConnEnabled)) { Util_restartClock(&startAdvClock, gapRole_AdvertOffTime); } } else { // Since gapRole_AdvertOffTime is set to 0, the device should not // automatically become discoverable again after a period of time. // Set enabler to FALSE; device will become discoverable again when // this value gets set to TRUE if (gapRole_AdvEnabled == TRUE) { gapRole_AdvEnabled = FALSE; } else { gapRole_AdvNonConnEnabled = FALSE; } } // Update state. if (gapRole_peripheralState == GAPROLE_CONNECTED_ADV) { // In the Advertising Off period gapRole_peripheralState = GAPROLE_CONNECTED; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } else { // In the Advertising Off period gapRole_peripheralState = GAPROLE_WAITING; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } } notify = TRUE; } else if (pPkt->hdr.status == LL_STATUS_ERROR_COMMAND_DISALLOWED) //we're already advertising { notify = FALSE; } else { gapRole_peripheralState = GAPROLE_ERROR; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); //gapRole_abort(); } } break; case GAP_LINK_ESTABLISHED_EVENT: { gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *) pMsg; if (pPkt->hdr.status == SUCCESS) { //add to database gapRoleInfo_Add(pPkt); // advertising will stop when a connection forms in the peripheral role if (pPkt->connRole == GAP_PROFILE_PERIPHERAL) { gapRole_peripheralState = GAPROLE_CONNECTED; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); // Check whether update parameter request is enabled if (gapRole_ParamUpdateEnable == TRUE) { // Get the minimum time upon connection establishment before the // peripheral can start a connection update procedure. uint16_t timeout = GAP_GetParamValue( TGAP_CONN_PAUSE_PERIPHERAL); Util_restartClock(&startUpdateClock, timeout * 1000); } } // Notify the Bond Manager to the connection VOID GAPBondMgr_LinkEst(pPkt->devAddrType, pPkt->devAddr, pPkt->connectionHandle, pPkt->connRole); } else if (pPkt->hdr.status == bleGAPConnNotAcceptable) { // Set enabler to FALSE; device will become discoverable again when // this value gets set to TRUE gapRole_AdvEnabled = FALSE; // Go to WAITING state, and then start advertising if (pPkt->connRole == GAP_PROFILE_PERIPHERAL) { gapRole_peripheralState = GAPROLE_WAITING; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } } else { if (pPkt->connRole == GAP_PROFILE_PERIPHERAL) { gapRole_peripheralState = GAPROLE_ERROR; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } else { gapRole_abort(); } } notify = TRUE; } break; case GAP_LINK_TERMINATED_EVENT: { gapTerminateLinkEvent_t *pPkt = (gapTerminateLinkEvent_t *) pMsg; // notify bond manager GAPBondMgr_LinkTerm(pPkt->connectionHandle); // Erase connection information (maybe make this a function) uint8 connHandleIndex = gapRoleInfo_Find(pPkt->connectionHandle); multiConnInfo[connHandleIndex].gapRole_ConnectionHandle = INVALID_CONNHANDLE; multiConnInfo[connHandleIndex].gapRole_ConnInterval = 0; multiConnInfo[connHandleIndex].gapRole_ConnSlaveLatency = 0; multiConnInfo[connHandleIndex].gapRole_ConnTimeout = 0; // Cancel all connection parameter update timers (if any active) Util_stopClock(&startUpdateClock); Util_stopClock(&updateTimeoutClock); notify = TRUE; if (multiConnInfo[connHandleIndex].gapRole_ConnRole == GAP_PROFILE_PERIPHERAL) { // If device was advertising when connection dropped if (gapRole_AdvNonConnEnabled) { // Continue advertising. gapRole_peripheralState = GAPROLE_ADVERTISING_NONCONN; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } // Else go to WAITING state. else { if (pPkt->reason == LL_SUPERVISION_TIMEOUT_TERM) { gapRole_peripheralState = GAPROLE_WAITING_AFTER_TIMEOUT; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } else { gapRole_peripheralState = GAPROLE_WAITING; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } // Start advertising, if enabled. gapRole_setEvent(START_ADVERTISING_EVT); } } } break; case GAP_LINK_PARAM_UPDATE_EVENT: { gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *) pMsg; // Cancel connection param update timeout timer (if active) Util_stopClock(&updateTimeoutClock); if (pPkt->hdr.status == SUCCESS) { // Store new connection parameters // gapRole_ConnInterval = pPkt->connInterval; // gapRole_ConnSlaveLatency = pPkt->connLatency; // gapRole_ConnTimeout = pPkt->connTimeout; // Make sure there's no pending connection update procedure if (Util_isActive(&startUpdateClock) == FALSE) { // // Notify the application with the new connection parameters // if (pGapRoles_ParamUpdateCB != NULL) // { // (*pGapRoles_ParamUpdateCB)(gapRole_ConnInterval, // gapRole_ConnSlaveLatency, // gapRole_ConnTimeout); // } } } notify = TRUE; } break; case GAP_PAIRING_REQ_EVENT: { gapPairingReqEvent_t *pPkt = (gapPairingReqEvent_t *) pMsg; // Send Pairing Failed Response VOID GAP_TerminateAuth(pPkt->connectionHandle, SMP_PAIRING_FAILED_NOT_SUPPORTED); } break; case GAP_SLAVE_REQUESTED_SECURITY_EVENT: { uint16_t connHandle = ((gapSlaveSecurityReqEvent_t *)pMsg)->connectionHandle; uint8_t authReq = ((gapSlaveSecurityReqEvent_t *)pMsg)->authReq; GAPBondMgr_SlaveReqSecurity(connHandle, authReq); } break; case GAP_DEVICE_INFO_EVENT: case GAP_DEVICE_DISCOVERY_EVENT: notify = TRUE; break; default: notify = FALSE; break; } if (notify == TRUE) //app needs to take further action { if (pGapRoles_AppCGs && pGapRoles_AppCGs->pfnPassThrough) { return (pGapRoles_AppCGs->pfnPassThrough((gapMultiRoleEvent_t *) pMsg)); } } return TRUE; }
/********************************************************************* * @fn simpleProfileChangeCB * * @brief Callback from SimpleBLEProfile indicating a value change * * @param paramID - parameter ID of the value that was changed. * * @return none */ static void simpleProfileChangeCB( uint8 paramID ) { uint8 newValue[20]; uint8 returnBytes; switch( paramID ) { case SIMPLEPROFILE_CHAR1: // 收到 CHAR1 的数据 SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR1, &newValue, &returnBytes); #if (defined HAL_LCD) && (HAL_LCD == TRUE) HalLcdWriteStringValue( "Char 1:", (uint16)(newValue[0]), 10, HAL_LCD_LINE_5 ); #endif // (defined HAL_LCD) && (HAL_LCD == TRUE) HalLedBlink (HAL_LED_1, 1, 50, 100);//这个的意思是, 100ms内,以50%的占空比闪烁1次, 实际就是点亮50ms break; case SIMPLEPROFILE_CHAR5: // 收到 CHAR5 的数据 SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR5, &newValue, &returnBytes); #if (defined HAL_LCD) && (HAL_LCD == TRUE) HalLcdWriteStringValue( "Char 5[0]:", (uint16)(newValue[0]), 16, HAL_LCD_LINE_5 ); HalLcdWriteStringValue( "Char 5[1]:", (uint16)(newValue[1]), 16, HAL_LCD_LINE_6 ); HalLcdWriteStringValue( "Char 5[2]:", (uint16)(newValue[2]), 16, HAL_LCD_LINE_7 ); HalLcdWriteStringValue( "Char 5[3]:", (uint16)(newValue[3]), 16, HAL_LCD_LINE_8 ); #endif // (defined HAL_LCD) && (HAL_LCD == TRUE) // 设定温度更新时间, 注意高位在前 if(returnBytes == 4) { sys_config.update_time_ms = (uint32)newValue[0]<<24 | (uint32)newValue[1]<<16| (uint32)newValue[2]<<8| (uint32)newValue[3]; osal_snv_write(0x80, sizeof(SYS_CONFIG), &sys_config); // 写所有参数 if(sys_config.update_time_ms > 0) { osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_READ_SENSOR_EVT, sys_config.update_time_ms); } else { osal_stop_timerEx( simpleBLEPeripheral_TaskID, SBP_READ_SENSOR_EVT); } } HalLedBlink (HAL_LED_2, 1, 50, 100);//这个的意思是, 100ms内,以50%的占空比闪烁1次, 实际就是点亮50ms break; case SIMPLEPROFILE_CHAR6: // 这个是我们添加char6, 用于做串口透传 与从机 notify 数据到主机 很合适 SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR6, &newValue, &returnBytes); { char str[21]={0}; char str2[32]={0}; osal_memcpy(str, newValue, returnBytes); sprintf(str2,"Char 6: %s", str); #if (defined HAL_LCD) && (HAL_LCD == TRUE) HalLcdWriteString(str2, HAL_LCD_LINE_6 ); #endif // (defined HAL_LCD) && (HAL_LCD == TRUE) // 通过串口透传出去,达到透传目的,amo家的透传就是使用 CHAR6 NPI_WriteTransport(newValue, returnBytes); HalLedBlink (HAL_LED_3, 1, 50, 100);//这个的意思是, 100ms内,以50%的占空比闪烁1次, 实际就是点亮50ms } break; case SIMPLEPROFILE_CHAR7: // 收到 CHAR7 的数据 SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR7, &newValue, &returnBytes); osal_memset(sys_config.name, 0, sizeof(sys_config.name)); osal_memcpy(sys_config.name, newValue, returnBytes); osal_snv_write(0x80, sizeof(SYS_CONFIG), &sys_config); // 写所有参数 HalLcdWriteString( "Char 7 Set", HAL_LCD_LINE_4 ); HalLcdWriteString( (char*)sys_config.name, HAL_LCD_LINE_5 ); // 需要重启后设备名生效 break; case SIMPLEPROFILE_CHAR8: // 收到 CHAR8 的数据 SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR8, &newValue, &returnBytes); // 最高温度报警 sys_config.tempeature_hight = newValue[0]<<8; sys_config.tempeature_hight |= newValue[1]; // 最低温度报警 sys_config.tempeature_low = newValue[2]<<8; sys_config.tempeature_low |= newValue[3]; break; case SIMPLEPROFILE_CHAR9: // adc 只读 break; case SIMPLEPROFILE_CHARA: // // pwm SimpleProfile_GetParameter( SIMPLEPROFILE_CHARA, &newValue, &returnBytes); #if (defined HAL_LCD) && (HAL_LCD == TRUE) HalLcdWriteStringValue( "Char A[0]:", (uint16)(newValue[0]), 16, HAL_LCD_LINE_5 ); HalLcdWriteStringValue( "Char A[1]:", (uint16)(newValue[1]), 16, HAL_LCD_LINE_6 ); HalLcdWriteStringValue( "Char A[2]:", (uint16)(newValue[2]), 16, HAL_LCD_LINE_7 ); HalLcdWriteStringValue( "Char A[3]:", (uint16)(newValue[3]), 16, HAL_LCD_LINE_8 ); #endif // (defined HAL_LCD) && (HAL_LCD == TRUE) // 设定pwm if(returnBytes == 4) { sys_config.pwm[3] = newValue[0]; // 白色 sys_config.pwm[2] = newValue[1]; // 红色 sys_config.pwm[1] = newValue[2]; // 绿色 sys_config.pwm[0] = newValue[3]; // 蓝色 osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_SET_PWM_EVT, 50); } break; default: // should not reach here! break; } }
/* Command sets, chosen options need to be stored in non-volatile memory - SC,<value> + set connection mode of device + <value> is a single digit number + 1 Do not auto-connect to last paired, 2 auto-connect to last paired - SN,<value> + set device name + <value> device's new name - S,R Reset the device - S,D Set device to be discoverable - S,DC Disconnect device from host */ static void processCommands(void) { //buf: Testing variables uint8 *buf = rxBuffer; buf[rxBufferIndex] = 0; if(rxBuffer[0] == 'K') { //keyboard commands if(rxBufferIndex == 3) { //printf("Keyboard key press and release\r\n"); if(rxBuffer[1] == 'U') { //Key released KBD_Report_RemoveKey(rxBuffer[2]); } else if(rxBuffer[1] == 'D') { //Key pressed KBD_Report_AddKey(rxBuffer[2]); } } else { //command as KS maybe, for Keyboard-report Send //printf("Sending report...\r\n"); KBD_Report_Update(); } } else if(rxBuffer[0] == 'M') { //mouse commands //printf("Mouse commands\r\n"); hidKbdMouseSendMouseReport(rxBuffer[1], rxBuffer[2], rxBuffer[3], rxBuffer[4]); } else if(rxBuffer[0] == 'S') { //setting commands //printf("Setting commands\r\n"); if((rxBuffer[1] == 'C') && (rxBuffer[2] == ',')) { //TO-DO: SET CONNECTION MODE //printf("Connection modes\r\n"); } else if((rxBuffer[1] == 'N') && (rxBuffer[2] == ',')) { uint8 i; uint8 deviceNewName[20]; uint8 deviceNewNameLength; uint8 deviceNewNameCRC; deviceNewNameLength = rxBufferIndex-3; if(deviceNewNameLength > 20) { printf("Name exceeds permitted length\r\n"); } else { for(i = 3; i < rxBufferIndex; i++) { deviceNewName[i-3] = rxBuffer[i]; } deviceNewName[deviceNewNameLength] = '\0'; deviceNewNameCRC = getCRC(deviceNewName, deviceNewNameLength); osal_snv_write(SNV_ID_DEVICE_NAME, 20, deviceNewName); osal_snv_write(SNV_ID_DEVICE_NAME_LENGTH, 1, &deviceNewNameLength); osal_snv_write(SNV_ID_DEVICE_NAME_CRC, 1, &deviceNewNameCRC); // printf("Name is being set, reset to set new name\r\n"); } } else if((rxBuffer[1] == ',') && (rxBuffer[2] == 'R')) { //reset the device HAL_SYSTEM_RESET(); } else if((rxBuffer[1] == ',') && (rxBuffer[2] == 'D')) { if(rxBuffer[3] == 'C') { //disconnect the device from host //printf("Disconnecting from host...\r\n"); GAPRole_TerminateConnection(); } else { //set device to be discoverable //printf("Set deveice to be discoverable\r\n"); } } else if((rxBuffer[1] == ',') && (rxBuffer[2] == 'S')) { //enable sleep mode printf("SLEEP\r\n"); sleepModeEnabled = 1; sleepMode(); } else if((rxBuffer[1] == ',') && (rxBuffer[2] == 'A')) { //disable sleep mode printf("ACTIVE\r\n"); sleepModeEnabled = 0; activeMode(); } } //after processing, reset rxBuffer and its index memset(rxBuffer, 0, 8); rxBufferIndex = 0; }
/*************************************************************************************************** * @fn Uart_Msg_Save_QST_NUM * * @brief Uart_Msg_Save_QST_NUM * * @param None * * @return None ***************************************************************************************************/ bool Uart_Msg_Save_QST_NUM( void ) { osal_snv_write(BLE_NVID_DEV_B, sizeof(SERIAL_NUM), gSerial_Num+DEV_B); have_save_qst_imei = true; return true; }
/********************************************************************* * @brief Task Event Processor function. * * Internal function defined in peripheral.h. */ uint16 GAPRole_ProcessEvent( uint8 task_id, uint16 events ) { VOID task_id; // OSAL required parameter that isn't used in this function if ( events & SYS_EVENT_MSG ) { uint8 *pMsg; if ( (pMsg = osal_msg_receive( gapRole_TaskID )) != NULL ) { gapRole_ProcessOSALMsg( (osal_event_hdr_t *)pMsg ); // Release the OSAL message VOID osal_msg_deallocate( pMsg ); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } if ( events & GAP_EVENT_SIGN_COUNTER_CHANGED ) { // Sign counter changed, save it to NV VOID osal_snv_write( BLE_NVID_SIGNCOUNTER, sizeof( uint32 ), &gapRole_signCounter ); return ( events ^ GAP_EVENT_SIGN_COUNTER_CHANGED ); } if ( events & START_ADVERTISING_EVT ) { if ( gapRole_AdvEnabled ) { gapAdvertisingParams_t params; // Setup advertisement parameters params.eventType = gapRole_AdvEventType; params.initiatorAddrType = gapRole_AdvDirectType; VOID osal_memcpy( params.initiatorAddr, gapRole_AdvDirectAddr, B_ADDR_LEN ); params.channelMap = gapRole_AdvChanMap; params.filterPolicy = gapRole_AdvFilterPolicy; if ( GAP_MakeDiscoverable( gapRole_TaskID, ¶ms ) != SUCCESS ) { gapRole_state = GAPROLE_ERROR; // Notify the application with the new state change if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange ) { pGapRoles_AppCGs->pfnStateChange( gapRole_state ); } } } return ( events ^ START_ADVERTISING_EVT ); } if ( events & RSSI_READ_EVT ) { // Only get RSSI when in a connection if ( gapRole_state == GAPROLE_CONNECTED ) { // Ask for RSSI VOID HCI_ReadRssiCmd( gapRole_ConnectionHandle ); // Setup next event if ( gapRole_RSSIReadRate ) { VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate ); } } return ( events ^ RSSI_READ_EVT ); } if ( events & START_CONN_UPDATE_EVT ) { // Start connection update procedure gapRole_startConnUpdate( GAPROLE_NO_ACTION ); return ( events ^ START_CONN_UPDATE_EVT ); } if ( events & CONN_PARAM_TIMEOUT_EVT ) { // Unsuccessful in updating connection parameters gapRole_HandleParamUpdateNoSuccess(); return ( events ^ CONN_PARAM_TIMEOUT_EVT ); } // Discard unknown events return 0; }
/********************************************************************* * @fn gapRole_ProcessGAPMsg * * @brief Process an incoming task message. * * @param pMsg - message to process * * @return none */ static void gapRole_ProcessGAPMsg( gapEventHdr_t *pMsg ) { uint8 notify = FALSE; // State changed notify the app? (default no) switch ( pMsg->opcode ) { case GAP_DEVICE_INIT_DONE_EVENT: { gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *)pMsg; bStatus_t stat = pPkt->hdr.status; if ( stat == SUCCESS ) { // Save off the generated keys VOID osal_snv_write( BLE_NVID_IRK, KEYLEN, gapRole_IRK ); VOID osal_snv_write( BLE_NVID_CSRK, KEYLEN, gapRole_SRK ); // Save off the information VOID osal_memcpy( gapRole_bdAddr, pPkt->devAddr, B_ADDR_LEN ); gapRole_state = GAPROLE_STARTED; // Update the advertising data stat = GAP_UpdateAdvertisingData( gapRole_TaskID, TRUE, gapRole_AdvertDataLen, gapRole_AdvertData ); } if ( stat != SUCCESS ) { gapRole_state = GAPROLE_ERROR; } notify = TRUE; } break; case GAP_ADV_DATA_UPDATE_DONE_EVENT: { gapAdvDataUpdateEvent_t *pPkt = (gapAdvDataUpdateEvent_t *)pMsg; if ( pPkt->hdr.status == SUCCESS ) { if ( pPkt->adType ) { // Setup the Response Data pPkt->hdr.status = GAP_UpdateAdvertisingData( gapRole_TaskID, FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData ); } else { // Start advertising VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT ); } } if ( pPkt->hdr.status != SUCCESS ) { // Set into Error state gapRole_state = GAPROLE_ERROR; notify = TRUE; } } break; case GAP_MAKE_DISCOVERABLE_DONE_EVENT: case GAP_END_DISCOVERABLE_DONE_EVENT: { gapMakeDiscoverableRspEvent_t *pPkt = (gapMakeDiscoverableRspEvent_t *)pMsg; if ( pPkt->hdr.status == SUCCESS ) { if ( pMsg->opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT ) { gapRole_state = GAPROLE_ADVERTISING; } else // GAP_END_DISCOVERABLE_DONE_EVENT { if ( gapRole_AdvertOffTime != 0 ) { if ( ( gapRole_AdvEnabled ) ) { VOID osal_start_timerEx( gapRole_TaskID, START_ADVERTISING_EVT, gapRole_AdvertOffTime ); } } else { // Since gapRole_AdvertOffTime is set to 0, the device should not // automatically become discoverable again after a period of time. // Set enabler to FALSE; device will become discoverable again when // this value gets set to TRUE gapRole_AdvEnabled = FALSE; } // In the Advertising Off period gapRole_state = GAPROLE_WAITING; } } else { gapRole_state = GAPROLE_ERROR; } notify = TRUE; } break; case GAP_LINK_ESTABLISHED_EVENT: { gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *)pMsg; if ( pPkt->hdr.status == SUCCESS ) { VOID osal_memcpy( gapRole_ConnectedDevAddr, pPkt->devAddr, B_ADDR_LEN ); gapRole_ConnectionHandle = pPkt->connectionHandle; gapRole_state = GAPROLE_CONNECTED; if ( gapRole_RSSIReadRate ) { // Start the RSSI Reads VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate ); } // Store connection information gapRole_ConnInterval = pPkt->connInterval; gapRole_ConnSlaveLatency = pPkt->connLatency; gapRole_ConnTimeout = pPkt->connTimeout; // Check whether update parameter request is enabled if ( gapRole_ParamUpdateEnable == TRUE ) { // Get the minimum time upon connection establishment before the // peripheral can start a connection update procedure. uint16 timeout = GAP_GetParamValue( TGAP_CONN_PAUSE_PERIPHERAL ); osal_start_timerEx( gapRole_TaskID, START_CONN_UPDATE_EVT, timeout*1000 ); } // Notify the Bond Manager to the connection VOID GAPBondMgr_LinkEst( pPkt->devAddrType, pPkt->devAddr, pPkt->connectionHandle, GAP_PROFILE_PERIPHERAL ); } else if ( pPkt->hdr.status == bleGAPConnNotAcceptable ) { // Set enabler to FALSE; device will become discoverable again when // this value gets set to TRUE gapRole_AdvEnabled = FALSE; // Go to WAITING state, and then start advertising gapRole_state = GAPROLE_WAITING; } else { gapRole_state = GAPROLE_ERROR; } notify = TRUE; } break; case GAP_LINK_TERMINATED_EVENT: { gapTerminateLinkEvent_t *pPkt = (gapTerminateLinkEvent_t *)pMsg; GAPBondMgr_ProcessGAPMsg( (gapEventHdr_t *)pMsg ); osal_memset( gapRole_ConnectedDevAddr, 0, B_ADDR_LEN ); // Erase connection information gapRole_ConnInterval = 0; gapRole_ConnSlaveLatency = 0; gapRole_ConnTimeout = 0; // Cancel all connection parameter update timers (if any active) VOID osal_stop_timerEx( gapRole_TaskID, START_CONN_UPDATE_EVT ); VOID osal_stop_timerEx( gapRole_TaskID, CONN_PARAM_TIMEOUT_EVT ); // Go to WAITING state, and then start advertising if( pPkt->reason == LL_SUPERVISION_TIMEOUT_TERM ) { gapRole_state = GAPROLE_WAITING_AFTER_TIMEOUT; } else { gapRole_state = GAPROLE_WAITING; } notify = TRUE; VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT ); gapRole_ConnectionHandle = INVALID_CONNHANDLE; } break; case GAP_LINK_PARAM_UPDATE_EVENT: { gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsg; // Cancel connection param update timeout timer (if active) VOID osal_stop_timerEx( gapRole_TaskID, CONN_PARAM_TIMEOUT_EVT ); if ( pPkt->hdr.status == SUCCESS ) { // Store new connection parameters gapRole_ConnInterval = pPkt->connInterval; gapRole_ConnSlaveLatency = pPkt->connLatency; gapRole_ConnTimeout = pPkt->connTimeout; // Make sure there's no pending connection update procedure if ( osal_get_timeoutEx( gapRole_TaskID, START_CONN_UPDATE_EVT ) == 0 ) { // Notify the application with the new connection parameters if ( pGapRoles_ParamUpdateCB != NULL ) { (*pGapRoles_ParamUpdateCB)( gapRole_ConnInterval, gapRole_ConnSlaveLatency, gapRole_ConnTimeout ); } } } } break; default: break; } if ( notify == TRUE ) { // Notify the application with the new state change if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange ) { pGapRoles_AppCGs->pfnStateChange( gapRole_state ); } } }
/************************************************************************************************** * @fn HalMotionHandleMeasurementStartEvent * * @brief Handles event indicating a new 10 msec measurement cycle has begun, * so we should start taking samples. * * @param None * * @return None **************************************************************************************************/ static void HalMotionHandleMeasurementStartEvent( void ) { if (HalMotionState == HAL_MOTION_STATE_WAITING_FOR_NEXT_MEASUREMENT) { int16 x, y, z; #if (HAL_MOTION_ENABLE_ROLL_COMPENSATION == TRUE) int8 ax, ay, az; #endif /* Update state */ HalMotionState = HAL_MOTION_STATE_MEASURING; HalGyroRead(&x, &y, &z ); samples.GyroSamples.X = x; samples.GyroSamples.Y = -y; samples.GyroSamples.Z = z; /* Done with Gyro samples, now get Accelerometer samples */ #if (HAL_MOTION_ENABLE_ROLL_COMPENSATION == TRUE) HalGyroReadAccelData( &ax, &ay, &az ); samples.AccSamples.X = ax; samples.AccSamples.Y = ay; samples.AccSamples.Z = -az; #endif /* Done with samples, so call Movea library routine to process them */ motion_status = AIR_MOTION_ProcessDelta(samples); /* Update state */ HalMotionState = HAL_MOTION_STATE_WAITING_FOR_NEXT_MEASUREMENT; if (motion_status.Status.IsDeltaComputed) { /* Avalid delta was computed */ /* Inform application that results are ready */ if (pHalMotionProcessFunction != NULL) { pHalMotionProcessFunction( motion_status.Delta.X, motion_status.Delta.Y ); } } } else if (HalMotionCalibrateGyro == TRUE && HalMotionState == HAL_MOTION_STATE_POWERING_ON) { // Currently calibrating int16 x, y, z; #if (HAL_MOTION_ENABLE_ROLL_COMPENSATION == TRUE) int8 ax, ay, az; #endif HalMotionState = HAL_MOTION_STATE_MEASURING; HalGyroRead( &x, &y, &z ); samples.GyroSamples.X = x; samples.GyroSamples.Y = -y; samples.GyroSamples.Z = z; /* Done with Gyro samples, now get Accelerometer samples */ #if (HAL_MOTION_ENABLE_ROLL_COMPENSATION == TRUE) HalGyroReadAccelData( &ax, &ay, &az ); samples.AccSamples.X = ax; samples.AccSamples.Y = ay; samples.AccSamples.Z = -az; #endif /* Done with samples, so call Movea library routine to process them */ motion_status = AIR_MOTION_ProcessDelta(samples); if (motion_status.Status.NewGyroOffset == true) { // Found a new valid gyro offset HalMotionGyroOffsets.x = motion_status.GyroOffsets.X; HalMotionGyroOffsets.y = motion_status.GyroOffsets.Y; HalMotionGyroOffsets.z = motion_status.GyroOffsets.Z; /* Store gyro offsets in NVM */ (void) osal_snv_write( HAL_MOTION_NV_ITEM_GYRO_OFFSETS_ID, sizeof( HalMotionGyroOffsets ), (uint8 *)&HalMotionGyroOffsets ); /* Power down motion hardware and go back to initial state */ HalMotionDisable(); /* Inform application that calibration is done */ if (pHalMotionCalCompleteNotificationFunction != NULL) { pHalMotionCalCompleteNotificationFunction(); } } else if (HalNbSamplesCalCnt == 0) { // Too many attempts ==> Reset the cal process: if (pHalMotionCalCompleteNotificationFunction != NULL) { /* Inform application that the current calibration is still valid */ pHalMotionCalCompleteNotificationFunction(); } HalMotionDisable(); } else { HalNbSamplesCalCnt--; /* Update state */ HalMotionState = HAL_MOTION_STATE_POWERING_ON; } } }
/********************************************************************* * @fn simpleProfile_WriteAttrCB * * @brief Validate attribute data prior to a write operation * * @param connHandle - connection message was received on * @param pAttr - pointer to attribute * @param pValue - pointer to data to be written * @param len - length of data * @param offset - offset of the first octet to be written * @param complete - whether this is the last packet * @param oper - whether to validate and/or write attribute value * * @return Success or Failure */ static bStatus_t simpleProfile_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset ) { bStatus_t status = SUCCESS; uint8 notifyApp = 0xFF; // If attribute permissions require authorization to write, return error if ( gattPermitAuthorWrite( pAttr->permissions ) ) { // Insufficient authorization return ( ATT_ERR_INSUFFICIENT_AUTHOR ); } if ( pAttr->type.len == ATT_BT_UUID_SIZE ) { // 16-bit UUID uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]); switch ( uuid ) { case SIMPLEPROFILE_CHAR1_UUID: //Validate the value // Make sure it's not a blob oper if ( offset == 0 ) { if ( len != 16 ) { status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } //Write the value if ( status == SUCCESS ) { uint8 beaconID[] = { pValue[0],pValue[1],pValue[2],pValue[3],pValue[4],pValue[5],pValue[6],pValue[7], pValue[8],pValue[9],pValue[10],pValue[11],pValue[12],pValue[13],pValue[14],pValue[15] }; VOID osal_snv_write(BEACON_ID, BEACON_LEN, &beaconID); SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR1, SIMPLEPROFILE_CHAR1_LEN, &beaconID ); /*VOID osal_memcpy( pValue, pAttr->pValue, SIMPLEPROFILE_CHAR1_LEN ); if( pAttr->pValue == simpleProfileChar1 ) { notifyApp = SIMPLEPROFILE_CHAR1; }*/ } break; case SIMPLEPROFILE_CHAR2_UUID: //Validate the value // Make sure it's not a blob oper if ( offset == 0 ) { if ( len != 4 ) { status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } //Write the value if ( status == SUCCESS ) { uint8 major[] = { pValue[0],pValue[1],pValue[2],pValue[3],pValue[4],pValue[5],pValue[6],pValue[7], pValue[8],pValue[9],pValue[10],pValue[11],pValue[12],pValue[13],pValue[14],pValue[15] }; VOID osal_snv_write(MAJOR_ID, MAJOR_LEN, &major); SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR2, SIMPLEPROFILE_CHAR2_LEN, &major ); /*VOID osal_memcpy( pValue, pAttr->pValue, SIMPLEPROFILE_CHAR2_LEN ); if( pAttr->pValue == simpleProfileChar2 ) { notifyApp = SIMPLEPROFILE_CHAR2; }*/ } break; case SIMPLEPROFILE_CHAR3_UUID: //Validate the value // Make sure it's not a blob oper if ( offset == 0 ) { if ( len != 1 ) { status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } //Write the value if ( status == SUCCESS ) { uint8 power[] = { pValue[0] }; VOID osal_snv_write(POWER_ID, POWER_LEN, &power); } break; case SIMPLEPROFILE_CHAR4_UUID: //Validate the value // Make sure it's not a blob oper if ( offset == 0 ) { if ( len != 1 ) { status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } //Write the value if ( status == SUCCESS ) { if (pValue[0] == 0xFA) { HAL_SYSTEM_RESET(); } } break; case GATT_CLIENT_CHAR_CFG_UUID: status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY ); break; default: // Should never get here! (characteristics 2 and 4 do not have write permissions) status = ATT_ERR_ATTR_NOT_FOUND; break; } } else { // 128-bit UUID status = ATT_ERR_INVALID_HANDLE; } // If a charactersitic value changed then callback function to notify application of change if ( (notifyApp != 0xFF ) && simpleProfile_AppCBs && simpleProfile_AppCBs->pfnSimpleProfileChange ) { simpleProfile_AppCBs->pfnSimpleProfileChange( notifyApp ); } return ( status ); }
/********************************************************************* * @fn gapRole_taskFxn * * @brief Task entry point for the GAP Peripheral Role. * * @param a0 - first argument * @param a1 - second argument * * @return none */ static void gapRole_taskFxn(UArg a0, UArg a1) { // Initialize profile gapRole_init(); // Profile main loop for (;;) { // Waits for a signal to the semaphore associated with the calling thread. // Note that the semaphore associated with a thread is signaled when a // message is queued to the message receive queue of the thread or when // ICall_signal() function is called onto the semaphore. ICall_Errno errno = ICall_wait(ICALL_TIMEOUT_FOREVER); if (errno == ICALL_ERRNO_SUCCESS) { ICall_EntityID dest; ICall_ServiceEnum src; ICall_HciExtEvt *pMsg = NULL; if (ICall_fetchServiceMsg(&src, &dest, (void **)&pMsg) == ICALL_ERRNO_SUCCESS) { uint8_t safeToDealloc = TRUE; if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == selfEntity)) { ICall_Stack_Event *pEvt = (ICall_Stack_Event *)pMsg; // Check for BLE stack events first if (pEvt->signature == 0xffff) { if (pEvt->event_flag & GAP_EVENT_SIGN_COUNTER_CHANGED) { // Sign counter changed, save it to NV VOID osal_snv_write(BLE_NVID_SIGNCOUNTER, sizeof(uint32_t), &gapRole_signCounter); } } else { // Process inter-task message safeToDealloc = gapRole_processStackMsg((ICall_Hdr *)pMsg); } } if (pMsg && safeToDealloc) { ICall_freeMsg(pMsg); } } } if (events & START_ADVERTISING_EVT) { events &= ~START_ADVERTISING_EVT; if (gapRole_AdvEnabled || gapRole_AdvNonConnEnabled) { gapAdvertisingParams_t params; // Setup advertisement parameters if (gapRole_AdvNonConnEnabled) { // Only advertise non-connectable undirected. params.eventType = GAP_ADTYPE_ADV_NONCONN_IND; } else { params.eventType = gapRole_AdvEventType; params.initiatorAddrType = gapRole_AdvDirectType; VOID memcpy(params.initiatorAddr, gapRole_AdvDirectAddr, B_ADDR_LEN); } params.channelMap = gapRole_AdvChanMap; params.filterPolicy = gapRole_AdvFilterPolicy; if (GAP_MakeDiscoverable(selfEntity, ¶ms) != SUCCESS) { gapRole_abort(); } } } if (events & CONN_PARAM_TIMEOUT_EVT) { events &= ~CONN_PARAM_TIMEOUT_EVT; // Unsuccessful in updating connection parameters gapRole_HandleParamUpdateNoSuccess(); } } // for }
/********************************************************************* * @fn gapCentralRole_ProcessGAPMsg * * @brief Process an incoming task message from GAP. * * @param pMsg - message to process * * @return none */ static void gapCentralRole_ProcessGAPMsg( gapEventHdr_t *pMsg ) { uint8 isBroadcastMsg = FALSE; switch ( pMsg->opcode ) { case GAP_DEVICE_INIT_DONE_EVENT: { gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *) pMsg; bStatus_t stat = pPkt->hdr.status; if ( pPkt->hdr.status == SUCCESS ) { // Save off the generated keys VOID osal_snv_write( BLE_NVID_IRK, KEYLEN, gapCentralRoleIRK ); VOID osal_snv_write( BLE_NVID_CSRK, KEYLEN, gapCentralRoleSRK ); // Save off the information VOID osal_memcpy( gapCentralRoleBdAddr, pPkt->devAddr, B_ADDR_LEN ); /////////////////////////////////////////////////////////////////////// // Broadcast // Save off the information VOID osal_memcpy( gapRole_bdAddr, pPkt->devAddr, B_ADDR_LEN ); gapRole_state = GAPROLE_STARTED; // Update the advertising data stat =GAP_UpdateAdvertisingData( gapRole_TaskID, TRUE, gapRole_AdvertDataLen, gapRole_AdvertData ); } if ( stat != SUCCESS ) { gapRole_state = GAPROLE_ERROR; } isBroadcastMsg = TRUE; } break; case GAP_LINK_ESTABLISHED_EVENT: { gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *) pMsg; if (pPkt->hdr.status == SUCCESS) { // Notify the Bond Manager of the connection VOID GAPBondMgr_LinkEst( pPkt->devAddrType, pPkt->devAddr, pPkt->connectionHandle, GAP_PROFILE_CENTRAL ); } } break; case GAP_LINK_TERMINATED_EVENT: { uint16 connHandle = ((gapTerminateLinkEvent_t *) pMsg)->connectionHandle; GAPBondMgr_ProcessGAPMsg( (gapEventHdr_t *)pMsg ); // Cancel RSSI reads GAPCentralRole_CancelRssi( connHandle ); } break; // temporary workaround case GAP_SLAVE_REQUESTED_SECURITY_EVENT: GAPBondMgr_ProcessGAPMsg( pMsg ); break; case GAP_ADV_DATA_UPDATE_DONE_EVENT: { gapAdvDataUpdateEvent_t *pPkt = (gapAdvDataUpdateEvent_t *)pMsg; if ( pPkt->hdr.status == SUCCESS ) { if ( pPkt->adType ) { // Setup the Response Data pPkt->hdr.status = GAP_UpdateAdvertisingData( gapRole_TaskID, FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData ); } else { // Start advertising VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT ); } } if ( pPkt->hdr.status != SUCCESS ) { // Set into Error state gapRole_state = GAPROLE_ERROR; isBroadcastMsg = TRUE; } } break; case GAP_MAKE_DISCOVERABLE_DONE_EVENT: case GAP_END_DISCOVERABLE_DONE_EVENT: { gapMakeDiscoverableRspEvent_t *pPkt = (gapMakeDiscoverableRspEvent_t *)pMsg; if ( pPkt->hdr.status == SUCCESS ) { if ( pMsg->opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT ) { gapRole_state = GAPROLE_ADVERTISING; } else // GAP_END_DISCOVERABLE_DONE_EVENT { if ( gapRole_AdvertOffTime != 0 ) { if ( ( gapRole_AdvEnabled ) ) { VOID osal_start_timerEx( gapRole_TaskID, START_ADVERTISING_EVT, gapRole_AdvertOffTime ); } } else { // Since gapRole_AdvertOffTime is set to 0, the device should not // automatically become discoverable again after a period of time. // Set enabler to FALSE; device will become discoverable again when // this value gets set to TRUE gapRole_AdvEnabled = FALSE; } // In the Advertising Off period gapRole_state = GAPROLE_WAITING; } } else { gapRole_state = GAPROLE_ERROR; } isBroadcastMsg = TRUE; } break; default: break; } // If a broadcast event, pass to broadcast callback. if ( isBroadcastMsg == TRUE ) { // Notify the application if ( pGapCentralRoleCB && pGapCentralRoleCB->broadcastCB ) { pGapCentralRoleCB->broadcastCB( gapRole_state ); } } // Otherwise pass to central callback else if ( pGapCentralRoleCB && pGapCentralRoleCB->centralCB ) { pGapCentralRoleCB->centralCB( (gapCentralRoleEvent_t *) pMsg ); } }
/*************************************************************************************************** * @fn BLE_set_par * * @brief BLE_set_par * * @param None * * @return None ***************************************************************************************************/ void BLE_set_par( uint8 *buffer) { NPI_PrintValue("set par",0); uint8 par_num = *buffer++; while(par_num) { switch(*buffer) { case ID_PAR_DOWN_PULSE: { ble_parameter.down_pulse_max = *(buffer+2); buffer += 3; NPI_PrintValue("d pulse",ble_parameter.down_pulse_max); } break; case ID_PAR_UP_PULSE: { ble_parameter.up_pulse_max = *(buffer+2); buffer += 3; NPI_PrintValue("u pulse",ble_parameter.up_pulse_max); } break; case ID_PAR_ADV_POLICY: { ble_parameter.adv_policy = *(buffer+2); buffer += 3; NPI_PrintValue("adv p",ble_parameter.adv_policy); } break; case ID_PAR_ADV_TIME: { ble_parameter.adv_time = *(buffer+2); buffer += 3; NPI_PrintValue("adv_time",ble_parameter.adv_time); } break; case ID_PAR_ABNORMAL_TIME: { buffer += 6; } break; case ID_PAR_ABNORMAL_POLICY: { buffer += 3; } break; default: buffer += 1; break; } par_num--; } //save par to NV osal_snv_write(BLE_NVID_PAR, sizeof(BLE_PARAMETER), &ble_parameter); BLE_Set_Parameter(); }
/*************************************************************************************************** * @fn Uart_Msg_Parse * * @brief parse uart Msg,this msg was came from e009 uart * * @param pBuffer: msg; length: msg length * * @return None ***************************************************************************************************/ bool Uart_Msg_Parse(uint8* pBuffer, uint8 length) { bool ret = TRUE; // pBuffer[0] = MSG_IDENTIFICATION;pBuffer[1]=msd id switch(pBuffer[1]) { case ID_E0092BLE_G_RSP: last_uart_send.msg_buffer[0] = 0; break; case ID_E0092BLE_TIME: BLE_Common_Response(ID_E0092BLE_TIME,RSP_OK); uart_pulse_timeout_count = 0; Set_Ble_Time(pBuffer+3); break; case ID_E0092BLE_REBOOT_BLE: BLE_Common_Response(ID_E0092BLE_REBOOT_BLE,RSP_OK); BLE_Reboot(); break; case ID_E0092BLE_IMEI: BLE_Common_Response(ID_E0092BLE_IMEI,RSP_OK); //gE009_ready = true; //osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_E009_READY, 250 ); osal_memcpy(gSerial_Num[DEV_B].imei,pBuffer+3,SERIAl_NUM_LEN); break; case ID_E0092BLE_IMSI: BLE_Common_Response(ID_E0092BLE_IMSI,RSP_OK); gE009_ready = true; waiting_e009_powerup = false; osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_E009_READY, 250 ); osal_memcpy(gSerial_Num[DEV_B].imsi,pBuffer+3,SERIAl_NUM_LEN); Uart_Msg_Save_QST_NUM(); break; case ID_E0092BLE_BAT: //QST E009 to BLE BLE_Common_Response(ID_E0092BLE_BAT,RSP_OK); sys_config.battery = *(pBuffer+3); osal_snv_write(BLE_NVID_SYS_CONF, sizeof(SYS_CONFIG), &sys_config); BLE_SEND_BAT_TO_HWJ(); break; case ID_E0092BLE_START_E009: BLE_Common_Response(ID_E0092BLE_START_E009,RSP_OK); BLE_Powerup_QST_E009(true); break; case ID_E0092BLE_POWEROFF: //QST E009 to BLE,power off himself BLE_Common_Response(ID_E0092BLE_POWEROFF,RSP_OK); BLE_Powerup_QST_E009(false); break; case ID_E0092BLE_REBOOT_OTHER: //HWJ reboot QST, QST reboot HWJ BLE_Common_Response(ID_E0092BLE_REBOOT_OTHER,RSP_OK); BLE_Reboot_Other(); break; case ID_E0092BLE_STATE: E009_state = *(pBuffer+3); if(E009_state == E009_STATE_SLEEP) { Save_E009_powerup_time( pBuffer+4 ); } BLE_Common_Response(ID_E0092BLE_STATE,E009_state); break; case ID_E0092BLE_START_ADV: //QST E009 to BLE, start advertising BLE_Common_Response(ID_E0092BLE_START_ADV,RSP_OK); BLE_start_adv(); break; case ID_E0092BLE_PAR: e009_abnormal_parameter.time = *(pBuffer+21); if(*(pBuffer+20) > 0 || *(pBuffer+19) > 0 || *(pBuffer+18) > 0) e009_abnormal_parameter.time = 240; AbnormalDelayBootE009Count = 2*e009_abnormal_parameter.time; e009_abnormal_parameter.policy = *(pBuffer+24); if(e009_abnormal_parameter.policy != 0) e009_abnormal_parameter.policy = 1; osal_snv_write(BLE_NVID_PAR_ABNORMAL, sizeof(E009_ABNORMAL_PARAMETER), &e009_abnormal_parameter); BLE_Common_Response(ID_E0092BLE_PAR,RSP_OK); //BLE_set_par( pBuffer+3 ); break; case ID_E0092BLE_REBOOT: BLE_Common_Response(ID_E0092BLE_REBOOT,RSP_OK); BLE_Reboot_E009(); break; default: ret = FALSE; break; } return ret; }
/********************************************************************* * @fn gapRole_processGAPMsg * * @brief Process an incoming task message. * * @param pMsg - message to process * * @return none */ static uint8_t gapRole_processGAPMsg(gapEventHdr_t *pMsg) { uint8_t notify = FALSE; // State changed notify the app? (default no) switch (pMsg->opcode) { case GAP_DEVICE_INIT_DONE_EVENT: { gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *)pMsg; bStatus_t stat = pPkt->hdr.status; if (stat == SUCCESS) { // Save off the generated keys VOID osal_snv_write(BLE_NVID_IRK, KEYLEN, gapRole_IRK); VOID osal_snv_write(BLE_NVID_CSRK, KEYLEN, gapRole_SRK); // Save off the information VOID memcpy(gapRole_bdAddr, pPkt->devAddr, B_ADDR_LEN); // Update the advertising data stat = GAP_UpdateAdvertisingData(selfEntity, TRUE, gapRole_AdvertDataLen, gapRole_AdvertData); } if (stat != SUCCESS) { gapRole_abort(); } notify = TRUE; } break; case GAP_ADV_DATA_UPDATE_DONE_EVENT: { gapAdvDataUpdateEvent_t *pPkt = (gapAdvDataUpdateEvent_t *)pMsg; if (pPkt->hdr.status == SUCCESS) { if (pPkt->adType) { // Setup the Response Data pPkt->hdr.status = GAP_UpdateAdvertisingData(selfEntity, FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData); } else if (Util_isActive(&startAdvClock) == FALSE) { // Start advertising gapRole_setEvent(START_ADVERTISING_EVT); } } if (pPkt->hdr.status != SUCCESS) { // Set into Error state gapRole_abort(); notify = TRUE; } } break; case GAP_MAKE_DISCOVERABLE_DONE_EVENT: case GAP_END_DISCOVERABLE_DONE_EVENT: { gapMakeDiscoverableRspEvent_t *pPkt = (gapMakeDiscoverableRspEvent_t *)pMsg; if (pPkt->hdr.status == SUCCESS) { if (pMsg->opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT) { gapRole_AdvEnabled = TRUE; } else // GAP_END_DISCOVERABLE_DONE_EVENT { if (gapRole_AdvertOffTime != 0) //restart advertising if param is set { if ((gapRole_AdvEnabled) || (gapRole_AdvNonConnEnabled)) { Util_restartClock(&startAdvClock, gapRole_AdvertOffTime); } } else { // Since gapRole_AdvertOffTime is set to 0, the device should not // automatically become discoverable again after a period of time. // Set enabler to FALSE; device will become discoverable again when // this value gets set to TRUE if (gapRole_AdvEnabled == TRUE) { gapRole_AdvEnabled = FALSE; } } } notify = TRUE; } else if (pPkt->hdr.status == LL_STATUS_ERROR_COMMAND_DISALLOWED) //we're already advertising { notify = FALSE; } else { gapRole_abort(); } } break; case GAP_LINK_ESTABLISHED_EVENT: { gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *)pMsg; uint8_t advertEnable = TRUE; if (pPkt->hdr.status == SUCCESS) { // Notify the Bond Manager to the connection VOID GAPBondMgr_LinkEst(pPkt->devAddrType, pPkt->devAddr, pPkt->connectionHandle, pPkt->connRole); //advertising will stop after connection formed as slave if ((pPkt->connRole) == GAP_PROFILE_PERIPHERAL) { gapRole_AdvEnabled = FALSE; //reenable advertising GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &advertEnable, NULL); } } else if (pPkt->hdr.status == bleGAPConnNotAcceptable) { // Set enabler to FALSE; device will become discoverable again when // this value gets set to TRUE gapRole_AdvEnabled = FALSE; } else { gapRole_abort(); } notify = TRUE; } break; case GAP_LINK_TERMINATED_EVENT: { gapTerminateLinkEvent_t *pPkt = (gapTerminateLinkEvent_t *)pMsg; linkDBInfo_t pInfo; linkDB_GetInfo(pPkt->connectionHandle, &pInfo); // notify bond manager GAPBondMgr_LinkTerm(pPkt->connectionHandle); notify = TRUE; } break; case GAP_SLAVE_REQUESTED_SECURITY_EVENT: { uint16_t connHandle = ((gapSlaveSecurityReqEvent_t *)pMsg)->connectionHandle; uint8_t authReq = ((gapSlaveSecurityReqEvent_t *)pMsg)->authReq; GAPBondMgr_SlaveReqSecurity(connHandle, authReq); } break; case GAP_LINK_PARAM_UPDATE_EVENT: { gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsg; // Cancel connection param update timeout timer (if active) Util_stopClock(&updateTimeoutClock); if (pPkt->hdr.status == SUCCESS) { notify = TRUE; } } break; default: notify = TRUE; break; } if (notify == TRUE) //app needs to take further action { if (pGapRoles_AppCGs && pGapRoles_AppCGs->pfnPassThrough) { return (pGapRoles_AppCGs->pfnPassThrough((gapMultiRoleEvent_t *)pMsg)); } } return TRUE; }