-
Notifications
You must be signed in to change notification settings - Fork 125
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BUG] capture_hid_report fails on cheap ONN Mouse from Walmart using QT Py RP2040 #18
Comments
I have now tested with two different brands of mouse. A Magic Eagle "gaming" mouse which works fine and a cheap "ONN USB Corded Mouse" from Walmart which never enumerates. Here is a link to the bad mouse (you can grab one for $8 at Walmart - it says it's a "best seller"). I have attached the descriptors and the wireshark captures for both devices to this comment.. I don't see an obvious difference so it might be at a lower level. However, I'm certainly no expert in USB traces. These are the ones that worked: I am no longer blocked by this issue, but please let me know if I can help in any way. |
IMHO, example currently only works as proof of concept. Most important thing is having the electrical signal works, above that is simply software protocol stack. Support all mices/keyboards are not easy, even tinyusb with more focused software still haven't supported all devices. I think you would have higher chance to get it work by SET_PROTOCOL to boot mode instead of report mode. I am working on #14 , that would help to glue the tinyusb software stack with this awesome pio controller, that would thing easier for user. Just subscribed and watched out for PRs. |
Hi @ATMakersBill did you get any solution for this? I have the same problem (#19) |
I think some of the cheap mice actually show up as hubs. There's good reason for this (they can reset the "mouse" part without losing the USB connection) and I think it might be throwing off the USB stack. |
I have tested this library with a few devices and most of them work fine, but I too have encountered some that don't work (same problem: enumeration failed): Microsoft Basic Optical Mouse v2.0 (Vendor ID: 0x045e, Product ID: 0x00cb) |
I am starting to think some of these devices are actually acting as hubs
with one device attached (so they can reset without disconnecting
perhaps)? Does that make any sense?
…On Mon, Apr 11, 2022 at 3:36 PM Jacek Fedoryński ***@***.***> wrote:
I have tested this library with a few devices and most of them work fine,
but I too have encountered some that don't work (same problem: enumeration
failed):
Microsoft Basic Optical Mouse v2.0 (Vendor ID: 0x045e, Product ID: 0x00cb)
ISY 4-Port USB 2.0 Hub (Vendor ID: 0x1a40, Product ID: 0x0101)
—
Reply to this email directly, view it on GitHub
<#18 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AH2UJUR2NCZTEWINUQGXTATVESEOHANCNFSM5RMDULXQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
--
Bill Binko
***@***.***
"Helping Makers Help Others"
Join us at http://atmakers.org
|
I don't think this is the problem, because I have another hub that works with the library. Also when I connect the problematic mouse to a PC, it doesn't show up as a hub. |
Hello all, |
Hi All, Amazing concept and great work getting it this far! Unfortunately I'm seeing this issue too. Using a similar random USB keyboard, I see lots of disconnections and reconnections, with occasional brief periods of stability. Not a new keyboard yet similar wallmart special, first time I've had an issue with it. @moc32 's suggestion gave me a good place to start. I'm seeing missing acks too. Adding a dash of debug to the pio_usb_bus_receive_packet_and_handshake function is pointing at the rx pio code experiencing some sort of bit errors. I'm printing the following inside pio_usb_bus_receive_packet_and_handshake based on good / bad crc (ignore the various CRC prints, I was trying to match them up to that calculated by my logic analyser):
Here's the debug output produced:
The good packet as seen by the logic analyser: The data of which matches the good print statement (if you byte swap the crc). The bad packet as seen by the logic analyser: Here's the data captured by the pico vs data captured by the logic analyser:
Seems the rx pio somehow got way otta wack with the bitstream at the bytes indicated by the carot? I'll start poking around in the pio code, @sekigon-gonnoc any pointers? Thanks, Phil |
Believe I've found the problem....and it's going to be tricky to solve. Enabled the debug version of the rx pio code (nice touch). Updated the side sets to drive the debug output high, for one cycle when dm pin was being sampled via the jump instruction. During a failure I see the following at the start of the packet: The debug pulses indicating the execution of the "jmp pin" instructions. Nicely centered in the bits. The pico read 804B12011001000000 before going wrong at 88FC7B, which should have been 081177. Looking at those bytes near the end of the packet: The sample point appears to be getting closer and closer to the transitions. Given that there's a two flip flop synchroniser on the PIO inputs, assuming that synchroniser is clocked off the pio clock (the datasheet isn't clear), then the input being processed is almost certainly from the previous bit. Which would make sense in at least the first error case with 0x08 becoming 0x88 by the last bit getting mis-sampled, with the transition missed and a rouge 1 added. The pio code could do with resynchronising on each edge. It seems to only synchronise on the first edge at present then assumes a perfect clock from the remote device for the entire 96 bit run. Seems that doesn't go well with old / cheap devices which don't have accurate clocks. At the same time squeezing that functionality in is going to be tricky. Possibly moving the bit decoding and unstuffing into the host to free up some instructions. Allowing the input to be re-synchronised on each edge. While adding a counter to take timed samples where there are no edges. Then its just a case of working out when the packet ends and how long it is / ensuring the final bits in the ISR which may not be a multiple of 8 due to the stuff bits are offloaded to the host. I'm tempted to have a go....for the challenge.....but I'm also looking at a $3 usb hub chip that'll save me hours of pio tinkering 😅. |
Thank you for the detailed report. |
I love that there is a known problem. Our assistive tech mouse and joystick projects would still greatly benefit from this. If there’s anything I can do (including funding to help this) please let me know. |
@sekigon-gonnoc I had a go re-working (butchering) the receive pio code. Attempting to resync on the edges, while still handing bit stuffing. It's nowhere near PR ready but might serve as inspiration for a fix: https://github.com/pgreenland/Pico-PIO-USB/tree/attempt_to_resync_on_edges Moved the eop sm from pio1 to pio0, freeing up some code space in pio1 for the larger receive routine. The biggest snag I found was with 8 x oversampling, there's not that much time for additional instructions between bits. For my low speed device, I've upped the oversampling to 16 x for now, which has it enumerating and working reliably. That same tweak won't be possible with the full speed version though :-(. Also discovered (yet haven't tested) something that may allow you to share a single rx / eop program, rather than have to keep swapping programs. The pico has an input invert option between the input pads and peripherals, page 248 of the datasheet (INOVER). I may be wrong, but the RX code was identical, while only the initial two wait's in the eop code needed to change. This is due to the idle state of the lines with the pullup resistor moving between dm and dp to indicate the speed. You may be able to use a single rx / eop program and just toggle the invert option when updating the clock dividers if full speed is required. @ATMakersBill if you have a moment, try running the capture_hid_report example on my branch, be interested to see if your walmart mouse behaves any better? While exploring other options to add additional USB ports to the pico, SPI connected host controllers for example. I came up empty, without adding lots of additional cost to the BOM. Getting this working universally would be awesome. Ideally keeping a state machine and 6 instructions spare, allowing the Pico-W to continue using its wifi (it makes use of the PIO for its SPI comms with the wifi module). |
I’ll be happy to. Probably Wednesday before I can get hardware and a build env setup. My day job had an aggressive script kiddie corrupt some code and it was my bug that allowed it, so my tomorrow will suck :-/ |
@pgreenland very interesting work.
This code is just an idea. Adjusting delays and change host code may be necessary ; Rise edge and EOP detector
; x8 or x10 oversamping
; jmp_pin->dm in_pin->dp
; both gpios are inverted
; 15 instructions
.wrap_target
start:
wait 0 pin 0 ; Wait for sop bit edge
pin_went_low:
irq 0 ; Trigger NRZI decoder
pin_low:
jmp pin pin_went_high ; Jump if the pin is now high
jmp pin pin_went_high ; Jump if the pin is now high
jmp pin pin_went_high ; Jump if the pin is now high
jmp pin pin_went_high ; Jump if the pin is now high
jmp pin_went_low
pin_went_high:
pin_still_high:
irq 0 ; Trigger NRZI decoder
in pin, 1
mov x, isr
jmp x-- eop ; Jump to eop if jmp_pin and in_pin are high because both inputs are inverted
jmp pin pin_still_high
jmp pin_went_low
eop:
mov isr, null
irq wait IRQ_RX_EOP
.wrap
; NRZI decoder
; 17 instructions
start:
set x, 0
.wrap_target
set_y:
set y, 5
irq_wait:
wait 1 irq 0 ; wait signal from edge detector
jmp !y flip ; ignore stuff bit, without error check
jmp PIN pin_high
pin_low:
jmp !x K1
K2:
in x, 1
jmp y-- irq_wait
K1:
in null, 1
jmp flip
pin_high:
jmp !x J1
J2:
in null, 1
jmp y-- irq_wait
J1:
mov x, ~x ; x: 0->~0
in x, 1
jmp set_y
flip:
mov x, ~x
.wrap |
All sounds good to me! I'll be ready and waiting to test with my garbage keyboard :-P Let me know if there's anything I can help with. I hadn't considered only synchronising on one edge, or unrolling the loop - both awesome suggestions. No matter how hard I squeezed I couldn't get everything I tried into 8 instructions between edges. Disclaimer I haven't tried the input inverting - spotted it as an option in the datasheet after stumbling into a reasonable looking register in a PIO simulator. Checkout https://github.com/soundpaint/rp2040pio used it a few times for different protocols now. Bit of a learning curve but it saves a lot of flashing and poking of the pi. And you can step through instructions with the input waveform. I've got code prepared for USB, if you're interested let me know and I'll drop it in a repo. |
@pgreenland I will try the simulator. Could you upload the code prepared for USB? |
@sekigon-gonnoc I've dropped the simulation sources in a repo with some notes on how to get it going, along with my attempt at a new rx program: https://github.com/pgreenland/pio_usb_simulation - feel free to lift any useful bits / give me a shout if you get stuck. |
@pgreenland @ATMakersBill Could you try this if you have time? #62 |
I am back in my office where I have the cheap mice and the boards. My boards are based on the Adafruit QTPy RP2040 and the Kee Boar (https://www.adafruit.com/product/5302?gclid=CjwKCAiAwc-dBhA7EiwAxPRylG8lcBxP42VvFXJf8sFzszYO6Mio6AguK2F1cWfctbU0CxUxRGKufBoC4kcQAvD_BwE) - they have a pins GP0 and GP1 set as D+/D- and I was able to get the basic example working on the main branch. However, I will have to setup the build env again as that machine has been repurposed so it will take me a bit of time. I hope to get to it this week Thanks for the progress. PS: I don't think you're asking me to use the simulator - I've no experience with that. |
Just an update, I am getting this error when trying to build your branch (I tried with my PICO SDK and having it fetch one):
Any ideas? |
Please switch tinyusb to master branch. |
I can't use the compiled binaries as I use a different D+/D- pin configuration. The changes are trivial (see patch file attached) but I think I need to build. I have updated the submodule (forgot how to do that for a sec) and have started a build - will crash for the night though. Thanks |
Awesome! I'm a bit slammed this week but will give it a go at the weekend - my little test setup may need a bit of dusting off bit shouldn't take much to fire it back up. Looks like you tried the simulator? :-P Will let you know how I get on. Thanks, |
Having trouble getting any output at all... afraid I'll have to brush up on getting output to Putty etc... but I'm working on it |
@sekigon-gonnoc working perfectly now, great work! The USB keyboard that was failing previously now enumerates every time (at least 10 times in a row). No unexpected disconnections and hid data streaming over the serial port when running the capture_hid_report example. |
@pgreenland Thank you for your report. The simulator and your test bench were really helpful |
I'm also having problems trying to use some old low speed devices like keyboard, mouse, joystick. |
@sekigon-gonnoc the problem occurs during FS/LS detection? |
UPDATE: Thanks to Dan Halbert at Adafruit, I tried testing with not just two mice, but two DIFFERENT mice and the original code worked with the other brand. So, this issue is very different now... it's that Pico-PIO-USB doesn't enumerate or support a very cheap mouse from Walmart. My gaming mouse enumerated and reported fine.
So, we could close this one and open a new issue or update this one - I'll add the new info in a separate comment and we can split if if needed. Thanks
I have wired a USB Female jack via 2x 22Ohm resistors to pins A0 and A1 of a QT Py RP2040 (GPIO29 and GPIO28) respectively. (See Image).
When trying the capture_hid_report example, I get errors when an optical mouse is plugged in. (See attached USB Descriptor from USBView)
opticalmouseDescr.txt
...
I expected to see HID reports printed to the USB console.
...
When run as-is, with only the config.pin_dp set to 28 instead of the default of 0, I got no terminal at all. When placed back in bootloader mode, Putty would fail with "unable to configure USB".
When I commented out the config.alarm_pool line (Line 18 of capture_hid_report) which I thought would put the interrupts in the main core, I got
When I moved all of the processing to core0 by calling core1_main() directly from main() and moving pio_usb_host_task() to the main loop, I got:
I realize that this may be my fault, but I am at a loss as to what to try next... :-/
Any ideas?
The text was updated successfully, but these errors were encountered: