Esempio n. 1
0
static uint32_t name_encode(const ble_advdata_t * p_advdata,
                            uint8_t *             p_encoded_data,
                            uint8_t *             p_len)
{
    uint32_t err_code;
    uint16_t name_length = BLE_GAP_ADV_MAX_SIZE - (2 + *p_len);
    uint8_t  adv_data_format;

    // Get GAP device name
    err_code = sd_ble_gap_device_name_get(&p_encoded_data[*p_len + 2], &name_length);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    // Compute length and type of name field
    if ((p_advdata->short_name_len != 0) && (name_length > p_advdata->short_name_len))
    {
        name_length     = p_advdata->short_name_len;
        adv_data_format = BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME;
    }
    else
    {
        adv_data_format = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME;
    }
    
    // Complete name field in encoded data
    p_encoded_data[(*p_len)++] = name_length + 1;
    p_encoded_data[(*p_len)++] = adv_data_format;
    (*p_len) += name_length;
    
    return NRF_SUCCESS;
}
Esempio n. 2
0
uint32_t conn_mw_ble_gap_device_name_get(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);

   uint32_t err_code = NRF_SUCCESS;
   uint32_t sd_err_code;

   uint8_t   dev_name[BLE_GAP_DEVNAME_MAX_LEN];
   uint8_t * p_dev_name = dev_name;

   uint16_t   len;
   uint16_t * p_len = &len;

   err_code = ble_gap_device_name_get_req_dec(p_rx_buf, rx_buf_len, &p_dev_name, &p_len);
   SER_ASSERT(err_code == NRF_SUCCESS, err_code);

   sd_err_code = sd_ble_gap_device_name_get(p_dev_name, p_len);

   err_code = ble_gap_device_name_get_rsp_enc(sd_err_code, p_dev_name, p_len, p_tx_buf, p_tx_buf_len);
   SER_ASSERT(err_code == NRF_SUCCESS, err_code);

   return err_code;
}
Esempio n. 3
0
ble_error_t nRF5xGap::getDeviceName(uint8_t *deviceName, unsigned *lengthP)
{
    if (sd_ble_gap_device_name_get(deviceName, (uint16_t *)lengthP) == NRF_SUCCESS) {
        return BLE_ERROR_NONE;
    } else {
        return BLE_ERROR_PARAM_OUT_OF_RANGE;
    }
}
Esempio n. 4
0
/**@brief     Function for the Advertising functionality initialization.
 *
 * @details   Encodes the required advertising data and passes it to the stack.
 *            The advertising data encoded here is specific for DFU. 
 *            Setting advertising data can by done by calling @ref ble_advdata_set.
 */
static uint32_t advertising_init(uint8_t adv_flags)
{
    uint32_t    err_code;
    uint16_t    len_advdata                 = 9;
    uint16_t    max_device_name_length      = MAX_ADV_DATA_LENGTH - len_advdata;
    uint16_t    actual_device_name_length   = max_device_name_length;

    uint8_t     p_encoded_advdata[MAX_ADV_DATA_LENGTH];
    
    // Encode flags.
    p_encoded_advdata[0]                    = 0x2;
    p_encoded_advdata[1]                    = BLE_GAP_AD_TYPE_FLAGS;
    p_encoded_advdata[2]                    = adv_flags;
    
    // Encode 'more available' uuid list.
    p_encoded_advdata[3]                    = 0x3;
    p_encoded_advdata[4]                    = BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE;
    p_encoded_advdata[5]                    = LSB_16(BLE_DFU_SERVICE_UUID);
    p_encoded_advdata[6]                    = MSB_16(BLE_DFU_SERVICE_UUID);

    // Get GAP device name and length
    err_code = sd_ble_gap_device_name_get(&p_encoded_advdata[9], &actual_device_name_length);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }
    
    // Set GAP device in advertising data.
    if (actual_device_name_length <= max_device_name_length)
    {
        p_encoded_advdata[7]                = actual_device_name_length + 1; // (actual_length + ADV_AD_TYPE_FIELD_SIZE(1))
        p_encoded_advdata[8]                = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME;
        len_advdata                        += actual_device_name_length;
    }
    else
    {
        // Must use a shorter advertising name than the actual name of the device
        p_encoded_advdata[7]                = max_device_name_length + 1; // (length + ADV_AD_TYPE_FIELD_SIZE(1))
        p_encoded_advdata[8]                = BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME;
        len_advdata                         = MAX_ADV_DATA_LENGTH;
    }
    return sd_ble_gap_adv_data_set(p_encoded_advdata, len_advdata, NULL, 0);
}
Esempio n. 5
0
/**@brief Function for decoding a command packet with RPC_SD_BLE_GAP_DEVICE_NAME_GET opcode.
 *
 * This function will decode the command, call the BLE Stack API, and also send command response
 * to the peer through the 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 gap_device_name_get_handle(uint8_t * p_command, uint32_t command_len)
{
    uint32_t err_code;

    uint16_t dev_name_len = 0;
    uint32_t index        = 0;

    // Two bytes will be reserved for the length of device name.
    uint8_t    resp_data[BLE_GAP_DEVNAME_MAX_LEN + sizeof(dev_name_len)];
    // Pointer to the device name length variable.
    uint8_t *  p_dev_name     = &(resp_data[2]);
    // Pointer to the device name target.
    uint16_t * p_dev_name_len = &(dev_name_len);

    // Length present.
    if (p_command[index++] == RPC_BLE_FIELD_PRESENT)
    {
        RPC_DECODER_LENGTH_CHECK(command_len, index, SD_BLE_GAP_DEVICE_NAME_GET);

        // Use the remote buffer size when calling the SoftDevice to make sure the caller has
        // enough memory allocated.
        *p_dev_name_len  = uint16_decode(&p_command[index]);
        index           += sizeof(uint16_t);

        RPC_DECODER_LENGTH_CHECK(command_len, index, SD_BLE_GAP_DEVICE_NAME_GET);

        // Verify that the remote buffer size is smaller or equal to the local buffer size.
        if (*p_dev_name_len > BLE_GAP_DEVNAME_MAX_LEN)
        {
            return ble_rpc_cmd_resp_send(SD_BLE_GAP_DEVICE_NAME_GET, NRF_ERROR_INVALID_LENGTH);
        }
    }
    else
    {
        RPC_DECODER_LENGTH_CHECK(command_len, index, SD_BLE_GAP_DEVICE_NAME_GET);
        p_dev_name_len = NULL;
    }

    // Remote result buffer is present.
    if (p_command[index++] == RPC_BLE_FIELD_NOT_PRESENT)
    {
        p_dev_name = NULL;
    }

    RPC_DECODER_LENGTH_CHECK(command_len, index, SD_BLE_GAP_DEVICE_NAME_GET);

    err_code = sd_ble_gap_device_name_get(p_dev_name, p_dev_name_len);

    if (err_code == NRF_SUCCESS)
    {

        // Encode the length.
        UNUSED_VARIABLE(uint16_encode(*p_dev_name_len, &resp_data[0]));

        // Calculate the total size of the device name and the device name length bytes.
        uint16_t total_len  = uint16_decode(&resp_data[0]);
        total_len          += sizeof(total_len);

        return ble_rpc_cmd_resp_data_send(SD_BLE_GAP_DEVICE_NAME_GET,
                                          NRF_SUCCESS,
                                          resp_data,
                                          total_len);
    }

    return ble_rpc_cmd_resp_send(SD_BLE_GAP_DEVICE_NAME_GET, err_code);
}
Esempio n. 6
0
static uint32_t name_encode(const ble_advdata_t * p_advdata,
                            uint8_t *             p_encoded_data,
                            uint8_t *             p_len)
{
    uint32_t err_code;
    uint16_t rem_adv_data_len;
    uint16_t actual_length;
    uint8_t  adv_data_format;
    uint8_t  adv_offset;
    
    adv_offset = *p_len;
    
    
    // Check for buffer overflow.
    if ((adv_offset + ADV_DATA_OFFSET > BLE_GAP_ADV_MAX_SIZE) ||
       ((p_advdata->short_name_len + ADV_DATA_OFFSET) > BLE_GAP_ADV_MAX_SIZE))
    {
        return NRF_ERROR_DATA_SIZE;
    }
    actual_length = rem_adv_data_len = (BLE_GAP_ADV_MAX_SIZE - adv_offset - ADV_FLAG_OFFSET);

    // Get GAP device name and length
    err_code = sd_ble_gap_device_name_get(&p_encoded_data[adv_offset + ADV_DATA_OFFSET],
                                          &actual_length);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }
    
    // Check if device internd to use short name and it can fit available data size.
    if ((p_advdata->name_type == BLE_ADVDATA_FULL_NAME) && (actual_length <= rem_adv_data_len))
    {
        // Complete device name can fit, setting Complete Name in Adv Data.
        adv_data_format = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME;
        rem_adv_data_len = actual_length;
    }
    else
    {
        // Else short name needs to be used. Or application has requested use of short name.
        adv_data_format = BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME;
        
        // If application has set a preference on the short name size, it needs to be considered,
        // else fit what can be fit.
        if ((p_advdata->short_name_len != 0) && (p_advdata->short_name_len <= rem_adv_data_len))
        {
            // Short name fits available size.
            rem_adv_data_len = p_advdata->short_name_len;
        }
        // Else whatever can fit the data buffer will be packed.
        else
        {
            rem_adv_data_len = actual_length;
        }
    }
    
    // Complete name field in encoded data.
    p_encoded_data[adv_offset++] = rem_adv_data_len + 1;
    p_encoded_data[adv_offset++] = adv_data_format;
    (*p_len) += (rem_adv_data_len + ADV_DATA_OFFSET);
    
    return NRF_SUCCESS;
}
Esempio n. 7
0
void
simble_adv_start(void)
{
        struct ble_gap_advdata advdata = { .length = 0 };

        struct ble_gap_ad_flags flags = {
                .payload_length = 1,
                .type = BLE_GAP_AD_TYPE_FLAGS,
                .flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE,
        };
        simble_add_advdata(&flags, &advdata);

        struct ble_gap_ad_name name;
        uint16_t namelen = sizeof(advdata);
        if (sd_ble_gap_device_name_get(name.name, &namelen) != NRF_SUCCESS)
                namelen = 0;
        name.type =  BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME;
        name.payload_length = namelen;
        simble_add_advdata(&name, &advdata);

        sd_ble_gap_adv_data_set(advdata.data, advdata.length, NULL, 0);

        ble_gap_adv_params_t adv_params = {
                .type = BLE_GAP_ADV_TYPE_ADV_IND,
                .fp = BLE_GAP_ADV_FP_ANY,
                .interval = 0x400,
        };
        sd_ble_gap_adv_start(&adv_params);
        onboard_led(ONBOARD_LED_ON);
}

static void
simble_srv_tx_init(void)
{
        uint16_t srv_handle;
        ble_uuid_t srv_uuid = {.type = BLE_UUID_TYPE_BLE, .uuid = 0x1804};
        sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
                                 &srv_uuid,
                                 &srv_handle);

        ble_gatts_char_handles_t chr_handles;
        ble_gatts_char_md_t char_meta = {.char_props = {.read = 1}};
        ble_uuid_t chr_uuid = {.type = BLE_UUID_TYPE_BLE, .uuid = 0x2a07};
        ble_gatts_attr_md_t chr_attr_meta = {
                .vloc = BLE_GATTS_VLOC_STACK,
        };
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&chr_attr_meta.read_perm);
        BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&chr_attr_meta.write_perm);
        uint8_t tx_val = 0;
        ble_gatts_attr_t chr_attr = {
                .p_uuid = &chr_uuid,
                .p_attr_md = &chr_attr_meta,
                .init_offs = 0,
                .init_len = sizeof(tx_val),
                .max_len = sizeof(tx_val),
                .p_value = &tx_val,
        };
        sd_ble_gatts_characteristic_add(srv_handle,
                                        &char_meta,
                                        &chr_attr,
                                        &chr_handles);
}

/* DM requires a `app_error_handler` */
void __attribute__((weak))
app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name)
{
        app_trace_log("[simble]: err: %d, line: %d, file: %s\r\n", error_code, line_num, p_file_name);
        for (;;) {
                /* NOTHING */
        }
}

