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

Native USB device-side MSC (Mass Storage Class) class layer implementation. More...

#include "ra8_usb_pmsc.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_pmsc_internal.h"
Include dependency graph for ra8_usb_pmsc.c:

Go to the source code of this file.

Enumerations

enum  ra8_usb_pmsc_cbw_offset_t : uint8_t {
  k_ra8_pmsc_cbw_off_signature = 0U ,
  k_ra8_pmsc_cbw_off_tag = 4U ,
  k_ra8_pmsc_cbw_off_data_length = 8U ,
  k_ra8_pmsc_cbw_off_flags = 12U ,
  k_ra8_pmsc_cbw_off_lun = 13U ,
  k_ra8_pmsc_cbw_off_cdb_length = 14U ,
  k_ra8_pmsc_cbw_off_cdb = 15U
}
 Byte offsets inside the 31-byte CBW header. More...
enum  ra8_usb_pmsc_csw_offset_t : uint8_t {
  k_ra8_pmsc_csw_off_signature = 0U ,
  k_ra8_pmsc_csw_off_tag = 4U ,
  k_ra8_pmsc_csw_off_residue = 8U ,
  k_ra8_pmsc_csw_off_status = 12U
}
 Byte offsets inside the 13-byte CSW. More...
enum  ra8_usb_pmsc_cbw_flag_t : uint8_t {
  k_ra8_pmsc_cbw_flag_data_out = 0x00U ,
  k_ra8_pmsc_cbw_flag_data_in = 0x80U
}
 bmCBWFlags direction bit values. More...
enum  ra8_usb_pmsc_signature_t : uint32_t {
  k_ra8_pmsc_cbw_signature = 0x43425355U ,
  k_ra8_pmsc_csw_signature = 0x53425355U
}
 BOT wrapper signatures (USB MSC BBB rev 1.0 sec 5). More...
enum  ra8_usb_pmsc_initial_tag_t : uint32_t { k_ra8_pmsc_initial_tag = 0U }
 Initial value of the cached BOT dCBWTag. More...
enum  ra8_usb_pmsc_lun_mask_t : uint8_t {
  k_ra8_pmsc_lun_field_mask = 0x0FU ,
  k_ra8_pmsc_cdb_field_mask = 0x1FU
}
 Field-width masks for bCBWLUN + bCBWCBLength bytes. More...

Functions

static uint16_t internal_bulk_max_packet (ra8_usb_speed_t speed)
 Pick the bulk-max-packet ceiling matching the negotiated speed.
static void internal_configure_pipes (void)
 Configure the two device-MSC bulk pipes against the local endpoints.
static void internal_pack_u32_le (uint32_t value, uint8_t *dst)
 Pack a uint32 into 4 little-endian bytes.
static uint32_t internal_unpack_u32_le (const uint8_t *src)
 Unpack a uint32 from 4 little-endian bytes.
void priv_zero_bytes (uint8_t *dst, uint32_t len)
 Zero len bytes at dst byte-by-byte.
static void internal_copy_bytes (uint8_t *dst, const uint8_t *src, uint32_t len)
 Copy len bytes from src to dst byte-by-byte.
ra8_err_t ra8_usb_pmsc_feed_cbw (const uint8_t *cbw)
 Inject a CBW directly into the BOT state machine.
static ra8_err_t internal_dispatch_scsi (uint8_t *data_buf, uint32_t data_buf_capacity, uint32_t *data_len, ra8_usb_pmsc_csw_status_t *csw_status)
 Dispatch the cached CDB to the right SCSI handler.
static ra8_err_t internal_dispatch_preconditions (uint32_t data_buf_capacity)
 Validate dispatch_command preconditions (driver state + bot phase + buffer capacity).
static void internal_dispatch_advance_state (uint32_t data_len)
 Advance BOT state after a successful CDB dispatch.
ra8_err_t ra8_usb_pmsc_dispatch_command (uint8_t *data_buf, uint32_t data_buf_capacity, uint32_t *data_len, ra8_usb_pmsc_csw_status_t *csw_status)
 Run the SCSI command currently parked in the BOT state.
