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