void
simble_init(const char *name)
{
        app_trace_init();
        sd_softdevice_enable(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, NULL); /* XXX assertion handler */

        ble_enable_params_t ble_params = {
#if defined(SD120)
                .gap_enable_params = {
                        .role = BLE_GAP_ROLE_PERIPH,
                },
#endif
                .gatts_enable_params = {
                        .service_changed = 1,
                },
        };
        sd_ble_enable(&ble_params);

        ble_gap_conn_sec_mode_t mode;
        BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&mode);
        sd_ble_gap_device_name_set(&mode, (const uint8_t *)name, strlen(name));

        // flash storage
        pstorage_init();

        simble_srv_tx_init();
}

uint8_t
simble_get_vendor_uuid_class(void)
{
        ble_uuid128_t vendorid = {{0x13,0xb0,0xa0,0x71,0xfe,0x62,0x4c,0x01,0xaa,0x4d,0xd8,0x03,0,0,0x0b,0xd0}};
        static uint8_t vendor_type = BLE_UUID_TYPE_UNKNOWN;

        if (vendor_type != BLE_UUID_TYPE_UNKNOWN)
                return (vendor_type);

        sd_ble_uuid_vs_add(&vendorid, &vendor_type);
        return (vendor_type);
}

void
simble_srv_register(struct service_desc *s)
{
        s->next = services;
        services = s;

        sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
                                 &s->uuid,
                                 &s->handle);

        for (int i = 0; i < s->char_count; ++i) {
                struct char_desc *c = &s->chars[i];
                ble_gatts_attr_md_t cccd_md;
                memset(&cccd_md, 0, sizeof(cccd_md));
                BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
                BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
                cccd_md.vloc = BLE_GATTS_VLOC_STACK;
                int have_write = c->write_cb != NULL;
                ble_gatts_char_md_t char_meta = {
                        .char_props = {
                                .broadcast = 0,
                                .read = 1,
                                .write_wo_resp = have_write,
                                .write = have_write,
                                .notify = c->notify,
                                .indicate = c->indicate,
                                .auth_signed_wr = have_write,
                        },
                        .p_char_user_desc = (uint8_t *)c->desc,
                        .char_user_desc_size = strlen(c->desc),
                        .char_user_desc_max_size = strlen(c->desc),
                        .p_char_pf = c->format.format != 0 ? &c->format : NULL,
                        .p_cccd_md = (c->notify || c->indicate) ? &cccd_md : NULL,
                };
                ble_gatts_attr_md_t chr_attr_meta = {
                        .vlen = 1,
                        .vloc = BLE_GATTS_VLOC_STACK,
                        .rd_auth = 1,
                        .wr_auth = 1,
                };
                BLE_GAP_CONN_SEC_MODE_SET_OPEN(&chr_attr_meta.read_perm);
                if (have_write)
                        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&chr_attr_meta.write_perm);
                else
                        BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&chr_attr_meta.write_perm);

                ble_gatts_attr_t chr_attr = {
                        .p_uuid = &c->uuid,
                        .p_attr_md = &chr_attr_meta,
                        .init_offs = 0,
                        .init_len = 0,
                        .max_len = c->length,
                };
                sd_ble_gatts_characteristic_add(s->handle,
                                                &char_meta,
                                                &chr_attr,
                                                &c->handles);
        }
}

