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?

Related