Skip to content

Commit fbe9312

Browse files
Add rf tester commands to cordio hci driver. This adds commands that allow you to send the HCI commands HCI_LE_Receiver_Test, HCI_LE_Transmitter_Test and HCI_LE_Test_End. The results of the test are obtained by the command complete command for HCI_LE_Test_End and passed to the user by the callback register in the test start calls.
1 parent 51d1a30 commit fbe9312

File tree

3 files changed

+140
-0
lines changed

3 files changed

+140
-0
lines changed

features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCIDriver.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,83 @@ uint16_t CordioHCIDriver::write(uint8_t type, uint16_t len, uint8_t *pData)
286286
void CordioHCIDriver::on_host_stack_inactivity()
287287
{
288288
}
289+
void CordioHCIDriver::handle_test_end(bool success, uint16_t packets) {
290+
if (_test_end_handler) {
291+
_test_end_handler(success, packets);
292+
_test_end_handler = nullptr;
293+
}
294+
}
295+
296+
ble_error_t CordioHCIDriver::rf_test_start_le_receiver_test(
297+
test_end_handler_t test_end_handler, uint8_t channel
298+
)
299+
{
300+
if (_test_end_handler) {
301+
return BLE_ERROR_INVALID_STATE;
302+
}
303+
304+
if (!test_end_handler) {
305+
return BLE_ERROR_INVALID_PARAM;
306+
}
307+
308+
_test_end_handler = test_end_handler;
309+
uint8_t *buf = hciCmdAlloc(HCI_OPCODE_LE_RECEIVER_TEST, HCI_LEN_LE_RECEIVER_TEST);
310+
311+
if (buf) {
312+
uint8_t* p = buf + HCI_CMD_HDR_LEN;
313+
UINT8_TO_BSTREAM(p, channel);
314+
hciCmdSend(buf);
315+
316+
return BLE_ERROR_NONE;
317+
}
318+
319+
return BLE_ERROR_NO_MEM;
320+
}
321+
322+
ble_error_t CordioHCIDriver::rf_test_start_le_transmitter_test(
323+
test_end_handler_t test_end_handler, uint8_t channel, uint8_t length, uint8_t type
324+
)
325+
{
326+
if (_test_end_handler) {
327+
return BLE_ERROR_INVALID_STATE;
328+
}
329+
330+
if (!test_end_handler) {
331+
return BLE_ERROR_INVALID_PARAM;
332+
}
333+
334+
_test_end_handler = test_end_handler;
335+
uint8_t *buf = hciCmdAlloc(HCI_OPCODE_LE_TRANSMITTER_TEST, HCI_LEN_LE_TRANSMITTER_TEST);
336+
337+
if (buf) {
338+
uint8_t* p = buf + HCI_CMD_HDR_LEN;
339+
UINT8_TO_BSTREAM(p, channel);
340+
UINT8_TO_BSTREAM(p, length);
341+
UINT8_TO_BSTREAM(p, type);
342+
hciCmdSend(buf);
343+
344+
return BLE_ERROR_NONE;
345+
}
346+
347+
return BLE_ERROR_NO_MEM;
348+
}
349+
350+
ble_error_t CordioHCIDriver::rf_test_end()
351+
{
352+
if (!_test_end_handler) {
353+
return BLE_ERROR_INVALID_STATE;
354+
}
355+
356+
uint8_t *buf = hciCmdAlloc(HCI_OPCODE_LE_TEST_END, HCI_LEN_LE_TEST_END);
357+
358+
if (buf) {
359+
hciCmdSend(buf);
360+
361+
return BLE_ERROR_NONE;
362+
}
363+
364+
return BLE_ERROR_NO_MEM;
365+
}
289366

290367
} // namespace cordio
291368
} // namespace vendor

features/FEATURE_BLE/targets/TARGET_CORDIO/driver/CordioHCIDriver.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include <BLETypes.h>
2323
#include "wsf_buf.h"
2424
#include "CordioHCITransportDriver.h"
25+
#include "ble/blecommon.h"
26+
#include "mbed.h"
2527

