Skip to content

Latest commit

 

History

History
76 lines (47 loc) · 2.87 KB

howto_facedancer_backend.rst

File metadata and controls

76 lines (47 loc) · 2.87 KB

How to write a new Facedancer Backend

Facedancer board backends can be found in the :repo:`facedancer/backends/<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:

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:

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.