ancs_attr_parser.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /**
  2. * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. /* Disclaimer: This client implementation of the Apple Notification Center Service can and will be changed at any time by Nordic Semiconductor ASA.
  41. * Server implementations such as the ones found in iOS can be changed at any time by Apple and may cause this client implementation to stop working.
  42. */
  43. #include "nrf_ble_ancs_c.h"
  44. #include "ancs_attr_parser.h"
  45. #include "nrf_log.h"
  46. static bool all_req_attrs_parsed(ble_ancs_c_t * p_ancs)
  47. {
  48. if (p_ancs->parse_info.expected_number_of_attrs == 0)
  49. {
  50. return true;
  51. }
  52. return false;
  53. }
  54. static bool attr_is_requested(ble_ancs_c_t * p_ancs, ble_ancs_c_attr_t attr)
  55. {
  56. if (p_ancs->parse_info.p_attr_list[attr.attr_id].get == true)
  57. {
  58. return true;
  59. }
  60. return false;
  61. }
  62. /**@brief Function for parsing command id and notification id.
  63. * Used in the @ref parse_get_notif_attrs_response state machine.
  64. *
  65. * @details UID and command ID will be received only once at the beginning of the first
  66. * GATTC notification of a new attribute request for a given iOS notification.
  67. *
  68. * @param[in] p_ancs Pointer to an ANCS instance to which the event belongs.
  69. * @param[in] p_data_src Pointer to data that was received from the Notification Provider.
  70. * @param[in] index Pointer to an index that helps us keep track of the current data to be parsed.
  71. *
  72. * @return The next parse state.
  73. */
  74. static ble_ancs_c_parse_state_t command_id_parse(ble_ancs_c_t * p_ancs,
  75. const uint8_t * p_data_src,
  76. uint32_t * index)
  77. {
  78. ble_ancs_c_parse_state_t parse_state;
  79. p_ancs->parse_info.command_id = (ble_ancs_c_cmd_id_val_t) p_data_src[(*index)++];
  80. switch (p_ancs->parse_info.command_id)
  81. {
  82. case BLE_ANCS_COMMAND_ID_GET_NOTIF_ATTRIBUTES:
  83. p_ancs->evt.evt_type = BLE_ANCS_C_EVT_NOTIF_ATTRIBUTE;
  84. p_ancs->parse_info.p_attr_list = p_ancs->ancs_notif_attr_list;
  85. p_ancs->parse_info.nb_of_attr = BLE_ANCS_NB_OF_NOTIF_ATTR;
  86. parse_state = NOTIF_UID;
  87. break;
  88. case BLE_ANCS_COMMAND_ID_GET_APP_ATTRIBUTES:
  89. p_ancs->evt.evt_type = BLE_ANCS_C_EVT_APP_ATTRIBUTE;
  90. p_ancs->parse_info.p_attr_list = p_ancs->ancs_app_attr_list;
  91. p_ancs->parse_info.nb_of_attr = BLE_ANCS_NB_OF_APP_ATTR;
  92. parse_state = APP_ID;
  93. break;
  94. default:
  95. //no valid command_id, abort the rest of the parsing procedure.
  96. NRF_LOG_DEBUG("Invalid Command ID");
  97. parse_state = DONE;
  98. break;
  99. }
  100. return parse_state;
  101. }
  102. static ble_ancs_c_parse_state_t notif_uid_parse(ble_ancs_c_t * p_ancs,
  103. const uint8_t * p_data_src,
  104. uint32_t * index)
  105. {
  106. p_ancs->evt.notif_uid = uint32_decode(&p_data_src[*index]);
  107. *index += sizeof(uint32_t);
  108. return ATTR_ID;
  109. }
  110. static ble_ancs_c_parse_state_t app_id_parse(ble_ancs_c_t * p_ancs,
  111. const uint8_t * p_data_src,
  112. uint32_t * index)
  113. {
  114. p_ancs->evt.app_id[p_ancs->parse_info.current_app_id_index] = p_data_src[(*index)++];
  115. if (p_ancs->evt.app_id[p_ancs->parse_info.current_app_id_index] != '\0')
  116. {
  117. p_ancs->parse_info.current_app_id_index++;
  118. return APP_ID;
  119. }
  120. else
  121. {
  122. return ATTR_ID;
  123. }
  124. }
  125. /**@brief Function for parsing the id of an iOS attribute.
  126. * Used in the @ref parse_get_notif_attrs_response state machine.
  127. *
  128. * @details We only request attributes that are registered with @ref ble_ancs_c_attr_add
  129. * once they have been reveiced we stop parsing.
  130. *
  131. * @param[in] p_ancs Pointer to an ANCS instance to which the event belongs.
  132. * @param[in] p_data_src Pointer to data that was received from the Notification Provider.
  133. * @param[in] index Pointer to an index that helps us keep track of the current data to be parsed.
  134. *
  135. * @return The next parse state.
  136. */
  137. static ble_ancs_c_parse_state_t attr_id_parse(ble_ancs_c_t * p_ancs,
  138. const uint8_t * p_data_src,
  139. uint32_t * index)
  140. {
  141. p_ancs->evt.attr.attr_id = p_data_src[(*index)++];
  142. if (p_ancs->evt.attr.attr_id >= p_ancs->parse_info.nb_of_attr)
  143. {
  144. NRF_LOG_DEBUG("Attribute ID Invalid.");
  145. return DONE;
  146. }
  147. p_ancs->evt.attr.p_attr_data = p_ancs->parse_info.p_attr_list[p_ancs->evt.attr.attr_id].p_attr_data;
  148. if (all_req_attrs_parsed(p_ancs))
  149. {
  150. NRF_LOG_DEBUG("All requested attributes received. ");
  151. return DONE;
  152. }
  153. else
  154. {
  155. if (attr_is_requested(p_ancs, p_ancs->evt.attr))
  156. {
  157. p_ancs->parse_info.expected_number_of_attrs--;
  158. }
  159. NRF_LOG_DEBUG("Attribute ID %i ", p_ancs->evt.attr.attr_id);
  160. return ATTR_LEN1;
  161. }
  162. }
  163. /**@brief Function for parsing the length of an iOS attribute.
  164. * Used in the @ref parse_get_notif_attrs_response state machine.
  165. *
  166. * @details The Length is 2 bytes. Since there is a chance we reveice the bytes in two different
  167. * GATTC notifications, we parse only the first byte here and then set the state machine
  168. * ready to parse the next byte.
  169. *
  170. * @param[in] p_ancs Pointer to an ANCS instance to which the event belongs.
  171. * @param[in] p_data_src Pointer to data that was received from the Notification Provider.
  172. * @param[in] index Pointer to an index that helps us keep track of the current data to be parsed.
  173. *
  174. * @return The next parse state.
  175. */
  176. static ble_ancs_c_parse_state_t attr_len1_parse(ble_ancs_c_t * p_ancs, const uint8_t * p_data_src, uint32_t * index)
  177. {
  178. p_ancs->evt.attr.attr_len = p_data_src[(*index)++];
  179. return ATTR_LEN2;
  180. }
  181. /**@brief Function for parsing the length of an iOS attribute.
  182. * Used in the @ref parse_get_notif_attrs_response state machine.
  183. *
  184. * @details Second byte of the length field. If the length is zero, it means that the attribute is not
  185. * present and the state machine is set to parse the next attribute.
  186. *
  187. * @param[in] p_ancs Pointer to an ANCS instance to which the event belongs.
  188. * @param[in] p_data_src Pointer to data that was received from the Notification Provider.
  189. * @param[in] index Pointer to an index that helps us keep track of the current data to be parsed.
  190. *
  191. * @return The next parse state.
  192. */
  193. static ble_ancs_c_parse_state_t attr_len2_parse(ble_ancs_c_t * p_ancs, const uint8_t * p_data_src, uint32_t * index)
  194. {
  195. p_ancs->evt.attr.attr_len |= (p_data_src[(*index)++] << 8);
  196. p_ancs->parse_info.current_attr_index = 0;
  197. if (p_ancs->evt.attr.attr_len != 0)
  198. {
  199. //If the attribute has a length but there is no allocated space for this attribute
  200. if ((p_ancs->parse_info.p_attr_list[p_ancs->evt.attr.attr_id].attr_len == 0) ||
  201. (p_ancs->parse_info.p_attr_list[p_ancs->evt.attr.attr_id].p_attr_data == NULL))
  202. {
  203. return ATTR_SKIP;
  204. }
  205. else
  206. {
  207. return ATTR_DATA;
  208. }
  209. }
  210. else
  211. {
  212. NRF_LOG_DEBUG("Attribute LEN %i ", p_ancs->evt.attr.attr_len);
  213. if (attr_is_requested(p_ancs, p_ancs->evt.attr))
  214. {
  215. p_ancs->evt_handler(&p_ancs->evt);
  216. }
  217. if (all_req_attrs_parsed(p_ancs))
  218. {
  219. return DONE;
  220. }
  221. else
  222. {
  223. return ATTR_ID;
  224. }
  225. }
  226. }
  227. /**@brief Function for parsing the data of an iOS attribute.
  228. * Used in the @ref parse_get_notif_attrs_response state machine.
  229. *
  230. * @details Read the data of the attribute into our local buffer.
  231. *
  232. * @param[in] p_ancs Pointer to an ANCS instance to which the event belongs.
  233. * @param[in] p_data_src Pointer to data that was received from the Notification Provider.
  234. * @param[in] index Pointer to an index that helps us keep track of the current data to be parsed.
  235. *
  236. * @return The next parse state.
  237. */
  238. static ble_ancs_c_parse_state_t attr_data_parse(ble_ancs_c_t * p_ancs,
  239. const uint8_t * p_data_src,
  240. uint32_t * index)
  241. {
  242. // We have not reached the end of the attribute, nor our max allocated internal size.
  243. // Proceed with copying data over to our buffer.
  244. if ( (p_ancs->parse_info.current_attr_index < p_ancs->parse_info.p_attr_list[p_ancs->evt.attr.attr_id].attr_len)
  245. && (p_ancs->parse_info.current_attr_index < p_ancs->evt.attr.attr_len))
  246. {
  247. //NRF_LOG_DEBUG("Byte copied to buffer: %c", p_data_src[(*index)]); // Un-comment this line to see every byte of an attribute as it is parsed. Commented out by default since it can overflow the uart buffer.
  248. p_ancs->evt.attr.p_attr_data[p_ancs->parse_info.current_attr_index++] = p_data_src[(*index)++];
  249. }
  250. // We have reached the end of the attribute, or our max allocated internal size.
  251. // Stop copying data over to our buffer. NUL-terminate at the current index.
  252. if ( (p_ancs->parse_info.current_attr_index == p_ancs->evt.attr.attr_len) ||
  253. (p_ancs->parse_info.current_attr_index == p_ancs->parse_info.p_attr_list[p_ancs->evt.attr.attr_id].attr_len - 1))
  254. {
  255. if (attr_is_requested(p_ancs, p_ancs->evt.attr))
  256. {
  257. p_ancs->evt.attr.p_attr_data[p_ancs->parse_info.current_attr_index] = '\0';
  258. }
  259. // If our max buffer size is smaller than the remaining attribute data, we must
  260. // increase index to skip the data until the start of the next attribute.
  261. if (p_ancs->parse_info.current_attr_index < p_ancs->evt.attr.attr_len)
  262. {
  263. return ATTR_SKIP;
  264. }
  265. NRF_LOG_DEBUG("Attribute finished!");
  266. if (attr_is_requested(p_ancs, p_ancs->evt.attr))
  267. {
  268. p_ancs->evt_handler(&p_ancs->evt);
  269. }
  270. if (all_req_attrs_parsed(p_ancs))
  271. {
  272. return DONE;
  273. }
  274. else
  275. {
  276. return ATTR_ID;
  277. }
  278. }
  279. return ATTR_DATA;
  280. }
  281. static ble_ancs_c_parse_state_t attr_skip(ble_ancs_c_t * p_ancs, const uint8_t * p_data_src, uint32_t * index)
  282. {
  283. // We have not reached the end of the attribute, nor our max allocated internal size.
  284. // Proceed with copying data over to our buffer.
  285. if (p_ancs->parse_info.current_attr_index < p_ancs->evt.attr.attr_len)
  286. {
  287. p_ancs->parse_info.current_attr_index++;
  288. (*index)++;
  289. }
  290. // At the end of the attribute, determine if it should be passed to event handler and
  291. // continue parsing the next attribute ID if we are not done with all the attributes.
  292. if (p_ancs->parse_info.current_attr_index == p_ancs->evt.attr.attr_len)
  293. {
  294. if (attr_is_requested(p_ancs, p_ancs->evt.attr))
  295. {
  296. p_ancs->evt_handler(&p_ancs->evt);
  297. }
  298. if (all_req_attrs_parsed(p_ancs))
  299. {
  300. return DONE;
  301. }
  302. else
  303. {
  304. return ATTR_ID;
  305. }
  306. }
  307. return ATTR_SKIP;
  308. }
  309. void ancs_parse_get_attrs_response(ble_ancs_c_t * p_ancs,
  310. const uint8_t * p_data_src,
  311. const uint16_t hvx_data_len)
  312. {
  313. uint32_t index;
  314. for (index = 0; index < hvx_data_len;)
  315. {
  316. switch (p_ancs->parse_info.parse_state)
  317. {
  318. case COMMAND_ID:
  319. p_ancs->parse_info.parse_state = command_id_parse(p_ancs, p_data_src, &index);
  320. break;
  321. case NOTIF_UID:
  322. p_ancs->parse_info.parse_state = notif_uid_parse(p_ancs, p_data_src, &index);
  323. break;
  324. case APP_ID:
  325. p_ancs->parse_info.parse_state = app_id_parse(p_ancs, p_data_src, &index);
  326. break;
  327. case ATTR_ID:
  328. p_ancs->parse_info.parse_state = attr_id_parse(p_ancs, p_data_src, &index);
  329. break;
  330. case ATTR_LEN1:
  331. p_ancs->parse_info.parse_state = attr_len1_parse(p_ancs, p_data_src, &index);
  332. break;
  333. case ATTR_LEN2:
  334. p_ancs->parse_info.parse_state = attr_len2_parse(p_ancs, p_data_src, &index);
  335. break;
  336. case ATTR_DATA:
  337. p_ancs->parse_info.parse_state = attr_data_parse(p_ancs, p_data_src, &index);
  338. break;
  339. case ATTR_SKIP:
  340. p_ancs->parse_info.parse_state = attr_skip(p_ancs, p_data_src, &index);
  341. break;
  342. case DONE:
  343. NRF_LOG_DEBUG("Parse state: Done ");
  344. index = hvx_data_len;
  345. break;
  346. default:
  347. // Default case will never trigger intentionally. Go to the DONE state to minimize the consequences.
  348. p_ancs->parse_info.parse_state = DONE;
  349. break;
  350. }
  351. }
  352. }