This software is a USB proxy based on raw-gadget and libusb. It is recommended to run this repo on a computer that has an USB OTG port, such as Raspberry Pi 4
or other hardware that can work with raw-gadget
, otherwise might need to use dummy_hcd
kernel module to set up virtual USB Device and Host controller that connected to each other inside the kernel.
------------ ----------------------------------------------- -----------------------
| | | | | |
| | |------------- -----------| |------------- |
| USB <-----> USB | Host COMPUTER | USB <-----> USB | USB |
| device | | host port | running usb-proxy | OTG port | | host port | Host |
| | |------------- with raw-gadget -----------| |------------- |
| | | | | |
------------ ----------------------------------------------- -----------------------
------------ ------------------------------------
| | | |
| | |------------- Host COMPUTER |
| USB <-----> USB | running usb-proxy |
| device | | host port | with raw-gadget |
| | |------------- and dummy_hcd |
| | | |
------------ ------------------------------------
Please clone the raw-gadget, and compile the kernel modules(if you need dummy_hcd
as well, please compile it, otherwise only need to compile raw-gadget
) in the repo, then load raw-gadget
kernel module, you will be able to access /dev/raw-gadget
afterward.
Install the package
sudo apt install libusb-1.0-0-dev libjsoncpp-dev
Please check the name of device
and driver
on your hardware with the following command. If you are going to use dummy_hcd
, then this step can be skipped, because usb-proxy
will use dummy_hcd
by default.
# For device name
$ ls /sys/class/udc/
fe980000.usb
# For driver name
$ cat /sys/class/udc/fe980000.usb/uevent
USB_UDC_NAME=fe980000.usb
Note: If you are not able to see the above on your Raspberry Pi 4
, probably you didn't enable the dwc2
kernel module, please execute the following command and try again after reboot.
$ echo "dtoverlay=dwc2" | sudo tee -a /boot/config.txt
$ echo "dwc2" | sudo tee -a /etc/modules
$ sudo reboot
Please plug the USB device that you want to test into Raspberry Pi 4
, then execute lsusb
on terminal.
$ lsusb
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 1b3f:2247 Generalplus Technology Inc. GENERAL WEBCAM
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
As you can see, There is a Bus 001 Device 003: ID 1b3f:2247 Generalplus Technology Inc. GENERAL WEBCAM
, and 1b3f:2247
is the vendor_id
and product_id
with a colon between them.
Usage:
-h/--help: print this help message
-v/--verbose: increase verbosity
--device: use specific device
--driver: use specific driver
--vendor_id: use specific vendor_id(HEX) of USB device
--product_id: use specific product_id(HEX) of USB device
--enable_injection: enable the injection feature
--injection_file: specify the file that contains injection rules
- If
device
not specified,usb-proxy
will usedummy_udc.0
as default device. - If
driver
not specified,usb-proxy
will usedummy_udc
as default driver. - If both
vendor_id
andproduct_id
not specified,usb-proxy
will connect the first USB device it can find.
For example:
$ ./usb-proxy --device=fe980000.usb --driver=fe980000.usb --vendor_id=1b3f --product_id=2247
Please replace fe980000.usb
with the device
that you have when running this software, and then replace the driver
variable with the string after USB_UDC_NAME=
in step 2. Please also modify the vendor_id
and product_id
variable that you have checked in step 3.
This feature is still very simple. Ideas or suggestions are very welcome.
Please edit the injection.json
for the injection rules. The following is the default template.
Note: The comment in the following template is only for explaining the meaning, please do not copy the comment, it is invalid in json.
{
"control": {
"modify": [ // For modify the control transfer data
{
"enable": false, // Enable this rule or not
"bRequestType": 0, // Hex value
"bRequest": 0, // Hex value
"wValue": 0, // Hex value
"wIndex": 0, // Hex value
"wLength": 0, // Hex value
"content_pattern": [], // If USB packet contains any data that match any patterns, the matched data will be replaced with the value in "replacement". Format is Hex string, for example: \\x01\\x00\\x00\\x00
"replacement": "" // The content after modified. Format is Hex string, for example: \\x02\\x00\\x00\\x00
}
],
"ignore": [ // For ignoring control transfer packet, it won't be sent to Host/Device if match the rule
{
"enable": false,
"bRequestType": 0,
"bRequest": 0,
"wValue": 0,
"wIndex": 0,
"wLength": 0,
"content_pattern": []
}
],
"stall": [ // For stalling Host if match the rule
{
"enable": false,
"bRequestType": 0,
"bRequest": 0,
"wValue": 0,
"wIndex": 0,
"wLength": 0,
"content_pattern": []
}
]
},
"int": [
{
"ep_address": 81, // Endpoint address in Hex
"enable": false,
"content_pattern": [],
"replacement": ""
}
],
"bulk": [
{
"ep_address": 81,
"enable": false,
"content_pattern": [],
"replacement": ""
}
],
"isoc": [] // This transfer type is not supported yet
}
For example, the following rules work with my USB mouse, and convert left click to right click, and convert right click to left click.
{
"control": {
"modify": [],
"ignore": [],
"stall": []
},
"int": [
{
"ep_address": 81,
"enable": true,
"content_pattern": ["\\x01\\x00\\x00\\x00"],
"replacement": "\\x02\\x00\\x00\\x00"
},
{
"ep_address": 81,
"enable": true,
"content_pattern": ["\\x02\\x00\\x00\\x00"],
"replacement": "\\x01\\x00\\x00\\x00"
}
],
"bulk": [],
"isoc": []
}
Use the --enable_injection
to enable this feature, and use --injection_file
to specify the file path of your customized injection rules, if it is not specified, usb-proxy
will use injection.json
by default.
For example
$ ./usb-proxy --device=fe980000.usb --driver=fe980000.usb --enable_injection --injection_file=myInjectionRules.json