ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_usb_composite.c File Reference

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"
Include dependency graph for ra8_usb_composite.c:

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...

Enumerations

enum  usbc_mask_t : uint16_t { k_usbc_byte_mask = 0xFFU }
 Low-byte mask for the setup-packet wIndex. More...
enum  ra8_usb_composite_state_t : uint8_t {
  k_ra8_usb_composite_state_idle = 0U ,
  k_ra8_usb_composite_state_setup_rx = 1U ,
  k_ra8_usb_composite_state_std_dispatch = 2U ,
  k_ra8_usb_composite_state_class_dispatch = 3U ,
  k_ra8_usb_composite_state_done = 4U
}
 Composite dispatch state-machine phases. More...
enum  ra8_usb_composite_request_type_t : uint8_t {
  k_ra8_usb_composite_req_type_mask = 0x60U ,
  k_ra8_usb_composite_req_type_standard = 0x00U ,
  k_ra8_usb_composite_req_type_class = 0x20U ,
  k_ra8_usb_composite_req_type_vendor = 0x40U
}
 bmRequestType type-field values (USB 2.0 sec 9.3.1). More...
enum  ra8_usb_composite_recipient_t : uint8_t {
  k_ra8_usb_composite_recipient_mask = 0x1FU ,
  k_ra8_usb_composite_recipient_device = 0x00U ,
  k_ra8_usb_composite_recipient_interface = 0x01U ,
  k_ra8_usb_composite_recipient_endpoint = 0x02U
}
 bmRequestType recipient-field values (USB 2.0 sec 9.3.1). More...
enum  ra8_usb_composite_std_request_t : uint8_t {
  k_ra8_usb_composite_std_get_status = 0x00U ,
  k_ra8_usb_composite_std_clear_feature = 0x01U ,
  k_ra8_usb_composite_std_set_feature = 0x03U ,
  k_ra8_usb_composite_std_set_address = 0x05U ,
  k_ra8_usb_composite_std_get_descriptor = 0x06U ,
  k_ra8_usb_composite_std_set_descriptor = 0x07U ,
  k_ra8_usb_composite_std_get_configuration = 0x08U ,
  k_ra8_usb_composite_std_set_configuration = 0x09U ,
  k_ra8_usb_composite_std_get_interface = 0x0AU ,
  k_ra8_usb_composite_std_set_interface = 0x0BU
}
 Standard bRequest codes the composite layer answers (USB 2.0 sec 9.4 Table 9-4). More...
enum  ra8_usb_composite_address_limit_t : uint8_t { k_ra8_usb_composite_max_address = 127U }
 USB address ceiling (USB 2.0 sec 9.4.6). More...
enum  ra8_usb_composite_handler_sentinel_t : uint8_t { k_ra8_usb_composite_handler_self }
 Marker the dispatch helper writes when the composite layer itself answered (no class fired). 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 = {}

Detailed Description

Native USB device-side composite-class layer implementation.

Tag
[Ring 3 / HAL] {World: NS}

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:

  • type == STANDARD -> STD_DISPATCH (composite layer answers).
  • type == CLASS -> CLASS_DISPATCH (route on wIndex to the registered class layer that owns that interface number). ... -> DONE -> IDLE.

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.

Enumeration Type Documentation

◆ ra8_usb_composite_address_limit_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.

◆ ra8_usb_composite_handler_sentinel_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.

◆ ra8_usb_composite_recipient_t

bmRequestType recipient-field values (USB 2.0 sec 9.3.1).

Enumerator
k_ra8_usb_composite_recipient_mask 

Mask for recipient.

k_ra8_usb_composite_recipient_device 

Device recipient.

k_ra8_usb_composite_recipient_interface 

Interface recipient.

k_ra8_usb_composite_recipient_endpoint 

Endpoint recipient.

Definition at line 103 of file ra8_usb_composite.c.

◆ ra8_usb_composite_request_type_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.

Enumerator
k_ra8_usb_composite_req_type_mask 

Mask for type field.

k_ra8_usb_composite_req_type_standard 

STANDARD request.

k_ra8_usb_composite_req_type_class 

CLASS request.

k_ra8_usb_composite_req_type_vendor 

VENDOR request.

Definition at line 92 of file ra8_usb_composite.c.

◆ ra8_usb_composite_state_t

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.

Enumerator
k_ra8_usb_composite_state_idle 

No SETUP in flight.

k_ra8_usb_composite_state_setup_rx 

SETUP arrived.

k_ra8_usb_composite_state_std_dispatch 

Standard request handler.

k_ra8_usb_composite_state_class_dispatch 

Class-routed dispatch.

k_ra8_usb_composite_state_done 

Reply staged.

Definition at line 76 of file ra8_usb_composite.c.

◆ ra8_usb_composite_std_request_t

Standard bRequest codes the composite layer answers (USB 2.0 sec 9.4 Table 9-4).

