/********************************************************************* * @fn ccChangeCB * * @brief Callback from Connection Control indicating a value change * * @param paramID - parameter ID of the value that was changed. * * @return none */ static void ccChangeCB( uint8 paramID ) { // CCSERVICE_CHAR1: read & notify only // CCSERVICE_CHAR: requested connection parameters if( paramID == CCSERVICE_CHAR2 ) { uint8 buf[CCSERVICE_CHAR2_LEN]; uint16 minConnInterval; uint16 maxConnInterval; uint16 slaveLatency; uint16 timeoutMultiplier; CcService_GetParameter( CCSERVICE_CHAR2, buf ); minConnInterval = BUILD_UINT16(buf[0],buf[1]); maxConnInterval = BUILD_UINT16(buf[2],buf[3]); slaveLatency = BUILD_UINT16(buf[4],buf[5]); timeoutMultiplier = BUILD_UINT16(buf[6],buf[7]); // Update connection parameters GAPRole_SendUpdateParam( minConnInterval, maxConnInterval, slaveLatency, timeoutMultiplier, GAPROLE_TERMINATE_LINK); } // CCSERVICE_CHAR3: Disconnect request if( paramID == CCSERVICE_CHAR3 ) { // Any change in the value will terminate the connection GAPRole_TerminateConnection(); } }
/** * SNP_terminateConn * */ uint8_t SNP_terminateConn(snpTermConnReq_t *pReq) { uint8_t status = SNP_SUCCESS; if(pReq->option == SNP_GAP_TERM_CONN_IMMEDIATLY) { uint16_t value; GAPRole_GetParameter(GAPROLE_CONNHANDLE, &value); if(pReq->connHandle != value) { return SNP_INVALID_PARAMS; } else { HCI_EXT_DisconnectImmedCmd(value); } } else if(pReq->option == SNP_GAP_TERM_CONN_DEFAULT) { status = GAPRole_TerminateConnection(); } else { return SNP_INVALID_PARAMS; } return status; }
/********************************************************************* * @fn processGapStateChange * * @brief Change the GAP state. * 1. Connected -> disconnect and start advertising * 2. Advertising -> stop advertising * 3. Disconnected/not advertising -> start advertising * * @param none * * @return none */ static void processGapStateChange(void) { if (gapProfileState != GAPROLE_CONNECTED) { uint8_t current_adv_enabled_status; uint8_t new_adv_enabled_status; // Find the current GAP advertising status GAPRole_GetParameter(GAPROLE_ADVERT_ENABLED, ¤t_adv_enabled_status); if (current_adv_enabled_status == FALSE) { new_adv_enabled_status = TRUE; } else { new_adv_enabled_status = FALSE; } // Change the GAP advertisement status to opposite of current status GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &new_adv_enabled_status); } if (gapProfileState == GAPROLE_CONNECTED) { uint8_t adv_enabled = TRUE; // Disconnect GAPRole_TerminateConnection(); // Start advertising GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &adv_enabled); } }
/******************************************************************************* * @fn SensorTagConnControl_processCharChangeEvt * * @brief Process a change in the connection control characteristics * * @return none */ void SensorTagConnControl_processCharChangeEvt(uint8_t paramID) { // CCSERVICE_CHAR1: read & notify only // CCSERVICE_CHAR: requested connection parameters if (paramID == CCSERVICE_CHAR2) { uint8_t buf[CCSERVICE_CHAR2_LEN]; // Get new connection parameters CcService_getParameter( CCSERVICE_CHAR2, buf); // Update connection parameters GAPRole_SendUpdateParam( BUILD_UINT16(buf[0],buf[1]), BUILD_UINT16(buf[2],buf[3]), // minConnInterval, maxConnInterval BUILD_UINT16(buf[4],buf[5]), BUILD_UINT16(buf[6],buf[7]), // slaveLatency, timeoutMultiplier GAPROLE_TERMINATE_LINK); } // CCSERVICE_CHAR3: Disconnect request else if (paramID == CCSERVICE_CHAR3) { // Any change in the value will terminate the connection GAPRole_TerminateConnection(); } }
uint8 Application_TerminateConnection() { if( gapProfileState == GAPROLE_CONNECTED ) { // Exit the connection GAPRole_TerminateConnection(); return SUCCESS; } return FAILURE; }
/********************************************************************* * @fn CyclingSensor_handleResetEvt * * @brief "soft" resets the device. This puts the device into a waiting * state, clears all white list, bonding and GATT service handle * information about previously previously connected devices. * * @param none * * @return none */ static void CyclingSensor_handleResetEvt(void) { static uint8_t isWLClear = FALSE; if (gapProfileState == GAPROLE_CONNECTED) { // Exit the connection. GAPRole_TerminateConnection(); } else if (gapProfileState == GAPROLE_ADVERTISING) { uint8_t value = FALSE; // Turn off advertising. GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &value); } else if (USING_WHITE_LIST == TRUE && isWLClear == FALSE) { // Set internal white list flag to true. isWLClear = TRUE; // Disable white list use with advertising. sensorUsingWhiteList = FALSE; // Temporary variable. uint8_t value = GAP_FILTER_POLICY_ALL; // Turn off white list filter policy. GAPRole_SetParameter(GAPROLE_ADV_FILTER_POLICY, sizeof(uint8_t), &value); // Clear the white list. HCI_LE_ClearWhiteListCmd(); } else if ((gapProfileState == GAPROLE_STARTED) || (gapProfileState == GAPROLE_WAITING) || (gapProfileState == GAPROLE_WAITING_AFTER_TIMEOUT)) { uint8_t eraseBonds = TRUE; // Stop the periodic expirations of the reset clock. Util_stopClock(&resetClock); // Set internal white list flag to false for next reset event. isWLClear = FALSE; // Erase all bonds. GAPBondMgr_SetParameter(GAPBOND_ERASE_ALLBONDS, 0, &eraseBonds); // Turn on GREEN LED for set time. //HalLedSet(HAL_LED_1, HAL_LED_MODE_BLINK); } }
/********************************************************************* * @fn HidDev_Close * * @brief Close the connection or stop advertising. * * @return None. */ void HidDev_Close( void ) { uint8 param; // if connected then disconnect if ( hidDevGapState == GAPROLE_CONNECTED ) { GAPRole_TerminateConnection(); } // else stop advertising else { param = FALSE; GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), ¶m ); } }
/********************************************************************* * @fn gapRole_processStackMsg * * @brief Process an incoming task message. * * @param pMsg - message to process * * @return none */ static uint8_t gapRole_processStackMsg(ICall_Hdr *pMsg) { uint8_t safeToDealloc = TRUE; switch (pMsg->event) { case GAP_MSG_EVENT: safeToDealloc = gapRole_processGAPMsg((gapEventHdr_t *)pMsg); break; case L2CAP_SIGNAL_EVENT: { l2capSignalEvent_t *pPkt = (l2capSignalEvent_t *)pMsg; // Process the Parameter Update Response if (pPkt->opcode == L2CAP_PARAM_UPDATE_RSP) { l2capParamUpdateRsp_t *pRsp = (l2capParamUpdateRsp_t *)&(pPkt->cmd.updateRsp); if ((pRsp->result == L2CAP_CONN_PARAMS_REJECTED) && (paramUpdateNoSuccessOption == GAPROLE_TERMINATE_LINK)) { // Cancel connection param update timeout timer Util_stopClock(&updateTimeoutClock); // Terminate connection immediately GAPRole_TerminateConnection(pPkt->connHandle); } else { uint16_t timeout = GAP_GetParamValue(TGAP_CONN_PARAM_TIMEOUT); // Let's wait for Controller to update connection parameters if they're // accepted. Otherwise, decide what to do based on no success option. Util_restartClock(&updateTimeoutClock, timeout); } } } break; default: break; } return (safeToDealloc); }
/********************************************************************* * @fn HidDev_SetParameter * * @brief Set a HID Dev parameter. * * @param param - Profile parameter ID * @param len - length of data to right * @param pValue - pointer to data to write. This is dependent on * the parameter ID and WILL be cast to the appropriate * data type (example: data type of uint16 will be cast to * uint16 pointer). * * @return bStatus_t */ bStatus_t HidDev_SetParameter( uint8 param, uint8 len, void *pValue ) { bStatus_t ret = SUCCESS; switch ( param ) { case HIDDEV_ERASE_ALLBONDS: if ( len == 0 ) { // See if the last report sent out wasn't a release key if ( osal_isbufset( lastNoti.value, 0x00, lastNoti.len ) == FALSE ) { // Send a release report before disconnecting, otherwise // the last pressed key would get 'stuck' on the HID Host. osal_memset( lastNoti.value, 0x00, lastNoti.len ); GATT_Notification( gapConnHandle, &lastNoti, FALSE ); } // Drop connection if ( hidDevGapState == GAPROLE_CONNECTED ) { GAPRole_TerminateConnection(); } // Flush report queue firstQIdx = lastQIdx = 0; // Erase bonding info GAPBondMgr_SetParameter( GAPBOND_ERASE_ALLBONDS, 0, NULL ); } else { ret = bleInvalidRange; } break; default: ret = INVALIDPARAMETER; break; } return ( ret ); }
/********************************************************************* * @fn pairStateCB * @brief Pairing state callback. * @return none */ static void simpleBLEPeripheralPairStateCB(uint16 connHandle, uint8 state, uint8 status) { if (state == GAPBOND_PAIRING_STATE_STARTED) { HalLcdWriteString("Pairing started", HAL_LCD_LINE_7); } else if (state == GAPBOND_PAIRING_STATE_COMPLETE) { if (status == SUCCESS) { HalLcdWriteString("Pairing success", HAL_LCD_LINE_7); } else { HalLcdWriteStringValue("Pairing fail", status, 10, HAL_LCD_LINE_7); uint8 a = GAPRole_TerminateConnection(); HalLcdWriteStringValue("Pairing fail--a", a, 10, HAL_LCD_LINE_7); } } else if (state == GAPBOND_PAIRING_STATE_BONDED) { if (status == SUCCESS) { HalLcdWriteString("Bonding success", HAL_LCD_LINE_1); } } //osal_start_timerEx(simpleBLEPeripheral_TaskID, SBP_ZEKEZANG_EVT, 5000); }
/********************************************************************* * @fn gapRole_HandleParamUpdateNoSuccess * * @brief Handle unsuccessful connection parameters update. * * @param none * * @return none */ static void gapRole_HandleParamUpdateNoSuccess(void) { // See which option was chosen for unsuccessful updates switch (paramUpdateNoSuccessOption) { case GAPROLE_RESEND_PARAM_UPDATE: gapRole_connUpdate(GAPROLE_RESEND_PARAM_UPDATE, &gapRole_updateConnParams); break; case GAPROLE_TERMINATE_LINK: GAPRole_TerminateConnection(gapRole_updateConnParams.connHandle); break; case GAPROLE_NO_ACTION: // fall through default: //do nothing break; } }
/********************************************************************* * @fn gapRole_HandleParamUpdateNoSuccess * * @brief Handle unsuccessful connection parameters update. * * @param none * * @return none */ static void gapRole_HandleParamUpdateNoSuccess( void ) { // See which option was choosen for unsuccessful updates switch ( paramUpdateNoSuccessOption ) { case GAPROLE_RESEND_PARAM_UPDATE: GAPRole_SendUpdateParam( gapRole_MinConnInterval, gapRole_MaxConnInterval, gapRole_SlaveLatency, gapRole_TimeoutMultiplier, GAPROLE_RESEND_PARAM_UPDATE ); break; case GAPROLE_TERMINATE_LINK: GAPRole_TerminateConnection(); break; case GAPROLE_NO_ACTION: // fall through default: //do nothing break; } }
/********************************************************************* * @fn Thermometer_ProcessEvent * * @brief Thermometer Application Task event processor. This function * is called to process all events for the task. Events * include timers, messages and any other user defined events. * * @param task_id - The OSAL assigned task ID. * @param events - events to process. This is a bit map and can * contain more than one event. * * @return events not processed */ uint16 Thermometer_ProcessEvent( uint8 task_id, uint16 events ) { VOID task_id; // OSAL required parameter that isn't used in this function uint8 notify_interval; int32 n32; if ( events & SYS_EVENT_MSG ) { uint8 *pMsg; if ( (pMsg = osal_msg_receive( thermometerTaskId )) != NULL ) { thermometer_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 & TH_START_DEVICE_EVT ) { // Start the Device VOID GAPRole_StartDevice( &thermometer_PeripheralCBs ); // Register with bond manager after starting device VOID GAPBondMgr_Register( &thermometer_BondMgrCBs ); updateUI(); return ( events ^ TH_START_DEVICE_EVT ); } if ( events & TH_START_DISCOVERY_EVT ) { if ( timeAppPairingStarted ) { // Postpone discovery until pairing completes timeAppDiscPostponed = TRUE; } else { timeAppDiscState = timeAppDiscStart(); } timeAppDiscState = timeAppDiscStart(); return ( events ^ TH_START_DISCOVERY_EVT ); } //periodic indications - if enabled if ( events & TH_PERIODIC_MEAS_EVT ) { // Perform periodic application task performPeriodicTask(); return (events ^ TH_PERIODIC_MEAS_EVT); } //periodic notifications for IMEAS if ( events & TH_PERIODIC_IMEAS_EVT ) { // Perform periodic application task performPeriodicImeasTask(); return (events ^ TH_PERIODIC_IMEAS_EVT); } // Disconnect after sending measurement if ( events & TH_DISCONNECT_EVT ) { uint8 advEnable = FALSE; //disable advertising on disconnect GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advEnable ); // Terminate Connection GAPRole_TerminateConnection(); return (events ^ TH_DISCONNECT_EVT); } if ( events & TH_CCC_UPDATE_EVT ) //This event is triggered when CCC is enabled if (gapProfileState == GAPROLE_CONNECTED) { temperatureMeasCharConfig = true; //if previously connected and measurements are active send stored if( connectedToLastAddress == true) { //send stored measurements thermometerSendStoredMeas(); } //Only start meas timer if it's not running if(thMeasTimerRunning == FALSE) { //read stored interval value Thermometer_GetParameter( THERMOMETER_INTERVAL, ¬ify_interval ); n32 = ((uint32)(notify_interval)) * (1000); //zero interval means should not perform meas if (n32 !=0) { // Start interval timer osal_start_timerEx( thermometerTaskId, TH_PERIODIC_MEAS_EVT, n32 ); thMeasTimerRunning = TRUE; } } return (events ^ TH_CCC_UPDATE_EVT); } return 0; }
/********************************************************************* * @fn BloodPressure_ProcessEvent * * @brief BloodPressure Application Task event processor. This function * is called to process all events for the task. Events * include timers, messages and any other user defined events. * * @param task_id - The OSAL assigned task ID. * @param events - events to process. This is a bit map and can * contain more than one event. * * @return events not processed */ uint16 BloodPressure_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( bloodPressureTaskId )) != NULL ) { bloodPressure_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 & BP_START_DEVICE_EVT ) { // Start the Device VOID GAPRole_StartDevice( &bloodPressure_PeripheralCBs ); // Register with bond manager after starting device GAPBondMgr_Register( (gapBondCBs_t *) &timeAppBondCB ); updateUI(); return ( events ^ BP_START_DEVICE_EVT ); } if ( events & BP_START_DISCOVERY_EVT ) { if ( timeAppPairingStarted ) { // Postpone discovery until pairing completes timeAppDiscPostponed = TRUE; } else { timeAppDiscState = timeAppDiscStart(); } return ( events ^ BP_START_DISCOVERY_EVT ); } /////////////////////////////////// // BP MEAS DONE /////////////////////////////////// if ( events & TIMER_BPMEAS_EVT ) { // Perform final measurement bpFinalMeas(); return (events ^ TIMER_BPMEAS_EVT); } /////////////////////////////////// // CUFF /////////////////////////////////// if ( events & BP_TIMER_CUFF_EVT ) { // Perform a Cutoff Measurement cuffMeas(); cuffCount++; // If cuff count not met, keep sending cuff measurements if(cuffCount < CUFF_MAX) { // Start interval timer to send BP, just for simulation osal_start_timerEx( bloodPressureTaskId, BP_TIMER_CUFF_EVT, TIMER_CUFF_PERIOD ); } // Get ready to send final measurement else { // Start timer to send final BP meas osal_start_timerEx( bloodPressureTaskId, TIMER_BPMEAS_EVT, TIMER_CUFF_PERIOD ); } return (events ^ BP_TIMER_CUFF_EVT); } // Enable Bloodpressure CCC if ( events & BP_CCC_UPDATE_EVT ) { if (gapProfileState == GAPROLE_CONNECTED) { //if previously connected and measurements are active send stored if( connectedToLastAddress == true) { //send stored measurements bpSendStoredMeas(); } } return (events ^ BP_CCC_UPDATE_EVT); } // Disconnect after sending measurement if ( events & BP_DISCONNECT_EVT ) { uint8 advEnable = FALSE; //disable advertising on disconnect GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advEnable ); HalLedSet ( HAL_LED_1, HAL_LED_MODE_ON ); // Terminate Connection GAPRole_TerminateConnection(); return (events ^ BP_DISCONNECT_EVT); } return 0; }
/********************************************************************* * @fn Thermometer_disconnectEvt * * @brief Disconnect. * * @param none * * @return none */ static void Thermometer_disconnectEvt(void) { // Terminate Connection. GAPRole_TerminateConnection(); }
/********************************************************************* * @fn sensorTag_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 sensorTag_HandleKeys( uint8 shift, uint8 keys ) { uint8 SK_Keys = 0; VOID shift; // Intentionally unreferenced parameter if (keys & HAL_KEY_SW_1) { // Reset the system if side key is pressed for more than 3 seconds sysResetRequest = TRUE; osal_start_timerEx( sensorTag_TaskID, ST_SYS_RESET_EVT, ST_SYS_RESET_DELAY ); if (!testMode ) // Side key { // If device is not in a connection, pressing the side key should toggle // advertising on and off if ( gapProfileState != GAPROLE_CONNECTED ) { uint8 current_adv_enabled_status; uint8 new_adv_enabled_status; // Find the current GAP advertising status GAPRole_GetParameter( GAPROLE_ADVERT_ENABLED, ¤t_adv_enabled_status ); if( current_adv_enabled_status == FALSE ) { new_adv_enabled_status = TRUE; } else { new_adv_enabled_status = FALSE; } // Change the GAP advertisement status to opposite of current status GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &new_adv_enabled_status ); } if ( gapProfileState == GAPROLE_CONNECTED ) { uint8 adv_enabled = TRUE; // Disconnect GAPRole_TerminateConnection(); // Start advertising GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &adv_enabled ); } } else { // Test mode if ( keys & HAL_KEY_SW_1 ) // Side key { SK_Keys |= SK_KEY_SIDE; } } } if ( keys & HAL_KEY_SW_2 ) // Carbon S2 { SK_Keys |= SK_KEY_LEFT; } if ( keys & HAL_KEY_SW_3 ) // Carbon S3 { SK_Keys |= SK_KEY_RIGHT; } if (!(keys & HAL_KEY_SW_1)) { // Cancel system reset request sysResetRequest = FALSE; } // Set the value of the keys state to the Simple Keys Profile; // This will send out a notification of the keys state if enabled SK_SetParameter( SK_KEY_ATTR, sizeof ( uint8 ), &SK_Keys ); }
/******************************************************************************* * @fn userAppPro * * @brief user Application event process * * @param evnet * * @return none */ void userAppPro(void) { if (userEvents & USER_10MS_EVT) { userEvents &= ~USER_10MS_EVT; Util_startClock(&periodicClock_10ms); KEY_Scan_10ms(); ChangeTime10mSec(); Pollint100mSec(); } #ifdef INCLUDE_CLKSTOP while (!Queue_empty(keyMsgQueue)) { KEY_stEvt_t *pMsg = (KEY_stEvt_t *)Util_dequeueMsg(keyMsgQueue); if (pMsg) { // Process message. switch(pMsg->GPIOName) { case KEY_NAME_3V3: if (KEY_HIGH == pMsg->GPIOStatus) { wifiPowerOn(); uartWriteDebug("poweron3v3", 10); OLED_ShowString(40,32, "WiCore"); userAppShowCharge(); // 启动广播 { uint8_t initialAdvertEnable = TRUE; GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initialAdvertEnable); } Util_startClock(&periodicClock_10ms); } else { wifiPowerDown(); uartWriteDebug("powerdown3v3", 12); // 清低电闪烁 systemState.lowBatteryFlag = 0; OLED_Clear(); // 这个执行时间较长 打乱了定时周期,所以stopClock是没有用的 //Util_stopClock(&periodicClock_10ms); // 服务器的按键开关机 设置一个按键放开标志位,等待1s后没有放开 // 就清标志位,关闭时钟 systemState.keyUpFlag = 3; // 2 为电源按键 等待按键放开标志,3为 服务器按键 systemState.delayCnt = 10; // 有链接,关闭 GAPRole_TerminateConnection(); } break; case KEY_POWER: if (KEY_IQR == pMsg->GPIOStatus) { KEY_DisableIRQ(); uartWriteDebug("tttt", 4); systemState.powerOffFlag = 1; systemState.delayPowerOffTime = 5; // 延时5s 判断是否是按键长按 Util_startClock(&periodicClock_10ms); } else if (KEY_LONG == pMsg->GPIOStatus) { if (1 == systemState.powerOffFlag) { systemState.powerOffFlag = 0; systemState.delayPowerOffTime = 0; wifiPowerOn(); userAppShowCharge(); OLED_ShowString(40,32, "WiCore"); // 启动广播 { uint8_t initialAdvertEnable = TRUE; GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initialAdvertEnable); } uartWriteDebug("poweron", 7); } else { //系统断电 wifiPowerDown(); uartWriteDebug("powerdown", 9); OLED_Clear(); systemState.lowBatteryFlag = 0; // 清低电闪烁 systemState.keyUpFlag = 2; // 2 为电源按键 等待按键放开标志,3为 服务器按键 // 有链接,关闭 GAPRole_TerminateConnection(); } systemState.keyShortFlag = 0; // 忽略短按事件 } else if (KEY_LOW == pMsg->GPIOStatus)// 松开 { if (2 == systemState.keyUpFlag) // 长按松开,关机 { systemState.keyUpFlag = 0; //开启外部中断 KEY_EnableIRQ(); { // 关闭广播 uint8_t initialAdvertEnable = FALSE; GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initialAdvertEnable); } Util_stopClock(&periodicClock_10ms); } else if (1 == systemState.keyShortFlag)// 短按松开 产生一次短按完整事件 { //短按事件处理 uartWriteDebug("短按", 4); } } else if (KEY_HIGH == pMsg->GPIOStatus) // 短按 { if (1 == systemState.powerOffFlag) // 等待长按事件 忽略此时的短按事件 { systemState.delayPowerOffTime = 5; // 防止timout 剩2s时又产生长按事件 } else { systemState.keyShortFlag = 1; } } break; default: break; } // Free the space from the message. ICall_free(pMsg); } } #else while (!Queue_empty(keyMsgQueue)) { KEY_stEvt_t *pMsg = (KEY_stEvt_t *)Util_dequeueMsg(keyMsgQueue); if (pMsg) { // Process message. switch(pMsg->GPIOName) { case KEY_NAME_3V3: if (KEY_HIGH == pMsg->GPIOStatus) { wifiPowerOn(); uartWriteDebug("poweron3v3", 10); OLED_ShowString(40,32, "WiCore"); userAppShowCharge(); // 启动广播 { uint8_t initialAdvertEnable = TRUE; GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initialAdvertEnable); } systemState.powerOffFlag = 0; } else { wifiPowerDown(); uartWriteDebug("powerdown3v3", 12); // 清低电闪烁 systemState.lowBatteryFlag = 0; OLED_Clear(); // 这个执行时间较长 打乱了定时周期,所以stopClock是没有用的 // 有链接,关闭 GAPRole_TerminateConnection(); systemState.powerOffFlag = 1; } break; case KEY_POWER: if (KEY_LONG == pMsg->GPIOStatus) { if (1 == systemState.powerOffFlag) { systemState.powerOffFlag = 0; systemState.delayPowerOffTime = 0; systemState.keyUpFlag=0; wifiPowerOn(); userAppShowCharge(); OLED_ShowString(40,32, "WiCore"); // 启动广播 { uint8_t initialAdvertEnable = TRUE; GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initialAdvertEnable); } uartWriteDebug("poweron", 7); } else { //系统断电 systemState.keyUpFlag=0; systemState.powerOffFlag = 1; wifiPowerDown(); uartWriteDebug("powerdown", 9); OLED_Clear(); systemState.lowBatteryFlag = 0; // 清低电闪烁 // 有链接,关闭 GAPRole_TerminateConnection(); } systemState.keyShortFlag = 0; // 忽略短按事件 } else if (KEY_LOW == pMsg->GPIOStatus)// 松开 { if (1 == systemState.keyShortFlag)// 短按松开 产生一次短按完整事件 { //短按事件处理 uartWriteDebug("短按", 4); systemState.keyShortFlag = 0; } } else if (KEY_HIGH == pMsg->GPIOStatus) // 短按 { if (1 == systemState.powerOffFlag) // 等待长按事件 忽略此时的短按事件 { // 关机中 不处理 } else { systemState.keyShortFlag = 1; } } break; default: break; } // Free the space from the message. ICall_free(pMsg); } } #endif }
/********************************************************************* * @fn RunningSensor_taskFxn * * @brief Running Application Task event processor. This function * is called to process all events for the task. Events * include timers, messages and any other user defined events. * * @param a0, a1 - not used. * * @return none */ void RunningSensor_taskFxn(UArg a0, UArg a1) { // Initialize the application. RunningSensor_init(); // Application 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) { if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == selfEntity)) { // Process inter-task message. RunningSensor_processStackMsg((ICall_Hdr *)pMsg); } if (pMsg) { ICall_freeMsg(pMsg); } } // If RTOS queue is not empty, process app message. while (!Queue_empty(appMsgQueue)) { rscEvt_t *pMsg = (rscEvt_t *)Util_dequeueMsg(appMsgQueue); if (pMsg) { // Process message. RunningSensor_processAppMsg(pMsg); // Free the space from the message. ICall_free(pMsg); } } } if (events) { // Running sensor periodic event. if (events & RSC_PERIODIC_EVT) { events &= ~RSC_PERIODIC_EVT; // Perform periodic sensor's periodic task. RunningSensor_periodicTask(); } // Parameter update event. if (events & RSC_CONN_PARAM_UPDATE_EVT) { events &= ~RSC_CONN_PARAM_UPDATE_EVT; // Send param update. If it fails, retry until successful. GAPRole_SendUpdateParam(DEFAULT_DESIRED_MIN_CONN_INTERVAL, DEFAULT_DESIRED_MAX_CONN_INTERVAL, DEFAULT_DESIRED_SLAVE_LATENCY, DEFAULT_DESIRED_CONN_TIMEOUT, GAPROLE_RESEND_PARAM_UPDATE); #if USING_NEGLECT_TIMEOUT // Assuming service discovery complete, start neglect timer. Util_startClock(&neglectClock); #endif //USING_NEGLECT_TIMEOUT } #if USING_NEGLECT_TIMEOUT // Neglect timer expired. if (events & RSC_NEGLECT_TIMEOUT_EVT) { events &= ~RSC_NEGLECT_TIMEOUT_EVT; // No user input, terminate connection. GAPRole_TerminateConnection(); } #endif //USING_NEGLECT_TIMEOUT // Soft reset event. if (events & RSC_RESET_EVT) { events &= ~RSC_RESET_EVT; RunningSensor_handleResetEvt(); } } } }
/********************************************************************* * @fn RunningSensor_ProcessEvent * * @brief Running Application Task event processor. This function * is called to process all events for the task. Events * include timers, messages and any other user defined events. * * @param task_id - The OSAL assigned task ID. * @param events - events to process. This is a bit map and can * contain more than one event. * * @return events not processed */ uint16 RunningSensor_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( sensor_TaskID )) != NULL ) { sensor_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 & START_DEVICE_EVT ) { // Start the Device VOID GAPRole_StartDevice( &runningPeripheralCB ); // Register with bond manager after starting device GAPBondMgr_Register( (gapBondCBs_t *) &runningBondCB ); return ( events ^ START_DEVICE_EVT ); } if ( events & RSC_PERIODIC_EVT ) { // Perform periodic sensor's periodic task sensorPeriodicTask(); return (events ^ RSC_PERIODIC_EVT); } if ( events & RSC_CONN_PARAM_UPDATE_EVT ) { // Send param update. If it fails, retry until successful. GAPRole_SendUpdateParam( DEFAULT_DESIRED_MIN_CONN_INTERVAL, DEFAULT_DESIRED_MAX_CONN_INTERVAL, DEFAULT_DESIRED_SLAVE_LATENCY, DEFAULT_DESIRED_CONN_TIMEOUT, GAPROLE_RESEND_PARAM_UPDATE ); // Assuming service discovery complete, start neglect timer if ( USING_NEGLECT_TIMEOUT ) { osal_start_timerEx( sensor_TaskID, RSC_NEGLECT_TIMEOUT_EVT, NEGLECT_TIMEOUT_DELAY ); } return (events ^ RSC_CONN_PARAM_UPDATE_EVT); } if ( events & RSC_NEGLECT_TIMEOUT_EVT ) { // No user input, terminate connection. GAPRole_TerminateConnection(); return ( events ^ RSC_NEGLECT_TIMEOUT_EVT ); } if ( events & RSC_RESET_EVT ) { if ( gapProfileState == GAPROLE_CONNECTED ) { // Exit the connection GAPRole_TerminateConnection(); // There is no callback for manual termination of the link. change state variable here. gapProfileState = GAPROLE_WAITING; // Set timer to give the end advertising event time to finish osal_start_timerEx( sensor_TaskID, RSC_RESET_EVT, 500 ); } else if ( gapProfileState == GAPROLE_ADVERTISING ) { uint8 value = FALSE; // Turn off advertising GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &value ); // Set timer to give the end advertising event time to finish osal_start_timerEx( sensor_TaskID, RSC_RESET_EVT, 500 ); } else if ( USING_WHITE_LIST == TRUE ) { //temporary variable uint8 value = GAP_FILTER_POLICY_ALL; // Turn off white list filter policy GAPRole_SetParameter(GAPROLE_ADV_FILTER_POLICY, sizeof( uint8 ), &value); sensorUsingWhiteList = FALSE; // Clear the white list HCI_LE_ClearWhiteListCmd(); // Set timer to give the end advertising event time to finish osal_start_timerEx( sensor_TaskID, RSC_RESET_EVT, 500 ); } else if ( (gapProfileState == GAPROLE_STARTED) || (gapProfileState == GAPROLE_WAITING) || (gapProfileState == GAPROLE_WAITING_AFTER_TIMEOUT) ) { uint8 eraseBonds = TRUE; // Erase all bonds GAPBondMgr_SetParameter( GAPBOND_ERASE_ALLBONDS, 0, &eraseBonds ); // Turn on GREEN LED for set time HalLedSet( HAL_LED_1, HAL_LED_MODE_BLINK ); return (events ^ RSC_RESET_EVT); } } // Discard unknown events return 0; }
/* 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 gapRole_ProcessOSALMsg * * @brief Process an incoming task message. * * @param pMsg - message to process * * @return none */ static void gapRole_ProcessOSALMsg( osal_event_hdr_t *pMsg ) { switch ( pMsg->event ) { case HCI_GAP_EVENT_EVENT: if ( pMsg->status == HCI_COMMAND_COMPLETE_EVENT_CODE ) { hciEvt_CmdComplete_t *pPkt = (hciEvt_CmdComplete_t *)pMsg; if ( pPkt->cmdOpcode == HCI_READ_RSSI ) { int8 rssi = (int8)pPkt->pReturnParam[3]; if ( (gapRole_state == GAPROLE_CONNECTED) && (rssi != RSSI_NOT_AVAILABLE) ) { // Report RSSI to app if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnRssiRead ) { pGapRoles_AppCGs->pfnRssiRead( rssi ); } } } } break; case GAP_MSG_EVENT: gapRole_ProcessGAPMsg( (gapEventHdr_t *)pMsg ); break; case L2CAP_SIGNAL_EVENT: { l2capSignalEvent_t *pPkt = (l2capSignalEvent_t *)pMsg; // Process the Parameter Update Response if ( pPkt->opcode == L2CAP_PARAM_UPDATE_RSP ) { l2capParamUpdateRsp_t *pRsp = (l2capParamUpdateRsp_t *)&(pPkt->cmd.updateRsp); if ( ( pRsp->result == L2CAP_CONN_PARAMS_REJECTED ) && ( paramUpdateNoSuccessOption == GAPROLE_TERMINATE_LINK ) ) { // Cancel connection param update timeout timer VOID osal_stop_timerEx( gapRole_TaskID, CONN_PARAM_TIMEOUT_EVT ); // Terminate connection immediately GAPRole_TerminateConnection(); } else { uint16 timeout = GAP_GetParamValue( TGAP_CONN_PARAM_TIMEOUT ); // Let's wait for Controller to update connection parameters if they're // accepted. Otherwise, decide what to do based on no success option. VOID osal_start_timerEx( gapRole_TaskID, CONN_PARAM_TIMEOUT_EVT, timeout ); } } } break; default: break; } }
/********************************************************************* * @fn timeApp_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 timeApp_HandleKeys( uint8 shift, uint8 keys ) { if ( keys & HAL_KEY_UP ) { // Start or stop advertising if ( timeAppGapState != GAPROLE_CONNECTED ) { uint8 advState; // Set fast advertising interval for user-initiated connections GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_FAST_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_FAST_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_FAST_ADV_DURATION ); // Toggle advertising state GAPRole_GetParameter( GAPROLE_ADVERT_ENABLED, &advState ); advState = !advState; GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advState ); // Set state variable if (advState == FALSE) { timeAppAdvCancelled = TRUE; } } } if ( keys & HAL_KEY_LEFT ) { attWriteReq_t req; // Send command to alert notificaton control point if ( ( timeAppGapState == GAPROLE_CONNECTED ) && ( timeAppHdlCache[HDL_ALERT_NTF_CTRL] != 0 ) ) { // Send write request req.len = 2; req.value[0] = *pTimeAppAlertCmd; req.value[1] = ALERT_NOTIF_CAT_ALL; req.sig = 0; req.cmd = 0; req.handle = timeAppHdlCache[HDL_ALERT_NTF_CTRL]; GATT_WriteCharValue( timeAppConnHandle, &req, timeAppTaskId ); LCD_WRITE_STRING_VALUE( "Alert cmd:", *pTimeAppAlertCmd, 10, HAL_LCD_LINE_1); } // Cycle through command test values if ( *pTimeAppAlertCmd == ALERT_NOTIF_DISABLE_UNREAD ) { pTimeAppAlertCmd = timeAppAlertCmd; } else { pTimeAppAlertCmd++; } } if ( keys & HAL_KEY_RIGHT ) { attWriteReq_t req; // Do a reference time update if ( ( timeAppGapState == GAPROLE_CONNECTED ) && ( timeAppHdlCache[HDL_REF_TIME_UPD_CTRL] != 0 ) ) { // Send write command req.len = 1; req.value[0] = timeAppRefUpdateVal; req.sig = 0; req.cmd = 1; req.handle = timeAppHdlCache[HDL_REF_TIME_UPD_CTRL]; GATT_WriteNoRsp( timeAppConnHandle, &req ); LCD_WRITE_STRING_VALUE( "Time update:", timeAppRefUpdateVal, 10, HAL_LCD_LINE_1); // Toggle between two reference time update values if ( timeAppRefUpdateVal == REF_TIME_UPDATE_GET ) { timeAppRefUpdateVal = REF_TIME_UPDATE_CANCEL; } else { timeAppRefUpdateVal = REF_TIME_UPDATE_GET; } } } if ( keys & HAL_KEY_CENTER ) { // If connected, terminate connection if ( timeAppGapState == GAPROLE_CONNECTED ) { GAPRole_TerminateConnection(); } } if ( keys & HAL_KEY_DOWN ) { attWriteReq_t req; // Write ringer control point if ( ( timeAppGapState == GAPROLE_CONNECTED ) && ( timeAppHdlCache[HDL_PAS_CTRL] != 0 ) ) { // Send write command req.len = 1; req.value[0] = timeAppRingerCmd; req.sig = 0; req.cmd = 1; req.handle = timeAppHdlCache[HDL_PAS_CTRL]; GATT_WriteNoRsp( timeAppConnHandle, &req ); LCD_WRITE_STRING_VALUE( "Ringer ctrl:", timeAppRingerCmd, 10, HAL_LCD_LINE_1); // Toggle between values if ( ++timeAppRingerCmd > RINGER_CANCEL_SILENT ) { timeAppRingerCmd = RINGER_SILENT_MODE; } } } if ( keys & HAL_KEY_SW_6 ) { } }
/********************************************************************* * @fn simpleTopology_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 simpleTopology_handleKeys(uint8_t shift, uint8_t keys) { (void)shift; // Intentionally unreferenced parameter if (LCDmenu == MAIN_MENU) { if (keys & KEY_LEFT) //show discovery results { selectKey = DISCOVERED_DEVICES; // If discovery has occurred and a device was found if (!scanningStarted && scanRes > 0) { // Increment index of current result (with wraparound) scanIdx++; if (scanIdx >= scanRes) { scanIdx = 0; } LCD_WRITE_STRING_VALUE("Device", (scanIdx + 1), 10, LCD_PAGE3); LCD_WRITE_STRING(Util_convertBdAddr2Str(devList[scanIdx].addr), LCD_PAGE4); } return; } if (keys & KEY_UP) //Scan for devices { // Start or stop discovery if (gapRoleNumLinks(GAPROLE_AVAILABLE_LINKS) > 0) //if we can connect to another device { if (!scanningStarted) //if we're not already scanning { scanningStarted = TRUE; scanRes = 0; LCD_WRITE_STRING("Discovering...", LCD_PAGE3); LCD_WRITE_STRING("", LCD_PAGE4); LCD_WRITE_STRING("", LCD_PAGE6); GAPRole_StartDiscovery(DEFAULT_DISCOVERY_MODE, DEFAULT_DISCOVERY_ACTIVE_SCAN, DEFAULT_DISCOVERY_WHITE_LIST); } else //cancel scanning { LCD_WRITE_STRING("Discovery Cancelled", LCD_PAGE3); GAPRole_CancelDiscovery(); scanningStarted = FALSE; } } else // can't add more links at this time { LCD_WRITE_STRING("Can't scan:no links ", LCD_PAGE3); } return; } if (keys & KEY_RIGHT) // turn advertising on / off { uint8_t adv; uint8_t adv_status; GAPRole_GetParameter(GAPROLE_ADVERT_ENABLED, &adv_status, NULL); if (adv_status) //turn off { adv = FALSE; GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &adv, NULL); } else //turn on { adv = TRUE; GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &adv, NULL); } return; } if (keys & KEY_SELECT) //connect to a discovered device { if (selectKey == DISCOVERED_DEVICES) // connect to a device { uint8_t addrType; uint8_t *peerAddr; if (connecting_state == 1) // if already attempting to connect, cancel connection { GAPRole_TerminateConnection(0xFFFE); LCD_WRITE_STRING("Connecting stopped.", LCD_PAGE3); connecting_state = 0; } else //establish new connection { // if there is a scan result if (scanRes > 0) { // connect to current device in scan result peerAddr = devList[scanIdx].addr; addrType = devList[scanIdx].addrType; GAPRole_EstablishLink(DEFAULT_LINK_HIGH_DUTY_CYCLE, DEFAULT_LINK_WHITE_LIST, addrType, peerAddr); connecting_state = 1; LCD_WRITE_STRING("Connecting", LCD_PAGE3); LCD_WRITE_STRING(Util_convertBdAddr2Str(peerAddr), LCD_PAGE4); } } } else if (selectKey == CONNECTED_DEVICES) //enter the device menu { if (multiConnInfo[connIdx].gapRole_ConnectionHandle != INVALID_CONNHANDLE) { LCDmenu = DEVICE_MENU; LCD_WRITE_STRING("Device Menu", LCD_PAGE3); LCD_WRITE_STRING(Util_convertBdAddr2Str(multiConnInfo[connIdx].gapRole_devAddr), LCD_PAGE4); if (multiConnInfo[connIdx].gapRole_ConnRole == GAP_PROFILE_CENTRAL) { LCD_WRITE_STRING("Connected as Central", LCD_PAGE5); LCD_WRITE_STRING("", LCD_PAGE6); LCD_WRITE_STRING("", LCD_PAGE7); } else //PERIPHERAL { LCD_WRITE_STRING("Connected as Periph", LCD_PAGE5); LCD_WRITE_STRING("", LCD_PAGE6); LCD_WRITE_STRING("", LCD_PAGE7); } //use this connection for all functionality connHandle = multiConnInfo[connIdx].gapRole_ConnectionHandle; } else // no active connection here LCD_WRITE_STRING("No Connection here.", LCD_PAGE3); } return; } if (keys & KEY_DOWN) //browse connected devices { LCD_WRITE_STRING("Connected Device:", LCD_PAGE3); if (++connIdx >= MAX_NUM_BLE_CONNS) //increment connIdx { connIdx = 0; } if (multiConnInfo[connIdx].gapRole_ConnectionHandle != INVALID_CONNHANDLE) //if there is a connection at this index { LCD_WRITE_STRING(Util_convertBdAddr2Str(multiConnInfo[connIdx].gapRole_devAddr), LCD_PAGE4); } else { LCD_WRITE_STRING("N/A", LCD_PAGE4); } selectKey = CONNECTED_DEVICES; } return; } else if (LCDmenu == DEVICE_MENU) { if (keys & KEY_UP) //read/whrite char { if (charHdl[connIdx] != 0) { uint8_t status; // Do a read or write as long as no other read or write is in progress if (doWrite) { // Do a write attWriteReq_t req; req.pValue = GATT_bm_alloc(connHandle, ATT_WRITE_REQ, 1, NULL); if ( req.pValue != NULL ) { req.handle = charHdl[connIdx]; req.len = 1; req.pValue[0] = charVal; req.sig = 0; req.cmd = 0; status = GATT_WriteCharValue(connHandle, &req, selfEntity); if ( status != SUCCESS ) { GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ); } } } else { // Do a read attReadReq_t req; req.handle = charHdl[connIdx]; status = GATT_ReadCharValue(connHandle, &req, selfEntity); } if (status == SUCCESS) { doWrite = !doWrite; } } return; } if (keys & KEY_RIGHT) //connection update...eventually { asm("NOP"); return; } if (keys & KEY_SELECT) { GAPRole_TerminateConnection(connHandle); LCD_WRITE_STRING("Disconnecting", LCD_PAGE5); LCD_WRITE_STRING("", LCD_PAGE6); return; } if (keys & KEY_DOWN) //back to main menu { LCDmenu = MAIN_MENU; LCD_WRITE_STRING("Main Menu", LCD_PAGE3); //clear screen LCD_WRITE_STRING("", LCD_PAGE4); LCD_WRITE_STRING("", LCD_PAGE5); LCD_WRITE_STRING("", LCD_PAGE6); LCD_WRITE_STRING("", LCD_PAGE7); LCD_WRITE_STRING_VALUE("Connected to ", gapRoleNumLinks(GAPROLE_ACTIVE_LINKS) ,10, LCD_PAGE0); connIdx = 0; return; } } }
/********************************************************************* * @fn HidDev_ProcessEvent * * @brief Hid Dev Task event processor. This function * is called to process all events for the task. Events * include timers, messages and any other user defined events. * * @param task_id - The OSAL assigned task ID. * @param events - events to process. This is a bit map and can * contain more than one event. * * @return events not processed */ uint16 HidDev_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( hidDevTaskId )) != NULL ) { hidDev_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 & START_DEVICE_EVT ) { // Start the Device VOID GAPRole_StartDevice( &hidDev_PeripheralCBs ); // Register with bond manager after starting device GAPBondMgr_Register( (gapBondCBs_t *) &hidDevBondCB ); return ( events ^ START_DEVICE_EVT ); } if ( events & HID_IDLE_EVT ) { if ( hidDevGapState == GAPROLE_CONNECTED ) { // if pairing in progress then restart timer if ( hidDevPairingStarted ) { hidDevStartIdleTimer(); } // else disconnect else { GAPRole_TerminateConnection(); } } return ( events ^ HID_IDLE_EVT ); } if ( events & BATT_PERIODIC_EVT ) { // Perform periodic battery task hidDevBattPeriodicTask(); return ( events ^ BATT_PERIODIC_EVT ); } if ( events & HID_SEND_REPORT_EVT ) { // if connection is secure if ( hidDevConnSecure ) { hidDevReport_t *pReport = hidDevDequeueReport(); if ( pReport != NULL ) { // Send report hidDevSendReport( pReport->id, pReport->type, pReport->len, pReport->data ); } return ( reportQEmpty() ? events ^ HID_SEND_REPORT_EVT : events ); } return ( events ^ HID_SEND_REPORT_EVT ); } return 0; }