/********************************************************************* * @fn OADTarget_getNextBlockReq * * @brief Process the Request for next image block. * * @param connHandle - connection message was received on * @param blkNum - block number to request from OAD Manager. * * @return None */ static void OADTarget_getNextBlockReq(uint16_t connHandle, uint16_t blkNum) { uint16_t value = GATTServApp_ReadCharCfg(connHandle, oadImgBlockConfig); // If notifications enabled if (value & GATT_CLIENT_CFG_NOTIFY) { attHandleValueNoti_t noti; noti.pValue = GATT_bm_alloc(connHandle, ATT_HANDLE_VALUE_NOTI, 2, NULL); if (noti.pValue != NULL) { gattAttribute_t *pAttr = GATTServApp_FindAttr(oadAttrTbl, GATT_NUM_ATTRS(oadAttrTbl), oadCharVals+OAD_CHAR_IMG_BLOCK); noti.handle = pAttr->handle; noti.len = 2; noti.pValue[0] = LO_UINT16(blkNum); noti.pValue[1] = HI_UINT16(blkNum); if (GATT_Notification(connHandle, ¬i, FALSE) != SUCCESS) { GATT_bm_free((gattMsg_t *)¬i, ATT_HANDLE_VALUE_NOTI); } } } }
/********************************************************************* * @fn OADTarget_rejectImage * * @brief Reject the Image identified by the OAD manager, send back * active image version, length and UID to manager. * * @param connHandle - connection message was received on. * @param pImgHdr - pointer to the img_hdr_t data to send. * * @return None. */ static void OADTarget_rejectImage(uint16_t connHandle, img_hdr_t *pImgHdr) { uint16_t value = GATTServApp_ReadCharCfg(connHandle, oadImgIdentifyConfig); // If notifications enabled if (value & GATT_CLIENT_CFG_NOTIFY) { attHandleValueNoti_t noti; noti.pValue = GATT_bm_alloc(connHandle, ATT_HANDLE_VALUE_NOTI, 8, NULL); if (noti.pValue != NULL) { gattAttribute_t *pAttr = GATTServApp_FindAttr(oadAttrTbl, GATT_NUM_ATTRS(oadAttrTbl), oadCharVals+OAD_CHAR_IMG_IDENTIFY); noti.handle = pAttr->handle; noti.len = OAD_IMG_HDR_SIZE; noti.pValue[0] = LO_UINT16(pImgHdr->ver); noti.pValue[1] = HI_UINT16(pImgHdr->ver); noti.pValue[2] = LO_UINT16(pImgHdr->len); noti.pValue[3] = HI_UINT16(pImgHdr->len); (void)memcpy(noti.pValue+4, pImgHdr->uid, sizeof(pImgHdr->uid)); if (GATT_Notification(connHandle, ¬i, FALSE) != SUCCESS) { GATT_bm_free((gattMsg_t *)¬i, ATT_HANDLE_VALUE_NOTI); } } } }
/********************************************************************* * @fn battNotifyCB * * @brief Send a notification of the level state characteristic. * * @param connHandle - linkDB item * * @return None. */ static void battNotifyCB( linkDBItem_t *pLinkItem ) { if ( pLinkItem->stateFlags & LINK_CONNECTED ) { uint16 value = GATTServApp_ReadCharCfg( pLinkItem->connectionHandle, battLevelClientCharCfg ); if ( value & GATT_CLIENT_CFG_NOTIFY ) { attHandleValueNoti_t noti; noti.pValue = GATT_bm_alloc( pLinkItem->connectionHandle, ATT_HANDLE_VALUE_NOTI, BATT_LEVEL_VALUE_LEN, NULL ); if ( noti.pValue != NULL ) { noti.handle = battAttrTbl[BATT_LEVEL_VALUE_IDX].handle; noti.len = BATT_LEVEL_VALUE_LEN; noti.pValue[0] = battLevel; if ( GATT_Notification( pLinkItem->connectionHandle, ¬i, FALSE ) != SUCCESS ) { GATT_bm_free( (gattMsg_t *)¬i, ATT_HANDLE_VALUE_NOTI ); } } } } }
/********************************************************************* * @fn ScanParam_RefreshNotify * * @brief Notify the peer to refresh the scan parameters. * * @param connHandle - connection handle * * @return None */ void ScanParam_RefreshNotify( uint16 connHandle ) { uint16 value; value = GATTServApp_ReadCharCfg( connHandle, scanParamRefreshClientCharCfg ); if ( value & GATT_CLIENT_CFG_NOTIFY ) { attHandleValueNoti_t noti; noti.pValue = GATT_bm_alloc( connHandle, ATT_HANDLE_VALUE_NOTI, SCAN_PARAM_REFRESH_LEN, NULL ); if (noti.pValue != NULL) { // send notification noti.handle = scanParamAttrTbl[SCAN_PARAM_REFRESH_CCCD_IDX].handle; noti.len = SCAN_PARAM_REFRESH_LEN; noti.pValue[0] = SCAN_PARAM_REFRESH_REQ; if ( GATT_Notification( connHandle, ¬i, FALSE ) != SUCCESS ) { GATT_bm_free( (gattMsg_t *)¬i, ATT_HANDLE_VALUE_NOTI ); } } } }
// Callback function invoked by app logic // to notify temperature update void Temp_NotifyTemperature(uint16 connHandle, struct temp *tBuf) { attHandleValueNoti_t tempNotify; uint16 value = GATTServApp_ReadCharCfg(connHandle, valueConfigCoordinates); tempNotify.handle = tempAttrTbl[2].handle; tempNotify.len = sizeof(struct temp); VOID osal_memcpy((uint8 *)&(tempNotify.value[0]), (uint8 *)tBuf, sizeof(struct temp)); if (value & GATT_CLIENT_CFG_NOTIFY) { GATT_Notification(connHandle, &tempNotify, FALSE ); } }
void ECG_Notify(uint16 connHandle, uint8 *ptr) { attHandleValueNoti_t ecgNotify; uint16 value = GATTServApp_ReadCharCfg(connHandle, valueConfigCoordinates); ecgNotify.handle = ecgAttrTbl[4].handle; ecgNotify.len = ECG_NOTIFY_BUFFER_SIZE; VOID osal_memcpy((uint8 *)&(ecgNotify.value[0]), ptr, ECG_NOTIFY_BUFFER_SIZE); if (value & GATT_CLIENT_CFG_NOTIFY) { GATT_Notification(connHandle, &ecgNotify, FALSE ); } }
/** * @fn battNotifyCB * * @brief Send a notification of the level state characteristic. * * @param connHandle - linkDB item * * @return None. */ static void battNotifyCB(linkDBItem_t *pLinkItem) { if (pLinkItem->stateFlags & LINK_CONNECTED) { uint16 value = GATTServApp_ReadCharCfg(pLinkItem->connectionHandle, battLevelClientCharCfg); if (value & GATT_CLIENT_CFG_NOTIFY) { attHandleValueNoti_t noti; noti.handle = battAttrTbl[BATT_LEVEL_VALUE_IDX].handle; noti.len = 1; noti.value[0] = battLevel; GATT_Notification(pLinkItem->connectionHandle, ¬i, FALSE); } } }
/********************************************************************* * @fn Thermometer_IMeasNotify * * @brief Send a notification containing a thermometer * measurement. * * @param connHandle - connection handle * @param pNoti - pointer to notification structure * * @return Success or Failure */ bStatus_t Thermometer_IMeasNotify( uint16 connHandle, attHandleValueNoti_t *pNoti) { uint16 value = GATTServApp_ReadCharCfg( connHandle, thermometerIMeasConfig ); // If notifications enabled if ( value & GATT_CLIENT_CFG_NOTIFY ) { // Set the handle pNoti->handle = thermometerAttrTbl[THERMOMETER_IMEAS_VALUE_POS].handle; // Send the Notification return GATT_Notification( connHandle, pNoti, FALSE ); } return bleIncorrectMode; }
/********************************************************************* * @fn ScanParam_RefreshNotify * * @brief Notify the peer to refresh the scan parameters. * * @param connHandle - connection handle * * @return None */ void ScanParam_RefreshNotify( uint16 connHandle ) { attHandleValueNoti_t noti; uint16 value; value = GATTServApp_ReadCharCfg( connHandle, scanParamRefreshClientCharCfg ); if ( value & GATT_CLIENT_CFG_NOTIFY ) { // send notification noti.handle = scanParamAttrTbl[SCAN_PARAM_REFRESH_CCCD_IDX].handle; noti.len = SCAN_PARAM_REFRESH_LEN; noti.value[0] = SCAN_PARAM_REFRESH_REQ; GATT_Notification( connHandle, ¬i, FALSE ); } }
/********************************************************************* * @fn Thermometer_IntervalIndicate * * @brief Send a interval change indication * * @param connHandle - connection handle * @param pNoti - pointer to notification structure * * @return Success or Failure */ bStatus_t Thermometer_IntervalIndicate( uint16 connHandle, attHandleValueInd_t *pNoti,uint8 taskId ) { uint16 value = GATTServApp_ReadCharCfg( connHandle, thermometerIntervalConfig ); // If indications enabled if ( value & GATT_CLIENT_CFG_INDICATE ) { // Set the handle (uses stored relative handle to lookup actual handle) pNoti->handle = thermometerAttrTbl[pNoti->handle].handle; // Send the Indication return GATT_Indication( connHandle, pNoti, FALSE, taskId ); } return bleIncorrectMode; }
/********************************************************************* * @fn Glucose_CtlPntIndicate * * @brief Send an indication containing a control point * message. * * @param connHandle - connection handle * @param pInd - pointer to indication structure * * @return Success or Failure */ bStatus_t Glucose_CtlPntIndicate( uint16 connHandle, attHandleValueInd_t *pInd, uint8 taskId ) { uint16 value = GATTServApp_ReadCharCfg( connHandle, glucoseControlConfig ); // If indications enabled if ( value & GATT_CLIENT_CFG_INDICATE ) { // Set the handle pInd->handle = glucoseAttrTbl[GLUCOSE_CTL_PNT_VALUE_POS].handle; // Send the Indication return GATT_Indication( connHandle, pInd, FALSE, taskId ); } return bleNotReady; }
/********************************************************************* * @fn BloodPressure_MeasIndicate * * @brief Send a indication containing a bloodPressure * measurement. * * @param connHandle - connection handle * @param pNoti - pointer to notification structure * * @return Success or Failure */ bStatus_t BloodPressure_MeasIndicate( uint16 connHandle, attHandleValueInd_t *pNoti,uint8 taskId ) { uint16 value = GATTServApp_ReadCharCfg( connHandle, bloodPressureMeasConfig ); // If indications enabled if ( value & GATT_CLIENT_CFG_INDICATE ) { // Set the handle pNoti->handle = bloodPressureAttrTbl[BLOODPRESSURE_MEAS_VALUE_POS].handle; // Send the Indication return GATT_Indication( connHandle, pNoti, FALSE, taskId ); } return bleIncorrectMode; }
/********************************************************************* * @fn simpleProfile_StateNotify * * @brief Send a notification containing a rate * measurement. * * @param connHandle - connection handle * @param pNoti - pointer to notification structure * * @return Success or Failure */ bStatus_t simpleProfile_StateNotify( uint16 connHandle, attHandleValueNoti_t *pNoti ) { uint16 value = GATTServApp_ReadCharCfg( connHandle, simpleProfileChar4Config ); // If notifications enabled if ( value & GATT_CLIENT_CFG_NOTIFY ) { // Set the handle pNoti->handle = simpleProfileAttrTbl[12].handle; // Send the notification return GATT_Notification( connHandle, pNoti, FALSE ); } return bleIncorrectMode; }
/********************************************************************* * @fn Cycling_MeasNotify * * @brief Send a notification containing a CSC * measurement. * * @param connHandle - connection handle * @param pNoti - pointer to notification structure * * @return Success or Failure */ bStatus_t Cycling_MeasNotify( uint16 connHandle, attHandleValueNoti_t *pNoti ) { uint16 value = GATTServApp_ReadCharCfg( connHandle, cyclingMeasClientCharCfg ); // If notifications enabled if ( value & GATT_CLIENT_CFG_NOTIFY ) { // Set the handle pNoti->handle = cyclingAttrTbl[CSC_MEAS_VALUE_POS].handle; // Send the notification return GATT_Notification( connHandle, pNoti, FALSE ); } return bleIncorrectMode; }
/********************************************************************* * @fn Glucose_ContextSend * * @brief Send a glucose measurement context. * * @param connHandle - connection handle * @param pNoti - pointer to notification structure * * @return Success or Failure */ bStatus_t Glucose_ContextSend( uint16 connHandle, attHandleValueNoti_t *pNoti, uint8 taskId ) { uint16 value = GATTServApp_ReadCharCfg( connHandle, glucoseContextConfig ); // If notifications enabled if ( value & GATT_CLIENT_CFG_NOTIFY ) { // Set the handle pNoti->handle = glucoseAttrTbl[GLUCOSE_CONTEXT_VALUE_POS].handle; // Send the Indication return GATT_Notification( connHandle, pNoti, FALSE ); } return bleNotReady; }
/********************************************************************* * @fn BloodPressure_IMeasNotify * * @brief Send a notification containing a bloodPressure * measurement. * * @param connHandle - connection handle * @param pNoti - pointer to notification structure * * @return Success or Failure */ bStatus_t BloodPressure_IMeasNotify( uint16 connHandle, attHandleValueNoti_t *pNoti, uint8 taskId ) { uint16 value = GATTServApp_ReadCharCfg( connHandle, bloodPressureIMeasConfig ); // If notifications enabled if ( value & GATT_CLIENT_CFG_NOTIFY ) { // Set the handle pNoti->handle = bloodPressureAttrTbl[BLOODPRESSURE_IMEAS_VALUE_POS].handle; // Send the Indication return GATT_Notification( connHandle, pNoti, FALSE); } return bleIncorrectMode; }
/********************************************************************* * @fn HeartRate_MeasNotify * * @brief Send a notification containing a heart rate * measurement. * * @param connHandle - connection handle * @param pNoti - pointer to notification structure * * @return Success or Failure */ bStatus_t HeartRate_MeasNotify(uint16 connHandle, attHandleValueNoti_t *pNoti) { uint16 value = GATTServApp_ReadCharCfg(connHandle, heartRateMeasClientCharCfg); // If notifications enabled if (value & GATT_CLIENT_CFG_NOTIFY) { // Set the handle. pNoti->handle = heartRateAttrTbl[HEARTRATE_MEAS_VALUE_POS].handle; // Send the notification. return GATT_Notification(connHandle, pNoti, FALSE); } return bleIncorrectMode; }
/********************************************************************* * @fn oadImgIdentifyReq * * @brief Process the Image Identify Request. * * @param connHandle - connection message was received on * @param pImgHdr - Pointer to the img_hdr_t data to send. * * @return None */ static void oadImgBlockReq(uint16 connHandle, uint16 blkNum) { uint16 value = GATTServApp_ReadCharCfg( connHandle, oadImgBlockConfig ); // If notifications enabled if ( value & GATT_CLIENT_CFG_NOTIFY ) { attHandleValueNoti_t noti; gattAttribute_t *pAttr = GATTServApp_FindAttr(oadAttrTbl, GATT_NUM_ATTRS(oadAttrTbl), oadCharVals+OAD_CHAR_IMG_BLOCK); noti.handle = pAttr->handle; noti.len = 2; noti.value[0] = LO_UINT16(blkNum); noti.value[1] = HI_UINT16(blkNum); VOID GATT_Notification(connHandle, ¬i, FALSE); } }
/********************************************************************* * @fn temp_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 temp_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset ) { bStatus_t status = ATT_ERR_ATTR_NOT_FOUND; if ( pAttr->type.len == ATT_BT_UUID_SIZE ) { uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]); switch ( uuid ) { case GATT_CLIENT_CHAR_CFG_UUID: status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY ); if (GATTServApp_ReadCharCfg(connHandle, valueConfigCoordinates) & GATT_CLIENT_CFG_NOTIFY) { iDoTurnOnTemp(); } else { iDoTurnOffTemp(); } break; case TEMP_UUID: if (len != sizeof(struct temp_ts)) { return ATT_ERR_INVALID_VALUE_SIZE; } recorder_set_read_base_ts((struct calendar *)(pValue + sizeof(struct temp))); status = SUCCESS; break; case TEMP_TIME_UUID: if (len != sizeof(struct calendar)) { return ATT_ERR_INVALID_VALUE_SIZE; } recorder_set_calendar_time((struct calendar *)pValue); status = SUCCESS; break; default: status = ATT_ERR_ATTR_NOT_FOUND; } } return ( status ); }
bStatus_t char4_notify(uint8 state) { attHandleValueNoti_t Report; GAPRole_GetParameter(GAPROLE_CONNHANDLE, &connHandle); uint16 value = GATTServApp_ReadCharCfg( connHandle, simpleProfileChar4Config); // If notifications enabled if ( value & GATT_CLIENT_CFG_NOTIFY ) { // Set the handle Report.handle = simpleProfileAttrTbl[14].handle; Report.len = 1; osal_memcpy(Report.value, &state, 1); // Send the notification return GATT_Notification( connHandle, &Report, FALSE ); } return bleIncorrectMode; }
/********************************************************************* * @fn GATTServApp_ProcessCCCWriteReq * * @brief Process the client characteristic configuration * write request for a given client. * * @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 validCfg - valid configuration * * @return Success or Failure */ bStatus_t GATTServApp_ProcessCCCWriteReq( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint16 len, uint16 offset, uint16 validCfg ) { bStatus_t status = SUCCESS; // Validate the value if ( offset == 0 ) { if ( len == 2 ) { uint16 value = BUILD_UINT16( pValue[0], pValue[1] ); // Validate characteristic configuration bit field if ( ( value & ~validCfg ) == 0 ) // indicate and/or notify { // Write the value if it's changed if ( GATTServApp_ReadCharCfg( connHandle, GATT_CCC_TBL(pAttr->pValue) ) != value ) { status = GATTServApp_WriteCharCfg( connHandle, GATT_CCC_TBL(pAttr->pValue), value ); } } else { status = ATT_ERR_INVALID_VALUE; } } else { status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } return ( status ); }
/******************************************************************************************************** * @fn ServerNotificationCallBack() * * @brief when connected, send notification automaticly!!. * * @param connHandle - connection handle * @param changeType - type of change * * @return none *********************************************************************************************************/ static void ServerNotificationCallBack(linkDBItem_t *pLinkItem) { if( pLinkItem->stateFlags & LINK_CONNECTED ){ uint16 value = GATTServApp_ReadCharCfg( pLinkItem->connectionHandle,simpleProfileChar2Config ); if ( value & GATT_CLIENT_CFG_NOTIFY ){ attHandleValueNoti_t noti; noti.handle = simpleProfileAttrTbl[CHAR2_CONFIG_INDEX].handle; noti.len = SIMPLEPROFILE_CHAR2_ATCLEN; // noti.value = simpleProfileChar2; osal_memcpy(noti.value, simpleProfileChar2, SIMPLEPROFILE_CHAR2_ATCLEN ); uint8 return_status; if(return_status = GATT_Notification( pLinkItem->connectionHandle, ¬i, FALSE )) LCDPrintText("Notif error",return_status,PRINT_VALUE); //else //LCDPrintText("Notif ok",0,PRINT_STRING); } } }
/********************************************************************* * @fn hidDevSendReport * * @brief Send a HID report. * * @param id - HID report ID. * @param type - HID report type. * @param len - Length of report. * @param pData - Report data. * * @return None. */ static void hidDevSendReport( uint8 id, uint8 type, uint8 len, uint8 *pData ) { hidRptMap_t *pRpt; gattAttribute_t *pAttr; uint16 retHandle; // get att handle for report if ( (pRpt = hidDevRptById(id, type)) != NULL ) { // if notifications are enabled if ( (pAttr = GATT_FindHandle(pRpt->cccdHandle, &retHandle)) != NULL ) { uint16 value; value = GATTServApp_ReadCharCfg( gapConnHandle, (gattCharCfg_t *) pAttr->pValue ); if ( value & GATT_CLIENT_CFG_NOTIFY ) { // After service discovery and encryption, the HID Device should request to // change to the preferred connection parameters that best suit its use case. if ( updateConnParams ) { GAPRole_SetParameter( GAPROLE_PARAM_UPDATE_REQ, sizeof( uint8 ), &updateConnParams ); updateConnParams = FALSE; } // send notification lastNoti.handle = pRpt->handle; lastNoti.len = len; osal_memcpy(lastNoti.value, pData, len); GATT_Notification( gapConnHandle, &lastNoti, FALSE ); // start idle timer hidDevStartIdleTimer(); } } } }
/********************************************************************* * @fn oadImgIdentifyReq * * @brief Process the Image Identify Request. * * @param connHandle - connection message was received on * @param pImgHdr - Pointer to the img_hdr_t data to send. * * @return None */ static void oadImgIdentifyReq(uint16 connHandle, img_hdr_t *pImgHdr) { uint16 value = GATTServApp_ReadCharCfg( connHandle, oadImgIdentifyConfig ); // If notifications enabled if ( value & GATT_CLIENT_CFG_NOTIFY ) { attHandleValueNoti_t noti; gattAttribute_t *pAttr = GATTServApp_FindAttr(oadAttrTbl, GATT_NUM_ATTRS(oadAttrTbl), oadCharVals+OAD_CHAR_IMG_IDENTIFY); noti.handle = pAttr->handle; noti.len = OAD_IMG_HDR_SIZE; noti.value[0] = LO_UINT16(pImgHdr->ver); noti.value[1] = HI_UINT16(pImgHdr->ver); noti.value[2] = LO_UINT16(pImgHdr->len); noti.value[3] = HI_UINT16(pImgHdr->len); (void)osal_memcpy(noti.value+4, pImgHdr->uid, sizeof(pImgHdr->uid)); VOID GATT_Notification(connHandle, ¬i, FALSE); } }
/********************************************************************* * @fn cycling_ReadAttrCB * * @brief Read an attribute. * * @param connHandle - connection message was received on * @param pAttr - pointer to attribute * @param pValue - pointer to data to be read * @param pLen - length of data to be read * @param offset - offset of the first octet to be read * @param maxLen - maximum length of data to be read * @param method - type of read message * * @return SUCCESS, blePending or Failure */ static bStatus_t cycling_ReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 *pLen, uint16 offset, uint8 maxLen, uint8 method ) { // Make sure it's not a blob operation (no attributes in the profile are long) if ( offset > 0 ) { return ( ATT_ERR_ATTR_NOT_LONG ); } bStatus_t status = SUCCESS; uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]); switch ( uuid ) { case SENSOR_LOC_UUID: { // Read Sensor Location *pLen = 1; pValue[0] = pAttr->pValue[0]; } break; case CSC_FEATURE_UUID: { //Read Cycling Feature *pLen = 2; pValue[0] = LO_UINT16(pAttr->pValue[0]); pValue[1] = HI_UINT16(pAttr->pValue[0]); } break; case GATT_CLIENT_CHAR_CFG_UUID: { // Read Measurement or Command Configuration if ( pAttr->pValue == (uint8*)cyclingMeasClientCharCfg ) { *pLen = 1; pValue[0] = GATTServApp_ReadCharCfg(connHandle, cyclingMeasClientCharCfg ); } else if ( pAttr->pValue == (uint8*)cyclingCommandClientCharCfg ) { *pLen = 1; pValue[0] = GATTServApp_ReadCharCfg(connHandle, cyclingCommandClientCharCfg ); } else { status = ATT_ERR_ATTR_NOT_FOUND; } } break; default: status = ATT_ERR_ATTR_NOT_FOUND; break; } // Notify app if ( cyclingServiceCB != NULL ) { (*cyclingServiceCB)( CSC_READ_ATTR, NULL ); } return ( status ); }
/********************************************************************* * @fn glucose_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 method - type of write message * * @return SUCCESS, blePending or Failure */ static bStatus_t glucose_WriteAttrCB(uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset, uint8 method) { bStatus_t status = SUCCESS; // Make sure it's not a blob operation // (no attributes in the profile are long). if (offset > 0) { return (ATT_ERR_ATTR_NOT_LONG); } uint16 uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]); switch (uuid) { case GATT_CLIENT_CHAR_CFG_UUID: // Glucose Notifications. if ((pAttr->handle == glucoseAttrTbl[GLUCOSE_MEAS_CONFIG_POS].handle || pAttr->handle == glucoseAttrTbl[GLUCOSE_CONTEXT_CONFIG_POS].handle)) { status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY); if (status == SUCCESS) { uint16 charCfg = BUILD_UINT16(pValue[0], pValue[1]); if(pAttr->handle == glucoseAttrTbl[GLUCOSE_MEAS_CONFIG_POS].handle) { (*glucoseServiceCB)((charCfg == 0) ? GLUCOSE_MEAS_NTF_DISABLED : GLUCOSE_MEAS_NTF_ENABLED, NULL, NULL); } else { (*glucoseServiceCB)((charCfg == 0) ? GLUCOSE_CONTEXT_NTF_DISABLED : GLUCOSE_CONTEXT_NTF_ENABLED, NULL, NULL); } } } // Glucose Indications. else if (pAttr->handle == glucoseAttrTbl[GLUCOSE_CTL_PNT_CONFIG_POS].handle) { status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_INDICATE); if (status == SUCCESS) { uint16 charCfg = BUILD_UINT16(pValue[0], pValue[1]); (*glucoseServiceCB)((charCfg == 0) ? GLUCOSE_CTL_PNT_IND_DISABLED : GLUCOSE_CTL_PNT_IND_ENABLED, NULL, NULL); } } else { status = ATT_ERR_INVALID_VALUE; } break; case RECORD_CTRL_PT_UUID: if(len >= GLUCOSE_CTL_PNT_MIN_SIZE && len <= GLUCOSE_CTL_PNT_MAX_SIZE) { uint8 opcode = pValue[0]; // If transfer in progress if (opcode != CTL_PNT_OP_ABORT && glucoseSendAllRecords) { status = GLUCOSE_ERR_IN_PROGRESS; } // If CCC not configured for glucose measurement else if (opcode == CTL_PNT_OP_REQ && !(GATTServApp_ReadCharCfg(connHandle, glucoseMeasConfig) & GATT_CLIENT_CFG_NOTIFY)) { status = GLUCOSE_ERR_CCC_CONFIG; } else { (*glucoseServiceCB)(GLUCOSE_CTL_PNT_CMD, pValue, len); } } else { status = ATT_ERR_INVALID_VALUE_SIZE; } break; default: status = ATT_ERR_ATTR_NOT_FOUND; break; } return (status); }