|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Native USB CDC ACM class layer implementation. More...
#include "ra8_usb_cdc.h"#include <stdint.h>#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_log.h"#include "ra8_usb.h"#include "ra8_usb_cdc_internal.h"Go to the source code of this file.
Data Structures | |
| struct | ra8_usb_cdc_state_t |
| Singleton shadow state for the CDC function. More... | |
Functions | |
| static void | internal_default_coding (ra8_usb_cdc_line_coding_t *coding) |
| Internal helper. | |
| static ra8_err_t | internal_configure_pipes (ra8_usb_speed_t speed) |
| Configure the three CDC pipes (bulk IN / OUT, intr IN). | |
| static void | internal_apply_line_coding (const uint8_t *data, uint16_t len) |
| Apply a host SET_LINE_CODING payload to the cached CDC line coding. | |
| void | ra8_usb_cdc_test_apply_line_coding (const uint8_t *data, uint16_t len) |
| Drive the private SET_LINE_CODING decoder from host tests. | |
| ra8_err_t | ra8_usb_cdc_init (ra8_usb_speed_t speed) |
| Bring up the CDC ACM function on a chosen USB controller. | |
| ra8_err_t | ra8_usb_cdc_deinit (void) |
| Tear down the CDC function and release the underlying controller. | |
| ra8_err_t | ra8_usb_cdc_attach (bool attached) |
| Raise / drop the D+ pull-up to advertise the CDC function. | |
| ra8_err_t | ra8_usb_cdc_send (const uint8_t *data, uint16_t len) |
| Send a chunk of bytes IN (device -> host). | |
| ra8_err_t | ra8_usb_cdc_recv (uint8_t *out_buf, uint16_t *inout_len) |
| Drain a chunk of bytes OUT (host -> device). | |
| static ra8_err_t | internal_pull_data_stage (uint8_t *buf, uint16_t cap, uint16_t *out_len) |
| Pull the SET_LINE_CODING data stage off EP0 (DCP) once it lands. | |
| static ra8_err_t | internal_dispatch_class_setup (const ra8_usb_setup_t *setup) |
| Decode a CDC class-specific SETUP packet body. | |
| ra8_err_t | ra8_usb_cdc_handle_setup (const ra8_usb_setup_t *setup) |
| Process a class-specific SETUP packet. | |
| ra8_err_t | ra8_usb_cdc_get_line_coding (ra8_usb_cdc_line_coding_t *out) |
| Get the most recently negotiated line coding. | |
| ra8_err_t | ra8_usb_cdc_get_line_state (bool *out_dtr, bool *out_rts) |
| Get the most recently received DTR / RTS bits. | |
Variables | |
| static const char * | s_tag = "USBCDC" |
| static ra8_usb_cdc_state_t | s_state = {} |
Native USB CDC ACM class layer implementation.
Glues the device-mode ra8_usb driver to a CDC ACM endpoint set so the host enumerates the board as /dev/ttyACM* (Linux / macOS) or COMn (Windows). Class-specific SETUP requests (SET_LINE_CODING / GET_LINE_CODING / SET_CONTROL_LINE_STATE) are answered locally; the CDC standard descriptors live in the caller's stack so this file does not own VID / PID.
The implementation is from-scratch – there is no FSP r_usb_pcdc source pulled in. Behaviourally it tracks the small subset that the CDC PSTN spec rev 1.20 makes mandatory for an ACM device:
Definition in file ra8_usb_cdc.c.
| enum ra8_usb_cdc_byte_idx_t : uint8_t |
Indices into the 7-byte SET_LINE_CODING payload.
Definition at line 99 of file ra8_usb_cdc.c.
| enum ra8_usb_cdc_byte_shift_t : uint8_t |
Per-byte left-shift constants for the little-endian baud accumulator in internal_apply_line_coding.
| Enumerator | |
|---|---|
| k_ra8_cdc_shift_byte0 | RA8 cdc shift byte0. |
| k_ra8_cdc_shift_byte1 | RA8 cdc shift byte1. |
| k_ra8_cdc_shift_byte2 | RA8 cdc shift byte2. |
| k_ra8_cdc_shift_byte3 | RA8 cdc shift byte3. |
Definition at line 88 of file ra8_usb_cdc.c.
| enum ra8_usb_cdc_data_stage_t : uint16_t |
Bound on the polled control-OUT data-stage drain.
This layer is polled throughout (ra8_usb_cdc_recv drives the bulk pipe the same way), so the SET_LINE_CODING data stage is drained by a bounded poll rather than an ISR callback. The bound exists so the SETUP path can never spin: the RA8 SIE ACKs the host's OUT packet into the DCP bank as soon as ra8_usb_dcp_out_arm sets PID = BUF, so the packet lands within a few bus microframes or the host has abandoned the transfer. Exhausting the bound is not an error path for the caller – the request is still ACKed, exactly as it was before the data stage was captured at all.
| Enumerator | |
|---|---|
| k_ra8_cdc_data_stage_polls | Max ra8_usb_dcp_out_read attempts. |
Definition at line 71 of file ra8_usb_cdc.c.
| enum ra8_usb_cdc_default_baud_t : uint32_t |
9600 baud assembled from the two low bytes above.
| Enumerator | |
|---|---|
| k_ra8_cdc_default_baud | RA8 cdc default baud. |
Definition at line 79 of file ra8_usb_cdc.c.
| enum ra8_usb_cdc_setup_field_t : uint8_t |
Constants used to decode CDC class-specific SETUPs.
Definition at line 45 of file ra8_usb_cdc.c.
|
static |
Apply a host SET_LINE_CODING payload to the cached CDC line coding.
Decodes the little-endian seven-byte USB CDC PSTN line-coding structure. The 32-bit DTE baud rate is assembled from bytes zero through three, followed by the character-format, parity-type, and data-bit fields. A null pointer or a short payload leaves the cached coding untouched.
| [in] | data | Pointer to the line-coding payload in host byte order; may be null to exercise the reject path. |
| [in] | len | Length of data in bytes. |
data is non-null, it references at least len readable bytes. Definition at line 225 of file ra8_usb_cdc.c.
References k_ra8_cdc_idx_baud_b0, k_ra8_cdc_idx_baud_b1, k_ra8_cdc_idx_baud_b2, k_ra8_cdc_idx_baud_b3, k_ra8_cdc_idx_char_format, k_ra8_cdc_idx_data_bits, k_ra8_cdc_idx_parity_type, k_ra8_cdc_line_coding_len, k_ra8_cdc_shift_byte1, k_ra8_cdc_shift_byte2, k_ra8_cdc_shift_byte3, and s_state.
Referenced by internal_dispatch_class_setup(), and ra8_usb_cdc_test_apply_line_coding().
|
static |
Configure the three CDC pipes (bulk IN / OUT, intr IN).
See implementation.
| [in] | speed | See implementation. |
| k_ra8_ok | Operation succeeded. |
Definition at line 163 of file ra8_usb_cdc.c.
References k_ra8_cdc_bulk_max_packet_fs, k_ra8_cdc_bulk_max_packet_hs, k_ra8_cdc_ep_bulk_in_addr, k_ra8_cdc_ep_bulk_out_addr, k_ra8_cdc_ep_intr_in_addr, k_ra8_cdc_intr_max_packet, k_ra8_cdc_pipe_bulk_in, k_ra8_cdc_pipe_bulk_out, k_ra8_cdc_pipe_intr_in, k_ra8_usb_ep_dir_in, k_ra8_usb_ep_dir_out, k_ra8_usb_ep_type_bulk, k_ra8_usb_ep_type_intr, k_ra8_usb_speed_hs, RA8_RETURN_ON_ERROR, ra8_usb_configure_endpoint(), and s_tag.
|
static |
Internal helper.
See implementation.
| [in] | coding | See implementation. |
Definition at line 140 of file ra8_usb_cdc.c.
References ra8_usb_cdc_line_coding_t::char_format, ra8_usb_cdc_line_coding_t::data_bits, ra8_usb_cdc_line_coding_t::dte_rate, k_ra8_cdc_default_baud, k_ra8_cdc_default_data_bits, k_ra8_cdc_default_parity_none, k_ra8_cdc_default_stop_bits, and ra8_usb_cdc_line_coding_t::parity_type.
Referenced by ra8_usb_cdc_init().
|
static |
Decode a CDC class-specific SETUP packet body.
See implementation.
| [in] | setup | See implementation. |
| k_ra8_ok | Operation succeeded. |
Definition at line 414 of file ra8_usb_cdc.c.
References ra8_usb_setup_t::b_request, internal_apply_line_coding(), internal_pull_data_stage(), k_ra8_cdc_line_coding_len, k_ra8_cdc_line_state_dtr, k_ra8_cdc_line_state_rts, k_ra8_cdc_req_get_line_coding, k_ra8_cdc_req_set_control_line_state, k_ra8_cdc_req_set_line_coding, k_ra8_err_not_supported, k_ra8_ok, ra8_usb_control_response(), s_state, and ra8_usb_setup_t::w_value.
Referenced by ra8_usb_cdc_handle_setup().
|
static |
Pull the SET_LINE_CODING data stage off EP0 (DCP) once it lands.
Drives the two-step control-OUT receive the device driver exposes: ra8_usb_dcp_out_arm sets DCPCTR.PID = BUF so the SIE ACKs the host's OUT token into the DCP bank, then ra8_usb_dcp_out_read drains that bank. The read reports k_ra8_err_no_data until the packet actually lands, so this polls it up to k_ra8_cdc_data_stage_polls times – matching the polled style of the rest of this layer (ra8_usb_cdc_recv drives the bulk-OUT pipe the same way) rather than requiring the caller to own a BRDY interrupt.
The bound is fail-soft by design: if the payload never arrives, the caller simply leaves the cached line coding untouched and still ACKs the status stage, which is exactly what the layer did before the data stage was captured. A host that does complete the transfer now has its baud rate, framing and parity recorded and visible through ra8_usb_cdc_get_line_coding.
| [out] | buf | Destination for the payload; must hold cap bytes. |
| [in] | cap | Capacity of buf in bytes. |
| [out] | out_len | Receives the host's payload length in bytes. |
| k_ra8_ok | A packet was drained; *out_len is its length. |
| k_ra8_err_null_ptr | buf or out_len is NULL. |
| k_ra8_err_invalid_arg | cap is zero. |
| k_ra8_err_no_data | The payload did not land within the poll bound. |
| other | Propagated from the arm / read pair. |
buf. Definition at line 375 of file ra8_usb_cdc.c.
References internal_pull_data_stage(), k_ra8_cdc_data_stage_polls, k_ra8_err_invalid_arg, k_ra8_err_no_data, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_usb_dcp_out_arm(), ra8_usb_dcp_out_read(), s_state, and s_tag.
Referenced by internal_dispatch_class_setup(), and internal_pull_data_stage().
|
nodiscard |
Raise / drop the D+ pull-up to advertise the CDC function.
| [in] | attached | true to attach, false to detach. |
| k_ra8_ok | State updated. |
| k_ra8_err_invalid_state | CDC not initialized. |
Definition at line 290 of file ra8_usb_cdc.c.
References k_ra8_err_invalid_state, ra8_usb_device_attach(), and s_state.
|
nodiscard |
Tear down the CDC function and release the underlying controller.
| k_ra8_ok | Released. |
| k_ra8_err_invalid_state | CDC was never initialized. |
Definition at line 277 of file ra8_usb_cdc.c.
References k_ra8_err_invalid_state, ra8_usb_device_attach(), ra8_usb_device_deinit(), and s_state.
|
nodiscard |
Get the most recently negotiated line coding.
| [out] | out | Receives the 7-byte coding payload. |
| k_ra8_ok | Copied. |
| k_ra8_err_invalid_arg | out was NULL. |
| k_ra8_err_invalid_state | CDC not initialized. |
Definition at line 457 of file ra8_usb_cdc.c.
References k_ra8_err_invalid_state, k_ra8_ok, RA8_CHECK_NULL_PTR, s_state, and s_tag.
|
nodiscard |
Get the most recently received DTR / RTS bits.
| [out] | out_dtr | true if DTR asserted. |
| [out] | out_rts | true if RTS asserted. |
| k_ra8_ok | State copied. |
| k_ra8_err_invalid_arg | out_dtr / out_rts were NULL. |
| k_ra8_err_invalid_state | CDC not initialized. |
Definition at line 467 of file ra8_usb_cdc.c.
References k_ra8_err_invalid_state, k_ra8_ok, RA8_CHECK_NULL_PTR, s_state, and s_tag.
|
nodiscard |
Process a class-specific SETUP packet.
Switches on b_request and either updates the stored line coding, returns the line coding payload, or stores the DTR / RTS bits. Standard (non-class) SETUPs are rejected with k_ra8_err_not_supported so the caller can fall back to its own standard-request handler.
| [in] | setup | The SETUP packet returned by ra8_usb_read_setup_if_valid. |
| k_ra8_ok | SETUP handled (status stage queued internally). |
| k_ra8_err_invalid_state | CDC not initialized. |
| k_ra8_err_invalid_arg | setup was NULL. |
| k_ra8_err_not_supported | bRequest is not a CDC ACM request this layer cares about. |
Definition at line 444 of file ra8_usb_cdc.c.
References ra8_usb_setup_t::bm_request_type, internal_dispatch_class_setup(), k_ra8_cdc_bm_class_recip_iface, k_ra8_cdc_bm_class_recip_in, k_ra8_err_invalid_state, k_ra8_err_not_supported, RA8_CHECK_NULL_PTR, s_state, and s_tag.
|
nodiscard |
Bring up the CDC ACM function on a chosen USB controller.
Initialises the underlying ra8_usb driver for speed, configures PIPE1 (bulk IN), PIPE2 (bulk OUT), PIPE6 (interrupt IN), seeds a default 9600/8/N/1 line coding, and stores DTR/RTS = 0. The D+ pull-up stays down – the caller raises it via ra8_usb_cdc_attach once it is ready to enumerate.
| [in] | speed | Which USB controller (FS or HS). |
| k_ra8_ok | CDC function ready. |
| k_ra8_err_invalid_arg | speed out of range. |
| k_ra8_err_hw_init_failed | Underlying ra8_usb_device_init failed. |
Definition at line 251 of file ra8_usb_cdc.c.
References internal_configure_pipes(), internal_default_coding(), k_ra8_err_hw_init_failed, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_usb_speed_fs, k_ra8_usb_speed_hs, ra8_log_error_val, ra8_log_info, ra8_usb_device_deinit(), ra8_usb_device_init(), s_state, and s_tag.
|
nodiscard |
Drain a chunk of bytes OUT (host -> device).
| [out] | out_buf | Destination buffer. |
| [in,out] | inout_len | On entry: capacity. On exit: bytes received. |
| k_ra8_ok | Bytes received. |
| k_ra8_err_no_data | Pipe was empty. |
| k_ra8_err_invalid_state | CDC not initialized. |
| k_ra8_err_invalid_arg | Bad pointers / capacity. |
Definition at line 314 of file ra8_usb_cdc.c.
References k_ra8_cdc_pipe_bulk_out, k_ra8_err_invalid_arg, k_ra8_err_invalid_state, RA8_CHECK_NULL_PTR, ra8_usb_queue_out(), s_state, and s_tag.
|
nodiscard |
Send a chunk of bytes IN (device -> host).
| [in] | data | Buffer to send. |
| [in] | len | Byte count, 0..bulk_max_packet of the speed. |
| k_ra8_ok | Transfer queued. |
| k_ra8_err_invalid_state | CDC not initialized. |
| k_ra8_err_invalid_arg | Bad data / len. |
Definition at line 303 of file ra8_usb_cdc.c.
References k_ra8_cdc_pipe_bulk_in, k_ra8_err_invalid_arg, k_ra8_err_invalid_state, ra8_usb_queue_in(), and s_state.
| void ra8_usb_cdc_test_apply_line_coding | ( | const uint8_t * | data, |
| uint16_t | len ) |
Drive the private SET_LINE_CODING decoder from host tests.
Forwards the caller-owned payload to the same private decoder used by the CDC SETUP handler. This is a test-access seam only; production code continues to call the private helper directly.
| [in] | data | Pointer to the line-coding payload in host byte order; may be null to exercise the reject path. |
| [in] | len | Length of data in bytes. |
data is non-null, it references at least len readable bytes. Definition at line 241 of file ra8_usb_cdc.c.
References internal_apply_line_coding().
|
static |
Definition at line 121 of file ra8_usb_cdc.c.
|
static |
Definition at line 39 of file ra8_usb_cdc.c.