Page 1 of 8

Reverse Engineering the Force Feedback Pro

Posted: Mon Jan 09, 2012 4:19 pm
by cal
I have been working a while in an attempt to put Force Feedback into my FFP with this adapter in Windows 7. My primary goal is to get sufficient FFB support to play at least the effects in IL2 (for which I now have to dual boot to XP to get the FFB). I have the 3DPVert working very nicely on a Tweeny now as a non-FFB joystick in Windows 7 (thank you!).

Secondary goal is to retire my separate self-made ATmega168-based USB-joystick and move the controllers under the 3DPVert, so I can have joystick and my home made rudder pedals and elevator and rudder trim potentiometers to a single device under Windows instead of two separate ones. Less boxes on the table and less problems with joystick IDs changing every now and then when having multiple devices. I think this should be quite a simple task of adding ADC, HID descriptors and report buildup - but FFB interests me more since I do not have it working in Win7.

I know what Grendel said earlier about not having FFB due too much work to reverse engineer the MIDI protocol etc.. I think it is time for others to continue where Grendel brought us!

I've studied some of the USB specs on FFB a bit and there does not seem to be any major showstoppers at least for the level of FFB support I'm planning. I've found a few examples on such HID descriptors on other forums. IL2 default FFB effects seem to contain only a spring, periodical and constant effects with some envelopes. And if it comes to that, I could easily modify the IL2's FFB effects for simpler ones with FEdit. But, before going there, I want a proof of concept on getting the stick to answer to FFB data in general while being connected via 3DPVert.

At the moment I have decoded most of the MIDI protocol essentials by tapping into the Joystick's pin 12 with a Tweeny's USART listening the traffic to the Joystick while using FEdit in XP and having the stick in the game port. I soldered the GND+MIDI pins out of the stick on a separate connector to get easy access to the MIDI channel. I can make this information public if someone's interested - latest if and when I can see this thing flying (other than out of the window, that is). It's not that complex protocol after all at least on the basics.

I even succeeded in modifying the 3DPVert code to move the Button4 to another pin so that Tweeny's USART TX-pin would be free - for sending MIDI data to the stick. So, next step was to start pushing some FFB data to the stick.

Now, here's where I've hit the wall. The stick does not respond to the FFB data I'm sending to it. It is like it doesn't even want to hear anything from the pin 12. Even the initialization routine FEdit does that disables the auto-centering spring does nothing. After reviewing several MIDI circuits, it sounds that AVR should be able to drive the MIDI directly from the TX-pin (with a protective 220ohm resistor in series for added safety - tried a few alternative circuits but with no better results). I've recorded the basic data being sent to the stick from FEdit and try to repeat that. (I first attempted to send it directly from the 3DPVert's TX-pin, but couldn't for some reason to make it send anything so I put another Tweeny connected only to the stick's pin 12 that is capable of sending data - I checked that it does by reading what it sends and it looks fine.)

Here's the question:
Grendel (or anyone else more familiar with the 3DPVert's code and the FFP stick), can you tell if the FFB has somehow been "disabled" (or not "enabled) in a way that the 3DPVert handshakes with the stick? Could it be that the way 3DPVert initializes the stick, the stick is in some kind of "wrong mode"?

There is still one confirmation test I should run to check which direction the problem lies, but it involves opening up the stick again and cutting its MIDI wire to disconnect it from the game port altogether and getting the Tweeny in between - so I could connect the stick to game port while having full electrical control on the MIDI wire. The far shot, simply connecting the Tweeny's TX-pin in parallel with the game port's pin 12 didn't work - as expected...

(I have a masters on EE and work as a professional programmer with years of hobby time on both areas. So, if you have ideas on any level - let me hear it. I think I can take even the nasty technical details - and if not, I'll learn to get it.)

Re: USB Converter for MS Sidewinder 3DPro, PP, and FFP

Posted: Wed Jan 11, 2012 3:51 pm
by ra9na
Today I had the exact same idea!
I really would like to revive my FFB! This thing is an amazing thing of HW and it would be very nice, to play the latest games with it...
I would really like to help you as best I can... So if you don't mind you could share your findings as detailed as possible. At first I would like to build kind of an adapter so I can plug in the joystick while having the MIDI RX pin connected to an oscillator.
Something that might work (but I doubt it): writing a nice mail to Microsoft an ask for some documentation on the protocol for the FF part...
http://answers.microsoft.com/en-us/wind ... b599b31bf5 Someone had the same question some time ago, but if we keep posting, perhaps something will happen =) ?
Oh and btw: I am also an EE from Germany...

Re: USB Converter for MS Sidewinder 3DPro, PP, and FFP

Posted: Thu Jan 12, 2012 11:39 am
by snoopy
Did Gren get back to you?

He might not be aware of your questions... try a PM pointing him here.

Re: USB Converter for MS Sidewinder 3DPro, PP, and FFP

Posted: Thu Jan 12, 2012 5:05 pm
by Grendel
Hm, no I didn't see the question. Weird.

I don't have a definitive answer, sorry. My guess would be that the FF interface is isolated from the OverDrive protocol (since FF was added later), all FF related actions are probably driven via MIDI channel 6. What exactly makes up these commands I don't know and would be subject to reverse engineering. Another place to look are older DirectX/DirectInput SDKs, chances are there are some notes about it. As for the USB side of things, check out the document "Device Class Definition for Physical Interface Devices (PID)" V1 (pid1_01.pdf, should be inside this archive.)

I did revive that thread on MS Answers, I'd suggest that everyone interested in this posts there as well :)

Re: USB Converter for MS Sidewinder 3DPro, PP, and FFP

Posted: Sat Jan 14, 2012 5:14 pm
by cal
Some progress, but still a critical bit is missing to go forward. I cut the MIDI-wire on the joystick and took both end out of it, so that I can have the stick on actual game port and still have full control on the MIDI-line to the stick with a Teensy.

I can now consistently control the effects on the joystick with a Teensy. There seemed to be some timing related issues i.e. that after certain commands, the joystick needs to be given a bit time to process them. I can start and stop a few pre-recorded effects and disable and enable the auto-center spring effect on the stick.

The problem still is that I need to get the stick "in the mood" to get my MIDI-commands. With the 3DPVert, the stick is NOT "in the mood". Actually, the stick is not "on the mood" by default even when it is connected to a real game port.

When connected to a real game port, opening FEdit in XP seems to do the trick. After that I can send commands and the joystick replies as expected. If I issue a command to re-enable the default auto-center spring effect as of going "out of application scope" I have to restart FEdit to put the stick back to the "mood" to receive commands.

The funny thing is that FEdit (or any application using FFB) can put the stick to the mood even if the MIDI-wire is completely disconnected. Which means, that the game port is talking to the stick also on FFB-related matters (at least this "mood switch") using the conventional pins instead of MIDI.

I believe this test confirms my earlier hunch, that the joystick is in a wrong "mode" and that's why it doesn't take the FFB commands in.

Does anyone have tools or know-how at hand to analyze what happens in the game port outside the MIDI-pin when you start FEdit or other FFB-using apps?

I think there is something previously unnoticed or overlooked that would provide the key to enabling FFB with 3DPVert.

Re: USB Converter for MS Sidewinder 3DPro, PP, and FFP

Posted: Mon Jan 16, 2012 5:28 am
by cal
After reading the MS patent description about bidirectional data transfer mechanism used between the game port and joystick, I am making a guess that the "Go to FFB Mode"-command I'm missing is one of the commands sent to the joystick using the "interrupts" in the Overdrive protocol.

If I understood the patent description correctly, there is only a limited number of commands that can be sent this way and since "SendData", "SendID", "Go to Analog Mode", "Go to Digital Mode" etc. already taking most of the options, there is quite a small number of "command codes" left to try.

Grendel, is it in the QueryFFP-function (written in asm) that the "kick" is the "interrupt" signal sent to the joystick and that the current code only implements the commands 1 and 2 (SendData and SendID i.e. commands with 1 and 2 interrupts total)? And maybe calling the QueryFFP-function differently (more than once/twice with the negative timing parameter?) or modifying it one could implement sending of the other commands too using the interrupts?

Since I cannot easily put the Tweeny completely in between the game port and joystick, and since there seem to be only quite finite number of commands towards the joystick possible, I was thinking of simply modifying the 3DPVert to try out a few commands and see if they trigger the missed "FFB mode" in the FFP. Or have I completely misunderstood the mechanism how "game port" can control the joystick?

Re: USB Converter for MS Sidewinder 3DPro, PP, and FFP

Posted: Mon Jan 16, 2012 7:44 pm
by Grendel
There is really only one "command" -- the stick detects the initiation of the analog query. When idle the capacitors are fully carged. The 1st step in a query is to discharge them to have the caps recarged from the stick. The SideWinder sticks detect the low-high carging transition and interpret this as a command. On a 3DPro you have to issue a timed sequence of commands to switch it over into digital mode. In digital mode each command will cause the stick to transfer its values using the button lines as a serial interface (clock on B1, data on B2-3) Another command during the transfer will cause ID data to be sent immediately after the position information. Another command while transfering the ID data will sent a 3DPro back to analog mode. The FFP doesn't have an analog emulation mode so it's never send any special sequence from the 3DP-Vert.

I doubt that there is a special OverDrive sequence necessary to enable FF. I'm fairly sure it's all in the MIDI commands. For verification tho you could hook up a scope on the X1 axis line and monitor the signal during enumeration.

Re: USB Converter for MS Sidewinder 3DPro, PP, and FFP

Posted: Wed Jan 18, 2012 4:55 pm
by cal
It is not all MIDI. I repeated the above-mentioned test and got the same result. The stick consistently goes into some "FFB mode" even when I have MIDI pin disconnected between the stick and game port when I startup FEdit. And only after that I can feed it the MIDI data so that the stick actually executes the given effects.

I even shorted the MIDI pin from the game port to ground (with a small resistor for safety) to prevent any crosstalk. And thus, I'm quite confident that the stick is not getting anything thru to the stick's MIDI input from game port and it still switches its mode. There is even a slight, but immediate and recognizable change in how the stick's auto-center-spring behaves right after starting FEdit (which also notices that it was not able to disable the auto-center-spring - as if game port would somehow also get feedback of the mode switch).

I don't have a scope. So, if anyone with one could see what's happening in the axis/button pins at the moment of an FFB-using application starts up and sets the stick to the "FFB mode".

Maybe, I could try to listen these pins with AVR with digital inputs (ADC is supposedly too slow for this) and high valued resistors (in attempt not to interfere to the signalling too much). Just that this would take much more time in order to get all of these pins wired out of the stick to the breadboard. Also, I'm still not 100% sure what kind of sequences I should be seeing in which pin.

BTW, Grendel, you mentioned about reviving a thread in "MS Answers". Don't know where that is - couldn't find a thread here with such a string. Some other forum?

Also, I finally got the time to write a short text document about the MIDI protocol decoded this far in somewhat readable format. Is this thread a place to post it or would you as moderator here prefer some other site/thread/forum? I'm not quite sure of the role of this particular forum for this type of "in the development"-kind of information.

Re: USB Converter for MS Sidewinder 3DPro, PP, and FFP

Posted: Wed Jan 18, 2012 10:55 pm
by ra9na
cal wrote:BTW, Grendel, you mentioned about reviving a thread in "MS Answers". Don't know where that is - couldn't find a thread here with such a string. Some other forum?
He meant my post directly under your first post in this thread here. Maybe this is the raeson, why I didn't get an answer from you =)...

Re: USB Converter for MS Sidewinder 3DPro, PP, and FFP

Posted: Wed Jan 18, 2012 11:52 pm
by Grendel
ra9na liked to in his 1st post. It's --> here.

Unfortunately I don't have a computer w/ a gameport anymore (one of the reasons I built the 3DP-Vert in the 1st place ;)) so I can't help w/ the signal analysis :(

Re: USB Converter for MS Sidewinder 3DPro, PP, and FFP

Posted: Thu Jan 19, 2012 3:34 am
by cal
Right - I think its time to find a single project space for this thing instead of splitting the discussion and information into many discussion forums.

And look what I found, looks like there is a place in Google Code just for that :)

http://code.google.com/p/adapt-ffb-joy/

There is already a preliminary Sidewinder MIDI description in the project's wiki page and an simple Arduino-based (USB-to-serial based) tool for sniffing and controlling the MIDI channel.

About the code then to convert the USB and MIDI data, I'm sure it can be done in C in a way that it compiles and works pretty much as such despite the mcu-platform. A simple interface that can be easily adapted to any other project like 3DPVert.

Re: Reverse Engineering the Force Feedback Pro

Posted: Thu Jan 19, 2012 12:49 pm
by Grendel
Interesting, only 9hrs old :) I'll definately keep an eye on that.

Re: Reverse Engineering the Force Feedback Pro

Posted: Sun Jan 22, 2012 10:52 am
by cal
Looks like there is a series of interrupt sequences going on in the X1-line during the enumeration with a real game port while nothing happens with it when running with 3DPVert.

Details are in the project Wiki.

Re: Reverse Engineering the Force Feedback Pro

Posted: Mon Jan 23, 2012 12:14 am
by Grendel
Some notes:

- the 1st pulse is probably to initial reading the stick to check if something is connceted
- following this should be a "read ID" sequence (pulse to start transmitting data, followed by a pulse while the data is still transmitting.) to determine that a FFP is indeed connected
- the 1-4-3 pulses block is probably it (initial read, ID read, switch to FF mode sequence)
- the "enable FF" sequence will have fairly tight timings measured in micro-seconds (less than 1ms pauses)
- the "enable FF" sequence is probably executed before the 1st MIDI command is send
- the overall sequence could also be: read, switch to FF, read ID (last two swapped, would allow for FF enable verification)
- or read, read ID, enable FF, read ID.
- pulses sent later are just initiating the transmission of the joysticks position data

The "enable FF" sequence could be similar to the "set digital mode" of a 3D Pro, which looks like (see Init3DPro() in 3DPro.c) :

pulse, wait 140us, pulse, wait 865us, pulse, wait 440us, pulse

May be worthwhile to modify the 3DP-Vert code to send that sequence after a FFP stick is detected (very easy modification.) MS may have reused the firmware from the 3D Pro... :)

