Skip to content
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

Sniffed Windows USB traffic for hid-tminit #3

Closed
scarburato opened this issue Aug 7, 2020 · 13 comments
Closed

Sniffed Windows USB traffic for hid-tminit #3

scarburato opened this issue Aug 7, 2020 · 13 comments

Comments

@scarburato
Copy link

Do you still have the capped traffic you used to get the USB controller request to initialize your Thrustmaster wheel? If so can you share them?

Would be nice to understand how the Windows's driver is able to understand which wheel really is the generic 044f:b65d so that we can write a single and polyvalent init driver for the Thrustmaster wheels. I'm not sure if it's even possible (is possible on Windows to have multiple Thrustmaster models at the same time?)

You can find my capped traffic from a T150 here, the control urb is the packet n° 210, it's a Wireshark file.

Maybe the correct title for this «issue» should be something like «Polyvalent hid-tminit»

@Kimplul
Copy link
Owner

Kimplul commented Aug 7, 2020

Yeah, I added the traffic to the testing branch, here.

I had a quick look through your file and it seems to be really different to mine, how did you capture your traffic if you don't mind me asking?

@scarburato
Copy link
Author

I didn't apply any filter while capping, so the packets from the wheel (device 1.23) are mixed with packets from the USB controller and the USB hub. Anyway I've added an already filtered file here

To cap the traffic I've created a VirtualBox vm with Windows 10 and used the USB pass through to expose to the guest the wheel. Wireshark was running on the host (Ubuntu) when I attached the wheel

@Kimplul
Copy link
Owner

Kimplul commented Aug 7, 2020

Okay, I think the VirtualBox vm would explain it, my captures were done with qemu. I believe they have their own usb translation systems. Anycase, I actually have a T150, but it's motors don't really spin properly anymore. I tried it out real quick and I got a capture that looks like this.

Virtual machines matter, as it would seem.

@Kimplul
Copy link
Owner

Kimplul commented Aug 7, 2020

Quick update, I really don't have the time to start testing out anything quite yet, but the main differences between my captures I've seen so far is in the packets no. 22 and 24. None of the values that are returned seem like obvious ID's, but packet 22 is maybe the closest to one that I can see.

From what I can tell,

T300RS = 56001FFF
T150   = 56050000

@scarburato
Copy link
Author

scarburato commented Aug 7, 2020

Not sure...

In the list of issues of this repo, you can find pcaps for the various model. If you open them and apply the filter usb.setup.bRequest == 0x56 select the packet, remove the filter and see the device's response (usually the very next packet) to that request you can see that each model of wheel responses with their own 4 bytes of data:

Model pcap CONTROL response data Value to switch
T500RS url 562b0000 0002
TMX url 56070000 0x0001, 0x0007
T300RS url 56190000 0x0002

It seems that the T300RS is reporting a different value, but maybe it could be an older hardware revision. Unfortunately I can't compare the T150RS because the link to that cap is dead.

In next days I'll try to investigate further

@scarburato
Copy link
Author

scarburato commented Aug 8, 2020

News:

The model cannot be the response to request 0x56, that response is somehow related to the firmware version. I've upgraded my firmware from version 11 to 21 and now the wheel answers with 56150000 instead of 56050000 (cap). Maybe the second byte is related to the firmware version because 0x15 == 21 but 0x05 == 5 != 11, so idk.

My new guess is the control packet with usb.setup.bRequest == 73, is suspiciously near the control packet used to switch the wheel mode and the response of the wheel seems to remain the same after the upgrade

Model Response bytes +6, +7
T150 (same both my and yours) 0x49002100000006030000000000000000 0x0603
T300 (yours) 0x49000301010006021300000005010000 0x0602
T300 (cap from gitlab) 0x49002100000006020000000000000000 0x0602
TMX 0x4700410000000704 0x0704
T500 0x4700030000000200 0x0200

It would be a little be tricky to compare 128bit constants but nothing impossible, we can store them in two uint64_t and for the wheels with 64bit codes we can simply shift left the bits by 64bits.

The only thing that seems a little bit off is that 128bit is a huge number to store the model ID, one could think that is the serial number but it's also the same between my T150 and yours but the T300 is different between yours and the one found on Gitlab, so irdk...

Or maybe they are only the two bytes starting at offset +6, so 0x0602 for the T300RS and 0x0603 for the T150.

In the next days I'll continue to do further investigations. I've asked if someone has other caps from their wheels on an issue on Gitlab let's hope kind person provides them so that maybe comparing caps from multiple wheel will reduce the differences enough to find the incriminated packets

EDIT: Now I have a doubt, maybe I took the first capture when I was running firmware 5 because I remember that some time ago I upgraded the wheel, but I do not remember exactly when. May could you verify with firmware is your wheel using?

@Kimplul
Copy link
Owner

Kimplul commented Aug 8, 2020

Sorry, I just moved apartments and I left the T150 at my parent's. If it's any help I checked that it had the newest firmware when I did the captures yesterday.

@scarburato
Copy link
Author

I've decided to take the chances and I wrote an automatic init driver based on the information available to me at the moment.

I hope I did Bingo!, if it is not the case it should not be difficult to re-adapt the driver to generate another type of request

@Kimplul
Copy link
Owner

Kimplul commented Aug 15, 2020

Hey there, just tested it out with my wheel, unfortunately it errors out with

URB to get model id failed with error -32

I took a pcapng, here's the data:
https://github.com/Kimplul/hid-tmff2/blob/pcaps/unified_init.pcapng

I remember getting similar return values when I initially started this project. I believe the issue was that I had to send out some commands to sort of "pre-initialize" the device. I'm guessing you've tested the repo with the T150, but here's apparently one more difference between the different wheels.

I can't quite remember if the setup_arr I have in my init.h were the commands that fixed the original issue, but I'll check it out.

EDIT: Nope, they weren't the commands we're looking for. I'll check other possibilities.

@scarburato
Copy link
Author

Thanks for trying out my driver, error 32 is broken pipe. The error is described as «The pipe type specified in the URB doesn't match the endpoint's actual type.».

Probably I should use usb_rcvctrlpipe instead of usb_sndctrlpipe when preparing the URBs at line 172 and at line 78 because they are control in not control out; maybe the t150 or my USB controller are more clement when facing wrong requests

@Kimplul
Copy link
Owner

Kimplul commented Aug 15, 2020

Oh yeah, you're right. Sorry, for some reason I didn't think to check what the error code means.
I changed it and the wheel initializes. Still get the error

URB to change wheel mode failed with error -32

but I suspect that's because the T300RS init is rather violent. Also, it happens to crash my VM.

EDIT: yep, unfortunately seems to be fairly reproducible without tweaking. Somwhat luckily, my setup_arr "fix" still works and prevents a crash. Only problem is, I have no idea if it works for other wheels.

EDIT UPON EDIT: I forked your repo and made the changes I had to do to get the T300RS working.
https://github.com/Kimplul/hid-tminit
If it turns out it works for the T150 (and if we can get someone who has a T500RS to test it) I can upen up a pull request.

@scarburato
Copy link
Author

but I suspect that's because the T300RS init is rather violent

I suspect it's more a USB controller thing, because both wheels (the t150 and the t300) violate the USB protocol by not responding back to the last control in packet (mine returns with status EPROTO, protocol error); anyway this is the fault of Thrustmaster's engineers, maybe in this case the best thing to do is to remove the error check in the last handler.

0k, I've tried it and it works fine just a few things to fix

  1. As Torvalds ﷺ commanded us the code should be indented with tabs 8 columns wide, not tabs. If, in the future, someone wants to include this module in the Kernel he will find the code, at least partially (I didn't completely follow His directives 😅), correctly formatted
  2. In tminit_interrupts() the send_buf is never freed from memory; also it should check if the alloc returned a NULL pointer (no more memory available) and in that case leave the function without trying to dereferencing the NULL pointer
  3. tminit_preinit_handler() is never used

For the rest it looks fine to me, when you want you can open a pull request

@Kimplul
Copy link
Owner

Kimplul commented Aug 16, 2020

Closing as @scarburato has set up a new init driver over at https://github.com/scarburato/hid-tminit, will be using that one instead of this project's own.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants