Skip to content

Commit c9016ad

Browse files
authored
Merge pull request #5 from HydraDancer/v1.1.2
v1.1.2
2 parents 5b30426 + 47dc148 commit c9016ad

16 files changed

+328
-207
lines changed

.pre-commit-config.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@
22
# See https://pre-commit.com/hooks.html for more hooks
33
repos:
44
- repo: https://github.com/pre-commit/pre-commit-hooks
5-
rev: v3.2.0
5+
rev: v4.6.0
66
hooks:
77
- id: trailing-whitespace
88
- id: check-yaml
99
- id: check-added-large-files
1010
- id: check-merge-conflict
1111
- repo: https://github.com/hhatto/autopep8
12-
rev: v2.0.4
12+
rev: v2.3.1
1313
hooks:
1414
- id: autopep8
1515
- repo: https://github.com/pylint-dev/pylint
16-
rev: v3.0.2
16+
rev: v3.2.5
1717
hooks:
1818
- id: pylint
1919
- repo: https://github.com/pre-commit/mirrors-clang-format

BUILD.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,11 @@ Currently, you need two HydraUSB3 boards connected together via HSPI. You just n
9090
To be able to access the HydraDancer boards and flash them, root privileges may be required, or you can provide them to your regular user, e.g. with the creation of a file `/etc/udev/rules.d/99-hydrausb3.rules` with
9191

9292
```
93-
# UDEV Rules for HydraUSB3 boards, https://github.com/hydrausb3
93+
# UDEV Rules for HydraUSB3 boards https://github.com/hydrausb3, Hydradancer https://github.com/HydraDancer/hydradancer_fw and Facedancer https://github.com/greatscottgadgets/Facedancer
9494
# WinChipHead CH569W Bootloader
9595
SUBSYSTEMS=="usb", ATTRS{idVendor}=="4348", ATTRS{idProduct}=="55e0", MODE="0664", GROUP="plugdev"
96+
# Hydradancer
97+
SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="27d8", MODE="0664", GROUP="plugdev"
9698
```
9799

98100
and having your user as member of the group `plugdev`.

README.md

Lines changed: 112 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,122 @@
22

33
Hydradancer provides a faster, USB2 High-Speed capable backend for Facedancer by taking advantage of fast communication protocols such as USB3, SerDes and HSPI.
44

5+
The following examples have been confirmed working:
6+
* hackrf-info.py
7+
* imperative.py
8+
* mass-storage.py
9+
* minimal.py (with test_minimal.py)
10+
* rubber-ducky.py
11+
* template.py
12+
* usbproxy.py : USB Flash Drive in USB2 High-Speed
13+
14+
**DISCLAIMER** : current results for the [highly-stressed stress test of Facedancer](https://github.com/greatscottgadgets/facedancer/blob/main/test/test_stress.py) with 20000 tries.
15+
16+
The current Facedancer stress test results are the following.
17+
* USB2 High-Speed
18+
* bulk IN/ctrl IN : pass
19+
* bulk OUT/ctrl OUT : fails after a few hundred/thousand tries, never reaches 20000
20+
* USB2 Full-Speed
21+
* bulk IN/ctrl IN : fails after a few hundred/thousand tries, never reaches 20000
22+
* bulk OUT/ctrl OUT : fails after a few hundred/thousand tries, never reaches 20000
23+
24+
We are currently working on fixing those issues and we have a few culprits in mind :
25+
* missed interrupts : the main culprit for now, it puts Hydradancer in a blocked state.
26+
* differences between HS/FS : HS has PING packets which reduces the amount of data transfers for OUT transactions. Since there are no FS examples from WCH and no indications in the datasheet, we experimented to solve this issue.
27+
28+
We implemented a [firmware](https://github.com/hydrausb3/wch-ch56x-lib/tree/main/tests/test_firmware_usb_stress_test) to test the USB2 implementation of `wch-ch56x-lib` with the same stress test and it passes with 100000 tries in both HS and FS. However, Hydradancer's firmware is more complex (more interrupts, USB3 and USB2 at the same time, delays to synchronize with Facedancer).
29+
30+
# Getting started (Hydradancer dongle)
31+
32+
1. To be able to access the HydraDancer boards and flash them, root privileges may be required, or you can provide them to your regular user, e.g. with the creation of a file `/etc/udev/rules.d/99-hydradancer.rules` with
33+
34+
```
35+
# UDEV Rules for HydraUSB3 boards https://github.com/hydrausb3, Hydradancer https://github.com/HydraDancer/hydradancer_fw and Facedancer https://github.com/greatscottgadgets/Facedancer
36+
# WinChipHead CH569W Bootloader
37+
SUBSYSTEMS=="usb", ATTRS{idVendor}=="4348", ATTRS{idProduct}=="55e0", MODE="0664", GROUP="plugdev"
38+
# Hydradancer
39+
SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="27d8", MODE="0664", GROUP="plugdev"
40+
```
41+
42+
and having your user as member of the group `plugdev`.
43+
44+
2. Flash the firmware to your Hydradancer dongle using the [latest release](https://github.com/HydraDancer/hydradancer_fw/releases/latest) (download `all-firmwares*.zip`) with [wch-ch56-isp](https://github.com/hydrausb3/wch-ch56x-isp/releases/latest)
45+
46+
First
47+
48+
```
49+
Put the Hydradancer dongle in firmware download mode. For that, you need the following buttons :
50+
* reset : button with "RST" next to it
51+
* flash mode : button with "Flash Mode" next to it
52+
53+
You need to hold the flash mode button, press reset and then release the flash mode button.
54+
```
55+
56+
Then, launch `wch-ch56x-isp`
57+
58+
```shell
59+
wch-ch56x-isp -vf firmware_hydradancer.bin
60+
```
61+
62+
3. Install Facedancer
63+
64+
Clone our Facedancer work
65+
66+
```shell
67+
https://github.com/HydraDancer/Facedancer
68+
```
69+
70+
Then, reuse your virtual env or create a new one to keep your local Python installation clean
71+
72+
```shell
73+
sudo apt install python3 python3-venv
74+
python3 -m venv venv
75+
```
76+
77+
Activate the venv
78+
79+
```shell
80+
source venv/bin/activate
81+
```
82+
83+
Install Facedancer
84+
85+
```shell
86+
cd Facedancer
87+
pip install --editable .
88+
```
89+
90+
The `--editable` isn't necessary but it allows you to modify Facedancer's files.
91+
92+
4. Test one of the examples
93+
94+
Then, tell Facedancer to use the Hydradancer backend
95+
96+
```shell
97+
export BACKEND=hydradancer
98+
```
99+
100+
And finally, run one of the examples to check if everything works
101+
102+
```shell
103+
python3 ./examples/rubber-ducky.py
104+
```
105+
106+
To test the proxy mode of Facedancer, you might need to use the following line (after editing `usbproxy.py` with the target vid/pid)
107+
108+
```shell
109+
sudo sh -c "env BACKEND=hydradancer ./venv/bin/python3 examples/usbproxy.py"
110+
```
111+
5112
# Comparison with other Facedancer boards
6113

7-
As shown in the table below, Hydradancer currently supports 5 endpoints other than endpoint 0 in either the IN or OUT directions, with numbers between 1-7. Hydradancer can also emulate USB2 High-speed peripherals. Host mode is currently unsupported, but could be implemented if needed.
114+
As shown in the table below, Hydradancer currently supports 5 endpoints other than endpoint 0 in either the IN or OUT directions, with numbers between 1-15. Hydradancer can also emulate USB2 High-speed peripherals. Host mode is currently unsupported, but could be implemented if needed.
8115

9116
|Board|Maximum speed |Number of endpoints (not EP0) |Host mode|
10117
|:---:|:----:|:-:|:-:|
11118
Facedancer21/Raspdancer |USB2 Full-speed |EP1 OUT, EP2 IN, EP3 IN |yes|
12119
GreatFET One |USB2 Full-speed |3 IN / 3 OUT |yes|
13-
**Hydradancer** |USB2 High-speed |6 IN / 6 OUT |no|
120+
**Hydradancer** |USB2 High-speed |5 IN / 5 OUT |no|
14121
(Cynthion/LUNA)(coming early 2024) |(USB2 High-speed) |(15 IN / 15 OUT) |(yes)|
15122

16123
<p style="text-align: center "><em>Facedancer backends functionalities</em></p>
@@ -103,67 +210,18 @@ Previous results for Hydradancer used priming, which made it faster. The new ver
103210
There are two configurations for Hydradancer:
104211

105212
* the Hydradancer dongle : only the firmware from `hydradancer/firmware_hydradancer` is needed.
106-
* (unmaintained) the dual-HydraUSB3 : you will need the firmware compiled from `hydradancer/firmware_control_board` and `hydradancer/firmware_emulation_board`.
213+
* (unmaintained) the dual-HydraUSB3 : you will need the firmware compiled from `legacy/hydradancer/firmware_control_board` and `legacy/hydradancer/firmware_emulation_board`.
107214

108215
To build and flash the firmware, see [the build tutorial](BUILD.md). If you don't want to build the firmwares yourself, you can skip the building part by using the [latest release](https://github.com/HydraDancer/hydradancer_fw/releases/latest).
109216

110-
# ... and finally, using Facedancer with Hydradancer !
111-
112-
First, clone Facedancer. While we hope to merge the Hydradancer backend for Facedancer into the [main repository](https://github.com/greatscottgadgets/Facedancer) along with some bug fixes we may have found, the Hydradancer backend is currently in our fork.
113-
114-
For the unmaintained dual-HydraUSB3 firmware, you will need v1.0.0 of our Facedancer fork.
115-
116-
```shell
117-
git clone https://github.com/HydraDancer/Facedancer
118-
```
119-
120-
Then, reuse your virtual env or create a new one to keep your local Python installation clean
121-
122-
```shell
123-
sudo apt install python3 python3-venv
124-
python3 -m venv venv
125-
```
126-
127-
Activate the venv
128-
129-
```shell
130-
source venv/bin/activate
131-
```
132-
133-
Install Facedancer
134-
135-
```shell
136-
cd Facedancer
137-
pip install --editable .
138-
```
139-
140-
The `--editable` isn't necessary but it allows you to modify Facedancer's files.
141-
142-
Then, tell Facedancer to use the Hydradancer backend
143-
144-
```shell
145-
export BACKEND=hydradancer
146-
```
147-
148-
And finally, run one of the examples to check if everything works, this one should make your cursor wiggle.
149-
150-
```shell
151-
python3 ./examples/crazy-mouse.py
152-
```
153-
154-
More information on the different peripherals that can be emulated can be found in `docs/Facedancer.md`
155-
156-
_Note for the dual-HydraUSB3 configuration: you might need to reset both boards after flashing the firmwares (control board first, then emulation board), or if any problem arises when running the scripts._
157-
158217
# Structure of the project
159218

160219
```
161220
hydradancer/
162-
| ├─ firmware_control_board # firmware for the board connected to Facedancer, dual-HydraUSB3 configuration
163-
| ├─ firmware_emulation_board # firmware for the board connected to the target USB port, dual-HydraUSB3 configuration
164221
| ├─ firmware_hydradancer # firmware for the Hydradancer dongle
222+
| ├─ legacy/ # old HydraUSB3 firmwares, unmaintained
165223
| ├─ tests/ # test firmwares to create various USB devices
166-
| | ├─ test_backend # Test a Facedancer-like configuration, but without Facedancer. Not up-to-date.
224+
| | ├─ test_backend # Not up-to-date. Test a Facedancer-like configuration, but without Facedancer.
167225
| | ├─ native/ # C programs using libusb to interact with the test firmwares
168226
| | ├─ scripts/ # Python scripts using pyusb to interact with the test firmwares
169227
tools/

docs/Testing.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Different firmwares have been created, along with Python scripts to execute the
4141

4242
Below are the different test cases and how to test them:
4343

44-
### Backend speedtest
44+
### (unmaintained) Backend speedtest
4545

4646
* Compile :
4747
* compile `test_backend/firmware_emulation_board` and `HydraDancer/hydradancer/firmware_control_board` with `make`

hydradancer/firmware_hydradancer/User/definitions.h

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@
1616
#include "wch-ch56x-lib/USBDevice/usb_device.h"
1717
#include "wch-ch56x-lib/USBDevice/usb_endpoints.h"
1818

19-
#define CUSTOM_REGISTER_ENDPOINT_MASK 0x000f
20-
#define CUSTOM_REGISTER_REQUEST_CODE_BIT_MASK 0x0010
21-
#define CUSTOM_REGISTER_REQUEST_CODE_MASK 0x01e0
22-
#define CUSTOM_REGISTER_REQUEST_CODE_OFFSET 0x5
23-
2419
#define USB2_LS 0x00
2520
#define USB2_FS 0x01
2621
#define USB2_HS 0x02
@@ -53,10 +48,10 @@
5348

5449
typedef struct __attribute__((packed))
5550
{
56-
uint8_t ep_in_status;
57-
uint8_t ep_out_status;
58-
uint8_t ep_in_nak;
59-
uint8_t other_events;
51+
uint16_t ep_in_status;
52+
uint16_t ep_out_status;
53+
uint16_t ep_in_nak;
54+
uint16_t other_events;
6055
} hydradancer_status_t;
6156

6257
typedef struct __attribute__((packed))
@@ -65,7 +60,7 @@ typedef struct __attribute__((packed))
6560
uint8_t value;
6661
} hydradancer_event_t;
6762

68-
#define MAX_ENDPOINTS_SUPPORTED 8 //including EP0
63+
#define MAX_ENDPOINTS_SUPPORTED 16 //including EP0
6964
extern uint8_t endpoint_mapping_reverse[MAX_ENDPOINTS_SUPPORTED]; //endpoint_mapping_reverse[PC_Endpoint] = Target_Endpoint
7065
extern uint8_t endpoint_mapping[MAX_ENDPOINTS_SUPPORTED]; //endpoint_mapping[Target_Endpoint] = PC_Endpoint
7166
extern __attribute__((aligned(16))) volatile hydradancer_status_t hydradancer_status __attribute__((section(".DMADATA")));
@@ -147,11 +142,14 @@ __attribute__((always_inline)) inline static void hydradancer_status_clear_nak(u
147142

148143
__attribute__((always_inline)) inline static void hydradancer_recover_out_interrupt(uint8_t endp_num)
149144
{
150-
ramx_pool_free(usb_device_1.endpoints.tx[endpoint_mapping[endp_num]].buffer);
151-
hydradancer_status_clear_out(endp_num);
152-
bsp_disable_interrupt();
153-
endp_rx_set_state(&usb_device_0, endp_num, ENDP_STATE_ACK);
154-
bsp_enable_interrupt();
145+
if (hydradancer_status.ep_out_status & (0x01 << endpoint_mapping_reverse[endp_num]))
146+
{
147+
ramx_pool_free(usb_device_1.endpoints.tx[endpoint_mapping[endp_num]].buffer);
148+
hydradancer_status_clear_out(endp_num);
149+
bsp_disable_interrupt();
150+
endp_rx_set_state(&usb_device_0, endp_num, ENDP_STATE_ACK);
151+
bsp_enable_interrupt();
152+
}
155153
}
156154

157155
#endif

hydradancer/firmware_hydradancer/User/main.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,14 @@ int main()
102102
usb_device_0.endpoints.tx_complete[5] = usb_emulation_endp5_tx_complete;
103103
usb_device_0.endpoints.tx_complete[6] = usb_emulation_endp6_tx_complete;
104104
usb_device_0.endpoints.tx_complete[7] = usb_emulation_endp7_tx_complete;
105+
usb_device_0.endpoints.tx_complete[8] = usb_emulation_endp7_tx_complete;
106+
usb_device_0.endpoints.tx_complete[9] = usb_emulation_endp7_tx_complete;
107+
usb_device_0.endpoints.tx_complete[10] = usb_emulation_endp7_tx_complete;
108+
usb_device_0.endpoints.tx_complete[11] = usb_emulation_endp7_tx_complete;
109+
usb_device_0.endpoints.tx_complete[12] = usb_emulation_endp7_tx_complete;
110+
usb_device_0.endpoints.tx_complete[13] = usb_emulation_endp7_tx_complete;
111+
usb_device_0.endpoints.tx_complete[14] = usb_emulation_endp7_tx_complete;
112+
usb_device_0.endpoints.tx_complete[15] = usb_emulation_endp7_tx_complete;
105113
usb_device_0.endpoints.rx_callback[0] = usb_emulation_endp0_rx_callback;
106114
usb_device_0.endpoints.rx_callback[1] = usb_emulation_endp1_rx_callback;
107115
usb_device_0.endpoints.rx_callback[2] = usb_emulation_endp2_rx_callback;
@@ -110,6 +118,14 @@ int main()
110118
usb_device_0.endpoints.rx_callback[5] = usb_emulation_endp5_rx_callback;
111119
usb_device_0.endpoints.rx_callback[6] = usb_emulation_endp6_rx_callback;
112120
usb_device_0.endpoints.rx_callback[7] = usb_emulation_endp7_rx_callback;
121+
usb_device_0.endpoints.rx_callback[8] = usb_emulation_endp7_rx_callback;
122+
usb_device_0.endpoints.rx_callback[9] = usb_emulation_endp7_rx_callback;
123+
usb_device_0.endpoints.rx_callback[10] = usb_emulation_endp7_rx_callback;
124+
usb_device_0.endpoints.rx_callback[11] = usb_emulation_endp7_rx_callback;
125+
usb_device_0.endpoints.rx_callback[12] = usb_emulation_endp7_rx_callback;
126+
usb_device_0.endpoints.rx_callback[13] = usb_emulation_endp7_rx_callback;
127+
usb_device_0.endpoints.rx_callback[14] = usb_emulation_endp7_rx_callback;
128+
usb_device_0.endpoints.rx_callback[15] = usb_emulation_endp7_rx_callback;
113129
usb_device_0.endpoints.nak_callback = usb_emulation_nak_callback;
114130

115131
usb2_user_handled.usb2_device_handle_bus_reset = usb_emulation_usb2_device_handle_bus_reset;
@@ -124,7 +140,6 @@ int main()
124140
usb_device_set_string_descriptors(&usb_device_0, NULL);
125141
// Set the USB device parameters
126142
usb2_ep0_passthrough_enabled(true);
127-
usb_device_set_endpoint_mask(&usb_device_0, ENDPOINT_1_RX | ENDPOINT_1_TX | ENDPOINT_2_RX | ENDPOINT_2_TX | ENDPOINT_3_RX | ENDPOINT_3_TX | ENDPOINT_4_RX | ENDPOINT_4_TX | ENDPOINT_5_RX | ENDPOINT_5_TX | ENDPOINT_6_RX | ENDPOINT_6_TX | ENDPOINT_7_RX | ENDPOINT_7_TX);
128143
usb_emulation_init_endpoints();
129144

130145
//=================== Finished initializing Emulation device =====================//

0 commit comments

Comments
 (0)