Author Topic: USB Sniffer using RP2040  (Read 7594 times)

0 Members and 1 Guest are viewing this topic.

Offline pmr

  • Contributor
  • Posts: 14
Re: USB Sniffer using RP2040
« Reply #25 on: June 01, 2023, 08:08:18 pm »
Quote
No, not at all. it is likely to be confused by that. There is not enough processing power to decide on the fly and switch the speed.

Ah, of course. It is already surprising that the uC is fast enough to bit bang a FS connection. Even without this feature the sniffer is exciting and imminently useful!

Still (clutching at straws here), according to the spec there is a 4 bit time pause after the PRE and the line polarity does not need to be switched, just the clock speed needs to change. Maybe the 4 bit times is just enough. On the other hand, you have probably already thought about this a lot more than I; I guess the hard part is in the case that the PID is not PRE and another byte immediately follows the PID -- checking and deciding on the PID might already take too much processing time in this case.
 

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11228
  • Country: us
    • Personal site
Re: USB Sniffer using RP2040
« Reply #26 on: June 01, 2023, 08:36:24 pm »
The capture is performed autonomously by the PIO, it does not know anything about the captured data, it can't tell the type of the packet or if the packet is even valid. It just receives the stream of bits, it does not even remove bit-stuffing.  It just captures bits as long as memory allows. All the processing for display is done later on the CPU, after capture is done.

I'm preparing a release of a much more capable sniffer with HS/FS/LS support using FPGA and a real USB PHY, but even that would not do PRE handling, at least initially. But it won't be confused by the mix of packets.

What is the actual use case for this?
Alex
 

Offline pmr

  • Contributor
  • Posts: 14
Re: USB Sniffer using RP2040
« Reply #27 on: June 01, 2023, 08:56:41 pm »
I am working on an FPGA based USB1.1 host (PHY / SIE in gateware and protocol using a tiny riscv softcore) on a ULX3S board. The host will handle 1 level of hub which has a keyboard and mouse attached. I was thinking about sniffing the host-hub traffic. I can debug the host-hub traffic first with a FS device in the hub and later the LS hub-device traffic as needed. The sniffer as-is will allow for that. Sniffing the host-hub traffic with an LS device attached would be even nicer -- but don't get me wrong: I am already super happy and impressed with the way it is now.

I'm trying to understand the code in capture.c (unfortunately I am new to RP2040). As far as I understand now, the PIO supports small programs per pin for fast responsiveness. the PIO0 program seems to do NRZI decoding and the PIO1 program seems to detect EOP's. The buffer seems to get filled with raw capture data in lines 581-609. Is that understanding correct?

Not sure I currently understand the format of the data capture buffer, either in raw format or processed format. Is that documented somewhere?
 

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11228
  • Country: us
    • Personal site
Re: USB Sniffer using RP2040
« Reply #28 on: June 01, 2023, 10:00:22 pm »
Sniffing the host-hub traffic with an LS device attached would be even nicer


Yeah, that would be the use case. I assumed not a lot of people would be doing host/hub implementations, especially capable of multiple speeds.

As far as I understand now, the PIO supports small programs per pin for fast responsiveness.
They are not really per pin, a subset of pins available to each PIO, but the ways they can use them are pretty limited.

the PIO0 program seems to do NRZI decoding
PIO0 does most of the work. It does not actually remove NRZI, but it handles re-synchronization to bit edges. This is likely unnecessary in practice, but I already had the code, so I left it there.

and the PIO1 program seems to detect EOP's.
PIO1 was a later addition. This is an attempt to synchronize capture to the stream. Otherwise if you start the capture in the middle of the packet, the whole thing will get messed up. PIO0 can only track its  state if it started from the idle line state.

PIO1 only runs once at the begging looking for any EOP. The line is assumed to be in the idle state after that, so it signals PIO00 to start running.

The buffer seems to get filled with raw capture data in lines 581-609. Is that understanding correct?
Yes, this is the main loop that pulls the data from the PIO.

Not sure I currently understand the format of the data capture buffer, either in raw format or processed format. Is that documented somewhere?
It is just raw bits. separated by the size word. PIO only captures 31 bits at a time, so that bit 32 remains 0 for normal data. And the size (in bits) is calculated by subtracting 1 from 0xffffffff for each bit. At the end of the packet that value is also pushed in the stream. But this value will always have bit 32 set to 1.

Now you can scan the buffer and find the first word with the MSB set, and you know the exact number of bits in the preceding data stream.

The parsing happens in the display.c.
Alex
 

Offline pmr

  • Contributor
  • Posts: 14
Re: USB Sniffer using RP2040
« Reply #29 on: June 01, 2023, 10:14:32 pm »
Quote
I assumed not a lot of people would be doing host/hub implementations, especially capable of multiple speeds.
That is probably a fair assessment. There does not seem to be a lot of host-hub stuff out there in the hobby scene.

Maybe at some point I'll experiment with detecting PRE in the buffer fill loop and switching the clock there. The main issue that I see now is that it runs on the other side of the FIFO, making timing difficult.
 

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11228
  • Country: us
    • Personal site
Re: USB Sniffer using RP2040
« Reply #30 on: June 01, 2023, 10:24:59 pm »
Maybe at some point I'll experiment with detecting PRE in the buffer fill loop and switching the clock there. The main issue that I see now is that it runs on the other side of the FIFO, making timing difficult.
Switching speed here is a complete reprogramming of the PIO program, since FS and LS are handled by the different  implementations, since PIO instruction set is very limited.

And yes, the timing would be hard to manage because you would have to interpret each packet on the fly to figure out which of them are PRE.  This may be easy enough, since PRE would fit entirely in a single word, so you can find it using a simple compare without decoding anything. And I think it would also be unique because there will be a tail of a lot of 0s, which is impossible in a normal data stream (except may be at the very end, but that is solvable by looking at the length word).

So, detecting the PRE may not be as hard. But switching PIO programs in time may be a bit tricky, but may be doable.

For the bigger sniffer, I'll keep it in mind.
« Last Edit: June 01, 2023, 10:26:30 pm by ataradov »
Alex
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14305
  • Country: fr
Re: USB Sniffer using RP2040
« Reply #31 on: June 01, 2023, 11:31:26 pm »
I'm looking forward to the next version of the RP2040, if there is ever one. With a more advanced PIO, maybe a bit more RAM, and why not Cortex-M4-based.
Wondering what the RPi has in store. ;D
 

Offline pmr

  • Contributor
  • Posts: 14
Re: USB Sniffer using RP2040
« Reply #32 on: June 02, 2023, 06:36:16 am »
Quote
since FS and LS are handled by the different  implementations
The LS signalling after a PRE uses FS polarity for J and K, so I guess the same PIO code should work?

Thinking about something like this in the buffer fill loop, in rough pseudo code:
Code: [Select]
if (v==EOP) {
  EOP_flag = true;
  <set clock divider to normal value>
  <insert EOP marker in buffer>
} else
if (v==PRE pattern && EOP_flag) {
  <set clock divider to LS speed>
  <insert PRE marker in buffer>
  EOP_flag = false
} else {
  <handle regular bits>
  EOP_flag = false
}
The remaining problem is that the loop only sees the PRE pattern after 31 bit times. The PRE pattern lasts only 16 bits, followed by a pause of 4 bits, 20 bits in total. That means the PIO code has already seen 11 FS bit times of the LS sync pattern by the time the loop detects it and switches the clock. This would mean that the switch happens in the first J of the low-speed KJKJKJKK sync pattern -- assuming that the host indeed produces a pause of 1...9 FS bit times. With the spec pause being 4 bit times, that should allow for a bit of jitter between the PIO loop and the buffer fill loop.
« Last Edit: June 02, 2023, 10:17:43 am by pmr »
 

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11228
  • Country: us
    • Personal site
Re: USB Sniffer using RP2040
« Reply #33 on: June 02, 2023, 03:05:38 pm »
Quote
since FS and LS are handled by the different  implementations
The LS signalling after a PRE uses FS polarity for J and K, so I guess the same PIO code should work?
In that case yes. The bit-rate difference is handled by the clock prescaler. It should be fast to change, but obviously would need some experimentation.

The remaining problem is that the loop only sees the PRE pattern after 31 bit times.

This is not the case. The PIO pushes out incomplete word as soon as EOP is detected. So all your main loop logic has to do is scan all the words, set a flag if a word has MSB set. This would indicate end of a previous packet. if you get a word that is PRE (compare full 32 bits, only 16 bits would be meaningful, the rest are guaranteed to be 0), then you have a PRE packet. You can double check the next word to see if it is a length of 16 to be absolutely sure. But I don't think this situation is possible normally.

Or you can just scan for PRE payload and wait for the next word to be a length of 16, no need to look for the end of the previous packet.
Alex
 

Offline pmr

  • Contributor
  • Posts: 14
Re: USB Sniffer using RP2040
« Reply #34 on: June 02, 2023, 03:46:08 pm »
Thanks for the feedback. The special thing about the PRE header is that it is not terminated by an EOP, only the LS package that follows has the EOP. This is described in section 8.6.5 of the spec. Hence the PRE packet will not be pushed to the FIFO individually. This is for another day, though.

-------

The RPI Pico arrived in the mail this afternoon and I'm happily using it to debug my stuff  :box:

I'm seeing intermittent errors on my SOF packets, so it has already found a first bug:
Code: [Select]
   ... : Folded 115 frames
1458583 : ERROR [NBIT]: SYNC = 0x80, PID = 0xa5, DATA: 0a 7c
   ... : Folded 24 frames
1483626 : ERROR [NBIT]: SYNC = 0x80, PID = 0xa5, DATA: 23 7c
   ... : Folded 52 frames
1536719 : ERROR [NBIT]: SYNC = 0x80, PID = 0xa5, DATA: 58 7c
Not sure I understand the error report. What is error "NBIT"? Does that mean the packet is not the required 24 bits? If so, what is error "SIZE"? I'm not asking for help on debugging this issue, just for a clarification of what the error message indicates.

 

Online ataradovTopic starter

  • Super Contributor
  • ***
  • Posts: 11228
  • Country: us
    • Personal site
Re: USB Sniffer using RP2040
« Reply #35 on: June 02, 2023, 03:51:35 pm »
If it is not terminated, then I'm not sure it is possible to receive it correctly. As the whole LS frame would be sampled in FS mode. This is likely to confuse the sate machine. And I'm not sure trying to intercept the 31-bit word and switch things mid-frame would work either. It might, but I would not expect it to be reliable.

NBIT means that the number of bits received after bit stuffing removal was not a multiple of 8.

SIZE means the number of bytes is not enough (or too many) for a given token type.

But given that it folds a lot of frames, the error seems to be intermittent, which is strange. It is possible that bit-stuffing is messed up, and sometimes does not work correctly for some values.
« Last Edit: June 02, 2023, 04:09:15 pm by ataradov »
Alex
 

Offline pmr

  • Contributor
  • Posts: 14
Re: USB Sniffer using RP2040
« Reply #36 on: June 02, 2023, 09:28:36 pm »
Quote
It is possible that bit-stuffing is messed up, and sometimes does not work correctly for some values.
Indeed: it made a mistake when a packet ended with 5 ones and a 0, mistakingly inserting an extra 0.

Many thanks for for having made this tool, it is really nice.
 

Offline tszaboo

  • Super Contributor
  • ***
  • Posts: 7307
  • Country: nl
  • Current job: ATEX product design
Re: USB Sniffer using RP2040
« Reply #37 on: June 02, 2023, 11:38:03 pm »
I'm looking forward to the next version of the RP2040, if there is ever one. With a more advanced PIO, maybe a bit more RAM, and why not Cortex-M4-based.
Wondering what the RPi has in store. ;D
Yeah, I wonder if there is any info on that. They definitely planned more than one micro, hence the naming.
I also hupe the signal integrity guy realizes, that you don't need to have every second pin as ground or power for the thing to work.
 

Offline PeterZ

  • Regular Contributor
  • *
  • Posts: 54
  • Country: de
Re: USB Sniffer using RP2040
« Reply #38 on: June 19, 2023, 12:55:29 pm »
Thanks for such nice and useful project.
I have altered the pcb design a bit to fit into one of those cheap "usb dongle" transparent boxes from aliexpress.
Built, programmed, plugged in, reports on ttyACM0 as "USB Sniffer Lite. Built on Apr 11 2023 20:41:25" - all works fine!
 

Offline pmr

  • Contributor
  • Posts: 14
Re: USB Sniffer using RP2040
« Reply #39 on: June 20, 2023, 09:30:18 pm »
Well, I got my simple FPGA usb1.1 host working. About 1,000 lines of verilog and 1,000 lines of C code. Supports hubs, keyboards and mice. About 4,000 LUTs including the RV32I softcore that runs the control code. Repo here: https://gitlab.com/pnru/usb_host

Many thanks for the RP2040 USB Sniffer that greatly helped tracking down some issues!  :) :) :)
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf