peer_database.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. /* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
  2. *
  3. * The information contained herein is property of Nordic Semiconductor ASA.
  4. * Terms and conditions of usage are described in detail in NORDIC
  5. * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
  6. *
  7. * Licensees are granted free, non-transferable use of the information. NO
  8. * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
  9. * the file.
  10. *
  11. */
  12. #include "peer_database.h"
  13. #include <string.h>
  14. #include "app_util.h"
  15. #include "peer_manager_types.h"
  16. #include "peer_manager_internal.h"
  17. #include "peer_data_storage.h"
  18. #include "pm_buffer.h"
  19. #include "sdk_common.h"
  20. #define MAX_REGISTRANTS 6 /**< The number of user that can register with the module. */
  21. #define N_WRITE_BUFFERS 8 /**< The number of write buffers available. */
  22. #define N_WRITE_BUFFER_RECORDS (N_WRITE_BUFFERS) /**< The number of write buffer records. */
  23. /**@brief Macro for verifying that the data ID is among the values eligible for using the write buffer.
  24. *
  25. * @param[in] data_id The data ID to verify.
  26. */
  27. #define VERIFY_DATA_ID_WRITE_BUF(data_id) \
  28. do \
  29. { \
  30. if (((data_id) != PM_PEER_DATA_ID_BONDING) && ((data_id) != PM_PEER_DATA_ID_GATT_LOCAL)) \
  31. { \
  32. return NRF_ERROR_INVALID_PARAM; \
  33. } \
  34. } while(0)
  35. /**@brief Struct for keeping track of one write buffer, from allocation, until it is fully written
  36. * or cancelled.
  37. */
  38. typedef struct
  39. {
  40. pm_peer_id_t peer_id; /**< The peer ID this buffer belongs to. */
  41. pm_peer_data_id_t data_id; /**< The data ID this buffer belongs to. */
  42. uint8_t buffer_block_id; /**< The index of the first (or only) buffer block containing peer data. */
  43. uint32_t n_bufs; /**< The number of buffer blocks containing peer data. */
  44. uint8_t store_busy : 1; /**< Flag indicating that the buffer was attempted written to flash, but a busy error was returned and the operation should be retried. */
  45. uint8_t store_flash_full : 1; /**< Flag indicating that the buffer was attempted written to flash, but a flash full error was returned and the operation should be retried after room has been made. */
  46. uint8_t store_requested : 1; /**< Flag indicating that the buffer is being written to flash. */
  47. pm_prepare_token_t prepare_token; /**< Token given by Peer Data Storage if room in flash has been reserved. */
  48. pm_store_token_t store_token; /**< Token given by Peer Data Storage when a flash write has been successfully requested. */
  49. } pdb_buffer_record_t;
  50. /**@brief Struct for keeping track of the state of the module.
  51. */
  52. typedef struct
  53. {
  54. pdb_evt_handler_t evt_handlers[MAX_REGISTRANTS]; /**< All registered event handlers. */
  55. uint8_t n_registrants; /**< The number of registered event handlers. */
  56. pm_buffer_t write_buffer; /**< The state of the write buffer. */
  57. pdb_buffer_record_t write_buffer_records[N_WRITE_BUFFER_RECORDS]; /**< The available write buffer records. */
  58. uint32_t n_writes; /**< The number of pending (Not yet successfully requested in Peer Data Storage) store operations. */
  59. } pdb_t;
  60. static pdb_t m_pdb = {.n_registrants = 0}; /**< The state of the module. */
  61. #define MODULE_INITIALIZED (m_pdb.n_registrants > 0) /**< Expression which is true when the module is initialized. */
  62. #include "sdk_macros.h"
  63. /**@brief Function for invalidating a record of a write buffer allocation.
  64. *
  65. * @param[in] p_record The record to invalidate.
  66. */
  67. static void write_buffer_record_invalidate(pdb_buffer_record_t * p_record)
  68. {
  69. p_record->peer_id = PM_PEER_ID_INVALID;
  70. p_record->data_id = PM_PEER_DATA_ID_INVALID;
  71. p_record->buffer_block_id = BUFFER_INVALID_ID;
  72. p_record->store_busy = false;
  73. p_record->store_flash_full = false;
  74. p_record->store_requested = false;
  75. p_record->n_bufs = 0;
  76. p_record->prepare_token = PDS_PREPARE_TOKEN_INVALID;
  77. p_record->store_token = PM_STORE_TOKEN_INVALID;
  78. }
  79. /**@brief Function for finding a record of a write buffer allocation.
  80. *
  81. * @param[in] peer_id The peer ID in the record.
  82. * @param[inout] p_index In: The starting index, out: The index of the record
  83. *
  84. * @return A pointer to the matching record, or NULL if none was found.
  85. */
  86. static pdb_buffer_record_t * write_buffer_record_find_next(pm_peer_id_t peer_id, int * p_index)
  87. {
  88. for (uint32_t i = *p_index; i < N_WRITE_BUFFER_RECORDS; i++)
  89. {
  90. if ((m_pdb.write_buffer_records[i].peer_id == peer_id))
  91. {
  92. return &m_pdb.write_buffer_records[i];
  93. }
  94. }
  95. return NULL;
  96. }
  97. /**@brief Function for finding a record of a write buffer allocation.
  98. *
  99. * @param[in] peer_id The peer ID in the record.
  100. * @param[in] data_id The data ID in the record.
  101. *
  102. * @return A pointer to the matching record, or NULL if none was found.
  103. */
  104. static pdb_buffer_record_t * write_buffer_record_find(pm_peer_id_t peer_id,
  105. pm_peer_data_id_t data_id)
  106. {
  107. int index = 0;
  108. pdb_buffer_record_t * p_record = write_buffer_record_find_next(peer_id, &index);
  109. while ((p_record != NULL) && (p_record->data_id != data_id))
  110. {
  111. index++;
  112. p_record = write_buffer_record_find_next(peer_id, &index);
  113. }
  114. return p_record;
  115. }
  116. /**@brief Function for finding an available record for write buffer allocation.
  117. *
  118. * @return A pointer to the available record, or NULL if none was found.
  119. */
  120. static pdb_buffer_record_t * write_buffer_record_find_unused(void)
  121. {
  122. return write_buffer_record_find(PM_PEER_ID_INVALID, PM_PEER_DATA_ID_INVALID);
  123. }
  124. /**@brief Function for gracefully deactivating a write buffer record.
  125. *
  126. * @details This function will first release any buffers, then invalidate the record.
  127. *
  128. * @param[inout] p_write_buffer_record The record to release.
  129. *
  130. * @return A pointer to the matching record, or NULL if none was found.
  131. */
  132. static void write_buffer_record_release(pdb_buffer_record_t * p_write_buffer_record)
  133. {
  134. for (uint32_t i = 0; i < p_write_buffer_record->n_bufs; i++)
  135. {
  136. pm_buffer_release(&m_pdb.write_buffer, p_write_buffer_record->buffer_block_id + i);
  137. }
  138. write_buffer_record_invalidate(p_write_buffer_record);
  139. }
  140. /**@brief Function for claiming and activating a write buffer record.
  141. *
  142. * @param[out] pp_write_buffer_record The claimed record.
  143. * @param[in] peer_id The peer ID this record should have.
  144. * @param[in] data_id The data ID this record should have.
  145. */
  146. static void write_buffer_record_get(pdb_buffer_record_t ** pp_write_buffer_record, pm_peer_id_t peer_id, pm_peer_data_id_t data_id)
  147. {
  148. if (pp_write_buffer_record == NULL)
  149. {
  150. return;
  151. }
  152. *pp_write_buffer_record = write_buffer_record_find_unused();
  153. if (*pp_write_buffer_record == NULL)
  154. {
  155. // This also means the buffer is full.
  156. return;
  157. }
  158. (*pp_write_buffer_record)->peer_id = peer_id;
  159. (*pp_write_buffer_record)->data_id = data_id;
  160. }
  161. /**@brief Function for dispatching outbound events to all registered event handlers.
  162. *
  163. * @param[in] p_event The event to dispatch.
  164. */
  165. static void pdb_evt_send(pdb_evt_t * p_event)
  166. {
  167. for (uint32_t i = 0; i < m_pdb.n_registrants; i++)
  168. {
  169. m_pdb.evt_handlers[i](p_event);
  170. }
  171. }
  172. /**@brief Function for resetting the internal state of the Peer Database module.
  173. *
  174. * @param[out] p_event The event to dispatch.
  175. */
  176. static void internal_state_reset(pdb_t * pdb)
  177. {
  178. memset(pdb, 0, sizeof(pdb_t));
  179. for (uint32_t i = 0; i < N_WRITE_BUFFER_RECORDS; i++)
  180. {
  181. write_buffer_record_invalidate(&pdb->write_buffer_records[i]);
  182. }
  183. }
  184. /**@brief Function for handling events from the Peer Data Storage module.
  185. *
  186. * @param[in] p_event The event to handle.
  187. */
  188. static void pds_evt_handler(pds_evt_t const * p_event)
  189. {
  190. ret_code_t err_code;
  191. pdb_buffer_record_t * p_write_buffer_record;
  192. bool retry_flash_full = false;
  193. pdb_evt_t event =
  194. {
  195. .peer_id = p_event->peer_id,
  196. .data_id = p_event->data_id,
  197. };
  198. p_write_buffer_record = write_buffer_record_find(p_event->peer_id, p_event->data_id);
  199. switch (p_event->evt_id)
  200. {
  201. case PDS_EVT_STORED:
  202. case PDS_EVT_UPDATED:
  203. if ( (p_write_buffer_record != NULL)
  204. //&& (p_write_buffer_record->store_token == p_event->store_token)
  205. && (p_write_buffer_record->store_requested))
  206. {
  207. write_buffer_record_release(p_write_buffer_record);
  208. event.evt_id = PDB_EVT_WRITE_BUF_STORED;
  209. event.params.write_buf_stored_evt.update = (p_event->evt_id == PDS_EVT_UPDATED);
  210. pdb_evt_send(&event);
  211. }
  212. else
  213. {
  214. event.evt_id = PDB_EVT_RAW_STORED;
  215. event.params.raw_stored_evt.store_token = p_event->store_token;
  216. pdb_evt_send(&event);
  217. }
  218. break;
  219. case PDS_EVT_ERROR_STORE:
  220. case PDS_EVT_ERROR_UPDATE:
  221. if ( (p_write_buffer_record != NULL)
  222. && (p_write_buffer_record->store_token == p_event->store_token)
  223. && (p_write_buffer_record->store_requested))
  224. {
  225. // Retry if internal buffer.
  226. m_pdb.n_writes++;
  227. p_write_buffer_record->store_requested = false;
  228. p_write_buffer_record->store_busy = true;
  229. }
  230. else
  231. {
  232. event.evt_id = PDB_EVT_RAW_STORE_FAILED;
  233. event.params.error_raw_store_evt.err_code = p_event->result;
  234. pdb_evt_send(&event);
  235. }
  236. break;
  237. case PDS_EVT_CLEARED:
  238. event.evt_id = PDB_EVT_CLEARED;
  239. pdb_evt_send(&event);
  240. break;
  241. case PDS_EVT_ERROR_CLEAR:
  242. event.evt_id = PDB_EVT_CLEAR_FAILED;
  243. event.params.clear_failed_evt.err_code = p_event->result;
  244. pdb_evt_send(&event);
  245. break;
  246. case PDS_EVT_PEER_ID_CLEAR:
  247. event.evt_id = PDB_EVT_PEER_FREED;
  248. pdb_evt_send(&event);
  249. break;
  250. case PDS_EVT_ERROR_PEER_ID_CLEAR:
  251. event.evt_id = PDB_EVT_PEER_FREE_FAILED;
  252. event.params.peer_free_failed_evt.err_code = p_event->result;
  253. pdb_evt_send(&event);
  254. break;
  255. case PDS_EVT_COMPRESSED:
  256. retry_flash_full = true;
  257. event.evt_id = PDB_EVT_COMPRESSED;
  258. pdb_evt_send(&event);
  259. break;
  260. case PDS_EVT_ERROR_UNEXPECTED:
  261. event.params.error_unexpected.err_code = p_event->result;
  262. break;
  263. default:
  264. break;
  265. }
  266. if (m_pdb.n_writes > 0)
  267. {
  268. for (uint32_t i = 0; i < N_WRITE_BUFFER_RECORDS; i++)
  269. {
  270. if ((m_pdb.write_buffer_records[i].store_busy)
  271. || (m_pdb.write_buffer_records[i].store_flash_full && retry_flash_full))
  272. {
  273. err_code = pdb_write_buf_store(m_pdb.write_buffer_records[i].peer_id,
  274. m_pdb.write_buffer_records[i].data_id);
  275. if (err_code != NRF_SUCCESS)
  276. {
  277. event.peer_id = m_pdb.write_buffer_records[i].peer_id;
  278. event.data_id = m_pdb.write_buffer_records[i].data_id;
  279. if (err_code == NRF_ERROR_NO_MEM)
  280. {
  281. event.evt_id = PDB_EVT_ERROR_NO_MEM;
  282. }
  283. else
  284. {
  285. event.evt_id = PDB_EVT_ERROR_UNEXPECTED;
  286. event.params.error_unexpected.err_code = err_code;
  287. }
  288. pdb_evt_send(&event);
  289. break;
  290. }
  291. }
  292. }
  293. }
  294. }
  295. ret_code_t pdb_register(pdb_evt_handler_t evt_handler)
  296. {
  297. if (m_pdb.n_registrants >= MAX_REGISTRANTS)
  298. {
  299. return NRF_ERROR_NO_MEM;
  300. }
  301. VERIFY_PARAM_NOT_NULL(evt_handler);
  302. if (!MODULE_INITIALIZED)
  303. {
  304. ret_code_t err_code;
  305. internal_state_reset(&m_pdb);
  306. err_code = pds_register(pds_evt_handler);
  307. if (err_code != NRF_SUCCESS)
  308. {
  309. return NRF_ERROR_INTERNAL;
  310. }
  311. PM_BUFFER_INIT(&m_pdb.write_buffer, N_WRITE_BUFFERS, PDB_WRITE_BUF_SIZE, err_code);
  312. if (err_code != NRF_SUCCESS)
  313. {
  314. return NRF_ERROR_INTERNAL;
  315. }
  316. }
  317. m_pdb.evt_handlers[m_pdb.n_registrants] = evt_handler;
  318. m_pdb.n_registrants += 1;
  319. return NRF_SUCCESS;
  320. }
  321. pm_peer_id_t pdb_peer_allocate(void)
  322. {
  323. if (!MODULE_INITIALIZED)
  324. {
  325. return PM_PEER_ID_INVALID;
  326. }
  327. return pds_peer_id_allocate();
  328. }
  329. ret_code_t pdb_peer_free(pm_peer_id_t peer_id)
  330. {
  331. VERIFY_MODULE_INITIALIZED();
  332. ret_code_t err_code_in = NRF_SUCCESS;
  333. ret_code_t err_code_out = NRF_SUCCESS;
  334. int index = 0;
  335. pdb_buffer_record_t * p_record = write_buffer_record_find_next(peer_id, &index);
  336. while (p_record != NULL)
  337. {
  338. err_code_in = pdb_write_buf_release(peer_id, p_record->data_id);
  339. if ( (err_code_in != NRF_SUCCESS)
  340. && (err_code_in != NRF_ERROR_NOT_FOUND))
  341. {
  342. err_code_out = NRF_ERROR_INTERNAL;
  343. }
  344. index++;
  345. p_record = write_buffer_record_find_next(peer_id, &index);
  346. }
  347. if (err_code_out == NRF_SUCCESS)
  348. {
  349. err_code_in = pds_peer_id_free(peer_id);
  350. if (err_code_in == NRF_SUCCESS)
  351. {
  352. // No action needed.
  353. }
  354. else if (err_code_in == NRF_ERROR_INVALID_PARAM)
  355. {
  356. err_code_out = NRF_ERROR_INVALID_PARAM;
  357. }
  358. else
  359. {
  360. err_code_out = NRF_ERROR_INTERNAL;
  361. }
  362. }
  363. return err_code_out;
  364. }
  365. ret_code_t pdb_read_buf_get(pm_peer_id_t peer_id,
  366. pm_peer_data_id_t data_id,
  367. pm_peer_data_flash_t * p_peer_data,
  368. pm_store_token_t * p_token)
  369. {
  370. VERIFY_MODULE_INITIALIZED();
  371. return pds_peer_data_read_ptr_get(peer_id, data_id, p_peer_data, p_token);
  372. }
  373. static void peer_data_point_to_buffer(pm_peer_data_t * p_peer_data, pm_peer_data_id_t data_id, uint8_t * p_buffer_memory, uint16_t n_bufs)
  374. {
  375. uint16_t n_bytes = n_bufs * PDB_WRITE_BUF_SIZE;
  376. p_peer_data->data_id = data_id;
  377. p_peer_data->p_all_data = (pm_peer_data_bonding_t *)p_buffer_memory;
  378. p_peer_data->length_words = BYTES_TO_WORDS(n_bytes);
  379. }
  380. static void peer_data_const_point_to_buffer(pm_peer_data_const_t * p_peer_data, pm_peer_data_id_t data_id, uint8_t * p_buffer_memory, uint32_t n_bufs)
  381. {
  382. peer_data_point_to_buffer((pm_peer_data_t*)p_peer_data, data_id, p_buffer_memory, n_bufs);
  383. }
  384. static void write_buf_length_words_set(pm_peer_data_const_t * p_peer_data)
  385. {
  386. switch (p_peer_data->data_id)
  387. {
  388. case PM_PEER_DATA_ID_BONDING:
  389. p_peer_data->length_words = PM_BONDING_DATA_N_WORDS();
  390. break;
  391. case PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING:
  392. p_peer_data->length_words = PM_SC_STATE_N_WORDS();
  393. break;
  394. case PM_PEER_DATA_ID_PEER_RANK:
  395. p_peer_data->length_words = PM_USAGE_INDEX_N_WORDS();
  396. break;
  397. case PM_PEER_DATA_ID_GATT_LOCAL:
  398. p_peer_data->length_words = PM_LOCAL_DB_N_WORDS(p_peer_data->p_local_gatt_db->len);
  399. break;
  400. default:
  401. // No action needed.
  402. break;
  403. }
  404. }
  405. ret_code_t pdb_write_buf_get(pm_peer_id_t peer_id,
  406. pm_peer_data_id_t data_id,
  407. uint32_t n_bufs,
  408. pm_peer_data_t * p_peer_data)
  409. {
  410. VERIFY_MODULE_INITIALIZED();
  411. VERIFY_PARAM_NOT_NULL(p_peer_data);
  412. VERIFY_DATA_ID_WRITE_BUF(data_id);
  413. if ( (n_bufs == 0)
  414. || (n_bufs > N_WRITE_BUFFERS)
  415. || !pds_peer_id_is_allocated(peer_id))
  416. {
  417. return NRF_ERROR_INVALID_PARAM;
  418. }
  419. pdb_buffer_record_t * write_buffer_record;
  420. uint8_t * p_buffer_memory;
  421. bool new_record = false;
  422. write_buffer_record = write_buffer_record_find(peer_id, data_id);
  423. if ((write_buffer_record != NULL) && (write_buffer_record->n_bufs < n_bufs))
  424. {
  425. // @TODO: Copy?
  426. // Existing buffer is too small.
  427. for (uint8_t i = 0; i < write_buffer_record->n_bufs; i++)
  428. {
  429. pm_buffer_release(&m_pdb.write_buffer, write_buffer_record->buffer_block_id + i);
  430. }
  431. write_buffer_record_invalidate(write_buffer_record);
  432. write_buffer_record = NULL;
  433. }
  434. else if ((write_buffer_record != NULL) && write_buffer_record->n_bufs > n_bufs)
  435. {
  436. // Release excess blocks.
  437. for (uint8_t i = n_bufs; i < write_buffer_record->n_bufs; i++)
  438. {
  439. pm_buffer_release(&m_pdb.write_buffer, write_buffer_record->buffer_block_id + i);
  440. }
  441. }
  442. if (write_buffer_record == NULL)
  443. {
  444. write_buffer_record_get(&write_buffer_record, peer_id, data_id);
  445. if (write_buffer_record == NULL)
  446. {
  447. return NRF_ERROR_BUSY;
  448. }
  449. }
  450. if (write_buffer_record->buffer_block_id == BUFFER_INVALID_ID)
  451. {
  452. write_buffer_record->buffer_block_id = pm_buffer_block_acquire(&m_pdb.write_buffer, n_bufs);
  453. if (write_buffer_record->buffer_block_id == BUFFER_INVALID_ID)
  454. {
  455. write_buffer_record_invalidate(write_buffer_record);
  456. return NRF_ERROR_BUSY;
  457. }
  458. new_record = true;
  459. }
  460. write_buffer_record->n_bufs = n_bufs;
  461. p_buffer_memory = pm_buffer_ptr_get(&m_pdb.write_buffer, write_buffer_record->buffer_block_id);
  462. if (p_buffer_memory == NULL)
  463. {
  464. return NRF_ERROR_INTERNAL;
  465. }
  466. peer_data_point_to_buffer(p_peer_data, data_id, p_buffer_memory, n_bufs);
  467. if (new_record && (data_id == PM_PEER_DATA_ID_GATT_LOCAL))
  468. {
  469. p_peer_data->p_local_gatt_db->len = PM_LOCAL_DB_LEN(p_peer_data->length_words);
  470. }
  471. return NRF_SUCCESS;
  472. }
  473. ret_code_t pdb_write_buf_release(pm_peer_id_t peer_id, pm_peer_data_id_t data_id)
  474. {
  475. VERIFY_MODULE_INITIALIZED();
  476. ret_code_t err_code = NRF_SUCCESS;
  477. pdb_buffer_record_t * p_write_buffer_record;
  478. p_write_buffer_record = write_buffer_record_find(peer_id, data_id);
  479. if (p_write_buffer_record == NULL)
  480. {
  481. return NRF_ERROR_NOT_FOUND;
  482. }
  483. if (p_write_buffer_record->prepare_token != PDS_PREPARE_TOKEN_INVALID)
  484. {
  485. err_code = pds_peer_data_write_prepare_cancel(p_write_buffer_record->prepare_token);
  486. if (err_code != NRF_SUCCESS)
  487. {
  488. err_code = NRF_ERROR_INTERNAL;
  489. }
  490. }
  491. write_buffer_record_release(p_write_buffer_record);
  492. return err_code;
  493. }
  494. ret_code_t pdb_write_buf_store_prepare(pm_peer_id_t peer_id, pm_peer_data_id_t data_id)
  495. {
  496. VERIFY_MODULE_INITIALIZED();
  497. VERIFY_DATA_ID_WRITE_BUF(data_id);
  498. ret_code_t err_code = NRF_SUCCESS;
  499. pdb_buffer_record_t * p_write_buffer_record;
  500. p_write_buffer_record = write_buffer_record_find(peer_id, data_id);
  501. if (p_write_buffer_record == NULL)
  502. {
  503. return NRF_ERROR_NOT_FOUND;
  504. }
  505. if (p_write_buffer_record->prepare_token == PDS_PREPARE_TOKEN_INVALID)
  506. {
  507. uint8_t * p_buffer_memory = pm_buffer_ptr_get(&m_pdb.write_buffer, p_write_buffer_record->buffer_block_id);
  508. pm_peer_data_const_t peer_data = {.data_id = data_id};
  509. if (p_buffer_memory == NULL)
  510. {
  511. return NRF_ERROR_INTERNAL;
  512. }
  513. peer_data_const_point_to_buffer(&peer_data, data_id, p_buffer_memory, p_write_buffer_record->n_bufs);
  514. write_buf_length_words_set(&peer_data);
  515. err_code = pds_peer_data_write_prepare(&peer_data, &p_write_buffer_record->prepare_token);
  516. if (err_code == NRF_ERROR_INVALID_LENGTH)
  517. {
  518. return NRF_ERROR_INTERNAL;
  519. }
  520. }
  521. return err_code;
  522. }
  523. static ret_code_t write_or_update(pm_peer_id_t peer_id,
  524. pm_peer_data_id_t data_id,
  525. pm_peer_data_const_t * p_peer_data,
  526. pm_store_token_t * p_store_token,
  527. pm_prepare_token_t prepare_token)
  528. {
  529. pm_peer_data_flash_t old_peer_data;
  530. pm_store_token_t old_store_token;
  531. ret_code_t err_code = pds_peer_data_read_ptr_get(peer_id, data_id, &old_peer_data, &old_store_token);
  532. if (err_code == NRF_SUCCESS)
  533. {
  534. err_code = pds_peer_data_write_prepare_cancel(prepare_token);
  535. if ((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NULL))
  536. {
  537. err_code = pds_peer_data_update(peer_id, p_peer_data, old_store_token, p_store_token);
  538. }
  539. else
  540. {
  541. err_code = NRF_ERROR_INTERNAL;
  542. }
  543. }
  544. else if (err_code == NRF_ERROR_NOT_FOUND)
  545. {
  546. if (prepare_token == PDS_PREPARE_TOKEN_INVALID)
  547. {
  548. err_code = pds_peer_data_write(peer_id, p_peer_data, p_store_token);
  549. }
  550. else
  551. {
  552. err_code = pds_peer_data_write_prepared(peer_id, p_peer_data, prepare_token, p_store_token);
  553. }
  554. }
  555. return err_code;
  556. }
  557. ret_code_t pdb_write_buf_store(pm_peer_id_t peer_id,
  558. pm_peer_data_id_t data_id)
  559. {
  560. VERIFY_MODULE_INITIALIZED();
  561. VERIFY_DATA_ID_WRITE_BUF(data_id);
  562. ret_code_t err_code = NRF_SUCCESS;
  563. pdb_buffer_record_t * p_write_buffer_record;
  564. uint8_t * p_buffer_memory;
  565. pm_peer_data_const_t peer_data = {.data_id = data_id};
  566. p_write_buffer_record = write_buffer_record_find(peer_id, data_id);
  567. if (p_write_buffer_record == NULL)
  568. {
  569. return NRF_ERROR_NOT_FOUND;
  570. }
  571. if (p_write_buffer_record->store_requested)
  572. {
  573. return NRF_SUCCESS;
  574. }
  575. p_buffer_memory = pm_buffer_ptr_get(&m_pdb.write_buffer, p_write_buffer_record->buffer_block_id);
  576. if (p_buffer_memory == NULL)
  577. {
  578. return NRF_ERROR_INTERNAL;
  579. }
  580. peer_data_const_point_to_buffer(&peer_data, data_id, p_buffer_memory, p_write_buffer_record->n_bufs);
  581. write_buf_length_words_set(&peer_data);
  582. err_code = write_or_update(peer_id, data_id, &peer_data, &p_write_buffer_record->store_token, p_write_buffer_record->prepare_token);
  583. if (p_write_buffer_record->store_busy && p_write_buffer_record->store_flash_full)
  584. {
  585. m_pdb.n_writes--;
  586. }
  587. if (err_code == NRF_SUCCESS)
  588. {
  589. p_write_buffer_record->store_requested = true;
  590. p_write_buffer_record->store_busy = false;
  591. p_write_buffer_record->store_flash_full = false;
  592. }
  593. else
  594. {
  595. if (err_code == NRF_ERROR_BUSY)
  596. {
  597. m_pdb.n_writes++;
  598. p_write_buffer_record->store_busy = true;
  599. p_write_buffer_record->store_flash_full = false;
  600. err_code = NRF_SUCCESS;
  601. }
  602. else if (err_code == NRF_ERROR_NO_MEM)
  603. {
  604. m_pdb.n_writes++;
  605. p_write_buffer_record->store_busy = false;
  606. p_write_buffer_record->store_flash_full = true;
  607. }
  608. else if ((err_code != NRF_ERROR_NO_MEM) && (err_code != NRF_ERROR_INVALID_PARAM))
  609. {
  610. err_code = NRF_ERROR_INTERNAL;
  611. }
  612. }
  613. return err_code;
  614. }
  615. ret_code_t pdb_clear(pm_peer_id_t peer_id, pm_peer_data_id_t data_id)
  616. {
  617. VERIFY_MODULE_INITIALIZED();
  618. return pds_peer_data_clear(peer_id, data_id);
  619. }
  620. uint32_t pdb_n_peers(void)
  621. {
  622. if (!MODULE_INITIALIZED)
  623. {
  624. return 0;
  625. }
  626. return pds_n_peers();
  627. }
  628. pm_peer_id_t pdb_next_peer_id_get(pm_peer_id_t prev_peer_id)
  629. {
  630. if (!MODULE_INITIALIZED)
  631. {
  632. return PM_PEER_ID_INVALID;
  633. }
  634. return pds_next_peer_id_get(prev_peer_id);
  635. }
  636. ret_code_t pdb_raw_read(pm_peer_id_t peer_id,
  637. pm_peer_data_id_t data_id,
  638. pm_peer_data_t * p_peer_data)
  639. {
  640. VERIFY_MODULE_INITIALIZED();
  641. return pds_peer_data_read(peer_id, data_id, p_peer_data, &p_peer_data->length_words);
  642. }
  643. ret_code_t pdb_raw_store(pm_peer_id_t peer_id,
  644. pm_peer_data_const_t * p_peer_data,
  645. pm_store_token_t * p_store_token)
  646. {
  647. VERIFY_MODULE_INITIALIZED();
  648. return write_or_update(peer_id, p_peer_data->data_id, p_peer_data, p_store_token, PDS_PREPARE_TOKEN_INVALID);
  649. }