-
Notifications
You must be signed in to change notification settings - Fork 175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
XP-PEN Star G430S_B doesn't work with DIGImend #388
Comments
So, I might be wrong, but it seems that first byte is 07, second byte encodes Button state, then there is horizontal coordinate (2 bytes), vertical coordinate (2 bytes) and pressure (2 bytes), then zero (2 bytes).
Running uclogic-probe breaks the tablet, so it changes USB ID and stops sending any HID events:
For this reason I'm going to collect the rest of data after I reconnect the tablet without uclogic-probe anymore. I have repeated every test several times in one file. The device likely doesn't support tilt but I have tried to record it as well just in case. I have also run some tests from http://digimend.github.io/support/howto/trbl/locating_failure/
TipSwitch corresponds to touch, So the default kernel driver seems to work correctly with this pen for Linux 5.4. I don't know if this is going to be useful, I also add this command's output: |
I have tried to fix it myself with this patch, but did achieve nothing:
DIGImend detects the tablet, but the code makes it change USB ID to 28bd:1227 and the tablet doesn't work anymore until it is reconnected. When I add the new ID near G430S white (which shares ID with G540), I have same effect as I had when I tried to just replace USB ID.
I guess, either I am doing something wrong or adding support for this tablet is not that easy. |
I have fixed the tablet behavior with this change within thekernel source:
This patch does, of course, break support for all tablets which do have an actual eraser switch on the back, but it works as temporary fix for people who only have one tablet. In order for The GIMP to recognize the tablet you need to (re)start GIMP while the tablet is connected. The reason, why the button did not work is the HID descriptor sent by the tablet itself (I have posted it above in binary form). It reports that it has an eraser, however generic input driver expects the tablet having an eraser to be flipped over and change the state of "Inverted" to set the tool to eraser, and then eraser button will work as use of this tool. While G430S_B does not have a backside button and the pen can't be detected when flipped upside down. This patch changes eraser behavior making it act as second side button, but this is not a proper fix, only a hack to make this particular tablet work properly. After this patch lower button works as middle mouse button as before, but upper button starts to work as right mouse button. |
Next step is to try and switch the tablet to its native mode with coordinates going up to (10160, 7620) instead of (32767, 32767) and HID reports being 12 bytes long instead of 10.
This method works, but it's kinda hard to analyze. If you want anyway, read this. There is a program, vusb-analyzer, which is supposed to help decoding the text dumps, however I didn't get it to work on a modern system. There is a newer version moved from sourceforge to github, however it's also old and I didn't try it. So, I have had to use
This is request and answer to get string descriptor 0x64, which is similar to what is done by uclogic-probe above:
The next echange is this one:
The first line means sending three bytes {0x02, 0xB0, 0x04} as interrupt transfer to endpoint 0x03 I have tried to change uclogic-probe.c to make it send this interrupt transfer after it's done with probing. This task proved quite challenging because even after I had the code in place, it would not work, returning -1 which means I/O error. After a while I have looked in dmesg and noticed this message:
This code works as expected:
After it's done, I start to get 12 bytes HID reports:
The first report corresponds to USB dump from exchange with proprietary driver, other reports have similar formats to 10-bytes reports above, but the first byte is 02 instead of 07 and coordinates are going from (0, 0) to native tablet resolution. The last four bytes remain 00. However, tablet does not work anymore after that, and HID reports from it are only recognized by usbhid-dump and usbmon. The same thing can be seen if you start and then stop proprietary driver. The tablet is sending events, but they are not processed. The likely reason is that the HID report descriptor is still the same, as it was, so the hid driver cannot decode the tablet events anymore, after their format has been changed. |
So, the next step is to make the kernel driver. There are two possibilities: easier and harder. The harder way involves sending bytes 0x02, 0xB0, 0x04 via an interrupt transfer, similar to what modified uclogic-probe.c does, as described above. The driver will also need a freshly written HID Report descriptor which allow the kernel to understand 12-bytes long reports, which in this mode, are sent from interface 2, rather than interface 1 (starting from 0). The result of easy way is very short and easy to understand: /*
* HID driver for XP-PEN G430S_B, simple version
* Based on hid-redragon.c Copyright (c) 2017 Robert Munteanu
* Copyright (c) 2020 Sturwandan
* SPDX-License-Identifier: GPL-2.0+
*/
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include "hid-ids.h"
/* The original report descriptor usage for upper button is set to Eraser (0x09 0x45),
* While the correct usage is TabletPick (0x09 0x46). This code fixes it. */
static __u8 *g430sb_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) {
if (*rsize == 109 && rdesc[16] == 0x09 && rdesc[17] == 0x45) {
dev_info(&hdev->dev, "Fixing XP-PEN Star G430S_B report descriptor.\n");
rdesc[17] = 0x46;
}
return rdesc;
}
static const struct hid_device_id g430sb_devices[] = {
{HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_G430SB)},
{}
};
MODULE_DEVICE_TABLE(hid, g430sb_devices);
static struct hid_driver g430sb_driver = {
.name = "g430sb",
.id_table = g430sb_devices,
.report_fixup = g430sb_report_fixup
};
module_hid_driver(g430sb_driver);
MODULE_LICENSE("GPL"); However in order for this driver to work, this patch is necessary so it's build together with other DIGImend drivers: diff -ru digimend-kernel-drivers-master/Makefile digimend-kernel-drivers-modified/Makefile
--- digimend-kernel-drivers-master/Makefile
+++ digimend-kernel-drivers-modified/Makefile
@@ -1,4 +1,4 @@
-obj-m := hid-kye.o hid-uclogic.o hid-polostar.o hid-viewsonic.o
+obj-m := hid-kye.o hid-uclogic.o hid-polostar.o hid-viewsonic.o hid-g430sb.o
hid-uclogic-objs := \
hid-uclogic-core.o \
hid-uclogic-rdesc.o \
@@ -44,7 +44,8 @@
rm -vf /lib/modules/*/extra/hid-kye.ko \
/lib/modules/*/extra/hid-polostar.ko \
/lib/modules/*/extra/hid-uclogic.ko \
- /lib/modules/*/extra/hid-viewsonic.ko
+ /lib/modules/*/extra/hid-viewsonic.ko \
+ /lib/modules/*/extra/hid-g430sb.ko
install: modules_install udev_rules_install depmod_conf_install xorg_conf_install
udevadm control --reload
diff -ru digimend-kernel-drivers-master/dkms.conf digimend-kernel-drivers-modified/dkms.conf
--- digimend-kernel-drivers-master/dkms.conf
+++ digimend-kernel-drivers-modified/dkms.conf
@@ -6,7 +6,9 @@
BUILT_MODULE_NAME[1]="hid-uclogic"
BUILT_MODULE_NAME[2]="hid-polostar"
BUILT_MODULE_NAME[3]="hid-viewsonic"
+BUILT_MODULE_NAME[4]="hid-g430sb"
DEST_MODULE_LOCATION[0]="/extra"
DEST_MODULE_LOCATION[1]="/extra"
DEST_MODULE_LOCATION[2]="/extra"
DEST_MODULE_LOCATION[3]="/extra"
+DEST_MODULE_LOCATION[4]="/extra"
diff -ru digimend-kernel-drivers-master/hid-ids.h digimend-kernel-drivers-modified/hid-ids.h
--- digimend-kernel-drivers-master/hid-ids.h
+++ digimend-kernel-drivers-modified/hid-ids.h
@@ -52,6 +52,8 @@
#define USB_VENDOR_ID_UGEE 0x28bd
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540 0x0075
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640 0x0094
+// XP-PEN G430S_B stands for black version
+#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G430SB 0x0913
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01 0x0042
#define USB_DEVICE_ID_UGEE_TABLET_G5 0x0074
#define USB_DEVICE_ID_UGEE_TABLET_EX07S 0x0071 I have tested this driver with my tablet and it seems to work fine. |
I have also made a native mode driver, it works, however there is an unsolved problem still. This driver switches the tablet to native mode first, sending bytes 0x02, 0xB0, 0x04 via an interrupt transfer to interface 0x03. This is different from all other tablets supported by DIGImend, so it's easier to write this driver in a separate file. In order to make this driver, I have taken hid-viewsonic.c driver and replaced the text strings with appropriate. It turns out that all the drivers have similar layout and I could have started from hid-redragon.c too, but I didn't discover it until much later. In order to send interrupt transfer, I needed to know the name of kernel function (which is not same as name of libusb function above) and how to use it.
The same include file usb.h has explanation, how to make a pipe knowing the endpoint: However there is a pitfall: for some reason this function can't just send data from regular variable, it needs that data to be located in a specific kind of memory, while local variables in functions are in kernel stack and not suitable. So I had to learn how to use kmalloc and kcalloc and copy those three bytes into a newly created buffer. Otherwise I was getting error -11 (EAGAIN) and wasn't able to figure out where it's coming from, since in wireshark it seemed that the USB packet was sent correctly and then the device responded with this error. The next problem was that there were no hid-reports from the device in evtest or /sys/kernel/debug/hid/*/events but usbhid-dump tool was able to demonstrate 12 byte reports, so the kernel was sending the correct packets. I have thought that was because of incorrect HID Report descriptor and tried to debug it.
As you can see, unlike this tool or hidrd, kernel provides full info about every field you are trying to interpret, including its bit-offset in hid reports. While trying to catch this problem, I have added check for interface number in both fixup and probe functions, so that will be only run once and added some more minor improvements. So after all those problems were fixed, I got a working driver for my tablet. However, one problem is still unsolved: |
Hello @Sturwandan, Thank you for all these informations. I have no idea about your problem unsolved but I see that in #291 , there is also the same init of tablet in the function As for me, I'm still blocked for my XP PEN Artist 12 Pro (#351). usbhid-dump tool is able to demonstrate 12 byte reports, so the kernel sends the correct packets but... still no success with evtest. May be a small detail but... :-( |
@alfazaz, actually, usbhid-dump bypasses kernel drivers and talks with hardware directly. So if you see something in it, it only means that the tablet sends reports correctly, but it doesn't mean that it is interpreted correctly. I suggest to try doing the same thing I did: find out encoding of your tablet reports and make sure that its description in rdesc is correct, especially bit offsets and usages. And make sure that it's coming from interface you expect. |
So, if I understand things well, I need to write a good rdesc. I'm working on it (I'm not an expert of these things so it's hard for me... If you have concrete tricks, you can write them on #351). Thanks. |
This tablet is similar in appearance to the white version has same size and buttons, however, USB ID is different.
Black tablet ID is 28bd:0913
White tablet ID is 28bd:0075
When I insert the tablet, following messages appear:
The tablet works with generic drivers, pressure sensitivity is available in GIMP, however, buttons on the pen do not work as expected: the button next to the tip works as MMB (middle mouse button), while the button further from the tip doesn't work at all. Expected behavior is: close button: RMB, far button: MMB
The far button works in principle, since this command
usbhid-dump -m 28bd:0913 -e stream
shows lines like006:036:001:STREAM 1588586846.485230 07 A0 E0 3B 0C 22 00 00 00 00
when no buttons are pressed, butA0 changes to A1 with tip touch, to A2 with close-to-tip button and A4 with far button. If I both touch the tablet and hold far button, I get A5, as expected (1+4), so we can conclude that the second byte encodes buttons, similar to G430S white, which works with DIGImend.
I have tried to change this line to
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540 0x0913
But it wasn't enough. Likely it happens because of different HID packet length, I have seen a bug report with similar problem on Windows drivers: hawku/TabletDriver#520
Playing with the monitor shows that, I get this numbers when I bring the pen to a tablet corner slowly and then pull away, without touching:
07 A0 00 00 00 00 00 00 00 00 || top left corner
07 A0 00 00 FF 7F 00 00 00 00 || bottom left corner
07 A0 FF 7F 00 00 00 00 00 00 || top right corner
07 A0 FF 7F FF 7F 00 00 00 00 || bottom right corner
A0 changes to C0 when I remove the pen from the tablet.
I have noticed that white tablet output is like this:
013:002:001:STREAM 1588592013.478316
07 A0 58 4F B1 39 00 00
So the HID packet length is indeed different.
I guess you will also need this information. I was able to decode it with
hidrd-convert -i hex -o spec
so I can see it contains data which is probably needed to support the tablet.The text was updated successfully, but these errors were encountered: