This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Custom GAP Service with User Descriptions (UUID 0x2901)

To enable comparability with an existing client, I'm attempting to configure the nRF51822 to provide a GAP service that includes user description descriptors (UUID 0x2901) for both the device name and appearance characteristics.

I have tried to accomplish this in two different ways:

  1. Adding an additional user description descriptor after calling sd_ble_gap_device_name_set()

void gap_params_init(void) {
    uint32_t err_code;
    ble_gap_conn_sec_mode_t sec_mode;

    ble_gatts_attr_t attr;
    ble_gatts_attr_md_t attr_md;
    ble_uuid_t uuid;

    uint16_t desc_handle;

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
    
    err_code = sd_ble_gap_device_name_set(&sec_mode, (uint8_t *)deviceName, strlen(deviceName));
    APP_ERROR_CHECK(err_code);

	/* We now add a descriptor attribute for the user description of the device
	 * name. Here we configure its attribute's metadata to allow open reads but
	 * no writes. */
	memset(&attr_md, 0, sizeof(attr_md));
	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
	BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.write_perm);
	attr_md.vloc = BLE_GATTS_VLOC_STACK;

	/* Indicate the that attribute is a user description descriptor */
	BLE_UUID_BLE_ASSIGN(uuid, BLE_UUID_DESCRIPTOR_CHAR_USER_DESC);

	/* Configure the value of the attribute. */
	memset(&attr, 0, sizeof(attr));
	attr.p_uuid = &uuid;
	attr.p_attr_md = &attr_md;
	attr.init_len = 11;
	attr.init_offs = 0;
	attr.max_len = 11;
	attr.p_value = (uint8_t *)"Device Name";

    err_code = sd_ble_gatts_descriptor_add(BLE_GATT_HANDLE_INVALID, &attr, &desc_handle);
    APP_ERROR_CHECK(err_code);

In this case, the sd_ble_gatts_descriptor_add(BLE_GATT_HANDLE_INVALID, attr, &desc_handle) call returns NRF_ERROR_FORBIDDEN.

  1. Creating the GAP service myself:

void gap_params_init(void) {
    uint32_t err_code;

    ble_gatts_char_md_t char_md;
    ble_gatts_attr_t attr;
    ble_gatts_attr_md_t attr_md;
    ble_uuid_t uuid;

    uint16_t service_handle;
    uint16_t char_handle;

    /* Create the GAP service */
    BLE_UUID_BLE_ASSIGN(uuid, BLE_UUID_GAP);

    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &uuid, &service_handle);
    APP_ERROR_CHECK(err_code);

    /* We add two characteristics to the GAP serivce: */

	/* The first characteristic is the device name, which should be read-able.
	 * Here, we use the characteristics metadata to make the device name
	 * characteristic readable.  We also add a user description field stating
	 * what the characteristic represents. */
	memset(&char_md, 0, sizeof(char_md));
	char_md.char_props.read = 1;
	char_md.p_char_user_desc = (uint8_t *)"Device Name";
	char_md.char_user_desc_max_size = 11;
	char_md.char_user_desc_size = 11;
	char_md.p_user_desc_md = NULL;
	char_md.p_char_pf = NULL;
	char_md.p_cccd_md = NULL;
	char_md.p_sccd_md = NULL;

	/* The attribute is the part of the characteristic that holds data, in this
	 * case, the device's actual name.  Here we configure its attribute's
	 * metadata to allow open reads but no writes. */
	memset(&attr_md, 0, sizeof(attr_md));
	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
	BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.write_perm);
	attr_md.vloc = BLE_GATTS_VLOC_STACK;

	/* Set the UUID of the device name attribute correctly */
	BLE_UUID_BLE_ASSIGN(uuid, BLE_UUID_GAP_CHARACTERISTIC_DEVICE_NAME);

	/* Configure the device name attribute itself */
	memset(&attr, 0, sizeof(attr));
	attr.p_uuid = &uuid;
	attr.p_attr_md = &attr_md;
	attr.init_len = strlen(deviceName);
	attr.init_offs = 0;
	attr.max_len = strlen(deviceName);
	attr.p_value = (uint8_t *)deviceName;

	/* Finally, add the device name characteristic to the GAP service */
	err_code = sd_ble_gatts_characteristic_add(service_handle, &char_md, &attr, &char_handle);
	APP_ERROR_CHECK(err_code);

        /* Appearance characteristic would be added here */

In this case, the sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &uuid, &service_handle) call returns NRF_ERROR_FORBIDDEN.

Can anyone suggest how to solve this problem?

Parents
  • Hi Kyle,

    I can answer your questions:

    1) Adding an additional user description descriptor after calling

    This won't work because the GAP and GATT services are prepopulated by the stack when you initialize the SoftDevice, and therefore you won't be able to add any attributes to neither of them.

    2) Creating the GAP service myself:

    This won't work either because you are trying to use certain UUIDs that are considered reserved for the SoftDevice, among them the GAP and GATT UUIDs (since those services, as mentioned, are always by default present and populated and controlled by the stack).

    Unfortunately there is no way in today's SD to achieve what you want. Unless you can modify the existing client, your best bet is to log an issue with support asking for this feature (ability to add optional descriptors in the GAP/GATT services).

    Sorry about this.

    Carles

Reply
  • Hi Kyle,

    I can answer your questions:

    1) Adding an additional user description descriptor after calling

    This won't work because the GAP and GATT services are prepopulated by the stack when you initialize the SoftDevice, and therefore you won't be able to add any attributes to neither of them.

    2) Creating the GAP service myself:

    This won't work either because you are trying to use certain UUIDs that are considered reserved for the SoftDevice, among them the GAP and GATT UUIDs (since those services, as mentioned, are always by default present and populated and controlled by the stack).

    Unfortunately there is no way in today's SD to achieve what you want. Unless you can modify the existing client, your best bet is to log an issue with support asking for this feature (ability to add optional descriptors in the GAP/GATT services).

    Sorry about this.

    Carles

Children
Related