[BACK]Return to ucom.c CVS log [TXT][DIR] Up to [local] / sys / dev / usb

Annotation of sys/dev/usb/ucom.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: ucom.c,v 1.41 2007/06/14 10:11:15 mbalmer Exp $ */
                      2: /*     $NetBSD: ucom.c,v 1.49 2003/01/01 00:10:25 thorpej Exp $        */
                      3:
                      4: /*
                      5:  * Copyright (c) 1998, 2000 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:  * This code is very heavily based on the 16550 driver, com.c.
                     42:  */
                     43:
                     44: #include <sys/param.h>
                     45: #include <sys/systm.h>
                     46: #include <sys/kernel.h>
                     47: #include <sys/rwlock.h>
                     48: #include <sys/ioctl.h>
                     49: #include <sys/conf.h>
                     50: #include <sys/tty.h>
                     51: #include <sys/file.h>
                     52: #include <sys/selinfo.h>
                     53: #include <sys/proc.h>
                     54: #include <sys/vnode.h>
                     55: #include <sys/device.h>
                     56: #include <sys/poll.h>
                     57:
                     58: #include <dev/usb/usb.h>
                     59:
                     60: #include <dev/usb/usbdi.h>
                     61: #include <dev/usb/usbdi_util.h>
                     62: #include <dev/usb/uhidev.h>
                     63: #include <dev/usb/usbdevs.h>
                     64: #include <dev/usb/usb_quirks.h>
                     65:
                     66: #include <dev/usb/ucomvar.h>
                     67:
                     68: #include "ucom.h"
                     69:
                     70: #if NUCOM > 0
                     71:
                     72: #ifdef UCOM_DEBUG
                     73: #define DPRINTFN(n, x) do { if (ucomdebug > (n)) printf x; } while (0)
                     74: int ucomdebug = 0;
                     75: #else
                     76: #define DPRINTFN(n, x)
                     77: #endif
                     78: #define DPRINTF(x) DPRINTFN(0, x)
                     79:
                     80: #define        UCOMUNIT_MASK           0x7f
                     81: #define        UCOMCUA_MASK            0x80
                     82:
                     83: #define LINESW(tp, func)       (linesw[(tp)->t_line].func)
                     84:
                     85: #define        UCOMUNIT(x)             (minor(x) & UCOMUNIT_MASK)
                     86: #define        UCOMCUA(x)              (minor(x) & UCOMCUA_MASK)
                     87:
                     88: struct ucom_softc {
                     89:        struct device           sc_dev;         /* base device */
                     90:
                     91:        usbd_device_handle      sc_udev;        /* USB device */
                     92:        struct uhidev_softc     *sc_uhidev;     /* hid device (if deeper) */
                     93:
                     94:        usbd_interface_handle   sc_iface;       /* data interface */
                     95:
                     96:        int                     sc_bulkin_no;   /* bulk in endpoint address */
                     97:        usbd_pipe_handle        sc_bulkin_pipe; /* bulk in pipe */
                     98:        usbd_xfer_handle        sc_ixfer;       /* read request */
                     99:        u_char                  *sc_ibuf;       /* read buffer */
                    100:        u_int                   sc_ibufsize;    /* read buffer size */
                    101:        u_int                   sc_ibufsizepad; /* read buffer size padded */
                    102:
                    103:        int                     sc_bulkout_no;  /* bulk out endpoint address */
                    104:        usbd_pipe_handle        sc_bulkout_pipe;/* bulk out pipe */
                    105:        usbd_xfer_handle        sc_oxfer;       /* write request */
                    106:        u_char                  *sc_obuf;       /* write buffer */
                    107:        u_int                   sc_obufsize;    /* write buffer size */
                    108:        u_int                   sc_opkthdrlen;  /* header length of
                    109:                                                 * output packet */
                    110:
                    111:        usbd_pipe_handle        sc_ipipe;       /* hid interrupt input pipe */
                    112:        usbd_pipe_handle        sc_opipe;       /* hid interrupt pipe */
                    113:
                    114:        struct ucom_methods     *sc_methods;
                    115:        void                    *sc_parent;
                    116:        int                     sc_portno;
                    117:
                    118:        struct tty              *sc_tty;        /* our tty */
                    119:        u_char                  sc_lsr;
                    120:        u_char                  sc_msr;
                    121:        u_char                  sc_mcr;
                    122:        u_char                  sc_tx_stopped;
                    123:        int                     sc_swflags;
                    124:
                    125:        u_char                  sc_cua;
                    126:
                    127:        struct rwlock           sc_lock;        /* lock during open */
                    128:        int                     sc_open;
                    129:        int                     sc_refcnt;
                    130:        u_char                  sc_dying;       /* disconnecting */
                    131: };
                    132:
                    133: void   ucom_cleanup(struct ucom_softc *);
                    134: void   ucom_hwiflow(struct ucom_softc *);
                    135: int    ucomparam(struct tty *, struct termios *);
                    136: void   ucomstart(struct tty *);
                    137: void   ucom_shutdown(struct ucom_softc *);
                    138: int    ucom_do_ioctl(struct ucom_softc *, u_long, caddr_t,
                    139:                              int, struct proc *);
                    140: void   ucom_dtr(struct ucom_softc *, int);
                    141: void   ucom_rts(struct ucom_softc *, int);
                    142: void   ucom_break(struct ucom_softc *, int);
                    143: usbd_status ucomstartread(struct ucom_softc *);
                    144: void   ucomreadcb(usbd_xfer_handle, usbd_private_handle, usbd_status);
                    145: void   ucomwritecb(usbd_xfer_handle, usbd_private_handle, usbd_status);
                    146: void   tiocm_to_ucom(struct ucom_softc *, u_long, int);
                    147: int    ucom_to_tiocm(struct ucom_softc *);
                    148: void   ucom_lock(struct ucom_softc *);
                    149: void   ucom_unlock(struct ucom_softc *);
                    150:
                    151: int ucom_match(struct device *, void *, void *);
                    152: void ucom_attach(struct device *, struct device *, void *);
                    153: int ucom_detach(struct device *, int);
                    154: int ucom_activate(struct device *, enum devact);
                    155:
                    156: struct cfdriver ucom_cd = {
                    157:        NULL, "ucom", DV_DULL
                    158: };
                    159:
                    160: const struct cfattach ucom_ca = {
                    161:        sizeof(struct ucom_softc),
                    162:        ucom_match,
                    163:        ucom_attach,
                    164:        ucom_detach,
                    165:        ucom_activate,
                    166: };
                    167:
                    168: void
                    169: ucom_lock(struct ucom_softc *sc)
                    170: {
                    171:        sc->sc_refcnt++;
                    172:        rw_enter_write(&sc->sc_lock);
                    173: }
                    174:
                    175: void
                    176: ucom_unlock(struct ucom_softc *sc)
                    177: {
                    178:        rw_exit_write(&sc->sc_lock);
                    179:        if (--sc->sc_refcnt < 0)
                    180:                usb_detach_wakeup(&sc->sc_dev);
                    181: }
                    182:
                    183: int
                    184: ucom_match(struct device *parent, void *match, void *aux)
                    185: {
                    186:        return (1);
                    187: }
                    188:
                    189: void
                    190: ucom_attach(struct device *parent, struct device *self, void *aux)
                    191: {
                    192:        struct ucom_softc *sc = (struct ucom_softc *)self;
                    193:        struct ucom_attach_args *uca = aux;
                    194:        struct tty *tp;
                    195:
                    196:        if (uca->info != NULL)
                    197:                printf(", %s", uca->info);
                    198:        printf("\n");
                    199:
                    200:        sc->sc_udev = uca->device;
                    201:        sc->sc_iface = uca->iface;
                    202:        sc->sc_bulkout_no = uca->bulkout;
                    203:        sc->sc_bulkin_no = uca->bulkin;
                    204:        sc->sc_uhidev = uca->uhidev;
                    205:        sc->sc_ibufsize = uca->ibufsize;
                    206:        sc->sc_ibufsizepad = uca->ibufsizepad;
                    207:        sc->sc_obufsize = uca->obufsize;
                    208:        sc->sc_opkthdrlen = uca->opkthdrlen;
                    209:        sc->sc_methods = uca->methods;
                    210:        sc->sc_parent = uca->arg;
                    211:        sc->sc_portno = uca->portno;
                    212:
                    213:        tp = ttymalloc();
                    214:        tp->t_oproc = ucomstart;
                    215:        tp->t_param = ucomparam;
                    216:        sc->sc_tty = tp;
                    217:        sc->sc_cua = 0;
                    218:
                    219:        rw_init(&sc->sc_lock, "ucomlk");
                    220:
                    221:        sc->sc_open = 0;
                    222: }
                    223:
                    224: int
                    225: ucom_detach(struct device *self, int flags)
                    226: {
                    227:        struct ucom_softc *sc = (struct ucom_softc *)self;
                    228:        struct tty *tp = sc->sc_tty;
                    229:        int maj, mn;
                    230:        int s;
                    231:
                    232:        DPRINTF(("ucom_detach: sc=%p flags=%d tp=%p, pipe=%d,%d\n",
                    233:                 sc, flags, tp, sc->sc_bulkin_no, sc->sc_bulkout_no));
                    234:
                    235:        sc->sc_dying = 1;
                    236:
                    237:        if (sc->sc_bulkin_pipe != NULL)
                    238:                usbd_abort_pipe(sc->sc_bulkin_pipe);
                    239:        if (sc->sc_bulkout_pipe != NULL)
                    240:                usbd_abort_pipe(sc->sc_bulkout_pipe);
                    241:
                    242:        s = splusb();
                    243:        if (--sc->sc_refcnt >= 0) {
                    244:                /* Wake up anyone waiting */
                    245:                if (tp != NULL) {
                    246:                        CLR(tp->t_state, TS_CARR_ON);
                    247:                        CLR(tp->t_cflag, CLOCAL | MDMBUF);
                    248:                        ttyflush(tp, FREAD|FWRITE);
                    249:                }
                    250:                /* Wait for processes to go away. */
                    251:                usb_detach_wait(&sc->sc_dev);
                    252:        }
                    253:        splx(s);
                    254:
                    255:        /* locate the major number */
                    256:        for (maj = 0; maj < nchrdev; maj++)
                    257:                if (cdevsw[maj].d_open == ucomopen)
                    258:                        break;
                    259:
                    260:        /* Nuke the vnodes for any open instances. */
                    261:        mn = self->dv_unit;
                    262:        DPRINTF(("ucom_detach: maj=%d mn=%d\n", maj, mn));
                    263:        vdevgone(maj, mn, mn, VCHR);
                    264:        vdevgone(maj, mn | UCOMCUA_MASK, mn | UCOMCUA_MASK, VCHR);
                    265:
                    266:        /* Detach and free the tty. */
                    267:        if (tp != NULL) {
                    268:                ttyfree(tp);
                    269:                sc->sc_tty = NULL;
                    270:        }
                    271:
                    272:        return (0);
                    273: }
                    274:
                    275: int
                    276: ucom_activate(struct device *self, enum devact act)
                    277: {
                    278:        struct ucom_softc *sc = (struct ucom_softc *)self;
                    279:
                    280:        DPRINTFN(5,("ucom_activate: %d\n", act));
                    281:
                    282:        switch (act) {
                    283:        case DVACT_ACTIVATE:
                    284:                break;
                    285:
                    286:        case DVACT_DEACTIVATE:
                    287:                sc->sc_dying = 1;
                    288:                break;
                    289:        }
                    290:        return (0);
                    291: }
                    292:
                    293: void
                    294: ucom_shutdown(struct ucom_softc *sc)
                    295: {
                    296:        struct tty *tp = sc->sc_tty;
                    297:
                    298:        DPRINTF(("ucom_shutdown\n"));
                    299:        /*
                    300:         * Hang up if necessary.  Wait a bit, so the other side has time to
                    301:         * notice even if we immediately open the port again.
                    302:         */
                    303:        if (ISSET(tp->t_cflag, HUPCL)) {
                    304:                ucom_dtr(sc, 0);
                    305:                (void)tsleep(sc, TTIPRI, ttclos, hz);
                    306:        }
                    307: }
                    308:
                    309: int
                    310: ucomopen(dev_t dev, int flag, int mode, struct proc *p)
                    311: {
                    312:        int unit = UCOMUNIT(dev);
                    313:        usbd_status err;
                    314:        struct ucom_softc *sc;
                    315:        struct tty *tp;
                    316:        struct termios t;
                    317:        int s;
                    318:        int error;
                    319:
                    320:        if (unit >= ucom_cd.cd_ndevs)
                    321:                return (ENXIO);
                    322:        sc = ucom_cd.cd_devs[unit];
                    323:        if (sc == NULL)
                    324:                return (ENXIO);
                    325:
                    326:        if (sc->sc_dying)
                    327:                return (EIO);
                    328:
                    329:        if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0)
                    330:                return (ENXIO);
                    331:
                    332:        /* open the pipes if this is the first open */
                    333:        ucom_lock(sc);
                    334:        if (sc->sc_open++ == 0) {
                    335:                s = splusb();
                    336:
                    337:                DPRINTF(("ucomopen: open pipes in=%d out=%d\n",
                    338:                    sc->sc_bulkin_no, sc->sc_bulkout_no));
                    339:                DPRINTF(("ucomopen: hid %p pipes in=%p out=%p\n",
                    340:                    sc->sc_uhidev, sc->sc_ipipe, sc->sc_opipe));
                    341:
                    342:                if (sc->sc_bulkin_no != -1) {
                    343:
                    344:                        /* Open the bulk pipes */
                    345:                        err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, 0,
                    346:                            &sc->sc_bulkin_pipe);
                    347:                        if (err) {
                    348:                                DPRINTF(("%s: open bulk out error (addr %d), err=%s\n",
                    349:                                    sc->sc_dev.dv_xname, sc->sc_bulkin_no,
                    350:                                    usbd_errstr(err)));
                    351:                                error = EIO;
                    352:                                goto fail_0;
                    353:                        }
                    354:                        err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no,
                    355:                            USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
                    356:                        if (err) {
                    357:                                DPRINTF(("%s: open bulk in error (addr %d), err=%s\n",
                    358:                                    sc->sc_dev.dv_xname, sc->sc_bulkout_no,
                    359:                                    usbd_errstr(err)));
                    360:                                error = EIO;
                    361:                                goto fail_1;
                    362:                        }
                    363:
                    364:                        /* Allocate a request and an input buffer and start reading. */
                    365:                        sc->sc_ixfer = usbd_alloc_xfer(sc->sc_udev);
                    366:                        if (sc->sc_ixfer == NULL) {
                    367:                                error = ENOMEM;
                    368:                                goto fail_2;
                    369:                        }
                    370:
                    371:                        sc->sc_ibuf = usbd_alloc_buffer(sc->sc_ixfer,
                    372:                            sc->sc_ibufsizepad);
                    373:                        if (sc->sc_ibuf == NULL) {
                    374:                                error = ENOMEM;
                    375:                                goto fail_2;
                    376:                        }
                    377:
                    378:                        sc->sc_oxfer = usbd_alloc_xfer(sc->sc_udev);
                    379:                        if (sc->sc_oxfer == NULL) {
                    380:                                error = ENOMEM;
                    381:                                goto fail_3;
                    382:                        }
                    383:                } else {
                    384:                        /*
                    385:                         * input/output pipes and xfers already allocated
                    386:                         * as is the input buffer.
                    387:                         */
                    388:                        sc->sc_ipipe = sc->sc_uhidev->sc_ipipe;
                    389:                        sc->sc_ixfer = sc->sc_uhidev->sc_ixfer;
                    390:                        sc->sc_opipe = sc->sc_uhidev->sc_opipe;
                    391:                        sc->sc_oxfer = sc->sc_uhidev->sc_oxfer;
                    392:                }
                    393:
                    394:                sc->sc_obuf = usbd_alloc_buffer(sc->sc_oxfer,
                    395:                    sc->sc_obufsize + sc->sc_opkthdrlen);
                    396:                if (sc->sc_obuf == NULL) {
                    397:                        error = ENOMEM;
                    398:                        goto fail_4;
                    399:                }
                    400:
                    401:                if (sc->sc_methods->ucom_open != NULL) {
                    402:                        error = sc->sc_methods->ucom_open(sc->sc_parent,
                    403:                            sc->sc_portno);
                    404:                        if (error) {
                    405:                                ucom_cleanup(sc);
                    406:                                splx(s);
                    407:                                ucom_unlock(sc);
                    408:                                return (error);
                    409:                        }
                    410:                }
                    411:
                    412:                ucom_status_change(sc);
                    413:
                    414:                ucomstartread(sc);
                    415:
                    416:                splx(s);
                    417:        }
                    418:        ucom_unlock(sc);
                    419:
                    420:        s = spltty();
                    421:        tp = sc->sc_tty;
                    422:        splx(s);
                    423:
                    424:        DPRINTF(("ucomopen: unit=%d, tp=%p\n", unit, tp));
                    425:
                    426:        tp->t_dev = dev;
                    427:        if (!ISSET(tp->t_state, TS_ISOPEN)) {
                    428:                SET(tp->t_state, TS_WOPEN);
                    429:                ttychars(tp);
                    430:
                    431:                /*
                    432:                 * Initialize the termios status to the defaults.  Add in the
                    433:                 * sticky bits from TIOCSFLAGS.
                    434:                 */
                    435:                t.c_ispeed = 0;
                    436:                t.c_ospeed = TTYDEF_SPEED;
                    437:                t.c_cflag = TTYDEF_CFLAG;
                    438:                if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
                    439:                        SET(t.c_cflag, CLOCAL);
                    440:                if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
                    441:                        SET(t.c_cflag, CRTSCTS);
                    442:                if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
                    443:                        SET(t.c_cflag, MDMBUF);
                    444:
                    445:                /* Make sure ucomparam() will do something. */
                    446:                tp->t_ospeed = 0;
                    447:                (void) ucomparam(tp, &t);
                    448:                tp->t_iflag = TTYDEF_IFLAG;
                    449:                tp->t_oflag = TTYDEF_OFLAG;
                    450:                tp->t_lflag = TTYDEF_LFLAG;
                    451:
                    452:                s = spltty();
                    453:                ttsetwater(tp);
                    454:
                    455:                /*
                    456:                 * Turn on DTR.  We must always do this, even if carrier is not
                    457:                 * present, because otherwise we'd have to use TIOCSDTR
                    458:                 * immediately after setting CLOCAL, which applications do not
                    459:                 * expect.  We always assert DTR while the device is open
                    460:                 * unless explicitly requested to deassert it.
                    461:                 */
                    462:                ucom_dtr(sc, 1);
                    463:
                    464:                /* XXX CLR(sc->sc_rx_flags, RX_ANY_BLOCK);*/
                    465:                ucom_hwiflow(sc);
                    466:
                    467:                if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || UCOMCUA(dev) ||
                    468:                    ISSET(sc->sc_msr, UMSR_DCD) || ISSET(tp->t_cflag, MDMBUF))
                    469:                        SET(tp->t_state, TS_CARR_ON);
                    470:                else
                    471:                        CLR(tp->t_state, TS_CARR_ON);
                    472:        } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) {
                    473:                error = EBUSY;
                    474:                goto bad;
                    475:        } else
                    476:                s = spltty();
                    477:
                    478:        if (UCOMCUA(dev)) {
                    479:                if (ISSET(tp->t_state, TS_ISOPEN)) {
                    480:                        /* Someone is already dialed in */
                    481:                        error = EBUSY;
                    482:                        goto bad1;
                    483:                }
                    484:                sc->sc_cua = 1;
                    485:        } else {
                    486:                /* tty (not cua) device, wait for carrier */
                    487:                if (ISSET(flag, O_NONBLOCK)) {
                    488:                        if (sc->sc_cua) {
                    489:                                error = EBUSY;
                    490:                                goto bad1;
                    491:                        }
                    492:                } else {
                    493:                        while (sc->sc_cua || (!ISSET(tp->t_cflag, CLOCAL) &&
                    494:                            !ISSET(tp->t_state, TS_CARR_ON))) {
                    495:                                SET(tp->t_state, TS_WOPEN);
                    496:                                error = ttysleep(tp, &tp->t_rawq,
                    497:                                    TTIPRI | PCATCH, ttopen, 0);
                    498:                                /*
                    499:                                 * If TS_WOPEN has been reset, that means the
                    500:                                 * cua device has been closed.  We don't want
                    501:                                 * to fail in that case, so just go around
                    502:                                 * again.
                    503:                                 */
                    504:                                if (error && ISSET(tp->t_state, TS_WOPEN)) {
                    505:                                        CLR(tp->t_state, TS_WOPEN);
                    506:                                        goto bad1;
                    507:                                }
                    508:                        }
                    509:                }
                    510:        }
                    511:        splx(s);
                    512:
                    513:        error = ttyopen(UCOMUNIT(dev), tp);
                    514:        if (error)
                    515:                goto bad;
                    516:
                    517:        error = (*LINESW(tp, l_open))(dev, tp);
                    518:        if (error)
                    519:                goto bad;
                    520:
                    521:        return (0);
                    522:
                    523: fail_4:
                    524:        if (sc->sc_uhidev == NULL)
                    525:                usbd_free_xfer(sc->sc_oxfer);
                    526:        sc->sc_oxfer = NULL;
                    527: fail_3:
                    528:        usbd_free_xfer(sc->sc_ixfer);
                    529:        sc->sc_ixfer = NULL;
                    530: fail_2:
                    531:        usbd_close_pipe(sc->sc_bulkout_pipe);
                    532:        sc->sc_bulkout_pipe = NULL;
                    533: fail_1:
                    534:        usbd_close_pipe(sc->sc_bulkin_pipe);
                    535:        sc->sc_bulkin_pipe = NULL;
                    536: fail_0:
                    537:        splx(s);
                    538:        ucom_unlock(sc);
                    539:        return (error);
                    540:
                    541: bad1:
                    542:        splx(s);
                    543: bad:
                    544:        ucom_lock(sc);
                    545:        ucom_cleanup(sc);
                    546:        ucom_unlock(sc);
                    547:
                    548:        return (error);
                    549: }
                    550:
                    551: int
                    552: ucomclose(dev_t dev, int flag, int mode, struct proc *p)
                    553: {
                    554:        struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
                    555:        struct tty *tp = sc->sc_tty;
                    556:        int s;
                    557:
                    558:        if (!ISSET(tp->t_state, TS_ISOPEN))
                    559:                return (0);
                    560:
                    561:        DPRINTF(("ucomclose: unit=%d\n", UCOMUNIT(dev)));
                    562:        ucom_lock(sc);
                    563:
                    564:        (*LINESW(tp, l_close))(tp, flag);
                    565:        s = spltty();
                    566:        CLR(tp->t_state, TS_BUSY | TS_FLUSH);
                    567:        sc->sc_cua = 0;
                    568:        ttyclose(tp);
                    569:        ucom_cleanup(sc);
                    570:        splx(s);
                    571:
                    572:        if (sc->sc_methods->ucom_close != NULL)
                    573:                sc->sc_methods->ucom_close(sc->sc_parent, sc->sc_portno);
                    574:
                    575:        ucom_unlock(sc);
                    576:
                    577:        return (0);
                    578: }
                    579:
                    580: int
                    581: ucomread(dev_t dev, struct uio *uio, int flag)
                    582: {
                    583:        struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
                    584:        struct tty *tp = sc->sc_tty;
                    585:        int error;
                    586:
                    587:        if (sc->sc_dying)
                    588:                return (EIO);
                    589:
                    590:        sc->sc_refcnt++;
                    591:        error = (*LINESW(tp, l_read))(tp, uio, flag);
                    592:        if (--sc->sc_refcnt < 0)
                    593:                usb_detach_wakeup(&sc->sc_dev);
                    594:        return (error);
                    595: }
                    596:
                    597: int
                    598: ucomwrite(dev_t dev, struct uio *uio, int flag)
                    599: {
                    600:        struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
                    601:        struct tty *tp = sc->sc_tty;
                    602:        int error;
                    603:
                    604:        if (sc->sc_dying)
                    605:                return (EIO);
                    606:
                    607:        sc->sc_refcnt++;
                    608:        error = (*LINESW(tp, l_write))(tp, uio, flag);
                    609:        if (--sc->sc_refcnt < 0)
                    610:                usb_detach_wakeup(&sc->sc_dev);
                    611:        return (error);
                    612: }
                    613:
                    614: struct tty *
                    615: ucomtty(dev_t dev)
                    616: {
                    617:        struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
                    618:        struct tty *tp = sc->sc_tty;
                    619:
                    620:        return (tp);
                    621: }
                    622:
                    623: int
                    624: ucomioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
                    625: {
                    626:        struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
                    627:        int error;
                    628:
                    629:        sc->sc_refcnt++;
                    630:        error = ucom_do_ioctl(sc, cmd, data, flag, p);
                    631:        if (--sc->sc_refcnt < 0)
                    632:                usb_detach_wakeup(&sc->sc_dev);
                    633:        return (error);
                    634: }
                    635:
                    636: int
                    637: ucom_do_ioctl(struct ucom_softc *sc, u_long cmd, caddr_t data,
                    638:              int flag, struct proc *p)
                    639: {
                    640:        struct tty *tp = sc->sc_tty;
                    641:        int error;
                    642:        int s;
                    643:
                    644:        if (sc->sc_dying)
                    645:                return (EIO);
                    646:
                    647:        DPRINTF(("ucomioctl: cmd=0x%08lx\n", cmd));
                    648:
                    649:        error = (*LINESW(tp, l_ioctl))(tp, cmd, data, flag, p);
                    650:        if (error >= 0)
                    651:                return (error);
                    652:
                    653:        error = ttioctl(tp, cmd, data, flag, p);
                    654:        if (error >= 0)
                    655:                return (error);
                    656:
                    657:        if (sc->sc_methods->ucom_ioctl != NULL) {
                    658:                error = sc->sc_methods->ucom_ioctl(sc->sc_parent,
                    659:                            sc->sc_portno, cmd, data, flag, p);
                    660:                if (error >= 0)
                    661:                        return (error);
                    662:        }
                    663:
                    664:        error = 0;
                    665:
                    666:        DPRINTF(("ucomioctl: our cmd=0x%08lx\n", cmd));
                    667:        s = spltty();
                    668:
                    669:        switch (cmd) {
                    670:        case TIOCSBRK:
                    671:                ucom_break(sc, 1);
                    672:                break;
                    673:
                    674:        case TIOCCBRK:
                    675:                ucom_break(sc, 0);
                    676:                break;
                    677:
                    678:        case TIOCSDTR:
                    679:                ucom_dtr(sc, 1);
                    680:                break;
                    681:
                    682:        case TIOCCDTR:
                    683:                ucom_dtr(sc, 0);
                    684:                break;
                    685:
                    686:        case TIOCGFLAGS:
                    687:                *(int *)data = sc->sc_swflags;
                    688:                break;
                    689:
                    690:        case TIOCSFLAGS:
                    691:                error = suser(p, 0);
                    692:                if (error)
                    693:                        break;
                    694:                sc->sc_swflags = *(int *)data;
                    695:                break;
                    696:
                    697:        case TIOCMSET:
                    698:        case TIOCMBIS:
                    699:        case TIOCMBIC:
                    700:                tiocm_to_ucom(sc, cmd, *(int *)data);
                    701:                break;
                    702:
                    703:        case TIOCMGET:
                    704:                *(int *)data = ucom_to_tiocm(sc);
                    705:                break;
                    706:
                    707:        default:
                    708:                error = ENOTTY;
                    709:                break;
                    710:        }
                    711:
                    712:        splx(s);
                    713:
                    714:        return (error);
                    715: }
                    716:
                    717: void
                    718: tiocm_to_ucom(struct ucom_softc *sc, u_long how, int ttybits)
                    719: {
                    720:        u_char combits;
                    721:
                    722:        combits = 0;
                    723:        if (ISSET(ttybits, TIOCM_DTR))
                    724:                SET(combits, UMCR_DTR);
                    725:        if (ISSET(ttybits, TIOCM_RTS))
                    726:                SET(combits, UMCR_RTS);
                    727:
                    728:        switch (how) {
                    729:        case TIOCMBIC:
                    730:                CLR(sc->sc_mcr, combits);
                    731:                break;
                    732:
                    733:        case TIOCMBIS:
                    734:                SET(sc->sc_mcr, combits);
                    735:                break;
                    736:
                    737:        case TIOCMSET:
                    738:                CLR(sc->sc_mcr, UMCR_DTR | UMCR_RTS);
                    739:                SET(sc->sc_mcr, combits);
                    740:                break;
                    741:        }
                    742:
                    743:        if (how == TIOCMSET || ISSET(combits, UMCR_DTR))
                    744:                ucom_dtr(sc, (sc->sc_mcr & UMCR_DTR) != 0);
                    745:        if (how == TIOCMSET || ISSET(combits, UMCR_RTS))
                    746:                ucom_rts(sc, (sc->sc_mcr & UMCR_RTS) != 0);
                    747: }
                    748:
                    749: int
                    750: ucom_to_tiocm(struct ucom_softc *sc)
                    751: {
                    752:        u_char combits;
                    753:        int ttybits = 0;
                    754:
                    755:        combits = sc->sc_mcr;
                    756:        if (ISSET(combits, UMCR_DTR))
                    757:                SET(ttybits, TIOCM_DTR);
                    758:        if (ISSET(combits, UMCR_RTS))
                    759:                SET(ttybits, TIOCM_RTS);
                    760:
                    761:        combits = sc->sc_msr;
                    762:        if (ISSET(combits, UMSR_DCD))
                    763:                SET(ttybits, TIOCM_CD);
                    764:        if (ISSET(combits, UMSR_CTS))
                    765:                SET(ttybits, TIOCM_CTS);
                    766:        if (ISSET(combits, UMSR_DSR))
                    767:                SET(ttybits, TIOCM_DSR);
                    768:        if (ISSET(combits, UMSR_RI | UMSR_TERI))
                    769:                SET(ttybits, TIOCM_RI);
                    770:
                    771: #if 0
                    772: XXX;
                    773:        if (sc->sc_ier != 0)
                    774:                SET(ttybits, TIOCM_LE);
                    775: #endif
                    776:
                    777:        return (ttybits);
                    778: }
                    779:
                    780: void
                    781: ucom_break(sc, onoff)
                    782:        struct ucom_softc *sc;
                    783:        int onoff;
                    784: {
                    785:        DPRINTF(("ucom_break: onoff=%d\n", onoff));
                    786:
                    787:        if (sc->sc_methods->ucom_set != NULL)
                    788:                sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
                    789:                    UCOM_SET_BREAK, onoff);
                    790: }
                    791:
                    792: void
                    793: ucom_dtr(struct ucom_softc *sc, int onoff)
                    794: {
                    795:        DPRINTF(("ucom_dtr: onoff=%d\n", onoff));
                    796:
                    797:        if (sc->sc_methods->ucom_set != NULL) {
                    798:                sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
                    799:                    UCOM_SET_DTR, onoff);
                    800:                /* When not using CRTSCTS, RTS follows DTR. */
                    801:                if (!(sc->sc_swflags & TIOCFLAG_CRTSCTS))
                    802:                        ucom_rts(sc, onoff);
                    803:        }
                    804: }
                    805:
                    806: void
                    807: ucom_rts(struct ucom_softc *sc, int onoff)
                    808: {
                    809:        DPRINTF(("ucom_rts: onoff=%d\n", onoff));
                    810:
                    811:        if (sc->sc_methods->ucom_set != NULL)
                    812:                sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
                    813:                    UCOM_SET_RTS, onoff);
                    814: }
                    815:
                    816: void
                    817: ucom_status_change(struct ucom_softc *sc)
                    818: {
                    819:        struct tty *tp = sc->sc_tty;
                    820:        u_char old_msr;
                    821:
                    822:        if (sc->sc_methods->ucom_get_status != NULL) {
                    823:                old_msr = sc->sc_msr;
                    824:                sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno,
                    825:                    &sc->sc_lsr, &sc->sc_msr);
                    826:
                    827:                ttytstamp(tp, old_msr & UMSR_CTS, sc->sc_msr & UMSR_CTS,
                    828:                    old_msr & UMSR_DCD, sc->sc_msr & UMSR_DCD);
                    829:
                    830:                if (ISSET((sc->sc_msr ^ old_msr), UMSR_DCD))
                    831:                        (*LINESW(tp, l_modem))(tp,
                    832:                            ISSET(sc->sc_msr, UMSR_DCD));
                    833:        } else {
                    834:                sc->sc_lsr = 0;
                    835:                sc->sc_msr = 0;
                    836:        }
                    837: }
                    838:
                    839: int
                    840: ucomparam(struct tty *tp, struct termios *t)
                    841: {
                    842:        struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)];
                    843:        int error;
                    844:
                    845:        if (sc->sc_dying)
                    846:                return (EIO);
                    847:
                    848:        /* Check requested parameters. */
                    849:        if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
                    850:                return (EINVAL);
                    851:
                    852:        /*
                    853:         * For the console, always force CLOCAL and !HUPCL, so that the port
                    854:         * is always active.
                    855:         */
                    856:        if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR)) {
                    857:                SET(t->c_cflag, CLOCAL);
                    858:                CLR(t->c_cflag, HUPCL);
                    859:        }
                    860:
                    861:        /*
                    862:         * If there were no changes, don't do anything.  This avoids dropping
                    863:         * input and improves performance when all we did was frob things like
                    864:         * VMIN and VTIME.
                    865:         */
                    866:        if (tp->t_ospeed == t->c_ospeed &&
                    867:            tp->t_cflag == t->c_cflag)
                    868:                return (0);
                    869:
                    870:        /* XXX lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag); */
                    871:
                    872:        /* And copy to tty. */
                    873:        tp->t_ispeed = 0;
                    874:        tp->t_ospeed = t->c_ospeed;
                    875:        tp->t_cflag = t->c_cflag;
                    876:
                    877:        if (sc->sc_methods->ucom_param != NULL) {
                    878:                error = sc->sc_methods->ucom_param(sc->sc_parent, sc->sc_portno,
                    879:                            t);
                    880:                if (error)
                    881:                        return (error);
                    882:        }
                    883:
                    884:        /* XXX worry about CHWFLOW */
                    885:
                    886:        /*
                    887:         * Update the tty layer's idea of the carrier bit, in case we changed
                    888:         * CLOCAL or MDMBUF.  We don't hang up here; we only do that by
                    889:         * explicit request.
                    890:         */
                    891:        DPRINTF(("ucomparam: l_modem\n"));
                    892:        (void) (*LINESW(tp, l_modem))(tp, 1 /* XXX carrier */ );
                    893:
                    894: #if 0
                    895: XXX what if the hardware is not open
                    896:        if (!ISSET(t->c_cflag, CHWFLOW)) {
                    897:                if (sc->sc_tx_stopped) {
                    898:                        sc->sc_tx_stopped = 0;
                    899:                        ucomstart(tp);
                    900:                }
                    901:        }
                    902: #endif
                    903:
                    904:        return (0);
                    905: }
                    906:
                    907: /*
                    908:  * (un)block input via hw flowcontrol
                    909:  */
                    910: void
                    911: ucom_hwiflow(struct ucom_softc *sc)
                    912: {
                    913:        DPRINTF(("ucom_hwiflow:\n"));
                    914: #if 0
                    915: XXX
                    916:        bus_space_tag_t iot = sc->sc_iot;
                    917:        bus_space_handle_t ioh = sc->sc_ioh;
                    918:
                    919:        if (sc->sc_mcr_rts == 0)
                    920:                return;
                    921:
                    922:        if (ISSET(sc->sc_rx_flags, RX_ANY_BLOCK)) {
                    923:                CLR(sc->sc_mcr, sc->sc_mcr_rts);
                    924:                CLR(sc->sc_mcr_active, sc->sc_mcr_rts);
                    925:        } else {
                    926:                SET(sc->sc_mcr, sc->sc_mcr_rts);
                    927:                SET(sc->sc_mcr_active, sc->sc_mcr_rts);
                    928:        }
                    929:        bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr_active);
                    930: #endif
                    931: }
                    932:
                    933: void
                    934: ucomstart(struct tty *tp)
                    935: {
                    936:        struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)];
                    937:        usbd_status err;
                    938:        int s;
                    939:        u_char *data;
                    940:        int cnt;
                    941:
                    942:        if (sc->sc_dying)
                    943:                return;
                    944:
                    945:        s = spltty();
                    946:        if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) {
                    947:                DPRINTFN(4,("ucomstart: no go, state=0x%x\n", tp->t_state));
                    948:                goto out;
                    949:        }
                    950:        if (sc->sc_tx_stopped)
                    951:                goto out;
                    952:
                    953:        if (tp->t_outq.c_cc <= tp->t_lowat) {
                    954:                if (ISSET(tp->t_state, TS_ASLEEP)) {
                    955:                        CLR(tp->t_state, TS_ASLEEP);
                    956:                        wakeup(&tp->t_outq);
                    957:                }
                    958:                selwakeup(&tp->t_wsel);
                    959:                if (tp->t_outq.c_cc == 0)
                    960:                        goto out;
                    961:        }
                    962:
                    963:        /* Grab the first contiguous region of buffer space. */
                    964:        data = tp->t_outq.c_cf;
                    965:        cnt = ndqb(&tp->t_outq, 0);
                    966:
                    967:        if (cnt == 0) {
                    968:                DPRINTF(("ucomstart: cnt==0\n"));
                    969:                goto out;
                    970:        }
                    971:
                    972:        SET(tp->t_state, TS_BUSY);
                    973:
                    974:        if (cnt > sc->sc_obufsize) {
                    975:                DPRINTF(("ucomstart: big buffer %d chars\n", cnt));
                    976:                cnt = sc->sc_obufsize;
                    977:        }
                    978:        if (sc->sc_methods->ucom_write != NULL)
                    979:                sc->sc_methods->ucom_write(sc->sc_parent, sc->sc_portno,
                    980:                                           sc->sc_obuf, data, &cnt);
                    981:        else
                    982:                memcpy(sc->sc_obuf, data, cnt);
                    983:
                    984:        DPRINTFN(4,("ucomstart: %d chars\n", cnt));
                    985: #ifdef DIAGNOSTIC
                    986:        if (sc->sc_oxfer == NULL) {
                    987:                printf("ucomstart: null oxfer\n");
                    988:                goto out;
                    989:        }
                    990: #endif
                    991:        if (sc->sc_bulkout_pipe != NULL) {
                    992:                usbd_setup_xfer(sc->sc_oxfer, sc->sc_bulkout_pipe,
                    993:                    (usbd_private_handle)sc, sc->sc_obuf, cnt,
                    994:                    USBD_NO_COPY, USBD_NO_TIMEOUT, ucomwritecb);
                    995:        } else {
                    996:                usbd_setup_xfer(sc->sc_oxfer, sc->sc_opipe,
                    997:                    (usbd_private_handle)sc, sc->sc_obuf, cnt,
                    998:                    USBD_NO_COPY, USBD_NO_TIMEOUT, ucomwritecb);
                    999:        }
                   1000:        /* What can we do on error? */
                   1001:        err = usbd_transfer(sc->sc_oxfer);
                   1002: #ifdef DIAGNOSTIC
                   1003:        if (err != USBD_IN_PROGRESS)
                   1004:                printf("ucomstart: err=%s\n", usbd_errstr(err));
                   1005: #endif
                   1006:
                   1007: out:
                   1008:        splx(s);
                   1009: }
                   1010:
                   1011: int
                   1012: ucomstop(struct tty *tp, int flag)
                   1013: {
                   1014:        DPRINTF(("ucomstop: flag=%d\n", flag));
                   1015: #if 0
                   1016:        /*struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)];*/
                   1017:        int s;
                   1018:
                   1019:        s = spltty();
                   1020:        if (ISSET(tp->t_state, TS_BUSY)) {
                   1021:                DPRINTF(("ucomstop: XXX\n"));
                   1022:                /* sc->sc_tx_stopped = 1; */
                   1023:                if (!ISSET(tp->t_state, TS_TTSTOP))
                   1024:                        SET(tp->t_state, TS_FLUSH);
                   1025:        }
                   1026:        splx(s);
                   1027: #endif
                   1028:        return (0);
                   1029: }
                   1030:
                   1031: void
                   1032: ucomwritecb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
                   1033: {
                   1034:        struct ucom_softc *sc = (struct ucom_softc *)p;
                   1035:        struct tty *tp = sc->sc_tty;
                   1036:        u_int32_t cc;
                   1037:        int s;
                   1038:
                   1039:        DPRINTFN(5,("ucomwritecb: %p %p status=%d\n", xfer, p, status));
                   1040:
                   1041:        if (status == USBD_CANCELLED || sc->sc_dying)
                   1042:                goto error;
                   1043:
                   1044:        if (sc->sc_bulkin_pipe != NULL) {
                   1045:                if (status) {
                   1046:                        usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
                   1047:                        /* XXX we should restart after some delay. */
                   1048:                        goto error;
                   1049:                }
                   1050:                usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL);
                   1051:        } else {
                   1052:                usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL);
                   1053:                // XXX above gives me wrong cc, no?
                   1054:        }
                   1055:
                   1056:        DPRINTFN(5,("ucomwritecb: cc=%d\n", cc));
                   1057:        /* convert from USB bytes to tty bytes */
                   1058:        cc -= sc->sc_opkthdrlen;
                   1059:
                   1060:        s = spltty();
                   1061:        CLR(tp->t_state, TS_BUSY);
                   1062:        if (ISSET(tp->t_state, TS_FLUSH))
                   1063:                CLR(tp->t_state, TS_FLUSH);
                   1064:        else
                   1065:                ndflush(&tp->t_outq, cc);
                   1066:        (*LINESW(tp, l_start))(tp);
                   1067:        splx(s);
                   1068:        return;
                   1069:
                   1070: error:
                   1071:        s = spltty();
                   1072:        CLR(tp->t_state, TS_BUSY);
                   1073:        splx(s);
                   1074: }
                   1075:
                   1076: usbd_status
                   1077: ucomstartread(struct ucom_softc *sc)
                   1078: {
                   1079:        usbd_status err;
                   1080:
                   1081:        DPRINTFN(5,("ucomstartread: start\n"));
                   1082: #ifdef DIAGNOSTIC
                   1083:        if (sc->sc_ixfer == NULL) {
                   1084:                DPRINTF(("ucomstartread: null ixfer\n"));
                   1085:                return (USBD_INVAL);
                   1086:        }
                   1087: #endif
                   1088:
                   1089:        if (sc->sc_bulkin_pipe != NULL) {
                   1090:                usbd_setup_xfer(sc->sc_ixfer, sc->sc_bulkin_pipe,
                   1091:                        (usbd_private_handle)sc,
                   1092:                        sc->sc_ibuf, sc->sc_ibufsize,
                   1093:                        USBD_SHORT_XFER_OK | USBD_NO_COPY,
                   1094:                        USBD_NO_TIMEOUT, ucomreadcb);
                   1095:                err = usbd_transfer(sc->sc_ixfer);
                   1096:                if (err != USBD_IN_PROGRESS) {
                   1097:                        DPRINTF(("ucomstartread: err=%s\n", usbd_errstr(err)));
                   1098:                        return (err);
                   1099:                }
                   1100:        }
                   1101:
                   1102:        return (USBD_NORMAL_COMPLETION);
                   1103: }
                   1104:
                   1105: void
                   1106: ucomreadcb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
                   1107: {
                   1108:        struct ucom_softc *sc = (struct ucom_softc *)p;
                   1109:        struct tty *tp = sc->sc_tty;
                   1110:        int (*rint)(int c, struct tty *tp) = LINESW(tp, l_rint);
                   1111:        usbd_status err;
                   1112:        u_int32_t cc;
                   1113:        u_char *cp;
                   1114:        int s;
                   1115:
                   1116:        DPRINTFN(5,("ucomreadcb: status=%d\n", status));
                   1117:
                   1118:        if (status == USBD_CANCELLED || status == USBD_IOERROR ||
                   1119:            sc->sc_dying) {
                   1120:                DPRINTF(("ucomreadcb: dying\n"));
                   1121:                /* Send something to wake upper layer */
                   1122:                s = spltty();
                   1123:                (*rint)('\n', tp);
                   1124:                ttwakeup(tp);
                   1125:                splx(s);
                   1126:                return;
                   1127:        }
                   1128:
                   1129:        if (status) {
                   1130:                if (sc->sc_bulkin_pipe != NULL) {
                   1131:                        usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
                   1132:                        /* XXX we should restart after some delay. */
                   1133:                        return;
                   1134:                }
                   1135:        }
                   1136:
                   1137:        usbd_get_xfer_status(xfer, NULL, (void *)&cp, &cc, NULL);
                   1138:        DPRINTFN(5,("ucomreadcb: got %d chars, tp=%p\n", cc, tp));
                   1139:        if (sc->sc_methods->ucom_read != NULL)
                   1140:                sc->sc_methods->ucom_read(sc->sc_parent, sc->sc_portno,
                   1141:                                          &cp, &cc);
                   1142:
                   1143:        s = spltty();
                   1144:        /* Give characters to tty layer. */
                   1145:        while (cc-- > 0) {
                   1146:                DPRINTFN(7,("ucomreadcb: char=0x%02x\n", *cp));
                   1147:                if ((*rint)(*cp++, tp) == -1) {
                   1148:                        /* XXX what should we do? */
                   1149:                        printf("%s: lost %d chars\n", sc->sc_dev.dv_xname,
                   1150:                               cc);
                   1151:                        break;
                   1152:                }
                   1153:        }
                   1154:        splx(s);
                   1155:
                   1156:        err = ucomstartread(sc);
                   1157:        if (err) {
                   1158:                printf("%s: read start failed\n", sc->sc_dev.dv_xname);
                   1159:                /* XXX what should we dow now? */
                   1160:        }
                   1161: }
                   1162:
                   1163: void
                   1164: ucom_cleanup(struct ucom_softc *sc)
                   1165: {
                   1166:        if (--sc->sc_open == 0) {
                   1167:                DPRINTF(("ucom_cleanup: closing pipes\n"));
                   1168:
                   1169:                ucom_shutdown(sc);
                   1170:                if (sc->sc_bulkin_pipe != NULL) {
                   1171:                        usbd_abort_pipe(sc->sc_bulkin_pipe);
                   1172:                        usbd_close_pipe(sc->sc_bulkin_pipe);
                   1173:                        sc->sc_bulkin_pipe = NULL;
                   1174:                }
                   1175:                if (sc->sc_bulkout_pipe != NULL) {
                   1176:                        usbd_abort_pipe(sc->sc_bulkout_pipe);
                   1177:                        usbd_close_pipe(sc->sc_bulkout_pipe);
                   1178:                        sc->sc_bulkout_pipe = NULL;
                   1179:                }
                   1180:                if (sc->sc_ixfer != NULL) {
                   1181:                        if (sc->sc_uhidev == NULL)
                   1182:                                usbd_free_xfer(sc->sc_ixfer);
                   1183:                        sc->sc_ixfer = NULL;
                   1184:                }
                   1185:                if (sc->sc_oxfer != NULL) {
                   1186:                        usbd_free_buffer(sc->sc_oxfer);
                   1187:                        if (sc->sc_uhidev == NULL)
                   1188:                                usbd_free_xfer(sc->sc_oxfer);
                   1189:                        sc->sc_oxfer = NULL;
                   1190:                }
                   1191:        }
                   1192: }
                   1193:
                   1194: #endif /* NUCOM > 0 */
                   1195:
                   1196: int
                   1197: ucomprint(void *aux, const char *pnp)
                   1198: {
                   1199:        struct ucom_attach_args *uca = aux;
                   1200:
                   1201:        if (pnp)
                   1202:                printf("ucom at %s", pnp);
                   1203:        if (uca->portno != UCOM_UNK_PORTNO)
                   1204:                printf(" portno %d", uca->portno);
                   1205:        return (UNCONF);
                   1206: }
                   1207:
                   1208: int
                   1209: ucomsubmatch(struct device *parent, void *match, void *aux)
                   1210: {
                   1211:         struct ucom_attach_args *uca = aux;
                   1212:         struct cfdata *cf = match;
                   1213:
                   1214:        if (uca->portno != UCOM_UNK_PORTNO &&
                   1215:            cf->ucomcf_portno != UCOM_UNK_PORTNO &&
                   1216:            cf->ucomcf_portno != uca->portno)
                   1217:                return (0);
                   1218:        return ((*cf->cf_attach->ca_match)(parent, cf, aux));
                   1219: }

CVSweb