The sequence to get out of analog mode is: pulse, pulse while data is transfered (will initiate ID packet transfer), pulse while ID data is transfered. Most likely this would also be the sequence to disable FF mode again (actually, this could also be the sequence to enter FF mode !)

Dang, you really need to monitor B1-4 along w/ X1 to get the whole picture :(

Re: Reverse Engineering the Force Feedback Pro

Posted: Mon Jan 23, 2012 7:45 am
by cal
Yep, I had the same day dream; using the 3DP's "set ditial mode" sequence after the FFP had been detected to see if it is "enable FFB" sequence on FFP (even removed the 3DP parts in the initialization sequence to make sure they won't interfere), but no - it was only a dream.

I also tried to replicate the sequence game port sends just to see if it would be that simple. Again, the second day dream was harassed by the harsh reality. Maybe I wasn't accurate enough on the timings (there were a few micro second differences here and there), but looks like there is more to it. All what was accomplished that I got the stick into a mode that almost any MIDI command made the FFP "crash" and disappear from the scene and recover only with a complete cold boot.

So, I'll next need to dispatch more wires out of the stick (5 more, buttons and X2) and extend the tester tool to take all those in. This will take a few days to get a time slot for it.

BTW, do you know how the X1 and X2 lines (sometimes incorrectly referred as Y2 in the code comments) differ from their usage in the communication to the stick? The 3DPVert (and seemingly the kernel driver too) always uses both the same way (pull both, release both). Or did I miss some place?

And when going into more timing details, do you know if the width of the pulse matters or only the delay between the pulses? Real game port seems to use pulse widths of 220us and 290us (always the last pulse in series of more than one pulses) and the delay width is 200us.

Re: Reverse Engineering the Force Feedback Pro

Posted: Mon Jan 23, 2012 4:03 pm
by Grendel
There are more possibilities -- the 3D Pro by default will only send data on B1 and B2. This allows to hook up two 3D Pros to a single gameport via a Y-cable. In order to use all 4 button lines for data transfer the 3D Pro needs the pulses on X1 and Y2 at the same time (the code comments are correct ! ;)). The FFP will only get the X1 pulses from a 3DP-Vert -- try moving the Y2 connection to X2, maybe that's all that's needed for FF mode...

A gameport will always pulse X1/2 and Y1/2 at the same time. The 3D Pro uses the presence of Y2 as an indication of being connected to a "full" gameport (two analog interfaces.) I don't know what the FFP does w/ the absence of X2.

Pulse lenghts are not important, voltage levels are. 50us on the Teensy w/ the 1k/1nF combo work reliably.

Re: Reverse Engineering the Force Feedback Pro

Posted: Mon Jan 23, 2012 6:07 pm
by cal
Ok, made the tester to print also buttons and X2-line values. Got some nice data out. It is still raw data, but since I have already well exceeded my time slot for doing this for now and pay for it tomorrow. I'll just leave the data for others to view if you could find anything on it.

Please see the "second sample" in:

http://code.google.com/p/adapt-ffb-joy/wiki/FFBModeInit

X2 seemed to change value too. And now that you mentioned about it, indeed the 3DPVert is connected to DB15 pin 13 (Y2), which is not connected to FFP. Instead DB15 pin 11 (X2) is. I hope it would not be that simple after all the... well, actually I do hope it would be that simple.

EDIT: Actually, it cannot be that simple as moving the cable from Y2 to X2 pin since even with a real game port, the FFB mode is not enabled by default, but first needs to be enabled with the sequences now under scrutiny.

EDIT 2: Indeed, the pulsing in X2 is not same as in X1. And looks like not all of it matters at least for normal positional data reading since 3DPVert works with FFP even when the X2 is not connected. Normal "Read" command for FFP includes pulsing the X2 line once too. Game port does it with about 400us pulse instead of X1 line's much shorter 230us pulse. In setup command sequence "1-4-3-2", all commands include X2 line pulsing (with pulse counts of "1-2-2-1" respectively with longer pulse widths and delays). X2 pulsing is not present in other commands. The 4-pulse command returns roughly 60 clocks of data to PC and the 2-pulse command about the same. Details update to the project wiki page above.

Re: Reverse Engineering the Force Feedback Pro

Posted: Wed Jan 25, 2012 4:23 pm
by Grendel
More notes:

- the FFP data packet is 16 clocks in size, the ID packet 14. This results in a 30 clock "big" packet for ID reads. Looks like you are counting each clock phase twice or the stick actually sends everything twice (would make sense for 2 and 4 pulse sequences).
- the X1/X2 pulse widths are defined by the R/C values in the game port circuitry and the resistor value to 5V inside the FFP. I would expect these to be fixed.
- the offset betw. X1/X2 start should be fixed too, it results from the differnt rising slopes. Ie. the shorter pulse will hit the logic "1" value earlier.
- the interesting numbers are the times between the start of pulses.
- I'm not sure reading X1/X2 digitally gives the whole picture. The "missing" pulses on X2 eg. are most likely "restarts", causing reading a long pulse instaed of two (see also PC analogue joystick interface). 290us is well w/ the data packet transaction period (100us + 16 * 10us). So every time you see a long X2, the software issued a pulse close to the end of reading a data packet (I call that "kick" in the 3DP-Vert code) to either read the ID, or issuing a timed sequence. You could miss X1 pulses as well. For clarity you can ignore the X2 line (should always follow X1.)

I got one of these. I may be able to find a XP machine w/ a gameport (and the power supplies involved... ;)). What exactly do I have to do to get FF to work ? Where can I d/l the FF software ? (Got my FFP from Goodwill...)

Re: Reverse Engineering the Force Feedback Pro

Posted: Tue Jan 31, 2012 5:19 am
by cal
Long time nothing done. Civil life and work getting a bit in the way of the hobby now.

I added links to the related information section of the project under subtitle Tools for Force Feedback in Windows for getting the FEdit application. It is part of DirectX 9.0 SDK (not the latest tho anymore). Install the SDK to get the FEdit-application.

You need to run Windows XP (latest SP is fine) - it has the built-in drivers for the old game port sidewinder joysticks. To install your controller in XP:
* Plug it in, click Start -> Control Panel (Switch to Classic view if you haven't already) -> click Game Controllers
* Click Add... -> Select Microsoft Sidewinder Auto Detect -> OK -> OK.

On older Windows, you need to install Sidewinder 3D drivers first - downloadable from Microsoft as a single executable.

Once installed and having your stick detected (should display "Microsoft SideWinder Force FeedBack Pro" and status "OK" in Game Controllers- control panel) you are ready to go.

Locate FEdit.exe from the SDK directories and run it. If you don't have any pre-made FFB effect files (with .ffe-suffix), you can easily create effects of your own in FEdit e.g. create a constant force and "Play" it and you should have the stick to react. You also need to actually have the FFP's power brick connected and your hand on the stick, since FFP has proximity check to see if you are really holding it or not. The stick does not move if you do not hold the stick. The stick however does take all FFB commands in fine even when not holding it.

As mentioned in earlier posts, already starting up FEdit, the stick is enumerated and FFB-mode enabled. You can then even quit FEdit and start pushing MIDI-data to the stick to make it react. The interesting part here is what happens when FEdit is started up.

Of course, if you don't want to use FEdit, any game or other application generating FFB-effects would do the same.

----

I know the digital view of the situation if not really giving all information especially with this archaic circuitry. A lot of educated guesswork on electric properties - and sheer luck - is also needed. The article on analog joystick interface was very useful on educating the guesswork, thanks.

EDIT: I tested, whether the X2-line has any real effect by shorting it permanently to ground (with 220 ohm resistor, which should be sufficient to keep the voltage level down) on real game port. The FFB-mode was still successfully enabled so I believe we can indeed forget the X2-line altogether.

Re: Reverse Engineering the Force Feedback Pro

Posted: Tue Jan 31, 2012 2:37 pm
by Grendel
Thanks, I'll see what I can do -- I do have access to a decent scope at work, looking at X1 and B1 (clock) should be sufficient to analyze the timings for the sequence to enable FF mode. Give me some time tho, busy as well... :/

Note on the grip sensor -- it's a photoelectric sensor, taping one of the holes w/ electrical or duct tape should free up one hand :)

Re: Reverse Engineering the Force Feedback Pro

Posted: Tue Jan 31, 2012 7:15 pm
by cal
Made it. I have now a version of 3DPVert that enables the FFB mode (and disables the auto-center spring). For testing purposes it also now, when pulling one joystick button plays a constant force effect and pressing another button it pauses the effect. It uses UART (pin D3) to send the MIDI data (which required remapping the button lines in an ugly way...).

The startup sequence indeed is the full set of pulse sets; 1-4-3-2-2-3-2 and then sending the MIDI commands.

Delays for sending the MIDI commands are as previously noted in the project wiki. Delays between the pulse sets that I use now and seem to work are: 7, 35, 14, 78, 3.3 and 59 ms respectively. The MIDI data can be sent immediately after the very last two-pulse command.

Using pulses with widths of 50us and 150us delay in between end of previous and start of the next one seems to work. These might not be the optimal in terms of reliability, but seem to work for now.

I'll update the project wiki soon to include the above information. Maybe I should post the (severely mutilated) source code of the 3DPVert version with prototype FFB there too just that everyone can start testing it. But that will have to wait until at least tomorrow since its already 3am and the kids need to be put to school and - stuff. The critical info is already above anyway.

The next step would be to work on the USB HID for FFB and more detailed analysis on the MIDI data to enable mapping of USB output reports to MIDI data packages.

Re: Reverse Engineering the Force Feedback Pro

Posted: Tue Jan 31, 2012 9:32 pm
by Grendel
Congratulations, good work ! :D I will take a closer look when I find some time, would be nice to shorten the sequence.

As for using D3 -- I would suggest to move B1-4 from D0-3 to D4-7, keeping B1 connected to D0 and D4. That way the button bits can be recreated via a swap command and the INT0 code stays valid.

Re: Reverse Engineering the Force Feedback Pro

Posted: Wed Feb 01, 2012 4:49 pm
by cal
I think I'll put the buttons to pins B0..B3 since D5 in Tweeny is in a bad location for breadboard constructs and the led is on D6. And sure, have that B0 and D0 connected for the INT0. Also, D1 and D2 would still be left free for INT1 and INT2 e.g. if someone wants to add pulse counters for digital pots or something.

I'll leave the F-port free since later, I'm planning to put those ADC pins into use for rudders, elevator trim and rudder trim pots (and get rid of my separate box for them with ATmega168 doing that with the software USB). Darn, there even room for analog flaps and if I completely loose it, for additional throttles for those four engine planes and... (calm down... clam now... deep breaths...)

Re: Reverse Engineering the Force Feedback Pro

Posted: Wed Feb 01, 2012 5:56 pm
by Grendel
B0-3 should work just fine for the buttons. If you want to hook up even more hardware, check out the Teensy++ board ! ;)

