Trigger do not work on custom database descriptor packets
Hi
I have following issue with phywhisperer, I am not able to trigger on dev.ctrl_transfer(bmRequestType=0x80, bRequest=0x06, wValue=0x0001, wIndex=0x0000, data_or_wLength=0x1F, timeout=5)
My trigger is set to phy.set_pattern(pattern=[0x80, 0x06, 0x00, 0x01, 0x00, 0x00, 0x1F])
I can trigger on any original packets received on USB bus by phywisperer but not on packets I want to inject using pyusb
When I inject packet I can see it with logic analyser Saleae, but cannot trigger on it using phywisperer
My physical setup: HOST/CONTROL PC connected to OS X, TARGET to USB key
try:
phy = pw.Usb()
phy.con(program_fpga=True)
print(phy.get_fpga_buildtime())
phy.load_bitstream("phywhisperer_top.bit")
phy.set_usb_mode('auto')
phy.set_pattern(pattern=[0x80, 0x06, 0x00, 0x01, 0x00, 0x00, 0x1F])
phy.set_capture_size(8000)
while True:
phy.set_power_source("host")
# time.sleep(0.5)
dev = usb.core.find(idVendor=2414, idProduct=2132)
dev.set_configuration()
if dev is None:
raise ValueError('Our device is not connected')
# print("USB Dev:", dev)
phy.set_trigger(num_triggers=1, delays=[453], widths=[80], enable=True)
phy.arm()
dev.ctrl_transfer(bmRequestType=0x80, bRequest=0x06, wValue=0x0001, wIndex=0x0000, data_or_wLength=0x1F, timeout=15)
time.sleep(0.5)
phy.set_power_source("off")
time.sleep(0.1)
# arm:
phy.set_power_source("host")
time.sleep(0.1)
# phy.wait_disarmed()
print("done")
phy.addpattern = True
.....
What does phy.get_usb_mode() return? (if it's "auto" then the target speed hasn't been detected properly, which means that the phy won't be programmed correctly).
It's also possible that things get out of whack because you're possibly re-arming PW in the while loop without having captured anything. If you must have a while loop around the PW arming, you should call reset_fpga() before re-arming (you'll also need to re-program all PW parameters).
Finally I would try relaxing the match pattern to see what PW is seeing.
Hi thanks for answer
phy.get_usb_mode() return auto and then FS if I check in loop. When I set it to FS manually it triggers but only for short pattern like [0x00, 0x1F] entire packet trigger is not working.
Can you try the following:
phy = pw.Usb()
phy.con(program_fpga=True)
print(phy.get_fpga_buildtime())
phy.reset_fpga()
phy.set_usb_mode('FS')
#phy.set_pattern(pattern=[0x80, 0x06, 0x00, 0x01, 0x00, 0x00, 0x1F])
phy.set_pattern(pattern=[0x80, 0x06])
phy.set_capture_size(8000)
phy.set_power_source("host")
# time.sleep(0.5)
dev = usb.core.find(idVendor=2414, idProduct=2132)
dev.set_configuration()
if dev is None:
raise ValueError('Our device is not connected')
phy.arm()
# make sure we haven't seen a match yet:
assert phy.armed() == True
dev.ctrl_transfer(bmRequestType=0x80, bRequest=0x06, wValue=0x0001, wIndex=0x0000, data_or_wLength=0x1F, timeout=15)
phy.wait_disarmed()
print("done")
phy.addpattern = True
raw = phy.read_capture_data()
...
Assuming this runs through, look for your pattern in raw.
you didn't; set trigger ? - so it not work, but this one works.. up to [0x00,0x00,0xFF,0xFF]
try:
phy = pw.Usb()
phy.con()
phy.set_usb_mode('FS')
phy.set_pattern(pattern=[0xFF, 0xFF])
phy.set_capture_size(8000)
while True:
phy.set_power_source("host")
time.sleep(0.25)
dev = usb.core.find(idVendor=2414, idProduct=2132)
dev.set_configuration()
if dev is None:
dev = usb.core.find(idVendor=2414, idProduct=2132)
dev.set_configuration()
# print("USB Dev:", dev)
# print(ret)
phy.set_trigger(num_triggers=2, delays=[0,453], widths=[80, 80], enable=True)
phy.arm()
assert phy.armed() == True
resp = dev.ctrl_transfer(bmRequestType=0x80, bRequest=0x06, wValue=0x0001, wIndex=0x0000, data_or_wLength=0xFFFF, timeout=15)
print(list(resp))
phy.set_power_source("off")
# time.sleep(0.1)
# arm:
phy.set_power_source("host")
# time.sleep(0.1)
phy.wait_disarmed()
print("done")
phy.addpattern = True
raw = phy.read_capture_data()
# if(phy.armed() == False):
Just an update, I haven't been able to set up a target with pyusb yet to investigate this further; I will try to do that sometime next week.
However I did check that I have no trouble with matching on a similar pattern -- in my case, [0x80, 0x06, 0x01, 0x03, 0x09, 0x04, 0xFF].
So I still suspect that the issue doesn't lie with the PW pattern matching logic. FYI, we verified random patterns and masks up to 64 bytes long in simulation.
That was my mistake pattern should be [0x80, 0x06, 0x01, 0x00, 0x00, 0x00, 0x1F] instead [0x80, 0x06, 0x00, 0x01, 0x00, 0x00, 0x1F]
Ah, so do you mean that it works and the issue can be closed?
Looks like, whatever pyusb sends its reversed in pattern
Is this a documentation issue? I mean it sounds like this is due to byte/bit ordering that USB uses being not an obvious mapping.
Did the PW-USB feedback show you the correct byte order? Just trying to figure out what all to document! I'm thinking at minimum we could make a small helper macro/function that maps from a USB request to the expected pattern over-the-wire (which would be a very very common usage)
This is what I want to test also on other stacks, on OS X it is weird that I can't set using pyusb Device/index as 0x0100/0x00 it simply do not send that correctly. What pyusb is doing is bit shift index | << 8 descriptor_type. The only request I can send as valid is
dev.ctrl_transfer(bmRequestType=0x80, bRequest=0x06, wValue=0x0101, wIndex=0x0000, data_or_wLength=0xFFFF)
Then on phywhisperer I need to catch as pattern
phy.set_pattern(pattern=[0x80,0x06,0x01,0x01,0x00,0x00,0xFF,0xFF])
Other example to show byte swap:
resp = dev.ctrl_transfer(bmRequestType=0x80, bRequest=0x06, wValue=0x1234, wIndex=0x0000, data_or_wLength=0xFFFF)]
phy.set_pattern(pattern=[0x80,0x06,0x34,0x12,0x00,0x00,0xFF,0xFF])

The byte ordering of USB is LSB first IIRC - so when it sends the 16-bit values, they go over the wire as 0x34, x012. This is the "unexpected" part since most people are used to MSB first! Having a helper function would make it more clear how the mapping works.
On the device/index - basically you are limited by the USB stack to sending only "Valid" things. The other trying to try is the wLength value. I've seen that on some stacks you can set it to 0xFFFF, on other stacks it gets limited (0x0400 is maximum I've seen on a few). It seems to be something added at some point in libusb, so you just get USB errors.
It's worth considering making a dedicated "usb host". GreatFET can basically be used as this too (Facedancer is basically designed for this). But I've also just used a raspberry pi that you can compile your specific version of libusb on...
Which version you compiled for Raspberry Pi ? nice hint. I am above on real project testing some USB dongle. I see I can get up to 71 bytes back when glitching and using OS X as. host but.. I also see bunch of errors on Saleae when triggering on crafted packet
You also connect Control PC and Host USB ports to Raspberry PI ? or use Control PC as some Laptop OSX/WIndows/Linux and only Host USB is connected to Raspberry from which you only craft and Send USB packets. On Control PC you use Python API of Phywhisperer to trigger and so on
So I'm not positive on control PC - I always did that from regular laptop. In theory (?) it should work but I never tried, so might be some problem with libusb on r-pi. I was using older verions of everything (older kernel).
I actually ended up just dedicating a computer to serve as my control instead (old laptop), so I didn't spend long on the r-pi idea! But In theory it would be nicer/smaller/easier to use r-pi. The laptop was something older - I was playing with Ubuntu 14 & a Windows 7 with an old (~Python 2.7) install.
If you try to send a wLength of 0xFFFF and it gives an error, but the packet does work with a wLength of something smaller (0x00FF) then you know the host is giving you the problem. The end device will ignore a larger wLength, so if you get an error with a wLength of 0xFFFF that means that you'll never get it working I think.
Sorry I don't have exact versions! But if you try a few VMs or something it should be helpful? I ended up doing bare metal as was concerned that the VM-->Host interface would also be giving me trouble. In the end I did get the 0xFFFF to work however - when I get a chance I'll try it on a few systems around to see if any "just work"
closing since no further updates