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