===================================== How to write a new Facedancer Backend ===================================== Facedancer board backends can be found in the :repo:`facedancer/backends/` directory. To create a new backend, follow these steps: 1. Derive a new backend class ----------------------------- All Facedancer board backends inherit from the ``FacedancerApp`` and ``FacedancerBackend`` classes. Begin by deriving your new backend class from these base classes, as shown below: .. code-block :: python from facedancer.core import FacedancerApp from facedancer.backends.base import FacedancerBackend class MydancerBackend(FacedancerApp, FacedancerBackend): app_name = "Mydancer" 2. Implement backend callback methods ------------------------------------- Your new backend must implement the required callback methods defined in the ``FacedancerBackend`` class. These methods contain the functionality specific to your Facedancer board: .. literalinclude:: ../../facedancer/backends/base.py :language: python :emphasize-lines: 0 :linenos: 3. Implement the backend event loop ----------------------------------- Facedancer uses a polling approach to service events originating from the Facedancer board. The actual events that need to be serviced will be specific to your Facedancer board but will generally include at least the following: * Receiving a setup packet. * Receiving data on an endpoint. * Receiving NAK events (e.g. host requested data from an IN endpoint) Facedancer will take care of scheduling execution of the ``service_irqs()`` callback but it is up to you to dispatch any events generated by your board to the corresponding methods of the Facedancer ``USBDevice`` object obtained in the ``FacedancerBackend.connect()`` callback. That said, most backend implementations will follow a pattern similiar to the pseudo-code below: .. code-block :: python class MydancerBackend(FacedancerApp, FacedancerBackend): ... def service_irqs(self): """ Core routine of the Facedancer execution/event loop. Continuously monitors the Moondancer's execution status, and reacts as events occur. """ # obtain latest events and handle them for event in self.mydancer.get_events(): match event: case USB_RECEIVE_SETUP: self.usb_device.create_request(event.data) case USB_RECEIVE_PACKET: self.usb_device.handle_data_available(event.endpoint_number, event.data) case USB_EP_IN_NAK: self.usb_device.handle_nak(event.endpoint_number) Additionally, referencing the ``service_irqs`` methods of the other backend implementations can provide valuable insights into handling events specific to your implementation.