peer_database.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. /**
  2. * Copyright (c) 2015 - 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. #include "sdk_common.h"
  41. #if NRF_MODULE_ENABLED(PEER_MANAGER)
  42. #include "peer_database.h"
  43. #include <string.h>
  44. #include "peer_manager_types.h"
  45. #include "peer_manager_internal.h"
  46. #include "peer_data_storage.h"
  47. #include "pm_buffer.h"
  48. #define NRF_LOG_MODULE_NAME peer_manager_pdb
  49. #if PM_LOG_ENABLED
  50. #define NRF_LOG_LEVEL PM_LOG_LEVEL
  51. #define NRF_LOG_INFO_COLOR PM_LOG_INFO_COLOR
  52. #define NRF_LOG_DEBUG_COLOR PM_LOG_DEBUG_COLOR
  53. #else
  54. #define NRF_LOG_LEVEL 0
  55. #endif // PM_LOG_ENABLED
  56. #include "nrf_log.h"
  57. #include "nrf_log_ctrl.h"
  58. NRF_LOG_MODULE_REGISTER();
  59. #include "nrf_strerror.h"
  60. /**@brief Macro for verifying that the data ID is among the values eligible for using the write buffer.
  61. *
  62. * @param[in] data_id The data ID to verify.
  63. */
  64. // @note emdi: could this maybe be a function?
  65. #define VERIFY_DATA_ID_WRITE_BUF(data_id) \
  66. do \
  67. { \
  68. if (((data_id) != PM_PEER_DATA_ID_BONDING) && ((data_id) != PM_PEER_DATA_ID_GATT_LOCAL)) \
  69. { \
  70. return NRF_ERROR_INVALID_PARAM; \
  71. } \
  72. } while (0)
  73. // The number of registered event handlers.
  74. #define PDB_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0]))
  75. // Peer Database event handlers in other Peer Manager submodules.
  76. extern void pm_pdb_evt_handler(pm_evt_t * p_event);
  77. extern void sm_pdb_evt_handler(pm_evt_t * p_event);
  78. #if !defined(PM_SERVICE_CHANGED_ENABLED) || (PM_SERVICE_CHANGED_ENABLED == 1)
  79. extern void gscm_pdb_evt_handler(pm_evt_t * p_event);
  80. #endif
  81. extern void gcm_pdb_evt_handler(pm_evt_t * p_event);
  82. // Peer Database events' handlers.
  83. // The number of elements in this array is PDB_EVENT_HANDLERS_CNT.
  84. static pm_evt_handler_internal_t const m_evt_handlers[] =
  85. {
  86. pm_pdb_evt_handler,
  87. sm_pdb_evt_handler,
  88. #if !defined(PM_SERVICE_CHANGED_ENABLED) || (PM_SERVICE_CHANGED_ENABLED == 1)
  89. gscm_pdb_evt_handler,
  90. #endif
  91. gcm_pdb_evt_handler,
  92. };
  93. /**@brief Struct for keeping track of one write buffer, from allocation, until it is fully written
  94. * or cancelled.
  95. */
  96. typedef struct
  97. {
  98. pm_peer_id_t peer_id; /**< The peer ID this buffer belongs to. */
  99. pm_peer_data_id_t data_id; /**< The data ID this buffer belongs to. */
  100. pm_store_token_t store_token; /**< Token given by Peer Data Storage when a flash write has been successfully requested. This is used as the check for whether such an operation has been successfully requested. */
  101. uint8_t n_bufs; /**< The number of buffer blocks containing peer data. */
  102. uint8_t buffer_block_id; /**< The index of the first (or only) buffer block containing peer data. */
  103. 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. */
  104. 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. */
  105. } pdb_buffer_record_t;
  106. static bool m_module_initialized;
  107. static pm_buffer_t m_write_buffer; /**< The internal states of the write buffer. */
  108. static pdb_buffer_record_t m_write_buffer_records[PM_FLASH_BUFFERS]; /**< The available write buffer records. */
  109. static bool m_pending_store = false; /**< Whether there are any pending (Not yet successfully requested in Peer Data Storage) store operations. This flag is for convenience only. The real bookkeeping is in the records (@ref m_write_buffer_records). */
  110. /**@brief Function for invalidating a record of a write buffer allocation.
  111. *
  112. * @param[in] p_record The record to invalidate.
  113. */
  114. static void write_buffer_record_invalidate(pdb_buffer_record_t * p_record)
  115. {
  116. p_record->peer_id = PM_PEER_ID_INVALID;
  117. p_record->data_id = PM_PEER_DATA_ID_INVALID;
  118. p_record->buffer_block_id = PM_BUFFER_INVALID_ID;
  119. p_record->store_busy = false;
  120. p_record->store_flash_full = false;
  121. p_record->n_bufs = 0;
  122. p_record->store_token = PM_STORE_TOKEN_INVALID;
  123. }
  124. /**@brief Function for finding a record of a write buffer allocation.
  125. *
  126. * @param[in] peer_id The peer ID in the record.
  127. * @param[inout] p_index In: The starting index, out: The index of the record
  128. *
  129. * @return A pointer to the matching record, or NULL if none was found.
  130. */
  131. static pdb_buffer_record_t * write_buffer_record_find_next(pm_peer_id_t peer_id, uint32_t * p_index)
  132. {
  133. for (uint32_t i = *p_index; i < PM_FLASH_BUFFERS; i++)
  134. {
  135. if ((m_write_buffer_records[i].peer_id == peer_id))
  136. {
  137. *p_index = i;
  138. return &m_write_buffer_records[i];
  139. }
  140. }
  141. return NULL;
  142. }
  143. /**@brief Function for finding a record of a write buffer allocation.
  144. *
  145. * @param[in] peer_id The peer ID in the record.
  146. * @param[in] data_id The data ID in the record.
  147. *
  148. * @return A pointer to the matching record, or NULL if none was found.
  149. */
  150. static pdb_buffer_record_t * write_buffer_record_find(pm_peer_id_t peer_id,
  151. pm_peer_data_id_t data_id)
  152. {
  153. uint32_t index = 0;
  154. pdb_buffer_record_t * p_record = write_buffer_record_find_next(peer_id, &index);
  155. while ((p_record != NULL) && ( (p_record->data_id != data_id)
  156. || (p_record->store_busy)
  157. || (p_record->store_flash_full)
  158. || (p_record->store_token != PM_STORE_TOKEN_INVALID)))
  159. {
  160. index++;
  161. p_record = write_buffer_record_find_next(peer_id, &index);
  162. }
  163. return p_record;
  164. }
  165. /**@brief Function for finding a record of a write buffer allocation that has been sent to be stored.
  166. *
  167. * @param[in] store_token The store token received when store was called for the record.
  168. *
  169. * @return A pointer to the matching record, or NULL if none was found.
  170. */
  171. static pdb_buffer_record_t * write_buffer_record_find_stored(pm_store_token_t store_token)
  172. {
  173. for (int i = 0; i < PM_FLASH_BUFFERS; i++)
  174. {
  175. if (m_write_buffer_records[i].store_token == store_token)
  176. {
  177. return &m_write_buffer_records[i];
  178. }
  179. }
  180. return NULL;
  181. }
  182. /**@brief Function for finding an available record for write buffer allocation.
  183. *
  184. * @return A pointer to the available record, or NULL if none was found.
  185. */
  186. static pdb_buffer_record_t * write_buffer_record_find_unused(void)
  187. {
  188. return write_buffer_record_find(PM_PEER_ID_INVALID, PM_PEER_DATA_ID_INVALID);
  189. }
  190. /**@brief Function for gracefully deactivating a write buffer record.
  191. *
  192. * @details This function will first release any buffers, then invalidate the record.
  193. *
  194. * @param[inout] p_write_buffer_record The record to release.
  195. *
  196. * @return A pointer to the matching record, or NULL if none was found.
  197. */
  198. static void write_buffer_record_release(pdb_buffer_record_t * p_write_buffer_record)
  199. {
  200. for (uint32_t i = 0; i < p_write_buffer_record->n_bufs; i++)
  201. {
  202. pm_buffer_release(&m_write_buffer, p_write_buffer_record->buffer_block_id + i);
  203. }
  204. write_buffer_record_invalidate(p_write_buffer_record);
  205. }
  206. /**@brief Function for claiming and activating a write buffer record.
  207. *
  208. * @param[out] pp_write_buffer_record The claimed record.
  209. * @param[in] peer_id The peer ID this record should have.
  210. * @param[in] data_id The data ID this record should have.
  211. */
  212. static void write_buffer_record_acquire(pdb_buffer_record_t ** pp_write_buffer_record,
  213. pm_peer_id_t peer_id,
  214. pm_peer_data_id_t data_id)
  215. {
  216. if (pp_write_buffer_record == NULL)
  217. {
  218. return;
  219. }
  220. *pp_write_buffer_record = write_buffer_record_find_unused();
  221. if (*pp_write_buffer_record == NULL)
  222. {
  223. // This also means the buffer is full.
  224. return;
  225. }
  226. (*pp_write_buffer_record)->peer_id = peer_id;
  227. (*pp_write_buffer_record)->data_id = data_id;
  228. }
  229. /**@brief Function for dispatching outbound events to all registered event handlers.
  230. *
  231. * @param[in] p_event The event to dispatch.
  232. */
  233. static void pdb_evt_send(pm_evt_t * p_event)
  234. {
  235. for (uint32_t i = 0; i < PDB_EVENT_HANDLERS_CNT; i++)
  236. {
  237. m_evt_handlers[i](p_event);
  238. }
  239. }
  240. /**@brief Function for resetting the internal state of the Peer Database module.
  241. *
  242. * @param[out] p_event The event to dispatch.
  243. */
  244. static void internal_state_reset()
  245. {
  246. for (uint32_t i = 0; i < PM_FLASH_BUFFERS; i++)
  247. {
  248. write_buffer_record_invalidate(&m_write_buffer_records[i]);
  249. }
  250. }
  251. 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)
  252. {
  253. uint16_t n_bytes = n_bufs * PDB_WRITE_BUF_SIZE;
  254. p_peer_data->data_id = data_id;
  255. p_peer_data->p_all_data = (pm_peer_data_bonding_t *)p_buffer_memory;
  256. p_peer_data->length_words = BYTES_TO_WORDS(n_bytes);
  257. }
  258. 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)
  259. {
  260. peer_data_point_to_buffer((pm_peer_data_t*)p_peer_data, data_id, p_buffer_memory, n_bufs);
  261. }
  262. static void write_buf_length_words_set(pm_peer_data_const_t * p_peer_data)
  263. {
  264. switch (p_peer_data->data_id)
  265. {
  266. case PM_PEER_DATA_ID_BONDING:
  267. p_peer_data->length_words = PM_BONDING_DATA_N_WORDS();
  268. break;
  269. case PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING:
  270. p_peer_data->length_words = PM_SC_STATE_N_WORDS();
  271. break;
  272. case PM_PEER_DATA_ID_PEER_RANK:
  273. p_peer_data->length_words = PM_USAGE_INDEX_N_WORDS();
  274. break;
  275. case PM_PEER_DATA_ID_GATT_LOCAL:
  276. p_peer_data->length_words = PM_LOCAL_DB_N_WORDS(p_peer_data->p_local_gatt_db->len);
  277. break;
  278. default:
  279. // No action needed.
  280. break;
  281. }
  282. }
  283. /**@brief Function for writing data into persistent storage. Writing happens asynchronously.
  284. *
  285. * @note This will unlock the data after it has been written.
  286. *
  287. * @param[in] p_write_buffer_record The write buffer record to write into persistent storage.
  288. *
  289. * @retval NRF_SUCCESS Data storing was successfully started.
  290. * @retval NRF_ERROR_STORAGE_FULL No space available in persistent storage. Please clear some
  291. * space, the operation will be reattempted after the next compress
  292. * procedure.
  293. * @retval NRF_ERROR_INVALID_PARAM Data ID was invalid.
  294. * @retval NRF_ERROR_INVALID_STATE Module is not initialized.
  295. * @retval NRF_ERROR_INTERNAL Unexpected internal error.
  296. */
  297. ret_code_t write_buf_store(pdb_buffer_record_t * p_write_buffer_record)
  298. {
  299. ret_code_t err_code = NRF_SUCCESS;
  300. pm_peer_data_const_t peer_data = {.data_id = p_write_buffer_record->data_id};
  301. uint8_t * p_buffer_memory;
  302. p_buffer_memory = pm_buffer_ptr_get(&m_write_buffer, p_write_buffer_record->buffer_block_id);
  303. if (p_buffer_memory == NULL)
  304. {
  305. NRF_LOG_ERROR("pm_buffer_ptr_get() could not retrieve RAM buffer. block_id: %d",
  306. p_write_buffer_record->buffer_block_id);
  307. return NRF_ERROR_INTERNAL;
  308. }
  309. peer_data_const_point_to_buffer(&peer_data,
  310. p_write_buffer_record->data_id,
  311. p_buffer_memory,
  312. p_write_buffer_record->n_bufs);
  313. write_buf_length_words_set(&peer_data);
  314. err_code = pds_peer_data_store(p_write_buffer_record->peer_id,
  315. &peer_data,
  316. &p_write_buffer_record->store_token);
  317. switch (err_code)
  318. {
  319. case NRF_SUCCESS:
  320. p_write_buffer_record->store_busy = false;
  321. p_write_buffer_record->store_flash_full = false;
  322. break;
  323. case NRF_ERROR_BUSY:
  324. p_write_buffer_record->store_busy = true;
  325. p_write_buffer_record->store_flash_full = false;
  326. m_pending_store = true;
  327. err_code = NRF_SUCCESS;
  328. break;
  329. case NRF_ERROR_STORAGE_FULL:
  330. p_write_buffer_record->store_busy = false;
  331. p_write_buffer_record->store_flash_full = true;
  332. m_pending_store = true;
  333. break;
  334. case NRF_ERROR_INVALID_PARAM:
  335. // No action.
  336. break;
  337. default:
  338. NRF_LOG_ERROR("pds_peer_data_store() returned %s. peer_id: %d",
  339. nrf_strerror_get(err_code),
  340. p_write_buffer_record->peer_id);
  341. err_code = NRF_ERROR_INTERNAL;
  342. break;
  343. }
  344. return err_code;
  345. }
  346. /**@brief This calls @ref write_buf_store and sends events based on the return value.
  347. *
  348. * See @ref write_buf_store for more info.
  349. *
  350. * @return Whether or not the store operation succeeded.
  351. */
  352. static bool write_buf_store_in_event(pdb_buffer_record_t * p_write_buffer_record)
  353. {
  354. ret_code_t err_code;
  355. pm_evt_t event;
  356. err_code = write_buf_store(p_write_buffer_record);
  357. if (err_code != NRF_SUCCESS)
  358. {
  359. event.conn_handle = BLE_CONN_HANDLE_INVALID;
  360. event.peer_id = p_write_buffer_record->peer_id;
  361. if (err_code == NRF_ERROR_STORAGE_FULL)
  362. {
  363. event.evt_id = PM_EVT_STORAGE_FULL;
  364. }
  365. else
  366. {
  367. event.evt_id = PM_EVT_ERROR_UNEXPECTED;
  368. event.params.error_unexpected.error = err_code;
  369. NRF_LOG_ERROR("Some peer data was not properly written to flash. write_buf_store() "\
  370. "returned %s for peer_id: %d",
  371. nrf_strerror_get(err_code),
  372. p_write_buffer_record->peer_id);
  373. }
  374. pdb_evt_send(&event);
  375. return false;
  376. }
  377. return true;
  378. }
  379. /**@brief This reattempts store operations on write buffers, that previously failed because of @ref
  380. * NRF_ERROR_BUSY or @ref NRF_ERROR_STORAGE_FULL errors.
  381. *
  382. * param[in] retry_flash_full Whether to retry operations that failed because of an
  383. * @ref NRF_ERROR_STORAGE_FULL error.
  384. */
  385. static void reattempt_previous_operations(bool retry_flash_full)
  386. {
  387. if (!m_pending_store)
  388. {
  389. return;
  390. }
  391. m_pending_store = false;
  392. for (uint32_t i = 0; i < PM_FLASH_BUFFERS; i++)
  393. {
  394. if ((m_write_buffer_records[i].store_busy)
  395. || (m_write_buffer_records[i].store_flash_full))
  396. {
  397. m_pending_store = true;
  398. if (m_write_buffer_records[i].store_busy || retry_flash_full)
  399. {
  400. if (!write_buf_store_in_event(&m_write_buffer_records[i]))
  401. {
  402. return;
  403. }
  404. }
  405. }
  406. }
  407. }
  408. /**@brief Function for handling events from the Peer Data Storage module.
  409. * This function is extern in Peer Data Storage.
  410. *
  411. * @param[in] p_event The event to handle.
  412. */
  413. void pdb_pds_evt_handler(pm_evt_t * p_event)
  414. {
  415. pdb_buffer_record_t * p_write_buffer_record;
  416. bool evt_send = true;
  417. bool retry_flash_full = false;
  418. p_write_buffer_record = write_buffer_record_find_stored(p_event->params.peer_data_update_succeeded.token);
  419. switch (p_event->evt_id)
  420. {
  421. case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED:
  422. if ( (p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE)
  423. && (p_write_buffer_record != NULL))
  424. {
  425. // The write came from PDB.
  426. write_buffer_record_release(p_write_buffer_record);
  427. }
  428. break;
  429. case PM_EVT_PEER_DATA_UPDATE_FAILED:
  430. if ( (p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE)
  431. && (p_write_buffer_record != NULL))
  432. {
  433. // The write came from PDB, retry.
  434. p_write_buffer_record->store_token = PM_STORE_TOKEN_INVALID;
  435. p_write_buffer_record->store_busy = true;
  436. m_pending_store = true;
  437. evt_send = false;
  438. }
  439. break;
  440. case PM_EVT_FLASH_GARBAGE_COLLECTED:
  441. retry_flash_full = true;
  442. break;
  443. default:
  444. break;
  445. }
  446. if (evt_send)
  447. {
  448. // Forward the event to all registered Peer Database event handlers.
  449. pdb_evt_send(p_event);
  450. }
  451. reattempt_previous_operations(retry_flash_full);
  452. }
  453. ret_code_t pdb_init()
  454. {
  455. ret_code_t err_code;
  456. NRF_PM_DEBUG_CHECK(!m_module_initialized);
  457. internal_state_reset();
  458. PM_BUFFER_INIT(&m_write_buffer, PM_FLASH_BUFFERS, PDB_WRITE_BUF_SIZE, err_code);
  459. if (err_code != NRF_SUCCESS)
  460. {
  461. NRF_LOG_ERROR("PM_BUFFER_INIT() returned %s.", nrf_strerror_get(err_code));
  462. return NRF_ERROR_INTERNAL;
  463. }
  464. m_module_initialized = true;
  465. return NRF_SUCCESS;
  466. }
  467. ret_code_t pdb_peer_free(pm_peer_id_t peer_id)
  468. {
  469. ret_code_t err_code;
  470. NRF_PM_DEBUG_CHECK(m_module_initialized);
  471. uint32_t index = 0;
  472. pdb_buffer_record_t * p_record = write_buffer_record_find_next(peer_id, &index);
  473. while (p_record != NULL)
  474. {
  475. err_code = pdb_write_buf_release(peer_id, p_record->data_id);
  476. UNUSED_VARIABLE(err_code); // All return values are acceptable.
  477. if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_NOT_FOUND))
  478. {
  479. NRF_LOG_ERROR("pdb_write_buf_release() returned %s which should not happen. peer_id: %d, "\
  480. "data_id: %d",
  481. nrf_strerror_get(err_code),
  482. peer_id,
  483. p_record->data_id);
  484. return NRF_ERROR_INTERNAL;
  485. }
  486. index++;
  487. p_record = write_buffer_record_find_next(peer_id, &index);
  488. }
  489. err_code = pds_peer_id_free(peer_id);
  490. if ((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_INVALID_PARAM))
  491. {
  492. return err_code;
  493. }
  494. else
  495. {
  496. NRF_LOG_ERROR("Peer ID %d was not properly released. pds_peer_id_free() returned %s. "\
  497. "peer_id: %d",
  498. peer_id,
  499. nrf_strerror_get(err_code));
  500. return NRF_ERROR_INTERNAL;
  501. }
  502. }
  503. ret_code_t pdb_peer_data_ptr_get(pm_peer_id_t peer_id,
  504. pm_peer_data_id_t data_id,
  505. pm_peer_data_flash_t * const p_peer_data)
  506. {
  507. NRF_PM_DEBUG_CHECK(m_module_initialized);
  508. NRF_PM_DEBUG_CHECK(p_peer_data != NULL);
  509. // Pass NULL to only retrieve a pointer.
  510. return pds_peer_data_read(peer_id, data_id, (pm_peer_data_t*)p_peer_data, NULL);
  511. }
  512. ret_code_t pdb_write_buf_get(pm_peer_id_t peer_id,
  513. pm_peer_data_id_t data_id,
  514. uint32_t n_bufs,
  515. pm_peer_data_t * p_peer_data)
  516. {
  517. NRF_PM_DEBUG_CHECK(m_module_initialized);
  518. VERIFY_PARAM_NOT_NULL(p_peer_data);
  519. VERIFY_DATA_ID_WRITE_BUF(data_id);
  520. if ((n_bufs == 0) || (n_bufs > PM_FLASH_BUFFERS))
  521. {
  522. return NRF_ERROR_INVALID_PARAM;
  523. }
  524. pdb_buffer_record_t * p_write_buffer_record;
  525. uint8_t * p_buffer_memory;
  526. bool new_record = false;
  527. p_write_buffer_record = write_buffer_record_find(peer_id, data_id);
  528. if (p_write_buffer_record == NULL)
  529. {
  530. // No buffer exists.
  531. write_buffer_record_acquire(&p_write_buffer_record, peer_id, data_id);
  532. if (p_write_buffer_record == NULL)
  533. {
  534. return NRF_ERROR_BUSY;
  535. }
  536. }
  537. else if (p_write_buffer_record->n_bufs != n_bufs)
  538. {
  539. // Buffer exists with a different n_bufs from what was requested.
  540. return NRF_ERROR_FORBIDDEN;
  541. }
  542. if (p_write_buffer_record->buffer_block_id == PM_BUFFER_INVALID_ID)
  543. {
  544. p_write_buffer_record->buffer_block_id = pm_buffer_block_acquire(&m_write_buffer, n_bufs);
  545. if (p_write_buffer_record->buffer_block_id == PM_BUFFER_INVALID_ID)
  546. {
  547. write_buffer_record_invalidate(p_write_buffer_record);
  548. return NRF_ERROR_BUSY;
  549. }
  550. new_record = true;
  551. }
  552. p_write_buffer_record->n_bufs = n_bufs;
  553. p_buffer_memory = pm_buffer_ptr_get(&m_write_buffer, p_write_buffer_record->buffer_block_id);
  554. if (p_buffer_memory == NULL)
  555. {
  556. NRF_LOG_ERROR("Cannot store data to flash because pm_buffer_ptr_get() could not retrieve "\
  557. "RAM buffer. Is block_id %d not allocated?",
  558. p_write_buffer_record->buffer_block_id);
  559. return NRF_ERROR_INTERNAL;
  560. }
  561. peer_data_point_to_buffer(p_peer_data, data_id, p_buffer_memory, n_bufs);
  562. if (new_record && (data_id == PM_PEER_DATA_ID_GATT_LOCAL))
  563. {
  564. p_peer_data->p_local_gatt_db->len = PM_LOCAL_DB_LEN(p_peer_data->length_words);
  565. }
  566. return NRF_SUCCESS;
  567. }
  568. ret_code_t pdb_write_buf_release(pm_peer_id_t peer_id, pm_peer_data_id_t data_id)
  569. {
  570. NRF_PM_DEBUG_CHECK(m_module_initialized);
  571. pdb_buffer_record_t * p_write_buffer_record;
  572. p_write_buffer_record = write_buffer_record_find(peer_id, data_id);
  573. if (p_write_buffer_record == NULL)
  574. {
  575. return NRF_ERROR_NOT_FOUND;
  576. }
  577. write_buffer_record_release(p_write_buffer_record);
  578. return NRF_SUCCESS;
  579. }
  580. ret_code_t pdb_write_buf_store(pm_peer_id_t peer_id,
  581. pm_peer_data_id_t data_id,
  582. pm_peer_id_t new_peer_id)
  583. {
  584. NRF_PM_DEBUG_CHECK(m_module_initialized);
  585. VERIFY_DATA_ID_WRITE_BUF(data_id);
  586. if (!pds_peer_id_is_allocated(new_peer_id))
  587. {
  588. return NRF_ERROR_INVALID_PARAM;
  589. }
  590. pdb_buffer_record_t * p_write_buffer_record = write_buffer_record_find(peer_id, data_id);
  591. if (p_write_buffer_record == NULL)
  592. {
  593. return NRF_ERROR_NOT_FOUND;
  594. }
  595. p_write_buffer_record->peer_id = new_peer_id;
  596. p_write_buffer_record->data_id = data_id;
  597. return write_buf_store(p_write_buffer_record);
  598. }
  599. #endif // NRF_MODULE_ENABLED(PEER_MANAGER)