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 11 12import libevdev 13import logging 14 15logger = logging.getLogger("hidtools.test.apple-keyboard") 16 17KERNEL_MODULE = ("apple", "hid-apple") 18 19 20class KbdData(object): 21 pass 22 23 24class AppleKeyboard(ArrayKeyboard): 25 # fmt: off 26 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 Collection 60 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 Collection 75 0xc0, # End Collection 76 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 Collection 138 ] 139 # fmt: on 140 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 = 1 149 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.uhdev 167 evdev = uhdev.get_evdev() 168 syn_event = self.syn_event 169 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] == 1 177 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0 178 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] == 0 186 187 def test_single_fn_function_key(self): 188 """check for function key reliability with the fn key.""" 189 uhdev = self.uhdev 190 evdev = uhdev.get_evdev() 191 syn_event = self.syn_event 192 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] == 1 202 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] == 0 210 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1 211 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.uhdev 222 evdev = uhdev.get_evdev() 223 syn_event = self.syn_event 224 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] == 1 234 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] == 0 249 250 def test_single_fn_function_key_inverted(self): 251 """check for function key reliability with the fn key.""" 252 uhdev = self.uhdev 253 evdev = uhdev.get_evdev() 254 syn_event = self.syn_event 255 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] == 1 265 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] == 0 273 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1 274 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.uhdev 285 evdev = uhdev.get_evdev() 286 syn_event = self.syn_event 287 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] == 1 299 assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1 300 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1 301 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] == 0 309 assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1 310 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1 311 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] == 0 319 assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1 320 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0 321 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] == 0 329 assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0 330 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0 331 332 def test_multiple_fn_function_key_release_between(self): 333 """check for function key reliability with the fn key.""" 334 uhdev = self.uhdev 335 evdev = uhdev.get_evdev() 336 syn_event = self.syn_event 337 338 # press F4 339 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] == 0 346 assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1 347 assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0 348 assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0 349 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0 350 351 # press Fn key 352 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] == 0 359 assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1 360 assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0 361 assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0 362 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1 363 364 # keep F4 and press F6 365 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] == 0 372 assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1 373 assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1 374 assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0 375 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1 376 377 # keep F4 and F6 378 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] == 0 384 assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1 385 assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1 386 assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0 387 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1 388 389 # release Fn key and all keys 390 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] == 0 399 assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 0 400 assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0 401 assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0 402 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0 403 404 def test_single_pageup_key_release_first(self): 405 """check for function key reliability with the [page] up key.""" 406 uhdev = self.uhdev 407 evdev = uhdev.get_evdev() 408 syn_event = self.syn_event 409 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] == 1 419 assert evdev.value[libevdev.EV_KEY.KEY_UP] == 0 420 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1 421 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] == 1 429 assert evdev.value[libevdev.EV_KEY.KEY_UP] == 0 430 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0 431 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] == 0 439 assert evdev.value[libevdev.EV_KEY.KEY_UP] == 0 440 assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0 441