Re: Reverse Engineering the Force Feedback Pro

Posted: Sat Feb 04, 2012 3:31 am
by cal
I got the pins changed now to B0..B3 and the code seems to work fine.I do have a couple of Teensy++s set aside for another project waiting in the queue, but there's plenty of room as a pin count as well as in free memory in the smaller Teensy still.

But, as I feared on the reliability, after the wiring changes - possibly coincidentally - the reliability of the FFB mode enabling really suffered. It fails 9 out of 10 times now where it used to succeed with that ratio before. It is a breadboard setup so rogue capacitance and loose pinholes could easily change these things a lot without any visible queues. Also, the temporary wires hanging out of the stick used for snooping the game port traffic are likely to pick up all kinds of disturbances. After I had added them earlier, reliability even with a real game port was slightly affected already.

I need to check if changing the pulse timing settings of 50us/150us to one or the other direction would bring more reliability into it. I'll get back on this hopefully in a couple of days.

EDIT: Ok, reliability is back after twiddling with the wires a bit. The above timings seem to be fine and the unreliability came from the wiring.

Re: Reverse Engineering the Force Feedback Pro

Posted: Sun Feb 05, 2012 11:40 am
by cal
The next problem. Now it is in the 3DP-Vert's USB-code. It limits the HID descriptor to 256 bytes while minimal FFB descriptor part already seems to be over 500 bytes (I've seen descriptors of over 1200 bytes long too).

In the code, the limit comes at least from most length variables being uint8_t. I changed these length variables to uint16_t in the obvious places and checked that everything still works as before. To test for the limit again, I started adding more buttons to get bigger HID descriptor (and extended the report size) and again checking that it still works (i.e. I can see more buttons in the Game Controller panel correctly). But, I still keep hitting the 256 descriptor size limit. So, there is something else than mere data types that brings the limit, but I cannot see what it is.

I changed the length/count variable data types in main(), and parameters for functions usb_send_EP0(), and lookup() (and even usb_send_IN() even tho it seems to be used only to send the report data, whose length is still within 256 bytes :). I also modified the struct descriptor_list_t to have uint16_t for length for the descriptor.

I also tried to see a way to add that OUT end point to the USB for the FFB data and I'm almost thinking already of trying to port the 3DP-Vert to use LUFA to handle the USB side. It should solve the HID descriptor length issue too. Just that I have no previous hands-on experience with LUFA, but they say it should be easy to use.

Re: Reverse Engineering the Force Feedback Pro

Posted: Mon Feb 06, 2012 12:21 am
by Grendel
Yeah, the USB code is highly optimized and simplyfied. I probably wouldn't use it for this project too. LUFA seems a reasonable option since it does come w/ a Joystick reference. Atmel's reference code is another option, I would suggest to stay away from it tho (last time I used it I found multiple errors in it.) Both USB stacks will give you a full chapter 9 implementation but in return will eat up more resources.

Re: Reverse Engineering the Force Feedback Pro

Posted: Fri Feb 10, 2012 10:48 pm
by VonVulcan
You guys are amazing! :D

Re: Reverse Engineering the Force Feedback Pro

Posted: Sat Feb 11, 2012 4:41 am
by cal
Lots of work, very little progress. Before actually porting the 3DPVert to LUFA, I tried to get the simplest FFB Joystick made with it to see how the USB, LUFA and Windows build-in USB PID driver works.

I'm posting this to indicate that I'm still working on this and to ask for help on the USB part. If you cannot help, please spread the word if you know someone who has worked on the topic. So, please let me know if anyone knows a working sample on any kind of force feedback HID device that works with built-in Windows USB PID drivers.

If I don't get the PID approach working in due time, I'll consider looking at MS samples from their SDKs for building a mini-driver to map DirectInput data already in the PC side to avoid the Windows PID driver issues. This also seems to be the most common approach by the commercial joystick manufacturers.

I started out from a basic LUFA (the latest beta due it having new features needed here) joystick samples and got them working fine on Teensy after some trivial modifications. Then experimented adding a few FFB descriptors found on the forums (links in project wiki). I keep hitting the same wall people around the net have been i.e. getting any force feedback HID working using the built-in USB PID driver in Windows. Many have said they finally solved it but never actually posted the final methods.

The closest I've come is a joystick that gets enumerated as FFB device after manually modifying some OEMForceFeedback-registry values and keys in Windows (thanks to ulao's experiments on this on a Microchip forum). Yes, manually since the HIDs I've used are likely to miss some axis-binding or something and Windows does not automatically detect the stick's features correctly. So, I did get some data to the device from PC during enumeration when starting FEdit. However, the data did not meet the expectations (i.e. as defined by HID descriptor) of the content and seemed more like garbage - even it's length was off by a couple of bytes.

Been reading USB HID specs and samples more than I really bargained for, but getting better at it. Even tried to work with the USB.org's sample but it has other complexities that seem to give trouble (custom force specs and tons of different report IDs). Also, the whole PID HID descriptor seem to be very picky on anything being missing or even slightly wrong resulting in Windows rejecting the whole device.

UPDATE: Ok, after bumping into a few discussions on LUFA compiler warnings, I ended up updating my WINAVR to the latest and found some compiler options in LUFA to allow for larger HID descriptors with more reports, collections and stack size. The defaults were too small. These made the critical difference and I can now get clear and understandable output reports from PC to the joystick using a "minimal FFB" descriptor found on the forums. The descriptor has its issues (requires manual registry manipulation at install time, no axis-binding for force direction etc.), but I'm now more confident on moving on to attempt on the full blown descriptor from USB.org's samples. Actually, even with the current descriptor, I could already move along with the LUFA port and having the test effects being played by Windows instead of by the adapter itself on hard coded joystick button bindings. I thought I was going mad and sad, but now there is hope again!

Re: Reverse Engineering the Force Feedback Pro

Posted: Sun Feb 12, 2012 1:26 am
by Grendel
I do have a SideWinder Force Feedback 2 and access to a USB protocol analyzer. I could capture the FF2s descriptors if you think that would help.

Re: Reverse Engineering the Force Feedback Pro

Posted: Sun Feb 12, 2012 4:30 am
by cal
That would be more than interesting. Last night, I got the USB.org's sample PID HID working (enumerates and I get sensible FFB data to the stick) with LUFA, but even with that HID, the OEMForceFeedback-registry key's values for Effects lack the binding to the X-Y-axis and I need to manually modify the entries (enable two bits in the Attributes-value that bind X and Y axis to the effect respectively) in order for the joystick to be considered as FFB device. I also need to figure out what response messages I need to give back to PC to certain FFB-commands the stick receives to give proper feedback on creating an effect.

It could be possible that the FFP2's HID and protocol might give some insight on the latter topic. Altho, I am afraid that FFP2 is actually working via MS's custom drivers for Sidewinders instead of using the standard PID HID-driver. Thus, its HID descriptor might not help that much.

On the other hand, if the standard PID approach doesn't work well, it might be possible (or even easier) to mimic FFP2 with the 3DPVert and use its drivers and protocol for FFP-adaptation. I understood that feature-wise, FFP2 and FFP are very similar (same buttons, axis and effects). Do you know if force feedback works also in 64-bit Windows 7 with FFP2 - meaning that the drivers are still maintained?

Re: Reverse Engineering the Force Feedback Pro

Posted: Mon Feb 13, 2012 2:09 pm
by Grendel
I don't know for sure but I bet W7 still supports the FFP2. Give me a few days, I'll try to capture the FFP2s descriptors.

Re: Reverse Engineering the Force Feedback Pro

Posted: Sat Feb 18, 2012 6:52 pm
by NamelessPFG
I own a SideWinder Force-Feedback 2 and can confirm that not only does it work on Vista/Win7 64-bit, but that force-feedback does indeed work in every game I know that has it, even with nothing more than the bare-bone drivers already present in Vista/Win7 64-bit. Good thing all of them allow in-game configuration of the FFB, too, because the drivers sure don't!

It also has a very tight centering force with practically no center play, but the centering forces are also gradual and ramp up more as you move away from center, unlike the Logitech WingMan Strike Force 3D I've tried. No wonder the SWFFB2 has the cult following that it does in the flight sim community over a decade after its release and discontinuation...it's not just a FFB stick, but a FFB stick with well-implemented forces.

However, low-level driver work and descriptor sniffing is beyond my league. I'll have to leave that to Grendel.

Re: Reverse Engineering the Force Feedback Pro

Posted: Sun Feb 19, 2012 5:01 pm
by cal
That's comforting to know, that the plan B of using FFP2's USB protocol is at least possible in Win7 64bit. Hopefully tho, we can get the PID driver would work for it. That way it would also allow extensions (like those extra sliders for e.g. elevator/rudder trims in IL2). FFP2's custom driver (if it uses one) might not allow for such extensions.

Re: Reverse Engineering the Force Feedback Pro

Posted: Mon Feb 20, 2012 1:57 pm
by Grendel
Entertaining -- the FF2's report descriptor is 1343 bytes long :shock:. 3 Feature reports, 14 output reports, and 2 input reports. Here are the descriptors decoded by the analyzer software. I attached the trace -- download and remove the .txt extension then load into DataCenter (64 bit version).

Regular descriptors:

Code: Select all

 Device Descriptor	    	 Radix:  
bLength	18
bDescriptorType	DEVICE (0x01)
bcdUSB	1.10 (0x0110)
bDeviceClass	Defined in Interface (0x00)
bDeviceSubClass	Defined in Interface (0x00)
bDeviceProtocol	Defined in Interface (0x00)
bMaxPacketSize0	8
idVendor	0x045e
idProduct	0x001b
bcdDevice	a.00 (0x0a00)
iManufacturer	Not Requested (1)
iProduct	SideWinder Force Feedback 2 Joystick (2)
iSerialNumber	None (0)
bNumConfigurations	1

  Configuration Descriptor	    	 Radix:  
