Merge tag 'hid-for-linus-2025073101' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid

Pull HID updates from Jiri Kosina:

- hardening of HID core parser against conversion to 0 bits in s32ton()
by buggy/malicious devices (Alan Stern)

- fix for potential NULL pointer dereference in hid-apple that could be
caused by malicious device with APPLE_MAGIC_BACKLIGHT quirk present
triggering overflow in data field (Qasim Ijaz)

- support for Wake-on-touch in intel-thc (Even Xu)

- support for "Input max input size control" and "Input interrupt
delay" I2C features in order to improve compatibility of THC devices
with legacy HIDI2C touch devices (Even Xu)

- support for Touch Bars on x86 MacBook Pros (Kerem Karabay)

- support for XP-PEN Artist 22R Pro (Joshua Goins)

- third party trackpart support for MacBookPro15,1 (Aditya Garg)

- Apple Magic Keyboard A311[89] USB-C support (Aditya Garg, Grigorii
Sokoli)

- support for operating modes in amd-sfh (Basavaraj Natikar)

- avoid setting up battery timer for Apple and Magicmouse devices
without battery (Aditya Garg)

- fix for behavior of the hid-mcp2221 driver for !CONFIG_IIO cases
(Heiko Schocher)

- other assorted fixups and device ID additions

* tag 'hid-for-linus-2025073101' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (54 commits)
HID: core: Harden s32ton() against conversion to 0 bits
HID: apple: validate feature-report field count to prevent NULL pointer dereference
HID: core: Improve the kerneldoc for hid_report_len()
selftests/hid: sync python tests to hid-tools 0.10
selftests/hid: sync the python tests to hid-tools 0.8
selftests/hid: run ruff format on the python part
HID: magicmouse: use secs_to_jiffies() for battery timeout
HID: apple: use secs_to_jiffies() for battery timeout
HID: magicmouse: avoid setting up battery timer when not needed
HID: apple: avoid setting up battery timer for devices without battery
HID: amd_sfh: Enable operating mode
HID: uclogic: Add support for XP-PEN Artist 22R Pro
HID: rate-limit hid_warn to prevent log flooding
HID: replace scnprintf() with sysfs_emit()
HID: uclogic: make read-only array reconnect_event static const
HID: mcp-2221: Replace manual comparison with min() macro
HID: intel-thc-hid: Separate max input size control conditional list
HID: mcp2221: set gpio pin mode
HID: multitouch: add device ID for Apple Touch Bar
HID: multitouch: specify that Apple Touch Bar is direct
...

