예제 #1
0
void bootloader_util_settings_get(const bootloader_settings_t ** pp_bootloader_settings)
{
    static bootloader_settings_t s_converted_boot_settings;

    // Depending on the configuration / version the compiler used the enums used in bootloader
    // settings might have different padding (half word / word padded).
    // Half word padding would be, bc = Bank Code enum, crc (half word), xx = byte padding:
    // bc0 xx  crc crc - bc1 xx  xx  xx  - rest of data
    // Word padding would be, bc = Bank Code enum, crc (half word), xx = byte padding:
    // bc0 xx  xx  xx  - crc crc xx  xx  - bc1 xx  xx  xx - rest of data
    // To ensure full compability when updating from older bootloader to new, the padding must
    // be checked and conversion must be done accordingly.
    // In case of empty flash, 0xFFFFFFFF it is unimportant how settings are loaded.
    uint32_t pad_test = *((uint32_t *)&m_boot_settings[SIZE_TEST_INDEX]) & 0xFFFFFF00;

    if (pad_test == ZERO)
    {
        // Bank code enum is word sized, thus it is safe to cast without conversion.
        // Read only pointer to bootloader settings in flash.
        bootloader_settings_t const * const p_bootloader_settings =
            (bootloader_settings_t *)&m_boot_settings[0];

        *pp_bootloader_settings = p_bootloader_settings;
    }
    else
    {
        // Bank code enum is half word sized, thus crc is following the bank code in same word.
        uint32_t index                           = 0;
        s_converted_boot_settings.bank_0         =
            (bootloader_bank_code_t)((uint16_t)(m_boot_settings[index]) & 0xFFFF);

        index                                   += sizeof(uint16_t);
        s_converted_boot_settings.bank_0_crc     = uint16_decode(&m_boot_settings[index]);

        index                                   += sizeof(uint16_t);
        s_converted_boot_settings.bank_1         =
            (bootloader_bank_code_t)((uint16_t)(m_boot_settings[index]) & 0xFFFF);

        // Rest of settings are word sized values and thus will be aligned to next word.
        index                                   += sizeof(uint32_t);
        s_converted_boot_settings.bank_0_size    = uint32_decode(&m_boot_settings[index]);;

        index                                   += sizeof(uint32_t);
        s_converted_boot_settings.sd_image_size  = uint32_decode(&m_boot_settings[index]);;

        index                                   += sizeof(uint32_t);
        s_converted_boot_settings.bl_image_size  = uint32_decode(&m_boot_settings[index]);;

        index                                   += sizeof(uint32_t);
        s_converted_boot_settings.app_image_size = uint32_decode(&m_boot_settings[index]);;

        index                                   += sizeof(uint32_t);
        s_converted_boot_settings.sd_image_start = uint32_decode(&m_boot_settings[index]);;

        *pp_bootloader_settings = &s_converted_boot_settings;
    }
}
예제 #2
0
/**@brief     Function for processing start data written by the peer to the DFU Packet
 *            Characteristic.
 *
 * @param[in] p_dfu DFU Service Structure.
 * @param[in] p_evt Pointer to the event received from the BLE stack.
 */
static void start_data_process(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt)
{
    uint32_t err_code;

    // Verify that the data is exactly four bytes (one word) long.
    if (p_evt->evt.ble_dfu_pkt_write.len != sizeof(uint32_t))
    {
        err_code = ble_dfu_response_send(p_dfu,
                                         BLE_DFU_START_PROCEDURE,
                                         BLE_DFU_RESP_VAL_NOT_SUPPORTED);
        APP_ERROR_CHECK(err_code);
    }
    else
    {
        // Extract the size of from the DFU Packet Characteristic.
        uint32_t image_size = uint32_decode(p_evt->evt.ble_dfu_pkt_write.p_data);

        err_code = dfu_image_size_set(image_size);

        // Translate the err_code returned by the above function to DFU Response Value.
        ble_dfu_resp_val_t resp_val;

        resp_val = nrf_error_to_dfu_resp_val(err_code, BLE_DFU_START_PROCEDURE);

        err_code = ble_dfu_response_send(p_dfu,
                                         BLE_DFU_START_PROCEDURE,
                                         resp_val);
        APP_ERROR_CHECK(err_code);
    }
}
예제 #3
0
/**@brief Decode an incoming control point write.
 *
 * @param[in]    rcvd_val       received write value
 * @param[in]    len            value length
 * @param[out]   decoded_ctrlpt decoded control point structure
 */
static uint32_t sc_ctrlpt_decode(uint8_t const       * p_rcvd_val,
                                 uint8_t               len,
                                 ble_sc_ctrlpt_val_t * p_write_val)
{
    int pos = 0;

    if (len < BLE_SC_CTRLPT_MIN_LEN)
    {
        return NRF_ERROR_INVALID_PARAM;
    }

    p_write_val->opcode = (ble_scpt_operator_t) p_rcvd_val[pos++];

    switch (p_write_val->opcode)
    {
        case BLE_SCPT_REQUEST_SUPPORTED_SENSOR_LOCATIONS:
            break;

        case BLE_SCPT_START_AUTOMATIC_CALIBRATION:
            break;

        case BLE_SCPT_UPDATE_SENSOR_LOCATION:
            p_write_val->location = (ble_sensor_location_t)p_rcvd_val[pos];
            break;

        case BLE_SCPT_SET_CUMULATIVE_VALUE:
            p_write_val->cumulative_value = uint32_decode(&(p_rcvd_val[pos]));
            break;

        default:
            return NRF_ERROR_INVALID_PARAM;
    }
    return NRF_SUCCESS;
}
예제 #4
0
파일: main.c 프로젝트: xueliu/nRF51822
/**@brief Callback handler to receive data on UDP port.
 *
 * @param[in]   p_socket         Socket identifier.
 * @param[in]   p_ip_header      IPv6 header containing source and destination addresses.
 * @param[in]   p_udp_header     UDP header identifying local and remote endpoints.
 * @param[in]   process_result   Result of data reception, there could be possible errors like
 *                               invalid checksum etc.
 * @param[in]   iot_pbuffer_t    Packet buffer containing the received data packet.
 *
 * @retval      NRF_SUCCESS      Indicates received data was handled successfully, else an error
 *                               code indicating reason for failure.
 */
uint32_t rx_udp_port_app_handler(const udp6_socket_t * p_socket,
                                 const ipv6_header_t * p_ip_header,
                                 const udp6_header_t * p_udp_header,
                                 uint32_t              process_result,
                                 iot_pbuffer_t       * p_rx_packet)
{
    // APPL_LOG("[APPL]: Got UDP6 data on socket 0x%08lx\r\n", p_socket->socket_id);

    APP_ERROR_CHECK(process_result);

    // Print PORTs
    // APPL_LOG("[APPL]: UDP Destination port: %lx\r\n", HTONS(p_udp_header->destport));
    // APPL_LOG("[APPL]: UDP Source port: %lx\r\n",      HTONS(p_udp_header->srcport));

    uint32_t rx_sequence_num = uint32_decode(&p_rx_packet->p_payload[0]);
    uint32_t ind_buff = 0;
    uint32_t err_code = get_packet_buffer_index(&ind_buff, &rx_sequence_num);
    if (err_code == NRF_ERROR_NOT_FOUND)
    {
        // Received packet sequence number is not found amongst expected packets.
        return NRF_SUCCESS;
    }

    if (0 == memcmp(p_rx_packet->p_payload, &m_packet_buffer[ind_buff][0], TEST_PACKET_PAYLOAD_LEN))
    {
        // If received packet is as expected, free slot in buffer.
        memset(&m_packet_buffer[ind_buff][0], 0x00, TEST_PACKET_PAYLOAD_LEN);
    }

    return NRF_SUCCESS;
}
예제 #5
0
/**
 * @brief Class specific OUT request data callback.
 *
 * @param status    Endpoint status.
 * @param p_context Context of transfer (set by @ref app_usbd_core_setup_data_handler_set).
 *
 * @return Standard error code.
 */
