441 lines · python
1#!/bin/env python32# SPDX-License-Identifier: GPL-2.03# -*- 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, TestArrayKeyboard10from hidtools.util import BusType11 12import libevdev13import logging14 15logger = logging.getLogger("hidtools.test.apple-keyboard")16 17KERNEL_MODULE = ("apple", "hid-apple")18 19 20class KbdData(object):21 pass22 23 24class AppleKeyboard(ArrayKeyboard):25 # fmt: off26 report_descriptor = [27 0x05, 0x01, # Usage Page (Generic Desktop)28 0x09, 0x06, # Usage (Keyboard)29 0xa1, 0x01, # Collection (Application)30 0x85, 0x01, # .Report ID (1)31 0x05, 0x07, # .Usage Page (Keyboard)32 0x19, 0xe0, # .Usage Minimum (224)33 0x29, 0xe7, # .Usage Maximum (231)34 0x15, 0x00, # .Logical Minimum (0)35 0x25, 0x01, # .Logical Maximum (1)36 0x75, 0x01, # .Report Size (1)37 0x95, 0x08, # .Report Count (8)38 0x81, 0x02, # .Input (Data,Var,Abs)39 0x75, 0x08, # .Report Size (8)40 0x95, 0x01, # .Report Count (1)41 0x81, 0x01, # .Input (Cnst,Arr,Abs)42 0x75, 0x01, # .Report Size (1)43 0x95, 0x05, # .Report Count (5)44 0x05, 0x08, # .Usage Page (LEDs)45 0x19, 0x01, # .Usage Minimum (1)46 0x29, 0x05, # .Usage Maximum (5)47 0x91, 0x02, # .Output (Data,Var,Abs)48 0x75, 0x03, # .Report Size (3)49 0x95, 0x01, # .Report Count (1)50 0x91, 0x01, # .Output (Cnst,Arr,Abs)51 0x75, 0x08, # .Report Size (8)52 0x95, 0x06, # .Report Count (6)53 0x15, 0x00, # .Logical Minimum (0)54 0x26, 0xff, 0x00, # .Logical Maximum (255)55 0x05, 0x07, # .Usage Page (Keyboard)56 0x19, 0x00, # .Usage Minimum (0)57 0x2a, 0xff, 0x00, # .Usage Maximum (255)58 0x81, 0x00, # .Input (Data,Arr,Abs)59 0xc0, # End Collection60 0x05, 0x0c, # Usage Page (Consumer Devices)61 0x09, 0x01, # Usage (Consumer Control)62 0xa1, 0x01, # Collection (Application)63 0x85, 0x47, # .Report ID (71)64 0x05, 0x01, # .Usage Page (Generic Desktop)65 0x09, 0x06, # .Usage (Keyboard)66 0xa1, 0x02, # .Collection (Logical)67 0x05, 0x06, # ..Usage Page (Generic Device Controls)68 0x09, 0x20, # ..Usage (Battery Strength)69 0x15, 0x00, # ..Logical Minimum (0)70 0x26, 0xff, 0x00, # ..Logical Maximum (255)71 0x75, 0x08, # ..Report Size (8)72 0x95, 0x01, # ..Report Count (1)73 0x81, 0x02, # ..Input (Data,Var,Abs)74 0xc0, # .End Collection75 0xc0, # End Collection76 0x05, 0x0c, # Usage Page (Consumer Devices)77 0x09, 0x01, # Usage (Consumer Control)78 0xa1, 0x01, # Collection (Application)79 0x85, 0x11, # .Report ID (17)80 0x15, 0x00, # .Logical Minimum (0)81 0x25, 0x01, # .Logical Maximum (1)82 0x75, 0x01, # .Report Size (1)83 0x95, 0x03, # .Report Count (3)84 0x81, 0x01, # .Input (Cnst,Arr,Abs)85 0x75, 0x01, # .Report Size (1)86 0x95, 0x01, # .Report Count (1)87 0x05, 0x0c, # .Usage Page (Consumer Devices)88 0x09, 0xb8, # .Usage (Eject)89 0x81, 0x02, # .Input (Data,Var,Abs)90 0x06, 0xff, 0x00, # .Usage Page (Vendor Usage Page 0xff)91 0x09, 0x03, # .Usage (Vendor Usage 0x03)92 0x81, 0x02, # .Input (Data,Var,Abs)93 0x75, 0x01, # .Report Size (1)94 0x95, 0x03, # .Report Count (3)95 0x81, 0x01, # .Input (Cnst,Arr,Abs)96 0x05, 0x0c, # .Usage Page (Consumer Devices)97 0x85, 0x12, # .Report ID (18)98 0x15, 0x00, # .Logical Minimum (0)99 0x25, 0x01, # .Logical Maximum (1)100 0x75, 0x01, # .Report Size (1)101 0x95, 0x01, # .Report Count (1)102 0x09, 0xcd, # .Usage (Play/Pause)103 0x81, 0x02, # .Input (Data,Var,Abs)104 0x09, 0xb3, # .Usage (Fast Forward)105 0x81, 0x02, # .Input (Data,Var,Abs)106 0x09, 0xb4, # .Usage (Rewind)107 0x81, 0x02, # .Input (Data,Var,Abs)108 0x09, 0xb5, # .Usage (Scan Next Track)109 0x81, 0x02, # .Input (Data,Var,Abs)110 0x09, 0xb6, # .Usage (Scan Previous Track)111 0x81, 0x02, # .Input (Data,Var,Abs)112 0x81, 0x01, # .Input (Cnst,Arr,Abs)113 0x81, 0x01, # .Input (Cnst,Arr,Abs)114 0x81, 0x01, # .Input (Cnst,Arr,Abs)115 0x85, 0x13, # .Report ID (19)116 0x15, 0x00, # .Logical Minimum (0)117 0x25, 0x01, # .Logical Maximum (1)118 0x75, 0x01, # .Report Size (1)119 0x95, 0x01, # .Report Count (1)120 0x06, 0x01, 0xff, # .Usage Page (Vendor Usage Page 0xff01)121 0x09, 0x0a, # .Usage (Vendor Usage 0x0a)122 0x81, 0x02, # .Input (Data,Var,Abs)123 0x06, 0x01, 0xff, # .Usage Page (Vendor Usage Page 0xff01)124 0x09, 0x0c, # .Usage (Vendor Usage 0x0c)125 0x81, 0x22, # .Input (Data,Var,Abs,NoPref)126 0x75, 0x01, # .Report Size (1)127 0x95, 0x06, # .Report Count (6)128 0x81, 0x01, # .Input (Cnst,Arr,Abs)129 0x85, 0x09, # .Report ID (9)130 0x09, 0x0b, # .Usage (Vendor Usage 0x0b)131 0x75, 0x08, # .Report Size (8)132 0x95, 0x01, # .Report Count (1)133 0xb1, 0x02, # .Feature (Data,Var,Abs)134 0x75, 0x08, # .Report Size (8)135 0x95, 0x02, # .Report Count (2)136 0xb1, 0x01, # .Feature (Cnst,Arr,Abs)137 0xc0, # End Collection138 ]139 # fmt: on140 141 def __init__(142 self,143 rdesc=report_descriptor,144 name="Apple Wireless Keyboard",145 input_info=(BusType.BLUETOOTH, 0x05AC, 0x0256),146 ):147 super().__init__(rdesc, name, input_info)148 self.default_reportID = 1149 150 def send_fn_state(self, state):151 data = KbdData()152 setattr(data, "0xff0003", state)153 r = self.create_report(data, reportID=17)154 self.call_input_event(r)155 return [r]156 157 158class TestAppleKeyboard(TestArrayKeyboard):159 kernel_modules = [KERNEL_MODULE]160 161 def create_device(self):162 return AppleKeyboard()163 164 def test_single_function_key(self):165 """check for function key reliability."""166 uhdev = self.uhdev167 evdev = uhdev.get_evdev()168 syn_event = self.syn_event169 170 r = uhdev.event(["F4"])171 expected = [syn_event]172 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 1))173 events = uhdev.next_sync_events()174 self.debug_reports(r, uhdev, events)175 self.assertInputEventsIn(expected, events)176 assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1177 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0178 179 r = uhdev.event([])180 expected = [syn_event]181 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 0))182 events = uhdev.next_sync_events()183 self.debug_reports(r, uhdev, events)184 self.assertInputEventsIn(expected, events)185 assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 0186 187 def test_single_fn_function_key(self):188 """check for function key reliability with the fn key."""189 uhdev = self.uhdev190 evdev = uhdev.get_evdev()191 syn_event = self.syn_event192 193 r = uhdev.send_fn_state(1)194 r.extend(uhdev.event(["F4"]))195 expected = [syn_event]196 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 1))197 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1))198 events = uhdev.next_sync_events()199 self.debug_reports(r, uhdev, events)200 self.assertInputEventsIn(expected, events)201 assert evdev.value[libevdev.EV_KEY.KEY_F4] == 1202 203 r = uhdev.event([])204 expected = [syn_event]205 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 0))206 events = uhdev.next_sync_events()207 self.debug_reports(r, uhdev, events)208 self.assertInputEventsIn(expected, events)209 assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0210 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1211 212 r = uhdev.send_fn_state(0)213 expected = [syn_event]214 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0))215 events = uhdev.next_sync_events()216 self.debug_reports(r, uhdev, events)217 self.assertInputEventsIn(expected, events)218 219 def test_single_fn_function_key_release_first(self):220 """check for function key reliability with the fn key."""221 uhdev = self.uhdev222 evdev = uhdev.get_evdev()223 syn_event = self.syn_event224 225 r = uhdev.send_fn_state(1)226 r.extend(uhdev.event(["F4"]))227 expected = [syn_event]228 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 1))229 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1))230 events = uhdev.next_sync_events()231 self.debug_reports(r, uhdev, events)232 self.assertInputEventsIn(expected, events)233 assert evdev.value[libevdev.EV_KEY.KEY_F4] == 1234 235 r = uhdev.send_fn_state(0)236 expected = [syn_event]237 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0))238 events = uhdev.next_sync_events()239 self.debug_reports(r, uhdev, events)240 self.assertInputEventsIn(expected, events)241 242 r = uhdev.event([])243 expected = [syn_event]244 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 0))245 events = uhdev.next_sync_events()246 self.debug_reports(r, uhdev, events)247 self.assertInputEventsIn(expected, events)248 assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0249 250 def test_single_fn_function_key_inverted(self):251 """check for function key reliability with the fn key."""252 uhdev = self.uhdev253 evdev = uhdev.get_evdev()254 syn_event = self.syn_event255 256 r = uhdev.event(["F4"])257 r.extend(uhdev.send_fn_state(1))258 expected = [syn_event]259 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 1))260 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1))261 events = uhdev.next_sync_events()262 self.debug_reports(r, uhdev, events)263 self.assertInputEventsIn(expected, events)264 assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1265 266 r = uhdev.event([])267 expected = [syn_event]268 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 0))269 events = uhdev.next_sync_events()270 self.debug_reports(r, uhdev, events)271 self.assertInputEventsIn(expected, events)272 assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 0273 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1274 275 r = uhdev.send_fn_state(0)276 expected = [syn_event]277 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0))278 events = uhdev.next_sync_events()279 self.debug_reports(r, uhdev, events)280 self.assertInputEventsIn(expected, events)281 282 def test_multiple_fn_function_key_release_first(self):283 """check for function key reliability with the fn key."""284 uhdev = self.uhdev285 evdev = uhdev.get_evdev()286 syn_event = self.syn_event287 288 r = uhdev.send_fn_state(1)289 r.extend(uhdev.event(["F4"]))290 r.extend(uhdev.event(["F4", "F6"]))291 expected = [syn_event]292 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 1))293 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F6, 1))294 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1))295 events = uhdev.next_sync_events()296 self.debug_reports(r, uhdev, events)297 self.assertInputEventsIn(expected, events)298 assert evdev.value[libevdev.EV_KEY.KEY_F4] == 1299 assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1300 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1301 302 r = uhdev.event(["F6"])303 expected = [syn_event]304 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 0))305 events = uhdev.next_sync_events()306 self.debug_reports(r, uhdev, events)307 self.assertInputEventsIn(expected, events)308 assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0309 assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1310 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1311 312 r = uhdev.send_fn_state(0)313 expected = [syn_event]314 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0))315 events = uhdev.next_sync_events()316 self.debug_reports(r, uhdev, events)317 self.assertInputEventsIn(expected, events)318 assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0319 assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1320 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0321 322 r = uhdev.event([])323 expected = [syn_event]324 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F6, 0))325 events = uhdev.next_sync_events()326 self.debug_reports(r, uhdev, events)327 self.assertInputEventsIn(expected, events)328 assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0329 assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0330 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0331 332 def test_multiple_fn_function_key_release_between(self):333 """check for function key reliability with the fn key."""334 uhdev = self.uhdev335 evdev = uhdev.get_evdev()336 syn_event = self.syn_event337 338 # press F4339 r = uhdev.event(["F4"])340 expected = [syn_event]341 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 1))342 events = uhdev.next_sync_events()343 self.debug_reports(r, uhdev, events)344 self.assertInputEventsIn(expected, events)345 assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0346 assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1347 assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0348 assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0349 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0350 351 # press Fn key352 r = uhdev.send_fn_state(1)353 expected = [syn_event]354 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1))355 events = uhdev.next_sync_events()356 self.debug_reports(r, uhdev, events)357 self.assertInputEventsIn(expected, events)358 assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0359 assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1360 assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0361 assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0362 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1363 364 # keep F4 and press F6365 r = uhdev.event(["F4", "F6"])366 expected = [syn_event]367 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F6, 1))368 events = uhdev.next_sync_events()369 self.debug_reports(r, uhdev, events)370 self.assertInputEventsIn(expected, events)371 assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0372 assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1373 assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1374 assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0375 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1376 377 # keep F4 and F6378 r = uhdev.event(["F4", "F6"])379 expected = []380 events = uhdev.next_sync_events()381 self.debug_reports(r, uhdev, events)382 self.assertInputEventsIn(expected, events)383 assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0384 assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1385 assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1386 assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0387 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1388 389 # release Fn key and all keys390 r = uhdev.send_fn_state(0)391 r.extend(uhdev.event([]))392 expected = [syn_event]393 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 0))394 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F6, 0))395 events = uhdev.next_sync_events()396 self.debug_reports(r, uhdev, events)397 self.assertInputEventsIn(expected, events)398 assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0399 assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 0400 assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0401 assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0402 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0403 404 def test_single_pageup_key_release_first(self):405 """check for function key reliability with the [page] up key."""406 uhdev = self.uhdev407 evdev = uhdev.get_evdev()408 syn_event = self.syn_event409 410 r = uhdev.send_fn_state(1)411 r.extend(uhdev.event(["UpArrow"]))412 expected = [syn_event]413 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_PAGEUP, 1))414 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1))415 events = uhdev.next_sync_events()416 self.debug_reports(r, uhdev, events)417 self.assertInputEventsIn(expected, events)418 assert evdev.value[libevdev.EV_KEY.KEY_PAGEUP] == 1419 assert evdev.value[libevdev.EV_KEY.KEY_UP] == 0420 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1421 422 r = uhdev.send_fn_state(0)423 expected = [syn_event]424 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0))425 events = uhdev.next_sync_events()426 self.debug_reports(r, uhdev, events)427 self.assertInputEventsIn(expected, events)428 assert evdev.value[libevdev.EV_KEY.KEY_PAGEUP] == 1429 assert evdev.value[libevdev.EV_KEY.KEY_UP] == 0430 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0431 432 r = uhdev.event([])433 expected = [syn_event]434 expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_PAGEUP, 0))435 events = uhdev.next_sync_events()436 self.debug_reports(r, uhdev, events)437 self.assertInputEventsIn(expected, events)438 assert evdev.value[libevdev.EV_KEY.KEY_PAGEUP] == 0439 assert evdev.value[libevdev.EV_KEY.KEY_UP] == 0440 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0441