libwacom icon indicating copy to clipboard operation
libwacom copied to clipboard

Fixing vendors that re-use USB IDs

Open whot opened this issue 1 year ago • 8 comments

Summary: we need some solution that allows us to match tablets that re-use the USB IDs. Huion, Gaomon and Ugee/XP-Pen seem to be the big offenders here and in some cases we can at least string match on the device name but e.g. #609 shows that's not always possible.

cc @JoseExposito - you've worked on some of these tablets in the kernel, is there anything we can export from the kernel to identify these tablets in userspace? Like stuffing an enum into id_input->version? Or some custom udev property? Or sysfs file?

whot avatar Dec 04 '23 01:12 whot

I did some digging, with uclogic-tools (https://github.com/DIGImend/uclogic-tools) I can read details including the Firmware version off the attached device:

$ sudo uclogic-probe 1 4 | uclogic-decode 
    |           Manufacturer: GAOMON
    |                Product: Gaomon Tablet
 64 |        Params block #1: ???????????????????????????????????????????????????????????????????????????????????????????????????
    |                          Max X: 8192
    |                          Max Y: 357
    |                   Max pressure: 2301
    |                     Resolution: 2048
    |
 79 |         Internal model: ???????????????????????????????????????????????????????????????????????????????????????????????????
 7b |         Buttons status: ???????????????????????????????????????????????????????????????????????????????????????????????????
 c8 |        Params block #2: ??|?????
    |                          Max X: 50800
    |                          Max Y: 31750
    |                   Max pressure: 8191
    |                     Resolution: 5080
    |
 c9 |       Firmware version: OEM02_T19m_200114
 ca |  Internal manufacturer: HUION Animation Technology Co.,ltd

Through the power of binwalk, strings and grep I found a TabletCfg.dt file in a download from the manufacturer that contains JSON data in { "FW_CODE": { "Properties":"values" } } format for 129 firmware codes, 86 of which are unique non-null firmware -> ProductName pairs like:

"OEM02_T19M": {
	"EnablePenKey0": false,
	"IsTouchHKey": false,
	"LED": false,
	"Langs": 131071,
	"MKeyConfig": null,
	"Multimedia": {
		"KeyCount": 0
	},
	"PenKeyCount": 3,
	"ProductName": "M106K PRO",
	"bMultimedia": false,
	"bOSD": false,
	"battery": false,
	"bluetooth": false,
	"dongle": false,
	"hasTitl": false,
	"hkeyNum": 12,
	"isMonitor": false,
	"isTouchMonitor": false,
	"mkeyNum": 0,
	"mouseModel": true,
	"passive": false,
	"penModel": "GM_PW205",
	"skeyNum": 16,
	"wireless": false
},

If we could read the Manufacturer/Product/Internal manufacturer and Firmware version values that uclogic-probe can read off the device, we might just be able to match some devices?

EDIT: kernel does read the firmware version, but doesn't expose it: https://github.com/torvalds/linux/blob/master/drivers/hid/hid-uclogic-params.c#L872 Their ver_ptr is only used to determine if they can go on to probe for other parameters, there are no sysfs_* or kobject references that would be needed for exposure via /sys.

AFAICT, we need a kernel patch, is anyone here friends with GregKH? :D

TacticalCode avatar Dec 04 '23 18:12 TacticalCode

Nice spotting. I wonder if we could just add a new custom uevent for the firmware version? I don't know what the politics are regarding that and/or if the infrastructure is in place.

whot avatar Dec 04 '23 21:12 whot

Through the power of binwalk, strings and grep I found a TabletCfg.dt file in a download from the manufacturer that contains JSON data in { "FW_CODE": { "Properties":"values" } } format for 129 firmware codes, 86 of which are unique non-null firmware -> ProductName pairs

Turns out, HUION ships a JavaScript file with similar contents in their proprietary driver.

Here is my table HUION INSPIROY H640P information:

$ sudo uclogic-probe 3 11 | uclogic-decode
    |           Manufacturer: HUION
    |                Product: Huion Tablet_H640P
 64 |        Params block #1: ???????????????????????????????????????????????????????????????????????????????????????????????????
    |                          Max X: 8192
    |                          Max Y: 357
    |                   Max pressure: 2301
    |                     Resolution: 2048
    |
 79 |         Internal model: ???????????????????????????????????????????????????????????????????????????????????????????????????
 7b |         Buttons status: ???????????????????????????????????????????????????????????????????????????????????????????????????
 c8 |        Params block #2: ??N?????
    |                          Max X: 32000
    |                          Max Y: 20000
    |                   Max pressure: 8191
    |                     Resolution: 5080
    |
 c9 |       Firmware version: HUION_T203_200720
 ca |  Internal manufacturer: HUION Animation Technology Co.,ltd

And, after some grep-ing, I found a file (res/StatuImg.js) that contains:

"HUION_T203": {
  "HBUTTON": {
    "0": "HKey1.png",
    "1": "HKey1.png",
    "2": "HKey1.png",
    "3": "HKey1.png",
    "4": "HKey1.png",
    "5": "HKey1.png"
  },
  "ProductName": "INSPIROY H640P"
}

This JavaScript file contains 79 non-null pairs of firmware + product name. But I guess that other driver downloads might contain similar files (I didn't check it).

For reference, here is the file after some Node.js magic:

Expand
[
  {
    "fw": "HUION_M165",
    "name": "KAMVAS GT-220 V2"
  },
  {
    "fw": "HUION_M167",
    "name": "KAMVAS  GT-221 Pro"
  },
  {
    "fw": "HUION_M168",
    "name": "KAMVAS GT-191"
  },
  {
    "fw": "HUION_M171",
    "name": "KAMVAS Pro 12 GT-116"
  },
  {
    "fw": "HUION_M174",
    "name": "KAMVAS GT-156HD V2"
  },
  {
    "fw": "HUION_M175",
    "name": "KAMVAS Pro 22 GT-221"
  },
  {
    "fw": "HUION_M182",
    "name": "KAMVAS Pro 13 GT-133"
  },
  {
    "fw": "HUION_M183",
    "name": "KAMVAS Pro 16 GT-156"
  },
  {
    "fw": "HUION_M184",
    "name": "KAMVAS Pro 24 GT-240"
  },
  {
    "fw": "HUION_M189",
    "name": "KAMVAS Pro 20 GT-192"
  },
  {
    "fw": "HUION_M18a",
    "name": "KAMVAS GT-191 V2"
  },
  {
    "fw": "HUION_M18e",
    "name": "KAMVAS 16(2019)"
  },
  {
    "fw": "HUION_M192",
    "name": "KAMVAS 20 GS1901"
  },
  {
    "fw": "HUION_M193",
    "name": "KAMVAS Pro 20 GT1901"
  },
  {
    "fw": "HUION_M194",
    "name": "KAMVAS Pro/Studio 22"
  },
  {
    "fw": "HUION_M19e",
    "name": "KAMVAS GT-191 V2"
  },
  {
    "fw": "HUION_M19f",
    "name": "KAMVAS 13 GS1331"
  },
  {
    "fw": "HUION_M19g",
    "name": "KAMVAS 22 GS2201"
  },
  {
    "fw": "HUION_M19p",
    "name": "KAMVAS 12 GS1161"
  },
  {
    "fw": "HUION_M19s",
    "name": "KAMVAS 16 GS1562"
  },
  {
    "fw": "HUION_M19t",
    "name": "KAMVAS 22 GS2202"
  },
  {
    "fw": "HUION_M202",
    "name": "KAMVAS Pro 16 GT1561"
  },
  {
    "fw": "HUION_M205",
    "name": "KAMVAS 24 Plus GS2402"
  },
  {
    "fw": "HUION_M206",
    "name": "KAMVAS 24 GS2401"
  },
  {
    "fw": "HUION_M207",
    "name": "KAMVAS Pro 24 GT2401"
  },
  {
    "fw": "HUION_M20a",
    "name": "KAMVAS Pro 16 Plus GT1562"
  },
  {
    "fw": "HUION_M20h",
    "name": "KAMVAS 13 GS1331"
  },
  {
    "fw": "HUION_M20j",
    "name": "KAMVAS Pro 12 GT-116"
  },
  {
    "fw": "HUION_M20k",
    "name": "KAMVAS Pro 13 GT-133"
  },
  {
    "fw": "HUION_M20m",
    "name": "KAMVAS Pro 16 GT-156"
  },
  {
    "fw": "HUION_M20q",
    "name": "KAMVAS Pro 16 GT1602"
  },
  {
    "fw": "HUION_M20s",
    "name": "KAMVAS 19"
  },
  {
    "fw": "HUION_M20u",
    "name": "KAMVAS GT-156(2021)"
  },
  {
    "fw": "HUION_M20v",
    "name": "KAMVAS GT-156(2021)"
  },
  {
    "fw": "HUION_M210",
    "name": "KAMVAS Pro 13 GT1302"
  },
  {
    "fw": "HUION_M211",
    "name": "Huion RDS-160"
  },
  {
    "fw": "HUION_M213",
    "name": "KAMVAS Pro 13 GT1302"
  },
  {
    "fw": "HUION_M214",
    "name": "KAMVAS Pro 16 GT1602"
  },
  {
    "fw": "HUION_M215",
    "name": "KAMVAS 13 GS1331"
  },
  {
    "fw": "HUION_M216",
    "name": "KAMVAS 13 GS1331"
  },
  {
    "fw": "HUION_M225",
    "name": "Kamvas RDS-220"
  },
  {
    "fw": "HUION_T161",
    "name": "INSPIROY  G10T"
  },
  {
    "fw": "HUION_T164",
    "name": "INSPIROY Q11K"
  },
  {
    "fw": "HUION_T166",
    "name": "Huion GC610/710"
  },
  {
    "fw": "HUION_T167",
    "name": "INSPIROY H1060P"
  },
  {
    "fw": "HUION_T172",
    "name": "INSPIROY H950P"
  },
  {
    "fw": "HUION_T173",
    "name": "INSPIROY H640P"
  },
  {
    "fw": "HUION_T174",
    "name": "INSPIROY NEW 1060 Plus"
  },
  {
    "fw": "HUION_T176",
    "name": "INSPIROY H430P"
  },
  {
    "fw": "HUION_T181",
    "name": "Huion HST640"
  },
  {
    "fw": "HUION_T184",
    "name": "INSPIROY H610PRO V2"
  },
  {
    "fw": "HUION_T185",
    "name": "INSPIROY Q11K V2"
  },
  {
    "fw": "HUION_T188",
    "name": "INSPIROY WH1409 V2"
  },
  {
    "fw": "HUION_T18C",
    "name": "Huion HC16"
  },
  {
    "fw": "HUION_T18a",
    "name": "INSPIROY H430P"
  },
  {
    "fw": "HUION_T18d",
    "name": "INSPIROY Q620M"
  },
  {
    "fw": "HUION_T191",
    "name": "INSPIROY H1161"
  },
  {
    "fw": "HUION_T193",
    "name": "Huion HS64"
  },
  {
    "fw": "HUION_T194",
    "name": "Huion HS610"
  },
  {
    "fw": "HUION_T198",
    "name": "INSPIROY Ink H320M"
  },
  {
    "fw": "HUION_T19c",
    "name": "Huion HS611"
  },
  {
    "fw": "HUION_T19g",
    "name": "Huion RTS-300"
  },
  {
    "fw": "HUION_T19h",
    "name": "Huion RTM-500"
  },
  {
    "fw": "HUION_T19k",
    "name": "Huion RTP-700"
  },
  {
    "fw": "HUION_T203",
    "name": "INSPIROY H640P"
  },
  {
    "fw": "HUION_T204",
    "name": "INSPIROY H950P"
  },
  {
    "fw": "HUION_T205",
    "name": "INSPIROY H1060P"
  },
  {
    "fw": "HUION_T206",
    "name": "Huion HS95"
  },
  {
    "fw": "HUION_T210",
    "name": "INSPIROY H420X"
  },
  {
    "fw": "HUION_T211",
    "name": "INSPIROY H580X"
  },
  {
    "fw": "HUION_T212",
    "name": "INSPIROY H610X"
  },
  {
    "fw": "HUION_T217",
    "name": "Huion RTE-100"
  },
  {
    "fw": "HUION_T218",
    "name": "Huion Note X10"
  },
  {
    "fw": "HUION_T219",
    "name": "INSPIROY H1060P"
  },
  {
    "fw": "HUION_T21a",
    "name": "INSPIROY H950P"
  },
  {
    "fw": "HUION_T21c",
    "name": "INSPIROY H430P"
  },
  {
    "fw": "HUION_T21e",
    "name": "INSPIROY H640P"
  },
  {
    "fw": "HUION_T21f",
    "name": "INSPIROY H950P"
  },
  {
    "fw": "HUION_T21g",
    "name": "INSPIROY H580X"
  }
]

So, it look like if we could access the firmware version from user-space, we'd be able to match the right device for a good number of tablets.

jexposit avatar Dec 05 '23 13:12 jexposit

@jexposit Nice, and your USB ID (lsusb) is 256c:006d too?

I was starting to think that maybe they fixed their device IDs (https://github.com/linuxwacom/libwacom/pull/614#issuecomment-1841426749) But this Huion H640P user also has the same IDs: https://github.com/linuxwacom/wacom-hid-descriptors/issues/322

I think I could hack up a patched hid-uclogic kernel driver to expose the firmware string via sysfs in a week or two as a PoC (but far from merge-able into the kernel), if someone can implement a PoC in libwacom? I'd need to know where to expose it in /sys, directories for the device are currently:

    48414      0 drwxr-xr-x   5 root     root            0 Dez  5 19:27 /sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/0003:256C:006D.0006
    48498      0 drwxr-xr-x   5 root     root            0 Dez  5 19:27 /sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.1/0003:256C:006D.0007
    48502      0 lrwxrwxrwx   1 root     root            0 Dez  5 19:27 /sys/bus/hid/devices/0003:256C:006D.0007 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.1/0003:256C:006D.0007
    48418      0 lrwxrwxrwx   1 root     root            0 Dez  5 19:27 /sys/bus/hid/devices/0003:256C:006D.0006 -> ../../../devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/0003:256C:006D.0006
    48982      0 lrwxrwxrwx   1 root     root            0 Dez  5 20:15 /sys/bus/hid/drivers/uclogic/0003:256C:006D.0007 -> ../../../../devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.1/0003:256C:006D.0007
    48717      0 lrwxrwxrwx   1 root     root            0 Dez  5 20:15 /sys/bus/hid/drivers/uclogic/0003:256C:006D.0006 -> ../../../../devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/0003:256C:006D.0006

I don't know if libwacom has enough info to construct those paths (including bus/controller number 0003 and whatever 0006 and 0007 is), or should it be placed under /sys/bus/hid/drivers/uclogic/<vid>:<pid>/firmware? That wouldn't account for multiple devices attached at the same time though (even if that should be a niche use case, who dual-wields graphical tablets?)

TacticalCode avatar Dec 05 '23 19:12 TacticalCode

I don't know if libwacom has enough info to construct those paths

Where the device is created from a device path (libwacom_new_from_path(), e.g. GNOME's mutter and control-center) we have access to the udev device so we can run up and down the tree to find whatever we need, regardless where you're trying to hide it ;)

Definitely needs to be in the /sys/devices part though to get accepted and be useful, not in /drivers/ (which is just a symlink anyway as you can see so no point trying to make it do anything it doesn't).

whot avatar Dec 05 '23 23:12 whot

I put together a couple of patches to expose to userspace the firmware name via sysfs attribute.

To keep things simple, I cherry-picked all patches from the upstream kernel not present in DIGImend and added my patches on top. Just clone this branch: https://github.com/JoseExposito/digimend-kernel-drivers/tree/sysfs-fw-name

In this way, you can test the changes without having to compile your own kernel. Just follow the instructions present here (basically, make && sudo make install): https://github.com/DIGImend/digimend-kernel-drivers?tab=readme-ov-file#installing-from-source-with-dkms

After loading the new driver, you should see a read only fw_name file:

$ ll /sys/devices/pci0000:00/0000:00:01.2/0000:20:00.0/0000:21:08.0/0000:2a:00.3/usb3/3-2/3-2:1.0/0003:256C:006D.000A/
-r--r--r--. 1 root root 4.0K Dec  9 21:01 country
lrwxrwxrwx. 1 root root    0 Dec  9 21:00 driver -> ../../../../../../../../../../bus/hid/drivers/uclogic
-r--r-----. 1 root root 4.0K Dec  9 21:01 fw_name
drwxr-xr-x. 3 root root    0 Dec  9 21:00 hidraw
drwxr-xr-x. 6 root root    0 Dec  9 21:00 input
-r--r--r--. 1 root root 4.0K Dec  9 21:01 modalias
drwxr-xr-x. 2 root root    0 Dec  9 21:00 power
-r--r--r--. 1 root root 4.0K Dec  9 21:00 report_descriptor
lrwxrwxrwx. 1 root root    0 Dec  9 21:00 subsystem -> ../../../../../../../../../../bus/hid
-rw-r--r--. 1 root root 4.0K Dec  9 21:00 uevent

Containing the firmware version name:

$ sudo cat /sys/devices/pci0000:00/0000:00:01.2/0000:20:00.0/0000:21:08.0/0000:2a:00.3/usb3/3-2/3-2:1.0/0003:256C:006D.000A/fw_name
HUION_T203_200720

@whot would this work for libwacom? I haven't investigated how I can find that file from libwacom yet, but if you don't have a device to test with I can try to do the libwacom part.

JoseExposito avatar Dec 09 '23 20:12 JoseExposito

Nice! g_udev_device_get_sysfs_attr() should pick it up then, needs to be added to get_device_info() and then the rest should be a breeze. Note that the device is the evdev device so you might have to do a g_udev_device_get_parent() loop (just hook into the existing one for the name attribute).

whot avatar Dec 10 '23 10:12 whot

I have created a small script to extract the firmware <-> model equivalences from the HUION driver: https://github.com/JoseExposito/uclogic-firmware-names

Here is the file it generated:

Expand
{
"HUION_M165": "KAMVAS GT-220 V2",
"HUION_M167": "KAMVAS  GT-221 Pro",
"HUION_M168": "KAMVAS GT-191",
"HUION_M171": "KAMVAS Pro 12 GT-116",
"HUION_M174": "KAMVAS GT-156HD V2",
"HUION_M175": "KAMVAS Pro 22 GT-221",
"HUION_M182": "KAMVAS Pro 13 GT-133",
"HUION_M183": "KAMVAS Pro 16 GT-156",
"HUION_M184": "KAMVAS Pro 24 GT-240",
"HUION_M189": "KAMVAS Pro 20 GT-192",
"HUION_M18a": "KAMVAS GT-191 V2",
"HUION_M18e": "KAMVAS 16(2019)",
"HUION_M192": "KAMVAS 20 GS1901",
"HUION_M193": "KAMVAS Pro 20 GT1901",
"HUION_M194": "KAMVAS Pro/Studio 22",
"HUION_M19e": "KAMVAS GT-191 V2",
"HUION_M19f": "KAMVAS 13 GS1331",
"HUION_M19g": "KAMVAS 22 GS2201",
"HUION_M19p": "KAMVAS 12 GS1161",
"HUION_M19s": "KAMVAS 16 GS1562",
"HUION_M19t": "KAMVAS 22 GS2202",
"HUION_M202": "KAMVAS Pro 16 GT1561",
"HUION_M205": "KAMVAS 24 Plus GS2402",
"HUION_M206": "KAMVAS 24 GS2401",
"HUION_M207": "KAMVAS Pro 24 GT2401",
"HUION_M20a": "KAMVAS Pro 16 Plus GT1562",
"HUION_M20h": "KAMVAS 13 GS1331",
"HUION_M20j": "KAMVAS Pro 12 GT-116",
"HUION_M20k": "KAMVAS Pro 13 GT-133",
"HUION_M20m": "KAMVAS Pro 16 GT-156",
"HUION_M20q": "KAMVAS Pro 16 GT1602",
"HUION_M20s": "KAMVAS 19",
"HUION_M20u": "KAMVAS GT-156(2021)",
"HUION_M20v": "KAMVAS GT-156(2021)",
"HUION_M210": "KAMVAS Pro 13 GT1302",
"HUION_M211": "Huion RDS-160",
"HUION_M213": "KAMVAS Pro 13 GT1302",
"HUION_M214": "KAMVAS Pro 16 GT1602",
"HUION_M215": "KAMVAS 13 GS1331",
"HUION_M216": "KAMVAS 13 GS1331",
"HUION_M225": "Kamvas RDS-220",
"HUION_T161": "INSPIROY  G10T",
"HUION_T164": "INSPIROY Q11K",
"HUION_T166": "Huion GC610/710",
"HUION_T167": "INSPIROY H1060P",
"HUION_T172": "INSPIROY H950P",
"HUION_T173": "INSPIROY H640P",
"HUION_T174": "INSPIROY NEW 1060 Plus",
"HUION_T176": "INSPIROY H430P",
"HUION_T181": "Huion HST640",
"HUION_T184": "INSPIROY H610PRO V2",
"HUION_T185": "INSPIROY Q11K V2",
"HUION_T188": "INSPIROY WH1409 V2",
"HUION_T18a": "INSPIROY H430P",
"HUION_T18c": "Huion HC16",
"HUION_T18d": "INSPIROY Q620M",
"HUION_T191": "INSPIROY H1161",
"HUION_T193": "Huion HS64",
"HUION_T194": "Huion HS610",
"HUION_T197": "INSPIROY KeyDial KD200",
"HUION_T198": "INSPIROY Ink H320M",
"HUION_T19c": "Huion HS611",
"HUION_T19g": "Huion RTS-300",
"HUION_T19h": "Huion RTM-500",
"HUION_T19k": "Huion RTP-700",
"HUION_T203": "INSPIROY H640P",
"HUION_T204": "INSPIROY H950P",
"HUION_T205": "INSPIROY H1060P",
"HUION_T206": "Huion HS95",
"HUION_T210": "INSPIROY H420X",
"HUION_T211": "INSPIROY H580X",
"HUION_T212": "INSPIROY H610X",
"HUION_T216": "INSPIROY DIAL 2",
"HUION_T217": "Huion RTE-100",
"HUION_T218": "Huion Note X10",
"HUION_T219": "INSPIROY H1060P",
"HUION_T21a": "INSPIROY H950P",
"HUION_T21c": "INSPIROY H430P",
"HUION_T21d": "Huion HS64",
"HUION_T21e": "INSPIROY H640P",
"HUION_T21f": "INSPIROY H950P",
"HUION_T21g": "INSPIROY H580X",
"HUION_T21j": "Inspiroy 2 S | H641P",
"HUION_T21k": "Inspiroy 2 M | H951P",
"HUION_T21m": "Inspiroy 2 L | H1061P",
"HUION_T223": "INSPIROY H420X",
"HUION_T224": "INSPIROY H580X",
"HUION_T225": "Huion HS64",
"HUION_T226": "Huion HC16",
"HUION_T227": "Huion HS610",
"HUION_T229": "INSPIROY H610X",
"HUION_T22b": "Inspiroy Dial 2",
"HUION_T22d": "H950P&IGG",
"HUION_T18C": "Huion HC16",
"HUION_T200": "Mini KeyDial KD100",
"HUION_T209": "Inspiroy Giano",
"HUION_T21n": "HUION KIZUNA HS952",
"HUION_T222": "Inspiroy Dial Q620M"
}

It looks like depending on the driver version the HUION_T216 is associated with Inspiroy Dial 2 or INSPIROY DIAL 2, so it looks like a good idea to convert to lower case before matching on libwacom.

jexposit avatar Dec 15 '23 12:12 jexposit

For reference, I extracted the firmware <-> model equivalences from the GAOMON driver and this is the result:

Expand
{
'00OEM_M171': 'GT116H',
'00OEM_M21q': 'GT116H',
'05OEM_T219': 'A5H_MT',
'06OEM_T21b': 'T01',
'07OEM_T21g': 'T02',
GM001_M201: 'PD1320',
GM001_M202: 'PD1220',
GM001_M203: 'PD1620',
GM001_M204: 'PD2400',
GM001_M205: 'G12',
GM001_M206: 'G13',
GM001_M207: 'PD1621',
GM001_M208: 'PD2401',
GM001_M209: 'GM116HD(TP)',
GM001_M20a: 'GM156HD(TP)',
GM001_M20b: 'G16',
GM001_M210: 'PD1610',
GM001_M211: 'PD1611',
GM001_M215: 'GM24',
GM001_M216: 'GM24TP',
GM001_M219: 'G22',
GM001_M21d: 'PD1161(GD)',
GM001_M21f: 'PD1561(GD)',
GM001_M21h: 'PD1220(GD)',
GM001_M21i: 'PD1320(GD)',
GM001_M21j: 'G12(GD)',
GM001_M21k: 'G13(GD)',
GM001_M21m: 'G16(GD)',
GM001_M21n: 'PD156Pro(GD)',
GM001_M21t: 'GM116HD',
GM001_M21u: 'GM156HD',
GM001_M220: 'G22',
GM001_M221: 'PD2200',
GM001_M226: 'PD2200',
GM001_M22b: 'PD1161',
GM001_M234: 'U16(4K)',
GM001_M235: 'U16 TP(4K)',
GM001_T201: 'M1220',
GM001_T202: 'M1230',
GM001_T203: 'S630',
GM001_T204: 'S830',
GM001_T207: 'M7',
GM001_T208: 'M8',
GM001_T213: '1060Pro',
GM001_T216: '1060Pro',
GM001_T21a: 'M10',
GM001_T21f: 'WH851',
GM001_T220: 'M7',
GM001_T221: 'M8',
GM001_T223: 'M6(2022)',
GM001_T22a: '1061Pro',
GM001_T22c: '1061Pro',
HUION_M175: 'GT226',
OEM00_T202: 'A5H',
OEM02_M165: 'GM220HD',
OEM02_M166: 'GM156HD',
OEM02_M171: 'GM116HD',
OEM02_M177: 'PD1560',
OEM02_M186: 'GM116HD',
OEM02_M187: 'GM156HD',
OEM02_M188: 'GM220HD',
OEM02_M18a: 'GM185',
OEM02_M191: 'PD1161',
OEM02_M196: 'PD1561',
OEM02_M198: 'PD2200',
OEM02_M19h: 'PD156Pro',
OEM02_T151: 'M106K',
OEM02_T156: 'S56K',
OEM02_T174: '1060PRO',
OEM02_T178: 'M106K',
OEM02_T17b: 'M10K 2018',
OEM02_T17c: 'WH850',
OEM02_T183: 'M6',
OEM02_T18e: 'S620',
OEM02_T195: 'SN540/M5',
OEM02_T19m: 'M106K PRO',
OEM02_T19n: 'M10K PRO',
OEM10_M173: 'TM156W',
OEM13_M171: 'GT-1106',
OEM16_M165: 'D22S',
OEM16_M193: 'D16 PRO',
OEM16_M201: 'SP1603',
OEM16_T205: 'M0610 PRO',
OEM16_T206: 'A1201',
OEM16_T211: 'A601',
OEM16_T212: 'A801',
OEM24_M20e: 'JR156',
OEM28_T18d: 'T01'
}

jexposit avatar Mar 21 '24 11:03 jexposit