BLE discovery with with CYW43012

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
CharlesOram
Level 3
Level 3
First like received Welcome!

Hi,

I am using the CYW43012 (or more specifically the Murata Type 1LV module) for a product where the CYW43012 operates as a central and connects to a peripheral, but I cannot get discovery of the characteristics of the peripheral working.

Where can I find some examples or documentation for this? The API documentation does not provide enough information on all the events and functions to be useful.

All the examples I have found just use hard-coded characteristic handles, but I don't want to do that unless I can guarantee that the handles will never change.

I would also like to get the central connecting to the peripheral with "Just Works" LE security (pairing with no bonding), but again there are no useful examples and no useful documentation for this. Please can someone point me in the right direction?

regards,

Charles

1 Solution
CharlesOram
Level 3
Level 3
First like received Welcome!

OK, I have got the discovery of my custom service's characteristics working.

The main problem was that the UUID reported in the GATT_DISCOVERY_RESULT_EVT event was a 128-bit UUID and I was using code for checking a 16-bit UUID.

So here's how I've got the discovery working for a custom service:

1. When there is a GATT_CONNECTION_STATUS_EVT event I start the service discovery, code is something like this:

        case GATT_CONNECTION_STATUS_EVT:

        {

            if ( p_event_data->connection_status.connected == WICED_TRUE )

            {

                connection_handle = p_event_data->connection_status.conn_id;

                memset(&ble_parameters, 0, sizeof(wiced_bt_gatt_discovery_param_t));

                ble_parameters.s_handle = 1;

                ble_parameters.e_handle = 0xFFFF;

                ble_parameters.uuid.len = LEN_UUID_128;

                memcpy(ble_parameters.uuid.uu.uuid128, my_custom_service_128bit_uuid, LEN_UUID_128);

                status = wiced_bt_gatt_send_discover(connection_handle, GATT_DISCOVER_SERVICES_BY_UUID, &ble_parameters);

                WPRINT_APP_INFO(("Disco send status %u\n", status));

                ble_state = BLE_STATE_DISCOVER_SERVICES;

            }

        }

I think you can also set the UUID to 0 and it will discover all services, but I know the UUID of my service so may as well just discover that.

2. In the GATT_DISCOVERY_RESULT_EVT event handler I save the handles of the service if p_event_data->discovery_result.discovery_type == GATT_DISCOVER_SERVICES_BY_UUID. And in the GATT_DISCOVERY_CPLT_EVT  event handler start discovery of the characteristics:

        case GATT_DISCOVERY_CPLT_EVT:

            WPRINT_APP_INFO( ( "Gatt disc cplt %u\n", (unsigned int)p_event_data->discovery_complete.status ) );

            /* Start searching characteristics, we will use discover all characteristics of the service discovery type. No uuid needs to be specified */

            memset( &ble_parameters.uuid, 0, sizeof( ble_parameters.uuid ) );

            ble_parameters.s_handle = service_start_handle;

            ble_parameters.e_handle = service_end_handle;

            status = wiced_bt_gatt_send_discover(connection_handle, GATT_DISCOVER_CHARACTERISTICS, &ble_parameters);

            WPRINT_APP_INFO(("Send disc ch status %x\n", status));

            ble_state = BLE_STATE_DISCOVER_CHAR;

            }

3. In the GATT_DISCOVERY_RESULT_EVT event handler match on the 128-bit UUID of the characteristic you are looking for and save the handle:

        case GATT_DISCOVERY_RESULT_EVT:

            if (p_event_data->discovery_result.discovery_type == GATT_DISCOVER_CHARACTERISTICS)

            {

                uint16_t value_handle;

                uint8_t *characteristic_uuid;

                wiced_bt_gatt_char_properties_t characteristic_prop;

                /* Extract characteristic UUID  */

                characteristic_uuid = GATT_DISCOVERY_RESULT_CHARACTERISTIC_UUID128(p_event_data);

                /* Extract characteristic value handle */

                value_handle = GATT_DISCOVERY_RESULT_CHARACTERISTIC_VALUE_HANDLE(p_event_data);

                characteristic_prop = p_event_data->discovery_result.discovery_data.characteristic_declaration.characteristic_properties;

                if (memcmp(characteristic_uuid, my_char1_128bit_uuid, sizeof(my_char1_128bit_uuid)) == 0)

                {

                    handle_char1 = value_handle;

                    WPRINT_APP_INFO(("Char1 h=%04X %x\n", (unsigned int)value_handle, (unsigned int)characteristic_prop));

                }

                else if (memcmp(characteristic_uuid, my_char2_128bit_uuid, sizeof(my_char2_128bit_uuid)) == 0)

                {

                    handle_char2 = value_handle;

                    WPRINT_APP_INFO(("Char2 ch h=%04X %x\n", (unsigned int)value_handle, (unsigned int)characteristic_prop));

                }

            }

4. In the GATT_DISCOVERY_CPLT_EVT event handler (once you detect that you have the handles of all your characteristics) you can then read one of the characteristics with something like:

void read_characteristic_data(void)

