|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Native USB device-side composite-class layer implementation. More...
#include "ra8_usb_composite.h"#include <stdint.h>#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_log.h"#include "ra8_usb.h"Go to the source code of this file.
Data Structures | |
| struct | ra8_usb_composite_state_data_t |
| Singleton shadow state for the composite-class driver. More... | |
Functions | |
| static void | internal_clear_if_owners (void) |
| Reset every IF-ownership slot to "unowned". | |
| static ra8_err_t | internal_validate_class (const ra8_usb_composite_class_t *cl) |
| Validate caller-supplied class-layer record. | |
| static ra8_err_t | internal_check_collision (const ra8_usb_composite_class_t *cl) |
| Detect IF-range overlap with already-registered classes. | |
| static void | internal_mark_ownership (const ra8_usb_composite_class_t *cl, uint8_t class_index) |
| Mark each IF in a class's range as owned by class_index. | |
| static ra8_err_t | internal_lookup_class_for_if (uint8_t if_num, uint8_t *out_idx) |
| Find the registered class that owns interface if_num. | |
| static ra8_err_t | internal_handle_standard (const ra8_usb_setup_t *setup) |
| Handle a STANDARD chapter-9 request internally. | |
| static ra8_err_t | internal_route_class (const ra8_usb_setup_t *setup, uint8_t *out_idx) |
| Route a CLASS or VENDOR SETUP request to the registered class whose IF range covers setup->w_index. | |
| static ra8_err_t | internal_require_init (void) |
| Pre-init guard helper used by every public entry point that is not init itself. | |
| ra8_err_t | ra8_usb_composite_init (ra8_usb_speed_t speed) |
| Bring up the composite-class driver on a chosen USB controller. | |
| ra8_err_t | ra8_usb_composite_close (void) |
| Tear down the composite-class driver and release the controller. | |
| ra8_err_t | ra8_usb_composite_register_class (const ra8_usb_composite_class_t *class_layer) |
| Register a single class layer with the composite driver. | |
| ra8_err_t | ra8_usb_composite_set_descriptors (const uint8_t *device_desc, const uint8_t *config_desc) |
| Cache caller-owned device + configuration descriptor pointers. | |
| ra8_err_t | ra8_usb_composite_step (void) |
| Drive the composite dispatch state machine forward by one step. | |
| ra8_err_t | ra8_usb_composite_dispatch_setup (const ra8_usb_setup_t *setup, uint8_t *out_handler_class) |
| Inject a SETUP packet directly into the dispatch logic. | |
| ra8_err_t | ra8_usb_composite_get_class_count (uint8_t *out_count) |
| Read back the number of currently-registered class layers. | |
| ra8_err_t | ra8_usb_composite_get_device_descriptor (const uint8_t **out_desc) |
| Read back the cached device descriptor pointer. | |
| ra8_err_t | ra8_usb_composite_get_config_descriptor (const uint8_t **out_desc) |
| Read back the cached configuration descriptor pointer. | |
Variables | |
| static const char * | s_tag = "USBCOMP" |
| static ra8_usb_composite_state_data_t | s_state = {} |
Native USB device-side composite-class layer implementation.
Glues the device-mode bring-up paths in ra8_usb to a class-agnostic composite dispatcher so the EK-RA8D2 can present multiple USB function classes (CDC + HID + MSC + ...) over a single physical connection. This file is the native composite layer; FSP's r_usb_composite .template reference templates are inspiration only – no FSP source is pulled in verbatim.
Mapping vs FSP (FSP element -> our entry point):
Dispatch state machine – per SETUP:
IDLE -> SETUP_RX (8-byte SETUP arrived) -> classify by bmRequestType.type:
Reference: USB 2.0 spec sec 9.3 "USB Device Requests" + sec 9.4 "Standard Device Requests"; Interface Association Descriptor ECN (USB-IF, 2003-07-23) for the IAD type identifier (0x0B) used in composite configuration descriptors.
Definition in file ra8_usb_composite.c.
| enum ra8_usb_composite_address_limit_t : uint8_t |
USB address ceiling (USB 2.0 sec 9.4.6).
| Enumerator | |
|---|---|
| k_ra8_usb_composite_max_address | 7-bit USB address. |
Definition at line 132 of file ra8_usb_composite.c.
| enum ra8_usb_composite_handler_sentinel_t : uint8_t |
Marker the dispatch helper writes when the composite layer itself answered (no class fired).
Returned via out_handler_class when a STANDARD request is dispatched. Equals k_ra8_usb_composite_max_classes so a direct comparison with the registered-class index is unambiguous.
| Enumerator | |
|---|---|
| k_ra8_usb_composite_handler_self | RA8 USB composite handler self. |
Definition at line 145 of file ra8_usb_composite.c.
| enum ra8_usb_composite_recipient_t : uint8_t |
bmRequestType recipient-field values (USB 2.0 sec 9.3.1).
Definition at line 103 of file ra8_usb_composite.c.
| enum ra8_usb_composite_request_type_t : uint8_t |
bmRequestType type-field values (USB 2.0 sec 9.3.1).
Bits [6:5] of bmRequestType: 0 = STANDARD, 1 = CLASS, 2 = VENDOR. The composite layer answers STANDARD itself and routes CLASS / VENDOR via interface number.
Definition at line 92 of file ra8_usb_composite.c.
| enum ra8_usb_composite_state_t : uint8_t |
Composite dispatch state-machine phases.
Each SETUP packet transitions IDLE -> SETUP_RX -> (STD_DISPATCH | CLASS_DISPATCH) -> DONE -> IDLE. The starter pumps the machine one phase per ra8_usb_composite_step call.
Definition at line 76 of file ra8_usb_composite.c.
| enum ra8_usb_composite_std_request_t : uint8_t |
Standard bRequest codes the composite layer answers (USB 2.0 sec 9.4 Table 9-4).
Definition at line 115 of file ra8_usb_composite.c.
| enum usbc_mask_t : uint16_t |
Low-byte mask for the setup-packet wIndex.
| Enumerator | |
|---|---|
| k_usbc_byte_mask | Usbc byte mask. |
Definition at line 64 of file ra8_usb_composite.c.
|
static |
Detect IF-range overlap with already-registered classes.
Walks [first, first+count) and returns k_ra8_err_exists if any slot is already owned (i.e. nonzero in if_owner_plus_one). USB 2.0 sec 9.6.5 requires interface numbers to be unique within a configuration.
| [in] | cl | See implementation. |
| k_ra8_ok | Operation succeeded. |
Definition at line 258 of file ra8_usb_composite.c.
References ra8_usb_composite_class_t::interface_number_count, ra8_usb_composite_class_t::interface_number_first, k_ra8_err_exists, k_ra8_ok, and s_state.
Referenced by ra8_usb_composite_register_class().
|
static |
Reset every IF-ownership slot to "unowned".
A slot value of 0 means "no class owns this IF"; a slot value of class_index + 1 means class class_index owns it. The +1 bias keeps a single uint8_t array (no "magic" sentinel needed) and lets if_owner_plus_one[i] != 0 be the collision check.
Definition at line 196 of file ra8_usb_composite.c.
References k_ra8_usb_composite_max_ifs, and s_state.
Referenced by ra8_usb_composite_close(), and ra8_usb_composite_init().
|
static |
Handle a STANDARD chapter-9 request internally.
The starter answers SET_ADDRESS by forwarding the new address into USBADDR via ra8_usb_set_address; GET_DESCRIPTOR / SET_CONFIGURATION are accepted as no-ops on the dispatch path because the actual descriptor data is staged elsewhere by the caller's chapter-9 stack. Other standard requests are also accepted (no-op) so the dispatch state machine always advances. The starter never STALLs a standard request from this layer; class layers can still stall their own class-specific requests by returning a non-zero error from handle_setup.
| [in] | setup | See implementation. |
| k_ra8_ok | Operation succeeded. |
Definition at line 349 of file ra8_usb_composite.c.
References ra8_usb_setup_t::b_request, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_usb_composite_max_address, k_ra8_usb_composite_std_set_address, ra8_usb_set_address(), s_state, and ra8_usb_setup_t::w_value.
Referenced by ra8_usb_composite_dispatch_setup().
|
static |
Find the registered class that owns interface if_num.
Returns the class index in *out_idx and k_ra8_ok, or k_ra8_err_not_found if if_num is not in any registered range.
| [in] | if_num | See implementation. |
| [in] | out_idx | See implementation. |
| k_ra8_ok | Operation succeeded. |
Definition at line 311 of file ra8_usb_composite.c.
References k_ra8_err_not_found, k_ra8_ok, k_ra8_usb_composite_max_ifs, and s_state.
Referenced by internal_route_class().
|
static |
Mark each IF in a class's range as owned by class_index.
Stored as class_index + 1 so 0 retains "unowned" semantics. The class index is later recovered with slot - 1.
| [in] | cl | See implementation. |
| [in] | class_index | See implementation. |
Definition at line 285 of file ra8_usb_composite.c.
References ra8_usb_composite_class_t::interface_number_count, ra8_usb_composite_class_t::interface_number_first, and s_state.
Referenced by ra8_usb_composite_register_class().
|
inlinestatic |
Pre-init guard helper used by every public entry point that is not init itself.
See implementation.
| k_ra8_ok | Operation succeeded. |
Definition at line 416 of file ra8_usb_composite.c.
References k_ra8_err_invalid_state, k_ra8_ok, and s_state.
Referenced by ra8_usb_composite_dispatch_setup(), ra8_usb_composite_get_class_count(), ra8_usb_composite_get_config_descriptor(), ra8_usb_composite_get_device_descriptor(), ra8_usb_composite_register_class(), ra8_usb_composite_set_descriptors(), and ra8_usb_composite_step().
|
static |
Route a CLASS or VENDOR SETUP request to the registered class whose IF range covers setup->w_index.
wIndex carries the recipient interface number for interface-recipient class requests (USB 2.0 sec 9.3.4). The starter uses the low byte of wIndex as the IF number; the high byte (for endpoint requests, sec 9.4) is ignored here because the composite registry is keyed on interface number.
| [in] | setup | See implementation. |
| [in] | out_idx | See implementation. |
| k_ra8_ok | Operation succeeded. |
Definition at line 388 of file ra8_usb_composite.c.
References ra8_usb_composite_class_t::ctx, ra8_usb_composite_class_t::handle_setup, internal_lookup_class_for_if(), k_ra8_ok, k_usbc_byte_mask, s_state, and ra8_usb_setup_t::w_index.
Referenced by ra8_usb_composite_dispatch_setup().
|
static |
Validate caller-supplied class-layer record.
Per the public contract: all three callbacks must be non-NULL, interface_number_count >= 1, and the requested IF range must fit under k_ra8_usb_composite_max_ifs.
| [in] | cl | See implementation. |
| k_ra8_ok | Operation succeeded. |
Definition at line 221 of file ra8_usb_composite.c.
References ra8_usb_composite_class_t::close, ra8_usb_composite_class_t::handle_setup, ra8_usb_composite_class_t::init, ra8_usb_composite_class_t::interface_number_count, ra8_usb_composite_class_t::interface_number_first, k_ra8_err_invalid_arg, k_ra8_err_null_ptr, k_ra8_ok, and k_ra8_usb_composite_max_ifs.
Referenced by ra8_usb_composite_register_class().
|
nodiscard |
Tear down the composite-class driver and release the controller.
Walks the registered class table and invokes each class's close callback in reverse-registration order. Then drops the cached class table and calls ra8_usb_device_deinit.
| k_ra8_ok | Released. |
| k_ra8_err_invalid_state | Driver was never initialized. |
Definition at line 456 of file ra8_usb_composite.c.
References ra8_usb_composite_class_t::close, ra8_usb_composite_class_t::ctx, internal_clear_if_owners(), k_ra8_err_invalid_state, k_ra8_ok, ra8_log_error_val, ra8_usb_device_deinit(), s_state, and s_tag.
|
nodiscard |
Inject a SETUP packet directly into the dispatch logic.
Test / debug entry point. Production code receives SETUPs from the controller's USBREQ / USBVAL / USBINDX / USBLENG mirrors via ra8_usb_read_setup_if_valid; tests bypass the FIFO and feed an 8-byte decoded SETUP directly. Standard chapter-9 requests are answered internally; class / vendor requests are routed to the registered class whose IF range covers setup->w_index.
| [in] | setup | Pointer to the 8-byte decoded SETUP packet. |
| [out] | out_handler_class | On success, receives the index of the class that handled the request, or k_ra8_usb_composite_max_classes if the composite layer answered (i.e. standard request). |
| k_ra8_ok | SETUP dispatched. |
| k_ra8_err_invalid_state | Driver not initialized. |
| k_ra8_err_null_ptr | setup or out_handler_class was NULL. |
| k_ra8_err_not_found | Class request whose wIndex does not fall in any registered class's IF range. |
Definition at line 583 of file ra8_usb_composite.c.
References ra8_usb_setup_t::bm_request_type, internal_handle_standard(), internal_require_init(), internal_route_class(), k_ra8_err_not_found, k_ra8_ok, k_ra8_usb_composite_handler_self, k_ra8_usb_composite_req_type_mask, k_ra8_usb_composite_req_type_standard, RA8_CHECK_NULL_PTR, s_state, and s_tag.
|
nodiscard |
Read back the number of currently-registered class layers.
| [out] | out_count | Receives the registered class count. |
| k_ra8_ok | Count returned. |
| k_ra8_err_invalid_state | Driver not initialized. |
| k_ra8_err_null_ptr | out_count was NULL. |
Definition at line 614 of file ra8_usb_composite.c.
References internal_require_init(), k_ra8_ok, RA8_CHECK_NULL_PTR, s_state, and s_tag.
|
nodiscard |
Read back the cached configuration descriptor pointer.
| [out] | out_desc | Receives the cached configuration descriptor pointer (or NULL if set_descriptors never ran). |
| k_ra8_ok | Pointer returned. |
| k_ra8_err_invalid_state | Driver not initialized. |
| k_ra8_err_null_ptr | out_desc was NULL. |
Definition at line 636 of file ra8_usb_composite.c.
References internal_require_init(), k_ra8_ok, RA8_CHECK_NULL_PTR, s_state, and s_tag.
|
nodiscard |
Read back the cached device descriptor pointer.
| [out] | out_desc | Receives the cached device descriptor pointer (or NULL if set_descriptors never ran). |
| k_ra8_ok | Pointer returned. |
| k_ra8_err_invalid_state | Driver not initialized. |
| k_ra8_err_null_ptr | out_desc was NULL. |
Definition at line 625 of file ra8_usb_composite.c.
References internal_require_init(), k_ra8_ok, RA8_CHECK_NULL_PTR, s_state, and s_tag.
|
nodiscard |
Bring up the composite-class driver on a chosen USB controller.
Initialises the underlying ra8_usb driver in DEVICE mode for speed, zeroes the registered-class table, primes the dispatch state machine to IDLE, and clears the cached descriptor pointers. D+ pull-up is left off so the application can publish the configuration descriptor before the host enumerates it.
| [in] | speed | Which USB controller (FS or HS). |
| k_ra8_ok | Composite ready, awaiting register_class. |
| k_ra8_err_invalid_arg | speed out of range. |
| k_ra8_err_hw_init_failed | Underlying ra8_usb_device_init failed. |
Definition at line 429 of file ra8_usb_composite.c.
References internal_clear_if_owners(), k_ra8_err_hw_init_failed, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_usb_composite_handler_self, k_ra8_usb_composite_max_classes, k_ra8_usb_composite_state_idle, k_ra8_usb_speed_fs, k_ra8_usb_speed_hs, ra8_log_error_val, ra8_log_info_val, ra8_usb_device_init(), s_state, and s_tag.
|
nodiscard |
Register a single class layer with the composite driver.
Validates the supplied class-layer record:
On success the record is copied into internal state and the class's init callback is invoked. Composition order is the order of register_class calls.
| [in] | class_layer | Class-layer snapshot. Copied by value. |
| k_ra8_ok | Class registered, init invoked. |
| k_ra8_err_invalid_state | Driver not initialized. |
| k_ra8_err_null_ptr | class_layer was NULL or any of its callbacks was NULL. |
| k_ra8_err_invalid_arg | interface_number_count was 0 or the requested IF range overflows the IF ceiling. |
| k_ra8_err_exists | IF range overlaps a previously-registered class. |
| k_ra8_err_no_mem | Class table is full (already at k_ra8_usb_composite_max_classes). |
Definition at line 492 of file ra8_usb_composite.c.
References ra8_usb_composite_class_t::ctx, ra8_usb_composite_class_t::init, internal_check_collision(), internal_mark_ownership(), internal_require_init(), internal_validate_class(), k_ra8_err_no_mem, k_ra8_ok, k_ra8_usb_composite_max_classes, ra8_log_error_val, ra8_log_info_val, s_state, and s_tag.
|
nodiscard |
Cache caller-owned device + configuration descriptor pointers.
The composite layer does not allocate descriptors itself; the application builds them (typically as static const uint8_t[]) and passes pointers in. The device_desc is the 18-byte standard device descriptor (USB 2.0 sec 9.6.1); the config_desc is the variable- length composite configuration descriptor that includes one IAD per multi-interface class (USB IAD ECN sec 9.X).
| [in] | device_desc | Pointer to the device descriptor. |
| [in] | config_desc | Pointer to the configuration descriptor. |
| k_ra8_ok | Descriptors cached. |
| k_ra8_err_invalid_state | Driver not initialized. |
| k_ra8_err_null_ptr | Either pointer was NULL. |
Definition at line 532 of file ra8_usb_composite.c.
References internal_require_init(), k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_log_info, s_state, and s_tag.
|
nodiscard |
Drive the composite dispatch state machine forward by one step.
Production code calls this from the EP0 / control-transfer completion ISR. Each call advances the state machine by one phase:
| k_ra8_ok | Step advanced. |
| k_ra8_err_invalid_state | Driver not initialized. |
Definition at line 552 of file ra8_usb_composite.c.
References internal_require_init(), k_ra8_ok, k_ra8_usb_composite_state_class_dispatch, k_ra8_usb_composite_state_done, k_ra8_usb_composite_state_idle, k_ra8_usb_composite_state_setup_rx, k_ra8_usb_composite_state_std_dispatch, and s_state.
|
static |
Definition at line 173 of file ra8_usb_composite.c.
|
static |
Definition at line 56 of file ra8_usb_composite.c.