WHAD Device discovery

When a host computer starts communicating with a WHAD interface, it sends a series of message to discover its characteristics and its supported domains in order to tailor the host features and match the capabilities exposed by the interface.

Discovery of interface characteristics

First, the host sends a DeviceInfoQuery message to the WHAD interface that is expected to responds with a DeviceInfoResp message. This message must provide the following information:

  • the device type

  • the device unique ID

  • the minimum supported version of WHAD protocol

  • the device maximum communication speed

  • the author name (limited to 64 characters)

  • the firmware project URL (linited to 256 characters)

  • the firmware major version number

  • the firmware minor version number

  • the firmware revision number

  • a list of capabilities

To build such a message, we need to define first our capabilities:

const whad_domain_desc_t CAPABILITIES[] = {
    {
        /* We support the Bluetooth Low Energy wireless protocol. */
        DOMAIN_BTLE,

        /* For this protocol, we are able to sniff, inject and emulate
           central and peripheral roles. */
        (whad_capability_t)(CAP_SNIFF | CAP_INJECT | CAP_SIMULATE_ROLE),

        /* We define the list of supported commands, based on NanoPb command values. */
        (
        CMD(ble_BleCommand_SniffAdv) |
        CMD(ble_BleCommand_SniffConnReq) |
        CMD(ble_BleCommand_SniffActiveConn) |
        CMD(ble_BleCommand_Start) |
        CMD(ble_BleCommand_Stop) |
        CMD(ble_BleCommand_SendRawPDU) |
        CMD(ble_BleCommand_SendPDU) |
        CMD(ble_BleCommand_CentralMode) |
        CMD(ble_BleCommand_PeripheralMode) |
        CMD(ble_BleCommand_ConnectTo) |
        CMD(ble_BleCommand_Disconnect) |
        CMD(ble_BleCommand_PrepareSequence) |
        CMD(ble_BleCommand_TriggerSequence) |
        CMD(ble_BleCommand_DeleteSequence) |
        CMD(ble_BleCommand_ScanMode)

        )
    },

    /* End of supported domains, MUST be there to mark the end of this list. */
    {DOMAIN_NONE, CAP_NONE, 0x00000000}
};

Once our capabilities defined, we can build the response message:

Message response;
whad_result_t result;

/* Create a device info response. */
result = whad_discovery_device_info_resp(
    /* Pointer to our response message. */
    &response,

    /* Butterfly device, does not really matter. */
    discovery_DeviceType_Butterfly,

    /* "Unique" device ID, usually customized */
    (uint8_t *)"MyAwesomeDevice",

    /* Supports WHAD protocol v2 */
    2,

    /* Max speed for our UART hw */
    115200,

    /* Firmware author. */
    "John Doe <jdoe@example.org",

    /* Firmware project URL. */
    "https://github.com/whad-team/demofw",

    /* Firmware version: major, minor, rev. */
    1, 0, 0,

    /* Capabilities as defined above. */
    CAPABILITIES
);

Note

The CAPABILITIES structure created above is used by both whad_discovery_device_info_resp() and whad_discovery_domain_info_resp() to provide the host with the supported domains and the related interface capabilities for the first one, and the supported commands for a specific domain for the second one.

Discovery of supported commands for a given domain

Once the host has discovered the device’ supported domains and its capabilities, it queries the WHAD interface to retrieve the implemented commands for each supported domain by sending multiple DeviceDomainInfoQuery messages.

Each of these messages must be answered by the WHAD interface with a DeviceDomainInfoResp specifying the supported commands for the requested domain. This message can be created through the whad_discovery_domain_info_resp() function, as shown below:

void process_discovery_message(Message *message)
{
    whad_result_t result;
    whad_domain_t domain;
    Message response;

    /* ... */

    /* Process any discovery message. */
    switch(whad_discovery_get_message_type(message))
    {
        /* DeviceDomainInfoQuery message. */
        case WHAD_DISCOVERY_DOMAIN_INFO_QUERY:
        {
            /* Parse incoming message. */
            if (whad_discovery_domain_info_query_parse(message, &domain) == WHAD_SUCCESS)
            {
                /* Fill response message with DeviceDomainInfoResp. */
                whad_discovery_domain_info_resp(
                    &response,
                    domain,
                    CAPABILITIES
                );
            }
            else
            {
                /* Error. */
                whad_generic_cmd_result(&response, WHAD_RESULT_ERROR);
            }
        }
        break;

        /* ... */
    }

}

Note

whad_discovery_domain_info_resp() will pick the corresponding supported commands from the provided capabilities array and build a valid message from it.

Transport speed update

The WHAD interface, in its DeviceInfoResp message, provides the host with its maximum communication speed and the host can at anytime decide to switch to that speed to get faster communication. This speed change is requested by the host through a SetTransportSpeed message. This message must be acknowledged by the WHAD interface before setting up the hardware to use this new speed setting.

First, the WHAD interface needs to create and send a generic CommandResult message with a result code of WHAD_RESULT_SUCCESS and then setup the new communication speed. Once the new speed configured and in use, the WHAD interface must send a new DeviceReadyResp message to let the host know that it is ready to operate.

Message response;


/* Send a success result code. */
whad_generic_cmd_result(&response, WHAD_RESULT_SUCCESS);
whad_send_message(&response);

/* Re-configure communication hardware with new speed. */

/* Once done and ready, send a DeviceReadyResp to host. */
whad_discovery_device_ready_resp(&response);
whad_send_message(&response);

Discovery message processing template

The following code is a basic code template for processing discovery messages:

void process_discovery_message(Message *message)
{
    whad_result_t result;
    whad_domain_t domain;
    uint32_t proto_version;
    Message response;

    /* Process any discovery message. */
    switch(whad_discovery_get_message_type(message))
    {

        /* DeviceInfoQuery message. */
        case WHAD_DISCOVERY_DEVICE_INFO_QUERY:
        {
            /* Parse incoming message. */
            if (whad_discovery_device_info_query_parse(message, &proto_version) == WHAD_SUCCESS)
            {
                /* Make sure we support the provided protocol version. */
                if (proto_version >= 2)
                {
                    /* Fill response message with DeviceInfoResp. */
                    whad_discovery_domain_info_resp(
                        &response,
                        domain,
                        CAPABILITIES
                    );
                }
                else
                {
                    /* Client protocol version is too old. */
                    whad_generic_cmd_result(&response, WHAD_RESULT_ERROR);
                }
            }
            else
            {
                /* Error. */
                whad_generic_cmd_result(&response, WHAD_RESULT_ERROR);
            }
        }
        break;

        /* DeviceDomainInfoQuery message. */
        case WHAD_DISCOVERY_DOMAIN_INFO_QUERY:
        {
            /* Parse incoming message. */
            if (whad_discovery_domain_info_query_parse(message, &domain) == WHAD_SUCCESS)
            {
                /* Fill response message with DeviceDomainInfoResp. */
                whad_discovery_domain_info_resp(
                    &response,
                    domain,
                    CAPABILITIES
                );
            }
            else
            {
                /* Error. */
                whad_generic_cmd_result(&response, WHAD_RESULT_ERROR);
            }
        }
        break;

        /* SetTransportSpeed */
        case WHAD_DISCOVERY_SET_TRANSPORT_SPEED:
        {
            /* Send a success result code. */
            whad_generic_cmd_result(&response, WHAD_RESULT_SUCCESS);
            whad_send_message(&response);
            whad_transport_send_pending();

            /* Re-configure communication hardware with new speed. */

            /* Once done and ready, send a DeviceReadyResp to host. */
            whad_discovery_device_ready_resp(&response);
            whad_send_message(&response);
        }
        break;

        /* DeviceResetQuery */
        case WHAD_DISCOVERY_DEVICE_RESET_QUERY:
        {
            /* Reset WHAD interface state. */
            interface_reset_state();

            /* Send a DeviceReadyResp. */
            whad_discovery_ready_resp(&response);
        }
        break;

        default:
        {
            /* Unsupported command. */
            whad_generic_cmd_result(&response, WHAD_RESULT_ERROR);
        }
        break;
    }
}

