1 /* $NetBSD: ugen.c,v 1.40 2000/06/01 14:28:59 augustss Exp $ */ 2 /* $FreeBSD: src/sys/dev/usb/ugen.c,v 1.26 1999/11/17 22:33:41 n_hibma Exp $ */ 3 4 /* 5 * Copyright (c) 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Lennart Augustsson (lennart@augustsson.net) at 10 * Carlstedt Research & Technology. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the NetBSD 23 * Foundation, Inc. and its contributors. 24 * 4. Neither the name of The NetBSD Foundation nor the names of its 25 * contributors may be used to endorse or promote products derived 26 * from this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 * POSSIBILITY OF SUCH DAMAGE. 39 */ 40 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/kernel.h> 45 #include <sys/malloc.h> 46 #if defined(__NetBSD__) || defined(__OpenBSD__) 47 #include <sys/device.h> 48 #include <sys/ioctl.h> 49 #elif defined(__FreeBSD__) 50 #include <sys/module.h> 51 #include <sys/bus.h> 52 #include <sys/ioccom.h> 53 #include <sys/conf.h> 54 #include <sys/fcntl.h> 55 #include <sys/filio.h> 56 #endif 57 #include <sys/conf.h> 58 #include <sys/tty.h> 59 #include <sys/file.h> 60 #include <sys/select.h> 61 #include <sys/proc.h> 62 #include <sys/vnode.h> 63 #include <sys/poll.h> 64 65 #include <dev/usb/usb.h> 66 #include <dev/usb/usbdi.h> 67 #include <dev/usb/usbdi_util.h> 68 69 #ifdef UGEN_DEBUG 70 #define DPRINTF(x) if (ugendebug) logprintf x 71 #define DPRINTFN(n,x) if (ugendebug>(n)) logprintf x 72 int ugendebug = 0; 73 #else 74 #define DPRINTF(x) 75 #define DPRINTFN(n,x) 76 #endif 77 78 struct ugen_endpoint { 79 struct ugen_softc *sc; 80 usb_endpoint_descriptor_t *edesc; 81 usbd_interface_handle iface; 82 int state; 83 #define UGEN_ASLP 0x02 /* waiting for data */ 84 #define UGEN_SHORT_OK 0x04 /* short xfers are OK */ 85 usbd_pipe_handle pipeh; 86 struct clist q; 87 struct selinfo rsel; 88 void *ibuf; 89 u_int32_t timeout; 90 }; 91 92 #define UGEN_CHUNK 128 /* chunk size for read */ 93 #define UGEN_IBSIZE 1020 /* buffer size */ 94 #define UGEN_BBSIZE 1024 95 96 struct ugen_softc { 97 USBBASEDEVICE sc_dev; /* base device */ 98 usbd_device_handle sc_udev; 99 100 char sc_is_open[USB_MAX_ENDPOINTS]; 101 struct ugen_endpoint sc_endpoints[USB_MAX_ENDPOINTS][2]; 102 #define OUT 0 103 #define IN 1 104 105 int sc_refcnt; 106 u_char sc_dying; 107 }; 108 109 #if defined(__NetBSD__) || defined(__OpenBSD__) 110 cdev_decl(ugen); 111 #elif defined(__FreeBSD__) 112 d_open_t ugenopen; 113 d_close_t ugenclose; 114 d_read_t ugenread; 115 d_write_t ugenwrite; 116 d_ioctl_t ugenioctl; 117 d_poll_t ugenpoll; 118 119 #define UGEN_CDEV_MAJOR 114 120 121 Static struct cdevsw ugen_cdevsw = { 122 /* open */ ugenopen, 123 /* close */ ugenclose, 124 /* read */ ugenread, 125 /* write */ ugenwrite, 126 /* ioctl */ ugenioctl, 127 /* poll */ ugenpoll, 128 /* mmap */ nommap, 129 /* strategy */ nostrategy, 130 /* name */ "ugen", 131 /* maj */ UGEN_CDEV_MAJOR, 132 /* dump */ nodump, 133 /* psize */ nopsize, 134 /* flags */ 0, 135 /* bmaj */ -1 136 }; 137 #endif 138 139 Static void ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr, 140 usbd_status status); 141 142 Static int ugen_do_read(struct ugen_softc *, int, struct uio *, int); 143 Static int ugen_do_write(struct ugen_softc *, int, struct uio *, int); 144 Static int ugen_do_ioctl(struct ugen_softc *, int, u_long, 145 caddr_t, int, struct proc *); 146 Static int ugen_set_config(struct ugen_softc *sc, int configno); 147 Static usb_config_descriptor_t *ugen_get_cdesc(struct ugen_softc *sc, 148 int index, int *lenp); 149 Static usbd_status ugen_set_interface(struct ugen_softc *, int, int); 150 Static int ugen_get_alt_index(struct ugen_softc *sc, int ifaceidx); 151 152 #define UGENUNIT(n) ((minor(n) >> 4) & 0xf) 153 #define UGENENDPOINT(n) (minor(n) & 0xf) 154 #define UGENDEV(u, e) (makedev(0, ((u) << 4) | (e))) 155 156 USB_DECLARE_DRIVER(ugen); 157 158 USB_MATCH(ugen) 159 { 160 USB_MATCH_START(ugen, uaa); 161 162 if (uaa->usegeneric) 163 return (UMATCH_GENERIC); 164 else 165 return (UMATCH_NONE); 166 } 167 168 USB_ATTACH(ugen) 169 { 170 USB_ATTACH_START(ugen, sc, uaa); 171 usbd_device_handle udev; 172 char devinfo[1024]; 173 usbd_status err; 174 int conf; 175 176 usbd_devinfo(uaa->device, 0, devinfo); 177 USB_ATTACH_SETUP; 178 printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo); 179 180 sc->sc_udev = udev = uaa->device; 181 182 /* First set configuration index 0, the default one for ugen. */ 183 err = usbd_set_config_index(udev, 0, 0); 184 if (err) { 185 printf("%s: setting configuration index 0 failed\n", 186 USBDEVNAME(sc->sc_dev)); 187 sc->sc_dying = 1; 188 USB_ATTACH_ERROR_RETURN; 189 } 190 conf = usbd_get_config_descriptor(udev)->bConfigurationValue; 191 192 /* Set up all the local state for this configuration. */ 193 err = ugen_set_config(sc, conf); 194 if (err) { 195 printf("%s: setting configuration %d failed\n", 196 USBDEVNAME(sc->sc_dev), conf); 197 sc->sc_dying = 1; 198 USB_ATTACH_ERROR_RETURN; 199 } 200 201 #ifdef __FreeBSD__ 202 { 203 static int global_init_done = 0; 204 if (!global_init_done) { 205 cdevsw_add(&ugen_cdevsw); 206 global_init_done = 1; 207 } 208 } 209 #endif 210 211 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, 212 USBDEV(sc->sc_dev)); 213 214 USB_ATTACH_SUCCESS_RETURN; 215 } 216 217 Static int 218 ugen_set_config(struct ugen_softc *sc, int configno) 219 { 220 usbd_device_handle dev = sc->sc_udev; 221 usbd_interface_handle iface; 222 usb_endpoint_descriptor_t *ed; 223 struct ugen_endpoint *sce; 224 u_int8_t niface, nendpt; 225 int ifaceno, endptno, endpt; 226 usbd_status err; 227 int dir; 228 229 DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n", 230 USBDEVNAME(sc->sc_dev), configno, sc)); 231 /* Avoid setting the current value. */ 232 if (usbd_get_config_descriptor(dev)->bConfigurationValue != configno) { 233 err = usbd_set_config_no(dev, configno, 0); 234 if (err) 235 return (err); 236 } 237 238 err = usbd_interface_count(dev, &niface); 239 if (err) 240 return (err); 241 memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints); 242 for (ifaceno = 0; ifaceno < niface; ifaceno++) { 243 DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno)); 244 err = usbd_device2interface_handle(dev, ifaceno, &iface); 245 if (err) 246 return (err); 247 err = usbd_endpoint_count(iface, &nendpt); 248 if (err) 249 return (err); 250 for (endptno = 0; endptno < nendpt; endptno++) { 251 ed = usbd_interface2endpoint_descriptor(iface,endptno); 252 endpt = ed->bEndpointAddress; 253 dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT; 254 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir]; 255 DPRINTFN(1,("ugen_set_config: endptno %d, endpt=0x%02x" 256 "(%d,%d), sce=%p\n", 257 endptno, endpt, UE_GET_ADDR(endpt), 258 UE_GET_DIR(endpt), sce)); 259 sce->sc = sc; 260 sce->edesc = ed; 261 sce->iface = iface; 262 } 263 } 264 return (USBD_NORMAL_COMPLETION); 265 } 266 267 int 268 ugenopen(dev_t dev, int flag, int mode, struct proc *p) 269 { 270 struct ugen_softc *sc; 271 int unit = UGENUNIT(dev); 272 int endpt = UGENENDPOINT(dev); 273 usb_endpoint_descriptor_t *edesc; 274 struct ugen_endpoint *sce; 275 int dir, isize; 276 usbd_status err; 277 278 USB_GET_SC_OPEN(ugen, unit, sc); 279 280 DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n", 281 flag, mode, unit, endpt)); 282 283 if (sc == NULL || sc->sc_dying) 284 return (ENXIO); 285 286 if (sc->sc_is_open[endpt]) 287 return (EBUSY); 288 289 if (endpt == USB_CONTROL_ENDPOINT) { 290 sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1; 291 return (0); 292 } 293 294 /* Make sure there are pipes for all directions. */ 295 for (dir = OUT; dir <= IN; dir++) { 296 if (flag & (dir == OUT ? FWRITE : FREAD)) { 297 sce = &sc->sc_endpoints[endpt][dir]; 298 if (sce == 0 || sce->edesc == 0) 299 return (ENXIO); 300 } 301 } 302 303 /* Actually open the pipes. */ 304 /* XXX Should back out properly if it fails. */ 305 for (dir = OUT; dir <= IN; dir++) { 306 if (!(flag & (dir == OUT ? FWRITE : FREAD))) 307 continue; 308 sce = &sc->sc_endpoints[endpt][dir]; 309 sce->state = 0; 310 sce->timeout = USBD_NO_TIMEOUT; 311 DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n", 312 sc, endpt, dir, sce)); 313 edesc = sce->edesc; 314 switch (edesc->bmAttributes & UE_XFERTYPE) { 315 case UE_INTERRUPT: 316 isize = UGETW(edesc->wMaxPacketSize); 317 if (isize == 0) /* shouldn't happen */ 318 return (EINVAL); 319 sce->ibuf = malloc(isize, M_USBDEV, M_WAITOK); 320 DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n", 321 endpt, isize)); 322 if (clalloc(&sce->q, UGEN_IBSIZE, 0) == -1) 323 return (ENOMEM); 324 err = usbd_open_pipe_intr(sce->iface, 325 edesc->bEndpointAddress, 326 USBD_SHORT_XFER_OK, &sce->pipeh, sce, 327 sce->ibuf, isize, ugenintr, 328 USBD_DEFAULT_INTERVAL); 329 if (err) { 330 free(sce->ibuf, M_USBDEV); 331 clfree(&sce->q); 332 return (EIO); 333 } 334 DPRINTFN(5, ("ugenopen: interrupt open done\n")); 335 break; 336 case UE_BULK: 337 err = usbd_open_pipe(sce->iface, 338 edesc->bEndpointAddress, 0, &sce->pipeh); 339 if (err) 340 return (EIO); 341 break; 342 case UE_CONTROL: 343 case UE_ISOCHRONOUS: 344 return (EINVAL); 345 } 346 } 347 sc->sc_is_open[endpt] = 1; 348 return (0); 349 } 350 351 int 352 ugenclose(dev_t dev, int flag, int mode, struct proc *p) 353 { 354 int endpt = UGENENDPOINT(dev); 355 struct ugen_softc *sc; 356 struct ugen_endpoint *sce; 357 int dir; 358 359 USB_GET_SC(ugen, UGENUNIT(dev), sc); 360 361 DPRINTFN(5, ("ugenclose: flag=%d, mode=%d, unit=%d, endpt=%d\n", 362 flag, mode, UGENUNIT(dev), endpt)); 363 364 #ifdef DIAGNOSTIC 365 if (!sc->sc_is_open[endpt]) { 366 printf("ugenclose: not open\n"); 367 return (EINVAL); 368 } 369 #endif 370 371 if (endpt == USB_CONTROL_ENDPOINT) { 372 DPRINTFN(5, ("ugenclose: close control\n")); 373 sc->sc_is_open[endpt] = 0; 374 return (0); 375 } 376 377 for (dir = OUT; dir <= IN; dir++) { 378 if (!(flag & (dir == OUT ? FWRITE : FREAD))) 379 continue; 380 sce = &sc->sc_endpoints[endpt][dir]; 381 if (sce == NULL || sce->pipeh == NULL) 382 continue; 383 DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n", 384 endpt, dir, sce)); 385 386 usbd_abort_pipe(sce->pipeh); 387 usbd_close_pipe(sce->pipeh); 388 sce->pipeh = NULL; 389 390 if (sce->ibuf != NULL) { 391 free(sce->ibuf, M_USBDEV); 392 sce->ibuf = NULL; 393 clfree(&sce->q); 394 395 } 396 } 397 sc->sc_is_open[endpt] = 0; 398 399 return (0); 400 } 401 402 Static int 403 ugen_do_read(struct ugen_softc *sc, int endpt, struct uio *uio, int flag) 404 { 405 struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN]; 406 u_int32_t n, tn; 407 char buf[UGEN_BBSIZE]; 408 usbd_xfer_handle xfer; 409 usbd_status err; 410 int s; 411 int error = 0; 412 u_char buffer[UGEN_CHUNK]; 413 414 #ifdef __NetBSD__ 415 DPRINTFN(5, ("ugenread: %d:%d\n", sc->sc_dev.dv_unit, endpt)); 416 #endif 417 418 if (sc->sc_dying) 419 return (EIO); 420 421 if (endpt == USB_CONTROL_ENDPOINT) 422 return (ENODEV); 423 424 #ifdef DIAGNOSTIC 425 if (sce->edesc == NULL) { 426 printf("ugenread: no edesc\n"); 427 return (EIO); 428 } 429 if (sce->pipeh == NULL) { 430 printf("ugenread: no pipe\n"); 431 return (EIO); 432 } 433 #endif 434 435 switch (sce->edesc->bmAttributes & UE_XFERTYPE) { 436 case UE_INTERRUPT: 437 /* Block until activity occured. */ 438 s = splusb(); 439 while (sce->q.c_cc == 0) { 440 if (flag & IO_NDELAY) { 441 splx(s); 442 return (EWOULDBLOCK); 443 } 444 sce->state |= UGEN_ASLP; 445 DPRINTFN(5, ("ugenread: sleep on %p\n", sc)); 446 error = tsleep(sce, PZERO | PCATCH, "ugenri", 0); 447 DPRINTFN(5, ("ugenread: woke, error=%d\n", error)); 448 if (sc->sc_dying) 449 error = EIO; 450 if (error) { 451 sce->state &= ~UGEN_ASLP; 452 break; 453 } 454 } 455 splx(s); 456 457 /* Transfer as many chunks as possible. */ 458 while (sce->q.c_cc > 0 && uio->uio_resid > 0 && !error) { 459 n = min(sce->q.c_cc, uio->uio_resid); 460 if (n > sizeof(buffer)) 461 n = sizeof(buffer); 462 463 /* Remove a small chunk from the input queue. */ 464 q_to_b(&sce->q, buffer, n); 465 DPRINTFN(5, ("ugenread: got %d chars\n", n)); 466 467 /* Copy the data to the user process. */ 468 error = uiomove(buffer, n, uio); 469 if (error) 470 break; 471 } 472 break; 473 case UE_BULK: 474 xfer = usbd_alloc_xfer(sc->sc_udev); 475 if (xfer == 0) 476 return (ENOMEM); 477 while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) { 478 DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n)); 479 tn = n; 480 err = usbd_bulk_transfer( 481 xfer, sce->pipeh, 482 sce->state & UGEN_SHORT_OK ? 483 USBD_SHORT_XFER_OK : 0, 484 sce->timeout, buf, &tn, "ugenrb"); 485 if (err) { 486 if (err == USBD_INTERRUPTED) 487 error = EINTR; 488 else if (err == USBD_TIMEOUT) 489 error = ETIMEDOUT; 490 else 491 error = EIO; 492 break; 493 } 494 DPRINTFN(1, ("ugenread: got %d bytes\n", tn)); 495 error = uiomove(buf, tn, uio); 496 if (error || tn < n) 497 break; 498 } 499 usbd_free_xfer(xfer); 500 break; 501 default: 502 return (ENXIO); 503 } 504 return (error); 505 } 506 507 int 508 ugenread(dev_t dev, struct uio *uio, int flag) 509 { 510 int endpt = UGENENDPOINT(dev); 511 struct ugen_softc *sc; 512 int error; 513 514 USB_GET_SC(ugen, UGENUNIT(dev), sc); 515 516 sc->sc_refcnt++; 517 error = ugen_do_read(sc, endpt, uio, flag); 518 if (--sc->sc_refcnt < 0) 519 usb_detach_wakeup(USBDEV(sc->sc_dev)); 520 return (error); 521 } 522 523 Static int 524 ugen_do_write(struct ugen_softc *sc, int endpt, struct uio *uio, int flag) 525 { 526 struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT]; 527 u_int32_t n; 528 int error = 0; 529 char buf[UGEN_BBSIZE]; 530 usbd_xfer_handle xfer; 531 usbd_status err; 532 533 DPRINTFN(5, ("%s: ugenwrite: %d\n", USBDEVNAME(sc->sc_dev), endpt)); 534 535 if (sc->sc_dying) 536 return (EIO); 537 538 if (endpt == USB_CONTROL_ENDPOINT) 539 return (ENODEV); 540 541 #ifdef DIAGNOSTIC 542 if (sce->edesc == NULL) { 543 printf("ugenwrite: no edesc\n"); 544 return (EIO); 545 } 546 if (sce->pipeh == NULL) { 547 printf("ugenwrite: no pipe\n"); 548 return (EIO); 549 } 550 #endif 551 552 switch (sce->edesc->bmAttributes & UE_XFERTYPE) { 553 case UE_BULK: 554 xfer = usbd_alloc_xfer(sc->sc_udev); 555 if (xfer == 0) 556 return (EIO); 557 while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) { 558 error = uiomove(buf, n, uio); 559 if (error) 560 break; 561 DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n)); 562 err = usbd_bulk_transfer(xfer, sce->pipeh, 0, 563 sce->timeout, buf, &n,"ugenwb"); 564 if (err) { 565 if (err == USBD_INTERRUPTED) 566 error = EINTR; 567 else if (err == USBD_TIMEOUT) 568 error = ETIMEDOUT; 569 else 570 error = EIO; 571 break; 572 } 573 } 574 usbd_free_xfer(xfer); 575 break; 576 default: 577 return (ENXIO); 578 } 579 return (error); 580 } 581 582 int 583 ugenwrite(dev_t dev, struct uio *uio, int flag) 584 { 585 int endpt = UGENENDPOINT(dev); 586 struct ugen_softc *sc; 587 int error; 588 589 USB_GET_SC(ugen, UGENUNIT(dev), sc); 590 591 sc->sc_refcnt++; 592 error = ugen_do_write(sc, endpt, uio, flag); 593 if (--sc->sc_refcnt < 0) 594 usb_detach_wakeup(USBDEV(sc->sc_dev)); 595 return (error); 596 } 597 598 #if defined(__NetBSD__) || defined(__OpenBSD__) 599 int 600 ugen_activate(device_ptr_t self, enum devact act) 601 { 602 struct ugen_softc *sc = (struct ugen_softc *)self; 603 604 switch (act) { 605 case DVACT_ACTIVATE: 606 return (EOPNOTSUPP); 607 break; 608 609 case DVACT_DEACTIVATE: 610 sc->sc_dying = 1; 611 break; 612 } 613 return (0); 614 } 615 #endif 616 617 USB_DETACH(ugen) 618 { 619 USB_DETACH_START(ugen, sc); 620 struct ugen_endpoint *sce; 621 int i, dir; 622 int s; 623 #if defined(__NetBSD__) || defined(__OpenBSD__) 624 int maj, mn; 625 626 DPRINTF(("ugen_detach: sc=%p flags=%d\n", sc, flags)); 627 #elif defined(__FreeBSD__) 628 DPRINTF(("ugen_detach: sc=%p\n", sc)); 629 #endif 630 631 sc->sc_dying = 1; 632 /* Abort all pipes. Causes processes waiting for transfer to wake. */ 633 for (i = 0; i < USB_MAX_ENDPOINTS; i++) { 634 for (dir = OUT; dir <= IN; dir++) { 635 sce = &sc->sc_endpoints[i][dir]; 636 if (sce && sce->pipeh) 637 usbd_abort_pipe(sce->pipeh); 638 } 639 } 640 641 s = splusb(); 642 if (--sc->sc_refcnt >= 0) { 643 /* Wake everyone */ 644 for (i = 0; i < USB_MAX_ENDPOINTS; i++) 645 wakeup(&sc->sc_endpoints[i][IN]); 646 /* Wait for processes to go away. */ 647 usb_detach_wait(USBDEV(sc->sc_dev)); 648 } 649 splx(s); 650 651 #if defined(__NetBSD__) || defined(__OpenBSD__) 652 /* locate the major number */ 653 for (maj = 0; maj < nchrdev; maj++) 654 if (cdevsw[maj].d_open == ugenopen) 655 break; 656 657 /* Nuke the vnodes for any open instances (calls close). */ 658 mn = self->dv_unit * USB_MAX_ENDPOINTS; 659 vdevgone(maj, mn, mn + USB_MAX_ENDPOINTS - 1, VCHR); 660 #elif defined(__FreeBSD__) 661 /* XXX not implemented yet */ 662 #endif 663 664 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, 665 USBDEV(sc->sc_dev)); 666 667 return (0); 668 } 669 670 Static void 671 ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) 672 { 673 struct ugen_endpoint *sce = addr; 674 /*struct ugen_softc *sc = sce->sc;*/ 675 u_int32_t count; 676 u_char *ibuf; 677 678 if (status == USBD_CANCELLED) 679 return; 680 681 if (status != USBD_NORMAL_COMPLETION) { 682 DPRINTF(("ugenintr: status=%d\n", status)); 683 usbd_clear_endpoint_stall_async(sce->pipeh); 684 return; 685 } 686 687 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); 688 ibuf = sce->ibuf; 689 690 DPRINTFN(5, ("ugenintr: xfer=%p status=%d count=%d\n", 691 xfer, status, count)); 692 DPRINTFN(5, (" data = %02x %02x %02x\n", 693 ibuf[0], ibuf[1], ibuf[2])); 694 695 (void)b_to_q(ibuf, count, &sce->q); 696 697 if (sce->state & UGEN_ASLP) { 698 sce->state &= ~UGEN_ASLP; 699 DPRINTFN(5, ("ugen_intr: waking %p\n", sce)); 700 wakeup(sce); 701 } 702 selwakeup(&sce->rsel); 703 } 704 705 Static usbd_status 706 ugen_set_interface(struct ugen_softc *sc, int ifaceidx, int altno) 707 { 708 usbd_interface_handle iface; 709 usb_endpoint_descriptor_t *ed; 710 usbd_status err; 711 struct ugen_endpoint *sce; 712 u_int8_t niface, nendpt, endptno, endpt; 713 int dir; 714 715 DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno)); 716 717 err = usbd_interface_count(sc->sc_udev, &niface); 718 if (err) 719 return (err); 720 if (ifaceidx < 0 || ifaceidx >= niface) 721 return (USBD_INVAL); 722 723 err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface); 724 if (err) 725 return (err); 726 err = usbd_endpoint_count(iface, &nendpt); 727 if (err) 728 return (err); 729 /* XXX should only do this after setting new altno has succeeded */ 730 for (endptno = 0; endptno < nendpt; endptno++) { 731 ed = usbd_interface2endpoint_descriptor(iface,endptno); 732 endpt = ed->bEndpointAddress; 733 dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT; 734 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir]; 735 sce->sc = 0; 736 sce->edesc = 0; 737 sce->iface = 0; 738 } 739 740 /* change setting */ 741 err = usbd_set_interface(iface, altno); 742 if (err) 743 return (err); 744 745 err = usbd_endpoint_count(iface, &nendpt); 746 if (err) 747 return (err); 748 for (endptno = 0; endptno < nendpt; endptno++) { 749 ed = usbd_interface2endpoint_descriptor(iface,endptno); 750 endpt = ed->bEndpointAddress; 751 dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT; 752 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir]; 753 sce->sc = sc; 754 sce->edesc = ed; 755 sce->iface = iface; 756 } 757 return (0); 758 } 759 760 /* Retrieve a complete descriptor for a certain device and index. */ 761 Static usb_config_descriptor_t * 762 ugen_get_cdesc(struct ugen_softc *sc, int index, int *lenp) 763 { 764 usb_config_descriptor_t *cdesc, *tdesc, cdescr; 765 int len; 766 usbd_status err; 767 768 if (index == USB_CURRENT_CONFIG_INDEX) { 769 tdesc = usbd_get_config_descriptor(sc->sc_udev); 770 len = UGETW(tdesc->wTotalLength); 771 if (lenp) 772 *lenp = len; 773 cdesc = malloc(len, M_TEMP, M_WAITOK); 774 memcpy(cdesc, tdesc, len); 775 DPRINTFN(5,("ugen_get_cdesc: current, len=%d\n", len)); 776 } else { 777 err = usbd_get_config_desc(sc->sc_udev, index, &cdescr); 778 if (err) 779 return (0); 780 len = UGETW(cdescr.wTotalLength); 781 DPRINTFN(5,("ugen_get_cdesc: index=%d, len=%d\n", index, len)); 782 if (lenp) 783 *lenp = len; 784 cdesc = malloc(len, M_TEMP, M_WAITOK); 785 err = usbd_get_config_desc_full(sc->sc_udev, index, cdesc,len); 786 if (err) { 787 free(cdesc, M_TEMP); 788 return (0); 789 } 790 } 791 return (cdesc); 792 } 793 794 Static int 795 ugen_get_alt_index(struct ugen_softc *sc, int ifaceidx) 796 { 797 usbd_interface_handle iface; 798 usbd_status err; 799 800 err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface); 801 if (err) 802 return (-1); 803 return (usbd_get_interface_altindex(iface)); 804 } 805 806 Static int 807 ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd, 808 caddr_t addr, int flag, struct proc *p) 809 { 810 struct ugen_endpoint *sce; 811 usbd_status err; 812 usbd_interface_handle iface; 813 struct usb_config_desc *cd; 814 usb_config_descriptor_t *cdesc; 815 struct usb_interface_desc *id; 816 usb_interface_descriptor_t *idesc; 817 struct usb_endpoint_desc *ed; 818 usb_endpoint_descriptor_t *edesc; 819 struct usb_alt_interface *ai; 820 struct usb_string_desc *si; 821 u_int8_t conf, alt; 822 823 DPRINTFN(5, ("ugenioctl: cmd=%08lx\n", cmd)); 824 if (sc->sc_dying) 825 return (EIO); 826 827 switch (cmd) { 828 case FIONBIO: 829 /* All handled in the upper FS layer. */ 830 return (0); 831 case USB_SET_SHORT_XFER: 832 /* This flag only affects read */ 833 if (endpt == USB_CONTROL_ENDPOINT) 834 return (EINVAL); 835 sce = &sc->sc_endpoints[endpt][IN]; 836 if (sce == NULL) 837 return (EINVAL); 838 #ifdef DIAGNOSTIC 839 if (sce->pipeh == NULL) { 840 printf("ugenioctl: USB_SET_SHORT_XFER, no pipe\n"); 841 return (EIO); 842 } 843 #endif 844 if (*(int *)addr) 845 sce->state |= UGEN_SHORT_OK; 846 else 847 sce->state &= ~UGEN_SHORT_OK; 848 return (0); 849 case USB_SET_TIMEOUT: 850 sce = &sc->sc_endpoints[endpt][IN]; 851 if (sce == NULL) 852 return (EINVAL); 853 #ifdef DIAGNOSTIC 854 if (sce->pipeh == NULL) { 855 printf("ugenioctl: USB_SET_TIMEOUT, no pipe\n"); 856 return (EIO); 857 } 858 #endif 859 sce->timeout = *(int *)addr; 860 return (0); 861 default: 862 break; 863 } 864 865 if (endpt != USB_CONTROL_ENDPOINT) 866 return (EINVAL); 867 868 switch (cmd) { 869 #ifdef UGEN_DEBUG 870 case USB_SETDEBUG: 871 ugendebug = *(int *)addr; 872 break; 873 #endif 874 case USB_GET_CONFIG: 875 err = usbd_get_config(sc->sc_udev, &conf); 876 if (err) 877 return (EIO); 878 *(int *)addr = conf; 879 break; 880 case USB_SET_CONFIG: 881 if (!(flag & FWRITE)) 882 return (EPERM); 883 err = ugen_set_config(sc, *(int *)addr); 884 if (err) 885 return (EIO); 886 break; 887 case USB_GET_ALTINTERFACE: 888 ai = (struct usb_alt_interface *)addr; 889 err = usbd_device2interface_handle(sc->sc_udev, 890 ai->interface_index, &iface); 891 if (err) 892 return (EINVAL); 893 idesc = usbd_get_interface_descriptor(iface); 894 if (idesc == NULL) 895 return (EIO); 896 ai->alt_no = idesc->bAlternateSetting; 897 break; 898 case USB_SET_ALTINTERFACE: 899 if (!(flag & FWRITE)) 900 return (EPERM); 901 ai = (struct usb_alt_interface *)addr; 902 err = usbd_device2interface_handle(sc->sc_udev, 903 ai->interface_index, &iface); 904 if (err) 905 return (EINVAL); 906 err = ugen_set_interface(sc, ai->interface_index, ai->alt_no); 907 if (err) 908 return (EINVAL); 909 break; 910 case USB_GET_NO_ALT: 911 ai = (struct usb_alt_interface *)addr; 912 cdesc = ugen_get_cdesc(sc, ai->config_index, 0); 913 if (cdesc == NULL) 914 return (EINVAL); 915 idesc = usbd_find_idesc(cdesc, ai->interface_index, 0); 916 if (idesc == NULL) { 917 free(cdesc, M_TEMP); 918 return (EINVAL); 919 } 920 ai->alt_no = usbd_get_no_alts(cdesc, idesc->bInterfaceNumber); 921 free(cdesc, M_TEMP); 922 break; 923 case USB_GET_DEVICE_DESC: 924 *(usb_device_descriptor_t *)addr = 925 *usbd_get_device_descriptor(sc->sc_udev); 926 break; 927 case USB_GET_CONFIG_DESC: 928 cd = (struct usb_config_desc *)addr; 929 cdesc = ugen_get_cdesc(sc, cd->config_index, 0); 930 if (cdesc == NULL) 931 return (EINVAL); 932 cd->desc = *cdesc; 933 free(cdesc, M_TEMP); 934 break; 935 case USB_GET_INTERFACE_DESC: 936 id = (struct usb_interface_desc *)addr; 937 cdesc = ugen_get_cdesc(sc, id->config_index, 0); 938 if (cdesc == NULL) 939 return (EINVAL); 940 if (id->config_index == USB_CURRENT_CONFIG_INDEX && 941 id->alt_index == USB_CURRENT_ALT_INDEX) 942 alt = ugen_get_alt_index(sc, id->interface_index); 943 else 944 alt = id->alt_index; 945 idesc = usbd_find_idesc(cdesc, id->interface_index, alt); 946 if (idesc == NULL) { 947 free(cdesc, M_TEMP); 948 return (EINVAL); 949 } 950 id->desc = *idesc; 951 free(cdesc, M_TEMP); 952 break; 953 case USB_GET_ENDPOINT_DESC: 954 ed = (struct usb_endpoint_desc *)addr; 955 cdesc = ugen_get_cdesc(sc, ed->config_index, 0); 956 if (cdesc == NULL) 957 return (EINVAL); 958 if (ed->config_index == USB_CURRENT_CONFIG_INDEX && 959 ed->alt_index == USB_CURRENT_ALT_INDEX) 960 alt = ugen_get_alt_index(sc, ed->interface_index); 961 else 962 alt = ed->alt_index; 963 edesc = usbd_find_edesc(cdesc, ed->interface_index, 964 alt, ed->endpoint_index); 965 if (edesc == NULL) { 966 free(cdesc, M_TEMP); 967 return (EINVAL); 968 } 969 ed->desc = *edesc; 970 free(cdesc, M_TEMP); 971 break; 972 case USB_GET_FULL_DESC: 973 { 974 int len; 975 struct iovec iov; 976 struct uio uio; 977 struct usb_full_desc *fd = (struct usb_full_desc *)addr; 978 int error; 979 980 cdesc = ugen_get_cdesc(sc, fd->config_index, &len); 981 if (len > fd->size) 982 len = fd->size; 983 iov.iov_base = (caddr_t)fd->data; 984 iov.iov_len = len; 985 uio.uio_iov = &iov; 986 uio.uio_iovcnt = 1; 987 uio.uio_resid = len; 988 uio.uio_offset = 0; 989 uio.uio_segflg = UIO_USERSPACE; 990 uio.uio_rw = UIO_READ; 991 uio.uio_procp = p; 992 error = uiomove((void *)cdesc, len, &uio); 993 free(cdesc, M_TEMP); 994 return (error); 995 } 996 case USB_GET_STRING_DESC: 997 si = (struct usb_string_desc *)addr; 998 err = usbd_get_string_desc(sc->sc_udev, si->string_index, 999 si->language_id, &si->desc); 1000 if (err) 1001 return (EINVAL); 1002 break; 1003 case USB_DO_REQUEST: 1004 { 1005 struct usb_ctl_request *ur = (void *)addr; 1006 int len = UGETW(ur->request.wLength); 1007 struct iovec iov; 1008 struct uio uio; 1009 void *ptr = 0; 1010 usbd_status err; 1011 int error = 0; 1012 1013 if (!(flag & FWRITE)) 1014 return (EPERM); 1015 /* Avoid requests that would damage the bus integrity. */ 1016 if ((ur->request.bmRequestType == UT_WRITE_DEVICE && 1017 ur->request.bRequest == UR_SET_ADDRESS) || 1018 (ur->request.bmRequestType == UT_WRITE_DEVICE && 1019 ur->request.bRequest == UR_SET_CONFIG) || 1020 (ur->request.bmRequestType == UT_WRITE_INTERFACE && 1021 ur->request.bRequest == UR_SET_INTERFACE)) 1022 return (EINVAL); 1023 1024 if (len < 0 || len > 32767) 1025 return (EINVAL); 1026 if (len != 0) { 1027 iov.iov_base = (caddr_t)ur->data; 1028 iov.iov_len = len; 1029 uio.uio_iov = &iov; 1030 uio.uio_iovcnt = 1; 1031 uio.uio_resid = len; 1032 uio.uio_offset = 0; 1033 uio.uio_segflg = UIO_USERSPACE; 1034 uio.uio_rw = 1035 ur->request.bmRequestType & UT_READ ? 1036 UIO_READ : UIO_WRITE; 1037 uio.uio_procp = p; 1038 ptr = malloc(len, M_TEMP, M_WAITOK); 1039 if (uio.uio_rw == UIO_WRITE) { 1040 error = uiomove(ptr, len, &uio); 1041 if (error) 1042 goto ret; 1043 } 1044 } 1045 err = usbd_do_request_flags(sc->sc_udev, &ur->request, 1046 ptr, ur->flags, &ur->actlen); 1047 if (err) { 1048 error = EIO; 1049 goto ret; 1050 } 1051 if (len != 0) { 1052 if (uio.uio_rw == UIO_READ) { 1053 error = uiomove(ptr, len, &uio); 1054 if (error) 1055 goto ret; 1056 } 1057 } 1058 ret: 1059 if (ptr) 1060 free(ptr, M_TEMP); 1061 return (error); 1062 } 1063 case USB_GET_DEVICEINFO: 1064 usbd_fill_deviceinfo(sc->sc_udev, 1065 (struct usb_device_info *)addr); 1066 break; 1067 default: 1068 return (EINVAL); 1069 } 1070 return (0); 1071 } 1072 1073 int 1074 ugenioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) 1075 { 1076 int endpt = UGENENDPOINT(dev); 1077 struct ugen_softc *sc; 1078 int error; 1079 1080 USB_GET_SC(ugen, UGENUNIT(dev), sc); 1081 1082 sc->sc_refcnt++; 1083 error = ugen_do_ioctl(sc, endpt, cmd, addr, flag, p); 1084 if (--sc->sc_refcnt < 0) 1085 usb_detach_wakeup(USBDEV(sc->sc_dev)); 1086 return (error); 1087 } 1088 1089 int 1090 ugenpoll(dev_t dev, int events, struct proc *p) 1091 { 1092 struct ugen_softc *sc; 1093 struct ugen_endpoint *sce; 1094 int revents = 0; 1095 int s; 1096 1097 USB_GET_SC(ugen, UGENUNIT(dev), sc); 1098 1099 if (sc->sc_dying) 1100 return (EIO); 1101 1102 /* XXX always IN */ 1103 sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN]; 1104 if (sce == NULL) 1105 return (EINVAL); 1106 #ifdef DIAGNOSTIC 1107 if (!sce->edesc) { 1108 printf("ugenpoll: no edesc\n"); 1109 return (EIO); 1110 } 1111 if (!sce->pipeh) { 1112 printf("ugenpoll: no pipe\n"); 1113 return (EIO); 1114 } 1115 #endif 1116 s = splusb(); 1117 switch (sce->edesc->bmAttributes & UE_XFERTYPE) { 1118 case UE_INTERRUPT: 1119 if (events & (POLLIN | POLLRDNORM)) { 1120 if (sce->q.c_cc > 0) 1121 revents |= events & (POLLIN | POLLRDNORM); 1122 else 1123 selrecord(p, &sce->rsel); 1124 } 1125 break; 1126 case UE_BULK: 1127 /* 1128 * We have no easy way of determining if a read will 1129 * yield any data or a write will happen. 1130 * Pretend they will. 1131 */ 1132 revents |= events & 1133 (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM); 1134 break; 1135 default: 1136 break; 1137 } 1138 splx(s); 1139 return (revents); 1140 } 1141 1142 #if defined(__FreeBSD__) 1143 DRIVER_MODULE(ugen, uhub, ugen_driver, ugen_devclass, usbd_driver_load, 0); 1144 #endif 1145