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

Native USB host-side Audio class layer implementation. More...

#include "ra8_usb_haud.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_haud.c:

Go to the source code of this file.

Data Structures

struct  ra8_usb_haud_state_t
 Singleton shadow state for the host-Audio driver. More...

Enumerations

enum  ra8_usb_haud_step_t : uint8_t {
  k_ra8_haud_step_idle = 0U ,
  k_ra8_haud_step_bus_reset = 1U ,
  k_ra8_haud_step_set_address = 2U ,
  k_ra8_haud_step_get_dev_desc = 3U ,
  k_ra8_haud_step_get_cfg_desc = 4U ,
  k_ra8_haud_step_set_config = 5U ,
  k_ra8_haud_step_set_interface = 6U ,
  k_ra8_haud_step_walk_desc = 7U ,
  k_ra8_haud_step_done = 8U
}
 Enumeration step machine states. More...
enum  ra8_usb_haud_setup_field_t : uint8_t {
  k_ra8_haud_bm_std_dev_in = 0x80U ,
  k_ra8_haud_bm_std_dev_out = 0x00U ,
  k_ra8_haud_bm_std_iface_out = 0x01U ,
  k_ra8_haud_breq_get_descriptor = 0x06U ,
  k_ra8_haud_breq_set_address = 0x05U ,
  k_ra8_haud_breq_set_config = 0x09U ,
  k_ra8_haud_breq_set_interface = 0x0BU ,
  k_ra8_haud_bm_class_iface_out = 0x21U ,
  k_ra8_haud_bm_class_iface_in = 0xA1U ,
  k_ra8_haud_bm_class_ep_out = 0x22U ,
  k_ra8_haud_bm_class_ep_in = 0xA2U ,
  k_ra8_haud_desc_device = 0x01U ,
  k_ra8_haud_desc_configuration = 0x02U
}
 Standard chapter-9 + Audio class request encodings. More...
enum  ra8_usb_haud_size_t : uint16_t {
  k_ra8_haud_dev_desc_len = 18U ,
  k_ra8_haud_cfg_desc_len = 9U ,
  k_ra8_haud_assigned_address = 1U ,
  k_ra8_haud_default_config = 1U ,
  k_ra8_haud_default_alt = 1U ,
  k_ra8_haud_volume_payload = 2U ,
  k_ra8_haud_mute_payload = 1U ,
  k_ra8_haud_sample_rate_payload = 3U
}
 Standard descriptor sizes and wire payloads. More...
enum  ra8_usb_haud_byte_shift_t : uint8_t {
  k_ra8_haud_shift_byte0 = 0U ,
  k_ra8_haud_shift_byte1 = 8U
}
 Per-byte left-shift constants for wValue / wIndex layout. More...
enum  ra8_usb_haud_default_unit_t : uint8_t {
  k_ra8_haud_default_feature_unit_id = 2U ,
  k_ra8_haud_default_ac_interface = 0U ,
  k_ra8_haud_default_as_interface = 1U ,
  k_ra8_haud_default_iso_out_ep = 1U ,
  k_ra8_haud_default_iso_in_ep = 0U
}
 Default Feature Unit ID applied by the descriptor-walk stub when the attached device follows the canonical USB-headphones layout (Input Terminal -> Feature Unit -> Output Terminal). More...

Functions

static uint16_t internal_iso_max_packet (ra8_usb_speed_t speed)
 Pick the iso-max-packet ceiling matching the negotiated speed.
static ra8_err_t internal_configure_pipes (void)
 Configure the host-Audio iso pipes against the attached device's endpoints.
static ra8_err_t internal_setup_get_descriptor (uint8_t desc_type, uint16_t length)
 Stage a chapter-9 GET_DESCRIPTOR SETUP request.
static ra8_err_t internal_setup_set_address (uint8_t address)
 Stage a SET_ADDRESS SETUP request.
static ra8_err_t internal_setup_set_config (uint8_t config_value)
 Stage a SET_CONFIGURATION SETUP request.
static ra8_err_t internal_setup_set_interface (void)
 Stage a SET_INTERFACE SETUP request to the AS interface.
static void internal_walk_config_descriptor (void)
 Populate s_state.device with stub descriptor data.
static ra8_err_t internal_do_idle (void)
 Step handler – bus-reset assert.
static ra8_err_t internal_do_bus_reset (void)
 Step handler – bus-reset release + SETUP for SET_ADDRESS.
static ra8_err_t internal_do_set_address (void)
 Step handler – store assigned address + SETUP for GET_DEVICE_DESCRIPTOR.
static ra8_err_t internal_do_get_dev_desc (void)
 Step handler – SETUP for GET_CONFIGURATION_DESCRIPTOR.
static ra8_err_t internal_do_get_cfg_desc (void)
 Step handler – SETUP for SET_CONFIGURATION.
static ra8_err_t internal_do_set_config (void)
 Step handler – SETUP for SET_INTERFACE (alt 1).
static ra8_err_t internal_do_set_interface (void)
 Step handler – pure software state move into walk_desc.
static ra8_err_t internal_do_walk_desc (void)
 Step handler – configure pipes and finalise.
static ra8_err_t internal_step_advance (void)
 Drive the enumeration step machine forward by one step.
static ra8_err_t internal_class_preflight (void)
 Common pre-flight for every class control transfer.
static bool internal_format_ok (uint8_t channel_count, uint8_t bits_per_sample, uint32_t sample_rate)
 Validate audio format against the supported ranges.
ra8_err_t ra8_usb_haud_init (ra8_usb_speed_t speed)
 Bring up the host-Audio driver on a chosen USB controller.
ra8_err_t ra8_usb_haud_close (void)
 Tear down the host-Audio driver and release the controller.
ra8_err_t ra8_usb_haud_attach_callback (ra8_usb_haud_attach_fn_t on_attach, void *ctx)
 Register (or detach) the attach callback.
ra8_err_t ra8_usb_haud_set_format (uint8_t channel_count, uint8_t bits_per_sample, uint32_t sample_rate_hz)
 Issue SET_CUR on the format-type-I descriptor (USB Audio 1.0 sec 5.2.3 "Class-Specific AS Interface Control Requests").
ra8_err_t ra8_usb_haud_set_volume (uint8_t channel, int16_t volume)
 Issue SET_CUR on the Feature Unit Volume control (USB Audio 1.0 sec 5.2.2.4.3 "Volume Control").
ra8_err_t ra8_usb_haud_set_mute (uint8_t channel, bool mute)
 Issue SET_CUR on the Feature Unit Mute control (USB Audio 1.0 sec 5.2.2.4.3.1 "Mute Control").
ra8_err_t ra8_usb_haud_send_samples (const uint8_t *buf, uint16_t len_bytes)
 Push isochronous-OUT samples to a speaker / headphones.
ra8_err_t ra8_usb_haud_recv_samples (uint8_t *buf, uint16_t max_len_bytes, uint16_t *got_len_bytes)
 Drain isochronous-IN samples from a microphone.
ra8_err_t ra8_usb_haud_step (void)
 Drive the enumeration step machine forward by one step.

Variables

static const char * s_tag = "USBHAUD"
static ra8_usb_haud_state_t s_state = {}

Detailed Description

Native USB host-side Audio class layer implementation.

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

Glues the host-mode bring-up paths in ra8_usb to a USB Audio class peripheral - speaker / headphones / microphone - attached on the EK-RA8D2's USB-host port. This file is the native host-Audio class layer; FSP's r_usb_haud.c is reference material only – nothing is pulled in verbatim.

Mapping vs FSP (FSP function -> our entry point):

The starter does CPU-FIFO, single-device, no-hub. Enumeration is driven step-by-step from the controller's CTRT interrupt path (production) or directly via ra8_usb_haud_step (tests). Each step issues exactly one chapter-9 SETUP request via ra8_usb_host_setup_request; the next CTRT advances the step.

Definition in file ra8_usb_haud.c.

Enumeration Type Documentation

◆ ra8_usb_haud_byte_shift_t

enum ra8_usb_haud_byte_shift_t : uint8_t

Per-byte left-shift constants for wValue / wIndex layout.

Enumerator
k_ra8_haud_shift_byte0 

RA8 haud shift byte0.

k_ra8_haud_shift_byte1 

RA8 haud shift byte1.

Definition at line 115 of file ra8_usb_haud.c.

◆ ra8_usb_haud_default_unit_t

Default Feature Unit ID applied by the descriptor-walk stub when the attached device follows the canonical USB-headphones layout (Input Terminal -> Feature Unit -> Output Terminal).

Enumerator
k_ra8_haud_default_feature_unit_id 

Common bUnitID for FU.

k_ra8_haud_default_ac_interface 

AC bInterfaceNumber.

k_ra8_haud_default_as_interface 

AS bInterfaceNumber.

k_ra8_haud_default_iso_out_ep 

Common iso-OUT EP num.

