-
Notifications
You must be signed in to change notification settings - Fork 272
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"Error setting up the device" on QEMU #209
Comments
The LUN size is queried using a I have seen this error as well but I did not find any solution except replugging the device (#95 (comment)) |
This might be related (page 155): https://www.seagate.com/files/staticfiles/support/docs/manual/Interface%20manuals/100293068j.pdf I'll see if I can implement and test the 16 byte command. |
Not sure if that is the problem here. Every device should be able to support the READ CAPACITY(10) command. Also I would assume that it responds with an error and not time out. What does the version field of the SCSI Inquiry Response say? |
Also, after READ CAPACITY (10) fails, it seems that INQUIRY also subsequently fails on new executions. |
Ok I see. That sounds more like the error I mentioned earlier. Some people suggested that sleeping for a couple of seconds helped in between sending commands to the device. |
What might also be worth trying if you can get total commander or USB Media explorer or similar running. Then we know that it has to work somehow... |
Could it be worth implementing something similar to Linux sd driver's spinup sequence? https://github.com/torvalds/linux/blob/master/drivers/scsi/sd.c#L2066 It does seem to include some quirks for weird USB flash drives which actually do not require to be spun up. It looks that in this particular case it simply waits one second between TEST UNIT READY and returning (and then it goes on with READ CAPACITY (16) which falls back to READ CAPACITY (10)). Reimplementing the whole thing in Kotlin might be a big effort considering that it considers a lot of different cases. For now I'll see what happens if I |
Nope, it still fails with the 1 sec delay and READ CAPACITY 16 |
Alright, in order to capture the specific case of the emulated USB drive on Wireshark, I did a qemu-inception: I booted a GNU/Linux VM with the emulated USB drive attached, then booted the Android VM inside of it and connected the emulated drive as a host USB device. Wireshark pcap: qemu-usb-capture.pcapng.gz If you check the timestamps you can clearly see when the app was started. I'll look into all this info, in the meantime I'll just drop this here in case it might be useful. |
I think I found the issue. Apparently, the device is STALLing the transfer This library apparently works around this by simply clearing the fault and retrying up to 5 times. I'm not sure how to do it on Android, but I will look into it in the next few days. |
Hey there, I had a look at the file. But I am not sure what exactly is happening.
For BULK transfer first and then also for control transfer. What that really means I do not know. Did you have time to try Total Commander? |
For some reason Wireshark does not parse the bulk in transfers from device to host to USBMS protocol frames. |
Sorry did not see your latest comment. Clearing the halt seems to be fairly low level and might not be supported in Android. Maybe releasing the USB interface/device altogether can help here. At least it sounds different from #95 (comment) so there is a chance that this might be possible. Thanks for the support I really appreciate it! |
That doesn't seem to be an error. See this capture from a valid communication (with the kernel):
https://www.kernel.org/doc/html/latest/driver-api/usb/error-codes.html I also noticed that the interface is set to 0xFFFF in our requests, which also seems to be the reason WireShark is not parsing the payloads as they look just fine to me.
No, I haven't purchased it. |
I think Total Commander with the USB plugin is free (or at least some test version) |
Reading this it seems to be just a matter of sending a controlTransfer command: https://developer.electricimp.com/resources/usberrors However, checking libusb's source code it seems it can be done with an ioctl: Which we can do, given that UsbCommunication exposes the underlying file descriptor (which can also be passed to libusb eventually) |
I see, so this actually seems to indicate that the endpoint is stalled currently and not available for communication. |
This might be convenient because sending a controlTransfer is possible within the Android API.
Which also means we might be able to just use libusb :D |
I can confirm it works with Total Commander. ... a little reverse engineering never killed nobody 🤷♂️
That's what I was thinking. I was also thinking that with enough infrastructure and wrappers in place we might just be able to link Linux's Also this would mean that GPLv2 code would have to be embedded in this Apache-licensed library, which would require a relicensing to GPLv2 or GPLv3 unless I missed something. EDIT: libusb is also GPL-licensed |
Ok awesome, then we just need to figure out what exactly they do differently. I feel like this might a fairly big change especially designing it in a way that we can easily merge upstream back to libaums every now and then. That is why I would suggest go for the control transfer first and then maybe try |
libusb even has a readme for Android https://github.com/libusb/libusb/tree/master/android |
That's the hardest thing. I quickly checked how all the components talk to each other and it's quite messy, it's likely not a matter of copying files and wrapping them.
Yep, but they don't provide real JNI wrappers and we would have to write them on our own. We'd need to see how bad Android's API gets in our way, because if we need just a bunch of ioctls we might just as well duct-tape them onto the API. |
I opened the USB plugin for Total Commander on Jadx and it looks like it's completely unobfuscated. Also there are strings that refer to libusb, but I haven't seen anything JNI related so it might be just bad naming. Anyway, that's it for me for today, I should really be doing other things right now. I should free in two weeks and I will gladly look deeper into it :) |
Interesting, if that is really the case we might even be able to ask them for the source code, given they linked libusb statically (LGPL). |
I did some RE on the TotalCommander plugin, I'm taking messy notes here: https://md.depau.eu/ZkErsTYJQLC7AQJhcyn7VA (editable if you wanna add comments) It looks like the culprit is sending that reset control sequence whenever communication fails. Also, it looks like it sends a get sense command whenever anything looks weird during setup. It seems that the libusb references assume that Android uses it underneath; the app does not include it. I haven't checked whether it actually does. In the weekend or next week I'm gonna check a bunch of other things then see if I can patch the library ;) |
Hey there, it seems that your note server is down :/ |
Hi, thanks for catching that, I'm taking it back up. EDIT: docker is throwing a fit, this is gonna take a while, the whole server is borked lol |
btw, I talked to the developer of Nexus Media Importer a couple of years back:
His reply Yes, I'm painfully aware of #1. According to the Mass Storage spec, you should be able
Maybe this helps at some point :D |
Thanks for pointing that out. I think I read about the Windows behavior somewhere. BTW libusb does have a function to perform port reset. As I said in the other thread I won't be working on this until the next year, but I did start tinkering on it last time I got the chance, I'll see if I can find some diffs in the meantime. EDIT: nope, can't find it :/ |
Here's what I use to run Android on QEMU, as discussed in #242: https://gist.github.com/Depau/77b06b18320f511db8fdae58e8bceead Note that I'm using Android v8.1-r2, not the latest one, I'll test it 9 too. |
an inquiry response at some point is all I can get :/ |
When using genymotion and a real usb pen drive I get this
Maybe there is also some protocol version libaums does not support which is the problem |
There is indeed another protocol and that is UAS which should be what is used by hard drive caddies, IDK how it's different from regular mass storage devices protocol. QEMU can emulate that too. Anyway, is that different from what you get if you connect it directly to an Android device? |
I meant that the spc/sbc version (scsi block commads) is different, but I did some research and libaums is only using the bare minimum which should be supported by every device. The only thing I noticed is that with spc>=5 there is a |
For what it's worth, here it says:
I haven't read the specifications not I can test it at the moment so I don't know if this may actually be useful, I'll leave it here just in case. |
I've got some free time to work on libaums 🎉 (but just for a few weeks) I'll try to work on QEMU testing again, hopefully it will also resolve the issues on real devices as we predicted. |
I would have tried to troubleshoot this issue on my own but I won't have a lot of time for it in the next days, I'll leave it here in case you do have some time.
The issue doesn't look like a regression as it doesn't work with any build of EtchDroid (both with my old fork of libaums and with upstream + wrapper) but also with your sample app.
As I mentioned in #206 I wasn't able to emulate a USB drive using the standard Android emulator, so I just used stock QEMU with Android-x86.
Steps to get the emulator running:
Set up using QEMU builds
cd
into it ([rpm]/bliss-something
)unsquashfs
d the system image in order to remove some bloatIn order to run the emulator with an emulated USB drive, I patched the script that comes with the Ax86 RPM builds: https://gist.github.com/Depau/6c0ccc7377949c68bb30608bef87b9cd
The script expects the disk images to be in the current working directory, so
cd
into the android image directory and run it.Set up using ISO images
When you're done installing, remove
-cdrom
This produces an emulated device that looks very close to my real USB drive:
lsusb -v (qemu)
lsusb -v (real, known working)
All Android-x86 builds I tested run with network ADB already enabled on port 5555, so you should be able to
adb connect localhost 5555
and install the test app to reproduce it.Logcat with stack trace
From what I've seen, the issue occurs when libaums tries to get the lun size;
bulkInTransfer
times out returning -1, no errno.Note that I've also experienced the issue on EtchDroid with known working USB drives/Android versions, for example when re-using the same USB drive after the app was stopped for whatever reason without reattaching the USB drive and killing the app.
The text was updated successfully, but these errors were encountered: