add files from nrf52832 bootloader project
This commit is contained in:
		@@ -0,0 +1,649 @@
 | 
			
		||||
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * The information contained herein is property of Nordic Semiconductor ASA.
 | 
			
		||||
 * Terms and conditions of usage are described in detail in NORDIC
 | 
			
		||||
 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensees are granted free, non-transferable use of the information. NO
 | 
			
		||||
 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
 | 
			
		||||
 * the file.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "ble_dfu.h"
 | 
			
		||||
#include "ble_types.h"
 | 
			
		||||
#include "ble_gatts.h"
 | 
			
		||||
#include "ble_srv_common.h"
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include "sdk_common.h"
 | 
			
		||||
 | 
			
		||||
#define MAX_DFU_PKT_LEN         20                                              /**< Maximum length (in bytes) of the DFU Packet characteristic. */
 | 
			
		||||
#define PKT_START_DFU_PARAM_LEN 2                                               /**< Length (in bytes) of the parameters for Packet Start DFU Request. */
 | 
			
		||||
#define PKT_INIT_DFU_PARAM_LEN  2                                               /**< Length (in bytes) of the parameters for Packet Init DFU Request. */
 | 
			
		||||
#define PKT_RCPT_NOTIF_REQ_LEN  3                                               /**< Length (in bytes) of the Packet Receipt Notification Request. */
 | 
			
		||||
#define MAX_PKTS_RCPT_NOTIF_LEN 6                                               /**< Maximum length (in bytes) of the Packets Receipt Notification. */
 | 
			
		||||
#define MAX_RESPONSE_LEN        7                                               /**< Maximum length (in bytes) of the response to a Control Point command. */
 | 
			
		||||
#define MAX_NOTIF_BUFFER_LEN    MAX(MAX_PKTS_RCPT_NOTIF_LEN, MAX_RESPONSE_LEN)  /**< Maximum length (in bytes) of the buffer needed by DFU Service while sending notifications to peer. */
 | 
			
		||||
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
    OP_CODE_START_DFU          = 1,                                             /**< Value of the Op code field for 'Start DFU' command.*/
 | 
			
		||||
    OP_CODE_RECEIVE_INIT       = 2,                                             /**< Value of the Op code field for 'Initialize DFU parameters' command.*/
 | 
			
		||||
    OP_CODE_RECEIVE_FW         = 3,                                             /**< Value of the Op code field for 'Receive firmware image' command.*/
 | 
			
		||||
    OP_CODE_VALIDATE           = 4,                                             /**< Value of the Op code field for 'Validate firmware' command.*/
 | 
			
		||||
    OP_CODE_ACTIVATE_N_RESET   = 5,                                             /**< Value of the Op code field for 'Activate & Reset' command.*/
 | 
			
		||||
    OP_CODE_SYS_RESET          = 6,                                             /**< Value of the Op code field for 'Reset System' command.*/
 | 
			
		||||
    OP_CODE_IMAGE_SIZE_REQ     = 7,                                             /**< Value of the Op code field for 'Report received image size' command.*/
 | 
			
		||||
    OP_CODE_PKT_RCPT_NOTIF_REQ = 8,                                             /**< Value of the Op code field for 'Request packet receipt notification.*/
 | 
			
		||||
    OP_CODE_RESPONSE           = 16,                                            /**< Value of the Op code field for 'Response.*/
 | 
			
		||||
    OP_CODE_PKT_RCPT_NOTIF     = 17                                             /**< Value of the Op code field for 'Packets Receipt Notification'.*/
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static bool     m_is_dfu_service_initialized = false;                           /**< Variable to check if the DFU service was initialized by the application.*/
 | 
			
		||||
static uint8_t  m_notif_buffer[MAX_NOTIF_BUFFER_LEN];                           /**< Buffer used for sending notifications to peer. */
 | 
			
		||||
 | 
			
		||||
/**@brief       Function for adding DFU Packet characteristic to the BLE Stack.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]   p_dfu DFU Service structure.
 | 
			
		||||
 *
 | 
			
		||||
 * @return      NRF_SUCCESS on success. Otherwise an error code.
 | 
			
		||||
 */
 | 
			
		||||
static uint32_t dfu_pkt_char_add(ble_dfu_t * const p_dfu)
 | 
			
		||||
{
 | 
			
		||||
    ble_gatts_char_md_t char_md;
 | 
			
		||||
    ble_gatts_attr_t    attr_char_value;
 | 
			
		||||
    ble_uuid_t          char_uuid;
 | 
			
		||||
    ble_gatts_attr_md_t attr_md;
 | 
			
		||||
 | 
			
		||||
    memset(&char_md, 0, sizeof(char_md));
 | 
			
		||||
 | 
			
		||||
    char_md.char_props.write_wo_resp = 1;
 | 
			
		||||
    char_md.p_char_user_desc         = NULL;
 | 
			
		||||
    char_md.p_char_pf                = NULL;
 | 
			
		||||
    char_md.p_user_desc_md           = NULL;
 | 
			
		||||
    char_md.p_cccd_md                = NULL;
 | 
			
		||||
    char_md.p_sccd_md                = NULL;
 | 
			
		||||
 | 
			
		||||
    char_uuid.type = p_dfu->uuid_type;
 | 
			
		||||
    char_uuid.uuid = BLE_DFU_PKT_CHAR_UUID;
 | 
			
		||||
 | 
			
		||||
    memset(&attr_md, 0, sizeof(attr_md));
 | 
			
		||||
 | 
			
		||||
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.read_perm);
 | 
			
		||||
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
 | 
			
		||||
 | 
			
		||||
    attr_md.vloc    = BLE_GATTS_VLOC_STACK;
 | 
			
		||||
    attr_md.rd_auth = 0;
 | 
			
		||||
    attr_md.wr_auth = 0;
 | 
			
		||||
    attr_md.vlen    = 1;
 | 
			
		||||
 | 
			
		||||
    memset(&attr_char_value, 0, sizeof(attr_char_value));
 | 
			
		||||
 | 
			
		||||
    attr_char_value.p_uuid    = &char_uuid;
 | 
			
		||||
    attr_char_value.p_attr_md = &attr_md;
 | 
			
		||||
    attr_char_value.init_len  = 0;
 | 
			
		||||
    attr_char_value.init_offs = 0;
 | 
			
		||||
    attr_char_value.max_len   = MAX_DFU_PKT_LEN;
 | 
			
		||||
    attr_char_value.p_value   = NULL;
 | 
			
		||||
 | 
			
		||||
    return sd_ble_gatts_characteristic_add(p_dfu->service_handle,
 | 
			
		||||
                                           &char_md,
 | 
			
		||||
                                           &attr_char_value,
 | 
			
		||||
                                           &p_dfu->dfu_pkt_handles);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**@brief       Function for adding DFU Revision characteristic to the BLE Stack.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]   p_dfu DFU Service structure.
 | 
			
		||||
 *
 | 
			
		||||
 * @return      NRF_SUCCESS on success. Otherwise an error code.
 | 
			
		||||
 */
 | 
			
		||||
static uint32_t dfu_rev_char_add(ble_dfu_t * const p_dfu, ble_dfu_init_t const * const p_dfu_init)
 | 
			
		||||
{
 | 
			
		||||
    ble_gatts_char_md_t char_md;
 | 
			
		||||
    ble_gatts_attr_t    attr_char_value;
 | 
			
		||||
    ble_uuid_t          char_uuid;
 | 
			
		||||
    ble_gatts_attr_md_t attr_md;
 | 
			
		||||
 | 
			
		||||
    memset(&char_md, 0, sizeof(char_md));
 | 
			
		||||
 | 
			
		||||
    char_md.char_props.read          = 1;
 | 
			
		||||
    char_md.p_char_user_desc         = NULL;
 | 
			
		||||
    char_md.p_char_pf                = NULL;
 | 
			
		||||
    char_md.p_user_desc_md           = NULL;
 | 
			
		||||
    char_md.p_cccd_md                = NULL;
 | 
			
		||||
    char_md.p_sccd_md                = NULL;
 | 
			
		||||
 | 
			
		||||
    char_uuid.type = p_dfu->uuid_type;
 | 
			
		||||
    char_uuid.uuid = BLE_DFU_REV_CHAR_UUID;
 | 
			
		||||
 | 
			
		||||
    memset(&attr_md, 0, sizeof(attr_md));
 | 
			
		||||
 | 
			
		||||
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
 | 
			
		||||
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.write_perm);
 | 
			
		||||
 | 
			
		||||
    attr_md.vloc    = BLE_GATTS_VLOC_STACK;
 | 
			
		||||
    attr_md.rd_auth = 0;
 | 
			
		||||
    attr_md.wr_auth = 0;
 | 
			
		||||
    attr_md.vlen    = 1;
 | 
			
		||||
 | 
			
		||||
    memset(&attr_char_value, 0, sizeof(attr_char_value));
 | 
			
		||||
 | 
			
		||||
    attr_char_value.p_uuid    = &char_uuid;
 | 
			
		||||
    attr_char_value.p_attr_md = &attr_md;
 | 
			
		||||
    attr_char_value.init_len  = sizeof(uint16_t);
 | 
			
		||||
    attr_char_value.init_offs = 0;
 | 
			
		||||
    attr_char_value.max_len   = sizeof(uint16_t);
 | 
			
		||||
    attr_char_value.p_value   = (uint8_t *)&p_dfu_init->revision;
 | 
			
		||||
 | 
			
		||||
    return sd_ble_gatts_characteristic_add(p_dfu->service_handle,
 | 
			
		||||
                                           &char_md,
 | 
			
		||||
                                           &attr_char_value,
 | 
			
		||||
                                           &p_dfu->dfu_rev_handles);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**@brief       Function for adding DFU Control Point characteristic to the BLE Stack.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]   p_dfu DFU Service structure.
 | 
			
		||||
 *
 | 
			
		||||
 * @return      NRF_SUCCESS on success. Otherwise an error code.
 | 
			
		||||
 */
 | 
			
		||||