2628
namespace ble {
2729
namespace vendor {
@@ -144,6 +146,47 @@ class CordioHCIDriver {
144146
*/
145147
virtual void on_host_stack_inactivity();
146148

149+
/* BLE Tester commands */
150+
151+
/**
152+
* This will be called by host part of the stack to indicate the end of the test.
153+
*
154+
* @param success True if the TEST END command was a success.
155+
* @param packets Number of packets received during the test.
156+
* @return BLE_ERROR_NONE on success.
157+
*/
158+
void handle_test_end(bool success, uint16_t packets);
159+
160+
/** Callback to inform the caller of the result of the test, the parameters are success and the
161+
* number of packets received.
162+
*/
163+
typedef mbed::Callback<void(bool, uint16_t)> test_end_handler_t;
164+
165+
/**
166+
* Start BLE receiver test. Call rf_test_end when you want to stop.
167+
* @param test_end_handler Handler that will be called with the number of packets received.
168+
* @param channel Channel to use.
169+
* @return BLE_ERROR_NONE on success.
170+
*/
171+
ble_error_t rf_test_start_le_receiver_test(test_end_handler_t test_end_handler, uint8_t channel);
172+
173+
/**
174+
* Start BLE transmitter test. Call rf_test_end when you want to stop.
175+
* @param test_end_handler Handler that will be called with status and the number of packets set to 0.
176+
* @param channel Channel to use.
177+
* @param length Size of payload.
178+
* @param type Type of pattern to transmit @see BLE spec Volume 6 Part F, Section 4.1.5.
179+
* @return BLE_ERROR_NONE on success.
180+
*/
181+
ble_error_t rf_test_start_le_transmitter_test(test_end_handler_t test_end_handler, uint8_t channel,
182+
uint8_t length, uint8_t type);
183+
184+
/**
185+
* Complete the test. This will trigger the end test event which will call handle_test_end
186+
* @return BLE_ERROR_NONE on success.
187+
*/
188+
ble_error_t rf_test_end();
189+
147190
protected:
148191
/**
149192
* Return a default set of memory pool that the Cordio stack can use.
@@ -170,6 +213,9 @@ class CordioHCIDriver {
170213
*/
171214
virtual void do_terminate() = 0;
172215

216+
protected:
217+
test_end_handler_t _test_end_handler;
218+
private:
173219
CordioHCITransportDriver& _transport_driver;
174220
};
175221

features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "hci_drv.h"
3535
#include "CordioBLE.h"
3636
#include "mbed_assert.h"
37+
#include "bstream.h"
3738

3839
#include "CordioPalAttClient.h"
3940
#include "CordioPalSecurityManager.h"
@@ -311,6 +312,22 @@ void BLE::processEvents()
311312
deviceInstance().initialization_status = INITIALIZED;
312313
_init_callback.call(&context);
313314
} break;
315+
#if MBED_CONF_CORDIO_ROUTE_UNHANDLED_COMMAND_COMPLETE_EVENTS
316+
case DM_UNHANDLED_CMD_CMPL_EVT_IND: {
317+
// upcast to unhandled command complete event to access the payload
318+
hciUnhandledCmdCmplEvt_t* unhandled = (hciUnhandledCmdCmplEvt_t*)msg;
319+
if (unhandled->hdr.status == HCI_SUCCESS && unhandled->hdr.param == HCI_OPCODE_LE_TEST_END) {
320+
// unhandled events are not parsed so we need to parse the payload ourselves
321+
uint8_t status;
322+
uint16_t packet_number;
323+
status = unhandled->param[0];
324+
BYTES_TO_UINT16(packet_number, unhandled->param + 1);
325+
326+
_hci_driver->handle_test_end(status == 0, packet_number);
327+
return;
328+
}
329+
}
330+
#endif // MBED_CONF_CORDIO_ROUTE_UNHANDLED_COMMAND_COMPLETE_EVENTS
314331

315332
default:
316333
impl::PalGapImpl::gap_handler(msg);

0 commit comments

Comments
 (0)