{

    wiced_bt_gatt_status_t status;

    wiced_bt_gatt_read_param_t read_param;

    ble_state = BLE_STATE_READ_CHAR_DATA;

    read_param.by_handle.handle = char1_handle;

    read_param.by_handle.auth_req = GATT_AUTH_REQ_NONE;

    status = wiced_bt_gatt_send_read(connection_handle, GATT_READ_BY_HANDLE, &read_param);

    WPRINT_APP_INFO(("Read status %u\n", status));

}

The only other problem I have now is that the scanning doesn't restart when I call wiced_bt_ble_scan() again (I've seen some posts here that mention this issue, so will go back and re-read those).

Good, so now I can go back and try to get the Just Works pairing just working

View solution in original post

0 Likes
4 Replies
SheetalJ
Moderator
Moderator
Moderator
First comment on KBA 750 replies posted 500 likes received

Hi Charles,

Client can discover the data contained in the advertisement packet of the peripheral. For ex, in hello sensor demo app(peripheral), hello_sensor_set_advertisement_data() function sets the data to be included in adv packet. Accordingly, you can look for the needed data at client side.

For "just works" security, can you please check wiced_bt_dev.h -> wiced_bt_dev_le_auth_req_t.

You can use the needed configuration and set the IO capabilities of the device using event BTM_PAIRING_IO_CAPABILITIES_BLE_REQUEST_EVT. Please check hello sensor.c file for more details.

Hi Sheetalj_96,

Thanks, but looking at the advertising data sent by the peripheral doesn't help me get the handles for the characteristic data, so is not what I need.

I am calling wiced_bt_gatt_send_discover()  with GATT_DISCOVER_SERVICES_BY_UUID and then GATT_DISCOVER_CHARACTERISTICS and I get  GATT_DISCOVERY_RESULT_EVT and GATT_DISCOVERY_CPLT_EVT events, but don't get the characteristics for my service and it is not clear what the relationship is between these events or their order of occurrence.

I have been using the ble_hello_client example to look at the pairing - I am setting the IO capabilities, but I'll have another look since I am possibly not setting them correctly.

regards,

Charles

0 Likes
CharlesOram
Level 3
Level 3
First like received Welcome!

OK, I have got the discovery of my custom service's characteristics working.

The main problem was that the UUID reported in the GATT_DISCOVERY_RESULT_EVT event was a 128-bit UUID and I was using code for checking a 16-bit UUID.

So here's how I've got the discovery working for a custom service:

1. When there is a GATT_CONNECTION_STATUS_EVT event I start the service discovery, code is something like this:

        case GATT_CONNECTION_STATUS_EVT:

        {

            if ( p_event_data->connection_status.connected == WICED_TRUE )

            {

                connection_handle = p_event_data->connection_status.conn_id;

                memset(&ble_parameters, 0, sizeof(wiced_bt_gatt_discovery_param_t));

                ble_parameters.s_handle = 1;

                ble_parameters.e_handle = 0xFFFF;

                ble_parameters.uuid.len = LEN_UUID_128;

                memcpy(ble_parameters.uuid.uu.uuid128, my_custom_service_128bit_uuid, LEN_UUID_128);

                status = wiced_bt_gatt_send_discover(connection_handle, GATT_DISCOVER_SERVICES_BY_UUID, &ble_parameters);

                WPRINT_APP_INFO(("Disco send status %u\n", status));

                ble_state = BLE_STATE_DISCOVER_SERVICES;

            }

        }

I think you can also set the UUID to 0 and it will discover all services, but I know the UUID of my service so may as well just discover that.

2. In the GATT_DISCOVERY_RESULT_EVT event handler I save the handles of the service if p_event_data->discovery_result.discovery_type == GATT_DISCOVER_SERVICES_BY_UUID. And in the GATT_DISCOVERY_CPLT_EVT  event handler start discovery of the characteristics:

        case GATT_DISCOVERY_CPLT_EVT:

            WPRINT_APP_INFO( ( "Gatt disc cplt %u\n", (unsigned int)p_event_data->discovery_complete.status ) );

            /* Start searching characteristics, we will use discover all characteristics of the service discovery type. No uuid needs to be specified */

            memset( &ble_parameters.uuid, 0, sizeof( ble_parameters.uuid ) );

            ble_parameters.s_handle = service_start_handle;

            ble_parameters.e_handle = service_end_handle;

            status = wiced_bt_gatt_send_discover(connection_handle, GATT_DISCOVER_CHARACTERISTICS, &ble_parameters);

            WPRINT_APP_INFO(("Send disc ch status %x\n", status));

            ble_state = BLE_STATE_DISCOVER_CHAR;

            }

