@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* USB Gadget HID driver for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
* Copyright (c) 2019-2022 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,
|
||||
@@ -23,8 +23,8 @@
|
||||
#include <input/joycon.h>
|
||||
#include <input/touch.h>
|
||||
#include <soc/hw_init.h>
|
||||
#include <soc/timer.h>
|
||||
#include <soc/t210.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
#include <memory_map.h>
|
||||
|
||||
@@ -159,14 +159,22 @@ static bool _jc_poll(gamepad_report_t *rpt)
|
||||
u16 y_raw = (jc_pad->lstick_y - jc_cal_ctx.cly_max) / 7;
|
||||
if (y_raw > 0x7F)
|
||||
y_raw = 0x7F;
|
||||
rpt->y = 0x7F - y_raw;
|
||||
// Hoag has inverted Y axis.
|
||||
if (!jc_pad->sio_mode)
|
||||
rpt->y = 0x7F - y_raw;
|
||||
else
|
||||
rpt->y = 0x7F + y_raw;
|
||||
}
|
||||
else
|
||||
{
|
||||
u16 y_raw = (jc_cal_ctx.cly_min - jc_pad->lstick_y) / 7;
|
||||
if (y_raw > 0x7F)
|
||||
y_raw = 0x7F;
|
||||
rpt->y = 0x7F + y_raw;
|
||||
// Hoag has inverted Y axis.
|
||||
if (!jc_pad->sio_mode)
|
||||
rpt->y = 0x7F + y_raw;
|
||||
else
|
||||
rpt->y = 0x7F - y_raw;
|
||||
}
|
||||
|
||||
// Calculate right analog stick.
|
||||
@@ -194,14 +202,22 @@ static bool _jc_poll(gamepad_report_t *rpt)
|
||||
u16 y_raw = (jc_pad->rstick_y - jc_cal_ctx.cry_max) / 7;
|
||||
if (y_raw > 0x7F)
|
||||
y_raw = 0x7F;
|
||||
rpt->rz = 0x7F - y_raw;
|
||||
// Hoag has inverted Y axis.
|
||||
if (!jc_pad->sio_mode)
|
||||
rpt->rz = 0x7F - y_raw;
|
||||
else
|
||||
rpt->rz = 0x7F + y_raw;
|
||||
}
|
||||
else
|
||||
{
|
||||
u16 y_raw = (jc_cal_ctx.cry_min - jc_pad->rstick_y) / 7;
|
||||
if (y_raw > 0x7F)
|
||||
y_raw = 0x7F;
|
||||
rpt->rz = 0x7F + y_raw;
|
||||
// Hoag has inverted Y axis.
|
||||
if (!jc_pad->sio_mode)
|
||||
rpt->rz = 0x7F + y_raw;
|
||||
else
|
||||
rpt->rz = 0x7F - y_raw;
|
||||
}
|
||||
|
||||
// Set D-pad.
|
||||
@@ -312,7 +328,7 @@ 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);
|
||||
if (status == USB_ERROR_XFER_ERROR)
|
||||
{
|
||||
usbs->set_text(usbs->label, "#FFDD00 Error:# EP IN transfer!");
|
||||
usbs->set_text(usbs->label, "#FFDD00 错误:#EP IN传输!");
|
||||
if (usb_ops.usbd_flush_endpoint)
|
||||
usb_ops.usbd_flush_endpoint(USB_EP_BULK_IN);
|
||||
}
|
||||
@@ -361,7 +377,7 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs)
|
||||
|
||||
if (usbs->type == USB_HID_GAMEPAD)
|
||||
{
|
||||
polling_time = 8000;
|
||||
polling_time = 15000;
|
||||
gadget_type = USB_GADGET_HID_GAMEPAD;
|
||||
}
|
||||
else
|
||||
@@ -370,7 +386,7 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs)
|
||||
gadget_type = USB_GADGET_HID_TOUCHPAD;
|
||||
}
|
||||
|
||||
usbs->set_text(usbs->label, "#C7EA46 Status:# Started USB");
|
||||
usbs->set_text(usbs->label, "#C7EA46 状态:#开启USB");
|
||||
|
||||
if (usb_ops.usb_device_init())
|
||||
{
|
||||
@@ -378,18 +394,18 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs)
|
||||
return 1;
|
||||
}
|
||||
|
||||
usbs->set_text(usbs->label, "#C7EA46 Status:# Waiting for connection");
|
||||
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 Status:# Waiting for HID report request");
|
||||
usbs->set_text(usbs->label, "#C7EA46 状态:#等待HID上报请求");
|
||||
|
||||
if (usb_ops.usb_device_class_send_hid_report())
|
||||
goto error;
|
||||
|
||||
usbs->set_text(usbs->label, "#C7EA46 Status:# Started HID emulation");
|
||||
usbs->set_text(usbs->label, "#C7EA46 状态:#开始HID模拟");
|
||||
|
||||
u32 timer_sys = get_tmr_ms() + 5000;
|
||||
while (true)
|
||||
@@ -427,11 +443,11 @@ int usb_device_gadget_hid(usb_ctxt_t *usbs)
|
||||
}
|
||||
}
|
||||
|
||||
usbs->set_text(usbs->label, "#C7EA46 Status:# HID ended");
|
||||
usbs->set_text(usbs->label, "#C7EA46 状态:#HID结束");
|
||||
goto exit;
|
||||
|
||||
error:
|
||||
usbs->set_text(usbs->label, "#FFDD00 Error:# Timed out or canceled");
|
||||
usbs->set_text(usbs->label, "#FFDD00 错误:#超时或取消");
|
||||
res = 1;
|
||||
|
||||
exit:
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Copyright (c) 2003-2008 Alan Stern
|
||||
* Copyright (c) 2009 Samsung Electronics
|
||||
* Author: Michal Nazarewicz <m.nazarewicz@samsung.com>
|
||||
* Copyright (c) 2019-2021 CTCaer
|
||||
* Copyright (c) 2019-2023 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,
|
||||
@@ -24,13 +24,14 @@
|
||||
#include <usb/usbd.h>
|
||||
#include <gfx_utils.h>
|
||||
#include <soc/hw_init.h>
|
||||
#include <soc/timer.h>
|
||||
#include <soc/t210.h>
|
||||
#include <storage/nx_sd.h>
|
||||
#include <storage/sd.h>
|
||||
#include <storage/sdmmc.h>
|
||||
#include <storage/emmc.h>
|
||||
#include <storage/sdmmc_driver.h>
|
||||
#include <utils/btn.h>
|
||||
#include <utils/sprintf.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
#include <memory_map.h>
|
||||
|
||||
@@ -283,40 +284,40 @@ 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)
|
||||
static void _handle_ep0_ctrl(usbd_gadget_ums_t *ums)
|
||||
{
|
||||
if (usb_ops.usbd_handle_ep0_ctrl_setup())
|
||||
raise_exception(ums, UMS_STATE_PROTOCOL_RESET);
|
||||
}
|
||||
|
||||
static int ums_wedge_bulk_in_endpoint(usbd_gadget_ums_t *ums)
|
||||
static int _wedge_bulk_in_endpoint(usbd_gadget_ums_t *ums)
|
||||
{
|
||||
/* usbd_set_ep_wedge(bulk_ctxt->bulk_in); */
|
||||
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int ums_set_stall(u32 ep)
|
||||
static int _set_ep_stall(u32 ep)
|
||||
{
|
||||
usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_STALL);
|
||||
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int ums_clear_stall(u32 ep)
|
||||
static int _clear_ep_stall(u32 ep)
|
||||
{
|
||||
usb_ops.usbd_set_ep_stall(ep, USB_EP_CFG_CLEAR);
|
||||
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static void ums_flush_endpoint(u32 ep)
|
||||
static void _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, u32 sync_timeout)
|
||||
static void _transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, u32 sync_timeout)
|
||||
{
|
||||
if (ep == bulk_ctxt->bulk_in)
|
||||
{
|
||||
@@ -326,11 +327,11 @@ static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt,
|
||||
|
||||
if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR)
|
||||
{
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# EP IN transfer!");
|
||||
ums_flush_endpoint(bulk_ctxt->bulk_in);
|
||||
ums->set_text(ums->label, "#FFDD00 错误:#EP 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 Error:# EP IN Buffer not aligned!");
|
||||
ums->set_text(ums->label, "#FFDD00 错误:#EP IN缓冲区未对齐!");
|
||||
|
||||
if (sync_timeout)
|
||||
bulk_ctxt->bulk_in_buf_state = BUF_STATE_EMPTY;
|
||||
@@ -343,18 +344,18 @@ static void _ums_transfer_start(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt,
|
||||
|
||||
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
|
||||
{
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# EP OUT transfer!");
|
||||
ums_flush_endpoint(bulk_ctxt->bulk_out);
|
||||
ums->set_text(ums->label, "#FFDD00 错误:#EP 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 Error:# EP OUT Buffer not aligned!");
|
||||
ums->set_text(ums->label, "#FFDD00 错误:#EP OUT缓冲区未对齐!");
|
||||
|
||||
if (sync_timeout)
|
||||
bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void _ums_transfer_out_big_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
static void _transfer_out_big_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_read_big(
|
||||
bulk_ctxt->bulk_out_buf, bulk_ctxt->bulk_out_length,
|
||||
@@ -362,14 +363,14 @@ static void _ums_transfer_out_big_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk
|
||||
|
||||
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
|
||||
{
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# EP OUT transfer!");
|
||||
ums_flush_endpoint(bulk_ctxt->bulk_out);
|
||||
ums->set_text(ums->label, "#FFDD00 错误:#EP OUT传输!");
|
||||
_flush_endpoint(bulk_ctxt->bulk_out);
|
||||
}
|
||||
|
||||
bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL;
|
||||
}
|
||||
|
||||
static void _ums_transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, u32 sync_timeout)
|
||||
static void _transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, u32 sync_timeout)
|
||||
{
|
||||
if (ep == bulk_ctxt->bulk_in)
|
||||
{
|
||||
@@ -378,8 +379,8 @@ static void _ums_transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt,
|
||||
|
||||
if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR)
|
||||
{
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# EP IN transfer!");
|
||||
ums_flush_endpoint(bulk_ctxt->bulk_in);
|
||||
ums->set_text(ums->label, "#FFDD00 错误:#EP IN传输!");
|
||||
_flush_endpoint(bulk_ctxt->bulk_in);
|
||||
}
|
||||
|
||||
bulk_ctxt->bulk_in_buf_state = BUF_STATE_EMPTY;
|
||||
@@ -391,15 +392,15 @@ static void _ums_transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt,
|
||||
|
||||
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
|
||||
{
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# EP OUT transfer!");
|
||||
ums_flush_endpoint(bulk_ctxt->bulk_out);
|
||||
ums->set_text(ums->label, "#FFDD00 错误:#EP OUT传输!");
|
||||
_flush_endpoint(bulk_ctxt->bulk_out);
|
||||
}
|
||||
|
||||
bulk_ctxt->bulk_out_buf_state = BUF_STATE_FULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void _ums_reset_buffer(bulk_ctxt_t *bulk_ctxt, u32 ep)
|
||||
static void _reset_buffer(bulk_ctxt_t *bulk_ctxt, u32 ep)
|
||||
{
|
||||
if (ep == bulk_ctxt->bulk_in)
|
||||
bulk_ctxt->bulk_in_buf = (u8 *)USB_EP_BULK_IN_BUF_ADDR;
|
||||
@@ -461,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 Warn:# Read - Out of range! Host notified.");
|
||||
ums->set_text(ums->label, "#FF8000 警告:#读 - 超出范围!主机通知。");
|
||||
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
|
||||
return UMS_RES_INVALID_ARG;
|
||||
@@ -474,20 +475,21 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
|
||||
// Limit IO transfers based on request for faster concurrent reads.
|
||||
u32 max_io_transfer = (amount_left >= UMS_SCSI_TRANSFER_512K) ?
|
||||
UMS_DISK_MAX_IO_TRANSFER_64K : UMS_DISK_MAX_IO_TRANSFER_32K;
|
||||
UMS_DISK_MAX_IO_TRANSFER_64K : UMS_DISK_MAX_IO_TRANSFER_32K;
|
||||
|
||||
while (true)
|
||||
{
|
||||
// Max io size and end sector limits.
|
||||
u32 amount = MIN(amount_left, max_io_transfer);
|
||||
amount = MIN(amount, ums->lun.num_sectors - lba_offset);
|
||||
amount = MIN(amount, ums->lun.num_sectors - lba_offset);
|
||||
|
||||
// Check if it is a read past the end sector.
|
||||
if (!amount)
|
||||
{
|
||||
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
ums->lun.sense_data_info = lba_offset;
|
||||
ums->lun.info_valid = 1;
|
||||
ums->lun.info_valid = 1;
|
||||
|
||||
bulk_ctxt->bulk_in_length = 0;
|
||||
bulk_ctxt->bulk_in_buf_state = BUF_STATE_FULL;
|
||||
break;
|
||||
@@ -499,7 +501,7 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
|
||||
// Wait for the async USB transfer to finish.
|
||||
if (!first_read)
|
||||
_ums_transfer_finish(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED);
|
||||
_transfer_finish(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED);
|
||||
|
||||
lba_offset += amount;
|
||||
amount_left -= amount;
|
||||
@@ -512,10 +514,10 @@ 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 Error:# SDMMC Read!");
|
||||
ums->lun.sense_data = SS_UNRECOVERED_READ_ERROR;
|
||||
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;
|
||||
ums->lun.info_valid = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -524,7 +526,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, USB_XFER_START);
|
||||
_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_START);
|
||||
first_read = false;
|
||||
|
||||
// Increment our buffer to read new data.
|
||||
@@ -550,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 Warn:# Write - Read only! Host notified.");
|
||||
ums->set_text(ums->label, "#FF8000 警告:#写 - 只读!主机通知。");
|
||||
ums->lun.sense_data = SS_WRITE_PROTECTED;
|
||||
|
||||
return UMS_RES_INVALID_ARG;
|
||||
@@ -574,15 +576,15 @@ 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 Warn:# Write - Out of range! Host notified.");
|
||||
ums->set_text(ums->label, "#FF8000 警告:#写 - 超出范围!主机通知。");
|
||||
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
|
||||
// Carry out the file writes.
|
||||
usb_lba_offset = lba_offset;
|
||||
amount_left_to_req = ums->data_size_from_cmnd;
|
||||
usb_lba_offset = lba_offset;
|
||||
amount_left_to_req = ums->data_size_from_cmnd;
|
||||
amount_left_to_write = ums->data_size_from_cmnd;
|
||||
|
||||
while (amount_left_to_write > 0)
|
||||
@@ -596,21 +598,21 @@ 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 Error:# Write - Past last sector!");
|
||||
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
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;
|
||||
ums->lun.info_valid = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the next buffer.
|
||||
usb_lba_offset += amount >> UMS_DISK_LBA_SHIFT;
|
||||
usb_lba_offset += amount >> UMS_DISK_LBA_SHIFT;
|
||||
ums->usb_amount_left -= amount;
|
||||
amount_left_to_req -= amount;
|
||||
amount_left_to_req -= amount;
|
||||
|
||||
bulk_ctxt->bulk_out_length = amount;
|
||||
|
||||
_ums_transfer_out_big_read(ums, bulk_ctxt);
|
||||
_transfer_out_big_read(ums, bulk_ctxt);
|
||||
}
|
||||
|
||||
if (bulk_ctxt->bulk_out_buf_state == BUF_STATE_FULL)
|
||||
@@ -620,10 +622,11 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
// Did something go wrong with the transfer?.
|
||||
if (bulk_ctxt->bulk_out_status != 0)
|
||||
{
|
||||
ums->lun.sense_data = SS_COMMUNICATION_FAILURE;
|
||||
ums->lun.sense_data = SS_COMMUNICATION_FAILURE;
|
||||
ums->lun.sense_data_info = lba_offset;
|
||||
ums->lun.info_valid = 1;
|
||||
s_printf(txt_buf, "#FFDD00 Error:# Write - Comm failure %d!", bulk_ctxt->bulk_out_status);
|
||||
ums->lun.info_valid = 1;
|
||||
|
||||
s_printf(txt_buf, "#FFDD00 错误:#写 - 通讯失败 %d!", bulk_ctxt->bulk_out_status);
|
||||
ums->set_text(ums->label, txt_buf);
|
||||
break;
|
||||
}
|
||||
@@ -661,10 +664,10 @@ 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 Error:# SDMMC Write!");
|
||||
ums->lun.sense_data = SS_WRITE_ERROR;
|
||||
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;
|
||||
ums->lun.info_valid = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -672,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 Error:# Empty Write!");
|
||||
ums->set_text(ums->label, "#FFDD00 错误:#写空!");
|
||||
ums->short_packet_received = 1;
|
||||
break;
|
||||
}
|
||||
@@ -688,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 Warn:# Verif - Out of range! Host notified.");
|
||||
ums->set_text(ums->label, "#FF8000 警告:#验证 - 超出范围!主机通知。");
|
||||
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
|
||||
return UMS_RES_INVALID_ARG;
|
||||
@@ -714,9 +717,9 @@ static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
amount = MIN(verification_length, USB_EP_BUFFER_MAX_SIZE >> UMS_DISK_LBA_SHIFT);
|
||||
amount = MIN(amount, ums->lun.num_sectors - lba_offset);
|
||||
if (amount == 0) {
|
||||
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
ums->lun.sense_data_info = lba_offset;
|
||||
ums->lun.info_valid = 1;
|
||||
ums->lun.info_valid = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -727,10 +730,10 @@ DPRINTF("File read %X @ %X\n", amount, lba_offset);
|
||||
|
||||
if (!amount)
|
||||
{
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# File verify!");
|
||||
ums->lun.sense_data = SS_UNRECOVERED_READ_ERROR;
|
||||
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;
|
||||
ums->lun.info_valid = 1;
|
||||
break;
|
||||
}
|
||||
lba_offset += amount;
|
||||
@@ -755,12 +758,12 @@ static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
|
||||
buf += 4;
|
||||
s_printf((char *)buf, "%04X%s",
|
||||
ums->lun.storage->cid.serial, ums->lun.type == MMC_SD ? " SD " : " eMMC ");
|
||||
ums->lun.storage->cid.serial, ums->lun.type == MMC_SD ? " SD卡 " : " eMMC ");
|
||||
|
||||
switch (ums->lun.partition)
|
||||
{
|
||||
case 0:
|
||||
strcpy((char *)buf + strlen((char *)buf), "RAW");
|
||||
strcpy((char *)buf + strlen((char *)buf), "原始");
|
||||
break;
|
||||
case EMMC_GPP + 1:
|
||||
s_printf((char *)buf + strlen((char *)buf), "GPP");
|
||||
@@ -796,19 +799,19 @@ 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 RAW");
|
||||
s_printf((char *)buf, "%s", "SD卡原始分区");
|
||||
break;
|
||||
case EMMC_GPP + 1:
|
||||
s_printf((char *)buf, "%s%s",
|
||||
ums->lun.type == MMC_SD ? "SD " : "eMMC ", "GPP");
|
||||
ums->lun.type == MMC_SD ? "SD卡 " : "eMMC ", "GPP");
|
||||
break;
|
||||
case EMMC_BOOT0 + 1:
|
||||
s_printf((char *)buf, "%s%s",
|
||||
ums->lun.type == MMC_SD ? "SD " : "eMMC ", "BOOT0");
|
||||
ums->lun.type == MMC_SD ? "SD卡 " : "eMMC ", "BOOT0");
|
||||
break;
|
||||
case EMMC_BOOT1 + 1:
|
||||
s_printf((char *)buf, "%s%s",
|
||||
ums->lun.type == MMC_SD ? "SD " : "eMMC ", "BOOT1");
|
||||
ums->lun.type == MMC_SD ? "SD卡 " : "eMMC ", "BOOT1");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1056,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 Status:# Unload attempt prevented");
|
||||
ums->set_text(ums->label, "#C7EA46 状态:#卸载尝试被阻止");
|
||||
ums->lun.sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
|
||||
|
||||
return UMS_RES_INVALID_ARG;
|
||||
@@ -1116,8 +1119,9 @@ static int _scsi_read_format_capacities(usbd_gadget_ums_t *ums, bulk_ctxt_t *bul
|
||||
|
||||
// Check whether the command is properly formed and whether its data size
|
||||
// and direction agree with the values we already have.
|
||||
static int _ums_check_scsi_cmd(usbd_gadget_ums_t *ums, u32 cmnd_size,
|
||||
enum data_direction data_dir, u32 mask, int needs_medium)
|
||||
static int _check_scsi_cmd(usbd_gadget_ums_t *ums, u32 cmnd_size,
|
||||
enum data_direction data_dir, u32 mask,
|
||||
int needs_medium)
|
||||
{
|
||||
//const char dirletter[4] = {'u', 'o', 'i', 'n'};
|
||||
DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n",
|
||||
@@ -1165,9 +1169,9 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n",
|
||||
|
||||
if (ums->cmnd[0] != SC_REQUEST_SENSE)
|
||||
{
|
||||
ums->lun.sense_data = SS_NO_SENSE;
|
||||
ums->lun.sense_data = SS_NO_SENSE;
|
||||
ums->lun.sense_data_info = 0;
|
||||
ums->lun.info_valid = 0;
|
||||
ums->lun.info_valid = 0;
|
||||
}
|
||||
|
||||
// If a unit attention condition exists, only INQUIRY and REQUEST SENSE
|
||||
@@ -1204,7 +1208,7 @@ DPRINTF("SCSI command: %X; Dc=%d, D%c=%X; Hc=%d, H%c=%X\n",
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
static int _parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
u32 len;
|
||||
int reply = UMS_RES_INVALID_ARG;
|
||||
@@ -1219,21 +1223,21 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
u32 mask = (1<<4);
|
||||
if (ums->cmnd[1] == 1 && ums->cmnd[2] == 0x80) // Inquiry S/N.
|
||||
mask = (1<<1) | (1<<2) | (1<<4);
|
||||
reply = _ums_check_scsi_cmd(ums, 6, DATA_DIR_TO_HOST, mask, 0);
|
||||
reply = _check_scsi_cmd(ums, 6, DATA_DIR_TO_HOST, mask, 0);
|
||||
if (reply == 0)
|
||||
reply = _scsi_inquiry(ums, bulk_ctxt);
|
||||
break;
|
||||
|
||||
case SC_LOG_SENSE:
|
||||
ums->data_size_from_cmnd = get_array_be_to_le16(&ums->cmnd[7]);
|
||||
reply = _ums_check_scsi_cmd(ums, 10, DATA_DIR_TO_HOST, (1<<1) | (1<<2) | (3<<7), 0);
|
||||
reply = _check_scsi_cmd(ums, 10, DATA_DIR_TO_HOST, (1<<1) | (1<<2) | (3<<7), 0);
|
||||
if (reply == 0)
|
||||
reply = _scsi_log_sense(ums, bulk_ctxt);
|
||||
break;
|
||||
|
||||
case SC_MODE_SELECT_6:
|
||||
ums->data_size_from_cmnd = ums->cmnd[4];
|
||||
reply = _ums_check_scsi_cmd(ums, 6, DATA_DIR_FROM_HOST, (1<<1) | (1<<4), 0);
|
||||
reply = _check_scsi_cmd(ums, 6, DATA_DIR_FROM_HOST, (1<<1) | (1<<4), 0);
|
||||
if (reply == 0)
|
||||
{
|
||||
// We don't support MODE SELECT.
|
||||
@@ -1244,7 +1248,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
|
||||
case SC_MODE_SELECT_10:
|
||||
ums->data_size_from_cmnd = get_array_be_to_le16(&ums->cmnd[7]);
|
||||
reply = _ums_check_scsi_cmd(ums, 10, DATA_DIR_FROM_HOST, (1<<1) | (3<<7), 0);
|
||||
reply = _check_scsi_cmd(ums, 10, DATA_DIR_FROM_HOST, (1<<1) | (3<<7), 0);
|
||||
if (reply == 0)
|
||||
{
|
||||
// We don't support MODE SELECT.
|
||||
@@ -1255,21 +1259,21 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
|
||||
case SC_MODE_SENSE_6:
|
||||
ums->data_size_from_cmnd = ums->cmnd[4];
|
||||
reply = _ums_check_scsi_cmd(ums, 6, DATA_DIR_TO_HOST, (1<<1) | (1<<2) | (1<<4), 0);
|
||||
reply = _check_scsi_cmd(ums, 6, DATA_DIR_TO_HOST, (1<<1) | (1<<2) | (1<<4), 0);
|
||||
if (reply == 0)
|
||||
reply = _scsi_mode_sense(ums, bulk_ctxt);
|
||||
break;
|
||||
|
||||
case SC_MODE_SENSE_10:
|
||||
ums->data_size_from_cmnd = get_array_be_to_le16(&ums->cmnd[7]);
|
||||
reply = _ums_check_scsi_cmd(ums, 10, DATA_DIR_TO_HOST, (1<<1) | (1<<2) | (3<<7), 0);
|
||||
reply = _check_scsi_cmd(ums, 10, DATA_DIR_TO_HOST, (1<<1) | (1<<2) | (3<<7), 0);
|
||||
if (reply == 0)
|
||||
reply = _scsi_mode_sense(ums, bulk_ctxt);
|
||||
break;
|
||||
|
||||
case SC_PREVENT_ALLOW_MEDIUM_REMOVAL:
|
||||
ums->data_size_from_cmnd = 0;
|
||||
reply = _ums_check_scsi_cmd(ums, 6, DATA_DIR_NONE, (1<<4), 0);
|
||||
reply = _check_scsi_cmd(ums, 6, DATA_DIR_NONE, (1<<4), 0);
|
||||
if (reply == 0)
|
||||
reply = _scsi_prevent_allow_removal(ums);
|
||||
break;
|
||||
@@ -1277,68 +1281,68 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
case SC_READ_6:
|
||||
len = ums->cmnd[4];
|
||||
ums->data_size_from_cmnd = (len == 0 ? 256 : len) << UMS_DISK_LBA_SHIFT;
|
||||
reply = _ums_check_scsi_cmd(ums, 6, DATA_DIR_TO_HOST, (7<<1) | (1<<4), 1);
|
||||
reply = _check_scsi_cmd(ums, 6, DATA_DIR_TO_HOST, (7<<1) | (1<<4), 1);
|
||||
if (reply == 0)
|
||||
reply = _scsi_read(ums, bulk_ctxt);
|
||||
break;
|
||||
|
||||
case SC_READ_10:
|
||||
ums->data_size_from_cmnd = get_array_be_to_le16(&ums->cmnd[7]) << UMS_DISK_LBA_SHIFT;
|
||||
reply = _ums_check_scsi_cmd(ums, 10, DATA_DIR_TO_HOST, (1<<1) | (0xf<<2) | (3<<7), 1);
|
||||
reply = _check_scsi_cmd(ums, 10, DATA_DIR_TO_HOST, (1<<1) | (0xf<<2) | (3<<7), 1);
|
||||
if (reply == 0)
|
||||
reply = _scsi_read(ums, bulk_ctxt);
|
||||
break;
|
||||
|
||||
case SC_READ_12:
|
||||
ums->data_size_from_cmnd = get_array_be_to_le32(&ums->cmnd[6]) << UMS_DISK_LBA_SHIFT;
|
||||
reply = _ums_check_scsi_cmd(ums, 12, DATA_DIR_TO_HOST, (1<<1) | (0xf<<2) | (0xf<<6), 1);
|
||||
reply = _check_scsi_cmd(ums, 12, DATA_DIR_TO_HOST, (1<<1) | (0xf<<2) | (0xf<<6), 1);
|
||||
if (reply == 0)
|
||||
reply = _scsi_read(ums, bulk_ctxt);
|
||||
break;
|
||||
|
||||
case SC_READ_CAPACITY:
|
||||
ums->data_size_from_cmnd = 8;
|
||||
reply = _ums_check_scsi_cmd(ums, 10, DATA_DIR_TO_HOST, (0xf<<2) | (1<<8), 1);
|
||||
reply = _check_scsi_cmd(ums, 10, DATA_DIR_TO_HOST, (0xf<<2) | (1<<8), 1);
|
||||
if (reply == 0)
|
||||
reply = _scsi_read_capacity(ums, bulk_ctxt);
|
||||
break;
|
||||
case SC_READ_FORMAT_CAPACITIES:
|
||||
ums->data_size_from_cmnd = get_array_be_to_le16(&ums->cmnd[7]);
|
||||
reply = _ums_check_scsi_cmd(ums, 10, DATA_DIR_TO_HOST, (3<<7), 1);
|
||||
reply = _check_scsi_cmd(ums, 10, DATA_DIR_TO_HOST, (3<<7), 1);
|
||||
if (reply == 0)
|
||||
reply = _scsi_read_format_capacities(ums, bulk_ctxt);
|
||||
break;
|
||||
|
||||
case SC_REQUEST_SENSE:
|
||||
ums->data_size_from_cmnd = ums->cmnd[4];
|
||||
reply = _ums_check_scsi_cmd(ums, 6, DATA_DIR_TO_HOST, (1<<4), 0);
|
||||
reply = _check_scsi_cmd(ums, 6, DATA_DIR_TO_HOST, (1<<4), 0);
|
||||
if (reply == 0)
|
||||
reply = _scsi_request_sense(ums, bulk_ctxt);
|
||||
break;
|
||||
|
||||
case SC_START_STOP_UNIT:
|
||||
ums->data_size_from_cmnd = 0;
|
||||
reply = _ums_check_scsi_cmd(ums, 6, DATA_DIR_NONE, (1<<1) | (1<<4), 0);
|
||||
reply = _check_scsi_cmd(ums, 6, DATA_DIR_NONE, (1<<1) | (1<<4), 0);
|
||||
if (reply == 0)
|
||||
reply = _scsi_start_stop(ums);
|
||||
break;
|
||||
|
||||
case SC_SYNCHRONIZE_CACHE:
|
||||
ums->data_size_from_cmnd = 0;
|
||||
reply = _ums_check_scsi_cmd(ums, 10, DATA_DIR_NONE, (0xf<<2) | (3<<7), 1);
|
||||
reply = _check_scsi_cmd(ums, 10, DATA_DIR_NONE, (0xf<<2) | (3<<7), 1);
|
||||
if (reply == 0)
|
||||
reply = 0; // Don't bother
|
||||
break;
|
||||
|
||||
case SC_TEST_UNIT_READY:
|
||||
ums->data_size_from_cmnd = 0;
|
||||
reply = _ums_check_scsi_cmd(ums, 6, DATA_DIR_NONE, 0, 1);
|
||||
reply = _check_scsi_cmd(ums, 6, DATA_DIR_NONE, 0, 1);
|
||||
break;
|
||||
|
||||
// This command is used by Windows. We support a minimal version and BytChk must be 0.
|
||||
case SC_VERIFY:
|
||||
ums->data_size_from_cmnd = 0;
|
||||
reply = _ums_check_scsi_cmd(ums, 10, DATA_DIR_NONE, (1<<1) | (0xf<<2) | (3<<7), 1);
|
||||
reply = _check_scsi_cmd(ums, 10, DATA_DIR_NONE, (1<<1) | (0xf<<2) | (3<<7), 1);
|
||||
if (reply == 0)
|
||||
reply = _scsi_verify(ums, bulk_ctxt);
|
||||
break;
|
||||
@@ -1346,21 +1350,21 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
case SC_WRITE_6:
|
||||
len = ums->cmnd[4];
|
||||
ums->data_size_from_cmnd = (len == 0 ? 256 : len) << UMS_DISK_LBA_SHIFT;
|
||||
reply = _ums_check_scsi_cmd(ums, 6, DATA_DIR_FROM_HOST, (7<<1) | (1<<4), 1);
|
||||
reply = _check_scsi_cmd(ums, 6, DATA_DIR_FROM_HOST, (7<<1) | (1<<4), 1);
|
||||
if (reply == 0)
|
||||
reply = _scsi_write(ums, bulk_ctxt);
|
||||
break;
|
||||
|
||||
case SC_WRITE_10:
|
||||
ums->data_size_from_cmnd = get_array_be_to_le16(&ums->cmnd[7]) << UMS_DISK_LBA_SHIFT;
|
||||
reply = _ums_check_scsi_cmd(ums, 10, DATA_DIR_FROM_HOST, (1<<1) | (0xf<<2) | (3<<7), 1);
|
||||
reply = _check_scsi_cmd(ums, 10, DATA_DIR_FROM_HOST, (1<<1) | (0xf<<2) | (3<<7), 1);
|
||||
if (reply == 0)
|
||||
reply = _scsi_write(ums, bulk_ctxt);
|
||||
break;
|
||||
|
||||
case SC_WRITE_12:
|
||||
ums->data_size_from_cmnd = get_array_be_to_le32(&ums->cmnd[6]) << UMS_DISK_LBA_SHIFT;
|
||||
reply = _ums_check_scsi_cmd(ums, 12, DATA_DIR_FROM_HOST, (1<<1) | (0xf<<2) | (0xf<<6), 1);
|
||||
reply = _check_scsi_cmd(ums, 12, DATA_DIR_FROM_HOST, (1<<1) | (0xf<<2) | (0xf<<6), 1);
|
||||
if (reply == 0)
|
||||
reply = _scsi_write(ums, bulk_ctxt);
|
||||
break;
|
||||
@@ -1374,7 +1378,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
case SC_SEND_DIAGNOSTIC:
|
||||
default:
|
||||
ums->data_size_from_cmnd = 0;
|
||||
reply = _ums_check_scsi_cmd(ums, ums->cmnd_size, DATA_DIR_UNKNOWN, 0xFF, 0);
|
||||
reply = _check_scsi_cmd(ums, ums->cmnd_size, DATA_DIR_UNKNOWN, 0xFF, 0);
|
||||
if (reply == 0)
|
||||
{
|
||||
ums->lun.sense_data = SS_INVALID_COMMAND;
|
||||
@@ -1386,7 +1390,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
if (reply == UMS_RES_INVALID_ARG)
|
||||
reply = 0; // Error reply length.
|
||||
|
||||
// Set up reply buffer for finish_reply(). Otherwise it's already set.
|
||||
// Set up reply buffer for _finish_reply(). Otherwise it's already set.
|
||||
if (reply >= 0 && ums->data_dir == DATA_DIR_TO_HOST)
|
||||
{
|
||||
reply = MIN((u32)reply, ums->data_size_from_cmnd);
|
||||
@@ -1398,7 +1402,7 @@ static int _ums_parse_scsi_cmd(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int pad_with_zeros(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
static int _pad_with_zeros(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
bulk_ctxt->bulk_in_buf_state = BUF_STATE_EMPTY; // For the first iteration.
|
||||
u32 current_len_to_keep = bulk_ctxt->bulk_in_length;
|
||||
@@ -1409,7 +1413,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, USB_XFER_SYNCED_DATA);
|
||||
_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA);
|
||||
ums->usb_amount_left -= nsend;
|
||||
current_len_to_keep = 0;
|
||||
}
|
||||
@@ -1417,7 +1421,7 @@ static int pad_with_zeros(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
static int _throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
if (bulk_ctxt->bulk_out_buf_state != BUF_STATE_EMPTY || ums->usb_amount_left > 0)
|
||||
{
|
||||
@@ -1427,7 +1431,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, USB_XFER_SYNCED_DATA);
|
||||
_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_DATA);
|
||||
ums->usb_amount_left -= amount;
|
||||
|
||||
return UMS_RES_OK;
|
||||
@@ -1448,7 +1452,7 @@ static int throw_away_data(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
static int _finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
int rc = UMS_RES_OK;
|
||||
|
||||
@@ -1461,9 +1465,9 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
case DATA_DIR_UNKNOWN:
|
||||
if (ums->can_stall)
|
||||
{
|
||||
ums_set_stall(bulk_ctxt->bulk_out);
|
||||
rc = ums_set_stall(bulk_ctxt->bulk_in);
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# Direction unknown. Stalled both EP!");
|
||||
_set_ep_stall(bulk_ctxt->bulk_out);
|
||||
rc = _set_ep_stall(bulk_ctxt->bulk_in);
|
||||
ums->set_text(ums->label, "#FFDD00 错误:#方向不明。两端EP都停了!");
|
||||
} // Else do nothing.
|
||||
break;
|
||||
|
||||
@@ -1474,7 +1478,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, USB_XFER_SYNCED_DATA);
|
||||
_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_DATA);
|
||||
|
||||
/* For Bulk-only, if we're allowed to stall then send the
|
||||
* short packet and halt the bulk-in endpoint. If we can't
|
||||
@@ -1482,16 +1486,16 @@ 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, USB_XFER_SYNCED_DATA);
|
||||
rc = ums_set_stall(bulk_ctxt->bulk_in);
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# Residue. Stalled EP IN!");
|
||||
_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停止!");
|
||||
}
|
||||
else
|
||||
rc = pad_with_zeros(ums, bulk_ctxt);
|
||||
rc = _pad_with_zeros(ums, bulk_ctxt);
|
||||
}
|
||||
|
||||
// In case we used SDMMC transfer, reset the buffer address.
|
||||
_ums_reset_buffer(bulk_ctxt, bulk_ctxt->bulk_in);
|
||||
_reset_buffer(bulk_ctxt, bulk_ctxt->bulk_in);
|
||||
break;
|
||||
|
||||
// We have processed all we want from the data the host has sent.
|
||||
@@ -1505,7 +1509,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
rc = UMS_RES_PROT_FATAL;
|
||||
}
|
||||
else // We can't stall. Read in the excess data and throw it away.
|
||||
rc = throw_away_data(ums, bulk_ctxt);
|
||||
rc = _throw_away_data(ums, bulk_ctxt);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1540,7 +1544,7 @@ static int finish_reply(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
* Line always at SE0.
|
||||
*/
|
||||
|
||||
static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
static int _received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
// Was this a real packet? Should it be ignored?
|
||||
if (bulk_ctxt->bulk_out_status || bulk_ctxt->bulk_out_ignore || ums->lun.unmounted)
|
||||
@@ -1557,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 Status:# EP in sleep");
|
||||
ums->set_text(ums->label, "#C7EA46 状态:#EP已休眠");
|
||||
ums->timeouts += 14;
|
||||
}
|
||||
else if (!ums->xusb) // Timeout only on USB2.
|
||||
@@ -1576,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 Status:# Medium unmounted");
|
||||
ums->set_text(ums->label, "#C7EA46 状态:#介质未挂载");
|
||||
ums->timeouts++;
|
||||
if (!bulk_ctxt->bulk_out_status)
|
||||
ums->timeouts += 3;
|
||||
@@ -1610,7 +1614,7 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
* we can simply accept and discard any data received
|
||||
* until the next reset.
|
||||
*/
|
||||
ums_wedge_bulk_in_endpoint(ums);
|
||||
_wedge_bulk_in_endpoint(ums);
|
||||
bulk_ctxt->bulk_out_ignore = 1;
|
||||
return UMS_RES_INVALID_ARG;
|
||||
}
|
||||
@@ -1626,9 +1630,9 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
* bulk pipes if we are allowed to. */
|
||||
if (ums->can_stall)
|
||||
{
|
||||
ums_set_stall(bulk_ctxt->bulk_out);
|
||||
ums_set_stall(bulk_ctxt->bulk_in);
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# CBW unknown - Stalled both EP!");
|
||||
_set_ep_stall(bulk_ctxt->bulk_out);
|
||||
_set_ep_stall(bulk_ctxt->bulk_in);
|
||||
ums->set_text(ums->label, "#FFDD00 错误:#CBW未知 - 两端EP都停了!");
|
||||
}
|
||||
|
||||
return UMS_RES_INVALID_ARG;
|
||||
@@ -1657,7 +1661,7 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
return UMS_RES_OK;
|
||||
}
|
||||
|
||||
static int get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
static int _get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
int rc = UMS_RES_OK;
|
||||
|
||||
@@ -1671,9 +1675,9 @@ static int get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
|
||||
// Queue a request to read a Bulk-only CBW.
|
||||
if (!ums->cbw_req_queued)
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_CMD);
|
||||
_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_CMD);
|
||||
else
|
||||
_ums_transfer_finish(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_CMD);
|
||||
_transfer_finish(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_CMD);
|
||||
|
||||
/*
|
||||
* On XUSB do not allow multiple requests for CBW to be done.
|
||||
@@ -1694,20 +1698,20 @@ static int get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
// //wait irq.
|
||||
// }
|
||||
|
||||
rc = received_cbw(ums, bulk_ctxt);
|
||||
rc = _received_cbw(ums, bulk_ctxt);
|
||||
bulk_ctxt->bulk_out_buf_state = BUF_STATE_EMPTY;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void send_status(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
static void _send_status(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
{
|
||||
u8 status = USB_STATUS_PASS;
|
||||
u32 sd = ums->lun.sense_data;
|
||||
|
||||
if (ums->phase_error)
|
||||
{
|
||||
ums->set_text(ums->label, "#FFDD00 Error:# Phase-error!");
|
||||
ums->set_text(ums->label, "#FFDD00 错误:#相位错误!");
|
||||
status = USB_STATUS_PHASE_ERROR;
|
||||
sd = SS_INVALID_COMMAND;
|
||||
}
|
||||
@@ -1723,26 +1727,26 @@ static void send_status(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
bulk_send_pkt_t *csw = (bulk_send_pkt_t *)bulk_ctxt->bulk_in_buf;
|
||||
|
||||
csw->Signature = USB_BULK_CS_SIG;
|
||||
csw->Tag = ums->tag;
|
||||
csw->Residue = ums->residue;
|
||||
csw->Status = status;
|
||||
csw->Tag = ums->tag;
|
||||
csw->Residue = ums->residue;
|
||||
csw->Status = status;
|
||||
|
||||
bulk_ctxt->bulk_in_length = USB_BULK_CS_WRAP_LEN;
|
||||
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_CMD);
|
||||
_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED_CMD);
|
||||
}
|
||||
|
||||
static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
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.
|
||||
ums_flush_endpoint(bulk_ctxt->bulk_in);
|
||||
ums_flush_endpoint(bulk_ctxt->bulk_out);
|
||||
_flush_endpoint(bulk_ctxt->bulk_in);
|
||||
_flush_endpoint(bulk_ctxt->bulk_out);
|
||||
|
||||
/* Reset the I/O buffer states and pointers, the SCSI
|
||||
* state, and the exception. Then invoke the handler. */
|
||||
|
||||
bulk_ctxt->bulk_in_buf_state = BUF_STATE_EMPTY;
|
||||
bulk_ctxt->bulk_in_buf_state = BUF_STATE_EMPTY;
|
||||
bulk_ctxt->bulk_out_buf_state = BUF_STATE_EMPTY;
|
||||
|
||||
old_state = ums->state;
|
||||
@@ -1750,10 +1754,10 @@ static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
if (old_state != UMS_STATE_ABORT_BULK_OUT)
|
||||
{
|
||||
ums->lun.prevent_medium_removal = 0;
|
||||
ums->lun.sense_data = SS_NO_SENSE;
|
||||
ums->lun.unit_attention_data = SS_NO_SENSE;
|
||||
ums->lun.sense_data_info = 0;
|
||||
ums->lun.info_valid = 0;
|
||||
ums->lun.sense_data = SS_NO_SENSE;
|
||||
ums->lun.unit_attention_data = SS_NO_SENSE;
|
||||
ums->lun.sense_data_info = 0;
|
||||
ums->lun.info_valid = 0;
|
||||
}
|
||||
|
||||
ums->state = UMS_STATE_NORMAL;
|
||||
@@ -1764,7 +1768,7 @@ static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
case UMS_STATE_NORMAL:
|
||||
break;
|
||||
case UMS_STATE_ABORT_BULK_OUT:
|
||||
send_status(ums, bulk_ctxt);
|
||||
_send_status(ums, bulk_ctxt);
|
||||
break;
|
||||
|
||||
case UMS_STATE_PROTOCOL_RESET:
|
||||
@@ -1774,7 +1778,7 @@ static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
if (bulk_ctxt->bulk_out_ignore)
|
||||
{
|
||||
bulk_ctxt->bulk_out_ignore = 0;
|
||||
ums_clear_stall(bulk_ctxt->bulk_in);
|
||||
_clear_ep_stall(bulk_ctxt->bulk_in);
|
||||
}
|
||||
ums->lun.unit_attention_data = SS_RESET_OCCURRED;
|
||||
break;
|
||||
@@ -1810,8 +1814,6 @@ static inline void _system_maintainance(usbd_gadget_ums_t *ums)
|
||||
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.
|
||||
@@ -1823,7 +1825,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
|
||||
xusb_device_get_ops(&usb_ops);
|
||||
}
|
||||
|
||||
usbs->set_text(usbs->label, "#C7EA46 Status:# Started USB");
|
||||
usbs->set_text(usbs->label, "#C7EA46 状态:#开启USB");
|
||||
|
||||
if (usb_ops.usb_device_init())
|
||||
{
|
||||
@@ -1834,17 +1836,17 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
|
||||
ums.state = UMS_STATE_NORMAL;
|
||||
ums.can_stall = 0;
|
||||
|
||||
ums.bulk_ctxt.bulk_in = USB_EP_BULK_IN;
|
||||
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 = USB_EP_BULK_OUT;
|
||||
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.
|
||||
ums.lun.ro = usbs->ro;
|
||||
ums.lun.type = usbs->type;
|
||||
ums.lun.ro = usbs->ro;
|
||||
ums.lun.type = usbs->type;
|
||||
ums.lun.partition = usbs->partition;
|
||||
ums.lun.offset = usbs->offset;
|
||||
ums.lun.offset = usbs->offset;
|
||||
ums.lun.removable = 1; // Always removable to force OSes to use prevent media removal.
|
||||
ums.lun.unit_attention_data = SS_RESET_OCCURRED;
|
||||
|
||||
@@ -1853,37 +1855,49 @@ 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 Status:# Mounting disk");
|
||||
ums.set_text(ums.label, "#C7EA46 状态:#挂载磁盘");
|
||||
|
||||
// Initialize sdmmc.
|
||||
if (usbs->type == MMC_SD)
|
||||
{
|
||||
sd_end();
|
||||
sd_mount();
|
||||
if (!sd_mount())
|
||||
{
|
||||
ums.set_text(ums.label, "#FFDD00 初始化SD卡失败!#");
|
||||
res = 1;
|
||||
goto init_fail;
|
||||
}
|
||||
sd_unmount();
|
||||
ums.lun.sdmmc = &sd_sdmmc;
|
||||
|
||||
ums.lun.sdmmc = &sd_sdmmc;
|
||||
ums.lun.storage = &sd_storage;
|
||||
}
|
||||
else
|
||||
{
|
||||
ums.lun.sdmmc = &sdmmc;
|
||||
ums.lun.storage = &storage;
|
||||
sdmmc_storage_init_mmc(ums.lun.storage, ums.lun.sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
sdmmc_storage_set_mmc_partition(ums.lun.storage, ums.lun.partition - 1);
|
||||
if (!emmc_initialize(false))
|
||||
{
|
||||
ums.set_text(ums.label, "#FFDD00 初始化eMMC失败!#");
|
||||
res = 1;
|
||||
goto init_fail;
|
||||
}
|
||||
emmc_set_partition(ums.lun.partition - 1);
|
||||
|
||||
ums.lun.sdmmc = &emmc_sdmmc;
|
||||
ums.lun.storage = &emmc_storage;
|
||||
}
|
||||
|
||||
ums.set_text(ums.label, "#C7EA46 Status:# Waiting for connection");
|
||||
ums.set_text(ums.label, "#C7EA46 状态:#等待连接");
|
||||
|
||||
// Initialize Control Endpoint.
|
||||
if (usb_ops.usb_device_enumerate(USB_GADGET_UMS))
|
||||
goto error;
|
||||
goto usb_enum_error;
|
||||
|
||||
ums.set_text(ums.label, "#C7EA46 Status:# Waiting for LUN");
|
||||
ums.set_text(ums.label, "#C7EA46 状态:#等待LUN");
|
||||
|
||||
if (usb_ops.usb_device_class_send_max_lun(0)) // One device for now.
|
||||
goto error;
|
||||
goto usb_enum_error;
|
||||
|
||||
ums.set_text(ums.label, "#C7EA46 Status:# Started UMS");
|
||||
ums.set_text(ums.label, "#C7EA46 状态:#开启UMS");
|
||||
|
||||
if (usbs->sectors)
|
||||
ums.lun.num_sectors = usbs->sectors;
|
||||
@@ -1900,49 +1914,50 @@ 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 Status:# Unload attempt prevented");
|
||||
ums.set_text(ums.label, "#C7EA46 状态:#卸载尝试被阻止");
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (ums.state != UMS_STATE_NORMAL)
|
||||
{
|
||||
handle_exception(&ums, &ums.bulk_ctxt);
|
||||
_handle_exception(&ums, &ums.bulk_ctxt);
|
||||
continue;
|
||||
}
|
||||
|
||||
ums_handle_ep0_ctrl(&ums);
|
||||
_handle_ep0_ctrl(&ums);
|
||||
|
||||
if (get_next_command(&ums, &ums.bulk_ctxt) || (ums.state > UMS_STATE_NORMAL))
|
||||
if (_get_next_command(&ums, &ums.bulk_ctxt) || (ums.state > UMS_STATE_NORMAL))
|
||||
continue;
|
||||
|
||||
ums_handle_ep0_ctrl(&ums);
|
||||
_handle_ep0_ctrl(&ums);
|
||||
|
||||
if (_ums_parse_scsi_cmd(&ums, &ums.bulk_ctxt) || (ums.state > UMS_STATE_NORMAL))
|
||||
if (_parse_scsi_cmd(&ums, &ums.bulk_ctxt) || (ums.state > UMS_STATE_NORMAL))
|
||||
continue;
|
||||
|
||||
ums_handle_ep0_ctrl(&ums);
|
||||
_handle_ep0_ctrl(&ums);
|
||||
|
||||
if (finish_reply(&ums, &ums.bulk_ctxt) || (ums.state > UMS_STATE_NORMAL))
|
||||
if (_finish_reply(&ums, &ums.bulk_ctxt) || (ums.state > UMS_STATE_NORMAL))
|
||||
continue;
|
||||
|
||||
send_status(&ums, &ums.bulk_ctxt);
|
||||
_send_status(&ums, &ums.bulk_ctxt);
|
||||
} while (ums.state != UMS_STATE_TERMINATED);
|
||||
|
||||
if (ums.lun.prevent_medium_removal)
|
||||
ums.set_text(ums.label, "#FFDD00 Error:# Disk unsafely ejected");
|
||||
ums.set_text(ums.label, "#FFDD00 错误:#磁盘不安全弹出");
|
||||
else
|
||||
ums.set_text(ums.label, "#C7EA46 Status:# Disk ejected");
|
||||
ums.set_text(ums.label, "#C7EA46 状态:#磁盘弹出");
|
||||
goto exit;
|
||||
|
||||
error:
|
||||
ums.set_text(ums.label, "#FFDD00 Error:# Timed out or canceled!");
|
||||
usb_enum_error:
|
||||
ums.set_text(ums.label, "#FFDD00 错误:#超时或取消!");
|
||||
res = 1;
|
||||
|
||||
exit:
|
||||
if (ums.lun.type == MMC_EMMC)
|
||||
sdmmc_storage_end(ums.lun.storage);
|
||||
emmc_end();
|
||||
|
||||
init_fail:
|
||||
usb_ops.usbd_end(true, false);
|
||||
|
||||
return res;
|
||||
|
||||
125
bdk/usb/usbd.c
125
bdk/usb/usbd.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Enhanced USB Device (EDCI) driver for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2019-2021 CTCaer
|
||||
* Copyright (c) 2019-2023 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,
|
||||
@@ -30,16 +30,16 @@
|
||||
#include <soc/gpio.h>
|
||||
#include <soc/pinmux.h>
|
||||
#include <soc/pmc.h>
|
||||
#include <soc/timer.h>
|
||||
#include <soc/t210.h>
|
||||
#include <utils/btn.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
#include <memory_map.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
USB_HW_EP0 = 0,
|
||||
USB_HW_EP1 = 1
|
||||
USB_HW_EP0 = 0,
|
||||
USB_HW_EP1 = 1
|
||||
} usb_hw_ep_t;
|
||||
|
||||
typedef enum
|
||||
@@ -143,11 +143,11 @@ static int _usbd_reset_usb_otg_phy_device_mode()
|
||||
|
||||
// Clear all device addresses, enabled setup requests and transmit events.
|
||||
usbd_otg->regs->periodiclistbase = 0;
|
||||
usbd_otg->regs->endptsetupstat = usbd_otg->regs->endptsetupstat;
|
||||
usbd_otg->regs->endptcomplete = usbd_otg->regs->endptcomplete;
|
||||
usbd_otg->regs->endptsetupstat = usbd_otg->regs->endptsetupstat;
|
||||
usbd_otg->regs->endptcomplete = usbd_otg->regs->endptcomplete;
|
||||
|
||||
// Stop device controller.
|
||||
usbd_otg->regs->usbcmd &= ~USB2D_USBCMD_RUN;
|
||||
usbd_otg->regs->usbcmd &= ~USB2D_USBCMD_RUN;
|
||||
|
||||
// Set controller mode to idle.
|
||||
usbd_otg->regs->usbmode &= ~USB2D_USBMODE_CM_MASK;
|
||||
@@ -192,16 +192,15 @@ static int _usbd_reset_usb_otg_phy_device_mode()
|
||||
usbd_otg->regs->usbintr = 0;
|
||||
|
||||
// Set the ID pullup and disable all OTGSC interrupts.
|
||||
usbd_otg->regs->otgsc = USB2D_OTGSC_USB_ID_PULLUP;
|
||||
usbd_otg->regs->otgsc = USB2D_OTGSC_USB_ID_PULLUP;
|
||||
|
||||
// Clear all relevant interrupt statuses.
|
||||
usbd_otg->regs->usbsts =
|
||||
USB2D_USBSTS_UI | USB2D_USBSTS_UEI | USB2D_USBSTS_PCI |
|
||||
USB2D_USBSTS_FRI | USB2D_USBSTS_SEI | USB2D_USBSTS_AAI |
|
||||
USB2D_USBSTS_URI | USB2D_USBSTS_SRI | USB2D_USBSTS_SLI;
|
||||
usbd_otg->regs->usbsts = USB2D_USBSTS_UI | USB2D_USBSTS_UEI | USB2D_USBSTS_PCI |
|
||||
USB2D_USBSTS_FRI | USB2D_USBSTS_SEI | USB2D_USBSTS_AAI |
|
||||
USB2D_USBSTS_URI | USB2D_USBSTS_SRI | USB2D_USBSTS_SLI;
|
||||
|
||||
// Disable and clear all OTGSC interrupts.
|
||||
usbd_otg->regs->otgsc = USB2D_OTGSC_USB_IRQ_STS_MASK;
|
||||
usbd_otg->regs->otgsc = USB2D_OTGSC_USB_IRQ_STS_MASK;
|
||||
|
||||
// Clear EP0, EP1, EP2 setup requests.
|
||||
usbd_otg->regs->endptsetupstat = 7; //TODO: Shouldn't this be endptsetupstat = endptsetupstat?
|
||||
@@ -222,11 +221,10 @@ static void _usb_charger_detect()
|
||||
usbd_otg->charger_detect |= 1;
|
||||
// Configure detect pin.
|
||||
PINMUX_AUX(PINMUX_AUX_LCD_GPIO1) &= ~(PINMUX_PARKED | PINMUX_TRISTATE | PINMUX_PULL_MASK);
|
||||
gpio_config(GPIO_PORT_V, GPIO_PIN_3, GPIO_MODE_GPIO);
|
||||
gpio_direction_input(GPIO_PORT_V, GPIO_PIN_3);
|
||||
|
||||
// Configure charger pin.
|
||||
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN1) &=
|
||||
~(PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_TRISTATE | PINMUX_PULL_MASK);
|
||||
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN1) &= ~(PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_TRISTATE | PINMUX_PULL_MASK);
|
||||
gpio_config(GPIO_PORT_CC, GPIO_PIN_5, GPIO_MODE_GPIO);
|
||||
gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_5, GPIO_OUTPUT_ENABLE);
|
||||
|
||||
@@ -289,12 +287,12 @@ static void _usb_init_phy()
|
||||
|
||||
// Configure misc UTMIP.
|
||||
USB(USB1_UTMIP_DEBOUNCE_CFG0) = (USB(USB1_UTMIP_DEBOUNCE_CFG0) & 0xFFFF0000) | 0xBB80;
|
||||
USB(USB1_UTMIP_BIAS_CFG1) = (USB(USB1_UTMIP_BIAS_CFG1) & 0xFFFFC0FF) | 0x100; // when osc is 38.4KHz
|
||||
USB(USB1_UTMIP_BIAS_CFG1) = (USB(USB1_UTMIP_BIAS_CFG1) & 0xFFFFC0FF) | 0x100; // when osc is 38.4KHz
|
||||
|
||||
//USB(USB1_UTMIP_SPARE_CFG0) &= 0xFFFFFEE7; unpatched0
|
||||
USB(USB1_UTMIP_BIAS_CFG2) |= 2; //patched0 - UTMIP_HSSQUELCH_LEVEL_NEW: 2.
|
||||
USB(USB1_UTMIP_BIAS_CFG2) |= 2; //patched0 - UTMIP_HSSQUELCH_LEVEL_NEW: 2.
|
||||
USB(USB1_UTMIP_SPARE_CFG0) &= 0xFFFFFE67; //patched0 - FUSE_HS_IREF_CAP_CFG
|
||||
USB(USB1_UTMIP_TX_CFG0) |= 0x80000;
|
||||
USB(USB1_UTMIP_TX_CFG0) |= 0x80000;
|
||||
|
||||
//USB(USB1_UTMIP_HSRX_CFG0) = (USB(USB1_UTMIP_HSRX_CFG0) & 0xFFF003FF) | 0x88000 | 0x4000; unpatched1
|
||||
USB(USB1_UTMIP_HSRX_CFG0) = (USB(USB1_UTMIP_HSRX_CFG0) & 0xF0F003FF) | 0x88000 | 0x4000; //patched1 - reset UTMIP_PCOUNT_UPDN_DIV: From 1 to 0.
|
||||
@@ -307,7 +305,7 @@ static void _usb_init_phy()
|
||||
CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) |= 0x40000000;
|
||||
|
||||
// Enable USB2 tracking clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_Y_SET) = BIT(CLK_Y_USB2_TRK);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_Y_SET) = BIT(CLK_Y_USB2_TRK);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_USB2_HSIC_TRK) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_USB2_HSIC_TRK) & 0xFFFFFF00) | 6; // Set trank divisor to 4.
|
||||
|
||||
USB(USB1_UTMIP_BIAS_CFG1) = (USB(USB1_UTMIP_BIAS_CFG1) & 0xFFC03F07) | 0x78000 | 0x50; // Set delays.
|
||||
@@ -338,7 +336,7 @@ static void _usb_init_phy()
|
||||
usleep(1);
|
||||
|
||||
// Clear power downs on UTMIP ID and VBUS wake up, PD, PD2, PDZI, PDCHRP, PDDR.
|
||||
PMC(APBDEV_PMC_USB_AO) &= 0xFFFFFFF3; // UTMIP ID and VBUS wake up.
|
||||
PMC(APBDEV_PMC_USB_AO) &= 0xFFFFFFF3; // UTMIP ID and VBUS wake up.
|
||||
usleep(1);
|
||||
USB(USB1_UTMIP_XCVR_CFG0) &= 0xFFFFBFFF; // UTMIP_FORCE_PD_POWERDOWN.
|
||||
usleep(1);
|
||||
@@ -362,14 +360,14 @@ int usb_device_init()
|
||||
|
||||
// AHB USB performance cfg.
|
||||
AHB_GIZMO(AHB_GIZMO_AHB_MEM) |= AHB_MEM_DONT_SPLIT_AHB_WR | AHB_MEM_ENB_FAST_REARBITRATE;
|
||||
AHB_GIZMO(AHB_GIZMO_USB) |= AHB_GIZMO_IMMEDIATE;
|
||||
AHB_GIZMO(AHB_GIZMO_USB) |= AHB_GIZMO_IMMEDIATE;
|
||||
AHB_GIZMO(AHB_ARBITRATION_PRIORITY_CTRL) = PRIORITY_CTRL_WEIGHT(7) | PRIORITY_SELECT_USB;
|
||||
AHB_GIZMO(AHB_AHB_MEM_PREFETCH_CFG1) =
|
||||
MEM_PREFETCH_ENABLE | MEM_PREFETCH_USB_MST_ID | MEM_PREFETCH_ADDR_BNDRY(12) | 0x1000; // Addr boundary 64KB, Inactivity 4096 cycles.
|
||||
AHB_GIZMO(AHB_AHB_MEM_PREFETCH_CFG1) = MEM_PREFETCH_ENABLE | MEM_PREFETCH_USB_MST_ID |
|
||||
MEM_PREFETCH_ADDR_BNDRY(12) | 0x1000; // Addr boundary 64KB, Inactivity 4096 cycles.
|
||||
|
||||
// Set software and hardware context storage and clear it.
|
||||
usbdaemon = (usbd_t *)USBD_ADDR; // Depends on USB_TD_BUFFER_PAGE_SIZE aligned address.
|
||||
usbd_otg = &usbd_usb_otg_controller_ctxt;
|
||||
usbd_otg = &usbd_usb_otg_controller_ctxt;
|
||||
memset(usbd_otg, 0, sizeof(usbd_controller_t));
|
||||
memset(usbdaemon, 0, sizeof(usbd_t));
|
||||
|
||||
@@ -443,6 +441,11 @@ static void _usb_device_power_down()
|
||||
usb_init_done = false;
|
||||
}
|
||||
|
||||
static void _usbd_disable_ep1()
|
||||
{
|
||||
usbd_otg->regs->endptctrl[1] = 0;
|
||||
}
|
||||
|
||||
static void _usbd_stall_reset_ep1(usb_dir_t direction, usb_ep_cfg_t stall)
|
||||
{
|
||||
stall &= 1;
|
||||
@@ -524,13 +527,11 @@ static void _usbd_initialize_ep_ctrl(u32 endpoint)
|
||||
{
|
||||
u32 endpoint_type = usbd_otg->regs->endptctrl[actual_ep] & ~USB2D_ENDPTCTRL_RX_EP_TYPE_MASK;
|
||||
if (actual_ep)
|
||||
{
|
||||
endpoint_type |= usbd_otg->gadget ? USB2D_ENDPTCTRL_RX_EP_TYPE_INTR : USB2D_ENDPTCTRL_RX_EP_TYPE_BULK;
|
||||
}
|
||||
else
|
||||
endpoint_type |= USB2D_ENDPTCTRL_RX_EP_TYPE_CTRL;
|
||||
|
||||
usbd_otg->regs->endptctrl[actual_ep] = endpoint_type;
|
||||
usbd_otg->regs->endptctrl[actual_ep] = endpoint_type;
|
||||
usbd_otg->regs->endptctrl[actual_ep] &= ~USB2D_ENDPTCTRL_RX_EP_STALL;
|
||||
|
||||
if (actual_ep == USB_HW_EP1)
|
||||
@@ -542,7 +543,7 @@ static void _usbd_initialize_ep_ctrl(u32 endpoint)
|
||||
|
||||
static int _usbd_initialize_ep0()
|
||||
{
|
||||
memset((void *)usbdaemon->qhs, 0, sizeof(dQH_t) * 4); // Clear all used EP queue heads.
|
||||
memset((void *)usbdaemon->qhs, 0, sizeof(dQH_t) * 4); // Clear all used EP queue heads.
|
||||
memset((void *)usbdaemon->dtds, 0, sizeof(dTD_t) * 4); // Clear all used EP0 token heads.
|
||||
|
||||
usbd_otg->regs->asynclistaddr = (u32)usbdaemon->qhs;
|
||||
@@ -583,8 +584,8 @@ int usbd_flush_endpoint(u32 endpoint)
|
||||
{
|
||||
|
||||
usb_hw_ep_t actual_ep = (endpoint & 2) >> 1;
|
||||
usb_dir_t direction = endpoint & 1;
|
||||
u32 reg_mask = endpoint;
|
||||
usb_dir_t direction = endpoint & 1;
|
||||
u32 reg_mask = endpoint;
|
||||
|
||||
// Flash all endpoints or 1.
|
||||
if (endpoint != USB_EP_ALL)
|
||||
@@ -628,19 +629,23 @@ int usbd_flush_endpoint(u32 endpoint)
|
||||
return USB_RES_OK;
|
||||
}
|
||||
|
||||
static void _usb_reset_disable_ep1()
|
||||
{
|
||||
usbd_flush_endpoint(USB_EP_ALL);
|
||||
_usbd_stall_reset_ep1(USB_DIR_OUT, USB_EP_CFG_RESET); // EP1 Bulk OUT.
|
||||
_usbd_stall_reset_ep1(USB_DIR_IN, USB_EP_CFG_RESET); // EP1 Bulk IN.
|
||||
_usbd_disable_ep1();
|
||||
|
||||
usbd_otg->config_num = 0;
|
||||
usbd_otg->interface_num = 0;
|
||||
usbd_otg->configuration_set = false;
|
||||
usbd_otg->max_lun_set = false;
|
||||
}
|
||||
|
||||
void usbd_end(bool reset_ep, bool only_controller)
|
||||
{
|
||||
if (reset_ep)
|
||||
{
|
||||
usbd_flush_endpoint(USB_EP_ALL);
|
||||
_usbd_stall_reset_ep1(USB_DIR_OUT, USB_EP_CFG_RESET); // EP1 Bulk OUT.
|
||||
_usbd_stall_reset_ep1(USB_DIR_IN, USB_EP_CFG_RESET); // EP1 Bulk IN.
|
||||
|
||||
usbd_otg->config_num = 0;
|
||||
usbd_otg->interface_num = 0;
|
||||
usbd_otg->configuration_set = false;
|
||||
usbd_otg->max_lun_set = false;
|
||||
}
|
||||
_usb_reset_disable_ep1();
|
||||
|
||||
// Stop device controller.
|
||||
usbd_otg->regs->usbcmd &= ~USB2D_USBCMD_RUN;
|
||||
@@ -659,9 +664,11 @@ static void _usbd_mark_ep_complete(u32 endpoint)
|
||||
usb_dir_t direction = endpoint & 1;
|
||||
|
||||
usbd_flush_endpoint(endpoint);
|
||||
|
||||
memset((void *)&usbdaemon->dtds[endpoint * 4], 0, sizeof(dTD_t) * 4);
|
||||
memset((void *)&usbdaemon->qhs[endpoint], 0, sizeof(dQH_t));
|
||||
usbdaemon->ep_configured[endpoint] = 0;
|
||||
memset((void *)&usbdaemon->qhs[endpoint], 0, sizeof(dQH_t));
|
||||
|
||||
usbdaemon->ep_configured[endpoint] = 0;
|
||||
usbdaemon->ep_bytes_requested[endpoint] = 0;
|
||||
|
||||
if (direction == USB_DIR_IN)
|
||||
@@ -762,7 +769,7 @@ static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, u32 sync_time
|
||||
// Set buffers addresses to all page pointers.
|
||||
u32 dt_buffer_offset = dtd_idx * USB_TD_BUFFER_MAX_SIZE;
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
usbdaemon->dtds[dtd_ep_idx + dtd_idx].pages[i] =
|
||||
usbdaemon->dtds[dtd_ep_idx + dtd_idx].pages[i] = !buf ? 0 :
|
||||
(u32)&buf[dt_buffer_offset + (USB_TD_BUFFER_PAGE_SIZE * i)];
|
||||
|
||||
//usbdaemon->dtds[dtd_ep_idx + dtd_idx].pages[5] =
|
||||
@@ -785,13 +792,13 @@ static int _usbd_ep_operation(usb_ep_t endpoint, u8 *buf, u32 len, u32 sync_time
|
||||
AHB_GIZMO(AHB_AHB_MEM_PREFETCH_CFG1) |= MEM_PREFETCH_ENABLE;
|
||||
|
||||
if (direction == USB_DIR_IN)
|
||||
{
|
||||
prime_bit = USB2D_ENDPT_STATUS_TX_OFFSET << actual_ep;
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
|
||||
}
|
||||
else
|
||||
prime_bit = USB2D_ENDPT_STATUS_RX_OFFSET << actual_ep;
|
||||
|
||||
// Flush data before priming EP.
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLEAN_WAY, false);
|
||||
|
||||
// Prime endpoint.
|
||||
usbd_otg->regs->endptprime |= prime_bit; // USB2_CONTROLLER_USB2D_ENDPTPRIME.
|
||||
|
||||
@@ -825,8 +832,9 @@ out:
|
||||
else if (_usbd_get_ep_status(endpoint) != USB_EP_STATUS_IDLE)
|
||||
res = USB_ERROR_XFER_ERROR;
|
||||
|
||||
// Invalidate data after OP is done.
|
||||
if (direction == USB_DIR_OUT)
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, false);
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -840,9 +848,8 @@ static int _usbd_ep_ack(usb_ep_t ep)
|
||||
static void _usbd_set_ep0_stall()
|
||||
{
|
||||
// EP Control endpoints must be always stalled together.
|
||||
usbd_otg->regs->endptctrl[0] =
|
||||
USB2D_ENDPTCTRL_TX_EP_ENABLE | USB2D_ENDPTCTRL_TX_EP_STALL |
|
||||
USB2D_ENDPTCTRL_RX_EP_ENABLE | USB2D_ENDPTCTRL_RX_EP_STALL;
|
||||
usbd_otg->regs->endptctrl[0] = USB2D_ENDPTCTRL_TX_EP_ENABLE | USB2D_ENDPTCTRL_TX_EP_STALL |
|
||||
USB2D_ENDPTCTRL_RX_EP_ENABLE | USB2D_ENDPTCTRL_RX_EP_STALL;
|
||||
}
|
||||
|
||||
int usbd_set_ep_stall(u32 endpoint, int ep_stall)
|
||||
@@ -1046,6 +1053,16 @@ static int _usbd_handle_set_request(bool *ep_stall)
|
||||
if (!res)
|
||||
{
|
||||
usbd_otg->config_num = usbd_otg->control_setup.wValue;
|
||||
|
||||
// Remove configuration.
|
||||
if (!usbd_otg->config_num)
|
||||
{
|
||||
//! TODO: Signal that to userspace.
|
||||
_usb_reset_disable_ep1();
|
||||
return res;
|
||||
}
|
||||
|
||||
// Initialize configuration.
|
||||
_usbd_initialize_ep_ctrl(USB_EP_BULK_OUT);
|
||||
_usbd_initialize_ep_ctrl(USB_EP_BULK_IN);
|
||||
usbd_otg->configuration_set = true;
|
||||
@@ -1321,8 +1338,8 @@ static int _usbd_ep0_initialize()
|
||||
|
||||
// Clear all device addresses, enabled setup requests, transmit events and flush all endpoints.
|
||||
usbd_otg->regs->periodiclistbase = 0;
|
||||
usbd_otg->regs->endptsetupstat = usbd_otg->regs->endptsetupstat;
|
||||
usbd_otg->regs->endptcomplete = usbd_otg->regs->endptcomplete;
|
||||
usbd_otg->regs->endptsetupstat = usbd_otg->regs->endptsetupstat;
|
||||
usbd_otg->regs->endptcomplete = usbd_otg->regs->endptcomplete;
|
||||
usbd_flush_endpoint(USB_EP_ALL);
|
||||
}
|
||||
|
||||
@@ -1470,7 +1487,7 @@ int usb_device_ep1_out_reading_finish(u32 *pending_bytes, u32 sync_timeout)
|
||||
|
||||
*pending_bytes = _usbd_get_ep1_out_bytes_read();
|
||||
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, false);
|
||||
|
||||
if (ep_status == USB_EP_STATUS_IDLE)
|
||||
return USB_RES_OK;
|
||||
|
||||
235
bdk/usb/xusbd.c
235
bdk/usb/xusbd.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* eXtensible USB Device driver (XDCI) for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2020-2021 CTCaer
|
||||
* Copyright (c) 2020-2022 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,
|
||||
@@ -28,9 +28,9 @@
|
||||
#include <soc/clock.h>
|
||||
#include <soc/fuse.h>
|
||||
#include <soc/pmc.h>
|
||||
#include <soc/timer.h>
|
||||
#include <soc/t210.h>
|
||||
#include <utils/btn.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
#include <memory_map.h>
|
||||
|
||||
@@ -397,9 +397,9 @@ typedef struct _xusbd_event_queues_t
|
||||
{
|
||||
event_trb_t xusb_event_ring_seg0[XUSB_TRB_SLOTS];
|
||||
event_trb_t xusb_event_ring_seg1[XUSB_TRB_SLOTS];
|
||||
data_trb_t xusb_cntrl_event_queue[XUSB_TRB_SLOTS];
|
||||
data_trb_t xusb_bulkin_event_queue[XUSB_TRB_SLOTS];
|
||||
data_trb_t xusb_bulkout_event_queue[XUSB_TRB_SLOTS];
|
||||
data_trb_t xusb_cntrl_event_queue[XUSB_TRB_SLOTS];
|
||||
data_trb_t xusb_bulkin_event_queue[XUSB_TRB_SLOTS];
|
||||
data_trb_t xusb_bulkout_event_queue[XUSB_TRB_SLOTS];
|
||||
volatile xusb_ep_ctx_t xusb_ep_ctxt[4];
|
||||
} xusbd_event_queues_t;
|
||||
|
||||
@@ -676,8 +676,8 @@ static int _xusb_ep_init_context(u32 ep_idx)
|
||||
{
|
||||
case XUSB_EP_CTRL_IN:
|
||||
usbd_xotg->cntrl_producer_cycle = 1;
|
||||
usbd_xotg->cntrl_epenqueue_ptr = xusb_evtq->xusb_cntrl_event_queue;
|
||||
usbd_xotg->cntrl_epdequeue_ptr = xusb_evtq->xusb_cntrl_event_queue;
|
||||
usbd_xotg->cntrl_epenqueue_ptr = xusb_evtq->xusb_cntrl_event_queue;
|
||||
usbd_xotg->cntrl_epdequeue_ptr = xusb_evtq->xusb_cntrl_event_queue;
|
||||
|
||||
_xusb_ep_set_type_and_metrics(ep_idx, ep_ctxt);
|
||||
|
||||
@@ -685,16 +685,16 @@ static int _xusb_ep_init_context(u32 ep_idx)
|
||||
ep_ctxt->trd_dequeueptr_hi = 0;
|
||||
|
||||
link_trb = (link_trb_t *)&xusb_evtq->xusb_cntrl_event_queue[XUSB_LINK_TRB_IDX];
|
||||
link_trb->toggle_cycle = 1;
|
||||
link_trb->toggle_cycle = 1;
|
||||
link_trb->ring_seg_ptrlo = (u32)xusb_evtq->xusb_cntrl_event_queue >> 4;
|
||||
link_trb->ring_seg_ptrhi = 0;
|
||||
link_trb->trb_type = XUSB_TRB_LINK;
|
||||
link_trb->trb_type = XUSB_TRB_LINK;
|
||||
break;
|
||||
|
||||
case USB_EP_BULK_OUT:
|
||||
usbd_xotg->bulkout_producer_cycle = 1;
|
||||
usbd_xotg->bulkout_epenqueue_ptr = xusb_evtq->xusb_bulkout_event_queue;
|
||||
usbd_xotg->bulkout_epdequeue_ptr = xusb_evtq->xusb_bulkout_event_queue;
|
||||
usbd_xotg->bulkout_epenqueue_ptr = xusb_evtq->xusb_bulkout_event_queue;
|
||||
usbd_xotg->bulkout_epdequeue_ptr = xusb_evtq->xusb_bulkout_event_queue;
|
||||
|
||||
_xusb_ep_set_type_and_metrics(ep_idx, ep_ctxt);
|
||||
|
||||
@@ -702,16 +702,16 @@ static int _xusb_ep_init_context(u32 ep_idx)
|
||||
ep_ctxt->trd_dequeueptr_hi = 0;
|
||||
|
||||
link_trb = (link_trb_t *)&xusb_evtq->xusb_bulkout_event_queue[XUSB_LINK_TRB_IDX];
|
||||
link_trb->toggle_cycle = 1;
|
||||
link_trb->toggle_cycle = 1;
|
||||
link_trb->ring_seg_ptrlo = (u32)xusb_evtq->xusb_bulkout_event_queue >> 4;
|
||||
link_trb->ring_seg_ptrhi = 0;
|
||||
link_trb->trb_type = XUSB_TRB_LINK;
|
||||
link_trb->trb_type = XUSB_TRB_LINK;
|
||||
break;
|
||||
|
||||
case USB_EP_BULK_IN:
|
||||
usbd_xotg->bulkin_producer_cycle = 1;
|
||||
usbd_xotg->bulkin_epenqueue_ptr = xusb_evtq->xusb_bulkin_event_queue;
|
||||
usbd_xotg->bulkin_epdequeue_ptr = xusb_evtq->xusb_bulkin_event_queue;
|
||||
usbd_xotg->bulkin_epenqueue_ptr = xusb_evtq->xusb_bulkin_event_queue;
|
||||
usbd_xotg->bulkin_epdequeue_ptr = xusb_evtq->xusb_bulkin_event_queue;
|
||||
|
||||
_xusb_ep_set_type_and_metrics(ep_idx, ep_ctxt);
|
||||
|
||||
@@ -719,10 +719,10 @@ static int _xusb_ep_init_context(u32 ep_idx)
|
||||
ep_ctxt->trd_dequeueptr_hi = 0;
|
||||
|
||||
link_trb = (link_trb_t *)&xusb_evtq->xusb_bulkin_event_queue[XUSB_LINK_TRB_IDX];
|
||||
link_trb->toggle_cycle = 1;
|
||||
link_trb->toggle_cycle = 1;
|
||||
link_trb->ring_seg_ptrlo = (u32)xusb_evtq->xusb_bulkin_event_queue >> 4;
|
||||
link_trb->ring_seg_ptrhi = 0;
|
||||
link_trb->trb_type = XUSB_TRB_LINK;
|
||||
link_trb->trb_type = XUSB_TRB_LINK;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -744,7 +744,7 @@ static int _xusbd_ep_initialize(u32 ep_idx)
|
||||
if (!res)
|
||||
{
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_PAUSE) &= ~BIT(ep_idx);
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) &= ~BIT(ep_idx);
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) &= ~BIT(ep_idx);
|
||||
}
|
||||
return res;
|
||||
default:
|
||||
@@ -752,6 +752,48 @@ static int _xusbd_ep_initialize(u32 ep_idx)
|
||||
}
|
||||
}
|
||||
|
||||
static void _xusbd_ep1_disable(u32 ep_idx)
|
||||
{
|
||||
volatile xusb_ep_ctx_t *ep_ctxt = &xusb_evtq->xusb_ep_ctxt[ep_idx];
|
||||
u32 ep_mask = BIT(ep_idx);
|
||||
|
||||
switch (ep_idx)
|
||||
{
|
||||
case USB_EP_BULK_OUT:
|
||||
case USB_EP_BULK_IN:
|
||||
// Skip if already disabled.
|
||||
if (!ep_ctxt->ep_state)
|
||||
return;
|
||||
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) |= ep_mask;
|
||||
|
||||
// Set EP state to disabled.
|
||||
ep_ctxt->ep_state = EP_DISABLED;
|
||||
|
||||
// Wait for EP status to change.
|
||||
_xusb_xhci_mask_wait(XUSB_DEV_XHCI_EP_STCHG, ep_mask, ep_mask, 1000);
|
||||
|
||||
// Clear status change.
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_STCHG) = ep_mask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _xusb_disable_ep1()
|
||||
{
|
||||
_xusbd_ep1_disable(USB_EP_BULK_OUT);
|
||||
_xusbd_ep1_disable(USB_EP_BULK_IN);
|
||||
|
||||
// Device mode stop.
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_CTRL) &= ~XHCI_CTRL_RUN;
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_ST) |= XHCI_ST_RC;
|
||||
|
||||
usbd_xotg->config_num = 0;
|
||||
usbd_xotg->interface_num = 0;
|
||||
usbd_xotg->max_lun_set = false;
|
||||
usbd_xotg->device_state = XUSB_DEFAULT;
|
||||
}
|
||||
|
||||
static void _xusb_init_phy()
|
||||
{
|
||||
// Configure and enable PLLU.
|
||||
@@ -785,7 +827,7 @@ static void _xusb_init_phy()
|
||||
(void)XUSB_PADCTL(XUSB_PADCTL_USB2_OTG_PAD0_CTL_1); // Commit write.
|
||||
|
||||
// Enable USB2 tracking clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_Y_SET) = BIT(CLK_Y_USB2_TRK);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_Y_SET) = BIT(CLK_Y_USB2_TRK);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_USB2_HSIC_TRK) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_USB2_HSIC_TRK) & 0xFFFFFF00) | 6; // Set trank divisor to 4.
|
||||
|
||||
// Set tracking parameters and trigger it.
|
||||
@@ -841,11 +883,9 @@ static void _xusbd_init_device_clocks()
|
||||
|
||||
int xusb_device_init()
|
||||
{
|
||||
/////////////////////////////////////////////////
|
||||
// Disable USB2 device controller clocks.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_USBD);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_USBD);
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
|
||||
// Enable XUSB clock and clear Reset to XUSB Pad Control.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = BIT(CLK_W_XUSB);
|
||||
@@ -881,7 +921,7 @@ int xusb_device_init()
|
||||
_xusbd_init_device_clocks();
|
||||
|
||||
// Enable AHB redirect for access to IRAM for Event/EP ring buffers.
|
||||
mc_enable_ahb_redirect(false); // Can be skipped if IRAM is not used.
|
||||
mc_enable_ahb_redirect();
|
||||
|
||||
// Enable XUSB device IPFS.
|
||||
XUSB_DEV_DEV(XUSB_DEV_CONFIGURATION) |= DEV_CONFIGURATION_EN_FPCI;
|
||||
@@ -896,10 +936,10 @@ int xusb_device_init()
|
||||
|
||||
// AHB USB performance cfg.
|
||||
AHB_GIZMO(AHB_GIZMO_AHB_MEM) |= AHB_MEM_DONT_SPLIT_AHB_WR | AHB_MEM_ENB_FAST_REARBITRATE;
|
||||
AHB_GIZMO(AHB_GIZMO_USB3) |= AHB_GIZMO_IMMEDIATE;
|
||||
AHB_GIZMO(AHB_ARBITRATION_PRIORITY_CTRL) = PRIORITY_CTRL_WEIGHT(7) | PRIORITY_SELECT_USB3;
|
||||
AHB_GIZMO(AHB_AHB_MEM_PREFETCH_CFG1) =
|
||||
MEM_PREFETCH_ENABLE | MEM_PREFETCH_USB3_MST_ID | MEM_PREFETCH_ADDR_BNDRY(12) | 0x1000; // Addr boundary 64KB, Inactivity 4096 cycles.
|
||||
AHB_GIZMO(AHB_GIZMO_USB3) |= AHB_GIZMO_IMMEDIATE;
|
||||
AHB_GIZMO(AHB_ARBITRATION_PRIORITY_CTRL) = PRIORITY_CTRL_WEIGHT(7) | PRIORITY_SELECT_USB3;
|
||||
AHB_GIZMO(AHB_AHB_MEM_PREFETCH_CFG1) = MEM_PREFETCH_ENABLE | MEM_PREFETCH_USB3_MST_ID |
|
||||
MEM_PREFETCH_ADDR_BNDRY(12) | 0x1000; // Addr boundary 64KB, Inactivity 4096 cycles.
|
||||
|
||||
// Initialize context.
|
||||
usbd_xotg = &usbd_xotg_controller_ctxt;
|
||||
@@ -907,8 +947,8 @@ int xusb_device_init()
|
||||
|
||||
// Initialize event and EP rings.
|
||||
_xusbd_ep_init_event_ring();
|
||||
memset(xusb_evtq->xusb_cntrl_event_queue, 0, sizeof(xusb_evtq->xusb_cntrl_event_queue));
|
||||
memset(xusb_evtq->xusb_bulkin_event_queue, 0, sizeof(xusb_evtq->xusb_bulkin_event_queue));
|
||||
memset(xusb_evtq->xusb_cntrl_event_queue, 0, sizeof(xusb_evtq->xusb_cntrl_event_queue));
|
||||
memset(xusb_evtq->xusb_bulkin_event_queue, 0, sizeof(xusb_evtq->xusb_bulkin_event_queue));
|
||||
memset(xusb_evtq->xusb_bulkout_event_queue, 0, sizeof(xusb_evtq->xusb_bulkout_event_queue));
|
||||
|
||||
// Initialize Control EP.
|
||||
@@ -927,6 +967,44 @@ int xusb_device_init()
|
||||
return USB_RES_OK;
|
||||
}
|
||||
|
||||
//! TODO: Power down more stuff.
|
||||
static void _xusb_device_power_down()
|
||||
{
|
||||
// Disable clock for XUSB Super-Speed and set source to CLK_M.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB_SS);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_SS) &= 0x1FFFFF00;
|
||||
usleep(2);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_XUSB_SS);
|
||||
|
||||
// Put XUSB device into reset.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_SET) = BIT(CLK_U_XUSB_DEV);
|
||||
usleep(2);
|
||||
|
||||
// Reset Full-Speed clock source to CLK_M and div1.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_FS) = 0;
|
||||
usleep(2);
|
||||
|
||||
// Disable XUSB device clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_CLR) = BIT(CLK_U_XUSB_DEV);
|
||||
|
||||
// Force UTMIP_PLL power down.
|
||||
CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG1) &= (~BIT(15));
|
||||
CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) |= BIT(4) | BIT(0); // UTMIP_FORCE_PD_SAMP_A/C_POWERDOWN.
|
||||
|
||||
// Force enable UTMIPLL IDDQ.
|
||||
CLOCK(CLK_RST_CONTROLLER_UTMIPLL_HW_PWRDN_CFG0) |= 3;
|
||||
|
||||
// Disable PLLU.
|
||||
clock_disable_pllu();
|
||||
|
||||
// Set XUSB_PADCTL clock reset.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB_PADCTL);
|
||||
|
||||
// Disable XUSB clock.
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_XUSB);
|
||||
}
|
||||
|
||||
static int _xusb_queue_trb(u32 ep_idx, void *trb, bool ring_doorbell)
|
||||
{
|
||||
int res = USB_RES_OK;
|
||||
@@ -946,7 +1024,9 @@ static int _xusb_queue_trb(u32 ep_idx, void *trb, bool ring_doorbell)
|
||||
link_trb = (link_trb_t *)next_trb;
|
||||
link_trb->cycle = usbd_xotg->cntrl_producer_cycle & 1;
|
||||
link_trb->toggle_cycle = 1;
|
||||
|
||||
next_trb = (data_trb_t *)(link_trb->ring_seg_ptrlo << 4);
|
||||
|
||||
usbd_xotg->cntrl_producer_cycle ^= 1;
|
||||
}
|
||||
usbd_xotg->cntrl_epenqueue_ptr = next_trb;
|
||||
@@ -962,7 +1042,9 @@ static int _xusb_queue_trb(u32 ep_idx, void *trb, bool ring_doorbell)
|
||||
link_trb = (link_trb_t *)next_trb;
|
||||
link_trb->cycle = usbd_xotg->bulkout_producer_cycle & 1;
|
||||
link_trb->toggle_cycle = 1;
|
||||
|
||||
next_trb = (data_trb_t *)(link_trb->ring_seg_ptrlo << 4);
|
||||
|
||||
usbd_xotg->bulkout_producer_cycle ^= 1;
|
||||
}
|
||||
usbd_xotg->bulkout_epenqueue_ptr = next_trb;
|
||||
@@ -978,7 +1060,9 @@ static int _xusb_queue_trb(u32 ep_idx, void *trb, bool ring_doorbell)
|
||||
link_trb = (link_trb_t *)next_trb;
|
||||
link_trb->cycle = usbd_xotg->bulkin_producer_cycle & 1;
|
||||
link_trb->toggle_cycle = 1;
|
||||
|
||||
next_trb = (data_trb_t *)(link_trb->ring_seg_ptrlo << 4);
|
||||
|
||||
usbd_xotg->bulkin_producer_cycle ^= 1;
|
||||
}
|
||||
usbd_xotg->bulkin_epenqueue_ptr = next_trb;
|
||||
@@ -993,10 +1077,13 @@ static int _xusb_queue_trb(u32 ep_idx, void *trb, bool ring_doorbell)
|
||||
// Ring doorbell.
|
||||
if (ring_doorbell)
|
||||
{
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
|
||||
// Flush data before transfer.
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLEAN_WAY, false);
|
||||
|
||||
u32 target_id = (ep_idx << 8) & 0xFFFF;
|
||||
if (ep_idx == XUSB_EP_CTRL_IN)
|
||||
target_id |= usbd_xotg->ctrl_seq_num << 16;
|
||||
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_DB) = target_id;
|
||||
}
|
||||
|
||||
@@ -1005,10 +1092,10 @@ static int _xusb_queue_trb(u32 ep_idx, void *trb, bool ring_doorbell)
|
||||
|
||||
static void _xusb_create_status_trb(status_trb_t *trb, usb_dir_t direction)
|
||||
{
|
||||
trb->cycle = usbd_xotg->cntrl_producer_cycle & 1;
|
||||
trb->ioc = 1; // Enable interrupt on completion.
|
||||
trb->cycle = usbd_xotg->cntrl_producer_cycle & 1;
|
||||
trb->ioc = 1; // Enable interrupt on completion.
|
||||
trb->trb_type = XUSB_TRB_STATUS;
|
||||
trb->dir = direction;
|
||||
trb->dir = direction;
|
||||
}
|
||||
|
||||
static void _xusb_create_normal_trb(normal_trb_t *trb, u8 *buf, u32 len, usb_dir_t direction)
|
||||
@@ -1022,16 +1109,16 @@ static void _xusb_create_normal_trb(normal_trb_t *trb, u8 *buf, u32 len, usb_dir
|
||||
|
||||
// Single TRB transfer.
|
||||
trb->td_size = 0;
|
||||
trb->chain = 0;
|
||||
trb->chain = 0;
|
||||
|
||||
if (direction == USB_DIR_IN)
|
||||
producer_cycle = usbd_xotg->bulkin_producer_cycle & 1;
|
||||
else
|
||||
producer_cycle = usbd_xotg->bulkout_producer_cycle & 1;
|
||||
|
||||
trb->cycle = producer_cycle;
|
||||
trb->isp = 1; // Enable interrupt on short packet.
|
||||
trb->ioc = 1; // Enable interrupt on completion.
|
||||
trb->cycle = producer_cycle;
|
||||
trb->isp = 1; // Enable interrupt on short packet.
|
||||
trb->ioc = 1; // Enable interrupt on completion.
|
||||
trb->trb_type = XUSB_TRB_NORMAL;
|
||||
}
|
||||
|
||||
@@ -1044,13 +1131,13 @@ static void _xusb_create_data_trb(data_trb_t *trb, u8 *buf, u32 len, usb_dir_t d
|
||||
|
||||
// Single TRB transfer.
|
||||
trb->td_size = 0;
|
||||
trb->chain = 0;
|
||||
trb->chain = 0;
|
||||
|
||||
trb->cycle = usbd_xotg->cntrl_producer_cycle & 1;
|
||||
trb->isp = 1; // Enable interrupt on short packet.
|
||||
trb->ioc = 1; // Enable interrupt on completion.
|
||||
trb->cycle = usbd_xotg->cntrl_producer_cycle & 1;
|
||||
trb->isp = 1; // Enable interrupt on short packet.
|
||||
trb->ioc = 1; // Enable interrupt on completion.
|
||||
trb->trb_type = XUSB_TRB_DATA;
|
||||
trb->dir = direction;
|
||||
trb->dir = direction;
|
||||
}
|
||||
|
||||
static int _xusb_issue_status_trb(usb_dir_t direction)
|
||||
@@ -1061,6 +1148,7 @@ static int _xusb_issue_status_trb(usb_dir_t direction)
|
||||
if (usbd_xotg->cntrl_epenqueue_ptr == usbd_xotg->cntrl_epdequeue_ptr || direction == USB_DIR_OUT)
|
||||
{
|
||||
_xusb_create_status_trb(&trb, direction);
|
||||
|
||||
res = _xusb_queue_trb(XUSB_EP_CTRL_IN, &trb, EP_RING_DOORBELL);
|
||||
usbd_xotg->wait_for_event_trb = XUSB_TRB_STATUS;
|
||||
}
|
||||
@@ -1076,6 +1164,7 @@ static int _xusb_issue_normal_trb(u8 *buf, u32 len, usb_dir_t direction)
|
||||
u32 ep_idx = USB_EP_BULK_IN;
|
||||
if (direction == USB_DIR_OUT)
|
||||
ep_idx = USB_EP_BULK_OUT;
|
||||
|
||||
int res = _xusb_queue_trb(ep_idx, &trb, EP_RING_DOORBELL);
|
||||
if (!res)
|
||||
usbd_xotg->wait_for_event_trb = XUSB_TRB_NORMAL;
|
||||
@@ -1091,6 +1180,7 @@ static int _xusb_issue_data_trb(u8 *buf, u32 len, usb_dir_t direction)
|
||||
if (usbd_xotg->cntrl_epenqueue_ptr == usbd_xotg->cntrl_epdequeue_ptr)
|
||||
{
|
||||
_xusb_create_data_trb(&trb, buf, len, direction);
|
||||
|
||||
res = _xusb_queue_trb(XUSB_EP_CTRL_IN, &trb, EP_RING_DOORBELL);
|
||||
if (!res)
|
||||
usbd_xotg->wait_for_event_trb = XUSB_TRB_DATA;
|
||||
@@ -1360,8 +1450,8 @@ static int _xusb_handle_get_ep_status(u32 ep_idx)
|
||||
u32 ep_mask = BIT(ep_idx);
|
||||
static u8 xusb_ep_status_descriptor[2] = {0};
|
||||
|
||||
xusb_ep_status_descriptor[0] =
|
||||
(XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) & ep_mask) ? USB_STATUS_EP_HALTED : USB_STATUS_EP_OK;
|
||||
xusb_ep_status_descriptor[0] = (XUSB_DEV_XHCI(XUSB_DEV_XHCI_EP_HALT) & ep_mask) ? USB_STATUS_EP_HALTED : USB_STATUS_EP_OK;
|
||||
|
||||
return _xusb_issue_data_trb(xusb_ep_status_descriptor, 2, USB_DIR_IN);
|
||||
}
|
||||
|
||||
@@ -1383,6 +1473,7 @@ static int _xusb_handle_get_class_request(usb_ctrl_setup_t *ctrl_setup)
|
||||
case USB_REQUEST_BULK_RESET:
|
||||
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)
|
||||
goto stall;
|
||||
@@ -1538,9 +1629,18 @@ static void _xusb_handle_set_request_dev_address(usb_ctrl_setup_t *ctrl_setup)
|
||||
|
||||
static void _xusb_handle_set_request_configuration(usb_ctrl_setup_t *ctrl_setup)
|
||||
{
|
||||
u32 config_num = ctrl_setup->wValue;
|
||||
if (!config_num) //TODO! we can change device_state here.
|
||||
usbd_xotg->config_num = ctrl_setup->wValue;
|
||||
|
||||
// Remove configuration.
|
||||
if (!usbd_xotg->config_num)
|
||||
{
|
||||
//! TODO: Signal that to userspace.
|
||||
_xusb_disable_ep1();
|
||||
|
||||
_xusb_issue_status_trb(USB_DIR_IN);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize BULK EPs.
|
||||
_xusbd_ep_initialize(USB_EP_BULK_OUT);
|
||||
@@ -1551,8 +1651,6 @@ static void _xusb_handle_set_request_configuration(usb_ctrl_setup_t *ctrl_setup)
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_ST) |= XHCI_ST_RC;
|
||||
|
||||
_xusb_issue_status_trb(USB_DIR_IN);
|
||||
|
||||
usbd_xotg->config_num = config_num;
|
||||
usbd_xotg->device_state = XUSB_CONFIGURED_STS_WAIT;
|
||||
}
|
||||
|
||||
@@ -1862,7 +1960,7 @@ int xusb_device_enumerate(usb_gadget_type gadget)
|
||||
|
||||
// Enable overrides for VBUS and ID.
|
||||
XUSB_PADCTL(XUSB_PADCTL_USB2_VBUS_ID) = (XUSB_PADCTL(XUSB_PADCTL_USB2_VBUS_ID) & ~(PADCTL_USB2_VBUS_ID_VBUS_OVR_MASK | PADCTL_USB2_VBUS_ID_SRC_MASK)) |
|
||||
PADCTL_USB2_VBUS_ID_VBUS_OVR_EN | PADCTL_USB2_VBUS_ID_SRC_ID_OVR_EN;
|
||||
PADCTL_USB2_VBUS_ID_VBUS_OVR_EN | PADCTL_USB2_VBUS_ID_SRC_ID_OVR_EN;
|
||||
|
||||
// Clear halt for LTSSM.
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTHALT) &= ~XHCI_PORTHALT_HALT_LTSSM;
|
||||
@@ -1873,16 +1971,15 @@ int xusb_device_enumerate(usb_gadget_type gadget)
|
||||
// Override access to High/Full Speed.
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_CFG_DEV_FE) = (XUSB_DEV_XHCI(XUSB_DEV_XHCI_CFG_DEV_FE) & ~XHCI_CFG_DEV_FE_PORTREGSEL_MASK) | XHCI_CFG_DEV_FE_PORTREGSEL_HSFS;
|
||||
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) =
|
||||
(XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) & ~XHCI_PORTSC_PLS_MASK) | XHCI_PORTSC_LWS | XHCI_PORTSC_PLS_RXDETECT;
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) = (XUSB_DEV_XHCI(XUSB_DEV_XHCI_PORTSC) & ~XHCI_PORTSC_PLS_MASK) | XHCI_PORTSC_LWS | XHCI_PORTSC_PLS_RXDETECT;
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_CFG_DEV_FE) &= ~XHCI_CFG_DEV_FE_PORTREGSEL_MASK;
|
||||
|
||||
// Enable VBUS and set ID to Float.
|
||||
XUSB_PADCTL(XUSB_PADCTL_USB2_VBUS_ID) = (XUSB_PADCTL(XUSB_PADCTL_USB2_VBUS_ID) & ~PADCTL_USB2_VBUS_ID_OVR_MASK) |
|
||||
PADCTL_USB2_VBUS_ID_OVR_FLOAT | PADCTL_USB2_VBUS_ID_VBUS_ON;
|
||||
PADCTL_USB2_VBUS_ID_OVR_FLOAT | PADCTL_USB2_VBUS_ID_VBUS_ON;
|
||||
|
||||
usbd_xotg->wait_for_event_trb = XUSB_TRB_SETUP;
|
||||
usbd_xotg->device_state = XUSB_DEFAULT;
|
||||
usbd_xotg->device_state = XUSB_DEFAULT;
|
||||
|
||||
// Timeout if cable or communication isn't started in 1.5 minutes.
|
||||
u32 timer = get_tmr_ms() + 90000;
|
||||
@@ -1902,17 +1999,16 @@ int xusb_device_enumerate(usb_gadget_type gadget)
|
||||
return USB_RES_OK;
|
||||
}
|
||||
|
||||
//! TODO: Do a full deinit.
|
||||
void xusb_end(bool reset_ep, bool only_controller)
|
||||
{
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB_SS);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_XUSB_SS);
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_SET) = BIT(CLK_U_XUSB_DEV);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_CLR) = BIT(CLK_U_XUSB_DEV);
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB_PADCTL);
|
||||
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_XUSB);
|
||||
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB);
|
||||
mc_disable_ahb_redirect(); // Can be skipped if IRAM is not used.
|
||||
// Disable endpoints and stop device mode operation.
|
||||
_xusb_disable_ep1();
|
||||
|
||||
// Disable device mode.
|
||||
XUSB_DEV_XHCI(XUSB_DEV_XHCI_CTRL) = 0;
|
||||
|
||||
//! TODO: Add only controller support?
|
||||
_xusb_device_power_down();
|
||||
}
|
||||
|
||||
int xusb_handle_ep0_ctrl_setup()
|
||||
@@ -1938,6 +2034,7 @@ int xusb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, u32 sync_tries)
|
||||
int res = USB_RES_OK;
|
||||
usbd_xotg->tx_count[USB_DIR_OUT] = 0;
|
||||
usbd_xotg->tx_bytes[USB_DIR_OUT] = len;
|
||||
|
||||
_xusb_issue_normal_trb(buf, len, USB_DIR_OUT);
|
||||
usbd_xotg->tx_count[USB_DIR_OUT]++;
|
||||
|
||||
@@ -1948,10 +2045,11 @@ int xusb_device_ep1_out_read(u8 *buf, u32 len, u32 *bytes_read, u32 sync_tries)
|
||||
|
||||
if (bytes_read)
|
||||
*bytes_read = res ? 0 : usbd_xotg->tx_bytes[USB_DIR_OUT];
|
||||
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
|
||||
}
|
||||
|
||||
// Invalidate data after transfer.
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, false);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1989,7 +2087,8 @@ int xusb_device_ep1_out_reading_finish(u32 *pending_bytes, u32 sync_tries)
|
||||
if (pending_bytes)
|
||||
*pending_bytes = res ? 0 : usbd_xotg->tx_bytes[USB_DIR_OUT];
|
||||
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
|
||||
// Invalidate data after transfer.
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, false);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -1999,11 +2098,13 @@ int xusb_device_ep1_in_write(u8 *buf, u32 len, u32 *bytes_written, u32 sync_trie
|
||||
if (len > USB_EP_BUFFER_MAX_SIZE)
|
||||
len = USB_EP_BUFFER_MAX_SIZE;
|
||||
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
|
||||
// Flush data before transfer.
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLEAN_WAY, false);
|
||||
|
||||
int res = USB_RES_OK;
|
||||
usbd_xotg->tx_count[USB_DIR_IN] = 0;
|
||||
usbd_xotg->tx_bytes[USB_DIR_IN] = len;
|
||||
|
||||
_xusb_issue_normal_trb(buf, len, USB_DIR_IN);
|
||||
usbd_xotg->tx_count[USB_DIR_IN]++;
|
||||
|
||||
@@ -2053,7 +2154,7 @@ bool xusb_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;
|
||||
|
||||
usbd_xotg->max_lun = max_lun;
|
||||
usbd_xotg->max_lun = max_lun;
|
||||
usbd_xotg->max_lun_set = true;
|
||||
|
||||
// Wait for request and transfer start.
|
||||
|
||||
Reference in New Issue
Block a user