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

Native USB device-side Printer class layer implementation. More...

#include "ra8_usb_pprn.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_pprn.c:

Go to the source code of this file.

Data Structures

struct  ra8_usb_pprn_state_t
 Singleton shadow state for the device-Printer function. More...

Enumerations

enum  ra8_usb_pprn_setup_field_t : uint8_t {
  k_ra8_pprn_bm_class_iface_in = 0xA1U ,
  k_ra8_pprn_bm_class_iface_out = 0x21U
}
 Constants used to recognise printer class-specific SETUPs. More...
enum  ra8_usb_pprn_default_status_t : uint8_t { k_ra8_pprn_default_port_status }
 Spec defaults the class layer seeds at init. 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 (ra8_usb_speed_t speed)
 Configure the two bulk pipes.
static void internal_reset_shadow (ra8_usb_speed_t speed)
 Reset shadow state to spec defaults.
static bool internal_is_known_class_request (uint8_t b_request)
 Recognise a printer class request code we forward.
ra8_err_t ra8_usb_pprn_init (ra8_usb_speed_t speed)
 Bring up the device-Printer function on a chosen USB controller.
ra8_err_t ra8_usb_pprn_close (void)
 Tear down the device-Printer function and release the controller.
ra8_err_t ra8_usb_pprn_set_descriptors (const uint8_t *desc, uint16_t desc_len, const uint8_t *device_id, uint16_t device_id_len)
 Install the caller-supplied descriptor blob and IEEE 1284 device-ID string.
ra8_err_t ra8_usb_pprn_recv (uint8_t *buf, uint16_t max_len, uint16_t *got_len)
 Drain inbound print-job data from the bulk-OUT endpoint.
ra8_err_t ra8_usb_pprn_send (const uint8_t *data, uint16_t len)
 Push outbound printer-status bytes on the bulk-IN endpoint.
ra8_err_t ra8_usb_pprn_set_port_status (uint8_t status_byte)
 Update the local port-status byte returned by GET_PORT_STATUS.
ra8_err_t ra8_usb_pprn_get_port_status (uint8_t *out_status)
 Read the current port-status byte.
ra8_err_t ra8_usb_pprn_attach_setup_handler (ra8_usb_pprn_setup_fn_t setup_fn, void *ctx)
 Register the application's printer class-setup handler.
ra8_err_t ra8_usb_pprn_handle_setup (const ra8_usb_setup_t *setup)
 Process a class-specific SETUP packet on EP0.

Variables

static const char * s_tag = "USBPPRN"
static ra8_usb_pprn_state_t s_state = {}

Detailed Description

Native USB device-side Printer class layer implementation.

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

Glues the device-mode ra8_usb driver to a USB Printer 1.1 function so the EK-RA8D2 enumerates as a uni-directional or bi-directional printer gadget. This file is the native peripheral-Printer class layer; FSP's r_usb_pprn_driver.c is reference material only, nothing is pulled in verbatim.

Reference: USB Printer Class 1.1 sec 4.2 "Class Specific Requests" (GET_DEVICE_ID = 0x00, GET_PORT_STATUS = 0x01, SOFT_RESET = 0x02).

Definition in file ra8_usb_pprn.c.

Enumeration Type Documentation

◆ ra8_usb_pprn_default_status_t

Spec defaults the class layer seeds at init.

"select | not-error" -> printer online, no error, paper-empty bit clear. Per USB Printer 1.1 sec 4.2.2.

Enumerator
k_ra8_pprn_default_port_status 

RA8 pprn default port status.

Definition at line 60 of file ra8_usb_pprn.c.

◆ ra8_usb_pprn_setup_field_t

Constants used to recognise printer class-specific SETUPs.

Per USB Printer 1.1 sec 4.2 "Class Specific Requests" all printer requests are interface-recipient class envelopes. IN side (0xA1) for GET_DEVICE_ID / GET_PORT_STATUS, OUT side (0x21) for SOFT_RESET (no data).

Enumerator
k_ra8_pprn_bm_class_iface_in 

Class | Iface | In.