k_ra8_haud_default_iso_in_ep 

No mic in default stub.

Definition at line 126 of file ra8_usb_haud.c.

◆ ra8_usb_haud_setup_field_t

Standard chapter-9 + Audio class request encodings.

Enumerator
k_ra8_haud_bm_std_dev_in 

Std | Device | In.

k_ra8_haud_bm_std_dev_out 

Std | Device | Out.

k_ra8_haud_bm_std_iface_out 

Std | Interface | Out.

k_ra8_haud_breq_get_descriptor 

GET_DESCRIPTOR.

k_ra8_haud_breq_set_address 

SET_ADDRESS.

k_ra8_haud_breq_set_config 

SET_CONFIGURATION.

k_ra8_haud_breq_set_interface 

SET_INTERFACE.

k_ra8_haud_bm_class_iface_out 

Class | Interface | Out.

k_ra8_haud_bm_class_iface_in 

Class | Interface | In.

k_ra8_haud_bm_class_ep_out 

Class | Endpoint | Out.

k_ra8_haud_bm_class_ep_in 

Class | Endpoint | In.

k_ra8_haud_desc_device 

DEVICE descriptor.

k_ra8_haud_desc_configuration 

CONFIGURATION descriptor.

Definition at line 77 of file ra8_usb_haud.c.

◆ ra8_usb_haud_size_t

enum ra8_usb_haud_size_t : uint16_t

Standard descriptor sizes and wire payloads.

Enumerator
k_ra8_haud_dev_desc_len 

USB DEVICE descriptor.

k_ra8_haud_cfg_desc_len 

CONFIGURATION descriptor hdr.

k_ra8_haud_assigned_address 

First assigned device addr.

k_ra8_haud_default_config 

bConfigurationValue = 1.

k_ra8_haud_default_alt 

Streaming alt setting.

k_ra8_haud_volume_payload 

16-bit signed dB payload.

k_ra8_haud_mute_payload 

1-byte boolean payload.

k_ra8_haud_sample_rate_payload 

24-bit LE rate payload.

Definition at line 100 of file ra8_usb_haud.c.

◆ ra8_usb_haud_step_t

enum ra8_usb_haud_step_t : uint8_t

Enumeration step machine states.

Mirrors FSP's host-Audio enumeration sequence in r_usb_haud.c. Each step issues exactly one SETUP via ra8_usb_host_setup_request; the next CTRT interrupt advances.

Enumerator
k_ra8_haud_step_idle 

Pre-attach.

k_ra8_haud_step_bus_reset 

Drive USBRST then release.

k_ra8_haud_step_set_address 

SET_ADDRESS to assigned 1.

k_ra8_haud_step_get_dev_desc 

GET_DEVICE_DESCRIPTOR (18).

k_ra8_haud_step_get_cfg_desc 

GET_CONFIGURATION_DESCRIPTOR.

k_ra8_haud_step_set_config 

SET_CONFIGURATION (1).

k_ra8_haud_step_set_interface 

SET_INTERFACE (alt 1).

k_ra8_haud_step_walk_desc 

Walk AC + AS interfaces.

k_ra8_haud_step_done 

Attach callback fires.

Definition at line 61 of file ra8_usb_haud.c.

Function Documentation

◆ internal_class_preflight()

ra8_err_t internal_class_preflight ( void )
static

Common pre-flight for every class control transfer.

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 625 of file ra8_usb_haud.c.

References k_ra8_err_invalid_state, k_ra8_ok, and s_state.

Referenced by ra8_usb_haud_recv_samples(), ra8_usb_haud_send_samples(), ra8_usb_haud_set_format(), ra8_usb_haud_set_mute(), and ra8_usb_haud_set_volume().

◆ internal_configure_pipes()

ra8_err_t internal_configure_pipes ( void )
static

Configure the host-Audio iso pipes against the attached device's endpoints.

Mirrors FSP's usb_haud_pipe_info. PIPE2 (iso-OUT) is configured if the device exposes a speaker; PIPE1 (iso-IN) is configured if it exposes a microphone. A device with neither endpoint is silently accepted – the class layer just won't be able to push or drain samples.

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 201 of file ra8_usb_haud.c.

References k_ra8_haud_pipe_iso_in, k_ra8_haud_pipe_iso_out, k_ra8_ok, k_ra8_usb_ep_dir_in, k_ra8_usb_ep_dir_out, k_ra8_usb_ep_type_iso, RA8_RETURN_ON_ERROR, ra8_usb_configure_endpoint(), s_state, and s_tag.

