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