/**@brief Function for setting security requirements of a characteristic. * * @param[in] level required security level. * @param[out] p_perm Characteristic security requirements. * * @return encoded security level and security mode. */ static inline void set_security_req(security_req_t level, ble_gap_conn_sec_mode_t * p_perm) { BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(p_perm); switch (level) { case SEC_NO_ACCESS: BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(p_perm); break; case SEC_OPEN: BLE_GAP_CONN_SEC_MODE_SET_OPEN(p_perm); break; case SEC_JUST_WORKS: BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(p_perm); break; case SEC_MITM: BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(p_perm); break; case SEC_SIGNED: BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(p_perm); break; case SEC_SIGNED_MITM: BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(p_perm); break; } return; }
error_t custom_add_in_characteristic(uint16_t service_handle, ble_uuid_t *p_uuid, uint8_t properties, SecurityManager::SecurityMode_t requiredSecurity, uint8_t *p_data, uint16_t length, uint16_t max_length, const uint8_t *userDescriptionDescriptorValuePtr, uint16_t userDescriptionDescriptorValueLen, bool readAuthorization, bool writeAuthorization, ble_gatts_char_handles_t *p_char_handle) { /* Characteristic metadata */ ble_gatts_attr_md_t cccd_md; ble_gatt_char_props_t char_props; memcpy(&char_props, &properties, 1); if (char_props.notify || char_props.indicate) { /* Notification requires cccd */ memclr_( &cccd_md, sizeof(ble_gatts_attr_md_t)); cccd_md.vloc = BLE_GATTS_VLOC_STACK; BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm); } ble_gatts_char_md_t char_md = {0}; char_md.char_props = char_props; char_md.p_cccd_md = (char_props.notify || char_props.indicate) ? &cccd_md : NULL; if ((userDescriptionDescriptorValueLen > 0) && (userDescriptionDescriptorValuePtr != NULL)) { char_md.p_char_user_desc = const_cast<uint8_t *>(userDescriptionDescriptorValuePtr); char_md.char_user_desc_max_size = userDescriptionDescriptorValueLen; char_md.char_user_desc_size = userDescriptionDescriptorValueLen; } /* Attribute declaration */ ble_gatts_attr_md_t attr_md = {0}; attr_md.rd_auth = readAuthorization; attr_md.wr_auth = writeAuthorization; attr_md.vloc = BLE_GATTS_VLOC_STACK; /* Always set variable size */ attr_md.vlen = 1; if (char_props.read || char_props.notify || char_props.indicate) { switch (requiredSecurity) { case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK : BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); break; case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM : BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.read_perm); break; case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM : BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.read_perm); break; case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM : BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(&attr_md.read_perm); break; case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM : BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(&attr_md.read_perm); break; default: break; }; } if (char_props.write || char_props.write_wo_resp) { switch (requiredSecurity) { case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK : BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); break; case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM : BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.write_perm); break; case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM : BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.write_perm); break; case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM : BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(&attr_md.write_perm); break; case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM : BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(&attr_md.write_perm); break; default: break; }; } ble_gatts_attr_t attr_char_value = {0}; attr_char_value.p_uuid = p_uuid; attr_char_value.p_attr_md = &attr_md; attr_char_value.init_len = length; attr_char_value.max_len = max_length; attr_char_value.p_value = p_data; ASSERT_STATUS ( sd_ble_gatts_characteristic_add(service_handle, &char_md, &attr_char_value, p_char_handle)); return ERROR_NONE; }