static ret_code_t cdc_acm_req_out_data_cb(nrf_drv_usbd_ep_status_t status, void * p_context)
{
    if (status != NRF_USBD_EP_OK)
    {
        return NRF_ERROR_INTERNAL;
    }

    app_usbd_cdc_acm_t const * p_cdc_acm = p_context;
    app_usbd_cdc_acm_ctx_t *   p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm);

    switch (p_cdc_acm_ctx->request.type)
    {
        case APP_USBD_CDC_REQ_SET_LINE_CODING:
        {
            memcpy(&p_cdc_acm_ctx->line_coding,
                   &p_cdc_acm_ctx->request.payload.line_coding,
                   sizeof(app_usbd_cdc_line_coding_t));

            NRF_LOG_INFO("REQ_SET_LINE_CODING: baudrate: %"PRIu32", databits: %u, "
                    "format: %u, parity: %u",
                    uint32_decode(p_cdc_acm_ctx->line_coding.dwDTERate),
                    p_cdc_acm_ctx->line_coding.bDataBits,
                    p_cdc_acm_ctx->line_coding.bCharFormat,
                    p_cdc_acm_ctx->line_coding.bParityType);
            break;
        }
        default:
            return NRF_ERROR_NOT_SUPPORTED;
    }

    return NRF_SUCCESS;
}
uint32_t ser_ble_cmd_rsp_result_code_dec(uint8_t const * const p_buf,
                                         uint32_t * const      p_pos,
                                         uint32_t              packet_len,
                                         uint8_t               op_code,
                                         uint32_t * const      p_result_code)
{
    SER_ASSERT_NOT_NULL(p_buf);
    SER_ASSERT_NOT_NULL(p_pos);
    SER_ASSERT_NOT_NULL(p_result_code);

    if (packet_len < SER_CMD_RSP_HEADER_SIZE)
    {
        return NRF_ERROR_DATA_SIZE;
    }

    if (p_buf[(*p_pos)] != op_code)
    {
        return NRF_ERROR_INVALID_DATA;
    }

    *p_result_code = uint32_decode(&(p_buf[(*p_pos) + SER_CMD_RSP_STATUS_CODE_POS]));
    *p_pos        += SER_CMD_RSP_HEADER_SIZE;

    return NRF_SUCCESS;
}
예제 #7
0
static ble_ancs_c_parse_state_t notif_uid_parse(ble_ancs_c_t  * p_ancs,
                                                const uint8_t * p_data_src,
                                                uint32_t      * index)
{
     p_ancs->evt.notif_uid = uint32_decode(&p_data_src[*index]);
     *index               += sizeof(uint32_t);
     return ATTR_ID;
}
예제 #8
0
void ant_common_page_81_decode(uint8_t const                     * p_page_buffer,
                               volatile ant_common_page81_data_t * p_page_data)
{
    ant_common_page81_data_layout_t const * p_incoming_data =
        (ant_common_page81_data_layout_t *)p_page_buffer;

    p_page_data->sw_revision_minor = p_incoming_data->sw_revision_minor;
    p_page_data->sw_revision_major = p_incoming_data->sw_revision_major;

    p_page_data->serial_number = uint32_decode(p_incoming_data->serial_number);

    page81_data_log(p_page_data);
}
예제 #9
0
/**@brief Function for receiving and validating notifications received from the Notification Provider.
 * 
 * @param[in] p_ancs     Pointer to an ANCS instance to which the event belongs.
 * @param[in] p_ble_evt  Bluetooth stack event.
 * @param[in] p_data_src Pointer to data that was received from the Notification Provider.
 * @param[in] hvx_len    Length of the data that was received by the Notification Provider.
 */
static void parse_notif(const ble_ancs_c_t * p_ancs,
                        ble_ancs_c_evt_t   * p_ancs_evt,
                        const uint8_t      * p_data_src,
                        const uint16_t       hvx_data_len)
{
    uint32_t err_code;
    if (hvx_data_len != BLE_ANCS_NOTIFICATION_DATA_LENGTH)
    {
        m_ancs_evt.evt_type = BLE_ANCS_C_EVT_INVALID_NOTIF;
        p_ancs->evt_handler(&m_ancs_evt);
    }

    /*lint --e{415} --e{416} -save suppress Warning 415: possible access out of bond */
    p_ancs_evt->notif.evt_id                    =
            (ble_ancs_c_evt_id_values_t) p_data_src[BLE_ANCS_NOTIF_EVT_ID_INDEX];

    p_ancs_evt->notif.evt_flags.silent          =
            (p_data_src[BLE_ANCS_NOTIF_FLAGS_INDEX] >> BLE_ANCS_EVENT_FLAG_SILENT) & 0x01;

    p_ancs_evt->notif.evt_flags.important       =
            (p_data_src[BLE_ANCS_NOTIF_FLAGS_INDEX] >> BLE_ANCS_EVENT_FLAG_IMPORTANT) & 0x01;

    p_ancs_evt->notif.evt_flags.pre_existing    =
            (p_data_src[BLE_ANCS_NOTIF_FLAGS_INDEX] >> BLE_ANCS_EVENT_FLAG_PREEXISTING) & 0x01;

    p_ancs_evt->notif.evt_flags.positive_action =
            (p_data_src[BLE_ANCS_NOTIF_FLAGS_INDEX] >> BLE_ANCS_EVENT_FLAG_POSITIVE_ACTION) & 0x01;

    p_ancs_evt->notif.evt_flags.negative_action =
            (p_data_src[BLE_ANCS_NOTIF_FLAGS_INDEX] >> BLE_ANCS_EVENT_FLAG_NEGATIVE_ACTION) & 0x01;

    p_ancs_evt->notif.category_id               =
        (ble_ancs_c_category_id_values_t) p_data_src[BLE_ANCS_NOTIF_CATEGORY_ID_INDEX];

    p_ancs_evt->notif.category_count            = p_data_src[BLE_ANCS_NOTIF_CATEGORY_CNT_INDEX];
    p_ancs_evt->notif.notif_uid = uint32_decode(&p_data_src[BLE_ANCS_NOTIF_NOTIF_UID]);
    /*lint -restore*/

    err_code = ble_ancs_verify_notification_format(&m_ancs_evt.notif);
    if (err_code == NRF_SUCCESS)
    {
        m_ancs_evt.evt_type = BLE_ANCS_C_EVT_NOTIF;
    }
    else
    {
        m_ancs_evt.evt_type = BLE_ANCS_C_EVT_INVALID_NOTIF;
    }

    p_ancs->evt_handler(&m_ancs_evt);
}
예제 #10
0
파일: main.c 프로젝트: xueliu/nRF51822
/**@brief Function for getting the index number of a stored packet or the index number of an empty
 *        slot in the buffer.
 *
 * @details Returns the index number of a stored packet with the provided packet sequence number.
 *          Use with INVALID_PACKET_SEQ_NUMBER as input to get the index number of the first
 *          empty slot in the buffer.
 *
 * @param[out] p_index_number         Index number of the first packet with matching sequence
 *                                    number.
 * @param[in]  pkt_seq_num            Packet sequence number.
 *
 * @retval     NRF_SUCCESS            Matching slot found in the buffer.
 * @retval     NRF_ERROR_NOT_FOUND    No match found in the buffer.
 */
static uint32_t get_packet_buffer_index(uint32_t * p_index_number, uint32_t * pkt_seq_num)
{
    uint32_t i;
    for (i = 0; i < PACKET_BUFFER_LEN; i++)
    {
        uint32_t rx_sequence_num = uint32_decode(&m_packet_buffer[i][0]);
        if (rx_sequence_num == *pkt_seq_num)
        {
            *p_index_number = i;
            return NRF_SUCCESS;
        }
    }
    *p_index_number = 0;
    return NRF_ERROR_NOT_FOUND;
}
uint32_t uint32_t_dec(uint8_t const * const p_buf,
                      uint32_t              buf_len,
                      uint32_t * const      p_index,
                      void *                p_field)
{
    SER_ASSERT_NOT_NULL(p_buf);
    SER_ASSERT_NOT_NULL(p_index);
    SER_ASSERT_NOT_NULL(p_field);

    uint32_t * p_uint32 = (uint32_t *)p_field;

    SER_ASSERT_LENGTH_LEQ(4, ((int32_t)buf_len - *p_index));

    *p_uint32 = uint32_decode(&p_buf[*p_index]);
    *p_index += 4;

    return NRF_SUCCESS;
}
예제 #12
0
/**@brief Function for parsing command id and notification id.
 *        Used in the @ref parse_get_notif_attrs_response state machine.
 *
 * @details UID and command ID will be received only once at the beginning of the first
 *          GATTC notification of a new attribute request for a given iOS notification.
 *
 * @param[in] p_ancs     Pointer to an ANCS instance to which the event belongs.
 * @param[in] p_data_src Pointer to data that was received from the Notification Provider.
 * @param[in] index      Pointer to an index that helps us keep track of the current data to be parsed.
 *
 * @return The next parse state.
 */
static ble_ancs_c_parse_state_t command_id_and_notif_parse(ble_ancs_c_t * p_ancs,
                                                           const uint8_t * p_data_src,
                                                           uint32_t * index)
{
    ble_ancs_c_command_id_values_t command_id;

    command_id = (ble_ancs_c_command_id_values_t) p_data_src[(*index)++];

    if (command_id != BLE_ANCS_COMMAND_ID_GET_NOTIF_ATTRIBUTES)
    {
        NRF_LOG_INFO("Invalid Command ID");
        return DONE;
    }

     p_ancs->evt.attr.notif_uid  = uint32_decode(&p_data_src[*index]);
     *index                     += sizeof(uint32_t);
     return ATTR_ID;

}
예제 #13
0
/**@brief Callback handler to receive data on UDP port.
 *
 * @param[in]   p_socket         Socket identifier.
 * @param[in]   p_ip_header      IPv6 header containing source and destination addresses.
 * @param[in]   p_udp_header     UDP header identifying local and remote endpoints.
 * @param[in]   process_result   Result of data reception, there could be possible errors like
 *                               invalid checksum etc.
 * @param[in]   iot_pbuffer_t    Packet buffer containing the received data packet.
 *
 * @retval      NRF_SUCCESS      Indicates received data was handled successfully, else an error
 *                               code indicating reason for failure.
 */
uint32_t rx_udp_port_app_handler(const udp6_socket_t * p_socket,
                                 const ipv6_header_t * p_ip_header,
                                 const udp6_header_t * p_udp_header,
                                 uint32_t              process_result,
                                 iot_pbuffer_t       * p_rx_packet)
{
    // APPL_LOG("[APPL]: Got UDP6 data on socket 0x%08lx\r\n", p_socket->socket_id);
    // APPL_LOG("[APPL]: Source IPv6 Address: ");
    // APPL_ADDR(p_ip_header->srcaddr);

    APP_ERROR_CHECK(process_result);

    // Print PORTs
    // APPL_LOG("[APPL]: UDP Destination port: %lx\r\n", HTONS(p_udp_header->destport));
    // APPL_LOG("[APPL]: UDP Source port: %lx\r\n",      HTONS(p_udp_header->srcport));

    // UDP packet received from the Client node.
    APPL_LOG("[APPL]: Received UDP packet sequence number: %ld\r\n", \
             uint32_decode(&p_rx_packet->p_payload[0]));

    iot_pbuffer_alloc_param_t   pbuff_param;
    iot_pbuffer_t             * p_tx_buffer;

    pbuff_param.flags  = PBUFFER_FLAG_DEFAULT;
    pbuff_param.type   = UDP6_PACKET_TYPE;
    pbuff_param.length = p_rx_packet->length;

    // Allocate packet buffer.
    uint32_t err_code = iot_pbuffer_allocate(&pbuff_param, &p_tx_buffer);
    APP_ERROR_CHECK(err_code);

    memcpy(p_tx_buffer->p_payload, p_rx_packet->p_payload, p_rx_packet->length);

    // Send back the received packet payload without any modification. 
    err_code = udp6_socket_sendto(&m_udp_socket, &p_ip_header->srcaddr, HTONS(UDP_PORT), p_tx_buffer);
    APP_ERROR_CHECK(err_code);

    m_display_state  = LEDS_TX_UDP_PACKET;
    m_udp_tx_occured = true;

    return NRF_SUCCESS;
}
예제 #14
0
void ble_rpc_cmd_rsp_pkt_received(uint8_t * packet, uint16_t packet_length)
{
    uint32_t index = 0;

    g_cmd_response_buf = packet;

    if (g_cmd_response_buf[index++] != BLE_RPC_PKT_RESP)
    {
        // Received a packet that is not of interest to the command encoder.
        return;
    }

    g_cmd_response.op_code = g_cmd_response_buf[index++];

    if (packet_length >= RPC_BLE_CMD_RESP_PKT_MIN_SIZE)
    {
        g_cmd_response.err_code = uint32_decode(&g_cmd_response_buf[index++]);
    }
    else
    {
        g_cmd_response.err_code = NRF_ERROR_INTERNAL;
    }
}
예제 #15
0
/**@brief Function for parsing received notification attribute response data.
 *
 * @details The data that comes from the Notification Provider can be much longer than what
 *          would fit in a single GATTC notification. Therefore, function relies on static
 *          variables and a state-oriented switch case.
 *          UID and command ID will be received only once at the beginning of the first 
 *          GATTC notification of a new attribute request for a given iOS notification.
 *          After this, we can loop several ID > LENGTH > DATA > ID > LENGTH > DATA until we have
 *          received all attributes we wanted as a Notification Consumer. The Notification Provider
 *          can also simply stop sending attributes.
 *
 * @param[in] p_ancs     Pointer to an ANCS instance to which the event belongs.
 * @param[in] p_data_src Pointer to data that was received from the Notification Provider.
 * @param[in] hvx_len    Length of the data that was received from the Notification Provider.
 */
static void parse_get_notif_attrs_response(ble_ancs_c_t  * p_ancs,
                                           const uint8_t * p_data_src,
                                           const uint16_t  hvx_data_len)
{
    static uint8_t               * p_data_dest;
    static uint16_t                current_attr_index;
    static ble_ancs_c_evt_t        evt;
    ble_ancs_c_command_id_values_t command_id;
    uint32_t                       index;

    evt.ancs_attr_list = m_ancs_attr_list;

    for (index = 0; index < hvx_data_len;)
    {
        switch (m_parse_state)
        {
            case COMMAND_ID_AND_NOTIF_UID:
                command_id = (ble_ancs_c_command_id_values_t) p_data_src[index++];
                if(command_id != BLE_ANCS_COMMAND_ID_GET_NOTIF_ATTRIBUTES)
                {
                    LOG("[ANCS]: Invalid Command ID");
                    m_parse_state = DONE;
                }

                evt.attr.notif_uid  = uint32_decode(&p_data_src[index]);
                index              += sizeof(uint32_t);
                m_parse_state       = ATTR_ID;

                if (evt.attr.notif_uid != m_ancs_evt.notif.notif_uid)
                {
                    LOG("UID mismatch: Notification UID %x , Attribute UID %x\n\r",
                        evt.notif.notif_uid,
                        evt.attr.notif_uid);
                    m_parse_state = DONE;
                }
                break;

            case ATTR_ID:
                if (m_expected_number_of_attrs == 0)
                {
                    LOG("[ANCS]: All requested attributes received\n\r");
                    m_parse_state = DONE;
                    index++;
                }
                else
                {
                    evt.attr.attr_id = (ble_ancs_c_notif_attr_id_values_t) p_data_src[index++];
                    p_data_dest        = m_ancs_attr_list[evt.attr.attr_id].p_attr_data;
                    if (m_ancs_attr_list[evt.attr.attr_id].get == true)
                    {
                        m_parse_state = ATTR_LEN1;
                    }
                    m_expected_number_of_attrs--;
                    LOG("Attribute ID %i \n\r", evt.attr.attr_id);
                }
                break;

            case ATTR_LEN1:
                evt.attr.attr_len = p_data_src[index++];
                m_parse_state       = ATTR_LEN2;
                break;

            case ATTR_LEN2:
                evt.attr.attr_len |= (p_data_src[index++] << 8);
                current_attr_index   = 0;
                if (evt.attr.attr_len != 0)
                {
                    m_parse_state = ATTR_DATA;
                }
                else
                {
                    evt.evt_type = BLE_ANCS_C_EVT_NOTIF_ATTRIBUTE;
                    p_ancs->evt_handler(&evt);
                    m_parse_state = ATTR_ID;
                }
                LOG("Attribute LEN %i \n\r", evt.attr.attr_len);
                break;

            case ATTR_DATA:
                // We have not reached the end of the attribute, nor our max allocated internal size.
                // Proceed with copying data over to our buffer.
                if (   (current_attr_index < m_ancs_attr_list[evt.attr.attr_id].attr_len)
                    && (current_attr_index < evt.attr.attr_len))
                {
                    p_data_dest[current_attr_index++] = p_data_src[index++];
                }
                // We have reached the end of the attribute, or our max allocated internal size.
                // Stop copying data over to our buffer. NUL-terminate at the current index.
                if ( (current_attr_index == evt.attr.attr_len) ||
                     (current_attr_index == m_ancs_attr_list[evt.attr.attr_id].attr_len))
                {
                    p_data_dest[current_attr_index] = '\0';
                    
                    // If our max buffer size is smaller than the remaining attribute data, we must
                    // increase index to skip the data until the start of the next attribute.
                    if (current_attr_index < evt.attr.attr_len)
                    {
                        index += (evt.attr.attr_len - current_attr_index);
                    }
                    m_parse_state = ATTR_ID;
                    LOG("Attribute finished!\n\r");
                    evt.evt_type = BLE_ANCS_C_EVT_NOTIF_ATTRIBUTE;
                    p_ancs->evt_handler(&evt);
                }
                break;

            case DONE:
                index = hvx_data_len;
                break;

            default:
                // Default case will never trigger intentionally. Go to the DONE state to minimize the consequences.
                m_parse_state = DONE;
                break;
        }
    }
}
예제 #16
0
/**@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)
{
    nrf_dfu_res_code_t  res_code;
    nrf_dfu_req_t       dfu_req;
    nrf_dfu_res_t       dfu_res = {{{0}}};

    memset(&dfu_req, 0, sizeof(nrf_dfu_req_t));

    switch (p_ble_write_evt->data[0])
    {
        case BLE_DFU_OP_CODE_CREATE_OBJECT:

            if (p_ble_write_evt->len != PKT_CREATE_PARAM_LEN)
            {
                return response_send(p_dfu,
                                     BLE_DFU_OP_CODE_CREATE_OBJECT,
                                     NRF_DFU_RES_CODE_INVALID_PARAMETER);
            }

            NRF_LOG_INFO("Received create object\r\n");

            // Reset the packet receipt notification on create object
            m_pkt_notif_target_cnt = m_pkt_notif_target;

            // Get type parameter
            //lint -save -e415
            dfu_req.obj_type    =  p_ble_write_evt->data[1];
            //lint -restore

            // Get length value
            //lint -save -e416
            dfu_req.object_size = uint32_decode(&(p_ble_write_evt->data[2]));
            //lint -restore

            // Set req type
            dfu_req.req_type        = NRF_DFU_OBJECT_OP_CREATE;

            res_code = nrf_dfu_req_handler_on_req(NULL, &dfu_req, &dfu_res);
            return response_send(p_dfu, BLE_DFU_OP_CODE_CREATE_OBJECT, res_code);

        case BLE_DFU_OP_CODE_EXECUTE_OBJECT:
            NRF_LOG_INFO("Received execute object\r\n");

            // Set req type
            dfu_req.req_type     =  NRF_DFU_OBJECT_OP_EXECUTE;

            res_code = nrf_dfu_req_handler_on_req(NULL, &dfu_req, &dfu_res);
            return response_send(p_dfu, BLE_DFU_OP_CODE_EXECUTE_OBJECT, res_code);

        case BLE_DFU_OP_CODE_SET_RECEIPT_NOTIF:
            NRF_LOG_INFO("Set receipt notif\r\n");
            if (p_ble_write_evt->len != PKT_SET_PRN_PARAM_LEN)
            {
                return (response_send(p_dfu,
                                      BLE_DFU_OP_CODE_SET_RECEIPT_NOTIF,
                                      NRF_DFU_RES_CODE_INVALID_PARAMETER));
            }

            //lint -save -e415
            m_pkt_notif_target = uint16_decode(&(p_ble_write_evt->data[1]));
            //lint -restore
            m_pkt_notif_target_cnt   = m_pkt_notif_target;

            return response_send(p_dfu, BLE_DFU_OP_CODE_SET_RECEIPT_NOTIF, NRF_DFU_RES_CODE_SUCCESS);

        case BLE_DFU_OP_CODE_CALCULATE_CRC:
            NRF_LOG_INFO("Received calculate CRC\r\n");

            dfu_req.req_type     =  NRF_DFU_OBJECT_OP_CRC;

            res_code = nrf_dfu_req_handler_on_req(NULL, &dfu_req, &dfu_res);
            if (res_code == NRF_DFU_RES_CODE_SUCCESS)
            {
                return response_crc_cmd_send(p_dfu, dfu_res.offset, dfu_res.crc);
            }
            else
            {
                return response_send(p_dfu, BLE_DFU_OP_CODE_CALCULATE_CRC, res_code);
            }

        case BLE_DFU_OP_CODE_SELECT_OBJECT:

            NRF_LOG_INFO("Received select object\r\n");
            if (p_ble_write_evt->len != PKT_READ_OBJECT_INFO_PARAM_LEN)
            {
                return response_send(p_dfu,
                                     BLE_DFU_OP_CODE_SELECT_OBJECT,
                                     NRF_DFU_RES_CODE_INVALID_PARAMETER);
            }

            // Set object type to read info about
            //lint -save -e415
            dfu_req.obj_type = p_ble_write_evt->data[1];
            //lint -restore

            dfu_req.req_type = NRF_DFU_OBJECT_OP_SELECT;

            res_code = nrf_dfu_req_handler_on_req(NULL, &dfu_req, &dfu_res);
            if (res_code == NRF_DFU_RES_CODE_SUCCESS)
            {
                return response_select_object_cmd_send(p_dfu, dfu_res.max_size, dfu_res.offset, dfu_res.crc);
            }
            else
            {
                return response_send(p_dfu, BLE_DFU_OP_CODE_SELECT_OBJECT, res_code);
            }

        default:
            NRF_LOG_INFO("Received unsupported OP code\r\n");
            // Unsupported op code.
            return response_send(p_dfu,
                                 p_ble_write_evt->data[0],
                                 NRF_DFU_RES_CODE_INVALID_PARAMETER);
    }
}
예제 #17
0
static void on_packet_received(serial_dfu_t * p_dfu)
{
    nrf_dfu_req_t       dfu_req;
    nrf_dfu_res_t       dfu_res = {{{0}}};

    serial_dfu_response_t serial_response;

    memset(&dfu_req, 0, sizeof(nrf_dfu_req_t));

    const serial_dfu_op_code_t op_code             = (serial_dfu_op_code_t)p_dfu->recv_buffer[0];
    const uint16_t             packet_payload_len  = p_dfu->slip.current_index - 1;
    uint8_t * p_payload                            = &p_dfu->recv_buffer[1];

    serial_response.op_code = op_code;

    nrf_gpio_pin_clear(CONNECTED_LED_PIN_NO);
    nrf_gpio_pin_set(AVAILABLE_LED_PIN_NO);

    switch (op_code)
    {
        case SERIAL_DFU_OP_CODE_CREATE_OBJECT:

            if (packet_payload_len != CREATE_OBJECT_REQUEST_LEN)
            {
                serial_response.resp_val = NRF_DFU_RES_CODE_INVALID_PARAMETER;
                break;
            }

            NRF_LOG_DEBUG("Received create object\r\n");

            // Reset the packet receipt notification on create object
            p_dfu->pkt_notif_target_count = p_dfu->pkt_notif_target;

            // Get type parameter
            dfu_req.obj_type    =  p_payload[0];

            // Get length value
            dfu_req.object_size = uint32_decode(&p_payload[1]);

            // Set req type
            dfu_req.req_type        = NRF_DFU_OBJECT_OP_CREATE;

            serial_response.resp_val = nrf_dfu_req_handler_on_req(NULL, &dfu_req, &dfu_res);
            break;

        case SERIAL_DFU_OP_CODE_SET_RECEIPT_NOTIF:
            NRF_LOG_DEBUG("Set receipt notif\r\n");
            if (packet_payload_len != SET_RECEIPT_NOTIF_REQUEST_LEN)
            {
                serial_response.resp_val = NRF_DFU_RES_CODE_INVALID_PARAMETER;
                break;
            }

            p_dfu->pkt_notif_target = uint16_decode(&p_payload[0]);
            p_dfu->pkt_notif_target_count   = p_dfu->pkt_notif_target;

            serial_response.resp_val = NRF_DFU_RES_CODE_SUCCESS;
            break;

        case SERIAL_DFU_OP_CODE_CALCULATE_CRC:
            NRF_LOG_DEBUG("Received calculate CRC\r\n");

            dfu_req.req_type     =  NRF_DFU_OBJECT_OP_CRC;

            serial_response.resp_val = nrf_dfu_req_handler_on_req(NULL, &dfu_req, &dfu_res);
            serial_response.crc_response.offset = dfu_res.offset;
            serial_response.crc_response.crc    = dfu_res.crc;
            break;

        case SERIAL_DFU_OP_CODE_EXECUTE_OBJECT:
            NRF_LOG_DEBUG("Received execute object\r\n");

            // Set req type
            dfu_req.req_type     =  NRF_DFU_OBJECT_OP_EXECUTE;

            serial_response.resp_val = nrf_dfu_req_handler_on_req(NULL, &dfu_req, &dfu_res);
            break;

        case SERIAL_DFU_OP_CODE_SELECT_OBJECT:

            NRF_LOG_DEBUG("Received select object\r\n");
            if (packet_payload_len != SELECT_OBJECT_REQUEST_LEN)
            {
                serial_response.resp_val = NRF_DFU_RES_CODE_INVALID_PARAMETER;
                break;
            }

            // Set object type to read info about
            dfu_req.obj_type = p_payload[0];

            dfu_req.req_type = NRF_DFU_OBJECT_OP_SELECT;

            serial_response.resp_val = nrf_dfu_req_handler_on_req(NULL, &dfu_req, &dfu_res);
            serial_response.select_response.max_size = dfu_res.max_size;
            serial_response.select_response.offset   = dfu_res.offset;
            serial_response.select_response.crc      = dfu_res.crc;
            break;

        case SERIAL_DFU_OP_CODE_GET_SERIAL_MTU:
            NRF_LOG_DEBUG("Received get serial mtu\r\n");

            serial_response.resp_val = NRF_DFU_RES_CODE_SUCCESS;
            serial_response.serial_mtu_response.mtu = sizeof(p_dfu->recv_buffer);
            break;

        case SERIAL_DFU_OP_CODE_WRITE_OBJECT:
             // Set req type
            dfu_req.req_type =  NRF_DFU_OBJECT_OP_WRITE;

            // Set data and length
            dfu_req.p_req    =  &p_payload[0];
            dfu_req.req_len  =  packet_payload_len;

            serial_response.resp_val = nrf_dfu_req_handler_on_req(NULL, &dfu_req, &dfu_res);
            if(serial_response.resp_val != NRF_DFU_RES_CODE_SUCCESS)
            {
                NRF_LOG_ERROR("Failure to run packet write\r\n");
            }

            // Check if a packet receipt notification is needed to be sent.
            if (p_dfu->pkt_notif_target != 0 && --p_dfu->pkt_notif_target_count == 0)
            {
                serial_response.op_code = SERIAL_DFU_OP_CODE_CALCULATE_CRC;
                serial_response.crc_response.offset = dfu_res.offset;
                serial_response.crc_response.crc    = dfu_res.crc;

                // Reset the counter for the number of firmware packets.
                p_dfu->pkt_notif_target_count = p_dfu->pkt_notif_target;
            }
            break;

        default:
            // Unsupported op code.
            NRF_LOG_WARNING("Received unsupported OP code\r\n");
            serial_response.resp_val = NRF_DFU_RES_CODE_INVALID_PARAMETER;
            break;
    }

    if (op_code != SERIAL_DFU_OP_CODE_WRITE_OBJECT)
    {
        response_send(p_dfu, &serial_response);
    }
}
/**@brief Function for decoding a ITU Sensor Service Configuration.
 *
 * @param[in]   p_iss			         ITU Sensor Service structure
 * @param[out]  p_encoded_buffer   Buffer where the encoded data will be written.
 *
 * @return      Size of encoded data.
 */