3. In the GATT_DISCOVERY_RESULT_EVT event handler match on the 128-bit UUID of the characteristic you are looking for and save the handle:

        case GATT_DISCOVERY_RESULT_EVT:

            if (p_event_data->discovery_result.discovery_type == GATT_DISCOVER_CHARACTERISTICS)

            {

                uint16_t value_handle;

                uint8_t *characteristic_uuid;

                wiced_bt_gatt_char_properties_t characteristic_prop;

                /* Extract characteristic UUID  */

                characteristic_uuid = GATT_DISCOVERY_RESULT_CHARACTERISTIC_UUID128(p_event_data);

                /* Extract characteristic value handle */

                value_handle = GATT_DISCOVERY_RESULT_CHARACTERISTIC_VALUE_HANDLE(p_event_data);

                characteristic_prop = p_event_data->discovery_result.discovery_data.characteristic_declaration.characteristic_properties;

                if (memcmp(characteristic_uuid, my_char1_128bit_uuid, sizeof(my_char1_128bit_uuid)) == 0)

                {

                    handle_char1 = value_handle;

                    WPRINT_APP_INFO(("Char1 h=%04X %x\n", (unsigned int)value_handle, (unsigned int)characteristic_prop));

                }

                else if (memcmp(characteristic_uuid, my_char2_128bit_uuid, sizeof(my_char2_128bit_uuid)) == 0)

                {

                    handle_char2 = value_handle;

                    WPRINT_APP_INFO(("Char2 ch h=%04X %x\n", (unsigned int)value_handle, (unsigned int)characteristic_prop));

                }

            }

4. In the GATT_DISCOVERY_CPLT_EVT event handler (once you detect that you have the handles of all your characteristics) you can then read one of the characteristics with something like:

void read_characteristic_data(void)

{

    wiced_bt_gatt_status_t status;

    wiced_bt_gatt_read_param_t read_param;

    ble_state = BLE_STATE_READ_CHAR_DATA;

    read_param.by_handle.handle = char1_handle;

    read_param.by_handle.auth_req = GATT_AUTH_REQ_NONE;

    status = wiced_bt_gatt_send_read(connection_handle, GATT_READ_BY_HANDLE, &read_param);

    WPRINT_APP_INFO(("Read status %u\n", status));

}

The only other problem I have now is that the scanning doesn't restart when I call wiced_bt_ble_scan() again (I've seen some posts here that mention this issue, so will go back and re-read those).

Good, so now I can go back and try to get the Just Works pairing just working

0 Likes
CharlesOram
Level 3
Level 3
First like received Welcome!

I also have LE Security working now.

I needed to get the IO capabilities right:

    case BTM_PAIRING_IO_CAPABILITIES_BLE_REQUEST_EVT:

        WPRINT_APP_INFO(( "IO capabilities req\n"));

        p_event_data->pairing_io_capabilities_ble_request.local_io_cap      = BTM_IO_CAPABILITIES_NONE;

        p_event_data->pairing_io_capabilities_ble_request.oob_data          = BTM_OOB_NONE;

        p_event_data->pairing_io_capabilities_ble_request.auth_req          = BTM_LE_AUTH_REQ_SC_ONLY; // This also seems to work with BTM_LE_AUTH_REQ_SC_BOND

        p_event_data->pairing_io_capabilities_ble_request.max_key_size      = 0x10;

        p_event_data->pairing_io_capabilities_ble_request.init_keys        = BTM_LE_KEY_PENC | BTM_LE_KEY_PID ;

        p_event_data->pairing_io_capabilities_ble_request.resp_keys        = BTM_LE_KEY_PENC | BTM_LE_KEY_PID ;

        break;

and start bonding and encryption once I have discovered all the characteristics (in the GATT_DISCOVERY_CPLT_EVT event handler):

    case GATT_DISCOVERY_CPLT_EVT:

        WPRINT_APP_INFO( ( "Gatt disc cplt %u\n", (unsigned int)p_event_data->discovery_complete.status ) );

        if (ble_state == BLE_STATE_DISCOVER_SERVICES)

        {

            /* Start searching characteristics, we will use discover all characteristics of the service discovery type. No uuid needs to be specified */

            memset( &ble_parameters.uuid, 0, sizeof( ble_parameters.uuid ) );

            ble_parameters.s_handle = service_start_handle;

            ble_parameters.e_handle = service_end_handle;

            status = wiced_bt_gatt_send_discover(connection_handle, GATT_DISCOVER_CHARACTERISTICS, &ble_parameters);

            WPRINT_APP_INFO(("Send disc ch status %x\n", status));

            ble_state = BLE_STATE_DISCOVER_CHAR;

        }

        else if (ble_state == BLE_STATE_DISCOVER_CHAR)

        {

            if (discovered_all_handles)

            {

                // Discovery complete - read the pairing data

                WPRINT_APP_INFO(("Discovery complete\n"));

                status = wiced_bt_dev_sec_bond(peer_addr, connection_addr_type, BT_TRANSPORT_LE, 0, NULL);

                if ((status == WICED_BT_SUCCESS) || (status == WICED_BT_PENDING))

                {

                    WPRINT_APP_INFO(( "starting encryption\n" ));

                    wiced_bt_dev_set_encryption(peer_addr, BT_TRANSPORT_LE, NULL);

                }

                else

                {

                    WPRINT_APP_INFO(("wiced_bt_dev_sec_bond %x \n", (unsigned int)status));

                }

            }

        }

        break;

(peer_addr and connection_addr_type were set in the scan result callback).

I now start reading the characteristics when I get the BTM_PAIRING_COMPLETE_EVT event.

- Charles

0 Likes