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

Modify pc-ble-driver example for Nordic UART Service

I try to modify one of the pc-ble-driver examples to work together with my PCA10040 and the Nordic UART Service example in my Qt application, but the application doesn´t discover two characteristics and receive an event with the ID 0x23 and 0x12:

Open softdevice...
Log:  2 - Successfully opened COM5. Baud rate: 1000000. Flow control: none. Parity: none.
Status:  6 - Target Reset performed
Status:  7 - Connection active
Enable softdevice...
Start scanning...
Scan started
Received advertisement report with device address:  0x453e4ff9a8
Connection established
Discovering primary service
Received an unhandled event with ID: 0x 23
Received service discovery response
Found  1  services
Discovered service with UUID: 0x 1 , start handle: 0x ffff , end handle: 0x ffff
Discovering characteristics
Received characteristic discovery response, characteristics count:  1
Characteristic handle: 0x c , UUID: 0x 2
Discovering characteristic's descriptors
No characteristic handle found
Received an unhandled event with ID: 0x 12
Disconnected, reason: 0x 22

How do I have to modify the code to use both characteristics of the service?

#include "qt_ble.h"

#define BLE_UUID_CCCD                                           0x2902

#define MSEC_TO_UNITS(TIME, RESOLUTION)                         (((TIME) * 1000) / (RESOLUTION))

#define BLE_UUID_NUS_SERVICE            0x0001
#define NUS_BASE_UUID                   {{0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E}}

//static uint32_t _mDeviceServiceUUID     = 0;
static uint32_t _mDeviceCharUUID        = 0;
static uint32_t _mErrorCode             = 0;
static uint32_t _mConfigID              = 0;
static uint16_t _mCCCDHandle            = 0;
static uint16_t _mCharHandle            = 0;
static uint16_t _mConnectionHandle      = 0;
static uint16_t _mServiceStartHandle    = 0;
static uint16_t _mServiceEndHandle      = 0;
static uint8_t  _mConnectedDevices      = 0;
static bool _mConnectionInProgress;

static ble_uuid_t UUID;
static ble_cfg_t _mBLE_Config;
static adapter_t* _mAdapter;
static physical_layer_t* _mPhy;
static data_link_layer_t* _mData_link_layer;
static transport_layer_t* _mTransport_layer;

static const ble_gap_scan_params_t Scan_Params =
{
    0,                       // Set if active scanning.
    0,                       // Set if selective scanning.
    0,
    (uint16_t)0x00A0,
    (uint16_t)0x0050,
    (uint16_t)0x00
};

static const ble_gap_conn_params_t Connection_Params =
{
    (uint16_t)MSEC_TO_UNITS(7.5, 1250),
    (uint16_t)MSEC_TO_UNITS(7.5, 1250),
    (uint16_t)0,
    (uint16_t)MSEC_TO_UNITS(4000, 10000)
};

uint32_t Qt_BLE::Open(QString Port, uint32_t ServiceUUID, uint32_t CharacteristicUUID)
{
    const uint32_t RAM_Start = 0;
    uint32_t* App_RAM_Base = NULL;

    /*
    _mDeviceServiceUUID = ServiceUUID;
    _mDeviceCharUUID = CharacteristicUUID;*/
    _mConfigID = 1;
    _mConnectedDevices = 0;
    _mConnectionHandle = 0;
    _mConnectionInProgress = false;

    _mPhy = sd_rpc_physical_layer_create_uart(Port.toLocal8Bit().data(), 1000000, SD_RPC_FLOW_CONTROL_NONE, SD_RPC_PARITY_NONE);
    _mData_link_layer = sd_rpc_data_link_layer_create_bt_three_wire(_mPhy, 250);
    _mTransport_layer = sd_rpc_transport_layer_create(_mData_link_layer, 1500);
    _mAdapter = sd_rpc_adapter_create(_mTransport_layer);
    sd_rpc_log_handler_severity_filter_set(_mAdapter, SD_RPC_LOG_INFO);

    DEBUG << "Open softdevice...";
    _mErrorCode = sd_rpc_open(_mAdapter, Qt_BLE::StatusHandler, Qt_BLE::on_Event, Qt_BLE::LogHandler);
    if(_mErrorCode != NRF_SUCCESS)
    {
        DEBUG << "Failed to open nRF BLE Driver. Error code: 0x" << hex << _mErrorCode;
    }

    _mBLE_Config.gap_cfg.role_count_cfg.periph_role_count    = 0;
    _mBLE_Config.gap_cfg.role_count_cfg.central_role_count   = 1;
    _mBLE_Config.gap_cfg.role_count_cfg.central_sec_count    = 0;

    _mErrorCode = sd_ble_cfg_set(_mAdapter, BLE_GAP_CFG_ROLE_COUNT, &_mBLE_Config, RAM_Start);
    if(_mErrorCode != NRF_SUCCESS)
    {
        DEBUG << "sd_ble_cfg_set() failed when attempting to set BLE_GAP_CFG_ROLE_COUNT. Error code: 0x" << hex << _mErrorCode;
    }

    memset(&_mBLE_Config, 0x00, sizeof(ble_cfg_t));
    _mBLE_Config.conn_cfg.conn_cfg_tag                        = _mConfigID;
    _mBLE_Config.conn_cfg.params.gatt_conn_cfg.att_mtu        = 150;

    _mErrorCode = sd_ble_cfg_set(_mAdapter, BLE_CONN_CFG_GATT, &_mBLE_Config, RAM_Start);
    if(_mErrorCode != NRF_SUCCESS)
    {
        DEBUG << "sd_ble_cfg_set() failed when attempting to set BLE_CONN_CFG_GATT. Error code: 0x" << hex << _mErrorCode;
    }

    DEBUG << "Enable softdevice...";
    _mErrorCode = sd_ble_enable(_mAdapter, App_RAM_Base);
    if(_mErrorCode != NRF_SUCCESS)
    {
        DEBUG << "Failed to enable nRF BLE Driver. Error code: 0x" << hex << _mErrorCode;
    }

    return _mErrorCode;
}

uint32_t Qt_BLE::StartScan(void)
{
    DEBUG << "Start scanning...";
    _mErrorCode = sd_ble_gap_scan_start(_mAdapter, &Scan_Params);
    if(_mErrorCode != NRF_SUCCESS)
    {
        DEBUG << "Scan start failed with error code: 0x" << hex << _mErrorCode;
    }
    else
    {
        DEBUG << "Scan started";
    }

    return _mErrorCode;
}

uint32_t Qt_BLE::Close(void)
{
    return sd_rpc_close(_mAdapter);
}

void Qt_BLE::StatusHandler(adapter_t* p_Adapter, sd_rpc_app_status_t Code, const char* p_Message)
{
    DEBUG << "Status: " << Code << "-" << p_Message;
}

void Qt_BLE::LogHandler(adapter_t* p_Adapter, sd_rpc_log_severity_t Severity, const char* p_Message)
{
    DEBUG << "Log: " << Severity << "-" << p_Message;
}

void Qt_BLE::AddressToString(ble_gap_addr_t Address, rsize_t Size, uint8_t* p_Buffer)
{
    char Temp[3];

    for(int i = 5; i >= 0; --i)
    {
        sprintf(Temp, "%02X", Address.addr[i]);
        strcat_s((char*)p_Buffer, Size, Temp);
    }
}

bool Qt_BLE::Find_Adv_Name(const ble_gap_evt_adv_report_t* p_Adv_Report, const char* p_Name)
{
    uint32_t ErrorCode;
    data_t adv_data;
    data_t dev_name;

    adv_data.p_Data = (uint8_t*)p_Adv_Report->data;
    adv_data.Length = p_Adv_Report->dlen;

    // Search for advertising names
    ErrorCode = Parse_Adv_Report(BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME, &adv_data, &dev_name);
    if(ErrorCode == NRF_SUCCESS)
    {
        if(memcmp(p_Name, dev_name.p_Data, dev_name.Length) == 0)
        {
            return true;
        }
    }
    else
    {
        // Look for the short local name if it was not found as complete
        ErrorCode = Parse_Adv_Report(BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME,  &adv_data, &dev_name);
        if(ErrorCode != NRF_SUCCESS)
        {
            return false;
        }

        if(memcmp(p_Name, dev_name.p_Data, dev_name.Length) == 0)
        {
            return true;
        }
    }

    return false;
}

