gattservapp.c 77 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565
  1. /**************************************************************************************************
  2. Phyplus Microelectronics Limited confidential and proprietary.
  3. All rights reserved.
  4. IMPORTANT: All rights of this software belong to Phyplus Microelectronics
  5. Limited ("Phyplus"). Your use of this Software is limited to those
  6. specific rights granted under the terms of the business contract, the
  7. confidential agreement, the non-disclosure agreement and any other forms
  8. of agreements as a customer or a partner of Phyplus. You may not use this
  9. Software unless you agree to abide by the terms of these agreements.
  10. You acknowledge that the Software may not be modified, copied,
  11. distributed or disclosed unless embedded on a Phyplus Bluetooth Low Energy
  12. (BLE) integrated circuit, either as a product or is integrated into your
  13. products. Other than for the aforementioned purposes, you may not use,
  14. reproduce, copy, prepare derivative works of, modify, distribute, perform,
  15. display or sell this Software and/or its documentation for any purposes.
  16. YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  17. PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  18. INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  19. NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  20. PHYPLUS OR ITS SUBSIDIARIES BE LIABLE OR OBLIGATED UNDER CONTRACT,
  21. NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  22. LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  23. INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  24. OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  25. OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  26. (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
  27. **************************************************************************************************/
  28. /*************************************************************************************************
  29. Filename: gattservapp.c
  30. Revised:
  31. Revision:
  32. Description: This file contains the GATT Server Application.
  33. **************************************************************************************************/
  34. #if ( HOST_CONFIG & ( CENTRAL_CFG | PERIPHERAL_CFG ) )
  35. /*******************************************************************************
  36. * INCLUDES
  37. */
  38. #include "bcomdef.h"
  39. #include "linkdb.h"
  40. #include "gatt.h"
  41. #include "gatt_uuid.h"
  42. #include "gattservapp.h"
  43. /*********************************************************************
  44. * MACROS
  45. */
  46. /*********************************************************************
  47. * CONSTANTS
  48. */
  49. /*********************************************************************
  50. * TYPEDEFS
  51. */
  52. // Structure to keep Prepare Write Requests for each Client
  53. typedef struct
  54. {
  55. uint16 connHandle; // connection message was received on
  56. attPrepareWriteReq_t *pPrepareWriteQ; // Prepare Write Request queue
  57. } prepareWrites_t;
  58. // GATT Structure to keep CBs information for each service being registered
  59. typedef struct
  60. {
  61. uint16 handle; // Service handle - assigned internally by GATT Server
  62. CONST gattServiceCBs_t *pCBs; // Service callback function pointers
  63. } gattServiceCBsInfo_t;
  64. // Service callbacks list item
  65. typedef struct _serviceCBsList
  66. {
  67. struct _serviceCBsList *next; // pointer to next service callbacks record
  68. gattServiceCBsInfo_t serviceInfo; // service handle/callbacks
  69. } serviceCBsList_t;
  70. /*********************************************************************
  71. * GLOBAL VARIABLES
  72. */
  73. /*********************************************************************
  74. * EXTERNAL VARIABLES
  75. */
  76. /*********************************************************************
  77. * EXTERNAL FUNCTIONS
  78. */
  79. extern l2capSegmentBuff_t l2capSegmentPkt;
  80. /*********************************************************************
  81. * LOCAL VARIABLES
  82. */
  83. uint8 GATTServApp_TaskID; // Task ID for internal task/event processing
  84. uint8 appTaskID = INVALID_TASK_ID; // The task ID of an app/profile that
  85. // wants GATT Server event messages
  86. // Server Prepare Write table (one entry per each physical link)
  87. static prepareWrites_t prepareWritesTbl[MAX_NUM_LL_CONN];
  88. // Maximum number of attributes that Server can prepare for writing per Client
  89. static uint8 maxNumPrepareWrites = 0;
  90. #ifdef PREPARE_QUEUE_STATIC
  91. static attPrepareWriteReq_t prepareQueue[MAX_NUM_LL_CONN*GATT_MAX_NUM_PREPARE_WRITES];
  92. #endif
  93. // Callbacks for services
  94. static serviceCBsList_t *serviceCBsList = NULL;
  95. // Globals to be used for processing an incoming request
  96. static uint8 attrLen;
  97. static uint8 attrValue[ATT_MTU_SIZE-1];
  98. static attMsg_t rsp;
  99. /*** Defined GATT Attributes ***/
  100. // GATT Service attribute
  101. static CONST gattAttrType_t gattService = { ATT_BT_UUID_SIZE, gattServiceUUID };
  102. #ifndef HID_VOICE_SPEC
  103. // Service Changed Characteristic Properties
  104. static uint8 serviceChangedCharProps = GATT_PROP_INDICATE;
  105. #endif
  106. // Service Changed attribute (hidden). Set the affected Attribute Handle range
  107. // to 0x0001 to 0xFFFF to indicate to the client to rediscover the entire set
  108. // of Attribute Handles on the server.
  109. // Client Characteristic configuration. Each client has its own instantiation
  110. // of the Client Characteristic Configuration. Reads of the Client Characteristic
  111. // Configuration only shows the configuration for that client and writes only
  112. // affect the configuration of that client.
  113. static gattCharCfg_t indCharCfg[GATT_MAX_NUM_CONN];
  114. #if defined ( TESTMODES )
  115. static uint16 paramValue = 0;
  116. #endif
  117. /*********************************************************************
  118. * Profile Attributes - Table
  119. */
  120. // GATT Attribute Table
  121. static gattAttribute_t gattAttrTbl[] = {
  122. // Generic Attribute Profile
  123. {
  124. { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */
  125. GATT_PERMIT_READ, /* permissions */
  126. 0, /* handle */
  127. (uint8 *)&gattService /* pValue */
  128. },
  129. #ifndef HID_VOICE_SPEC
  130. // Characteristic Declaration
  131. {
  132. { ATT_BT_UUID_SIZE, characterUUID },
  133. GATT_PERMIT_READ,
  134. 0,
  135. &serviceChangedCharProps
  136. },
  137. // Attribute Service Changed
  138. {
  139. { ATT_BT_UUID_SIZE, serviceChangedUUID },
  140. 0,
  141. 0,
  142. NULL
  143. },
  144. // Client Characteristic configuration
  145. {
  146. { ATT_BT_UUID_SIZE, clientCharCfgUUID },
  147. GATT_PERMIT_READ | GATT_PERMIT_WRITE,
  148. 0,
  149. (uint8 *)indCharCfg
  150. }
  151. #endif
  152. };
  153. /*********************************************************************
  154. * LOCAL FUNCTIONS
  155. */
  156. static void gattServApp_ProcessMsg( gattMsgEvent_t *pMsg );
  157. static bStatus_t gattServApp_ProcessExchangeMTUReq( gattMsgEvent_t *pMsg );
  158. static bStatus_t gattServApp_ProcessFindByTypeValueReq( gattMsgEvent_t *pMsg, uint16 *pErrHandle );
  159. static bStatus_t gattServApp_ProcessReadByTypeReq( gattMsgEvent_t *pMsg, uint16 *pErrHandle );
  160. static bStatus_t gattServApp_ProcessReadReq( gattMsgEvent_t *pMsg, uint16 *pErrHandle );
  161. static bStatus_t gattServApp_ProcessReadBlobReq( gattMsgEvent_t *pMsg, uint16 *pErrHandle );
  162. static bStatus_t gattServApp_ProcessReadMultiReq( gattMsgEvent_t *pMsg, uint16 *pErrHandle );
  163. static bStatus_t gattServApp_ProcessReadByGrpTypeReq( gattMsgEvent_t *pMsg, uint16 *pErrHandle );
  164. static bStatus_t gattServApp_ProcessWriteReq( gattMsgEvent_t *pMsg, uint16 *pErrHandle );
  165. static bStatus_t gattServApp_ProcessPrepareWriteReq( gattMsgEvent_t *pMsg, uint16 *pErrHandle );
  166. static bStatus_t gattServApp_ProcessExecuteWriteReq( gattMsgEvent_t *pMsg, uint16 *pErrHandle );
  167. static bStatus_t gattServApp_RegisterServiceCBs( uint16 handle, CONST gattServiceCBs_t *pServiceCBs );
  168. static bStatus_t gattServApp_DeregisterServiceCBs( uint16 handle );
  169. static bStatus_t gattServApp_SetNumPrepareWrites( uint8 numPrepareWrites );
  170. static uint8 gattServApp_PrepareWriteQInUse( void );
  171. static CONST gattServiceCBs_t *gattServApp_FindServiceCBs( uint16 service );
  172. static bStatus_t gattServApp_EnqueuePrepareWriteReq( uint16 connHandle, attPrepareWriteReq_t *pReq );
  173. static prepareWrites_t *gattServApp_FindPrepareWriteQ( uint16 connHandle );
  174. static gattCharCfg_t *gattServApp_FindCharCfgItem( uint16 connHandle,
  175. gattCharCfg_t *charCfgTbl );
  176. static pfnGATTReadAttrCB_t gattServApp_FindReadAttrCB( uint16 handle );
  177. static pfnGATTWriteAttrCB_t gattServApp_FindWriteAttrCB( uint16 handle );
  178. static pfnGATTAuthorizeAttrCB_t gattServApp_FindAuthorizeAttrCB( uint16 handle );
  179. /*********************************************************************
  180. * API FUNCTIONS
  181. */
  182. // GATT App Callback functions
  183. static void gattServApp_HandleConnStatusCB( uint16 connHandle, uint8 changeType );
  184. static bStatus_t gattServApp_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
  185. uint8 *pValue, uint8 len, uint16 offset );
  186. /*********************************************************************
  187. * PROFILE CALLBACKS
  188. */
  189. // GATT Service Callbacks
  190. CONST gattServiceCBs_t gattServiceCBs =
  191. {
  192. NULL, // Read callback function pointer
  193. gattServApp_WriteAttrCB, // Write callback function pointer
  194. NULL // Authorization callback function pointer
  195. };
  196. static gattServMsgCB_t s_GATTServCB = NULL;
  197. /*********************************************************************
  198. * @fn GATTServApp_RegisterForMsgs
  199. *
  200. * @brief Register your task ID to receive event messages from
  201. * the GATT Server Application.
  202. *
  203. * @param taskId - Default task ID to send events
  204. *
  205. * @return none
  206. */
  207. void GATTServApp_RegisterForMsg( uint8 taskID )
  208. {
  209. appTaskID = taskID;
  210. }
  211. /*********************************************************************
  212. * @fn GATTServApp_Init
  213. *
  214. * @brief Initialize the GATT Server Application.
  215. *
  216. * @param taskId - Task identifier for the desired task
  217. *
  218. * @return none
  219. */
  220. void GATTServApp_Init( uint8 taskId )
  221. {
  222. GATTServApp_TaskID = taskId;
  223. // Initialize Client Characteristic Configuration attributes
  224. GATTServApp_InitCharCfg( INVALID_CONNHANDLE, indCharCfg );
  225. // Initialize Prepare Write Table
  226. for ( uint8 i = 0; i < MAX_NUM_LL_CONN; i++ )
  227. {
  228. // Initialize connection handle
  229. prepareWritesTbl[i].connHandle = INVALID_CONNHANDLE;
  230. // Initialize the prepare write queue
  231. prepareWritesTbl[i].pPrepareWriteQ = NULL;
  232. }
  233. // Set up the initial prepare write queues
  234. gattServApp_SetNumPrepareWrites( GATT_MAX_NUM_PREPARE_WRITES );
  235. // Register to receive incoming ATT Requests
  236. GATT_RegisterForReq( GATTServApp_TaskID );
  237. // Register with Link DB to receive link status change callback
  238. VOID linkDB_Register( gattServApp_HandleConnStatusCB );
  239. }
  240. /*********************************************************************
  241. * @fn GATTServApp_ProcessEvent
  242. *
  243. * @brief GATT Server Application Task event processor. This function
  244. * is called to process all events for the task. Events include
  245. * timers, messages and any other user defined events.
  246. *
  247. * @param task_id - The OSAL assigned task ID.
  248. * @param events - events to process. This is a bit map and can
  249. * contain more than one event.
  250. *
  251. * @return none
  252. */
  253. uint16 GATTServApp_ProcessEvent( uint8 task_id, uint16 events )
  254. {
  255. if ( events & SYS_EVENT_MSG )
  256. {
  257. osal_event_hdr_t *pMsg;
  258. if ( (pMsg = ( osal_event_hdr_t *)osal_msg_receive( GATTServApp_TaskID )) != NULL )
  259. {
  260. // Process incoming messages
  261. switch ( pMsg->event )
  262. {
  263. // Incoming GATT message
  264. case GATT_MSG_EVENT:
  265. gattServApp_ProcessMsg( (gattMsgEvent_t *)pMsg );
  266. break;
  267. default:
  268. // Unsupported message
  269. break;
  270. }
  271. // Release the OSAL message
  272. VOID osal_msg_deallocate( (uint8 *)pMsg );
  273. }
  274. // return unprocessed events
  275. return (events ^ SYS_EVENT_MSG);
  276. }
  277. // Discard unknown events
  278. return 0;
  279. }
  280. /******************************************************************************
  281. * @fn GATTServApp_RegisterService
  282. *
  283. * @brief Register a service's attribute list and callback functions with
  284. * the GATT Server Application.
  285. *
  286. * @param pAttrs - Array of attribute records to be registered
  287. * @param numAttrs - Number of attributes in array
  288. * @param pServiceCBs - Service callback function pointers
  289. *
  290. * @return SUCCESS: Service registered successfully.
  291. * INVALIDPARAMETER: Invalid service field.
  292. * FAILURE: Not enough attribute handles available.
  293. * bleMemAllocError: Memory allocation error occurred.
  294. */
  295. bStatus_t GATTServApp_RegisterService( gattAttribute_t *pAttrs, uint16 numAttrs,
  296. CONST gattServiceCBs_t *pServiceCBs )
  297. {
  298. uint8 status;
  299. // First register the service attribute list with GATT Server
  300. if ( pAttrs != NULL )
  301. {
  302. gattService_t service;
  303. service.attrs = pAttrs;
  304. service.numAttrs = numAttrs;
  305. status = GATT_RegisterService( &service );
  306. if ( ( status == SUCCESS ) && ( pServiceCBs != NULL ) )
  307. {
  308. // Register the service CBs with GATT Server Application
  309. status = gattServApp_RegisterServiceCBs( GATT_SERVICE_HANDLE( pAttrs ),
  310. pServiceCBs );
  311. }
  312. }
  313. else
  314. {
  315. status = INVALIDPARAMETER;
  316. }
  317. return ( status );
  318. }
  319. /******************************************************************************
  320. * @fn GATTServApp_DeregisterService
  321. *
  322. * @brief Deregister a service's attribute list and callback functions from
  323. * the GATT Server Application.
  324. *
  325. * NOTE: It's the caller's responsibility to free the service attribute
  326. * list returned from this API.
  327. *
  328. * @param handle - handle of service to be deregistered
  329. * @param p2pAttrs - pointer to array of attribute records (to be returned)
  330. *
  331. * @return SUCCESS: Service deregistered successfully.
  332. * FAILURE: Service not found.
  333. */
  334. bStatus_t GATTServApp_DeregisterService( uint16 handle, gattAttribute_t **p2pAttrs )
  335. {
  336. uint8 status;
  337. // First deregister the service CBs with GATT Server Application
  338. status = gattServApp_DeregisterServiceCBs( handle );
  339. if ( status == SUCCESS )
  340. {
  341. gattService_t service;
  342. // Deregister the service attribute list with GATT Server
  343. status = GATT_DeregisterService( handle, &service );
  344. if ( status == SUCCESS )
  345. {
  346. if ( p2pAttrs != NULL )
  347. {
  348. *p2pAttrs = service.attrs;
  349. }
  350. }
  351. }
  352. return ( status );
  353. }
  354. /*********************************************************************
  355. * @fn GATTServApp_SetParameter
  356. *
  357. * @brief Set a GATT Server parameter.
  358. *
  359. * @param param - Profile parameter ID
  360. * @param len - length of data to right
  361. * @param pValue - pointer to data to write. This is dependent on the
  362. * the parameter ID and WILL be cast to the appropriate
  363. * data type (example: data type of uint16 will be cast
  364. * to uint16 pointer).
  365. *
  366. * @return SUCCESS: Parameter set successful
  367. * FAILURE: Parameter in use
  368. * INVALIDPARAMETER: Invalid parameter
  369. * bleInvalidRange: Invalid value
  370. * bleMemAllocError: Memory allocation failed
  371. */
  372. bStatus_t GATTServApp_SetParameter( uint8 param, uint8 len, void *pValue )
  373. {
  374. bStatus_t status = SUCCESS;
  375. switch ( param )
  376. {
  377. case GATT_PARAM_NUM_PREPARE_WRITES:
  378. if ( len == sizeof ( uint8 ) )
  379. {
  380. if ( !gattServApp_PrepareWriteQInUse() )
  381. {
  382. // Set the new nunber of prepare writes
  383. status = gattServApp_SetNumPrepareWrites( *((uint8*)pValue) );
  384. }
  385. else
  386. {
  387. status = FAILURE;
  388. }
  389. }
  390. else
  391. {
  392. status = bleInvalidRange;
  393. }
  394. break;
  395. default:
  396. status = INVALIDPARAMETER;
  397. break;
  398. }
  399. return ( status );
  400. }
  401. /*********************************************************************
  402. * @fn GATTServApp_GetParameter
  403. *
  404. * @brief Get a GATT Server parameter.
  405. *
  406. * @param param - Profile parameter ID
  407. * @param pValue - pointer to data to put. This is dependent on the
  408. * parameter ID and WILL be cast to the appropriate
  409. * data type (example: data type of uint16 will be
  410. * cast to uint16 pointer).
  411. *
  412. * @return SUCCESS: Parameter get successful
  413. * INVALIDPARAMETER: Invalid parameter
  414. */
  415. bStatus_t GATTServApp_GetParameter( uint8 param, void *pValue )
  416. {
  417. bStatus_t status = SUCCESS;
  418. switch ( param )
  419. {
  420. case GATT_PARAM_NUM_PREPARE_WRITES:
  421. *((uint8*)pValue) = maxNumPrepareWrites;
  422. break;
  423. default:
  424. status = INVALIDPARAMETER;
  425. break;
  426. }
  427. return ( status );
  428. }
  429. /*********************************************************************
  430. * @fn gattServApp_SetNumPrepareWrites
  431. *
  432. * @brief Set the maximum number of the prepare writes.
  433. *
  434. * @param numPrepareWrites - number of prepare writes
  435. *
  436. * @return SUCCESS: New number set successfully.
  437. * bleMemAllocError: Memory allocation failed.
  438. */
  439. static bStatus_t gattServApp_SetNumPrepareWrites( uint8 numPrepareWrites )
  440. {
  441. attPrepareWriteReq_t *pQueue;
  442. uint16 queueSize = ( MAX_NUM_LL_CONN * numPrepareWrites * sizeof( attPrepareWriteReq_t ) );
  443. // First make sure no one can get access to the Prepare Write Table
  444. maxNumPrepareWrites = 0;
  445. // Free the existing prepare write queues
  446. if ( prepareWritesTbl[0].pPrepareWriteQ != NULL )
  447. {
  448. #ifndef PREPARE_QUEUE_STATIC
  449. osal_mem_free( prepareWritesTbl[0].pPrepareWriteQ );
  450. #endif
  451. // Null out the prepare writes queues
  452. for ( uint8 i = 0; i < MAX_NUM_LL_CONN; i++ )
  453. {
  454. prepareWritesTbl[i].pPrepareWriteQ = NULL;
  455. }
  456. }
  457. // Allocate the prepare write queues
  458. #ifdef PREPARE_QUEUE_STATIC
  459. pQueue = prepareQueue;
  460. #else
  461. pQueue = osal_mem_alloc( queueSize );
  462. #endif
  463. if ( pQueue != NULL )
  464. {
  465. // Initialize the prepare write queues
  466. VOID osal_memset( pQueue, 0, queueSize );
  467. // Set up the prepare write queue for each client (i.e., connection)
  468. for ( uint8 i = 0; i < MAX_NUM_LL_CONN; i++ )
  469. {
  470. uint8 nextQ = i * numPrepareWrites; // Index of next available queue
  471. prepareWritesTbl[i].pPrepareWriteQ = &(pQueue[nextQ]);
  472. // Mark the prepare write request items as empty
  473. for ( uint8 j = 0; j < numPrepareWrites; j++ )
  474. {
  475. prepareWritesTbl[i].pPrepareWriteQ[j].handle = GATT_INVALID_HANDLE;
  476. }
  477. }
  478. // Set the new number of prepare writes
  479. maxNumPrepareWrites = numPrepareWrites;
  480. return ( SUCCESS );
  481. }
  482. return ( bleMemAllocError );
  483. }
  484. /*********************************************************************
  485. * @fn GATTServApp_FindAttr
  486. *
  487. * @brief Find the attribute record within a service attribute
  488. * table for a given attribute value pointer.
  489. *
  490. * @param pAttrTbl - pointer to attribute table
  491. * @param numAttrs - number of attributes in attribute table
  492. * @param pValue - pointer to attribute value
  493. *
  494. * @return Pointer to attribute record. NULL, if not found.
  495. */
  496. gattAttribute_t *GATTServApp_FindAttr( gattAttribute_t *pAttrTbl, uint16 numAttrs, uint8 *pValue )
  497. {
  498. for ( uint16 i = 0; i < numAttrs; i++ )
  499. {
  500. if ( pAttrTbl[i].pValue == pValue )
  501. {
  502. // Attribute record found
  503. return ( &(pAttrTbl[i]) );
  504. }
  505. }
  506. return ( (gattAttribute_t *)NULL );
  507. }
  508. /******************************************************************************
  509. * @fn GATTServApp_AddService
  510. *
  511. * @brief Add function for the GATT Service.
  512. *
  513. * @param services - services to add. This is a bit map and can
  514. * contain more than one service.
  515. *
  516. * @return SUCCESS: Service added successfully.
  517. * INVALIDPARAMETER: Invalid service field.
  518. * FAILURE: Not enough attribute handles available.
  519. * bleMemAllocError: Memory allocation error occurred.
  520. */
  521. bStatus_t GATTServApp_AddService( uint32 services )
  522. {
  523. uint8 status = SUCCESS;
  524. if ( services & GATT_SERVICE )
  525. {
  526. // Register GATT attribute list and CBs with GATT Server Application
  527. status = GATTServApp_RegisterService( gattAttrTbl, GATT_NUM_ATTRS( gattAttrTbl ),
  528. &gattServiceCBs );
  529. }
  530. return ( status );
  531. }
  532. /******************************************************************************
  533. * @fn GATTServApp_DelService
  534. *
  535. * @brief Delete function for the GATT Service.
  536. *
  537. * @param services - services to delete. This is a bit map and can
  538. * contain more than one service.
  539. *
  540. * @return SUCCESS: Service deleted successfully.
  541. * FAILURE: Service not found.
  542. */
  543. bStatus_t GATTServApp_DelService( uint32 services )
  544. {
  545. uint8 status = SUCCESS;
  546. if ( services & GATT_SERVICE )
  547. {
  548. // Deregister GATT attribute list and CBs from GATT Server Application
  549. status = GATTServApp_DeregisterService( GATT_SERVICE_HANDLE( gattAttrTbl ), NULL );
  550. }
  551. return ( status );
  552. }
  553. /******************************************************************************
  554. * @fn gattServApp_RegisterServiceCBs
  555. *
  556. * @brief Register callback functions for a service.
  557. *
  558. * @param handle - handle of service being registered
  559. * @param pServiceCBs - pointer to service CBs to be registered
  560. *
  561. * @return SUCCESS: Service CBs were registered successfully.
  562. * INVALIDPARAMETER: Invalid service CB field.
  563. * bleMemAllocError: Memory allocation error occurred.
  564. */
  565. static bStatus_t gattServApp_RegisterServiceCBs( uint16 handle,
  566. CONST gattServiceCBs_t *pServiceCBs )
  567. {
  568. serviceCBsList_t *pNewItem;
  569. // Make sure the service handle is specified
  570. if ( handle == GATT_INVALID_HANDLE )
  571. {
  572. return ( INVALIDPARAMETER );
  573. }
  574. // Fill in the new service list
  575. pNewItem = (serviceCBsList_t *)osal_mem_alloc( sizeof( serviceCBsList_t ) );
  576. if ( pNewItem == NULL )
  577. {
  578. // Not enough memory
  579. return ( bleMemAllocError );
  580. }
  581. // Set up new service CBs item
  582. pNewItem->next = NULL;
  583. pNewItem->serviceInfo.handle = handle;
  584. pNewItem->serviceInfo.pCBs = pServiceCBs;
  585. // Find spot in list
  586. if ( serviceCBsList == NULL )
  587. {
  588. // First item in list
  589. serviceCBsList = pNewItem;
  590. }
  591. else
  592. {
  593. serviceCBsList_t *pLoop = serviceCBsList;
  594. // Look for end of list
  595. while ( pLoop->next != NULL )
  596. {
  597. pLoop = pLoop->next;
  598. }
  599. // Put new item at end of list
  600. pLoop->next = pNewItem;
  601. }
  602. return ( SUCCESS );
  603. }
  604. /******************************************************************************
  605. * @fn gattServApp_DeregisterServiceCBs
  606. *
  607. * @brief Deregister callback functions for a service.
  608. *
  609. * @param handle - handle of service CBs to be deregistered
  610. *
  611. * @return SUCCESS: Service CBs were deregistered successfully.
  612. * FAILURE: Service CBs were not found.
  613. */
  614. static bStatus_t gattServApp_DeregisterServiceCBs( uint16 handle )
  615. {
  616. serviceCBsList_t *pLoop = serviceCBsList;
  617. serviceCBsList_t *pPrev = NULL;
  618. // Look for service
  619. while ( pLoop != NULL )
  620. {
  621. if ( pLoop->serviceInfo.handle == handle )
  622. {
  623. // Service CBs found; unlink it
  624. if ( pPrev == NULL )
  625. {
  626. // First item in list
  627. serviceCBsList = pLoop->next;
  628. }
  629. else
  630. {
  631. pPrev->next = pLoop->next;
  632. }
  633. // Free the service CB record
  634. osal_mem_free( pLoop );
  635. return ( SUCCESS );
  636. }
  637. pPrev = pLoop;
  638. pLoop = pLoop->next;
  639. }
  640. // Service CBs not found
  641. return ( FAILURE );
  642. }
  643. /*********************************************************************
  644. * @fn gattServApp_FindServiceCBs
  645. *
  646. * @brief Find service's callback record.
  647. *
  648. * @param handle - owner of service
  649. *
  650. * @return Pointer to service record. NULL, otherwise.
  651. */
  652. static CONST gattServiceCBs_t *gattServApp_FindServiceCBs( uint16 handle )
  653. {
  654. serviceCBsList_t *pLoop = serviceCBsList;
  655. while ( pLoop != NULL )
  656. {
  657. if ( pLoop->serviceInfo.handle == handle )
  658. {
  659. return ( pLoop->serviceInfo.pCBs );
  660. }
  661. // Try next service
  662. pLoop = pLoop->next;
  663. }
  664. return ( (gattServiceCBs_t *)NULL );
  665. }
  666. /*********************************************************************
  667. * @fn gattServApp_ProcessMsg
  668. *
  669. * @brief GATT Server App message processing function.
  670. *
  671. * @param pMsg - pointer to received message
  672. *
  673. * @return Success or Failure
  674. */
  675. static void gattServApp_ProcessMsg( gattMsgEvent_t *pMsg )
  676. {
  677. uint16 errHandle = GATT_INVALID_HANDLE;
  678. uint8 status;
  679. #if defined ( TESTMODES )
  680. if ( paramValue == GATT_TESTMODE_NO_RSP )
  681. {
  682. // Notify GATT that a message has been processed
  683. // Note: This call is optional if flow control is not used.
  684. GATT_AppCompletedMsg( pMsg );
  685. // Just ignore the incoming request messages
  686. return;
  687. }
  688. #endif
  689. // Process the GATT server message
  690. switch ( pMsg->method )
  691. {
  692. case ATT_EXCHANGE_MTU_REQ:
  693. status = gattServApp_ProcessExchangeMTUReq( pMsg );
  694. break;
  695. case ATT_FIND_BY_TYPE_VALUE_REQ:
  696. status = gattServApp_ProcessFindByTypeValueReq( pMsg, &errHandle );
  697. break;
  698. case ATT_READ_BY_TYPE_REQ:
  699. status = gattServApp_ProcessReadByTypeReq( pMsg, &errHandle );
  700. break;
  701. case ATT_READ_REQ:
  702. status = gattServApp_ProcessReadReq( pMsg, &errHandle );
  703. break;
  704. case ATT_READ_BLOB_REQ:
  705. status = gattServApp_ProcessReadBlobReq( pMsg, &errHandle );
  706. break;
  707. case ATT_READ_MULTI_REQ:
  708. status = gattServApp_ProcessReadMultiReq( pMsg, &errHandle );
  709. break;
  710. case ATT_READ_BY_GRP_TYPE_REQ:
  711. status = gattServApp_ProcessReadByGrpTypeReq( pMsg, &errHandle );
  712. break;
  713. case ATT_WRITE_REQ:
  714. status = gattServApp_ProcessWriteReq( pMsg, &errHandle );
  715. break;
  716. case ATT_PREPARE_WRITE_REQ:
  717. status = gattServApp_ProcessPrepareWriteReq( pMsg, &errHandle );
  718. break;
  719. case ATT_EXECUTE_WRITE_REQ:
  720. status = gattServApp_ProcessExecuteWriteReq( pMsg, &errHandle );
  721. break;
  722. default:
  723. // Unknown request - ignore it!
  724. status = SUCCESS;
  725. break;
  726. }
  727. // See if we need to send an error response back
  728. if ( status != SUCCESS )
  729. {
  730. // Make sure the request was not sent locally
  731. if ( pMsg->hdr.status != bleNotConnected )
  732. {
  733. attErrorRsp_t *pRsp = &rsp.errorRsp;
  734. pRsp->reqOpcode = pMsg->method;
  735. pRsp->handle = errHandle;
  736. pRsp->errCode = status;
  737. VOID ATT_ErrorRsp( pMsg->connHandle, pRsp );
  738. }
  739. }
  740. // Notify GATT that a message has been processed
  741. // Note: This call is optional if flow control is not used.
  742. GATT_AppCompletedMsg( pMsg );
  743. // if app task ask the gatt message, copy and send to app task
  744. if(s_GATTServCB)
  745. s_GATTServCB(pMsg);
  746. }
  747. /*********************************************************************
  748. * @fn gattServApp_ProcessExchangeMTUReq
  749. *
  750. * @brief Process Exchange MTU Request.
  751. *
  752. * @param pMsg - pointer to received message
  753. *
  754. * @return Success
  755. */
  756. static bStatus_t gattServApp_ProcessExchangeMTUReq( gattMsgEvent_t *pMsg )
  757. {
  758. attExchangeMTURsp_t *pRsp = &rsp.exchangeMTURsp;
  759. // ATT_MTU shall be set to the minimum of the Client Rx MTU and Server Rx MTU values
  760. // Set the Server Rx MTU parameter to the maximum MTU that this server can receive
  761. #if defined ( TESTMODES )
  762. if ( paramValue == GATT_TESTMODE_MAX_MTU_SIZE )
  763. {
  764. pRsp->serverRxMTU = ATT_MAX_MTU_SIZE;
  765. }
  766. else
  767. #endif
  768. pRsp->serverRxMTU = g_ATT_MTU_SIZE_MAX;//ATT_MTU_SIZE;
  769. // Send response back
  770. VOID ATT_ExchangeMTURsp( pMsg->connHandle, pRsp );
  771. return ( SUCCESS );
  772. }
  773. /*********************************************************************
  774. * @fn gattServApp_ProcessFindByTypeValueReq
  775. *
  776. * @brief Process Find By Type Value Request.
  777. *
  778. * @param pMsg - pointer to received message
  779. * @param pErrHandle - attribute handle that generates an error
  780. *
  781. * @return Success or Failure
  782. */
  783. static bStatus_t gattServApp_ProcessFindByTypeValueReq( gattMsgEvent_t *pMsg, uint16 *pErrHandle )
  784. {
  785. attFindByTypeValueReq_t *pReq = &pMsg->msg.findByTypeValueReq;
  786. attFindByTypeValueRsp_t *pRsp = &rsp.findByTypeValueRsp;
  787. gattAttribute_t *pAttr;
  788. uint16 service;
  789. // Initialize the response
  790. VOID osal_memset( pRsp, 0, sizeof( attFindByTypeValueRsp_t ) );
  791. // Only attributes with attribute handles between and including the Starting
  792. // Handle parameter and the Ending Handle parameter that match the requested
  793. // attribute type and the attribute value will be returned.
  794. // All attribute types are effectively compared as 128-bit UUIDs,
  795. // even if a 16-bit UUID is provided in this request or defined
  796. // for an attribute.
  797. pAttr = GATT_FindHandleUUID( pReq->startHandle, pReq->endHandle,
  798. pReq->type.uuid, pReq->type.len, &service );
  799. while ( ( pAttr != NULL ) && ( pRsp->numInfo < g_ATT_MAX_NUM_HANDLES_INFO ) )
  800. {
  801. uint16 grpEndHandle;
  802. // It is not possible to use this request on an attribute that has a value
  803. // that is longer than (ATT_MTU - 7).
  804. if ( GATTServApp_ReadAttr( pMsg->connHandle, pAttr, service, attrValue,
  805. &attrLen, 0, (g_ATT_MTU_SIZE-7) ) == SUCCESS )
  806. {
  807. // Attribute values should be compared in terms of length and binary representation.
  808. if ( ( pReq->len == attrLen ) && osal_memcmp( pReq->value, attrValue, attrLen) )
  809. {
  810. // New attribute found
  811. // Set the Found Handle to the attribute that has the exact attribute
  812. // type and attribute value from the request.
  813. pRsp->handlesInfo[pRsp->numInfo].handle = pAttr->handle;
  814. }
  815. }
  816. // Try to find the next attribute
  817. pAttr = GATT_FindNextAttr( pAttr, pReq->endHandle, service, &grpEndHandle );
  818. // Set Group End Handle
  819. if ( pRsp->handlesInfo[pRsp->numInfo].handle != 0 )
  820. {
  821. // If the attribute type is a grouping attribute, the Group End Handle
  822. // shall be defined by that higher layer specification. If the attribute
  823. // type is not a grouping attribute, the Group End Handle shall be equal
  824. // to the Found Attribute Handle.
  825. if ( pAttr != NULL )
  826. {
  827. pRsp->handlesInfo[pRsp->numInfo++].grpEndHandle = grpEndHandle;
  828. }
  829. else
  830. {
  831. // If no other attributes with the same attribute type exist after the
  832. // Found Attribute Handle, the Group End Handle shall be set to 0xFFFF.
  833. pRsp->handlesInfo[pRsp->numInfo++].grpEndHandle = GATT_MAX_HANDLE;
  834. }
  835. }
  836. } // while
  837. if ( pRsp->numInfo > 0 )
  838. {
  839. // Send a response back
  840. VOID ATT_FindByTypeValueRsp( pMsg->connHandle, pRsp );
  841. return ( SUCCESS );
  842. }
  843. *pErrHandle = pReq->startHandle;
  844. return ( ATT_ERR_ATTR_NOT_FOUND );
  845. }
  846. /*********************************************************************
  847. * @fn gattServApp_ProcessReadByTypeReq
  848. *
  849. * @brief Process Read By Type Request.
  850. *
  851. * @param pMsg - pointer to received message
  852. * @param pErrHandle - attribute handle that generates an error
  853. *
  854. * @return Success or Failure
  855. */
  856. static bStatus_t gattServApp_ProcessReadByTypeReq( gattMsgEvent_t *pMsg, uint16 *pErrHandle )
  857. {
  858. attReadByTypeReq_t *pReq = &pMsg->msg.readByTypeReq;
  859. attReadByTypeRsp_t *pRsp = &rsp.readByTypeRsp;
  860. uint16 startHandle = pReq->startHandle;
  861. uint8 dataLen = 0;
  862. uint8 status = SUCCESS;
  863. // Only the attributes with attribute handles between and including the
  864. // Starting Handle and the Ending Handle with the attribute type that is
  865. // the same as the Attribute Type given will be returned.
  866. // Make sure there's enough room at least for an attribute handle (no value)
  867. while ( dataLen <= (g_ATT_MTU_SIZE-4) )
  868. {
  869. uint16 service;
  870. gattAttribute_t *pAttr;
  871. // All attribute types are effectively compared as 128-bit UUIDs, even if
  872. // a 16-bit UUID is provided in this request or defined for an attribute.
  873. pAttr = GATT_FindHandleUUID( startHandle, pReq->endHandle, pReq->type.uuid,
  874. pReq->type.len, &service );
  875. if ( pAttr == NULL )
  876. {
  877. break; // No more attribute found
  878. }
  879. // Update start handle so it has the right value if we break from the loop
  880. startHandle = pAttr->handle;
  881. // Make sure the attribute has sufficient permissions to allow reading
  882. status = GATT_VerifyReadPermissions( pMsg->connHandle, pAttr->permissions );
  883. if ( status != SUCCESS )
  884. {
  885. break;
  886. }
  887. // Read the attribute value. If the attribute value is longer than
  888. // (ATT_MTU - 4) or 253 octets, whichever is smaller, then the first
  889. // (ATT_MTU - 4) or 253 octets shall be included in this response.
  890. status = GATTServApp_ReadAttr( pMsg->connHandle, pAttr, service, attrValue,
  891. &attrLen, 0, (g_ATT_MTU_SIZE-4) );
  892. if ( status != SUCCESS )
  893. {
  894. break; // Cannot read the attribute value
  895. }
  896. // See if this is the first attribute found
  897. if ( dataLen == 0 )
  898. {
  899. // Use the length of the first attribute value for the length field
  900. pRsp->len = 2 + attrLen;
  901. }
  902. else
  903. {
  904. // If the attributes have attribute values that have the same length
  905. // then these attributes can all be read in a single request.
  906. if ( pRsp->len != 2 + attrLen )
  907. {
  908. break;
  909. }
  910. }
  911. // Make sure there's enough room for this attribute handle and value
  912. if ( dataLen + attrLen > (g_ATT_MTU_SIZE-4) )
  913. {
  914. break;
  915. }
  916. // Add the handle value pair to the response
  917. pRsp->dataList[dataLen++] = LO_UINT16( pAttr->handle );
  918. pRsp->dataList[dataLen++] = HI_UINT16( pAttr->handle );
  919. VOID osal_memcpy( &(pRsp->dataList[dataLen]), attrValue, attrLen );
  920. dataLen += attrLen;
  921. if ( startHandle == GATT_MAX_HANDLE )
  922. {
  923. break; // We're done
  924. }
  925. // Update start handle and search again
  926. startHandle++;
  927. } // while
  928. // See what to respond
  929. if ( dataLen > 0 )
  930. {
  931. // Set the number of attribute handle-value pairs found
  932. pRsp->numPairs = dataLen / pRsp->len;
  933. // Send a response back
  934. VOID ATT_ReadByTypeRsp( pMsg->connHandle, pRsp );
  935. return ( SUCCESS );
  936. }
  937. if ( status == SUCCESS )
  938. {
  939. // Attribute not found -- dataLen must be 0
  940. status = ATT_ERR_ATTR_NOT_FOUND;
  941. }
  942. *pErrHandle = startHandle;
  943. return ( status );
  944. }
  945. /*********************************************************************
  946. * @fn gattServApp_ProcessReadReq
  947. *
  948. * @brief Process Read Request.
  949. *
  950. * @param pMsg - pointer to received message
  951. * @param pErrHandle - attribute handle that generates an error
  952. *
  953. * @return Success or Failure
  954. */
  955. static bStatus_t gattServApp_ProcessReadReq( gattMsgEvent_t *pMsg, uint16 *pErrHandle )
  956. {
  957. attReadReq_t *pReq = &pMsg->msg.readReq;
  958. gattAttribute_t *pAttr;
  959. uint16 service;
  960. uint8 status;
  961. pAttr = GATT_FindHandle( pReq->handle, &service );
  962. if ( pAttr != NULL )
  963. {
  964. attReadRsp_t *pRsp = &rsp.readRsp;
  965. // Build and send a response back. If the attribute value is longer
  966. // than (ATT_MTU - 1) then (ATT_MTU - 1) octets shall be included
  967. // in this response.
  968. status = GATTServApp_ReadAttr( pMsg->connHandle, pAttr, service, pRsp->value,
  969. &pRsp->len, 0, (g_ATT_MTU_SIZE-1) );
  970. if ( status == SUCCESS )
  971. {
  972. // Send a response back
  973. VOID ATT_ReadRsp( pMsg->connHandle, pRsp );
  974. }
  975. }
  976. else
  977. {
  978. status = ATT_ERR_INVALID_HANDLE;
  979. }
  980. if ( status != SUCCESS )
  981. {
  982. *pErrHandle = pReq->handle;
  983. }
  984. return ( status );
  985. }
  986. /*********************************************************************
  987. * @fn gattServApp_ProcessReadBlobReq
  988. *
  989. * @brief Process Read Blob Request.
  990. *
  991. * @param pMsg - pointer to received message
  992. * @param pErrHandle - attribute handle that generates an error
  993. *
  994. * @return Success or Failure
  995. */
  996. static bStatus_t gattServApp_ProcessReadBlobReq( gattMsgEvent_t *pMsg, uint16 *pErrHandle )
  997. {
  998. attReadBlobReq_t *pReq = &pMsg->msg.readBlobReq;
  999. gattAttribute_t *pAttr;
  1000. uint16 service;
  1001. uint8 status;
  1002. pAttr = GATT_FindHandle( pReq->handle, &service );
  1003. if ( pAttr != NULL )
  1004. {
  1005. attReadBlobRsp_t *pRsp = &rsp.readBlobRsp;
  1006. // Read part attribute value. If the attribute value is longer than
  1007. // (Value Offset + ATT_MTU - 1) then (ATT_MTU - 1) octets from Value
  1008. // Offset shall be included in this response.
  1009. status = GATTServApp_ReadAttr( pMsg->connHandle, pAttr, service, pRsp->value,
  1010. &pRsp->len, pReq->offset, (g_ATT_MTU_SIZE-1) );
  1011. if ( status == SUCCESS )
  1012. {
  1013. // Send a response back
  1014. VOID ATT_ReadBlobRsp( pMsg->connHandle, pRsp );
  1015. }
  1016. }
  1017. else
  1018. {
  1019. status = ATT_ERR_INVALID_HANDLE;
  1020. }
  1021. if ( status != SUCCESS )
  1022. {
  1023. *pErrHandle = pReq->handle;
  1024. }
  1025. return ( status );
  1026. }
  1027. /*********************************************************************
  1028. * @fn gattServApp_ProcessReadMultiReq
  1029. *
  1030. * @brief Process Read Multiple Request.
  1031. *
  1032. * @param pMsg - pointer to received message
  1033. * @param pErrHandle - attribute handle that generates an error
  1034. *
  1035. * @return Success or Failure
  1036. */
  1037. static bStatus_t gattServApp_ProcessReadMultiReq( gattMsgEvent_t *pMsg, uint16 *pErrHandle )
  1038. {
  1039. attReadMultiReq_t *pReq = &pMsg->msg.readMultiReq;
  1040. attReadMultiRsp_t *pRsp = &rsp.readMultiRsp;
  1041. uint8 status = SUCCESS;
  1042. // Set the response length
  1043. pRsp->len = 0;
  1044. for ( uint8 i = 0; ( i < pReq->numHandles ) && ( pRsp->len < (g_ATT_MTU_SIZE-1) ); i++ )
  1045. {
  1046. gattAttribute_t *pAttr;
  1047. uint16 service;
  1048. pAttr = GATT_FindHandle( pReq->handle[i], &service );
  1049. if ( pAttr == NULL )
  1050. {
  1051. // Should never get here!
  1052. status = ATT_ERR_INVALID_HANDLE;
  1053. // The handle of the first attribute causing the error
  1054. *pErrHandle = pReq->handle[i];
  1055. break;
  1056. }
  1057. // If the Set Of Values parameter is longer than (ATT_MTU - 1) then only
  1058. // the first (ATT_MTU - 1) octets shall be included in this response.
  1059. status = GATTServApp_ReadAttr( pMsg->connHandle, pAttr, service, attrValue,
  1060. &attrLen, 0, (g_ATT_MTU_SIZE-1) );
  1061. if ( status != SUCCESS )
  1062. {
  1063. // The handle of the first attribute causing the error
  1064. *pErrHandle = pReq->handle[i];
  1065. break;
  1066. }
  1067. // Make sure there's enough room in the response for this attribute value
  1068. if ( pRsp->len + attrLen > (g_ATT_MTU_SIZE-1) )
  1069. {
  1070. attrLen = (g_ATT_MTU_SIZE-1) - pRsp->len;
  1071. }
  1072. // Append this value to the end of the response
  1073. VOID osal_memcpy( &(pRsp->values[pRsp->len]), attrValue, attrLen );
  1074. pRsp->len += attrLen;
  1075. }
  1076. if ( status == SUCCESS )
  1077. {
  1078. // Send a response back
  1079. VOID ATT_ReadMultiRsp( pMsg->connHandle, pRsp );
  1080. }
  1081. return ( status );
  1082. }
  1083. /*********************************************************************
  1084. * @fn gattServApp_ProcessReadByGrpTypeReq
  1085. *
  1086. * @brief Process Read By Group Type Request.
  1087. *
  1088. * @param pMsg - pointer to received message
  1089. * @param pErrHandle - attribute handle that generates an error
  1090. *
  1091. * @return Success or Failure
  1092. */
  1093. static bStatus_t gattServApp_ProcessReadByGrpTypeReq( gattMsgEvent_t *pMsg, uint16 *pErrHandle )
  1094. {
  1095. attReadByGrpTypeReq_t *pReq = &pMsg->msg.readByGrpTypeReq;
  1096. attReadByGrpTypeRsp_t *pRsp = &rsp.readByGrpTypeRsp;
  1097. uint16 service;
  1098. gattAttribute_t *pAttr;
  1099. uint8 dataLen = 0;
  1100. uint8 status = SUCCESS;
  1101. // Only the attributes with attribute handles between and including the
  1102. // Starting Handle and the Ending Handle with the attribute type that is
  1103. // the same as the Attribute Type given will be returned.
  1104. // All attribute types are effectively compared as 128-bit UUIDs,
  1105. // even if a 16-bit UUID is provided in this request or defined
  1106. // for an attribute.
  1107. pAttr = GATT_FindHandleUUID( pReq->startHandle, pReq->endHandle,
  1108. pReq->type.uuid, pReq->type.len, &service );
  1109. while ( pAttr != NULL )
  1110. {
  1111. uint16 endGrpHandle;
  1112. // The service, include and characteristic declarations are readable and
  1113. // require no authentication or authorization, therefore insufficient
  1114. // authentication or read not permitted errors shall not occur.
  1115. status = GATT_VerifyReadPermissions( pMsg->connHandle, pAttr->permissions );
  1116. if ( status != SUCCESS )
  1117. {
  1118. *pErrHandle = pAttr->handle;
  1119. break;
  1120. }
  1121. // Read the attribute value. If the attribute value is longer than
  1122. // (ATT_MTU - 6) or 251 octets, whichever is smaller, then the first
  1123. // (ATT_MTU - 6) or 251 octets shall be included in this response.
  1124. status = GATTServApp_ReadAttr( pMsg->connHandle, pAttr, service, attrValue,
  1125. &attrLen, 0, (g_ATT_MTU_SIZE-6) );
  1126. if ( status != SUCCESS )
  1127. {
  1128. // Cannot read the attribute value
  1129. *pErrHandle = pAttr->handle;
  1130. break;
  1131. }
  1132. // See if this is the first attribute found
  1133. if ( dataLen == 0 )
  1134. {
  1135. // Use the length of the first attribute value for the length field
  1136. pRsp->len = 2 + 2 + attrLen;
  1137. }
  1138. else
  1139. {
  1140. // If the attributes have attribute values that have the same length
  1141. // then these attributes can all be read in a single request.
  1142. if ( pRsp->len != 2 + 2 + attrLen )
  1143. {
  1144. break; // We're done here
  1145. }
  1146. // Make sure there's enough room for this attribute handle, end group handle and value
  1147. if ( dataLen + attrLen > (g_ATT_MTU_SIZE-6) )
  1148. {
  1149. break; // We're done here
  1150. }
  1151. }
  1152. // Add Attribute Handle to the response
  1153. pRsp->dataList[dataLen++] = LO_UINT16( pAttr->handle );
  1154. pRsp->dataList[dataLen++] = HI_UINT16( pAttr->handle );
  1155. // Try to find the next attribute
  1156. pAttr = GATT_FindNextAttr( pAttr, pReq->endHandle, service, &endGrpHandle );
  1157. // Add End Group Handle to the response
  1158. if ( pAttr != NULL )
  1159. {
  1160. // The End Group Handle is the handle of the last attribute within the
  1161. // service definition
  1162. pRsp->dataList[dataLen++] = LO_UINT16( endGrpHandle );
  1163. pRsp->dataList[dataLen++] = HI_UINT16( endGrpHandle );
  1164. }
  1165. else
  1166. {
  1167. // The ending handle of the last service can be 0xFFFF
  1168. pRsp->dataList[dataLen++] = LO_UINT16( GATT_MAX_HANDLE );
  1169. pRsp->dataList[dataLen++] = HI_UINT16( GATT_MAX_HANDLE );
  1170. }
  1171. // Add Attribute Value to the response
  1172. VOID osal_memcpy( &(pRsp->dataList[dataLen]), attrValue, attrLen );
  1173. dataLen += attrLen;
  1174. } // while
  1175. // See what to respond
  1176. if ( dataLen > 0 )
  1177. {
  1178. // Set the number of attribute handle, end group handle and value sets found
  1179. pRsp->numGrps = dataLen / pRsp->len;
  1180. // Send a response back
  1181. VOID ATT_ReadByGrpTypeRsp( pMsg->connHandle, pRsp );
  1182. return ( SUCCESS );
  1183. }
  1184. if ( status == SUCCESS )
  1185. {
  1186. // No grouping attribute found -- dataLen must be 0
  1187. status = ATT_ERR_ATTR_NOT_FOUND;
  1188. }
  1189. *pErrHandle = pReq->startHandle;
  1190. return ( status );
  1191. }
  1192. /*********************************************************************
  1193. * @fn gattServApp_ProcessWriteReq
  1194. *
  1195. * @brief Process Write Request or Command.
  1196. *
  1197. * @param pMsg - pointer to received message
  1198. * @param pErrHandle - attribute handle that generates an error
  1199. *
  1200. * @return Success or Failure
  1201. */
  1202. static bStatus_t gattServApp_ProcessWriteReq( gattMsgEvent_t *pMsg, uint16 *pErrHandle )
  1203. {
  1204. attWriteReq_t *pReq = &(pMsg->msg.writeReq);
  1205. gattAttribute_t *pAttr;
  1206. uint16 service;
  1207. uint8 status = SUCCESS;
  1208. // No Error Response or Write Response shall be sent in response to Write
  1209. // Command. If the server cannot write this attribute for any reason the
  1210. // command shall be ignored.
  1211. pAttr = GATT_FindHandle( pReq->handle, &service );
  1212. if ( pAttr != NULL )
  1213. {
  1214. // Authorization is handled by the application/profile
  1215. if ( gattPermitAuthorWrite( pAttr->permissions ) )
  1216. {
  1217. // Use Service's authorization callback to authorize the request
  1218. pfnGATTAuthorizeAttrCB_t pfnCB = gattServApp_FindAuthorizeAttrCB( service );
  1219. if ( pfnCB != NULL )
  1220. {
  1221. status = (*pfnCB)( pMsg->connHandle, pAttr, ATT_WRITE_REQ );
  1222. }
  1223. else
  1224. {
  1225. status = ATT_ERR_UNLIKELY;
  1226. }
  1227. }
  1228. // If everything is fine then try to write the new value
  1229. if ( status == SUCCESS )
  1230. {
  1231. // Use Service's write callback to write the request
  1232. status = GATTServApp_WriteAttr( pMsg->connHandle, pReq->handle,
  1233. pReq->value, pReq->len, 0 );
  1234. if ( ( status == SUCCESS ) && ( pReq->cmd == FALSE ) )
  1235. {
  1236. // Send a response back
  1237. //VOID ATT_WriteRsp( pMsg->connHandle );
  1238. uint8 st=ATT_WriteRsp( pMsg->connHandle );
  1239. // if(st)
  1240. // {
  1241. // AT_LOG("[ATT_RSP ERR] %x %x\n",st,l2capSegmentPkt.fragment);
  1242. // }
  1243. }
  1244. }
  1245. }
  1246. else
  1247. {
  1248. status = ATT_ERR_INVALID_HANDLE;
  1249. }
  1250. if ( status != SUCCESS )
  1251. {
  1252. *pErrHandle = pReq->handle;
  1253. }
  1254. return ( pReq->cmd ? SUCCESS : status );
  1255. }
  1256. /*********************************************************************
  1257. * @fn gattServApp_ProcessPrepareWriteReq
  1258. *
  1259. * @brief Process Prepare Write Request.
  1260. *
  1261. * @param pMsg - pointer to received message
  1262. * @param pErrHandle - attribute handle that generates an error
  1263. *
  1264. * @return Success or Failure
  1265. */
  1266. static bStatus_t gattServApp_ProcessPrepareWriteReq( gattMsgEvent_t *pMsg, uint16 *pErrHandle )
  1267. {
  1268. attPrepareWriteReq_t *pReq = &pMsg->msg.prepareWriteReq;
  1269. gattAttribute_t *pAttr;
  1270. uint16 service;
  1271. uint8 status = SUCCESS;
  1272. pAttr = GATT_FindHandle( pReq->handle, &service );
  1273. if ( pAttr != NULL )
  1274. {
  1275. // Authorization is handled by the application/profile
  1276. if ( gattPermitAuthorWrite( pAttr->permissions ) )
  1277. {
  1278. // Use Service's authorization callback to authorize the request
  1279. pfnGATTAuthorizeAttrCB_t pfnCB = gattServApp_FindAuthorizeAttrCB( service );
  1280. if ( pfnCB != NULL )
  1281. {
  1282. status = (*pfnCB)( pMsg->connHandle, pAttr, ATT_WRITE_REQ );
  1283. }
  1284. else
  1285. {
  1286. status = ATT_ERR_UNLIKELY;
  1287. }
  1288. }
  1289. if ( status == SUCCESS )
  1290. {
  1291. #if defined ( TESTMODES )
  1292. if ( paramValue == GATT_TESTMODE_CORRUPT_PW_DATA )
  1293. {
  1294. pReq->value[0] = ~(pReq->value[0]);
  1295. }
  1296. #endif
  1297. // Enqueue the request for now
  1298. status = gattServApp_EnqueuePrepareWriteReq( pMsg->connHandle, pReq );
  1299. if ( status == SUCCESS )
  1300. {
  1301. //LOG("pre off[%d] len[%d]\n", pReq->offset, pReq->len);
  1302. // Send a response back
  1303. VOID ATT_PrepareWriteRsp( pMsg->connHandle, (attPrepareWriteRsp_t *)pReq );
  1304. }
  1305. }
  1306. }
  1307. else
  1308. {
  1309. status = ATT_ERR_INVALID_HANDLE;
  1310. }
  1311. if ( status != SUCCESS )
  1312. {
  1313. *pErrHandle = pReq->handle;
  1314. }
  1315. return ( status );
  1316. }
  1317. /*********************************************************************
  1318. * @fn gattServApp_ProcessExecuteWriteReq
  1319. *
  1320. * @brief Process Execute Write Request.
  1321. *
  1322. * @param pMsg - pointer to received message
  1323. * @param pErrHandle - attribute handle that generates an error
  1324. *
  1325. * @return Success or Failure
  1326. */
  1327. static bStatus_t gattServApp_ProcessExecuteWriteReq( gattMsgEvent_t *pMsg, uint16 *pErrHandle )
  1328. {
  1329. attExecuteWriteReq_t *pReq = &pMsg->msg.executeWriteReq;
  1330. prepareWrites_t *pQueue;
  1331. uint8 status = SUCCESS;
  1332. // See if this client has a prepare write queue
  1333. pQueue = gattServApp_FindPrepareWriteQ( pMsg->connHandle );
  1334. if ( pQueue != NULL )
  1335. {
  1336. for ( uint8 i = 0; i < maxNumPrepareWrites; i++ )
  1337. {
  1338. attPrepareWriteReq_t *pWriteReq = &(pQueue->pPrepareWriteQ[i]);
  1339. // See if there're any prepared write requests in the queue
  1340. if ( pWriteReq->handle == GATT_INVALID_HANDLE )
  1341. {
  1342. break; // We're done
  1343. }
  1344. // Execute the request
  1345. if ( pReq->flags == ATT_WRITE_PREPARED_VALUES )
  1346. {
  1347. status = GATTServApp_WriteAttr( pMsg->connHandle, pWriteReq->handle,
  1348. pWriteReq->value, pWriteReq->len,
  1349. pWriteReq->offset );
  1350. //LOG("exe off[%d]len[%d]", pWriteReq->offset, pWriteReq->len);
  1351. // If the prepare write requests can not be written, the queue shall
  1352. // be cleared and then an Error Response shall be sent with a high
  1353. // layer defined error code.
  1354. if ( status != SUCCESS )
  1355. {
  1356. // Cancel the remaining prepared writes
  1357. pReq->flags = ATT_CANCEL_PREPARED_WRITES;
  1358. // The Attribute Handle in Error shall be set to the attribute handle
  1359. // of the attribute from the prepare write queue that caused this
  1360. // application error
  1361. *pErrHandle = pWriteReq->handle;
  1362. }
  1363. }
  1364. else // ATT_CANCEL_PREPARED_WRITES
  1365. {
  1366. // Cancel all prepared writes - just ignore the request
  1367. }
  1368. // Clear the queue item
  1369. VOID osal_memset( pWriteReq, 0, sizeof( attPrepareWriteRsp_t ) );
  1370. // Mark this item as empty
  1371. pWriteReq->handle = GATT_INVALID_HANDLE;
  1372. } // for loop
  1373. // Mark this queue as empty
  1374. pQueue->connHandle = INVALID_CONNHANDLE;
  1375. }
  1376. // Send a response back
  1377. if ( status == SUCCESS )
  1378. {
  1379. VOID ATT_ExecuteWriteRsp( pMsg->connHandle );
  1380. }
  1381. return ( status );
  1382. }
  1383. /*********************************************************************
  1384. * @fn gattServApp_EnqueuePrepareWriteReq
  1385. *
  1386. * @brief Enqueue Prepare Write Request.
  1387. *
  1388. * @param connHandle - connection packet was received on
  1389. * @param pReq - pointer to request
  1390. *
  1391. * @return Success or Failure
  1392. */
  1393. static bStatus_t gattServApp_EnqueuePrepareWriteReq( uint16 connHandle, attPrepareWriteReq_t *pReq )
  1394. {
  1395. prepareWrites_t *pQueue;
  1396. // First see if there's queue already assocaited with this client
  1397. pQueue = gattServApp_FindPrepareWriteQ( connHandle );
  1398. if ( pQueue == NULL )
  1399. {
  1400. // Find a queue for this client
  1401. pQueue = gattServApp_FindPrepareWriteQ( INVALID_CONNHANDLE );
  1402. if ( pQueue != NULL )
  1403. {
  1404. pQueue->connHandle = connHandle;
  1405. }
  1406. }
  1407. // If a queue is found for this client then enqueue the request
  1408. if ( pQueue != NULL )
  1409. {
  1410. for ( uint8 i = 0; i < maxNumPrepareWrites; i++ )
  1411. {
  1412. if ( pQueue->pPrepareWriteQ[i].handle == GATT_INVALID_HANDLE )
  1413. {
  1414. // Store the request here
  1415. VOID osal_memcpy( &(pQueue->pPrepareWriteQ[i]), pReq, sizeof ( attPrepareWriteReq_t ) );
  1416. //LOG("enq off[%d]len[%d]\n", pReq->offset, pReq->len);
  1417. return ( SUCCESS );
  1418. }
  1419. }
  1420. }
  1421. return ( ATT_ERR_PREPARE_QUEUE_FULL );
  1422. }
  1423. /*********************************************************************
  1424. * @fn gattServApp_FindPrepareWriteQ
  1425. *
  1426. * @brief Find client's queue.
  1427. *
  1428. * @param connHandle - connection used by client
  1429. *
  1430. * @return Pointer to queue. NULL, otherwise.
  1431. */
  1432. static prepareWrites_t *gattServApp_FindPrepareWriteQ( uint16 connHandle )
  1433. {
  1434. // First see if this client has already a queue
  1435. for ( uint8 i = 0; i < MAX_NUM_LL_CONN; i++ )
  1436. {
  1437. if ( prepareWritesTbl[i].connHandle == connHandle )
  1438. {
  1439. // Queue found
  1440. return ( &(prepareWritesTbl[i]) );
  1441. }
  1442. }
  1443. return ( (prepareWrites_t *)NULL );
  1444. }
  1445. /*********************************************************************
  1446. * @fn gattServApp_PrepareWriteQInUse
  1447. *
  1448. * @brief Check to see if the prepare write queue is in use.
  1449. *
  1450. * @param void
  1451. *
  1452. * @return TRUE if queue in use. FALSE, otherwise.
  1453. */
  1454. static uint8 gattServApp_PrepareWriteQInUse( void )
  1455. {
  1456. // See if any prepare write queue is in use
  1457. for ( uint8 i = 0; i < MAX_NUM_LL_CONN; i++ )
  1458. {
  1459. if ( prepareWritesTbl[i].connHandle != INVALID_CONNHANDLE )
  1460. {
  1461. for ( uint8 j = 0; j < maxNumPrepareWrites; j++ )
  1462. {
  1463. if ( prepareWritesTbl[i].pPrepareWriteQ[j].handle != GATT_INVALID_HANDLE )
  1464. {
  1465. // Queue item is in use
  1466. return ( TRUE );
  1467. }
  1468. } // for
  1469. }
  1470. } // for
  1471. return ( FALSE );
  1472. }
  1473. /*********************************************************************
  1474. * @fn gattServApp_FindCharCfgItem
  1475. *
  1476. * @brief Find the characteristic configuration for a given client.
  1477. * Uses the connection handle to search the charactersitic
  1478. * configuration table of a client.
  1479. *
  1480. * @param connHandle - connection handle (0xFFFF for empty entry)
  1481. * @param charCfgTbl - characteristic configuration table.
  1482. *
  1483. * @return pointer to the found item. NULL, otherwise.
  1484. */
  1485. static gattCharCfg_t *gattServApp_FindCharCfgItem( uint16 connHandle,
  1486. gattCharCfg_t *charCfgTbl )
  1487. {
  1488. for ( uint8 i = 0; i < GATT_MAX_NUM_CONN; i++ )
  1489. {
  1490. if ( charCfgTbl[i].connHandle == connHandle )
  1491. {
  1492. // Entry found
  1493. return ( &(charCfgTbl[i]) );
  1494. }
  1495. }
  1496. return ( (gattCharCfg_t *)NULL );
  1497. }
  1498. /*********************************************************************
  1499. * @fn gattServApp_FindReadAttrCB
  1500. *
  1501. * @brief Find the Read Attribute CB function pointer for a given service.
  1502. *
  1503. * @param handle - service attribute handle
  1504. *
  1505. * @return pointer to the found CB. NULL, otherwise.
  1506. */
  1507. static pfnGATTReadAttrCB_t gattServApp_FindReadAttrCB( uint16 handle )
  1508. {
  1509. CONST gattServiceCBs_t *pCBs = gattServApp_FindServiceCBs( handle );
  1510. return ( ( pCBs == NULL ) ? NULL : pCBs->pfnReadAttrCB );
  1511. }
  1512. /*********************************************************************
  1513. * @fn gattServApp_FindWriteAttrCB
  1514. *
  1515. * @brief Find the Write CB Attribute function pointer for a given service.
  1516. *
  1517. * @param handle - service attribute handle
  1518. *
  1519. * @return pointer to the found CB. NULL, otherwise.
  1520. */
  1521. static pfnGATTWriteAttrCB_t gattServApp_FindWriteAttrCB( uint16 handle )
  1522. {
  1523. CONST gattServiceCBs_t *pCBs = gattServApp_FindServiceCBs( handle );
  1524. return ( ( pCBs == NULL ) ? NULL : pCBs->pfnWriteAttrCB );
  1525. }
  1526. /*********************************************************************
  1527. * @fn gattServApp_FindAuthorizeAttrCB
  1528. *
  1529. * @brief Find the Authorize Attribute CB function pointer for a given service.
  1530. *
  1531. * @param handle - service attribute handle
  1532. *
  1533. * @return pointer to the found CB. NULL, otherwise.
  1534. */
  1535. static pfnGATTAuthorizeAttrCB_t gattServApp_FindAuthorizeAttrCB( uint16 handle )
  1536. {
  1537. CONST gattServiceCBs_t *pCBs = gattServApp_FindServiceCBs( handle );
  1538. return ( ( pCBs == NULL ) ? NULL : pCBs->pfnAuthorizeAttrCB );
  1539. }
  1540. /*********************************************************************
  1541. * @fn gattServApp_ValidateWriteAttrCB
  1542. *
  1543. * @brief Validate and/or Write attribute data
  1544. *
  1545. * @param connHandle - connection message was received on
  1546. * @param pAttr - pointer to attribute
  1547. * @param pValue - pointer to data to be written
  1548. * @param len - length of data
  1549. * @param offset - offset of the first octet to be written
  1550. *
  1551. * @return Success or Failure
  1552. */
  1553. static bStatus_t gattServApp_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
  1554. uint8 *pValue, uint8 len, uint16 offset )
  1555. {
  1556. bStatus_t status = SUCCESS;
  1557. if ( pAttr->type.len == ATT_BT_UUID_SIZE )
  1558. {
  1559. // 16-bit UUID
  1560. uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
  1561. switch ( uuid )
  1562. {
  1563. case GATT_CLIENT_CHAR_CFG_UUID:
  1564. status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len,
  1565. offset, GATT_CLIENT_CFG_INDICATE );
  1566. break;
  1567. default:
  1568. // Should never get here!
  1569. status = ATT_ERR_INVALID_HANDLE;
  1570. }
  1571. }
  1572. else
  1573. {
  1574. // 128-bit UUID
  1575. status = ATT_ERR_INVALID_HANDLE;
  1576. }
  1577. return ( status );
  1578. }
  1579. /*********************************************************************
  1580. * @fn GATTServApp_ReadAttr
  1581. *
  1582. * @brief Read an attribute. If the format of the attribute value
  1583. * is unknown to GATT Server, use the callback function
  1584. * provided by the Service.
  1585. *
  1586. * @param connHandle - connection message was received on
  1587. * @param pAttr - pointer to attribute
  1588. * @param service - handle of owner service
  1589. * @param pValue - pointer to data to be read
  1590. * @param pLen - length of data to be read
  1591. * @param offset - offset of the first octet to be read
  1592. * @param maxLen - maximum length of data to be read
  1593. *
  1594. * @return Success or Failure
  1595. */
  1596. uint8 GATTServApp_ReadAttr( uint16 connHandle, gattAttribute_t *pAttr,
  1597. uint16 service, uint8 *pValue, uint8 *pLen,
  1598. uint16 offset, uint8 maxLen )
  1599. {
  1600. uint8 useCB = FALSE;
  1601. bStatus_t status = SUCCESS;
  1602. // Authorization is handled by the application/profile
  1603. if ( gattPermitAuthorRead( pAttr->permissions ) )
  1604. {
  1605. // Use Service's authorization callback to authorize the request
  1606. pfnGATTAuthorizeAttrCB_t pfnCB = gattServApp_FindAuthorizeAttrCB( service );
  1607. if ( pfnCB != NULL )
  1608. {
  1609. status = (*pfnCB)( connHandle, pAttr, ATT_READ_REQ );
  1610. }
  1611. else
  1612. {
  1613. status = ATT_ERR_UNLIKELY;
  1614. }
  1615. if ( status != SUCCESS )
  1616. {
  1617. // Read operation failed!
  1618. return ( status );
  1619. }
  1620. }
  1621. // Check the UUID length
  1622. if ( pAttr->type.len == ATT_BT_UUID_SIZE )
  1623. {
  1624. // 16-bit UUID
  1625. uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
  1626. switch ( uuid )
  1627. {
  1628. case GATT_PRIMARY_SERVICE_UUID:
  1629. case GATT_SECONDARY_SERVICE_UUID:
  1630. // Make sure it's not a blob operation
  1631. if ( offset == 0 )
  1632. {
  1633. gattAttrType_t *pType = (gattAttrType_t *)(pAttr->pValue);
  1634. *pLen = pType->len;
  1635. VOID osal_memcpy( pValue, pType->uuid, pType->len );
  1636. }
  1637. else
  1638. {
  1639. status = ATT_ERR_ATTR_NOT_LONG;
  1640. }
  1641. break;
  1642. case GATT_CHARACTER_UUID:
  1643. // Make sure it's not a blob operation
  1644. if ( offset == 0 )
  1645. {
  1646. gattAttribute_t *pCharValue;
  1647. // The Attribute Value of a Characteristic Declaration includes the
  1648. // Characteristic Properties, Characteristic Value Attribute Handle
  1649. // and UUID.
  1650. *pLen = 1;
  1651. pValue[0] = *pAttr->pValue; // Properties
  1652. // The Characteristic Value Attribute exists immediately following
  1653. // the Characteristic Declaration.
  1654. pCharValue = GATT_FindHandle( pAttr->handle+1, NULL );
  1655. if ( pCharValue != NULL )
  1656. {
  1657. // It can be a 128-bit UUID
  1658. *pLen += (2 + pCharValue->type.len);
  1659. // Attribute Handle
  1660. pValue[1] = LO_UINT16( pCharValue->handle );
  1661. pValue[2] = HI_UINT16( pCharValue->handle );
  1662. // Attribute UUID
  1663. VOID osal_memcpy( &(pValue[3]), pCharValue->type.uuid, pCharValue->type.len );
  1664. }
  1665. else
  1666. {
  1667. // Should never get here!
  1668. *pLen += (2 + ATT_BT_UUID_SIZE);
  1669. // Set both Attribute Handle and UUID to 0
  1670. VOID osal_memset( &(pValue[1]), 0, (2 + ATT_BT_UUID_SIZE) );
  1671. }
  1672. }
  1673. else
  1674. {
  1675. status = ATT_ERR_ATTR_NOT_LONG;
  1676. }
  1677. break;
  1678. case GATT_INCLUDE_UUID:
  1679. // Make sure it's not a blob operation
  1680. if ( offset == 0 )
  1681. {
  1682. uint16 servHandle;
  1683. uint16 endGrpHandle;
  1684. gattAttribute_t *pIncluded;
  1685. uint16 handle = *((uint16 *)(pAttr->pValue));
  1686. // The Attribute Value of an Include Declaration is set the
  1687. // included service Attribute Handle, the End Group Handle,
  1688. // and the service UUID. The Service UUID shall only be present
  1689. // when the UUID is a 16-bit Bluetooth UUID.
  1690. *pLen = 4;
  1691. pValue[0] = LO_UINT16( handle );
  1692. pValue[1] = HI_UINT16( handle );
  1693. // Find the included service attribute record
  1694. pIncluded = GATT_FindHandle( handle, &servHandle );
  1695. if ( pIncluded != NULL )
  1696. {
  1697. gattAttrType_t *pServiceUUID = (gattAttrType_t *)pIncluded->pValue;
  1698. // Find out the End Group handle
  1699. if ( ( GATT_FindNextAttr( pIncluded, GATT_MAX_HANDLE,
  1700. servHandle, &endGrpHandle ) == NULL ) &&
  1701. ( !gattSecondaryServiceType( pIncluded->type ) ) )
  1702. {
  1703. // The ending handle of the last service can be 0xFFFF
  1704. endGrpHandle = GATT_MAX_HANDLE;
  1705. }
  1706. // Include only 16-bit Service UUID
  1707. if ( pServiceUUID->len == ATT_BT_UUID_SIZE )
  1708. {
  1709. VOID osal_memcpy( &(pValue[4]), pServiceUUID->uuid, ATT_BT_UUID_SIZE );
  1710. *pLen += ATT_BT_UUID_SIZE;
  1711. }
  1712. }
  1713. else
  1714. {
  1715. // Should never get here!
  1716. endGrpHandle = handle;
  1717. }
  1718. // End Group Handle
  1719. pValue[2] = LO_UINT16( endGrpHandle );
  1720. pValue[3] = HI_UINT16( endGrpHandle );
  1721. }
  1722. else
  1723. {
  1724. status = ATT_ERR_ATTR_NOT_LONG;
  1725. }
  1726. break;
  1727. case GATT_CLIENT_CHAR_CFG_UUID:
  1728. // Make sure it's not a blob operation
  1729. if ( offset == 0 )
  1730. {
  1731. uint16 value = GATTServApp_ReadCharCfg( connHandle,
  1732. (gattCharCfg_t *)(pAttr->pValue) );
  1733. *pLen = 2;
  1734. pValue[0] = LO_UINT16( value );
  1735. pValue[1] = HI_UINT16( value );
  1736. }
  1737. else
  1738. {
  1739. status = ATT_ERR_ATTR_NOT_LONG;
  1740. }
  1741. break;
  1742. case GATT_CHAR_EXT_PROPS_UUID:
  1743. case GATT_SERV_CHAR_CFG_UUID:
  1744. // Make sure it's not a blob operation
  1745. if ( offset == 0 )
  1746. {
  1747. uint16 value = *((uint16 *)(pAttr->pValue));
  1748. *pLen = 2;
  1749. pValue[0] = LO_UINT16( value );
  1750. pValue[1] = HI_UINT16( value );
  1751. }
  1752. else
  1753. {
  1754. status = ATT_ERR_ATTR_NOT_LONG;
  1755. }
  1756. break;
  1757. case GATT_CHAR_USER_DESC_UUID:
  1758. {
  1759. uint8 len = osal_strlen( (char *)(pAttr->pValue) ); // Could be a long attribute
  1760. // If the value offset of the Read Blob Request is greater than the
  1761. // length of the attribute value, an Error Response shall be sent with
  1762. // the error code Invalid Offset.
  1763. if ( offset <= len )
  1764. {
  1765. // If the value offset is equal than the length of the attribute
  1766. // value, then the length of the part attribute value shall be zero.
  1767. if ( offset == len )
  1768. {
  1769. len = 0;
  1770. }
  1771. else
  1772. {
  1773. // If the attribute value is longer than (Value Offset + maxLen)
  1774. // then maxLen octets from Value Offset shall be included in
  1775. // this response.
  1776. if ( len > ( offset + maxLen ) )
  1777. {
  1778. len = maxLen;
  1779. }
  1780. else
  1781. {
  1782. len -= offset;
  1783. }
  1784. }
  1785. *pLen = len;
  1786. VOID osal_memcpy( pValue, &(pAttr->pValue[offset]), len );
  1787. }
  1788. else
  1789. {
  1790. status = ATT_ERR_INVALID_OFFSET;
  1791. }
  1792. }
  1793. break;
  1794. case GATT_CHAR_FORMAT_UUID:
  1795. // Make sure it's not a blob operation
  1796. if ( offset == 0 )
  1797. {
  1798. gattCharFormat_t *pFormat = (gattCharFormat_t *)(pAttr->pValue);
  1799. *pLen = 7;
  1800. pValue[0] = pFormat->format;
  1801. pValue[1] = pFormat->exponent;
  1802. pValue[2] = LO_UINT16( pFormat->unit );
  1803. pValue[3] = HI_UINT16( pFormat->unit );
  1804. pValue[4] = pFormat->nameSpace;
  1805. pValue[5] = LO_UINT16( pFormat->desc );
  1806. pValue[6] = HI_UINT16( pFormat->desc );
  1807. }
  1808. else
  1809. {
  1810. status = ATT_ERR_ATTR_NOT_LONG;
  1811. }
  1812. break;
  1813. default:
  1814. useCB = TRUE;
  1815. break;
  1816. }
  1817. }
  1818. else
  1819. {
  1820. useCB = TRUE;
  1821. }
  1822. if ( useCB == TRUE )
  1823. {
  1824. // Use Service's read callback to process the request
  1825. pfnGATTReadAttrCB_t pfnCB = gattServApp_FindReadAttrCB( service );
  1826. if ( pfnCB != NULL )
  1827. {
  1828. // Read the attribute value
  1829. status = (*pfnCB)( connHandle, pAttr, pValue, pLen, offset, maxLen );
  1830. }
  1831. else
  1832. {
  1833. status = ATT_ERR_UNLIKELY;
  1834. }
  1835. }
  1836. return ( status );
  1837. }
  1838. /*********************************************************************
  1839. * @fn GATTServApp_WriteAttr
  1840. *
  1841. * @brief Write attribute data
  1842. *
  1843. * @param connHandle - connection message was received on
  1844. * @param handle - attribute handle
  1845. * @param pValue - pointer to data to be written
  1846. * @param len - length of data
  1847. * @param offset - offset of the first octet to be written
  1848. *
  1849. * @return Success or Failure
  1850. */
  1851. uint8 GATTServApp_WriteAttr( uint16 connHandle, uint16 handle,
  1852. uint8 *pValue, uint16 len, uint16 offset )
  1853. {
  1854. uint16 service;
  1855. gattAttribute_t *pAttr;
  1856. bStatus_t status;
  1857. // Find the owner of the attribute
  1858. pAttr = GATT_FindHandle( handle, &service );
  1859. if ( pAttr != NULL )
  1860. {
  1861. // Find out the owner's callback functions
  1862. pfnGATTWriteAttrCB_t pfnCB = gattServApp_FindWriteAttrCB( service );
  1863. if ( pfnCB != NULL )
  1864. {
  1865. // Try to write the new value
  1866. status = (*pfnCB)( connHandle, pAttr, pValue, len, offset );
  1867. }
  1868. else
  1869. {
  1870. status = ATT_ERR_UNLIKELY;
  1871. }
  1872. }
  1873. else
  1874. {
  1875. status = ATT_ERR_INVALID_HANDLE;
  1876. }
  1877. return ( status );
  1878. }
  1879. /*********************************************************************
  1880. * @fn GATTServApp_SetParamValue
  1881. *
  1882. * @brief Set a GATT Server Application Parameter value. Use this
  1883. * function to change the default GATT parameter values.
  1884. *
  1885. * @param value - new param value
  1886. *
  1887. * @return void
  1888. */
  1889. void GATTServApp_SetParamValue( uint16 value )
  1890. {
  1891. #if defined ( TESTMODES )
  1892. paramValue = value;
  1893. #else
  1894. VOID value;
  1895. #endif
  1896. }
  1897. /*********************************************************************
  1898. * @fn GATTServApp_GetParamValue
  1899. *
  1900. * @brief Get a GATT Server Application Parameter value.
  1901. *
  1902. * @param none
  1903. *
  1904. * @return GATT Parameter value
  1905. */
  1906. uint16 GATTServApp_GetParamValue( void )
  1907. {
  1908. #if defined ( TESTMODES )
  1909. return ( paramValue );
  1910. #else
  1911. return ( 0 );
  1912. #endif
  1913. }
  1914. /*********************************************************************
  1915. * @fn GATTServApp_UpdateCharCfg
  1916. *
  1917. * @brief Update the Client Characteristic Configuration for a given
  1918. * Client.
  1919. *
  1920. * Note: This API should only be called from the Bond Manager.
  1921. *
  1922. * @param connHandle - connection handle.
  1923. * @param attrHandle - attribute handle.
  1924. * @param value - characteristic configuration value (from NV).
  1925. *
  1926. * @return Success or Failure
  1927. */
  1928. bStatus_t GATTServApp_UpdateCharCfg( uint16 connHandle, uint16 attrHandle, uint16 value )
  1929. {
  1930. uint8 buf[2];
  1931. buf[0] = LO_UINT16( value );
  1932. buf[1] = HI_UINT16( value );
  1933. return ( GATTServApp_WriteAttr( connHandle, attrHandle, buf, 2, 0 ) );
  1934. }
  1935. /*********************************************************************
  1936. * @fn GATTServApp_SendServiceChangedInd
  1937. *
  1938. * @brief Send out a Service Changed Indication.
  1939. *
  1940. * @param connHandle - connection to use
  1941. * @param taskId - task to be notified of confirmation
  1942. *
  1943. * @return SUCCESS: Indication was sent successfully.
  1944. * FAILURE: Service Changed attribute not found.
  1945. * INVALIDPARAMETER: Invalid connection handle or request field.
  1946. * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
  1947. * bleNotConnected: Connection is down.
  1948. * blePending: A confirmation is pending with this client.
  1949. */
  1950. bStatus_t GATTServApp_SendServiceChangedInd( uint16 connHandle, uint8 taskId )
  1951. {
  1952. uint16 value = GATTServApp_ReadCharCfg( connHandle, indCharCfg );
  1953. if ( value & GATT_CLIENT_CFG_INDICATE )
  1954. {
  1955. return ( GATT_ServiceChangedInd( connHandle, taskId ) );
  1956. }
  1957. return ( FAILURE );
  1958. }
  1959. /*********************************************************************
  1960. * @fn GATTServApp_InitCharCfg
  1961. *
  1962. * @brief Initialize the client characteristic configuration table.
  1963. *
  1964. * Note: Each client has its own instantiation of the Client
  1965. * Characteristic Configuration. Reads/Writes of the Client
  1966. * Characteristic Configuration only only affect the
  1967. * configuration of that client.
  1968. *
  1969. * @param connHandle - connection handle (0xFFFF for all connections).
  1970. * @param charCfgTbl - client characteristic configuration table.
  1971. *
  1972. * @return none
  1973. */
  1974. void GATTServApp_InitCharCfg( uint16 connHandle, gattCharCfg_t *charCfgTbl )
  1975. {
  1976. // Initialize Client Characteristic Configuration attributes
  1977. if ( connHandle == INVALID_CONNHANDLE )
  1978. {
  1979. for ( uint8 i = 0; i < GATT_MAX_NUM_CONN; i++ )
  1980. {
  1981. charCfgTbl[i].connHandle = INVALID_CONNHANDLE;
  1982. charCfgTbl[i].value = GATT_CFG_NO_OPERATION;
  1983. }
  1984. }
  1985. else
  1986. {
  1987. gattCharCfg_t *pItem = gattServApp_FindCharCfgItem( connHandle, charCfgTbl );
  1988. if ( pItem != NULL )
  1989. {
  1990. pItem->connHandle = INVALID_CONNHANDLE;
  1991. pItem->value = GATT_CFG_NO_OPERATION;
  1992. }
  1993. }
  1994. }
  1995. /*********************************************************************
  1996. * @fn GATTServApp_ReadCharCfg
  1997. *
  1998. * @brief Read the client characteristic configuration for a given
  1999. * client.
  2000. *
  2001. * Note: Each client has its own instantiation of the Client
  2002. * Characteristic Configuration. Reads of the Client
  2003. * Characteristic Configuration only shows the configuration
  2004. * for that client.
  2005. *
  2006. * @param connHandle - connection handle.
  2007. * @param charCfgTbl - client characteristic configuration table.
  2008. *
  2009. * @return attribute value
  2010. */
  2011. uint16 GATTServApp_ReadCharCfg( uint16 connHandle, gattCharCfg_t *charCfgTbl )
  2012. {
  2013. gattCharCfg_t *pItem;
  2014. pItem = gattServApp_FindCharCfgItem( connHandle, charCfgTbl );
  2015. if ( pItem != NULL )
  2016. {
  2017. return ( (uint16)(pItem->value) );
  2018. }
  2019. return ( (uint16)GATT_CFG_NO_OPERATION );
  2020. }
  2021. /*********************************************************************
  2022. * @fn GATTServApp_WriteCharCfg
  2023. *
  2024. * @brief Write the client characteristic configuration for a given
  2025. * client.
  2026. *
  2027. * Note: Each client has its own instantiation of the Client
  2028. * Characteristic Configuration. Writes of the Client
  2029. * Characteristic Configuration only only affect the
  2030. * configuration of that client.
  2031. *
  2032. * @param connHandle - connection handle.
  2033. * @param charCfgTbl - client characteristic configuration table.
  2034. * @param value - attribute new value.
  2035. *
  2036. * @return Success or Failure
  2037. */
  2038. uint8 GATTServApp_WriteCharCfg( uint16 connHandle, gattCharCfg_t *charCfgTbl,
  2039. uint16 value )
  2040. {
  2041. gattCharCfg_t *pItem;
  2042. pItem = gattServApp_FindCharCfgItem( connHandle, charCfgTbl );
  2043. if ( pItem == NULL )
  2044. {
  2045. pItem = gattServApp_FindCharCfgItem( INVALID_CONNHANDLE, charCfgTbl );
  2046. if ( pItem == NULL )
  2047. {
  2048. return ( ATT_ERR_INSUFFICIENT_RESOURCES );
  2049. }
  2050. pItem->connHandle = connHandle;
  2051. }
  2052. // Write the new value for this client
  2053. pItem->value = value;
  2054. return ( SUCCESS );
  2055. }
  2056. /*********************************************************************
  2057. * @fn GATTServApp_ProcessCCCWriteReq
  2058. *
  2059. * @brief Process the client characteristic configuration
  2060. * write request for a given client.
  2061. *
  2062. * @param connHandle - connection message was received on
  2063. * @param pAttr - pointer to attribute
  2064. * @param pValue - pointer to data to be written
  2065. * @param len - length of data
  2066. * @param offset - offset of the first octet to be written
  2067. * @param validCfg - valid configuration
  2068. *
  2069. * @return Success or Failure
  2070. */
  2071. bStatus_t GATTServApp_ProcessCCCWriteReq( uint16 connHandle, gattAttribute_t *pAttr,
  2072. uint8 *pValue, uint8 len, uint16 offset,
  2073. uint16 validCfg )
  2074. {
  2075. bStatus_t status = SUCCESS;
  2076. // Validate the value
  2077. if ( offset == 0 )
  2078. {
  2079. if ( len == 2 )
  2080. {
  2081. uint16 value = BUILD_UINT16( pValue[0], pValue[1] );
  2082. // Validate characteristic configuration bit field
  2083. if ( ( value & ~validCfg ) == 0 ) // indicate and/or notify
  2084. {
  2085. // Write the value if it's changed
  2086. if ( GATTServApp_ReadCharCfg( connHandle,
  2087. (gattCharCfg_t *)(pAttr->pValue) ) != value )
  2088. {
  2089. status = GATTServApp_WriteCharCfg( connHandle,
  2090. (gattCharCfg_t *)(pAttr->pValue),
  2091. value );
  2092. if ( status == SUCCESS )
  2093. {
  2094. // Notify the application
  2095. GATTServApp_SendCCCUpdatedEvent( connHandle, pAttr->handle, value );
  2096. }
  2097. }
  2098. }
  2099. else
  2100. {
  2101. status = ATT_ERR_INVALID_VALUE;
  2102. }
  2103. }
  2104. else
  2105. {
  2106. status = ATT_ERR_INVALID_VALUE_SIZE;
  2107. }
  2108. }
  2109. else
  2110. {
  2111. status = ATT_ERR_ATTR_NOT_LONG;
  2112. }
  2113. return ( status );
  2114. }
  2115. /*********************************************************************
  2116. * @fn GATTServApp_ProcessCharCfg
  2117. *
  2118. * @brief Process Client Charateristic Configuration change.
  2119. *
  2120. * @param charCfgTbl - characteristic configuration table.
  2121. * @param pValue - pointer to attribute value.
  2122. * @param authenticated - whether an authenticated link is required.
  2123. * @param attrTbl - attribute table.
  2124. * @param numAttrs - number of attributes in attribute table.
  2125. * @param taskId - task to be notified of confirmation.
  2126. *
  2127. * @return Success or Failure
  2128. */
  2129. bStatus_t GATTServApp_ProcessCharCfg( gattCharCfg_t *charCfgTbl, uint8 *pValue,
  2130. uint8 authenticated, gattAttribute_t *attrTbl,
  2131. uint16 numAttrs, uint8 taskId )
  2132. {
  2133. bStatus_t status = SUCCESS;
  2134. for ( uint8 i = 0; i < GATT_MAX_NUM_CONN; i++ )
  2135. {
  2136. gattCharCfg_t *pItem = &(charCfgTbl[i]);
  2137. if ( ( pItem->connHandle != INVALID_CONNHANDLE ) &&
  2138. ( pItem->value != GATT_CFG_NO_OPERATION ) )
  2139. {
  2140. gattAttribute_t *pAttr;
  2141. // Find the characteristic value attribute
  2142. pAttr = GATTServApp_FindAttr( attrTbl, numAttrs, pValue );
  2143. if ( pAttr != NULL )
  2144. {
  2145. attHandleValueNoti_t noti;
  2146. // If the attribute value is longer than (ATT_MTU - 3) octets, then
  2147. // only the first (ATT_MTU - 3) octets of this attributes value can
  2148. // be sent in a notification.
  2149. if ( GATTServApp_ReadAttr( pItem->connHandle, pAttr,
  2150. GATT_SERVICE_HANDLE( attrTbl ), noti.value,
  2151. &noti.len, 0, (g_ATT_MTU_SIZE-3) ) == SUCCESS )
  2152. {
  2153. noti.handle = pAttr->handle;
  2154. if ( pItem->value & GATT_CLIENT_CFG_NOTIFY )
  2155. {
  2156. status |= GATT_Notification( pItem->connHandle, &noti, authenticated );
  2157. }
  2158. if ( pItem->value & GATT_CLIENT_CFG_INDICATE )
  2159. {
  2160. status |= GATT_Indication( pItem->connHandle, (attHandleValueInd_t *)&noti,
  2161. authenticated, taskId );
  2162. }
  2163. }
  2164. }
  2165. }
  2166. } // for
  2167. return ( status );
  2168. }
  2169. /*********************************************************************
  2170. * @fn gattServApp_HandleConnStatusCB
  2171. *
  2172. * @brief GATT Server Application link status change handler function.
  2173. *
  2174. * @param connHandle - connection handle
  2175. * @param changeType - type of change
  2176. *
  2177. * @return none
  2178. */
  2179. static void gattServApp_HandleConnStatusCB( uint16 connHandle, uint8 changeType )
  2180. {
  2181. // Check to see if the connection has dropped
  2182. if ( ( changeType == LINKDB_STATUS_UPDATE_REMOVED ) ||
  2183. ( ( changeType == LINKDB_STATUS_UPDATE_STATEFLAGS ) &&
  2184. ( !linkDB_Up( connHandle ) ) ) )
  2185. {
  2186. prepareWrites_t *pQueue = gattServApp_FindPrepareWriteQ( connHandle );
  2187. // See if this client has a prepare write queue
  2188. if ( pQueue != NULL )
  2189. {
  2190. for ( uint8 i = 0; i < maxNumPrepareWrites; i++ )
  2191. {
  2192. attPrepareWriteReq_t *pWriteReq = &(pQueue->pPrepareWriteQ[i]);
  2193. // See if there're any prepared write requests in the queue
  2194. if ( pWriteReq->handle == GATT_INVALID_HANDLE )
  2195. {
  2196. break;
  2197. }
  2198. // Clear the queue item
  2199. VOID osal_memset( pWriteReq, 0, sizeof( attPrepareWriteRsp_t ) );
  2200. } // for loop
  2201. // Mark this queue as empty
  2202. pQueue->connHandle = INVALID_CONNHANDLE;
  2203. }
  2204. // Reset Client Char Config when connection drops
  2205. GATTServApp_InitCharCfg( connHandle, indCharCfg );
  2206. }
  2207. }
  2208. /*********************************************************************
  2209. * @fn GATTServApp_SendCCCUpdatedEvent
  2210. *
  2211. * @brief Build and send the GATT_CLIENT_CHAR_CFG_UPDATED_EVENT to
  2212. * the app.
  2213. *
  2214. * @param connHandle - connection handle
  2215. * @param attrHandle - attribute handle
  2216. * @param value - attribute new value
  2217. *
  2218. * @return none
  2219. */
  2220. void GATTServApp_SendCCCUpdatedEvent( uint16 connHandle, uint16 attrHandle, uint16 value )
  2221. {
  2222. if ( appTaskID != INVALID_TASK_ID )
  2223. {
  2224. // Allocate, build and send event
  2225. gattClientCharCfgUpdatedEvent_t *pEvent =
  2226. (gattClientCharCfgUpdatedEvent_t *)osal_msg_allocate( (uint16)(sizeof ( gattClientCharCfgUpdatedEvent_t )) );
  2227. if ( pEvent )
  2228. {
  2229. pEvent->hdr.event = GATT_SERV_MSG_EVENT;
  2230. pEvent->hdr.status = SUCCESS;
  2231. pEvent->method = GATT_CLIENT_CHAR_CFG_UPDATED_EVENT;
  2232. pEvent->connHandle = connHandle;
  2233. pEvent->attrHandle = attrHandle;
  2234. pEvent->value = value;
  2235. VOID osal_msg_send( appTaskID, (uint8 *)pEvent );
  2236. }
  2237. }
  2238. }
  2239. bStatus_t gattServApp_RegisterCB(gattServMsgCB_t cb)
  2240. {
  2241. s_GATTServCB = cb;
  2242. return SUCCESS;
  2243. }
  2244. #endif // ( CENTRAL_CFG | PERIPHERAL_CFG )
  2245. /****************************************************************************
  2246. ****************************************************************************/