Exemple #1
0
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;
}
Exemple #2
0
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;
}