@WMXZ Will try. Note I tried SDFormatter, including allowing resize... and it still does not read... But it now acts more like the other disk in that it does not repeat.... Just stops...
@WMXZ, @Kutre, @mjs513
One thing that I see in sd_msc.cpp, in the "MSC_disk_read(BYTE *buff, DWORD sector, UINT count)" and "MSC_disk_write(const BYTE *buff, DWORD sector, UINT count)" functions is
"WaitDriveReady()". I probably did not comment that out in the library I sent. Comment them out in sd_msc.cpp and see if the library stabalises. It did on my side. Not as many hangs as
before. Only when I try copy a 4.3MB file from one file to another file on the same USB drive and that seems to be due to buffer size which is using multi sector reads and writes.
Thanks @wwatson,
Will try it.
As I mentioned in the T4 thread, with my two thumb drives the call to mscInit is hanging, in the call to msDeviceInquiry, which has called msDoCommand,
msDoCommand has the flags of CMDDIRDATAIN so it queues the command to the datapipeOut pipe and the return buffer to the datapipeIn pipe and we make it through the two loops waiting for msOutCompleted and msInCompleted.. It then go to call msGetCSW, which queues a prefilled in buffer on the datapipeIN pipe and waits for a callback (which waits for msInCompleted which is never cleared (Callback is not called....
The last stuff in my debug output:
Questions I have include:Code:## mscInit before DeviceInquiry ## msDeviceInquiry before do command 36 msController CallbackOut (static) transfer->qtd.token = 1 msController dataOut (static) msDoCommand after msOutCompleted loop msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static) msDoCommand after msInCompleted loop msGetCSW before QDT msGetCSW after QDT
The msGetCSW is setting up transfer from the datapipeIn, and it is also prefilling the buffer it sets up to some values. Who is it that triggers something to actually be returned on this pipe?
I understand when I setup to send an INQUIRY command (setup on output pipe), that the device will respond with a Inquiry response, which will come back on the input pipe.
But does it also automatically respond with a second packet of the status block?
Do you have a link to some PDF or the like that you have been using to understand the SCSI stuff?
Maybe something like: https://www.usb.org/sites/default/fi...assbulk_10.pdf ?
Thanks and again good stuff!
Just setup TD 1.47B2 and ran uSDFS_test.ino on the T3.6 at 180MHZ and 240MHZ. Tested good on Kingston 16G flash drive and a Seagate 250GB hard drive with "WaitDriveReady()" enabled. But when I disabled "WaitDriveReady()" at 240MHZ it fails on writing to a file. On my other T3.6 system it still works at 240MHZ. There are lots of other USB drivers involved on that system. I am going to port this latest version of uSDFS over to that system and see if it reacts the same way.
Need to be able to better detect errors. "msController::checkCSW(msCommandStatusWrapper _t *CSW)" is where it is done".
Thanks @wwatson - Lots of information in there about the different commands and structures!
The Document I linked to in #29 from the USB Spec documents did not have any of those details, but does have some interesting stuff about CBW and CSW usages and about the handshaking between host and device and things like if a device does not like something it may stall the pipes...
For the fun of it I may try some other type of disk to see if they get beyond the INQUIRY command.
@PaulStoffregen - Wondering how best to do something using usbhost_t36 library. I have done some stuff in the library, but am unsure about some of the low level stuff and how best to do it...
Example: The USB document for USB Bulk storage talking about Data transfer conditions (Section 5.3) has a simple Flow chart that shows what you should do to output the next CBW.
First step after Enter: Attemt to read CSW from Bulk-In-endpoint And then a conditional box (STALL Bulk-In -OR- Bulk Error) ...
Question is how do we properly do this with our Pipes/Transfers - Currently the code simply queues up a buffer to the input pipe and waits for a response to happen (Callback function sets a completed variable)
This is a modified version of @wwatson's code in that I print out a few more things, check to see if the queue failed ...Code:uint8_t msController::msGetCSW() { uint8_t CSWResult = 0; msCommandStatusWrapper_t StatusBlockWrapper = (msCommandStatusWrapper_t) { .Signature = CSWSIGNATURE, .Tag = 0, .DataResidue = 0, // TODO: Proccess this if received. .Status = 0 }; println("msGetCSW before QDT"); if (!queue_Data_Transfer(datapipeIn, &StatusBlockWrapper, sizeof(StatusBlockWrapper), this)) { println("msController::msGetCSW QDT failed"); } println("msGetCSW after QDT"); uint16_t timeout_loop_count=32767; while(!msInCompleted /*&& --timeout_loop_count*/); msInCompleted = false; CSWResult = checkCSW(&StatusBlockWrapper); return CSWResult; }
The current code hangs on my machine with a couple of different USB Sticks after the INQUIRY call... I played around with timeout loop, which is shown semi-commented out...
This allowed it to continue, but then we still have the transfer structure pending on the pipe so things out of sync...
Again not sure of how to handle this. I don't know of any normal way to for example cancel a transfer? Or put in timeout? ...
Suggestions?
Kurt
P.S. - I understand you might be busy with a few other things![]()
@Kurte
That is where I am at with this as well. How to detect a stalled pipe and other errors or conditions that constitute performing a reset recovery.
This is the code that checks for a valid CSW:
The tag mismatch error is the most common error I get. When I hex dump the CSW the signature is there but the tag and status are always zero. Sometimes I get a status byte=1 which is an invalid CBW sent. I have never been able to detect a phase error which is status byte=2.Code://--------------------------------------------------------------------------- // Check for valid CSW uint8_t msController::checkCSW(msCommandStatusWrapper_t *CSW) { if(CSW->Signature != CSWSIGNATURE) return MSCSWSIGERROR; // Signature error if(CSW->Tag != CBWTag) return MSCSWTAGERROR; // Tag mismatch error if(CSW->Status != 0) return CSW->Status; // Actual status from last transaction return MSCOMMANDPASS; // Command transaction success (0) }
Section 6 in the usbmassbulk_10.pdf manual gives lots of information on how to handle error conditions.
@wwatson - Understand...
I did a little more hacking and maybe some of the issue is handling conditions and errors.
That is I hacked up your function:
So I can see what data is coming back from the different commands and the like:Code:void msController::new_dataIn(const Transfer_t *transfer) { uint32_t len = transfer->length - ((transfer->qtd.token >> 16) & 0x7FFF); println("msController dataIn (static): ", len, DEC); print_hexbytes((uint8_t*)transfer->buffer, (len < 32)? len : 32 ); if (len >= 4) { uint32_t l = *(uint32_t*)transfer->buffer; if (l == CBWSIGNATURE) println("** CBWSIGNATURE"); else if (l == CSWSIGNATURE) println("** CSWSIGNATURE"); else println("** ????"); } msInCompleted = true; // Last in transaction is completed. }
Notice the ending, that the data returned from the INQUIRY command was a CSW message not a data message. So you already received the status... But thought it was result of inqury.Code:Test uSDFS 2:/ USB2 PLL running reset waited 6 USBHS_ASYNCLISTADDR = 0 USBHS_PERIODICLISTBASE = 20005000 periodictable = 20005000 ## mscInit Called port change: 10001803 connect begin reset port change: 18001205 port enabled end recovery new_Device: 480 Mbit/sec new_Pipe enumeration: enumeration: enumeration: Device Descriptor: 12 01 00 02 09 00 01 40 E3 05 08 06 98 32 00 01 00 01 VendorID = 05E3, ProductID = 0608, Version = 3298 Class/Subclass/Protocol = 9(Hub) / 0 / 1(Single-TT) Number of Configurations = 1 enumeration: enumeration: Product: USB2.0 Hub enumeration: Config data length = 25 enumeration: Configuration Descriptor: 09 02 19 00 01 01 00 E0 32 NumInterfaces = 1 ConfigurationValue = 1 09 04 00 00 01 09 00 00 00 Interface = 0 Number of endpoints = 1 Class/Subclass/Protocol = 9(Hub) / 0 / 0 07 05 81 03 01 00 0C Endpoint = 1 IN Type = Interrupt Max Size = 1 Polling Interval = 12 enumeration: USBHub memory usage = 960 USBHub claim_device this=20004660 found possible interface, altsetting=0 number of interfaces found = 1 USBHub control callback 09 29 04 E0 00 32 64 00 FF 00 00 00 00 00 00 00 Hub ports = 4 USBHub control callback USBHub control callback USBHub control callback USBHub control callback power turned on to all ports device addr = 1 new_Pipe allocate_interrupt_pipe_bandwidth ep interval = 12 interval = 256 best_bandwidth = 2, at offset = 0 pipe cap1 = F0012101 HUB Callback (member) status = 4 getstatus, port = 2 USBHub control callback 01 01 01 00 New Port Status status=10101 port=2 state=0 Device is present: Has Power USBHub control callback Port Status Cleared, port=2 timer event (19999 us): Debounce Timer, this = 20004660, timer = 20004978 ports in use bitmask = 4 getstatus, port = 2 USBHub control callback 01 01 00 00 New Port Status status=101 port=2 state=2 Device is present: Has Power timer event (19999 us): Debounce Timer, this = 20004660, timer = 20004978 ports in use bitmask = 4 getstatus, port = 2 USBHub control callback 01 01 00 00 New Port Status status=101 port=2 state=3 Device is present: Has Power timer event (19999 us): Debounce Timer, this = 20004660, timer = 20004978 ports in use bitmask = 4 getstatus, port = 2 USBHub control callback 01 01 00 00 New Port Status status=101 port=2 state=4 Device is present: Has Power timer event (19999 us): Debounce Timer, this = 20004660, timer = 20004978 ports in use bitmask = 4 getstatus, port = 2 USBHub control callback 01 01 00 00 New Port Status status=101 port=2 state=5 Device is present: Has Power timer event (19999 us): Debounce Timer, this = 20004660, timer = 20004978 ports in use bitmask = 4 getstatus, port = 2 USBHub control callback 01 01 00 00 New Port Status status=101 port=2 state=6 Device is present: Has Power sending reset send_setreset USBHub control callback unhandled setup, message = 40323 timer event (19999 us): Debounce Timer, this = 20004660, timer = 20004978 ports in use bitmask = 0 HUB Callback (member) status = 4 getstatus, port = 2 USBHub control callback 03 05 10 00 New Port Status status=100503 port=2 state=7 Device is present: Enabled, speed = 480 Mbit/sec Has Power USBHub control callback unhandled setup, message = 140123 timer event (24999 us): Hello, I'm resettimer, this = 20004660, timer = 20004994 port_doing_reset = 2 PORT_RECOVERY new_Device: 480 Mbit/sec new_Pipe enumeration: enumeration: enumeration: Device Descriptor: 12 01 00 02 00 00 00 40 0C 09 00 10 00 11 01 02 00 01 VendorID = 090C, ProductID = 1000, Version = 1100 Class/Subclass/Protocol = 0 / 0 / 0 Number of Configurations = 1 enumeration: enumeration: Manufacturer: SMI Corporation enumeration: Product: USB DISK enumeration: Config data length = 32 enumeration: Configuration Descriptor: 09 02 20 00 01 01 00 80 FA NumInterfaces = 1 ConfigurationValue = 1 09 04 00 00 02 08 06 50 00 Interface = 0 Number of endpoints = 2 Class/Subclass/Protocol = 8(Mass Storage) / 6(SCSI) / 80(Bulk Only) 07 05 81 02 00 02 FF Endpoint = 1 IN Type = Bulk Max Size = 512 Polling Interval = 255 07 05 02 02 00 02 FF Endpoint = 2 OUT Type = Bulk Max Size = 512 Polling Interval = 255 enumeration: msController claim this=20004A40 Descriptor 4 = INTERFACE msController claim this=20004A40 09 04 00 00 02 08 06 50 00 07 05 81 02 00 02 FF 07 05 02 02 00 02 FF endpointType = 2 numendpoint=2 endpointIn=81 endpointOut=2 packet size in (msController) = 512 packet size out (msController) = 512 polling intervalIn = 255 polling intervalOut = 255 new_Pipe new_Pipe Descriptor 5 = ENDPOINT Descriptor 5 = ENDPOINT ## mscInit after available ## mscInit after reset control CallbackIn (msController) 00 00 00 00 00 00 00 00 ## mscInit after msgGetMaxLun control CallbackIn (msController) 00 00 00 00 00 00 00 00 ## mscInit before startstopunit msController CallbackOut (static) transfer->qtd.token = 1 msController dataOut (static) msGetCSW before QDT msGetCSW after QDT msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static): 13 55 53 42 53 02 00 00 00 00 00 00 00 00 ** CSWSIGNATURE ## mscInit before media ready msController CallbackOut (static) transfer->qtd.token = 1 msController dataOut (static) msGetCSW before QDT msGetCSW after QDT msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static): 13 55 53 42 53 03 00 00 00 00 00 00 00 00 ** CSWSIGNATURE ## mscInit before DeviceInquiry ## msDeviceInquiry before do command 36 msController CallbackOut (static) transfer->qtd.token = 1 msController dataOut (static) msDoCommand after msOutCompleted loop msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static): 13 55 53 42 53 04 00 00 00 00 00 00 00 00 ** CSWSIGNATURE msDoCommand after msInCompleted loop msGetCSW before QDT msGetCSW after QDT
Kurt
@Kurte
I think I see what you are getting at. For each CBW sent there needs to be a corresponding CSW read in and checked. My code is only getting the CSW at the end of "msDoCommand()" which is probably causing things to get out of sync.
Thanks, When I get back from work today I am going to redo the msDoCommand()" and "msGetCSW()" functions.
You are really good at this.
Hi @wwatson,
Thanks,
Not sure yet what is the correct way of programming this yet - Still just starting to trace my way through...
But so far it looks like for each command you output you are receiving a CSWSignature message back... Not sure about your data that probably should be returned for the INQUIRY command?
Actually I think there is an issue with the INQUIRY command:
That is I think you are asking it to not return any data... Page 92 of your SCSI document...
You are passing in allocation length=0 and I think that is saying don't return anything... So I changed:
In yours you had .CommandData as all 0's after CMDINQUIRY... I put it to the size of structure you specified.Code:uint8_t msController::msDeviceInquiry(msInquiryResponse_t * const Inquiry) { msCommandBlockWrapper_t CommandBlockWrapper = (msCommandBlockWrapper_t) { .Signature = CBWSIGNATURE, .Tag = ++CBWTag, .TransferLength = sizeof(msInquiryResponse_t), .Flags = CMDDIRDATAIN, .LUN = 0, .CommandLength = 6, .CommandData = {CMDINQUIRY,0x00,0x00,0x00,sizeof(msInquiryResponse_t),0x00} }; Serial.printf("## msDeviceInquiry before do command %u\n", sizeof(msInquiryResponse_t) ); uint8_t retval = msDoCommand(&CommandBlockWrapper, Inquiry); Serial.printf("## msDeviceInquiry after do command %u\n", retval ); return retval; }
And now when the inquiry is called, it now returns a data structure of unknown data...Code:msController dataOut (static)31 55 53 42 43 0D 00 00 00 00 02 00 00 80 00 0A 28 00 00 00 40 00 00 00 01 00 00 00 00 00 00 00 msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static): 512 53 44 46 4F 52 4D 41 54 45 44 20 08 00 00 00 00 00 00 00 00 00 00 23 5B AA 4E 00 00 00 00 00 00 ** ???? msDoCommand after msOutCompleted loop msDoCommand after msInCompleted loop msGetCSW before QDT msGetCSW after QDT msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static): 13 55 53 42 53 0D 00 00 00 00 00 00 00 00 ** CSWSIGNATURE
Then we get back the status response the code continues...
@all - With the one change I mentioned above:
.CommandData = {CMDINQUIRY,0x00,0x00,0x00,sizeof(msInquiryRespons e_t),0x00}
One of my Thumbdrives worked...
Then I removed the debug stuff (it still worked...) Then tried with Cruzer 1GB and it hung.. Doing lots of command transfers...
So I am pretty sure it is hung calling in:Code:sController CallbackOut (static) transfer->qtd.token = 1 msController dataOut (static)31 55 53 42 43 7C 00 00 00 00 00 00 00 80 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static): 13 55 53 42 53 7C 00 00 00 00 00 00 00 01 ** CSWSIGNATURE msController CallbackOut (static) transfer->qtd.token = 1 msController dataOut (static)31 55 53 42 43 7D 00 00 00 00 00 00 00 80 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static): 13 55 53 42 53 7D 00 00 00 00 00 00 00 01 ** CSWSIGNATURE
Which if I am looking correct: msTestReady will be sending command data: .CommandData = {CMDTESTUNITREADY, 0x00, 0x00, 0x00, 0x00, 0x00}Code:uint8_t msController::WaitMediaReady() { uint8_t msResult = 0; do { msResult = msTestReady(); } while(msResult); // TODO: Process a Timeout return msResult; }
Where #define CMDTESTUNITREADY 0x00
But if I look in the SCSI command PDF it shows opcode=0
Is write(6) 3.59WRITE (6) command page 248 ... Says obsolete... It is returning error code=1 (fail)...
@all
Wow Kurt you made a lot of progress on this - trying to keep up while isolating the FD issue which I think we have it narrowed to the clock or FD timing issue. Had scope on 3 different boards today watching the transfers - yes it does transfer but noting reading the data properly. Think @tonton81 going to have to check FD timings
@Kurte
Nice detective work.
I saw the ommision you were talking about and changed it on my end as well. I also found the same ommision in msGetMaxLUNS() which has not been implemented yet. The Seagate manual
(page 179) says "The allocation length should be at least 16". I added a define in the MassStorage.h file #define MAXLUNS 16".
This is the modified msReportLUNs() function:
I also modified msDoCommand() to this:Code://--------------------------------------------------------------------------- // Report LUNs uint8_t msController::msReportLUNs(uint8_t *Buffer) { msCommandBlockWrapper_t CommandBlockWrapper = (msCommandBlockWrapper_t) { .Signature = CBWSIGNATURE, .Tag = ++CBWTag, .TransferLength = MAXLUNS, .Flags = CMDDIRDATAIN, .LUN = 0, .CommandLength = 8, .CommandData = {CMDREPORTLUNS, 0x00, 0x00, 0x00, 0x00, 0x00, MAXLUNS, 0x00} }; return msDoCommand(&CommandBlockWrapper, Buffer); }
So far, I am not getting the occasional lockups I was with the original version.Code://--------------------------------------------------------------------------- // Send SCSI Command uint8_t msController::msDoCommand(msCommandBlockWrapper_t *CBW, void *buffer) { uint8_t CSWResult = 0; if(CBWTag == 0xFFFFFFFF) CBWTag = 1; if((CBW->Flags == CMDDIRDATAIN)) { // Data from device queue_Data_Transfer(datapipeOut, CBW, sizeof(msCommandBlockWrapper_t), this); while(!msOutCompleted); // Wait for out transaction to complete. msOutCompleted = false; queue_Data_Transfer(datapipeIn, buffer, CBW->TransferLength, this); while(!msInCompleted); // Wait for in transaction to complete. msInCompleted = false; if((CSWResult = msGetCSW()) != 0) return CSWResult; } else { // Data to device queue_Data_Transfer(datapipeOut, CBW, sizeof(msCommandBlockWrapper_t), this); while(!msOutCompleted); // Wait for out transaction to complete. msOutCompleted = false; queue_Data_Transfer(datapipeOut, buffer, CBW->TransferLength, this); while(!msOutCompleted); // Wait for second out transaction to complete. msOutCompleted = false; if((CSWResult = msGetCSW()) != 0) return CSWResult; } return CSWResult; // Return CSW status }
I also was able to do copies of large files to the same drive at 240MHZ with buffer sizes up to 8192 bytes without the lockups.
I tested with several hard drives and two different Kingston flash drives.
Maybe you can test the modified version and see if it changes anything with your devices.
One question. Are you testing with T3.6 and T4 or just T4?
This is the sketch I used to check the Inquiry function:
Code:#include "uSDFS.h" #include "MassStorage.h" /* * for APL see http://elm-chan.org/fsw/ff/00index_e.html */ #define TEST_DRV 2 // #if TEST_DRV == 0 const char *Dev = "0:/"; // SPI #elif TEST_DRV == 1 const char *Dev = "1:/"; //SDHC #elif TEST_DRV == 2 const char *Dev = "2:/"; //USB #endif FRESULT rc; /* Result code */ FATFS fatfs; /* File system object */ FIL fil; /* File object */ DIR dir; /* Directory object */ FILINFO fno; /* File information object */ msInquiryResponse_t *diskInquiry; msSCSICapacity_t *diskCapacity; void die(const char *text, FRESULT rc) { Serial.printf("%s: Failed with rc=%u.\r\n", text,rc); while(1) asm("wfi"); } void setup() { // put your setup code here, to run once: while(!Serial); Serial.println("Test Drive Inquiry with uSDFS"); Serial.print("Waiting For Device: "); Serial.println(Dev); if((rc = f_mount (&fatfs, Dev, 1))) die("Mount",rc); /* Mount/Unmount a logical drive */ //----------------------------------------------------------- Serial.printf("\nChange drive\n"); if((rc = f_chdrive(Dev))) die("chdrive",rc); // Show stats for Mass Storage Device Serial.printf("\nDo Device Inquiry\n"); if(TEST_DRV == 2) { diskInquiry = getDriveInquiry(); Serial.printf("Removable Device: "); if(diskInquiry->Removable == 1) Serial.printf("YES\n"); else Serial.printf("NO\n"); Serial.printf(" VendorID: %8.8s\n",diskInquiry->VendorID); Serial.printf(" ProductID: %16.16s\n",diskInquiry->ProductID); Serial.printf(" RevisionID: %4.4s\n",diskInquiry->RevisionID); Serial.printf("\nGet Device Capacity Specs\n"); diskCapacity = getDriveCapacity(); Serial.printf(" Sector Count: %ld\n",diskCapacity->Blocks); Serial.printf(" Sector size: %ld\n",diskCapacity->BlockSize); Serial.printf(" Disk Capacity: %ld * %ld Bytes\n",diskCapacity->Blocks, diskCapacity->BlockSize); } Serial.printf("\nDevice Inquiry Test Finished.\n"); } void loop() { delay(1000); }
@wwatson and @KurtE
I just incorporated both yours and Kurt's changes in the lib for two of my thumb drives worked like a charm (Cruzer 2gb and sansdisk 32gb) for the third, a microcenter 1gb thumb drive it failed with the following results, going to try a ssd drive in a bit will let you know how that goes:
Code:Test Drive Inquiry with uSDFS Waiting For Device: 2:/ USB2 PLL running reset waited 6 USBHS_ASYNCLISTADDR = 0 USBHS_PERIODICLISTBASE = 20004000 periodictable = 20004000 port change: 10001803 connect begin reset port change: 18001205 port enabled end recovery new_Device: 480 Mbit/sec new_Pipe enumeration: enumeration: enumeration: Device Descriptor: 12 01 00 02 00 00 00 40 07 13 63 01 00 01 01 02 03 01 VendorID = 1307, ProductID = 0163, Version = 0100 Class/Subclass/Protocol = 0 / 0 / 0 Number of Configurations = 1 enumeration: enumeration: Manufacturer: USB 2.0 enumeration: Product: Flash Disk enumeration: Serial Number: 0ee644744fd53c enumeration: Config data length = 39 enumeration: Configuration Descriptor: 09 02 27 00 01 01 00 80 28 NumInterfaces = 1 ConfigurationValue = 1 09 04 00 00 03 08 06 50 00 Interface = 0 Number of endpoints = 3 Class/Subclass/Protocol = 8(Mass Storage) / 6(SCSI) / 80(Bulk Only) 07 05 01 02 00 02 01 Endpoint = 1 OUT Type = Bulk Max Size = 512 Polling Interval = 1 07 05 82 02 00 02 01 Endpoint = 2 IN Type = Bulk Max Size = 512 Polling Interval = 1 07 05 83 03 40 00 08 Endpoint = 3 IN Type = Interrupt Max Size = 64 Polling Interval = 8 enumeration: msController claim this=20002EE0 Descriptor 4 = INTERFACE msController claim this=20002EE0 09 04 00 00 03 08 06 50 00 07 05 01 02 00 02 01 07 05 82 02 00 02 01 07 05 83 03 40 00 08 endpointType = 2 Descriptor 5 = ENDPOINT Descriptor 5 = ENDPOINT Descriptor 5 = ENDPOINT
@all
Hooked up a 120GB SSD and got the following results (buf: didn't work), drive is formatted to exFat:
Code:Test Drive Inquiry with uSDFS Waiting For Device: 2:/ USB2 PLL running reset waited 6 USBHS_ASYNCLISTADDR = 0 USBHS_PERIODICLISTBASE = 20004000 periodictable = 20004000 port change: 10001803 connect begin reset port change: 18001205 port enabled end recovery new_Device: 480 Mbit/sec new_Pipe enumeration: enumeration: enumeration: Device Descriptor: 12 01 10 02 00 00 00 40 2D 15 78 05 09 05 01 02 03 01 VendorID = 152D, ProductID = 0578, Version = 0509 Class/Subclass/Protocol = 0 / 0 / 0 Number of Configurations = 1 enumeration: enumeration: Manufacturer: JMicron enumeration: Product: External USB 3.0 enumeration: Serial Number: 0123456789CB enumeration: Config data length = 85 enumeration: Configuration Descriptor: 09 02 55 00 01 01 00 80 FA NumInterfaces = 1 ConfigurationValue = 1 09 04 00 00 02 08 06 50 00 Interface = 0 Number of endpoints = 2 Class/Subclass/Protocol = 8(Mass Storage) / 6(SCSI) / 80(Bulk Only) 07 05 81 02 00 02 00 Endpoint = 1 IN Type = Bulk Max Size = 512 Polling Interval = 0 07 05 02 02 00 02 00 Endpoint = 2 OUT Type = Bulk Max Size = 512 Polling Interval = 0 09 04 00 01 04 08 06 62 00 Interface = 0 Number of endpoints = 4 Class/Subclass/Protocol = 8(Mass Storage) / 6(SCSI) / 98(UAS) 07 05 01 02 00 02 00 Endpoint = 1 OUT Type = Bulk Max Size = 512 Polling Interval = 0 04 24 01 00 07 05 82 02 00 02 00 Endpoint = 2 IN Type = Bulk Max Size = 512 Polling Interval = 0 04 24 02 00 07 05 83 02 00 02 00 Endpoint = 3 IN Type = Bulk Max Size = 512 Polling Interval = 0 04 24 03 00 07 05 04 02 00 02 00 Endpoint = 4 OUT Type = Bulk Max Size = 512 Polling Interval = 0 04 24 04 00 enumeration: msController claim this=20002EE0 Descriptor 4 = INTERFACE msController claim this=20002EE0 09 04 00 00 02 08 06 50 00 07 05 81 02 00 02 00 07 05 02 02 00 02 00 09 04 00 01 04 08 06 62 00 07 05 01 02 00 02 00 04 24 01 00 07 05 82 02 00 02 00 04 24 02 00 07 05 83 02 00 02 00 04 24 03 00 07 05 04 02 00 02 00 04 24 04 00 endpointType = 2 numendpoint=2 endpointIn=81 endpointOut=2 packet size in (msController) = 512 packet size out (msController) = 512 polling intervalIn = 0 polling intervalOut = 0 new_Pipe new_Pipe Descriptor 5 = ENDPOINT Descriptor 5 = ENDPOINT Descriptor 4 = INTERFACE Descriptor 5 = ENDPOINT Descriptor 36 = ??? Descriptor 5 = ENDPOINT Descriptor 36 = ??? Descriptor 5 = ENDPOINT Descriptor 36 = ??? Descriptor 5 = ENDPOINT Descriptor 36 = ??? control CallbackIn (msController) 00 00 00 00 00 00 00 00 control CallbackIn (msController) 00 00 00 00 00 00 00 00 msController CallbackOut (static) transfer->qtd.token = 0 msController dataOut (static) msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static) msController CallbackOut (static) transfer->qtd.token = 0 msController dataOut (static) msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static) msController CallbackOut (static) transfer->qtd.token = 0 msController dataOut (static) msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static) msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static) msController CallbackOut (static) transfer->qtd.token = 0 msController dataOut (static) msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static) msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static) msController CallbackOut (static) transfer->qtd.token = 0 msController dataOut (static) msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static) msController CallbackOut (static) transfer->qtd.token = 0 msController dataOut (static) msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static) msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static) msController CallbackOut (static) transfer->qtd.token = 0 msController dataOut (static) msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static) msController CallbackOut (static) transfer->qtd.token = 0 msController dataOut (static) msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static) msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static) Mount: Failed with rc=13.
@all
Using the same SSD but with a startech sata/ide converter I pretty much get the same results as in previous post:
Code:Test Drive Inquiry with uSDFS Waiting For Device: 2:/ USB2 PLL running reset waited 6 USBHS_ASYNCLISTADDR = 0 USBHS_PERIODICLISTBASE = 20004000 periodictable = 20004000 port change: 10001803 connect begin reset port change: 18001205 port enabled end recovery new_Device: 480 Mbit/sec new_Pipe enumeration: enumeration: enumeration: Device Descriptor: 12 01 10 02 00 00 00 40 75 1F 11 06 06 00 04 05 06 01 VendorID = 1F75, ProductID = 0611, Version = 0006 Class/Subclass/Protocol = 0 / 0 / 0 Number of Configurations = 1 enumeration: enumeration: Manufacturer: doesn't want to copy rest
@mjs513 and @wwatson and others...
Wonder if your 1GB is hanging the same way as my 1GB...
Note: I have additional debug stuff turned on:
With this you can see all of the input and output stuff going on. And in my case it was hanging in the loop for media available (WaitMeidaReady)Code:void msController::new_dataOut(const Transfer_t *transfer) { uint32_t len = transfer->length - ((transfer->qtd.token >> 16) & 0x7FFF); println("msController dataOut (static)", len, DEC); print_hexbytes((uint8_t*)transfer->buffer, (len < 32)? len : 32 ); msOutCompleted = true; // Last out transaction is completed. } void msController::new_dataIn(const Transfer_t *transfer) { uint32_t len = transfer->length - ((transfer->qtd.token >> 16) & 0x7FFF); println("msController dataIn (static): ", len, DEC); print_hexbytes((uint8_t*)transfer->buffer, (len < 32)? len : 32 ); if (len >= 4) { uint32_t l = *(uint32_t*)transfer->buffer; if (l == CBWSIGNATURE) println("** CBWSIGNATURE"); else if (l == CSWSIGNATURE) println("** CSWSIGNATURE"); else println("** ????"); } msInCompleted = true; // Last in transaction is completed. }
Yesterday I was playing iwth the WaitMediaReady to maybe call msRequestSense if the mediaAvailable call fails... To maybe see what the failure codes are...
Comments embeded ()
Now to look up what the response codes are...Code:(Here we ask for the media ready) msController CallbackOut (static) transfer->qtd.token = 1 msController dataOut (static)31 55 53 42 43 35 00 00 00 00 00 00 00 80 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (Response - ends with 01 - fail) msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static): 13 55 53 42 53 35 00 00 00 00 00 00 00 01 ** CSWSIGNATURE (Now ask for request sense) msController CallbackOut (static) transfer->qtd.token = 1 msController dataOut (static)31 55 53 42 43 36 00 00 00 12 00 00 00 80 00 06 03 00 00 00 12 00 00 00 00 00 00 00 00 00 00 00 msController CallbackIn (static) transfer->qtd.token = 0 (response of sense) msController dataIn (static): 18 70 00 02 00 00 00 00 0A 00 00 00 00 3A 00 00 00 00 00 ** ???? msDoCommand after msOutCompleted loop msDoCommand after msInCompleted loop msController CallbackIn (static) transfer->qtd.token = 0 msController dataIn (static): 13 55 53 42 53 36 00 00 00 00 00 00 00 00 ** CSWSIGNATURE (I had the waitMedia also dump out the response)... WaitMediaReady RSP:70 00 02 00 00 00 00 0A 00 00 00 00 3A 00 .... Repeats for ever or until I unplug
@KurtE
Not even getting that far - hanging before that on endpoints (BTW - Hot swapping works)
Either that or I am editing the wrong file? (masstoragedriver.cpp)Code:Test Drive Inquiry with uSDFS Waiting For Device: 2:/ USB2 PLL running reset waited 6 USBHS_ASYNCLISTADDR = 0 USBHS_PERIODICLISTBASE = 20004000 periodictable = 20004000 port change: 10001803 connect begin reset port change: 18001205 port enabled end recovery new_Device: 480 Mbit/sec new_Pipe enumeration: enumeration: enumeration: Device Descriptor: 12 01 00 02 00 00 00 40 07 13 63 01 00 01 01 02 03 01 VendorID = 1307, ProductID = 0163, Version = 0100 Class/Subclass/Protocol = 0 / 0 / 0 Number of Configurations = 1 enumeration: enumeration: Manufacturer: USB 2.0 enumeration: Product: Flash Disk enumeration: Serial Number: 0ee644744fd53c enumeration: Config data length = 39 enumeration: Configuration Descriptor: 09 02 27 00 01 01 00 80 28 NumInterfaces = 1 ConfigurationValue = 1 09 04 00 00 03 08 06 50 00 Interface = 0 Number of endpoints = 3 Class/Subclass/Protocol = 8(Mass Storage) / 6(SCSI) / 80(Bulk Only) 07 05 01 02 00 02 01 Endpoint = 1 OUT Type = Bulk Max Size = 512 Polling Interval = 1 07 05 82 02 00 02 01 Endpoint = 2 IN Type = Bulk Max Size = 512 Polling Interval = 1 07 05 83 03 40 00 08 Endpoint = 3 IN Type = Interrupt Max Size = 64 Polling Interval = 8 enumeration: msController claim this=20002F00 Descriptor 4 = INTERFACE msController claim this=20002F00 09 04 00 00 03 08 06 50 00 07 05 01 02 00 02 01 07 05 82 02 00 02 01 07 05 83 03 40 00 08 endpointType = 2 Descriptor 5 = ENDPOINT Descriptor 5 = ENDPOINT Descriptor 5 = ENDPOINT DIES AT THIS POINT
Actually sort of interesting. In particular this one shows 3 end points (The others show 2)
If you look at: bool msController::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len)Code:07 05 01 02 00 02 01 Endpoint = 1 OUT Type = Bulk Max Size = 512 Polling Interval = 1 07 05 82 02 00 02 01 Endpoint = 2 IN Type = Bulk Max Size = 512 Polling Interval = 1 07 05 83 03 40 00 08 Endpoint = 3 IN Type = Interrupt Max Size = 64 Polling Interval = 8
It is assuming that first end point is In and the second endpoint is out, which in this case is reversed, so then the code:
Will fail and it won't claim the device...Code:if ((endpointIn & 0xF0) != 0x80) return false; // must be IN direction if ((endpointOut & 0xF0) != 0x00) return false; // must be OUT direction
The code probably needs to walk the number of end points, and find the IN and the OUT. (The 80 bit).
The Joystick claim code I believe has the stuff to walk through the endpoints to find the ones it want's ...
@KurtE
I noticed that it was showing 3 endpoints which was kind of strange, like you said.hope its portable enough to transfer.The Joystick claim code I believe has the stuff to walk through the endpoints to find the ones it want's ...
Should be easy enough: Just setup index to first endpoint in buffer set index or like for IN/OUT endpoints in code to something like 0xff , increment by the size (7), and then check the end point, if it is a Bulk OUTPUT, remember it's index (OUT), and if it is input bulk remember it's index... If we ran through all of the end points and either of them is still 0xff then error...
Then change code that used fixed index for fields of it to use saved index plus offset...
Things like: uint32_t sizeIn = descriptors[13] | (descriptors[14] << 8);
would look more like: uint32_t sizeIn = descriptors[in_endpoint_offset+4] | (descriptors[in_endpoint_offset+5] << 8);
Depending on what you save as the index...
EDIT: Should I take a crack at it?
@mjs513 and @wwatson - follow on to previous post... Maybe something like:
I may not be printing out everything here as before, but most of it...Code:bool msController::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len) { println("msController claim this=", (uint32_t)this, HEX); // only claim at interface level if (type != 1) return false; if (len < 9+7+7) return false; // Interface descriptor + 2 endpoint decriptors print_hexbytes(descriptors, len); uint32_t numendpoint = descriptors[4]; if (numendpoint < 1) return false; if (descriptors[5] != 8) return false; // bInterfaceClass, 8 = MASS Storage class if (descriptors[6] != 6) return false; // bInterfaceSubClass, 6 = SCSI transparent command set (SCSI Standards) if (descriptors[7] != 80) return false; // bInterfaceProtocol, 80 = BULK-ONLY TRANSPORT #if 1 uint8_t desc_index = 9; uint8_t in_index = 0xff, out_index = 0xff; println("numendpoint=", numendpoint, HEX); while (numendpoint--) { if ((descriptors[desc_index] != 7) || (descriptors[desc_index+1] != 5)) return false; // not an end point if (descriptors[desc_index+3] == 2) { // Bulk end point if (descriptors[desc_index+2] & 0x80) in_index = desc_index; else out_index = desc_index; } desc_index += 7; // point to next one... } if ((in_index == 0xff) || (out_index == 0xff)) return false; // did not find end point endpointIn = descriptors[in_index+2]; // bulk-in descriptor 1 81h endpointOut = descriptors[out_index+2]; // bulk-out descriptor 2 02h println("endpointIn=", endpointIn, HEX); println("endpointOut=", endpointOut, HEX); uint32_t sizeIn = descriptors[in_index+4] | (descriptors[in_index+5] << 8); println("packet size in (msController) = ", sizeIn); uint32_t sizeOut = descriptors[out_index+4] | (descriptors[out_index+5] << 8); println("packet size out (msController) = ", sizeOut); packetSizeIn = sizeIn; packetSizeOut = sizeOut; uint32_t intervalIn = descriptors[in_index+6]; uint32_t intervalOut = descriptors[out_index+6]; println("polling intervalIn = ", intervalIn); println("polling intervalOut = ", intervalOut); datapipeIn = new_Pipe(dev, 2, endpointIn, 1, packetSizeIn, intervalIn); datapipeOut = new_Pipe(dev, 2, endpointOut, 0, packetSizeOut, intervalOut); #else if (descriptors[10] != 5 || descriptors[17] != 5) return false; // Must have bulk-in and bulk-out endpoints uint8_t endpointType = (descriptors[12] | descriptors[19]) & 0x03; println("endpointType = ",endpointType); endpointIn = descriptors[11]; // bulk-in descriptor 1 81h endpointOut = descriptors[18]; // bulk-out descriptor 2 02h if ((endpointIn & 0xF0) != 0x80) return false; // must be IN direction if ((endpointOut & 0xF0) != 0x00) return false; // must be OUT direction println("numendpoint=", numendpoint, HEX); println("endpointIn=", endpointIn, HEX); println("endpointOut=", endpointOut, HEX); uint32_t sizeIn = descriptors[13] | (descriptors[14] << 8); println("packet size in (msController) = ", sizeIn); uint32_t sizeOut = descriptors[20] | (descriptors[21] << 8); println("packet size out (msController) = ", sizeOut); packetSizeIn = sizeIn; packetSizeOut = sizeOut; uint32_t intervalIn = descriptors[15]; uint32_t intervalOut = descriptors[22]; println("polling intervalIn = ", intervalIn); println("polling intervalOut = ", intervalOut); datapipeIn = new_Pipe(dev, 2, endpointIn, 1, packetSizeIn, intervalIn); datapipeOut = new_Pipe(dev, 2, endpointOut, 0, packetSizeOut, intervalOut); #endif datapipeIn->callback_function = callbackIn; datapipeOut->callback_function = callbackOut; msOutCompleted = false; msInCompleted = false; deviceAvailable = true; return true; }