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

Longer BLE Device name

I'm using NCS v1.5.0 to create a BLE peripheral using nRF5340-DK.

I set the device name in the prj.conf file using CONFIG_BT_DEVICE_NAME and the name shows up when BLE advertising starts (using LightBlue to monitor).

But the device name seems to be truncated (to about 11 characters).   

To try to get the full name (about 21 characters), I first tried to set CONFIG_BT_DEVICE_NAME to 32 (larger than the actual name), but that didn't have any effect.

I found an NCS BLE tutorial in DevZone (written by Haakonsh on 11 Feb 2020) that suggested the following:

#define DEVICE_NAME      CONFIG_BT_DEVICE_NAME        // Set in prj.conf
#define DEVICE_NAME_LEN  (sizeof(DEVICE_NAME) - 1)

static const struct bt_data ad[] = {
	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
        BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
};

then using this when calling bt_le_adv_start:

        err = bt_le_adv_start(BT_LE_ADV_PARAM(
                                   BT_LE_ADV_OPT_CONNECTABLE
                                 | BT_LE_ADV_OPT_ONE_TIME
                                 | BT_LE_ADV_OPT_USE_NAME,
                                 160,
                                 1600,
                                 NULL),
                              ad, ARRAY_SIZE(ad),
                              sd, ARRAY_SIZE(sd));

This call returns -22  (Illegal argument).   I traced the origin of the error to this call in hci_core.c (around line 7880):

static int le_adv_update(struct bt_le_ext_adv *adv,
			 const struct bt_data *ad, size_t ad_len,
			 const struct bt_data *sd, size_t sd_len,
			 bool ext_adv, bool scannable, bool use_name)
{
	struct bt_ad d[2] = {};
	struct bt_data data;
	size_t d_len;
	int err;

	if (use_name) {
		const char *name = bt_get_name();

		if ((ad && ad_has_name(ad, ad_len)) ||
		    (sd && ad_has_name(sd, sd_len))) {
			/* Cannot use name if name is already set */
			return -EINVAL;
		}

		data = (struct bt_data)BT_DATA(
			BT_DATA_NAME_COMPLETE,
			name, strlen(name));
	}

The call to "ad_has_name" checks if the name is specified in the arguments:

static inline bool ad_has_name(const struct bt_data *ad, size_t ad_len)
{
	size_t i;

	for (i = 0; i < ad_len; i++) {
		if (ad[i].type == BT_DATA_NAME_COMPLETE ||
		    ad[i].type == BT_DATA_NAME_SHORTENED) {
			return true;
		}
	}

	return false;
}

Since the name is specified it returns true.

The "return -EINVAL" occurs since the name was defined in the ad[] array (using BT_DATA_NAME_COMPLETE).

The comment "Cannot use name if name is already set" seems to indicate that the name has been declared/defined somewhere else, but I don't see where...

Is this check really necessary?     

I know BLE advertisement names can be longer (I have used longer ones on other systems).   Did I miss something?

Thanks!!

Parents
  • Hi

    What else is included in your advertisements? Please note that the BLE spec. only allows up to a total of 31 bytes per advertisements, where 2 bytes are overhead. If you have I.E. a UUID and/or TX power in your advertisement packet as well that usually causes the advertising name to be shortened. How many bytes does your advertisement packet include if you exclude the device name? If the advertisement exceeds 31 bytes I would suggest putting either device name or the UUID (or similar) in a scan response packet instead, which is done in the guide by Håkon as well.

    Best regards,

    Simon

  • Hi Simon,

    Thanks for your reply.

    I think my advertising data is less than 24 bytes.

    static const struct bt_data ad[] = {
    	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
    #if 1
            BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
    #endif
    #if 0
    	BT_DATA_BYTES(BT_DATA_UUID16_ALL,
    		      BT_UUID_16_ENCODE(BT_UUID_HRS_VAL),
    		      BT_UUID_16_ENCODE(BT_UUID_BAS_VAL),
    		      BT_UUID_16_ENCODE(BT_UUID_DIS_VAL)
                         )
    #endif
    };
    
    static const struct bt_data sd[] = {
    	BT_DATA_BYTES(BT_DATA_UUID128_ALL, UUID_DXTER_BASE, UUID_DXTER_STETH_SERVICE),
    };
    

    Discounting the lines removed by #if 0, The advertising data should only be the FLAGS and the device name.   The device name length is 21 bytes.

    I send the 128-bit UUID as scan data.

    Here is the call to start advertising:

    	err = bt_le_adv_start(BT_LE_ADV_CONN_NAME,
                                     ad, ARRAY_SIZE(ad),
                                     sd, ARRAY_SIZE(sd));

    Stepping through the code, the advertising data is "updated" in hci_core.c  at the call to le_adv_update() (line 7880).  If "use_name" is true (and it is),  the ad[] array is checked (via ad_has_name) to see if a name parameter has been sent in.  Since it has (via the BT_DATA_NAME_COMPLETE in the ad[1] item, it returns true, which causes the error. 

    It seemed that the very data that should be being copied into the advertising data (around line 7899 of hci_core.c), is causing the error that aborts the advertising update. 

    I then realized that "use_name" doesn't mean to use the name in the ad[] array...     So I changed the Flag in the bt_le_adv_start call to BT_LE_ADV_CONN and the full name appears.

    So it looks like if you use BT_LE_ADV_CONN_NAME with another name in ad[], an error  occurs, and if you use BT_LE_ADV_CONN with a name in ad[], it uses the full name (assume BT_DATA_NAME_COMPLETE),   But it also appears that if you use BT_LE_ADV_CONN with no name in ad[], the full name also appears (extracted from CONFIG_BT_DEVICE_NAME) and if you use BT_LE_ADV_CONN_NAME with no name in ad[] a truncated name appears.

    A bit confusing, but seems to make sense after reading through the actual hci_core.c code...

    Thanks...

Reply
  • Hi Simon,

    Thanks for your reply.

    I think my advertising data is less than 24 bytes.

    static const struct bt_data ad[] = {
    	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
    #if 1
            BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
    #endif
    #if 0
    	BT_DATA_BYTES(BT_DATA_UUID16_ALL,
    		      BT_UUID_16_ENCODE(BT_UUID_HRS_VAL),
    		      BT_UUID_16_ENCODE(BT_UUID_BAS_VAL),
    		      BT_UUID_16_ENCODE(BT_UUID_DIS_VAL)
                         )
    #endif
    };
    
    static const struct bt_data sd[] = {
    	BT_DATA_BYTES(BT_DATA_UUID128_ALL, UUID_DXTER_BASE, UUID_DXTER_STETH_SERVICE),
    };
    

    Discounting the lines removed by #if 0, The advertising data should only be the FLAGS and the device name.   The device name length is 21 bytes.

    I send the 128-bit UUID as scan data.

    Here is the call to start advertising:

    	err = bt_le_adv_start(BT_LE_ADV_CONN_NAME,
                                     ad, ARRAY_SIZE(ad),
                                     sd, ARRAY_SIZE(sd));

    Stepping through the code, the advertising data is "updated" in hci_core.c  at the call to le_adv_update() (line 7880).  If "use_name" is true (and it is),  the ad[] array is checked (via ad_has_name) to see if a name parameter has been sent in.  Since it has (via the BT_DATA_NAME_COMPLETE in the ad[1] item, it returns true, which causes the error. 

    It seemed that the very data that should be being copied into the advertising data (around line 7899 of hci_core.c), is causing the error that aborts the advertising update. 

    I then realized that "use_name" doesn't mean to use the name in the ad[] array...     So I changed the Flag in the bt_le_adv_start call to BT_LE_ADV_CONN and the full name appears.

    So it looks like if you use BT_LE_ADV_CONN_NAME with another name in ad[], an error  occurs, and if you use BT_LE_ADV_CONN with a name in ad[], it uses the full name (assume BT_DATA_NAME_COMPLETE),   But it also appears that if you use BT_LE_ADV_CONN with no name in ad[], the full name also appears (extracted from CONFIG_BT_DEVICE_NAME) and if you use BT_LE_ADV_CONN_NAME with no name in ad[] a truncated name appears.

    A bit confusing, but seems to make sense after reading through the actual hci_core.c code...

    Thanks...

Children
No Data
Related