Referenced by internal_do_walk_desc(), ra8_usb_cdc_init(), ra8_usb_paud_init(), ra8_usb_phid_init(), ra8_usb_pprn_init(), and ra8_usb_pvnd_init().

◆ internal_do_bus_reset()

ra8_err_t internal_do_bus_reset ( void )
static

Step handler – bus-reset release + SETUP for SET_ADDRESS.

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 427 of file ra8_usb_haud.c.

References internal_setup_set_address(), k_ra8_haud_assigned_address, k_ra8_haud_step_set_address, RA8_RETURN_ON_ERROR, ra8_usb_host_bus_reset(), s_state, and s_tag.

Referenced by internal_step_advance().

◆ internal_do_get_cfg_desc()

ra8_err_t internal_do_get_cfg_desc ( void )
static

Step handler – SETUP for SET_CONFIGURATION.

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 497 of file ra8_usb_haud.c.

References internal_setup_set_config(), internal_walk_config_descriptor(), k_ra8_haud_default_config, k_ra8_haud_step_set_config, and s_state.

Referenced by internal_step_advance().

◆ internal_do_get_dev_desc()

ra8_err_t internal_do_get_dev_desc ( void )
static

Step handler – SETUP for GET_CONFIGURATION_DESCRIPTOR.

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 477 of file ra8_usb_haud.c.

References internal_setup_get_descriptor(), k_ra8_haud_cfg_desc_len, k_ra8_haud_desc_configuration, k_ra8_haud_step_get_cfg_desc, and s_state.

Referenced by internal_step_advance().

◆ internal_do_idle()

ra8_err_t internal_do_idle ( void )
static

Step handler – bus-reset assert.

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 407 of file ra8_usb_haud.c.

References k_ra8_haud_step_bus_reset, ra8_usb_host_bus_reset(), and s_state.

Referenced by internal_step_advance().

◆ internal_do_set_address()

ra8_err_t internal_do_set_address ( void )
static

Step handler – store assigned address + SETUP for GET_DEVICE_DESCRIPTOR.

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 452 of file ra8_usb_haud.c.

References internal_setup_get_descriptor(), k_ra8_haud_assigned_address, k_ra8_haud_desc_device, k_ra8_haud_dev_desc_len, k_ra8_haud_step_get_dev_desc, RA8_RETURN_ON_ERROR, ra8_usb_set_address(), s_state, and s_tag.

Referenced by internal_step_advance().

◆ internal_do_set_config()

ra8_err_t internal_do_set_config ( void )
static

Step handler – SETUP for SET_INTERFACE (alt 1).

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 520 of file ra8_usb_haud.c.

References internal_setup_set_interface(), k_ra8_haud_step_set_interface, and s_state.

Referenced by internal_step_advance().

◆ internal_do_set_interface()

ra8_err_t internal_do_set_interface ( void )
static

Step handler – pure software state move into walk_desc.

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 540 of file ra8_usb_haud.c.

References k_ra8_haud_step_walk_desc, k_ra8_ok, and s_state.

Referenced by internal_step_advance().

◆ internal_do_walk_desc()

ra8_err_t internal_do_walk_desc ( void )
static

Step handler – configure pipes and finalise.

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 560 of file ra8_usb_haud.c.

References internal_configure_pipes(), k_ra8_haud_step_done, k_ra8_ok, RA8_RETURN_ON_ERROR, s_state, and s_tag.

Referenced by internal_step_advance().

◆ internal_format_ok()

bool internal_format_ok ( uint8_t channel_count,
uint8_t bits_per_sample,
uint32_t sample_rate )
static

Validate audio format against the supported ranges.

See implementation.

Parameters
[in]channel_countSee implementation.
[in]bits_per_sampleSee implementation.
[in]sample_rateSee 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 653 of file ra8_usb_haud.c.

References k_ra8_haud_max_bits, k_ra8_haud_max_channels, k_ra8_haud_max_sample_rate_hz, k_ra8_haud_min_bits, k_ra8_haud_min_channels, and k_ra8_haud_min_sample_rate_hz.

Referenced by ra8_usb_haud_set_format().

◆ internal_iso_max_packet()

uint16_t internal_iso_max_packet ( ra8_usb_speed_t speed)
static

Pick the iso-max-packet ceiling matching the negotiated speed.

See implementation.

Parameters
[in]speedSee 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 175 of file ra8_usb_haud.c.

