From f6add3157a7cd1e331138ba62f0e715fd3e3121b Mon Sep 17 00:00:00 2001 From: schneider <schneider@blinkenlichts.net> Date: Sun, 11 Oct 2020 23:26:53 +0200 Subject: [PATCH] feat(ble): Add ATT client module --- epicardium/ble/ble_api.h | 10 ++ epicardium/ble/ble_attc.c | 270 +++++++++++++++++++++++++++++++++++++ epicardium/ble/ble_main.c | 22 ++- epicardium/ble/meson.build | 1 + epicardium/ble/stack.c | 1 + 5 files changed, 303 insertions(+), 1 deletion(-) create mode 100644 epicardium/ble/ble_attc.c diff --git a/epicardium/ble/ble_api.h b/epicardium/ble/ble_api.h index 84f27ef5d..d46b0fe8e 100644 --- a/epicardium/ble/ble_api.h +++ b/epicardium/ble/ble_api.h @@ -1,5 +1,11 @@ #pragma once +#include <stdint.h> +#include "wsf_types.h" + +#include "att_api.h" +#include "dm_api.h" + #define CARD10_UUID_SUFFIX \ 0x42, 0x23, 0x42, 0x23, 0x42, 0x23, 0x42, 0x23, 0x42, 0x23, 0x42, 0x23 #define CARD10_UUID_PREFIX 0x02, 0x23, 0x42 @@ -16,3 +22,7 @@ /*************************************************************************************************/ void BleStart(void); + +/* ATT client module interface. Used by main BLE module */ +void bleValueUpdate(attEvt_t *pMsg); +void bleDiscCback(dmConnId_t connId, uint8_t status); diff --git a/epicardium/ble/ble_attc.c b/epicardium/ble/ble_attc.c new file mode 100644 index 000000000..3f73f38e0 --- /dev/null +++ b/epicardium/ble/ble_attc.c @@ -0,0 +1,270 @@ +#include <stdint.h> +#include <stdbool.h> + +#include "wsf_types.h" +#include "util/bstream.h" +#include "app_api.h" +#include "app_cfg.h" +#include "att_api.h" +#include "dm_api.h" +#include "gatt/gatt_api.h" +#include "gap/gap_api.h" +#include "tipc/tipc_api.h" + +#include "modules/log.h" +/* card10: + * copied from lib/sdk/Libraries/BTLE/stack/ble-profiles/sources/apps/tag/tag_main.c + * and lib/sdk/Libraries/BTLE/stack/ble-profiles/sources/apps/watch/watch_main.c + */ +/* clang-format off */ +/* clang-formet turned off for easier diffing against orginal file */ + +/************************************************************************************************** + ATT Client Discovery Data +**************************************************************************************************/ + +static uint16_t s_hdlList[APP_DB_HDL_LIST_LEN]; + +/*! the Client handle list, s_hdlList[], is set as follows: + * + * ------------------------------- <- BLE_DISC_GATT_START + * | GATT svc changed handle | + * ------------------------------- + * | GATT svc changed ccc handle | + * ------------------------------- <- BLE_DISC_GAP_START + * | GAP central addr res handle | + * ------------------------------- + * | GAP RPA Only handle | + * ------------------------------- <- BLE_DISC_CTS_START + * | TIPC_CTS_CT_HDL_IDX | + * ------------------------------- + * | TIPC_CTS_CT_CCC_HDL_IDX | + * ------------------------------- + * | TIPC_CTS_LTI_HDL_IDX | + * ------------------------------- + * | TIPC_CTS_RTI_HDL_IDX | + * ------------------------------- + */ + +/*! Start of each service's handles in the the handle list */ +#define BLE_DISC_GATT_START 0 +#define BLE_DISC_GAP_START (BLE_DISC_GATT_START + GATT_HDL_LIST_LEN) +#define BLE_DISC_CTS_START (BLE_DISC_GAP_START + GAP_HDL_LIST_LEN) +#define BLE_DISC_HDL_LIST_LEN (BLE_DISC_CTS_START + TIPC_CTS_HDL_LIST_LEN) + +/*! Pointers into handle list for each service's handles */ +static uint16_t *pBleGattHdlList = &s_hdlList[BLE_DISC_GATT_START]; +static uint16_t *pBleGapHdlList = &s_hdlList[BLE_DISC_GAP_START]; +static uint16_t *pBleCtsHdlList = &s_hdlList[BLE_DISC_CTS_START]; + +/* sanity check: make sure handle list length is <= app db handle list length */ +extern char wsf_ct_assert[(BLE_DISC_HDL_LIST_LEN <= APP_DB_HDL_LIST_LEN) ? 1 : -1]; + +/************************************************************************************************** + ATT Client Data +**************************************************************************************************/ + +/* Default value for GATT service changed ccc descriptor */ +static const uint8_t bleGattScCccVal[] = {UINT16_TO_BYTES(ATT_CLIENT_CFG_INDICATE)}; + +/* List of characteristics to configure */ +static const attcDiscCfg_t bleDiscCfgList[] = +{ + /* Write: GATT service changed ccc descriptor */ + {bleGattScCccVal, sizeof(bleGattScCccVal), (GATT_SC_CCC_HDL_IDX + BLE_DISC_GATT_START)}, + + /* Read: GAP central address resolution attribute */ + {NULL, 0, (GAP_CAR_HDL_IDX + BLE_DISC_GAP_START)}, + + /* Read: CTS Current time */ + {NULL, 0, (TIPC_CTS_CT_HDL_IDX + BLE_DISC_CTS_START)}, + + /* Read: CTS Local time information */ + {NULL, 0, (TIPC_CTS_LTI_HDL_IDX + BLE_DISC_CTS_START)}, + + /* Read: CTS Reference time information */ + {NULL, 0, (TIPC_CTS_RTI_HDL_IDX + BLE_DISC_CTS_START)}, +}; + +/* Characteristic configuration list length */ +#define BLE_DISC_CFG_LIST_LEN (sizeof(bleDiscCfgList) / sizeof(attcDiscCfg_t)) + +/* sanity check: make sure configuration list length is <= handle list length */ +extern char wsf_ct_assert[(BLE_DISC_CFG_LIST_LEN <= BLE_DISC_HDL_LIST_LEN) ? 1 : -1]; + + +/************************************************************************************************** + ATT Client Discovery Data +**************************************************************************************************/ + +/*! Discovery states: enumeration of services to be discovered */ +enum +{ + BLE_DISC_GATT_SVC, /* GATT service */ + BLE_DISC_GAP_SVC, /* GAP service */ + BLE_DISC_SLAVE_CTS_SVC, + BLE_DISC_SVC_MAX /* Discovery complete */ +}; + +/*************************************************************************************************/ +/*! + * \brief Process a received ATT indication. + * + * \param pMsg Pointer to ATT callback event message. + * + * \return None. + */ +/*************************************************************************************************/ +void bleValueUpdate(attEvt_t *pMsg) +{ + if (pMsg->hdr.status == ATT_SUCCESS) + { + /* determine which profile the handle belongs to */ + + /* GATT */ + if (GattValueUpdate(pBleGattHdlList, pMsg) == ATT_SUCCESS) + { + return; + } + + /* GAP */ + if (GapValueUpdate(pBleGapHdlList, pMsg) == ATT_SUCCESS) + { + return; + } + + /* current time */ + if (TipcCtsValueUpdate(pBleCtsHdlList, pMsg) == ATT_SUCCESS) + { + return; + } + + } +} + +/*************************************************************************************************/ +/*! + * \brief GAP service discovery has completed. + * + * \param connId Connection identifier. + * + * \return None. + */ +/*************************************************************************************************/ +static void bleDiscGapCmpl(dmConnId_t connId) +{ + appDbHdl_t dbHdl; + + /* if RPA Only attribute found on peer device */ + if ((pBleGapHdlList[GAP_RPAO_HDL_IDX] != ATT_HANDLE_NONE) && + ((dbHdl = AppDbGetHdl(connId)) != APP_DB_HDL_NONE)) + { + /* update DB */ + AppDbSetPeerRpao(dbHdl, TRUE); + } +} + +/*************************************************************************************************/ +/*! + * \brief Discovery callback. + * + * \param connId Connection identifier. + * \param status Service or configuration status. + * + * \return None. + */ +/*************************************************************************************************/ +void bleDiscCback(dmConnId_t connId, uint8_t status) +{ + static uint8_t discState; + + static const char * const disc_status[] = { + "APP_DISC_INIT", /*!< \brief No discovery or configuration complete */ + "APP_DISC_SEC_REQUIRED", /*!< \brief Security required to complete configuration */ + "APP_DISC_START", /*!< \brief Service discovery started */ + "APP_DISC_CMPL", /*!< \brief Service discovery complete */ + "APP_DISC_FAILED", /*!< \brief Service discovery failed */ + "APP_DISC_CFG_START", /*!< \brief Service configuration started */ + "APP_DISC_CFG_CONN_START", /*!< \brief Configuration for connection setup started */ + "APP_DISC_CFG_CMPL" /*!< \brief Service configuration complete */ + }; + LOG_INFO("ble", "bleDiscCback: %s (%d)", disc_status[status], status); + + switch(status) + { + case APP_DISC_INIT: + /* set handle list when initialization requested */ + AppDiscSetHdlList(connId, BLE_DISC_HDL_LIST_LEN, s_hdlList); + break; + + case APP_DISC_SEC_REQUIRED: + /* request security */ + AppSlaveSecurityReq(connId); + break; + + case APP_DISC_START: + /* initialize discovery state */ + discState = BLE_DISC_GATT_SVC; + + GattDiscover(connId, pBleGattHdlList); + break; + + case APP_DISC_FAILED: + case APP_DISC_CMPL: + if (status == APP_DISC_FAILED && pAppCfg->abortDisc) + { + if (discState == BLE_DISC_GATT_SVC) + { + /* discovery failed */ + AppDiscComplete(connId, APP_DISC_FAILED); + break; + } + } + + /* next discovery state */ + discState++; + + if (discState == BLE_DISC_GAP_SVC) + { + /* discover GAP service */ + GapDiscover(connId, pBleGapHdlList); + } + else if (discState == BLE_DISC_SLAVE_CTS_SVC) + { + /* discover current time service */ + TipcCtsDiscover(connId, pBleCtsHdlList); + } + else + { + /* discovery complete */ + AppDiscComplete(connId, APP_DISC_CMPL); + + /* GAP service discovery completed */ + bleDiscGapCmpl(connId); + + /* start configuration */ + AppDiscConfigure(connId, APP_DISC_CFG_START, BLE_DISC_CFG_LIST_LEN, + (attcDiscCfg_t *) bleDiscCfgList, BLE_DISC_HDL_LIST_LEN, s_hdlList); + } + break; + + case APP_DISC_CFG_START: + /* start configuration */ + AppDiscConfigure(connId, APP_DISC_CFG_START, BLE_DISC_CFG_LIST_LEN, + (attcDiscCfg_t *) bleDiscCfgList, BLE_DISC_HDL_LIST_LEN, s_hdlList); + break; + + case APP_DISC_CFG_CMPL: + AppDiscComplete(connId, APP_DISC_CFG_CMPL); + break; + + case APP_DISC_CFG_CONN_START: + /* no connection setup configuration for this application */ + break; + + default: + break; + } +} + +/* clang-format on */ diff --git a/epicardium/ble/ble_main.c b/epicardium/ble/ble_main.c index 5c6f70da6..30de5536c 100644 --- a/epicardium/ble/ble_main.c +++ b/epicardium/ble/ble_main.c @@ -143,6 +143,12 @@ static const smpCfg_t bleSmpCfg = .attemptExp = 2, /*! Exponent to raise attemptTimeout on maxAttempts */ }; +/*! Configurable parameters for service and characteristic discovery */ +static const appDiscCfg_t bleDiscCfg = +{ + FALSE /*! TRUE to wait for a secure connection before initiating discovery */ +}; + /* Configuration structure */ static const attCfg_t bleAttCfg = { @@ -676,7 +682,6 @@ static void scannerScanReport(dmEvt_t *pMsg) } } - /*************************************************************************************************/ /*! * \brief Process messages from the event handler. @@ -696,6 +701,11 @@ static void bleProcMsg(bleMsg_t *pMsg) BasProcMsg(&pMsg->hdr); break; + case ATTC_READ_RSP: + case ATTC_HANDLE_VALUE_IND: + bleValueUpdate((attEvt_t *) pMsg); + break; + case ATTS_HANDLE_VALUE_CNF: BasProcMsg(&pMsg->hdr); break; @@ -861,10 +871,12 @@ static void BleHandlerInit(void) pAppSlaveCfg = (appSlaveCfg_t *) &bleSlaveCfg; pAppSecCfg = (appSecCfg_t *) &bleSecCfg; pAppUpdateCfg = (appUpdateCfg_t *) &bleUpdateCfg; + pAppDiscCfg = (appDiscCfg_t *) &bleDiscCfg; pAppMasterCfg = (appMasterCfg_t *) &scannerMasterCfg; /* Initialize application framework */ AppSlaveInit(); + AppDiscInit(); /* Set stack configuration pointers */ pSmpCfg = (smpCfg_t *) &bleSmpCfg; @@ -898,10 +910,15 @@ static void BleHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) /* process security-related messages */ AppSlaveSecProcDmMsg((dmEvt_t *) pMsg); + + /* process discovery-related messages */ + AppDiscProcDmMsg((dmEvt_t *) pMsg); } else if (pMsg->event >= ATT_CBACK_START && pMsg->event <= ATT_CBACK_END) { LOG_INFO("ble", "Ble got evt %d: %s", pMsg->event, att_events[pMsg->event - ATT_CBACK_START]); + /* process discovery-related ATT messages */ + AppDiscProcAttMsg((attEvt_t *) pMsg); } else if (pMsg->event >= L2C_COC_CBACK_START && pMsg->event <= L2C_COC_CBACK_CBACK_END) { @@ -936,6 +953,9 @@ void BleStart(void) AttConnRegister(AppServerConnCback); AttsCccRegister(BLE_NUM_CCC_IDX, (attsCccSet_t *) bleCccSet, bleCccCback); + /* Register for app framework discovery callbacks */ + AppDiscRegister(bleDiscCback); + /* Initialize attribute server database */ SvcCoreAddGroup(); SvcDisAddGroup(); // Device Information Service diff --git a/epicardium/ble/meson.build b/epicardium/ble/meson.build index 058022ec9..84b6dbe40 100644 --- a/epicardium/ble/meson.build +++ b/epicardium/ble/meson.build @@ -2,6 +2,7 @@ ble_sources = files( 'ble.c', 'stack.c', 'ble_main.c', + 'ble_attc.c', 'svc_dis.c', 'svc_core.c', 'bondings.c', diff --git a/epicardium/ble/stack.c b/epicardium/ble/stack.c index 35a9d4118..d5e092179 100644 --- a/epicardium/ble/stack.c +++ b/epicardium/ble/stack.c @@ -184,6 +184,7 @@ void StackInit(void) AttHandlerInit(handlerId); AttsInit(); AttsIndInit(); + AttcInit(); handlerId = WsfOsSetNextHandler(SmpHandler); SmpHandlerInit(handlerId); -- GitLab