ra8_err_t ra8_usb_pmsc_build_csw (ra8_usb_pmsc_csw_status_t csw_status, uint32_t residue, uint8_t *out_csw)
 Build the 13-byte CSW for the in-flight command.
ra8_err_t ra8_usb_pmsc_step (void)
 Drive the BOT (Bulk-Only Transport) state machine forward by one step.
ra8_err_t ra8_usb_pmsc_attach_storage (const ra8_usb_pmsc_storage_t *storage)
 Bind a caller-owned storage backend to the device-MSC class.
ra8_err_t ra8_usb_pmsc_init (ra8_usb_speed_t speed)
 Bring up the device-MSC driver on a chosen USB controller.
ra8_err_t ra8_usb_pmsc_close (void)
 Tear down the device-MSC driver and release the controller.

Variables

static const char * s_tag = "USBPMSC"
ra8_usb_pmsc_state_data_t g_usb_pmsc_state = {}
 Singleton shadow state shared by both device-MSC TUs.

Detailed Description

Native USB device-side MSC (Mass Storage Class) class layer implementation.

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

Glues the device-mode bring-up paths in ra8_usb to a USB Mass Storage Class (Bulk-Only-Transport / BBB) function so the EK-RA8D2 appears as a USB drive on the host side. This file is the native device-MSC class layer; FSP's r_usb_pmsc_driver.c, r_usb_pmsc.c, and r_media_driver_api.c are reference material only – no FSP source is pulled in verbatim.

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

  • usb_pmsc_init -> ra8_usb_pmsc_init
  • usb_pmsc_check_cbw -> internal_check_cbw
  • usb_pmsc_setcsw -> internal_setcsw
  • usb_pmsc_csw_transfer -> CSW_TX phase in internal_pump
  • usb_pmsc_receive_cbw -> IDLE phase in internal_pump
  • usb_pmsc_get_max_lun -> internal_handle_get_max_lun
  • pmsc_atapi_command_processing -> internal_dispatch_scsi

The starter is single-LUN, single-instance. Get-Max-LUN returns 0; Mass Storage Reset rewinds the state machine to IDLE.

BOT (Bulk-Only Transport) state machine – per command:

IDLE -> CBW_RX (pull 31-byte CBW) -> CDB_DECODE -> DATA_TX (push read data) | DATA_RX (pull write data) -> CSW_TX (push 13-byte CSW) -> IDLE

On invalid CBW signature the spec mandates phase-error CSW, which the starter emits by transitioning straight to CSW_TX with status k_ra8_pmsc_csw_status_phase_error.

Definition in file ra8_usb_pmsc.c.

Enumeration Type Documentation

◆ ra8_usb_pmsc_cbw_flag_t

enum ra8_usb_pmsc_cbw_flag_t : uint8_t

bmCBWFlags direction bit values.

Enumerator
k_ra8_pmsc_cbw_flag_data_out 

Host -> device.

k_ra8_pmsc_cbw_flag_data_in 

Device -> host.

Definition at line 97 of file ra8_usb_pmsc.c.

◆ ra8_usb_pmsc_cbw_offset_t

enum ra8_usb_pmsc_cbw_offset_t : uint8_t

Byte offsets inside the 31-byte CBW header.

See USB MSC BBB rev 1.0 sec 5.1 Table 5.1 "Command Block Wrapper".

Enumerator
k_ra8_pmsc_cbw_off_signature 

dCBWSignature [4].

k_ra8_pmsc_cbw_off_tag 

dCBWTag [4].

k_ra8_pmsc_cbw_off_data_length 

dCBWDataTransferLen.

k_ra8_pmsc_cbw_off_flags 

bmCBWFlags.

k_ra8_pmsc_cbw_off_lun 

bCBWLUN (low nib).

k_ra8_pmsc_cbw_off_cdb_length 

bCBWCBLength (low 5).

k_ra8_pmsc_cbw_off_cdb 

CBWCB [16].

Definition at line 69 of file ra8_usb_pmsc.c.

◆ ra8_usb_pmsc_csw_offset_t

enum ra8_usb_pmsc_csw_offset_t : uint8_t

Byte offsets inside the 13-byte CSW.

See USB MSC BBB rev 1.0 sec 5.2 Table 5.2 "Command Status Wrapper".

