Microbit as a BLE gamepad

Dependents:   nRF51822

Fork of nrf51-sdk by Lancaster University

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers peer_database.c Source File

peer_database.c

00001 /*
00002  * Copyright (c) Nordic Semiconductor ASA
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without modification,
00006  * are permitted provided that the following conditions are met:
00007  *
00008  *   1. Redistributions of source code must retain the above copyright notice, this
00009  *   list of conditions and the following disclaimer.
00010  *
00011  *   2. Redistributions in binary form must reproduce the above copyright notice, this
00012  *   list of conditions and the following disclaimer in the documentation and/or
00013  *   other materials provided with the distribution.
00014  *
00015  *   3. Neither the name of Nordic Semiconductor ASA nor the names of other
00016  *   contributors to this software may be used to endorse or promote products
00017  *   derived from this software without specific prior written permission.
00018  *
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00021  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00022  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00023  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00024  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00025  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00026  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00027  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00028  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00029  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030  *
00031  */
00032 
00033 
00034 #include "peer_database.h"
00035 
00036 #include <string.h>
00037 #include "peer_manager_types.h "
00038 #include "peer_data_storage.h"
00039 #include "pm_buffer.h"
00040 
00041 
00042 #define MAX_REGISTRANTS    6                         /**< The number of user that can register with the module. */
00043 
00044 #define MODULE_INITIALIZED (m_pdb.n_registrants > 0) /**< Expression which is true when the module is initialized. */
00045 
00046 #define N_WRITE_BUFFERS        8                     /**< The number of write buffers available. */
00047 #define N_WRITE_BUFFER_RECORDS (N_WRITE_BUFFERS)     /**< The number of write buffer records. */
00048 
00049 /**@brief Macro for verifying that the module is initialized. It will cause the function to return
00050  *        @ref NRF_ERROR_INVALID_STATE if not.
00051  */
00052 #define VERIFY_MODULE_INITIALIZED()     \
00053 do                                      \
00054 {                                       \
00055     if (!MODULE_INITIALIZED)            \
00056     {                                   \
00057         return NRF_ERROR_INVALID_STATE; \
00058     }                                   \
00059 } while(0)
00060 
00061 
00062 /**@brief Macro for verifying that the module is initialized. It will cause the function to return
00063  *        if not.
00064  */
00065 #define VERIFY_MODULE_INITIALIZED_VOID()\
00066 do                                      \
00067 {                                       \
00068     if (!MODULE_INITIALIZED)            \
00069     {                                   \
00070         return;                         \
00071     }                                   \
00072 } while(0)
00073 
00074 
00075 /**@brief Macro for verifying that the module is initialized. It will cause the function to return
00076  *        if not.
00077  *
00078  * @param[in] param  The variable to check if is NULL.
00079  */
00080 #define VERIFY_PARAM_NOT_NULL(param)    \
00081 do                                      \
00082 {                                       \
00083     if (param == NULL)                  \
00084     {                                   \
00085         return NRF_ERROR_NULL;          \
00086     }                                   \
00087 } while(0)
00088 
00089 
00090 typedef struct
00091 {
00092     pm_peer_id_t        peer_id;
00093     pm_peer_data_id_t   data_id;
00094     uint8_t             buffer_block_id;
00095     uint8_t             store_busy       : 1;
00096     uint8_t             store_flash_full : 1;
00097     uint8_t             store_requested  : 1;
00098     uint32_t            n_bufs;
00099     pm_prepare_token_t  prepare_token;
00100     pm_store_token_t    store_token;
00101 } pdb_buffer_record_t;
00102 
00103 typedef struct
00104 {
00105     pdb_evt_handler_t   evt_handlers[MAX_REGISTRANTS];
00106     uint8_t             n_registrants;
00107     pm_buffer_t         write_buffer;
00108     pdb_buffer_record_t write_buffer_records[N_WRITE_BUFFER_RECORDS];
00109     uint32_t            n_writes;
00110 } pdb_t;
00111 
00112 static pdb_t m_pdb = {.n_registrants = 0};
00113 
00114 
00115 /**@brief Function for invalidating a record of a write buffer allocation.
00116  *
00117  * @param[in]  p_record  The record to invalidate.
00118  */
00119 static void write_buffer_record_invalidate(pdb_buffer_record_t * p_record)
00120 {
00121     p_record->peer_id          = PM_PEER_ID_INVALID;
00122     p_record->data_id          = PM_PEER_DATA_ID_INVALID;
00123     p_record->buffer_block_id  = BUFFER_INVALID_ID;
00124     p_record->store_busy       = false;
00125     p_record->store_flash_full = false;
00126     p_record->store_requested  = false;
00127     p_record->n_bufs           = 0;
00128     p_record->prepare_token    = PDS_PREPARE_TOKEN_INVALID;
00129     p_record->store_token      = PDS_STORE_TOKEN_INVALID;
00130 }
00131 
00132 
00133 /**@brief Function for finding a record of a write buffer allocation.
00134  *
00135  * @param[in]  peer_id  The peer ID in the record.
00136  * @param[in]  data_id  The data ID in the record.
00137  *
00138  * @return  A pointer to the matching record, or NULL if none was found.
00139  */
00140 static pdb_buffer_record_t * write_buffer_record_find(pm_peer_id_t      peer_id,
00141                                                       pm_peer_data_id_t data_id)
00142 {
00143     for (int i = 0; i < N_WRITE_BUFFER_RECORDS; i++)
00144     {
00145         if   ((m_pdb.write_buffer_records[i].peer_id == peer_id)
00146            && (m_pdb.write_buffer_records[i].data_id == data_id))
00147         {
00148             return &m_pdb.write_buffer_records[i];
00149         }
00150     }
00151     return NULL;
00152 }
00153 
00154 
00155 /**@brief Function for finding an available record for write buffer allocation.
00156  *
00157  * @return  A pointer to the available record, or NULL if none was found.
00158  */
00159 static pdb_buffer_record_t * write_buffer_record_find_unused(void)
00160 {
00161     return write_buffer_record_find(PM_PEER_ID_INVALID, PM_PEER_DATA_ID_INVALID);
00162 }
00163 
00164 
00165 /**@brief Function for gracefully deactivating a write buffer record.
00166  *
00167  * @details This function will first release any buffers, then invalidate the record.
00168  *
00169  * @param[inout] p_write_buffer_record  The record to release.
00170  *
00171  * @return  A pointer to the matching record, or NULL if none was found.
00172  */
00173 static void write_buffer_record_release(pdb_buffer_record_t * p_write_buffer_record)
00174 {
00175     for (int i = 0; i < p_write_buffer_record->n_bufs; i++)
00176     {
00177         pm_buffer_release(&m_pdb.write_buffer, p_write_buffer_record->buffer_block_id + i);
00178     }
00179 
00180     write_buffer_record_invalidate(p_write_buffer_record);
00181 }
00182 
00183 
00184 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)
00185 {
00186     if (pp_write_buffer_record == NULL)
00187     {
00188         return;
00189     }
00190     *pp_write_buffer_record = write_buffer_record_find_unused();
00191     if (*pp_write_buffer_record == NULL)
00192     {
00193         // This also means the buffer is full.
00194         return;
00195     }
00196     (*pp_write_buffer_record)->peer_id = peer_id;
00197     (*pp_write_buffer_record)->data_id = data_id;
00198 }
00199 
00200 
00201 /**@brief Function for dispatching outbound events to all registered event handlers.
00202  *
00203  * @param[in]  p_event  The event to dispatch.
00204  */
00205 static void pdb_evt_send(pdb_evt_t * p_event)
00206 {
00207     for (int i = 0; i < m_pdb.n_registrants; i++)
00208     {
00209         m_pdb.evt_handlers[i](p_event);
00210     }
00211 }
00212 
00213 
00214 /**@brief Function for resetting the internal state of the Peer Database module.
00215  *
00216  * @param[out] p_event  The event to dispatch.
00217  */
00218 static void internal_state_reset(pdb_t * pdb)
00219 {
00220     memset(pdb, 0, sizeof(pdb_t));
00221     for (int i = 0; i < N_WRITE_BUFFER_RECORDS; i++)
00222     {
00223         write_buffer_record_invalidate(&pdb->write_buffer_records[i]);
00224     }
00225 }
00226 
00227 
00228 /**@brief Function for handling events from the Peer Data Storage module.
00229  *
00230  * @param[in]  p_event  The event to handle.
00231  */
00232 static void pds_evt_handler(pds_evt_t const * p_event)
00233 {
00234     ret_code_t            err_code;
00235     pdb_buffer_record_t * p_write_buffer_record;
00236     bool                  retry_flash_full = false;
00237     pdb_evt_t             event =
00238     {
00239         .peer_id = p_event->peer_id,
00240         .data_id = p_event->data_id,
00241     };
00242 
00243     p_write_buffer_record = write_buffer_record_find(p_event->peer_id, p_event->data_id);
00244 
00245     switch (p_event->evt_id)
00246     {
00247         case PDS_EVT_STORED:
00248             if (   (p_write_buffer_record != NULL)
00249                 //&& (p_write_buffer_record->store_token == p_event->store_token)
00250                 && (p_write_buffer_record->store_requested))
00251             {
00252                 write_buffer_record_release(p_write_buffer_record);
00253                 event.evt_id = PDB_EVT_WRITE_BUF_STORED;
00254                 pdb_evt_send(&event);
00255             }
00256             else
00257             {
00258                 event.evt_id = PDB_EVT_RAW_STORED;
00259                 pdb_evt_send(&event);
00260             }
00261             break;
00262         case PDS_EVT_ERROR_STORE:
00263             if (   (p_write_buffer_record != NULL)
00264                 && (p_write_buffer_record->store_token == p_event->store_token)
00265                 && (p_write_buffer_record->store_requested))
00266             {
00267                 // Retry if internal buffer.
00268                 m_pdb.n_writes++;
00269                 p_write_buffer_record->store_requested = false;
00270                 p_write_buffer_record->store_busy      = true;
00271             }
00272             else
00273             {
00274                 event.evt_id = PDB_EVT_RAW_STORE_FAILED;
00275                 pdb_evt_send(&event);
00276             }
00277             break;
00278         case PDS_EVT_CLEARED:
00279             event.evt_id = PDB_EVT_CLEARED;
00280             pdb_evt_send(&event);
00281             break;
00282         case PDS_EVT_ERROR_CLEAR:
00283             event.evt_id = PDB_EVT_CLEAR_FAILED;
00284             pdb_evt_send(&event);
00285             break;
00286         case PDS_EVT_COMPRESSED:
00287             retry_flash_full = true;
00288             event.evt_id = PDB_EVT_COMPRESSED;
00289             pdb_evt_send(&event);
00290             break;
00291         default:
00292             break;
00293     }
00294 
00295     if (m_pdb.n_writes > 0)
00296     {
00297         for (int i = 0; i < N_WRITE_BUFFER_RECORDS; i++)
00298         {
00299             if  ((m_pdb.write_buffer_records[i].store_busy)
00300               || (m_pdb.write_buffer_records[i].store_flash_full && retry_flash_full))
00301             {
00302                 err_code = pdb_write_buf_store(m_pdb.write_buffer_records[i].peer_id,
00303                                                m_pdb.write_buffer_records[i].data_id);
00304                 if (err_code != NRF_SUCCESS)
00305                 {
00306                     event.peer_id = m_pdb.write_buffer_records[i].peer_id;
00307                     event.data_id = m_pdb.write_buffer_records[i].data_id;
00308                     if (err_code == NRF_ERROR_NO_MEM)
00309                     {
00310                         event.evt_id = PDB_EVT_ERROR_NO_MEM;
00311                     }
00312                     else
00313                     {
00314                         event.evt_id = PDB_EVT_ERROR_UNEXPECTED;
00315                     }
00316 
00317                     pdb_evt_send(&event);
00318                     break;
00319                 }
00320             }
00321         }
00322     }
00323 }
00324 
00325 
00326 ret_code_t pdb_register(pdb_evt_handler_t evt_handler)
00327 {
00328     if (m_pdb.n_registrants >= MAX_REGISTRANTS)
00329     {
00330         return NRF_ERROR_NO_MEM;
00331     }
00332 
00333     VERIFY_PARAM_NOT_NULL(evt_handler);
00334 
00335     if (!MODULE_INITIALIZED)
00336     {
00337         ret_code_t err_code;
00338 
00339         internal_state_reset(&m_pdb);
00340         err_code = pds_register(pds_evt_handler);
00341         if (err_code != NRF_SUCCESS)
00342         {
00343             return err_code;
00344         }
00345         PM_BUFFER_INIT(&m_pdb.write_buffer, N_WRITE_BUFFERS, PDB_WRITE_BUF_SIZE, err_code);
00346         if (err_code != NRF_SUCCESS)
00347         {
00348             return err_code;
00349         }
00350     }
00351 
00352     m_pdb.evt_handlers[m_pdb.n_registrants] = evt_handler;
00353     m_pdb.n_registrants += 1;
00354 
00355     return NRF_SUCCESS;
00356 }
00357 
00358 
00359 pm_peer_id_t pdb_peer_allocate(void)
00360 {
00361     if (!MODULE_INITIALIZED)
00362     {
00363         return PM_PEER_ID_INVALID;
00364     }
00365 
00366     return pds_peer_id_allocate();
00367 }
00368 
00369 
00370 ret_code_t pdb_peer_free(pm_peer_id_t peer_id)
00371 {
00372     VERIFY_MODULE_INITIALIZED();
00373 
00374     return pds_peer_id_free(peer_id);
00375 }
00376 
00377 
00378 ret_code_t pdb_read_buf_get(pm_peer_id_t           peer_id,
00379                             pm_peer_data_id_t      data_id,
00380                             pm_peer_data_flash_t * p_peer_data,
00381                             pm_store_token_t     * p_token)
00382 {
00383     VERIFY_MODULE_INITIALIZED();
00384 
00385     return pds_peer_data_read_ptr_get(peer_id, data_id, p_peer_data, p_token);
00386 }
00387 
00388 
00389 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)
00390 {
00391     uint16_t n_bytes = n_bufs * PDB_WRITE_BUF_SIZE;
00392     p_peer_data->data_type    = data_id;
00393 
00394     switch(p_peer_data->data_type)
00395     {
00396         case PM_PEER_DATA_ID_BONDING:
00397             p_peer_data->data.p_bonding_data = (pm_peer_data_bonding_t *)p_buffer_memory;
00398             p_peer_data->length_words = PM_BONDING_DATA_N_WORDS();
00399             break;
00400         case PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING:
00401             p_peer_data->data.p_service_changed_pending = (bool *)p_buffer_memory;
00402             p_peer_data->length_words = PM_SC_STATE_N_WORDS();
00403             break;
00404         case PM_PEER_DATA_ID_GATT_LOCAL:
00405             p_peer_data->data.p_local_gatt_db = (pm_peer_data_local_gatt_db_t *)p_buffer_memory;
00406             p_peer_data->length_words = PM_LOCAL_DB_N_WORDS(n_bytes);
00407             break;
00408         case PM_PEER_DATA_ID_GATT_REMOTE:
00409             p_peer_data->data.p_remote_gatt_db = (pm_peer_data_remote_gatt_db_t *)p_buffer_memory;
00410             p_peer_data->length_words = PM_REMOTE_DB_N_WORDS(n_bytes / sizeof(ble_gatt_db_srv_t));
00411             break;
00412         case PM_PEER_DATA_ID_APPLICATION:
00413             p_peer_data->data.p_application_data = p_buffer_memory;
00414             p_peer_data->length_words = PM_N_WORDS(n_bytes);
00415             break;
00416         default:
00417             p_peer_data->length_words = 0;
00418             break;
00419     }
00420 }
00421 
00422 
00423 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)
00424 {
00425     peer_data_point_to_buffer((pm_peer_data_t*)p_peer_data, data_id, p_buffer_memory, n_bufs);
00426 }
00427 
00428 
00429 ret_code_t pdb_write_buf_get(pm_peer_id_t       peer_id,
00430                              pm_peer_data_id_t  data_id,
00431                              uint32_t           n_bufs,
00432                              pm_peer_data_t   * p_peer_data)
00433 {
00434     VERIFY_MODULE_INITIALIZED();
00435     VERIFY_PARAM_NOT_NULL(p_peer_data);
00436     if (   !PM_PEER_DATA_ID_IS_VALID(data_id)
00437         || (n_bufs == 0)
00438         || (n_bufs > N_WRITE_BUFFERS)
00439         || !pds_peer_id_is_allocated(peer_id))
00440     {
00441         return NRF_ERROR_INVALID_PARAM;
00442     }
00443 
00444     pdb_buffer_record_t * write_buffer_record;
00445     uint8_t             * p_buffer_memory;
00446 
00447     write_buffer_record = write_buffer_record_find(peer_id, data_id);
00448 
00449     if ((write_buffer_record != NULL) && (write_buffer_record->n_bufs < n_bufs))
00450     {
00451         // @TODO: Copy?
00452         // Existing buffer is too small.
00453         for (uint8_t i = 0; i < write_buffer_record->n_bufs; i++)
00454         {
00455             pm_buffer_release(&m_pdb.write_buffer, write_buffer_record->buffer_block_id + i);
00456         }
00457         write_buffer_record_invalidate(write_buffer_record);
00458         write_buffer_record = NULL;
00459     }
00460     else if ((write_buffer_record != NULL) && write_buffer_record->n_bufs > n_bufs)
00461     {
00462         // Release excess blocks.
00463         for (uint8_t i = n_bufs; i < write_buffer_record->n_bufs; i++)
00464         {
00465             pm_buffer_release(&m_pdb.write_buffer, write_buffer_record->buffer_block_id + i);
00466         }
00467     }
00468 
00469     if (write_buffer_record == NULL)
00470     {
00471         write_buffer_record_get(&write_buffer_record, peer_id, data_id);
00472         if (write_buffer_record == NULL)
00473         {
00474             return NRF_ERROR_BUSY;
00475         }
00476     }
00477 
00478     if (write_buffer_record->buffer_block_id == BUFFER_INVALID_ID)
00479     {
00480         write_buffer_record->buffer_block_id = pm_buffer_block_acquire(&m_pdb.write_buffer, n_bufs);
00481 
00482         if (write_buffer_record->buffer_block_id == BUFFER_INVALID_ID)
00483         {
00484             write_buffer_record_invalidate(write_buffer_record);
00485             return NRF_ERROR_BUSY;
00486         }
00487     }
00488 
00489     write_buffer_record->n_bufs = n_bufs;
00490 
00491     p_buffer_memory = pm_buffer_ptr_get(&m_pdb.write_buffer, write_buffer_record->buffer_block_id);
00492 
00493     if (p_buffer_memory == NULL)
00494     {
00495         return NRF_ERROR_INTERNAL;
00496     }
00497 
00498     peer_data_point_to_buffer(p_peer_data, data_id, p_buffer_memory, n_bufs);
00499     switch(data_id)
00500     {
00501         case PM_PEER_DATA_ID_BONDING:
00502             /* No action needed. */
00503             break;
00504         case PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING:
00505             /* No action needed. */
00506             break;
00507         case PM_PEER_DATA_ID_GATT_LOCAL:
00508         {
00509             uint32_t size_offset = sizeof(pm_peer_data_local_gatt_db_t);
00510             p_peer_data->data.p_local_gatt_db->p_data = &p_buffer_memory[size_offset];
00511             p_peer_data->data.p_local_gatt_db->len    = (PDB_WRITE_BUF_SIZE*n_bufs)-size_offset;
00512         }
00513             break;
00514         case PM_PEER_DATA_ID_GATT_REMOTE:
00515         {
00516             uint32_t size_offset = sizeof(pm_peer_data_remote_gatt_db_t);
00517             p_peer_data->data.p_remote_gatt_db->p_data = (ble_gatt_db_srv_t*)&(p_buffer_memory[size_offset]);
00518             p_peer_data->data.p_remote_gatt_db->service_count
00519                             = ((PDB_WRITE_BUF_SIZE*n_bufs)-size_offset)/sizeof(ble_gatt_db_srv_t);
00520         }
00521             break;
00522         case PM_PEER_DATA_ID_APPLICATION:
00523         {
00524             p_peer_data->data.p_application_data = p_buffer_memory;
00525         }
00526             break;
00527         default:
00528             // Invalid data_id. This should have been picked up earlier.
00529             return NRF_ERROR_INTERNAL;
00530     }
00531 
00532     return NRF_SUCCESS;
00533 }
00534 
00535 
00536 ret_code_t pdb_write_buf_release(pm_peer_id_t peer_id, pm_peer_data_id_t data_id)
00537 {
00538     VERIFY_MODULE_INITIALIZED();
00539 
00540     ret_code_t            err_code = NRF_SUCCESS;
00541     pdb_buffer_record_t * p_write_buffer_record;
00542     p_write_buffer_record = write_buffer_record_find(peer_id, data_id);
00543 
00544     if (p_write_buffer_record == NULL)
00545     {
00546         return NRF_ERROR_NOT_FOUND;
00547     }
00548 
00549     if (p_write_buffer_record->prepare_token != PDS_PREPARE_TOKEN_INVALID)
00550     {
00551         err_code = pds_peer_data_write_prepare_cancel(p_write_buffer_record->prepare_token);
00552         if (err_code != NRF_SUCCESS)
00553         {
00554             err_code = NRF_ERROR_INTERNAL;
00555         }
00556     }
00557 
00558     write_buffer_record_release(p_write_buffer_record);
00559 
00560     return err_code;
00561 }
00562 
00563 
00564 ret_code_t pdb_write_buf_store_prepare(pm_peer_id_t peer_id, pm_peer_data_id_t data_id)
00565 {
00566     VERIFY_MODULE_INITIALIZED();
00567 
00568     ret_code_t            err_code = NRF_SUCCESS;
00569     pdb_buffer_record_t * p_write_buffer_record;
00570     p_write_buffer_record = write_buffer_record_find(peer_id, data_id);
00571 
00572     if (p_write_buffer_record == NULL)
00573     {
00574         return NRF_ERROR_NOT_FOUND;
00575     }
00576 
00577     if (p_write_buffer_record->prepare_token == PDS_PREPARE_TOKEN_INVALID)
00578     {
00579         uint8_t * p_buffer_memory = pm_buffer_ptr_get(&m_pdb.write_buffer, p_write_buffer_record->buffer_block_id);
00580         pm_peer_data_const_t peer_data = {.data_type = data_id};
00581 
00582         if (p_buffer_memory == NULL)
00583         {
00584             return NRF_ERROR_INTERNAL;
00585         }
00586 
00587         peer_data_const_point_to_buffer(&peer_data, data_id, p_buffer_memory, p_write_buffer_record->n_bufs);
00588 
00589         err_code = pds_peer_data_write_prepare(&peer_data, &p_write_buffer_record->prepare_token);
00590         if (err_code == NRF_ERROR_INVALID_LENGTH)
00591         {
00592             return NRF_ERROR_INTERNAL;
00593         }
00594     }
00595 
00596     return err_code;
00597 }
00598 
00599 
00600 static ret_code_t write_or_update(pm_peer_id_t           peer_id,
00601                                   pm_peer_data_id_t      data_id,
00602                                   pm_peer_data_const_t * p_peer_data,
00603                                   pm_store_token_t     * p_store_token,
00604                                   pm_prepare_token_t     prepare_token)
00605 {
00606     pm_peer_data_flash_t old_peer_data;
00607     pm_store_token_t     old_store_token;
00608     ret_code_t err_code = pds_peer_data_read_ptr_get(peer_id, data_id, &old_peer_data, &old_store_token);
00609 
00610     if (err_code == NRF_SUCCESS)
00611     {
00612         pds_peer_data_write_prepare_cancel(prepare_token);
00613         err_code = pds_peer_data_update(peer_id, p_peer_data, old_store_token, p_store_token);
00614     }
00615     else if (err_code == NRF_ERROR_NOT_FOUND)
00616     {
00617         if (prepare_token == PDS_PREPARE_TOKEN_INVALID)
00618         {
00619             err_code = pds_peer_data_write(peer_id, p_peer_data, p_store_token);
00620         }
00621         else
00622         {
00623             err_code = pds_peer_data_write_prepared(peer_id, p_peer_data, prepare_token, p_store_token);
00624         }
00625     }
00626     return err_code;
00627 }
00628 
00629 
00630 ret_code_t pdb_write_buf_store(pm_peer_id_t      peer_id,
00631                                pm_peer_data_id_t data_id)
00632 {
00633     VERIFY_MODULE_INITIALIZED();
00634 
00635     ret_code_t            err_code = NRF_SUCCESS;
00636     pdb_buffer_record_t * p_write_buffer_record;
00637     uint8_t             * p_buffer_memory;
00638     pm_peer_data_const_t  peer_data = {.data_type = data_id};
00639 
00640 
00641     p_write_buffer_record = write_buffer_record_find(peer_id, data_id);
00642 
00643     if (p_write_buffer_record == NULL)
00644     {
00645         return NRF_ERROR_NOT_FOUND;
00646     }
00647 
00648     if (p_write_buffer_record->store_requested)
00649     {
00650         return NRF_SUCCESS;
00651     }
00652 
00653     p_buffer_memory = pm_buffer_ptr_get(&m_pdb.write_buffer, p_write_buffer_record->buffer_block_id);
00654 
00655     if (p_buffer_memory == NULL)
00656     {
00657         return NRF_ERROR_INTERNAL;
00658     }
00659 
00660     peer_data_const_point_to_buffer(&peer_data, data_id, p_buffer_memory, p_write_buffer_record->n_bufs);
00661 
00662     switch (data_id)
00663     {
00664         case PM_PEER_DATA_ID_BONDING:
00665             peer_data.length_words = PM_BONDING_DATA_N_WORDS();
00666             break;
00667         case PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING:
00668             peer_data.length_words = PM_SC_STATE_N_WORDS();
00669             break;
00670         case PM_PEER_DATA_ID_GATT_LOCAL:
00671             peer_data.length_words = PM_LOCAL_DB_N_WORDS(peer_data.data.p_local_gatt_db->len);
00672             break;
00673         case PM_PEER_DATA_ID_GATT_REMOTE:
00674             peer_data.length_words = PM_REMOTE_DB_N_WORDS(peer_data.data.p_remote_gatt_db->service_count);
00675             break;
00676         case PM_PEER_DATA_ID_APPLICATION:
00677             peer_data.length_words = PM_N_WORDS(p_write_buffer_record->n_bufs * PDB_WRITE_BUF_SIZE);
00678             break;
00679         default:
00680             return NRF_ERROR_INVALID_PARAM;
00681     }
00682 
00683     err_code = write_or_update(peer_id, data_id, &peer_data, &p_write_buffer_record->store_token, p_write_buffer_record->prepare_token);
00684 
00685     if (p_write_buffer_record->store_busy && p_write_buffer_record->store_flash_full)
00686     {
00687         m_pdb.n_writes--;
00688     }
00689 
00690     if (err_code == NRF_SUCCESS)
00691     {
00692         p_write_buffer_record->store_requested  = true;
00693         p_write_buffer_record->store_busy       = false;
00694         p_write_buffer_record->store_flash_full = false;
00695     }
00696     else
00697     {
00698         if (err_code == NRF_ERROR_BUSY)
00699         {
00700             m_pdb.n_writes++;
00701             p_write_buffer_record->store_busy       = true;
00702             p_write_buffer_record->store_flash_full = false;
00703             err_code = NRF_SUCCESS;
00704         }
00705         else if (err_code == NRF_ERROR_NO_MEM)
00706         {
00707             m_pdb.n_writes++;
00708             p_write_buffer_record->store_busy       = false;
00709             p_write_buffer_record->store_flash_full = true;
00710         }
00711         else if ((err_code != NRF_ERROR_NO_MEM) && (err_code != NRF_ERROR_INVALID_PARAM))
00712         {
00713             err_code = NRF_ERROR_INTERNAL;
00714         }
00715     }
00716 
00717     return err_code;
00718 }
00719 
00720 
00721 ret_code_t pdb_clear(pm_peer_id_t peer_id, pm_peer_data_id_t data_id)
00722 {
00723     VERIFY_MODULE_INITIALIZED();
00724 
00725     return pds_peer_data_clear(peer_id, data_id);
00726 }
00727 
00728 
00729 uint32_t pdb_n_peers(void)
00730 {
00731     if (!MODULE_INITIALIZED)
00732     {
00733         return 0;
00734     }
00735 
00736     return pds_n_peers();
00737 }
00738 
00739 
00740 pm_peer_id_t pdb_next_peer_id_get(pm_peer_id_t prev_peer_id)
00741 {
00742     if (!MODULE_INITIALIZED)
00743     {
00744         return PM_PEER_ID_INVALID;
00745     }
00746 
00747     return pds_next_peer_id_get(prev_peer_id);
00748 }
00749 
00750 
00751 ret_code_t pdb_raw_read(pm_peer_id_t      peer_id,
00752                         pm_peer_data_id_t data_id,
00753                         pm_peer_data_t  * p_peer_data)
00754 {
00755     VERIFY_MODULE_INITIALIZED();
00756     return pds_peer_data_read(peer_id, data_id, p_peer_data, &p_peer_data->length_words);
00757 }
00758 
00759 
00760 ret_code_t pdb_raw_store(pm_peer_id_t           peer_id,
00761                          pm_peer_data_const_t * p_peer_data,
00762                          pm_store_token_t     * p_store_token)
00763 {
00764     VERIFY_MODULE_INITIALIZED();
00765     
00766     return write_or_update(peer_id, p_peer_data->data_type, p_peer_data, p_store_token, PDS_PREPARE_TOKEN_INVALID);
00767 }
00768