uint32_t Qt_BLE::Parse_Adv_Report(uint8_t type, data_t* p_AdvData, data_t* p_TypeData)
{
    uint32_t Index = 0;
    uint8_t* p_Data;

    p_Data = p_AdvData->p_Data;

    while(Index < p_AdvData->Length)
    {
        uint8_t field_length = p_Data[Index];
        uint8_t field_type   = p_Data[Index + 1];

        if(field_type == type)
        {
            p_TypeData->p_Data = &p_Data[Index + 2];
            p_TypeData->Length = field_length - 1;

            return NRF_SUCCESS;
        }

        Index += field_length + 1;
    }

    return NRF_ERROR_NOT_FOUND;
}

uint32_t Qt_BLE::Start_ServiceDiscovery(adapter_t* p_Adapter)
{
    uint16_t Start_Handle = 0x01;

    DEBUG << "Discovering primary service";

    ble_uuid128_t         nus_base_uuid = NUS_BASE_UUID;

    _mErrorCode = sd_ble_uuid_vs_add(p_Adapter, &nus_base_uuid, &UUID.type);
    if(_mErrorCode != NRF_SUCCESS)
    {
        DEBUG << "Failed to get UUID with error code: 0x" << hex << _mErrorCode;
    }

    UUID.uuid = BLE_UUID_NUS_SERVICE;

    // Initiate procedure to find the primary BLE_UUID_HEART_RATE_SERVICE.
    _mErrorCode = sd_ble_gattc_primary_services_discover(p_Adapter, _mConnectionHandle, Start_Handle, &UUID);
    if(_mErrorCode != NRF_SUCCESS)
    {
        DEBUG << "Failed to initiate or continue a GATT Primary Service Discovery procedure with error code: 0x" << hex << _mErrorCode;
    }

    return _mErrorCode;
}

void Qt_BLE::on_Event(adapter_t* p_Adapter, ble_evt_t* p_Event)
{
    switch(p_Event->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
        {
            Qt_BLE::on_Connected(p_Adapter, &(p_Event->evt.gap_evt));
            break;
        }
        case BLE_GAP_EVT_DISCONNECTED:
        {
            DEBUG << "Disconnected, reason: 0x" << hex << p_Event->evt.gap_evt.params.disconnected.reason;

            _mConnectedDevices--;
            _mConnectionHandle = 0;
            break;
        }
        case BLE_GAP_EVT_ADV_REPORT:
        {
            Qt_BLE::on_Adv_Report(p_Adapter, &(p_Event->evt.gap_evt));
            break;
        }
        case BLE_GAP_EVT_TIMEOUT:
        {
            Qt_BLE::on_Timeout(&(p_Event->evt.gap_evt));
            break;
        }
        case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
        {
            on_Service_Discovery_Response(&(p_Event->evt.gattc_evt));
            break;
        }
        case BLE_GATTC_EVT_CHAR_DISC_RSP:
        {
            on_Characteristic_Discovery_Response(&(p_Event->evt.gattc_evt));
            break;
        }
        case BLE_GATTC_EVT_DESC_DISC_RSP:
        {
            on_Descriptor_Discovery_Response(&(p_Event->evt.gattc_evt));
            break;
        }
        case BLE_GATTC_EVT_WRITE_RSP:
        {
            on_Write_Response(&(p_Event->evt.gattc_evt));
            break;
        }
        case BLE_GATTC_EVT_HVX:
        {
            DEBUG << "BLE_GATTC_EVT_HVX";
            //on_hvx(&(p_ble_evt->evt.gattc_evt));
            break;
        }
        case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
        {
            on_Conn_Params_Update_Request(&(p_Event->evt.gap_evt));
            break;
        }
        case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST:
        {
            on_Exchange_MTU_Request(&(p_Event->evt.gatts_evt));
            break;
        }
        case BLE_GATTC_EVT_EXCHANGE_MTU_RSP:
        {
            DEBUG << "BLE_GATTC_EVT_EXCHANGE_MTU_RSP";
            //on_exchange_mtu_response(&(p_ble_evt->evt.gattc_evt));
            break;
        }
        default:
        {
            DEBUG << "Received an unhandled event with ID: 0x" << hex << p_Event->header.evt_id;
            break;
        }
    }
}

