/********************************************************************* * @fn BloodPressure_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 * * @return Success or Failure */ static bStatus_t BloodPressure_WriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr, uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method) { bStatus_t status = SUCCESS; uint16 uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]); switch (uuid) { case GATT_CLIENT_CHAR_CFG_UUID: if (pAttr->handle == bloodPressureAttrTbl[BLOODPRESSURE_MEAS_CONFIG_POS].handle) { // BloodPressure Indications. status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_INDICATE); if (status == SUCCESS) { uint16 value = BUILD_UINT16(pValue[0], pValue[1]); (*bloodPressureServiceCB)((value == GATT_CFG_NO_OPERATION) ? BLOODPRESSURE_MEAS_NOTI_DISABLED : BLOODPRESSURE_MEAS_NOTI_ENABLED); } } else if (pAttr->handle == bloodPressureAttrTbl[BLOODPRESSURE_IMEAS_CONFIG_POS].handle) { // BloodPressure Notifications. status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY); if (status == SUCCESS) { uint16 value = BUILD_UINT16(pValue[0], pValue[1]); (*bloodPressureServiceCB)((value == GATT_CFG_NO_OPERATION) ? BLOODPRESSURE_IMEAS_NOTI_DISABLED : BLOODPRESSURE_IMEAS_NOTI_ENABLED); } } else { status = ATT_ERR_INVALID_HANDLE; } break; default: status = ATT_ERR_ATTR_NOT_FOUND; break; } return (status); }
/********************************************************************* * @fn accel_WriteAttrCB * * @brief Validate attribute data prior to a write operation * * @param connHandle – connection message was received on * @param pReq - pointer to request * * @return Success or Failure */ static bStatus_t accel_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset ) { bStatus_t status = SUCCESS; uint8 notify = 0xFF; if ( pAttr->type.len == ATT_BT_UUID_SIZE ) { uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]); switch ( uuid ) { case ACCEL_ENABLER_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 if ( pValue[0] != FALSE && pValue[0] != TRUE ) status = ATT_ERR_INVALID_VALUE; } else { status = ATT_ERR_ATTR_NOT_LONG; } //Write the value if ( status == SUCCESS ) { uint8 *pCurValue = (uint8 *)pAttr->pValue; *pCurValue = pValue[0]; notify = ACCEL_ENABLER; } 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! status = ATT_ERR_ATTR_NOT_FOUND; } } else { // 128-bit UUID status = ATT_ERR_INVALID_HANDLE; } // If an attribute changed then callback function to notify application of change if ( (notify != 0xFF) && accel_AppCBs && accel_AppCBs->pfnAccelEnabler ) accel_AppCBs->pfnAccelEnabler(); return ( status ); }
/** * @fn uartServ2WriteAttrCB * * @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 * * @return Success or Failure */ static bStatus_t uartServ2WriteAttrCB(uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset) { bStatus_t status = SUCCESS; uint16 uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]); dmsg(("\033[40;31m0xFFE0 (Notify)\033[0m\n")); switch (uuid) { case GATT_CLIENT_CHAR_CFG_UUID: status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY); if (status == SUCCESS) { uint16 charCfg = BUILD_UINT16(pValue[0], pValue[1]); if (uartServ2_AppCBs) { (*uartServ2_AppCBs)((charCfg == GATT_CFG_NO_OPERATION) ? UARTSERV2_NOTI_DISABLED : UARTSERV2_NOTI_ENABLED); } } break; default: status = ATT_ERR_ATTR_NOT_FOUND; break; } return (status); }
/********************************************************************* * @fn Battery_Service_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 Battery_Service_WriteAttrCB( uint16_t connHandle, gattAttribute_t *pAttr, uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method ) { bStatus_t status = SUCCESS; uint8_t paramID = 0xFF; // See if request is regarding a Client Characterisic Configuration if ( ! memcmp(pAttr->type.uuid, clientCharCfgUUID, pAttr->type.len) ) { // Allow notification and indication, but do not check if really allowed per CCCD. status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY | GATT_CLIENT_CFG_INDICATE ); } else { // If we get here, that means you've forgotten to add an if clause for a // characteristic value attribute in the attribute table that has WRITE permissions. status = ATT_ERR_ATTR_NOT_FOUND; } // Let the application know something changed (if it did) by using the // callback it registered earlier (if it did). if (paramID != 0xFF) if ( pAppCBs && pAppCBs->pfnChangeCb ) pAppCBs->pfnChangeCb( paramID ); // Call app function from stack task context. return status; }
/********************************************************************* * @fn battWriteAttrCB * * @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 * * @return Success or Failure */ static bStatus_t battWriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset ) { bStatus_t status = SUCCESS; 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 ( status == SUCCESS ) { uint16 charCfg = BUILD_UINT16( pValue[0], pValue[1] ); if ( battServiceCB ) { (*battServiceCB)( (charCfg == GATT_CFG_NO_OPERATION) ? BATT_LEVEL_NOTI_DISABLED : BATT_LEVEL_NOTI_ENABLED); } } break; default: status = ATT_ERR_ATTR_NOT_FOUND; break; } return ( status ); }
/********************************************************************* * @fn SK_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 SK_writeAttrCB(uint16_t connHandle, gattAttribute_t *pAttr, uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method) { bStatus_t status = SUCCESS; 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 GATT_CLIENT_CHAR_CFG_UUID: status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY); break; default: // Should never get here! status = ATT_ERR_ATTR_NOT_FOUND; break; } } else { // 128-bit UUID status = ATT_ERR_INVALID_HANDLE; } return (status); }
static bStatus_t consoleProfile_WriteAttrCB(uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset) { unsigned char i; bStatus_t status; if (pAttr->type.len == ATT_BT_UUID_SIZE && BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]) == GATT_CLIENT_CHAR_CFG_UUID) { status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY); // Setup console if we're connected, otherwise disable for (i = 0; i < GATT_MAX_NUM_CONN; i++) { if (consoleProfileCharCfg[i].value == 1) { io.writein = io.write; io.writeout = io.write; ble_console_enabled = 1; OS_timer_stop(DELAY_TIMER); interpreter_banner(); goto done; } } ble_console_enabled = 0; done: return status; } for (i = 0; i < len; i++) { OS_type(pValue[i]); } return SUCCESS; }
/********************************************************************* * @fn oadWriteAttrCB * * @brief Validate and Write attribute data * * @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 oadWriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr, uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method) { bStatus_t status = SUCCESS; if (pAttr->type.len == ATT_BT_UUID_SIZE) { // 16-bit UUID uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]); if (uuid == GATT_CLIENT_CHAR_CFG_UUID) { // Process a CCC write request. status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY); } else { status = ATT_ERR_ATTR_NOT_FOUND; // Should never get here! } } else { // 128-bit UUID if (!memcmp(pAttr->type.uuid, oadCharUUID[OAD_CHAR_IMG_IDENTIFY], ATT_UUID_SIZE)) { /* OAD manager is identifying the new image. * The manager presents header information by which this device can * accept or reject an OAD of a new application image. */ // Notify Application if (oadTargetWriteCB != NULL) { (*oadTargetWriteCB)(OAD_WRITE_IDENTIFY_REQ, connHandle, pValue); } } else if (!memcmp(pAttr->type.uuid, oadCharUUID[OAD_CHAR_IMG_BLOCK], ATT_UUID_SIZE)) { /* The OAD manager has sent a block from the new image. */ // Notify the application. if (oadTargetWriteCB != NULL) { (*oadTargetWriteCB)(OAD_WRITE_BLOCK_REQ, connHandle, pValue); } } else { status = ATT_ERR_ATTR_NOT_FOUND; // Should never get here! } } return status; }
/********************************************************************* * @fn scanParamWriteAttrCB * * @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 scanParamWriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset ) { 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]); // Only one writeable attribute if ( uuid == SCAN_INTERVAL_WINDOW_UUID ) { // require encryption if ( linkDB_Encrypted( connHandle ) == FALSE ) { return ( ATT_ERR_INSUFFICIENT_ENCRYPT ); } if ( len == SCAN_INTERVAL_WINDOW_CHAR_LEN ) { uint16 interval = BUILD_UINT16( pValue[0], pValue[1] ); uint16 window = BUILD_UINT16( pValue[0], pValue[1] ); // Validate values if ( window <= interval ) { osal_memcpy( pAttr->pValue, pValue, len ); (*scanParamServiceCB)( SCAN_INTERVAL_WINDOW_SET ); } else { status = ATT_ERR_INVALID_VALUE; } } else { status = ATT_ERR_INVALID_VALUE_SIZE; } } else if ( uuid == GATT_CLIENT_CHAR_CFG_UUID ) { status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY ); } else { status = ATT_ERR_ATTR_NOT_FOUND; } return ( status ); }
/********************************************************************* * @fn audioProfile_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 read message * * @return SUCCESS, ATT_ERR_INSUFFICIENT_AUTHOR, * ATT_ERR_ATTR_NOT_LONG, or ATT_ERR_INVALID_HANDLE */ static bStatus_t audioProfile_WriteAttrCB(uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint16 len, uint16 offset, uint8 method) { bStatus_t status = SUCCESS; if (offset != 0) { return ATT_ERR_ATTR_NOT_LONG; } 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 GATT_CLIENT_CHAR_CFG_UUID: status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY); break; default: // Should never get here! status = ATT_ERR_ATTR_NOT_FOUND; break; } } else if (pAttr->type.len == ATT_UUID_SIZE) { // 128-bit UUID uint16 uuid = BUILD_UINT16(pAttr->type.uuid[12], pAttr->type.uuid[13]); switch (uuid) { case AUDIOPROFILE_START_UUID: case AUDIOPROFILE_AUDIO_UUID: // Write not permitted status = ATT_ERR_WRITE_NOT_PERMITTED; break; default: // Should never get here! status = ATT_ERR_ATTR_NOT_FOUND; break; } } else { status = ATT_ERR_INVALID_HANDLE; } return status; }
/********************************************************************* * @fn heartRate_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 heartRate_WriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr, uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method) { bStatus_t status = SUCCESS; uint16 uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]); switch (uuid) { case HEARTRATE_CTRL_PT_UUID: if (offset > 0) { status = ATT_ERR_ATTR_NOT_LONG; } else if (len != 1) { status = ATT_ERR_INVALID_VALUE_SIZE; } else if (*pValue != HEARTRATE_COMMAND_ENERGY_EXP) { status = HEARTRATE_ERR_NOT_SUP; } else { *(pAttr->pValue) = pValue[0]; (*heartRateServiceCB)(HEARTRATE_COMMAND_SET); } break; case GATT_CLIENT_CHAR_CFG_UUID: status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY); if (status == SUCCESS) { uint16 charCfg = BUILD_UINT16(pValue[0], pValue[1]); (*heartRateServiceCB)((charCfg == GATT_CFG_NO_OPERATION) ? HEARTRATE_MEAS_NOTI_DISABLED : HEARTRATE_MEAS_NOTI_ENABLED); } break; default: status = ATT_ERR_ATTR_NOT_FOUND; break; } return (status); }
/********************************************************************* * @fn sensor_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 * * @return Success or Failure */ static bStatus_t sensor_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset ) { bStatus_t status = SUCCESS; uint8 notifyApp = 0xFF; uint16 uuid; // If attribute permissions require authorization to write, return error if ( gattPermitAuthorWrite( pAttr->permissions ) ) { // Insufficient authorization return ( ATT_ERR_INSUFFICIENT_AUTHOR ); } if (utilExtractUuid16(pAttr,&uuid) == FAILURE) { // Invalid handle return ATT_ERR_INVALID_HANDLE; } switch ( uuid ) { case SENSOR_DATA_UUID: // Should not get here 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! status = ATT_ERR_ATTR_NOT_FOUND; break; } // If a charactersitic value changed then callback function to notify application of change if ( (notifyApp != 0xFF ) && sensor_AppCBs && sensor_AppCBs->pfnSensorChange ) { sensor_AppCBs->pfnSensorChange( notifyApp ); } return ( status ); }
/********************************************************************* * @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 ); }
/********************************************************************* * @fn oadWriteAttrCB * * @brief Validate and Write attribute data * * @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 oadWriteAttrCB(uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset, uint8 method) { bStatus_t status = SUCCESS; if ( pAttr->type.len == ATT_BT_UUID_SIZE ) { // 16-bit UUID uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]); if ( uuid == GATT_CLIENT_CHAR_CFG_UUID) { status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY ); } else { status = ATT_ERR_ATTR_NOT_FOUND; // Should never get here! } } else { // 128-bit UUID if (osal_memcmp(pAttr->type.uuid, oadCharUUID[OAD_CHAR_IMG_IDENTIFY], ATT_UUID_SIZE)) { status = oadImgIdentifyWrite( connHandle, pValue ); } else if (osal_memcmp(pAttr->type.uuid, oadCharUUID[OAD_CHAR_IMG_BLOCK], ATT_UUID_SIZE)) { status = oadImgBlockWrite( connHandle, pValue ); } else { status = ATT_ERR_ATTR_NOT_FOUND; // Should never get here! } } return status; }
/********************************************************************* * @fn sensor_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 * * @return Success or Failure */ static bStatus_t sensor_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset, uint8 method ) { bStatus_t status = SUCCESS; uint8 notifyApp = 0xFF; uint16 uuid; // If attribute permissions require authorization to write, return error if ( gattPermitAuthorWrite( pAttr->permissions ) ) { // Insufficient authorization return ( ATT_ERR_INSUFFICIENT_AUTHOR ); } if (utilExtractUuid16(pAttr,&uuid) == FAILURE) { // Invalid handle return ATT_ERR_INVALID_HANDLE; } switch ( uuid ) { case SENSOR_DATA_UUID: case SENSOR_CALIBR_UUID: // Should not get here break; case SENSOR_CONFIG_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 *pCurValue = (uint8 *)pAttr->pValue; *pCurValue = pValue[0]; if( pAttr->pValue == &sensorCfg ) { notifyApp = SENSOR_CONF; } } break; case SENSOR_PERIOD_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]>=(SENSOR_MIN_UPDATE_PERIOD/SENSOR_PERIOD_RESOLUTION)) { uint8 *pCurValue = (uint8 *)pAttr->pValue; *pCurValue = pValue[0]; if( pAttr->pValue == &sensorPeriod ) { notifyApp = SENSOR_PERI; } } else { status = ATT_ERR_INVALID_VALUE; } } 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! status = ATT_ERR_ATTR_NOT_FOUND; break; } // If a charactersitic value changed then callback function to notify application of change if ( (notifyApp != 0xFF ) && sensor_AppCBs && sensor_AppCBs->pfnSensorChange ) { sensor_AppCBs->pfnSensorChange( notifyApp ); } return ( status ); }
/********************************************************************* * @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 * * @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: 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 *pCurValue = (uint8 *)pAttr->pValue; *pCurValue = pValue[0]; if( pAttr->pValue == &simpleProfileChar1 ) { notifyApp = SIMPLEPROFILE_CHAR1; } else { notifyApp = SIMPLEPROFILE_CHAR3; } } break; case GATT_CLIENT_CHAR_CFG_UUID: status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY ); break; case SIMPLEPROFILE_CHAR6_UUID: //Validate the value // Make sure it's not a blob oper if ( offset == 0 ) { if ( len != SIMPLEPROFILE_CHAR6_LEN ) { status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } //Write the value if ( status == SUCCESS ) { VOID osal_memcpy(pAttr->pValue, pValue, len); notifyApp = SIMPLEPROFILE_CHAR6; } 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 ccService_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 * * @return Success or Failure */ static bStatus_t ccService_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset, uint8 method ) { uint16 uuid; 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 (utilExtractUuid16(pAttr,&uuid) == FAILURE) { // Invalid handle return ATT_ERR_INVALID_HANDLE; } switch ( uuid ) { case CCSERVICE_CHAR2_UUID: // Validate the value // Make sure it's not a blob oper if ( offset == 0 ) { if ( len != CCSERVICE_CHAR2_LEN ) { status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } // Write the value if ( status == SUCCESS ) { VOID osal_memcpy( ccServiceChar2, pValue, CCSERVICE_CHAR2_LEN ); notifyApp = CCSERVICE_CHAR2; } break; case CCSERVICE_CHAR3_UUID: 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 *pCurValue = (uint8 *)pAttr->pValue; *pCurValue = pValue[0]; notifyApp = CCSERVICE_CHAR3; } break; case GATT_CLIENT_CHAR_CFG_UUID: status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY ); break; default: status = ATT_ERR_ATTR_NOT_FOUND; break; } // If a charactersitic value changed then callback function to notify application of change if ( (notifyApp != 0xFF ) && ccService_AppCBs && ccService_AppCBs->pfnCcChange ) { ccService_AppCBs->pfnCcChange( notifyApp ); } return ( status ); }
/********************************************************************* * @fn lights_WriteAttrCB * * @brief Validate attribute data prior to a write operation * * @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 or Failure */ static bStatus_t lights_WriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr, uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method) { 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 LIGHTSPROFILE_RED_UUID: case LIGHTSPROFILE_GREEN_UUID: case LIGHTSPROFILE_BLUE_UUID: case LIGHTSPROFILE_WHITE_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 *pCurValue = (uint8 *)pAttr->pValue; *pCurValue = pValue[0]; if( pAttr->pValue == &lightsProfileRGBW[0] ) { notifyApp = LIGHTSPROFILE_RED; } if( pAttr->pValue == &lightsProfileRGBW[1] ) { notifyApp = LIGHTSPROFILE_GREEN; } if( pAttr->pValue == &lightsProfileRGBW[2] ) { notifyApp = LIGHTSPROFILE_BLUE; } if( pAttr->pValue == &lightsProfileRGBW[3] ) { notifyApp = LIGHTSPROFILE_WHITE; } } break; case LIGHTSPROFILE_RGBW_UUID: if ( offset == 0 ) { if ( len != LIGHTSPROFILE_RGBW_LEN ) { status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } if ( status == SUCCESS ) { uint8 *pCurValue = (uint8 *)pAttr->pValue; memcpy( pCurValue, pValue, LIGHTSPROFILE_RGBW_LEN ); if( (int)pAttr->pValue == (int)&lightsProfileRGBW ) { notifyApp = LIGHTSPROFILE_RGBW; } } 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! status = ATT_ERR_ATTR_NOT_FOUND; break; } } else { // 128-bit UUID status = ATT_ERR_INVALID_HANDLE; } // If a characteristic value changed then callback function to notify application of change if ( (notifyApp != 0xFF ) && lights_AppCBs && lights_AppCBs->pfnLightsProfileChange ) { lights_AppCBs->pfnLightsProfileChange( notifyApp ); } return ( status ); }
/********************************************************************* * @fn sensor_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 sensor_WriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr, uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method) { bStatus_t status = SUCCESS; uint8_t notifyApp = 0xFF; uint16_t uuid; // If attribute permissions require authorization to write, return error if (gattPermitAuthorWrite(pAttr->permissions)) { // Insufficient authorization return (ATT_ERR_INSUFFICIENT_AUTHOR); } if (utilExtractUuid16(pAttr,&uuid) == FAILURE) { // Invalid handle return ATT_ERR_INVALID_HANDLE; } switch (uuid) { case REGISTER_DATA_UUID: // Validate the value // Make sure it's not a blob oper if (offset == 0) { if (len > REGISTER_DATA_LEN ) { status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } // Write the value if (status == SUCCESS) { memcpy(pAttr->pValue, pValue, len); sensor_writeRegister(); } break; case REGISTER_ADDR_UUID: // Validate the value // Make sure it's not a blob oper if (offset == 0) { if (len > REGISTER_ADDRESS_LEN ) { status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } // Write the value if (status == SUCCESS) { if (pValue[0] <= REGISTER_DATA_LEN ) { memcpy(pAttr->pValue, pValue, len); // Address changed; read data sensor_readRegister(); if (pAttr->pValue == (uint8_t*)®isterAddress ) { notifyApp = REGISTER_ADDR; } } else { status = ATT_ERR_INVALID_VALUE; } } break; case REGISTER_DEV_UUID: // Validate the value // Make sure it's not a blob oper if (offset == 0) { if (len != REGISTER_DEVICE_LEN ) { status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } // Write the value if (status == SUCCESS) { if (pValue[0] < REGISTER_INTERFACE_NUM ) { memcpy(pAttr->pValue, pValue, REGISTER_DEVICE_LEN); if (pAttr->pValue == (uint8_t*)®isterDeviceID ) { notifyApp = REGISTER_DEV; // bspI2cReset(); sensor_initRegister(registerDeviceID[0], registerDeviceID[1]); } } else { status = ATT_ERR_INVALID_VALUE; } } 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! status = ATT_ERR_ATTR_NOT_FOUND; break; } // If a characteristic value changed then callback function // to notify application of change if ((notifyApp != 0xFF ) && sensor_AppCBs && sensor_AppCBs->pfnSensorChange) { sensor_AppCBs->pfnSensorChange(notifyApp); } return (status); }
/** * 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 buttonsProfile_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 BLE_BUTTONS_A_CHAR_UUID: P1_7 = getValue(pAttr, pValue, len, offset, &status); break; case BLE_BUTTONS_B_CHAR_UUID: P1_1 = getValue(pAttr, pValue, len, offset, &status); break; case BLE_BUTTONS_X_CHAR_UUID: P0_6 = getValue(pAttr, pValue, len, offset, &status); break; case BLE_BUTTONS_Y_CHAR_UUID: P0_5 = getValue(pAttr, pValue, len, offset, &status); break; case BLE_BUTTONS_UP_CHAR_UUID: P2_0 = getValue(pAttr, pValue, len, offset, &status); break; case BLE_BUTTONS_DN_CHAR_UUID: if (getValue(pAttr, pValue, len, offset, &status) > 0) { I2CIO |= 0x02; // SCL } else { I2CIO &= ~0x02; // SCL } break; case BLE_BUTTONS_L_CHAR_UUID: P0_7 = getValue(pAttr, pValue, len, offset, &status); break; case BLE_BUTTONS_R_CHAR_UUID: P1_6 = getValue(pAttr, pValue, len, offset, &status); break; case BLE_BUTTONS_LB_CHAR_UUID: P0_2 = getValue(pAttr, pValue, len, offset, &status); break; case BLE_BUTTONS_RB_CHAR_UUID: if (getValue(pAttr, pValue, len, offset, &status) > 0) { I2CIO |= 0x01; // SDA } else { I2CIO &= ~0x01; // SDA } break; case BLE_BUTTONS_START_CHAR_UUID: P0_1 = getValue(pAttr, pValue, len, offset, &status); break; case BLE_BUTTONS_BACK_CHAR_UUID: P0_0 = getValue(pAttr, pValue, len, offset, &status); break; case BLE_BUTTONS_GUIDE_CHAR_UUID: P1_0 = getValue(pAttr, pValue, len, offset, &status); break; case BLE_BUTTONS_LS_CHAR_UUID: P0_3 = getValue(pAttr, pValue, len, offset, &status); break; case BLE_BUTTONS_RS_CHAR_UUID: P0_4 = getValue(pAttr, pValue, len, offset, &status); break; case BLE_BUTTONS_LX_CHAR_UUID: setChannelValue(6 - 1, pAttr, pValue, len, offset, &status); break; case BLE_BUTTONS_LY_CHAR_UUID: setChannelValue(5 - 1, pAttr, pValue, len, offset, &status); break; case BLE_BUTTONS_RX_CHAR_UUID: setChannelValue(4 - 1, pAttr, pValue, len, offset, &status); break; case BLE_BUTTONS_RY_CHAR_UUID: setChannelValue(2 - 1, pAttr, pValue, len, offset, &status); break; case BLE_BUTTONS_LT_CHAR_UUID: setChannelValue(3 - 1, pAttr, pValue, len, offset, &status); break; case BLE_BUTTONS_RT_CHAR_UUID: setChannelValue(1 - 1, pAttr, pValue, len, offset, &status); 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 ) && buttonsProfile_AppCBs && buttonsProfile_AppCBs->pfnButtonsProfileChange ) { buttonsProfile_AppCBs->pfnButtonsProfileChange( notifyApp ); } return (status); };
/********************************************************************* * @fn HidDev_WriteAttrCB * * @brief HID Dev attribute read callback. * * @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 * * @return Success or Failure */ bStatus_t HidDev_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset ) { bStatus_t status = SUCCESS; hidRptMap_t *pRpt; // 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]); if ( uuid == REPORT_UUID || uuid == BOOT_KEY_OUTPUT_UUID ) { // find report ID in table if ((pRpt = hidDevRptByHandle(pAttr->handle)) != NULL) { // execute report callback status = (*pHidDevCB->reportCB)( pRpt->id, pRpt->type, uuid, HID_DEV_OPER_WRITE, &len, pValue ); } } else if ( uuid == HID_CTRL_PT_UUID ) { // Validate length and value range if ( len == 1 ) { if ( pValue[0] == HID_CMD_SUSPEND || pValue[0] == HID_CMD_EXIT_SUSPEND ) { // execute HID app event callback (*pHidDevCB->evtCB)( (pValue[0] == HID_CMD_SUSPEND) ? HID_DEV_SUSPEND_EVT : HID_DEV_EXIT_SUSPEND_EVT ); } else { status = ATT_ERR_INVALID_VALUE; } } else { status = ATT_ERR_INVALID_VALUE_SIZE; } } else if ( uuid == GATT_CLIENT_CHAR_CFG_UUID ) { status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY ); if ( status == SUCCESS ) { uint16 charCfg = BUILD_UINT16( pValue[0], pValue[1] ); // find report ID in table if ( (pRpt = hidDevRptByCccdHandle(pAttr->handle)) != NULL ) { // execute report callback (*pHidDevCB->reportCB)( pRpt->id, pRpt->type, uuid, (charCfg == GATT_CLIENT_CFG_NOTIFY) ? HID_DEV_OPER_ENABLE : HID_DEV_OPER_DISABLE, &len, pValue ); } } } else if ( uuid == PROTOCOL_MODE_UUID ) { if ( len == HID_PROTOCOL_MODE_LEN ) { if ( pValue[0] == HID_PROTOCOL_MODE_BOOT || pValue[0] == HID_PROTOCOL_MODE_REPORT ) { pAttr->pValue[0] = pValue[0]; // execute HID app event callback (*pHidDevCB->evtCB)( (pValue[0] == HID_PROTOCOL_MODE_BOOT) ? HID_DEV_SET_BOOT_EVT : HID_DEV_SET_REPORT_EVT ); } else { status = ATT_ERR_INVALID_VALUE; } } else { status = ATT_ERR_INVALID_VALUE_SIZE; } } // restart idle timer if (status == SUCCESS) { hidDevStartIdleTimer(); } return ( status ); }
/********************************************************************* * @fn cycling_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 cycling_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset, uint8 method ) { bStatus_t status = SUCCESS; uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]); if ( offset > 0 ) { return (ATT_ERR_ATTR_NOT_LONG); } switch ( uuid ) { case SC_CTRL_PT_UUID: // Make sure Control Point Cfg is not already in progress if ( scOpInProgress == TRUE ) { status = CSC_ERR_PROC_IN_PROGRESS; } // Make sure Control Point Cfg is configured for Indications else if ( (cyclingCommandClientCharCfg[connHandle].value & GATT_CLIENT_CFG_INDICATE) == FALSE ) { status = CSC_ERR_CCC_IMPROPER_CFG; } else { // Process CSC command cycling_ProcessCSCCmd( pAttr->handle, pValue, len ); connectionHandle = connHandle; } break; // For Measure and Commands CCC case GATT_CLIENT_CHAR_CFG_UUID: if ( pAttr->handle == cyclingAttrTbl[CSC_COMMAND_CFG_POS].handle ) { status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_INDICATE ); // Notify app if ( cyclingServiceCB != NULL ) { (*cyclingServiceCB)( CSC_WRITE_ATTR, NULL ); } } else if ( pAttr->handle == cyclingAttrTbl[CSC_MEAS_CFG_POS].handle ) { status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY ); if ( status == SUCCESS ) { // Notify app if ( cyclingServiceCB != NULL ) { uint16 charCfg = BUILD_UINT16( pValue[0], pValue[1] ); (*cyclingServiceCB)( ((charCfg == GATT_CFG_NO_OPERATION) ? CSC_MEAS_NOTI_DISABLED : CSC_MEAS_NOTI_ENABLED ), NULL ); } } } break; default: status = ATT_ERR_ATTR_NOT_FOUND; break; } return ( status ); }
/********************************************************************* * @fn sensor_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 sensor_WriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr, uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method) { bStatus_t status = SUCCESS; uint8_t notifyApp = 0xFF; uint16_t uuid; if (utilExtractUuid16(pAttr,&uuid) == FAILURE) { // Invalid handle return ATT_ERR_INVALID_HANDLE; } switch (uuid) { case SENSOR_DATA_UUID: // Should not get here break; case SENSOR_CONFIG_UUID: // Validate the value // Make sure it's not a blob oper if (offset == 0) { if (len != SENSOR_CONFIG_LEN) { status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } // Write the value if (status == SUCCESS) { memcpy(pAttr->pValue, pValue, SENSOR_CONFIG_LEN); if (pAttr->pValue == (uint8_t*)&sensorCfg) { notifyApp = SENSOR_CONF; } } break; case SENSOR_PERIOD_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]>=(SENSOR_MIN_UPDATE_PERIOD/SENSOR_PERIOD_RESOLUTION)) { uint8_t *pCurValue = (uint8_t *)pAttr->pValue; *pCurValue = pValue[0]; if (pAttr->pValue == &sensorPeriod) { notifyApp = SENSOR_PERI; } } else { status = ATT_ERR_INVALID_VALUE; } } 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! status = ATT_ERR_ATTR_NOT_FOUND; break; } // If a characteristic value changed then callback function // to notify application of change if ((notifyApp != 0xFF) && sensor_AppCBs && sensor_AppCBs->pfnSensorChange) { sensor_AppCBs->pfnSensorChange(notifyApp); } return (status); }
/********************************************************************* * @fn proxReporter_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 proxReporter_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset, uint8 method ) { bStatus_t status = SUCCESS; uint8 notify = 0xFF; 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 ALERT_LEVEL_UUID: // Validate the value // Make sure it's not a blob operation if ( offset == 0 ) { if ( len > 1 ) status = ATT_ERR_INVALID_VALUE_SIZE; else { if ( pValue[0] > PP_ALERT_LEVEL_HIGH ) status = ATT_ERR_INVALID_VALUE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } //Write the value if ( status == SUCCESS ) { uint8 *pCurValue = (uint8 *)pAttr->pValue; *pCurValue = pValue[0]; if( pAttr->pValue == &llAlertLevel ) notify = PP_LINK_LOSS_ALERT_LEVEL; else notify = PP_IM_ALERT_LEVEL; } 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! status = ATT_ERR_ATTR_NOT_FOUND; break; } } else { // 128-bit UUID status = ATT_ERR_INVALID_HANDLE; } // If an attribute changed then callback function to notify application of change if ( (notify != 0xFF) && pp_AppCBs && pp_AppCBs->pfnAttrChange ) pp_AppCBs->pfnAttrChange( notify ); return ( status ); }
/********************************************************************* * @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 biscuit_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 VENDOR_NAME_CHAR_UUID: case RX_DATA_CHAR_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 *pCurValue = (uint8 *)pAttr->pValue; *pCurValue = pValue[0]; // if( pAttr->pValue == &vendorNameCharValue ) { notifyApp = VENDOR_NAME_CHAR; } // else { notifyApp = RX_DATA_CHAR; } } 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 const uint8 uuid[ATT_UUID_SIZE] = { UUID_BASE_TAIL, LO_UINT16(pAttr->type.uuid[0]), pAttr->type.uuid[1], UUID_BASE_HEAD }; if ( osal_memcmp(pAttr->type.uuid, rxDataCharUUID, ATT_UUID_SIZE) ) { //Validate the value // Make sure it's not a blob oper if ( offset == 0 ) { if ( len > 20 ) { status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } //Write the value if ( status == SUCCESS ) { // uint8 *pCurValue = (uint8 *)pAttr->pValue; // *pCurValue = pValue[0]; HalUARTWrite(HAL_UART_PORT_0, pValue, len); notifyApp = RX_DATA_CHAR; } else { // Should never get here! (characteristics 2 and 4 do not have write permissions) status = ATT_ERR_ATTR_NOT_FOUND; } } else if ( osal_memcmp(pAttr->type.uuid, resetWriteCharUUID, ATT_UUID_SIZE) ) // UUID 0004 { resetWriteChar = 1; } else if ( osal_memcmp(uuid, vendorNameCharUUID, ATT_UUID_SIZE) ) { //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 *pCurValue = (uint8 *)pAttr->pValue; *pCurValue = pValue[0]; // if( pAttr->pValue == &vendorNameCharValue ) //char 1 or 3? { notifyApp = VENDOR_NAME_CHAR; } // else { notifyApp = RX_DATA_CHAR; } } else { // Should never get here! (characteristics 2 and 4 do not have write permissions) status = ATT_ERR_ATTR_NOT_FOUND; } } } // If a charactersitic value changed then callback function to notify application of change if ( (notifyApp != 0xFF ) && biscuitProfile_AppCBs && biscuitProfile_AppCBs->pfnBiscuitProfileChange ) { biscuitProfile_AppCBs->pfnBiscuitProfileChange( notifyApp ); } return ( status ); }
/********************************************************************* * @fn thermometer_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 * * @return Success or Failure */ static bStatus_t thermometer_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset ) { bStatus_t status = SUCCESS; uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]); switch ( uuid ) { case GATT_CLIENT_CHAR_CFG_UUID: // Validate/Write Temperature measurement setting if ( pAttr->handle == thermometerAttrTbl[THERMOMETER_TEMP_CHAR_CONFIG_POS].handle ) { status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_INDICATE ); if ( status == SUCCESS ) { uint16 value = BUILD_UINT16( pValue[0], pValue[1] ); (*thermometerServiceCB)( (value == GATT_CFG_NO_OPERATION) ? THERMOMETER_TEMP_IND_DISABLED : THERMOMETER_TEMP_IND_ENABLED ); } } // Validate/Write Intermediate measurement setting else if ( pAttr->handle == thermometerAttrTbl[THERMOMETER_IMEAS_CHAR_CONFIG_POS].handle ) { status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY ); if ( status == SUCCESS ) { uint16 value = BUILD_UINT16( pValue[0], pValue[1] ); // Notify application (*thermometerServiceCB)( (value == GATT_CFG_NO_OPERATION) ? THERMOMETER_IMEAS_NOTI_DISABLED : THERMOMETER_IMEAS_NOTI_ENABLED); } } // Validate/Write Interval Client Char Config else if ( pAttr->handle == thermometerAttrTbl[THERMOMETER_INTERVAL_CHAR_CONFIG_POS].handle ) { status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_INDICATE ); if ( status == SUCCESS ) { uint16 value = BUILD_UINT16( pValue[0], pValue[1] ); // Notify application (*thermometerServiceCB)( (value == GATT_CFG_NO_OPERATION) ? THERMOMETER_INTERVAL_IND_DISABLED : THERMOMETER_INTERVAL_IND_ENABLED); } else { status = ATT_ERR_INVALID_HANDLE; } } else { status = ATT_ERR_INVALID_VALUE_SIZE; } break; case THERMOMETER_INTERVAL_UUID: // Validate the value // Make sure it's not a blob oper if ( offset == 0 ) { if ( len != THERMOMETER_INTERVAL_LEN ) status = ATT_ERR_INVALID_VALUE_SIZE; } else { status = ATT_ERR_ATTR_NOT_LONG; } //validate range if ((*pValue >= thermometerIRange.high) | ((*pValue <= thermometerIRange.low) & (*pValue != 0))) { status = ATT_ERR_INVALID_VALUE; } //Write the value if ( status == SUCCESS ) { uint8 *pCurValue = (uint8 *)pAttr->pValue; // *pCurValue = *pValue; VOID osal_memcpy( pCurValue, pValue, THERMOMETER_INTERVAL_LEN ) ; //notify application of write (*thermometerServiceCB)(THERMOMETER_INTERVAL_SET); } break; default: status = ATT_ERR_ATTR_NOT_FOUND; break; } return ( status ); }
static bStatus_t simpleProfile_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset ) { //LCDPrintText("Profile_WriteAttr",0,PRINT_STRING); 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:{ if ( offset >= SIMPLEPROFILE_CHAR1_ATCLEN ) return ( ATT_ERR_ATTR_NOT_LONG ); // determine read length uint8 actrual_len = MIN(len, SIMPLEPROFILE_CHAR1_ATCLEN - offset); osal_memcpy( &simpleProfileChar1[offset], pValue, actrual_len); notifyApp = SIMPLEPROFILE_CHAR1; break; } /*case SIMPLEPROFILE_CHAR2_UUID:{ if ( offset >= SIMPLEPROFILE_CHAR2_LEN ) return ( ATT_ERR_ATTR_NOT_LONG ); // determine read length uint8 actrual_len = MIN(len, SIMPLEPROFILE_CHAR2_LEN - offset); osal_memcpy( &simpleProfileChar2[offset], pValue, actrual_len); notifyApp = SIMPLEPROFILE_CHAR2; break; }*/ case GATT_CLIENT_CHAR_CFG_UUID:{ status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY ); notifyApp = SIMPLEPROFILE_CFG_CHAR2; 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 ); //调用回调函数 simpleProfileChangeCB() 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); }
/********************************************************************* * @fn test_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 test_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset ) { bStatus_t status = SUCCESS; uint8 notifyApp = 0xFF; uint16 uuid; // If attribute permissions require authorization to write, return error if ( gattPermitAuthorWrite( pAttr->permissions ) ) { // Insufficient authorization return ( ATT_ERR_INSUFFICIENT_AUTHOR ); } if (utilExtractUuid16(pAttr,&uuid) == FAILURE) { // Invalid handle return ATT_ERR_INVALID_HANDLE; } switch ( uuid ) { case TEST_CONF_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 *pCurValue = (uint8 *)pAttr->pValue; *pCurValue = pValue[0]; if( pAttr->pValue == &testConf ) { notifyApp = TEST_CONF_ATTR; } } 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; } // If a charactersitic value changed then callback function to notify application of change if ( (notifyApp != 0xFF ) && test_AppCBs && test_AppCBs->pfnTestChange ) { test_AppCBs->pfnTestChange( notifyApp ); } return ( status ); }
/********************************************************************* * @fn climbProfile_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 climbProfile_WriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr, uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method) { 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 CLIMBPROFILE_CHAR1_UUID: //should not get here break; case CLIMBPROFILE_CHAR2_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 ) { VOID memcpy( pAttr->pValue, pValue, len ); //VERIFICARE!!!! uint8 i; for(i = len; i < CLIMBPROFILE_CHAR2_LEN;i++){ //azzera il resto della caratteristica pAttr->pValue[i] = 0; } notifyApp = CLIMBPROFILE_CHAR2; //TODO: in some way the len parameter needs to be passed to app! } 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 characteristic value changed then callback function to notify application of change if ( (notifyApp != 0xFF ) && climbProfile_AppCBs && climbProfile_AppCBs->pfnClimbProfileChange ) { climbProfile_AppCBs->pfnClimbProfileChange( notifyApp ); } return ( status ); }