static uint32_t dfu_ctrl_pt_add(ble_dfu_t * const p_dfu)
 | 
			
		||||
{
 | 
			
		||||
    ble_gatts_char_md_t char_md;
 | 
			
		||||
    ble_gatts_attr_t    attr_char_value;
 | 
			
		||||
    ble_uuid_t          char_uuid;
 | 
			
		||||
    ble_gatts_attr_md_t attr_md;
 | 
			
		||||
 | 
			
		||||
    memset(&char_md, 0, sizeof(char_md));
 | 
			
		||||
 | 
			
		||||
    char_md.char_props.write  = 1;
 | 
			
		||||
    char_md.char_props.notify = 1;
 | 
			
		||||
    char_md.p_char_user_desc  = NULL;
 | 
			
		||||
    char_md.p_char_pf         = NULL;
 | 
			
		||||
    char_md.p_user_desc_md    = NULL;
 | 
			
		||||
    char_md.p_cccd_md         = NULL;
 | 
			
		||||
    char_md.p_sccd_md         = NULL;
 | 
			
		||||
 | 
			
		||||
    char_uuid.type = p_dfu->uuid_type;
 | 
			
		||||
    char_uuid.uuid = BLE_DFU_CTRL_PT_UUID;
 | 
			
		||||
 | 
			
		||||
    memset(&attr_md, 0, sizeof(attr_md));
 | 
			
		||||
 | 
			
		||||
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.read_perm);
 | 
			
		||||
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
 | 
			
		||||
 | 
			
		||||
    attr_md.vloc    = BLE_GATTS_VLOC_STACK;
 | 
			
		||||
    attr_md.rd_auth = 0;
 | 
			
		||||
    attr_md.wr_auth = 1;
 | 
			
		||||
    attr_md.vlen    = 1;
 | 
			
		||||
 | 
			
		||||
    memset(&attr_char_value, 0, sizeof(attr_char_value));
 | 
			
		||||
 | 
			
		||||
    attr_char_value.p_uuid    = &char_uuid;
 | 
			
		||||
    attr_char_value.p_attr_md = &attr_md;
 | 
			
		||||
    attr_char_value.init_len  = 0;
 | 
			
		||||
    attr_char_value.init_offs = 0;
 | 
			
		||||
    attr_char_value.max_len   = BLE_GATT_ATT_MTU_DEFAULT;
 | 
			
		||||
    attr_char_value.p_value   = NULL;
 | 
			
		||||
 | 
			
		||||
    return sd_ble_gatts_characteristic_add(p_dfu->service_handle,
 | 
			
		||||
                                           &char_md,
 | 
			
		||||
                                           &attr_char_value,
 | 
			
		||||
                                           &p_dfu->dfu_ctrl_pt_handles);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**@brief     Function for handling the @ref BLE_GAP_EVT_CONNECTED event from the S110 SoftDevice.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] p_dfu     DFU Service Structure.
 | 
			
		||||
 * @param[in] p_ble_evt Pointer to the event received from BLE stack.
 | 
			
		||||
 */
 | 
			
		||||
static void on_connect(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
 | 
			
		||||
{
 | 
			
		||||
    p_dfu->conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**@brief     Function for checking if the CCCD of DFU Control point is configured for Notification.
 | 
			
		||||
 *
 | 
			
		||||
 * @details   This function checks if the CCCD of DFU Control Point characteristic is configured
 | 
			
		||||
 *            for Notification by the DFU Controller.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] p_dfu DFU Service structure.
 | 
			
		||||
 *
 | 
			
		||||
 * @return    True if the CCCD of DFU Control Point characteristic is configured for Notification.
 | 
			
		||||
 *            False otherwise.
 | 
			
		||||
 */
 | 
			
		||||
static bool is_cccd_configured(ble_dfu_t * p_dfu)
 | 
			
		||||
{
 | 
			
		||||
    // Check if the CCCDs are configured.
 | 
			
		||||
    uint8_t  cccd_val_buf[BLE_CCCD_VALUE_LEN];
 | 
			
		||||
    ble_gatts_value_t gatts_value;
 | 
			
		||||
 | 
			
		||||
    // Initialize value struct.
 | 
			
		||||
    memset(&gatts_value, 0, sizeof(gatts_value));
 | 
			
		||||
 | 
			
		||||
    gatts_value.len     = BLE_CCCD_VALUE_LEN;
 | 
			
		||||
    gatts_value.offset  = 0;
 | 
			
		||||
    gatts_value.p_value = cccd_val_buf;
 | 
			
		||||
 | 
			
		||||
    // Check the CCCD Value of DFU Control Point.
 | 
			
		||||
    uint32_t err_code = sd_ble_gatts_value_get(p_dfu->conn_handle,
 | 
			
		||||
                                               p_dfu->dfu_ctrl_pt_handles.cccd_handle,
 | 
			
		||||
                                               &gatts_value);
 | 
			
		||||
    if (err_code != NRF_SUCCESS)
 | 
			
		||||
    {
 | 
			
		||||
        if (p_dfu->error_handler != NULL)
 | 
			
		||||
        {
 | 
			
		||||
            p_dfu->error_handler(err_code);
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ble_srv_is_notification_enabled(cccd_val_buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**@brief     Function for handling a Write event on the Control Point characteristic.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] p_dfu             DFU Service Structure.
 | 
			
		||||
 * @param[in] p_ble_write_evt   Pointer to the write event received from BLE stack.
 | 
			
		||||
 *
 | 
			
		||||
 * @return    NRF_SUCCESS on successful processing of control point write. Otherwise an error code.
 | 
			
		||||
 */
 | 
			
		||||
static uint32_t on_ctrl_pt_write(ble_dfu_t * p_dfu, ble_gatts_evt_write_t * p_ble_write_evt)
 | 
			
		||||
{
 | 
			
		||||
    ble_gatts_rw_authorize_reply_params_t auth_reply;
 | 
			
		||||
 | 
			
		||||
    auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
 | 
			
		||||
    auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
 | 
			
		||||
    auth_reply.params.write.update = 1;
 | 
			
		||||
    auth_reply.params.write.offset = p_ble_write_evt->offset;
 | 
			
		||||
    auth_reply.params.write.len = p_ble_write_evt->len;
 | 
			
		||||
    auth_reply.params.write.p_data = p_ble_write_evt->data;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if (!is_cccd_configured(p_dfu))
 | 
			
		||||
    {
 | 
			
		||||
        // Send an error response to the peer indicating that the CCCD is improperly configured.
 | 
			
		||||
        auth_reply.params.write.gatt_status =
 | 
			
		||||
            BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR;
 | 
			
		||||
 | 
			
		||||
        return (sd_ble_gatts_rw_authorize_reply(p_dfu->conn_handle, &auth_reply));
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t err_code;
 | 
			
		||||
 | 
			
		||||
        auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
 | 
			
		||||
 | 
			
		||||
        err_code = (sd_ble_gatts_rw_authorize_reply(p_dfu->conn_handle, &auth_reply));
 | 
			
		||||
        VERIFY_SUCCESS(err_code);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ble_dfu_evt_t ble_dfu_evt;
 | 
			
		||||
 | 
			
		||||
    switch (p_ble_write_evt->data[0])
 | 
			
		||||
    {
 | 
			
		||||
        case OP_CODE_START_DFU:
 | 
			
		||||
            ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_START;
 | 
			
		||||
 | 
			
		||||
            if (p_ble_write_evt->len < PKT_START_DFU_PARAM_LEN)
 | 
			
		||||
            {
 | 
			
		||||
                return ble_dfu_response_send(p_dfu,
 | 
			
		||||
                                             (ble_dfu_procedure_t) p_ble_write_evt->data[0],
 | 
			
		||||
                                             BLE_DFU_RESP_VAL_OPER_FAILED);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            ble_dfu_evt.evt.ble_dfu_pkt_write.len    = 1;
 | 
			
		||||
            ble_dfu_evt.evt.ble_dfu_pkt_write.p_data = &(p_ble_write_evt->data[1]);
 | 
			
		||||
 | 
			
		||||
            p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case OP_CODE_RECEIVE_INIT:
 | 
			
		||||
            ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_RECEIVE_INIT_DATA;
 | 
			
		||||
 | 
			
		||||
            if (p_ble_write_evt->len < PKT_INIT_DFU_PARAM_LEN)
 | 
			
		||||
            {
 | 
			
		||||
                return ble_dfu_response_send(p_dfu,
 | 
			
		||||
                                             (ble_dfu_procedure_t) p_ble_write_evt->data[0],
 | 
			
		||||
                                             BLE_DFU_RESP_VAL_OPER_FAILED);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            ble_dfu_evt.evt.ble_dfu_pkt_write.len    = 1;
 | 
			
		||||
            ble_dfu_evt.evt.ble_dfu_pkt_write.p_data = &(p_ble_write_evt->data[1]);
 | 
			
		||||
 | 
			
		||||
            p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case OP_CODE_RECEIVE_FW:
 | 
			
		||||
            ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_RECEIVE_APP_DATA;
 | 
			
		||||
 | 
			
		||||
            p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case OP_CODE_VALIDATE:
 | 
			
		||||
            ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_VALIDATE;
 | 
			
		||||
 | 
			
		||||
            p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case OP_CODE_ACTIVATE_N_RESET:
 | 
			
		||||
            ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_ACTIVATE_N_RESET;
 | 
			
		||||
 | 
			
		||||
            p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case OP_CODE_SYS_RESET:
 | 
			
		||||
            ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_SYS_RESET;
 | 
			
		||||
 | 
			
		||||
            p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case OP_CODE_PKT_RCPT_NOTIF_REQ:
 | 
			
		||||
            if (p_ble_write_evt->len < PKT_RCPT_NOTIF_REQ_LEN)
 | 
			
		||||
            {
 | 
			
		||||
                return (ble_dfu_response_send(p_dfu,
 | 
			
		||||
                                              BLE_DFU_PKT_RCPT_REQ_PROCEDURE,
 | 
			
		||||
                                              BLE_DFU_RESP_VAL_NOT_SUPPORTED));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            ble_dfu_evt.evt.pkt_rcpt_notif_req.num_of_pkts =
 | 
			
		||||
                uint16_decode(&(p_ble_write_evt->data[1]));
 | 
			
		||||
 | 
			
		||||
            if (ble_dfu_evt.evt.pkt_rcpt_notif_req.num_of_pkts == 0)
 | 
			
		||||
            {
 | 
			
		||||
                ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_PKT_RCPT_NOTIF_DISABLED;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_PKT_RCPT_NOTIF_ENABLED;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
 | 
			
		||||
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case OP_CODE_IMAGE_SIZE_REQ:
 | 
			
		||||
            ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_BYTES_RECEIVED_SEND;
 | 
			
		||||
 | 
			
		||||
            p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        default:
 | 
			
		||||
            // Unsupported op code.
 | 
			
		||||
            return ble_dfu_response_send(p_dfu,
 | 
			
		||||
                                         (ble_dfu_procedure_t) p_ble_write_evt->data[0],
 | 
			
		||||
                                         BLE_DFU_RESP_VAL_NOT_SUPPORTED);
 | 
			
		||||
    }
 | 
			
		||||
    return NRF_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**@brief     Function for handling the @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST event from the S110
 | 
			
		||||
 *            Stack.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] p_dfu     DFU Service Structure.
 | 
			
		||||
 * @param[in] p_ble_evt Pointer to the event received from BLE stack.
 | 
			
		||||
 */
 | 
			
		||||
static void on_rw_authorize_req(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
 | 
			
		||||
{
 | 
			
		||||
    ble_gatts_evt_rw_authorize_request_t * p_authorize_request;
 | 
			
		||||
 | 
			
		||||
    p_authorize_request = &(p_ble_evt->evt.gatts_evt.params.authorize_request);
 | 
			
		||||
 | 
			
		||||
    if (
 | 
			
		||||
        (p_authorize_request->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
 | 
			
		||||
        &&
 | 
			
		||||
        (p_authorize_request->request.write.handle == p_dfu->dfu_ctrl_pt_handles.value_handle)
 | 
			
		||||
        && 
 | 
			
		||||
        (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op != BLE_GATTS_OP_PREP_WRITE_REQ)
 | 
			
		||||
        &&
 | 
			
		||||
        (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_NOW)
 | 
			
		||||
        &&
 | 
			
		||||
        (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)
 | 
			
		||||
       )
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t err_code;
 | 
			
		||||
 | 
			
		||||
        err_code = on_ctrl_pt_write(p_dfu, &(p_authorize_request->request.write));
 | 
			
		||||
 | 
			
		||||
        if (err_code != NRF_SUCCESS && p_dfu->error_handler != NULL)
 | 
			
		||||
        {
 | 
			
		||||
            p_dfu->error_handler(err_code);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**@brief     Function for handling the @ref BLE_GATTS_EVT_WRITE event from the S110 SoftDevice.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] p_dfu     DFU Service Structure.
 | 
			
		||||
 * @param[in] p_ble_evt Pointer to the event received from BLE stack.
 | 
			
		||||
 */
 | 
			
		||||
static void on_write(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
 | 
			
		||||
{
 | 
			
		||||
    if (p_ble_evt->evt.gatts_evt.params.write.handle == p_dfu->dfu_pkt_handles.value_handle)
 | 
			
		||||
    {
 | 
			
		||||
        // DFU Packet written
 | 
			
		||||
 | 
			
		||||
        ble_dfu_evt_t ble_dfu_evt;
 | 
			
		||||
 | 
			
		||||
        ble_dfu_evt.ble_dfu_evt_type             = BLE_DFU_PACKET_WRITE;
 | 
			
		||||
        ble_dfu_evt.evt.ble_dfu_pkt_write.len    = p_ble_evt->evt.gatts_evt.params.write.len;
 | 
			
		||||
        ble_dfu_evt.evt.ble_dfu_pkt_write.p_data = p_ble_evt->evt.gatts_evt.params.write.data;
 | 
			
		||||
 | 
			
		||||
        p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**@brief     Function for handling the BLE_GAP_EVT_DISCONNECTED event from the S110 SoftDevice.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] p_dfu     DFU Service Structure.
 | 
			
		||||
 * @param[in] p_ble_evt Pointer to the event received from BLE stack.
 | 
			
		||||
 */
 | 
			
		||||
static void on_disconnect(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
 | 
			
		||||
{
 | 
			
		||||
    p_dfu->conn_handle = BLE_CONN_HANDLE_INVALID;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint32_t ble_dfu_init(ble_dfu_t * p_dfu, ble_dfu_init_t * p_dfu_init)
 | 
			
		||||
{
 | 
			
		||||
    if ((p_dfu == NULL) || (p_dfu_init == NULL) || (p_dfu_init->evt_handler == NULL))
 | 
			
		||||
    {
 | 
			
		||||
        return NRF_ERROR_NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    p_dfu->conn_handle = BLE_CONN_HANDLE_INVALID;
 | 
			
		||||
 | 
			
		||||
    ble_uuid_t service_uuid;
 | 
			
		||||
    uint32_t   err_code;
 | 
			
		||||
 | 
			
		||||
    const ble_uuid128_t base_uuid128 =
 | 
			
		||||
    {
 | 
			
		||||
        {
 | 
			
		||||
            0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
 | 
			
		||||
            0xDE, 0xEF, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    service_uuid.uuid = BLE_DFU_SERVICE_UUID;
 | 
			
		||||
 | 
			
		||||
    err_code = sd_ble_uuid_vs_add(&base_uuid128, &(service_uuid.type));
 | 
			
		||||
    VERIFY_SUCCESS(err_code);
 | 
			
		||||
 | 
			
		||||
    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
 | 
			
		||||
                                        &service_uuid,
 | 
			
		||||
                                        &(p_dfu->service_handle));
 | 
			
		||||
    VERIFY_SUCCESS(err_code);
 | 
			
		||||
 | 
			
		||||
    p_dfu->uuid_type = service_uuid.type;
 | 
			
		||||
 | 
			
		||||
    err_code = dfu_pkt_char_add(p_dfu);
 | 
			
		||||
    VERIFY_SUCCESS(err_code);
 | 
			
		||||
 | 
			
		||||
    err_code = dfu_ctrl_pt_add(p_dfu);
 | 
			
		||||
    VERIFY_SUCCESS(err_code);
 | 
			
		||||
 | 
			
		||||
    err_code = dfu_rev_char_add(p_dfu, p_dfu_init);
 | 
			
		||||
    VERIFY_SUCCESS(err_code);
 | 
			
		||||
 | 
			
		||||
    p_dfu->evt_handler = p_dfu_init->evt_handler;
 | 
			
		||||
 | 
			
		||||
    if (p_dfu_init->error_handler != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        p_dfu->error_handler = p_dfu_init->error_handler;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    m_is_dfu_service_initialized = true;
 | 
			
		||||
 | 
			
		||||
    return NRF_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void ble_dfu_on_ble_evt(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
 | 
			
		||||
{
 | 
			
		||||
    if ((p_dfu == NULL) || (p_ble_evt == NULL))
 | 
			
		||||
    {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (p_dfu->evt_handler != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        switch (p_ble_evt->header.evt_id)
 | 
			
		||||
        {
 | 
			
		||||
            case BLE_GAP_EVT_CONNECTED:
 | 
			
		||||
                on_connect(p_dfu, p_ble_evt);
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case BLE_GATTS_EVT_WRITE:
 | 
			
		||||
                on_write(p_dfu, p_ble_evt);
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case BLE_GAP_EVT_DISCONNECTED:
 | 
			
		||||
                on_disconnect(p_dfu, p_ble_evt);
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
 | 
			
		||||
                on_rw_authorize_req(p_dfu, p_ble_evt);
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
                // No implementation needed.
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint32_t ble_dfu_bytes_rcvd_report(ble_dfu_t * p_dfu, uint32_t num_of_firmware_bytes_rcvd)
 | 
			
		||||
{
 | 
			
		||||
    if (p_dfu == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        return NRF_ERROR_NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((p_dfu->conn_handle == BLE_CONN_HANDLE_INVALID) || !m_is_dfu_service_initialized)
 | 
			
		||||
    {
 | 
			
		||||
        return NRF_ERROR_INVALID_STATE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ble_gatts_hvx_params_t hvx_params;
 | 
			
		||||
    uint16_t               index = 0;
 | 
			
		||||
 | 
			
		||||
    // Encode the Op Code.
 | 
			
		||||
    m_notif_buffer[index++] = OP_CODE_RESPONSE;
 | 
			
		||||
 | 
			
		||||
    // Encode the Reqest Op Code.
 | 
			
		||||
    m_notif_buffer[index++] = OP_CODE_IMAGE_SIZE_REQ;
 | 
			
		||||
 | 
			
		||||
    // Encode the Response Value.
 | 
			
		||||
    m_notif_buffer[index++] = (uint8_t)BLE_DFU_RESP_VAL_SUCCESS;
 | 
			
		||||
 | 
			
		||||
    index += uint32_encode(num_of_firmware_bytes_rcvd, &m_notif_buffer[index]);
 | 
			
		||||
 | 
			
		||||
    memset(&hvx_params, 0, sizeof(hvx_params));
 | 
			
		||||
 | 
			
		||||
    hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle;
 | 
			
		||||
    hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
 | 
			
		||||
    hvx_params.offset = 0;
 | 
			
		||||
    hvx_params.p_len  = &index;
 | 
			
		||||
    hvx_params.p_data = m_notif_buffer;
 | 
			
		||||
 | 
			
		||||
    return sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint32_t ble_dfu_pkts_rcpt_notify(ble_dfu_t * p_dfu, uint32_t num_of_firmware_bytes_rcvd)
 | 
			
		||||
{
 | 
			
		||||
    if (p_dfu == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        return NRF_ERROR_NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((p_dfu->conn_handle == BLE_CONN_HANDLE_INVALID) || !m_is_dfu_service_initialized)
 | 
			
		||||
    {
 | 
			
		||||
        return NRF_ERROR_INVALID_STATE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ble_gatts_hvx_params_t hvx_params;
 | 
			
		||||
    uint16_t               index = 0;
 | 
			
		||||
 | 
			
		||||
    m_notif_buffer[index++] = OP_CODE_PKT_RCPT_NOTIF;
 | 
			
		||||
 | 
			
		||||
    index += uint32_encode(num_of_firmware_bytes_rcvd, &m_notif_buffer[index]);
 | 
			
		||||
 | 
			
		||||
    memset(&hvx_params, 0, sizeof(hvx_params));
 | 
			
		||||
 | 
			
		||||
    hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle;
 | 
			
		||||
    hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
 | 
			
		||||
    hvx_params.offset = 0;
 | 
			
		||||
    hvx_params.p_len  = &index;
 | 
			
		||||
    hvx_params.p_data = m_notif_buffer;
 | 
			
		||||
 | 
			
		||||
    return sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint32_t ble_dfu_response_send(ble_dfu_t         * p_dfu,
 | 
			
		||||
                               ble_dfu_procedure_t dfu_proc,
 | 
			
		||||
                               ble_dfu_resp_val_t  resp_val)
 | 
			
		||||
{
 | 
			
		||||
    if (p_dfu == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        return NRF_ERROR_NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((p_dfu->conn_handle == BLE_CONN_HANDLE_INVALID) || !m_is_dfu_service_initialized)
 | 
			
		||||
    {
 | 
			
		||||
        return NRF_ERROR_INVALID_STATE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ble_gatts_hvx_params_t hvx_params;
 | 
			
		||||
    uint16_t               index = 0;
 | 
			
		||||
 | 
			
		||||
    m_notif_buffer[index++] = OP_CODE_RESPONSE;
 | 
			
		||||
 | 
			
		||||
    // Encode the Request Op code
 | 
			
		||||
    m_notif_buffer[index++] = (uint8_t)dfu_proc;
 | 
			
		||||
 | 
			
		||||
    // Encode the Response Value.
 | 
			
		||||
    m_notif_buffer[index++] = (uint8_t)resp_val;
 | 
			
		||||
 | 
			
		||||
    memset(&hvx_params, 0, sizeof(hvx_params));
 | 
			
		||||
 | 
			
		||||
    hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle;
 | 
			
		||||
    hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
 | 
			
		||||
    hvx_params.offset = 0;
 | 
			
		||||
    hvx_params.p_len  = &index;
 | 
			
		||||
    hvx_params.p_data = m_notif_buffer;
 | 
			
		||||
 | 
			
		||||
    return sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params);
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,239 @@
 | 
			
		||||
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * The information contained herein is property of Nordic Semiconductor ASA.
 | 
			
		||||
 * Terms and conditions of usage are described in detail in NORDIC
 | 
			
		||||
 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensees are granted free, non-transferable use of the information. NO
 | 
			
		||||
 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
 | 
			
		||||
 * the file.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**@file
 | 
			
		||||
 *
 | 
			
		||||
 * @defgroup ble_sdk_srv_dfu Device Firmware Update Service
 | 
			
		||||
 * @{
 | 
			
		||||
 * @ingroup  ble_sdk_srv
 | 
			
		||||
 * @brief    Device Firmware Update Service
 | 
			
		||||
 *
 | 
			
		||||
 * @details  The Device Firmware Update (DFU) service is a GATT based service that can be used for
 | 
			
		||||
 *           performing firmware updates over BLE. Note that this implementation uses vendor
 | 
			
		||||
 *           specific UUIDs for service and characteristics and is intended to demonstrate the
 | 
			
		||||
 *           firmware updates over BLE. Refer @ref bledfu_transport_bleservice and @ref
 | 
			
		||||
 *            bledfu_transport_bleprofile for more information on the service and profile respectively.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef BLE_DFU_H__
 | 
			
		||||
#define BLE_DFU_H__
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "ble_gatts.h"
 | 
			
		||||
#include "ble_gap.h"
 | 
			
		||||
#include "ble.h"
 | 
			
		||||
#include "ble_srv_common.h"
 | 
			
		||||
 | 
			
		||||
#define BLE_DFU_SERVICE_UUID                 0x1530                       /**< The UUID of the DFU Service. */
 | 
			
		||||
#define BLE_DFU_PKT_CHAR_UUID                0x1532                       /**< The UUID of the DFU Packet Characteristic. */
 | 
			
		||||
#define BLE_DFU_CTRL_PT_UUID                 0x1531                       /**< The UUID of the DFU Control Point. */
 | 
			
		||||
#define BLE_DFU_STATUS_REP_UUID              0x1533                       /**< The UUID of the DFU Status Report Characteristic. */
 | 
			
		||||
#define BLE_DFU_REV_CHAR_UUID                0x1534                       /**< The UUID of the DFU Revision Characteristic. */
 | 
			
		||||
 | 
			
		||||
/**@brief   DFU Event type.
 | 
			
		||||
 *
 | 
			
		||||
 * @details This enumeration contains the types of events that will be received from the DFU Service.
 | 
			
		||||
 */
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
    BLE_DFU_START,                                                      /**< The event indicating that the peer wants the application to prepare for a new firmware update. */
 | 
			
		||||
    BLE_DFU_RECEIVE_INIT_DATA,                                          /**< The event indicating that the peer wants the application to prepare to receive init parameters. */
 | 
			
		||||
    BLE_DFU_RECEIVE_APP_DATA,                                           /**< The event indicating that the peer wants the application to prepare to receive the new firmware image. */
 | 
			
		||||
    BLE_DFU_VALIDATE,                                                   /**< The event indicating that the peer wants the application to validate the newly received firmware image. */
 | 
			
		||||
    BLE_DFU_ACTIVATE_N_RESET,                                           /**< The event indicating that the peer wants the application to undergo activate new firmware and restart with new valid application */
 | 
			
		||||
    BLE_DFU_SYS_RESET,                                                  /**< The event indicating that the peer wants the application to undergo a reset and start the currently valid application image.*/
 | 
			
		||||
    BLE_DFU_PKT_RCPT_NOTIF_ENABLED,                                     /**< The event indicating that the peer has enabled packet receipt notifications. It is the responsibility of the application to call @ref ble_dfu_pkts_rcpt_notify each time the number of packets indicated by num_of_pkts field in @ref ble_dfu_evt_t is received.*/
 | 
			
		||||
    BLE_DFU_PKT_RCPT_NOTIF_DISABLED,                                    /**< The event indicating that the peer has disabled the packet receipt notifications.*/
 | 
			
		||||
    BLE_DFU_PACKET_WRITE,                                               /**< The event indicating that the peer has written a value to the 'DFU Packet' characteristic. The data received from the peer will be present in the @ref BLE_DFU_PACKET_WRITE element contained within @ref ble_dfu_evt_t.*/
 | 
			
		||||
    BLE_DFU_BYTES_RECEIVED_SEND                                         /**< The event indicating that the peer is requesting for the number of bytes of firmware data last received by the application. It is the responsibility of the application to call @ref ble_dfu_pkts_rcpt_notify in response to this event. */
 | 
			
		||||
} ble_dfu_evt_type_t;
 | 
			
		||||
 | 
			
		||||
/**@brief   DFU Procedure type.
 | 
			
		||||
 *
 | 
			
		||||
 * @details This enumeration contains the types of DFU procedures.
 | 
			
		||||
 */
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
    BLE_DFU_START_PROCEDURE        = 1,                                 /**< DFU Start procedure.*/
 | 
			
		||||
    BLE_DFU_INIT_PROCEDURE         = 2,                                 /**< DFU Initialization procedure.*/
 | 
			
		||||
    BLE_DFU_RECEIVE_APP_PROCEDURE  = 3,                                 /**< Firmware receiving procedure.*/
 | 
			
		||||
    BLE_DFU_VALIDATE_PROCEDURE     = 4,                                 /**< Firmware image validation procedure .*/
 | 
			
		||||
    BLE_DFU_PKT_RCPT_REQ_PROCEDURE = 8                                  /**< Packet receipt notification request procedure. */
 | 
			
		||||
} ble_dfu_procedure_t;
 | 
			
		||||
 | 
			
		||||
/**@brief   DFU Response value type.
 | 
			
		||||
 */
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
    BLE_DFU_RESP_VAL_SUCCESS = 1,                                       /**< Success.*/
 | 
			
		||||
    BLE_DFU_RESP_VAL_INVALID_STATE,                                     /**< Invalid state.*/
 | 
			
		||||
    BLE_DFU_RESP_VAL_NOT_SUPPORTED,                                     /**< Operation not supported.*/
 | 
			
		||||
    BLE_DFU_RESP_VAL_DATA_SIZE,                                         /**< Data size exceeds limit.*/
 | 
			
		||||
    BLE_DFU_RESP_VAL_CRC_ERROR,                                         /**< CRC Error.*/
 | 
			
		||||
    BLE_DFU_RESP_VAL_OPER_FAILED                                        /**< Operation failed.*/
 | 
			
		||||
} ble_dfu_resp_val_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**@brief   DFU Packet structure.
 | 
			
		||||
 *
 | 
			
		||||
 * @details This structure contains the value of the DFU Packet characteristic as written by the
 | 
			
		||||
 *          peer and the length of the value written. It will be filled by the DFU Service when the
 | 
			
		||||
 *          peer writes to the DFU Packet characteristic.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *                    p_data;                                /**< Pointer to the received packet. This will point to a word aligned memory location.*/
 | 
			
		||||
    uint8_t                      len;                                   /**< Length of the packet received. */
 | 
			
		||||
} ble_dfu_pkt_write_t;
 | 
			
		||||
 | 
			
		||||
/**@brief   Packet receipt notification request structure.
 | 
			
		||||
 *
 | 
			
		||||
 * @details This structure contains the contents of the packet receipt notification request
 | 
			
		||||
 *          sent by the DFU Controller.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    uint16_t                     num_of_pkts;                           /**< The number of packets of firmware data to be received by application before sending the next Packet Receipt Notification to the peer. */
 | 
			
		||||
} ble_pkt_rcpt_notif_req_t;
 | 
			
		||||
 | 
			
		||||
/**@brief   DFU Event structure.
 | 
			
		||||
 *
 | 
			
		||||
 * @details This structure contains the event generated by the DFU Service based on the data
 | 
			
		||||
 *          received from the peer.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    ble_dfu_evt_type_t           ble_dfu_evt_type;                      /**< Type of the event.*/
 | 
			
		||||
    union
 | 
			
		||||
    {
 | 
			
		||||
        ble_dfu_pkt_write_t      ble_dfu_pkt_write;                     /**< The DFU packet received. This field is when the @ref ble_dfu_evt_type field is set to @ref BLE_DFU_PACKET_WRITE.*/
 | 
			
		||||
        ble_pkt_rcpt_notif_req_t pkt_rcpt_notif_req;                    /**< Packet receipt notification request. This field is when the @ref ble_dfu_evt_type field is set to @ref BLE_DFU_PKT_RCPT_NOTIF_ENABLED.*/
 | 
			
		||||
    } evt;
 | 
			
		||||
} ble_dfu_evt_t;
 | 
			
		||||
 | 
			
		||||
// Forward declaration of the ble_dfu_t type.
 | 
			
		||||
typedef struct ble_dfu_s ble_dfu_t;
 | 
			
		||||
 | 
			
		||||
/**@brief DFU Service event handler type. */
 | 
			
		||||
typedef void (*ble_dfu_evt_handler_t) (ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt);
 | 
			
		||||
 | 
			
		||||
/**@brief   DFU service structure.
 | 
			
		||||
 *
 | 
			
		||||
 * @details This structure contains status information related to the service.
 | 
			
		||||
 */
 | 
			
		||||
struct ble_dfu_s
 | 
			
		||||
{
 | 
			
		||||
    uint16_t                     conn_handle;                           /**< Handle of the current connection (as provided by the SoftDevice). This will be BLE_CONN_HANDLE_INVALID when not in a connection. */
 | 
			
		||||
    uint16_t                     revision;                              /**< Handle of DFU Service (as provided by the SoftDevice). */
 | 
			
		||||
    uint16_t                     service_handle;                        /**< Handle of DFU Service (as provided by the SoftDevice). */
 | 
			
		||||
    uint8_t                      uuid_type;                             /**< UUID type assigned for DFU Service by the SoftDevice. */
 | 
			
		||||
    ble_gatts_char_handles_t     dfu_pkt_handles;                       /**< Handles related to the DFU Packet characteristic. */
 | 
			
		||||
    ble_gatts_char_handles_t     dfu_ctrl_pt_handles;                   /**< Handles related to the DFU Control Point characteristic. */
 | 
			
		||||
    ble_gatts_char_handles_t     dfu_status_rep_handles;                /**< Handles related to the DFU Status Report characteristic. */
 | 
			
		||||
    ble_gatts_char_handles_t     dfu_rev_handles;                       /**< Handles related to the DFU Revision characteristic. */
 | 
			
		||||
    ble_dfu_evt_handler_t        evt_handler;                           /**< The event handler to be called when an event is to be sent to the application.*/
 | 
			
		||||
    ble_srv_error_handler_t      error_handler;                         /**< Function to be called in case of an error. */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**@brief      DFU service initialization structure.
 | 
			
		||||
 *
 | 
			
		||||
 * @details    This structure contains the initialization information for the DFU Service. The
 | 
			
		||||
 *             application needs to fill this structure and pass it to the DFU Service using the
 | 
			
		||||
 *             @ref ble_dfu_init function.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    uint16_t                     revision;                              /**< Revision number to be exposed by the DFU service. */
 | 
			
		||||
    ble_dfu_evt_handler_t        evt_handler;                           /**< Event handler to be called for handling events in the Device Firmware Update Service. */
 | 
			
		||||
    ble_srv_error_handler_t      error_handler;                         /**< Function to be called in case of an error. */
 | 
			
		||||
} ble_dfu_init_t;
 | 
			
		||||
 | 
			
		||||
/**@brief      Function for handling a BLE event.
 | 
			
		||||
 *
 | 
			
		||||
 * @details    The DFU service expects the application to call this function each time an event
 | 
			
		||||
 *             is received from the SoftDevice. This function processes the event, if it is
 | 
			
		||||
 *             relevant for the DFU service and calls the DFU event handler of the application if
 | 
			
		||||
 *             necessary.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]  p_dfu        Pointer to the DFU service structure.
 | 
			
		||||
 * @param[in]  p_ble_evt    Pointer to the event received from SoftDevice.
 | 
			
		||||
 */
 | 
			
		||||
void ble_dfu_on_ble_evt(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt);
 | 
			
		||||
 | 
			
		||||
/**@brief      Function for initializing the DFU service.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[out] p_dfu        Device Firmware Update service structure. This structure will have to be
 | 
			
		||||
 *                          supplied by the application. It will be initialized by this function,
 | 
			
		||||
 *                          and will later be used to identify the service instance.
 | 
			
		||||
 * @param[in]  p_dfu_init   Information needed to initialize the service.
 | 
			
		||||
 *
 | 
			
		||||
 * @return     NRF_SUCCESS if the DFU service and its characteristics were successfully added to the
 | 
			
		||||
 *             SoftDevice. Otherwise an error code.
 | 
			
		||||
 *             This function returns NRF_ERROR_NULL if the value of evt_handler in p_dfu_init
 | 
			
		||||
 *             structure provided is NULL or if the pointers supplied as input are NULL.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t ble_dfu_init(ble_dfu_t * p_dfu, ble_dfu_init_t * p_dfu_init);
 | 
			
		||||
 | 
			
		||||
/**@brief       Function for sending response to a control point command.
 | 
			
		||||
 *
 | 
			
		||||
 * @details     This function will encode a DFU Control Point response using the given input
 | 
			
		||||
 *              parameters and will send a notification of the same to the peer.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]   p_dfu       Pointer to the DFU service structure.
 | 
			
		||||
 * @param[in]   dfu_proc    Procedure for which this response is to be sent.
 | 
			
		||||
 * @param[in]   resp_val    Response value.
 | 
			
		||||
 *
 | 
			
		||||
 * @return      NRF_SUCCESS if the DFU Service has successfully requested the SoftDevice to
 | 
			
		||||
 *              send the notification. Otherwise an error code.
 | 
			
		||||
 *              This function returns NRF_ERROR_INVALID_STATE if the device is not connected to a
 | 
			
		||||
 *              peer or if the DFU service is not initialized or if the notification of the DFU
 | 
			
		||||
 *              Status Report characteristic was not enabled by the peer. It returns NRF_ERROR_NULL
 | 
			
		||||
 *              if the pointer p_dfu is NULL.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t ble_dfu_response_send(ble_dfu_t *          p_dfu,
 | 
			
		||||
                               ble_dfu_procedure_t  dfu_proc,
 | 
			
		||||
                               ble_dfu_resp_val_t   resp_val);
 | 
			
		||||
 | 
			
		||||
/**@brief      Function for notifying the peer about the number of bytes of firmware data received.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]  p_dfu                      Pointer to the DFU service structure.
 | 
			
		||||
 * @param[in]  num_of_firmware_bytes_rcvd Number of bytes.
 | 
			
		||||
 *
 | 
			
		||||
 * @return     NRF_SUCCESS if the DFU Service has successfully requested the SoftDevice to send
 | 
			
		||||
 *             the notification. Otherwise an error code.
 | 
			
		||||
 *             This function returns NRF_ERROR_INVALID_STATE if the device is not connected to a
 | 
			
		||||
 *             peer or if the DFU service is not initialized or if the notification of the DFU
 | 
			
		||||
 *             Status Report characteristic was not enabled by the peer. It returns NRF_ERROR_NULL
 | 
			
		||||
 *             if the pointer p_dfu is NULL.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t ble_dfu_bytes_rcvd_report(ble_dfu_t * p_dfu, uint32_t num_of_firmware_bytes_rcvd);
 | 
			
		||||
 | 
			
		||||
/**@brief      Function for sending Packet Receipt Notification to the peer.
 | 
			
		||||
 *
 | 
			
		||||
 *             This function will encode the number of bytes received as input parameter into a
 | 
			
		||||
 *             notification of the control point characteristic and send it to the peer.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]  p_dfu                      Pointer to the DFU service structure.
 | 
			
		||||
 * @param[in]  num_of_firmware_bytes_rcvd Number of bytes of firmware image received.
 | 
			
		||||
 *
 | 
			
		||||
 * @return     NRF_SUCCESS if the DFU Service has successfully requested the SoftDevice to send
 | 
			
		||||
 *             the notification. Otherwise an error code.
 | 
			
		||||
 *             This function returns NRF_ERROR_INVALID_STATE if the device is not connected to a
 | 
			
		||||
 *             peer or if the DFU service is not initialized or if the notification of the DFU
 | 
			
		||||
 *             Status Report characteristic was not enabled by the peer. It returns NRF_ERROR_NULL
 | 
			
		||||
 *             if the pointer p_dfu is NULL.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t ble_dfu_pkts_rcpt_notify(ble_dfu_t * p_dfu, uint32_t num_of_firmware_bytes_rcvd);
 | 
			
		||||
 | 
			
		||||
#endif // BLE_DFU_H__
 | 
			
		||||
 | 
			
		||||
/** @} */
 | 
			
		||||
@@ -0,0 +1,277 @@
 | 
			
		||||
/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * The information contained herein is property of Nordic Semiconductor ASA.
 | 
			
		||||
 * Terms and conditions of usage are described in detail in NORDIC
 | 
			
		||||
 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensees are granted free, non-transferable use of the information. NO
 | 
			
		||||
 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
 | 
			
		||||
 * the file.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Attention! 
 | 
			
		||||
*  To maintain compliance with Nordic Semiconductor ASA<53>s Bluetooth profile 
 | 
			
		||||
*  qualification listings, this section of source code must not be modified.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "ble_dis.h"
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "app_error.h"
 | 
			
		||||
#include "ble_gatts.h"
 | 
			
		||||
#include "nordic_common.h"
 | 
			
		||||
#include "ble_srv_common.h"
 | 
			
		||||
#include "app_util.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define BLE_DIS_SYS_ID_LEN 8  /**< Length of System ID Characteristic Value. */
 | 
			
		||||
#define BLE_DIS_PNP_ID_LEN 7  /**< Length of Pnp ID Characteristic Value. */
 | 
			
		||||
 | 
			
		||||
static uint16_t                 service_handle;
 | 
			
		||||
static ble_gatts_char_handles_t manufact_name_handles;
 | 
			
		||||
static ble_gatts_char_handles_t model_num_handles;
 | 
			
		||||
static ble_gatts_char_handles_t serial_num_handles;
 | 
			
		||||
static ble_gatts_char_handles_t hw_rev_handles;
 | 
			
		||||
static ble_gatts_char_handles_t fw_rev_handles;
 | 
			
		||||
static ble_gatts_char_handles_t sw_rev_handles;
 | 
			
		||||
static ble_gatts_char_handles_t sys_id_handles;
 | 
			
		||||
static ble_gatts_char_handles_t reg_cert_data_list_handles;
 | 
			
		||||
static ble_gatts_char_handles_t pnp_id_handles;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**@brief Function for encoding a System ID.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[out]  p_encoded_buffer   Buffer where the encoded data will be written.
 | 
			
		||||
 * @param[in]   p_sys_id           System ID to be encoded.
 | 
			
		||||
 */
 | 
			
		||||
static void sys_id_encode(uint8_t * p_encoded_buffer, const ble_dis_sys_id_t * p_sys_id)
 | 
			
		||||
{
 | 
			
		||||
    APP_ERROR_CHECK_BOOL(p_sys_id != NULL);
 | 
			
		||||
    APP_ERROR_CHECK_BOOL(p_encoded_buffer != NULL);
 | 
			
		||||
 | 
			
		||||
    p_encoded_buffer[0] = (p_sys_id->manufacturer_id & 0x00000000FF);
 | 
			
		||||
    p_encoded_buffer[1] = (p_sys_id->manufacturer_id & 0x000000FF00) >> 8;
 | 
			
		||||
    p_encoded_buffer[2] = (p_sys_id->manufacturer_id & 0x0000FF0000) >> 16;
 | 
			
		||||
    p_encoded_buffer[3] = (p_sys_id->manufacturer_id & 0x00FF000000) >> 24;
 | 
			
		||||
    p_encoded_buffer[4] = (p_sys_id->manufacturer_id & 0xFF00000000) >> 32;
 | 
			
		||||
 | 
			
		||||
    p_encoded_buffer[5] = (p_sys_id->organizationally_unique_id & 0x0000FF);
 | 
			
		||||
    p_encoded_buffer[6] = (p_sys_id->organizationally_unique_id & 0x00FF00) >> 8;
 | 
			
		||||
    p_encoded_buffer[7] = (p_sys_id->organizationally_unique_id & 0xFF0000) >> 16;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**@brief Function for encoding a PnP ID.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[out]  p_encoded_buffer   Buffer where the encoded data will be written.
 | 
			
		||||
 * @param[in]   p_pnp_id           PnP ID to be encoded.
 | 
			
		||||
 */
 | 
			
		||||
static void pnp_id_encode(uint8_t * p_encoded_buffer, const ble_dis_pnp_id_t * p_pnp_id)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t len = 0;
 | 
			
		||||
 | 
			
		||||
    APP_ERROR_CHECK_BOOL(p_pnp_id != NULL);
 | 
			
		||||
    APP_ERROR_CHECK_BOOL(p_encoded_buffer != NULL);
 | 
			
		||||
 | 
			
		||||
    p_encoded_buffer[len++] = p_pnp_id->vendor_id_source;
 | 
			
		||||
 | 
			
		||||
    len += uint16_encode(p_pnp_id->vendor_id, &p_encoded_buffer[len]);
 | 
			
		||||
    len += uint16_encode(p_pnp_id->product_id, &p_encoded_buffer[len]);
 | 
			
		||||
    len += uint16_encode(p_pnp_id->product_version, &p_encoded_buffer[len]);
 | 
			
		||||
 | 
			
		||||
    APP_ERROR_CHECK_BOOL(len == BLE_DIS_PNP_ID_LEN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**@brief Function for adding the Characteristic.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]   uuid           UUID of characteristic to be added.
 | 
			
		||||
 * @param[in]   p_char_value   Initial value of characteristic to be added.
 | 
			
		||||
 * @param[in]   char_len       Length of initial value. This will also be the maximum value.
 | 
			
		||||
 * @param[in]   dis_attr_md    Security settings of characteristic to be added.
 | 
			
		||||
 * @param[out]  p_handles      Handles of new characteristic.
 | 
			
		||||
 *
 | 
			
		||||
 * @return      NRF_SUCCESS on success, otherwise an error code.
 | 
			
		||||
 */
 | 
			
		||||
static uint32_t char_add(uint16_t                        uuid,
 | 
			
		||||
                         uint8_t                       * p_char_value,
 | 
			
		||||
                         uint16_t                        char_len,
 | 
			
		||||
                         const ble_srv_security_mode_t * dis_attr_md,
 | 
			
		||||
                         ble_gatts_char_handles_t      * p_handles)
 | 
			
		||||
{
 | 
			
		||||
    ble_uuid_t          ble_uuid;
 | 
			
		||||
    ble_gatts_char_md_t char_md;
 | 
			
		||||
    ble_gatts_attr_t    attr_char_value;
 | 
			
		||||
    ble_gatts_attr_md_t attr_md;
 | 
			
		||||
 | 
			
		||||
    APP_ERROR_CHECK_BOOL(p_char_value != NULL);
 | 
			
		||||
    APP_ERROR_CHECK_BOOL(char_len > 0);
 | 
			
		||||
 | 
			
		||||
    // The ble_gatts_char_md_t structure uses bit fields. So we reset the memory to zero.
 | 
			
		||||
    memset(&char_md, 0, sizeof(char_md));
 | 
			
		||||
 | 
			
		||||
    char_md.char_props.read  = 1;
 | 
			
		||||
    char_md.p_char_user_desc = NULL;
 | 
			
		||||
    char_md.p_char_pf        = NULL;
 | 
			
		||||
    char_md.p_user_desc_md   = NULL;
 | 
			
		||||
    char_md.p_cccd_md        = NULL;
 | 
			
		||||
    char_md.p_sccd_md        = NULL;
 | 
			
		||||
 | 
			
		||||
    BLE_UUID_BLE_ASSIGN(ble_uuid, uuid);
 | 
			
		||||
 | 
			
		||||
    memset(&attr_md, 0, sizeof(attr_md));
 | 
			
		||||
 | 
			
		||||
    attr_md.read_perm  = dis_attr_md->read_perm;
 | 
			
		||||
    attr_md.write_perm = dis_attr_md->write_perm;
 | 
			
		||||
    attr_md.vloc       = BLE_GATTS_VLOC_STACK;
 | 
			
		||||
    attr_md.rd_auth    = 0;
 | 
			
		||||
    attr_md.wr_auth    = 0;
 | 
			
		||||
    attr_md.vlen       = 0;
 | 
			
		||||
 | 
			
		||||
    memset(&attr_char_value, 0, sizeof(attr_char_value));
 | 
			
		||||
 | 
			
		||||
    attr_char_value.p_uuid    = &ble_uuid;
 | 
			
		||||
    attr_char_value.p_attr_md = &attr_md;
 | 
			
		||||
    attr_char_value.init_len  = char_len;
 | 
			
		||||
    attr_char_value.init_offs = 0;
 | 
			
		||||
    attr_char_value.max_len   = char_len;
 | 
			
		||||
    attr_char_value.p_value   = p_char_value;
 | 
			
		||||
 | 
			
		||||
    return sd_ble_gatts_characteristic_add(service_handle, &char_md, &attr_char_value, p_handles);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint32_t ble_dis_init(const ble_dis_init_t * p_dis_init)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t   err_code;
 | 
			
		||||
    ble_uuid_t ble_uuid;
 | 
			
		||||
 | 
			
		||||
    // Add service
 | 
			
		||||
    BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_DEVICE_INFORMATION_SERVICE);
 | 
			
		||||
 | 
			
		||||
    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &service_handle);
 | 
			
		||||
    if (err_code != NRF_SUCCESS)
 | 
			
		||||
    {
 | 
			
		||||
        return err_code;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Add characteristics
 | 
			
		||||
    if (p_dis_init->manufact_name_str.length > 0)
 | 
			
		||||
    {
 | 
			
		||||
        err_code = char_add(BLE_UUID_MANUFACTURER_NAME_STRING_CHAR,
 | 
			
		||||
                            p_dis_init->manufact_name_str.p_str,
 | 
			
		||||
                            p_dis_init->manufact_name_str.length,
 | 
			
		||||
                            &p_dis_init->dis_attr_md,
 | 
			
		||||
                            &manufact_name_handles);
 | 
			
		||||
        if (err_code != NRF_SUCCESS)
 | 
			
		||||
        {
 | 
			
		||||
            return err_code;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (p_dis_init->model_num_str.length > 0)
 | 
			
		||||
    {
 | 
			
		||||
        err_code = char_add(BLE_UUID_MODEL_NUMBER_STRING_CHAR,
 | 
			
		||||
                            p_dis_init->model_num_str.p_str,
 | 
			
		||||
                            p_dis_init->model_num_str.length,
 | 
			
		||||
                            &p_dis_init->dis_attr_md,
 | 
			
		||||
                            &model_num_handles);
 | 
			
		||||
        if (err_code != NRF_SUCCESS)
 | 
			
		||||
        {
 | 
			
		||||
            return err_code;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (p_dis_init->serial_num_str.length > 0)
 | 
			
		||||
    {
 | 
			
		||||
        err_code = char_add(BLE_UUID_SERIAL_NUMBER_STRING_CHAR,
 | 
			
		||||
                            p_dis_init->serial_num_str.p_str,
 | 
			
		||||
                            p_dis_init->serial_num_str.length,
 | 
			
		||||
                            &p_dis_init->dis_attr_md,
 | 
			
		||||
                            &serial_num_handles);
 | 
			
		||||
        if (err_code != NRF_SUCCESS)
 | 
			
		||||
        {
 | 
			
		||||
            return err_code;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (p_dis_init->hw_rev_str.length > 0)
 | 
			
		||||
    {
 | 
			
		||||
        err_code = char_add(BLE_UUID_HARDWARE_REVISION_STRING_CHAR,
 | 
			
		||||
                            p_dis_init->hw_rev_str.p_str,
 | 
			
		||||
                            p_dis_init->hw_rev_str.length,
 | 
			
		||||
                            &p_dis_init->dis_attr_md,
 | 
			
		||||
                            &hw_rev_handles);
 | 
			
		||||
        if (err_code != NRF_SUCCESS)
 | 
			
		||||
        {
 | 
			
		||||
            return err_code;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (p_dis_init->fw_rev_str.length > 0)
 | 
			
		||||
    {
 | 
			
		||||
        err_code = char_add(BLE_UUID_FIRMWARE_REVISION_STRING_CHAR,
 | 
			
		||||
                            p_dis_init->fw_rev_str.p_str,
 | 
			
		||||
                            p_dis_init->fw_rev_str.length,
 | 
			
		||||
                            &p_dis_init->dis_attr_md,
 | 
			
		||||
                            &fw_rev_handles);
 | 
			
		||||
        if (err_code != NRF_SUCCESS)
 | 
			
		||||
        {
 | 
			
		||||
            return err_code;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (p_dis_init->sw_rev_str.length > 0)
 | 
			
		||||
    {
 | 
			
		||||
        err_code = char_add(BLE_UUID_SOFTWARE_REVISION_STRING_CHAR,
 | 
			
		||||
                            p_dis_init->sw_rev_str.p_str,
 | 
			
		||||
                            p_dis_init->sw_rev_str.length,
 | 
			
		||||
                            &p_dis_init->dis_attr_md,
 | 
			
		||||
                            &sw_rev_handles);
 | 
			
		||||
        if (err_code != NRF_SUCCESS)
 | 
			
		||||
        {
 | 
			
		||||
            return err_code;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (p_dis_init->p_sys_id != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        uint8_t encoded_sys_id[BLE_DIS_SYS_ID_LEN];
 | 
			
		||||
 | 
			
		||||
        sys_id_encode(encoded_sys_id, p_dis_init->p_sys_id);
 | 
			
		||||
        err_code = char_add(BLE_UUID_SYSTEM_ID_CHAR,
 | 
			
		||||
                            encoded_sys_id,
 | 
			
		||||
                            BLE_DIS_SYS_ID_LEN,
 | 
			
		||||
                            &p_dis_init->dis_attr_md,
 | 
			
		||||
                            &sys_id_handles);
 | 
			
		||||
        if (err_code != NRF_SUCCESS)
 | 
			
		||||
        {
 | 
			
		||||
            return err_code;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (p_dis_init->p_reg_cert_data_list != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        err_code = char_add(BLE_UUID_IEEE_REGULATORY_CERTIFICATION_DATA_LIST_CHAR,
 | 
			
		||||
                            p_dis_init->p_reg_cert_data_list->p_list,
 | 
			
		||||
                            p_dis_init->p_reg_cert_data_list->list_len,
 | 
			
		||||
                            &p_dis_init->dis_attr_md,
 | 
			
		||||
                            ®_cert_data_list_handles);
 | 
			
		||||
        if (err_code != NRF_SUCCESS)
 | 
			
		||||
        {
 | 
			
		||||
            return err_code;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (p_dis_init->p_pnp_id != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        uint8_t encoded_pnp_id[BLE_DIS_PNP_ID_LEN];
 | 
			
		||||
 | 
			
		||||
        pnp_id_encode(encoded_pnp_id, p_dis_init->p_pnp_id);
 | 
			
		||||
        err_code = char_add(BLE_UUID_PNP_ID_CHAR,
 | 
			
		||||
                            encoded_pnp_id,
 | 
			
		||||
                            BLE_DIS_PNP_ID_LEN,
 | 
			
		||||
                            &p_dis_init->dis_attr_md,
 | 
			
		||||
                            &pnp_id_handles);
 | 
			
		||||
        if (err_code != NRF_SUCCESS)
 | 
			
		||||
        {
 | 
			
		||||
            return err_code;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return NRF_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,98 @@
 | 
			
		||||
/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * The information contained herein is property of Nordic Semiconductor ASA.
 | 
			
		||||
 * Terms and conditions of usage are described in detail in NORDIC
 | 
			
		||||
 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensees are granted free, non-transferable use of the information. NO
 | 
			
		||||
 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
 | 
			
		||||
 * the file.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** @file
 | 
			
		||||
 *
 | 
			
		||||
 * @defgroup ble_sdk_srv_dis Device Information Service
 | 
			
		||||
 * @{
 | 
			
		||||
 * @ingroup ble_sdk_srv
 | 
			
		||||
 * @brief Device Information Service module.
 | 
			
		||||
 *
 | 
			
		||||
 * @details This module implements the Device Information Service.
 | 
			
		||||
 *          During initialization it adds the Device Information Service to the BLE stack database.
 | 
			
		||||
 *          It then encodes the supplied information, and adds the curresponding characteristics.
 | 
			
		||||
 *
 | 
			
		||||
 * @note Attention! 
 | 
			
		||||
 *  To maintain compliance with Nordic Semiconductor ASA Bluetooth profile 
 | 
			
		||||
 *  qualification listings, this section of source code must not be modified.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef BLE_DIS_H__
 | 
			
		||||
#define BLE_DIS_H__
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "ble_srv_common.h"
 | 
			
		||||
 | 
			
		||||
/** @defgroup DIS_VENDOR_ID_SRC_VALUES Vendor ID Source values  
 | 
			
		||||
 * @{
 | 
			
		||||
 */
 | 
			
		||||
#define BLE_DIS_VENDOR_ID_SRC_BLUETOOTH_SIG   1                 /**< Vendor ID assigned by Bluetooth SIG. */
 | 
			
		||||
#define BLE_DIS_VENDOR_ID_SRC_USB_IMPL_FORUM  2                 /**< Vendor ID assigned by USB Implementer's Forum. */
 | 
			
		||||
/** @} */
 | 
			
		||||
 | 
			
		||||
/**@brief System ID parameters */
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    uint64_t manufacturer_id;                                   /**< Manufacturer ID. Only 5 LSOs shall be used. */
 | 
			
		||||
    uint32_t organizationally_unique_id;                        /**< Organizationally unique ID. Only 3 LSOs shall be used. */
 | 
			
		||||
} ble_dis_sys_id_t;
 | 
			
		||||
 | 
			
		||||
/**@brief IEEE 11073-20601 Regulatory Certification Data List Structure */
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *  p_list;                                          /**< Pointer the byte array containing the encoded opaque structure based on IEEE 11073-20601 specification. */
 | 
			
		||||
    uint8_t    list_len;                                        /**< Length of the byte array. */
 | 
			
		||||
} ble_dis_reg_cert_data_list_t;
 | 
			
		||||
 | 
			
		||||
/**@brief PnP ID parameters */
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    uint8_t  vendor_id_source;                                  /**< Vendor ID Source. see @ref DIS_VENDOR_ID_SRC_VALUES. */
 | 
			
		||||
    uint16_t vendor_id;                                         /**< Vendor ID. */
 | 
			
		||||
    uint16_t product_id;                                        /**< Product ID. */
 | 
			
		||||
    uint16_t product_version;                                   /**< Product Version. */
 | 
			
		||||
} ble_dis_pnp_id_t;
 | 
			
		||||
 | 
			
		||||
/**@brief Device Information Service init structure. This contains all possible characteristics 
 | 
			
		||||
 *        needed for initialization of the service.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    ble_srv_utf8_str_t             manufact_name_str;           /**< Manufacturer Name String. */
 | 
			
		||||
    ble_srv_utf8_str_t             model_num_str;               /**< Model Number String. */
 | 
			
		||||
    ble_srv_utf8_str_t             serial_num_str;              /**< Serial Number String. */
 | 
			
		||||
    ble_srv_utf8_str_t             hw_rev_str;                  /**< Hardware Revision String. */
 | 
			
		||||
    ble_srv_utf8_str_t             fw_rev_str;                  /**< Firmware Revision String. */
 | 
			
		||||
    ble_srv_utf8_str_t             sw_rev_str;                  /**< Software Revision String. */
 | 
			
		||||
    ble_dis_sys_id_t *             p_sys_id;                    /**< System ID. */
 | 
			
		||||
    ble_dis_reg_cert_data_list_t * p_reg_cert_data_list;        /**< IEEE 11073-20601 Regulatory Certification Data List. */
 | 
			
		||||
    ble_dis_pnp_id_t *             p_pnp_id;                    /**< PnP ID. */
 | 
			
		||||
    ble_srv_security_mode_t        dis_attr_md;                 /**< Initial Security Setting for Device Information Characteristics. */
 | 
			
		||||
} ble_dis_init_t;
 | 
			
		||||
 | 
			
		||||
/**@brief Function for initializing the Device Information Service.
 | 
			
		||||
 *
 | 
			
		||||
 * @details This call allows the application to initialize the device information service. 
 | 
			
		||||
 *          It adds the DIS service and DIS characteristics to the database, using the initial
 | 
			
		||||
 *          values supplied through the p_dis_init parameter. Characteristics which are not to be
 | 
			
		||||
 *          added, shall be set to NULL in p_dis_init.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]   p_dis_init   The structure containing the values of characteristics needed by the
 | 
			
		||||
 *                           service.
 | 
			
		||||
 *
 | 
			
		||||
 * @return      NRF_SUCCESS on successful initialization of service.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t ble_dis_init(const ble_dis_init_t * p_dis_init);
 | 
			
		||||
 | 
			
		||||
#endif // BLE_DIS_H__
 | 
			
		||||
 | 
			
		||||
/** @} */
 | 
			
		||||
		Reference in New Issue
	
	Block a user