void Qt_BLE::on_Adv_Report(adapter_t* p_Adapter, const ble_gap_evt_t* const p_Event)
{
    uint32_t ErrorCode;
    uint8_t Buffer[50] = {0};

    AddressToString(p_Event->params.adv_report.peer_addr, sizeof(Buffer), Buffer);
    DEBUG << "Received advertisement report with device address: " << Buffer;

    if(Find_Adv_Name(&p_Event->params.adv_report, "Nordic_UART"))
    {
        ErrorCode = sd_ble_gap_connect(p_Adapter, &(p_Event->params.adv_report.peer_addr), &Scan_Params, &Connection_Params, _mConfigID);
        if(ErrorCode != NRF_SUCCESS)
        {
            DEBUG << "Connection Request Failed, reason %d\n" << ErrorCode;
            return;
        }
    }
}

void Qt_BLE::on_Connected(adapter_t* p_Adapter, const ble_gap_evt_t* const p_Event)
{
    DEBUG << "Connection established";

    _mConnectedDevices++;
    _mConnectionHandle = p_Event->conn_handle;
    _mConnectionInProgress = false;

    Start_ServiceDiscovery(p_Adapter);
}

void Qt_BLE::on_Timeout(const ble_gap_evt_t* const p_Event)
{
    if(p_Event->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)
    {
        _mConnectionInProgress = false;
    }
    else if(p_Event->params.timeout.src == BLE_GAP_TIMEOUT_SRC_SCAN)
    {
        StartScan();
    }
}

void Qt_BLE::on_Service_Discovery_Response(const ble_gattc_evt_t* const p_Event)
{
    uint32_t ServiceIndex;
    const ble_gattc_service_t* Service;
    ble_gattc_handle_range_t HandleRange;

    DEBUG << "Received service discovery response";

    if(p_Event->gatt_status != NRF_SUCCESS)
    {
        DEBUG << "Service discovery failed. Error code 0x" << hex << p_Event->gatt_status;
        return;
    }

    if(p_Event->params.prim_srvc_disc_rsp.count == 0)
    {
        DEBUG << "Service not found";
    }
    else
    {
        DEBUG << "Found " << p_Event->params.prim_srvc_disc_rsp.count << " services";
    }

    ServiceIndex = 0; /* We expect to discover only the Heart Rate service as requested. */
    Service = &(p_Event->params.prim_srvc_disc_rsp.services[ServiceIndex]);

    if(Service->uuid.uuid != UUID.uuid)
    {
        DEBUG << "Unknown service discovered with UUID: 0x" << hex << Service->uuid.uuid;
        return;
    }

    _mServiceStartHandle = Service->handle_range.start_handle;
    _mServiceEndHandle = Service->handle_range.end_handle;

    DEBUG << "Discovered service with UUID: 0x" << hex << Service->uuid.uuid << ", start handle: 0x" << hex << _mServiceEndHandle << ", end handle: 0x" << hex << _mServiceEndHandle;
    DEBUG << "Discovering characteristics";

    HandleRange.start_handle = _mServiceStartHandle;
    HandleRange.end_handle = _mServiceEndHandle;

    _mErrorCode = sd_ble_gattc_characteristics_discover(_mAdapter, _mConnectionHandle, &HandleRange);
    if(_mErrorCode != NRF_SUCCESS)
    {
        DEBUG << "sd_ble_gattc_characteristics_discover() failed, reason: " << hex << _mErrorCode;
        return;
    }
}