Discovery API reference

Defines

BAUDRATE_MAX

Enums

enum whad_domain_t

Values:

enumerator DOMAIN_NONE

Domain is unknown

enumerator DOMAIN_PHY

PHY domain

enumerator DOMAIN_BT_CLASSIC

Bluetooth Classic domain

enumerator DOMAIN_BTLE

Bluetooth Low Energy domain

enumerator DOMAIN_DOT15D4

IEEE802.15.4 domain

enumerator DOMAIN_SIXLOWPAN

6LowPAN domain

enumerator DOMAIN_ESB

Enhanced ShockBurst domain

enumerator DOMAIN_LOGITECH_UNIFYING

Logitech Unifying domain

enumerator DOMAIN_MOSART

Mosart domain

enumerator DOMAIN_ANT

ANT domain

enumerator DOMAIN_ANT_PLUS

ANT+ domain

enumerator DOMAIN_ANT_FS

ANT FS domain

enum whad_capability_t

Values:

enumerator CAP_NONE

No capability

enumerator CAP_SCAN

Can scan other devices

enumerator CAP_SNIFF

Can sniff packets/data

enumerator CAP_INJECT

Can inject packets/data

enumerator CAP_JAM

Can jam

enumerator CAP_HIJACK

Can hijack connection

enumerator CAP_HOOK

Can hook connection

enumerator CAP_SIMULATE_ROLE

Can simulate a role

enumerator CAP_NO_RAW_DATA

Cannot access raw data

enum whad_discovery_msgtype_t

Values:

enumerator WHAD_DISCOVERY_UNKNOWN
enumerator WHAD_DISCOVERY_DEVICE_INFO_QUERY
enumerator WHAD_DISCOVERY_DEVICE_INFO_RESP
enumerator WHAD_DISCOVERY_DEVICE_RESET
enumerator WHAD_DISCOVERY_READY_RESP
enumerator WHAD_DISCOVERY_DOMAIN_INFO_QUERY
enumerator WHAD_DISCOVERY_DOMAIN_INFO_RESP
enumerator WHAD_DISCOVERY_SET_SPEED

Functions

whad_discovery_msgtype_t whad_discovery_get_message_type(Message *p_message)
bool whad_discovery_is_domain_supported(const whad_domain_desc_t *p_capabilities, whad_domain_t domain)
bool whad_disc_enum_capabilities_cb(pb_ostream_t *ostream, const pb_field_t *field, void *const *arg)
uint64_t whad_discovery_get_supported_commands(whad_domain_t domain, whad_domain_desc_t *p_capabilities)
whad_result_t whad_discovery_device_info_query(Message *p_message, uint32_t proto_version)

Initialize a discovery device info query.

Parameters:
  • p_message[inout] Pointer to the message structure to initialize

  • proto_version[in] Version of the WHAD protocol supported by the sender

Return values:
  • WHAD_SUCCESS – Success.

  • WHAD_ERROR – Invalid message pointer.

whad_result_t whad_discovery_device_info_query_parse(Message *p_message, uint32_t *p_proto_version)

Parse a discovery device info query.

Parameters:
  • p_message[in] Pointer to the message structure to initialize

  • p_proto_version[inout] Pointer to the output protocol version variable

Return values:
  • WHAD_SUCCESS – Success.

  • WHAD_ERROR – Invalid message pointer.

whad_result_t whad_discovery_device_info_resp(Message *p_message, discovery_DeviceType device_type, uint8_t *devid, uint32_t proto_min_ver, uint32_t max_speed, char *fw_author, char *fw_url, uint32_t fw_version_major, uint32_t fw_version_minor, uint32_t fw_version_rev, whad_domain_desc_t *capabilities)

