libwacom
libwacom copied to clipboard
Fixing vendors that re-use USB IDs
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?
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
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.
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 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?)
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).
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.
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).
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.
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'
}