Enumerator
k_ra8_usb_composite_std_get_status 

GET_STATUS.

k_ra8_usb_composite_std_clear_feature 

CLEAR_FEATURE.

k_ra8_usb_composite_std_set_feature 

SET_FEATURE.

k_ra8_usb_composite_std_set_address 

SET_ADDRESS.

k_ra8_usb_composite_std_get_descriptor 

GET_DESCRIPTOR.

k_ra8_usb_composite_std_set_descriptor 

SET_DESCRIPTOR.

k_ra8_usb_composite_std_get_configuration 

GET_CONFIGURATION.

k_ra8_usb_composite_std_set_configuration 

SET_CONFIGURATION.

k_ra8_usb_composite_std_get_interface 

GET_INTERFACE.

k_ra8_usb_composite_std_set_interface 

SET_INTERFACE.

Definition at line 115 of file ra8_usb_composite.c.

◆ usbc_mask_t

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.

Function Documentation

◆ internal_check_collision()

ra8_err_t internal_check_collision ( const ra8_usb_composite_class_t * cl)
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.

Parameters
[in]clSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

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().

◆ internal_clear_if_owners()

void internal_clear_if_owners ( void )
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.

Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

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().

◆ internal_handle_standard()

ra8_err_t internal_handle_standard ( const ra8_usb_setup_t * setup)
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.

Returns
k_ra8_ok on success.
Parameters
[in]setupSee implementation.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

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().

◆ internal_lookup_class_for_if()

ra8_err_t internal_lookup_class_for_if ( uint8_t if_num,
uint8_t * out_idx )
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.

Parameters
[in]if_numSee implementation.
[in]out_idxSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

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().

◆ internal_mark_ownership()

void internal_mark_ownership ( const ra8_usb_composite_class_t * cl,
uint8_t class_index )
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.

Parameters
[in]clSee implementation.
[in]class_indexSee implementation.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

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().

◆ internal_require_init()

ra8_err_t internal_require_init ( void )
inlinestatic

Pre-init guard helper used by every public entry point that is not init itself.

See implementation.

Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

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().

◆ internal_route_class()

ra8_err_t internal_route_class ( const ra8_usb_setup_t * setup,
uint8_t * out_idx )
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.

Parameters
[in]setupSee implementation.
[in]out_idxSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

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().

◆ internal_validate_class()

ra8_err_t internal_validate_class ( const ra8_usb_composite_class_t * cl)
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.

Parameters
[in]clSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

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().

◆ ra8_usb_composite_close()

ra8_err_t ra8_usb_composite_close ( void )
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.

Returns
ra8_err_t error code.
Return values
k_ra8_okReleased.
k_ra8_err_invalid_stateDriver was never initialized.
Precondition
Single-threaded shutdown context.
Postcondition
ra8_usb_device_deinit ran; subsequent composite API calls return k_ra8_err_invalid_state.
Note
Not thread-safe.
Since
0.1.0

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.

◆ ra8_usb_composite_dispatch_setup()

ra8_err_t ra8_usb_composite_dispatch_setup ( const ra8_usb_setup_t * setup,
uint8_t * out_handler_class )
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.

Parameters
[in]setupPointer to the 8-byte decoded SETUP packet.
[out]out_handler_classOn 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).
Returns
ra8_err_t error code.
Return values
k_ra8_okSETUP dispatched.
k_ra8_err_invalid_stateDriver not initialized.
k_ra8_err_null_ptrsetup or out_handler_class was NULL.
k_ra8_err_not_foundClass request whose wIndex does not fall in any registered class's IF range.
Precondition
Both pointers non-NULL.
Postcondition
On k_ra8_ok for a class request, the matching class's handle_setup callback was invoked exactly once.
Note
Not thread-safe.
Since
0.1.0

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.

◆ ra8_usb_composite_get_class_count()

ra8_err_t ra8_usb_composite_get_class_count ( uint8_t * out_count)
nodiscard

Read back the number of currently-registered class layers.

Parameters
[out]out_countReceives the registered class count.
Returns
ra8_err_t error code.
Return values
k_ra8_okCount returned.
k_ra8_err_invalid_stateDriver not initialized.
k_ra8_err_null_ptrout_count was NULL.
Precondition
out_count non-NULL.
Postcondition
No state mutated.
Note
Not thread-safe.
Since
0.1.0

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.

◆ ra8_usb_composite_get_config_descriptor()

ra8_err_t ra8_usb_composite_get_config_descriptor ( const uint8_t ** out_desc)
nodiscard

Read back the cached configuration descriptor pointer.

Parameters
[out]out_descReceives the cached configuration descriptor pointer (or NULL if set_descriptors never ran).
Returns
ra8_err_t error code.
Return values
k_ra8_okPointer returned.
k_ra8_err_invalid_stateDriver not initialized.
k_ra8_err_null_ptrout_desc was NULL.
Precondition
out_desc non-NULL.
Postcondition
No state mutated.
Note
Not thread-safe.
Since
0.1.0

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.

