添加ble gatt blood pressure功能 参考: 【蓝牙】如何新建一个BLE GATT SERVICE
其中上面blog中提到的 用生成的handle
Subject: [PATCH] add blood pressure --- TWS/apps/applications/earbud/av_headset.h | 107 ++++----- TWS/apps/applications/earbud/av_headset_db.db | 3 + TWS/apps/applications/earbud/av_headset_gatt.c | 182 ++++++++++++++- TWS/apps/applications/earbud/av_headset_gatt.h | 23 +- .../earbud/qcc512x_qcc302x/CF376_CF440/earbud.x2p | 4 +- .../profiles/default_qcc512x_qcc302x/library.h | 6 +- .../gatt_blood_pressure_server.c | 255 +++++++++++++++++++++ .../gatt_blood_pressure_server.h | 93 ++++++++ .../gatt_blood_pressure_server_db.dbi | 29 +++ .../gatt_blood_pressure_server_db.h | 22 ++ .../gatt_blood_pressure_server_uuids.h | 9 + TWS/apps/libs/library/library.h | 6 +- TWS/apps/libs/libs_qcc512x_qcc302x.x2p | 6 + TWS/apps/libs/libs_qcc512x_rom_v21.x2p | 6 + 14 files changed, 672 insertions(+), 79 deletions(-) create mode 100644 TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server.c create mode 100644 TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server.h create mode 100644 TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server_db.dbi create mode 100644 TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server_db.h create mode 100644 TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server_uuids.h diff --git a/TWS/apps/applications/earbud/av_headset.h b/TWS/apps/applications/earbud/av_headset.h index de2ce49..afe63bc 100644 --- a/TWS/apps/applications/earbud/av_headset.h +++ b/TWS/apps/applications/earbud/av_headset.h @@ -14,11 +14,11 @@ Legal information <CENTER><b>Confidential and Proprietary – Qualcomm Technologies International, Ltd.</b></CENTER> -<b>NO PUBLIC DISCLOSURE PERMITTED:</b> Please report postings of this document on public servers or websites to: DocCtrlAgent@qualcomm.com. +<b>NO PUBLIC DISCLOSURE PERMITTED:</b> Please report postings of this document on public servers or websites to: DocCtrlAgent@qualcomm.com. <b>Restricted Distribution:</b> Not to be distributed to anyone who is not an employee of either Qualcomm Technologies International, Ltd. or its affiliated companies without the express approval of Qualcomm Configuration Management. -Not to be used, copied, reproduced, or modified in whole or in part, nor its contents revealed in any manner to others without the express written permission of Qualcomm Technologies International, Ltd. +Not to be used, copied, reproduced, or modified in whole or in part, nor its contents revealed in any manner to others without the express written permission of Qualcomm Technologies International, Ltd. All Qualcomm products mentioned herein are products of Qualcomm Technologies, Inc. and/or its subsidiaries. @@ -43,23 +43,23 @@ include @startuml - class init << (T,Green) >> #paleGreen { + class init << (T,Green) >> #paleGreen { Initialise the application .... Initialises all other modules at startup } - class led << (T,lightblue) >> { + class led << (T,lightblue) >> { Manages the LEDs } - class hfp << (T,lightblue) >> #Orange { - Manages HFP connections + class hfp << (T,lightblue) >> #Orange { + Manages HFP connections } - class ui << (T,lightblue) >> #Orange { - Manages the UI + class ui << (T,lightblue) >> #Orange { + Manages the UI } - class sm << (T,lightblue) >> #lightBlue { - Main application state machine + class sm << (T,lightblue) >> #lightBlue { + Main application state machine } class link_policy << (T,lightblue) >> { Manages the device link policy settings @@ -67,10 +67,10 @@ include class av << (T,lightblue) >> #Orange { Manages A2DP and AVRCP connections } - class charger << (T,lightblue) >> { + class charger << (T,lightblue) >> { Manages the charger } - class battery << (T,lightblue) >> { + class battery << (T,lightblue) >> { Manages the battery status } class temperature << (T,lightblue) >> { @@ -79,52 +79,52 @@ include class power << (T,lightblue) >> #Orange { Manages power, shutdown, sleep } - class pairing << (T,lightblue) >> #Orange { - Manages peer and handset pairing + class pairing << (T,lightblue) >> #Orange { + Manages peer and handset pairing } - class scanning << (T,lightblue) >> { - Manages the device scanning state + class scanning << (T,lightblue) >> { + Manages the device scanning state } - class device << (T,lightblue) >> { + class device << (T,lightblue) >> { Paired devices database } - class con_manager << (T,lightblue) >> { - Manages the device connection state machine + class con_manager << (T,lightblue) >> { + Manages the device connection state machine } - class peer_sig << (T,lightblue) >> { + class peer_sig << (T,lightblue) >> { Manages peer signalling messages } - class handset_sig << (T,lightblue) >> { - Manages the handset signalling messages + class handset_sig << (T,lightblue) >> { + Manages the handset signalling messages } - class phy_state << (T,lightblue) >> #Orange { + class phy_state << (T,lightblue) >> #Orange { Manages physcial state of the Earbud } - class kymera << (T,lightblue) >> { + class kymera << (T,lightblue) >> { Manages the audio subsystem } - class upgrade << (T,red) >> #lightGrey { - Manages the device upgrade + class upgrade << (T,red) >> #lightGrey { + Manages the device upgrade } - class proximity << (T,lightblue) >> { + class proximity << (T,lightblue) >> { Manages the proximity sensor } - class accelerometer << (T,lightblue) >> { + class accelerometer << (T,lightblue) >> { Manages the accelerometer } - class rules << (.,red) >> #yellow { - Application rules engine + class rules << (.,red) >> #yellow { + Application rules engine } - class chains << (.,red) >> #pink { - User defined audio chains + class chains << (.,red) >> #pink { + User defined audio chains } - class buttons << (.,red) >> #pink { - User defined button inputs + class buttons << (.,red) >> #pink { + User defined button inputs } - class peer_sync << (T,lightblue) >> { + class peer_sync << (T,lightblue) >> { Peer Earbud state synchronisation } - class scofwd << (T,lightblue) >> { + class scofwd << (T,lightblue) >> { SCO and MIC forwarding } @@ -201,7 +201,7 @@ include scofwd -l-> peer_sig : scofwd sig scofwd -u-> link_policy - @enduml + @enduml */ @@ -271,7 +271,7 @@ include enum { /*! Connecting reminder timeout */ - APP_INTERNAL_UI_CONNECTING_TIMEOUT= INTERNAL_MESSAGE_BASE, + APP_INTERNAL_UI_CONNECTING_TIMEOUT= INTERNAL_MESSAGE_BASE, APP_INTERNAL_UI_INQUIRY_TIMEOUT, /*!< Inquiry reminder timeout */ APP_INTERNAL_PAIRING_INIT }; @@ -357,30 +357,30 @@ typedef struct appTaskData advManagerTaskData adv_manager; /*!< Task information for the advertising manager */ } appTaskData; -/*! The global application data structure. +/*! The global application data structure. \note Do not access directly */ extern appTaskData globalApp; -/*! Get pointer to application data structure */ +/*! Get pointer to application data structure */ #define appGetApp() (&globalApp) -/*! Get pointer to application task */ +/*! Get pointer to application task */ #define appGetAppTask() (&globalApp.task) -/*! Get pointer to the system message task */ +/*! Get pointer to the system message task */ #define appGetSysTask() (&globalApp.systask) /*! Get pointer to init data structure */ #define appGetInit() (&globalApp.init) -/*! Get pointer to UI data structure */ +/*! Get pointer to UI data structure */ #define appGetUi() (&globalApp.ui) -/*! Get pointer to UI task */ +/*! Get pointer to UI task */ #define appGetUiTask() (&globalApp.ui.task) -/*! Get pointer to LED controller data structure */ +/*! Get pointer to LED controller data structure */ #define appGetLed() (&globalApp.led) /*! Get pointer to the proximity sensor data structure */ @@ -391,16 +391,16 @@ extern appTaskData globalApp; /*! Get pointer to the acceleromter data structure */ #define appGetAccelerometer() (&globalApp.accelerometer) -/*! Get pointer to Link Policy Manager data structure */ +/*! Get pointer to Link Policy Manager data structure */ #define appGetLp() (&globalApp.lp) -/*! Get pointer to CODEC task */ +/*! Get pointer to CODEC task */ #define appGetCodecTask() (globalApp.codec_task) -/*! Get pointer to HFP data structure */ +/*! Get pointer to HFP data structure */ #define appGetHfp() (&globalApp.hfp) -/*! Get pointer to HFP task */ +/*! Get pointer to HFP task */ #define appGetHfpTask() (&globalApp.hfp.task) /*! Get pointer to the GATT modules task data */ @@ -427,7 +427,10 @@ extern appTaskData globalApp; #define appGetGattBatteryServerRight(inst) (&appGetGattInstance(inst)->battery_server_right) #endif #define appGetHrTask() (&globalApp.gatt.gatt_hr_task) - +#define appGetBloodPressureTask() (&globalApp.gatt.gatt_blood_pressure_task) +#if defined(INCLUDE_GATT_BLOOD_PRESSURE) +#define appGetGattBPServerInst(inst) (&appGetGattInstance(inst)->bp_server) +#endif #if defined(INCLUDE_GATT_HR_SERVER) #define appGetGattHrServerInst(inst) (&appGetGattInstance(inst)->hr_server) @@ -480,12 +483,12 @@ extern appTaskData globalApp; #endif /* INCLUDE_DFU */ #ifdef INCLUDE_AV -/*! Get pointer to AV data structure */ +/*! Get pointer to AV data structure */ #define appGetAv() (&globalApp.av) #endif #ifdef INCLUDE_CHARGER -/*! Get pointer to charger data structure */ +/*! Get pointer to charger data structure */ #define appGetCharger() (&globalApp.charger) #endif diff --git a/TWS/apps/applications/earbud/av_headset_db.db b/TWS/apps/applications/earbud/av_headset_db.db index ba8e99a..03c53d7 100644 --- a/TWS/apps/applications/earbud/av_headset_db.db +++ b/TWS/apps/applications/earbud/av_headset_db.db @@ -22,3 +22,6 @@ ADD_BATTERY_SERVICE(2) #ifdef INCLUDE_GATT_HR_SERVER #include "gatt_heart_rate_server_db.dbi" #endif +#if defined(INCLUDE_GATT_BLOOD_PRESSURE) +#include "gatt_blood_pressure_server_db.dbi" +#endif diff --git a/TWS/apps/applications/earbud/av_headset_gatt.c b/TWS/apps/applications/earbud/av_headset_gatt.c index a8ff5ad..6de1073 100644 --- a/TWS/apps/applications/earbud/av_headset_gatt.c +++ b/TWS/apps/applications/earbud/av_headset_gatt.c @@ -83,7 +83,7 @@ static void appGattHandleGattExchangeMtuInd(GATT_EXCHANGE_MTU_IND_T* ind) GattExchangeMtuResponse(ind->cid, appConfigBleGattMtuMin()); } -/*! @brief Handle confirmation about GATT Manager registration. +/*! @brief Handle confirmation about GATT Manager registration. And set-up for resolvable addressing. */ @@ -151,8 +151,10 @@ bool appGattGoConnectable(void) #ifdef INCLUDE_GATT_HR_SERVER appAdvManagerSetService(advert,GATT_SERVICE_UUID_HEART_RATE); #endif + // appAdvManagerSetService(advert,GATT_SERVICE_UUID_BLOOD_PRESSURE); + adv_params.undirect_adv.filter_policy = ble_filter_none; - appConfigBleGetAdvertisingRate(appGetGatt()->advertising_mode, + appConfigBleGetAdvertisingRate(appGetGatt()->advertising_mode, &adv_params.undirect_adv.adv_interval_min, &adv_params.undirect_adv.adv_interval_max); appAdvManagerSetAdvertParams(advert, &adv_params); @@ -226,7 +228,7 @@ static void appGattHandleGattManRemoteClientConnectCfm(GATT_MANAGER_REMOTE_CLIEN // gattClientAdd(cfm->cid,ble_gap_role_peripheral); Does discovery. Not obvs useful. } else - { + { DEBUG_LOG("appGattHandleGattManRemoteClientConnectCfm. Unable to add new GATT client"); GattManagerDisconnectRequest(cfm->cid); } @@ -326,6 +328,8 @@ static void appGattHandleBattServerReadLevelInd(const GATT_BATTERY_SERVER_READ_L /* Return requested battery level */ GattBatteryServerReadLevelResponse(ind->battery_server, ind->cid, battery_percent); + GattBatteryServerSendLevelNotification(ind->battery_server, (uint16)0x0002, &ind->cid, 99); + } #define NAMESPACE_BLUETOOTH_SIG 0x01 /* Bluetooth SIG Namespace */ @@ -354,7 +358,7 @@ static void appGattHandleBatteryServerReadPresentationInd(const GATT_BATTERY_SER Panic(); } - DEBUG_LOG("appGattHandleBatteryServerReadPresentationInd bas=[0x%p] cid=[0x%x]\n", + DEBUG_LOG("appGattHandleBatteryServerReadPresentationInd bas=[0x%p] cid=[0x%x]\n", ind->battery_server,ind->cid); GattBatteryServerReadPresentationResponse(ind->battery_server, @@ -397,7 +401,7 @@ static void appGattHandleGattGapReadDeviceNameInd(const GATT_GAP_SERVER_READ_DEV DEBUG_LOG("appGattHandleGattGapReadDeviceNameInd"); - /* It is (barely) possible that there is not a local name set, + /* It is (barely) possible that there is not a local name set, in which case use a fallback */ if (!name) { @@ -509,7 +513,7 @@ static void appGattMessageHandler(Task task, MessageId id, Message message) /*! Handle CL_DM_BLE_CONFIGURE_LOCAL_ADDRESS_CFM message - This completes the library initialisation, so inform the application + This completes the library initialisation, so inform the application */ static void appGattHandleDmBleCconfigureLocalAddressCfm(CL_DM_BLE_CONFIGURE_LOCAL_ADDRESS_CFM_T *cfm) { @@ -534,8 +538,150 @@ bool appGattHandleConnectionLibraryMessages(MessageId id, Message message, bool } return already_handled; } +#if defined(INCLUDE_GATT_BLOOD_PRESSURE) +void sendSeanLevelAccessRsp(const SEANS *sean_server, uint16 cid, uint8 sean_level, uint16 result) +{ + DEBUG_LOG("SEAN: sendSeanLevelAccessRsp: result:%d\n", result); + + sendSeanAccessRsp((Task)&sean_server->lib_task, cid, HANDLE_SEAN_READ, result, 1, &sean_level); +} +void sendSeanLevelAccessRsp_2(const SEANS *sean_server, uint16 cid, uint8 sean_level, uint16 result) +{ + DEBUG_LOG("SEAN: sendSeanLevelAccessRsp: result:%d\n", result); + + sendSeanAccessRsp((Task)&sean_server->lib_task, cid, HANDLE_SEAN_NOTIFICATION, result, 2, &sean_level); +} + +bool GattSeanServerReadSthResponse(const SEANS *sean_server, uint16 cid, uint8 sean_level) +{ + DEBUG_LOG("SEAN: GattSeanServerReadSthResponse: sean_level:%d\n", sean_level); + + gatt_status_t status = gatt_status_failure; + + if (sean_server == NULL) + { + return FALSE; + } + + if (sean_level <= 0xff) + { + status = gatt_status_success; + } + else + { + status = gatt_status_insufficient_resources; + } + sendSeanLevelAccessRsp(sean_server, cid, sean_level, status); + + return TRUE; +} +bool GattSeanServerReadclientconfigResponse(const SEANS *sean_server, uint16 cid, uint16 sean_level) +{ + DEBUG_LOG("SEAN: GattSeanServerReadSthResponse: sean_level:%d\n", sean_level); + + gatt_status_t status = gatt_status_failure; + + if (sean_server == NULL) + { + return FALSE; + } + + if (sean_level <= 0xffff) + { + status = gatt_status_success; + } + else + { + status = gatt_status_insufficient_resources; + } + sendSeanLevelAccessRsp_2(sean_server, cid, sean_level, status); + + return TRUE; +} + +static uint8 i = 0; + +static void appGattHandleSeanServerReadSthInd(const GATT_SEAN_SERVER_READ_STH_IND_T * ind) +{ + uint8 return_value = 0xAA; + if (i%2 == 1)return_value = 0xBB; + else return_value = 0xAA; + DEBUG_LOG("SEAN: appGattHandleSeanServerReadSthInd bas=[0x%p] cid=[0x%x]\n", (void *)ind->sean_server, ind->cid); + + DEBUG_LOG("SEAN: Return value =[%u]\n", return_value); + i++; + if (i == 100)i = 0; + /* Return requested battery level */ + GattSeanServerReadSthResponse(ind->sean_server, ind->cid, return_value); +} +static void appGattHandleSeanServerReadclientconfigInd(const GATT_SEAN_SERVER_READ_STH_IND_T * ind) +{ + uint16 return_value = 0xAAAA; + if (i%2 == 1)return_value = 0xBBBB; + else return_value = 0xAAAA; + DEBUG_LOG("SEAN: appGattHandleSeanServerReadSthInd bas=[0x%p] cid=[0x%x]\n", (void *)ind->sean_server, ind->cid); + + DEBUG_LOG("SEAN: Return value =[%u]\n", return_value); + i++; + if (i == 100)i = 0; + /* Return requested battery level */ + GattSeanServerReadclientconfigResponse(ind->sean_server, ind->cid, return_value); +} +#if 0 +static void appGattHandleSeanServerReadClientConfig(const GATT_SEAN_SERVER_WRITE_CLIENT_CONFIG_IND_T *ind) +{ + DEBUG_LOG("SEAN: appGattHandleSeanServerReadClientConfig Return value =[%u]\n", ind->config_value); + //global_sean_server = ind->sean_server; + cur_cid = ind->cid; +} +#endif +static void appGattHandleSeanServerWriteSth(const GATT_SEAN_SERVER_WRITE_STH_IND_T * ind) +{ + uint16 client_config = 0; + + client_config = ind->write_value ; + // client_config = 0x98; + DEBUG_LOG("SEAN: appGattHandleSeanServerWriteSth, write_value=[0x%x] cid=[0x%x]\n", client_config,ind->cid); + GattSeanServerWriteToNofityResponse(ind->sean_server, ind->cid, client_config); + +} + +void appGattSeanMessageHandler(Task task, MessageId id, Message message) +{ + UNUSED(task); + + DEBUG_LOG("SEAN: appGattSeanMessageHandler id:%d 0x%x", id, id); + switch (id) + { + case GATT_SEAN_SERVER_READ_STH_IND: + //TODO: DO STH HERE! + appGattHandleSeanServerReadSthInd((const GATT_SEAN_SERVER_READ_STH_IND_T *) message); + break; + case GATT_SEAN_SERVER_WRITE_STH_IND: + appGattHandleSeanServerWriteSth((const GATT_SEAN_SERVER_WRITE_STH_IND_T *)message); + DEBUG_LOG("SEAN: appGattSeanMessageHandler:GATT_SEAN_SERVER_READ_STH_IND_T++"); + + appGattHandleSeanServerReadclientconfigInd((const GATT_SEAN_SERVER_READ_STH_IND_T *) message); + + DEBUG_LOG("SEAN: appGattSeanMessageHandler:GATT_SEAN_SERVER_READ_STH_IND_T--"); + break; + case GATT_SEAN_SERVER_READ_CLIENT_CONFIG_IND: + DEBUG_LOG("SEAN: appGattSeanMessageHandler:GATT_SEAN_SERVER_READ_CLIENT_CONFIG_IND"); + appGattHandleSeanServerReadclientconfigInd((const GATT_SEAN_SERVER_READ_STH_IND_T *) message); + break; + case GATT_SEAN_SERVER_WRITE_CLIENT_CONFIG_IND: + DEBUG_LOG("SEAN: appGattSeanMessageHandler:GATT_SEAN_SERVER_WRITE_CLIENT_CONFIG_IND cid=[0x%x]",((const GATT_SEAN_SERVER_READ_STH_IND_T *) message)->cid); + // appGattHandleSeanServerReadClientConfig((const GATT_SEAN_SERVER_WRITE_CLIENT_CONFIG_IND_T *)message); + + break; + default: + DEBUG_LOG("SEAN: appGattSeanMessageHandler. Unhandled message id:0x%x", id); + break; + } +} +#endif #ifdef INCLUDE_GATT_BATTERY_SERVER static void appGattBatteryMessageHandler(Task task, MessageId id, Message message) { @@ -597,7 +743,9 @@ void appGattInit(void) #ifdef INCLUDE_GATT_BATTERY_SERVER gatt->gatt_battery_task.handler = appGattBatteryMessageHandler; #endif - +#if defined(INCLUDE_GATT_BLOOD_PRESSURE) + gatt->gatt_blood_pressure_task.handler = appGattSeanMessageHandler; +#endif /* Initialise the GATT Manager */ if (!GattManagerInit(appGetGattTask())) { @@ -619,8 +767,8 @@ void appGattInit(void) #endif for (gatt_instance = 0; gatt_instance < appConfigBleGetGattServerInstances(); gatt_instance++) { - if (GattServerInit(appGetGattServerInst(gatt_instance), appGetGattTask(), - HANDLE_GATT_SERVICE, HANDLE_GATT_SERVICE_END) + if (GattServerInit(appGetGattServerInst(gatt_instance), appGetGattTask(), + HANDLE_GATT_SERVICE, HANDLE_GATT_SERVICE_END) != gatt_server_status_success) { DEBUG_LOG("APP:GATT: GATT server init failed"); @@ -628,7 +776,7 @@ void appGattInit(void) } if (GattGapServerInit(appGetGattGapServerInst(gatt_instance), appGetGattGapTask(), - HANDLE_GAP_SERVICE, HANDLE_GAP_SERVICE_END) + HANDLE_GAP_SERVICE, HANDLE_GAP_SERVICE_END) != gatt_gap_server_status_success) { DEBUG_LOG("APP:GATT: GAP server init failed"); @@ -637,7 +785,7 @@ void appGattInit(void) #ifdef INCLUDE_GATT_BATTERY_SERVER if (!GattBatteryServerInit(appGetGattBatteryServerLeft(gatt_instance), - appGetGattBatteryTask(), &battery_server_params, + appGetGattBatteryTask(), &battery_server_params, HANDLE_BATTERY_SERVICE1, HANDLE_BATTERY_SERVICE1_END)) { DEBUG_LOG("APP:GATT: GATT battery server init (left) failed"); @@ -645,7 +793,7 @@ void appGattInit(void) } if (!GattBatteryServerInit(appGetGattBatteryServerRight(gatt_instance), - appGetGattBatteryTask(), &battery_server_params, + appGetGattBatteryTask(), &battery_server_params, HANDLE_BATTERY_SERVICE2, HANDLE_BATTERY_SERVICE2_END)) { DEBUG_LOG("APP:GATT: GATT battery server init (right) failed"); @@ -658,6 +806,16 @@ void appGattInit(void) #endif #ifdef INCLUDE_GATT_HR_SERVER GattHrServerInit(appGetHrTask(),appGetGattHrServerInst(gatt_instance),HANDLE_HEART_RATE_SERVICE,HANDLE_HEART_RATE_SERVICE_END); +#endif +#if defined(INCLUDE_GATT_BLOOD_PRESSURE) + + gatt_sean_server_init_params_t bloodpressure_server_params = {.enable_notifications = TRUE}; + + GattSeanServerInit(appGetGattBPServerInst(gatt_instance), + appGetBloodPressureTask(), + &bloodpressure_server_params, + HANDLE_SEAN_SERVICE, + HANDLE_SEAN_SERVICE_END); #endif } /* complete registration of servers */ diff --git a/TWS/apps/applications/earbud/av_headset_gatt.h b/TWS/apps/applications/earbud/av_headset_gatt.h index 16c07ef..8dcd3a9 100644 --- a/TWS/apps/applications/earbud/av_headset_gatt.h +++ b/TWS/apps/applications/earbud/av_headset_gatt.h @@ -16,7 +16,7 @@ #include <gatt_gap_server.h> #include <gatt_battery_server.h> #include <gatt_heart_rate_server.h> - +#include <gatt_blood_pressure_server.h> /*! Messages sent by the av_headset_gatt module */ typedef enum { APP_GATT_INIT_CFM = APP_GATT_MESSAGE_BASE, /*!< Application GATT module has initialised */ @@ -26,7 +26,7 @@ typedef enum { } av_headet_gatt_messages; -/*! GATT Client Configuration attributes that need to be stored per remote client +/*! GATT Client Configuration attributes that need to be stored per remote client @note This is a server only structure */ @@ -64,6 +64,9 @@ typedef struct #ifdef INCLUDE_GATT_HR_SERVER GHRS_T hr_server; #endif +#if defined(INCLUDE_GATT_BLOOD_PRESSURE) + SEANS bp_server; +#endif } gattGattServerInfo; @@ -77,6 +80,8 @@ typedef struct TaskData gatt_battery_task; TaskData gatt_hr_task; + + TaskData gatt_blood_pressure_task; /*! Advertising rate to use when connecting */ appConfigBleAdvertisingMode advertising_mode; @@ -93,7 +98,7 @@ COMPILE_TIME_ASSERT(1==appConfigBleGetGattServerInstances(),double_check_multipl /*! Start a BLE connection Starts advertising to make a new connection as a peripheral. The message - APP_GATT_CONNECTABLE will be sent when advertising is started. And + APP_GATT_CONNECTABLE will be sent when advertising is started. And APP_GATT_CONNECTION_MADE if a connection is made. \returns FALSE if there is an existing connection, TRUE otherwise @@ -106,7 +111,7 @@ bool appGattGoConnectable(void); and the application logic currently allows a connection then advertising will be started. - If there is an existin BLE connection, or advertising is in progress, and + If there is an existin BLE connection, or advertising is in progress, and connections are no longer allowed - then the BLE activity will be stopped. \param allow Enable or disable BLE connection @@ -115,7 +120,7 @@ bool appGattGoConnectable(void); */ bool appGattAllowBleConnections(bool allow); -/*! Does the GATT module have a BLE connection +/*! Does the GATT module have a BLE connection \return TRUE if there is a BLE connection */ #define appGattHasBleConnection() (0 != appGetGatt()->instance[0].conn_id) @@ -139,13 +144,13 @@ void appGattSetAdvertisingMode(appConfigBleAdvertisingMode mode); /*! Handler for connection library messages not sent directly This function is called to handle any connection library messages sent to - the application that the GATT module is interested in. If a message + the application that the GATT module is interested in. If a message is processed then the function returns TRUE. - \note Some connection library messages can be sent directly as the + \note Some connection library messages can be sent directly as the request is able to specify a destination for the response. - \param id Identifier of the connection library message + \param id Identifier of the connection library message \param message The message content (if any) \param already_handled Indication whether this message has been processed by another module. The handler may choose to ignore certain @@ -157,7 +162,7 @@ void appGattSetAdvertisingMode(appConfigBleAdvertisingMode mode); bool appGattHandleConnectionLibraryMessages(MessageId id, Message message, bool already_handled); -/*! @brief Initialise the GATT component. +/*! @brief Initialise the GATT component. */ void appGattInit(void); diff --git a/TWS/apps/applications/earbud/qcc512x_qcc302x/CF376_CF440/earbud.x2p b/TWS/apps/applications/earbud/qcc512x_qcc302x/CF376_CF440/earbud.x2p index 7b0a062..2d3e323 100644 --- a/TWS/apps/applications/earbud/qcc512x_qcc302x/CF376_CF440/earbud.x2p +++ b/TWS/apps/applications/earbud/qcc512x_qcc302x/CF376_CF440/earbud.x2p @@ -12,13 +12,13 @@ <property name="CHIP_TYPE">qcc512x_qcc302x</property> <property name="DBG_CORE">app/p1</property> <property name="DEFAULT_LIBS">usb_early_init</property> - <property name="DEFS">AV_DEBUG BLUELAB CF376_CF440 DEBUG HAVE_1_BUTTON HAVE_32BIT_DATA_WIDTH HAVE_3_LEDS HAVE_THERMISTOR HYDRA HYDRACORE INCLUDE_AV INCLUDE_CHARGER INCLUDE_DFU INCLUDE_GATT INCLUDE_GATT_BATTERY_SERVER INCLUDE_GATT_GAIA_SERVER INCLUDE_HFP INCLUDE_MICFWD INCLUDE_PROMPTS INCLUDE_SCOFWD INCLUDE_TEMPERATURE INCLUDE_TONES INSTALL_HYDRA_LOG THERMISTOR_ADC=adcsel_led5 THERMISTOR_DATA_FILE=thermistor_lp4549652p3m.h THERMISTOR_ON=THERMISTOR_PIO_UNUSED USE_BDADDR_FOR_LEFT_RIGHT __KALIMBA__</property> + <property name="DEFS">AV_DEBUG BLUELAB CF376_CF440 DEBUG HAVE_1_BUTTON HAVE_32BIT_DATA_WIDTH HAVE_3_LEDS HAVE_THERMISTOR HYDRA HYDRACORE INCLUDE_AV INCLUDE_CHARGER INCLUDE_DFU INCLUDE_GATT INCLUDE_GATT_BATTERY_SERVER INCLUDE_GATT_GAIA_SERVER INCLUDE_GATT_BLOOD_PRESSURE INCLUDE_HFP INCLUDE_MICFWD INCLUDE_PROMPTS INCLUDE_SCOFWD INCLUDE_TEMPERATURE INCLUDE_TONES INSTALL_HYDRA_LOG THERMISTOR_ADC=adcsel_led5 THERMISTOR_DATA_FILE=thermistor_lp4549652p3m.h THERMISTOR_ON=THERMISTOR_PIO_UNUSED USE_BDADDR_FOR_LEFT_RIGHT __KALIMBA__</property> <property name="EXTRA_WARNINGS">FALSE</property> <property name="FLASH_CONFIG">..\..\64Mbit_default_flash_config.py</property> <property name="HW_VARIANT">CF376_CF440</property> <property name="INCPATHS">../../../../installed_libs\include\firmware_qcc512x_qcc302x ../../../../installed_libs\include\firmware_qcc512x_qcc302x/app ../../../../installed_libs\include\profiles\default_qcc512x_qcc302x ../../../../installed_libs\include\standard ../../chains sdk://audio/kalimba/kymera/common/interface/gen/k32</property> <property name="LIBPATHS">../../../../installed_libs\lib\default_qcc512x_qcc302x\native ../../../../installed_libs\lib\os\qcc512x_qcc302x</property> - <property name="LIBS">a2dp anc audio_plugin_common audio_processor avrcp bdaddr byte_utils chain connection cryptovm custom_operator file_list gaia gain_utils gatt gatt_battery_server gatt_gap_server gatt_manager gatt_server hfp input_event_manager logging operators packetiser_helper pio_common region rtime rwcp_server sdp_parse service system_clock transport_adaptation transport_manager upgrade usb_device_class vmal gatt_heart_rate_server</property> + <property name="LIBS">a2dp anc audio_plugin_common audio_processor avrcp bdaddr byte_utils chain connection cryptovm custom_operator file_list gaia gain_utils gatt gatt_battery_server gatt_gap_server gatt_manager gatt_server hfp input_event_manager logging operators packetiser_helper pio_common region rtime rwcp_server sdp_parse service system_clock transport_adaptation transport_manager upgrade usb_device_class vmal gatt_heart_rate_server gatt_blood_pressure_server</property> <property name="OUTPUT">earbud</property> <property name="OUTPUT_TYPE">EXECUTABLE</property> <property name="PRESERVED_LIBS">qcc512x_qcc302x</property> diff --git a/TWS/apps/installed_libs/include/profiles/default_qcc512x_qcc302x/library.h b/TWS/apps/installed_libs/include/profiles/default_qcc512x_qcc302x/library.h index bc7a218..690eee3 100644 --- a/TWS/apps/installed_libs/include/profiles/default_qcc512x_qcc302x/library.h +++ b/TWS/apps/installed_libs/include/profiles/default_qcc512x_qcc302x/library.h @@ -64,7 +64,7 @@ all ADK libraries. /*! @brief Default reserved service channel */ #define RESERVED_DEFAULT_CHANNEL (0x0E) -/*! Base values for library messages +/*! Base values for library messages */ @@ -164,7 +164,7 @@ all ADK libraries. messages are handled by default in the main task. Consequently the NFC_CL_MESSAGE_BASE SHOULD NOT be the same value as another base handled in the main task. Its value can be changed. - + @warning NFC_MESSAGE_BASE is used for the NFC_API and CAN NOT be changed. The NFC API messages are handled by default in NFC_CL task. If NFC_CL task is overridden by the main task then 0x7E00 SHOULD NOT be use by other base. @@ -185,6 +185,8 @@ all ADK libraries. /*! @brief Message base for transport manager libraries*/ #define TRANSPORT_MGR_MESSAGE_BASE 0x7F7A #define VA_AUDIO_MGR_MESSAGE_BASE 0x7F80 +#define GATT_SEAN_SERVER_MESSAGE_BASE 0x7F90 + #endif /* _LIBRARY_H */ /*@}*/ diff --git a/TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server.c b/TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server.c new file mode 100644 index 0000000..8ac6381 --- /dev/null +++ b/TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server.c @@ -0,0 +1,255 @@ +#include "gatt_blood_pressure_server.h" +#include "gatt_blood_pressure_server_db.h" +void sendSeanAccessRsp(Task task, + uint16 cid, + uint16 handle, + uint16 result, + uint16 size_value, + const uint8 *value) +{ + if (!GattManagerServerAccessResponse(task, cid, handle, result, size_value, value)) + { + /* The GATT Manager should always know how to send this response */ + GATT_SEAN_SERVER_DEBUG_PANIC(("Couldn't send GATT access response\n")); + } +} + +static void sendSeanAccessErrorRsp(const SEANS *sean_server, const GATT_MANAGER_SERVER_ACCESS_IND_T *access_ind, uint16 error) +{ + sendSeanAccessRsp((Task)&sean_server->lib_task, access_ind->cid, access_ind->handle, error, 0, NULL); +} + +static void seanServiceAccess(SEANS *sean_server, const GATT_MANAGER_SERVER_ACCESS_IND_T *access_ind) +{ + if (access_ind->flags & ATT_ACCESS_READ) + { + sendSeanAccessRsp((Task)&sean_server->lib_task, access_ind->cid, HANDLE_SEAN_SERVICE, gatt_status_success, 0, NULL); + } + else if (access_ind->flags & ATT_ACCESS_WRITE) + { + /* Write of battery level not allowed. */ + sendSeanAccessErrorRsp(sean_server, access_ind, gatt_status_write_not_permitted); + } + else + { + /* Reject access requests that aren't read/write, which shouldn't happen. */ + sendSeanAccessErrorRsp(sean_server, access_ind, gatt_status_request_not_supported); + } +} +static void readSthAccess(SEANS *sean_server, const GATT_MANAGER_SERVER_ACCESS_IND_T *access_ind) +{ + PRINT("SEAN: readSthAccess\n"); + // UNUSED(sean_server); + // UNUSED(access_ind); + if (access_ind->flags & ATT_ACCESS_READ) + { + PRINT("SEAN: readSthAccess: ATT_ACCESS_READ\n"); + /* Send read level message to app_task so it can return the current level */ + MAKE_SEAN_MESSAGE(GATT_SEAN_SERVER_READ_STH_IND); + message->sean_server = sean_server; /* Pass the instance which can be returned in the response */ + message->cid = access_ind->cid; /* Pass the CID which can be returned in the response */ + MessageSend(sean_server->app_task, GATT_SEAN_SERVER_READ_STH_IND, message); + } + else if (access_ind->flags & ATT_ACCESS_WRITE) + { + PRINT("SEAN: readSthAccess: ATT_ACCESS_WRITE\n"); + /* Send read level message to app_task so it can return the current level */ + MAKE_SEAN_MESSAGE(GATT_SEAN_SERVER_WRITE_STH_IND); + message->sean_server = sean_server; /* Pass the instance which can be returned in the response */ + message->cid = access_ind->cid; /* Pass the CID which can be returned in the response */ + message->write_value = (access_ind->value[0]) + (access_ind->value[1]<<8); +// sendSeanNotificationRsp((Task)&sean_server->lib_task, access_ind->cid, HANDLE_SEAN_CLIENT_CONFIG_MESSAGE, GATT_CLIENT_CONFIG_OCTET_SIZE, access_ind->value); + MessageSend(sean_server->app_task, GATT_SEAN_SERVER_WRITE_STH_IND, message); + sendSeanAccessRsp((Task)&sean_server->lib_task, access_ind->cid, access_ind->handle, gatt_status_success, 0, NULL); + //DEBUG_LOG("SEAN: WRITE VALUE: %02x%02x\n", access_ind->value[0], access_ind->value[1]); + + } + else + { + /* Reject access requests that aren't read/write, which shouldn't happen. */ + sendSeanAccessErrorRsp(sean_server, access_ind, gatt_status_request_not_supported); + } +} +static void seanConfigAccess(SEANS *seanserver, const GATT_MANAGER_SERVER_ACCESS_IND_T *access_ind) +{ + if (access_ind->flags & ATT_ACCESS_READ) + { + /* On a Read, ask the app for current client config value */ + MAKE_SEAN_MESSAGE(GATT_SEAN_SERVER_READ_CLIENT_CONFIG_IND); + message->sean_server = seanserver; /* Pass the instance which can be returned in the response */ + message->cid = access_ind->cid; /* Pass the CID so the client can be identified */ + MessageSend(seanserver->app_task, GATT_SEAN_SERVER_READ_CLIENT_CONFIG_IND, message); + } + else if (access_ind->flags & ATT_ACCESS_WRITE) + { + if (access_ind->size_value == GATT_CLIENT_CONFIG_OCTET_SIZE) + { + /* On a Write, send new client config value to the app */ + MAKE_SEAN_MESSAGE(GATT_SEAN_SERVER_WRITE_CLIENT_CONFIG_IND); + message->sean_server = seanserver; + message->cid = access_ind->cid; + message->config_value = (access_ind->value[0] & 0xFF) | ((access_ind->value[1] << 8) & 0xFF00); + MessageSend(seanserver->app_task, GATT_SEAN_SERVER_WRITE_CLIENT_CONFIG_IND, message); + /* Library response to the access request */ + sendSeanAccessRsp(&seanserver->lib_task, access_ind->cid, access_ind->handle, gatt_status_success, 0, NULL); + + } + else + { + sendSeanAccessErrorRsp(seanserver, access_ind, gatt_status_invalid_length); + } + } + else + { + /* Reject access requests that aren't read/write, which shouldn't happen. */ + sendSeanAccessErrorRsp(seanserver, access_ind, gatt_status_request_not_supported); + } +} +static void handleSeanAccess(SEANS *sean_server, const GATT_MANAGER_SERVER_ACCESS_IND_T *access_ind) +{ + switch (access_ind->handle) + { + case HANDLE_SEAN_SERVICE: + { + PRINT("SEAN: handleSeanAccess: HANDLE_SEAN_SERVICE_MESSAGE\n"); + seanServiceAccess(sean_server, access_ind); + } + break; + + case HANDLE_SEAN_READ: + { + PRINT("SEAN: handleSeanAccess: HANDLE_SEAN_READ_MESSAGE\n"); + readSthAccess(sean_server, access_ind); + } + break; + + case HANDLE_SEAN_WRITE: + { + PRINT("SEAN: handleSeanAccess: HANDLE_SEAN_WRITE_MESSAGE\n"); + readSthAccess(sean_server, access_ind); + } + break; + + case HANDLE_SEAN_NOTIFICATION: + { + PRINT("SEAN: handleSeanAccess: HANDLE_SEAN_CLIENT_CONFIG_MESSAGE\n"); + seanConfigAccess(sean_server, access_ind); + } + + break; + + default: + { + /* Respond to invalid handles */ + sendSeanAccessErrorRsp(sean_server, access_ind, gatt_status_invalid_handle); + } + break; + } +} + +static void seanServerMsgHandler(Task task,MessageId id,Message payload) +{ + //DEBUG_LOG("SEAN: seanServerMsgHandler, id: %d\n", id); + SEANS *sean_server = (SEANS *)task; + + switch (id) + { + case GATT_MANAGER_SERVER_ACCESS_IND: + { + /* Read/write access to characteristic */ + handleSeanAccess(sean_server,(GATT_MANAGER_SERVER_ACCESS_IND_T *)payload); + } + break; + case GATT_MANAGER_REMOTE_CLIENT_NOTIFICATION_CFM: + { + /* Library just absorbs confirmation messages */ + } + break; + default: + { + /* Unrecognised GATT Manager message */ + GATT_SEAN_SERVER_DEBUG_PANIC(("SEAN: GATT Manager Server Msg not handled\n")); + } + break; + } +} +bool GattSeanServerInit(SEANS *sean_server, + Task app_task, + const gatt_sean_server_init_params_t *init_params, + uint16 start_handle, + uint16 end_handle) +{ +// DEBUG_LOG("SEAN: GattSeanServerInit\n"); + + gatt_manager_server_registration_params_t registration_params; + + if ((app_task == NULL) || (sean_server == NULL)) + { + GATT_SEAN_SERVER_PANIC(("SEANS: Invalid Initialisation parameters")); + return FALSE; + } + + /* Set up library handler for external messages */ + sean_server->lib_task.handler = seanServerMsgHandler; + + /* Store the Task function parameter. + All library messages need to be sent here */ + sean_server->app_task = app_task; + + /* Check optional initialisation parameters */ + /* When GATT_MANAGER_USE_CONST_DB is enabled then it is the callers responsibility + * to register the appropriate GATT battery server configuration when the + * const database is registered. + */ + if (init_params) + { + /* Store notifications enable flag */ + sean_server->notifications_enabled = init_params->enable_notifications; + } + else + { + sean_server->notifications_enabled = FALSE; + } + + /* Setup data required for Battery Service to be registered with the GATT Manager */ + registration_params.task = &sean_server->lib_task; + registration_params.start_handle = start_handle; + registration_params.end_handle = end_handle; + + /* Register with the GATT Manager and verify the result */ + return (GattManagerRegisterServer(®istration_params) == gatt_manager_status_success); +} +static void sendSeanNotificationRsp(Task task, + uint16 cid, + uint16 handle, + uint16 size_value, + const uint8 *value) +{ + PRINT("SEAN: sendSeanNotificationRsp++\n"); + GattManagerRemoteClientNotify(task, cid, handle, size_value, value); + + PRINT("SEAN: sendSeanNotificationRsp--\n"); +} +void sendSeanConfigAccessRsp(const SEANS *sean_server, uint16 cid, uint16 client_config) +{ + uint8 config_resp[GATT_CLIENT_CONFIG_OCTET_SIZE]; + + config_resp[0] = client_config & 0xFF; + config_resp[1] = (client_config >> 8) & 0xFF; + sendSeanNotificationRsp((Task)&sean_server->lib_task, cid, HANDLE_SEAN_READ, 1, config_resp); + +} +bool GattSeanServerWriteToNofityResponse(const SEANS *sean_server, uint16 cid, uint16 client_config) +{ + PRINT("SEAN: GattSeanServerReadClientConfigResponse\n"); + if (sean_server == NULL) + { + return FALSE; + } + PRINT("SEAN: GattSeanServerReadClientConfigResponse 2\n"); + + sendSeanConfigAccessRsp(sean_server, cid, client_config); + + return TRUE; +} + diff --git a/TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server.h b/TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server.h new file mode 100644 index 0000000..10ef0a7 --- /dev/null +++ b/TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server.h @@ -0,0 +1,93 @@ +#ifndef GATT_BLOOD_PRESSURE_SERVER_H_ +#define GATT_BLOOD_PRESSURE_SERVER_H_ +#include "gatt_manager.h" +#include <panic.h> +#include <print.h> +#include <stdio.h> +#include <stdlib.h> +#include <csrtypes.h> +#include <message.h> +#include <library.h> + +#define GATT_CLIENT_CONFIG_OCTET_SIZE sizeof(uint8) * 2 + +typedef enum +{ + /* Server messages */ + GATT_SEAN_SERVER_READ_STH_IND = GATT_SEAN_SERVER_MESSAGE_BASE, /* 00 */ + GATT_SEAN_SERVER_WRITE_STH_IND, /* 01 */ + GATT_SEAN_SERVER_READ_CLIENT_CONFIG_IND, + GATT_SEAN_SERVER_WRITE_CLIENT_CONFIG_IND, + /* Library message limit */ + GATT_SEAN_SERVER_MESSAGE_TOP +} gatt_sean_server_message_id_t; +//#ifdef DEBUG_LOG +//#undef DEBUG_LOG +//#define DEBUG_LOG(x) PRINT(x) +//#endif +#define GATT_SEAN_SERVER_DEBUG_INFO(x) {PRINT(("%s:%d - ", __FILE__, __LINE__)); PRINT(x);} +#define GATT_SEAN_SERVER_DEBUG_PANIC(x) {GATT_SEAN_SERVER_DEBUG_INFO(x); Panic();} +#define GATT_SEAN_SERVER_PANIC(x) {GATT_SEAN_SERVER_DEBUG_INFO(x); Panic();} + +typedef struct __SEANS +{ + TaskData lib_task; + Task app_task; + bool notifications_enabled; +} SEANS; +typedef struct +{ + bool enable_notifications; /*! Flag that can be used to enable or disable notifications */ +} gatt_sean_server_init_params_t; +typedef struct __GATT_SEAN_SERVER_READ_STH_IND +{ + const SEANS *sean_server; + uint16 cid; +} GATT_SEAN_SERVER_READ_STH_IND_T; +typedef struct __GATT_SEAN_SERVER_WRITE_STH_IND +{ + const SEANS *sean_server; + uint16 cid; + uint16 write_value; +} GATT_SEAN_SERVER_WRITE_STH_IND_T; +typedef struct __GATT_SEAN_SERVER_READ_CLIENT_CONFIG_IND +{ + const SEANS *sean_server; + uint16 cid; +} GATT_SEAN_SERVER_READ_CLIENT_CONFIG_IND_T; + +/*! @brief Contents of the GATT_BATTERY_SERVER_WRITE_CLIENT_CONFIG_IND message that is sent by the library, + due to a write of the local battery level client configuration characteristic. + */ +typedef struct __GATT_SEAN_SERVER_WRITE_CLIENT_CONFIG_IND +{ + const SEANS *sean_server; + uint16 cid; + uint16 config_value; +} GATT_SEAN_SERVER_WRITE_CLIENT_CONFIG_IND_T; +#define MAKE_SEAN_MESSAGE(TYPE) TYPE##_T *message = (TYPE##_T*)PanicNull(calloc(1,sizeof(TYPE##_T))) +#define MAKE_SEAN_MESSAGE_WITH_LEN(TYPE, LEN) TYPE##_T *message = (TYPE##_T *) PanicNull(calloc(1,sizeof(TYPE##_T) + ((LEN) - 1) * sizeof(uint8))) + + +void sendSeanAccessRsp(Task task, + uint16 cid, + uint16 handle, + uint16 result, + uint16 size_value, + const uint8 *value); +void sendSeanLevelAccessRsp(const SEANS *sean_server, uint16 cid, uint8 sean_level, uint16 result); +bool GattSeanServerReadSthResponse(const SEANS *sean_server, uint16 cid, uint8 sean_level); +void appGattSeanMessageHandler(Task task, MessageId id, Message message); + +void sendSeanConfigAccessRsp(const SEANS *sean_server, uint16 cid, uint16 client_config); +void sendSeanLevelAccessRsp_2(const SEANS *sean_server, uint16 cid, uint8 sean_level, uint16 result); +bool GattSeanServerReadclientconfigResponse(const SEANS *sean_server, uint16 cid, uint16 sean_level); +bool GattSeanServerWriteToNofityResponse(const SEANS *sean_server, uint16 cid, uint16 client_config); + +bool GattSeanServerInit(SEANS *sean_server, + Task app_task, + const gatt_sean_server_init_params_t *init_params, + uint16 start_handle, + uint16 end_handle); + +#endif diff --git a/TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server_db.dbi b/TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server_db.dbi new file mode 100644 index 0000000..3a6f9b5 --- /dev/null +++ b/TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server_db.dbi @@ -0,0 +1,29 @@ +#ifndef __GATT_SEAN_SERVER_DB_DBI__ +#define __GATT_SEAN_SERVER_DB_DBI__ + +#include "gatt_blood_pressure_server_uuids.h" + +primary_service { + uuid : UUID_SEAN_SERVICE, + name : "SEAN_SERVICE", + characteristic { + uuid : UUID_SEAN_READ, + name : "SEAN_READ", + flags : [ FLAG_IRQ , FLAG_DYNLEN ], + properties : [ read , notify ], + value : 0x0, + client_config { + flags : [ FLAG_IRQ , FLAG_DYNLEN ], + name : "SEAN_NOTIFICATION" + } + }, + + characteristic { + uuid : UUID_SEAN_WRITE, + name : "SEAN_WRITE", + flags : [ FLAG_IRQ , FLAG_DYNLEN ], + properties : [ write ], + value : 0x0 + } +}, +#endif /* __GATT_SEAN_SERVER_DB_DBI__ */ diff --git a/TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server_db.h b/TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server_db.h new file mode 100644 index 0000000..46489df --- /dev/null +++ b/TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server_db.h @@ -0,0 +1,22 @@ +/* + * THIS FILE IS AUTOGENERATED, DO NOT EDIT! + * + * generated by gattdbgen from gatt_blood_pressure_server/gatt_blood_pressure_server_db.dbi_ + */ +#ifndef __GATT_BLOOD_PRESSURE_SERVER_DB_H +#define __GATT_BLOOD_PRESSURE_SERVER_DB_H + +#include <csrtypes.h> + +#define HANDLE_SEAN_SERVICE (0x0001) +#define HANDLE_SEAN_SERVICE_END (0xffff) +#define HANDLE_SEAN_READ (0x0003) +#define HANDLE_SEAN_NOTIFICATION (0x0004) +#define HANDLE_SEAN_WRITE (0x0006) + +uint16 *GattGetDatabase(uint16 *len); +uint16 GattGetDatabaseSize(void); + +#endif + +/* End-of-File */ diff --git a/TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server_uuids.h b/TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server_uuids.h new file mode 100644 index 0000000..fcca7ec --- /dev/null +++ b/TWS/apps/libs/gatt_blood_pressure_server/gatt_blood_pressure_server_uuids.h @@ -0,0 +1,9 @@ +#ifndef __SEAN_UUIDS_H__ +#define __SEAN_UUIDS_H__ + +#define UUID_SEAN_SERVICE 0x1810 +#define UUID_SEAN_READ 0x2A35 +#define UUID_SEAN_WRITE 0x2A49 +//#define UUID_SEAN_NOTIFY 0x2A35 + +#endif /* __SEAN_UUIDS_H__ */ diff --git a/TWS/apps/libs/library/library.h b/TWS/apps/libs/library/library.h index bc7a218..690eee3 100644 --- a/TWS/apps/libs/library/library.h +++ b/TWS/apps/libs/library/library.h @@ -64,7 +64,7 @@ all ADK libraries. /*! @brief Default reserved service channel */ #define RESERVED_DEFAULT_CHANNEL (0x0E) -/*! Base values for library messages +/*! Base values for library messages */ @@ -164,7 +164,7 @@ all ADK libraries. messages are handled by default in the main task. Consequently the NFC_CL_MESSAGE_BASE SHOULD NOT be the same value as another base handled in the main task. Its value can be changed. - + @warning NFC_MESSAGE_BASE is used for the NFC_API and CAN NOT be changed. The NFC API messages are handled by default in NFC_CL task. If NFC_CL task is overridden by the main task then 0x7E00 SHOULD NOT be use by other base. @@ -185,6 +185,8 @@ all ADK libraries. /*! @brief Message base for transport manager libraries*/ #define TRANSPORT_MGR_MESSAGE_BASE 0x7F7A #define VA_AUDIO_MGR_MESSAGE_BASE 0x7F80 +#define GATT_SEAN_SERVER_MESSAGE_BASE 0x7F90 + #endif /* _LIBRARY_H */ /*@}*/ diff --git a/TWS/apps/libs/libs_qcc512x_qcc302x.x2p b/TWS/apps/libs/libs_qcc512x_qcc302x.x2p index e82d830..20e18bf 100644 --- a/TWS/apps/libs/libs_qcc512x_qcc302x.x2p +++ b/TWS/apps/libs/libs_qcc512x_qcc302x.x2p @@ -992,6 +992,12 @@ <file path="gatt_transmit_power_server/gatt_transmit_power_server_private.h"/> <file path="gatt_transmit_power_server/gatt_transmit_power_server_uuids.h"/> </folder> + <folder name="gatt_blood_pressure_server"> + <file path="gatt_blood_pressure_server/gatt_blood_pressure_server.c"/> + <file path="gatt_blood_pressure_server/gatt_blood_pressure_server.h"/> + <file path="gatt_blood_pressure_server/gatt_blood_pressure_server_db.dbi"/> + <file path="gatt_blood_pressure_server/gatt_blood_pressure_server_uuids.h"/> + </folder> <folder name="hfp"> <file path="hfp/hfp.h"/> <file path="hfp/hfp_at_cmd.c"/> diff --git a/TWS/apps/libs/libs_qcc512x_rom_v21.x2p b/TWS/apps/libs/libs_qcc512x_rom_v21.x2p index c6d5bd7..c36c5cc 100644 --- a/TWS/apps/libs/libs_qcc512x_rom_v21.x2p +++ b/TWS/apps/libs/libs_qcc512x_rom_v21.x2p @@ -876,6 +876,12 @@ <file path="gatt_heart_rate_server/gatt_heart_rate_server_private.h"/> <file path="gatt_heart_rate_server/gatt_heart_rate_server_uuids.h"/> </folder> + <folder name="gatt_blood_pressure_server"> + <file path="gatt_blood_pressure_server/gatt_blood_pressure_server.c"/> + <file path="gatt_blood_pressure_server/gatt_blood_pressure_server.h"/> + <file path="gatt_blood_pressure_server/gatt_blood_pressure_server_db.dbi"/> + <file path="gatt_blood_pressure_server/gatt_blood_pressure_server_uuids.h"/> + </folder> <folder name="gatt_hid_client"> <file path="gatt_hid_client/gatt_hid_client.c"/> <file path="gatt_hid_client/gatt_hid_client.h"/> -- 2.14.1.windows.1有些参考blog中提到的没有需要自己定义,如下
在参考过程中发现读功能发出后老是断线,后来参考电池gatt_battery_level_service发现要回复一个respond,读notify config descp也是,参考电池回复一下respond,不然后莫名掉线
在实现notify中出现手机端老是不能接收到设备,后来调试时,在battery加了notify功能,电池可以通知,说明tws此功能是可以的,后来,在原来notify再加了read功能,发现nrf connect仍没有notify, 后面再看了一下写的uuid为对应的name形成的handle,将size由2改成1个字节,就可以在手机端收到了,后来发现电池改成2个字节手机也收不到了,看来是数据长度的问题 编译后会生成 btsnoop log分析也成功了 会出现切换主耳,广播扫描不了,发现是关掉了,是逻辑中的电池电量的对比引起
diff --git a/TWS/apps/applications/earbud/av_headset_conn_rules.c b/TWS/apps/applications/earbud/av_headset_conn_rules.c index 361b4dd..c3f11dd 100644 --- a/TWS/apps/applications/earbud/av_headset_conn_rules.c +++ b/TWS/apps/applications/earbud/av_headset_conn_rules.c @@ -2397,7 +2397,8 @@ static ruleAction ruleBleConnectionUpdate(void) if (our_battery < peer_battery) { DEBUG_LOG("ruleBleConnectionUpdate Peer (out of case) has stronger battery."); - connectable = FALSE; + //comment by zhongyukang ,otherwise it will mask ble adv + // connectable = FALSE; } else if (our_battery == peer_battery) {逻辑中uart与blood pressure service连接起来,期间 面临的主要是编译问题
From 04717add8eaebdf90a642d631d29ce3f18ddebcc Mon Sep 17 00:00:00 2001 From: zyukang <zyukang@waterworld.com.cn> Date: Tue, 22 Sep 2020 11:47:20 +0800 Subject: [PATCH 1/3] connect uart and blood service --- TWS/apps/applications/earbud/av_headset_gatt.c | 23 ++++++++++++++++++++++- TWS/apps/applications/earbud/av_headset_gatt.h | 4 +++- TWS/apps/applications/earbud/peripherals/uart.c | 10 ++++++++-- TWS/apps/applications/earbud/peripherals/uart.h | 2 ++ 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/TWS/apps/applications/earbud/av_headset_gatt.c b/TWS/apps/applications/earbud/av_headset_gatt.c index 9fb890c..491051b 100644 --- a/TWS/apps/applications/earbud/av_headset_gatt.c +++ b/TWS/apps/applications/earbud/av_headset_gatt.c @@ -23,7 +23,13 @@ #include <gatt_gap_server.h> #include <gaia.h> #include <panic.h> - +#ifdef HAVE_UART +#include "peripherals/uart.h" +#endif +#if defined(INCLUDE_GATT_BLOOD_PRESSURE) +const SEANS *gsean_server =NULL; +uint16 gcid = 0; +#endif /*! Earbud GATT database, for the required GATT and GAP servers. */ extern const uint16 gattDatabase[]; @@ -624,6 +630,8 @@ static void appGattHandleSeanServerReadclientconfigInd(const GATT_SEAN_SERVER_RE i++; if (i == 100)i = 0; /* Return requested battery level */ + gsean_server = ind->sean_server; + gcid = ind->cid; GattSeanServerReadclientconfigResponse(ind->sean_server, ind->cid, return_value); } #if 0 @@ -637,14 +645,27 @@ static void appGattHandleSeanServerReadClientConfig(const GATT_SEAN_SERVER_WRITE static void appGattHandleSeanServerWriteSth(const GATT_SEAN_SERVER_WRITE_STH_IND_T * ind) { uint16 client_config = 0; + uint8 config_resp[GATT_CLIENT_CONFIG_OCTET_SIZE]; client_config = ind->write_value ; // client_config = 0x98; DEBUG_LOG("SEAN: appGattHandleSeanServerWriteSth, write_value=[0x%x] cid=[0x%x]\n", client_config,ind->cid); GattSeanServerWriteToNofityResponse(ind->sean_server, ind->cid, client_config); + config_resp[0] = client_config & 0xFF; + config_resp[1] = (client_config >> 8) & 0xFF; +#ifdef HAVE_UART + uart_data_stream_tx_data((const uint8*)&config_resp,1); +#endif } +bool GattSeanServerNofityClient( uint16 value) +{ + if((gsean_server) &&(gcid)) { + return GattSeanServerWriteToNofityResponse(gsean_server,gcid, value); + } + return FALSE; +} void appGattSeanMessageHandler(Task task, MessageId id, Message message) { UNUSED(task); diff --git a/TWS/apps/applications/earbud/av_headset_gatt.h b/TWS/apps/applications/earbud/av_headset_gatt.h index 8dcd3a9..79e2d12 100644 --- a/TWS/apps/applications/earbud/av_headset_gatt.h +++ b/TWS/apps/applications/earbud/av_headset_gatt.h @@ -165,6 +165,8 @@ bool appGattHandleConnectionLibraryMessages(MessageId id, Message message, bool /*! @brief Initialise the GATT component. */ void appGattInit(void); - +#ifdef INCLUDE_GATT_BLOOD_PRESSURE +extern bool GattSeanServerNofityClient( uint16 value); +#endif #endif /* _AV_HEADSET_GATT_H_ */ diff --git a/TWS/apps/applications/earbud/peripherals/uart.c b/TWS/apps/applications/earbud/peripherals/uart.c index 2622592..9ae999c 100644 --- a/TWS/apps/applications/earbud/peripherals/uart.c +++ b/TWS/apps/applications/earbud/peripherals/uart.c @@ -1,9 +1,11 @@ #ifdef HAVE_UART #include "uart.h" +#ifdef INCLUDE_GATT_BLOOD_PRESSURE +extern bool GattSeanServerNofityClient( uint16 value); +#endif UARTStreamTaskData theUARTStreamTask; static void UARTStreamMessageHandler(Task ppTask,MessageId pId,Message pMessage); static void uart_data_stream_rx_data(Source src); -static void uart_data_stream_tx_data(const uint8*data,uint16 length); /*UART*/ void uart_data_stream_init(void) { @@ -60,7 +62,11 @@ void uart_data_stream_rx_data(Source src) PanicNull((void*)data); DEBUG_LOG("uart_data_stream_rx_data reg:0x%x 0x%x 0x%x",data[0],data[1],data[2]); /*Transmitthereceiveddata*/ - uart_data_stream_tx_data(data,length); +// uart_data_stream_tx_data(data,length); +#ifdef INCLUDE_GATT_BLOOD_PRESSURE + uint16 value = (data[0] &0xFF) |((data[1] <<8)&0xFF00); + GattSeanServerNofityClient((uint16)value); +#endif /*Discardsthespecifiedamountofbytesfromthefrontofthespecified source*/ SourceDrop(src,length); diff --git a/TWS/apps/applications/earbud/peripherals/uart.h b/TWS/apps/applications/earbud/peripherals/uart.h index 12d33c9..c5dcb85 100644 --- a/TWS/apps/applications/earbud/peripherals/uart.h +++ b/TWS/apps/applications/earbud/peripherals/uart.h @@ -23,4 +23,6 @@ Sink uart_sink; Source uart_source; }UARTStreamTaskData; extern void uart_data_stream_init(void); +extern void uart_data_stream_tx_data(const uint8*data,uint16 length); + #endif -- 1.9.1添加只在使能notify功能时才发通知给client
From 46161a3012e80bab2cfb7ebaf1b481a64fb63780 Mon Sep 17 00:00:00 2001 From: zyukang <zyukang@waterworld.com.cn> Date: Tue, 22 Sep 2020 14:22:49 +0800 Subject: [PATCH 2/3] blood pressure service add notify func --- TWS/apps/applications/earbud/av_headset_gatt.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/TWS/apps/applications/earbud/av_headset_gatt.c b/TWS/apps/applications/earbud/av_headset_gatt.c index 491051b..8d7f583 100644 --- a/TWS/apps/applications/earbud/av_headset_gatt.c +++ b/TWS/apps/applications/earbud/av_headset_gatt.c @@ -630,8 +630,6 @@ static void appGattHandleSeanServerReadclientconfigInd(const GATT_SEAN_SERVER_RE i++; if (i == 100)i = 0; /* Return requested battery level */ - gsean_server = ind->sean_server; - gcid = ind->cid; GattSeanServerReadclientconfigResponse(ind->sean_server, ind->cid, return_value); } #if 0 @@ -650,7 +648,7 @@ static void appGattHandleSeanServerWriteSth(const GATT_SEAN_SERVER_WRITE_STH_IND client_config = ind->write_value ; // client_config = 0x98; DEBUG_LOG("SEAN: appGattHandleSeanServerWriteSth, write_value=[0x%x] cid=[0x%x]\n", client_config,ind->cid); - GattSeanServerWriteToNofityResponse(ind->sean_server, ind->cid, client_config); + // GattSeanServerWriteToNofityResponse(ind->sean_server, ind->cid, client_config); config_resp[0] = client_config & 0xFF; config_resp[1] = (client_config >> 8) & 0xFF; @@ -691,9 +689,16 @@ void appGattSeanMessageHandler(Task task, MessageId id, Message message) appGattHandleSeanServerReadclientconfigInd((const GATT_SEAN_SERVER_READ_STH_IND_T *) message); break; case GATT_SEAN_SERVER_WRITE_CLIENT_CONFIG_IND: - DEBUG_LOG("SEAN: appGattSeanMessageHandler:GATT_SEAN_SERVER_WRITE_CLIENT_CONFIG_IND cid=[0x%x]",((const GATT_SEAN_SERVER_READ_STH_IND_T *) message)->cid); + DEBUG_LOG("SEAN: appGattSeanMessageHandler:GATT_SEAN_SERVER_WRITE_CLIENT_CONFIG_IND cid=[0x%x] value:0x%x",((const GATT_SEAN_SERVER_WRITE_CLIENT_CONFIG_IND_T *) message)->cid,((const GATT_SEAN_SERVER_WRITE_CLIENT_CONFIG_IND_T *) message)->config_value); // appGattHandleSeanServerReadClientConfig((const GATT_SEAN_SERVER_WRITE_CLIENT_CONFIG_IND_T *)message); - + GATT_SEAN_SERVER_WRITE_CLIENT_CONFIG_IND_T * ind = (( GATT_SEAN_SERVER_WRITE_CLIENT_CONFIG_IND_T *) message); + if (ind->config_value) { + gsean_server = ind->sean_server; + gcid = ind->cid; + }else { + gsean_server = NULL; + gcid = 0; + } break; default: DEBUG_LOG("SEAN: appGattSeanMessageHandler. Unhandled message id:0x%x", id); -- 1.9.1修改att数据长度,最大为10个字节,修改空指针引起的crash (多数是数组越界访问),发给client最大10个字节,接收2个字节
会有一系列问题
后来fae给的建议是在生产时完成对耳,然后将平台删除对耳的去掉
diff --git a/TWS/apps/applications/earbud/av_headset_ui.c b/TWS/apps/applications/earbud/av_headset_ui.c index 1b121e2..045db69 100644 --- a/TWS/apps/applications/earbud/av_headset_ui.c +++ b/TWS/apps/applications/earbud/av_headset_ui.c @@ -918,9 +918,16 @@ static void appUiHandleMessage(Task task, MessageId id, Message message) /* Delete Handset Pairings */ case APP_MFB_BUTTON_8_SECOND: - DEBUG_LOG("APP_MFB_BUTTON_6_SECOND"); + DEBUG_LOG("APP_MFB_BUTTON_8_SECOND"); if (appSmIsOutOfCase()) - appSmDeleteHandsets(); + { + if (!appSmIsPairing()) + appSmPairHandset(); + else + { + // TODO: Cancel pairing + } + } break; #if defined(HAVE_6_BUTTONS) || defined(HAVE_9_BUTTONS)担心ota升级会有影响,就测试了一下,发现dfu不能用传统蓝牙升级,打开即可
diff --git a/TWS/apps/applications/earbud/av_headset_config.h b/TWS/apps/applications/earbud/av_headset_config.h index f67b9c3..08cf45a 100644 --- a/TWS/apps/applications/earbud/av_headset_config.h +++ b/TWS/apps/applications/earbud/av_headset_config.h @@ -22,7 +22,7 @@ /*! Can BREDR be used to perform upgrades when not in the case */ -#define appConfigDfuAllowBredrUpgradeOutOfCase() FALSE +#define appConfigDfuAllowBredrUpgradeOutOfCase() TRUE /*! Only allow upgrades when the request has been made by the user (through the UI)制作dfu包
80-cg791-1_ab_adk_6.3.x_device_firmware_upgrade_user_guide.pdf以下出现的跟据需求选
最后生成 通过gaia连接tws升级 这里试了很多次,不过都是接着升级的,出现了错误,后来发现要升级前,重新poweroff /poweron就没怎么出现以下的footer错误了 之后出现连接gaia连接不上,也是断电上电解决 的