bLength	9
bDescriptorType	CONFIGURATION (0x02)
wTotalLength	41
bNumInterfaces	1
bConfigurationValue	1
iConfiguration	None (0)
bmAttributes.Reserved	0
bmAttributes.RemoteWakeup	RemoteWakeup Supported (0b1)
bmAttributes.SelfPowered	Bus Powered (0b0)
bMaxPower	100mA (0x32)

 Interface Descriptor	    	 Radix:  
bLength	9
bDescriptorType	INTERFACE (0x04)
bInterfaceNumber	0
bAlternateSetting	0
bNumEndpoints	2
bInterfaceClass	Human Interface Device (0x03)
bInterfaceSubClass	None (0x00)
bInterfaceProtocol	None (0x00)
iInterface	None (0)

 HID Descriptor	    	 Radix:  
bLength	9
bDescriptorType	HID (33)
bcdHID	1.00 (0x0100)
bCountryCode	0x00
bNumDescriptors	1
bDescriptorType	REPORT (34)
wDescriptorLength	1343

  Endpoint Descriptor	    	 Radix:  
bLength	7
bDescriptorType	ENDPOINT (0x05)
bEndpointAddress	1 IN (0b10000001)
bmAttributes.TransferType	Interrupt (0b11)
wMaxPacketSize.PacketSize	64
wMaxPacketSize.Transactions	One transaction per microframe if HS (0b00)
bInterval	1

  Endpoint Descriptor	    	 Radix:  
bLength	7
bDescriptorType	ENDPOINT (0x05)
bEndpointAddress	2 OUT (0b00000010)
bmAttributes.TransferType	Interrupt (0b11)
wMaxPacketSize.PacketSize	16
wMaxPacketSize.Transactions	One transaction per microframe if HS (0b00)
bInterval	4
Here's the beast -- the Report Descriptor:

Code: Select all

Get Report Descriptor
 General	    	 Radix:  
Timestamp	0:09.269.305.483
Duration	169.997.583 ms
Length	1343 Bytes
  Report Descriptor	    	 Radix:  
Usage Page	Generic Desktop Controls (0x01)
Usage	Joystick (0x04)
Collection	Application (0x01)
  Report ID	1
  Usage	Pointer (0x01)
  Collection	Physical (0x00)
    Unit	0
    Unit Exponent	0
    Logical Minimum	-512
    Logical Maximum	511
    Physical Minimum	0
    Physical Maximum	1023
    Report Count	1
    Report Size	10
    Usage	X (0x30)
    Input	Data (0x02)
    Report Size	6
    Input	Constant (0x01)
    Usage	Y (0x31)
    Report Size	10
    Input	Data (0x02)
    Report Size	6
    Report Count	1
    Input	Constant (0x01)
    Logical Minimum	-32
    Logical Maximum	31
    Physical Minimum	0
    Physical Maximum	63
    Unit	20
    Usage	Rz (0x35)
    Input	Data (0x02)
    Report Size	2
    Input	Constant (0x01)
    Unit	0
  End Collection	
  Report Size	7
  Report Count	1
  Logical Minimum	0
  Logical Maximum	127
  Physical Minimum	0
  Physical Maximum	127
  Usage	Slider (0x36)
  Input	Data (0x02)
  Report Size	1
  Input	Constant (0x01)
  Usage	Hat switch (0x39)
  Logical Minimum	0
  Logical Maximum	7
  Physical Minimum	0
  Physical Maximum	315
  Unit	20
  Report Size	4
  Report Count	1
  Input	Data (0x42)
  Report Count	1
  Input	Constant (0x01)
  Unit	0
  Usage Page	Button (0x09)
  Usage Minimum	Button 1 (primary/trigger) (0x01)
  Usage Maximum	Button 8 (0x08)
  Logical Minimum	0
  Logical Maximum	1
  Physical Minimum	0
  Physical Maximum	1
  Report Count	8
  Report Size	1
  Input	Data (0x02)
  Report Count	4
  Report Size	8
  Input	Constant (0x01)
  Usage Page	PID Page (0x0f)
  Usage	Undefined (0x92)
  Collection	Logical (0x02)
    Report ID	2
    Usage	Undefined (0x9f)
    Usage	Undefined (0xa0)
    Usage	Undefined (0xa4)
    Usage	Undefined (0xa5)
    Usage	Undefined (0xa6)
    Logical Minimum	0
    Logical Maximum	1
    Physical Minimum	0
    Physical Maximum	1
    Report Size	1
    Report Count	5
    Input	Data (0x02)
    Report Count	3
    Input	Constant (0x03)
    Usage	Undefined (0x94)
    Logical Minimum	0
    Logical Maximum	1
    Physical Minimum	0
    Physical Maximum	1
    Report Size	1
    Report Count	1
    Input	Data (0x02)
    Usage	Undefined (0x22)
    Logical Minimum	1
    Logical Maximum	40
    Physical Minimum	1
    Physical Maximum	40
    Report Size	7
    Report Count	1
    Input	Data (0x02)
  End Collection	
  Usage	Undefined (0x21)
  Collection	Logical (0x02)
    Report ID	1
    Usage	Undefined (0x22)
    Logical Minimum	1
    Logical Maximum	40
    Physical Minimum	1
    Physical Maximum	40
    Report Size	8
    Report Count	1
    Output	Data (0x02)
    Usage	Undefined (0x25)
    Collection	Logical (0x02)
      Usage	Undefined (0x26)
      Usage	Undefined (0x27)
      Usage	Undefined (0x30)
      Usage	Undefined (0x31)
      Usage	Undefined (0x32)
      Usage	Undefined (0x33)
      Usage	Undefined (0x34)
      Usage	Undefined (0x40)
      Usage	Undefined (0x41)
      Usage	Undefined (0x42)
      Usage	Undefined (0x43)
      Usage	Undefined (0x28)
      Logical Maximum	12
      Logical Minimum	1
      Physical Minimum	1
      Physical Maximum	12
      Report Size	8
      Report Count	1
      Output	Data (0x00)
    End Collection	
    Usage	Undefined (0x50)
    Usage	Undefined (0x54)
    Usage	Undefined (0x51)
    Logical Minimum	0
    Logical Maximum	32767
    Physical Minimum	0
    Physical Maximum	32767
    Unit	4099
    Unit Exponent	-3
    Report Size	16
    Report Count	3
    Output	Data (0x02)
    Unit Exponent	0
    Unit	0
    Usage	Undefined (0x52)
    Logical Minimum	0
    Logical Maximum	255
    Physical Minimum	0
    Physical Maximum	10000
    Report Size	8
    Report Count	1
    Output	Data (0x02)
    Usage	Undefined (0x53)
    Logical Minimum	1
    Logical Maximum	8
    Physical Minimum	1
    Physical Maximum	8
    Report Size	8
    Report Count	1
    Output	Data (0x02)
    Usage	Undefined (0x55)
    Collection	Logical (0x02)
      Usage Page	Generic Desktop Controls (0x01)
      Usage	X (0x30)
      Usage	Y (0x31)
      Logical Minimum	0
      Logical Maximum	1
      Report Size	1
      Report Count	2
      Output	Data (0x02)
    End Collection	
    Usage Page	PID Page (0x0f)
    Usage	Undefined (0x56)
    Report Count	1
    Output	Data (0x02)
    Report Count	5
    Output	Constant (0x03)
    Usage	Undefined (0x57)
    Collection	Logical (0x02)
      Usage	Instance 1 (0x000a0001)
      Usage	Instance 2 (0x000a0002)
      Unit	20
      Unit Exponent	-2
      Logical Minimum	0
      Logical Maximum	255
      Physical Minimum	0
      Physical Maximum	0
      Unit	0
      Report Size	8
      Report Count	2
      Output	Data (0x02)
      Unit Exponent	0
      Unit	0
    End Collection	
    Usage Page	PID Page (0x0f)
    Usage	Undefined (0xa7)
    Unit	4099
    Unit Exponent	-3
    Logical Minimum	0
    Logical Maximum	32767
    Physical Minimum	0
    Physical Maximum	32767
    Report Size	16
    Report Count	1
    Output	Data (0x02)
    Unit	0
    Unit Exponent	0
  End Collection	
  Usage Page	PID Page (0x0f)
  Usage	Undefined (0x5a)
  Collection	Logical (0x02)
    Report ID	2
    Usage	Undefined (0x22)
    Logical Minimum	1
    Logical Maximum	40
    Physical Minimum	1
    Physical Maximum	40
    Report Size	8
    Report Count	1
    Output	Data (0x02)
    Usage	Undefined (0x5b)
    Usage	Undefined (0x5d)
    Logical Minimum	0
    Logical Maximum	255
    Physical Minimum	0
    Physical Maximum	10000
    Report Count	2
    Output	Data (0x02)
    Usage	Undefined (0x5c)
    Usage	Undefined (0x5e)
    Unit	4099
    Unit Exponent	-3
    Logical Maximum	32767
    Physical Maximum	32767
    Report Size	16
    Output	Data (0x02)
    Physical Maximum	0
    Unit	0
    Unit Exponent	0
  End Collection	
  Usage	Undefined (0x5f)
  Collection	Logical (0x02)
    Report ID	3
    Usage	Undefined (0x22)
    Logical Minimum	1
    Logical Maximum	40
    Physical Minimum	1
    Physical Maximum	40
    Report Size	8
    Report Count	1
    Output	Data (0x02)
    Usage	Undefined (0x23)
    Logical Minimum	0
    Logical Maximum	1
    Physical Minimum	0
    Physical Maximum	1
    Report Size	4
    Report Count	1
    Output	Data (0x02)
    Usage	Undefined (0x58)
    Collection	Logical (0x02)
      Usage	Instance 1 (0x000a0001)
      Usage	Instance 2 (0x000a0002)
      Report Size	2
      Report Count	2
      Output	Data (0x02)
    End Collection	
    Logical Minimum	-128
    Logical Maximum	127
    Physical Minimum	-10000
    Physical Maximum	10000
    Usage	Undefined (0x60)
    Report Size	8
    Report Count	1
    Output	Data (0x02)
    Physical Minimum	-10000
    Physical Maximum	10000
    Usage	Undefined (0x61)
    Usage	Undefined (0x62)
    Report Count	2
    Output	Data (0x02)
    Logical Minimum	0
    Logical Maximum	255
    Physical Minimum	0
    Physical Maximum	10000
    Usage	Undefined (0x63)
    Usage	Undefined (0x64)
    Report Size	8
    Report Count	2
    Output	Data (0x02)
    Usage	Undefined (0x65)
    Physical Maximum	10000
    Report Count	1
    Output	Data (0x02)
  End Collection	
  Usage	Undefined (0x6e)
  Collection	Logical (0x02)
    Report ID	4
    Usage	Undefined (0x22)
    Logical Minimum	1
    Logical Maximum	40
    Physical Minimum	1
    Physical Maximum	40
    Report Size	8
    Report Count	1
    Output	Data (0x02)
    Usage	Undefined (0x70)
    Logical Minimum	0
    Logical Maximum	255
    Physical Minimum	0
    Physical Maximum	10000
    Report Size	8
    Report Count	1
    Output	Data (0x02)
    Usage	Undefined (0x6f)
    Logical Minimum	-128
    Logical Maximum	127
    Physical Minimum	-10000
    Physical Maximum	10000
    Report Count	1
    Output	Data (0x02)
    Usage	Undefined (0x71)
    Unit	20
    Unit Exponent	-2
    Logical Minimum	0
    Logical Maximum	255
    Physical Minimum	0
    Physical Maximum	0
    Output	Data (0x02)
    Usage	Undefined (0x72)
    Logical Maximum	32767
    Physical Maximum	32767
    Unit	4099
    Unit Exponent	-3
    Report Size	16
    Report Count	1
    Output	Data (0x02)
    Unit	0
    Unit Exponent	0
  End Collection	
  Usage	Undefined (0x73)
  Collection	Logical (0x02)
    Report ID	5
    Usage	Undefined (0x22)
    Logical Minimum	1
    Logical Maximum	40
    Physical Minimum	1
    Physical Maximum	40
    Report Size	8
    Report Count	1
    Output	Data (0x02)
    Usage	Undefined (0x70)
    Logical Minimum	-255
    Logical Maximum	255
    Physical Minimum	-10000
    Physical Maximum	10000
    Report Size	16
    Report Count	1
    Output	Data (0x02)
  End Collection	
  Usage	Undefined (0x74)
  Collection	Logical (0x02)
    Report ID	6
    Usage	Undefined (0x22)
    Logical Minimum	1
    Logical Maximum	40
    Physical Minimum	1
    Physical Maximum	40
    Report Size	8
    Report Count	1
    Output	Data (0x02)
    Usage	Undefined (0x75)
    Usage	Undefined (0x76)
    Logical Minimum	-128
    Logical Maximum	127
    Physical Minimum	-10000
    Physical Maximum	10000
    Report Size	8
    Report Count	2
    Output	Data (0x02)
  End Collection	
  Usage	Undefined (0x68)
  Collection	Logical (0x02)
    Report ID	7
    Usage	Undefined (0x22)
    Logical Minimum	1
    Logical Maximum	40
    Physical Minimum	1
    Physical Maximum	40
    Report Size	8
    Report Count	1
    Output	Data (0x02)
    Usage	Undefined (0x6c)
    Logical Minimum	0
    Logical Maximum	10000
    Physical Minimum	0
    Physical Maximum	10000
    Report Size	16
    Report Count	1
    Output	Data (0x02)
    Usage	Undefined (0x69)
    Logical Minimum	-127
    Logical Maximum	127
    Physical Minimum	0
    Physical Maximum	255
    Report Size	8
    Report Count	12
    Output	Data (0x0102)
  End Collection	
  Usage	Undefined (0x66)
  Collection	Logical (0x02)
    Report ID	8
    Usage Page	Generic Desktop Controls (0x01)
    Usage	X (0x30)
    Usage	Y (0x31)
    Logical Minimum	-127
    Logical Maximum	127
    Physical Minimum	0
    Physical Maximum	255
    Report Size	8
    Report Count	2
    Output	Data (0x02)
  End Collection	
  Usage Page	PID Page (0x0f)
  Usage	Undefined (0x77)
  Collection	Logical (0x02)
    Report ID	10
    Usage	Undefined (0x22)
    Logical Minimum	1
    Logical Maximum	40
    Physical Minimum	1
    Physical Maximum	40
    Report Size	8
    Report Count	1
    Output	Data (0x02)
    Usage	Undefined (0x78)
    Collection	Logical (0x02)
      Usage	Undefined (0x79)
      Usage	Undefined (0x7a)
      Usage	Undefined (0x7b)
      Logical Minimum	1
      Logical Maximum	3
      Report Size	8
      Report Count	1
      Output	Data (0x00)
    End Collection	
    Usage	Undefined (0x7c)
    Logical Minimum	0
    Logical Maximum	255
    Physical Minimum	0
    Physical Maximum	255
    Output	Data (0x02)
  End Collection	
  Usage	Undefined (0x90)
  Collection	Logical (0x02)
    Report ID	11
    Usage	Undefined (0x22)
    Logical Maximum	40
    Logical Minimum	1
    Physical Minimum	1
    Physical Maximum	40
    Report Size	8
    Report Count	1
    Output	Data (0x02)
  End Collection	
  Usage	Undefined (0x96)
  Collection	Logical (0x02)
    Report ID	12
    Usage	Undefined (0x97)
    Usage	Undefined (0x98)
    Usage	Undefined (0x99)
    Usage	Undefined (0x9a)
    Usage	Undefined (0x9b)
    Usage	Undefined (0x9c)
    Logical Minimum	1
    Logical Maximum	6
    Report Size	8
    Report Count	1
    Output	Data (0x00)
  End Collection	
  Usage	Undefined (0x7d)
  Collection	Logical (0x02)
    Report ID	13
    Usage	Undefined (0x7e)
    Logical Minimum	0
    Logical Maximum	255
    Physical Minimum	0
    Physical Maximum	10000
    Report Size	8
    Report Count	1
    Output	Data (0x02)
  End Collection	
  Usage	Undefined (0x6b)
  Collection	Logical (0x02)
    Report ID	14
    Usage	Undefined (0x22)
    Logical Minimum	1
    Logical Maximum	40
    Physical Minimum	1
    Physical Maximum	40
    Report Size	8
    Report Count	1
    Output	Data (0x02)
    Usage	Undefined (0x6d)
    Logical Minimum	0
    Logical Maximum	255
    Physical Minimum	0
    Physical Maximum	255
    Report Size	8
    Report Count	1
    Output	Data (0x02)
    Usage	Undefined (0x51)
    Unit	4099
    Unit Exponent	-3
    Logical Minimum	0
    Logical Maximum	32767
    Physical Minimum	0
    Physical Maximum	32767
    Report Size	16
    Report Count	1
    Output	Data (0x02)
    Unit Exponent	0
    Unit	0
  End Collection	
  Usage	Undefined (0xab)
  Collection	Logical (0x02)
    Report ID	1
    Usage	Undefined (0x25)
    Collection	Logical (0x02)
      Usage	Undefined (0x26)
      Usage	Undefined (0x27)
      Usage	Undefined (0x30)
      Usage	Undefined (0x31)
      Usage	Undefined (0x32)
      Usage	Undefined (0x33)
      Usage	Undefined (0x34)
      Usage	Undefined (0x40)
      Usage	Undefined (0x41)
      Usage	Undefined (0x42)
      Usage	Undefined (0x43)
      Usage	Undefined (0x28)
      Logical Maximum	12
      Logical Minimum	1
      Physical Minimum	1
      Physical Maximum	12
      Report Size	8
      Report Count	1
      Feature	Data (0x00)
    End Collection	
    Usage Page	Generic Desktop Controls (0x01)
    Usage	Byte Count (0x3b)
    Logical Minimum	0
    Logical Maximum	511
    Physical Minimum	0
    Physical Maximum	511
    Report Size	10
    Report Count	1
    Feature	Data (0x02)
    Report Size	6
    Feature	Constant (0x01)
  End Collection	
  Usage Page	PID Page (0x0f)
  Usage	Undefined (0x89)
  Collection	Logical (0x02)
    Report ID	2
    Usage	Undefined (0x22)
    Logical Maximum	40
    Logical Minimum	1
    Physical Minimum	1
    Physical Maximum	40
    Report Size	8
    Report Count	1
    Feature	Data (0x02)
    Usage	Undefined (0x8b)
    Collection	Logical (0x02)
      Usage	Undefined (0x8c)
      Usage	Undefined (0x8d)
      Usage	Undefined (0x8e)
      Logical Maximum	3
      Logical Minimum	1
      Physical Minimum	1
      Physical Maximum	3
      Report Size	8
      Report Count	1
      Feature	Data (0x00)
    End Collection	
    Usage	Undefined (0xac)
    Logical Minimum	0
    Logical Maximum	0
    Physical Minimum	0
    Physical Maximum	0
    Report Size	16
    Report Count	1
    Feature	Data (0x00)
  End Collection	
  Usage	Undefined (0x7f)
  Collection	Logical (0x02)
    Report ID	3
    Usage	Undefined (0x80)
    Report Size	16
    Report Count	1
    Logical Minimum	0
    Physical Minimum	0
    Logical Maximum	0
    Physical Maximum	0
    Feature	Data (0x02)
    Usage	Undefined (0x83)
    Logical Maximum	255
    Physical Maximum	255
    Report Size	8
    Report Count	1
    Feature	Data (0x02)
    Usage	Undefined (0xa9)
    Usage	Undefined (0xaa)
    Report Size	1
    Report Count	2
    Logical Minimum	0
    Logical Maximum	1
    Physical Minimum	0
    Physical Maximum	1
    Feature	Data (0x02)
    Report Size	6
    Report Count	1
    Feature	Constant (0x03)
  End Collection	
