ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_usb_pprn.c
Go to the documentation of this file.
1
21
22#include "ra8_usb_pprn.h"
23
24#include <stdint.h>
25
26#include "ra8_attributes.h"
27#include "ra8_check.h"
28#include "ra8_err.h"
29#include "ra8_log.h"
30#include "ra8_usb.h"
31
32static const char* s_tag = "USBPPRN";
33
34/* =============================================================================
35 * Internal constants
36 * =============================================================================
37 */
38
52
60typedef enum : uint8_t {
62 (uint8_t)((1U << 4U) | (1U << 3U)),
64
65/* =============================================================================
66 * Internal state
67 * =============================================================================
68 */
69
86
88
89/* =============================================================================
90 * Internal helpers
91 * =============================================================================
92 */
93
115
130{
131 const uint16_t mp = internal_bulk_max_packet(speed);
132
133 /* Both calls receive the init-validated speed and compile-time pipe tuples
134 * that satisfy every `ra8_usb_configure_endpoint` argument guard. */
135 (void)ra8_usb_configure_endpoint(speed,
140 mp);
141 (void)ra8_usb_configure_endpoint(speed,
146 mp);
147}
148
163{
164 s_state.speed = speed;
165 s_state.bulk_max_packet = internal_bulk_max_packet(speed);
166 s_state.desc = nullptr;
167 s_state.desc_len = 0U;
168 s_state.device_id = nullptr;
169 s_state.device_id_len = 0U;
170 s_state.port_status = (uint8_t)k_ra8_pprn_default_port_status;
171 s_state.setup_cb = nullptr;
172 s_state.setup_ctx = nullptr;
173}
174
190static bool internal_is_known_class_request(uint8_t b_request)
191{
192 return (b_request == k_ra8_pprn_req_get_device_id) ||
193 (b_request == k_ra8_pprn_req_get_port_status) || (b_request == k_ra8_pprn_req_soft_reset);
194}
195
196/* =============================================================================
197 * Lifecycle
198 * =============================================================================
199 */
200
202{
203 if ((speed != k_ra8_usb_speed_fs) && (speed != k_ra8_usb_speed_hs)) {
205 }
206 const ra8_err_t usb_err = ra8_usb_device_init(speed);
207 if (usb_err != k_ra8_ok) {
208 ra8_log_error_val(s_tag, "ra8_usb_device_init failed", (uint32_t)usb_err);
210 }
212
214 s_state.initialized = true;
215 ra8_log_info_val(s_tag, "device-Printer ready", (uint32_t)speed);
216 return k_ra8_ok;
217}
218
220{
221 if (!s_state.initialized) {
223 }
224 (void)ra8_usb_device_attach(s_state.speed, false);
225 const ra8_err_t err = ra8_usb_device_deinit(s_state.speed);
226 s_state.initialized = false;
227 s_state.desc = nullptr;
228 s_state.device_id = nullptr;
229 s_state.setup_cb = nullptr;
230 s_state.setup_ctx = nullptr;
231 return err;
232}
233
234/* =============================================================================
235 * Descriptor + identity handoff
236 * =============================================================================
237 */
238
240 uint16_t desc_len,
241 const uint8_t* device_id,
242 uint16_t device_id_len)
243{
244 if (!s_state.initialized) {
246 }
247 RA8_CHECK_NULL_PTR(desc, s_tag, "set_descriptors: desc");
248 if (desc_len == 0U) {
250 }
251 /* device_id is optional, but the (ptr, len) pair must agree. */
252 const bool id_ptr_set = (device_id != nullptr);
253 const bool id_len_set = (device_id_len != 0U);
254 if (id_ptr_set != id_len_set) {
256 }
257 s_state.desc = desc;
258 s_state.desc_len = desc_len;
259 s_state.device_id = device_id;
260 s_state.device_id_len = device_id_len;
261 return k_ra8_ok;
262}
263
264/* =============================================================================
265 * Print data transport
266 * =============================================================================
267 */
268
269ra8_err_t ra8_usb_pprn_recv(uint8_t* buf, uint16_t max_len, uint16_t* got_len)
270{
271 RA8_CHECK_NULL_PTR(buf, s_tag, "recv: buf");
272 RA8_CHECK_NULL_PTR(got_len, s_tag, "recv: got_len");
273 if (!s_state.initialized) {
275 }
276 if (max_len == 0U) {
278 }
279 uint16_t inout_len = max_len;
280 const ra8_err_t err =
281 ra8_usb_queue_out(s_state.speed, k_ra8_pprn_pipe_bulk_out, buf, &inout_len, true);
282 if (err == k_ra8_ok) {
283 *got_len = inout_len;
284 } else {
285 *got_len = 0U;
286 }
287 return err;
288}
289
290ra8_err_t ra8_usb_pprn_send(const uint8_t* data, uint16_t len)
291{
292 if (!s_state.initialized) {
294 }
295 if ((data == nullptr) && (len != 0U)) {
296 return k_ra8_err_null_ptr;
297 }
298 if ((len == 0U) || (len > s_state.bulk_max_packet)) {
300 }
301 return ra8_usb_queue_in(s_state.speed, k_ra8_pprn_pipe_bulk_in, data, len);
302}
303
304/* =============================================================================
305 * Port-status shadow
306 * =============================================================================
307 */
308
310{
311 if (!s_state.initialized) {
313 }
314 s_state.port_status = status_byte;
315 return k_ra8_ok;
316}
317
319{
320 RA8_CHECK_NULL_PTR(out_status, s_tag, "get_port_status: out_status");
321 if (!s_state.initialized) {
323 }
324 *out_status = s_state.port_status;
325 return k_ra8_ok;
326}
327
328/* =============================================================================
329 * Setup-handler attach
330 * =============================================================================
331 */
332
334{
335 if (!s_state.initialized) {
337 }
338 s_state.setup_cb = setup_fn;
339 s_state.setup_ctx = ctx;
340 return k_ra8_ok;
341}
342
343/* =============================================================================
344 * Class SETUP dispatch
345 * =============================================================================
346 */
347
349{
350 RA8_CHECK_NULL_PTR(setup, s_tag, "handle_setup: setup");
351 if (!s_state.initialized) {
353 }
357 }
360 }
361 /* SOFT_RESET (USB Printer 1.1 sec 4.2.3) flushes both bulk pipes;
362 * implemented here as a no-op shadow refresh so the application can
363 * re-arm pipes from its callback if it wants to. */
364 if (s_state.setup_cb != nullptr) {
365 const ra8_err_t cb_err = s_state.setup_cb(s_state.setup_ctx, setup);
366 if (cb_err != k_ra8_ok) {
367 return ra8_usb_control_response(s_state.speed, false);
368 }
369 }
370 return ra8_usb_control_response(s_state.speed, true);
371}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Error Code Definitions for ra8-firmware.
@ k_ra8_err_hw_init_failed
Hardware peripheral failed to initialise.
Definition ra8_err.h:290
@ k_ra8_err_not_supported
Requested feature not compiled in, not wired, or not supported by this MCU variant.
Definition ra8_err.h:180
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
Definition ra8_err.h:478
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_info_val(tag, message, value)
RA8 log info val.
Definition ra8_log.h:366
#define ra8_log_error_val(tag, message, value)
RA8 log error val.
Definition ra8_log.h:337
static uint32_t s_state
Native USB controller driver public API (device + host modes).
ra8_err_t ra8_usb_queue_out(ra8_usb_speed_t speed, uint8_t pipe_num, uint8_t *out_buf, uint16_t *inout_len, bool rearm)
Drain an OUT transfer (host -> device) from pipe_num.
@ k_ra8_usb_ep_type_bulk
Bulk transfer.
ra8_err_t ra8_usb_device_init(ra8_usb_speed_t speed)
Bring up a USB controller in device mode.
ra8_err_t ra8_usb_control_response(ra8_usb_speed_t speed, bool accept)
Issue a control-transfer status response on EP0.
ra8_err_t ra8_usb_device_deinit(ra8_usb_speed_t speed)
Tear down a USB controller and drop its MSTP reference.
ra8_err_t ra8_usb_configure_endpoint(ra8_usb_speed_t speed, uint8_t pipe_num, uint8_t ep_addr, ra8_usb_ep_dir_t dir, ra8_usb_ep_type_t type, uint16_t max_packet)
Configure a non-control PIPE for IN or OUT bulk / interrupt / iso transfers.
ra8_err_t ra8_usb_device_attach(ra8_usb_speed_t speed, bool attached)
Raise / drop the D+ pull-up to advertise the device to the host.
@ k_ra8_usb_ep_dir_in
Device -> host.
@ k_ra8_usb_ep_dir_out
Host -> device.
ra8_usb_speed_t
Selects which controller instance the call targets.
@ k_ra8_usb_speed_hs
High-Speed controller (USBHS @ 0x40351000).
@ k_ra8_usb_speed_fs
Full-Speed controller (USBFS @ 0x40250000).
ra8_err_t ra8_usb_queue_in(ra8_usb_speed_t speed, uint8_t pipe_num, const uint8_t *data, uint16_t len)
Queue an IN transfer (device -> host) on pipe_num.
static ra8_err_t internal_configure_pipes(void)
Configure the host-Audio iso pipes against the attached device's endpoints.
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_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_handle_setup(const ra8_usb_setup_t *setup)
Process a class-specific SETUP packet on EP0.
ra8_usb_pprn_default_status_t
Spec defaults the class layer seeds at init.
@ k_ra8_pprn_default_port_status
RA8 pprn default port status.
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_usb_pprn_setup_field_t
Constants used to recognise printer class-specific SETUPs.
@ k_ra8_pprn_bm_class_iface_in
Class | Iface | In.
@ k_ra8_pprn_bm_class_iface_out
Class | Iface | Out.
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.
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.
static uint16_t internal_bulk_max_packet(ra8_usb_speed_t speed)
Pick the bulk-max-packet ceiling matching the negotiated speed.
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_close(void)
Tear down the device-Printer function and release the controller.
ra8_err_t ra8_usb_pprn_send(const uint8_t *data, uint16_t len)
Push outbound printer-status bytes on the bulk-IN endpoint.
Native USB device-side Printer class layer.
@ k_ra8_pprn_pipe_bulk_in
PIPE4 -> EP2 IN (status).
@ k_ra8_pprn_pipe_bulk_out
PIPE3 -> EP1 OUT (print data).
ra8_err_t(* ra8_usb_pprn_setup_fn_t)(void *ctx, const ra8_usb_setup_t *setup)
Caller-supplied printer class-setup handler signature.
@ k_ra8_pprn_bulk_max_packet_fs
Bulk size at FS.
@ k_ra8_pprn_bulk_max_packet_hs
Bulk size at HS.
@ k_ra8_pprn_ep_bulk_in_addr
EP2 IN address.
@ k_ra8_pprn_ep_bulk_out_addr
EP1 OUT address.
@ k_ra8_pprn_req_soft_reset
SOFT_RESET.
@ k_ra8_pprn_req_get_device_id
GET_DEVICE_ID.
@ k_ra8_pprn_req_get_port_status
GET_PORT_STATUS.
Singleton shadow state for the device-Printer function.
bool initialized
True after init.
uint16_t desc_len
Descriptor blob byte len.
void * setup_ctx
Class handler context.
uint8_t port_status
Current port-status byte.
const uint8_t * device_id
Cached device-ID payload.
uint16_t device_id_len
Device-ID byte length.
ra8_usb_pprn_setup_fn_t setup_cb
Application class handler.
ra8_usb_speed_t speed
Underlying controller.
const uint8_t * desc
Cached descriptor blob.
uint16_t bulk_max_packet
Pipe max-packet size.
Decoded 8-byte USB SETUP packet.
uint8_t b_request
bRequest code.
uint8_t bm_request_type
Request direction / type / recipient.