1 /* $NetBSD: ucom.c,v 1.74 2007/12/30 21:49:47 smb Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 2000 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) at 9 * Carlstedt Research & Technology. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 /* 40 * This code is very heavily based on the 16550 driver, com.c. 41 */ 42 43 #include <sys/cdefs.h> 44 __KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.74 2007/12/30 21:49:47 smb Exp $"); 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/kernel.h> 49 #include <sys/ioctl.h> 50 #include <sys/conf.h> 51 #include <sys/tty.h> 52 #include <sys/file.h> 53 #include <sys/select.h> 54 #include <sys/proc.h> 55 #include <sys/vnode.h> 56 #include <sys/device.h> 57 #include <sys/poll.h> 58 #include <sys/kauth.h> 59 #if defined(__NetBSD__) 60 #include "rnd.h" 61 #if NRND > 0 62 #include <sys/rnd.h> 63 #endif 64 #endif 65 66 #include <dev/usb/usb.h> 67 68 #include <dev/usb/usbdi.h> 69 #include <dev/usb/usbdi_util.h> 70 #include <dev/usb/usbdevs.h> 71 #include <dev/usb/usb_quirks.h> 72 73 #include <dev/usb/ucomvar.h> 74 75 #include "ucom.h" 76 77 #include "locators.h" 78 79 #if NUCOM > 0 80 81 #ifdef UCOM_DEBUG 82 #define DPRINTFN(n, x) if (ucomdebug > (n)) logprintf x 83 int ucomdebug = 0; 84 #else 85 #define DPRINTFN(n, x) 86 #endif 87 #define DPRINTF(x) DPRINTFN(0, x) 88 89 #define UCOMUNIT_MASK 0x3ffff 90 #define UCOMDIALOUT_MASK 0x80000 91 #define UCOMCALLUNIT_MASK 0x40000 92 93 #define UCOMUNIT(x) (minor(x) & UCOMUNIT_MASK) 94 #define UCOMDIALOUT(x) (minor(x) & UCOMDIALOUT_MASK) 95 #define UCOMCALLUNIT(x) (minor(x) & UCOMCALLUNIT_MASK) 96 97 struct ucom_softc { 98 USBBASEDEVICE sc_dev; /* base device */ 99 100 usbd_device_handle sc_udev; /* USB device */ 101 102 usbd_interface_handle sc_iface; /* data interface */ 103 104 int sc_bulkin_no; /* bulk in endpoint address */ 105 usbd_pipe_handle sc_bulkin_pipe; /* bulk in pipe */ 106 usbd_xfer_handle sc_ixfer; /* read request */ 107 u_char *sc_ibuf; /* read buffer */ 108 u_int sc_ibufsize; /* read buffer size */ 109 u_int sc_ibufsizepad; /* read buffer size padded */ 110 111 int sc_bulkout_no; /* bulk out endpoint address */ 112 usbd_pipe_handle sc_bulkout_pipe;/* bulk out pipe */ 113 usbd_xfer_handle sc_oxfer; /* write request */ 114 u_char *sc_obuf; /* write buffer */ 115 u_int sc_obufsize; /* write buffer size */ 116 u_int sc_opkthdrlen; /* header length of 117 * output packet */ 118 119 struct ucom_methods *sc_methods; 120 void *sc_parent; 121 int sc_portno; 122 123 struct tty *sc_tty; /* our tty */ 124 u_char sc_lsr; 125 u_char sc_msr; 126 u_char sc_mcr; 127 u_char sc_tx_stopped; 128 int sc_swflags; 129 130 u_char sc_opening; /* lock during open */ 131 int sc_refcnt; 132 u_char sc_dying; /* disconnecting */ 133 134 #if defined(__NetBSD__) && NRND > 0 135 rndsource_element_t sc_rndsource; /* random source */ 136 #endif 137 }; 138 139 dev_type_open(ucomopen); 140 dev_type_close(ucomclose); 141 dev_type_read(ucomread); 142 dev_type_write(ucomwrite); 143 dev_type_ioctl(ucomioctl); 144 dev_type_stop(ucomstop); 145 dev_type_tty(ucomtty); 146 dev_type_poll(ucompoll); 147 148 const struct cdevsw ucom_cdevsw = { 149 ucomopen, ucomclose, ucomread, ucomwrite, ucomioctl, 150 ucomstop, ucomtty, ucompoll, nommap, ttykqfilter, D_TTY 151 }; 152 153 Static void ucom_cleanup(struct ucom_softc *); 154 Static void ucom_hwiflow(struct ucom_softc *); 155 Static int ucomparam(struct tty *, struct termios *); 156 Static void ucomstart(struct tty *); 157 Static void ucom_shutdown(struct ucom_softc *); 158 Static int ucom_do_ioctl(struct ucom_softc *, u_long, void *, 159 int, struct lwp *); 160 Static void ucom_dtr(struct ucom_softc *, int); 161 Static void ucom_rts(struct ucom_softc *, int); 162 Static void ucom_break(struct ucom_softc *, int); 163 Static usbd_status ucomstartread(struct ucom_softc *); 164 Static void ucomreadcb(usbd_xfer_handle, usbd_private_handle, usbd_status); 165 Static void ucomwritecb(usbd_xfer_handle, usbd_private_handle, usbd_status); 166 Static void tiocm_to_ucom(struct ucom_softc *, u_long, int); 167 Static int ucom_to_tiocm(struct ucom_softc *); 168 169 USB_DECLARE_DRIVER(ucom); 170 171 USB_MATCH(ucom) 172 { 173 return (1); 174 } 175 176 USB_ATTACH(ucom) 177 { 178 struct ucom_softc *sc = (struct ucom_softc *)self; 179 struct ucom_attach_args *uca = aux; 180 struct tty *tp; 181 182 if (uca->info != NULL) 183 printf(": %s", uca->info); 184 printf("\n"); 185 186 sc->sc_udev = uca->device; 187 sc->sc_iface = uca->iface; 188 sc->sc_bulkout_no = uca->bulkout; 189 sc->sc_bulkin_no = uca->bulkin; 190 sc->sc_ibufsize = uca->ibufsize; 191 sc->sc_ibufsizepad = uca->ibufsizepad; 192 sc->sc_obufsize = uca->obufsize; 193 sc->sc_opkthdrlen = uca->opkthdrlen; 194 sc->sc_methods = uca->methods; 195 sc->sc_parent = uca->arg; 196 sc->sc_portno = uca->portno; 197 198 tp = ttymalloc(); 199 tp->t_oproc = ucomstart; 200 tp->t_param = ucomparam; 201 sc->sc_tty = tp; 202 203 DPRINTF(("ucom_attach: tty_attach %p\n", tp)); 204 tty_attach(tp); 205 206 #if defined(__NetBSD__) && NRND > 0 207 rnd_attach_source(&sc->sc_rndsource, USBDEVNAME(sc->sc_dev), 208 RND_TYPE_TTY, 0); 209 #endif 210 211 if (!pmf_device_register(self, NULL, NULL)) 212 aprint_error_dev(self, "couldn't establish power handler\n"); 213 USB_ATTACH_SUCCESS_RETURN; 214 } 215 216 USB_DETACH(ucom) 217 { 218 struct ucom_softc *sc = (struct ucom_softc *)self; 219 struct tty *tp = sc->sc_tty; 220 int maj, mn; 221 int s; 222 223 DPRINTF(("ucom_detach: sc=%p flags=%d tp=%p, pipe=%d,%d\n", 224 sc, flags, tp, sc->sc_bulkin_no, sc->sc_bulkout_no)); 225 226 sc->sc_dying = 1; 227 pmf_device_deregister(self); 228 229 if (sc->sc_bulkin_pipe != NULL) 230 usbd_abort_pipe(sc->sc_bulkin_pipe); 231 if (sc->sc_bulkout_pipe != NULL) 232 usbd_abort_pipe(sc->sc_bulkout_pipe); 233 234 s = splusb(); 235 if (--sc->sc_refcnt >= 0) { 236 /* Wake up anyone waiting */ 237 if (tp != NULL) { 238 mutex_spin_enter(&tty_lock); 239 CLR(tp->t_state, TS_CARR_ON); 240 CLR(tp->t_cflag, CLOCAL | MDMBUF); 241 ttyflush(tp, FREAD|FWRITE); 242 mutex_spin_exit(&tty_lock); 243 } 244 /* Wait for processes to go away. */ 245 usb_detach_wait(USBDEV(sc->sc_dev)); 246 } 247 splx(s); 248 249 /* locate the major number */ 250 maj = cdevsw_lookup_major(&ucom_cdevsw); 251 252 /* Nuke the vnodes for any open instances. */ 253 mn = device_unit(self); 254 DPRINTF(("ucom_detach: maj=%d mn=%d\n", maj, mn)); 255 vdevgone(maj, mn, mn, VCHR); 256 vdevgone(maj, mn | UCOMDIALOUT_MASK, mn | UCOMDIALOUT_MASK, VCHR); 257 vdevgone(maj, mn | UCOMCALLUNIT_MASK, mn | UCOMCALLUNIT_MASK, VCHR); 258 259 /* Detach and free the tty. */ 260 if (tp != NULL) { 261 tty_detach(tp); 262 ttyfree(tp); 263 sc->sc_tty = NULL; 264 } 265 266 /* Detach the random source */ 267 #if defined(__NetBSD__) && NRND > 0 268 rnd_detach_source(&sc->sc_rndsource); 269 #endif 270 271 return (0); 272 } 273 274 int 275 ucom_activate(device_ptr_t self, enum devact act) 276 { 277 struct ucom_softc *sc = (struct ucom_softc *)self; 278 279 DPRINTFN(5,("ucom_activate: %d\n", act)); 280 281 switch (act) { 282 case DVACT_ACTIVATE: 283 return (EOPNOTSUPP); 284 285 case DVACT_DEACTIVATE: 286 sc->sc_dying = 1; 287 break; 288 } 289 return (0); 290 } 291 292 void 293 ucom_shutdown(struct ucom_softc *sc) 294 { 295 struct tty *tp = sc->sc_tty; 296 297 DPRINTF(("ucom_shutdown\n")); 298 /* 299 * Hang up if necessary. Wait a bit, so the other side has time to 300 * notice even if we immediately open the port again. 301 */ 302 if (ISSET(tp->t_cflag, HUPCL)) { 303 ucom_dtr(sc, 0); 304 (void)tsleep(sc, TTIPRI, ttclos, hz); 305 } 306 } 307 308 int 309 ucomopen(dev_t dev, int flag, int mode, struct lwp *l) 310 { 311 int unit = UCOMUNIT(dev); 312 usbd_status err; 313 struct ucom_softc *sc; 314 struct tty *tp; 315 int s; 316 int error; 317 318 if (unit >= ucom_cd.cd_ndevs) 319 return (ENXIO); 320 sc = ucom_cd.cd_devs[unit]; 321 if (sc == NULL) 322 return (ENXIO); 323 324 if (sc->sc_dying) 325 return (EIO); 326 327 if (!device_is_active(&sc->sc_dev)) 328 return (ENXIO); 329 330 tp = sc->sc_tty; 331 332 DPRINTF(("ucomopen: unit=%d, tp=%p\n", unit, tp)); 333 334 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 335 return (EBUSY); 336 337 s = spltty(); 338 339 /* 340 * Do the following iff this is a first open. 341 */ 342 while (sc->sc_opening) 343 tsleep(&sc->sc_opening, PRIBIO, "ucomop", 0); 344 345 if (sc->sc_dying) { 346 splx(s); 347 return (EIO); 348 } 349 sc->sc_opening = 1; 350 351 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 352 struct termios t; 353 354 tp->t_dev = dev; 355 356 if (sc->sc_methods->ucom_open != NULL) { 357 error = sc->sc_methods->ucom_open(sc->sc_parent, 358 sc->sc_portno); 359 if (error) { 360 ucom_cleanup(sc); 361 sc->sc_opening = 0; 362 wakeup(&sc->sc_opening); 363 splx(s); 364 return (error); 365 } 366 } 367 368 ucom_status_change(sc); 369 370 /* 371 * Initialize the termios status to the defaults. Add in the 372 * sticky bits from TIOCSFLAGS. 373 */ 374 t.c_ispeed = 0; 375 t.c_ospeed = TTYDEF_SPEED; 376 t.c_cflag = TTYDEF_CFLAG; 377 if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) 378 SET(t.c_cflag, CLOCAL); 379 if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) 380 SET(t.c_cflag, CRTSCTS); 381 if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) 382 SET(t.c_cflag, MDMBUF); 383 /* Make sure ucomparam() will do something. */ 384 tp->t_ospeed = 0; 385 (void) ucomparam(tp, &t); 386 tp->t_iflag = TTYDEF_IFLAG; 387 tp->t_oflag = TTYDEF_OFLAG; 388 tp->t_lflag = TTYDEF_LFLAG; 389 ttychars(tp); 390 ttsetwater(tp); 391 392 /* 393 * Turn on DTR. We must always do this, even if carrier is not 394 * present, because otherwise we'd have to use TIOCSDTR 395 * immediately after setting CLOCAL, which applications do not 396 * expect. We always assert DTR while the device is open 397 * unless explicitly requested to deassert it. Ditto RTS. 398 */ 399 ucom_dtr(sc, 1); 400 ucom_rts(sc, 1); 401 402 /* XXX CLR(sc->sc_rx_flags, RX_ANY_BLOCK);*/ 403 ucom_hwiflow(sc); 404 405 DPRINTF(("ucomopen: open pipes in=%d out=%d\n", 406 sc->sc_bulkin_no, sc->sc_bulkout_no)); 407 408 /* Open the bulk pipes */ 409 err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, 0, 410 &sc->sc_bulkin_pipe); 411 if (err) { 412 DPRINTF(("%s: open bulk in error (addr %d), err=%s\n", 413 USBDEVNAME(sc->sc_dev), sc->sc_bulkin_no, 414 usbd_errstr(err))); 415 error = EIO; 416 goto fail_0; 417 } 418 err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no, 419 USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe); 420 if (err) { 421 DPRINTF(("%s: open bulk out error (addr %d), err=%s\n", 422 USBDEVNAME(sc->sc_dev), sc->sc_bulkout_no, 423 usbd_errstr(err))); 424 error = EIO; 425 goto fail_1; 426 } 427 428 /* Allocate a request and an input buffer and start reading. */ 429 sc->sc_ixfer = usbd_alloc_xfer(sc->sc_udev); 430 if (sc->sc_ixfer == NULL) { 431 error = ENOMEM; 432 goto fail_2; 433 } 434 435 sc->sc_ibuf = usbd_alloc_buffer(sc->sc_ixfer, 436 sc->sc_ibufsizepad); 437 if (sc->sc_ibuf == NULL) { 438 error = ENOMEM; 439 goto fail_3; 440 } 441 442 sc->sc_oxfer = usbd_alloc_xfer(sc->sc_udev); 443 if (sc->sc_oxfer == NULL) { 444 error = ENOMEM; 445 goto fail_3; 446 } 447 448 sc->sc_obuf = usbd_alloc_buffer(sc->sc_oxfer, 449 sc->sc_obufsize + 450 sc->sc_opkthdrlen); 451 if (sc->sc_obuf == NULL) { 452 error = ENOMEM; 453 goto fail_4; 454 } 455 456 ucomstartread(sc); 457 } 458 sc->sc_opening = 0; 459 wakeup(&sc->sc_opening); 460 splx(s); 461 462 error = ttyopen(tp, UCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK)); 463 if (error) 464 goto bad; 465 466 error = (*tp->t_linesw->l_open)(dev, tp); 467 if (error) 468 goto bad; 469 470 return (0); 471 472 fail_4: 473 usbd_free_xfer(sc->sc_oxfer); 474 sc->sc_oxfer = NULL; 475 fail_3: 476 usbd_free_xfer(sc->sc_ixfer); 477 sc->sc_ixfer = NULL; 478 fail_2: 479 usbd_close_pipe(sc->sc_bulkout_pipe); 480 sc->sc_bulkout_pipe = NULL; 481 fail_1: 482 usbd_close_pipe(sc->sc_bulkin_pipe); 483 sc->sc_bulkin_pipe = NULL; 484 fail_0: 485 sc->sc_opening = 0; 486 wakeup(&sc->sc_opening); 487 splx(s); 488 return (error); 489 490 bad: 491 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 492 /* 493 * We failed to open the device, and nobody else had it opened. 494 * Clean up the state as appropriate. 495 */ 496 ucom_cleanup(sc); 497 } 498 499 return (error); 500 } 501 502 int 503 ucomclose(dev_t dev, int flag, int mode, struct lwp *l) 504 { 505 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; 506 struct tty *tp = sc->sc_tty; 507 508 DPRINTF(("ucomclose: unit=%d\n", UCOMUNIT(dev))); 509 if (!ISSET(tp->t_state, TS_ISOPEN)) 510 return (0); 511 512 sc->sc_refcnt++; 513 514 (*tp->t_linesw->l_close)(tp, flag); 515 ttyclose(tp); 516 517 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 518 /* 519 * Although we got a last close, the device may still be in 520 * use; e.g. if this was the dialout node, and there are still 521 * processes waiting for carrier on the non-dialout node. 522 */ 523 ucom_cleanup(sc); 524 } 525 526 if (sc->sc_methods->ucom_close != NULL) 527 sc->sc_methods->ucom_close(sc->sc_parent, sc->sc_portno); 528 529 if (--sc->sc_refcnt < 0) 530 usb_detach_wakeup(USBDEV(sc->sc_dev)); 531 532 return (0); 533 } 534 535 int 536 ucomread(dev_t dev, struct uio *uio, int flag) 537 { 538 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; 539 struct tty *tp = sc->sc_tty; 540 int error; 541 542 if (sc->sc_dying) 543 return (EIO); 544 545 sc->sc_refcnt++; 546 error = ((*tp->t_linesw->l_read)(tp, uio, flag)); 547 if (--sc->sc_refcnt < 0) 548 usb_detach_wakeup(USBDEV(sc->sc_dev)); 549 return (error); 550 } 551 552 int 553 ucomwrite(dev_t dev, struct uio *uio, int flag) 554 { 555 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; 556 struct tty *tp = sc->sc_tty; 557 int error; 558 559 if (sc->sc_dying) 560 return (EIO); 561 562 sc->sc_refcnt++; 563 error = ((*tp->t_linesw->l_write)(tp, uio, flag)); 564 if (--sc->sc_refcnt < 0) 565 usb_detach_wakeup(USBDEV(sc->sc_dev)); 566 return (error); 567 } 568 569 int 570 ucompoll(dev_t dev, int events, struct lwp *l) 571 { 572 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; 573 struct tty *tp = sc->sc_tty; 574 int revents; 575 576 if (sc->sc_dying) 577 return (POLLHUP); 578 579 sc->sc_refcnt++; 580 revents = ((*tp->t_linesw->l_poll)(tp, events, l)); 581 if (--sc->sc_refcnt < 0) 582 usb_detach_wakeup(USBDEV(sc->sc_dev)); 583 return (revents); 584 } 585 586 struct tty * 587 ucomtty(dev_t dev) 588 { 589 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; 590 struct tty *tp = sc->sc_tty; 591 592 return (tp); 593 } 594 595 int 596 ucomioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 597 { 598 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; 599 int error; 600 601 sc->sc_refcnt++; 602 error = ucom_do_ioctl(sc, cmd, data, flag, l); 603 if (--sc->sc_refcnt < 0) 604 usb_detach_wakeup(USBDEV(sc->sc_dev)); 605 return (error); 606 } 607 608 Static int 609 ucom_do_ioctl(struct ucom_softc *sc, u_long cmd, void *data, 610 int flag, struct lwp *l) 611 { 612 struct tty *tp = sc->sc_tty; 613 int error; 614 int s; 615 616 if (sc->sc_dying) 617 return (EIO); 618 619 DPRINTF(("ucomioctl: cmd=0x%08lx\n", cmd)); 620 621 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 622 if (error != EPASSTHROUGH) 623 return (error); 624 625 error = ttioctl(tp, cmd, data, flag, l); 626 if (error != EPASSTHROUGH) 627 return (error); 628 629 if (sc->sc_methods->ucom_ioctl != NULL) { 630 error = sc->sc_methods->ucom_ioctl(sc->sc_parent, 631 sc->sc_portno, cmd, data, flag, l->l_proc); 632 if (error != EPASSTHROUGH) 633 return (error); 634 } 635 636 error = 0; 637 638 DPRINTF(("ucomioctl: our cmd=0x%08lx\n", cmd)); 639 s = spltty(); 640 641 switch (cmd) { 642 case TIOCSBRK: 643 ucom_break(sc, 1); 644 break; 645 646 case TIOCCBRK: 647 ucom_break(sc, 0); 648 break; 649 650 case TIOCSDTR: 651 ucom_dtr(sc, 1); 652 break; 653 654 case TIOCCDTR: 655 ucom_dtr(sc, 0); 656 break; 657 658 case TIOCGFLAGS: 659 *(int *)data = sc->sc_swflags; 660 break; 661 662 case TIOCSFLAGS: 663 error = kauth_authorize_device_tty(l->l_cred, 664 KAUTH_DEVICE_TTY_PRIVSET, tp); 665 if (error) 666 break; 667 sc->sc_swflags = *(int *)data; 668 break; 669 670 case TIOCMSET: 671 case TIOCMBIS: 672 case TIOCMBIC: 673 tiocm_to_ucom(sc, cmd, *(int *)data); 674 break; 675 676 case TIOCMGET: 677 *(int *)data = ucom_to_tiocm(sc); 678 break; 679 680 default: 681 error = EPASSTHROUGH; 682 break; 683 } 684 685 splx(s); 686 687 return (error); 688 } 689 690 Static void 691 tiocm_to_ucom(struct ucom_softc *sc, u_long how, int ttybits) 692 { 693 u_char combits; 694 695 combits = 0; 696 if (ISSET(ttybits, TIOCM_DTR)) 697 SET(combits, UMCR_DTR); 698 if (ISSET(ttybits, TIOCM_RTS)) 699 SET(combits, UMCR_RTS); 700 701 switch (how) { 702 case TIOCMBIC: 703 CLR(sc->sc_mcr, combits); 704 break; 705 706 case TIOCMBIS: 707 SET(sc->sc_mcr, combits); 708 break; 709 710 case TIOCMSET: 711 CLR(sc->sc_mcr, UMCR_DTR | UMCR_RTS); 712 SET(sc->sc_mcr, combits); 713 break; 714 } 715 716 if (how == TIOCMSET || ISSET(combits, UMCR_DTR)) 717 ucom_dtr(sc, (sc->sc_mcr & UMCR_DTR) != 0); 718 if (how == TIOCMSET || ISSET(combits, UMCR_RTS)) 719 ucom_rts(sc, (sc->sc_mcr & UMCR_RTS) != 0); 720 } 721 722 Static int 723 ucom_to_tiocm(struct ucom_softc *sc) 724 { 725 u_char combits; 726 int ttybits = 0; 727 728 combits = sc->sc_mcr; 729 if (ISSET(combits, UMCR_DTR)) 730 SET(ttybits, TIOCM_DTR); 731 if (ISSET(combits, UMCR_RTS)) 732 SET(ttybits, TIOCM_RTS); 733 734 combits = sc->sc_msr; 735 if (ISSET(combits, UMSR_DCD)) 736 SET(ttybits, TIOCM_CD); 737 if (ISSET(combits, UMSR_CTS)) 738 SET(ttybits, TIOCM_CTS); 739 if (ISSET(combits, UMSR_DSR)) 740 SET(ttybits, TIOCM_DSR); 741 if (ISSET(combits, UMSR_RI | UMSR_TERI)) 742 SET(ttybits, TIOCM_RI); 743 744 #if 0 745 XXX; 746 if (sc->sc_ier != 0) 747 SET(ttybits, TIOCM_LE); 748 #endif 749 750 return (ttybits); 751 } 752 753 Static void 754 ucom_break(sc, onoff) 755 struct ucom_softc *sc; 756 int onoff; 757 { 758 DPRINTF(("ucom_break: onoff=%d\n", onoff)); 759 760 if (sc->sc_methods->ucom_set != NULL) 761 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, 762 UCOM_SET_BREAK, onoff); 763 } 764 765 Static void 766 ucom_dtr(struct ucom_softc *sc, int onoff) 767 { 768 DPRINTF(("ucom_dtr: onoff=%d\n", onoff)); 769 770 if (sc->sc_methods->ucom_set != NULL) 771 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, 772 UCOM_SET_DTR, onoff); 773 } 774 775 Static void 776 ucom_rts(struct ucom_softc *sc, int onoff) 777 { 778 DPRINTF(("ucom_rts: onoff=%d\n", onoff)); 779 780 if (sc->sc_methods->ucom_set != NULL) 781 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, 782 UCOM_SET_RTS, onoff); 783 } 784 785 void 786 ucom_status_change(struct ucom_softc *sc) 787 { 788 struct tty *tp = sc->sc_tty; 789 u_char old_msr; 790 791 if (sc->sc_methods->ucom_get_status != NULL) { 792 old_msr = sc->sc_msr; 793 sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno, 794 &sc->sc_lsr, &sc->sc_msr); 795 if (ISSET((sc->sc_msr ^ old_msr), UMSR_DCD)) 796 (*tp->t_linesw->l_modem)(tp, 797 ISSET(sc->sc_msr, UMSR_DCD)); 798 } else { 799 sc->sc_lsr = 0; 800 /* Assume DCD is present, if we have no chance to check it. */ 801 sc->sc_msr = UMSR_DCD; 802 } 803 } 804 805 Static int 806 ucomparam(struct tty *tp, struct termios *t) 807 { 808 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)]; 809 int error; 810 811 if (sc->sc_dying) 812 return (EIO); 813 814 /* Check requested parameters. */ 815 if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 816 return (EINVAL); 817 818 /* 819 * For the console, always force CLOCAL and !HUPCL, so that the port 820 * is always active. 821 */ 822 if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR)) { 823 SET(t->c_cflag, CLOCAL); 824 CLR(t->c_cflag, HUPCL); 825 } 826 827 /* 828 * If there were no changes, don't do anything. This avoids dropping 829 * input and improves performance when all we did was frob things like 830 * VMIN and VTIME. 831 */ 832 if (tp->t_ospeed == t->c_ospeed && 833 tp->t_cflag == t->c_cflag) 834 return (0); 835 836 /* XXX lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag); */ 837 838 /* And copy to tty. */ 839 tp->t_ispeed = 0; 840 tp->t_ospeed = t->c_ospeed; 841 tp->t_cflag = t->c_cflag; 842 843 if (sc->sc_methods->ucom_param != NULL) { 844 error = sc->sc_methods->ucom_param(sc->sc_parent, sc->sc_portno, 845 t); 846 if (error) 847 return (error); 848 } 849 850 /* XXX worry about CHWFLOW */ 851 852 /* 853 * Update the tty layer's idea of the carrier bit, in case we changed 854 * CLOCAL or MDMBUF. We don't hang up here; we only do that by 855 * explicit request. 856 */ 857 DPRINTF(("ucomparam: l_modem\n")); 858 (void) (*tp->t_linesw->l_modem)(tp, ISSET(sc->sc_msr, UMSR_DCD)); 859 860 #if 0 861 XXX what if the hardware is not open 862 if (!ISSET(t->c_cflag, CHWFLOW)) { 863 if (sc->sc_tx_stopped) { 864 sc->sc_tx_stopped = 0; 865 ucomstart(tp); 866 } 867 } 868 #endif 869 870 return (0); 871 } 872 873 /* 874 * (un)block input via hw flowcontrol 875 */ 876 Static void 877 ucom_hwiflow(struct ucom_softc *sc) 878 { 879 DPRINTF(("ucom_hwiflow:\n")); 880 #if 0 881 XXX 882 bus_space_tag_t iot = sc->sc_iot; 883 bus_space_handle_t ioh = sc->sc_ioh; 884 885 if (sc->sc_mcr_rts == 0) 886 return; 887 888 if (ISSET(sc->sc_rx_flags, RX_ANY_BLOCK)) { 889 CLR(sc->sc_mcr, sc->sc_mcr_rts); 890 CLR(sc->sc_mcr_active, sc->sc_mcr_rts); 891 } else { 892 SET(sc->sc_mcr, sc->sc_mcr_rts); 893 SET(sc->sc_mcr_active, sc->sc_mcr_rts); 894 } 895 bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr_active); 896 #endif 897 } 898 899 Static void 900 ucomstart(struct tty *tp) 901 { 902 struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)]; 903 usbd_status err; 904 int s; 905 u_char *data; 906 int cnt; 907 908 if (sc->sc_dying) 909 return; 910 911 s = spltty(); 912 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) { 913 DPRINTFN(4,("ucomstart: no go, state=0x%x\n", tp->t_state)); 914 goto out; 915 } 916 if (sc->sc_tx_stopped) 917 goto out; 918 919 if (!ttypull(tp)) 920 goto out; 921 922 /* Grab the first contiguous region of buffer space. */ 923 data = tp->t_outq.c_cf; 924 cnt = ndqb(&tp->t_outq, 0); 925 926 if (cnt == 0) { 927 DPRINTF(("ucomstart: cnt==0\n")); 928 goto out; 929 } 930 931 SET(tp->t_state, TS_BUSY); 932 933 if (cnt > sc->sc_obufsize) { 934 DPRINTF(("ucomstart: big buffer %d chars\n", cnt)); 935 cnt = sc->sc_obufsize; 936 } 937 if (sc->sc_methods->ucom_write != NULL) 938 sc->sc_methods->ucom_write(sc->sc_parent, sc->sc_portno, 939 sc->sc_obuf, data, &cnt); 940 else 941 memcpy(sc->sc_obuf, data, cnt); 942 943 DPRINTFN(4,("ucomstart: %d chars\n", cnt)); 944 usbd_setup_xfer(sc->sc_oxfer, sc->sc_bulkout_pipe, 945 (usbd_private_handle)sc, sc->sc_obuf, cnt, 946 USBD_NO_COPY, USBD_NO_TIMEOUT, ucomwritecb); 947 /* What can we do on error? */ 948 err = usbd_transfer(sc->sc_oxfer); 949 #ifdef DIAGNOSTIC 950 if (err != USBD_IN_PROGRESS) 951 printf("ucomstart: err=%s\n", usbd_errstr(err)); 952 #endif 953 954 out: 955 splx(s); 956 } 957 958 void 959 ucomstop(struct tty *tp, int flag) 960 { 961 DPRINTF(("ucomstop: flag=%d\n", flag)); 962 #if 0 963 /*struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)];*/ 964 int s; 965 966 s = spltty(); 967 if (ISSET(tp->t_state, TS_BUSY)) { 968 DPRINTF(("ucomstop: XXX\n")); 969 /* sc->sc_tx_stopped = 1; */ 970 if (!ISSET(tp->t_state, TS_TTSTOP)) 971 SET(tp->t_state, TS_FLUSH); 972 } 973 splx(s); 974 #endif 975 } 976 977 Static void 978 ucomwritecb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status) 979 { 980 struct ucom_softc *sc = (struct ucom_softc *)p; 981 struct tty *tp = sc->sc_tty; 982 u_int32_t cc; 983 int s; 984 985 DPRINTFN(5,("ucomwritecb: status=%d\n", status)); 986 987 if (status == USBD_CANCELLED || sc->sc_dying) 988 goto error; 989 990 if (status) { 991 DPRINTF(("ucomwritecb: status=%d\n", status)); 992 usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); 993 /* XXX we should restart after some delay. */ 994 goto error; 995 } 996 997 usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); 998 #if defined(__NetBSD__) && NRND > 0 999 rnd_add_uint32(&sc->sc_rndsource, cc); 1000 #endif 1001 DPRINTFN(5,("ucomwritecb: cc=%d\n", cc)); 1002 /* convert from USB bytes to tty bytes */ 1003 cc -= sc->sc_opkthdrlen; 1004 1005 s = spltty(); 1006 CLR(tp->t_state, TS_BUSY); 1007 if (ISSET(tp->t_state, TS_FLUSH)) 1008 CLR(tp->t_state, TS_FLUSH); 1009 else 1010 ndflush(&tp->t_outq, cc); 1011 (*tp->t_linesw->l_start)(tp); 1012 splx(s); 1013 return; 1014 1015 error: 1016 s = spltty(); 1017 CLR(tp->t_state, TS_BUSY); 1018 splx(s); 1019 } 1020 1021 Static usbd_status 1022 ucomstartread(struct ucom_softc *sc) 1023 { 1024 usbd_status err; 1025 1026 DPRINTFN(5,("ucomstartread: start\n")); 1027 usbd_setup_xfer(sc->sc_ixfer, sc->sc_bulkin_pipe, 1028 (usbd_private_handle)sc, 1029 sc->sc_ibuf, sc->sc_ibufsize, 1030 USBD_SHORT_XFER_OK | USBD_NO_COPY, 1031 USBD_NO_TIMEOUT, ucomreadcb); 1032 err = usbd_transfer(sc->sc_ixfer); 1033 if (err != USBD_IN_PROGRESS) { 1034 DPRINTF(("ucomstartread: err=%s\n", usbd_errstr(err))); 1035 return (err); 1036 } 1037 return (USBD_NORMAL_COMPLETION); 1038 } 1039 1040 Static void 1041 ucomreadcb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status) 1042 { 1043 struct ucom_softc *sc = (struct ucom_softc *)p; 1044 struct tty *tp = sc->sc_tty; 1045 int (*rint)(int, struct tty *) = tp->t_linesw->l_rint; 1046 usbd_status err; 1047 u_int32_t cc; 1048 u_char *cp; 1049 int s; 1050 1051 DPRINTFN(5,("ucomreadcb: status=%d\n", status)); 1052 1053 if (status == USBD_CANCELLED || status == USBD_IOERROR || 1054 sc->sc_dying) { 1055 DPRINTF(("ucomreadcb: dying\n")); 1056 /* Send something to wake upper layer */ 1057 s = spltty(); 1058 (*rint)('\n', tp); 1059 mutex_spin_enter(&tty_lock); /* XXX */ 1060 ttwakeup(tp); 1061 mutex_spin_exit(&tty_lock); /* XXX */ 1062 splx(s); 1063 return; 1064 } 1065 1066 if (status) { 1067 usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); 1068 /* XXX we should restart after some delay. */ 1069 return; 1070 } 1071 1072 usbd_get_xfer_status(xfer, NULL, (void *)&cp, &cc, NULL); 1073 #if defined(__NetBSD__) && NRND > 0 1074 rnd_add_uint32(&sc->sc_rndsource, cc); 1075 #endif 1076 DPRINTFN(5,("ucomreadcb: got %d chars, tp=%p\n", cc, tp)); 1077 if (sc->sc_methods->ucom_read != NULL) 1078 sc->sc_methods->ucom_read(sc->sc_parent, sc->sc_portno, 1079 &cp, &cc); 1080 1081 s = spltty(); 1082 /* Give characters to tty layer. */ 1083 while (cc-- > 0) { 1084 DPRINTFN(7,("ucomreadcb: char=0x%02x\n", *cp)); 1085 if ((*rint)(*cp++, tp) == -1) { 1086 /* XXX what should we do? */ 1087 printf("%s: lost %d chars\n", USBDEVNAME(sc->sc_dev), 1088 cc); 1089 break; 1090 } 1091 } 1092 splx(s); 1093 1094 err = ucomstartread(sc); 1095 if (err) { 1096 printf("%s: read start failed\n", USBDEVNAME(sc->sc_dev)); 1097 /* XXX what should we dow now? */ 1098 } 1099 } 1100 1101 Static void 1102 ucom_cleanup(struct ucom_softc *sc) 1103 { 1104 DPRINTF(("ucom_cleanup: closing pipes\n")); 1105 1106 ucom_shutdown(sc); 1107 if (sc->sc_bulkin_pipe != NULL) { 1108 usbd_abort_pipe(sc->sc_bulkin_pipe); 1109 usbd_close_pipe(sc->sc_bulkin_pipe); 1110 sc->sc_bulkin_pipe = NULL; 1111 } 1112 if (sc->sc_bulkout_pipe != NULL) { 1113 usbd_abort_pipe(sc->sc_bulkout_pipe); 1114 usbd_close_pipe(sc->sc_bulkout_pipe); 1115 sc->sc_bulkout_pipe = NULL; 1116 } 1117 if (sc->sc_ixfer != NULL) { 1118 usbd_free_xfer(sc->sc_ixfer); 1119 sc->sc_ixfer = NULL; 1120 } 1121 if (sc->sc_oxfer != NULL) { 1122 usbd_free_xfer(sc->sc_oxfer); 1123 sc->sc_oxfer = NULL; 1124 } 1125 } 1126 1127 #endif /* NUCOM > 0 */ 1128 1129 int 1130 ucomprint(void *aux, const char *pnp) 1131 { 1132 struct ucom_attach_args *uca = aux; 1133 1134 if (pnp) 1135 aprint_normal("ucom at %s", pnp); 1136 if (uca->portno != UCOM_UNK_PORTNO) 1137 aprint_normal(" portno %d", uca->portno); 1138 return (UNCONF); 1139 } 1140 1141 int 1142 ucomsubmatch(struct device *parent, struct cfdata *cf, 1143 const int *ldesc, void *aux) 1144 { 1145 struct ucom_attach_args *uca = aux; 1146 1147 if (uca->portno != UCOM_UNK_PORTNO && 1148 cf->cf_loc[UCOMBUSCF_PORTNO] != UCOMBUSCF_PORTNO_DEFAULT && 1149 cf->cf_loc[UCOMBUSCF_PORTNO] != uca->portno) 1150 return (0); 1151 return (config_match(parent, cf, aux)); 1152 } 1153