diff --git a/docs/Makefile b/docs/Makefile index 69fe55ec..f3f9d372 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -13,7 +13,13 @@ help: .PHONY: help Makefile +# api docs +apidocs: + rm -rf source/api_docs/ + sphinx-apidoc -o source/api_docs/ ../facedancer + # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + diff --git a/docs/source/conf.py b/docs/source/conf.py index 18ea6af8..d3ee6f7b 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,3 +1,5 @@ +import time + import sphinx_rtd_theme extensions = [ @@ -7,7 +9,7 @@ # -- Project information ----------------------------------------------------- project = 'Facedancer' -copyright = '2023, Great Scott Gadgets' +copyright = time.strftime('2018-%Y, Great Scott Gadgets') author = 'Great Scott Gadget' version = '' @@ -16,22 +18,35 @@ # -- General configuration --------------------------------------------------- +templates_path = ['_templates'] +exclude_patterns = ['_build'] +source_suffix = '.rst' +master_doc = 'index' +language = "en" +exclude_patterns = [] +pygments_style = None + extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.extlinks', + 'sphinx.ext.napoleon', + 'sphinx.ext.viewcode', ] + +# configure extension: extlinks extlinks = { 'repo': ('https://github.com/greatscottgadgets/facedancer/blob/main/%s', '%s'), 'example': ('https://github.com/greatscottgadgets/facedancer/blob/main/examples/%s', '%s'), } -templates_path = ['_templates'] -exclude_patterns = ['_build'] -source_suffix = '.rst' -master_doc = 'index' -language = "en" -exclude_patterns = [] -pygments_style = None +# configure extension: napoleon +napoleon_google_docstring = True +napoleon_numpy_docstring = False +napoleon_include_init_with_doc = True +napoleon_use_ivar = True +napoleon_include_private_with_doc = False +napoleon_include_special_with_doc = True +napoleon_use_param = False # -- Options for HTML output ------------------------------------------------- diff --git a/examples/minimal.py b/examples/minimal.py new file mode 100644 index 00000000..05ae3ec9 --- /dev/null +++ b/examples/minimal.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +# pylint: disable=unused-wildcard-import, wildcard-import +# +# This file is part of FaceDancer. +# + +import logging + +from facedancer import * +from facedancer import main + +# TODO some way to declare device speed + +@use_inner_classes_automatically +class MyDevice(USBDevice): + product_string : str = "Example USB Device" + manufacturer_string : str = "Facedancer" + vendor_id : int = 0x1209 + product_id : int = 0x0001 + + class MyConfiguration(USBConfiguration): + + class MyInterface(USBInterface): + + class MyInEndpoint(USBEndpoint): + number : int = 1 + direction : USBDirection = USBDirection.IN + + def handle_data_requested(self: USBEndpoint): + self.send(b"device sent response on bulk endpoint", blocking=True) + + class MyOutEndpoint(USBEndpoint): + number : int = 1 + direction : USBDirection = USBDirection.OUT + + def handle_data_received(self: USBEndpoint, data): + logging.info(f"device received '{data}' on bulk endpoint") + + @vendor_request_handler(number=1, direction=USBDirection.IN) + @to_device + def my_vendor_request_handler(self: USBDevice, request: USBControlRequest): + request.reply(b"device sent response on control endpoint") + + @vendor_request_handler(number=2, direction=USBDirection.OUT) + @to_device + def my_other_vendor_request_handler(self: USBDevice, request: USBControlRequest): + logging.info(f"device received '{request.index}' '{request.value}' '{request.data}' on control endpoint") + request.ack() + + +main(MyDevice) diff --git a/examples/usbproxy.py b/examples/usbproxy.py new file mode 100644 index 00000000..ecf4214e --- /dev/null +++ b/examples/usbproxy.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +# +# This file is part of FaceDancer. +# +""" USB Proxy example; forwards all USB transactions and logs them to the console. """ + +from facedancer import * +from facedancer import main + +from facedancer.proxy import USBProxyDevice +from facedancer.filters import USBProxySetupFilters, USBProxyPrettyPrintFilter + +# replace with the proxied device's information +ID_VENDOR=0x09e8 +ID_PRODUCT=0x0031 + + +if __name__ == "__main__": + # create a USB Proxy Device + proxy = USBProxyDevice(idVendor=ID_VENDOR, idProduct=ID_PRODUCT) + + # add a filter to forward control transfers between the target host and + # proxied device + proxy.add_filter(USBProxySetupFilters(proxy, verbose=0)) + + # add a filter to log USB transactions to the console + proxy.add_filter(USBProxyPrettyPrintFilter(verbose=5)) + + main(proxy)