Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/tools/testing/selftests/hid/tests/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 19 kB image not shown  

Quelle  test_keyboard.py   Sprache: Python

 
#!/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()

Messung V0.5
C=87 H=90 G=88

¤ Dauer der Verarbeitung: 0.6 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.