Enumerator
k_ra8_pmsc_csw_off_signature 

dCSWSignature [4].

k_ra8_pmsc_csw_off_tag 

dCSWTag [4].

k_ra8_pmsc_csw_off_residue 

dCSWDataResidue.

k_ra8_pmsc_csw_off_status 

bCSWStatus.

Definition at line 86 of file ra8_usb_pmsc.c.

◆ ra8_usb_pmsc_initial_tag_t

enum ra8_usb_pmsc_initial_tag_t : uint32_t

Initial value of the cached BOT dCBWTag.

Enumerator
k_ra8_pmsc_initial_tag 

Reset value.

Definition at line 118 of file ra8_usb_pmsc.c.

◆ ra8_usb_pmsc_lun_mask_t

enum ra8_usb_pmsc_lun_mask_t : uint8_t

Field-width masks for bCBWLUN + bCBWCBLength bytes.

See USB MSC BBB rev 1.0 sec 5.1 Table 5.1: bCBWLUN occupies the low 4 bits; bCBWCBLength occupies the low 5 bits.

Enumerator
k_ra8_pmsc_lun_field_mask 

Low 4 bits of bCBWLUN.

k_ra8_pmsc_cdb_field_mask 

Low 5 bits of bCBWCBLen.

Definition at line 129 of file ra8_usb_pmsc.c.

◆ ra8_usb_pmsc_signature_t

enum ra8_usb_pmsc_signature_t : uint32_t

BOT wrapper signatures (USB MSC BBB rev 1.0 sec 5).

Stored on-wire little-endian. dCBWSignature 'USBC' is 0x43425355; dCSWSignature 'USBS' is 0x53425355.

Enumerator
k_ra8_pmsc_cbw_signature 

'USBC' little-endian.

k_ra8_pmsc_csw_signature 

'USBS' little-endian.

Definition at line 109 of file ra8_usb_pmsc.c.

Function Documentation

◆ internal_bulk_max_packet()

uint16_t internal_bulk_max_packet ( ra8_usb_speed_t speed)
static

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

See implementation.

Parameters
[in]speedSee implementation.
Returns
The bulk-endpoint maximum packet size in bytes for speed.
Return values
k_ra8_pmsc_bulk_max_packet_hsspeed is k_ra8_usb_speed_hs.
k_ra8_pmsc_bulk_max_packet_fsAny other speed.
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 163 of file ra8_usb_pmsc.c.

References k_ra8_pmsc_bulk_max_packet_fs, k_ra8_pmsc_bulk_max_packet_hs, and k_ra8_usb_speed_hs.

Referenced by internal_configure_pipes().

◆ internal_configure_pipes()

void internal_configure_pipes ( void )
static

Configure the two device-MSC bulk pipes against the local endpoints.

Mirrors FSP's usb_pstd_pipe_table writes condensed for the MSC case. PIPE3 = bulk-IN, PIPE4 = bulk-OUT, matching the host-MSC layer for symmetry.

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 185 of file ra8_usb_pmsc.c.

References g_usb_pmsc_state, internal_bulk_max_packet(), k_ra8_pmsc_ep_bulk_in, k_ra8_pmsc_ep_bulk_out, k_ra8_pmsc_pipe_bulk_in, k_ra8_pmsc_pipe_bulk_out, k_ra8_usb_ep_dir_in, k_ra8_usb_ep_dir_out, k_ra8_usb_ep_type_bulk, and ra8_usb_configure_endpoint().

Referenced by ra8_usb_pmsc_init().

◆ internal_copy_bytes()

void internal_copy_bytes ( uint8_t * dst,
const uint8_t * src,
uint32_t len )
static

Copy len bytes from src to dst byte-by-byte.

See implementation.

Parameters
[in]dstSee implementation.
[in]srcSee implementation.
[in]lenSee 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 272 of file ra8_usb_pmsc.c.

Referenced by ra8_usb_pmsc_feed_cbw().

◆ internal_dispatch_advance_state()

void internal_dispatch_advance_state ( uint32_t data_len)
static

Advance BOT state after a successful CDB dispatch.

See implementation.

Parameters
[in]data_lenSee 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 418 of file ra8_usb_pmsc.c.

References g_usb_pmsc_state, k_ra8_pmsc_state_csw_tx, k_ra8_pmsc_state_data_rx, and k_ra8_pmsc_state_data_tx.

Referenced by ra8_usb_pmsc_dispatch_command().

◆ internal_dispatch_preconditions()

ra8_err_t internal_dispatch_preconditions ( uint32_t data_buf_capacity)
static

Validate dispatch_command preconditions (driver state + bot phase + buffer capacity).

See implementation.

Parameters
[in]data_buf_capacitySee 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_pmsc.c.

References g_usb_pmsc_state, k_ra8_err_invalid_size, k_ra8_err_invalid_state, k_ra8_ok, and k_ra8_pmsc_state_cdb_decode.

Referenced by ra8_usb_pmsc_dispatch_command().

◆ internal_dispatch_scsi()

ra8_err_t internal_dispatch_scsi ( uint8_t * data_buf,
uint32_t data_buf_capacity,
uint32_t * data_len,
ra8_usb_pmsc_csw_status_t * csw_status )
static

Dispatch the cached CDB to the right SCSI handler.

Helper for ra8_usb_pmsc_dispatch_command. Returns k_ra8_ok and a populated *data_len on a supported opcode; sets *csw_status to failed on an unsupported opcode and leaves *data_len zero.

Parameters
[in]data_bufSee implementation.
[in]data_buf_capacitySee implementation.
[in]data_lenSee implementation.
[in]csw_statusSee 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 343 of file ra8_usb_pmsc.c.

References g_usb_pmsc_state, k_ra8_ok, k_ra8_pmsc_cdb_off_opcode, k_ra8_pmsc_csw_status_failed, k_ra8_pmsc_scsi_inquiry, k_ra8_pmsc_scsi_mode_sense_6, k_ra8_pmsc_scsi_read_10, k_ra8_pmsc_scsi_read_capacity_10, k_ra8_pmsc_scsi_request_sense, k_ra8_pmsc_scsi_test_unit_ready, k_ra8_pmsc_scsi_write_10, priv_handle_inquiry(), priv_handle_mode_sense(), priv_handle_read10(), priv_handle_read_capacity(), priv_handle_request_sense(), and priv_handle_write10().

Referenced by ra8_usb_pmsc_dispatch_command().

◆ internal_pack_u32_le()

void internal_pack_u32_le ( uint32_t value,
uint8_t * dst )
static

Pack a uint32 into 4 little-endian bytes.

See implementation.

Parameters
[in]valueSee implementation.
[in]dstSee 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 219 of file ra8_usb_pmsc.c.

References k_ra8_pmsc_byte_mask, k_ra8_pmsc_shift_byte0, k_ra8_pmsc_shift_byte1, k_ra8_pmsc_shift_byte2, and k_ra8_pmsc_shift_byte3.

Referenced by ra8_usb_pmsc_build_csw().

◆ internal_unpack_u32_le()

uint32_t internal_unpack_u32_le ( const uint8_t * src)
static

Unpack a uint32 from 4 little-endian bytes.

See implementation.

Parameters
[in]srcSee 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 242 of file ra8_usb_pmsc.c.

References k_ra8_pmsc_shift_byte0, k_ra8_pmsc_shift_byte1, k_ra8_pmsc_shift_byte2, and k_ra8_pmsc_shift_byte3.

Referenced by ra8_usb_pmsc_feed_cbw().

◆ priv_zero_bytes()

void priv_zero_bytes ( uint8_t * dst,
uint32_t len )

Zero len bytes at dst byte-by-byte.

Avoids memset so the project's clang-tidy clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling gate stays clean. Defined in ra8_usb_pmsc.c, shared with the SCSI handler TU.

Parameters
[out]dstDestination buffer (non-null, at least len bytes).
[in]lenByte count to clear.
Precondition
dst is non-null and spans at least len bytes.
Module state is consistent.
Postcondition
All len bytes at dst are zero.
No other state mutated.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 250 of file ra8_usb_pmsc.c.

Referenced by priv_handle_inquiry(), priv_handle_mode_sense(), priv_handle_read_capacity(), priv_handle_request_sense(), ra8_usb_pmsc_build_csw(), and ra8_usb_pmsc_init().

◆ ra8_usb_pmsc_attach_storage()

ra8_err_t ra8_usb_pmsc_attach_storage ( const ra8_usb_pmsc_storage_t * storage)
nodiscard

Bind a caller-owned storage backend to the device-MSC class.

The four function pointers in storage are validated for NULL and the struct is copied into internal state. After this call the BOT state machine can answer SCSI commands the host issues.

Parameters
[in]storageStorage backend snapshot. Copied by value.
Returns
ra8_err_t error code.
Return values
k_ra8_okBackend installed.
k_ra8_err_invalid_stateDriver not initialized.
k_ra8_err_null_ptrstorage was NULL or any callback was NULL.
Precondition
ra8_usb_pmsc_init has run.
All four callbacks non-NULL.
Postcondition
Subsequent SCSI commands route through the supplied callbacks.
Note
Not thread-safe.
Since
0.1.0

Definition at line 515 of file ra8_usb_pmsc.c.

References g_usb_pmsc_state, ra8_usb_pmsc_storage_t::get_capacity, ra8_usb_pmsc_storage_t::get_inquiry, k_ra8_err_invalid_state, k_ra8_ok, k_ra8_pmsc_state_idle, RA8_CHECK_NULL_PTR, ra8_log_info, ra8_usb_pmsc_storage_t::read_block, s_tag, and ra8_usb_pmsc_storage_t::write_block.

◆ ra8_usb_pmsc_build_csw()

ra8_err_t ra8_usb_pmsc_build_csw ( ra8_usb_pmsc_csw_status_t csw_status,
uint32_t residue,
uint8_t * out_csw )
nodiscard

Build the 13-byte CSW for the in-flight command.

Test / debug entry point. Production code calls this internally during the CSW_TX phase. The CSW is laid out per USB MSC BBB rev 1.0 sec 5.2: dCSWSignature='USBS', dCSWTag echoed from the CBW, dCSWDataResidue computed from the CBW dCBWDataTransferLength minus the actual byte count produced, bCSWStatus from csw_status.

Parameters
[in]csw_statusStatus byte to embed in the CSW.
[in]residueBytes that were NOT transferred (CBW expected minus actual).
[out]out_cswReceives the 13-byte CSW buffer.
Returns
ra8_err_t error code.
Return values
k_ra8_okCSW constructed.
k_ra8_err_null_ptrout_csw was NULL.
k_ra8_err_invalid_stateDriver not initialized, or no CBW currently in-flight.
Precondition
out_csw non-NULL.
A prior ra8_usb_pmsc_feed_cbw set the dCBWTag we echo.
Postcondition
out_csw[0..3] == 0x55, 0x53, 0x42, 0x53 (CSW signature 'USBS', little-endian on wire).
out_csw[12] == csw_status.
Note
Not thread-safe.
Since
0.1.0

Definition at line 454 of file ra8_usb_pmsc.c.

References g_usb_pmsc_state, internal_pack_u32_le(), k_ra8_err_invalid_state, k_ra8_ok, k_ra8_pmsc_csw_len, k_ra8_pmsc_csw_off_residue, k_ra8_pmsc_csw_off_signature, k_ra8_pmsc_csw_off_status, k_ra8_pmsc_csw_off_tag, k_ra8_pmsc_csw_signature, k_ra8_pmsc_state_idle, priv_zero_bytes(), RA8_CHECK_NULL_PTR, and s_tag.

◆ ra8_usb_pmsc_close()

ra8_err_t ra8_usb_pmsc_close ( void )
nodiscard

Tear down the device-MSC 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_device_deinit ran; D+ pull-up dropped; subsequent device-MSC API calls return k_ra8_err_invalid_state.
Note
Not thread-safe.
Since
0.1.0

Definition at line 568 of file ra8_usb_pmsc.c.

References g_usb_pmsc_state, k_ra8_err_invalid_state, k_ra8_pmsc_state_idle, ra8_usb_device_attach(), and ra8_usb_device_deinit().

◆ ra8_usb_pmsc_dispatch_command()