References k_ra8_haud_iso_max_packet_fs, k_ra8_haud_iso_max_packet_hs, and k_ra8_usb_speed_hs.

Referenced by internal_walk_config_descriptor().

◆ internal_setup_get_descriptor()

ra8_err_t internal_setup_get_descriptor ( uint8_t desc_type,
uint16_t length )
static

Stage a chapter-9 GET_DESCRIPTOR SETUP request.

See implementation.

Parameters
[in]desc_typeSee implementation.
[in]lengthSee 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 240 of file ra8_usb_haud.c.

References k_ra8_haud_bm_std_dev_in, k_ra8_haud_breq_get_descriptor, k_ra8_haud_shift_byte1, ra8_usb_host_setup_request(), and s_state.

Referenced by internal_do_get_dev_desc(), and internal_do_set_address().

◆ internal_setup_set_address()

ra8_err_t internal_setup_set_address ( uint8_t address)
static

Stage a SET_ADDRESS SETUP request.

See implementation.

Parameters
[in]addressSee 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 267 of file ra8_usb_haud.c.

References k_ra8_haud_bm_std_dev_out, k_ra8_haud_breq_set_address, ra8_usb_host_setup_request(), and s_state.

Referenced by internal_do_bus_reset().

◆ internal_setup_set_config()

ra8_err_t internal_setup_set_config ( uint8_t config_value)
static

Stage a SET_CONFIGURATION SETUP request.

See implementation.

Parameters
[in]config_valueSee 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 294 of file ra8_usb_haud.c.

References k_ra8_haud_bm_std_dev_out, k_ra8_haud_breq_set_config, ra8_usb_host_setup_request(), and s_state.

Referenced by internal_do_get_cfg_desc().

◆ internal_setup_set_interface()

ra8_err_t internal_setup_set_interface ( void )
static

Stage a SET_INTERFACE SETUP request to the AS interface.

Per USB Audio 1.0 sec 4.5 the host must select a non-zero Audio-Streaming alt setting (alt 0 is the "zero-bandwidth" default) for any iso-EP transfers to actually move data.

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 323 of file ra8_usb_haud.c.

References k_ra8_haud_bm_std_iface_out, k_ra8_haud_breq_set_interface, k_ra8_haud_default_alt, ra8_usb_host_setup_request(), and s_state.

Referenced by internal_do_set_config().

◆ internal_step_advance()

ra8_err_t internal_step_advance ( void )
static

Drive the enumeration step machine forward by one step.

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 586 of file ra8_usb_haud.c.

References internal_do_bus_reset(), internal_do_get_cfg_desc(), internal_do_get_dev_desc(), internal_do_idle(), internal_do_set_address(), internal_do_set_config(), internal_do_set_interface(), internal_do_walk_desc(), k_ra8_haud_step_bus_reset, k_ra8_haud_step_get_cfg_desc, k_ra8_haud_step_get_dev_desc, k_ra8_haud_step_idle, k_ra8_haud_step_set_address, k_ra8_haud_step_set_config, k_ra8_haud_step_set_interface, k_ra8_haud_step_walk_desc, k_ra8_ok, and s_state.

Referenced by ra8_usb_haud_step().

◆ internal_walk_config_descriptor()

void internal_walk_config_descriptor ( void )
static

Populate s_state.device with stub descriptor data.

In production this routine walks the configuration descriptor returned in the GET_CONFIG_DESCRIPTOR data stage. It locates:

  1. The Audio-Control interface (bInterfaceClass = 0x01, bInterfaceSubClass = 0x01).
  2. At least one Audio-Streaming interface (bInterfaceClass = 0x01, bInterfaceSubClass = 0x02), and within it the FORMAT_TYPE_I class-specific AS descriptor (bDescriptorSubtype = 0x02, bFormatType = 0x01) - this is where bNrChannels, bBitResolution, and the tSamFreq[] range live.
  3. The isochronous-IN / OUT endpoints inside that AS interface (bmAttributes & 0x03 == 0x01).
  4. (Optional but useful) Within the AC interface's class-specific descriptors, the Feature Unit (bDescriptorSubtype = 0x06) - the bUnitID field is what wIndex's high byte must carry for any SET_CUR(VOLUME) / SET_CUR(MUTE) request. The walk also visits Input Terminal (0x02), Output Terminal (0x03), and Selector Unit (0x05) entries to make sure the Feature Unit picked is the one chained between the input and output terminals (rather than a sidechain unit).

