Commit bbb027ba authored by schneider's avatar schneider

feat(ble): epicardium support for retrieving scan reports

parent c0a3ed9e
......@@ -45,10 +45,15 @@
#include "api/interrupt-sender.h"
#include "modules/log.h"
#define SCAN_REPORTS_NUM 16
static bool active;
static uint8_t advertising_mode = APP_MODE_NONE;
static uint8_t advertising_mode_target = APP_MODE_NONE;
static enum ble_event_type ble_event;
static struct epic_scan_report scan_reports[SCAN_REPORTS_NUM];
static int scan_reports_head;
static int scan_reports_tail;
/**************************************************************************************************
Macros
......@@ -188,6 +193,15 @@ static const uint8_t bleAdvDataConn[] =
DM_FLAG_LE_BREDR_NOT_SUP,
};
static const appMasterCfg_t scannerMasterCfg =
{
420, /*! The scan interval, in 0.625 ms units */
420, /*! The scan window, in 0.625 ms units */
0, /*! The scan duration in ms */
DM_DISC_MODE_NONE, /*! The GAP discovery mode */
DM_SCAN_TYPE_PASSIVE
/*!< The scan type (active or passive) */
};
/**************************************************************************************************
Client Characteristic Configuration Descriptors
......@@ -472,15 +486,45 @@ static void bleSetup(bleMsg_t *pMsg)
active = true;
/* TODO: Sadly, not advertising leads to a higher current consumption... */
epic_ble_set_bondable(false);
epic_ble_set_mode(false, false);
}
void epic_ble_set_bondable(bool bondable)
void epic_ble_set_mode(bool bondable, bool scanner)
{
if(!active) {
return;
}
if(scanner && bondable) {
/* TODO: return error */
return;
}
if(scanner) {
if(advertising_mode != APP_MODE_NONE) {
advertising_mode_target = APP_MODE_NONE;
advertising_mode = APP_MODE_NONE;
AppAdvStop();
}
dmConnId_t connId;
if ((connId = AppConnIsOpen()) != DM_CONN_ID_NONE) {
AppConnClose(connId);
}
/* Normal scanning filters out duplicates. We don't
* want that for now... */
//AppScanStart(scannerMasterCfg.discMode, scannerMasterCfg.scanType, scannerMasterCfg.scanDuration);
DmScanSetInterval(HCI_SCAN_PHY_LE_1M_BIT, &pAppMasterCfg->scanInterval,
&pAppMasterCfg->scanWindow);
DmScanStart(HCI_SCAN_PHY_LE_1M_BIT, scannerMasterCfg.discMode,
&scannerMasterCfg.scanType, FALSE, scannerMasterCfg.scanDuration, 0);
return;
} else {
AppScanStop();
}
if(bondable) {
/* We need to stop advertising in between or the
* adv set will not be changed.
......@@ -576,6 +620,48 @@ static void bleHandleNumericComparison(dmSecCnfIndEvt_t *pCnfInd)
trigger_event(BLE_EVENT_HANDLE_NUMERIC_COMPARISON);
}
int epic_ble_get_scan_report(struct epic_scan_report *rpt)
{
if(scan_reports_head == scan_reports_tail) {
return -ENOENT;
}
int new_tail = (scan_reports_tail + 1) % SCAN_REPORTS_NUM;
*rpt = scan_reports[new_tail];
scan_reports_tail = new_tail;
return 0;
}
static void scannerScanReport(dmEvt_t *pMsg)
{
struct epic_scan_report *scan_report;
int next_head = (scan_reports_head + 1) % SCAN_REPORTS_NUM;
if(next_head == scan_reports_tail) {
trigger_event(BLE_EVENT_SCAN_REPORT);
return;
}
scan_reports_head = next_head;
scan_report = &scan_reports[scan_reports_head];
memset(scan_report->data, 0, sizeof(scan_report->data));
memccpy(scan_report->data, pMsg->scanReport.pData, pMsg->scanReport.len, sizeof(scan_report->data));
scan_report->len = pMsg->scanReport.len;
scan_report->rssi = pMsg->scanReport.rssi;
scan_report->eventType = pMsg->scanReport.eventType;
scan_report->addrType = pMsg->scanReport.addrType;
memcpy(scan_report->addr, pMsg->scanReport.addr, BDA_ADDR_LEN);
scan_report->directAddrType = pMsg->scanReport.directAddrType;
memcpy(scan_report->directAddr, pMsg->scanReport.directAddr, BDA_ADDR_LEN);
trigger_event(BLE_EVENT_SCAN_REPORT);
if((scan_reports_head + 1) % SCAN_REPORTS_NUM == scan_reports_tail) {
LOG_WARN("ble", "Application missing scan results");
}
}
/*************************************************************************************************/
/*!
* \brief Process messages from the event handler.
......@@ -610,10 +696,9 @@ static void bleProcMsg(bleMsg_t *pMsg)
case DM_ADV_START_IND:
LOG_INFO("ble", "Advertisement started %u %u", advertising_mode, advertising_mode_target);
if(advertising_mode != advertising_mode_target) {
if(advertising_mode != advertising_mode_target || advertising_mode_target == APP_MODE_NONE) {
AppAdvStop();
}
break;
case DM_ADV_STOP_IND:
......@@ -719,6 +804,10 @@ static void bleProcMsg(bleMsg_t *pMsg)
bleHandleNumericComparison(&pMsg->dm.cnfInd);
break;
case DM_SCAN_REPORT_IND:
scannerScanReport((dmEvt_t *)pMsg);
break;
case DM_HW_ERROR_IND:
LOG_ERR("ble", "HW Error");
break;
......@@ -749,6 +838,7 @@ static void BleHandlerInit(void)
pAppSlaveCfg = (appSlaveCfg_t *) &bleSlaveCfg;
pAppSecCfg = (appSecCfg_t *) &bleSecCfg;
pAppUpdateCfg = (appUpdateCfg_t *) &bleUpdateCfg;
pAppMasterCfg = (appMasterCfg_t *) &scannerMasterCfg;
/* Initialize application framework */
AppSlaveInit();
......@@ -779,7 +869,7 @@ static void BleHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg)
if (pMsg->event >= DM_CBACK_START && pMsg->event <= DM_CBACK_END)
{
LOG_INFO("ble", "Ble got evt %d: %s", pMsg->event, dm_events[pMsg->event - DM_CBACK_START]);
if(pMsg->event != DM_SCAN_REPORT_IND) LOG_INFO("ble", "Ble got evt %d: %s", pMsg->event, dm_events[pMsg->event - DM_CBACK_START]);
/* process advertising and connection-related messages */
AppSlaveProcDmMsg((dmEvt_t *) pMsg);
......
......@@ -130,11 +130,7 @@ void StackInit(void)
.freeMemAvail = LL_MEMORY_FOOTPRINT
};
#ifdef DATS_APP_USE_LEGACY_API
memUsed = LlInitControllerExtInit(&ll_init_cfg);
#else /* DATS_APP_USE_LEGACY_API */
memUsed = LlInitControllerExtInit(&ll_init_cfg);
#endif /* DATS_APP_USE_LEGACY_API */
if(memUsed != LL_MEMORY_FOOTPRINT)
{
printf("Controller memory mismatch 0x%x != 0x%x\n", (unsigned int)memUsed,
......@@ -142,6 +138,11 @@ void StackInit(void)
}
#endif
SecInit();
SecRandInit();
SecAesInit();
SecCmacInit();
SecEccInit();
/* card10:
* These calls register a queue for callbacks in the OS abstraction
......@@ -153,14 +154,10 @@ void StackInit(void)
handlerId = WsfOsSetNextHandler(HciHandler);
HciHandlerInit(handlerId);
SecInit();
SecAesInit();
SecCmacInit();
SecEccInit();
handlerId = WsfOsSetNextHandler(DmHandler);
DmDevVsInit(0);
DmAdvInit();
DmScanInit();
DmConnInit();
DmConnSlaveInit();
DmSecInit();
......
......@@ -149,10 +149,11 @@ typedef _Bool bool;
#define API_CONFIG_GET_BOOLEAN 0x132
#define API_CONFIG_SET_STRING 0x133
#define API_BLE_GET_COMPARE_VALUE 0x140
#define API_BLE_COMPARE_RESPONSE 0x141
#define API_BLE_SET_BONDABLE 0x142
#define API_BLE_GET_EVENT 0x143
#define API_BLE_GET_COMPARE_VALUE 0x140
#define API_BLE_COMPARE_RESPONSE 0x141
#define API_BLE_SET_MODE 0x142
#define API_BLE_GET_EVENT 0x143
#define API_BLE_GET_SCAN_REPORT 0x144
/* clang-format on */
......@@ -2036,7 +2037,7 @@ API(API_USB_CDCACM, int epic_usb_cdcacm(void));
/**
* Takes a gpio pin specified with the gpio module and transmits
* the led data. The format `GG:RR:BB` is expected.
* the led data. The format ``GG:RR:BB`` is expected.
*
* :param uint8_t pin: The gpio pin to be used for data.
* :param uint8_t * pixels: The buffer, in which the pixel data is stored.
......@@ -2135,9 +2136,29 @@ enum ble_event_type {
BLE_EVENT_PAIRING_FAILED = 2,
/** A pairing procedure has successfully completed */
BLE_EVENT_PAIRING_COMPLETE = 3,
/** New scan data is available */
BLE_EVENT_SCAN_REPORT = 4,
};
/**
* Scan report data. Bases on ``hciLeAdvReportEvt_t`` from BLE stack.
*
* TODO: 64 bytes for data is an arbitrary number ATM */
struct epic_scan_report
{
uint8_t data[64]; /*!< \brief advertising or scan response data. */
uint8_t len; /*!< \brief length of advertising or scan response data. */
int8_t rssi; /*!< \brief RSSI. */
uint8_t eventType; /*!< \brief Advertising event type. */
uint8_t addrType; /*!< \brief Address type. */
uint8_t addr[6]; /*!< \brief Device address. */
/* \brief direct fields */
uint8_t directAddrType; /*!< \brief Direct advertising address type. */
uint8_t directAddr[6]; /*!< \brief Direct advertising address. */
};
/**
* **Interrupt Service Routine** for :c:data:`EPIC_INT_BLE`
*
......@@ -2202,22 +2223,44 @@ API(API_BLE_GET_COMPARE_VALUE, uint32_t epic_ble_get_compare_value(void));
API(API_BLE_COMPARE_RESPONSE, void epic_ble_compare_response(bool confirmed));
/**
* Allow or disallow new bondings to happen
* Set the desired mode of the BLE stack.
*
* There are three allowed modes:
*
* - Peripheral which is not bondable (bondable = ``false``, scanner = ``false``).
* - Peripheral which is bondable (bondable = ``true``, scanner = ``false``).
* - Observer which scans for advertisements (bondable = ``false``, scanner = ``true``).
*
* By default the card10 will not allow new bondings to be made. New
* bondings have to explicitly allowed by calling this function.
*
* While bonadable the card10 will change its advertisements to
* While bondable the card10 will change its advertisements to
* indicate to scanning hosts that it is available for discovery.
*
* When scanning is active, :c:data:`BLE_EVENT_SCAN_REPORT` events will be sent
* and the scan reports can be fetched using :c:func:`epic_ble_get_scan_report`.
*
* When switching applications new bondings are automatically
* disallowed.
* disallowed and scanning is stopped.
*
* :param bool bondable: `true` if new bondings should be allowed.
* :param bool scanner: `true` if scanning should be turned on.
*
* .. versionadded:: 1.16
*/
API(API_BLE_SET_BONDABLE, void epic_ble_set_bondable(bool bondable));
API(API_BLE_SET_MODE, void epic_ble_set_mode(bool bondable, bool scanner));
/**
* Retrieve a scan report from the queue of scan reports.
*
* :param struct epic_scan_report* rpt: Pointer where the report will be stored.
*
* :return: `0` on success or a negative value if an error occured. Possible
* errors:
*
* - ``-ENOENT``: No scan report available
*
*/
API(API_BLE_GET_SCAN_REPORT, int epic_ble_get_scan_report(struct epic_scan_report *rpt));
#endif /* _EPICARDIUM_H */
......@@ -292,7 +292,7 @@ int hardware_reset(void)
/*
* BLE
*/
epic_ble_set_bondable(false);
epic_ble_set_mode(false, false);
return 0;
}
......@@ -421,6 +421,7 @@ ble_compileargs = [
'-DINIT_BROADCASTER',
'-DINIT_PERIPHERAL',
'-DINIT_ENCRYPTED',
'-DINIT_OBSERVER',
]
if get_option('ble_trace')
......
......@@ -33,7 +33,7 @@ static MP_DEFINE_CONST_FUN_OBJ_0(ble_get_event_obj, mp_ble_get_event);
static mp_obj_t mp_ble_set_bondable(mp_obj_t bondable_obj)
{
bool bondable = mp_obj_is_true(bondable_obj);
epic_ble_set_bondable(bondable);
epic_ble_set_mode(bondable, false);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(ble_set_bondable_obj, mp_ble_set_bondable);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment