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;