static void its_conf_decode(iss_t * p_iss,uint16_t data_length, uint8_t * data)
{
		if(data_length > 0){		
			//p_iss->gatt_db_needs_cleaning = true;
			uint8_t data_bits = data[0];
			//if(BIT_VALUE(data_bits,ITS_MEAS_FLAG_OVERRIDE_BIT_PLACEMENT)){
					//OVERRIDE.. Client wants to set new values
					if(data_length > 1){
						
						uint8_t i = 1;
						
						//Check if Seq. nr. is set	
						if(BIT_VALUE(data_bits,ITS_MEAS_FLAG_SPACE_TIME_BIT_PLACEMENT)){
							p_iss->coord = data[i];	
							i++;
							p_iss->curr_seq_nr = uint16_decode(&data[i]);	
							i += 2;
						}
					
						//Check if Unit is set	
						if(BIT_VALUE(data_bits,ITS_MEAS_FLAG_UNIT_BIT_PLACEMENT)){
								p_iss->unit = uint16_decode(&data[i]);
								i += 2;
						}
						
						//Check if Type is set	
						if(BIT_VALUE(data_bits,ITS_MEAS_FLAG_TYPE_MAKE_BIT_PLACEMENT)){
								p_iss->type = data[i];
								i++;
								p_iss->make = data[i];
								i++;
						}
											
						//Check if ID is set	
						if(BIT_VALUE(data_bits,ITS_MEAS_FLAG_ID_BIT_PLACEMENT)){
								p_iss->ID = uint16_decode(&data[i]);
								i += 2;
						}
						
						//Check if Sampling freq. is set	
						if(BIT_VALUE(data_bits,ITS_MEAS_FLAG_SAMP_FREQ_BIT_PLACEMENT)){
								p_iss->samp_freq_in_m_sec = uint32_decode(&data[i]);
								p_iss->p_update_samp_freq();
						}
					}					
			/*}else{
				//set presentation			
				
				// SET Space + Time
				p_iss->space_time_present = BIT_VALUE(data_bits,ITS_MEAS_FLAG_SPACE_TIME_BIT_PLACEMENT);
				
				//SET Unit	
				p_iss->unit_present = BIT_VALUE(data_bits,ITS_MEAS_FLAG_UNIT_BIT_PLACEMENT);
				
				//SET Type	
				p_iss->type_make_present = BIT_VALUE(data_bits,ITS_MEAS_FLAG_TYPE_MAKE_BIT_PLACEMENT);
				
				//SET ID	
				p_iss->ID_present = BIT_VALUE(data_bits,ITS_MEAS_FLAG_ID_BIT_PLACEMENT);
				
				//SET Sampling freq.	
				p_iss->samp_freq_present = BIT_VALUE(data_bits,ITS_MEAS_FLAG_SAMP_FREQ_BIT_PLACEMENT);
			}
			
			uint16_t data_len = MAX_HTM_LEN;
			uint8_t data_buf[MAX_HTM_LEN];
			memset(data_buf, 0, sizeof(data_buf));
			data_len = its_conf_encode(p_iss, data_buf);
			sd_ble_gatts_value_set(p_iss->meas_conf_handles.value_handle,
																			0,
																			&data_len,
																			data_buf);*/
		}
}
예제 #19
0
/**@brief     Function for processing start data written by the peer to the DFU Packet
 *            Characteristic.
 *
 * @param[in] p_dfu     DFU Service Structure.
 * @param[in] p_evt     Pointer to the event received from the S110 SoftDevice.
 */