End Collection	

  Sample Input Report [1]	    	 Radix:  
Byte 0.0 (8b)	Report ID
Byte 1.0 (10b)	X
Byte 3.0 (10b)	Y
Byte 5.0 (6b)	Rz
Byte 6.0 (7b)	Pointer
Byte 7.0 (4b)	Hat switch
Byte 8.0 (1b)	Button 1 (primary/trigger)
Byte 8.1 (1b)	Button 2 (secondary)
Byte 8.2 (1b)	Button 3 (tertiary)
Byte 8.3 (1b)	Button 4
Byte 8.4 (1b)	Button 5
Byte 8.5 (1b)	Button 6
Byte 8.6 (1b)	Button 7
Byte 8.7 (1b)	Button 8
  Sample Input Report [2]	    	 Radix:  
Byte 0.0 (8b)	Report ID
Byte 1.0 (1b)	Undefined
Byte 1.1 (1b)	Undefined
Byte 1.2 (1b)	Undefined
Byte 1.3 (1b)	Undefined
Byte 1.4 (1b)	Undefined
Byte 2.0 (1b)	Undefined
Byte 2.1 (7b)	Undefined

  Sample Output Report [1]	    	 Radix:  
Byte 0.0 (8b)	Report ID
Byte 1.0 (8b)	Undefined
Byte 2.0 (8b)	PID Page Array
Byte 3.0 (16b)	Undefined
Byte 5.0 (16b)	Undefined
Byte 7.0 (16b)	Undefined
Byte 9.0 (8b)	Undefined
Byte 10.0 (8b)	Undefined
Byte 11.0 (1b)	X
Byte 11.1 (1b)	Y
Byte 11.2 (1b)	Undefined
Byte 12.0 (8b)	Instance 1
Byte 13.0 (8b)	Instance 2
Byte 14.0 (16b)	Undefined
 Sample Output Report [2]	    	 Radix:  
Byte 0.0 (8b)	Report ID
Byte 1.0 (8b)	Undefined
Byte 2.0 (8b)	Undefined
Byte 3.0 (8b)	Undefined
Byte 4.0 (16b)	Undefined
Byte 6.0 (16b)	Undefined
 Sample Output Report [3]	    	 Radix:  
Byte 0.0 (8b)	Report ID
Byte 1.0 (8b)	Undefined
Byte 2.0 (4b)	Undefined
Byte 2.4 (2b)	Instance 1
Byte 2.6 (2b)	Instance 2
Byte 3.0 (8b)	Undefined
Byte 4.0 (8b)	Undefined
Byte 5.0 (8b)	Undefined
Byte 6.0 (8b)	Undefined
Byte 7.0 (8b)	Undefined
Byte 8.0 (8b)	Undefined
 Sample Output Report [4]	    	 Radix:  
Byte 0.0 (8b)	Report ID
Byte 1.0 (8b)	Undefined
Byte 2.0 (8b)	Undefined
Byte 3.0 (8b)	Undefined
Byte 4.0 (8b)	Undefined
Byte 5.0 (16b)	Undefined
 Sample Output Report [5]	    	 Radix:  
Byte 0.0 (8b)	Report ID
Byte 1.0 (8b)	Undefined
Byte 2.0 (16b)	Undefined
 Sample Output Report [6]	    	 Radix:  
Byte 0.0 (8b)	Report ID
Byte 1.0 (8b)	Undefined
Byte 2.0 (8b)	Undefined
Byte 3.0 (8b)	Undefined
 Sample Output Report [7]	    	 Radix:  
