xref: /linux/tools/testing/selftests/hid/tests/test_apple_keyboard.py (revision 989fe6771266bdb82a815d78802c5aa7c918fdfd)
1#!/bin/env python3
2# SPDX-License-Identifier: GPL-2.0
3# -*- coding: utf-8 -*-
4#
5# Copyright (c) 2019 Benjamin Tissoires <benjamin.tissoires@gmail.com>
6# Copyright (c) 2019 Red Hat, Inc.
7#
8
9from .test_keyboard import ArrayKeyboard, TestArrayKeyboard
10from hidtools.util import BusType
11from . import base
12
13import libevdev
14import logging
15
16logger = logging.getLogger("hidtools.test.apple-keyboard")
17
18KERNEL_MODULE = base.KernelModule("apple", "hid-apple")
19
20
21class KbdData(object):
22    pass
23
24
25class AppleKeyboard(ArrayKeyboard):
26    # fmt: off
27    report_descriptor = [
28        0x05, 0x01,         # Usage Page (Generic Desktop)
29        0x09, 0x06,         # Usage (Keyboard)
30        0xa1, 0x01,         # Collection (Application)
31        0x85, 0x01,         # .Report ID (1)
32        0x05, 0x07,         # .Usage Page (Keyboard)
33        0x19, 0xe0,         # .Usage Minimum (224)
34        0x29, 0xe7,         # .Usage Maximum (231)
35        0x15, 0x00,         # .Logical Minimum (0)
36        0x25, 0x01,         # .Logical Maximum (1)
37        0x75, 0x01,         # .Report Size (1)
38        0x95, 0x08,         # .Report Count (8)
39        0x81, 0x02,         # .Input (Data,Var,Abs)
40        0x75, 0x08,         # .Report Size (8)
41        0x95, 0x01,         # .Report Count (1)
42        0x81, 0x01,         # .Input (Cnst,Arr,Abs)
43        0x75, 0x01,         # .Report Size (1)
44        0x95, 0x05,         # .Report Count (5)
45        0x05, 0x08,         # .Usage Page (LEDs)
46        0x19, 0x01,         # .Usage Minimum (1)
47        0x29, 0x05,         # .Usage Maximum (5)
48        0x91, 0x02,         # .Output (Data,Var,Abs)
49        0x75, 0x03,         # .Report Size (3)
50        0x95, 0x01,         # .Report Count (1)
51        0x91, 0x01,         # .Output (Cnst,Arr,Abs)
52        0x75, 0x08,         # .Report Size (8)
53        0x95, 0x06,         # .Report Count (6)
54        0x15, 0x00,         # .Logical Minimum (0)
55        0x26, 0xff, 0x00,   # .Logical Maximum (255)
56        0x05, 0x07,         # .Usage Page (Keyboard)
57        0x19, 0x00,         # .Usage Minimum (0)
58        0x2a, 0xff, 0x00,   # .Usage Maximum (255)
59        0x81, 0x00,         # .Input (Data,Arr,Abs)
60        0xc0,               # End Collection
61        0x05, 0x0c,         # Usage Page (Consumer Devices)
62        0x09, 0x01,         # Usage (Consumer Control)
63        0xa1, 0x01,         # Collection (Application)
64        0x85, 0x47,         # .Report ID (71)
65        0x05, 0x01,         # .Usage Page (Generic Desktop)
66        0x09, 0x06,         # .Usage (Keyboard)
67        0xa1, 0x02,         # .Collection (Logical)
68        0x05, 0x06,         # ..Usage Page (Generic Device Controls)
69        0x09, 0x20,         # ..Usage (Battery Strength)
70        0x15, 0x00,         # ..Logical Minimum (0)
71        0x26, 0xff, 0x00,   # ..Logical Maximum (255)
72        0x75, 0x08,         # ..Report Size (8)
73        0x95, 0x01,         # ..Report Count (1)
74        0x81, 0x02,         # ..Input (Data,Var,Abs)
75        0xc0,               # .End Collection
76        0xc0,               # End Collection
77        0x05, 0x0c,         # Usage Page (Consumer Devices)
78        0x09, 0x01,         # Usage (Consumer Control)
79        0xa1, 0x01,         # Collection (Application)
80        0x85, 0x11,         # .Report ID (17)
81        0x15, 0x00,         # .Logical Minimum (0)
82        0x25, 0x01,         # .Logical Maximum (1)
83        0x75, 0x01,         # .Report Size (1)
84        0x95, 0x03,         # .Report Count (3)
85        0x81, 0x01,         # .Input (Cnst,Arr,Abs)
86        0x75, 0x01,         # .Report Size (1)
87        0x95, 0x01,         # .Report Count (1)
88        0x05, 0x0c,         # .Usage Page (Consumer Devices)
89        0x09, 0xb8,         # .Usage (Eject)
90        0x81, 0x02,         # .Input (Data,Var,Abs)
91        0x06, 0xff, 0x00,   # .Usage Page (Vendor Usage Page 0xff)
92        0x09, 0x03,         # .Usage (Vendor Usage 0x03)
93        0x81, 0x02,         # .Input (Data,Var,Abs)
94        0x75, 0x01,         # .Report Size (1)
95        0x95, 0x03,         # .Report Count (3)
96        0x81, 0x01,         # .Input (Cnst,Arr,Abs)
97        0x05, 0x0c,         # .Usage Page (Consumer Devices)
98        0x85, 0x12,         # .Report ID (18)
99        0x15, 0x00,         # .Logical Minimum (0)
100        0x25, 0x01,         # .Logical Maximum (1)
101        0x75, 0x01,         # .Report Size (1)
102        0x95, 0x01,         # .Report Count (1)
103        0x09, 0xcd,         # .Usage (Play/Pause)
104        0x81, 0x02,         # .Input (Data,Var,Abs)
105        0x09, 0xb3,         # .Usage (Fast Forward)
106        0x81, 0x02,         # .Input (Data,Var,Abs)
107        0x09, 0xb4,         # .Usage (Rewind)
108        0x81, 0x02,         # .Input (Data,Var,Abs)
109        0x09, 0xb5,         # .Usage (Scan Next Track)
110        0x81, 0x02,         # .Input (Data,Var,Abs)
111        0x09, 0xb6,         # .Usage (Scan Previous Track)
112        0x81, 0x02,         # .Input (Data,Var,Abs)
113        0x81, 0x01,         # .Input (Cnst,Arr,Abs)
114        0x81, 0x01,         # .Input (Cnst,Arr,Abs)
115        0x81, 0x01,         # .Input (Cnst,Arr,Abs)
116        0x85, 0x13,         # .Report ID (19)
117        0x15, 0x00,         # .Logical Minimum (0)
118        0x25, 0x01,         # .Logical Maximum (1)
119        0x75, 0x01,         # .Report Size (1)
120        0x95, 0x01,         # .Report Count (1)
121        0x06, 0x01, 0xff,   # .Usage Page (Vendor Usage Page 0xff01)
122        0x09, 0x0a,         # .Usage (Vendor Usage 0x0a)
123        0x81, 0x02,         # .Input (Data,Var,Abs)
124        0x06, 0x01, 0xff,   # .Usage Page (Vendor Usage Page 0xff01)
125        0x09, 0x0c,         # .Usage (Vendor Usage 0x0c)
126        0x81, 0x22,         # .Input (Data,Var,Abs,NoPref)
127        0x75, 0x01,         # .Report Size (1)
128        0x95, 0x06,         # .Report Count (6)
129        0x81, 0x01,         # .Input (Cnst,Arr,Abs)
130        0x85, 0x09,         # .Report ID (9)
131        0x09, 0x0b,         # .Usage (Vendor Usage 0x0b)
132        0x75, 0x08,         # .Report Size (8)
133        0x95, 0x01,         # .Report Count (1)
134        0xb1, 0x02,         # .Feature (Data,Var,Abs)
135        0x75, 0x08,         # .Report Size (8)
136        0x95, 0x02,         # .Report Count (2)
137        0xb1, 0x01,         # .Feature (Cnst,Arr,Abs)
138        0xc0,               # End Collection
139    ]
140    # fmt: on
141
142    def __init__(
143        self,
144        rdesc=report_descriptor,
145        name="Apple Wireless Keyboard",
146        input_info=(BusType.BLUETOOTH, 0x05AC, 0x0256),
147    ):
148        super().__init__(rdesc, name, input_info)
149        self.default_reportID = 1
150
151    def send_fn_state(self, state):
152        data = KbdData()
153        setattr(data, "0xff0003", state)
154        r = self.create_report(data, reportID=17)
155        self.call_input_event(r)
156        return [r]
157
158
159class TestAppleKeyboard(TestArrayKeyboard):
160    kernel_modules = [KERNEL_MODULE]
161
162    def create_device(self):
163        return AppleKeyboard()
164
165    def test_single_function_key(self):
166        """check for function key reliability."""
167        uhdev = self.uhdev
168        evdev = uhdev.get_evdev()
169        syn_event = self.syn_event
170
171        r = uhdev.event(["F4"])
172        expected = [syn_event]
173        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 1))
174        events = uhdev.next_sync_events()
175        self.debug_reports(r, uhdev, events)
176        self.assertInputEventsIn(expected, events)
177        assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1
178        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0
179
180        r = uhdev.event([])
181        expected = [syn_event]
182        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 0))
183        events = uhdev.next_sync_events()
184        self.debug_reports(r, uhdev, events)
185        self.assertInputEventsIn(expected, events)
186        assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 0
187
188    def test_single_fn_function_key(self):
189        """check for function key reliability with the fn key."""
190        uhdev = self.uhdev
191        evdev = uhdev.get_evdev()
192        syn_event = self.syn_event
193
194        r = uhdev.send_fn_state(1)
195        r.extend(uhdev.event(["F4"]))
196        expected = [syn_event]
197        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 1))
198        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1))
199        events = uhdev.next_sync_events()
200        self.debug_reports(r, uhdev, events)
201        self.assertInputEventsIn(expected, events)
202        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 1
203
204        r = uhdev.event([])
205        expected = [syn_event]
206        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 0))
207        events = uhdev.next_sync_events()
208        self.debug_reports(r, uhdev, events)
209        self.assertInputEventsIn(expected, events)
210        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
211        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1
212
213        r = uhdev.send_fn_state(0)
214        expected = [syn_event]
215        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0))
216        events = uhdev.next_sync_events()
217        self.debug_reports(r, uhdev, events)
218        self.assertInputEventsIn(expected, events)
219
220    def test_single_fn_function_key_release_first(self):
221        """check for function key reliability with the fn key."""
222        uhdev = self.uhdev
223        evdev = uhdev.get_evdev()
224        syn_event = self.syn_event
225
226        r = uhdev.send_fn_state(1)
227        r.extend(uhdev.event(["F4"]))
228        expected = [syn_event]
229        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 1))
230        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1))
231        events = uhdev.next_sync_events()
232        self.debug_reports(r, uhdev, events)
233        self.assertInputEventsIn(expected, events)
234        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 1
235
236        r = uhdev.send_fn_state(0)
237        expected = [syn_event]
238        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0))
239        events = uhdev.next_sync_events()
240        self.debug_reports(r, uhdev, events)
241        self.assertInputEventsIn(expected, events)
242
243        r = uhdev.event([])
244        expected = [syn_event]
245        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 0))
246        events = uhdev.next_sync_events()
247        self.debug_reports(r, uhdev, events)
248        self.assertInputEventsIn(expected, events)
249        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
250
251    def test_single_fn_function_key_inverted(self):
252        """check for function key reliability with the fn key."""
253        uhdev = self.uhdev
254        evdev = uhdev.get_evdev()
255        syn_event = self.syn_event
256
257        r = uhdev.event(["F4"])
258        r.extend(uhdev.send_fn_state(1))
259        expected = [syn_event]
260        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 1))
261        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1))
262        events = uhdev.next_sync_events()
263        self.debug_reports(r, uhdev, events)
264        self.assertInputEventsIn(expected, events)
265        assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1
266
267        r = uhdev.event([])
268        expected = [syn_event]
269        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 0))
270        events = uhdev.next_sync_events()
271        self.debug_reports(r, uhdev, events)
272        self.assertInputEventsIn(expected, events)
273        assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 0
274        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1
275
276        r = uhdev.send_fn_state(0)
277        expected = [syn_event]
278        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0))
279        events = uhdev.next_sync_events()
280        self.debug_reports(r, uhdev, events)
281        self.assertInputEventsIn(expected, events)
282
283    def test_multiple_fn_function_key_release_first(self):
284        """check for function key reliability with the fn key."""
285        uhdev = self.uhdev
286        evdev = uhdev.get_evdev()
287        syn_event = self.syn_event
288
289        r = uhdev.send_fn_state(1)
290        r.extend(uhdev.event(["F4"]))
291        r.extend(uhdev.event(["F4", "F6"]))
292        expected = [syn_event]
293        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 1))
294        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F6, 1))
295        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1))
296        events = uhdev.next_sync_events()
297        self.debug_reports(r, uhdev, events)
298        self.assertInputEventsIn(expected, events)
299        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 1
300        assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1
301        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1
302
303        r = uhdev.event(["F6"])
304        expected = [syn_event]
305        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 0))
306        events = uhdev.next_sync_events()
307        self.debug_reports(r, uhdev, events)
308        self.assertInputEventsIn(expected, events)
309        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
310        assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1
311        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1
312
313        r = uhdev.send_fn_state(0)
314        expected = [syn_event]
315        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0))
316        events = uhdev.next_sync_events()
317        self.debug_reports(r, uhdev, events)
318        self.assertInputEventsIn(expected, events)
319        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
320        assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1
321        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0
322
323        r = uhdev.event([])
324        expected = [syn_event]
325        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F6, 0))
326        events = uhdev.next_sync_events()
327        self.debug_reports(r, uhdev, events)
328        self.assertInputEventsIn(expected, events)
329        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
330        assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0
331        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0
332
333    def test_multiple_fn_function_key_release_between(self):
334        """check for function key reliability with the fn key."""
335        uhdev = self.uhdev
336        evdev = uhdev.get_evdev()
337        syn_event = self.syn_event
338
339        # press F4
340        r = uhdev.event(["F4"])
341        expected = [syn_event]
342        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 1))
343        events = uhdev.next_sync_events()
344        self.debug_reports(r, uhdev, events)
345        self.assertInputEventsIn(expected, events)
346        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
347        assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1
348        assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0
349        assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0
350        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0
351
352        # press Fn key
353        r = uhdev.send_fn_state(1)
354        expected = [syn_event]
355        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1))
356        events = uhdev.next_sync_events()
357        self.debug_reports(r, uhdev, events)
358        self.assertInputEventsIn(expected, events)
359        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
360        assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1
361        assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0
362        assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0
363        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1
364
365        # keep F4 and press F6
366        r = uhdev.event(["F4", "F6"])
367        expected = [syn_event]
368        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F6, 1))
369        events = uhdev.next_sync_events()
370        self.debug_reports(r, uhdev, events)
371        self.assertInputEventsIn(expected, events)
372        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
373        assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1
374        assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1
375        assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0
376        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1
377
378        # keep F4 and F6
379        r = uhdev.event(["F4", "F6"])
380        expected = []
381        events = uhdev.next_sync_events()
382        self.debug_reports(r, uhdev, events)
383        self.assertInputEventsIn(expected, events)
384        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
385        assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1
386        assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1
387        assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0
388        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1
389
390        # release Fn key and all keys
391        r = uhdev.send_fn_state(0)
392        r.extend(uhdev.event([]))
393        expected = [syn_event]
394        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 0))
395        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F6, 0))
396        events = uhdev.next_sync_events()
397        self.debug_reports(r, uhdev, events)
398        self.assertInputEventsIn(expected, events)
399        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
400        assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 0
401        assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0
402        assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0
403        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0
404
405    def test_single_pageup_key_release_first(self):
406        """check for function key reliability with the [page] up key."""
407        uhdev = self.uhdev
408        evdev = uhdev.get_evdev()
409        syn_event = self.syn_event
410
411        r = uhdev.send_fn_state(1)
412        r.extend(uhdev.event(["UpArrow"]))
413        expected = [syn_event]
414        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_PAGEUP, 1))
415        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1))
416        events = uhdev.next_sync_events()
417        self.debug_reports(r, uhdev, events)
418        self.assertInputEventsIn(expected, events)
419        assert evdev.value[libevdev.EV_KEY.KEY_PAGEUP] == 1
420        assert evdev.value[libevdev.EV_KEY.KEY_UP] == 0
421        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1
422
423        r = uhdev.send_fn_state(0)
424        expected = [syn_event]
425        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0))
426        events = uhdev.next_sync_events()
427        self.debug_reports(r, uhdev, events)
428        self.assertInputEventsIn(expected, events)
429        assert evdev.value[libevdev.EV_KEY.KEY_PAGEUP] == 1
430        assert evdev.value[libevdev.EV_KEY.KEY_UP] == 0
431        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0
432
433        r = uhdev.event([])
434        expected = [syn_event]
435        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_PAGEUP, 0))
436        events = uhdev.next_sync_events()
437        self.debug_reports(r, uhdev, events)
438        self.assertInputEventsIn(expected, events)
439        assert evdev.value[libevdev.EV_KEY.KEY_PAGEUP] == 0
440        assert evdev.value[libevdev.EV_KEY.KEY_UP] == 0
441        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0
442