static void start_data_process(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt)
{
    uint32_t err_code;
    
    dfu_start_packet_t start_packet   = {.dfu_update_mode = m_update_mode};    
    dfu_update_packet_t update_packet =
    {
        .packet_type         = START_PACKET,
        .params.start_packet = &start_packet
    };
    
    uint32_t length = p_evt->evt.ble_dfu_pkt_write.len;

    // Verify that the data is exactly three * four bytes (three words) long.
    // Or a single word to support backwards compatibility of application image transfer.
    if ((length != (3 * sizeof(uint32_t))) && (length != sizeof(uint32_t)))
    {
        err_code = ble_dfu_response_send(p_dfu,
                                         BLE_DFU_START_PROCEDURE,
                                         BLE_DFU_RESP_VAL_NOT_SUPPORTED);
        APP_ERROR_CHECK(err_code);
    }
    else
    {
        // Extract the size of from the DFU Packet Characteristic.
        uint8_t * length_data = p_evt->evt.ble_dfu_pkt_write.p_data;

        if (length == sizeof(uint32_t))
        {
            // Legacy update.
            start_packet.sd_image_size  = 0;
            start_packet.bl_image_size  = 0;
            start_packet.app_image_size = uint32_decode(length_data);
        }
        else
        {
            start_packet.sd_image_size  = uint32_decode(length_data);
            start_packet.bl_image_size  = uint32_decode(length_data + 4);
            start_packet.app_image_size = uint32_decode(length_data + 8);
        }

        err_code = dfu_start_pkt_handle(&update_packet);
        if (err_code != NRF_SUCCESS)
        {
            // Translate the err_code returned by the above function to DFU Response Value.
            ble_dfu_resp_val_t resp_val;

            resp_val = nrf_err_code_translate(err_code, BLE_DFU_START_PROCEDURE);

            err_code = ble_dfu_response_send(p_dfu, BLE_DFU_START_PROCEDURE, resp_val);
        }

        APP_ERROR_CHECK(err_code);
    }
}


/**@brief     Function for processing initialization data written by the peer to the DFU Packet
 *            Characteristic.
 *
 * @param[in] p_dfu     DFU Service Structure.
 * @param[in] p_evt     Pointer to the event received from the S110 SoftDevice.
 */