void Qt_BLE::on_Characteristic_Discovery_Response(const ble_gattc_evt_t* const p_Event)
{
    ble_gattc_handle_range_t HandleRange;

    if(p_Event->gatt_status != NRF_SUCCESS)
    {
        DEBUG << "Characteristic discovery failed. Error code 0x" << p_Event->gatt_status;
        return;
    }

    DEBUG << "Received characteristic discovery response, characteristics count: " << p_Event->params.char_disc_rsp.count;

    for(int i = 0; i < p_Event->params.char_disc_rsp.count; i++)
    {
        DEBUG << "Characteristic handle: 0x" << hex <<p_Event->params.char_disc_rsp.chars[i].handle_decl << ", UUID: 0x" << hex << p_Event->params.char_disc_rsp.chars[i].uuid.uuid;

        if(p_Event->params.char_disc_rsp.chars[i].uuid.uuid == _mDeviceCharUUID)
        {
            _mCharHandle = p_Event->params.char_disc_rsp.chars[i].handle_decl;
        }
    }

    DEBUG << "Discovering characteristic's descriptors";

    if(_mCharHandle == 0)
    {
        DEBUG << "No characteristic handle found";
        return;
    }

    HandleRange.start_handle = _mCharHandle;
    HandleRange.end_handle = _mServiceEndHandle;

    _mErrorCode = sd_ble_gattc_descriptors_discover(_mAdapter, _mConnectionHandle, &HandleRange);
    if(_mErrorCode != NRF_SUCCESS)
    {
        DEBUG << "sd_ble_gattc_descriptors_discover() failed, reason: " << hex << _mErrorCode;
    }
}

void Qt_BLE::on_Descriptor_Discovery_Response(const ble_gattc_evt_t* const p_Event)
{
    if(p_Event->gatt_status != NRF_SUCCESS)
    {
        DEBUG << "Descriptor discovery failed. Error code 0x" << hex << p_Event->gatt_status;
    }

    DEBUG << "Received descriptor discovery response, descriptor count: " << p_Event->params.desc_disc_rsp.count;

    for(int i = 0; i < p_Event->params.desc_disc_rsp.count; i++)
    {
        DEBUG << "Descriptor handle: 0x" << hex << p_Event->params.desc_disc_rsp.descs[i].handle << ", UUID: 0x" << hex << p_Event->params.desc_disc_rsp.descs[i].uuid.uuid;

        if(p_Event->params.desc_disc_rsp.descs[i].uuid.uuid == BLE_UUID_CCCD)
        {
            _mCCCDHandle = p_Event->params.desc_disc_rsp.descs[i].handle;

            ble_gattc_write_params_t write_params;
            uint8_t                  cccd_value[2] = {0x01, 0};

            DEBUG << "Setting HRM CCCD";

            if(_mCCCDHandle == 0)
            {
                DEBUG << "Error. No CCCD handle has been found";
            }

            write_params.handle     = _mCCCDHandle;
            write_params.len        = 2;
            write_params.p_value    = cccd_value;
            write_params.write_op   = BLE_GATT_OP_WRITE_REQ;
            write_params.offset     = 0;

            sd_ble_gattc_write(_mAdapter, _mConnectionHandle, &write_params);
        }
    }
}

void Qt_BLE::on_Write_Response(const ble_gattc_evt_t* const p_Event)
{
    DEBUG << "Received write response.";

    if(p_Event->gatt_status != NRF_SUCCESS)
    {
        DEBUG << "Error. Write operation failed. Error code: 0x" << hex << p_Event->gatt_status;
    }
}

void Qt_BLE::on_Conn_Params_Update_Request(const ble_gap_evt_t* const p_Event)
{
    _mErrorCode = sd_ble_gap_conn_param_update(_mAdapter, _mConnectionHandle, &(p_Event->params.conn_param_update_request.conn_params));
    if(_mErrorCode != NRF_SUCCESS)
    {
        DEBUG << "Conn params update failed, Error code: " << hex << _mErrorCode;
    }
}

void Qt_BLE::on_Exchange_MTU_Request(const ble_gatts_evt_t* const)
{
    _mErrorCode = sd_ble_gatts_exchange_mtu_reply(_mAdapter, _mConnectionHandle, BLE_GATT_ATT_MTU_DEFAULT);

    if(_mErrorCode != NRF_SUCCESS)
    {
        DEBUG << "MTU exchange request reply failed, err_code: 0x" << hex << _mErrorCode;
    }
}

Parents Reply Children
No Data
Related