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

S130 Custom UUID Service discovery

I have S110 peripheral device with custom UUID, created as described in www.nordicsemi.com/.../80193304 . On the other side i have S130 device who successfuly scans and connects to peripheral device. But when i try to discover services, i cant get custom service - i get that type is BLE_UUID_TYPE_UNKNOWN. All other servces is like ble_bas, ble_dis are discovered. I use S130 demo code.

So my question - how to discover custom UUIID service on S130 device?

  • Hi,

    I was solving similar problem and the solution is described in the S120/S130 documentation: you need to call "sd_ble_uuid_vs_add" which allows you to add several custom 128-bit UUID bases to the stack. In second parameter of that call you will receive unique custom UUID type number which you should store and use later on (it will be relative to "BLE_UUID_TYPE_VENDOR_BEGIN"). When you then call "sd_ble_gattc_primary_services_discover" and get event "BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP" then you will see correct type and 16-bit UUID inside "ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp.services[index].uuid" structure. Now problem is where you can get the 128-bit base UUID. In case you have hardcoded stack on peripheral side then you can easily hardcode it on GATTC side as well. If not then you have still chance to pass this because BT SiG requires to place primary service UUID into Advertising Data which are known to Central device prior to connection and service discovery (by parsing "ble_evt->evt.gap_evt.params.adv_report.data" upon receiving "BLE_GAP_EVT_ADV_REPORT" event). I've passed all this and it works great.

    Now there is more generic situation which I'm having problems with: how to handle when only one Service UUID is in Advertising Data but GATT server on Peripheral side hosts more custom services with different 128-bit UUID bases? I ended up at the same point os you originally where "...services[index].uuid" structure contains type "BLE_UUID_TYPE_UNKNOWN" and 16-bit short UUID = 0x0000. But in the log from BLE sniffer I know that (of course) Peripheral returns full 128-bit UUID inside "Read by Group Type Response" (OPCODE = 0x11, Group Handle Value Pair structure inside Attribute Data). So ultimate question is: is there any way how to access raw Rx data of this response at the time of receiving "BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP" event? If so then I could parse it inside the application and problem is solved. If not then it brings the question: how can I send raw ATT command (I can build the structure for this OPCODE manually) and receive response? Or how to do it on L2CAP layer if this cannot be done on ATT due to Nordic S120/S130 API constrains?

    Every idea or answer is much appreciated.

    Update from 16-Feb-2015:

    Thanks to Nordic support team I have working solution finally:

    If after calling "sd_ble_gattc_primary_services_discover" response "...gattc_evt.params.prim_srvc_disc_rsp.services[index].uuid.type" is "BLE_UUID_TYPE_UNKNOWN" then you can get full 128-bit UUID by issuing "sd_ble_gattc_read" (raw GATTC READ command) on the very same handle ("...gattc_evt.params.prim_srvc_disc_rsp.services[index].handle_range.start_handle"). Response contains full 128-bit Service UUID (in "...gattc_evt.params.read_rsp" structure). It should be then used in "sd_ble_uuid_vs_add" call followed by repeated "sd_ble_gattc_primary_services_discover" (on the same start handle) which will return correct "BLE_UUID_TYPE_VENDOR_BEGIN" type and 16-bit short Service UUID in the response.

    Drawback of this solution is that there are exactly two more command-response GATT messages which makes Service Discovery longer by at least 4 connection intervals per such unknown custom 128-bit UUID base. Seems no workaround possible unless you avoid using SoftDevice API at all.

    Update from 2-Apr-2015

    Hi James,

    Here is example of code which is working for me (place it inside inner loop going through all discovered primary services after return from "sd_ble_gattc_primary_services_discover"):

    if (gsp_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp.services[index].uuid.type == BLE_UUID_TYPE_UNKNOWN) {
        // Unknown 128-bit UUID => read handle again to get full answer.
        err_code = sd_ble_gattc_read(m_central_conn_handle, gsp_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp.services[index].handle_range.start_handle, 0);
        if (err_code != NRF_SUCCESS) {
            return err_code;
        }
        err_code = event_handle(BLE_GATTC_EVT_READ_RSP, m_time_out, gs_evt_buf, sizeof(gs_evt_buf));
        if (err_code != NRF_SUCCESS) {
            return err_code;
        }
    
        // Response should contain full 128-bit UUID.
        uint8_t * rsp_data    = (uint8_t *)gsp_ble_evt->evt.gattc_evt.params.read_rsp.data;
        uint8_t rsp_data_len  = gsp_ble_evt->evt.gattc_evt.params.read_rsp.len;
        if (rsp_data_len == 16) {
            // Mask 16-bit UUID part to zeros.
            rsp_data[12] = 0x00;
            rsp_data[13] = 0x00;
    
            // Copy gathered 128bit UUID as future base.
            memcpy(m_uuid128base.uuid128, rsp_data, 16);
            err_code = sd_ble_uuid_vs_add((const ble_uuid128_t *)&m_uuid128base, &m_uuid128base_type);
            APP_ERROR_CHECK(err_code);
        }
    }
    
  • Hi,

    I have the same problem than DiamondS. From S130 device, I try to discover my services in S110 peripheral, but i can not found it.

    Jan Steffl I tried your solution but I get an error in sd_ble_gattc_read function, and i dont understand why. Can you give a clearer statement of how to solve this problem? Or even share an excerpt from the code in question?

  • I solved this different way. For peripheral devices i use device_manager_central.h from nrf-sdk in the same way as in the S120 examples (since S130 is a mix of S110 and S120). So it handles all the connectivity, bonding, etc. When i need discover services i use ble_db_discovery.h, which handles discovery process (also example is form 120). But before all that i add custom service UUID, because i know what services i need:

    err_code = sd_ble_uuid_vs_add(&base_uuid, &uuidType);
    APP_ERROR_CHECK(err_code);
    

    And now everything is ok.

    There is also device_maneger_peripheral.h to use in S130, for example when you whant to connect your phone. But for now i see that you can't use both device managers. Would be greate if Nordic update this sdk with devices_manager that handles both central and peripheral devices.

  • Well in general you have 3 situations:

    1. You know the custom 128-bit UUID base at the development time - then it is pretty much trivial to hard code into the FW,
    2. You get 128-bit UUID from ADV_IND or SCAN_RSP data - then you just need to parse string for particular AD nodes, not a big deal.
    3. You cannot get 128-bit UUID(s) before connection time and then you need to do Service Discovery procedure as suggested above.

    Regarding "device manager": I do not use it any more but Central and Peripheral roles are opposite and it's hard to imagine how to merge it. If you run dual role at the same time then you should anyway keep them separately in the FW e.g. by having one module managing GAP Central and GAP Peripheral. From what I see in S120 documentation released with SDK it's the case already but I might be missing some detail which prevents you from using it this way.

  • I've added example to original post (just one post per user restriction and limited length of comments...). Cheers Jan

Related