Skip to content

Draft: bpf: add support for Huion Kamvas 13 (Gen 3) (model GS1333)

The Huion Kamvas 13 (Gen 3) (model GS1333) has five buttons and two wheels that each have an additional button at their center, for a total of 7 buttons. It is compatible with the PW600 pen, which has an eraser end and three buttons on the barrel.

  • I only own the bundled PW600L pen, which lacks the eraser, so I am unable to test its behavior.

In firmware mode, and without any HID-BPF program loaded, only the pen position, pressure, and tilt work as expected (at least when using the Wacom driver in X11 — it doesn't work with libinput (missing tablet capabilities: resolution)). The five buttons provide fixed keystrokes, the wheels and wheel buttons do nothing, and the barrel buttons perform — in order, from the tip — middle-click, nothing, and invert (BTN_STYLUS, BTN_TOUCH, and BTN_TOOL_RUBBER through libinput).

I have started to write a HID-BPF program to handle the vendor mode reports and would like to find out if I'm on the right track with it before continuing on to handle the firmware mode. I am aware of various code style issues and plan to fix those afterwards.

At the moment:

  • Pen position, pressure, and tilt work (although tilt compensation may be necessary — I'd like to experiment with this a bit)
  • All three pen buttons work (with a caveat [1])
  • All seven buttons work [2]
  • Rotation of both wheels is decoded properly in hid-recorder
  • The bottom wheel's rotation doesn't appear to be usable in any application (no events show up in libinput record, either)
  • The top wheel's rotation has worked sporadically in a way that confuses me [3]

Testing has been done using Xubuntu 24.04, running the 6.11.0-1008-oem kernel.

I have attached a text file that contains the HID descriptors, analysis, and sample reports recorded while performing various actions in both modes. (The tablet is rotated 180° on my desk. I made a concerted effort to not let myself get confused while labeling directions in this file, but if you see anything odd, I'm happy to double check!)

[1] According to the firmware mode HID descriptor, the third barrel button bit is Invert, and the next bit is Eraser. Because my pen doesn't have the eraser, I can't test what happens when the pen is inverted. However, the stable/0010-Huion__Kamvas-Pro-19.bpf.c program describes a very similar situation, and I am planning to follow what was done there with the hope that it works the same way.

[2] Only one button can be pressed at a time, although there can be some unusual, but seemingly harmless situations. For example, if you hold button 1, then hold button 7, it will appear as if button 7 was quickly pressed and released (and button 1 was quickly released and then pressed). Then, if you release button 1 while button 7 is still held, button 1 will appear to be held until button 7 is released.

[3] Throughout the time I've worked on this program, I have never had the top wheel work beyond seeing REL_WHEEL events when using libinput record. However, when I sat down to write this message today, I was able to use it as a regular scroll wheel and rebind its actions using xsetwacom. After that, I did other testing and was then never able to get it to work again. I assume I'm doing something silly, but at the moment, I'm at a loss as to what's going on.

It may be useful to note that, when using the libinput driver, the following line shows up in Xorg.log whenever I use the wheel: (EE) event9 - HUION Huion Tablet_GS1333 Keypad: Unexpected event type EV_REL (0x2)

I have some specific questions I'd like to ask, as well:

#define REPORT_SUBTYPE_PEN_OUT 0x00

__u8 last_button_state;	// line #227

SEC(HID_BPF_DEVICE_EVENT)

last_button_state is uninitialized until a button is pressed, and can be returned in this uninitialized state if a wheel event occurs before a button event. Is there some guarantee that it starts as 0, or should I initialize it somewhere?

		CollectionPhysical(	// line #133
			// Byte 1 are the buttons
			Usage_Dig_BarrelSwitch	 // BTN_STYLUS, needed so we get to be a tablet pad
			ReportCount(1)
			ReportSize(1)
			Input(Var|Abs)
			ReportCount(7) // Padding
			Input(Const)
			// Bytes 2/3 - x/y just exist so we get to be a tablet pad
			UsagePage_GenericDesktop
			Usage_GD_X
			Usage_GD_Y
			ReportCount(2)
			ReportSize(8)
			Input(Var|Abs)

It still shows up as a tablet pad for me without these. Are these actually necessary to keep?

	if (reportSubtype == REPORT_SUBTYPE_PEN || reportSubtype == REPORT_SUBTYPE_PEN_OUT) {
		//Invert Y tilt
		data[11] = -data[11];	// line #289

Is it safe to invert the sign of an unsigned (__u8) value like this?

Edited by Nicholas LaPointe

Merge request reports

Loading