diff options
| author | Scott Larson <[email protected]> | 2021-01-07 16:53:02 -0800 |
|---|---|---|
| committer | Scott Larson <[email protected]> | 2021-01-07 16:53:02 -0800 |
| commit | 9823f3857d7eb54c8416d9eab316aab0257130f9 (patch) | |
| tree | 65690334fd54075e35169ff3d34040c66ba0dbe2 /common/usbx_device_classes | |
| parent | d8014ecb428bb2d5cf50cba68dd8e7022ee35171 (diff) | |
update to v6.1.3v6.1.3_rel
Diffstat (limited to 'common/usbx_device_classes')
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; |
