This enables to run device tests against an actual device connected to our CI. It uses https://github.com/mmahut/tpmb to enter bootloader and then it uploads a debug firmware to the device. The debug mode is the used to "click" the buttons but we might improve this and actually use the hardware buttons instead.pull/945/head
parent
bc4e8eaa16
commit
4264e87319
@ -0,0 +1,8 @@
|
||||
# Hardware tests
|
||||
|
||||
Hardware tests are device tests that run against an actual device instead of an emulator.
|
||||
This works thanks to [tpmb](https://github.com/mmahut/tpmb), which is a small arduino
|
||||
device capable of pushing an actual buttons on the device. Currently T1 is supported
|
||||
but TT might follow.
|
||||
|
||||
See `ci/test.yml` "hardware legacy device test" what exactly is run.
|
@ -0,0 +1,20 @@
|
||||
import configparser
|
||||
import sys
|
||||
|
||||
from device.t1 import TrezorOne
|
||||
|
||||
|
||||
def main(file: str = None):
|
||||
config = configparser.ConfigParser()
|
||||
config.read_file(open("hardware.cfg"))
|
||||
t1 = TrezorOne(
|
||||
config["t1"]["location"], config["t1"]["port"], config["t1"]["arduino_serial"],
|
||||
)
|
||||
t1.update_firmware(file)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
file = None
|
||||
if len(sys.argv) == 2:
|
||||
file = sys.argv[1]
|
||||
main(file)
|
@ -0,0 +1,14 @@
|
||||
with import <nixpkgs> {};
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
name = "trezor-firmware-hardware-tests";
|
||||
buildInputs = [
|
||||
uhubctl
|
||||
ffmpeg
|
||||
pipenv
|
||||
libusb1
|
||||
dejavu_fonts
|
||||
];
|
||||
LD_LIBRARY_PATH = "${libusb1}/lib";
|
||||
NIX_ENFORCE_PURITY = 0;
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
import datetime
|
||||
import os
|
||||
import time
|
||||
|
||||
import serial
|
||||
|
||||
|
||||
class Device:
|
||||
def __init__(self, uhub_location, uhub_port, arduino_serial):
|
||||
self.uhub_location = uhub_location
|
||||
self.uhub_port = uhub_port
|
||||
self.arduino_serial = arduino_serial
|
||||
self.serial = serial.Serial(arduino_serial, 9600)
|
||||
|
||||
def power_on(self):
|
||||
self.now()
|
||||
print("[hardware/usb] Turning power on...")
|
||||
os.system(
|
||||
"uhubctl -l {} -p {} -a on > /dev/null".format(
|
||||
self.uhub_location, self.uhub_port
|
||||
)
|
||||
)
|
||||
self.wait(3)
|
||||
|
||||
def power_off(self):
|
||||
self.now()
|
||||
print("[hardware/usb] Turning power off...")
|
||||
os.system(
|
||||
"uhubctl -l {} -p {} -r 100 -a off > /dev/null".format(
|
||||
self.uhub_location, self.uhub_port
|
||||
)
|
||||
)
|
||||
self.wait(3)
|
||||
|
||||
def touch(self, location, action):
|
||||
raise NotImplementedError
|
||||
|
||||
@staticmethod
|
||||
def wait(seconds):
|
||||
Device.now()
|
||||
print("[software] Waiting for {} seconds...".format(seconds))
|
||||
time.sleep(seconds)
|
||||
|
||||
@staticmethod
|
||||
def now():
|
||||
print("\n[timestamp] {}".format(datetime.datetime.now()))
|
@ -0,0 +1,47 @@
|
||||
import os
|
||||
|
||||
from .device import Device
|
||||
|
||||
|
||||
class TrezorOne(Device):
|
||||
def touch(self, location, action):
|
||||
self.now()
|
||||
print(
|
||||
"[hardware/trezor] Touching the {} button by {}...".format(location, action)
|
||||
)
|
||||
self.serial.write(("{} {}\n".format(location, action)).encode())
|
||||
|
||||
def update_firmware(self, file=None):
|
||||
if file:
|
||||
unofficial = True
|
||||
trezorctlcmd = "trezorctl firmware-update -s -f {} &".format(file)
|
||||
print("[software/trezorctl] Updating the firmware to {}...".format(file))
|
||||
else:
|
||||
unofficial = False
|
||||
trezorctlcmd = "trezorctl firmware-update &"
|
||||
print("[software/trezorctl] Updating the firmware to latest...")
|
||||
self._enter_bootloader()
|
||||
|
||||
os.system(trezorctlcmd)
|
||||
self.wait(3)
|
||||
self.touch("right", "click")
|
||||
self.wait(20)
|
||||
if unofficial:
|
||||
self.touch("right", "click")
|
||||
self.wait(10)
|
||||
self.power_off()
|
||||
self.power_on()
|
||||
if unofficial:
|
||||
self.touch("right", "click")
|
||||
self.wait(5)
|
||||
self.touch("right", "click")
|
||||
self.wait(5)
|
||||
os.system("trezorctl get-features|grep version")
|
||||
|
||||
def _enter_bootloader(self):
|
||||
self.power_off()
|
||||
self.touch("all", "press")
|
||||
self.wait(2)
|
||||
self.power_on()
|
||||
self.wait(2)
|
||||
self.touch("all", "unpress")
|
@ -0,0 +1,4 @@
|
||||
[t1]
|
||||
location = 3-1.4
|
||||
port = 3
|
||||
arduino_serial = /dev/ttyACM0
|
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
if [ $# -ne 2 ]
|
||||
then
|
||||
echo "Usage: $0 commit_id [start|stop]"
|
||||
fi
|
||||
|
||||
OUTPUTFILE=video_$1_$(date +%s).mp4
|
||||
INPUTDEVICE=/dev/video0
|
||||
|
||||
if [ "$2" == "start" ]; then
|
||||
echo "[software/video] Starting record to $OUTPUTFILE"
|
||||
ffmpeg -loglevel panic -f oss -f video4linux2 -i $INPUTDEVICE \
|
||||
-vf "drawtext=font=Dejavu Sans: \
|
||||
text='$1 | %{localtime} | %{pts}': x=(w-tw)/2: y=h-(2*lh): fontcolor=white: box=1: boxcolor=0x00000000@1: fontsize=15" $OUTPUTFILE &
|
||||
export VPID=$!
|
||||
elif [ "$2" == "stop" ]; then
|
||||
echo "[software/video] Stopping the recording of $OUTPUTFILE"
|
||||
pkill ffmpeg
|
||||
sync
|
||||
fi
|
Loading…
Reference in new issue