1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright 2010, Gleb Smirnoff <glebius@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 /* 32 * http://www.eeti.com.tw/pdf/Software%20Programming%20Guide_v2.0.pdf 33 */ 34 35 #include <sys/param.h> 36 #include <sys/bus.h> 37 #include <sys/callout.h> 38 #include <sys/conf.h> 39 #include <sys/kernel.h> 40 #include <sys/lock.h> 41 #include <sys/module.h> 42 #include <sys/mutex.h> 43 #include <sys/sysctl.h> 44 #include <sys/systm.h> 45 46 #include <dev/usb/usb.h> 47 #include <dev/usb/usbdi.h> 48 #include <dev/usb/usbdi_util.h> 49 #include <dev/usb/usbhid.h> 50 #include "usbdevs.h" 51 52 #include <sys/ioccom.h> 53 #include <sys/fcntl.h> 54 #include <sys/tty.h> 55 56 #define USB_DEBUG_VAR uep_debug 57 #include <dev/usb/usb_debug.h> 58 59 #ifdef USB_DEBUG 60 static int uep_debug = 0; 61 62 static SYSCTL_NODE(_hw_usb, OID_AUTO, uep, CTLFLAG_RW, 0, "USB uep"); 63 SYSCTL_INT(_hw_usb_uep, OID_AUTO, debug, CTLFLAG_RWTUN, 64 &uep_debug, 0, "Debug level"); 65 #endif 66 67 #define UEP_MAX_X 2047 68 #define UEP_MAX_Y 2047 69 70 #define UEP_DOWN 0x01 71 #define UEP_PACKET_LEN_MAX 16 72 #define UEP_PACKET_LEN_REPORT 5 73 #define UEP_PACKET_LEN_REPORT2 6 74 #define UEP_PACKET_DIAG 0x0a 75 #define UEP_PACKET_REPORT_MASK 0xe0 76 #define UEP_PACKET_REPORT 0x80 77 #define UEP_PACKET_REPORT_PRESSURE 0xc0 78 #define UEP_PACKET_REPORT_PLAYER 0xa0 79 #define UEP_PACKET_LEN_MASK 80 81 #define UEP_FIFO_BUF_SIZE 8 /* bytes */ 82 #define UEP_FIFO_QUEUE_MAXLEN 50 /* units */ 83 84 enum { 85 UEP_INTR_DT, 86 UEP_N_TRANSFER, 87 }; 88 89 struct uep_softc { 90 struct mtx mtx; 91 92 struct usb_xfer *xfer[UEP_N_TRANSFER]; 93 struct usb_fifo_sc fifo; 94 95 u_int pollrate; 96 u_int state; 97 #define UEP_ENABLED 0x01 98 99 /* Reassembling buffer. */ 100 u_char buf[UEP_PACKET_LEN_MAX]; 101 uint8_t buf_len; 102 }; 103 104 static usb_callback_t uep_intr_callback; 105 106 static device_probe_t uep_probe; 107 static device_attach_t uep_attach; 108 static device_detach_t uep_detach; 109 110 static usb_fifo_cmd_t uep_start_read; 111 static usb_fifo_cmd_t uep_stop_read; 112 static usb_fifo_open_t uep_open; 113 static usb_fifo_close_t uep_close; 114 115 static void uep_put_queue(struct uep_softc *, u_char *); 116 117 static struct usb_fifo_methods uep_fifo_methods = { 118 .f_open = &uep_open, 119 .f_close = &uep_close, 120 .f_start_read = &uep_start_read, 121 .f_stop_read = &uep_stop_read, 122 .basename[0] = "uep", 123 }; 124 125 static int 126 get_pkt_len(u_char *buf) 127 { 128 if (buf[0] == UEP_PACKET_DIAG) { 129 int len; 130 131 len = buf[1] + 2; 132 if (len > UEP_PACKET_LEN_MAX) { 133 DPRINTF("bad packet len %u\n", len); 134 return (UEP_PACKET_LEN_MAX); 135 } 136 137 return (len); 138 } 139 140 switch (buf[0] & UEP_PACKET_REPORT_MASK) { 141 case UEP_PACKET_REPORT: 142 return (UEP_PACKET_LEN_REPORT); 143 case UEP_PACKET_REPORT_PRESSURE: 144 case UEP_PACKET_REPORT_PLAYER: 145 case UEP_PACKET_REPORT_PRESSURE | UEP_PACKET_REPORT_PLAYER: 146 return (UEP_PACKET_LEN_REPORT2); 147 default: 148 DPRINTF("bad packet len 0\n"); 149 return (0); 150 } 151 } 152 153 static void 154 uep_process_pkt(struct uep_softc *sc, u_char *buf) 155 { 156 int32_t x, y; 157 158 if ((buf[0] & 0xFE) != 0x80) { 159 DPRINTF("bad input packet format 0x%.2x\n", buf[0]); 160 return; 161 } 162 163 /* 164 * Packet format is 5 bytes: 165 * 166 * 1000000T 167 * 0000AAAA 168 * 0AAAAAAA 169 * 0000BBBB 170 * 0BBBBBBB 171 * 172 * T: 1=touched 0=not touched 173 * A: bits of axis A position, MSB to LSB 174 * B: bits of axis B position, MSB to LSB 175 * 176 * For the unit I have, which is CTF1020-S from CarTFT.com, 177 * A = X and B = Y. But in NetBSD uep(4) it is other way round :) 178 * 179 * The controller sends a stream of T=1 events while the 180 * panel is touched, followed by a single T=0 event. 181 * 182 */ 183 184 x = (buf[1] << 7) | buf[2]; 185 y = (buf[3] << 7) | buf[4]; 186 187 DPRINTFN(2, "x %u y %u\n", x, y); 188 189 uep_put_queue(sc, buf); 190 } 191 192 static void 193 uep_intr_callback(struct usb_xfer *xfer, usb_error_t error) 194 { 195 struct uep_softc *sc = usbd_xfer_softc(xfer); 196 int len; 197 198 usbd_xfer_status(xfer, &len, NULL, NULL, NULL); 199 200 switch (USB_GET_STATE(xfer)) { 201 case USB_ST_TRANSFERRED: 202 { 203 struct usb_page_cache *pc; 204 u_char buf[17], *p; 205 int pkt_len; 206 207 if (len > (int)sizeof(buf)) { 208 DPRINTF("bad input length %d\n", len); 209 goto tr_setup; 210 } 211 212 pc = usbd_xfer_get_frame(xfer, 0); 213 usbd_copy_out(pc, 0, buf, len); 214 215 /* 216 * The below code mimics Linux a lot. I don't know 217 * why NetBSD reads complete packets, but we need 218 * to reassamble 'em like Linux does (tries?). 219 */ 220 if (sc->buf_len > 0) { 221 int res; 222 223 if (sc->buf_len == 1) 224 sc->buf[1] = buf[0]; 225 226 if ((pkt_len = get_pkt_len(sc->buf)) == 0) 227 goto tr_setup; 228 229 res = pkt_len - sc->buf_len; 230 memcpy(sc->buf + sc->buf_len, buf, res); 231 uep_process_pkt(sc, sc->buf); 232 sc->buf_len = 0; 233 234 p = buf + res; 235 len -= res; 236 } else 237 p = buf; 238 239 if (len == 1) { 240 sc->buf[0] = buf[0]; 241 sc->buf_len = 1; 242 243 goto tr_setup; 244 } 245 246 while (len > 0) { 247 if ((pkt_len = get_pkt_len(p)) == 0) 248 goto tr_setup; 249 250 /* full packet: process */ 251 if (pkt_len <= len) { 252 uep_process_pkt(sc, p); 253 } else { 254 /* incomplete packet: save in buffer */ 255 memcpy(sc->buf, p, len); 256 sc->buf_len = len; 257 } 258 p += pkt_len; 259 len -= pkt_len; 260 } 261 } 262 case USB_ST_SETUP: 263 tr_setup: 264 /* check if we can put more data into the FIFO */ 265 if (usb_fifo_put_bytes_max(sc->fifo.fp[USB_FIFO_RX]) != 0) { 266 usbd_xfer_set_frame_len(xfer, 0, 267 usbd_xfer_max_len(xfer)); 268 usbd_transfer_submit(xfer); 269 } 270 break; 271 272 default: 273 if (error != USB_ERR_CANCELLED) { 274 /* try clear stall first */ 275 usbd_xfer_set_stall(xfer); 276 goto tr_setup; 277 } 278 break; 279 } 280 } 281 282 static const struct usb_config uep_config[UEP_N_TRANSFER] = { 283 [UEP_INTR_DT] = { 284 .type = UE_INTERRUPT, 285 .endpoint = UE_ADDR_ANY, 286 .direction = UE_DIR_IN, 287 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 288 .bufsize = 0, /* use wMaxPacketSize */ 289 .callback = &uep_intr_callback, 290 }, 291 }; 292 293 static const STRUCT_USB_HOST_ID uep_devs[] = { 294 {USB_VPI(USB_VENDOR_EGALAX, USB_PRODUCT_EGALAX_TPANEL, 0)}, 295 {USB_VPI(USB_VENDOR_EGALAX, USB_PRODUCT_EGALAX_TPANEL2, 0)}, 296 {USB_VPI(USB_VENDOR_EGALAX2, USB_PRODUCT_EGALAX2_TPANEL, 0)}, 297 }; 298 299 static int 300 uep_probe(device_t dev) 301 { 302 struct usb_attach_arg *uaa = device_get_ivars(dev); 303 304 if (uaa->usb_mode != USB_MODE_HOST) 305 return (ENXIO); 306 if (uaa->info.bConfigIndex != 0) 307 return (ENXIO); 308 if (uaa->info.bIfaceIndex != 0) 309 return (ENXIO); 310 311 return (usbd_lookup_id_by_uaa(uep_devs, sizeof(uep_devs), uaa)); 312 } 313 314 static int 315 uep_attach(device_t dev) 316 { 317 struct usb_attach_arg *uaa = device_get_ivars(dev); 318 struct uep_softc *sc = device_get_softc(dev); 319 int error; 320 321 device_set_usb_desc(dev); 322 323 mtx_init(&sc->mtx, "uep lock", NULL, MTX_DEF); 324 325 error = usbd_transfer_setup(uaa->device, &uaa->info.bIfaceIndex, 326 sc->xfer, uep_config, UEP_N_TRANSFER, sc, &sc->mtx); 327 328 if (error) { 329 DPRINTF("usbd_transfer_setup error=%s\n", usbd_errstr(error)); 330 goto detach; 331 } 332 333 error = usb_fifo_attach(uaa->device, sc, &sc->mtx, &uep_fifo_methods, 334 &sc->fifo, device_get_unit(dev), -1, uaa->info.bIfaceIndex, 335 UID_ROOT, GID_OPERATOR, 0644); 336 337 if (error) { 338 DPRINTF("usb_fifo_attach error=%s\n", usbd_errstr(error)); 339 goto detach; 340 } 341 342 sc->buf_len = 0; 343 344 return (0); 345 346 detach: 347 uep_detach(dev); 348 349 return (ENOMEM); /* XXX */ 350 } 351 352 static int 353 uep_detach(device_t dev) 354 { 355 struct uep_softc *sc = device_get_softc(dev); 356 357 usb_fifo_detach(&sc->fifo); 358 359 usbd_transfer_unsetup(sc->xfer, UEP_N_TRANSFER); 360 361 mtx_destroy(&sc->mtx); 362 363 return (0); 364 } 365 366 static void 367 uep_start_read(struct usb_fifo *fifo) 368 { 369 struct uep_softc *sc = usb_fifo_softc(fifo); 370 u_int rate; 371 372 if ((rate = sc->pollrate) > 1000) 373 rate = 1000; 374 375 if (rate > 0 && sc->xfer[UEP_INTR_DT] != NULL) { 376 usbd_transfer_stop(sc->xfer[UEP_INTR_DT]); 377 usbd_xfer_set_interval(sc->xfer[UEP_INTR_DT], 1000 / rate); 378 sc->pollrate = 0; 379 } 380 381 usbd_transfer_start(sc->xfer[UEP_INTR_DT]); 382 } 383 384 static void 385 uep_stop_read(struct usb_fifo *fifo) 386 { 387 struct uep_softc *sc = usb_fifo_softc(fifo); 388 389 usbd_transfer_stop(sc->xfer[UEP_INTR_DT]); 390 } 391 392 static void 393 uep_put_queue(struct uep_softc *sc, u_char *buf) 394 { 395 usb_fifo_put_data_linear(sc->fifo.fp[USB_FIFO_RX], buf, 396 UEP_PACKET_LEN_REPORT, 1); 397 } 398 399 static int 400 uep_open(struct usb_fifo *fifo, int fflags) 401 { 402 if (fflags & FREAD) { 403 struct uep_softc *sc = usb_fifo_softc(fifo); 404 405 if (sc->state & UEP_ENABLED) 406 return (EBUSY); 407 if (usb_fifo_alloc_buffer(fifo, UEP_FIFO_BUF_SIZE, 408 UEP_FIFO_QUEUE_MAXLEN)) 409 return (ENOMEM); 410 411 sc->state |= UEP_ENABLED; 412 } 413 414 return (0); 415 } 416 417 static void 418 uep_close(struct usb_fifo *fifo, int fflags) 419 { 420 if (fflags & FREAD) { 421 struct uep_softc *sc = usb_fifo_softc(fifo); 422 423 sc->state &= ~(UEP_ENABLED); 424 usb_fifo_free_buffer(fifo); 425 } 426 } 427 428 static devclass_t uep_devclass; 429 430 static device_method_t uep_methods[] = { 431 DEVMETHOD(device_probe, uep_probe), 432 DEVMETHOD(device_attach, uep_attach), 433 DEVMETHOD(device_detach, uep_detach), 434 { 0, 0 }, 435 }; 436 437 static driver_t uep_driver = { 438 .name = "uep", 439 .methods = uep_methods, 440 .size = sizeof(struct uep_softc), 441 }; 442 443 DRIVER_MODULE(uep, uhub, uep_driver, uep_devclass, NULL, NULL); 444 MODULE_DEPEND(uep, usb, 1, 1, 1); 445 MODULE_VERSION(uep, 1); 446 USB_PNP_HOST_INFO(uep_devs); 447