+1667 -476
+28
Documentation/hid/intel-thc-hid.rst
··· 188 188 Reset line is controlled by BIOS (or EFI) through ACPI _RST method, driver needs to call this 189 189 device ACPI _RST method to reset touch IC during initialization. 190 190 191 + 2.3 Max input size control 192 + -------------------------- 193 + 194 + This is a new feature introduced in Panther Lake platform, THC hardware allows driver to set 195 + a max input size for RxDMA. After this max size gets set and enabled, for every input report 196 + packet reading, THC hardware sequencer will first read incoming input packet size, then compare 197 + input packet size with the given max size: 198 + 199 + - if input packet size <= max size, THC continues using input packet size to finish the reading 200 + - if input packet size > max size, there is potential input data crash risk during 201 + transferring, THC will use max size instead of input packet size for reading 202 + 203 + This feature is used to avoid data corruption which will cause RxDMA buffer overrun issue for 204 + I2C bus, and enhance whole system stability. 205 + 206 + 2.4 Interrupt delay 207 + ------------------- 208 + 209 + Because of MCU performance limitation, some touch devices cannot de-assert interrupt pin 210 + immediately after input data is transferred, which cause an interrupt toggle delay. But THC 211 + always detects next interrupt immediately after last input interrupt is handled. In this 212 + case, the delayed interrupt de-assertion will be recognized as a new interrupt signal by THC, 213 + and causes THC to start an input report reading spuriously. 214 + 215 + In order to avoid this situation, THC introduced interrupt delay new feature in Panther Lake 216 + platform, where THC allows driver to set an interrupt delay. After this feature is enabled, 217 + THC will delay this given time for next interrupt detection. 218 + 191 219 3. High level concept 192 220 ===================== 193 221
+1
drivers/hid/Kconfig
··· 771 771 Say Y here if you have one of the following devices: 772 772 - 3M PCT touch screens 773 773 - ActionStar dual touch panels 774 + - Apple Touch Bar on x86 MacBook Pros 774 775 - Atmel panels 775 776 - Cando dual touch panels 776 777 - Chunghwa panels
+23
drivers/hid/amd-sfh-hid/amd_sfh_client.c
··· 146 146 return "gyroscope"; 147 147 case mag_idx: 148 148 return "magnetometer"; 149 + case op_idx: 150 + return "operating-mode"; 149 151 case als_idx: 150 152 case ACS_IDX: /* ambient color sensor */ 151 153 return "ALS"; ··· 245 243 rc = -ENOMEM; 246 244 goto cleanup; 247 245 } 246 + 247 + if (cl_data->sensor_idx[i] == op_idx) { 248 + info.period = AMD_SFH_IDLE_LOOP; 249 + info.sensor_idx = cl_data->sensor_idx[i]; 250 + info.dma_address = cl_data->sensor_dma_addr[i]; 251 + mp2_ops->start(privdata, info); 252 + cl_data->sensor_sts[i] = amd_sfh_wait_for_response(privdata, 253 + cl_data->sensor_idx[i], 254 + SENSOR_ENABLED); 255 + if (cl_data->sensor_sts[i] == SENSOR_ENABLED) 256 + cl_data->is_any_sensor_enabled = true; 257 + continue; 258 + } 259 + 248 260 cl_data->sensor_sts[i] = SENSOR_DISABLED; 249 261 cl_data->sensor_requested_cnt[i] = 0; 250 262 cl_data->cur_hid_dev = i; ··· 319 303 320 304 for (i = 0; i < cl_data->num_hid_devices; i++) { 321 305 cl_data->cur_hid_dev = i; 306 + if (cl_data->sensor_idx[i] == op_idx) { 307 + dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n", 308 + cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]), 309 + cl_data->sensor_sts[i]); 310 + continue; 311 + } 312 + 322 313 if (cl_data->sensor_sts[i] == SENSOR_ENABLED) { 323 314 rc = amdtp_hid_probe(i, cl_data); 324 315 if (rc)
+1 -1
drivers/hid/amd-sfh-hid/amd_sfh_hid.h
··· 11 11 #ifndef AMDSFH_HID_H 12 12 #define AMDSFH_HID_H 13 13 14 - #define MAX_HID_DEVICES 6 14 + #define MAX_HID_DEVICES 7 15 15 #define AMD_SFH_HID_VENDOR 0x1022 16 16 #define AMD_SFH_HID_PRODUCT 0x0001 17 17
+4
drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
··· 29 29 #define ACEL_EN BIT(0) 30 30 #define GYRO_EN BIT(1) 31 31 #define MAGNO_EN BIT(2) 32 + #define OP_EN BIT(15) 32 33 #define HPD_EN BIT(16) 33 34 #define ALS_EN BIT(19) 34 35 #define ACS_EN BIT(22) ··· 232 231 233 232 if (MAGNO_EN & activestatus) 234 233 sensor_id[num_of_sensors++] = mag_idx; 234 + 235 + if (OP_EN & activestatus) 236 + sensor_id[num_of_sensors++] = op_idx; 235 237 236 238 if (ALS_EN & activestatus) 237 239 sensor_id[num_of_sensors++] = als_idx;
+1
drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
··· 79 79 accel_idx = 0, 80 80 gyro_idx = 1, 81 81 mag_idx = 2, 82 + op_idx = 15, 82 83 als_idx = 19 83 84 }; 84 85
+145 -99
drivers/hid/hid-apple.c
··· 30 30 #include "hid-ids.h" 31 31 32 32 #define APPLE_RDESC_JIS BIT(0) 33 - #define APPLE_IGNORE_MOUSE BIT(1) 33 + /* BIT(1) reserved, was: APPLE_IGNORE_MOUSE */ 34 34 #define APPLE_HAS_FN BIT(2) 35 35 /* BIT(3) reserved, was: APPLE_HIDDEV */ 36 36 #define APPLE_ISO_TILDE_QUIRK BIT(4) ··· 42 42 #define APPLE_BACKLIGHT_CTL BIT(10) 43 43 #define APPLE_IS_NON_APPLE BIT(11) 44 44 #define APPLE_MAGIC_BACKLIGHT BIT(12) 45 + #define APPLE_DISABLE_FKEYS BIT(13) 45 46 46 - #define APPLE_FLAG_FKEY 0x01 47 + #define APPLE_FLAG_FKEY BIT(0) 48 + #define APPLE_FLAG_TB_FKEY BIT(1) 47 49 48 50 #define HID_COUNTRY_INTERNATIONAL_ISO 13 49 - #define APPLE_BATTERY_TIMEOUT_MS 60000 51 + #define APPLE_BATTERY_TIMEOUT_SEC 60 50 52 51 53 #define HID_USAGE_MAGIC_BL 0xff00000f 52 54 #define APPLE_MAGIC_REPORT_ID_POWER 3 ··· 57 55 static unsigned int fnmode = 3; 58 56 module_param(fnmode, uint, 0644); 59 57 MODULE_PARM_DESC(fnmode, "Mode of fn key on Apple keyboards (0 = disabled, " 60 - "1 = fkeyslast, 2 = fkeysfirst, [3] = auto)"); 58 + "1 = fkeyslast, 2 = fkeysfirst, [3] = auto, 4 = fkeysdisabled)"); 61 59 62 60 static int iso_layout = -1; 63 61 module_param(iso_layout, int, 0644); ··· 91 89 struct hid_device *hdev; 92 90 }; 93 91 92 + struct apple_backlight_config_report { 93 + u8 report_id; 94 + u8 version; 95 + u16 backlight_off, backlight_on_min, backlight_on_max; 96 + }; 97 + 98 + struct apple_backlight_set_report { 99 + u8 report_id; 100 + u8 version; 101 + u16 backlight; 102 + u16 rate; 103 + }; 104 + 94 105 struct apple_magic_backlight { 95 106 struct led_classdev cdev; 96 107 struct hid_report *brightness; ··· 123 108 struct apple_key_translation { 124 109 u16 from; 125 110 u16 to; 126 - u8 flags; 111 + unsigned long flags; 127 112 }; 128 113 129 114 static const struct apple_key_translation magic_keyboard_alu_fn_keys[] = { ··· 167 152 { } 168 153 }; 169 154 170 - struct apple_backlight_config_report { 171 - u8 report_id; 172 - u8 version; 173 - u16 backlight_off, backlight_on_min, backlight_on_max; 174 - }; 175 - 176 - struct apple_backlight_set_report { 177 - u8 report_id; 178 - u8 version; 179 - u16 backlight; 180 - u16 rate; 181 - }; 182 - 183 - 184 - static const struct apple_key_translation apple2021_fn_keys[] = { 155 + static const struct apple_key_translation magic_keyboard_2021_and_2024_fn_keys[] = { 185 156 { KEY_BACKSPACE, KEY_DELETE }, 186 157 { KEY_ENTER, KEY_INSERT }, 187 158 { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, ··· 213 212 static const struct apple_key_translation macbookpro_no_esc_fn_keys[] = { 214 213 { KEY_BACKSPACE, KEY_DELETE }, 215 214 { KEY_ENTER, KEY_INSERT }, 216 - { KEY_GRAVE, KEY_ESC }, 217 - { KEY_1, KEY_F1 }, 218 - { KEY_2, KEY_F2 }, 219 - { KEY_3, KEY_F3 }, 220 - { KEY_4, KEY_F4 }, 221 - { KEY_5, KEY_F5 }, 222 - { KEY_6, KEY_F6 }, 223 - { KEY_7, KEY_F7 }, 224 - { KEY_8, KEY_F8 }, 225 - { KEY_9, KEY_F9 }, 226 - { KEY_0, KEY_F10 }, 227 - { KEY_MINUS, KEY_F11 }, 228 - { KEY_EQUAL, KEY_F12 }, 215 + { KEY_GRAVE, KEY_ESC, APPLE_FLAG_TB_FKEY }, 216 + { KEY_1, KEY_F1, APPLE_FLAG_TB_FKEY }, 217 + { KEY_2, KEY_F2, APPLE_FLAG_TB_FKEY }, 218 + { KEY_3, KEY_F3, APPLE_FLAG_TB_FKEY }, 219 + { KEY_4, KEY_F4, APPLE_FLAG_TB_FKEY }, 220 + { KEY_5, KEY_F5, APPLE_FLAG_TB_FKEY }, 221 + { KEY_6, KEY_F6, APPLE_FLAG_TB_FKEY }, 222 + { KEY_7, KEY_F7, APPLE_FLAG_TB_FKEY }, 223 + { KEY_8, KEY_F8, APPLE_FLAG_TB_FKEY }, 224 + { KEY_9, KEY_F9, APPLE_FLAG_TB_FKEY }, 225 + { KEY_0, KEY_F10, APPLE_FLAG_TB_FKEY }, 226 + { KEY_MINUS, KEY_F11, APPLE_FLAG_TB_FKEY }, 227 + { KEY_EQUAL, KEY_F12, APPLE_FLAG_TB_FKEY }, 229 228 { KEY_UP, KEY_PAGEUP }, 230 229 { KEY_DOWN, KEY_PAGEDOWN }, 231 230 { KEY_LEFT, KEY_HOME }, ··· 236 235 static const struct apple_key_translation macbookpro_dedicated_esc_fn_keys[] = { 237 236 { KEY_BACKSPACE, KEY_DELETE }, 238 237 { KEY_ENTER, KEY_INSERT }, 239 - { KEY_1, KEY_F1 }, 240 - { KEY_2, KEY_F2 }, 241 - { KEY_3, KEY_F3 }, 242 - { KEY_4, KEY_F4 }, 243 - { KEY_5, KEY_F5 }, 244 - { KEY_6, KEY_F6 }, 245 - { KEY_7, KEY_F7 }, 246 - { KEY_8, KEY_F8 }, 247 - { KEY_9, KEY_F9 }, 248 - { KEY_0, KEY_F10 }, 249 - { KEY_MINUS, KEY_F11 }, 250 - { KEY_EQUAL, KEY_F12 }, 238 + { KEY_1, KEY_F1, APPLE_FLAG_TB_FKEY }, 239 + { KEY_2, KEY_F2, APPLE_FLAG_TB_FKEY }, 240 + { KEY_3, KEY_F3, APPLE_FLAG_TB_FKEY }, 241 + { KEY_4, KEY_F4, APPLE_FLAG_TB_FKEY }, 242 + { KEY_5, KEY_F5, APPLE_FLAG_TB_FKEY }, 243 + { KEY_6, KEY_F6, APPLE_FLAG_TB_FKEY }, 244 + { KEY_7, KEY_F7, APPLE_FLAG_TB_FKEY }, 245 + { KEY_8, KEY_F8, APPLE_FLAG_TB_FKEY }, 246 + { KEY_9, KEY_F9, APPLE_FLAG_TB_FKEY }, 247 + { KEY_0, KEY_F10, APPLE_FLAG_TB_FKEY }, 248 + { KEY_MINUS, KEY_F11, APPLE_FLAG_TB_FKEY }, 249 + { KEY_EQUAL, KEY_F12, APPLE_FLAG_TB_FKEY }, 251 250 { KEY_UP, KEY_PAGEUP }, 252 251 { KEY_DOWN, KEY_PAGEDOWN }, 253 252 { KEY_LEFT, KEY_HOME }, ··· 426 425 unsigned int real_fnmode; 427 426 428 427 if (fnmode == 3) { 429 - real_fnmode = (asc->quirks & APPLE_IS_NON_APPLE) ? 2 : 1; 428 + if (asc->quirks & APPLE_DISABLE_FKEYS) 429 + real_fnmode = 4; 430 + else if (asc->quirks & APPLE_IS_NON_APPLE) 431 + real_fnmode = 2; 432 + else 433 + real_fnmode = 1; 430 434 } else { 431 435 real_fnmode = fnmode; 432 436 } ··· 472 466 asc->fn_on = !!value; 473 467 474 468 if (real_fnmode) { 475 - if (hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI || 476 - hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO || 477 - hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS || 478 - hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI || 479 - hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO || 480 - hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS || 481 - hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI || 482 - hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO || 483 - hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS) 469 + switch (hid->product) { 470 + case USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI: 471 + case USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO: 472 + case USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS: 473 + case USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI: 474 + case USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO: 475 + case USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS: 476 + case USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI: 477 + case USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO: 478 + case USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS: 484 479 table = magic_keyboard_alu_fn_keys; 485 - else if (hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2015 || 486 - hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2015) 480 + break; 481 + case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2015: 482 + case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2015: 487 483 table = magic_keyboard_2015_fn_keys; 488 - else if (hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021 || 489 - hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2024 || 490 - hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021 || 491 - hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021) 492 - table = apple2021_fn_keys; 493 - else if (hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132 || 494 - hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680 || 495 - hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213) 496 - table = macbookpro_no_esc_fn_keys; 497 - else if (hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K || 498 - hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223 || 499 - hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F) 500 - table = macbookpro_dedicated_esc_fn_keys; 501 - else if (hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K || 502 - hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K) 503 - table = apple_fn_keys; 504 - else if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI && 505 - hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) 506 - table = macbookair_fn_keys; 507 - else if (hid->product < 0x21d || hid->product >= 0x300) 508 - table = powerbook_fn_keys; 509 - else 484 + break; 485 + case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021: 486 + case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021: 487 + case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021: 488 + case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2024: 489 + case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2024: 490 + case USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2024: 491 + table = magic_keyboard_2021_and_2024_fn_keys; 492 + break; 493 + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132: 494 + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213: 495 + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680: 496 + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT: 497 + table = macbookpro_no_esc_fn_keys; 498 + break; 499 + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F: 500 + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K: 501 + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223: 502 + table = macbookpro_dedicated_esc_fn_keys; 503 + break; 504 + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K: 505 + case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K: 510 506 table = apple_fn_keys; 507 + break; 508 + default: 509 + if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI && 510 + hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) 511 + table = macbookair_fn_keys; 512 + else if (hid->product < 0x21d || hid->product >= 0x300) 513 + table = powerbook_fn_keys; 514 + else 515 + table = apple_fn_keys; 516 + } 511 517 512 518 trans = apple_find_translation(table, code); 513 519 ··· 542 524 do_translate = asc->fn_on; 543 525 break; 544 526 default: 545 - /* should never happen */ 527 + /* case 4 */ 546 528 do_translate = false; 529 + } 530 + } else if (trans->flags & APPLE_FLAG_TB_FKEY) { 531 + switch (real_fnmode) { 532 + case 4: 533 + do_translate = false; 534 + break; 535 + default: 536 + do_translate = asc->fn_on; 547 537 } 548 538 } else { 549 539 do_translate = asc->fn_on; ··· 645 619 646 620 if (apple_fetch_battery(hdev) == 0) { 647 621 mod_timer(&asc->battery_timer, 648 - jiffies + msecs_to_jiffies(APPLE_BATTERY_TIMEOUT_MS)); 622 + jiffies + secs_to_jiffies(APPLE_BATTERY_TIMEOUT_SEC)); 649 623 } 650 624 } 651 625 ··· 708 682 apple_setup_key_translation(input, apple_iso_keyboard); 709 683 apple_setup_key_translation(input, magic_keyboard_alu_fn_keys); 710 684 apple_setup_key_translation(input, magic_keyboard_2015_fn_keys); 711 - apple_setup_key_translation(input, apple2021_fn_keys); 685 + apple_setup_key_translation(input, magic_keyboard_2021_and_2024_fn_keys); 712 686 apple_setup_key_translation(input, macbookpro_no_esc_fn_keys); 713 687 apple_setup_key_translation(input, macbookpro_dedicated_esc_fn_keys); 714 688 } ··· 916 890 backlight->brightness = report_enum->report_id_hash[APPLE_MAGIC_REPORT_ID_BRIGHTNESS]; 917 891 backlight->power = report_enum->report_id_hash[APPLE_MAGIC_REPORT_ID_POWER]; 918 892 919 - if (!backlight->brightness || !backlight->power) 893 + if (!backlight->brightness || backlight->brightness->maxfield < 2 || 894 + !backlight->power || backlight->power->maxfield < 2) 920 895 return -ENODEV; 921 896 922 897 backlight->cdev.name = ":white:" LED_FUNCTION_KBD_BACKLIGHT; ··· 960 933 return ret; 961 934 } 962 935 963 - timer_setup(&asc->battery_timer, apple_battery_timer_tick, 0); 964 - mod_timer(&asc->battery_timer, 965 - jiffies + msecs_to_jiffies(APPLE_BATTERY_TIMEOUT_MS)); 966 - apple_fetch_battery(hdev); 936 + if (quirks & APPLE_RDESC_BATTERY) { 937 + timer_setup(&asc->battery_timer, apple_battery_timer_tick, 0); 938 + mod_timer(&asc->battery_timer, 939 + jiffies + secs_to_jiffies(APPLE_BATTERY_TIMEOUT_SEC)); 940 + apple_fetch_battery(hdev); 941 + } 967 942 968 943 if (quirks & APPLE_BACKLIGHT_CTL) 969 944 apple_backlight_init(hdev); ··· 979 950 return 0; 980 951 981 952 out_err: 982 - timer_delete_sync(&asc->battery_timer); 953 + if (quirks & APPLE_RDESC_BATTERY) 954 + timer_delete_sync(&asc->battery_timer); 955 + 983 956 hid_hw_stop(hdev); 984 957 return ret; 985 958 } ··· 990 959 { 991 960 struct apple_sc *asc = hid_get_drvdata(hdev); 992 961 993 - timer_delete_sync(&asc->battery_timer); 962 + if (asc->quirks & APPLE_RDESC_BATTERY) 963 + timer_delete_sync(&asc->battery_timer); 994 964 995 965 hid_hw_stop(hdev); 996 966 } ··· 1161 1129 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K), 1162 1130 .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK }, 1163 1131 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132), 1164 - .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK }, 1132 + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK | 1133 + APPLE_DISABLE_FKEYS }, 1165 1134 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680), 1166 - .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK }, 1135 + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK | 1136 + APPLE_DISABLE_FKEYS }, 1137 + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT), 1138 + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK | 1139 + APPLE_DISABLE_FKEYS }, 1167 1140 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213), 1168 - .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK }, 1141 + .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK | 1142 + APPLE_DISABLE_FKEYS }, 1169 1143 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K), 1170 - .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 1144 + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_DISABLE_FKEYS }, 1171 1145 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223), 1172 - .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 1146 + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_DISABLE_FKEYS }, 1173 1147 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K), 1174 1148 .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 1175 1149 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F), 1176 - .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 1150 + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_DISABLE_FKEYS }, 1177 1151 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), 1178 1152 .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, 1179 1153 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), ··· 1195 1157 .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY }, 1196 1158 { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021), 1197 1159 .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 1198 - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2024), 1199 - .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY }, 1200 - { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2024), 1201 - .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 1202 1160 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021), 1203 1161 .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY }, 1204 1162 { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021), ··· 1202 1168 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021), 1203 1169 .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY }, 1204 1170 { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021), 1171 + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 1172 + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2024), 1173 + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY }, 1174 + { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2024), 1175 + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 1176 + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2024), 1177 + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY }, 1178 + { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2024), 1179 + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 1180 + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2024), 1181 + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY }, 1182 + { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2024), 1205 1183 .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 1206 1184 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT), 1207 1185 .driver_data = APPLE_MAGIC_BACKLIGHT },
+8 -4
drivers/hid/hid-core.c
··· 66 66 67 67 static u32 s32ton(__s32 value, unsigned int n) 68 68 { 69 - s32 a = value >> (n - 1); 69 + s32 a; 70 70 71 + if (!value || !n) 72 + return 0; 73 + 74 + a = value >> (n - 1); 71 75 if (a && a != -1) 72 76 return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1; 73 77 return value & ((1 << n) - 1); ··· 663 659 default: 664 660 if (item->tag >= HID_MAIN_ITEM_TAG_RESERVED_MIN && 665 661 item->tag <= HID_MAIN_ITEM_TAG_RESERVED_MAX) 666 - hid_warn(parser->device, "reserved main item tag 0x%x\n", item->tag); 662 + hid_warn_ratelimited(parser->device, "reserved main item tag 0x%x\n", item->tag); 667 663 else 668 - hid_warn(parser->device, "unknown main item tag 0x%x\n", item->tag); 664 + hid_warn_ratelimited(parser->device, "unknown main item tag 0x%x\n", item->tag); 669 665 ret = 0; 670 666 } 671 667 ··· 2813 2809 { 2814 2810 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 2815 2811 2816 - return scnprintf(buf, PAGE_SIZE, "hid:b%04Xg%04Xv%08Xp%08X\n", 2812 + return sysfs_emit(buf, "hid:b%04Xg%04Xv%08Xp%08X\n", 2817 2813 hdev->bus, hdev->group, hdev->vendor, hdev->product); 2818 2814 } 2819 2815 static DEVICE_ATTR_RO(modalias);
+1 -1
drivers/hid/hid-debug.c
··· 3726 3726 */ 3727 3727 if (!list->hdev || !list->hdev->debug) { 3728 3728 ret = -EIO; 3729 - set_current_state(TASK_RUNNING); 3729 + __set_current_state(TASK_RUNNING); 3730 3730 goto out; 3731 3731 } 3732 3732
+17 -13
drivers/hid/hid-ids.h
··· 167 167 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS 0x0257 168 168 #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2015 0x0267 169 169 #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2015 0x026c 170 + #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021 0x029c 171 + #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021 0x029a 172 + #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021 0x029f 173 + #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2024 0x0320 174 + #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2024 0x0321 175 + #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2024 0x0322 170 176 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI 0x0290 171 177 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO 0x0291 172 178 #define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS 0x0292 173 179 #define USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI 0x0272 174 180 #define USB_DEVICE_ID_APPLE_WELLSPRING9_ISO 0x0273 175 181 #define USB_DEVICE_ID_APPLE_WELLSPRING9_JIS 0x0274 176 - #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K 0x027a 177 - #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132 0x027b 178 - #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680 0x027c 179 - #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213 0x027d 180 - #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K 0x027e 181 - #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223 0x027f 182 - #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K 0x0280 183 - #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F 0x0340 182 + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K 0x027a 183 + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132 0x027b 184 + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680 0x027c 185 + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT 0x0278 186 + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213 0x027d 187 + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K 0x027e 188 + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223 0x027f 189 + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K 0x0280 190 + #define USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F 0x0340 184 191 #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a 185 192 #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b 186 193 #define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240 ··· 195 188 #define USB_DEVICE_ID_APPLE_IRCONTROL3 0x8241 196 189 #define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242 197 190 #define USB_DEVICE_ID_APPLE_IRCONTROL5 0x8243 198 - #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021 0x029c 199 - #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2024 0x0320 200 - #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021 0x029a 201 - #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021 0x029f 202 191 #define USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT 0x8102 203 192 #define USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY 0x8302 204 193 ··· 849 846 #define USB_DEVICE_ID_PXN_V12 0x1212 850 847 #define USB_DEVICE_ID_PXN_V12_LITE 0x1112 851 848 #define USB_DEVICE_ID_PXN_V12_LITE_2 0x1211 852 - #define USB_DEVICE_LITE_STAR_GT987_FF 0x2141 849 + #define USB_DEVICE_ID_LITE_STAR_GT987 0x2141 853 850 854 851 #define USB_VENDOR_ID_LOGITECH 0x046d 855 852 #define USB_DEVICE_ID_LOGITECH_Z_10_SPK 0x0a07 ··· 1409 1406 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S 0x0909 1410 1407 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_SW 0x0933 1411 1408 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06 0x0078 1409 + #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_22R_PRO 0x091b 1412 1410 #define USB_DEVICE_ID_UGEE_TABLET_G5 0x0074 1413 1411 #define USB_DEVICE_ID_UGEE_TABLET_EX07S 0x0071 1414 1412 #define USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720 0x0055
+3 -3
drivers/hid/hid-lg4ff.c
··· 956 956 return 0; 957 957 } 958 958 959 - count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->wdata.combine); 959 + count = sysfs_emit(buf, "%u\n", entry->wdata.combine); 960 960 return count; 961 961 } 962 962 ··· 1009 1009 return 0; 1010 1010 } 1011 1011 1012 - count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->wdata.range); 1012 + count = sysfs_emit(buf, "%u\n", entry->wdata.range); 1013 1013 return count; 1014 1014 } 1015 1015 ··· 1073 1073 return 0; 1074 1074 } 1075 1075 1076 - count = scnprintf(buf, PAGE_SIZE, "%s: %s\n", entry->wdata.real_tag, entry->wdata.real_name); 1076 + count = sysfs_emit(buf, "%s: %s\n", entry->wdata.real_tag, entry->wdata.real_name); 1077 1077 return count; 1078 1078 } 1079 1079
+40 -24
drivers/hid/hid-magicmouse.c
··· 60 60 #define MOUSE_REPORT_ID 0x29 61 61 #define MOUSE2_REPORT_ID 0x12 62 62 #define DOUBLE_REPORT_ID 0xf7 63 - #define USB_BATTERY_TIMEOUT_MS 60000 63 + #define USB_BATTERY_TIMEOUT_SEC 60 64 64 65 65 /* These definitions are not precise, but they're close enough. (Bits 66 66 * 0x03 seem to indicate the aspect ratio of the touch, bits 0x70 seem ··· 791 791 hid_err(msc->hdev, "unable to request touch data (%d)\n", ret); 792 792 } 793 793 794 + static bool is_usb_magicmouse2(__u32 vendor, __u32 product) 795 + { 796 + if (vendor != USB_VENDOR_ID_APPLE) 797 + return false; 798 + return product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 || 799 + product == USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC; 800 + } 801 + 802 + static bool is_usb_magictrackpad2(__u32 vendor, __u32 product) 803 + { 804 + if (vendor != USB_VENDOR_ID_APPLE) 805 + return false; 806 + return product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 || 807 + product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC; 808 + } 809 + 794 810 static int magicmouse_fetch_battery(struct hid_device *hdev) 795 811 { 796 812 #ifdef CONFIG_HID_BATTERY_STRENGTH 797 813 struct hid_report_enum *report_enum; 798 814 struct hid_report *report; 799 815 800 - if (!hdev->battery || hdev->vendor != USB_VENDOR_ID_APPLE || 801 - (hdev->product != USB_DEVICE_ID_APPLE_MAGICMOUSE2 && 802 - hdev->product != USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC && 803 - hdev->product != USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 && 804 - hdev->product != USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC)) 816 + if (!hdev->battery || 817 + (!is_usb_magicmouse2(hdev->vendor, hdev->product) && 818 + !is_usb_magictrackpad2(hdev->vendor, hdev->product))) 805 819 return -1; 806 820 807 821 report_enum = &hdev->report_enum[hdev->battery_report_type]; ··· 841 827 842 828 if (magicmouse_fetch_battery(hdev) == 0) { 843 829 mod_timer(&msc->battery_timer, 844 - jiffies + msecs_to_jiffies(USB_BATTERY_TIMEOUT_MS)); 830 + jiffies + secs_to_jiffies(USB_BATTERY_TIMEOUT_SEC)); 845 831 } 846 832 } 847 833 ··· 877 863 return ret; 878 864 } 879 865 880 - timer_setup(&msc->battery_timer, magicmouse_battery_timer_tick, 0); 881 - mod_timer(&msc->battery_timer, 882 - jiffies + msecs_to_jiffies(USB_BATTERY_TIMEOUT_MS)); 883 - magicmouse_fetch_battery(hdev); 866 + if (is_usb_magicmouse2(id->vendor, id->product) || 867 + is_usb_magictrackpad2(id->vendor, id->product)) { 868 + timer_setup(&msc->battery_timer, magicmouse_battery_timer_tick, 0); 869 + mod_timer(&msc->battery_timer, 870 + jiffies + secs_to_jiffies(USB_BATTERY_TIMEOUT_SEC)); 871 + magicmouse_fetch_battery(hdev); 872 + } 884 873 885 - if (id->vendor == USB_VENDOR_ID_APPLE && 886 - (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 || 887 - id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC || 888 - ((id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 || 889 - id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) && 890 - hdev->type != HID_TYPE_USBMOUSE))) 874 + if (is_usb_magicmouse2(id->vendor, id->product) || 875 + (is_usb_magictrackpad2(id->vendor, id->product) && 876 + hdev->type != HID_TYPE_USBMOUSE)) 891 877 return 0; 892 878 893 879 if (!msc->input) { ··· 950 936 951 937 return 0; 952 938 err_stop_hw: 953 - timer_delete_sync(&msc->battery_timer); 939 + if (is_usb_magicmouse2(id->vendor, id->product) || 940 + is_usb_magictrackpad2(id->vendor, id->product)) 941 + timer_delete_sync(&msc->battery_timer); 942 + 954 943 hid_hw_stop(hdev); 955 944 return ret; 956 945 } ··· 964 947 965 948 if (msc) { 966 949 cancel_delayed_work_sync(&msc->work); 967 - timer_delete_sync(&msc->battery_timer); 950 + if (is_usb_magicmouse2(hdev->vendor, hdev->product) || 951 + is_usb_magictrackpad2(hdev->vendor, hdev->product)) 952 + timer_delete_sync(&msc->battery_timer); 968 953 } 969 954 970 955 hid_hw_stop(hdev); ··· 983 964 * 0x05, 0x01, // Usage Page (Generic Desktop) 0 984 965 * 0x09, 0x02, // Usage (Mouse) 2 985 966 */ 986 - if (hdev->vendor == USB_VENDOR_ID_APPLE && 987 - (hdev->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 || 988 - hdev->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC || 989 - hdev->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 || 990 - hdev->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) && 967 + if ((is_usb_magicmouse2(hdev->vendor, hdev->product) || 968 + is_usb_magictrackpad2(hdev->vendor, hdev->product)) && 991 969 *rsize == 83 && rdesc[46] == 0x84 && rdesc[58] == 0x85) { 992 970 hid_info(hdev, 993 971 "fixing up magicmouse battery report descriptor\n");
+100 -8
drivers/hid/hid-mcp2221.c
··· 18 18 #include <linux/i2c.h> 19 19 #include <linux/gpio/driver.h> 20 20 #include <linux/iio/iio.h> 21 + #include <linux/minmax.h> 21 22 #include "hid-ids.h" 22 23 23 24 /* Commands codes in a raw output report */ ··· 55 54 MCP2221_ALT_F_NOT_GPIOV = 0xEE, 56 55 MCP2221_ALT_F_NOT_GPIOD = 0xEF, 57 56 }; 57 + 58 + /* MCP SRAM read offsets cmd: MCP2221_GET_SRAM_SETTINGS */ 59 + enum { 60 + MCP2221_SRAM_RD_GP0 = 22, 61 + MCP2221_SRAM_RD_GP1 = 23, 62 + MCP2221_SRAM_RD_GP2 = 24, 63 + MCP2221_SRAM_RD_GP3 = 25, 64 + }; 65 + 66 + /* MCP SRAM write offsets cmd: MCP2221_SET_SRAM_SETTINGS */ 67 + enum { 68 + MCP2221_SRAM_WR_GP_ENA_ALTER = 7, 69 + MCP2221_SRAM_WR_GP0 = 8, 70 + MCP2221_SRAM_WR_GP1 = 9, 71 + MCP2221_SRAM_WR_GP2 = 10, 72 + MCP2221_SRAM_WR_GP3 = 11, 73 + }; 74 + 75 + #define MCP2221_SRAM_GP_DESIGN_MASK 0x07 76 + #define MCP2221_SRAM_GP_DIRECTION_MASK 0x08 77 + #define MCP2221_SRAM_GP_VALUE_MASK 0x10 58 78 59 79 /* MCP GPIO direction encoding */ 60 80 enum { ··· 263 241 264 242 idx = 0; 265 243 sent = 0; 266 - if (msg->len < 60) 267 - len = msg->len; 268 - else 269 - len = 60; 244 + len = min(msg->len, 60); 270 245 271 246 do { 272 247 mcp->txbuf[0] = type; ··· 290 271 break; 291 272 292 273 idx = idx + len; 293 - if ((msg->len - sent) < 60) 294 - len = msg->len - sent; 295 - else 296 - len = 60; 274 + len = min(msg->len - sent, 60); 297 275 298 276 /* 299 277 * Testing shows delay is needed between successive writes ··· 623 607 }; 624 608 625 609 #if IS_REACHABLE(CONFIG_GPIOLIB) 610 + static int mcp_gpio_read_sram(struct mcp2221 *mcp) 611 + { 612 + int ret; 613 + 614 + memset(mcp->txbuf, 0, 64); 615 + mcp->txbuf[0] = MCP2221_GET_SRAM_SETTINGS; 616 + 617 + mutex_lock(&mcp->lock); 618 + ret = mcp_send_data_req_status(mcp, mcp->txbuf, 64); 619 + mutex_unlock(&mcp->lock); 620 + 621 + return ret; 622 + } 623 + 624 + /* 625 + * If CONFIG_IIO is not enabled, check for the gpio pins 626 + * if they are in gpio mode. For the ones which are not 627 + * in gpio mode, set them into gpio mode. 628 + */ 629 + static int mcp2221_check_gpio_pinfunc(struct mcp2221 *mcp) 630 + { 631 + int i; 632 + int needgpiofix = 0; 633 + int ret; 634 + 635 + if (IS_ENABLED(CONFIG_IIO)) 636 + return 0; 637 + 638 + ret = mcp_gpio_read_sram(mcp); 639 + if (ret) 640 + return ret; 641 + 642 + for (i = 0; i < MCP_NGPIO; i++) { 643 + if ((mcp->mode[i] & MCP2221_SRAM_GP_DESIGN_MASK) != 0x0) { 644 + dev_warn(&mcp->hdev->dev, 645 + "GPIO %d not in gpio mode\n", i); 646 + needgpiofix = 1; 647 + } 648 + } 649 + 650 + if (!needgpiofix) 651 + return 0; 652 + 653 + /* 654 + * Set all bytes to 0, so Bit 7 is not set. The chip 655 + * only changes content of a register when bit 7 is set. 656 + */ 657 + memset(mcp->txbuf, 0, 64); 658 + mcp->txbuf[0] = MCP2221_SET_SRAM_SETTINGS; 659 + 660 + /* 661 + * Set bit 7 in MCP2221_SRAM_WR_GP_ENA_ALTER to enable 662 + * loading of a new set of gpio settings to GP SRAM 663 + */ 664 + mcp->txbuf[MCP2221_SRAM_WR_GP_ENA_ALTER] = 0x80; 665 + for (i = 0; i < MCP_NGPIO; i++) { 666 + if ((mcp->mode[i] & MCP2221_SRAM_GP_DESIGN_MASK) == 0x0) { 667 + /* write current GPIO mode */ 668 + mcp->txbuf[MCP2221_SRAM_WR_GP0 + i] = mcp->mode[i]; 669 + } else { 670 + /* pin is not in gpio mode, set it to input mode */ 671 + mcp->txbuf[MCP2221_SRAM_WR_GP0 + i] = 0x08; 672 + dev_warn(&mcp->hdev->dev, 673 + "Set GPIO mode for gpio pin %d!\n", i); 674 + } 675 + } 676 + 677 + mutex_lock(&mcp->lock); 678 + ret = mcp_send_data_req_status(mcp, mcp->txbuf, 64); 679 + mutex_unlock(&mcp->lock); 680 + 681 + return ret; 682 + } 683 + 626 684 static int mcp_gpio_get(struct gpio_chip *gc, 627 685 unsigned int offset) 628 686 { ··· 1308 1218 ret = devm_gpiochip_add_data(&hdev->dev, mcp->gc, mcp); 1309 1219 if (ret) 1310 1220 return ret; 1221 + 1222 + mcp2221_check_gpio_pinfunc(mcp); 1311 1223 #endif 1312 1224 1313 1225 #if IS_REACHABLE(CONFIG_IIO)
+57 -5
drivers/hid/hid-multitouch.c
··· 73 73 #define MT_QUIRK_FORCE_MULTI_INPUT BIT(20) 74 74 #define MT_QUIRK_DISABLE_WAKEUP BIT(21) 75 75 #define MT_QUIRK_ORIENTATION_INVERT BIT(22) 76 + #define MT_QUIRK_APPLE_TOUCHBAR BIT(23) 76 77 77 78 #define MT_INPUTMODE_TOUCHSCREEN 0x02 78 79 #define MT_INPUTMODE_TOUCHPAD 0x03 ··· 221 220 #define MT_CLS_GOOGLE 0x0111 222 221 #define MT_CLS_RAZER_BLADE_STEALTH 0x0112 223 222 #define MT_CLS_SMART_TECH 0x0113 223 + #define MT_CLS_APPLE_TOUCHBAR 0x0114 224 224 #define MT_CLS_SIS 0x0457 225 225 226 226 #define MT_DEFAULT_MAXCONTACT 10 ··· 406 404 MT_QUIRK_IGNORE_DUPLICATES | 407 405 MT_QUIRK_CONTACT_CNT_ACCURATE | 408 406 MT_QUIRK_SEPARATE_APP_REPORT, 407 + }, 408 + { .name = MT_CLS_APPLE_TOUCHBAR, 409 + .quirks = MT_QUIRK_HOVERING | 410 + MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE | 411 + MT_QUIRK_APPLE_TOUCHBAR, 412 + .maxcontacts = 11, 409 413 }, 410 414 { .name = MT_CLS_SIS, 411 415 .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | ··· 633 625 static struct mt_report_data *mt_allocate_report_data(struct mt_device *td, 634 626 struct hid_report *report) 635 627 { 628 + struct mt_class *cls = &td->mtclass; 636 629 struct mt_report_data *rdata; 637 630 struct hid_field *field; 638 631 int r, n; ··· 658 649 659 650 if (field->logical == HID_DG_FINGER || td->hdev->group != HID_GROUP_MULTITOUCH_WIN_8) { 660 651 for (n = 0; n < field->report_count; n++) { 661 - if (field->usage[n].hid == HID_DG_CONTACTID) { 652 + unsigned int hid = field->usage[n].hid; 653 + 654 + if (hid == HID_DG_CONTACTID || 655 + (cls->quirks & MT_QUIRK_APPLE_TOUCHBAR && 656 + hid == HID_DG_TRANSDUCER_INDEX)) { 662 657 rdata->is_mt_collection = true; 663 658 break; 664 659 } ··· 834 821 835 822 MT_STORE_FIELD(confidence_state); 836 823 return 1; 824 + case HID_DG_TOUCH: 825 + /* 826 + * Legacy devices use TIPSWITCH and not TOUCH. 827 + * One special case here is of the Apple Touch Bars. 828 + * In these devices, the tip state is contained in 829 + * fields with the HID_DG_TOUCH usage. 830 + * Let's just ignore this field for other devices. 831 + */ 832 + if (!(cls->quirks & MT_QUIRK_APPLE_TOUCHBAR)) 833 + return -1; 834 + fallthrough; 837 835 case HID_DG_TIPSWITCH: 838 836 if (field->application != HID_GD_SYSTEM_MULTIAXIS) 839 837 input_set_capability(hi->input, 840 838 EV_KEY, BTN_TOUCH); 841 839 MT_STORE_FIELD(tip_state); 842 840 return 1; 841 + case HID_DG_TRANSDUCER_INDEX: 842 + /* 843 + * Contact ID in case of Apple Touch Bars is contained 844 + * in fields with HID_DG_TRANSDUCER_INDEX usage. 845 + */ 846 + if (!(cls->quirks & MT_QUIRK_APPLE_TOUCHBAR)) 847 + return 0; 848 + fallthrough; 843 849 case HID_DG_CONTACTID: 844 850 MT_STORE_FIELD(contactid); 845 851 app->touches_by_report++; ··· 914 882 return 1; 915 883 case HID_DG_CONTACTMAX: 916 884 /* contact max are global to the report */ 917 - return -1; 918 - case HID_DG_TOUCH: 919 - /* Legacy devices use TIPSWITCH and not TOUCH. 920 - * Let's just ignore this field. */ 921 885 return -1; 922 886 } 923 887 /* let hid-input decide for the others */ ··· 1342 1314 struct input_dev *input = hi->input; 1343 1315 int ret; 1344 1316 1317 + /* 1318 + * HID_DG_CONTACTMAX field is not present on Apple Touch Bars, 1319 + * but the maximum contact count is greater than the default. 1320 + */ 1321 + if (cls->quirks & MT_QUIRK_APPLE_TOUCHBAR && cls->maxcontacts) 1322 + td->maxcontacts = cls->maxcontacts; 1323 + 1345 1324 if (!td->maxcontacts) 1346 1325 td->maxcontacts = MT_DEFAULT_MAXCONTACT; 1347 1326 1348 1327 mt_post_parse(td, app); 1349 1328 if (td->serial_maybe) 1350 1329 mt_post_parse_default_settings(td, app); 1330 + 1331 + /* 1332 + * The application for Apple Touch Bars is HID_DG_TOUCHPAD, 1333 + * but these devices are direct. 1334 + */ 1335 + if (cls->quirks & MT_QUIRK_APPLE_TOUCHBAR) 1336 + app->mt_flags |= INPUT_MT_DIRECT; 1351 1337 1352 1338 if (cls->is_indirect) 1353 1339 app->mt_flags |= INPUT_MT_POINTER; ··· 1865 1823 if (ret != 0) 1866 1824 return ret; 1867 1825 1826 + if (mtclass->name == MT_CLS_APPLE_TOUCHBAR && 1827 + !hid_find_field(hdev, HID_INPUT_REPORT, 1828 + HID_DG_TOUCHPAD, HID_DG_TRANSDUCER_INDEX)) 1829 + return -ENODEV; 1830 + 1868 1831 if (mtclass->quirks & MT_QUIRK_FIX_CONST_CONTACT_ID) 1869 1832 mt_fix_const_fields(hdev, HID_DG_CONTACTID); 1870 1833 ··· 2366 2319 { .driver_data = MT_CLS_NSMU, 2367 2320 MT_USB_DEVICE(USB_VENDOR_ID_XIROKU, 2368 2321 USB_DEVICE_ID_XIROKU_CSR2) }, 2322 + 2323 + /* Apple Touch Bar */ 2324 + { .driver_data = MT_CLS_APPLE_TOUCHBAR, 2325 + HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 2326 + USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY) }, 2369 2327 2370 2328 /* Google MT devices */ 2371 2329 { .driver_data = MT_CLS_GOOGLE,
+1 -8
drivers/hid/hid-quirks.c
··· 314 314 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K) }, 315 315 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132) }, 316 316 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680) }, 317 + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT) }, 317 318 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213) }, 318 319 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K) }, 319 320 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223) }, ··· 974 973 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI) }, 975 974 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) }, 976 975 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) }, 977 - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K) }, 978 - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132) }, 979 - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680) }, 980 - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213) }, 981 - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K) }, 982 - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223) }, 983 - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K) }, 984 - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F) }, 985 976 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, 986 977 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, 987 978 { }
+62 -4
drivers/hid/hid-uclogic-core.c
··· 62 62 return rdesc; 63 63 } 64 64 65 + /* Buttons considered valid tablet pad inputs. */ 66 + static const unsigned int uclogic_extra_input_mapping[] = { 67 + BTN_0, 68 + BTN_1, 69 + BTN_2, 70 + BTN_3, 71 + BTN_4, 72 + BTN_5, 73 + BTN_6, 74 + BTN_7, 75 + BTN_8, 76 + BTN_RIGHT, 77 + BTN_MIDDLE, 78 + BTN_SIDE, 79 + BTN_EXTRA, 80 + BTN_FORWARD, 81 + BTN_BACK, 82 + BTN_B, 83 + BTN_A, 84 + BTN_BASE, 85 + BTN_BASE2, 86 + BTN_X 87 + }; 88 + 65 89 static int uclogic_input_mapping(struct hid_device *hdev, 66 90 struct hid_input *hi, 67 91 struct hid_field *field, ··· 96 72 struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); 97 73 struct uclogic_params *params = &drvdata->params; 98 74 99 - /* Discard invalid pen usages */ 100 - if (params->pen.usage_invalid && (field->application == HID_DG_PEN)) 101 - return -1; 75 + if (field->application == HID_GD_KEYPAD) { 76 + /* 77 + * Remap input buttons to sensible ones that are not invalid. 78 + * This only affects previous behavior for devices with more than ten or so buttons. 79 + */ 80 + const int key = (usage->hid & HID_USAGE) - 1; 81 + 82 + if (key < ARRAY_SIZE(uclogic_extra_input_mapping)) { 83 + hid_map_usage(hi, 84 + usage, 85 + bit, 86 + max, 87 + EV_KEY, 88 + uclogic_extra_input_mapping[key]); 89 + return 1; 90 + } 91 + } else if (field->application == HID_DG_PEN) { 92 + /* Discard invalid pen usages */ 93 + if (params->pen.usage_invalid) 94 + return -1; 95 + } 102 96 103 97 /* Let hid-core decide what to do */ 104 98 return 0; ··· 449 407 450 408 /* If need to, and can, transform the bitmap dial reports */ 451 409 if (frame->bitmap_dial_byte > 0 && frame->bitmap_dial_byte < size) { 452 - if (data[frame->bitmap_dial_byte] == 2) 410 + switch (data[frame->bitmap_dial_byte]) { 411 + case 2: 453 412 data[frame->bitmap_dial_byte] = -1; 413 + break; 414 + 415 + /* Everything below here is for tablets that shove multiple dials into 1 byte */ 416 + case 16: 417 + data[frame->bitmap_dial_byte] = 0; 418 + data[frame->bitmap_second_dial_destination_byte] = 1; 419 + break; 420 + 421 + case 32: 422 + data[frame->bitmap_dial_byte] = 0; 423 + data[frame->bitmap_second_dial_destination_byte] = -1; 424 + break; 425 + } 454 426 } 455 427 456 428 return 0; ··· 602 546 .driver_data = UCLOGIC_MOUSE_FRAME_QUIRK | UCLOGIC_BATTERY_QUIRK }, 603 547 { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, 604 548 USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06) }, 549 + { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, 550 + USB_DEVICE_ID_UGEE_XPPEN_TABLET_22R_PRO) }, 605 551 { } 606 552 }; 607 553 MODULE_DEVICE_TABLE(hid, uclogic_devices);
+133 -1
drivers/hid/hid-uclogic-params.c
··· 103 103 frame->touch_flip_at); 104 104 hid_dbg(hdev, "\t\t.bitmap_dial_byte = %u\n", 105 105 frame->bitmap_dial_byte); 106 + hid_dbg(hdev, "\t\t.bitmap_second_dial_destination_byte = %u\n", 107 + frame->bitmap_second_dial_destination_byte); 106 108 } 107 109 108 110 /** ··· 1343 1341 struct uclogic_params *p) 1344 1342 { 1345 1343 struct uclogic_raw_event_hook *event_hook; 1346 - __u8 reconnect_event[] = { 1344 + static const __u8 reconnect_event[] = { 1347 1345 /* Event received on wireless tablet reconnection */ 1348 1346 0x02, 0xF8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 1349 1347 }; ··· 1525 1523 memcpy(params, &p, sizeof(*params)); 1526 1524 memset(&p, 0, sizeof(p)); 1527 1525 rc = 0; 1526 + cleanup: 1527 + kfree(str_desc); 1528 + uclogic_params_cleanup(&p); 1529 + return rc; 1530 + } 1531 + 1532 + /* 1533 + * uclogic_params_init_ugee_xppen_pro_22r() - Initializes a UGEE XP-Pen Pro 22R tablet device. 1534 + * 1535 + * @hdev: The HID device of the tablet interface to initialize and get 1536 + * parameters from. Cannot be NULL. 1537 + * @params: Parameters to fill in (to be cleaned with 1538 + * uclogic_params_cleanup()). Not modified in case of error. 1539 + * Cannot be NULL. 1540 + * 1541 + * Returns: 1542 + * Zero, if successful. A negative errno code on error. 1543 + */ 1544 + static int uclogic_params_init_ugee_xppen_pro_22r(struct uclogic_params *params, 1545 + struct hid_device *hdev, 1546 + const u8 rdesc_frame_arr[], 1547 + const size_t rdesc_frame_size) 1548 + { 1549 + int rc = 0; 1550 + struct usb_interface *iface; 1551 + __u8 bInterfaceNumber; 1552 + const int str_desc_len = 12; 1553 + u8 *str_desc = NULL; 1554 + __u8 *rdesc_pen = NULL; 1555 + s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; 1556 + enum uclogic_params_frame_type frame_type; 1557 + /* The resulting parameters (noop) */ 1558 + struct uclogic_params p = {0, }; 1559 + 1560 + if (!hdev || !params) { 1561 + rc = -EINVAL; 1562 + goto cleanup; 1563 + } 1564 + 1565 + iface = to_usb_interface(hdev->dev.parent); 1566 + bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; 1567 + 1568 + /* Ignore non-pen interfaces */ 1569 + if (bInterfaceNumber != 2) { 1570 + rc = -EINVAL; 1571 + uclogic_params_init_invalid(&p); 1572 + goto cleanup; 1573 + } 1574 + 1575 + /* 1576 + * Initialize the interface by sending magic data. 1577 + * This magic data is the same as other UGEE v2 tablets. 1578 + */ 1579 + rc = uclogic_probe_interface(hdev, 1580 + uclogic_ugee_v2_probe_arr, 1581 + uclogic_ugee_v2_probe_size, 1582 + uclogic_ugee_v2_probe_endpoint); 1583 + if (rc) { 1584 + uclogic_params_init_invalid(&p); 1585 + goto cleanup; 1586 + } 1587 + 1588 + /** 1589 + * Read the string descriptor containing pen and frame parameters. 1590 + * These are slightly different than typical UGEE v2 devices. 1591 + */ 1592 + rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len); 1593 + if (rc != str_desc_len) { 1594 + rc = (rc < 0) ? rc : -EINVAL; 1595 + hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc); 1596 + uclogic_params_init_invalid(&p); 1597 + goto cleanup; 1598 + } 1599 + 1600 + rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len, 1601 + desc_params, 1602 + ARRAY_SIZE(desc_params), 1603 + &frame_type); 1604 + if (rc) 1605 + goto cleanup; 1606 + 1607 + // str_desc doesn't report the correct amount of buttons, so manually fix it 1608 + desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = 20; 1609 + 1610 + kfree(str_desc); 1611 + str_desc = NULL; 1612 + 1613 + /* Initialize the pen interface */ 1614 + rdesc_pen = uclogic_rdesc_template_apply( 1615 + uclogic_rdesc_ugee_v2_pen_template_arr, 1616 + uclogic_rdesc_ugee_v2_pen_template_size, 1617 + desc_params, ARRAY_SIZE(desc_params)); 1618 + if (!rdesc_pen) { 1619 + rc = -ENOMEM; 1620 + goto cleanup; 1621 + } 1622 + 1623 + p.pen.desc_ptr = rdesc_pen; 1624 + p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size; 1625 + p.pen.id = 0x02; 1626 + p.pen.subreport_list[0].value = 0xf0; 1627 + p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID; 1628 + 1629 + /* Initialize the frame interface */ 1630 + rc = uclogic_params_frame_init_with_desc( 1631 + &p.frame_list[0], 1632 + rdesc_frame_arr, 1633 + rdesc_frame_size, 1634 + UCLOGIC_RDESC_V1_FRAME_ID); 1635 + if (rc < 0) { 1636 + hid_err(hdev, "initializing frame params failed: %d\n", rc); 1637 + goto cleanup; 1638 + } 1639 + 1640 + p.frame_list[0].bitmap_dial_byte = 7; 1641 + p.frame_list[0].bitmap_second_dial_destination_byte = 8; 1642 + 1643 + /* Output parameters */ 1644 + memcpy(params, &p, sizeof(*params)); 1645 + memset(&p, 0, sizeof(p)); 1528 1646 cleanup: 1529 1647 kfree(str_desc); 1530 1648 uclogic_params_cleanup(&p); ··· 1966 1844 hid_warn(hdev, "pen parameters not found"); 1967 1845 uclogic_params_init_invalid(&p); 1968 1846 } 1847 + 1848 + break; 1849 + case VID_PID(USB_VENDOR_ID_UGEE, 1850 + USB_DEVICE_ID_UGEE_XPPEN_TABLET_22R_PRO): 1851 + rc = uclogic_params_init_ugee_xppen_pro_22r(&p, 1852 + hdev, 1853 + uclogic_rdesc_xppen_artist_22r_pro_frame_arr, 1854 + uclogic_rdesc_xppen_artist_22r_pro_frame_size); 1855 + if (rc != 0) 1856 + goto cleanup; 1969 1857 1970 1858 break; 1971 1859 }
+5
drivers/hid/hid-uclogic-params.h
··· 175 175 * counterclockwise, as opposed to the normal 1 and -1. 176 176 */ 177 177 unsigned int bitmap_dial_byte; 178 + /* 179 + * Destination offset for the second bitmap dial byte, if the tablet 180 + * supports a second dial at all. 181 + */ 182 + unsigned int bitmap_second_dial_destination_byte; 178 183 }; 179 184 180 185 /*
+44
drivers/hid/hid-uclogic-rdesc.c
··· 1193 1193 const size_t uclogic_rdesc_xppen_deco01_frame_size = 1194 1194 sizeof(uclogic_rdesc_xppen_deco01_frame_arr); 1195 1195 1196 + /* Fixed report descriptor for XP-Pen Arist 22R Pro frame */ 1197 + const __u8 uclogic_rdesc_xppen_artist_22r_pro_frame_arr[] = { 1198 + 0x05, 0x01, /* Usage Page (Desktop), */ 1199 + 0x09, 0x07, /* Usage (Keypad), */ 1200 + 0xA1, 0x01, /* Collection (Application), */ 1201 + 0x85, UCLOGIC_RDESC_V1_FRAME_ID, 1202 + /* Report ID (Virtual report), */ 1203 + 0x05, 0x0D, /* Usage Page (Digitizer), */ 1204 + 0x09, 0x39, /* Usage (Tablet Function Keys), */ 1205 + 0xA0, /* Collection (Physical), */ 1206 + 0x14, /* Logical Minimum (0), */ 1207 + 0x25, 0x01, /* Logical Maximum (1), */ 1208 + 0x75, 0x01, /* Report Size (1), */ 1209 + 0x95, 0x08, /* Report Count (8), */ 1210 + 0x81, 0x01, /* Input (Constant), */ 1211 + 0x05, 0x09, /* Usage Page (Button), */ 1212 + 0x19, 0x01, /* Usage Minimum (01h), */ 1213 + 0x29, 0x14, /* Usage Maximum (14h), */ 1214 + 0x95, 0x14, /* Report Count (20), */ 1215 + 0x81, 0x02, /* Input (Variable), */ 1216 + 0x95, 0x14, /* Report Count (20), */ 1217 + 0x81, 0x01, /* Input (Constant), */ 1218 + 0x05, 0x01, /* Usage Page (Desktop), */ 1219 + 0x09, 0x38, /* Usage (Wheel), */ 1220 + 0x75, 0x08, /* Report Size (8), */ 1221 + 0x95, 0x01, /* Report Count (1), */ 1222 + 0x15, 0xFF, /* Logical Minimum (-1), */ 1223 + 0x25, 0x08, /* Logical Maximum (8), */ 1224 + 0x81, 0x06, /* Input (Variable, Relative), */ 1225 + 0x05, 0x0C, /* Usage Page (Consumer Devices), */ 1226 + 0x0A, 0x38, 0x02, /* Usage (AC PAN), */ 1227 + 0x95, 0x01, /* Report Count (1), */ 1228 + 0x81, 0x06, /* Input (Variable, Relative), */ 1229 + 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 1230 + 0x75, 0x08, /* Report Size (8), */ 1231 + 0x95, 0x01, /* Report Count (1), */ 1232 + 0x81, 0x02, /* Input (Variable), */ 1233 + 0xC0, /* End Collection */ 1234 + 0xC0, /* End Collection */ 1235 + }; 1236 + 1237 + const size_t uclogic_rdesc_xppen_artist_22r_pro_frame_size = 1238 + sizeof(uclogic_rdesc_xppen_artist_22r_pro_frame_arr); 1239 + 1196 1240 /** 1197 1241 * uclogic_rdesc_template_apply() - apply report descriptor parameters to a 1198 1242 * report descriptor template, creating a report descriptor. Copies the
+4
drivers/hid/hid-uclogic-rdesc.h
··· 210 210 /* Least-significant bit of Ugee G5 frame rotary encoder state */ 211 211 #define UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB 38 212 212 213 + /* Fixed report descriptor for XP-Pen Arist 22R Pro frame */ 214 + extern const __u8 uclogic_rdesc_xppen_artist_22r_pro_frame_arr[]; 215 + extern const size_t uclogic_rdesc_xppen_artist_22r_pro_frame_size; 216 + 213 217 #endif /* _HID_UCLOGIC_RDESC_H */
+3 -2
drivers/hid/hid-universal-pidff.c
··· 57 57 const struct hid_device_id *id) 58 58 { 59 59 int i, error; 60 + 60 61 error = hid_parse(hdev); 61 62 if (error) { 62 63 hid_err(hdev, "HID parse failed\n"); ··· 92 91 93 92 /* Check if HID_PID support is enabled */ 94 93 int (*init_function)(struct hid_device *, u32); 95 - init_function = hid_pidff_init_with_quirks; 96 94 95 + init_function = hid_pidff_init_with_quirks; 97 96 if (!init_function) { 98 97 hid_warn(hdev, "HID_PID support not enabled!\n"); 99 98 return 0; ··· 178 177 .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY }, 179 178 { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE_2), 180 179 .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY }, 181 - { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_LITE_STAR_GT987_FF), 180 + { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_LITE_STAR_GT987), 182 181 .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY }, 183 182 { HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_INVICTA) }, 184 183 { HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_FORTE) },
+1
drivers/hid/intel-thc-hid/Makefile
··· 8 8 obj-$(CONFIG_INTEL_THC_HID) += intel-thc.o 9 9 intel-thc-objs += intel-thc/intel-thc-dev.o 10 10 intel-thc-objs += intel-thc/intel-thc-dma.o 11 + intel-thc-objs += intel-thc/intel-thc-wot.o 11 12 12 13 obj-$(CONFIG_INTEL_QUICKSPI) += intel-quickspi.o 13 14 intel-quickspi-objs += intel-quickspi/pci-quickspi.o
+138 -78
drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
··· 11 11 #include <linux/sizes.h> 12 12 #include <linux/pm_runtime.h> 13 13 14 + #include <linux/gpio/consumer.h> 15 + 14 16 #include "intel-thc-dev.h" 15 17 #include "intel-thc-hw.h" 18 + #include "intel-thc-wot.h" 16 19 17 20 #include "quicki2c-dev.h" 18 21 #include "quicki2c-hid.h" 19 22 #include "quicki2c-protocol.h" 23 + 24 + static struct quicki2c_ddata ptl_ddata = { 25 + .max_detect_size = MAX_RX_DETECT_SIZE_PTL, 26 + }; 20 27 21 28 /* THC QuickI2C ACPI method to get device properties */ 22 29 /* HIDI2C device method */ ··· 34 27 static guid_t thc_platform_guid = 35 28 GUID_INIT(0x84005682, 0x5b71, 0x41a4, 0x8d, 0x66, 0x81, 0x30, 0xf7, 0x87, 0xa1, 0x38); 36 29 30 + /* QuickI2C Wake-on-Touch GPIO resource */ 31 + static const struct acpi_gpio_params wake_gpio = { 0, 0, true }; 32 + 33 + static const struct acpi_gpio_mapping quicki2c_gpios[] = { 34 + { "wake-on-touch", &wake_gpio, 1 }, 35 + { } 36 + }; 37 + 37 38 /** 38 39 * quicki2c_acpi_get_dsm_property - Query device ACPI DSM parameter 39 - * 40 - * @adev: point to ACPI device 40 + * @adev: Point to ACPI device 41 41 * @guid: ACPI method's guid 42 42 * @rev: ACPI method's revision 43 43 * @func: ACPI method's function number 44 44 * @type: ACPI parameter's data type 45 - * @prop_buf: point to return buffer 45 + * @prop_buf: Point to return buffer 46 46 * 47 47 * This is a helper function for device to query its ACPI DSM parameters. 48 48 * 49 - * Return: 0 if success or ENODEV on failed. 49 + * Return: 0 if success or ENODEV on failure. 50 50 */ 51 51 static int quicki2c_acpi_get_dsm_property(struct acpi_device *adev, const guid_t *guid, 52 52 u64 rev, u64 func, acpi_object_type type, void *prop_buf) ··· 81 67 82 68 /** 83 69 * quicki2c_acpi_get_dsd_property - Query device ACPI DSD parameter 84 - * 85 - * @adev: point to ACPI device 70 + * @adev: Point to ACPI device 86 71 * @dsd_method_name: ACPI method's property name 87 72 * @type: ACPI parameter's data type 88 - * @prop_buf: point to return buffer 73 + * @prop_buf: Point to return buffer 89 74 * 90 75 * This is a helper function for device to query its ACPI DSD parameters. 91 76 * ··· 113 100 } 114 101 115 102 /** 116 - * quicki2c_get_acpi_resources - Query all quicki2c devices' ACPI parameters 103 + * quicki2c_get_acpi_resources - Query all QuickI2C devices' ACPI parameters 104 + * @qcdev: Point to quicki2c_device structure 117 105 * 118 - * @qcdev: point to quicki2c device 106 + * This function gets all QuickI2C devices' ACPI resource. 119 107 * 120 - * This function gets all quicki2c devices' ACPI resource. 121 - * 122 - * Return: 0 if success or error code on failed. 108 + * Return: 0 if success or error code on failure. 123 109 */ 124 110 static int quicki2c_get_acpi_resources(struct quicki2c_device *qcdev) 125 111 { ··· 204 192 } 205 193 206 194 /** 207 - * quicki2c_irq_quick_handler - The ISR of the quicki2c driver 208 - * 195 + * quicki2c_irq_quick_handler - The ISR of the QuickI2C driver 209 196 * @irq: The irq number 210 - * @dev_id: pointer to the device structure 197 + * @dev_id: Pointer to the quicki2c_device structure 211 198 * 212 199 * Return: IRQ_WAKE_THREAD if further process needed. 213 200 */ ··· 225 214 226 215 /** 227 216 * try_recover - Try to recovery THC and Device 228 - * @qcdev: pointer to quicki2c device 217 + * @qcdev: Pointer to quicki2c_device structure 229 218 * 230 - * This function is a error handler, called when fatal error happens. 231 - * It try to reset Touch Device and re-configure THC to recovery 232 - * transferring between Device and THC. 219 + * This function is an error handler, called when fatal error happens. 220 + * It try to reset touch device and re-configure THC to recovery 221 + * communication between touch device and THC. 233 222 * 234 - * Return: 0 if successful or error code on failed 223 + * Return: 0 if successful or error code on failure 235 224 */ 236 225 static int try_recover(struct quicki2c_device *qcdev) 237 226 { ··· 275 264 continue; 276 265 } 277 266 278 - /* discard samples before driver probe complete */ 267 + /* Discard samples before driver probe complete */ 279 268 if (qcdev->state != QUICKI2C_ENABLED) 280 269 continue; 281 270 ··· 287 276 } 288 277 289 278 /** 290 - * quicki2c_irq_thread_handler - IRQ thread handler of quicki2c driver 291 - * 279 + * quicki2c_irq_thread_handler - IRQ thread handler of QuickI2C driver 292 280 * @irq: The IRQ number 293 - * @dev_id: pointer to the quicki2c device structure 281 + * @dev_id: Pointer to the quicki2c_device structure 294 282 * 295 283 * Return: IRQ_HANDLED to finish this handler. 296 284 */ ··· 335 325 } 336 326 337 327 /** 338 - * quicki2c_dev_init - Initialize quicki2c device 328 + * quicki2c_dev_init - Initialize QuickI2C device 329 + * @pdev: Pointer to the THC PCI device 330 + * @mem_addr: The Pointer of MMIO memory address 331 + * @ddata: Point to quicki2c_ddata structure 339 332 * 340 - * @pdev: pointer to the thc pci device 341 - * @mem_addr: The pointer of MMIO memory address 342 - * 343 - * Alloc quicki2c device structure and initialized THC device, 333 + * Alloc quicki2c_device structure and initialized THC device, 344 334 * then configure THC to HIDI2C mode. 345 335 * 346 336 * If success, enable THC hardware interrupt. 347 337 * 348 - * Return: pointer to the quicki2c device structure if success 349 - * or NULL on failed. 338 + * Return: Pointer to the quicki2c_device structure if success 339 + * or NULL on failure. 350 340 */ 351 - static struct quicki2c_device *quicki2c_dev_init(struct pci_dev *pdev, void __iomem *mem_addr) 341 + static struct quicki2c_device *quicki2c_dev_init(struct pci_dev *pdev, void __iomem *mem_addr, 342 + const struct quicki2c_ddata *ddata) 352 343 { 353 344 struct device *dev = &pdev->dev; 354 345 struct quicki2c_device *qcdev; ··· 363 352 qcdev->dev = dev; 364 353 qcdev->mem_addr = mem_addr; 365 354 qcdev->state = QUICKI2C_DISABLED; 355 + qcdev->ddata = ddata; 366 356 367 357 init_waitqueue_head(&qcdev->reset_ack_wq); 368 358 369 - /* thc hw init */ 359 + /* THC hardware init */ 370 360 qcdev->thc_hw = thc_dev_init(qcdev->dev, qcdev->mem_addr); 371 361 if (IS_ERR(qcdev->thc_hw)) { 372 362 ret = PTR_ERR(qcdev->thc_hw); ··· 404 392 405 393 thc_interrupt_enable(qcdev->thc_hw, true); 406 394 395 + thc_wot_config(qcdev->thc_hw, &quicki2c_gpios[0]); 396 + 407 397 qcdev->state = QUICKI2C_INITED; 408 398 409 399 return qcdev; 410 400 } 411 401 412 402 /** 413 - * quicki2c_dev_deinit - De-initialize quicki2c device 414 - * 415 - * @qcdev: pointer to the quicki2c device structure 403 + * quicki2c_dev_deinit - De-initialize QuickI2C device 404 + * @qcdev: Pointer to the quicki2c_device structure 416 405 * 417 406 * Disable THC interrupt and deinitilize THC. 418 407 */ ··· 421 408 { 422 409 thc_interrupt_enable(qcdev->thc_hw, false); 423 410 thc_ltr_unconfig(qcdev->thc_hw); 411 + thc_wot_unconfig(qcdev->thc_hw); 424 412 425 413 qcdev->state = QUICKI2C_DISABLED; 426 414 } 427 415 428 416 /** 429 - * quicki2c_dma_init - Configure THC DMA for quicki2c device 430 - * @qcdev: pointer to the quicki2c device structure 417 + * quicki2c_dma_adv_enable - Configure and enable DMA advanced features 418 + * @qcdev: Pointer to the quicki2c_device structure 419 + * 420 + * If platform supports THC DMA advanced features, such as max input size 421 + * control or interrupt delay, configures and enables them. 422 + */ 423 + static void quicki2c_dma_adv_enable(struct quicki2c_device *qcdev) 424 + { 425 + /* 426 + * If platform supports max input size control feature and touch device 427 + * max input length <= THC detect capability, enable the feature with device 428 + * max input length. 429 + */ 430 + if (qcdev->ddata->max_detect_size >= 431 + le16_to_cpu(qcdev->dev_desc.max_input_len)) { 432 + thc_i2c_set_rx_max_size(qcdev->thc_hw, 433 + le16_to_cpu(qcdev->dev_desc.max_input_len)); 434 + thc_i2c_rx_max_size_enable(qcdev->thc_hw, true); 435 + } 436 + 437 + /* If platform supports interrupt delay feature, enable it with given delay */ 438 + if (qcdev->ddata->interrupt_delay) { 439 + thc_i2c_set_rx_int_delay(qcdev->thc_hw, 440 + qcdev->ddata->interrupt_delay); 441 + thc_i2c_rx_int_delay_enable(qcdev->thc_hw, true); 442 + } 443 + } 444 + 445 + /** 446 + * quicki2c_dma_adv_disable - Disable DMA advanced features 447 + * @qcdev: Pointer to the quicki2c device structure 448 + * 449 + * Disable all DMA advanced features if platform supports. 450 + */ 451 + static void quicki2c_dma_adv_disable(struct quicki2c_device *qcdev) 452 + { 453 + if (qcdev->ddata->max_detect_size) 454 + thc_i2c_rx_max_size_enable(qcdev->thc_hw, false); 455 + 456 + if (qcdev->ddata->interrupt_delay) 457 + thc_i2c_rx_int_delay_enable(qcdev->thc_hw, false); 458 + } 459 + 460 + /** 461 + * quicki2c_dma_init - Configure THC DMA for QuickI2C device 462 + * @qcdev: Pointer to the quicki2c_device structure 431 463 * 432 464 * This function uses TIC's parameters(such as max input length, max output 433 465 * length) to allocate THC DMA buffers and configure THC DMA engines. 434 466 * 435 - * Return: 0 if success or error code on failed. 467 + * Return: 0 if success or error code on failure. 436 468 */ 437 469 static int quicki2c_dma_init(struct quicki2c_device *qcdev) 438 470 { ··· 509 451 return ret; 510 452 } 511 453 512 - return ret; 454 + if (qcdev->ddata) 455 + quicki2c_dma_adv_enable(qcdev); 456 + 457 + return 0; 513 458 } 514 459 515 460 /** 516 - * quicki2c_dma_deinit - Release THC DMA for quicki2c device 517 - * @qcdev: pointer to the quicki2c device structure 461 + * quicki2c_dma_deinit - Release THC DMA for QuickI2C device 462 + * @qcdev: Pointer to the quicki2c_device structure 518 463 * 519 464 * Stop THC DMA engines and release all DMA buffers. 520 465 * ··· 526 465 { 527 466 thc_dma_unconfigure(qcdev->thc_hw); 528 467 thc_dma_release(qcdev->thc_hw); 468 + 469 + if (qcdev->ddata) 470 + quicki2c_dma_adv_disable(qcdev); 529 471 } 530 472 531 473 /** 532 474 * quicki2c_alloc_report_buf - Alloc report buffers 533 - * @qcdev: pointer to the quicki2c device structure 475 + * @qcdev: Pointer to the quicki2c_device structure 534 476 * 535 477 * Allocate report descriptor buffer, it will be used for restore TIC HID 536 478 * report descriptor. ··· 544 480 * Allocate output report buffer, it will be used for store HID output report, 545 481 * such as set feature. 546 482 * 547 - * Return: 0 if success or error code on failed. 483 + * Return: 0 if success or error code on failure. 548 484 */ 549 485 static int quicki2c_alloc_report_buf(struct quicki2c_device *qcdev) 550 486 { ··· 582 518 } 583 519 584 520 /* 585 - * quicki2c_probe: Quicki2c driver probe function 586 - * 587 - * @pdev: point to pci device 588 - * @id: point to pci_device_id structure 521 + * quicki2c_probe: QuickI2C driver probe function 522 + * @pdev: Point to PCI device 523 + * @id: Point to pci_device_id structure 589 524 * 590 525 * This function initializes THC and HIDI2C device, the flow is: 591 - * - do THC pci device initialization 592 - * - query HIDI2C ACPI parameters 593 - * - configure THC to HIDI2C mode 594 - * - go through HIDI2C enumeration flow 595 - * |- read device descriptor 596 - * |- reset HIDI2C device 597 - * - enable THC interrupt and DMA 598 - * - read report descriptor 599 - * - register HID device 600 - * - enable runtime power management 526 + * - Do THC pci device initialization 527 + * - Query HIDI2C ACPI parameters 528 + * - Configure THC to HIDI2C mode 529 + * - Go through HIDI2C enumeration flow 530 + * |- Read device descriptor 531 + * |- Reset HIDI2C device 532 + * - Enable THC interrupt and DMA 533 + * - Read report descriptor 534 + * - Register HID device 535 + * - Enable runtime power management 601 536 * 602 - * Return 0 if success or error code on failed. 537 + * Return 0 if success or error code on failure. 603 538 */ 604 - static int quicki2c_probe(struct pci_dev *pdev, 605 - const struct pci_device_id *id) 539 + static int quicki2c_probe(struct pci_dev *pdev, const struct pci_device_id *id) 606 540 { 541 + const struct quicki2c_ddata *ddata = (const struct quicki2c_ddata *)id->driver_data; 607 542 struct quicki2c_device *qcdev; 608 543 void __iomem *mem_addr; 609 544 int ret; ··· 640 577 641 578 pdev->irq = pci_irq_vector(pdev, 0); 642 579 643 - qcdev = quicki2c_dev_init(pdev, mem_addr); 580 + qcdev = quicki2c_dev_init(pdev, mem_addr, ddata); 644 581 if (IS_ERR(qcdev)) { 645 582 dev_err_once(&pdev->dev, "QuickI2C device init failed\n"); 646 583 ret = PTR_ERR(qcdev); ··· 731 668 732 669 /** 733 670 * quicki2c_remove - Device Removal Routine 671 + * @pdev: Point to PCI device structure 734 672 * 735 - * @pdev: PCI device structure 736 - * 737 - * This is called by the PCI subsystem to alert the driver 738 - * that it should release a PCI device. 673 + * This is called by the PCI subsystem to alert the driver that it should 674 + * release a PCI device. 739 675 */ 740 676 static void quicki2c_remove(struct pci_dev *pdev) 741 677 { ··· 756 694 757 695 /** 758 696 * quicki2c_shutdown - Device Shutdown Routine 697 + * @pdev: Point to PCI device structure 759 698 * 760 - * @pdev: PCI device structure 761 - * 762 - * This is called from the reboot notifier 763 - * it's a simplified version of remove so we go down 764 - * faster. 699 + * This is called from the reboot notifier, it's a simplified version of remove 700 + * so we go down faster. 765 701 */ 766 702 static void quicki2c_shutdown(struct pci_dev *pdev) 767 703 { ··· 990 930 }; 991 931 992 932 static const struct pci_device_id quicki2c_pci_tbl[] = { 993 - {PCI_VDEVICE(INTEL, THC_LNL_DEVICE_ID_I2C_PORT1), }, 994 - {PCI_VDEVICE(INTEL, THC_LNL_DEVICE_ID_I2C_PORT2), }, 995 - {PCI_VDEVICE(INTEL, THC_PTL_H_DEVICE_ID_I2C_PORT1), }, 996 - {PCI_VDEVICE(INTEL, THC_PTL_H_DEVICE_ID_I2C_PORT2), }, 997 - {PCI_VDEVICE(INTEL, THC_PTL_U_DEVICE_ID_I2C_PORT1), }, 998 - {PCI_VDEVICE(INTEL, THC_PTL_U_DEVICE_ID_I2C_PORT2), }, 999 - {} 933 + { PCI_DEVICE_DATA(INTEL, THC_LNL_DEVICE_ID_I2C_PORT1, NULL) }, 934 + { PCI_DEVICE_DATA(INTEL, THC_LNL_DEVICE_ID_I2C_PORT2, NULL) }, 935 + { PCI_DEVICE_DATA(INTEL, THC_PTL_H_DEVICE_ID_I2C_PORT1, &ptl_ddata) }, 936 + { PCI_DEVICE_DATA(INTEL, THC_PTL_H_DEVICE_ID_I2C_PORT2, &ptl_ddata) }, 937 + { PCI_DEVICE_DATA(INTEL, THC_PTL_U_DEVICE_ID_I2C_PORT1, &ptl_ddata) }, 938 + { PCI_DEVICE_DATA(INTEL, THC_PTL_U_DEVICE_ID_I2C_PORT2, &ptl_ddata) }, 939 + { } 1000 940 }; 1001 941 MODULE_DEVICE_TABLE(pci, quicki2c_pci_tbl); 1002 942
+36 -19
drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h
··· 7 7 #include <linux/hid-over-i2c.h> 8 8 #include <linux/workqueue.h> 9 9 10 - #define THC_LNL_DEVICE_ID_I2C_PORT1 0xA848 11 - #define THC_LNL_DEVICE_ID_I2C_PORT2 0xA84A 12 - #define THC_PTL_H_DEVICE_ID_I2C_PORT1 0xE348 13 - #define THC_PTL_H_DEVICE_ID_I2C_PORT2 0xE34A 14 - #define THC_PTL_U_DEVICE_ID_I2C_PORT1 0xE448 15 - #define THC_PTL_U_DEVICE_ID_I2C_PORT2 0xE44A 10 + #define PCI_DEVICE_ID_INTEL_THC_LNL_DEVICE_ID_I2C_PORT1 0xA848 11 + #define PCI_DEVICE_ID_INTEL_THC_LNL_DEVICE_ID_I2C_PORT2 0xA84A 12 + #define PCI_DEVICE_ID_INTEL_THC_PTL_H_DEVICE_ID_I2C_PORT1 0xE348 13 + #define PCI_DEVICE_ID_INTEL_THC_PTL_H_DEVICE_ID_I2C_PORT2 0xE34A 14 + #define PCI_DEVICE_ID_INTEL_THC_PTL_U_DEVICE_ID_I2C_PORT1 0xE448 15 + #define PCI_DEVICE_ID_INTEL_THC_PTL_U_DEVICE_ID_I2C_PORT2 0xE44A 16 16 17 17 /* Packet size value, the unit is 16 bytes */ 18 18 #define MAX_PACKET_SIZE_VALUE_LNL 256 ··· 35 35 #define QUICKI2C_DEFAULT_ACTIVE_LTR_VALUE 5 36 36 #define QUICKI2C_DEFAULT_LP_LTR_VALUE 500 37 37 #define QUICKI2C_RPM_TIMEOUT_MS 500 38 + 39 + /* PTL Max packet size detection capability is 255 Bytes */ 40 + #define MAX_RX_DETECT_SIZE_PTL 255 41 + 42 + /* Default interrupt delay is 1ms, suitable for most devices */ 43 + #define DEFAULT_INTERRUPT_DELAY_US (1 * USEC_PER_MSEC) 38 44 39 45 /* 40 46 * THC uses runtime auto suspend to dynamically switch between THC active LTR ··· 128 122 u64 HMSL; 129 123 }; 130 124 125 + /** 126 + * struct quicki2c_ddata - Driver specific data for quicki2c device 127 + * @max_detect_size: Identify max packet size detect for rx 128 + * @interrupt_delay: Identify interrupt detect delay for rx 129 + */ 130 + struct quicki2c_ddata { 131 + u32 max_detect_size; 132 + u32 interrupt_delay; 133 + }; 134 + 131 135 struct device; 132 136 struct pci_dev; 133 137 struct thc_device; ··· 146 130 147 131 /** 148 132 * struct quicki2c_device - THC QuickI2C device struct 149 - * @dev: point to kernel device 150 - * @pdev: point to PCI device 151 - * @thc_hw: point to THC device 152 - * @hid_dev: point to hid device 153 - * @acpi_dev: point to ACPI device 154 - * @driver_data: point to quicki2c specific driver data 133 + * @dev: Point to kernel device 134 + * @pdev: Point to PCI device 135 + * @thc_hw: Point to THC device 136 + * @hid_dev: Point to HID device 137 + * @acpi_dev: Point to ACPI device 138 + * @ddata: Point to QuickI2C platform specific driver data 155 139 * @state: THC I2C device state 156 140 * @mem_addr: MMIO memory address 157 - * @dev_desc: device descriptor for HIDI2C protocol 141 + * @dev_desc: Device descriptor for HIDI2C protocol 158 142 * @i2c_slave_addr: HIDI2C device slave address 159 143 * @hid_desc_addr: Register address for retrieve HID device descriptor 160 144 * @active_ltr_val: THC active LTR value ··· 162 146 * @i2c_speed_mode: 0 - standard mode, 1 - fast mode, 2 - fast mode plus 163 147 * @i2c_clock_hcnt: I2C CLK high period time (unit in cycle count) 164 148 * @i2c_clock_lcnt: I2C CLK low period time (unit in cycle count) 165 - * @report_descriptor: store a copy of device report descriptor 166 - * @input_buf: store a copy of latest input report data 167 - * @report_buf: store a copy of latest input/output report packet from set/get feature 168 - * @report_len: the length of input/output report packet 169 - * @reset_ack_wq: workqueue for waiting reset response from device 170 - * @reset_ack: indicate reset response received or not 149 + * @report_descriptor: Store a copy of device report descriptor 150 + * @input_buf: Store a copy of latest input report data 151 + * @report_buf: Store a copy of latest input/output report packet from set/get feature 152 + * @report_len: The length of input/output report packet 153 + * @reset_ack_wq: Workqueue for waiting reset response from device 154 + * @reset_ack: Indicate reset response received or not 171 155 */ 172 156 struct quicki2c_device { 173 157 struct device *dev; ··· 175 159 struct thc_device *thc_hw; 176 160 struct hid_device *hid_dev; 177 161 struct acpi_device *acpi_dev; 162 + const struct quicki2c_ddata *ddata; 178 163 enum quicki2c_dev_state state; 179 164 180 165 void __iomem *mem_addr;
+15
drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
··· 11 11 #include <linux/pci.h> 12 12 #include <linux/pm_runtime.h> 13 13 14 + #include <linux/gpio/consumer.h> 15 + 14 16 #include "intel-thc-dev.h" 15 17 #include "intel-thc-hw.h" 18 + #include "intel-thc-wot.h" 16 19 17 20 #include "quickspi-dev.h" 18 21 #include "quickspi-hid.h" ··· 48 45 static guid_t thc_platform_guid = 49 46 GUID_INIT(0x84005682, 0x5b71, 0x41a4, 0x8d, 0x66, 0x81, 0x30, 50 47 0xf7, 0x87, 0xa1, 0x38); 48 + 49 + 50 + /* QuickSPI Wake-on-Touch GPIO resource */ 51 + static const struct acpi_gpio_params wake_gpio = { 0, 0, true }; 52 + 53 + static const struct acpi_gpio_mapping quickspi_gpios[] = { 54 + { "wake-on-touch", &wake_gpio, 1 }, 55 + { } 56 + }; 51 57 52 58 /** 53 59 * thc_acpi_get_property - Query device ACPI parameter ··· 438 426 439 427 thc_interrupt_enable(qsdev->thc_hw, true); 440 428 429 + thc_wot_config(qsdev->thc_hw, &quickspi_gpios[0]); 430 + 441 431 qsdev->state = QUICKSPI_INITIATED; 442 432 443 433 return qsdev; ··· 456 442 { 457 443 thc_interrupt_enable(qsdev->thc_hw, false); 458 444 thc_ltr_unconfig(qsdev->thc_hw); 445 + thc_wot_unconfig(qsdev->thc_hw); 459 446 460 447 qsdev->state = QUICKSPI_DISABLED; 461 448 }
+140
drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.c
··· 2 2 /* Copyright (c) 2024 Intel Corporation */ 3 3 4 4 #include <linux/bitfield.h> 5 + #include <linux/math.h> 5 6 #include <linux/regmap.h> 6 7 7 8 #include "intel-thc-dev.h" ··· 1571 1570 return 0; 1572 1571 } 1573 1572 EXPORT_SYMBOL_NS_GPL(thc_i2c_subip_regs_restore, "INTEL_THC"); 1573 + 1574 + /** 1575 + * thc_i2c_set_rx_max_size - Set I2C Rx transfer max input size 1576 + * @dev: The pointer of THC private device context 1577 + * @max_rx_size: Max input report packet size for input report 1578 + * 1579 + * Set @max_rx_size for I2C RxDMA max input size control feature. 1580 + * 1581 + * Return: 0 on success, other error codes on failure. 1582 + */ 1583 + int thc_i2c_set_rx_max_size(struct thc_device *dev, u32 max_rx_size) 1584 + { 1585 + u32 val; 1586 + int ret; 1587 + 1588 + if (!dev) 1589 + return -EINVAL; 1590 + 1591 + if (!max_rx_size) 1592 + return -EOPNOTSUPP; 1593 + 1594 + ret = regmap_read(dev->thc_regmap, THC_M_PRT_SW_SEQ_STS_OFFSET, &val); 1595 + if (ret) 1596 + return ret; 1597 + 1598 + val |= FIELD_PREP(THC_M_PRT_SPI_ICRRD_OPCODE_I2C_MAX_SIZE, max_rx_size); 1599 + 1600 + ret = regmap_write(dev->thc_regmap, THC_M_PRT_SPI_ICRRD_OPCODE_OFFSET, val); 1601 + if (ret) 1602 + return ret; 1603 + 1604 + dev->i2c_max_rx_size = max_rx_size; 1605 + 1606 + return 0; 1607 + } 1608 + EXPORT_SYMBOL_NS_GPL(thc_i2c_set_rx_max_size, "INTEL_THC"); 1609 + 1610 + /** 1611 + * thc_i2c_rx_max_size_enable - Enable I2C Rx max input size control 1612 + * @dev: The pointer of THC private device context 1613 + * @enable: Enable max input size control or not 1614 + * 1615 + * Enable or disable I2C RxDMA max input size control feature. 1616 + * Max input size control only can be enabled after max input size 1617 + * was set by thc_i2c_set_rx_max_size(). 1618 + * 1619 + * Return: 0 on success, other error codes on failure. 1620 + */ 1621 + int thc_i2c_rx_max_size_enable(struct thc_device *dev, bool enable) 1622 + { 1623 + u32 mask = THC_M_PRT_SPI_ICRRD_OPCODE_I2C_MAX_SIZE_EN; 1624 + u32 val = enable ? mask : 0; 1625 + int ret; 1626 + 1627 + if (!dev) 1628 + return -EINVAL; 1629 + 1630 + if (!dev->i2c_max_rx_size) 1631 + return -EOPNOTSUPP; 1632 + 1633 + ret = regmap_write_bits(dev->thc_regmap, THC_M_PRT_SPI_ICRRD_OPCODE_OFFSET, mask, val); 1634 + if (ret) 1635 + return ret; 1636 + 1637 + dev->i2c_max_rx_size_en = enable; 1638 + 1639 + return 0; 1640 + } 1641 + EXPORT_SYMBOL_NS_GPL(thc_i2c_rx_max_size_enable, "INTEL_THC"); 1642 + 1643 + /** 1644 + * thc_i2c_set_rx_int_delay - Set I2C Rx input interrupt delay value 1645 + * @dev: The pointer of THC private device context 1646 + * @delay_us: Interrupt delay value, unit is us 1647 + * 1648 + * Set @delay_us for I2C RxDMA input interrupt delay feature. 1649 + * 1650 + * Return: 0 on success, other error codes on failure. 1651 + */ 1652 + int thc_i2c_set_rx_int_delay(struct thc_device *dev, u32 delay_us) 1653 + { 1654 + u32 val; 1655 + int ret; 1656 + 1657 + if (!dev) 1658 + return -EINVAL; 1659 + 1660 + if (!delay_us) 1661 + return -EOPNOTSUPP; 1662 + 1663 + ret = regmap_read(dev->thc_regmap, THC_M_PRT_SW_SEQ_STS_OFFSET, &val); 1664 + if (ret) 1665 + return ret; 1666 + 1667 + /* THC hardware counts at 10us unit */ 1668 + val |= FIELD_PREP(THC_M_PRT_SPI_ICRRD_OPCODE_I2C_INTERVAL, DIV_ROUND_UP(delay_us, 10)); 1669 + 1670 + ret = regmap_write(dev->thc_regmap, THC_M_PRT_SPI_ICRRD_OPCODE_OFFSET, val); 1671 + if (ret) 1672 + return ret; 1673 + 1674 + dev->i2c_int_delay_us = delay_us; 1675 + 1676 + return 0; 1677 + } 1678 + EXPORT_SYMBOL_NS_GPL(thc_i2c_set_rx_int_delay, "INTEL_THC"); 1679 + 1680 + /** 1681 + * thc_i2c_rx_int_delay_enable - Enable I2C Rx interrupt delay 1682 + * @dev: The pointer of THC private device context 1683 + * @enable: Enable interrupt delay or not 1684 + * 1685 + * Enable or disable I2C RxDMA input interrupt delay feature. 1686 + * Input interrupt delay can only be enabled after interrupt delay value 1687 + * was set by thc_i2c_set_rx_int_delay(). 1688 + * 1689 + * Return: 0 on success, other error codes on failure. 1690 + */ 1691 + int thc_i2c_rx_int_delay_enable(struct thc_device *dev, bool enable) 1692 + { 1693 + u32 mask = THC_M_PRT_SPI_ICRRD_OPCODE_I2C_INTERVAL_EN; 1694 + u32 val = enable ? mask : 0; 1695 + int ret; 1696 + 1697 + if (!dev) 1698 + return -EINVAL; 1699 + 1700 + if (!dev->i2c_int_delay_us) 1701 + return -EOPNOTSUPP; 1702 + 1703 + ret = regmap_write_bits(dev->thc_regmap, THC_M_PRT_SPI_ICRRD_OPCODE_OFFSET, mask, val); 1704 + if (ret) 1705 + return ret; 1706 + 1707 + dev->i2c_int_delay_en = enable; 1708 + 1709 + return 0; 1710 + } 1711 + EXPORT_SYMBOL_NS_GPL(thc_i2c_rx_int_delay_enable, "INTEL_THC"); 1574 1712 1575 1713 MODULE_AUTHOR("Xinpeng Sun <xinpeng.sun@intel.com>"); 1576 1714 MODULE_AUTHOR("Even Xu <even.xu@intel.com>");
+25 -8
drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.h
··· 9 9 #include <linux/workqueue.h> 10 10 11 11 #include "intel-thc-dma.h" 12 + #include "intel-thc-wot.h" 12 13 13 14 #define THC_REGMAP_COMMON_OFFSET 0x10 14 15 #define THC_REGMAP_MMIO_OFFSET 0x1000 ··· 53 52 * struct thc_device - THC private device struct 54 53 * @thc_regmap: MMIO regmap structure for accessing THC registers 55 54 * @mmio_addr: MMIO registers address 56 - * @thc_bus_lock: mutex locker for THC config 57 - * @port_type: port type of THC port instance 55 + * @thc_bus_lock: Mutex locker for THC config 56 + * @port_type: Port type of THC port instance 58 57 * @pio_int_supported: PIO interrupt supported flag 59 58 * @dma_ctx: DMA specific data 60 - * @write_complete_wait: signal event for DMA write complete 61 - * @swdma_complete_wait: signal event for SWDMA sequence complete 62 - * @write_done: bool value that indicates if DMA write is done 63 - * @swdma_done: bool value that indicates if SWDMA swquence is done 64 - * @perf_limit: the delay between read operation and write operation 65 - * @i2c_subip_regs: the copy of THC I2C sub-system registers for resuming restore 59 + * @wot: THC Wake-on-Touch data 60 + * @write_complete_wait: Signal event for DMA write complete 61 + * @swdma_complete_wait: Signal event for SWDMA sequence complete 62 + * @write_done: Bool value that indicates if DMA write is done 63 + * @swdma_done: Bool value that indicates if SWDMA sequence is done 64 + * @perf_limit: The delay between read operation and write operation 65 + * @i2c_subip_regs: The copy of THC I2C sub-system registers for resuming restore 66 + * @i2c_max_rx_size: I2C Rx transfer max input size 67 + * @i2c_int_delay_us: I2C input interrupt delay, unit is us 68 + * @i2c_max_rx_size_en: Bool value that indicates I2C max input size control enabled or not 69 + * @i2c_int_delay_en: Bool value that indicates I2C input interrupt delay enabled or not 66 70 */ 67 71 struct thc_device { 68 72 struct device *dev; ··· 79 73 80 74 struct thc_dma_context *dma_ctx; 81 75 76 + struct thc_wot wot; 77 + 82 78 wait_queue_head_t write_complete_wait; 83 79 wait_queue_head_t swdma_complete_wait; 84 80 bool write_done; ··· 89 81 u32 perf_limit; 90 82 91 83 u32 *i2c_subip_regs; 84 + 85 + u32 i2c_max_rx_size; 86 + u32 i2c_int_delay_us; 87 + bool i2c_max_rx_size_en; 88 + bool i2c_int_delay_en; 92 89 }; 93 90 94 91 struct thc_device *thc_dev_init(struct device *device, void __iomem *mem_addr); ··· 125 112 const u32 speed, const u32 hcnt, const u32 lcnt); 126 113 int thc_i2c_subip_regs_save(struct thc_device *dev); 127 114 int thc_i2c_subip_regs_restore(struct thc_device *dev); 115 + int thc_i2c_set_rx_max_size(struct thc_device *dev, u32 max_rx_size); 116 + int thc_i2c_rx_max_size_enable(struct thc_device *dev, bool enable); 117 + int thc_i2c_set_rx_int_delay(struct thc_device *dev, u32 delay_us); 118 + int thc_i2c_rx_int_delay_enable(struct thc_device *dev, bool enable); 128 119 129 120 #endif /* _INTEL_THC_DEV_H_ */
+40
drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.c
··· 712 712 713 713 thc_reset_dma_settings(dev); 714 714 715 + /* 716 + * Max input size control feature is only available for RxDMA, it must keep disabled 717 + * during SWDMA operation, and restore to previous state after SWDMA is done. 718 + * Max input size variables in THC device context track hardware state, and keep change 719 + * when feature state was changed, so those variables cannot be used to record feature 720 + * state after state was changed during SWDMA operation. Here have to use a temp variable 721 + * in DMA context to record feature state before SWDMA operation. 722 + */ 723 + if (dev->i2c_max_rx_size_en) { 724 + thc_i2c_rx_max_size_enable(dev, false); 725 + dev->dma_ctx->rx_max_size_en = true; 726 + } 727 + 728 + /* 729 + * Interrupt delay feature is in the same situation with max input size control feature, 730 + * needs record feature state before SWDMA. 731 + */ 732 + if (dev->i2c_int_delay_en) { 733 + thc_i2c_rx_int_delay_enable(dev, false); 734 + dev->dma_ctx->rx_int_delay_en = true; 735 + } 736 + 715 737 mask = THC_M_PRT_RPRD_CNTRL_SW_THC_SWDMA_I2C_WBC | 716 738 THC_M_PRT_RPRD_CNTRL_SW_THC_SWDMA_I2C_RX_DLEN_EN; 717 739 val = FIELD_PREP(THC_M_PRT_RPRD_CNTRL_SW_THC_SWDMA_I2C_WBC, write_len) | ··· 775 753 ret = thc_wait_for_dma_pause(dev, THC_SWDMA); 776 754 if (ret) 777 755 return ret; 756 + 757 + /* 758 + * Restore max input size control feature to previous state after SWDMA if it was 759 + * enabled before SWDMA, and reset temp rx_max_size_en variable for next time. 760 + */ 761 + if (dev->dma_ctx->rx_max_size_en) { 762 + thc_i2c_rx_max_size_enable(dev, true); 763 + dev->dma_ctx->rx_max_size_en = false; 764 + } 765 + 766 + /* 767 + * Restore input interrupt delay feature to previous state after SWDMA if it was 768 + * enabled before SWDMA, and reset temp rx_int_delay_en variable for next time. 769 + */ 770 + if (dev->dma_ctx->rx_int_delay_en) { 771 + thc_i2c_rx_int_delay_enable(dev, true); 772 + dev->dma_ctx->rx_int_delay_en = false; 773 + } 778 774 779 775 thc_reset_dma_settings(dev); 780 776
+23 -15
drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.h
··· 27 27 28 28 /** 29 29 * THC DMA channels: 30 - * @THC_RXDMA1: legacy channel, reserved for raw data reading 30 + * @THC_RXDMA1: Legacy channel, reserved for raw data reading 31 31 * @THC_RXDMA2: DMA to read HID data from touch device 32 32 * @THC_TXDMA: DMA to write to touch device 33 33 * @THC_SWDMA: SW triggered DMA to write and read from touch device ··· 42 42 43 43 /** 44 44 * THC DMA Physical Memory Descriptor (PRD) 45 - * @dest_addr: bit[53:0], destination address in system memory 46 - * @int_on_completion: bit[63], if set, thc will trigger interrupt to driver 47 - * @len: bit[87:64], length of this entry 48 - * @end_of_prd: bit[88], if set, this entry is last one of current PRD table 49 - * @hw_status: bit[90:89], hw status bits 45 + * @dest_addr: Bit[53:0], destination address in system memory 46 + * @int_on_completion: Bit[63], if set, thc will trigger interrupt to driver 47 + * @len: Bit[87:64], length of this entry 48 + * @end_of_prd: Bit[88], if set, this entry is last one of current PRD table 49 + * @hw_status: Bit[90:89], hardware status bits 50 50 */ 51 51 struct thc_prd_entry { 52 52 u64 dest_addr : 54; ··· 88 88 * struct thc_dma_configuration - THC DMA configure 89 89 * @dma_channel: DMA channel for current DMA configuration 90 90 * @prd_tbls_dma_handle: DMA buffer handle 91 - * @dir: direction of DMA for this config 91 + * @dir: Direction of DMA for this config 92 92 * @prd_tbls: PRD tables for current DMA 93 - * @sgls: array of pointers to scatter-gather lists 94 - * @sgls_nent: actual number of entries per sg list 95 - * @prd_tbl_num: actual number of PRD tables 96 - * @max_packet_size: size of the buffer needed for 1 DMA message (1 PRD table) 93 + * @sgls: Array of pointers to scatter-gather lists 94 + * @sgls_nent: Actual number of entries per scatter-gather list 95 + * @prd_tbl_num: Actual number of PRD tables 96 + * @max_packet_size: Size of the buffer needed for 1 DMA message (1 PRD table) 97 97 * @prd_base_addr_high: High 32bits memory address where stores PRD table 98 - * @prd_base_addr_low: low 32bits memory address where stores PRD table 98 + * @prd_base_addr_low: Low 32bits memory address where stores PRD table 99 99 * @prd_cntrl: PRD control register value 100 100 * @dma_cntrl: DMA control register value 101 101 */ ··· 117 117 u32 dma_cntrl; 118 118 }; 119 119 120 - /* 121 - * THC DMA context 122 - * Store all THC Channel configures 120 + /** 121 + * struct thc_dma_context - THC DMA context 122 + * @thc_dma_configuration: Array of all THC Channel configures 123 + * @use_write_interrupts: Indicate TxDMA using interrupt or polling 124 + * @rx_max_size_en: Temp flag to indicate THC I2C Rx max input size control feature 125 + * enabled or not, only be used during SWDMA operation. 126 + * @rx_int_delay_en: Temp flag to indicate THC I2C Rx interrupt delay feature 127 + * enabled or not, only be used during SWDMA operation. 123 128 */ 124 129 struct thc_dma_context { 125 130 struct thc_dma_configuration dma_config[MAX_THC_DMA_CHANNEL]; 126 131 u8 use_write_interrupts; 132 + 133 + bool rx_max_size_en; 134 + bool rx_int_delay_en; 127 135 }; 128 136 129 137 struct thc_device;
+5
drivers/hid/intel-thc-hid/intel-thc/intel-thc-hw.h
··· 399 399 #define THC_M_PRT_SPI_ICRRD_OPCODE_SPI_DIO GENMASK(23, 16) 400 400 #define THC_M_PRT_SPI_ICRRD_OPCODE_SPI_QIO GENMASK(15, 8) 401 401 402 + #define THC_M_PRT_SPI_ICRRD_OPCODE_I2C_MAX_SIZE GENMASK(15, 0) 403 + #define THC_M_PRT_SPI_ICRRD_OPCODE_I2C_INTERVAL GENMASK(23, 16) 404 + #define THC_M_PRT_SPI_ICRRD_OPCODE_I2C_INTERVAL_EN BIT(30) 405 + #define THC_M_PRT_SPI_ICRRD_OPCODE_I2C_MAX_SIZE_EN BIT(31) 406 + 402 407 #define THC_M_PRT_INT_EN_SIPE BIT(0) 403 408 #define THC_M_PRT_INT_EN_SBO BIT(1) 404 409 #define THC_M_PRT_INT_EN_SIDR BIT(2)
+94
drivers/hid/intel-thc-hid/intel-thc/intel-thc-wot.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2025 Intel Corporation */ 3 + 4 + #include <linux/acpi.h> 5 + #include <linux/pm_wakeirq.h> 6 + 7 + #include "intel-thc-dev.h" 8 + #include "intel-thc-wot.h" 9 + 10 + /** 11 + * thc_wot_config - Query and configure wake-on-touch feature 12 + * @thc_dev: Point to thc_device structure 13 + * @gpio_map: Point to ACPI GPIO resource mapping structure 14 + * 15 + * THC ACPI device only provides _CRS with GpioInt() resources, doesn't contain 16 + * _DSD to map this GPIO resource, so this function first registers wake GPIO 17 + * mapping manually, then queries wake-on-touch GPIO resource from ACPI, 18 + * if it exists and is wake-able, configure driver to enable it, otherwise, 19 + * return immediately. 20 + * This function will not return error as it doesn't impact major function. 21 + */ 22 + void thc_wot_config(struct thc_device *thc_dev, const struct acpi_gpio_mapping *gpio_map) 23 + { 24 + struct acpi_device *adev; 25 + struct thc_wot *wot; 26 + int ret; 27 + 28 + if (!thc_dev) 29 + return; 30 + 31 + adev = ACPI_COMPANION(thc_dev->dev); 32 + if (!adev) 33 + return; 34 + 35 + wot = &thc_dev->wot; 36 + 37 + ret = acpi_dev_add_driver_gpios(adev, gpio_map); 38 + if (ret) { 39 + dev_warn(thc_dev->dev, "Can't add wake GPIO resource, ret = %d\n", ret); 40 + return; 41 + } 42 + 43 + wot->gpio_irq = acpi_dev_gpio_irq_wake_get_by(adev, "wake-on-touch", 0, 44 + &wot->gpio_irq_wakeable); 45 + if (wot->gpio_irq <= 0) { 46 + dev_warn(thc_dev->dev, "Can't find wake GPIO resource\n"); 47 + return; 48 + } 49 + 50 + if (!wot->gpio_irq_wakeable) { 51 + dev_warn(thc_dev->dev, "GPIO resource isn't wakeable\n"); 52 + return; 53 + } 54 + 55 + ret = device_init_wakeup(thc_dev->dev, true); 56 + if (ret) { 57 + dev_warn(thc_dev->dev, "Failed to init wake up.\n"); 58 + return; 59 + } 60 + 61 + ret = dev_pm_set_dedicated_wake_irq(thc_dev->dev, wot->gpio_irq); 62 + if (ret) { 63 + dev_warn(thc_dev->dev, "Failed to set wake up IRQ.\n"); 64 + device_init_wakeup(thc_dev->dev, false); 65 + } 66 + } 67 + EXPORT_SYMBOL_NS_GPL(thc_wot_config, "INTEL_THC"); 68 + 69 + /** 70 + * thc_wot_unconfig - Unconfig wake-on-touch feature 71 + * @thc_dev: Point to thc_device structure 72 + * 73 + * Configure driver to disable wake-on-touch and release ACPI resource. 74 + */ 75 + void thc_wot_unconfig(struct thc_device *thc_dev) 76 + { 77 + struct acpi_device *adev; 78 + 79 + if (!thc_dev) 80 + return; 81 + 82 + adev = ACPI_COMPANION(thc_dev->dev); 83 + if (!adev) 84 + return; 85 + 86 + if (thc_dev->wot.gpio_irq_wakeable) 87 + device_init_wakeup(thc_dev->dev, false); 88 + 89 + if (thc_dev->wot.gpio_irq > 0) { 90 + dev_pm_clear_wake_irq(thc_dev->dev); 91 + acpi_dev_remove_driver_gpios(adev); 92 + } 93 + } 94 + EXPORT_SYMBOL_NS_GPL(thc_wot_unconfig, "INTEL_THC");
+26
drivers/hid/intel-thc-hid/intel-thc/intel-thc-wot.h
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2025 Intel Corporation */ 3 + 4 + #ifndef _INTEL_THC_WOT_H_ 5 + #define _INTEL_THC_WOT_H_ 6 + 7 + #include <linux/types.h> 8 + 9 + #include <linux/gpio/consumer.h> 10 + 11 + /** 12 + * struct thc_wot - THC Wake-on-Touch data structure 13 + * @gpio_irq : GPIO interrupt IRQ number for wake-on-touch 14 + * @gpio_irq_wakeable : Indicate GPIO IRQ workable or not 15 + */ 16 + struct thc_wot { 17 + int gpio_irq; 18 + bool gpio_irq_wakeable; 19 + }; 20 + 21 + struct thc_device; 22 + 23 + void thc_wot_config(struct thc_device *thc_dev, const struct acpi_gpio_mapping *gpio_map); 24 + void thc_wot_unconfig(struct thc_device *thc_dev); 25 + 26 + #endif /* _INTEL_THC_WOT_H_ */
+23 -23
drivers/hid/usbhid/hid-pidff.c
··· 210 210 */ 211 211 static s32 pidff_clamp(s32 i, struct hid_field *field) 212 212 { 213 - s32 clamped = clamp(i, field->logical_minimum, field->logical_maximum); 214 - pr_debug("clamped from %d to %d", i, clamped); 215 - return clamped; 213 + return (s32)clamp(i, field->logical_minimum, field->logical_maximum); 216 214 } 217 215 218 216 /* ··· 227 229 */ 228 230 static int pidff_rescale_signed(int i, struct hid_field *field) 229 231 { 230 - if (i > 0) return i * field->logical_maximum / S16_MAX; 231 - if (i < 0) return i * field->logical_minimum / S16_MIN; 232 + if (i > 0) 233 + return i * field->logical_maximum / S16_MAX; 234 + if (i < 0) 235 + return i * field->logical_minimum / S16_MIN; 232 236 return 0; 233 237 } 234 238 ··· 241 241 { 242 242 u32 scaled_time = time; 243 243 int exponent = field->unit_exponent; 244 - pr_debug("time field exponent: %d\n", exponent); 245 244 246 - for (;exponent < FF_TIME_EXPONENT; exponent++) 245 + pr_debug("time field exponent: %d\n", exponent); 246 + for (; exponent < FF_TIME_EXPONENT; exponent++) 247 247 scaled_time *= 10; 248 - for (;exponent > FF_TIME_EXPONENT; exponent--) 248 + for (; exponent > FF_TIME_EXPONENT; exponent--) 249 249 scaled_time /= 10; 250 250 251 251 pr_debug("time calculated from %d to %d\n", time, scaled_time); ··· 275 275 276 276 static void pidff_set_time(struct pidff_usage *usage, u16 time) 277 277 { 278 - u32 modified_time = pidff_rescale_time(time, usage->field); 279 - usage->value[0] = pidff_clamp(modified_time, usage->field); 278 + usage->value[0] = pidff_clamp( 279 + pidff_rescale_time(time, usage->field), usage->field); 280 280 } 281 281 282 282 static void pidff_set_duration(struct pidff_usage *usage, u16 duration) ··· 332 332 struct ff_envelope *old) 333 333 { 334 334 bool needs_new_envelope; 335 + 335 336 needs_new_envelope = envelope->attack_level != 0 || 336 337 envelope->fade_level != 0 || 337 338 envelope->attack_length != 0 || ··· 569 568 hid_dbg(pidff->hid, "DEVICE_CONTROL is a bitmask\n"); 570 569 571 570 /* Clear current bitmask */ 572 - for(i = 0; i < sizeof(pidff_device_control); i++) { 571 + for (i = 0; i < sizeof(pidff_device_control); i++) { 573 572 index = pidff->control_id[i]; 574 573 if (index < 1) 575 574 continue; ··· 620 619 struct hid_device *hid = pidff->hid; 621 620 622 621 /* Repeat if PID_SIMULTANEOUS_MAX < 2 to make sure it's correct */ 623 - for(i = 0; i < 20; i++) { 622 + for (i = 0; i < 20; i++) { 624 623 hid_hw_request(hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT); 625 624 hid_hw_wait(hid); 626 625 ··· 716 715 static int pidff_playback(struct input_dev *dev, int effect_id, int value) 717 716 { 718 717 struct pidff_device *pidff = dev->ff->private; 718 + 719 719 pidff_playback_pid(pidff, pidff->pid_id[effect_id], value); 720 720 return 0; 721 721 } ··· 851 849 case FF_INERTIA: 852 850 case FF_FRICTION: 853 851 if (!old) { 854 - switch(effect->type) { 852 + switch (effect->type) { 855 853 case FF_SPRING: 856 854 type_id = PID_SPRING; 857 855 break; ··· 942 940 struct hid_report *report, int count, int strict) 943 941 { 944 942 if (!report) { 945 - pr_debug("pidff_find_fields, null report\n"); 943 + pr_debug("%s, null report\n", __func__); 946 944 return -1; 947 945 } 948 946 ··· 976 974 pr_debug("Delay field not found, but that's OK\n"); 977 975 pr_debug("Setting MISSING_DELAY quirk\n"); 978 976 return_value |= HID_PIDFF_QUIRK_MISSING_DELAY; 979 - } 980 - else if (!found && table[k] == pidff_set_condition[PID_PARAM_BLOCK_OFFSET]) { 977 + } else if (!found && table[k] == pidff_set_condition[PID_PARAM_BLOCK_OFFSET]) { 981 978 pr_debug("PBO field not found, but that's OK\n"); 982 979 pr_debug("Setting MISSING_PBO quirk\n"); 983 980 return_value |= HID_PIDFF_QUIRK_MISSING_PBO; 984 - } 985 - else if (!found && strict) { 981 + } else if (!found && strict) { 986 982 pr_debug("failed to locate %d\n", k); 987 983 return -1; 988 984 } ··· 1069 1069 int usage, int enforce_min) 1070 1070 { 1071 1071 if (!report) { 1072 - pr_debug("pidff_find_special_field, null report\n"); 1072 + pr_debug("%s, null report\n", __func__); 1073 1073 return NULL; 1074 1074 } 1075 1075 ··· 1081 1081 if (!enforce_min || 1082 1082 report->field[i]->logical_minimum == 1) 1083 1083 return report->field[i]; 1084 - else { 1085 - pr_err("logical_minimum is not 1 as it should be\n"); 1086 - return NULL; 1087 - } 1084 + 1085 + pr_err("logical_minimum is not 1 as it should be\n"); 1086 + return NULL; 1088 1087 } 1089 1088 } 1090 1089 return NULL; ··· 1206 1207 1207 1208 for (i = 0; i < sizeof(pidff_effect_types); i++) { 1208 1209 int pidff_type = pidff->type_id[i]; 1210 + 1209 1211 if (pidff->set_effect_type->usage[pidff_type].hid != 1210 1212 pidff->create_new_effect_type->usage[pidff_type].hid) { 1211 1213 hid_err(pidff->hid,
+1 -2
drivers/hid/usbhid/hid-pidff.h
··· 9 9 /* Delay field (0xA7) missing. Skip it during set effect report upload */ 10 10 #define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0) 11 11 12 - /* Missing Paramter block offset (0x23). Skip it during SET_CONDITION 13 - report upload */ 12 + /* Missing Paramter block offset (0x23). Skip it during SET_CONDITION upload */ 14 13 #define HID_PIDFF_QUIRK_MISSING_PBO BIT(1) 15 14 16 15 /* Initialise device control field even if logical_minimum != 1 */
+7 -1
include/linux/hid.h
··· 1216 1216 /** 1217 1217 * hid_report_len - calculate the report length 1218 1218 * 1219 - * @report: the report we want to know the length 1219 + * @report: the report whose length we want to know 1220 + * 1221 + * The length counts the report ID byte, but only if the ID is nonzero 1222 + * and therefore is included in the report. Reports whose ID is zero 1223 + * never include an ID byte. 1220 1224 */ 1221 1225 static inline u32 hid_report_len(struct hid_report *report) 1222 1226 { ··· 1243 1239 dev_notice(&(hid)->dev, fmt, ##__VA_ARGS__) 1244 1240 #define hid_warn(hid, fmt, ...) \ 1245 1241 dev_warn(&(hid)->dev, fmt, ##__VA_ARGS__) 1242 + #define hid_warn_ratelimited(hid, fmt, ...) \ 1243 + dev_warn_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__) 1246 1244 #define hid_info(hid, fmt, ...) \ 1247 1245 dev_info(&(hid)->dev, fmt, ##__VA_ARGS__) 1248 1246 #define hid_dbg(hid, fmt, ...) \
+30 -16
tools/testing/selftests/hid/tests/base.py
··· 5 5 # Copyright (c) 2017 Benjamin Tissoires <benjamin.tissoires@gmail.com> 6 6 # Copyright (c) 2017 Red Hat, Inc. 7 7 8 + import dataclasses 8 9 import libevdev 9 10 import os 10 11 import pytest ··· 146 145 self.name = name 147 146 148 147 148 + @dataclasses.dataclass 149 + class HidBpf: 150 + object_name: str 151 + has_rdesc_fixup: bool 152 + 153 + 154 + @dataclasses.dataclass 155 + class KernelModule: 156 + driver_name: str 157 + module_name: str 158 + 159 + 149 160 class BaseTestCase: 150 161 class TestUhid(object): 151 162 syn_event = libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT) # type: ignore ··· 168 155 169 156 # List of kernel modules to load before starting the test 170 157 # if any module is not available (not compiled), the test will skip. 171 - # Each element is a tuple '(kernel driver name, kernel module)', 172 - # for example ("playstation", "hid-playstation") 173 - kernel_modules: List[Tuple[str, str]] = [] 158 + # Each element is a KernelModule object, for example 159 + # KernelModule("playstation", "hid-playstation") 160 + kernel_modules: List[KernelModule] = [] 174 161 175 162 # List of in kernel HID-BPF object files to load 176 163 # before starting the test 177 164 # Any existing pre-loaded HID-BPF module will be removed 178 165 # before the ones in this list will be manually loaded. 179 - # Each Element is a tuple '(hid_bpf_object, rdesc_fixup_present)', 180 - # for example '("xppen-ArtistPro16Gen2.bpf.o", True)' 181 - # If 'rdesc_fixup_present' is True, the test needs to wait 166 + # Each Element is a HidBpf object, for example 167 + # 'HidBpf("xppen-ArtistPro16Gen2.bpf.o", True)' 168 + # If 'has_rdesc_fixup' is True, the test needs to wait 182 169 # for one unbind and rebind before it can be sure the kernel is 183 170 # ready 184 - hid_bpfs: List[Tuple[str, bool]] = [] 171 + hid_bpfs: List[HidBpf] = [] 185 172 186 173 def assertInputEventsIn(self, expected_events, effective_events): 187 174 effective_events = effective_events.copy() ··· 245 232 246 233 @pytest.fixture() 247 234 def load_kernel_module(self): 248 - for kernel_driver, kernel_module in self.kernel_modules: 249 - self._load_kernel_module(kernel_driver, kernel_module) 235 + for k in self.kernel_modules: 236 + self._load_kernel_module(k.driver_name, k.module_name) 250 237 yield 251 238 252 239 def load_hid_bpfs(self): 240 + # this function will only work when run in the kernel tree 253 241 script_dir = Path(os.path.dirname(os.path.realpath(__file__))) 254 242 root_dir = (script_dir / "../../../../..").resolve() 255 243 bpf_dir = root_dir / "drivers/hid/bpf/progs" 244 + 245 + if not bpf_dir.exists(): 246 + pytest.skip("looks like we are not in the kernel tree, skipping") 256 247 257 248 udev_hid_bpf = shutil.which("udev-hid-bpf") 258 249 if not udev_hid_bpf: 259 250 pytest.skip("udev-hid-bpf not found in $PATH, skipping") 260 251 261 - wait = False 262 - for _, rdesc_fixup in self.hid_bpfs: 263 - if rdesc_fixup: 264 - wait = True 252 + wait = any(b.has_rdesc_fixup for b in self.hid_bpfs) 265 253 266 - for hid_bpf, _ in self.hid_bpfs: 254 + for hid_bpf in self.hid_bpfs: 267 255 # We need to start `udev-hid-bpf` in the background 268 256 # and dispatch uhid events in case the kernel needs 269 257 # to fetch features on the device ··· 274 260 "--verbose", 275 261 "add", 276 262 str(self.uhdev.sys_path), 277 - str(bpf_dir / hid_bpf), 263 + str(bpf_dir / hid_bpf.object_name), 278 264 ], 279 265 ) 280 266 while process.poll() is None: 281 267 self.uhdev.dispatch(1) 282 268 283 - if process.poll() != 0: 269 + if process.returncode != 0: 284 270 pytest.fail( 285 271 f"Couldn't insert hid-bpf program '{hid_bpf}', marking the test as failed" 286 272 )
+38 -11
tools/testing/selftests/hid/tests/base_device.py
··· 18 18 # You should have received a copy of the GNU General Public License 19 19 # along with this program. If not, see <http://www.gnu.org/licenses/>. 20 20 21 + import dataclasses 21 22 import fcntl 22 23 import functools 23 24 import libevdev 24 25 import os 26 + import threading 25 27 26 28 try: 27 29 import pyudev ··· 106 104 return self._type.str_value 107 105 108 106 107 + @dataclasses.dataclass 108 + class HidReadiness: 109 + is_ready: bool = False 110 + count: int = 0 111 + 112 + 109 113 class HIDIsReady(object): 110 114 """ 111 115 Companion class that binds to a kernel mechanism ··· 123 115 def __init__(self: "HIDIsReady", uhid: UHIDDevice) -> None: 124 116 self.uhid = uhid 125 117 126 - def is_ready(self: "HIDIsReady") -> bool: 118 + def is_ready(self: "HIDIsReady") -> HidReadiness: 127 119 """ 128 120 Overwrite in subclasses: should return True or False whether 129 121 the attached uhid device is ready or not. 130 122 """ 131 - return False 123 + return HidReadiness() 132 124 133 125 134 126 class UdevHIDIsReady(HIDIsReady): 135 127 _pyudev_context: ClassVar[Optional[pyudev.Context]] = None 136 128 _pyudev_monitor: ClassVar[Optional[pyudev.Monitor]] = None 137 - _uhid_devices: ClassVar[Dict[int, Tuple[bool, int]]] = {} 129 + _uhid_devices: ClassVar[Dict[int, HidReadiness]] = {} 138 130 139 131 def __init__(self: "UdevHIDIsReady", uhid: UHIDDevice) -> None: 140 132 super().__init__(uhid) ··· 165 157 166 158 id = int(event.sys_path.strip().split(".")[-1], 16) 167 159 168 - device_ready, count = cls._uhid_devices.get(id, (False, 0)) 160 + readiness = cls._uhid_devices.setdefault(id, HidReadiness()) 169 161 170 162 ready = event.action == "bind" 171 - if not device_ready and ready: 172 - count += 1 173 - cls._uhid_devices[id] = (ready, count) 163 + if not readiness.is_ready and ready: 164 + readiness.count += 1 174 165 175 - def is_ready(self: "UdevHIDIsReady") -> Tuple[bool, int]: 166 + readiness.is_ready = ready 167 + 168 + def is_ready(self: "UdevHIDIsReady") -> HidReadiness: 176 169 try: 177 170 return self._uhid_devices[self.uhid.hid_id] 178 171 except KeyError: 179 - return (False, 0) 172 + return HidReadiness() 180 173 181 174 182 175 class EvdevMatch(object): ··· 331 322 332 323 @property 333 324 def kernel_is_ready(self: "BaseDevice") -> bool: 334 - return self._kernel_is_ready.is_ready()[0] and self.started 325 + return self._kernel_is_ready.is_ready().is_ready and self.started 335 326 336 327 @property 337 328 def kernel_ready_count(self: "BaseDevice") -> int: 338 - return self._kernel_is_ready.is_ready()[1] 329 + return self._kernel_is_ready.is_ready().count 339 330 340 331 @property 341 332 def input_nodes(self: "BaseDevice") -> List[EvdevDevice]: ··· 345 336 if not self.kernel_is_ready or not self.started: 346 337 return [] 347 338 339 + # Starting with kernel v6.16, an event is emitted when 340 + # userspace opens a kernel device, and for some devices 341 + # this translates into a SET_REPORT. 342 + # Because EvdevDevice(path) opens every single evdev node 343 + # we need to have a separate thread to process the incoming 344 + # SET_REPORT or we end up having to wait for the kernel 345 + # timeout of 5 seconds. 346 + done = False 347 + 348 + def dispatch(): 349 + while not done: 350 + self.dispatch(1) 351 + 352 + t = threading.Thread(target=dispatch) 353 + t.start() 354 + 348 355 self._input_nodes = [ 349 356 EvdevDevice(path) 350 357 for path in self.walk_sysfs("input", "input/input*/event*") 351 358 ] 359 + done = True 360 + t.join() 352 361 return self._input_nodes 353 362 354 363 def match_evdev_rule(self, application, evdev):
+2 -1
tools/testing/selftests/hid/tests/test_apple_keyboard.py
··· 8 8 9 9 from .test_keyboard import ArrayKeyboard, TestArrayKeyboard 10 10 from hidtools.util import BusType 11 + from . import base 11 12 12 13 import libevdev 13 14 import logging 14 15 15 16 logger = logging.getLogger("hidtools.test.apple-keyboard") 16 17 17 - KERNEL_MODULE = ("apple", "hid-apple") 18 + KERNEL_MODULE = base.KernelModule("apple", "hid-apple") 18 19 19 20 20 21 class KbdData(object):
+2 -1
tools/testing/selftests/hid/tests/test_gamepad.py
··· 12 12 13 13 from .base_gamepad import BaseGamepad, JoystickGamepad, AxisMapping 14 14 from hidtools.util import BusType 15 + from .base import HidBpf 15 16 16 17 import logging 17 18 ··· 655 654 656 655 657 656 class TestRaptorMach2Joystick(BaseTest.TestGamepad): 658 - hid_bpfs = [("FR-TEC__Raptor-Mach-2.bpf.o", True)] 657 + hid_bpfs = [HidBpf("FR-TEC__Raptor-Mach-2.bpf.o", True)] 659 658 660 659 def create_device(self): 661 660 return RaptorMach2Joystick(
+2 -1
tools/testing/selftests/hid/tests/test_ite_keyboard.py
··· 11 11 12 12 import libevdev 13 13 import logging 14 + from . import base 14 15 15 16 logger = logging.getLogger("hidtools.test.ite-keyboard") 16 17 17 - KERNEL_MODULE = ("itetech", "hid_ite") 18 + KERNEL_MODULE = base.KernelModule("itetech", "hid_ite") 18 19 19 20 20 21 class KbdData(object):
+1 -1
tools/testing/selftests/hid/tests/test_multitouch.py
··· 17 17 18 18 logger = logging.getLogger("hidtools.test.multitouch") 19 19 20 - KERNEL_MODULE = ("hid-multitouch", "hid_multitouch") 20 + KERNEL_MODULE = base.KernelModule("hid-multitouch", "hid_multitouch") 21 21 22 22 23 23 def BIT(x):
+4 -3
tools/testing/selftests/hid/tests/test_sony.py
··· 7 7 # 8 8 9 9 from .base import application_matches 10 + from .base import KernelModule 10 11 from .test_gamepad import BaseTest 11 12 from hidtools.device.sony_gamepad import ( 12 13 PS3Controller, ··· 25 24 26 25 logger = logging.getLogger("hidtools.test.sony") 27 26 28 - PS3_MODULE = ("sony", "hid_sony") 29 - PS4_MODULE = ("playstation", "hid_playstation") 30 - PS5_MODULE = ("playstation", "hid_playstation") 27 + PS3_MODULE = KernelModule("sony", "hid_sony") 28 + PS4_MODULE = KernelModule("playstation", "hid_playstation") 29 + PS5_MODULE = KernelModule("playstation", "hid_playstation") 31 30 32 31 33 32 class SonyBaseTest:
+6 -5
tools/testing/selftests/hid/tests/test_tablet.py
··· 10 10 import copy 11 11 from enum import Enum 12 12 from hidtools.util import BusType 13 + from .base import HidBpf 13 14 import libevdev 14 15 import logging 15 16 import pytest ··· 1229 1228 pen.current_state = state 1230 1229 1231 1230 def call_input_event(self, report): 1232 - if report[0] == 0x0a: 1231 + if report[0] == 0x0A: 1233 1232 # ensures the original second Eraser usage is null 1234 - report[1] &= 0xdf 1233 + report[1] &= 0xDF 1235 1234 1236 1235 # ensures the original last bit is equal to bit 6 (In Range) 1237 1236 if report[1] & 0x40: ··· 1473 1472 1474 1473 1475 1474 class TestXPPen_ArtistPro16Gen2_28bd_095b(BaseTest.TestTablet): 1476 - hid_bpfs = [("XPPen__ArtistPro16Gen2.bpf.o", True)] 1475 + hid_bpfs = [HidBpf("XPPen__ArtistPro16Gen2.bpf.o", True)] 1477 1476 1478 1477 def create_device(self): 1479 1478 dev = XPPen_ArtistPro16Gen2_28bd_095b( ··· 1485 1484 1486 1485 1487 1486 class TestXPPen_Artist24_28bd_093a(BaseTest.TestTablet): 1488 - hid_bpfs = [("XPPen__Artist24.bpf.o", True)] 1487 + hid_bpfs = [HidBpf("XPPen__Artist24.bpf.o", True)] 1489 1488 1490 1489 def create_device(self): 1491 1490 return XPPen_Artist24_28bd_093a( ··· 1496 1495 1497 1496 1498 1497 class TestHuion_Kamvas_Pro_19_256c_006b(BaseTest.TestTablet): 1499 - hid_bpfs = [("Huion__Kamvas-Pro-19.bpf.o", True)] 1498 + hid_bpfs = [HidBpf("Huion__Kamvas-Pro-19.bpf.o", True)] 1500 1499 1501 1500 def create_device(self): 1502 1501 return Huion_Kamvas_Pro_19_256c_006b(
+327 -118
tools/testing/selftests/hid/tests/test_wacom_generic.py
··· 40 40 41 41 logger = logging.getLogger("hidtools.test.wacom") 42 42 43 - KERNEL_MODULE = ("wacom", "wacom") 43 + KERNEL_MODULE = base.KernelModule("wacom", "wacom") 44 44 45 45 46 46 class ProximityState(Enum): ··· 892 892 locations. The value of `t` may be incremented over time to move the 893 893 points along a linear path. 894 894 """ 895 - return [ self.make_contact(id, t) for id in range(0, n) ] 895 + return [self.make_contact(id, t) for id in range(0, n)] 896 896 897 - def assert_contact(self, uhdev, evdev, contact_ids, t=0): 897 + def assert_contact(self, evdev, contact_ids, t=0): 898 898 """ 899 899 Assert properties of a contact generated by make_contact. 900 900 """ ··· 916 916 assert evdev.slots[slot_num][libevdev.EV_ABS.ABS_MT_POSITION_X] == x 917 917 assert evdev.slots[slot_num][libevdev.EV_ABS.ABS_MT_POSITION_Y] == y 918 918 919 - def assert_contacts(self, uhdev, evdev, data, t=0): 919 + def assert_contacts(self, evdev, data, t=0): 920 920 """ 921 921 Assert properties of a list of contacts generated by make_contacts. 922 922 """ 923 923 for contact_ids in data: 924 - self.assert_contact(uhdev, evdev, contact_ids, t) 924 + self.assert_contact(evdev, contact_ids, t) 925 925 926 926 def test_contact_id_0(self): 927 927 """ ··· 997 997 998 998 assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events 999 999 1000 - self.assert_contacts(uhdev, evdev, 1001 - [ self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = None), 1002 - self.ContactIds(contact_id = 1, tracking_id = 0, slot_num = 0), 1003 - self.ContactIds(contact_id = 2, tracking_id = -1, slot_num = None), 1004 - self.ContactIds(contact_id = 3, tracking_id = 1, slot_num = 1), 1005 - self.ContactIds(contact_id = 4, tracking_id = -1, slot_num = None) ]) 1000 + self.assert_contacts( 1001 + evdev, 1002 + [ 1003 + self.ContactIds(contact_id=0, tracking_id=-1, slot_num=None), 1004 + self.ContactIds(contact_id=1, tracking_id=0, slot_num=0), 1005 + self.ContactIds(contact_id=2, tracking_id=-1, slot_num=None), 1006 + self.ContactIds(contact_id=3, tracking_id=1, slot_num=1), 1007 + self.ContactIds(contact_id=4, tracking_id=-1, slot_num=None), 1008 + ], 1009 + ) 1006 1010 1007 1011 def confidence_change_assert_playback(self, uhdev, evdev, timeline): 1008 1012 """ ··· 1030 1026 events = uhdev.next_sync_events() 1031 1027 self.debug_reports(r, uhdev, events) 1032 1028 1033 - ids = [ x[0] for x in state ] 1034 - self.assert_contacts(uhdev, evdev, ids, t) 1029 + ids = [x[0] for x in state] 1030 + self.assert_contacts(evdev, ids, t) 1035 1031 1036 1032 t += 1 1037 1033 ··· 1048 1044 uhdev = self.uhdev 1049 1045 evdev = uhdev.get_evdev() 1050 1046 1051 - self.confidence_change_assert_playback(uhdev, evdev, [ 1052 - # t=0: Contact 0 == Down + confident; Contact 1 == Down + confident 1053 - # Both fingers confidently in contact 1054 - [(self.ContactIds(contact_id = 0, tracking_id = 0, slot_num = 0), True, True), 1055 - (self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)], 1056 - 1057 - # t=1: Contact 0 == !Down + confident; Contact 1 == Down + confident 1058 - # First finger looses confidence and clears only the tipswitch flag 1059 - [(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, True), 1060 - (self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)], 1061 - 1062 - # t=2: Contact 0 == !Down + !confident; Contact 1 == Down + confident 1063 - # First finger has lost confidence and has both flags cleared 1064 - [(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False), 1065 - (self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)], 1066 - 1067 - # t=3: Contact 0 == !Down + !confident; Contact 1 == Down + confident 1068 - # First finger has lost confidence and has both flags cleared 1069 - [(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False), 1070 - (self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)] 1071 - ]) 1047 + self.confidence_change_assert_playback( 1048 + uhdev, 1049 + evdev, 1050 + [ 1051 + # t=0: Contact 0 == Down + confident; Contact 1 == Down + confident 1052 + # Both fingers confidently in contact 1053 + [ 1054 + ( 1055 + self.ContactIds(contact_id=0, tracking_id=0, slot_num=0), 1056 + True, 1057 + True, 1058 + ), 1059 + ( 1060 + self.ContactIds(contact_id=1, tracking_id=1, slot_num=1), 1061 + True, 1062 + True, 1063 + ), 1064 + ], 1065 + # t=1: Contact 0 == !Down + confident; Contact 1 == Down + confident 1066 + # First finger looses confidence and clears only the tipswitch flag 1067 + [ 1068 + ( 1069 + self.ContactIds(contact_id=0, tracking_id=-1, slot_num=0), 1070 + False, 1071 + True, 1072 + ), 1073 + ( 1074 + self.ContactIds(contact_id=1, tracking_id=1, slot_num=1), 1075 + True, 1076 + True, 1077 + ), 1078 + ], 1079 + # t=2: Contact 0 == !Down + !confident; Contact 1 == Down + confident 1080 + # First finger has lost confidence and has both flags cleared 1081 + [ 1082 + ( 1083 + self.ContactIds(contact_id=0, tracking_id=-1, slot_num=0), 1084 + False, 1085 + False, 1086 + ), 1087 + ( 1088 + self.ContactIds(contact_id=1, tracking_id=1, slot_num=1), 1089 + True, 1090 + True, 1091 + ), 1092 + ], 1093 + # t=3: Contact 0 == !Down + !confident; Contact 1 == Down + confident 1094 + # First finger has lost confidence and has both flags cleared 1095 + [ 1096 + ( 1097 + self.ContactIds(contact_id=0, tracking_id=-1, slot_num=0), 1098 + False, 1099 + False, 1100 + ), 1101 + ( 1102 + self.ContactIds(contact_id=1, tracking_id=1, slot_num=1), 1103 + True, 1104 + True, 1105 + ), 1106 + ], 1107 + ], 1108 + ) 1072 1109 1073 1110 def test_confidence_loss_b(self): 1074 1111 """ ··· 1124 1079 uhdev = self.uhdev 1125 1080 evdev = uhdev.get_evdev() 1126 1081 1127 - self.confidence_change_assert_playback(uhdev, evdev, [ 1128 - # t=0: Contact 0 == Down + confident; Contact 1 == Down + confident 1129 - # Both fingers confidently in contact 1130 - [(self.ContactIds(contact_id = 0, tracking_id = 0, slot_num = 0), True, True), 1131 - (self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)], 1132 - 1133 - # t=1: Contact 0 == !Down + !confident; Contact 1 == Down + confident 1134 - # First finger looses confidence and has both flags cleared simultaneously 1135 - [(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False), 1136 - (self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)], 1137 - 1138 - # t=2: Contact 0 == !Down + !confident; Contact 1 == Down + confident 1139 - # First finger has lost confidence and has both flags cleared 1140 - [(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False), 1141 - (self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)], 1142 - 1143 - # t=3: Contact 0 == !Down + !confident; Contact 1 == Down + confident 1144 - # First finger has lost confidence and has both flags cleared 1145 - [(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False), 1146 - (self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)] 1147 - ]) 1082 + self.confidence_change_assert_playback( 1083 + uhdev, 1084 + evdev, 1085 + [ 1086 + # t=0: Contact 0 == Down + confident; Contact 1 == Down + confident 1087 + # Both fingers confidently in contact 1088 + [ 1089 + ( 1090 + self.ContactIds(contact_id=0, tracking_id=0, slot_num=0), 1091 + True, 1092 + True, 1093 + ), 1094 + ( 1095 + self.ContactIds(contact_id=1, tracking_id=1, slot_num=1), 1096 + True, 1097 + True, 1098 + ), 1099 + ], 1100 + # t=1: Contact 0 == !Down + !confident; Contact 1 == Down + confident 1101 + # First finger looses confidence and has both flags cleared simultaneously 1102 + [ 1103 + ( 1104 + self.ContactIds(contact_id=0, tracking_id=-1, slot_num=0), 1105 + False, 1106 + False, 1107 + ), 1108 + ( 1109 + self.ContactIds(contact_id=1, tracking_id=1, slot_num=1), 1110 + True, 1111 + True, 1112 + ), 1113 + ], 1114 + # t=2: Contact 0 == !Down + !confident; Contact 1 == Down + confident 1115 + # First finger has lost confidence and has both flags cleared 1116 + [ 1117 + ( 1118 + self.ContactIds(contact_id=0, tracking_id=-1, slot_num=0), 1119 + False, 1120 + False, 1121 + ), 1122 + ( 1123 + self.ContactIds(contact_id=1, tracking_id=1, slot_num=1), 1124 + True, 1125 + True, 1126 + ), 1127 + ], 1128 + # t=3: Contact 0 == !Down + !confident; Contact 1 == Down + confident 1129 + # First finger has lost confidence and has both flags cleared 1130 + [ 1131 + ( 1132 + self.ContactIds(contact_id=0, tracking_id=-1, slot_num=0), 1133 + False, 1134 + False, 1135 + ), 1136 + ( 1137 + self.ContactIds(contact_id=1, tracking_id=1, slot_num=1), 1138 + True, 1139 + True, 1140 + ), 1141 + ], 1142 + ], 1143 + ) 1148 1144 1149 1145 def test_confidence_loss_c(self): 1150 1146 """ ··· 1199 1113 uhdev = self.uhdev 1200 1114 evdev = uhdev.get_evdev() 1201 1115 1202 - self.confidence_change_assert_playback(uhdev, evdev, [ 1203 - # t=0: Contact 0 == Down + confident; Contact 1 == Down + confident 1204 - # Both fingers confidently in contact 1205 - [(self.ContactIds(contact_id = 0, tracking_id = 0, slot_num = 0), True, True), 1206 - (self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)], 1207 - 1208 - # t=1: Contact 0 == Down + !confident; Contact 1 == Down + confident 1209 - # First finger looses confidence and clears only the confidence flag 1210 - [(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), True, False), 1211 - (self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)], 1212 - 1213 - # t=2: Contact 0 == !Down + !confident; Contact 1 == Down + confident 1214 - # First finger has lost confidence and has both flags cleared 1215 - [(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False), 1216 - (self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)], 1217 - 1218 - # t=3: Contact 0 == !Down + !confident; Contact 1 == Down + confident 1219 - # First finger has lost confidence and has both flags cleared 1220 - [(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, False), 1221 - (self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)] 1222 - ]) 1116 + self.confidence_change_assert_playback( 1117 + uhdev, 1118 + evdev, 1119 + [ 1120 + # t=0: Contact 0 == Down + confident; Contact 1 == Down + confident 1121 + # Both fingers confidently in contact 1122 + [ 1123 + ( 1124 + self.ContactIds(contact_id=0, tracking_id=0, slot_num=0), 1125 + True, 1126 + True, 1127 + ), 1128 + ( 1129 + self.ContactIds(contact_id=1, tracking_id=1, slot_num=1), 1130 + True, 1131 + True, 1132 + ), 1133 + ], 1134 + # t=1: Contact 0 == Down + !confident; Contact 1 == Down + confident 1135 + # First finger looses confidence and clears only the confidence flag 1136 + [ 1137 + ( 1138 + self.ContactIds(contact_id=0, tracking_id=-1, slot_num=0), 1139 + True, 1140 + False, 1141 + ), 1142 + ( 1143 + self.ContactIds(contact_id=1, tracking_id=1, slot_num=1), 1144 + True, 1145 + True, 1146 + ), 1147 + ], 1148 + # t=2: Contact 0 == !Down + !confident; Contact 1 == Down + confident 1149 + # First finger has lost confidence and has both flags cleared 1150 + [ 1151 + ( 1152 + self.ContactIds(contact_id=0, tracking_id=-1, slot_num=0), 1153 + False, 1154 + False, 1155 + ), 1156 + ( 1157 + self.ContactIds(contact_id=1, tracking_id=1, slot_num=1), 1158 + True, 1159 + True, 1160 + ), 1161 + ], 1162 + # t=3: Contact 0 == !Down + !confident; Contact 1 == Down + confident 1163 + # First finger has lost confidence and has both flags cleared 1164 + [ 1165 + ( 1166 + self.ContactIds(contact_id=0, tracking_id=-1, slot_num=0), 1167 + False, 1168 + False, 1169 + ), 1170 + ( 1171 + self.ContactIds(contact_id=1, tracking_id=1, slot_num=1), 1172 + True, 1173 + True, 1174 + ), 1175 + ], 1176 + ], 1177 + ) 1223 1178 1224 1179 def test_confidence_gain_a(self): 1225 1180 """ ··· 1271 1144 uhdev = self.uhdev 1272 1145 evdev = uhdev.get_evdev() 1273 1146 1274 - self.confidence_change_assert_playback(uhdev, evdev, [ 1275 - # t=0: Contact 0 == Down + !confident; Contact 1 == Down + confident 1276 - # Only second finger is confidently in contact 1277 - [(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = None), True, False), 1278 - (self.ContactIds(contact_id = 1, tracking_id = 0, slot_num = 0), True, True)], 1279 - 1280 - # t=1: Contact 0 == Down + !confident; Contact 1 == Down + confident 1281 - # First finger gains confidence 1282 - [(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = None), True, False), 1283 - (self.ContactIds(contact_id = 1, tracking_id = 0, slot_num = 0), True, True)], 1284 - 1285 - # t=2: Contact 0 == Down + confident; Contact 1 == Down + confident 1286 - # First finger remains confident 1287 - [(self.ContactIds(contact_id = 0, tracking_id = 1, slot_num = 1), True, True), 1288 - (self.ContactIds(contact_id = 1, tracking_id = 0, slot_num = 0), True, True)], 1289 - 1290 - # t=3: Contact 0 == Down + confident; Contact 1 == Down + confident 1291 - # First finger remains confident 1292 - [(self.ContactIds(contact_id = 0, tracking_id = 1, slot_num = 1), True, True), 1293 - (self.ContactIds(contact_id = 1, tracking_id = 0, slot_num = 0), True, True)] 1294 - ]) 1147 + self.confidence_change_assert_playback( 1148 + uhdev, 1149 + evdev, 1150 + [ 1151 + # t=0: Contact 0 == Down + !confident; Contact 1 == Down + confident 1152 + # Only second finger is confidently in contact 1153 + [ 1154 + ( 1155 + self.ContactIds(contact_id=0, tracking_id=-1, slot_num=None), 1156 + True, 1157 + False, 1158 + ), 1159 + ( 1160 + self.ContactIds(contact_id=1, tracking_id=0, slot_num=0), 1161 + True, 1162 + True, 1163 + ), 1164 + ], 1165 + # t=1: Contact 0 == Down + !confident; Contact 1 == Down + confident 1166 + # First finger gains confidence 1167 + [ 1168 + ( 1169 + self.ContactIds(contact_id=0, tracking_id=-1, slot_num=None), 1170 + True, 1171 + False, 1172 + ), 1173 + ( 1174 + self.ContactIds(contact_id=1, tracking_id=0, slot_num=0), 1175 + True, 1176 + True, 1177 + ), 1178 + ], 1179 + # t=2: Contact 0 == Down + confident; Contact 1 == Down + confident 1180 + # First finger remains confident 1181 + [ 1182 + ( 1183 + self.ContactIds(contact_id=0, tracking_id=1, slot_num=1), 1184 + True, 1185 + True, 1186 + ), 1187 + ( 1188 + self.ContactIds(contact_id=1, tracking_id=0, slot_num=0), 1189 + True, 1190 + True, 1191 + ), 1192 + ], 1193 + # t=3: Contact 0 == Down + confident; Contact 1 == Down + confident 1194 + # First finger remains confident 1195 + [ 1196 + ( 1197 + self.ContactIds(contact_id=0, tracking_id=1, slot_num=1), 1198 + True, 1199 + True, 1200 + ), 1201 + ( 1202 + self.ContactIds(contact_id=1, tracking_id=0, slot_num=0), 1203 + True, 1204 + True, 1205 + ), 1206 + ], 1207 + ], 1208 + ) 1295 1209 1296 1210 def test_confidence_gain_b(self): 1297 1211 """ ··· 1343 1175 uhdev = self.uhdev 1344 1176 evdev = uhdev.get_evdev() 1345 1177 1346 - self.confidence_change_assert_playback(uhdev, evdev, [ 1347 - # t=0: Contact 0 == Down + confident; Contact 1 == Down + confident 1348 - # First and second finger confidently in contact 1349 - [(self.ContactIds(contact_id = 0, tracking_id = 0, slot_num = 0), True, True), 1350 - (self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)], 1351 - 1352 - # t=1: Contact 0 == Down + !confident; Contact 1 == Down + confident 1353 - # Firtst finger looses confidence 1354 - [(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), True, False), 1355 - (self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)], 1356 - 1357 - # t=2: Contact 0 == Down + confident; Contact 1 == Down + confident 1358 - # First finger gains confidence 1359 - [(self.ContactIds(contact_id = 0, tracking_id = 2, slot_num = 0), True, True), 1360 - (self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)], 1361 - 1362 - # t=3: Contact 0 == !Down + confident; Contact 1 == Down + confident 1363 - # First finger goes up 1364 - [(self.ContactIds(contact_id = 0, tracking_id = -1, slot_num = 0), False, True), 1365 - (self.ContactIds(contact_id = 1, tracking_id = 1, slot_num = 1), True, True)] 1366 - ]) 1178 + self.confidence_change_assert_playback( 1179 + uhdev, 1180 + evdev, 1181 + [ 1182 + # t=0: Contact 0 == Down + confident; Contact 1 == Down + confident 1183 + # First and second finger confidently in contact 1184 + [ 1185 + ( 1186 + self.ContactIds(contact_id=0, tracking_id=0, slot_num=0), 1187 + True, 1188 + True, 1189 + ), 1190 + ( 1191 + self.ContactIds(contact_id=1, tracking_id=1, slot_num=1), 1192 + True, 1193 + True, 1194 + ), 1195 + ], 1196 + # t=1: Contact 0 == Down + !confident; Contact 1 == Down + confident 1197 + # Firtst finger looses confidence 1198 + [ 1199 + ( 1200 + self.ContactIds(contact_id=0, tracking_id=-1, slot_num=0), 1201 + True, 1202 + False, 1203 + ), 1204 + ( 1205 + self.ContactIds(contact_id=1, tracking_id=1, slot_num=1), 1206 + True, 1207 + True, 1208 + ), 1209 + ], 1210 + # t=2: Contact 0 == Down + confident; Contact 1 == Down + confident 1211 + # First finger gains confidence 1212 + [ 1213 + ( 1214 + self.ContactIds(contact_id=0, tracking_id=2, slot_num=0), 1215 + True, 1216 + True, 1217 + ), 1218 + ( 1219 + self.ContactIds(contact_id=1, tracking_id=1, slot_num=1), 1220 + True, 1221 + True, 1222 + ), 1223 + ], 1224 + # t=3: Contact 0 == !Down + confident; Contact 1 == Down + confident 1225 + # First finger goes up 1226 + [ 1227 + ( 1228 + self.ContactIds(contact_id=0, tracking_id=-1, slot_num=0), 1229 + False, 1230 + True, 1231 + ), 1232 + ( 1233 + self.ContactIds(contact_id=1, tracking_id=1, slot_num=1), 1234 + True, 1235 + True, 1236 + ), 1237 + ], 1238 + ], 1239 + )