ra8_err_t ra8_usb_pmsc_dispatch_command ( uint8_t * data_buf,
uint32_t data_buf_capacity,
uint32_t * data_len,
ra8_usb_pmsc_csw_status_t * csw_status )
nodiscard

Run the SCSI command currently parked in the BOT state.

Test / debug entry point. After ra8_usb_pmsc_feed_cbw accepts a CBW, this routine invokes the storage backend (if any) and stages the data-phase output buffer / pulls the CSW status byte. On unsupported opcodes the CSW status is set to k_ra8_pmsc_csw_status_failed.

Parameters
[out]data_bufBuffer that receives the data-IN payload (or provides the data-OUT payload). Caller sized to at least data_buf_capacity bytes.
[in]data_buf_capacityCapacity of data_buf in bytes.
[out]data_lenReceives the actual data byte count produced / consumed.
[out]csw_statusReceives the CSW status byte the device will emit at the end of the transaction.
Returns
ra8_err_t error code.
Return values
k_ra8_okCommand dispatched (the CSW status byte may still be k_ra8_pmsc_csw_status_failed).
k_ra8_err_null_ptrAny output pointer was NULL.
k_ra8_err_invalid_stateDriver not initialized, storage not attached, or no CBW currently in-flight.
k_ra8_err_invalid_sizedata_buf_capacity was 0.
Precondition
ra8_usb_pmsc_feed_cbw returned k_ra8_ok immediately prior.
Postcondition
On success *data_len is the byte count to push / pull and *csw_status is the CSW status byte.
Note
Not thread-safe.
Since
0.1.0

Definition at line 429 of file ra8_usb_pmsc.c.

References internal_dispatch_advance_state(), internal_dispatch_preconditions(), internal_dispatch_scsi(), k_ra8_ok, k_ra8_pmsc_csw_status_failed, k_ra8_pmsc_csw_status_passed, RA8_CHECK_NULL_PTR, and s_tag.

◆ ra8_usb_pmsc_feed_cbw()

ra8_err_t ra8_usb_pmsc_feed_cbw ( const uint8_t * cbw)
nodiscard

Inject a CBW directly into the BOT state machine.

Test / debug entry point. Production code receives CBWs from the bulk-OUT pipe; tests bypass the FIFO and feed the 31-byte buffer directly. Returns k_ra8_err_invalid_arg on signature mismatch (USB MSC BBB rev 1.0 sec 6.2.1 "Valid CBW").

Parameters
[in]cbwPointer to a 31-byte CBW.
Returns
ra8_err_t error code.
Return values
k_ra8_okCBW accepted; state machine now in CDB_DECODE.
k_ra8_err_null_ptrcbw was NULL.
k_ra8_err_invalid_stateDriver not initialized, or storage not attached.
k_ra8_err_invalid_argSignature mismatch (CBW invalid). In this case the BOT machine transitions to a phase-error CSW_TX as required by USB MSC BBB rev 1.0 sec 6.6.1 "CBW Not Valid".
Precondition
cbw non-NULL.
Postcondition
On k_ra8_ok the cached SCSI opcode and data-length are valid for ra8_usb_pmsc_dispatch_command.
Note
Not thread-safe.
Since
0.1.0

Definition at line 284 of file ra8_usb_pmsc.c.

References g_usb_pmsc_state, internal_copy_bytes(), internal_unpack_u32_le(), k_ra8_err_invalid_arg, k_ra8_err_invalid_state, k_ra8_ok, k_ra8_pmsc_cbw_flag_data_in, k_ra8_pmsc_cbw_off_cdb, k_ra8_pmsc_cbw_off_cdb_length, k_ra8_pmsc_cbw_off_data_length, k_ra8_pmsc_cbw_off_flags, k_ra8_pmsc_cbw_off_lun, k_ra8_pmsc_cbw_off_signature, k_ra8_pmsc_cbw_off_tag, k_ra8_pmsc_cbw_signature, k_ra8_pmsc_cdb_field_mask, k_ra8_pmsc_cdb_max_len, k_ra8_pmsc_lun_field_mask, k_ra8_pmsc_state_cdb_decode, k_ra8_pmsc_state_csw_tx, RA8_CHECK_NULL_PTR, and s_tag.

◆ ra8_usb_pmsc_init()

ra8_err_t ra8_usb_pmsc_init ( ra8_usb_speed_t speed)
nodiscard

Bring up the device-MSC driver on a chosen USB controller.

Initialises the underlying ra8_usb driver in DEVICE mode for speed, configures the bulk-IN / bulk-OUT pipes (PIPE3 / PIPE4) with the speed-appropriate maximum packet size, primes the BOT state machine to the IDLE state, and zeroes the BOT command tag counter. 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_okDevice-MSC ready, awaiting attach_storage.
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 BOT state machine in IDLE; storage backend NULL.
Note
Not thread-safe.
See also
ra8_usb_pmsc_attach_storage
ra8_usb_pmsc_close
Since
0.1.0

Definition at line 538 of file ra8_usb_pmsc.c.

References g_usb_pmsc_state, internal_configure_pipes(), k_ra8_err_hw_init_failed, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_pmsc_cdb_max_len, k_ra8_pmsc_initial_tag, k_ra8_pmsc_state_idle, k_ra8_usb_speed_fs, k_ra8_usb_speed_hs, priv_zero_bytes(), ra8_log_error_val, ra8_log_info_val, ra8_usb_device_init(), and s_tag.

◆ ra8_usb_pmsc_step()

ra8_err_t ra8_usb_pmsc_step ( void )
nodiscard

Drive the BOT (Bulk-Only Transport) state machine forward by one step.

Production code calls this from the bulk-OUT completion ISR. The state machine cycles through:

  • IDLE: wait for the bulk-OUT pipe to deliver a 31-byte CBW.
  • CBW_RX: parse the CBW, validate the 'USBC' signature, decode the CDB.
  • CDB_DECODE: dispatch to one of the SCSI command handlers (INQUIRY / READ_CAPACITY / READ(10) / WRITE(10) / TEST_UNIT_READY / REQUEST_SENSE / MODE_SENSE(6)).
  • DATA_TX: push read data on bulk-IN.
  • DATA_RX: drain write data from bulk-OUT.
  • CSW_TX: push the 13-byte CSW on bulk-IN.
  • IDLE.

Each call advances by exactly one phase; the caller pumps the state machine until it idles back to CBW reception.

Returns
ra8_err_t error code.
Return values
k_ra8_okStep advanced.
k_ra8_err_invalid_stateDriver not initialized, or storage not attached.
Precondition
ra8_usb_pmsc_init has run.
ra8_usb_pmsc_attach_storage has run.
Postcondition
Internal BOT state machine advances by one phase.
Note
Not thread-safe.
Since
0.1.0

Definition at line 470 of file ra8_usb_pmsc.c.

References g_usb_pmsc_state, k_ra8_err_invalid_state, k_ra8_ok, k_ra8_pmsc_state_cbw_rx, k_ra8_pmsc_state_cdb_decode, k_ra8_pmsc_state_csw_tx, k_ra8_pmsc_state_data_rx, k_ra8_pmsc_state_data_tx, and k_ra8_pmsc_state_idle.

Variable Documentation

◆ g_usb_pmsc_state

ra8_usb_pmsc_state_data_t g_usb_pmsc_state = {}

Singleton shadow state shared by both device-MSC TUs.

Defined in ra8_usb_pmsc.c; the SCSI handler TU reads the cached CDB and storage backend through this extern declaration.

Note
Single-instance, single-LUN; not thread-safe.
Warning
Direct modification outside the driver TUs is forbidden.
Since
0.1.0

Definition at line 139 of file ra8_usb_pmsc.c.

Referenced by internal_configure_pipes(), internal_dispatch_advance_state(), internal_dispatch_preconditions(), internal_dispatch_scsi(), priv_handle_inquiry(), priv_handle_read10(), priv_handle_read_capacity(), priv_handle_write10(), ra8_usb_pmsc_attach_storage(), ra8_usb_pmsc_build_csw(), ra8_usb_pmsc_close(), ra8_usb_pmsc_feed_cbw(), ra8_usb_pmsc_init(), and ra8_usb_pmsc_step().

◆ s_tag

const char* s_tag = "USBPMSC"
static

Definition at line 55 of file ra8_usb_pmsc.c.