gapgattserver.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974
  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: gapgattserver.c
  30. Revised:
  31. Revision:
  32. Description: GAP Attribute Server
  33. **************************************************************************************************/
  34. /*********************************************************************
  35. * INCLUDES
  36. */
  37. #include "bcomdef.h"
  38. #include "OSAL.h"
  39. #include "gap.h"
  40. #include "gapgattserver.h"
  41. #include "att.h"
  42. #include "gatt.h"
  43. #include "gatt_uuid.h"
  44. #include "gattservapp.h"
  45. /*********************************************************************
  46. * MACROS
  47. */
  48. /*********************************************************************
  49. * CONSTANTS
  50. */
  51. // Position of device name in attribute table
  52. #define GAP_DEVICE_NAME_POS 2
  53. #define GAP_APPEARANCE_POS 4
  54. #define GAP_PRIVACY_FLAG_POS 6
  55. /*********************************************************************
  56. * TYPEDEFS
  57. */
  58. /*********************************************************************
  59. * GLOBAL VARIABLES
  60. */
  61. /*********************************************************************
  62. * EXTERNAL VARIABLES
  63. */
  64. /*********************************************************************
  65. * EXTERNAL FUNCTIONS
  66. */
  67. /*********************************************************************
  68. * LOCAL VARIABLES
  69. */
  70. static const ggsAppCBs_t *ggs_AppCBs = NULL;
  71. #if defined ( TESTMODES )
  72. static uint16 paramValue = 0;
  73. #endif
  74. /*********************************************************************
  75. * Profile Attributes - variables
  76. */
  77. // GAP Service
  78. static CONST gattAttrType_t gapService = { ATT_BT_UUID_SIZE, gapServiceUUID };
  79. // Device Name Characteristic Properties
  80. static uint8 deviceNameCharProps = GATT_PROP_READ;
  81. // Device Name attribute (0 - 248 octets) - extra octet for null-terminate char
  82. static uint8 deviceName[GAP_DEVICE_NAME_LEN+1] = { 0 };
  83. // Appearance Characteristic Properties
  84. static uint8 appearanceCharProps = GATT_PROP_READ;
  85. // Appearance attribute (2-octet enumerated value as defined by Bluetooth Assigned Numbers document)
  86. static uint16 appearance = GAP_APPEARE_UNKNOWN;
  87. #if ( HOST_CONFIG & PERIPHERAL_CFG )
  88. #if defined (GAP_PRIVACY) || defined (GAP_PRIVACY_RECONNECT)
  89. // Peripheral Privacy Flag Characteristic Properties
  90. static uint8 periPrivacyFlagCharProps = GATT_PROP_READ;
  91. // Peripheral Privacy Flag attribute (1 octet)
  92. static uint8 periPrivacyFlag = GAP_PRIVACY_DISABLED;
  93. #endif // GAP_PRIVACY || GAP_PRIVACY_RECONNECT
  94. #if defined (GAP_PRIVACY_RECONNECT)
  95. // Reconnection Address Characteristic Properties
  96. static uint8 reconnectAddrCharProps = GATT_PROP_WRITE;
  97. // Reconnection Address attribute (6 octets)
  98. static uint8 reconnectAddr[B_ADDR_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  99. #endif // GAP_PRIVACY_RECONNECT
  100. // Peripheral Preferred Connection Parameters Characteristic Properties
  101. static uint8 periConnParamCharProps = GATT_PROP_READ;
  102. // Peripheral Preferred Connection Parameters attribute (8 octets)
  103. static gapPeriConnectParams_t periConnParameters = { 80, 160, 0, 1000 };
  104. #endif // PERIPHERAL_CFG
  105. /*********************************************************************
  106. * Profile Attributes - Table
  107. */
  108. // GAP Attribute Table
  109. static gattAttribute_t gapAttrTbl[] =
  110. {
  111. // Generic Access Profile
  112. {
  113. { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */
  114. GATT_PERMIT_READ, /* permissions */
  115. 0, /* handle */
  116. (uint8 *)&gapService /* pValue */
  117. },
  118. // Characteristic Declaration
  119. {
  120. { ATT_BT_UUID_SIZE, characterUUID },
  121. GATT_PERMIT_READ,
  122. 0,
  123. &deviceNameCharProps
  124. },
  125. // Device Name attribute
  126. {
  127. { ATT_BT_UUID_SIZE, deviceNameUUID },
  128. GATT_PERMIT_READ,
  129. 0,
  130. deviceName
  131. },
  132. // Characteristic Declaration
  133. {
  134. { ATT_BT_UUID_SIZE, characterUUID },
  135. GATT_PERMIT_READ,
  136. 0,
  137. &appearanceCharProps
  138. },
  139. // Icon attribute
  140. {
  141. { ATT_BT_UUID_SIZE, appearanceUUID },
  142. GATT_PERMIT_READ,
  143. 0,
  144. (uint8 *)&appearance
  145. },
  146. #if ( HOST_CONFIG & PERIPHERAL_CFG )
  147. #if defined (GAP_PRIVACY) || defined (GAP_PRIVACY_RECONNECT)
  148. // Characteristic Declaration
  149. {
  150. { ATT_BT_UUID_SIZE, characterUUID },
  151. GATT_PERMIT_READ,
  152. 0,
  153. &periPrivacyFlagCharProps
  154. },
  155. // Peripheral Privacy Flag attribute
  156. {
  157. { ATT_BT_UUID_SIZE, periPrivacyFlagUUID },
  158. GATT_PERMIT_READ,
  159. 0,
  160. (uint8 *)&periPrivacyFlag
  161. },
  162. #endif // GAP_PRIVACY || GAP_PRIVACY_RECONNECT
  163. #if defined (GAP_PRIVACY_RECONNECT)
  164. // Characteristic Declaration
  165. {
  166. { ATT_BT_UUID_SIZE, characterUUID },
  167. GATT_PERMIT_READ,
  168. 0,
  169. &reconnectAddrCharProps
  170. },
  171. // Reconnection Address attribute
  172. {
  173. { ATT_BT_UUID_SIZE, reconnectAddrUUID },
  174. GATT_PERMIT_AUTHEN_WRITE,
  175. 0,
  176. reconnectAddr
  177. },
  178. #endif // GAP_PRIVACY_RECONNECT
  179. // Characteristic Declaration
  180. {
  181. { ATT_BT_UUID_SIZE, characterUUID },
  182. GATT_PERMIT_READ,
  183. 0,
  184. &periConnParamCharProps
  185. },
  186. // Peripheral Preferred Connection Parameters attribute
  187. {
  188. { ATT_BT_UUID_SIZE, periConnParamUUID },
  189. GATT_PERMIT_READ,
  190. 0,
  191. (uint8 *)&periConnParameters
  192. },
  193. #endif // PERIPHERAL_CFG
  194. };
  195. /*********************************************************************
  196. * LOCAL FUNCTIONS
  197. */
  198. static void ggs_SetAttrWPermit( uint8 wPermit, uint8 *pPermissions, uint8 *pCharProps );
  199. /*********************************************************************
  200. * PUBLIC FUNCTIONS
  201. */
  202. // GGS Callback functions
  203. static uint8 ggs_ReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
  204. uint8 *pValue, uint8 *pLen, uint16 offset, uint8 maxLen );
  205. static bStatus_t ggs_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
  206. uint8 *pValue, uint8 len, uint16 offset );
  207. /*********************************************************************
  208. * PROFILE CALLBACKS
  209. */
  210. // GAP Service Callbacks
  211. CONST gattServiceCBs_t gapServiceCBs =
  212. {
  213. ggs_ReadAttrCB, // Read callback function pointer
  214. ggs_WriteAttrCB, // Write callback function pointer
  215. NULL // Authorization callback function pointer
  216. };
  217. /*********************************************************************
  218. * @fn GGS_SetParameter
  219. *
  220. * @brief Set a GAP GATT Server parameter.
  221. *
  222. * @param param - Profile parameter ID
  223. * @param len - length of data to right
  224. * @param value - pointer to data to write. This is dependent on
  225. * the parameter ID and WILL be cast to the appropriate
  226. * data type (example: data type of uint16 will be cast to
  227. * uint16 pointer).
  228. *
  229. * @return bStatus_t
  230. */
  231. bStatus_t GGS_SetParameter( uint8 param, uint8 len, void *value )
  232. {
  233. bStatus_t ret = SUCCESS;
  234. switch ( param )
  235. {
  236. case GGS_DEVICE_NAME_ATT:
  237. // Always leave room for null-terminate char
  238. if ( len <= GAP_DEVICE_NAME_LEN )
  239. {
  240. VOID osal_memset( deviceName, 0, GAP_DEVICE_NAME_LEN+1 );
  241. VOID osal_memcpy( deviceName, value, len );
  242. }
  243. else
  244. {
  245. ret = bleInvalidRange;
  246. }
  247. break;
  248. case GGS_APPEARANCE_ATT:
  249. if ( len == sizeof ( uint16 ) )
  250. {
  251. appearance = *((uint16*)value);
  252. }
  253. else
  254. {
  255. ret = bleInvalidRange;
  256. }
  257. break;
  258. #if ( HOST_CONFIG & PERIPHERAL_CFG )
  259. #if defined (GAP_PRIVACY) || defined (GAP_PRIVACY_RECONNECT)
  260. case GGS_PERI_PRIVACY_FLAG_ATT:
  261. if ( len == sizeof ( uint8 ) )
  262. {
  263. periPrivacyFlag = *((uint8*)value);
  264. }
  265. else
  266. {
  267. ret = bleInvalidRange;
  268. }
  269. break;
  270. case GGS_PERI_PRIVACY_FLAG_PROPS:
  271. if ( len == sizeof ( uint8 ) )
  272. {
  273. periPrivacyFlagCharProps = *((uint8*)value);
  274. }
  275. else
  276. {
  277. ret = bleInvalidRange;
  278. }
  279. break;
  280. case GGS_W_PERMIT_PRIVACY_FLAG_ATT:
  281. if ( len == sizeof ( uint8 ) )
  282. {
  283. uint8 wPermit = *(uint8 *)value;
  284. // Optionally Writeable with Authentication
  285. if ( !gattPermitWrite( wPermit ) )
  286. {
  287. ggs_SetAttrWPermit( wPermit,
  288. &(gapAttrTbl[GAP_PRIVACY_FLAG_POS].permissions),
  289. gapAttrTbl[GAP_PRIVACY_FLAG_POS-1].pValue );
  290. }
  291. else
  292. {
  293. ret = bleInvalidRange;
  294. }
  295. }
  296. else
  297. {
  298. ret = bleInvalidRange;
  299. }
  300. break;
  301. #endif // GAP_PRIVACY || GAP_PRIVACY_RECONNECT
  302. #if defined (GAP_PRIVACY_RECONNECT)
  303. case GGS_RECONNCT_ADDR_ATT:
  304. if ( len == B_ADDR_LEN )
  305. {
  306. VOID osal_memcpy( reconnectAddr, value, len );
  307. }
  308. else
  309. {
  310. ret = bleInvalidRange;
  311. }
  312. break;
  313. #endif // GAP_PRIVACY_RECONNECT
  314. case GGS_PERI_CONN_PARAM_ATT:
  315. if ( len == sizeof(gapPeriConnectParams_t) )
  316. {
  317. periConnParameters = *((gapPeriConnectParams_t *)(value));
  318. }
  319. else
  320. {
  321. ret = bleInvalidRange;
  322. }
  323. break;
  324. #endif // PERIPHERAL_CFG
  325. case GGS_W_PERMIT_DEVICE_NAME_ATT:
  326. if ( len == sizeof ( uint8 ) )
  327. {
  328. // Optionally Writeable
  329. ggs_SetAttrWPermit( *(uint8 *)value,
  330. &(gapAttrTbl[GAP_DEVICE_NAME_POS].permissions),
  331. gapAttrTbl[GAP_DEVICE_NAME_POS-1].pValue );
  332. }
  333. else
  334. {
  335. ret = bleInvalidRange;
  336. }
  337. break;
  338. case GGS_W_PERMIT_APPEARANCE_ATT:
  339. if ( len == sizeof ( uint8 ) )
  340. {
  341. // Optionally Writeable
  342. ggs_SetAttrWPermit( *(uint8 *)value,
  343. &(gapAttrTbl[GAP_APPEARANCE_POS].permissions),
  344. gapAttrTbl[GAP_APPEARANCE_POS-1].pValue );
  345. }
  346. else
  347. {
  348. ret = bleInvalidRange;
  349. }
  350. break;
  351. default:
  352. ret = INVALIDPARAMETER;
  353. break;
  354. }
  355. return ( ret );
  356. }
  357. /*********************************************************************
  358. * @fn GGS_GetParameter
  359. *
  360. * @brief Get a GAP GATT Server parameter.
  361. *
  362. * @param param - Profile parameter ID
  363. * @param value - pointer to data to put. This is dependent on
  364. * the parameter ID and WILL be cast to the appropriate
  365. * data type (example: data type of uint16 will be cast to
  366. * uint16 pointer).
  367. *
  368. * @return bStatus_t
  369. */
  370. bStatus_t GGS_GetParameter( uint8 param, void *value )
  371. {
  372. bStatus_t ret = SUCCESS;
  373. switch ( param )
  374. {
  375. case GGS_DEVICE_NAME_ATT:
  376. VOID osal_memcpy( value, deviceName, GAP_DEVICE_NAME_LEN );
  377. break;
  378. case GGS_APPEARANCE_ATT:
  379. *((uint16*)value) = appearance;
  380. break;
  381. #if ( HOST_CONFIG & PERIPHERAL_CFG )
  382. #if defined (GAP_PRIVACY) || defined (GAP_PRIVACY_RECONNECT)
  383. case GGS_PERI_PRIVACY_FLAG_ATT:
  384. *((uint8*)value) = periPrivacyFlag;
  385. break;
  386. case GGS_PERI_PRIVACY_FLAG_PROPS:
  387. *((uint8*)value) = periPrivacyFlagCharProps;
  388. break;
  389. #endif // GAP_PRIVACY || GAP_PRIVACY_RECONNECT
  390. #if defined (GAP_PRIVACY_RECONNECT)
  391. case GGS_RECONNCT_ADDR_ATT:
  392. VOID osal_memcpy( value, reconnectAddr, B_ADDR_LEN );
  393. break;
  394. #endif // GAP_PRIVACY_RECONNECT
  395. case GGS_PERI_CONN_PARAM_ATT:
  396. *((gapPeriConnectParams_t *)(value)) = periConnParameters;
  397. break;
  398. #endif // PERIPHERAL_CFG
  399. default:
  400. ret = INVALIDPARAMETER;
  401. break;
  402. }
  403. return ( ret );
  404. }
  405. /*********************************************************************
  406. * @fn GGS_SetParamValue
  407. *
  408. * @brief Set a GGS Parameter value. Use this function to change
  409. * the default GGS parameter values.
  410. *
  411. * @param value - new GGS param value
  412. *
  413. * @return void
  414. */
  415. void GGS_SetParamValue( uint16 value )
  416. {
  417. #if defined ( TESTMODES )
  418. uint8 wpermit;
  419. paramValue = value;
  420. switch ( value )
  421. {
  422. case GGS_TESTMODE_OFF:
  423. wpermit = 0;
  424. VOID GGS_SetParameter( GGS_W_PERMIT_DEVICE_NAME_ATT, sizeof( uint8 ), (void*)&wpermit );
  425. VOID GGS_SetParameter( GGS_W_PERMIT_APPEARANCE_ATT, sizeof( uint8 ), (void*)&wpermit );
  426. VOID GGS_SetParameter( GGS_W_PERMIT_PRIVACY_FLAG_ATT, sizeof( uint8 ), (void*)&wpermit );
  427. break;
  428. case GGS_TESTMODE_W_PERMIT_DEVICE_NAME:
  429. wpermit = GATT_PERMIT_WRITE;
  430. VOID GGS_SetParameter( GGS_W_PERMIT_DEVICE_NAME_ATT, sizeof( uint8 ), (void*)&wpermit );
  431. break;
  432. case GGS_TESTMODE_W_PERMIT_APPEARANCE:
  433. wpermit = GATT_PERMIT_WRITE;
  434. VOID GGS_SetParameter( GGS_W_PERMIT_APPEARANCE_ATT, sizeof( uint8 ), (void*)&wpermit );
  435. break;
  436. case GGS_TESTMODE_W_PERMIT_PRIVACY_FLAG:
  437. wpermit = GATT_PERMIT_AUTHEN_WRITE;
  438. VOID GGS_SetParameter( GGS_W_PERMIT_PRIVACY_FLAG_ATT, sizeof( uint8 ), (void*)&wpermit );
  439. break;
  440. default:
  441. break;
  442. }
  443. #else
  444. VOID value;
  445. #endif
  446. }
  447. /*********************************************************************
  448. * @fn GGS_GetParamValue
  449. *
  450. * @brief Get a GGS Parameter value.
  451. *
  452. * @param none
  453. *
  454. * @return GGS Parameter value
  455. */
  456. uint16 GGS_GetParamValue( void )
  457. {
  458. #if defined ( TESTMODES )
  459. return ( paramValue );
  460. #else
  461. return ( 0 );
  462. #endif
  463. }
  464. /*********************************************************************
  465. * LOCAL FUNCTION PROTOTYPES
  466. */
  467. /*********************************************************************
  468. * @fn GGS_AddService
  469. *
  470. * @brief Add function for the GAP GATT Service.
  471. *
  472. * @param services - services to add. This is a bit map and can
  473. * contain more than one service.
  474. *
  475. * @return SUCCESS: Service added successfully.
  476. * INVALIDPARAMETER: Invalid service field.
  477. * FAILURE: Not enough attribute handles available.
  478. * bleMemAllocError: Memory allocation error occurred.
  479. */
  480. bStatus_t GGS_AddService( uint32 services )
  481. {
  482. uint8 status = SUCCESS;
  483. if ( services & GAP_SERVICE )
  484. {
  485. // Register GAP attribute list and CBs with GATT Server Server App
  486. status = GATTServApp_RegisterService( gapAttrTbl, GATT_NUM_ATTRS( gapAttrTbl ),
  487. &gapServiceCBs );
  488. }
  489. return ( status );
  490. }
  491. /******************************************************************************
  492. * @fn GATTServApp_DelService
  493. *
  494. * @brief Delete function for the GAP GATT Service.
  495. *
  496. * @param services - services to delete. This is a bit map and can
  497. * contain more than one service.
  498. *
  499. * @return SUCCESS: Service deleted successfully.
  500. * FAILURE: Service not found.
  501. */
  502. bStatus_t GGS_DelService( uint32 services )
  503. {
  504. uint8 status = SUCCESS;
  505. if ( services & GAP_SERVICE )
  506. {
  507. // Deregister GAP attribute list and CBs from GATT Server Application
  508. status = GATTServApp_DeregisterService( GATT_SERVICE_HANDLE( gapAttrTbl ), NULL );
  509. }
  510. return ( status );
  511. }
  512. /*********************************************************************
  513. * @fn GGS_RegisterAppCBs
  514. *
  515. * @brief Registers the application callback function.
  516. *
  517. * Note: Callback registration is needed only when the
  518. * Device Name is made writable. The application
  519. * will be notified when the Device Name is changed
  520. * over the air.
  521. *
  522. * @param appCallbacks - pointer to application callbacks.
  523. *
  524. * @return none
  525. */
  526. void GGS_RegisterAppCBs( ggsAppCBs_t *appCallbacks )
  527. {
  528. ggs_AppCBs = appCallbacks;
  529. }
  530. /*********************************************************************
  531. * @fn ggs_SetAttrWPermit
  532. *
  533. * @brief Update attribute Write access permissions and characteristic
  534. * properties for over-the-air write operations.
  535. *
  536. * @param wPermit - write acces permissions
  537. * @param pPermissions - pointer to attribute permissions
  538. * @param pCharProps - pointer to characteristic properties
  539. *
  540. * @return none
  541. */
  542. static void ggs_SetAttrWPermit( uint8 wPermit, uint8 *pPermissions, uint8 *pCharProps )
  543. {
  544. // Update attribute Write access permissions
  545. if ( gattPermitWrite( wPermit ) )
  546. {
  547. *pPermissions |= GATT_PERMIT_WRITE;
  548. }
  549. else
  550. {
  551. *pPermissions &= ~GATT_PERMIT_WRITE;
  552. }
  553. if ( gattPermitAuthenWrite( wPermit ) )
  554. {
  555. *pPermissions |= GATT_PERMIT_AUTHEN_WRITE;
  556. }
  557. else
  558. {
  559. *pPermissions &= ~GATT_PERMIT_AUTHEN_WRITE;
  560. }
  561. if ( gattPermitAuthorWrite( wPermit ) )
  562. {
  563. *pPermissions |= GATT_PERMIT_AUTHOR_WRITE;
  564. }
  565. else
  566. {
  567. *pPermissions &= ~GATT_PERMIT_AUTHOR_WRITE;
  568. }
  569. // Update attribute Write characteristic properties
  570. if ( gattPermitWrite( wPermit ) ||
  571. gattPermitAuthenWrite( wPermit ) ||
  572. gattPermitAuthorWrite( wPermit ) )
  573. {
  574. *pCharProps |= (GATT_PROP_WRITE_NO_RSP | GATT_PROP_WRITE);
  575. }
  576. else if ( wPermit == 0 )
  577. {
  578. // Attribute not Writable
  579. *pCharProps &= ~(GATT_PROP_WRITE_NO_RSP | GATT_PROP_WRITE);
  580. }
  581. }
  582. /*********************************************************************
  583. * @fn ggs_ReadAttrCB
  584. *
  585. * @brief Read an attribute.
  586. *
  587. * @param connHandle - connection message was received on
  588. * @param pAttr - pointer to attribute
  589. * @param pValue - pointer to data to be read
  590. * @param pLen - length of data to be read
  591. * @param offset - offset of the first octet to be read
  592. * @param maxLen - maximum length of data to be read
  593. *
  594. * @return Success or Failure
  595. */
  596. static uint8 ggs_ReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
  597. uint8 *pValue, uint8 *pLen, uint16 offset, uint8 maxLen )
  598. {
  599. uint16 uuid;
  600. bStatus_t status = SUCCESS;
  601. VOID connHandle; // Not needed for now!
  602. // Make sure it's not a blob operation
  603. if ( offset > 0 )
  604. {
  605. return ( ATT_ERR_ATTR_NOT_LONG );
  606. }
  607. if ( pAttr->type.len == ATT_BT_UUID_SIZE )
  608. {
  609. // 16-bit UUID
  610. uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
  611. switch ( uuid )
  612. {
  613. case DEVICE_NAME_UUID:
  614. {
  615. uint8 len = osal_strlen( (char *)(pAttr->pValue) );
  616. // If the attribute value is longer than maxLen then maxLen
  617. // octets shall be included in this response.
  618. if ( len > maxLen )
  619. {
  620. len = maxLen;
  621. }
  622. *pLen = len;
  623. VOID osal_memcpy( pValue, pAttr->pValue, len );
  624. }
  625. break;
  626. case APPEARANCE_UUID:
  627. {
  628. uint16 value = *((uint16 *)(pAttr->pValue));
  629. *pLen = 2;
  630. pValue[0] = LO_UINT16( value );
  631. pValue[1] = HI_UINT16( value );
  632. }
  633. break;
  634. case RECONNECT_ADDR_UUID:
  635. *pLen = B_ADDR_LEN;
  636. VOID osal_memcpy( pValue, pAttr->pValue, B_ADDR_LEN );
  637. break;
  638. case PERI_PRIVACY_FLAG_UUID:
  639. *pLen = 1;
  640. *pValue = *pAttr->pValue;
  641. break;
  642. case PERI_CONN_PARAM_UUID:
  643. if ( pAttr->pValue != NULL )
  644. {
  645. gapPeriConnectParams_t *pConnectParam = (gapPeriConnectParams_t *)(pAttr->pValue);
  646. *pLen = 8;
  647. pValue[0] = LO_UINT16( pConnectParam->intervalMin );
  648. pValue[1] = HI_UINT16( pConnectParam->intervalMin );
  649. pValue[2] = LO_UINT16( pConnectParam->intervalMax );
  650. pValue[3] = HI_UINT16( pConnectParam->intervalMax );
  651. pValue[4] = LO_UINT16( pConnectParam->latency );
  652. pValue[5] = HI_UINT16( pConnectParam->latency );
  653. pValue[6] = LO_UINT16( pConnectParam->timeout );
  654. pValue[7] = HI_UINT16( pConnectParam->timeout );
  655. }
  656. else
  657. {
  658. *pLen = 0;
  659. }
  660. break;
  661. default:
  662. // Should never get here!
  663. *pLen = 0;
  664. status = ATT_ERR_INVALID_HANDLE;
  665. break;
  666. }
  667. }
  668. else
  669. {
  670. // 128-bit UUID
  671. *pLen = 0;
  672. status = ATT_ERR_INVALID_HANDLE;
  673. }
  674. return ( status );
  675. }
  676. /*********************************************************************
  677. * @fn ggs_ValidateWriteAttrCB
  678. *
  679. * @brief Validate and Write attribute data
  680. *
  681. * @param connHandle - connection message was received on
  682. * @param pAttr - pointer to attribute
  683. * @param pValue - pointer to data to be written
  684. * @param len - length of data
  685. * @param offset - offset of the first octet to be written
  686. *
  687. * @return Success or Failure
  688. */
  689. static bStatus_t ggs_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
  690. uint8 *pValue, uint8 len, uint16 offset )
  691. {
  692. bStatus_t status = SUCCESS;
  693. VOID connHandle; // Not needed for now!
  694. if ( pAttr->type.len == ATT_BT_UUID_SIZE )
  695. {
  696. // 16-bit UUID
  697. uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
  698. switch ( uuid )
  699. {
  700. case DEVICE_NAME_UUID:
  701. // Validate the long value
  702. {
  703. uint8 curLen = osal_strlen( (char *)(pAttr->pValue) );
  704. // If the value offset is greater than the current length of the
  705. // attribute value then an Error Response shall be sent with the
  706. // error code Invalid Offset.
  707. if ( offset <= curLen )
  708. {
  709. // Always leave room for null-terminate char
  710. if ( ( offset + len ) > GAP_DEVICE_NAME_LEN )
  711. {
  712. // Appliction error
  713. status = ATT_ERR_INVALID_VALUE_SIZE;
  714. }
  715. }
  716. else
  717. {
  718. status = ATT_ERR_INVALID_OFFSET;
  719. }
  720. }
  721. // Write the long value
  722. if ( status == SUCCESS )
  723. {
  724. VOID osal_memcpy( &(pAttr->pValue[offset]), pValue, len );
  725. offset += len;
  726. pAttr->pValue[offset] = '\0';
  727. // Notify application
  728. if ( ggs_AppCBs && ggs_AppCBs->pfnAttrValueChange )
  729. {
  730. ggs_AppCBs->pfnAttrValueChange( GGS_DEVICE_NAME_ID );
  731. }
  732. }
  733. break;
  734. case APPEARANCE_UUID:
  735. // Validate the value
  736. if ( offset == 0 )
  737. {
  738. if ( len != 2 )
  739. {
  740. status = ATT_ERR_INVALID_VALUE_SIZE;
  741. }
  742. }
  743. else
  744. {
  745. status = ATT_ERR_ATTR_NOT_LONG;
  746. }
  747. // Write the value
  748. if ( status == SUCCESS )
  749. {
  750. uint16 *pCurValue = (uint16 *)pAttr->pValue;
  751. *pCurValue = BUILD_UINT16( pValue[0], pValue[1] );
  752. // Notify application
  753. if ( ggs_AppCBs && ggs_AppCBs->pfnAttrValueChange )
  754. {
  755. ggs_AppCBs->pfnAttrValueChange( GGS_APPEARANCE_ID );
  756. }
  757. }
  758. break;
  759. case RECONNECT_ADDR_UUID:
  760. // Validate the value - writable by a bonded device
  761. #if ( HOST_CONFIG & PERIPHERAL_CFG )
  762. #if defined (GAP_PRIVACY) || defined (GAP_PRIVACY_RECONNECT)
  763. if ( periPrivacyFlag == GAP_PRIVACY_DISABLED )
  764. {
  765. status = ATT_ERR_WRITE_NOT_PERMITTED;
  766. }
  767. else
  768. #endif // GAP_PRIVACY || GAP_PRIVACY_RECONNECT
  769. #endif // PERIPHERAL_CFG
  770. if ( offset == 0 )
  771. {
  772. if ( len != B_ADDR_LEN )
  773. {
  774. status = ATT_ERR_INVALID_VALUE_SIZE;
  775. }
  776. }
  777. else
  778. {
  779. status = ATT_ERR_ATTR_NOT_LONG;
  780. }
  781. // Write the value
  782. if ( status == SUCCESS )
  783. {
  784. VOID osal_memcpy( pAttr->pValue, pValue, B_ADDR_LEN );
  785. }
  786. break;
  787. case PERI_PRIVACY_FLAG_UUID:
  788. // Validate the value - writable by a bonded device
  789. #if ( HOST_CONFIG & PERIPHERAL_CFG )
  790. #if defined (GAP_PRIVACY) || defined (GAP_PRIVACY_RECONNECT)
  791. if ( (periPrivacyFlagCharProps & GATT_PROP_WRITE) == 0 )
  792. {
  793. status = ATT_ERR_WRITE_NOT_PERMITTED;
  794. }
  795. else
  796. #endif // GAP_PRIVACY || GAP_PRIVACY_RECONNECT
  797. #endif // PERIPHERAL_CFG
  798. if ( offset == 0 )
  799. {
  800. if ( len == 1 )
  801. {
  802. // Validate characteristic configuration bit field
  803. if ( ( *pValue != GAP_PRIVACY_DISABLED ) &&
  804. ( *pValue != GAP_PRIVACY_ENABLED ) )
  805. {
  806. status = ATT_ERR_INVALID_VALUE;
  807. }
  808. }
  809. else
  810. {
  811. status = ATT_ERR_INVALID_VALUE_SIZE;
  812. }
  813. }
  814. else
  815. {
  816. status = ATT_ERR_ATTR_NOT_LONG;
  817. }
  818. // Write the value
  819. if ( status == SUCCESS )
  820. {
  821. *pAttr->pValue = *pValue;
  822. }
  823. break;
  824. default:
  825. // Should never get here!
  826. status = ATT_ERR_INVALID_HANDLE;
  827. }
  828. }
  829. else
  830. {
  831. // 128-bit UUID
  832. status = ATT_ERR_INVALID_HANDLE;
  833. }
  834. return ( status );
  835. }
  836. /*********************************************************************
  837. *********************************************************************/