void
simble_srv_init(struct service_desc *s, uint8_t type, uint16_t id)
{
        *s = (struct service_desc){
                .uuid = {.type = type,
                         .uuid = id},
                .char_count = 0,
        };
};

void
simble_srv_char_add(struct service_desc *s, struct char_desc *c, uint8_t type, uint16_t id, const char *desc, uint16_t length)
{
        *c = (struct char_desc){
                .uuid = {
                        .type = type,
                        .uuid = id
                },
                .desc = desc,
                .length = length,
        };
Esempio n. 8
0
static uint32_t name_encode(const ble_advdata_t * p_advdata,
                            uint8_t             * p_encoded_data,
                            uint16_t            * p_offset,
                            uint16_t              max_size)
{
    uint32_t err_code;
    uint16_t rem_adv_data_len;
    uint16_t actual_length;
    uint8_t  adv_data_format;


    // Validate parameters
    if((BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && (0 == p_advdata->short_name_len))
    {
        return NRF_ERROR_INVALID_PARAM;
    }

    // Check for buffer overflow.
    if ( (((*p_offset) + ADV_AD_DATA_OFFSET) > max_size) ||
            ( (BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) &&
              (((*p_offset) + ADV_AD_DATA_OFFSET + p_advdata->short_name_len) > max_size)))
    {
        return NRF_ERROR_DATA_SIZE;
    }

    rem_adv_data_len = max_size - (*p_offset) - ADV_AD_DATA_OFFSET;
    actual_length    = rem_adv_data_len;

    // Get GAP device name and length
    err_code = sd_ble_gap_device_name_get(&p_encoded_data[(*p_offset) + ADV_AD_DATA_OFFSET],
                                          &actual_length);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    // Check if device intend to use short name and it can fit available data size.
    if ((p_advdata->name_type == BLE_ADVDATA_FULL_NAME) && (actual_length <= rem_adv_data_len))
    {
        // Complete device name can fit, setting Complete Name in Adv Data.
        adv_data_format = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME;
    }
    else
    {
        // Else short name needs to be used. Or application has requested use of short name.
        adv_data_format = BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME;

        // If application has set a preference on the short name size, it needs to be considered,
        // else fit what can be fit.
        if ((BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) &&
                (p_advdata->short_name_len <= rem_adv_data_len))
        {
            // Short name fits available size.
            actual_length = p_advdata->short_name_len;
        }
        // Else whatever can fit the data buffer will be packed.
        else
        {
            actual_length = rem_adv_data_len;
        }
    }

    // There is only 1 byte intended to encode length which is (actual_length + ADV_AD_TYPE_FIELD_SIZE)
    if(actual_length > (0x00FF - ADV_AD_TYPE_FIELD_SIZE))
    {
        return NRF_ERROR_DATA_SIZE;
    }

    // Complete name field in encoded data.
    p_encoded_data[*p_offset]  = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE + actual_length);
    *p_offset                 += ADV_LENGTH_FIELD_SIZE;
    p_encoded_data[*p_offset]  = adv_data_format;
    *p_offset                 += ADV_AD_TYPE_FIELD_SIZE;
    *p_offset                 += actual_length;

    return NRF_SUCCESS;
}