/********************************************************************* * @fn Time_indGattMsg * * @brief Handle indications and notifications. * * @param pMsg - GATT message. * * @return none */ void Time_indGattMsg(gattMsgEvent_t *pMsg) { uint8_t i; // Look up the handle in the handle cache for (i = 0; i < HDL_CACHE_LEN; i++) { if (pMsg->msg.handleValueNoti.handle == Time_handleCache[i]) { break; } } // Perform processing for this handle switch (i) { case HDL_CURR_TIME_CT_TIME_START: // Set clock to time read from time server Time_clockSet(pMsg->msg.handleValueNoti.pValue); break; default: break; } // Send confirm for indication if (pMsg->method == ATT_HANDLE_VALUE_IND) { ATT_HandleValueCfm(pMsg->connHandle); } }
/********************************************************************* * @fn timeAppIndGattMsg * * @brief Handle indications and notifications. * * @param pMsg - GATT message. * * @return none */ void timeAppIndGattMsg( gattMsgEvent_t *pMsg ) { uint8 i; // Look up the handle in the handle cache for ( i = 0; i < HDL_CACHE_LEN; i++ ) { if ( pMsg->msg.handleValueNoti.handle == timeAppHdlCache[i] ) { break; } } // Perform processing for this handle switch ( i ) { case HDL_CURR_TIME_CT_TIME_START: // Set clock to time read from time server timeAppClockSet( pMsg->msg.handleValueNoti.pValue ); break; case HDL_NWA_NWA_START: // Display network availability state if ( pMsg->msg.handleValueInd.pValue[0] == 1 ) { LCD_WRITE_STRING( "Network: Yes", HAL_LCD_LINE_1 ); } else { LCD_WRITE_STRING( "Network: None", HAL_LCD_LINE_1 ); } break; case HDL_ALERT_NTF_UNREAD_START: // Display unread message alert { uint8 *p = pMsg->msg.handleValueNoti.pValue; uint8 len = pMsg->msg.handleValueNoti.len; if ( p[0] <= ALERT_CAT_ID_MAX && len == 2 ) { LCD_WRITE_STRING_VALUE( (char *) timeAppAlertCatStr[p[0]], p[1], 10, HAL_LCD_LINE_1 ); LCD_WRITE_STRING( "", HAL_LCD_LINE_2 ); } } break; case HDL_ALERT_NTF_NEW_START: // Display incoming message timeAppDisplayAlert( pMsg->msg.handleValueNoti.pValue, pMsg->msg.handleValueNoti.len ); break; case HDL_BATT_LEVEL_START: // Display battery level LCD_WRITE_STRING_VALUE( "Battery%", pMsg->msg.handleValueNoti.pValue[0], 10, HAL_LCD_LINE_2 ); break; case HDL_PAS_ALERT_START: // Display phone alert status LCD_WRITE_STRING_VALUE( "Phone Alert:", pMsg->msg.handleValueNoti.pValue[0], 16, HAL_LCD_LINE_1 ); break; case HDL_PAS_RINGER_START: // Display ringer state if ( pMsg->msg.handleValueNoti.pValue[0] == 0 ) { LCD_WRITE_STRING( "Ringer Off", HAL_LCD_LINE_2 ); } else { LCD_WRITE_STRING( "Ringer On", HAL_LCD_LINE_2 ); } break; default: break; } // Send confirm for indication if ( pMsg->method == ATT_HANDLE_VALUE_IND ) { ATT_HandleValueCfm( pMsg->connHandle ); } }
static void hidappProcessGATTMsg( gattMsgEvent_t *pPkt ) { // Build the message first switch ( pPkt->method ) { case ATT_HANDLE_VALUE_NOTI: // First try to send out pending HID report if ( reportRetries > 0 ) { hidappSendInReport( &lastInReport ); reportRetries = 0; osal_stop_timerEx( hidappTaskId, HIDAPP_EVT_REPORT_RETRY ); } // Send incoming HID report if ( hidappSendInReport( &(pPkt->msg.handleValueNoti) ) == FALSE ) { // Save report for retries later osal_memcpy( &lastInReport, &(pPkt->msg.handleValueNoti), sizeof( attHandleValueNoti_t ) ); reportRetries = 1; osal_start_timerEx( hidappTaskId, HIDAPP_EVT_REPORT_RETRY, HIDAPP_INPUT_RETRY_TIMEOUT ); } break; case ATT_FIND_BY_TYPE_VALUE_RSP: // Response from GATT_DiscPrimaryServiceByUUID // Service found, store handles if ( pPkt->msg.findByTypeValueRsp.numInfo > 0 ) { serviceStartHandle = pPkt->msg.findByTypeValueRsp.handlesInfo[0].handle; serviceEndHandle = pPkt->msg.findByTypeValueRsp.handlesInfo[0].grpEndHandle; } // If procedure complete else if ( pPkt->hdr.status == bleProcedureComplete ) { if ( serviceStartHandle != 0 ) { if ( serviceToDiscover == GATT_SERVICE_UUID ) { // Begin the search for characteristic handle of the service readReq.startHandle = serviceStartHandle; readReq.endHandle = serviceEndHandle; readReqType.len = 2; readReqType.uuid[0] = LO_UINT16(SERVICE_CHANGED_UUID); readReqType.uuid[1] = HI_UINT16(SERVICE_CHANGED_UUID); readReq.type = readReqType; GATT_DiscCharsByUUID(connHandle, &readReq, hidappTaskId ); } else if ( serviceToDiscover == HID_SERVICE_UUID ) { // Discover all characteristics GATT_DiscAllChars( connHandle, serviceStartHandle, serviceEndHandle, hidappTaskId ); } } } break; case ATT_READ_BY_TYPE_RSP: // Response from Discover all Characteristics. // Success indicates packet with characteristic discoveries. if ( pPkt->hdr.status == SUCCESS ) { attReadByTypeRsp_t rsp = pPkt->msg.readByTypeRsp; uint8 idx = 0; if ( serviceToDiscover == GATT_SERVICE_UUID ) { // We have discovered the GATT Service Characteristic handle uint8 low = LO_UINT16(pPkt->msg.readByTypeRsp.dataList[3]); uint8 high = HI_UINT16(pPkt->msg.readByTypeRsp.dataList[4]); serviceChangeHandle = BUILD_UINT16(low, high); // Break to skip next part, it doesn't apply here break; } // Search characteristics for those with notification permissions. while( idx < ((rsp.numPairs * rsp.len ) - 1)) { // Check permissions of characteristic for notification permission if ( (rsp.dataList[idx+2] & GATT_PROP_NOTIFY ) ) { uint16* pHandle = (mouseCharHandle == GATT_INVALID_HANDLE) ? &mouseCharHandle : &keyCharHandle ; if ( pHandle == &keyCharHandle && consumerCtrlCharHandle == GATT_INVALID_HANDLE ) { pHandle = ( keyCharHandle == GATT_INVALID_HANDLE ) ? &keyCharHandle : &consumerCtrlCharHandle; } if ( *pHandle == GATT_INVALID_HANDLE ) { *pHandle = BUILD_UINT16( rsp.dataList[idx+3], rsp.dataList[idx+4] ); } } idx += rsp.len; } } // This indicates that there is no more characteristic data // to be discovered within the given handle range. else if ( pPkt->hdr.status == bleProcedureComplete ) { if ( serviceToDiscover == GATT_SERVICE_UUID ) { // Begin Service Discovery of HID Service serviceToDiscover = HID_SERVICE_UUID; hidappDiscoverService( connHandle, HID_SERVICE_UUID ); // Break to skip next part, it doesn't apply yet. break; } if ( enableCCCDs == TRUE ) { mouseCCCHandle = mouseCharHandle + 1; // Begin configuring the characteristics for notifications hidappEnableNotification( connHandle, mouseCCCHandle ); } else { serviceDiscComplete = TRUE; } } break; case ATT_WRITE_RSP: if ( pPkt->hdr.status == SUCCESS && !serviceDiscComplete ) { uint16 handle = ( keyCCCHandle == GATT_INVALID_HANDLE ) ? ( keyCCCHandle = keyCharHandle + 1 ) : ( consumerCtrlCCCHandle = consumerCtrlCharHandle + 1 ); hidappEnableNotification( connHandle, handle ); if ( consumerCtrlCCCHandle != GATT_INVALID_HANDLE) { serviceDiscComplete = TRUE; } } break; // Service Change indication case ATT_HANDLE_VALUE_IND: // Note: this logic assumes that the only indications that will be sent // will come from that GATT Service Changed Characteristic if ( pPkt->hdr.status == SUCCESS ) { serviceChange = CHANGE_OCCURED; // Acknowledge receipt of indication ATT_HandleValueCfm( pPkt->connHandle ); // Handles in server have changed while devices are connected if ( ( gapBondMgrState == PAIRED_BONDED_STATE ) && ( serviceChangeHandle == pPkt->msg.handleValueInd.handle ) ) { // Begin Service Discovery of HID Service serviceToDiscover = HID_SERVICE_UUID; hidappDiscoverService( connHandle, HID_SERVICE_UUID ); serviceChange = NO_CHANGE; } } break; default: // Unknown event break; } }
/********************************************************************* * @fn timeAppIndGattMsg * * @brief Handle indications and notifications. * * @param pMsg - GATT message. * * @return none */ void timeAppIndGattMsg( gattMsgEvent_t *pMsg ) { uint8 i; // Look up the handle in the handle cache for ( i = 0; i < HDL_CACHE_LEN; i++ ) { if ( pMsg->msg.handleValueNoti.handle == timeAppHdlCache[i] ) { break; } } // Perform processing for this handle switch ( i ) { case HDL_CURR_TIME_CT_TIME_START: // Set clock to time read from time server timeAppClockSet( pMsg->msg.handleValueNoti.value ); break; case HDL_NWA_NWA_START: // Display network availability state if ( pMsg->msg.handleValueInd.value[0] == 1 ) { LCD_WRITE_STRING( "Network: Yes", HAL_LCD_LINE_1 ); } else { LCD_WRITE_STRING( "Network: None", HAL_LCD_LINE_1 ); } break; case HDL_ALERT_NTF_UNREAD_START: // Display unread message alerts { uint8 *p = pMsg->msg.handleValueNoti.value; uint8 len = pMsg->msg.handleValueNoti.len; uint8 line; for ( line = 1; line <= 2 && len >= 2; line++, len -= 2 ) { if ( ALERT_MAJOR_CAT(p[0]) <= ALERT_CAT_ID_MAX ) { LCD_WRITE_STRING_VALUE( (char *) timeAppAlertCatStr[ALERT_MAJOR_CAT(p[0])], p[1], 10, line ); } p += 2; } } break; case HDL_ALERT_NTF_INCOM_START: // Display incoming message timeAppDisplayAlert( pMsg->msg.handleValueNoti.value, pMsg->msg.handleValueNoti.len ); break; case HDL_BATT_LEVEL_STATE_START: // Display battery level LCD_WRITE_STRING_VALUE( "Battery%", pMsg->msg.handleValueNoti.value[0], 10, HAL_LCD_LINE_2 ); break; default: break; } // Send confirm for indication if ( pMsg->method == ATT_HANDLE_VALUE_IND ) { ATT_HandleValueCfm( pMsg->connHandle ); } }
/********************************************************************* * @fn glucoseIndGattMsg * * @brief Handle indications and notifications. * * @param pMsg - GATT message. * * @return none */ void glucoseIndGattMsg( gattMsgEvent_t *pMsg ) { uint8 i; // Look up the handle in the handle cache for ( i = 0; i < HDL_CACHE_LEN; i++ ) { if ( pMsg->msg.handleValueInd.handle == glucoseHdlCache[i] ) { break; } } // Perform processing for this handle switch ( i ) { case HDL_GLUCOSE_START: { uint8* p = pMsg->msg.handleValueNoti.value; // restart procedure timer if (glucCollWritePending == true) { osal_start_timerEx( glucCollTaskId, PROCEDURE_TIMEOUT_EVT, GLUCOSE_PROCEDURE_TIMEOUT ); } memset(&glucoseMeas, 0, sizeof(glucoseMeas)); // Flags glucoseMeas.flags = *p++; // Sequence number glucoseMeas.seqNum = BUILD_UINT16(p[0], p[1]); LCD_WRITE_STRING_VALUE( "SeqNum:", glucoseMeas.seqNum, 10, HAL_LCD_LINE_1 ); p += 2; // Base time memcpy(glucoseMeas.baseTime, p, 7); p += 7; // Time offset; if (glucoseMeas.flags & GLUCOSE_MEAS_FLAG_TIME_OFFSET) { glucoseMeas.timeOffset = BUILD_UINT16(p[0], p[1]); p += 2; } // Glucose concentration if(glucoseMeas.flags & GLUCOSE_MEAS_FLAG_CONCENTRATION) { glucoseMeas.concentration = BUILD_UINT16(p[0], p[1]); if(glucoseMeas.flags & GLUCOSE_MEAS_FLAG_UNITS) LCD_WRITE_STRING_VALUE( STR_MMOL_PER_L, glucoseMeas.concentration, 10, HAL_LCD_LINE_2 ); else LCD_WRITE_STRING_VALUE( STR_MG_PER_DL, glucoseMeas.concentration, 10, HAL_LCD_LINE_2 ); p += 2; // Type sample location glucoseMeas.typeSampleLocation = *p++; } // Sensor status annunciation if (glucoseMeas.flags & GLUCOSE_MEAS_FLAG_STATUS_ANNUNCIATION) { glucoseMeas.sensorStatus = BUILD_UINT16(p[0], p[1]); p += 2; } } break; case HDL_GLUCOSE_CONTEXT_START: { uint8* p = pMsg->msg.handleValueNoti.value; // restart procedure timer if (glucCollWritePending == true) { osal_start_timerEx( glucCollTaskId, PROCEDURE_TIMEOUT_EVT, GLUCOSE_PROCEDURE_TIMEOUT ); } memset(&glucoseContext, 0, sizeof(glucoseContext)); // Flags glucoseContext.flags = *p++; // Sequence number glucoseContext.seqNum = BUILD_UINT16(p[0], p[1]); p += 2; // Extended flags if(glucoseContext.flags & GLUCOSE_CONTEXT_FLAG_EXTENDED) { glucoseContext.extendedFlags = *p++; } // Carbohydrate if(glucoseContext.flags & GLUCOSE_CONTEXT_FLAG_CARBO) { // carbohydrate ID glucoseContext.carboId = *p++; // Carbohydrate glucoseContext.carboVal = BUILD_UINT16(p[0], p[1]); p += 2; } // Meal if(glucoseContext.flags & GLUCOSE_CONTEXT_FLAG_MEAL) { glucoseContext.mealVal = *p++; } // Tester health if(glucoseContext.flags & GLUCOSE_CONTEXT_FLAG_TESTER_HEALTH) { glucoseContext.TesterHealthVal = *p++; } // Exercise if(glucoseContext.flags & GLUCOSE_CONTEXT_FLAG_EXERCISE) { // Duration glucoseContext.exerciseDuration = BUILD_UINT16(p[0], p[1]); p += 2; // Intensity glucoseContext.exerciseIntensity = *p++; } // Medication if(glucoseContext.flags & GLUCOSE_CONTEXT_FLAG_MEDICATION) { // Medication ID glucoseContext.medId = *p++; // Medication glucoseContext.medVal = BUILD_UINT16(p[0], p[1]); p += 2; } // HbA1c if(glucoseContext.flags & GLUCOSE_CONTEXT_FLAG_HbA1c) { glucoseContext.HbA1cVal = BUILD_UINT16(p[0], p[1]); LCD_WRITE_STRING_VALUE( "HbA1c:", glucoseContext.HbA1cVal, 10, HAL_LCD_LINE_3 ); p += 2; } } break; case HDL_GLUCOSE_CTL_PNT_START: { uint8* pValue = pMsg->msg.handleValueInd.value; // stop procedure timer osal_stop_timerEx( glucCollTaskId, PROCEDURE_TIMEOUT_EVT ); if(pValue[0] == CTL_PNT_OP_NUM_RSP) { if(pMsg->msg.handleValueInd.len >= 3) { LCD_WRITE_STRING("Matching ", HAL_LCD_LINE_1); LCD_WRITE_STRING( "Records:", HAL_LCD_LINE_2 ); LCD_WRITE_STRING_VALUE("", BUILD_UINT16(pValue[2], pValue[3]), 10, HAL_LCD_LINE_3 ); } } else if(pValue[0] == CTL_PNT_OP_REQ_RSP && glucCollClearPending) { glucCollClearPending = false; if(pMsg->msg.handleValueInd.len >= 3) { switch(pValue[3]) { case CTL_PNT_RSP_SUCCESS: LCD_WRITE_STRING("Records", HAL_LCD_LINE_1); LCD_WRITE_STRING("Cleared", HAL_LCD_LINE_2 ); LCD_WRITE_STRING("", HAL_LCD_LINE_3 ); break; case CTL_PNT_RSP_NO_RECORDS: LCD_WRITE_STRING("No Matching", HAL_LCD_LINE_1); LCD_WRITE_STRING("Records", HAL_LCD_LINE_2 ); LCD_WRITE_STRING("to Delete", HAL_LCD_LINE_3 ); break; default: LCD_WRITE_STRING("Error:", HAL_LCD_LINE_1); LCD_WRITE_STRING_VALUE("", pValue[3], 10, HAL_LCD_LINE_2 ); LCD_WRITE_STRING( "", HAL_LCD_LINE_3 ); break; } } } else if(pValue[0] == CTL_PNT_OP_REQ_RSP) { if(pMsg->msg.handleValueInd.len >= 3) { switch(pValue[3]) { case CTL_PNT_RSP_SUCCESS: break; case CTL_PNT_RSP_NO_RECORDS: LCD_WRITE_STRING("No Matching", HAL_LCD_LINE_1); LCD_WRITE_STRING("Records", HAL_LCD_LINE_2 ); LCD_WRITE_STRING("Found", HAL_LCD_LINE_3 ); break; default: LCD_WRITE_STRING("Error:", HAL_LCD_LINE_1); LCD_WRITE_STRING_VALUE("", pValue[3], 10, HAL_LCD_LINE_2 ); LCD_WRITE_STRING( "", HAL_LCD_LINE_3 ); break; } } } } break; default: break; } // Send confirm for indication if ( pMsg->method == ATT_HANDLE_VALUE_IND ) { ATT_HandleValueCfm( pMsg->connHandle ); } }