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