This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Any updates for USBD CDC ACM?

Is there a place to make suggestions for new releases of nRF5 SDK's or even contribute?

I've been using the current USBD CDC ACM library and needed to modify the app_usbd_cdc_acm.h and app_usbd_cdc_acm.c files to add support for SET_LINE_CODING class requests to create events in the cdc_acm_user_ev_handler. From the event I can extract the data rate, stop bits, parity and data bits requested from the host exactly when it occurs and update a UART module or make a copy of the data that can be processed in main later (in main is a must for my application); instead of polling the m_app_cdc_acm instance (m_app_cdc_acm.specific.p_data->ctx.line_coding) for changes in main, which would be unsafe. It appears the data is only stored in the m_app_cdc_acm instance to respond to GET_LINE_CODING requests.

The SET_LINE_CODING request's data is needed for USB to UART bridges and should be easily accessible in a finished CDC ACM library, are there any updates on the horizon?

Would be nice to get CONTROL_LINE_STATE class requests to generate user events also, or even the individual events for changes to DTR and RTS (I realise APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN is DTR).

I can't see any of these features, let me know if they already exist and I'm blind or there is a better way to go about this?

Cheers, John.

Example of changes to setup_req_class_out in app_usbd_cdc_acm.c:

static ret_code_t setup_req_class_out(app_usbd_class_inst_t const * p_inst,
                                      app_usbd_setup_evt_t const *  p_setup_ev)
{
    app_usbd_cdc_acm_t const * p_cdc_acm = cdc_acm_get(p_inst);
    app_usbd_cdc_acm_ctx_t *   p_cdc_acm_ctx = cdc_acm_ctx_get(p_cdc_acm);

    switch (p_setup_ev->setup.bmRequest)
    {
        case APP_USBD_CDC_REQ_SET_LINE_CODING:
        {
            if (p_setup_ev->setup.wLength.w != sizeof(app_usbd_cdc_line_coding_t))
            {
                return NRF_ERROR_NOT_SUPPORTED;
            }

            // Modification
            ret_code_t ret = cdc_acm_req_out_datastage(p_inst, p_setup_ev);

            const app_usbd_cdc_acm_user_event_t ev = APP_USBD_CDC_ACM_USER_EVT_SET_LINE_CODING;
            user_event_handler(p_inst, ev);

            return ret;
            
            // Uncomment below for original
            //return cdc_acm_req_out_datastage(p_inst, p_setup_ev);

            // END
        }
        case APP_USBD_CDC_REQ_SET_CONTROL_LINE_STATE:
        {
            if (p_setup_ev->setup.wLength.w != 0)
            {
                return NRF_ERROR_NOT_SUPPORTED;
            }

            NRF_LOG_INFO("REQ_SET_CONTROL_LINE_STATE: 0x%x", p_setup_ev->setup.wValue.w);

            bool old_dtr = (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR) ?
                            true : false;
            p_cdc_acm_ctx->line_state = p_setup_ev->setup.wValue.w;

            bool new_dtr = (p_cdc_acm_ctx->line_state & APP_USBD_CDC_ACM_LINE_STATE_DTR) ?
                            true : false;

            if (old_dtr == new_dtr)
            {
                return NRF_SUCCESS;
            }

            const app_usbd_cdc_acm_user_event_t ev = new_dtr ?
                  APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN : APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE;

            user_event_handler(p_inst, ev);

            if (!new_dtr)
            {
                /*Abort DATA endpoints on port close */
                nrf_drv_usbd_ep_t ep;
                ep = data_ep_in_addr_get(p_inst);
                nrf_drv_usbd_ep_abort(ep);
                ep = data_ep_out_addr_get(p_inst);
                nrf_drv_usbd_ep_abort(ep);

                // Set rx transfers configuration to default state.
                p_cdc_acm_ctx->rx_transfer[0].p_buf = NULL;
                p_cdc_acm_ctx->rx_transfer[1].p_buf = NULL;
                p_cdc_acm_ctx->bytes_left = 0;
                p_cdc_acm_ctx->bytes_read = 0;
                p_cdc_acm_ctx->last_read  = 0;
                p_cdc_acm_ctx->cur_read   = 0;
                p_cdc_acm_ctx->p_copy_pos = p_cdc_acm_ctx->internal_rx_buf;
            }

            return NRF_SUCCESS;
        }
        default:
            break;
    }

    return NRF_ERROR_NOT_SUPPORTED;
}

Example of changes to app_usbd_cdc_acm_user_event_t in app_usbd_cdc_acm.h:

typedef enum app_usbd_cdc_acm_user_event_e {
    APP_USBD_CDC_ACM_USER_EVT_RX_DONE,     /**< User event RX_DONE.    */
    APP_USBD_CDC_ACM_USER_EVT_TX_DONE,     /**< User event TX_DONE.    */

    APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN,   /**< User event PORT_OPEN.  */
    APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE,  /**< User event PORT_CLOSE. */
    // Modification
    APP_USBD_CDC_ACM_USER_EVT_SET_LINE_CODING
    // END
} app_usbd_cdc_acm_user_event_t;
Parents Reply Children
No Data
Related