mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-14 12:37:32 +00:00
selftests: hid: import hid-tools hid-keyboards tests
These tests have been developed in the hid-tools[0] tree for a while. Now that we have a proper selftests/hid kernel entry and that the tests are more reliable, it is time to directly include those in the kernel tree. [0] https://gitlab.freedesktop.org/libevdev/hid-tools Cc: Nicolas Saenz Julienne <nsaenzjulienne@suse.de> Cc: Peter Hutterer <peter.hutterer@who-t.net> Cc: Roderick Colenbrander <roderick.colenbrander@sony.com> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Roderick Colenbrander <roderick.colenbrander@sony.com> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
This commit is contained in:
parent
8837469ac4
commit
b2c4944e16
3 changed files with 493 additions and 0 deletions
|
@ -7,6 +7,7 @@ include ../../../scripts/Makefile.include
|
|||
|
||||
TEST_PROGS := hid-core.sh
|
||||
TEST_PROGS += hid-gamepad.sh
|
||||
TEST_PROGS += hid-keyboard.sh
|
||||
|
||||
CXX ?= $(CROSS_COMPILE)g++
|
||||
|
||||
|
|
7
tools/testing/selftests/hid/hid-keyboard.sh
Executable file
7
tools/testing/selftests/hid/hid-keyboard.sh
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/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
|
485
tools/testing/selftests/hid/tests/test_keyboard.py
Normal file
485
tools/testing/selftests/hid/tests/test_keyboard.py
Normal file
|
@ -0,0 +1,485 @@
|
|||
#!/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2018 Benjamin Tissoires <benjamin.tissoires@gmail.com>
|
||||
# Copyright (c) 2018 Red Hat, Inc.
|
||||
#
|
||||
|
||||
from . import base
|
||||
import hidtools.hid
|
||||
import libevdev
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger("hidtools.test.keyboard")
|
||||
|
||||
|
||||
class InvalidHIDCommunication(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class KeyboardData(object):
|
||||
pass
|
||||
|
||||
|
||||
class BaseKeyboard(base.UHIDTestDevice):
|
||||
def __init__(self, rdesc, name=None, input_info=None):
|
||||
assert rdesc is not None
|
||||
super().__init__(name, "Key", input_info=input_info, rdesc=rdesc)
|
||||
self.keystates = {}
|
||||
|
||||
def _update_key_state(self, keys):
|
||||
"""
|
||||
Update the internal state of keys with the new state given.
|
||||
|
||||
:param key: a tuple of chars for the currently pressed keys.
|
||||
"""
|
||||
# First remove the already released keys
|
||||
unused_keys = [k for k, v in self.keystates.items() if not v]
|
||||
for key in unused_keys:
|
||||
del self.keystates[key]
|
||||
|
||||
# self.keystates contains now the list of currently pressed keys,
|
||||
# release them...
|
||||
for key in self.keystates.keys():
|
||||
self.keystates[key] = False
|
||||
|
||||
# ...and press those that are in parameter
|
||||
for key in keys:
|
||||
self.keystates[key] = True
|
||||
|
||||
def _create_report_data(self):
|
||||
keyboard = KeyboardData()
|
||||
for key, value in self.keystates.items():
|
||||
key = key.replace(" ", "").lower()
|
||||
setattr(keyboard, key, value)
|
||||
return keyboard
|
||||
|
||||
def create_array_report(self, keys, reportID=None, application=None):
|
||||
"""
|
||||
Return an input report for this device.
|
||||
|
||||
:param keys: a tuple of chars for the pressed keys. The class maintains
|
||||
the list of currently pressed keys, so to release a key, the caller
|
||||
needs to call again this function without the key in this tuple.
|
||||
:param reportID: the numeric report ID for this report, if needed
|
||||
"""
|
||||
self._update_key_state(keys)
|
||||
reportID = reportID or self.default_reportID
|
||||
|
||||
keyboard = self._create_report_data()
|
||||
return self.create_report(keyboard, reportID=reportID, application=application)
|
||||
|
||||
def event(self, keys, reportID=None, application=None):
|
||||
"""
|
||||
Send an input event on the default report ID.
|
||||
|
||||
:param keys: a tuple of chars for the pressed keys. The class maintains
|
||||
the list of currently pressed keys, so to release a key, the caller
|
||||
needs to call again this function without the key in this tuple.
|
||||
"""
|
||||
r = self.create_array_report(keys, reportID, application)
|
||||
self.call_input_event(r)
|
||||
return [r]
|
||||
|
||||
|
||||
class PlainKeyboard(BaseKeyboard):
|
||||
# fmt: off
|
||||
report_descriptor = [
|
||||
0x05, 0x01, # Usage Page (Generic Desktop)
|
||||
0x09, 0x06, # Usage (Keyboard)
|
||||
0xa1, 0x01, # Collection (Application)
|
||||
0x85, 0x01, # .Report ID (1)
|
||||
0x05, 0x07, # .Usage Page (Keyboard)
|
||||
0x19, 0xe0, # .Usage Minimum (224)
|
||||
0x29, 0xe7, # .Usage Maximum (231)
|
||||
0x15, 0x00, # .Logical Minimum (0)
|
||||
0x25, 0x01, # .Logical Maximum (1)
|
||||
0x75, 0x01, # .Report Size (1)
|
||||
0x95, 0x08, # .Report Count (8)
|
||||
0x81, 0x02, # .Input (Data,Var,Abs)
|
||||
0x19, 0x00, # .Usage Minimum (0)
|
||||
0x29, 0x97, # .Usage Maximum (151)
|
||||
0x15, 0x00, # .Logical Minimum (0)
|
||||
0x25, 0x01, # .Logical Maximum (1)
|
||||
0x75, 0x01, # .Report Size (1)
|
||||
0x95, 0x98, # .Report Count (152)
|
||||
0x81, 0x02, # .Input (Data,Var,Abs)
|
||||
0xc0, # End Collection
|
||||
]
|
||||
# fmt: on
|
||||
|
||||
def __init__(self, rdesc=report_descriptor, name=None, input_info=None):
|
||||
super().__init__(rdesc, name, input_info)
|
||||
self.default_reportID = 1
|
||||
|
||||
|
||||
class ArrayKeyboard(BaseKeyboard):
|
||||
# fmt: off
|
||||
report_descriptor = [
|
||||
0x05, 0x01, # Usage Page (Generic Desktop)
|
||||
0x09, 0x06, # Usage (Keyboard)
|
||||
0xa1, 0x01, # Collection (Application)
|
||||
0x05, 0x07, # .Usage Page (Keyboard)
|
||||
0x19, 0xe0, # .Usage Minimum (224)
|
||||
0x29, 0xe7, # .Usage Maximum (231)
|
||||
0x15, 0x00, # .Logical Minimum (0)
|
||||
0x25, 0x01, # .Logical Maximum (1)
|
||||
0x75, 0x01, # .Report Size (1)
|
||||
0x95, 0x08, # .Report Count (8)
|
||||
0x81, 0x02, # .Input (Data,Var,Abs)
|
||||
0x95, 0x06, # .Report Count (6)
|
||||
0x75, 0x08, # .Report Size (8)
|
||||
0x15, 0x00, # .Logical Minimum (0)
|
||||
0x26, 0xa4, 0x00, # .Logical Maximum (164)
|
||||
0x05, 0x07, # .Usage Page (Keyboard)
|
||||
0x19, 0x00, # .Usage Minimum (0)
|
||||
0x29, 0xa4, # .Usage Maximum (164)
|
||||
0x81, 0x00, # .Input (Data,Arr,Abs)
|
||||
0xc0, # End Collection
|
||||
]
|
||||
# fmt: on
|
||||
|
||||
def __init__(self, rdesc=report_descriptor, name=None, input_info=None):
|
||||
super().__init__(rdesc, name, input_info)
|
||||
|
||||
def _create_report_data(self):
|
||||
data = KeyboardData()
|
||||
array = []
|
||||
|
||||
hut = hidtools.hut.HUT
|
||||
|
||||
# strip modifiers from the array
|
||||
for k, v in self.keystates.items():
|
||||
# we ignore depressed keys
|
||||
if not v:
|
||||
continue
|
||||
|
||||
usage = hut[0x07].from_name[k].usage
|
||||
if usage >= 224 and usage <= 231:
|
||||
# modifier
|
||||
setattr(data, k.lower(), 1)
|
||||
else:
|
||||
array.append(k)
|
||||
|
||||
# if array length is bigger than 6, report ErrorRollOver
|
||||
if len(array) > 6:
|
||||
array = ["ErrorRollOver"] * 6
|
||||
|
||||
data.keyboard = array
|
||||
return data
|
||||
|
||||
|
||||
class LEDKeyboard(ArrayKeyboard):
|
||||
# fmt: off
|
||||
report_descriptor = [
|
||||
0x05, 0x01, # Usage Page (Generic Desktop)
|
||||
0x09, 0x06, # Usage (Keyboard)
|
||||
0xa1, 0x01, # Collection (Application)
|
||||
0x05, 0x07, # .Usage Page (Keyboard)
|
||||
0x19, 0xe0, # .Usage Minimum (224)
|
||||
0x29, 0xe7, # .Usage Maximum (231)
|
||||
0x15, 0x00, # .Logical Minimum (0)
|
||||
0x25, 0x01, # .Logical Maximum (1)
|
||||
0x75, 0x01, # .Report Size (1)
|
||||
0x95, 0x08, # .Report Count (8)
|
||||
0x81, 0x02, # .Input (Data,Var,Abs)
|
||||
0x95, 0x01, # .Report Count (1)
|
||||
0x75, 0x08, # .Report Size (8)
|
||||
0x81, 0x01, # .Input (Cnst,Arr,Abs)
|
||||
0x95, 0x05, # .Report Count (5)
|
||||
0x75, 0x01, # .Report Size (1)
|
||||
0x05, 0x08, # .Usage Page (LEDs)
|
||||
0x19, 0x01, # .Usage Minimum (1)
|
||||
0x29, 0x05, # .Usage Maximum (5)
|
||||
0x91, 0x02, # .Output (Data,Var,Abs)
|
||||
0x95, 0x01, # .Report Count (1)
|
||||
0x75, 0x03, # .Report Size (3)
|
||||
0x91, 0x01, # .Output (Cnst,Arr,Abs)
|
||||
0x95, 0x06, # .Report Count (6)
|
||||
0x75, 0x08, # .Report Size (8)
|
||||
0x15, 0x00, # .Logical Minimum (0)
|
||||
0x26, 0xa4, 0x00, # .Logical Maximum (164)
|
||||
0x05, 0x07, # .Usage Page (Keyboard)
|
||||
0x19, 0x00, # .Usage Minimum (0)
|
||||
0x29, 0xa4, # .Usage Maximum (164)
|
||||
0x81, 0x00, # .Input (Data,Arr,Abs)
|
||||
0xc0, # End Collection
|
||||
]
|
||||
# fmt: on
|
||||
|
||||
def __init__(self, rdesc=report_descriptor, name=None, input_info=None):
|
||||
super().__init__(rdesc, name, input_info)
|
||||
|
||||
|
||||
# Some Primax manufactured keyboards set the Usage Page after having defined
|
||||
# some local Usages. It relies on the fact that the specification states that
|
||||
# Usages are to be concatenated with Usage Pages upon finding a Main item (see
|
||||
# 6.2.2.8). This test covers this case.
|
||||
class PrimaxKeyboard(ArrayKeyboard):
|
||||
# fmt: off
|
||||
report_descriptor = [
|
||||
0x05, 0x01, # Usage Page (Generic Desktop)
|
||||
0x09, 0x06, # Usage (Keyboard)
|
||||
0xA1, 0x01, # Collection (Application)
|
||||
0x05, 0x07, # .Usage Page (Keyboard)
|
||||
0x19, 0xE0, # .Usage Minimum (224)
|
||||
0x29, 0xE7, # .Usage Maximum (231)
|
||||
0x15, 0x00, # .Logical Minimum (0)
|
||||
0x25, 0x01, # .Logical Maximum (1)
|
||||
0x75, 0x01, # .Report Size (1)
|
||||
0x95, 0x08, # .Report Count (8)
|
||||
0x81, 0x02, # .Input (Data,Var,Abs)
|
||||
0x75, 0x08, # .Report Size (8)
|
||||
0x95, 0x01, # .Report Count (1)
|
||||
0x81, 0x01, # .Input (Data,Var,Abs)
|
||||
0x05, 0x08, # .Usage Page (LEDs)
|
||||
0x19, 0x01, # .Usage Minimum (1)
|
||||
0x29, 0x03, # .Usage Maximum (3)
|
||||
0x75, 0x01, # .Report Size (1)
|
||||
0x95, 0x03, # .Report Count (3)
|
||||
0x91, 0x02, # .Output (Data,Var,Abs)
|
||||
0x95, 0x01, # .Report Count (1)
|
||||
0x75, 0x05, # .Report Size (5)
|
||||
0x91, 0x01, # .Output (Constant)
|
||||
0x15, 0x00, # .Logical Minimum (0)
|
||||
0x26, 0xFF, 0x00, # .Logical Maximum (255)
|
||||
0x19, 0x00, # .Usage Minimum (0)
|
||||
0x2A, 0xFF, 0x00, # .Usage Maximum (255)
|
||||
0x05, 0x07, # .Usage Page (Keyboard)
|
||||
0x75, 0x08, # .Report Size (8)
|
||||
0x95, 0x06, # .Report Count (6)
|
||||
0x81, 0x00, # .Input (Data,Arr,Abs)
|
||||
0xC0, # End Collection
|
||||
]
|
||||
# fmt: on
|
||||
|
||||
def __init__(self, rdesc=report_descriptor, name=None, input_info=None):
|
||||
super().__init__(rdesc, name, input_info)
|
||||
|
||||
|
||||
class BaseTest:
|
||||
class TestKeyboard(base.BaseTestCase.TestUhid):
|
||||
def test_single_key(self):
|
||||
"""check for key reliability."""
|
||||
uhdev = self.uhdev
|
||||
evdev = uhdev.get_evdev()
|
||||
syn_event = self.syn_event
|
||||
|
||||
r = uhdev.event(["a and A"])
|
||||
expected = [syn_event]
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_A, 1))
|
||||
events = uhdev.next_sync_events()
|
||||
self.debug_reports(r, uhdev, events)
|
||||
self.assertInputEventsIn(expected, events)
|
||||
assert evdev.value[libevdev.EV_KEY.KEY_A] == 1
|
||||
|
||||
r = uhdev.event([])
|
||||
expected = [syn_event]
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_A, 0))
|
||||
events = uhdev.next_sync_events()
|
||||
self.debug_reports(r, uhdev, events)
|
||||
self.assertInputEventsIn(expected, events)
|
||||
assert evdev.value[libevdev.EV_KEY.KEY_A] == 0
|
||||
|
||||
def test_two_keys(self):
|
||||
uhdev = self.uhdev
|
||||
evdev = uhdev.get_evdev()
|
||||
syn_event = self.syn_event
|
||||
|
||||
r = uhdev.event(["a and A", "q and Q"])
|
||||
expected = [syn_event]
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_A, 1))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_Q, 1))
|
||||
events = uhdev.next_sync_events()
|
||||
self.debug_reports(r, uhdev, events)
|
||||
self.assertInputEventsIn(expected, events)
|
||||
assert evdev.value[libevdev.EV_KEY.KEY_A] == 1
|
||||
|
||||
r = uhdev.event([])
|
||||
expected = [syn_event]
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_A, 0))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_Q, 0))
|
||||
events = uhdev.next_sync_events()
|
||||
self.debug_reports(r, uhdev, events)
|
||||
self.assertInputEventsIn(expected, events)
|
||||
assert evdev.value[libevdev.EV_KEY.KEY_A] == 0
|
||||
assert evdev.value[libevdev.EV_KEY.KEY_Q] == 0
|
||||
|
||||
r = uhdev.event(["c and C"])
|
||||
expected = [syn_event]
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_C, 1))
|
||||
events = uhdev.next_sync_events()
|
||||
self.debug_reports(r, uhdev, events)
|
||||
self.assertInputEventsIn(expected, events)
|
||||
assert evdev.value[libevdev.EV_KEY.KEY_C] == 1
|
||||
|
||||
r = uhdev.event(["c and C", "Spacebar"])
|
||||
expected = [syn_event]
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_SPACE, 1))
|
||||
events = uhdev.next_sync_events()
|
||||
self.debug_reports(r, uhdev, events)
|
||||
assert libevdev.InputEvent(libevdev.EV_KEY.KEY_C) not in events
|
||||
self.assertInputEventsIn(expected, events)
|
||||
assert evdev.value[libevdev.EV_KEY.KEY_C] == 1
|
||||
assert evdev.value[libevdev.EV_KEY.KEY_SPACE] == 1
|
||||
|
||||
r = uhdev.event(["Spacebar"])
|
||||
expected = [syn_event]
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_C, 0))
|
||||
events = uhdev.next_sync_events()
|
||||
self.debug_reports(r, uhdev, events)
|
||||
assert libevdev.InputEvent(libevdev.EV_KEY.KEY_SPACE) not in events
|
||||
self.assertInputEventsIn(expected, events)
|
||||
assert evdev.value[libevdev.EV_KEY.KEY_C] == 0
|
||||
assert evdev.value[libevdev.EV_KEY.KEY_SPACE] == 1
|
||||
|
||||
r = uhdev.event([])
|
||||
expected = [syn_event]
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_SPACE, 0))
|
||||
events = uhdev.next_sync_events()
|
||||
self.debug_reports(r, uhdev, events)
|
||||
self.assertInputEventsIn(expected, events)
|
||||
assert evdev.value[libevdev.EV_KEY.KEY_SPACE] == 0
|
||||
|
||||
def test_modifiers(self):
|
||||
# ctrl-alt-del would be very nice :)
|
||||
uhdev = self.uhdev
|
||||
syn_event = self.syn_event
|
||||
|
||||
r = uhdev.event(["LeftControl", "LeftShift", "= and +"])
|
||||
expected = [syn_event]
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_LEFTCTRL, 1))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_LEFTSHIFT, 1))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_EQUAL, 1))
|
||||
events = uhdev.next_sync_events()
|
||||
self.debug_reports(r, uhdev, events)
|
||||
self.assertInputEventsIn(expected, events)
|
||||
|
||||
|
||||
class TestPlainKeyboard(BaseTest.TestKeyboard):
|
||||
def create_device(self):
|
||||
return PlainKeyboard()
|
||||
|
||||
def test_10_keys(self):
|
||||
uhdev = self.uhdev
|
||||
syn_event = self.syn_event
|
||||
|
||||
r = uhdev.event(
|
||||
[
|
||||
"1 and !",
|
||||
"2 and @",
|
||||
"3 and #",
|
||||
"4 and $",
|
||||
"5 and %",
|
||||
"6 and ^",
|
||||
"7 and &",
|
||||
"8 and *",
|
||||
"9 and (",
|
||||
"0 and )",
|
||||
]
|
||||
)
|
||||
expected = [syn_event]
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_0, 1))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_1, 1))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_2, 1))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_3, 1))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_4, 1))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_5, 1))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_6, 1))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_7, 1))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_8, 1))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_9, 1))
|
||||
events = uhdev.next_sync_events()
|
||||
self.debug_reports(r, uhdev, events)
|
||||
self.assertInputEventsIn(expected, events)
|
||||
|
||||
r = uhdev.event([])
|
||||
expected = [syn_event]
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_0, 0))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_1, 0))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_2, 0))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_3, 0))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_4, 0))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_5, 0))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_6, 0))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_7, 0))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_8, 0))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_9, 0))
|
||||
events = uhdev.next_sync_events()
|
||||
self.debug_reports(r, uhdev, events)
|
||||
self.assertInputEventsIn(expected, events)
|
||||
|
||||
|
||||
class TestArrayKeyboard(BaseTest.TestKeyboard):
|
||||
def create_device(self):
|
||||
return ArrayKeyboard()
|
||||
|
||||
def test_10_keys(self):
|
||||
uhdev = self.uhdev
|
||||
syn_event = self.syn_event
|
||||
|
||||
r = uhdev.event(
|
||||
[
|
||||
"1 and !",
|
||||
"2 and @",
|
||||
"3 and #",
|
||||
"4 and $",
|
||||
"5 and %",
|
||||
"6 and ^",
|
||||
]
|
||||
)
|
||||
expected = [syn_event]
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_1, 1))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_2, 1))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_3, 1))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_4, 1))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_5, 1))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_6, 1))
|
||||
events = uhdev.next_sync_events()
|
||||
|
||||
self.debug_reports(r, uhdev, events)
|
||||
self.assertInputEventsIn(expected, events)
|
||||
|
||||
# ErrRollOver
|
||||
r = uhdev.event(
|
||||
[
|
||||
"1 and !",
|
||||
"2 and @",
|
||||
"3 and #",
|
||||
"4 and $",
|
||||
"5 and %",
|
||||
"6 and ^",
|
||||
"7 and &",
|
||||
"8 and *",
|
||||
"9 and (",
|
||||
"0 and )",
|
||||
]
|
||||
)
|
||||
events = uhdev.next_sync_events()
|
||||
|
||||
self.debug_reports(r, uhdev, events)
|
||||
|
||||
assert len(events) == 0
|
||||
|
||||
r = uhdev.event([])
|
||||
expected = [syn_event]
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_1, 0))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_2, 0))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_3, 0))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_4, 0))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_5, 0))
|
||||
expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_6, 0))
|
||||
events = uhdev.next_sync_events()
|
||||
self.debug_reports(r, uhdev, events)
|
||||
self.assertInputEventsIn(expected, events)
|
||||
|
||||
|
||||
class TestLEDKeyboard(BaseTest.TestKeyboard):
|
||||
def create_device(self):
|
||||
return LEDKeyboard()
|
||||
|
||||
|
||||
class TestPrimaxKeyboard(BaseTest.TestKeyboard):
|
||||
def create_device(self):
|
||||
return PrimaxKeyboard()
|
Loading…
Reference in a new issue