update bdk

Signed-off-by: Damien Zhao <zdm65477730@126.com>
This commit is contained in:
Damien Zhao
2022-11-08 22:29:07 +08:00
parent 049845227d
commit f1db80024c
76 changed files with 2567 additions and 1831 deletions

View File

@@ -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-2020 CTCaer
* Copyright (c) 2019-2021 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,
@@ -109,7 +109,7 @@
#define SS_WRITE_ERROR 0x30C02
#define SS_WRITE_PROTECTED 0x72700
#define SK(x) ((u8) ((x) >> 16)) /* Sense Key byte, etc. */
#define SK(x) ((u8) ((x) >> 16)) // Sense Key byte, etc.
#define ASC(x) ((u8) ((x) >> 8))
#define ASCQ(x) ((u8) (x))
@@ -203,7 +203,7 @@ typedef struct _bulk_ctxt_t {
typedef struct _usbd_gadget_ums_t {
bulk_ctxt_t bulk_ctxt;
int cmnd_size;
u32 cmnd_size;
u8 cmnd[SCSI_MAX_CMD_SZ];
u32 lun_idx; // lun index
@@ -217,6 +217,7 @@ typedef struct _usbd_gadget_ums_t {
u32 tag;
u32 residue;
u32 usb_amount_left;
bool cbw_req_queued;
u32 phase_error;
u32 short_packet_received;
@@ -368,12 +369,12 @@ static void _ums_transfer_out_big_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk
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)
static void _ums_transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt, u32 ep, u32 sync_timeout)
{
if (ep == bulk_ctxt->bulk_in)
{
bulk_ctxt->bulk_in_status = usb_ops.usb_device_ep1_in_writing_finish(
&bulk_ctxt->bulk_in_length_actual);
&bulk_ctxt->bulk_in_length_actual, sync_timeout);
if (bulk_ctxt->bulk_in_status == USB_ERROR_XFER_ERROR)
{
@@ -386,7 +387,7 @@ static void _ums_transfer_finish(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt,
else
{
bulk_ctxt->bulk_out_status = usb_ops.usb_device_ep1_out_reading_finish(
&bulk_ctxt->bulk_out_length_actual);
&bulk_ctxt->bulk_out_length_actual, sync_timeout);
if (bulk_ctxt->bulk_out_status == USB_ERROR_XFER_ERROR)
{
@@ -460,6 +461,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->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return UMS_RES_INVALID_ARG;
@@ -497,7 +499,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);
_ums_transfer_finish(ums, bulk_ctxt, bulk_ctxt->bulk_in, USB_XFER_SYNCED);
lba_offset += amount;
amount_left -= amount;
@@ -548,6 +550,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->lun.sense_data = SS_WRITE_PROTECTED;
return UMS_RES_INVALID_ARG;
@@ -571,34 +574,33 @@ 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->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return UMS_RES_INVALID_ARG;
}
/* Carry out the file writes */
// Carry out the file writes.
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)
{
/* Queue a request for more data from the host */
if (amount_left_to_req)
// Queue a request for more data from the host.
if (amount_left_to_req > 0)
{
// Limit write to max supported read from EP OUT.
amount = MIN(amount_left_to_req, UMS_EP_OUT_MAX_XFER);
if (usb_lba_offset >= ums->lun.num_sectors) //////////Check if it works with concurrency
if (usb_lba_offset >= ums->lun.num_sectors)
{
ums->set_text(ums->label, "#FFDD00 Error:# Write - Past last sector!");
amount_left_to_req = 0;
ums->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
ums->lun.sense_data_info = usb_lba_offset;
ums->lun.info_valid = 1;
continue;
break;
}
// Get the next buffer.
@@ -640,12 +642,12 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
*/
amount = MIN(amount, bulk_ctxt->bulk_out_length);
/* Don't write a partial block */
// Don't write a partial block.
amount -= (amount & 511);
if (amount == 0)
goto empty_write;
/* Perform the write */
// Perform the write.
if (!sdmmc_storage_write(ums->lun.storage, ums->lun.offset + lba_offset,
amount >> UMS_DISK_LBA_SHIFT, (u8 *)bulk_ctxt->bulk_out_buf))
amount = 0;
@@ -656,7 +658,7 @@ DPRINTF("file write %X @ %X\n", amount, lba_offset);
amount_left_to_write -= amount;
ums->residue -= amount;
/* If an error occurred, report it and its position */
// If an error occurred, report it and its position.
if (!amount)
{
ums->set_text(ums->label, "#FFDD00 Error:# SDMMC Write!");
@@ -686,6 +688,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->lun.sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return UMS_RES_INVALID_ARG;
@@ -1007,7 +1010,7 @@ static int _scsi_mode_sense(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
return UMS_RES_INVALID_ARG;
}
/* Store the mode data length */
// Store the mode data length.
if (ums->cmnd[0] == SC_MODE_SENSE_6)
buf0[0] = len - 1;
else
@@ -1089,8 +1092,7 @@ static int _scsi_prevent_allow_removal(usbd_gadget_ums_t *ums)
// Notify for possible unmounting?
// Normally we sync here but we do synced writes to SDMMC.
if (ums->lun.prevent_medium_removal && !prevent)
;
if (ums->lun.prevent_medium_removal && !prevent) { /* Do nothing */ }
ums->lun.prevent_medium_removal = prevent;
@@ -1114,7 +1116,7 @@ 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, int cmnd_size,
static int _ums_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'};
@@ -1540,12 +1542,12 @@ static int finish_reply(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? */
// Was this a real packet? Should it be ignored?
if (bulk_ctxt->bulk_out_status || bulk_ctxt->bulk_out_ignore || ums->lun.unmounted)
{
if (bulk_ctxt->bulk_out_status || ums->lun.unmounted)
{
DPRINTF("USB: EP timeout\n");
DPRINTF("USB: EP timeout (%d)\n", bulk_ctxt->bulk_out_status);
// In case we disconnected, exit UMS.
// Raise timeout if removable and didn't got a unit ready command inside 4s.
if (bulk_ctxt->bulk_out_status == USB2_ERROR_XFER_EP_DISABLED ||
@@ -1576,6 +1578,8 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
{
ums->set_text(ums->label, "#C7EA46 Status:# Medium unmounted");
ums->timeouts++;
if (!bulk_ctxt->bulk_out_status)
ums->timeouts += 3;
}
if (ums->timeouts > 20)
@@ -1586,29 +1590,34 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
return UMS_RES_INVALID_ARG;
}
/* Is the CBW valid? */
// Clear request flag to allow a new one to be queued.
ums->cbw_req_queued = false;
// Is the CBW valid?
bulk_recv_pkt_t *cbw = (bulk_recv_pkt_t *)bulk_ctxt->bulk_out_buf;
if (bulk_ctxt->bulk_out_length_actual != USB_BULK_CB_WRAP_LEN || cbw->Signature != USB_BULK_CB_SIG)
{
gfx_printf("USB: invalid CBW: len %X sig 0x%X\n", bulk_ctxt->bulk_out_length_actual, cbw->Signature);
// The Bulk-only spec says we MUST stall the IN endpoint
// (6.6.1), so it's unavoidable. It also says we must
// retain this state until the next reset, but there's
// no way to tell the controller driver it should ignore
// Clear-Feature(HALT) requests.
//
// We aren't required to halt the OUT endpoint; instead
// we can simply accept and discard any data received
// until the next reset.
/*
* The Bulk-only spec says we MUST stall the IN endpoint
* (6.6.1), so it's unavoidable. It also says we must
* retain this state until the next reset, but there's
* no way to tell the controller driver it should ignore
* Clear-Feature(HALT) requests.
*
* We aren't required to halt the OUT endpoint; instead
* we can simply accept and discard any data received
* until the next reset.
*/
ums_wedge_bulk_in_endpoint(ums);
bulk_ctxt->bulk_out_ignore = 1;
return UMS_RES_INVALID_ARG;
}
/* Is the CBW meaningful? */
// Is the CBW meaningful?
if (cbw->Lun >= UMS_MAX_LUN || cbw->Flags & ~USB_BULK_IN_FLAG ||
cbw->Length <= 0 || cbw->Length > SCSI_MAX_CMD_SZ)
cbw->Length == 0 || cbw->Length > SCSI_MAX_CMD_SZ)
{
gfx_printf("USB: non-meaningful CBW: lun = %X, flags = 0x%X, cmdlen %X\n",
cbw->Lun, cbw->Flags, cbw->Length);
@@ -1625,7 +1634,7 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
return UMS_RES_INVALID_ARG;
}
/* Save the command for later */
// Save the command for later.
ums->cmnd_size = cbw->Length;
memcpy(ums->cmnd, cbw->CDB, ums->cmnd_size);
@@ -1660,8 +1669,20 @@ static int get_next_command(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
bulk_ctxt->bulk_out_length = USB_BULK_CB_WRAP_LEN;
/* Queue a request to read a Bulk-only CBW */
_ums_transfer_start(ums, bulk_ctxt, bulk_ctxt->bulk_out, USB_XFER_SYNCED_CMD);
// 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);
else
_ums_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.
* This avoids an issue with some XHCI controllers and OS combos (e.g. ASMedia and Linux/Mac OS)
* which confuse that and concatenate an old CBW request with another write request (SCSI Write)
* and create a babble error (transmit overflow).
*/
if (ums->xusb)
ums->cbw_req_queued = true;
/* We will drain the buffer in software, which means we
* can reuse it for the next filling. No need to advance
@@ -1698,7 +1719,7 @@ static void send_status(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
SK(sd), ASC(sd), ASCQ(sd), ums->lun.sense_data_info);
}
/* Store and send the Bulk-only CSW */
// Store and send the Bulk-only CSW.
bulk_send_pkt_t *csw = (bulk_send_pkt_t *)bulk_ctxt->bulk_in_buf;
csw->Signature = USB_BULK_CS_SIG;
@@ -1714,7 +1735,7 @@ 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 */
// Clear out the controller's fifos.
ums_flush_endpoint(bulk_ctxt->bulk_in);
ums_flush_endpoint(bulk_ctxt->bulk_out);
@@ -1737,7 +1758,7 @@ static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
ums->state = UMS_STATE_NORMAL;
/* Carry out any extra actions required for the exception */
// Carry out any extra actions required for the exception.
switch (old_state)
{
case UMS_STATE_NORMAL:
@@ -1759,7 +1780,7 @@ static void handle_exception(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
break;
case UMS_STATE_EXIT:
ums->state = UMS_STATE_TERMINATED; /* Stop the thread */
ums->state = UMS_STATE_TERMINATED; // Stop the thread.
break;
default:
@@ -1837,6 +1858,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
// Initialize sdmmc.
if (usbs->type == MMC_SD)
{
sd_end();
sd_mount();
sd_unmount();
ums.lun.sdmmc = &sd_sdmmc;
@@ -1907,7 +1929,10 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
send_status(&ums, &ums.bulk_ctxt);
} while (ums.state != UMS_STATE_TERMINATED);
ums.set_text(ums.label, "#C7EA46 Status:# Disk ejected");
if (ums.lun.prevent_medium_removal)
ums.set_text(ums.label, "#FFDD00 Error:# Disk unsafely ejected");
else
ums.set_text(ums.label, "#C7EA46 Status:# Disk ejected");
goto exit;
error: