static uint32_t uuid_list_sized_encode(const ble_advdata_uuid_list_t * p_uuid_list, uint8_t adv_type, uint8_t uuid_size, uint8_t * p_encoded_data, uint8_t * p_len) { int i; bool is_heading_written = false; uint8_t start_pos = *p_len; for (i = 0; i < p_uuid_list->uuid_cnt; i++) { uint32_t err_code; uint8_t encoded_size; ble_uuid_t uuid = p_uuid_list->p_uuids[i]; // Find size err_code = sd_ble_uuid_encode(&uuid, &encoded_size, NULL); if (err_code != NRF_SUCCESS) { return err_code; } // Check size if (encoded_size == uuid_size) { uint8_t heading_bytes = (is_heading_written) ? 0 : 2; // Check for buffer overflow if (*p_len + encoded_size + heading_bytes > BLE_GAP_ADV_MAX_SIZE) { return NRF_ERROR_DATA_SIZE; } if (!is_heading_written) { // Write AD structure heading (*p_len)++; p_encoded_data[(*p_len)++] = adv_type; is_heading_written = true; } // Write UUID err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &p_encoded_data[*p_len]); if (err_code != NRF_SUCCESS) { return err_code; } (*p_len) += encoded_size; } } if (is_heading_written) { // Write length p_encoded_data[start_pos] = (*p_len) - (start_pos + 1); } return NRF_SUCCESS; }
uint32_t conn_mw_ble_uuid_encode(uint8_t const * const p_rx_buf, uint32_t rx_buf_len, uint8_t * const p_tx_buf, uint32_t * const p_tx_buf_len) { SER_ASSERT_NOT_NULL(p_rx_buf); SER_ASSERT_NOT_NULL(p_tx_buf); SER_ASSERT_NOT_NULL(p_tx_buf_len); uint8_t raw_uuid[16]; uint8_t uuid_len = sizeof (raw_uuid); uint8_t * p_uuid_len = &uuid_len; uint8_t * p_raw_uuid = raw_uuid; ble_uuid_t uuid; ble_uuid_t * p_uuid = &uuid; uint32_t err_code = NRF_SUCCESS; uint32_t sd_err_code; err_code = ble_uuid_encode_req_dec(p_rx_buf, rx_buf_len, &p_uuid, &p_uuid_len, &p_raw_uuid); SER_ASSERT(err_code == NRF_SUCCESS, err_code); sd_err_code = sd_ble_uuid_encode(p_uuid, p_uuid_len, p_raw_uuid); err_code = ble_uuid_encode_rsp_enc(sd_err_code, p_tx_buf, p_tx_buf_len, uuid_len, p_raw_uuid); SER_ASSERT(err_code == NRF_SUCCESS, err_code); return err_code; }
/**@brief Function for decoding a command packet with RPC_SD_BLE_UUID_ENCODE opcode. * * This function will decode the command, call the BLE Stack API, and also send command response * to the peer through the transport layer. * * @param[in] p_command The encoded structure that needs to be decoded and passed on * to the BLE Stack API. * @param[in] command_len The length of the encoded command read from transport layer. * * @retval NRF_SUCCESS If the decoding of the command was successful, the SoftDevice * API was called, and the command response was sent to peer, * otherwise an error code. * @retval NRF_ERROR_INVALID_LENGTH If the content length of the packet is not conforming to the * codec specification. */ static uint32_t uuid_encode_handle(uint8_t * p_command, uint32_t command_len) { ble_uuid_t uuid_data; uint32_t err_code; // uuid can be up to 16 bytes, and 1 byte length field uint8_t response_buffer[sizeof(ble_uuid128_t) + sizeof(uint8_t)]; uint32_t index = 0; ble_uuid_t * p_uuid_data = &uuid_data; uint8_t * p_length = &(response_buffer[0]); uint8_t * p_result_buffer = &(response_buffer[1]); // UUID field present. if (p_command[index++] == RPC_BLE_FIELD_PRESENT) { RPC_DECODER_LENGTH_CHECK(command_len, index, SD_BLE_UUID_ENCODE); uuid_data.uuid = uint16_decode(&(p_command[index])); index += sizeof(uint16_t); RPC_DECODER_LENGTH_CHECK(command_len, index, SD_BLE_UUID_ENCODE); uuid_data.type = p_command[index++]; } else { RPC_DECODER_LENGTH_CHECK(command_len, index, SD_BLE_UUID_ENCODE); p_uuid_data = NULL; } // Length field not present. if (p_command[index++] == RPC_BLE_FIELD_NOT_PRESENT) { RPC_DECODER_LENGTH_CHECK(command_len, index, SD_BLE_UUID_ENCODE); p_length = NULL; } // Result buffer not present. if (p_command[index++] == RPC_BLE_FIELD_NOT_PRESENT) { p_result_buffer = NULL; } RPC_DECODER_LENGTH_CHECK(command_len, index, SD_BLE_UUID_ENCODE); err_code = sd_ble_uuid_encode(p_uuid_data, p_length, p_result_buffer); if (err_code == NRF_SUCCESS) { return ble_rpc_cmd_resp_data_send(SD_BLE_UUID_ENCODE, NRF_SUCCESS, response_buffer, response_buffer[0] + sizeof(uint8_t)); } return ble_rpc_cmd_resp_send(SD_BLE_UUID_ENCODE, err_code); }
/**@brief Function for adding Report Map characteristics. * * @param[in] p_hids HID Service structure. * @param[in] p_hids_init Service initialization structure. * * @return NRF_SUCCESS on success, otherwise an error code. */ static uint32_t rep_map_char_add(ble_hids_t * p_hids, const ble_hids_init_t * p_hids_init) { uint32_t err_code; ble_gatts_char_md_t char_md; ble_gatts_attr_t attr_char_value; ble_uuid_t ble_uuid; ble_gatts_attr_md_t attr_md; // Add Report Map characteristic memset(&char_md, 0, sizeof(char_md)); char_md.char_props.read = 1; char_md.p_char_user_desc = NULL; char_md.p_char_pf = NULL; char_md.p_user_desc_md = NULL; char_md.p_cccd_md = NULL; char_md.p_sccd_md = NULL; BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_REPORT_MAP_CHAR); memset(&attr_md, 0, sizeof(attr_md)); attr_md.read_perm = p_hids_init->rep_map.security_mode.read_perm; attr_md.write_perm = p_hids_init->rep_map.security_mode.write_perm; attr_md.vloc = BLE_GATTS_VLOC_STACK; attr_md.rd_auth = 0; attr_md.wr_auth = 0; attr_md.vlen = 1; memset(&attr_char_value, 0, sizeof(attr_char_value)); attr_char_value.p_uuid = &ble_uuid; attr_char_value.p_attr_md = &attr_md; attr_char_value.init_len = p_hids_init->rep_map.data_len; attr_char_value.init_offs = 0; attr_char_value.max_len = p_hids_init->rep_map.data_len; attr_char_value.p_value = p_hids_init->rep_map.p_data; err_code = sd_ble_gatts_characteristic_add(p_hids->service_handle, &char_md, &attr_char_value, &p_hids->rep_map_handles); if (err_code != NRF_SUCCESS) { return err_code; } if (p_hids_init->rep_map.ext_rep_ref_num != 0 && p_hids_init->rep_map.p_ext_rep_ref == NULL) { return NRF_ERROR_INVALID_PARAM; } for (int i = 0; i < p_hids_init->rep_map.ext_rep_ref_num; ++i) { uint8_t encoded_rep_ref[sizeof(ble_uuid128_t)]; uint8_t encoded_rep_ref_len; // Add External Report Reference descriptor BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_EXTERNAL_REPORT_REF_DESCR); memset(&attr_md, 0, sizeof(attr_md)); BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.write_perm); attr_md.vloc = BLE_GATTS_VLOC_STACK; attr_md.rd_auth = 0; attr_md.wr_auth = 0; attr_md.vlen = 0; err_code = sd_ble_uuid_encode(&p_hids_init->rep_map.p_ext_rep_ref[i], &encoded_rep_ref_len, encoded_rep_ref); if (err_code != NRF_SUCCESS) { return err_code; } memset(&attr_char_value, 0, sizeof(attr_char_value)); attr_char_value.p_uuid = &ble_uuid; attr_char_value.p_attr_md = &attr_md; attr_char_value.init_len = encoded_rep_ref_len; attr_char_value.init_offs = 0; attr_char_value.max_len = attr_char_value.init_len; attr_char_value.p_value = encoded_rep_ref; err_code = sd_ble_gatts_descriptor_add(p_hids->rep_map_handles.value_handle, &attr_char_value, &p_hids->rep_map_ext_rep_ref_handle); if (err_code != NRF_SUCCESS) { return err_code; } } return NRF_SUCCESS; }
static uint32_t uuid_list_sized_encode(const ble_advdata_uuid_list_t * p_uuid_list, uint8_t adv_type, uint8_t uuid_size, uint8_t * p_encoded_data, uint16_t * p_offset, uint16_t max_size) { int i; bool is_heading_written = false; uint16_t start_pos = *p_offset; uint16_t length; for (i = 0; i < p_uuid_list->uuid_cnt; i++) { uint32_t err_code; uint8_t encoded_size; ble_uuid_t uuid = p_uuid_list->p_uuids[i]; // Find encoded uuid size. err_code = sd_ble_uuid_encode(&uuid, &encoded_size, NULL); if (err_code != NRF_SUCCESS) { return err_code; } // Check size. if (encoded_size == uuid_size) { uint8_t heading_bytes = (is_heading_written) ? 0 : ADV_AD_DATA_OFFSET; // Check for buffer overflow if (((*p_offset) + encoded_size + heading_bytes) > max_size) { return NRF_ERROR_DATA_SIZE; } if (!is_heading_written) { // Write AD structure heading. *p_offset += ADV_LENGTH_FIELD_SIZE; p_encoded_data[*p_offset] = adv_type; *p_offset += ADV_AD_TYPE_FIELD_SIZE; is_heading_written = true; } // Write UUID. err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &p_encoded_data[*p_offset]); if (err_code != NRF_SUCCESS) { return err_code; } *p_offset += encoded_size; } } if (is_heading_written) { // Write length. length = (*p_offset) - (start_pos + ADV_LENGTH_FIELD_SIZE); // There is only 1 byte intended to encode length if(length > 0x00FF) { return NRF_ERROR_DATA_SIZE; } p_encoded_data[start_pos] = (uint8_t)length; } return NRF_SUCCESS; }