ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_usb_hhid.c
Go to the documentation of this file.
1
36
37#include "ra8_usb_hhid.h"
38
39#include <stdint.h>
40
41#include "ra8_attributes.h"
42#include "ra8_check.h"
43#include "ra8_err.h"
44#include "ra8_log.h"
45#include "ra8_usb.h"
46#include "ra8_usb_regs.h"
47
48static const char* s_tag = "USBHHID";
49
50/* =============================================================================
51 * Internal constants
52 * =============================================================================
53 */
54
75
80typedef enum : uint8_t {
81 /* Chapter-9 standard requests (USB 2.0 spec section 9.4). */
90 /* HID class-specific request envelopes (USB HID 1.11 sec 7.2). */
93 /* Descriptor types in wValue's high byte (chapter 9). */
99
113
122
123/* =============================================================================
124 * Internal state
125 * =============================================================================
126 */
127
145
147/* =============================================================================
148 * Internal helpers
149 * =============================================================================
150 */
151
172
192{
195 s_state.device.intr_in_ep,
198 s_state.device.intr_in_max_packet);
199 RA8_RETURN_ON_ERROR(err, s_tag, "hhid: intr-in cfg");
200
201 if (s_state.device.intr_out_ep != 0U) {
204 s_state.device.intr_out_ep,
207 s_state.device.intr_out_max_packet);
208 }
209 return err;
210}
211
228static ra8_err_t internal_setup_get_descriptor(uint8_t desc_type, uint16_t length)
229{
230 const ra8_usb_setup_t setup = {
231 .bm_request_type = k_ra8_hhid_bm_std_dev_in,
233 .w_value = (uint16_t)((uint16_t)desc_type << k_ra8_hhid_shift_byte1),
234 .w_index = 0U,
235 .w_length = length,
236 };
237 return ra8_usb_host_setup_request(s_state.speed, &setup);
238}
239
256{
257 const ra8_usb_setup_t setup = {
258 .bm_request_type = k_ra8_hhid_bm_std_dev_out,
259 .b_request = k_ra8_hhid_breq_set_address,
260 .w_value = (uint16_t)address,
261 .w_index = 0U,
262 .w_length = 0U,
263 };
264 return ra8_usb_host_setup_request(s_state.speed, &setup);
265}
266
282static ra8_err_t internal_setup_set_config(uint8_t config_value)
283{
284 const ra8_usb_setup_t setup = {
285 .bm_request_type = k_ra8_hhid_bm_std_dev_out,
286 .b_request = k_ra8_hhid_breq_set_config,
287 .w_value = (uint16_t)config_value,
288 .w_index = 0U,
289 .w_length = 0U,
290 };
291 return ra8_usb_host_setup_request(s_state.speed, &setup);
292}
293
309{
310 const ra8_usb_setup_t setup = {
311 .bm_request_type = k_ra8_hhid_bm_std_iface_out,
313 .w_value = 0U,
314 .w_index = 0U,
315 .w_length = 0U,
316 };
317 return ra8_usb_host_setup_request(s_state.speed, &setup);
318}
319
340{
341 const ra8_usb_setup_t setup = {
342 .bm_request_type = k_ra8_hhid_bm_std_iface_in,
344 .w_value = (uint16_t)((uint16_t)k_ra8_hhid_desc_report << k_ra8_hhid_shift_byte1),
345 .w_index = (uint16_t)s_state.device.interface_number,
346 .w_length = length,
347 };
348 return ra8_usb_host_setup_request(s_state.speed, &setup);
349}
350
374{
375 s_state.device.device_address = k_ra8_hhid_assigned_address;
376 s_state.device.intr_in_ep = 1U;
377 s_state.device.intr_out_ep = 0U;
378 s_state.device.interface_number = 0U;
379 s_state.device.subclass = k_ra8_hhid_subclass_boot;
380 s_state.device.protocol = k_ra8_hhid_protocol_keyboard;
381 s_state.device.intr_in_max_packet = internal_intr_max_packet(s_state.speed);
382 s_state.device.intr_out_max_packet = 0U;
383 s_state.device.report_descriptor_len = 0U;
384 s_state.device.hid_descriptor = s_state.hid_desc;
385 s_state.device.report_descriptor = s_state.report_desc;
386 /* VID / PID stay at zero until the production GET_DEVICE_DESCRIPTOR
387 * data stage lands; both fields are informational. */
388}
389
405{
407 return ra8_usb_host_bus_reset(s_state.speed, true);
408}
409
425{
426 const ra8_err_t rel = ra8_usb_host_bus_reset(s_state.speed, false);
427 RA8_RETURN_ON_ERROR(rel, /* GCOVR_EXCL_BR_LINE -- stored speed valid; reset rejects only speed */
428 s_tag,
429 "hhid: release bus reset");
432}
433
450{
452 RA8_RETURN_ON_ERROR(addr_err, /* GCOVR_EXCL_BR_LINE -- valid speed + static in-range address */
453 s_tag,
454 "hhid: set USBADDR");
457}
458
478
498
518
539
561
577{
578 s_state.attached = true;
580 if (s_state.attach_cb != nullptr) {
581 s_state.attach_cb(s_state.attach_ctx, &s_state.device);
582 }
583 return k_ra8_ok;
584}
585
604{
605 switch (s_state.step) {
607 return internal_do_idle();
609 return internal_do_bus_reset();
617 return internal_do_set_config();
621 return internal_do_walk_desc();
624 default:
625 /* Already done; idempotent. */
626 return k_ra8_ok;
627 }
628}
629
650
651/* =============================================================================
652 * Lifecycle
653 * =============================================================================
654 */
655
657{
658 if ((speed != k_ra8_usb_speed_fs) && (speed != k_ra8_usb_speed_hs)) {
660 }
661 const ra8_err_t usb_err = ra8_usb_host_init(speed);
662 if (usb_err != k_ra8_ok) {
663 ra8_log_error_val(s_tag, "ra8_usb_host_init failed", (uint32_t)usb_err);
665 }
666
667 s_state.speed = speed;
669 s_state.attached = false;
670 s_state.attach_cb = nullptr;
671 s_state.attach_ctx = nullptr;
672 s_state.device = (ra8_usb_hhid_device_t){};
673 s_state.initialized = true;
674
675 ra8_log_info_val(s_tag, "host-HID ready", (uint32_t)speed);
676 return k_ra8_ok;
677}
678
680{
681 if (!s_state.initialized) {
683 }
684 /* Bus power down: drop UACT before tearing the controller. */
685 (void)ra8_usb_host_set_uact(s_state.speed, false);
686 const ra8_err_t err = ra8_usb_host_deinit(s_state.speed);
687 s_state.initialized = false;
688 s_state.attached = false;
689 s_state.attach_cb = nullptr;
690 s_state.attach_ctx = nullptr;
692 return err;
693}
694
695/* =============================================================================
696 * Attach callback
697 * =============================================================================
698 */
699
701{
702 if (!s_state.initialized) {
704 }
705 s_state.attach_cb = on_attach;
706 s_state.attach_ctx = ctx;
707 return k_ra8_ok;
708}
709
710/* =============================================================================
711 * Class control transfers
712 * =============================================================================
713 */
714
723
729{
730 if (speed == k_ra8_usb_speed_hs) {
731 return ra8_usb_hs();
732 }
733 if (speed == k_ra8_usb_speed_fs) {
734 return ra8_usb_fs();
735 }
736 return nullptr;
737}
738
768static uint16_t internal_dcp_in_drain(volatile r_usb_regs_t* reg, uint8_t* out, uint16_t max_len)
769{
770 if (max_len == 0U) {
771 return 0U;
772 }
773 /* HUM Ch 36.2.7 "CFIFOSEL" p 1976 */ /* pipe=0 (DCP), MBW=16, ISEL=1. */
774 uint16_t sel = (uint16_t)k_ra8_hhid_dcp_pipe_dcp & (uint16_t)k_ra8_fifosel_curpipe;
775 sel = (uint16_t)(sel | k_ra8_fifosel_mbw_16);
776 sel = (uint16_t)(sel | k_ra8_fifosel_isel);
777 reg->CFIFOSEL = sel;
778
779 /* HUM Ch 36.2.8 "CFIFOCTR" p 1979 */ /* bounded FRDY spin. */
780 uint16_t ready = 0U;
781 for (uint16_t i = 0U; i < k_ra8_hhid_fifo_poll_lim; ++i) {
782 if ((reg->CFIFOCTR & k_ra8_fifoctr_frdy) != 0U) {
783 ready = 1U;
784 break;
785 }
786 }
787 if (ready == 0U) {
788 return 0U;
789 }
790
791 const uint16_t available = (uint16_t)(reg->CFIFOCTR & k_ra8_fifoctr_dtln);
792 uint16_t take = (available < max_len) ? available : max_len;
793
794 /* HUM Ch 36.2.5 "CFIFO" p 1973 */ /* 16-bit LE drain. */
795 enum : uint8_t {
796 k_byte_bits = 8U,
797 k_byte_mask = 0xFFU,
798 };
799 const uint16_t even = (uint16_t)(take >> 1U);
800 for (uint16_t i = 0U; i < even; ++i) {
801 const uint16_t word = reg->CFIFO;
802 out[(2U * i) + 0U] = (uint8_t)(word & k_byte_mask);
803 out[(2U * i) + 1U] = (uint8_t)((word >> k_byte_bits) & k_byte_mask);
804 }
805 if ((take & 1U) != 0U) {
806 const uint16_t word = reg->CFIFO;
807 out[take - 1U] = (uint8_t)(word & k_byte_mask);
808 }
809 /* Release the buffer so the controller can ACK the IN data phase. */
811 return take;
812}
813
814/* USB HID 1.11 sec 7.2.1 "Get_Report request":
815 * bmRequestType = 0xA1 (D2H | Class | Interface)
816 * bRequest = 0x01 (GET_REPORT)
817 * wValue.high = report type (1=Input / 2=Output / 3=Feature)
818 * wValue.low = report ID (0 if device uses a single unnamed report)
819 */
821 uint8_t target_report_id,
822 uint8_t* out_buf,
823 uint16_t max_len,
824 uint16_t* got_len)
825{
826 RA8_CHECK_NULL_PTR(out_buf, s_tag, "get_report: out_buf");
827 RA8_CHECK_NULL_PTR(got_len, s_tag, "get_report: got_len");
828 if (!s_state.initialized) {
830 }
831 if (!s_state.attached) {
833 }
834 if (!internal_report_type_ok(target_report_type)) {
836 }
837 if (max_len == 0U) {
839 }
840
841 const uint16_t value = (uint16_t)(((uint16_t)target_report_type << k_ra8_hhid_shift_byte1) |
842 (uint16_t)target_report_id);
843 const ra8_usb_setup_t setup = {
844 .bm_request_type = k_ra8_hhid_bm_class_iface_in,
845 .b_request = k_ra8_hhid_req_get_report,
846 .w_value = value,
847 .w_index = (uint16_t)s_state.device.interface_number,
848 .w_length = max_len,
849 };
850 *got_len = 0U;
851 const ra8_err_t setup_err = ra8_usb_host_setup_request(s_state.speed, &setup);
852 if (setup_err != k_ra8_ok) {
853 return setup_err;
854 }
855
856 /* Wire the IN data phase: after the SETUP request lands the
857 * controller drives an IN token on EP0 and the device's response
858 * ends up in the DCP CFIFO. Drain it into the caller's buffer. */
859 volatile r_usb_regs_t* reg = internal_pick_regs(s_state.speed);
860 if (reg != nullptr) {
861 *got_len = internal_dcp_in_drain(reg, out_buf, max_len);
862 }
863 return k_ra8_ok;
864}
865
866/* USB HID 1.11 sec 7.2.2 "Set_Report request":
867 * bmRequestType = 0x21 (H2D | Class | Interface)
868 * bRequest = 0x09 (SET_REPORT)
869 */
871 uint8_t target_report_id,
872 const uint8_t* in_buf,
873 uint16_t len)
874{
875 if (!s_state.initialized) {
877 }
878 if (!s_state.attached) {
880 }
881 if ((in_buf == nullptr) && (len != 0U)) {
882 return k_ra8_err_null_ptr;
883 }
884 if (!internal_report_type_ok(target_report_type)) {
886 }
887
888 const uint16_t value = (uint16_t)(((uint16_t)target_report_type << k_ra8_hhid_shift_byte1) |
889 (uint16_t)target_report_id);
890 const ra8_usb_setup_t setup = {
891 .bm_request_type = k_ra8_hhid_bm_class_iface_out,
892 .b_request = k_ra8_hhid_req_set_report,
893 .w_value = value,
894 .w_index = (uint16_t)s_state.device.interface_number,
895 .w_length = len,
896 };
897 /* Production path queues `in_buf[0..len-1]` on the DCP data stage
898 * once the controller advances past the SETUP token. The starter
899 * just ensures the SETUP envelope hits the wire. */
900 (void)in_buf;
901 return ra8_usb_host_setup_request(s_state.speed, &setup);
902}
903
904/* USB HID 1.11 sec 7.2.4 "Set_Idle request":
905 * bmRequestType = 0x21
906 * bRequest = 0x0A (SET_IDLE)
907 * wValue.high = duration (in 4 ms units)
908 * wValue.low = report ID (0 = "all reports")
909 */
910ra8_err_t ra8_usb_hhid_set_idle(uint8_t duration, uint8_t report_id)
911{
912 if (!s_state.initialized) {
914 }
915 if (!s_state.attached) {
917 }
918 const uint16_t value =
919 (uint16_t)(((uint16_t)duration << k_ra8_hhid_shift_byte1) | (uint16_t)report_id);
920 const ra8_usb_setup_t setup = {
921 .bm_request_type = k_ra8_hhid_bm_class_iface_out,
922 .b_request = k_ra8_hhid_req_set_idle,
923 .w_value = value,
924 .w_index = (uint16_t)s_state.device.interface_number,
925 .w_length = 0U,
926 };
927 return ra8_usb_host_setup_request(s_state.speed, &setup);
928}
929
930/* USB HID 1.11 sec 7.2.6 "Set_Protocol request":
931 * bmRequestType = 0x21
932 * bRequest = 0x0B (SET_PROTOCOL)
933 * wValue = 0 (boot protocol) or 1 (report protocol)
934 */
936{
937 if (!s_state.initialized) {
939 }
940 if (!s_state.attached) {
942 }
943 if ((boot_or_report != k_ra8_hhid_proto_boot) && (boot_or_report != k_ra8_hhid_proto_report)) {
945 }
946 const ra8_usb_setup_t setup = {
947 .bm_request_type = k_ra8_hhid_bm_class_iface_out,
948 .b_request = k_ra8_hhid_req_set_protocol,
949 .w_value = (uint16_t)boot_or_report,
950 .w_index = (uint16_t)s_state.device.interface_number,
951 .w_length = 0U,
952 };
953 return ra8_usb_host_setup_request(s_state.speed, &setup);
954}
955
956/* =============================================================================
957 * Interrupt-IN polling
958 * =============================================================================
959 */
960
961ra8_err_t ra8_usb_hhid_get_input_report(uint8_t* out_buf, uint16_t max_len, uint16_t* got_len)
962{
963 RA8_CHECK_NULL_PTR(out_buf, s_tag, "get_input_report: out_buf");
964 RA8_CHECK_NULL_PTR(got_len, s_tag, "get_input_report: got_len");
965 if (!s_state.initialized) {
967 }
968 if (!s_state.attached) {
970 }
971 if (max_len == 0U) {
973 }
974 uint16_t inout_len = max_len;
975 const ra8_err_t err =
976 ra8_usb_queue_out(s_state.speed, k_ra8_hhid_pipe_intr_in, out_buf, &inout_len, true);
977 if (err == k_ra8_ok) {
978 *got_len = inout_len;
979 } else {
980 *got_len = 0U;
981 }
982 return err;
983}
984
985/* =============================================================================
986 * Test / introspection helpers
987 * =============================================================================
988 */
989
991{
992 if (!s_state.initialized) {
994 }
995 return internal_step_advance();
996}
@ k_byte_bits
Bits per byte (SHPR field width).
Definition emu_exc.h:99
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_RETURN_ON_ERROR(err, tag, message)
Early return on error, propagating the code upward.
Definition ra8_check.h:184
#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
@ 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
@ k_byte_mask
Byte mask.
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_intr
Interrupt transfer.
ra8_err_t ra8_usb_set_address(ra8_usb_speed_t speed, uint8_t address)
Program the device USB address into USBADDR.
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.
@ 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).
static ra8_err_t internal_do_set_address(void)
Step handler – store assigned address + SETUP for GET_DEVICE_DESCRIPTOR.
static volatile r_usb_regs_t * internal_pick_regs(ra8_usb_speed_t speed)
Pick the controller register window for the active speed.
ra8_err_t ra8_usb_hhid_close(void)
Tear down the host-HID driver and release the controller.
static ra8_err_t internal_setup_set_config(uint8_t config_value)
Stage a SET_CONFIGURATION SETUP request.
ra8_err_t ra8_usb_hhid_set_report(ra8_usb_hhid_report_type_t target_report_type, uint8_t target_report_id, const uint8_t *in_buf, uint16_t len)
Issue SET_REPORT (USB HID 1.11 sec 7.2.2) over the DCP.
static ra8_err_t internal_do_idle(void)
Step handler – bus-reset assert.
ra8_usb_hhid_byte_shift_t
Per-byte left-shift constants for wValue layout.
@ k_ra8_hhid_shift_byte0
RA8 hhid shift byte0.
@ k_ra8_hhid_shift_byte1
RA8 hhid shift byte1.
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)
Step handler – SETUP for SET_INTERFACE.
static ra8_err_t internal_setup_set_interface(void)
Stage a SET_INTERFACE (alt 0, iface 0) SETUP request.
static ra8_err_t internal_setup_get_descriptor(uint8_t desc_type, uint16_t length)
Stage a chapter-9 GET_DESCRIPTOR SETUP request.
static uint16_t internal_intr_max_packet(ra8_usb_speed_t speed)
Pick the interrupt-max-packet ceiling for the negotiated speed.
ra8_usb_hhid_setup_field_t
Standard chapter-9 + HID class request encodings.
@ k_ra8_hhid_desc_configuration
CONFIGURATION descriptor.
@ k_ra8_hhid_bm_class_iface_in
Class | Interface | In.
@ k_ra8_hhid_breq_set_interface
SET_INTERFACE.
@ k_ra8_hhid_breq_set_address
SET_ADDRESS.
@ k_ra8_hhid_breq_set_config
SET_CONFIGURATION.
@ k_ra8_hhid_bm_class_iface_out
Class | Interface | Out.
@ k_ra8_hhid_desc_device
DEVICE descriptor.
@ k_ra8_hhid_breq_get_descriptor
GET_DESCRIPTOR.
@ k_ra8_hhid_desc_endpoint
ENDPOINT descriptor.
@ k_ra8_hhid_desc_interface
INTERFACE descriptor.
@ k_ra8_hhid_bm_std_dev_in
Std | Device | In.
@ k_ra8_hhid_bm_std_iface_out
Std | Interface | Out.
@ k_ra8_hhid_bm_std_dev_out
Std | Device | Out.
@ k_ra8_hhid_bm_std_iface_in
Std | Interface | In.
ra8_err_t ra8_usb_hhid_set_protocol(ra8_usb_hhid_protocol_select_t boot_or_report)
Issue SET_PROTOCOL (USB HID 1.11 sec 7.2.6) over the DCP.
static ra8_err_t internal_do_bus_reset(void)
Step handler – bus-reset release + SETUP for SET_ADDRESS.
static bool internal_report_type_ok(ra8_usb_hhid_report_type_t t)
Validate that a ra8_usb_hhid_report_type_t value is in range.
static ra8_err_t internal_do_get_dev_desc(void)
Step handler – SETUP for GET_CONFIGURATION_DESCRIPTOR.
static void internal_walk_config_descriptor(void)
Populate s_state.device with stub descriptor data.
static ra8_err_t internal_do_set_interface(void)
Step handler – pure software descriptor walk.
ra8_usb_hhid_step_t
Enumeration step machine states.
@ k_ra8_hhid_step_get_cfg_desc
GET_CONFIGURATION_DESCRIPTOR.
@ k_ra8_hhid_step_idle
Pre-attach.
@ k_ra8_hhid_step_get_dev_desc
GET_DEVICE_DESCRIPTOR (18 B).
@ k_ra8_hhid_step_get_report_desc
GET_DESCRIPTOR (Report).
@ k_ra8_hhid_step_set_address
SET_ADDRESS to assigned 1.
@ k_ra8_hhid_step_walk_desc
Find HID IF; populate pipes.
@ k_ra8_hhid_step_set_interface
SET_INTERFACE (0).
@ k_ra8_hhid_step_bus_reset
Drive USBRST then release.
@ k_ra8_hhid_step_done
Attach callback fires.
@ k_ra8_hhid_step_set_config
SET_CONFIGURATION (1).
static ra8_err_t internal_setup_get_report_descriptor(uint16_t length)
Stage a GET_DESCRIPTOR (Report descriptor) SETUP request.
ra8_usb_hhid_dcp_t
CFIFO programming constants used by the EP0 IN drain helper.
@ k_ra8_hhid_fifo_poll_lim
FRDY-poll budget.
@ k_ra8_hhid_dcp_pipe_dcp
DCP / EP0 select.
ra8_err_t ra8_usb_hhid_init(ra8_usb_speed_t speed)
Bring up the host-HID driver on a chosen USB controller.
ra8_err_t ra8_usb_hhid_set_idle(uint8_t duration, uint8_t report_id)
Issue SET_IDLE (USB HID 1.11 sec 7.2.4) over the DCP.
ra8_err_t ra8_usb_hhid_get_input_report(uint8_t *out_buf, uint16_t max_len, uint16_t *got_len)
Drain the next input report from the interrupt-IN pipe.
ra8_err_t ra8_usb_hhid_get_report(ra8_usb_hhid_report_type_t target_report_type, uint8_t target_report_id, uint8_t *out_buf, uint16_t max_len, uint16_t *got_len)
Issue GET_REPORT (USB HID 1.11 sec 7.2.1) over the DCP.
ra8_usb_hhid_size_t
Standard descriptor sizes and request payload sizes.
@ k_ra8_hhid_ep_desc_len
ENDPOINT descriptor.
@ k_ra8_hhid_iface_desc_len
INTERFACE descriptor.
@ k_ra8_hhid_dev_desc_len
USB DEVICE descriptor.
@ k_ra8_hhid_hid_desc_len
HID class descriptor (min).
@ k_ra8_hhid_cfg_desc_len
CONFIGURATION descriptor hdr.
@ k_ra8_hhid_assigned_address
First assigned device addr.
@ k_ra8_hhid_default_config
bConfigurationValue = 1.
static ra8_err_t internal_do_walk_desc(void)
Step handler – configure pipes + SETUP GET_DESCRIPTOR(Report).
static ra8_err_t internal_do_get_report_desc(void)
Step handler – finalise + fire attach callback.
ra8_err_t ra8_usb_hhid_step(void)
Drive the enumeration step machine forward by one step.
ra8_err_t ra8_usb_hhid_attach_callback(ra8_usb_hhid_attach_fn_t on_attach, void *ctx)
Register (or detach) the attach callback.
static uint16_t internal_dcp_in_drain(volatile r_usb_regs_t *reg, uint8_t *out, uint16_t max_len)
Drain the DCP (EP0) IN FIFO after a class GET_REPORT SETUP.
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)
Step handler – SETUP for SET_CONFIGURATION.
static ra8_err_t internal_configure_pipes(void)
Configure the host-HID interrupt-IN pipe against the attached device's endpoint.
Native USB host-side HID (Human Interface Device) class layer.
ra8_usb_hhid_report_type_t
HID report-type selector encoded in wValue's high byte for GET_REPORT / SET_REPORT.
@ k_ra8_hhid_report_type_input
Input report.
@ k_ra8_hhid_report_type_feature
Feature report.
@ k_ra8_hhid_report_type_output
Output report.
void(* ra8_usb_hhid_attach_fn_t)(void *ctx, const ra8_usb_hhid_device_t *device)
Attach-callback signature.
@ k_ra8_hhid_protocol_keyboard
Boot keyboard.
@ k_ra8_hhid_subclass_boot
Boot Interface Subclass.
@ k_ra8_hhid_desc_report
HID Report descriptor.
@ k_ra8_hhid_intr_max_packet_default
Boot-protocol default.
@ k_ra8_hhid_intr_max_packet_hs
HS ceiling.
@ k_ra8_hhid_report_desc_max
Cached Report desc max len.
@ k_ra8_hhid_req_set_report
SET_REPORT.
@ k_ra8_hhid_req_get_report
GET_REPORT.
@ k_ra8_hhid_req_set_protocol
SET_PROTOCOL.
@ k_ra8_hhid_req_set_idle
SET_IDLE.
ra8_usb_hhid_protocol_select_t
wValue payload for SET_PROTOCOL.
@ k_ra8_hhid_proto_boot
Boot protocol.
@ k_ra8_hhid_proto_report
Report protocol.
@ k_ra8_hhid_pipe_intr_out
PIPE7 -> attached EP intr OUT.
@ k_ra8_hhid_pipe_intr_in
PIPE6 -> attached EP intr IN.
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.
USB Full-Speed + High-Speed controller layout for the Renesas RA8D2.
@ k_ra8_fifoctr_frdy
FIFO ready.
@ k_ra8_fifoctr_bclr
Buffer clear.
@ k_ra8_fifoctr_dtln
Data length (write-bytes-rem).
@ k_ra8_fifosel_isel
CFIFO direction (DCP only).
@ k_ra8_fifosel_mbw_16
16-bit FIFO access width.
@ k_ra8_fifosel_curpipe
Current pipe select [3:0].
static volatile r_usb_regs_t * ra8_usb_hs(void)
Get pointer to the USB HS controller register block.
static volatile r_usb_regs_t * ra8_usb_fs(void)
Compile-time offset and size insurance for r_usb_regs_t.
USB FS / HS register window (device-mode subset).
volatile uint16_t CFIFOCTR
+0x022 Control FIFO control.
volatile uint16_t CFIFOSEL
+0x020 Control FIFO select.
volatile uint16_t CFIFO
+0x014 Control FIFO data port.
Snapshot of the attached HID device, passed to the attach callback.
Singleton shadow state for the host-HID driver.
ra8_usb_hhid_device_t device
Snapshot of attached device.
bool attached
True after enumeration done.
void * attach_ctx
Attach callback ctx.
uint8_t hid_desc[k_ra8_hhid_hid_desc_len]
HID class descriptor cache.
ra8_usb_speed_t speed
Underlying controller.
ra8_usb_hhid_attach_fn_t attach_cb
Attach callback, or NULL.
ra8_usb_hhid_step_t step
Current enumeration step.
uint8_t report_desc[k_ra8_hhid_report_desc_max]
HID Report descriptor cache.
bool initialized
True after ra8_usb_hhid_init.
Decoded 8-byte USB SETUP packet.