◆ ra8_usb_composite_get_device_descriptor()

ra8_err_t ra8_usb_composite_get_device_descriptor ( const uint8_t ** out_desc)
nodiscard

Read back the cached device descriptor pointer.

Parameters
[out]out_descReceives the cached device descriptor pointer (or NULL if set_descriptors never ran).
Returns
ra8_err_t error code.
Return values
k_ra8_okPointer returned.
k_ra8_err_invalid_stateDriver not initialized.
k_ra8_err_null_ptrout_desc was NULL.
Precondition
out_desc non-NULL.
Postcondition
No state mutated.
Note
Not thread-safe.
Since
0.1.0

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.

◆ ra8_usb_composite_init()

ra8_err_t ra8_usb_composite_init ( ra8_usb_speed_t speed)
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.

Parameters
[in]speedWhich USB controller (FS or HS).
Returns
ra8_err_t error code.
Return values
k_ra8_okComposite ready, awaiting register_class.
k_ra8_err_invalid_argspeed out of range.
k_ra8_err_hw_init_failedUnderlying ra8_usb_device_init failed.
Precondition
Single-threaded init context.
ra8_mstp_init and ra8_pwr_init already ran.
Postcondition
ra8_usb_device_init succeeded for speed.
Internal class registry empty; descriptors NULL.
Note
Not thread-safe.
See also
ra8_usb_composite_register_class
ra8_usb_composite_set_descriptors
ra8_usb_composite_close
Since
0.1.0

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.

◆ ra8_usb_composite_register_class()

ra8_err_t ra8_usb_composite_register_class ( const ra8_usb_composite_class_t * class_layer)
nodiscard

Register a single class layer with the composite driver.

Validates the supplied class-layer record:

  • All three function pointers (init, handle_setup, close) must be non-NULL.
  • interface_number_count must be >= 1.
  • interface_number_first + interface_number_count must not exceed k_ra8_usb_composite_max_ifs.
  • The [first, first+count) IF range must not overlap any previously-registered class's range (collision detection).

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.

Parameters
[in]class_layerClass-layer snapshot. Copied by value.
Returns
ra8_err_t error code.
Return values
k_ra8_okClass registered, init invoked.
k_ra8_err_invalid_stateDriver not initialized.
k_ra8_err_null_ptrclass_layer was NULL or any of its callbacks was NULL.
k_ra8_err_invalid_arginterface_number_count was 0 or the requested IF range overflows the IF ceiling.
k_ra8_err_existsIF range overlaps a previously-registered class.
k_ra8_err_no_memClass table is full (already at k_ra8_usb_composite_max_classes).
Precondition
ra8_usb_composite_init has run.
All three callbacks non-NULL.
Postcondition
Class slot count incremented; class's init callback invoked.
Note
Not thread-safe.
Since
0.1.0

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.

◆ ra8_usb_composite_set_descriptors()

ra8_err_t ra8_usb_composite_set_descriptors ( const uint8_t * device_desc,
const uint8_t * config_desc )
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).

Parameters
[in]device_descPointer to the device descriptor.
[in]config_descPointer to the configuration descriptor.
Returns
ra8_err_t error code.
Return values
k_ra8_okDescriptors cached.
k_ra8_err_invalid_stateDriver not initialized.
k_ra8_err_null_ptrEither pointer was NULL.
Precondition
ra8_usb_composite_init has run.
Both descriptors point to caller-owned memory that lives for the device's session.
Postcondition
ra8_usb_composite_get_device_descriptor / ra8_usb_composite_get_config_descriptor return the supplied pointers.
Note
Not thread-safe.
Since
0.1.0

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.

◆ ra8_usb_composite_step()

ra8_err_t ra8_usb_composite_step ( void )
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:

  • IDLE: wait for the next SETUP packet.
  • SETUP_RX: a SETUP arrived; classify it (standard / class / vendor) using bm_request_type and route accordingly.
  • STD_DISPATCH: standard chapter-9 requests (GET_DESCRIPTOR, SET_ADDRESS, SET_CONFIGURATION) handled here.
  • CLASS_DISPATCH: class / vendor requests routed to the registered class whose IF range covers setup->w_index.
  • DONE: transfer staged; next step idles back to SETUP_RX.
Returns
ra8_err_t error code.
Return values
k_ra8_okStep advanced.
k_ra8_err_invalid_stateDriver not initialized.
Precondition
ra8_usb_composite_init has run.
Postcondition
Internal state machine advances by one phase.
Note
Not thread-safe.
Since
0.1.0

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.

Variable Documentation

◆ s_state

ra8_usb_composite_state_data_t s_state = {}
static

Definition at line 173 of file ra8_usb_composite.c.

◆ s_tag

const char* s_tag = "USBCOMP"
static

Definition at line 56 of file ra8_usb_composite.c.