Checking hardware with hwtest

This is a utility for checking hardware functionality on devices.
Currently hwtest can check the following:
* framebuffer access
* drm/kms
* camera image capture (uses ffmpeg and v4l-utils)
* input devices (uses evtest)
* Accelerometer/magnetometer/gyroscope
* Temperature sensors
* Light/Proximity sensors
$ sudo apk add hwtest
$ sudo hwtest
Category Model Path Status Value 
framebuffer DRM emulated /sys/class/graphics/fb0 working Not running 
drm - /sys/class/drm/card1-DSI-1 working 720x1440 
camera ov5640 /sys/class/video4linux/v4l-subdev0 working 320x240,640x480,1280x720 
magnetometer lis3mdl /sys/bus/iio/devices/iio:device2 working -0.06, 0.35, 0.93 gauss 
accelerometer mpu6050 /sys/bus/iio/devices/iio:device1 working 1.46, 0.17, -10.53 g 
gyroscope mpu6050 /sys/bus/iio/devices/iio:device1 working -0.05, -0.03, 0.04 rad/s 
temperature mpu6050 /sys/bus/iio/devices/iio:device1 working 37 deg C 
temperature axp813-adc /sys/bus/iio/devices/iio:device0 working 28500 deg C 
proximity stk3310 /sys/bus/iio/devices/iio:device3 working 300.8 
illuminance stk3310 /sys/bus/iio/devices/iio:device3 working 397 lux 
input generic ft5x06 (12) /dev/input/event2 working 
input 1c21800.lradc /dev/input/event1 working 
input axp20x-pek /dev/input/event0 working 
== Export and verify ==
Hwtest includes the --export and --verify option. The export option generates a file with the test results, this file can later be used with the verify option to create a diff of working hardware.
This is mainly useful for testing if a kernel still works after rebasing on a newer upstream linux version.
Running hwtest with the camera module unloaded so it fails.
$ sudo hwtest --export pinephone.ini
Category Model Path Status Value 
framebuffer DRM emulated /sys/class/graphics/fb0 working Not running 
drm - /sys/class/drm/card1-DSI-1 working 720x1440 
camera ov5640 /sys/class/video4linux/v4l-subdev0 broken 
magnetometer lis3mdl /sys/bus/iio/devices/iio:device2 working 0.01, -0.01, 1.19 gauss 
accelerometer mpu6050 /sys/bus/iio/devices/iio:device1 working 0.3, 0.12, -10.52 g 
gyroscope mpu6050 /sys/bus/iio/devices/iio:device1 working -0.04, -0.03, 0.04 rad/s 
temperature mpu6050 /sys/bus/iio/devices/iio:device1 working 32 deg C 
temperature axp813-adc /sys/bus/iio/devices/iio:device0 working 22600 deg C 
input generic ft5x06 (12) /dev/input/event1 working 
input axp20x-pek /dev/input/event0 working 
The generated ini file:
[hwtest]
export-version = 1
[framebuffer]
; /sys/class/graphics/fb0
drm emulated = True
[drm]
; /sys/class/drm/card1-dsi-1
- = True
[camera]
; /sys/class/video4linux/v4l-subdev0
ov5640 = False
[magnetometer]
; /sys/bus/iio/devices/iio:device2
lis3mdl = True
[accelerometer]
; /sys/bus/iio/devices/iio:device1
mpu6050 = True
[gyroscope]
; /sys/bus/iio/devices/iio:device1
mpu6050 = True
[temperature]
; /sys/bus/iio/devices/iio:device1
mpu6050 = True
; /sys/bus/iio/devices/iio:device0
axp813-adc = True
[input]
; /dev/input/event1
generic ft5x06 (12) = True
; /dev/input/event0
axp20x-pek = True
After fixing the camera and running hwtest with the verify option:
$ sudo hwtest --verify pinephone.ini 
Fixed hardware: 
 * ov5640 [/sys/class/video4linux/v4l-subdev0] 320x240,640x480,1280x720
==Troubleshooting==
===Installation===
hwtest (here, 0.6.0) is implicitly dependent on the minor version number of python, 3.x. 
$ apk info -a hwtest
...
hwtest-0.6.0-r4 depends on:
python3
...
hwtest-0.6.0-r4 provides:
cmd:hwtest=0.6.0-r4
py3.10:hwtest=0.6.0-r4
...
In case of a (seldom, but not unexpected) minor version upgrade to the python package (here, from 3.10 to 3.11), 
hwtest installation will succeed, but will refuse to run:
$ hwtest
Traceback (most recent call last):
 File "/usr/bin/hwtest", line 33, in <module>
 sys.exit(load_entry_point('hwtest==0.6.0', 'console_scripts', 'hwtest')())
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "/usr/bin/hwtest", line 22, in importlib_load_entry_point
 for entry_point in distribution(dist_name).entry_points
 ^^^^^^^^^^^^^^^^^^^^^^^
 File "/usr/lib/python3.11/importlib/metadata/__init__.py", line 964, in distribution
 return Distribution.from_name(distribution_name)
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "/usr/lib/python3.11/importlib/metadata/__init__.py", line 561, in from_name
 raise PackageNotFoundError(name)
importlib.metadata.PackageNotFoundError: No package metadata was found for hwtest
$ python --version
Python 3.11.0
===Usage: display (terminal) size===
hwtest text output format is hardwired for terminal sizes typical on a desktop, e.g., 80x24. On-device terminals (e.g., gnome console) may be 44x18, and problematic.
If an interactive on-device run terminates with an error such as ValueError: Sign not allowed in string format specifier, the formatter code is at fault, and must be modified.
Since hwtest is written in python, the edits are easily done on-device, per-device.
An example patch to formatter.py is given below:
formatter-smallscreen.patch
--- formatter.py.orig 2022-03-04 15:59:56.639759891 -0700
+++ formatter.py 2022-03-04 15:59:51.686426859 -0700
@@ -62,13 +62,24 @@
 def start(self):
 width, height = shutil.get_terminal_size((120, 25))
+ #print("(dbg) width, height", width, height) 
+ #phosh/kgx, portrait, moto-osprey w,h is 44,17 [similar for harpia, a3]
 self.row = "{: <16} {: <20} "
 width -= 16 + 1 + 20 + 1
+ if width < 12:
+ #print("(dbg) bad (adjusted) width (narrow screen?):", width, ", hardwiring to 20")
+ width = 20
 flexwidth = math.floor((width - 10) / 2)
+ if flexwidth < 0:
+ print("(dbg) flexwidth < 0; MUST NOT OCCUR; hardwiring to 5", flexwidth)
+ flexwidth = 5
 self.row += "{: <" + str(flexwidth) + "} "
 self.row += "{: <10} "
 self.row += "{}"
+ #print("(dbg) DEBUG: self.row", type(self.row), self.row)
+ if "-" in self.row:
+ print("(dbg) FAIL: self.row contains '-' sign, position", self.row.index("-"))
 print(self.row.format("Category", "Model", "Path", "Status", "Value"))
 def result(self, result):
Category:Guide