Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

Pull HID updates from Jiri Kosina:

- import a bunch of HID selftests from out-of-tree hid-tools project
(Benjamin Tissoires)

- drastically reducing Bluetooth disconnects on hid-nintendo driven
devices (Daniel J. Ogorchock)

- lazy initialization of battery interfaces in wacom driver (Jason
Gerecke)

- generic support for all Kye tablets (David Yang)

- proper rumble queue overrun handling in hid-nintendo (Daniel J.
Ogorchock)

- support for ADC measurement in logitech-hidpp driver (Bastien Nocera)

- reset GPIO support in i2c-hid (Hans de Goede)

- improved handling of generic "Digitizer" usage (Jason Gerecke)

- support for KEY_CAMERA_FOCUS (Feng Qi)

- quirks for Apple Geyser 3 and Apple Geyser 4 (Alex Henrie)

- assorted functional fixes and device ID additions

* tag 'for-linus-2023042601' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (54 commits)
HID: amd_sfh: Fix max supported HID devices
HID: wacom: generic: Set battery quirk only when we see battery data
HID: wacom: Lazy-init batteries
HID: Ignore battery for ELAN touchscreen on ROG Flow X13 GV301RA
HID: asus: explicitly include linux/leds.h
HID: lg-g15: explicitly include linux/leds.h
HID: steelseries: explicitly include linux/leds.h
HID: apple: Set the tilde quirk flag on the Geyser 3
HID: apple: explicitly include linux/leds.h
HID: mcp2221: fix get and get_direction for gpio
HID: mcp2221: fix report layout for gpio get
HID: wacom: Set a default resolution for older tablets
HID: i2c-hid-of: Add reset GPIO support to i2c-hid-of
HID: i2c-hid-of: Allow using i2c-hid-of on non OF platforms
HID: i2c-hid-of: Consistenly use dev local variable in probe()
HID: kye: Fix rdesc for kye tablets
HID: amd_sfh: Support for additional light sensor
HID: amd_sfh: Handle "no sensors" enabled for SFH1.1
HID: amd_sfh: Increase sensor command timeout for SFH1.1
HID: amd_sfh: Correct the stop all command
...

+9668 -636
+17
Documentation/ABI/testing/sysfs-bus-usb
··· 166 166 The file will be present for all speeds of USB devices, and will 167 167 always read "no" for USB 1.1 and USB 2.0 devices. 168 168 169 + What: /sys/bus/usb/devices/<INTERFACE>/wireless_status 170 + Date: February 2023 171 + Contact: Bastien Nocera <hadess@hadess.net> 172 + Description: 173 + Some USB devices use a USB receiver dongle to communicate 174 + wirelessly with their device using proprietary protocols. This 175 + attribute allows user-space to know whether the device is 176 + connected to its receiver dongle, and, for example, consider 177 + the device to be absent when choosing whether to show the 178 + device's battery, show a headset in a list of outputs, or show 179 + an on-screen keyboard if the only wireless keyboard is 180 + turned off. 181 + This attribute is not to be used to replace protocol specific 182 + statuses available in WWAN, WLAN/Wi-Fi, Bluetooth, etc. 183 + If the device does not use a receiver dongle with a wireless 184 + device, then this attribute will not exist. 185 + 169 186 What: /sys/bus/usb/devices/.../<hub_interface>/port<X> 170 187 Date: August 2012 171 188 Contact: Lan Tianyu <tianyu.lan@intel.com>
+1
drivers/hid/amd-sfh-hid/amd_sfh_client.c
··· 147 147 case mag_idx: 148 148 return "magnetometer"; 149 149 case als_idx: 150 + case ACS_IDX: /* ambient color sensor */ 150 151 return "ALS"; 151 152 case HPD_IDX: 152 153 return "HPD";
+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 5 14 + #define MAX_HID_DEVICES 6 15 15 #define AMD_SFH_HID_VENDOR 0x1022 16 16 #define AMD_SFH_HID_PRODUCT 0x0001 17 17
+13
drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
··· 29 29 #define MAGNO_EN BIT(2) 30 30 #define HPD_EN BIT(16) 31 31 #define ALS_EN BIT(19) 32 + #define ACS_EN BIT(22) 32 33 33 34 static int sensor_mask_override = -1; 34 35 module_param_named(sensor_mask, sensor_mask_override, int, 0444); ··· 234 233 if (HPD_EN & activestatus) 235 234 sensor_id[num_of_sensors++] = HPD_IDX; 236 235 236 + if (ACS_EN & activestatus) 237 + sensor_id[num_of_sensors++] = ACS_IDX; 238 + 237 239 return num_of_sensors; 238 240 } 239 241 ··· 371 367 return devm_add_action_or_reset(&pdev->dev, privdata->mp2_ops->remove, privdata); 372 368 } 373 369 370 + static void amd_sfh_shutdown(struct pci_dev *pdev) 371 + { 372 + struct amd_mp2_dev *mp2 = pci_get_drvdata(pdev); 373 + 374 + if (mp2 && mp2->mp2_ops) 375 + mp2->mp2_ops->stop_all(mp2); 376 + } 377 + 374 378 static int __maybe_unused amd_mp2_pci_resume(struct device *dev) 375 379 { 376 380 struct amd_mp2_dev *mp2 = dev_get_drvdata(dev); ··· 413 401 .id_table = amd_mp2_pci_tbl, 414 402 .probe = amd_mp2_pci_probe, 415 403 .driver.pm = &amd_mp2_pm_ops, 404 + .shutdown = amd_sfh_shutdown, 416 405 }; 417 406 module_pci_driver(amd_mp2_pci_driver); 418 407
+1
drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
··· 23 23 #define V2_STATUS 0x2 24 24 25 25 #define HPD_IDX 16 26 + #define ACS_IDX 22 26 27 27 28 #define SENSOR_DISCOVERY_STATUS_MASK GENMASK(5, 3) 28 29 #define SENSOR_DISCOVERY_STATUS_SHIFT 3
+4
drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c
··· 48 48 sizeof(comp3_report_descriptor)); 49 49 break; 50 50 case als_idx: /* ambient light sensor */ 51 + case ACS_IDX: /* ambient color sensor */ 51 52 memset(rep_desc, 0, sizeof(als_report_descriptor)); 52 53 memcpy(rep_desc, als_report_descriptor, 53 54 sizeof(als_report_descriptor)); ··· 98 97 } 99 98 break; 100 99 case als_idx: 100 + case ACS_IDX: /* ambient color sensor */ 101 101 switch (descriptor_name) { 102 102 case descr_size: 103 103 return sizeof(als_report_descriptor); ··· 176 174 report_size = sizeof(magno_feature); 177 175 break; 178 176 case als_idx: /* ambient light sensor */ 177 + case ACS_IDX: /* ambient color sensor */ 179 178 get_common_features(&als_feature.common_property, report_id); 180 179 als_feature.als_change_sesnitivity = HID_DEFAULT_SENSITIVITY; 181 180 als_feature.als_sensitivity_min = HID_DEFAULT_MIN_VALUE; ··· 248 245 report_size = sizeof(magno_input); 249 246 break; 250 247 case als_idx: /* Als */ 248 + case ACS_IDX: /* ambient color sensor */ 251 249 get_common_inputs(&als_input.common_property, report_id); 252 250 /* For ALS ,V2 Platforms uses C2P_MSG5 register instead of DRAM access method */ 253 251 if (supported_input == V2_STATUS)
+1 -1
drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
··· 218 218 OFFSET_SENSOR_DATA_DEFAULT; 219 219 memcpy_fromio(&als_data, sensoraddr, sizeof(struct sfh_als_data)); 220 220 get_common_inputs(&als_input.common_property, report_id); 221 - als_input.illuminance_value = als_data.lux; 221 + als_input.illuminance_value = float_to_int(als_data.lux); 222 222 report_size = sizeof(als_input); 223 223 memcpy(input_report, &als_input, sizeof(als_input)); 224 224 break;
+11
drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
··· 112 112 cl_data->num_hid_devices = amd_sfh_get_sensor_num(privdata, &cl_data->sensor_idx[0]); 113 113 if (cl_data->num_hid_devices == 0) 114 114 return -ENODEV; 115 + cl_data->is_any_sensor_enabled = false; 115 116 116 117 INIT_DELAYED_WORK(&cl_data->work, amd_sfh_work); 117 118 INIT_DELAYED_WORK(&cl_data->work_buffer, amd_sfh_work_buffer); ··· 171 170 status = (status == 0) ? SENSOR_ENABLED : SENSOR_DISABLED; 172 171 173 172 if (status == SENSOR_ENABLED) { 173 + cl_data->is_any_sensor_enabled = true; 174 174 cl_data->sensor_sts[i] = SENSOR_ENABLED; 175 175 rc = amdtp_hid_probe(i, cl_data); 176 176 if (rc) { ··· 188 186 cl_data->sensor_sts[i]); 189 187 goto cleanup; 190 188 } 189 + } else { 190 + cl_data->sensor_sts[i] = SENSOR_DISABLED; 191 191 } 192 192 dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n", 193 193 cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]), 194 194 cl_data->sensor_sts[i]); 195 + } 196 + 197 + if (!cl_data->is_any_sensor_enabled) { 198 + dev_warn(dev, "Failed to discover, sensors not enabled is %d\n", 199 + cl_data->is_any_sensor_enabled); 200 + rc = -EOPNOTSUPP; 201 + goto cleanup; 195 202 } 196 203 197 204 schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
+7 -3
drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
··· 16 16 { 17 17 struct sfh_cmd_response cmd_resp; 18 18 19 - /* Get response with status within a max of 1600 ms timeout */ 19 + /* Get response with status within a max of 10000 ms timeout */ 20 20 if (!readl_poll_timeout(mp2->mmio + AMD_P2C_MSG(0), cmd_resp.resp, 21 21 (cmd_resp.response.response == 0 && 22 22 cmd_resp.response.cmd_id == cmd_id && (sid == 0xff || 23 - cmd_resp.response.sensor_id == sid)), 500, 1600000)) 23 + cmd_resp.response.sensor_id == sid)), 500, 10000000)) 24 24 return cmd_resp.response.response; 25 25 26 26 return -1; ··· 33 33 cmd_base.ul = 0; 34 34 cmd_base.cmd.cmd_id = ENABLE_SENSOR; 35 35 cmd_base.cmd.intr_disable = 0; 36 + cmd_base.cmd.sub_cmd_value = 1; 36 37 cmd_base.cmd.sensor_id = info.sensor_idx; 37 38 38 39 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG(0)); ··· 46 45 cmd_base.ul = 0; 47 46 cmd_base.cmd.cmd_id = DISABLE_SENSOR; 48 47 cmd_base.cmd.intr_disable = 0; 48 + cmd_base.cmd.sub_cmd_value = 1; 49 49 cmd_base.cmd.sensor_id = sensor_idx; 50 50 51 51 writeq(0x0, privdata->mmio + AMD_C2P_MSG(1)); ··· 58 56 struct sfh_cmd_base cmd_base; 59 57 60 58 cmd_base.ul = 0; 61 - cmd_base.cmd.cmd_id = STOP_ALL_SENSORS; 59 + cmd_base.cmd.cmd_id = DISABLE_SENSOR; 62 60 cmd_base.cmd.intr_disable = 0; 61 + /* 0xf indicates all sensors */ 62 + cmd_base.cmd.sensor_id = 0xf; 63 63 64 64 writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG(0)); 65 65 }
+4 -4
drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
··· 33 33 struct { 34 34 u32 sensor_id : 4; 35 35 u32 cmd_id : 4; 36 - u32 sub_cmd_id : 6; 37 - u32 length : 12; 38 - u32 rsvd : 5; 36 + u32 sub_cmd_id : 8; 37 + u32 sub_cmd_value : 12; 38 + u32 rsvd : 3; 39 39 u32 intr_disable : 1; 40 40 } cmd; 41 41 }; ··· 133 133 134 134 struct sfh_als_data { 135 135 struct sfh_common_data commondata; 136 - u16 lux; 136 + u32 lux; 137 137 }; 138 138 139 139 struct hpd_status {
+12 -8
drivers/hid/hid-apple.c
··· 22 22 #include <linux/slab.h> 23 23 #include <linux/timer.h> 24 24 #include <linux/string.h> 25 + #include <linux/leds.h> 25 26 26 27 #include "hid-ids.h" 27 28 ··· 876 875 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI), 877 876 .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, 878 877 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO), 879 - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, 878 + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | 879 + APPLE_ISO_TILDE_QUIRK }, 880 880 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS), 881 881 .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | 882 882 APPLE_RDESC_JIS }, 883 883 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI), 884 884 .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, 885 885 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO), 886 - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, 886 + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | 887 + APPLE_ISO_TILDE_QUIRK }, 887 888 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS), 888 889 .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | 889 890 APPLE_RDESC_JIS }, ··· 904 901 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI), 905 902 .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, 906 903 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO), 907 - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, 904 + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | 905 + APPLE_ISO_TILDE_QUIRK }, 908 906 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS), 909 907 .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | 910 908 APPLE_RDESC_JIS }, ··· 946 942 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI), 947 943 .driver_data = APPLE_HAS_FN }, 948 944 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO), 949 - .driver_data = APPLE_HAS_FN }, 945 + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 950 946 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS), 951 947 .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, 952 948 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI), 953 949 .driver_data = APPLE_HAS_FN }, 954 950 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO), 955 - .driver_data = APPLE_HAS_FN }, 951 + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 956 952 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS), 957 953 .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, 958 954 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI), 959 955 .driver_data = APPLE_HAS_FN }, 960 956 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO), 961 - .driver_data = APPLE_HAS_FN }, 957 + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 962 958 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), 963 959 .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, 964 960 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI), 965 961 .driver_data = APPLE_HAS_FN }, 966 962 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO), 967 - .driver_data = APPLE_HAS_FN }, 963 + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 968 964 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS), 969 965 .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, 970 966 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI), 971 967 .driver_data = APPLE_HAS_FN }, 972 968 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO), 973 - .driver_data = APPLE_HAS_FN }, 969 + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, 974 970 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS), 975 971 .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, 976 972 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI),
+1
drivers/hid/hid-asus.c
··· 30 30 #include <linux/input/mt.h> 31 31 #include <linux/usb.h> /* For to_usb_interface for T100 touchpad intf check */ 32 32 #include <linux/power_supply.h> 33 + #include <linux/leds.h> 33 34 34 35 #include "hid-ids.h" 35 36
+9 -1
drivers/hid/hid-ids.h
··· 415 415 #define I2C_DEVICE_ID_HP_SPECTRE_X360_15 0x2817 416 416 #define I2C_DEVICE_ID_HP_SPECTRE_X360_13_AW0020NG 0x29DF 417 417 #define I2C_DEVICE_ID_ASUS_TP420IA_TOUCHSCREEN 0x2BC8 418 + #define I2C_DEVICE_ID_ASUS_GV301RA_TOUCHSCREEN 0x2C82 418 419 #define USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN 0x2544 419 420 #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706 420 421 #define I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN 0x261A ··· 722 721 #define USB_DEVICE_ID_GENIUS_MANTICORE 0x0153 723 722 #define USB_DEVICE_ID_GENIUS_GX_IMPERATOR 0x4018 724 723 #define USB_DEVICE_ID_KYE_GPEN_560 0x5003 724 + #define USB_DEVICE_ID_KYE_EASYPEN_M406 0x5005 725 + #define USB_DEVICE_ID_KYE_EASYPEN_M506 0x500F 725 726 #define USB_DEVICE_ID_KYE_EASYPEN_I405X 0x5010 726 727 #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X 0x5011 727 - #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2 0x501a 728 + #define USB_DEVICE_ID_KYE_EASYPEN_M406W 0x5012 728 729 #define USB_DEVICE_ID_KYE_EASYPEN_M610X 0x5013 730 + #define USB_DEVICE_ID_KYE_EASYPEN_340 0x5014 729 731 #define USB_DEVICE_ID_KYE_PENSKETCH_M912 0x5015 732 + #define USB_DEVICE_ID_KYE_MOUSEPEN_M508WX 0x5016 733 + #define USB_DEVICE_ID_KYE_MOUSEPEN_M508X 0x5017 730 734 #define USB_DEVICE_ID_KYE_EASYPEN_M406XE 0x5019 735 + #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2 0x501A 736 + #define USB_DEVICE_ID_KYE_PENSKETCH_T609A 0x501B 731 737 732 738 #define USB_VENDOR_ID_LABTEC 0x1020 733 739 #define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD 0x0006
+12
drivers/hid/hid-input.c
··· 372 372 HID_BATTERY_QUIRK_IGNORE }, 373 373 { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_ASUS_TP420IA_TOUCHSCREEN), 374 374 HID_BATTERY_QUIRK_IGNORE }, 375 + { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_ASUS_GV301RA_TOUCHSCREEN), 376 + HID_BATTERY_QUIRK_IGNORE }, 375 377 { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN), 376 378 HID_BATTERY_QUIRK_IGNORE }, 377 379 { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN), ··· 1269 1267 return; 1270 1268 } 1271 1269 goto unknown; 1270 + case HID_UP_CAMERA: 1271 + switch (usage->hid & HID_USAGE) { 1272 + case 0x020: 1273 + map_key_clear(KEY_CAMERA_FOCUS); break; 1274 + case 0x021: 1275 + map_key_clear(KEY_CAMERA); break; 1276 + default: 1277 + goto ignore; 1278 + } 1279 + break; 1272 1280 1273 1281 case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */ 1274 1282 set_bit(EV_REP, input->evbit);
+411 -531
drivers/hid/hid-kye.c
··· 5 5 * Copyright (c) 2009 Jiri Kosina 6 6 * Copyright (c) 2009 Tomas Hanak 7 7 * Copyright (c) 2012 Nikolai Kondrashov 8 + * Copyright (c) 2023 David Yang 8 9 */ 9 10 10 - /* 11 - */ 12 - 11 + #include <asm-generic/unaligned.h> 13 12 #include <linux/device.h> 14 13 #include <linux/hid.h> 15 14 #include <linux/module.h> 16 15 17 16 #include "hid-ids.h" 18 17 19 - /* Original EasyPen i405X report descriptor size */ 20 - #define EASYPEN_I405X_RDESC_ORIG_SIZE 476 18 + /* Data gathered from Database/VID0458_PID????/Vista/TBoard/default.xml in ioTablet driver 19 + * 20 + * TODO: 21 + * - Add battery and sleep support for EasyPen M406W and MousePen M508WX 22 + * - Investigate ScrollZ.MiceFMT buttons of EasyPen M406 23 + */ 21 24 22 - /* Fixed EasyPen i405X report descriptor */ 23 - static __u8 easypen_i405x_rdesc_fixed[] = { 24 - 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 25 - 0x09, 0x01, /* Usage (01h), */ 26 - 0xA1, 0x01, /* Collection (Application), */ 27 - 0x85, 0x05, /* Report ID (5), */ 28 - 0x09, 0x01, /* Usage (01h), */ 29 - 0x15, 0x80, /* Logical Minimum (-128), */ 30 - 0x25, 0x7F, /* Logical Maximum (127), */ 31 - 0x75, 0x08, /* Report Size (8), */ 32 - 0x95, 0x07, /* Report Count (7), */ 33 - 0xB1, 0x02, /* Feature (Variable), */ 34 - 0xC0, /* End Collection, */ 35 - 0x05, 0x0D, /* Usage Page (Digitizer), */ 36 - 0x09, 0x01, /* Usage (Digitizer), */ 37 - 0xA1, 0x01, /* Collection (Application), */ 38 - 0x85, 0x10, /* Report ID (16), */ 39 - 0x09, 0x20, /* Usage (Stylus), */ 40 - 0xA0, /* Collection (Physical), */ 41 - 0x14, /* Logical Minimum (0), */ 42 - 0x25, 0x01, /* Logical Maximum (1), */ 43 - 0x75, 0x01, /* Report Size (1), */ 44 - 0x09, 0x42, /* Usage (Tip Switch), */ 45 - 0x09, 0x44, /* Usage (Barrel Switch), */ 46 - 0x09, 0x46, /* Usage (Tablet Pick), */ 47 - 0x95, 0x03, /* Report Count (3), */ 48 - 0x81, 0x02, /* Input (Variable), */ 49 - 0x95, 0x04, /* Report Count (4), */ 50 - 0x81, 0x03, /* Input (Constant, Variable), */ 51 - 0x09, 0x32, /* Usage (In Range), */ 52 - 0x95, 0x01, /* Report Count (1), */ 53 - 0x81, 0x02, /* Input (Variable), */ 54 - 0x75, 0x10, /* Report Size (16), */ 55 - 0x95, 0x01, /* Report Count (1), */ 56 - 0xA4, /* Push, */ 57 - 0x05, 0x01, /* Usage Page (Desktop), */ 58 - 0x55, 0xFD, /* Unit Exponent (-3), */ 59 - 0x65, 0x13, /* Unit (Inch), */ 60 - 0x34, /* Physical Minimum (0), */ 61 - 0x09, 0x30, /* Usage (X), */ 62 - 0x46, 0x7C, 0x15, /* Physical Maximum (5500), */ 63 - 0x26, 0x00, 0x37, /* Logical Maximum (14080), */ 64 - 0x81, 0x02, /* Input (Variable), */ 65 - 0x09, 0x31, /* Usage (Y), */ 66 - 0x46, 0xA0, 0x0F, /* Physical Maximum (4000), */ 67 - 0x26, 0x00, 0x28, /* Logical Maximum (10240), */ 68 - 0x81, 0x02, /* Input (Variable), */ 69 - 0xB4, /* Pop, */ 70 - 0x09, 0x30, /* Usage (Tip Pressure), */ 71 - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 72 - 0x81, 0x02, /* Input (Variable), */ 73 - 0xC0, /* End Collection, */ 74 - 0xC0 /* End Collection */ 25 + static const __u8 easypen_m406_control_rdesc[] = { 26 + 0x05, 0x0C, /* Usage Page (Consumer), */ 27 + 0x09, 0x01, /* Usage (Consumer Control), */ 28 + 0xA1, 0x01, /* Collection (Application), */ 29 + 0x85, 0x12, /* Report ID (18), */ 30 + 0x0A, 0x45, 0x02, /* Usage (AC Rotate), */ 31 + 0x09, 0x40, /* Usage (Menu), */ 32 + 0x0A, 0x2F, 0x02, /* Usage (AC Zoom), */ 33 + 0x0A, 0x46, 0x02, /* Usage (AC Resize), */ 34 + 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */ 35 + 0x0A, 0x6A, 0x02, /* Usage (AC Delete), */ 36 + 0x0A, 0x24, 0x02, /* Usage (AC Back), */ 37 + 0x0A, 0x25, 0x02, /* Usage (AC Forward), */ 38 + 0x14, /* Logical Minimum (0), */ 39 + 0x25, 0x01, /* Logical Maximum (1), */ 40 + 0x75, 0x01, /* Report Size (1), */ 41 + 0x95, 0x08, /* Report Count (8), */ 42 + 0x81, 0x02, /* Input (Variable), */ 43 + 0x95, 0x30, /* Report Count (48), */ 44 + 0x81, 0x01, /* Input (Constant), */ 45 + 0xC0 /* End Collection */ 75 46 }; 76 47 77 - /* Original MousePen i608X report descriptor size */ 78 - #define MOUSEPEN_I608X_RDESC_ORIG_SIZE 476 79 - 80 - /* Fixed MousePen i608X report descriptor */ 81 - static __u8 mousepen_i608x_rdesc_fixed[] = { 82 - 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 83 - 0x09, 0x01, /* Usage (01h), */ 84 - 0xA1, 0x01, /* Collection (Application), */ 85 - 0x85, 0x05, /* Report ID (5), */ 86 - 0x09, 0x01, /* Usage (01h), */ 87 - 0x15, 0x80, /* Logical Minimum (-128), */ 88 - 0x25, 0x7F, /* Logical Maximum (127), */ 89 - 0x75, 0x08, /* Report Size (8), */ 90 - 0x95, 0x07, /* Report Count (7), */ 91 - 0xB1, 0x02, /* Feature (Variable), */ 92 - 0xC0, /* End Collection, */ 93 - 0x05, 0x0D, /* Usage Page (Digitizer), */ 94 - 0x09, 0x01, /* Usage (Digitizer), */ 95 - 0xA1, 0x01, /* Collection (Application), */ 96 - 0x85, 0x10, /* Report ID (16), */ 97 - 0x09, 0x20, /* Usage (Stylus), */ 98 - 0xA0, /* Collection (Physical), */ 99 - 0x14, /* Logical Minimum (0), */ 100 - 0x25, 0x01, /* Logical Maximum (1), */ 101 - 0x75, 0x01, /* Report Size (1), */ 102 - 0x09, 0x42, /* Usage (Tip Switch), */ 103 - 0x09, 0x44, /* Usage (Barrel Switch), */ 104 - 0x09, 0x46, /* Usage (Tablet Pick), */ 105 - 0x95, 0x03, /* Report Count (3), */ 106 - 0x81, 0x02, /* Input (Variable), */ 107 - 0x95, 0x04, /* Report Count (4), */ 108 - 0x81, 0x03, /* Input (Constant, Variable), */ 109 - 0x09, 0x32, /* Usage (In Range), */ 110 - 0x95, 0x01, /* Report Count (1), */ 111 - 0x81, 0x02, /* Input (Variable), */ 112 - 0x75, 0x10, /* Report Size (16), */ 113 - 0x95, 0x01, /* Report Count (1), */ 114 - 0xA4, /* Push, */ 115 - 0x05, 0x01, /* Usage Page (Desktop), */ 116 - 0x55, 0xFD, /* Unit Exponent (-3), */ 117 - 0x65, 0x13, /* Unit (Inch), */ 118 - 0x34, /* Physical Minimum (0), */ 119 - 0x09, 0x30, /* Usage (X), */ 120 - 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */ 121 - 0x26, 0x00, 0x50, /* Logical Maximum (20480), */ 122 - 0x81, 0x02, /* Input (Variable), */ 123 - 0x09, 0x31, /* Usage (Y), */ 124 - 0x46, 0x70, 0x17, /* Physical Maximum (6000), */ 125 - 0x26, 0x00, 0x3C, /* Logical Maximum (15360), */ 126 - 0x81, 0x02, /* Input (Variable), */ 127 - 0xB4, /* Pop, */ 128 - 0x09, 0x30, /* Usage (Tip Pressure), */ 129 - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 130 - 0x81, 0x02, /* Input (Variable), */ 131 - 0xC0, /* End Collection, */ 132 - 0xC0, /* End Collection, */ 133 - 0x05, 0x01, /* Usage Page (Desktop), */ 134 - 0x09, 0x02, /* Usage (Mouse), */ 135 - 0xA1, 0x01, /* Collection (Application), */ 136 - 0x85, 0x11, /* Report ID (17), */ 137 - 0x09, 0x01, /* Usage (Pointer), */ 138 - 0xA0, /* Collection (Physical), */ 139 - 0x14, /* Logical Minimum (0), */ 140 - 0xA4, /* Push, */ 141 - 0x05, 0x09, /* Usage Page (Button), */ 142 - 0x75, 0x01, /* Report Size (1), */ 143 - 0x19, 0x01, /* Usage Minimum (01h), */ 144 - 0x29, 0x03, /* Usage Maximum (03h), */ 145 - 0x25, 0x01, /* Logical Maximum (1), */ 146 - 0x95, 0x03, /* Report Count (3), */ 147 - 0x81, 0x02, /* Input (Variable), */ 148 - 0x95, 0x05, /* Report Count (5), */ 149 - 0x81, 0x01, /* Input (Constant), */ 150 - 0xB4, /* Pop, */ 151 - 0x95, 0x01, /* Report Count (1), */ 152 - 0xA4, /* Push, */ 153 - 0x55, 0xFD, /* Unit Exponent (-3), */ 154 - 0x65, 0x13, /* Unit (Inch), */ 155 - 0x34, /* Physical Minimum (0), */ 156 - 0x75, 0x10, /* Report Size (16), */ 157 - 0x09, 0x30, /* Usage (X), */ 158 - 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */ 159 - 0x26, 0x00, 0x50, /* Logical Maximum (20480), */ 160 - 0x81, 0x02, /* Input (Variable), */ 161 - 0x09, 0x31, /* Usage (Y), */ 162 - 0x46, 0x70, 0x17, /* Physical Maximum (6000), */ 163 - 0x26, 0x00, 0x3C, /* Logical Maximum (15360), */ 164 - 0x81, 0x02, /* Input (Variable), */ 165 - 0xB4, /* Pop, */ 166 - 0x75, 0x08, /* Report Size (8), */ 167 - 0x09, 0x38, /* Usage (Wheel), */ 168 - 0x15, 0xFF, /* Logical Minimum (-1), */ 169 - 0x25, 0x01, /* Logical Maximum (1), */ 170 - 0x81, 0x06, /* Input (Variable, Relative), */ 171 - 0x81, 0x01, /* Input (Constant), */ 172 - 0xC0, /* End Collection, */ 173 - 0xC0 /* End Collection */ 48 + static const __u8 easypen_m506_control_rdesc[] = { 49 + 0x05, 0x0C, /* Usage Page (Consumer), */ 50 + 0x09, 0x01, /* Usage (Consumer Control), */ 51 + 0xA1, 0x01, /* Collection (Application), */ 52 + 0x85, 0x12, /* Report ID (18), */ 53 + 0x0A, 0x6A, 0x02, /* Usage (AC Delete), */ 54 + 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */ 55 + 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ 56 + 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ 57 + 0x14, /* Logical Minimum (0), */ 58 + 0x25, 0x01, /* Logical Maximum (1), */ 59 + 0x75, 0x01, /* Report Size (1), */ 60 + 0x95, 0x04, /* Report Count (4), */ 61 + 0x81, 0x02, /* Input (Variable), */ 62 + 0x95, 0x34, /* Report Count (52), */ 63 + 0x81, 0x01, /* Input (Constant), */ 64 + 0xC0 /* End Collection */ 174 65 }; 175 66 176 - /* Original MousePen i608X v2 report descriptor size */ 177 - #define MOUSEPEN_I608X_V2_RDESC_ORIG_SIZE 482 67 + static const __u8 easypen_m406w_control_rdesc[] = { 68 + 0x05, 0x0C, /* Usage Page (Consumer), */ 69 + 0x09, 0x01, /* Usage (Consumer Control), */ 70 + 0xA1, 0x01, /* Collection (Application), */ 71 + 0x85, 0x12, /* Report ID (18), */ 72 + 0x0A, 0x6A, 0x02, /* Usage (AC Delete), */ 73 + 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */ 74 + 0x0A, 0x01, 0x02, /* Usage (AC New), */ 75 + 0x09, 0x40, /* Usage (Menu), */ 76 + 0x14, /* Logical Minimum (0), */ 77 + 0x25, 0x01, /* Logical Maximum (1), */ 78 + 0x75, 0x01, /* Report Size (1), */ 79 + 0x95, 0x04, /* Report Count (4), */ 80 + 0x81, 0x02, /* Input (Variable), */ 81 + 0x95, 0x34, /* Report Count (52), */ 82 + 0x81, 0x01, /* Input (Constant), */ 83 + 0xC0 /* End Collection */ 84 + }; 178 85 179 - /* Fixed MousePen i608X v2 report descriptor */ 180 - static __u8 mousepen_i608x_v2_rdesc_fixed[] = { 86 + static const __u8 easypen_m610x_control_rdesc[] = { 87 + 0x05, 0x0C, /* Usage Page (Consumer), */ 88 + 0x09, 0x01, /* Usage (Consumer Control), */ 89 + 0xA1, 0x01, /* Collection (Application), */ 90 + 0x85, 0x12, /* Report ID (18), */ 91 + 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */ 92 + 0x0A, 0x79, 0x02, /* Usage (AC Redo Or Repeat), */ 93 + 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ 94 + 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ 95 + 0x14, /* Logical Minimum (0), */ 96 + 0x25, 0x01, /* Logical Maximum (1), */ 97 + 0x75, 0x01, /* Report Size (1), */ 98 + 0x95, 0x04, /* Report Count (4), */ 99 + 0x81, 0x02, /* Input (Variable), */ 100 + 0x95, 0x34, /* Report Count (52), */ 101 + 0x81, 0x01, /* Input (Constant), */ 102 + 0xC0 /* End Collection */ 103 + }; 104 + 105 + static const __u8 pensketch_m912_control_rdesc[] = { 106 + 0x05, 0x0C, /* Usage Page (Consumer), */ 107 + 0x09, 0x01, /* Usage (Consumer Control), */ 108 + 0xA1, 0x01, /* Collection (Application), */ 109 + 0x85, 0x12, /* Report ID (18), */ 110 + 0x14, /* Logical Minimum (0), */ 111 + 0x25, 0x01, /* Logical Maximum (1), */ 112 + 0x75, 0x01, /* Report Size (1), */ 113 + 0x95, 0x08, /* Report Count (8), */ 114 + 0x05, 0x0C, /* Usage Page (Consumer), */ 115 + 0x0A, 0x6A, 0x02, /* Usage (AC Delete), */ 116 + 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */ 117 + 0x0A, 0x01, 0x02, /* Usage (AC New), */ 118 + 0x0A, 0x2F, 0x02, /* Usage (AC Zoom), */ 119 + 0x0A, 0x25, 0x02, /* Usage (AC Forward), */ 120 + 0x0A, 0x24, 0x02, /* Usage (AC Back), */ 121 + 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ 122 + 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ 123 + 0x81, 0x02, /* Input (Variable), */ 124 + 0x95, 0x30, /* Report Count (48), */ 125 + 0x81, 0x03, /* Input (Constant, Variable), */ 126 + 0xC0 /* End Collection */ 127 + }; 128 + 129 + static const __u8 mousepen_m508wx_control_rdesc[] = { 130 + 0x05, 0x0C, /* Usage Page (Consumer), */ 131 + 0x09, 0x01, /* Usage (Consumer Control), */ 132 + 0xA1, 0x01, /* Collection (Application), */ 133 + 0x85, 0x12, /* Report ID (18), */ 134 + 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */ 135 + 0x0A, 0x6A, 0x02, /* Usage (AC Delete), */ 136 + 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ 137 + 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ 138 + 0x14, /* Logical Minimum (0), */ 139 + 0x25, 0x01, /* Logical Maximum (1), */ 140 + 0x75, 0x01, /* Report Size (1), */ 141 + 0x95, 0x04, /* Report Count (4), */ 142 + 0x81, 0x02, /* Input (Variable), */ 143 + 0x95, 0x34, /* Report Count (52), */ 144 + 0x81, 0x01, /* Input (Constant), */ 145 + 0xC0 /* End Collection */ 146 + }; 147 + 148 + static const __u8 mousepen_m508x_control_rdesc[] = { 149 + 0x05, 0x0C, /* Usage Page (Consumer), */ 150 + 0x09, 0x01, /* Usage (Consumer Control), */ 151 + 0xA1, 0x01, /* Collection (Application), */ 152 + 0x85, 0x12, /* Report ID (18), */ 153 + 0x0A, 0x01, 0x02, /* Usage (AC New), */ 154 + 0x09, 0x40, /* Usage (Menu), */ 155 + 0x0A, 0x6A, 0x02, /* Usage (AC Delete), */ 156 + 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */ 157 + 0x14, /* Logical Minimum (0), */ 158 + 0x25, 0x01, /* Logical Maximum (1), */ 159 + 0x75, 0x01, /* Report Size (1), */ 160 + 0x95, 0x04, /* Report Count (4), */ 161 + 0x81, 0x02, /* Input (Variable), */ 162 + 0x81, 0x01, /* Input (Constant), */ 163 + 0x15, 0xFF, /* Logical Minimum (-1), */ 164 + 0x95, 0x10, /* Report Count (16), */ 165 + 0x81, 0x01, /* Input (Constant), */ 166 + 0x0A, 0x35, 0x02, /* Usage (AC Scroll), */ 167 + 0x0A, 0x2F, 0x02, /* Usage (AC Zoom), */ 168 + 0x0A, 0x38, 0x02, /* Usage (AC Pan), */ 169 + 0x75, 0x08, /* Report Size (8), */ 170 + 0x95, 0x03, /* Report Count (3), */ 171 + 0x81, 0x06, /* Input (Variable, Relative), */ 172 + 0x95, 0x01, /* Report Count (1), */ 173 + 0x81, 0x01, /* Input (Constant), */ 174 + 0xC0 /* End Collection */ 175 + }; 176 + 177 + static const __u8 easypen_m406xe_control_rdesc[] = { 178 + 0x05, 0x0C, /* Usage Page (Consumer), */ 179 + 0x09, 0x01, /* Usage (Consumer Control), */ 180 + 0xA1, 0x01, /* Collection (Application), */ 181 + 0x85, 0x12, /* Report ID (18), */ 182 + 0x14, /* Logical Minimum (0), */ 183 + 0x25, 0x01, /* Logical Maximum (1), */ 184 + 0x75, 0x01, /* Report Size (1), */ 185 + 0x95, 0x04, /* Report Count (4), */ 186 + 0x0A, 0x79, 0x02, /* Usage (AC Redo Or Repeat), */ 187 + 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */ 188 + 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ 189 + 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ 190 + 0x81, 0x02, /* Input (Variable), */ 191 + 0x95, 0x34, /* Report Count (52), */ 192 + 0x81, 0x03, /* Input (Constant, Variable), */ 193 + 0xC0 /* End Collection */ 194 + }; 195 + 196 + static const __u8 pensketch_t609a_control_rdesc[] = { 197 + 0x05, 0x0C, /* Usage Page (Consumer), */ 198 + 0x09, 0x01, /* Usage (Consumer Control), */ 199 + 0xA1, 0x01, /* Collection (Application), */ 200 + 0x85, 0x12, /* Report ID (18), */ 201 + 0x0A, 0x6A, 0x02, /* Usage (AC Delete), */ 202 + 0x14, /* Logical Minimum (0), */ 203 + 0x25, 0x01, /* Logical Maximum (1), */ 204 + 0x75, 0x01, /* Report Size (1), */ 205 + 0x95, 0x08, /* Report Count (8), */ 206 + 0x81, 0x02, /* Input (Variable), */ 207 + 0x95, 0x37, /* Report Count (55), */ 208 + 0x81, 0x01, /* Input (Constant), */ 209 + 0xC0 /* End Collection */ 210 + }; 211 + 212 + /* Fix indexes in kye_tablet_fixup if you change this */ 213 + static const __u8 kye_tablet_rdesc[] = { 181 214 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 182 215 0x09, 0x01, /* Usage (01h), */ 183 216 0xA1, 0x01, /* Collection (Application), */ 184 217 0x85, 0x05, /* Report ID (5), */ 185 - 0x09, 0x01, /* Usage (01h), */ 186 - 0x15, 0x80, /* Logical Minimum (-128), */ 187 - 0x25, 0x7F, /* Logical Maximum (127), */ 188 - 0x75, 0x08, /* Report Size (8), */ 189 - 0x95, 0x07, /* Report Count (7), */ 190 - 0xB1, 0x02, /* Feature (Variable), */ 191 - 0xC0, /* End Collection, */ 192 - 0x05, 0x0D, /* Usage Page (Digitizer), */ 193 - 0x09, 0x01, /* Usage (Digitizer), */ 194 - 0xA1, 0x01, /* Collection (Application), */ 195 - 0x85, 0x10, /* Report ID (16), */ 196 - 0x09, 0x20, /* Usage (Stylus), */ 197 - 0xA0, /* Collection (Physical), */ 198 - 0x14, /* Logical Minimum (0), */ 199 - 0x25, 0x01, /* Logical Maximum (1), */ 200 - 0x75, 0x01, /* Report Size (1), */ 201 - 0x09, 0x42, /* Usage (Tip Switch), */ 202 - 0x09, 0x44, /* Usage (Barrel Switch), */ 203 - 0x09, 0x46, /* Usage (Tablet Pick), */ 204 - 0x95, 0x03, /* Report Count (3), */ 205 - 0x81, 0x02, /* Input (Variable), */ 206 - 0x95, 0x04, /* Report Count (4), */ 207 - 0x81, 0x03, /* Input (Constant, Variable), */ 208 - 0x09, 0x32, /* Usage (In Range), */ 209 - 0x95, 0x01, /* Report Count (1), */ 210 - 0x81, 0x02, /* Input (Variable), */ 211 - 0x75, 0x10, /* Report Size (16), */ 212 - 0x95, 0x01, /* Report Count (1), */ 213 - 0xA4, /* Push, */ 214 - 0x05, 0x01, /* Usage Page (Desktop), */ 215 - 0x55, 0xFD, /* Unit Exponent (-3), */ 216 - 0x65, 0x13, /* Unit (Inch), */ 217 - 0x34, /* Physical Minimum (0), */ 218 - 0x09, 0x30, /* Usage (X), */ 219 - 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */ 220 - 0x27, 0x00, 0xA0, 0x00, 0x00, /* Logical Maximum (40960), */ 221 - 0x81, 0x02, /* Input (Variable), */ 222 - 0x09, 0x31, /* Usage (Y), */ 223 - 0x46, 0x70, 0x17, /* Physical Maximum (6000), */ 224 - 0x26, 0x00, 0x78, /* Logical Maximum (30720), */ 225 - 0x81, 0x02, /* Input (Variable), */ 226 - 0xB4, /* Pop, */ 227 - 0x09, 0x30, /* Usage (Tip Pressure), */ 228 - 0x26, 0xFF, 0x07, /* Logical Maximum (2047), */ 229 - 0x81, 0x02, /* Input (Variable), */ 230 - 0xC0, /* End Collection, */ 231 - 0xC0, /* End Collection, */ 232 - 0x05, 0x01, /* Usage Page (Desktop), */ 233 - 0x09, 0x02, /* Usage (Mouse), */ 234 - 0xA1, 0x01, /* Collection (Application), */ 235 - 0x85, 0x11, /* Report ID (17), */ 236 - 0x09, 0x01, /* Usage (Pointer), */ 237 - 0xA0, /* Collection (Physical), */ 238 - 0x14, /* Logical Minimum (0), */ 239 - 0xA4, /* Push, */ 240 - 0x05, 0x09, /* Usage Page (Button), */ 241 - 0x75, 0x01, /* Report Size (1), */ 242 - 0x19, 0x01, /* Usage Minimum (01h), */ 243 - 0x29, 0x03, /* Usage Maximum (03h), */ 244 - 0x25, 0x01, /* Logical Maximum (1), */ 245 - 0x95, 0x03, /* Report Count (3), */ 246 - 0x81, 0x02, /* Input (Variable), */ 247 - 0x95, 0x05, /* Report Count (5), */ 248 - 0x81, 0x01, /* Input (Constant), */ 249 - 0xB4, /* Pop, */ 250 - 0x95, 0x01, /* Report Count (1), */ 251 - 0xA4, /* Push, */ 252 - 0x55, 0xFD, /* Unit Exponent (-3), */ 253 - 0x65, 0x13, /* Unit (Inch), */ 254 - 0x34, /* Physical Minimum (0), */ 255 - 0x75, 0x10, /* Report Size (16), */ 256 - 0x09, 0x30, /* Usage (X), */ 257 - 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */ 258 - 0x27, 0x00, 0xA0, 0x00, 0x00, /* Logical Maximum (40960), */ 259 - 0x81, 0x02, /* Input (Variable), */ 260 - 0x09, 0x31, /* Usage (Y), */ 261 - 0x46, 0x70, 0x17, /* Physical Maximum (6000), */ 262 - 0x26, 0x00, 0x78, /* Logical Maximum (30720), */ 263 - 0x81, 0x02, /* Input (Variable), */ 264 - 0xB4, /* Pop, */ 265 - 0x75, 0x08, /* Report Size (8), */ 266 - 0x09, 0x38, /* Usage (Wheel), */ 267 - 0x15, 0xFF, /* Logical Minimum (-1), */ 268 - 0x25, 0x01, /* Logical Maximum (1), */ 269 - 0x81, 0x06, /* Input (Variable, Relative), */ 270 - 0x81, 0x01, /* Input (Constant), */ 271 - 0xC0, /* End Collection, */ 272 - 0xC0 /* End Collection */ 273 - }; 274 - 275 - /* Original EasyPen M610X report descriptor size */ 276 - #define EASYPEN_M610X_RDESC_ORIG_SIZE 476 277 - 278 - /* Fixed EasyPen M610X report descriptor */ 279 - static __u8 easypen_m610x_rdesc_fixed[] = { 280 - 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 281 - 0x09, 0x01, /* Usage (01h), */ 282 - 0xA1, 0x01, /* Collection (Application), */ 283 - 0x85, 0x05, /* Report ID (5), */ 284 - 0x09, 0x01, /* Usage (01h), */ 285 - 0x15, 0x80, /* Logical Minimum (-128), */ 286 - 0x25, 0x7F, /* Logical Maximum (127), */ 287 - 0x75, 0x08, /* Report Size (8), */ 288 - 0x95, 0x07, /* Report Count (7), */ 289 - 0xB1, 0x02, /* Feature (Variable), */ 290 - 0xC0, /* End Collection, */ 291 - 0x05, 0x0D, /* Usage Page (Digitizer), */ 292 - 0x09, 0x01, /* Usage (Digitizer), */ 293 - 0xA1, 0x01, /* Collection (Application), */ 294 - 0x85, 0x10, /* Report ID (16), */ 295 - 0x09, 0x20, /* Usage (Stylus), */ 296 - 0xA0, /* Collection (Physical), */ 297 - 0x14, /* Logical Minimum (0), */ 298 - 0x25, 0x01, /* Logical Maximum (1), */ 299 - 0x75, 0x01, /* Report Size (1), */ 300 - 0x09, 0x42, /* Usage (Tip Switch), */ 301 - 0x09, 0x44, /* Usage (Barrel Switch), */ 302 - 0x09, 0x46, /* Usage (Tablet Pick), */ 303 - 0x95, 0x03, /* Report Count (3), */ 304 - 0x81, 0x02, /* Input (Variable), */ 305 - 0x95, 0x04, /* Report Count (4), */ 306 - 0x81, 0x03, /* Input (Constant, Variable), */ 307 - 0x09, 0x32, /* Usage (In Range), */ 308 - 0x95, 0x01, /* Report Count (1), */ 309 - 0x81, 0x02, /* Input (Variable), */ 310 - 0x75, 0x10, /* Report Size (16), */ 311 - 0x95, 0x01, /* Report Count (1), */ 312 - 0xA4, /* Push, */ 313 - 0x05, 0x01, /* Usage Page (Desktop), */ 314 - 0x55, 0xFD, /* Unit Exponent (-3), */ 315 - 0x65, 0x13, /* Unit (Inch), */ 316 - 0x34, /* Physical Minimum (0), */ 317 - 0x09, 0x30, /* Usage (X), */ 318 - 0x46, 0x10, 0x27, /* Physical Maximum (10000), */ 319 - 0x27, 0x00, 0xA0, 0x00, 0x00, /* Logical Maximum (40960), */ 320 - 0x81, 0x02, /* Input (Variable), */ 321 - 0x09, 0x31, /* Usage (Y), */ 322 - 0x46, 0x6A, 0x18, /* Physical Maximum (6250), */ 323 - 0x26, 0x00, 0x64, /* Logical Maximum (25600), */ 324 - 0x81, 0x02, /* Input (Variable), */ 325 - 0xB4, /* Pop, */ 326 - 0x09, 0x30, /* Usage (Tip Pressure), */ 327 - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 328 - 0x81, 0x02, /* Input (Variable), */ 329 - 0xC0, /* End Collection, */ 330 - 0xC0, /* End Collection, */ 331 - 0x05, 0x0C, /* Usage Page (Consumer), */ 332 - 0x09, 0x01, /* Usage (Consumer Control), */ 333 - 0xA1, 0x01, /* Collection (Application), */ 334 - 0x85, 0x12, /* Report ID (18), */ 335 - 0x14, /* Logical Minimum (0), */ 336 - 0x25, 0x01, /* Logical Maximum (1), */ 337 - 0x75, 0x01, /* Report Size (1), */ 338 - 0x95, 0x04, /* Report Count (4), */ 339 - 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */ 340 - 0x0A, 0x79, 0x02, /* Usage (AC Redo Or Repeat), */ 341 - 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ 342 - 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ 343 - 0x81, 0x02, /* Input (Variable), */ 344 - 0x95, 0x01, /* Report Count (1), */ 345 - 0x75, 0x14, /* Report Size (20), */ 346 - 0x81, 0x03, /* Input (Constant, Variable), */ 347 - 0x75, 0x20, /* Report Size (32), */ 348 - 0x81, 0x03, /* Input (Constant, Variable), */ 349 - 0xC0 /* End Collection */ 350 - }; 351 - 352 - 353 - /* Original PenSketch M912 report descriptor size */ 354 - #define PENSKETCH_M912_RDESC_ORIG_SIZE 482 355 - 356 - /* Fixed PenSketch M912 report descriptor */ 357 - static __u8 pensketch_m912_rdesc_fixed[] = { 358 - 0x05, 0x01, /* Usage Page (Desktop), */ 359 - 0x08, /* Usage (00h), */ 360 - 0xA1, 0x01, /* Collection (Application), */ 361 - 0x85, 0x05, /* Report ID (5), */ 362 - 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 363 218 0x09, 0x01, /* Usage (01h), */ 364 219 0x15, 0x81, /* Logical Minimum (-127), */ 365 220 0x25, 0x7F, /* Logical Maximum (127), */ ··· 237 382 0x95, 0x03, /* Report Count (3), */ 238 383 0x81, 0x02, /* Input (Variable), */ 239 384 0x95, 0x04, /* Report Count (4), */ 240 - 0x81, 0x03, /* Input (Constant, Variable), */ 385 + 0x81, 0x01, /* Input (Constant), */ 241 386 0x09, 0x32, /* Usage (In Range), */ 242 387 0x95, 0x01, /* Report Count (1), */ 243 388 0x81, 0x02, /* Input (Variable), */ 244 389 0x75, 0x10, /* Report Size (16), */ 245 - 0x95, 0x01, /* Report Count (1), */ 246 390 0xA4, /* Push, */ 247 391 0x05, 0x01, /* Usage Page (Desktop), */ 248 - 0x55, 0xFD, /* Unit Exponent (-3), */ 249 - 0x65, 0x13, /* Unit (Inch), */ 250 - 0x14, /* Logical Minimum (0), */ 251 - 0x34, /* Physical Minimum (0), */ 252 392 0x09, 0x30, /* Usage (X), */ 253 - 0x27, 0x00, 0xF0, 0x00, 0x00, /* Logical Maximum (61440), */ 254 - 0x46, 0xE0, 0x2E, /* Physical Maximum (12000), */ 393 + 0x27, 0xFF, 0x7F, 0x00, 0x00, /* Logical Maximum (32767), */ 394 + 0x34, /* Physical Minimum (0), */ 395 + 0x47, 0x00, 0x00, 0x00, 0x00, /* Physical Maximum (0), */ 396 + 0x65, 0x11, /* Unit (Centimeter), */ 397 + 0x55, 0x00, /* Unit Exponent (0), */ 398 + 0x75, 0x10, /* Report Size (16), */ 255 399 0x81, 0x02, /* Input (Variable), */ 256 400 0x09, 0x31, /* Usage (Y), */ 257 - 0x27, 0x00, 0xB4, 0x00, 0x00, /* Logical Maximum (46080), */ 258 - 0x46, 0x28, 0x23, /* Physical Maximum (9000), */ 401 + 0x27, 0xFF, 0x7F, 0x00, 0x00, /* Logical Maximum (32767), */ 402 + 0x47, 0x00, 0x00, 0x00, 0x00, /* Physical Maximum (0), */ 259 403 0x81, 0x02, /* Input (Variable), */ 260 404 0xB4, /* Pop, */ 405 + 0x05, 0x0D, /* Usage Page (Digitizer), */ 261 406 0x09, 0x30, /* Usage (Tip Pressure), */ 262 - 0x14, /* Logical Minimum (0), */ 263 - 0x26, 0xFF, 0x07, /* Logical Maximum (2047), */ 407 + 0x27, 0xFF, 0x07, 0x00, 0x00, /* Logical Maximum (2047), */ 264 408 0x81, 0x02, /* Input (Variable), */ 265 409 0xC0, /* End Collection, */ 266 410 0xC0, /* End Collection, */ ··· 270 416 0x09, 0x21, /* Usage (Puck), */ 271 417 0xA0, /* Collection (Physical), */ 272 418 0x05, 0x09, /* Usage Page (Button), */ 273 - 0x75, 0x01, /* Report Size (1), */ 274 419 0x19, 0x01, /* Usage Minimum (01h), */ 275 420 0x29, 0x03, /* Usage Maximum (03h), */ 276 421 0x14, /* Logical Minimum (0), */ 277 422 0x25, 0x01, /* Logical Maximum (1), */ 423 + 0x75, 0x01, /* Report Size (1), */ 278 424 0x95, 0x03, /* Report Count (3), */ 279 425 0x81, 0x02, /* Input (Variable), */ 280 426 0x95, 0x04, /* Report Count (4), */ 281 427 0x81, 0x01, /* Input (Constant), */ 428 + 0x05, 0x0D, /* Usage Page (Digitizer), */ 429 + 0x09, 0x32, /* Usage (In Range), */ 282 430 0x95, 0x01, /* Report Count (1), */ 283 - 0x0B, 0x32, 0x00, 0x0D, 0x00, /* Usage (Digitizer In Range), */ 284 - 0x14, /* Logical Minimum (0), */ 285 - 0x25, 0x01, /* Logical Maximum (1), */ 286 431 0x81, 0x02, /* Input (Variable), */ 287 - 0xA4, /* Push, */ 288 432 0x05, 0x01, /* Usage Page (Desktop), */ 289 - 0x75, 0x10, /* Report Size (16), */ 290 - 0x95, 0x01, /* Report Count (1), */ 291 - 0x55, 0xFD, /* Unit Exponent (-3), */ 292 - 0x65, 0x13, /* Unit (Inch), */ 293 - 0x14, /* Logical Minimum (0), */ 294 - 0x34, /* Physical Minimum (0), */ 433 + 0xA4, /* Push, */ 295 434 0x09, 0x30, /* Usage (X), */ 296 - 0x27, 0x00, 0xF0, 0x00, 0x00, /* Logical Maximum (61440), */ 297 - 0x46, 0xE0, 0x2E, /* Physical Maximum (12000), */ 435 + 0x27, 0xFF, 0x7F, 0x00, 0x00, /* Logical Maximum (32767), */ 436 + 0x34, /* Physical Minimum (0), */ 437 + 0x47, 0x00, 0x00, 0x00, 0x00, /* Physical Maximum (0), */ 438 + 0x65, 0x11, /* Unit (Centimeter), */ 439 + 0x55, 0x00, /* Unit Exponent (0), */ 440 + 0x75, 0x10, /* Report Size (16), */ 298 441 0x81, 0x02, /* Input (Variable), */ 299 442 0x09, 0x31, /* Usage (Y), */ 300 - 0x27, 0x00, 0xB4, 0x00, 0x00, /* Logical Maximum (46080), */ 301 - 0x46, 0x28, 0x23, /* Physical Maximum (9000), */ 443 + 0x27, 0xFF, 0x7F, 0x00, 0x00, /* Logical Maximum (32767), */ 444 + 0x47, 0x00, 0x00, 0x00, 0x00, /* Physical Maximum (0), */ 302 445 0x81, 0x02, /* Input (Variable), */ 446 + 0xB4, /* Pop, */ 303 447 0x09, 0x38, /* Usage (Wheel), */ 448 + 0x15, 0xFF, /* Logical Minimum (-1), */ 304 449 0x75, 0x08, /* Report Size (8), */ 305 450 0x95, 0x01, /* Report Count (1), */ 306 - 0x15, 0xFF, /* Logical Minimum (-1), */ 307 - 0x25, 0x01, /* Logical Maximum (1), */ 308 - 0x34, /* Physical Minimum (0), */ 309 - 0x44, /* Physical Maximum (0), */ 310 451 0x81, 0x06, /* Input (Variable, Relative), */ 311 - 0xB4, /* Pop, */ 452 + 0x81, 0x01, /* Input (Constant), */ 312 453 0xC0, /* End Collection, */ 313 - 0xC0, /* End Collection, */ 314 - 0x05, 0x0C, /* Usage Page (Consumer), */ 315 - 0x09, 0x01, /* Usage (Consumer Control), */ 316 - 0xA1, 0x01, /* Collection (Application), */ 317 - 0x85, 0x12, /* Report ID (18), */ 318 - 0x14, /* Logical Minimum (0), */ 319 - 0x25, 0x01, /* Logical Maximum (1), */ 320 - 0x75, 0x01, /* Report Size (1), */ 321 - 0x95, 0x08, /* Report Count (8), */ 322 - 0x05, 0x0C, /* Usage Page (Consumer), */ 323 - 0x0A, 0x6A, 0x02, /* Usage (AC Delete), */ 324 - 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */ 325 - 0x0A, 0x01, 0x02, /* Usage (AC New), */ 326 - 0x0A, 0x2F, 0x02, /* Usage (AC Zoom), */ 327 - 0x0A, 0x25, 0x02, /* Usage (AC Forward), */ 328 - 0x0A, 0x24, 0x02, /* Usage (AC Back), */ 329 - 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ 330 - 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ 331 - 0x81, 0x02, /* Input (Variable), */ 332 - 0x95, 0x30, /* Report Count (48), */ 333 - 0x81, 0x03, /* Input (Constant, Variable), */ 334 454 0xC0 /* End Collection */ 335 455 }; 336 456 337 - /* Original EasyPen M406XE report descriptor size */ 338 - #define EASYPEN_M406XE_RDESC_ORIG_SIZE 476 339 - 340 - /* Fixed EasyPen M406XE report descriptor */ 341 - static __u8 easypen_m406xe_rdesc_fixed[] = { 342 - 0x05, 0x01, /* Usage Page (Desktop), */ 343 - 0x09, 0x01, /* Usage (01h), */ 344 - 0xA1, 0x01, /* Collection (Application), */ 345 - 0x85, 0x05, /* Report ID (5), */ 346 - 0x09, 0x01, /* Usage (01h), */ 347 - 0x15, 0x80, /* Logical Minimum (-128), */ 348 - 0x25, 0x7F, /* Logical Maximum (127), */ 349 - 0x75, 0x08, /* Report Size (8), */ 350 - 0x95, 0x07, /* Report Count (7), */ 351 - 0xB1, 0x02, /* Feature (Variable), */ 352 - 0xC0, /* End Collection, */ 353 - 0x05, 0x0D, /* Usage Page (Digitizer), */ 354 - 0x09, 0x01, /* Usage (Digitizer), */ 355 - 0xA1, 0x01, /* Collection (Application), */ 356 - 0x85, 0x10, /* Report ID (16), */ 357 - 0x09, 0x20, /* Usage (Stylus), */ 358 - 0xA0, /* Collection (Physical), */ 359 - 0x14, /* Logical Minimum (0), */ 360 - 0x25, 0x01, /* Logical Maximum (1), */ 361 - 0x75, 0x01, /* Report Size (1), */ 362 - 0x09, 0x42, /* Usage (Tip Switch), */ 363 - 0x09, 0x44, /* Usage (Barrel Switch), */ 364 - 0x09, 0x46, /* Usage (Tablet Pick), */ 365 - 0x95, 0x03, /* Report Count (3), */ 366 - 0x81, 0x02, /* Input (Variable), */ 367 - 0x95, 0x04, /* Report Count (4), */ 368 - 0x81, 0x03, /* Input (Constant, Variable), */ 369 - 0x09, 0x32, /* Usage (In Range), */ 370 - 0x95, 0x01, /* Report Count (1), */ 371 - 0x81, 0x02, /* Input (Variable), */ 372 - 0x75, 0x10, /* Report Size (16), */ 373 - 0x95, 0x01, /* Report Count (1), */ 374 - 0xA4, /* Push, */ 375 - 0x05, 0x01, /* Usage Page (Desktop), */ 376 - 0x55, 0xFD, /* Unit Exponent (-3), */ 377 - 0x65, 0x13, /* Unit (Inch), */ 378 - 0x34, /* Physical Minimum (0), */ 379 - 0x09, 0x30, /* Usage (X), */ 380 - 0x46, 0x70, 0x17, /* Physical Maximum (6000), */ 381 - 0x26, 0x00, 0x3C, /* Logical Maximum (15360), */ 382 - 0x81, 0x02, /* Input (Variable), */ 383 - 0x09, 0x31, /* Usage (Y), */ 384 - 0x46, 0xA0, 0x0F, /* Physical Maximum (4000), */ 385 - 0x26, 0x00, 0x28, /* Logical Maximum (10240), */ 386 - 0x81, 0x02, /* Input (Variable), */ 387 - 0xB4, /* Pop, */ 388 - 0x09, 0x30, /* Usage (Tip Pressure), */ 389 - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 390 - 0x81, 0x02, /* Input (Variable), */ 391 - 0xC0, /* End Collection, */ 392 - 0xC0, /* End Collection */ 393 - 0x05, 0x0C, /* Usage Page (Consumer), */ 394 - 0x09, 0x01, /* Usage (Consumer Control), */ 395 - 0xA1, 0x01, /* Collection (Application), */ 396 - 0x85, 0x12, /* Report ID (18), */ 397 - 0x14, /* Logical Minimum (0), */ 398 - 0x25, 0x01, /* Logical Maximum (1), */ 399 - 0x75, 0x01, /* Report Size (1), */ 400 - 0x95, 0x04, /* Report Count (4), */ 401 - 0x0A, 0x79, 0x02, /* Usage (AC Redo Or Repeat), */ 402 - 0x0A, 0x1A, 0x02, /* Usage (AC Undo), */ 403 - 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ 404 - 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ 405 - 0x81, 0x02, /* Input (Variable), */ 406 - 0x95, 0x34, /* Report Count (52), */ 407 - 0x81, 0x03, /* Input (Constant, Variable), */ 408 - 0xC0 /* End Collection */ 457 + static const struct kye_tablet_info { 458 + __u32 product; 459 + __s32 x_logical_maximum; 460 + __s32 y_logical_maximum; 461 + __s32 pressure_logical_maximum; 462 + __s32 x_physical_maximum; 463 + __s32 y_physical_maximum; 464 + __s8 unit_exponent; 465 + __s8 unit; 466 + bool has_punk; 467 + unsigned int control_rsize; 468 + const __u8 *control_rdesc; 469 + } kye_tablets_info[] = { 470 + {USB_DEVICE_ID_KYE_EASYPEN_M406, /* 0x5005 */ 471 + 15360, 10240, 1023, 6, 4, 0, 0x13, false, 472 + sizeof(easypen_m406_control_rdesc), easypen_m406_control_rdesc}, 473 + {USB_DEVICE_ID_KYE_EASYPEN_M506, /* 0x500F */ 474 + 24576, 20480, 1023, 6, 5, 0, 0x13, false, 475 + sizeof(easypen_m506_control_rdesc), easypen_m506_control_rdesc}, 476 + {USB_DEVICE_ID_KYE_EASYPEN_I405X, /* 0x5010 */ 477 + 14080, 10240, 1023, 55, 40, -1, 0x13, false}, 478 + {USB_DEVICE_ID_KYE_MOUSEPEN_I608X, /* 0x5011 */ 479 + 20480, 15360, 2047, 8, 6, 0, 0x13, true}, 480 + {USB_DEVICE_ID_KYE_EASYPEN_M406W, /* 0x5012 */ 481 + 15360, 10240, 1023, 6, 4, 0, 0x13, false, 482 + sizeof(easypen_m406w_control_rdesc), easypen_m406w_control_rdesc}, 483 + {USB_DEVICE_ID_KYE_EASYPEN_M610X, /* 0x5013 */ 484 + 40960, 25600, 1023, 1000, 625, -2, 0x13, false, 485 + sizeof(easypen_m610x_control_rdesc), easypen_m610x_control_rdesc}, 486 + {USB_DEVICE_ID_KYE_EASYPEN_340, /* 0x5014 */ 487 + 10240, 7680, 1023, 4, 3, 0, 0x13, false}, 488 + {USB_DEVICE_ID_KYE_PENSKETCH_M912, /* 0x5015 */ 489 + 61440, 46080, 2047, 12, 9, 0, 0x13, true, 490 + sizeof(pensketch_m912_control_rdesc), pensketch_m912_control_rdesc}, 491 + {USB_DEVICE_ID_KYE_MOUSEPEN_M508WX, /* 0x5016 */ 492 + 40960, 25600, 2047, 8, 5, 0, 0x13, true, 493 + sizeof(mousepen_m508wx_control_rdesc), mousepen_m508wx_control_rdesc}, 494 + {USB_DEVICE_ID_KYE_MOUSEPEN_M508X, /* 0x5017 */ 495 + 40960, 25600, 2047, 8, 5, 0, 0x13, true, 496 + sizeof(mousepen_m508x_control_rdesc), mousepen_m508x_control_rdesc}, 497 + {USB_DEVICE_ID_KYE_EASYPEN_M406XE, /* 0x5019 */ 498 + 15360, 10240, 1023, 6, 4, 0, 0x13, false, 499 + sizeof(easypen_m406xe_control_rdesc), easypen_m406xe_control_rdesc}, 500 + {USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2, /* 0x501A */ 501 + 40960, 30720, 2047, 8, 6, 0, 0x13, true}, 502 + {USB_DEVICE_ID_KYE_PENSKETCH_T609A, /* 0x501B */ 503 + 43520, 28160, 1023, 85, 55, -1, 0x13, false, 504 + sizeof(pensketch_t609a_control_rdesc), pensketch_t609a_control_rdesc}, 505 + {} 409 506 }; 410 507 411 508 static __u8 *kye_consumer_control_fixup(struct hid_device *hdev, __u8 *rdesc, 412 - unsigned int *rsize, int offset, const char *device_name) { 509 + unsigned int *rsize, int offset, const char *device_name) 510 + { 413 511 /* 414 512 * the fixup that need to be done: 415 513 * - change Usage Maximum in the Consumer Control ··· 377 571 hid_info(hdev, "fixing up %s report descriptor\n", device_name); 378 572 rdesc[offset + 12] = 0x2f; 379 573 } 574 + return rdesc; 575 + } 576 + 577 + /* 578 + * Fix tablet descriptor of so-called "DataFormat 2". 579 + * 580 + * Though we may achieve a usable descriptor from original vendor-defined one, 581 + * some problems exist: 582 + * - Their Logical Maximum never exceed 32767 (7F FF), though device do report 583 + * values greater than that; 584 + * - Physical Maximums are arbitrarily filled (always equal to Logical 585 + * Maximum); 586 + * - Detail for control buttons are not provided (a vendor-defined Usage Page 587 + * with fixed content). 588 + * 589 + * Thus we use a pre-defined parameter table rather than digging it from 590 + * original descriptor. 591 + * 592 + * We may as well write a fallback routine for unrecognized kye tablet, but it's 593 + * clear kye are unlikely to produce new models in the foreseeable future, so we 594 + * simply enumerate all possible models. 595 + */ 596 + static __u8 *kye_tablet_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) 597 + { 598 + const struct kye_tablet_info *info; 599 + unsigned int newsize; 600 + 601 + if (*rsize < sizeof(kye_tablet_rdesc)) { 602 + hid_warn(hdev, 603 + "tablet report size too small, or kye_tablet_rdesc unexpectedly large\n"); 604 + return rdesc; 605 + } 606 + 607 + for (info = kye_tablets_info; info->product; info++) { 608 + if (hdev->product == info->product) 609 + break; 610 + } 611 + 612 + if (!info->product) { 613 + hid_err(hdev, "tablet unknown, someone forget to add kye_tablet_info entry?\n"); 614 + return rdesc; 615 + } 616 + 617 + newsize = info->has_punk ? sizeof(kye_tablet_rdesc) : 112; 618 + memcpy(rdesc, kye_tablet_rdesc, newsize); 619 + 620 + put_unaligned_le32(info->x_logical_maximum, rdesc + 66); 621 + put_unaligned_le32(info->x_physical_maximum, rdesc + 72); 622 + rdesc[77] = info->unit; 623 + rdesc[79] = info->unit_exponent; 624 + put_unaligned_le32(info->y_logical_maximum, rdesc + 87); 625 + put_unaligned_le32(info->y_physical_maximum, rdesc + 92); 626 + put_unaligned_le32(info->pressure_logical_maximum, rdesc + 104); 627 + 628 + if (info->has_punk) { 629 + put_unaligned_le32(info->x_logical_maximum, rdesc + 156); 630 + put_unaligned_le32(info->x_physical_maximum, rdesc + 162); 631 + rdesc[167] = info->unit; 632 + rdesc[169] = info->unit_exponent; 633 + put_unaligned_le32(info->y_logical_maximum, rdesc + 177); 634 + put_unaligned_le32(info->y_physical_maximum, rdesc + 182); 635 + } 636 + 637 + if (info->control_rsize) { 638 + if (newsize + info->control_rsize > *rsize) 639 + hid_err(hdev, "control rdesc unexpectedly large"); 640 + else { 641 + memcpy(rdesc + newsize, info->control_rdesc, info->control_rsize); 642 + newsize += info->control_rsize; 643 + } 644 + } 645 + 646 + *rsize = newsize; 380 647 return rdesc; 381 648 } 382 649 ··· 481 602 rdesc[74] = 0x08; 482 603 } 483 604 break; 484 - case USB_DEVICE_ID_KYE_EASYPEN_I405X: 485 - if (*rsize == EASYPEN_I405X_RDESC_ORIG_SIZE) { 486 - rdesc = easypen_i405x_rdesc_fixed; 487 - *rsize = sizeof(easypen_i405x_rdesc_fixed); 488 - } 489 - break; 490 - case USB_DEVICE_ID_KYE_MOUSEPEN_I608X: 491 - if (*rsize == MOUSEPEN_I608X_RDESC_ORIG_SIZE) { 492 - rdesc = mousepen_i608x_rdesc_fixed; 493 - *rsize = sizeof(mousepen_i608x_rdesc_fixed); 494 - } 495 - break; 496 - case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2: 497 - if (*rsize == MOUSEPEN_I608X_V2_RDESC_ORIG_SIZE) { 498 - rdesc = mousepen_i608x_v2_rdesc_fixed; 499 - *rsize = sizeof(mousepen_i608x_v2_rdesc_fixed); 500 - } 501 - break; 502 - case USB_DEVICE_ID_KYE_EASYPEN_M610X: 503 - if (*rsize == EASYPEN_M610X_RDESC_ORIG_SIZE) { 504 - rdesc = easypen_m610x_rdesc_fixed; 505 - *rsize = sizeof(easypen_m610x_rdesc_fixed); 506 - } 507 - break; 508 - case USB_DEVICE_ID_KYE_EASYPEN_M406XE: 509 - if (*rsize == EASYPEN_M406XE_RDESC_ORIG_SIZE) { 510 - rdesc = easypen_m406xe_rdesc_fixed; 511 - *rsize = sizeof(easypen_m406xe_rdesc_fixed); 512 - } 513 - break; 514 - case USB_DEVICE_ID_KYE_PENSKETCH_M912: 515 - if (*rsize == PENSKETCH_M912_RDESC_ORIG_SIZE) { 516 - rdesc = pensketch_m912_rdesc_fixed; 517 - *rsize = sizeof(pensketch_m912_rdesc_fixed); 518 - } 519 - break; 520 605 case USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE: 521 606 rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104, 522 607 "Genius Gila Gaming Mouse"); 523 - break; 524 - case USB_DEVICE_ID_GENIUS_GX_IMPERATOR: 525 - rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 83, 526 - "Genius Gx Imperator Keyboard"); 527 608 break; 528 609 case USB_DEVICE_ID_GENIUS_MANTICORE: 529 610 rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104, 530 611 "Genius Manticore Keyboard"); 531 612 break; 613 + case USB_DEVICE_ID_GENIUS_GX_IMPERATOR: 614 + rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 83, 615 + "Genius Gx Imperator Keyboard"); 616 + break; 617 + case USB_DEVICE_ID_KYE_EASYPEN_M406: 618 + case USB_DEVICE_ID_KYE_EASYPEN_M506: 619 + case USB_DEVICE_ID_KYE_EASYPEN_I405X: 620 + case USB_DEVICE_ID_KYE_MOUSEPEN_I608X: 621 + case USB_DEVICE_ID_KYE_EASYPEN_M406W: 622 + case USB_DEVICE_ID_KYE_EASYPEN_M610X: 623 + case USB_DEVICE_ID_KYE_EASYPEN_340: 624 + case USB_DEVICE_ID_KYE_PENSKETCH_M912: 625 + case USB_DEVICE_ID_KYE_MOUSEPEN_M508WX: 626 + case USB_DEVICE_ID_KYE_MOUSEPEN_M508X: 627 + case USB_DEVICE_ID_KYE_EASYPEN_M406XE: 628 + case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2: 629 + case USB_DEVICE_ID_KYE_PENSKETCH_T609A: 630 + rdesc = kye_tablet_fixup(hdev, rdesc, rsize); 631 + break; 532 632 } 533 633 return rdesc; 534 634 } 535 635 536 - /** 537 - * kye_tablet_enable() - Enable fully-functional tablet mode by setting a special feature report. 538 - * 539 - * @hdev: HID device 540 - * 541 - * The specific report ID and data were discovered by sniffing the 542 - * Windows driver traffic. 543 - */ 544 636 static int kye_tablet_enable(struct hid_device *hdev) 545 637 { 546 638 struct list_head *list; ··· 538 688 539 689 value = report->field[0]->value; 540 690 691 + /* 692 + * The code is for DataFormat 2 of config xml. They have no obvious 693 + * meaning (at least not configurable in Windows driver) except enabling 694 + * fully-functional tablet mode (absolute positioning). Otherwise, the 695 + * tablet acts like a relative mouse. 696 + * 697 + * Though there're magic codes for DataFormat 3 and 4, no devices use 698 + * these DataFormats. 699 + */ 541 700 value[0] = 0x12; 542 701 value[1] = 0x10; 543 702 value[2] = 0x11; ··· 576 717 } 577 718 578 719 switch (id->product) { 579 - case USB_DEVICE_ID_KYE_EASYPEN_I405X: 580 - case USB_DEVICE_ID_KYE_MOUSEPEN_I608X: 581 - case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2: 582 - case USB_DEVICE_ID_KYE_EASYPEN_M610X: 583 - case USB_DEVICE_ID_KYE_EASYPEN_M406XE: 584 - case USB_DEVICE_ID_KYE_PENSKETCH_M912: 585 - ret = kye_tablet_enable(hdev); 586 - if (ret) { 587 - hid_err(hdev, "tablet enabling failed\n"); 588 - goto enabling_err; 589 - } 590 - break; 591 720 case USB_DEVICE_ID_GENIUS_MANTICORE: 592 721 /* 593 722 * The manticore keyboard needs to have all the interfaces ··· 583 736 */ 584 737 if (hid_hw_open(hdev)) 585 738 hid_hw_close(hdev); 739 + break; 740 + case USB_DEVICE_ID_KYE_EASYPEN_M406: 741 + case USB_DEVICE_ID_KYE_EASYPEN_M506: 742 + case USB_DEVICE_ID_KYE_EASYPEN_I405X: 743 + case USB_DEVICE_ID_KYE_MOUSEPEN_I608X: 744 + case USB_DEVICE_ID_KYE_EASYPEN_M406W: 745 + case USB_DEVICE_ID_KYE_EASYPEN_M610X: 746 + case USB_DEVICE_ID_KYE_EASYPEN_340: 747 + case USB_DEVICE_ID_KYE_PENSKETCH_M912: 748 + case USB_DEVICE_ID_KYE_MOUSEPEN_M508WX: 749 + case USB_DEVICE_ID_KYE_MOUSEPEN_M508X: 750 + case USB_DEVICE_ID_KYE_EASYPEN_M406XE: 751 + case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2: 752 + case USB_DEVICE_ID_KYE_PENSKETCH_T609A: 753 + ret = kye_tablet_enable(hdev); 754 + if (ret) { 755 + hid_err(hdev, "tablet enabling failed\n"); 756 + goto enabling_err; 757 + } 586 758 break; 587 759 } 588 760 ··· 615 749 static const struct hid_device_id kye_devices[] = { 616 750 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, 617 751 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 752 + USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) }, 753 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 754 + USB_DEVICE_ID_GENIUS_MANTICORE) }, 755 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 756 + USB_DEVICE_ID_GENIUS_GX_IMPERATOR) }, 757 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 758 + USB_DEVICE_ID_KYE_EASYPEN_M406) }, 759 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 760 + USB_DEVICE_ID_KYE_EASYPEN_M506) }, 761 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 618 762 USB_DEVICE_ID_KYE_EASYPEN_I405X) }, 619 763 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 620 764 USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, 621 765 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 622 - USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2) }, 766 + USB_DEVICE_ID_KYE_EASYPEN_M406W) }, 623 767 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 624 768 USB_DEVICE_ID_KYE_EASYPEN_M610X) }, 625 769 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 626 - USB_DEVICE_ID_KYE_EASYPEN_M406XE) }, 627 - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 628 - USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) }, 629 - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 630 - USB_DEVICE_ID_GENIUS_GX_IMPERATOR) }, 631 - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 632 - USB_DEVICE_ID_GENIUS_MANTICORE) }, 770 + USB_DEVICE_ID_KYE_EASYPEN_340) }, 633 771 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 634 772 USB_DEVICE_ID_KYE_PENSKETCH_M912) }, 773 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 774 + USB_DEVICE_ID_KYE_MOUSEPEN_M508WX) }, 775 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 776 + USB_DEVICE_ID_KYE_MOUSEPEN_M508X) }, 777 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 778 + USB_DEVICE_ID_KYE_EASYPEN_M406XE) }, 779 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 780 + USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2) }, 781 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 782 + USB_DEVICE_ID_KYE_PENSKETCH_T609A) }, 635 783 { } 636 784 }; 637 785 MODULE_DEVICE_TABLE(hid, kye_devices);
+1
drivers/hid/hid-lg-g15.c
··· 7 7 8 8 #include <linux/device.h> 9 9 #include <linux/hid.h> 10 + #include <linux/leds.h> 10 11 #include <linux/module.h> 11 12 #include <linux/random.h> 12 13 #include <linux/sched.h>
+249 -7
drivers/hid/hid-logitech-hidpp.c
··· 74 74 #define HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS BIT(27) 75 75 #define HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS BIT(28) 76 76 #define HIDPP_QUIRK_HI_RES_SCROLL_1P0 BIT(29) 77 + #define HIDPP_QUIRK_WIRELESS_STATUS BIT(30) 77 78 78 79 /* These are just aliases for now */ 79 80 #define HIDPP_QUIRK_KBD_SCROLL_WHEEL HIDPP_QUIRK_HIDPP_WHEELS ··· 95 94 #define HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL BIT(7) 96 95 #define HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL BIT(8) 97 96 #define HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL BIT(9) 97 + #define HIDPP_CAPABILITY_ADC_MEASUREMENT BIT(10) 98 98 99 99 #define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 100 100 ··· 147 145 u8 feature_index; 148 146 u8 solar_feature_index; 149 147 u8 voltage_feature_index; 148 + u8 adc_measurement_feature_index; 150 149 struct power_supply_desc desc; 151 150 struct power_supply *ps; 152 151 char name[64]; ··· 472 469 kfree(*name); 473 470 474 471 *name = new_name; 472 + } 473 + 474 + /* 475 + * Updates the USB wireless_status based on whether the headset 476 + * is turned on and reachable. 477 + */ 478 + static void hidpp_update_usb_wireless_status(struct hidpp_device *hidpp) 479 + { 480 + struct hid_device *hdev = hidpp->hid_dev; 481 + struct usb_interface *intf; 482 + 483 + if (!(hidpp->quirks & HIDPP_QUIRK_WIRELESS_STATUS)) 484 + return; 485 + if (!hid_is_usb(hdev)) 486 + return; 487 + 488 + intf = to_usb_interface(hdev->dev.parent); 489 + usb_set_wireless_status(intf, hidpp->battery.online ? 490 + USB_WIRELESS_STATUS_CONNECTED : 491 + USB_WIRELESS_STATUS_DISCONNECTED); 475 492 } 476 493 477 494 /** ··· 876 853 if (ret) 877 854 return ret; 878 855 879 - snprintf(hdev->uniq, sizeof(hdev->uniq), "%04x-%4phD", 880 - hdev->product, &serial); 856 + snprintf(hdev->uniq, sizeof(hdev->uniq), "%4phD", &serial); 881 857 dbg_hid("HID++ Unifying: Got serial: %s\n", hdev->uniq); 882 858 883 859 name = hidpp_unifying_get_name(hidpp); ··· 966 944 print_version: 967 945 hid_info(hidpp->hid_dev, "HID++ %u.%u device connected.\n", 968 946 hidpp->protocol_major, hidpp->protocol_minor); 947 + return 0; 948 + } 949 + 950 + /* -------------------------------------------------------------------------- */ 951 + /* 0x0003: Device Information */ 952 + /* -------------------------------------------------------------------------- */ 953 + 954 + #define HIDPP_PAGE_DEVICE_INFORMATION 0x0003 955 + 956 + #define CMD_GET_DEVICE_INFO 0x00 957 + 958 + static int hidpp_get_serial(struct hidpp_device *hidpp, u32 *serial) 959 + { 960 + struct hidpp_report response; 961 + u8 feature_type; 962 + u8 feature_index; 963 + int ret; 964 + 965 + ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_DEVICE_INFORMATION, 966 + &feature_index, 967 + &feature_type); 968 + if (ret) 969 + return ret; 970 + 971 + ret = hidpp_send_fap_command_sync(hidpp, feature_index, 972 + CMD_GET_DEVICE_INFO, 973 + NULL, 0, &response); 974 + if (ret) 975 + return ret; 976 + 977 + /* See hidpp_unifying_get_serial() */ 978 + *serial = *((u32 *)&response.rap.params[1]); 979 + return 0; 980 + } 981 + 982 + static int hidpp_serial_init(struct hidpp_device *hidpp) 983 + { 984 + struct hid_device *hdev = hidpp->hid_dev; 985 + u32 serial; 986 + int ret; 987 + 988 + ret = hidpp_get_serial(hidpp, &serial); 989 + if (ret) 990 + return ret; 991 + 992 + snprintf(hdev->uniq, sizeof(hdev->uniq), "%4phD", &serial); 993 + dbg_hid("HID++ DeviceInformation: Got serial: %s\n", hdev->uniq); 994 + 969 995 return 0; 970 996 } 971 997 ··· 1427 1357 * there are a few devices that use different battery technology. 1428 1358 */ 1429 1359 1430 - static const int voltages[] = { 1360 + static const int voltages[100] = { 1431 1361 4186, 4156, 4143, 4133, 4122, 4113, 4103, 4094, 4086, 4075, 1432 1362 4067, 4059, 4051, 4043, 4035, 4027, 4019, 4011, 4003, 3997, 1433 1363 3989, 3983, 3976, 3969, 3961, 3955, 3949, 3942, 3935, 3929, ··· 1441 1371 }; 1442 1372 1443 1373 int i; 1444 - 1445 - BUILD_BUG_ON(ARRAY_SIZE(voltages) != 100); 1446 1374 1447 1375 if (unlikely(voltage < 3500 || voltage >= 5000)) 1448 1376 hid_warn_once(hid_dev, ··· 1811 1743 &feature_type); 1812 1744 1813 1745 return ret; 1746 + } 1747 + 1748 + /* -------------------------------------------------------------------------- */ 1749 + /* 0x1f20: ADC measurement */ 1750 + /* -------------------------------------------------------------------------- */ 1751 + 1752 + #define HIDPP_PAGE_ADC_MEASUREMENT 0x1f20 1753 + 1754 + #define CMD_ADC_MEASUREMENT_GET_ADC_MEASUREMENT 0x00 1755 + 1756 + #define EVENT_ADC_MEASUREMENT_STATUS_BROADCAST 0x00 1757 + 1758 + static int hidpp20_map_adc_measurement_1f20_capacity(struct hid_device *hid_dev, int voltage) 1759 + { 1760 + /* NB: This voltage curve doesn't necessarily map perfectly to all 1761 + * devices that implement the ADC_MEASUREMENT feature. This is because 1762 + * there are a few devices that use different battery technology. 1763 + * 1764 + * Adapted from: 1765 + * https://github.com/Sapd/HeadsetControl/blob/acd972be0468e039b93aae81221f20a54d2d60f7/src/devices/logitech_g633_g933_935.c#L44-L52 1766 + */ 1767 + static const int voltages[100] = { 1768 + 4030, 4024, 4018, 4011, 4003, 3994, 3985, 3975, 3963, 3951, 1769 + 3937, 3922, 3907, 3893, 3880, 3868, 3857, 3846, 3837, 3828, 1770 + 3820, 3812, 3805, 3798, 3791, 3785, 3779, 3773, 3768, 3762, 1771 + 3757, 3752, 3747, 3742, 3738, 3733, 3729, 3724, 3720, 3716, 1772 + 3712, 3708, 3704, 3700, 3696, 3692, 3688, 3685, 3681, 3677, 1773 + 3674, 3670, 3667, 3663, 3660, 3657, 3653, 3650, 3646, 3643, 1774 + 3640, 3637, 3633, 3630, 3627, 3624, 3620, 3617, 3614, 3611, 1775 + 3608, 3604, 3601, 3598, 3595, 3592, 3589, 3585, 3582, 3579, 1776 + 3576, 3573, 3569, 3566, 3563, 3560, 3556, 3553, 3550, 3546, 1777 + 3543, 3539, 3536, 3532, 3529, 3525, 3499, 3466, 3433, 3399, 1778 + }; 1779 + 1780 + int i; 1781 + 1782 + if (voltage == 0) 1783 + return 0; 1784 + 1785 + if (unlikely(voltage < 3400 || voltage >= 5000)) 1786 + hid_warn_once(hid_dev, 1787 + "%s: possibly using the wrong voltage curve\n", 1788 + __func__); 1789 + 1790 + for (i = 0; i < ARRAY_SIZE(voltages); i++) { 1791 + if (voltage >= voltages[i]) 1792 + return ARRAY_SIZE(voltages) - i; 1793 + } 1794 + 1795 + return 0; 1796 + } 1797 + 1798 + static int hidpp20_map_adc_measurement_1f20(u8 data[3], int *voltage) 1799 + { 1800 + int status; 1801 + u8 flags; 1802 + 1803 + flags = data[2]; 1804 + 1805 + switch (flags) { 1806 + case 0x01: 1807 + status = POWER_SUPPLY_STATUS_DISCHARGING; 1808 + break; 1809 + case 0x03: 1810 + status = POWER_SUPPLY_STATUS_CHARGING; 1811 + break; 1812 + case 0x07: 1813 + status = POWER_SUPPLY_STATUS_FULL; 1814 + break; 1815 + case 0x0F: 1816 + default: 1817 + status = POWER_SUPPLY_STATUS_UNKNOWN; 1818 + break; 1819 + } 1820 + 1821 + *voltage = get_unaligned_be16(data); 1822 + 1823 + dbg_hid("Parsed 1f20 data as flag 0x%02x voltage %dmV\n", 1824 + flags, *voltage); 1825 + 1826 + return status; 1827 + } 1828 + 1829 + /* Return value is whether the device is online */ 1830 + static bool hidpp20_get_adc_measurement_1f20(struct hidpp_device *hidpp, 1831 + u8 feature_index, 1832 + int *status, int *voltage) 1833 + { 1834 + struct hidpp_report response; 1835 + int ret; 1836 + u8 *params = (u8 *)response.fap.params; 1837 + 1838 + *status = POWER_SUPPLY_STATUS_UNKNOWN; 1839 + *voltage = 0; 1840 + ret = hidpp_send_fap_command_sync(hidpp, feature_index, 1841 + CMD_ADC_MEASUREMENT_GET_ADC_MEASUREMENT, 1842 + NULL, 0, &response); 1843 + 1844 + if (ret > 0) { 1845 + hid_dbg(hidpp->hid_dev, "%s: received protocol error 0x%02x\n", 1846 + __func__, ret); 1847 + return false; 1848 + } 1849 + 1850 + *status = hidpp20_map_adc_measurement_1f20(params, voltage); 1851 + return true; 1852 + } 1853 + 1854 + static int hidpp20_query_adc_measurement_info_1f20(struct hidpp_device *hidpp) 1855 + { 1856 + u8 feature_type; 1857 + 1858 + if (hidpp->battery.adc_measurement_feature_index == 0xff) { 1859 + int ret; 1860 + 1861 + ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_ADC_MEASUREMENT, 1862 + &hidpp->battery.adc_measurement_feature_index, 1863 + &feature_type); 1864 + if (ret) 1865 + return ret; 1866 + 1867 + hidpp->capabilities |= HIDPP_CAPABILITY_ADC_MEASUREMENT; 1868 + } 1869 + 1870 + hidpp->battery.online = hidpp20_get_adc_measurement_1f20(hidpp, 1871 + hidpp->battery.adc_measurement_feature_index, 1872 + &hidpp->battery.status, 1873 + &hidpp->battery.voltage); 1874 + hidpp->battery.capacity = hidpp20_map_adc_measurement_1f20_capacity(hidpp->hid_dev, 1875 + hidpp->battery.voltage); 1876 + hidpp_update_usb_wireless_status(hidpp); 1877 + 1878 + return 0; 1879 + } 1880 + 1881 + static int hidpp20_adc_measurement_event_1f20(struct hidpp_device *hidpp, 1882 + u8 *data, int size) 1883 + { 1884 + struct hidpp_report *report = (struct hidpp_report *)data; 1885 + int status, voltage; 1886 + 1887 + if (report->fap.feature_index != hidpp->battery.adc_measurement_feature_index || 1888 + report->fap.funcindex_clientid != EVENT_ADC_MEASUREMENT_STATUS_BROADCAST) 1889 + return 0; 1890 + 1891 + status = hidpp20_map_adc_measurement_1f20(report->fap.params, &voltage); 1892 + 1893 + hidpp->battery.online = status != POWER_SUPPLY_STATUS_UNKNOWN; 1894 + 1895 + if (voltage != hidpp->battery.voltage || status != hidpp->battery.status) { 1896 + hidpp->battery.status = status; 1897 + hidpp->battery.voltage = voltage; 1898 + hidpp->battery.capacity = hidpp20_map_adc_measurement_1f20_capacity(hidpp->hid_dev, voltage); 1899 + if (hidpp->battery.ps) 1900 + power_supply_changed(hidpp->battery.ps); 1901 + hidpp_update_usb_wireless_status(hidpp); 1902 + } 1903 + return 0; 1814 1904 } 1815 1905 1816 1906 /* -------------------------------------------------------------------------- */ ··· 3889 3663 ret = hidpp20_battery_voltage_event(hidpp, data, size); 3890 3664 if (ret != 0) 3891 3665 return ret; 3666 + ret = hidpp20_adc_measurement_event_1f20(hidpp, data, size); 3667 + if (ret != 0) 3668 + return ret; 3892 3669 } 3893 3670 3894 3671 if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP10_BATTERY) { ··· 4015 3786 hidpp->battery.feature_index = 0xff; 4016 3787 hidpp->battery.solar_feature_index = 0xff; 4017 3788 hidpp->battery.voltage_feature_index = 0xff; 3789 + hidpp->battery.adc_measurement_feature_index = 0xff; 4018 3790 4019 3791 if (hidpp->protocol_major >= 2) { 4020 3792 if (hidpp->quirks & HIDPP_QUIRK_CLASS_K750) ··· 4029 3799 ret = hidpp20_query_battery_info_1004(hidpp); 4030 3800 if (ret) 4031 3801 ret = hidpp20_query_battery_voltage_info(hidpp); 3802 + if (ret) 3803 + ret = hidpp20_query_adc_measurement_info_1f20(hidpp); 4032 3804 } 4033 3805 4034 3806 if (ret) ··· 4060 3828 4061 3829 if (hidpp->capabilities & HIDPP_CAPABILITY_BATTERY_MILEAGE || 4062 3830 hidpp->capabilities & HIDPP_CAPABILITY_BATTERY_PERCENTAGE || 4063 - hidpp->capabilities & HIDPP_CAPABILITY_BATTERY_VOLTAGE) 3831 + hidpp->capabilities & HIDPP_CAPABILITY_BATTERY_VOLTAGE || 3832 + hidpp->capabilities & HIDPP_CAPABILITY_ADC_MEASUREMENT) 4064 3833 battery_props[num_battery_props++] = 4065 3834 POWER_SUPPLY_PROP_CAPACITY; 4066 3835 ··· 4069 3836 battery_props[num_battery_props++] = 4070 3837 POWER_SUPPLY_PROP_CAPACITY_LEVEL; 4071 3838 4072 - if (hidpp->capabilities & HIDPP_CAPABILITY_BATTERY_VOLTAGE) 3839 + if (hidpp->capabilities & HIDPP_CAPABILITY_BATTERY_VOLTAGE || 3840 + hidpp->capabilities & HIDPP_CAPABILITY_ADC_MEASUREMENT) 4073 3841 battery_props[num_battery_props++] = 4074 3842 POWER_SUPPLY_PROP_VOLTAGE_NOW; 4075 3843 ··· 4243 4009 hidpp20_query_battery_voltage_info(hidpp); 4244 4010 else if (hidpp->capabilities & HIDPP_CAPABILITY_UNIFIED_BATTERY) 4245 4011 hidpp20_query_battery_info_1004(hidpp); 4012 + else if (hidpp->capabilities & HIDPP_CAPABILITY_ADC_MEASUREMENT) 4013 + hidpp20_query_adc_measurement_info_1f20(hidpp); 4246 4014 else 4247 4015 hidpp20_query_battery_info_1000(hidpp); 4248 4016 } ··· 4446 4210 4447 4211 if (hidpp->quirks & HIDPP_QUIRK_UNIFYING) 4448 4212 hidpp_unifying_init(hidpp); 4213 + else if (hid_is_usb(hidpp->hid_dev)) 4214 + hidpp_serial_init(hidpp); 4449 4215 4450 4216 connected = hidpp_root_get_protocol_version(hidpp) == 0; 4451 4217 atomic_set(&hidpp->connected, connected); ··· 4616 4378 .driver_data = HIDPP_QUIRK_CLASS_G920 | HIDPP_QUIRK_FORCE_OUTPUT_REPORTS }, 4617 4379 { /* Logitech G Pro Gaming Mouse over USB */ 4618 4380 HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC088) }, 4381 + 4382 + { /* G935 Gaming Headset */ 4383 + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0x0a87), 4384 + .driver_data = HIDPP_QUIRK_WIRELESS_STATUS }, 4619 4385 4620 4386 { /* MX5000 keyboard over Bluetooth */ 4621 4387 HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb305),
+3 -3
drivers/hid/hid-mcp2221.c
··· 79 79 u8 cmd; 80 80 u8 dummy; 81 81 struct { 82 - u8 direction; 83 82 u8 value; 83 + u8 direction; 84 84 } gpio[MCP_NGPIO]; 85 85 } __packed; 86 86 ··· 594 594 595 595 mcp->txbuf[0] = MCP2221_GPIO_GET; 596 596 597 - mcp->gp_idx = offsetof(struct mcp_get_gpio, gpio[offset].value); 597 + mcp->gp_idx = offsetof(struct mcp_get_gpio, gpio[offset]); 598 598 599 599 mutex_lock(&mcp->lock); 600 600 ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1); ··· 675 675 676 676 mcp->txbuf[0] = MCP2221_GPIO_GET; 677 677 678 - mcp->gp_idx = offsetof(struct mcp_get_gpio, gpio[offset].direction); 678 + mcp->gp_idx = offsetof(struct mcp_get_gpio, gpio[offset]); 679 679 680 680 mutex_lock(&mcp->lock); 681 681 ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1);
+86 -9
drivers/hid/hid-nintendo.c
··· 433 433 u8 usb_ack_match; 434 434 u8 subcmd_ack_match; 435 435 bool received_input_report; 436 + unsigned int last_input_report_msecs; 436 437 unsigned int last_subcmd_sent_msecs; 438 + unsigned int consecutive_valid_report_deltas; 437 439 438 440 /* factory calibration data */ 439 441 struct joycon_stick_cal left_stick_cal_x; ··· 545 543 * Sending subcommands and/or rumble data at too high a rate can cause bluetooth 546 544 * controller disconnections. 547 545 */ 546 + #define JC_INPUT_REPORT_MIN_DELTA 8 547 + #define JC_INPUT_REPORT_MAX_DELTA 17 548 + #define JC_SUBCMD_TX_OFFSET_MS 4 549 + #define JC_SUBCMD_VALID_DELTA_REQ 3 550 + #define JC_SUBCMD_RATE_MAX_ATTEMPTS 500 551 + #define JC_SUBCMD_RATE_LIMITER_USB_MS 20 552 + #define JC_SUBCMD_RATE_LIMITER_BT_MS 60 553 + #define JC_SUBCMD_RATE_LIMITER_MS(ctlr) ((ctlr)->hdev->bus == BUS_USB ? JC_SUBCMD_RATE_LIMITER_USB_MS : JC_SUBCMD_RATE_LIMITER_BT_MS) 548 554 static void joycon_enforce_subcmd_rate(struct joycon_ctlr *ctlr) 549 555 { 550 - static const unsigned int max_subcmd_rate_ms = 25; 551 - unsigned int current_ms = jiffies_to_msecs(jiffies); 552 - unsigned int delta_ms = current_ms - ctlr->last_subcmd_sent_msecs; 556 + unsigned int current_ms; 557 + unsigned long subcmd_delta; 558 + int consecutive_valid_deltas = 0; 559 + int attempts = 0; 560 + unsigned long flags; 553 561 554 - while (delta_ms < max_subcmd_rate_ms && 555 - ctlr->ctlr_state == JOYCON_CTLR_STATE_READ) { 562 + if (unlikely(ctlr->ctlr_state != JOYCON_CTLR_STATE_READ)) 563 + return; 564 + 565 + do { 556 566 joycon_wait_for_input_report(ctlr); 557 567 current_ms = jiffies_to_msecs(jiffies); 558 - delta_ms = current_ms - ctlr->last_subcmd_sent_msecs; 568 + subcmd_delta = current_ms - ctlr->last_subcmd_sent_msecs; 569 + 570 + spin_lock_irqsave(&ctlr->lock, flags); 571 + consecutive_valid_deltas = ctlr->consecutive_valid_report_deltas; 572 + spin_unlock_irqrestore(&ctlr->lock, flags); 573 + 574 + attempts++; 575 + } while ((consecutive_valid_deltas < JC_SUBCMD_VALID_DELTA_REQ || 576 + subcmd_delta < JC_SUBCMD_RATE_LIMITER_MS(ctlr)) && 577 + ctlr->ctlr_state == JOYCON_CTLR_STATE_READ && 578 + attempts < JC_SUBCMD_RATE_MAX_ATTEMPTS); 579 + 580 + if (attempts >= JC_SUBCMD_RATE_MAX_ATTEMPTS) { 581 + hid_warn(ctlr->hdev, "%s: exceeded max attempts", __func__); 582 + return; 559 583 } 584 + 560 585 ctlr->last_subcmd_sent_msecs = current_ms; 586 + 587 + /* 588 + * Wait a short time after receiving an input report before 589 + * transmitting. This should reduce odds of a TX coinciding with an RX. 590 + * Minimizing concurrent BT traffic with the controller seems to lower 591 + * the rate of disconnections. 592 + */ 593 + msleep(JC_SUBCMD_TX_OFFSET_MS); 561 594 } 562 595 563 596 static int joycon_hid_send_sync(struct joycon_ctlr *ctlr, u8 *data, size_t len, ··· 1260 1223 u8 tmp; 1261 1224 u32 btns; 1262 1225 unsigned long msecs = jiffies_to_msecs(jiffies); 1226 + unsigned long report_delta_ms = msecs - ctlr->last_input_report_msecs; 1263 1227 1264 1228 spin_lock_irqsave(&ctlr->lock, flags); 1265 1229 if (IS_ENABLED(CONFIG_NINTENDO_FF) && rep->vibrator_report && ··· 1401 1363 } 1402 1364 1403 1365 input_sync(dev); 1366 + 1367 + spin_lock_irqsave(&ctlr->lock, flags); 1368 + ctlr->last_input_report_msecs = msecs; 1369 + /* 1370 + * Was this input report a reasonable time delta compared to the prior 1371 + * report? We use this information to decide when a safe time is to send 1372 + * rumble packets or subcommand packets. 1373 + */ 1374 + if (report_delta_ms >= JC_INPUT_REPORT_MIN_DELTA && 1375 + report_delta_ms <= JC_INPUT_REPORT_MAX_DELTA) { 1376 + if (ctlr->consecutive_valid_report_deltas < JC_SUBCMD_VALID_DELTA_REQ) 1377 + ctlr->consecutive_valid_report_deltas++; 1378 + } else { 1379 + ctlr->consecutive_valid_report_deltas = 0; 1380 + } 1381 + /* 1382 + * Our consecutive valid report tracking is only relevant for 1383 + * bluetooth-connected controllers. For USB devices, we're beholden to 1384 + * USB's underlying polling rate anyway. Always set to the consecutive 1385 + * delta requirement. 1386 + */ 1387 + if (ctlr->hdev->bus == BUS_USB) 1388 + ctlr->consecutive_valid_report_deltas = JC_SUBCMD_VALID_DELTA_REQ; 1389 + 1390 + spin_unlock_irqrestore(&ctlr->lock, flags); 1404 1391 1405 1392 /* 1406 1393 * Immediately after receiving a report is the most reliable time to ··· 1590 1527 u16 freq_l_low; 1591 1528 u16 freq_l_high; 1592 1529 unsigned long flags; 1530 + int next_rq_head; 1593 1531 1594 1532 spin_lock_irqsave(&ctlr->lock, flags); 1595 1533 freq_r_low = ctlr->rumble_rl_freq; ··· 1611 1547 joycon_encode_rumble(data, freq_l_low, freq_l_high, amp); 1612 1548 1613 1549 spin_lock_irqsave(&ctlr->lock, flags); 1614 - if (++ctlr->rumble_queue_head >= JC_RUMBLE_QUEUE_SIZE) 1615 - ctlr->rumble_queue_head = 0; 1550 + 1551 + next_rq_head = ctlr->rumble_queue_head + 1; 1552 + if (next_rq_head >= JC_RUMBLE_QUEUE_SIZE) 1553 + next_rq_head = 0; 1554 + 1555 + /* Did we overrun the circular buffer? 1556 + * If so, be sure we keep the latest intended rumble state. 1557 + */ 1558 + if (next_rq_head == ctlr->rumble_queue_tail) { 1559 + hid_dbg(ctlr->hdev, "rumble queue is full"); 1560 + /* overwrite the prior value at the end of the circular buf */ 1561 + next_rq_head = ctlr->rumble_queue_head; 1562 + } 1563 + 1564 + ctlr->rumble_queue_head = next_rq_head; 1616 1565 memcpy(ctlr->rumble_data[ctlr->rumble_queue_head], data, 1617 1566 JC_RUMBLE_DATA_SIZE); 1618 1567 ··· 2205 2128 2206 2129 ctlr->hdev = hdev; 2207 2130 ctlr->ctlr_state = JOYCON_CTLR_STATE_INIT; 2208 - ctlr->rumble_queue_head = JC_RUMBLE_QUEUE_SIZE - 1; 2131 + ctlr->rumble_queue_head = 0; 2209 2132 ctlr->rumble_queue_tail = 0; 2210 2133 hid_set_drvdata(hdev, ctlr); 2211 2134 mutex_init(&ctlr->output_mutex);
+13 -5
drivers/hid/hid-quirks.c
··· 104 104 { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_1f4a), HID_QUIRK_ALWAYS_POLL }, 105 105 { HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6680), HID_QUIRK_MULTI_INPUT }, 106 106 { HID_USB_DEVICE(USB_VENDOR_ID_INNOMEDIA, USB_DEVICE_ID_INNEX_GENESIS_ATARI), HID_QUIRK_MULTI_INPUT }, 107 - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X), HID_QUIRK_MULTI_INPUT }, 108 - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X), HID_QUIRK_MULTI_INPUT }, 109 - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2), HID_QUIRK_MULTI_INPUT }, 110 - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912), HID_QUIRK_MULTI_INPUT }, 111 - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M406XE), HID_QUIRK_MULTI_INPUT }, 112 107 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE_ID2), HID_QUIRK_ALWAYS_POLL }, 108 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M406), HID_QUIRK_MULTI_INPUT }, 109 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M506), HID_QUIRK_MULTI_INPUT }, 110 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X), HID_QUIRK_MULTI_INPUT }, 111 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X), HID_QUIRK_MULTI_INPUT }, 112 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M406W), HID_QUIRK_MULTI_INPUT }, 113 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X), HID_QUIRK_MULTI_INPUT }, 114 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_340), HID_QUIRK_MULTI_INPUT }, 115 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912), HID_QUIRK_MULTI_INPUT }, 116 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_M508WX), HID_QUIRK_MULTI_INPUT }, 117 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_M508X), HID_QUIRK_MULTI_INPUT }, 118 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M406XE), HID_QUIRK_MULTI_INPUT }, 119 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2), HID_QUIRK_MULTI_INPUT }, 120 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_T609A), HID_QUIRK_MULTI_INPUT }, 113 121 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_OPTICAL_USB_MOUSE_600E), HID_QUIRK_ALWAYS_POLL }, 114 122 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D), HID_QUIRK_ALWAYS_POLL }, 115 123 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019), HID_QUIRK_ALWAYS_POLL },
+1
drivers/hid/hid-steelseries.c
··· 11 11 #include <linux/device.h> 12 12 #include <linux/hid.h> 13 13 #include <linux/module.h> 14 + #include <linux/leds.h> 14 15 15 16 #include "hid-ids.h" 16 17
+4 -2
drivers/hid/i2c-hid/Kconfig
··· 23 23 24 24 config I2C_HID_OF 25 25 tristate "HID over I2C transport layer Open Firmware driver" 26 - depends on OF 26 + # No "depends on OF" because this can also be used for manually 27 + # (board-file) instantiated "hid-over-i2c" type i2c-clients. 27 28 select I2C_HID_CORE 28 29 help 29 30 Say Y here if you use a keyboard, a touchpad, a touchscreen, or any 30 31 other HID based devices which is connected to your computer via I2C. 31 - This driver supports Open Firmware (Device Tree)-based systems. 32 + This driver supports Open Firmware (Device Tree)-based systems as 33 + well as binding to manually (board-file) instantiated i2c-hid-clients. 32 34 33 35 If unsure, say N. 34 36
+29 -9
drivers/hid/i2c-hid/i2c-hid-of.c
··· 21 21 22 22 #include <linux/delay.h> 23 23 #include <linux/device.h> 24 + #include <linux/gpio/consumer.h> 24 25 #include <linux/hid.h> 25 26 #include <linux/i2c.h> 26 27 #include <linux/kernel.h> ··· 36 35 struct i2chid_ops ops; 37 36 38 37 struct i2c_client *client; 38 + struct gpio_desc *reset_gpio; 39 39 struct regulator_bulk_data supplies[2]; 40 40 int post_power_delay_ms; 41 + int post_reset_delay_ms; 41 42 }; 42 43 43 44 static int i2c_hid_of_power_up(struct i2chid_ops *ops) ··· 58 55 if (ihid_of->post_power_delay_ms) 59 56 msleep(ihid_of->post_power_delay_ms); 60 57 58 + gpiod_set_value_cansleep(ihid_of->reset_gpio, 0); 59 + if (ihid_of->post_reset_delay_ms) 60 + msleep(ihid_of->post_reset_delay_ms); 61 + 61 62 return 0; 62 63 } 63 64 ··· 69 62 { 70 63 struct i2c_hid_of *ihid_of = container_of(ops, struct i2c_hid_of, ops); 71 64 65 + gpiod_set_value_cansleep(ihid_of->reset_gpio, 1); 72 66 regulator_bulk_disable(ARRAY_SIZE(ihid_of->supplies), 73 67 ihid_of->supplies); 74 68 } ··· 83 75 int ret; 84 76 u32 val; 85 77 86 - ihid_of = devm_kzalloc(&client->dev, sizeof(*ihid_of), GFP_KERNEL); 78 + ihid_of = devm_kzalloc(dev, sizeof(*ihid_of), GFP_KERNEL); 87 79 if (!ihid_of) 88 80 return -ENOMEM; 89 81 90 82 ihid_of->ops.power_up = i2c_hid_of_power_up; 91 83 ihid_of->ops.power_down = i2c_hid_of_power_down; 92 84 93 - ret = of_property_read_u32(dev->of_node, "hid-descr-addr", &val); 85 + ret = device_property_read_u32(dev, "hid-descr-addr", &val); 94 86 if (ret) { 95 - dev_err(&client->dev, "HID register address not provided\n"); 87 + dev_err(dev, "HID register address not provided\n"); 96 88 return -ENODEV; 97 89 } 98 90 if (val >> 16) { 99 - dev_err(&client->dev, "Bad HID register address: 0x%08x\n", 100 - val); 91 + dev_err(dev, "Bad HID register address: 0x%08x\n", val); 101 92 return -EINVAL; 102 93 } 103 94 hid_descriptor_address = val; 104 95 105 - if (!device_property_read_u32(&client->dev, "post-power-on-delay-ms", 106 - &val)) 96 + if (!device_property_read_u32(dev, "post-power-on-delay-ms", &val)) 107 97 ihid_of->post_power_delay_ms = val; 98 + 99 + /* 100 + * Note this is a kernel internal device-property set by x86 platform code, 101 + * this MUST not be used in devicetree files without first adding it to 102 + * the DT bindings. 103 + */ 104 + if (!device_property_read_u32(dev, "post-reset-deassert-delay-ms", &val)) 105 + ihid_of->post_reset_delay_ms = val; 106 + 107 + /* Start out with reset asserted */ 108 + ihid_of->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); 109 + if (IS_ERR(ihid_of->reset_gpio)) 110 + return PTR_ERR(ihid_of->reset_gpio); 108 111 109 112 ihid_of->supplies[0].supply = "vdd"; 110 113 ihid_of->supplies[1].supply = "vddl"; 111 - ret = devm_regulator_bulk_get(&client->dev, 112 - ARRAY_SIZE(ihid_of->supplies), 114 + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ihid_of->supplies), 113 115 ihid_of->supplies); 114 116 if (ret) 115 117 return ret; ··· 134 116 hid_descriptor_address, quirks); 135 117 } 136 118 119 + #ifdef CONFIG_OF 137 120 static const struct of_device_id i2c_hid_of_match[] = { 138 121 { .compatible = "hid-over-i2c" }, 139 122 {}, 140 123 }; 141 124 MODULE_DEVICE_TABLE(of, i2c_hid_of_match); 125 + #endif 142 126 143 127 static const struct i2c_device_id i2c_hid_of_id_table[] = { 144 128 { "hid", 0 },
-10
drivers/hid/wacom_sys.c
··· 2372 2372 if (error) 2373 2373 goto fail; 2374 2374 2375 - if (!(features->device_type & WACOM_DEVICETYPE_WL_MONITOR) && 2376 - (features->quirks & WACOM_QUIRK_BATTERY)) { 2377 - error = wacom_initialize_battery(wacom); 2378 - if (error) 2379 - goto fail; 2380 - } 2381 - 2382 2375 error = wacom_register_inputs(wacom); 2383 2376 if (error) 2384 2377 goto fail; ··· 2502 2509 2503 2510 strscpy(wacom_wac->name, wacom_wac1->name, 2504 2511 sizeof(wacom_wac->name)); 2505 - error = wacom_initialize_battery(wacom); 2506 - if (error) 2507 - goto fail; 2508 2512 } 2509 2513 2510 2514 return;
+53 -31
drivers/hid/wacom_wac.c
··· 113 113 bool bat_connected, bool ps_connected) 114 114 { 115 115 struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); 116 + bool bat_initialized = wacom->battery.battery; 117 + bool has_quirk = wacom_wac->features.quirks & WACOM_QUIRK_BATTERY; 118 + 119 + if (bat_initialized != has_quirk) 120 + wacom_schedule_work(wacom_wac, WACOM_WORKER_BATTERY); 116 121 117 122 __wacom_notify_battery(&wacom->battery, bat_status, bat_capacity, 118 123 bat_charging, bat_connected, ps_connected); ··· 1313 1308 1314 1309 struct input_dev *pen_input = wacom->pen_input; 1315 1310 unsigned char *data = wacom->data; 1311 + int number_of_valid_frames = 0; 1312 + int time_interval = 15000000; 1313 + ktime_t time_packet_received = ktime_get(); 1316 1314 int i; 1317 1315 1318 1316 if (wacom->features.type == INTUOSP2_BT || ··· 1336 1328 wacom->id[0] |= (wacom->serial[0] >> 32) & 0xFFFFF; 1337 1329 } 1338 1330 1331 + /* number of valid frames */ 1339 1332 for (i = 0; i < pen_frames; i++) { 1333 + unsigned char *frame = &data[i*pen_frame_len + 1]; 1334 + bool valid = frame[0] & 0x80; 1335 + 1336 + if (valid) 1337 + number_of_valid_frames++; 1338 + } 1339 + 1340 + if (number_of_valid_frames) { 1341 + if (wacom->hid_data.time_delayed) 1342 + time_interval = ktime_get() - wacom->hid_data.time_delayed; 1343 + time_interval /= number_of_valid_frames; 1344 + wacom->hid_data.time_delayed = time_packet_received; 1345 + } 1346 + 1347 + for (i = 0; i < number_of_valid_frames; i++) { 1340 1348 unsigned char *frame = &data[i*pen_frame_len + 1]; 1341 1349 bool valid = frame[0] & 0x80; 1342 1350 bool prox = frame[0] & 0x40; 1343 1351 bool range = frame[0] & 0x20; 1344 1352 bool invert = frame[0] & 0x10; 1353 + int frames_number_reversed = number_of_valid_frames - i - 1; 1354 + int event_timestamp = time_packet_received - frames_number_reversed * time_interval; 1345 1355 1346 1356 if (!valid) 1347 1357 continue; ··· 1372 1346 wacom->tool[0] = 0; 1373 1347 wacom->id[0] = 0; 1374 1348 wacom->serial[0] = 0; 1349 + wacom->hid_data.time_delayed = 0; 1375 1350 return; 1376 1351 } 1377 1352 ··· 1409 1382 get_unaligned_le16(&frame[11])); 1410 1383 } 1411 1384 } 1385 + 1412 1386 if (wacom->tool[0]) { 1413 1387 input_report_abs(pen_input, ABS_PRESSURE, get_unaligned_le16(&frame[5])); 1414 1388 if (wacom->features.type == INTUOSP2_BT || ··· 1432 1404 } 1433 1405 1434 1406 wacom->shared->stylus_in_proximity = prox; 1407 + 1408 + /* add timestamp to unpack the frames */ 1409 + input_set_timestamp(pen_input, event_timestamp); 1435 1410 1436 1411 input_sync(pen_input); 1437 1412 } ··· 1926 1895 int fmax = field->logical_maximum; 1927 1896 unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid); 1928 1897 int resolution_code = code; 1898 + int resolution = hidinput_calc_abs_res(field, resolution_code); 1929 1899 1930 1900 if (equivalent_usage == HID_DG_TWIST) { 1931 1901 resolution_code = ABS_RZ; ··· 1947 1915 switch (type) { 1948 1916 case EV_ABS: 1949 1917 input_set_abs_params(input, code, fmin, fmax, fuzz, 0); 1950 - input_abs_set_res(input, code, 1951 - hidinput_calc_abs_res(field, resolution_code)); 1918 + 1919 + /* older tablet may miss physical usage */ 1920 + if ((code == ABS_X || code == ABS_Y) && !resolution) { 1921 + resolution = WACOM_INTUOS_RES; 1922 + hid_warn(input, 1923 + "Wacom usage (%d) missing resolution \n", 1924 + code); 1925 + } 1926 + input_abs_set_res(input, code, resolution); 1952 1927 break; 1953 1928 case EV_KEY: 1954 1929 case EV_MSC: ··· 1968 1929 static void wacom_wac_battery_usage_mapping(struct hid_device *hdev, 1969 1930 struct hid_field *field, struct hid_usage *usage) 1970 1931 { 1971 - struct wacom *wacom = hid_get_drvdata(hdev); 1972 - struct wacom_wac *wacom_wac = &wacom->wacom_wac; 1973 - struct wacom_features *features = &wacom_wac->features; 1974 - unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); 1975 - 1976 - switch (equivalent_usage) { 1977 - case HID_DG_BATTERYSTRENGTH: 1978 - case WACOM_HID_WD_BATTERY_LEVEL: 1979 - case WACOM_HID_WD_BATTERY_CHARGING: 1980 - features->quirks |= WACOM_QUIRK_BATTERY; 1981 - break; 1982 - } 1932 + return; 1983 1933 } 1984 1934 1985 1935 static void wacom_wac_battery_event(struct hid_device *hdev, struct hid_field *field, ··· 1989 1961 wacom_wac->hid_data.bat_connected = 1; 1990 1962 wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO; 1991 1963 } 1964 + wacom_wac->features.quirks |= WACOM_QUIRK_BATTERY; 1992 1965 break; 1993 1966 case WACOM_HID_WD_BATTERY_LEVEL: 1994 1967 value = value * 100 / (field->logical_maximum - field->logical_minimum); 1995 1968 wacom_wac->hid_data.battery_capacity = value; 1996 1969 wacom_wac->hid_data.bat_connected = 1; 1997 1970 wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO; 1971 + wacom_wac->features.quirks |= WACOM_QUIRK_BATTERY; 1998 1972 break; 1999 1973 case WACOM_HID_WD_BATTERY_CHARGING: 2000 1974 wacom_wac->hid_data.bat_charging = value; 2001 1975 wacom_wac->hid_data.ps_connected = value; 2002 1976 wacom_wac->hid_data.bat_connected = 1; 2003 1977 wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO; 1978 + wacom_wac->features.quirks |= WACOM_QUIRK_BATTERY; 2004 1979 break; 2005 1980 } 2006 1981 } ··· 2019 1988 { 2020 1989 struct wacom *wacom = hid_get_drvdata(hdev); 2021 1990 struct wacom_wac *wacom_wac = &wacom->wacom_wac; 2022 - struct wacom_features *features = &wacom_wac->features; 2023 1991 2024 - if (features->quirks & WACOM_QUIRK_BATTERY) { 2025 - int status = wacom_wac->hid_data.bat_status; 2026 - int capacity = wacom_wac->hid_data.battery_capacity; 2027 - bool charging = wacom_wac->hid_data.bat_charging; 2028 - bool connected = wacom_wac->hid_data.bat_connected; 2029 - bool powered = wacom_wac->hid_data.ps_connected; 1992 + int status = wacom_wac->hid_data.bat_status; 1993 + int capacity = wacom_wac->hid_data.battery_capacity; 1994 + bool charging = wacom_wac->hid_data.bat_charging; 1995 + bool connected = wacom_wac->hid_data.bat_connected; 1996 + bool powered = wacom_wac->hid_data.ps_connected; 2030 1997 2031 - wacom_notify_battery(wacom_wac, status, capacity, charging, 2032 - connected, powered); 2033 - } 1998 + wacom_notify_battery(wacom_wac, status, capacity, charging, 1999 + connected, powered); 2034 2000 } 2035 2001 2036 2002 static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, ··· 3393 3365 int battery = (data[8] & 0x3f) * 100 / 31; 3394 3366 bool charging = !!(data[8] & 0x80); 3395 3367 3368 + features->quirks |= WACOM_QUIRK_BATTERY; 3396 3369 wacom_notify_battery(wacom_wac, WACOM_POWER_SUPPLY_STATUS_AUTO, 3397 3370 battery, charging, battery || charging, 1); 3398 - 3399 - if (!wacom->battery.battery && 3400 - !(features->quirks & WACOM_QUIRK_BATTERY)) { 3401 - features->quirks |= WACOM_QUIRK_BATTERY; 3402 - wacom_schedule_work(wacom_wac, WACOM_WORKER_BATTERY); 3403 - } 3404 3371 } 3405 3372 else if ((features->quirks & WACOM_QUIRK_BATTERY) && 3406 3373 wacom->battery.battery) { 3407 3374 features->quirks &= ~WACOM_QUIRK_BATTERY; 3408 - wacom_schedule_work(wacom_wac, WACOM_WORKER_BATTERY); 3409 3375 wacom_notify_battery(wacom_wac, POWER_SUPPLY_STATUS_UNKNOWN, 0, 0, 0, 0); 3410 3376 } 3411 3377 return 0;
+1
drivers/hid/wacom_wac.h
··· 324 324 int ps_connected; 325 325 bool pad_input_event_flag; 326 326 unsigned short sequence_number; 327 + int time_delayed; 327 328 }; 328 329 329 330 struct wacom_remote_data {
+40
drivers/usb/core/message.c
··· 1908 1908 usb_put_intf(iface); /* Undo _get_ in usb_queue_reset_device() */ 1909 1909 } 1910 1910 1911 + /* 1912 + * Internal function to set the wireless_status sysfs attribute 1913 + * See usb_set_wireless_status() for more details 1914 + */ 1915 + static void __usb_wireless_status_intf(struct work_struct *ws) 1916 + { 1917 + struct usb_interface *iface = 1918 + container_of(ws, struct usb_interface, wireless_status_work); 1919 + 1920 + device_lock(iface->dev.parent); 1921 + if (iface->sysfs_files_created) 1922 + usb_update_wireless_status_attr(iface); 1923 + device_unlock(iface->dev.parent); 1924 + usb_put_intf(iface); /* Undo _get_ in usb_set_wireless_status() */ 1925 + } 1926 + 1927 + /** 1928 + * usb_set_wireless_status - sets the wireless_status struct member 1929 + * @iface: the interface to modify 1930 + * @status: the new wireless status 1931 + * 1932 + * Set the wireless_status struct member to the new value, and emit 1933 + * sysfs changes as necessary. 1934 + * 1935 + * Returns: 0 on success, -EALREADY if already set. 1936 + */ 1937 + int usb_set_wireless_status(struct usb_interface *iface, 1938 + enum usb_wireless_status status) 1939 + { 1940 + if (iface->wireless_status == status) 1941 + return -EALREADY; 1942 + 1943 + usb_get_intf(iface); 1944 + iface->wireless_status = status; 1945 + schedule_work(&iface->wireless_status_work); 1946 + 1947 + return 0; 1948 + } 1949 + EXPORT_SYMBOL_GPL(usb_set_wireless_status); 1911 1950 1912 1951 /* 1913 1952 * usb_set_configuration - Makes a particular device setting be current ··· 2139 2100 intf->dev.type = &usb_if_device_type; 2140 2101 intf->dev.groups = usb_interface_groups; 2141 2102 INIT_WORK(&intf->reset_ws, __usb_queue_reset_device); 2103 + INIT_WORK(&intf->wireless_status_work, __usb_wireless_status_intf); 2142 2104 intf->minor = -1; 2143 2105 device_initialize(&intf->dev); 2144 2106 pm_runtime_no_callbacks(&intf->dev);
+50
drivers/usb/core/sysfs.c
··· 1227 1227 .is_visible = intf_assoc_attrs_are_visible, 1228 1228 }; 1229 1229 1230 + static ssize_t wireless_status_show(struct device *dev, 1231 + struct device_attribute *attr, char *buf) 1232 + { 1233 + struct usb_interface *intf; 1234 + 1235 + intf = to_usb_interface(dev); 1236 + if (intf->wireless_status == USB_WIRELESS_STATUS_DISCONNECTED) 1237 + return sysfs_emit(buf, "%s\n", "disconnected"); 1238 + return sysfs_emit(buf, "%s\n", "connected"); 1239 + } 1240 + static DEVICE_ATTR_RO(wireless_status); 1241 + 1242 + static struct attribute *intf_wireless_status_attrs[] = { 1243 + &dev_attr_wireless_status.attr, 1244 + NULL 1245 + }; 1246 + 1247 + static umode_t intf_wireless_status_attr_is_visible(struct kobject *kobj, 1248 + struct attribute *a, int n) 1249 + { 1250 + struct device *dev = kobj_to_dev(kobj); 1251 + struct usb_interface *intf = to_usb_interface(dev); 1252 + 1253 + if (a != &dev_attr_wireless_status.attr || 1254 + intf->wireless_status != USB_WIRELESS_STATUS_NA) 1255 + return a->mode; 1256 + return 0; 1257 + } 1258 + 1259 + static const struct attribute_group intf_wireless_status_attr_grp = { 1260 + .attrs = intf_wireless_status_attrs, 1261 + .is_visible = intf_wireless_status_attr_is_visible, 1262 + }; 1263 + 1264 + int usb_update_wireless_status_attr(struct usb_interface *intf) 1265 + { 1266 + struct device *dev = &intf->dev; 1267 + int ret; 1268 + 1269 + ret = sysfs_update_group(&dev->kobj, &intf_wireless_status_attr_grp); 1270 + if (ret < 0) 1271 + return ret; 1272 + 1273 + sysfs_notify(&dev->kobj, NULL, "wireless_status"); 1274 + kobject_uevent(&dev->kobj, KOBJ_CHANGE); 1275 + 1276 + return 0; 1277 + } 1278 + 1230 1279 const struct attribute_group *usb_interface_groups[] = { 1231 1280 &intf_attr_grp, 1232 1281 &intf_assoc_attr_grp, 1282 + &intf_wireless_status_attr_grp, 1233 1283 NULL 1234 1284 }; 1235 1285
+1
drivers/usb/core/usb.h
··· 15 15 extern void usb_remove_sysfs_dev_files(struct usb_device *dev); 16 16 extern void usb_create_sysfs_intf_files(struct usb_interface *intf); 17 17 extern void usb_remove_sysfs_intf_files(struct usb_interface *intf); 18 + extern int usb_update_wireless_status_attr(struct usb_interface *intf); 18 19 extern int usb_create_ep_devs(struct device *parent, 19 20 struct usb_host_endpoint *endpoint, 20 21 struct usb_device *udev);
+2 -1
include/linux/hid.h
··· 156 156 #define HID_UP_DIGITIZER 0x000d0000 157 157 #define HID_UP_PID 0x000f0000 158 158 #define HID_UP_BATTERY 0x00850000 159 + #define HID_UP_CAMERA 0x00900000 159 160 #define HID_UP_HPVENDOR 0xff7f0000 160 161 #define HID_UP_HPVENDOR2 0xff010000 161 162 #define HID_UP_MSVENDOR 0xff000000 ··· 874 873 /* We ignore a few input applications that are not widely used */ 875 874 #define IS_INPUT_APPLICATION(a) \ 876 875 (((a >= HID_UP_GENDESK) && (a <= HID_GD_MULTIAXIS)) \ 877 - || ((a >= HID_DG_PEN) && (a <= HID_DG_WHITEBOARD)) \ 876 + || ((a >= HID_DG_DIGITIZER) && (a <= HID_DG_WHITEBOARD)) \ 878 877 || (a == HID_GD_SYSTEM_CONTROL) || (a == HID_CP_CONSUMER_CONTROL) \ 879 878 || (a == HID_GD_WIRELESS_RADIO_CTLS)) 880 879
+16
include/linux/usb.h
··· 170 170 return usb_find_common_endpoints_reverse(alt, NULL, NULL, NULL, int_out); 171 171 } 172 172 173 + enum usb_wireless_status { 174 + USB_WIRELESS_STATUS_NA = 0, 175 + USB_WIRELESS_STATUS_DISCONNECTED, 176 + USB_WIRELESS_STATUS_CONNECTED, 177 + }; 178 + 173 179 /** 174 180 * struct usb_interface - what usb device drivers talk to 175 181 * @altsetting: array of interface structures, one for each alternate ··· 203 197 * following a reset or suspend operation it doesn't support. 204 198 * @authorized: This allows to (de)authorize individual interfaces instead 205 199 * a whole device in contrast to the device authorization. 200 + * @wireless_status: if the USB device uses a receiver/emitter combo, whether 201 + * the emitter is connected. 202 + * @wireless_status_work: Used for scheduling wireless status changes 203 + * from atomic context. 206 204 * @dev: driver model's view of this device 207 205 * @usb_dev: if an interface is bound to the USB major, this will point 208 206 * to the sysfs representation for that device. ··· 263 253 unsigned needs_binding:1; /* needs delayed unbind/rebind */ 264 254 unsigned resetting_device:1; /* true: bandwidth alloc after reset */ 265 255 unsigned authorized:1; /* used for interface authorization */ 256 + enum usb_wireless_status wireless_status; 257 + struct work_struct wireless_status_work; 266 258 267 259 struct device dev; /* interface specific device info */ 268 260 struct device *usb_dev; ··· 899 887 900 888 extern void usb_driver_release_interface(struct usb_driver *driver, 901 889 struct usb_interface *iface); 890 + 891 + int usb_set_wireless_status(struct usb_interface *iface, 892 + enum usb_wireless_status status); 893 + 902 894 const struct usb_device_id *usb_match_id(struct usb_interface *interface, 903 895 const struct usb_device_id *id); 904 896 extern int usb_match_one_id(struct usb_interface *interface,
+12
tools/testing/selftests/hid/Makefile
··· 5 5 include ../../../scripts/Makefile.arch 6 6 include ../../../scripts/Makefile.include 7 7 8 + TEST_PROGS := hid-core.sh 9 + TEST_PROGS += hid-apple.sh 10 + TEST_PROGS += hid-gamepad.sh 11 + TEST_PROGS += hid-ite.sh 12 + TEST_PROGS += hid-keyboard.sh 13 + TEST_PROGS += hid-mouse.sh 14 + TEST_PROGS += hid-multitouch.sh 15 + TEST_PROGS += hid-sony.sh 16 + TEST_PROGS += hid-tablet.sh 17 + TEST_PROGS += hid-usb_crash.sh 18 + TEST_PROGS += hid-wacom.sh 19 + 8 20 CXX ?= $(CROSS_COMPILE)g++ 9 21 10 22 HOSTPKG_CONFIG := pkg-config
+11
tools/testing/selftests/hid/config
··· 20 20 CONFIG_HID_BPF=y 21 21 CONFIG_INPUT_EVDEV=y 22 22 CONFIG_UHID=y 23 + CONFIG_LEDS_CLASS_MULTICOLOR=y 24 + CONFIG_USB=y 25 + CONFIG_USB_HID=y 26 + CONFIG_HID_APPLE=y 27 + CONFIG_HID_ITE=y 28 + CONFIG_HID_MULTITOUCH=y 29 + CONFIG_HID_PLAYSTATION=y 30 + CONFIG_PLAYSTATION_FF=y 31 + CONFIG_HID_SONY=y 32 + CONFIG_SONY_FF=y 33 + CONFIG_HID_WACOM=y
+7
tools/testing/selftests/hid/hid-apple.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Runs tests for the HID subsystem 4 + 5 + export TARGET=test_apple_keyboard.py 6 + 7 + bash ./run-hid-tools-tests.sh
+7
tools/testing/selftests/hid/hid-core.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Runs tests for the HID subsystem 4 + 5 + export TARGET=test_hid_core.py 6 + 7 + bash ./run-hid-tools-tests.sh
+7
tools/testing/selftests/hid/hid-gamepad.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Runs tests for the HID subsystem 4 + 5 + export TARGET=test_gamepad.py 6 + 7 + bash ./run-hid-tools-tests.sh
+7
tools/testing/selftests/hid/hid-ite.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Runs tests for the HID subsystem 4 + 5 + export TARGET=test_ite_keyboard.py 6 + 7 + bash ./run-hid-tools-tests.sh
+7
tools/testing/selftests/hid/hid-keyboard.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Runs tests for the HID subsystem 4 + 5 + export TARGET=test_keyboard.py 6 + 7 + bash ./run-hid-tools-tests.sh
+7
tools/testing/selftests/hid/hid-mouse.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Runs tests for the HID subsystem 4 + 5 + export TARGET=test_mouse.py 6 + 7 + bash ./run-hid-tools-tests.sh
+7
tools/testing/selftests/hid/hid-multitouch.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Runs tests for the HID subsystem 4 + 5 + export TARGET=test_multitouch.py 6 + 7 + bash ./run-hid-tools-tests.sh
+7
tools/testing/selftests/hid/hid-sony.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Runs tests for the HID subsystem 4 + 5 + export TARGET=test_sony.py 6 + 7 + bash ./run-hid-tools-tests.sh
+7
tools/testing/selftests/hid/hid-tablet.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Runs tests for the HID subsystem 4 + 5 + export TARGET=test_tablet.py 6 + 7 + bash ./run-hid-tools-tests.sh
+7
tools/testing/selftests/hid/hid-usb_crash.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Runs tests for the HID subsystem 4 + 5 + export TARGET=test_usb_crash.py 6 + 7 + bash ./run-hid-tools-tests.sh
+7
tools/testing/selftests/hid/hid-wacom.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Runs tests for the HID subsystem 4 + 5 + export TARGET=test_wacom_generic.py 6 + 7 + bash ./run-hid-tools-tests.sh
+28
tools/testing/selftests/hid/run-hid-tools-tests.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Runs tests for the HID subsystem 4 + 5 + if ! command -v python3 > /dev/null 2>&1; then 6 + echo "hid-tools: [SKIP] python3 not installed" 7 + exit 77 8 + fi 9 + 10 + if ! python3 -c "import pytest" > /dev/null 2>&1; then 11 + echo "hid: [SKIP/ pytest module not installed" 12 + exit 77 13 + fi 14 + 15 + if ! python3 -c "import pytest_tap" > /dev/null 2>&1; then 16 + echo "hid: [SKIP/ pytest_tap module not installed" 17 + exit 77 18 + fi 19 + 20 + if ! python3 -c "import hidtools" > /dev/null 2>&1; then 21 + echo "hid: [SKIP/ hid-tools module not installed" 22 + exit 77 23 + fi 24 + 25 + TARGET=${TARGET:=.} 26 + 27 + echo TAP version 13 28 + python3 -u -m pytest $PYTEST_XDIST ./tests/$TARGET --tap-stream --udevd
+3
tools/testing/selftests/hid/settings
··· 1 + # HID tests can be long, so give a little bit more time 2 + # to them 3 + timeout=200
+2
tools/testing/selftests/hid/tests/__init__.py
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # Just to make sphinx-apidoc document this directory
+345
tools/testing/selftests/hid/tests/base.py
··· 1 + #!/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # -*- coding: utf-8 -*- 4 + # 5 + # Copyright (c) 2017 Benjamin Tissoires <benjamin.tissoires@gmail.com> 6 + # Copyright (c) 2017 Red Hat, Inc. 7 + 8 + import libevdev 9 + import os 10 + import pytest 11 + import time 12 + 13 + import logging 14 + 15 + from hidtools.device.base_device import BaseDevice, EvdevMatch, SysfsFile 16 + from pathlib import Path 17 + from typing import Final 18 + 19 + logger = logging.getLogger("hidtools.test.base") 20 + 21 + # application to matches 22 + application_matches: Final = { 23 + # pyright: ignore 24 + "Accelerometer": EvdevMatch( 25 + req_properties=[ 26 + libevdev.INPUT_PROP_ACCELEROMETER, 27 + ] 28 + ), 29 + "Game Pad": EvdevMatch( # in systemd, this is a lot more complex, but that will do 30 + requires=[ 31 + libevdev.EV_ABS.ABS_X, 32 + libevdev.EV_ABS.ABS_Y, 33 + libevdev.EV_ABS.ABS_RX, 34 + libevdev.EV_ABS.ABS_RY, 35 + libevdev.EV_KEY.BTN_START, 36 + ], 37 + excl_properties=[ 38 + libevdev.INPUT_PROP_ACCELEROMETER, 39 + ], 40 + ), 41 + "Joystick": EvdevMatch( # in systemd, this is a lot more complex, but that will do 42 + requires=[ 43 + libevdev.EV_ABS.ABS_RX, 44 + libevdev.EV_ABS.ABS_RY, 45 + libevdev.EV_KEY.BTN_START, 46 + ], 47 + excl_properties=[ 48 + libevdev.INPUT_PROP_ACCELEROMETER, 49 + ], 50 + ), 51 + "Key": EvdevMatch( 52 + requires=[ 53 + libevdev.EV_KEY.KEY_A, 54 + ], 55 + excl_properties=[ 56 + libevdev.INPUT_PROP_ACCELEROMETER, 57 + libevdev.INPUT_PROP_DIRECT, 58 + libevdev.INPUT_PROP_POINTER, 59 + ], 60 + ), 61 + "Mouse": EvdevMatch( 62 + requires=[ 63 + libevdev.EV_REL.REL_X, 64 + libevdev.EV_REL.REL_Y, 65 + libevdev.EV_KEY.BTN_LEFT, 66 + ], 67 + excl_properties=[ 68 + libevdev.INPUT_PROP_ACCELEROMETER, 69 + ], 70 + ), 71 + "Pad": EvdevMatch( 72 + requires=[ 73 + libevdev.EV_KEY.BTN_0, 74 + ], 75 + excludes=[ 76 + libevdev.EV_KEY.BTN_TOOL_PEN, 77 + libevdev.EV_KEY.BTN_TOUCH, 78 + libevdev.EV_ABS.ABS_DISTANCE, 79 + ], 80 + excl_properties=[ 81 + libevdev.INPUT_PROP_ACCELEROMETER, 82 + ], 83 + ), 84 + "Pen": EvdevMatch( 85 + requires=[ 86 + libevdev.EV_KEY.BTN_STYLUS, 87 + libevdev.EV_ABS.ABS_X, 88 + libevdev.EV_ABS.ABS_Y, 89 + ], 90 + excl_properties=[ 91 + libevdev.INPUT_PROP_ACCELEROMETER, 92 + ], 93 + ), 94 + "Stylus": EvdevMatch( 95 + requires=[ 96 + libevdev.EV_KEY.BTN_STYLUS, 97 + libevdev.EV_ABS.ABS_X, 98 + libevdev.EV_ABS.ABS_Y, 99 + ], 100 + excl_properties=[ 101 + libevdev.INPUT_PROP_ACCELEROMETER, 102 + ], 103 + ), 104 + "Touch Pad": EvdevMatch( 105 + requires=[ 106 + libevdev.EV_KEY.BTN_LEFT, 107 + libevdev.EV_ABS.ABS_X, 108 + libevdev.EV_ABS.ABS_Y, 109 + ], 110 + excludes=[libevdev.EV_KEY.BTN_TOOL_PEN, libevdev.EV_KEY.BTN_STYLUS], 111 + req_properties=[ 112 + libevdev.INPUT_PROP_POINTER, 113 + ], 114 + excl_properties=[ 115 + libevdev.INPUT_PROP_ACCELEROMETER, 116 + ], 117 + ), 118 + "Touch Screen": EvdevMatch( 119 + requires=[ 120 + libevdev.EV_KEY.BTN_TOUCH, 121 + libevdev.EV_ABS.ABS_X, 122 + libevdev.EV_ABS.ABS_Y, 123 + ], 124 + excludes=[libevdev.EV_KEY.BTN_TOOL_PEN, libevdev.EV_KEY.BTN_STYLUS], 125 + req_properties=[ 126 + libevdev.INPUT_PROP_DIRECT, 127 + ], 128 + excl_properties=[ 129 + libevdev.INPUT_PROP_ACCELEROMETER, 130 + ], 131 + ), 132 + } 133 + 134 + 135 + class UHIDTestDevice(BaseDevice): 136 + def __init__(self, name, application, rdesc_str=None, rdesc=None, input_info=None): 137 + super().__init__(name, application, rdesc_str, rdesc, input_info) 138 + self.application_matches = application_matches 139 + if name is None: 140 + name = f"uhid test {self.__class__.__name__}" 141 + if not name.startswith("uhid test "): 142 + name = "uhid test " + self.name 143 + self.name = name 144 + 145 + 146 + class BaseTestCase: 147 + class TestUhid(object): 148 + syn_event = libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT) # type: ignore 149 + key_event = libevdev.InputEvent(libevdev.EV_KEY) # type: ignore 150 + abs_event = libevdev.InputEvent(libevdev.EV_ABS) # type: ignore 151 + rel_event = libevdev.InputEvent(libevdev.EV_REL) # type: ignore 152 + msc_event = libevdev.InputEvent(libevdev.EV_MSC.MSC_SCAN) # type: ignore 153 + 154 + # List of kernel modules to load before starting the test 155 + # if any module is not available (not compiled), the test will skip. 156 + # Each element is a tuple '(kernel driver name, kernel module)', 157 + # for example ("playstation", "hid-playstation") 158 + kernel_modules = [] 159 + 160 + def assertInputEventsIn(self, expected_events, effective_events): 161 + effective_events = effective_events.copy() 162 + for ev in expected_events: 163 + assert ev in effective_events 164 + effective_events.remove(ev) 165 + return effective_events 166 + 167 + def assertInputEvents(self, expected_events, effective_events): 168 + remaining = self.assertInputEventsIn(expected_events, effective_events) 169 + assert remaining == [] 170 + 171 + @classmethod 172 + def debug_reports(cls, reports, uhdev=None, events=None): 173 + data = [" ".join([f"{v:02x}" for v in r]) for r in reports] 174 + 175 + if uhdev is not None: 176 + human_data = [ 177 + uhdev.parsed_rdesc.format_report(r, split_lines=True) 178 + for r in reports 179 + ] 180 + try: 181 + human_data = [ 182 + f'\n\t {" " * h.index("/")}'.join(h.split("\n")) 183 + for h in human_data 184 + ] 185 + except ValueError: 186 + # '/' not found: not a numbered report 187 + human_data = ["\n\t ".join(h.split("\n")) for h in human_data] 188 + data = [f"{d}\n\t ====> {h}" for d, h in zip(data, human_data)] 189 + 190 + reports = data 191 + 192 + if len(reports) == 1: 193 + print("sending 1 report:") 194 + else: 195 + print(f"sending {len(reports)} reports:") 196 + for report in reports: 197 + print("\t", report) 198 + 199 + if events is not None: 200 + print("events received:", events) 201 + 202 + def create_device(self): 203 + raise Exception("please reimplement me in subclasses") 204 + 205 + def _load_kernel_module(self, kernel_driver, kernel_module): 206 + sysfs_path = Path("/sys/bus/hid/drivers") 207 + if kernel_driver is not None: 208 + sysfs_path /= kernel_driver 209 + else: 210 + # special case for when testing all available modules: 211 + # we don't know beforehand the name of the module from modinfo 212 + sysfs_path = Path("/sys/module") / kernel_module.replace("-", "_") 213 + if not sysfs_path.exists(): 214 + import subprocess 215 + 216 + ret = subprocess.run(["/usr/sbin/modprobe", kernel_module]) 217 + if ret.returncode != 0: 218 + pytest.skip( 219 + f"module {kernel_module} could not be loaded, skipping the test" 220 + ) 221 + 222 + @pytest.fixture() 223 + def load_kernel_module(self): 224 + for kernel_driver, kernel_module in self.kernel_modules: 225 + self._load_kernel_module(kernel_driver, kernel_module) 226 + yield 227 + 228 + @pytest.fixture() 229 + def new_uhdev(self, load_kernel_module): 230 + return self.create_device() 231 + 232 + def assertName(self, uhdev): 233 + evdev = uhdev.get_evdev() 234 + assert uhdev.name in evdev.name 235 + 236 + @pytest.fixture(autouse=True) 237 + def context(self, new_uhdev, request): 238 + try: 239 + with HIDTestUdevRule.instance(): 240 + with new_uhdev as self.uhdev: 241 + skip_cond = request.node.get_closest_marker("skip_if_uhdev") 242 + if skip_cond: 243 + test, message, *rest = skip_cond.args 244 + 245 + if test(self.uhdev): 246 + pytest.skip(message) 247 + 248 + self.uhdev.create_kernel_device() 249 + now = time.time() 250 + while not self.uhdev.is_ready() and time.time() - now < 5: 251 + self.uhdev.dispatch(1) 252 + if self.uhdev.get_evdev() is None: 253 + logger.warning( 254 + f"available list of input nodes: (default application is '{self.uhdev.application}')" 255 + ) 256 + logger.warning(self.uhdev.input_nodes) 257 + yield 258 + self.uhdev = None 259 + except PermissionError: 260 + pytest.skip("Insufficient permissions, run me as root") 261 + 262 + @pytest.fixture(autouse=True) 263 + def check_taint(self): 264 + # we are abusing SysfsFile here, it's in /proc, but meh 265 + taint_file = SysfsFile("/proc/sys/kernel/tainted") 266 + taint = taint_file.int_value 267 + 268 + yield 269 + 270 + assert taint_file.int_value == taint 271 + 272 + def test_creation(self): 273 + """Make sure the device gets processed by the kernel and creates 274 + the expected application input node. 275 + 276 + If this fail, there is something wrong in the device report 277 + descriptors.""" 278 + uhdev = self.uhdev 279 + assert uhdev is not None 280 + assert uhdev.get_evdev() is not None 281 + self.assertName(uhdev) 282 + assert len(uhdev.next_sync_events()) == 0 283 + assert uhdev.get_evdev() is not None 284 + 285 + 286 + class HIDTestUdevRule(object): 287 + _instance = None 288 + """ 289 + A context-manager compatible class that sets up our udev rules file and 290 + deletes it on context exit. 291 + 292 + This class is tailored to our test setup: it only sets up the udev rule 293 + on the **second** context and it cleans it up again on the last context 294 + removed. This matches the expected pytest setup: we enter a context for 295 + the session once, then once for each test (the first of which will 296 + trigger the udev rule) and once the last test exited and the session 297 + exited, we clean up after ourselves. 298 + """ 299 + 300 + def __init__(self): 301 + self.refs = 0 302 + self.rulesfile = None 303 + 304 + def __enter__(self): 305 + self.refs += 1 306 + if self.refs == 2 and self.rulesfile is None: 307 + self.create_udev_rule() 308 + self.reload_udev_rules() 309 + 310 + def __exit__(self, exc_type, exc_value, traceback): 311 + self.refs -= 1 312 + if self.refs == 0 and self.rulesfile: 313 + os.remove(self.rulesfile.name) 314 + self.reload_udev_rules() 315 + 316 + def reload_udev_rules(self): 317 + import subprocess 318 + 319 + subprocess.run("udevadm control --reload-rules".split()) 320 + subprocess.run("systemd-hwdb update".split()) 321 + 322 + def create_udev_rule(self): 323 + import tempfile 324 + 325 + os.makedirs("/run/udev/rules.d", exist_ok=True) 326 + with tempfile.NamedTemporaryFile( 327 + prefix="91-uhid-test-device-REMOVEME-", 328 + suffix=".rules", 329 + mode="w+", 330 + dir="/run/udev/rules.d", 331 + delete=False, 332 + ) as f: 333 + f.write( 334 + 'KERNELS=="*input*", ATTRS{name}=="*uhid test *", ENV{LIBINPUT_IGNORE_DEVICE}="1"\n' 335 + ) 336 + f.write( 337 + 'KERNELS=="*input*", ATTRS{name}=="*uhid test * System Multi Axis", ENV{ID_INPUT_TOUCHSCREEN}="", ENV{ID_INPUT_SYSTEM_MULTIAXIS}="1"\n' 338 + ) 339 + self.rulesfile = f 340 + 341 + @classmethod 342 + def instance(cls): 343 + if not cls._instance: 344 + cls._instance = HIDTestUdevRule() 345 + return cls._instance
+81
tools/testing/selftests/hid/tests/conftest.py
··· 1 + #!/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # -*- coding: utf-8 -*- 4 + # 5 + # Copyright (c) 2017 Benjamin Tissoires <benjamin.tissoires@gmail.com> 6 + # Copyright (c) 2017 Red Hat, Inc. 7 + 8 + import platform 9 + import pytest 10 + import re 11 + import resource 12 + import subprocess 13 + from .base import HIDTestUdevRule 14 + from pathlib import Path 15 + 16 + 17 + # See the comment in HIDTestUdevRule, this doesn't set up but it will clean 18 + # up once the last test exited. 19 + @pytest.fixture(autouse=True, scope="session") 20 + def udev_rules_session_setup(): 21 + with HIDTestUdevRule.instance(): 22 + yield 23 + 24 + 25 + @pytest.fixture(autouse=True, scope="session") 26 + def setup_rlimit(): 27 + resource.setrlimit(resource.RLIMIT_CORE, (0, 0)) 28 + 29 + 30 + @pytest.fixture(autouse=True, scope="session") 31 + def start_udevd(pytestconfig): 32 + if pytestconfig.getoption("udevd"): 33 + import subprocess 34 + 35 + with subprocess.Popen("/usr/lib/systemd/systemd-udevd") as proc: 36 + yield 37 + proc.kill() 38 + else: 39 + yield 40 + 41 + 42 + def pytest_configure(config): 43 + config.addinivalue_line( 44 + "markers", 45 + "skip_if_uhdev(condition, message): mark test to skip if the condition on the uhdev device is met", 46 + ) 47 + 48 + 49 + # Generate the list of modules and modaliases 50 + # for the tests that need to be parametrized with those 51 + def pytest_generate_tests(metafunc): 52 + if "usbVidPid" in metafunc.fixturenames: 53 + modules = ( 54 + Path("/lib/modules/") 55 + / platform.uname().release 56 + / "kernel" 57 + / "drivers" 58 + / "hid" 59 + ) 60 + 61 + modalias_re = re.compile(r"alias:\s+hid:b0003g.*v([0-9a-fA-F]+)p([0-9a-fA-F]+)") 62 + 63 + params = [] 64 + ids = [] 65 + for module in modules.glob("*.ko"): 66 + p = subprocess.run( 67 + ["modinfo", module], capture_output=True, check=True, encoding="utf-8" 68 + ) 69 + for line in p.stdout.split("\n"): 70 + m = modalias_re.match(line) 71 + if m is not None: 72 + vid, pid = m.groups() 73 + vid = int(vid, 16) 74 + pid = int(pid, 16) 75 + params.append([module.name.replace(".ko", ""), vid, pid]) 76 + ids.append(f"{module.name} {vid:04x}:{pid:04x}") 77 + metafunc.parametrize("usbVidPid", params, ids=ids) 78 + 79 + 80 + def pytest_addoption(parser): 81 + parser.addoption("--udevd", action="store_true", default=False)
+1360
tools/testing/selftests/hid/tests/descriptors_wacom.py
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + 3 + # fmt: off 4 + wacom_pth660_v145 = [ 5 + 0x05, 0x01, # . Usage Page (Desktop), 6 + 0x09, 0x02, # . Usage (Mouse), 7 + 0xA1, 0x01, # . Collection (Application), 8 + 0x85, 0x01, # . Report ID (1), 9 + 0x09, 0x01, # . Usage (Pointer), 10 + 0xA1, 0x00, # . Collection (Physical), 11 + 0x05, 0x09, # . Usage Page (Button), 12 + 0x19, 0x01, # . Usage Minimum (01h), 13 + 0x29, 0x03, # . Usage Maximum (03h), 14 + 0x15, 0x00, # . Logical Minimum (0), 15 + 0x25, 0x01, # . Logical Maximum (1), 16 + 0x75, 0x01, # . Report Size (1), 17 + 0x95, 0x03, # . Report Count (3), 18 + 0x81, 0x02, # . Input (Variable), 19 + 0x75, 0x01, # . Report Size (1), 20 + 0x95, 0x05, # . Report Count (5), 21 + 0x81, 0x03, # . Input (Constant, Variable), 22 + 0x05, 0x01, # . Usage Page (Desktop), 23 + 0x09, 0x30, # . Usage (X), 24 + 0x09, 0x31, # . Usage (Y), 25 + 0x15, 0x81, # . Logical Minimum (-127), 26 + 0x25, 0x7F, # . Logical Maximum (127), 27 + 0x75, 0x08, # . Report Size (8), 28 + 0x95, 0x02, # . Report Count (2), 29 + 0x81, 0x06, # . Input (Variable, Relative), 30 + 0xC0, # . End Collection, 31 + 0xC0, # . End Collection, 32 + 0x06, 0x0D, 0xFF, # . Usage Page (FF0Dh), 33 + 0x09, 0x01, # . Usage (01h), 34 + 0xA1, 0x01, # . Collection (Application), 35 + 0x85, 0x10, # . Report ID (16), 36 + 0x09, 0x20, # . Usage (20h), 37 + 0xA1, 0x00, # . Collection (Physical), 38 + 0x09, 0x42, # . Usage (42h), 39 + 0x09, 0x44, # . Usage (44h), 40 + 0x09, 0x5A, # . Usage (5Ah), 41 + 0x09, 0x45, # . Usage (45h), 42 + 0x09, 0x3C, # . Usage (3Ch), 43 + 0x09, 0x32, # . Usage (32h), 44 + 0x09, 0x36, # . Usage (36h), 45 + 0x15, 0x00, # . Logical Minimum (0), 46 + 0x25, 0x01, # . Logical Maximum (1), 47 + 0x75, 0x01, # . Report Size (1), 48 + 0x95, 0x07, # . Report Count (7), 49 + 0x81, 0x02, # . Input (Variable), 50 + 0x95, 0x01, # . Report Count (1), 51 + 0x81, 0x03, # . Input (Constant, Variable), 52 + 0x0A, 0x30, 0x01, # . Usage (0130h), 53 + 0x65, 0x11, # . Unit (Centimeter), 54 + 0x55, 0x0D, # . Unit Exponent (13), 55 + 0x35, 0x00, # . Physical Minimum (0), 56 + 0x47, 0x80, 0x57, 0x00, 0x00, # . Physical Maximum (22400), 57 + 0x15, 0x00, # . Logical Minimum (0), 58 + 0x27, 0x00, 0xAF, 0x00, 0x00, # . Logical Maximum (44800), 59 + 0x75, 0x18, # . Report Size (24), 60 + 0x95, 0x01, # . Report Count (1), 61 + 0x81, 0x02, # . Input (Variable), 62 + 0x0A, 0x31, 0x01, # . Usage (0131h), 63 + 0x47, 0xD0, 0x39, 0x00, 0x00, # . Physical Maximum (14800), 64 + 0x27, 0xA0, 0x73, 0x00, 0x00, # . Logical Maximum (29600), 65 + 0x81, 0x02, # . Input (Variable), 66 + 0x09, 0x30, # . Usage (30h), 67 + 0x55, 0x00, # . Unit Exponent (0), 68 + 0x65, 0x00, # . Unit, 69 + 0x15, 0x00, # . Logical Minimum (0), 70 + 0x26, 0xFF, 0x1F, # . Logical Maximum (8191), # !!! Errata: Missing Physical Max = 0 71 + 0x75, 0x10, # . Report Size (16), 72 + 0x81, 0x02, # . Input (Variable), 73 + 0x09, 0x3D, # . Usage (3Dh), 74 + 0x09, 0x3E, # . Usage (3Eh), 75 + 0x65, 0x14, # . Unit (Degrees), 76 + 0x55, 0x00, # . Unit Exponent (0), 77 + 0x35, 0xC0, # . Physical Minimum (-64), 78 + 0x45, 0x3F, # . Physical Maximum (63), 79 + 0x15, 0xC0, # . Logical Minimum (-64), 80 + 0x25, 0x3F, # . Logical Maximum (63), 81 + 0x75, 0x08, # . Report Size (8), 82 + 0x95, 0x02, # . Report Count (2), 83 + 0x81, 0x02, # . Input (Variable), 84 + 0x09, 0x41, # . Usage (41h), 85 + 0x65, 0x14, # . Unit (Degrees), 86 + 0x55, 0x00, # . Unit Exponent (0), 87 + 0x36, 0x4C, 0xFF, # . Physical Minimum (-180), 88 + 0x46, 0xB3, 0x00, # . Physical Maximum (179), 89 + 0x16, 0x7C, 0xFC, # . Logical Minimum (-900), 90 + 0x26, 0x83, 0x03, # . Logical Maximum (899), 91 + 0x75, 0x10, # . Report Size (16), 92 + 0x95, 0x01, # . Report Count (1), 93 + 0x81, 0x0A, # . Input (Variable, Wrap), 94 + 0x0A, 0x03, 0x0D, # . Usage (0D03h), 95 + 0x65, 0x00, # . Unit, 96 + 0x55, 0x00, # . Unit Exponent (0), 97 + 0x15, 0x00, # . Logical Minimum (0), 98 + 0x26, 0xFF, 0x07, # . Logical Maximum (2047), # !!! Errata: Missing Physical Min/Max = 0 99 + 0x75, 0x10, # . Report Size (16), 100 + 0x95, 0x01, # . Report Count (1), 101 + 0x81, 0x02, # . Input (Variable), 102 + 0x0A, 0x32, 0x01, # . Usage (0132h), 103 + 0x15, 0x00, # . Logical Minimum (0), 104 + 0x25, 0x3F, # . Logical Maximum (63), 105 + 0x75, 0x08, # . Report Size (8), 106 + 0x95, 0x01, # . Report Count (1), 107 + 0x81, 0x02, # . Input (Variable), 108 + 0x09, 0x5B, # . Usage (5Bh), 109 + 0x09, 0x5C, # . Usage (5Ch), 110 + 0x17, 0x00, 0x00, 0x00, 0x80, # . Logical Minimum (-2147483648), 111 + 0x27, 0xFF, 0xFF, 0xFF, 0x7F, # . Logical Maximum (2147483647), 112 + 0x75, 0x20, # . Report Size (32), 113 + 0x95, 0x02, # . Report Count (2), 114 + 0x81, 0x02, # . Input (Variable), 115 + 0x09, 0x77, # . Usage (77h), 116 + 0x15, 0x00, # . Logical Minimum (0), 117 + 0x26, 0xFF, 0x0F, # . Logical Maximum (4095), 118 + 0x75, 0x10, # . Report Size (16), 119 + 0x95, 0x01, # . Report Count (1), 120 + 0x81, 0x02, # . Input (Variable), 121 + 0xC0, # . End Collection, 122 + 0x85, 0x11, # . Report ID (17), 123 + 0x09, 0x39, # . Usage (39h), 124 + 0xA1, 0x00, # . Collection (Physical), 125 + 0x1A, 0x10, 0x09, # . Usage Minimum (0910h), 126 + 0x2A, 0x17, 0x09, # . Usage Maximum (0917h), 127 + 0x15, 0x00, # . Logical Minimum (0), 128 + 0x25, 0x01, # . Logical Maximum (1), 129 + 0x75, 0x01, # . Report Size (1), 130 + 0x95, 0x08, # . Report Count (8), 131 + 0x81, 0x02, # . Input (Variable), 132 + 0x1A, 0x40, 0x09, # . Usage Minimum (0940h), 133 + 0x2A, 0x47, 0x09, # . Usage Maximum (0947h), 134 + 0x81, 0x02, # . Input (Variable), 135 + 0x0A, 0x95, 0x09, # . Usage (0995h), 136 + 0x95, 0x01, # . Report Count (1), 137 + 0x81, 0x02, # . Input (Variable), 138 + 0x95, 0x07, # . Report Count (7), 139 + 0x81, 0x03, # . Input (Constant, Variable), 140 + 0x0A, 0x38, 0x01, # . Usage (0138h), 141 + 0x65, 0x14, # . Unit (Degrees), 142 + 0x55, 0x00, # . Unit Exponent (0), 143 + 0x35, 0x00, # . Physical Minimum (0), 144 + 0x46, 0x67, 0x01, # . Physical Maximum (359), 145 + 0x15, 0x00, # . Logical Minimum (0), 146 + 0x25, 0x47, # . Logical Maximum (71), 147 + 0x75, 0x07, # . Report Size (7), 148 + 0x95, 0x01, # . Report Count (1), 149 + 0x81, 0x0A, # . Input (Variable, Wrap), 150 + 0x0A, 0x39, 0x01, # . Usage (0139h), 151 + 0x65, 0x00, # . Unit, 152 + 0x55, 0x00, # . Unit Exponent (0), 153 + 0x25, 0x01, # . Logical Maximum (1), # !!! Errata: Missing Physical Max = 0 154 + 0x75, 0x01, # . Report Size (1), 155 + 0x95, 0x01, # . Report Count (1), 156 + 0x81, 0x02, # . Input (Variable), 157 + 0x75, 0x08, # . Report Size (8), 158 + 0x95, 0x04, # . Report Count (4), 159 + 0x81, 0x03, # . Input (Constant, Variable), 160 + 0xC0, # . End Collection, 161 + 0x85, 0x13, # . Report ID (19), 162 + 0x0A, 0x13, 0x10, # . Usage (1013h), 163 + 0xA1, 0x00, # . Collection (Physical), 164 + 0x0A, 0x3B, 0x04, # . Usage (043Bh), 165 + 0x15, 0x00, # . Logical Minimum (0), 166 + 0x25, 0x64, # . Logical Maximum (100), 167 + 0x75, 0x07, # . Report Size (7), 168 + 0x95, 0x01, # . Report Count (1), 169 + 0x81, 0x02, # . Input (Variable), 170 + 0x0A, 0x04, 0x04, # . Usage (0404h), 171 + 0x25, 0x01, # . Logical Maximum (1), 172 + 0x75, 0x01, # . Report Size (1), 173 + 0x81, 0x02, # . Input (Variable), 174 + 0x0A, 0x52, 0x04, # . Usage (0452h), 175 + 0x15, 0x00, # . Logical Minimum (0), 176 + 0x25, 0x01, # . Logical Maximum (1), 177 + 0x75, 0x01, # . Report Size (1), 178 + 0x95, 0x01, # . Report Count (1), 179 + 0x81, 0x02, # . Input (Variable), 180 + 0x95, 0x06, # . Report Count (6), 181 + 0x81, 0x03, # . Input (Constant, Variable), 182 + 0x0A, 0x54, 0x04, # . Usage (0454h), 183 + 0x95, 0x01, # . Report Count (1), 184 + 0x81, 0x02, # . Input (Variable), 185 + 0x75, 0x08, # . Report Size (8), 186 + 0x95, 0x06, # . Report Count (6), 187 + 0x81, 0x03, # . Input (Constant, Variable), 188 + 0xC0, # . End Collection, 189 + 0x09, 0x0E, # . Usage (0Eh), 190 + 0xA1, 0x02, # . Collection (Logical), 191 + 0x15, 0x00, # . Logical Minimum (0), 192 + 0x85, 0x02, # . Report ID (2), 193 + 0x09, 0x01, # . Usage (01h), 194 + 0x75, 0x08, # . Report Size (8), 195 + 0x25, 0x01, # . Logical Maximum (1), 196 + 0x95, 0x01, # . Report Count (1), 197 + 0xB1, 0x02, # . Feature (Variable), 198 + 0x85, 0x03, # . Report ID (3), 199 + 0x0A, 0x03, 0x10, # . Usage (1003h), 200 + 0x26, 0xFF, 0x00, # . Logical Maximum (255), 201 + 0x95, 0x01, # . Report Count (1), 202 + 0xB1, 0x02, # . Feature (Variable), 203 + 0x85, 0x04, # . Report ID (4), 204 + 0x0A, 0x04, 0x10, # . Usage (1004h), 205 + 0x25, 0x01, # . Logical Maximum (1), 206 + 0x95, 0x01, # . Report Count (1), 207 + 0xB1, 0x02, # . Feature (Variable), 208 + 0x85, 0x07, # . Report ID (7), 209 + 0x0A, 0x09, 0x10, # . Usage (1009h), 210 + 0x25, 0x02, # . Logical Maximum (2), 211 + 0x95, 0x01, # . Report Count (1), 212 + 0xB1, 0x02, # . Feature (Variable), 213 + 0x95, 0x01, # . Report Count (1), 214 + 0xB1, 0x03, # . Feature (Constant, Variable), 215 + 0x0A, 0x07, 0x10, # . Usage (1007h), 216 + 0x09, 0x00, # . Usage (00h), 217 + 0x0A, 0x08, 0x10, # . Usage (1008h), 218 + 0x09, 0x00, # . Usage (00h), 219 + 0x09, 0x00, # . Usage (00h), 220 + 0x09, 0x00, # . Usage (00h), 221 + 0x27, 0xFF, 0xFF, 0x00, 0x00, # . Logical Maximum (65535), 222 + 0x75, 0x10, # . Report Size (16), 223 + 0x95, 0x06, # . Report Count (6), 224 + 0xB1, 0x02, # . Feature (Variable), 225 + 0x75, 0x08, # . Report Size (8), 226 + 0x95, 0x01, # . Report Count (1), 227 + 0xB1, 0x03, # . Feature (Constant, Variable), 228 + 0x85, 0x0C, # . Report ID (12), 229 + 0x0A, 0x30, 0x0D, # . Usage (0D30h), 230 + 0x0A, 0x31, 0x0D, # . Usage (0D31h), 231 + 0x0A, 0x32, 0x0D, # . Usage (0D32h), 232 + 0x0A, 0x33, 0x0D, # . Usage (0D33h), # !!! Errata: Missing Non-zero Physical Max 233 + 0x65, 0x11, # . Unit (Centimeter), 234 + 0x55, 0x0D, # . Unit Exponent (13), 235 + 0x75, 0x10, # . Report Size (16), 236 + 0x95, 0x04, # . Report Count (4), 237 + 0xB1, 0x03, # . Feature (Constant, Variable), 238 + 0x85, 0x0D, # . Report ID (13), 239 + 0x65, 0x00, # . Unit, 240 + 0x55, 0x00, # . Unit Exponent (0), 241 + 0x0A, 0x0D, 0x10, # . Usage (100Dh), 242 + 0x15, 0x00, # . Logical Minimum (0), 243 + 0x25, 0x01, # . Logical Maximum (1), 244 + 0x75, 0x08, # . Report Size (8), 245 + 0x95, 0x01, # . Report Count (1), 246 + 0xB1, 0x02, # . Feature (Variable), 247 + 0x85, 0x14, # . Report ID (20), 248 + 0x0A, 0x14, 0x10, # . Usage (1014h), 249 + 0x26, 0xFF, 0x00, # . Logical Maximum (255), 250 + 0x95, 0x0D, # . Report Count (13), 251 + 0xB1, 0x02, # . Feature (Variable), 252 + 0x85, 0x31, # . Report ID (49), 253 + 0x0A, 0x31, 0x10, # . Usage (1031h), 254 + 0x25, 0x64, # . Logical Maximum (100), 255 + 0x95, 0x05, # . Report Count (5), 256 + 0xB1, 0x02, # . Feature (Variable), 257 + 0x85, 0x32, # . Report ID (50), 258 + 0x0A, 0x31, 0x10, # . Usage (1031h), 259 + 0x25, 0x64, # . Logical Maximum (100), 260 + 0x95, 0x01, # . Report Count (1), 261 + 0xB1, 0x02, # . Feature (Variable), 262 + 0x0A, 0x32, 0x10, # . Usage (1032h), 263 + 0x25, 0x03, # . Logical Maximum (3), 264 + 0xB1, 0x02, # . Feature (Variable), 265 + 0x85, 0x34, # . Report ID (52), 266 + 0x0A, 0x34, 0x10, # . Usage (1034h), 267 + 0x25, 0x01, # . Logical Maximum (1), 268 + 0x95, 0x04, # . Report Count (4), 269 + 0xB1, 0x02, # . Feature (Variable), 270 + 0x85, 0x35, # . Report ID (53), 271 + 0x0A, 0x35, 0x10, # . Usage (1035h), 272 + 0x26, 0xFF, 0x00, # . Logical Maximum (255), 273 + 0x95, 0x0A, # . Report Count (10), 274 + 0xB1, 0x02, # . Feature (Variable), 275 + 0x85, 0x36, # . Report ID (54), 276 + 0x0A, 0x35, 0x10, # . Usage (1035h), 277 + 0x26, 0xFF, 0x00, # . Logical Maximum (255), 278 + 0x96, 0x01, 0x01, # . Report Count (257), 279 + 0xB1, 0x02, # . Feature (Variable), 280 + 0x85, 0xCC, # . Report ID (204), 281 + 0x0A, 0xCC, 0x10, # . Usage (10CCh), 282 + 0x26, 0xFF, 0x00, # . Logical Maximum (255), 283 + 0x95, 0x02, # . Report Count (2), 284 + 0xB1, 0x02, # . Feature (Variable), 285 + 0xC0, # . End Collection, 286 + 0x0A, 0xAC, 0x10, # . Usage (10ACh), 287 + 0xA1, 0x02, # . Collection (Logical), 288 + 0x15, 0x00, # . Logical Minimum (0), 289 + 0x26, 0xFF, 0x00, # . Logical Maximum (255), 290 + 0x75, 0x08, # . Report Size (8), 291 + 0x85, 0xAC, # . Report ID (172), 292 + 0x09, 0x00, # . Usage (00h), 293 + 0x95, 0xBF, # . Report Count (191), 294 + 0x81, 0x02, # . Input (Variable), 295 + 0x85, 0x33, # . Report ID (51), 296 + 0x09, 0x00, # . Usage (00h), 297 + 0x95, 0x12, # . Report Count (18), 298 + 0xB1, 0x02, # . Feature (Variable), 299 + 0x85, 0x64, # . Report ID (100), 300 + 0x09, 0x00, # . Usage (00h), 301 + 0x95, 0x0C, # . Report Count (12), 302 + 0xB1, 0x02, # . Feature (Variable), 303 + 0x85, 0x15, # . Report ID (21), 304 + 0x09, 0x00, # . Usage (00h), 305 + 0x95, 0x0E, # . Report Count (14), 306 + 0xB1, 0x02, # . Feature (Variable), 307 + 0x85, 0x12, # . Report ID (18), 308 + 0x09, 0x00, # . Usage (00h), 309 + 0x95, 0x04, # . Report Count (4), 310 + 0xB1, 0x02, # . Feature (Variable), 311 + 0x85, 0x16, # . Report ID (22), 312 + 0x09, 0x00, # . Usage (00h), 313 + 0x95, 0x0E, # . Report Count (14), 314 + 0xB1, 0x02, # . Feature (Variable), 315 + 0x85, 0x40, # . Report ID (64), 316 + 0x09, 0x00, # . Usage (00h), 317 + 0x95, 0x01, # . Report Count (1), 318 + 0xB1, 0x02, # . Feature (Variable), 319 + 0x85, 0x41, # . Report ID (65), 320 + 0x09, 0x00, # . Usage (00h), 321 + 0x95, 0x01, # . Report Count (1), 322 + 0xB1, 0x02, # . Feature (Variable), 323 + 0x85, 0x42, # . Report ID (66), 324 + 0x09, 0x00, # . Usage (00h), 325 + 0x95, 0x04, # . Report Count (4), 326 + 0xB1, 0x02, # . Feature (Variable), 327 + 0x85, 0x43, # . Report ID (67), 328 + 0x09, 0x00, # . Usage (00h), 329 + 0x95, 0x0D, # . Report Count (13), 330 + 0xB1, 0x02, # . Feature (Variable), 331 + 0x85, 0x44, # . Report ID (68), 332 + 0x09, 0x00, # . Usage (00h), 333 + 0x95, 0x3F, # . Report Count (63), 334 + 0xB1, 0x02, # . Feature (Variable), 335 + 0x85, 0x45, # . Report ID (69), 336 + 0x09, 0x00, # . Usage (00h), 337 + 0x95, 0x20, # . Report Count (32), 338 + 0xB1, 0x02, # . Feature (Variable), 339 + 0x85, 0x60, # . Report ID (96), 340 + 0x09, 0x00, # . Usage (00h), 341 + 0x95, 0x3F, # . Report Count (63), 342 + 0xB1, 0x02, # . Feature (Variable), 343 + 0x85, 0x61, # . Report ID (97), 344 + 0x09, 0x00, # . Usage (00h), 345 + 0x95, 0x3E, # . Report Count (62), 346 + 0xB1, 0x02, # . Feature (Variable), 347 + 0x85, 0x62, # . Report ID (98), 348 + 0x09, 0x00, # . Usage (00h), 349 + 0x95, 0x3E, # . Report Count (62), 350 + 0xB1, 0x02, # . Feature (Variable), 351 + 0xC0, # . End Collection, 352 + 0x85, 0xD0, # . Report ID (208), 353 + 0x09, 0x01, # . Usage (01h), 354 + 0x96, 0x08, 0x00, # . Report Count (8), 355 + 0xB1, 0x02, # . Feature (Variable), 356 + 0x85, 0xD1, # . Report ID (209), 357 + 0x09, 0x01, # . Usage (01h), 358 + 0x96, 0x04, 0x01, # . Report Count (260), 359 + 0xB1, 0x02, # . Feature (Variable), 360 + 0x85, 0xD2, # . Report ID (210), 361 + 0x09, 0x01, # . Usage (01h), 362 + 0x96, 0x04, 0x01, # . Report Count (260), 363 + 0xB1, 0x02, # . Feature (Variable), 364 + 0x85, 0xD3, # . Report ID (211), 365 + 0x09, 0x01, # . Usage (01h), 366 + 0x96, 0x04, 0x00, # . Report Count (4), 367 + 0xB1, 0x02, # . Feature (Variable), 368 + 0x85, 0xD4, # . Report ID (212), 369 + 0x09, 0x01, # . Usage (01h), 370 + 0x96, 0x04, 0x00, # . Report Count (4), 371 + 0xB1, 0x02, # . Feature (Variable), 372 + 0x85, 0xD5, # . Report ID (213), 373 + 0x09, 0x01, # . Usage (01h), 374 + 0x96, 0x04, 0x00, # . Report Count (4), 375 + 0xB1, 0x02, # . Feature (Variable), 376 + 0x85, 0xD6, # . Report ID (214), 377 + 0x09, 0x01, # . Usage (01h), 378 + 0x96, 0x04, 0x00, # . Report Count (4), 379 + 0xB1, 0x02, # . Feature (Variable), 380 + 0x85, 0xD7, # . Report ID (215), 381 + 0x09, 0x01, # . Usage (01h), 382 + 0x96, 0x08, 0x00, # . Report Count (8), 383 + 0xB1, 0x02, # . Feature (Variable), 384 + 0x85, 0xD8, # . Report ID (216), 385 + 0x09, 0x01, # . Usage (01h), 386 + 0x96, 0x0C, 0x00, # . Report Count (12), 387 + 0xB1, 0x02, # . Feature (Variable), 388 + 0x85, 0xD9, # . Report ID (217), 389 + 0x09, 0x01, # . Usage (01h), 390 + 0x96, 0x00, 0x0A, # . Report Count (2560), 391 + 0xB1, 0x02, # . Feature (Variable), 392 + 0x85, 0xDA, # . Report ID (218), 393 + 0x09, 0x01, # . Usage (01h), 394 + 0x96, 0x04, 0x04, # . Report Count (1028), 395 + 0xB1, 0x02, # . Feature (Variable), 396 + 0x85, 0xDB, # . Report ID (219), 397 + 0x09, 0x01, # . Usage (01h), 398 + 0x96, 0x06, 0x00, # . Report Count (6), 399 + 0xB1, 0x02, # . Feature (Variable), 400 + 0x85, 0xDC, # . Report ID (220), 401 + 0x09, 0x01, # . Usage (01h), 402 + 0x96, 0x02, 0x00, # . Report Count (2), 403 + 0xB1, 0x02, # . Feature (Variable), 404 + 0x85, 0xDD, # . Report ID (221), 405 + 0x09, 0x01, # . Usage (01h), 406 + 0x96, 0x04, 0x00, # . Report Count (4), 407 + 0xB1, 0x02, # . Feature (Variable), 408 + 0x85, 0xDE, # . Report ID (222), 409 + 0x09, 0x01, # . Usage (01h), 410 + 0x96, 0x04, 0x00, # . Report Count (4), 411 + 0xB1, 0x02, # . Feature (Variable), 412 + 0x85, 0xDF, # . Report ID (223), 413 + 0x09, 0x01, # . Usage (01h), 414 + 0x96, 0x22, 0x00, # . Report Count (34), 415 + 0xB1, 0x02, # . Feature (Variable), 416 + 0x85, 0xE0, # . Report ID (224), 417 + 0x09, 0x01, # . Usage (01h), 418 + 0x96, 0x01, 0x00, # . Report Count (1), 419 + 0xB1, 0x02, # . Feature (Variable), 420 + 0x85, 0xE1, # . Report ID (225), 421 + 0x09, 0x01, # . Usage (01h), 422 + 0x96, 0x02, 0x00, # . Report Count (2), 423 + 0xB1, 0x02, # . Feature (Variable), 424 + 0x85, 0xE2, # . Report ID (226), 425 + 0x09, 0x01, # . Usage (01h), 426 + 0x96, 0x02, 0x00, # . Report Count (2), 427 + 0xB1, 0x02, # . Feature (Variable), 428 + 0x85, 0xE3, # . Report ID (227), 429 + 0x09, 0x01, # . Usage (01h), 430 + 0x96, 0x02, 0x00, # . Report Count (2), 431 + 0xB1, 0x02, # . Feature (Variable), 432 + 0x85, 0xE4, # . Report ID (228), 433 + 0x09, 0x01, # . Usage (01h), 434 + 0x96, 0xFF, 0x01, # . Report Count (511), 435 + 0xB1, 0x02, # . Feature (Variable), 436 + 0xC0 # . End Collection 437 + ] 438 + # fmt: on 439 + 440 + # Report ID (20), Usage (1014h), Report Count (13) -> 15 441 + wacom_pth660_v150 = wacom_pth660_v145.copy() 442 + wacom_pth660_v150[0x2CB] = 0x0F 443 + 444 + # fmt: off 445 + wacom_pth860_v145 = [ 446 + 0x05, 0x01, # . Usage Page (Desktop), 447 + 0x09, 0x02, # . Usage (Mouse), 448 + 0xA1, 0x01, # . Collection (Application), 449 + 0x85, 0x01, # . Report ID (1), 450 + 0x09, 0x01, # . Usage (Pointer), 451 + 0xA1, 0x00, # . Collection (Physical), 452 + 0x05, 0x09, # . Usage Page (Button), 453 + 0x19, 0x01, # . Usage Minimum (01h), 454 + 0x29, 0x03, # . Usage Maximum (03h), 455 + 0x15, 0x00, # . Logical Minimum (0), 456 + 0x25, 0x01, # . Logical Maximum (1), 457 + 0x75, 0x01, # . Report Size (1), 458 + 0x95, 0x03, # . Report Count (3), 459 + 0x81, 0x02, # . Input (Variable), 460 + 0x95, 0x05, # . Report Count (5), 461 + 0x81, 0x03, # . Input (Constant, Variable), 462 + 0x05, 0x01, # . Usage Page (Desktop), 463 + 0x09, 0x30, # . Usage (X), 464 + 0x09, 0x31, # . Usage (Y), 465 + 0x15, 0x80, # . Logical Minimum (-128), 466 + 0x25, 0x7F, # . Logical Maximum (127), 467 + 0x75, 0x08, # . Report Size (8), 468 + 0x95, 0x02, # . Report Count (2), 469 + 0x81, 0x06, # . Input (Variable, Relative), 470 + 0xC0, # . End Collection, 471 + 0xC0, # . End Collection, 472 + 0x06, 0x0D, 0xFF, # . Usage Page (FF0Dh), 473 + 0x09, 0x01, # . Usage (01h), 474 + 0xA1, 0x01, # . Collection (Application), 475 + 0x85, 0x10, # . Report ID (16), 476 + 0x09, 0x20, # . Usage (20h), 477 + 0xA1, 0x00, # . Collection (Physical), 478 + 0x09, 0x42, # . Usage (42h), 479 + 0x09, 0x44, # . Usage (44h), 480 + 0x09, 0x5A, # . Usage (5Ah), 481 + 0x09, 0x45, # . Usage (45h), 482 + 0x09, 0x3C, # . Usage (3Ch), 483 + 0x09, 0x32, # . Usage (32h), 484 + 0x09, 0x36, # . Usage (36h), 485 + 0x15, 0x00, # . Logical Minimum (0), 486 + 0x25, 0x01, # . Logical Maximum (1), 487 + 0x75, 0x01, # . Report Size (1), 488 + 0x95, 0x07, # . Report Count (7), 489 + 0x81, 0x02, # . Input (Variable), 490 + 0x95, 0x01, # . Report Count (1), 491 + 0x81, 0x03, # . Input (Constant, Variable), 492 + 0x0A, 0x30, 0x01, # . Usage (0130h), 493 + 0x65, 0x11, # . Unit (Centimeter), 494 + 0x55, 0x0D, # . Unit Exponent (13), 495 + 0x35, 0x00, # . Physical Minimum (0), 496 + 0x47, 0x7C, 0x79, 0x00, 0x00, # . Physical Maximum (31100), 497 + 0x15, 0x00, # . Logical Minimum (0), 498 + 0x27, 0xF8, 0xF2, 0x00, 0x00, # . Logical Maximum (62200), 499 + 0x75, 0x18, # . Report Size (24), 500 + 0x95, 0x01, # . Report Count (1), 501 + 0x81, 0x02, # . Input (Variable), 502 + 0x0A, 0x31, 0x01, # . Usage (0131h), 503 + 0x47, 0x60, 0x54, 0x00, 0x00, # . Physical Maximum (21600), 504 + 0x27, 0xC0, 0xA8, 0x00, 0x00, # . Logical Maximum (43200), 505 + 0x81, 0x02, # . Input (Variable), 506 + 0x09, 0x30, # . Usage (30h), # !!! Errata: Missing Physical Max = 0 507 + 0x55, 0x00, # . Unit Exponent (0), 508 + 0x65, 0x00, # . Unit, 509 + 0x15, 0x00, # . Logical Minimum (0), 510 + 0x26, 0xFF, 0x1F, # . Logical Maximum (8191), 511 + 0x75, 0x10, # . Report Size (16), 512 + 0x81, 0x02, # . Input (Variable), 513 + 0x09, 0x3D, # . Usage (3Dh), 514 + 0x09, 0x3E, # . Usage (3Eh), 515 + 0x65, 0x14, # . Unit (Degrees), 516 + 0x55, 0x00, # . Unit Exponent (0), 517 + 0x35, 0xC0, # . Physical Minimum (-64), 518 + 0x45, 0x3F, # . Physical Maximum (63), 519 + 0x15, 0xC0, # . Logical Minimum (-64), 520 + 0x25, 0x3F, # . Logical Maximum (63), 521 + 0x75, 0x08, # . Report Size (8), 522 + 0x95, 0x02, # . Report Count (2), 523 + 0x81, 0x02, # . Input (Variable), 524 + 0x09, 0x41, # . Usage (41h), 525 + 0x65, 0x14, # . Unit (Degrees), 526 + 0x55, 0x00, # . Unit Exponent (0), 527 + 0x36, 0x4C, 0xFF, # . Physical Minimum (-180), 528 + 0x46, 0xB3, 0x00, # . Physical Maximum (179), 529 + 0x16, 0x7C, 0xFC, # . Logical Minimum (-900), 530 + 0x26, 0x83, 0x03, # . Logical Maximum (899), 531 + 0x75, 0x10, # . Report Size (16), 532 + 0x95, 0x01, # . Report Count (1), 533 + 0x81, 0x0A, # . Input (Variable, Wrap), 534 + 0x0A, 0x03, 0x0D, # . Usage (0D03h), 535 + 0x65, 0x00, # . Unit, 536 + 0x55, 0x00, # . Unit Exponent (0), 537 + 0x15, 0x00, # . Logical Minimum (0), 538 + 0x26, 0xFF, 0x07, # . Logical Maximum (2047), # !!! Errata: Missing Physical Min/Max = 0 539 + 0x75, 0x10, # . Report Size (16), 540 + 0x95, 0x01, # . Report Count (1), 541 + 0x81, 0x02, # . Input (Variable), 542 + 0x0A, 0x32, 0x01, # . Usage (0132h), 543 + 0x15, 0x00, # . Logical Minimum (0), 544 + 0x25, 0x3F, # . Logical Maximum (63), 545 + 0x75, 0x08, # . Report Size (8), 546 + 0x95, 0x01, # . Report Count (1), 547 + 0x81, 0x02, # . Input (Variable), 548 + 0x09, 0x5B, # . Usage (5Bh), 549 + 0x09, 0x5C, # . Usage (5Ch), 550 + 0x17, 0x00, 0x00, 0x00, 0x80, # . Logical Minimum (-2147483648), 551 + 0x27, 0xFF, 0xFF, 0xFF, 0x7F, # . Logical Maximum (2147483647), 552 + 0x75, 0x20, # . Report Size (32), 553 + 0x95, 0x02, # . Report Count (2), 554 + 0x81, 0x02, # . Input (Variable), 555 + 0x09, 0x77, # . Usage (77h), 556 + 0x16, 0x00, 0x00, # . Logical Minimum (0), 557 + 0x26, 0xFF, 0x0F, # . Logical Maximum (4095), 558 + 0x75, 0x10, # . Report Size (16), 559 + 0x95, 0x01, # . Report Count (1), 560 + 0x81, 0x02, # . Input (Variable), 561 + 0xC0, # . End Collection, 562 + 0x85, 0x11, # . Report ID (17), 563 + 0x09, 0x39, # . Usage (39h), 564 + 0xA1, 0x00, # . Collection (Physical), 565 + 0x1A, 0x10, 0x09, # . Usage Minimum (0910h), 566 + 0x2A, 0x17, 0x09, # . Usage Maximum (0917h), 567 + 0x15, 0x00, # . Logical Minimum (0), 568 + 0x25, 0x01, # . Logical Maximum (1), 569 + 0x75, 0x01, # . Report Size (1), 570 + 0x95, 0x08, # . Report Count (8), 571 + 0x81, 0x02, # . Input (Variable), 572 + 0x1A, 0x40, 0x09, # . Usage Minimum (0940h), 573 + 0x2A, 0x47, 0x09, # . Usage Maximum (0947h), 574 + 0x81, 0x02, # . Input (Variable), 575 + 0x0A, 0x95, 0x09, # . Usage (0995h), 576 + 0x95, 0x01, # . Report Count (1), 577 + 0x81, 0x02, # . Input (Variable), 578 + 0x95, 0x07, # . Report Count (7), 579 + 0x81, 0x03, # . Input (Constant, Variable), 580 + 0x0A, 0x38, 0x01, # . Usage (0138h), 581 + 0x65, 0x14, # . Unit (Degrees), 582 + 0x55, 0x00, # . Unit Exponent (0), 583 + 0x35, 0x00, # . Physical Minimum (0), 584 + 0x46, 0x67, 0x01, # . Physical Maximum (359), 585 + 0x15, 0x00, # . Logical Minimum (0), 586 + 0x25, 0x47, # . Logical Maximum (71), 587 + 0x75, 0x07, # . Report Size (7), 588 + 0x95, 0x01, # . Report Count (1), 589 + 0x81, 0x0A, # . Input (Variable, Wrap), 590 + 0x0A, 0x39, 0x01, # . Usage (0139h), 591 + 0x65, 0x00, # . Unit, 592 + 0x55, 0x00, # . Unit Exponent (0), 593 + 0x25, 0x01, # . Logical Maximum (1), # !!! Errata: Missing Physical Max = 0 594 + 0x75, 0x01, # . Report Size (1), 595 + 0x95, 0x01, # . Report Count (1), 596 + 0x81, 0x02, # . Input (Variable), 597 + 0x75, 0x08, # . Report Size (8), 598 + 0x95, 0x04, # . Report Count (4), 599 + 0x81, 0x03, # . Input (Constant, Variable), 600 + 0xC0, # . End Collection, 601 + 0x85, 0x13, # . Report ID (19), 602 + 0x0A, 0x13, 0x10, # . Usage (1013h), 603 + 0xA1, 0x00, # . Collection (Physical), 604 + 0x0A, 0x3B, 0x04, # . Usage (043Bh), 605 + 0x15, 0x00, # . Logical Minimum (0), 606 + 0x25, 0x64, # . Logical Maximum (100), 607 + 0x75, 0x07, # . Report Size (7), 608 + 0x95, 0x01, # . Report Count (1), 609 + 0x81, 0x02, # . Input (Variable), 610 + 0x0A, 0x04, 0x04, # . Usage (0404h), 611 + 0x25, 0x01, # . Logical Maximum (1), 612 + 0x75, 0x01, # . Report Size (1), 613 + 0x81, 0x02, # . Input (Variable), 614 + 0x0A, 0x52, 0x04, # . Usage (0452h), 615 + 0x15, 0x00, # . Logical Minimum (0), 616 + 0x25, 0x01, # . Logical Maximum (1), 617 + 0x75, 0x01, # . Report Size (1), 618 + 0x95, 0x01, # . Report Count (1), 619 + 0x81, 0x02, # . Input (Variable), 620 + 0x95, 0x06, # . Report Count (6), 621 + 0x81, 0x03, # . Input (Constant, Variable), 622 + 0x0A, 0x54, 0x04, # . Usage (0454h), 623 + 0x95, 0x01, # . Report Count (1), 624 + 0x81, 0x02, # . Input (Variable), 625 + 0x75, 0x08, # . Report Size (8), 626 + 0x95, 0x06, # . Report Count (6), 627 + 0x81, 0x03, # . Input (Constant, Variable), 628 + 0xC0, # . End Collection, 629 + 0x09, 0x0E, # . Usage (0Eh), 630 + 0xA1, 0x02, # . Collection (Logical), 631 + 0x15, 0x00, # . Logical Minimum (0), 632 + 0x85, 0x02, # . Report ID (2), 633 + 0x09, 0x01, # . Usage (01h), 634 + 0x75, 0x08, # . Report Size (8), 635 + 0x25, 0x01, # . Logical Maximum (1), 636 + 0x95, 0x01, # . Report Count (1), 637 + 0xB1, 0x02, # . Feature (Variable), 638 + 0x85, 0x03, # . Report ID (3), 639 + 0x0A, 0x03, 0x10, # . Usage (1003h), 640 + 0x26, 0xFF, 0x00, # . Logical Maximum (255), 641 + 0x95, 0x01, # . Report Count (1), 642 + 0xB1, 0x02, # . Feature (Variable), 643 + 0x85, 0x04, # . Report ID (4), 644 + 0x0A, 0x04, 0x10, # . Usage (1004h), 645 + 0x25, 0x01, # . Logical Maximum (1), 646 + 0x95, 0x01, # . Report Count (1), 647 + 0xB1, 0x02, # . Feature (Variable), 648 + 0x85, 0x07, # . Report ID (7), 649 + 0x0A, 0x09, 0x10, # . Usage (1009h), 650 + 0x25, 0x02, # . Logical Maximum (2), 651 + 0x95, 0x01, # . Report Count (1), 652 + 0xB1, 0x02, # . Feature (Variable), 653 + 0x95, 0x01, # . Report Count (1), 654 + 0xB1, 0x03, # . Feature (Constant, Variable), 655 + 0x0A, 0x07, 0x10, # . Usage (1007h), 656 + 0x09, 0x00, # . Usage (00h), 657 + 0x0A, 0x08, 0x10, # . Usage (1008h), 658 + 0x09, 0x00, # . Usage (00h), 659 + 0x09, 0x00, # . Usage (00h), 660 + 0x09, 0x00, # . Usage (00h), 661 + 0x27, 0xFF, 0xFF, 0x00, 0x00, # . Logical Maximum (65535), 662 + 0x75, 0x10, # . Report Size (16), 663 + 0x95, 0x06, # . Report Count (6), 664 + 0xB1, 0x02, # . Feature (Variable), 665 + 0x75, 0x08, # . Report Size (8), 666 + 0x95, 0x01, # . Report Count (1), 667 + 0xB1, 0x03, # . Feature (Constant, Variable), 668 + 0x85, 0x0C, # . Report ID (12), 669 + 0x0A, 0x30, 0x0D, # . Usage (0D30h), 670 + 0x0A, 0x31, 0x0D, # . Usage (0D31h), 671 + 0x0A, 0x32, 0x0D, # . Usage (0D32h), 672 + 0x0A, 0x33, 0x0D, # . Usage (0D33h), # !!! Errata: Missing Non-zero Physical Max 673 + 0x65, 0x11, # . Unit (Centimeter), 674 + 0x55, 0x0D, # . Unit Exponent (13), 675 + 0x75, 0x10, # . Report Size (16), 676 + 0x95, 0x04, # . Report Count (4), 677 + 0xB1, 0x03, # . Feature (Constant, Variable), 678 + 0x85, 0x0D, # . Report ID (13), 679 + 0x65, 0x00, # . Unit, 680 + 0x55, 0x00, # . Unit Exponent (0), 681 + 0x0A, 0x0D, 0x10, # . Usage (100Dh), 682 + 0x15, 0x00, # . Logical Minimum (0), 683 + 0x25, 0x01, # . Logical Maximum (1), 684 + 0x75, 0x08, # . Report Size (8), 685 + 0x95, 0x01, # . Report Count (1), 686 + 0xB1, 0x02, # . Feature (Variable), 687 + 0x85, 0x14, # . Report ID (20), 688 + 0x0A, 0x14, 0x10, # . Usage (1014h), 689 + 0x26, 0xFF, 0x00, # . Logical Maximum (255), 690 + 0x95, 0x0D, # . Report Count (13), 691 + 0xB1, 0x02, # . Feature (Variable), 692 + 0x85, 0x31, # . Report ID (49), 693 + 0x0A, 0x31, 0x10, # . Usage (1031h), 694 + 0x25, 0x64, # . Logical Maximum (100), 695 + 0x95, 0x05, # . Report Count (5), 696 + 0xB1, 0x02, # . Feature (Variable), 697 + 0x85, 0x32, # . Report ID (50), 698 + 0x0A, 0x31, 0x10, # . Usage (1031h), 699 + 0x25, 0x64, # . Logical Maximum (100), 700 + 0x95, 0x01, # . Report Count (1), 701 + 0xB1, 0x02, # . Feature (Variable), 702 + 0x0A, 0x32, 0x10, # . Usage (1032h), 703 + 0x25, 0x03, # . Logical Maximum (3), 704 + 0xB1, 0x02, # . Feature (Variable), 705 + 0x85, 0x34, # . Report ID (52), 706 + 0x0A, 0x34, 0x10, # . Usage (1034h), 707 + 0x25, 0x01, # . Logical Maximum (1), 708 + 0x95, 0x04, # . Report Count (4), 709 + 0xB1, 0x02, # . Feature (Variable), 710 + 0x85, 0x35, # . Report ID (53), 711 + 0x0A, 0x35, 0x10, # . Usage (1035h), 712 + 0x26, 0xFF, 0x00, # . Logical Maximum (255), 713 + 0x95, 0x0A, # . Report Count (10), 714 + 0xB1, 0x02, # . Feature (Variable), 715 + 0x85, 0x36, # . Report ID (54), 716 + 0x0A, 0x35, 0x10, # . Usage (1035h), 717 + 0x26, 0xFF, 0x00, # . Logical Maximum (255), 718 + 0x96, 0x01, 0x01, # . Report Count (257), 719 + 0xB1, 0x02, # . Feature (Variable), 720 + 0x85, 0xCC, # . Report ID (204), 721 + 0x0A, 0xCC, 0x10, # . Usage (10CCh), 722 + 0x26, 0xFF, 0x00, # . Logical Maximum (255), 723 + 0x95, 0x02, # . Report Count (2), 724 + 0xB1, 0x02, # . Feature (Variable), 725 + 0xC0, # . End Collection, 726 + 0x0A, 0xAC, 0x10, # . Usage (10ACh), 727 + 0xA1, 0x02, # . Collection (Logical), 728 + 0x15, 0x00, # . Logical Minimum (0), 729 + 0x26, 0xFF, 0x00, # . Logical Maximum (255), 730 + 0x75, 0x08, # . Report Size (8), 731 + 0x85, 0xAC, # . Report ID (172), 732 + 0x09, 0x00, # . Usage (00h), 733 + 0x95, 0xBF, # . Report Count (191), 734 + 0x81, 0x02, # . Input (Variable), 735 + 0x85, 0x33, # . Report ID (51), 736 + 0x09, 0x00, # . Usage (00h), 737 + 0x95, 0x12, # . Report Count (18), 738 + 0xB1, 0x02, # . Feature (Variable), 739 + 0x85, 0x64, # . Report ID (100), 740 + 0x09, 0x00, # . Usage (00h), 741 + 0x95, 0x0C, # . Report Count (12), 742 + 0xB1, 0x02, # . Feature (Variable), 743 + 0x85, 0x15, # . Report ID (21), 744 + 0x09, 0x00, # . Usage (00h), 745 + 0x95, 0x0E, # . Report Count (14), 746 + 0xB1, 0x02, # . Feature (Variable), 747 + 0x85, 0x12, # . Report ID (18), 748 + 0x09, 0x00, # . Usage (00h), 749 + 0x95, 0x04, # . Report Count (4), 750 + 0xB1, 0x02, # . Feature (Variable), 751 + 0x85, 0x16, # . Report ID (22), 752 + 0x09, 0x00, # . Usage (00h), 753 + 0x95, 0x0E, # . Report Count (14), 754 + 0xB1, 0x02, # . Feature (Variable), 755 + 0x85, 0x40, # . Report ID (64), 756 + 0x09, 0x00, # . Usage (00h), 757 + 0x95, 0x01, # . Report Count (1), 758 + 0xB1, 0x02, # . Feature (Variable), 759 + 0x85, 0x41, # . Report ID (65), 760 + 0x09, 0x00, # . Usage (00h), 761 + 0x95, 0x01, # . Report Count (1), 762 + 0xB1, 0x02, # . Feature (Variable), 763 + 0x85, 0x42, # . Report ID (66), 764 + 0x09, 0x00, # . Usage (00h), 765 + 0x95, 0x04, # . Report Count (4), 766 + 0xB1, 0x02, # . Feature (Variable), 767 + 0x85, 0x43, # . Report ID (67), 768 + 0x09, 0x00, # . Usage (00h), 769 + 0x95, 0x0D, # . Report Count (13), 770 + 0xB1, 0x02, # . Feature (Variable), 771 + 0x85, 0x44, # . Report ID (68), 772 + 0x09, 0x00, # . Usage (00h), 773 + 0x95, 0x3F, # . Report Count (63), 774 + 0xB1, 0x02, # . Feature (Variable), 775 + 0x85, 0x45, # . Report ID (69), 776 + 0x09, 0x00, # . Usage (00h), 777 + 0x95, 0x20, # . Report Count (32), 778 + 0xB1, 0x02, # . Feature (Variable), 779 + 0x85, 0x60, # . Report ID (96), 780 + 0x09, 0x00, # . Usage (00h), 781 + 0x95, 0x3F, # . Report Count (63), 782 + 0xB1, 0x02, # . Feature (Variable), 783 + 0x85, 0x61, # . Report ID (97), 784 + 0x09, 0x00, # . Usage (00h), 785 + 0x95, 0x3E, # . Report Count (62), 786 + 0xB1, 0x02, # . Feature (Variable), 787 + 0x85, 0x62, # . Report ID (98), 788 + 0x09, 0x00, # . Usage (00h), 789 + 0x95, 0x3E, # . Report Count (62), 790 + 0xB1, 0x02, # . Feature (Variable), 791 + 0xC0, # . End Collection, 792 + 0x85, 0xD0, # . Report ID (208), 793 + 0x09, 0x01, # . Usage (01h), 794 + 0x96, 0x08, 0x00, # . Report Count (8), 795 + 0xB1, 0x02, # . Feature (Variable), 796 + 0x85, 0xD1, # . Report ID (209), 797 + 0x09, 0x01, # . Usage (01h), 798 + 0x96, 0x04, 0x01, # . Report Count (260), 799 + 0xB1, 0x02, # . Feature (Variable), 800 + 0x85, 0xD2, # . Report ID (210), 801 + 0x09, 0x01, # . Usage (01h), 802 + 0x96, 0x04, 0x01, # . Report Count (260), 803 + 0xB1, 0x02, # . Feature (Variable), 804 + 0x85, 0xD3, # . Report ID (211), 805 + 0x09, 0x01, # . Usage (01h), 806 + 0x96, 0x04, 0x00, # . Report Count (4), 807 + 0xB1, 0x02, # . Feature (Variable), 808 + 0x85, 0xD4, # . Report ID (212), 809 + 0x09, 0x01, # . Usage (01h), 810 + 0x96, 0x04, 0x00, # . Report Count (4), 811 + 0xB1, 0x02, # . Feature (Variable), 812 + 0x85, 0xD5, # . Report ID (213), 813 + 0x09, 0x01, # . Usage (01h), 814 + 0x96, 0x04, 0x00, # . Report Count (4), 815 + 0xB1, 0x02, # . Feature (Variable), 816 + 0x85, 0xD6, # . Report ID (214), 817 + 0x09, 0x01, # . Usage (01h), 818 + 0x96, 0x04, 0x00, # . Report Count (4), 819 + 0xB1, 0x02, # . Feature (Variable), 820 + 0x85, 0xD7, # . Report ID (215), 821 + 0x09, 0x01, # . Usage (01h), 822 + 0x96, 0x08, 0x00, # . Report Count (8), 823 + 0xB1, 0x02, # . Feature (Variable), 824 + 0x85, 0xD8, # . Report ID (216), 825 + 0x09, 0x01, # . Usage (01h), 826 + 0x96, 0x0C, 0x00, # . Report Count (12), 827 + 0xB1, 0x02, # . Feature (Variable), 828 + 0x85, 0xD9, # . Report ID (217), 829 + 0x09, 0x01, # . Usage (01h), 830 + 0x96, 0x00, 0x0A, # . Report Count (2560), 831 + 0xB1, 0x02, # . Feature (Variable), 832 + 0x85, 0xDA, # . Report ID (218), 833 + 0x09, 0x01, # . Usage (01h), 834 + 0x96, 0x04, 0x04, # . Report Count (1028), 835 + 0xB1, 0x02, # . Feature (Variable), 836 + 0x85, 0xDB, # . Report ID (219), 837 + 0x09, 0x01, # . Usage (01h), 838 + 0x96, 0x06, 0x00, # . Report Count (6), 839 + 0xB1, 0x02, # . Feature (Variable), 840 + 0x85, 0xDC, # . Report ID (220), 841 + 0x09, 0x01, # . Usage (01h), 842 + 0x96, 0x02, 0x00, # . Report Count (2), 843 + 0xB1, 0x02, # . Feature (Variable), 844 + 0x85, 0xDD, # . Report ID (221), 845 + 0x09, 0x01, # . Usage (01h), 846 + 0x96, 0x04, 0x00, # . Report Count (4), 847 + 0xB1, 0x02, # . Feature (Variable), 848 + 0x85, 0xDE, # . Report ID (222), 849 + 0x09, 0x01, # . Usage (01h), 850 + 0x96, 0x04, 0x00, # . Report Count (4), 851 + 0xB1, 0x02, # . Feature (Variable), 852 + 0x85, 0xDF, # . Report ID (223), 853 + 0x09, 0x01, # . Usage (01h), 854 + 0x96, 0x22, 0x00, # . Report Count (34), 855 + 0xB1, 0x02, # . Feature (Variable), 856 + 0x85, 0xE0, # . Report ID (224), 857 + 0x09, 0x01, # . Usage (01h), 858 + 0x96, 0x01, 0x00, # . Report Count (1), 859 + 0xB1, 0x02, # . Feature (Variable), 860 + 0x85, 0xE1, # . Report ID (225), 861 + 0x09, 0x01, # . Usage (01h), 862 + 0x96, 0x02, 0x00, # . Report Count (2), 863 + 0xB1, 0x02, # . Feature (Variable), 864 + 0x85, 0xE2, # . Report ID (226), 865 + 0x09, 0x01, # . Usage (01h), 866 + 0x96, 0x02, 0x00, # . Report Count (2), 867 + 0xB1, 0x02, # . Feature (Variable), 868 + 0x85, 0xE3, # . Report ID (227), 869 + 0x09, 0x01, # . Usage (01h), 870 + 0x96, 0x02, 0x00, # . Report Count (2), 871 + 0xB1, 0x02, # . Feature (Variable), 872 + 0x85, 0xE4, # . Report ID (228), 873 + 0x09, 0x01, # . Usage (01h), 874 + 0x96, 0xFF, 0x01, # . Report Count (511), 875 + 0xB1, 0x02, # . Feature (Variable), 876 + 0xC0 # . End Collection 877 + ] 878 + # fmt: on 879 + 880 + # Report ID (20), Usage (1014h), Report Count (13) -> 15 881 + wacom_pth860_v150 = wacom_pth860_v145.copy() 882 + wacom_pth860_v150[0x2CA] = 0x0F 883 + 884 + # fmt: off 885 + wacom_pth460_v105 = [ 886 + 0x06, 0x0D, 0xFF, # . Usage Page (FF0Dh), 887 + 0x09, 0x01, # . Usage (01h), 888 + 0xA1, 0x01, # . Collection (Application), 889 + 0x85, 0x10, # . Report ID (16), 890 + 0x09, 0x20, # . Usage (20h), 891 + 0x35, 0x00, # . Physical Minimum (0), 892 + 0x45, 0x00, # . Physical Maximum (0), 893 + 0x15, 0x00, # . Logical Minimum (0), 894 + 0x25, 0x01, # . Logical Maximum (1), 895 + 0xA1, 0x00, # . Collection (Physical), 896 + 0x09, 0x42, # . Usage (42h), 897 + 0x09, 0x44, # . Usage (44h), 898 + 0x09, 0x5A, # . Usage (5Ah), 899 + 0x09, 0x45, # . Usage (45h), 900 + 0x09, 0x3C, # . Usage (3Ch), 901 + 0x09, 0x32, # . Usage (32h), 902 + 0x09, 0x36, # . Usage (36h), 903 + 0x25, 0x01, # . Logical Maximum (1), 904 + 0x75, 0x01, # . Report Size (1), 905 + 0x95, 0x07, # . Report Count (7), 906 + 0x81, 0x02, # . Input (Variable), 907 + 0x95, 0x01, # . Report Count (1), 908 + 0x81, 0x03, # . Input (Constant, Variable), 909 + 0x0A, 0x30, 0x01, # . Usage (0130h), 910 + 0x65, 0x11, # . Unit (Centimeter), 911 + 0x55, 0x0D, # . Unit Exponent (13), 912 + 0x47, 0x58, 0x3E, 0x00, 0x00, # . Physical Maximum (15960), 913 + 0x27, 0xB0, 0x7C, 0x00, 0x00, # . Logical Maximum (31920), 914 + 0x75, 0x18, # . Report Size (24), 915 + 0x95, 0x01, # . Report Count (1), 916 + 0x81, 0x02, # . Input (Variable), 917 + 0x0A, 0x31, 0x01, # . Usage (0131h), 918 + 0x47, 0xF7, 0x26, 0x00, 0x00, # . Physical Maximum (9975), 919 + 0x27, 0xEE, 0x4D, 0x00, 0x00, # . Logical Maximum (19950), 920 + 0x81, 0x02, # . Input (Variable), 921 + 0x09, 0x30, # . Usage (30h), 922 + 0x55, 0x00, # . Unit Exponent (0), 923 + 0x65, 0x00, # . Unit, 924 + 0x26, 0xFF, 0x1F, # . Logical Maximum (8191), # !!! Errata: Missing Physical Max = 0 925 + 0x75, 0x10, # . Report Size (16), 926 + 0x81, 0x02, # . Input (Variable), 927 + 0x09, 0x3D, # . Usage (3Dh), 928 + 0x09, 0x3E, # . Usage (3Eh), 929 + 0x65, 0x14, # . Unit (Degrees), 930 + 0x55, 0x00, # . Unit Exponent (0), 931 + 0x35, 0xC0, # . Physical Minimum (-64), 932 + 0x45, 0x3F, # . Physical Maximum (63), 933 + 0x15, 0xC0, # . Logical Minimum (-64), 934 + 0x25, 0x3F, # . Logical Maximum (63), 935 + 0x75, 0x08, # . Report Size (8), 936 + 0x95, 0x02, # . Report Count (2), 937 + 0x81, 0x02, # . Input (Variable), 938 + 0x09, 0x41, # . Usage (41h), 939 + 0x65, 0x14, # . Unit (Degrees), 940 + 0x55, 0x00, # . Unit Exponent (0), 941 + 0x36, 0x4C, 0xFF, # . Physical Minimum (-180), 942 + 0x46, 0xB3, 0x00, # . Physical Maximum (179), 943 + 0x16, 0x7C, 0xFC, # . Logical Minimum (-900), 944 + 0x26, 0x83, 0x03, # . Logical Maximum (899), 945 + 0x75, 0x10, # . Report Size (16), 946 + 0x95, 0x01, # . Report Count (1), 947 + 0x81, 0x0A, # . Input (Variable, Wrap), 948 + 0x0A, 0x03, 0x0D, # . Usage (0D03h), 949 + 0x65, 0x00, # . Unit, 950 + 0x55, 0x00, # . Unit Exponent (0), 951 + 0x35, 0x00, # . Physical Minimum (0), 952 + 0x45, 0x00, # . Physical Maximum (0), 953 + 0x15, 0x00, # . Logical Minimum (0), 954 + 0x26, 0xFF, 0x07, # . Logical Maximum (2047), 955 + 0x81, 0x02, # . Input (Variable), 956 + 0x0A, 0x32, 0x01, # . Usage (0132h), 957 + 0x25, 0x3F, # . Logical Maximum (63), 958 + 0x75, 0x08, # . Report Size (8), 959 + 0x95, 0x01, # . Report Count (1), 960 + 0x81, 0x02, # . Input (Variable), 961 + 0x09, 0x5B, # . Usage (5Bh), 962 + 0x09, 0x5C, # . Usage (5Ch), 963 + 0x17, 0x00, 0x00, 0x00, 0x80, # . Logical Minimum (-2147483648), 964 + 0x27, 0xFF, 0xFF, 0xFF, 0x7F, # . Logical Maximum (2147483647), 965 + 0x75, 0x20, # . Report Size (32), 966 + 0x95, 0x02, # . Report Count (2), 967 + 0x81, 0x02, # . Input (Variable), 968 + 0x09, 0x77, # . Usage (77h), 969 + 0x15, 0x00, # . Logical Minimum (0), 970 + 0x26, 0xFF, 0x0F, # . Logical Maximum (4095), 971 + 0x75, 0x10, # . Report Size (16), 972 + 0x95, 0x01, # . Report Count (1), 973 + 0x81, 0x02, # . Input (Variable), 974 + 0xC0, # . End Collection, 975 + 0x85, 0x11, # . Report ID (17), 976 + 0x65, 0x00, # . Unit, 977 + 0x55, 0x00, # . Unit Exponent (0), 978 + 0x35, 0x00, # . Physical Minimum (0), 979 + 0x45, 0x00, # . Physical Maximum (0), 980 + 0x09, 0x39, # . Usage (39h), 981 + 0xA1, 0x00, # . Collection (Physical), 982 + 0x09, 0x39, # . Usage (39h), 983 + 0xA1, 0x00, # . Collection (Physical), 984 + 0x35, 0x00, # . Physical Minimum (0), 985 + 0x45, 0x00, # . Physical Maximum (0), 986 + 0x15, 0x00, # . Logical Minimum (0), 987 + 0x1A, 0x10, 0x09, # . Usage Minimum (0910h), 988 + 0x2A, 0x15, 0x09, # . Usage Maximum (0915h), 989 + 0x15, 0x00, # . Logical Minimum (0), 990 + 0x25, 0x01, # . Logical Maximum (1), 991 + 0x75, 0x01, # . Report Size (1), 992 + 0x95, 0x06, # . Report Count (6), 993 + 0x81, 0x02, # . Input (Variable), 994 + 0x95, 0x02, # . Report Count (2), 995 + 0x81, 0x03, # . Input (Constant, Variable), 996 + 0xC0, # . End Collection, 997 + 0x75, 0x08, # . Report Size (8), 998 + 0x95, 0x01, # . Report Count (1), 999 + 0x81, 0x03, # . Input (Constant, Variable), 1000 + 0x09, 0x39, # . Usage (39h), 1001 + 0xA1, 0x00, # . Collection (Physical), 1002 + 0x35, 0x00, # . Physical Minimum (0), 1003 + 0x45, 0x00, # . Physical Maximum (0), 1004 + 0x0A, 0x95, 0x09, # . Usage (0995h), 1005 + 0x15, 0x00, # . Logical Minimum (0), 1006 + 0x25, 0x01, # . Logical Maximum (1), 1007 + 0x75, 0x01, # . Report Size (1), 1008 + 0x95, 0x01, # . Report Count (1), 1009 + 0x81, 0x02, # . Input (Variable), 1010 + 0x95, 0x07, # . Report Count (7), 1011 + 0x81, 0x03, # . Input (Constant, Variable), 1012 + 0xC0, # . End Collection, 1013 + 0x09, 0x39, # . Usage (39h), 1014 + 0xA1, 0x00, # . Collection (Physical), 1015 + 0x35, 0x00, # . Physical Minimum (0), 1016 + 0x15, 0x00, # . Logical Minimum (0), 1017 + 0x0A, 0x38, 0x01, # . Usage (0138h), 1018 + 0x65, 0x14, # . Unit (Degrees), 1019 + 0x55, 0x00, # . Unit Exponent (0), 1020 + 0x35, 0x00, # . Physical Minimum (0), 1021 + 0x46, 0x67, 0x01, # . Physical Maximum (359), 1022 + 0x15, 0x00, # . Logical Minimum (0), 1023 + 0x25, 0x47, # . Logical Maximum (71), 1024 + 0x75, 0x07, # . Report Size (7), 1025 + 0x95, 0x01, # . Report Count (1), 1026 + 0x81, 0x4A, # . Input (Variable, Wrap, Null State), 1027 + 0x0A, 0x39, 0x01, # . Usage (0139h), 1028 + 0x65, 0x00, # . Unit, 1029 + 0x55, 0x00, # . Unit Exponent (0), 1030 + 0x45, 0x00, # . Physical Maximum (0), 1031 + 0x25, 0x01, # . Logical Maximum (1), 1032 + 0x75, 0x01, # . Report Size (1), 1033 + 0x95, 0x01, # . Report Count (1), 1034 + 0x81, 0x02, # . Input (Variable), 1035 + 0xC0, # . End Collection, 1036 + 0x75, 0x08, # . Report Size (8), 1037 + 0x95, 0x04, # . Report Count (4), 1038 + 0x81, 0x03, # . Input (Constant, Variable), 1039 + 0xC0, # . End Collection, 1040 + 0x85, 0x13, # . Report ID (19), 1041 + 0x65, 0x00, # . Unit, 1042 + 0x55, 0x00, # . Unit Exponent (0), 1043 + 0x35, 0x00, # . Physical Minimum (0), 1044 + 0x45, 0x00, # . Physical Maximum (0), 1045 + 0x0A, 0x13, 0x10, # . Usage (1013h), 1046 + 0xA1, 0x00, # . Collection (Physical), 1047 + 0x0A, 0x13, 0x10, # . Usage (1013h), 1048 + 0xA1, 0x00, # . Collection (Physical), 1049 + 0x35, 0x00, # . Physical Minimum (0), 1050 + 0x45, 0x00, # . Physical Maximum (0), 1051 + 0x15, 0x00, # . Logical Minimum (0), 1052 + 0x0A, 0x3B, 0x04, # . Usage (043Bh), 1053 + 0x15, 0x00, # . Logical Minimum (0), 1054 + 0x25, 0x64, # . Logical Maximum (100), 1055 + 0x75, 0x07, # . Report Size (7), 1056 + 0x95, 0x01, # . Report Count (1), 1057 + 0x81, 0x02, # . Input (Variable), 1058 + 0x0A, 0x04, 0x04, # . Usage (0404h), 1059 + 0x25, 0x01, # . Logical Maximum (1), 1060 + 0x75, 0x01, # . Report Size (1), 1061 + 0x81, 0x02, # . Input (Variable), 1062 + 0xC0, # . End Collection, 1063 + 0x0A, 0x13, 0x10, # . Usage (1013h), 1064 + 0xA1, 0x00, # . Collection (Physical), 1065 + 0x35, 0x00, # . Physical Minimum (0), 1066 + 0x45, 0x00, # . Physical Maximum (0), 1067 + 0x0A, 0x52, 0x04, # . Usage (0452h), 1068 + 0x15, 0x00, # . Logical Minimum (0), 1069 + 0x25, 0x01, # . Logical Maximum (1), 1070 + 0x75, 0x01, # . Report Size (1), 1071 + 0x95, 0x01, # . Report Count (1), 1072 + 0x81, 0x02, # . Input (Variable), 1073 + 0x0A, 0x41, 0x04, # . Usage (0441h), 1074 + 0x15, 0x00, # . Logical Minimum (0), 1075 + 0x25, 0x07, # . Logical Maximum (7), 1076 + 0x75, 0x03, # . Report Size (3), 1077 + 0x95, 0x02, # . Report Count (2), 1078 + 0x81, 0x02, # . Input (Variable), 1079 + 0x0A, 0x54, 0x04, # . Usage (0454h), 1080 + 0x15, 0x00, # . Logical Minimum (0), 1081 + 0x25, 0x01, # . Logical Maximum (1), 1082 + 0x75, 0x01, # . Report Size (1), 1083 + 0x95, 0x01, # . Report Count (1), 1084 + 0x81, 0x02, # . Input (Variable), 1085 + 0xC0, # . End Collection, 1086 + 0x0A, 0x13, 0x10, # . Usage (1013h), 1087 + 0xA1, 0x00, # . Collection (Physical), 1088 + 0x35, 0x00, # . Physical Minimum (0), 1089 + 0x45, 0x00, # . Physical Maximum (0), 1090 + 0x15, 0x00, # . Logical Minimum (0), 1091 + 0x0A, 0x3C, 0x04, # . Usage (043Ch), 1092 + 0x55, 0x00, # . Unit Exponent (0), 1093 + 0x65, 0x00, # . Unit, 1094 + 0x15, 0xFB, # . Logical Minimum (-5), 1095 + 0x25, 0x32, # . Logical Maximum (50), 1096 + 0x75, 0x08, # . Report Size (8), 1097 + 0x95, 0x01, # . Report Count (1), 1098 + 0x81, 0x02, # . Input (Variable), 1099 + 0xC0, # . End Collection, 1100 + 0x0A, 0x13, 0x10, # . Usage (1013h), 1101 + 0xA1, 0x00, # . Collection (Physical), 1102 + 0x35, 0x00, # . Physical Minimum (0), 1103 + 0x45, 0x00, # . Physical Maximum (0), 1104 + 0x15, 0x00, # . Logical Minimum (0), 1105 + 0x0A, 0x3D, 0x04, # . Usage (043Dh), 1106 + 0x55, 0x00, # . Unit Exponent (0), 1107 + 0x65, 0x00, # . Unit, 1108 + 0x15, 0x00, # . Logical Minimum (0), 1109 + 0x26, 0xFF, 0x0F, # . Logical Maximum (4095), 1110 + 0x75, 0x10, # . Report Size (16), 1111 + 0x95, 0x01, # . Report Count (1), 1112 + 0x81, 0x02, # . Input (Variable), 1113 + 0xC0, # . End Collection, 1114 + 0x75, 0x08, # . Report Size (8), 1115 + 0x95, 0x03, # . Report Count (3), 1116 + 0x81, 0x03, # . Input (Constant, Variable), 1117 + 0xC0, # . End Collection, 1118 + 0x09, 0x0E, # . Usage (0Eh), 1119 + 0xA1, 0x02, # . Collection (Logical), 1120 + 0x85, 0x02, # . Report ID (2), 1121 + 0x0A, 0x02, 0x10, # . Usage (1002h), 1122 + 0x15, 0x02, # . Logical Minimum (2), 1123 + 0x25, 0x02, # . Logical Maximum (2), 1124 + 0x75, 0x08, # . Report Size (8), 1125 + 0x95, 0x01, # . Report Count (1), 1126 + 0xB1, 0x02, # . Feature (Variable), 1127 + 0x85, 0x03, # . Report ID (3), 1128 + 0x0A, 0x03, 0x10, # . Usage (1003h), 1129 + 0x15, 0x00, # . Logical Minimum (0), 1130 + 0x26, 0xFF, 0x00, # . Logical Maximum (255), 1131 + 0x95, 0x01, # . Report Count (1), 1132 + 0xB1, 0x02, # . Feature (Variable), 1133 + 0x85, 0x04, # . Report ID (4), 1134 + 0x0A, 0x04, 0x10, # . Usage (1004h), 1135 + 0x15, 0x00, # . Logical Minimum (0), 1136 + 0x25, 0x01, # . Logical Maximum (1), 1137 + 0x95, 0x01, # . Report Count (1), 1138 + 0xB1, 0x02, # . Feature (Variable), 1139 + 0x85, 0x07, # . Report ID (7), 1140 + 0x0A, 0x09, 0x10, # . Usage (1009h), 1141 + 0x15, 0x00, # . Logical Minimum (0), 1142 + 0x26, 0xFF, 0x00, # . Logical Maximum (255), 1143 + 0x95, 0x01, # . Report Count (1), 1144 + 0xB1, 0x02, # . Feature (Variable), 1145 + 0xB1, 0x03, # . Feature (Constant, Variable), 1146 + 0x0A, 0x07, 0x10, # . Usage (1007h), 1147 + 0x09, 0x00, # . Usage (00h), 1148 + 0x0A, 0x08, 0x10, # . Usage (1008h), 1149 + 0x09, 0x00, # . Usage (00h), 1150 + 0x09, 0x00, # . Usage (00h), 1151 + 0x09, 0x00, # . Usage (00h), 1152 + 0x27, 0xFF, 0xFF, 0x00, 0x00, # . Logical Maximum (65535), 1153 + 0x75, 0x10, # . Report Size (16), 1154 + 0x95, 0x06, # . Report Count (6), 1155 + 0xB1, 0x02, # . Feature (Variable), 1156 + 0x09, 0x00, # . Usage (00h), 1157 + 0x25, 0x00, # . Logical Maximum (0), 1158 + 0x75, 0x08, # . Report Size (8), 1159 + 0x95, 0x01, # . Report Count (1), 1160 + 0xB1, 0x03, # . Feature (Constant, Variable), 1161 + 0x85, 0x0C, # . Report ID (12), 1162 + 0x0A, 0x30, 0x0D, # . Usage (0D30h), 1163 + 0x0A, 0x31, 0x0D, # . Usage (0D31h), 1164 + 0x0A, 0x32, 0x0D, # . Usage (0D32h), 1165 + 0x0A, 0x33, 0x0D, # . Usage (0D33h), 1166 + 0x65, 0x11, # . Unit (Centimeter), 1167 + 0x55, 0x0D, # . Unit Exponent (13), 1168 + 0x35, 0x00, # . Physical Minimum (0), 1169 + 0x46, 0xC8, 0x00, # . Physical Maximum (200), 1170 + 0x15, 0x00, # . Logical Minimum (0), 1171 + 0x26, 0x90, 0x01, # . Logical Maximum (400), 1172 + 0x75, 0x10, # . Report Size (16), 1173 + 0x95, 0x04, # . Report Count (4), 1174 + 0xB1, 0x02, # . Feature (Variable), 1175 + 0x85, 0x0D, # . Report ID (13), 1176 + 0x0A, 0x0D, 0x10, # . Usage (100Dh), 1177 + 0x65, 0x00, # . Unit, 1178 + 0x55, 0x00, # . Unit Exponent (0), 1179 + 0x45, 0x00, # . Physical Maximum (0), 1180 + 0x25, 0x01, # . Logical Maximum (1), 1181 + 0x75, 0x08, # . Report Size (8), 1182 + 0x95, 0x01, # . Report Count (1), 1183 + 0xB1, 0x02, # . Feature (Variable), 1184 + 0x85, 0x14, # . Report ID (20), 1185 + 0x0A, 0x14, 0x10, # . Usage (1014h), 1186 + 0x26, 0xFF, 0x00, # . Logical Maximum (255), 1187 + 0x95, 0x0D, # . Report Count (13), 1188 + 0xB1, 0x02, # . Feature (Variable), 1189 + 0x85, 0xCC, # . Report ID (204), 1190 + 0x0A, 0xCC, 0x10, # . Usage (10CCh), 1191 + 0x95, 0x02, # . Report Count (2), 1192 + 0xB1, 0x02, # . Feature (Variable), 1193 + 0xC0, # . End Collection, 1194 + 0x09, 0x0E, # . Usage (0Eh), 1195 + 0xA1, 0x02, # . Collection (Logical), 1196 + 0x85, 0x31, # . Report ID (49), 1197 + 0x0A, 0x31, 0x10, # . Usage (1031h), 1198 + 0x25, 0x64, # . Logical Maximum (100), 1199 + 0x95, 0x03, # . Report Count (3), 1200 + 0xB1, 0x02, # . Feature (Variable), 1201 + 0x95, 0x02, # . Report Count (2), 1202 + 0xB1, 0x03, # . Feature (Constant, Variable), 1203 + 0xC0, # . End Collection, 1204 + 0x0A, 0xAC, 0x10, # . Usage (10ACh), 1205 + 0xA1, 0x02, # . Collection (Logical), 1206 + 0x15, 0x00, # . Logical Minimum (0), 1207 + 0x26, 0xFF, 0x00, # . Logical Maximum (255), 1208 + 0x75, 0x08, # . Report Size (8), 1209 + 0x85, 0xAC, # . Report ID (172), 1210 + 0x09, 0x00, # . Usage (00h), 1211 + 0x96, 0xBF, 0x00, # . Report Count (191), 1212 + 0x81, 0x02, # . Input (Variable), 1213 + 0x85, 0x15, # . Report ID (21), 1214 + 0x09, 0x00, # . Usage (00h), 1215 + 0x95, 0x0E, # . Report Count (14), 1216 + 0xB1, 0x02, # . Feature (Variable), 1217 + 0x85, 0x33, # . Report ID (51), 1218 + 0x09, 0x00, # . Usage (00h), 1219 + 0x95, 0x12, # . Report Count (18), 1220 + 0xB1, 0x02, # . Feature (Variable), 1221 + 0x85, 0x44, # . Report ID (68), 1222 + 0x09, 0x00, # . Usage (00h), 1223 + 0x95, 0x04, # . Report Count (4), 1224 + 0xB1, 0x02, # . Feature (Variable), 1225 + 0x85, 0x45, # . Report ID (69), 1226 + 0x09, 0x00, # . Usage (00h), 1227 + 0x95, 0x20, # . Report Count (32), 1228 + 0xB1, 0x02, # . Feature (Variable), 1229 + 0x85, 0x60, # . Report ID (96), 1230 + 0x09, 0x00, # . Usage (00h), 1231 + 0x95, 0x3F, # . Report Count (63), 1232 + 0xB1, 0x02, # . Feature (Variable), 1233 + 0x85, 0x61, # . Report ID (97), 1234 + 0x09, 0x00, # . Usage (00h), 1235 + 0x95, 0x3E, # . Report Count (62), 1236 + 0xB1, 0x02, # . Feature (Variable), 1237 + 0x85, 0x62, # . Report ID (98), 1238 + 0x09, 0x00, # . Usage (00h), 1239 + 0x95, 0x3E, # . Report Count (62), 1240 + 0xB1, 0x02, # . Feature (Variable), 1241 + 0x85, 0x65, # . Report ID (101), 1242 + 0x09, 0x00, # . Usage (00h), 1243 + 0x95, 0x04, # . Report Count (4), 1244 + 0xB1, 0x02, # . Feature (Variable), 1245 + 0x85, 0x66, # . Report ID (102), 1246 + 0x09, 0x00, # . Usage (00h), 1247 + 0x95, 0x04, # . Report Count (4), 1248 + 0xB1, 0x02, # . Feature (Variable), 1249 + 0x85, 0x67, # . Report ID (103), 1250 + 0x09, 0x00, # . Usage (00h), 1251 + 0x95, 0x04, # . Report Count (4), 1252 + 0xB1, 0x02, # . Feature (Variable), 1253 + 0x85, 0x68, # . Report ID (104), 1254 + 0x09, 0x00, # . Usage (00h), 1255 + 0x95, 0x11, # . Report Count (17), 1256 + 0xB1, 0x02, # . Feature (Variable), 1257 + 0x85, 0x6F, # . Report ID (111), 1258 + 0x09, 0x00, # . Usage (00h), 1259 + 0x95, 0x3E, # . Report Count (62), 1260 + 0xB1, 0x02, # . Feature (Variable), 1261 + 0x85, 0xCD, # . Report ID (205), 1262 + 0x09, 0x00, # . Usage (00h), 1263 + 0x95, 0x02, # . Report Count (2), 1264 + 0xB1, 0x02, # . Feature (Variable), 1265 + 0x85, 0x16, # . Report ID (22), 1266 + 0x09, 0x00, # . Usage (00h), 1267 + 0x95, 0x0E, # . Report Count (14), 1268 + 0xB1, 0x02, # . Feature (Variable), 1269 + 0x85, 0x35, # . Report ID (53), 1270 + 0x09, 0x00, # . Usage (00h), 1271 + 0x95, 0x0A, # . Report Count (10), 1272 + 0xB1, 0x02, # . Feature (Variable), 1273 + 0xC0, # . End Collection, 1274 + 0x85, 0xD1, # . Report ID (209), 1275 + 0x09, 0x01, # . Usage (01h), 1276 + 0x96, 0x04, 0x01, # . Report Count (260), 1277 + 0xB1, 0x02, # . Feature (Variable), 1278 + 0x85, 0xD2, # . Report ID (210), 1279 + 0x09, 0x01, # . Usage (01h), 1280 + 0x96, 0x04, 0x01, # . Report Count (260), 1281 + 0xB1, 0x02, # . Feature (Variable), 1282 + 0x85, 0xD3, # . Report ID (211), 1283 + 0x09, 0x01, # . Usage (01h), 1284 + 0x96, 0x04, 0x00, # . Report Count (4), 1285 + 0xB1, 0x02, # . Feature (Variable), 1286 + 0x85, 0xD4, # . Report ID (212), 1287 + 0x09, 0x01, # . Usage (01h), 1288 + 0x96, 0x04, 0x00, # . Report Count (4), 1289 + 0xB1, 0x02, # . Feature (Variable), 1290 + 0x85, 0xD5, # . Report ID (213), 1291 + 0x09, 0x01, # . Usage (01h), 1292 + 0x96, 0x04, 0x00, # . Report Count (4), 1293 + 0xB1, 0x02, # . Feature (Variable), 1294 + 0x85, 0xD6, # . Report ID (214), 1295 + 0x09, 0x01, # . Usage (01h), 1296 + 0x96, 0x04, 0x00, # . Report Count (4), 1297 + 0xB1, 0x02, # . Feature (Variable), 1298 + 0x85, 0xD7, # . Report ID (215), 1299 + 0x09, 0x01, # . Usage (01h), 1300 + 0x96, 0x08, 0x00, # . Report Count (8), 1301 + 0xB1, 0x02, # . Feature (Variable), 1302 + 0x85, 0xD8, # . Report ID (216), 1303 + 0x09, 0x01, # . Usage (01h), 1304 + 0x96, 0x0C, 0x00, # . Report Count (12), 1305 + 0xB1, 0x02, # . Feature (Variable), 1306 + 0x85, 0xD9, # . Report ID (217), 1307 + 0x09, 0x01, # . Usage (01h), 1308 + 0x96, 0x00, 0x0A, # . Report Count (2560), 1309 + 0xB1, 0x02, # . Feature (Variable), 1310 + 0x85, 0xDA, # . Report ID (218), 1311 + 0x09, 0x01, # . Usage (01h), 1312 + 0x96, 0x04, 0x04, # . Report Count (1028), 1313 + 0xB1, 0x02, # . Feature (Variable), 1314 + 0x85, 0xDB, # . Report ID (219), 1315 + 0x09, 0x01, # . Usage (01h), 1316 + 0x96, 0x06, 0x00, # . Report Count (6), 1317 + 0xB1, 0x02, # . Feature (Variable), 1318 + 0x85, 0xDC, # . Report ID (220), 1319 + 0x09, 0x01, # . Usage (01h), 1320 + 0x96, 0x02, 0x00, # . Report Count (2), 1321 + 0xB1, 0x02, # . Feature (Variable), 1322 + 0x85, 0xDD, # . Report ID (221), 1323 + 0x09, 0x01, # . Usage (01h), 1324 + 0x96, 0x04, 0x00, # . Report Count (4), 1325 + 0xB1, 0x02, # . Feature (Variable), 1326 + 0x85, 0xDE, # . Report ID (222), 1327 + 0x09, 0x01, # . Usage (01h), 1328 + 0x96, 0x04, 0x00, # . Report Count (4), 1329 + 0xB1, 0x02, # . Feature (Variable), 1330 + 0x85, 0xDF, # . Report ID (223), 1331 + 0x09, 0x01, # . Usage (01h), 1332 + 0x96, 0x22, 0x00, # . Report Count (34), 1333 + 0xB1, 0x02, # . Feature (Variable), 1334 + 0x85, 0xE0, # . Report ID (224), 1335 + 0x09, 0x01, # . Usage (01h), 1336 + 0x96, 0x01, 0x00, # . Report Count (1), 1337 + 0xB1, 0x02, # . Feature (Variable), 1338 + 0x85, 0xE1, # . Report ID (225), 1339 + 0x09, 0x01, # . Usage (01h), 1340 + 0x96, 0x02, 0x00, # . Report Count (2), 1341 + 0xB1, 0x02, # . Feature (Variable), 1342 + 0x85, 0xE2, # . Report ID (226), 1343 + 0x09, 0x01, # . Usage (01h), 1344 + 0x96, 0x02, 0x00, # . Report Count (2), 1345 + 0xB1, 0x02, # . Feature (Variable), 1346 + 0x85, 0xE3, # . Report ID (227), 1347 + 0x09, 0x01, # . Usage (01h), 1348 + 0x96, 0x02, 0x00, # . Report Count (2), 1349 + 0xB1, 0x02, # . Feature (Variable), 1350 + 0x85, 0xE4, # . Report ID (228), 1351 + 0x09, 0x01, # . Usage (01h), 1352 + 0x96, 0xFF, 0x01, # . Report Count (511), 1353 + 0xB1, 0x02, # . Feature (Variable), 1354 + 0x85, 0xCB, # . Report ID (203), 1355 + 0x09, 0x01, # . Usage (01h), 1356 + 0x96, 0x1F, 0x00, # . Report Count (31), 1357 + 0xB1, 0x02, # . Feature (Variable), 1358 + 0xC0 # . End Collection 1359 + ] 1360 + # fmt: on
+440
tools/testing/selftests/hid/tests/test_apple_keyboard.py
··· 1 + #!/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # -*- coding: utf-8 -*- 4 + # 5 + # Copyright (c) 2019 Benjamin Tissoires <benjamin.tissoires@gmail.com> 6 + # Copyright (c) 2019 Red Hat, Inc. 7 + # 8 + 9 + from .test_keyboard import ArrayKeyboard, TestArrayKeyboard 10 + from hidtools.util import BusType 11 + 12 + import libevdev 13 + import logging 14 + 15 + logger = logging.getLogger("hidtools.test.apple-keyboard") 16 + 17 + KERNEL_MODULE = ("apple", "hid-apple") 18 + 19 + 20 + class KbdData(object): 21 + pass 22 + 23 + 24 + class AppleKeyboard(ArrayKeyboard): 25 + # fmt: off 26 + report_descriptor = [ 27 + 0x05, 0x01, # Usage Page (Generic Desktop) 28 + 0x09, 0x06, # Usage (Keyboard) 29 + 0xa1, 0x01, # Collection (Application) 30 + 0x85, 0x01, # .Report ID (1) 31 + 0x05, 0x07, # .Usage Page (Keyboard) 32 + 0x19, 0xe0, # .Usage Minimum (224) 33 + 0x29, 0xe7, # .Usage Maximum (231) 34 + 0x15, 0x00, # .Logical Minimum (0) 35 + 0x25, 0x01, # .Logical Maximum (1) 36 + 0x75, 0x01, # .Report Size (1) 37 + 0x95, 0x08, # .Report Count (8) 38 + 0x81, 0x02, # .Input (Data,Var,Abs) 39 + 0x75, 0x08, # .Report Size (8) 40 + 0x95, 0x01, # .Report Count (1) 41 + 0x81, 0x01, # .Input (Cnst,Arr,Abs) 42 + 0x75, 0x01, # .Report Size (1) 43 + 0x95, 0x05, # .Report Count (5) 44 + 0x05, 0x08, # .Usage Page (LEDs) 45 + 0x19, 0x01, # .Usage Minimum (1) 46 + 0x29, 0x05, # .Usage Maximum (5) 47 + 0x91, 0x02, # .Output (Data,Var,Abs) 48 + 0x75, 0x03, # .Report Size (3) 49 + 0x95, 0x01, # .Report Count (1) 50 + 0x91, 0x01, # .Output (Cnst,Arr,Abs) 51 + 0x75, 0x08, # .Report Size (8) 52 + 0x95, 0x06, # .Report Count (6) 53 + 0x15, 0x00, # .Logical Minimum (0) 54 + 0x26, 0xff, 0x00, # .Logical Maximum (255) 55 + 0x05, 0x07, # .Usage Page (Keyboard) 56 + 0x19, 0x00, # .Usage Minimum (0) 57 + 0x2a, 0xff, 0x00, # .Usage Maximum (255) 58 + 0x81, 0x00, # .Input (Data,Arr,Abs) 59 + 0xc0, # End Collection 60 + 0x05, 0x0c, # Usage Page (Consumer Devices) 61 + 0x09, 0x01, # Usage (Consumer Control) 62 + 0xa1, 0x01, # Collection (Application) 63 + 0x85, 0x47, # .Report ID (71) 64 + 0x05, 0x01, # .Usage Page (Generic Desktop) 65 + 0x09, 0x06, # .Usage (Keyboard) 66 + 0xa1, 0x02, # .Collection (Logical) 67 + 0x05, 0x06, # ..Usage Page (Generic Device Controls) 68 + 0x09, 0x20, # ..Usage (Battery Strength) 69 + 0x15, 0x00, # ..Logical Minimum (0) 70 + 0x26, 0xff, 0x00, # ..Logical Maximum (255) 71 + 0x75, 0x08, # ..Report Size (8) 72 + 0x95, 0x01, # ..Report Count (1) 73 + 0x81, 0x02, # ..Input (Data,Var,Abs) 74 + 0xc0, # .End Collection 75 + 0xc0, # End Collection 76 + 0x05, 0x0c, # Usage Page (Consumer Devices) 77 + 0x09, 0x01, # Usage (Consumer Control) 78 + 0xa1, 0x01, # Collection (Application) 79 + 0x85, 0x11, # .Report ID (17) 80 + 0x15, 0x00, # .Logical Minimum (0) 81 + 0x25, 0x01, # .Logical Maximum (1) 82 + 0x75, 0x01, # .Report Size (1) 83 + 0x95, 0x03, # .Report Count (3) 84 + 0x81, 0x01, # .Input (Cnst,Arr,Abs) 85 + 0x75, 0x01, # .Report Size (1) 86 + 0x95, 0x01, # .Report Count (1) 87 + 0x05, 0x0c, # .Usage Page (Consumer Devices) 88 + 0x09, 0xb8, # .Usage (Eject) 89 + 0x81, 0x02, # .Input (Data,Var,Abs) 90 + 0x06, 0xff, 0x00, # .Usage Page (Vendor Usage Page 0xff) 91 + 0x09, 0x03, # .Usage (Vendor Usage 0x03) 92 + 0x81, 0x02, # .Input (Data,Var,Abs) 93 + 0x75, 0x01, # .Report Size (1) 94 + 0x95, 0x03, # .Report Count (3) 95 + 0x81, 0x01, # .Input (Cnst,Arr,Abs) 96 + 0x05, 0x0c, # .Usage Page (Consumer Devices) 97 + 0x85, 0x12, # .Report ID (18) 98 + 0x15, 0x00, # .Logical Minimum (0) 99 + 0x25, 0x01, # .Logical Maximum (1) 100 + 0x75, 0x01, # .Report Size (1) 101 + 0x95, 0x01, # .Report Count (1) 102 + 0x09, 0xcd, # .Usage (Play/Pause) 103 + 0x81, 0x02, # .Input (Data,Var,Abs) 104 + 0x09, 0xb3, # .Usage (Fast Forward) 105 + 0x81, 0x02, # .Input (Data,Var,Abs) 106 + 0x09, 0xb4, # .Usage (Rewind) 107 + 0x81, 0x02, # .Input (Data,Var,Abs) 108 + 0x09, 0xb5, # .Usage (Scan Next Track) 109 + 0x81, 0x02, # .Input (Data,Var,Abs) 110 + 0x09, 0xb6, # .Usage (Scan Previous Track) 111 + 0x81, 0x02, # .Input (Data,Var,Abs) 112 + 0x81, 0x01, # .Input (Cnst,Arr,Abs) 113 + 0x81, 0x01, # .Input (Cnst,Arr,Abs) 114 + 0x81, 0x01, # .Input (Cnst,Arr,Abs) 115 + 0x85, 0x13, # .Report ID (19) 116 + 0x15, 0x00, # .Logical Minimum (0) 117 + 0x25, 0x01, # .Logical Maximum (1) 118 + 0x75, 0x01, # .Report Size (1) 119 + 0x95, 0x01, # .Report Count (1) 120 + 0x06, 0x01, 0xff, # .Usage Page (Vendor Usage Page 0xff01) 121 + 0x09, 0x0a, # .Usage (Vendor Usage 0x0a) 122 + 0x81, 0x02, # .Input (Data,Var,Abs) 123 + 0x06, 0x01, 0xff, # .Usage Page (Vendor Usage Page 0xff01) 124 + 0x09, 0x0c, # .Usage (Vendor Usage 0x0c) 125 + 0x81, 0x22, # .Input (Data,Var,Abs,NoPref) 126 + 0x75, 0x01, # .Report Size (1) 127 + 0x95, 0x06, # .Report Count (6) 128 + 0x81, 0x01, # .Input (Cnst,Arr,Abs) 129 + 0x85, 0x09, # .Report ID (9) 130 + 0x09, 0x0b, # .Usage (Vendor Usage 0x0b) 131 + 0x75, 0x08, # .Report Size (8) 132 + 0x95, 0x01, # .Report Count (1) 133 + 0xb1, 0x02, # .Feature (Data,Var,Abs) 134 + 0x75, 0x08, # .Report Size (8) 135 + 0x95, 0x02, # .Report Count (2) 136 + 0xb1, 0x01, # .Feature (Cnst,Arr,Abs) 137 + 0xc0, # End Collection 138 + ] 139 + # fmt: on 140 + 141 + def __init__( 142 + self, 143 + rdesc=report_descriptor, 144 + name="Apple Wireless Keyboard", 145 + input_info=(BusType.BLUETOOTH, 0x05AC, 0x0256), 146 + ): 147 + super().__init__(rdesc, name, input_info) 148 + self.default_reportID = 1 149 + 150 + def send_fn_state(self, state): 151 + data = KbdData() 152 + setattr(data, "0xff0003", state) 153 + r = self.create_report(data, reportID=17) 154 + self.call_input_event(r) 155 + return [r] 156 + 157 + 158 + class TestAppleKeyboard(TestArrayKeyboard): 159 + kernel_modules = [KERNEL_MODULE] 160 + 161 + def create_device(self): 162 + return AppleKeyboard() 163 + 164 + def test_single_function_key(self): 165 + """check for function key reliability.""" 166 + uhdev = self.uhdev 167 + evdev = uhdev.get_evdev() 168 + syn_event = self.syn_event 169 + 170 + r = uhdev.event(["F4"]) 171 + expected = [syn_event] 172 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 1)) 173 + events = uhdev.next_sync_events() 174 + self.debug_reports(r, uhdev, events) 175 + self.assertInputEventsIn(expected, events) 176 + assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1 177 + assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0 178 + 179 + r = uhdev.event([]) 180 + expected = [syn_event] 181 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 0)) 182 + events = uhdev.next_sync_events() 183 + self.debug_reports(r, uhdev, events) 184 + self.assertInputEventsIn(expected, events) 185 + assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 0 186 + 187 + def test_single_fn_function_key(self): 188 + """check for function key reliability with the fn key.""" 189 + uhdev = self.uhdev 190 + evdev = uhdev.get_evdev() 191 + syn_event = self.syn_event 192 + 193 + r = uhdev.send_fn_state(1) 194 + r.extend(uhdev.event(["F4"])) 195 + expected = [syn_event] 196 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 1)) 197 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1)) 198 + events = uhdev.next_sync_events() 199 + self.debug_reports(r, uhdev, events) 200 + self.assertInputEventsIn(expected, events) 201 + assert evdev.value[libevdev.EV_KEY.KEY_F4] == 1 202 + 203 + r = uhdev.event([]) 204 + expected = [syn_event] 205 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 0)) 206 + events = uhdev.next_sync_events() 207 + self.debug_reports(r, uhdev, events) 208 + self.assertInputEventsIn(expected, events) 209 + assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0 210 + assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1 211 + 212 + r = uhdev.send_fn_state(0) 213 + expected = [syn_event] 214 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0)) 215 + events = uhdev.next_sync_events() 216 + self.debug_reports(r, uhdev, events) 217 + self.assertInputEventsIn(expected, events) 218 + 219 + def test_single_fn_function_key_release_first(self): 220 + """check for function key reliability with the fn key.""" 221 + uhdev = self.uhdev 222 + evdev = uhdev.get_evdev() 223 + syn_event = self.syn_event 224 + 225 + r = uhdev.send_fn_state(1) 226 + r.extend(uhdev.event(["F4"])) 227 + expected = [syn_event] 228 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 1)) 229 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1)) 230 + events = uhdev.next_sync_events() 231 + self.debug_reports(r, uhdev, events) 232 + self.assertInputEventsIn(expected, events) 233 + assert evdev.value[libevdev.EV_KEY.KEY_F4] == 1 234 + 235 + r = uhdev.send_fn_state(0) 236 + expected = [syn_event] 237 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0)) 238 + events = uhdev.next_sync_events() 239 + self.debug_reports(r, uhdev, events) 240 + self.assertInputEventsIn(expected, events) 241 + 242 + r = uhdev.event([]) 243 + expected = [syn_event] 244 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 0)) 245 + events = uhdev.next_sync_events() 246 + self.debug_reports(r, uhdev, events) 247 + self.assertInputEventsIn(expected, events) 248 + assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0 249 + 250 + def test_single_fn_function_key_inverted(self): 251 + """check for function key reliability with the fn key.""" 252 + uhdev = self.uhdev 253 + evdev = uhdev.get_evdev() 254 + syn_event = self.syn_event 255 + 256 + r = uhdev.event(["F4"]) 257 + r.extend(uhdev.send_fn_state(1)) 258 + expected = [syn_event] 259 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 1)) 260 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1)) 261 + events = uhdev.next_sync_events() 262 + self.debug_reports(r, uhdev, events) 263 + self.assertInputEventsIn(expected, events) 264 + assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1 265 + 266 + r = uhdev.event([]) 267 + expected = [syn_event] 268 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 0)) 269 + events = uhdev.next_sync_events() 270 + self.debug_reports(r, uhdev, events) 271 + self.assertInputEventsIn(expected, events) 272 + assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 0 273 + assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1 274 + 275 + r = uhdev.send_fn_state(0) 276 + expected = [syn_event] 277 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0)) 278 + events = uhdev.next_sync_events() 279 + self.debug_reports(r, uhdev, events) 280 + self.assertInputEventsIn(expected, events) 281 + 282 + def test_multiple_fn_function_key_release_first(self): 283 + """check for function key reliability with the fn key.""" 284 + uhdev = self.uhdev 285 + evdev = uhdev.get_evdev() 286 + syn_event = self.syn_event 287 + 288 + r = uhdev.send_fn_state(1) 289 + r.extend(uhdev.event(["F4"])) 290 + r.extend(uhdev.event(["F4", "F6"])) 291 + expected = [syn_event] 292 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 1)) 293 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F6, 1)) 294 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1)) 295 + events = uhdev.next_sync_events() 296 + self.debug_reports(r, uhdev, events) 297 + self.assertInputEventsIn(expected, events) 298 + assert evdev.value[libevdev.EV_KEY.KEY_F4] == 1 299 + assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1 300 + assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1 301 + 302 + r = uhdev.event(["F6"]) 303 + expected = [syn_event] 304 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 0)) 305 + events = uhdev.next_sync_events() 306 + self.debug_reports(r, uhdev, events) 307 + self.assertInputEventsIn(expected, events) 308 + assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0 309 + assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1 310 + assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1 311 + 312 + r = uhdev.send_fn_state(0) 313 + expected = [syn_event] 314 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0)) 315 + events = uhdev.next_sync_events() 316 + self.debug_reports(r, uhdev, events) 317 + self.assertInputEventsIn(expected, events) 318 + assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0 319 + assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1 320 + assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0 321 + 322 + r = uhdev.event([]) 323 + expected = [syn_event] 324 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F6, 0)) 325 + events = uhdev.next_sync_events() 326 + self.debug_reports(r, uhdev, events) 327 + self.assertInputEventsIn(expected, events) 328 + assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0 329 + assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0 330 + assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0 331 + 332 + def test_multiple_fn_function_key_release_between(self): 333 + """check for function key reliability with the fn key.""" 334 + uhdev = self.uhdev 335 + evdev = uhdev.get_evdev() 336 + syn_event = self.syn_event 337 + 338 + # press F4 339 + r = uhdev.event(["F4"]) 340 + expected = [syn_event] 341 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 1)) 342 + events = uhdev.next_sync_events() 343 + self.debug_reports(r, uhdev, events) 344 + self.assertInputEventsIn(expected, events) 345 + assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0 346 + assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1 347 + assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0 348 + assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0 349 + assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0 350 + 351 + # press Fn key 352 + r = uhdev.send_fn_state(1) 353 + expected = [syn_event] 354 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1)) 355 + events = uhdev.next_sync_events() 356 + self.debug_reports(r, uhdev, events) 357 + self.assertInputEventsIn(expected, events) 358 + assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0 359 + assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1 360 + assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0 361 + assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0 362 + assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1 363 + 364 + # keep F4 and press F6 365 + r = uhdev.event(["F4", "F6"]) 366 + expected = [syn_event] 367 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F6, 1)) 368 + events = uhdev.next_sync_events() 369 + self.debug_reports(r, uhdev, events) 370 + self.assertInputEventsIn(expected, events) 371 + assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0 372 + assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1 373 + assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1 374 + assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0 375 + assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1 376 + 377 + # keep F4 and F6 378 + r = uhdev.event(["F4", "F6"]) 379 + expected = [] 380 + events = uhdev.next_sync_events() 381 + self.debug_reports(r, uhdev, events) 382 + self.assertInputEventsIn(expected, events) 383 + assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0 384 + assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1 385 + assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1 386 + assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0 387 + assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1 388 + 389 + # release Fn key and all keys 390 + r = uhdev.send_fn_state(0) 391 + r.extend(uhdev.event([])) 392 + expected = [syn_event] 393 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 0)) 394 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F6, 0)) 395 + events = uhdev.next_sync_events() 396 + self.debug_reports(r, uhdev, events) 397 + self.assertInputEventsIn(expected, events) 398 + assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0 399 + assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 0 400 + assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0 401 + assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0 402 + assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0 403 + 404 + def test_single_pageup_key_release_first(self): 405 + """check for function key reliability with the [page] up key.""" 406 + uhdev = self.uhdev 407 + evdev = uhdev.get_evdev() 408 + syn_event = self.syn_event 409 + 410 + r = uhdev.send_fn_state(1) 411 + r.extend(uhdev.event(["UpArrow"])) 412 + expected = [syn_event] 413 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_PAGEUP, 1)) 414 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1)) 415 + events = uhdev.next_sync_events() 416 + self.debug_reports(r, uhdev, events) 417 + self.assertInputEventsIn(expected, events) 418 + assert evdev.value[libevdev.EV_KEY.KEY_PAGEUP] == 1 419 + assert evdev.value[libevdev.EV_KEY.KEY_UP] == 0 420 + assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1 421 + 422 + r = uhdev.send_fn_state(0) 423 + expected = [syn_event] 424 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0)) 425 + events = uhdev.next_sync_events() 426 + self.debug_reports(r, uhdev, events) 427 + self.assertInputEventsIn(expected, events) 428 + assert evdev.value[libevdev.EV_KEY.KEY_PAGEUP] == 1 429 + assert evdev.value[libevdev.EV_KEY.KEY_UP] == 0 430 + assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0 431 + 432 + r = uhdev.event([]) 433 + expected = [syn_event] 434 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_PAGEUP, 0)) 435 + events = uhdev.next_sync_events() 436 + self.debug_reports(r, uhdev, events) 437 + self.assertInputEventsIn(expected, events) 438 + assert evdev.value[libevdev.EV_KEY.KEY_PAGEUP] == 0 439 + assert evdev.value[libevdev.EV_KEY.KEY_UP] == 0 440 + assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0
+209
tools/testing/selftests/hid/tests/test_gamepad.py
··· 1 + #!/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # -*- coding: utf-8 -*- 4 + # 5 + # Copyright (c) 2019 Benjamin Tissoires <benjamin.tissoires@gmail.com> 6 + # Copyright (c) 2019 Red Hat, Inc. 7 + # 8 + 9 + from . import base 10 + import libevdev 11 + import pytest 12 + 13 + from hidtools.device.base_gamepad import AsusGamepad, SaitekGamepad 14 + 15 + import logging 16 + 17 + logger = logging.getLogger("hidtools.test.gamepad") 18 + 19 + 20 + class BaseTest: 21 + class TestGamepad(base.BaseTestCase.TestUhid): 22 + @pytest.fixture(autouse=True) 23 + def send_initial_state(self): 24 + """send an empty report to initialize the axes""" 25 + uhdev = self.uhdev 26 + 27 + r = uhdev.event() 28 + events = uhdev.next_sync_events() 29 + self.debug_reports(r, uhdev, events) 30 + 31 + def assert_button(self, button): 32 + uhdev = self.uhdev 33 + evdev = uhdev.get_evdev() 34 + syn_event = self.syn_event 35 + 36 + buttons = {} 37 + key = libevdev.evbit(uhdev.buttons_map[button]) 38 + 39 + buttons[button] = True 40 + r = uhdev.event(buttons=buttons) 41 + expected_event = libevdev.InputEvent(key, 1) 42 + events = uhdev.next_sync_events() 43 + self.debug_reports(r, uhdev, events) 44 + self.assertInputEventsIn((syn_event, expected_event), events) 45 + assert evdev.value[key] == 1 46 + 47 + buttons[button] = False 48 + r = uhdev.event(buttons=buttons) 49 + expected_event = libevdev.InputEvent(key, 0) 50 + events = uhdev.next_sync_events() 51 + self.debug_reports(r, uhdev, events) 52 + self.assertInputEventsIn((syn_event, expected_event), events) 53 + assert evdev.value[key] == 0 54 + 55 + def test_buttons(self): 56 + """check for button reliability.""" 57 + uhdev = self.uhdev 58 + 59 + for b in uhdev.buttons: 60 + self.assert_button(b) 61 + 62 + def test_dual_buttons(self): 63 + """check for button reliability when pressing 2 buttons""" 64 + uhdev = self.uhdev 65 + evdev = uhdev.get_evdev() 66 + syn_event = self.syn_event 67 + 68 + # can change intended b1 b2 values 69 + b1 = uhdev.buttons[0] 70 + key1 = libevdev.evbit(uhdev.buttons_map[b1]) 71 + b2 = uhdev.buttons[1] 72 + key2 = libevdev.evbit(uhdev.buttons_map[b2]) 73 + 74 + buttons = {b1: True, b2: True} 75 + r = uhdev.event(buttons=buttons) 76 + expected_event0 = libevdev.InputEvent(key1, 1) 77 + expected_event1 = libevdev.InputEvent(key2, 1) 78 + events = uhdev.next_sync_events() 79 + self.debug_reports(r, uhdev, events) 80 + self.assertInputEventsIn( 81 + (syn_event, expected_event0, expected_event1), events 82 + ) 83 + assert evdev.value[key1] == 1 84 + assert evdev.value[key2] == 1 85 + 86 + buttons = {b1: False, b2: None} 87 + r = uhdev.event(buttons=buttons) 88 + expected_event = libevdev.InputEvent(key1, 0) 89 + events = uhdev.next_sync_events() 90 + self.debug_reports(r, uhdev, events) 91 + self.assertInputEventsIn((syn_event, expected_event), events) 92 + assert evdev.value[key1] == 0 93 + assert evdev.value[key2] == 1 94 + 95 + buttons = {b1: None, b2: False} 96 + r = uhdev.event(buttons=buttons) 97 + expected_event = libevdev.InputEvent(key2, 0) 98 + events = uhdev.next_sync_events() 99 + self.debug_reports(r, uhdev, events) 100 + self.assertInputEventsIn((syn_event, expected_event), events) 101 + assert evdev.value[key1] == 0 102 + assert evdev.value[key2] == 0 103 + 104 + def _get_libevdev_abs_events(self, which): 105 + """Returns which ABS_* evdev axes are expected for the given stick""" 106 + abs_map = self.uhdev.axes_map[which] 107 + 108 + x = abs_map["x"].evdev 109 + y = abs_map["y"].evdev 110 + 111 + assert x 112 + assert y 113 + 114 + return x, y 115 + 116 + def _test_joystick_press(self, which, data): 117 + uhdev = self.uhdev 118 + 119 + libevdev_axes = self._get_libevdev_abs_events(which) 120 + 121 + r = None 122 + if which == "left_stick": 123 + r = uhdev.event(left=data) 124 + else: 125 + r = uhdev.event(right=data) 126 + events = uhdev.next_sync_events() 127 + self.debug_reports(r, uhdev, events) 128 + 129 + for i, d in enumerate(data): 130 + if d is not None and d != 127: 131 + assert libevdev.InputEvent(libevdev_axes[i], d) in events 132 + else: 133 + assert libevdev.InputEvent(libevdev_axes[i]) not in events 134 + 135 + def test_left_joystick_press_left(self): 136 + """check for the left joystick reliability""" 137 + self._test_joystick_press("left_stick", (63, None)) 138 + self._test_joystick_press("left_stick", (0, 127)) 139 + 140 + def test_left_joystick_press_right(self): 141 + """check for the left joystick reliability""" 142 + self._test_joystick_press("left_stick", (191, 127)) 143 + self._test_joystick_press("left_stick", (255, None)) 144 + 145 + def test_left_joystick_press_up(self): 146 + """check for the left joystick reliability""" 147 + self._test_joystick_press("left_stick", (None, 63)) 148 + self._test_joystick_press("left_stick", (127, 0)) 149 + 150 + def test_left_joystick_press_down(self): 151 + """check for the left joystick reliability""" 152 + self._test_joystick_press("left_stick", (127, 191)) 153 + self._test_joystick_press("left_stick", (None, 255)) 154 + 155 + def test_right_joystick_press_left(self): 156 + """check for the right joystick reliability""" 157 + self._test_joystick_press("right_stick", (63, None)) 158 + self._test_joystick_press("right_stick", (0, 127)) 159 + 160 + def test_right_joystick_press_right(self): 161 + """check for the right joystick reliability""" 162 + self._test_joystick_press("right_stick", (191, 127)) 163 + self._test_joystick_press("right_stick", (255, None)) 164 + 165 + def test_right_joystick_press_up(self): 166 + """check for the right joystick reliability""" 167 + self._test_joystick_press("right_stick", (None, 63)) 168 + self._test_joystick_press("right_stick", (127, 0)) 169 + 170 + def test_right_joystick_press_down(self): 171 + """check for the right joystick reliability""" 172 + self._test_joystick_press("right_stick", (127, 191)) 173 + self._test_joystick_press("right_stick", (None, 255)) 174 + 175 + @pytest.mark.skip_if_uhdev( 176 + lambda uhdev: "Hat switch" not in uhdev.fields, 177 + "Device not compatible, missing Hat switch usage", 178 + ) 179 + @pytest.mark.parametrize( 180 + "hat_value,expected_evdev,evdev_value", 181 + [ 182 + (0, "ABS_HAT0Y", -1), 183 + (2, "ABS_HAT0X", 1), 184 + (4, "ABS_HAT0Y", 1), 185 + (6, "ABS_HAT0X", -1), 186 + ], 187 + ) 188 + def test_hat_switch(self, hat_value, expected_evdev, evdev_value): 189 + uhdev = self.uhdev 190 + 191 + r = uhdev.event(hat_switch=hat_value) 192 + events = uhdev.next_sync_events() 193 + self.debug_reports(r, uhdev, events) 194 + assert ( 195 + libevdev.InputEvent( 196 + libevdev.evbit("EV_ABS", expected_evdev), evdev_value 197 + ) 198 + in events 199 + ) 200 + 201 + 202 + class TestSaitekGamepad(BaseTest.TestGamepad): 203 + def create_device(self): 204 + return SaitekGamepad() 205 + 206 + 207 + class TestAsusGamepad(BaseTest.TestGamepad): 208 + def create_device(self): 209 + return AsusGamepad()
+154
tools/testing/selftests/hid/tests/test_hid_core.py
··· 1 + #!/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # -*- coding: utf-8 -*- 4 + # 5 + # Copyright (c) 2017 Benjamin Tissoires <benjamin.tissoires@gmail.com> 6 + # Copyright (c) 2017 Red Hat, Inc. 7 + # 8 + # This program is free software: you can redistribute it and/or modify 9 + # it under the terms of the GNU General Public License as published by 10 + # the Free Software Foundation; either version 2 of the License, or 11 + # (at your option) any later version. 12 + # 13 + # This program is distributed in the hope that it will be useful, 14 + # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 + # GNU General Public License for more details. 17 + # 18 + # You should have received a copy of the GNU General Public License 19 + # along with this program. If not, see <http://www.gnu.org/licenses/>. 20 + # 21 + 22 + # This is for generic devices 23 + 24 + from . import base 25 + import logging 26 + 27 + logger = logging.getLogger("hidtools.test.hid") 28 + 29 + 30 + class TestCollectionOverflow(base.BaseTestCase.TestUhid): 31 + """ 32 + Test class to test re-allocation of the HID collection stack in 33 + hid-core.c. 34 + """ 35 + 36 + def create_device(self): 37 + # fmt: off 38 + report_descriptor = [ 39 + 0x05, 0x01, # .Usage Page (Generic Desktop) 40 + 0x09, 0x02, # .Usage (Mouse) 41 + 0xa1, 0x01, # .Collection (Application) 42 + 0x09, 0x02, # ..Usage (Mouse) 43 + 0xa1, 0x02, # ..Collection (Logical) 44 + 0x09, 0x01, # ...Usage (Pointer) 45 + 0xa1, 0x00, # ...Collection (Physical) 46 + 0x05, 0x09, # ....Usage Page (Button) 47 + 0x19, 0x01, # ....Usage Minimum (1) 48 + 0x29, 0x03, # ....Usage Maximum (3) 49 + 0x15, 0x00, # ....Logical Minimum (0) 50 + 0x25, 0x01, # ....Logical Maximum (1) 51 + 0x75, 0x01, # ....Report Size (1) 52 + 0x95, 0x03, # ....Report Count (3) 53 + 0x81, 0x02, # ....Input (Data,Var,Abs) 54 + 0x75, 0x05, # ....Report Size (5) 55 + 0x95, 0x01, # ....Report Count (1) 56 + 0x81, 0x03, # ....Input (Cnst,Var,Abs) 57 + 0xa1, 0x02, # ....Collection (Logical) 58 + 0x09, 0x01, # .....Usage (Pointer) 59 + 0xa1, 0x02, # ....Collection (Logical) 60 + 0x09, 0x01, # .....Usage (Pointer) 61 + 0xa1, 0x02, # ....Collection (Logical) 62 + 0x09, 0x01, # .....Usage (Pointer) 63 + 0xa1, 0x02, # ....Collection (Logical) 64 + 0x09, 0x01, # .....Usage (Pointer) 65 + 0xa1, 0x02, # ....Collection (Logical) 66 + 0x09, 0x01, # .....Usage (Pointer) 67 + 0xa1, 0x02, # ....Collection (Logical) 68 + 0x09, 0x01, # .....Usage (Pointer) 69 + 0xa1, 0x02, # ....Collection (Logical) 70 + 0x09, 0x01, # .....Usage (Pointer) 71 + 0xa1, 0x02, # ....Collection (Logical) 72 + 0x09, 0x01, # .....Usage (Pointer) 73 + 0xa1, 0x02, # ....Collection (Logical) 74 + 0x09, 0x01, # .....Usage (Pointer) 75 + 0xa1, 0x02, # ....Collection (Logical) 76 + 0x09, 0x01, # .....Usage (Pointer) 77 + 0xa1, 0x02, # ....Collection (Logical) 78 + 0x09, 0x01, # .....Usage (Pointer) 79 + 0xa1, 0x02, # ....Collection (Logical) 80 + 0x09, 0x01, # .....Usage (Pointer) 81 + 0xa1, 0x02, # ....Collection (Logical) 82 + 0x09, 0x01, # .....Usage (Pointer) 83 + 0xa1, 0x02, # ....Collection (Logical) 84 + 0x09, 0x01, # .....Usage (Pointer) 85 + 0xa1, 0x02, # ....Collection (Logical) 86 + 0x09, 0x01, # .....Usage (Pointer) 87 + 0xa1, 0x02, # ....Collection (Logical) 88 + 0x09, 0x01, # .....Usage (Pointer) 89 + 0xa1, 0x02, # ....Collection (Logical) 90 + 0x09, 0x01, # .....Usage (Pointer) 91 + 0x05, 0x01, # .....Usage Page (Generic Desktop) 92 + 0x09, 0x30, # .....Usage (X) 93 + 0x09, 0x31, # .....Usage (Y) 94 + 0x15, 0x81, # .....Logical Minimum (-127) 95 + 0x25, 0x7f, # .....Logical Maximum (127) 96 + 0x75, 0x08, # .....Report Size (8) 97 + 0x95, 0x02, # .....Report Count (2) 98 + 0x81, 0x06, # .....Input (Data,Var,Rel) 99 + 0xa1, 0x02, # ...Collection (Logical) 100 + 0x85, 0x12, # ....Report ID (18) 101 + 0x09, 0x48, # ....Usage (Resolution Multiplier) 102 + 0x95, 0x01, # ....Report Count (1) 103 + 0x75, 0x02, # ....Report Size (2) 104 + 0x15, 0x00, # ....Logical Minimum (0) 105 + 0x25, 0x01, # ....Logical Maximum (1) 106 + 0x35, 0x01, # ....Physical Minimum (1) 107 + 0x45, 0x0c, # ....Physical Maximum (12) 108 + 0xb1, 0x02, # ....Feature (Data,Var,Abs) 109 + 0x85, 0x1a, # ....Report ID (26) 110 + 0x09, 0x38, # ....Usage (Wheel) 111 + 0x35, 0x00, # ....Physical Minimum (0) 112 + 0x45, 0x00, # ....Physical Maximum (0) 113 + 0x95, 0x01, # ....Report Count (1) 114 + 0x75, 0x10, # ....Report Size (16) 115 + 0x16, 0x01, 0x80, # ....Logical Minimum (-32767) 116 + 0x26, 0xff, 0x7f, # ....Logical Maximum (32767) 117 + 0x81, 0x06, # ....Input (Data,Var,Rel) 118 + 0xc0, # ...End Collection 119 + 0xc0, # ...End Collection 120 + 0xc0, # ...End Collection 121 + 0xc0, # ...End Collection 122 + 0xc0, # ...End Collection 123 + 0xc0, # ...End Collection 124 + 0xc0, # ...End Collection 125 + 0xc0, # ...End Collection 126 + 0xc0, # ...End Collection 127 + 0xc0, # ...End Collection 128 + 0xc0, # ...End Collection 129 + 0xc0, # ...End Collection 130 + 0xc0, # ...End Collection 131 + 0xc0, # ...End Collection 132 + 0xc0, # ...End Collection 133 + 0xc0, # ...End Collection 134 + 0xc0, # ...End Collection 135 + 0xc0, # ...End Collection 136 + 0xc0, # ...End Collection 137 + 0xc0, # ..End Collection 138 + 0xc0, # .End Collection 139 + ] 140 + # fmt: on 141 + return base.UHIDTestDevice( 142 + name=None, rdesc=report_descriptor, application="Mouse" 143 + ) 144 + 145 + def test_rdesc(self): 146 + """ 147 + This test can only check for negatives. If the kernel crashes, you 148 + know why. If this test passes, either the bug isn't present or just 149 + didn't get triggered. No way to know. 150 + 151 + For an explanation, see kernel patch 152 + HID: core: replace the collection tree pointers with indices 153 + """ 154 + pass
+166
tools/testing/selftests/hid/tests/test_ite_keyboard.py
··· 1 + #!/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # -*- coding: utf-8 -*- 4 + # 5 + # Copyright (c) 2020 Benjamin Tissoires <benjamin.tissoires@gmail.com> 6 + # Copyright (c) 2020 Red Hat, Inc. 7 + # 8 + 9 + from .test_keyboard import ArrayKeyboard, TestArrayKeyboard 10 + from hidtools.util import BusType 11 + 12 + import libevdev 13 + import logging 14 + 15 + logger = logging.getLogger("hidtools.test.ite-keyboard") 16 + 17 + KERNEL_MODULE = ("itetech", "hid_ite") 18 + 19 + 20 + class KbdData(object): 21 + pass 22 + 23 + 24 + # The ITE keyboards have an issue regarding the Wifi key: 25 + # nothing comes in when pressing the key, but we get a null 26 + # event on the key release. 27 + # This test covers this case. 28 + class ITEKeyboard(ArrayKeyboard): 29 + # fmt: off 30 + report_descriptor = [ 31 + 0x06, 0x85, 0xff, # Usage Page (Vendor Usage Page 0xff85) 32 + 0x09, 0x95, # Usage (Vendor Usage 0x95) 3 33 + 0xa1, 0x01, # Collection (Application) 5 34 + 0x85, 0x5a, # .Report ID (90) 7 35 + 0x09, 0x01, # .Usage (Vendor Usage 0x01) 9 36 + 0x15, 0x00, # .Logical Minimum (0) 11 37 + 0x26, 0xff, 0x00, # .Logical Maximum (255) 13 38 + 0x75, 0x08, # .Report Size (8) 16 39 + 0x95, 0x10, # .Report Count (16) 18 40 + 0xb1, 0x00, # .Feature (Data,Arr,Abs) 20 41 + 0xc0, # End Collection 22 42 + 0x05, 0x01, # Usage Page (Generic Desktop) 23 43 + 0x09, 0x06, # Usage (Keyboard) 25 44 + 0xa1, 0x01, # Collection (Application) 27 45 + 0x85, 0x01, # .Report ID (1) 29 46 + 0x75, 0x01, # .Report Size (1) 31 47 + 0x95, 0x08, # .Report Count (8) 33 48 + 0x05, 0x07, # .Usage Page (Keyboard) 35 49 + 0x19, 0xe0, # .Usage Minimum (224) 37 50 + 0x29, 0xe7, # .Usage Maximum (231) 39 51 + 0x15, 0x00, # .Logical Minimum (0) 41 52 + 0x25, 0x01, # .Logical Maximum (1) 43 53 + 0x81, 0x02, # .Input (Data,Var,Abs) 45 54 + 0x95, 0x01, # .Report Count (1) 47 55 + 0x75, 0x08, # .Report Size (8) 49 56 + 0x81, 0x03, # .Input (Cnst,Var,Abs) 51 57 + 0x95, 0x05, # .Report Count (5) 53 58 + 0x75, 0x01, # .Report Size (1) 55 59 + 0x05, 0x08, # .Usage Page (LEDs) 57 60 + 0x19, 0x01, # .Usage Minimum (1) 59 61 + 0x29, 0x05, # .Usage Maximum (5) 61 62 + 0x91, 0x02, # .Output (Data,Var,Abs) 63 63 + 0x95, 0x01, # .Report Count (1) 65 64 + 0x75, 0x03, # .Report Size (3) 67 65 + 0x91, 0x03, # .Output (Cnst,Var,Abs) 69 66 + 0x95, 0x06, # .Report Count (6) 71 67 + 0x75, 0x08, # .Report Size (8) 73 68 + 0x15, 0x00, # .Logical Minimum (0) 75 69 + 0x26, 0xff, 0x00, # .Logical Maximum (255) 77 70 + 0x05, 0x07, # .Usage Page (Keyboard) 80 71 + 0x19, 0x00, # .Usage Minimum (0) 82 72 + 0x2a, 0xff, 0x00, # .Usage Maximum (255) 84 73 + 0x81, 0x00, # .Input (Data,Arr,Abs) 87 74 + 0xc0, # End Collection 89 75 + 0x05, 0x0c, # Usage Page (Consumer Devices) 90 76 + 0x09, 0x01, # Usage (Consumer Control) 92 77 + 0xa1, 0x01, # Collection (Application) 94 78 + 0x85, 0x02, # .Report ID (2) 96 79 + 0x19, 0x00, # .Usage Minimum (0) 98 80 + 0x2a, 0x3c, 0x02, # .Usage Maximum (572) 100 81 + 0x15, 0x00, # .Logical Minimum (0) 103 82 + 0x26, 0x3c, 0x02, # .Logical Maximum (572) 105 83 + 0x75, 0x10, # .Report Size (16) 108 84 + 0x95, 0x01, # .Report Count (1) 110 85 + 0x81, 0x00, # .Input (Data,Arr,Abs) 112 86 + 0xc0, # End Collection 114 87 + 0x05, 0x01, # Usage Page (Generic Desktop) 115 88 + 0x09, 0x0c, # Usage (Wireless Radio Controls) 117 89 + 0xa1, 0x01, # Collection (Application) 119 90 + 0x85, 0x03, # .Report ID (3) 121 91 + 0x15, 0x00, # .Logical Minimum (0) 123 92 + 0x25, 0x01, # .Logical Maximum (1) 125 93 + 0x09, 0xc6, # .Usage (Wireless Radio Button) 127 94 + 0x95, 0x01, # .Report Count (1) 129 95 + 0x75, 0x01, # .Report Size (1) 131 96 + 0x81, 0x06, # .Input (Data,Var,Rel) 133 97 + 0x75, 0x07, # .Report Size (7) 135 98 + 0x81, 0x03, # .Input (Cnst,Var,Abs) 137 99 + 0xc0, # End Collection 139 100 + 0x05, 0x88, # Usage Page (Vendor Usage Page 0x88) 140 101 + 0x09, 0x01, # Usage (Vendor Usage 0x01) 142 102 + 0xa1, 0x01, # Collection (Application) 144 103 + 0x85, 0x04, # .Report ID (4) 146 104 + 0x19, 0x00, # .Usage Minimum (0) 148 105 + 0x2a, 0xff, 0xff, # .Usage Maximum (65535) 150 106 + 0x15, 0x00, # .Logical Minimum (0) 153 107 + 0x26, 0xff, 0xff, # .Logical Maximum (65535) 155 108 + 0x75, 0x08, # .Report Size (8) 158 109 + 0x95, 0x02, # .Report Count (2) 160 110 + 0x81, 0x02, # .Input (Data,Var,Abs) 162 111 + 0xc0, # End Collection 164 112 + 0x05, 0x01, # Usage Page (Generic Desktop) 165 113 + 0x09, 0x80, # Usage (System Control) 167 114 + 0xa1, 0x01, # Collection (Application) 169 115 + 0x85, 0x05, # .Report ID (5) 171 116 + 0x19, 0x81, # .Usage Minimum (129) 173 117 + 0x29, 0x83, # .Usage Maximum (131) 175 118 + 0x15, 0x00, # .Logical Minimum (0) 177 119 + 0x25, 0x01, # .Logical Maximum (1) 179 120 + 0x95, 0x08, # .Report Count (8) 181 121 + 0x75, 0x01, # .Report Size (1) 183 122 + 0x81, 0x02, # .Input (Data,Var,Abs) 185 123 + 0xc0, # End Collection 187 124 + ] 125 + # fmt: on 126 + 127 + def __init__( 128 + self, 129 + rdesc=report_descriptor, 130 + name=None, 131 + input_info=(BusType.USB, 0x06CB, 0x2968), 132 + ): 133 + super().__init__(rdesc, name, input_info) 134 + 135 + def event(self, keys, reportID=None, application=None): 136 + application = application or "Keyboard" 137 + return super().event(keys, reportID, application) 138 + 139 + 140 + class TestITEKeyboard(TestArrayKeyboard): 141 + kernel_modules = [KERNEL_MODULE] 142 + 143 + def create_device(self): 144 + return ITEKeyboard() 145 + 146 + def test_wifi_key(self): 147 + uhdev = self.uhdev 148 + syn_event = self.syn_event 149 + 150 + # the following sends a 'release' event on the Wifi key. 151 + # the kernel is supposed to translate this into Wifi key 152 + # down and up 153 + r = [0x03, 0x00] 154 + uhdev.call_input_event(r) 155 + expected = [syn_event] 156 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_RFKILL, 1)) 157 + events = uhdev.next_sync_events() 158 + self.debug_reports([r], uhdev, events) 159 + self.assertInputEventsIn(expected, events) 160 + 161 + expected = [syn_event] 162 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_RFKILL, 0)) 163 + # the kernel sends the two down/up key events in a batch, no need to 164 + # call events = uhdev.next_sync_events() 165 + self.debug_reports([], uhdev, events) 166 + self.assertInputEventsIn(expected, events)
+485
tools/testing/selftests/hid/tests/test_keyboard.py
··· 1 + #!/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # -*- coding: utf-8 -*- 4 + # 5 + # Copyright (c) 2018 Benjamin Tissoires <benjamin.tissoires@gmail.com> 6 + # Copyright (c) 2018 Red Hat, Inc. 7 + # 8 + 9 + from . import base 10 + import hidtools.hid 11 + import libevdev 12 + import logging 13 + 14 + logger = logging.getLogger("hidtools.test.keyboard") 15 + 16 + 17 + class InvalidHIDCommunication(Exception): 18 + pass 19 + 20 + 21 + class KeyboardData(object): 22 + pass 23 + 24 + 25 + class BaseKeyboard(base.UHIDTestDevice): 26 + def __init__(self, rdesc, name=None, input_info=None): 27 + assert rdesc is not None 28 + super().__init__(name, "Key", input_info=input_info, rdesc=rdesc) 29 + self.keystates = {} 30 + 31 + def _update_key_state(self, keys): 32 + """ 33 + Update the internal state of keys with the new state given. 34 + 35 + :param key: a tuple of chars for the currently pressed keys. 36 + """ 37 + # First remove the already released keys 38 + unused_keys = [k for k, v in self.keystates.items() if not v] 39 + for key in unused_keys: 40 + del self.keystates[key] 41 + 42 + # self.keystates contains now the list of currently pressed keys, 43 + # release them... 44 + for key in self.keystates.keys(): 45 + self.keystates[key] = False 46 + 47 + # ...and press those that are in parameter 48 + for key in keys: 49 + self.keystates[key] = True 50 + 51 + def _create_report_data(self): 52 + keyboard = KeyboardData() 53 + for key, value in self.keystates.items(): 54 + key = key.replace(" ", "").lower() 55 + setattr(keyboard, key, value) 56 + return keyboard 57 + 58 + def create_array_report(self, keys, reportID=None, application=None): 59 + """ 60 + Return an input report for this device. 61 + 62 + :param keys: a tuple of chars for the pressed keys. The class maintains 63 + the list of currently pressed keys, so to release a key, the caller 64 + needs to call again this function without the key in this tuple. 65 + :param reportID: the numeric report ID for this report, if needed 66 + """ 67 + self._update_key_state(keys) 68 + reportID = reportID or self.default_reportID 69 + 70 + keyboard = self._create_report_data() 71 + return self.create_report(keyboard, reportID=reportID, application=application) 72 + 73 + def event(self, keys, reportID=None, application=None): 74 + """ 75 + Send an input event on the default report ID. 76 + 77 + :param keys: a tuple of chars for the pressed keys. The class maintains 78 + the list of currently pressed keys, so to release a key, the caller 79 + needs to call again this function without the key in this tuple. 80 + """ 81 + r = self.create_array_report(keys, reportID, application) 82 + self.call_input_event(r) 83 + return [r] 84 + 85 + 86 + class PlainKeyboard(BaseKeyboard): 87 + # fmt: off 88 + report_descriptor = [ 89 + 0x05, 0x01, # Usage Page (Generic Desktop) 90 + 0x09, 0x06, # Usage (Keyboard) 91 + 0xa1, 0x01, # Collection (Application) 92 + 0x85, 0x01, # .Report ID (1) 93 + 0x05, 0x07, # .Usage Page (Keyboard) 94 + 0x19, 0xe0, # .Usage Minimum (224) 95 + 0x29, 0xe7, # .Usage Maximum (231) 96 + 0x15, 0x00, # .Logical Minimum (0) 97 + 0x25, 0x01, # .Logical Maximum (1) 98 + 0x75, 0x01, # .Report Size (1) 99 + 0x95, 0x08, # .Report Count (8) 100 + 0x81, 0x02, # .Input (Data,Var,Abs) 101 + 0x19, 0x00, # .Usage Minimum (0) 102 + 0x29, 0x97, # .Usage Maximum (151) 103 + 0x15, 0x00, # .Logical Minimum (0) 104 + 0x25, 0x01, # .Logical Maximum (1) 105 + 0x75, 0x01, # .Report Size (1) 106 + 0x95, 0x98, # .Report Count (152) 107 + 0x81, 0x02, # .Input (Data,Var,Abs) 108 + 0xc0, # End Collection 109 + ] 110 + # fmt: on 111 + 112 + def __init__(self, rdesc=report_descriptor, name=None, input_info=None): 113 + super().__init__(rdesc, name, input_info) 114 + self.default_reportID = 1 115 + 116 + 117 + class ArrayKeyboard(BaseKeyboard): 118 + # fmt: off 119 + report_descriptor = [ 120 + 0x05, 0x01, # Usage Page (Generic Desktop) 121 + 0x09, 0x06, # Usage (Keyboard) 122 + 0xa1, 0x01, # Collection (Application) 123 + 0x05, 0x07, # .Usage Page (Keyboard) 124 + 0x19, 0xe0, # .Usage Minimum (224) 125 + 0x29, 0xe7, # .Usage Maximum (231) 126 + 0x15, 0x00, # .Logical Minimum (0) 127 + 0x25, 0x01, # .Logical Maximum (1) 128 + 0x75, 0x01, # .Report Size (1) 129 + 0x95, 0x08, # .Report Count (8) 130 + 0x81, 0x02, # .Input (Data,Var,Abs) 131 + 0x95, 0x06, # .Report Count (6) 132 + 0x75, 0x08, # .Report Size (8) 133 + 0x15, 0x00, # .Logical Minimum (0) 134 + 0x26, 0xa4, 0x00, # .Logical Maximum (164) 135 + 0x05, 0x07, # .Usage Page (Keyboard) 136 + 0x19, 0x00, # .Usage Minimum (0) 137 + 0x29, 0xa4, # .Usage Maximum (164) 138 + 0x81, 0x00, # .Input (Data,Arr,Abs) 139 + 0xc0, # End Collection 140 + ] 141 + # fmt: on 142 + 143 + def __init__(self, rdesc=report_descriptor, name=None, input_info=None): 144 + super().__init__(rdesc, name, input_info) 145 + 146 + def _create_report_data(self): 147 + data = KeyboardData() 148 + array = [] 149 + 150 + hut = hidtools.hut.HUT 151 + 152 + # strip modifiers from the array 153 + for k, v in self.keystates.items(): 154 + # we ignore depressed keys 155 + if not v: 156 + continue 157 + 158 + usage = hut[0x07].from_name[k].usage 159 + if usage >= 224 and usage <= 231: 160 + # modifier 161 + setattr(data, k.lower(), 1) 162 + else: 163 + array.append(k) 164 + 165 + # if array length is bigger than 6, report ErrorRollOver 166 + if len(array) > 6: 167 + array = ["ErrorRollOver"] * 6 168 + 169 + data.keyboard = array 170 + return data 171 + 172 + 173 + class LEDKeyboard(ArrayKeyboard): 174 + # fmt: off 175 + report_descriptor = [ 176 + 0x05, 0x01, # Usage Page (Generic Desktop) 177 + 0x09, 0x06, # Usage (Keyboard) 178 + 0xa1, 0x01, # Collection (Application) 179 + 0x05, 0x07, # .Usage Page (Keyboard) 180 + 0x19, 0xe0, # .Usage Minimum (224) 181 + 0x29, 0xe7, # .Usage Maximum (231) 182 + 0x15, 0x00, # .Logical Minimum (0) 183 + 0x25, 0x01, # .Logical Maximum (1) 184 + 0x75, 0x01, # .Report Size (1) 185 + 0x95, 0x08, # .Report Count (8) 186 + 0x81, 0x02, # .Input (Data,Var,Abs) 187 + 0x95, 0x01, # .Report Count (1) 188 + 0x75, 0x08, # .Report Size (8) 189 + 0x81, 0x01, # .Input (Cnst,Arr,Abs) 190 + 0x95, 0x05, # .Report Count (5) 191 + 0x75, 0x01, # .Report Size (1) 192 + 0x05, 0x08, # .Usage Page (LEDs) 193 + 0x19, 0x01, # .Usage Minimum (1) 194 + 0x29, 0x05, # .Usage Maximum (5) 195 + 0x91, 0x02, # .Output (Data,Var,Abs) 196 + 0x95, 0x01, # .Report Count (1) 197 + 0x75, 0x03, # .Report Size (3) 198 + 0x91, 0x01, # .Output (Cnst,Arr,Abs) 199 + 0x95, 0x06, # .Report Count (6) 200 + 0x75, 0x08, # .Report Size (8) 201 + 0x15, 0x00, # .Logical Minimum (0) 202 + 0x26, 0xa4, 0x00, # .Logical Maximum (164) 203 + 0x05, 0x07, # .Usage Page (Keyboard) 204 + 0x19, 0x00, # .Usage Minimum (0) 205 + 0x29, 0xa4, # .Usage Maximum (164) 206 + 0x81, 0x00, # .Input (Data,Arr,Abs) 207 + 0xc0, # End Collection 208 + ] 209 + # fmt: on 210 + 211 + def __init__(self, rdesc=report_descriptor, name=None, input_info=None): 212 + super().__init__(rdesc, name, input_info) 213 + 214 + 215 + # Some Primax manufactured keyboards set the Usage Page after having defined 216 + # some local Usages. It relies on the fact that the specification states that 217 + # Usages are to be concatenated with Usage Pages upon finding a Main item (see 218 + # 6.2.2.8). This test covers this case. 219 + class PrimaxKeyboard(ArrayKeyboard): 220 + # fmt: off 221 + report_descriptor = [ 222 + 0x05, 0x01, # Usage Page (Generic Desktop) 223 + 0x09, 0x06, # Usage (Keyboard) 224 + 0xA1, 0x01, # Collection (Application) 225 + 0x05, 0x07, # .Usage Page (Keyboard) 226 + 0x19, 0xE0, # .Usage Minimum (224) 227 + 0x29, 0xE7, # .Usage Maximum (231) 228 + 0x15, 0x00, # .Logical Minimum (0) 229 + 0x25, 0x01, # .Logical Maximum (1) 230 + 0x75, 0x01, # .Report Size (1) 231 + 0x95, 0x08, # .Report Count (8) 232 + 0x81, 0x02, # .Input (Data,Var,Abs) 233 + 0x75, 0x08, # .Report Size (8) 234 + 0x95, 0x01, # .Report Count (1) 235 + 0x81, 0x01, # .Input (Data,Var,Abs) 236 + 0x05, 0x08, # .Usage Page (LEDs) 237 + 0x19, 0x01, # .Usage Minimum (1) 238 + 0x29, 0x03, # .Usage Maximum (3) 239 + 0x75, 0x01, # .Report Size (1) 240 + 0x95, 0x03, # .Report Count (3) 241 + 0x91, 0x02, # .Output (Data,Var,Abs) 242 + 0x95, 0x01, # .Report Count (1) 243 + 0x75, 0x05, # .Report Size (5) 244 + 0x91, 0x01, # .Output (Constant) 245 + 0x15, 0x00, # .Logical Minimum (0) 246 + 0x26, 0xFF, 0x00, # .Logical Maximum (255) 247 + 0x19, 0x00, # .Usage Minimum (0) 248 + 0x2A, 0xFF, 0x00, # .Usage Maximum (255) 249 + 0x05, 0x07, # .Usage Page (Keyboard) 250 + 0x75, 0x08, # .Report Size (8) 251 + 0x95, 0x06, # .Report Count (6) 252 + 0x81, 0x00, # .Input (Data,Arr,Abs) 253 + 0xC0, # End Collection 254 + ] 255 + # fmt: on 256 + 257 + def __init__(self, rdesc=report_descriptor, name=None, input_info=None): 258 + super().__init__(rdesc, name, input_info) 259 + 260 + 261 + class BaseTest: 262 + class TestKeyboard(base.BaseTestCase.TestUhid): 263 + def test_single_key(self): 264 + """check for key reliability.""" 265 + uhdev = self.uhdev 266 + evdev = uhdev.get_evdev() 267 + syn_event = self.syn_event 268 + 269 + r = uhdev.event(["a and A"]) 270 + expected = [syn_event] 271 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_A, 1)) 272 + events = uhdev.next_sync_events() 273 + self.debug_reports(r, uhdev, events) 274 + self.assertInputEventsIn(expected, events) 275 + assert evdev.value[libevdev.EV_KEY.KEY_A] == 1 276 + 277 + r = uhdev.event([]) 278 + expected = [syn_event] 279 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_A, 0)) 280 + events = uhdev.next_sync_events() 281 + self.debug_reports(r, uhdev, events) 282 + self.assertInputEventsIn(expected, events) 283 + assert evdev.value[libevdev.EV_KEY.KEY_A] == 0 284 + 285 + def test_two_keys(self): 286 + uhdev = self.uhdev 287 + evdev = uhdev.get_evdev() 288 + syn_event = self.syn_event 289 + 290 + r = uhdev.event(["a and A", "q and Q"]) 291 + expected = [syn_event] 292 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_A, 1)) 293 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_Q, 1)) 294 + events = uhdev.next_sync_events() 295 + self.debug_reports(r, uhdev, events) 296 + self.assertInputEventsIn(expected, events) 297 + assert evdev.value[libevdev.EV_KEY.KEY_A] == 1 298 + 299 + r = uhdev.event([]) 300 + expected = [syn_event] 301 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_A, 0)) 302 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_Q, 0)) 303 + events = uhdev.next_sync_events() 304 + self.debug_reports(r, uhdev, events) 305 + self.assertInputEventsIn(expected, events) 306 + assert evdev.value[libevdev.EV_KEY.KEY_A] == 0 307 + assert evdev.value[libevdev.EV_KEY.KEY_Q] == 0 308 + 309 + r = uhdev.event(["c and C"]) 310 + expected = [syn_event] 311 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_C, 1)) 312 + events = uhdev.next_sync_events() 313 + self.debug_reports(r, uhdev, events) 314 + self.assertInputEventsIn(expected, events) 315 + assert evdev.value[libevdev.EV_KEY.KEY_C] == 1 316 + 317 + r = uhdev.event(["c and C", "Spacebar"]) 318 + expected = [syn_event] 319 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_SPACE, 1)) 320 + events = uhdev.next_sync_events() 321 + self.debug_reports(r, uhdev, events) 322 + assert libevdev.InputEvent(libevdev.EV_KEY.KEY_C) not in events 323 + self.assertInputEventsIn(expected, events) 324 + assert evdev.value[libevdev.EV_KEY.KEY_C] == 1 325 + assert evdev.value[libevdev.EV_KEY.KEY_SPACE] == 1 326 + 327 + r = uhdev.event(["Spacebar"]) 328 + expected = [syn_event] 329 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_C, 0)) 330 + events = uhdev.next_sync_events() 331 + self.debug_reports(r, uhdev, events) 332 + assert libevdev.InputEvent(libevdev.EV_KEY.KEY_SPACE) not in events 333 + self.assertInputEventsIn(expected, events) 334 + assert evdev.value[libevdev.EV_KEY.KEY_C] == 0 335 + assert evdev.value[libevdev.EV_KEY.KEY_SPACE] == 1 336 + 337 + r = uhdev.event([]) 338 + expected = [syn_event] 339 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_SPACE, 0)) 340 + events = uhdev.next_sync_events() 341 + self.debug_reports(r, uhdev, events) 342 + self.assertInputEventsIn(expected, events) 343 + assert evdev.value[libevdev.EV_KEY.KEY_SPACE] == 0 344 + 345 + def test_modifiers(self): 346 + # ctrl-alt-del would be very nice :) 347 + uhdev = self.uhdev 348 + syn_event = self.syn_event 349 + 350 + r = uhdev.event(["LeftControl", "LeftShift", "= and +"]) 351 + expected = [syn_event] 352 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_LEFTCTRL, 1)) 353 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_LEFTSHIFT, 1)) 354 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_EQUAL, 1)) 355 + events = uhdev.next_sync_events() 356 + self.debug_reports(r, uhdev, events) 357 + self.assertInputEventsIn(expected, events) 358 + 359 + 360 + class TestPlainKeyboard(BaseTest.TestKeyboard): 361 + def create_device(self): 362 + return PlainKeyboard() 363 + 364 + def test_10_keys(self): 365 + uhdev = self.uhdev 366 + syn_event = self.syn_event 367 + 368 + r = uhdev.event( 369 + [ 370 + "1 and !", 371 + "2 and @", 372 + "3 and #", 373 + "4 and $", 374 + "5 and %", 375 + "6 and ^", 376 + "7 and &", 377 + "8 and *", 378 + "9 and (", 379 + "0 and )", 380 + ] 381 + ) 382 + expected = [syn_event] 383 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_0, 1)) 384 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_1, 1)) 385 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_2, 1)) 386 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_3, 1)) 387 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_4, 1)) 388 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_5, 1)) 389 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_6, 1)) 390 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_7, 1)) 391 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_8, 1)) 392 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_9, 1)) 393 + events = uhdev.next_sync_events() 394 + self.debug_reports(r, uhdev, events) 395 + self.assertInputEventsIn(expected, events) 396 + 397 + r = uhdev.event([]) 398 + expected = [syn_event] 399 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_0, 0)) 400 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_1, 0)) 401 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_2, 0)) 402 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_3, 0)) 403 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_4, 0)) 404 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_5, 0)) 405 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_6, 0)) 406 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_7, 0)) 407 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_8, 0)) 408 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_9, 0)) 409 + events = uhdev.next_sync_events() 410 + self.debug_reports(r, uhdev, events) 411 + self.assertInputEventsIn(expected, events) 412 + 413 + 414 + class TestArrayKeyboard(BaseTest.TestKeyboard): 415 + def create_device(self): 416 + return ArrayKeyboard() 417 + 418 + def test_10_keys(self): 419 + uhdev = self.uhdev 420 + syn_event = self.syn_event 421 + 422 + r = uhdev.event( 423 + [ 424 + "1 and !", 425 + "2 and @", 426 + "3 and #", 427 + "4 and $", 428 + "5 and %", 429 + "6 and ^", 430 + ] 431 + ) 432 + expected = [syn_event] 433 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_1, 1)) 434 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_2, 1)) 435 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_3, 1)) 436 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_4, 1)) 437 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_5, 1)) 438 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_6, 1)) 439 + events = uhdev.next_sync_events() 440 + 441 + self.debug_reports(r, uhdev, events) 442 + self.assertInputEventsIn(expected, events) 443 + 444 + # ErrRollOver 445 + r = uhdev.event( 446 + [ 447 + "1 and !", 448 + "2 and @", 449 + "3 and #", 450 + "4 and $", 451 + "5 and %", 452 + "6 and ^", 453 + "7 and &", 454 + "8 and *", 455 + "9 and (", 456 + "0 and )", 457 + ] 458 + ) 459 + events = uhdev.next_sync_events() 460 + 461 + self.debug_reports(r, uhdev, events) 462 + 463 + assert len(events) == 0 464 + 465 + r = uhdev.event([]) 466 + expected = [syn_event] 467 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_1, 0)) 468 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_2, 0)) 469 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_3, 0)) 470 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_4, 0)) 471 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_5, 0)) 472 + expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_6, 0)) 473 + events = uhdev.next_sync_events() 474 + self.debug_reports(r, uhdev, events) 475 + self.assertInputEventsIn(expected, events) 476 + 477 + 478 + class TestLEDKeyboard(BaseTest.TestKeyboard): 479 + def create_device(self): 480 + return LEDKeyboard() 481 + 482 + 483 + class TestPrimaxKeyboard(BaseTest.TestKeyboard): 484 + def create_device(self): 485 + return PrimaxKeyboard()
+977
tools/testing/selftests/hid/tests/test_mouse.py
··· 1 + #!/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # -*- coding: utf-8 -*- 4 + # 5 + # Copyright (c) 2017 Benjamin Tissoires <benjamin.tissoires@gmail.com> 6 + # Copyright (c) 2017 Red Hat, Inc. 7 + # 8 + 9 + from . import base 10 + import hidtools.hid 11 + from hidtools.util import BusType 12 + import libevdev 13 + import logging 14 + import pytest 15 + 16 + logger = logging.getLogger("hidtools.test.mouse") 17 + 18 + # workaround https://gitlab.freedesktop.org/libevdev/python-libevdev/issues/6 19 + try: 20 + libevdev.EV_REL.REL_WHEEL_HI_RES 21 + except AttributeError: 22 + libevdev.EV_REL.REL_WHEEL_HI_RES = libevdev.EV_REL.REL_0B 23 + libevdev.EV_REL.REL_HWHEEL_HI_RES = libevdev.EV_REL.REL_0C 24 + 25 + 26 + class InvalidHIDCommunication(Exception): 27 + pass 28 + 29 + 30 + class MouseData(object): 31 + pass 32 + 33 + 34 + class BaseMouse(base.UHIDTestDevice): 35 + def __init__(self, rdesc, name=None, input_info=None): 36 + assert rdesc is not None 37 + super().__init__(name, "Mouse", input_info=input_info, rdesc=rdesc) 38 + self.left = False 39 + self.right = False 40 + self.middle = False 41 + 42 + def create_report(self, x, y, buttons=None, wheels=None, reportID=None): 43 + """ 44 + Return an input report for this device. 45 + 46 + :param x: relative x 47 + :param y: relative y 48 + :param buttons: a (l, r, m) tuple of bools for the button states, 49 + where ``None`` is "leave unchanged" 50 + :param wheels: a single value for the vertical wheel or a (vertical, horizontal) tuple for 51 + the two wheels 52 + :param reportID: the numeric report ID for this report, if needed 53 + """ 54 + if buttons is not None: 55 + l, r, m = buttons 56 + if l is not None: 57 + self.left = l 58 + if r is not None: 59 + self.right = r 60 + if m is not None: 61 + self.middle = m 62 + left = self.left 63 + right = self.right 64 + middle = self.middle 65 + # Note: the BaseMouse doesn't actually have a wheel but the 66 + # create_report magic only fills in those fields exist, so let's 67 + # make this generic here. 68 + wheel, acpan = 0, 0 69 + if wheels is not None: 70 + if isinstance(wheels, tuple): 71 + wheel = wheels[0] 72 + acpan = wheels[1] 73 + else: 74 + wheel = wheels 75 + 76 + reportID = reportID or self.default_reportID 77 + 78 + mouse = MouseData() 79 + mouse.b1 = int(left) 80 + mouse.b2 = int(right) 81 + mouse.b3 = int(middle) 82 + mouse.x = x 83 + mouse.y = y 84 + mouse.wheel = wheel 85 + mouse.acpan = acpan 86 + return super().create_report(mouse, reportID=reportID) 87 + 88 + def event(self, x, y, buttons=None, wheels=None): 89 + """ 90 + Send an input event on the default report ID. 91 + 92 + :param x: relative x 93 + :param y: relative y 94 + :param buttons: a (l, r, m) tuple of bools for the button states, 95 + where ``None`` is "leave unchanged" 96 + :param wheels: a single value for the vertical wheel or a (vertical, horizontal) tuple for 97 + the two wheels 98 + """ 99 + r = self.create_report(x, y, buttons, wheels) 100 + self.call_input_event(r) 101 + return [r] 102 + 103 + 104 + class ButtonMouse(BaseMouse): 105 + # fmt: off 106 + report_descriptor = [ 107 + 0x05, 0x01, # .Usage Page (Generic Desktop) 0 108 + 0x09, 0x02, # .Usage (Mouse) 2 109 + 0xa1, 0x01, # .Collection (Application) 4 110 + 0x09, 0x02, # ..Usage (Mouse) 6 111 + 0xa1, 0x02, # ..Collection (Logical) 8 112 + 0x09, 0x01, # ...Usage (Pointer) 10 113 + 0xa1, 0x00, # ...Collection (Physical) 12 114 + 0x05, 0x09, # ....Usage Page (Button) 14 115 + 0x19, 0x01, # ....Usage Minimum (1) 16 116 + 0x29, 0x03, # ....Usage Maximum (3) 18 117 + 0x15, 0x00, # ....Logical Minimum (0) 20 118 + 0x25, 0x01, # ....Logical Maximum (1) 22 119 + 0x75, 0x01, # ....Report Size (1) 24 120 + 0x95, 0x03, # ....Report Count (3) 26 121 + 0x81, 0x02, # ....Input (Data,Var,Abs) 28 122 + 0x75, 0x05, # ....Report Size (5) 30 123 + 0x95, 0x01, # ....Report Count (1) 32 124 + 0x81, 0x03, # ....Input (Cnst,Var,Abs) 34 125 + 0x05, 0x01, # ....Usage Page (Generic Desktop) 36 126 + 0x09, 0x30, # ....Usage (X) 38 127 + 0x09, 0x31, # ....Usage (Y) 40 128 + 0x15, 0x81, # ....Logical Minimum (-127) 42 129 + 0x25, 0x7f, # ....Logical Maximum (127) 44 130 + 0x75, 0x08, # ....Report Size (8) 46 131 + 0x95, 0x02, # ....Report Count (2) 48 132 + 0x81, 0x06, # ....Input (Data,Var,Rel) 50 133 + 0xc0, # ...End Collection 52 134 + 0xc0, # ..End Collection 53 135 + 0xc0, # .End Collection 54 136 + ] 137 + # fmt: on 138 + 139 + def __init__(self, rdesc=report_descriptor, name=None, input_info=None): 140 + super().__init__(rdesc, name, input_info) 141 + 142 + def fake_report(self, x, y, buttons): 143 + if buttons is not None: 144 + left, right, middle = buttons 145 + if left is None: 146 + left = self.left 147 + if right is None: 148 + right = self.right 149 + if middle is None: 150 + middle = self.middle 151 + else: 152 + left = self.left 153 + right = self.right 154 + middle = self.middle 155 + 156 + button_mask = sum(1 << i for i, b in enumerate([left, right, middle]) if b) 157 + x = max(-127, min(127, x)) 158 + y = max(-127, min(127, y)) 159 + x = hidtools.util.to_twos_comp(x, 8) 160 + y = hidtools.util.to_twos_comp(y, 8) 161 + return [button_mask, x, y] 162 + 163 + 164 + class WheelMouse(ButtonMouse): 165 + # fmt: off 166 + report_descriptor = [ 167 + 0x05, 0x01, # Usage Page (Generic Desktop) 0 168 + 0x09, 0x02, # Usage (Mouse) 2 169 + 0xa1, 0x01, # Collection (Application) 4 170 + 0x05, 0x09, # .Usage Page (Button) 6 171 + 0x19, 0x01, # .Usage Minimum (1) 8 172 + 0x29, 0x03, # .Usage Maximum (3) 10 173 + 0x15, 0x00, # .Logical Minimum (0) 12 174 + 0x25, 0x01, # .Logical Maximum (1) 14 175 + 0x95, 0x03, # .Report Count (3) 16 176 + 0x75, 0x01, # .Report Size (1) 18 177 + 0x81, 0x02, # .Input (Data,Var,Abs) 20 178 + 0x95, 0x01, # .Report Count (1) 22 179 + 0x75, 0x05, # .Report Size (5) 24 180 + 0x81, 0x03, # .Input (Cnst,Var,Abs) 26 181 + 0x05, 0x01, # .Usage Page (Generic Desktop) 28 182 + 0x09, 0x01, # .Usage (Pointer) 30 183 + 0xa1, 0x00, # .Collection (Physical) 32 184 + 0x09, 0x30, # ..Usage (X) 34 185 + 0x09, 0x31, # ..Usage (Y) 36 186 + 0x15, 0x81, # ..Logical Minimum (-127) 38 187 + 0x25, 0x7f, # ..Logical Maximum (127) 40 188 + 0x75, 0x08, # ..Report Size (8) 42 189 + 0x95, 0x02, # ..Report Count (2) 44 190 + 0x81, 0x06, # ..Input (Data,Var,Rel) 46 191 + 0xc0, # .End Collection 48 192 + 0x09, 0x38, # .Usage (Wheel) 49 193 + 0x15, 0x81, # .Logical Minimum (-127) 51 194 + 0x25, 0x7f, # .Logical Maximum (127) 53 195 + 0x75, 0x08, # .Report Size (8) 55 196 + 0x95, 0x01, # .Report Count (1) 57 197 + 0x81, 0x06, # .Input (Data,Var,Rel) 59 198 + 0xc0, # End Collection 61 199 + ] 200 + # fmt: on 201 + 202 + def __init__(self, rdesc=report_descriptor, name=None, input_info=None): 203 + super().__init__(rdesc, name, input_info) 204 + self.wheel_multiplier = 1 205 + 206 + 207 + class TwoWheelMouse(WheelMouse): 208 + # fmt: off 209 + report_descriptor = [ 210 + 0x05, 0x01, # Usage Page (Generic Desktop) 0 211 + 0x09, 0x02, # Usage (Mouse) 2 212 + 0xa1, 0x01, # Collection (Application) 4 213 + 0x09, 0x01, # .Usage (Pointer) 6 214 + 0xa1, 0x00, # .Collection (Physical) 8 215 + 0x05, 0x09, # ..Usage Page (Button) 10 216 + 0x19, 0x01, # ..Usage Minimum (1) 12 217 + 0x29, 0x10, # ..Usage Maximum (16) 14 218 + 0x15, 0x00, # ..Logical Minimum (0) 16 219 + 0x25, 0x01, # ..Logical Maximum (1) 18 220 + 0x95, 0x10, # ..Report Count (16) 20 221 + 0x75, 0x01, # ..Report Size (1) 22 222 + 0x81, 0x02, # ..Input (Data,Var,Abs) 24 223 + 0x05, 0x01, # ..Usage Page (Generic Desktop) 26 224 + 0x16, 0x01, 0x80, # ..Logical Minimum (-32767) 28 225 + 0x26, 0xff, 0x7f, # ..Logical Maximum (32767) 31 226 + 0x75, 0x10, # ..Report Size (16) 34 227 + 0x95, 0x02, # ..Report Count (2) 36 228 + 0x09, 0x30, # ..Usage (X) 38 229 + 0x09, 0x31, # ..Usage (Y) 40 230 + 0x81, 0x06, # ..Input (Data,Var,Rel) 42 231 + 0x15, 0x81, # ..Logical Minimum (-127) 44 232 + 0x25, 0x7f, # ..Logical Maximum (127) 46 233 + 0x75, 0x08, # ..Report Size (8) 48 234 + 0x95, 0x01, # ..Report Count (1) 50 235 + 0x09, 0x38, # ..Usage (Wheel) 52 236 + 0x81, 0x06, # ..Input (Data,Var,Rel) 54 237 + 0x05, 0x0c, # ..Usage Page (Consumer Devices) 56 238 + 0x0a, 0x38, 0x02, # ..Usage (AC Pan) 58 239 + 0x95, 0x01, # ..Report Count (1) 61 240 + 0x81, 0x06, # ..Input (Data,Var,Rel) 63 241 + 0xc0, # .End Collection 65 242 + 0xc0, # End Collection 66 243 + ] 244 + # fmt: on 245 + 246 + def __init__(self, rdesc=report_descriptor, name=None, input_info=None): 247 + super().__init__(rdesc, name, input_info) 248 + self.hwheel_multiplier = 1 249 + 250 + 251 + class MIDongleMIWirelessMouse(TwoWheelMouse): 252 + # fmt: off 253 + report_descriptor = [ 254 + 0x05, 0x01, # Usage Page (Generic Desktop) 255 + 0x09, 0x02, # Usage (Mouse) 256 + 0xa1, 0x01, # Collection (Application) 257 + 0x85, 0x01, # .Report ID (1) 258 + 0x09, 0x01, # .Usage (Pointer) 259 + 0xa1, 0x00, # .Collection (Physical) 260 + 0x95, 0x05, # ..Report Count (5) 261 + 0x75, 0x01, # ..Report Size (1) 262 + 0x05, 0x09, # ..Usage Page (Button) 263 + 0x19, 0x01, # ..Usage Minimum (1) 264 + 0x29, 0x05, # ..Usage Maximum (5) 265 + 0x15, 0x00, # ..Logical Minimum (0) 266 + 0x25, 0x01, # ..Logical Maximum (1) 267 + 0x81, 0x02, # ..Input (Data,Var,Abs) 268 + 0x95, 0x01, # ..Report Count (1) 269 + 0x75, 0x03, # ..Report Size (3) 270 + 0x81, 0x01, # ..Input (Cnst,Arr,Abs) 271 + 0x75, 0x08, # ..Report Size (8) 272 + 0x95, 0x01, # ..Report Count (1) 273 + 0x05, 0x01, # ..Usage Page (Generic Desktop) 274 + 0x09, 0x38, # ..Usage (Wheel) 275 + 0x15, 0x81, # ..Logical Minimum (-127) 276 + 0x25, 0x7f, # ..Logical Maximum (127) 277 + 0x81, 0x06, # ..Input (Data,Var,Rel) 278 + 0x05, 0x0c, # ..Usage Page (Consumer Devices) 279 + 0x0a, 0x38, 0x02, # ..Usage (AC Pan) 280 + 0x95, 0x01, # ..Report Count (1) 281 + 0x81, 0x06, # ..Input (Data,Var,Rel) 282 + 0xc0, # .End Collection 283 + 0x85, 0x02, # .Report ID (2) 284 + 0x09, 0x01, # .Usage (Consumer Control) 285 + 0xa1, 0x00, # .Collection (Physical) 286 + 0x75, 0x0c, # ..Report Size (12) 287 + 0x95, 0x02, # ..Report Count (2) 288 + 0x05, 0x01, # ..Usage Page (Generic Desktop) 289 + 0x09, 0x30, # ..Usage (X) 290 + 0x09, 0x31, # ..Usage (Y) 291 + 0x16, 0x01, 0xf8, # ..Logical Minimum (-2047) 292 + 0x26, 0xff, 0x07, # ..Logical Maximum (2047) 293 + 0x81, 0x06, # ..Input (Data,Var,Rel) 294 + 0xc0, # .End Collection 295 + 0xc0, # End Collection 296 + 0x05, 0x0c, # Usage Page (Consumer Devices) 297 + 0x09, 0x01, # Usage (Consumer Control) 298 + 0xa1, 0x01, # Collection (Application) 299 + 0x85, 0x03, # .Report ID (3) 300 + 0x15, 0x00, # .Logical Minimum (0) 301 + 0x25, 0x01, # .Logical Maximum (1) 302 + 0x75, 0x01, # .Report Size (1) 303 + 0x95, 0x01, # .Report Count (1) 304 + 0x09, 0xcd, # .Usage (Play/Pause) 305 + 0x81, 0x06, # .Input (Data,Var,Rel) 306 + 0x0a, 0x83, 0x01, # .Usage (AL Consumer Control Config) 307 + 0x81, 0x06, # .Input (Data,Var,Rel) 308 + 0x09, 0xb5, # .Usage (Scan Next Track) 309 + 0x81, 0x06, # .Input (Data,Var,Rel) 310 + 0x09, 0xb6, # .Usage (Scan Previous Track) 311 + 0x81, 0x06, # .Input (Data,Var,Rel) 312 + 0x09, 0xea, # .Usage (Volume Down) 313 + 0x81, 0x06, # .Input (Data,Var,Rel) 314 + 0x09, 0xe9, # .Usage (Volume Up) 315 + 0x81, 0x06, # .Input (Data,Var,Rel) 316 + 0x0a, 0x25, 0x02, # .Usage (AC Forward) 317 + 0x81, 0x06, # .Input (Data,Var,Rel) 318 + 0x0a, 0x24, 0x02, # .Usage (AC Back) 319 + 0x81, 0x06, # .Input (Data,Var,Rel) 320 + 0xc0, # End Collection 321 + ] 322 + # fmt: on 323 + device_input_info = (BusType.USB, 0x2717, 0x003B) 324 + device_name = "uhid test MI Dongle MI Wireless Mouse" 325 + 326 + def __init__( 327 + self, rdesc=report_descriptor, name=device_name, input_info=device_input_info 328 + ): 329 + super().__init__(rdesc, name, input_info) 330 + 331 + def event(self, x, y, buttons=None, wheels=None): 332 + # this mouse spreads the relative pointer and the mouse buttons 333 + # onto 2 distinct reports 334 + rs = [] 335 + r = self.create_report(x, y, buttons, wheels, reportID=1) 336 + self.call_input_event(r) 337 + rs.append(r) 338 + r = self.create_report(x, y, buttons, reportID=2) 339 + self.call_input_event(r) 340 + rs.append(r) 341 + return rs 342 + 343 + 344 + class ResolutionMultiplierMouse(TwoWheelMouse): 345 + # fmt: off 346 + report_descriptor = [ 347 + 0x05, 0x01, # Usage Page (Generic Desktop) 83 348 + 0x09, 0x02, # Usage (Mouse) 85 349 + 0xa1, 0x01, # Collection (Application) 87 350 + 0x05, 0x01, # .Usage Page (Generic Desktop) 89 351 + 0x09, 0x02, # .Usage (Mouse) 91 352 + 0xa1, 0x02, # .Collection (Logical) 93 353 + 0x85, 0x11, # ..Report ID (17) 95 354 + 0x09, 0x01, # ..Usage (Pointer) 97 355 + 0xa1, 0x00, # ..Collection (Physical) 99 356 + 0x05, 0x09, # ...Usage Page (Button) 101 357 + 0x19, 0x01, # ...Usage Minimum (1) 103 358 + 0x29, 0x03, # ...Usage Maximum (3) 105 359 + 0x95, 0x03, # ...Report Count (3) 107 360 + 0x75, 0x01, # ...Report Size (1) 109 361 + 0x25, 0x01, # ...Logical Maximum (1) 111 362 + 0x81, 0x02, # ...Input (Data,Var,Abs) 113 363 + 0x95, 0x01, # ...Report Count (1) 115 364 + 0x81, 0x01, # ...Input (Cnst,Arr,Abs) 117 365 + 0x09, 0x05, # ...Usage (Vendor Usage 0x05) 119 366 + 0x81, 0x02, # ...Input (Data,Var,Abs) 121 367 + 0x95, 0x03, # ...Report Count (3) 123 368 + 0x81, 0x01, # ...Input (Cnst,Arr,Abs) 125 369 + 0x05, 0x01, # ...Usage Page (Generic Desktop) 127 370 + 0x09, 0x30, # ...Usage (X) 129 371 + 0x09, 0x31, # ...Usage (Y) 131 372 + 0x95, 0x02, # ...Report Count (2) 133 373 + 0x75, 0x08, # ...Report Size (8) 135 374 + 0x15, 0x81, # ...Logical Minimum (-127) 137 375 + 0x25, 0x7f, # ...Logical Maximum (127) 139 376 + 0x81, 0x06, # ...Input (Data,Var,Rel) 141 377 + 0xa1, 0x02, # ...Collection (Logical) 143 378 + 0x85, 0x12, # ....Report ID (18) 145 379 + 0x09, 0x48, # ....Usage (Resolution Multiplier) 147 380 + 0x95, 0x01, # ....Report Count (1) 149 381 + 0x75, 0x02, # ....Report Size (2) 151 382 + 0x15, 0x00, # ....Logical Minimum (0) 153 383 + 0x25, 0x01, # ....Logical Maximum (1) 155 384 + 0x35, 0x01, # ....Physical Minimum (1) 157 385 + 0x45, 0x04, # ....Physical Maximum (4) 159 386 + 0xb1, 0x02, # ....Feature (Data,Var,Abs) 161 387 + 0x35, 0x00, # ....Physical Minimum (0) 163 388 + 0x45, 0x00, # ....Physical Maximum (0) 165 389 + 0x75, 0x06, # ....Report Size (6) 167 390 + 0xb1, 0x01, # ....Feature (Cnst,Arr,Abs) 169 391 + 0x85, 0x11, # ....Report ID (17) 171 392 + 0x09, 0x38, # ....Usage (Wheel) 173 393 + 0x15, 0x81, # ....Logical Minimum (-127) 175 394 + 0x25, 0x7f, # ....Logical Maximum (127) 177 395 + 0x75, 0x08, # ....Report Size (8) 179 396 + 0x81, 0x06, # ....Input (Data,Var,Rel) 181 397 + 0xc0, # ...End Collection 183 398 + 0x05, 0x0c, # ...Usage Page (Consumer Devices) 184 399 + 0x75, 0x08, # ...Report Size (8) 186 400 + 0x0a, 0x38, 0x02, # ...Usage (AC Pan) 188 401 + 0x81, 0x06, # ...Input (Data,Var,Rel) 191 402 + 0xc0, # ..End Collection 193 403 + 0xc0, # .End Collection 194 404 + 0xc0, # End Collection 195 405 + ] 406 + # fmt: on 407 + 408 + def __init__(self, rdesc=report_descriptor, name=None, input_info=None): 409 + super().__init__(rdesc, name, input_info) 410 + self.default_reportID = 0x11 411 + 412 + # Feature Report 12, multiplier Feature value must be set to 0b01, 413 + # i.e. 1. We should extract that from the descriptor instead 414 + # of hardcoding it here, but meanwhile this will do. 415 + self.set_feature_report = [0x12, 0x1] 416 + 417 + def set_report(self, req, rnum, rtype, data): 418 + if rtype != self.UHID_FEATURE_REPORT: 419 + raise InvalidHIDCommunication(f"Unexpected report type: {rtype}") 420 + if rnum != 0x12: 421 + raise InvalidHIDCommunication(f"Unexpected report number: {rnum}") 422 + 423 + if data != self.set_feature_report: 424 + raise InvalidHIDCommunication( 425 + f"Unexpected data: {data}, expected {self.set_feature_report}" 426 + ) 427 + 428 + self.wheel_multiplier = 4 429 + 430 + return 0 431 + 432 + 433 + class BadResolutionMultiplierMouse(ResolutionMultiplierMouse): 434 + def set_report(self, req, rnum, rtype, data): 435 + super().set_report(req, rnum, rtype, data) 436 + 437 + self.wheel_multiplier = 1 438 + self.hwheel_multiplier = 1 439 + return 32 # EPIPE 440 + 441 + 442 + class ResolutionMultiplierHWheelMouse(TwoWheelMouse): 443 + # fmt: off 444 + report_descriptor = [ 445 + 0x05, 0x01, # Usage Page (Generic Desktop) 0 446 + 0x09, 0x02, # Usage (Mouse) 2 447 + 0xa1, 0x01, # Collection (Application) 4 448 + 0x05, 0x01, # .Usage Page (Generic Desktop) 6 449 + 0x09, 0x02, # .Usage (Mouse) 8 450 + 0xa1, 0x02, # .Collection (Logical) 10 451 + 0x85, 0x1a, # ..Report ID (26) 12 452 + 0x09, 0x01, # ..Usage (Pointer) 14 453 + 0xa1, 0x00, # ..Collection (Physical) 16 454 + 0x05, 0x09, # ...Usage Page (Button) 18 455 + 0x19, 0x01, # ...Usage Minimum (1) 20 456 + 0x29, 0x05, # ...Usage Maximum (5) 22 457 + 0x95, 0x05, # ...Report Count (5) 24 458 + 0x75, 0x01, # ...Report Size (1) 26 459 + 0x15, 0x00, # ...Logical Minimum (0) 28 460 + 0x25, 0x01, # ...Logical Maximum (1) 30 461 + 0x81, 0x02, # ...Input (Data,Var,Abs) 32 462 + 0x75, 0x03, # ...Report Size (3) 34 463 + 0x95, 0x01, # ...Report Count (1) 36 464 + 0x81, 0x01, # ...Input (Cnst,Arr,Abs) 38 465 + 0x05, 0x01, # ...Usage Page (Generic Desktop) 40 466 + 0x09, 0x30, # ...Usage (X) 42 467 + 0x09, 0x31, # ...Usage (Y) 44 468 + 0x95, 0x02, # ...Report Count (2) 46 469 + 0x75, 0x10, # ...Report Size (16) 48 470 + 0x16, 0x01, 0x80, # ...Logical Minimum (-32767) 50 471 + 0x26, 0xff, 0x7f, # ...Logical Maximum (32767) 53 472 + 0x81, 0x06, # ...Input (Data,Var,Rel) 56 473 + 0xa1, 0x02, # ...Collection (Logical) 58 474 + 0x85, 0x12, # ....Report ID (18) 60 475 + 0x09, 0x48, # ....Usage (Resolution Multiplier) 62 476 + 0x95, 0x01, # ....Report Count (1) 64 477 + 0x75, 0x02, # ....Report Size (2) 66 478 + 0x15, 0x00, # ....Logical Minimum (0) 68 479 + 0x25, 0x01, # ....Logical Maximum (1) 70 480 + 0x35, 0x01, # ....Physical Minimum (1) 72 481 + 0x45, 0x0c, # ....Physical Maximum (12) 74 482 + 0xb1, 0x02, # ....Feature (Data,Var,Abs) 76 483 + 0x85, 0x1a, # ....Report ID (26) 78 484 + 0x09, 0x38, # ....Usage (Wheel) 80 485 + 0x35, 0x00, # ....Physical Minimum (0) 82 486 + 0x45, 0x00, # ....Physical Maximum (0) 84 487 + 0x95, 0x01, # ....Report Count (1) 86 488 + 0x75, 0x10, # ....Report Size (16) 88 489 + 0x16, 0x01, 0x80, # ....Logical Minimum (-32767) 90 490 + 0x26, 0xff, 0x7f, # ....Logical Maximum (32767) 93 491 + 0x81, 0x06, # ....Input (Data,Var,Rel) 96 492 + 0xc0, # ...End Collection 98 493 + 0xa1, 0x02, # ...Collection (Logical) 99 494 + 0x85, 0x12, # ....Report ID (18) 101 495 + 0x09, 0x48, # ....Usage (Resolution Multiplier) 103 496 + 0x75, 0x02, # ....Report Size (2) 105 497 + 0x15, 0x00, # ....Logical Minimum (0) 107 498 + 0x25, 0x01, # ....Logical Maximum (1) 109 499 + 0x35, 0x01, # ....Physical Minimum (1) 111 500 + 0x45, 0x0c, # ....Physical Maximum (12) 113 501 + 0xb1, 0x02, # ....Feature (Data,Var,Abs) 115 502 + 0x35, 0x00, # ....Physical Minimum (0) 117 503 + 0x45, 0x00, # ....Physical Maximum (0) 119 504 + 0x75, 0x04, # ....Report Size (4) 121 505 + 0xb1, 0x01, # ....Feature (Cnst,Arr,Abs) 123 506 + 0x85, 0x1a, # ....Report ID (26) 125 507 + 0x05, 0x0c, # ....Usage Page (Consumer Devices) 127 508 + 0x95, 0x01, # ....Report Count (1) 129 509 + 0x75, 0x10, # ....Report Size (16) 131 510 + 0x16, 0x01, 0x80, # ....Logical Minimum (-32767) 133 511 + 0x26, 0xff, 0x7f, # ....Logical Maximum (32767) 136 512 + 0x0a, 0x38, 0x02, # ....Usage (AC Pan) 139 513 + 0x81, 0x06, # ....Input (Data,Var,Rel) 142 514 + 0xc0, # ...End Collection 144 515 + 0xc0, # ..End Collection 145 516 + 0xc0, # .End Collection 146 517 + 0xc0, # End Collection 147 518 + ] 519 + # fmt: on 520 + 521 + def __init__(self, rdesc=report_descriptor, name=None, input_info=None): 522 + super().__init__(rdesc, name, input_info) 523 + self.default_reportID = 0x1A 524 + 525 + # Feature Report 12, multiplier Feature value must be set to 0b0101, 526 + # i.e. 5. We should extract that from the descriptor instead 527 + # of hardcoding it here, but meanwhile this will do. 528 + self.set_feature_report = [0x12, 0x5] 529 + 530 + def set_report(self, req, rnum, rtype, data): 531 + super().set_report(req, rnum, rtype, data) 532 + 533 + self.wheel_multiplier = 12 534 + self.hwheel_multiplier = 12 535 + 536 + return 0 537 + 538 + 539 + class BaseTest: 540 + class TestMouse(base.BaseTestCase.TestUhid): 541 + def test_buttons(self): 542 + """check for button reliability.""" 543 + uhdev = self.uhdev 544 + evdev = uhdev.get_evdev() 545 + syn_event = self.syn_event 546 + 547 + r = uhdev.event(0, 0, (None, True, None)) 548 + expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_RIGHT, 1) 549 + events = uhdev.next_sync_events() 550 + self.debug_reports(r, uhdev, events) 551 + self.assertInputEventsIn((syn_event, expected_event), events) 552 + assert evdev.value[libevdev.EV_KEY.BTN_RIGHT] == 1 553 + 554 + r = uhdev.event(0, 0, (None, False, None)) 555 + expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_RIGHT, 0) 556 + events = uhdev.next_sync_events() 557 + self.debug_reports(r, uhdev, events) 558 + self.assertInputEventsIn((syn_event, expected_event), events) 559 + assert evdev.value[libevdev.EV_KEY.BTN_RIGHT] == 0 560 + 561 + r = uhdev.event(0, 0, (None, None, True)) 562 + expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_MIDDLE, 1) 563 + events = uhdev.next_sync_events() 564 + self.debug_reports(r, uhdev, events) 565 + self.assertInputEventsIn((syn_event, expected_event), events) 566 + assert evdev.value[libevdev.EV_KEY.BTN_MIDDLE] == 1 567 + 568 + r = uhdev.event(0, 0, (None, None, False)) 569 + expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_MIDDLE, 0) 570 + events = uhdev.next_sync_events() 571 + self.debug_reports(r, uhdev, events) 572 + self.assertInputEventsIn((syn_event, expected_event), events) 573 + assert evdev.value[libevdev.EV_KEY.BTN_MIDDLE] == 0 574 + 575 + r = uhdev.event(0, 0, (True, None, None)) 576 + expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 1) 577 + events = uhdev.next_sync_events() 578 + self.debug_reports(r, uhdev, events) 579 + self.assertInputEventsIn((syn_event, expected_event), events) 580 + assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 1 581 + 582 + r = uhdev.event(0, 0, (False, None, None)) 583 + expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 0) 584 + events = uhdev.next_sync_events() 585 + self.debug_reports(r, uhdev, events) 586 + self.assertInputEventsIn((syn_event, expected_event), events) 587 + assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 0 588 + 589 + r = uhdev.event(0, 0, (True, True, None)) 590 + expected_event0 = libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 1) 591 + expected_event1 = libevdev.InputEvent(libevdev.EV_KEY.BTN_RIGHT, 1) 592 + events = uhdev.next_sync_events() 593 + self.debug_reports(r, uhdev, events) 594 + self.assertInputEventsIn( 595 + (syn_event, expected_event0, expected_event1), events 596 + ) 597 + assert evdev.value[libevdev.EV_KEY.BTN_RIGHT] == 1 598 + assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 1 599 + 600 + r = uhdev.event(0, 0, (False, None, None)) 601 + expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 0) 602 + events = uhdev.next_sync_events() 603 + self.debug_reports(r, uhdev, events) 604 + self.assertInputEventsIn((syn_event, expected_event), events) 605 + assert evdev.value[libevdev.EV_KEY.BTN_RIGHT] == 1 606 + assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 0 607 + 608 + r = uhdev.event(0, 0, (None, False, None)) 609 + expected_event = libevdev.InputEvent(libevdev.EV_KEY.BTN_RIGHT, 0) 610 + events = uhdev.next_sync_events() 611 + self.debug_reports(r, uhdev, events) 612 + self.assertInputEventsIn((syn_event, expected_event), events) 613 + assert evdev.value[libevdev.EV_KEY.BTN_RIGHT] == 0 614 + assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 0 615 + 616 + def test_relative(self): 617 + """Check for relative events.""" 618 + uhdev = self.uhdev 619 + 620 + syn_event = self.syn_event 621 + 622 + r = uhdev.event(0, -1) 623 + expected_event = libevdev.InputEvent(libevdev.EV_REL.REL_Y, -1) 624 + events = uhdev.next_sync_events() 625 + self.debug_reports(r, uhdev, events) 626 + self.assertInputEvents((syn_event, expected_event), events) 627 + 628 + r = uhdev.event(1, 0) 629 + expected_event = libevdev.InputEvent(libevdev.EV_REL.REL_X, 1) 630 + events = uhdev.next_sync_events() 631 + self.debug_reports(r, uhdev, events) 632 + self.assertInputEvents((syn_event, expected_event), events) 633 + 634 + r = uhdev.event(-1, 2) 635 + expected_event0 = libevdev.InputEvent(libevdev.EV_REL.REL_X, -1) 636 + expected_event1 = libevdev.InputEvent(libevdev.EV_REL.REL_Y, 2) 637 + events = uhdev.next_sync_events() 638 + self.debug_reports(r, uhdev, events) 639 + self.assertInputEvents( 640 + (syn_event, expected_event0, expected_event1), events 641 + ) 642 + 643 + 644 + class TestSimpleMouse(BaseTest.TestMouse): 645 + def create_device(self): 646 + return ButtonMouse() 647 + 648 + def test_rdesc(self): 649 + """Check that the testsuite actually manages to format the 650 + reports according to the report descriptors. 651 + No kernel device is used here""" 652 + uhdev = self.uhdev 653 + 654 + event = (0, 0, (None, None, None)) 655 + assert uhdev.fake_report(*event) == uhdev.create_report(*event) 656 + 657 + event = (0, 0, (None, True, None)) 658 + assert uhdev.fake_report(*event) == uhdev.create_report(*event) 659 + 660 + event = (0, 0, (True, True, None)) 661 + assert uhdev.fake_report(*event) == uhdev.create_report(*event) 662 + 663 + event = (0, 0, (False, False, False)) 664 + assert uhdev.fake_report(*event) == uhdev.create_report(*event) 665 + 666 + event = (1, 0, (True, False, True)) 667 + assert uhdev.fake_report(*event) == uhdev.create_report(*event) 668 + 669 + event = (-1, 0, (True, False, True)) 670 + assert uhdev.fake_report(*event) == uhdev.create_report(*event) 671 + 672 + event = (-5, 5, (True, False, True)) 673 + assert uhdev.fake_report(*event) == uhdev.create_report(*event) 674 + 675 + event = (-127, 127, (True, False, True)) 676 + assert uhdev.fake_report(*event) == uhdev.create_report(*event) 677 + 678 + event = (0, -128, (True, False, True)) 679 + with pytest.raises(hidtools.hid.RangeError): 680 + uhdev.create_report(*event) 681 + 682 + 683 + class TestWheelMouse(BaseTest.TestMouse): 684 + def create_device(self): 685 + return WheelMouse() 686 + 687 + def is_wheel_highres(self, uhdev): 688 + evdev = uhdev.get_evdev() 689 + assert evdev.has(libevdev.EV_REL.REL_WHEEL) 690 + return evdev.has(libevdev.EV_REL.REL_WHEEL_HI_RES) 691 + 692 + def test_wheel(self): 693 + uhdev = self.uhdev 694 + 695 + # check if the kernel is high res wheel compatible 696 + high_res_wheel = self.is_wheel_highres(uhdev) 697 + 698 + syn_event = self.syn_event 699 + # The Resolution Multiplier is applied to the HID reports, so we 700 + # need to pre-multiply too. 701 + mult = uhdev.wheel_multiplier 702 + 703 + r = uhdev.event(0, 0, wheels=1 * mult) 704 + expected = [syn_event] 705 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL, 1)) 706 + if high_res_wheel: 707 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, 120)) 708 + events = uhdev.next_sync_events() 709 + self.debug_reports(r, uhdev, events) 710 + self.assertInputEvents(expected, events) 711 + 712 + r = uhdev.event(0, 0, wheels=-1 * mult) 713 + expected = [syn_event] 714 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL, -1)) 715 + if high_res_wheel: 716 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, -120)) 717 + events = uhdev.next_sync_events() 718 + self.debug_reports(r, uhdev, events) 719 + self.assertInputEvents(expected, events) 720 + 721 + r = uhdev.event(-1, 2, wheels=3 * mult) 722 + expected = [syn_event] 723 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_X, -1)) 724 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_Y, 2)) 725 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL, 3)) 726 + if high_res_wheel: 727 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, 360)) 728 + events = uhdev.next_sync_events() 729 + self.debug_reports(r, uhdev, events) 730 + self.assertInputEvents(expected, events) 731 + 732 + 733 + class TestTwoWheelMouse(TestWheelMouse): 734 + def create_device(self): 735 + return TwoWheelMouse() 736 + 737 + def is_hwheel_highres(self, uhdev): 738 + evdev = uhdev.get_evdev() 739 + assert evdev.has(libevdev.EV_REL.REL_HWHEEL) 740 + return evdev.has(libevdev.EV_REL.REL_HWHEEL_HI_RES) 741 + 742 + def test_ac_pan(self): 743 + uhdev = self.uhdev 744 + 745 + # check if the kernel is high res wheel compatible 746 + high_res_wheel = self.is_wheel_highres(uhdev) 747 + high_res_hwheel = self.is_hwheel_highres(uhdev) 748 + assert high_res_wheel == high_res_hwheel 749 + 750 + syn_event = self.syn_event 751 + # The Resolution Multiplier is applied to the HID reports, so we 752 + # need to pre-multiply too. 753 + hmult = uhdev.hwheel_multiplier 754 + vmult = uhdev.wheel_multiplier 755 + 756 + r = uhdev.event(0, 0, wheels=(0, 1 * hmult)) 757 + expected = [syn_event] 758 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL, 1)) 759 + if high_res_hwheel: 760 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, 120)) 761 + events = uhdev.next_sync_events() 762 + self.debug_reports(r, uhdev, events) 763 + self.assertInputEvents(expected, events) 764 + 765 + r = uhdev.event(0, 0, wheels=(0, -1 * hmult)) 766 + expected = [syn_event] 767 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL, -1)) 768 + if high_res_hwheel: 769 + expected.append( 770 + libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, -120) 771 + ) 772 + events = uhdev.next_sync_events() 773 + self.debug_reports(r, uhdev, events) 774 + self.assertInputEvents(expected, events) 775 + 776 + r = uhdev.event(-1, 2, wheels=(0, 3 * hmult)) 777 + expected = [syn_event] 778 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_X, -1)) 779 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_Y, 2)) 780 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL, 3)) 781 + if high_res_hwheel: 782 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, 360)) 783 + events = uhdev.next_sync_events() 784 + self.debug_reports(r, uhdev, events) 785 + self.assertInputEvents(expected, events) 786 + 787 + r = uhdev.event(-1, 2, wheels=(-3 * vmult, 4 * hmult)) 788 + expected = [syn_event] 789 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_X, -1)) 790 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_Y, 2)) 791 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL, -3)) 792 + if high_res_wheel: 793 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, -360)) 794 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL, 4)) 795 + if high_res_wheel: 796 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, 480)) 797 + events = uhdev.next_sync_events() 798 + self.debug_reports(r, uhdev, events) 799 + self.assertInputEvents(expected, events) 800 + 801 + 802 + class TestResolutionMultiplierMouse(TestTwoWheelMouse): 803 + def create_device(self): 804 + return ResolutionMultiplierMouse() 805 + 806 + def is_wheel_highres(self, uhdev): 807 + high_res = super().is_wheel_highres(uhdev) 808 + 809 + if not high_res: 810 + # the kernel doesn't seem to support the high res wheel mice, 811 + # make sure we haven't triggered the feature 812 + assert uhdev.wheel_multiplier == 1 813 + 814 + return high_res 815 + 816 + def test_resolution_multiplier_wheel(self): 817 + uhdev = self.uhdev 818 + 819 + if not self.is_wheel_highres(uhdev): 820 + pytest.skip("Kernel not compatible, we can not trigger the conditions") 821 + 822 + assert uhdev.wheel_multiplier > 1 823 + assert 120 % uhdev.wheel_multiplier == 0 824 + 825 + def test_wheel_with_multiplier(self): 826 + uhdev = self.uhdev 827 + 828 + if not self.is_wheel_highres(uhdev): 829 + pytest.skip("Kernel not compatible, we can not trigger the conditions") 830 + 831 + assert uhdev.wheel_multiplier > 1 832 + 833 + syn_event = self.syn_event 834 + mult = uhdev.wheel_multiplier 835 + 836 + r = uhdev.event(0, 0, wheels=1) 837 + expected = [syn_event] 838 + expected.append( 839 + libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, 120 / mult) 840 + ) 841 + events = uhdev.next_sync_events() 842 + self.debug_reports(r, uhdev, events) 843 + self.assertInputEvents(expected, events) 844 + 845 + r = uhdev.event(0, 0, wheels=-1) 846 + expected = [syn_event] 847 + expected.append( 848 + libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, -120 / mult) 849 + ) 850 + events = uhdev.next_sync_events() 851 + self.debug_reports(r, uhdev, events) 852 + self.assertInputEvents(expected, events) 853 + 854 + expected = [syn_event] 855 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_X, 1)) 856 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_Y, -2)) 857 + expected.append( 858 + libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL_HI_RES, 120 / mult) 859 + ) 860 + 861 + for _ in range(mult - 1): 862 + r = uhdev.event(1, -2, wheels=1) 863 + events = uhdev.next_sync_events() 864 + self.debug_reports(r, uhdev, events) 865 + self.assertInputEvents(expected, events) 866 + 867 + r = uhdev.event(1, -2, wheels=1) 868 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_WHEEL, 1)) 869 + events = uhdev.next_sync_events() 870 + self.debug_reports(r, uhdev, events) 871 + self.assertInputEvents(expected, events) 872 + 873 + 874 + class TestBadResolutionMultiplierMouse(TestTwoWheelMouse): 875 + def create_device(self): 876 + return BadResolutionMultiplierMouse() 877 + 878 + def is_wheel_highres(self, uhdev): 879 + high_res = super().is_wheel_highres(uhdev) 880 + 881 + assert uhdev.wheel_multiplier == 1 882 + 883 + return high_res 884 + 885 + def test_resolution_multiplier_wheel(self): 886 + uhdev = self.uhdev 887 + 888 + assert uhdev.wheel_multiplier == 1 889 + 890 + 891 + class TestResolutionMultiplierHWheelMouse(TestResolutionMultiplierMouse): 892 + def create_device(self): 893 + return ResolutionMultiplierHWheelMouse() 894 + 895 + def is_hwheel_highres(self, uhdev): 896 + high_res = super().is_hwheel_highres(uhdev) 897 + 898 + if not high_res: 899 + # the kernel doesn't seem to support the high res wheel mice, 900 + # make sure we haven't triggered the feature 901 + assert uhdev.hwheel_multiplier == 1 902 + 903 + return high_res 904 + 905 + def test_resolution_multiplier_ac_pan(self): 906 + uhdev = self.uhdev 907 + 908 + if not self.is_hwheel_highres(uhdev): 909 + pytest.skip("Kernel not compatible, we can not trigger the conditions") 910 + 911 + assert uhdev.hwheel_multiplier > 1 912 + assert 120 % uhdev.hwheel_multiplier == 0 913 + 914 + def test_ac_pan_with_multiplier(self): 915 + uhdev = self.uhdev 916 + 917 + if not self.is_hwheel_highres(uhdev): 918 + pytest.skip("Kernel not compatible, we can not trigger the conditions") 919 + 920 + assert uhdev.hwheel_multiplier > 1 921 + 922 + syn_event = self.syn_event 923 + hmult = uhdev.hwheel_multiplier 924 + 925 + r = uhdev.event(0, 0, wheels=(0, 1)) 926 + expected = [syn_event] 927 + expected.append( 928 + libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, 120 / hmult) 929 + ) 930 + events = uhdev.next_sync_events() 931 + self.debug_reports(r, uhdev, events) 932 + self.assertInputEvents(expected, events) 933 + 934 + r = uhdev.event(0, 0, wheels=(0, -1)) 935 + expected = [syn_event] 936 + expected.append( 937 + libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, -120 / hmult) 938 + ) 939 + events = uhdev.next_sync_events() 940 + self.debug_reports(r, uhdev, events) 941 + self.assertInputEvents(expected, events) 942 + 943 + expected = [syn_event] 944 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_X, 1)) 945 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_Y, -2)) 946 + expected.append( 947 + libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL_HI_RES, 120 / hmult) 948 + ) 949 + 950 + for _ in range(hmult - 1): 951 + r = uhdev.event(1, -2, wheels=(0, 1)) 952 + events = uhdev.next_sync_events() 953 + self.debug_reports(r, uhdev, events) 954 + self.assertInputEvents(expected, events) 955 + 956 + r = uhdev.event(1, -2, wheels=(0, 1)) 957 + expected.append(libevdev.InputEvent(libevdev.EV_REL.REL_HWHEEL, 1)) 958 + events = uhdev.next_sync_events() 959 + self.debug_reports(r, uhdev, events) 960 + self.assertInputEvents(expected, events) 961 + 962 + 963 + class TestMiMouse(TestWheelMouse): 964 + def create_device(self): 965 + return MIDongleMIWirelessMouse() 966 + 967 + def assertInputEvents(self, expected_events, effective_events): 968 + # Buttons and x/y are spread over two HID reports, so we can get two 969 + # event frames for this device. 970 + remaining = self.assertInputEventsIn(expected_events, effective_events) 971 + try: 972 + remaining.remove(libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT, 0)) 973 + except ValueError: 974 + # If there's no SYN_REPORT in the list, continue and let the 975 + # assert below print out the real error 976 + pass 977 + assert remaining == []
+2088
tools/testing/selftests/hid/tests/test_multitouch.py
··· 1 + #!/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # -*- coding: utf-8 -*- 4 + # 5 + # Copyright (c) 2017 Benjamin Tissoires <benjamin.tissoires@gmail.com> 6 + # Copyright (c) 2017 Red Hat, Inc. 7 + # 8 + 9 + from . import base 10 + from hidtools.hut import HUT 11 + from hidtools.util import BusType 12 + import libevdev 13 + import logging 14 + import pytest 15 + import sys 16 + import time 17 + 18 + logger = logging.getLogger("hidtools.test.multitouch") 19 + 20 + KERNEL_MODULE = ("hid-multitouch", "hid_multitouch") 21 + 22 + 23 + def BIT(x): 24 + return 1 << x 25 + 26 + 27 + mt_quirks = { 28 + "NOT_SEEN_MEANS_UP": BIT(0), 29 + "SLOT_IS_CONTACTID": BIT(1), 30 + "CYPRESS": BIT(2), 31 + "SLOT_IS_CONTACTNUMBER": BIT(3), 32 + "ALWAYS_VALID": BIT(4), 33 + "VALID_IS_INRANGE": BIT(5), 34 + "VALID_IS_CONFIDENCE": BIT(6), 35 + "CONFIDENCE": BIT(7), 36 + "SLOT_IS_CONTACTID_MINUS_ONE": BIT(8), 37 + "NO_AREA": BIT(9), 38 + "IGNORE_DUPLICATES": BIT(10), 39 + "HOVERING": BIT(11), 40 + "CONTACT_CNT_ACCURATE": BIT(12), 41 + "FORCE_GET_FEATURE": BIT(13), 42 + "FIX_CONST_CONTACT_ID": BIT(14), 43 + "TOUCH_SIZE_SCALING": BIT(15), 44 + "STICKY_FINGERS": BIT(16), 45 + "ASUS_CUSTOM_UP": BIT(17), 46 + "WIN8_PTP_BUTTONS": BIT(18), 47 + "SEPARATE_APP_REPORT": BIT(19), 48 + "MT_QUIRK_FORCE_MULTI_INPUT": BIT(20), 49 + } 50 + 51 + 52 + class Data(object): 53 + pass 54 + 55 + 56 + class Touch(object): 57 + def __init__(self, id, x, y): 58 + self.contactid = id 59 + self.x = x 60 + self.y = y 61 + self.cx = x 62 + self.cy = y 63 + self.tipswitch = True 64 + self.confidence = True 65 + self.tippressure = 15 66 + self.azimuth = 0 67 + self.inrange = True 68 + self.width = 10 69 + self.height = 10 70 + 71 + 72 + class Pen(Touch): 73 + def __init__(self, x, y): 74 + super().__init__(0, x, y) 75 + self.barrel = False 76 + self.invert = False 77 + self.eraser = False 78 + self.x_tilt = False 79 + self.y_tilt = False 80 + self.twist = 0 81 + 82 + 83 + class Digitizer(base.UHIDTestDevice): 84 + @classmethod 85 + def msCertificationBlob(cls, reportID): 86 + return f""" 87 + Usage Page (Digitizers) 88 + Usage (Touch Screen) 89 + Collection (Application) 90 + Report ID ({reportID}) 91 + Usage Page (0xff00) 92 + Usage (0xc5) 93 + Logical Minimum (0) 94 + Logical Maximum (255) 95 + Report Size (8) 96 + Report Count (256) 97 + Feature (Data,Var,Abs) 98 + End Collection 99 + """ 100 + 101 + def __init__( 102 + self, 103 + name, 104 + rdesc_str=None, 105 + rdesc=None, 106 + application="Touch Screen", 107 + physical="Finger", 108 + max_contacts=None, 109 + input_info=(BusType.USB, 1, 2), 110 + quirks=None, 111 + ): 112 + super().__init__(name, application, rdesc_str, rdesc, input_info) 113 + self.scantime = 0 114 + self.quirks = quirks 115 + if max_contacts is None: 116 + self.max_contacts = sys.maxsize 117 + for features in self.parsed_rdesc.feature_reports.values(): 118 + for feature in features: 119 + if feature.usage_name in ["Contact Max"]: 120 + self.max_contacts = feature.logical_max 121 + for inputs in self.parsed_rdesc.input_reports.values(): 122 + for i in inputs: 123 + if ( 124 + i.usage_name in ["Contact Count"] 125 + and i.logical_max > 0 126 + and self.max_contacts > i.logical_max 127 + ): 128 + self.max_contacts = i.logical_max 129 + if self.max_contacts == sys.maxsize: 130 + self.max_contacts = 1 131 + else: 132 + self.max_contacts = max_contacts 133 + self.physical = physical 134 + self.cur_application = application 135 + 136 + for features in self.parsed_rdesc.feature_reports.values(): 137 + for feature in features: 138 + if feature.usage_name == "Inputmode": 139 + self.cur_application = "Mouse" 140 + 141 + self.fields = [] 142 + for r in self.parsed_rdesc.input_reports.values(): 143 + if r.application_name == self.application: 144 + physicals = [f.physical_name for f in r] 145 + if self.physical not in physicals and None not in physicals: 146 + continue 147 + self.fields = [f.usage_name for f in r] 148 + 149 + @property 150 + def touches_in_a_report(self): 151 + return self.fields.count("Contact Id") 152 + 153 + def event(self, slots, global_data=None, contact_count=None, incr_scantime=True): 154 + if incr_scantime: 155 + self.scantime += 1 156 + rs = [] 157 + # make sure we have only the required number of available slots 158 + slots = slots[: self.max_contacts] 159 + 160 + if global_data is None: 161 + global_data = Data() 162 + if contact_count is None: 163 + global_data.contactcount = len(slots) 164 + else: 165 + global_data.contactcount = contact_count 166 + global_data.scantime = self.scantime 167 + 168 + while len(slots): 169 + r = self.create_report( 170 + application=self.cur_application, data=slots, global_data=global_data 171 + ) 172 + self.call_input_event(r) 173 + rs.append(r) 174 + global_data.contactcount = 0 175 + return rs 176 + 177 + def get_report(self, req, rnum, rtype): 178 + if rtype != self.UHID_FEATURE_REPORT: 179 + return (1, []) 180 + 181 + rdesc = None 182 + for v in self.parsed_rdesc.feature_reports.values(): 183 + if v.report_ID == rnum: 184 + rdesc = v 185 + 186 + if rdesc is None: 187 + return (1, []) 188 + 189 + if "Contact Max" not in [f.usage_name for f in rdesc]: 190 + return (1, []) 191 + 192 + self.contactmax = self.max_contacts 193 + r = rdesc.create_report([self], None) 194 + return (0, r) 195 + 196 + def set_report(self, req, rnum, rtype, data): 197 + if rtype != self.UHID_FEATURE_REPORT: 198 + return 1 199 + 200 + rdesc = None 201 + for v in self.parsed_rdesc.feature_reports.values(): 202 + if v.report_ID == rnum: 203 + rdesc = v 204 + 205 + if rdesc is None: 206 + return 1 207 + 208 + if "Inputmode" not in [f.usage_name for f in rdesc]: 209 + return 0 210 + 211 + Inputmode_seen = False 212 + for f in rdesc: 213 + if "Inputmode" == f.usage_name: 214 + values = f.get_values(data) 215 + assert len(values) == 1 216 + value = values[0] 217 + 218 + if not Inputmode_seen: 219 + Inputmode_seen = True 220 + if value == 0: 221 + self.cur_application = "Mouse" 222 + elif value == 2: 223 + self.cur_application = "Touch Screen" 224 + elif value == 3: 225 + self.cur_application = "Touch Pad" 226 + else: 227 + if value != 0: 228 + # Elan bug where the device doesn't work properly 229 + # if we set twice an Input Mode in the same Feature 230 + self.cur_application = "Mouse" 231 + 232 + return 0 233 + 234 + 235 + class PTP(Digitizer): 236 + def __init__( 237 + self, 238 + name, 239 + type="Click Pad", 240 + rdesc_str=None, 241 + rdesc=None, 242 + application="Touch Pad", 243 + physical="Pointer", 244 + max_contacts=None, 245 + input_info=None, 246 + ): 247 + self.type = type.lower().replace(" ", "") 248 + if self.type == "clickpad": 249 + self.buttontype = 0 250 + else: # pressurepad 251 + self.buttontype = 1 252 + self.clickpad_state = False 253 + self.left_state = False 254 + self.right_state = False 255 + super().__init__( 256 + name, rdesc_str, rdesc, application, physical, max_contacts, input_info 257 + ) 258 + 259 + def event( 260 + self, 261 + slots=None, 262 + click=None, 263 + left=None, 264 + right=None, 265 + contact_count=None, 266 + incr_scantime=True, 267 + ): 268 + # update our internal state 269 + if click is not None: 270 + self.clickpad_state = click 271 + if left is not None: 272 + self.left_state = left 273 + if right is not None: 274 + self.right_state = right 275 + 276 + # now create the global data 277 + global_data = Data() 278 + global_data.b1 = 1 if self.clickpad_state else 0 279 + global_data.b2 = 1 if self.left_state else 0 280 + global_data.b3 = 1 if self.right_state else 0 281 + 282 + if slots is None: 283 + slots = [Data()] 284 + 285 + return super().event(slots, global_data, contact_count, incr_scantime) 286 + 287 + 288 + class MinWin8TSParallel(Digitizer): 289 + def __init__(self, max_slots): 290 + self.max_slots = max_slots 291 + self.phys_max = 120, 90 292 + rdesc_finger_str = f""" 293 + Usage Page (Digitizers) 294 + Usage (Finger) 295 + Collection (Logical) 296 + Report Size (1) 297 + Report Count (1) 298 + Logical Minimum (0) 299 + Logical Maximum (1) 300 + Usage (Tip Switch) 301 + Input (Data,Var,Abs) 302 + Report Size (7) 303 + Logical Maximum (127) 304 + Input (Cnst,Var,Abs) 305 + Report Size (8) 306 + Logical Maximum (255) 307 + Usage (Contact Id) 308 + Input (Data,Var,Abs) 309 + Report Size (16) 310 + Unit Exponent (-1) 311 + Unit (SILinear: cm) 312 + Logical Maximum (4095) 313 + Physical Minimum (0) 314 + Physical Maximum ({self.phys_max[0]}) 315 + Usage Page (Generic Desktop) 316 + Usage (X) 317 + Input (Data,Var,Abs) 318 + Physical Maximum ({self.phys_max[1]}) 319 + Usage (Y) 320 + Input (Data,Var,Abs) 321 + Usage Page (Digitizers) 322 + Usage (Azimuth) 323 + Logical Maximum (360) 324 + Unit (SILinear: deg) 325 + Report Size (16) 326 + Input (Data,Var,Abs) 327 + End Collection 328 + """ 329 + rdesc_str = f""" 330 + Usage Page (Digitizers) 331 + Usage (Touch Screen) 332 + Collection (Application) 333 + Report ID (1) 334 + {rdesc_finger_str * self.max_slots} 335 + Unit Exponent (-4) 336 + Unit (SILinear: s) 337 + Logical Maximum (65535) 338 + Physical Maximum (65535) 339 + Usage Page (Digitizers) 340 + Usage (Scan Time) 341 + Input (Data,Var,Abs) 342 + Report Size (8) 343 + Logical Maximum (255) 344 + Usage (Contact Count) 345 + Input (Data,Var,Abs) 346 + Report ID (2) 347 + Logical Maximum ({self.max_slots}) 348 + Usage (Contact Max) 349 + Feature (Data,Var,Abs) 350 + End Collection 351 + {Digitizer.msCertificationBlob(68)} 352 + """ 353 + super().__init__(f"uhid test parallel {self.max_slots}", rdesc_str) 354 + 355 + 356 + class MinWin8TSHybrid(Digitizer): 357 + def __init__(self): 358 + self.max_slots = 10 359 + self.phys_max = 120, 90 360 + rdesc_finger_str = f""" 361 + Usage Page (Digitizers) 362 + Usage (Finger) 363 + Collection (Logical) 364 + Report Size (1) 365 + Report Count (1) 366 + Logical Minimum (0) 367 + Logical Maximum (1) 368 + Usage (Tip Switch) 369 + Input (Data,Var,Abs) 370 + Report Size (7) 371 + Logical Maximum (127) 372 + Input (Cnst,Var,Abs) 373 + Report Size (8) 374 + Logical Maximum (255) 375 + Usage (Contact Id) 376 + Input (Data,Var,Abs) 377 + Report Size (16) 378 + Unit Exponent (-1) 379 + Unit (SILinear: cm) 380 + Logical Maximum (4095) 381 + Physical Minimum (0) 382 + Physical Maximum ({self.phys_max[0]}) 383 + Usage Page (Generic Desktop) 384 + Usage (X) 385 + Input (Data,Var,Abs) 386 + Physical Maximum ({self.phys_max[1]}) 387 + Usage (Y) 388 + Input (Data,Var,Abs) 389 + End Collection 390 + """ 391 + rdesc_str = f""" 392 + Usage Page (Digitizers) 393 + Usage (Touch Screen) 394 + Collection (Application) 395 + Report ID (1) 396 + {rdesc_finger_str * 2} 397 + Unit Exponent (-4) 398 + Unit (SILinear: s) 399 + Logical Maximum (65535) 400 + Physical Maximum (65535) 401 + Usage Page (Digitizers) 402 + Usage (Scan Time) 403 + Input (Data,Var,Abs) 404 + Report Size (8) 405 + Logical Maximum (255) 406 + Usage (Contact Count) 407 + Input (Data,Var,Abs) 408 + Report ID (2) 409 + Logical Maximum ({self.max_slots}) 410 + Usage (Contact Max) 411 + Feature (Data,Var,Abs) 412 + End Collection 413 + {Digitizer.msCertificationBlob(68)} 414 + """ 415 + super().__init__("uhid test hybrid", rdesc_str) 416 + 417 + 418 + class Win8TSConfidence(Digitizer): 419 + def __init__(self, max_slots): 420 + self.max_slots = max_slots 421 + self.phys_max = 120, 90 422 + rdesc_finger_str = f""" 423 + Usage Page (Digitizers) 424 + Usage (Finger) 425 + Collection (Logical) 426 + Report Size (1) 427 + Report Count (1) 428 + Logical Minimum (0) 429 + Logical Maximum (1) 430 + Usage (Tip Switch) 431 + Input (Data,Var,Abs) 432 + Usage (Confidence) 433 + Input (Data,Var,Abs) 434 + Report Size (6) 435 + Logical Maximum (127) 436 + Input (Cnst,Var,Abs) 437 + Report Size (8) 438 + Logical Maximum (255) 439 + Usage (Contact Id) 440 + Input (Data,Var,Abs) 441 + Report Size (16) 442 + Unit Exponent (-1) 443 + Unit (SILinear: cm) 444 + Logical Maximum (4095) 445 + Physical Minimum (0) 446 + Physical Maximum ({self.phys_max[0]}) 447 + Usage Page (Generic Desktop) 448 + Usage (X) 449 + Input (Data,Var,Abs) 450 + Physical Maximum ({self.phys_max[1]}) 451 + Usage (Y) 452 + Input (Data,Var,Abs) 453 + Usage Page (Digitizers) 454 + Usage (Azimuth) 455 + Logical Maximum (360) 456 + Unit (SILinear: deg) 457 + Report Size (16) 458 + Input (Data,Var,Abs) 459 + End Collection 460 + """ 461 + rdesc_str = f""" 462 + Usage Page (Digitizers) 463 + Usage (Touch Screen) 464 + Collection (Application) 465 + Report ID (1) 466 + {rdesc_finger_str * self.max_slots} 467 + Unit Exponent (-4) 468 + Unit (SILinear: s) 469 + Logical Maximum (65535) 470 + Physical Maximum (65535) 471 + Usage Page (Digitizers) 472 + Usage (Scan Time) 473 + Input (Data,Var,Abs) 474 + Report Size (8) 475 + Logical Maximum (255) 476 + Usage (Contact Count) 477 + Input (Data,Var,Abs) 478 + Report ID (2) 479 + Logical Maximum ({self.max_slots}) 480 + Usage (Contact Max) 481 + Feature (Data,Var,Abs) 482 + End Collection 483 + {Digitizer.msCertificationBlob(68)} 484 + """ 485 + super().__init__(f"uhid test confidence {self.max_slots}", rdesc_str) 486 + 487 + 488 + class SmartTechDigitizer(Digitizer): 489 + def __init__(self, name, input_info): 490 + super().__init__( 491 + name, 492 + rdesc="05 01 09 02 a1 01 85 01 09 01 a1 00 05 09 19 01 29 03 15 00 25 01 95 03 75 01 81 02 95 05 81 03 05 01 15 00 26 ff 0f 55 0e 65 11 75 10 95 01 35 00 46 c8 37 09 30 81 02 46 68 1f 09 31 81 02 45 00 c0 c0 05 0d 09 06 15 00 26 ff 00 a1 01 85 02 75 08 95 3f 09 00 82 02 01 95 3f 09 00 92 02 01 c0 05 0d 09 04 a1 01 85 05 05 0d 09 20 a1 00 25 01 75 01 95 02 09 42 09 45 81 02 75 06 95 01 09 30 81 02 26 ff 00 75 08 09 51 81 02 75 10 09 38 81 02 95 02 26 ff 0f 09 48 09 49 81 02 05 01 09 30 09 31 81 02 c0 05 0d 09 20 a1 00 25 01 75 01 95 02 09 42 09 45 81 02 75 06 95 01 09 30 81 02 26 ff 00 75 08 09 51 81 02 75 10 09 38 81 02 95 02 26 ff 0f 09 48 09 49 81 02 05 01 09 30 09 31 81 02 c0 05 0d 09 20 a1 00 25 01 75 01 95 02 09 42 09 45 81 02 75 06 95 01 09 30 81 02 26 ff 00 75 08 09 51 81 02 75 10 09 38 81 02 95 02 26 ff 0f 09 48 09 49 81 02 05 01 09 30 09 31 81 02 c0 05 0d 09 20 a1 00 25 01 75 01 95 02 09 42 09 45 81 02 75 06 95 01 09 30 81 02 26 ff 00 75 08 09 51 81 02 75 10 09 38 81 02 95 02 26 ff 0f 09 48 09 49 81 02 05 01 09 30 09 31 81 02 c0 05 0d 75 08 95 01 15 00 25 0a 09 54 81 02 09 55 b1 02 c0 05 0d 09 0e a1 01 85 04 09 23 a1 02 15 00 25 02 75 08 95 02 09 52 09 53 b1 02 c0 c0 05 0d 09 04 a1 01 85 03 05 0d 09 22 a1 02 15 00 25 01 75 01 95 02 09 42 09 47 81 02 95 02 81 03 75 04 95 01 25 0f 09 30 81 02 26 ff 00 75 08 95 01 09 51 81 02 75 10 27 a0 8c 00 00 55 0e 65 14 47 a0 8c 00 00 09 3f 81 02 65 11 26 ff 0f 46 c8 37 09 48 81 02 46 68 1f 09 49 81 02 05 01 46 c8 37 09 30 81 02 46 68 1f 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 15 00 25 01 75 01 95 02 09 42 09 47 81 02 95 02 81 03 75 04 95 01 25 0f 09 30 81 02 26 ff 00 75 08 95 01 09 51 81 02 75 10 27 a0 8c 00 00 55 0e 65 14 47 a0 8c 00 00 09 3f 81 02 65 11 26 ff 0f 46 c8 37 09 48 81 02 46 68 1f 09 49 81 02 05 01 46 c8 37 09 30 81 02 46 68 1f 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 15 00 25 01 75 01 95 02 09 42 09 47 81 02 95 02 81 03 75 04 95 01 25 0f 09 30 81 02 26 ff 00 75 08 95 01 09 51 81 02 75 10 27 a0 8c 00 00 55 0e 65 14 47 a0 8c 00 00 09 3f 81 02 65 11 26 ff 0f 46 c8 37 09 48 81 02 46 68 1f 09 49 81 02 05 01 46 c8 37 09 30 81 02 46 68 1f 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 15 00 25 01 75 01 95 02 09 42 09 47 81 02 95 02 81 03 75 04 95 01 25 0f 09 30 81 02 26 ff 00 75 08 95 01 09 51 81 02 75 10 27 a0 8c 00 00 55 0e 65 14 47 a0 8c 00 00 09 3f 81 02 65 11 26 ff 0f 46 c8 37 09 48 81 02 46 68 1f 09 49 81 02 05 01 46 c8 37 09 30 81 02 46 68 1f 09 31 81 02 45 00 c0 05 0d 75 08 95 01 15 00 25 0a 09 54 81 02 09 55 b1 02 c0 05 0d 09 04 a1 01 85 06 09 22 a1 02 15 00 25 01 75 01 95 02 09 42 09 47 81 02 95 06 81 03 95 01 75 10 65 11 55 0e 26 ff 0f 46 c8 37 09 48 81 02 46 68 1f 09 49 81 02 05 01 46 c8 37 09 30 81 02 46 68 1f 09 31 81 02 45 00 c0 c0 05 0d 09 02 a1 01 85 07 09 20 a1 02 25 01 75 01 95 04 09 42 09 44 09 3c 09 45 81 02 75 04 95 01 25 0f 09 30 81 02 26 ff 00 75 08 09 38 81 02 75 10 27 a0 8c 00 00 55 0e 65 14 47 a0 8c 00 00 09 3f 81 02 65 11 26 ff 0f 46 c8 37 09 48 81 02 46 68 1f 09 49 81 02 05 01 46 c8 37 09 30 81 02 46 68 1f 09 31 81 02 45 00 c0 c0 05 0d 09 02 a1 01 85 08 09 20 a1 02 25 01 75 01 95 04 09 42 09 44 09 3c 09 45 81 02 75 04 95 01 25 0f 09 30 81 02 26 ff 00 75 08 09 38 81 02 75 10 27 a0 8c 00 00 55 0e 65 14 47 a0 8c 00 00 09 3f 81 02 65 11 26 ff 0f 46 c8 37 09 48 81 02 46 68 1f 09 49 81 02 05 01 46 c8 37 09 30 81 02 46 68 1f 09 31 81 02 45 00 c0 c0 05 0d 09 02 a1 01 85 09 09 20 a1 02 25 01 75 01 95 04 09 42 09 44 09 3c 09 45 81 02 75 04 95 01 25 0f 09 30 81 02 26 ff 00 75 08 09 38 81 02 75 10 27 a0 8c 00 00 55 0e 65 14 47 a0 8c 00 00 09 3f 81 02 65 11 26 ff 0f 46 c8 37 09 48 81 02 46 68 1f 09 49 81 02 05 01 46 c8 37 09 30 81 02 46 68 1f 09 31 81 02 45 00 c0 c0 05 0d 09 02 a1 01 85 0a 09 20 a1 02 25 01 75 01 95 04 09 42 09 44 09 3c 09 45 81 02 75 04 95 01 25 0f 09 30 81 02 26 ff 00 75 08 09 38 81 02 75 10 27 a0 8c 00 00 55 0e 65 14 47 a0 8c 00 00 09 3f 81 02 65 11 26 ff 0f 46 c8 37 09 48 81 02 46 68 1f 09 49 81 02 05 01 46 c8 37 09 30 81 02 46 68 1f 09 31 81 02 45 00 c0 c0", 493 + input_info=input_info, 494 + ) 495 + 496 + def create_report(self, data, global_data=None, reportID=None, application=None): 497 + # this device has *a lot* of different reports, and most of them 498 + # have the Touch Screen application. But the first one is a stylus 499 + # report (as stated in the physical type), so we simply override 500 + # the report ID to use what the device sends 501 + return super().create_report(data, global_data=global_data, reportID=3) 502 + 503 + def match_evdev_rule(self, application, evdev): 504 + # we need to select the correct evdev node, as the device has multiple 505 + # Touch Screen application collections 506 + if application != "Touch Screen": 507 + return True 508 + absinfo = evdev.absinfo[libevdev.EV_ABS.ABS_MT_POSITION_X] 509 + return absinfo is not None and absinfo.resolution == 3 510 + 511 + 512 + class BaseTest: 513 + class TestMultitouch(base.BaseTestCase.TestUhid): 514 + kernel_modules = [KERNEL_MODULE] 515 + 516 + def create_device(self): 517 + raise Exception("please reimplement me in subclasses") 518 + 519 + def get_slot(self, uhdev, t, default): 520 + if uhdev.quirks is None: 521 + return default 522 + 523 + if "SLOT_IS_CONTACTID" in uhdev.quirks: 524 + return t.contactid 525 + 526 + if "SLOT_IS_CONTACTID_MINUS_ONE" in uhdev.quirks: 527 + return t.contactid - 1 528 + 529 + return default 530 + 531 + def test_creation(self): 532 + """Make sure the device gets processed by the kernel and creates 533 + the expected application input node. 534 + 535 + If this fail, there is something wrong in the device report 536 + descriptors.""" 537 + super().test_creation() 538 + 539 + uhdev = self.uhdev 540 + evdev = uhdev.get_evdev() 541 + 542 + # some sanity checking for the quirks 543 + if uhdev.quirks is not None: 544 + for q in uhdev.quirks: 545 + assert q in mt_quirks 546 + 547 + assert evdev.num_slots == uhdev.max_contacts 548 + 549 + if uhdev.max_contacts > 1: 550 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 551 + assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 552 + if uhdev.max_contacts > 2: 553 + assert evdev.slots[2][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 554 + 555 + def test_required_usages(self): 556 + """Make sure the device exports the correct required features and 557 + inputs.""" 558 + uhdev = self.uhdev 559 + rdesc = uhdev.parsed_rdesc 560 + for feature in rdesc.feature_reports.values(): 561 + for field in feature: 562 + page_id = field.usage >> 16 563 + value = field.usage & 0xFF 564 + try: 565 + if HUT[page_id][value] == "Contact Max": 566 + assert HUT[page_id][field.application] in [ 567 + "Touch Screen", 568 + "Touch Pad", 569 + "System Multi-Axis Controller", 570 + ] 571 + except KeyError: 572 + pass 573 + 574 + try: 575 + if HUT[page_id][value] == "Inputmode": 576 + assert HUT[page_id][field.application] in [ 577 + "Touch Screen", 578 + "Touch Pad", 579 + "Device Configuration", 580 + ] 581 + except KeyError: 582 + pass 583 + 584 + def test_mt_single_touch(self): 585 + """send a single touch in the first slot of the device, 586 + and release it.""" 587 + uhdev = self.uhdev 588 + evdev = uhdev.get_evdev() 589 + 590 + t0 = Touch(1, 50, 100) 591 + r = uhdev.event([t0]) 592 + events = uhdev.next_sync_events() 593 + self.debug_reports(r, uhdev, events) 594 + 595 + slot = self.get_slot(uhdev, t0, 0) 596 + 597 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events 598 + assert evdev.slots[slot][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0 599 + assert evdev.slots[slot][libevdev.EV_ABS.ABS_MT_POSITION_X] == 50 600 + assert evdev.slots[slot][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 100 601 + 602 + t0.tipswitch = False 603 + if uhdev.quirks is None or "VALID_IS_INRANGE" not in uhdev.quirks: 604 + t0.inrange = False 605 + r = uhdev.event([t0]) 606 + events = uhdev.next_sync_events() 607 + self.debug_reports(r, uhdev, events) 608 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 0) in events 609 + assert evdev.slots[slot][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 610 + 611 + def test_mt_dual_touch(self): 612 + """Send 2 touches in the first 2 slots. 613 + Make sure the kernel sees this as a dual touch. 614 + Release and check 615 + 616 + Note: PTP will send here BTN_DOUBLETAP emulation""" 617 + uhdev = self.uhdev 618 + evdev = uhdev.get_evdev() 619 + 620 + t0 = Touch(1, 50, 100) 621 + t1 = Touch(2, 150, 200) 622 + 623 + if uhdev.quirks is not None and ( 624 + "SLOT_IS_CONTACTID" in uhdev.quirks 625 + or "SLOT_IS_CONTACTNUMBER" in uhdev.quirks 626 + ): 627 + t1.contactid = 0 628 + 629 + slot0 = self.get_slot(uhdev, t0, 0) 630 + slot1 = self.get_slot(uhdev, t1, 1) 631 + 632 + r = uhdev.event([t0]) 633 + events = uhdev.next_sync_events() 634 + self.debug_reports(r, uhdev, events) 635 + 636 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events 637 + assert evdev.value[libevdev.EV_KEY.BTN_TOUCH] == 1 638 + assert evdev.slots[slot0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0 639 + assert evdev.slots[slot0][libevdev.EV_ABS.ABS_MT_POSITION_X] == 50 640 + assert evdev.slots[slot0][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 100 641 + assert evdev.slots[slot1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 642 + 643 + r = uhdev.event([t0, t1]) 644 + events = uhdev.next_sync_events() 645 + self.debug_reports(r, uhdev, events) 646 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH) not in events 647 + assert evdev.value[libevdev.EV_KEY.BTN_TOUCH] == 1 648 + assert ( 649 + libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_X, 5) not in events 650 + ) 651 + assert ( 652 + libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_Y, 10) not in events 653 + ) 654 + assert evdev.slots[slot0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0 655 + assert evdev.slots[slot0][libevdev.EV_ABS.ABS_MT_POSITION_X] == 50 656 + assert evdev.slots[slot0][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 100 657 + assert evdev.slots[slot1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 1 658 + assert evdev.slots[slot1][libevdev.EV_ABS.ABS_MT_POSITION_X] == 150 659 + assert evdev.slots[slot1][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 200 660 + 661 + t0.tipswitch = False 662 + if uhdev.quirks is None or "VALID_IS_INRANGE" not in uhdev.quirks: 663 + t0.inrange = False 664 + r = uhdev.event([t0, t1]) 665 + events = uhdev.next_sync_events() 666 + self.debug_reports(r, uhdev, events) 667 + assert evdev.slots[slot0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 668 + assert evdev.slots[slot1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 1 669 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_X) not in events 670 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_Y) not in events 671 + 672 + t1.tipswitch = False 673 + if uhdev.quirks is None or "VALID_IS_INRANGE" not in uhdev.quirks: 674 + t1.inrange = False 675 + 676 + if uhdev.quirks is not None and "SLOT_IS_CONTACTNUMBER" in uhdev.quirks: 677 + r = uhdev.event([t0, t1]) 678 + else: 679 + r = uhdev.event([t1]) 680 + 681 + events = uhdev.next_sync_events() 682 + self.debug_reports(r, uhdev, events) 683 + assert evdev.slots[slot0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 684 + assert evdev.slots[slot1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 685 + 686 + @pytest.mark.skip_if_uhdev( 687 + lambda uhdev: uhdev.max_contacts <= 2, "Device not compatible" 688 + ) 689 + def test_mt_triple_tap(self): 690 + """Send 3 touches in the first 3 slots. 691 + Make sure the kernel sees this as a triple touch. 692 + Release and check 693 + 694 + Note: PTP will send here BTN_TRIPLETAP emulation""" 695 + uhdev = self.uhdev 696 + evdev = uhdev.get_evdev() 697 + 698 + t0 = Touch(1, 50, 100) 699 + t1 = Touch(2, 150, 200) 700 + t2 = Touch(3, 250, 300) 701 + r = uhdev.event([t0, t1, t2]) 702 + events = uhdev.next_sync_events() 703 + self.debug_reports(r, uhdev, events) 704 + 705 + slot0 = self.get_slot(uhdev, t0, 0) 706 + slot1 = self.get_slot(uhdev, t1, 1) 707 + slot2 = self.get_slot(uhdev, t2, 2) 708 + 709 + assert evdev.slots[slot0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0 710 + assert evdev.slots[slot0][libevdev.EV_ABS.ABS_MT_POSITION_X] == 50 711 + assert evdev.slots[slot0][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 100 712 + assert evdev.slots[slot1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 1 713 + assert evdev.slots[slot1][libevdev.EV_ABS.ABS_MT_POSITION_X] == 150 714 + assert evdev.slots[slot1][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 200 715 + assert evdev.slots[slot2][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 2 716 + assert evdev.slots[slot2][libevdev.EV_ABS.ABS_MT_POSITION_X] == 250 717 + assert evdev.slots[slot2][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 300 718 + 719 + t0.tipswitch = False 720 + t1.tipswitch = False 721 + t2.tipswitch = False 722 + if uhdev.quirks is None or "VALID_IS_INRANGE" not in uhdev.quirks: 723 + t0.inrange = False 724 + t1.inrange = False 725 + t2.inrange = False 726 + r = uhdev.event([t0, t1, t2]) 727 + events = uhdev.next_sync_events() 728 + self.debug_reports(r, uhdev, events) 729 + 730 + assert evdev.slots[slot0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 731 + assert evdev.slots[slot1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 732 + assert evdev.slots[slot2][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 733 + 734 + @pytest.mark.skip_if_uhdev( 735 + lambda uhdev: uhdev.max_contacts <= 2, "Device not compatible" 736 + ) 737 + def test_mt_max_contact(self): 738 + """send the maximum number of contact as reported by the device. 739 + Make sure all contacts are forwarded and that there is no miss. 740 + Release and check.""" 741 + uhdev = self.uhdev 742 + evdev = uhdev.get_evdev() 743 + 744 + touches = [ 745 + Touch(i, (i + 3) * 20, (i + 3) * 20 + 5) 746 + for i in range(uhdev.max_contacts) 747 + ] 748 + if ( 749 + uhdev.quirks is not None 750 + and "SLOT_IS_CONTACTID_MINUS_ONE" in uhdev.quirks 751 + ): 752 + for t in touches: 753 + t.contactid += 1 754 + r = uhdev.event(touches) 755 + events = uhdev.next_sync_events() 756 + self.debug_reports(r, uhdev, events) 757 + for i, t in enumerate(touches): 758 + slot = self.get_slot(uhdev, t, i) 759 + 760 + assert evdev.slots[slot][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == i 761 + assert evdev.slots[slot][libevdev.EV_ABS.ABS_MT_POSITION_X] == t.x 762 + assert evdev.slots[slot][libevdev.EV_ABS.ABS_MT_POSITION_Y] == t.y 763 + 764 + for t in touches: 765 + t.tipswitch = False 766 + if uhdev.quirks is None or "VALID_IS_INRANGE" not in uhdev.quirks: 767 + t.inrange = False 768 + 769 + r = uhdev.event(touches) 770 + events = uhdev.next_sync_events() 771 + self.debug_reports(r, uhdev, events) 772 + for i, t in enumerate(touches): 773 + slot = self.get_slot(uhdev, t, i) 774 + 775 + assert evdev.slots[slot][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 776 + 777 + @pytest.mark.skip_if_uhdev( 778 + lambda uhdev: ( 779 + uhdev.touches_in_a_report == 1 780 + or uhdev.quirks is not None 781 + and "CONTACT_CNT_ACCURATE" not in uhdev.quirks 782 + ), 783 + "Device not compatible, we can not trigger the conditions", 784 + ) 785 + def test_mt_contact_count_accurate(self): 786 + """Test the MT_QUIRK_CONTACT_CNT_ACCURATE from the kernel. 787 + A report should forward an accurate contact count and the kernel 788 + should ignore any data provided after we have reached this 789 + contact count.""" 790 + uhdev = self.uhdev 791 + evdev = uhdev.get_evdev() 792 + 793 + t0 = Touch(1, 50, 100) 794 + t1 = Touch(2, 150, 200) 795 + 796 + slot0 = self.get_slot(uhdev, t0, 0) 797 + slot1 = self.get_slot(uhdev, t1, 1) 798 + 799 + r = uhdev.event([t0, t1], contact_count=1) 800 + events = uhdev.next_sync_events() 801 + self.debug_reports(r, uhdev, events) 802 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events 803 + assert evdev.value[libevdev.EV_KEY.BTN_TOUCH] == 1 804 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_TRACKING_ID, 0) in events 805 + assert evdev.slots[slot0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0 806 + assert evdev.slots[slot0][libevdev.EV_ABS.ABS_MT_POSITION_X] == 50 807 + assert evdev.slots[slot0][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 100 808 + assert evdev.slots[slot1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 809 + 810 + class TestWin8Multitouch(TestMultitouch): 811 + def test_required_usages8(self): 812 + """Make sure the device exports the correct required features and 813 + inputs.""" 814 + uhdev = self.uhdev 815 + rdesc = uhdev.parsed_rdesc 816 + for feature in rdesc.feature_reports.values(): 817 + for field in feature: 818 + page_id = field.usage >> 16 819 + value = field.usage & 0xFF 820 + try: 821 + if HUT[page_id][value] == "Inputmode": 822 + assert HUT[field.application] not in ["Touch Screen"] 823 + except KeyError: 824 + pass 825 + 826 + @pytest.mark.skip_if_uhdev( 827 + lambda uhdev: uhdev.fields.count("X") == uhdev.touches_in_a_report, 828 + "Device not compatible, we can not trigger the conditions", 829 + ) 830 + def test_mt_tx_cx(self): 831 + """send a single touch in the first slot of the device, with 832 + different values of Tx and Cx. Make sure the kernel reports Tx.""" 833 + uhdev = self.uhdev 834 + evdev = uhdev.get_evdev() 835 + 836 + t0 = Touch(1, 5, 10) 837 + t0.cx = 50 838 + t0.cy = 100 839 + r = uhdev.event([t0]) 840 + events = uhdev.next_sync_events() 841 + self.debug_reports(r, uhdev, events) 842 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events 843 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0 844 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_X] == 5 845 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TOOL_X] == 50 846 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 10 847 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TOOL_Y] == 100 848 + 849 + @pytest.mark.skip_if_uhdev( 850 + lambda uhdev: "In Range" not in uhdev.fields, 851 + "Device not compatible, missing In Range usage", 852 + ) 853 + def test_mt_inrange(self): 854 + """Send one contact that has the InRange bit set before/after 855 + tipswitch. 856 + Kernel is supposed to mark the contact with a distance > 0 857 + when inrange is set but not tipswitch. 858 + 859 + This tests the hovering capability of devices (MT_QUIRK_HOVERING). 860 + 861 + Make sure the contact is only released from the kernel POV 862 + when the inrange bit is set to 0.""" 863 + uhdev = self.uhdev 864 + evdev = uhdev.get_evdev() 865 + 866 + t0 = Touch(1, 150, 200) 867 + t0.tipswitch = False 868 + r = uhdev.event([t0]) 869 + events = uhdev.next_sync_events() 870 + self.debug_reports(r, uhdev, events) 871 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events 872 + assert evdev.value[libevdev.EV_KEY.BTN_TOUCH] == 1 873 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_TRACKING_ID, 0) in events 874 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_DISTANCE) in events 875 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_DISTANCE] > 0 876 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0 877 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_X] == 150 878 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 200 879 + assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 880 + 881 + t0.tipswitch = True 882 + r = uhdev.event([t0]) 883 + events = uhdev.next_sync_events() 884 + self.debug_reports(r, uhdev, events) 885 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_DISTANCE, 0) in events 886 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_DISTANCE] == 0 887 + 888 + t0.tipswitch = False 889 + r = uhdev.event([t0]) 890 + events = uhdev.next_sync_events() 891 + self.debug_reports(r, uhdev, events) 892 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_DISTANCE) in events 893 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_DISTANCE] > 0 894 + 895 + t0.inrange = False 896 + r = uhdev.event([t0]) 897 + events = uhdev.next_sync_events() 898 + self.debug_reports(r, uhdev, events) 899 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 0) in events 900 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 901 + 902 + def test_mt_duplicates(self): 903 + """Test the MT_QUIRK_IGNORE_DUPLICATES from the kernel. 904 + If a touch is reported more than once with the same Contact ID, 905 + we should only handle the first touch. 906 + 907 + Note: this is not in MS spec, but the current kernel behaves 908 + like that""" 909 + uhdev = self.uhdev 910 + evdev = uhdev.get_evdev() 911 + 912 + t0 = Touch(1, 5, 10) 913 + t1 = Touch(1, 15, 20) 914 + t2 = Touch(2, 50, 100) 915 + 916 + r = uhdev.event([t0, t1, t2], contact_count=2) 917 + events = uhdev.next_sync_events() 918 + self.debug_reports(r, uhdev, events) 919 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events 920 + assert evdev.value[libevdev.EV_KEY.BTN_TOUCH] == 1 921 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_TRACKING_ID, 0) in events 922 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0 923 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_X] == 5 924 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 10 925 + assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 1 926 + assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_POSITION_X] == 50 927 + assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 100 928 + 929 + def test_mt_release_miss(self): 930 + """send a single touch in the first slot of the device, and 931 + forget to release it. The kernel is supposed to release by itself 932 + the touch in 100ms. 933 + Make sure that we are dealing with a new touch by resending the 934 + same touch after the timeout expired, and check that the kernel 935 + considers it as a separate touch (different tracking ID)""" 936 + uhdev = self.uhdev 937 + evdev = uhdev.get_evdev() 938 + 939 + t0 = Touch(1, 5, 10) 940 + r = uhdev.event([t0]) 941 + events = uhdev.next_sync_events() 942 + self.debug_reports(r, uhdev, events) 943 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0 944 + 945 + time.sleep(0.2) 946 + events = uhdev.next_sync_events() 947 + self.debug_reports(r, uhdev, events) 948 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 0) in events 949 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 950 + 951 + r = uhdev.event([t0]) 952 + events = uhdev.next_sync_events() 953 + self.debug_reports(r, uhdev, events) 954 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 1 955 + 956 + @pytest.mark.skip_if_uhdev( 957 + lambda uhdev: "Azimuth" not in uhdev.fields, 958 + "Device not compatible, missing Azimuth usage", 959 + ) 960 + def test_mt_azimuth(self): 961 + """Check for the azimtuh information bit. 962 + When azimuth is presented by the device, it should be exported 963 + as ABS_MT_ORIENTATION and the exported value should report a quarter 964 + of circle.""" 965 + uhdev = self.uhdev 966 + 967 + t0 = Touch(1, 5, 10) 968 + t0.azimuth = 270 969 + 970 + r = uhdev.event([t0]) 971 + events = uhdev.next_sync_events() 972 + self.debug_reports(r, uhdev, events) 973 + 974 + # orientation is clockwise, while Azimuth is counter clockwise 975 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_ORIENTATION, 90) in events 976 + 977 + class TestPTP(TestWin8Multitouch): 978 + def test_ptp_buttons(self): 979 + """check for button reliability. 980 + There are 2 types of touchpads: the click pads and the pressure pads. 981 + Each should reliably report the BTN_LEFT events. 982 + """ 983 + uhdev = self.uhdev 984 + evdev = uhdev.get_evdev() 985 + 986 + if uhdev.type == "clickpad": 987 + r = uhdev.event(click=True) 988 + events = uhdev.next_sync_events() 989 + self.debug_reports(r, uhdev, events) 990 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 1) in events 991 + assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 1 992 + 993 + r = uhdev.event(click=False) 994 + events = uhdev.next_sync_events() 995 + self.debug_reports(r, uhdev, events) 996 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 0) in events 997 + assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 0 998 + else: 999 + r = uhdev.event(left=True) 1000 + events = uhdev.next_sync_events() 1001 + self.debug_reports(r, uhdev, events) 1002 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 1) in events 1003 + assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 1 1004 + 1005 + r = uhdev.event(left=False) 1006 + events = uhdev.next_sync_events() 1007 + self.debug_reports(r, uhdev, events) 1008 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 0) in events 1009 + assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 0 1010 + 1011 + r = uhdev.event(right=True) 1012 + events = uhdev.next_sync_events() 1013 + self.debug_reports(r, uhdev, events) 1014 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_RIGHT, 1) in events 1015 + assert evdev.value[libevdev.EV_KEY.BTN_RIGHT] == 1 1016 + 1017 + r = uhdev.event(right=False) 1018 + events = uhdev.next_sync_events() 1019 + self.debug_reports(r, uhdev, events) 1020 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_RIGHT, 0) in events 1021 + assert evdev.value[libevdev.EV_KEY.BTN_RIGHT] == 0 1022 + 1023 + @pytest.mark.skip_if_uhdev( 1024 + lambda uhdev: "Confidence" not in uhdev.fields, 1025 + "Device not compatible, missing Confidence usage", 1026 + ) 1027 + def test_ptp_confidence(self): 1028 + """Check for the validity of the confidence bit. 1029 + When a contact is marked as not confident, it should be detected 1030 + as a palm from the kernel POV and released. 1031 + 1032 + Note: if the kernel exports ABS_MT_TOOL_TYPE, it shouldn't release 1033 + the touch but instead convert it to ABS_MT_TOOL_PALM.""" 1034 + uhdev = self.uhdev 1035 + evdev = uhdev.get_evdev() 1036 + 1037 + t0 = Touch(1, 150, 200) 1038 + r = uhdev.event([t0]) 1039 + events = uhdev.next_sync_events() 1040 + self.debug_reports(r, uhdev, events) 1041 + 1042 + t0.confidence = False 1043 + r = uhdev.event([t0]) 1044 + events = uhdev.next_sync_events() 1045 + self.debug_reports(r, uhdev, events) 1046 + 1047 + if evdev.absinfo[libevdev.EV_ABS.ABS_MT_TOOL_TYPE] is not None: 1048 + # the kernel exports MT_TOOL_PALM 1049 + assert ( 1050 + libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_TOOL_TYPE, 2) in events 1051 + ) 1052 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] != -1 1053 + 1054 + t0.tipswitch = False 1055 + r = uhdev.event([t0]) 1056 + events = uhdev.next_sync_events() 1057 + self.debug_reports(r, uhdev, events) 1058 + 1059 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 0) in events 1060 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 1061 + 1062 + @pytest.mark.skip_if_uhdev( 1063 + lambda uhdev: uhdev.touches_in_a_report >= uhdev.max_contacts, 1064 + "Device not compatible, we can not trigger the conditions", 1065 + ) 1066 + def test_ptp_non_touch_data(self): 1067 + """Some single finger hybrid touchpads might not provide the 1068 + button information in subsequent reports (only in the first report). 1069 + 1070 + Emulate this and make sure we do not release the buttons in the 1071 + middle of the event.""" 1072 + uhdev = self.uhdev 1073 + evdev = uhdev.get_evdev() 1074 + 1075 + touches = [Touch(i, i * 10, i * 10 + 5) for i in range(uhdev.max_contacts)] 1076 + contact_count = uhdev.max_contacts 1077 + incr_scantime = True 1078 + btn_state = True 1079 + events = None 1080 + while touches: 1081 + t = touches[: uhdev.touches_in_a_report] 1082 + touches = touches[uhdev.touches_in_a_report :] 1083 + r = uhdev.event( 1084 + t, 1085 + click=btn_state, 1086 + left=btn_state, 1087 + contact_count=contact_count, 1088 + incr_scantime=incr_scantime, 1089 + ) 1090 + contact_count = 0 1091 + incr_scantime = False 1092 + btn_state = False 1093 + events = uhdev.next_sync_events() 1094 + self.debug_reports(r, uhdev, events) 1095 + if touches: 1096 + assert len(events) == 0 1097 + 1098 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 1) in events 1099 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 0) not in events 1100 + assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 1 1101 + 1102 + 1103 + ################################################################################ 1104 + # 1105 + # Windows 7 compatible devices 1106 + # 1107 + ################################################################################ 1108 + class Test3m_0596_0500(BaseTest.TestMultitouch): 1109 + def create_device(self): 1110 + return Digitizer( 1111 + "uhid test 3m_0596_0500", 1112 + rdesc="05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 09 01 95 01 75 01 15 00 25 01 81 02 95 07 75 01 81 03 95 01 75 08 81 03 05 01 09 30 09 31 15 00 26 ff 7f 35 00 46 00 00 95 02 75 10 81 02 c0 a1 02 15 00 26 ff 00 09 01 95 39 75 08 81 01 c0 c0 05 0d 09 0e a1 01 85 11 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 09 04 a1 01 85 10 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 3a 06 81 02 09 31 46 e8 03 81 02 c0 05 0d a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 3a 06 81 02 09 31 46 e8 03 81 02 c0 05 0d a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 3a 06 81 02 09 31 46 e8 03 81 02 c0 05 0d a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 3a 06 81 02 09 31 46 e8 03 81 02 c0 05 0d a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 3a 06 81 02 09 31 46 e8 03 81 02 c0 05 0d a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 3a 06 81 02 09 31 46 e8 03 81 02 c0 05 0d a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 3a 06 81 02 09 31 46 e8 03 81 02 c0 05 0d a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 3a 06 81 02 09 31 46 e8 03 81 02 c0 05 0d a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 3a 06 81 02 09 31 46 e8 03 81 02 c0 05 0d a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 3a 06 81 02 09 31 46 e8 03 81 02 c0 05 0d 09 54 95 01 75 08 15 00 25 0a 81 02 85 12 09 55 95 01 75 08 15 00 25 0a b1 02 06 00 ff 15 00 26 ff 00 85 03 09 01 75 08 95 07 b1 02 85 04 09 01 75 08 95 17 b1 02 85 05 09 01 75 08 95 47 b1 02 85 06 09 01 75 08 95 07 b1 02 85 07 09 01 75 08 95 07 b1 02 85 08 09 01 75 08 95 07 b1 02 85 09 09 01 75 08 95 3f b1 02 c0", 1113 + input_info=(BusType.USB, 0x0596, 0x0500), 1114 + max_contacts=60, 1115 + quirks=("VALID_IS_CONFIDENCE", "SLOT_IS_CONTACTID", "TOUCH_SIZE_SCALING"), 1116 + ) 1117 + 1118 + 1119 + class Test3m_0596_0506(BaseTest.TestMultitouch): 1120 + def create_device(self): 1121 + return Digitizer( 1122 + "uhid test 3m_0596_0506", 1123 + rdesc="05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 09 01 95 01 75 01 15 00 25 01 81 02 95 07 75 01 81 03 95 01 75 08 81 03 05 01 09 30 09 31 15 00 26 ff 7f 35 00 46 00 00 95 02 75 10 81 02 c0 a1 02 15 00 26 ff 00 09 01 95 39 75 08 81 03 c0 c0 05 0d 09 0e a1 01 85 11 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 09 04 a1 01 85 13 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 d6 0a 81 02 09 31 46 22 06 81 02 05 0d 75 10 95 01 09 48 81 02 09 49 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 d6 0a 81 02 09 31 46 22 06 81 02 05 0d 75 10 95 01 09 48 81 02 09 49 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 d6 0a 81 02 09 31 46 22 06 81 02 05 0d 75 10 95 01 09 48 81 02 09 49 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 d6 0a 81 02 09 31 46 22 06 81 02 05 0d 75 10 95 01 09 48 81 02 09 49 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 d6 0a 81 02 09 31 46 22 06 81 02 05 0d 75 10 95 01 09 48 81 02 09 49 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 d6 0a 81 02 09 31 46 22 06 81 02 05 0d 75 10 95 01 09 48 81 02 09 49 81 02 c0 05 0d 09 54 95 01 75 08 15 00 25 3c 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 02 81 03 05 0d 85 12 09 55 95 01 75 08 15 00 25 3c b1 02 06 00 ff 15 00 26 ff 00 85 03 09 01 75 08 95 07 b1 02 85 04 09 01 75 08 95 17 b1 02 85 05 09 01 75 08 95 47 b1 02 85 06 09 01 75 08 95 07 b1 02 85 73 09 01 75 08 95 07 b1 02 85 08 09 01 75 08 95 07 b1 02 85 09 09 01 75 08 95 3f b1 02 85 0f 09 01 75 08 96 07 02 b1 02 c0", 1124 + input_info=(BusType.USB, 0x0596, 0x0506), 1125 + max_contacts=60, 1126 + quirks=("VALID_IS_CONFIDENCE", "SLOT_IS_CONTACTID", "TOUCH_SIZE_SCALING"), 1127 + ) 1128 + 1129 + 1130 + class TestActionStar_2101_1011(BaseTest.TestMultitouch): 1131 + def create_device(self): 1132 + return Digitizer( 1133 + "uhid test ActionStar_2101_1011", 1134 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 81 02 05 01 35 00 55 0e 65 33 75 10 95 01 09 30 26 ff 4d 46 70 03 81 02 09 31 26 ff 2b 46 f1 01 81 02 46 00 00 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 81 02 05 01 35 00 55 0e 65 33 75 10 95 01 09 30 26 ff 4d 46 70 03 81 02 09 31 26 ff 2b 46 f1 01 81 02 46 00 00 c0 05 0d 09 54 75 08 95 01 81 02 05 0d 85 02 09 55 25 02 75 08 95 01 b1 02 c0", 1135 + input_info=(BusType.USB, 0x2101, 0x1011), 1136 + ) 1137 + 1138 + def test_mt_actionstar_inrange(self): 1139 + """Special sequence that might not be handled properly""" 1140 + uhdev = self.uhdev 1141 + evdev = uhdev.get_evdev() 1142 + 1143 + # fmt: off 1144 + sequence = [ 1145 + # t0 = Touch(1, 6999, 2441) | t1 = Touch(2, 15227, 2026) 1146 + '01 ff 01 57 1b 89 09 ff 02 7b 3b ea 07 02', 1147 + # t0.xy = (6996, 2450) | t1.y = 2028 1148 + '01 ff 01 54 1b 92 09 ff 02 7b 3b ec 07 02', 1149 + # t1.xy = (15233, 2040) | t0.tipswitch = False 1150 + '01 ff 02 81 3b f8 07 fe 01 54 1b 92 09 02', 1151 + # t1 | t0.inrange = False 1152 + '01 ff 02 81 3b f8 07 fc 01 54 1b 92 09 02', 1153 + ] 1154 + # fmt: on 1155 + 1156 + for num, r_str in enumerate(sequence): 1157 + r = [int(i, 16) for i in r_str.split()] 1158 + uhdev.call_input_event(r) 1159 + events = uhdev.next_sync_events() 1160 + self.debug_reports([r], uhdev) 1161 + for e in events: 1162 + print(e) 1163 + if num == 2: 1164 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 1165 + 1166 + 1167 + class TestAsus_computers_0486_0185(BaseTest.TestMultitouch): 1168 + def create_device(self): 1169 + return Digitizer( 1170 + "uhid test asus-computers_0486_0185", 1171 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 95 01 75 01 81 02 09 32 81 02 09 47 81 02 75 05 81 03 09 30 26 ff 00 75 08 81 02 09 51 25 02 81 02 26 96 0d 05 01 75 10 55 0d 65 33 09 30 35 00 46 fd 1d 81 02 09 31 46 60 11 81 02 c0 09 22 a1 02 05 0d 35 00 45 00 55 00 65 00 09 42 25 01 75 01 81 02 09 32 81 02 09 47 81 02 75 05 81 03 09 30 26 ff 00 75 08 81 02 09 51 25 02 81 02 26 96 0d 05 01 75 10 55 0d 65 33 09 30 46 fd 1d 81 02 09 31 46 60 11 81 02 c0 35 00 45 00 55 00 65 00 05 0d 09 54 75 08 25 02 81 02 85 08 09 55 b1 02 c0 09 0e a1 01 85 07 09 22 a1 00 09 52 25 0a b1 02 c0 05 0c 09 01 a1 01 85 06 09 01 26 ff 00 95 08 b1 02 c0 c0 05 01 09 02 a1 01 85 03 09 01 a1 00 05 09 19 01 29 02 25 01 75 01 95 02 81 02 95 06 81 03 26 96 0d 05 01 75 10 95 01 55 0d 65 33 09 30 46 fd 1d 81 02 09 31 46 60 11 81 02 c0 c0 06 ff 01 09 01 a1 01 26 ff 00 35 00 45 00 55 00 65 00 85 05 75 08 95 3f 09 00 81 02 c0", 1172 + input_info=(BusType.USB, 0x0486, 0x0185), 1173 + quirks=("VALID_IS_CONFIDENCE", "SLOT_IS_CONTACTID_MINUS_ONE"), 1174 + ) 1175 + 1176 + 1177 + class TestAtmel_03eb_201c(BaseTest.TestMultitouch): 1178 + def create_device(self): 1179 + return Digitizer( 1180 + "uhid test atmel_03eb_201c", 1181 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 81 02 05 01 35 00 55 0e 65 33 75 10 95 01 09 30 26 ff 4b 46 70 03 81 02 09 31 26 ff 2b 46 f1 01 81 02 46 00 00 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 81 02 05 01 35 00 55 0e 65 33 75 10 95 01 09 30 26 ff 4b 46 70 03 81 02 09 31 26 ff 2b 46 f1 01 81 02 46 00 00 c0 05 0d 09 54 75 08 95 01 81 02 05 0d 85 02 09 55 25 02 75 08 95 01 b1 02 c0", 1182 + input_info=(BusType.USB, 0x03EB, 0x201C), 1183 + ) 1184 + 1185 + 1186 + class TestAtmel_03eb_211c(BaseTest.TestMultitouch): 1187 + def create_device(self): 1188 + return Digitizer( 1189 + "uhid test atmel_03eb_211c", 1190 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 37 81 02 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 46 56 0a 26 ff 0f 09 30 81 02 46 b2 05 26 ff 0f 09 31 81 02 05 0d 75 08 85 02 09 55 25 10 b1 02 c0 c0", 1191 + input_info=(BusType.USB, 0x03EB, 0x211C), 1192 + ) 1193 + 1194 + 1195 + class TestCando_2087_0a02(BaseTest.TestMultitouch): 1196 + def create_device(self): 1197 + return Digitizer( 1198 + "uhid test cando_2087_0a02", 1199 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 0f 75 10 55 0e 65 33 09 30 35 00 46 6d 03 81 02 46 ec 01 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 0f 75 10 55 0e 65 33 09 30 35 00 46 6d 03 81 02 46 ec 01 09 31 81 02 c0 05 0d 09 54 95 01 75 08 15 00 25 02 81 02 85 02 09 55 b1 02 c0 06 00 ff 09 01 a1 01 85 a6 95 22 75 08 26 ff 00 15 00 09 01 81 02 85 a5 95 06 75 08 26 ff 00 15 00 09 01 91 02 c0", 1200 + input_info=(BusType.USB, 0x2087, 0x0A02), 1201 + ) 1202 + 1203 + 1204 + class TestCando_2087_0b03(BaseTest.TestMultitouch): 1205 + def create_device(self): 1206 + return Digitizer( 1207 + "uhid test cando_2087_0b03", 1208 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 81 02 05 01 35 00 55 0e 65 33 75 10 95 01 09 30 26 ff 49 46 f2 03 81 02 09 31 26 ff 29 46 39 02 81 02 46 00 00 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 81 02 05 01 35 00 55 0e 65 33 75 10 95 01 09 30 26 ff 49 46 f2 03 81 02 09 31 26 ff 29 46 39 02 81 02 46 00 00 c0 05 0d 09 54 75 08 95 01 81 02 05 0d 85 02 09 55 25 02 75 08 95 01 b1 02 c0", 1209 + input_info=(BusType.USB, 0x2087, 0x0B03), 1210 + ) 1211 + 1212 + 1213 + class TestCVTouch_1ff7_0013(BaseTest.TestMultitouch): 1214 + def create_device(self): 1215 + return Digitizer( 1216 + "uhid test cvtouch_1ff7_0013", 1217 + rdesc="06 00 ff 09 00 a1 01 85 fd 06 00 ff 09 01 09 02 09 03 09 04 09 05 09 06 15 00 26 ff 00 75 08 95 06 81 02 85 fe 06 00 ff 09 01 09 02 09 03 09 04 15 00 26 ff 00 75 08 95 04 b1 02 c0 05 01 09 02 a1 01 09 01 a1 00 85 01 05 09 19 01 29 03 15 00 25 01 95 03 75 01 81 02 95 01 75 05 81 03 05 01 09 30 09 31 15 00 26 ff 7f 35 00 46 ff 7f 75 10 95 02 81 02 05 0d 09 33 15 00 26 ff 00 35 00 46 ff 00 75 08 95 01 81 02 05 01 09 38 15 81 25 7f 35 81 45 7f 95 01 81 06 c0 c0 06 00 ff 09 00 a1 01 85 fc 15 00 26 ff 00 19 01 29 3f 75 08 95 3f 81 02 19 01 29 3f 91 02 c0 06 00 ff 09 00 a1 01 85 fb 15 00 26 ff 00 19 01 29 3f 75 08 95 3f 81 02 19 01 29 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 15 00 26 ff 7f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 15 00 26 ff 7f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 15 00 26 ff 7f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 15 00 26 ff 7f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 15 00 26 ff 7f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 15 00 26 ff 7f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 81 02 c0 05 0d 09 54 15 00 26 ff 00 95 01 75 08 81 02 85 03 09 55 15 00 25 02 b1 02 c0 09 0e a1 01 85 04 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0", 1218 + input_info=(BusType.USB, 0x1FF7, 0x0013), 1219 + quirks=("NOT_SEEN_MEANS_UP",), 1220 + ) 1221 + 1222 + 1223 + class TestCvtouch_1ff7_0017(BaseTest.TestMultitouch): 1224 + def create_device(self): 1225 + return Digitizer( 1226 + "uhid test cvtouch_1ff7_0017", 1227 + rdesc="06 00 ff 09 00 a1 01 85 fd 06 00 ff 09 01 09 02 09 03 09 04 09 05 09 06 15 00 26 ff 00 75 08 95 06 81 02 85 fe 06 00 ff 09 01 09 02 09 03 09 04 15 00 26 ff 00 75 08 95 04 b1 02 c0 05 01 09 02 a1 01 09 01 a1 00 85 01 05 09 19 01 29 03 15 00 25 01 95 03 75 01 81 02 95 01 75 05 81 03 05 01 09 30 09 31 15 00 26 ff 0f 35 00 46 ff 0f 75 10 95 02 81 02 09 00 15 00 25 ff 35 00 45 ff 75 08 95 01 81 02 09 38 15 81 25 7f 95 01 81 06 c0 c0 06 00 ff 09 00 a1 01 85 fc 15 00 25 ff 19 01 29 3f 75 08 95 3f 81 02 19 01 29 3f 91 02 c0 06 00 ff 09 00 a1 01 85 fb 15 00 25 ff 19 01 29 3f 75 08 95 3f 81 02 19 01 29 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 15 00 26 ff 0f 75 10 55 00 65 00 09 30 35 00 46 ff 0f 81 02 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 15 00 26 ff 0f 75 10 55 00 65 00 09 30 35 00 46 ff 0f 81 02 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 15 00 26 ff 0f 75 10 55 00 65 00 09 30 35 00 46 ff 0f 81 02 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 15 00 26 ff 0f 75 10 55 00 65 00 09 30 35 00 46 ff 0f 81 02 09 31 81 02 c0 05 0d 09 54 95 01 75 08 81 02 85 03 09 55 25 02 b1 02 c0 09 0e a1 01 85 04 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0", 1228 + input_info=(BusType.USB, 0x1FF7, 0x0017), 1229 + ) 1230 + 1231 + 1232 + class TestCypress_04b4_c001(BaseTest.TestMultitouch): 1233 + def create_device(self): 1234 + return Digitizer( 1235 + "uhid test cypress_04b4_c001", 1236 + rdesc="05 01 09 02 a1 01 85 01 09 01 a1 00 05 09 19 01 29 03 15 00 25 01 95 03 75 01 81 02 95 01 75 05 81 01 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0 05 0d 09 04 a1 01 85 02 09 22 09 53 95 01 75 08 81 02 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 15 00 25 20 09 48 81 02 09 49 81 02 05 01 15 00 26 d0 07 75 10 55 00 65 00 09 30 15 00 26 d0 07 35 00 45 00 81 02 09 31 45 00 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 15 00 25 20 09 48 81 02 09 49 81 02 05 01 15 00 26 d0 07 75 10 55 00 65 00 09 30 15 00 26 d0 07 35 00 45 00 81 02 09 31 45 00 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 15 00 25 20 09 48 81 02 09 49 81 02 05 01 15 00 26 d0 07 75 10 55 00 65 00 09 30 15 00 26 d0 07 35 00 45 00 81 02 09 31 45 00 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 15 00 25 20 09 48 81 02 09 49 81 02 05 01 15 00 26 d0 07 75 10 55 00 65 00 09 30 15 00 26 d0 07 35 00 45 00 81 02 09 31 45 00 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 15 00 25 20 09 48 81 02 09 49 81 02 05 01 15 00 26 d0 07 75 10 55 00 65 00 09 30 15 00 26 d0 07 35 00 45 00 81 02 09 31 45 00 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 15 00 25 20 09 48 81 02 09 49 81 02 05 01 15 00 26 d0 07 75 10 55 00 65 00 09 30 15 00 26 d0 07 35 00 45 00 81 02 09 31 45 00 81 02 c0 05 0d 09 54 95 01 75 08 15 00 25 0a 81 02 09 55 b1 02 c0 09 0e a1 01 85 03 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0", 1237 + input_info=(BusType.USB, 0x04B4, 0xC001), 1238 + ) 1239 + 1240 + 1241 + class TestData_modul_7374_1232(BaseTest.TestMultitouch): 1242 + def create_device(self): 1243 + return Digitizer( 1244 + "uhid test data-modul_7374_1232", 1245 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 37 81 02 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 46 d0 07 26 ff 0f 09 30 81 02 46 40 06 09 31 81 02 05 0d 75 08 85 02 09 55 25 10 b1 02 c0 c0", 1246 + input_info=(BusType.USB, 0x7374, 0x1232), 1247 + ) 1248 + 1249 + 1250 + class TestData_modul_7374_1252(BaseTest.TestMultitouch): 1251 + def create_device(self): 1252 + return Digitizer( 1253 + "uhid test data-modul_7374_1252", 1254 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 37 81 02 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 46 d0 07 26 ff 0f 09 30 81 02 46 40 06 09 31 81 02 05 0d 75 08 85 02 09 55 25 10 b1 02 c0 c0", 1255 + input_info=(BusType.USB, 0x7374, 0x1252), 1256 + ) 1257 + 1258 + 1259 + class TestE4_2219_044c(BaseTest.TestMultitouch): 1260 + def create_device(self): 1261 + return Digitizer( 1262 + "uhid test e4_2219_044c", 1263 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 46 00 00 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 46 00 00 81 02 c0 05 0d 09 54 95 01 75 08 15 00 25 08 81 02 09 55 b1 02 c0 09 0e a1 01 85 02 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 85 03 09 01 a1 00 05 09 19 01 29 03 15 00 25 01 95 03 75 01 81 02 95 01 75 05 81 01 05 01 09 30 09 31 15 00 26 ff 7f 75 10 95 02 81 02 05 01 09 38 15 81 25 7f 75 08 95 01 81 06 c0 c0", 1264 + input_info=(BusType.USB, 0x2219, 0x044C), 1265 + ) 1266 + 1267 + 1268 + class TestEgalax_capacitive_0eef_7224(BaseTest.TestMultitouch): 1269 + def create_device(self): 1270 + return Digitizer( 1271 + "uhid test egalax-capacitive_0eef_7224", 1272 + rdesc="05 0d 09 04 a1 01 85 04 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 15 00 25 01 81 02 09 51 75 05 95 01 16 00 00 26 10 00 81 02 09 47 75 01 95 01 15 00 25 01 81 02 05 01 09 30 75 10 95 01 55 0d 65 33 35 00 46 34 49 26 ff 7f 81 02 09 31 75 10 95 01 55 0d 65 33 35 00 46 37 29 26 ff 7f 81 02 05 0d 09 55 25 08 75 08 95 01 b1 02 c0 c0 05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 20 a1 00 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 75 01 81 03 05 01 09 30 75 10 95 01 a4 55 0d 65 33 36 00 00 46 34 49 16 00 00 26 ff 0f 81 02 09 31 16 00 00 26 ff 0f 36 00 00 46 37 29 81 02 b4 c0 c0 05 0d 09 0e a1 01 85 05 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0", 1273 + input_info=(BusType.USB, 0x0EEF, 0x7224), 1274 + quirks=("SLOT_IS_CONTACTID", "ALWAYS_VALID"), 1275 + ) 1276 + 1277 + 1278 + class TestEgalax_capacitive_0eef_72fa(BaseTest.TestMultitouch): 1279 + def create_device(self): 1280 + return Digitizer( 1281 + "uhid test egalax-capacitive_0eef_72fa", 1282 + rdesc="05 0d 09 04 a1 01 85 04 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 15 00 25 01 81 02 09 51 75 05 95 01 16 00 00 26 10 00 81 02 09 47 75 01 95 01 15 00 25 01 81 02 05 01 09 30 75 10 95 01 55 0d 65 33 35 00 46 72 22 26 ff 7f 81 02 09 31 75 10 95 01 55 0d 65 33 35 00 46 87 13 26 ff 7f 81 02 05 0d 09 55 25 08 75 08 95 01 b1 02 c0 c0 05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 20 a1 00 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 75 01 81 03 05 01 09 30 75 10 95 01 a4 55 0d 65 33 36 00 00 46 72 22 16 00 00 26 ff 0f 81 02 09 31 16 00 00 26 ff 0f 36 00 00 46 87 13 81 02 b4 c0 c0 05 0d 09 0e a1 01 85 05 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0", 1283 + input_info=(BusType.USB, 0x0EEF, 0x72FA), 1284 + quirks=("SLOT_IS_CONTACTID", "VALID_IS_INRANGE"), 1285 + ) 1286 + 1287 + 1288 + class TestEgalax_capacitive_0eef_7336(BaseTest.TestMultitouch): 1289 + def create_device(self): 1290 + return Digitizer( 1291 + "uhid test egalax-capacitive_0eef_7336", 1292 + rdesc="05 0d 09 04 a1 01 85 04 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 15 00 25 01 81 02 09 51 75 05 95 01 16 00 00 26 10 00 81 02 09 47 75 01 95 01 15 00 25 01 81 02 05 01 09 30 75 10 95 01 55 0d 65 33 35 00 46 c1 20 26 ff 7f 81 02 09 31 75 10 95 01 55 0d 65 33 35 00 46 c2 18 26 ff 7f 81 02 05 0d 09 55 25 08 75 08 95 01 b1 02 c0 c0 05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 20 a1 00 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 75 01 81 03 05 01 09 30 75 10 95 01 a4 55 0d 65 33 36 00 00 46 c1 20 16 00 00 26 ff 0f 81 02 09 31 16 00 00 26 ff 0f 36 00 00 46 c2 18 81 02 b4 c0 c0 05 0d 09 0e a1 01 85 05 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0", 1293 + input_info=(BusType.USB, 0x0EEF, 0x7336), 1294 + ) 1295 + 1296 + 1297 + class TestEgalax_capacitive_0eef_7337(BaseTest.TestMultitouch): 1298 + def create_device(self): 1299 + return Digitizer( 1300 + "uhid test egalax-capacitive_0eef_7337", 1301 + rdesc="05 0d 09 04 a1 01 85 04 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 15 00 25 01 81 02 09 51 75 05 95 01 16 00 00 26 10 00 81 02 09 47 75 01 95 01 15 00 25 01 81 02 05 01 09 30 75 10 95 01 55 0d 65 33 35 00 46 ae 17 26 ff 7f 81 02 09 31 75 10 95 01 55 0d 65 33 35 00 46 c3 0e 26 ff 7f 81 02 05 0d 09 55 25 08 75 08 95 01 b1 02 c0 c0 05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 20 a1 00 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 75 01 81 03 05 01 09 30 75 10 95 01 a4 55 0d 65 33 36 00 00 46 ae 17 16 00 00 26 ff 0f 81 02 09 31 16 00 00 26 ff 0f 36 00 00 46 c3 0e 81 02 b4 c0 c0 05 0d 09 0e a1 01 85 05 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0", 1302 + input_info=(BusType.USB, 0x0EEF, 0x7337), 1303 + ) 1304 + 1305 + 1306 + class TestEgalax_capacitive_0eef_7349(BaseTest.TestMultitouch): 1307 + def create_device(self): 1308 + return Digitizer( 1309 + "uhid test egalax-capacitive_0eef_7349", 1310 + rdesc="05 0d 09 04 a1 01 85 04 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 15 00 25 01 81 02 09 51 75 05 95 01 16 00 00 26 10 00 81 02 09 47 75 01 95 01 15 00 25 01 81 02 05 01 09 30 75 10 95 01 55 0d 65 33 35 00 46 34 49 26 ff 7f 81 02 09 31 75 10 95 01 55 0d 65 33 35 00 46 37 29 26 ff 7f 81 02 05 0d 09 55 25 08 75 08 95 01 b1 02 c0 c0 05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 20 a1 00 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 75 01 81 03 05 01 09 30 75 10 95 01 a4 55 0d 65 33 36 00 00 46 34 49 16 00 00 26 ff 0f 81 02 09 31 16 00 00 26 ff 0f 36 00 00 46 37 29 81 02 b4 c0 c0 05 0d 09 0e a1 01 85 05 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0", 1311 + input_info=(BusType.USB, 0x0EEF, 0x7349), 1312 + quirks=("SLOT_IS_CONTACTID", "ALWAYS_VALID"), 1313 + ) 1314 + 1315 + 1316 + class TestEgalax_capacitive_0eef_73f4(BaseTest.TestMultitouch): 1317 + def create_device(self): 1318 + return Digitizer( 1319 + "uhid test egalax-capacitive_0eef_73f4", 1320 + rdesc="05 0d 09 04 a1 01 85 04 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 15 00 25 01 81 02 09 51 75 05 95 01 16 00 00 26 10 00 81 02 09 47 75 01 95 01 15 00 25 01 81 02 05 01 09 30 75 10 95 01 55 0d 65 33 35 00 46 96 4e 26 ff 7f 81 02 09 31 75 10 95 01 55 0d 65 33 35 00 46 23 2c 26 ff 7f 81 02 05 0d 09 55 25 08 75 08 95 01 b1 02 c0 c0 05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 20 a1 00 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 75 01 81 03 05 01 09 30 75 10 95 01 a4 55 0d 65 33 36 00 00 46 96 4e 16 00 00 26 ff 0f 81 02 09 31 16 00 00 26 ff 0f 36 00 00 46 23 2c 81 02 b4 c0 c0 05 0d 09 0e a1 01 85 05 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0", 1321 + input_info=(BusType.USB, 0x0EEF, 0x73F4), 1322 + ) 1323 + 1324 + 1325 + class TestEgalax_capacitive_0eef_a001(BaseTest.TestMultitouch): 1326 + def create_device(self): 1327 + return Digitizer( 1328 + "uhid test egalax-capacitive_0eef_a001", 1329 + rdesc="05 0d 09 04 a1 01 85 04 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 15 00 25 01 81 02 09 51 75 05 95 01 16 00 00 26 10 00 81 02 09 47 75 01 95 01 15 00 25 01 81 02 05 01 09 30 75 10 95 01 55 0d 65 33 35 00 46 23 28 26 ff 7f 81 02 09 31 75 10 95 01 55 0d 65 33 35 00 46 11 19 26 ff 7f 81 02 05 0d 09 55 25 08 75 08 95 01 b1 02 c0 c0 05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 0e a1 01 85 05 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0", 1330 + input_info=(BusType.USB, 0x0EEF, 0xA001), 1331 + quirks=("SLOT_IS_CONTACTID", "VALID_IS_INRANGE"), 1332 + ) 1333 + 1334 + 1335 + class TestElo_touchsystems_04e7_0022(BaseTest.TestMultitouch): 1336 + def create_device(self): 1337 + return Digitizer( 1338 + "uhid test elo-touchsystems_04e7_0022", 1339 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 0f 75 10 55 0e 65 33 09 30 35 00 46 ff 0f 81 02 46 ff 0f 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 0f 75 10 55 00 65 00 09 30 35 00 46 ff 0f 81 02 46 ff 0f 09 31 81 02 c0 05 0d 09 54 25 10 95 01 75 08 81 02 85 08 09 55 25 02 b1 02 c0 09 0e a1 01 85 07 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 06 00 ff 09 55 85 80 15 00 26 ff 00 75 08 95 01 b1 82 c0 05 01 09 02 a1 01 85 54 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 15 00 26 ff 0f 75 10 95 01 81 02 09 31 75 10 95 01 81 02 09 3b 16 00 00 26 00 01 36 00 00 46 00 01 66 00 00 75 10 95 01 81 62 c0 c0", 1340 + input_info=(BusType.USB, 0x04E7, 0x0022), 1341 + ) 1342 + 1343 + 1344 + class TestElo_touchsystems_04e7_0080(BaseTest.TestMultitouch): 1345 + def create_device(self): 1346 + return Digitizer( 1347 + "uhid test elo-touchsystems_04e7_0080", 1348 + rdesc="05 0d 09 04 a1 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 03 81 03 09 32 09 47 95 02 81 02 95 02 81 03 09 51 75 08 95 01 81 02 05 01 26 ff 7f 65 11 55 0e 46 7c 24 75 10 95 01 09 30 81 02 09 31 46 96 14 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 95 03 81 03 09 32 09 47 95 02 81 02 95 02 81 03 09 51 75 08 95 01 81 02 05 01 26 ff 7f 65 11 55 0e 46 7c 24 75 10 95 01 09 30 81 02 09 31 46 96 14 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 95 03 81 03 09 32 09 47 95 02 81 02 95 02 81 03 09 51 75 08 95 01 81 02 05 01 26 ff 7f 65 11 55 0e 46 7c 24 75 10 95 01 09 30 81 02 09 31 46 96 14 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 95 03 81 03 09 32 09 47 95 02 81 02 95 02 81 03 09 51 75 08 95 01 81 02 05 01 26 ff 7f 65 11 55 0e 46 7c 24 75 10 95 01 09 30 81 02 09 31 46 96 14 81 02 c0 05 0d 09 54 75 08 95 01 15 00 25 08 81 02 09 55 b1 02 c0", 1349 + input_info=(BusType.USB, 0x04E7, 0x0080), 1350 + ) 1351 + 1352 + 1353 + class TestFlatfrog_25b5_0002(BaseTest.TestMultitouch): 1354 + def create_device(self): 1355 + return Digitizer( 1356 + "uhid test flatfrog_25b5_0002", 1357 + rdesc="05 0d 09 04 a1 01 85 05 09 22 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 05 0d 09 22 65 00 55 00 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 05 0d 09 22 65 00 55 00 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 05 0d 09 22 65 00 55 00 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 05 0d 09 22 65 00 55 00 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 05 0d 09 22 65 00 55 00 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 05 0d 09 22 65 00 55 00 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 05 0d 09 22 65 00 55 00 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 05 0d 09 22 65 00 55 00 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 05 0d 09 22 65 00 55 00 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 05 0d 09 22 65 00 55 00 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 05 0d 09 22 65 00 55 00 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 05 0d 09 22 65 00 55 00 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 05 0d 09 22 65 00 55 00 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 05 0d 09 22 65 00 55 00 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 05 0d 09 22 65 00 55 00 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 05 0d 09 22 65 00 55 00 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 05 0d 09 22 65 00 55 00 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 05 0d 09 22 65 00 55 00 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 05 0d 09 22 65 00 55 00 a1 02 05 0d 15 00 25 01 75 01 95 01 09 42 81 02 09 32 81 02 95 06 81 03 75 08 95 01 25 7f 09 51 81 02 05 01 65 11 55 0e 75 10 35 00 26 a6 2b 46 48 1b 09 30 81 02 26 90 18 46 59 0f 09 31 81 02 05 0d 65 11 55 0f 75 08 25 7f 45 7f 09 48 81 02 09 49 81 02 65 00 55 00 75 10 26 00 04 46 00 04 09 30 81 02 c0 65 00 55 00 05 0d 55 0c 66 01 10 75 20 95 01 27 ff ff ff 7f 45 00 09 56 81 02 75 08 95 01 15 00 25 28 09 54 81 02 09 55 85 06 25 28 b1 02 c0 65 00 55 00 45 00 09 0e a1 01 85 03 09 23 a1 02 09 52 15 02 25 02 75 08 95 01 b1 02 09 53 15 00 25 0a 75 08 95 01 b1 02 c0 c0", 1358 + input_info=(BusType.USB, 0x25B5, 0x0002), 1359 + quirks=("NOT_SEEN_MEANS_UP", "NO_AREA"), 1360 + max_contacts=40, 1361 + ) 1362 + 1363 + 1364 + class TestFocaltech_10c4_81b9(BaseTest.TestMultitouch): 1365 + def create_device(self): 1366 + return Digitizer( 1367 + "uhid test focaltech_10c4_81b9", 1368 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 00 04 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 26 58 02 09 31 46 00 00 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 00 04 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 26 58 02 09 31 46 00 00 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 00 04 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 26 58 02 09 31 46 00 00 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 00 04 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 26 58 02 09 31 46 00 00 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 00 04 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 26 58 02 09 31 46 00 00 81 02 c0 05 0d 09 54 95 01 75 08 15 00 25 08 81 02 85 02 09 55 75 08 95 01 b1 02 c0", 1369 + input_info=(BusType.USB, 0x10C4, 0x81B9), 1370 + quirks=("ALWAYS_VALID",), 1371 + max_contacts=5, 1372 + ) 1373 + 1374 + 1375 + class TestHanvon_20b3_0a18(BaseTest.TestMultitouch): 1376 + def create_device(self): 1377 + return Digitizer( 1378 + "uhid test hanvon_20b3_0a18", 1379 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 81 02 05 01 35 00 55 0e 65 33 75 10 95 01 09 30 26 ff 4b 46 70 03 81 02 09 31 26 ff 2b 46 f1 01 81 02 46 00 00 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 81 02 05 01 35 00 55 0e 65 33 75 10 95 01 09 30 26 ff 4b 46 70 03 81 02 09 31 26 ff 2b 46 f1 01 81 02 46 00 00 c0 05 0d 09 54 75 08 95 01 81 02 05 0d 85 02 09 55 25 02 75 08 95 01 b1 02 c0", 1380 + input_info=(BusType.USB, 0x20B3, 0x0A18), 1381 + ) 1382 + 1383 + 1384 + class TestHuitoo_03f7_0003(BaseTest.TestMultitouch): 1385 + def create_device(self): 1386 + return Digitizer( 1387 + "uhid test huitoo_03f7_0003", 1388 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 00 65 00 35 00 46 ff 0f 09 30 26 ff 0f 81 02 09 31 26 ff 0f 81 02 05 0d 09 48 26 ff 0f 81 02 09 49 26 ff 0f 81 02 c0 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 00 65 00 35 00 46 ff 0f 09 30 26 ff 0f 81 02 09 31 26 ff 0f 81 02 05 0d 09 48 26 ff 0f 81 02 09 49 26 ff 0f 81 02 c0 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 00 65 00 35 00 46 ff 0f 09 30 26 ff 0f 81 02 09 31 26 ff 0f 81 02 05 0d 09 48 26 ff 0f 81 02 09 49 26 ff 0f 81 02 c0 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 00 65 00 35 00 46 ff 0f 09 30 26 ff 0f 81 02 09 31 26 ff 0f 81 02 05 0d 09 48 26 ff 0f 81 02 09 49 26 ff 0f 81 02 c0 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 00 65 00 35 00 46 ff 0f 09 30 26 ff 0f 81 02 09 31 26 ff 0f 81 02 05 0d 09 48 26 ff 0f 81 02 09 49 26 ff 0f 81 02 c0 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 00 65 00 35 00 46 ff 0f 09 30 26 ff 0f 81 02 09 31 26 ff 0f 81 02 05 0d 09 48 26 ff 0f 81 02 09 49 26 ff 0f 81 02 c0 05 0d 09 54 95 01 75 08 15 00 25 08 81 02 09 55 b1 02 c0 09 0e a1 01 85 02 09 23 a1 02 09 52 09 53 15 00 25 10 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 85 03 09 01 a1 00 05 09 19 01 29 03 15 00 25 01 95 03 75 01 81 02 95 01 75 05 81 01 05 01 09 30 09 31 15 00 26 ff 0f 35 00 46 ff 0f 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 85 04 15 00 26 ff 00 75 08 95 3f 09 02 81 02 95 3f 09 02 91 02 c0", 1389 + input_info=(BusType.USB, 0x03F7, 0x0003), 1390 + ) 1391 + 1392 + 1393 + class TestIdeacom_1cb6_6650(BaseTest.TestMultitouch): 1394 + def create_device(self): 1395 + return Digitizer( 1396 + "uhid test ideacom_1cb6_6650", 1397 + rdesc="05 0d 09 04 a1 01 85 0a 09 22 a1 00 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 81 03 05 01 26 ff 1f 75 10 95 01 55 0d 65 33 09 31 35 00 46 61 13 81 02 09 30 46 73 22 81 02 05 0d 75 08 95 01 09 30 26 ff 00 81 02 09 51 81 02 85 0c 09 55 25 02 95 01 b1 02 c0 06 00 ff 85 02 09 01 75 08 95 07 b1 02 85 03 09 02 75 08 95 07 b1 02 85 04 09 03 75 08 95 07 b1 02 85 05 09 04 75 08 95 07 b1 02 85 06 09 05 75 08 96 27 00 b1 02 85 07 09 06 75 08 96 27 00 b1 02 85 08 09 07 75 08 95 07 b1 02 85 09 09 08 75 08 95 07 b1 02 85 0b 09 09 75 08 96 07 00 b1 02 85 0d 09 0a 75 08 96 27 00 b1 02 c0 09 0e a1 01 85 0e 09 52 09 53 95 07 b1 02 c0 05 01 09 02 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 75 06 95 01 81 01 05 01 09 31 09 30 15 00 27 ff 1f 00 00 75 10 95 02 81 02 c0 09 01 a1 02 15 00 26 ff 00 95 02 75 08 81 03 c0 c0", 1398 + input_info=(BusType.USB, 0x1CB6, 0x6650), 1399 + ) 1400 + 1401 + 1402 + class TestIdeacom_1cb6_6651(BaseTest.TestMultitouch): 1403 + def create_device(self): 1404 + return Digitizer( 1405 + "uhid test ideacom_1cb6_6651", 1406 + rdesc="05 0d 09 04 a1 01 85 0a 09 22 a1 02 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 81 03 05 01 26 ff 1f 75 10 95 01 55 0d 65 33 09 31 35 00 46 39 13 81 02 09 30 46 24 22 81 02 05 0d 75 08 95 01 09 30 26 ff 00 81 02 09 51 81 02 85 0c 09 55 25 02 95 01 b1 02 c0 06 00 ff 85 02 09 01 75 08 95 07 b1 02 85 03 09 02 75 08 95 07 b1 02 85 04 09 03 75 08 95 07 b1 02 85 05 09 04 75 08 95 07 b1 02 85 06 09 05 75 08 95 1f b1 02 85 07 09 06 75 08 96 1f 00 b1 02 85 08 09 07 75 08 95 07 b1 02 85 09 09 08 75 08 95 07 b1 02 85 0b 09 09 75 08 95 07 b1 02 85 0d 09 0a 75 08 96 1f 00 b1 02 c0 09 0e a1 01 85 0e 09 52 09 53 95 07 b1 02 c0 05 01 09 02 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 75 06 95 01 81 01 05 01 09 31 09 30 15 00 27 ff 1f 00 00 75 10 95 02 81 02 c0 09 01 a1 02 15 00 26 ff 00 95 02 75 08 81 03 c0 c0", 1407 + input_info=(BusType.USB, 0x1CB6, 0x6651), 1408 + ) 1409 + 1410 + 1411 + class TestIkaist_2793_0001(BaseTest.TestMultitouch): 1412 + def create_device(self): 1413 + return Digitizer( 1414 + "uhid test ikaist_2793_0001", 1415 + rdesc="05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 09 01 95 01 75 01 15 00 25 01 81 02 95 07 75 01 81 03 95 01 75 08 81 03 05 01 09 30 09 31 15 00 26 ff 7f 35 00 46 00 00 95 02 75 10 81 02 c0 a1 02 15 00 26 ff 00 09 01 95 39 75 08 81 03 c0 c0 05 0d 09 0e a1 01 85 11 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 09 04 a1 01 85 13 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 51 07 81 02 09 31 46 96 04 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 51 07 81 02 09 31 46 96 04 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 51 07 81 02 09 31 46 96 04 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 51 07 81 02 09 31 46 96 04 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 51 07 81 02 09 31 46 96 04 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 51 07 81 02 09 31 46 96 04 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 51 07 81 02 09 31 46 96 04 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 51 07 81 02 09 31 46 96 04 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 51 07 81 02 09 31 46 96 04 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 33 09 30 35 00 46 51 07 81 02 09 31 46 96 04 81 02 c0 05 0d 09 54 95 01 75 08 15 00 25 3c 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 02 81 03 05 0d 85 12 09 55 95 01 75 08 15 00 25 3c b1 02 06 00 ff 15 00 26 ff 00 85 1e 09 01 75 08 95 80 b1 02 85 1f 09 01 75 08 96 3f 01 b1 02 c0", 1416 + input_info=(BusType.USB, 0x2793, 0x0001), 1417 + ) 1418 + 1419 + 1420 + class TestIrmtouch_23c9_5666(BaseTest.TestMultitouch): 1421 + def create_device(self): 1422 + return Digitizer( 1423 + "uhid test irmtouch_23c9_5666", 1424 + rdesc="05 0d 09 04 a1 01 85 0a 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 15 00 26 ff 7f 75 10 09 30 81 02 09 31 81 02 05 0d 09 48 09 49 95 02 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 15 00 26 ff 7f 75 10 09 30 81 02 09 31 81 02 05 0d 09 48 09 49 95 02 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 15 00 26 ff 7f 75 10 09 30 81 02 09 31 81 02 05 0d 09 48 09 49 95 02 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 15 00 26 ff 7f 75 10 09 30 81 02 09 31 81 02 05 0d 09 48 09 49 95 02 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 15 00 26 ff 7f 75 10 09 30 81 02 09 31 81 02 05 0d 09 48 09 49 95 02 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 15 00 26 ff 7f 75 10 09 30 81 02 09 31 81 02 05 0d 09 48 09 49 95 02 81 02 c0 05 0d 09 54 95 01 75 08 81 02 09 55 25 06 b1 02 c0 09 0e a1 01 85 0c 09 23 a1 02 09 52 15 00 25 06 75 08 95 01 b1 02 c0 c0", 1425 + input_info=(BusType.USB, 0x23C9, 0x5666), 1426 + ) 1427 + 1428 + 1429 + class TestIrtouch_6615_0070(BaseTest.TestMultitouch): 1430 + def create_device(self): 1431 + return Digitizer( 1432 + "uhid test irtouch_6615_0070", 1433 + rdesc="05 01 09 02 a1 01 85 10 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 06 81 03 05 01 09 30 09 31 15 00 26 ff 7f 75 10 95 02 81 02 c0 c0 05 0d 09 04 a1 01 85 30 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 81 02 05 01 09 30 26 ff 7f 55 0f 65 11 35 00 46 51 02 75 10 95 01 81 02 09 31 35 00 46 73 01 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 81 02 05 01 09 30 26 ff 7f 55 0f 65 11 35 00 46 51 02 75 10 95 01 81 02 09 31 35 00 46 73 01 81 02 c0 05 0d 09 54 15 00 26 02 00 75 08 95 01 81 02 85 03 09 55 15 00 26 ff 00 75 08 95 01 b1 02 c0 05 0d 09 0e a1 01 85 02 09 52 09 53 15 00 26 ff 00 75 08 95 02 b1 02 c0 05 0d 09 02 a1 01 85 20 09 20 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 03 05 01 09 30 26 ff 7f 55 0f 65 11 35 00 46 51 02 75 10 95 01 81 02 09 31 35 00 46 73 01 81 02 85 01 06 00 ff 09 01 75 08 95 01 b1 02 c0 c0", 1434 + input_info=(BusType.USB, 0x6615, 0x0070), 1435 + ) 1436 + 1437 + 1438 + class TestIrtouch_6615_0081(BaseTest.TestMultitouch): 1439 + def create_device(self): 1440 + return Digitizer( 1441 + "uhid test irtouch_6615_0081", 1442 + rdesc="05 0d 09 04 a1 01 85 30 09 22 09 00 15 00 26 ff 00 75 08 95 05 81 02 a1 00 05 0d 09 51 15 00 26 ff 00 75 08 95 01 81 02 05 01 09 30 26 ff 7f 55 0e 65 13 35 00 46 b5 04 75 10 95 01 81 02 09 31 35 00 46 8a 03 81 02 09 32 35 00 46 8a 03 81 02 09 00 15 00 26 ff 7f 75 10 95 01 81 02 09 00 15 00 26 ff 7f 75 10 95 01 81 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 00 15 00 26 ff 00 75 08 95 01 81 02 c0 a1 00 05 0d 09 51 15 00 26 ff 00 75 08 95 01 81 02 05 01 09 30 26 ff 7f 55 0e 65 13 35 00 46 b5 04 75 10 95 01 81 02 09 31 35 00 46 8a 03 81 02 09 32 35 00 46 8a 03 81 02 09 00 15 00 26 ff 7f 75 10 95 01 81 02 09 00 15 00 26 ff 7f 75 10 95 01 81 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 00 15 00 26 ff 00 75 08 95 01 81 02 c0 a1 00 05 0d 09 51 15 00 26 ff 00 75 08 95 01 81 02 05 01 09 30 26 ff 7f 55 0e 65 13 35 00 46 b5 04 75 10 95 01 81 02 09 31 35 00 46 8a 03 81 02 09 32 35 00 46 8a 03 81 02 09 00 15 00 26 ff 7f 75 10 95 01 81 02 09 00 15 00 26 ff 7f 75 10 95 01 81 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 00 15 00 26 ff 00 75 08 95 01 81 02 c0 a1 00 05 0d 09 54 15 00 25 1f 75 05 95 01 81 02 09 00 15 00 25 07 75 03 95 01 81 02 09 00 15 00 26 ff 00 75 08 95 01 81 02 c0 09 55 85 03 15 00 26 ff 00 75 08 95 01 b1 02 c0 05 0d 09 0e a1 01 85 02 09 52 09 53 15 00 26 ff 00 75 08 95 02 b1 02 c0 06 00 ff 09 00 a1 01 09 02 a1 00 85 aa 09 06 15 00 26 ff 00 35 00 46 ff 00 75 08 95 3f b1 02 c0 c0 05 01 09 02 a1 01 85 10 09 01 a1 00 05 01 09 00 15 00 26 ff 00 75 08 95 05 81 02 09 30 09 31 09 32 15 00 26 ff 7f 75 10 95 03 81 02 05 09 19 01 29 08 15 00 25 01 95 08 75 01 81 02 09 00 15 00 26 ff 00 75 08 95 02 81 02 c0 c0 06 00 ff 09 00 a1 01 85 40 09 00 15 00 26 ff 00 75 08 95 2e 81 02 c0", 1443 + input_info=(BusType.USB, 0x6615, 0x0081), 1444 + ) 1445 + 1446 + 1447 + class TestLG_043e_9aa1(BaseTest.TestMultitouch): 1448 + def create_device(self): 1449 + return Digitizer( 1450 + "uhid test lg_043e_9aa1", 1451 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 09 31 46 78 0a 26 38 04 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 46 78 0a 26 38 04 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 46 78 0a 26 38 04 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 46 78 0a 26 38 04 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 46 78 0a 26 38 04 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 46 78 0a 26 38 04 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 46 78 0a 26 38 04 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 46 78 0a 26 38 04 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 46 78 0a 26 38 04 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 46 78 0a 26 38 04 09 31 81 02 c0 05 0d 09 54 95 01 75 08 15 00 25 0a 81 02 25 0a 09 55 b1 02 c0 09 0e a1 01 85 03 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 85 04 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 75 10 95 01 15 00 26 7f 07 81 02 09 31 26 37 04 81 02 c0 c0 06 00 ff 09 01 a1 01 85 05 15 00 26 ff 00 75 08 95 19 09 01 b1 02 c0 05 14 09 2b a1 02 85 07 09 2b 15 00 25 0a 75 08 95 40 b1 02 09 4b 15 00 25 0a 75 08 95 02 91 02 c0 05 14 09 2c a1 02 85 08 09 2b 15 00 25 0a 75 08 95 05 81 02 09 4b 15 00 25 0a 75 08 95 47 91 02 c0", 1452 + input_info=(BusType.USB, 0x043E, 0x9AA1), 1453 + ) 1454 + 1455 + 1456 + class TestLG_043e_9aa3(BaseTest.TestMultitouch): 1457 + def create_device(self): 1458 + return Digitizer( 1459 + "uhid test lg_043e_9aa3", 1460 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 09 31 46 78 0a 26 38 04 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 46 78 0a 26 38 04 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 46 78 0a 26 38 04 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 46 78 0a 26 38 04 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 46 78 0a 26 38 04 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 46 78 0a 26 38 04 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 46 78 0a 26 38 04 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 46 78 0a 26 38 04 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 46 78 0a 26 38 04 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 46 78 0a 26 38 04 09 31 81 02 c0 05 0d 09 54 95 01 75 08 15 00 25 0a 81 02 25 0a 09 55 b1 02 c0 09 0e a1 01 85 03 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 85 04 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 75 10 95 01 15 00 26 7f 07 81 02 09 31 26 37 04 81 02 c0 c0 06 00 ff 09 01 a1 01 85 05 15 00 26 ff 00 75 08 95 19 09 01 b1 02 c0 05 14 09 2b a1 02 85 07 09 2b 15 00 25 0a 75 08 95 40 b1 02 09 4b 15 00 25 0a 75 08 95 02 91 02 c0 05 14 09 2c a1 02 85 08 09 2b 15 00 25 0a 75 08 95 05 81 02 09 4b 15 00 25 0a 75 08 95 47 91 02 c0", 1461 + input_info=(BusType.USB, 0x043E, 0x9AA3), 1462 + ) 1463 + 1464 + 1465 + class TestLG_1fd2_0064(BaseTest.TestMultitouch): 1466 + def create_device(self): 1467 + return Digitizer( 1468 + "uhid test lg_1fd2_0064", 1469 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 a1 00 05 01 26 80 07 75 10 55 0e 65 33 09 30 35 00 46 53 07 81 02 26 38 04 46 20 04 09 31 81 02 45 00 c0 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 a1 00 05 01 26 80 07 75 10 55 0e 65 33 09 30 35 00 46 53 07 81 02 26 38 04 46 20 04 09 31 81 02 45 00 c0 c0 05 0d 09 54 95 01 75 08 81 02 85 08 09 55 95 01 25 02 b1 02 c0 09 0e a1 01 85 07 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 85 03 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 75 10 95 02 15 00 26 ff 7f 81 02 c0 c0", 1470 + input_info=(BusType.USB, 0x1FD2, 0x0064), 1471 + ) 1472 + 1473 + 1474 + class TestLumio_202e_0006(BaseTest.TestMultitouch): 1475 + def create_device(self): 1476 + return Digitizer( 1477 + "uhid test lumio_202e_0006", 1478 + rdesc="05 0d 09 04 a1 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 03 81 03 09 32 09 47 95 02 81 02 95 02 81 03 09 51 75 08 95 01 81 02 05 01 26 ff 7f 65 11 55 0e 46 b0 0e 75 10 95 01 09 30 81 02 09 31 46 c2 0b 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 95 03 81 03 09 32 09 47 95 02 81 02 95 02 81 03 09 51 75 08 95 01 81 02 05 01 26 ff 7f 65 11 55 0e 46 b0 0e 75 10 95 01 09 30 81 02 09 31 46 c2 0b 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 95 03 81 03 09 32 09 47 95 02 81 02 95 02 81 03 09 51 75 08 95 01 81 02 05 01 26 ff 7f 65 11 55 0e 46 b0 0e 75 10 95 01 09 30 81 02 09 31 46 c2 0b 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 95 03 81 03 09 32 09 47 95 02 81 02 95 02 81 03 09 51 75 08 95 01 81 02 05 01 26 ff 7f 65 11 55 0e 46 b0 0e 75 10 95 01 09 30 81 02 09 31 46 c2 0b 81 02 c0 05 0d 09 54 75 08 95 01 15 00 25 08 81 02 09 55 b1 02 c0", 1479 + input_info=(BusType.USB, 0x202E, 0x0006), 1480 + quirks=("VALID_IS_CONFIDENCE", "SLOT_IS_CONTACTID_MINUS_ONE"), 1481 + ) 1482 + 1483 + 1484 + class TestLumio_202e_0007(BaseTest.TestMultitouch): 1485 + def create_device(self): 1486 + return Digitizer( 1487 + "uhid test lumio_202e_0007", 1488 + rdesc="05 0d 09 04 a1 01 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 95 03 81 03 09 32 09 47 95 02 81 02 95 0a 81 03 05 01 26 ff 7f 65 11 55 0e 46 ba 0e 75 10 95 01 09 30 81 02 09 31 46 ea 0b 81 02 05 0d 09 51 75 10 95 01 81 02 09 55 15 00 25 08 75 08 95 01 b1 02 c0 c0", 1489 + input_info=(BusType.USB, 0x202E, 0x0007), 1490 + quirks=("VALID_IS_CONFIDENCE", "SLOT_IS_CONTACTID_MINUS_ONE"), 1491 + ) 1492 + 1493 + 1494 + class TestNexio_1870_0100(BaseTest.TestMultitouch): 1495 + def create_device(self): 1496 + return Digitizer( 1497 + "uhid test nexio_1870_0100", 1498 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0e 65 11 09 30 35 00 46 1e 19 81 02 26 ff 3f 09 31 35 00 46 be 0f 81 02 26 ff 3f c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0e 65 11 09 30 35 00 46 1e 19 81 02 26 ff 3f 09 31 35 00 46 be 0f 81 02 26 ff 3f c0 05 0d 09 54 95 01 75 08 25 02 81 02 85 02 09 55 25 02 b1 02 c0 09 0e a1 01 85 03 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 09 01 a1 00 85 04 05 09 95 03 75 01 19 01 29 03 15 00 25 01 81 02 95 01 75 05 81 01 05 01 75 10 95 02 09 30 09 31 15 00 26 ff 7f 81 02 c0 c0 05 0d 09 02 a1 01 85 05 09 20 a1 00 09 42 09 32 15 00 25 01 75 01 95 02 81 02 95 0e 81 03 05 01 26 ff 3f 75 10 95 01 55 0e 65 11 09 30 35 00 46 1e 19 81 02 26 ff 3f 09 31 35 00 46 be 0f 81 02 26 ff 3f c0 c0 06 00 ff 09 01 a1 01 85 06 19 01 29 40 15 00 26 ff 00 75 08 95 40 81 00 19 01 29 40 91 00 c0", 1499 + input_info=(BusType.USB, 0x1870, 0x0100), 1500 + ) 1501 + 1502 + 1503 + class TestNexio_1870_010d(BaseTest.TestMultitouch): 1504 + def create_device(self): 1505 + return Digitizer( 1506 + "uhid test nexio_1870_010d", 1507 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 05 0d 09 54 95 01 75 08 25 02 81 02 85 02 09 55 25 06 b1 02 c0 09 0e a1 01 85 03 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 09 01 a1 00 85 04 05 09 95 03 75 01 19 01 29 03 15 00 25 01 81 02 95 01 75 05 81 01 05 01 75 10 95 02 09 30 09 31 15 00 26 ff 7f 81 02 c0 c0 05 0d 09 02 a1 01 85 05 09 20 a1 00 09 42 09 32 15 00 25 01 75 01 95 02 81 02 95 0e 81 03 05 01 26 ff 3f 75 10 95 01 55 0e 65 11 09 30 35 00 46 1e 19 81 02 26 ff 3f 09 31 35 00 46 be 0f 81 02 26 ff 3f c0 c0 06 00 ff 09 01 a1 01 85 06 19 01 29 40 15 00 26 ff 00 75 08 95 3e 81 00 19 01 29 40 91 00 c0", 1508 + input_info=(BusType.USB, 0x1870, 0x010D), 1509 + ) 1510 + 1511 + 1512 + class TestNexio_1870_0119(BaseTest.TestMultitouch): 1513 + def create_device(self): 1514 + return Digitizer( 1515 + "uhid test nexio_1870_0119", 1516 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 05 0d 09 54 95 01 75 08 25 02 81 02 85 02 09 55 25 06 b1 02 c0 09 0e a1 01 85 03 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 09 01 a1 00 85 04 05 09 95 03 75 01 19 01 29 03 15 00 25 01 81 02 95 01 75 05 81 01 05 01 75 10 95 02 09 30 09 31 15 00 26 ff 7f 81 02 c0 c0 05 0d 09 02 a1 01 85 05 09 20 a1 00 09 42 09 32 15 00 25 01 75 01 95 02 81 02 95 0e 81 03 05 01 26 ff 3f 75 10 95 01 55 0e 65 11 09 30 35 00 46 1e 19 81 02 26 ff 3f 09 31 35 00 46 be 0f 81 02 26 ff 3f c0 c0 06 00 ff 09 01 a1 01 85 06 19 01 29 40 15 00 26 ff 00 75 08 95 3e 81 00 19 01 29 40 91 00 c0", 1517 + input_info=(BusType.USB, 0x1870, 0x0119), 1518 + ) 1519 + 1520 + 1521 + class TestPenmount_14e1_3500(BaseTest.TestMultitouch): 1522 + def create_device(self): 1523 + return Digitizer( 1524 + "uhid test penmount_14e1_3500", 1525 + rdesc="05 0d 09 04 a1 01 09 22 a1 00 09 51 15 00 25 0f 75 04 95 01 81 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 81 01 05 01 75 10 95 01 09 30 26 ff 07 81 02 09 31 26 ff 07 81 02 05 0d 09 55 75 08 95 05 b1 02 c0 c0", 1526 + input_info=(BusType.USB, 0x14E1, 0x3500), 1527 + quirks=("VALID_IS_CONFIDENCE",), 1528 + max_contacts=10, 1529 + ) 1530 + 1531 + 1532 + class TestPixart_093a_8002(BaseTest.TestMultitouch): 1533 + def create_device(self): 1534 + return Digitizer( 1535 + "uhid test pixart_093a_8002", 1536 + rdesc="05 01 09 02 a1 01 85 0d 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 03 05 01 55 0e 65 11 75 10 95 01 35 00 46 5a 14 26 ff 7f 09 30 81 22 46 72 0b 26 ff 7f 09 31 81 22 95 08 75 08 81 03 c0 c0 05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 5a 14 26 ff 7f 81 02 09 31 46 72 0b 26 ff 7f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 5a 14 26 ff 7f 81 02 46 72 0b 26 ff 7f 09 31 81 02 c0 05 0d 09 54 15 00 26 ff 00 95 01 75 08 81 02 09 55 25 02 95 01 85 02 b1 02 c0 05 0d 09 0e a1 01 06 00 ff 09 01 26 ff 00 75 08 95 47 85 03 b1 02 09 01 96 ff 03 85 04 b1 02 09 01 95 0b 85 05 b1 02 09 01 96 ff 03 85 06 b1 02 09 01 95 0f 85 07 b1 02 09 01 96 ff 03 85 08 b1 02 09 01 96 ff 03 85 09 b1 02 09 01 95 3f 85 0a b1 02 09 01 96 ff 03 85 0b b1 02 09 01 96 c3 03 85 0e b1 02 09 01 96 ff 03 85 0f b1 02 09 01 96 83 03 85 10 b1 02 09 01 96 93 00 85 11 b1 02 09 01 96 ff 03 85 12 b1 02 05 0d 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 85 0c b1 02 c0 c0", 1537 + input_info=(BusType.USB, 0x093A, 0x8002), 1538 + quirks=("VALID_IS_INRANGE", "SLOT_IS_CONTACTNUMBER"), 1539 + ) 1540 + 1541 + 1542 + class TestPqlabs_1ef1_0001(BaseTest.TestMultitouch): 1543 + def create_device(self): 1544 + return Digitizer( 1545 + "uhid test pqlabs_1ef1_0001", 1546 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0e 65 11 09 30 35 00 46 1e 19 81 02 26 ff 3f 09 31 35 00 46 be 0f 81 02 26 ff 3f c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0e 65 11 09 30 35 00 46 1e 19 81 02 26 ff 3f 09 31 35 00 46 be 0f 81 02 26 ff 3f c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0e 65 11 09 30 35 00 46 1e 19 81 02 26 ff 3f 09 31 35 00 46 be 0f 81 02 26 ff 3f c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0e 65 11 09 30 35 00 46 1e 19 81 02 26 ff 3f 09 31 35 00 46 be 0f 81 02 26 ff 3f c0 05 0d 09 54 95 01 75 08 25 02 81 02 85 02 09 55 25 02 b1 02 c0 09 0e a1 01 85 03 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 09 01 a1 00 85 04 05 09 95 03 75 01 19 01 29 03 15 00 25 01 81 02 95 01 75 05 81 01 05 01 75 10 95 02 09 30 09 31 15 00 26 ff 3f 81 02 c0 c0 05 8c 09 07 a1 01 85 11 09 02 15 00 26 ff 00 75 08 95 3f 81 02 85 10 09 10 91 02 c0", 1547 + input_info=(BusType.USB, 0x1EF1, 0x0001), 1548 + ) 1549 + 1550 + 1551 + class TestQuanta_0408_3000(BaseTest.TestMultitouch): 1552 + def create_device(self): 1553 + return Digitizer( 1554 + "uhid test quanta_0408_3000", 1555 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 e3 13 26 7f 07 81 02 09 31 46 2f 0b 26 37 04 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 e3 13 26 7f 07 81 02 46 2f 0b 26 37 04 09 31 81 02 c0 05 0d 09 54 15 00 26 ff 00 95 01 75 08 81 02 09 55 25 02 95 01 85 02 b1 02 06 00 ff 09 01 26 ff 00 75 08 95 2f 85 03 b1 02 09 01 96 ff 03 85 04 b1 02 09 01 95 0b 85 05 b1 02 09 01 96 ff 03 85 06 b1 02 c0", 1556 + input_info=(BusType.USB, 0x0408, 0x3000), 1557 + ) 1558 + 1559 + 1560 + class TestQuanta_0408_3001(BaseTest.TestMultitouch): 1561 + def create_device(self): 1562 + return Digitizer( 1563 + "uhid test quanta_0408_3001", 1564 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 09 31 46 78 0a 26 38 04 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 80 07 81 02 46 78 0a 26 38 04 09 31 81 02 c0 05 0d 09 54 15 00 26 ff 00 95 01 75 08 81 02 09 55 25 02 95 01 85 02 b1 02 06 00 ff 09 01 26 ff 00 75 08 95 47 85 03 b1 02 09 01 96 ff 03 85 04 b1 02 09 01 95 0b 85 05 b1 02 09 01 96 ff 03 85 06 b1 02 09 01 95 0f 85 07 b1 02 09 01 96 ff 03 85 08 b1 02 09 01 96 ff 03 85 09 b1 02 09 01 95 0f 85 0a b1 02 09 01 96 ff 03 85 0b b1 02 c0", 1565 + input_info=(BusType.USB, 0x0408, 0x3001), 1566 + quirks=("VALID_IS_CONFIDENCE", "SLOT_IS_CONTACTID"), 1567 + ) 1568 + 1569 + 1570 + class TestQuanta_0408_3008_1(BaseTest.TestMultitouch): 1571 + def create_device(self): 1572 + return Digitizer( 1573 + "uhid test quanta_0408_3008_1", 1574 + rdesc="05 01 09 02 a1 01 85 0d 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 03 05 01 55 0e 65 11 75 10 95 01 35 00 46 4c 11 26 7f 07 09 30 81 22 46 bb 09 26 37 04 09 31 81 22 95 08 75 08 81 03 c0 c0 05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 4c 11 26 7f 07 81 02 09 31 46 bb 09 26 37 04 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 4c 11 26 7f 07 81 02 46 bb 09 26 37 04 09 31 81 02 c0 05 0d 09 54 15 00 26 ff 00 95 01 75 08 81 02 09 55 25 02 95 01 85 02 b1 02 c0 05 0d 09 0e a1 01 06 00 ff 09 01 26 ff 00 75 08 95 47 85 03 b1 02 09 01 96 ff 03 85 04 b1 02 09 01 95 0b 85 05 b1 02 09 01 96 ff 03 85 06 b1 02 09 01 95 0f 85 07 b1 02 09 01 96 ff 03 85 08 b1 02 09 01 96 ff 03 85 09 b1 02 09 01 95 3f 85 0a b1 02 09 01 96 ff 03 85 0b b1 02 09 01 96 c3 03 85 0e b1 02 09 01 96 ff 03 85 0f b1 02 09 01 96 83 03 85 10 b1 02 09 01 96 93 00 85 11 b1 02 09 01 96 ff 03 85 12 b1 02 05 0d 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 85 0c b1 02 c0 c0", 1575 + input_info=(BusType.USB, 0x0408, 0x3008), 1576 + ) 1577 + 1578 + 1579 + class TestQuanta_0408_3008(BaseTest.TestMultitouch): 1580 + def create_device(self): 1581 + return Digitizer( 1582 + "uhid test quanta_0408_3008", 1583 + rdesc="05 01 09 02 a1 01 85 0d 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 03 05 01 55 0e 65 11 75 10 95 01 35 00 46 98 12 26 7f 07 09 30 81 22 46 78 0a 26 37 04 09 31 81 22 c0 c0 05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 7f 07 81 02 09 31 46 78 0a 26 37 04 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 7f 07 81 02 46 78 0a 26 37 04 09 31 81 02 c0 05 0d 09 54 15 00 26 ff 00 95 01 75 08 81 02 09 55 25 02 95 01 85 02 b1 02 c0 05 0d 09 0e a1 01 06 00 ff 09 01 26 ff 00 75 08 95 47 85 03 b1 02 09 01 96 ff 03 85 04 b1 02 09 01 95 0b 85 05 b1 02 09 01 96 ff 03 85 06 b1 02 09 01 95 0f 85 07 b1 02 09 01 96 ff 03 85 08 b1 02 09 01 96 ff 03 85 09 b1 02 09 01 95 3f 85 0a b1 02 09 01 96 ff 03 85 0b b1 02 09 01 96 c3 03 85 0e b1 02 09 01 96 ff 03 85 0f b1 02 09 01 96 83 03 85 10 b1 02 09 01 96 93 00 85 11 b1 02 09 01 96 ff 03 85 12 b1 02 05 0d 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 85 0c b1 02 c0 c0", 1584 + input_info=(BusType.USB, 0x0408, 0x3008), 1585 + ) 1586 + 1587 + 1588 + class TestRafi_05bd_0107(BaseTest.TestMultitouch): 1589 + def create_device(self): 1590 + return Digitizer( 1591 + "uhid test rafi_05bd_0107", 1592 + rdesc="05 0d 09 04 a1 01 85 01 09 22 65 00 55 00 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 25 09 95 01 81 02 05 01 46 9c 01 26 ff 03 35 00 75 10 09 30 81 02 46 e7 00 26 ff 03 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 25 09 95 01 81 02 05 01 46 9c 01 26 ff 03 35 00 75 10 09 30 81 02 46 e7 00 26 ff 03 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 25 09 95 01 81 02 05 01 46 9c 01 26 ff 03 35 00 75 10 09 30 81 02 46 e7 00 26 ff 03 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 25 09 95 01 81 02 05 01 46 9c 01 26 ff 03 35 00 75 10 09 30 81 02 46 e7 00 26 ff 03 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 25 09 95 01 81 02 05 01 46 9c 01 26 ff 03 35 00 75 10 09 30 81 02 46 e7 00 26 ff 03 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 25 09 95 01 81 02 05 01 46 9c 01 26 ff 03 35 00 75 10 09 30 81 02 46 e7 00 26 ff 03 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 25 09 95 01 81 02 05 01 46 9c 01 26 ff 03 35 00 75 10 09 30 81 02 46 e7 00 26 ff 03 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 25 09 95 01 81 02 05 01 46 9c 01 26 ff 03 35 00 75 10 09 30 81 02 46 e7 00 26 ff 03 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 25 09 95 01 81 02 05 01 46 9c 01 26 ff 03 35 00 75 10 09 30 81 02 46 e7 00 26 ff 03 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 25 09 95 01 81 02 05 01 46 9c 01 26 ff 03 35 00 75 10 09 30 81 02 46 e7 00 26 ff 03 09 31 81 02 c0 05 0d 09 54 95 01 75 08 15 00 25 09 81 02 05 0d 85 02 95 01 75 08 09 55 25 0a b1 02 c0 09 0e a1 01 85 03 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 09 01 a1 00 85 05 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 06 81 03 05 01 65 11 55 0f 09 30 26 ff 03 35 00 46 9c 01 75 10 95 01 81 02 09 31 26 ff 03 35 00 46 e7 00 81 02 c0 c0", 1593 + input_info=(BusType.USB, 0x05BD, 0x0107), 1594 + ) 1595 + 1596 + 1597 + class TestRndplus_2512_5003(BaseTest.TestMultitouch): 1598 + def create_device(self): 1599 + return Digitizer( 1600 + "uhid test rndplus_2512_5003", 1601 + rdesc="05 0d 09 04 a1 01 85 02 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 46 00 00 81 02 05 0d 09 48 09 49 75 10 95 02 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 46 00 00 81 02 05 0d 09 48 09 49 75 10 95 02 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 46 00 00 81 02 05 0d 09 48 09 49 75 10 95 02 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 46 00 00 81 02 05 0d 09 48 09 49 75 10 95 02 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 46 00 00 81 02 05 0d 09 48 09 49 75 10 95 02 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 46 00 00 81 02 05 0d 09 48 09 49 75 10 95 02 81 02 c0 05 0d 09 54 95 01 75 08 15 00 25 08 81 02 85 08 09 55 b1 02 c0 09 0e a1 01 85 07 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 85 03 09 01 a1 00 05 09 19 01 29 03 15 00 25 01 95 03 75 01 81 02 95 01 75 05 81 01 05 01 09 30 09 31 16 00 00 26 ff 3f 36 00 00 46 ff 3f 66 00 00 75 10 95 02 81 62 c0 c0", 1602 + input_info=(BusType.USB, 0x2512, 0x5003), 1603 + ) 1604 + 1605 + 1606 + class TestRndplus_2512_5004(BaseTest.TestMultitouch): 1607 + def create_device(self): 1608 + return Digitizer( 1609 + "uhid test rndplus_2512_5004", 1610 + rdesc="05 0d 09 04 a1 01 85 04 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 46 00 00 81 02 05 0d 09 48 09 49 75 10 95 02 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 46 00 00 81 02 05 0d 09 48 09 49 75 10 95 02 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 46 00 00 81 02 05 0d 09 48 09 49 75 10 95 02 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 46 00 00 81 02 05 0d 09 48 09 49 75 10 95 02 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 46 00 00 81 02 05 0d 09 48 09 49 75 10 95 02 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 00 65 00 09 30 35 00 46 00 00 81 02 09 31 46 00 00 81 02 05 0d 09 48 09 49 75 10 95 02 81 02 c0 05 0d 09 54 95 01 75 08 15 00 25 08 81 02 85 05 09 55 b1 02 c0 09 0e a1 01 85 06 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 85 03 09 01 a1 00 05 09 19 01 29 03 15 00 25 01 95 03 75 01 81 02 95 01 75 05 81 01 05 01 09 30 09 31 16 00 00 26 ff 3f 36 00 00 46 ff 3f 66 00 00 75 10 95 02 81 62 c0 c0 06 00 ff 09 01 a1 01 85 01 09 01 15 00 26 ff 00 75 08 95 3f 82 00 01 85 02 09 01 15 00 26 ff 00 75 08 95 3f 92 00 01 c0", 1611 + input_info=(BusType.USB, 0x2512, 0x5004), 1612 + ) 1613 + 1614 + 1615 + class TestSitronix_1403_5001(BaseTest.TestMultitouch): 1616 + def create_device(self): 1617 + return Digitizer( 1618 + "uhid test sitronix_1403_5001", 1619 + rdesc="05 0d 09 04 a1 01 85 01 09 54 95 01 75 08 81 02 09 22 a1 02 09 51 75 06 95 01 81 02 09 42 09 32 15 00 25 01 75 01 95 02 81 02 05 01 26 90 04 75 0c 95 01 55 0f 65 11 a4 09 30 46 e1 00 81 02 26 50 03 09 31 45 7d 81 02 05 0d 75 08 95 02 09 48 09 49 81 02 c0 a1 02 09 51 75 06 95 01 81 02 09 42 09 32 15 00 25 01 75 01 95 02 81 02 b4 a4 09 30 46 e1 00 81 02 26 50 03 09 31 45 7d 81 02 05 0d 75 08 95 02 09 48 09 49 81 02 c0 a1 02 09 51 75 06 95 01 81 02 09 42 09 32 15 00 25 01 75 01 95 02 81 02 b4 a4 09 30 46 e1 00 81 02 26 50 03 09 31 45 7d 81 02 05 0d 75 08 95 02 09 48 09 49 81 02 c0 a1 02 09 51 75 06 95 01 81 02 09 42 09 32 15 00 25 01 75 01 95 02 81 02 b4 a4 09 30 46 e1 00 81 02 26 50 03 09 31 45 7d 81 02 05 0d 75 08 95 02 09 48 09 49 81 02 c0 a1 02 09 51 75 06 95 01 81 02 09 42 09 32 15 00 25 01 75 01 95 02 81 02 b4 a4 09 30 46 e1 00 81 02 26 50 03 09 31 45 7d 81 02 05 0d 75 08 95 02 09 48 09 49 81 02 c0 a1 02 09 51 75 06 95 01 81 02 09 42 09 32 15 00 25 01 75 01 95 02 81 02 b4 a4 09 30 46 e1 00 81 02 26 50 03 09 31 45 7d 81 02 05 0d 75 08 95 02 09 48 09 49 81 02 c0 a1 02 09 51 75 06 95 01 81 02 09 42 09 32 15 00 25 01 75 01 95 02 81 02 b4 a4 09 30 46 e1 00 81 02 26 50 03 09 31 45 7d 81 02 05 0d 75 08 95 02 09 48 09 49 81 02 c0 a1 02 09 51 75 06 95 01 81 02 09 42 09 32 15 00 25 01 75 01 95 02 81 02 b4 a4 09 30 46 e1 00 81 02 26 50 03 09 31 45 7d 81 02 05 0d 75 08 95 02 09 48 09 49 81 02 c0 a1 02 09 51 75 06 95 01 81 02 09 42 09 32 15 00 25 01 75 01 95 02 81 02 b4 a4 09 30 46 e1 00 81 02 26 50 03 09 31 45 7d 81 02 05 0d 75 08 95 02 09 48 09 49 81 02 c0 a1 02 09 51 75 06 95 01 81 02 09 42 09 32 15 00 25 01 75 01 95 02 81 02 b4 09 30 46 e1 00 81 02 26 50 03 09 31 45 7d 81 02 05 0d 75 08 95 04 09 48 09 49 81 02 c0 85 02 09 55 26 ff 00 75 08 95 01 b1 02 09 04 15 00 25 ff 75 08 95 07 91 02 c0 09 0e a1 01 85 03 09 23 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0", 1620 + input_info=(BusType.USB, 0x1403, 0x5001), 1621 + max_contacts=10, 1622 + ) 1623 + 1624 + 1625 + class TestSmart_0b8c_0092(BaseTest.TestMultitouch): 1626 + def create_device(self): 1627 + return SmartTechDigitizer( 1628 + "uhid test smart_0b8c_0092", input_info=(BusType.USB, 0x0B8C, 0x0092) 1629 + ) 1630 + 1631 + 1632 + class TestStantum_1f87_0002(BaseTest.TestMultitouch): 1633 + def create_device(self): 1634 + return Digitizer( 1635 + "uhid test stantum_1f87_0002", 1636 + rdesc="05 0d 09 04 a1 01 85 03 05 0d 09 54 95 01 75 08 81 02 06 00 ff 75 02 09 01 81 01 75 0e 09 02 81 02 05 0d 09 22 a1 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 30 81 02 05 0d 25 1f 75 05 09 48 81 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 31 81 02 05 0d 25 1f 75 05 09 49 81 02 75 08 09 51 95 01 81 02 09 30 75 05 81 02 09 42 15 00 25 01 75 01 95 01 81 02 09 47 81 02 09 32 81 02 c0 a1 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 30 81 02 05 0d 25 1f 75 05 09 48 81 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 31 81 02 05 0d 25 1f 75 05 09 49 81 02 75 08 09 51 95 01 81 02 09 30 75 05 81 02 09 42 15 00 25 01 75 01 95 01 81 02 09 47 81 02 09 32 81 02 c0 a1 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 30 81 02 05 0d 25 1f 75 05 09 48 81 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 31 81 02 05 0d 25 1f 75 05 09 49 81 02 75 08 09 51 95 01 81 02 09 30 75 05 81 02 09 42 15 00 25 01 75 01 95 01 81 02 09 47 81 02 09 32 81 02 c0 a1 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 30 81 02 05 0d 25 1f 75 05 09 48 81 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 31 81 02 05 0d 25 1f 75 05 09 49 81 02 75 08 09 51 95 01 81 02 09 30 75 05 81 02 09 42 15 00 25 01 75 01 95 01 81 02 09 47 81 02 09 32 81 02 c0 a1 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 30 81 02 05 0d 25 1f 75 05 09 48 81 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 31 81 02 05 0d 25 1f 75 05 09 49 81 02 75 08 09 51 95 01 81 02 09 30 75 05 81 02 09 42 15 00 25 01 75 01 95 01 81 02 09 47 81 02 09 32 81 02 c0 a1 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 30 81 02 05 0d 25 1f 75 05 09 48 81 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 31 81 02 05 0d 25 1f 75 05 09 49 81 02 75 08 09 51 95 01 81 02 09 30 75 05 81 02 09 42 15 00 25 01 75 01 95 01 81 02 09 47 81 02 09 32 81 02 c0 a1 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 30 81 02 05 0d 25 1f 75 05 09 48 81 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 31 81 02 05 0d 25 1f 75 05 09 49 81 02 75 08 09 51 95 01 81 02 09 30 75 05 81 02 09 42 15 00 25 01 75 01 95 01 81 02 09 47 81 02 09 32 81 02 c0 a1 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 30 81 02 05 0d 25 1f 75 05 09 48 81 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 31 81 02 05 0d 25 1f 75 05 09 49 81 02 75 08 09 51 95 01 81 02 09 30 75 05 81 02 09 42 15 00 25 01 75 01 95 01 81 02 09 47 81 02 09 32 81 02 c0 a1 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 30 81 02 05 0d 25 1f 75 05 09 48 81 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 31 81 02 05 0d 25 1f 75 05 09 49 81 02 75 08 09 51 95 01 81 02 09 30 75 05 81 02 09 42 15 00 25 01 75 01 95 01 81 02 09 47 81 02 09 32 81 02 c0 a1 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 30 81 02 05 0d 25 1f 75 05 09 48 81 02 05 01 16 00 00 26 ff 07 75 0b 55 00 65 00 09 31 81 02 05 0d 25 1f 75 05 09 49 81 02 75 08 09 51 95 01 81 02 09 30 75 05 81 02 09 42 15 00 25 01 75 01 95 01 81 02 09 47 81 02 09 32 81 02 c0 85 08 05 0d 09 55 95 01 75 08 25 0a b1 02 c0", 1637 + input_info=(BusType.USB, 0x1F87, 0x0002), 1638 + ) 1639 + 1640 + 1641 + class TestTopseed_1784_0016(BaseTest.TestMultitouch): 1642 + def create_device(self): 1643 + return Digitizer( 1644 + "uhid test topseed_1784_0016", 1645 + rdesc="05 0d 09 04 a1 01 85 04 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 04 75 10 55 00 65 00 09 30 35 00 46 ff 04 81 02 09 31 46 ff 04 81 02 c0 05 0d 09 54 95 01 75 08 15 00 25 0a 81 02 09 55 b1 02 c0 05 0c 09 01 a1 01 85 03 a1 02 09 b5 15 00 25 01 75 01 95 01 81 02 09 b6 81 02 09 b7 81 02 09 cd 81 02 09 e2 81 02 09 e9 81 02 09 ea 81 02 05 01 09 82 81 02 c0 c0", 1646 + input_info=(BusType.USB, 0x1784, 0x0016), 1647 + max_contacts=2, 1648 + ) 1649 + 1650 + 1651 + class TestTpv_25aa_8883(BaseTest.TestMultitouch): 1652 + def create_device(self): 1653 + return Digitizer( 1654 + "uhid test tpv_25aa_8883", 1655 + rdesc="05 01 09 02 a1 01 85 0d 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 05 0d 09 32 95 01 75 01 81 02 95 01 75 05 81 03 05 01 55 0e 65 11 75 10 95 01 35 00 46 98 12 26 7f 07 09 30 81 22 46 78 0a 26 37 04 09 31 81 22 35 00 45 00 15 81 25 7f 75 08 95 01 09 38 81 06 09 00 75 08 95 07 81 03 c0 c0 05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 7f 07 81 02 09 31 46 78 0a 26 37 04 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 75 10 55 0e 65 11 09 30 35 00 46 98 12 26 7f 07 81 02 46 78 0a 26 37 04 09 31 81 02 c0 05 0d 09 54 15 00 26 ff 00 95 01 75 08 81 02 09 55 25 02 95 01 85 02 b1 02 c0 05 0d 09 0e a1 01 06 00 ff 09 01 26 ff 00 75 08 95 47 85 03 b1 02 09 01 96 ff 03 85 04 b1 02 09 01 95 0b 85 05 b1 02 09 01 96 ff 03 85 06 b1 02 09 01 95 0f 85 07 b1 02 09 01 96 ff 03 85 08 b1 02 09 01 96 ff 03 85 09 b1 02 09 01 95 3f 85 0a b1 02 09 01 96 ff 03 85 0b b1 02 09 01 96 c3 03 85 0e b1 02 09 01 96 ff 03 85 0f b1 02 09 01 96 83 03 85 10 b1 02 09 01 96 93 00 85 11 b1 02 09 01 96 ff 03 85 12 b1 02 05 0d 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 85 0c b1 02 c0 c0", 1656 + input_info=(BusType.USB, 0x25AA, 0x8883), 1657 + ) 1658 + 1659 + 1660 + class TestTrs_star_238f_0001(BaseTest.TestMultitouch): 1661 + def create_device(self): 1662 + return Digitizer( 1663 + "uhid test trs-star_238f_0001", 1664 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 95 01 81 03 09 37 95 01 81 03 95 01 81 03 15 00 25 0f 75 04 09 51 95 01 81 02 09 54 95 01 81 02 09 55 95 01 81 02 05 01 26 ff 03 15 00 75 10 65 00 09 30 95 01 81 02 09 31 81 02 c0 05 0d 09 0e 85 02 09 23 a1 02 15 00 25 0a 09 52 75 08 95 01 b1 02 09 53 95 01 b1 02 09 55 95 01 b1 02 c0 c0", 1665 + input_info=(BusType.USB, 0x238F, 0x0001), 1666 + ) 1667 + 1668 + 1669 + class TestUnitec_227d_0103(BaseTest.TestMultitouch): 1670 + def create_device(self): 1671 + return Digitizer( 1672 + "uhid test unitec_227d_0103", 1673 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 81 02 05 01 35 00 55 0e 65 33 75 10 95 01 09 30 16 00 00 26 ff 4f 36 00 00 46 6c 03 81 02 09 31 16 00 00 26 ff 3b 36 00 00 46 ed 01 81 02 26 00 00 46 00 00 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 81 02 05 01 35 00 55 0e 65 33 75 10 95 01 09 30 16 00 00 26 ff 4f 36 00 00 46 6c 03 81 02 09 31 16 00 00 26 ff 3b 36 00 00 46 ed 01 81 02 26 00 00 46 00 00 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 81 02 05 01 35 00 55 0e 65 33 75 10 95 01 09 30 16 00 00 26 ff 4f 36 00 00 46 6c 03 81 02 09 31 16 00 00 26 ff 3b 36 00 00 46 ed 01 81 02 26 00 00 46 00 00 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 81 02 05 01 35 00 55 0e 65 33 75 10 95 01 09 30 16 00 00 26 ff 4f 36 00 00 46 6c 03 81 02 09 31 16 00 00 26 ff 3b 36 00 00 46 ed 01 81 02 26 00 00 46 00 00 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 81 02 05 01 35 00 55 0e 65 33 75 10 95 01 09 30 16 00 00 26 ff 4f 36 00 00 46 6c 03 81 02 09 31 16 00 00 26 ff 3b 36 00 00 46 ed 01 81 02 26 00 00 46 00 00 c0 05 0d 09 54 75 08 95 01 81 02 05 0d 85 03 09 55 25 05 75 08 95 01 b1 02 c0 05 0d 09 0e a1 01 85 04 09 53 15 00 25 05 75 08 95 01 b1 02 c0", 1674 + input_info=(BusType.USB, 0x227D, 0x0103), 1675 + ) 1676 + 1677 + 1678 + class TestZytronic_14c8_0005(BaseTest.TestMultitouch): 1679 + def create_device(self): 1680 + return Digitizer( 1681 + "uhid test zytronic_14c8_0005", 1682 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 95 01 81 02 95 06 81 01 05 01 26 00 10 75 10 95 01 65 00 09 30 81 02 09 31 46 00 10 81 02 05 0d 09 51 26 ff 00 75 08 95 01 81 02 c0 85 02 09 55 15 00 25 08 75 08 95 01 b1 02 c0 05 0d 09 0e a1 01 85 03 a1 02 09 23 09 52 09 53 15 00 25 08 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 09 01 a1 00 85 04 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 15 00 26 00 10 35 00 46 00 10 65 00 75 10 95 02 81 62 c0 c0 06 00 ff 09 01 a1 01 85 05 09 00 15 00 26 ff 00 75 08 95 3f b1 02 c0 06 00 ff 09 01 a1 01 85 06 09 00 15 00 26 ff 00 75 08 95 3f 81 02 c0", 1683 + input_info=(BusType.USB, 0x14C8, 0x0005), 1684 + ) 1685 + 1686 + 1687 + class TestZytronic_14c8_0006(BaseTest.TestMultitouch): 1688 + def create_device(self): 1689 + return Digitizer( 1690 + "uhid test zytronic_14c8_0006", 1691 + rdesc="05 0d 09 04 a1 01 85 01 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 00 10 75 10 09 30 81 02 09 31 81 02 05 0d c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 00 10 75 10 09 30 81 02 09 31 81 02 05 0d c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 00 10 75 10 09 30 81 02 09 31 81 02 05 0d c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 00 10 75 10 09 30 81 02 09 31 81 02 05 0d c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 00 10 75 10 09 30 81 02 09 31 81 02 05 0d c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 00 10 75 10 09 30 81 02 09 31 81 02 05 0d c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 00 10 75 10 09 30 81 02 09 31 81 02 05 0d c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 00 10 75 10 09 30 81 02 09 31 81 02 05 0d c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 00 10 75 10 09 30 81 02 09 31 81 02 05 0d c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 00 10 75 10 09 30 81 02 09 31 81 02 05 0d c0 05 0d 09 54 95 01 75 08 15 00 25 3c 81 02 05 0d 85 02 09 55 95 01 75 08 15 00 25 3c b1 02 c0 09 0e a1 01 85 03 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 09 01 a1 00 85 04 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 15 00 26 00 10 35 00 46 00 10 65 00 75 10 95 02 81 62 c0 c0 06 00 ff 09 01 a1 01 85 05 09 00 15 00 26 ff 00 75 08 95 3f b1 02 c0 06 00 ff 09 01 a1 01 85 06 09 00 15 00 26 ff 00 75 08 95 3f 81 02 c0", 1692 + input_info=(BusType.USB, 0x14C8, 0x0006), 1693 + ) 1694 + 1695 + 1696 + ################################################################################ 1697 + # 1698 + # Windows 8 compatible devices 1699 + # 1700 + ################################################################################ 1701 + 1702 + 1703 + class TestMinWin8TSParallelTriple(BaseTest.TestWin8Multitouch): 1704 + def create_device(self): 1705 + return MinWin8TSParallel(3) 1706 + 1707 + 1708 + class TestMinWin8TSParallel(BaseTest.TestWin8Multitouch): 1709 + def create_device(self): 1710 + return MinWin8TSParallel(10) 1711 + 1712 + 1713 + class TestMinWin8TSHybrid(BaseTest.TestWin8Multitouch): 1714 + def create_device(self): 1715 + return MinWin8TSHybrid() 1716 + 1717 + 1718 + class TestWin8TSConfidence(BaseTest.TestWin8Multitouch): 1719 + def create_device(self): 1720 + return Win8TSConfidence(5) 1721 + 1722 + @pytest.mark.skip_if_uhdev( 1723 + lambda uhdev: "Confidence" not in uhdev.fields, 1724 + "Device not compatible, missing Confidence usage", 1725 + ) 1726 + def test_mt_confidence_bad_release(self): 1727 + """Check for the validity of the confidence bit. 1728 + When a contact is marked as not confident, it should be detected 1729 + as a palm from the kernel POV and released. 1730 + 1731 + Note: if the kernel exports ABS_MT_TOOL_TYPE, it shouldn't release 1732 + the touch but instead convert it to ABS_MT_TOOL_PALM.""" 1733 + uhdev = self.uhdev 1734 + evdev = uhdev.get_evdev() 1735 + 1736 + t0 = Touch(1, 150, 200) 1737 + r = uhdev.event([t0]) 1738 + events = uhdev.next_sync_events() 1739 + self.debug_reports(r, uhdev, events) 1740 + 1741 + t0.confidence = False 1742 + t0.tipswitch = False 1743 + r = uhdev.event([t0]) 1744 + events = uhdev.next_sync_events() 1745 + self.debug_reports(r, uhdev, events) 1746 + 1747 + if evdev.absinfo[libevdev.EV_ABS.ABS_MT_TOOL_TYPE] is not None: 1748 + # the kernel exports MT_TOOL_PALM 1749 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_TOOL_TYPE, 2) in events 1750 + 1751 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 0) in events 1752 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 1753 + 1754 + 1755 + class TestElanXPS9360(BaseTest.TestWin8Multitouch): 1756 + def create_device(self): 1757 + return Digitizer( 1758 + "uhid test ElanXPS9360", 1759 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 a4 26 20 0d 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 50 07 46 a6 00 09 31 81 02 b4 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 a4 26 20 0d 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 50 07 46 a6 00 09 31 81 02 b4 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 a4 26 20 0d 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 50 07 46 a6 00 09 31 81 02 b4 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 a4 26 20 0d 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 50 07 46 a6 00 09 31 81 02 b4 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 a4 26 20 0d 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 50 07 46 a6 00 09 31 81 02 b4 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 a4 26 20 0d 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 50 07 46 a6 00 09 31 81 02 b4 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 a4 26 20 0d 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 50 07 46 a6 00 09 31 81 02 b4 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 a4 26 20 0d 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 50 07 46 a6 00 09 31 81 02 b4 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 a4 26 20 0d 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 50 07 46 a6 00 09 31 81 02 b4 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 a4 26 20 0d 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 50 07 46 a6 00 09 31 81 02 b4 c0 05 0d 09 56 55 00 65 00 27 ff ff ff 7f 95 01 75 20 81 02 09 54 25 7f 95 01 75 08 81 02 85 0a 09 55 25 0a b1 02 85 44 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 06 ff 01 09 01 a1 01 85 02 15 00 26 ff 00 75 08 95 40 09 00 81 02 c0 06 00 ff 09 01 a1 01 85 03 75 08 95 1f 09 01 91 02 c0 06 01 ff 09 01 a1 01 85 04 15 00 26 ff 00 75 08 95 13 09 00 81 02 c0", 1760 + ) 1761 + 1762 + 1763 + class TestTouchpadXPS9360(BaseTest.TestPTP): 1764 + def create_device(self): 1765 + return PTP( 1766 + "uhid test TouchpadXPS9360", 1767 + max_contacts=5, 1768 + rdesc="05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 01 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0 05 0d 09 05 a1 01 85 03 05 0d 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 75 01 95 03 81 03 05 01 15 00 26 c0 04 75 10 55 0e 65 11 09 30 35 00 46 f5 03 95 01 81 02 46 36 02 26 a8 02 09 31 81 02 c0 05 0d 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 75 01 95 03 81 03 05 01 15 00 26 c0 04 75 10 55 0e 65 11 09 30 35 00 46 f5 03 95 01 81 02 46 36 02 26 a8 02 09 31 81 02 c0 05 0d 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 75 01 95 03 81 03 05 01 15 00 26 c0 04 75 10 55 0e 65 11 09 30 35 00 46 f5 03 95 01 81 02 46 36 02 26 a8 02 09 31 81 02 c0 05 0d 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 75 01 95 03 81 03 05 01 15 00 26 c0 04 75 10 55 0e 65 11 09 30 35 00 46 f5 03 95 01 81 02 46 36 02 26 a8 02 09 31 81 02 c0 05 0d 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 75 01 95 03 81 03 05 01 15 00 26 c0 04 75 10 55 0e 65 11 09 30 35 00 46 f5 03 95 01 81 02 46 36 02 26 a8 02 09 31 81 02 c0 05 0d 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 09 54 25 7f 95 01 75 08 81 02 05 09 09 01 25 01 75 01 95 01 81 02 95 07 81 03 05 0d 85 08 09 55 09 59 75 04 95 02 25 0f b1 02 85 0d 09 60 75 01 95 01 15 00 25 01 b1 02 95 07 b1 03 85 07 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 0e a1 01 85 04 09 22 a1 02 09 52 15 00 25 0a 75 08 95 01 b1 02 c0 09 22 a1 00 85 06 09 57 09 58 75 01 95 02 25 01 b1 02 95 06 b1 03 c0 c0 06 00 ff 09 01 a1 01 85 09 09 02 15 00 26 ff 00 75 08 95 14 91 02 85 0a 09 03 15 00 26 ff 00 75 08 95 14 91 02 85 0b 09 04 15 00 26 ff 00 75 08 95 3d 81 02 85 0c 09 05 15 00 26 ff 00 75 08 95 3d 81 02 85 0f 09 06 15 00 26 ff 00 75 08 95 03 b1 02 85 0e 09 07 15 00 26 ff 00 75 08 95 01 b1 02 c0", 1769 + ) 1770 + 1771 + 1772 + class TestSurfaceBook2(BaseTest.TestPTP): 1773 + def create_device(self): 1774 + return PTP( 1775 + "uhid test SurfaceBook2", 1776 + max_contacts=5, 1777 + rdesc="05 01 09 06 A1 01 85 01 14 25 01 75 01 95 08 05 07 19 E0 29 E7 81 02 75 08 95 0A 18 29 91 26 FF 00 80 05 0C 0A C0 02 A1 02 1A C1 02 2A C6 02 95 06 B1 03 C0 05 08 19 01 29 03 75 01 95 03 25 01 91 02 95 05 91 01 C0 05 01 09 02 A1 01 85 02 05 09 19 01 29 05 81 02 95 01 75 03 81 03 15 81 25 7F 75 08 95 02 05 01 09 30 09 31 81 06 A1 02 09 48 14 25 01 35 01 45 10 75 02 95 01 A4 B1 02 09 38 15 81 25 7F 34 44 75 08 81 06 C0 A1 02 09 48 B4 B1 02 34 44 75 04 B1 03 05 0C 0A 38 02 15 81 25 7F 75 08 81 06 C0 C0 05 0C 09 01 A1 01 85 03 75 10 14 26 FF 03 18 2A FF 03 80 C0 06 05 FF 09 01 A1 01 85 0D 25 FF 95 02 75 08 09 20 81 02 09 22 91 02 15 81 25 7F 95 20 75 08 09 21 81 02 09 23 91 02 C0 09 02 A1 01 85 0C 14 25 FF 95 01 08 91 02 C0 05 0D 09 05 A1 01 85 04 09 22 A1 02 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 03 09 51 81 02 75 01 95 03 81 03 05 01 26 E4 07 75 10 55 0E 65 11 09 30 46 F2 03 95 01 81 02 46 94 02 26 29 05 09 31 81 02 44 54 64 C0 05 0D 09 22 A1 02 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 03 09 51 81 02 75 01 95 03 81 03 05 01 26 E4 07 75 10 55 0E 65 11 09 30 46 F2 03 95 01 81 02 46 94 02 26 29 05 09 31 81 02 44 54 64 C0 05 0D 09 22 A1 02 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 03 09 51 81 02 75 01 95 03 81 03 05 01 26 E4 07 75 10 55 0E 65 11 09 30 46 F2 03 95 01 81 02 46 94 02 26 29 05 09 31 81 02 C0 05 0D 09 22 A1 02 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 03 09 51 81 02 75 01 95 03 81 03 05 01 26 E4 07 75 10 55 0E 65 11 09 30 46 F2 03 95 01 81 02 46 94 02 26 29 05 09 31 81 02 44 54 64 C0 05 0D 09 22 A1 02 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 03 09 51 81 02 75 01 95 03 81 03 05 01 26 E4 07 75 10 55 0E 65 11 09 30 46 F2 03 95 01 81 02 46 94 02 26 29 05 09 31 81 02 C0 05 0D 55 0C 66 01 10 47 FF FF 00 00 27 FF FF 00 00 09 56 81 02 09 54 25 7F 75 08 81 02 05 09 09 01 25 01 75 01 81 02 95 07 81 03 05 0D 85 04 09 55 09 59 75 04 95 02 25 0F B1 02 06 00 FF 09 C6 85 05 14 25 08 75 08 95 01 B1 02 09 C7 26 FF 00 75 08 95 20 B1 02 C0 05 0D 09 0E A1 01 85 07 09 22 A1 02 09 52 14 25 0A 75 08 95 01 B1 02 C0 09 22 A0 85 08 09 57 09 58 75 01 95 02 25 01 B1 02 95 06 B1 03 C0 C0 06 07 FF 09 01 A1 01 85 0A 09 02 26 FF 00 75 08 95 14 91 02 85 09 09 03 91 02 85 0A 09 04 95 26 81 02 85 09 09 05 81 02 85 09 09 06 95 01 B1 02 85 0B 09 07 B1 02 C0 06 05 FF 09 04 A1 01 85 0E 09 31 91 02 09 31 81 03 09 30 91 02 09 30 81 02 95 39 09 32 92 02 01 09 32 82 02 01 C0 06 05 FF 09 50 A1 01 85 20 14 25 FF 75 08 95 3C 09 60 82 02 01 09 61 92 02 01 09 62 B2 02 01 85 21 09 63 82 02 01 09 64 92 02 01 09 65 B2 02 01 85 22 25 FF 75 20 95 04 19 66 29 69 81 02 19 6A 29 6D 91 02 19 6E 29 71 B1 02 85 23 19 72 29 75 81 02 19 76 29 79 91 02 19 7A 29 7D B1 02 85 24 19 7E 29 81 81 02 19 82 29 85 91 02 19 86 29 89 B1 02 85 25 19 8A 29 8D 81 02 19 8E 29 91 91 02 19 92 29 95 B1 02 85 26 19 96 29 99 81 02 19 9A 29 9D 91 02 19 9E 29 A1 B1 02 85 27 19 A2 29 A5 81 02 19 A6 29 A9 91 02 19 AA 29 AD B1 02 85 28 19 AE 29 B1 81 02 19 B2 29 B5 91 02 19 B6 29 B9 B1 02 85 29 19 BA 29 BD 81 02 19 BE 29 C1 91 02 19 C2 29 C5 B1 02 C0 06 00 FF 0A 00 F9 A1 01 85 32 75 10 95 02 14 27 FF FF 00 00 0A 01 F9 B1 02 75 20 95 01 25 FF 0A 02 F9 B1 02 75 08 95 08 26 FF 00 0A 03 F9 B2 02 01 95 10 0A 04 F9 B2 02 01 0A 05 F9 B2 02 01 95 01 75 10 27 FF FF 00 00 0A 06 F9 81 02 C0", 1778 + ) 1779 + 1780 + 1781 + class Test3m_0596_051c(BaseTest.TestWin8Multitouch): 1782 + def create_device(self): 1783 + return Digitizer( 1784 + "uhid test 3m_0596_051c", 1785 + rdesc="05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 09 01 95 01 75 01 15 00 25 01 81 02 95 07 75 01 81 03 95 01 75 08 81 03 05 01 09 30 09 31 15 00 26 ff 7f 35 00 46 ff 7f 95 02 75 10 81 02 c0 a1 02 15 00 26 ff 00 09 01 95 39 75 08 81 03 c0 c0 05 0d 09 0e a1 01 85 11 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 09 04 a1 01 85 13 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 81 03 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 d1 12 81 02 09 31 46 b2 0b 81 02 06 00 ff 75 10 95 02 09 01 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 81 03 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 d1 12 81 02 09 31 46 b2 0b 81 02 06 00 ff 75 10 95 02 09 01 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 81 03 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 d1 12 81 02 09 31 46 b2 0b 81 02 06 00 ff 75 10 95 02 09 01 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 81 03 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 d1 12 81 02 09 31 46 b2 0b 81 02 06 00 ff 75 10 95 02 09 01 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 81 03 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 d1 12 81 02 09 31 46 b2 0b 81 02 06 00 ff 75 10 95 02 09 01 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 81 03 09 47 81 02 95 05 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 d1 12 81 02 09 31 46 b2 0b 81 02 06 00 ff 75 10 95 02 09 01 81 02 c0 05 0d 09 54 95 01 75 08 15 00 25 14 81 02 05 0d 55 0c 66 01 10 35 00 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 05 0d 09 55 85 12 15 00 25 14 75 08 95 01 b1 02 85 44 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 06 00 ff 15 00 26 ff 00 85 03 09 01 75 08 95 07 b1 02 85 04 09 01 75 08 95 17 b1 02 85 05 09 01 75 08 95 47 b1 02 85 06 09 01 75 08 95 07 b1 02 85 73 09 01 75 08 95 07 b1 02 85 08 09 01 75 08 95 07 b1 02 85 09 09 01 75 08 95 3f b1 02 85 0f 09 01 75 08 96 07 02 b1 02 c0", 1786 + ) 1787 + 1788 + 1789 + class Testadvanced_silicon_04e8_2084(BaseTest.TestWin8Multitouch): 1790 + def create_device(self): 1791 + return Digitizer( 1792 + "uhid test advanced_silicon_04e8_2084", 1793 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 c0 14 81 02 46 ae 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 c0 14 81 02 46 ae 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 c0 14 81 02 46 ae 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 c0 14 81 02 46 ae 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 c0 14 81 02 46 ae 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 c0 14 81 02 46 ae 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 c0 14 81 02 46 ae 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 c0 14 81 02 46 ae 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 c0 14 81 02 46 ae 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 c0 14 81 02 46 ae 0b 09 31 81 02 45 00 c0 05 0d 15 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 25 0a 75 08 09 54 81 02 85 44 09 55 b1 02 85 44 06 00 ff 09 c5 26 ff 00 96 00 01 b1 02 85 f0 09 01 95 04 b1 02 85 f2 09 03 b1 02 09 04 b1 02 09 05 b1 02 95 01 09 06 b1 02 09 07 b1 02 85 f1 09 02 95 07 91 02 85 f3 09 08 95 3d b1 02 c0", 1794 + ) 1795 + 1796 + 1797 + class Testadvanced_silicon_2149_2306(BaseTest.TestWin8Multitouch): 1798 + def create_device(self): 1799 + return Digitizer( 1800 + "uhid test advanced_silicon_2149_2306", 1801 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f6 13 81 02 46 40 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f6 13 81 02 46 40 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f6 13 81 02 46 40 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f6 13 81 02 46 40 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f6 13 81 02 46 40 0b 09 31 81 02 45 00 c0 05 0d 15 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 25 0a 75 08 09 54 81 02 85 44 09 55 b1 02 85 44 06 00 ff 09 c5 26 ff 00 96 00 01 b1 02 85 f0 09 01 95 04 81 02 85 f2 09 03 b1 02 09 04 b1 02 09 05 b1 02 95 01 09 06 b1 02 09 07 b1 02 85 f1 09 02 95 07 91 02 85 f3 09 08 95 3d b1 02 c0", 1802 + ) 1803 + 1804 + 1805 + class Testadvanced_silicon_2149_230a(BaseTest.TestWin8Multitouch): 1806 + def create_device(self): 1807 + return Digitizer( 1808 + "uhid test advanced_silicon_2149_230a", 1809 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f6 13 81 02 46 40 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f6 13 81 02 46 40 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f6 13 81 02 46 40 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f6 13 81 02 46 40 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f6 13 81 02 46 40 0b 09 31 81 02 45 00 c0 05 0d 15 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 25 0a 75 08 09 54 81 02 85 44 09 55 b1 02 85 44 06 00 ff 09 c5 26 ff 00 96 00 01 b1 02 85 f0 09 01 95 04 81 02 85 f2 09 03 b1 02 09 04 b1 02 09 05 b1 02 95 01 09 06 b1 02 09 07 b1 02 85 f1 09 02 95 07 91 02 85 f3 09 08 95 3d b1 02 c0", 1810 + ) 1811 + 1812 + 1813 + class Testadvanced_silicon_2149_231c(BaseTest.TestWin8Multitouch): 1814 + def create_device(self): 1815 + return Digitizer( 1816 + "uhid test advanced_silicon_2149_231c", 1817 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 e2 13 81 02 46 32 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 e2 13 81 02 46 32 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 e2 13 81 02 46 32 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 e2 13 81 02 46 32 0b 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 e2 13 81 02 46 32 0b 09 31 81 02 45 00 c0 05 0d 15 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 25 0a 75 08 09 54 81 02 85 44 09 55 b1 02 85 44 06 00 ff 09 c5 26 ff 00 96 00 01 b1 02 85 f0 09 01 95 04 b1 02 85 f2 09 03 b1 02 09 04 b1 02 09 05 b1 02 95 01 09 06 b1 02 09 07 b1 02 85 f1 09 02 95 07 91 02 85 f3 09 08 95 3d b1 02 c0", 1818 + ) 1819 + 1820 + 1821 + class Testadvanced_silicon_2149_2703(BaseTest.TestWin8Multitouch): 1822 + def create_device(self): 1823 + return Digitizer( 1824 + "uhid test advanced_silicon_2149_2703", 1825 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 66 17 81 02 46 34 0d 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 66 17 81 02 46 34 0d 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 66 17 81 02 46 34 0d 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 66 17 81 02 46 34 0d 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 66 17 81 02 46 34 0d 09 31 81 02 45 00 c0 05 0d 15 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 25 0a 75 08 09 54 81 02 85 44 09 55 b1 02 85 44 06 00 ff 09 c5 26 ff 00 96 00 01 b1 02 85 f0 09 01 95 04 81 02 85 f2 09 03 b1 02 09 04 b1 02 09 05 b1 02 95 01 09 06 b1 02 09 07 b1 02 85 f1 09 02 95 07 91 02 85 f3 09 08 95 3d b1 02 c0", 1826 + ) 1827 + 1828 + 1829 + class Testadvanced_silicon_2149_270b(BaseTest.TestWin8Multitouch): 1830 + def create_device(self): 1831 + return Digitizer( 1832 + "uhid test advanced_silicon_2149_270b", 1833 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 52 17 81 02 46 20 0d 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 52 17 81 02 46 20 0d 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 52 17 81 02 46 20 0d 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 52 17 81 02 46 20 0d 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 52 17 81 02 46 20 0d 09 31 81 02 45 00 c0 05 0d 15 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 25 0a 75 08 09 54 81 02 85 44 09 55 b1 02 85 44 06 00 ff 09 c5 26 ff 00 96 00 01 b1 02 85 f0 09 01 95 04 b1 02 85 f2 09 03 b1 02 09 04 b1 02 09 05 b1 02 95 01 09 06 b1 02 09 07 b1 02 85 f1 09 02 95 07 91 02 85 f3 09 08 95 3d b1 02 c0", 1834 + ) 1835 + 1836 + 1837 + class Testadvanced_silicon_2575_0204(BaseTest.TestWin8Multitouch): 1838 + """found on the Dell Canvas 27""" 1839 + 1840 + def create_device(self): 1841 + return Digitizer( 1842 + "uhid test advanced_silicon_2575_0204", 1843 + rdesc="05 0d 09 04 a1 01 85 01 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 25 7f 09 51 75 07 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 4f 17 81 02 46 1d 0d 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 25 7f 09 51 75 07 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 4f 17 81 02 46 1d 0d 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 25 7f 09 51 75 07 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 4f 17 81 02 46 1d 0d 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 25 7f 09 51 75 07 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 4f 17 81 02 46 1d 0d 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 25 7f 09 51 75 07 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 4f 17 81 02 46 1d 0d 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 25 7f 09 51 75 07 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 4f 17 81 02 46 1d 0d 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 25 7f 09 51 75 07 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 4f 17 81 02 46 1d 0d 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 25 7f 09 51 75 07 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 4f 17 81 02 46 1d 0d 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 25 7f 09 51 75 07 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 4f 17 81 02 46 1d 0d 09 31 81 02 45 00 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 25 7f 09 51 75 07 95 01 81 02 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 4f 17 81 02 46 1d 0d 09 31 81 02 45 00 c0 05 0d 15 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 25 0a 75 08 09 54 81 02 85 42 09 55 25 0a b1 02 85 44 06 00 ff 09 c5 26 ff 00 96 00 01 b1 02 c0 05 01 09 0e a1 01 85 05 05 01 09 08 a1 00 09 30 55 0e 65 11 15 00 26 ff 7f 35 00 46 4f 17 75 10 95 01 81 42 09 31 46 1d 0d 81 42 06 00 ff 09 01 75 20 81 03 05 01 09 37 55 00 65 14 16 98 fe 26 68 01 36 98 fe 46 68 01 75 0f 81 06 05 09 09 01 65 00 15 00 25 01 35 00 45 00 75 01 81 02 05 0d 09 42 81 02 09 51 75 07 25 7f 81 02 05 0d 09 48 55 0e 65 11 15 00 26 ff 7f 35 00 46 ff 7f 75 10 81 02 09 49 81 02 09 3f 55 00 65 14 15 00 26 67 01 35 00 46 67 01 81 0a c0 65 00 35 00 45 00 05 0d 15 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 25 05 75 08 09 54 81 02 85 47 09 55 25 05 b1 02 c0 06 00 ff 09 04 a1 01 85 f0 09 01 75 08 95 04 b1 02 85 f2 09 03 b1 02 09 04 b1 02 09 05 b1 02 85 c0 09 01 95 03 b1 02 85 c2 09 01 95 0f b1 02 85 c4 09 01 95 3e b1 02 85 c5 09 01 95 7e b1 02 85 c6 09 01 95 fe b1 02 85 c8 09 01 96 fe 03 b1 02 85 0a 09 01 95 3f b1 02 c0", 1844 + ) 1845 + 1846 + 1847 + class Testadvanced_silicon_2619_5610(BaseTest.TestWin8Multitouch): 1848 + def create_device(self): 1849 + return Digitizer( 1850 + "uhid test advanced_silicon_2619_5610", 1851 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 a1 00 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f9 15 81 02 46 73 0c 09 31 81 02 45 00 c0 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 a1 00 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f9 15 81 02 46 73 0c 09 31 81 02 45 00 c0 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 a1 00 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f9 15 81 02 46 73 0c 09 31 81 02 45 00 c0 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 a1 00 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f9 15 81 02 46 73 0c 09 31 81 02 45 00 c0 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 a1 00 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f9 15 81 02 46 73 0c 09 31 81 02 45 00 c0 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 a1 00 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f9 15 81 02 46 73 0c 09 31 81 02 45 00 c0 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 a1 00 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f9 15 81 02 46 73 0c 09 31 81 02 45 00 c0 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 a1 00 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f9 15 81 02 46 73 0c 09 31 81 02 45 00 c0 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 a1 00 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f9 15 81 02 46 73 0c 09 31 81 02 45 00 c0 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 02 81 03 09 51 25 1f 75 05 95 01 81 02 a1 00 05 01 26 ff 7f 75 10 55 0e 65 11 09 30 35 00 46 f9 15 81 02 46 73 0c 09 31 81 02 45 00 c0 c0 05 0d 15 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 25 0a 75 08 09 54 81 02 85 44 09 55 b1 02 85 44 06 00 ff 09 c5 26 ff 00 96 00 01 b1 02 85 f0 09 01 95 04 81 02 85 f2 09 03 b1 02 09 04 b1 02 09 05 b1 02 95 01 09 06 b1 02 09 07 b1 02 85 f1 09 02 95 07 91 02 c0", 1852 + ) 1853 + 1854 + 1855 + class Testatmel_03eb_8409(BaseTest.TestWin8Multitouch): 1856 + def create_device(self): 1857 + return Digitizer( 1858 + "uhid test atmel_03eb_8409", 1859 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 02 46 c8 0a 26 6f 08 09 30 81 02 35 00 35 00 46 18 06 26 77 0f 09 31 81 02 35 00 35 00 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 48 81 02 09 49 81 02 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 02 46 c8 0a 26 6f 08 09 30 81 02 35 00 35 00 46 18 06 26 77 0f 09 31 81 02 35 00 35 00 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 48 81 02 09 49 81 02 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 02 46 c8 0a 26 6f 08 09 30 81 02 35 00 35 00 46 18 06 26 77 0f 09 31 81 02 35 00 35 00 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 48 81 02 09 49 81 02 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 02 46 c8 0a 26 6f 08 09 30 81 02 35 00 35 00 46 18 06 26 77 0f 09 31 81 02 35 00 35 00 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 48 81 02 09 49 81 02 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 02 46 c8 0a 26 6f 08 09 30 81 02 35 00 35 00 46 18 06 26 77 0f 09 31 81 02 35 00 35 00 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 48 81 02 09 49 81 02 c0 05 0d 27 ff ff 00 00 75 10 95 01 09 56 81 02 15 00 25 1f 75 05 09 54 95 01 81 02 75 03 25 01 95 01 81 03 75 08 85 02 09 55 25 10 b1 02 06 00 ff 85 05 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 00 a1 01 85 03 09 20 a1 00 15 00 25 01 75 01 95 01 09 42 81 02 09 44 81 02 09 45 81 02 81 03 09 32 81 02 95 03 81 03 05 01 55 0e 65 11 35 00 75 10 95 02 46 c8 0a 26 6f 08 09 30 81 02 46 18 06 26 77 0f 09 31 81 02 05 0d 09 30 15 01 26 ff 00 75 08 95 01 81 02 c0 c0", 1860 + ) 1861 + 1862 + 1863 + class Testatmel_03eb_840b(BaseTest.TestWin8Multitouch): 1864 + def create_device(self): 1865 + return Digitizer( 1866 + "uhid test atmel_03eb_840b", 1867 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 01 46 00 0a 26 ff 0f 09 30 81 02 09 00 81 03 46 a0 05 26 ff 0f 09 31 81 02 09 00 81 03 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 00 81 03 09 00 81 03 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 01 46 00 0a 26 ff 0f 09 30 81 02 09 00 81 03 46 a0 05 26 ff 0f 09 31 81 02 09 00 81 03 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 00 81 03 09 00 81 03 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 01 46 00 0a 26 ff 0f 09 30 81 02 09 00 81 03 46 a0 05 26 ff 0f 09 31 81 02 09 00 81 03 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 00 81 03 09 00 81 03 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 01 46 00 0a 26 ff 0f 09 30 81 02 09 00 81 03 46 a0 05 26 ff 0f 09 31 81 02 09 00 81 03 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 00 81 03 09 00 81 03 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 01 46 00 0a 26 ff 0f 09 30 81 02 09 00 81 03 46 a0 05 26 ff 0f 09 31 81 02 09 00 81 03 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 00 81 03 09 00 81 03 c0 05 0d 27 ff ff 00 00 75 10 95 01 09 56 81 02 15 00 25 1f 75 05 09 54 95 01 81 02 75 03 25 01 95 01 81 03 75 08 85 02 09 55 25 10 b1 02 06 00 ff 85 05 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 02 a1 01 85 03 09 20 a1 00 15 00 25 01 75 01 95 01 09 42 81 02 09 44 81 02 09 45 81 02 81 03 09 32 81 02 95 03 81 03 05 01 55 0e 65 11 35 00 75 10 95 02 46 00 0a 26 ff 0f 09 30 81 02 46 a0 05 26 ff 0f 09 31 81 02 05 0d 09 30 15 01 26 ff 00 75 08 95 01 81 02 c0 c0", 1868 + ) 1869 + 1870 + 1871 + class Testdell_044e_1220(BaseTest.TestPTP): 1872 + def create_device(self): 1873 + return PTP( 1874 + "uhid test dell_044e_1220", 1875 + type="pressurepad", 1876 + rdesc="05 01 09 02 a1 01 85 01 09 01 a1 00 05 09 19 01 29 03 15 00 25 01 75 01 95 03 81 02 95 05 81 01 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 09 38 95 01 81 06 05 0c 0a 38 02 81 06 c0 c0 05 0d 09 05 a1 01 85 08 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 75 01 95 03 81 03 05 01 15 00 26 af 04 75 10 55 0e 65 11 09 30 35 00 46 e8 03 95 01 81 02 26 7b 02 46 12 02 09 31 81 02 c0 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 05 0d 09 56 81 02 09 54 25 05 95 01 75 08 81 02 05 09 19 01 29 03 25 01 75 01 95 03 81 02 95 05 81 03 05 0d 85 09 09 55 75 08 95 01 25 05 b1 02 06 00 ff 85 0a 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 06 01 ff 09 01 a1 01 85 03 09 01 15 00 26 ff 00 95 1b 81 02 85 04 09 02 95 50 81 02 85 05 09 03 95 07 b1 02 85 06 09 04 81 02 c0 06 02 ff 09 01 a1 01 85 07 09 02 95 86 75 08 b1 02 c0 05 0d 09 0e a1 01 85 0b 09 22 a1 02 09 52 15 00 25 0a 75 08 95 01 b1 02 c0 09 22 a1 00 85 0c 09 57 09 58 75 01 95 02 25 01 b1 02 95 06 b1 03 c0 c0", 1877 + ) 1878 + 1879 + 1880 + class Testdell_06cb_75db(BaseTest.TestPTP): 1881 + def create_device(self): 1882 + return PTP( 1883 + "uhid test dell_06cb_75db", 1884 + max_contacts=3, 1885 + rdesc="05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 01 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0 05 0d 09 05 a1 01 85 03 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 75 01 95 03 81 03 05 01 15 00 26 c8 04 75 10 55 0e 65 11 09 30 35 00 46 fb 03 95 01 81 02 46 6c 02 26 e8 02 09 31 81 02 c0 05 0d 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 75 01 95 03 81 03 05 01 15 00 26 c8 04 75 10 55 0e 65 11 09 30 35 00 46 fb 03 95 01 81 02 46 6c 02 26 e8 02 09 31 81 02 c0 05 0d 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 75 01 95 03 81 03 05 01 15 00 26 c8 04 75 10 55 0e 65 11 09 30 35 00 46 fb 03 95 01 81 02 46 6c 02 26 e8 02 09 31 81 02 05 0d c0 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 09 54 25 7f 95 01 75 08 81 02 05 09 09 01 25 01 75 01 95 01 81 02 95 07 81 03 05 0d 85 08 09 55 09 59 75 04 95 02 25 0f b1 02 85 0d 09 60 75 01 95 01 15 00 25 01 b1 02 95 07 b1 03 85 07 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 0e a1 01 85 04 09 22 a1 02 09 52 15 00 25 0a 75 08 95 01 b1 02 c0 09 22 a1 00 85 06 09 57 09 58 75 01 95 02 25 01 b1 02 95 06 b1 03 c0 c0 06 00 ff 09 01 a1 01 85 09 09 02 15 00 26 ff 00 75 08 95 14 91 02 85 0a 09 03 15 00 26 ff 00 75 08 95 14 91 02 85 0b 09 04 15 00 26 ff 00 75 08 95 1a 81 02 85 0c 09 05 15 00 26 ff 00 75 08 95 1a 81 02 85 0f 09 06 15 00 26 ff 00 75 08 95 01 b1 02 85 0e 09 07 15 00 26 ff 00 75 08 95 01 b1 02 c0", 1886 + ) 1887 + 1888 + 1889 + class Testegalax_capacitive_0eef_790a(BaseTest.TestWin8Multitouch): 1890 + def create_device(self): 1891 + return Digitizer( 1892 + "uhid test egalax_capacitive_0eef_790a", 1893 + max_contacts=10, 1894 + rdesc="05 0d 09 04 a1 01 85 06 05 0d 09 54 75 08 15 00 25 0c 95 01 81 02 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 03 75 08 09 51 95 01 15 00 25 20 81 02 05 01 26 ff 0f 75 10 55 0e 65 11 09 30 35 00 46 13 0c 81 02 46 cb 06 09 31 81 02 75 08 95 02 81 03 81 03 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 03 75 08 09 51 95 01 15 00 25 20 81 02 05 01 26 ff 0f 75 10 55 0e 65 11 09 30 35 00 46 13 0c 81 02 46 cb 06 09 31 81 02 75 08 95 02 81 03 81 03 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 03 75 08 09 51 95 01 15 00 25 20 81 02 05 01 26 ff 0f 75 10 55 0e 65 11 09 30 35 00 46 13 0c 81 02 46 cb 06 09 31 81 02 75 08 95 02 81 03 81 03 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 03 75 08 09 51 95 01 15 00 25 20 81 02 05 01 26 ff 0f 75 10 55 0e 65 11 09 30 35 00 46 13 0c 81 02 46 cb 06 09 31 81 02 75 08 95 02 81 03 81 03 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 03 75 08 09 51 95 01 15 00 25 20 81 02 05 01 26 ff 0f 75 10 55 0e 65 11 09 30 35 00 46 13 0c 81 02 46 cb 06 09 31 81 02 75 08 95 02 81 03 81 03 c0 05 0d 17 00 00 00 00 27 ff ff ff 7f 75 20 95 01 55 00 65 00 09 56 81 02 09 55 09 53 75 08 95 02 26 ff 00 b1 02 06 00 ff 09 c5 85 07 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 01 09 01 a1 01 85 01 09 01 a1 02 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 0e a1 01 85 05 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0", 1895 + ) 1896 + 1897 + 1898 + class Testelan_04f3_000a(BaseTest.TestWin8Multitouch): 1899 + def create_device(self): 1900 + return Digitizer( 1901 + "uhid test elan_04f3_000a", 1902 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 00 08 46 a6 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 00 08 46 a6 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 00 08 46 a6 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 00 08 46 a6 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 00 08 46 a6 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 00 08 46 a6 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 00 08 46 a6 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 00 08 46 a6 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 00 08 46 a6 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 00 08 46 a6 00 09 31 81 02 c0 05 0d 09 56 55 00 65 00 27 ff ff ff 7f 95 01 75 20 81 02 09 54 25 7f 95 01 75 08 81 02 85 0a 09 55 25 0a b1 02 85 44 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 06 ff 01 09 01 a1 01 85 02 15 00 26 ff 00 75 08 95 40 09 00 81 02 c0 06 00 ff 09 01 a1 01 85 03 75 08 95 1f 09 01 91 02 c0 06 01 ff 09 01 a1 01 85 04 15 00 26 ff 00 75 08 95 13 09 00 81 02 c0", 1903 + ) 1904 + 1905 + 1906 + class Testelan_04f3_000c(BaseTest.TestWin8Multitouch): 1907 + def create_device(self): 1908 + return Digitizer( 1909 + "uhid test elan_04f3_000c", 1910 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 40 0e 75 10 55 0f 65 11 09 30 35 00 46 01 01 95 02 81 02 26 00 08 46 91 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 40 0e 75 10 55 0f 65 11 09 30 35 00 46 01 01 95 02 81 02 26 00 08 46 91 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 40 0e 75 10 55 0f 65 11 09 30 35 00 46 01 01 95 02 81 02 26 00 08 46 91 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 40 0e 75 10 55 0f 65 11 09 30 35 00 46 01 01 95 02 81 02 26 00 08 46 91 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 40 0e 75 10 55 0f 65 11 09 30 35 00 46 01 01 95 02 81 02 26 00 08 46 91 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 40 0e 75 10 55 0f 65 11 09 30 35 00 46 01 01 95 02 81 02 26 00 08 46 91 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 40 0e 75 10 55 0f 65 11 09 30 35 00 46 01 01 95 02 81 02 26 00 08 46 91 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 40 0e 75 10 55 0f 65 11 09 30 35 00 46 01 01 95 02 81 02 26 00 08 46 91 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 40 0e 75 10 55 0f 65 11 09 30 35 00 46 01 01 95 02 81 02 26 00 08 46 91 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 40 0e 75 10 55 0f 65 11 09 30 35 00 46 01 01 95 02 81 02 26 00 08 46 91 00 09 31 81 02 c0 05 0d 09 56 55 00 65 00 27 ff ff ff 7f 95 01 75 20 81 02 09 54 25 7f 95 01 75 08 81 02 85 0a 09 55 25 0a b1 02 85 44 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 06 ff 01 09 01 a1 01 85 02 15 00 26 ff 00 75 08 95 40 09 00 81 02 c0 06 00 ff 09 01 a1 01 85 03 75 08 95 1f 09 01 91 02 c0 06 01 ff 09 01 a1 01 85 04 15 00 26 ff 00 75 08 95 13 09 00 81 02 c0", 1911 + ) 1912 + 1913 + 1914 + class Testelan_04f3_010c(BaseTest.TestWin8Multitouch): 1915 + def create_device(self): 1916 + return Digitizer( 1917 + "uhid test elan_04f3_010c", 1918 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c2 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c2 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c2 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c2 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c2 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c2 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c2 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c2 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c2 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c2 00 09 31 81 02 c0 05 0d 09 56 55 00 65 00 27 ff ff ff 7f 95 01 75 20 81 02 09 54 25 7f 95 01 75 08 81 02 85 0a 09 55 25 0a b1 02 85 44 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 06 ff 01 09 01 a1 01 85 02 15 00 26 ff 00 75 08 95 40 09 00 81 02 c0 06 00 ff 09 01 a1 01 85 03 75 08 95 1f 09 01 91 02 c0 06 01 ff 09 01 a1 01 85 04 15 00 26 ff 00 75 08 95 13 09 00 81 02 c0", 1919 + ) 1920 + 1921 + 1922 + class Testelan_04f3_0125(BaseTest.TestWin8Multitouch): 1923 + def create_device(self): 1924 + return Digitizer( 1925 + "uhid test elan_04f3_0125", 1926 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c1 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c1 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c1 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c1 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c1 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c1 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c1 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c1 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c1 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 f0 0c 75 10 55 0f 65 11 09 30 35 00 46 58 01 95 02 81 02 26 50 07 46 c1 00 09 31 81 02 c0 05 0d 09 56 55 00 65 00 27 ff ff ff 7f 95 01 75 20 81 02 09 54 25 7f 95 01 75 08 81 02 85 0a 09 55 25 0a b1 02 85 44 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 06 ff 01 09 01 a1 01 85 02 15 00 26 ff 00 75 08 95 40 09 00 81 02 c0 06 00 ff 09 01 a1 01 85 03 75 08 95 1f 09 01 91 02 c0 06 01 ff 09 01 a1 01 85 04 15 00 26 ff 00 75 08 95 13 09 00 81 02 c0", 1927 + ) 1928 + 1929 + 1930 + class Testelan_04f3_016f(BaseTest.TestWin8Multitouch): 1931 + def create_device(self): 1932 + return Digitizer( 1933 + "uhid test elan_04f3_016f", 1934 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 40 08 46 a6 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 40 08 46 a6 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 40 08 46 a6 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 40 08 46 a6 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 40 08 46 a6 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 40 08 46 a6 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 40 08 46 a6 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 40 08 46 a6 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 40 08 46 a6 00 09 31 81 02 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 40 08 46 a6 00 09 31 81 02 c0 05 0d 09 56 55 00 65 00 27 ff ff ff 7f 95 01 75 20 81 02 09 54 25 7f 95 01 75 08 81 02 85 0a 09 55 25 0a b1 02 85 44 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 06 ff 01 09 01 a1 01 85 02 15 00 26 ff 00 75 08 95 40 09 00 81 02 c0 06 00 ff 09 01 a1 01 85 03 75 08 95 1f 09 01 91 02 c0 06 01 ff 09 01 a1 01 85 04 15 00 26 ff 00 75 08 95 13 09 00 81 02 c0", 1935 + ) 1936 + 1937 + 1938 + class Testelan_04f3_0732(BaseTest.TestWin8Multitouch): 1939 + def create_device(self): 1940 + return Digitizer( 1941 + "uhid test elan_04f3_0732", 1942 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0b 75 10 55 0f 65 11 09 30 35 00 46 ff 00 95 02 81 02 26 40 07 46 85 00 09 31 81 02 c0 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0b 75 10 55 0f 65 11 09 30 35 00 46 ff 00 95 02 81 02 26 40 07 46 85 00 09 31 81 02 c0 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0b 75 10 55 0f 65 11 09 30 35 00 46 ff 00 95 02 81 02 26 40 07 46 85 00 09 31 81 02 c0 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0b 75 10 55 0f 65 11 09 30 35 00 46 ff 00 95 02 81 02 26 40 07 46 85 00 09 31 81 02 c0 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0b 75 10 55 0f 65 11 09 30 35 00 46 ff 00 95 02 81 02 26 40 07 46 85 00 09 31 81 02 c0 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0b 75 10 55 0f 65 11 09 30 35 00 46 ff 00 95 02 81 02 26 40 07 46 85 00 09 31 81 02 c0 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0b 75 10 55 0f 65 11 09 30 35 00 46 ff 00 95 02 81 02 26 40 07 46 85 00 09 31 81 02 c0 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0b 75 10 55 0f 65 11 09 30 35 00 46 ff 00 95 02 81 02 26 40 07 46 85 00 09 31 81 02 c0 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0b 75 10 55 0f 65 11 09 30 35 00 46 ff 00 95 02 81 02 26 40 07 46 85 00 09 31 81 02 c0 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0b 75 10 55 0f 65 11 09 30 35 00 46 ff 00 95 02 81 02 26 40 07 46 85 00 09 31 81 02 c0 05 0d 09 56 55 00 65 00 27 ff ff 00 00 95 01 75 20 81 02 09 54 25 7f 95 01 75 08 81 02 85 0a 09 55 25 0a b1 02 85 44 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 06 ff 01 09 01 a1 01 85 02 15 00 25 ff 75 08 95 40 09 00 81 02 c0 06 00 ff 09 01 a1 01 85 03 75 08 95 1f 09 01 91 02 c0", 1943 + ) 1944 + 1945 + 1946 + class Testelan_04f3_200a(BaseTest.TestWin8Multitouch): 1947 + def create_device(self): 1948 + return Digitizer( 1949 + "uhid test elan_04f3_200a", 1950 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 40 08 46 a6 00 09 31 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 75 06 09 51 25 3f 81 02 26 ff 00 75 08 09 48 81 02 09 49 81 02 95 01 05 01 26 c0 0e 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 02 81 02 26 40 08 46 a6 00 09 31 81 02 c0 05 0d 09 56 55 00 65 00 27 ff ff 00 00 95 01 75 20 81 02 09 54 25 7f 95 01 75 08 81 02 85 0a 09 55 25 0a b1 02 85 0e 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0", 1951 + ) 1952 + 1953 + 1954 + class Testelan_04f3_300b(BaseTest.TestPTP): 1955 + def create_device(self): 1956 + return PTP( 1957 + "uhid test elan_04f3_300b", 1958 + max_contacts=3, 1959 + rdesc="05 01 09 02 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 09 38 15 81 25 7f 75 08 95 03 81 06 05 0c 0a 38 02 95 01 81 06 75 08 95 03 81 03 c0 06 00 ff 85 0d 09 c5 15 00 26 ff 00 75 08 95 04 b1 02 85 0c 09 c6 96 76 02 75 08 b1 02 85 0b 09 c7 95 42 75 08 b1 02 09 01 85 5d 95 1f 75 08 81 06 c0 05 0d 09 05 a1 01 85 04 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 02 25 02 09 51 81 02 75 01 95 04 81 03 05 01 15 00 26 a7 0c 75 10 55 0e 65 13 09 30 35 00 46 9d 01 95 01 81 02 46 25 01 26 2b 09 26 2b 09 09 31 81 02 05 0d 15 00 25 64 95 03 c0 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 09 54 25 7f 95 01 75 08 81 02 05 09 09 01 25 01 75 01 95 01 81 02 95 07 81 03 05 0d 85 02 09 55 09 59 75 04 95 02 25 0f b1 02 85 07 09 60 75 01 95 01 15 00 25 01 b1 02 95 0f b1 03 06 00 ff 06 00 ff 85 06 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 0e a1 01 85 03 09 22 a1 00 09 52 15 00 25 0a 75 08 95 02 b1 02 c0 09 22 a1 00 85 05 09 57 09 58 15 00 75 01 95 02 25 03 b1 02 95 0e b1 03 c0 c0", 1960 + ) 1961 + 1962 + 1963 + class Testelan_04f3_3045(BaseTest.TestPTP): 1964 + def create_device(self): 1965 + return PTP( 1966 + "uhid test elan_04f3_3045", 1967 + rdesc="05 01 09 02 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 09 38 15 81 25 7f 75 08 95 03 81 06 05 0c 0a 38 02 95 01 81 06 75 08 95 03 81 03 c0 c0 05 0d 09 05 a1 01 85 04 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 75 01 95 02 81 03 95 01 75 04 25 0f 09 51 81 02 05 01 15 00 26 80 0c 75 10 55 0e 65 13 09 30 35 00 46 90 01 95 01 81 02 46 13 01 26 96 08 26 96 08 09 31 81 02 05 0d 15 00 25 64 95 03 c0 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 09 54 25 7f 95 01 75 08 81 02 05 09 09 01 25 01 75 01 95 01 81 02 95 07 81 03 09 c5 75 08 95 04 81 03 05 0d 85 02 09 55 09 59 75 04 95 02 25 0f b1 02 85 07 09 60 75 01 95 01 15 00 25 01 b1 02 95 0f b1 03 06 00 ff 06 00 ff 85 06 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 85 0d 09 c5 15 00 26 ff 00 75 08 95 04 b1 02 85 0c 09 c6 96 8a 02 75 08 b1 02 85 0b 09 c7 95 80 75 08 b1 02 c0 05 0d 09 0e a1 01 85 03 09 22 a1 00 09 52 15 00 25 0a 75 08 95 02 b1 02 c0 09 22 a1 00 85 05 09 57 09 58 15 00 75 01 95 02 25 03 b1 02 95 0e b1 03 c0 c0", 1968 + ) 1969 + 1970 + 1971 + class Testelan_04f3_313a(BaseTest.TestPTP): 1972 + def create_device(self): 1973 + return PTP( 1974 + "uhid test elan_04f3_313a", 1975 + type="touchpad", 1976 + input_info=(BusType.I2C, 0x04F3, 0x313A), 1977 + rdesc="05 01 09 02 a1 01 85 01 09 01 a1 00 05 09 19 01 29 03 15 00 25 01 75 01 95 03 81 02 95 05 81 03 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 75 08 95 05 81 03 c0 06 00 ff 09 01 85 0e 09 c5 15 00 26 ff 00 75 08 95 04 b1 02 85 0a 09 c6 15 00 26 ff 00 75 08 95 04 b1 02 c0 06 00 ff 09 01 a1 01 85 5c 09 01 95 0b 75 08 81 06 85 0d 09 c5 15 00 26 ff 00 75 08 95 04 b1 02 85 0c 09 c6 96 80 03 75 08 b1 02 85 0b 09 c7 95 82 75 08 b1 02 c0 05 0d 09 05 a1 01 85 04 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 05 09 09 02 09 03 15 00 25 01 75 01 95 02 81 02 05 0d 95 01 75 04 25 0f 09 51 81 02 05 01 15 00 26 d7 0e 75 10 55 0d 65 11 09 30 35 00 46 44 2f 95 01 81 02 46 12 16 26 eb 06 26 eb 06 09 31 81 02 05 0d 15 00 25 64 95 03 c0 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 09 54 25 7f 95 01 75 08 81 02 25 01 75 01 95 08 81 03 09 c5 75 08 95 02 81 03 05 0d 85 02 09 55 09 59 75 04 95 02 25 0f b1 02 85 07 09 60 75 01 95 01 15 00 25 01 b1 02 95 0f b1 03 06 00 ff 06 00 ff 85 06 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 0e a1 01 85 03 09 22 a1 00 09 52 15 00 25 0a 75 10 95 01 b1 02 c0 09 22 a1 00 85 05 09 57 09 58 75 01 95 02 25 01 b1 02 95 0e b1 03 c0 c0 05 01 09 02 a1 01 85 2a 09 01 a1 00 05 09 19 01 29 03 15 00 25 01 75 01 95 03 81 02 95 05 81 03 05 01 09 30 09 31 15 81 25 7f 35 81 45 7f 55 00 65 13 75 08 95 02 81 06 75 08 95 05 81 03 c0 c0", 1978 + ) 1979 + 1980 + 1981 + class Testelo_04e7_0080(BaseTest.TestWin8Multitouch): 1982 + def create_device(self): 1983 + return Digitizer( 1984 + "uhid test elo_04e7_0080", 1985 + rdesc="05 0d 09 04 a1 01 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 03 81 03 09 32 95 02 81 02 95 02 81 03 09 51 75 08 95 01 81 02 05 01 26 ff 7f 65 11 55 0e 75 10 09 30 46 7c 24 81 02 09 31 46 96 14 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 03 81 03 09 32 95 02 81 02 95 02 81 03 09 51 75 08 95 01 81 02 05 01 26 ff 7f 65 11 55 0e 75 10 09 30 46 7c 24 81 02 09 31 46 96 14 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 03 81 03 09 32 95 02 81 02 95 02 81 03 09 51 75 08 95 01 81 02 05 01 26 ff 7f 65 11 55 0e 75 10 09 30 46 7c 24 81 02 09 31 46 96 14 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 03 81 03 09 32 95 02 81 02 95 02 81 03 09 51 75 08 95 01 81 02 05 01 26 ff 7f 65 11 55 0e 75 10 09 30 46 7c 24 81 02 09 31 46 96 14 81 02 c0 05 0d 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 09 54 75 08 95 01 15 00 25 08 81 02 09 55 b1 02 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0", 1986 + ) 1987 + 1988 + 1989 + class Testilitek_222a_0015(BaseTest.TestWin8Multitouch): 1990 + def create_device(self): 1991 + return Digitizer( 1992 + "uhid test ilitek_222a_0015", 1993 + rdesc="05 0d 09 04 a1 01 85 04 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 c2 16 35 00 46 b3 08 81 42 09 31 26 c2 0c 46 e4 04 81 42 c0 05 0d 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 c2 16 35 00 46 b3 08 81 42 09 31 26 c2 0c 46 e4 04 81 42 c0 05 0d 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 c2 16 35 00 46 b3 08 81 42 09 31 26 c2 0c 46 e4 04 81 42 c0 05 0d 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 c2 16 35 00 46 b3 08 81 42 09 31 26 c2 0c 46 e4 04 81 42 c0 05 0d 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 c2 16 35 00 46 b3 08 81 42 09 31 26 c2 0c 46 e4 04 81 42 c0 05 0d 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 c2 16 35 00 46 b3 08 81 42 09 31 26 c2 0c 46 e4 04 81 42 c0 05 0d 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 c2 16 35 00 46 b3 08 81 42 09 31 26 c2 0c 46 e4 04 81 42 c0 05 0d 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 c2 16 35 00 46 b3 08 81 42 09 31 26 c2 0c 46 e4 04 81 42 c0 05 0d 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 c2 16 35 00 46 b3 08 81 42 09 31 26 c2 0c 46 e4 04 81 42 c0 05 0d 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 c2 16 35 00 46 b3 08 81 42 09 31 26 c2 0c 46 e4 04 81 42 c0 05 0d 09 56 55 00 65 00 27 ff ff ff 7f 95 01 75 20 81 02 09 54 25 7f 95 01 75 08 81 02 85 02 09 55 25 0a b1 02 06 00 ff 09 c5 85 06 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 06 00 ff 09 01 a1 01 09 01 85 03 15 00 26 ff 00 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0", 1994 + ) 1995 + 1996 + 1997 + class Testilitek_222a_001c(BaseTest.TestWin8Multitouch): 1998 + def create_device(self): 1999 + return Digitizer( 2000 + "uhid test ilitek_222a_001c", 2001 + rdesc="05 0d 09 04 a1 01 85 04 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 74 1d 35 00 46 70 0d 81 42 09 31 26 74 10 46 8f 07 81 42 c0 05 0d 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 74 1d 35 00 46 70 0d 81 42 09 31 26 74 10 46 8f 07 81 42 c0 05 0d 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 74 1d 35 00 46 70 0d 81 42 09 31 26 74 10 46 8f 07 81 42 c0 05 0d 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 74 1d 35 00 46 70 0d 81 42 09 31 26 74 10 46 8f 07 81 42 c0 05 0d 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 74 1d 35 00 46 70 0d 81 42 09 31 26 74 10 46 8f 07 81 42 c0 05 0d 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 74 1d 35 00 46 70 0d 81 42 09 31 26 74 10 46 8f 07 81 42 c0 05 0d 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 74 1d 35 00 46 70 0d 81 42 09 31 26 74 10 46 8f 07 81 42 c0 05 0d 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 74 1d 35 00 46 70 0d 81 42 09 31 26 74 10 46 8f 07 81 42 c0 05 0d 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 74 1d 35 00 46 70 0d 81 42 09 31 26 74 10 46 8f 07 81 42 c0 05 0d 09 22 a1 02 05 0d 95 01 75 06 09 51 15 00 25 3f 81 02 09 42 25 01 75 01 95 01 81 02 75 01 95 01 81 03 05 01 75 10 55 0e 65 11 09 30 26 74 1d 35 00 46 70 0d 81 42 09 31 26 74 10 46 8f 07 81 42 c0 05 0d 09 56 55 00 65 00 27 ff ff ff 7f 95 01 75 20 81 02 09 54 25 7f 95 01 75 08 81 02 85 02 09 55 25 0a b1 02 06 00 ff 09 c5 85 06 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 06 00 ff 09 01 a1 01 09 01 85 03 15 00 26 ff 00 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0", 2002 + ) 2003 + 2004 + 2005 + class Testite_06cb_2968(BaseTest.TestPTP): 2006 + def create_device(self): 2007 + return PTP( 2008 + "uhid test ite_06cb_2968", 2009 + rdesc="05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 01 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0 05 0d 09 05 a1 01 85 03 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 75 01 95 03 81 03 05 01 15 00 26 1b 04 75 10 55 0e 65 11 09 30 35 00 46 6c 03 95 01 81 02 46 db 01 26 3b 02 09 31 81 02 05 0d c0 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 09 54 25 7f 95 01 75 08 81 02 05 09 09 01 25 01 75 01 95 01 81 02 95 07 81 03 05 0d 85 08 09 55 09 59 75 04 95 02 25 0f b1 02 85 0d 09 60 75 01 95 01 15 00 25 01 b1 02 95 07 b1 03 85 07 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 0e a1 01 85 04 09 22 a1 02 09 52 15 00 25 0a 75 08 95 01 b1 02 c0 09 22 a1 00 85 06 09 57 09 58 75 01 95 02 25 01 b1 02 95 06 b1 03 c0 c0 06 00 ff 09 01 a1 01 85 09 09 02 15 00 26 ff 00 75 08 95 14 91 02 85 0a 09 03 15 00 26 ff 00 75 08 95 14 91 02 85 0b 09 04 15 00 26 ff 00 75 08 95 1a 81 02 85 0c 09 05 15 00 26 ff 00 75 08 95 1a 81 02 85 0f 09 06 15 00 26 ff 00 75 08 95 01 b1 02 85 0e 09 07 15 00 26 ff 00 75 08 95 01 b1 02 c0", 2010 + max_contacts=5, 2011 + input_info=(0x3, 0x06CB, 0x2968), 2012 + ) 2013 + 2014 + 2015 + class Testn_trig_1b96_0c01(BaseTest.TestWin8Multitouch): 2016 + def create_device(self): 2017 + return Digitizer( 2018 + "uhid test n_trig_1b96_0c01", 2019 + rdesc="75 08 15 00 26 ff 00 06 0b ff 09 0b a1 01 95 0f 09 29 85 29 b1 02 95 1f 09 2a 85 2a b1 02 95 3e 09 2b 85 2b b1 02 95 fe 09 2c 85 2c b1 02 96 fe 01 09 2d 85 2d b1 02 95 02 09 48 85 48 b1 02 95 0f 09 2e 85 2e 81 02 95 1f 09 2f 85 2f 81 02 95 3e 09 30 85 30 81 02 95 fe 09 31 85 31 81 02 96 fe 01 09 32 85 32 81 02 75 08 96 fe 0f 09 35 85 35 81 02 c0 05 0d 09 02 a1 01 85 01 09 20 35 00 a1 00 09 32 09 42 09 44 09 3c 09 45 15 00 25 01 75 01 95 05 81 02 95 03 81 03 05 01 09 30 75 10 95 01 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 b4 05 0d 09 30 26 00 01 81 02 06 00 ff 09 01 81 02 c0 85 0c 06 00 ff 09 0c 75 08 95 06 26 ff 00 b1 02 85 0b 09 0b 95 02 b1 02 85 11 09 11 b1 02 85 15 09 15 95 05 b1 02 85 18 09 18 95 0c b1 02 c0 05 0d 09 04 a1 01 85 03 06 00 ff 09 01 75 10 95 01 15 00 27 ff ff 00 00 81 02 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 54 95 01 75 08 81 02 09 56 75 20 95 01 27 ff ff ff 0f 81 02 85 04 09 55 75 08 95 01 25 0b b1 02 85 0a 06 00 ff 09 03 15 00 b1 02 85 1b 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0", 2020 + ) 2021 + 2022 + 2023 + class Testn_trig_1b96_0c03(BaseTest.TestWin8Multitouch): 2024 + def create_device(self): 2025 + return Digitizer( 2026 + "uhid test n_trig_1b96_0c03", 2027 + rdesc="75 08 15 00 26 ff 00 06 0b ff 09 0b a1 01 95 0f 09 29 85 29 b1 02 95 1f 09 2a 85 2a b1 02 95 3e 09 2b 85 2b b1 02 95 fe 09 2c 85 2c b1 02 96 fe 01 09 2d 85 2d b1 02 95 02 09 48 85 48 b1 02 95 0f 09 2e 85 2e 81 02 95 1f 09 2f 85 2f 81 02 95 3e 09 30 85 30 81 02 95 fe 09 31 85 31 81 02 96 fe 01 09 32 85 32 81 02 75 08 96 fe 0f 09 35 85 35 81 02 c0 05 0d 09 02 a1 01 85 01 09 20 35 00 a1 00 09 32 09 42 09 44 09 3c 09 45 15 00 25 01 75 01 95 05 81 02 95 03 81 03 05 01 09 30 75 10 95 01 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 b4 05 0d 09 30 26 00 01 81 02 06 00 ff 09 01 81 02 c0 85 0c 06 00 ff 09 0c 75 08 95 06 26 ff 00 b1 02 85 0b 09 0b 95 02 b1 02 85 11 09 11 b1 02 85 15 09 15 95 05 b1 02 85 18 09 18 95 0c b1 02 c0 05 0d 09 04 a1 01 85 03 06 00 ff 09 01 75 10 95 01 15 00 27 ff ff 00 00 81 02 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 54 95 01 75 08 81 02 09 56 75 20 95 01 27 ff ff ff 0f 81 02 85 04 09 55 75 08 95 01 25 0b b1 02 85 0a 06 00 ff 09 03 15 00 b1 02 85 1b 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0", 2028 + ) 2029 + 2030 + 2031 + class Testn_trig_1b96_0f00(BaseTest.TestWin8Multitouch): 2032 + def create_device(self): 2033 + return Digitizer( 2034 + "uhid test n_trig_1b96_0f00", 2035 + rdesc="75 08 15 00 26 ff 00 06 0b ff 09 0b a1 01 95 0f 09 29 85 29 b1 02 95 1f 09 2a 85 2a b1 02 95 3e 09 2b 85 2b b1 02 95 fe 09 2c 85 2c b1 02 96 fe 01 09 2d 85 2d b1 02 95 02 09 48 85 48 b1 02 95 0f 09 2e 85 2e 81 02 95 1f 09 2f 85 2f 81 02 95 3e 09 30 85 30 81 02 95 fe 09 31 85 31 81 02 96 fe 01 09 32 85 32 81 02 75 08 96 fe 0f 09 35 85 35 81 02 c0 05 0d 09 02 a1 01 85 01 09 20 35 00 a1 00 09 32 09 42 09 44 09 3c 09 45 15 00 25 01 75 01 95 05 81 02 95 03 81 03 05 01 09 30 75 10 95 01 a4 55 0e 65 11 46 03 0a 26 80 25 81 02 09 31 46 a1 05 26 20 1c 81 02 b4 05 0d 09 30 26 00 01 81 02 06 00 ff 09 01 81 02 c0 85 0c 06 00 ff 09 0c 75 08 95 06 26 ff 00 b1 02 85 0b 09 0b 95 02 b1 02 85 11 09 11 b1 02 85 15 09 15 95 05 b1 02 85 18 09 18 95 0c b1 02 c0 05 0d 09 04 a1 01 85 03 06 00 ff 09 01 75 10 95 01 15 00 27 ff ff 00 00 81 02 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 03 0a 26 80 25 81 02 09 31 46 a1 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 03 0a 26 80 25 81 02 09 31 46 a1 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 54 95 01 75 08 81 02 09 56 75 20 95 01 27 ff ff ff 0f 81 02 85 04 09 55 75 08 95 01 25 0b b1 02 85 0a 06 00 ff 09 03 15 00 b1 02 85 1b 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0", 2036 + ) 2037 + 2038 + 2039 + class Testn_trig_1b96_0f04(BaseTest.TestWin8Multitouch): 2040 + def create_device(self): 2041 + return Digitizer( 2042 + "uhid test n_trig_1b96_0f04", 2043 + rdesc="75 08 15 00 26 ff 00 06 0b ff 09 0b a1 01 95 0f 09 29 85 29 b1 02 95 1f 09 2a 85 2a b1 02 95 3e 09 2b 85 2b b1 02 95 fe 09 2c 85 2c b1 02 96 fe 01 09 2d 85 2d b1 02 95 02 09 48 85 48 b1 02 95 0f 09 2e 85 2e 81 02 95 1f 09 2f 85 2f 81 02 95 3e 09 30 85 30 81 02 95 fe 09 31 85 31 81 02 96 fe 01 09 32 85 32 81 02 75 08 96 fe 0f 09 35 85 35 81 02 c0 05 0d 09 02 a1 01 85 01 09 20 35 00 a1 00 09 32 09 42 09 44 09 3c 09 45 15 00 25 01 75 01 95 05 81 02 95 03 81 03 05 01 09 30 75 10 95 01 a4 55 0e 65 11 46 7f 0b 26 80 25 81 02 09 31 46 78 06 26 20 1c 81 02 b4 05 0d 09 30 26 00 01 81 02 06 00 ff 09 01 81 02 c0 85 0c 06 00 ff 09 0c 75 08 95 06 26 ff 00 b1 02 85 0b 09 0b 95 02 b1 02 85 11 09 11 b1 02 85 15 09 15 95 05 b1 02 85 18 09 18 95 0c b1 02 c0 05 0d 09 04 a1 01 85 03 06 00 ff 09 01 75 10 95 01 15 00 27 ff ff 00 00 81 02 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 7f 0b 26 80 25 81 02 09 31 46 78 06 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 7f 0b 26 80 25 81 02 09 31 46 78 06 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 54 95 01 75 08 81 02 09 56 75 20 95 01 27 ff ff ff 0f 81 02 85 04 09 55 75 08 95 01 25 0b b1 02 85 0a 06 00 ff 09 03 15 00 b1 02 85 1b 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0", 2044 + ) 2045 + 2046 + 2047 + class Testn_trig_1b96_1000(BaseTest.TestWin8Multitouch): 2048 + def create_device(self): 2049 + return Digitizer( 2050 + "uhid test n_trig_1b96_1000", 2051 + rdesc="75 08 15 00 26 ff 00 06 0b ff 09 0b a1 01 95 0f 09 29 85 29 b1 02 95 1f 09 2a 85 2a b1 02 95 3e 09 2b 85 2b b1 02 95 fe 09 2c 85 2c b1 02 96 fe 01 09 2d 85 2d b1 02 95 02 09 48 85 48 b1 02 95 0f 09 2e 85 2e 81 02 95 1f 09 2f 85 2f 81 02 95 3e 09 30 85 30 81 02 95 fe 09 31 85 31 81 02 96 fe 01 09 32 85 32 81 02 75 08 96 fe 0f 09 35 85 35 81 02 c0 05 0d 09 02 a1 01 85 01 09 20 35 00 a1 00 09 32 09 42 09 44 09 3c 09 45 15 00 25 01 75 01 95 05 81 02 95 03 81 03 05 01 09 30 75 10 95 01 a4 55 0e 65 11 46 03 0a 26 80 25 81 02 09 31 46 a1 05 26 20 1c 81 02 b4 05 0d 09 30 26 00 01 81 02 06 00 ff 09 01 81 02 c0 85 0c 06 00 ff 09 0c 75 08 95 06 26 ff 00 b1 02 85 0b 09 0b 95 02 b1 02 85 11 09 11 b1 02 85 15 09 15 95 05 b1 02 85 18 09 18 95 0c b1 02 c0 05 0d 09 04 a1 01 85 03 06 00 ff 09 01 75 10 95 01 15 00 27 ff ff 00 00 81 02 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 03 0a 26 80 25 81 02 09 31 46 a1 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 03 0a 26 80 25 81 02 09 31 46 a1 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 54 95 01 75 08 81 02 09 56 75 20 95 01 27 ff ff ff 0f 81 02 85 04 09 55 75 08 95 01 25 0b b1 02 85 0a 06 00 ff 09 03 15 00 b1 02 85 1b 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0", 2052 + ) 2053 + 2054 + 2055 + class Testsharp_04dd_9681(BaseTest.TestWin8Multitouch): 2056 + def create_device(self): 2057 + return Digitizer( 2058 + "uhid test sharp_04dd_9681", 2059 + rdesc="06 00 ff 09 01 a1 01 75 08 26 ff 00 15 00 85 06 95 3f 09 01 91 02 85 05 95 3f 09 01 81 02 c0 05 0d 09 04 a1 01 85 81 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 03 75 08 09 51 95 01 81 02 05 01 65 11 55 0f 35 00 46 b0 01 26 80 07 75 10 09 30 81 02 46 f3 00 26 38 04 09 31 81 02 05 0d 09 48 09 49 26 ff 00 95 02 75 08 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 03 75 08 09 51 95 01 81 02 05 01 65 11 55 0f 35 00 46 b0 01 26 80 07 75 10 09 30 81 02 46 f3 00 26 38 04 09 31 81 02 05 0d 09 48 09 49 26 ff 00 95 02 75 08 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 03 75 08 09 51 95 01 81 02 05 01 65 11 55 0f 35 00 46 b0 01 26 80 07 75 10 09 30 81 02 46 f3 00 26 38 04 09 31 81 02 05 0d 09 48 09 49 26 ff 00 95 02 75 08 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 03 75 08 09 51 95 01 81 02 05 01 65 11 55 0f 35 00 46 b0 01 26 80 07 75 10 09 30 81 02 46 f3 00 26 38 04 09 31 81 02 05 0d 09 48 09 49 26 ff 00 95 02 75 08 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 03 75 08 09 51 95 01 81 02 05 01 65 11 55 0f 35 00 46 b0 01 26 80 07 75 10 09 30 81 02 46 f3 00 26 38 04 09 31 81 02 05 0d 09 48 09 49 26 ff 00 95 02 75 08 81 02 c0 05 0d 09 56 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 81 02 09 54 95 01 75 08 15 00 25 0a 81 02 85 84 09 55 b1 02 85 87 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 09 0e a1 01 85 83 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 09 01 a1 00 85 80 05 09 19 01 29 01 15 00 25 01 95 01 75 01 81 02 95 01 75 07 81 01 05 01 65 11 55 0f 09 30 26 80 07 35 00 46 66 00 75 10 95 01 81 02 09 31 26 38 04 35 00 46 4d 00 81 02 c0 c0", 2060 + ) 2061 + 2062 + 2063 + class Testsipodev_0603_0002(BaseTest.TestPTP): 2064 + def create_device(self): 2065 + return PTP( 2066 + "uhid test sipodev_0603_0002", 2067 + type="clickpad", 2068 + rdesc="05 01 09 02 a1 01 85 03 09 01 a1 00 05 09 19 01 29 02 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 15 80 25 7f 75 08 95 02 81 06 c0 c0 05 0d 09 05 a1 01 85 04 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 75 01 95 02 81 03 95 01 75 04 25 05 09 51 81 02 05 01 15 00 26 44 0a 75 0c 55 0e 65 11 09 30 35 00 46 ac 03 95 01 81 02 46 fe 01 26 34 05 75 0c 09 31 81 02 05 0d c0 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 09 54 25 0a 95 01 75 04 81 02 75 01 95 03 81 03 05 09 09 01 25 01 75 01 95 01 81 02 05 0d 85 0a 09 55 09 59 75 04 95 02 25 0f b1 02 85 0b 09 60 75 01 95 01 15 00 25 01 b1 02 95 07 b1 03 85 09 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 0e a1 01 85 06 09 22 a1 02 09 52 15 00 25 0a 75 08 95 01 b1 02 c0 09 22 a1 00 85 07 09 57 09 58 75 01 95 02 25 01 b1 02 95 06 b1 03 c0 c0 05 01 09 0c a1 01 85 08 15 00 25 01 09 c6 75 01 95 01 81 06 75 07 81 03 c0 05 01 09 80 a1 01 85 01 15 00 25 01 75 01 0a 81 00 0a 82 00 0a 83 00 95 03 81 06 95 05 81 01 c0 06 0c 00 09 01 a1 01 85 02 25 01 15 00 75 01 0a b5 00 0a b6 00 0a b7 00 0a cd 00 0a e2 00 0a a2 00 0a e9 00 0a ea 00 95 08 81 02 0a 83 01 0a 6f 00 0a 70 00 0a 88 01 0a 8a 01 0a 92 01 0a a8 02 0a 24 02 95 08 81 02 0a 21 02 0a 23 02 0a 96 01 0a 25 02 0a 26 02 0a 27 02 0a 23 02 0a b1 02 95 08 81 02 c0 06 00 ff 09 01 a1 01 85 05 15 00 26 ff 00 19 01 29 02 75 08 95 05 b1 02 c0", 2069 + ) 2070 + 2071 + 2072 + class Testsynaptics_06cb_1d10(BaseTest.TestWin8Multitouch): 2073 + def create_device(self): 2074 + return Digitizer( 2075 + "uhid test synaptics_06cb_1d10", 2076 + rdesc="05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 75 08 95 02 15 81 25 7f 35 81 45 7f 55 0e 65 11 81 06 c0 c0 05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 03 75 08 09 51 15 01 26 ff 00 95 01 81 42 05 01 15 00 26 3c 0c 75 10 55 0e 65 11 09 30 35 12 46 2a 0c 81 02 09 31 15 00 26 f1 06 35 12 46 df 06 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 03 75 08 09 51 15 01 26 ff 00 95 01 81 42 05 01 15 00 26 3c 0c 75 10 55 0e 65 11 09 30 35 12 46 2a 0c 81 02 09 31 15 00 26 f1 06 35 12 46 df 06 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 03 75 08 09 51 15 01 26 ff 00 95 01 81 42 05 01 15 00 26 3c 0c 75 10 55 0e 65 11 09 30 35 12 46 2a 0c 81 02 09 31 15 00 26 f1 06 35 12 46 df 06 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 03 75 08 09 51 15 01 26 ff 00 95 01 81 42 05 01 15 00 26 3c 0c 75 10 55 0e 65 11 09 30 35 12 46 2a 0c 81 02 09 31 15 00 26 f1 06 35 12 46 df 06 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 03 75 08 09 51 15 01 26 ff 00 95 01 81 42 05 01 15 00 26 3c 0c 75 10 55 0e 65 11 09 30 35 12 46 2a 0c 81 02 09 31 15 00 26 f1 06 35 12 46 df 06 81 02 c0 05 0d 05 0d 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 09 54 95 01 75 08 15 00 25 0f 81 02 85 08 09 55 b1 03 85 07 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 06 00 ff 09 01 a1 01 85 09 09 02 15 00 26 ff 00 75 08 95 3f 91 02 85 0a 09 03 15 00 26 ff 00 75 08 95 05 91 02 85 0b 09 04 15 00 26 ff 00 75 08 95 3d 81 02 85 0c 09 05 15 00 26 ff 00 75 08 95 01 81 02 85 0f 09 06 15 00 26 ff 00 75 08 95 01 b1 02 c0", 2077 + ) 2078 + 2079 + 2080 + class Testsynaptics_06cb_ce08(BaseTest.TestPTP): 2081 + def create_device(self): 2082 + return PTP( 2083 + "uhid test synaptics_06cb_ce08", 2084 + max_contacts=5, 2085 + physical="Vendor Usage 1", 2086 + input_info=(BusType.I2C, 0x06CB, 0xCE08), 2087 + rdesc="05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 01 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0 05 01 09 02 a1 01 85 18 09 01 a1 00 05 09 19 01 29 03 46 00 00 15 00 25 01 75 01 95 03 81 02 95 05 81 01 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0 06 00 ff 09 02 a1 01 85 20 09 01 a1 00 09 03 15 00 26 ff 00 35 00 46 ff 00 75 08 95 05 81 02 c0 c0 05 0d 09 05 a1 01 85 03 05 0d 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 75 01 95 03 81 03 05 01 15 00 26 f8 04 75 10 55 0e 65 11 09 30 35 00 46 24 04 95 01 81 02 46 30 02 26 a0 02 09 31 81 02 c0 05 0d 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 75 01 95 03 81 03 05 01 15 00 26 f8 04 75 10 55 0e 65 11 09 30 35 00 46 24 04 95 01 81 02 46 30 02 26 a0 02 09 31 81 02 c0 05 0d 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 75 01 95 03 81 03 05 01 15 00 26 f8 04 75 10 55 0e 65 11 09 30 35 00 46 24 04 95 01 81 02 46 30 02 26 a0 02 09 31 81 02 c0 05 0d 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 75 01 95 03 81 03 05 01 15 00 26 f8 04 75 10 55 0e 65 11 09 30 35 00 46 24 04 95 01 81 02 46 30 02 26 a0 02 09 31 81 02 c0 05 0d 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 75 01 95 03 81 03 05 01 15 00 26 f8 04 75 10 55 0e 65 11 09 30 35 00 46 24 04 95 01 81 02 46 30 02 26 a0 02 09 31 81 02 c0 05 0d 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 09 54 25 7f 95 01 75 08 81 02 05 09 09 01 25 01 75 01 95 01 81 02 95 07 81 03 05 0d 85 08 09 55 09 59 75 04 95 02 25 0f b1 02 85 0d 09 60 75 01 95 01 15 00 25 01 b1 02 95 07 b1 03 85 07 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 0e a1 01 85 04 09 22 a1 02 09 52 15 00 25 0a 75 08 95 01 b1 02 c0 09 22 a1 00 85 06 09 57 09 58 75 01 95 02 25 01 b1 02 95 06 b1 03 c0 c0 06 00 ff 09 01 a1 01 85 09 09 02 15 00 26 ff 00 75 08 95 14 91 02 85 0a 09 03 15 00 26 ff 00 75 08 95 14 91 02 85 0b 09 04 15 00 26 ff 00 75 08 95 45 81 02 85 0c 09 05 15 00 26 ff 00 75 08 95 45 81 02 85 0f 09 06 15 00 26 ff 00 75 08 95 03 b1 02 85 0e 09 07 15 00 26 ff 00 75 08 95 01 b1 02 c0", 2088 + )
+342
tools/testing/selftests/hid/tests/test_sony.py
··· 1 + #!/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # -*- coding: utf-8 -*- 4 + # 5 + # Copyright (c) 2020 Benjamin Tissoires <benjamin.tissoires@gmail.com> 6 + # Copyright (c) 2020 Red Hat, Inc. 7 + # 8 + 9 + from .base import application_matches 10 + from .test_gamepad import BaseTest 11 + from hidtools.device.sony_gamepad import ( 12 + PS3Controller, 13 + PS4ControllerBluetooth, 14 + PS4ControllerUSB, 15 + PS5ControllerBluetooth, 16 + PS5ControllerUSB, 17 + PSTouchPoint, 18 + ) 19 + from hidtools.util import BusType 20 + 21 + import libevdev 22 + import logging 23 + import pytest 24 + 25 + logger = logging.getLogger("hidtools.test.sony") 26 + 27 + PS3_MODULE = ("sony", "hid_sony") 28 + PS4_MODULE = ("playstation", "hid_playstation") 29 + PS5_MODULE = ("playstation", "hid_playstation") 30 + 31 + 32 + class SonyBaseTest: 33 + class SonyTest(BaseTest.TestGamepad): 34 + pass 35 + 36 + class SonyPS4ControllerTest(SonyTest): 37 + kernel_modules = [PS4_MODULE] 38 + 39 + def test_accelerometer(self): 40 + uhdev = self.uhdev 41 + evdev = uhdev.get_evdev("Accelerometer") 42 + 43 + for x in range(-32000, 32000, 4000): 44 + r = uhdev.event(accel=(x, None, None)) 45 + events = uhdev.next_sync_events("Accelerometer") 46 + self.debug_reports(r, uhdev, events) 47 + 48 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_X) in events 49 + value = evdev.value[libevdev.EV_ABS.ABS_X] 50 + # Check against range due to small loss in precision due 51 + # to inverse calibration, followed by calibration by hid-sony. 52 + assert x - 1 <= value <= x + 1 53 + 54 + for y in range(-32000, 32000, 4000): 55 + r = uhdev.event(accel=(None, y, None)) 56 + events = uhdev.next_sync_events("Accelerometer") 57 + self.debug_reports(r, uhdev, events) 58 + 59 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_Y) in events 60 + value = evdev.value[libevdev.EV_ABS.ABS_Y] 61 + assert y - 1 <= value <= y + 1 62 + 63 + for z in range(-32000, 32000, 4000): 64 + r = uhdev.event(accel=(None, None, z)) 65 + events = uhdev.next_sync_events("Accelerometer") 66 + self.debug_reports(r, uhdev, events) 67 + 68 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_Z) in events 69 + value = evdev.value[libevdev.EV_ABS.ABS_Z] 70 + assert z - 1 <= value <= z + 1 71 + 72 + def test_gyroscope(self): 73 + uhdev = self.uhdev 74 + evdev = uhdev.get_evdev("Accelerometer") 75 + 76 + for rx in range(-2000000, 2000000, 200000): 77 + r = uhdev.event(gyro=(rx, None, None)) 78 + events = uhdev.next_sync_events("Accelerometer") 79 + self.debug_reports(r, uhdev, events) 80 + 81 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_RX) in events 82 + value = evdev.value[libevdev.EV_ABS.ABS_RX] 83 + # Sensor internal value is 16-bit, but calibrated is 22-bit, so 84 + # 6-bit (64) difference, so allow a range of +/- 64. 85 + assert rx - 64 <= value <= rx + 64 86 + 87 + for ry in range(-2000000, 2000000, 200000): 88 + r = uhdev.event(gyro=(None, ry, None)) 89 + events = uhdev.next_sync_events("Accelerometer") 90 + self.debug_reports(r, uhdev, events) 91 + 92 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_RY) in events 93 + value = evdev.value[libevdev.EV_ABS.ABS_RY] 94 + assert ry - 64 <= value <= ry + 64 95 + 96 + for rz in range(-2000000, 2000000, 200000): 97 + r = uhdev.event(gyro=(None, None, rz)) 98 + events = uhdev.next_sync_events("Accelerometer") 99 + self.debug_reports(r, uhdev, events) 100 + 101 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_RZ) in events 102 + value = evdev.value[libevdev.EV_ABS.ABS_RZ] 103 + assert rz - 64 <= value <= rz + 64 104 + 105 + def test_battery(self): 106 + uhdev = self.uhdev 107 + 108 + assert uhdev.power_supply_class is not None 109 + 110 + # DS4 capacity levels are in increments of 10. 111 + # Battery is never below 5%. 112 + for i in range(5, 105, 10): 113 + uhdev.battery.capacity = i 114 + uhdev.event() 115 + assert uhdev.power_supply_class.capacity == i 116 + 117 + # Discharging tests only make sense for BlueTooth. 118 + if uhdev.bus == BusType.BLUETOOTH: 119 + uhdev.battery.cable_connected = False 120 + uhdev.battery.capacity = 45 121 + uhdev.event() 122 + assert uhdev.power_supply_class.status == "Discharging" 123 + 124 + uhdev.battery.cable_connected = True 125 + uhdev.battery.capacity = 5 126 + uhdev.event() 127 + assert uhdev.power_supply_class.status == "Charging" 128 + 129 + uhdev.battery.capacity = 100 130 + uhdev.event() 131 + assert uhdev.power_supply_class.status == "Charging" 132 + 133 + uhdev.battery.full = True 134 + uhdev.event() 135 + assert uhdev.power_supply_class.status == "Full" 136 + 137 + def test_mt_single_touch(self): 138 + """send a single touch in the first slot of the device, 139 + and release it.""" 140 + uhdev = self.uhdev 141 + evdev = uhdev.get_evdev("Touch Pad") 142 + 143 + t0 = PSTouchPoint(1, 50, 100) 144 + r = uhdev.event(touch=[t0]) 145 + events = uhdev.next_sync_events("Touch Pad") 146 + self.debug_reports(r, uhdev, events) 147 + 148 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events 149 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0 150 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_X] == 50 151 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 100 152 + 153 + t0.tipswitch = False 154 + r = uhdev.event(touch=[t0]) 155 + events = uhdev.next_sync_events("Touch Pad") 156 + self.debug_reports(r, uhdev, events) 157 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 0) in events 158 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 159 + 160 + def test_mt_dual_touch(self): 161 + """Send 2 touches in the first 2 slots. 162 + Make sure the kernel sees this as a dual touch. 163 + Release and check 164 + 165 + Note: PTP will send here BTN_DOUBLETAP emulation""" 166 + uhdev = self.uhdev 167 + evdev = uhdev.get_evdev("Touch Pad") 168 + 169 + t0 = PSTouchPoint(1, 50, 100) 170 + t1 = PSTouchPoint(2, 150, 200) 171 + 172 + r = uhdev.event(touch=[t0]) 173 + events = uhdev.next_sync_events("Touch Pad") 174 + self.debug_reports(r, uhdev, events) 175 + 176 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events 177 + assert evdev.value[libevdev.EV_KEY.BTN_TOUCH] == 1 178 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0 179 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_X] == 50 180 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 100 181 + assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 182 + 183 + r = uhdev.event(touch=[t0, t1]) 184 + events = uhdev.next_sync_events("Touch Pad") 185 + self.debug_reports(r, uhdev, events) 186 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH) not in events 187 + assert evdev.value[libevdev.EV_KEY.BTN_TOUCH] == 1 188 + assert ( 189 + libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_X, 5) not in events 190 + ) 191 + assert ( 192 + libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_Y, 10) not in events 193 + ) 194 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0 195 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_X] == 50 196 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 100 197 + assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 1 198 + assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_POSITION_X] == 150 199 + assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 200 200 + 201 + t0.tipswitch = False 202 + r = uhdev.event(touch=[t0, t1]) 203 + events = uhdev.next_sync_events("Touch Pad") 204 + self.debug_reports(r, uhdev, events) 205 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 206 + assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 1 207 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_X) not in events 208 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_Y) not in events 209 + 210 + t1.tipswitch = False 211 + r = uhdev.event(touch=[t1]) 212 + 213 + events = uhdev.next_sync_events("Touch Pad") 214 + self.debug_reports(r, uhdev, events) 215 + assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 216 + assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1 217 + 218 + 219 + class TestPS3Controller(SonyBaseTest.SonyTest): 220 + kernel_modules = [PS3_MODULE] 221 + 222 + def create_device(self): 223 + controller = PS3Controller() 224 + controller.application_matches = application_matches 225 + return controller 226 + 227 + @pytest.fixture(autouse=True) 228 + def start_controller(self): 229 + # emulate a 'PS' button press to tell the kernel we are ready to accept events 230 + self.assert_button(17) 231 + 232 + # drain any remaining udev events 233 + while self.uhdev.dispatch(10): 234 + pass 235 + 236 + def test_led(self): 237 + for k, v in self.uhdev.led_classes.items(): 238 + # the kernel might have set a LED for us 239 + logger.info(f"{k}: {v.brightness}") 240 + 241 + idx = int(k[-1]) - 1 242 + assert self.uhdev.hw_leds.get_led(idx)[0] == bool(v.brightness) 243 + 244 + v.brightness = 0 245 + self.uhdev.dispatch(10) 246 + assert self.uhdev.hw_leds.get_led(idx)[0] is False 247 + 248 + v.brightness = v.max_brightness 249 + self.uhdev.dispatch(10) 250 + assert self.uhdev.hw_leds.get_led(idx)[0] 251 + 252 + 253 + class CalibratedPS4Controller(object): 254 + # DS4 reports uncalibrated sensor data. Calibration coefficients 255 + # can be retrieved using a feature report (0x2 USB / 0x5 BT). 256 + # The values below are the processed calibration values for the 257 + # DS4s matching the feature reports of PS4ControllerBluetooth/USB 258 + # as dumped from hid-sony 'ds4_get_calibration_data'. 259 + # 260 + # Note we duplicate those values here in case the kernel changes them 261 + # so we can have tests passing even if hid-tools doesn't have the 262 + # correct values. 263 + accelerometer_calibration_data = { 264 + "x": {"bias": -73, "numer": 16384, "denom": 16472}, 265 + "y": {"bias": -352, "numer": 16384, "denom": 16344}, 266 + "z": {"bias": 81, "numer": 16384, "denom": 16319}, 267 + } 268 + gyroscope_calibration_data = { 269 + "x": {"bias": 0, "numer": 1105920, "denom": 17827}, 270 + "y": {"bias": 0, "numer": 1105920, "denom": 17777}, 271 + "z": {"bias": 0, "numer": 1105920, "denom": 17748}, 272 + } 273 + 274 + 275 + class CalibratedPS4ControllerBluetooth(CalibratedPS4Controller, PS4ControllerBluetooth): 276 + pass 277 + 278 + 279 + class TestPS4ControllerBluetooth(SonyBaseTest.SonyPS4ControllerTest): 280 + def create_device(self): 281 + controller = CalibratedPS4ControllerBluetooth() 282 + controller.application_matches = application_matches 283 + return controller 284 + 285 + 286 + class CalibratedPS4ControllerUSB(CalibratedPS4Controller, PS4ControllerUSB): 287 + pass 288 + 289 + 290 + class TestPS4ControllerUSB(SonyBaseTest.SonyPS4ControllerTest): 291 + def create_device(self): 292 + controller = CalibratedPS4ControllerUSB() 293 + controller.application_matches = application_matches 294 + return controller 295 + 296 + 297 + class CalibratedPS5Controller(object): 298 + # DualSense reports uncalibrated sensor data. Calibration coefficients 299 + # can be retrieved using feature report 0x09. 300 + # The values below are the processed calibration values for the 301 + # DualSene matching the feature reports of PS5ControllerBluetooth/USB 302 + # as dumped from hid-playstation 'dualsense_get_calibration_data'. 303 + # 304 + # Note we duplicate those values here in case the kernel changes them 305 + # so we can have tests passing even if hid-tools doesn't have the 306 + # correct values. 307 + accelerometer_calibration_data = { 308 + "x": {"bias": 0, "numer": 16384, "denom": 16374}, 309 + "y": {"bias": -114, "numer": 16384, "denom": 16362}, 310 + "z": {"bias": 2, "numer": 16384, "denom": 16395}, 311 + } 312 + gyroscope_calibration_data = { 313 + "x": {"bias": 0, "numer": 1105920, "denom": 17727}, 314 + "y": {"bias": 0, "numer": 1105920, "denom": 17728}, 315 + "z": {"bias": 0, "numer": 1105920, "denom": 17769}, 316 + } 317 + 318 + 319 + class CalibratedPS5ControllerBluetooth(CalibratedPS5Controller, PS5ControllerBluetooth): 320 + pass 321 + 322 + 323 + class TestPS5ControllerBluetooth(SonyBaseTest.SonyPS4ControllerTest): 324 + kernel_modules = [PS5_MODULE] 325 + 326 + def create_device(self): 327 + controller = CalibratedPS5ControllerBluetooth() 328 + controller.application_matches = application_matches 329 + return controller 330 + 331 + 332 + class CalibratedPS5ControllerUSB(CalibratedPS5Controller, PS5ControllerUSB): 333 + pass 334 + 335 + 336 + class TestPS5ControllerUSB(SonyBaseTest.SonyPS4ControllerTest): 337 + kernel_modules = [PS5_MODULE] 338 + 339 + def create_device(self): 340 + controller = CalibratedPS5ControllerUSB() 341 + controller.application_matches = application_matches 342 + return controller
+872
tools/testing/selftests/hid/tests/test_tablet.py
··· 1 + #!/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # -*- coding: utf-8 -*- 4 + # 5 + # Copyright (c) 2021 Benjamin Tissoires <benjamin.tissoires@gmail.com> 6 + # Copyright (c) 2021 Red Hat, Inc. 7 + # 8 + 9 + from . import base 10 + import copy 11 + from enum import Enum 12 + from hidtools.util import BusType 13 + import libevdev 14 + import logging 15 + import pytest 16 + from typing import Dict, Tuple 17 + 18 + logger = logging.getLogger("hidtools.test.tablet") 19 + 20 + 21 + class PenState(Enum): 22 + """Pen states according to Microsoft reference: 23 + https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states 24 + """ 25 + 26 + PEN_IS_OUT_OF_RANGE = (False, None) 27 + PEN_IS_IN_RANGE = (False, libevdev.EV_KEY.BTN_TOOL_PEN) 28 + PEN_IS_IN_CONTACT = (True, libevdev.EV_KEY.BTN_TOOL_PEN) 29 + PEN_IS_IN_RANGE_WITH_ERASING_INTENT = (False, libevdev.EV_KEY.BTN_TOOL_RUBBER) 30 + PEN_IS_ERASING = (True, libevdev.EV_KEY.BTN_TOOL_RUBBER) 31 + 32 + def __init__(self, touch, tool): 33 + self.touch = touch 34 + self.tool = tool 35 + 36 + @classmethod 37 + def from_evdev(cls, evdev) -> "PenState": 38 + touch = bool(evdev.value[libevdev.EV_KEY.BTN_TOUCH]) 39 + tool = None 40 + if ( 41 + evdev.value[libevdev.EV_KEY.BTN_TOOL_RUBBER] 42 + and not evdev.value[libevdev.EV_KEY.BTN_TOOL_PEN] 43 + ): 44 + tool = libevdev.EV_KEY.BTN_TOOL_RUBBER 45 + elif ( 46 + evdev.value[libevdev.EV_KEY.BTN_TOOL_PEN] 47 + and not evdev.value[libevdev.EV_KEY.BTN_TOOL_RUBBER] 48 + ): 49 + tool = libevdev.EV_KEY.BTN_TOOL_PEN 50 + elif ( 51 + evdev.value[libevdev.EV_KEY.BTN_TOOL_PEN] 52 + or evdev.value[libevdev.EV_KEY.BTN_TOOL_RUBBER] 53 + ): 54 + raise ValueError("2 tools are not allowed") 55 + 56 + return cls((touch, tool)) 57 + 58 + def apply(self, events) -> "PenState": 59 + if libevdev.EV_SYN.SYN_REPORT in events: 60 + raise ValueError("EV_SYN is in the event sequence") 61 + touch = self.touch 62 + touch_found = False 63 + tool = self.tool 64 + tool_found = False 65 + 66 + for ev in events: 67 + if ev == libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH): 68 + if touch_found: 69 + raise ValueError(f"duplicated BTN_TOUCH in {events}") 70 + touch_found = True 71 + touch = bool(ev.value) 72 + elif ev in ( 73 + libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN), 74 + libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_RUBBER), 75 + ): 76 + if tool_found: 77 + raise ValueError(f"duplicated BTN_TOOL_* in {events}") 78 + tool_found = True 79 + if ev.value: 80 + tool = ev.code 81 + else: 82 + tool = None 83 + 84 + new_state = PenState((touch, tool)) 85 + assert ( 86 + new_state in self.valid_transitions() 87 + ), f"moving from {self} to {new_state} is forbidden" 88 + 89 + return new_state 90 + 91 + def valid_transitions(self) -> Tuple["PenState", ...]: 92 + """Following the state machine in the URL above, with a couple of addition 93 + for skipping the in-range state, due to historical reasons. 94 + 95 + Note that those transitions are from the evdev point of view, not HID""" 96 + if self == PenState.PEN_IS_OUT_OF_RANGE: 97 + return ( 98 + PenState.PEN_IS_OUT_OF_RANGE, 99 + PenState.PEN_IS_IN_RANGE, 100 + PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 101 + PenState.PEN_IS_IN_CONTACT, 102 + PenState.PEN_IS_ERASING, 103 + ) 104 + 105 + if self == PenState.PEN_IS_IN_RANGE: 106 + return ( 107 + PenState.PEN_IS_IN_RANGE, 108 + PenState.PEN_IS_OUT_OF_RANGE, 109 + PenState.PEN_IS_IN_CONTACT, 110 + ) 111 + 112 + if self == PenState.PEN_IS_IN_CONTACT: 113 + return ( 114 + PenState.PEN_IS_IN_CONTACT, 115 + PenState.PEN_IS_IN_RANGE, 116 + PenState.PEN_IS_OUT_OF_RANGE, 117 + ) 118 + 119 + if self == PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT: 120 + return ( 121 + PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 122 + PenState.PEN_IS_OUT_OF_RANGE, 123 + PenState.PEN_IS_ERASING, 124 + ) 125 + 126 + if self == PenState.PEN_IS_ERASING: 127 + return ( 128 + PenState.PEN_IS_ERASING, 129 + PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 130 + PenState.PEN_IS_OUT_OF_RANGE, 131 + ) 132 + 133 + return tuple() 134 + 135 + 136 + class Data(object): 137 + pass 138 + 139 + 140 + class Pen(object): 141 + def __init__(self, x, y): 142 + self.x = x 143 + self.y = y 144 + self.tipswitch = False 145 + self.tippressure = 15 146 + self.azimuth = 0 147 + self.inrange = False 148 + self.width = 10 149 + self.height = 10 150 + self.barrelswitch = False 151 + self.invert = False 152 + self.eraser = False 153 + self.x_tilt = 0 154 + self.y_tilt = 0 155 + self.twist = 0 156 + self._old_values = None 157 + self.current_state = None 158 + 159 + def _restore(self): 160 + if self._old_values is not None: 161 + for i in [ 162 + "x", 163 + "y", 164 + "tippressure", 165 + "azimuth", 166 + "width", 167 + "height", 168 + "twist", 169 + "x_tilt", 170 + "y_tilt", 171 + ]: 172 + setattr(self, i, getattr(self._old_values, i)) 173 + 174 + def move_to(self, state): 175 + # fill in the previous values 176 + if self.current_state == PenState.PEN_IS_OUT_OF_RANGE: 177 + self._restore() 178 + 179 + print(f"\n *** pen is moving to {state} ***") 180 + 181 + if state == PenState.PEN_IS_OUT_OF_RANGE: 182 + self._old_values = copy.copy(self) 183 + self.x = 0 184 + self.y = 0 185 + self.tipswitch = False 186 + self.tippressure = 0 187 + self.azimuth = 0 188 + self.inrange = False 189 + self.width = 0 190 + self.height = 0 191 + self.invert = False 192 + self.eraser = False 193 + self.x_tilt = 0 194 + self.y_tilt = 0 195 + self.twist = 0 196 + elif state == PenState.PEN_IS_IN_RANGE: 197 + self.tipswitch = False 198 + self.inrange = True 199 + self.invert = False 200 + self.eraser = False 201 + elif state == PenState.PEN_IS_IN_CONTACT: 202 + self.tipswitch = True 203 + self.inrange = True 204 + self.invert = False 205 + self.eraser = False 206 + elif state == PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT: 207 + self.tipswitch = False 208 + self.inrange = True 209 + self.invert = True 210 + self.eraser = False 211 + elif state == PenState.PEN_IS_ERASING: 212 + self.tipswitch = False 213 + self.inrange = True 214 + self.invert = True 215 + self.eraser = True 216 + 217 + self.current_state = state 218 + 219 + def __assert_axis(self, evdev, axis, value): 220 + if ( 221 + axis == libevdev.EV_KEY.BTN_TOOL_RUBBER 222 + and evdev.value[libevdev.EV_KEY.BTN_TOOL_RUBBER] is None 223 + ): 224 + return 225 + 226 + assert ( 227 + evdev.value[axis] == value 228 + ), f"assert evdev.value[{axis}] ({evdev.value[axis]}) != {value}" 229 + 230 + def assert_expected_input_events(self, evdev): 231 + assert evdev.value[libevdev.EV_ABS.ABS_X] == self.x 232 + assert evdev.value[libevdev.EV_ABS.ABS_Y] == self.y 233 + assert self.current_state == PenState.from_evdev(evdev) 234 + 235 + @staticmethod 236 + def legal_transitions() -> Dict[str, Tuple[PenState, ...]]: 237 + """This is the first half of the Windows Pen Implementation state machine: 238 + we don't have Invert nor Erase bits, so just move in/out-of-range or proximity. 239 + https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states 240 + """ 241 + return { 242 + "in-range": (PenState.PEN_IS_IN_RANGE,), 243 + "in-range -> out-of-range": ( 244 + PenState.PEN_IS_IN_RANGE, 245 + PenState.PEN_IS_OUT_OF_RANGE, 246 + ), 247 + "in-range -> touch": (PenState.PEN_IS_IN_RANGE, PenState.PEN_IS_IN_CONTACT), 248 + "in-range -> touch -> release": ( 249 + PenState.PEN_IS_IN_RANGE, 250 + PenState.PEN_IS_IN_CONTACT, 251 + PenState.PEN_IS_IN_RANGE, 252 + ), 253 + "in-range -> touch -> release -> out-of-range": ( 254 + PenState.PEN_IS_IN_RANGE, 255 + PenState.PEN_IS_IN_CONTACT, 256 + PenState.PEN_IS_IN_RANGE, 257 + PenState.PEN_IS_OUT_OF_RANGE, 258 + ), 259 + } 260 + 261 + @staticmethod 262 + def legal_transitions_with_invert() -> Dict[str, Tuple[PenState, ...]]: 263 + """This is the second half of the Windows Pen Implementation state machine: 264 + we now have Invert and Erase bits, so move in/out or proximity with the intend 265 + to erase. 266 + https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states 267 + """ 268 + return { 269 + "hover-erasing": (PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT,), 270 + "hover-erasing -> out-of-range": ( 271 + PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 272 + PenState.PEN_IS_OUT_OF_RANGE, 273 + ), 274 + "hover-erasing -> erase": ( 275 + PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 276 + PenState.PEN_IS_ERASING, 277 + ), 278 + "hover-erasing -> erase -> release": ( 279 + PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 280 + PenState.PEN_IS_ERASING, 281 + PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 282 + ), 283 + "hover-erasing -> erase -> release -> out-of-range": ( 284 + PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 285 + PenState.PEN_IS_ERASING, 286 + PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 287 + PenState.PEN_IS_OUT_OF_RANGE, 288 + ), 289 + "hover-erasing -> in-range": ( 290 + PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 291 + PenState.PEN_IS_IN_RANGE, 292 + ), 293 + "in-range -> hover-erasing": ( 294 + PenState.PEN_IS_IN_RANGE, 295 + PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 296 + ), 297 + } 298 + 299 + @staticmethod 300 + def tolerated_transitions() -> Dict[str, Tuple[PenState, ...]]: 301 + """This is not adhering to the Windows Pen Implementation state machine 302 + but we should expect the kernel to behave properly, mostly for historical 303 + reasons.""" 304 + return { 305 + "direct-in-contact": (PenState.PEN_IS_IN_CONTACT,), 306 + "direct-in-contact -> out-of-range": ( 307 + PenState.PEN_IS_IN_CONTACT, 308 + PenState.PEN_IS_OUT_OF_RANGE, 309 + ), 310 + } 311 + 312 + @staticmethod 313 + def tolerated_transitions_with_invert() -> Dict[str, Tuple[PenState, ...]]: 314 + """This is the second half of the Windows Pen Implementation state machine: 315 + we now have Invert and Erase bits, so move in/out or proximity with the intend 316 + to erase. 317 + https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states 318 + """ 319 + return { 320 + "direct-erase": (PenState.PEN_IS_ERASING,), 321 + "direct-erase -> out-of-range": ( 322 + PenState.PEN_IS_ERASING, 323 + PenState.PEN_IS_OUT_OF_RANGE, 324 + ), 325 + } 326 + 327 + @staticmethod 328 + def broken_transitions() -> Dict[str, Tuple[PenState, ...]]: 329 + """Those tests are definitely not part of the Windows specification. 330 + However, a half broken device might export those transitions. 331 + For example, a pen that has the eraser button might wobble between 332 + touching and erasing if the tablet doesn't enforce the Windows 333 + state machine.""" 334 + return { 335 + "in-range -> touch -> erase -> hover-erase": ( 336 + PenState.PEN_IS_IN_RANGE, 337 + PenState.PEN_IS_IN_CONTACT, 338 + PenState.PEN_IS_ERASING, 339 + PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 340 + ), 341 + "in-range -> erase -> hover-erase": ( 342 + PenState.PEN_IS_IN_RANGE, 343 + PenState.PEN_IS_ERASING, 344 + PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 345 + ), 346 + "hover-erase -> erase -> touch -> in-range": ( 347 + PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 348 + PenState.PEN_IS_ERASING, 349 + PenState.PEN_IS_IN_CONTACT, 350 + PenState.PEN_IS_IN_RANGE, 351 + ), 352 + "hover-erase -> touch -> in-range": ( 353 + PenState.PEN_IS_IN_RANGE_WITH_ERASING_INTENT, 354 + PenState.PEN_IS_IN_CONTACT, 355 + PenState.PEN_IS_IN_RANGE, 356 + ), 357 + "touch -> erase -> touch -> erase": ( 358 + PenState.PEN_IS_IN_CONTACT, 359 + PenState.PEN_IS_ERASING, 360 + PenState.PEN_IS_IN_CONTACT, 361 + PenState.PEN_IS_ERASING, 362 + ), 363 + } 364 + 365 + 366 + class PenDigitizer(base.UHIDTestDevice): 367 + def __init__( 368 + self, 369 + name, 370 + rdesc_str=None, 371 + rdesc=None, 372 + application="Pen", 373 + physical="Stylus", 374 + input_info=(BusType.USB, 1, 2), 375 + evdev_name_suffix=None, 376 + ): 377 + super().__init__(name, application, rdesc_str, rdesc, input_info) 378 + self.physical = physical 379 + self.cur_application = application 380 + if evdev_name_suffix is not None: 381 + self.name += evdev_name_suffix 382 + 383 + self.fields = [] 384 + for r in self.parsed_rdesc.input_reports.values(): 385 + if r.application_name == self.application: 386 + physicals = [f.physical_name for f in r] 387 + if self.physical not in physicals and None not in physicals: 388 + continue 389 + self.fields = [f.usage_name for f in r] 390 + 391 + def event(self, pen): 392 + rs = [] 393 + r = self.create_report(application=self.cur_application, data=pen) 394 + self.call_input_event(r) 395 + rs.append(r) 396 + return rs 397 + 398 + def get_report(self, req, rnum, rtype): 399 + if rtype != self.UHID_FEATURE_REPORT: 400 + return (1, []) 401 + 402 + rdesc = None 403 + for v in self.parsed_rdesc.feature_reports.values(): 404 + if v.report_ID == rnum: 405 + rdesc = v 406 + 407 + if rdesc is None: 408 + return (1, []) 409 + 410 + return (1, []) 411 + 412 + def set_report(self, req, rnum, rtype, data): 413 + if rtype != self.UHID_FEATURE_REPORT: 414 + return 1 415 + 416 + rdesc = None 417 + for v in self.parsed_rdesc.feature_reports.values(): 418 + if v.report_ID == rnum: 419 + rdesc = v 420 + 421 + if rdesc is None: 422 + return 1 423 + 424 + return 1 425 + 426 + 427 + class BaseTest: 428 + class TestTablet(base.BaseTestCase.TestUhid): 429 + def create_device(self): 430 + raise Exception("please reimplement me in subclasses") 431 + 432 + def post(self, uhdev, pen): 433 + r = uhdev.event(pen) 434 + events = uhdev.next_sync_events() 435 + self.debug_reports(r, uhdev, events) 436 + return events 437 + 438 + def validate_transitions(self, from_state, pen, evdev, events): 439 + # check that the final state is correct 440 + pen.assert_expected_input_events(evdev) 441 + 442 + # check that the transitions are valid 443 + sync_events = [] 444 + while libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT) in events: 445 + # split the first EV_SYN from the list 446 + idx = events.index(libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT)) 447 + sync_events = events[:idx] 448 + events = events[idx + 1 :] 449 + 450 + # now check for a valid transition 451 + from_state = from_state.apply(sync_events) 452 + 453 + if events: 454 + from_state = from_state.apply(sync_events) 455 + 456 + def _test_states(self, state_list, scribble): 457 + """Internal method to test against a list of 458 + transition between states. 459 + state_list is a list of PenState objects 460 + scribble is a boolean which tells if we need 461 + to wobble a little the X,Y coordinates of the pen 462 + between each state transition.""" 463 + uhdev = self.uhdev 464 + evdev = uhdev.get_evdev() 465 + 466 + cur_state = PenState.PEN_IS_OUT_OF_RANGE 467 + 468 + p = Pen(50, 60) 469 + p.move_to(PenState.PEN_IS_OUT_OF_RANGE) 470 + events = self.post(uhdev, p) 471 + self.validate_transitions(cur_state, p, evdev, events) 472 + 473 + cur_state = p.current_state 474 + 475 + for state in state_list: 476 + if scribble and cur_state != PenState.PEN_IS_OUT_OF_RANGE: 477 + p.x += 1 478 + p.y -= 1 479 + events = self.post(uhdev, p) 480 + self.validate_transitions(cur_state, p, evdev, events) 481 + assert len(events) >= 3 # X, Y, SYN 482 + p.move_to(state) 483 + if scribble and state != PenState.PEN_IS_OUT_OF_RANGE: 484 + p.x += 1 485 + p.y -= 1 486 + events = self.post(uhdev, p) 487 + self.validate_transitions(cur_state, p, evdev, events) 488 + cur_state = p.current_state 489 + 490 + @pytest.mark.parametrize("scribble", [True, False], ids=["scribble", "static"]) 491 + @pytest.mark.parametrize( 492 + "state_list", 493 + [pytest.param(v, id=k) for k, v in Pen.legal_transitions().items()], 494 + ) 495 + def test_valid_pen_states(self, state_list, scribble): 496 + """This is the first half of the Windows Pen Implementation state machine: 497 + we don't have Invert nor Erase bits, so just move in/out-of-range or proximity. 498 + https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states 499 + """ 500 + self._test_states(state_list, scribble) 501 + 502 + @pytest.mark.parametrize("scribble", [True, False], ids=["scribble", "static"]) 503 + @pytest.mark.parametrize( 504 + "state_list", 505 + [pytest.param(v, id=k) for k, v in Pen.tolerated_transitions().items()], 506 + ) 507 + def test_tolerated_pen_states(self, state_list, scribble): 508 + """This is not adhering to the Windows Pen Implementation state machine 509 + but we should expect the kernel to behave properly, mostly for historical 510 + reasons.""" 511 + self._test_states(state_list, scribble) 512 + 513 + @pytest.mark.skip_if_uhdev( 514 + lambda uhdev: "Invert" not in uhdev.fields, 515 + "Device not compatible, missing Invert usage", 516 + ) 517 + @pytest.mark.parametrize("scribble", [True, False], ids=["scribble", "static"]) 518 + @pytest.mark.parametrize( 519 + "state_list", 520 + [ 521 + pytest.param(v, id=k) 522 + for k, v in Pen.legal_transitions_with_invert().items() 523 + ], 524 + ) 525 + def test_valid_invert_pen_states(self, state_list, scribble): 526 + """This is the second half of the Windows Pen Implementation state machine: 527 + we now have Invert and Erase bits, so move in/out or proximity with the intend 528 + to erase. 529 + https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states 530 + """ 531 + self._test_states(state_list, scribble) 532 + 533 + @pytest.mark.skip_if_uhdev( 534 + lambda uhdev: "Invert" not in uhdev.fields, 535 + "Device not compatible, missing Invert usage", 536 + ) 537 + @pytest.mark.parametrize("scribble", [True, False], ids=["scribble", "static"]) 538 + @pytest.mark.parametrize( 539 + "state_list", 540 + [ 541 + pytest.param(v, id=k) 542 + for k, v in Pen.tolerated_transitions_with_invert().items() 543 + ], 544 + ) 545 + def test_tolerated_invert_pen_states(self, state_list, scribble): 546 + """This is the second half of the Windows Pen Implementation state machine: 547 + we now have Invert and Erase bits, so move in/out or proximity with the intend 548 + to erase. 549 + https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states 550 + """ 551 + self._test_states(state_list, scribble) 552 + 553 + @pytest.mark.skip_if_uhdev( 554 + lambda uhdev: "Invert" not in uhdev.fields, 555 + "Device not compatible, missing Invert usage", 556 + ) 557 + @pytest.mark.parametrize("scribble", [True, False], ids=["scribble", "static"]) 558 + @pytest.mark.parametrize( 559 + "state_list", 560 + [pytest.param(v, id=k) for k, v in Pen.broken_transitions().items()], 561 + ) 562 + def test_tolerated_broken_pen_states(self, state_list, scribble): 563 + """Those tests are definitely not part of the Windows specification. 564 + However, a half broken device might export those transitions. 565 + For example, a pen that has the eraser button might wobble between 566 + touching and erasing if the tablet doesn't enforce the Windows 567 + state machine.""" 568 + self._test_states(state_list, scribble) 569 + 570 + @pytest.mark.skip_if_uhdev( 571 + lambda uhdev: "Barrel Switch" not in uhdev.fields, 572 + "Device not compatible, missing Barrel Switch usage", 573 + ) 574 + def test_primary_button(self): 575 + """Primary button (stylus) pressed, reports as pressed even while hovering. 576 + Actual reporting from the device: hid=TIPSWITCH,BARRELSWITCH,INRANGE (code=TOUCH,STYLUS,PEN): 577 + { 0, 0, 1 } <- hover 578 + { 0, 1, 1 } <- primary button pressed 579 + { 0, 1, 1 } <- liftoff 580 + { 0, 0, 0 } <- leaves 581 + """ 582 + 583 + uhdev = self.uhdev 584 + evdev = uhdev.get_evdev() 585 + 586 + p = Pen(50, 60) 587 + p.inrange = True 588 + events = self.post(uhdev, p) 589 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN, 1) in events 590 + assert evdev.value[libevdev.EV_ABS.ABS_X] == 50 591 + assert evdev.value[libevdev.EV_ABS.ABS_Y] == 60 592 + assert not evdev.value[libevdev.EV_KEY.BTN_STYLUS] 593 + 594 + p.barrelswitch = True 595 + events = self.post(uhdev, p) 596 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS, 1) in events 597 + 598 + p.x += 1 599 + p.y -= 1 600 + events = self.post(uhdev, p) 601 + assert len(events) == 3 # X, Y, SYN 602 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_X, 51) in events 603 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_Y, 59) in events 604 + 605 + p.barrelswitch = False 606 + events = self.post(uhdev, p) 607 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS, 0) in events 608 + 609 + p.inrange = False 610 + events = self.post(uhdev, p) 611 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN, 0) in events 612 + 613 + @pytest.mark.skip_if_uhdev( 614 + lambda uhdev: "Barrel Switch" not in uhdev.fields, 615 + "Device not compatible, missing Barrel Switch usage", 616 + ) 617 + def test_contact_primary_button(self): 618 + """Primary button (stylus) pressed, reports as pressed even while hovering. 619 + Actual reporting from the device: hid=TIPSWITCH,BARRELSWITCH,INRANGE (code=TOUCH,STYLUS,PEN): 620 + { 0, 0, 1 } <- hover 621 + { 0, 1, 1 } <- primary button pressed 622 + { 1, 1, 1 } <- touch-down 623 + { 1, 1, 1 } <- still touch, scribble on the screen 624 + { 0, 1, 1 } <- liftoff 625 + { 0, 0, 0 } <- leaves 626 + """ 627 + 628 + uhdev = self.uhdev 629 + evdev = uhdev.get_evdev() 630 + 631 + p = Pen(50, 60) 632 + p.inrange = True 633 + events = self.post(uhdev, p) 634 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN, 1) in events 635 + assert evdev.value[libevdev.EV_ABS.ABS_X] == 50 636 + assert evdev.value[libevdev.EV_ABS.ABS_Y] == 60 637 + assert not evdev.value[libevdev.EV_KEY.BTN_STYLUS] 638 + 639 + p.barrelswitch = True 640 + events = self.post(uhdev, p) 641 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS, 1) in events 642 + 643 + p.tipswitch = True 644 + events = self.post(uhdev, p) 645 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events 646 + assert evdev.value[libevdev.EV_KEY.BTN_STYLUS] 647 + 648 + p.x += 1 649 + p.y -= 1 650 + events = self.post(uhdev, p) 651 + assert len(events) == 3 # X, Y, SYN 652 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_X, 51) in events 653 + assert libevdev.InputEvent(libevdev.EV_ABS.ABS_Y, 59) in events 654 + 655 + p.tipswitch = False 656 + events = self.post(uhdev, p) 657 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 0) in events 658 + 659 + p.barrelswitch = False 660 + p.inrange = False 661 + events = self.post(uhdev, p) 662 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN, 0) in events 663 + assert libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS, 0) in events 664 + 665 + 666 + class GXTP_pen(PenDigitizer): 667 + def event(self, pen): 668 + if not hasattr(self, "prev_tip_state"): 669 + self.prev_tip_state = False 670 + 671 + internal_pen = copy.copy(pen) 672 + 673 + # bug in the controller: when the pen touches the 674 + # surface, in-range stays to 1, but when 675 + # the pen moves in-range gets reverted to 0 676 + if pen.tipswitch and self.prev_tip_state: 677 + internal_pen.inrange = False 678 + 679 + self.prev_tip_state = pen.tipswitch 680 + 681 + # another bug in the controller: when the pen is 682 + # inverted, invert is set to 1, but as soon as 683 + # the pen touches the surface, eraser is correctly 684 + # set to 1 but invert is released 685 + if pen.eraser: 686 + internal_pen.invert = False 687 + 688 + return super().event(internal_pen) 689 + 690 + 691 + class USIPen(PenDigitizer): 692 + pass 693 + 694 + 695 + ################################################################################ 696 + # 697 + # Windows 7 compatible devices 698 + # 699 + ################################################################################ 700 + # class TestEgalax_capacitive_0eef_7224(BaseTest.TestTablet): 701 + # def create_device(self): 702 + # return PenDigitizer('uhid test egalax-capacitive_0eef_7224', 703 + # rdesc='05 0d 09 04 a1 01 85 04 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 15 00 25 01 81 02 09 51 75 05 95 01 16 00 00 26 10 00 81 02 09 47 75 01 95 01 15 00 25 01 81 02 05 01 09 30 75 10 95 01 55 0d 65 33 35 00 46 34 49 26 ff 7f 81 02 09 31 75 10 95 01 55 0d 65 33 35 00 46 37 29 26 ff 7f 81 02 05 0d 09 55 25 08 75 08 95 01 b1 02 c0 c0 05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 20 a1 00 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 75 01 81 03 05 01 09 30 75 10 95 01 a4 55 0d 65 33 36 00 00 46 34 49 16 00 00 26 ff 0f 81 02 09 31 16 00 00 26 ff 0f 36 00 00 46 37 29 81 02 b4 c0 c0 05 0d 09 0e a1 01 85 05 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0', 704 + # input_info=(BusType.USB, 0x0eef, 0x7224), 705 + # evdev_name_suffix=' Touchscreen') 706 + # 707 + # 708 + # class TestEgalax_capacitive_0eef_72fa(BaseTest.TestTablet): 709 + # def create_device(self): 710 + # return PenDigitizer('uhid test egalax-capacitive_0eef_72fa', 711 + # rdesc='05 0d 09 04 a1 01 85 04 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 15 00 25 01 81 02 09 51 75 05 95 01 16 00 00 26 10 00 81 02 09 47 75 01 95 01 15 00 25 01 81 02 05 01 09 30 75 10 95 01 55 0d 65 33 35 00 46 72 22 26 ff 7f 81 02 09 31 75 10 95 01 55 0d 65 33 35 00 46 87 13 26 ff 7f 81 02 05 0d 09 55 25 08 75 08 95 01 b1 02 c0 c0 05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 20 a1 00 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 75 01 81 03 05 01 09 30 75 10 95 01 a4 55 0d 65 33 36 00 00 46 72 22 16 00 00 26 ff 0f 81 02 09 31 16 00 00 26 ff 0f 36 00 00 46 87 13 81 02 b4 c0 c0 05 0d 09 0e a1 01 85 05 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0', 712 + # input_info=(BusType.USB, 0x0eef, 0x72fa), 713 + # evdev_name_suffix=' Touchscreen') 714 + # 715 + # 716 + # class TestEgalax_capacitive_0eef_7336(BaseTest.TestTablet): 717 + # def create_device(self): 718 + # return PenDigitizer('uhid test egalax-capacitive_0eef_7336', 719 + # rdesc='05 0d 09 04 a1 01 85 04 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 15 00 25 01 81 02 09 51 75 05 95 01 16 00 00 26 10 00 81 02 09 47 75 01 95 01 15 00 25 01 81 02 05 01 09 30 75 10 95 01 55 0d 65 33 35 00 46 c1 20 26 ff 7f 81 02 09 31 75 10 95 01 55 0d 65 33 35 00 46 c2 18 26 ff 7f 81 02 05 0d 09 55 25 08 75 08 95 01 b1 02 c0 c0 05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 20 a1 00 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 75 01 81 03 05 01 09 30 75 10 95 01 a4 55 0d 65 33 36 00 00 46 c1 20 16 00 00 26 ff 0f 81 02 09 31 16 00 00 26 ff 0f 36 00 00 46 c2 18 81 02 b4 c0 c0 05 0d 09 0e a1 01 85 05 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0', 720 + # input_info=(BusType.USB, 0x0eef, 0x7336), 721 + # evdev_name_suffix=' Touchscreen') 722 + # 723 + # 724 + # class TestEgalax_capacitive_0eef_7337(BaseTest.TestTablet): 725 + # def create_device(self): 726 + # return PenDigitizer('uhid test egalax-capacitive_0eef_7337', 727 + # rdesc='05 0d 09 04 a1 01 85 04 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 15 00 25 01 81 02 09 51 75 05 95 01 16 00 00 26 10 00 81 02 09 47 75 01 95 01 15 00 25 01 81 02 05 01 09 30 75 10 95 01 55 0d 65 33 35 00 46 ae 17 26 ff 7f 81 02 09 31 75 10 95 01 55 0d 65 33 35 00 46 c3 0e 26 ff 7f 81 02 05 0d 09 55 25 08 75 08 95 01 b1 02 c0 c0 05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 20 a1 00 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 75 01 81 03 05 01 09 30 75 10 95 01 a4 55 0d 65 33 36 00 00 46 ae 17 16 00 00 26 ff 0f 81 02 09 31 16 00 00 26 ff 0f 36 00 00 46 c3 0e 81 02 b4 c0 c0 05 0d 09 0e a1 01 85 05 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0', 728 + # input_info=(BusType.USB, 0x0eef, 0x7337), 729 + # evdev_name_suffix=' Touchscreen') 730 + # 731 + # 732 + # class TestEgalax_capacitive_0eef_7349(BaseTest.TestTablet): 733 + # def create_device(self): 734 + # return PenDigitizer('uhid test egalax-capacitive_0eef_7349', 735 + # rdesc='05 0d 09 04 a1 01 85 04 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 15 00 25 01 81 02 09 51 75 05 95 01 16 00 00 26 10 00 81 02 09 47 75 01 95 01 15 00 25 01 81 02 05 01 09 30 75 10 95 01 55 0d 65 33 35 00 46 34 49 26 ff 7f 81 02 09 31 75 10 95 01 55 0d 65 33 35 00 46 37 29 26 ff 7f 81 02 05 0d 09 55 25 08 75 08 95 01 b1 02 c0 c0 05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 20 a1 00 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 75 01 81 03 05 01 09 30 75 10 95 01 a4 55 0d 65 33 36 00 00 46 34 49 16 00 00 26 ff 0f 81 02 09 31 16 00 00 26 ff 0f 36 00 00 46 37 29 81 02 b4 c0 c0 05 0d 09 0e a1 01 85 05 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0', 736 + # input_info=(BusType.USB, 0x0eef, 0x7349), 737 + # evdev_name_suffix=' Touchscreen') 738 + # 739 + # 740 + # class TestEgalax_capacitive_0eef_73f4(BaseTest.TestTablet): 741 + # def create_device(self): 742 + # return PenDigitizer('uhid test egalax-capacitive_0eef_73f4', 743 + # rdesc='05 0d 09 04 a1 01 85 04 09 22 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 09 32 15 00 25 01 81 02 09 51 75 05 95 01 16 00 00 26 10 00 81 02 09 47 75 01 95 01 15 00 25 01 81 02 05 01 09 30 75 10 95 01 55 0d 65 33 35 00 46 96 4e 26 ff 7f 81 02 09 31 75 10 95 01 55 0d 65 33 35 00 46 23 2c 26 ff 7f 81 02 05 0d 09 55 25 08 75 08 95 01 b1 02 c0 c0 05 01 09 01 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 01 75 06 81 01 05 01 09 30 09 31 16 00 00 26 ff 0f 36 00 00 46 ff 0f 66 00 00 75 10 95 02 81 02 c0 c0 06 00 ff 09 01 a1 01 09 01 15 00 26 ff 00 85 03 75 08 95 3f 81 02 06 00 ff 09 01 15 00 26 ff 00 75 08 95 3f 91 02 c0 05 0d 09 04 a1 01 85 02 09 20 a1 00 09 42 09 32 15 00 25 01 95 02 75 01 81 02 95 06 75 01 81 03 05 01 09 30 75 10 95 01 a4 55 0d 65 33 36 00 00 46 96 4e 16 00 00 26 ff 0f 81 02 09 31 16 00 00 26 ff 0f 36 00 00 46 23 2c 81 02 b4 c0 c0 05 0d 09 0e a1 01 85 05 09 22 a1 00 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0', 744 + # input_info=(BusType.USB, 0x0eef, 0x73f4), 745 + # evdev_name_suffix=' Touchscreen') 746 + # 747 + # bogus: BTN_TOOL_PEN is not emitted 748 + # class TestIrtouch_6615_0070(BaseTest.TestTablet): 749 + # def create_device(self): 750 + # return PenDigitizer('uhid test irtouch_6615_0070', 751 + # rdesc='05 01 09 02 a1 01 85 10 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 95 02 75 01 81 02 95 06 81 03 05 01 09 30 09 31 15 00 26 ff 7f 75 10 95 02 81 02 c0 c0 05 0d 09 04 a1 01 85 30 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 81 02 05 01 09 30 26 ff 7f 55 0f 65 11 35 00 46 51 02 75 10 95 01 81 02 09 31 35 00 46 73 01 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 81 02 05 01 09 30 26 ff 7f 55 0f 65 11 35 00 46 51 02 75 10 95 01 81 02 09 31 35 00 46 73 01 81 02 c0 05 0d 09 54 15 00 26 02 00 75 08 95 01 81 02 85 03 09 55 15 00 26 ff 00 75 08 95 01 b1 02 c0 05 0d 09 0e a1 01 85 02 09 52 09 53 15 00 26 ff 00 75 08 95 02 b1 02 c0 05 0d 09 02 a1 01 85 20 09 20 a1 00 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 03 05 01 09 30 26 ff 7f 55 0f 65 11 35 00 46 51 02 75 10 95 01 81 02 09 31 35 00 46 73 01 81 02 85 01 06 00 ff 09 01 75 08 95 01 b1 02 c0 c0', 752 + # input_info=(BusType.USB, 0x6615, 0x0070)) 753 + 754 + 755 + class TestNexio_1870_0100(BaseTest.TestTablet): 756 + def create_device(self): 757 + return PenDigitizer( 758 + "uhid test nexio_1870_0100", 759 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0e 65 11 09 30 35 00 46 1e 19 81 02 26 ff 3f 09 31 35 00 46 be 0f 81 02 26 ff 3f c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0e 65 11 09 30 35 00 46 1e 19 81 02 26 ff 3f 09 31 35 00 46 be 0f 81 02 26 ff 3f c0 05 0d 09 54 95 01 75 08 25 02 81 02 85 02 09 55 25 02 b1 02 c0 09 0e a1 01 85 03 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 09 01 a1 00 85 04 05 09 95 03 75 01 19 01 29 03 15 00 25 01 81 02 95 01 75 05 81 01 05 01 75 10 95 02 09 30 09 31 15 00 26 ff 7f 81 02 c0 c0 05 0d 09 02 a1 01 85 05 09 20 a1 00 09 42 09 32 15 00 25 01 75 01 95 02 81 02 95 0e 81 03 05 01 26 ff 3f 75 10 95 01 55 0e 65 11 09 30 35 00 46 1e 19 81 02 26 ff 3f 09 31 35 00 46 be 0f 81 02 26 ff 3f c0 c0 06 00 ff 09 01 a1 01 85 06 19 01 29 40 15 00 26 ff 00 75 08 95 40 81 00 19 01 29 40 91 00 c0", 760 + input_info=(BusType.USB, 0x1870, 0x0100), 761 + ) 762 + 763 + 764 + class TestNexio_1870_010d(BaseTest.TestTablet): 765 + def create_device(self): 766 + return PenDigitizer( 767 + "uhid test nexio_1870_010d", 768 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 05 0d 09 54 95 01 75 08 25 02 81 02 85 02 09 55 25 06 b1 02 c0 09 0e a1 01 85 03 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 09 01 a1 00 85 04 05 09 95 03 75 01 19 01 29 03 15 00 25 01 81 02 95 01 75 05 81 01 05 01 75 10 95 02 09 30 09 31 15 00 26 ff 7f 81 02 c0 c0 05 0d 09 02 a1 01 85 05 09 20 a1 00 09 42 09 32 15 00 25 01 75 01 95 02 81 02 95 0e 81 03 05 01 26 ff 3f 75 10 95 01 55 0e 65 11 09 30 35 00 46 1e 19 81 02 26 ff 3f 09 31 35 00 46 be 0f 81 02 26 ff 3f c0 c0 06 00 ff 09 01 a1 01 85 06 19 01 29 40 15 00 26 ff 00 75 08 95 3e 81 00 19 01 29 40 91 00 c0", 769 + input_info=(BusType.USB, 0x1870, 0x010D), 770 + ) 771 + 772 + 773 + class TestNexio_1870_0119(BaseTest.TestTablet): 774 + def create_device(self): 775 + return PenDigitizer( 776 + "uhid test nexio_1870_0119", 777 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 95 06 81 03 75 08 09 51 95 01 81 02 05 01 26 ff 3f 75 10 55 0d 65 00 09 30 35 00 46 00 00 81 02 26 ff 3f 09 31 35 00 46 00 00 81 02 26 ff 3f 05 0d 09 48 35 00 26 ff 3f 81 02 09 49 35 00 26 ff 3f 81 02 c0 05 0d 09 54 95 01 75 08 25 02 81 02 85 02 09 55 25 06 b1 02 c0 09 0e a1 01 85 03 09 23 a1 02 09 52 09 53 15 00 25 0a 75 08 95 02 b1 02 c0 c0 05 01 09 02 a1 01 09 01 a1 00 85 04 05 09 95 03 75 01 19 01 29 03 15 00 25 01 81 02 95 01 75 05 81 01 05 01 75 10 95 02 09 30 09 31 15 00 26 ff 7f 81 02 c0 c0 05 0d 09 02 a1 01 85 05 09 20 a1 00 09 42 09 32 15 00 25 01 75 01 95 02 81 02 95 0e 81 03 05 01 26 ff 3f 75 10 95 01 55 0e 65 11 09 30 35 00 46 1e 19 81 02 26 ff 3f 09 31 35 00 46 be 0f 81 02 26 ff 3f c0 c0 06 00 ff 09 01 a1 01 85 06 19 01 29 40 15 00 26 ff 00 75 08 95 3e 81 00 19 01 29 40 91 00 c0", 778 + input_info=(BusType.USB, 0x1870, 0x0119), 779 + ) 780 + 781 + 782 + ################################################################################ 783 + # 784 + # Windows 8 compatible devices 785 + # 786 + ################################################################################ 787 + 788 + # bogus: application is 'undefined' 789 + # class Testatmel_03eb_8409(BaseTest.TestTablet): 790 + # def create_device(self): 791 + # return PenDigitizer('uhid test atmel_03eb_8409', rdesc='05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 02 46 c8 0a 26 6f 08 09 30 81 02 35 00 35 00 46 18 06 26 77 0f 09 31 81 02 35 00 35 00 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 48 81 02 09 49 81 02 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 02 46 c8 0a 26 6f 08 09 30 81 02 35 00 35 00 46 18 06 26 77 0f 09 31 81 02 35 00 35 00 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 48 81 02 09 49 81 02 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 02 46 c8 0a 26 6f 08 09 30 81 02 35 00 35 00 46 18 06 26 77 0f 09 31 81 02 35 00 35 00 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 48 81 02 09 49 81 02 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 02 46 c8 0a 26 6f 08 09 30 81 02 35 00 35 00 46 18 06 26 77 0f 09 31 81 02 35 00 35 00 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 48 81 02 09 49 81 02 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 02 46 c8 0a 26 6f 08 09 30 81 02 35 00 35 00 46 18 06 26 77 0f 09 31 81 02 35 00 35 00 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 48 81 02 09 49 81 02 c0 05 0d 27 ff ff 00 00 75 10 95 01 09 56 81 02 15 00 25 1f 75 05 09 54 95 01 81 02 75 03 25 01 95 01 81 03 75 08 85 02 09 55 25 10 b1 02 06 00 ff 85 05 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 00 a1 01 85 03 09 20 a1 00 15 00 25 01 75 01 95 01 09 42 81 02 09 44 81 02 09 45 81 02 81 03 09 32 81 02 95 03 81 03 05 01 55 0e 65 11 35 00 75 10 95 02 46 c8 0a 26 6f 08 09 30 81 02 46 18 06 26 77 0f 09 31 81 02 05 0d 09 30 15 01 26 ff 00 75 08 95 01 81 02 c0 c0') 792 + 793 + 794 + class Testatmel_03eb_840b(BaseTest.TestTablet): 795 + def create_device(self): 796 + return PenDigitizer( 797 + "uhid test atmel_03eb_840b", 798 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 01 46 00 0a 26 ff 0f 09 30 81 02 09 00 81 03 46 a0 05 26 ff 0f 09 31 81 02 09 00 81 03 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 00 81 03 09 00 81 03 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 01 46 00 0a 26 ff 0f 09 30 81 02 09 00 81 03 46 a0 05 26 ff 0f 09 31 81 02 09 00 81 03 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 00 81 03 09 00 81 03 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 01 46 00 0a 26 ff 0f 09 30 81 02 09 00 81 03 46 a0 05 26 ff 0f 09 31 81 02 09 00 81 03 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 00 81 03 09 00 81 03 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 01 46 00 0a 26 ff 0f 09 30 81 02 09 00 81 03 46 a0 05 26 ff 0f 09 31 81 02 09 00 81 03 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 00 81 03 09 00 81 03 c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 95 01 81 03 25 1f 75 05 09 51 81 02 05 01 55 0e 65 11 35 00 75 10 95 01 46 00 0a 26 ff 0f 09 30 81 02 09 00 81 03 46 a0 05 26 ff 0f 09 31 81 02 09 00 81 03 05 0d 95 01 75 08 15 00 26 ff 00 46 ff 00 09 00 81 03 09 00 81 03 c0 05 0d 27 ff ff 00 00 75 10 95 01 09 56 81 02 15 00 25 1f 75 05 09 54 95 01 81 02 75 03 25 01 95 01 81 03 75 08 85 02 09 55 25 10 b1 02 06 00 ff 85 05 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 02 a1 01 85 03 09 20 a1 00 15 00 25 01 75 01 95 01 09 42 81 02 09 44 81 02 09 45 81 02 81 03 09 32 81 02 95 03 81 03 05 01 55 0e 65 11 35 00 75 10 95 02 46 00 0a 26 ff 0f 09 30 81 02 46 a0 05 26 ff 0f 09 31 81 02 05 0d 09 30 15 01 26 ff 00 75 08 95 01 81 02 c0 c0", 799 + ) 800 + 801 + 802 + class Testn_trig_1b96_0c01(BaseTest.TestTablet): 803 + def create_device(self): 804 + return PenDigitizer( 805 + "uhid test n_trig_1b96_0c01", 806 + rdesc="75 08 15 00 26 ff 00 06 0b ff 09 0b a1 01 95 0f 09 29 85 29 b1 02 95 1f 09 2a 85 2a b1 02 95 3e 09 2b 85 2b b1 02 95 fe 09 2c 85 2c b1 02 96 fe 01 09 2d 85 2d b1 02 95 02 09 48 85 48 b1 02 95 0f 09 2e 85 2e 81 02 95 1f 09 2f 85 2f 81 02 95 3e 09 30 85 30 81 02 95 fe 09 31 85 31 81 02 96 fe 01 09 32 85 32 81 02 75 08 96 fe 0f 09 35 85 35 81 02 c0 05 0d 09 02 a1 01 85 01 09 20 35 00 a1 00 09 32 09 42 09 44 09 3c 09 45 15 00 25 01 75 01 95 05 81 02 95 03 81 03 05 01 09 30 75 10 95 01 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 b4 05 0d 09 30 26 00 01 81 02 06 00 ff 09 01 81 02 c0 85 0c 06 00 ff 09 0c 75 08 95 06 26 ff 00 b1 02 85 0b 09 0b 95 02 b1 02 85 11 09 11 b1 02 85 15 09 15 95 05 b1 02 85 18 09 18 95 0c b1 02 c0 05 0d 09 04 a1 01 85 03 06 00 ff 09 01 75 10 95 01 15 00 27 ff ff 00 00 81 02 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 54 95 01 75 08 81 02 09 56 75 20 95 01 27 ff ff ff 0f 81 02 85 04 09 55 75 08 95 01 25 0b b1 02 85 0a 06 00 ff 09 03 15 00 b1 02 85 1b 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0", 807 + ) 808 + 809 + 810 + class Testn_trig_1b96_0c03(BaseTest.TestTablet): 811 + def create_device(self): 812 + return PenDigitizer( 813 + "uhid test n_trig_1b96_0c03", 814 + rdesc="75 08 15 00 26 ff 00 06 0b ff 09 0b a1 01 95 0f 09 29 85 29 b1 02 95 1f 09 2a 85 2a b1 02 95 3e 09 2b 85 2b b1 02 95 fe 09 2c 85 2c b1 02 96 fe 01 09 2d 85 2d b1 02 95 02 09 48 85 48 b1 02 95 0f 09 2e 85 2e 81 02 95 1f 09 2f 85 2f 81 02 95 3e 09 30 85 30 81 02 95 fe 09 31 85 31 81 02 96 fe 01 09 32 85 32 81 02 75 08 96 fe 0f 09 35 85 35 81 02 c0 05 0d 09 02 a1 01 85 01 09 20 35 00 a1 00 09 32 09 42 09 44 09 3c 09 45 15 00 25 01 75 01 95 05 81 02 95 03 81 03 05 01 09 30 75 10 95 01 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 b4 05 0d 09 30 26 00 01 81 02 06 00 ff 09 01 81 02 c0 85 0c 06 00 ff 09 0c 75 08 95 06 26 ff 00 b1 02 85 0b 09 0b 95 02 b1 02 85 11 09 11 b1 02 85 15 09 15 95 05 b1 02 85 18 09 18 95 0c b1 02 c0 05 0d 09 04 a1 01 85 03 06 00 ff 09 01 75 10 95 01 15 00 27 ff ff 00 00 81 02 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 15 0a 26 80 25 81 02 09 31 46 b4 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 54 95 01 75 08 81 02 09 56 75 20 95 01 27 ff ff ff 0f 81 02 85 04 09 55 75 08 95 01 25 0b b1 02 85 0a 06 00 ff 09 03 15 00 b1 02 85 1b 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0", 815 + ) 816 + 817 + 818 + class Testn_trig_1b96_0f00(BaseTest.TestTablet): 819 + def create_device(self): 820 + return PenDigitizer( 821 + "uhid test n_trig_1b96_0f00", 822 + rdesc="75 08 15 00 26 ff 00 06 0b ff 09 0b a1 01 95 0f 09 29 85 29 b1 02 95 1f 09 2a 85 2a b1 02 95 3e 09 2b 85 2b b1 02 95 fe 09 2c 85 2c b1 02 96 fe 01 09 2d 85 2d b1 02 95 02 09 48 85 48 b1 02 95 0f 09 2e 85 2e 81 02 95 1f 09 2f 85 2f 81 02 95 3e 09 30 85 30 81 02 95 fe 09 31 85 31 81 02 96 fe 01 09 32 85 32 81 02 75 08 96 fe 0f 09 35 85 35 81 02 c0 05 0d 09 02 a1 01 85 01 09 20 35 00 a1 00 09 32 09 42 09 44 09 3c 09 45 15 00 25 01 75 01 95 05 81 02 95 03 81 03 05 01 09 30 75 10 95 01 a4 55 0e 65 11 46 03 0a 26 80 25 81 02 09 31 46 a1 05 26 20 1c 81 02 b4 05 0d 09 30 26 00 01 81 02 06 00 ff 09 01 81 02 c0 85 0c 06 00 ff 09 0c 75 08 95 06 26 ff 00 b1 02 85 0b 09 0b 95 02 b1 02 85 11 09 11 b1 02 85 15 09 15 95 05 b1 02 85 18 09 18 95 0c b1 02 c0 05 0d 09 04 a1 01 85 03 06 00 ff 09 01 75 10 95 01 15 00 27 ff ff 00 00 81 02 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 03 0a 26 80 25 81 02 09 31 46 a1 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 03 0a 26 80 25 81 02 09 31 46 a1 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 54 95 01 75 08 81 02 09 56 75 20 95 01 27 ff ff ff 0f 81 02 85 04 09 55 75 08 95 01 25 0b b1 02 85 0a 06 00 ff 09 03 15 00 b1 02 85 1b 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0", 823 + ) 824 + 825 + 826 + class Testn_trig_1b96_0f04(BaseTest.TestTablet): 827 + def create_device(self): 828 + return PenDigitizer( 829 + "uhid test n_trig_1b96_0f04", 830 + rdesc="75 08 15 00 26 ff 00 06 0b ff 09 0b a1 01 95 0f 09 29 85 29 b1 02 95 1f 09 2a 85 2a b1 02 95 3e 09 2b 85 2b b1 02 95 fe 09 2c 85 2c b1 02 96 fe 01 09 2d 85 2d b1 02 95 02 09 48 85 48 b1 02 95 0f 09 2e 85 2e 81 02 95 1f 09 2f 85 2f 81 02 95 3e 09 30 85 30 81 02 95 fe 09 31 85 31 81 02 96 fe 01 09 32 85 32 81 02 75 08 96 fe 0f 09 35 85 35 81 02 c0 05 0d 09 02 a1 01 85 01 09 20 35 00 a1 00 09 32 09 42 09 44 09 3c 09 45 15 00 25 01 75 01 95 05 81 02 95 03 81 03 05 01 09 30 75 10 95 01 a4 55 0e 65 11 46 7f 0b 26 80 25 81 02 09 31 46 78 06 26 20 1c 81 02 b4 05 0d 09 30 26 00 01 81 02 06 00 ff 09 01 81 02 c0 85 0c 06 00 ff 09 0c 75 08 95 06 26 ff 00 b1 02 85 0b 09 0b 95 02 b1 02 85 11 09 11 b1 02 85 15 09 15 95 05 b1 02 85 18 09 18 95 0c b1 02 c0 05 0d 09 04 a1 01 85 03 06 00 ff 09 01 75 10 95 01 15 00 27 ff ff 00 00 81 02 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 7f 0b 26 80 25 81 02 09 31 46 78 06 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 7f 0b 26 80 25 81 02 09 31 46 78 06 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 54 95 01 75 08 81 02 09 56 75 20 95 01 27 ff ff ff 0f 81 02 85 04 09 55 75 08 95 01 25 0b b1 02 85 0a 06 00 ff 09 03 15 00 b1 02 85 1b 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0", 831 + ) 832 + 833 + 834 + class Testn_trig_1b96_1000(BaseTest.TestTablet): 835 + def create_device(self): 836 + return PenDigitizer( 837 + "uhid test n_trig_1b96_1000", 838 + rdesc="75 08 15 00 26 ff 00 06 0b ff 09 0b a1 01 95 0f 09 29 85 29 b1 02 95 1f 09 2a 85 2a b1 02 95 3e 09 2b 85 2b b1 02 95 fe 09 2c 85 2c b1 02 96 fe 01 09 2d 85 2d b1 02 95 02 09 48 85 48 b1 02 95 0f 09 2e 85 2e 81 02 95 1f 09 2f 85 2f 81 02 95 3e 09 30 85 30 81 02 95 fe 09 31 85 31 81 02 96 fe 01 09 32 85 32 81 02 75 08 96 fe 0f 09 35 85 35 81 02 c0 05 0d 09 02 a1 01 85 01 09 20 35 00 a1 00 09 32 09 42 09 44 09 3c 09 45 15 00 25 01 75 01 95 05 81 02 95 03 81 03 05 01 09 30 75 10 95 01 a4 55 0e 65 11 46 03 0a 26 80 25 81 02 09 31 46 a1 05 26 20 1c 81 02 b4 05 0d 09 30 26 00 01 81 02 06 00 ff 09 01 81 02 c0 85 0c 06 00 ff 09 0c 75 08 95 06 26 ff 00 b1 02 85 0b 09 0b 95 02 b1 02 85 11 09 11 b1 02 85 15 09 15 95 05 b1 02 85 18 09 18 95 0c b1 02 c0 05 0d 09 04 a1 01 85 03 06 00 ff 09 01 75 10 95 01 15 00 27 ff ff 00 00 81 02 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 03 0a 26 80 25 81 02 09 31 46 a1 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 01 81 03 09 47 81 02 95 05 81 03 75 10 09 51 27 ff ff 00 00 95 01 81 02 05 01 09 30 75 10 95 02 a4 55 0e 65 11 46 03 0a 26 80 25 81 02 09 31 46 a1 05 26 20 1c 81 02 05 0d 09 48 95 01 26 80 25 81 02 09 49 26 20 1c 81 02 b4 06 00 ff 09 02 75 08 95 04 15 00 26 ff 00 81 02 c0 05 0d 09 54 95 01 75 08 81 02 09 56 75 20 95 01 27 ff ff ff 0f 81 02 85 04 09 55 75 08 95 01 25 0b b1 02 85 0a 06 00 ff 09 03 15 00 b1 02 85 1b 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0", 839 + ) 840 + 841 + 842 + class TestGXTP_27c6_0113(BaseTest.TestTablet): 843 + def create_device(self): 844 + return GXTP_pen( 845 + "uhid test GXTP_27c6_0113", 846 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 55 0e 65 11 35 00 15 00 09 42 25 01 75 01 95 01 81 02 95 07 81 01 95 01 75 08 09 51 81 02 75 10 05 01 26 00 14 46 1f 07 09 30 81 02 26 80 0c 46 77 04 09 31 81 02 05 0d c0 09 22 a1 02 09 42 25 01 75 01 95 01 81 02 95 07 81 01 95 01 75 08 09 51 81 02 75 10 05 01 26 00 14 46 1f 07 09 30 81 02 26 80 0c 46 77 04 09 31 81 02 05 0d c0 09 22 a1 02 09 42 25 01 75 01 95 01 81 02 95 07 81 01 95 01 75 08 09 51 81 02 75 10 05 01 26 00 14 46 1f 07 09 30 81 02 26 80 0c 46 77 04 09 31 81 02 05 0d c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 01 75 08 09 51 95 01 81 02 05 01 26 00 14 75 10 55 0e 65 11 09 30 35 00 46 1f 07 81 02 26 80 0c 46 77 04 09 31 81 02 05 0d c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 95 07 81 01 75 08 09 51 95 01 81 02 05 01 26 00 14 75 10 55 0e 65 11 09 30 35 00 46 1f 07 81 02 26 80 0c 46 77 04 09 31 81 02 05 0d c0 09 54 15 00 25 7f 75 08 95 01 81 02 85 02 09 55 95 01 25 0a b1 02 85 03 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 02 a1 01 85 08 09 20 a1 00 09 42 09 44 09 3c 09 45 15 00 25 01 75 01 95 04 81 02 95 01 81 03 09 32 81 02 95 02 81 03 95 01 75 08 09 51 81 02 05 01 09 30 75 10 95 01 a4 55 0e 65 11 35 00 26 00 14 46 1f 07 81 42 09 31 26 80 0c 46 77 04 81 42 b4 05 0d 09 30 26 ff 0f 81 02 09 3d 65 14 55 0e 36 d8 dc 46 28 23 16 d8 dc 26 28 23 81 02 09 3e 81 02 c0 c0 06 f0 ff 09 01 a1 01 85 0e 09 01 15 00 25 ff 75 08 95 40 91 02 09 01 15 00 25 ff 75 08 95 40 81 02 c0 05 01 09 06 a1 01 85 04 05 07 09 e3 15 00 25 01 75 01 95 01 81 02 95 07 81 03 c0", 847 + ) 848 + 849 + 850 + ################################################################################ 851 + # 852 + # Windows 8 compatible devices with USI Pen 853 + # 854 + ################################################################################ 855 + 856 + 857 + class TestElan_04f3_2A49(BaseTest.TestTablet): 858 + def create_device(self): 859 + return USIPen( 860 + "uhid test Elan_04f3_2A49", 861 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 55 0f 65 11 35 00 45 ff 09 48 81 02 09 49 81 02 09 30 81 02 95 01 05 01 a4 26 cf 0f 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 01 81 02 26 77 0a 46 a6 00 09 31 81 02 b4 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 55 0f 65 11 35 00 45 ff 09 48 81 02 09 49 81 02 09 30 81 02 95 01 05 01 a4 26 cf 0f 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 01 81 02 26 77 0a 46 a6 00 09 31 81 02 b4 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 55 0f 65 11 35 00 45 ff 09 48 81 02 09 49 81 02 09 30 81 02 95 01 05 01 a4 26 cf 0f 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 01 81 02 26 77 0a 46 a6 00 09 31 81 02 b4 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 55 0f 65 11 35 00 45 ff 09 48 81 02 09 49 81 02 09 30 81 02 95 01 05 01 a4 26 cf 0f 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 01 81 02 26 77 0a 46 a6 00 09 31 81 02 b4 c0 05 0d 09 22 a1 02 05 0d 09 42 15 00 25 01 75 01 95 01 81 02 75 01 81 03 75 06 09 51 25 3f 81 02 26 ff 00 75 08 55 0f 65 11 35 00 45 ff 09 48 81 02 09 49 81 02 09 30 81 02 95 01 05 01 a4 26 cf 0f 75 10 55 0f 65 11 09 30 35 00 46 26 01 95 01 81 02 26 77 0a 46 a6 00 09 31 81 02 b4 c0 05 0d 09 54 25 7f 96 01 00 75 08 81 02 85 0a 09 55 25 0a b1 02 85 44 06 00 ff 09 c5 16 00 00 26 ff 00 75 08 96 00 01 b1 02 c0 06 ff 01 09 01 a1 01 85 02 16 00 00 26 ff 00 75 08 95 40 09 00 81 02 c0 06 00 ff 09 01 a1 01 85 03 75 08 95 20 09 01 91 02 c0 06 00 ff 09 01 a1 01 85 06 09 03 75 08 95 12 91 02 09 04 75 08 95 03 b1 02 c0 06 01 ff 09 01 a1 01 85 04 15 00 26 ff 00 75 08 95 13 09 00 81 02 c0 05 0d 09 02 a1 01 85 07 35 00 09 20 a1 00 09 32 09 42 09 44 09 3c 09 45 15 00 25 01 75 01 95 05 81 02 95 03 81 03 05 01 09 30 75 10 95 01 a4 55 0f 65 11 46 26 01 26 1c 48 81 42 09 31 46 a6 00 26 bc 2f 81 42 b4 05 0d 09 30 26 00 10 81 02 75 08 95 01 09 3b 25 64 81 42 09 38 15 00 25 02 81 02 09 5c 26 ff 00 81 02 09 5e 81 02 09 70 a1 02 15 01 25 06 09 72 09 73 09 74 09 75 09 76 09 77 81 20 09 5b 25 ff 75 40 81 02 c0 06 00 ff 75 08 95 02 09 01 81 02 c0 05 0d 85 60 09 81 a1 02 09 38 75 08 95 01 15 00 25 02 81 02 09 81 15 01 25 04 09 82 09 83 09 84 09 85 81 20 c0 85 61 09 5c a1 02 15 00 26 ff 00 75 08 95 01 09 38 b1 02 09 5c 26 ff 00 b1 02 09 5d 75 01 95 01 25 01 b1 02 95 07 b1 03 c0 85 62 09 5e a1 02 09 38 15 00 25 02 75 08 95 01 b1 02 09 5e 26 ff 00 b1 02 09 5f 75 01 25 01 b1 02 75 07 b1 03 c0 85 63 09 70 a1 02 75 08 95 01 15 00 25 02 09 38 b1 02 09 70 a1 02 25 06 09 72 09 73 09 74 09 75 09 76 09 77 b1 20 c0 09 71 75 01 25 01 b1 02 75 07 b1 03 c0 85 64 09 80 15 00 25 ff 75 40 95 01 b1 02 85 65 09 44 a1 02 09 38 75 08 95 01 25 02 b1 02 15 01 25 03 09 44 a1 02 09 a4 09 44 09 5a 09 45 09 a3 b1 20 c0 09 5a a1 02 09 a4 09 44 09 5a 09 45 09 a3 b1 20 c0 09 45 a1 02 09 a4 09 44 09 5a 09 45 09 a3 b1 20 c0 c0 85 66 75 08 95 01 05 0d 09 90 a1 02 09 38 25 02 b1 02 09 91 75 10 26 ff 0f b1 02 09 92 75 40 25 ff b1 02 05 06 09 2a 75 08 26 ff 00 a1 02 09 2d b1 02 09 2e b1 02 c0 c0 85 67 05 06 09 2b a1 02 05 0d 25 02 09 38 b1 02 05 06 09 2b a1 02 09 2d 26 ff 00 b1 02 09 2e b1 02 c0 c0 85 68 06 00 ff 09 01 a1 02 05 0d 09 38 75 08 95 01 25 02 b1 02 06 00 ff 09 01 75 10 27 ff ff 00 00 b1 02 c0 85 69 05 0d 09 38 75 08 95 01 15 00 25 02 b1 02 c0 06 00 ff 09 81 a1 01 85 17 75 08 95 1f 09 05 81 02 c0", 862 + input_info=(BusType.I2C, 0x04F3, 0x2A49), 863 + ) 864 + 865 + 866 + class TestGoodix_27c6_0e00(BaseTest.TestTablet): 867 + def create_device(self): 868 + return USIPen( 869 + "uhid test Elan_04f3_2A49", 870 + rdesc="05 0d 09 04 a1 01 85 01 09 22 a1 02 55 0e 65 11 35 00 15 00 09 42 25 01 75 01 95 01 81 02 25 7f 09 30 75 07 81 42 95 01 75 08 09 51 81 02 75 10 05 01 26 04 20 46 e6 09 09 30 81 02 26 60 15 46 9a 06 09 31 81 02 05 0d 55 0f 75 08 25 ff 45 ff 09 48 81 42 09 49 81 42 55 0e c0 09 22 a1 02 09 42 25 01 75 01 95 01 81 02 25 7f 09 30 75 07 81 42 95 01 75 08 09 51 81 02 75 10 05 01 26 04 20 46 e6 09 09 30 81 02 26 60 15 46 9a 06 09 31 81 02 05 0d 55 0f 75 08 25 ff 45 ff 09 48 81 42 09 49 81 42 55 0e c0 09 22 a1 02 09 42 25 01 75 01 95 01 81 02 25 7f 09 30 75 07 81 42 95 01 75 08 09 51 81 02 75 10 05 01 26 04 20 46 e6 09 09 30 81 02 26 60 15 46 9a 06 09 31 81 02 05 0d 55 0f 75 08 25 ff 45 ff 09 48 81 42 09 49 81 42 55 0e c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 25 7f 09 30 75 07 81 42 75 08 09 51 95 01 81 02 05 01 26 04 20 75 10 55 0e 65 11 09 30 35 00 46 e6 09 81 02 26 60 15 46 9a 06 09 31 81 02 05 0d 55 0f 75 08 25 ff 45 ff 09 48 81 42 09 49 81 42 55 0e c0 09 22 a1 02 09 42 15 00 25 01 75 01 95 01 81 02 25 7f 09 30 75 07 81 42 75 08 09 51 95 01 81 02 05 01 26 04 20 75 10 55 0e 65 11 09 30 35 00 46 e6 09 81 02 26 60 15 46 9a 06 09 31 81 02 05 0d 55 0f 75 08 25 ff 45 ff 09 48 81 42 09 49 81 42 55 0e c0 09 54 15 00 25 7f 75 08 95 01 81 02 85 02 09 55 95 01 25 0a b1 02 85 03 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 02 a1 01 09 20 a1 00 85 08 05 01 a4 09 30 35 00 46 e6 09 15 00 26 04 20 55 0d 65 13 75 10 95 01 81 02 09 31 46 9a 06 26 60 15 81 02 b4 05 0d 09 38 95 01 75 08 15 00 25 01 81 02 09 30 75 10 26 ff 0f 81 02 09 31 81 02 09 42 09 44 09 5a 09 3c 09 45 09 32 75 01 95 06 25 01 81 02 95 02 81 03 09 3d 55 0e 65 14 36 d8 dc 46 28 23 16 d8 dc 26 28 23 95 01 75 10 81 02 09 3e 81 02 09 41 15 00 27 a0 8c 00 00 35 00 47 a0 8c 00 00 81 02 05 20 0a 53 04 65 00 16 01 f8 26 ff 07 75 10 95 01 81 02 0a 54 04 81 02 0a 55 04 81 02 0a 57 04 81 02 0a 58 04 81 02 0a 59 04 81 02 0a 72 04 81 02 0a 73 04 81 02 0a 74 04 81 02 05 0d 09 3b 15 00 25 64 75 08 81 02 09 5b 25 ff 75 40 81 02 06 00 ff 09 5b 75 20 81 02 05 0d 09 5c 26 ff 00 75 08 81 02 09 5e 81 02 09 70 a1 02 15 01 25 06 09 72 09 73 09 74 09 75 09 76 09 77 81 20 c0 06 00 ff 09 01 15 00 27 ff ff 00 00 75 10 95 01 81 02 85 09 09 81 a1 02 09 81 15 01 25 04 09 82 09 83 09 84 09 85 81 20 c0 85 10 09 5c a1 02 15 00 25 01 75 08 95 01 09 38 b1 02 09 5c 26 ff 00 b1 02 09 5d 75 01 95 01 25 01 b1 02 95 07 b1 03 c0 85 11 09 5e a1 02 09 38 15 00 25 01 75 08 95 01 b1 02 09 5e 26 ff 00 b1 02 09 5f 75 01 25 01 b1 02 75 07 b1 03 c0 85 12 09 70 a1 02 75 08 95 01 15 00 25 01 09 38 b1 02 09 70 a1 02 25 06 09 72 09 73 09 74 09 75 09 76 09 77 b1 20 c0 09 71 75 01 25 01 b1 02 75 07 b1 03 c0 85 13 09 80 15 00 25 ff 75 40 95 01 b1 02 85 14 09 44 a1 02 09 38 75 08 95 01 25 01 b1 02 15 01 25 03 09 44 a1 02 09 a4 09 44 09 5a 09 45 09 a3 b1 20 c0 09 5a a1 02 09 a4 09 44 09 5a 09 45 09 a3 b1 20 c0 09 45 a1 02 09 a4 09 44 09 5a 09 45 09 a3 b1 20 c0 c0 85 15 75 08 95 01 05 0d 09 90 a1 02 09 38 25 01 b1 02 09 91 75 10 26 ff 0f b1 02 09 92 75 40 25 ff b1 02 05 06 09 2a 75 08 26 ff 00 a1 02 09 2d b1 02 09 2e b1 02 c0 c0 85 16 05 06 09 2b a1 02 05 0d 25 01 09 38 b1 02 05 06 09 2b a1 02 09 2d 26 ff 00 b1 02 09 2e b1 02 c0 c0 85 17 06 00 ff 09 01 a1 02 05 0d 09 38 75 08 95 01 25 01 b1 02 06 00 ff 09 01 75 10 27 ff ff 00 00 b1 02 c0 85 18 05 0d 09 38 75 08 95 01 15 00 25 01 b1 02 c0 c0 06 f0 ff 09 01 a1 01 85 0e 09 01 15 00 25 ff 75 08 95 40 91 02 09 01 15 00 25 ff 75 08 95 40 81 02 c0", 871 + input_info=(BusType.I2C, 0x27C6, 0x0E00), 872 + )
+103
tools/testing/selftests/hid/tests/test_usb_crash.py
··· 1 + #!/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # -*- coding: utf-8 -*- 4 + # 5 + # Copyright (c) 2021 Benjamin Tissoires <benjamin.tissoires@gmail.com> 6 + # Copyright (c) 2021 Red Hat, Inc. 7 + # 8 + 9 + # This is to ensure we don't crash when emulating USB devices 10 + 11 + from . import base 12 + import pytest 13 + import logging 14 + 15 + logger = logging.getLogger("hidtools.test.usb") 16 + 17 + 18 + class USBDev(base.UHIDTestDevice): 19 + # fmt: off 20 + report_descriptor = [ 21 + 0x05, 0x01, # .Usage Page (Generic Desktop) 0 22 + 0x09, 0x02, # .Usage (Mouse) 2 23 + 0xa1, 0x01, # .Collection (Application) 4 24 + 0x09, 0x02, # ..Usage (Mouse) 6 25 + 0xa1, 0x02, # ..Collection (Logical) 8 26 + 0x09, 0x01, # ...Usage (Pointer) 10 27 + 0xa1, 0x00, # ...Collection (Physical) 12 28 + 0x05, 0x09, # ....Usage Page (Button) 14 29 + 0x19, 0x01, # ....Usage Minimum (1) 16 30 + 0x29, 0x03, # ....Usage Maximum (3) 18 31 + 0x15, 0x00, # ....Logical Minimum (0) 20 32 + 0x25, 0x01, # ....Logical Maximum (1) 22 33 + 0x75, 0x01, # ....Report Size (1) 24 34 + 0x95, 0x03, # ....Report Count (3) 26 35 + 0x81, 0x02, # ....Input (Data,Var,Abs) 28 36 + 0x75, 0x05, # ....Report Size (5) 30 37 + 0x95, 0x01, # ....Report Count (1) 32 38 + 0x81, 0x03, # ....Input (Cnst,Var,Abs) 34 39 + 0x05, 0x01, # ....Usage Page (Generic Desktop) 36 40 + 0x09, 0x30, # ....Usage (X) 38 41 + 0x09, 0x31, # ....Usage (Y) 40 42 + 0x15, 0x81, # ....Logical Minimum (-127) 42 43 + 0x25, 0x7f, # ....Logical Maximum (127) 44 44 + 0x75, 0x08, # ....Report Size (8) 46 45 + 0x95, 0x02, # ....Report Count (2) 48 46 + 0x81, 0x06, # ....Input (Data,Var,Rel) 50 47 + 0xc0, # ...End Collection 52 48 + 0xc0, # ..End Collection 53 49 + 0xc0, # .End Collection 54 50 + ] 51 + # fmt: on 52 + 53 + def __init__(self, name=None, input_info=None): 54 + super().__init__( 55 + name, "Mouse", input_info=input_info, rdesc=USBDev.report_descriptor 56 + ) 57 + 58 + # skip witing for udev events, it's likely that the report 59 + # descriptor is wrong 60 + def is_ready(self): 61 + return True 62 + 63 + # we don't have an evdev node here, so paper over 64 + # the checks 65 + def get_evdev(self, application=None): 66 + return "OK" 67 + 68 + 69 + class TestUSBDevice(base.BaseTestCase.TestUhid): 70 + """ 71 + Test class to test if an emulated USB device crashes 72 + the kernel. 73 + """ 74 + 75 + # conftest.py is generating the following fixture: 76 + # 77 + # @pytest.fixture(params=[('modulename', 1, 2)]) 78 + # def usbVidPid(self, request): 79 + # return request.param 80 + 81 + @pytest.fixture() 82 + def new_uhdev(self, usbVidPid, request): 83 + self.module, self.vid, self.pid = usbVidPid 84 + self._load_kernel_module(None, self.module) 85 + return USBDev(input_info=(3, self.vid, self.pid)) 86 + 87 + def test_creation(self): 88 + """ 89 + inject the USB dev through uhid and immediately see if there is a crash: 90 + 91 + uhid can create a USB device with the BUS_USB bus, and some 92 + drivers assume that they can then access USB related structures 93 + when they are actually provided a uhid device. This leads to 94 + a crash because those access result in a segmentation fault. 95 + 96 + The kernel should not crash on any (random) user space correct 97 + use of its API. So run through all available modules and declared 98 + devices to see if we can generate a uhid device without a crash. 99 + 100 + The test is empty as the fixture `check_taint` is doing the job (and 101 + honestly, when the kernel crashes, the whole machine freezes). 102 + """ 103 + assert True
+844
tools/testing/selftests/hid/tests/test_wacom_generic.py
··· 1 + #!/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + # -*- coding: utf-8 -*- 4 + # 5 + # Copyright (c) 2017 Benjamin Tissoires <benjamin.tissoires@gmail.com> 6 + # Copyright (c) 2017 Red Hat, Inc. 7 + # Copyright (c) 2020 Wacom Technology Corp. 8 + # 9 + # Authors: 10 + # Jason Gerecke <jason.gerecke@wacom.com> 11 + 12 + """ 13 + Tests for the Wacom driver generic codepath. 14 + 15 + This module tests the function of the Wacom driver's generic codepath. 16 + The generic codepath is used by devices which are not explicitly listed 17 + in the driver's device table. It uses the device's HID descriptor to 18 + decode reports sent by the device. 19 + """ 20 + 21 + from .descriptors_wacom import ( 22 + wacom_pth660_v145, 23 + wacom_pth660_v150, 24 + wacom_pth860_v145, 25 + wacom_pth860_v150, 26 + wacom_pth460_v105, 27 + ) 28 + 29 + import attr 30 + from enum import Enum 31 + from hidtools.hut import HUT 32 + from hidtools.hid import HidUnit 33 + from . import base 34 + import libevdev 35 + import pytest 36 + 37 + import logging 38 + 39 + logger = logging.getLogger("hidtools.test.wacom") 40 + 41 + KERNEL_MODULE = ("wacom", "wacom") 42 + 43 + 44 + class ProximityState(Enum): 45 + """ 46 + Enumeration of allowed proximity states. 47 + """ 48 + 49 + # Tool is not able to be sensed by the device 50 + OUT = 0 51 + 52 + # Tool is close enough to be sensed, but some data may be invalid 53 + # or inaccurate 54 + IN_PROXIMITY = 1 55 + 56 + # Tool is close enough to be sensed with high accuracy. All data 57 + # valid. 58 + IN_RANGE = 2 59 + 60 + def fill(self, reportdata): 61 + """Fill a report with approrpiate HID properties/values.""" 62 + reportdata.inrange = self in [ProximityState.IN_RANGE] 63 + reportdata.wacomsense = self in [ 64 + ProximityState.IN_PROXIMITY, 65 + ProximityState.IN_RANGE, 66 + ] 67 + 68 + 69 + class ReportData: 70 + """ 71 + Placeholder for HID report values. 72 + """ 73 + 74 + pass 75 + 76 + 77 + @attr.s 78 + class Buttons: 79 + """ 80 + Stylus button state. 81 + 82 + Describes the state of each of the buttons / "side switches" that 83 + may be present on a stylus. Buttons set to 'None' indicate the 84 + state is "unchanged" since the previous event. 85 + """ 86 + 87 + primary = attr.ib(default=None) 88 + secondary = attr.ib(default=None) 89 + tertiary = attr.ib(default=None) 90 + 91 + @staticmethod 92 + def clear(): 93 + """Button object with all states cleared.""" 94 + return Buttons(False, False, False) 95 + 96 + def fill(self, reportdata): 97 + """Fill a report with approrpiate HID properties/values.""" 98 + reportdata.barrelswitch = int(self.primary or 0) 99 + reportdata.secondarybarrelswitch = int(self.secondary or 0) 100 + reportdata.b3 = int(self.tertiary or 0) 101 + 102 + 103 + @attr.s 104 + class ToolID: 105 + """ 106 + Stylus tool identifiers. 107 + 108 + Contains values used to identify a specific stylus, e.g. its serial 109 + number and tool-type identifier. Values of ``0`` may sometimes be 110 + used for the out-of-range condition. 111 + """ 112 + 113 + serial = attr.ib() 114 + tooltype = attr.ib() 115 + 116 + @staticmethod 117 + def clear(): 118 + """ToolID object with all fields cleared.""" 119 + return ToolID(0, 0) 120 + 121 + def fill(self, reportdata): 122 + """Fill a report with approrpiate HID properties/values.""" 123 + reportdata.transducerserialnumber = self.serial & 0xFFFFFFFF 124 + reportdata.serialhi = (self.serial >> 32) & 0xFFFFFFFF 125 + reportdata.tooltype = self.tooltype 126 + 127 + 128 + @attr.s 129 + class PhysRange: 130 + """ 131 + Range of HID physical values, with units. 132 + """ 133 + 134 + unit = attr.ib() 135 + min_size = attr.ib() 136 + max_size = attr.ib() 137 + 138 + CENTIMETER = HidUnit.from_string("SILinear: cm") 139 + DEGREE = HidUnit.from_string("EnglishRotation: deg") 140 + 141 + def contains(self, field): 142 + """ 143 + Check if the physical size of the provided field is in range. 144 + 145 + Compare the physical size described by the provided HID field 146 + against the range of sizes described by this object. This is 147 + an exclusive range comparison (e.g. 0 cm is not within the 148 + range 0 cm - 5 cm) and exact unit comparison (e.g. 1 inch is 149 + not within the range 0 cm - 5 cm). 150 + """ 151 + phys_size = (field.physical_max - field.physical_min) * 10 ** (field.unit_exp) 152 + return ( 153 + field.unit == self.unit.value 154 + and phys_size > self.min_size 155 + and phys_size < self.max_size 156 + ) 157 + 158 + 159 + class BaseTablet(base.UHIDTestDevice): 160 + """ 161 + Skeleton object for all kinds of tablet devices. 162 + """ 163 + 164 + def __init__(self, rdesc, name=None, info=None): 165 + assert rdesc is not None 166 + super().__init__(name, "Pen", input_info=info, rdesc=rdesc) 167 + self.buttons = Buttons.clear() 168 + self.toolid = ToolID.clear() 169 + self.proximity = ProximityState.OUT 170 + self.offset = 0 171 + self.ring = -1 172 + self.ek0 = False 173 + 174 + def match_evdev_rule(self, application, evdev): 175 + """ 176 + Filter out evdev nodes based on the requested application. 177 + 178 + The Wacom driver may create several device nodes for each USB 179 + interface device. It is crucial that we run tests with the 180 + expected device node or things will obviously go off the rails. 181 + Use the Wacom driver's usual naming conventions to apply a 182 + sensible default filter. 183 + """ 184 + if application in ["Pen", "Pad"]: 185 + return evdev.name.endswith(application) 186 + else: 187 + return True 188 + 189 + def create_report( 190 + self, x, y, pressure, buttons=None, toolid=None, proximity=None, reportID=None 191 + ): 192 + """ 193 + Return an input report for this device. 194 + 195 + :param x: absolute x 196 + :param y: absolute y 197 + :param pressure: pressure 198 + :param buttons: stylus button state. Use ``None`` for unchanged. 199 + :param toolid: tool identifiers. Use ``None`` for unchanged. 200 + :param proximity: a ProximityState indicating the sensor's ability 201 + to detect and report attributes of this tool. Use ``None`` 202 + for unchanged. 203 + :param reportID: the numeric report ID for this report, if needed 204 + """ 205 + if buttons is not None: 206 + self.buttons = buttons 207 + buttons = self.buttons 208 + 209 + if toolid is not None: 210 + self.toolid = toolid 211 + toolid = self.toolid 212 + 213 + if proximity is not None: 214 + self.proximity = proximity 215 + proximity = self.proximity 216 + 217 + reportID = reportID or self.default_reportID 218 + 219 + report = ReportData() 220 + report.x = x 221 + report.y = y 222 + report.tippressure = pressure 223 + report.tipswitch = pressure > 0 224 + buttons.fill(report) 225 + proximity.fill(report) 226 + toolid.fill(report) 227 + 228 + return super().create_report(report, reportID=reportID) 229 + 230 + def create_report_heartbeat(self, reportID): 231 + """ 232 + Return a heartbeat input report for this device. 233 + 234 + Heartbeat reports generally contain battery status information, 235 + among other things. 236 + """ 237 + report = ReportData() 238 + report.wacombatterycharging = 1 239 + return super().create_report(report, reportID=reportID) 240 + 241 + def create_report_pad(self, reportID, ring, ek0): 242 + report = ReportData() 243 + 244 + if ring is not None: 245 + self.ring = ring 246 + ring = self.ring 247 + 248 + if ek0 is not None: 249 + self.ek0 = ek0 250 + ek0 = self.ek0 251 + 252 + if ring >= 0: 253 + report.wacomtouchring = ring 254 + report.wacomtouchringstatus = 1 255 + else: 256 + report.wacomtouchring = 0x7F 257 + report.wacomtouchringstatus = 0 258 + 259 + report.wacomexpresskey00 = ek0 260 + return super().create_report(report, reportID=reportID) 261 + 262 + def event(self, x, y, pressure, buttons=None, toolid=None, proximity=None): 263 + """ 264 + Send an input event on the default report ID. 265 + 266 + :param x: absolute x 267 + :param y: absolute y 268 + :param buttons: stylus button state. Use ``None`` for unchanged. 269 + :param toolid: tool identifiers. Use ``None`` for unchanged. 270 + :param proximity: a ProximityState indicating the sensor's ability 271 + to detect and report attributes of this tool. Use ``None`` 272 + for unchanged. 273 + """ 274 + r = self.create_report(x, y, pressure, buttons, toolid, proximity) 275 + self.call_input_event(r) 276 + return [r] 277 + 278 + def event_heartbeat(self, reportID): 279 + """ 280 + Send a heartbeat event on the requested report ID. 281 + """ 282 + r = self.create_report_heartbeat(reportID) 283 + self.call_input_event(r) 284 + return [r] 285 + 286 + def event_pad(self, reportID, ring=None, ek0=None): 287 + """ 288 + Send a pad event on the requested report ID. 289 + """ 290 + r = self.create_report_pad(reportID, ring, ek0) 291 + self.call_input_event(r) 292 + return [r] 293 + 294 + def get_report(self, req, rnum, rtype): 295 + if rtype != self.UHID_FEATURE_REPORT: 296 + return (1, []) 297 + 298 + rdesc = None 299 + for v in self.parsed_rdesc.feature_reports.values(): 300 + if v.report_ID == rnum: 301 + rdesc = v 302 + 303 + if rdesc is None: 304 + return (1, []) 305 + 306 + result = (1, []) 307 + result = self.create_report_offset(rdesc) or result 308 + return result 309 + 310 + def create_report_offset(self, rdesc): 311 + require = [ 312 + "Wacom Offset Left", 313 + "Wacom Offset Top", 314 + "Wacom Offset Right", 315 + "Wacom Offset Bottom", 316 + ] 317 + if not set(require).issubset(set([f.usage_name for f in rdesc])): 318 + return None 319 + 320 + report = ReportData() 321 + report.wacomoffsetleft = self.offset 322 + report.wacomoffsettop = self.offset 323 + report.wacomoffsetright = self.offset 324 + report.wacomoffsetbottom = self.offset 325 + r = rdesc.create_report([report], None) 326 + return (0, r) 327 + 328 + 329 + class OpaqueTablet(BaseTablet): 330 + """ 331 + Bare-bones opaque tablet with a minimum of features. 332 + 333 + A tablet stripped down to its absolute core. It is capable of 334 + reporting X/Y position and if the pen is in contact. No pressure, 335 + no barrel switches, no eraser. Notably it *does* report an "In 336 + Range" flag, but this is only because the Wacom driver expects 337 + one to function properly. The device uses only standard HID usages, 338 + not any of Wacom's vendor-defined pages. 339 + """ 340 + 341 + # fmt: off 342 + report_descriptor = [ 343 + 0x05, 0x0D, # . Usage Page (Digitizer), 344 + 0x09, 0x01, # . Usage (Digitizer), 345 + 0xA1, 0x01, # . Collection (Application), 346 + 0x85, 0x01, # . Report ID (1), 347 + 0x09, 0x20, # . Usage (Stylus), 348 + 0xA1, 0x00, # . Collection (Physical), 349 + 0x09, 0x42, # . Usage (Tip Switch), 350 + 0x09, 0x32, # . Usage (In Range), 351 + 0x15, 0x00, # . Logical Minimum (0), 352 + 0x25, 0x01, # . Logical Maximum (1), 353 + 0x75, 0x01, # . Report Size (1), 354 + 0x95, 0x02, # . Report Count (2), 355 + 0x81, 0x02, # . Input (Variable), 356 + 0x95, 0x06, # . Report Count (6), 357 + 0x81, 0x03, # . Input (Constant, Variable), 358 + 0x05, 0x01, # . Usage Page (Desktop), 359 + 0x09, 0x30, # . Usage (X), 360 + 0x27, 0x80, 0x3E, 0x00, 0x00, # . Logical Maximum (16000), 361 + 0x47, 0x80, 0x3E, 0x00, 0x00, # . Physical Maximum (16000), 362 + 0x65, 0x11, # . Unit (Centimeter), 363 + 0x55, 0x0D, # . Unit Exponent (13), 364 + 0x75, 0x10, # . Report Size (16), 365 + 0x95, 0x01, # . Report Count (1), 366 + 0x81, 0x02, # . Input (Variable), 367 + 0x09, 0x31, # . Usage (Y), 368 + 0x27, 0x28, 0x23, 0x00, 0x00, # . Logical Maximum (9000), 369 + 0x47, 0x28, 0x23, 0x00, 0x00, # . Physical Maximum (9000), 370 + 0x81, 0x02, # . Input (Variable), 371 + 0xC0, # . End Collection, 372 + 0xC0, # . End Collection, 373 + ] 374 + # fmt: on 375 + 376 + def __init__(self, rdesc=report_descriptor, name=None, info=(0x3, 0x056A, 0x9999)): 377 + super().__init__(rdesc, name, info) 378 + self.default_reportID = 1 379 + 380 + 381 + class OpaqueCTLTablet(BaseTablet): 382 + """ 383 + Opaque tablet similar to something in the CTL product line. 384 + 385 + A pen-only tablet with most basic features you would expect from 386 + an actual device. Position, eraser, pressure, barrel buttons. 387 + Uses the Wacom vendor-defined usage page. 388 + """ 389 + 390 + # fmt: off 391 + report_descriptor = [ 392 + 0x06, 0x0D, 0xFF, # . Usage Page (Vnd Wacom Emr), 393 + 0x09, 0x01, # . Usage (Digitizer), 394 + 0xA1, 0x01, # . Collection (Application), 395 + 0x85, 0x10, # . Report ID (16), 396 + 0x09, 0x20, # . Usage (Stylus), 397 + 0x35, 0x00, # . Physical Minimum (0), 398 + 0x45, 0x00, # . Physical Maximum (0), 399 + 0x15, 0x00, # . Logical Minimum (0), 400 + 0x25, 0x01, # . Logical Maximum (1), 401 + 0xA1, 0x00, # . Collection (Physical), 402 + 0x09, 0x42, # . Usage (Tip Switch), 403 + 0x09, 0x44, # . Usage (Barrel Switch), 404 + 0x09, 0x5A, # . Usage (Secondary Barrel Switch), 405 + 0x09, 0x45, # . Usage (Eraser), 406 + 0x09, 0x3C, # . Usage (Invert), 407 + 0x09, 0x32, # . Usage (In Range), 408 + 0x09, 0x36, # . Usage (In Proximity), 409 + 0x25, 0x01, # . Logical Maximum (1), 410 + 0x75, 0x01, # . Report Size (1), 411 + 0x95, 0x07, # . Report Count (7), 412 + 0x81, 0x02, # . Input (Variable), 413 + 0x95, 0x01, # . Report Count (1), 414 + 0x81, 0x03, # . Input (Constant, Variable), 415 + 0x0A, 0x30, 0x01, # . Usage (X), 416 + 0x65, 0x11, # . Unit (Centimeter), 417 + 0x55, 0x0D, # . Unit Exponent (13), 418 + 0x47, 0x80, 0x3E, 0x00, 0x00, # . Physical Maximum (16000), 419 + 0x27, 0x80, 0x3E, 0x00, 0x00, # . Logical Maximum (16000), 420 + 0x75, 0x18, # . Report Size (24), 421 + 0x95, 0x01, # . Report Count (1), 422 + 0x81, 0x02, # . Input (Variable), 423 + 0x0A, 0x31, 0x01, # . Usage (Y), 424 + 0x47, 0x28, 0x23, 0x00, 0x00, # . Physical Maximum (9000), 425 + 0x27, 0x28, 0x23, 0x00, 0x00, # . Logical Maximum (9000), 426 + 0x81, 0x02, # . Input (Variable), 427 + 0x09, 0x30, # . Usage (Tip Pressure), 428 + 0x55, 0x00, # . Unit Exponent (0), 429 + 0x65, 0x00, # . Unit, 430 + 0x47, 0x00, 0x00, 0x00, 0x00, # . Physical Maximum (0), 431 + 0x26, 0xFF, 0x0F, # . Logical Maximum (4095), 432 + 0x75, 0x10, # . Report Size (16), 433 + 0x81, 0x02, # . Input (Variable), 434 + 0x75, 0x08, # . Report Size (8), 435 + 0x95, 0x06, # . Report Count (6), 436 + 0x81, 0x03, # . Input (Constant, Variable), 437 + 0x0A, 0x32, 0x01, # . Usage (Z), 438 + 0x25, 0x3F, # . Logical Maximum (63), 439 + 0x75, 0x08, # . Report Size (8), 440 + 0x95, 0x01, # . Report Count (1), 441 + 0x81, 0x02, # . Input (Variable), 442 + 0x09, 0x5B, # . Usage (Transducer Serial Number), 443 + 0x09, 0x5C, # . Usage (Transducer Serial Number Hi), 444 + 0x17, 0x00, 0x00, 0x00, 0x80, # . Logical Minimum (-2147483648), 445 + 0x27, 0xFF, 0xFF, 0xFF, 0x7F, # . Logical Maximum (2147483647), 446 + 0x75, 0x20, # . Report Size (32), 447 + 0x95, 0x02, # . Report Count (2), 448 + 0x81, 0x02, # . Input (Variable), 449 + 0x09, 0x77, # . Usage (Tool Type), 450 + 0x15, 0x00, # . Logical Minimum (0), 451 + 0x26, 0xFF, 0x0F, # . Logical Maximum (4095), 452 + 0x75, 0x10, # . Report Size (16), 453 + 0x95, 0x01, # . Report Count (1), 454 + 0x81, 0x02, # . Input (Variable), 455 + 0xC0, # . End Collection, 456 + 0xC0 # . End Collection 457 + ] 458 + # fmt: on 459 + 460 + def __init__(self, rdesc=report_descriptor, name=None, info=(0x3, 0x056A, 0x9999)): 461 + super().__init__(rdesc, name, info) 462 + self.default_reportID = 16 463 + 464 + 465 + class PTHX60_Pen(BaseTablet): 466 + """ 467 + Pen interface of a PTH-660 / PTH-860 / PTH-460 tablet. 468 + 469 + This generation of devices are nearly identical to each other, though 470 + the PTH-460 uses a slightly different descriptor construction (splits 471 + the pad among several physical collections) 472 + """ 473 + 474 + def __init__(self, rdesc=None, name=None, info=None): 475 + super().__init__(rdesc, name, info) 476 + self.default_reportID = 16 477 + 478 + 479 + class BaseTest: 480 + class TestTablet(base.BaseTestCase.TestUhid): 481 + kernel_modules = [KERNEL_MODULE] 482 + 483 + def sync_and_assert_events( 484 + self, report, expected_events, auto_syn=True, strict=False 485 + ): 486 + """ 487 + Assert we see the expected events in response to a report. 488 + """ 489 + uhdev = self.uhdev 490 + syn_event = self.syn_event 491 + if auto_syn: 492 + expected_events.append(syn_event) 493 + actual_events = uhdev.next_sync_events() 494 + self.debug_reports(report, uhdev, actual_events) 495 + if strict: 496 + self.assertInputEvents(expected_events, actual_events) 497 + else: 498 + self.assertInputEventsIn(expected_events, actual_events) 499 + 500 + def get_usages(self, uhdev): 501 + def get_report_usages(report): 502 + application = report.application 503 + for field in report.fields: 504 + if field.usages is not None: 505 + for usage in field.usages: 506 + yield (field, usage, application) 507 + else: 508 + yield (field, field.usage, application) 509 + 510 + desc = uhdev.parsed_rdesc 511 + reports = [ 512 + *desc.input_reports.values(), 513 + *desc.feature_reports.values(), 514 + *desc.output_reports.values(), 515 + ] 516 + for report in reports: 517 + for usage in get_report_usages(report): 518 + yield usage 519 + 520 + def assertName(self, uhdev): 521 + """ 522 + Assert that the name is as we expect. 523 + 524 + The Wacom driver applies a number of decorations to the name 525 + provided by the hardware. We cannot rely on the definition of 526 + this assertion from the base class to work properly. 527 + """ 528 + evdev = uhdev.get_evdev() 529 + expected_name = uhdev.name + " Pen" 530 + if "wacom" not in expected_name.lower(): 531 + expected_name = "Wacom " + expected_name 532 + assert evdev.name == expected_name 533 + 534 + def test_descriptor_physicals(self): 535 + """ 536 + Verify that all HID usages which should have a physical range 537 + actually do, and those which shouldn't don't. Also verify that 538 + the associated unit is correct and within a sensible range. 539 + """ 540 + 541 + def usage_id(page_name, usage_name): 542 + page = HUT.usage_page_from_name(page_name) 543 + return (page.page_id << 16) | page[usage_name].usage 544 + 545 + required = { 546 + usage_id("Generic Desktop", "X"): PhysRange( 547 + PhysRange.CENTIMETER, 5, 150 548 + ), 549 + usage_id("Generic Desktop", "Y"): PhysRange( 550 + PhysRange.CENTIMETER, 5, 150 551 + ), 552 + usage_id("Digitizers", "X Tilt"): PhysRange(PhysRange.DEGREE, 90, 180), 553 + usage_id("Digitizers", "Y Tilt"): PhysRange(PhysRange.DEGREE, 90, 180), 554 + usage_id("Digitizers", "Twist"): PhysRange(PhysRange.DEGREE, 358, 360), 555 + usage_id("Wacom", "X Tilt"): PhysRange(PhysRange.DEGREE, 90, 180), 556 + usage_id("Wacom", "Y Tilt"): PhysRange(PhysRange.DEGREE, 90, 180), 557 + usage_id("Wacom", "Twist"): PhysRange(PhysRange.DEGREE, 358, 360), 558 + usage_id("Wacom", "X"): PhysRange(PhysRange.CENTIMETER, 5, 150), 559 + usage_id("Wacom", "Y"): PhysRange(PhysRange.CENTIMETER, 5, 150), 560 + usage_id("Wacom", "Wacom TouchRing"): PhysRange( 561 + PhysRange.DEGREE, 358, 360 562 + ), 563 + usage_id("Wacom", "Wacom Offset Left"): PhysRange( 564 + PhysRange.CENTIMETER, 0, 0.5 565 + ), 566 + usage_id("Wacom", "Wacom Offset Top"): PhysRange( 567 + PhysRange.CENTIMETER, 0, 0.5 568 + ), 569 + usage_id("Wacom", "Wacom Offset Right"): PhysRange( 570 + PhysRange.CENTIMETER, 0, 0.5 571 + ), 572 + usage_id("Wacom", "Wacom Offset Bottom"): PhysRange( 573 + PhysRange.CENTIMETER, 0, 0.5 574 + ), 575 + } 576 + for field, usage, application in self.get_usages(self.uhdev): 577 + if application == usage_id("Generic Desktop", "Mouse"): 578 + # Ignore the vestigial Mouse collection which exists 579 + # on Wacom tablets only for backwards compatibility. 580 + continue 581 + 582 + expect_physical = usage in required 583 + 584 + phys_set = field.physical_min != 0 or field.physical_max != 0 585 + assert phys_set == expect_physical 586 + 587 + unit_set = field.unit != 0 588 + assert unit_set == expect_physical 589 + 590 + if unit_set: 591 + assert required[usage].contains(field) 592 + 593 + def test_prop_direct(self): 594 + """ 595 + Todo: Verify that INPUT_PROP_DIRECT is set on display devices. 596 + """ 597 + pass 598 + 599 + def test_prop_pointer(self): 600 + """ 601 + Todo: Verify that INPUT_PROP_POINTER is set on opaque devices. 602 + """ 603 + pass 604 + 605 + 606 + class TestOpaqueTablet(BaseTest.TestTablet): 607 + def create_device(self): 608 + return OpaqueTablet() 609 + 610 + def test_sanity(self): 611 + """ 612 + Bring a pen into contact with the tablet, then remove it. 613 + 614 + Ensure that we get the basic tool/touch/motion events that should 615 + be sent by the driver. 616 + """ 617 + uhdev = self.uhdev 618 + 619 + self.sync_and_assert_events( 620 + uhdev.event( 621 + 100, 622 + 200, 623 + pressure=300, 624 + buttons=Buttons.clear(), 625 + toolid=ToolID(serial=1, tooltype=1), 626 + proximity=ProximityState.IN_RANGE, 627 + ), 628 + [ 629 + libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN, 1), 630 + libevdev.InputEvent(libevdev.EV_ABS.ABS_X, 100), 631 + libevdev.InputEvent(libevdev.EV_ABS.ABS_Y, 200), 632 + libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1), 633 + ], 634 + ) 635 + 636 + self.sync_and_assert_events( 637 + uhdev.event(110, 220, pressure=0), 638 + [ 639 + libevdev.InputEvent(libevdev.EV_ABS.ABS_X, 110), 640 + libevdev.InputEvent(libevdev.EV_ABS.ABS_Y, 220), 641 + libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 0), 642 + ], 643 + ) 644 + 645 + self.sync_and_assert_events( 646 + uhdev.event( 647 + 120, 648 + 230, 649 + pressure=0, 650 + toolid=ToolID.clear(), 651 + proximity=ProximityState.OUT, 652 + ), 653 + [ 654 + libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN, 0), 655 + ], 656 + ) 657 + 658 + self.sync_and_assert_events( 659 + uhdev.event(130, 240, pressure=0), [], auto_syn=False, strict=True 660 + ) 661 + 662 + 663 + class TestOpaqueCTLTablet(TestOpaqueTablet): 664 + def create_device(self): 665 + return OpaqueCTLTablet() 666 + 667 + def test_buttons(self): 668 + """ 669 + Test that the barrel buttons (side switches) work as expected. 670 + 671 + Press and release each button individually to verify that we get 672 + the expected events. 673 + """ 674 + uhdev = self.uhdev 675 + 676 + self.sync_and_assert_events( 677 + uhdev.event( 678 + 100, 679 + 200, 680 + pressure=0, 681 + buttons=Buttons.clear(), 682 + toolid=ToolID(serial=1, tooltype=1), 683 + proximity=ProximityState.IN_RANGE, 684 + ), 685 + [ 686 + libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN, 1), 687 + libevdev.InputEvent(libevdev.EV_ABS.ABS_X, 100), 688 + libevdev.InputEvent(libevdev.EV_ABS.ABS_Y, 200), 689 + libevdev.InputEvent(libevdev.EV_MSC.MSC_SERIAL, 1), 690 + ], 691 + ) 692 + 693 + self.sync_and_assert_events( 694 + uhdev.event(100, 200, pressure=0, buttons=Buttons(primary=True)), 695 + [ 696 + libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS, 1), 697 + libevdev.InputEvent(libevdev.EV_MSC.MSC_SERIAL, 1), 698 + ], 699 + ) 700 + 701 + self.sync_and_assert_events( 702 + uhdev.event(100, 200, pressure=0, buttons=Buttons(primary=False)), 703 + [ 704 + libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS, 0), 705 + libevdev.InputEvent(libevdev.EV_MSC.MSC_SERIAL, 1), 706 + ], 707 + ) 708 + 709 + self.sync_and_assert_events( 710 + uhdev.event(100, 200, pressure=0, buttons=Buttons(secondary=True)), 711 + [ 712 + libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS2, 1), 713 + libevdev.InputEvent(libevdev.EV_MSC.MSC_SERIAL, 1), 714 + ], 715 + ) 716 + 717 + self.sync_and_assert_events( 718 + uhdev.event(100, 200, pressure=0, buttons=Buttons(secondary=False)), 719 + [ 720 + libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS2, 0), 721 + libevdev.InputEvent(libevdev.EV_MSC.MSC_SERIAL, 1), 722 + ], 723 + ) 724 + 725 + 726 + PTHX60_Devices = [ 727 + {"rdesc": wacom_pth660_v145, "info": (0x3, 0x056A, 0x0357)}, 728 + {"rdesc": wacom_pth660_v150, "info": (0x3, 0x056A, 0x0357)}, 729 + {"rdesc": wacom_pth860_v145, "info": (0x3, 0x056A, 0x0358)}, 730 + {"rdesc": wacom_pth860_v150, "info": (0x3, 0x056A, 0x0358)}, 731 + {"rdesc": wacom_pth460_v105, "info": (0x3, 0x056A, 0x0392)}, 732 + ] 733 + 734 + PTHX60_Names = [ 735 + "PTH-660/v145", 736 + "PTH-660/v150", 737 + "PTH-860/v145", 738 + "PTH-860/v150", 739 + "PTH-460/v105", 740 + ] 741 + 742 + 743 + class TestPTHX60_Pen(TestOpaqueCTLTablet): 744 + @pytest.fixture( 745 + autouse=True, scope="class", params=PTHX60_Devices, ids=PTHX60_Names 746 + ) 747 + def set_device_params(self, request): 748 + request.cls.device_params = request.param 749 + 750 + def create_device(self): 751 + return PTHX60_Pen(**self.device_params) 752 + 753 + @pytest.mark.xfail 754 + def test_descriptor_physicals(self): 755 + # XFAIL: Various documented errata 756 + super().test_descriptor_physicals() 757 + 758 + def test_heartbeat_spurious(self): 759 + """ 760 + Test that the heartbeat report does not send spurious events. 761 + """ 762 + uhdev = self.uhdev 763 + 764 + self.sync_and_assert_events( 765 + uhdev.event( 766 + 100, 767 + 200, 768 + pressure=300, 769 + buttons=Buttons.clear(), 770 + toolid=ToolID(serial=1, tooltype=0x822), 771 + proximity=ProximityState.IN_RANGE, 772 + ), 773 + [ 774 + libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN, 1), 775 + libevdev.InputEvent(libevdev.EV_ABS.ABS_X, 100), 776 + libevdev.InputEvent(libevdev.EV_ABS.ABS_Y, 200), 777 + libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1), 778 + ], 779 + ) 780 + 781 + # Exactly zero events: not even a SYN 782 + self.sync_and_assert_events( 783 + uhdev.event_heartbeat(19), [], auto_syn=False, strict=True 784 + ) 785 + 786 + self.sync_and_assert_events( 787 + uhdev.event(110, 200, pressure=300), 788 + [ 789 + libevdev.InputEvent(libevdev.EV_ABS.ABS_X, 110), 790 + ], 791 + ) 792 + 793 + def test_empty_pad_sync(self): 794 + self.empty_pad_sync(num=3, denom=16, reverse=True) 795 + 796 + def empty_pad_sync(self, num, denom, reverse): 797 + """ 798 + Test that multiple pad collections do not trigger empty syncs. 799 + """ 800 + 801 + def offset_rotation(value): 802 + """ 803 + Offset touchring rotation values by the same factor as the 804 + Linux kernel. Tablets historically don't use the same origin 805 + as HID, and it sometimes changes from tablet to tablet... 806 + """ 807 + evdev = self.uhdev.get_evdev() 808 + info = evdev.absinfo[libevdev.EV_ABS.ABS_WHEEL] 809 + delta = info.maximum - info.minimum + 1 810 + if reverse: 811 + value = info.maximum - value 812 + value += num * delta // denom 813 + if value > info.maximum: 814 + value -= delta 815 + elif value < info.minimum: 816 + value += delta 817 + return value 818 + 819 + uhdev = self.uhdev 820 + uhdev.application = "Pad" 821 + evdev = uhdev.get_evdev() 822 + 823 + print(evdev.name) 824 + self.sync_and_assert_events( 825 + uhdev.event_pad(reportID=17, ring=0, ek0=1), 826 + [ 827 + libevdev.InputEvent(libevdev.EV_KEY.BTN_0, 1), 828 + libevdev.InputEvent(libevdev.EV_ABS.ABS_WHEEL, offset_rotation(0)), 829 + libevdev.InputEvent(libevdev.EV_ABS.ABS_MISC, 15), 830 + ], 831 + ) 832 + 833 + self.sync_and_assert_events( 834 + uhdev.event_pad(reportID=17, ring=1, ek0=1), 835 + [libevdev.InputEvent(libevdev.EV_ABS.ABS_WHEEL, offset_rotation(1))], 836 + ) 837 + 838 + self.sync_and_assert_events( 839 + uhdev.event_pad(reportID=17, ring=2, ek0=0), 840 + [ 841 + libevdev.InputEvent(libevdev.EV_ABS.ABS_WHEEL, offset_rotation(2)), 842 + libevdev.InputEvent(libevdev.EV_KEY.BTN_0, 0), 843 + ], 844 + )
+15 -10
tools/testing/selftests/hid/vmtest.sh
··· 16 16 exit 1 17 17 ;; 18 18 esac 19 - DEFAULT_COMMAND="./hid_bpf" 20 19 SCRIPT_DIR="$(dirname $(realpath $0))" 21 20 OUTPUT_DIR="$SCRIPT_DIR/results" 22 21 KCONFIG_REL_PATHS=("${SCRIPT_DIR}/config" "${SCRIPT_DIR}/config.common" "${SCRIPT_DIR}/config.${ARCH}") ··· 24 25 LOG_FILE_BASE="$(date +"hid_selftests.%Y-%m-%d_%H-%M-%S")" 25 26 LOG_FILE="${LOG_FILE_BASE}.log" 26 27 EXIT_STATUS_FILE="${LOG_FILE_BASE}.exit_status" 27 - CONTAINER_IMAGE="registry.fedoraproject.org/fedora:36" 28 + CONTAINER_IMAGE="registry.freedesktop.org/libevdev/hid-tools/fedora/37:2023-02-17.1" 29 + 30 + TARGETS="${TARGETS:=$(basename ${SCRIPT_DIR})}" 31 + DEFAULT_COMMAND="pip3 install hid-tools; make -C tools/testing/selftests TARGETS=${TARGETS} run_tests" 28 32 29 33 usage() 30 34 { ··· 35 33 Usage: $0 [-i] [-s] [-d <output_dir>] -- [<command>] 36 34 37 35 <command> is the command you would normally run when you are in 38 - tools/testing/selftests/bpf. e.g: 36 + the source kernel direcory. e.g: 39 37 40 - $0 -- ./hid_bpf 38 + $0 -- ./tools/testing/selftests/hid/hid_bpf 41 39 42 40 If no command is specified and a debug shell (-s) is not requested, 43 41 "${DEFAULT_COMMAND}" will be run by default. ··· 45 43 If you build your kernel using KBUILD_OUTPUT= or O= options, these 46 44 can be passed as environment variables to the script: 47 45 48 - O=<kernel_build_path> $0 -- ./hid_bpf 46 + O=<kernel_build_path> $0 -- ./tools/testing/selftests/hid/hid_bpf 49 47 50 48 or 51 49 52 - KBUILD_OUTPUT=<kernel_build_path> $0 -- ./hid_bpf 50 + KBUILD_OUTPUT=<kernel_build_path> $0 -- ./tools/testing/selftests/hid/hid_bpf 53 51 54 52 Options: 55 53 ··· 93 91 94 92 run_vm() 95 93 { 96 - local b2c="$1" 97 - local kernel_bzimage="$2" 98 - local command="$3" 94 + local run_dir="$1" 95 + local b2c="$2" 96 + local kernel_bzimage="$3" 97 + local command="$4" 99 98 local post_command="" 99 + 100 + cd "${run_dir}" 100 101 101 102 if ! which "${QEMU_BINARY}" &> /dev/null; then 102 103 cat <<EOF ··· 278 273 fi 279 274 280 275 update_selftests "${kernel_checkout}" "${make_command}" 281 - run_vm $b2c "${kernel_bzimage}" "${command}" 276 + run_vm "${kernel_checkout}" $b2c "${kernel_bzimage}" "${command}" 282 277 if [[ "${debug_shell}" != "yes" ]]; then 283 278 echo "Logs saved in ${OUTPUT_DIR}/${LOG_FILE}" 284 279 fi