k_ra8_pprn_bm_class_iface_out 

Class | Iface | Out.

Definition at line 48 of file ra8_usb_pprn.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_pprn_bulk_max_packet_hsspeed is k_ra8_usb_speed_hs.
k_ra8_pprn_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 110 of file ra8_usb_pprn.c.

References k_ra8_pprn_bulk_max_packet_fs, k_ra8_pprn_bulk_max_packet_hs, and k_ra8_usb_speed_hs.

Referenced by internal_configure_pipes(), and internal_reset_shadow().

◆ internal_configure_pipes()

void internal_configure_pipes ( ra8_usb_speed_t speed)
static

Configure the two bulk pipes.

See implementation.

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

References internal_bulk_max_packet(), k_ra8_pprn_ep_bulk_in_addr, k_ra8_pprn_ep_bulk_out_addr, k_ra8_pprn_pipe_bulk_in, k_ra8_pprn_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().

◆ internal_is_known_class_request()

bool internal_is_known_class_request ( uint8_t b_request)
static

Recognise a printer class request code we forward.

See implementation.

Parameters
[in]b_requestSee 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 190 of file ra8_usb_pprn.c.

References k_ra8_pprn_req_get_device_id, k_ra8_pprn_req_get_port_status, and k_ra8_pprn_req_soft_reset.

Referenced by ra8_usb_pprn_handle_setup().

◆ internal_reset_shadow()

void internal_reset_shadow ( ra8_usb_speed_t speed)
static

Reset shadow state to spec defaults.

See implementation.

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

References internal_bulk_max_packet(), k_ra8_pprn_default_port_status, and s_state.

Referenced by ra8_usb_pprn_init().

◆ ra8_usb_pprn_attach_setup_handler()

ra8_err_t ra8_usb_pprn_attach_setup_handler ( ra8_usb_pprn_setup_fn_t setup_fn,
void * ctx )
nodiscard

Register the application's printer class-setup handler.

Pass NULL for setup_fn to detach. The class layer pre-decodes the SETUP envelope and forwards it if its bmRequestType indicates a class-recipient-interface request and its bRequest is one of GET_DEVICE_ID / GET_PORT_STATUS / SOFT_RESET.

Parameters
[in]setup_fnApplication's handler. NULL detaches.
[in]ctxContext pointer threaded back into setup_fn.
Returns
ra8_err_t error code.
Return values
k_ra8_okHandler installed.
k_ra8_err_invalid_stateDriver not initialized.
Precondition
ra8_usb_pprn_init succeeded.
Postcondition
On the next class SETUP, setup_fn(ctx, &setup) fires.
Note
Not thread-safe.
Since
0.1.0

Definition at line 333 of file ra8_usb_pprn.c.

References k_ra8_err_invalid_state, k_ra8_ok, and s_state.

Referenced by demo_usb_bringup().

◆ ra8_usb_pprn_close()

ra8_err_t ra8_usb_pprn_close ( void )
nodiscard

Tear down the device-Printer function 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-Printer API calls return k_ra8_err_invalid_state.
Note
Not thread-safe.
Since
0.1.0

Definition at line 219 of file ra8_usb_pprn.c.

References k_ra8_err_invalid_state, ra8_usb_device_attach(), ra8_usb_device_deinit(), and s_state.

◆ ra8_usb_pprn_get_port_status()

ra8_err_t ra8_usb_pprn_get_port_status ( uint8_t * out_status)
nodiscard

Read the current port-status byte.

Parameters
[out]out_statusReceives the current status byte.
Returns
ra8_err_t error code.
Return values
k_ra8_okValue copied.
k_ra8_err_invalid_stateDriver not initialized.
k_ra8_err_null_ptrout_status was NULL.
Precondition
out_status non-NULL.
Postcondition
No internal state mutated.
Note
Not thread-safe.
Since
0.1.0

Definition at line 318 of file ra8_usb_pprn.c.

References k_ra8_err_invalid_state, k_ra8_ok, RA8_CHECK_NULL_PTR, s_state, and s_tag.

Referenced by demo_printer_setup().

◆ ra8_usb_pprn_handle_setup()

ra8_err_t ra8_usb_pprn_handle_setup ( const ra8_usb_setup_t * setup)
nodiscard

Process a class-specific SETUP packet on EP0.

Switches on b_request: SOFT_RESET re-arms the bulk pipes internally; GET_DEVICE_ID / GET_PORT_STATUS forward to the registered application handler if any (the application normally queues the device-ID payload or the port-status byte itself). Standard (non-class) SETUPs are rejected with k_ra8_err_not_supported.

Parameters
[in]setupThe SETUP packet returned by ra8_usb_read_setup_if_valid.
Returns
ra8_err_t error code.
Return values
k_ra8_okSETUP handled (status stage queued internally).
k_ra8_err_invalid_stateDriver not initialized.
k_ra8_err_null_ptrsetup was NULL.
k_ra8_err_not_supportedbRequest is not a printer class request.
Precondition
ra8_usb_pprn_init succeeded.
Postcondition
Internal port-status shadow may have been refreshed by the application callback.
Note
Call from the CTRT ISR path of ra8_usb.
Since
0.1.0

Definition at line 348 of file ra8_usb_pprn.c.

References ra8_usb_setup_t::b_request, ra8_usb_setup_t::bm_request_type, internal_is_known_class_request(), k_ra8_err_invalid_state, k_ra8_err_not_supported, k_ra8_ok, k_ra8_pprn_bm_class_iface_in, k_ra8_pprn_bm_class_iface_out, RA8_CHECK_NULL_PTR, ra8_usb_control_response(), s_state, and s_tag.

Referenced by demo_dispatch_setup().

◆ ra8_usb_pprn_init()

ra8_err_t ra8_usb_pprn_init ( ra8_usb_speed_t speed)
nodiscard

Bring up the device-Printer function on a chosen USB controller.

Initialises the underlying ra8_usb driver in DEVICE mode for speed, configures PIPE3 (bulk OUT) and PIPE4 (bulk IN), seeds the port-status shadow to "select | not-error" (online, no error, no paper-out), and leaves the D+ pull-up dropped. The caller raises it via ra8_usb_device_attach once descriptors are set.

Parameters
[in]speedWhich USB controller (FS or HS).
Returns
ra8_err_t error code.
Return values
k_ra8_okDevice-Printer ready.
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
Internal state machine armed; descriptor pointer cleared.
Pipe3 / pipe4 configured at the speed's default packet size.
Note
Not thread-safe.
See also
ra8_usb_pprn_set_descriptors
ra8_usb_pprn_close
Since
0.1.0

Definition at line 201 of file ra8_usb_pprn.c.

References internal_configure_pipes(), internal_reset_shadow(), k_ra8_err_hw_init_failed, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_usb_speed_fs, k_ra8_usb_speed_hs, ra8_log_error_val, ra8_log_info_val, ra8_usb_device_init(), s_state, and s_tag.

Referenced by demo_usb_bringup().

◆ ra8_usb_pprn_recv()

ra8_err_t ra8_usb_pprn_recv ( uint8_t * buf,
uint16_t max_len,
uint16_t * got_len )
nodiscard

Drain inbound print-job data from the bulk-OUT endpoint.

Parameters
[out]bufReceive buffer.
[in]max_lenCapacity of buf, > 0.
[out]got_lenReceives the number of bytes actually placed.
Returns
ra8_err_t error code.
Return values
k_ra8_okBytes drained.
k_ra8_err_no_dataPipe was empty.
k_ra8_err_null_ptrbuf or got_len was NULL.
k_ra8_err_invalid_stateDriver not initialized.
k_ra8_err_invalid_argmax_len == 0.
Precondition
ra8_usb_pprn_init succeeded.
Postcondition
On success *got_len reflects the actual byte count.
Note
Not thread-safe.
Since
0.1.0

Definition at line 269 of file ra8_usb_pprn.c.

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

Referenced by demo_drain_print_job().

◆ ra8_usb_pprn_send()

ra8_err_t ra8_usb_pprn_send ( const uint8_t * data,
uint16_t len )
nodiscard

