necroware / gameport-adapter

GamePort adapter to connect old DB15 joysticks to USB port
GNU General Public License v3.0
289 stars 55 forks source link

Added support for daisy-chained sidewinder gamepads #84

Open dferyance opened 8 months ago

dferyance commented 8 months ago

This is adding support for up to 2 daisy-chained sidewinder gamepads. The code is generic enough that I think it will work with the maximum of 4, but I don't have 4 to test with.

Partially fixes #10 . The reason I say partial is that issue 10 is also requesting passthrough. These changes do not address passthrough.

MacGH23 commented 8 months ago

1st: 2 are working without problems, but only with exact 2. If I attach only 1 I get an Unknown USB Error And also no Joystick is working any longer. 3D Pro or FFB. But this can also be a problem with the lastest source source itself because it it also not working. https://github.com/necroware/gameport-adapter/issues/85

I have 4 for testing. I changed to 4 in sidewinder and Joystick.h static const auto MAX_GAMEPADS{min(Joystick::MAX_JOYSTICKS, 4)}; static const auto MAX_JOYSTICKS{4u}; Was this right ? Then it is not working with 1,2,3 or 4.

dferyance commented 8 months ago

I was playing around with it more last evening. Something odd is happening with the joystick count. I don't know if it happened when I synced my branch or what because I had had tried those scenarios before. This will take some investigation. I'll post an update.

MacGH23 commented 8 months ago

Look like you used the current main which break the support of the 3D Pro

JocPro commented 8 months ago

1st: 2 are working without problems, but only with exact 2. If I attach only 1 I get an Unknown USB Error And also no Joystick is working any longer. 3D Pro or FFB. But this can also be a problem with the lastest source source itself because it it also not working. #85

I have 4 for testing. I changed to 4 in sidewinder and Joystick.h static const auto MAX_GAMEPADS{min(Joystick::MAX_JOYSTICKS, 4)}; static const auto MAX_JOYSTICKS{4u}; Was this right ? Then it is not working with 1,2,3 or 4.

I second this. I was testing yesterday and thought that I had bricked my adapter. Tried today with 3 and 4 Sidewinders and noticed exactly the same behavior, Unknown USB device unless it's configured for 2 gamepads with both connected.

dferyance commented 8 months ago

Thanks for testing. Yeah, I'm not sure what went wrong but I'll post an update when I figure it out. A couple of tips though if you have difficulty with the arduino being recognized:

dferyance commented 8 months ago

The code was using too much ram when storing the USB hid descriptors. I cut that back down to the original size by re-using the descriptor for all 4 gamepads. I also found a case where the joystick count wasn't being detected properly. This could be what was impacting other sidewinders.

Haven't so far it is running good for me with 1 or 2 gamepads and the max count set to 4. I don't have other sidewinder accessories to try though.

MacGH23 commented 8 months ago

Hi, Thanks for the update. It is working better :-) 1-2 are working without problems. With 3 attached sometimes the game control panel is not coming up. I see the adapter but with a "clock" waiting. A reattach of the USB cable helps normally. But if correctly recognized, all 3 are working without problems simultaneously.

With 4 attached, the LED on the side of Pin14 is blinking rapidly, 3 are working, but sometimes (see 3.) game CPL is hanging.

3DPro ist still not working at all. But I guess this is a problem of https://github.com/necroware/gameport-adapter/issues/85

MacGH23 commented 8 months ago

@dferyance If you need 2 more for testing, the old ones are quite cheap to get in Germany. If you like I buy 2 pcs and send it to you. Or you can buy it yourself and I can send you the amount via paypal ;-)

dferyance commented 7 months ago

I acquired 2 more gamepads via ebay. 3 seems to work ok, and I can replicate 4 not working. I suspect it is a power supply issue. The last one in the chain has a very dim led and I also see a blinking light on the arduino. This will take some investigation but it is possible that the 4 just won't work with the hardware. I might have some time this weekend to look into it.

What is odd, I'd expect that all 4 leds would be in parallel and thus the same brightness. But instead, it is acting like it is wired in series and each one down the chain is a little dimmer.

necroware commented 7 months ago

This has to be a serious issue. USB 2.0 gives you up to 500mA. Arduino takes around 200mA and each gamepad takes about the same. Already with two gamepads in series you risk to burn your USB port. I wouldn't suggest to use more, than one joystick per USB adapter without additional power supply with at least 200mA per device. For four devices and the arduino you'd need at least 1A.

MacGH23 commented 7 months ago

You normally can not damage the USB port. You just get only 500mA I made some measurements with a USB-C power meter

But even is 3 is the maximum, it is still a very great improvement !!

necroware commented 7 months ago

You can actually destroy an USB port if it has no over current protection. I fried one, so speaking out of experience :) Arduino can take in peak up to 40mA per input. May be it takes 60mA in average, but we have to keep an eye on the peaks. measurement with an oscilloscope would be interesting. The other values with gamepads are kind of suspicious. First one takes 15mA, second and third only 5mA, that is strange. I might be wrong, but I'd expect that to be linear. That the last one takes only 2mA is a sign, that it doesn't initialize properly. Well, assumptions, assumptions, but as I experimented with Sidewinder 3D Pro in the beginning, I saw peaks of 400mA.

MacGH23 commented 7 months ago

The newer USB normally should have a protection ;-) Just measured again with 3 other Gamepads. More or less the same result. I try to setup a Osci measurement next week

dferyance commented 7 months ago

It looks like the arduino pro micro has a PTC on its input. This is good to help protect the USB port. But it likely is causing some voltage drop. I'm seeing a lower voltage (3.6v) on the end of the chain with the gameport adapter while with my real gameport I see about 4v.

My guess is the sidewinder intentionally has a diode drop on the power lines to avoid overloading the gameport if you plug in too large of a chain.

It could be the combination of PTC + diode drops causes the 4th to not have enough voltage. So far I don't see this happening though. I used an interposer to inject power directly into the 4th and it still doesn't communicate. So that points at a communication issue.

MacGH23 commented 7 months ago

Had the same Idea and also added an add. 5V power to the last one. Same result. Rapid blinking. I measure 5V on the VCC of the MicroUSB version.

MacGH23 commented 7 months ago

Made a Osci measurement, since forgot the modified cable for the lab, I did only some voltage measurements. The 5V raises within 5-7ms to full 5V without any drops. 100% stable with 4 gamepads. I measure the current next week

MacGH23 commented 7 months ago

The latest fix for the 3D Pro fixes also the non working 3dpro with the daisy chain mod https://github.com/necroware/gameport-adapter/issues/85 I copied the 2 lines in the Hidjoystick.h and now 3D pro and gamepads are working. Please include it in your merge ;-)

necroware commented 7 months ago

Nice! This is a very cool contribution. I would like to rethink how joysticks can be registered and may be change the interfaces, so such things can be made easier in the future, but I'll have to think about it a little bit. Give me some days to propose something.

So far one more question, is it actually possible to daisy chain different (Sidewinder) devices? Do you know, what Microsoft says about it?

MacGH23 commented 7 months ago

Yes, with a real Gamport you can add a Microsoft Joystick behind a MS GamePad. But You have to press the "Mode" button on the GamePad and the GamePad uses pass-through mode and disappear from the game device list and the e.g. 3DPro was shown. You couldn't use both at the same time. With the firmware the Mode button just do nothing (with only Gamepads attached), except the Gamepads does not deliver any data. Pressing the mode button again everyting is working fine again. If I add the 3DPro behind the GamePad the firmware don't recognize the Gamepad and the Joystick if I press the Mode button. But this I guess is not a big issue ;-)

BTW the fix for the 3Dpro dosen't fix the max3 devices issue.

MacGH23 commented 7 months ago

Here some Info from an old KB https://www.betaarchive.com/wiki/index.php/Microsoft_KB_Archive/179658

dferyance commented 7 months ago

I was able to look over this a little over the weekend. My current hypothesis is there is a problem with the way I did the USB-hid code. I can replicate the error with no game pads connected in analog mode by hard-coding the joystick count to 4. I also was able to check the sidewinder communication with my logic analyzer with 4 and all 4 are sending packets ok. So this is pretty much ruling out anything to do with the sidewinder connection.

The USB hid is tricky as it has to detect how many you have in the chain instead of knowing ahead of time how many interfaces to report. Even with the logic to initialize the pluggable usb later in the initialization process, I think some kind of state or counter must be getting setup wrong. This is hard to trace through especially as turning on logging disables the rest of the USB.

I feel like there should be only a single instance of HidDevice instead of the 4. But this may require more significant changes to the USB code than I had hoped to get away with.

dferyance commented 7 months ago

This puzzle has been bothering me so I was digging through USB code late last night but I finally found the exact problem. It ended up simpler than I had thought. The USB stack has some tight limits. The number of endpoints is limited to 7 in USBDesc.h. 1 endpoint is the control endpoint, 3 are taken up by the serial comms so that leaves 3 for our use.

The USB code in question is part of the arduino libraries. So it isn't a simple change to this repo to increase the limit. The one option I see that doesn't require modifying the arduino libraries is to disable the CDC serial console by defining CDC_DISABLED. This has the downside that you must enter bootloader mode to re-flash the firmware. But disabling CDC does work.

image

necroware commented 7 months ago

Yes, I thought about it yesterday, that the limitation might come from the Arduino library itself, but I had no time to answer. I would say, we can mention it in the documentation, but per default we should just limit the amount of gamepads to 3. In the most cases nobody has as many SW Gamepads and if more required, you can still use another adapter. With USB it is not a problem. This daisy chaining feature was introduced back then, because GamePort was usually limited to one on a PC. It's cool to have it implemented though, I just have to find some time to rearrange the device registration code a bit.

MacGH23 commented 7 months ago

Thanks for finding the root cause. Then i don't need to measure the current tomorrow in the lab ;-) I would also see 3 as a maximum is a good solution. Better than i ever expected ;-) I have 6 Pads, so 2 adapters would be fine.

Perhaps we can raise a issue at Arduino lib to increase the USB stack ;-)

dferyance commented 7 months ago

The ATmega32U4 datasheet indicates:

Endpoint 0 for Control Transfers: up to 64-bytes – Six Programmable Endpoints with IN or Out Directions and with Bulk, Interrupt or Isochronous Transfers

So looks like a MCU limitation.

dferyance commented 5 months ago

I updated my branch to include a calculation regarding how many endpoints are available. So if you build it with defaults, it will auto-limit to 3. But if you build it with CDC_DISABLED, it will allow all 4. I changed up error handling to allow for connecting all 4 when only 3 are supported. That used to error out entirely.

I think this is the best we can do. With CDC enabled (which is default), you don't need to go to bootloader mode to reprogram and it is limited to 3. But with CDC disabled, all 4 are supported but reprogramming requires bootloader mode.

MacGH23 commented 5 months ago

Perfect - Thanks

MacGH23 commented 5 months ago

Just tried it on Win11. Unfortunately only 1 Gamepad is detected and this is also very slow. Win10 is working without problems