gattservapp.c 75 KB

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