Push outbound printer-status bytes on the bulk-IN endpoint.

Only meaningful on a bi-directional printer interface (protocol 0x02 / 0x03). Uni-directional printers should ignore this function.

Parameters
[in]dataStatus payload.
[in]lenPayload length.
Returns
ra8_err_t error code.
Return values
k_ra8_okBytes queued onto bulk-IN.
k_ra8_err_invalid_stateDriver not initialized.
k_ra8_err_null_ptrdata was NULL with len > 0.
k_ra8_err_invalid_arglen == 0 or larger than the pipe max.
Precondition
ra8_usb_pprn_init succeeded.
Postcondition
len bytes sit on PIPE4.
Note
Not thread-safe.
Since
0.1.0

Definition at line 290 of file ra8_usb_pprn.c.

References k_ra8_err_invalid_arg, k_ra8_err_invalid_state, k_ra8_err_null_ptr, k_ra8_pprn_pipe_bulk_in, ra8_usb_queue_in(), and s_state.

◆ ra8_usb_pprn_set_descriptors()

ra8_err_t ra8_usb_pprn_set_descriptors ( const uint8_t * desc,
uint16_t desc_len,
const uint8_t * device_id,
uint16_t device_id_len )
nodiscard

Install the caller-supplied descriptor blob and IEEE 1284 device-ID string.

The descriptor blob is the configuration / interface / EP descriptor triplet (or quadruplet for bi-directional). The device-ID string is the IEEE 1284-style device-ID payload returned by GET_DEVICE_ID; USB Printer 1.1 sec 4.2.1 "GET_DEVICE_ID" specifies a 2-byte big-endian length followed by the device-ID string. Pass device_id == NULL / device_id_len == 0 if the caller will instead handle GET_DEVICE_ID via its setup callback.

Parameters
[in]descPointer to the caller-owned descriptor blob.
[in]desc_lenByte length of desc.
[in]device_idPointer to the IEEE 1284 device-ID payload (caller-owned, may be NULL).
[in]device_id_lenByte length of device_id.
Returns
ra8_err_t error code.
Return values
k_ra8_okPointers + lengths stored.
k_ra8_err_invalid_stateDriver not initialized.
k_ra8_err_null_ptrdesc was NULL.
k_ra8_err_invalid_argdesc_len == 0, or (device_id != NULL) ^ (device_id_len > 0).
Precondition
ra8_usb_pprn_init succeeded.
Postcondition
GET_DESCRIPTOR(Configuration) and GET_DEVICE_ID requests are served from these buffers.
Note
Not thread-safe.
Since
0.1.0

Definition at line 239 of file ra8_usb_pprn.c.

References k_ra8_err_invalid_arg, k_ra8_err_invalid_state, k_ra8_ok, RA8_CHECK_NULL_PTR, s_state, and s_tag.

Referenced by demo_usb_bringup().

◆ ra8_usb_pprn_set_port_status()

ra8_err_t ra8_usb_pprn_set_port_status ( uint8_t status_byte)
nodiscard

Update the local port-status byte returned by GET_PORT_STATUS.

The shape of the byte is documented in ra8_usb_pprn_port_status_bit_t. The application typically calls this from its job-scheduler (e.g. when the paper sensor flips state).

Parameters
[in]status_byteThe new port-status byte.
Returns
ra8_err_t error code.
Return values
k_ra8_okShadow updated.
k_ra8_err_invalid_stateDriver not initialized.
Precondition
ra8_usb_pprn_init succeeded.
Postcondition
ra8_usb_pprn_get_port_status reflects the new value.
Note
Not thread-safe.
Since
0.1.0

Definition at line 309 of file ra8_usb_pprn.c.

References k_ra8_err_invalid_state, k_ra8_ok, and s_state.

Variable Documentation

◆ s_state

ra8_usb_pprn_state_t s_state = {}
static

Definition at line 87 of file ra8_usb_pprn.c.

◆ s_tag

const char* s_tag = "USBPPRN"
static

Definition at line 32 of file ra8_usb_pprn.c.