1 /* $NetBSD: uirda.c,v 1.18 2004/10/23 13:28:26 augustss 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.18 2004/10/23 13:28:26 augustss 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, usb_proc_ptr p); 231 int uirda_close(void *h, int flag, int mode, usb_proc_ptr p); 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, usb_proc_ptr p); 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 devinfo[1024]; 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 usbd_devinfo(dev, 0, devinfo, sizeof(devinfo)); 305 USB_ATTACH_SETUP; 306 printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo); 307 308 sc->sc_udev = dev; 309 sc->sc_iface = iface; 310 311 epcount = 0; 312 (void)usbd_endpoint_count(iface, &epcount); 313 314 sc->sc_rd_addr = -1; 315 sc->sc_wr_addr = -1; 316 for (i = 0; i < epcount; i++) { 317 ed = usbd_interface2endpoint_descriptor(iface, i); 318 if (ed == NULL) { 319 printf("%s: couldn't get ep %d\n", 320 USBDEVNAME(sc->sc_dev), i); 321 USB_ATTACH_ERROR_RETURN; 322 } 323 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 324 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 325 sc->sc_rd_addr = ed->bEndpointAddress; 326 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 327 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 328 sc->sc_wr_addr = ed->bEndpointAddress; 329 } 330 } 331 if (sc->sc_rd_addr == -1 || sc->sc_wr_addr == -1) { 332 printf("%s: missing endpoint\n", USBDEVNAME(sc->sc_dev)); 333 USB_ATTACH_ERROR_RETURN; 334 } 335 336 /* Get the IrDA descriptor */ 337 err = usbd_get_desc(sc->sc_udev, UDESC_IRDA, 0, 338 USB_IRDA_DESCRIPTOR_SIZE, &sc->sc_irdadesc); 339 if (err) { 340 /* maybe it's embedded in the config desc? */ 341 const void *d = usb_find_desc(sc->sc_udev, UDESC_IRDA, 342 USBD_SUBTYPE_ANY); 343 if (d == NULL) { 344 printf("%s: Cannot get IrDA descriptor\n", 345 USBDEVNAME(sc->sc_dev)); 346 USB_ATTACH_ERROR_RETURN; 347 } 348 memcpy(&sc->sc_irdadesc, d, USB_IRDA_DESCRIPTOR_SIZE); 349 } 350 DPRINTF(("uirda_attach: bmDataSize=0x%02x bmWindowSize=0x%02x " 351 "bmMinTurnaroundTime=0x%02x wBaudRate=0x%04x " 352 "bmAdditionalBOFs=0x%02x bIrdaSniff=%d bMaxUnicastList=%d\n", 353 sc->sc_irdadesc.bmDataSize, 354 sc->sc_irdadesc.bmWindowSize, 355 sc->sc_irdadesc.bmMinTurnaroundTime, 356 UGETW(sc->sc_irdadesc.wBaudRate), 357 sc->sc_irdadesc.bmAdditionalBOFs, 358 sc->sc_irdadesc.bIrdaSniff, 359 sc->sc_irdadesc.bMaxUnicastList)); 360 361 specrev = UGETW(sc->sc_irdadesc.bcdSpecRevision); 362 printf("%s: USB-IrDA protocol version %x.%02x\n", 363 USBDEVNAME(sc->sc_dev), specrev >> 8, specrev & 0xff); 364 365 DPRINTFN(10, ("uirda_attach: %p\n", sc->sc_udev)); 366 367 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, 368 USBDEV(sc->sc_dev)); 369 370 lockinit(&sc->sc_wr_buf_lk, PZERO, "iirwrl", 0, 0); 371 lockinit(&sc->sc_rd_buf_lk, PZERO, "uirrdl", 0, 0); 372 373 ia.ia_type = IR_TYPE_IRFRAME; 374 ia.ia_methods = &uirda_methods; 375 ia.ia_handle = sc; 376 377 sc->sc_child = config_found(self, &ia, ir_print); 378 379 USB_ATTACH_SUCCESS_RETURN; 380 } 381 382 USB_DETACH(uirda) 383 { 384 USB_DETACH_START(uirda, sc); 385 int s; 386 int rv = 0; 387 388 DPRINTF(("uirda_detach: sc=%p flags=%d\n", sc, flags)); 389 390 sc->sc_dying = 1; 391 /* Abort all pipes. Causes processes waiting for transfer to wake. */ 392 if (sc->sc_rd_pipe != NULL) { 393 usbd_abort_pipe(sc->sc_rd_pipe); 394 usbd_close_pipe(sc->sc_rd_pipe); 395 sc->sc_rd_pipe = NULL; 396 } 397 if (sc->sc_wr_pipe != NULL) { 398 usbd_abort_pipe(sc->sc_wr_pipe); 399 usbd_close_pipe(sc->sc_wr_pipe); 400 sc->sc_wr_pipe = NULL; 401 } 402 wakeup(&sc->sc_rd_count); 403 404 s = splusb(); 405 if (--sc->sc_refcnt >= 0) { 406 /* Wait for processes to go away. */ 407 usb_detach_wait(USBDEV(sc->sc_dev)); 408 } 409 splx(s); 410 411 if (sc->sc_child != NULL) { 412 rv = config_detach(sc->sc_child, flags); 413 sc->sc_child = NULL; 414 } 415 416 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, 417 USBDEV(sc->sc_dev)); 418 419 return (rv); 420 } 421 422 int 423 uirda_activate(device_ptr_t self, enum devact act) 424 { 425 struct uirda_softc *sc = (struct uirda_softc *)self; 426 int error = 0; 427 428 switch (act) { 429 case DVACT_ACTIVATE: 430 return (EOPNOTSUPP); 431 break; 432 433 case DVACT_DEACTIVATE: 434 sc->sc_dying = 1; 435 if (sc->sc_child != NULL) 436 error = config_deactivate(sc->sc_child); 437 break; 438 } 439 return (error); 440 } 441 442 int 443 uirda_open(void *h, int flag, int mode, usb_proc_ptr p) 444 { 445 struct uirda_softc *sc = h; 446 int error; 447 usbd_status err; 448 449 DPRINTF(("%s: sc=%p\n", __func__, sc)); 450 451 err = usbd_open_pipe(sc->sc_iface, sc->sc_rd_addr, 0, &sc->sc_rd_pipe); 452 if (err) { 453 error = EIO; 454 goto bad1; 455 } 456 err = usbd_open_pipe(sc->sc_iface, sc->sc_wr_addr, 0, &sc->sc_wr_pipe); 457 if (err) { 458 error = EIO; 459 goto bad2; 460 } 461 sc->sc_rd_xfer = usbd_alloc_xfer(sc->sc_udev); 462 if (sc->sc_rd_xfer == NULL) { 463 error = ENOMEM; 464 goto bad3; 465 } 466 sc->sc_wr_xfer = usbd_alloc_xfer(sc->sc_udev); 467 if (sc->sc_wr_xfer == NULL) { 468 error = ENOMEM; 469 goto bad4; 470 } 471 sc->sc_rd_buf = usbd_alloc_buffer(sc->sc_rd_xfer, 472 IRDA_MAX_FRAME_SIZE + UIRDA_INPUT_HEADER_SIZE); 473 if (sc->sc_rd_buf == NULL) { 474 error = ENOMEM; 475 goto bad5; 476 } 477 sc->sc_wr_buf = usbd_alloc_buffer(sc->sc_wr_xfer, 478 IRDA_MAX_FRAME_SIZE + UIRDA_OUTPUT_HEADER_SIZE); 479 if (sc->sc_wr_buf == NULL) { 480 error = ENOMEM; 481 goto bad5; 482 } 483 sc->sc_rd_count = 0; 484 sc->sc_rd_err = 0; 485 sc->sc_params.speed = 0; 486 sc->sc_params.ebofs = 0; 487 sc->sc_params.maxsize = IRDA_MAX_FRAME_SIZE; 488 sc->sc_wr_hdr = -1; 489 490 err = uirda_start_read(sc); 491 /* XXX check err */ 492 493 return (0); 494 495 bad5: 496 usbd_free_xfer(sc->sc_wr_xfer); 497 sc->sc_wr_xfer = NULL; 498 bad4: 499 usbd_free_xfer(sc->sc_rd_xfer); 500 sc->sc_rd_xfer = NULL; 501 bad3: 502 usbd_close_pipe(sc->sc_wr_pipe); 503 sc->sc_wr_pipe = NULL; 504 bad2: 505 usbd_close_pipe(sc->sc_rd_pipe); 506 sc->sc_rd_pipe = NULL; 507 bad1: 508 return (error); 509 } 510 511 int 512 uirda_close(void *h, int flag, int mode, usb_proc_ptr p) 513 { 514 struct uirda_softc *sc = h; 515 516 DPRINTF(("%s: sc=%p\n", __func__, sc)); 517 518 if (sc->sc_rd_pipe != NULL) { 519 usbd_abort_pipe(sc->sc_rd_pipe); 520 usbd_close_pipe(sc->sc_rd_pipe); 521 sc->sc_rd_pipe = NULL; 522 } 523 if (sc->sc_wr_pipe != NULL) { 524 usbd_abort_pipe(sc->sc_wr_pipe); 525 usbd_close_pipe(sc->sc_wr_pipe); 526 sc->sc_wr_pipe = NULL; 527 } 528 if (sc->sc_rd_xfer != NULL) { 529 usbd_free_xfer(sc->sc_rd_xfer); 530 sc->sc_rd_xfer = NULL; 531 sc->sc_rd_buf = NULL; 532 } 533 if (sc->sc_wr_xfer != NULL) { 534 usbd_free_xfer(sc->sc_wr_xfer); 535 sc->sc_wr_xfer = NULL; 536 sc->sc_wr_buf = NULL; 537 } 538 539 return (0); 540 } 541 542 int 543 uirda_read(void *h, struct uio *uio, int flag) 544 { 545 struct uirda_softc *sc = h; 546 usbd_status err; 547 int s; 548 int error; 549 u_int n; 550 551 DPRINTFN(1,("%s: sc=%p\n", __func__, sc)); 552 553 if (sc->sc_dying) 554 return (EIO); 555 556 #ifdef DIAGNOSTIC 557 if (sc->sc_rd_buf == NULL) 558 return (EINVAL); 559 #endif 560 561 sc->sc_refcnt++; 562 563 do { 564 s = splusb(); 565 while (sc->sc_rd_count == 0) { 566 DPRINTFN(5,("uirda_read: calling tsleep()\n")); 567 error = tsleep(&sc->sc_rd_count, PZERO | PCATCH, 568 "uirdrd", 0); 569 if (sc->sc_dying) 570 error = EIO; 571 if (error) { 572 splx(s); 573 DPRINTF(("uirda_read: tsleep() = %d\n", error)); 574 goto ret; 575 } 576 } 577 splx(s); 578 579 lockmgr(&sc->sc_rd_buf_lk, LK_EXCLUSIVE, NULL); 580 n = sc->sc_rd_count - UIRDA_INPUT_HEADER_SIZE; 581 DPRINTFN(1,("%s: sc=%p n=%u, hdr=0x%02x\n", __func__, 582 sc, n, sc->sc_rd_buf[0])); 583 if (n > uio->uio_resid) 584 error = EINVAL; 585 else 586 error = uiomove(sc->sc_rd_buf+UIRDA_INPUT_HEADER_SIZE, 587 n, uio); 588 sc->sc_rd_count = 0; 589 lockmgr(&sc->sc_rd_buf_lk, LK_RELEASE, NULL); 590 591 err = uirda_start_read(sc); 592 /* XXX check err */ 593 594 } while (n == 0); 595 596 DPRINTFN(1,("uirda_read: return %d\n", error)); 597 598 ret: 599 if (--sc->sc_refcnt < 0) 600 usb_detach_wakeup(USBDEV(sc->sc_dev)); 601 return (error); 602 } 603 604 int 605 uirda_write(void *h, struct uio *uio, int flag) 606 { 607 struct uirda_softc *sc = h; 608 usbd_status err; 609 u_int32_t n; 610 int error = 0; 611 612 DPRINTFN(1,("%s: sc=%p\n", __func__, sc)); 613 614 if (sc->sc_dying) 615 return (EIO); 616 617 #ifdef DIAGNOSTIC 618 if (sc->sc_wr_buf == NULL) 619 return (EINVAL); 620 #endif 621 622 n = uio->uio_resid; 623 if (n > sc->sc_params.maxsize) 624 return (EINVAL); 625 626 sc->sc_refcnt++; 627 lockmgr(&sc->sc_wr_buf_lk, LK_EXCLUSIVE, NULL); 628 629 sc->sc_wr_buf[0] = UIRDA_EB_NO_CHANGE | UIRDA_NO_SPEED; 630 error = uiomove(sc->sc_wr_buf + UIRDA_OUTPUT_HEADER_SIZE, n, uio); 631 if (!error) { 632 DPRINTFN(1, ("uirdawrite: transfer %d bytes\n", n)); 633 634 n++; 635 err = usbd_bulk_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe, 636 USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 637 UIRDA_WR_TIMEOUT, 638 sc->sc_wr_buf, &n, "uirdawr"); 639 DPRINTFN(2, ("uirdawrite: err=%d\n", err)); 640 if (err) { 641 if (err == USBD_INTERRUPTED) 642 error = EINTR; 643 else if (err == USBD_TIMEOUT) 644 error = ETIMEDOUT; 645 else 646 error = EIO; 647 } 648 } 649 650 lockmgr(&sc->sc_wr_buf_lk, LK_RELEASE, NULL); 651 if (--sc->sc_refcnt < 0) 652 usb_detach_wakeup(USBDEV(sc->sc_dev)); 653 654 DPRINTFN(1,("%s: sc=%p done\n", __func__, sc)); 655 return (error); 656 } 657 658 int 659 uirda_poll(void *h, int events, usb_proc_ptr p) 660 { 661 struct uirda_softc *sc = h; 662 int revents = 0; 663 int s; 664 665 DPRINTFN(1,("%s: sc=%p\n", __func__, sc)); 666 667 s = splusb(); 668 if (events & (POLLOUT | POLLWRNORM)) 669 revents |= events & (POLLOUT | POLLWRNORM); 670 if (events & (POLLIN | POLLRDNORM)) { 671 if (sc->sc_rd_count != 0) { 672 DPRINTFN(2,("%s: have data\n", __func__)); 673 revents |= events & (POLLIN | POLLRDNORM); 674 } else { 675 DPRINTFN(2,("%s: recording select\n", __func__)); 676 selrecord(p, &sc->sc_rd_sel); 677 } 678 } 679 splx(s); 680 681 return (revents); 682 } 683 684 static void 685 filt_uirdardetach(struct knote *kn) 686 { 687 struct uirda_softc *sc = kn->kn_hook; 688 int s; 689 690 s = splusb(); 691 SLIST_REMOVE(&sc->sc_rd_sel.sel_klist, kn, knote, kn_selnext); 692 splx(s); 693 } 694 695 static int 696 filt_uirdaread(struct knote *kn, long hint) 697 { 698 struct uirda_softc *sc = kn->kn_hook; 699 700 kn->kn_data = sc->sc_rd_count; 701 return (kn->kn_data > 0); 702 } 703 704 static void 705 filt_uirdawdetach(struct knote *kn) 706 { 707 struct uirda_softc *sc = kn->kn_hook; 708 int s; 709 710 s = splusb(); 711 SLIST_REMOVE(&sc->sc_wr_sel.sel_klist, kn, knote, kn_selnext); 712 splx(s); 713 } 714 715 static const struct filterops uirdaread_filtops = 716 { 1, NULL, filt_uirdardetach, filt_uirdaread }; 717 static const struct filterops uirdawrite_filtops = 718 { 1, NULL, filt_uirdawdetach, filt_seltrue }; 719 720 int 721 uirda_kqfilter(void *h, struct knote *kn) 722 { 723 struct uirda_softc *sc = kn->kn_hook; 724 struct klist *klist; 725 int s; 726 727 switch (kn->kn_filter) { 728 case EVFILT_READ: 729 klist = &sc->sc_rd_sel.sel_klist; 730 kn->kn_fop = &uirdaread_filtops; 731 break; 732 case EVFILT_WRITE: 733 klist = &sc->sc_wr_sel.sel_klist; 734 kn->kn_fop = &uirdawrite_filtops; 735 break; 736 default: 737 return (1); 738 } 739 740 kn->kn_hook = sc; 741 742 s = splusb(); 743 SLIST_INSERT_HEAD(klist, kn, kn_selnext); 744 splx(s); 745 746 return (0); 747 } 748 749 int 750 uirda_set_params(void *h, struct irda_params *p) 751 { 752 struct uirda_softc *sc = h; 753 usbd_status err; 754 int i; 755 u_int8_t hdr; 756 u_int32_t n; 757 u_int mask; 758 759 DPRINTF(("%s: sc=%p, speed=%d ebofs=%d maxsize=%d\n", __func__, 760 sc, p->speed, p->ebofs, p->maxsize)); 761 762 if (sc->sc_dying) 763 return (EIO); 764 765 hdr = 0; 766 if (p->ebofs != sc->sc_params.ebofs) { 767 /* round up ebofs */ 768 mask = sc->sc_irdadesc.bmAdditionalBOFs; 769 for (i = 0; i < UIRDA_NEBOFS; i++) { 770 if ((mask & uirda_ebofs[i].mask) && 771 uirda_ebofs[i].count >= p->ebofs) { 772 hdr = uirda_ebofs[i].header; 773 goto found1; 774 } 775 } 776 /* no good value found */ 777 return (EINVAL); 778 found1: 779 DPRINTF(("uirda_set_params: ebofs hdr=0x%02x\n", hdr)); 780 ; 781 782 } 783 if (hdr != 0 || p->speed != sc->sc_params.speed) { 784 /* find speed */ 785 mask = UGETW(sc->sc_irdadesc.wBaudRate); 786 for (i = 0; i < UIRDA_NSPEEDS; i++) { 787 if ((mask & uirda_speeds[i].mask) && 788 uirda_speeds[i].speed == p->speed) { 789 hdr |= uirda_speeds[i].header; 790 goto found2; 791 } 792 } 793 /* no good value found */ 794 return (EINVAL); 795 found2: 796 DPRINTF(("uirda_set_params: speed hdr=0x%02x\n", hdr)); 797 ; 798 } 799 if (p->maxsize != sc->sc_params.maxsize) { 800 if (p->maxsize > IRDA_MAX_FRAME_SIZE) 801 return (EINVAL); 802 sc->sc_params.maxsize = p->maxsize; 803 #if 0 804 DPRINTF(("%s: new buffers, old size=%d\n", __func__, 805 sc->sc_params.maxsize)); 806 if (p->maxsize > 10000 || p < 0) /* XXX */ 807 return (EINVAL); 808 809 /* Change the write buffer */ 810 lockmgr(&sc->sc_wr_buf_lk, LK_EXCLUSIVE, NULL); 811 if (sc->sc_wr_buf != NULL) 812 usbd_free_buffer(sc->sc_wr_xfer); 813 sc->sc_wr_buf = usbd_alloc_buffer(sc->sc_wr_xfer, p->maxsize+1); 814 lockmgr(&sc->sc_wr_buf_lk, LK_RELEASE, NULL); 815 if (sc->sc_wr_buf == NULL) 816 return (ENOMEM); 817 818 /* Change the read buffer */ 819 lockmgr(&sc->sc_rd_buf_lk, LK_EXCLUSIVE, NULL); 820 usbd_abort_pipe(sc->sc_rd_pipe); 821 if (sc->sc_rd_buf != NULL) 822 usbd_free_buffer(sc->sc_rd_xfer); 823 sc->sc_rd_buf = usbd_alloc_buffer(sc->sc_rd_xfer, p->maxsize+1); 824 sc->sc_rd_count = 0; 825 if (sc->sc_rd_buf == NULL) { 826 lockmgr(&sc->sc_rd_buf_lk, LK_RELEASE, NULL); 827 return (ENOMEM); 828 } 829 sc->sc_params.maxsize = p->maxsize; 830 err = uirda_start_read(sc); /* XXX check */ 831 lockmgr(&sc->sc_rd_buf_lk, LK_RELEASE, NULL); 832 #endif 833 } 834 if (hdr != 0 && hdr != sc->sc_wr_hdr) { 835 /* 836 * A change has occurred, transmit a 0 length frame with 837 * the new settings. The 0 length frame is not sent to the 838 * device. 839 */ 840 DPRINTF(("%s: sc=%p setting header 0x%02x\n", 841 __func__, sc, hdr)); 842 sc->sc_wr_hdr = hdr; 843 lockmgr(&sc->sc_wr_buf_lk, LK_EXCLUSIVE, NULL); 844 sc->sc_wr_buf[0] = hdr; 845 n = UIRDA_OUTPUT_HEADER_SIZE; 846 err = usbd_bulk_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe, 847 USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 848 UIRDA_WR_TIMEOUT, sc->sc_wr_buf, &n, "uirdast"); 849 if (err) { 850 printf("%s: set failed, err=%d\n", 851 USBDEVNAME(sc->sc_dev), err); 852 usbd_clear_endpoint_stall(sc->sc_wr_pipe); 853 } 854 lockmgr(&sc->sc_wr_buf_lk, LK_RELEASE, NULL); 855 } 856 857 sc->sc_params = *p; 858 859 return (0); 860 } 861 862 int 863 uirda_get_speeds(void *h, int *speeds) 864 { 865 struct uirda_softc *sc = h; 866 u_int isp; 867 u_int usp; 868 869 DPRINTF(("%s: sc=%p\n", __func__, sc)); 870 871 if (sc->sc_dying) 872 return (EIO); 873 874 usp = UGETW(sc->sc_irdadesc.wBaudRate); 875 isp = 0; 876 if (usp & UI_BR_4000000) isp |= IRDA_SPEED_4000000; 877 if (usp & UI_BR_1152000) isp |= IRDA_SPEED_1152000; 878 if (usp & UI_BR_576000) isp |= IRDA_SPEED_576000; 879 if (usp & UI_BR_115200) isp |= IRDA_SPEED_115200; 880 if (usp & UI_BR_57600) isp |= IRDA_SPEED_57600; 881 if (usp & UI_BR_38400) isp |= IRDA_SPEED_38400; 882 if (usp & UI_BR_19200) isp |= IRDA_SPEED_19200; 883 if (usp & UI_BR_9600) isp |= IRDA_SPEED_9600; 884 if (usp & UI_BR_2400) isp |= IRDA_SPEED_2400; 885 *speeds = isp; 886 return (0); 887 } 888 889 int 890 uirda_get_turnarounds(void *h, int *turnarounds) 891 { 892 struct uirda_softc *sc = h; 893 u_int ita; 894 u_int uta; 895 896 DPRINTF(("%s: sc=%p\n", __func__, sc)); 897 898 if (sc->sc_dying) 899 return (EIO); 900 901 uta = sc->sc_irdadesc.bmMinTurnaroundTime; 902 ita = 0; 903 if (uta & UI_TA_0) ita |= IRDA_TURNT_0; 904 if (uta & UI_TA_10) ita |= IRDA_TURNT_10; 905 if (uta & UI_TA_50) ita |= IRDA_TURNT_50; 906 if (uta & UI_TA_100) ita |= IRDA_TURNT_100; 907 if (uta & UI_TA_500) ita |= IRDA_TURNT_500; 908 if (uta & UI_TA_1000) ita |= IRDA_TURNT_1000; 909 if (uta & UI_TA_5000) ita |= IRDA_TURNT_5000; 910 if (uta & UI_TA_10000) ita |= IRDA_TURNT_10000; 911 *turnarounds = ita; 912 return (0); 913 } 914 915 void 916 uirda_rd_cb(usbd_xfer_handle xfer, usbd_private_handle priv, 917 usbd_status status) 918 { 919 struct uirda_softc *sc = priv; 920 u_int32_t size; 921 922 DPRINTFN(1,("%s: sc=%p\n", __func__, sc)); 923 924 if (status == USBD_CANCELLED) /* this is normal */ 925 return; 926 if (status) { 927 size = UIRDA_INPUT_HEADER_SIZE; 928 sc->sc_rd_err = 1; 929 } else { 930 usbd_get_xfer_status(xfer, NULL, NULL, &size, NULL); 931 } 932 DPRINTFN(1,("%s: sc=%p size=%u, err=%d\n", __func__, sc, size, 933 sc->sc_rd_err)); 934 sc->sc_rd_count = size; 935 wakeup(&sc->sc_rd_count); /* XXX should use flag */ 936 selnotify(&sc->sc_rd_sel, 0); 937 } 938 939 usbd_status 940 uirda_start_read(struct uirda_softc *sc) 941 { 942 usbd_status err; 943 944 DPRINTFN(1,("%s: sc=%p, size=%d\n", __func__, sc, 945 sc->sc_params.maxsize + UIRDA_INPUT_HEADER_SIZE)); 946 947 if (sc->sc_dying) 948 return (USBD_IOERROR); 949 950 if (sc->sc_rd_err) { 951 sc->sc_rd_err = 0; 952 DPRINTF(("uirda_start_read: clear stall\n")); 953 usbd_clear_endpoint_stall(sc->sc_rd_pipe); 954 } 955 956 usbd_setup_xfer(sc->sc_rd_xfer, sc->sc_rd_pipe, sc, sc->sc_rd_buf, 957 sc->sc_params.maxsize + UIRDA_INPUT_HEADER_SIZE, 958 USBD_SHORT_XFER_OK | USBD_NO_COPY, 959 USBD_NO_TIMEOUT, uirda_rd_cb); 960 err = usbd_transfer(sc->sc_rd_xfer); 961 if (err != USBD_IN_PROGRESS) { 962 DPRINTF(("uirda_start_read: err=%d\n", err)); 963 return (err); 964 } 965 return (USBD_NORMAL_COMPLETION); 966 } 967