The starter relies on the fact that a typical USB-headphones device advertises the canonical "Input Terminal -> Feature Unit (id=2) -> Output Terminal" graph, with 48 kHz / 16-bit / stereo PCM and an iso-OUT endpoint at EP address 1. If the attached device deviates, the production path will overwrite these defaults during the descriptor walk.

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 375 of file ra8_usb_haud.c.

References internal_iso_max_packet(), k_ra8_haud_assigned_address, k_ra8_haud_default_ac_interface, k_ra8_haud_default_as_interface, k_ra8_haud_default_bits, k_ra8_haud_default_channels, k_ra8_haud_default_feature_unit_id, k_ra8_haud_default_iso_in_ep, k_ra8_haud_default_iso_out_ep, k_ra8_haud_default_sample_rate_hz, and s_state.

Referenced by internal_do_get_cfg_desc().

◆ ra8_usb_haud_attach_callback()

ra8_err_t ra8_usb_haud_attach_callback ( ra8_usb_haud_attach_fn_t on_attach,
void * ctx )
nodiscard

Register (or detach) the attach callback.

The supplied callback fires exactly once per attach event, after the descriptor walk identifies an Audio-Control interface (class=0x01 / subclass=0x01) and at least one Audio-Streaming interface (class=0x01 / subclass=0x02), and the matching isochronous IN / OUT endpoints and Feature Unit are cached. Pass NULL to detach.

Parameters
[in]on_attachCallback. NULL detaches.
[in]ctxContext pointer threaded back into on_attach.
Returns
ra8_err_t error code.
Return values
k_ra8_okCallback installed.
k_ra8_err_invalid_stateDriver was never initialized.
Precondition
ra8_usb_haud_init has run.
Postcondition
On a subsequent attach, on_attach(ctx, &device) fires once.
Note
Not thread-safe.
Since
0.1.0

Definition at line 719 of file ra8_usb_haud.c.

References k_ra8_err_invalid_state, k_ra8_ok, and s_state.

◆ ra8_usb_haud_close()

ra8_err_t ra8_usb_haud_close ( void )
nodiscard

Tear down the host-Audio driver and release the controller.

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_host_deinit ran; SOF generation halted; bus power dropped; subsequent host-Audio API calls return k_ra8_err_invalid_state.
Note
Not thread-safe.
Since
0.1.0

Definition at line 698 of file ra8_usb_haud.c.

References k_ra8_err_invalid_state, k_ra8_haud_step_idle, ra8_usb_host_deinit(), ra8_usb_host_set_uact(), and s_state.

◆ ra8_usb_haud_init()

ra8_err_t ra8_usb_haud_init ( ra8_usb_speed_t speed)
nodiscard

Bring up the host-Audio driver on a chosen USB controller.

Initialises the underlying ra8_usb driver in HOST mode for speed, leaves the bus in the "wait for attach" state (UACT cleared), and arms the internal enumeration step machine. Delegates to ra8_usb_host_init.

Parameters
[in]speedWhich USB controller (FS or HS).
Returns
ra8_err_t error code.
Return values
k_ra8_okHost-Audio ready, awaiting attach.
k_ra8_err_invalid_argspeed out of range.
k_ra8_err_hw_init_failedUnderlying ra8_usb_host_init failed.
Precondition
Single-threaded init context.
ra8_mstp_init and ra8_pwr_init already ran.
Postcondition
ra8_usb_host_init succeeded for speed.
Internal step machine armed; attach callback has not fired.
Note
Not thread-safe.
See also
ra8_usb_haud_attach_callback
ra8_usb_haud_close
Since
0.1.0

Definition at line 675 of file ra8_usb_haud.c.

References k_ra8_err_hw_init_failed, k_ra8_err_invalid_arg, k_ra8_haud_step_idle, k_ra8_ok, k_ra8_usb_speed_fs, k_ra8_usb_speed_hs, ra8_log_error_val, ra8_log_info_val, ra8_usb_host_init(), s_state, and s_tag.

◆ ra8_usb_haud_recv_samples()

ra8_err_t ra8_usb_haud_recv_samples ( uint8_t * buf,
uint16_t max_len_bytes,
uint16_t * got_len_bytes )
nodiscard

Drain isochronous-IN samples from a microphone.

Polling / non-blocking. Pulls bytes from the configured PIPE1 (isochronous IN) into buf. Returns k_ra8_err_no_data if the pipe has no bytes ready in this micro-frame.

