| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: uep.c,v 1.15 2010/11/03 22:34:23 dyoung Exp $ */ | | 1 | /* $NetBSD: uep.c,v 1.16 2011/01/24 17:11:17 mbalmer Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2004 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2004 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Tyler C. Sarna (tsarna@netbsd.org). | | 8 | * by Tyler C. Sarna (tsarna@netbsd.org). |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -21,34 +21,29 @@ | | | @@ -21,34 +21,29 @@ |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | /* | | 32 | /* |
33 | * eGalax USB touchpanel controller driver. | | 33 | * eGalax USB touchpanel controller driver. |
34 | * | | | |
35 | * For Programming Documentation, see: | | | |
36 | * | | | |
37 | * http://www.egalax.com/SoftwareProgrammingGuide_1.1.pdf | | | |
38 | */ | | 34 | */ |
39 | | | | |
40 | #include <sys/cdefs.h> | | 35 | #include <sys/cdefs.h> |
41 | __KERNEL_RCSID(0, "$NetBSD: uep.c,v 1.15 2010/11/03 22:34:23 dyoung Exp $"); | | 36 | __KERNEL_RCSID(0, "$NetBSD: uep.c,v 1.16 2011/01/24 17:11:17 mbalmer Exp $"); |
42 | | | 37 | |
43 | #include <sys/param.h> | | 38 | #include <sys/param.h> |
44 | #include <sys/systm.h> | | 39 | #include <sys/systm.h> |
45 | #include <sys/kernel.h> | | 40 | #include <sys/kernel.h> |
46 | #include <sys/malloc.h> | | 41 | #include <sys/malloc.h> |
47 | #include <sys/device.h> | | 42 | #include <sys/device.h> |
48 | #include <sys/ioctl.h> | | 43 | #include <sys/ioctl.h> |
49 | #include <sys/vnode.h> | | 44 | #include <sys/vnode.h> |
50 | | | 45 | |
51 | #include <dev/usb/usb.h> | | 46 | #include <dev/usb/usb.h> |
52 | #include <dev/usb/usbdi.h> | | 47 | #include <dev/usb/usbdi.h> |
53 | #include <dev/usb/usbdi_util.h> | | 48 | #include <dev/usb/usbdi_util.h> |
54 | #include <dev/usb/usbdevs.h> | | 49 | #include <dev/usb/usbdevs.h> |
| @@ -97,68 +92,68 @@ const struct wsmouse_accessops uep_acces | | | @@ -97,68 +92,68 @@ const struct wsmouse_accessops uep_acces |
97 | uep_ioctl, | | 92 | uep_ioctl, |
98 | uep_disable, | | 93 | uep_disable, |
99 | }; | | 94 | }; |
100 | | | 95 | |
101 | int uep_match(device_t, cfdata_t, void *); | | 96 | int uep_match(device_t, cfdata_t, void *); |
102 | void uep_attach(device_t, device_t, void *); | | 97 | void uep_attach(device_t, device_t, void *); |
103 | void uep_childdet(device_t, device_t); | | 98 | void uep_childdet(device_t, device_t); |
104 | int uep_detach(device_t, int); | | 99 | int uep_detach(device_t, int); |
105 | int uep_activate(device_t, enum devact); | | 100 | int uep_activate(device_t, enum devact); |
106 | extern struct cfdriver uep_cd; | | 101 | extern struct cfdriver uep_cd; |
107 | CFATTACH_DECL2_NEW(uep, sizeof(struct uep_softc), uep_match, uep_attach, | | 102 | CFATTACH_DECL2_NEW(uep, sizeof(struct uep_softc), uep_match, uep_attach, |
108 | uep_detach, uep_activate, NULL, uep_childdet); | | 103 | uep_detach, uep_activate, NULL, uep_childdet); |
109 | | | 104 | |
110 | int | | 105 | int |
111 | uep_match(device_t parent, cfdata_t match, void *aux) | | 106 | uep_match(device_t parent, cfdata_t match, void *aux) |
112 | { | | 107 | { |
113 | struct usb_attach_arg *uaa = aux; | | 108 | struct usb_attach_arg *uaa = aux; |
114 | | | 109 | |
115 | if ((uaa->vendor == USB_VENDOR_EGALAX) && ( | | 110 | if ((uaa->vendor == USB_VENDOR_EGALAX) && ( |
116 | (uaa->product == USB_PRODUCT_EGALAX_TPANEL) | | 111 | (uaa->product == USB_PRODUCT_EGALAX_TPANEL) |
117 | || (uaa->product == USB_PRODUCT_EGALAX_TPANEL2) | | 112 | || (uaa->product == USB_PRODUCT_EGALAX_TPANEL2))) |
118 | )) | | | |
119 | return UMATCH_VENDOR_PRODUCT; | | 113 | return UMATCH_VENDOR_PRODUCT; |
120 | | | 114 | |
121 | if ((uaa->vendor == USB_VENDOR_EGALAX2) | | 115 | if ((uaa->vendor == USB_VENDOR_EGALAX2) |
122 | && (uaa->product == USB_PRODUCT_EGALAX2_TPANEL)) | | 116 | && (uaa->product == USB_PRODUCT_EGALAX2_TPANEL)) |
123 | return UMATCH_VENDOR_PRODUCT; | | 117 | return UMATCH_VENDOR_PRODUCT; |
124 | | | 118 | |
125 | | | 119 | |
126 | return UMATCH_NONE; | | 120 | return UMATCH_NONE; |
127 | } | | 121 | } |
128 | | | 122 | |
129 | void | | 123 | void |
130 | uep_attach(device_t parent, device_t self, void *aux) | | 124 | uep_attach(device_t parent, device_t self, void *aux) |
131 | { | | 125 | { |
132 | struct uep_softc *sc = device_private(self); | | 126 | struct uep_softc *sc = device_private(self); |
133 | struct usb_attach_arg *uaa = aux; | | 127 | struct usb_attach_arg *uaa = aux; |
134 | usbd_device_handle dev = uaa->device; | | 128 | usbd_device_handle dev = uaa->device; |
135 | usb_config_descriptor_t *cdesc; | | 129 | usb_config_descriptor_t *cdesc; |
136 | usb_interface_descriptor_t *id; | | 130 | usb_interface_descriptor_t *id; |
137 | usb_endpoint_descriptor_t *ed; | | 131 | usb_endpoint_descriptor_t *ed; |
| | | 132 | usb_device_request_t req; |
| | | 133 | uByte act; |
138 | struct wsmousedev_attach_args a; | | 134 | struct wsmousedev_attach_args a; |
139 | char *devinfop; | | 135 | char *devinfop; |
140 | usbd_status err; | | 136 | usbd_status err; |
141 | int i, found; | | 137 | int i, found; |
142 | | | 138 | |
143 | sc->sc_dev = self; | | 139 | sc->sc_dev = self; |
144 | | | 140 | |
145 | aprint_naive("\n"); | | 141 | aprint_naive("\n"); |
146 | aprint_normal("\n"); | | 142 | aprint_normal("\n"); |
147 | | | 143 | |
148 | devinfop = usbd_devinfo_alloc(dev, 0); | | 144 | devinfop = usbd_devinfo_alloc(dev, 0); |
149 | aprint_normal_dev(self, "%s\n", devinfop); | | 145 | aprint_normal_dev(self, "%s\n", devinfop); |
150 | usbd_devinfo_free(devinfop); | | 146 | usbd_devinfo_free(devinfop); |
151 | | | | |
152 | sc->sc_udev = dev; | | 147 | sc->sc_udev = dev; |
153 | sc->sc_intr_number = -1; | | 148 | sc->sc_intr_number = -1; |
154 | sc->sc_intr_pipe = NULL; | | 149 | sc->sc_intr_pipe = NULL; |
155 | sc->sc_enabled = sc->sc_isize = 0; | | 150 | sc->sc_enabled = sc->sc_isize = 0; |
156 | | | 151 | |
157 | /* Move the device into the configured state. */ | | 152 | /* Move the device into the configured state. */ |
158 | err = usbd_set_config_index(dev, 0, 1); | | 153 | err = usbd_set_config_index(dev, 0, 1); |
159 | if (err) { | | 154 | if (err) { |
160 | aprint_error("\n%s: failed to set configuration, err=%s\n", | | 155 | aprint_error("\n%s: failed to set configuration, err=%s\n", |
161 | device_xname(sc->sc_dev), usbd_errstr(err)); | | 156 | device_xname(sc->sc_dev), usbd_errstr(err)); |
162 | sc->sc_dying = 1; | | 157 | sc->sc_dying = 1; |
163 | return; | | 158 | return; |
164 | } | | 159 | } |
| @@ -198,64 +193,68 @@ uep_attach(device_t parent, device_t sel | | | @@ -198,64 +193,68 @@ uep_attach(device_t parent, device_t sel |
198 | if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && | | 193 | if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && |
199 | UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { | | 194 | UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { |
200 | sc->sc_intr_number = ed->bEndpointAddress; | | 195 | sc->sc_intr_number = ed->bEndpointAddress; |
201 | sc->sc_isize = UGETW(ed->wMaxPacketSize); | | 196 | sc->sc_isize = UGETW(ed->wMaxPacketSize); |
202 | } | | 197 | } |
203 | } | | 198 | } |
204 | | | 199 | |
205 | if (sc->sc_intr_number== -1) { | | 200 | if (sc->sc_intr_number== -1) { |
206 | aprint_error_dev(self, "Could not find interrupt in\n"); | | 201 | aprint_error_dev(self, "Could not find interrupt in\n"); |
207 | sc->sc_dying = 1; | | 202 | sc->sc_dying = 1; |
208 | return; | | 203 | return; |
209 | } | | 204 | } |
210 | | | 205 | |
211 | usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, | | 206 | /* Newer controllers need an activation command */ |
212 | sc->sc_dev); | | 207 | req.bmRequestType = UT_WRITE_VENDOR_DEVICE; |
| | | 208 | req.bRequest = 0x0a; |
| | | 209 | USETW(req.wValue, 'A'); |
| | | 210 | USETW(req.wIndex, 0); |
| | | 211 | USETW(req.wLength, 1); |
| | | 212 | usbd_do_request(dev, &req, &act); |
| | | 213 | |
| | | 214 | usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); |
213 | | | 215 | |
214 | a.accessops = &uep_accessops; | | 216 | a.accessops = &uep_accessops; |
215 | a.accesscookie = sc; | | 217 | a.accesscookie = sc; |
216 | | | 218 | |
217 | sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint); | | 219 | sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint); |
218 | | | 220 | |
219 | tpcalib_init(&sc->sc_tpcalib); | | 221 | tpcalib_init(&sc->sc_tpcalib); |
220 | tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS, | | 222 | tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS, |
221 | (void *)&default_calib, 0, 0); | | 223 | (void *)&default_calib, 0, 0); |
222 | | | 224 | |
223 | return; | | 225 | return; |
224 | } | | 226 | } |
225 | | | 227 | |
226 | int | | 228 | int |
227 | uep_detach(device_t self, int flags) | | 229 | uep_detach(device_t self, int flags) |
228 | { | | 230 | { |
229 | struct uep_softc *sc = device_private(self); | | 231 | struct uep_softc *sc = device_private(self); |
230 | int rv = 0; | | 232 | int rv = 0; |
231 | | | 233 | |
232 | if (sc->sc_intr_pipe != NULL) { | | 234 | if (sc->sc_intr_pipe != NULL) { |
233 | usbd_abort_pipe(sc->sc_intr_pipe); | | 235 | usbd_abort_pipe(sc->sc_intr_pipe); |
234 | usbd_close_pipe(sc->sc_intr_pipe); | | 236 | usbd_close_pipe(sc->sc_intr_pipe); |
235 | sc->sc_intr_pipe = NULL; | | 237 | sc->sc_intr_pipe = NULL; |
236 | } | | 238 | } |
237 | | | | |
238 | sc->sc_dying = 1; | | 239 | sc->sc_dying = 1; |
239 | | | 240 | |
240 | /* save current calib as defaults */ | | 241 | /* save current calib as defaults */ |
241 | default_calib = sc->sc_tpcalib.sc_saved; | | 242 | default_calib = sc->sc_tpcalib.sc_saved; |
242 | | | 243 | |
243 | if (sc->sc_wsmousedev != NULL) | | 244 | if (sc->sc_wsmousedev != NULL) |
244 | rv = config_detach(sc->sc_wsmousedev, flags); | | 245 | rv = config_detach(sc->sc_wsmousedev, flags); |
245 | | | 246 | |
246 | usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, | | 247 | usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); |
247 | sc->sc_dev); | | | |
248 | | | | |
249 | return rv; | | 248 | return rv; |
250 | } | | 249 | } |
251 | | | 250 | |
252 | void | | 251 | void |
253 | uep_childdet(device_t self, device_t child) | | 252 | uep_childdet(device_t self, device_t child) |
254 | { | | 253 | { |
255 | struct uep_softc *sc = device_private(self); | | 254 | struct uep_softc *sc = device_private(self); |
256 | | | 255 | |
257 | KASSERT(sc->sc_wsmousedev == child); | | 256 | KASSERT(sc->sc_wsmousedev == child); |
258 | sc->sc_wsmousedev = NULL; | | 257 | sc->sc_wsmousedev = NULL; |
259 | } | | 258 | } |
260 | | | 259 | |
261 | int | | 260 | int |
| @@ -276,26 +275,27 @@ Static int | | | @@ -276,26 +275,27 @@ Static int |
276 | uep_enable(void *v) | | 275 | uep_enable(void *v) |
277 | { | | 276 | { |
278 | struct uep_softc *sc = v; | | 277 | struct uep_softc *sc = v; |
279 | int err; | | 278 | int err; |
280 | | | 279 | |
281 | if (sc->sc_dying) | | 280 | if (sc->sc_dying) |
282 | return EIO; | | 281 | return EIO; |
283 | | | 282 | |
284 | if (sc->sc_enabled) | | 283 | if (sc->sc_enabled) |
285 | return EBUSY; | | 284 | return EBUSY; |
286 | | | 285 | |
287 | if (sc->sc_isize == 0) | | 286 | if (sc->sc_isize == 0) |
288 | return 0; | | 287 | return 0; |
| | | 288 | |
289 | sc->sc_ibuf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK); | | 289 | sc->sc_ibuf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK); |
290 | err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_intr_number, | | 290 | err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_intr_number, |
291 | USBD_SHORT_XFER_OK, &sc->sc_intr_pipe, sc, sc->sc_ibuf, | | 291 | USBD_SHORT_XFER_OK, &sc->sc_intr_pipe, sc, sc->sc_ibuf, |
292 | sc->sc_isize, uep_intr, USBD_DEFAULT_INTERVAL); | | 292 | sc->sc_isize, uep_intr, USBD_DEFAULT_INTERVAL); |
293 | if (err) { | | 293 | if (err) { |
294 | free(sc->sc_ibuf, M_USBDEV); | | 294 | free(sc->sc_ibuf, M_USBDEV); |
295 | sc->sc_intr_pipe = NULL; | | 295 | sc->sc_intr_pipe = NULL; |
296 | return EIO; | | 296 | return EIO; |
297 | } | | 297 | } |
298 | | | 298 | |
299 | sc->sc_enabled = 1; | | 299 | sc->sc_enabled = 1; |
300 | | | 300 | |
301 | return 0; | | 301 | return 0; |
| @@ -354,75 +354,90 @@ uep_ioctl(void *v, u_long cmd, void *dat | | | @@ -354,75 +354,90 @@ uep_ioctl(void *v, u_long cmd, void *dat |
354 | case WSMOUSEIO_SCALIBCOORDS: | | 354 | case WSMOUSEIO_SCALIBCOORDS: |
355 | case WSMOUSEIO_GCALIBCOORDS: | | 355 | case WSMOUSEIO_GCALIBCOORDS: |
356 | return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, l); | | 356 | return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, l); |
357 | } | | 357 | } |
358 | | | 358 | |
359 | return EPASSTHROUGH; | | 359 | return EPASSTHROUGH; |
360 | } | | 360 | } |
361 | | | 361 | |
362 | void | | 362 | void |
363 | uep_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) | | 363 | uep_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) |
364 | { | | 364 | { |
365 | struct uep_softc *sc = addr; | | 365 | struct uep_softc *sc = addr; |
366 | u_char *p = sc->sc_ibuf; | | 366 | u_char *p = sc->sc_ibuf; |
| | | 367 | u_char msk; |
367 | u_int32_t len; | | 368 | u_int32_t len; |
368 | int x = 0, y = 0, s; | | 369 | int x = 0, y = 0, s; |
369 | | | 370 | |
370 | usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL); | | 371 | usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL); |
371 | | | 372 | |
372 | if (status == USBD_CANCELLED) | | 373 | if (status == USBD_CANCELLED) |
373 | return; | | 374 | return; |
374 | | | 375 | |
375 | if (status != USBD_NORMAL_COMPLETION) { | | 376 | if (status != USBD_NORMAL_COMPLETION) { |
376 | aprint_error_dev(sc->sc_dev, "status %d\n", status); | | 377 | aprint_error_dev(sc->sc_dev, "status %d\n", status); |
377 | usbd_clear_endpoint_stall_async(sc->sc_intr_pipe); | | 378 | usbd_clear_endpoint_stall_async(sc->sc_intr_pipe); |
378 | return; | | 379 | return; |
379 | } | | 380 | } |
380 | | | 381 | |
381 | if (len != 5) { | | 382 | /* First bit is always set to 1 */ |
382 | #if 0 | | 383 | if ((p[0] & 0x80) != 0x80) { |
383 | printf("%s: bad input length %d != %d\n", | | 384 | aprint_error_dev(sc->sc_dev, "bad input packet format\n"); |
384 | device_xname(sc->sc_dev), len, sc->sc_isize); | | | |
385 | #endif | | | |
386 | return; | | | |
387 | } | | | |
388 | | | | |
389 | if ((p[0] & 0xFE) != 0x80) { | | | |
390 | aprint_error_dev(sc->sc_dev, | | | |
391 | "bad input packet format\n"); | | | |
392 | return; | | 385 | return; |
393 | } | | 386 | } |
394 | | | 387 | |
395 | if (sc->sc_wsmousedev != NULL) { | | 388 | if (sc->sc_wsmousedev != NULL) { |
396 | /* | | 389 | /* |
397 | * Packet format is 5 bytes: | | 390 | * Each report package may contain 5 or 6 bytes as below: |
398 | * | | 391 | * |
399 | * 1000000T | | 392 | * Byte 0 1ZM00HLT |
400 | * 0000AAAA | | 393 | * Byte 1 0AAAAAAA |
401 | * 0AAAAAAA | | 394 | * Byte 2 0AAAAAAA |
402 | * 0000BBBB | | 395 | * Byte 3 0BBBBBBB |
403 | * 0BBBBBBB | | 396 | * Byte 4 0BBBBBBB |
404 | * | | 397 | * Byte 5 0PPPPPPP |
405 | * T: 1=touched 0=not touched | | 398 | * |
406 | * A: bits of axis A position, MSB to LSB | | 399 | * Z: 1=byte 5 is pressure information, 0=no pressure |
407 | * B: bits of axis B position, MSB to LSB | | 400 | * M: 1=byte 5 is play id, 0=no player id |
408 | * | | 401 | * T: 1=touched, 0=not touched |
409 | * For the unit I have, A = Y and B = X. | | 402 | * H,L: Resolution |
410 | * I don't know if units exist with A=X and B=Y, | | 403 | * 0,0: 11 bits |
411 | * if so we'll cross that bridge when we come to it. | | 404 | * 0,1: 12 bits |
412 | * | | 405 | * 1,0: 13 bits |
413 | * The controller sends a stream of T=1 events while the | | 406 | * 1,1: 14 bits |
414 | * panel is touched, followed by a single T=0 event. | | 407 | * A: bits of axis A position, MSB to LSB |
415 | * | | 408 | * B: bits of axis B position, MSB to LSB |
416 | */ | | 409 | * |
417 | | | 410 | * The packet has six bytes only if Z or M is set. |
418 | x = (p[3] << 7) | p[4]; | | 411 | * Byte 5, if sent, is ignored. |
419 | y = (p[1] << 7) | p[2]; | | 412 | * |
| | | 413 | * For the unit I have, A = Y and B = X. |
| | | 414 | * I don't know if units exist with A=X and B=Y, |
| | | 415 | * if so we'll cross that bridge when we come to it. |
| | | 416 | * |
| | | 417 | * The controller sends a stream of T=1 events while the |
| | | 418 | * panel is touched, followed by a single T=0 event. |
| | | 419 | */ |
| | | 420 | switch (p[0] & 0x06) { |
| | | 421 | case 0x02: |
| | | 422 | msk = 0x1f; |
| | | 423 | break; |
| | | 424 | case 0x04: |
| | | 425 | msk = 0x3f; |
| | | 426 | break; |
| | | 427 | case 0x06: |
| | | 428 | msk = 0x7f; |
| | | 429 | break; |
| | | 430 | default: |
| | | 431 | msk = 0x0f; /* H=0, L=0 */ |
| | | 432 | } |
| | | 433 | x = ((p[3] & msk) << 7) | p[4]; |
| | | 434 | y = ((p[1] & msk) << 7) | p[2]; |
420 | | | 435 | |
421 | tpcalib_trans(&sc->sc_tpcalib, x, y, &x, &y); | | 436 | tpcalib_trans(&sc->sc_tpcalib, x, y, &x, &y); |
422 | | | 437 | |
423 | s = spltty(); | | 438 | s = spltty(); |
424 | wsmouse_input(sc->sc_wsmousedev, p[0] & 0x01, x, y, 0, 0, | | 439 | wsmouse_input(sc->sc_wsmousedev, p[0] & 0x01, x, y, 0, 0, |
425 | WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y); | | 440 | WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y); |
426 | splx(s); | | 441 | splx(s); |
427 | } | | 442 | } |
428 | } | | 443 | } |