Facedancer board backends can be found in the :repo:`facedancer/backends/<facedancer/backends/>` directory.
To create a new backend, follow these steps:
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"
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:
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.