ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_usb_hhub.c
Go to the documentation of this file.
1
26
27#include "ra8_usb_hhub.h"
28
29#include <stdint.h>
30
31#include "ra8_attributes.h"
32#include "ra8_check.h"
33#include "ra8_err.h"
34#include "ra8_log.h"
35#include "ra8_usb.h"
36
37static const char* s_tag = "USBHHUB";
38
39/* =============================================================================
40 * Internal constants
41 * =============================================================================
42 */
43
58
63typedef enum : uint8_t {
64 /* Chapter-9 standard requests. */
70 /* HUB class request envelopes (USB 2.0 sec 11.24.1 Table 11-14). */
74 /* Descriptor types in wValue's high byte. */
78
92
97typedef enum : uint8_t {
100
101/* =============================================================================
102 * Internal state
103 * =============================================================================
104 */
105
119
121
122/* =============================================================================
123 * Internal helpers
124 * =============================================================================
125 */
126
143static ra8_err_t internal_setup_get_descriptor(uint8_t desc_type, uint16_t length)
144{
145 const ra8_usb_setup_t setup = {
146 .bm_request_type = k_ra8_hhub_bm_std_dev_in,
147 .b_request = k_ra8_hhub_breq_get_desc,
148 .w_value = (uint16_t)((uint16_t)desc_type << k_ra8_hhub_shift_byte1),
149 .w_index = 0U,
150 .w_length = length,
151 };
152 return ra8_usb_host_setup_request(s_state.speed, &setup);
153}
154
171{
172 const ra8_usb_setup_t setup = {
173 .bm_request_type = k_ra8_hhub_bm_std_dev_out,
174 .b_request = k_ra8_hhub_breq_set_address,
175 .w_value = (uint16_t)address,
176 .w_index = 0U,
177 .w_length = 0U,
178 };
179 return ra8_usb_host_setup_request(s_state.speed, &setup);
180}
181
197static ra8_err_t internal_setup_set_config(uint8_t config_value)
198{
199 const ra8_usb_setup_t setup = {
200 .bm_request_type = k_ra8_hhub_bm_std_dev_out,
201 .b_request = k_ra8_hhub_breq_set_config,
202 .w_value = (uint16_t)config_value,
203 .w_index = 0U,
204 .w_length = 0U,
205 };
206 return ra8_usb_host_setup_request(s_state.speed, &setup);
207}
208
227{
228 const ra8_usb_setup_t setup = {
229 .bm_request_type = k_ra8_hhub_bm_class_dev_in,
231 .w_value = (uint16_t)((uint16_t)k_ra8_hhub_desc_hub << k_ra8_hhub_shift_byte1),
232 .w_index = 0U,
233 .w_length = k_ra8_hhub_hub_desc_len,
234 };
235 return ra8_usb_host_setup_request(s_state.speed, &setup);
236}
237
255{
256 s_state.device.device_address = k_ra8_hhub_assigned_address;
257 s_state.device.port_count = k_ra8_hhub_default_ports;
258 s_state.device.vendor_id = 0U;
259 s_state.device.product_id = 0U;
260}
261
277static bool internal_port_ok(uint8_t port)
278{
279 return (port >= k_ra8_hhub_first_port) && (port <= s_state.device.port_count);
280}
281
282/* ---- Per-step handlers ---- */
283
298{
300 return ra8_usb_host_bus_reset(s_state.speed, true);
301}
302
317{
318 /* `ra8_usb_host_bus_reset` rejects only an invalid controller selector;
319 * `ra8_usb_hhub_init` validated and stored this selector before the step
320 * machine became reachable. */
321 (void)ra8_usb_host_bus_reset(s_state.speed, false);
324}
325
340{
341 /* The stored speed was validated at init and the assigned address is a
342 * compile-time member of the controller's accepted range. */
346}
347
366
385
404
419{
421 s_state.attached = true;
423 if (s_state.attach_cb != nullptr) {
424 s_state.attach_cb(s_state.attach_ctx, &s_state.device);
425 }
426 return k_ra8_ok;
427}
428
444{
445 switch (s_state.step) {
447 return internal_do_idle();
449 return internal_do_bus_reset();
457 return internal_do_set_config();
460 default:
461 /* Already done; idempotent. */
462 return k_ra8_ok;
463 }
464}
465
466/* =============================================================================
467 * Lifecycle
468 * =============================================================================
469 */
470
472{
473 if ((speed != k_ra8_usb_speed_fs) && (speed != k_ra8_usb_speed_hs)) {
475 }
476 const ra8_err_t usb_err = ra8_usb_host_init(speed);
477 if (usb_err != k_ra8_ok) {
478 ra8_log_error_val(s_tag, "ra8_usb_host_init failed", (uint32_t)usb_err);
480 }
481
482 s_state.speed = speed;
484 s_state.attached = false;
485 s_state.attach_cb = nullptr;
486 s_state.attach_ctx = nullptr;
487 s_state.device = (ra8_usb_hhub_device_t){};
488 s_state.initialized = true;
489
490 ra8_log_info_val(s_tag, "host-HUB ready", (uint32_t)speed);
491 return k_ra8_ok;
492}
493
495{
496 if (!s_state.initialized) {
498 }
499 (void)ra8_usb_host_set_uact(s_state.speed, false);
500 const ra8_err_t err = ra8_usb_host_deinit(s_state.speed);
501 s_state.initialized = false;
502 s_state.attached = false;
503 s_state.attach_cb = nullptr;
504 s_state.attach_ctx = nullptr;
506 return err;
507}
508
509/* =============================================================================
510 * Attach callback
511 * =============================================================================
512 */
513
515{
516 if (!s_state.initialized) {
518 }
519 s_state.attach_cb = on_attach;
520 s_state.attach_ctx = ctx;
521 return k_ra8_ok;
522}
523
524/* =============================================================================
525 * HUB class control transfers
526 * =============================================================================
527 */
528
530{
531 RA8_CHECK_NULL_PTR(count, s_tag, "get_port_count: count");
532 if (!s_state.initialized) {
534 }
535 if (!s_state.attached) {
537 }
538 *count = s_state.device.port_count;
539 return k_ra8_ok;
540}
541
542/* USB 2.0 sec 11.24.2.7 GET_PORT_STATUS:
543 * bmRequestType = 0xA3 (D2H | Class | Other)
544 * bRequest = 0x00 (GET_STATUS)
545 * wValue = 0
546 * wIndex = port
547 * wLength = 4
548 */
549ra8_err_t ra8_usb_hhub_get_port_status(uint8_t port, uint32_t* status)
550{
551 RA8_CHECK_NULL_PTR(status, s_tag, "get_port_status: status");
552 if (!s_state.initialized) {
554 }
555 if (!s_state.attached) {
557 }
558 if (!internal_port_ok(port)) {
560 }
561 *status = 0U;
562 const ra8_usb_setup_t setup = {
563 .bm_request_type = k_ra8_hhub_bm_class_other_in,
564 .b_request = k_ra8_hhub_req_get_status,
565 .w_value = 0U,
566 .w_index = (uint16_t)port,
567 .w_length = k_ra8_hhub_port_status_len,
568 };
569 return ra8_usb_host_setup_request(s_state.speed, &setup);
570}
571
572/* USB 2.0 sec 11.24.2.13 SET_PORT_FEATURE:
573 * bmRequestType = 0x23 (H2D | Class | Other)
574 * bRequest = 0x03 (SET_FEATURE)
575 * wValue = feature
576 * wIndex = port
577 * wLength = 0
578 */
580{
581 if (!s_state.initialized) {
583 }
584 if (!s_state.attached) {
586 }
587 if (!internal_port_ok(port)) {
589 }
590 const ra8_usb_setup_t setup = {
591 .bm_request_type = k_ra8_hhub_bm_class_other_out,
592 .b_request = k_ra8_hhub_req_set_feature,
593 .w_value = (uint16_t)feature,
594 .w_index = (uint16_t)port,
595 .w_length = 0U,
596 };
597 return ra8_usb_host_setup_request(s_state.speed, &setup);
598}
599
600/* USB 2.0 sec 11.24.2.2 CLEAR_PORT_FEATURE:
601 * bmRequestType = 0x23 (H2D | Class | Other)
602 * bRequest = 0x01 (CLEAR_FEATURE)
603 * wValue = feature
604 * wIndex = port
605 * wLength = 0
606 */
608{
609 if (!s_state.initialized) {
611 }
612 if (!s_state.attached) {
614 }
615 if (!internal_port_ok(port)) {
617 }
618 const ra8_usb_setup_t setup = {
619 .bm_request_type = k_ra8_hhub_bm_class_other_out,
620 .b_request = k_ra8_hhub_req_clear_feature,
621 .w_value = (uint16_t)feature,
622 .w_index = (uint16_t)port,
623 .w_length = 0U,
624 };
625 return ra8_usb_host_setup_request(s_state.speed, &setup);
626}
627
628/* =============================================================================
629 * Test / introspection helpers
630 * =============================================================================
631 */
632
634{
635 if (!s_state.initialized) {
637 }
638 return internal_step_advance();
639}
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_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
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_set_address(ra8_usb_speed_t speed, uint8_t address)
Program the device USB address into USBADDR.
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).
static ra8_err_t internal_do_get_hub_desc(void)
Internal helper.
static ra8_err_t internal_do_set_address(void)
Internal helper.
static ra8_err_t internal_setup_set_config(uint8_t config_value)
Stage a SET_CONFIGURATION SETUP request.
static ra8_err_t internal_do_idle(void)
Internal helper.
ra8_err_t ra8_usb_hhub_set_port_feature(uint8_t port, ra8_usb_hhub_feature_t feature)
Issue SET_PORT_FEATURE (USB 2.0 sec 11.24.2.13) over the DCP.
static ra8_err_t internal_step_advance(void)
Drive the enumeration step machine forward by one step.
static ra8_err_t internal_do_set_config(void)
Internal helper.
ra8_err_t ra8_usb_hhub_step(void)
Drive the enumeration step machine forward by one step.
static ra8_err_t internal_setup_get_descriptor(uint8_t desc_type, uint16_t length)
Stage a chapter-9 GET_DESCRIPTOR SETUP request.
ra8_usb_hhub_size_t
Standard descriptor sizes / payload sizes.
@ k_ra8_hhub_port_status_len
GET_PORT_STATUS data length.
@ k_ra8_hhub_default_ports
Stub default port count.
@ k_ra8_hhub_assigned_address
First assigned device addr.
@ k_ra8_hhub_dev_desc_len
USB DEVICE descriptor.
@ k_ra8_hhub_hub_desc_len
Min HUB class descriptor.
@ k_ra8_hhub_cfg_desc_len
CONFIG descriptor header.
@ k_ra8_hhub_default_config
bConfigurationValue = 1.
ra8_err_t ra8_usb_hhub_close(void)
Tear down the host-HUB driver and release the controller.
static ra8_err_t internal_do_bus_reset(void)
Internal helper.
static ra8_err_t internal_do_get_dev_desc(void)
Internal helper.
static ra8_err_t internal_setup_get_hub_descriptor(void)
Stage a GET_DESCRIPTOR(HUB) class request.
static bool internal_port_ok(uint8_t port)
Validate port is within [1, port_count].
ra8_err_t ra8_usb_hhub_attach_callback(ra8_usb_hhub_attach_fn_t on_attach, void *ctx)
Register (or detach) the HUB attach callback.
ra8_err_t ra8_usb_hhub_init(ra8_usb_speed_t speed)
Bring up the host-HUB driver on a chosen USB controller.
ra8_err_t ra8_usb_hhub_clear_port_feature(uint8_t port, ra8_usb_hhub_feature_t feature)
Issue CLEAR_PORT_FEATURE (USB 2.0 sec 11.24.2.2) over the DCP.
ra8_usb_hhub_setup_field_t
Standard chapter-9 + HUB class request encodings.
@ k_ra8_hhub_bm_std_dev_out
Std | Device | Out.
@ k_ra8_hhub_bm_class_other_out
Class | Other | Out.
@ k_ra8_hhub_bm_std_dev_in
Std | Device | In.
@ k_ra8_hhub_breq_set_config
SET_CONFIGURATION.
@ k_ra8_hhub_breq_set_address
SET_ADDRESS.
@ k_ra8_hhub_breq_get_desc
GET_DESCRIPTOR.
@ k_ra8_hhub_bm_class_dev_in
Class | Device | In.
@ k_ra8_hhub_bm_class_other_in
Class | Other | In.
@ k_ra8_hhub_desc_configuration
CONFIG descriptor.
@ k_ra8_hhub_desc_device
DEVICE descriptor.
ra8_usb_hhub_step_t
Enumeration step machine states.
@ k_ra8_hhub_step_bus_reset
Drive USBRST then release.
@ k_ra8_hhub_step_get_hub_desc
GET_DESCRIPTOR(HUB) class.
@ k_ra8_hhub_step_set_address
SET_ADDRESS to assigned 1.
@ k_ra8_hhub_step_get_cfg_desc
GET_CONFIGURATION_DESCRIPTOR.
@ k_ra8_hhub_step_set_config
SET_CONFIGURATION (1).
@ k_ra8_hhub_step_get_dev_desc
GET_DEVICE_DESCRIPTOR.
@ k_ra8_hhub_step_idle
Pre-attach.
@ k_ra8_hhub_step_done
Attach callback fires.
static void internal_populate_device_defaults(void)
Populate s_state.device with stub descriptor data.
ra8_err_t ra8_usb_hhub_get_port_status(uint8_t port, uint32_t *status)
Issue GET_PORT_STATUS (USB 2.0 sec 11.24.2.7) over the DCP.
ra8_usb_hhub_byte_shift_t
Per-byte left-shift constants for wValue layout.
@ k_ra8_hhub_shift_byte1
Shift to high byte of a 16-bit field.
ra8_err_t ra8_usb_hhub_get_port_count(uint8_t *count)
Read the cached downstream port count from the HUB descriptor.
static ra8_err_t internal_setup_set_address(uint8_t address)
Stage a SET_ADDRESS SETUP request.
static ra8_err_t internal_do_get_cfg_desc(void)
Internal helper.
Native USB host-side HUB class layer.
void(* ra8_usb_hhub_attach_fn_t)(void *ctx, const ra8_usb_hhub_device_t *device)
Attach-callback signature.
ra8_usb_hhub_feature_t
HUB port feature selectors (USB 2.0 Table 11-17).
@ k_ra8_hhub_req_clear_feature
CLEAR_FEATURE.
@ k_ra8_hhub_req_set_feature
SET_FEATURE.
@ k_ra8_hhub_req_get_descriptor
GET_DESCRIPTOR.
@ k_ra8_hhub_req_get_status
GET_STATUS.
@ k_ra8_hhub_desc_hub
HUB class descriptor type.
@ k_ra8_hhub_first_port
Port numbering starts at 1.
ra8_err_t ra8_usb_host_bus_reset(ra8_usb_speed_t speed, bool assert_reset)
Drive (or release) the bus reset line.
ra8_err_t ra8_usb_host_init(ra8_usb_speed_t speed)
Bring up a USB controller in HOST mode.
ra8_err_t ra8_usb_host_deinit(ra8_usb_speed_t speed)
Tear down a host-mode controller and drop its MSTP reference.
ra8_err_t ra8_usb_host_setup_request(ra8_usb_speed_t speed, const ra8_usb_setup_t *setup)
Issue a SETUP packet through the DCP (host -> peripheral).
ra8_err_t ra8_usb_host_set_uact(ra8_usb_speed_t speed, bool enable)
Enable / disable SOF (Start-of-Frame) generation on the bus.
Snapshot of the attached HUB device, passed to the attach callback.
Singleton shadow state for the host-HUB driver.
ra8_usb_speed_t speed
Underlying controller.
void * attach_ctx
Attach callback ctx.
ra8_usb_hhub_device_t device
Snapshot of attached HUB.
bool initialized
True after ra8_usb_hhub_init.
bool attached
True after enumeration done.
ra8_usb_hhub_step_t step
Current enumeration step.
ra8_usb_hhub_attach_fn_t attach_cb
Attach callback, or NULL.
Decoded 8-byte USB SETUP packet.