P2 USB Host driver (re-)development thread
Wuerfel_21 Posts: 3,788
edited 2023-05-07 20:50 in Propeller 2
So, as mentioned elsewhere, I'm looking to revamp the current USB driver landscape a bit, since it's a major pain point right now.
So far I'm trying to work off @macca 's hub-supporting P2ASM-only version.
Goals so far (in order of importance):
- Improve stability and device support
- Implement "EmuPad" interface for Keyboard/gamepad similar to what my emulator programs currently use (input data gets placed in user-provided location with button remapping already applied). Allow dynamic loading of mappings.
- Implement low-level interface for Spin applications (query device presence and raw report)
- Allow compile-time configuration to disable un-needed components
- Allow polling to be synchronized to external event (COGATN) for consistent input latency.
- Re-implement functionality lost in macca's version (Keyboard LEDs and mouse)
- Implement high-level interface for Spin applications
Current device support issues I am aware of:
- Hotplugging some devices seems to hang the driver until disconnect (flashing error LED). This even more so if the plugging is happening on a hub port. Maybe just power-cycle the bus in such cases.
- PS/2 adapter doesn't work through hub (LED flash) (UPDATE: Fixed!)
- Weird poll rate / NAK issue with NeoGeo mini controller (might magically disappear again) (UPDATE: yes seems to disappear without debugger loaded)
- 8bitdo SN30pro still doesn't correctly initialize (bus analyzer action required)
Further interesting observations:
- NeoGeo mini poll rate /NAK issue seems to disappear with DEBUG disabled. Curious.
- The PS3 report format has a lot of stuff going on, wow. Pressure sensitive buttons anyone? (I didn't know my cheap-at-the-time StrikeFX even HAD those!)
Also, here's the first awful little program. It just displays the reports from memory on VGA, which is how I came to the two factoids above.
Still the abovementioned issues. I tried to make it reset on error, but it seems like
host_resetdoesn't properly reset something and the whole thing crashes, so I backed that out again.
Ah yes, inexplicable memory corruption. My favorite. This is after I fixed another one already (
Okay, I think I "fixed" all the memory corruption issues (seriously awful to just modify the pointers in place like that...)
It seems like something doesn't quite get reset still... It is possible to get it into a state where plugging the hub in (with no devices) leads to an infinite reset loop still. Though the likelyhood of hotplug working has increased.
As it were, I suffer in my own hell because that oopsie was introduced by me earlier.
OK, I think I brute-forced the stability issues away. I can hotplug any old carp (including the hub itself) and it just re-tries until it works. Even if I plug in a device that causes it the great madness (like the PS/2 adapter), it will just re-try until I remove the offending hardware.
Well, that's nice I guess.
Was trying to run this and try out my own gamepads to see what happens but ran into issues.... it's been a while since I messed with my P2 board and flexspin etc and haven't been following the most recent P2 developments lately but I seem to be getting this syntax problem now... maybe a newer version of flex will fix it. I'm still on 5.9.26 from a couple of months back by the looks of it.
Here's what I get with flex:
Did we get some new conditional IF compilation support in the end? Or is this something to do with using other toolchains? I did just read this...
EDIT: Ok just downloaded the latest version 6.1.1 of flex and the problem disappeared. Probably related to the new feature:
"Also supported now are Spin2 FIELD and ^@ operators, and conditional assembly directives. "
Oh yea, should have mentioned that. Ideally, use the cirrent git master of flexspin.
Oh yea, should have mentioned that. Ideally, use the cirrent git master of flexspin.
I was thinking if wouldn't be a better idea to rewrite the driver with only the core functionalities and leave the "high-level" functions to the spin (or pasm) program, to allow support for other devices, like serial adapters, pen drives, etc. A more generic usb host driver, that is.
I was looking at the P1 usb host driver. The exposed spin methods are way too low level, but it gives the idea of what I would like to do. Basically the driver would just handle the low level connection, disconnection and data transfers. Everything else, from the device enumeration, to interrupt data read (or whatever the device needs), will be handled by Spin (or pasm) through a mailbox.
BTW, I just tried your source with the conditional directives and seems that the implementation I'm working on for my tool works (need to rewrite them as C-style directives, but works).
Coming from the intent of having better input in the emulators, having to externally wrangle the USB driver while it still hogs a cog is a non-starter. The other cogs are all busy doing something. Though I can see how removing complexity from the driver is attractive ;3
I can see your point Wuerfel_21. For emulators using HIDs using a single COG for all processing is pretty nice.
Longer term for the P2 it could be good to have a (different) more extensible USB driver that can support other devices in a more generic way. Perhaps looking at how other embedded platforms expose USB would give hints as to some handy APIs and framework to provide. There was this LUFA project for AVRs I once used that seemed quite extensible and reasonably easy to use USB from client code, although there are likely others too by now.
Yea, having choices is good
Yes, right, I was actually thinking about a more flexible way to handle devices, with the option to embed the handler in the USB cog, and if the device is unknown notify the application so it can handle it.
I guess that at least the initial device configuration must be done by the driver.
Making the drivers more modular, certainly. Maybe store all device data in RAM and burst read/write it into some generic cog registers when using that device. If this memory is allocated sortof-dynamically, we possibly could even have nested hubs and such.
But that's a future thing. Right now I just want well-working inputs
I've started to implement the new EmuPad code.
- report up to 10 buttons + 8 directions + device presence into an array of longs in user-provided memory
- report format configurable by spin constants
- support for any HID device (with ability to load button maps from file)
- keyboard support (maybe also file-loadable)
Current "hot garbage" proof concept code is attached. I've also wrenched it into NeoYume (MegaYume does more complex stuff) for a little proof-of-concept:
Nice one. Good to see it already doing something interesting in NeoYume. Will eventually have to get another one of these and build up a second joystick setup soon for proper dual player gaming.
FYI, I'm working on some code cleanup, mainly label renames to be more "consistent" to what they do, get rid of all those buffers management, etc. but also a couple of optimizations (got rid of those double pre/cur report buffers). I'll push the changes after some testings.
I already got rid of the cur/pre in mine because otherwise it wouldn't fit into the ~12k that NeoYume leaves for the input blob...
(Also, there really needs to be some attention to making sure it can't get stuck in any state... Yesterday I had the USB lock up completely a number of times while demonstrating on live forum. Presumably related to the slightly loose miniUSB port on my hub.)
AFAIK managing error states is one of the biggest challenges in USB... god speed for this implementiation. Is there any work on USB devices? I'd love to be able to use P2 directly as USB serial or HID device.
@macca see that you pushed your stuff. In my version I reduced the large buffers to 4, because 0/1 are redundant.
Also, the dpad -> hat conversion in the Xinput/PS3 codepaths can be optimized (and actually, a lot of the XInput stuff). See the last ZIP I posted. Routine should still slot right in.
Anyways, will deal with this tomorrow hopefully.
I got USB serial just barely working, transmit only. (not published yet) https://forums.parallax.com/discussion/175254/usb-device-serial-device But with USB, just enumerating is half the battle.
Yes, that could be removed, I need to verify the hdev_port usage because 0 means the device is directily attached to the port (1-4 are the hub ports).
I tried to use your updated code but seems there is something weird with the axes, the values are not at all right.
Does the ## in this instruction
rdlong hidr_axis+0, ptrb[##6]have a special meaning ? Because I don't support it and maybe it is the cause of the issue (doesn't look the right position of the axis value).
Nevermind: SCALE is 1 for BYTE and LUT operations, 2 for WORD operations and 4 for LONG operations. When using an augmented operand (##/AUGS), SCALE is always 1.
Thanks to your online documentation, I can't find a reference in the Parallax docs...
I have pushed some changes to automatically reset the device in case of errors (instead of waiting forever for a command that can never arrive...).
May not be the ideal solution because all devices are rescanned and initialized but at least it should not be necessary to unplug the hub.
Oh, I made the reset-on-error change as well, but I see you added some stuff to make double sure that the modes and such are correct.
Just tell me when you think you're done so I can do my thing without having to constantly merge in upstream changes.
Ok, getting back to this, I merged your changes in @macca.
However, I think your busted keyboard support on the root port. Not entirely sure what is going on, it seems to configure correctly. Then it gets a NAK on the first poll (as normal), but the next poll times out and the driver resets.
I think it's this change that broke it:
Or rather, un-doing seems to resolve the issue.
Also, I figured out why the PS/2 adapter doesn't work on hub: not enough delay after reset. Really needs a lot, too. Sent this as a PR.
Good detective work. Allowing older PS/2 type devices via USB adapters/hubs will be handy. I for one have an old school PS/2 trackball which could make a good controller in some cases where pointing devices are used.