Skip to content

Commit 1f2109c

Browse files
committed
Add support for setting the USB speed of a Facedancer board
1 parent c19271e commit 1f2109c

File tree

8 files changed

+32
-47
lines changed

8 files changed

+32
-47
lines changed

facedancer/backends/MAXUSBApp.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ def get_version(self):
131131
return self.read_register(self.reg_revision)
132132

133133

134-
def connect(self, usb_device, max_ep0_packet_size=64):
134+
def connect(self, usb_device, max_packet_size_ep0=64, device_speed=None):
135135
if self.read_register(self.reg_usb_control) & self.usb_control_connect:
136136
self.write_register(self.reg_usb_control, self.usb_control_vbgate)
137137
time.sleep(.1)

facedancer/backends/base.py

+3-10
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,14 @@ def get_version(self):
3232
raise NotImplementedError
3333

3434

35-
def set_device_speed(self, device_speed: DeviceSpeed=DeviceSpeed.FULL):
36-
"""
37-
Sets the speed to be used when connecting the Facedancer's target port.
38-
39-
device_speed: the requested device speed.
40-
"""
41-
raise NotImplementedError
42-
43-
44-
def connect(self, usb_device: USBDevice, max_ep0_packet_size: int=64):
35+
def connect(self, usb_device: USBDevice, max_packet_size_ep0: int=64, device_speed: DeviceSpeed=DeviceSpeed.FULL):
4536
"""
4637
Prepares backend to connect to the target host and emulate
4738
a given device.
4839
4940
usb_device: The USBDevice object that represents the emulated device.
41+
max_packet_size_ep0: Max packet size for control endpoint.
42+
device_speed: Requested usb speed for the Facedancer board.
5043
"""
5144
raise NotImplementedError
5245

facedancer/backends/greatdancer.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def __init__(self, device=None, verbose=0, quirks=None):
9898
self.endpoint_stalled[i] = False
9999

100100
# Assume a max packet size of 64 until configured otherwise.
101-
self.max_ep0_packet_size = 64
101+
self.max_packet_size_ep0 = 64
102102

103103
# Start off by assuming we're not waiting for an OUT control transfer's
104104
# data stage. # See _handle_setup_complete_on_endpoint for details.
@@ -182,7 +182,7 @@ def _generate_endpoint_config_arguments(self, config):
182182
return arguments
183183

184184

185-
def connect(self, usb_device, max_ep0_packet_size=64):
185+
def connect(self, usb_device, max_packet_size_ep0=64, device_speed=DeviceSpeed.FULL):
186186
"""
187187
Prepares the GreatDancer to connect to the target host and emulate
188188
a given device.
@@ -191,7 +191,10 @@ def connect(self, usb_device, max_ep0_packet_size=64):
191191
emulated.
192192
"""
193193

194-
self.max_ep0_packet_size = max_ep0_packet_size
194+
if device_speed != DeviceSpeed.FULL:
195+
log.warn(f"GreatFET only supports USB Full Speed. Ignoring requested speed: {device_speed.name}")
196+
197+
self.max_packet_size_ep0 = max_packet_size_ep0
195198

196199
quirks = 0
197200

@@ -201,7 +204,7 @@ def connect(self, usb_device, max_ep0_packet_size=64):
201204

202205
quirks |= self.QUIRK_MANUAL_SET_ADDRESS
203206

204-
self.api.connect(self.max_ep0_packet_size, quirks)
207+
self.api.connect(self.max_packet_size_ep0, quirks)
205208
self.connected_device = usb_device
206209

207210
log.info("Connecting to host.")
@@ -545,7 +548,7 @@ def _handle_transfer_complete_on_endpoint(self, endpoint_number, direction):
545548
self.pending_control_request.data.extend(new_data)
546549

547550
all_data_received = len(self.pending_control_request.data) == self.pending_control_request.length
548-
is_short_packet = len(new_data) < self.max_ep0_packet_size
551+
is_short_packet = len(new_data) < self.max_packet_size_ep0
549552

550553
if all_data_received or is_short_packet:
551554

facedancer/backends/greathost.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ def __init__(self, verbose=0, quirks=[], autoconnect=True, device=None):
132132
self.connect()
133133

134134

135-
def connect(self):
135+
def connect(self, device_speed=None):
136136
"""
137137
Sets up our host to talk to the device, including turning on VBUS.
138138
"""

facedancer/backends/libusbhost.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def __init__(self, verbose=0, quirks=[], index=0, **kwargs):
7676
pass
7777

7878

79-
def connect(self):
79+
def connect(self, device_speed=None):
8080
"""
8181
Sets up our host to talk to the device, including turning on VBUS.
8282
"""

facedancer/backends/moondancer.py

+10-19
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def __init__(self, device: USBDevice=None, verbose: int=0, quirks: List[str]=[])
8989
self.endpoint_stalled[i] = False
9090

9191
# Assume a max packet size of 64 until configured otherwise.
92-
self.max_ep0_packet_size = 64
92+
self.max_packet_size_ep0 = 64
9393

9494
# Start off by assuming we're not waiting for an OUT control transfer's
9595
# data stage. # See handle_setup_complete_on_endpoint for details.
@@ -100,9 +100,6 @@ def __init__(self, device: USBDevice=None, verbose: int=0, quirks: List[str]=[])
100100
# for data transfer readiness.
101101
self.configuration = None
102102

103-
# By default, Cynthion's target port operates at High speed.
104-
self.device_speed = DeviceSpeed.HIGH
105-
106103
#
107104
# Store our list of quirks to handle.
108105
#
@@ -151,16 +148,7 @@ def get_version(self):
151148
raise NotImplementedError()
152149

153150

154-
def set_device_speed(self, device_speed: DeviceSpeed=DeviceSpeed.FULL):
155-
"""
156-
Sets the speed to be used when connecting Cynthion's target port.
157-
158-
device_speed: the requested device speed.
159-
"""
160-
self.device_speed = device_speed
161-
162-
163-
def connect(self, usb_device: USBDevice, max_ep0_packet_size: int=64):
151+
def connect(self, usb_device: USBDevice, max_packet_size_ep0: int=64, device_speed: DeviceSpeed=DeviceSpeed.FULL):
164152
"""
165153
Prepares Cynthion to connect to the target host and emulate
166154
a given device.
@@ -169,9 +157,12 @@ def connect(self, usb_device: USBDevice, max_ep0_packet_size: int=64):
169157
emulated.
170158
"""
171159

172-
log.debug(f"moondancer.connect(max_ep0_packet_size:{max_ep0_packet_size}, device_speed:{self.device_speed}, quirks:{self.quirks})")
160+
if device_speed not in [DeviceSpeed.FULL, DeviceSpeed.HIGH]:
161+
log.warn(f"Moondancer only supports USB Full and High Speed. Ignoring requested speed: {device_speed.name}")
162+
163+
log.debug(f"moondancer.connect(max_packet_size_ep0:{max_packet_size_ep0}, device_speed:{device_speed}, quirks:{self.quirks})")
173164

174-
self.max_ep0_packet_size = max_ep0_packet_size
165+
self.max_packet_size_ep0 = max_packet_size_ep0
175166

176167
# compute our quirk flags
177168
quirks = 0
@@ -180,13 +171,13 @@ def connect(self, usb_device: USBDevice, max_ep0_packet_size: int=64):
180171
quirks |= QuirkFlag.MANUAL_SET_ADDRESS
181172

182173
# connect to target host
183-
self.api.connect(self.max_ep0_packet_size, self.device_speed, quirks)
174+
self.api.connect(self.max_packet_size_ep0, device_speed, quirks)
184175
self.connected_device = usb_device
185176

186177
# get device name
187178
device_name = f"{type(self.connected_device).__module__}.{type(self.connected_device).__qualname__}"
188179

189-
log.info(f"Connected '{device_name}' to target host.")
180+
log.info(f"Connected {device_speed.name} speed device '{device_name}' to target host.")
190181

191182

192183
def disconnect(self):
@@ -474,7 +465,7 @@ def handle_receive_packet(self, endpoint_number: int):
474465
self.pending_control_request.data.extend(new_data)
475466

476467
all_data_received = len(self.pending_control_request.data) == self.pending_control_request.length
477-
is_short_packet = len(new_data) < self.max_ep0_packet_size
468+
is_short_packet = len(new_data) < self.max_packet_size_ep0
478469

479470
if all_data_received or is_short_packet:
480471
# Handle the completed setup request...

facedancer/device.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from .core import FacedancerUSBApp
1717
from .types import DescriptorTypes, LanguageIDs, USBStandardRequests
1818
from .types import USBDirection, USBRequestType, USBRequestRecipient
19+
from .types import DeviceSpeed
1920

2021
from .magic import instantiate_subordinates
2122

@@ -165,12 +166,12 @@ def add_configuration(self, configuration: USBConfiguration):
165166
configuration.parent = self
166167

167168

168-
def connect(self):
169+
def connect(self, device_speed: DeviceSpeed=DeviceSpeed.FULL):
169170
""" Connects this device to the host; e.g. turning on our presence-detect pull up. """
170171
if self.backend is None:
171172
self.backend = FacedancerUSBApp()
172173

173-
self.backend.connect(self, self.max_packet_size_ep0)
174+
self.backend.connect(self, max_packet_size_ep0=self.max_packet_size_ep0, device_speed=device_speed)
174175

175176

176177
def disconnect(self):
@@ -182,7 +183,8 @@ async def run(self):
182183
""" Runs the actual device emulation. """
183184

184185
# Sanity check to avoid common issues.
185-
if len(self.configurations) == 0:
186+
from .proxy import USBProxyDevice
187+
if len(self.configurations) == 0 and not isinstance(self, USBProxyDevice):
186188
log.error("No configurations defined on the emulated device! "
187189
"Did you forget @use_inner_classes_automatically?")
188190

facedancer/proxy.py

+3-7
Original file line numberDiff line numberDiff line change
@@ -311,15 +311,11 @@ def connect(self):
311311
# Since we're working at the transfer levels, the packet sizes will automatically be translated, anyway.
312312
self.max_packet_size_ep0 = 64
313313

314-
# Get the speed of the device being proxied and attempt to set it if the backend supports it.
314+
# Get the USB device speed of the device being proxied.
315315
device_speed = self.proxied_device.device_speed()
316-
try:
317-
# FIXME self.backend does not yet exist here so this will always fail
318-
self.backend.set_device_speed(device_speed)
319-
except Exception as e:
320-
log.warning(f"-- facedancer backend does not support setting device speed: {device_speed.name} --")
321316

322-
super().connect()
317+
# Connect device.
318+
super().connect(device_speed=device_speed)
323319

324320
# TODO check if we still need this in facedancer v3
325321
# skipping USB.state_attached may not be strictly correct (9.1.1.{1,2})

0 commit comments

Comments
 (0)