uplift libbdk

Signed-off-by: Damien Zhao <zdm65477730@126.com>
This commit is contained in:
Damien Zhao
2025-11-21 22:20:38 +08:00
parent 3454c13e4a
commit ec6518ccbf
73 changed files with 5114 additions and 1659 deletions

View File

@@ -151,7 +151,7 @@ typedef struct _usb_cfg_hid_descr_t
usb_cfg_descr_t config;
usb_inter_descr_t interface;
usb_hid_descr_t hid;
usb_ep_descr_t endpoint[2];
usb_ep_descr_t endpoint[1];
} __attribute__((packed)) usb_cfg_hid_descr_t;
typedef struct _usb_dev_bot_t

View File

@@ -1,7 +1,7 @@
/*
* USB driver for Tegra X1
*
* Copyright (c) 2019-2020 CTCaer
* Copyright (c) 2019-2025 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,
@@ -409,10 +409,10 @@ static usb_cfg_hid_descr_t usb_configuration_descriptor_hid_jc =
.interface.bDescriptorType = USB_DESCRIPTOR_INTERFACE,
.interface.bInterfaceNumber = 0,
.interface.bAlternateSetting = 0,
.interface.bNumEndpoints = 2,
.interface.bNumEndpoints = 1,
.interface.bInterfaceClass = 0x03, // Human Interface Device Class.
.interface.bInterfaceSubClass = 0x00, // SCSI Transparent Command Set.
.interface.bInterfaceProtocol = 0x00, // Bulk-Only Transport.
.interface.bInterfaceSubClass = 0x00, // No Subclass.
.interface.bInterfaceProtocol = 0x00, // None.
.interface.iInterface = 0x00,
.hid.bLength = 9,
@@ -430,14 +430,6 @@ static usb_cfg_hid_descr_t usb_configuration_descriptor_hid_jc =
.endpoint[0].bmAttributes = USB_EP_TYPE_INTR,
.endpoint[0].wMaxPacketSize = 0x200,
.endpoint[0].bInterval = 4, // 8ms on HS.
/* Endpoint descriptor structure EP1 OUT */
.endpoint[1].bLength = 7,
.endpoint[1].bDescriptorType = USB_DESCRIPTOR_ENDPOINT,
.endpoint[1].bEndpointAddress = 0x01, // USB_EP_ADDR_BULK_OUT.
.endpoint[1].bmAttributes = USB_EP_TYPE_INTR,
.endpoint[1].wMaxPacketSize = 0x200,
.endpoint[1].bInterval = 4 // 8ms on HS.
};
static u8 usb_vendor_string_descriptor_hid[22] =
@@ -478,10 +470,10 @@ static usb_cfg_hid_descr_t usb_configuration_descriptor_hid_touch =
.interface.bDescriptorType = USB_DESCRIPTOR_INTERFACE,
.interface.bInterfaceNumber = 0,
.interface.bAlternateSetting = 0,
.interface.bNumEndpoints = 2,
.interface.bNumEndpoints = 1,
.interface.bInterfaceClass = 0x03, // Human Interface Device Class.
.interface.bInterfaceSubClass = 0x00, // SCSI Transparent Command Set.
.interface.bInterfaceProtocol = 0x00, // Bulk-Only Transport.
.interface.bInterfaceSubClass = 0x00, // No Subclass.
.interface.bInterfaceProtocol = 0x00, // None.
.interface.iInterface = 0x00,
.hid.bLength = 9,
@@ -499,14 +491,6 @@ static usb_cfg_hid_descr_t usb_configuration_descriptor_hid_touch =
.endpoint[0].bmAttributes = USB_EP_TYPE_INTR,
.endpoint[0].wMaxPacketSize = 0x200,
.endpoint[0].bInterval = 3, // 4ms on HS.
/* Endpoint descriptor structure EP1 OUT */
.endpoint[1].bLength = 7,
.endpoint[1].bDescriptorType = USB_DESCRIPTOR_ENDPOINT,
.endpoint[1].bEndpointAddress = 0x01, // USB_EP_ADDR_BULK_OUT.
.endpoint[1].bmAttributes = USB_EP_TYPE_INTR,
.endpoint[1].wMaxPacketSize = 0x200,
.endpoint[1].bInterval = 3 // 4ms on HS.
};
usb_desc_t usb_gadget_ums_descriptors =

View File

@@ -1,7 +1,7 @@
/*
* USB Gadget HID driver for Tegra X1
*
* Copyright (c) 2019-2022 CTCaer
* Copyright (c) 2019-2025 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,
@@ -80,6 +80,8 @@ enum {
static jc_cal_t jc_cal_ctx;
static usb_ops_t usb_ops;
static void *rpt_buffer = (u8 *)USB_EP_BULK_IN_BUF_ADDR;
static bool _jc_calibration(const jc_gamepad_rpt_t *jc_pad)
{
// Calibrate left stick.
@@ -347,10 +349,10 @@ static bool _fts_touch_read(touchpad_report_t *rpt)
static u8 _hid_transfer_start(usb_ctxt_t *usbs, u32 len)
{
u8 status = usb_ops.usb_device_ep1_in_write((u8 *)USB_EP_BULK_IN_BUF_ADDR, len, NULL, USB_XFER_SYNCED_CMD);
u8 status = usb_ops.usb_device_ep1_in_write(rpt_buffer, len, NULL, USB_XFER_SYNCED_CMD);
if (status == USB_ERROR_XFER_ERROR)
{
usbs->set_text(usbs->label, "#FFDD00 错误#EP IN传输");
usbs->set_text(usbs->label, "#FFDD00 错误:#端口IN传输错误!");
if (usb_ops.usbd_flush_endpoint)
usb_ops.usbd_flush_endpoint(USB_EP_BULK_IN);
}
@@ -364,12 +366,12 @@ static u8 _hid_transfer_start(usb_ctxt_t *usbs, u32 len)
static bool _hid_poll_jc(usb_ctxt_t *usbs)
{
int res = _jc_poll((gamepad_report_t *)USB_EP_BULK_IN_BUF_ADDR);
int res = _jc_poll(rpt_buffer);
if (res == INPUT_POLL_EXIT)
return true;
// Send HID report.
if (res == INPUT_POLL_HAS_PACKET)
if (res == INPUT_POLL_HAS_PACKET || usbs->idle)
if (_hid_transfer_start(usbs, sizeof(gamepad_report_t)))
return true; // EP Error.
@@ -378,7 +380,7 @@ static bool _hid_poll_jc(usb_ctxt_t *usbs)
static bool _hid_poll_touch(usb_ctxt_t *usbs)
{
_fts_touch_read((touchpad_report_t *)USB_EP_BULK_IN_BUF_ADDR);
_fts_touch_read(rpt_buffer);
// Send HID report.
if (_hid_transfer_start(usbs, sizeof(touchpad_report_t)))
@@ -399,6 +401,10 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs)
else
xusb_device_get_ops(&usb_ops);
// Always push packets by default.
//! TODO: For now only per polling rate or on change is supported.
usbs->idle = 1;
if (usbs->type == USB_HID_GAMEPAD)
{
polling_time = 15000;
@@ -410,7 +416,7 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs)
gadget_type = USB_GADGET_HID_TOUCHPAD;
}
usbs->set_text(usbs->label, "#C7EA46 状态#USB1已开启");
usbs->set_text(usbs->label, "#C7EA46 状态:#USB已启动");
if (usb_ops.usb_device_init())
{
@@ -418,24 +424,32 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs)
return 1;
}
usbs->set_text(usbs->label, "#C7EA46 状态#等待连接");
usbs->set_text(usbs->label, "#C7EA46 状态:#正在等待连接");
// Initialize Control Endpoint.
if (usb_ops.usb_device_enumerate(gadget_type))
goto error;
usbs->set_text(usbs->label, "#C7EA46 状态#等待HID报请求");
usbs->set_text(usbs->label, "#C7EA46 状态:#正在等待HID报请求");
if (usb_ops.usb_device_class_send_hid_report())
u32 rpt_size = usbs->type == USB_HID_GAMEPAD ? sizeof(gamepad_report_t) : sizeof(touchpad_report_t);
if (usb_ops.usb_device_class_send_hid_report(rpt_buffer, rpt_size))
goto error;
usbs->set_text(usbs->label, "#C7EA46 状态#HID模拟已开启");
usbs->set_text(usbs->label, "#C7EA46 状态:#HID仿真已启动");
u32 timer_sys = get_tmr_ms() + 5000;
while (true)
{
u32 timer = get_tmr_us();
// Check for suspended USB in case the cable was pulled.
if (usb_ops.usb_device_get_suspended())
break; // Disconnected.
// Handle control endpoint.
usb_ops.usbd_handle_ep0_ctrl_setup(&usbs->idle);
// Parse input device.
if (usbs->type == USB_HID_GAMEPAD)
{
@@ -448,13 +462,6 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs)
break;
}
// Check for suspended USB in case the cable was pulled.
if (usb_ops.usb_device_get_suspended())
break; // Disconnected.
// Handle control endpoint.
usb_ops.usbd_handle_ep0_ctrl_setup();
// Wait max gadget timing.
timer = get_tmr_us() - timer;
if (timer < polling_time)
@@ -467,11 +474,11 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs)
}
}
usbs->set_text(usbs->label, "#C7EA46 状态#HID已结束");
usbs->set_text(usbs->label, "#C7EA46 状态:#HID已结束");
goto exit;
error:
usbs->set_text(usbs->label, "#FFDD00 错误#超时或已取消");
usbs->set_text(usbs->label, "#FFDD00 错误:#超时或已取消");
res = 1;
exit:

View File

@@ -28,11 +28,10 @@
#include <soc/t210.h>
#include <storage/sd.h>
#include <storage/sdmmc.h>
#include <storage/emmc.h>
#include <storage/sdmmc_driver.h>
#include <storage/emmc.h>
#include <utils/btn.h>
#include <utils/sprintf.h>
#include <utils/util.h>
#include <memory_map.h>
@@ -287,7 +286,7 @@ static void raise_exception(usbd_gadget_ums_t *ums, enum ums_state new_state)
static void _handle_ep0_ctrl(usbd_gadget_ums_t *ums)
{
if (usb_ops.usbd_handle_ep0_ctrl_setup())
if (usb_ops.usbd_handle_ep0_ctrl_setup(NULL))
raise_exception(ums, UMS_STATE_PROTOCOL_RESET);
}
@@ -328,11 +327,11 @@ static void _transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32
if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR)
{
ums->set_text(ums->label, "#FFDD00 错误:#EP IN传输");
ums->set_text(ums->label, "#FFDD00 错误:#端口IN传输错误!");
_flush_endpoint(bulk_ctxt->bulk_in);
}
else if (bulk_ctxt->bulk_in_status == USB2_ERROR_XFER_NOT_ALIGNED)
ums->set_text(ums->label, "#FFDD00 错误:#EP IN缓冲区未对齐");
ums->set_text(ums->label, "#FFDD00 错误:#端口IN缓冲区未对齐!");
if (sync_timeout)
bulk_ctxt->bulk_in_buf_state = BUF_STATE_EMPTY;
@@ -345,11 +344,11 @@ static void _transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
{
ums->set_text(ums->label, "#FFDD00 错误:#EP OUT传输");
ums->set_text(ums->label, "#FFDD00 错误:#端口OUT传输错误!");
_flush_endpoint(bulk_ctxt->bulk_out);
}
else if (bulk_ctxt->bulk_out_status == USB2_ERROR_XFER_NOT_ALIGNED)
ums->set_text(ums->label, "#FFDD00 错误:#EP OUT缓冲区未对齐");
ums->set_text(ums->label, "#FFDD00 错误:#端口OUT缓冲区未对齐!");
if (sync_timeout)
bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL;
@@ -364,7 +363,7 @@ static void _transfer_out_big_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctx
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
{
ums->set_text(ums->label, "#FFDD00 错误:#EP OUT传输");
ums->set_text(ums->label, "#FFDD00 错误:#端口OUT传输错误!");
_flush_endpoint(bulk_ctxt->bulk_out);
}
@@ -380,7 +379,7 @@ static void _transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32
if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR)
{
ums->set_text(ums->label, "#FFDD00 错误:#EP IN传输");
ums->set_text(ums->label, "#FFDD00 错误:#端口IN传输错误!");
_flush_endpoint(bulk_ctxt->bulk_in);
}
@@ -393,7 +392,7 @@ static void _transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
{
ums->set_text(ums->label, "#FFDD00 错误:#EP OUT传输");
ums->set_text(ums->label, "#FFDD00 错误:#端口OUT传输!");
_flush_endpoint(bulk_ctxt->bulk_out);
}
@@ -463,7 +462,7 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
}
if (lba_offset >= ums->lun.num_sectors)
{
ums->set_text(ums->label, "#FF8000 警告:#读取 - 超出范围!已通知主机");
ums->set_text(ums->label, "#FF8000 警告:#读取超出范围!主机已通知。");
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return UMS_RES_INVALID_ARG;
@@ -515,7 +514,7 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
// If an error occurred, report it and its position.
if (!amount)
{
ums->set_text(ums->label, "#FFDD00 错误:# SDMMC读取");
ums->set_text(ums->label, "#FFDD00 错误:#SDMMC读取失败");
ums->lun.sense_data = SS_UNRECOVERED_READ_ERROR;
ums->lun.sense_data_info = lba_offset;
ums->lun.info_valid = 1;
@@ -553,7 +552,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
if (ums->lun.ro)
{
ums->set_text(ums->label, "#FF8000 警告:#写入 - 只读已通知主机。");
ums->set_text(ums->label, "#FF8000 警告:#写入受阻 - 只读模式! 已通知主机。");
ums->lun.sense_data = SS_WRITE_PROTECTED;
return UMS_RES_INVALID_ARG;
@@ -577,7 +576,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
// Check that starting LBA is not past the end sector offset.
if (lba_offset >= ums->lun.num_sectors)
{
ums->set_text(ums->label, "#FF8000 警告:#写入 - 超出范围已通知主机。");
ums->set_text(ums->label, "#FF8000 警告:#写入超出范围! 已通知主机。");
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return UMS_RES_INVALID_ARG;
@@ -599,7 +598,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
if (usb_lba_offset >= ums->lun.num_sectors)
{
ums->set_text(ums->label, "#FFDD00 错误#写入 - 超出最后扇区");
ums->set_text(ums->label, "#FFDD00 错误:# 写入超过最后一个扇区!");
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
ums->lun.sense_data_info = usb_lba_offset;
ums->lun.info_valid = 1;
@@ -627,7 +626,7 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
ums->lun.sense_data_info = lba_offset;
ums->lun.info_valid = 1;
s_printf(txt_buf, "#FFDD00 错误:#写入 - 通讯失败 %d", bulk_ctxt->bulk_out_status);
s_printf(txt_buf, "#FFDD00 错误:#写入通信失败 %d", bulk_ctxt->bulk_out_status);
ums->set_text(ums->label, txt_buf);
break;
}
@@ -665,7 +664,7 @@ DPRINTF("file write %X @ %X\n", amount, lba_offset);
// If an error occurred, report it and its position.
if (!amount)
{
ums->set_text(ums->label, "#FFDD00 错误:#SDMMC写入");
ums->set_text(ums->label, "#FFDD00 错误:#SDMMC写入失败");
ums->lun.sense_data = SS_WRITE_ERROR;
ums->lun.sense_data_info = lba_offset;
ums->lun.info_valid = 1;
@@ -676,7 +675,7 @@ DPRINTF("file write %X @ %X\n", amount, lba_offset);
// Did the host decide to stop early?
if (bulk_ctxt->bulk_out_length_actual < bulk_ctxt->bulk_out_length)
{
ums->set_text(ums->label, "#FFDD00 错误:#空写入");
ums->set_text(ums->label, "#FFDD00 错误:#空写入");
ums->short_packet_received = 1;
break;
}
@@ -692,7 +691,7 @@ static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
u32 lba_offset = get_array_be_to_le32(&ums->cmnd[2]);
if (lba_offset >= ums->lun.num_sectors)
{
ums->set_text(ums->label, "#FF8000 警告:#校验 - 超出范围已通知主机。");
ums->set_text(ums->label, "#FF8000 警告:#验证超出范围! 已通知主机。");
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return UMS_RES_INVALID_ARG;
@@ -731,7 +730,7 @@ DPRINTF("File read %X @ %X\n", amount, lba_offset);
if (!amount)
{
ums->set_text(ums->label, "#FFDD00 错误:#文件验!");
ums->set_text(ums->label, "#FFDD00 错误:#文件验证失败");
ums->lun.sense_data = SS_UNRECOVERED_READ_ERROR;
ums->lun.sense_data_info = lba_offset;
ums->lun.info_valid = 1;
@@ -764,7 +763,7 @@ static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
switch (ums->lun.partition)
{
case 0:
strcpy((char *)buf + strlen((char *)buf), "原始");
strcpy((char *)buf + strlen((char *)buf), "RAW");
break;
case EMMC_GPP + 1:
s_printf((char *)buf + strlen((char *)buf), "GPP");
@@ -800,7 +799,7 @@ static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
switch (ums->lun.partition)
{
case 0:
s_printf((char *)buf, "%s", "SD卡原始分区");
s_printf((char *)buf, "%s", "SD RAW");
break;
case EMMC_GPP + 1:
s_printf((char *)buf, "%s%s",
@@ -1060,7 +1059,7 @@ static int _scsi_start_stop(usbd_gadget_ums_t *ums)
// Check if we are allowed to unload the media.
if (ums->lun.prevent_medium_removal)
{
ums->set_text(ums->label, "#C7EA46 状态:#卸载尝试已被阻止");
ums->set_text(ums->label, "#C7EA46 状态:#尝试卸载被阻止");
ums->lun.sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
return UMS_RES_INVALID_ARG;
@@ -1468,7 +1467,7 @@ static int _finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{
_set_ep_stall(bulk_ctxt->bulk_out);
rc = _set_ep_stall(bulk_ctxt->bulk_in);
ums->set_text(ums->label, "#FFDD00 错误:#方向不明。两端EP已暂停");
ums->set_text(ums->label, "#FFDD00 错误:#方向未知。已停止两个端口");
} // Else do nothing.
break;
@@ -1489,7 +1488,7 @@ static int _finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{
_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA);
rc = _set_ep_stall(bulk_ctxt->bulk_in);
ums->set_text(ums->label, "#FFDD00 错误:#数据残留。EP IN已停止!");
ums->set_text(ums->label, "#FFDD00 错误:#残留。已停止端口IN");
}
else
rc = _pad_with_zeros(ums, bulk_ctxt);
@@ -1562,7 +1561,7 @@ static int _received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{
if (usb_ops.usb_device_get_port_in_sleep())
{
ums->set_text(ums->label, "#C7EA46 状态#EP已休眠");
ums->set_text(ums->label, "#C7EA46 状态:#端口休眠");
ums->timeouts += 14;
}
else if (!ums->xusb) // Timeout only on USB2.
@@ -1581,7 +1580,7 @@ static int _received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
if (ums->lun.unmounted)
{
ums->set_text(ums->label, "#C7EA46 状态#介质未挂");
ums->set_text(ums->label, "#C7EA46 状态:# 介质已卸");
ums->timeouts++;
if (!bulk_ctxt->bulk_out_status)
ums->timeouts += 3;
@@ -1633,7 +1632,7 @@ static int _received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{
_set_ep_stall(bulk_ctxt->bulk_out);
_set_ep_stall(bulk_ctxt->bulk_in);
ums->set_text(ums->label, "#FFDD00 错误:#CBW未知 - 两端EP已停止!");
ums->set_text(ums->label, "#FFDD00 错误:#CBW未知 - 已停止两个端口");
}
return UMS_RES_INVALID_ARG;
@@ -1712,7 +1711,7 @@ static void _send_status(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
if (ums->phase_error)
{
ums->set_text(ums->label, "#FFDD00 错误#相位错误");
ums->set_text(ums->label, "#FFDD00 错误:# 阶段性错误!");
status = USB_STATUS_PHASE_ERROR;
sd = SS_INVALID_COMMAND;
}
@@ -1826,7 +1825,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
xusb_device_get_ops(&usb_ops);
}
usbs->set_text(usbs->label, "#C7EA46 状态:#USB已开启");
usbs->set_text(usbs->label, "#C7EA46 状态:#已启动USB");
if (usb_ops.usb_device_init())
{
@@ -1857,7 +1856,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
ums.set_text = usbs->set_text;
ums.system_maintenance = usbs->system_maintenance;
ums.set_text(ums.label, "#C7EA46 状态:#磁盘挂载中");
ums.set_text(ums.label, "#C7EA46 状态:#挂载磁盘");
// Initialize sdmmc.
if (usbs->type == MMC_SD)
@@ -1888,18 +1887,18 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
ums.lun.storage = &emmc_storage;
}
ums.set_text(ums.label, "#C7EA46 状态:#连接等待中");
ums.set_text(ums.label, "#C7EA46 状态:#正在等待连接");
// Initialize Control Endpoint.
if (usb_ops.usb_device_enumerate(USB_GADGET_UMS))
goto usb_enum_error;
ums.set_text(ums.label, "#C7EA46 状态:#LUN等待中");
ums.set_text(ums.label, "#C7EA46 状态:#正在等待LUN");
if (usb_ops.usb_device_class_send_max_lun(0)) // One device for now.
goto usb_enum_error;
ums.set_text(ums.label, "#C7EA46 状态:#UMS已开启");
ums.set_text(ums.label, "#C7EA46 状态:#已启动UMS");
// If partition sectors are not set get them from hardware.
if (!ums.lun.num_sectors)
@@ -1920,7 +1919,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
{
// Check if we are allowed to unload the media.
if (ums.lun.prevent_medium_removal)
ums.set_text(ums.label, "#C7EA46 状态:#卸载尝试已被阻止");
ums.set_text(ums.label, "#C7EA46 状态:#尝试卸载被阻止");
else
break;
}
@@ -1952,13 +1951,13 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
} while (ums.state != UMS_STATE_TERMINATED);
if (ums.lun.prevent_medium_removal)
ums.set_text(ums.label, "#FFDD00 错误:#磁盘已未安全弹出");
ums.set_text(ums.label, "#FFDD00 错误:#磁盘安全弹出");
else
ums.set_text(ums.label, "#C7EA46 状态:#磁盘已弹出");
goto exit;
usb_enum_error:
ums.set_text(ums.label, "#FFDD00 错误:#超时或取消!");
ums.set_text(ums.label, "#FFDD00 错误:#超时或取消!");
res = 1;
exit:

View File

@@ -1,7 +1,7 @@
/*
* Enhanced USB Device (EDCI) driver for Tegra X1
*
* Copyright (c) 2019-2024 CTCaer
* Copyright (c) 2019-2025 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,
@@ -101,7 +101,11 @@ typedef struct _usbd_controller_t
bool configuration_set;
bool max_lun_set;
bool bulk_reset_req;
u32 intr_idle_rate;
bool intr_idle_req;
bool hid_report_sent;
void *hid_rpt_buffer;
u32 hid_rpt_size;
u32 charger_detect;
} usbd_controller_t;
@@ -881,7 +885,7 @@ int usbd_set_ep_stall(u32 endpoint, int ep_stall)
return USB_RES_OK;
}
static void _usbd_handle_get_class_request(bool *transmit_data, u8 *descriptor, int *size, bool *ep_stall)
static void _usbd_handle_get_class_request(bool *transmit_data, u8 *desc, int *size, bool *ep_stall)
{
u8 _bRequest = usbd_otg->control_setup.bRequest;
u16 _wIndex = usbd_otg->control_setup.wIndex;
@@ -889,9 +893,9 @@ static void _usbd_handle_get_class_request(bool *transmit_data, u8 *descriptor,
u16 _wLength = usbd_otg->control_setup.wLength;
bool valid_interface = _wIndex == usbd_otg->interface_num;
bool valid_len = (_bRequest == USB_REQUEST_BULK_GET_MAX_LUN) ? 1 : 0;
bool valid_val = (_bRequest >= USB_REQUEST_BULK_GET_MAX_LUN) ? (!_wValue) : true;
if (!valid_interface || _wValue != 0 || _wLength != valid_len)
if (!valid_interface || !valid_val)
{
*ep_stall = true;
return;
@@ -899,23 +903,51 @@ static void _usbd_handle_get_class_request(bool *transmit_data, u8 *descriptor,
switch (_bRequest)
{
case USB_REQUEST_INTR_GET_REPORT:
if (usbd_otg->hid_rpt_size != _wLength)
break;
// _wValue unused as there's only one report type and id.
*transmit_data = true;
*size = usbd_otg->hid_rpt_size;
memcpy(desc, usbd_otg->hid_rpt_buffer, usbd_otg->hid_rpt_size);
return;
case USB_REQUEST_INTR_SET_IDLE:
if (_wLength)
break;
usbd_otg->intr_idle_rate = (_wValue & 0xFF) * 4 * 1000; // Only one interface so upper byte ignored.
usbd_otg->intr_idle_req = true;
_usbd_ep_ack(USB_EP_CTRL_IN);
return; // DELAYED_STATUS;
case USB_REQUEST_BULK_RESET:
if (_wLength)
break;
_usbd_ep_ack(USB_EP_CTRL_IN);
usbd_otg->bulk_reset_req = true;
break; // DELAYED_STATUS;
return; // DELAYED_STATUS;
case USB_REQUEST_BULK_GET_MAX_LUN:
if (_wLength != 1)
break;
*transmit_data = true;
*size = 1;
descriptor[0] = usbd_otg->max_lun; // Set 0 LUN for 1 drive supported.
desc[0] = usbd_otg->max_lun; // Set 0 LUN for 1 drive supported.
usbd_otg->max_lun_set = true;
break;
return;
default:
*ep_stall = true;
break;
}
*ep_stall = true;
}
static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor, int *size, bool *ep_stall)
static void _usbd_handle_get_descriptor(bool *transmit_data, void **desc, int *size, bool *ep_stall)
{
u8 descriptor_type = usbd_otg->control_setup.wValue >> 8;
u8 descriptor_subtype = usbd_otg->control_setup.wValue & 0xFF;
@@ -931,7 +963,7 @@ static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor,
usb_device_descriptor.bcdDevice = (soc_rev >> 16) & 0xF; // MINORREV.
usb_device_descriptor.bcdDevice |= ((soc_rev >> 4) & 0xF) << 8; // MAJORREV.
*/
*descriptor = usbd_otg->desc->dev;
*desc = usbd_otg->desc->dev;
*size = usbd_otg->desc->dev->bLength;
*transmit_data = true;
return;
@@ -941,13 +973,13 @@ static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor,
{
if (usbd_otg->port_speed == USB_HIGH_SPEED) // High speed. 512 bytes.
{
usbd_otg->desc->cfg->endpoint[0].wMaxPacketSize = 0x200;
usbd_otg->desc->cfg->endpoint[1].wMaxPacketSize = 0x200;
for (u32 i = 0; i < usbd_otg->desc->cfg->interface.bNumEndpoints; i++)
usbd_otg->desc->cfg->endpoint[i].wMaxPacketSize = 0x200; // No burst.
}
else // Full speed. 64 bytes.
{
usbd_otg->desc->cfg->endpoint[0].wMaxPacketSize = 0x40;
usbd_otg->desc->cfg->endpoint[1].wMaxPacketSize = 0x40;
for (u32 i = 0; i < usbd_otg->desc->cfg->interface.bNumEndpoints; i++)
usbd_otg->desc->cfg->endpoint[i].wMaxPacketSize = 0x40;
}
}
else
@@ -955,20 +987,22 @@ static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor,
usb_cfg_hid_descr_t *tmp = (usb_cfg_hid_descr_t *)usbd_otg->desc->cfg;
if (usbd_otg->port_speed == USB_HIGH_SPEED) // High speed. 512 bytes.
{
tmp->endpoint[0].wMaxPacketSize = 0x200;
tmp->endpoint[1].wMaxPacketSize = 0x200;
tmp->endpoint[0].bInterval = usbd_otg->gadget == USB_GADGET_HID_GAMEPAD ? 4 : 3; // 8ms : 4ms.
tmp->endpoint[1].bInterval = usbd_otg->gadget == USB_GADGET_HID_GAMEPAD ? 4 : 3; // 8ms : 4ms.
for (u32 i = 0; i < tmp->interface.bNumEndpoints; i++)
{
tmp->endpoint[i].wMaxPacketSize = 0x200;
tmp->endpoint[i].bInterval = usbd_otg->gadget == USB_GADGET_HID_GAMEPAD ? 4 : 3; // 8ms : 4ms.
}
}
else // Full speed. 64 bytes.
{
tmp->endpoint[0].wMaxPacketSize = 0x40;
tmp->endpoint[1].wMaxPacketSize = 0x40;
tmp->endpoint[0].bInterval = usbd_otg->gadget == USB_GADGET_HID_GAMEPAD ? 8 : 4; // 8ms : 4ms.
tmp->endpoint[1].bInterval = usbd_otg->gadget == USB_GADGET_HID_GAMEPAD ? 8 : 4; // 8ms : 4ms.
for (u32 i = 0; i < tmp->interface.bNumEndpoints; i++)
{
tmp->endpoint[i].wMaxPacketSize = 0x40;
tmp->endpoint[i].bInterval = usbd_otg->gadget == USB_GADGET_HID_GAMEPAD ? 8 : 4; // 8ms : 4ms.
}
}
}
*descriptor = usbd_otg->desc->cfg;
*desc = usbd_otg->desc->cfg;
*size = usbd_otg->desc->cfg->config.wTotalLength;
*transmit_data = true;
return;
@@ -976,23 +1010,23 @@ static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor,
switch (descriptor_subtype)
{
case 1:
*descriptor = usbd_otg->desc->vendor;
*desc = usbd_otg->desc->vendor;
*size = usbd_otg->desc->vendor[0];
break;
case 2:
*descriptor = usbd_otg->desc->product;
*desc = usbd_otg->desc->product;
*size = usbd_otg->desc->product[0];
break;
case 3:
*descriptor = usbd_otg->desc->serial;
*desc = usbd_otg->desc->serial;
*size = usbd_otg->desc->serial[0];
break;
case 0xEE:
*descriptor = usbd_otg->desc->ms_os;
*desc = usbd_otg->desc->ms_os;
*size = usbd_otg->desc->ms_os->bLength;
break;
default:
*descriptor = usbd_otg->desc->lang_id;
*desc = usbd_otg->desc->lang_id;
*size = 4;
break;
}
@@ -1002,7 +1036,7 @@ static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor,
if (!usbd_otg->desc->dev_qual)
goto exit;
usbd_otg->desc->dev_qual->bNumOtherConfigs = 1;
*descriptor = usbd_otg->desc->dev_qual;
*desc = usbd_otg->desc->dev_qual;
*size = usbd_otg->desc->dev_qual->bLength;
*transmit_data = true;
return;
@@ -1011,22 +1045,22 @@ static void _usbd_handle_get_descriptor(bool *transmit_data, void **descriptor,
goto exit;
if (usbd_otg->port_speed == USB_HIGH_SPEED)
{
usbd_otg->desc->cfg_other->endpoint[0].wMaxPacketSize = 0x40;
usbd_otg->desc->cfg_other->endpoint[1].wMaxPacketSize = 0x40;
for (u32 i = 0; i < usbd_otg->desc->cfg_other->interface.bNumEndpoints; i++)
usbd_otg->desc->cfg_other->endpoint[i].wMaxPacketSize = 0x40;
}
else
{
usbd_otg->desc->cfg_other->endpoint[0].wMaxPacketSize = 0x200;
usbd_otg->desc->cfg_other->endpoint[1].wMaxPacketSize = 0x200;
for (u32 i = 0; i < usbd_otg->desc->cfg_other->interface.bNumEndpoints; i++)
usbd_otg->desc->cfg_other->endpoint[i].wMaxPacketSize = 0x200;
}
if ((usbd_otg->charger_detect & 1) && (usbd_otg->charger_detect & 2))
usbd_otg->desc->cfg_other->config.bMaxPower = 500 / 2;
*descriptor = usbd_otg->desc->cfg_other;
*desc = usbd_otg->desc->cfg_other;
*size = usbd_otg->desc->cfg_other->config.wTotalLength;
*transmit_data = true;
return;
case USB_DESCRIPTOR_DEVICE_BINARY_OBJECT:
*descriptor = usbd_otg->desc->dev_bot;
*desc = usbd_otg->desc->dev_bot;
*size = usbd_otg->desc->dev_bot->wTotalLength;
*transmit_data = true;
return;
@@ -1086,7 +1120,7 @@ static int _usbd_handle_ep0_control_transfer()
bool ep_stall = false;
bool transmit_data = false;
u8 *descriptor = (u8 *)USB_DESCRIPTOR_ADDR;
u8 *desc = (u8 *)USB_DESCRIPTOR_ADDR;
int size = 0;
u8 _bmRequestType = usbd_otg->control_setup.bmRequestType;
@@ -1099,17 +1133,17 @@ static int _usbd_handle_ep0_control_transfer()
switch (_bmRequestType)
{
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE):
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE): // 0x00.
res = _usbd_handle_set_request(&ep_stall);
break;
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE):
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE): // 0x01.
res = _usbd_ep_ack(USB_EP_CTRL_IN);
if (!res)
usbd_otg->interface_num = _wValue;
break;
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT):
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT): // 0x02.
switch (_bRequest)
{
case USB_REQUEST_CLEAR_FEATURE:
@@ -1153,25 +1187,25 @@ static int _usbd_handle_ep0_control_transfer()
}
break;
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE):
memset(descriptor, 0, _wLength);
_usbd_handle_get_class_request(&transmit_data, descriptor, &size, &ep_stall);
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE): // 0x21.
memset(desc, 0, _wLength);
_usbd_handle_get_class_request(&transmit_data, desc, &size, &ep_stall);
break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE):
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE): // 0x80.
switch (_bRequest)
{
case USB_REQUEST_GET_STATUS:
descriptor[0] = USB_STATUS_DEV_SELF_POWERED;
descriptor[1] = 0; // No support for remove wake up.
desc[0] = USB_STATUS_DEV_SELF_POWERED;
desc[1] = 0; // No support for remove wake up.
transmit_data = true;
size = 2;
break;
case USB_REQUEST_GET_DESCRIPTOR:
_usbd_handle_get_descriptor(&transmit_data, (void **)&descriptor, &size, &ep_stall);
_usbd_handle_get_descriptor(&transmit_data, (void **)&desc, &size, &ep_stall);
break;
case USB_REQUEST_GET_CONFIGURATION:
descriptor = (u8 *)&usbd_otg->config_num;
desc = (u8 *)&usbd_otg->config_num;
size = _wLength;
transmit_data = true;
break;
@@ -1181,28 +1215,28 @@ static int _usbd_handle_ep0_control_transfer()
}
break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE):
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE): // 0x81.
if (_bRequest == USB_REQUEST_GET_INTERFACE)
{
memset(descriptor, 0, _wLength);
descriptor[0] = usbd_otg->interface_num;
memset(desc, 0, _wLength);
desc[0] = usbd_otg->interface_num;
size = _wLength;
}
else if (_bRequest == USB_REQUEST_GET_STATUS)
{
memset(descriptor, 0, _wLength);
memset(desc, 0, _wLength);
size = _wLength;
}
else if (_bRequest == USB_REQUEST_GET_DESCRIPTOR && (_wValue >> 8) == USB_DESCRIPTOR_HID_REPORT && usbd_otg->gadget > USB_GADGET_UMS)
else if (_bRequest == USB_REQUEST_GET_DESCRIPTOR && (_wValue >> 8) == USB_DESCRIPTOR_HID_REPORT && usbd_otg->gadget >= USB_GADGET_HID_GAMEPAD)
{
if (usbd_otg->gadget == USB_GADGET_HID_GAMEPAD)
{
descriptor = (u8 *)&hid_report_descriptor_jc;
desc = (u8 *)&hid_report_descriptor_jc;
size = hid_report_descriptor_jc_size;
}
else // USB_GADGET_HID_TOUCHPAD
{
descriptor = (u8 *)&hid_report_descriptor_touch;
desc = (u8 *)&hid_report_descriptor_touch;
size = hid_report_descriptor_touch_size;
}
@@ -1219,7 +1253,7 @@ static int _usbd_handle_ep0_control_transfer()
transmit_data = true;
break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT):
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT): // 0x82.
if (_bRequest == USB_REQUEST_GET_STATUS)
{
int ep_req;
@@ -1243,12 +1277,12 @@ static int _usbd_handle_ep0_control_transfer()
}
size = _wLength;
memset(descriptor, 0, size);
memset(desc, 0, size);
if (_usbd_get_ep_status(ep_req) == USB_EP_STATUS_STALLED)
descriptor[0] = USB_STATUS_EP_HALTED;
desc[0] = USB_STATUS_EP_HALTED;
else
descriptor[0] = USB_STATUS_EP_OK;
desc[0] = USB_STATUS_EP_OK;
transmit_data = true;
}
@@ -1256,24 +1290,24 @@ static int _usbd_handle_ep0_control_transfer()
_usbd_stall_reset_ep1(3, USB_EP_CFG_STALL);
break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE):
memset(descriptor, 0, _wLength);
_usbd_handle_get_class_request(&transmit_data, descriptor, &size, &ep_stall);
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE): // 0xA1.
memset(desc, 0, _wLength);
_usbd_handle_get_class_request(&transmit_data, desc, &size, &ep_stall);
break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_INTERFACE):
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_DEVICE):
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_DEVICE): // 0xC0.
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_INTERFACE): // 0xC1.
if (_bRequest == USB_REQUEST_GET_MS_DESCRIPTOR)
{
switch (_wIndex)
{
case USB_DESCRIPTOR_MS_COMPAT_ID:
descriptor = (u8 *)usbd_otg->desc->ms_cid;
desc = (u8 *)usbd_otg->desc->ms_cid;
size = usbd_otg->desc->ms_cid->dLength;
transmit_data = true;
break;
case USB_DESCRIPTOR_MS_EXTENDED_PROPERTIES:
descriptor = (u8 *)usbd_otg->desc->mx_ext;
desc = (u8 *)usbd_otg->desc->mx_ext;
size = usbd_otg->desc->mx_ext->dLength;
transmit_data = true;
break;
@@ -1294,7 +1328,7 @@ static int _usbd_handle_ep0_control_transfer()
// Transmit data to HOST if any.
if (transmit_data)
{
memcpy(usb_ep0_ctrl_buf, descriptor, size);
memcpy(usb_ep0_ctrl_buf, desc, size);
if (_wLength < size)
size = _wLength;
@@ -1393,7 +1427,7 @@ int usb_device_enumerate(usb_gadget_type gadget)
return _usbd_ep0_initialize();
}
int usbd_handle_ep0_ctrl_setup()
int usbd_handle_ep0_ctrl_setup(u32 *data)
{
// Acknowledge setup request for EP0 and copy its configuration.
u32 ep0_setup_req = usbd_otg->regs->endptsetupstat;
@@ -1405,6 +1439,15 @@ int usbd_handle_ep0_ctrl_setup()
memset(usb_ep0_ctrl_buf, 0, USB_TD_BUFFER_PAGE_SIZE);
}
if (usbd_otg->intr_idle_req)
{
if (data)
*data = usbd_otg->intr_idle_rate;
usbd_otg->intr_idle_req = false;
return USB_RES_OK;
}
// Only return error if bulk reset was requested.
if (usbd_otg->bulk_reset_req)
{
@@ -1487,7 +1530,7 @@ int usb_device_ep1_out_reading_finish(u32 *pending_bytes, u32 sync_timeout)
if ((ep_status == USB_EP_STATUS_IDLE) || (ep_status == USB_EP_STATUS_DISABLED))
break;
usbd_handle_ep0_ctrl_setup();
usbd_handle_ep0_ctrl_setup(NULL);
}
while ((ep_status == USB_EP_STATUS_ACTIVE) || (ep_status == USB_EP_STATUS_STALLED));
@@ -1536,7 +1579,7 @@ int usb_device_ep1_in_writing_finish(u32 *pending_bytes, u32 sync_timeout)
if ((ep_status == USB_EP_STATUS_IDLE) || (ep_status == USB_EP_STATUS_DISABLED))
break;
usbd_handle_ep0_ctrl_setup();
usbd_handle_ep0_ctrl_setup(NULL);
}
while ((ep_status == USB_EP_STATUS_ACTIVE) || (ep_status == USB_EP_STATUS_STALLED));
@@ -1572,7 +1615,7 @@ int usb_device_class_send_max_lun(u8 max_lun)
while (!usbd_otg->max_lun_set)
{
usbd_handle_ep0_ctrl_setup();
usbd_handle_ep0_ctrl_setup(NULL);
if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
return USB_ERROR_USER_ABORT;
}
@@ -1580,15 +1623,19 @@ int usb_device_class_send_max_lun(u8 max_lun)
return USB_RES_OK;
}
int usb_device_class_send_hid_report()
int usb_device_class_send_hid_report(void *rpt_buffer, u32 rpt_size)
{
// Set buffers.
usbd_otg->hid_rpt_buffer = rpt_buffer;
usbd_otg->hid_rpt_size = rpt_size;
// 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_ctrl_setup();
usbd_handle_ep0_ctrl_setup(NULL);
if (timer < get_tmr_ms() || btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
return USB_ERROR_USER_ABORT;
}

View File

@@ -1,7 +1,7 @@
/*
* Enhanced & eXtensible USB Device (EDCI & XDCI) driver for Tegra X1
*
* Copyright (c) 2019-2021 CTCaer
* Copyright (c) 2019-2025 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,
@@ -31,11 +31,11 @@
#define USB_EP_BUFFER_ALIGN (USB_TD_BUFFER_PAGE_SIZE)
#define USB_XFER_START 0
#define USB_XFER_SYNCED_ENUM 1000000
#define USB_XFER_SYNCED_CMD 1000000
#define USB_XFER_SYNCED_DATA 2000000
#define USB_XFER_SYNCED_CLASS 5000000
#define USB_XFER_SYNCED -1
#define USB_XFER_SYNCED_ENUM 1000000 // ~2s.
#define USB_XFER_SYNCED_CMD 1000000 // ~2s.
#define USB_XFER_SYNCED_DATA 2000000 // ~4s.
#define USB_XFER_SYNCED_CLASS 5000000 // ~10s.
#define USB_XFER_SYNCED -1 // Max.
typedef enum _usb_hid_type
{
@@ -122,6 +122,9 @@ typedef enum {
USB_REQUEST_GET_MS_DESCRIPTOR = 0x99,
USB_REQUEST_INTR_GET_REPORT = 1,
USB_REQUEST_INTR_SET_IDLE = 10,
USB_REQUEST_BULK_GET_MAX_LUN = 0xFE,
USB_REQUEST_BULK_RESET = 0xFF
} usb_standard_req_t;
@@ -167,12 +170,13 @@ typedef struct _usb_ops_t
{
int (*usbd_flush_endpoint)(u32);
int (*usbd_set_ep_stall)(u32, int);
int (*usbd_handle_ep0_ctrl_setup)();
int (*usbd_handle_ep0_ctrl_setup)(u32 *);
void (*usbd_end)(bool, bool);
int (*usb_device_init)();
int (*usb_device_enumerate)(usb_gadget_type gadget);
int (*usb_device_enumerate)(usb_gadget_type);
int (*usb_device_class_send_max_lun)(u8);
int (*usb_device_class_send_hid_report)();
int (*usb_device_class_send_hid_report)(void *, u32);
int (*usb_device_ep1_out_read)(u8 *, u32, u32 *, u32);
int (*usb_device_ep1_out_read_big)(u8 *, u32, u32 *);
@@ -186,10 +190,17 @@ typedef struct _usb_ops_t
typedef struct _usb_ctxt_t
{
u32 type;
// UMS.
u32 partition;
u32 offset;
u32 sectors;
u32 ro;
// HID.
u32 idle;
// System.
void (*system_maintenance)(bool);
void *label;
void (*set_text)(void *, const char *);
@@ -201,4 +212,4 @@ 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);
#endif
#endif

View File

@@ -1,7 +1,7 @@
/*
* eXtensible USB Device driver (XDCI) for Tegra X1
*
* Copyright (c) 2020-2024 CTCaer
* Copyright (c) 2020-2025 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,
@@ -381,6 +381,10 @@ typedef struct _xusbd_controller_t
u8 max_lun;
bool max_lun_set;
void *hid_rpt_buffer;
u32 hid_rpt_size;
u32 intr_idle_rate;
bool intr_idle_req;
bool bulk_reset_req;
} xusbd_controller_t;
@@ -1469,20 +1473,39 @@ static int _xusb_handle_get_class_request(const usb_ctrl_setup_t *ctrl_setup)
u16 _wLength = ctrl_setup->wLength;
bool valid_interface = _wIndex == usbd_xotg->interface_num;
bool valid_len = (_bRequest == USB_REQUEST_BULK_GET_MAX_LUN) ? 1 : 0;
bool valid_val = (_bRequest >= USB_REQUEST_BULK_GET_MAX_LUN) ? (!_wValue) : true;
if (!valid_interface || _wValue != 0 || _wLength != valid_len)
if (!valid_interface || !valid_val)
goto stall;
switch (_bRequest)
{
case USB_REQUEST_INTR_GET_REPORT:
if (usbd_xotg->hid_rpt_size != _wLength)
goto stall;
// _wValue unused as there's only one report type and id.
return _xusb_issue_data_trb(usbd_xotg->hid_rpt_buffer, usbd_xotg->hid_rpt_size, USB_DIR_IN);
case USB_REQUEST_INTR_SET_IDLE:
if (_wLength)
goto stall;
usbd_xotg->intr_idle_rate = (_wValue & 0xFF) * 4 * 1000; // Only one interface so upper byte ignored.
usbd_xotg->intr_idle_req = true;
return _xusb_issue_status_trb(USB_DIR_IN); // DELAYED_STATUS;
case USB_REQUEST_BULK_RESET:
if (_wLength)
goto stall;
usbd_xotg->bulk_reset_req = true;
return _xusb_issue_status_trb(USB_DIR_IN); // DELAYED_STATUS;
case USB_REQUEST_BULK_GET_MAX_LUN:
if (!usbd_xotg->max_lun_set)
if (_wLength != 1 || !usbd_xotg->max_lun_set)
goto stall;
usbd_xotg->device_state = XUSB_LUN_CONFIGURED_STS_WAIT;
return _xusb_issue_data_trb(&usbd_xotg->max_lun, 1, USB_DIR_IN);
}
@@ -1495,7 +1518,7 @@ stall:
static int _xusb_handle_get_descriptor(const usb_ctrl_setup_t *ctrl_setup)
{
u32 size;
void *descriptor;
void *desc;
u32 wLength = ctrl_setup->wLength;
@@ -1513,7 +1536,7 @@ static int _xusb_handle_get_descriptor(const usb_ctrl_setup_t *ctrl_setup)
usb_device_descriptor.bcdDevice = (soc_rev >> 16) & 0xF; // MINORREV.
usb_device_descriptor.bcdDevice |= ((soc_rev >> 4) & 0xF) << 8; // MAJORREV.
*/
descriptor = usbd_xotg->desc->dev;
desc = usbd_xotg->desc->dev;
size = usbd_xotg->desc->dev->bLength;
break;
case USB_DESCRIPTOR_CONFIGURATION:
@@ -1522,13 +1545,13 @@ static int _xusb_handle_get_descriptor(const usb_ctrl_setup_t *ctrl_setup)
{
if (usbd_xotg->port_speed == XUSB_HIGH_SPEED) // High speed. 512 bytes.
{
usbd_xotg->desc->cfg->endpoint[0].wMaxPacketSize = 0x200; // No burst.
usbd_xotg->desc->cfg->endpoint[1].wMaxPacketSize = 0x200; // No burst.
for (u32 i = 0; i < usbd_xotg->desc->cfg->interface.bNumEndpoints; i++)
usbd_xotg->desc->cfg->endpoint[i].wMaxPacketSize = 0x200; // No burst.
}
else // Full speed. 64 bytes.
{
usbd_xotg->desc->cfg->endpoint[0].wMaxPacketSize = 0x40;
usbd_xotg->desc->cfg->endpoint[1].wMaxPacketSize = 0x40;
for (u32 i = 0; i < usbd_xotg->desc->cfg->interface.bNumEndpoints; i++)
usbd_xotg->desc->cfg->endpoint[i].wMaxPacketSize = 0x40;
}
}
else
@@ -1536,43 +1559,45 @@ static int _xusb_handle_get_descriptor(const usb_ctrl_setup_t *ctrl_setup)
usb_cfg_hid_descr_t *tmp = (usb_cfg_hid_descr_t *)usbd_xotg->desc->cfg;
if (usbd_xotg->port_speed == XUSB_HIGH_SPEED) // High speed. 512 bytes.
{
tmp->endpoint[0].wMaxPacketSize = 0x200;
tmp->endpoint[1].wMaxPacketSize = 0x200;
tmp->endpoint[0].bInterval = usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD ? 4 : 3; // 8ms : 4ms.
tmp->endpoint[1].bInterval = usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD ? 4 : 3; // 8ms : 4ms.
for (u32 i = 0; i < tmp->interface.bNumEndpoints; i++)
{
tmp->endpoint[i].wMaxPacketSize = 0x200;
tmp->endpoint[i].bInterval = usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD ? 4 : 3; // 8ms : 4ms.
}
}
else // Full speed. 64 bytes.
{
tmp->endpoint[0].wMaxPacketSize = 0x40;
tmp->endpoint[1].wMaxPacketSize = 0x40;
tmp->endpoint[0].bInterval = usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD ? 8 : 4; // 8ms : 4ms.
tmp->endpoint[1].bInterval = usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD ? 8 : 4; // 8ms : 4ms.
for (u32 i = 0; i < tmp->interface.bNumEndpoints; i++)
{
tmp->endpoint[i].wMaxPacketSize = 0x40;
tmp->endpoint[i].bInterval = usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD ? 8 : 4; // 8ms : 4ms.
}
}
}
descriptor = usbd_xotg->desc->cfg;
desc = usbd_xotg->desc->cfg;
size = usbd_xotg->desc->cfg->config.wTotalLength;
break;
case USB_DESCRIPTOR_STRING:
switch (descriptor_subtype)
{
case 1:
descriptor = usbd_xotg->desc->vendor;
desc = usbd_xotg->desc->vendor;
size = usbd_xotg->desc->vendor[0];
break;
case 2:
descriptor = usbd_xotg->desc->product;
desc = usbd_xotg->desc->product;
size = usbd_xotg->desc->product[0];
break;
case 3:
descriptor = usbd_xotg->desc->serial;
desc = usbd_xotg->desc->serial;
size = usbd_xotg->desc->serial[0];
break;
case 0xEE:
descriptor = usbd_xotg->desc->ms_os;
desc = usbd_xotg->desc->ms_os;
size = usbd_xotg->desc->ms_os->bLength;
break;
default:
descriptor = usbd_xotg->desc->lang_id;
desc = usbd_xotg->desc->lang_id;
size = 4;
break;
}
@@ -1584,7 +1609,7 @@ static int _xusb_handle_get_descriptor(const usb_ctrl_setup_t *ctrl_setup)
return USB_RES_OK;
}
usbd_xotg->desc->dev_qual->bNumOtherConfigs = 0;
descriptor = usbd_xotg->desc->dev_qual;
desc = usbd_xotg->desc->dev_qual;
size = usbd_xotg->desc->dev_qual->bLength;
break;
case USB_DESCRIPTOR_OTHER_SPEED_CONFIGURATION:
@@ -1595,19 +1620,19 @@ static int _xusb_handle_get_descriptor(const usb_ctrl_setup_t *ctrl_setup)
}
if (usbd_xotg->port_speed == XUSB_HIGH_SPEED)
{
usbd_xotg->desc->cfg_other->endpoint[0].wMaxPacketSize = 0x40;
usbd_xotg->desc->cfg_other->endpoint[1].wMaxPacketSize = 0x40;
for (u32 i = 0; i < usbd_xotg->desc->cfg_other->interface.bNumEndpoints; i++)
usbd_xotg->desc->cfg_other->endpoint[i].wMaxPacketSize = 0x40;
}
else
{
usbd_xotg->desc->cfg_other->endpoint[0].wMaxPacketSize = 0x200;
usbd_xotg->desc->cfg_other->endpoint[1].wMaxPacketSize = 0x200;
for (u32 i = 0; i < usbd_xotg->desc->cfg_other->interface.bNumEndpoints; i++)
usbd_xotg->desc->cfg_other->endpoint[i].wMaxPacketSize = 0x200;
}
descriptor = usbd_xotg->desc->cfg_other;
desc = usbd_xotg->desc->cfg_other;
size = usbd_xotg->desc->cfg_other->config.wTotalLength;
break;
case USB_DESCRIPTOR_DEVICE_BINARY_OBJECT:
descriptor = usbd_xotg->desc->dev_bot;
desc = usbd_xotg->desc->dev_bot;
size = usbd_xotg->desc->dev_bot->wTotalLength;
break;
default:
@@ -1618,7 +1643,7 @@ static int _xusb_handle_get_descriptor(const usb_ctrl_setup_t *ctrl_setup)
if (wLength < size)
size = wLength;
return _xusb_issue_data_trb(descriptor, size, USB_DIR_IN);
return _xusb_issue_data_trb(desc, size, USB_DIR_IN);
}
static void _xusb_handle_set_request_dev_address(const usb_ctrl_setup_t *ctrl_setup)
@@ -1688,18 +1713,18 @@ static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup)
switch (_bmRequestType)
{
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE):
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE): // 0x00.
if (_bRequest == USB_REQUEST_SET_ADDRESS)
_xusb_handle_set_request_dev_address(ctrl_setup);
else if (_bRequest == USB_REQUEST_SET_CONFIGURATION)
_xusb_handle_set_request_configuration(ctrl_setup);
return USB_RES_OK; // What about others.
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE):
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE): // 0x01.
usbd_xotg->interface_num = _wValue;
return _xusb_issue_status_trb(USB_DIR_IN);
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT):
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT): // 0x02.
if ((_wValue & 0xFF) == USB_FEATURE_ENDPOINT_HALT)
{
if (_bRequest == USB_REQUEST_CLEAR_FEATURE || _bRequest == USB_REQUEST_SET_FEATURE)
@@ -1735,10 +1760,10 @@ static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup)
ep_stall = true;
break;
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE):
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE): // 0x21.
return _xusb_handle_get_class_request(ctrl_setup);
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE):
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE): // 0x80.
switch (_bRequest)
{
case USB_REQUEST_GET_STATUS:
@@ -1760,7 +1785,7 @@ static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup)
}
break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE):
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE): // 0x81.
if (_bRequest == USB_REQUEST_GET_INTERFACE)
{
desc = xusb_interface_descriptor;
@@ -1774,7 +1799,7 @@ static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup)
size = sizeof(xusb_status_descriptor);
transmit_data = true;
}
else if (_bRequest == USB_REQUEST_GET_DESCRIPTOR && (_wValue >> 8) == USB_DESCRIPTOR_HID_REPORT && usbd_xotg->gadget > USB_GADGET_UMS)
else if (_bRequest == USB_REQUEST_GET_DESCRIPTOR && (_wValue >> 8) == USB_DESCRIPTOR_HID_REPORT && usbd_xotg->gadget >= USB_GADGET_HID_GAMEPAD)
{
if (usbd_xotg->gadget == USB_GADGET_HID_GAMEPAD)
{
@@ -1793,7 +1818,7 @@ static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup)
ep_stall = true;
break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT):
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT): // 0x82.
if (_bRequest == USB_REQUEST_GET_STATUS)
{
u32 ep = 0;
@@ -1821,11 +1846,11 @@ static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup)
ep_stall = true;
break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE):
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE): // 0xA1.
return _xusb_handle_get_class_request(ctrl_setup);
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_INTERFACE):
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_DEVICE):
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_DEVICE): // 0xC0.
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_INTERFACE): // 0xC1.
if (_bRequest == USB_REQUEST_GET_MS_DESCRIPTOR)
{
switch (_wIndex)
@@ -2017,12 +2042,24 @@ void xusb_end(bool reset_ep, bool only_controller)
_xusb_device_power_down();
}
int xusb_handle_ep0_ctrl_setup()
int xusb_handle_ep0_ctrl_setup(u32 *data)
{
/*
* EP0 Control handling is done by normal ep operation in XUSB.
* Here we handle the bulk reset only.
* Here we handle the interface only, except if HID.
*/
if (usbd_xotg->gadget >= USB_GADGET_HID_GAMEPAD)
_xusb_ep_operation(1);
if (usbd_xotg->intr_idle_req)
{
if (data)
*data = usbd_xotg->intr_idle_rate;
usbd_xotg->intr_idle_req = false;
return USB_RES_OK;
}
if (usbd_xotg->bulk_reset_req)
{
usbd_xotg->bulk_reset_req = false;
@@ -2176,8 +2213,12 @@ bool xusb_device_class_send_max_lun(u8 max_lun)
return false;
}
bool xusb_device_class_send_hid_report()
bool xusb_device_class_send_hid_report(void *rpt_buffer, u32 rpt_size)
{
// Set buffers.
usbd_xotg->hid_rpt_buffer = rpt_buffer;
usbd_xotg->hid_rpt_size = rpt_size;
// Timeout if get GET_HID_REPORT request doesn't happen in 10s.
u32 timer = get_tmr_ms() + 10000;