Parameters
[out]bufDestination buffer.
[in]max_len_bytesCapacity of buf, > 0.
[out]got_len_bytesReceives the number of bytes actually placed.
Returns
ra8_err_t error code.
Return values
k_ra8_okBytes drained; *got_len_bytes reflects the count.
k_ra8_err_no_dataPipe was empty.
k_ra8_err_null_ptrbuf or got_len_bytes was NULL.
k_ra8_err_invalid_stateDriver not initialized, no device attached, or device has no iso-IN endpoint.
k_ra8_err_invalid_argmax_len_bytes == 0.
Precondition
ra8_usb_haud_init succeeded.
Attach callback already fired with an iso-IN endpoint.
Postcondition
On success *got_len_bytes reflects the actual byte count.
Note
Not thread-safe.
Since
0.1.0

Definition at line 864 of file ra8_usb_haud.c.

References internal_class_preflight(), k_ra8_err_invalid_arg, k_ra8_err_invalid_state, k_ra8_haud_pipe_iso_in, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_usb_queue_out(), s_state, and s_tag.

◆ ra8_usb_haud_send_samples()

ra8_err_t ra8_usb_haud_send_samples ( const uint8_t * buf,
uint16_t len_bytes )
nodiscard

Push isochronous-OUT samples to a speaker / headphones.

Streams buf[0..len_bytes-1] onto the iso-OUT pipe configured for the attached Audio-Streaming interface. PCM byte-order matches the Audio-Streaming format (little-endian per USB Audio Data Formats 1.0 sec 2.2). Non-blocking; bytes that don't fit in the current micro-frame return k_ra8_err_busy for the caller to retry.

Parameters
[in]bufSample byte buffer.
[in]len_bytesNumber of bytes in buf.
Returns
ra8_err_t error code.
Return values
k_ra8_okBytes queued for the next iso-OUT slot.
k_ra8_err_null_ptrbuf == NULL and len_bytes != 0.
k_ra8_err_invalid_stateDriver not initialized, no device attached, or device has no iso-OUT endpoint.
k_ra8_err_invalid_arglen_bytes == 0.
k_ra8_err_busyiso-OUT pipe busy.
Precondition
ra8_usb_haud_init succeeded.
Attach callback already fired with an iso-OUT endpoint.
Postcondition
On success bytes queued onto PIPE2.
Note
Not thread-safe.
Since
0.1.0

Definition at line 843 of file ra8_usb_haud.c.

References internal_class_preflight(), k_ra8_err_invalid_arg, k_ra8_err_invalid_state, k_ra8_err_null_ptr, k_ra8_haud_pipe_iso_out, k_ra8_ok, ra8_usb_queue_in(), and s_state.

◆ ra8_usb_haud_set_format()

ra8_err_t ra8_usb_haud_set_format ( uint8_t channel_count,
uint8_t bits_per_sample,
uint32_t sample_rate_hz )
nodiscard

Issue SET_CUR on the format-type-I descriptor (USB Audio 1.0 sec 5.2.3 "Class-Specific AS Interface Control Requests").

Builds an 8-byte SETUP packet with bmRequestType = 0x22 (Class | Endpoint | Host-to-Device), bRequest = 0x01 (SET_CUR), and wValue = (SAMPLING_FREQ_CONTROL << 8). The data stage payload is a 3-byte little-endian sample rate (USB Audio 1.0 sec 5.2.3.2.3.1). Channel count and bits-per-sample are validated and recorded into the cached device snapshot, but the wire transfer for those is already implicit in the chosen Audio-Streaming interface alt setting; this entry point just refreshes the iso-EP sampling-rate.

Parameters
[in]channel_countChannels (1..8).
[in]bits_per_sample8..32.
[in]sample_rate_hz8000..192000.
Returns
ra8_err_t error code.
Return values
k_ra8_okSETUP queued.
k_ra8_err_invalid_stateDriver not initialized, or no device attached.
k_ra8_err_invalid_argOne of channel_count / bits_per_sample / sample_rate_hz is out of range.
k_ra8_err_busyController busy with a prior SETUP.
Precondition
ra8_usb_haud_init succeeded.
Attach callback already fired.
Postcondition
On success the SETUP mirror registers hold the SET_CUR request envelope; the cached format snapshot is updated.
Note
Not thread-safe.
Since
0.1.0

Definition at line 743 of file ra8_usb_haud.c.

References internal_class_preflight(), internal_format_ok(), k_ra8_err_invalid_arg, k_ra8_haud_bm_class_ep_out, k_ra8_haud_ep_control_sampling_freq, k_ra8_haud_req_set_cur, k_ra8_haud_sample_rate_payload, k_ra8_haud_shift_byte1, k_ra8_ok, ra8_usb_host_setup_request(), and s_state.

◆ ra8_usb_haud_set_mute()

ra8_err_t ra8_usb_haud_set_mute ( uint8_t channel,
bool mute )
nodiscard

Issue SET_CUR on the Feature Unit Mute control (USB Audio 1.0 sec 5.2.2.4.3.1 "Mute Control").

Builds an 8-byte SETUP packet with bmRequestType = 0x21 (Class | Interface | Host-to-Device), bRequest = 0x01 (SET_CUR), and wValue = (MUTE_CONTROL << 8) | channel. wIndex packs the Feature Unit ID in the high byte and the AudioControl interface in the low byte. Mute is a one-byte boolean (0 = unmute, 1 = mute).

Parameters
[in]channelLogical channel (0 = main, 1..N per channel).
[in]mutetrue = mute, false = unmute.
Returns
ra8_err_t error code.
Return values
k_ra8_okSETUP queued.
k_ra8_err_invalid_stateDriver not initialized, or no device attached.
k_ra8_err_busyController busy with a prior SETUP.
Precondition
ra8_usb_haud_init succeeded.
Attach callback already fired.
Postcondition
On success the SETUP mirror registers hold the SET_CUR request envelope.
Note
Not thread-safe.
Since
0.1.0

Definition at line 815 of file ra8_usb_haud.c.

References internal_class_preflight(), k_ra8_haud_bm_class_iface_out, k_ra8_haud_fu_control_mute, k_ra8_haud_mute_payload, k_ra8_haud_req_set_cur, k_ra8_haud_shift_byte1, k_ra8_ok, ra8_usb_host_setup_request(), and s_state.

◆ ra8_usb_haud_set_volume()

ra8_err_t ra8_usb_haud_set_volume ( uint8_t channel,
int16_t volume )
nodiscard

Issue SET_CUR on the Feature Unit Volume control (USB Audio 1.0 sec 5.2.2.4.3 "Volume Control").

Builds an 8-byte SETUP packet with bmRequestType = 0x21 (Class | Interface | Host-to-Device), bRequest = 0x01 (SET_CUR), and wValue = (VOLUME_CONTROL << 8) | channel. wIndex packs the Feature Unit ID in the high byte and the AudioControl interface in the low byte. Volume is a signed 16-bit value in 1/256 dB steps; 0x8000 is the silence sentinel.

Parameters
[in]channelLogical channel (0 = main, 1..N per channel).
[in]volumeSigned dB in 1/256 step.
Returns
ra8_err_t error code.
Return values
k_ra8_okSETUP queued.
k_ra8_err_invalid_stateDriver not initialized, or no device attached.
k_ra8_err_busyController busy with a prior SETUP.
Precondition
ra8_usb_haud_init succeeded.
Attach callback already fired.
Postcondition
On success the SETUP mirror registers hold the SET_CUR request envelope.
Note
Not thread-safe.
Since
0.1.0

Definition at line 780 of file ra8_usb_haud.c.

References internal_class_preflight(), k_ra8_haud_bm_class_iface_out, k_ra8_haud_fu_control_volume, k_ra8_haud_req_set_cur, k_ra8_haud_shift_byte1, k_ra8_haud_volume_payload, k_ra8_ok, ra8_usb_host_setup_request(), and s_state.

◆ ra8_usb_haud_step()

ra8_err_t ra8_usb_haud_step ( void )
nodiscard

Drive the enumeration step machine forward by one step.

Test / debug entry point. The production path drives this from the ra8_usb_dispatch callback when the controller fires a CTRT or BRDY interrupt; tests call it directly to walk the state machine deterministically.

Returns
ra8_err_t error code.
Return values
k_ra8_okStep advanced.
k_ra8_err_invalid_stateDriver not initialized.
Precondition
ra8_usb_haud_init succeeded.
Postcondition
Internal enumeration step counter advances by one. When the step machine reaches the terminal state the registered attach callback fires.
Note
Not thread-safe.
Since
0.1.0

Definition at line 894 of file ra8_usb_haud.c.

References internal_step_advance(), k_ra8_err_invalid_state, and s_state.

Variable Documentation

◆ s_state

ra8_usb_haud_state_t s_state = {}
static

Definition at line 153 of file ra8_usb_haud.c.

◆ s_tag

const char* s_tag = "USBHAUD"
static

Definition at line 46 of file ra8_usb_haud.c.