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

HID and NUS

Hello,

I am attempting to incorporate NUS example (app_uart) into the HID keyboard example. The whole thing compiles with no warning, but when I add {BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE} to m_adv_uuids, the adverstising never starts. I was able to locate where it fails through the debugger. When it enters the line APP_ERROR_CHECK(err_code) it fails.

static void advertising_init(void)
{
    uint32_t               err_code;
    uint8_t                adv_flags;
    ble_advertising_init_t init;

    memset(&init, 0, sizeof(init));

    adv_flags                            = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    init.advdata.name_type               = BLE_ADVDATA_FULL_NAME;
    init.advdata.include_appearance      = true;
    init.advdata.flags                   = adv_flags;
    init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
    init.advdata.uuids_complete.p_uuids  = m_adv_uuids;

    init.config.ble_adv_whitelist_enabled          = true;
    init.config.ble_adv_directed_high_duty_enabled = true;
    init.config.ble_adv_directed_enabled           = false;
    init.config.ble_adv_directed_interval          = 0;
    init.config.ble_adv_directed_timeout           = 0;
    init.config.ble_adv_fast_enabled               = true;
    init.config.ble_adv_fast_interval              = APP_ADV_FAST_INTERVAL;
    init.config.ble_adv_fast_timeout               = APP_ADV_FAST_DURATION;
    init.config.ble_adv_slow_enabled               = true;
    init.config.ble_adv_slow_interval              = APP_ADV_SLOW_INTERVAL;
    init.config.ble_adv_slow_timeout               = APP_ADV_SLOW_DURATION;

    init.evt_handler   = on_adv_evt;
    init.error_handler = ble_advertising_error_handler;

    err_code = ble_advertising_init(&m_advertising, &init);
    APP_ERROR_CHECK(err_code);

    ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
}

I have tried the same with OTS and altough I wasn't able to communicate trough it I was able to advertise it. I have defined the following in sdk_config.h :

#define BLE_NUS_ENABLED 1

Any idea on what could cause an advertising failure?

Parents
  • well you could just debug through to find out where the error is returned or look at the error code to see which one it is. Most likely you've put too much in the advertising packet and overfilled it so you're getting an error that there's no space. 

  • Sorry, I see now what you mean. I have found out here what is the advertising packet. I know how to reduce the size taken by my device name, but it's not enough. I would need to reduce the data field of the NUS, but I'm not sure where to edit that. Probably in ble_nus.h. I will continue to look.

  • Hi,

    Which function returns the error code now? and is it still NRF_ERROR_INVALID_PARAM?

  • Hello, yes it is still the same error and it is the same function as before that returns it.

    I have shortened the advertising packet as much as I think I could :

    No device name = 0 byte

    -BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE flag = 3 bytes(?)

    -HID = 4 bytes (Altough I have two reports for this profile, could it make it longer? Let's assume 8)

    -BAS = Not sure about this one, I did not find where it says it is advertised, but I would assume it takes 4 more bytes...

    -NUS = For the sake of testing, I have reduced BLE_NUS_MAX_DATA_LEN to 1. I don't know if the fact that there is both RX and TX extends the space taken by the NUS, I assume it does. For my application I don't need TX. (data(1) + manufacturer ID(2) + length(1) + type(2?) = 6 bytes?)

    In total I think that would make 17-21 bytes, no? I must be wrong because if so it should work if it's under 31 bytes...

  • OK, so you get NRF_ERROR_INVALID_PARAM returned from ble_advertising_init()? Which SDK are you using?

    Assuming SDK 15.2, this means that the error probably comes from ble_advdata_encode(). That function is responsible for encoding the advertisement packet and is quite easy to understand. Essentially there is an if statement for each field, so you can check with a debugger which fails (which is invalid).

  • Hello Einar, yes, that seems to be the function that returns the error. More specifically, it's the If Statement that encodes the complete UUID list.

    This statement calls the function uuid_list_encode() so I went further to see what could be the problem. This function is in two parts, one for encoding 16 bits UUIDs and the other for encoding 128 bits UUIDs.

    When encoding my first service, HID, the debugger will enter this function, execute the 16 bits and 128 bits sections with no failure. However, when encoding the NUS service, it enters the same function but fails at the 16 bits encoding and skips over the 128 bits encoding, resulting in the error code 0x07.

    Is there a way to specify which encoding to use for NUS without impacting the encoding for HID?

Reply
  • Hello Einar, yes, that seems to be the function that returns the error. More specifically, it's the If Statement that encodes the complete UUID list.

    This statement calls the function uuid_list_encode() so I went further to see what could be the problem. This function is in two parts, one for encoding 16 bits UUIDs and the other for encoding 128 bits UUIDs.

    When encoding my first service, HID, the debugger will enter this function, execute the 16 bits and 128 bits sections with no failure. However, when encoding the NUS service, it enters the same function but fails at the 16 bits encoding and skips over the 128 bits encoding, resulting in the error code 0x07.

    Is there a way to specify which encoding to use for NUS without impacting the encoding for HID?

Children
  • Ok, so I went further with the debugger. Inside uuid_list_encode(), there is two calls for the function uuid_list_sized_encode(). In that function, there is a call to another function, sd_ble_uuid_encode() that I'm pretty positive is the source of my problem. Looking in that last function, you see that it returns NRF_ERROR_INVALID_PARAM when the UUID type is invalid.

    You can see that the type for NUS is 0x02 (BLE_UUID_TYPE_VENDOR_BEGIN). Somehow it doesn't seem to recognize 0x02 as a valid type. I changed it to 0x01 (BLE_UUID_TYPE_BLE) with the debugger and the error was gone, but of course, I know 0x02 should work, normally.

    Now I need help resolving why it doesn't accept 0x02 as a valid type...

  • I see. Then I assume the problem is that the SoftDevice has not been configured with the custom base UUID. This is done by ble_nus_init(), so this has to be called before you configure the advertisement packet. You can see the same issue with the NUS example from the SDK if you change the order of the calls to services_init() and advertising_init().

  • Thank you so much for your help. I initiated the NUS service before advertising it, as you said. I had another problem that followed where I did'nt have enough RAM. I was able to change it and now I have successfully implemented NUS with HID. Again, thank you.

Related