Byte 0.0 (8b)	Report ID
Byte 1.0 (8b)	Undefined
Byte 2.0 (16b)	Undefined
Byte 4.0 (8b)	Undefined
Byte 5.0 (8b)	Undefined
Byte 6.0 (8b)	Undefined
Byte 7.0 (8b)	Undefined
Byte 8.0 (8b)	Undefined
Byte 9.0 (8b)	Undefined
Byte 10.0 (8b)	Undefined
Byte 11.0 (8b)	Undefined
Byte 12.0 (8b)	Undefined
Byte 13.0 (8b)	Undefined
Byte 14.0 (8b)	Undefined
Byte 15.0 (8b)	Undefined
 Sample Output Report [8]	    	 Radix:  
Byte 0.0 (8b)	Report ID
Byte 1.0 (8b)	X
Byte 2.0 (8b)	Y
 Sample Output Report [10]	    	 Radix:  
Byte 0.0 (8b)	Report ID
Byte 1.0 (8b)	Undefined
Byte 2.0 (8b)	PID Page Array
Byte 3.0 (8b)	Undefined
 Sample Output Report [11]	    	 Radix:  
Byte 0.0 (8b)	Report ID
Byte 1.0 (8b)	Undefined
 Sample Output Report [12]	    	 Radix:  
Byte 0.0 (8b)	Report ID
Byte 1.0 (8b)	PID Page Array
 Sample Output Report [13]	    	 Radix:  
Byte 0.0 (8b)	Report ID
Byte 1.0 (8b)	Undefined
 Sample Output Report [14]	    	 Radix:  
Byte 0.0 (8b)	Report ID
Byte 1.0 (8b)	Undefined
Byte 2.0 (8b)	Undefined
Byte 3.0 (16b)	Undefined

  Sample Feature Report [1]	    	 Radix:  
Byte 0.0 (8b)	Report ID
Byte 1.0 (8b)	PID Page Array
Byte 2.0 (10b)	Reserved
 Sample Feature Report [2]	    	 Radix:  
Byte 0.0 (8b)	Report ID
Byte 1.0 (8b)	Undefined
Byte 2.0 (8b)	PID Page Array
Byte 3.0 (16b)	PID Page Array
  Sample Feature Report [3]	    	 Radix:  
Byte 0.0 (8b)	Report ID
Byte 1.0 (16b)	Undefined
Byte 3.0 (8b)	Undefined
Byte 4.0 (1b)	Undefined
Byte 4.1 (1b)	Undefined
As a dump:

Code: Select all

radix: hexadecimal
05 01 09 04 A1 01 85 01 09 01 A1 00 66 00 00 55
00 16 00 FE 26 FF 01 35 00 46 FF 03 95 01 75 0A
09 30 81 02 75 06 81 01 09 31 75 0A 81 02 75 06
95 01 81 01 15 E0 25 1F 35 00 45 3F 66 14 00 09
35 81 02 75 02 81 01 66 00 00 C0 75 07 95 01 15
00 25 7F 35 00 45 7F 09 36 81 02 75 01 81 01 09
39 15 00 25 07 35 00 46 3B 01 66 14 00 75 04 95
01 81 42 95 01 81 01 66 00 00 05 09 19 01 29 08
15 00 25 01 35 00 45 01 95 08 75 01 81 02 95 04
75 08 81 01 05 0F 09 92 A1 02 85 02 09 9F 09 A0
09 A4 09 A5 09 A6 15 00 25 01 35 00 45 01 75 01
95 05 81 02 95 03 81 03 09 94 15 00 25 01 35 00
45 01 75 01 95 01 81 02 09 22 15 01 25 28 35 01
45 28 75 07 95 01 81 02 C0 09 21 A1 02 85 01 09
22 15 01 25 28 35 01 45 28 75 08 95 01 91 02 09
25 A1 02 09 26 09 27 09 30 09 31 09 32 09 33 09
34 09 40 09 41 09 42 09 43 09 28 25 0C 15 01 35
01 45 0C 75 08 95 01 91 00 C0 09 50 09 54 09 51
15 00 26 FF 7F 35 00 46 FF 7F 66 03 10 55 FD 75
10 95 03 91 02 55 00 66 00 00 09 52 15 00 26 FF
00 35 00 46 10 27 75 08 95 01 91 02 09 53 15 01
25 08 35 01 45 08 75 08 95 01 91 02 09 55 A1 02
05 01 09 30 09 31 15 00 25 01 75 01 95 02 91 02
C0 05 0F 09 56 95 01 91 02 95 05 91 03 09 57 A1
02 0B 01 00 0A 00 0B 02 00 0A 00 66 14 00 55 FE
15 00 26 FF 00 35 00 47 A0 8C 00 00 66 00 00 75
08 95 02 91 02 55 00 66 00 00 C0 05 0F 09 A7 66
03 10 55 FD 15 00 26 FF 7F 35 00 46 FF 7F 75 10
95 01 91 02 66 00 00 55 00 C0 05 0F 09 5A A1 02
85 02 09 22 15 01 25 28 35 01 45 28 75 08 95 01
91 02 09 5B 09 5D 15 00 26 FF 00 35 00 46 10 27
95 02 91 02 09 5C 09 5E 66 03 10 55 FD 26 FF 7F
46 FF 7F 75 10 91 02 45 00 66 00 00 55 00 C0 09
5F A1 02 85 03 09 22 15 01 25 28 35 01 45 28 75
08 95 01 91 02 09 23 15 00 25 01 35 00 45 01 75
04 95 01 91 02 09 58 A1 02 0B 01 00 0A 00 0B 02
00 0A 00 75 02 95 02 91 02 C0 15 80 25 7F 36 F0
D8 46 10 27 09 60 75 08 95 01 91 02 36 F0 D8 46
10 27 09 61 09 62 95 02 91 02 15 00 26 FF 00 35
00 46 10 27 09 63 09 64 75 08 95 02 91 02 09 65
46 10 27 95 01 91 02 C0 09 6E A1 02 85 04 09 22
15 01 25 28 35 01 45 28 75 08 95 01 91 02 09 70
15 00 26 FF 00 35 00 46 10 27 75 08 95 01 91 02
09 6F 15 80 25 7F 36 F0 D8 46 10 27 95 01 91 02
09 71 66 14 00 55 FE 15 00 26 FF 00 35 00 47 A0
8C 00 00 91 02 09 72 26 FF 7F 46 FF 7F 66 03 10
55 FD 75 10 95 01 91 02 66 00 00 55 00 C0 09 73
A1 02 85 05 09 22 15 01 25 28 35 01 45 28 75 08
95 01 91 02 09 70 16 01 FF 26 FF 00 36 F0 D8 46
10 27 75 10 95 01 91 02 C0 09 74 A1 02 85 06 09
22 15 01 25 28 35 01 45 28 75 08 95 01 91 02 09
75 09 76 15 80 25 7F 36 F0 D8 46 10 27 75 08 95
02 91 02 C0 09 68 A1 02 85 07 09 22 15 01 25 28
35 01 45 28 75 08 95 01 91 02 09 6C 15 00 26 10
27 35 00 46 10 27 75 10 95 01 91 02 09 69 15 81
25 7F 35 00 46 FF 00 75 08 95 0C 92 02 01 C0 09
66 A1 02 85 08 05 01 09 30 09 31 15 81 25 7F 35
00 46 FF 00 75 08 95 02 91 02 C0 05 0F 09 77 A1
02 85 0A 09 22 15 01 25 28 35 01 45 28 75 08 95
01 91 02 09 78 A1 02 09 79 09 7A 09 7B 15 01 25
03 75 08 95 01 91 00 C0 09 7C 15 00 26 FF 00 35
00 46 FF 00 91 02 C0 09 90 A1 02 85 0B 09 22 25
28 15 01 35 01 45 28 75 08 95 01 91 02 C0 09 96
A1 02 85 0C 09 97 09 98 09 99 09 9A 09 9B 09 9C
15 01 25 06 75 08 95 01 91 00 C0 09 7D A1 02 85
0D 09 7E 15 00 26 FF 00 35 00 46 10 27 75 08 95
01 91 02 C0 09 6B A1 02 85 0E 09 22 15 01 25 28
35 01 45 28 75 08 95 01 91 02 09 6D 15 00 26 FF
00 35 00 46 FF 00 75 08 95 01 91 02 09 51 66 03
10 55 FD 15 00 26 FF 7F 35 00 46 FF 7F 75 10 95
01 91 02 55 00 66 00 00 C0 09 AB A1 02 85 01 09
25 A1 02 09 26 09 27 09 30 09 31 09 32 09 33 09
34 09 40 09 41 09 42 09 43 09 28 25 0C 15 01 35
01 45 0C 75 08 95 01 B1 00 C0 05 01 09 3B 15 00
26 FF 01 35 00 46 FF 01 75 0A 95 01 B1 02 75 06
B1 01 C0 05 0F 09 89 A1 02 85 02 09 22 25 28 15
01 35 01 45 28 75 08 95 01 B1 02 09 8B A1 02 09
8C 09 8D 09 8E 25 03 15 01 35 01 45 03 75 08 95
01 B1 00 C0 09 AC 15 00 27 FF FF 00 00 35 00 47
FF FF 00 00 75 10 95 01 B1 00 C0 09 7F A1 02 85
03 09 80 75 10 95 01 15 00 35 00 27 FF FF 00 00
47 FF FF 00 00 B1 02 09 83 26 FF 00 46 FF 00 75
08 95 01 B1 02 09 A9 09 AA 75 01 95 02 15 00 25
01 35 00 45 01 B1 02 75 06 95 01 B1 03 C0 C0

Re: Reverse Engineering the Force Feedback Pro

Posted: Tue Feb 21, 2012 3:59 pm
by cal
Thanks!

Crivens! It really looks like it is using the PID driver in there instead of a custom one. At least all the PID-related report descriptors are there and looking very familiar. Compared to the USB.org's sample PID HID it is slightly larger (offers a couple of more effect types and some PID states etc.). I'll need to compare these two now and see what is wrong with the USB.org's sample as to why it is not automatically (without RegEdit-magic that is) recognized as a FFB device. On the other hand, the Sidewinder's seem to come with registry keys for FFB from the .inf-files so, in the end, it might be possible that this 3DPVert+FFB might need a simple .inf-file too to make it fully functional. Well have to see. It could still be a problem in descriptor I'm using or the answers I'm giving (which is none now) when the device is first plugged-in to PC and Windows starts to look drivers for it.

Indeed, as you noticed, these PID descriptors tend to get huge and I have only started to understand something on why much of the stuff is there (well, not really understand "why" but at least I can see how it brings more information about the effects protocol).

On the side note; I just got the 3DPVert ported to LUFA and have included a working "enable FFB mode" command there too at startup. I'm still sorting the code a little bit to isolate your original 3DPVert code since you are distributing it with a bit more restrictive license than what I have in store for the FFB code (going out in MIT license to make it simple). This first port however is strictly for FFP and Teensy 2 (I severely amputated it from many of the other parts) since the other sticks have no FFB and at this point I wanted to simplify the prototyping by having as little of moving parts as possible. I'll also have some extra inputs in it to allow additional buttons and potentiometers to be plugged in. It should be quite a simple matter to include the amputated parts back in once the whole thing works together. I'll upload it into the site in a day or two and we are finally approaching the position where I hoped to be in the very early stages of the project :)

Re: Reverse Engineering the Force Feedback Pro

