Skip to content

Instantly share code, notes, and snippets.

@pickeditmate
Forked from ktemkin/example_usb_tester.py
Created February 6, 2023 19:47
Show Gist options
  • Save pickeditmate/459809bd5de8c13165e729f0f8482ccd to your computer and use it in GitHub Desktop.
Save pickeditmate/459809bd5de8c13165e729f0f8482ccd to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import greatfet
from greatfet import GreatFET
from facedancer.backends.GreatDancerApp import GreatDancerApp
from facedancer.backends.GreatDancerHostApp import GreatDancerHostApp
TESTER_SERIAL_NUMBER = '0000d1c466e6380c5213'
# Note that these don't exactly line up with the data printed in the EHCI
# spec or in the LPC manual. J and K and swapped in low-speed and full speed;
# and the manual writes them from the perspective of a low-speed device. We
# use full speed constants, as that's our current operating mode.
LINE_STATE_SE0 = 0
LINE_STATE_K = 1
LINE_STATE_J = 2
LINE_STATE_SE1 = 3
# Find our DUT and tester GreatFETS.
gfs = GreatFET(find_all=True)
try:
tester_gf = [gf for gf in gfs if gf.serial_number() == TESTER_SERIAL_NUMBER][0]
dut_gf = [gf for gf in gfs if gf.serial_number() != TESTER_SERIAL_NUMBER][0]
except IndexError:
print("Could not attach to both the DUT and tester GreatFET.")
# Set up the objects we'll use to manipulate the DUT and tester GreatFETs.
dut = GreatDancerApp(device=dut_gf)
dut_host = GreatDancerHostApp(device=dut_gf)
tester = GreatDancerApp(device=tester_gf)
tester_host = GreatDancerHostApp(device=tester_gf)
#
# Simple test: we need to see each of lines in both of its logic states
# -- including an SE0 (both low), an J (D+ high, D- low) and a K (D+ low, D- high).
#
# This ensures that all of the lines are connected and working.
#
# With the DUT disconnected, we should have a SE0.
dut.disconnect()
assert(dut_host.current_line_state() == LINE_STATE_SE0)
assert(tester_host.current_line_state() == LINE_STATE_SE0)
assert(dut_host.current_device_speed() == GreatDancerHostApp.DEVICE_SPEED_NONE)
assert(tester_host.current_device_speed() == GreatDancerHostApp.DEVICE_SPEED_NONE)
# Post the DUT into device mode; this should active
# our pull-up, and force the system into an idle state.
# We should have a J state from everyone's perspectives.
dut.connect(None)
assert(dut_host.current_line_state() == LINE_STATE_J)
assert(tester_host.current_line_state() == LINE_STATE_J)
assert(dut_host.current_device_speed() == GreatDancerHostApp.DEVICE_SPEED_FULL)
assert(tester_host.current_device_speed() == GreatDancerHostApp.DEVICE_SPEED_FULL)
#
# Unforuntately, the early production devices can't use USB test mode,
# and thus can't force different bus states. Instead, we'll send the DUT some
# data and sample the data lines, and make sure we observe at least _some_ K states.
#
# Send some sample data to the device...
tester_host.connect()
tester_host.bus_reset()
tester_host.set_up_endpoint(0, GreatDancerHostApp.ENDPOINT_TYPE_CONTROL, 64, 0,
GreatDancerHostApp.DEVICE_SPEED_FULL, True, True)
tester_host.send_on_endpoint(0, b"0" * 1000, False, False)
# ... and record the values we capture.
values = { 'SE0': 0, 'J': 0, 'K': 0 }
for _ in range(10000):
values[dut_host.current_line_state(as_string=True)] += 1
# Ensure we captured some K's.
assert(values['K'] > 0)
# If we got here, in this sample script, all tests passed.
print("All tests passed!")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment