static void handleAccessWrite(GATT_ACCESS_IND_T *p_ind) { /* Check all the services that support attribute 'Write' operation handled * by application */ if(GapCheckHandleRange(p_ind->handle)) { GapHandleAccessWrite(p_ind); } else if(HidCheckHandleRange(p_ind->handle)) { HidHandleAccessWrite(p_ind); } else if(BatteryCheckHandleRange(p_ind->handle)) { BatteryHandleAccessWrite(p_ind); } else if(ScanParamCheckHandleRange(p_ind->handle)) { ScanParamHandleAccessWrite(p_ind); } else { GattAccessRsp(p_ind->cid, p_ind->handle, gatt_status_write_not_permitted, 0, NULL); } }
extern void ScanParamHandleAccessRead(GATT_ACCESS_IND_T *p_ind) { uint16 length = 0; uint8 val[2], *p_value = NULL; sys_status rc = sys_status_success; switch(p_ind->handle) { case HANDLE_SCAN_REFRESH_C_CFG: { p_value = val; length = 2; /* Two Octets */ BufWriteUint16(&p_value, scan_param_data.refresh_client_config); /* BufWriteUint16 will have incremented p_value. Revert it back * to point to val. */ p_value -= length; } break; default: { rc = gatt_status_read_not_permitted; } break; } GattAccessRsp(p_ind->cid, p_ind->handle, rc, length, p_value); }
extern void ImmAlertHandleAccessWrite(GATT_ACCESS_IND_T *p_ind) { sys_status rc = sys_status_success; switch(p_ind->handle) { case HANDLE_IMM_ALERT_LEVEL: { uint8 level = BufReadUint8(&p_ind->value); /* Ignore reserved values for Alert Level */ if((level < alert_level_reserved) && (g_imm_alert_data.p_alert_handler_fn != NULL)) { /* Call registered function handler to raise alarm as per * the configured alert level */ (*(g_imm_alert_data.p_alert_handler_fn))((alert_level)level); } /* Else Ignore the alert */ } break; default: rc = gatt_status_write_not_permitted; break; } GattAccessRsp(p_ind->cid, p_ind->handle, rc, 0, NULL); }
extern void BatteryHandleAccessWrite(GATT_ACCESS_IND_T *p_ind) { uint8 *p_value = p_ind->value; uint16 client_config; sys_status rc = sys_status_success; switch(p_ind->handle) { case HANDLE_BATT_LEVEL_C_CFG: { client_config = BufReadUint16(&p_value); /* Client Configuration is bit field value so ideally bitwise * comparison should be used but since the application supports only * notifications, direct comparison is being used. */ if((client_config == gatt_client_config_notification) || (client_config == gatt_client_config_none)) { g_batt_data.level_client_config = client_config; /* Write battery level client configuration to NVM if the * device is bonded. */ Nvm_Write(&client_config, sizeof(client_config), g_batt_data.nvm_offset + BATTERY_NVM_LEVEL_CLIENT_CONFIG_OFFSET); } else { /* INDICATION or RESERVED */ /* Return error as only notifications are supported */ rc = gatt_status_desc_improper_config; } } break; default: rc = gatt_status_write_not_permitted; break; } /* Send ACCESS RESPONSE */ GattAccessRsp(p_ind->cid, p_ind->handle, rc, 0, NULL); /* Send an update as soon as notifications are configured */ if(g_batt_data.level_client_config & gatt_client_config_notification) { /* Reset current battery level to an invalid value so that it * triggers notifications on reading the current battery level */ g_batt_data.level = 0xFF; /* 0 to 100: Valid value range */ BatteryUpdateLevel(p_ind->cid); } }
/*----------------------------------------------------------------------------* * NAME * HandleAccessWrite * * DESCRIPTION * This function handles write operations on attributes (as received in * GATT_ACCESS_IND message) maintained by the application and responds * with the GATT_ACCESS_RSP message. * * PARAMETERS * p_ind [in] Data received in GATT_ACCESS_IND message. * * RETURNS * Nothing *----------------------------------------------------------------------------*/ extern void HandleAccessWrite(GATT_ACCESS_IND_T *p_ind) { /* For the received attribute handle, check all the services that support * attribute 'Write' operation handled by application. */ /* More services may be added here to support their write operations */ if(GapCheckHandleRange(p_ind->handle)) { /* Attribute handle belongs to GAP service */ GapHandleAccessWrite(p_ind); } else if(BatteryCheckHandleRange(p_ind->handle)) { /* Attribute handle belongs to BATTERY service */ BatteryHandleAccessWrite(p_ind); } else if(EsurlBeaconCheckHandleRange(p_ind->handle)) { /* Attribute handle belongs to Beacon service */ EsurlBeaconHandleAccessWrite(p_ind); } else { /* Application doesn't support 'Write' operation on received attribute * handle, so return 'gatt_status_write_not_permitted' status */ GattAccessRsp(p_ind->cid, p_ind->handle, gatt_status_write_not_permitted, 0, NULL); } }
extern void BatteryHandleAccessWrite(GATT_ACCESS_IND_T *p_ind) { uint8 *p_value = p_ind->value; uint16 client_config; sys_status rc = sys_status_success; switch(p_ind->handle) { case HANDLE_BATT_LEVEL_C_CFG: { client_config = BufReadUint16(&p_value); if((client_config == gatt_client_config_notification) || (client_config == gatt_client_config_none)) { g_batt_data.level_client_config = client_config; /* Write batery level client configuration to NVM if the * device is bonded. */ if(AppIsDeviceBonded()) { Nvm_Write((uint16 *)&client_config, sizeof(client_config), g_batt_data.nvm_offset + BATTERY_NVM_LEVEL_CLIENT_CONFIG_OFFSET); } } else { /* INDICATION or RESERVED */ /* Return error as only notifications are supported */ rc = gatt_status_app_mask; } } break; default: { rc = gatt_status_write_not_permitted; } break; } /* Send ACCESS RESPONSE */ GattAccessRsp(p_ind->cid, p_ind->handle, rc, 0, NULL); /* Send an update as soon as notifications are configured */ if(g_batt_data.level_client_config == gatt_client_config_notification) { /* Reset current battery level to an invalid value so that it * triggers notifications on reading the current battery level */ g_batt_data.level = 0xFF; /* 0 to 100: Valid value range */ BatteryUpdateLevel(p_ind->cid); } }
extern void ScanParamHandleAccessWrite(GATT_ACCESS_IND_T *p_ind) { uint8 *p_value = p_ind->value; sys_status rc = sys_status_success; switch(p_ind->handle) { case HANDLE_SCAN_INTERVAL_WINDOW: { scan_param_data.interval = BufReadUint16(&p_value); scan_param_data.window = BufReadUint16(&p_value); } break; case HANDLE_SCAN_REFRESH_C_CFG: { uint16 client_config = BufReadUint16(&p_value); /* Client Configuration is bit field value so ideally bitwise * comparison should be used but since the application supports only * notifications, direct comparison is being used. */ if((client_config == gatt_client_config_notification) || (client_config == gatt_client_config_none)) { scan_param_data.refresh_client_config = client_config; /* Write Scan refresh Client configuration to NVM if the * device is bonded. */ Nvm_Write(&client_config, sizeof(gatt_client_config), scan_param_data.nvm_offset+ SCAN_PARAM_NVM_REFRESH_CLIENT_CONFIG_OFFSET); } else { /* INDICATION or RESERVED */ /* Return Error as only Notifications are supported */ rc = gatt_status_desc_improper_config; } } break; default: { rc = gatt_status_write_not_permitted; } break; } GattAccessRsp(p_ind->cid, p_ind->handle, rc, 0, NULL); }
/*----------------------------------------------------------------------------* * NAME * HandleAccessWrite * * DESCRIPTION * This function handles write operations on Battery Service attributes * maintained by the application and responds with the GATT_ACCESS_RSP * message. * * PARAMETERS * p_ind [in] Data received in GATT_ACCESS_IND message. * * RETURNS * Nothing *----------------------------------------------------------------------------*/ extern void BatteryHandleAccessWrite(GATT_ACCESS_IND_T *p_ind) { uint8 *p_value = p_ind->value; /* New attribute value */ uint16 client_config; /* Client configuration descriptor */ sys_status rc = sys_status_success; /* Function status */ switch(p_ind->handle) { case HANDLE_BATT_LEVEL_C_CFG: { /* Write the client configuration descriptor for the battery level * characteristic. */ client_config = BufReadUint16(&p_value); /* Only notifications are allowed for this client configuration * descriptor. */ if((client_config == gatt_client_config_notification) || (client_config == gatt_client_config_none)) { g_batt_data.level_client_config = client_config; } else { /* INDICATION or RESERVED */ /* Return error as only notifications are supported */ rc = gatt_status_app_mask; } } break; default: rc = gatt_status_write_not_permitted; break; } /* Send ACCESS RESPONSE */ GattAccessRsp(p_ind->cid, p_ind->handle, rc, 0, NULL); /* Send an update as soon as notifications are configured */ if(g_batt_data.level_client_config == gatt_client_config_notification) { /* Reset current battery level to an invalid value so that it * triggers notifications on reading the current battery level */ g_batt_data.level = 0xFF; /* 0 to 100: Valid value range */ /* Update the battery level and send notification. */ BatteryUpdateLevel(p_ind->cid); } }
static void handleAccessWrite(GATT_ACCESS_IND_T *p_ind) { /* Check all the services that support attribute 'Write' operation handled * by application */ if(GapCheckHandleRange(p_ind->handle)) { GapHandleAccessWrite(p_ind); } #ifdef ENABLE_OTA else if(GattCheckHandleRange(p_ind->handle)) { /* Attribute handle belongs to Gatt service */ GattHandleAccessWrite(p_ind); } else if(OtaCheckHandleRange(p_ind->handle)) { /* Attribute handle belongs to OTA service */ OtaHandleAccessWrite(p_ind); } #endif /* ENABLE_OTA */ else if(HidCheckHandleRange(p_ind->handle)) { HidHandleAccessWrite(p_ind); } #ifdef __PROPRIETARY_HID_SUPPORT__ else if(HidBootCheckHandleRange(p_ind->handle)) { HidBootHandleAccessWrite(p_ind); } #endif /* __PROPRIETARY_HID_SUPPORT__ */ else if(BatteryCheckHandleRange(p_ind->handle)) { BatteryHandleAccessWrite(p_ind); } else if(ScanParamCheckHandleRange(p_ind->handle)) { ScanParamHandleAccessWrite(p_ind); } else if(BondMgmtCheckHandleRange(p_ind->handle)) { BondMgmtHandleAccessWrite(p_ind); } else { GattAccessRsp(p_ind->cid, p_ind->handle, gatt_status_write_not_permitted, 0, NULL); } }
extern void DeviceInfoHandleAccessRead(GATT_ACCESS_IND_T *p_ind) { uint16 length = 0; uint8 *p_value = NULL; sys_status rc = gatt_status_irq_proceed; /* Let the firmware handle reads on this service. * Send response indication */ GattAccessRsp(p_ind->cid, p_ind->handle, rc, length, p_value); }
extern void HandleAccessRead(GATT_ACCESS_IND_T *p_ind) { /* For the received attribute handle, check all the services that support * attribute 'Read' operation handled by application. */ if(GapCheckHandleRange(p_ind->handle)) { /* Attribute handle belongs to GAP service */ GapHandleAccessRead(p_ind); } #ifdef ENABLE_OTA else if(GattCheckHandleRange(p_ind->handle)) { /* Attribute handle belongs to Gatt service */ GattHandleAccessRead(p_ind); } else if(OtaCheckHandleRange(p_ind->handle)) { /* Attribute handle belongs to OTA service */ OtaHandleAccessRead(p_ind); } #endif /* ENABLE_OTA */ else if(HeartRateCheckHandleRange(p_ind->handle)) { /* Attribute handle belongs to Heart Rate service */ HeartRateHandleAccessRead(p_ind); } else if(BatteryCheckHandleRange(p_ind->handle)) { /* Attribute handle belongs to Battery service */ BatteryHandleAccessRead(p_ind); } else if(DeviceInfoCheckHandleRange(p_ind->handle)) { /* Attribute handle belongs to Device Information Service. */ DeviceInfoHandleAccessRead(p_ind); } else { /* Application doesn't support 'Read' operation on received * attribute handle, hence return 'gatt_status_read_not_permitted' * status */ GattAccessRsp(p_ind->cid, p_ind->handle, gatt_status_read_not_permitted, 0, NULL); } }
extern void GapHandleAccessRead(GATT_ACCESS_IND_T *p_ind) { uint16 length = 0; uint8 *p_value = NULL; sys_status rc = sys_status_success; switch(p_ind->handle) { case HANDLE_DEVICE_NAME: { /* Validate offset against length, it should be less than * device name length */ if(p_ind -> offset < g_gap_data.length) { length = g_gap_data.length - p_ind -> offset; p_value = (g_gap_data.p_dev_name + p_ind -> offset); } else { rc = gatt_status_invalid_offset; } } break; #ifdef __GAP_PRIVACY_SUPPORT__ case HANDLE_PERIPHERAL_PRIVACY_FLAG: { length = 1; p_value = (uint8 *)&g_gap_data.peripheral_privacy_flag; } break; #endif /* __GAP_PRIVACY_SUPPORT__ */ default: /* Let firmware handle the request */ rc = gatt_status_irq_proceed; break; } GattAccessRsp(p_ind->cid, p_ind->handle, rc, length, p_value); }
extern void GapHandleAccessWrite(GATT_ACCESS_IND_T *p_ind) { sys_status rc = sys_status_success; switch(p_ind->handle) { case HANDLE_DEVICE_NAME: /* Update device name */ updateDeviceName(p_ind->size_value, p_ind->value); break; #ifdef __GAP_PRIVACY_SUPPORT__ case HANDLE_PERIPHERAL_PRIVACY_FLAG: GapSetPeripheralPrivacyFlag(BufReadUint8(&p_ind->value)); break; case HANDLE_RECONNECTION_ADDRESS: /* There is no specific application error code when the remote * device writes to the reconnection address when peripheral * privacy flag is disabled. So, send a success write response * but don't update the reconnection address. */ if(g_gap_data.peripheral_privacy_flag) { /* Store the re-connection address only if it is valid. */ if(GapIsReconnectionAddressValid()) { GapSetReconnectionAddress(p_ind->value); } } break; #endif /* __GAP_PRIVACY_SUPPORT__ */ default: { /* No more IRQ characteristics */ rc = gatt_status_write_not_permitted; } break; } GattAccessRsp(p_ind->cid, p_ind->handle, rc, 0, NULL); }
extern void BatteryHandleAccessRead(GATT_ACCESS_IND_T *p_ind) { uint16 length = 0; uint8 value[2]; uint8 *p_val = NULL; sys_status rc = sys_status_success; switch(p_ind->handle) { /* Battery level is being read */ case HANDLE_BATT_LEVEL: { /* Reading battery level */ length = 1; /* One Octet */ g_batt_data.level = readBatteryLevel(); value[0] = g_batt_data.level; } break; /* Client Characteristic Configuration for the Battery Level * Characteristic is being read */ case HANDLE_BATT_LEVEL_C_CFG: { length = 2; /* Two Octets */ p_val = value; BufWriteUint16((uint8 **)&p_val, g_batt_data.level_client_config); } break; default: /* No more IRQ characteristics */ rc = gatt_status_read_not_permitted; break; } /* Send Access response */ GattAccessRsp(p_ind->cid, p_ind->handle, rc, length, value); }
/*----------------------------------------------------------------------------* * NAME * BatteryHandleAccessRead * * DESCRIPTION * This function handles read operations on Battery Service attributes * maintained by the application and responds with the GATT_ACCESS_RSP * message. * * PARAMETERS * p_ind [in] Data received in GATT_ACCESS_IND message. * * RETURNS * Nothing *----------------------------------------------------------------------------*/ extern void BatteryHandleAccessRead(GATT_ACCESS_IND_T *p_ind) { uint16 length = 0; /* Length of attribute data, octets */ uint8 value[2]; /* Attribute value */ uint8 *p_val = NULL; /* Pointer to attribute value */ sys_status rc = sys_status_success; /* Function status */ switch(p_ind->handle) { case HANDLE_BATT_LEVEL: { /* Read the battery level */ length = 1; /* One Octet */ g_batt_data.level = readBatteryLevel(); value[0] = g_batt_data.level; } break; case HANDLE_BATT_LEVEL_C_CFG: { /* Read the client configuration descriptor for the battery level * characteristic. */ length = 2; /* Two Octets */ p_val = value; BufWriteUint16((uint8 **)&p_val, g_batt_data.level_client_config); } break; default: /* No more IRQ characteristics */ rc = gatt_status_read_not_permitted; break; } /* Send ACCESS RESPONSE */ GattAccessRsp(p_ind->cid, p_ind->handle, rc, length, value); }
/*-----------------------------------------------------------------------------* * NAME * OtaHandleAccessRead * * DESCRIPTION * Handle read-access requests from the Host where the characteristic * handle falls within the range of the OTAU Application Service. * * PARAMETERS * p_ind [in] Read request data * * RETURNS * Nothing *----------------------------------------------------------------------------*/ void OtaHandleAccessRead(GATT_ACCESS_IND_T *p_ind) { sys_status rc = sys_status_success; /* Function status */ uint8 data_length = 0; /* Length of data to return in octets */ uint8 *p_value = NULL; /* Pointer to return data */ csr_application_id current_app; /* Index of the current application */ switch (p_ind->handle) { case HANDLE_CSR_OTA_CURRENT_APP: /* Read the index of the current application */ current_app = OtaReadCurrentApp(); p_value = (uint8 *)¤t_app; data_length = 1; break; case HANDLE_CSR_OTA_DATA_TRANSFER: /* Read the value of the Data Transfer characteristic */ p_value = (uint8 *)data_transfer_memory; data_length = data_transfer_data_length; break; case HANDLE_CSR_OTA_DATA_TRANSFER_CLIENT_CONFIG: /* Read the value of the Data Transfer Client Characteristic * Configuration Descriptor */ p_value = (uint8 *)data_transfer_configuration; data_length = 2; break; default: /* Reading is not supported on this handle */ rc = gatt_status_read_not_permitted; break; } GattAccessRsp(p_ind->cid, p_ind->handle, rc, data_length, p_value); }
extern void GattHandleAccessWrite(GATT_ACCESS_IND_T *p_ind) { uint16 client_config; uint8 *p_value = p_ind->value; sys_status rc = gatt_status_write_not_permitted; if(p_ind->handle == HANDLE_SERVICE_CHANGED_CLIENT_CONFIG) { uint8 dev_index; dev_index = AppGetConnectedDeviceIndex(); client_config = BufReadUint16(&p_value); /* Client configuration is a bit field value, so ideally bit wise * comparison should be used but since the application supports only * indications or nothing, direct comparison should be used. */ if((client_config == gatt_client_config_indication) || (client_config == gatt_client_config_none)) { g_gatt_data.serv_changed_config[dev_index] = client_config; rc = sys_status_success; if(AppIsDeviceBonded(dev_index)) { /* Write to NVM the Service Changed Client Configuration value */ Nvm_Write((uint16*)&(g_gatt_data.serv_changed_config[dev_index]), sizeof(g_gatt_data.serv_changed_config[dev_index]), (g_gatt_data.nvm_offset + SERV_CHANGED_CLIENT_CONFIG_OFFSET(dev_index))); } } else { rc = gatt_status_desc_improper_config; } } /* Send Access Response */ GattAccessRsp(p_ind->cid, p_ind->handle, rc, 0, NULL); }
/*----------------------------------------------------------------------------* * NAME * HandleAccessWrite * * DESCRIPTION * This function handles Write operation on attributes (as received in * GATT_ACCESS_IND message) maintained by the application. * * RETURNS * Nothing * *---------------------------------------------------------------------------*/ extern void HandleAccessWrite(GATT_ACCESS_IND_T *p_ind) { /* For the received attribute handle, check all the services that support * attribute 'Write' operation handled by application. */ if(GapCheckHandleRange(p_ind->handle)) { /* Attribute handle belongs to GAP service */ GapHandleAccessWrite(p_ind); } else if(MeshControlCheckHandleRange(p_ind->handle)) { /* Attribute handle belongs to Mesh Control service */ MeshControlHandleAccessWrite(p_ind); } #ifdef ENABLE_GATT_OTA_SERVICE else if(GattCheckHandleRange(p_ind->handle)) { /* Attribute handle belongs to Gatt service */ GattHandleAccessWrite(p_ind); } else if(OtaCheckHandleRange(p_ind->handle)) { OtaHandleAccessWrite(p_ind); } #endif /* ENABLE_GATT_OTA_SERVICE */ else { /* Application doesn't support 'Write' operation on received * attribute handle, hence return 'gatt_status_write_not_permitted' * status */ GattAccessRsp(p_ind->cid, p_ind->handle, gatt_status_write_not_permitted, 0, NULL); } }
extern void GapHandleAccessWrite(GATT_ACCESS_IND_T *p_ind) { sys_status rc = sys_status_success; switch(p_ind->handle) { case HANDLE_DEVICE_NAME: /* Update device name */ updateDeviceName(p_ind->size_value, p_ind->value); break; default: /* No more IRQ characteristics */ rc = gatt_status_write_not_permitted; break; } GattAccessRsp(p_ind->cid, p_ind->handle, rc, 0, NULL); }
extern void GattHandleAccessRead(GATT_ACCESS_IND_T *p_ind) { uint16 data_length = 0; uint8 value[2]; uint8 *p_value = NULL; sys_status rc = gatt_status_read_not_permitted; uint8 dev_index = AppGetConnectedDeviceIndex(); if(p_ind->handle == HANDLE_SERVICE_CHANGED_CLIENT_CONFIG) { /* Service changed client characteristic configuration descriptor read * has been requested */ data_length = 2; p_value = value; BufWriteUint16((uint8 **)&p_value, g_gatt_data.serv_changed_config[dev_index]); rc = sys_status_success; } /* Send Access Response */ GattAccessRsp(p_ind->cid, p_ind->handle, rc, data_length, p_value); }
extern void GapHandleAccessRead(GATT_ACCESS_IND_T *p_ind) { uint16 length = 0; uint8 *p_value = NULL; sys_status rc = sys_status_success; switch(p_ind->handle) { case HANDLE_DEVICE_NAME: { /* Validate offset against length, it should be less than * device name length */ if(p_ind -> offset < g_gap_data.length) { length = g_gap_data.length - p_ind -> offset; p_value = (g_gap_data.p_dev_name + p_ind -> offset); } else { rc = gatt_status_invalid_offset; } } break; default: /* No more IRQ characteristics */ rc = gatt_status_irq_proceed; break; } GattAccessRsp(p_ind->cid, p_ind->handle, rc, length, p_value); }
/*----------------------------------------------------------------------------* * NAME * GapHandleAccessRead * * DESCRIPTION * This function handles read operations on GAP Service attributes * maintained by the application and responds with the GATT_ACCESS_RSP * message. * * PARAMETERS * p_ind [in] Data received in GATT_ACCESS_IND message. * * RETURNS * Nothing *----------------------------------------------------------------------------*/ extern void GapHandleAccessRead(GATT_ACCESS_IND_T *p_ind) { uint16 length = 0; /* Length of attribute data, octets */ uint8 *p_value = NULL; /* Pointer to attribute value */ sys_status rc = sys_status_success; /* Function status */ switch(p_ind->handle) { case HANDLE_DEVICE_NAME: { /* Validate offset against length, it should be less than the * device name length */ if(p_ind->offset < g_gap_data.length) { length = g_gap_data.length - p_ind->offset; p_value = g_gap_data.p_dev_name + p_ind->offset; } else { rc = gatt_status_invalid_offset; } } break; default: /* No more IRQ characteristics */ rc = gatt_status_read_not_permitted; break; } /* Send the GATT response. */ GattAccessRsp(p_ind->cid, p_ind->handle, rc, length, p_value); }
extern void HeartRateHandleAccessRead(GATT_ACCESS_IND_T *p_ind) { /* Initialise to 2 octets for Client Configuration */ uint16 length = 2; uint8 value[2]; uint8 *p_val = NULL; sys_status rc = sys_status_success; switch(p_ind->handle) { /* Client configuration of the Heart Rate Measurement Characteristic is * being read. */ case HANDLE_HEART_RATE_MEASUREMENT_C_CFG: { p_val = value; /* copy the client configuration value in response buffer */ BufWriteUint16(&p_val, g_hr_serv_data.hr_meas_client_config); } break; default: { /* Let the firmware handle.the request */ rc = gatt_status_irq_proceed; } break; } /* Send GATT Response for the received request */ GattAccessRsp(p_ind->cid, p_ind->handle, rc, length, value); }
extern void HeartRateHandleAccessWrite(GATT_ACCESS_IND_T *p_ind) { uint8 *p_value = p_ind->value; gatt_client_config client_config; sys_status rc = sys_status_success; switch(p_ind->handle) { /* Heart Rate measurement characteristic client configuration is being * written */ case HANDLE_HEART_RATE_MEASUREMENT_C_CFG: { client_config = BufReadUint16(&p_value); /* Client Configuration is bit field value so ideally bitwise * comparison should be used but since the application supports only * notifications, direct comparison is being used. */ if((client_config == gatt_client_config_notification) || (client_config == gatt_client_config_none)) { /* Store the new client configuration */ g_hr_serv_data.hr_meas_client_config = client_config; /* Write Heart Rate Measurement Client configuration to NVM if * the device is bonded. */ if(AppIsDeviceBonded()) { Nvm_Write((uint16*)&client_config, sizeof(client_config), g_hr_serv_data.nvm_offset + HR_NVM_HR_MEAS_CLIENT_CONFIG_OFFSET); } /* Start sending the HR measurement notifications if they are * not being sent currently. */ StartSendingHRMeasurements(); } else { /* INDICATION or RESERVED */ /* Return Error as only Notifications are supported */ rc = gatt_status_desc_improper_config; } break; } /* Heart Rate Control point is being written */ case HANDLE_HEART_RATE_CONTROL_POINT: { /* Extract the written value */ uint8 cntl_point_val = BufReadUint8(&p_value); /* Check if the HR client has reset the expended energy. */ if(cntl_point_val == hr_control_point_reset_energy) { /* Yes, it has. Make a note of it. */ g_hr_serv_data.energy_expended = 0; g_hr_serv_data.reset_energy_expended_received = TRUE; } else /* Reserved Value */ { rc = gatt_status_desc_improper_config; } break; } default: { /* Write is not permitted on any other characteristic/attribute */ rc = gatt_status_write_not_permitted; break; } } /* Send ACCESS RESPONSE */ GattAccessRsp(p_ind->cid, p_ind->handle, rc, 0, NULL); }
/*-----------------------------------------------------------------------------* * NAME * OtaHandleAccessWrite * * DESCRIPTION * Handle write-access requests from the Host where the characteristic * handle falls within the range of the OTAU Application Service. * * PARAMETERS * p_ind [in] Write request data * * RETURNS * Nothing *----------------------------------------------------------------------------*/ void OtaHandleAccessWrite(GATT_ACCESS_IND_T *p_ind) { sys_status rc = gatt_status_write_not_permitted; /* Function status */ switch (p_ind->handle) { case HANDLE_CSR_OTA_CURRENT_APP: { /* Set the index of the current application */ const uint8 app_id = p_ind->value[0]; /* New application index */ #if defined(USE_STATIC_RANDOM_ADDRESS) || defined(USE_RESOLVABLE_RANDOM_ADDRESS) BD_ADDR_T bd_addr; /* Bluetooth Device address */ GapGetRandomAddress(&bd_addr); #endif /* USE_STATIC_RANDOM_ADDRESS || USE_RESOLVABLE_RANDOM_ADDRESS */ rc = OtaWriteCurrentApp(app_id, IS_BONDED, &(CONN_HOST_ADDR), LINK_DIVERSIFIER, #if defined(USE_STATIC_RANDOM_ADDRESS) || defined(USE_RESOLVABLE_RANDOM_ADDRESS) &bd_addr, #else NULL, #endif CONNECTION_IRK, GattServiceChangedIndActive()); if (rc != sys_status_success) { /* Sanitise the result. If OtaWriteCurrentApp fails it will be * because one or more of the supplied parameters was invalid. */ rc = gatt_status_invalid_param_value; } } break; case HANDLE_CSR_OTA_READ_CS_BLOCK: /* Set the offset and length of a block of CS to read */ /* Validate input (expecting uint16[2]) */ if (p_ind->size_value == WORDS_TO_BYTES(sizeof(uint16[2]))) { const uint16 offset = BufReadUint16(&p_ind->value); data_transfer_data_length = (uint8)BufReadUint16(&p_ind->value); rc = readCsBlock(offset, data_transfer_data_length, data_transfer_memory); } else { rc = gatt_status_invalid_length; } break; case HANDLE_CSR_OTA_DATA_TRANSFER_CLIENT_CONFIG: { /* Modify the Data Transfer Client Characteristic Configuration * Descriptor */ const uint16 client_config = BufReadUint16(&p_ind->value); /* Requested descriptor value */ if((client_config == gatt_client_config_notification) || (client_config == gatt_client_config_none)) { data_transfer_configuration[0] = client_config; rc = sys_status_success; } else { /* INDICATION or RESERVED */ /* Return error as only notifications are supported */ rc = gatt_status_desc_improper_config; } } break; default: /* Writing to this characteristic is not permitted */ break; } GattAccessRsp(p_ind->cid, p_ind->handle, rc, 0, NULL); /* Perform any follow-up actions */ if (rc == sys_status_success) { switch (p_ind->handle) { case HANDLE_CSR_OTA_READ_CS_BLOCK: /* If this write action was to trigger a CS key read and * notifications have been enabled send the result now. */ if (data_transfer_configuration[0] == gatt_client_config_notification) { GattCharValueNotification(CONNECTION_CID, HANDLE_CSR_OTA_DATA_TRANSFER, data_transfer_data_length, data_transfer_memory); } break; case HANDLE_CSR_OTA_CURRENT_APP: /* If a new application index has been requested disconnect from * the Host and reset the device to run the new application. */ /* Record that the GATT database may be different after the * device has reset. */ GattOnOtaSwitch(); /* When the disconnect confirmation comes in, call OtaReset() */ g_ota_reset_required = TRUE; /* Disconnect from the Host */ GattDisconnectReq(CONNECTION_CID); break; default: /* No follow up action necessary */ break; } } }
extern void HidHandleAccessWrite(GATT_ACCESS_IND_T *p_ind) { uint16 client_config, input_rpt_hndl; uint8 *p_value = p_ind->value; sys_status rc = sys_status_success; bool update_input_report_config = FALSE; switch(p_ind->handle) { case HANDLE_HID_INPUT_RPT_CLIENT_CONFIG: case HANDLE_HID_BOOT_INPUT_RPT_CLIENT_CONFIG: { /* Copy the value being written by the remote device to a local * variable */ client_config = BufReadUint16(&p_value); /* Client Configuration is bit field value so ideally bitwise * comparison should be used but since the application supports only * notifications, direct comparison is being used. */ if((client_config == gatt_client_config_notification) || (client_config == gatt_client_config_none)) { /* CCCD of input report and boot input report have different * offsets at which their values are written into NVM */ uint16 offset; if(p_ind->handle == HANDLE_HID_INPUT_RPT_CLIENT_CONFIG) { hid_data.input_client_config = client_config; /* If Report mode set, update Input Report Configuration * for Report mode */ if(hid_data.report_mode) { update_input_report_config = TRUE; input_rpt_hndl = HANDLE_HID_INPUT_REPORT; } offset = hid_data.nvm_offset+ HID_NVM_INPUT_RPT_CLIENT_CONFIG_OFFSET; } else /* Input Boot Report Client Configuration */ { hid_data.input_boot_client_config = client_config; /* If Report mode not set, update Input Report Configuration * for Boot mode */ if(!hid_data.report_mode) { update_input_report_config = TRUE; input_rpt_hndl = HANDLE_HID_BOOT_INPUT_REPORT; } offset = hid_data.nvm_offset+ HID_NVM_INPUT_BOOT_RPT_CLIENT_CONFIG_OFFSET; } /* Write HID Input Report Client configuration or HID Input Boot * Report Client configuration to NVM if the devices are bonded. */ Nvm_Write(&client_config, sizeof(gatt_client_config), offset); /* Device shall only trigger Input reports (boot / main) if * notifications are enabled for characteristic corresponding * to the current protocol mode. */ if(update_input_report_config) { updateInputReportConfiguration(client_config, input_rpt_hndl); } } else { /* INDICATION or RESERVED */ /* Return Error as only Notifications are supported for * mouse application */ rc = gatt_status_desc_improper_config; } } break; case HANDLE_HID_CONTROL_POINT: { /* Copy the value being written by the remote device to a local * variable. */ uint8 control_op = BufReadUint8(&p_value); handleControlPointUpdate(control_op); } break; case HANDLE_HID_PROTOCOL_MODE: { /* Copy the value being written by the remote device to a local * variable. */ uint8 mode = BufReadUint8(&p_value); /* Update the protocol mode only if the value being written is not * the same as the already existing protocol mode. */ hid_protocol_mode old_mode = hid_data.report_mode; if(((mode == hid_boot_mode) || (mode == hid_report_mode)) && (mode != old_mode)) /* Change of Protocol Mode */ { if(mode == hid_boot_mode) { client_config = hid_data.input_boot_client_config; input_rpt_hndl = HANDLE_HID_BOOT_INPUT_REPORT; } else { client_config = hid_data.input_client_config; input_rpt_hndl = HANDLE_HID_INPUT_REPORT; } hid_data.report_mode = mode; /* After the protocol mode is updated, update the service * notification status from the notifications * on CCCD of the respective mode handles. */ updateInputReportConfiguration(client_config, input_rpt_hndl); } /* Else Ignore the value */ } break; case HANDLE_HID_FEATURE_REPORT: { /* Copy the value being written by the remote device to a local * variable. */ sensor_resolution resolution = BufReadUint8(&p_value); /* Update the mouse resolution. This is an example feature report. * Customers can define vendor specific feature reports and * implement their handling as per the requirements */ if(!SetSensorResolution(resolution)) { rc = gatt_status_att_val_oor; } } break; default: { /* No more IRQ characteristics in HID service */ rc = gatt_status_write_not_permitted; } break; } /* Send ACCESS RESPONSE */ GattAccessRsp(p_ind->cid, p_ind->handle, rc, 0, NULL); }
extern void HidHandleAccessRead(GATT_ACCESS_IND_T *p_ind) { uint16 length = 0; uint8 *p_value = NULL; uint8 val[2]; sys_status rc = sys_status_success; switch(p_ind->handle) { case HANDLE_HID_INPUT_RPT_CLIENT_CONFIG: { p_value = val; BufWriteUint16(&p_value, hid_data.input_client_config); /* CCCD value of a characteristic is 2 bytes in length. */ length = 2; /* BufWriteUint16 will have incremented p_value. Revert it back * to point to val. */ p_value -= length; } break; case HANDLE_HID_BOOT_INPUT_RPT_CLIENT_CONFIG: { p_value = val; BufWriteUint16(&p_value, hid_data.input_boot_client_config); /* CCCD value of a characteristic is 2 bytes in length. */ length = 2; /* BufWriteUint16 will have incremented p_value. Revert it back * to point to val. */ p_value -= length; } break; case HANDLE_HID_INPUT_REPORT: { /* The input report array is maintained by mouse_hw.c. Get a * reference to it. */ p_value = GetMouseReport(HID_INPUT_REPORT_ID); length = ATTR_LEN_HID_INPUT_REPORT; } break; case HANDLE_HID_BOOT_INPUT_REPORT: { /* The input report array is maintained by mouse_hw.c. Get a * reference to it. */ p_value = GetMouseReport(HID_INPUT_REPORT_ID); length = ATTR_LEN_HID_BOOT_INPUT_REPORT; } break; case HANDLE_HID_PROTOCOL_MODE: { p_value = val; /* Get the current protocol mode. */ p_value[0] = hid_data.report_mode; length = ATTR_LEN_HID_PROTOCOL_MODE; } break; case HANDLE_HID_FEATURE_REPORT: { p_value = val; val[0] = GetSensorResolution(); /* Feature report value is 1 byte in length */ length = ATTR_LEN_HID_FEATURE_REPORT; } break; default: { /* Let firmware handle the request */ rc = gatt_status_irq_proceed; } break; } GattAccessRsp(p_ind->cid, p_ind->handle, rc, length, p_value); }
extern void HeartRateHandleAccessWrite(GATT_ACCESS_IND_T *p_ind) { uint8 *p_value = p_ind->value; gatt_client_config client_config; sys_status rc = sys_status_success; switch(p_ind->handle) { /* Heart Rate measurement characteristic client configuration is being * written */ case HANDLE_EEG_MEASUREMENT_C_CFG: { client_config = BufReadUint16(&p_value); /* Client Configuration is bit field value so ideally bitwise * comparison should be used but since the application supports only * notifications, direct comparison is being used. */ if((client_config == gatt_client_config_notification) || (client_config == gatt_client_config_none)) { /* Store the new client configuration */ g_eeg_serv_data.hr_meas_client_config = client_config; /* Write Heart Rate Measurement Client configuration to NVM if * the device is bonded. */ if(AppIsDeviceBonded()) { Nvm_Write((uint16*)&client_config, sizeof(client_config), g_eeg_serv_data.nvm_offset + HR_NVM_HR_MEAS_CLIENT_CONFIG_OFFSET); } /* Start sending the HR measurement notifications if they are * not being sent currently. */ StartSendingHRMeasurements(); } else { /* INDICATION or RESERVED */ /* Return Error as only Notifications are supported */ rc = gatt_status_desc_improper_config; } break; } /* EEG channels Control point is being written */ case HANDLE_EEG_CHANNELS: { /* Extract the written value */ g_eeg_serv_data.channel_map = BufReadUint16(&p_value); DebugWriteString("\n\rChannel map updated"); break; } case HANDLE_EEG_ACQUISITION_RATE: { g_eeg_serv_data.acquisition_rate = BufReadUint16(&p_value); TimerDelete(g_eeg_serv_data.acq_tmr); g_eeg_serv_data.acq_tmr = TimerCreate((uint32) (1000000/g_eeg_serv_data.acquisition_rate), TRUE, acquireData); DebugWriteString("\n\rAcq Rate changed"); break; } default: { /* Write is not permitted on any other characteristic/attribute */ rc = gatt_status_write_not_permitted; break; } } /* Send ACCESS RESPONSE */ GattAccessRsp(p_ind->cid, p_ind->handle, rc, 0, NULL); }