Posted: Tue Feb 21, 2012 4:50 pm
by cal
Here's the report descriptors with descriptive texts in place of the "undefined"s. Biggest differences seem to be in the memory management reports and effect indexing mechanism. FF2 also seems to support more force feedback features than FFP (e.g. non-zero phase in periodic effects and startup delay for an effect). So, Microsoft did some other under-the-hood improvements too to the FF2 than just the form factor and USB connectivity.

I would not be surprised to see that the Windows' PID driver is actually made for the FF2 features in mind and it might be required to adhere to that subset and ways of usages its descriptor has...

Code: Select all

Usage Page   Generic Desktop Controls (0x01)
Usage   Joystick (0x04)
Collection   Application (0x01)
  Report ID   1
  Usage   Pointer (0x01)
  Collection   Physical (0x00)
    Unit   0
    Unit Exponent   0
    Logical Minimum   -512
    Logical Maximum   511
    Physical Minimum   0
    Physical Maximum   1023
    Report Count   1
    Report Size   10
    Usage   X (0x30)
    Input   Data (0x02)
    Report Size   6
    Input   Constant (0x01)
    Usage   Y (0x31)
    Report Size   10
    Input   Data (0x02)
    Report Size   6
    Report Count   1
    Input   Constant (0x01)
    Logical Minimum   -32
    Logical Maximum   31
    Physical Minimum   0
    Physical Maximum   63
    Unit   20
    Usage   Rz (0x35)
    Input   Data (0x02)
    Report Size   2
    Input   Constant (0x01)
    Unit   0
  End Collection   
  
  Report Size   7
  Report Count   1
  Logical Minimum   0
  Logical Maximum   127
  Physical Minimum   0
  Physical Maximum   127
  Usage   Slider (0x36)
  Input   Data (0x02)
  Report Size   1
  Input   Constant (0x01)
  Usage   Hat switch (0x39)
  Logical Minimum   0
  Logical Maximum   7
  Physical Minimum   0
  Physical Maximum   315
  Unit   20
  Report Size   4
  Report Count   1
  Input   Data (0x42)
  Report Count   1
  Input   Constant (0x01)
  Unit   0
  Usage Page   Button (0x09)
  Usage Minimum   Button 1 (primary/trigger) (0x01)
  Usage Maximum   Button 8 (0x08)
  Logical Minimum   0
  Logical Maximum   1
  Physical Minimum   0
  Physical Maximum   1
  Report Count   8
  Report Size   1
  Input   Data (0x02)
  
  Report Count   4
  Report Size   8
  Input   Constant (0x01)
  
  ----> Here's the FFB part of it all ---->

  Usage Page   PID Page (0x0f)
  Usage   PID State Report (0x92)
  Collection   Logical (0x02)
    Report ID   2
    Usage   Device Paused (0x9f)
    Usage   Actuators Enabled (0xa0)
    Usage   Safety Switch (0xa4)
    Usage   Actuator Override Switch (0xa5)
    Usage   Actuator Power (0xa6)
    Logical Minimum   0
    Logical Maximum   1
    Physical Minimum   0
    Physical Maximum   1
    Report Size   1
    Report Count   5
    Input   Data (0x02)
    Report Count   3
    Input   Constant (0x03)	
    Usage   Effect Playing (0x94)
    Logical Minimum   0
    Logical Maximum   1
    Physical Minimum   0
    Physical Maximum   1
    Report Size   1
    Report Count   1
    Input   Data (0x02)	
    Usage   Effect Block Index (0x22)
    Logical Minimum   1
    Logical Maximum   40
    Physical Minimum   1
    Physical Maximum   40
    Report Size   7
    Report Count   1
    Input   Data (0x02)
  End Collection   
  
  Usage   Set Effect Report (0x21)
  Collection   Logical (0x02)
    Report ID   1
    Usage    Effect Block Inde (0x22)
    Logical Minimum   1
    Logical Maximum   40
    Physical Minimum   1
    Physical Maximum   40
    Report Size   8
    Report Count   1
    Output   Data (0x02)
    Usage   Effect Type (0x25)
    Collection   Logical (0x02)
      Usage   ET Constant Force (0x26)
      Usage   ET Ramp (0x27)
      Usage   ET Square (0x30)
      Usage   ET Sine (0x31)
      Usage   ET Triangle (0x32)
      Usage   ET Sawtooth Up (0x33)
      Usage   ET Sawtooth Down (0x34)
      Usage   ET Spring (0x40)
      Usage   ET Damper (0x41)
      Usage   ET Inertia (0x42)
      Usage   ET Friction (0x43)
      Usage   ET Custom Force Data (0x28)
      Logical Maximum   12
      Logical Minimum   1
      Physical Minimum   1
      Physical Maximum   12
      Report Size   8
      Report Count   1
      Output   Data (0x00)
    End Collection   
	
    Usage   Duration (0x50)
    Usage   Trigger Repeat Interval (0x54)
    Usage   Sample Period (0x51)
    Logical Minimum   0
    Logical Maximum   32767
    Physical Minimum   0
    Physical Maximum   32767
    Unit   4099
    Unit Exponent   -3
    Report Size   16
    Report Count   3
    Output   Data (0x02)
	
    Unit Exponent   0
    Unit   0
    Usage   Gain (0x52)
    Logical Minimum   0
    Logical Maximum   255
    Physical Minimum   0
    Physical Maximum   10000
    Report Size   8
    Report Count   1
    Output   Data (0x02)
    Usage   Trigger Button (0x53)
    Logical Minimum   1
    Logical Maximum   8
    Physical Minimum   1
    Physical Maximum   8
    Report Size   8
    Report Count   1
    Output   Data (0x02)
    Usage   Axes Enable (0x55)
    Collection   Logical (0x02)
      Usage Page   Generic Desktop Controls (0x01)
      Usage   X (0x30)
      Usage   Y (0x31)
      Logical Minimum   0
      Logical Maximum   1
      Report Size   1
      Report Count   2
      Output   Data (0x02)
    End Collection   
	
    Usage Page   PID Page (0x0f)
    Usage   Direction Enable (0x56)
    Report Count   1
    Output   Data (0x02)
    Report Count   5
    Output   Constant (0x03)
    Usage   Direction (0x57)
    Collection   Logical (0x02)
      Usage   Instance 1 (0x000a0001)
      Usage   Instance 2 (0x000a0002)
      Unit   20
      Unit Exponent   -2
      Logical Minimum   0
      Logical Maximum   255
      Physical Minimum   0
      Physical Maximum   0
      Unit   0
      Report Size   8
      Report Count   2
      Output   Data (0x02)
      Unit Exponent   0
      Unit   0
    End Collection   
	
    Usage Page   PID Page (0x0f)
    Usage   Start Delay (0xa7)
    Unit   4099
    Unit Exponent   -3
    Logical Minimum   0
    Logical Maximum   32767
    Physical Minimum   0
    Physical Maximum   32767
    Report Size   16
    Report Count   1
    Output   Data (0x02)
    Unit   0
    Unit Exponent   0
  End Collection   
  
  Usage Page   PID Page (0x0f)
  Usage   Set Envelope Report (0x5a)
  Collection   Logical (0x02)
    Report ID   2
    Usage    Effect Block Inde (0x22)
    Logical Minimum   1
    Logical Maximum   40
    Physical Minimum   1
    Physical Maximum   40
    Report Size   8
    Report Count   1
    Output   Data (0x02)
    Usage   Attack Level (0x5b)
    Usage   Fade Level (0x5d)
    Logical Minimum   0
    Logical Maximum   255
    Physical Minimum   0
    Physical Maximum   10000
    Report Count   2
    Output   Data (0x02)
    Usage   Attack Time (0x5c)
    Usage   Fade Time (0x5e)
    Unit   4099
    Unit Exponent   -3
    Logical Maximum   32767
    Physical Maximum   32767
    Report Size   16
    Output   Data (0x02)
    Physical Maximum   0
    Unit   0
    Unit Exponent   0
  End Collection   
  
  Usage   Set Condition Report (0x5f)
  Collection   Logical (0x02)
    Report ID   3
    Usage   Effect Block Index (0x22)
    Logical Minimum   1
    Logical Maximum   40
    Physical Minimum   1
    Physical Maximum   40
    Report Size   8
    Report Count   1
    Output   Data (0x02)
    Usage   Parameter Block Offset (0x23)
    Logical Minimum   0
    Logical Maximum   1
    Physical Minimum   0
    Physical Maximum   1
    Report Size   4
    Report Count   1
    Output   Data (0x02)
    Usage   Type Specific Block Offset (0x58)
    Collection   Logical (0x02)
      Usage   Instance 1 (0x000a0001)
      Usage   Instance 2 (0x000a0002)
      Report Size   2
      Report Count   2
      Output   Data (0x02)
    End Collection   
    Logical Minimum   -128
    Logical Maximum   127
    Physical Minimum   -10000
    Physical Maximum   10000
    Usage   CP Offset (0x60)
    Report Size   8
    Report Count   1
    Output   Data (0x02)
    Physical Minimum   -10000
    Physical Maximum   10000
    Usage   Positive Coefficient (0x61)
    Usage   Negative Coefficient (0x62)
    Report Count   2
    Output   Data (0x02)
    Logical Minimum   0
    Logical Maximum   255
    Physical Minimum   0
    Physical Maximum   10000
    Usage   Positive Saturation (0x63)
    Usage   Negative Saturation (0x64)
    Report Size   8
    Report Count   2
    Output   Data (0x02)
    Usage   Dead Band (0x65)
    Physical Maximum   10000
    Report Count   1
    Output   Data (0x02)
  End Collection   
  
  Usage   Set Periodic Report (0x6e)
  Collection   Logical (0x02)
    Report ID   4
    Usage   Effect Block Index (0x22)
    Logical Minimum   1
    Logical Maximum   40
    Physical Minimum   1
    Physical Maximum   40
    Report Size   8
    Report Count   1
    Output   Data (0x02)
    Usage   Magnitude (0x70)
    Logical Minimum   0
    Logical Maximum   255
    Physical Minimum   0
    Physical Maximum   10000
    Report Size   8
    Report Count   1
    Output   Data (0x02)
    Usage   Offset (0x6f)
    Logical Minimum   -128
    Logical Maximum   127
    Physical Minimum   -10000
    Physical Maximum   10000
    Report Count   1
    Output   Data (0x02)
    Usage   Phase (0x71)
    Unit   20
    Unit Exponent   -2
    Logical Minimum   0
    Logical Maximum   255
    Physical Minimum   0
    Physical Maximum   0
    Output   Data (0x02)
    Usage   Period	(0x72)
    Logical Maximum   32767
    Physical Maximum   32767
    Unit   4099
    Unit Exponent   -3
    Report Size   16
    Report Count   1
    Output   Data (0x02)
    Unit   0
    Unit Exponent   0
  End Collection  
  
  Usage   Set Constant Force Report (0x73)
  Collection   Logical (0x02)
    Report ID   5
    Usage   Effect Block Index (0x22)
    Logical Minimum   1
    Logical Maximum   40
    Physical Minimum   1
    Physical Maximum   40
    Report Size   8
    Report Count   1
    Output   Data (0x02)
    Usage   Magnitude (0x70)
    Logical Minimum   -255
    Logical Maximum   255
    Physical Minimum   -10000
    Physical Maximum   10000
    Report Size   16
    Report Count   1
    Output   Data (0x02)
  End Collection   
  
  Usage   Set Ramp Force Report (0x74)
  Collection   Logical (0x02)
    Report ID   6
    Usage   Effect Block Index (0x22)
    Logical Minimum   1
    Logical Maximum   40
    Physical Minimum   1
    Physical Maximum   40
    Report Size   8
    Report Count   1
    Output   Data (0x02)
    Usage   Ramp Start (0x75)
    Usage   Ramp End (0x76)
    Logical Minimum   -128
    Logical Maximum   127
    Physical Minimum   -10000
    Physical Maximum   10000
    Report Size   8
    Report Count   2
    Output   Data (0x02)
  End Collection   
  
  Usage   Custom Force Data Report (0x68)
  Collection   Logical (0x02)
    Report ID   7
    Usage   Effect Block Index (0x22)
    Logical Minimum   1
    Logical Maximum   40
    Physical Minimum   1
    Physical Maximum   40
    Report Size   8
    Report Count   1
    Output   Data (0x02)
    Usage   Custom Force Data Offset (0x6c)
    Logical Minimum   0
    Logical Maximum   10000
    Physical Minimum   0
    Physical Maximum   10000
    Report Size   16
    Report Count   1
    Output   Data (0x02)
    Usage   Custom Force Data (0x69)
    Logical Minimum   -127
    Logical Maximum   127
    Physical Minimum   0
    Physical Maximum   255
    Report Size   8
    Report Count   12
    Output   Data (0x0102)
  End Collection   
  
  Usage   Download Force Sample (0x66)
  Collection   Logical (0x02)
    Report ID   8
    Usage Page   Generic Desktop Controls (0x01)
    Usage   X (0x30)
    Usage   Y (0x31)
    Logical Minimum   -127
    Logical Maximum   127
    Physical Minimum   0
    Physical Maximum   255
    Report Size   8
    Report Count   2
    Output   Data (0x02)
  End Collection   
  
  Usage Page   PID Page (0x0f)
  Usage   Effect Operation Report (0x77)
  Collection   Logical (0x02)
    Report ID   10
    Usage   Effect Block Index (0x22)
    Logical Minimum   1
    Logical Maximum   40
    Physical Minimum   1
    Physical Maximum   40
    Report Size   8
    Report Count   1
    Output   Data (0x02)
    Usage   Effect Operation (0x78)
    Collection   Logical (0x02)
      Usage   Op Effect Start (0x79)
      Usage   Op Effect Start Solo (0x7a)
      Usage   Op Effect Stop (0x7b)
      Logical Minimum   1
      Logical Maximum   3
      Report Size   8
      Report Count   1
      Output   Data (0x00)
    End Collection   
    Usage   Loop Count (0x7c)
    Logical Minimum   0
    Logical Maximum   255
    Physical Minimum   0
    Physical Maximum   255
    Output   Data (0x02)
  End Collection   
  
  Usage   PID Block Free Report (0x90)
  Collection   Logical (0x02)
    Report ID   11
    Usage   Effect Block Index (0x22)
    Logical Maximum   40
    Logical Minimum   1
    Physical Minimum   1
    Physical Maximum   40
    Report Size   8
    Report Count   1
    Output   Data (0x02)
  End Collection   
  
  Usage   PID Device Control (0x96)
  Collection   Logical (0x02)
    Report ID   12
    Usage   DC Enable Actuators (0x97)
    Usage   DC Disable Actuators (0x98)
    Usage   DC Stop All Effects (0x99)
    Usage   DC Device Reset (0x9a)
    Usage   DC Device Pause (0x9b)
    Usage   DC Device Continue (0x9c)
    Logical Minimum   1
    Logical Maximum   6
    Report Size   8
    Report Count   1
    Output   Data (0x00)
  End Collection   
  
  Usage   Device Gain Report (0x7d)
  Collection   Logical (0x02)
    Report ID   13
    Usage   Device Gain (0x7e)
    Logical Minimum   0
    Logical Maximum   255
    Physical Minimum   0
    Physical Maximum   10000
    Report Size   8
    Report Count   1
    Output   Data (0x02)
  End Collection   
  
  Usage   Set Custom Force Report (0x6b)
  Collection   Logical (0x02)
    Report ID   14
    Usage   Effect Block Index (0x22)
    Logical Minimum   1
    Logical Maximum   40
    Physical Minimum   1
    Physical Maximum   40
    Report Size   8
    Report Count   1
    Output   Data (0x02)
    Usage   Sample Count (0x6d)
    Logical Minimum   0
    Logical Maximum   255
    Physical Minimum   0
    Physical Maximum   255
    Report Size   8
    Report Count   1
    Output   Data (0x02)
    Usage   Sample Period (0x51)
    Unit   4099
    Unit Exponent   -3
    Logical Minimum   0
    Logical Maximum   32767
    Physical Minimum   0
    Physical Maximum   32767
    Report Size   16
    Report Count   1
    Output   Data (0x02)
    Unit Exponent   0
    Unit   0
  End Collection   
  
  Usage   Create New Effect Report (0xab)
  Collection   Logical (0x02)
    Report ID   1
    Usage   Effect Type (0x25)
    Collection   Logical (0x02)
      Usage   ET Constant Force (0x26)
      Usage   ET Ramp (0x27)
      Usage   ET Square (0x30)
      Usage   ET Sine (0x31)
      Usage   ET Triangle (0x32)
      Usage   ET Sawtooth Up (0x33)
      Usage   ET Sawtooth Down (0x34)
      Usage   ET Spring (0x40)
      Usage   ET Damper (0x41)
      Usage   ET Inertia (0x42)
      Usage   ET Friction (0x43)
      Usage   ET Custom Force Data (0x28)
      Logical Maximum   12
      Logical Minimum   1
      Physical Minimum   1
      Physical Maximum   12
      Report Size   8
      Report Count   1
      Feature   Data (0x00)
    End Collection   
    Usage Page   Generic Desktop Controls (0x01)
    Usage   Byte Count (0x3b)
    Logical Minimum   0
    Logical Maximum   511
    Physical Minimum   0
    Physical Maximum   511
    Report Size   10
    Report Count   1
    Feature   Data (0x02)
    Report Size   6
    Feature   Constant (0x01)
  End Collection   
  
  Usage Page   PID Page (0x0f)
  Usage   PID Block Load Report (0x89)
  Collection   Logical (0x02)
    Report ID   2
    Usage   Effect Block Index (0x22)
    Logical Maximum   40
    Logical Minimum   1
    Physical Minimum   1
    Physical Maximum   40
    Report Size   8
    Report Count   1
    Feature   Data (0x02)
    Usage   Block Load Status (0x8b)
    Collection   Logical (0x02)
      Usage   Block Load Success (0x8c)
      Usage   Block Load Full (0x8d)
      Usage   Block Load Error (0x8e)
      Logical Maximum   3
      Logical Minimum   1
      Physical Minimum   1
      Physical Maximum   3
      Report Size   8
      Report Count   1
      Feature   Data (0x00)
    End Collection   
    Usage   RAM Pool Available (0xac)
    Logical Minimum   0
    Logical Maximum   0
    Physical Minimum   0
    Physical Maximum   0
    Report Size   16
    Report Count   1
    Feature   Data (0x00)
  End Collection   
  
  Usage   PID Pool Report (0x7f)
  Collection   Logical (0x02)
    Report ID   3
    Usage   RAM Pool Size (0x80)
    Report Size   16
    Report Count   1
    Logical Minimum   0
    Physical Minimum   0
    Logical Maximum   0
    Physical Maximum   0
    Feature   Data (0x02)
    Usage   Simultaneous Effects Max (0x83)
    Logical Maximum   255
    Physical Maximum   255
    Report Size   8
    Report Count   1
    Feature   Data (0x02)
    Usage   Device Managed Pool (0xa9)
    Usage   Shared Parameter Blocks (0xaa)
    Report Size   1
    Report Count   2
    Logical Minimum   0
    Logical Maximum   1
    Physical Minimum   0
    Physical Maximum   1
    Feature   Data (0x02)
    Report Size   6
    Report Count   1
    Feature   Constant (0x03)
  End Collection   
