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
-
enumerator DOMAIN_NONE
-
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
-
enumerator CAP_NONE
-
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
-
enumerator WHAD_DISCOVERY_UNKNOWN
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_tstructure 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.