/**@brief Function for processing a received vendor specific packet. * * @param[in] p_buffer Pointer to the packet data. * @param[in] length Length of packet data in bytes. */ static void rx_vendor_specific_pkt_type_handle(const uint8_t * p_buffer, uint32_t length) { // @note: no pointer validation check needed as allready checked by calling function. uint32_t err_code; if (is_rx_pkt_valid(p_buffer, length)) { // RX packet is valid: validate sequence number. const uint8_t rx_seq_number = packet_seq_nmbr_extract(p_buffer); if (packet_number_expected_get() == rx_seq_number) { // Sequence number is valid: transmit acknowledgement. packet_number_expected_inc(); ack_transmit(); m_is_slip_decode_ready = true; err_code = hci_mem_pool_rx_data_size_set(length); APP_ERROR_CHECK(err_code); err_code = hci_mem_pool_rx_produce(HCI_RX_BUF_SIZE, (void **)&mp_slip_used_rx_buffer); APP_ERROR_CHECK_BOOL((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NO_MEM)); // If memory pool RX buffer produce succeeded we register that buffer to slip layer // otherwise we register the internal acknowledgement buffer. err_code = hci_slip_rx_buffer_register( (err_code == NRF_SUCCESS) ? mp_slip_used_rx_buffer : m_rx_ack_buffer, (err_code == NRF_SUCCESS) ? HCI_RX_BUF_SIZE : ACK_BUF_SIZE); APP_ERROR_CHECK(err_code); if (m_transport_event_handle != NULL) { // Send application event of RX packet reception. const hci_transport_evt_t evt = {HCI_TRANSPORT_RX_RDY}; m_transport_event_handle(evt); } } else { // RX packet discarded: sequence number not valid, set the same buffer to slip layer in // order to avoid buffer overrun. err_code = hci_slip_rx_buffer_register(mp_slip_used_rx_buffer, HCI_RX_BUF_SIZE); APP_ERROR_CHECK(err_code); // As packet did not have expected sequence number: send acknowledgement with the // current expected sequence number. ack_transmit(); } } else { // RX packet discarded: reset the same buffer to slip layer in order to avoid buffer // overrun. err_code = hci_slip_rx_buffer_register(mp_slip_used_rx_buffer, HCI_RX_BUF_SIZE); APP_ERROR_CHECK(err_code); } }
uint32_t hci_transport_open(void) { mp_tx_buffer = NULL; m_tx_buffer_length = 0; m_tx_retry_counter = 0; m_is_slip_decode_ready = false; m_tx_state = TX_STATE_IDLE; m_packet_expected_seq_number = INITIAL_ACK_NUMBER_EXPECTED; m_packet_transmit_seq_number = INITIAL_ACK_NUMBER_TX; m_tx_done_result_code = HCI_TRANSPORT_TX_DONE_FAILURE; uint32_t err_code = app_timer_create(&m_app_timer_id, APP_TIMER_MODE_REPEATED, hci_transport_timeout_handle); if (err_code != NRF_SUCCESS) { // @note: conduct required interface adjustment. return NRF_ERROR_INTERNAL; } err_code = hci_mem_pool_open(); if (err_code != NRF_SUCCESS) { return err_code; } err_code = hci_slip_open(); if (err_code != NRF_SUCCESS) { return err_code; } err_code = hci_mem_pool_rx_produce(RX_BUF_SIZE, (void **)&mp_slip_used_rx_buffer); if (err_code != NRF_SUCCESS) { // @note: conduct required interface adjustment. return NRF_ERROR_INTERNAL; } err_code = hci_slip_rx_buffer_register(mp_slip_used_rx_buffer, RX_BUF_SIZE); return err_code; }
/**@brief Function for processing application 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 app_data_process(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt) { uint32_t err_code; if ((p_evt->evt.ble_dfu_pkt_write.len & (sizeof(uint32_t) - 1)) != 0) { // Data length is not a multiple of 4 (word size). err_code = ble_dfu_response_send(p_dfu, BLE_DFU_RECEIVE_APP_PROCEDURE, BLE_DFU_RESP_VAL_NOT_SUPPORTED); APP_ERROR_CHECK(err_code); return; } uint32_t length = p_evt->evt.ble_dfu_pkt_write.len; err_code = hci_mem_pool_rx_produce(length, (void**) &mp_rx_buffer); if (err_code != NRF_SUCCESS) { dfu_error_notify(p_dfu, err_code); return; } uint8_t * p_data_packet = p_evt->evt.ble_dfu_pkt_write.p_data; memcpy(mp_rx_buffer, p_data_packet, length); err_code = hci_mem_pool_rx_data_size_set(length); if (err_code != NRF_SUCCESS) { dfu_error_notify(p_dfu, err_code); return; } err_code = hci_mem_pool_rx_extract(&mp_rx_buffer, &length); if (err_code != NRF_SUCCESS) { dfu_error_notify(p_dfu, err_code); return; } dfu_update_packet_t dfu_pkt; dfu_pkt.packet_type = DATA_PACKET; dfu_pkt.params.data_packet.packet_length = length / sizeof(uint32_t); dfu_pkt.params.data_packet.p_data_packet = (uint32_t*)mp_rx_buffer; err_code = dfu_data_pkt_handle(&dfu_pkt); if (err_code == NRF_SUCCESS) { // All the expected firmware data has been received and processed successfully. m_num_of_firmware_bytes_rcvd += p_evt->evt.ble_dfu_pkt_write.len; // Notify the DFU Controller about the success about the procedure. err_code = ble_dfu_response_send(p_dfu, BLE_DFU_RECEIVE_APP_PROCEDURE, BLE_DFU_RESP_VAL_SUCCESS); APP_ERROR_CHECK(err_code); } else if (err_code == NRF_ERROR_INVALID_LENGTH) { // Firmware data packet was handled successfully. And more firmware data is expected. m_num_of_firmware_bytes_rcvd += p_evt->evt.ble_dfu_pkt_write.len; // Check if a packet receipt notification is needed to be sent. if (m_pkt_rcpt_notif_enabled) { // Decrement the counter for the number firmware packets needed for sending the // next packet receipt notification. m_pkt_notif_target_cnt--; if (m_pkt_notif_target_cnt == 0) { err_code = ble_dfu_pkts_rcpt_notify(p_dfu, m_num_of_firmware_bytes_rcvd); APP_ERROR_CHECK(err_code); // Reset the counter for the number of firmware packets. m_pkt_notif_target_cnt = m_pkt_notif_target; } } } else { uint32_t hci_error = hci_mem_pool_rx_consume(mp_rx_buffer); if (hci_error != NRF_SUCCESS) { dfu_error_notify(p_dfu, hci_error); } dfu_error_notify(p_dfu, err_code); } }
/**@brief Function for handling slip events. * * @param[in] event The event structure. */ void slip_event_handle(hci_slip_evt_t event) { uint32_t return_code; uint32_t err_code; switch (event.evt_type) { case HCI_SLIP_TX_DONE: tx_sm_event_handle(TX_EVENT_SLIP_TX_DONE); break; case HCI_SLIP_RX_RDY: return_code = packet_type_decode(event.packet, event.packet_length); switch (return_code) { case PKT_TYPE_VENDOR_SPECIFIC: rx_vendor_specific_pkt_type_handle(event.packet, event.packet_length); break; case PKT_TYPE_ACK: if (rx_ack_pkt_type_handle(event.packet)) { // Valid expected acknowledgement packet received: set correct TX done event // callback function result code and execute state change. m_tx_done_result_code = HCI_TRANSPORT_TX_DONE_SUCCESS; tx_sm_event_handle(TX_EVENT_VALID_RX_ACK); } /* fall-through */ default: // RX packet dropped: reset memory buffer to slip in order to avoid RX buffer // overflow. // If existing mem pool produced RX buffer exists reuse that one. If existing // mem pool produced RX buffer does not exist try to produce new one. If // producing fails use the internal acknowledgement buffer. if (mp_slip_used_rx_buffer != NULL) { err_code = hci_slip_rx_buffer_register(mp_slip_used_rx_buffer, HCI_RX_BUF_SIZE); APP_ERROR_CHECK(err_code); } else { err_code = hci_mem_pool_rx_produce(HCI_RX_BUF_SIZE, (void **)&mp_slip_used_rx_buffer); APP_ERROR_CHECK_BOOL((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NO_MEM)); err_code = hci_slip_rx_buffer_register( (err_code == NRF_SUCCESS) ? mp_slip_used_rx_buffer : m_rx_ack_buffer, (err_code == NRF_SUCCESS) ? HCI_RX_BUF_SIZE : ACK_BUF_SIZE); APP_ERROR_CHECK(err_code); } break; } break; case HCI_SLIP_RX_OVERFLOW: err_code = hci_slip_rx_buffer_register(m_rx_ack_buffer, ACK_BUF_SIZE); APP_ERROR_CHECK(err_code); break; case HCI_SLIP_ERROR: APP_ERROR_HANDLER(event.evt_type); break; default: APP_ERROR_HANDLER(event.evt_type); break; } }