End Collection   

Re: Reverse Engineering the Force Feedback Pro

Posted: Thu Feb 23, 2012 4:47 pm
by cal
Finally, I managed to get some actual code published (please, notify me if the credits in the code are not as you would like them to be).

The project site now contains source code and hex file for the prototype version 1 in the downloads-section. It combines 3DPVert, LUFA (for USB comms) and code to enable FFP's "force feedback"-mode at startup. The HID descriptor has also a few additional controls for extra controls.

3DPVert code in this prototype has been stripped to only contain FFP-related code for simplicity.

To see the device as FFB device (e.g. in FEdit or a game) you need to do the registry magic mentioned in the project wiki-page. The code outputs all force feedback data it gets from the host to its USART TX port so it can be viewed with a device reading serial data.

Re: Reverse Engineering the Force Feedback Pro

Posted: Fri Mar 09, 2012 6:39 pm
by cal
The thingy mostly works now.

The FF2 descriptor made the real difference in finding out what the WIndows PID driver really accepts. I've done full scale testing with FEdit, FConst and some preliminary testing with IL2 game too. With FEdit, I can play effects mostly fine. In IL2, there are some weird glitches and issues in the effects making it not really playable yet, but I consider this level of achievement as a proper proof of concept :)

Also, no need for that registry magic anymore - plug the joystick in and Windows will automatically generate correct OEM/FFB registry entries it likes to have. The decisive factor was the FF2 descriptors and that I needed to report a correct PID state reports when requested. None of which seem to be documented anywhere in sufficient detail - as you might guess. The FF2 descriptor also has several features not really supported by FFP (like phase or offset of periodic forces).

Creating effects, playing and stopping them work. The Windows USB-protocol implementation did (surprise surprise) not actually match the one described in USB.org's documents, but had some shortcuts that caused some pulling of hair (or what's left of it) at a time.

Almost all effect types now work when played using e.g. FEdit; constant effect, sine, triangle, square, spring, friction, inertia almost as much as FFP can support them. There were lots of nasty number format conversions and FFP limitations to stumble into. Ramps are not fully working yet - FFP also has very strict limits on what kind of ramps it actually can perform (only rampup from MIN to MAX or rampdown from MAX to MIN - nothing in between).

FFP can play up to 10 effects simultaneously even tho it can hold 40 definitions in its memory. Both properties are now taken into account. The adapter now needs to keep all 40 definitions in memory (taking a lot of RAM) since USB data updates are not always sent to MIDI immediately and need to be cached in the adapter. Some optimization could be done but ATmega32U4 can just take it all already now.

Most on-fly updates to already playing effects are also now working. E.g. changing direction or magnitude of a force already playing work. There are some limitations in FFP as it does allow changing e.g. magnitude of already playing constant force, but not periodic forces.

All that after tens of hours of tedious trial and error, half-educated guesses and even a few reboots due blue-screens in XP. Windows 7 64-bit works too.

FFB also seem to affect the joystick position reports by making some of the values jump erratically every now and then. I remember seeing some button line activity when playing effects - possibly it reports to PC whether an effect is playing or not or something like that. At the moment, I just ignore all that data, but it might be causing the erratic jumps (and random reported button clicks) in the input reports.

I suspect that there are also issues with the way I use LUFA-library too since I run into random issues if I get a large burst of output data going to the joystick in a short period of time. There seem to be also some timing issues with the MIDI-data to joystick. There are also some timing issues in replying to some USB-requests too quickly from the adapter to PC. I hope to get these solved by getting in touch with some LUFA-experts. It now looks very plausible to have a generic sample force feedback joystick project added to LUFA too.

I have already updated some of the MIDI-protocol documentation parts in the project Wiki and I'll post the new version of the code in the coming days too.

Thank you to all involved - especially Grendel and Ulao - for the help and support to get this thing already this far! I hope we can finalize it to be actually playable with any decent game.

BTW: I just got a second FFP with €10 to make sure the efforts are not wasted for me if one happens to break...

Re: Reverse Engineering the Force Feedback Pro

Posted: Sun Mar 11, 2012 2:19 am
by Grendel
Congratulations, fantastic work ! Well done ! :)