static void init_data_process(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt)
{
    uint32_t            err_code;
    dfu_update_packet_t dfu_pkt;
    uint8_t             num_of_padding_bytes = 0;    

    dfu_pkt.packet_type   = INIT_PACKET;

    dfu_pkt.params.data_packet.p_data_packet = (uint32_t *)p_evt->evt.ble_dfu_pkt_write.p_data;

    // The DFU module accepts the dfu_pkt.packet_length to be in 'number of words'. And so if the
    // received data does not have a size which is a multiple of four, it should be padded with
    // zeros and the packet_length should be incremented accordingly before calling
    // dfu_init_pkt_handle.
    if ((p_evt->evt.ble_dfu_pkt_write.len & (sizeof(uint32_t) - 1)) != 0)
    {
         // Find out the number of bytes to be padded.
         num_of_padding_bytes = sizeof(uint32_t)
                                -
                                (p_evt->evt.ble_dfu_pkt_write.len & (sizeof(uint32_t) - 1));

         uint32_t i;
         for (i = 0; i < num_of_padding_bytes; i++)
         {
             dfu_pkt.params.data_packet.p_data_packet[p_evt->evt.ble_dfu_pkt_write.len + i] = 0;
         }
    }

    dfu_pkt.params.data_packet.packet_length = 
        (p_evt->evt.ble_dfu_pkt_write.len + num_of_padding_bytes) / sizeof(uint32_t);

    err_code = dfu_init_pkt_handle(&dfu_pkt);

    // Translate the err_code returned by the above function to DFU Response Value.
    ble_dfu_resp_val_t resp_val;

    resp_val = nrf_err_code_translate(err_code, BLE_DFU_INIT_PROCEDURE);

    err_code = ble_dfu_response_send(p_dfu, BLE_DFU_INIT_PROCEDURE, resp_val);
    APP_ERROR_CHECK(err_code);
}
void ble_agsensor_process_request(uint8_t data_len, uint8_t * p_data, uint16_t op_code, bool read_start, bool app_request, bool write)
{

    APPL_LOG("ble_agsensor_process_request opcode %d \r\n", (int)op_code);
    if (isConfigSendWaiting == true && write == false && app_request == false)
    {
        APPL_LOG("ble_agsensor_process_request 1 \r\n");
        return;
    }

//    APPL_LOG("ble_agsensor_process_request 2 \r\n");

	uint8_t sensor_depth;
	uint32_t tempData32 = 0;
	uint16_t tempData16 = 0;

    // Asked for stop sending the Data for specific opcode
    if (app_request == true && read_start == false && opcode_inRead == op_code && write == false){
    	// Set to date time as they count as the ping message
    	opcode_inRead = BLE_AGSENSOR_CONFIGURATION_OPCODE_DATETIME;
        APPL_LOG("ble_agsensor_process_request 2 \r\n");
    	return;
    }

    hvx_p_config_len = 0;
    (hvx_p_config_len) += uint16_encode(op_code, &hvx_encoded_buffer[hvx_p_config_len]);

    switch (op_code)
    {
		case BLE_AGSENSOR_CONFIGURATION_OPCODE_DATETIME:
			if (write && data_len >=4 && p_data != NULL) {
				tempData32 = (((uint32_t)((uint8_t *)p_data)[0]) << 0)  |
			                     (((uint32_t)((uint8_t *)p_data)[1]) << 8)  |
			                     (((uint32_t)((uint8_t *)p_data)[2]) << 16) |
			                     (((uint32_t)((uint8_t *)p_data)[3]) << 24 );

			    setOffsetTime(tempData32);
			    APPL_LOG("Date time offset update  \r\n");
			    return;
			}
			else {
//			    APPL_LOG("Date time msg created  \r\n");
				datetimeReadEnable = read_start;
				tempData32 = getTimeInSec();
//				tempData32 = SwapByte4(tempData32);
			    (hvx_p_config_len) += uint32_encode(tempData32, &hvx_encoded_buffer[hvx_p_config_len]);
			}
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_BATTERY_LEVEL: // read only
			batteryLevelReadEnable = read_start;
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_LONGITUDE_LATITUDE:
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_BONDED_DONGLE_RSSI: // read only
			bondedDongleRssiReadEnable = read_start;
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_BONDED_DONGLE_MAC_ADDRESS: // read only
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_TIME_SYNC_OFFSET:
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_UPDATE_RATE:
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_DATUM:
			break;

			/*Mosture */
		case BLE_AGSENSOR_CONFIGURATION_OPCODE_MOSTURE_AIRWATER:
			if (write && data_len >= 5 && p_data != NULL)
			{
			    APPL_LOG("Moisture sensor AirWater write request\r\n");
				sensor_depth = p_data[0];
				// Write the Air value in the config
				tempData16 = uint16_decode(&p_data[1]);
				cfgWriteConfig(&moisture_air[sensor_depth], &tempData16, sizeof(tempData16));

				// Write the Water value in the config
				tempData16 = uint16_decode(&p_data[3]);
				cfgWriteConfig(&moisture_water[sensor_depth], &tempData16, sizeof(tempData16));

				// Need to create response msg so application get the response to update the UI.
				ble_agsensor_create_temp_msg(op_code, p_data, data_len);
			    return;
			}
			else
			{
				if(read_start)
				{
					msg_sensor_depth = MAX_SENSOR_COUNT;
				    APPL_LOG("moisture sensor air Water read request\r\n");
				    // Job is done so need to return msg will be created on the ACK call back
				    return;
				}
				else
				{
					msg_sensor_depth--;
					if (msg_sensor_depth == 0) {
				    	opcode_inRead = BLE_AGSENSOR_CONFIGURATION_OPCODE_DATETIME;
					}
				}
				// Add the sensor count in the sending msg
				hvx_encoded_buffer[hvx_p_config_len] = msg_sensor_depth;
				hvx_p_config_len ++;

				// Add the Air value in the sending msg
				cfgReadConfig(&moisture_air[msg_sensor_depth], &tempData16, sizeof(tempData16));
				(hvx_p_config_len) += uint16_encode(tempData16, &hvx_encoded_buffer[hvx_p_config_len]);

				// Add the Water value in the sending msg
				cfgReadConfig(&moisture_water[msg_sensor_depth], &tempData16, sizeof(tempData16));
				(hvx_p_config_len) += uint16_encode(tempData16, &hvx_encoded_buffer[hvx_p_config_len]);

				// If app have requested specific data which is not read start then need to create the temp msg
				if(app_request == true) {
					ble_agsensor_create_temp_msg(0, &hvx_encoded_buffer, hvx_p_config_len);
				}
			    APPL_LOG("moisture sensor Air Water data created %d\r\n", msg_sensor_depth);
			}
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_MOSTURE_ABCD:
			if (write && data_len >=17 && p_data != NULL)
			{
			    APPL_LOG("Moisture sensor ABCD write request\r\n");
				sensor_depth = p_data[0];
				// Write the A value in the config
				tempData32 = uint32_decode(&p_data[1]);
				cfgWriteConfig(&moisture_A[sensor_depth], &tempData32, sizeof(tempData32));
				// Write the B value in the config
				tempData32 = uint32_decode(&p_data[5]);
				cfgWriteConfig(&moisture_B[sensor_depth], &tempData32, sizeof(tempData32));
				// Write the B value in the config
				tempData32 = uint32_decode(&p_data[9]);
				cfgWriteConfig(&moisture_C[sensor_depth], &tempData32, sizeof(tempData32));
				// Write the B value in the config
				tempData32 = uint32_decode(&p_data[13]);
				cfgWriteConfig(&moisture_D[sensor_depth], &tempData32, sizeof(tempData32));

				// Need to create response msg so application get the response to update the UI.
				ble_agsensor_create_temp_msg(op_code, p_data, data_len);
			    return;
			}
			else
			{
				if(read_start)
				{
					msg_sensor_depth = MAX_SENSOR_COUNT;
				    APPL_LOG("moisture sensor ABCD read request\r\n");
				    // Job is done so need to return msg will be created on the ACK call back
				    return;
				}
				else
				{
					msg_sensor_depth--;
					if (msg_sensor_depth == 0) {
				    	opcode_inRead = BLE_AGSENSOR_CONFIGURATION_OPCODE_DATETIME;
					}
				}
				// Add the sensor count in the sending msg
				hvx_encoded_buffer[hvx_p_config_len] = msg_sensor_depth;
				hvx_p_config_len ++;

				// Add the A value in the sending msg
				cfgReadConfig(&moisture_A[msg_sensor_depth], &tempData32, sizeof(tempData32));
				(hvx_p_config_len) += uint32_encode(tempData32, &hvx_encoded_buffer[hvx_p_config_len]);

				// Add the B value in the sending msg
				cfgReadConfig(&moisture_B[msg_sensor_depth], &tempData32, sizeof(tempData32));
				(hvx_p_config_len) += uint32_encode(tempData32, &hvx_encoded_buffer[hvx_p_config_len]);

				// Add the C value in the sending msg
				cfgReadConfig(&moisture_C[msg_sensor_depth], &tempData32, sizeof(tempData32));
				(hvx_p_config_len) += uint32_encode(tempData32, &hvx_encoded_buffer[hvx_p_config_len]);

				// Add the D value in the sending msg
				cfgReadConfig(&moisture_D[msg_sensor_depth], &tempData32, sizeof(tempData32));
				(hvx_p_config_len) += uint32_encode(tempData32, &hvx_encoded_buffer[hvx_p_config_len]);

				// If app have requested specific data which is not read start then need to create the temp msg
				if(app_request == true) {
					ble_agsensor_create_temp_msg(0, &hvx_encoded_buffer, hvx_p_config_len);
				}
			    APPL_LOG("moisture sensor ABCD data created %d\r\n", msg_sensor_depth);
			}
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_TEMPERATURE_AB:
			if (write && data_len >=9 && p_data != NULL)
			{
			    APPL_LOG("temperature sensor AB write request\r\n");
				sensor_depth = p_data[0];
				// Write the A value in the config
				tempData32 = uint32_decode(&p_data[1]);
				cfgWriteConfig(&temperature_A[sensor_depth], &tempData32, sizeof(tempData32));
				// Write the B value in the config
				tempData32 = uint32_decode(&p_data[5]);
				cfgWriteConfig(&temperature_B[sensor_depth], &tempData32, sizeof(tempData32));

				// Need to create response msg so application get the response to update the UI.
				ble_agsensor_create_temp_msg(op_code, p_data, data_len);
			    return;
			}
			else
			{
				if(read_start)
				{
					msg_sensor_depth = MAX_SENSOR_COUNT;
				    APPL_LOG("temperature sensor AB read request\r\n");
				    // Job is done so need to return msg will be created on the ACK call back
				    return;
				}
				else
				{
					msg_sensor_depth--;
					if (msg_sensor_depth == 0) {
				    	opcode_inRead = BLE_AGSENSOR_CONFIGURATION_OPCODE_DATETIME;
					}
				}
				// Add the sensor count in the sending msg
				hvx_encoded_buffer[hvx_p_config_len] = msg_sensor_depth;
				hvx_p_config_len ++;

				// Add the A value in the sending msg
				cfgReadConfig(&temperature_A[msg_sensor_depth], &tempData32, sizeof(tempData32));
				(hvx_p_config_len) += uint32_encode(tempData32, &hvx_encoded_buffer[hvx_p_config_len]);

				// Add the B value in the sending msg
				cfgReadConfig(&temperature_B[msg_sensor_depth], &tempData32, sizeof(tempData32));
				(hvx_p_config_len) += uint32_encode(tempData32, &hvx_encoded_buffer[hvx_p_config_len]);

				// If app have requested specific data which is not read start then need to create the temp msg
				if(app_request == true) {
					ble_agsensor_create_temp_msg(0, &hvx_encoded_buffer, hvx_p_config_len);
				}
			    APPL_LOG("temperature sensor AB data created %d\r\n", msg_sensor_depth);
			}
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_SALINITY_AIRWATER:
			if (write && data_len >=5 && p_data != NULL)
			{
			    APPL_LOG("Salinity sensor AirWater write request\r\n");
				sensor_depth = p_data[0];

				// Write the Air value in the config
				tempData16 = uint16_decode(&p_data[1]);
				cfgWriteConfig(&salinity_air[sensor_depth], &tempData16, sizeof(tempData16));

				// Write the Water value in the config
				tempData16 = uint16_decode(&p_data[3]);
				cfgWriteConfig(&salinity_water[sensor_depth], &tempData16, sizeof(tempData16));

				// Need to create response msg so application get the response to update the UI.
				ble_agsensor_create_temp_msg(op_code, p_data, data_len);
			    return;
			}
			else
			{
				if(read_start)
				{
					msg_sensor_depth = MAX_SENSOR_COUNT;
				    APPL_LOG("Salinity sensor AirWater read request\r\n");
				    // Job is done so need to return msg will be created on the ACK call back
				    return;
				}
				else
				{
					msg_sensor_depth--;
					if (msg_sensor_depth == 0) {
				    	opcode_inRead = BLE_AGSENSOR_CONFIGURATION_OPCODE_DATETIME;
					}
				}
				// Add the sensor count in the sending msg
				hvx_encoded_buffer[hvx_p_config_len] = msg_sensor_depth;
				hvx_p_config_len ++;

				// Add the Air value in the sending msg
				cfgReadConfig(&salinity_air[msg_sensor_depth], &tempData16, sizeof(tempData16));
				(hvx_p_config_len) += uint16_encode(tempData16, &hvx_encoded_buffer[hvx_p_config_len]);

				// Add the Water value in the sending msg
				cfgReadConfig(&salinity_water[msg_sensor_depth], &tempData16, sizeof(tempData16));
				(hvx_p_config_len) += uint16_encode(tempData16, &hvx_encoded_buffer[hvx_p_config_len]);

				// If app have requested specific data which is not read start then need to create the temp msg
				if(app_request == true) {
					ble_agsensor_create_temp_msg(0, &hvx_encoded_buffer, hvx_p_config_len);
				}
			    APPL_LOG("Salinity sensor AirWater data created %d\r\n", msg_sensor_depth);
			}
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_SALINITY_D:
			if (write && data_len >=5 && p_data != NULL)
			{
			    APPL_LOG("Salinity sensor D write request\r\n");
				sensor_depth = p_data[0];
				// Write the D value in the config
				tempData32 = uint32_decode(&p_data[1]);
				cfgWriteConfig(&salinity_D[sensor_depth], &tempData32, sizeof(tempData32));

				// Need to create response msg so application get the response to update the UI.
				ble_agsensor_create_temp_msg(op_code, p_data, data_len);
			    return;
			}
			else
			{
				if(read_start)
				{
					msg_sensor_depth = MAX_SENSOR_COUNT;
				    APPL_LOG("Salinity sensor D read request\r\n");
				    // Job is done so need to return msg will be created on the ACK call back
				    return;
				}
				else
				{
					msg_sensor_depth--;
					if (msg_sensor_depth == 0) {
				    	opcode_inRead = BLE_AGSENSOR_CONFIGURATION_OPCODE_DATETIME;
					}
				}
				// Add the sensor count in the sending msg
				hvx_encoded_buffer[hvx_p_config_len] = msg_sensor_depth;
				hvx_p_config_len ++;

				// Add the D value in the sending msg
				cfgReadConfig(&salinity_D[msg_sensor_depth], &tempData32, sizeof(tempData32));
				(hvx_p_config_len) += uint32_encode(tempData32, &hvx_encoded_buffer[hvx_p_config_len]);

				// If app have requested specific data which is not read start then need to create the temp msg
				if(app_request == true) {
					ble_agsensor_create_temp_msg(0, &hvx_encoded_buffer, hvx_p_config_len);
				}
			    APPL_LOG("Salinity sensor D data created %d\r\n", msg_sensor_depth);
			}
			break;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_START_MEASUREMENT:
			isMeasuringSensor = true;
		    sentek_sensor_measurement_type_set(SENSOR_MEASUREMENT_CONTINUOUS);
		    APPL_LOG("Start Measurement\r\n");
			return;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_STOP_MEASUREMENT:
			isMeasuringSensor = false;
		    sentek_sensor_measurement_type_set(SENSOR_MEASUREMENT_NONE);
		    APPL_LOG("Stop doing Measurement\r\n");
		    return;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_AIR_NORMALIZE:
		    sentek_sensor_measurement_type_set(SENSOR_MEASUREMENT_AIR_NORMALIZATION);
		    airNormalizationInProgress = true;
		    APPL_LOG("Air Normalization Request\r\n");
			return;

		case BLE_AGSENSOR_CONFIGURATION_OPCODE_WATER_NORMALIZE:
		    sentek_sensor_measurement_type_set(SENSOR_MEASUREMENT_WATER_NORMALIZATION);
		    waterNormalizationInProgress = true;
		    APPL_LOG("Water Normalization Request\r\n");
		    return;

        default:
            APPL_LOG("Default msg created %d\r\n", (int)op_code);
			datetimeReadEnable = read_start;
			opcode_inRead = BLE_AGSENSOR_CONFIGURATION_OPCODE_DATETIME;
			tempData32 = getTimeInSec();
//			tempData32 = SwapByte4(tempData32);
		    (hvx_p_config_len) += uint32_encode(tempData32, &hvx_encoded_buffer[hvx_p_config_len]);
            break;
    }
	if (isConnected == true && configIndicationEnable == true) {
        isConfigSendWaiting = true;
	    return;
	}
//    APPL_LOG("read_request 6 \r\n");
	return;
}