123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- /**
- * Copyright (c) 2017 - 2020, Nordic Semiconductor ASA
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form, except as embedded into a Nordic
- * Semiconductor ASA integrated circuit in a product or a software update for
- * such product, must reproduce the above copyright notice, this list of
- * conditions and the following disclaimer in the documentation and/or other
- * materials provided with the distribution.
- *
- * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * 4. This software, with or without modification, must only be used with a
- * Nordic Semiconductor ASA integrated circuit.
- *
- * 5. Any software provided in binary form under this license must not be reverse
- * engineered, decompiled, modified and/or disassembled.
- *
- * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
- #include "sdk_common.h"
- #if NRF_MODULE_ENABLED(NRF_CLI_CDC_ACM)
- #include "nrf_cli_cdc_acm.h"
- #include "nrf_queue.h"
- #include "app_error.h"
- #include "nrf_assert.h"
- #if APP_USBD_CONFIG_EVENT_QUEUE_ENABLE
- #error "Current CLI CDC implementation supports only USB with event queue disabled (see APP_USBD_CONFIG_EVENT_QUEUE_ENABLE)"
- #endif
- static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
- app_usbd_cdc_acm_user_event_t event);
- /*lint -save -e26 -e40 -e64 -e123 -e505 -e651*/
- /**
- * @brief CDC_ACM class instance.
- * */
- APP_USBD_CDC_ACM_GLOBAL_DEF(nrf_cli_cdc_acm,
- cdc_acm_user_ev_handler,
- NRF_CLI_CDC_ACM_COMM_INTERFACE,
- NRF_CLI_CDC_ACM_DATA_INTERFACE,
- NRF_CLI_CDC_ACM_COMM_EPIN,
- NRF_CLI_CDC_ACM_DATA_EPIN,
- NRF_CLI_CDC_ACM_DATA_EPOUT,
- APP_USBD_CDC_COMM_PROTOCOL_AT_V250
- );
- /*lint -restore*/
- NRF_QUEUE_DEF(uint8_t,
- m_rx_queue,
- 2*NRF_DRV_USBD_EPSIZE,
- NRF_QUEUE_MODE_OVERFLOW);
- static char m_rx_buffer[NRF_DRV_USBD_EPSIZE];
- static nrf_cli_cdc_acm_internal_t * mp_internal;
- /**
- * @brief Set new buffer and process any data if already present
- *
- * This is internal function.
- * The result of its execution is the library waiting for the event of the new data.
- * If there is already any data that was returned from the CDC internal buffer
- * it would be processed here.
- */
- static void cdc_acm_process_and_prepare_buffer(app_usbd_cdc_acm_t const * p_cdc_acm)
- {
- for (;;)
- {
- if (!nrf_queue_is_empty(&m_rx_queue))
- {
- mp_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_RX_RDY, mp_internal->p_cb->p_context);
- }
- ret_code_t ret = app_usbd_cdc_acm_read_any(&nrf_cli_cdc_acm,
- m_rx_buffer,
- sizeof(m_rx_buffer));
- if (ret == NRF_SUCCESS)
- {
- size_t size = app_usbd_cdc_acm_rx_size(p_cdc_acm);
- size_t qsize = nrf_queue_in(&m_rx_queue, m_rx_buffer, size);
- ASSERT(size == qsize);
- UNUSED_VARIABLE(qsize);
- }
- else if (ret == NRF_ERROR_IO_PENDING)
- {
- break;
- }
- else
- {
- APP_ERROR_CHECK(ret);
- break;
- }
- }
- }
- /**
- * @brief User event handler.
- * */
- static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
- app_usbd_cdc_acm_user_event_t event)
- {
- app_usbd_cdc_acm_t const * p_cdc_acm = app_usbd_cdc_acm_class_get(p_inst);
- switch (event)
- {
- case APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN:
- {
- /*Setup first transfer*/
- cdc_acm_process_and_prepare_buffer(p_cdc_acm);
- break;
- }
- case APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE:
- mp_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, mp_internal->p_cb->p_context);
- break;
- case APP_USBD_CDC_ACM_USER_EVT_TX_DONE:
- mp_internal->p_cb->handler(NRF_CLI_TRANSPORT_EVT_TX_RDY, mp_internal->p_cb->p_context);
- break;
- case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
- {
- /*Get amount of data transfered*/
- size_t size = app_usbd_cdc_acm_rx_size(p_cdc_acm);
- size_t qsize = nrf_queue_in(&m_rx_queue, m_rx_buffer, size);
- ASSERT(size == qsize);
- UNUSED_VARIABLE(qsize);
- /*Setup next transfer*/
- cdc_acm_process_and_prepare_buffer(p_cdc_acm);
- break;
- }
- default:
- break;
- }
- }
- static ret_code_t cli_cdc_acm_init(nrf_cli_transport_t const * p_transport,
- void const * p_config,
- nrf_cli_transport_handler_t evt_handler,
- void * p_context)
- {
- UNUSED_PARAMETER(p_config);
- nrf_cli_cdc_acm_internal_t * p_internal =
- CONTAINER_OF(p_transport, nrf_cli_cdc_acm_internal_t, transport);
- p_internal->p_cb->handler = evt_handler;
- p_internal->p_cb->p_context = p_context;
- mp_internal = p_internal;
- return NRF_SUCCESS;
- }
- static ret_code_t cli_cdc_acm_uninit(nrf_cli_transport_t const * p_transport)
- {
- UNUSED_PARAMETER(p_transport);
- return NRF_SUCCESS;
- }
- static ret_code_t cli_cdc_acm_enable(nrf_cli_transport_t const * p_transport,
- bool blocking)
- {
- UNUSED_PARAMETER(p_transport);
- if (blocking)
- {
- return NRF_ERROR_NOT_SUPPORTED;
- }
- else
- {
- return NRF_SUCCESS;
- }
- }
- static ret_code_t cli_cdc_acm_read(nrf_cli_transport_t const * p_transport,
- void * p_data,
- size_t length,
- size_t * p_cnt)
- {
- ASSERT(p_cnt);
- UNUSED_PARAMETER(p_transport);
- size_t size = nrf_queue_out(&m_rx_queue, p_data, length);
- *p_cnt = size;
- return NRF_SUCCESS;
- }
- static ret_code_t cli_cdc_acm_write(nrf_cli_transport_t const * p_transport,
- void const * p_data,
- size_t length,
- size_t * p_cnt)
- {
- ASSERT(p_cnt);
- UNUSED_PARAMETER(p_transport);
- ret_code_t ret;
- ret = app_usbd_cdc_acm_write(&nrf_cli_cdc_acm, p_data, length);
- if (ret == NRF_SUCCESS || ret == NRF_ERROR_INVALID_STATE)
- {
- *p_cnt = length;
- ret = NRF_SUCCESS;
- }
- else if (ret == NRF_ERROR_BUSY)
- {
- *p_cnt = 0;
- ret = NRF_SUCCESS;
- }
- else
- {
- /* Nothing to do */
- }
- return ret;
- }
- const nrf_cli_transport_api_t nrf_cli_cdc_acm_transport_api = {
- .init = cli_cdc_acm_init,
- .uninit = cli_cdc_acm_uninit,
- .enable = cli_cdc_acm_enable,
- .read = cli_cdc_acm_read,
- .write = cli_cdc_acm_write,
- };
- #endif // NRF_MODULE_ENABLED(NRF_CLI_CDC_ACM)
|