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