Skip to content
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

Failing to proxy device with large configuration descriptor #162

Open
xairy opened this issue Aug 5, 2024 · 1 comment
Open

Failing to proxy device with large configuration descriptor #162

xairy opened this issue Aug 5, 2024 · 1 comment
Assignees
Labels
enhancement potential new feature

Comments

@xairy
Copy link

xairy commented Aug 5, 2024

With this fix applied, proxying a Logitech Webcam C110, which has a large configuration descriptor, fails with:

...
INFO    | logging        | [16:21:55] USBControlRequest(direction=1, type=0, recipient=0, number=6, value=512, index=0, length=1132, data=bytearray(b''), device=USBProxyDevice(name='generic device', device_class=0, device_subclass=0, protocol_revision_number=0, max_packet_size_ep0=64, vendor_id=24843, product_id=18003, manufacturer_string='Facedancer', product_string='Generic USB Device', serial_number_string='S/N 3420E', supported_languages=(<LanguageIDs.ENGLISH_US: 1033>,), device_revision=0, usb_spec_version=2, device_speed=None, descriptors={<DescriptorTypes.DEVICE: 1>: <function USBBaseDevice.__post_init__.<locals>.<lambda> at 0x7f07bd3e7ee0>, <DescriptorTypes.CONFIGURATION: 2>: <bound method USBBaseDevice.get_configuration_descriptor of ...>, <DescriptorTypes.STRING: 3>: <bound method USBBaseDevice.get_string_descriptor of ...>}, configurations={}, backend=<facedancer.backends.moondancer.MoondancerApp object at 0x7f07bc6347f0>))
INFO    | logging        | [16:21:55] <: b'\t\x02l\x04\x04\x01\x00\x80\xfa\x08\x0b\x00\x02\x0e\x03\x00\x04\t\x04\x00\x00\x01\x0e\x01\x00\x04\r$\x01\x00\x01O\x00\x80\xc3\xc9\x01\x01\x01\x1c$\x06\x06\xb0\xd0\xbbh\xa4a\x83K\x90\xb7\xa6!_<Op\x18\x01\x02\x03\xff\xff\xff\x00\x12$\x02\x01\x01\x02\x00\x00\x00\x00\x00\x00\x00\x00\x03\x0e\n\x00\x0b$\x05\x02\x01\x00\x00\x02\x7f\x15\x00\t$\x03\x03\x01\x01\x00\x02\x00\x07\x05\x81\x03\x10\x00\x07\x05%\x03\x10\x00\t\x04\x01\x00\x00\x0e\x02\x00\x04\x0f$\x01\x02\xe9\x02\x82\x00\x03\x01\x01\x00\x01\x00\x00\x1b$\x04\x01\tYUY2\x00\x00\x10\x00\x80\x00\x00\xaa\x008\x9bq\x10\x01\x00\x00\x00\x00"$\x05\x01\x01\x80\x02\xe0\x01\x00\x00e\x04\x00\x00\xca\x08\x00`\t\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00"$\x05\x02\x01`\x01 \x01\x00@s\x01\x00\x80\xe6\x02\x00\x18\x03\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00"$\x05\x03\x01@\x01\xf0\x00\x00@\x19\x01\x00\x802\x02\x00X\x02\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00"$\x05\x04\x01\xb0\x00\x90\x00\x00\xd0\\\x00\x00\xa0\xb9\x00\x00\xc6\x00\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00"$\x05\x05\x01\xa0\x00x\x00\x00PF\x00\x00\xa0\x8c\x00\x00\x96\x00\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00"$\x05\x06\x01 \x02 \x01\x00\xc0=\x02\x00\x80{\x04\x00\xc8\x04\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00"$\x05\x07\x01\xb0\x01\xf0\x00\x00\xb0{\x01\x00`\xf7\x02\x00*\x03\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00"$\x05\x08\x01@\x01\xb0\x00\x00@\xce\x00\x00\x80\x9c\x01\x00\xb8\x01\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00"$\x05\t\x01\x80\x02h\x01\x00\xc0K\x03\x00\x80\x97\x06\x00\x08\x07\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00\x06$\r\x01\x01\x04\x0b$\x06\x02\x0b\x01\x01\x00\x00\x00\x00"$\x07\x01\x01\x80\x02\xe0\x01\x00\x80\x97\x06\x00\x00/\r\x00\x10\x0e\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00"$\x07\x02\x01`\x01 \x01\x00\xe0,\x02\x00\xc0Y\x04\x00\xa4\x04\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00"$\x07\x03\x01@\x01\xf0\x00\x00\xe0\xa5\x01\x00\xc0K\x03\x00\x84\x03\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00"$\x07\x04\x01\xb0\x00\x90\x00\x008\x8b\x00\x00p\x16\x01\x00)\x01\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00"$\x07\x05\x01\xa0\x00x\x00\x00xi\x00\x00\xf0\xd2\x00\x00\xe1\x00\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00"$\x07\x06\x01 \x02 \x01\x00\xa0\\\x03\x00@\xb9\x06\x00,\x07\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00"$\x07\x07\x01\xb0\x01\xf0\x00\x00\x889\x02\x00\x10s\x04\x00\xbf\x04\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00"$\x07\x08\x01@\x01\xb0\x00\x00`5\x01\x00\xc0j\x02\x00\x94\x02\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00"$\x07\t\x01\x80\x02h\x01\x00\xa0\xf1\x04\x00@\xe3\t\x00\x8c\n\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00"$\x07\n\x01 \x03\xe0\x01\x00`=\x08\x00\xc0z\x10\x00\x94\x11\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00"$\x07\x0b\x01\x00\x04\x00\x03\x00\x00\xe0\x10\x00\x00\xc0!\x00\x00$\x00\x15\x16\x05\x00\x02\x15\x16\x05\x00*,\n\x00\x06$\r\x01\x01\x04\t\x04\x01\x01\x01\x0e\x02\x00\x04\x07\x05\x82\x05\x00\x14\x01\t\x04\x01\x02\x01\x0e\x02\x00\x04\x07\x05\x82\x05\x00\x0c\x01\t\x04\x01\x03\x01\x0e\x02\x00\x04\x07\x05\x82\x05\x00\x04\x01\t\x04\x01\x04\x01\x0e\x02\x00\x04\x07\x05\x82\x05\x00\x02\x01\x08\x0b\x02\x02\x01\x00\x00\x05\t\x04\x02\x00\x00\x01\x01\x00\x05\t$\x01\x00\x01+\x00\x01\x03\x0c$\x02\x01\x01\x02\x00\x01\x00\x00\x00\x00\r$\x06\x05\x01\x06\x03\x00\x00\x00\x00\x00\x00\t$\x03\x03\x01\x01\x00\x05\x00\t\x04\x03\x00\x00\x01\x02\x00\x05\t\x04\x03\x01\x01\x01\x02\x00\x05\x07$\x01\x03\x01\x01\x00 $\x02\x01\x01\x02\x10\x08\x80\xbb\x00D\xac\x00\xc0]\x00"V\x00\x80>\x00\xe0.\x00\x11+\x00@\x1f\x00\t\x05\x83\rd\x00\x04\x00\x00\x07%\x01\x01\x01\x00\x00\t\x04\x03\x02\x01\x01\x02\x00\x05\x07$\x01\x03\x01\x01\x00 $\x02\x01\x01\x01\x08\x08\x80\xbb\x00D\xac\x00\xc0]\x00"V\x00\x80>\x00\xe0.\x00\x11+\x00@\x1f\x00\t\x05\x83\r2\x00\x04\x00\x00\x07%\x01\x01\x01\x00\x00'
INFO    | moondancer     | Disconnecting from target host.
Traceback (most recent call last):
  File "./examples/usbproxy.py", line 30, in <module>
    main(proxy)
  File "/home/user/.local/lib/python3.8/site-packages/facedancer/devices/__init__.py", line 41, in default_main
    device.emulate(*coroutines)
  File "/home/user/.local/lib/python3.8/site-packages/facedancer/device.py", line 232, in emulate
    self.run_with(*coroutines)
  File "/home/user/.local/lib/python3.8/site-packages/facedancer/device.py", line 217, in run_with
    asyncio.run(inner())
  File "/usr/lib/python3.8/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()
  File "/home/user/.local/lib/python3.8/site-packages/facedancer/device.py", line 215, in inner
    await asyncio.gather(self.run(), *coroutines)
  File "/home/user/.local/lib/python3.8/site-packages/facedancer/device.py", line 204, in run
    self.backend.service_irqs()
  File "/home/user/.local/lib/python3.8/site-packages/facedancer/backends/moondancer.py", line 414, in service_irqs
    self.handle_receive_control(event.endpoint_number)
  File "/home/user/.local/lib/python3.8/site-packages/facedancer/backends/moondancer.py", line 480, in handle_receive_control
    self.connected_device.handle_request(request)
  File "/home/user/.local/lib/python3.8/site-packages/facedancer/proxy.py", line 131, in handle_request
    self._proxy_in_control_request(request)
  File "/home/user/.local/lib/python3.8/site-packages/facedancer/proxy.py", line 246, in _proxy_in_control_request
    self.send(0, data)
  File "/home/user/.local/lib/python3.8/site-packages/facedancer/device.py", line 272, in send
    self.backend.send_on_endpoint(0, data, blocking=blocking)
  File "/home/user/.local/lib/python3.8/site-packages/facedancer/backends/moondancer.py", line 329, in send_on_endpoint
    self.api.write_endpoint(endpoint_number, blocking, bytes(data))
  File "/home/user/.local/lib/python3.8/site-packages/pygreat/comms.py", line 1126, in method
    return self.execute_command(verb_number, in_format, out_format, name=name, class_name=class_name,
  File "/home/user/.local/lib/python3.8/site-packages/pygreat/comms.py", line 1281, in execute_command
    return self.comms_backend.execute_command(self.CLASS_NUMBER, verb, in_format,
  File "/home/user/.local/lib/python3.8/site-packages/pygreat/comms.py", line 788, in execute_command
    raw_result = self.execute_raw_command(class_number, verb, payload, timeout,
  File "/home/user/.local/lib/python3.8/site-packages/pygreat/comms_backends/usb1.py", line 381, in execute_raw_command
    raise ValueError("Command payload is too long!")
ValueError: Command payload is too long!

This appears to be caused by LIBGREAT_MAX_COMMAND_SIZE in pygreat being only 1024.

I tried increasing LIBGREAT_MAX_COMMAND_SIZE to 4096, but this soft-bricked my Cynthion. I had to reload the facedancer firmware into it to make it work again.

@antoinevg antoinevg self-assigned this Aug 7, 2024
@antoinevg
Copy link
Member

antoinevg commented Aug 29, 2024

Generally there are no transfer size limits in Facedancer as it packetizes all transfers except for CONTROL IN transfers as this would require some fairly complex state synchronization between the Facedancer host code and the Facedancer device firmware.

On Cynthion, the firmware sets LIBGREAT_MAX_COMMAND_SIZE to 1024 bytes as we only have 64 kB of RAM available to us on the Facedancer SoC. (!)

GreatFET does a little better and can handle up to 4096 bytes but it also suffers from the same inherent problem.

That said, it occurs to me that this limit was imposed before we moved the Facedancer firmware to the qspi flash which has freed up about 50% of the available RAM.

So you could try to also bump LIBGREAT_MAX_COMMAND_SIZE a little higher in firmware/libgreat/src/gcp.rs.

We're also working on making the Cynthion HyperRAM available to the SoC which will allow us to greatly increase the transfer size.

Though ideally this is a limitation that needs to be removed from Facedancer itself.

The tracking issue for this is here: greatscottgadgets/facedancer#114

@antoinevg antoinevg added the enhancement potential new feature label Oct 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement potential new feature
Projects
None yet
Development

No branches or pull requests

2 participants