xref: /netbsd-src/sys/dev/usb/uintuos.c (revision 57da788e746d15ab69460e76ed92ca1711440ec6)
1*57da788eSmacallan /*	$NetBSD: uintuos.c,v 1.1 2022/06/30 06:30:44 macallan Exp $	*/
2*57da788eSmacallan 
3*57da788eSmacallan /*
4*57da788eSmacallan  * Copyright (c) 2019 The NetBSD Foundation, Inc.
5*57da788eSmacallan  * All rights reserved.
6*57da788eSmacallan  *
7*57da788eSmacallan  * This code is derived from software contributed to The NetBSD Foundation
8*57da788eSmacallan  * by Yorick Hardy.
9*57da788eSmacallan  *
10*57da788eSmacallan  * Redistribution and use in source and binary forms, with or without
11*57da788eSmacallan  * modification, are permitted provided that the following conditions
12*57da788eSmacallan  * are met:
13*57da788eSmacallan  * 1. Redistributions of source code must retain the above copyright
14*57da788eSmacallan  *    notice, this list of conditions and the following disclaimer.
15*57da788eSmacallan  * 2. Redistributions in binary form must reproduce the above copyright
16*57da788eSmacallan  *    notice, this list of conditions and the following disclaimer in the
17*57da788eSmacallan  *    documentation and/or other materials provided with the distribution.
18*57da788eSmacallan  *
19*57da788eSmacallan  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*57da788eSmacallan  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*57da788eSmacallan  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*57da788eSmacallan  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*57da788eSmacallan  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*57da788eSmacallan  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*57da788eSmacallan  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*57da788eSmacallan  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*57da788eSmacallan  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*57da788eSmacallan  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*57da788eSmacallan  * POSSIBILITY OF SUCH DAMAGE.
30*57da788eSmacallan  */
31*57da788eSmacallan 
32*57da788eSmacallan /*
33*57da788eSmacallan  *  Wacom Intuos Pen driver.
34*57da788eSmacallan  *  (partially based on uep.c and ums.c)
35*57da788eSmacallan  */
36*57da788eSmacallan #include <sys/cdefs.h>
37*57da788eSmacallan __KERNEL_RCSID(0, "$NetBSD: uintuos.c,v 1.1 2022/06/30 06:30:44 macallan Exp $");
38*57da788eSmacallan 
39*57da788eSmacallan #include <sys/param.h>
40*57da788eSmacallan #include <sys/systm.h>
41*57da788eSmacallan #include <sys/kernel.h>
42*57da788eSmacallan #include <sys/device.h>
43*57da788eSmacallan #include <sys/ioctl.h>
44*57da788eSmacallan #include <sys/vnode.h>
45*57da788eSmacallan 
46*57da788eSmacallan #include <dev/usb/usb.h>
47*57da788eSmacallan #include <dev/usb/usbhid.h>
48*57da788eSmacallan 
49*57da788eSmacallan #include <dev/usb/usbdi.h>
50*57da788eSmacallan #include <dev/usb/usbdivar.h>
51*57da788eSmacallan #include <dev/usb/usbdi_util.h>
52*57da788eSmacallan #include <dev/usb/usbdevs.h>
53*57da788eSmacallan #include <dev/usb/uhidev.h>
54*57da788eSmacallan 
55*57da788eSmacallan #include <dev/wscons/wsconsio.h>
56*57da788eSmacallan #include <dev/wscons/wsmousevar.h>
57*57da788eSmacallan #include <dev/wscons/tpcalibvar.h>
58*57da788eSmacallan 
59*57da788eSmacallan struct uintuos_softc {
60*57da788eSmacallan 	struct uhidev sc_hdev;
61*57da788eSmacallan 
62*57da788eSmacallan 	device_t		sc_wsmousedev;	/* wsmouse device */
63*57da788eSmacallan 	struct tpcalib_softc	sc_tpcalib;	/* calibration */
64*57da788eSmacallan 
65*57da788eSmacallan 	u_char sc_enabled;
66*57da788eSmacallan 	u_char sc_dying;
67*57da788eSmacallan };
68*57da788eSmacallan 
69*57da788eSmacallan Static void uintuos_cth490_intr(struct uhidev *, void *, u_int);
70*57da788eSmacallan Static void uintuos_ctl6100_intr(struct uhidev *, void *, u_int);
71*57da788eSmacallan 
72*57da788eSmacallan Static int	uintuos_enable(void *);
73*57da788eSmacallan Static void	uintuos_disable(void *);
74*57da788eSmacallan Static int	uintuos_ioctl(void *, u_long, void *, int, struct lwp *);
75*57da788eSmacallan 
76*57da788eSmacallan const struct wsmouse_accessops uintuos_accessops = {
77*57da788eSmacallan 	uintuos_enable,
78*57da788eSmacallan 	uintuos_ioctl,
79*57da788eSmacallan 	uintuos_disable,
80*57da788eSmacallan };
81*57da788eSmacallan 
82*57da788eSmacallan int uintuos_match(device_t, cfdata_t, void *);
83*57da788eSmacallan void uintuos_attach(device_t, device_t, void *);
84*57da788eSmacallan void uintuos_childdet(device_t, device_t);
85*57da788eSmacallan int uintuos_detach(device_t, int);
86*57da788eSmacallan int uintuos_activate(device_t, enum devact);
87*57da788eSmacallan 
88*57da788eSmacallan CFATTACH_DECL2_NEW(uintuos, sizeof(struct uintuos_softc), uintuos_match, uintuos_attach,
89*57da788eSmacallan     uintuos_detach, uintuos_activate, NULL, uintuos_childdet);
90*57da788eSmacallan 
91*57da788eSmacallan int
uintuos_match(device_t parent,cfdata_t match,void * aux)92*57da788eSmacallan uintuos_match(device_t parent, cfdata_t match, void *aux)
93*57da788eSmacallan {
94*57da788eSmacallan 	struct uhidev_attach_arg *uha = aux;
95*57da788eSmacallan 
96*57da788eSmacallan 	if ((uha->uiaa->uiaa_vendor == USB_VENDOR_WACOM) &&
97*57da788eSmacallan 		(uha->uiaa->uiaa_product == USB_PRODUCT_WACOM_CTH490K0) &&
98*57da788eSmacallan 		(uha->reportid == 16))
99*57da788eSmacallan 		return UMATCH_VENDOR_PRODUCT;
100*57da788eSmacallan 
101*57da788eSmacallan 	if ((uha->uiaa->uiaa_vendor == USB_VENDOR_WACOM) &&
102*57da788eSmacallan 		(uha->uiaa->uiaa_product == USB_PRODUCT_WACOM_CTL6100WL) &&
103*57da788eSmacallan 		(uha->reportid == 16))
104*57da788eSmacallan 		return UMATCH_VENDOR_PRODUCT;
105*57da788eSmacallan 
106*57da788eSmacallan 	return UMATCH_NONE;
107*57da788eSmacallan }
108*57da788eSmacallan 
109*57da788eSmacallan void
uintuos_attach(device_t parent,device_t self,void * aux)110*57da788eSmacallan uintuos_attach(device_t parent, device_t self, void *aux)
111*57da788eSmacallan {
112*57da788eSmacallan 	struct uintuos_softc *sc = device_private(self);
113*57da788eSmacallan 	struct uhidev_attach_arg *uha = aux;
114*57da788eSmacallan 	struct wsmousedev_attach_args a;
115*57da788eSmacallan 	struct wsmouse_calibcoords default_calib;
116*57da788eSmacallan 
117*57da788eSmacallan 	aprint_normal("\n");
118*57da788eSmacallan 	aprint_naive("\n");
119*57da788eSmacallan 
120*57da788eSmacallan 	sc->sc_hdev.sc_dev = self;
121*57da788eSmacallan 	sc->sc_hdev.sc_parent = uha->parent;
122*57da788eSmacallan 	sc->sc_hdev.sc_report_id = uha->reportid;
123*57da788eSmacallan 
124*57da788eSmacallan 	switch (uha->uiaa->uiaa_product) {
125*57da788eSmacallan 	case USB_PRODUCT_WACOM_CTH490K0:
126*57da788eSmacallan 		default_calib.minx = 0,
127*57da788eSmacallan 		default_calib.miny = 0,
128*57da788eSmacallan 		default_calib.maxx = 7600,
129*57da788eSmacallan 		default_calib.maxy = 4750,
130*57da788eSmacallan 		sc->sc_hdev.sc_intr = uintuos_cth490_intr;
131*57da788eSmacallan 		break;
132*57da788eSmacallan 	case USB_PRODUCT_WACOM_CTL6100WL:
133*57da788eSmacallan 		default_calib.minx = 0,
134*57da788eSmacallan 		default_calib.miny = 0,
135*57da788eSmacallan 		default_calib.maxx = 21600,
136*57da788eSmacallan 		default_calib.maxy = 13471,
137*57da788eSmacallan 		sc->sc_hdev.sc_intr = uintuos_ctl6100_intr;
138*57da788eSmacallan 		break;
139*57da788eSmacallan 	default:
140*57da788eSmacallan 		sc->sc_hdev.sc_intr = uintuos_cth490_intr;
141*57da788eSmacallan 		aprint_error_dev(self, "unsupported product\n");
142*57da788eSmacallan 		break;
143*57da788eSmacallan 	}
144*57da788eSmacallan 
145*57da788eSmacallan 
146*57da788eSmacallan 	if (!pmf_device_register(self, NULL, NULL))
147*57da788eSmacallan 		aprint_error_dev(self, "couldn't establish power handler\n");
148*57da788eSmacallan 
149*57da788eSmacallan 	a.accessops = &uintuos_accessops;
150*57da788eSmacallan 	a.accesscookie = sc;
151*57da788eSmacallan 
152*57da788eSmacallan 	sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
153*57da788eSmacallan 
154*57da788eSmacallan 	default_calib.samplelen = WSMOUSE_CALIBCOORDS_RESET,
155*57da788eSmacallan 	tpcalib_init(&sc->sc_tpcalib);
156*57da788eSmacallan 	tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
157*57da788eSmacallan 		(void *)&default_calib, 0, 0);
158*57da788eSmacallan 
159*57da788eSmacallan 	return;
160*57da788eSmacallan }
161*57da788eSmacallan 
162*57da788eSmacallan int
uintuos_detach(device_t self,int flags)163*57da788eSmacallan uintuos_detach(device_t self, int flags)
164*57da788eSmacallan {
165*57da788eSmacallan 	struct uintuos_softc *sc = device_private(self);
166*57da788eSmacallan 	int rv = 0;
167*57da788eSmacallan 
168*57da788eSmacallan 	sc->sc_dying = 1;
169*57da788eSmacallan 
170*57da788eSmacallan 	if (sc->sc_wsmousedev != NULL)
171*57da788eSmacallan 		rv = config_detach(sc->sc_wsmousedev, flags);
172*57da788eSmacallan 
173*57da788eSmacallan 	pmf_device_deregister(self);
174*57da788eSmacallan 
175*57da788eSmacallan 	return rv;
176*57da788eSmacallan }
177*57da788eSmacallan 
178*57da788eSmacallan void
uintuos_childdet(device_t self,device_t child)179*57da788eSmacallan uintuos_childdet(device_t self, device_t child)
180*57da788eSmacallan {
181*57da788eSmacallan 	struct uintuos_softc *sc = device_private(self);
182*57da788eSmacallan 
183*57da788eSmacallan 	KASSERT(sc->sc_wsmousedev == child);
184*57da788eSmacallan 	sc->sc_wsmousedev = NULL;
185*57da788eSmacallan }
186*57da788eSmacallan 
187*57da788eSmacallan int
uintuos_activate(device_t self,enum devact act)188*57da788eSmacallan uintuos_activate(device_t self, enum devact act)
189*57da788eSmacallan {
190*57da788eSmacallan 	struct uintuos_softc *sc = device_private(self);
191*57da788eSmacallan 
192*57da788eSmacallan 	switch (act) {
193*57da788eSmacallan 	case DVACT_DEACTIVATE:
194*57da788eSmacallan 		sc->sc_dying = 1;
195*57da788eSmacallan 		return 0;
196*57da788eSmacallan 	default:
197*57da788eSmacallan 		return EOPNOTSUPP;
198*57da788eSmacallan 	}
199*57da788eSmacallan }
200*57da788eSmacallan 
201*57da788eSmacallan Static int
uintuos_enable(void * v)202*57da788eSmacallan uintuos_enable(void *v)
203*57da788eSmacallan {
204*57da788eSmacallan 	struct uintuos_softc *sc = v;
205*57da788eSmacallan 	int error;
206*57da788eSmacallan 
207*57da788eSmacallan 	if (sc->sc_dying)
208*57da788eSmacallan 		return EIO;
209*57da788eSmacallan 
210*57da788eSmacallan 	if (sc->sc_enabled)
211*57da788eSmacallan 		return EBUSY;
212*57da788eSmacallan 
213*57da788eSmacallan 	sc->sc_enabled = 1;
214*57da788eSmacallan 
215*57da788eSmacallan 	error = uhidev_open(&sc->sc_hdev);
216*57da788eSmacallan 	if (error)
217*57da788eSmacallan 		sc->sc_enabled = 0;
218*57da788eSmacallan 
219*57da788eSmacallan 	return error;
220*57da788eSmacallan }
221*57da788eSmacallan 
222*57da788eSmacallan Static void
uintuos_disable(void * v)223*57da788eSmacallan uintuos_disable(void *v)
224*57da788eSmacallan {
225*57da788eSmacallan 	struct uintuos_softc *sc = v;
226*57da788eSmacallan 
227*57da788eSmacallan 	if (!sc->sc_enabled) {
228*57da788eSmacallan 		printf("uintuos_disable: not enabled\n");
229*57da788eSmacallan 		return;
230*57da788eSmacallan 	}
231*57da788eSmacallan 
232*57da788eSmacallan 	sc->sc_enabled = 0;
233*57da788eSmacallan 	uhidev_close(&sc->sc_hdev);
234*57da788eSmacallan }
235*57da788eSmacallan 
236*57da788eSmacallan Static int
uintuos_ioctl(void * v,u_long cmd,void * data,int flag,struct lwp * l)237*57da788eSmacallan uintuos_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
238*57da788eSmacallan {
239*57da788eSmacallan 	struct uintuos_softc *sc = v;
240*57da788eSmacallan 	struct wsmouse_id *id;
241*57da788eSmacallan 
242*57da788eSmacallan 	switch (cmd) {
243*57da788eSmacallan 	case WSMOUSEIO_GTYPE:
244*57da788eSmacallan 		*(u_int *)data = WSMOUSE_TYPE_TPANEL;
245*57da788eSmacallan 		return 0;
246*57da788eSmacallan 
247*57da788eSmacallan 	case WSMOUSEIO_GETID:
248*57da788eSmacallan 		id = (struct wsmouse_id *)data;
249*57da788eSmacallan 		if (id->type != WSMOUSE_ID_TYPE_UIDSTR)
250*57da788eSmacallan 		 	return EINVAL;
251*57da788eSmacallan 
252*57da788eSmacallan 		snprintf(id->data, WSMOUSE_ID_MAXLEN, "%s %s %s",
253*57da788eSmacallan 			sc->sc_hdev.sc_parent->sc_udev->ud_vendor,
254*57da788eSmacallan 			sc->sc_hdev.sc_parent->sc_udev->ud_product,
255*57da788eSmacallan 			sc->sc_hdev.sc_parent->sc_udev->ud_serial);
256*57da788eSmacallan 		id->length = strlen(id->data);
257*57da788eSmacallan 		return 0;
258*57da788eSmacallan 
259*57da788eSmacallan 	case WSMOUSEIO_SCALIBCOORDS:
260*57da788eSmacallan 	case WSMOUSEIO_GCALIBCOORDS:
261*57da788eSmacallan 		return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, l);
262*57da788eSmacallan 	}
263*57da788eSmacallan 
264*57da788eSmacallan 	return EPASSTHROUGH;
265*57da788eSmacallan }
266*57da788eSmacallan 
267*57da788eSmacallan void
uintuos_cth490_intr(struct uhidev * addr,void * ibuf,u_int len)268*57da788eSmacallan uintuos_cth490_intr(struct uhidev *addr, void *ibuf, u_int len)
269*57da788eSmacallan {
270*57da788eSmacallan 	struct uintuos_softc *sc = (struct uintuos_softc *)addr;
271*57da788eSmacallan 	u_char *p = ibuf;
272*57da788eSmacallan 	u_int btns = 0;
273*57da788eSmacallan 	int x = 0, y = 0, z = 0, s;
274*57da788eSmacallan 
275*57da788eSmacallan 	if (len != 9) {
276*57da788eSmacallan 		aprint_error_dev(sc->sc_hdev.sc_dev, "wrong report size - ignoring\n");
277*57da788eSmacallan 		return;
278*57da788eSmacallan 	}
279*57da788eSmacallan 
280*57da788eSmacallan 	/*
281*57da788eSmacallan 	 * Each report package contains 9 bytes as below (guessed by inspection):
282*57da788eSmacallan 	 *
283*57da788eSmacallan 	 * Byte 0	?VR? ?21T
284*57da788eSmacallan 	 * Byte 1	X coordinate (high byte)
285*57da788eSmacallan 	 * Byte 2	X coordinate (low byte)
286*57da788eSmacallan 	 * Byte 3	Y coordinate (high byte)
287*57da788eSmacallan 	 * Byte 4	Y coordinate (low byte)
288*57da788eSmacallan 	 * Byte 5	Pressure (high byte)
289*57da788eSmacallan 	 * Byte 6	Pressure (low byte)
290*57da788eSmacallan 	 * Byte 7	zero
291*57da788eSmacallan 	 * Byte 8	quality
292*57da788eSmacallan 	 *
293*57da788eSmacallan 	 * V: 1=valid data, 0=don't use
294*57da788eSmacallan 	 * R: 1=in range, 2=cannot sense
295*57da788eSmacallan 	 * 1: barrel button 1, 1=pressed, 0=not pressed
296*57da788eSmacallan 	 * 2: barrel button 2, 1=pressed, 0=not pressed
297*57da788eSmacallan 	 * T: 1=touched, 0=not touched (unreliable?)
298*57da788eSmacallan 	 * quality: 0 - 255, 255 = most reliable?
299*57da788eSmacallan 	 *
300*57da788eSmacallan 	 */
301*57da788eSmacallan 
302*57da788eSmacallan 	/* no valid data or not in range */
303*57da788eSmacallan 	if ((p[0] & 0x40) == 0 || (p[0] & 0x20) == 0)
304*57da788eSmacallan 		return;
305*57da788eSmacallan 
306*57da788eSmacallan 	if (sc->sc_wsmousedev != NULL) {
307*57da788eSmacallan 		x = (p[1] << 8) | p[2];
308*57da788eSmacallan 		y = (p[3] << 8) | p[4];
309*57da788eSmacallan 		z = (p[5] << 8) | p[6];
310*57da788eSmacallan 
311*57da788eSmacallan 		/*
312*57da788eSmacallan 		 * The "T" bit seems to require a *lot* of pressure to remain "1",
313*57da788eSmacallan 		 * use the pressure value instead (> 255) for button 1
314*57da788eSmacallan 		 *
315*57da788eSmacallan 		 */
316*57da788eSmacallan 		if (p[5] != 0)
317*57da788eSmacallan 			btns |= 1;
318*57da788eSmacallan 
319*57da788eSmacallan 		/* barrel button 1 => button 2 */
320*57da788eSmacallan 		if (p[0] & 0x02)
321*57da788eSmacallan 			btns |= 2;
322*57da788eSmacallan 
323*57da788eSmacallan 		/* barrel button 2 => button 3 */
324*57da788eSmacallan 		if (p[0] & 0x04)
325*57da788eSmacallan 			btns |= 4;
326*57da788eSmacallan 
327*57da788eSmacallan 		tpcalib_trans(&sc->sc_tpcalib, x, y, &x, &y);
328*57da788eSmacallan 
329*57da788eSmacallan 		s = spltty();
330*57da788eSmacallan 		wsmouse_input(sc->sc_wsmousedev, btns, x, y, z, 0,
331*57da788eSmacallan 			WSMOUSE_INPUT_ABSOLUTE_X |
332*57da788eSmacallan 			WSMOUSE_INPUT_ABSOLUTE_Y |
333*57da788eSmacallan 			WSMOUSE_INPUT_ABSOLUTE_Z);
334*57da788eSmacallan 		splx(s);
335*57da788eSmacallan 	}
336*57da788eSmacallan }
337*57da788eSmacallan 
338*57da788eSmacallan void
uintuos_ctl6100_intr(struct uhidev * addr,void * ibuf,u_int len)339*57da788eSmacallan uintuos_ctl6100_intr(struct uhidev *addr, void *ibuf, u_int len)
340*57da788eSmacallan {
341*57da788eSmacallan 	struct uintuos_softc *sc = (struct uintuos_softc *)addr;
342*57da788eSmacallan 	u_char *p = ibuf;
343*57da788eSmacallan 	u_int btns = 0;
344*57da788eSmacallan 	int x = 0, y = 0, z = 0, s;
345*57da788eSmacallan 
346*57da788eSmacallan 	if (len != 26) {
347*57da788eSmacallan 		aprint_error_dev(sc->sc_hdev.sc_dev, "wrong report size - ignoring\n");
348*57da788eSmacallan 		return;
349*57da788eSmacallan 	}
350*57da788eSmacallan 
351*57da788eSmacallan 	/*
352*57da788eSmacallan 	 * Each report package contains 26 bytes as below (guessed by inspection):
353*57da788eSmacallan 	 *
354*57da788eSmacallan 	 * Byte 0	?VR? ?21T
355*57da788eSmacallan 	 * Byte 1	X coordinate (low byte)
356*57da788eSmacallan 	 * Byte 2	X coordinate (high byte)
357*57da788eSmacallan 	 * Byte 3	zero
358*57da788eSmacallan 	 * Byte 4	Y coordinate (low byte)
359*57da788eSmacallan 	 * Byte 5	Y coordinate (high byte)
360*57da788eSmacallan 	 * Byte 6	zero
361*57da788eSmacallan 	 * Byte 7	Pressure (low byte)
362*57da788eSmacallan 	 * Byte 8	Pressure (high byte)
363*57da788eSmacallan 	 * Byte 9	zero
364*57da788eSmacallan 	 * Byte 10..14	zero
365*57da788eSmacallan 	 * Byte 15	quality?
366*57da788eSmacallan 	 * Byte 16..25	unknown
367*57da788eSmacallan 	 *
368*57da788eSmacallan 	 * V: 1=valid data, 0=don't use
369*57da788eSmacallan 	 * R: 1=in range, 0=cannot sense
370*57da788eSmacallan 	 * 1: barrel button 1, 1=pressed, 0=not pressed
371*57da788eSmacallan 	 * 2: barrel button 2, 1=pressed, 0=not pressed
372*57da788eSmacallan 	 * T: 1=touched, 0=not touched
373*57da788eSmacallan 	 * quality: 0 - 63, 0 = most reliable?
374*57da788eSmacallan 	 *
375*57da788eSmacallan 	 */
376*57da788eSmacallan 
377*57da788eSmacallan 	/* no valid data or not in range */
378*57da788eSmacallan 	if ((p[0] & 0x40) == 0 || (p[0] & 0x20) == 0)
379*57da788eSmacallan 		return;
380*57da788eSmacallan 
381*57da788eSmacallan 	if (sc->sc_wsmousedev != NULL) {
382*57da788eSmacallan 		x = (p[2] << 8) | p[1];
383*57da788eSmacallan 		y = (p[5] << 8) | p[4];
384*57da788eSmacallan 		z = (p[8] << 8) | p[7];
385*57da788eSmacallan 
386*57da788eSmacallan 		btns = p[0] & 0x7;
387*57da788eSmacallan 
388*57da788eSmacallan 		tpcalib_trans(&sc->sc_tpcalib, x, y, &x, &y);
389*57da788eSmacallan 
390*57da788eSmacallan 		s = spltty();
391*57da788eSmacallan 		wsmouse_input(sc->sc_wsmousedev, btns, x, y, z, 0,
392*57da788eSmacallan 			WSMOUSE_INPUT_ABSOLUTE_X |
393*57da788eSmacallan 			WSMOUSE_INPUT_ABSOLUTE_Y |
394*57da788eSmacallan 			WSMOUSE_INPUT_ABSOLUTE_Z);
395*57da788eSmacallan 		splx(s);
396*57da788eSmacallan 	}
397*57da788eSmacallan }
398