diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..f232466 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,28 @@ +name: UmockdevTest + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Install umockdev + run: sudo apt-get update -y && sudo apt-get install -y umockdev + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: '1.20' + + - name: Build command line tool + run: go build -v -o /tmp/usbrelay cmd/usbrelay/main.go + + - name: Run umockdev tests + run: cd test && chmod +x test.sh && ./test.sh \ No newline at end of file diff --git a/README.md b/README.md index c51ef27..002099b 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,16 @@ udev rules: - `sudo udevadm control --reload-rules && sudo udevadm trigger` 4. Make sure to unplug and replug the USB device! +## Testing + +Testing is done via a mocked virtual USB device with [umockdev](https://github.com/martinpitt/umockdev). + +A 4 channel device was used to record the USB communication with [wireshark](https://www.wireshark.org/) and `usbmon` +while executing the command line tool. + +Each command's communication is stored in a separate `pcap` file in the test directory and replayed for the command line +tool with `umockdev-run` using the actual device's stored sysfs device and udev properties. + ## Credits This package is an amalgamation of a few people's previous work: diff --git a/test/01-list-start.pcapng b/test/01-list-start.pcapng new file mode 100644 index 0000000..6dc864b Binary files /dev/null and b/test/01-list-start.pcapng differ diff --git a/test/02-on-all.pcapng b/test/02-on-all.pcapng new file mode 100644 index 0000000..c653da5 Binary files /dev/null and b/test/02-on-all.pcapng differ diff --git a/test/03-off-all.pcapng b/test/03-off-all.pcapng new file mode 100644 index 0000000..ea2d4c2 Binary files /dev/null and b/test/03-off-all.pcapng differ diff --git a/test/04-toggle-all.pcapng b/test/04-toggle-all.pcapng new file mode 100644 index 0000000..6e65831 Binary files /dev/null and b/test/04-toggle-all.pcapng differ diff --git a/test/05-setserial-rel01-rel02.pcapng b/test/05-setserial-rel01-rel02.pcapng new file mode 100644 index 0000000..939c423 Binary files /dev/null and b/test/05-setserial-rel01-rel02.pcapng differ diff --git a/test/06-setserial-rel02-rel01.pcapng b/test/06-setserial-rel02-rel01.pcapng new file mode 100644 index 0000000..c330cd7 Binary files /dev/null and b/test/06-setserial-rel02-rel01.pcapng differ diff --git a/test/07-list-end.pcapng b/test/07-list-end.pcapng new file mode 100644 index 0000000..de221a8 Binary files /dev/null and b/test/07-list-end.pcapng differ diff --git a/test/relay.umockdev b/test/relay.umockdev new file mode 100644 index 0000000..4c996ca --- /dev/null +++ b/test/relay.umockdev @@ -0,0 +1,454 @@ +P: /devices/pci0000:00/0000:00:01.2/0000:02:00.0/0000:03:08.0/0000:06:00.1/usb1/1-3 +N: bus/usb/001/007=1201100100000008C016DF0500010102000109022200010100800A09040000010300000009210101000122160007058103080064 +E: BUSNUM=001 +E: CURRENT_TAGS=:seat:uaccess: +E: DEVNAME=/dev/bus/usb/001/007 +E: DEVNUM=007 +E: DEVTYPE=usb_device +E: DRIVER=usb +E: ID_BUS=usb +E: ID_FOR_SEAT=usb-pci-0000_06_00_1-usb-0_3 +E: ID_MODEL=USBRelay4 +E: ID_MODEL_ENC=USBRelay4 +E: ID_MODEL_FROM_DATABASE=HID device except mice, keyboards, and joysticks +E: ID_MODEL_ID=05df +E: ID_PATH=pci-0000:06:00.1-usb-0:3 +E: ID_PATH_TAG=pci-0000_06_00_1-usb-0_3 +E: ID_REVISION=0100 +E: ID_SERIAL=www.dcttech.com_USBRelay4 +E: ID_USB_INTERFACES=:030000: +E: ID_USB_MODEL=USBRelay4 +E: ID_USB_MODEL_ENC=USBRelay4 +E: ID_USB_MODEL_ID=05df +E: ID_USB_REVISION=0100 +E: ID_USB_SERIAL=www.dcttech.com_USBRelay4 +E: ID_USB_VENDOR=www.dcttech.com +E: ID_USB_VENDOR_ENC=www.dcttech.com +E: ID_USB_VENDOR_ID=16c0 +E: ID_VENDOR=www.dcttech.com +E: ID_VENDOR_ENC=www.dcttech.com +E: ID_VENDOR_FROM_DATABASE=Van Ooijen Technische Informatica +E: ID_VENDOR_ID=16c0 +E: MAJOR=189 +E: MINOR=6 +E: PRODUCT=16c0/5df/100 +E: SUBSYSTEM=usb +E: TAGS=:seat:uaccess: +E: TYPE=0/0/0 +A: authorized=1\n +A: avoid_reset_quirk=0\n +A: bConfigurationValue=1\n +A: bDeviceClass=00\n +A: bDeviceProtocol=00\n +A: bDeviceSubClass=00\n +A: bMaxPacketSize0=8\n +A: bMaxPower=20mA\n +A: bNumConfigurations=1\n +A: bNumInterfaces= 1\n +A: bcdDevice=0100\n +A: bmAttributes=80\n +A: busnum=1\n +A: configuration= +H: descriptors=1201100100000008C016DF0500010102000109022200010100800A09040000010300000009210101000122160007058103080064 +A: dev=189:6\n +A: devnum=7\n +A: devpath=3\n +L: driver=../../../../../../../../bus/usb/drivers/usb +L: firmware_node=../../../../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:2e/device:2f/device:40/device:41/device:42/device:45 +A: idProduct=05df\n +A: idVendor=16c0\n +A: ltm_capable=no\n +A: manufacturer=www.dcttech.com\n +A: maxchild=0\n +A: physical_location/dock=no\n +A: physical_location/horizontal_position=right\n +A: physical_location/lid=no\n +A: physical_location/panel=back\n +A: physical_location/vertical_position=center\n +L: port=../1-0:1.0/usb1-port3 +A: power/active_duration=122028\n +A: power/async=enabled\n +A: power/autosuspend=2\n +A: power/autosuspend_delay_ms=2000\n +A: power/connected_duration=122028\n +A: power/control=on\n +A: power/level=on\n +A: power/persist=1\n +A: power/runtime_active_kids=0\n +A: power/runtime_active_time=121748\n +A: power/runtime_enabled=forbidden\n +A: power/runtime_status=active\n +A: power/runtime_suspended_time=0\n +A: power/runtime_usage=1\n +A: product=USBRelay4\n +A: quirks=0x0\n +A: removable=removable\n +A: rx_lanes=1\n +A: speed=1.5\n +A: tx_lanes=1\n +A: urbnum=13\n +A: version= 1.10\n + +P: /devices/pci0000:00/0000:00:01.2/0000:02:00.0/0000:03:08.0/0000:06:00.1/usb1 +N: bus/usb/001/001=12010002090001406B1D020002060302010109021900010100E0000904000001090000000705810304000C +E: BUSNUM=001 +E: CURRENT_TAGS=:seat: +E: DEVNAME=/dev/bus/usb/001/001 +E: DEVNUM=001 +E: DEVTYPE=usb_device +E: DRIVER=usb +E: ID_AUTOSUSPEND=1 +E: ID_BUS=usb +E: ID_FOR_SEAT=usb-pci-0000_06_00_1 +E: ID_MODEL=xHCI_Host_Controller +E: ID_MODEL_ENC=xHCI\x20Host\x20Controller +E: ID_MODEL_FROM_DATABASE=2.0 root hub +E: ID_MODEL_ID=0002 +E: ID_PATH=pci-0000:06:00.1 +E: ID_PATH_TAG=pci-0000_06_00_1 +E: ID_REVISION=0602 +E: ID_SERIAL=Linux_6.2.0-31-generic_xhci-hcd_xHCI_Host_Controller_0000:06:00.1 +E: ID_SERIAL_SHORT=0000:06:00.1 +E: ID_USB_INTERFACES=:090000: +E: ID_USB_MODEL=xHCI_Host_Controller +E: ID_USB_MODEL_ENC=xHCI\x20Host\x20Controller +E: ID_USB_MODEL_ID=0002 +E: ID_USB_REVISION=0602 +E: ID_USB_SERIAL=Linux_6.2.0-31-generic_xhci-hcd_xHCI_Host_Controller_0000:06:00.1 +E: ID_USB_SERIAL_SHORT=0000:06:00.1 +E: ID_USB_VENDOR=Linux_6.2.0-31-generic_xhci-hcd +E: ID_USB_VENDOR_ENC=Linux\x206.2.0-31-generic\x20xhci-hcd +E: ID_USB_VENDOR_ID=1d6b +E: ID_VENDOR=Linux_6.2.0-31-generic_xhci-hcd +E: ID_VENDOR_ENC=Linux\x206.2.0-31-generic\x20xhci-hcd +E: ID_VENDOR_FROM_DATABASE=Linux Foundation +E: ID_VENDOR_ID=1d6b +E: MAJOR=189 +E: MINOR=0 +E: PRODUCT=1d6b/2/602 +E: SUBSYSTEM=usb +E: TAGS=:seat: +E: TYPE=9/0/1 +A: authorized=1\n +A: authorized_default=1\n +A: avoid_reset_quirk=0\n +A: bConfigurationValue=1\n +A: bDeviceClass=09\n +A: bDeviceProtocol=01\n +A: bDeviceSubClass=00\n +A: bMaxPacketSize0=64\n +A: bMaxPower=0mA\n +A: bNumConfigurations=1\n +A: bNumInterfaces= 1\n +A: bcdDevice=0602\n +A: bmAttributes=e0\n +A: busnum=1\n +A: configuration= +H: descriptors=12010002090001406B1D020002060302010109021900010100E0000904000001090000000705810304000C +A: dev=189:0\n +A: devnum=1\n +A: devpath=0\n +L: driver=../../../../../../../bus/usb/drivers/usb +L: firmware_node=../../../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:2e/device:2f/device:40/device:41/device:42 +A: idProduct=0002\n +A: idVendor=1d6b\n +A: interface_authorized_default=1\n +A: ltm_capable=no\n +A: manufacturer=Linux 6.2.0-31-generic xhci-hcd\n +A: maxchild=6\n +A: power/active_duration=6656836\n +A: power/async=enabled\n +A: power/autosuspend=0\n +A: power/autosuspend_delay_ms=0\n +A: power/connected_duration=6656836\n +A: power/control=auto\n +A: power/level=auto\n +A: power/runtime_active_kids=2\n +A: power/runtime_active_time=6656831\n +A: power/runtime_enabled=enabled\n +A: power/runtime_status=active\n +A: power/runtime_suspended_time=0\n +A: power/runtime_usage=0\n +A: power/wakeup=disabled\n +A: power/wakeup_abort_count=\n +A: power/wakeup_active=\n +A: power/wakeup_active_count=\n +A: power/wakeup_count=\n +A: power/wakeup_expire_count=\n +A: power/wakeup_last_time_ms=\n +A: power/wakeup_max_time_ms=\n +A: power/wakeup_total_time_ms=\n +A: product=xHCI Host Controller\n +A: quirks=0x0\n +A: removable=unknown\n +A: rx_lanes=1\n +A: serial=0000:06:00.1\n +A: speed=480\n +A: tx_lanes=1\n +A: urbnum=181\n +A: version= 2.00\n + +P: /devices/pci0000:00/0000:00:01.2/0000:02:00.0/0000:03:08.0/0000:06:00.1 +E: DRIVER=xhci_hcd +E: ID_MODEL_FROM_DATABASE=Matisse USB 3.0 Host Controller +E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller +E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI +E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller +E: ID_VENDOR_FROM_DATABASE=Advanced Micro Devices, Inc. [AMD] +E: MODALIAS=pci:v00001022d0000149Csv00001022sd00001486bc0Csc03i30 +E: PCI_CLASS=C0330 +E: PCI_ID=1022:149C +E: PCI_SLOT_NAME=0000:06:00.1 +E: PCI_SUBSYS_ID=1022:1486 +E: SUBSYSTEM=pci +A: ari_enabled=0\n +A: broken_parity_status=0\n +A: class=0x0c0330\n +H: config=22109C14070410000030030C10008000040040FC000000000000000000000000000000000000000000000000221086140000000048000000000000000A010000 +A: consistent_dma_mask_bits=64\n +A: current_link_speed=16.0 GT/s PCIe\n +A: current_link_width=16\n +A: d3cold_allowed=1\n +A: dbc=disabled\n +A: device=0x149c\n +A: dma_mask_bits=64\n +L: driver=../../../../../../bus/pci/drivers/xhci_hcd +A: driver_override=(null)\n +A: enable=1\n +L: firmware_node=../../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:2e/device:2f/device:40/device:41 +A: irq=41\n +A: link/l0s_aspm=0\n +A: link/l1_aspm=0\n +A: local_cpulist=0-15\n +A: local_cpus=0000ffff\n +A: max_link_speed=16.0 GT/s PCIe\n +A: max_link_width=16\n +A: modalias=pci:v00001022d0000149Csv00001022sd00001486bc0Csc03i30\n +A: msi_bus=1\n +A: msi_irqs/41=msi\n +A: numa_node=-1\n +A: pools=poolinfo - 0.1\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 0 0 128 0\nbuffer-32 0 0 32 0\nxHCI 1KB stream ctx arrays 0 0 1024 0\nxHCI 256 byte stream ctx arrays 0 0 256 0\nxHCI input/output contexts 4 5 2112 5\nxHCI ring segments 12 14 4096 14\nbuffer-2048 3 6 2048 3\nbuffer-512 0 0 512 0\nbuffer-128 18 32 128 1\nbuffer-32 0 0 32 0\n +A: power/async=enabled\n +A: power/control=on\n +A: power/runtime_active_kids=1\n +A: power/runtime_active_time=6657357\n +A: power/runtime_enabled=forbidden\n +A: power/runtime_status=active\n +A: power/runtime_suspended_time=0\n +A: power/runtime_usage=1\n +A: power/wakeup=enabled\n +A: power/wakeup_abort_count=0\n +A: power/wakeup_active=0\n +A: power/wakeup_active_count=0\n +A: power/wakeup_count=0\n +A: power/wakeup_expire_count=0\n +A: power/wakeup_last_time_ms=0\n +A: power/wakeup_max_time_ms=0\n +A: power/wakeup_total_time_ms=0\n +A: power_state=D0\n +A: resource=0x00000000fc400000 0x00000000fc4fffff 0x0000000000140204\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n +A: revision=0x00\n +A: subsystem_device=0x1486\n +A: subsystem_vendor=0x1022\n +A: vendor=0x1022\n + +P: /devices/pci0000:00/0000:00:01.2/0000:02:00.0/0000:03:08.0 +E: DRIVER=pcieport +E: ID_MODEL_FROM_DATABASE=Matisse PCIe GPP Bridge +E: ID_PCI_CLASS_FROM_DATABASE=Bridge +E: ID_PCI_INTERFACE_FROM_DATABASE=Normal decode +E: ID_PCI_SUBCLASS_FROM_DATABASE=PCI bridge +E: ID_VENDOR_FROM_DATABASE=Advanced Micro Devices, Inc. [AMD] +E: MODALIAS=pci:v00001022d000057A4sv00001022sd00001484bc06sc04i00 +E: PCI_CLASS=60400 +E: PCI_ID=1022:57A4 +E: PCI_SLOT_NAME=0000:03:08.0 +E: PCI_SUBSYS_ID=1022:1484 +E: SUBSYSTEM=pci +A: ari_enabled=0\n +A: broken_parity_status=0\n +A: class=0x060400\n +H: config=2210A457070410000000040610000100000000000000000003060600F101000030FC40FCF1FF010000000000000000000000000050000000000000000A011200 +A: consistent_dma_mask_bits=32\n +A: current_link_speed=16.0 GT/s PCIe\n +A: current_link_width=16\n +A: d3cold_allowed=1\n +A: device=0x57a4\n +A: dma_mask_bits=32\n +L: driver=../../../../../bus/pci/drivers/pcieport +A: driver_override=(null)\n +A: enable=2\n +L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:2e/device:2f/device:40 +A: irq=34\n +A: local_cpulist=0-15\n +A: local_cpus=0000ffff\n +A: max_link_speed=16.0 GT/s PCIe\n +A: max_link_width=16\n +A: modalias=pci:v00001022d000057A4sv00001022sd00001484bc06sc04i00\n +A: msi_bus=1\n +A: msi_irqs/34=msi\n +A: numa_node=-1\n +A: power/async=enabled\n +A: power/autosuspend_delay_ms=100\n +A: power/control=auto\n +A: power/runtime_active_kids=3\n +A: power/runtime_active_time=6657364\n +A: power/runtime_enabled=enabled\n +A: power/runtime_status=active\n +A: power/runtime_suspended_time=0\n +A: power/runtime_usage=0\n +A: power/wakeup=disabled\n +A: power/wakeup_abort_count=\n +A: power/wakeup_active=\n +A: power/wakeup_active_count=\n +A: power/wakeup_count=\n +A: power/wakeup_expire_count=\n +A: power/wakeup_last_time_ms=\n +A: power/wakeup_max_time_ms=\n +A: power/wakeup_total_time_ms=\n +A: power_state=D0\n +A: reset_method=pm\n +A: resource=0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x00000000fc300000 0x00000000fc4fffff 0x0000000000000200\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n +A: revision=0x00\n +A: secondary_bus_number=6\n +A: subordinate_bus_number=6\n +A: subsystem_device=0x1484\n +A: subsystem_vendor=0x1022\n +A: vendor=0x1022\n + +P: /devices/pci0000:00/0000:00:01.2/0000:02:00.0 +E: DRIVER=pcieport +E: ID_MODEL_FROM_DATABASE=Matisse Switch Upstream +E: ID_PCI_CLASS_FROM_DATABASE=Bridge +E: ID_PCI_INTERFACE_FROM_DATABASE=Normal decode +E: ID_PCI_SUBCLASS_FROM_DATABASE=PCI bridge +E: ID_VENDOR_FROM_DATABASE=Advanced Micro Devices, Inc. [AMD] +E: MODALIAS=pci:v00001022d000057ADsv00000000sd00000000bc06sc04i00 +E: PCI_CLASS=60400 +E: PCI_ID=1022:57AD +E: PCI_SLOT_NAME=0000:02:00.0 +E: PCI_SUBSYS_ID=0000:0000 +E: SUBSYSTEM=pci +A: ari_enabled=0\n +A: broken_parity_status=0\n +A: class=0x060400\n +H: config=2210AD57070010000000040610000100000000000000000002030800F1F1000030FC80FCF1FF010000000000000000000000000050000000000000000A011200 +A: consistent_dma_mask_bits=32\n +A: current_link_speed=16.0 GT/s PCIe\n +A: current_link_width=4\n +A: d3cold_allowed=1\n +A: device=0x57ad\n +A: dma_mask_bits=32\n +L: driver=../../../../bus/pci/drivers/pcieport +A: driver_override=(null)\n +A: enable=2\n +L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:2e/device:2f +A: irq=24\n +A: link/l1_1_aspm=0\n +A: link/l1_1_pcipm=0\n +A: link/l1_aspm=0\n +A: local_cpulist=0-15\n +A: local_cpus=0000ffff\n +A: max_link_speed=16.0 GT/s PCIe\n +A: max_link_width=8\n +A: modalias=pci:v00001022d000057ADsv00000000sd00000000bc06sc04i00\n +A: msi_bus=1\n +A: numa_node=-1\n +A: power/async=enabled\n +A: power/autosuspend_delay_ms=100\n +A: power/control=auto\n +A: power/runtime_active_kids=5\n +A: power/runtime_active_time=6657367\n +A: power/runtime_enabled=enabled\n +A: power/runtime_status=active\n +A: power/runtime_suspended_time=0\n +A: power/runtime_usage=0\n +A: power/wakeup=disabled\n +A: power/wakeup_abort_count=\n +A: power/wakeup_active=\n +A: power/wakeup_active_count=\n +A: power/wakeup_count=\n +A: power/wakeup_expire_count=\n +A: power/wakeup_last_time_ms=\n +A: power/wakeup_max_time_ms=\n +A: power/wakeup_total_time_ms=\n +A: power_state=D0\n +A: reset_method=pm bus\n +A: resource=0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x000000000000f000 0x000000000000ffff 0x0000000000000101\n0x00000000fc300000 0x00000000fc8fffff 0x0000000000000200\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n +A: revision=0x00\n +A: secondary_bus_number=3\n +A: subordinate_bus_number=8\n +A: subsystem_device=0x0000\n +A: subsystem_vendor=0x0000\n +A: vendor=0x1022\n + +P: /devices/pci0000:00/0000:00:01.2 +E: DRIVER=pcieport +E: ID_MODEL_FROM_DATABASE=Starship/Matisse GPP Bridge +E: ID_PCI_CLASS_FROM_DATABASE=Bridge +E: ID_PCI_INTERFACE_FROM_DATABASE=Normal decode +E: ID_PCI_SUBCLASS_FROM_DATABASE=PCI bridge +E: ID_VENDOR_FROM_DATABASE=Advanced Micro Devices, Inc. [AMD] +E: MODALIAS=pci:v00001022d00001483sv00001022sd00001453bc06sc04i00 +E: PCI_CLASS=60400 +E: PCI_ID=1022:1483 +E: PCI_SLOT_NAME=0000:00:01.2 +E: PCI_SUBSYS_ID=1022:1453 +E: SUBSYSTEM=pci +A: aer_dev_correctable=RxErr 0\nBadTLP 0\nBadDLLP 0\nRollover 0\nTimeout 0\nNonFatalErr 0\nCorrIntErr 0\nHeaderOF 0\nTOTAL_ERR_COR 0\n +A: aer_dev_fatal=Undefined 0\nDLP 0\nSDES 0\nTLP 0\nFCP 0\nCmpltTO 0\nCmpltAbrt 0\nUnxCmplt 0\nRxOF 0\nMalfTLP 0\nECRC 0\nUnsupReq 0\nACSViol 0\nUncorrIntErr 0\nBlockedTLP 0\nAtomicOpBlocked 0\nTLPBlockedErr 0\nPoisonTLPBlocked 0\nTOTAL_ERR_FATAL 0\n +A: aer_dev_nonfatal=Undefined 0\nDLP 0\nSDES 0\nTLP 0\nFCP 0\nCmpltTO 0\nCmpltAbrt 0\nUnxCmplt 0\nRxOF 0\nMalfTLP 0\nECRC 0\nUnsupReq 0\nACSViol 0\nUncorrIntErr 0\nBlockedTLP 0\nAtomicOpBlocked 0\nTLPBlockedErr 0\nPoisonTLPBlocked 0\nTOTAL_ERR_NONFATAL 0\n +A: aer_rootport_total_err_cor=0\n +A: aer_rootport_total_err_fatal=0\n +A: aer_rootport_total_err_nonfatal=0\n +A: ari_enabled=0\n +A: broken_parity_status=0\n +A: class=0x060400\n +H: config=22108314070410000000040610008100000000000000000000020800F1F1002030FC80FCF1FF01000000000000000000000000005000000000000000FF001200 +A: consistent_dma_mask_bits=32\n +A: current_link_speed=16.0 GT/s PCIe\n +A: current_link_width=4\n +A: d3cold_allowed=1\n +A: device=0x1483\n +A: dma_mask_bits=32\n +L: driver=../../../bus/pci/drivers/pcieport +A: driver_override=(null)\n +A: enable=2\n +L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:2e +A: irq=27\n +A: local_cpulist=0-15\n +A: local_cpus=0000ffff\n +A: max_link_speed=16.0 GT/s PCIe\n +A: max_link_width=8\n +A: modalias=pci:v00001022d00001483sv00001022sd00001453bc06sc04i00\n +A: msi_bus=1\n +A: msi_irqs/27=msi\n +A: numa_node=-1\n +A: power/async=enabled\n +A: power/autosuspend_delay_ms=100\n +A: power/control=auto\n +A: power/runtime_active_kids=1\n +A: power/runtime_active_time=6657374\n +A: power/runtime_enabled=enabled\n +A: power/runtime_status=active\n +A: power/runtime_suspended_time=0\n +A: power/runtime_usage=0\n +A: power/wakeup=enabled\n +A: power/wakeup_abort_count=0\n +A: power/wakeup_active=0\n +A: power/wakeup_active_count=0\n +A: power/wakeup_count=0\n +A: power/wakeup_expire_count=0\n +A: power/wakeup_last_time_ms=0\n +A: power/wakeup_max_time_ms=0\n +A: power/wakeup_total_time_ms=0\n +A: power_state=D0\n +A: reset_method=pm\n +A: resource=0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x000000000000f000 0x000000000000ffff 0x0000000000000101\n0x00000000fc300000 0x00000000fc8fffff 0x0000000000000200\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n +A: revision=0x00\n +A: secondary_bus_number=2\n +A: subordinate_bus_number=8\n +A: subsystem_device=0x1453\n +A: subsystem_vendor=0x1022\n +A: vendor=0x1022\n + diff --git a/test/test.sh b/test/test.sh new file mode 100755 index 0000000..b6e4fcc --- /dev/null +++ b/test/test.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +PCAPPATH="/sys/devices/pci0000:00/0000:00:01.2/0000:02:00.0/0000:03:08.0/0000:06:00.1/usb1/1-3" + +commands=( +"list" +"on REL01 all" +"off REL01 all" +"toggle REL01 all" +"setserial REL01 REL02" +"setserial REL02 REL01" +"list" +) +tests=( +"umockdev-run --device relay.umockdev --pcap $PCAPPATH=01-list-start.pcapng /tmp/usbrelay list" +"umockdev-run --device relay.umockdev --pcap $PCAPPATH=02-on-all.pcapng /tmp/usbrelay on REL01 all" +"umockdev-run --device relay.umockdev --pcap $PCAPPATH=03-off-all.pcapng /tmp/usbrelay off REL01 all" +"umockdev-run --device relay.umockdev --pcap $PCAPPATH=04-toggle-all.pcapng /tmp/usbrelay toggle REL01 all" +"umockdev-run --device relay.umockdev --pcap $PCAPPATH=05-setserial-rel01-rel02.pcapng /tmp/usbrelay setserial REL01 REL02" +"umockdev-run --device relay.umockdev --pcap $PCAPPATH=06-setserial-rel02-rel01.pcapng /tmp/usbrelay setserial REL02 REL01" +"umockdev-run --device relay.umockdev --pcap $PCAPPATH=07-list-end.pcapng /tmp/usbrelay list" +) + +for (( i = 0; i < ${#tests[@]} ; i++ )); do + printf 'Running: %s\n' "${commands[$i]}" + + if ! ${tests[$i]}; then + printf '\Failed: %s\n' "${commands[$i]}" + exit 1 + fi +done \ No newline at end of file diff --git a/usbrelay.go b/usbrelay.go index df10109..490f72b 100644 --- a/usbrelay.go +++ b/usbrelay.go @@ -34,7 +34,7 @@ func Enumerate() ([]*Device, error) { if err != nil { return devices, err } - if numRelays < 0 || numRelays > 8 { + if numRelays < 0 && numRelays != R_ALL { return nil, fmt.Errorf("%w num relays: %d", ErrInvalidNumberOfRelays, numRelays) }