Commit ab396fb2 authored by Jiri Kosina's avatar Jiri Kosina

Merge branch 'for-6.4/tests' into for-linus

- import of bunch of HID selftests from out-of-tree hid-tools project
  (Benjamin Tissoires)
parents 67471b89 bf81de76
......@@ -5,6 +5,18 @@ include ../../../build/Build.include
include ../../../scripts/Makefile.arch
include ../../../scripts/Makefile.include
TEST_PROGS := hid-core.sh
TEST_PROGS += hid-apple.sh
TEST_PROGS += hid-gamepad.sh
TEST_PROGS += hid-ite.sh
TEST_PROGS += hid-keyboard.sh
TEST_PROGS += hid-mouse.sh
TEST_PROGS += hid-multitouch.sh
TEST_PROGS += hid-sony.sh
TEST_PROGS += hid-tablet.sh
TEST_PROGS += hid-usb_crash.sh
TEST_PROGS += hid-wacom.sh
CXX ?= $(CROSS_COMPILE)g++
HOSTPKG_CONFIG := pkg-config
......
......@@ -20,3 +20,14 @@ CONFIG_HID=y
CONFIG_HID_BPF=y
CONFIG_INPUT_EVDEV=y
CONFIG_UHID=y
CONFIG_LEDS_CLASS_MULTICOLOR=y
CONFIG_USB=y
CONFIG_USB_HID=y
CONFIG_HID_APPLE=y
CONFIG_HID_ITE=y
CONFIG_HID_MULTITOUCH=y
CONFIG_HID_PLAYSTATION=y
CONFIG_PLAYSTATION_FF=y
CONFIG_HID_SONY=y
CONFIG_SONY_FF=y
CONFIG_HID_WACOM=y
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Runs tests for the HID subsystem
export TARGET=test_apple_keyboard.py
bash ./run-hid-tools-tests.sh
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Runs tests for the HID subsystem
export TARGET=test_hid_core.py
bash ./run-hid-tools-tests.sh
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Runs tests for the HID subsystem
export TARGET=test_gamepad.py
bash ./run-hid-tools-tests.sh
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Runs tests for the HID subsystem
export TARGET=test_ite_keyboard.py
bash ./run-hid-tools-tests.sh
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Runs tests for the HID subsystem
export TARGET=test_keyboard.py
bash ./run-hid-tools-tests.sh
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Runs tests for the HID subsystem
export TARGET=test_mouse.py
bash ./run-hid-tools-tests.sh
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Runs tests for the HID subsystem
export TARGET=test_multitouch.py
bash ./run-hid-tools-tests.sh
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Runs tests for the HID subsystem
export TARGET=test_sony.py
bash ./run-hid-tools-tests.sh
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Runs tests for the HID subsystem
export TARGET=test_tablet.py
bash ./run-hid-tools-tests.sh
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Runs tests for the HID subsystem
export TARGET=test_usb_crash.py
bash ./run-hid-tools-tests.sh
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Runs tests for the HID subsystem
export TARGET=test_wacom_generic.py
bash ./run-hid-tools-tests.sh
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Runs tests for the HID subsystem
if ! command -v python3 > /dev/null 2>&1; then
echo "hid-tools: [SKIP] python3 not installed"
exit 77
fi
if ! python3 -c "import pytest" > /dev/null 2>&1; then
echo "hid: [SKIP/ pytest module not installed"
exit 77
fi
if ! python3 -c "import pytest_tap" > /dev/null 2>&1; then
echo "hid: [SKIP/ pytest_tap module not installed"
exit 77
fi
if ! python3 -c "import hidtools" > /dev/null 2>&1; then
echo "hid: [SKIP/ hid-tools module not installed"
exit 77
fi
TARGET=${TARGET:=.}
echo TAP version 13
python3 -u -m pytest $PYTEST_XDIST ./tests/$TARGET --tap-stream --udevd
# HID tests can be long, so give a little bit more time
# to them
timeout=200
# SPDX-License-Identifier: GPL-2.0
# Just to make sphinx-apidoc document this directory
This diff is collapsed.
#!/bin/env python3
# SPDX-License-Identifier: GPL-2.0
# -*- coding: utf-8 -*-
#
# Copyright (c) 2017 Benjamin Tissoires <benjamin.tissoires@gmail.com>
# Copyright (c) 2017 Red Hat, Inc.
import platform
import pytest
import re
import resource
import subprocess
from .base import HIDTestUdevRule
from pathlib import Path
# See the comment in HIDTestUdevRule, this doesn't set up but it will clean
# up once the last test exited.
@pytest.fixture(autouse=True, scope="session")
def udev_rules_session_setup():
with HIDTestUdevRule.instance():
yield
@pytest.fixture(autouse=True, scope="session")
def setup_rlimit():
resource.setrlimit(resource.RLIMIT_CORE, (0, 0))
@pytest.fixture(autouse=True, scope="session")
def start_udevd(pytestconfig):
if pytestconfig.getoption("udevd"):
import subprocess
with subprocess.Popen("/usr/lib/systemd/systemd-udevd") as proc:
yield
proc.kill()
else:
yield
def pytest_configure(config):
config.addinivalue_line(
"markers",
"skip_if_uhdev(condition, message): mark test to skip if the condition on the uhdev device is met",
)
# Generate the list of modules and modaliases
# for the tests that need to be parametrized with those
def pytest_generate_tests(metafunc):
if "usbVidPid" in metafunc.fixturenames:
modules = (
Path("/lib/modules/")
/ platform.uname().release
/ "kernel"
/ "drivers"
/ "hid"
)
modalias_re = re.compile(r"alias:\s+hid:b0003g.*v([0-9a-fA-F]+)p([0-9a-fA-F]+)")
params = []
ids = []
for module in modules.glob("*.ko"):
p = subprocess.run(
["modinfo", module], capture_output=True, check=True, encoding="utf-8"
)
for line in p.stdout.split("\n"):
m = modalias_re.match(line)
if m is not None:
vid, pid = m.groups()
vid = int(vid, 16)
pid = int(pid, 16)
params.append([module.name.replace(".ko", ""), vid, pid])
ids.append(f"{module.name} {vid:04x}:{pid:04x}")
metafunc.parametrize("usbVidPid", params, ids=ids)
def pytest_addoption(parser):
parser.addoption("--udevd", action="store_true", default=False)
This diff is collapsed.
This diff is collapsed.
#!/bin/env python3
# SPDX-License-Identifier: GPL-2.0
# -*- coding: utf-8 -*-
#
# Copyright (c) 2019 Benjamin Tissoires <benjamin.tissoires@gmail.com>
# Copyright (c) 2019 Red Hat, Inc.
#
from . import base
import libevdev
import pytest
from hidtools.device.base_gamepad import AsusGamepad, SaitekGamepad
import logging
logger = logging.getLogger("hidtools.test.gamepad")
class BaseTest:
class TestGamepad(base.BaseTestCase.TestUhid):
@pytest.fixture(autouse=True)
def send_initial_state(self):
"""send an empty report to initialize the axes"""
uhdev = self.uhdev
r = uhdev.event()
events = uhdev.next_sync_events()
self.debug_reports(r, uhdev, events)
def assert_button(self, button):
uhdev = self.uhdev
evdev = uhdev.get_evdev()
syn_event = self.syn_event
buttons = {}
key = libevdev.evbit(uhdev.buttons_map[button])
buttons[button] = True
r = uhdev.event(buttons=buttons)
expected_event = libevdev.InputEvent(key, 1)
events = uhdev.next_sync_events()
self.debug_reports(r, uhdev, events)
self.assertInputEventsIn((syn_event, expected_event), events)
assert evdev.value[key] == 1
buttons[button] = False
r = uhdev.event(buttons=buttons)
expected_event = libevdev.InputEvent(key, 0)
events = uhdev.next_sync_events()
self.debug_reports(r, uhdev, events)
self.assertInputEventsIn((syn_event, expected_event), events)
assert evdev.value[key] == 0
def test_buttons(self):
"""check for button reliability."""
uhdev = self.uhdev
for b in uhdev.buttons:
self.assert_button(b)
def test_dual_buttons(self):
"""check for button reliability when pressing 2 buttons"""
uhdev = self.uhdev
evdev = uhdev.get_evdev()
syn_event = self.syn_event
# can change intended b1 b2 values
b1 = uhdev.buttons[0]
key1 = libevdev.evbit(uhdev.buttons_map[b1])
b2 = uhdev.buttons[1]
key2 = libevdev.evbit(uhdev.buttons_map[b2])
buttons = {b1: True, b2: True}
r = uhdev.event(buttons=buttons)
expected_event0 = libevdev.InputEvent(key1, 1)
expected_event1 = libevdev.InputEvent(key2, 1)
events = uhdev.next_sync_events()
self.debug_reports(r, uhdev, events)
self.assertInputEventsIn(
(syn_event, expected_event0, expected_event1), events
)
assert evdev.value[key1] == 1
assert evdev.value[key2] == 1
buttons = {b1: False, b2: None}
r = uhdev.event(buttons=buttons)
expected_event = libevdev.InputEvent(key1, 0)
events = uhdev.next_sync_events()
self.debug_reports(r, uhdev, events)
self.assertInputEventsIn((syn_event, expected_event), events)
assert evdev.value[key1] == 0
assert evdev.value[key2] == 1
buttons = {b1: None, b2: False}
r = uhdev.event(buttons=buttons)
expected_event = libevdev.InputEvent(key2, 0)
events = uhdev.next_sync_events()
self.debug_reports(r, uhdev, events)
self.assertInputEventsIn((syn_event, expected_event), events)
assert evdev.value[key1] == 0
assert evdev.value[key2] == 0
def _get_libevdev_abs_events(self, which):
"""Returns which ABS_* evdev axes are expected for the given stick"""
abs_map = self.uhdev.axes_map[which]
x = abs_map["x"].evdev
y = abs_map["y"].evdev
assert x
assert y
return x, y
def _test_joystick_press(self, which, data):
uhdev = self.uhdev
libevdev_axes = self._get_libevdev_abs_events(which)
r = None
if which == "left_stick":
r = uhdev.event(left=data)
else:
r = uhdev.event(right=data)
events = uhdev.next_sync_events()
self.debug_reports(r, uhdev, events)
for i, d in enumerate(data):
if d is not None and d != 127:
assert libevdev.InputEvent(libevdev_axes[i], d) in events
else:
assert libevdev.InputEvent(libevdev_axes[i]) not in events
def test_left_joystick_press_left(self):
"""check for the left joystick reliability"""
self._test_joystick_press("left_stick", (63, None))
self._test_joystick_press("left_stick", (0, 127))
def test_left_joystick_press_right(self):
"""check for the left joystick reliability"""
self._test_joystick_press("left_stick", (191, 127))
self._test_joystick_press("left_stick", (255, None))
def test_left_joystick_press_up(self):
"""check for the left joystick reliability"""
self._test_joystick_press("left_stick", (None, 63))
self._test_joystick_press("left_stick", (127, 0))
def test_left_joystick_press_down(self):
"""check for the left joystick reliability"""
self._test_joystick_press("left_stick", (127, 191))
self._test_joystick_press("left_stick", (None, 255))
def test_right_joystick_press_left(self):
"""check for the right joystick reliability"""
self._test_joystick_press("right_stick", (63, None))
self._test_joystick_press("right_stick", (0, 127))
def test_right_joystick_press_right(self):
"""check for the right joystick reliability"""
self._test_joystick_press("right_stick", (191, 127))
self._test_joystick_press("right_stick", (255, None))
def test_right_joystick_press_up(self):
"""check for the right joystick reliability"""
self._test_joystick_press("right_stick", (None, 63))
self._test_joystick_press("right_stick", (127, 0))
def test_right_joystick_press_down(self):
"""check for the right joystick reliability"""
self._test_joystick_press("right_stick", (127, 191))
self._test_joystick_press("right_stick", (None, 255))
@pytest.mark.skip_if_uhdev(
lambda uhdev: "Hat switch" not in uhdev.fields,
"Device not compatible, missing Hat switch usage",
)
@pytest.mark.parametrize(
"hat_value,expected_evdev,evdev_value",
[
(0, "ABS_HAT0Y", -1),
(2, "ABS_HAT0X", 1),
(4, "ABS_HAT0Y", 1),
(6, "ABS_HAT0X", -1),
],
)
def test_hat_switch(self, hat_value, expected_evdev, evdev_value):
uhdev = self.uhdev
r = uhdev.event(hat_switch=hat_value)
events = uhdev.next_sync_events()
self.debug_reports(r, uhdev, events)
assert (
libevdev.InputEvent(
libevdev.evbit("EV_ABS", expected_evdev), evdev_value
)
in events
)
class TestSaitekGamepad(BaseTest.TestGamepad):
def create_device(self):
return SaitekGamepad()
class TestAsusGamepad(BaseTest.TestGamepad):
def create_device(self):
return AsusGamepad()
#!/bin/env python3
# SPDX-License-Identifier: GPL-2.0
# -*- coding: utf-8 -*-
#
# Copyright (c) 2017 Benjamin Tissoires <benjamin.tissoires@gmail.com>
# Copyright (c) 2017 Red Hat, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This is for generic devices
from . import base
import logging
logger = logging.getLogger("hidtools.test.hid")
class TestCollectionOverflow(base.BaseTestCase.TestUhid):
"""
Test class to test re-allocation of the HID collection stack in
hid-core.c.
"""
def create_device(self):
# fmt: off
report_descriptor = [
0x05, 0x01, # .Usage Page (Generic Desktop)
0x09, 0x02, # .Usage (Mouse)
0xa1, 0x01, # .Collection (Application)
0x09, 0x02, # ..Usage (Mouse)
0xa1, 0x02, # ..Collection (Logical)
0x09, 0x01, # ...Usage (Pointer)
0xa1, 0x00, # ...Collection (Physical)
0x05, 0x09, # ....Usage Page (Button)
0x19, 0x01, # ....Usage Minimum (1)
0x29, 0x03, # ....Usage Maximum (3)
0x15, 0x00, # ....Logical Minimum (0)
0x25, 0x01, # ....Logical Maximum (1)
0x75, 0x01, # ....Report Size (1)
0x95, 0x03, # ....Report Count (3)
0x81, 0x02, # ....Input (Data,Var,Abs)
0x75, 0x05, # ....Report Size (5)
0x95, 0x01, # ....Report Count (1)
0x81, 0x03, # ....Input (Cnst,Var,Abs)
0xa1, 0x02, # ....Collection (Logical)
0x09, 0x01, # .....Usage (Pointer)
0xa1, 0x02, # ....Collection (Logical)
0x09, 0x01, # .....Usage (Pointer)
0xa1, 0x02, # ....Collection (Logical)
0x09, 0x01, # .....Usage (Pointer)
0xa1, 0x02, # ....Collection (Logical)
0x09, 0x01, # .....Usage (Pointer)
0xa1, 0x02, # ....Collection (Logical)
0x09, 0x01, # .....Usage (Pointer)
0xa1, 0x02, # ....Collection (Logical)
0x09, 0x01, # .....Usage (Pointer)
0xa1, 0x02, # ....Collection (Logical)
0x09, 0x01, # .....Usage (Pointer)
0xa1, 0x02, # ....Collection (Logical)
0x09, 0x01, # .....Usage (Pointer)
0xa1, 0x02, # ....Collection (Logical)
0x09, 0x01, # .....Usage (Pointer)
0xa1, 0x02, # ....Collection (Logical)
0x09, 0x01, # .....Usage (Pointer)
0xa1, 0x02, # ....Collection (Logical)
0x09, 0x01, # .....Usage (Pointer)
0xa1, 0x02, # ....Collection (Logical)
0x09, 0x01, # .....Usage (Pointer)
0xa1, 0x02, # ....Collection (Logical)
0x09, 0x01, # .....Usage (Pointer)
0xa1, 0x02, # ....Collection (Logical)
0x09, 0x01, # .....Usage (Pointer)
0xa1, 0x02, # ....Collection (Logical)
0x09, 0x01, # .....Usage (Pointer)
0xa1, 0x02, # ....Collection (Logical)
0x09, 0x01, # .....Usage (Pointer)
0xa1, 0x02, # ....Collection (Logical)
0x09, 0x01, # .....Usage (Pointer)
0x05, 0x01, # .....Usage Page (Generic Desktop)
0x09, 0x30, # .....Usage (X)
0x09, 0x31, # .....Usage (Y)
0x15, 0x81, # .....Logical Minimum (-127)
0x25, 0x7f, # .....Logical Maximum (127)
0x75, 0x08, # .....Report Size (8)
0x95, 0x02, # .....Report Count (2)
0x81, 0x06, # .....Input (Data,Var,Rel)
0xa1, 0x02, # ...Collection (Logical)
0x85, 0x12, # ....Report ID (18)
0x09, 0x48, # ....Usage (Resolution Multiplier)
0x95, 0x01, # ....Report Count (1)
0x75, 0x02, # ....Report Size (2)
0x15, 0x00, # ....Logical Minimum (0)
0x25, 0x01, # ....Logical Maximum (1)
0x35, 0x01, # ....Physical Minimum (1)
0x45, 0x0c, # ....Physical Maximum (12)
0xb1, 0x02, # ....Feature (Data,Var,Abs)
0x85, 0x1a, # ....Report ID (26)
0x09, 0x38, # ....Usage (Wheel)
0x35, 0x00, # ....Physical Minimum (0)
0x45, 0x00, # ....Physical Maximum (0)
0x95, 0x01, # ....Report Count (1)
0x75, 0x10, # ....Report Size (16)
0x16, 0x01, 0x80, # ....Logical Minimum (-32767)
0x26, 0xff, 0x7f, # ....Logical Maximum (32767)
0x81, 0x06, # ....Input (Data,Var,Rel)
0xc0, # ...End Collection
0xc0, # ...End Collection
0xc0, # ...End Collection
0xc0, # ...End Collection
0xc0, # ...End Collection
0xc0, # ...End Collection
0xc0, # ...End Collection
0xc0, # ...End Collection
0xc0, # ...End Collection
0xc0, # ...End Collection
0xc0, # ...End Collection
0xc0, # ...End Collection
0xc0, # ...End Collection
0xc0, # ...End Collection
0xc0, # ...End Collection
0xc0, # ...End Collection
0xc0, # ...End Collection
0xc0, # ...End Collection
0xc0, # ...End Collection
0xc0, # ..End Collection
0xc0, # .End Collection
]
# fmt: on
return base.UHIDTestDevice(
name=None, rdesc=report_descriptor, application="Mouse"
)
def test_rdesc(self):
"""
This test can only check for negatives. If the kernel crashes, you
know why. If this test passes, either the bug isn't present or just
didn't get triggered. No way to know.
For an explanation, see kernel patch
HID: core: replace the collection tree pointers with indices
"""
pass
#!/bin/env python3
# SPDX-License-Identifier: GPL-2.0
# -*- coding: utf-8 -*-
#
# Copyright (c) 2020 Benjamin Tissoires <benjamin.tissoires@gmail.com>
# Copyright (c) 2020 Red Hat, Inc.
#
from .test_keyboard import ArrayKeyboard, TestArrayKeyboard
from hidtools.util import BusType
import libevdev
import logging
logger = logging.getLogger("hidtools.test.ite-keyboard")
KERNEL_MODULE = ("itetech", "hid_ite")
class KbdData(object):
pass
# The ITE keyboards have an issue regarding the Wifi key:
# nothing comes in when pressing the key, but we get a null
# event on the key release.
# This test covers this case.
class ITEKeyboard(ArrayKeyboard):
# fmt: off
report_descriptor = [
0x06, 0x85, 0xff, # Usage Page (Vendor Usage Page 0xff85)
0x09, 0x95, # Usage (Vendor Usage 0x95) 3
0xa1, 0x01, # Collection (Application) 5
0x85, 0x5a, # .Report ID (90) 7
0x09, 0x01, # .Usage (Vendor Usage 0x01) 9
0x15, 0x00, # .Logical Minimum (0) 11
0x26, 0xff, 0x00, # .Logical Maximum (255) 13
0x75, 0x08, # .Report Size (8) 16
0x95, 0x10, # .Report Count (16) 18
0xb1, 0x00, # .Feature (Data,Arr,Abs) 20
0xc0, # End Collection 22
0x05, 0x01, # Usage Page (Generic Desktop) 23
0x09, 0x06, # Usage (Keyboard) 25
0xa1, 0x01, # Collection (Application) 27
0x85, 0x01, # .Report ID (1) 29
0x75, 0x01, # .Report Size (1) 31
0x95, 0x08, # .Report Count (8) 33
0x05, 0x07, # .Usage Page (Keyboard) 35
0x19, 0xe0, # .Usage Minimum (224) 37
0x29, 0xe7, # .Usage Maximum (231) 39
0x15, 0x00, # .Logical Minimum (0) 41
0x25, 0x01, # .Logical Maximum (1) 43
0x81, 0x02, # .Input (Data,Var,Abs) 45
0x95, 0x01, # .Report Count (1) 47
0x75, 0x08, # .Report Size (8) 49
0x81, 0x03, # .Input (Cnst,Var,Abs) 51
0x95, 0x05, # .Report Count (5) 53
0x75, 0x01, # .Report Size (1) 55
0x05, 0x08, # .Usage Page (LEDs) 57
0x19, 0x01, # .Usage Minimum (1) 59
0x29, 0x05, # .Usage Maximum (5) 61
0x91, 0x02, # .Output (Data,Var,Abs) 63
0x95, 0x01, # .Report Count (1) 65
0x75, 0x03, # .Report Size (3) 67
0x91, 0x03, # .Output (Cnst,Var,Abs) 69
0x95, 0x06, # .Report Count (6) 71
0x75, 0x08, # .Report Size (8) 73
0x15, 0x00, # .Logical Minimum (0) 75
0x26, 0xff, 0x00, # .Logical Maximum (255) 77
0x05, 0x07, # .Usage Page (Keyboard) 80
0x19, 0x00, # .Usage Minimum (0) 82
0x2a, 0xff, 0x00, # .Usage Maximum (255) 84
0x81, 0x00, # .Input (Data,Arr,Abs) 87
0xc0, # End Collection 89
0x05, 0x0c, # Usage Page (Consumer Devices) 90
0x09, 0x01, # Usage (Consumer Control) 92
0xa1, 0x01, # Collection (Application) 94
0x85, 0x02, # .Report ID (2) 96
0x19, 0x00, # .Usage Minimum (0) 98
0x2a, 0x3c, 0x02, # .Usage Maximum (572) 100
0x15, 0x00, # .Logical Minimum (0) 103
0x26, 0x3c, 0x02, # .Logical Maximum (572) 105
0x75, 0x10, # .Report Size (16) 108
0x95, 0x01, # .Report Count (1) 110
0x81, 0x00, # .Input (Data,Arr,Abs) 112
0xc0, # End Collection 114
0x05, 0x01, # Usage Page (Generic Desktop) 115
0x09, 0x0c, # Usage (Wireless Radio Controls) 117
0xa1, 0x01, # Collection (Application) 119
0x85, 0x03, # .Report ID (3) 121
0x15, 0x00, # .Logical Minimum (0) 123
0x25, 0x01, # .Logical Maximum (1) 125
0x09, 0xc6, # .Usage (Wireless Radio Button) 127
0x95, 0x01, # .Report Count (1) 129
0x75, 0x01, # .Report Size (1) 131
0x81, 0x06, # .Input (Data,Var,Rel) 133
0x75, 0x07, # .Report Size (7) 135
0x81, 0x03, # .Input (Cnst,Var,Abs) 137
0xc0, # End Collection 139
0x05, 0x88, # Usage Page (Vendor Usage Page 0x88) 140
0x09, 0x01, # Usage (Vendor Usage 0x01) 142
0xa1, 0x01, # Collection (Application) 144
0x85, 0x04, # .Report ID (4) 146
0x19, 0x00, # .Usage Minimum (0) 148
0x2a, 0xff, 0xff, # .Usage Maximum (65535) 150
0x15, 0x00, # .Logical Minimum (0) 153
0x26, 0xff, 0xff, # .Logical Maximum (65535) 155
0x75, 0x08, # .Report Size (8) 158
0x95, 0x02, # .Report Count (2) 160
0x81, 0x02, # .Input (Data,Var,Abs) 162
0xc0, # End Collection 164
0x05, 0x01, # Usage Page (Generic Desktop) 165
0x09, 0x80, # Usage (System Control) 167
0xa1, 0x01, # Collection (Application) 169
0x85, 0x05, # .Report ID (5) 171
0x19, 0x81, # .Usage Minimum (129) 173
0x29, 0x83, # .Usage Maximum (131) 175
0x15, 0x00, # .Logical Minimum (0) 177
0x25, 0x01, # .Logical Maximum (1) 179
0x95, 0x08, # .Report Count (8) 181
0x75, 0x01, # .Report Size (1) 183
0x81, 0x02, # .Input (Data,Var,Abs) 185
0xc0, # End Collection 187
]
# fmt: on
def __init__(
self,
rdesc=report_descriptor,
name=None,
input_info=(BusType.USB, 0x06CB, 0x2968),
):
super().__init__(rdesc, name, input_info)
def event(self, keys, reportID=None, application=None):
application = application or "Keyboard"
return super().event(keys, reportID, application)
class TestITEKeyboard(TestArrayKeyboard):
kernel_modules = [KERNEL_MODULE]
def create_device(self):
return ITEKeyboard()
def test_wifi_key(self):
uhdev = self.uhdev
syn_event = self.syn_event
# the following sends a 'release' event on the Wifi key.
# the kernel is supposed to translate this into Wifi key
# down and up
r = [0x03, 0x00]
uhdev.call_input_event(r)
expected = [syn_event]
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_RFKILL, 1))
events = uhdev.next_sync_events()
self.debug_reports([r], uhdev, events)
self.assertInputEventsIn(expected, events)
expected = [syn_event]
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_RFKILL, 0))
# the kernel sends the two down/up key events in a batch, no need to
# call events = uhdev.next_sync_events()
self.debug_reports([], uhdev, events)
self.assertInputEventsIn(expected, events)
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#!/bin/env python3
# SPDX-License-Identifier: GPL-2.0
# -*- coding: utf-8 -*-
#
# Copyright (c) 2021 Benjamin Tissoires <benjamin.tissoires@gmail.com>
# Copyright (c) 2021 Red Hat, Inc.
#
# This is to ensure we don't crash when emulating USB devices
from . import base
import pytest
import logging
logger = logging.getLogger("hidtools.test.usb")
class USBDev(base.UHIDTestDevice):
# fmt: off
report_descriptor = [
0x05, 0x01, # .Usage Page (Generic Desktop) 0
0x09, 0x02, # .Usage (Mouse) 2
0xa1, 0x01, # .Collection (Application) 4
0x09, 0x02, # ..Usage (Mouse) 6
0xa1, 0x02, # ..Collection (Logical) 8
0x09, 0x01, # ...Usage (Pointer) 10
0xa1, 0x00, # ...Collection (Physical) 12
0x05, 0x09, # ....Usage Page (Button) 14
0x19, 0x01, # ....Usage Minimum (1) 16
0x29, 0x03, # ....Usage Maximum (3) 18
0x15, 0x00, # ....Logical Minimum (0) 20
0x25, 0x01, # ....Logical Maximum (1) 22
0x75, 0x01, # ....Report Size (1) 24
0x95, 0x03, # ....Report Count (3) 26
0x81, 0x02, # ....Input (Data,Var,Abs) 28
0x75, 0x05, # ....Report Size (5) 30
0x95, 0x01, # ....Report Count (1) 32
0x81, 0x03, # ....Input (Cnst,Var,Abs) 34
0x05, 0x01, # ....Usage Page (Generic Desktop) 36
0x09, 0x30, # ....Usage (X) 38
0x09, 0x31, # ....Usage (Y) 40
0x15, 0x81, # ....Logical Minimum (-127) 42
0x25, 0x7f, # ....Logical Maximum (127) 44
0x75, 0x08, # ....Report Size (8) 46
0x95, 0x02, # ....Report Count (2) 48
0x81, 0x06, # ....Input (Data,Var,Rel) 50
0xc0, # ...End Collection 52
0xc0, # ..End Collection 53
0xc0, # .End Collection 54
]
# fmt: on
def __init__(self, name=None, input_info=None):
super().__init__(
name, "Mouse", input_info=input_info, rdesc=USBDev.report_descriptor
)
# skip witing for udev events, it's likely that the report
# descriptor is wrong
def is_ready(self):
return True
# we don't have an evdev node here, so paper over
# the checks
def get_evdev(self, application=None):
return "OK"
class TestUSBDevice(base.BaseTestCase.TestUhid):
"""
Test class to test if an emulated USB device crashes
the kernel.
"""
# conftest.py is generating the following fixture:
#
# @pytest.fixture(params=[('modulename', 1, 2)])
# def usbVidPid(self, request):
# return request.param
@pytest.fixture()
def new_uhdev(self, usbVidPid, request):
self.module, self.vid, self.pid = usbVidPid
self._load_kernel_module(None, self.module)
return USBDev(input_info=(3, self.vid, self.pid))
def test_creation(self):
"""
inject the USB dev through uhid and immediately see if there is a crash:
uhid can create a USB device with the BUS_USB bus, and some
drivers assume that they can then access USB related structures
when they are actually provided a uhid device. This leads to
a crash because those access result in a segmentation fault.
The kernel should not crash on any (random) user space correct
use of its API. So run through all available modules and declared
devices to see if we can generate a uhid device without a crash.
The test is empty as the fixture `check_taint` is doing the job (and
honestly, when the kernel crashes, the whole machine freezes).
"""
assert True
This diff is collapsed.
......@@ -16,7 +16,6 @@ x86_64)
exit 1
;;
esac
DEFAULT_COMMAND="./hid_bpf"
SCRIPT_DIR="$(dirname $(realpath $0))"
OUTPUT_DIR="$SCRIPT_DIR/results"
KCONFIG_REL_PATHS=("${SCRIPT_DIR}/config" "${SCRIPT_DIR}/config.common" "${SCRIPT_DIR}/config.${ARCH}")
......@@ -25,7 +24,10 @@ NUM_COMPILE_JOBS="$(nproc)"
LOG_FILE_BASE="$(date +"hid_selftests.%Y-%m-%d_%H-%M-%S")"
LOG_FILE="${LOG_FILE_BASE}.log"
EXIT_STATUS_FILE="${LOG_FILE_BASE}.exit_status"
CONTAINER_IMAGE="registry.fedoraproject.org/fedora:36"
CONTAINER_IMAGE="registry.freedesktop.org/libevdev/hid-tools/fedora/37:2023-02-17.1"
TARGETS="${TARGETS:=$(basename ${SCRIPT_DIR})}"
DEFAULT_COMMAND="pip3 install hid-tools; make -C tools/testing/selftests TARGETS=${TARGETS} run_tests"
usage()
{
......@@ -33,9 +35,9 @@ usage()
Usage: $0 [-i] [-s] [-d <output_dir>] -- [<command>]
<command> is the command you would normally run when you are in
tools/testing/selftests/bpf. e.g:
the source kernel direcory. e.g:
$0 -- ./hid_bpf
$0 -- ./tools/testing/selftests/hid/hid_bpf
If no command is specified and a debug shell (-s) is not requested,
"${DEFAULT_COMMAND}" will be run by default.
......@@ -43,11 +45,11 @@ If no command is specified and a debug shell (-s) is not requested,
If you build your kernel using KBUILD_OUTPUT= or O= options, these
can be passed as environment variables to the script:
O=<kernel_build_path> $0 -- ./hid_bpf
O=<kernel_build_path> $0 -- ./tools/testing/selftests/hid/hid_bpf
or
KBUILD_OUTPUT=<kernel_build_path> $0 -- ./hid_bpf
KBUILD_OUTPUT=<kernel_build_path> $0 -- ./tools/testing/selftests/hid/hid_bpf
Options:
......@@ -91,11 +93,14 @@ update_selftests()
run_vm()
{
local b2c="$1"
local kernel_bzimage="$2"
local command="$3"
local run_dir="$1"
local b2c="$2"
local kernel_bzimage="$3"
local command="$4"
local post_command=""
cd "${run_dir}"
if ! which "${QEMU_BINARY}" &> /dev/null; then
cat <<EOF
Could not find ${QEMU_BINARY}
......@@ -273,7 +278,7 @@ main()
fi
update_selftests "${kernel_checkout}" "${make_command}"
run_vm $b2c "${kernel_bzimage}" "${command}"
run_vm "${kernel_checkout}" $b2c "${kernel_bzimage}" "${command}"
if [[ "${debug_shell}" != "yes" ]]; then
echo "Logs saved in ${OUTPUT_DIR}/${LOG_FILE}"
fi
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment