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