tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: Huion tablet support
On 2025-02-19, adr wrote:
> Hi.
>
> I'm going to do some work adding support for the drawing tablets I
> discussed here:
>
> https://mail-index.netbsd.org/netbsd-users/2023/05/14/msg029686.html
>
> These devices use chips called uclogic that are found on many other
> devices.
>
> These devices use the same vendor:product id for different models,
> don't conform to the hid standard, strings descriptors have to be
> read to obtain parameters and set the tablet mode (full, phone).
> These strings are different between models. Trying to make a general
> algorithm to manage all models is not a great idea in my opinion.
> Look at the linux driver:
>
> https://raw.githubusercontent.com/DIGImend/digimend-kernel-drivers/master/hid-uclogic-params.c
>
> They try first as if the device were an old one, then gess if it is
> wrong and try another way, and all of this making exeptions for
> different models anyway. And this driver hasn't been written by a
> vendor, there is no certainty that the next chip will make something
> different, for example the codification of the parameters in the
> string descriptor, so the code has to be kneaded again... I really
> don't like it.
>
> In sort what I did basically was adding some code in uhidev.c and
> supporting files to set the device in the adecuate mode and set
> the descriptor report for the corresponding model (I made it easy
> to add new models and reuse if possible the structures, &c)
>
> The problem is that pressure is not managed by ums(4).
>
> I've been using the old usbtablet driver still maintained in openbsd.
>
> I don't like this workaround:
>
> 1. The driver is not in netbsd's xorg.
> 2. Deattaching the device will freeze the system.
> 3. With wscons support, it will work in whatever environment that uses
> wscons, not just xorg.
>
> This could bring support to netbsd for a lot of graphics tablets,
> these chips are use by several manufactures (Huion, Yiynova, Ugee,
> Monoprice, Turcom...).
>
> One cheap solution I'm seeing is to check in ums.c for HUD_TIP_PRESSURE
> at ums_attach(), when hid_start_parse() is used for calibration,
> then change hidms_loc_z to match that of pressure.
>
> A similar check should be done in sys/dev/hid/hidms.c:hidms_intr()
> to add the flag WSMOUSE_INPUT_ABSOLUTE_Z. Would be a good idea
> to check for the HIDMS_DIGITIZER flag and assume that z will be
> absolute?
>
> If devices have problems with that, the check could be narrow to
> a list of devices instead, but I doubt those devices could work
> correctly with wscons anyway...
>
> Some thoughts or guidance before I start digging in?
>
> Regards.
> adr.
For pressure on a Wacom Intuos -- on the Xorg side of things -- I
have been using the attached patch for many years. It abuses the Z
input for pressure, so probably not what we want commited; but
perhaps it provides a starting point.
--
Kind regards,
Yorick Hardy
Index: external/mit/xf86-input-ws/dist/include/ws-properties.h
===================================================================
RCS file: /cvsroot/xsrc/external/mit/xf86-input-ws/dist/include/ws-properties.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 ws-properties.h
--- external/mit/xf86-input-ws/dist/include/ws-properties.h 27 Nov 2009 14:17:19 -0000 1.1.1.1
+++ external/mit/xf86-input-ws/dist/include/ws-properties.h 16 Jul 2022 21:31:52 -0000
@@ -27,6 +27,10 @@
/* CARD32, 4 values [minx, maxx, miny, maxy], or no values for unset */
#define WS_PROP_CALIBRATION "WS Pointer Axis Calibration"
+/* Run-time pressure calibration */
+/* CARD32, 2 values [minz, maxz], or no values for unset */
+#define WS_PROP_PRESSURE "WS Pointer Pressure Calibration"
+
/* Swap x and y axis. */
/* BOOL */
#define WS_PROP_SWAP_AXES "WS Pointer Axes Swap"
Index: external/mit/xf86-input-ws/dist/man/ws.man
===================================================================
RCS file: /cvsroot/xsrc/external/mit/xf86-input-ws/dist/man/ws.man,v
retrieving revision 1.3
diff -u -r1.3 ws.man
--- external/mit/xf86-input-ws/dist/man/ws.man 2 Aug 2011 09:30:15 -0000 1.3
+++ external/mit/xf86-input-ws/dist/man/ws.man 16 Jul 2022 21:31:52 -0000
@@ -143,6 +143,9 @@
1 boolean value (8 bits, 0 or 1). 1 swaps x/y axes. This property
is present only for devices with absolute coordinates (ie
tablets and touchscreens).
+.TP 7
+.BI "WS Pointer Pressure Calibration"
+2 32 bits values, in the order min-z, max-z.
.SH "SEE ALSO"
__xservername__(1), xinput(1), __xconfigfile__(__filemansuffix__),
Index: external/mit/xf86-input-ws/dist/src/ws.c
===================================================================
RCS file: /cvsroot/xsrc/external/mit/xf86-input-ws/dist/src/ws.c,v
retrieving revision 1.16
diff -u -r1.16 ws.c
--- external/mit/xf86-input-ws/dist/src/ws.c 4 Dec 2021 15:21:55 -0000 1.16
+++ external/mit/xf86-input-ws/dist/src/ws.c 16 Jul 2022 21:31:52 -0000
@@ -66,6 +66,7 @@
static int wsSetProperty(DeviceIntPtr, Atom, XIPropertyValuePtr, BOOL);
static Atom prop_calibration = 0;
+static Atom prop_pressure = 0;
static Atom prop_swap = 0;
#ifdef DEBUG
@@ -271,7 +272,13 @@
priv->max_x = screenInfo.screens[priv->screen_no]->width - 1;
priv->min_y = 0;
priv->max_y = screenInfo.screens[priv->screen_no]->height - 1;
+ priv->min_z = -1;
+ priv->max_z = -1;
+ priv->min_w = -1;
+ priv->max_w = -1;
priv->raw = 0;
+ /* Allow options to override this */
+ priv->raw = xf86SetBoolOption(pInfo->options, "Raw", priv->raw);
/* don't rely on the device type - we may be listening to a mux */
if (ioctl(pInfo->fd, WSMOUSEIO_GCALIBCOORDS,
@@ -314,6 +321,8 @@
xf86Msg(X_CONFIG,
"%s device will work in raw mode\n",
pInfo->name);
+ /* Assume a touch panel / tablet since we are in raw mode */
+ priv->type = WSMOUSE_TYPE_TPANEL;
}
/* Allow options to override this */
@@ -329,6 +338,18 @@
priv->max_y = xf86SetIntOption(pInfo->options, "MaxY", priv->max_y);
xf86Msg(X_INFO, "%s maximum y position: %d\n",
pInfo->name, priv->max_y);
+ priv->min_z = xf86SetIntOption(pInfo->options, "MinZ", priv->min_z);
+ xf86Msg(X_INFO, "%s minimum z position: %d\n",
+ pInfo->name, priv->min_z);
+ priv->max_z = xf86SetIntOption(pInfo->options, "MaxZ", priv->max_z);
+ xf86Msg(X_INFO, "%s maximum z position: %d\n",
+ pInfo->name, priv->max_z);
+ priv->min_w = xf86SetIntOption(pInfo->options, "MinW", priv->min_w);
+ xf86Msg(X_INFO, "%s minimum w position: %d\n",
+ pInfo->name, priv->min_w);
+ priv->max_w = xf86SetIntOption(pInfo->options, "MaxW", priv->max_w);
+ xf86Msg(X_INFO, "%s maximum w position: %d\n",
+ pInfo->name, priv->max_w);
pInfo->device_control = wsProc;
pInfo->read_input = wsReadInput;
@@ -417,7 +438,7 @@
InputInfoPtr pInfo = (InputInfoPtr)pWS->public.devicePrivate;
WSDevicePtr priv = (WSDevicePtr)pInfo->private;
unsigned char map[NBUTTONS + 1];
- int i, xmin, xmax, ymin, ymax;
+ int i, xmin, xmax, ymin, ymax, zmin, zmax, wmin, wmax;
Atom btn_labels[NBUTTONS] = {0};
Atom axes_labels[NAXES] = {0};
@@ -446,6 +467,11 @@
ymax = -1;
}
+ zmin = priv->min_z;
+ zmax = priv->max_z;
+ wmin = priv->min_w;
+ wmax = priv->max_w;
+
if (priv->swap_axes) {
int tmp;
tmp = xmin;
@@ -458,9 +484,13 @@
if ((priv->type == WSMOUSE_TYPE_TPANEL)) {
axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X);
axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y);
+ axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE);
+ axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_DISTANCE);
} else {
axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
+ axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Z);
+ axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_WHEEL);
}
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 14
axes_labels[HSCROLL_AXIS] =
@@ -496,6 +526,24 @@
);
xf86InitValuatorDefaults(pWS, 1);
+ xf86InitValuatorAxisStruct(pWS, 2,
+ axes_labels[2],
+ zmin, zmax, 1, 0, 1
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
+ , priv->type == WSMOUSE_TYPE_TPANEL ? Absolute : Relative
+#endif
+ );
+ xf86InitValuatorDefaults(pWS, 2);
+
+ xf86InitValuatorAxisStruct(pWS, 3,
+ axes_labels[3],
+ wmin, wmax, 1, 0, 1
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
+ , priv->type == WSMOUSE_TYPE_TPANEL ? Absolute : Relative
+#endif
+ );
+ xf86InitValuatorDefaults(pWS, 3);
+
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 14
xf86InitValuatorAxisStruct(pWS, HSCROLL_AXIS,
@@ -621,7 +669,7 @@
int n, c;
struct wscons_event *event = eventList;
unsigned char *pBuf;
- int ax, ay;
+ int ax, ay, az, aw;
priv = pInfo->private;
@@ -636,6 +684,7 @@
return;
n /= sizeof(struct wscons_event);
+ ax = 0; ay = 0; az = 0; aw = 0;
while( n-- ) {
int buttons = priv->lastButtons;
int dx = 0, dy = 0, dz = 0, dw = 0;
@@ -644,7 +693,6 @@
int hscroll = 0, vscroll = 0;
#endif
- ax = 0; ay = 0;
switch (event->type) {
case WSCONS_EVENT_MOUSE_UP:
@@ -684,14 +732,15 @@
dz = event->value;
break;
case WSCONS_EVENT_MOUSE_ABSOLUTE_Z:
- /* ignore those */
- ++event;
- continue;
+ az = event->value;
break;
case WSCONS_EVENT_MOUSE_DELTA_W:
DBG(4, ErrorF("Relative W %d\n", event->value));
dw = event->value;
break;
+ case WSCONS_EVENT_MOUSE_ABSOLUTE_W:
+ aw = event->value;
+ break;
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 14
case WSCONS_EVENT_HSCROLL:
hscroll = event->value;
@@ -774,18 +823,42 @@
ax = ay;
ay = tmp;
}
- if (ax) {
- /* absolute position event */
- DBG(3, ErrorF("postMotionEvent X %d\n", ax));
- xf86PostMotionEvent(pInfo->dev, 1, 0, 1, ax);
- }
- if (ay) {
- /* absolute position event */
- DBG(3, ErrorF("postMotionEvent y %d\n", ay));
- xf86PostMotionEvent(pInfo->dev, 1, 1, 1, ay);
- }
++event;
}
+
+ /*
+ * Report movement after looking at all events,
+ * so that x-y motion can be reported together.
+ *
+ * There must be a better way to check x, y (and z) combinations?
+ * Should dx and dy also be posted together?
+ */
+ if (ax && ay) {
+ /* absolute position event */
+ DBG(3, ErrorF("postMotionEvent X %d\n", ax));
+ xf86PostMotionEvent(pInfo->dev, 1, 0, 2, ax, ay);
+ }
+ if (ax && !ay) {
+ /* absolute position event */
+ DBG(3, ErrorF("postMotionEvent X %d\n", ax));
+ xf86PostMotionEvent(pInfo->dev, 1, 0, 1, ax);
+ }
+ if (ay && !ax) {
+ /* absolute position event */
+ DBG(3, ErrorF("postMotionEvent y %d\n", ay));
+ xf86PostMotionEvent(pInfo->dev, 1, 1, 1, ay);
+ }
+ if (az) {
+ /* absolute position event */
+ DBG(3, ErrorF("postMotionEvent Z %d\n", az));
+ xf86PostMotionEvent(pInfo->dev, 1, 2, 1, az);
+ }
+ if (aw) {
+ /* absolute position event */
+ DBG(3, ErrorF("postMotionEvent W %d\n", aw));
+ xf86PostMotionEvent(pInfo->dev, 1, 3, 1, aw);
+ }
+
return;
} /* wsReadInput */
@@ -887,6 +960,13 @@
XISetDevicePropertyDeletable(device, prop_calibration, FALSE);
+ prop_pressure = MakeAtom(WS_PROP_PRESSURE,
+ strlen(WS_PROP_PRESSURE), TRUE);
+ rc = XIChangeDeviceProperty(device, prop_pressure, XA_INTEGER, 32,
+ PropModeReplace, 2, &priv->min_z, FALSE);
+ if (rc != Success)
+ return;
+
prop_swap = MakeAtom(WS_PROP_SWAP_AXES,
strlen(WS_PROP_SWAP_AXES), TRUE);
rc = XIChangeDeviceProperty(device, prop_swap, XA_INTEGER, 8,
@@ -905,7 +985,8 @@
struct wsmouse_calibcoords coords;
int need_update = 0;
AxisInfoPtr ax = device->valuator->axes,
- ay = device->valuator->axes + 1;
+ ay = device->valuator->axes + 1,
+ az = device->valuator->axes + 2;
DBG(1, ErrorF("wsSetProperty %s\n", NameForAtom(atom)));
@@ -948,6 +1029,26 @@
ay->max_value = priv->max_x;
}
}
+ } else if (atom == prop_pressure) {
+ if (val->format != 32 || val->type != XA_INTEGER)
+ return BadMatch;
+ if (val->size != 2 && val->size != 0)
+ return BadMatch;
+ if (!checkonly) {
+ if (val->size == 0) {
+ DBG(1, ErrorF(" uncalibrate pressure\n"));
+ priv->min_z = 0;
+ priv->max_z = -1;
+ } else {
+ priv->min_z = ((int *)(val->data))[0];
+ priv->max_z = ((int *)(val->data))[1];
+ DBG(1, ErrorF(" calibrate pressure %d %d\n",
+ priv->min_z, priv->max_z));
+ }
+ /* Update axes descriptors */
+ az->min_value = priv->min_z;
+ az->max_value = priv->max_z;
+ }
} else if (atom == prop_swap) {
if (val->format != 8 || val->type != XA_INTEGER ||
val->size != 1)
Index: external/mit/xf86-input-ws/dist/src/ws.h
===================================================================
RCS file: /cvsroot/xsrc/external/mit/xf86-input-ws/dist/src/ws.h,v
retrieving revision 1.6
diff -u -r1.6 ws.h
--- external/mit/xf86-input-ws/dist/src/ws.h 4 Dec 2021 15:21:55 -0000 1.6
+++ external/mit/xf86-input-ws/dist/src/ws.h 16 Jul 2022 21:31:52 -0000
@@ -27,9 +27,9 @@
# define DBG(lvl, f)
#endif
-#define NAXES 4 /* X and Y, horizontal and vertical scrolling */
-#define HSCROLL_AXIS 2
-#define VSCROLL_AXIS 3
+#define NAXES 6 /* X, Y, Z, W and horizontal and vertical scrolling */
+#define HSCROLL_AXIS 4
+#define VSCROLL_AXIS 5
#define NBUTTONS 32 /* max theoretical buttons */
#define DFLTBUTTONS 3 /* default number of buttons */
@@ -41,6 +41,7 @@
unsigned int buttons; /* # of buttons */
unsigned int lastButtons; /* last state of buttons */
int min_x, max_x, min_y, max_y; /* coord space */
+ int min_z, max_z, min_w, max_w; /* coord space */
int swap_axes;
int raw;
int inv_x, inv_y;
Home |
Main Index |
Thread Index |
Old Index