gattprofile.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832
  1. /********************************** (C) COPYRIGHT *******************************
  2. * File Name : gattprofile.C
  3. * Author : WCH
  4. * Version : V1.0
  5. * Date : 2018/12/10
  6. * Description : Customize services with five different attributes,
  7. * including readable, writable, notification,
  8. * readable and writable, and safe readable
  9. *********************************************************************************
  10. * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
  11. * Attention: This software (modified or not) and binary are used for
  12. * microcontroller manufactured by Nanjing Qinheng Microelectronics.
  13. *******************************************************************************/
  14. /*********************************************************************
  15. * INCLUDES
  16. */
  17. #include <user_config.h>
  18. #include "gattprofile.h"
  19. /*********************************************************************
  20. * MACROS
  21. */
  22. /*********************************************************************
  23. * CONSTANTS
  24. */
  25. // Position of simpleProfilechar4 value in attribute array
  26. #define SIMPLEPROFILE_CHAR4_VALUE_POS 11
  27. #if(DEBUG == DEBUG_UART_BLE)
  28. #define SIMPLEPROFILE_CHAR5_VALUE_POS 15
  29. #endif
  30. /*********************************************************************
  31. * TYPEDEFS
  32. */
  33. /*********************************************************************
  34. * GLOBAL VARIABLES
  35. */
  36. // Simple GATT Profile Service UUID: 0xFFF0
  37. const uint8_t simpleProfileServUUID[ATT_BT_UUID_SIZE] = {
  38. LO_UINT16(SIMPLEPROFILE_SERV_UUID), HI_UINT16(SIMPLEPROFILE_SERV_UUID)};
  39. // Characteristic 1 UUID: 0xFFF1
  40. const uint8_t simpleProfilechar1UUID[ATT_BT_UUID_SIZE] = {
  41. LO_UINT16(SIMPLEPROFILE_CHAR1_UUID), HI_UINT16(SIMPLEPROFILE_CHAR1_UUID)};
  42. // Characteristic 2 UUID: 0xFFF2
  43. const uint8_t simpleProfilechar2UUID[ATT_BT_UUID_SIZE] = {
  44. LO_UINT16(SIMPLEPROFILE_CHAR2_UUID), HI_UINT16(SIMPLEPROFILE_CHAR2_UUID)};
  45. // Characteristic 3 UUID: 0xFFF3
  46. const uint8_t simpleProfilechar3UUID[ATT_BT_UUID_SIZE] = {
  47. LO_UINT16(SIMPLEPROFILE_CHAR3_UUID), HI_UINT16(SIMPLEPROFILE_CHAR3_UUID)};
  48. // Characteristic 4 UUID: 0xFFF4
  49. const uint8_t simpleProfilechar4UUID[ATT_BT_UUID_SIZE] = {
  50. LO_UINT16(SIMPLEPROFILE_CHAR4_UUID), HI_UINT16(SIMPLEPROFILE_CHAR4_UUID)};
  51. #if(DEBUG == DEBUG_UART_BLE)
  52. // Characteristic 5 UUID: 0xFFF5
  53. const uint8_t simpleProfilechar5UUID[ATT_BT_UUID_SIZE] = {
  54. LO_UINT16(SIMPLEPROFILE_CHAR5_UUID), HI_UINT16(SIMPLEPROFILE_CHAR5_UUID)};
  55. #endif
  56. /*********************************************************************
  57. * EXTERNAL VARIABLES
  58. */
  59. /*********************************************************************
  60. * EXTERNAL FUNCTIONS
  61. */
  62. /*********************************************************************
  63. * LOCAL VARIABLES
  64. */
  65. static simpleProfileCBs_t *simpleProfile_AppCBs = NULL;
  66. /*********************************************************************
  67. * Profile Attributes - variables
  68. */
  69. // Simple Profile Service attribute
  70. static const gattAttrType_t simpleProfileService = {ATT_BT_UUID_SIZE, simpleProfileServUUID};
  71. // Simple Profile Characteristic 1 Properties
  72. static uint8_t simpleProfileChar1Props = GATT_PROP_READ | GATT_PROP_WRITE | GATT_PROP_WRITE_NO_RSP;
  73. // Characteristic 1 Value
  74. static uint8_t simpleProfileChar1[SIMPLEPROFILE_CHAR1_LEN] = {0};
  75. // Simple Profile Characteristic 1 User Description
  76. static uint8_t simpleProfileChar1UserDesp[] = "Characteristic 1\0";
  77. // Simple Profile Characteristic 2 Properties
  78. static uint8_t simpleProfileChar2Props = GATT_PROP_READ;
  79. // Characteristic 2 Value
  80. static uint8_t simpleProfileChar2[SIMPLEPROFILE_CHAR2_LEN] = {0};
  81. // Simple Profile Characteristic 2 User Description
  82. static uint8_t simpleProfileChar2UserDesp[] = "Characteristic 2\0";
  83. // Simple Profile Characteristic 3 Properties
  84. static uint8_t simpleProfileChar3Props = GATT_PROP_WRITE_NO_RSP;
  85. // Characteristic 3 Value
  86. static uint8_t simpleProfileChar3[SIMPLEPROFILE_CHAR3_LEN] = {0};
  87. // Simple Profile Characteristic 3 User Description
  88. static uint8_t simpleProfileChar3UserDesp[] = "Characteristic 3\0";
  89. // Simple Profile Characteristic 4 Properties
  90. static uint8_t simpleProfileChar4Props = GATT_PROP_NOTIFY | GATT_PROP_WRITE;
  91. // Characteristic 4 Value
  92. static uint8_t simpleProfileChar4[SIMPLEPROFILE_CHAR4_LEN] = {0};
  93. // Simple Profile Characteristic 4 Configuration Each client has its own
  94. // instantiation of the Client Characteristic Configuration. Reads of the
  95. // Client Characteristic Configuration only shows the configuration for
  96. // that client and writes only affect the configuration of that client.
  97. static gattCharCfg_t simpleProfileChar4Config[4];
  98. // Simple Profile Characteristic 4 User Description
  99. static uint8_t simpleProfileChar4UserDesp[] = "Characteristic 4\0";
  100. #if(DEBUG == DEBUG_UART_BLE)
  101. // Simple Profile Characteristic 5 Properties
  102. static uint8_t simpleProfileChar5Props = GATT_PROP_NOTIFY | GATT_PROP_WRITE;
  103. // Characteristic 5 Value
  104. static uint8_t simpleProfileChar5[SIMPLEPROFILE_CHAR5_LEN] = {0};
  105. // Simple Profile Characteristic 5 Configuration Each client has its own
  106. // instantiation of the Client Characteristic Configuration. Reads of the
  107. // Client Characteristic Configuration only shows the configuration for
  108. // that client and writes only affect the configuration of that client.
  109. static gattCharCfg_t simpleProfileChar5Config[4];
  110. // Simple Profile Characteristic 5 User Description
  111. static uint8_t simpleProfileChar5UserDesp[] = "Characteristic 5\0";
  112. #endif
  113. /*********************************************************************
  114. * Profile Attributes - Table
  115. */
  116. static gattAttribute_t simpleProfileAttrTbl[] = {
  117. // Simple Profile Service
  118. {
  119. {ATT_BT_UUID_SIZE, primaryServiceUUID}, /* type */
  120. GATT_PERMIT_READ, /* permissions */
  121. 0, /* handle */
  122. (uint8_t *)&simpleProfileService /* pValue */
  123. },
  124. // Characteristic 1 Declaration
  125. {
  126. {ATT_BT_UUID_SIZE, characterUUID},
  127. GATT_PERMIT_READ,
  128. 0,
  129. &simpleProfileChar1Props},
  130. // Characteristic Value 1
  131. {
  132. {ATT_BT_UUID_SIZE, simpleProfilechar1UUID},
  133. GATT_PERMIT_READ | GATT_PERMIT_WRITE,
  134. 0,
  135. simpleProfileChar1},
  136. // Characteristic 1 User Description
  137. {
  138. {ATT_BT_UUID_SIZE, charUserDescUUID},
  139. GATT_PERMIT_READ,
  140. 0,
  141. simpleProfileChar1UserDesp},
  142. // Characteristic 2 Declaration
  143. {
  144. {ATT_BT_UUID_SIZE, characterUUID},
  145. GATT_PERMIT_READ,
  146. 0,
  147. &simpleProfileChar2Props},
  148. // Characteristic Value 2
  149. {
  150. {ATT_BT_UUID_SIZE, simpleProfilechar2UUID},
  151. GATT_PERMIT_READ,
  152. 0,
  153. simpleProfileChar2},
  154. // Characteristic 2 User Description
  155. {
  156. {ATT_BT_UUID_SIZE, charUserDescUUID},
  157. GATT_PERMIT_READ,
  158. 0,
  159. simpleProfileChar2UserDesp},
  160. // Characteristic 3 Declaration
  161. {
  162. {ATT_BT_UUID_SIZE, characterUUID},
  163. GATT_PERMIT_READ,
  164. 0,
  165. &simpleProfileChar3Props},
  166. // Characteristic Value 3
  167. {
  168. {ATT_BT_UUID_SIZE, simpleProfilechar3UUID},
  169. GATT_PERMIT_WRITE,
  170. 0,
  171. simpleProfileChar3},
  172. // Characteristic 3 User Description
  173. {
  174. {ATT_BT_UUID_SIZE, charUserDescUUID},
  175. GATT_PERMIT_READ,
  176. 0,
  177. simpleProfileChar3UserDesp},
  178. // Characteristic 4 Declaration
  179. {
  180. {ATT_BT_UUID_SIZE, characterUUID},
  181. GATT_PERMIT_READ,
  182. 0,
  183. &simpleProfileChar4Props},
  184. // Characteristic Value 4
  185. {
  186. {ATT_BT_UUID_SIZE, simpleProfilechar4UUID},
  187. GATT_PERMIT_WRITE,
  188. 0,
  189. simpleProfileChar4},
  190. // Characteristic 4 configuration
  191. {
  192. {ATT_BT_UUID_SIZE, clientCharCfgUUID},
  193. GATT_PERMIT_READ | GATT_PERMIT_WRITE,
  194. 0,
  195. (uint8_t *)simpleProfileChar4Config},
  196. // Characteristic 4 User Description
  197. {
  198. {ATT_BT_UUID_SIZE, charUserDescUUID},
  199. GATT_PERMIT_READ,
  200. 0,
  201. simpleProfileChar4UserDesp},
  202. #if(DEBUG == DEBUG_UART_BLE)
  203. // Characteristic 5 Declaration
  204. {
  205. {ATT_BT_UUID_SIZE, characterUUID},
  206. GATT_PERMIT_READ,
  207. 0,
  208. &simpleProfileChar5Props},
  209. // Characteristic Value 5
  210. {
  211. {ATT_BT_UUID_SIZE, simpleProfilechar5UUID},
  212. GATT_PERMIT_WRITE,
  213. 0,
  214. simpleProfileChar5},
  215. // Characteristic 5 configuration
  216. {
  217. {ATT_BT_UUID_SIZE, clientCharCfgUUID},
  218. GATT_PERMIT_READ | GATT_PERMIT_WRITE,
  219. 0,
  220. (uint8_t *)simpleProfileChar5Config},
  221. // Characteristic 5 User Description
  222. {
  223. {ATT_BT_UUID_SIZE, charUserDescUUID},
  224. GATT_PERMIT_READ,
  225. 0,
  226. simpleProfileChar5UserDesp},
  227. #endif
  228. };
  229. /*********************************************************************
  230. * LOCAL FUNCTIONS
  231. */
  232. static bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
  233. uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method);
  234. static bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
  235. uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method);
  236. static void simpleProfile_HandleConnStatusCB(uint16_t connHandle, uint8_t changeType);
  237. /*********************************************************************
  238. * PROFILE CALLBACKS
  239. */
  240. // Simple Profile Service Callbacks
  241. gattServiceCBs_t simpleProfileCBs = {
  242. simpleProfile_ReadAttrCB, // Read callback function pointer
  243. simpleProfile_WriteAttrCB, // Write callback function pointer
  244. NULL // Authorization callback function pointer
  245. };
  246. /*********************************************************************
  247. * PUBLIC FUNCTIONS
  248. */
  249. /*********************************************************************
  250. * @fn SimpleProfile_AddService
  251. *
  252. * @brief Initializes the Simple Profile service by registering
  253. * GATT attributes with the GATT server.
  254. *
  255. * @param services - services to add. This is a bit map and can
  256. * contain more than one service.
  257. *
  258. * @return Success or Failure
  259. */
  260. bStatus_t SimpleProfile_AddService(uint32_t services)
  261. {
  262. uint8_t status = SUCCESS;
  263. // Initialize Client Characteristic Configuration attributes
  264. GATTServApp_InitCharCfg(INVALID_CONNHANDLE, simpleProfileChar4Config);
  265. #if(DEBUG == DEBUG_UART_BLE)
  266. GATTServApp_InitCharCfg(INVALID_CONNHANDLE, simpleProfileChar5Config);
  267. #endif
  268. // Register with Link DB to receive link status change callback
  269. linkDB_Register(simpleProfile_HandleConnStatusCB);
  270. if(services & SIMPLEPROFILE_SERVICE)
  271. {
  272. // Register GATT attribute list and CBs with GATT Server App
  273. status = GATTServApp_RegisterService(simpleProfileAttrTbl,
  274. GATT_NUM_ATTRS(simpleProfileAttrTbl),
  275. GATT_MAX_ENCRYPT_KEY_SIZE,
  276. &simpleProfileCBs);
  277. }
  278. return (status);
  279. }
  280. /*********************************************************************
  281. * @fn SimpleProfile_RegisterAppCBs
  282. *
  283. * @brief Registers the application callback function. Only call
  284. * this function once.
  285. *
  286. * @param callbacks - pointer to application callbacks.
  287. *
  288. * @return SUCCESS or bleAlreadyInRequestedMode
  289. */
  290. bStatus_t SimpleProfile_RegisterAppCBs(simpleProfileCBs_t *appCallbacks)
  291. {
  292. if(appCallbacks)
  293. {
  294. simpleProfile_AppCBs = appCallbacks;
  295. return (SUCCESS);
  296. }
  297. else
  298. {
  299. return (bleAlreadyInRequestedMode);
  300. }
  301. }
  302. /*********************************************************************
  303. * @fn SimpleProfile_SetParameter
  304. *
  305. * @brief Set a Simple Profile parameter.
  306. *
  307. * @param param - Profile parameter ID
  308. * @param len - length of data to right
  309. * @param value - pointer to data to write. This is dependent on
  310. * the parameter ID and WILL be cast to the appropriate
  311. * data type (example: data type of uint16_t will be cast to
  312. * uint16_t pointer).
  313. *
  314. * @return bStatus_t
  315. */
  316. bStatus_t SimpleProfile_SetParameter(uint8_t param, uint16_t len, void *value)
  317. {
  318. bStatus_t ret = SUCCESS;
  319. switch(param)
  320. {
  321. case SIMPLEPROFILE_CHAR1:
  322. if(len == SIMPLEPROFILE_CHAR1_LEN)
  323. {
  324. tmos_memcpy(simpleProfileChar1, value, SIMPLEPROFILE_CHAR1_LEN);
  325. }
  326. else
  327. {
  328. ret = bleInvalidRange;
  329. }
  330. break;
  331. case SIMPLEPROFILE_CHAR2:
  332. if(len == SIMPLEPROFILE_CHAR2_LEN)
  333. {
  334. tmos_memcpy(simpleProfileChar2, value, SIMPLEPROFILE_CHAR2_LEN);
  335. }
  336. else
  337. {
  338. ret = bleInvalidRange;
  339. }
  340. break;
  341. case SIMPLEPROFILE_CHAR3:
  342. if(len == SIMPLEPROFILE_CHAR3_LEN)
  343. {
  344. tmos_memcpy(simpleProfileChar3, value, SIMPLEPROFILE_CHAR3_LEN);
  345. }
  346. else
  347. {
  348. ret = bleInvalidRange;
  349. }
  350. break;
  351. case SIMPLEPROFILE_CHAR4:
  352. if(len == SIMPLEPROFILE_CHAR4_LEN)
  353. {
  354. tmos_memcpy(simpleProfileChar4, value, SIMPLEPROFILE_CHAR4_LEN);
  355. }
  356. else
  357. {
  358. ret = bleInvalidRange;
  359. }
  360. break;
  361. #if(DEBUG == DEBUG_UART_BLE)
  362. case SIMPLEPROFILE_CHAR5:
  363. if(len == SIMPLEPROFILE_CHAR5_LEN)
  364. {
  365. tmos_memcpy(simpleProfileChar5, value, SIMPLEPROFILE_CHAR5_LEN);
  366. }
  367. else
  368. {
  369. ret = bleInvalidRange;
  370. }
  371. break;
  372. #endif
  373. default:
  374. ret = INVALIDPARAMETER;
  375. break;
  376. }
  377. return (ret);
  378. }
  379. /*********************************************************************
  380. * @fn SimpleProfile_GetParameter
  381. *
  382. * @brief Get a Simple Profile parameter.
  383. *
  384. * @param param - Profile parameter ID
  385. * @param value - pointer to data to put. This is dependent on
  386. * the parameter ID and WILL be cast to the appropriate
  387. * data type (example: data type of uint16_t will be cast to
  388. * uint16_t pointer).
  389. *
  390. * @return bStatus_t
  391. */
  392. bStatus_t SimpleProfile_GetParameter(uint8_t param, void *value)
  393. {
  394. bStatus_t ret = SUCCESS;
  395. switch(param)
  396. {
  397. case SIMPLEPROFILE_CHAR1:
  398. tmos_memcpy(value, simpleProfileChar1, SIMPLEPROFILE_CHAR1_LEN);
  399. break;
  400. case SIMPLEPROFILE_CHAR2:
  401. tmos_memcpy(value, simpleProfileChar2, SIMPLEPROFILE_CHAR2_LEN);
  402. break;
  403. case SIMPLEPROFILE_CHAR3:
  404. tmos_memcpy(value, simpleProfileChar3, SIMPLEPROFILE_CHAR3_LEN);
  405. break;
  406. case SIMPLEPROFILE_CHAR4:
  407. tmos_memcpy(value, simpleProfileChar4, SIMPLEPROFILE_CHAR4_LEN);
  408. break;
  409. #if(DEBUG == DEBUG_UART_BLE)
  410. case SIMPLEPROFILE_CHAR5:
  411. tmos_memcpy(value, simpleProfileChar5, SIMPLEPROFILE_CHAR5_LEN);
  412. break;
  413. #endif
  414. default:
  415. ret = INVALIDPARAMETER;
  416. break;
  417. }
  418. return (ret);
  419. }
  420. /*********************************************************************
  421. * @fn simpleProfileChar4_Notify
  422. *
  423. * @brief Send a notification containing a heart rate
  424. * measurement.
  425. *
  426. * @param connHandle - connection handle
  427. * @param pNoti - pointer to notification structure
  428. *
  429. * @return Success or Failure
  430. */
  431. bStatus_t simpleProfileChar4_Notify(uint16_t connHandle, attHandleValueNoti_t *pNoti)
  432. {
  433. uint16_t value = GATTServApp_ReadCharCfg(connHandle, simpleProfileChar4Config);
  434. // If notifications enabled
  435. if(value & GATT_CLIENT_CFG_NOTIFY)
  436. {
  437. // Set the handle
  438. pNoti->handle = simpleProfileAttrTbl[SIMPLEPROFILE_CHAR4_VALUE_POS].handle;
  439. // Send the notification
  440. return GATT_Notification(connHandle, pNoti, FALSE);
  441. }
  442. return bleIncorrectMode;
  443. }
  444. #if(DEBUG == DEBUG_UART_BLE)
  445. /*********************************************************************
  446. * @fn simpleProfileChar5_Notify
  447. *
  448. * @brief Send a notification containing a heart rate
  449. * measurement.
  450. *
  451. * @param connHandle - connection handle
  452. * @param pNoti - pointer to notification structure
  453. *
  454. * @return Success or Failure
  455. */
  456. bStatus_t simpleProfileChar5_Notify(uint16_t connHandle, attHandleValueNoti_t *pNoti)
  457. {
  458. uint16_t value = GATTServApp_ReadCharCfg(connHandle, simpleProfileChar5Config);
  459. // If notifications enabled
  460. if(value & GATT_CLIENT_CFG_NOTIFY)
  461. {
  462. // Set the handle
  463. pNoti->handle = simpleProfileAttrTbl[SIMPLEPROFILE_CHAR5_VALUE_POS].handle;
  464. // Send the notification
  465. return GATT_Notification(connHandle, pNoti, FALSE);
  466. }
  467. return bleIncorrectMode;
  468. }
  469. #endif
  470. /*********************************************************************
  471. * @fn simpleProfile_ReadAttrCB
  472. *
  473. * @brief Read an attribute.
  474. *
  475. * @param connHandle - connection message was received on
  476. * @param pAttr - pointer to attribute
  477. * @param pValue - pointer to data to be read
  478. * @param pLen - length of data to be read
  479. * @param offset - offset of the first octet to be read
  480. * @param maxLen - maximum length of data to be read
  481. *
  482. * @return Success or Failure
  483. */
  484. static bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
  485. uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method)
  486. {
  487. bStatus_t status = SUCCESS;
  488. // Make sure it's not a blob operation (no attributes in the profile are long)
  489. if(offset > 0)
  490. {
  491. return (ATT_ERR_ATTR_NOT_LONG);
  492. }
  493. if(pAttr->type.len == ATT_BT_UUID_SIZE)
  494. {
  495. // 16-bit UUID
  496. uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
  497. switch(uuid)
  498. {
  499. // No need for "GATT_SERVICE_UUID" or "GATT_CLIENT_CHAR_CFG_UUID" cases;
  500. // gattserverapp handles those reads
  501. // characteristics 1 and 2 have read permissions
  502. // characteritisc 3 does not have read permissions; therefore it is not
  503. // included here
  504. // characteristic 4 does not have read permissions, but because it
  505. // can be sent as a notification, it is included here
  506. case SIMPLEPROFILE_CHAR1_UUID:
  507. if(maxLen > SIMPLEPROFILE_CHAR1_LEN)
  508. {
  509. *pLen = SIMPLEPROFILE_CHAR1_LEN;
  510. }
  511. else
  512. {
  513. *pLen = maxLen;
  514. }
  515. tmos_memcpy(pValue, pAttr->pValue, *pLen);
  516. break;
  517. case SIMPLEPROFILE_CHAR2_UUID:
  518. if(maxLen > SIMPLEPROFILE_CHAR2_LEN)
  519. {
  520. *pLen = SIMPLEPROFILE_CHAR2_LEN;
  521. }
  522. else
  523. {
  524. *pLen = maxLen;
  525. }
  526. tmos_memcpy(pValue, pAttr->pValue, *pLen);
  527. break;
  528. case SIMPLEPROFILE_CHAR4_UUID:
  529. if(maxLen > SIMPLEPROFILE_CHAR4_LEN)
  530. {
  531. *pLen = SIMPLEPROFILE_CHAR4_LEN;
  532. }
  533. else
  534. {
  535. *pLen = maxLen;
  536. }
  537. tmos_memcpy(pValue, pAttr->pValue, *pLen);
  538. break;
  539. #if(DEBUG == DEBUG_UART_BLE)
  540. case SIMPLEPROFILE_CHAR5_UUID:
  541. if(maxLen > SIMPLEPROFILE_CHAR5_LEN)
  542. {
  543. *pLen = SIMPLEPROFILE_CHAR5_LEN;
  544. }
  545. else
  546. {
  547. *pLen = maxLen;
  548. }
  549. tmos_memcpy(pValue, pAttr->pValue, *pLen);
  550. break;
  551. #endif
  552. default:
  553. // Should never get here! (characteristics 3 and 4 do not have read permissions)
  554. *pLen = 0;
  555. status = ATT_ERR_ATTR_NOT_FOUND;
  556. break;
  557. }
  558. }
  559. else
  560. {
  561. // 128-bit UUID
  562. *pLen = 0;
  563. status = ATT_ERR_INVALID_HANDLE;
  564. }
  565. return (status);
  566. }
  567. /*********************************************************************
  568. * @fn simpleProfile_WriteAttrCB
  569. *
  570. * @brief Validate attribute data prior to a write operation
  571. *
  572. * @param connHandle - connection message was received on
  573. * @param pAttr - pointer to attribute
  574. * @param pValue - pointer to data to be written
  575. * @param len - length of data
  576. * @param offset - offset of the first octet to be written
  577. *
  578. * @return Success or Failure
  579. */
  580. static bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
  581. uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method)
  582. {
  583. bStatus_t status = SUCCESS;
  584. uint8_t notifyApp = 0xFF;
  585. // If attribute permissions require authorization to write, return error
  586. if(gattPermitAuthorWrite(pAttr->permissions))
  587. {
  588. // Insufficient authorization
  589. return (ATT_ERR_INSUFFICIENT_AUTHOR);
  590. }
  591. if(pAttr->type.len == ATT_BT_UUID_SIZE)
  592. {
  593. // 16-bit UUID
  594. uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
  595. switch(uuid)
  596. {
  597. case SIMPLEPROFILE_CHAR1_UUID:
  598. //Validate the value
  599. // Make sure it's not a blob oper
  600. if(offset == 0)
  601. {
  602. if(len > SIMPLEPROFILE_CHAR1_LEN)
  603. {
  604. status = ATT_ERR_INVALID_VALUE_SIZE;
  605. }
  606. }
  607. else
  608. {
  609. status = ATT_ERR_ATTR_NOT_LONG;
  610. }
  611. //Write the value
  612. if(status == SUCCESS)
  613. {
  614. tmos_memcpy(pAttr->pValue, pValue, SIMPLEPROFILE_CHAR1_LEN);
  615. notifyApp = SIMPLEPROFILE_CHAR1;
  616. }
  617. break;
  618. case SIMPLEPROFILE_CHAR3_UUID:
  619. //Validate the value
  620. // Make sure it's not a blob oper
  621. if(offset == 0)
  622. {
  623. if(len > SIMPLEPROFILE_CHAR3_LEN)
  624. {
  625. status = ATT_ERR_INVALID_VALUE_SIZE;
  626. }
  627. }
  628. else
  629. {
  630. status = ATT_ERR_ATTR_NOT_LONG;
  631. }
  632. //Write the value
  633. if(status == SUCCESS)
  634. {
  635. tmos_memcpy(pAttr->pValue, pValue, SIMPLEPROFILE_CHAR3_LEN);
  636. notifyApp = SIMPLEPROFILE_CHAR3;
  637. }
  638. break;
  639. case SIMPLEPROFILE_CHAR4_UUID:
  640. //Validate the value
  641. // Make sure it's not a blob oper
  642. if(offset == 0)
  643. {
  644. if(len > SIMPLEPROFILE_CHAR4_LEN)
  645. {
  646. status = ATT_ERR_INVALID_VALUE_SIZE;
  647. }
  648. }
  649. else
  650. {
  651. status = ATT_ERR_ATTR_NOT_LONG;
  652. }
  653. //Write the value
  654. if(status == SUCCESS)
  655. {
  656. tmos_memcpy(pAttr->pValue, pValue, SIMPLEPROFILE_CHAR4_LEN);
  657. notifyApp = SIMPLEPROFILE_CHAR4;
  658. }
  659. break;
  660. #if(DEBUG == DEBUG_UART_BLE)
  661. case SIMPLEPROFILE_CHAR5_UUID:
  662. //Validate the value
  663. // Make sure it's not a blob oper
  664. if(offset == 0)
  665. {
  666. if(len > SIMPLEPROFILE_CHAR5_LEN)
  667. {
  668. status = ATT_ERR_INVALID_VALUE_SIZE;
  669. }
  670. }
  671. else
  672. {
  673. status = ATT_ERR_ATTR_NOT_LONG;
  674. }
  675. //Write the value
  676. if(status == SUCCESS)
  677. {
  678. tmos_memcpy(pAttr->pValue, pValue, SIMPLEPROFILE_CHAR5_LEN);
  679. notifyApp = SIMPLEPROFILE_CHAR5;
  680. }
  681. break;
  682. #endif
  683. case GATT_CLIENT_CHAR_CFG_UUID:
  684. status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len,
  685. offset, GATT_CLIENT_CFG_NOTIFY);
  686. break;
  687. default:
  688. // Should never get here! (characteristics 2 and 4 do not have write permissions)
  689. status = ATT_ERR_ATTR_NOT_FOUND;
  690. break;
  691. }
  692. }
  693. else
  694. {
  695. // 128-bit UUID
  696. status = ATT_ERR_INVALID_HANDLE;
  697. }
  698. // If a charactersitic value changed then callback function to notify application of change
  699. if((notifyApp != 0xFF) && simpleProfile_AppCBs && simpleProfile_AppCBs->pfnSimpleProfileChange)
  700. {
  701. simpleProfile_AppCBs->pfnSimpleProfileChange(notifyApp, pValue, len);
  702. }
  703. return (status);
  704. }
  705. /*********************************************************************
  706. * @fn simpleProfile_HandleConnStatusCB
  707. *
  708. * @brief Simple Profile link status change handler function.
  709. *
  710. * @param connHandle - connection handle
  711. * @param changeType - type of change
  712. *
  713. * @return none
  714. */
  715. static void simpleProfile_HandleConnStatusCB(uint16_t connHandle, uint8_t changeType)
  716. {
  717. // Make sure this is not loopback connection
  718. if(connHandle != LOOPBACK_CONNHANDLE)
  719. {
  720. // Reset Client Char Config if connection has dropped
  721. if((changeType == LINKDB_STATUS_UPDATE_REMOVED) ||
  722. ((changeType == LINKDB_STATUS_UPDATE_STATEFLAGS) &&
  723. (!linkDB_Up(connHandle))))
  724. {
  725. GATTServApp_InitCharCfg(connHandle, simpleProfileChar4Config);
  726. #if(DEBUG == DEBUG_UART_BLE)
  727. GATTServApp_InitCharCfg(connHandle, simpleProfileChar5Config);
  728. #endif
  729. }
  730. }
  731. }
  732. /*********************************************************************
  733. *********************************************************************/