From c7fcea5f35df9f44ebeb7fe71173a725ee000495 Mon Sep 17 00:00:00 2001 From: CTCaer Date: Sun, 15 Nov 2020 14:30:25 +0200 Subject: [PATCH] usb: Rfactor driver/gadgets in prep for XUSB Allow gadgets using different USB controllers on demand. This will allow plugging in XUSB for Mariko usage. --- bdk/usb/usb_descriptors.c | 43 ++++--- bdk/usb/usb_gadget_hid.c | 23 ++-- bdk/usb/usb_gadget_ums.c | 79 +++++++----- bdk/usb/usb_t210.h | 2 +- bdk/usb/usbd.c | 263 ++++++++++++++++---------------------- bdk/usb/usbd.h | 163 +++++++++++++++++------ 6 files changed, 313 insertions(+), 260 deletions(-) diff --git a/bdk/usb/usb_descriptors.c b/bdk/usb/usb_descriptors.c index fe9bde4..252577e 100644 --- a/bdk/usb/usb_descriptors.c +++ b/bdk/usb/usb_descriptors.c @@ -19,7 +19,7 @@ #include #include -usb_dev_descr_t usb_device_descriptor_ums = +static usb_dev_descr_t usb_device_descriptor_ums = { .bLength = 18, .bDescriptorType = USB_DESCRIPTOR_DEVICE, @@ -37,7 +37,7 @@ usb_dev_descr_t usb_device_descriptor_ums = .bNumConfigs = 1 }; -usb_dev_qual_descr_t usb_device_qualifier_descriptor = +static usb_dev_qual_descr_t usb_device_qualifier_descriptor = { .bLength = 10, .bDescriptorType = USB_DESCRIPTOR_DEVICE_QUALIFIER, @@ -50,7 +50,7 @@ usb_dev_qual_descr_t usb_device_qualifier_descriptor = .bReserved = 0x00 }; -usb_cfg_simple_descr_t usb_configuration_descriptor_ums = +static usb_cfg_simple_descr_t usb_configuration_descriptor_ums = { /* Configuration descriptor structure */ .config.bLength = 9, @@ -90,7 +90,7 @@ usb_cfg_simple_descr_t usb_configuration_descriptor_ums = .endpoint[1].bInterval = 0x00 }; -usb_cfg_simple_descr_t usb_other_speed_config_descriptor_ums = +static usb_cfg_simple_descr_t usb_other_speed_config_descriptor_ums = { /* Other Speed Configuration descriptor structure */ .config.bLength = 9, @@ -130,7 +130,7 @@ usb_cfg_simple_descr_t usb_other_speed_config_descriptor_ums = .endpoint[1].bInterval = 0 }; -usb_dev_bot_t usb_device_binary_object_descriptor = +static usb_dev_bot_t usb_device_binary_object_descriptor = { .bLength = 5, .bDescriptorType = USB_DESCRIPTOR_DEVICE_BINARY_OBJECT, @@ -155,33 +155,33 @@ usb_dev_bot_t usb_device_binary_object_descriptor = .wU2DevExitLat = 0 }; -u8 usb_lang_id_string_descriptor[4] = +static u8 usb_lang_id_string_descriptor[4] = { 4, 3, 0x09, 0x04 }; -u8 usb_serial_string_descriptor[26] = +static u8 usb_serial_string_descriptor[26] = { 26, 0x03, 'C', 0x00, '7', 0x00, 'C', 0x00, '0', 0x00, '9', 0x00, '2', 0x00, '4', 0x00, '2', 0x00, 'F', 0x00, '7', 0x00, '0', 0x00, '3', 0x00 }; -u8 usb_vendor_string_descriptor_ums[32] = +static u8 usb_vendor_string_descriptor_ums[32] = { 26, 0x03, 'N', 0, 'y', 0, 'x', 0, ' ', 0, 'U', 0, 'S', 0, 'B', 0, ' ', 0, 'D', 0, 'i', 0, 's', 0, 'k', 0 }; -u8 usb_product_string_descriptor_ums[22] = +static u8 usb_product_string_descriptor_ums[22] = { 8, 0x03, 'U', 0, 'M', 0, 'S', 0 }; -usb_ms_os_descr_t usb_ms_os_descriptor = +static usb_ms_os_descr_t usb_ms_os_descriptor = { .bLength = 0x28, .bDescriptorType = 0x03, @@ -195,7 +195,7 @@ usb_ms_os_descr_t usb_ms_os_descriptor = .bVendorCode = 0x99, }; -usb_ms_cid_descr_t usb_ms_cid_descriptor = +static usb_ms_cid_descr_t usb_ms_cid_descriptor = { .dLength = 0x28, .wVersion = 0x100, @@ -212,7 +212,7 @@ usb_ms_cid_descr_t usb_ms_cid_descriptor = .bCompatibleId[5] = 'B', }; -usb_ms_ext_prop_descr_t usb_ms_ext_prop_descriptor_ums = +static usb_ms_ext_prop_descr_t usb_ms_ext_prop_descriptor_ums = { .dLength = 0x48, .wVersion = 0x100, @@ -251,7 +251,7 @@ usb_ms_ext_prop_descr_t usb_ms_ext_prop_descriptor_ums = .wPropertyData[1] = 0x10, }; -usb_ms_ext_prop_descr_t usb_ms_ext_prop_descriptor_hid = +static usb_ms_ext_prop_descr_t usb_ms_ext_prop_descriptor_hid = { .dLength = 7, .wVersion = 0x100, @@ -259,7 +259,7 @@ usb_ms_ext_prop_descr_t usb_ms_ext_prop_descriptor_hid = .wSections = 0, }; -usb_dev_descr_t usb_device_descriptor_hid_jc = +static usb_dev_descr_t usb_device_descriptor_hid_jc = { .bLength = 18, .bDescriptorType = USB_DESCRIPTOR_DEVICE, @@ -277,7 +277,7 @@ usb_dev_descr_t usb_device_descriptor_hid_jc = .bNumConfigs = 1 }; -usb_dev_descr_t usb_device_descriptor_hid_touch = +static usb_dev_descr_t usb_device_descriptor_hid_touch = { .bLength = 18, .bDescriptorType = USB_DESCRIPTOR_DEVICE, @@ -332,6 +332,8 @@ u8 hid_report_descriptor_jc[] = 0xc0 // END_COLLECTION(), }; +u32 hid_report_descriptor_jc_size = sizeof(hid_report_descriptor_jc); + u8 hid_report_descriptor_touch[] = { 0x05, 0x0d, // USAGE_PAGE (Digitizers) @@ -388,6 +390,7 @@ u8 hid_report_descriptor_touch[] = 0xc0, // END_COLLECTION 0xc0, // END_COLLECTION }; +u32 hid_report_descriptor_touch_size = sizeof(hid_report_descriptor_touch); static usb_cfg_hid_descr_t usb_configuration_descriptor_hid_jc = { @@ -418,7 +421,7 @@ static usb_cfg_hid_descr_t usb_configuration_descriptor_hid_jc = .hid.bCountryCode = 0, .hid.bNumDescriptors = 1, .hid.bClassDescriptorType = USB_DESCRIPTOR_HID_REPORT, - .hid.bDescriptorLength = 0x43, + .hid.bDescriptorLength = sizeof(hid_report_descriptor_jc), /* Endpoint descriptor structure EP1 IN */ .endpoint[0].bLength = 7, @@ -437,28 +440,28 @@ static usb_cfg_hid_descr_t usb_configuration_descriptor_hid_jc = .endpoint[1].bInterval = 4 // 4ms on FS, 8ms on HS. }; -u8 usb_vendor_string_descriptor_hid[22] = +static u8 usb_vendor_string_descriptor_hid[22] = { 16, 0x03, 'N', 0, 'y', 0, 'x', 0, ' ', 0, 'U', 0, 'S', 0, 'B', 0 }; -u8 usb_product_string_descriptor_hid_jc[24] = +static u8 usb_product_string_descriptor_hid_jc[24] = { 24, 0x03, 'N', 0, 'y', 0, 'x', 0, ' ', 0, 'J', 0, 'o', 0, 'y', 0, '-', 0, 'C', 0, 'o', 0, 'n', 0 }; -u8 usb_product_string_descriptor_hid_touch[26] = +static u8 usb_product_string_descriptor_hid_touch[26] = { 26, 0x03, 'N', 0, 'y', 0, 'x', 0, ' ', 0, 'T', 0, 'o', 0, 'u', 0, 'c', 0, 'h', 0, 'p', 0, 'a', 0, 'd', 0 }; -usb_cfg_hid_descr_t usb_configuration_descriptor_hid_touch = +static usb_cfg_hid_descr_t usb_configuration_descriptor_hid_touch = { /* Configuration descriptor structure */ .config.bLength = 9, diff --git a/bdk/usb/usb_gadget_hid.c b/bdk/usb/usb_gadget_hid.c index e26dd9a..0772864 100644 --- a/bdk/usb/usb_gadget_hid.c +++ b/bdk/usb/usb_gadget_hid.c @@ -67,6 +67,7 @@ typedef struct _jc_cal_t } jc_cal_t; static jc_cal_t jc_cal_ctx; +static usb_ops_t usb_ops; static bool _jc_calibration(jc_gamepad_rpt_t *jc_pad) { @@ -306,12 +307,12 @@ static bool _fts_touch_read(touchpad_report_t *rpt) static u8 _hid_transfer_start(usb_ctxt_t *usbs, u32 len) { - u8 status = usb_device_write_ep1_in((u8 *)USB_EP_BULK_IN_BUF_ADDR, len, NULL, true); - + u8 status = usb_ops.usb_device_ep1_in_write((u8 *)USB_EP_BULK_IN_BUF_ADDR, len, NULL, USB_XFER_SYNCED); if (status == 26) { usbs->set_text(usbs->label, "#C7EA46 Status:# Error EP IN"); - usbd_flush_endpoint(3); + if (usb_ops.usbd_flush_endpoint) + usb_ops.usbd_flush_endpoint(USB_EP_BULK_IN); } // Linux mitigation: If timed out, clear status. @@ -350,6 +351,8 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs) u32 gadget_type; u32 polling_time; + // Get USB Controller ops. + usb_device_get_ops(&usb_ops); if (usbs->type == USB_HID_GAMEPAD) { polling_time = 8000; @@ -363,21 +366,21 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs) usbs->set_text(usbs->label, "#C7EA46 Status:# Started USB"); - if (usb_device_init()) + if (usb_ops.usb_device_init()) { - usbd_end(false, true); + usb_ops.usbd_end(false, true); return 1; } usbs->set_text(usbs->label, "#C7EA46 Status:# Waiting for connection"); // Initialize Control Endpoint. - if (usb_device_ep0_initialize(gadget_type)) + if (usb_ops.usb_device_enumerate(gadget_type)) goto error; usbs->set_text(usbs->label, "#C7EA46 Status:# Waiting for HID report request"); - if (usb_device_get_hid_report()) + if (usb_ops.usb_device_class_send_hid_report()) goto error; usbs->set_text(usbs->label, "#C7EA46 Status:# Started HID emulation"); @@ -400,11 +403,11 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs) } // Check for suspended USB in case the cable was pulled. - if (usb_device_get_suspended()) + if (usb_ops.usb_device_get_suspended()) break; // Disconnected. // Handle control endpoint. - usbd_handle_ep0_pending_control_transfer(); + usb_ops.usbd_handle_ep0_ctrl_setup(); // Wait max gadget timing. timer = get_tmr_us() - timer; @@ -426,7 +429,7 @@ error: res = 1; exit: - usbd_end(true, false); + usb_ops.usbd_end(true, false); return res; } diff --git a/bdk/usb/usb_gadget_ums.c b/bdk/usb/usb_gadget_ums.c index 00d399c..70efa77 100644 --- a/bdk/usb/usb_gadget_ums.c +++ b/bdk/usb/usb_gadget_ums.c @@ -221,6 +221,8 @@ typedef struct _usbd_gadget_ums_t { void (*set_text)(void *, const char *); } usbd_gadget_ums_t; +static usb_ops_t usb_ops; + static inline void put_array_le_to_be16(u16 val, void *p) { u8 *_p = p; @@ -271,7 +273,7 @@ static void raise_exception(usbd_gadget_ums_t *ums, enum ums_state new_state) static void ums_handle_ep0_ctrl(usbd_gadget_ums_t *ums) { - if (usbd_handle_ep0_pending_control_transfer()) + if (usb_ops.usbd_handle_ep0_ctrl_setup()) raise_exception(ums, UMS_STATE_PROTOCOL_RESET); } @@ -284,30 +286,36 @@ static int ums_wedge_bulk_in_endpoint(usbd_gadget_ums_t *ums) static int ums_set_stall(u32 ep) { - usbd_set_ep_stall(ep, 1); + usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_STALL); return 0; } static int ums_clear_stall(u32 ep) { - usbd_set_ep_stall(ep, 0); + usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_CLEAR); return 0; } +static void ums_flush_endpoint(u32 ep) +{ + if (usb_ops.usbd_flush_endpoint) + usb_ops.usbd_flush_endpoint(ep); +} + static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, bool sync) { if (ep == bulk_ctxt->bulk_in) { - bulk_ctxt->bulk_in_status = usb_device_write_ep1_in( + bulk_ctxt->bulk_in_status = usb_ops.usb_device_ep1_in_write( bulk_ctxt->bulk_in_buf, bulk_ctxt->bulk_in_length, &bulk_ctxt->bulk_in_length_actual, sync); if (bulk_ctxt->bulk_in_status == 26) { ums->set_text(ums->label, "#C7EA46 Status:# Error EP IN"); - usbd_flush_endpoint(bulk_ctxt->bulk_in); + ums_flush_endpoint(bulk_ctxt->bulk_in); } if (sync) @@ -315,14 +323,14 @@ static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, } else { - bulk_ctxt->bulk_out_status = usb_device_read_ep1_out( + bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_read( bulk_ctxt->bulk_out_buf, bulk_ctxt->bulk_out_length, &bulk_ctxt->bulk_out_length_actual, sync); if (bulk_ctxt->bulk_out_status == 26) { ums->set_text(ums->label, "#C7EA46 Status:# Error EP OUT"); - usbd_flush_endpoint(bulk_ctxt->bulk_out); + ums_flush_endpoint(bulk_ctxt->bulk_out); } if (sync) @@ -332,14 +340,14 @@ static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, static void _ums_transfer_out_big_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { - bulk_ctxt->bulk_out_status = usb_device_read_ep1_out_big_reads( + bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_read_big( bulk_ctxt->bulk_out_buf, bulk_ctxt->bulk_out_length, &bulk_ctxt->bulk_out_length_actual); if (bulk_ctxt->bulk_out_status == 26) { ums->set_text(ums->label, "#C7EA46 Status:# Error EP OUT"); - usbd_flush_endpoint(bulk_ctxt->bulk_out); + ums_flush_endpoint(bulk_ctxt->bulk_out); } bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL; @@ -349,24 +357,26 @@ static void _ums_transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, { if (ep == bulk_ctxt->bulk_in) { - bulk_ctxt->bulk_in_status = usb_device_ep1_in_writing_finish(&bulk_ctxt->bulk_in_length_actual); + bulk_ctxt->bulk_in_status = usb_ops.usb_device_ep1_in_writing_finish( + &bulk_ctxt->bulk_in_length_actual); if (bulk_ctxt->bulk_in_status == 26) { ums->set_text(ums->label, "#C7EA46 Status:# Error EP IN"); - usbd_flush_endpoint(bulk_ctxt->bulk_in); + ums_flush_endpoint(bulk_ctxt->bulk_in); } bulk_ctxt->bulk_in_buf_state = BUF_STATE_EMPTY; } else { - bulk_ctxt->bulk_out_status = usb_device_ep1_out_reading_finish(&bulk_ctxt->bulk_out_length_actual); + bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_reading_finish( + &bulk_ctxt->bulk_out_length_actual, 1000000); if (bulk_ctxt->bulk_out_status == 26) { ums->set_text(ums->label, "#C7EA46 Status:# Error EP OUT"); - usbd_flush_endpoint(bulk_ctxt->bulk_out); + ums_flush_endpoint(bulk_ctxt->bulk_out); } bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL; @@ -497,7 +507,7 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) break; // Start the USB transfer. - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, false); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_START); first_read = false; // Increment our buffer to read new data. @@ -943,7 +953,7 @@ static int _scsi_mode_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) buf += 4; } else // SC_MODE_SENSE_10. - { + { buf[3] = (ums->lun.ro ? 0x80 : 0x00); // WP, DPOFUA. buf += 8; } @@ -1382,7 +1392,7 @@ static int pad_with_zeros(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) u32 nsend = MIN(ums->usb_amount_left, USB_EP_BUFFER_MAX_SIZE); memset(bulk_ctxt->bulk_in_buf + current_len_to_keep, 0, nsend - current_len_to_keep); bulk_ctxt->bulk_in_length = nsend; - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, true); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); ums->usb_amount_left -= nsend; current_len_to_keep = 0; } @@ -1400,7 +1410,7 @@ static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) u32 amount = MIN(ums->usb_amount_left, USB_EP_BUFFER_MAX_SIZE); bulk_ctxt->bulk_out_length = amount; - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, true); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED); ums->usb_amount_left -= amount; return 0; @@ -1447,7 +1457,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) // If there's no residue, simply send the last buffer. if (!ums->residue) { - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, true); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); /* For Bulk-only, if we're allowed to stall then send the * short packet and halt the bulk-in endpoint. If we can't @@ -1455,7 +1465,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) } else if (ums->can_stall) { - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, true); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); rc = ums_set_stall(bulk_ctxt->bulk_in); ums->set_text(ums->label, "#C7EA46 Status:# Residue. Stalled EP IN"); } @@ -1528,7 +1538,7 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) { if (bulk_ctxt->bulk_out_status == 3) { - if (usb_device_get_port_status() == 0x885) + if (usb_ops.usb_device_get_port_in_sleep()) { ums->set_text(ums->label, "#C7EA46 Status:# EP in sleep"); ums->timeouts += 10; @@ -1634,7 +1644,7 @@ static int get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) bulk_ctxt->bulk_out_length = USB_BULK_CB_WRAP_LEN; /* Queue a request to read a Bulk-only CBW */ - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, true); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED); /* We will drain the buffer in software, which means we * can reuse it for the next filling. No need to advance @@ -1680,7 +1690,7 @@ static void send_status(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) csw->Status = status; bulk_ctxt->bulk_in_length = USB_BULK_CS_WRAP_LEN; - _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, true); + _ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED); } static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) @@ -1688,8 +1698,8 @@ static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) enum ums_state old_state; /* Clear out the controller's fifos */ - usbd_flush_endpoint(bulk_ctxt->bulk_in); - usbd_flush_endpoint(bulk_ctxt->bulk_out); + ums_flush_endpoint(bulk_ctxt->bulk_in); + ums_flush_endpoint(bulk_ctxt->bulk_out); /* Reset the I/O buffer states and pointers, the SCSI * state, and the exception. Then invoke the handler. */ @@ -1764,26 +1774,25 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs) int res = 0; sdmmc_t sdmmc; sdmmc_storage_t storage; + usbd_gadget_ums_t ums = {0}; + // Get USB Controller ops. + usb_device_get_ops(&usb_ops); usbs->set_text(usbs->label, "#C7EA46 Status:# Started USB"); - if (usb_device_init()) + if (usb_ops.usb_device_init()) { - usbd_end(false, true); + usb_ops.usbd_end(false, true); return 1; } - usbd_gadget_ums_t ums; - memset(&ums, 0, sizeof(usbd_gadget_ums_t)); - - ums.bulk_out_maxpacket = usbd_get_max_pkt_length(USB_EP_BULK_IN); ums.state = UMS_STATE_NORMAL; ums.can_stall = 0; - ums.bulk_ctxt.bulk_in = 3; + ums.bulk_ctxt.bulk_in = USB_EP_BULK_IN; ums.bulk_ctxt.bulk_in_buf = (u8 *)USB_EP_BULK_IN_BUF_ADDR; - ums.bulk_ctxt.bulk_out = 2; + ums.bulk_ctxt.bulk_out = USB_EP_BULK_OUT; ums.bulk_ctxt.bulk_out_buf = (u8 *)USB_EP_BULK_OUT_BUF_ADDR; // Set LUN parameters. @@ -1820,12 +1829,12 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs) ums.set_text(ums.label, "#C7EA46 Status:# Waiting for connection"); // Initialize Control Endpoint. - if (usb_device_ep0_initialize(USB_GADGET_UMS)) + if (usb_ops.usb_device_enumerate(USB_GADGET_UMS)) goto error; ums.set_text(ums.label, "#C7EA46 Status:# Waiting for LUN"); - if (usb_device_get_max_lun(0)) // One device for now. + if (usb_ops.usb_device_class_send_max_lun(0)) // One device for now. goto error; ums.set_text(ums.label, "#C7EA46 Status:# Started UMS"); @@ -1885,7 +1894,7 @@ exit: if (ums.lun.type == MMC_EMMC) sdmmc_storage_end(ums.lun.storage); - usbd_end(true, false); + usb_ops.usbd_end(true, false); return res; } diff --git a/bdk/usb/usb_t210.h b/bdk/usb/usb_t210.h index 3bc83b1..6b07609 100644 --- a/bdk/usb/usb_t210.h +++ b/bdk/usb/usb_t210.h @@ -1,7 +1,7 @@ /* * Enhanced USB (EHCI) device driver for Tegra X1 * - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2020 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/bdk/usb/usbd.c b/bdk/usb/usbd.c index ea4d146..ae62f09 100644 --- a/bdk/usb/usbd.c +++ b/bdk/usb/usbd.c @@ -1,7 +1,7 @@ /* * Enhanced USB (EHCI) Device driver for Tegra X1 * - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2020 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include @@ -42,20 +42,6 @@ typedef enum USB_HW_EP1 = 1 } usb_hw_ep_t; -typedef enum -{ - USB_EP_ADDR_CTRL_OUT = 0x00, - USB_EP_ADDR_CTRL_IN = 0x80, - USB_EP_ADDR_BULK_OUT = 0x01, - USB_EP_ADDR_BULK_IN = 0x81, -} usb_ep_addr_t; - -typedef enum -{ - USB_EP_CFG_RESET = 0, - USB_EP_CFG_STALL = 1 -} usb_ep_cfg_t; - typedef enum { USB_EP_STATUS_IDLE = 0, @@ -67,72 +53,12 @@ typedef enum } usb_ep_status_t; typedef enum { - USB_SETUP_RECIPIENT_DEVICE = 0, - USB_SETUP_RECIPIENT_INTERFACE = 1, - USB_SETUP_RECIPIENT_ENDPOINT = 2, - USB_SETUP_RECIPIENT_OTHER = 3, - - USB_SETUP_TYPE_STANDARD = 0x00, - USB_SETUP_TYPE_CLASS = 0x20, - USB_SETUP_TYPE_VENDOR = 0x40, - USB_SETUP_TYPE_RESERVED = 0x60, - - USB_SETUP_HOST_TO_DEVICE = 0x00, - USB_SETUP_DEVICE_TO_HOST = 0x80, -} usb_setup_req_type_t; - -typedef enum { - USB_REQUEST_GET_STATUS = 0, - USB_REQUEST_CLEAR_FEATURE = 1, - USB_REQUEST_SET_FEATURE = 3, - USB_REQUEST_SET_ADDRESS = 5, - USB_REQUEST_GET_DESCRIPTOR = 6, - USB_REQUEST_SET_DESCRIPTOR = 7, - USB_REQUEST_GET_CONFIGURATION = 8, - USB_REQUEST_SET_CONFIGURATION = 9, - USB_REQUEST_GET_INTERFACE = 10, - USB_REQUEST_SET_INTERFACE = 11, - USB_REQUEST_SYNCH_FRAME = 12, - - USB_REQUEST_GET_MS_DESCRIPTOR = 0x99, - - USB_REQUEST_BULK_GET_MAX_LUN = 0xFE, - USB_REQUEST_BULK_RESET = 0xFF -} usb_standard_req_t; - -typedef enum { - USB_FEATURE_ENDPOINT_HALT = 0, - USB_FEATURE_DEVICE_REMOTE_WAKEUP = 1, - USB_FEATURE_TEST_MODE = 2, -} usb_get_status_req_t; - -typedef enum { - USB_STATUS_EP_OK = 0, - USB_STATUS_EP_HALTED = 1, - - USB_STATUS_DEV_SELF_POWERED = 1, - USB_STATUS_DEV_REMOTE_WAKE = 2, -} usb_set_clear_feature_req_t; - -typedef enum { - USB_XFER_DIR_OUT = 0, - USB_XFER_DIR_IN = 1, -} usb_xfer_dir_t; - -typedef enum { - USB_SPEED_LOW = 0, - USB_SPEED_FULL = 1, - USB_SPEED_HIGH = 2, - USB_SPEED_SUPER = 3, + USB_LOW_SPEED = 0, + USB_FULL_SPEED = 1, + USB_HIGH_SPEED = 2, + USB_SUPER_SPEED = 3, } usb_speed_t; -typedef enum { - USB_XFER_TYPE_CONTROL = 0, - USB_XFER_TYPE_ISOCHRONOUS = 1, - USB_XFER_TYPE_BULK = 2, - USB_XFER_TYPE_INTERRUPT = 3, -} usb_xfer_type_t; - typedef struct _dTD_t { vu32 next_dTD; @@ -161,15 +87,6 @@ typedef struct _usbd_t int ep_bytes_requested[4]; } usbd_t; -typedef struct _usb_ctrl_setup_t -{ - u8 bmRequestType; - u8 bRequest; - u16 wValue; - u16 wIndex; - u16 wLength; -} usb_ctrl_setup_t; - typedef struct _usbd_controller_t { u32 port_speed; @@ -188,6 +105,15 @@ typedef struct _usbd_controller_t bool charger_detect; } usbd_controller_t; +extern u8 hid_report_descriptor_jc[]; +extern u8 hid_report_descriptor_touch[]; +extern u32 hid_report_descriptor_jc_size; +extern u32 hid_report_descriptor_touch_size; + +extern usb_desc_t usb_gadget_hid_jc_descriptors; +extern usb_desc_t usb_gadget_hid_touch_descriptors; +extern usb_desc_t usb_gadget_ums_descriptors; + usbd_t *usbdaemon; usbd_controller_t *usbd_otg; @@ -535,10 +461,10 @@ static void _usb_device_power_down() usb_init_done = false; } -static void _usbd_stall_reset_ep1(usb_xfer_dir_t direction, usb_ep_cfg_t stall) +static void _usbd_stall_reset_ep1(usb_dir_t direction, usb_ep_cfg_t stall) { stall &= 1; - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) { usbd_otg->regs->endptctrl[1] = (usbd_otg->regs->endptctrl[1] & ~USB2D_ENDPTCTRL_TX_EP_STALL) | ((u32)stall << 16); if (!stall) @@ -552,39 +478,14 @@ static void _usbd_stall_reset_ep1(usb_xfer_dir_t direction, usb_ep_cfg_t stall) } } -void usbd_end(bool reset_ep, bool only_controller) -{ - if (reset_ep) - { - usbd_flush_endpoint(USB_EP_ALL); - _usbd_stall_reset_ep1(0, USB_EP_CFG_RESET); // EP1 Bulk IN. - _usbd_stall_reset_ep1(1, USB_EP_CFG_RESET); // EP1 Bulk OUT. - //TODO: what about EP0 simultaneous in/out reset. - - usbd_otg->configuration = 0; - usbd_otg->interface = 0; - usbd_otg->configuration_set = 0; - usbd_otg->max_lun_set = 0; - } - - // Stop device controller. - usbd_otg->regs->usbcmd &= ~USB2D_USBCMD_RUN; - - // Enable PHY auto low power suspend. - usbd_otg->regs->hostpc1_devlc |= USB2D_HOSTPC1_DEVLC_ASUS; - - if (!only_controller) - _usb_device_power_down(); -} - void usb_device_stall_ep1_bulk_out() { - _usbd_stall_reset_ep1(USB_XFER_DIR_OUT, USB_EP_CFG_STALL); + _usbd_stall_reset_ep1(USB_DIR_OUT, USB_EP_CFG_STALL); } void usb_device_stall_ep1_bulk_in() { - _usbd_stall_reset_ep1(USB_XFER_DIR_IN, USB_EP_CFG_STALL); + _usbd_stall_reset_ep1(USB_DIR_IN, USB_EP_CFG_STALL); } int usbd_get_max_pkt_length(int endpoint) @@ -608,7 +509,7 @@ int usbd_get_max_pkt_length(int endpoint) static void _usbd_initialize_ep_ctrl(u32 endpoint) { usb_hw_ep_t actual_ep = (endpoint & 2) >> 1; - usb_xfer_dir_t direction = endpoint & 1; + usb_dir_t direction = endpoint & 1; memset((void *)&usbdaemon->qhs[endpoint], 0, sizeof(dQH_t)); @@ -620,7 +521,7 @@ static void _usbd_initialize_ep_ctrl(u32 endpoint) u32 max_packet_len = usbd_get_max_pkt_length(endpoint) & USB_QHD_EP_CAP_MAX_PKT_LEN_MASK; usbdaemon->qhs[endpoint].ep_capabilities |= max_packet_len << 16; - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) { u32 endpoint_type = usbd_otg->regs->endptctrl[actual_ep] & ~USB2D_ENDPTCTRL_TX_EP_TYPE_MASK; if (actual_ep) @@ -700,13 +601,13 @@ int usbd_flush_endpoint(u32 endpoint) { usb_hw_ep_t actual_ep = (endpoint & 2) >> 1; - usb_xfer_dir_t direction = endpoint & 1; + usb_dir_t direction = endpoint & 1; u32 reg_mask = endpoint; // Flash all endpoints or 1. if (endpoint != USB_EP_ALL) { - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) reg_mask = USB2D_ENDPT_STATUS_TX_OFFSET << actual_ep; else reg_mask = USB2D_ENDPT_STATUS_RX_OFFSET << actual_ep; @@ -745,11 +646,36 @@ int usbd_flush_endpoint(u32 endpoint) return 0; } +void usbd_end(bool reset_ep, bool only_controller) +{ + if (reset_ep) + { + usbd_flush_endpoint(USB_EP_ALL); + _usbd_stall_reset_ep1(0, USB_EP_CFG_RESET); // EP1 Bulk IN. + _usbd_stall_reset_ep1(1, USB_EP_CFG_RESET); // EP1 Bulk OUT. + //TODO: what about EP0 simultaneous in/out reset. + + usbd_otg->configuration = 0; + usbd_otg->interface = 0; + usbd_otg->configuration_set = false; + usbd_otg->max_lun_set = false; + } + + // Stop device controller. + usbd_otg->regs->usbcmd &= ~USB2D_USBCMD_RUN; + + // Enable PHY auto low power suspend. + usbd_otg->regs->hostpc1_devlc |= USB2D_HOSTPC1_DEVLC_ASUS; + + if (!only_controller) + _usb_device_power_down(); +} + static void _usbd_mark_ep_complete(u32 endpoint) { u32 complete_bit; usb_hw_ep_t actual_ep = (endpoint & 2) >> 1; - usb_xfer_dir_t direction = endpoint & 1; + usb_dir_t direction = endpoint & 1; usbd_flush_endpoint(endpoint); memset((void *)&usbdaemon->dtds[endpoint * 4], 0, sizeof(dTD_t) * 4); @@ -757,7 +683,7 @@ static void _usbd_mark_ep_complete(u32 endpoint) usbdaemon->ep_configured[endpoint] = 0; usbdaemon->ep_bytes_requested[endpoint] = 0; - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) complete_bit = USB2D_ENDPT_STATUS_TX_OFFSET << actual_ep; else complete_bit = USB2D_ENDPT_STATUS_RX_OFFSET << actual_ep; @@ -771,9 +697,9 @@ static usb_ep_status_t _usbd_get_ep_status(usb_ep_t endpoint) u32 reg_val; u32 reg_mask; u32 actual_ep = (endpoint & 2) >> 1; - usb_xfer_dir_t direction = endpoint & 1; + usb_dir_t direction = endpoint & 1; - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) reg_mask = USB2D_ENDPT_STATUS_TX_OFFSET << actual_ep; else reg_mask = USB2D_ENDPT_STATUS_RX_OFFSET << actual_ep; @@ -784,7 +710,7 @@ static usb_ep_status_t _usbd_get_ep_status(usb_ep_t endpoint) reg_val = usbd_otg->regs->endptctrl[0]; // Check stalled status. - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) status = reg_val & USB2D_ENDPTCTRL_TX_EP_STALL; else status = reg_val & USB2D_ENDPTCTRL_RX_EP_STALL; @@ -793,7 +719,7 @@ static usb_ep_status_t _usbd_get_ep_status(usb_ep_t endpoint) return USB_EP_STATUS_STALLED; // Check enabled status. - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) status = reg_val & USB2D_ENDPTCTRL_TX_EP_ENABLE; else status = reg_val & USB2D_ENDPTCTRL_RX_EP_ENABLE; @@ -824,7 +750,7 @@ static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, bool sync) u32 prime_bit; usb_hw_ep_t actual_ep = (endpoint & 2) >> 1; - usb_xfer_dir_t direction = endpoint & 1; + usb_dir_t direction = endpoint & 1; u32 length_left = len; u32 dtd_ep_idx = endpoint * 4; @@ -877,7 +803,7 @@ static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, bool sync) AHB_GIZMO(AHB_AHB_MEM_PREFETCH_CFG1) &= ~MEM_PREFETCH_ENABLE; AHB_GIZMO(AHB_AHB_MEM_PREFETCH_CFG1) |= MEM_PREFETCH_ENABLE; - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) { prime_bit = USB2D_ENDPT_STATUS_TX_OFFSET << actual_ep; bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); @@ -918,7 +844,7 @@ out: else if (_usbd_get_ep_status(endpoint) != USB_EP_STATUS_IDLE) res = 26; - if (direction == USB_XFER_DIR_OUT) + if (direction == USB_DIR_OUT) bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); } @@ -938,25 +864,27 @@ static void _usbd_set_ep0_stall() USB2D_ENDPTCTRL_RX_EP_ENABLE | USB2D_ENDPTCTRL_RX_EP_STALL; } -void usbd_set_ep_stall(u32 endpoint, int ep_stall) +int usbd_set_ep_stall(u32 endpoint, int ep_stall) { usb_hw_ep_t actual_ep = (endpoint & 2) >> 1; - usb_xfer_dir_t direction = endpoint & 1; + usb_dir_t direction = endpoint & 1; if (ep_stall) { - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) usbd_otg->regs->endptctrl[actual_ep] |= USB2D_ENDPTCTRL_TX_EP_STALL; // Stall EP Bulk IN. else usbd_otg->regs->endptctrl[actual_ep] |= USB2D_ENDPTCTRL_RX_EP_STALL; // Stall EP Bulk OUT. } else { - if (direction == USB_XFER_DIR_IN) + if (direction == USB_DIR_IN) usbd_otg->regs->endptctrl[actual_ep] &= ~USB2D_ENDPTCTRL_TX_EP_STALL; // Clear stall EP Bulk IN. else usbd_otg->regs->endptctrl[actual_ep] &= ~USB2D_ENDPTCTRL_RX_EP_STALL; // Clear stall EP Bulk OUT. } + + return 0; } static void _usbd_handle_get_class_request(bool *transmit_data, u8 *descriptor, int *size, int *ep_stall) @@ -1256,12 +1184,12 @@ static int _usbd_handle_ep0_control_transfer() if (usbd_otg->type == USB_GADGET_HID_GAMEPAD) { descriptor = (u8 *)&hid_report_descriptor_jc; - _wLength = sizeof(hid_report_descriptor_jc); + _wLength = hid_report_descriptor_jc_size; } else // USB_GADGET_HID_TOUCHPAD { descriptor = (u8 *)&hid_report_descriptor_touch; - _wLength = sizeof(hid_report_descriptor_touch); + _wLength = hid_report_descriptor_touch_size; } usbd_otg->hid_report_sent = 1; @@ -1432,7 +1360,7 @@ static int _usbd_ep0_initialize() return 3; } -int usb_device_ep0_initialize(usb_gadget_type type) +int usb_device_enumerate(usb_gadget_type type) { switch (type) { @@ -1455,7 +1383,7 @@ int usb_device_ep0_initialize(usb_gadget_type type) return result; } -int usbd_handle_ep0_pending_control_transfer() +int usbd_handle_ep0_ctrl_setup() { // Acknowledge setup request for EP0 and copy its configuration. u32 ep0_setup_req = usbd_otg->regs->endptsetupstat; @@ -1476,17 +1404,17 @@ int usbd_handle_ep0_pending_control_transfer() return 0; } -static usb_ep_status_t _usbd_get_ep1_status(usb_xfer_dir_t dir) +static usb_ep_status_t _usbd_get_ep1_status(usb_dir_t dir) { usb_ep_t ep; - if (dir == USB_XFER_DIR_OUT) + if (dir == USB_DIR_OUT) ep = USB_EP_BULK_OUT; else ep = USB_EP_BULK_IN; return _usbd_get_ep_status(ep); } -int usb_device_read_ep1_out(u8 *buf, u32 len, u32 *bytes_read, bool sync) +int usb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, bool sync) { if (len > USB_EP_BUFFER_MAX_SIZE) len = USB_EP_BUFFER_MAX_SIZE; @@ -1504,7 +1432,7 @@ int usb_device_read_ep1_out(u8 *buf, u32 len, u32 *bytes_read, bool sync) return result; } -int usb_device_read_ep1_out_big_reads(u8 *buf, u32 len, u32 *bytes_read) +int usb_device_ep1_out_read_big(u8 *buf, u32 len, u32 *bytes_read) { if (len > USB_EP_BULK_OUT_MAX_XFER) len = USB_EP_BULK_OUT_MAX_XFER; @@ -1518,7 +1446,7 @@ int usb_device_read_ep1_out_big_reads(u8 *buf, u32 len, u32 *bytes_read) { u32 len_ep = MIN(len, USB_EP_BUFFER_MAX_SIZE); - result = usb_device_read_ep1_out(buf_curr, len_ep, &bytes, true); + result = usb_device_ep1_out_read(buf_curr, len_ep, &bytes, USB_XFER_SYNCED); if (!result) { len -= len_ep; @@ -1540,16 +1468,16 @@ static int _usbd_get_ep1_out_bytes_read() return (usbdaemon->ep_bytes_requested[2] - (usbdaemon->qhs[2].token >> 16)); } -int usb_device_ep1_out_reading_finish(u32 *pending_bytes) +int usb_device_ep1_out_reading_finish(u32 *pending_bytes, int tries) { usb_ep_status_t ep_status; do { - ep_status = _usbd_get_ep1_status(USB_XFER_DIR_OUT); + ep_status = _usbd_get_ep1_status(USB_DIR_OUT); if ((ep_status == USB_EP_STATUS_IDLE) || (ep_status == USB_EP_STATUS_DISABLED)) break; - usbd_handle_ep0_pending_control_transfer(); + usbd_handle_ep0_ctrl_setup(); } while ((ep_status == USB_EP_STATUS_ACTIVE) || (ep_status == USB_EP_STATUS_STALLED)); @@ -1565,7 +1493,7 @@ int usb_device_ep1_out_reading_finish(u32 *pending_bytes) return 26; } -int usb_device_write_ep1_in(u8 *buf, u32 len, u32 *bytes_written, bool sync) +int usb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, bool sync) { if (len > USB_EP_BUFFER_MAX_SIZE) len = USB_EP_BUFFER_MAX_SIZE; @@ -1596,11 +1524,11 @@ int usb_device_ep1_in_writing_finish(u32 *pending_bytes) usb_ep_status_t ep_status; do { - ep_status = _usbd_get_ep1_status(USB_XFER_DIR_IN); + ep_status = _usbd_get_ep1_status(USB_DIR_IN); if ((ep_status == USB_EP_STATUS_IDLE) || (ep_status == USB_EP_STATUS_DISABLED)) break; - usbd_handle_ep0_pending_control_transfer(); + usbd_handle_ep0_ctrl_setup(); } while ((ep_status == USB_EP_STATUS_ACTIVE) || (ep_status == USB_EP_STATUS_STALLED)); @@ -1621,12 +1549,13 @@ bool usb_device_get_suspended() return (suspended ? true : false); } -u32 usb_device_get_port_status() +bool usb_device_get_port_in_sleep() { - return (usbd_otg->regs->portsc1); + // Windows heuristic: Forces port into suspend, sleep and J-State. + return (usbd_otg->regs->portsc1) == 0x885; } -bool usb_device_get_max_lun(u8 max_lun) +bool usb_device_class_send_max_lun(u8 max_lun) { // Timeout if get MAX_LUN request doesn't happen in 10s. u32 timer = get_tmr_ms() + 10000; @@ -1635,7 +1564,7 @@ bool usb_device_get_max_lun(u8 max_lun) while (!usbd_otg->max_lun_set) { - usbd_handle_ep0_pending_control_transfer(); + usbd_handle_ep0_ctrl_setup(); if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) return true; } @@ -1643,17 +1572,39 @@ bool usb_device_get_max_lun(u8 max_lun) return false; } -bool usb_device_get_hid_report() +bool usb_device_class_send_hid_report() { // Timeout if get GET_HID_REPORT request doesn't happen in 10s. u32 timer = get_tmr_ms() + 10000; + // Wait for request and transfer start. while (!usbd_otg->hid_report_sent) { - usbd_handle_ep0_pending_control_transfer(); + usbd_handle_ep0_ctrl_setup(); if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) return true; } return false; } + +void usb_device_get_ops(usb_ops_t *ops) +{ + ops->usbd_flush_endpoint = usbd_flush_endpoint; + ops->usbd_set_ep_stall = usbd_set_ep_stall; + ops->usbd_handle_ep0_ctrl_setup = usbd_handle_ep0_ctrl_setup; + ops->usbd_end = usbd_end; + ops->usb_device_init = usb_device_init; + ops->usb_device_enumerate = usb_device_enumerate; + ops->usb_device_class_send_max_lun = usb_device_class_send_max_lun; + ops->usb_device_class_send_hid_report = usb_device_class_send_hid_report; + ops->usb_device_get_suspended = usb_device_get_suspended; + ops->usb_device_get_port_in_sleep = usb_device_get_port_in_sleep; + + ops->usb_device_ep1_out_read = usb_device_ep1_out_read; + ops->usb_device_ep1_out_read_big = usb_device_ep1_out_read_big; + ops->usb_device_ep1_out_reading_finish = usb_device_ep1_out_reading_finish; + ops->usb_device_ep1_in_write = usb_device_ep1_in_write; + ops->usb_device_ep1_in_writing_finish = usb_device_ep1_in_writing_finish; +} + diff --git a/bdk/usb/usbd.h b/bdk/usb/usbd.h index fb64949..fb83396 100644 --- a/bdk/usb/usbd.h +++ b/bdk/usb/usbd.h @@ -29,6 +29,129 @@ #define USB_EP_BUFFER_4_TD (USB_TD_BUFFER_MAX_SIZE * 4) #define USB_EP_BUFFER_MAX_SIZE (USB_EP_BUFFER_4_TD) +#define USB_XFER_START false +#define USB_XFER_SYNCED true + +typedef enum _usb_hid_type +{ + USB_HID_GAMEPAD, + USB_HID_TOUCHPAD +} usb_hid_type; + +typedef enum _usb_gadget_type +{ + USB_GADGET_UMS = 0, + USB_GADGET_HID_GAMEPAD = 1, + USB_GADGET_HID_TOUCHPAD = 2, +} usb_gadget_type; + +typedef enum { + USB_DIR_OUT = 0, + USB_DIR_IN = 1, +} usb_dir_t; + +typedef enum +{ + USB_EP_CTRL_OUT = 0, // EP0. + USB_EP_CTRL_IN = 1, // EP0. + USB_EP_BULK_OUT = 2, // EP1. + USB_EP_BULK_IN = 3, // EP1. + USB_EP_ALL = 0xFFFFFFFF +} usb_ep_t; + +typedef enum +{ + USB_EP_ADDR_CTRL_OUT = 0x00, + USB_EP_ADDR_CTRL_IN = 0x80, + USB_EP_ADDR_BULK_OUT = 0x01, + USB_EP_ADDR_BULK_IN = 0x81, +} usb_ep_addr_t; + +typedef enum +{ + USB_EP_CFG_CLEAR = 0, + USB_EP_CFG_RESET = 0, + USB_EP_CFG_STALL = 1 +} usb_ep_cfg_t; + +typedef enum { + USB_STATUS_EP_OK = 0, + USB_STATUS_EP_HALTED = 1, + + USB_STATUS_DEV_SELF_POWERED = 1, + USB_STATUS_DEV_REMOTE_WAKE = 2, +} usb_set_clear_feature_req_t; + +typedef enum { + USB_SETUP_RECIPIENT_DEVICE = 0, + USB_SETUP_RECIPIENT_INTERFACE = 1, + USB_SETUP_RECIPIENT_ENDPOINT = 2, + USB_SETUP_RECIPIENT_OTHER = 3, + + USB_SETUP_TYPE_STANDARD = 0x00, + USB_SETUP_TYPE_CLASS = 0x20, + USB_SETUP_TYPE_VENDOR = 0x40, + USB_SETUP_TYPE_RESERVED = 0x60, + + USB_SETUP_HOST_TO_DEVICE = 0x00, + USB_SETUP_DEVICE_TO_HOST = 0x80, +} usb_setup_req_type_t; + +typedef enum { + USB_REQUEST_GET_STATUS = 0, + USB_REQUEST_CLEAR_FEATURE = 1, + USB_REQUEST_SET_FEATURE = 3, + USB_REQUEST_SET_ADDRESS = 5, + USB_REQUEST_GET_DESCRIPTOR = 6, + USB_REQUEST_SET_DESCRIPTOR = 7, + USB_REQUEST_GET_CONFIGURATION = 8, + USB_REQUEST_SET_CONFIGURATION = 9, + USB_REQUEST_GET_INTERFACE = 10, + USB_REQUEST_SET_INTERFACE = 11, + USB_REQUEST_SYNCH_FRAME = 12, + USB_REQUEST_SET_SEL = 13, + + USB_REQUEST_GET_MS_DESCRIPTOR = 0x99, + + USB_REQUEST_BULK_GET_MAX_LUN = 0xFE, + USB_REQUEST_BULK_RESET = 0xFF +} usb_standard_req_t; + +typedef enum { + USB_FEATURE_ENDPOINT_HALT = 0, + USB_FEATURE_DEVICE_REMOTE_WAKEUP = 1, + USB_FEATURE_TEST_MODE = 2, +} usb_get_status_req_t; + +typedef struct _usb_ctrl_setup_t +{ + u8 bmRequestType; + u8 bRequest; + u16 wValue; + u16 wIndex; + u16 wLength; +} usb_ctrl_setup_t; + +typedef struct _usb_ops_t +{ + int (*usbd_flush_endpoint)(u32); + int (*usbd_set_ep_stall)(u32, int); + int (*usbd_handle_ep0_ctrl_setup)(); + void (*usbd_end)(bool, bool); + int (*usb_device_init)(); + int (*usb_device_enumerate)(usb_gadget_type gadget); + bool (*usb_device_class_send_max_lun)(u8); + bool (*usb_device_class_send_hid_report)(); + + int (*usb_device_ep1_out_read)(u8 *, u32, u32 *, bool); + int (*usb_device_ep1_out_read_big)(u8 *, u32, u32 *); + int (*usb_device_ep1_out_reading_finish)(u32 *, int); + int (*usb_device_ep1_in_write)(u8 *, u32, u32 *, bool); + int (*usb_device_ep1_in_writing_finish)(u32 *); + bool (*usb_device_get_suspended)(); + bool (*usb_device_get_port_in_sleep)(); +} usb_ops_t; + typedef struct _usb_ctxt_t { u32 type; @@ -41,46 +164,10 @@ typedef struct _usb_ctxt_t void (*set_text)(void *, const char *); } usb_ctxt_t; -typedef enum _usb_hid_type -{ - USB_HID_GAMEPAD, - USB_HID_TOUCHPAD -} usb_hid_type; - -typedef enum _usb_gadget_type -{ - USB_GADGET_UMS, - USB_GADGET_HID_GAMEPAD, - USB_GADGET_HID_TOUCHPAD -} usb_gadget_type; - -typedef enum -{ - USB_EP_CTRL_OUT = 0, // EP0. - USB_EP_CTRL_IN = 1, // EP0. - USB_EP_BULK_OUT = 2, // EP1. - USB_EP_BULK_IN = 3, // EP1. - USB_EP_ALL = 0xFFFFFFFF -} usb_ep_t; - -int usbd_flush_endpoint(u32 ep); -void usbd_set_ep_stall(u32 endpoint, int ep_stall); -int usbd_get_max_pkt_length(int endpoint); -int usbd_handle_ep0_pending_control_transfer(); -void usbd_end(bool reset_ep, bool only_controller); -int usb_device_init(); -int usb_device_ep0_initialize(usb_gadget_type type); -int usb_device_read_ep1_out(u8 *buf, u32 len, u32 *bytes_read, bool sync); -int usb_device_read_ep1_out_big_reads(u8 *buf, u32 len, u32 *bytes_read); -int usb_device_ep1_out_reading_finish(u32 *pending_bytes); -int usb_device_write_ep1_in(u8 *buf, u32 len, u32 *bytes_written, bool sync); -int usb_device_ep1_in_writing_finish(u32 *pending_bytes); -bool usb_device_get_suspended(); +void usb_device_get_ops(usb_ops_t *ops); +void xusb_device_get_ops(usb_ops_t *ops); int usb_device_gadget_ums(usb_ctxt_t *usbs); int usb_device_gadget_hid(usb_ctxt_t *usbs); -bool usb_device_get_max_lun(u8 max_lun); -bool usb_device_get_hid_report(); -u32 usb_device_get_port_status(); #endif \ No newline at end of file