summaryrefslogtreecommitdiff
path: root/common/usbx_device_classes
diff options
context:
space:
mode:
authorScott Larson <[email protected]>2021-01-07 16:53:02 -0800
committerScott Larson <[email protected]>2021-01-07 16:53:02 -0800
commit9823f3857d7eb54c8416d9eab316aab0257130f9 (patch)
tree65690334fd54075e35169ff3d34040c66ba0dbe2 /common/usbx_device_classes
parentd8014ecb428bb2d5cf50cba68dd8e7022ee35171 (diff)
update to v6.1.3v6.1.3_rel
Diffstat (limited to 'common/usbx_device_classes')
-rw-r--r--common/usbx_device_classes/inc/ux_device_class_hid.h17
-rw-r--r--common/usbx_device_classes/inc/ux_device_class_storage.h10
-rw-r--r--common/usbx_device_classes/src/ux_device_class_hid_activate.c9
-rw-r--r--common/usbx_device_classes/src/ux_device_class_hid_control_request.c16
-rw-r--r--common/usbx_device_classes/src/ux_device_class_storage_control_request.c25
-rw-r--r--common/usbx_device_classes/src/ux_device_class_storage_csw_send.c8
-rw-r--r--common/usbx_device_classes/src/ux_device_class_storage_inquiry.c48
-rw-r--r--common/usbx_device_classes/src/ux_device_class_storage_mode_select.c11
-rw-r--r--common/usbx_device_classes/src/ux_device_class_storage_read.c50
-rw-r--r--common/usbx_device_classes/src/ux_device_class_storage_report_key.c7
-rw-r--r--common/usbx_device_classes/src/ux_device_class_storage_request_sense.c30
-rw-r--r--common/usbx_device_classes/src/ux_device_class_storage_test_ready.c14
-rw-r--r--common/usbx_device_classes/src/ux_device_class_storage_thread.c70
-rw-r--r--common/usbx_device_classes/src/ux_device_class_storage_write.c43
14 files changed, 284 insertions, 74 deletions
diff --git a/common/usbx_device_classes/inc/ux_device_class_hid.h b/common/usbx_device_classes/inc/ux_device_class_hid.h
index 05e3833..fc86bdd 100644
--- a/common/usbx_device_classes/inc/ux_device_class_hid.h
+++ b/common/usbx_device_classes/inc/ux_device_class_hid.h
@@ -26,7 +26,7 @@
/* COMPONENT DEFINITION RELEASE */
/* */
/* ux_device_class_hid.h PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Chaoqiong Xiao, Microsoft Corporation */
@@ -46,6 +46,10 @@
/* TX symbols instead of using */
/* them directly, */
/* resulting in version 6.1 */
+/* 12-31-2020 Chaoqiong Xiao Modified comment(s), */
+/* added Get/Set Protocol */
+/* request support, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
@@ -79,6 +83,11 @@
#define UX_DEVICE_CLASS_HID_REPORT_TYPE_OUTPUT 0x2
#define UX_DEVICE_CLASS_HID_REPORT_TYPE_FEATURE 0x3
+/* Define HID Protocols. */
+
+#define UX_DEVICE_CLASS_HID_PROTOCOL_BOOT 0
+#define UX_DEVICE_CLASS_HID_PROTOCOL_REPORT 1
+
/* Define HID event info structure. */
#ifndef UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH
@@ -130,6 +139,7 @@ typedef struct UX_SLAVE_CLASS_HID_STRUCT
UX_EVENT_FLAGS_GROUP ux_device_class_hid_event_flags_group;
ULONG ux_device_class_hid_event_idle_rate;
ULONG ux_device_class_hid_event_wait_timeout;
+ ULONG ux_device_class_hid_protocol;
UX_SLAVE_CLASS_HID_EVENT *ux_device_class_hid_event_array;
UX_SLAVE_CLASS_HID_EVENT *ux_device_class_hid_event_array_head;
UX_SLAVE_CLASS_HID_EVENT *ux_device_class_hid_event_array_tail;
@@ -171,8 +181,7 @@ UINT _ux_device_class_hid_report_set(UX_SLAVE_CLASS_HID *hid, ULONG descriptor_
ULONG request_index, ULONG host_length);
UINT _ux_device_class_hid_report_get(UX_SLAVE_CLASS_HID *hid, ULONG descriptor_type,
ULONG request_index, ULONG host_length);
-
-
+
/* Define Device HID Class API prototypes. */
#define ux_device_class_hid_entry _ux_device_class_hid_entry
@@ -181,5 +190,7 @@ UINT _ux_device_class_hid_report_get(UX_SLAVE_CLASS_HID *hid, ULONG descriptor_
#define ux_device_class_hid_report_set _ux_device_class_hid_report_set
#define ux_device_class_hid_report_get _ux_device_class_hid_report_get
+#define ux_device_class_hid_protocol_get(hid) (hid -> ux_device_class_hid_protocol)
+
#endif
diff --git a/common/usbx_device_classes/inc/ux_device_class_storage.h b/common/usbx_device_classes/inc/ux_device_class_storage.h
index e658da8..c55bbec 100644
--- a/common/usbx_device_classes/inc/ux_device_class_storage.h
+++ b/common/usbx_device_classes/inc/ux_device_class_storage.h
@@ -26,7 +26,7 @@
/* COMPONENT DEFINITION RELEASE */
/* */
/* ux_device_class_storage.h PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Chaoqiong Xiao, Microsoft Corporation */
@@ -44,6 +44,9 @@
/* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
/* optimized command logic, */
/* resulting in version 6.1 */
+/* 12-31-2020 Chaoqiong Xiao Modified comment(s), */
+/* fixed USB CV test issues, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
@@ -450,6 +453,11 @@ typedef struct UX_SLAVE_CLASS_STORAGE_STRUCT
UX_SLAVE_INTERFACE *ux_slave_class_storage_interface;
ULONG ux_slave_class_storage_number_lun;
UX_SLAVE_CLASS_STORAGE_LUN ux_slave_class_storage_lun[UX_MAX_SLAVE_LUN];
+ ULONG ux_slave_class_storage_host_length;
+ UCHAR ux_slave_class_storage_cbw_flags;
+ UCHAR ux_slave_class_storage_cbw_lun;
+ UCHAR ux_slave_class_storage_reserved[2];
+ ULONG ux_slave_class_storage_csw_residue;
ULONG ux_slave_class_storage_csw_status;
VOID (*ux_slave_class_storage_instance_activate)(VOID *);
VOID (*ux_slave_class_storage_instance_deactivate)(VOID *);
diff --git a/common/usbx_device_classes/src/ux_device_class_hid_activate.c b/common/usbx_device_classes/src/ux_device_class_hid_activate.c
index 749b7de..0d3b12c 100644
--- a/common/usbx_device_classes/src/ux_device_class_hid_activate.c
+++ b/common/usbx_device_classes/src/ux_device_class_hid_activate.c
@@ -33,7 +33,7 @@
/* FUNCTION RELEASE */
/* */
/* _ux_device_class_hid_activate PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Chaoqiong Xiao, Microsoft Corporation */
@@ -65,6 +65,10 @@
/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
/* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
/* resulting in version 6.1 */
+/* 12-31-2020 Chaoqiong Xiao Modified comment(s), */
+/* added Get/Set Protocol */
+/* request support, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _ux_device_class_hid_activate(UX_SLAVE_CLASS_COMMAND *command)
@@ -113,6 +117,9 @@ UX_SLAVE_ENDPOINT *endpoint_interrupt;
if (endpoint_interrupt == UX_NULL)
return (UX_ERROR);
+ /* Default HID protocol is report protocol. */
+ hid -> ux_device_class_hid_protocol = UX_DEVICE_CLASS_HID_PROTOCOL_REPORT;
+
/* Save the endpoint in the hid instance. */
hid -> ux_device_class_hid_interrupt_endpoint = endpoint_interrupt;
diff --git a/common/usbx_device_classes/src/ux_device_class_hid_control_request.c b/common/usbx_device_classes/src/ux_device_class_hid_control_request.c
index a2a58b5..f5c9d10 100644
--- a/common/usbx_device_classes/src/ux_device_class_hid_control_request.c
+++ b/common/usbx_device_classes/src/ux_device_class_hid_control_request.c
@@ -34,7 +34,7 @@
/* FUNCTION RELEASE */
/* */
/* _ux_device_class_hid_control_request PORTABLE C */
-/* 6.1.2 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Chaoqiong Xiao, Microsoft Corporation */
@@ -77,6 +77,10 @@
/* 11-09-2020 Chaoqiong Xiao Modified comment(s), */
/* fixed compile warnings 64b, */
/* resulting in version 6.1.2 */
+/* 12-31-2020 Chaoqiong Xiao Modified comment(s), */
+/* added Get/Set Protocol */
+/* request support, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _ux_device_class_hid_control_request(UX_SLAVE_CLASS_COMMAND *command)
@@ -183,9 +187,17 @@ UX_SLAVE_CLASS_HID *hid;
break;
case UX_DEVICE_CLASS_HID_COMMAND_GET_PROTOCOL:
+
+ /* Send the protocol. */
+ *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR)hid -> ux_device_class_hid_protocol;
+ _ux_device_stack_transfer_request(transfer_request, 1, request_length);
+ break;
+
case UX_DEVICE_CLASS_HID_COMMAND_SET_PROTOCOL:
- /* Not supported now. */
+ /* Accept the protocol. */
+ hid -> ux_device_class_hid_protocol = request_value;
+ break;
default:
diff --git a/common/usbx_device_classes/src/ux_device_class_storage_control_request.c b/common/usbx_device_classes/src/ux_device_class_storage_control_request.c
index bd9925d..aec7681 100644
--- a/common/usbx_device_classes/src/ux_device_class_storage_control_request.c
+++ b/common/usbx_device_classes/src/ux_device_class_storage_control_request.c
@@ -35,7 +35,7 @@
/* FUNCTION RELEASE */
/* */
/* _ux_device_class_storage_control_request PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Chaoqiong Xiao, Microsoft Corporation */
@@ -70,6 +70,9 @@
/* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
/* optimized command logic, */
/* resulting in version 6.1 */
+/* 12-31-2020 Chaoqiong Xiao Modified comment(s), */
+/* fixed USB CV test issues, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _ux_device_class_storage_control_request(UX_SLAVE_CLASS_COMMAND *command)
@@ -79,6 +82,8 @@ UX_SLAVE_TRANSFER *transfer_request;
UX_SLAVE_DEVICE *device;
UX_SLAVE_CLASS *class;
ULONG request;
+ULONG request_value;
+ULONG request_length;
UX_SLAVE_CLASS_STORAGE *storage;
UX_SLAVE_INTERFACE *interface;
UX_SLAVE_ENDPOINT *endpoint_in;
@@ -93,6 +98,12 @@ UX_SLAVE_ENDPOINT *endpoint_out;
/* Extract the request type from the SETUP packet.. */
request = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_REQUEST);
+ request_value = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_VALUE);
+ request_length = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_LENGTH);
+
+ /* Check if wValue is valid. */
+ if (request_value != 0)
+ return(UX_ERROR);
/* Get the class container. */
class = command -> ux_slave_class_command_class_ptr;
@@ -106,6 +117,10 @@ UX_SLAVE_ENDPOINT *endpoint_out;
case UX_SLAVE_CLASS_STORAGE_RESET:
+ /* Check if wLength is valid. */
+ if (request_length != 0)
+ return(UX_ERROR);
+
/* We need the interface to the class. */
interface = storage -> ux_slave_class_storage_interface;
@@ -144,6 +159,10 @@ UX_SLAVE_ENDPOINT *endpoint_out;
case UX_SLAVE_CLASS_STORAGE_GET_MAX_LUN:
+ /* Check if wLength is valid. */
+ if (request_length < 1)
+ return(UX_ERROR);
+
/* Set the value of the number of LUN in the buffer. The max number of LUN is the
number of declared LUN - 1. */
*transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR)(storage -> ux_slave_class_storage_number_lun -1);
@@ -157,8 +176,8 @@ UX_SLAVE_ENDPOINT *endpoint_out;
default:
- /* Unknown function. It's not handled. */
- return(UX_ERROR);
+ /* Unknown function. It's not handled. */
+ return(UX_ERROR);
}
/* It's handled. */
diff --git a/common/usbx_device_classes/src/ux_device_class_storage_csw_send.c b/common/usbx_device_classes/src/ux_device_class_storage_csw_send.c
index 8e9374a..2eb5709 100644
--- a/common/usbx_device_classes/src/ux_device_class_storage_csw_send.c
+++ b/common/usbx_device_classes/src/ux_device_class_storage_csw_send.c
@@ -38,7 +38,7 @@
/* FUNCTION RELEASE */
/* */
/* _ux_device_class_storage_csw_send PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Chaoqiong Xiao, Microsoft Corporation */
@@ -80,6 +80,9 @@
/* verified memset and memcpy */
/* cases, */
/* resulting in version 6.1 */
+/* 12-31-2020 Chaoqiong Xiao Modified comment(s), */
+/* fixed USB CV test issues, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _ux_device_class_storage_csw_send(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun,
@@ -112,6 +115,9 @@ UCHAR *csw_buffer;
/* Store the SCSI tag from the CBW. */
_ux_utility_long_put(&csw_buffer[UX_SLAVE_CLASS_STORAGE_CSW_TAG], storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_scsi_tag);
+ /* Store the dCSWDataResidue. */
+ _ux_utility_long_put(&csw_buffer[UX_SLAVE_CLASS_STORAGE_CSW_DATA_RESIDUE], storage -> ux_slave_class_storage_csw_residue);
+
/* Store the status of the previous operation. */
csw_buffer[UX_SLAVE_CLASS_STORAGE_CSW_STATUS] = (UCHAR)storage -> ux_slave_class_storage_csw_status;
diff --git a/common/usbx_device_classes/src/ux_device_class_storage_inquiry.c b/common/usbx_device_classes/src/ux_device_class_storage_inquiry.c
index 1cd1d05..2c5a005 100644
--- a/common/usbx_device_classes/src/ux_device_class_storage_inquiry.c
+++ b/common/usbx_device_classes/src/ux_device_class_storage_inquiry.c
@@ -39,7 +39,7 @@
/* FUNCTION RELEASE */
/* */
/* _ux_device_class_storage_inquiry PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Chaoqiong Xiao, Microsoft Corporation */
@@ -82,16 +82,19 @@
/* verified memset and memcpy */
/* cases, */
/* resulting in version 6.1 */
+/* 12-31-2020 Chaoqiong Xiao Modified comment(s), */
+/* fixed USB CV test issues, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _ux_device_class_storage_inquiry(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in,
UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb)
{
-UINT status;
+UINT status = UX_SUCCESS;
UX_SLAVE_TRANSFER *transfer_request;
UCHAR inquiry_page_code;
-UCHAR inquiry_length;
+ULONG inquiry_length;
UCHAR *inquiry_buffer;
UX_PARAMETER_NOT_USED(endpoint_out);
@@ -99,11 +102,20 @@ UCHAR *inquiry_buffer;
/* If trace is enabled, insert this event into the trace buffer. */
UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_INQUIRY, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
+ /* Check direction. */
+ if (storage -> ux_slave_class_storage_host_length &&
+ (storage -> ux_slave_class_storage_cbw_flags & 0x80) == 0)
+ {
+ _ux_device_stack_endpoint_stall(endpoint_out);
+ storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR;
+ return(UX_ERROR);
+ }
+
/* From the SCSI Inquiry payload, get the page code. */
inquiry_page_code = *(cbwcb + UX_SLAVE_CLASS_STORAGE_INQUIRY_PAGE_CODE);
/* And the length to be returned. */
- inquiry_length = *(cbwcb + UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_ADDITIONAL_LENGTH);
+ inquiry_length = storage -> ux_slave_class_storage_host_length;
/* Obtain the pointer to the transfer request. */
transfer_request = &endpoint_in -> ux_slave_endpoint_transfer_request;
@@ -116,7 +128,7 @@ UCHAR *inquiry_buffer;
/* Check for the maximum length to be returned. */
if (inquiry_length > UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH)
- inquiry_length = UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH;
+ inquiry_length = UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH;
/* Default CSW to passed. */
storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PASSED;
@@ -157,12 +169,6 @@ UCHAR *inquiry_buffer;
_ux_utility_memory_copy(inquiry_buffer + UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_PRODUCT_REVISION,
storage -> ux_slave_class_storage_product_rev, 4); /* Use case of memcpy is verified. */
- /* Send a data payload with the inquiry response buffer. */
- _ux_device_stack_transfer_request(transfer_request, inquiry_length, inquiry_length);
-
- /* Now success. */
- status = UX_SUCCESS;
-
break;
case UX_SLAVE_CLASS_STORAGE_INQUIRY_PAGE_CODE_SERIAL:
@@ -177,11 +183,9 @@ UCHAR *inquiry_buffer;
_ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer + 4, storage -> ux_slave_class_storage_product_serial, 20); /* Use case of memcpy is verified. */
/* Send a data payload with the inquiry response buffer. */
- _ux_device_stack_transfer_request(transfer_request, 24, 24);
+ if (inquiry_length > 24)
+ inquiry_length = 24;
- /* Now success. */
- status = UX_SUCCESS;
-
break;
default:
@@ -202,6 +206,20 @@ UCHAR *inquiry_buffer;
break;
}
+ /* Error cases. */
+ if (status != UX_SUCCESS)
+ return(status);
+
+ /* Send a data payload with the inquiry response buffer. */
+ if (inquiry_length)
+ _ux_device_stack_transfer_request(transfer_request, inquiry_length, inquiry_length);
+
+ /* Check length. */
+ if (storage -> ux_slave_class_storage_host_length != inquiry_length)
+ {
+ _ux_device_stack_endpoint_stall(endpoint_in);
+ }
+
/* Return completion status. */
return(status);
}
diff --git a/common/usbx_device_classes/src/ux_device_class_storage_mode_select.c b/common/usbx_device_classes/src/ux_device_class_storage_mode_select.c
index 08c3d7d..6ef4fdd 100644
--- a/common/usbx_device_classes/src/ux_device_class_storage_mode_select.c
+++ b/common/usbx_device_classes/src/ux_device_class_storage_mode_select.c
@@ -35,7 +35,7 @@
/* FUNCTION RELEASE */
/* */
/* _ux_device_class_storage_mode_select PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Chaoqiong Xiao, Microsoft Corporation */
@@ -73,6 +73,9 @@
/* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
/* optimized command logic, */
/* resulting in version 6.1 */
+/* 12-31-2020 Chaoqiong Xiao Modified comment(s), */
+/* fixed USB CV test issues, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _ux_device_class_storage_mode_select(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun,
@@ -87,7 +90,11 @@ UINT _ux_device_class_storage_mode_select(UX_SLAVE_CLASS_STORAGE *storage, ULON
UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_MODE_SELECT, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
/* This command is not yet supported. So Stall the endpoint. */
- _ux_device_stack_endpoint_stall(endpoint_out);
+ if (storage -> ux_slave_class_storage_host_length)
+ {
+ _ux_device_stack_endpoint_stall(endpoint_out);
+ storage -> ux_slave_class_storage_csw_residue = storage -> ux_slave_class_storage_host_length;
+ }
/* And update the REQUEST_SENSE codes. */
storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_status =
diff --git a/common/usbx_device_classes/src/ux_device_class_storage_read.c b/common/usbx_device_classes/src/ux_device_class_storage_read.c
index 79f00cf..08e7e1e 100644
--- a/common/usbx_device_classes/src/ux_device_class_storage_read.c
+++ b/common/usbx_device_classes/src/ux_device_class_storage_read.c
@@ -35,7 +35,7 @@
/* FUNCTION RELEASE */
/* */
/* _ux_device_class_storage_read PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Chaoqiong Xiao, Microsoft Corporation */
@@ -78,6 +78,9 @@
/* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
/* optimized command logic, */
/* resulting in version 6.1 */
+/* 12-31-2020 Chaoqiong Xiao Modified comment(s), */
+/* fixed USB CV test issues, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _ux_device_class_storage_read(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun,
@@ -93,6 +96,7 @@ ULONG number_blocks;
ULONG media_status;
ULONG total_length;
ULONG transfer_length;
+ULONG done_length;
UX_PARAMETER_NOT_USED(endpoint_out);
@@ -120,7 +124,26 @@ ULONG transfer_length;
/* Default CSW to failed. */
storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_FAILED;
+ /* Check transfer length. */
+
+ /* Case (7). Host length < device length. */
+ if (total_length > storage -> ux_slave_class_storage_host_length)
+ {
+ _ux_device_stack_endpoint_stall(endpoint_in);
+ storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR;
+ return(UX_ERROR);
+ }
+
+ /* Case (8). Hi <> Do. */
+ if ((storage -> ux_slave_class_storage_cbw_flags & 0x80) == 0)
+ {
+ _ux_device_stack_endpoint_stall(endpoint_out);
+ storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR;
+ return(UX_ERROR);
+ }
+
/* It may take several transfers to send the requested data. */
+ done_length = 0;
while (total_number_blocks)
{
@@ -138,6 +161,9 @@ ULONG transfer_length;
/* We have a problem, media status error. Return a bad completion and wait for the
REQUEST_SENSE command. */
_ux_device_stack_endpoint_stall(endpoint_in);
+
+ /* Update residue. */
+ storage -> ux_slave_class_storage_csw_residue = storage -> ux_slave_class_storage_host_length - done_length;
/* Return an error. */
return(UX_ERROR);
@@ -173,6 +199,9 @@ ULONG transfer_length;
REQUEST_SENSE command. */
_ux_device_stack_endpoint_stall(endpoint_in);
+ /* Update residue. */
+ storage -> ux_slave_class_storage_csw_residue = storage -> ux_slave_class_storage_host_length - done_length;
+
/* And update the REQUEST_SENSE codes. */
storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_status = media_status;
@@ -191,6 +220,9 @@ ULONG transfer_length;
REQUEST_SENSE command. */
_ux_device_stack_endpoint_stall(endpoint_in);
+ /* Update residue. */
+ storage -> ux_slave_class_storage_csw_residue = storage -> ux_slave_class_storage_host_length - done_length;
+
/* Update the REQUEST_SENSE codes. */
storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_status =
UX_DEVICE_CLASS_STORAGE_SENSE_STATUS(0x02,0x54,0x00);
@@ -205,14 +237,26 @@ ULONG transfer_length;
/* Update the length to remain. */
total_length -= transfer_length;
+ done_length += transfer_length;
/* Update the number of blocks to read. */
total_number_blocks -= number_blocks;
}
-
+
+ /* Case (4), (5). Host length too large. */
+ if (storage -> ux_slave_class_storage_host_length > done_length)
+ {
+
+ /* Stall Bulk-In. */
+ _ux_device_stack_endpoint_stall(endpoint_in);
+
+ /* Update residure. */
+ storage -> ux_slave_class_storage_csw_residue = storage -> ux_slave_class_storage_host_length - done_length;
+ }
+
/* Now we set the CSW with success. */
storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PASSED;
/* Return completion status. */
- return(status);
+ return(UX_SUCCESS);
}
diff --git a/common/usbx_device_classes/src/ux_device_class_storage_report_key.c b/common/usbx_device_classes/src/ux_device_class_storage_report_key.c
index 70b1662..003ae94 100644
--- a/common/usbx_device_classes/src/ux_device_class_storage_report_key.c
+++ b/common/usbx_device_classes/src/ux_device_class_storage_report_key.c
@@ -39,7 +39,7 @@
/* FUNCTION RELEASE */
/* */
/* _ux_device_class_storage_report_key PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Chaoqiong Xiao, Microsoft Corporation */
@@ -79,6 +79,9 @@
/* verified memset and memcpy */
/* cases, */
/* resulting in version 6.1 */
+/* 12-31-2020 Chaoqiong Xiao Modified comment(s), */
+/* fixed compile warning, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _ux_device_class_storage_report_key(UX_SLAVE_CLASS_STORAGE *storage,
@@ -88,7 +91,7 @@ UINT _ux_device_class_storage_report_key(UX_SLAVE_CLASS_STORAGE *storage,
UCHAR *cbwcb)
{
-UINT status;
+UINT status = UX_SUCCESS;
UX_SLAVE_TRANSFER *transfer_request;
ULONG allocation_length;
ULONG key_format;
diff --git a/common/usbx_device_classes/src/ux_device_class_storage_request_sense.c b/common/usbx_device_classes/src/ux_device_class_storage_request_sense.c
index 6d7d4ef..15c2015 100644
--- a/common/usbx_device_classes/src/ux_device_class_storage_request_sense.c
+++ b/common/usbx_device_classes/src/ux_device_class_storage_request_sense.c
@@ -39,7 +39,7 @@
/* FUNCTION RELEASE */
/* */
/* _ux_device_class_storage_request_sense PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Chaoqiong Xiao, Microsoft Corporation */
@@ -80,16 +80,20 @@
/* verified memset and memcpy */
/* cases, */
/* resulting in version 6.1 */
+/* 12-31-2020 Chaoqiong Xiao Modified comment(s), */
+/* fixed USB CV test issues, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _ux_device_class_storage_request_sense(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in,
UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb)
{
-UINT status;
+UINT status = UX_SUCCESS;
UX_SLAVE_TRANSFER *transfer_request;
UCHAR *sense_buffer;
UCHAR key, code, qualifier;
+ULONG sense_length;
UX_PARAMETER_NOT_USED(cbwcb);
@@ -98,11 +102,16 @@ UCHAR key, code, qualifier;
/* Obtain the pointer to the transfer request. */
transfer_request = &endpoint_in -> ux_slave_endpoint_transfer_request;
+ /* Get length. */
+ sense_length = storage -> ux_slave_class_storage_host_length;
+ if (sense_length > UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH)
+ sense_length = UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH;
+
/* Obtain sense buffer. */
sense_buffer = transfer_request -> ux_slave_transfer_request_data_pointer;
/* Ensure it is cleaned. */
- _ux_utility_memory_set(sense_buffer, 0, UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH); /* Use case of memset is verified. */
+ _ux_utility_memory_set(sense_buffer, 0, sense_length); /* Use case of memset is verified. */
/* Initialize the response buffer with the error code. */
sense_buffer[UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_ERROR_CODE] =
@@ -133,12 +142,15 @@ UCHAR key, code, qualifier;
sense_buffer[UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_ADD_LENGTH] = 10;
/* Send a data payload with the sense codes. */
- _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH,
- UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH);
-
- /* Now we set the CSW with success. */
- storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PASSED;
- status = UX_SUCCESS;
+ if (sense_length)
+ _ux_device_stack_transfer_request(transfer_request, sense_length, sense_length);
+
+ /* Check length. */
+ if (storage -> ux_slave_class_storage_host_length != sense_length)
+ {
+ _ux_device_stack_endpoint_stall(endpoint_in);
+ storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR;
+ }
/* Return completion status. */
return(status);
diff --git a/common/usbx_device_classes/src/ux_device_class_storage_test_ready.c b/common/usbx_device_classes/src/ux_device_class_storage_test_ready.c
index 295ade0..ac627f9 100644
--- a/common/usbx_device_classes/src/ux_device_class_storage_test_ready.c
+++ b/common/usbx_device_classes/src/ux_device_class_storage_test_ready.c
@@ -35,7 +35,7 @@
/* FUNCTION RELEASE */
/* */
/* _ux_device_class_storage_test_ready PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Chaoqiong Xiao, Microsoft Corporation */
@@ -75,6 +75,9 @@
/* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
/* optimized command logic, */
/* resulting in version 6.1 */
+/* 12-31-2020 Chaoqiong Xiao Modified comment(s), */
+/* fixed USB CV test issues, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _ux_device_class_storage_test_ready(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in,
@@ -103,7 +106,14 @@ ULONG media_status;
storage -> ux_slave_class_storage_csw_status = (status == UX_SUCCESS) ?
UX_SLAVE_CLASS_STORAGE_CSW_PASSED : UX_SLAVE_CLASS_STORAGE_CSW_FAILED;
status = UX_SUCCESS;
-
+
+ /* Case (9) Ho > Dn. */
+ if (storage -> ux_slave_class_storage_host_length)
+ {
+ _ux_device_stack_endpoint_stall(endpoint_out);
+ storage -> ux_slave_class_storage_csw_residue = storage -> ux_slave_class_storage_host_length;
+ }
+
/* Return completion status. */
return(status);
}
diff --git a/common/usbx_device_classes/src/ux_device_class_storage_thread.c b/common/usbx_device_classes/src/ux_device_class_storage_thread.c
index 3fa1d29..5f6983a 100644
--- a/common/usbx_device_classes/src/ux_device_class_storage_thread.c
+++ b/common/usbx_device_classes/src/ux_device_class_storage_thread.c
@@ -35,7 +35,7 @@
/* FUNCTION RELEASE */
/* */
/* _ux_device_class_storage_thread PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Chaoqiong Xiao, Microsoft Corporation */
@@ -100,6 +100,9 @@
/* TX symbols instead of using */
/* them directly, */
/* resulting in version 6.1 */
+/* 12-31-2020 Chaoqiong Xiao Modified comment(s), */
+/* fixed USB CV test issues, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
VOID _ux_device_class_storage_thread(ULONG storage_class)
@@ -117,6 +120,7 @@ ULONG length;
ULONG cbwcb_length;
ULONG lun;
UCHAR *scsi_command;
+UCHAR *cbw_cb;
/* This thread runs forever but can be suspended or resumed. */
@@ -188,10 +192,21 @@ UCHAR *scsi_command;
/* Obtain the lun from the CBW. */
lun = (ULONG) *(scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_LUN);
+ storage -> ux_slave_class_storage_cbw_lun = (UCHAR)lun;
/* We have to memorize the SCSI command tag for the CSW phase. */
storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_scsi_tag = _ux_utility_long_get(scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_TAG);
+ /* Get dCBWDataTransferLength: number of bytes to transfer. */
+ storage -> ux_slave_class_storage_host_length = _ux_utility_long_get(scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_DATA_LENGTH);
+
+ /* Save bmCBWFlags. */
+ storage -> ux_slave_class_storage_cbw_flags = *(scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_FLAGS);
+
+ /* Reset CSW status. */
+ storage -> ux_slave_class_storage_csw_residue = 0;
+ storage -> ux_slave_class_storage_csw_status = 0;
+
/* Ensure the LUN number is within our declared values and check the command
content and format. First we make sure we have a complete CBW. */
if ((lun < storage -> ux_slave_class_storage_number_lun) && (length == UX_SLAVE_CLASS_STORAGE_CBW_LENGTH))
@@ -209,128 +224,129 @@ UCHAR *scsi_command;
{
/* Analyze the command stored in the CBWCB. */
- switch (*(scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB))
+ cbw_cb = scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB;
+ switch (*(cbw_cb))
{
case UX_SLAVE_CLASS_STORAGE_SCSI_TEST_READY:
- _ux_device_class_storage_test_ready(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB);
+ _ux_device_class_storage_test_ready(storage, lun, endpoint_in, endpoint_out, cbw_cb);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_REQUEST_SENSE:
- _ux_device_class_storage_request_sense(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB);
+ _ux_device_class_storage_request_sense(storage, lun, endpoint_in, endpoint_out, cbw_cb);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_FORMAT:
- _ux_device_class_storage_format(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB);
+ _ux_device_class_storage_format(storage, lun, endpoint_in, endpoint_out, cbw_cb);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_INQUIRY:
- _ux_device_class_storage_inquiry(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB);
+ _ux_device_class_storage_inquiry(storage, lun, endpoint_in, endpoint_out, cbw_cb);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_START_STOP:
- _ux_device_class_storage_start_stop(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB);
+ _ux_device_class_storage_start_stop(storage, lun, endpoint_in, endpoint_out, cbw_cb);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_PREVENT_ALLOW_MEDIA_REMOVAL:
- _ux_device_class_storage_prevent_allow_media_removal(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB);
+ _ux_device_class_storage_prevent_allow_media_removal(storage, lun, endpoint_in, endpoint_out, cbw_cb);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_READ_FORMAT_CAPACITY:
- _ux_device_class_storage_read_format_capacity(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB);
+ _ux_device_class_storage_read_format_capacity(storage, lun, endpoint_in, endpoint_out, cbw_cb);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_READ_CAPACITY:
- _ux_device_class_storage_read_capacity(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB);
+ _ux_device_class_storage_read_capacity(storage, lun, endpoint_in, endpoint_out, cbw_cb);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_VERIFY:
- _ux_device_class_storage_verify(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB);
+ _ux_device_class_storage_verify(storage, lun, endpoint_in, endpoint_out, cbw_cb);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SELECT:
- _ux_device_class_storage_mode_select(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB);
+ _ux_device_class_storage_mode_select(storage, lun, endpoint_in, endpoint_out, cbw_cb);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE_SHORT:
case UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE:
- _ux_device_class_storage_mode_sense(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB);
+ _ux_device_class_storage_mode_sense(storage, lun, endpoint_in, endpoint_out, cbw_cb);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_READ32:
- _ux_device_class_storage_read(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB,
+ _ux_device_class_storage_read(storage, lun, endpoint_in, endpoint_out, cbw_cb,
UX_SLAVE_CLASS_STORAGE_SCSI_READ32);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_READ16:
- _ux_device_class_storage_read(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB,
+ _ux_device_class_storage_read(storage, lun, endpoint_in, endpoint_out, cbw_cb,
UX_SLAVE_CLASS_STORAGE_SCSI_READ16);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE32:
- _ux_device_class_storage_write(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB,
+ _ux_device_class_storage_write(storage, lun, endpoint_in, endpoint_out, cbw_cb,
UX_SLAVE_CLASS_STORAGE_SCSI_WRITE32);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16:
- _ux_device_class_storage_write(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB,
+ _ux_device_class_storage_write(storage, lun, endpoint_in, endpoint_out, cbw_cb,
UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_SYNCHRONIZE_CACHE:
- _ux_device_class_storage_synchronize_cache(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB, *(scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB));
+ _ux_device_class_storage_synchronize_cache(storage, lun, endpoint_in, endpoint_out, cbw_cb, *(cbw_cb));
break;
#ifdef UX_SLAVE_CLASS_STORAGE_INCLUDE_MMC
case UX_SLAVE_CLASS_STORAGE_SCSI_GET_STATUS_NOTIFICATION:
- _ux_device_class_storage_get_status_notification(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB);
+ _ux_device_class_storage_get_status_notification(storage, lun, endpoint_in, endpoint_out, cbw_cb);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_GET_CONFIGURATION:
- _ux_device_class_storage_get_configuration(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB);
+ _ux_device_class_storage_get_configuration(storage, lun, endpoint_in, endpoint_out, cbw_cb);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_READ_DISK_INFORMATION:
- _ux_device_class_storage_read_disk_information(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB);
+ _ux_device_class_storage_read_disk_information(storage, lun, endpoint_in, endpoint_out, cbw_cb);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_REPORT_KEY:
- _ux_device_class_storage_report_key(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB);
+ _ux_device_class_storage_report_key(storage, lun, endpoint_in, endpoint_out, cbw_cb);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_GET_PERFORMANCE:
- _ux_device_class_storage_get_performance(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB);
+ _ux_device_class_storage_get_performance(storage, lun, endpoint_in, endpoint_out, cbw_cb);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_READ_DVD_STRUCTURE:
- _ux_device_class_storage_read_dvd_structure(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB);
+ _ux_device_class_storage_read_dvd_structure(storage, lun, endpoint_in, endpoint_out, cbw_cb);
break;
case UX_SLAVE_CLASS_STORAGE_SCSI_READ_TOC:
- status = _ux_device_class_storage_read_toc(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB);
+ status = _ux_device_class_storage_read_toc(storage, lun, endpoint_in, endpoint_out, cbw_cb);
/* Special treatment of TOC command. If error, default to Stall endpoint. */
if (status == UX_SUCCESS)
@@ -342,8 +358,8 @@ UCHAR *scsi_command;
/* The command is unknown or unsupported, so we stall the endpoint. */
- if (_ux_utility_long_get(scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_DATA_LENGTH) > 0 &&
- ((*(scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_FLAGS) & 0x80) == 0))
+ if (storage -> ux_slave_class_storage_host_length > 0 &&
+ ((storage -> ux_slave_class_storage_cbw_flags & 0x80) == 0))
/* Data-Out from host to device, stall OUT. */
_ux_device_stack_endpoint_stall(endpoint_out);
diff --git a/common/usbx_device_classes/src/ux_device_class_storage_write.c b/common/usbx_device_classes/src/ux_device_class_storage_write.c
index c42bf10..47560f0 100644
--- a/common/usbx_device_classes/src/ux_device_class_storage_write.c
+++ b/common/usbx_device_classes/src/ux_device_class_storage_write.c
@@ -34,7 +34,7 @@
/* FUNCTION RELEASE */
/* */
/* _ux_device_class_storage_write PORTABLE C */
-/* 6.1 */
+/* 6.1.3 */
/* AUTHOR */
/* */
/* Chaoqiong Xiao, Microsoft Corporation */
@@ -80,6 +80,9 @@
/* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
/* optimized command logic, */
/* resulting in version 6.1 */
+/* 12-31-2020 Chaoqiong Xiao Modified comment(s), */
+/* fixed USB CV test issues, */
+/* resulting in version 6.1.3 */
/* */
/**************************************************************************/
UINT _ux_device_class_storage_write(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun,
@@ -95,6 +98,7 @@ ULONG number_blocks;
ULONG media_status;
ULONG total_length;
ULONG transfer_length;
+ULONG done_length;
UX_PARAMETER_NOT_USED(endpoint_in);
@@ -160,11 +164,30 @@ ULONG transfer_length;
/* Compute the total length to transfer and how much remains. */
total_length = total_number_blocks * storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_block_length;
-
+
+ /* Check transfer length. */
+
+ /* Case (3) Hn < Do. */
+ if (total_length > storage -> ux_slave_class_storage_host_length)
+ {
+ _ux_device_stack_endpoint_stall(endpoint_out);
+ storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR;
+ return(UX_ERROR);
+ }
+
+ /* Case (8). Hi <> Do. */
+ if ((storage -> ux_slave_class_storage_cbw_flags & 0x80) != 0)
+ {
+ _ux_device_stack_endpoint_stall(endpoint_in);
+ storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR;
+ return(UX_ERROR);
+ }
+
/* Default status to success. */
status = UX_SUCCESS;
/* It may take several transfers to send the requested data. */
+ done_length = 0;
while (total_length)
{
@@ -185,6 +208,9 @@ ULONG transfer_length;
REQUEST_SENSE command. */
_ux_device_stack_endpoint_stall(endpoint_out);
+ /* Update residue. */
+ storage -> ux_slave_class_storage_csw_residue = storage -> ux_slave_class_storage_host_length - done_length;
+
/* And update the REQUEST_SENSE codes. */
storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_status =
UX_DEVICE_CLASS_STORAGE_SENSE_STATUS(0x02,0x54,0x00);
@@ -207,6 +233,9 @@ ULONG transfer_length;
REQUEST_SENSE command. */
_ux_device_stack_endpoint_stall(endpoint_out);
+ /* Update residue. */
+ storage -> ux_slave_class_storage_csw_residue = storage -> ux_slave_class_storage_host_length - done_length;
+
/* And update the REQUEST_SENSE codes. */
storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_status = media_status;
@@ -218,9 +247,17 @@ ULONG transfer_length;
lba += number_blocks;
/* Update the length to remain. */
- total_length -= transfer_length;
+ total_length -= transfer_length;
+ done_length += transfer_length;
}
+ /* Update residue. */
+ storage -> ux_slave_class_storage_csw_residue = storage -> ux_slave_class_storage_host_length - done_length;
+
+ /* Case (9), (11). If host expects more transfer, stall it. */
+ if (storage -> ux_slave_class_storage_csw_residue)
+ _ux_device_stack_endpoint_stall(endpoint_out);
+
/* Now we set the CSW with success. */
storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PASSED;