Shop OBEX P1 Docs P2 Docs Learn Events
P2 USB Host driver (re-)development thread - Page 2 — Parallax Forums

P2 USB Host driver (re-)development thread

2456715

Comments

  • maccamacca Posts: 718
    edited 2023-04-29 08:36

    @Wuerfel_21 said:
    I think it's this change that broke it:
    Or rather, un-doing seems to resolve the issue.

    Yes, that was it! I don't know what I was thinking... it was effectively resetting (badly) the timing to full-speed even for low speed devices without hub.

    As a side effect (and not sure it was the cause) all issues I had plugging and unplugging low speed devices on the hub seems gone... I have a SNES replica gamepad that was almost always resetting the connection when unplugged and now seems to work reliably all times... maybe it is just a coincidence...

    Of course it was a coincidence... still resetting when unplugging... go figure...

  • Also, it seems that hkbd_ep_addr doesn't get reset when the keyboard disconnects, preventing any keyboards from enumerating on other ports. The disconnect routine expects the address to also be in hdev_ep_addr, which is explicitly cleared when the keyboard connects. Not sure how to fix this variable confusion. If only hdev_ep_addr were to be used, we couldn't use devices with multiple endpoints (such as the PS/2 adapter, which also has a mouse endpoint. I think combined kb/mouse wireless receivers also work like that?)

  • @Wuerfel_21 said:
    Also, it seems that hkbd_ep_addr doesn't get reset when the keyboard disconnects, preventing any keyboards from enumerating on other ports. The disconnect routine expects the address to also be in hdev_ep_addr, which is explicitly cleared when the keyboard connects. Not sure how to fix this variable confusion. If only hdev_ep_addr were to be used, we couldn't use devices with multiple endpoints (such as the PS/2 adapter, which also has a mouse endpoint. I think combined kb/mouse wireless receivers also work like that?)

    Ah.. I always get a reset when unplugging the low speed devices here so it is very difficult for me to check these issues.
    The hub disconnect routine should check the hdev_type instead of the endpoint address and clear the dedicated variables. This should also allow to have keyboard/mouse combo working by restoring the original mouse handler routines.

    Will try to fix it and also clean a bit that hidle loop.

  • While you do that, can you properly mark all the ALTx replaced fields with 0-0 (or using the one-operand variants of GETBYTE etc)? Trips me up when reading code.

  • Wuerfel_21Wuerfel_21 Posts: 4,449
    edited 2023-04-29 18:54

    I've posted a public version of NeoYume with hub support, see other thread: https://forums.parallax.com/discussion/comment/1550065/#Comment_1550065

    Attached is also the VGA display thing with my current driver version. Raw display is currently out of order because I removed the buffer compare code.

    Slight obnoxiousness is that macca merged the keyboard buffers with the gamepad buffers, so now there's no easy way to check a key. Will have to figure out something (just moving it back into its own buffer seems silly, but it's only 8 bytes...)

    Actually, the gamepad report buffers are pretty huge and really not needed for gamepads where we usually don't care about discrete events to begin with, so maybe I will just get rid of them and then add back the keyboard buffer.


    Other thing I'm thinking about is loadable gamepad button mappings. Would be neat to share them between programs. To that end, I propose the following:

    • Mappings are stored in a file called PADMAP.TXT in the SD root
    • Each line (terminated by CR/CR+LF/EOF) is one "rule"
    • Each line may have any amount of leading and trailing whitespace (space or tab)
    • Empty lines are to be ignored.
    • A line starting with a # is a comment.
    • The first word (=contiguous run of ASCII 21..126) determines which application it applies to. "*" indicates a generic rule ("*abcd" does not!)
    • Irrelevant app-specific rules should be treated as comments (not parsed) to allow special extended syntax
    • The next word should be 8 hex digits (uppercase only) containing the device ID (PID/VID)
    • Following from that is a series of decimal numbers defining which HID button (1 based) to map to each virtual button. Zero means to not map the button. A # can also start a comment at this point.
    • Any excess buttons are to be ignored, any missing buttons to be filled with zero
    • The first 10 buttons are standard and correspond to the common-ish layout of most HID controllers. In order:

      1. North face button
      2. East face button
      3. South face button
      4. West face button
      5. Upper left trigger
      6. Upper right trigger
      7. Lower left trigger
      8. Lower right trigger
      9. "Select" or equivalent center button
      10. "Start" or equivalent center button
    • An app-specific rule can override a generic rule (regardless of position in the file).

    • A generic rule should not override preset rules compiled into the application
    • An application should be able to load at least 16 rules (~256 bytes of buffer after parsing) on top of any built-in ones (not counting overridden rules). Excess rules should be discarded, but overrides can still happen when the buffer is full.

    Example:

    # Application  PID+VID   N  E  S  W L1 R1 L2 R2 Sl St
    
          *       0E6F1112   4  1  2  3  0  0  0  0  9 10 # NeoGeo mini
          *       1C590026   1  2  3  4  5  6  0  0  7  8 # THE GAMEPAD
       megayume   0F0D00C1   1  8  2  3  4  7  0  0  9 10 # RetroBit 6-button controller
    
  • I figured out a better way to map controllers to virtual players. Instead of just using the hub port number, I count the number of gamepads connected to lower-numbered ports than the current one and use that. This means you can use any port on your hub for a keyboard (useful if you have a keyboard with inbuilt hub) or other device.

  • roglohrogloh Posts: 5,151
    edited 2023-05-01 03:22

    Just tried out your latest test rev on P2-EVAL with a cheap USB hub and a real USB gamepad on one port and that USB arcade breakout board I have on another USB port. Seems to work nicely. Cool! :smiley: I also hot swapped around between physical USB ports and it seemed to follow your latest logic - I didn't connect a kbd yet though. So far haven't seen any reconnection hiccups either which is good.

    I will have to try NeoYume again with your latest USB work @Wuerfel_21 - much of that stuff was on my older MacBookPro and I'm using another Mac now so I still have to migrate it over...story of my life ATM unfortunately.

    Update: I just fit a USB keyboard to the hub (in addition to the USB gamepads) and do see the arrow keys and ZXCV plus enter and backspace keys influencing the player 1 controller buttons. Nice. :smile:

  • Few changes today...

    • Restored mouse support, for now it handles only single devices (no keyboard+mouse combo support, need to find how to handle that)
    • Restored keyboard LEDs toggle, with support for CAPS LOCK handling
    • Removed the error check from the interrupt report calls, this seems to avoid the resets when unplugging a device (the chances that the device in unplugged in the middle of a transaction is very high). Hope doesn't cause endless loops somewhere else.
  • Got stuck trying to merge new macca changes due to flexsplorp (I think there's something busted with conditional ASM, which I tried to use to gate the mouse code to reduce bloat for applications that don't need it.)

  • Though it does seem that removing the error check increases stability!

  • Wuerfel_21Wuerfel_21 Posts: 4,449
    edited 2023-05-02 14:25

    Also, here is the current driver test thing. I've re-done it to have a pseudo-graphical display of the EmuPad data. It also includes the mapping parser, but using a DAT string as the source, which allows you to verify PADMAP.TXT rules without taking out the SD card.

    The driver now also lets you set the basepin dynamically and has a keyboard state check method.

    Next up I think I'll make a Spin interface to the full HID reports. And also an event-driven keyboard interface. Not sure if I want to include scancode->ASCII conversion in the driver proper (given that it can get complex really fast when you want to support different layouts, their deadkeys, etc. Chinese/Japanese IME composition anyone?) And hopefully by then I can get the mouse stuff integrated without the compiler throwing up...

  • There's now a hidpad_to_vga.spin2 and an emupad_to_vga.spin2 for showcasing their respective APIs.

    If you're wondering what the difference is:

    EmuPad: for emulators and simple games
    + Reads both keyboard and gamepads
    + Automatic button map handling
    + Automatic player assignment
    + Automatic analog stick -> digital conversion
    + Reports written to the location of your choice, in the format of your choice
    - (currently) limited to 10 buttons and digital directions
    HIDpad: for advanced usage
    + returns everything from the device (including caps and device VID/PID)
    - brain hurt

  • Unrelatedly, it seems that people have figured out (?) the XBox One protocol, too, so that might be interesting to add. It seems that it uses subclass $47 and protocol $D0, needs some sort of startup command and uses a slightly different stupid proprietary format.

    Don't have one though. If someone who does wants to try getting it going with me, I'd be down for that.

    Relatedly, I think Switch controllers just work? Leave it to Nintendo of all gaming-related capitalistic entities to respect a standard. Don't have an actual 1st party one, but the 3rd party wired controller I have just works (after fixing the button map through PADMAP.TXT, of course :) )

  • I've pushed the git repo I've been using to locally track changes to github now: https://github.com/Wuerfel21/usbnew

  • roglohrogloh Posts: 5,151
    edited 2023-05-03 13:19

    Just confirming the latest code posted above seems to work nicely with a PS3 game controller (in case that has not already been tested). Left analog stick maps to U/D/L/R buttons and both L&R 1&2 trigger buttons work as well. Nice.

  • Genuine sixaxis/DS3? I'm only testing using a cheapo.

  • Yeah it's a real Sony dualshock 3 sixaxis.

  • pik33pik33 Posts: 2,350

    How complex it can be to add a mouse to this driver?

  • maccas version already has mouse, but for me it stopped working when I tried adding it, seemingly due to compiler bugs. Planning to add it soon when we can figure the bugs out

  • Ok, will give the mouse stuff another try. Currently trying to think of the nicest API I can expose for it. It's slightly tricky because unlike the keyboard and gamepad, which send absolute states, the mouse sends position deltas. My best idea is to accumulate the deltas into 32-bit values and optionally allow setting a clip limit (i.e. if its zero you get infinite relative positions, if non-zero it clamps between zero and the limit)

  • Well, weird if/else issue still exists, so no mouse today. But I managed to at least isolate the bug.

  • pik33pik33 Posts: 2,350

    If you can, also allow the user to receive the raw mouse buffer.

    Mice are strange beasts :) I experimented with them in Ultibo on Raspberry. The problem was: no wheel in boot mode. There is a wheel field in the boot mode specification, but it didn't work in Ultibo.

    So I hacked the mouse driver to init it in the full report mode. That opened "a box with Pandora" (This is a real quote from one of our politicians... he means "Pandora's box"). I tested several mice and discovered 8-, 12- and 16-bit protocols, at least 5 different of them... ended with an overengineered and still not 100% working algorithm that recognizes the mouse language based on its reports.

  • @pik33 said:
    So I hacked the mouse driver to init it in the full report mode. That opened "a box with Pandora" (This is a real quote from one of our politicians... he means "Pandora's box"). I tested several mice and discovered 8-, 12- and 16-bit protocols, at least 5 different of them... ended with an overengineered and still not 100% working algorithm that recognizes the mouse language based on its reports.

    You know, there's a correct way to do that ;P
    We already have barebones HID descriptor parsing for gamepads, should be easy-ish to adapt to mice. I'd assume a mouse descriptor is normally less ridiculous Or maybe more. If I find a mouse that necessitates it, I might look into it. Wonder what goes on with an expensive programmable mouse like my Logitech G502...

  • @pik33 said:
    If you can, also allow the user to receive the raw mouse buffer.

    Mice are strange beasts :) I experimented with them in Ultibo on Raspberry. The problem was: no wheel in boot mode. There is a wheel field in the boot mode specification, but it didn't work in Ultibo.

    So I hacked the mouse driver to init it in the full report mode. That opened "a box with Pandora" (This is a real quote from one of our politicians... he means "Pandora's box"). I tested several mice and discovered 8-, 12- and 16-bit protocols, at least 5 different of them... ended with an overengineered and still not 100% working algorithm that recognizes the mouse language based on its reports.

    +1 Giving a P2 access to any extra button states and a scroll wheel would be very handy for mouse based USB HIDs. Unfortunately the boot protocol is limited and mice with extra features fall back to some lowest common denominator 2 or 3 button device with that report. With so many possibilities at least getting access to the raw report descriptor could be helpful. It would then be up to the client code to parse and make sense of it.

  • Wuerfel_21Wuerfel_21 Posts: 4,449
    edited 2023-05-06 20:16

    You get either the boot protocol report OR the full report. So if the driver is running boot protocol there is no backdoor to sneak out the full report because it doesn't exist (and if there was, it needs theoretically unbounded (in practice I think the max USB1.1 packet size is 256 byte?) buffer space, which I've eliminated on the gamepad side.

  • roglohrogloh Posts: 5,151
    edited 2023-05-06 20:56

    @Wuerfel_21 said:
    You get either the boot protocol report OR the full report. So if the driver is running boot protocol there is no backdoor to sneak out the full report because it doesn't exist (and if there was, it needs theoretically unbounded (in practice I think the max USB1.1 packet size is 256 byte?) buffer space, which I've eliminated on the gamepad side.

    Yeah so it has to be an either/or operating mode then, if it could be supported at all.

    Another thing I found when hacking around with mice and my video driver is that it was very handy to have the usb mouse driver code deposit its X/Y coordinates directly into a long in HUB RAM. That way my video driver could synchronously update the mouse sprite on every frame without needing an additional COG to do this work and waiting on the video driver timing.

    Without a COG dedicated to doing this I found the mouse update on screen could get jerky. If some hook could possibly be added to call an optional custom HUB RAM function or something on each USB mouse update it might be useful way to save a COG that otherwise updates the mouse co-ordinates in the video driver. This would be a very short function call. It might need to just scale X,Y into 16 bits each and atomically write it into a given long address in HUB. When I did it like this it allows silky smooth updates without any real COG overhead. The co-ordinates are just screen pixels for the given resolution. Without this capability it just gets more painful to achieve.

  • pik33pik33 Posts: 2,350
    edited 2023-05-06 20:59

    All what I got with the hack were 8 (first?) bytes of the report. Nothing unusual in there: dx,dy,buttons,wheel. The differences were length, position and odrer of the fields. 8 and 16 bits are simple, but I have a wireless Logitech mouse - a 12-bit nightmare :) You have to split bytes to nibbles and combine these nibbles to fields.

  • @rogloh said:
    Another thing I found when hacking around with mice and my video driver is that it was very handy to have the usb mouse driver code deposit its X/Y coordinates directly into a long in HUB RAM. That way my video driver could synchronously update the mouse sprite on every frame without needing an additional COG to do this work and waiting on the video driver timing.

    Yea that's what I think I'll do. Do you mean one word for X/Y each or one long each? I'm favoring the latter. But it'll dump it in it's own DAT area.

  • @pik33 said:
    All what I got with the hack were 8 (first?) bytes of the report. Nothing unusual in there: dx,dy,buttons,wheel. The differences were length, position and odrer of the fields. 8 and 16 bits are simple, but I have a wireless Logitech mouse - a 12-bit nightmare :) You have to split bytes to nibbles and combine these nibbles to fields.

    I was talking about the descriptor itself having weird bytecodes in it. The driver already has a function to read arbitrary bit fields.

  • Ok, I've merged in basic mouse support. Get from GitHub. I've wrenched basic mouse info printing into the hidpad test, but I can't get the cursor to appear in @rogloh 's funny video driver. Please tell me what I'm doing wrong.

Sign In or Register to comment.