Categories
C/C++ Coding Embedded Linux Software

Debug Linux Input Device Hardware

The trackpad on my Lenovo IdeaPad 530s running Linux started periodically freezing. How to debug the problem?

Lenovo 530s Laptop

An add-on PCB Assembly designed for use with Arduino / ESP32.

First, which version of Linux is running?

cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.1 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.1 LTS"
VERSION_ID="18.04"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

We are running Ubuntu Linux 18.04 (Bionic Beaver).

Now lets get Linux kernel and GCC versions.

cat /proc/version
Linux version 4.15.0-213-generic (buildd@lcy02-amd64-079) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #224-Ubuntu SMP Mon Jun 19 13:30:12 UTC 2023

Or, using uname command:

uname -a
Linux ideapad-530S 4.15.0-213-generic #224-Ubuntu SMP Mon Jun 19 13:30:12 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

So we can see 64bit (x86_64) AMD architecture with Linux kernel 4.15.0-213-generic which is standard version for Bionic.

Lenovo Ideapad 530s Trackpad input device.

What we know from viewing syslog ( /var/log/syslog ) after trackpad freeze a udev device “MSFT0001:01 06CB:7F27 Touchpad” is removed and module libinput is unloaded:

Feb 1 15:07:16 ideapad-530S /usr/lib/gdm3/gdm-x-session[3206]: (II) config/udev: removing device MSFT0001:01 06CB:7F27 Touchpad
Feb 1 15:07:16 ideapad-530S /usr/lib/gdm3/gdm-x-session[3206]: (**) Option "fd" "42"
Feb 1 15:07:16 ideapad-530S /usr/lib/gdm3/gdm-x-session[3206]: (II) event14 - MSFT0001:01 06CB:7F27 Touchpad: device removed
Feb 1 15:07:16 ideapad-530S /usr/lib/gdm3/gdm-x-session[3206]: (II) UnloadModule: "libinput"

Okay, now lets find the TouchPad input device.

We can list all loaded input devices and search for “Touchpad”:

sudo cat /proc/bus/input/devices

N: Name="MSFT0001:01 06CB:7F27 Touchpad"
P: Phys=i2c-MSFT0001:01
S: Sysfs=/devices/pci0000:00/0000:00:15.0/i2c_designware.0/i2c-3/i2c-MSFT0001:01/0018:06CB:7F27.0001/input/input16
U: Uniq=
H: Handlers=mouse0 event14
B: PROP=5
B: EV=1b
B: KEY=e520 10000 0 0 0 0
B: ABS=260800000000003
B: MSC=20

Or we can use contextual grep to extract just the entry for “touchpad”

grep -iA2 touchpad /proc/bus/input/devices
N: Name="MSFT0001:01 06CB:7F27 Touchpad"
P: Phys=i2c-MSFT0001:01
S: Sysfs=/devices/pci0000:00/0000:00:15.0/i2c_designware.0/i2c-3/i2c-MSFT0001:01/0018:06CB:7F27.0001/input/input16

This gives the device name “MSFT0001:01 06CB:7F27 Touchpad” and informs it is communicating over PCI bus using i2c.

I2C is a two-wire serial communication protocol using a serial data line (SDA) and a serial clock line (SCL). The protocol supports multiple target devices on a communication bus and can also support multiple controllers that send and receive commands and data.

In an age of ubiquitous USB peripherals i2c protocol is still widely used in laptops – on my Lenovo machine it interfaces power button, keyboard and trackpad.

Human Input Device (HID) over i2c is a protocol developed by Microsoft, the specification is available here and there is some interesting background in this document.

Okay, to see if we get any data from touchpad lets cat device file descriptor to see if any binary data is transmitted when touchpad is activated:

sudo cat /dev/input/event14
袛f�9h袛f�5�袛f�6�袛f�J袛f�E袛f��袛f��袛f�袛f�袛�6�袛f

To view input device data as text we can install and use evtest – Input device event monitor and query tool. The c source code for this helpful tool is available here.

sudo apt install evtest

Device details are displayed following a list of all supported events.

sudo evtest /dev/input/event14
Input driver version is 1.0.1
Input device ID: bus 0x18 vendor 0x6cb product 0x7f27 version 0x100
Input device name: "MSFT0001:01 06CB:7F27 Touchpad"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 272 (BTN_LEFT)
Event code 325 (BTN_TOOL_FINGER)
Event code 328 (BTN_TOOL_QUINTTAP)
Event code 330 (BTN_TOUCH)
Event code 333 (BTN_TOOL_DOUBLETAP)

Event type 3 (EV_ABS)
Event code 0 (ABS_X)
Value 860
Min 0
Max 1224
Resolution 12
Event code 1 (ABS_Y)
Value 397
Min 0
Max 804
Resolution 12

Touchpad interactions are then reported:

Event: time 1721481862.564796, -------------- SYN_REPORT ------------
Event: time 1721481862.571954, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 437
Event: time 1721481862.571954, type 3 (EV_ABS), code 1 (ABS_Y), value 437
Event: time 1721481928.193073, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 0
Event: time 1721481928.193073, type 1 (EV_KEY), code 333 (BTN_TOOL_DOUBLETAP), value 0

…………………………………………………..

To restart / reload the trackpad input device we have two tasks – Xorg windowing GUI input driver and Linux kernel hardware driver.

xinput is a utility to configure and test X input devices, such as mice, keyboards, and touchpads.

Lets get a list of all input devices registered with Xorg:

xinput --list
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
↳ MSFT0001:01 06CB:7F27 Touchpad id=10 [slave pointer (2)]⎣ Virtual core keyboard id=3 [master keyboard (2)]
↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)]
↳ Power Button id=6 [slave keyboard (3)]
↳ Video Bus id=7 [slave keyboard (3)]
↳ Power Button id=8 [slave keyboard (3)]
↳ Integrated Camera: Integrated C id=9 [slave keyboard (3)]
↳ Ideapad extra buttons id=11 [slave keyboard (3)]
↳ AT Translated Set 2 keyboard id=12 [slave keyboard (3)]

We can ask xinput for device (id=10) status:

xinput --list-props 10
Device 'MSFT0001:01 06CB:7F27 Touchpad':
Device Enabled (142): 1
Coordinate Transformation Matrix (144): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000
libinput Tapping Enabled (279): 1
....
Device Node (267): "/dev/input/event7"
Device Product ID (268): 1739, 32551

Lets try restarting the x input driver using id or by device name:

xinput disable 10
xinput enable 10

xinput disable 'MSFT0001:01 06CB:7F27 Touchpad'
xinput enable 'MSFT0001:01 06CB:7F27 Touchpad'

Now lets find and restart Kernal touch input module by listing all loaded kernel modules, identifying touchpad driver:

lsmod | grep touch
hid_multitouch 24576 0
hid 122880 3 i2c_hid,hid_multitouch,hid_generic

This informs trackpad is loaded into kernel via module “hid_multitouch”. As this is open source we can take a look on git at the source code for this module.

To unload/reload the device as sudo root user:

sudo modprobe -r hid_multitouch
sudo modprobe hid_multitouch

Unfortunately, reloading module does not fix the frozen trackpad. Only a reboot gets it running again.

We could file a bug report with module developers but Ubuntu Bionic like our laptop is quite old now and so we will probably just update to latest Linux version on new hardware.

By admin

Software and Internet developer with an open source perspective interested in web, coding, data analytics & visualisation, micro-controllers, internet of things, sensor devices, networks and electronics.