1 /* $NetBSD: uirda.c,v 1.14 2002/11/26 18:49:49 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.14 2002/11/26 18:49:49 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, 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 usb_descriptor_t *usb_find_desc(usbd_device_handle dev, int type); 251 252 /* 253 * These devices don't quite follow the spec. Speed changing is broken 254 * and they don't handle windows. 255 * But we change speed in a safe way, and don't use windows now. 256 * Some devices also seem to have an interrupt pipe that can be ignored. 257 * 258 * Table information taken from Linux driver. 259 */ 260 Static const struct usb_devno uirda_devs[] = { 261 { USB_VENDOR_ACTISYS, USB_PRODUCT_ACTISYS_IR2000U }, 262 { USB_VENDOR_EXTENDED, USB_PRODUCT_EXTENDED_XTNDACCESS }, 263 { USB_VENDOR_KAWATSU, USB_PRODUCT_KAWATSU_KC180 }, 264 }; 265 #define uirda_lookup(v, p) (usb_lookup(uirda_devs, v, p)) 266 267 USB_DECLARE_DRIVER(uirda); 268 269 USB_MATCH(uirda) 270 { 271 USB_MATCH_START(uirda, uaa); 272 usb_interface_descriptor_t *id; 273 274 DPRINTFN(50,("uirda_match\n")); 275 276 if (uaa->iface == NULL) 277 return (UMATCH_NONE); 278 279 if (uirda_lookup(uaa->vendor, uaa->product) != NULL) 280 return (UMATCH_VENDOR_PRODUCT); 281 282 id = usbd_get_interface_descriptor(uaa->iface); 283 if (id != NULL && 284 id->bInterfaceClass == UICLASS_APPL_SPEC && 285 id->bInterfaceSubClass == UISUBCLASS_IRDA && 286 id->bInterfaceProtocol == UIPROTO_IRDA) 287 return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO); 288 return (UMATCH_NONE); 289 } 290 291 USB_ATTACH(uirda) 292 { 293 USB_ATTACH_START(uirda, sc, uaa); 294 usbd_device_handle dev = uaa->device; 295 usbd_interface_handle iface = uaa->iface; 296 char devinfo[1024]; 297 usb_endpoint_descriptor_t *ed; 298 usbd_status err; 299 u_int8_t epcount; 300 u_int specrev; 301 int i; 302 struct ir_attach_args ia; 303 304 DPRINTFN(10,("uirda_attach: sc=%p\n", sc)); 305 306 usbd_devinfo(dev, 0, devinfo); 307 USB_ATTACH_SETUP; 308 printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo); 309 310 sc->sc_udev = dev; 311 sc->sc_iface = iface; 312 313 epcount = 0; 314 (void)usbd_endpoint_count(iface, &epcount); 315 316 sc->sc_rd_addr = -1; 317 sc->sc_wr_addr = -1; 318 for (i = 0; i < epcount; i++) { 319 ed = usbd_interface2endpoint_descriptor(iface, i); 320 if (ed == NULL) { 321 printf("%s: couldn't get ep %d\n", 322 USBDEVNAME(sc->sc_dev), i); 323 USB_ATTACH_ERROR_RETURN; 324 } 325 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 326 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 327 sc->sc_rd_addr = ed->bEndpointAddress; 328 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 329 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 330 sc->sc_wr_addr = ed->bEndpointAddress; 331 } 332 } 333 if (sc->sc_rd_addr == -1 || sc->sc_wr_addr == -1) { 334 printf("%s: missing endpoint\n", USBDEVNAME(sc->sc_dev)); 335 USB_ATTACH_ERROR_RETURN; 336 } 337 338 /* Get the IrDA descriptor */ 339 err = usbd_get_desc(sc->sc_udev, UDESC_IRDA, 0, 340 USB_IRDA_DESCRIPTOR_SIZE, &sc->sc_irdadesc); 341 if (err) { 342 /* maybe it's embedded in the config desc? */ 343 void *d = usb_find_desc(sc->sc_udev, UDESC_IRDA); 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, usb_proc_ptr p) 445 { 446 struct uirda_softc *sc = h; 447 int error; 448 usbd_status err; 449 450 DPRINTF(("%s: sc=%p\n", __func__, sc)); 451 452 err = usbd_open_pipe(sc->sc_iface, sc->sc_rd_addr, 0, &sc->sc_rd_pipe); 453 if (err) { 454 error = EIO; 455 goto bad1; 456 } 457 err = usbd_open_pipe(sc->sc_iface, sc->sc_wr_addr, 0, &sc->sc_wr_pipe); 458 if (err) { 459 error = EIO; 460 goto bad2; 461 } 462 sc->sc_rd_xfer = usbd_alloc_xfer(sc->sc_udev); 463 if (sc->sc_rd_xfer == NULL) { 464 error = ENOMEM; 465 goto bad3; 466 } 467 sc->sc_wr_xfer = usbd_alloc_xfer(sc->sc_udev); 468 if (sc->sc_wr_xfer == NULL) { 469 error = ENOMEM; 470 goto bad4; 471 } 472 sc->sc_rd_buf = usbd_alloc_buffer(sc->sc_rd_xfer, 473 IRDA_MAX_FRAME_SIZE + UIRDA_INPUT_HEADER_SIZE); 474 if (sc->sc_rd_buf == NULL) { 475 error = ENOMEM; 476 goto bad5; 477 } 478 sc->sc_wr_buf = usbd_alloc_buffer(sc->sc_wr_xfer, 479 IRDA_MAX_FRAME_SIZE + UIRDA_OUTPUT_HEADER_SIZE); 480 if (sc->sc_wr_buf == NULL) { 481 error = ENOMEM; 482 goto bad5; 483 } 484 sc->sc_rd_count = 0; 485 sc->sc_rd_err = 0; 486 sc->sc_params.speed = 0; 487 sc->sc_params.ebofs = 0; 488 sc->sc_params.maxsize = IRDA_MAX_FRAME_SIZE; 489 sc->sc_wr_hdr = -1; 490 491 err = uirda_start_read(sc); 492 /* XXX check err */ 493 494 return (0); 495 496 bad5: 497 usbd_free_xfer(sc->sc_wr_xfer); 498 sc->sc_wr_xfer = NULL; 499 bad4: 500 usbd_free_xfer(sc->sc_rd_xfer); 501 sc->sc_rd_xfer = NULL; 502 bad3: 503 usbd_close_pipe(sc->sc_wr_pipe); 504 sc->sc_wr_pipe = NULL; 505 bad2: 506 usbd_close_pipe(sc->sc_rd_pipe); 507 sc->sc_rd_pipe = NULL; 508 bad1: 509 return (error); 510 } 511 512 int 513 uirda_close(void *h, int flag, int mode, usb_proc_ptr p) 514 { 515 struct uirda_softc *sc = h; 516 517 DPRINTF(("%s: sc=%p\n", __func__, sc)); 518 519 if (sc->sc_rd_pipe != NULL) { 520 usbd_abort_pipe(sc->sc_rd_pipe); 521 usbd_close_pipe(sc->sc_rd_pipe); 522 sc->sc_rd_pipe = NULL; 523 } 524 if (sc->sc_wr_pipe != NULL) { 525 usbd_abort_pipe(sc->sc_wr_pipe); 526 usbd_close_pipe(sc->sc_wr_pipe); 527 sc->sc_wr_pipe = NULL; 528 } 529 if (sc->sc_rd_xfer != NULL) { 530 usbd_free_xfer(sc->sc_rd_xfer); 531 sc->sc_rd_xfer = NULL; 532 sc->sc_rd_buf = NULL; 533 } 534 if (sc->sc_wr_xfer != NULL) { 535 usbd_free_xfer(sc->sc_wr_xfer); 536 sc->sc_wr_xfer = NULL; 537 sc->sc_wr_buf = NULL; 538 } 539 540 return (0); 541 } 542 543 int 544 uirda_read(void *h, struct uio *uio, int flag) 545 { 546 struct uirda_softc *sc = h; 547 usbd_status err; 548 int s; 549 int error; 550 u_int n; 551 552 DPRINTFN(1,("%s: sc=%p\n", __func__, sc)); 553 554 if (sc->sc_dying) 555 return (EIO); 556 557 #ifdef DIAGNOSTIC 558 if (sc->sc_rd_buf == NULL) 559 return (EINVAL); 560 #endif 561 562 sc->sc_refcnt++; 563 564 do { 565 s = splusb(); 566 while (sc->sc_rd_count == 0) { 567 DPRINTFN(5,("uirda_read: calling tsleep()\n")); 568 error = tsleep(&sc->sc_rd_count, PZERO | PCATCH, 569 "uirdrd", 0); 570 if (sc->sc_dying) 571 error = EIO; 572 if (error) { 573 splx(s); 574 DPRINTF(("uirda_read: tsleep() = %d\n", error)); 575 goto ret; 576 } 577 } 578 splx(s); 579 580 lockmgr(&sc->sc_rd_buf_lk, LK_EXCLUSIVE, NULL); 581 n = sc->sc_rd_count - UIRDA_INPUT_HEADER_SIZE; 582 DPRINTFN(1,("%s: sc=%p n=%u, hdr=0x%02x\n", __func__, 583 sc, n, sc->sc_rd_buf[0])); 584 if (n > uio->uio_resid) 585 error = EINVAL; 586 else 587 error = uiomove(sc->sc_rd_buf+UIRDA_INPUT_HEADER_SIZE, 588 n, uio); 589 sc->sc_rd_count = 0; 590 lockmgr(&sc->sc_rd_buf_lk, LK_RELEASE, NULL); 591 592 err = uirda_start_read(sc); 593 /* XXX check err */ 594 595 } while (n == 0); 596 597 DPRINTFN(1,("uirda_read: return %d\n", error)); 598 599 ret: 600 if (--sc->sc_refcnt < 0) 601 usb_detach_wakeup(USBDEV(sc->sc_dev)); 602 return (error); 603 } 604 605 int 606 uirda_write(void *h, struct uio *uio, int flag) 607 { 608 struct uirda_softc *sc = h; 609 usbd_status err; 610 u_int32_t n; 611 int error = 0; 612 613 DPRINTFN(1,("%s: sc=%p\n", __func__, sc)); 614 615 if (sc->sc_dying) 616 return (EIO); 617 618 #ifdef DIAGNOSTIC 619 if (sc->sc_wr_buf == NULL) 620 return (EINVAL); 621 #endif 622 623 n = uio->uio_resid; 624 if (n > sc->sc_params.maxsize) 625 return (EINVAL); 626 627 sc->sc_refcnt++; 628 lockmgr(&sc->sc_wr_buf_lk, LK_EXCLUSIVE, NULL); 629 630 sc->sc_wr_buf[0] = UIRDA_EB_NO_CHANGE | UIRDA_NO_SPEED; 631 error = uiomove(sc->sc_wr_buf + UIRDA_OUTPUT_HEADER_SIZE, n, uio); 632 if (!error) { 633 DPRINTFN(1, ("uirdawrite: transfer %d bytes\n", n)); 634 635 n++; 636 err = usbd_bulk_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe, 637 USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 638 UIRDA_WR_TIMEOUT, 639 sc->sc_wr_buf, &n, "uirdawr"); 640 DPRINTFN(2, ("uirdawrite: err=%d\n", err)); 641 if (err) { 642 if (err == USBD_INTERRUPTED) 643 error = EINTR; 644 else if (err == USBD_TIMEOUT) 645 error = ETIMEDOUT; 646 else 647 error = EIO; 648 } 649 } 650 651 lockmgr(&sc->sc_wr_buf_lk, LK_RELEASE, NULL); 652 if (--sc->sc_refcnt < 0) 653 usb_detach_wakeup(USBDEV(sc->sc_dev)); 654 655 DPRINTFN(1,("%s: sc=%p done\n", __func__, sc)); 656 return (error); 657 } 658 659 int 660 uirda_poll(void *h, int events, usb_proc_ptr p) 661 { 662 struct uirda_softc *sc = h; 663 int revents = 0; 664 int s; 665 666 DPRINTFN(1,("%s: sc=%p\n", __func__, sc)); 667 668 s = splusb(); 669 if (events & (POLLOUT | POLLWRNORM)) 670 revents |= events & (POLLOUT | POLLWRNORM); 671 if (events & (POLLIN | POLLRDNORM)) { 672 if (sc->sc_rd_count != 0) { 673 DPRINTFN(2,("%s: have data\n", __func__)); 674 revents |= events & (POLLIN | POLLRDNORM); 675 } else { 676 DPRINTFN(2,("%s: recording select\n", __func__)); 677 selrecord(p, &sc->sc_rd_sel); 678 } 679 } 680 splx(s); 681 682 return (revents); 683 } 684 685 static void 686 filt_uirdardetach(struct knote *kn) 687 { 688 struct uirda_softc *sc = kn->kn_hook; 689 int s; 690 691 s = splusb(); 692 SLIST_REMOVE(&sc->sc_rd_sel.sel_klist, kn, knote, kn_selnext); 693 splx(s); 694 } 695 696 static int 697 filt_uirdaread(struct knote *kn, long hint) 698 { 699 struct uirda_softc *sc = kn->kn_hook; 700 701 kn->kn_data = sc->sc_rd_count; 702 return (kn->kn_data > 0); 703 } 704 705 static void 706 filt_uirdawdetach(struct knote *kn) 707 { 708 struct uirda_softc *sc = kn->kn_hook; 709 int s; 710 711 s = splusb(); 712 SLIST_REMOVE(&sc->sc_wr_sel.sel_klist, kn, knote, kn_selnext); 713 splx(s); 714 } 715 716 static const struct filterops uirdaread_filtops = 717 { 1, NULL, filt_uirdardetach, filt_uirdaread }; 718 static const struct filterops uirdawrite_filtops = 719 { 1, NULL, filt_uirdawdetach, filt_seltrue }; 720 721 int 722 uirda_kqfilter(void *h, struct knote *kn) 723 { 724 struct uirda_softc *sc = kn->kn_hook; 725 struct klist *klist; 726 int s; 727 728 switch (kn->kn_filter) { 729 case EVFILT_READ: 730 klist = &sc->sc_rd_sel.sel_klist; 731 kn->kn_fop = &uirdaread_filtops; 732 break; 733 case EVFILT_WRITE: 734 klist = &sc->sc_wr_sel.sel_klist; 735 kn->kn_fop = &uirdawrite_filtops; 736 break; 737 default: 738 return (1); 739 } 740 741 kn->kn_hook = sc; 742 743 s = splusb(); 744 SLIST_INSERT_HEAD(klist, kn, kn_selnext); 745 splx(s); 746 747 return (0); 748 } 749 750 int 751 uirda_set_params(void *h, struct irda_params *p) 752 { 753 struct uirda_softc *sc = h; 754 usbd_status err; 755 int i; 756 u_int8_t hdr; 757 u_int32_t n; 758 u_int mask; 759 760 DPRINTF(("%s: sc=%p, speed=%d ebofs=%d maxsize=%d\n", __func__, 761 sc, p->speed, p->ebofs, p->maxsize)); 762 763 if (sc->sc_dying) 764 return (EIO); 765 766 hdr = 0; 767 if (p->ebofs != sc->sc_params.ebofs) { 768 /* round up ebofs */ 769 mask = sc->sc_irdadesc.bmAdditionalBOFs; 770 for (i = 0; i < UIRDA_NEBOFS; i++) { 771 if ((mask & uirda_ebofs[i].mask) && 772 uirda_ebofs[i].count >= p->ebofs) { 773 hdr = uirda_ebofs[i].header; 774 goto found1; 775 } 776 } 777 /* no good value found */ 778 return (EINVAL); 779 found1: 780 DPRINTF(("uirda_set_params: ebofs hdr=0x%02x\n", hdr)); 781 ; 782 783 } 784 if (hdr != 0 || p->speed != sc->sc_params.speed) { 785 /* find speed */ 786 mask = UGETW(sc->sc_irdadesc.wBaudRate); 787 for (i = 0; i < UIRDA_NSPEEDS; i++) { 788 if ((mask & uirda_speeds[i].mask) && 789 uirda_speeds[i].speed == p->speed) { 790 hdr |= uirda_speeds[i].header; 791 goto found2; 792 } 793 } 794 /* no good value found */ 795 return (EINVAL); 796 found2: 797 DPRINTF(("uirda_set_params: speed hdr=0x%02x\n", hdr)); 798 ; 799 } 800 if (p->maxsize != sc->sc_params.maxsize) { 801 if (p->maxsize > IRDA_MAX_FRAME_SIZE) 802 return (EINVAL); 803 sc->sc_params.maxsize = p->maxsize; 804 #if 0 805 DPRINTF(("%s: new buffers, old size=%d\n", __func__, 806 sc->sc_params.maxsize)); 807 if (p->maxsize > 10000 || p < 0) /* XXX */ 808 return (EINVAL); 809 810 /* Change the write buffer */ 811 lockmgr(&sc->sc_wr_buf_lk, LK_EXCLUSIVE, NULL); 812 if (sc->sc_wr_buf != NULL) 813 usbd_free_buffer(sc->sc_wr_xfer); 814 sc->sc_wr_buf = usbd_alloc_buffer(sc->sc_wr_xfer, p->maxsize+1); 815 lockmgr(&sc->sc_wr_buf_lk, LK_RELEASE, NULL); 816 if (sc->sc_wr_buf == NULL) 817 return (ENOMEM); 818 819 /* Change the read buffer */ 820 lockmgr(&sc->sc_rd_buf_lk, LK_EXCLUSIVE, NULL); 821 usbd_abort_pipe(sc->sc_rd_pipe); 822 if (sc->sc_rd_buf != NULL) 823 usbd_free_buffer(sc->sc_rd_xfer); 824 sc->sc_rd_buf = usbd_alloc_buffer(sc->sc_rd_xfer, p->maxsize+1); 825 sc->sc_rd_count = 0; 826 if (sc->sc_rd_buf == NULL) { 827 lockmgr(&sc->sc_rd_buf_lk, LK_RELEASE, NULL); 828 return (ENOMEM); 829 } 830 sc->sc_params.maxsize = p->maxsize; 831 err = uirda_start_read(sc); /* XXX check */ 832 lockmgr(&sc->sc_rd_buf_lk, LK_RELEASE, NULL); 833 #endif 834 } 835 if (hdr != 0 && hdr != sc->sc_wr_hdr) { 836 /* 837 * A change has occurred, transmit a 0 length frame with 838 * the new settings. The 0 length frame is not sent to the 839 * device. 840 */ 841 DPRINTF(("%s: sc=%p setting header 0x%02x\n", 842 __func__, sc, hdr)); 843 sc->sc_wr_hdr = hdr; 844 lockmgr(&sc->sc_wr_buf_lk, LK_EXCLUSIVE, NULL); 845 sc->sc_wr_buf[0] = hdr; 846 n = UIRDA_OUTPUT_HEADER_SIZE; 847 err = usbd_bulk_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe, 848 USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 849 UIRDA_WR_TIMEOUT, sc->sc_wr_buf, &n, "uirdast"); 850 if (err) { 851 printf("%s: set failed, err=%d\n", 852 USBDEVNAME(sc->sc_dev), err); 853 usbd_clear_endpoint_stall(sc->sc_wr_pipe); 854 } 855 lockmgr(&sc->sc_wr_buf_lk, LK_RELEASE, NULL); 856 } 857 858 sc->sc_params = *p; 859 860 return (0); 861 } 862 863 int 864 uirda_get_speeds(void *h, int *speeds) 865 { 866 struct uirda_softc *sc = h; 867 u_int isp; 868 u_int usp; 869 870 DPRINTF(("%s: sc=%p\n", __func__, sc)); 871 872 if (sc->sc_dying) 873 return (EIO); 874 875 usp = UGETW(sc->sc_irdadesc.wBaudRate); 876 isp = 0; 877 if (usp & UI_BR_4000000) isp |= IRDA_SPEED_4000000; 878 if (usp & UI_BR_1152000) isp |= IRDA_SPEED_1152000; 879 if (usp & UI_BR_576000) isp |= IRDA_SPEED_576000; 880 if (usp & UI_BR_115200) isp |= IRDA_SPEED_115200; 881 if (usp & UI_BR_57600) isp |= IRDA_SPEED_57600; 882 if (usp & UI_BR_38400) isp |= IRDA_SPEED_38400; 883 if (usp & UI_BR_19200) isp |= IRDA_SPEED_19200; 884 if (usp & UI_BR_9600) isp |= IRDA_SPEED_9600; 885 if (usp & UI_BR_2400) isp |= IRDA_SPEED_2400; 886 *speeds = isp; 887 return (0); 888 } 889 890 int 891 uirda_get_turnarounds(void *h, int *turnarounds) 892 { 893 struct uirda_softc *sc = h; 894 u_int ita; 895 u_int uta; 896 897 DPRINTF(("%s: sc=%p\n", __func__, sc)); 898 899 if (sc->sc_dying) 900 return (EIO); 901 902 uta = sc->sc_irdadesc.bmMinTurnaroundTime; 903 ita = 0; 904 if (uta & UI_TA_0) ita |= IRDA_TURNT_0; 905 if (uta & UI_TA_10) ita |= IRDA_TURNT_10; 906 if (uta & UI_TA_50) ita |= IRDA_TURNT_50; 907 if (uta & UI_TA_100) ita |= IRDA_TURNT_100; 908 if (uta & UI_TA_500) ita |= IRDA_TURNT_500; 909 if (uta & UI_TA_1000) ita |= IRDA_TURNT_1000; 910 if (uta & UI_TA_5000) ita |= IRDA_TURNT_5000; 911 if (uta & UI_TA_10000) ita |= IRDA_TURNT_10000; 912 *turnarounds = ita; 913 return (0); 914 } 915 916 void 917 uirda_rd_cb(usbd_xfer_handle xfer, usbd_private_handle priv, 918 usbd_status status) 919 { 920 struct uirda_softc *sc = priv; 921 u_int32_t size; 922 923 DPRINTFN(1,("%s: sc=%p\n", __func__, sc)); 924 925 if (status == USBD_CANCELLED) /* this is normal */ 926 return; 927 if (status) { 928 size = UIRDA_INPUT_HEADER_SIZE; 929 sc->sc_rd_err = 1; 930 } else { 931 usbd_get_xfer_status(xfer, NULL, NULL, &size, NULL); 932 } 933 DPRINTFN(1,("%s: sc=%p size=%u, err=%d\n", __func__, sc, size, 934 sc->sc_rd_err)); 935 sc->sc_rd_count = size; 936 wakeup(&sc->sc_rd_count); /* XXX should use flag */ 937 selnotify(&sc->sc_rd_sel, 0); 938 } 939 940 usbd_status 941 uirda_start_read(struct uirda_softc *sc) 942 { 943 usbd_status err; 944 945 DPRINTFN(1,("%s: sc=%p, size=%d\n", __func__, sc, 946 sc->sc_params.maxsize + UIRDA_INPUT_HEADER_SIZE)); 947 948 if (sc->sc_dying) 949 return (USBD_IOERROR); 950 951 if (sc->sc_rd_err) { 952 sc->sc_rd_err = 0; 953 DPRINTF(("uirda_start_read: clear stall\n")); 954 usbd_clear_endpoint_stall(sc->sc_rd_pipe); 955 } 956 957 usbd_setup_xfer(sc->sc_rd_xfer, sc->sc_rd_pipe, sc, sc->sc_rd_buf, 958 sc->sc_params.maxsize + UIRDA_INPUT_HEADER_SIZE, 959 USBD_SHORT_XFER_OK | USBD_NO_COPY, 960 USBD_NO_TIMEOUT, uirda_rd_cb); 961 err = usbd_transfer(sc->sc_rd_xfer); 962 if (err != USBD_IN_PROGRESS) { 963 DPRINTF(("uirda_start_read: err=%d\n", err)); 964 return (err); 965 } 966 return (USBD_NORMAL_COMPLETION); 967 } 968