1 /* $NetBSD: uirda.c,v 1.40 2016/07/07 06:55:42 msaitoh Exp $ */ 2 3 /* 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Lennart Augustsson (lennart@augustsson.net). 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 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 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 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: uirda.c,v 1.40 2016/07/07 06:55:42 msaitoh Exp $"); 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/kernel.h> 38 #include <sys/device.h> 39 #include <sys/mutex.h> 40 #include <sys/ioctl.h> 41 #include <sys/conf.h> 42 #include <sys/file.h> 43 #include <sys/poll.h> 44 #include <sys/select.h> 45 #include <sys/proc.h> 46 47 #include <dev/usb/usb.h> 48 #include <dev/usb/usbdi.h> 49 #include <dev/usb/usbdi_util.h> 50 #include <dev/usb/usbdevs.h> 51 52 #include <dev/ir/ir.h> 53 #include <dev/ir/irdaio.h> 54 #include <dev/ir/irframevar.h> 55 56 #include <dev/usb/uirdavar.h> 57 58 #ifdef UIRDA_DEBUG 59 #define DPRINTF(x) if (uirdadebug) printf x 60 #define DPRINTFN(n,x) if (uirdadebug>(n)) printf x 61 int uirdadebug = 0; 62 #else 63 #define DPRINTF(x) 64 #define DPRINTFN(n,x) 65 #endif 66 67 68 /* Class specific requests */ 69 #define UR_IRDA_RECEIVING 0x01 /* Receive in progress? */ 70 #define UR_IRDA_CHECK_MEDIA_BUSY 0x03 71 #define UR_IRDA_SET_RATE_SNIFF 0x04 /* opt */ 72 #define UR_IRDA_SET_UNICAST_LIST 0x05 /* opt */ 73 #define UR_IRDA_GET_DESC 0x06 74 75 #define UIRDA_NEBOFS 8 76 static struct { 77 int count; 78 int mask; 79 int header; 80 } uirda_ebofs[UIRDA_NEBOFS] = { 81 { 0, UI_EB_0, UIRDA_EB_0 }, 82 { 1, UI_EB_1, UIRDA_EB_1 }, 83 { 2, UI_EB_2, UIRDA_EB_2 }, 84 { 3, UI_EB_3, UIRDA_EB_3 }, 85 { 6, UI_EB_6, UIRDA_EB_6 }, 86 { 12, UI_EB_12, UIRDA_EB_12 }, 87 { 24, UI_EB_24, UIRDA_EB_24 }, 88 { 48, UI_EB_48, UIRDA_EB_48 } 89 }; 90 91 #define UIRDA_NSPEEDS 9 92 static struct { 93 int speed; 94 int mask; 95 int header; 96 } uirda_speeds[UIRDA_NSPEEDS] = { 97 { 4000000, UI_BR_4000000, UIRDA_4000000 }, 98 { 1152000, UI_BR_1152000, UIRDA_1152000 }, 99 { 576000, UI_BR_576000, UIRDA_576000 }, 100 { 115200, UI_BR_115200, UIRDA_115200 }, 101 { 57600, UI_BR_57600, UIRDA_57600 }, 102 { 38400, UI_BR_38400, UIRDA_38400 }, 103 { 19200, UI_BR_19200, UIRDA_19200 }, 104 { 9600, UI_BR_9600, UIRDA_9600 }, 105 { 2400, UI_BR_2400, UIRDA_2400 }, 106 }; 107 108 109 110 int uirda_open(void *, int, int, struct lwp *); 111 int uirda_close(void *, int, int, struct lwp *); 112 int uirda_read(void *, struct uio *, int); 113 int uirda_write(void *, struct uio *, int); 114 int uirda_set_params(void *, struct irda_params *); 115 int uirda_get_speeds(void *, int *); 116 int uirda_get_turnarounds(void *, int *); 117 int uirda_poll(void *, int, struct lwp *); 118 int uirda_kqfilter(void *, struct knote *); 119 120 struct irframe_methods uirda_methods = { 121 uirda_open, uirda_close, uirda_read, uirda_write, uirda_poll, 122 uirda_kqfilter, uirda_set_params, uirda_get_speeds, 123 uirda_get_turnarounds 124 }; 125 126 void uirda_rd_cb(struct usbd_xfer *xfer, void *priv, 127 usbd_status status); 128 usbd_status uirda_start_read(struct uirda_softc *sc); 129 130 /* 131 * These devices don't quite follow the spec. Speed changing is broken 132 * and they don't handle windows. 133 * But we change speed in a safe way, and don't use windows now. 134 * Some devices also seem to have an interrupt pipe that can be ignored. 135 * 136 * Table information taken from Linux driver. 137 */ 138 Static const struct usb_devno uirda_devs[] = { 139 { USB_VENDOR_ACTISYS, USB_PRODUCT_ACTISYS_IR2000U }, 140 { USB_VENDOR_EXTENDED, USB_PRODUCT_EXTENDED_XTNDACCESS }, 141 { USB_VENDOR_KAWATSU, USB_PRODUCT_KAWATSU_KC180 }, 142 }; 143 #define uirda_lookup(v, p) (usb_lookup(uirda_devs, v, p)) 144 145 int uirda_match(device_t, cfdata_t, void *); 146 void uirda_attach(device_t, device_t, void *); 147 void uirda_childdet(device_t, device_t); 148 int uirda_detach(device_t, int); 149 int uirda_activate(device_t, enum devact); 150 extern struct cfdriver uirda_cd; 151 CFATTACH_DECL2_NEW(uirda, sizeof(struct uirda_softc), uirda_match, 152 uirda_attach, uirda_detach, uirda_activate, NULL, uirda_childdet); 153 154 int 155 uirda_match(device_t parent, cfdata_t match, void *aux) 156 { 157 struct usbif_attach_arg *uiaa = aux; 158 159 DPRINTFN(50,("uirda_match\n")); 160 161 if (uirda_lookup(uiaa->uiaa_vendor, uiaa->uiaa_product) != NULL) 162 return UMATCH_VENDOR_PRODUCT; 163 164 if (uiaa->uiaa_class == UICLASS_APPL_SPEC && 165 uiaa->uiaa_subclass == UISUBCLASS_IRDA && 166 uiaa->uiaa_proto == UIPROTO_IRDA) 167 return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO; 168 return UMATCH_NONE; 169 } 170 171 void 172 uirda_attach(device_t parent, device_t self, void *aux) 173 { 174 struct uirda_softc *sc = device_private(self); 175 struct usbif_attach_arg *uiaa = aux; 176 struct usbd_device * dev = uiaa->uiaa_device; 177 struct usbd_interface *iface = uiaa->uiaa_iface; 178 char *devinfop; 179 usb_endpoint_descriptor_t *ed; 180 usbd_status err; 181 uint8_t epcount; 182 u_int specrev; 183 int i; 184 struct ir_attach_args ia; 185 186 DPRINTFN(10,("uirda_attach: sc=%p\n", sc)); 187 188 sc->sc_dev = self; 189 190 aprint_naive("\n"); 191 aprint_normal("\n"); 192 193 devinfop = usbd_devinfo_alloc(dev, 0); 194 aprint_normal_dev(self, "%s\n", devinfop); 195 usbd_devinfo_free(devinfop); 196 197 sc->sc_udev = dev; 198 sc->sc_iface = iface; 199 200 if (sc->sc_hdszi == 0) 201 sc->sc_hdszi = UIRDA_INPUT_HEADER_SIZE; 202 203 epcount = 0; 204 (void)usbd_endpoint_count(iface, &epcount); 205 206 sc->sc_rd_addr = -1; 207 sc->sc_wr_addr = -1; 208 for (i = 0; i < epcount; i++) { 209 ed = usbd_interface2endpoint_descriptor(iface, i); 210 if (ed == NULL) { 211 aprint_error_dev(self, "couldn't get ep %d\n", i); 212 return; 213 } 214 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 215 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 216 sc->sc_rd_addr = ed->bEndpointAddress; 217 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 218 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 219 sc->sc_wr_addr = ed->bEndpointAddress; 220 } 221 } 222 if (sc->sc_rd_addr == -1 || sc->sc_wr_addr == -1) { 223 aprint_error_dev(self, "missing endpoint\n"); 224 return; 225 } 226 227 if (sc->sc_loadfw(sc) != 0) { 228 return; 229 } 230 231 /* Get the IrDA descriptor */ 232 err = usbd_get_class_desc(sc->sc_udev, UDESC_IRDA, 0, 233 USB_IRDA_DESCRIPTOR_SIZE, &sc->sc_irdadesc); 234 aprint_error_dev(self, "error %d reading class desc\n", err); 235 if (err) { 236 err = usbd_get_desc(sc->sc_udev, UDESC_IRDA, 0, 237 USB_IRDA_DESCRIPTOR_SIZE, &sc->sc_irdadesc); 238 } 239 aprint_error_dev(self, "error %d reading desc\n", err); 240 if (err) { 241 /* maybe it's embedded in the config desc? */ 242 usbd_desc_iter_t iter; 243 const usb_descriptor_t *d; 244 usb_desc_iter_init(sc->sc_udev, &iter); 245 for (;;) { 246 d = usb_desc_iter_next(&iter); 247 if (!d || d->bDescriptorType == UDESC_IRDA) 248 break; 249 } 250 if (d == NULL) { 251 aprint_error_dev(self, 252 "Cannot get IrDA descriptor\n"); 253 return; 254 } 255 memcpy(&sc->sc_irdadesc, d, USB_IRDA_DESCRIPTOR_SIZE); 256 } 257 DPRINTF(("uirda_attach: bDescriptorSize %d bDescriptorType 0x%x " 258 "bmDataSize=0x%02x bmWindowSize=0x%02x " 259 "bmMinTurnaroundTime=0x%02x wBaudRate=0x%04x " 260 "bmAdditionalBOFs=0x%02x bIrdaSniff=%d bMaxUnicastList=%d\n", 261 sc->sc_irdadesc.bLength, 262 sc->sc_irdadesc.bDescriptorType, 263 sc->sc_irdadesc.bmDataSize, 264 sc->sc_irdadesc.bmWindowSize, 265 sc->sc_irdadesc.bmMinTurnaroundTime, 266 UGETW(sc->sc_irdadesc.wBaudRate), 267 sc->sc_irdadesc.bmAdditionalBOFs, 268 sc->sc_irdadesc.bIrdaSniff, 269 sc->sc_irdadesc.bMaxUnicastList)); 270 271 specrev = UGETW(sc->sc_irdadesc.bcdSpecRevision); 272 aprint_normal_dev(self, "USB-IrDA protocol version %x.%02x\n", 273 specrev >> 8, specrev & 0xff); 274 275 DPRINTFN(10, ("uirda_attach: %p\n", sc->sc_udev)); 276 277 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); 278 279 mutex_init(&sc->sc_wr_buf_lk, MUTEX_DEFAULT, IPL_NONE); 280 mutex_init(&sc->sc_rd_buf_lk, MUTEX_DEFAULT, IPL_NONE); 281 selinit(&sc->sc_rd_sel); 282 selinit(&sc->sc_wr_sel); 283 284 ia.ia_type = IR_TYPE_IRFRAME; 285 ia.ia_methods = sc->sc_irm ? sc->sc_irm : &uirda_methods; 286 ia.ia_handle = sc; 287 288 sc->sc_child = config_found(self, &ia, ir_print); 289 290 return; 291 } 292 293 int 294 uirda_detach(device_t self, int flags) 295 { 296 struct uirda_softc *sc = device_private(self); 297 int s; 298 int rv = 0; 299 300 DPRINTF(("uirda_detach: sc=%p flags=%d\n", sc, flags)); 301 302 sc->sc_dying = 1; 303 /* Abort all pipes. Causes processes waiting for transfer to wake. */ 304 if (sc->sc_rd_pipe != NULL) { 305 usbd_abort_pipe(sc->sc_rd_pipe); 306 } 307 if (sc->sc_wr_pipe != NULL) { 308 usbd_abort_pipe(sc->sc_wr_pipe); 309 } 310 if (sc->sc_rd_xfer != NULL) { 311 usbd_destroy_xfer(sc->sc_rd_xfer); 312 sc->sc_rd_xfer = NULL; 313 sc->sc_rd_buf = NULL; 314 } 315 if (sc->sc_wr_xfer != NULL) { 316 usbd_destroy_xfer(sc->sc_wr_xfer); 317 sc->sc_wr_xfer = NULL; 318 sc->sc_wr_buf = NULL; 319 } 320 if (sc->sc_rd_pipe != NULL) { 321 usbd_close_pipe(sc->sc_rd_pipe); 322 sc->sc_rd_pipe = NULL; 323 } 324 if (sc->sc_wr_pipe != NULL) { 325 usbd_close_pipe(sc->sc_wr_pipe); 326 sc->sc_wr_pipe = NULL; 327 } 328 wakeup(&sc->sc_rd_count); 329 330 s = splusb(); 331 if (--sc->sc_refcnt >= 0) { 332 /* Wait for processes to go away. */ 333 usb_detach_waitold(sc->sc_dev); 334 } 335 splx(s); 336 337 if (sc->sc_child != NULL) 338 rv = config_detach(sc->sc_child, flags); 339 340 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); 341 342 mutex_destroy(&sc->sc_wr_buf_lk); 343 mutex_destroy(&sc->sc_rd_buf_lk); 344 seldestroy(&sc->sc_rd_sel); 345 seldestroy(&sc->sc_wr_sel); 346 347 return rv; 348 } 349 350 void 351 uirda_childdet(device_t self, device_t child) 352 { 353 struct uirda_softc *sc = device_private(self); 354 355 KASSERT(sc->sc_child == child); 356 sc->sc_child = NULL; 357 } 358 359 int 360 uirda_activate(device_t self, enum devact act) 361 { 362 struct uirda_softc *sc = device_private(self); 363 364 switch (act) { 365 case DVACT_DEACTIVATE: 366 sc->sc_dying = 1; 367 return 0; 368 default: 369 return EOPNOTSUPP; 370 } 371 } 372 373 int 374 uirda_open(void *h, int flag, int mode, 375 struct lwp *l) 376 { 377 struct uirda_softc *sc = h; 378 int error; 379 usbd_status err; 380 381 DPRINTF(("%s: sc=%p\n", __func__, sc)); 382 383 err = usbd_open_pipe(sc->sc_iface, sc->sc_rd_addr, 0, &sc->sc_rd_pipe); 384 if (err) { 385 error = EIO; 386 goto bad1; 387 } 388 err = usbd_open_pipe(sc->sc_iface, sc->sc_wr_addr, 0, &sc->sc_wr_pipe); 389 if (err) { 390 error = EIO; 391 goto bad2; 392 } 393 error = usbd_create_xfer(sc->sc_rd_pipe, 394 IRDA_MAX_FRAME_SIZE + sc->sc_hdszi, USBD_SHORT_XFER_OK, 0, 395 &sc->sc_rd_xfer); 396 if (error) 397 goto bad3; 398 sc->sc_rd_buf = usbd_get_buffer(sc->sc_rd_xfer); 399 400 /* worst case ST-UIRDA length */ 401 error = usbd_create_xfer(sc->sc_wr_pipe, 402 IRDA_MAX_FRAME_SIZE + UIRDA_OUTPUT_HEADER_SIZE + 2 + 1, 403 USBD_FORCE_SHORT_XFER, 0, &sc->sc_wr_xfer); 404 if (error) 405 goto bad4; 406 sc->sc_wr_buf = usbd_get_buffer(sc->sc_wr_xfer); 407 408 sc->sc_rd_count = 0; 409 sc->sc_rd_err = 0; 410 sc->sc_params.speed = 0; 411 sc->sc_params.ebofs = 0; 412 sc->sc_params.maxsize = IRDA_MAX_FRAME_SIZE; 413 sc->sc_wr_hdr = -1; 414 415 err = uirda_start_read(sc); 416 /* XXX check err */ 417 418 return 0; 419 420 bad4: 421 usbd_destroy_xfer(sc->sc_rd_xfer); 422 sc->sc_rd_xfer = NULL; 423 bad3: 424 usbd_close_pipe(sc->sc_wr_pipe); 425 sc->sc_wr_pipe = NULL; 426 bad2: 427 usbd_close_pipe(sc->sc_rd_pipe); 428 sc->sc_rd_pipe = NULL; 429 bad1: 430 return error; 431 } 432 433 int 434 uirda_close(void *h, int flag, int mode, 435 struct lwp *l) 436 { 437 struct uirda_softc *sc = h; 438 439 DPRINTF(("%s: sc=%p\n", __func__, sc)); 440 441 if (sc->sc_rd_pipe != NULL) { 442 usbd_abort_pipe(sc->sc_rd_pipe); 443 } 444 if (sc->sc_wr_pipe != NULL) { 445 usbd_abort_pipe(sc->sc_wr_pipe); 446 } 447 if (sc->sc_rd_xfer != NULL) { 448 usbd_destroy_xfer(sc->sc_rd_xfer); 449 sc->sc_rd_xfer = NULL; 450 sc->sc_rd_buf = NULL; 451 } 452 if (sc->sc_wr_xfer != NULL) { 453 usbd_destroy_xfer(sc->sc_wr_xfer); 454 sc->sc_wr_xfer = NULL; 455 sc->sc_wr_buf = NULL; 456 } 457 if (sc->sc_rd_pipe != NULL) { 458 usbd_close_pipe(sc->sc_rd_pipe); 459 sc->sc_rd_pipe = NULL; 460 } 461 if (sc->sc_wr_pipe != NULL) { 462 usbd_close_pipe(sc->sc_wr_pipe); 463 sc->sc_wr_pipe = NULL; 464 } 465 466 return 0; 467 } 468 469 int 470 uirda_read(void *h, struct uio *uio, int flag) 471 { 472 struct uirda_softc *sc = h; 473 int s; 474 int error; 475 u_int n; 476 477 DPRINTFN(1,("%s: sc=%p\n", __func__, sc)); 478 479 if (sc->sc_dying) 480 return EIO; 481 482 #ifdef DIAGNOSTIC 483 if (sc->sc_rd_buf == NULL) 484 return EINVAL; 485 #endif 486 487 sc->sc_refcnt++; 488 489 do { 490 s = splusb(); 491 while (sc->sc_rd_count == 0) { 492 DPRINTFN(5,("uirda_read: calling tsleep()\n")); 493 error = tsleep(&sc->sc_rd_count, PZERO | PCATCH, 494 "uirdrd", 0); 495 if (sc->sc_dying) 496 error = EIO; 497 if (error) { 498 splx(s); 499 DPRINTF(("uirda_read: tsleep() = %d\n", error)); 500 goto ret; 501 } 502 } 503 splx(s); 504 505 mutex_enter(&sc->sc_rd_buf_lk); 506 n = sc->sc_rd_count - sc->sc_hdszi; 507 DPRINTFN(1,("%s: sc=%p n=%u, hdr=0x%02x\n", __func__, 508 sc, n, sc->sc_rd_buf[0])); 509 if (n > uio->uio_resid) 510 error = EINVAL; 511 else 512 error = uiomove(sc->sc_rd_buf + sc->sc_hdszi, n, uio); 513 sc->sc_rd_count = 0; 514 mutex_exit(&sc->sc_rd_buf_lk); 515 516 uirda_start_read(sc); 517 /* XXX check uirda_start_read() return value */ 518 519 } while (n == 0); 520 521 DPRINTFN(1,("uirda_read: return %d\n", error)); 522 523 ret: 524 if (--sc->sc_refcnt < 0) 525 usb_detach_wakeupold(sc->sc_dev); 526 return error; 527 } 528 529 int 530 uirda_write(void *h, struct uio *uio, int flag) 531 { 532 struct uirda_softc *sc = h; 533 usbd_status err; 534 uint32_t n; 535 int error = 0; 536 537 DPRINTFN(1,("%s: sc=%p\n", __func__, sc)); 538 539 if (sc->sc_dying) 540 return EIO; 541 542 #ifdef DIAGNOSTIC 543 if (sc->sc_wr_buf == NULL) 544 return EINVAL; 545 #endif 546 547 n = uio->uio_resid; 548 if (n > sc->sc_params.maxsize) 549 return EINVAL; 550 551 sc->sc_refcnt++; 552 mutex_enter(&sc->sc_wr_buf_lk); 553 554 sc->sc_wr_buf[0] = UIRDA_EB_NO_CHANGE | UIRDA_NO_SPEED; 555 error = uiomove(sc->sc_wr_buf + UIRDA_OUTPUT_HEADER_SIZE, n, uio); 556 if (error) 557 goto done; 558 559 DPRINTFN(1, ("uirdawrite: transfer %d bytes\n", n)); 560 561 n += UIRDA_OUTPUT_HEADER_SIZE; 562 err = usbd_bulk_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe, 563 USBD_FORCE_SHORT_XFER, UIRDA_WR_TIMEOUT, sc->sc_wr_buf, &n); 564 DPRINTFN(2, ("uirdawrite: err=%d\n", err)); 565 if (err) { 566 if (err == USBD_INTERRUPTED) 567 error = EINTR; 568 else if (err == USBD_TIMEOUT) 569 error = ETIMEDOUT; 570 else 571 error = EIO; 572 } 573 done: 574 mutex_exit(&sc->sc_wr_buf_lk); 575 if (--sc->sc_refcnt < 0) 576 usb_detach_wakeupold(sc->sc_dev); 577 578 DPRINTFN(1,("%s: sc=%p done\n", __func__, sc)); 579 return error; 580 } 581 582 int 583 uirda_poll(void *h, int events, struct lwp *l) 584 { 585 struct uirda_softc *sc = h; 586 int revents = 0; 587 int s; 588 589 DPRINTFN(1,("%s: sc=%p\n", __func__, sc)); 590 591 s = splusb(); 592 if (events & (POLLOUT | POLLWRNORM)) 593 revents |= events & (POLLOUT | POLLWRNORM); 594 if (events & (POLLIN | POLLRDNORM)) { 595 if (sc->sc_rd_count != 0) { 596 DPRINTFN(2,("%s: have data\n", __func__)); 597 revents |= events & (POLLIN | POLLRDNORM); 598 } else { 599 DPRINTFN(2,("%s: recording select\n", __func__)); 600 selrecord(l, &sc->sc_rd_sel); 601 } 602 } 603 splx(s); 604 605 return revents; 606 } 607 608 static void 609 filt_uirdardetach(struct knote *kn) 610 { 611 struct uirda_softc *sc = kn->kn_hook; 612 int s; 613 614 s = splusb(); 615 SLIST_REMOVE(&sc->sc_rd_sel.sel_klist, kn, knote, kn_selnext); 616 splx(s); 617 } 618 619 static int 620 filt_uirdaread(struct knote *kn, long hint) 621 { 622 struct uirda_softc *sc = kn->kn_hook; 623 624 kn->kn_data = sc->sc_rd_count; 625 return kn->kn_data > 0; 626 } 627 628 static void 629 filt_uirdawdetach(struct knote *kn) 630 { 631 struct uirda_softc *sc = kn->kn_hook; 632 int s; 633 634 s = splusb(); 635 SLIST_REMOVE(&sc->sc_wr_sel.sel_klist, kn, knote, kn_selnext); 636 splx(s); 637 } 638 639 static const struct filterops uirdaread_filtops = 640 { 1, NULL, filt_uirdardetach, filt_uirdaread }; 641 static const struct filterops uirdawrite_filtops = 642 { 1, NULL, filt_uirdawdetach, filt_seltrue }; 643 644 int 645 uirda_kqfilter(void *h, struct knote *kn) 646 { 647 struct uirda_softc *sc = kn->kn_hook; 648 struct klist *klist; 649 int s; 650 651 switch (kn->kn_filter) { 652 case EVFILT_READ: 653 klist = &sc->sc_rd_sel.sel_klist; 654 kn->kn_fop = &uirdaread_filtops; 655 break; 656 case EVFILT_WRITE: 657 klist = &sc->sc_wr_sel.sel_klist; 658 kn->kn_fop = &uirdawrite_filtops; 659 break; 660 default: 661 return EINVAL; 662 } 663 664 kn->kn_hook = sc; 665 666 s = splusb(); 667 SLIST_INSERT_HEAD(klist, kn, kn_selnext); 668 splx(s); 669 670 return 0; 671 } 672 673 int 674 uirda_set_params(void *h, struct irda_params *p) 675 { 676 struct uirda_softc *sc = h; 677 usbd_status err; 678 int i; 679 uint8_t hdr; 680 uint32_t n; 681 u_int mask; 682 683 DPRINTF(("%s: sc=%p, speed=%d ebofs=%d maxsize=%d\n", __func__, 684 sc, p->speed, p->ebofs, p->maxsize)); 685 686 if (sc->sc_dying) 687 return EIO; 688 689 hdr = 0; 690 if (p->ebofs != sc->sc_params.ebofs) { 691 /* round up ebofs */ 692 mask = 1 /* sc->sc_irdadesc.bmAdditionalBOFs*/; 693 DPRINTF(("u.s.p.: mask=0x%x, sc->ebofs=%d, p->ebofs=%d\n", 694 mask, sc->sc_params.ebofs, p->ebofs)); 695 for (i = 0; i < UIRDA_NEBOFS; i++) { 696 DPRINTF(("u.s.p.: u_e[%d].mask=0x%x, count=%d\n", 697 i, uirda_ebofs[i].mask, uirda_ebofs[i].count)); 698 if ((mask & uirda_ebofs[i].mask) && 699 uirda_ebofs[i].count >= p->ebofs) { 700 hdr = uirda_ebofs[i].header; 701 goto found1; 702 } 703 } 704 for (i = 0; i < UIRDA_NEBOFS; i++) { 705 DPRINTF(("u.s.p.: u_e[%d].mask=0x%x, count=%d\n", 706 i, uirda_ebofs[i].mask, uirda_ebofs[i].count)); 707 if ((mask & uirda_ebofs[i].mask)) { 708 hdr = uirda_ebofs[i].header; 709 goto found1; 710 } 711 } 712 /* no good value found */ 713 return EINVAL; 714 found1: 715 DPRINTF(("uirda_set_params: ebofs hdr=0x%02x\n", hdr)); 716 ; 717 718 } 719 if (hdr != 0 || p->speed != sc->sc_params.speed) { 720 /* find speed */ 721 mask = UGETW(sc->sc_irdadesc.wBaudRate); 722 for (i = 0; i < UIRDA_NSPEEDS; i++) { 723 if ((mask & uirda_speeds[i].mask) && 724 uirda_speeds[i].speed == p->speed) { 725 hdr |= uirda_speeds[i].header; 726 goto found2; 727 } 728 } 729 /* no good value found */ 730 return EINVAL; 731 found2: 732 DPRINTF(("uirda_set_params: speed hdr=0x%02x\n", hdr)); 733 ; 734 } 735 if (p->maxsize != sc->sc_params.maxsize) { 736 if (p->maxsize > IRDA_MAX_FRAME_SIZE) 737 return EINVAL; 738 sc->sc_params.maxsize = p->maxsize; 739 #if 0 740 DPRINTF(("%s: new buffers, old size=%d\n", __func__, 741 sc->sc_params.maxsize)); 742 if (p->maxsize > 10000 || p < 0) /* XXX */ 743 return EINVAL; 744 745 /* Change the write buffer */ 746 mutex_enter(&sc->sc_wr_buf_lk); 747 if (sc->sc_wr_buf != NULL) 748 usbd_free_buffer(sc->sc_wr_xfer); 749 sc->sc_wr_buf = usbd_get_buffer(sc->sc_wr_xfer, p->maxsize+1); 750 mutex_exit(&sc->sc_wr_buf_lk); 751 if (sc->sc_wr_buf == NULL) 752 return ENOMEM; 753 754 /* Change the read buffer */ 755 mutex_enter(&sc->sc_rd_buf_lk); 756 usbd_abort_pipe(sc->sc_rd_pipe); 757 if (sc->sc_rd_buf != NULL) 758 usbd_free_buffer(sc->sc_rd_xfer); 759 sc->sc_rd_buf = usbd_get_buffer(sc->sc_rd_xfer, p->maxsize+1); 760 sc->sc_rd_count = 0; 761 if (sc->sc_rd_buf == NULL) { 762 mutex_exit(&sc->sc_rd_buf_lk); 763 return ENOMEM; 764 } 765 sc->sc_params.maxsize = p->maxsize; 766 err = uirda_start_read(sc); /* XXX check */ 767 mutex_exit(&sc->sc_rd_buf_lk); 768 #endif 769 } 770 if (hdr != 0 && hdr != sc->sc_wr_hdr) { 771 /* 772 * A change has occurred, transmit a 0 length frame with 773 * the new settings. The 0 length frame is not sent to the 774 * device. 775 */ 776 DPRINTF(("%s: sc=%p setting header 0x%02x\n", 777 __func__, sc, hdr)); 778 sc->sc_wr_hdr = hdr; 779 mutex_enter(&sc->sc_wr_buf_lk); 780 sc->sc_wr_buf[0] = hdr; 781 n = UIRDA_OUTPUT_HEADER_SIZE; 782 err = usbd_bulk_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe, 783 USBD_FORCE_SHORT_XFER, UIRDA_WR_TIMEOUT, 784 sc->sc_wr_buf, &n); 785 if (err) { 786 aprint_error_dev(sc->sc_dev, "set failed, err=%d\n", 787 err); 788 usbd_clear_endpoint_stall(sc->sc_wr_pipe); 789 } 790 mutex_exit(&sc->sc_wr_buf_lk); 791 } 792 793 sc->sc_params = *p; 794 795 return 0; 796 } 797 798 int 799 uirda_get_speeds(void *h, int *speeds) 800 { 801 struct uirda_softc *sc = h; 802 u_int isp; 803 u_int usp; 804 805 DPRINTF(("%s: sc=%p\n", __func__, sc)); 806 807 if (sc->sc_dying) 808 return EIO; 809 810 usp = UGETW(sc->sc_irdadesc.wBaudRate); 811 isp = 0; 812 if (usp & UI_BR_4000000) isp |= IRDA_SPEED_4000000; 813 if (usp & UI_BR_1152000) isp |= IRDA_SPEED_1152000; 814 if (usp & UI_BR_576000) isp |= IRDA_SPEED_576000; 815 if (usp & UI_BR_115200) isp |= IRDA_SPEED_115200; 816 if (usp & UI_BR_57600) isp |= IRDA_SPEED_57600; 817 if (usp & UI_BR_38400) isp |= IRDA_SPEED_38400; 818 if (usp & UI_BR_19200) isp |= IRDA_SPEED_19200; 819 if (usp & UI_BR_9600) isp |= IRDA_SPEED_9600; 820 if (usp & UI_BR_2400) isp |= IRDA_SPEED_2400; 821 *speeds = isp; 822 DPRINTF(("%s: speeds = 0x%x\n", __func__, isp)); 823 return 0; 824 } 825 826 int 827 uirda_get_turnarounds(void *h, int *turnarounds) 828 { 829 struct uirda_softc *sc = h; 830 u_int ita; 831 u_int uta; 832 833 DPRINTF(("%s: sc=%p\n", __func__, sc)); 834 835 if (sc->sc_dying) 836 return EIO; 837 838 uta = sc->sc_irdadesc.bmMinTurnaroundTime; 839 ita = 0; 840 if (uta & UI_TA_0) ita |= IRDA_TURNT_0; 841 if (uta & UI_TA_10) ita |= IRDA_TURNT_10; 842 if (uta & UI_TA_50) ita |= IRDA_TURNT_50; 843 if (uta & UI_TA_100) ita |= IRDA_TURNT_100; 844 if (uta & UI_TA_500) ita |= IRDA_TURNT_500; 845 if (uta & UI_TA_1000) ita |= IRDA_TURNT_1000; 846 if (uta & UI_TA_5000) ita |= IRDA_TURNT_5000; 847 if (uta & UI_TA_10000) ita |= IRDA_TURNT_10000; 848 *turnarounds = ita; 849 return 0; 850 } 851 852 void 853 uirda_rd_cb(struct usbd_xfer *xfer, void *priv, 854 usbd_status status) 855 { 856 struct uirda_softc *sc = priv; 857 uint32_t size; 858 859 DPRINTFN(1,("%s: sc=%p\n", __func__, sc)); 860 861 if (status == USBD_CANCELLED) /* this is normal */ 862 return; 863 if (status) { 864 size = sc->sc_hdszi; 865 sc->sc_rd_err = 1; 866 } else { 867 usbd_get_xfer_status(xfer, NULL, NULL, &size, NULL); 868 } 869 DPRINTFN(1,("%s: sc=%p size=%u, err=%d\n", __func__, sc, size, 870 sc->sc_rd_err)); 871 sc->sc_rd_count = size; 872 wakeup(&sc->sc_rd_count); /* XXX should use flag */ 873 selnotify(&sc->sc_rd_sel, 0, 0); 874 } 875 876 usbd_status 877 uirda_start_read(struct uirda_softc *sc) 878 { 879 usbd_status err; 880 881 DPRINTFN(1,("%s: sc=%p, size=%d\n", __func__, sc, 882 sc->sc_params.maxsize + UIRDA_INPUT_HEADER_SIZE)); 883 884 if (sc->sc_dying) 885 return USBD_IOERROR; 886 887 if (sc->sc_rd_err) { 888 sc->sc_rd_err = 0; 889 DPRINTF(("uirda_start_read: clear stall\n")); 890 usbd_clear_endpoint_stall(sc->sc_rd_pipe); 891 } 892 893 usbd_setup_xfer(sc->sc_rd_xfer, sc, sc->sc_rd_buf, 894 sc->sc_params.maxsize + sc->sc_hdszi, USBD_SHORT_XFER_OK, 895 USBD_NO_TIMEOUT, uirda_rd_cb); 896 err = usbd_transfer(sc->sc_rd_xfer); 897 if (err != USBD_IN_PROGRESS) { 898 DPRINTF(("uirda_start_read: err=%d\n", err)); 899 return err; 900 } 901 return USBD_NORMAL_COMPLETION; 902 } 903 904 usbd_status 905 usbd_get_class_desc(struct usbd_device *dev, int type, int index, int len, void *desc) 906 { 907 usb_device_request_t req; 908 909 DPRINTFN(3,("usbd_get_desc: type=%d, index=%d, len=%d\n", 910 type, index, len)); 911 912 req.bmRequestType = 0xa1; /* XXX ? */ 913 req.bRequest = UR_GET_DESCRIPTOR; 914 USETW2(req.wValue, type, index); 915 USETW(req.wIndex, 0); 916 USETW(req.wLength, len); 917 return usbd_do_request(dev, &req, desc); 918 } 919