Initialize a discovery device information response message.

Parameters:
  • p_message[inout] Pointer to the message structure to initialize

  • device_type[in] Device type

  • devid[in] Device identifier (text string, max 16 bytes)

  • proto_min_ver[in] WHAD protocol minimum supported version

  • max_speed[in] Maximum USART speed supported by the device

  • fw_author[in] Pointer to a text string containing the name of the author

  • fw_url[in] Pointer to a text string containing the URL of the firmware (Github repository, website, etc.)

  • fw_version_major[in] Firmware version major number

  • fw_version_minor[in] Firmware version minor number

  • fw_version_rev[in] Firmware version revision number

  • capabilities[in] Firmware capabilities, as a pointer to a WhadDeviceCapability structure

Return values:
  • WHAD_SUCCESS – Success.

  • WHAD_ERROR – Invalid message pointer.

whad_result_t whad_discovery_domain_info_query(Message *p_message, whad_domain_t domain)

Initialize a discovery device info query.

Parameters:
  • p_message[inout] Pointer to the message structure to initialize

  • domain[in] Domain to query

Return values:
  • WHAD_SUCCESS – Success.

  • WHAD_ERROR – Invalid message pointer.

whad_result_t whad_discovery_domain_info_query_parse(Message *p_message, whad_domain_t *p_domain)

Parse a domain info query.

Parameters:
  • p_message[in] Pointer to the message to parse

  • p_domain[inout] Pointer to the domain contained in the query

Return values:
  • WHAD_SUCCESS – Success.

  • WHAD_ERROR – Invalid message or domain pointer.

whad_result_t whad_discovery_domain_info_resp(Message *p_message, whad_domain_t domain, whad_domain_desc_t *p_capabilities)

Initialize a discovery domain information response message.

Parameters:
  • p_message[inout] Pointer to the message structure to initialize

  • domain[in] Device supported domain

  • p_capabilities[in] Pointer to a whad_domain_desc_t structure defining the supported capabilities

Return values:
  • WHAD_SUCCESS – Success.

  • WHAD_ERROR – Invalid message pointer.

whad_result_t whad_discovery_domain_info_resp_parse(Message *p_message, whad_domain_t *p_domain, uint64_t *p_supp_commands)

Parse a domain info query.

Parameters:
  • p_message[in] Pointer to the message to parse

  • p_domain[inout] Pointer to the domain contained in the query

  • p_supp_commands[inout] Pointer to a supported commands field

Return values:
  • WHAD_SUCCESS – Success.

  • WHAD_ERROR – Invalid message or domain pointer.

whad_result_t whad_discovery_device_reset(Message *p_message)

Initialize a discovery device reset message.

Parameters:

p_message[inout] Pointer to the message structure to initialize

Return values:
  • WHAD_SUCCESS – Success.

  • WHAD_ERROR – Invalid message pointer.

whad_result_t whad_discovery_ready_resp(Message *p_message)

Initialize a discovery ready response message.

Parameters:

p_message[inout] Pointer to the message structure to initialize

Return values:
  • WHAD_SUCCESS – Success.

  • WHAD_ERROR – Invalid message pointer.

whad_result_t whad_discovery_set_speed(Message *p_message, uint32_t speed)

Initialize a device speed configuration message.

Parameters:
  • p_message[inout] Pointer to the message structure to initialize

  • speed[in] Communication speed

Return values:
  • WHAD_SUCCESS – Success.

  • WHAD_ERROR – Invalid message pointer.

whad_result_t whad_discovery_set_speed_parse(Message *p_message, uint32_t *p_speed)

Parse a speed configuration message.

Parameters:
  • p_message[in] Pointer to the message to parse

  • p_speed[inout] Pointer to a uint32_t that will contain the specified speed

Return values:
  • WHAD_SUCCESS – Success.

  • WHAD_ERROR – Invalid message or domain pointer.