greatscottgadgets / facedancer

Implement your own USB device in Python, supported by a hardware peripheral such as Cynthion or GreatFET
BSD 3-Clause "New" or "Revised" License
785 stars 118 forks source link

Control transfer limited to 512 bytes with GreatFET #113

Open mossmann opened 3 months ago

mossmann commented 3 months ago

It looks like this is only a problem with the pyusb backend for pygreat. The problem should go away if we migrate GreatFET to the usb1 backend. To reproduce:

#!/usr/bin/env python3

from facedancer import main
from facedancer import *

class TestDevice(USBDevice):

    def __init__(self):
        super().__init__(
            vendor_id=0x1209,
            product_id=0x0001,
            product_string="Test Device"
        )

        configuration = USBConfiguration()
        self.add_configuration(configuration)

        interface = USBInterface()
        configuration.add_interface(interface)

    @vendor_request_handler(number=1)
    def handle_my_request(self, request):
        request.reply(b'A' * 520)

main(TestDevice())
import usb
d=usb.core.find(idVendor=0x1209, idProduct=0x0001)
d.ctrl_transfer(request_type, 1, 0, 0, data_or_wLength=1000

result:

  File "/tmp/size-limit-test.py", line 24, in handle_my_request
    request.reply(b'A' * 520)
  File "/home/mossmann/src/facedancer/facedancer/request.py", line 254, in reply
    self.device.send(endpoint_number=0, data=data)
  File "/home/mossmann/src/facedancer/facedancer/device.py", line 268, in send
    self.backend.send_on_endpoint(0, data, blocking=blocking)
  File "/home/mossmann/src/facedancer/facedancer/backends/greatdancer.py", line 251, in send_on_endpoint
    self.api.send_on_endpoint(ep_num, bytes(data))
  File "/tmp/f/lib/python3.11/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 "/tmp/f/lib/python3.11/site-packages/pygreat/comms.py", line 1281, in execute_command
    return self.comms_backend.execute_command(self.CLASS_NUMBER, verb, in_format,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/tmp/f/lib/python3.11/site-packages/pygreat/comms.py", line 788, in execute_command
    raw_result = self.execute_raw_command(class_number, verb, payload, timeout,
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/tmp/f/lib/python3.11/site-packages/pygreat/comms_backends/usb.py", line 394, in execute_raw_command
    future_utils.raise_from(self._exception_for_command_failure(error_number, pretty_name), None)
  File "/home/mossmann/.local/lib/python3.11/site-packages/future/utils/__init__.py", line 406, in raise_from
    exec(execstr, myglobals, mylocals)
  File "<string>", line 1, in <module>
pygreat.comms.CommandFailureError: greatdancer.send_on_endpoint: gpio: host requested to send 520, but our maximum packet size is 512! [ENOSPC]