1 /* $NetBSD: uirda.c,v 1.53 2022/08/07 11:25:32 riastradh 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.53 2022/08/07 11:25:32 riastradh 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 mutex_init(&sc->sc_wr_buf_lk, MUTEX_DEFAULT, IPL_NONE); 205 mutex_init(&sc->sc_rd_buf_lk, MUTEX_DEFAULT, IPL_NONE); 206 selinit(&sc->sc_rd_sel); 207 208 if (sc->sc_hdszi == 0) 209 sc->sc_hdszi = UIRDA_INPUT_HEADER_SIZE; 210 211 epcount = 0; 212 (void)usbd_endpoint_count(iface, &epcount); 213 214 sc->sc_rd_addr = -1; 215 sc->sc_wr_addr = -1; 216 for (i = 0; i < epcount; i++) { 217 ed = usbd_interface2endpoint_descriptor(iface, i); 218 if (ed == NULL) { 219 aprint_error_dev(self, "couldn't get ep %d\n", i); 220 return; 221 } 222 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 223 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 224 sc->sc_rd_addr = ed->bEndpointAddress; 225 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 226 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 227 sc->sc_wr_addr = ed->bEndpointAddress; 228 } 229 } 230 if (sc->sc_rd_addr == -1 || sc->sc_wr_addr == -1) { 231 aprint_error_dev(self, "missing endpoint\n"); 232 return; 233 } 234 235 if (sc->sc_loadfw(sc) != 0) { 236 return; 237 } 238 239 /* Get the IrDA descriptor */ 240 err = usbd_get_class_desc(sc->sc_udev, UDESC_IRDA, 0, 241 USB_IRDA_DESCRIPTOR_SIZE, &sc->sc_irdadesc); 242 aprint_error_dev(self, "error %d reading class desc\n", err); 243 if (err) { 244 err = usbd_get_desc(sc->sc_udev, UDESC_IRDA, 0, 245 USB_IRDA_DESCRIPTOR_SIZE, &sc->sc_irdadesc); 246 } 247 aprint_error_dev(self, "error %d reading desc\n", err); 248 if (err) { 249 /* maybe it's embedded in the config desc? */ 250 usbd_desc_iter_t iter; 251 const usb_descriptor_t *d; 252 usb_desc_iter_init(sc->sc_udev, &iter); 253 for (;;) { 254 d = usb_desc_iter_next(&iter); 255 if (!d || d->bDescriptorType == UDESC_IRDA) 256 break; 257 } 258 if (d == NULL) { 259 aprint_error_dev(self, 260 "Cannot get IrDA descriptor\n"); 261 return; 262 } 263 memcpy(&sc->sc_irdadesc, d, USB_IRDA_DESCRIPTOR_SIZE); 264 } 265 DPRINTF(("uirda_attach: bDescriptorSize %d bDescriptorType %#x " 266 "bmDataSize=0x%02x bmWindowSize=0x%02x " 267 "bmMinTurnaroundTime=0x%02x wBaudRate=0x%04x " 268 "bmAdditionalBOFs=0x%02x bIrdaSniff=%d bMaxUnicastList=%d\n", 269 sc->sc_irdadesc.bLength, 270 sc->sc_irdadesc.bDescriptorType, 271 sc->sc_irdadesc.bmDataSize, 272 sc->sc_irdadesc.bmWindowSize, 273 sc->sc_irdadesc.bmMinTurnaroundTime, 274 UGETW(sc->sc_irdadesc.wBaudRate), 275 sc->sc_irdadesc.bmAdditionalBOFs, 276 sc->sc_irdadesc.bIrdaSniff, 277 sc->sc_irdadesc.bMaxUnicastList)); 278 279 specrev = UGETW(sc->sc_irdadesc.bcdSpecRevision); 280 aprint_normal_dev(self, "USB-IrDA protocol version %x.%02x\n", 281 specrev >> 8, specrev & 0xff); 282 283 DPRINTFN(10, ("uirda_attach: %p\n", sc->sc_udev)); 284 285 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); 286 287 ia.ia_type = IR_TYPE_IRFRAME; 288 ia.ia_methods = sc->sc_irm ? sc->sc_irm : &uirda_methods; 289 ia.ia_handle = sc; 290 291 sc->sc_child = config_found(self, &ia, ir_print, CFARGS_NONE); 292 293 return; 294 } 295 296 int 297 uirda_detach(device_t self, int flags) 298 { 299 struct uirda_softc *sc = device_private(self); 300 int s; 301 int rv = 0; 302 303 DPRINTF(("uirda_detach: sc=%p flags=%d\n", sc, flags)); 304 305 sc->sc_dying = 1; 306 /* Abort all pipes. Causes processes waiting for transfer to wake. */ 307 if (sc->sc_rd_pipe != NULL) { 308 usbd_abort_pipe(sc->sc_rd_pipe); 309 } 310 if (sc->sc_wr_pipe != NULL) { 311 usbd_abort_pipe(sc->sc_wr_pipe); 312 } 313 if (sc->sc_rd_xfer != NULL) { 314 usbd_destroy_xfer(sc->sc_rd_xfer); 315 sc->sc_rd_xfer = NULL; 316 sc->sc_rd_buf = NULL; 317 } 318 if (sc->sc_wr_xfer != NULL) { 319 usbd_destroy_xfer(sc->sc_wr_xfer); 320 sc->sc_wr_xfer = NULL; 321 sc->sc_wr_buf = NULL; 322 } 323 if (sc->sc_rd_pipe != NULL) { 324 usbd_close_pipe(sc->sc_rd_pipe); 325 sc->sc_rd_pipe = NULL; 326 } 327 if (sc->sc_wr_pipe != NULL) { 328 usbd_close_pipe(sc->sc_wr_pipe); 329 sc->sc_wr_pipe = NULL; 330 } 331 wakeup(&sc->sc_rd_count); 332 333 s = splusb(); 334 if (--sc->sc_refcnt >= 0) { 335 /* Wait for processes to go away. */ 336 usb_detach_waitold(sc->sc_dev); 337 } 338 splx(s); 339 340 if (sc->sc_child != NULL) 341 rv = config_detach(sc->sc_child, flags); 342 343 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); 344 345 mutex_destroy(&sc->sc_wr_buf_lk); 346 mutex_destroy(&sc->sc_rd_buf_lk); 347 seldestroy(&sc->sc_rd_sel); 348 349 return rv; 350 } 351 352 void 353 uirda_childdet(device_t self, device_t child) 354 { 355 struct uirda_softc *sc = device_private(self); 356 357 KASSERT(sc->sc_child == child); 358 sc->sc_child = NULL; 359 } 360 361 int 362 uirda_activate(device_t self, enum devact act) 363 { 364 struct uirda_softc *sc = device_private(self); 365 366 switch (act) { 367 case DVACT_DEACTIVATE: 368 sc->sc_dying = 1; 369 return 0; 370 default: 371 return EOPNOTSUPP; 372 } 373 } 374 375 int 376 uirda_open(void *h, int flag, int mode, 377 struct lwp *l) 378 { 379 struct uirda_softc *sc = h; 380 int error; 381 usbd_status err; 382 383 DPRINTF(("%s: sc=%p\n", __func__, sc)); 384 385 err = usbd_open_pipe(sc->sc_iface, sc->sc_rd_addr, 0, &sc->sc_rd_pipe); 386 if (err) { 387 error = EIO; 388 goto bad1; 389 } 390 err = usbd_open_pipe(sc->sc_iface, sc->sc_wr_addr, 0, &sc->sc_wr_pipe); 391 if (err) { 392 error = EIO; 393 goto bad2; 394 } 395 error = usbd_create_xfer(sc->sc_rd_pipe, 396 IRDA_MAX_FRAME_SIZE + sc->sc_hdszi, 0, 0, 397 &sc->sc_rd_xfer); 398 if (error) 399 goto bad3; 400 sc->sc_rd_buf = usbd_get_buffer(sc->sc_rd_xfer); 401 402 /* worst case ST-UIRDA length */ 403 error = usbd_create_xfer(sc->sc_wr_pipe, 404 IRDA_MAX_FRAME_SIZE + UIRDA_OUTPUT_HEADER_SIZE + 2 + 1, 405 USBD_FORCE_SHORT_XFER, 0, &sc->sc_wr_xfer); 406 if (error) 407 goto bad4; 408 sc->sc_wr_buf = usbd_get_buffer(sc->sc_wr_xfer); 409 410 sc->sc_rd_count = 0; 411 sc->sc_rd_err = 0; 412 sc->sc_params.speed = 0; 413 sc->sc_params.ebofs = 0; 414 sc->sc_params.maxsize = IRDA_MAX_FRAME_SIZE; 415 sc->sc_wr_hdr = -1; 416 417 err = uirda_start_read(sc); 418 /* XXX check err */ 419 420 return 0; 421 422 bad4: 423 usbd_destroy_xfer(sc->sc_rd_xfer); 424 sc->sc_rd_xfer = NULL; 425 bad3: 426 usbd_close_pipe(sc->sc_wr_pipe); 427 sc->sc_wr_pipe = NULL; 428 bad2: 429 usbd_close_pipe(sc->sc_rd_pipe); 430 sc->sc_rd_pipe = NULL; 431 bad1: 432 return error; 433 } 434 435 int 436 uirda_close(void *h, int flag, int mode, 437 struct lwp *l) 438 { 439 struct uirda_softc *sc = h; 440 441 DPRINTF(("%s: sc=%p\n", __func__, sc)); 442 443 if (sc->sc_rd_pipe != NULL) { 444 usbd_abort_pipe(sc->sc_rd_pipe); 445 } 446 if (sc->sc_wr_pipe != NULL) { 447 usbd_abort_pipe(sc->sc_wr_pipe); 448 } 449 if (sc->sc_rd_xfer != NULL) { 450 usbd_destroy_xfer(sc->sc_rd_xfer); 451 sc->sc_rd_xfer = NULL; 452 sc->sc_rd_buf = NULL; 453 } 454 if (sc->sc_wr_xfer != NULL) { 455 usbd_destroy_xfer(sc->sc_wr_xfer); 456 sc->sc_wr_xfer = NULL; 457 sc->sc_wr_buf = NULL; 458 } 459 if (sc->sc_rd_pipe != NULL) { 460 usbd_close_pipe(sc->sc_rd_pipe); 461 sc->sc_rd_pipe = NULL; 462 } 463 if (sc->sc_wr_pipe != NULL) { 464 usbd_close_pipe(sc->sc_wr_pipe); 465 sc->sc_wr_pipe = NULL; 466 } 467 468 return 0; 469 } 470 471 int 472 uirda_read(void *h, struct uio *uio, int flag) 473 { 474 struct uirda_softc *sc = h; 475 int s; 476 int error; 477 u_int n; 478 479 DPRINTFN(1,("%s: sc=%p\n", __func__, sc)); 480 481 if (sc->sc_dying) 482 return EIO; 483 484 #ifdef DIAGNOSTIC 485 if (sc->sc_rd_buf == NULL) 486 return EINVAL; 487 #endif 488 489 sc->sc_refcnt++; 490 491 do { 492 s = splusb(); 493 while (sc->sc_rd_count == 0) { 494 DPRINTFN(5,("uirda_read: calling tsleep()\n")); 495 error = tsleep(&sc->sc_rd_count, PZERO | PCATCH, 496 "uirdrd", 0); 497 if (sc->sc_dying) 498 error = EIO; 499 if (error) { 500 splx(s); 501 DPRINTF(("uirda_read: tsleep() = %d\n", error)); 502 goto ret; 503 } 504 } 505 splx(s); 506 507 mutex_enter(&sc->sc_rd_buf_lk); 508 n = sc->sc_rd_count - sc->sc_hdszi; 509 DPRINTFN(1,("%s: sc=%p n=%u, hdr=0x%02x\n", __func__, 510 sc, n, sc->sc_rd_buf[0])); 511 if (n > uio->uio_resid) 512 error = EINVAL; 513 else 514 error = uiomove(sc->sc_rd_buf + sc->sc_hdszi, n, uio); 515 sc->sc_rd_count = 0; 516 mutex_exit(&sc->sc_rd_buf_lk); 517 518 uirda_start_read(sc); 519 /* XXX check uirda_start_read() return value */ 520 521 } while (n == 0); 522 523 DPRINTFN(1,("uirda_read: return %d\n", error)); 524 525 ret: 526 if (--sc->sc_refcnt < 0) 527 usb_detach_wakeupold(sc->sc_dev); 528 return error; 529 } 530 531 int 532 uirda_write(void *h, struct uio *uio, int flag) 533 { 534 struct uirda_softc *sc = h; 535 usbd_status err; 536 uint32_t n; 537 int error = 0; 538 539 DPRINTFN(1,("%s: sc=%p\n", __func__, sc)); 540 541 if (sc->sc_dying) 542 return EIO; 543 544 #ifdef DIAGNOSTIC 545 if (sc->sc_wr_buf == NULL) 546 return EINVAL; 547 #endif 548 549 n = uio->uio_resid; 550 if (n > sc->sc_params.maxsize) 551 return EINVAL; 552 553 sc->sc_refcnt++; 554 mutex_enter(&sc->sc_wr_buf_lk); 555 556 sc->sc_wr_buf[0] = UIRDA_EB_NO_CHANGE | UIRDA_NO_SPEED; 557 error = uiomove(sc->sc_wr_buf + UIRDA_OUTPUT_HEADER_SIZE, n, uio); 558 if (error) 559 goto done; 560 561 DPRINTFN(1, ("uirdawrite: transfer %d bytes\n", n)); 562 563 n += UIRDA_OUTPUT_HEADER_SIZE; 564 err = usbd_bulk_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe, 565 USBD_FORCE_SHORT_XFER, UIRDA_WR_TIMEOUT, sc->sc_wr_buf, &n); 566 DPRINTFN(2, ("uirdawrite: err=%d\n", err)); 567 if (err) { 568 if (err == USBD_INTERRUPTED) 569 error = EINTR; 570 else if (err == USBD_TIMEOUT) 571 error = ETIMEDOUT; 572 else 573 error = EIO; 574 } 575 done: 576 mutex_exit(&sc->sc_wr_buf_lk); 577 if (--sc->sc_refcnt < 0) 578 usb_detach_wakeupold(sc->sc_dev); 579 580 DPRINTFN(1,("%s: sc=%p done\n", __func__, sc)); 581 return error; 582 } 583 584 int 585 uirda_poll(void *h, int events, struct lwp *l) 586 { 587 struct uirda_softc *sc = h; 588 int revents = 0; 589 int s; 590 591 DPRINTFN(1,("%s: sc=%p\n", __func__, sc)); 592 593 s = splusb(); 594 if (events & (POLLOUT | POLLWRNORM)) 595 revents |= events & (POLLOUT | POLLWRNORM); 596 if (events & (POLLIN | POLLRDNORM)) { 597 if (sc->sc_rd_count != 0) { 598 DPRINTFN(2,("%s: have data\n", __func__)); 599 revents |= events & (POLLIN | POLLRDNORM); 600 } else { 601 DPRINTFN(2,("%s: recording select\n", __func__)); 602 selrecord(l, &sc->sc_rd_sel); 603 } 604 } 605 splx(s); 606 607 return revents; 608 } 609 610 static void 611 filt_uirdardetach(struct knote *kn) 612 { 613 struct uirda_softc *sc = kn->kn_hook; 614 int s; 615 616 s = splusb(); 617 selremove_knote(&sc->sc_rd_sel, kn); 618 splx(s); 619 } 620 621 static int 622 filt_uirdaread(struct knote *kn, long hint) 623 { 624 struct uirda_softc *sc = kn->kn_hook; 625 626 kn->kn_data = sc->sc_rd_count; 627 return kn->kn_data > 0; 628 } 629 630 static const struct filterops uirdaread_filtops = { 631 .f_flags = FILTEROP_ISFD, 632 .f_attach = NULL, 633 .f_detach = filt_uirdardetach, 634 .f_event = filt_uirdaread, 635 }; 636 637 int 638 uirda_kqfilter(void *h, struct knote *kn) 639 { 640 struct uirda_softc *sc = kn->kn_hook; 641 int s; 642 643 switch (kn->kn_filter) { 644 case EVFILT_READ: 645 kn->kn_fop = &uirdaread_filtops; 646 kn->kn_hook = sc; 647 s = splusb(); 648 selrecord_knote(&sc->sc_rd_sel, kn); 649 splx(s); 650 break; 651 652 case EVFILT_WRITE: 653 kn->kn_fop = &seltrue_filtops; 654 break; 655 656 default: 657 return EINVAL; 658 } 659 660 return 0; 661 } 662 663 int 664 uirda_set_params(void *h, struct irda_params *p) 665 { 666 struct uirda_softc *sc = h; 667 usbd_status err; 668 int i; 669 uint8_t hdr; 670 uint32_t n; 671 u_int mask; 672 673 DPRINTF(("%s: sc=%p, speed=%d ebofs=%d maxsize=%d\n", __func__, 674 sc, p->speed, p->ebofs, p->maxsize)); 675 676 if (sc->sc_dying) 677 return EIO; 678 679 hdr = 0; 680 if (p->ebofs != sc->sc_params.ebofs) { 681 /* round up ebofs */ 682 mask = 1 /* sc->sc_irdadesc.bmAdditionalBOFs*/; 683 DPRINTF(("u.s.p.: mask=%#x, sc->ebofs=%d, p->ebofs=%d\n", 684 mask, sc->sc_params.ebofs, p->ebofs)); 685 for (i = 0; i < UIRDA_NEBOFS; i++) { 686 DPRINTF(("u.s.p.: u_e[%d].mask=%#x, count=%d\n", 687 i, uirda_ebofs[i].mask, uirda_ebofs[i].count)); 688 if ((mask & uirda_ebofs[i].mask) && 689 uirda_ebofs[i].count >= p->ebofs) { 690 hdr = uirda_ebofs[i].header; 691 goto found1; 692 } 693 } 694 for (i = 0; i < UIRDA_NEBOFS; i++) { 695 DPRINTF(("u.s.p.: u_e[%d].mask=%#x, count=%d\n", 696 i, uirda_ebofs[i].mask, uirda_ebofs[i].count)); 697 if ((mask & uirda_ebofs[i].mask)) { 698 hdr = uirda_ebofs[i].header; 699 goto found1; 700 } 701 } 702 /* no good value found */ 703 return EINVAL; 704 found1: 705 DPRINTF(("uirda_set_params: ebofs hdr=0x%02x\n", hdr)); 706 ; 707 708 } 709 if (hdr != 0 || p->speed != sc->sc_params.speed) { 710 /* find speed */ 711 mask = UGETW(sc->sc_irdadesc.wBaudRate); 712 for (i = 0; i < UIRDA_NSPEEDS; i++) { 713 if ((mask & uirda_speeds[i].mask) && 714 uirda_speeds[i].speed == p->speed) { 715 hdr |= uirda_speeds[i].header; 716 goto found2; 717 } 718 } 719 /* no good value found */ 720 return EINVAL; 721 found2: 722 DPRINTF(("uirda_set_params: speed hdr=0x%02x\n", hdr)); 723 ; 724 } 725 if (p->maxsize != sc->sc_params.maxsize) { 726 if (p->maxsize > IRDA_MAX_FRAME_SIZE) 727 return EINVAL; 728 sc->sc_params.maxsize = p->maxsize; 729 #if 0 730 DPRINTF(("%s: new buffers, old size=%d\n", __func__, 731 sc->sc_params.maxsize)); 732 if (p->maxsize > 10000 || p < 0) /* XXX */ 733 return EINVAL; 734 735 /* Change the write buffer */ 736 mutex_enter(&sc->sc_wr_buf_lk); 737 if (sc->sc_wr_buf != NULL) 738 usbd_free_buffer(sc->sc_wr_xfer); 739 sc->sc_wr_buf = usbd_get_buffer(sc->sc_wr_xfer, p->maxsize+1); 740 mutex_exit(&sc->sc_wr_buf_lk); 741 if (sc->sc_wr_buf == NULL) 742 return ENOMEM; 743 744 /* Change the read buffer */ 745 mutex_enter(&sc->sc_rd_buf_lk); 746 usbd_abort_pipe(sc->sc_rd_pipe); 747 if (sc->sc_rd_buf != NULL) 748 usbd_free_buffer(sc->sc_rd_xfer); 749 sc->sc_rd_buf = usbd_get_buffer(sc->sc_rd_xfer, p->maxsize+1); 750 sc->sc_rd_count = 0; 751 if (sc->sc_rd_buf == NULL) { 752 mutex_exit(&sc->sc_rd_buf_lk); 753 return ENOMEM; 754 } 755 sc->sc_params.maxsize = p->maxsize; 756 err = uirda_start_read(sc); /* XXX check */ 757 mutex_exit(&sc->sc_rd_buf_lk); 758 #endif 759 } 760 if (hdr != 0 && hdr != sc->sc_wr_hdr) { 761 /* 762 * A change has occurred, transmit a 0 length frame with 763 * the new settings. The 0 length frame is not sent to the 764 * device. 765 */ 766 DPRINTF(("%s: sc=%p setting header 0x%02x\n", 767 __func__, sc, hdr)); 768 sc->sc_wr_hdr = hdr; 769 mutex_enter(&sc->sc_wr_buf_lk); 770 sc->sc_wr_buf[0] = hdr; 771 n = UIRDA_OUTPUT_HEADER_SIZE; 772 err = usbd_bulk_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe, 773 USBD_FORCE_SHORT_XFER, UIRDA_WR_TIMEOUT, 774 sc->sc_wr_buf, &n); 775 if (err) { 776 aprint_error_dev(sc->sc_dev, "set failed, err=%d\n", 777 err); 778 usbd_clear_endpoint_stall(sc->sc_wr_pipe); 779 } 780 mutex_exit(&sc->sc_wr_buf_lk); 781 } 782 783 sc->sc_params = *p; 784 785 return 0; 786 } 787 788 int 789 uirda_get_speeds(void *h, int *speeds) 790 { 791 struct uirda_softc *sc = h; 792 u_int isp; 793 u_int usp; 794 795 DPRINTF(("%s: sc=%p\n", __func__, sc)); 796 797 if (sc->sc_dying) 798 return EIO; 799 800 usp = UGETW(sc->sc_irdadesc.wBaudRate); 801 isp = 0; 802 if (usp & UI_BR_4000000) isp |= IRDA_SPEED_4000000; 803 if (usp & UI_BR_1152000) isp |= IRDA_SPEED_1152000; 804 if (usp & UI_BR_576000) isp |= IRDA_SPEED_576000; 805 if (usp & UI_BR_115200) isp |= IRDA_SPEED_115200; 806 if (usp & UI_BR_57600) isp |= IRDA_SPEED_57600; 807 if (usp & UI_BR_38400) isp |= IRDA_SPEED_38400; 808 if (usp & UI_BR_19200) isp |= IRDA_SPEED_19200; 809 if (usp & UI_BR_9600) isp |= IRDA_SPEED_9600; 810 if (usp & UI_BR_2400) isp |= IRDA_SPEED_2400; 811 *speeds = isp; 812 DPRINTF(("%s: speeds = %#x\n", __func__, isp)); 813 return 0; 814 } 815 816 int 817 uirda_get_turnarounds(void *h, int *turnarounds) 818 { 819 struct uirda_softc *sc = h; 820 u_int ita; 821 u_int uta; 822 823 DPRINTF(("%s: sc=%p\n", __func__, sc)); 824 825 if (sc->sc_dying) 826 return EIO; 827 828 uta = sc->sc_irdadesc.bmMinTurnaroundTime; 829 ita = 0; 830 if (uta & UI_TA_0) ita |= IRDA_TURNT_0; 831 if (uta & UI_TA_10) ita |= IRDA_TURNT_10; 832 if (uta & UI_TA_50) ita |= IRDA_TURNT_50; 833 if (uta & UI_TA_100) ita |= IRDA_TURNT_100; 834 if (uta & UI_TA_500) ita |= IRDA_TURNT_500; 835 if (uta & UI_TA_1000) ita |= IRDA_TURNT_1000; 836 if (uta & UI_TA_5000) ita |= IRDA_TURNT_5000; 837 if (uta & UI_TA_10000) ita |= IRDA_TURNT_10000; 838 *turnarounds = ita; 839 return 0; 840 } 841 842 static void 843 uirda_rd_cb(struct usbd_xfer *xfer, void *priv, 844 usbd_status status) 845 { 846 struct uirda_softc *sc = priv; 847 uint32_t size; 848 849 DPRINTFN(1,("%s: sc=%p\n", __func__, sc)); 850 851 if (status == USBD_CANCELLED) /* this is normal */ 852 return; 853 if (status) { 854 size = sc->sc_hdszi; 855 sc->sc_rd_err = 1; 856 } else { 857 usbd_get_xfer_status(xfer, NULL, NULL, &size, NULL); 858 } 859 DPRINTFN(1,("%s: sc=%p size=%u, err=%d\n", __func__, sc, size, 860 sc->sc_rd_err)); 861 sc->sc_rd_count = size; 862 wakeup(&sc->sc_rd_count); /* XXX should use flag */ 863 selnotify(&sc->sc_rd_sel, 0, 0); 864 } 865 866 static usbd_status 867 uirda_start_read(struct uirda_softc *sc) 868 { 869 usbd_status err; 870 871 DPRINTFN(1,("%s: sc=%p, size=%d\n", __func__, sc, 872 sc->sc_params.maxsize + UIRDA_INPUT_HEADER_SIZE)); 873 874 if (sc->sc_dying) 875 return USBD_IOERROR; 876 877 if (sc->sc_rd_err) { 878 sc->sc_rd_err = 0; 879 DPRINTF(("uirda_start_read: clear stall\n")); 880 usbd_clear_endpoint_stall(sc->sc_rd_pipe); 881 } 882 883 usbd_setup_xfer(sc->sc_rd_xfer, sc, sc->sc_rd_buf, 884 sc->sc_params.maxsize + sc->sc_hdszi, USBD_SHORT_XFER_OK, 885 USBD_NO_TIMEOUT, uirda_rd_cb); 886 err = usbd_transfer(sc->sc_rd_xfer); 887 if (err != USBD_IN_PROGRESS) { 888 DPRINTF(("uirda_start_read: err=%d\n", err)); 889 return err; 890 } 891 return USBD_NORMAL_COMPLETION; 892 } 893 894 usbd_status 895 usbd_get_class_desc(struct usbd_device *dev, int type, int index, int len, void *desc) 896 { 897 usb_device_request_t req; 898 899 DPRINTFN(3,("usbd_get_desc: type=%d, index=%d, len=%d\n", 900 type, index, len)); 901 902 req.bmRequestType = 0xa1; /* XXX ? */ 903 req.bRequest = UR_GET_DESCRIPTOR; 904 USETW2(req.wValue, type, index); 905 USETW(req.wIndex, 0); 906 USETW(req.wLength, len); 907 return usbd_do_request(dev, &req, desc); 908 } 909