diff options
Diffstat (limited to 'firmware/usbstack')
-rw-r--r-- | firmware/usbstack/usb_storage.c | 44 |
1 files changed, 23 insertions, 21 deletions
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c index 0b433764cf..1f7069dfe2 100644 --- a/firmware/usbstack/usb_storage.c +++ b/firmware/usbstack/usb_storage.c | |||
@@ -245,6 +245,7 @@ static struct { | |||
245 | static void handle_scsi(struct command_block_wrapper* cbw); | 245 | static void handle_scsi(struct command_block_wrapper* cbw); |
246 | static void send_csw(int status); | 246 | static void send_csw(int status); |
247 | static void send_command_result(void *data,int size); | 247 | static void send_command_result(void *data,int size); |
248 | static void send_command_failed_result(void); | ||
248 | static void send_block_data(void *data,int size); | 249 | static void send_block_data(void *data,int size); |
249 | static void receive_block_data(void *data,int size); | 250 | static void receive_block_data(void *data,int size); |
250 | static void identify2inquiry(int lun); | 251 | static void identify2inquiry(int lun); |
@@ -258,6 +259,7 @@ static enum { | |||
258 | WAITING_FOR_COMMAND, | 259 | WAITING_FOR_COMMAND, |
259 | SENDING_BLOCKS, | 260 | SENDING_BLOCKS, |
260 | SENDING_RESULT, | 261 | SENDING_RESULT, |
262 | SENDING_FAILED_RESULT, | ||
261 | RECEIVING_BLOCKS, | 263 | RECEIVING_BLOCKS, |
262 | SENDING_CSW | 264 | SENDING_CSW |
263 | } state = WAITING_FOR_COMMAND; | 265 | } state = WAITING_FOR_COMMAND; |
@@ -468,6 +470,12 @@ void usb_storage_transfer_complete(bool in,int status,int length) | |||
468 | cur_sense_data.ascq=0; | 470 | cur_sense_data.ascq=0; |
469 | } | 471 | } |
470 | break; | 472 | break; |
473 | case SENDING_FAILED_RESULT: | ||
474 | if(in==false) { | ||
475 | logf("OUT received in SENDING"); | ||
476 | } | ||
477 | send_csw(UMS_STATUS_FAIL); | ||
478 | break; | ||
471 | case SENDING_BLOCKS: | 479 | case SENDING_BLOCKS: |
472 | if(in==false) { | 480 | if(in==false) { |
473 | logf("OUT received in SENDING"); | 481 | logf("OUT received in SENDING"); |
@@ -657,6 +665,7 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
657 | 665 | ||
658 | case SCSI_REQUEST_SENSE: { | 666 | case SCSI_REQUEST_SENSE: { |
659 | tb.sense_data->ResponseCode=0x70;/*current error*/ | 667 | tb.sense_data->ResponseCode=0x70;/*current error*/ |
668 | tb.sense_data->Obsolete=0; | ||
660 | tb.sense_data->fei_sensekey=cur_sense_data.sense_key&0x0f; | 669 | tb.sense_data->fei_sensekey=cur_sense_data.sense_key&0x0f; |
661 | tb.sense_data->Information=cur_sense_data.information; | 670 | tb.sense_data->Information=cur_sense_data.information; |
662 | tb.sense_data->AdditionalSenseLength=10; | 671 | tb.sense_data->AdditionalSenseLength=10; |
@@ -673,9 +682,7 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
673 | 682 | ||
674 | case SCSI_MODE_SENSE_10: { | 683 | case SCSI_MODE_SENSE_10: { |
675 | if(! lun_present) { | 684 | if(! lun_present) { |
676 | /* Windows expects an empty command result before the csw */ | 685 | send_command_failed_result(); |
677 | usb_drv_send(usb_endpoint, 0, 0); | ||
678 | send_csw(UMS_STATUS_FAIL); | ||
679 | cur_sense_data.sense_key=SENSE_NOT_READY; | 686 | cur_sense_data.sense_key=SENSE_NOT_READY; |
680 | cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; | 687 | cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; |
681 | cur_sense_data.ascq=0; | 688 | cur_sense_data.ascq=0; |
@@ -719,9 +726,7 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
719 | MIN(sizeof(struct mode_sense_data_10), length)); | 726 | MIN(sizeof(struct mode_sense_data_10), length)); |
720 | break; | 727 | break; |
721 | default: | 728 | default: |
722 | /* Windows expects an empty command result before the csw */ | 729 | send_command_failed_result(); |
723 | usb_drv_send(usb_endpoint, 0, 0); | ||
724 | send_csw(UMS_STATUS_FAIL); | ||
725 | cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST; | 730 | cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST; |
726 | cur_sense_data.asc=ASC_INVALID_FIELD_IN_CBD; | 731 | cur_sense_data.asc=ASC_INVALID_FIELD_IN_CBD; |
727 | cur_sense_data.ascq=0; | 732 | cur_sense_data.ascq=0; |
@@ -731,9 +736,7 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
731 | } | 736 | } |
732 | case SCSI_MODE_SENSE_6: { | 737 | case SCSI_MODE_SENSE_6: { |
733 | if(! lun_present) { | 738 | if(! lun_present) { |
734 | /* Windows expects an empty command result before the csw */ | 739 | send_command_failed_result(); |
735 | usb_drv_send(usb_endpoint, 0, 0); | ||
736 | send_csw(UMS_STATUS_FAIL); | ||
737 | cur_sense_data.sense_key=SENSE_NOT_READY; | 740 | cur_sense_data.sense_key=SENSE_NOT_READY; |
738 | cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; | 741 | cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; |
739 | cur_sense_data.ascq=0; | 742 | cur_sense_data.ascq=0; |
@@ -776,9 +779,7 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
776 | MIN(sizeof(struct mode_sense_data_6), length)); | 779 | MIN(sizeof(struct mode_sense_data_6), length)); |
777 | break; | 780 | break; |
778 | default: | 781 | default: |
779 | /* Windows expects an empty command result before the csw */ | 782 | send_command_failed_result(); |
780 | usb_drv_send(usb_endpoint, 0, 0); | ||
781 | send_csw(UMS_STATUS_FAIL); | ||
782 | cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST; | 783 | cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST; |
783 | cur_sense_data.asc=ASC_INVALID_FIELD_IN_CBD; | 784 | cur_sense_data.asc=ASC_INVALID_FIELD_IN_CBD; |
784 | cur_sense_data.ascq=0; | 785 | cur_sense_data.ascq=0; |
@@ -827,9 +828,7 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
827 | } | 828 | } |
828 | else | 829 | else |
829 | { | 830 | { |
830 | /* Windows expects an empty command result before the csw */ | 831 | send_command_failed_result(); |
831 | usb_drv_send(usb_endpoint, 0, 0); | ||
832 | send_csw(UMS_STATUS_FAIL); | ||
833 | cur_sense_data.sense_key=SENSE_NOT_READY; | 832 | cur_sense_data.sense_key=SENSE_NOT_READY; |
834 | cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; | 833 | cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; |
835 | cur_sense_data.ascq=0; | 834 | cur_sense_data.ascq=0; |
@@ -851,9 +850,7 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
851 | } | 850 | } |
852 | else | 851 | else |
853 | { | 852 | { |
854 | /* Windows expects an empty command result before the csw */ | 853 | send_command_failed_result(); |
855 | usb_drv_send(usb_endpoint, 0, 0); | ||
856 | send_csw(UMS_STATUS_FAIL); | ||
857 | cur_sense_data.sense_key=SENSE_NOT_READY; | 854 | cur_sense_data.sense_key=SENSE_NOT_READY; |
858 | cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; | 855 | cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; |
859 | cur_sense_data.ascq=0; | 856 | cur_sense_data.ascq=0; |
@@ -864,9 +861,7 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
864 | case SCSI_READ_10: | 861 | case SCSI_READ_10: |
865 | logf("scsi read10 %d",lun); | 862 | logf("scsi read10 %d",lun); |
866 | if(! lun_present) { | 863 | if(! lun_present) { |
867 | /* Windows expects an empty command result before the csw */ | 864 | send_command_failed_result(); |
868 | usb_drv_send(usb_endpoint, 0, 0); | ||
869 | send_csw(UMS_STATUS_FAIL); | ||
870 | cur_sense_data.sense_key=SENSE_NOT_READY; | 865 | cur_sense_data.sense_key=SENSE_NOT_READY; |
871 | cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; | 866 | cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; |
872 | cur_sense_data.ascq=0; | 867 | cur_sense_data.ascq=0; |
@@ -957,6 +952,12 @@ static void send_command_result(void *data,int size) | |||
957 | state = SENDING_RESULT; | 952 | state = SENDING_RESULT; |
958 | } | 953 | } |
959 | 954 | ||
955 | static void send_command_failed_result(void) | ||
956 | { | ||
957 | usb_drv_send_nonblocking(usb_endpoint, NULL, 0); | ||
958 | state = SENDING_FAILED_RESULT; | ||
959 | } | ||
960 | |||
960 | static void receive_block_data(void *data,int size) | 961 | static void receive_block_data(void *data,int size) |
961 | { | 962 | { |
962 | usb_drv_recv(usb_endpoint, data, size); | 963 | usb_drv_recv(usb_endpoint, data, size); |
@@ -1026,6 +1027,7 @@ static void identify2inquiry(int lun) | |||
1026 | 1027 | ||
1027 | tb.inquiry->DeviceType = DIRECT_ACCESS_DEVICE; | 1028 | tb.inquiry->DeviceType = DIRECT_ACCESS_DEVICE; |
1028 | tb.inquiry->AdditionalLength = 0x1f; | 1029 | tb.inquiry->AdditionalLength = 0x1f; |
1030 | memset(tb.inquiry->Reserved, 0, 3); | ||
1029 | tb.inquiry->Versions = 4; /* SPC-2 */ | 1031 | tb.inquiry->Versions = 4; /* SPC-2 */ |
1030 | tb.inquiry->Format = 2; /* SPC-2/3 inquiry format */ | 1032 | tb.inquiry->Format = 2; /* SPC-2/3 inquiry format */ |
1031 | 1033 | ||