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

Annotation of sys/dev/usb/umct.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: umct.c,v 1.26 2007/06/14 10:11:16 mbalmer Exp $       */
        !             2: /*     $NetBSD: umct.c,v 1.10 2003/02/23 04:20:07 simonb Exp $ */
        !             3: /*
        !             4:  * Copyright (c) 2001 The NetBSD Foundation, Inc.
        !             5:  * All rights reserved.
        !             6:  *
        !             7:  * This code is derived from software contributed to The NetBSD Foundation
        !             8:  * by Ichiro FUKUHARA (ichiro@ichiro.org).
        !             9:  *
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  * 3. All advertising materials mentioning features or use of this software
        !            19:  *    must display the following acknowledgement:
        !            20:  *        This product includes software developed by the NetBSD
        !            21:  *        Foundation, Inc. and its contributors.
        !            22:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            23:  *    contributors may be used to endorse or promote products derived
        !            24:  *    from this software without specific prior written permission.
        !            25:  *
        !            26:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            27:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            36:  * POSSIBILITY OF SUCH DAMAGE.
        !            37:  */
        !            38:
        !            39: /*
        !            40:  * MCT USB-RS232 Interface Controller
        !            41:  * http://www.mct.com.tw/prod/rs232.html
        !            42:  * http://www.dlink.com/products/usb/dsbs25
        !            43:  */
        !            44:
        !            45: #include <sys/param.h>
        !            46: #include <sys/systm.h>
        !            47: #include <sys/kernel.h>
        !            48: #include <sys/malloc.h>
        !            49: #include <sys/ioctl.h>
        !            50: #include <sys/conf.h>
        !            51: #include <sys/tty.h>
        !            52: #include <sys/file.h>
        !            53: #include <sys/selinfo.h>
        !            54: #include <sys/proc.h>
        !            55: #include <sys/vnode.h>
        !            56: #include <sys/device.h>
        !            57: #include <sys/poll.h>
        !            58:
        !            59: #include <dev/usb/usb.h>
        !            60: #include <dev/usb/usbcdc.h>
        !            61:
        !            62: #include <dev/usb/usbdi.h>
        !            63: #include <dev/usb/usbdi_util.h>
        !            64: #include <dev/usb/usbdevs.h>
        !            65: #include <dev/usb/usb_quirks.h>
        !            66:
        !            67: #include <dev/usb/usbdevs.h>
        !            68: #include <dev/usb/ucomvar.h>
        !            69:
        !            70: #include <dev/usb/umct.h>
        !            71:
        !            72: #ifdef UMCT_DEBUG
        !            73: #define DPRINTFN(n, x)  do { if (umctdebug > (n)) printf x; } while (0)
        !            74: int    umctdebug = 0;
        !            75: #else
        !            76: #define DPRINTFN(n, x)
        !            77: #endif
        !            78: #define DPRINTF(x) DPRINTFN(0, x)
        !            79:
        !            80: #define        UMCT_CONFIG_INDEX       0
        !            81: #define        UMCT_IFACE_INDEX        0
        !            82:
        !            83: struct umct_softc {
        !            84:        struct device            sc_dev;        /* base device */
        !            85:        usbd_device_handle      sc_udev;        /* USB device */
        !            86:        usbd_interface_handle    sc_iface;      /* interface */
        !            87:        int                      sc_iface_number;       /* interface number */
        !            88:        u_int16_t                sc_product;
        !            89:
        !            90:        int                      sc_intr_number;        /* interrupt number */
        !            91:        usbd_pipe_handle         sc_intr_pipe;  /* interrupt pipe */
        !            92:        u_char                  *sc_intr_buf;   /* interrupt buffer */
        !            93:        int                      sc_isize;
        !            94:
        !            95:        usb_cdc_line_state_t     sc_line_state; /* current line state */
        !            96:        u_char                   sc_dtr;        /* current DTR state */
        !            97:        u_char                   sc_rts;        /* current RTS state */
        !            98:        u_char                   sc_break;      /* set break */
        !            99:
        !           100:        u_char                   sc_status;
        !           101:
        !           102:        struct device           *sc_subdev;     /* ucom device */
        !           103:
        !           104:        u_char                   sc_dying;      /* disconnecting */
        !           105:
        !           106:        u_char                   sc_lsr;        /* Local status register */
        !           107:        u_char                   sc_msr;        /* umct status register */
        !           108:
        !           109:        u_int                    last_lcr;      /* keep lcr register */
        !           110: };
        !           111:
        !           112: /*
        !           113:  * These are the maximum number of bytes transferred per frame.
        !           114:  * The output buffer size cannot be increased due to the size encoding.
        !           115:  */
        !           116: #define UMCTIBUFSIZE 256
        !           117: #define UMCTOBUFSIZE 256
        !           118:
        !           119: void umct_init(struct umct_softc *);
        !           120: void umct_set_baudrate(struct umct_softc *, u_int);
        !           121: void umct_set_lcr(struct umct_softc *, u_int);
        !           122: void umct_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
        !           123:
        !           124: void umct_set(void *, int, int, int);
        !           125: void umct_dtr(struct umct_softc *, int);
        !           126: void umct_rts(struct umct_softc *, int);
        !           127: void umct_break(struct umct_softc *, int);
        !           128: void umct_set_line_state(struct umct_softc *);
        !           129: void umct_get_status(void *, int portno, u_char *lsr, u_char *msr);
        !           130: int  umct_param(void *, int, struct termios *);
        !           131: int  umct_open(void *, int);
        !           132: void umct_close(void *, int);
        !           133:
        !           134: struct ucom_methods umct_methods = {
        !           135:        umct_get_status,
        !           136:        umct_set,
        !           137:        umct_param,
        !           138:        NULL,
        !           139:        umct_open,
        !           140:        umct_close,
        !           141:        NULL,
        !           142:        NULL,
        !           143: };
        !           144:
        !           145: static const struct usb_devno umct_devs[] = {
        !           146:        /* MCT USB-232 Interface Products */
        !           147:        { USB_VENDOR_MCT, USB_PRODUCT_MCT_USB232 },
        !           148:        /* Sitecom USB-232 Products */
        !           149:        { USB_VENDOR_MCT, USB_PRODUCT_MCT_SITECOM_USB232 },
        !           150:        /* D-Link DU-H3SP USB BAY Hub Products */
        !           151:        { USB_VENDOR_MCT, USB_PRODUCT_MCT_DU_H3SP_USB232 },
        !           152:        /* BELKIN F5U109 */
        !           153:        { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U109 },
        !           154:        /* BELKIN F5U409 */
        !           155:        { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U409 },
        !           156: };
        !           157: #define umct_lookup(v, p) usb_lookup(umct_devs, v, p)
        !           158:
        !           159: int umct_match(struct device *, void *, void *);
        !           160: void umct_attach(struct device *, struct device *, void *);
        !           161: int umct_detach(struct device *, int);
        !           162: int umct_activate(struct device *, enum devact);
        !           163:
        !           164: struct cfdriver umct_cd = {
        !           165:        NULL, "umct", DV_DULL
        !           166: };
        !           167:
        !           168: const struct cfattach umct_ca = {
        !           169:        sizeof(struct umct_softc),
        !           170:        umct_match,
        !           171:        umct_attach,
        !           172:        umct_detach,
        !           173:        umct_activate,
        !           174: };
        !           175:
        !           176: int
        !           177: umct_match(struct device *parent, void *match, void *aux)
        !           178: {
        !           179:        struct usb_attach_arg *uaa = aux;
        !           180:
        !           181:        if (uaa->iface != NULL)
        !           182:                return (UMATCH_NONE);
        !           183:
        !           184:        return (umct_lookup(uaa->vendor, uaa->product) != NULL ?
        !           185:                UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
        !           186: }
        !           187:
        !           188: void
        !           189: umct_attach(struct device *parent, struct device *self, void *aux)
        !           190: {
        !           191:        struct umct_softc *sc = (struct umct_softc *)self;
        !           192:        struct usb_attach_arg *uaa = aux;
        !           193:        usbd_device_handle dev = uaa->device;
        !           194:        usb_config_descriptor_t *cdesc;
        !           195:        usb_interface_descriptor_t *id;
        !           196:        usb_endpoint_descriptor_t *ed;
        !           197:
        !           198:        char *devinfop;
        !           199:        char *devname = sc->sc_dev.dv_xname;
        !           200:        usbd_status err;
        !           201:        int i;
        !           202:        struct ucom_attach_args uca;
        !           203:
        !           204:        devinfop = usbd_devinfo_alloc(dev, 0);
        !           205:        printf("\n%s: %s\n", devname, devinfop);
        !           206:        usbd_devinfo_free(devinfop);
        !           207:
        !           208:         sc->sc_udev = dev;
        !           209:        sc->sc_product = uaa->product;
        !           210:
        !           211:        DPRINTF(("\n\numct attach: sc=%p\n", sc));
        !           212:
        !           213:        /* initialize endpoints */
        !           214:        uca.bulkin = uca.bulkout = -1;
        !           215:        sc->sc_intr_number = -1;
        !           216:        sc->sc_intr_pipe = NULL;
        !           217:
        !           218:        /* Move the device into the configured state. */
        !           219:        err = usbd_set_config_index(dev, UMCT_CONFIG_INDEX, 1);
        !           220:        if (err) {
        !           221:                printf("\n%s: failed to set configuration, err=%s\n",
        !           222:                        devname, usbd_errstr(err));
        !           223:                sc->sc_dying = 1;
        !           224:                return;
        !           225:        }
        !           226:
        !           227:        /* get the config descriptor */
        !           228:        cdesc = usbd_get_config_descriptor(sc->sc_udev);
        !           229:
        !           230:        if (cdesc == NULL) {
        !           231:                printf("%s: failed to get configuration descriptor\n",
        !           232:                        sc->sc_dev.dv_xname);
        !           233:                sc->sc_dying = 1;
        !           234:                return;
        !           235:        }
        !           236:
        !           237:        /* get the interface */
        !           238:        err = usbd_device2interface_handle(dev, UMCT_IFACE_INDEX,
        !           239:                                                        &sc->sc_iface);
        !           240:        if (err) {
        !           241:                printf("\n%s: failed to get interface, err=%s\n",
        !           242:                        devname, usbd_errstr(err));
        !           243:                sc->sc_dying = 1;
        !           244:                return;
        !           245:        }
        !           246:
        !           247:        /* Find the bulk{in,out} and interrupt endpoints */
        !           248:
        !           249:        id = usbd_get_interface_descriptor(sc->sc_iface);
        !           250:        sc->sc_iface_number = id->bInterfaceNumber;
        !           251:
        !           252:        for (i = 0; i < id->bNumEndpoints; i++) {
        !           253:                ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
        !           254:                if (ed == NULL) {
        !           255:                        printf("%s: no endpoint descriptor for %d\n",
        !           256:                                sc->sc_dev.dv_xname, i);
        !           257:                        sc->sc_dying = 1;
        !           258:                        return;
        !           259:                }
        !           260:
        !           261:                /*
        !           262:                 * The Bulkin endpoint is marked as an interrupt. Since
        !           263:                 * we can't rely on the endpoint descriptor order, we'll
        !           264:                 * check the wMaxPacketSize field to differentiate.
        !           265:                 */
        !           266:                if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
        !           267:                    UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT &&
        !           268:                    UGETW(ed->wMaxPacketSize) != 0x2) {
        !           269:                        uca.bulkin = ed->bEndpointAddress;
        !           270:                } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
        !           271:                    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
        !           272:                        uca.bulkout = ed->bEndpointAddress;
        !           273:                } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
        !           274:                    UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
        !           275:                        sc->sc_intr_number = ed->bEndpointAddress;
        !           276:                        sc->sc_isize = UGETW(ed->wMaxPacketSize);
        !           277:                }
        !           278:        }
        !           279:
        !           280:        if (uca.bulkin == -1) {
        !           281:                printf("%s: Could not find data bulk in\n",
        !           282:                        sc->sc_dev.dv_xname);
        !           283:                sc->sc_dying = 1;
        !           284:                return;
        !           285:        }
        !           286:
        !           287:        if (uca.bulkout == -1) {
        !           288:                printf("%s: Could not find data bulk out\n",
        !           289:                        sc->sc_dev.dv_xname);
        !           290:                sc->sc_dying = 1;
        !           291:                return;
        !           292:        }
        !           293:
        !           294:        if (sc->sc_intr_number== -1) {
        !           295:                printf("%s: Could not find interrupt in\n",
        !           296:                        sc->sc_dev.dv_xname);
        !           297:                sc->sc_dying = 1;
        !           298:                return;
        !           299:        }
        !           300:
        !           301:        sc->sc_dtr = sc->sc_rts = 0;
        !           302:        uca.portno = UCOM_UNK_PORTNO;
        !           303:        /* bulkin, bulkout set above */
        !           304:        uca.ibufsize = UMCTIBUFSIZE;
        !           305:        if (sc->sc_product == USB_PRODUCT_MCT_SITECOM_USB232)
        !           306:                uca.obufsize = 16; /* device is broken */
        !           307:        else
        !           308:                uca.obufsize = UMCTOBUFSIZE;
        !           309:        uca.ibufsizepad = UMCTIBUFSIZE;
        !           310:        uca.opkthdrlen = 0;
        !           311:        uca.device = dev;
        !           312:        uca.iface = sc->sc_iface;
        !           313:        uca.methods = &umct_methods;
        !           314:        uca.arg = sc;
        !           315:        uca.info = NULL;
        !           316:
        !           317:        umct_init(sc);
        !           318:
        !           319:        usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
        !           320:                           &sc->sc_dev);
        !           321:
        !           322:        DPRINTF(("umct: in=0x%x out=0x%x intr=0x%x\n",
        !           323:                        uca.bulkin, uca.bulkout, sc->sc_intr_number ));
        !           324:        sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
        !           325: }
        !           326:
        !           327: int
        !           328: umct_detach(struct device *self, int flags)
        !           329: {
        !           330:        struct umct_softc *sc = (struct umct_softc *)self;
        !           331:        int rv = 0;
        !           332:
        !           333:        DPRINTF(("umct_detach: sc=%p flags=%d\n", sc, flags));
        !           334:
        !           335:         if (sc->sc_intr_pipe != NULL) {
        !           336:                 usbd_abort_pipe(sc->sc_intr_pipe);
        !           337:                 usbd_close_pipe(sc->sc_intr_pipe);
        !           338:                free(sc->sc_intr_buf, M_USBDEV);
        !           339:                 sc->sc_intr_pipe = NULL;
        !           340:         }
        !           341:
        !           342:        sc->sc_dying = 1;
        !           343:        if (sc->sc_subdev != NULL) {
        !           344:                rv = config_detach(sc->sc_subdev, flags);
        !           345:                sc->sc_subdev = NULL;
        !           346:        }
        !           347:
        !           348:        usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
        !           349:                           &sc->sc_dev);
        !           350:
        !           351:        return (rv);
        !           352: }
        !           353:
        !           354: int
        !           355: umct_activate(struct device *self, enum devact act)
        !           356: {
        !           357:        struct umct_softc *sc = (struct umct_softc *)self;
        !           358:        int rv = 0;
        !           359:
        !           360:        switch (act) {
        !           361:        case DVACT_ACTIVATE:
        !           362:                break;
        !           363:
        !           364:        case DVACT_DEACTIVATE:
        !           365:                if (sc->sc_subdev != NULL)
        !           366:                        rv = config_deactivate(sc->sc_subdev);
        !           367:                sc->sc_dying = 1;
        !           368:                break;
        !           369:        }
        !           370:        return (rv);
        !           371: }
        !           372:
        !           373: void
        !           374: umct_set_line_state(struct umct_softc *sc)
        !           375: {
        !           376:        usb_device_request_t req;
        !           377:        uByte ls;
        !           378:
        !           379:        ls = (sc->sc_dtr ? MCR_DTR : 0) |
        !           380:             (sc->sc_rts ? MCR_RTS : 0);
        !           381:
        !           382:        DPRINTF(("umct_set_line_state: DTR=%d,RTS=%d,ls=%02x\n",
        !           383:                        sc->sc_dtr, sc->sc_rts, ls));
        !           384:
        !           385:        req.bmRequestType = UMCT_SET_REQUEST;
        !           386:        req.bRequest = REQ_SET_MCR;
        !           387:        USETW(req.wValue, 0);
        !           388:        USETW(req.wIndex, sc->sc_iface_number);
        !           389:        USETW(req.wLength, LENGTH_SET_MCR);
        !           390:
        !           391:        (void)usbd_do_request(sc->sc_udev, &req, &ls);
        !           392: }
        !           393:
        !           394: void
        !           395: umct_set(void *addr, int portno, int reg, int onoff)
        !           396: {
        !           397:        struct umct_softc *sc = addr;
        !           398:
        !           399:        switch (reg) {
        !           400:        case UCOM_SET_DTR:
        !           401:                umct_dtr(sc, onoff);
        !           402:                break;
        !           403:        case UCOM_SET_RTS:
        !           404:                umct_rts(sc, onoff);
        !           405:                break;
        !           406:        case UCOM_SET_BREAK:
        !           407:                umct_break(sc, onoff);
        !           408:                break;
        !           409:        default:
        !           410:                break;
        !           411:        }
        !           412: }
        !           413:
        !           414: void
        !           415: umct_dtr(struct umct_softc *sc, int onoff)
        !           416: {
        !           417:
        !           418:        DPRINTF(("umct_dtr: onoff=%d\n", onoff));
        !           419:
        !           420:        if (sc->sc_dtr == onoff)
        !           421:                return;
        !           422:        sc->sc_dtr = onoff;
        !           423:
        !           424:        umct_set_line_state(sc);
        !           425: }
        !           426:
        !           427: void
        !           428: umct_rts(struct umct_softc *sc, int onoff)
        !           429: {
        !           430:        DPRINTF(("umct_rts: onoff=%d\n", onoff));
        !           431:
        !           432:        if (sc->sc_rts == onoff)
        !           433:                return;
        !           434:        sc->sc_rts = onoff;
        !           435:
        !           436:        umct_set_line_state(sc);
        !           437: }
        !           438:
        !           439: void
        !           440: umct_break(struct umct_softc *sc, int onoff)
        !           441: {
        !           442:        DPRINTF(("umct_break: onoff=%d\n", onoff));
        !           443:
        !           444:        umct_set_lcr(sc, onoff ? sc->last_lcr | LCR_SET_BREAK :
        !           445:                     sc->last_lcr);
        !           446: }
        !           447:
        !           448: void
        !           449: umct_set_lcr(struct umct_softc *sc, u_int data)
        !           450: {
        !           451:        usb_device_request_t req;
        !           452:        uByte adata;
        !           453:
        !           454:        adata = data;
        !           455:        req.bmRequestType = UMCT_SET_REQUEST;
        !           456:        req.bRequest = REQ_SET_LCR;
        !           457:        USETW(req.wValue, 0);
        !           458:        USETW(req.wIndex, sc->sc_iface_number);
        !           459:        USETW(req.wLength, LENGTH_SET_LCR);
        !           460:
        !           461:        /* XXX should check */
        !           462:        (void)usbd_do_request(sc->sc_udev, &req, &adata);
        !           463: }
        !           464:
        !           465: void
        !           466: umct_set_baudrate(struct umct_softc *sc, u_int rate)
        !           467: {
        !           468:         usb_device_request_t req;
        !           469:        uDWord arate;
        !           470:        u_int val;
        !           471:
        !           472:        if (sc->sc_product == USB_PRODUCT_MCT_SITECOM_USB232 ||
        !           473:            sc->sc_product == USB_PRODUCT_BELKIN_F5U109) {
        !           474:                switch (rate) {
        !           475:                case    300: val = 0x01; break;
        !           476:                case    600: val = 0x02; break;
        !           477:                case   1200: val = 0x03; break;
        !           478:                case   2400: val = 0x04; break;
        !           479:                case   4800: val = 0x06; break;
        !           480:                case   9600: val = 0x08; break;
        !           481:                case  19200: val = 0x09; break;
        !           482:                case  38400: val = 0x0a; break;
        !           483:                case  57600: val = 0x0b; break;
        !           484:                case 115200: val = 0x0c; break;
        !           485:                default:     val = -1; break;
        !           486:                }
        !           487:        } else {
        !           488:                val = UMCT_BAUD_RATE(rate);
        !           489:        }
        !           490:        USETDW(arate, val);
        !           491:
        !           492:         req.bmRequestType = UMCT_SET_REQUEST;
        !           493:         req.bRequest = REQ_SET_BAUD_RATE;
        !           494:         USETW(req.wValue, 0);
        !           495:         USETW(req.wIndex, sc->sc_iface_number);
        !           496:         USETW(req.wLength, LENGTH_BAUD_RATE);
        !           497:
        !           498:        /* XXX should check */
        !           499:         (void)usbd_do_request(sc->sc_udev, &req, arate);
        !           500: }
        !           501:
        !           502: void
        !           503: umct_init(struct umct_softc *sc)
        !           504: {
        !           505:        umct_set_baudrate(sc, 9600);
        !           506:        umct_set_lcr(sc, LCR_DATA_BITS_8 | LCR_PARITY_NONE | LCR_STOP_BITS_1);
        !           507: }
        !           508:
        !           509: int
        !           510: umct_param(void *addr, int portno, struct termios *t)
        !           511: {
        !           512:        struct umct_softc *sc = addr;
        !           513:        u_int data = 0;
        !           514:
        !           515:        DPRINTF(("umct_param: sc=%p\n", sc));
        !           516:
        !           517:        DPRINTF(("umct_param: BAUDRATE=%d\n", t->c_ospeed));
        !           518:
        !           519:        if (ISSET(t->c_cflag, CSTOPB))
        !           520:                data |= LCR_STOP_BITS_2;
        !           521:        else
        !           522:                data |= LCR_STOP_BITS_1;
        !           523:        if (ISSET(t->c_cflag, PARENB)) {
        !           524:                if (ISSET(t->c_cflag, PARODD))
        !           525:                        data |= LCR_PARITY_ODD;
        !           526:                else
        !           527:                        data |= LCR_PARITY_EVEN;
        !           528:        } else
        !           529:                data |= LCR_PARITY_NONE;
        !           530:        switch (ISSET(t->c_cflag, CSIZE)) {
        !           531:        case CS5:
        !           532:                data |= LCR_DATA_BITS_5;
        !           533:                break;
        !           534:        case CS6:
        !           535:                data |= LCR_DATA_BITS_6;
        !           536:                break;
        !           537:        case CS7:
        !           538:                data |= LCR_DATA_BITS_7;
        !           539:                break;
        !           540:        case CS8:
        !           541:                data |= LCR_DATA_BITS_8;
        !           542:                break;
        !           543:        }
        !           544:
        !           545:        umct_set_baudrate(sc, t->c_ospeed);
        !           546:
        !           547:        sc->last_lcr = data;
        !           548:        umct_set_lcr(sc, data);
        !           549:
        !           550:        return (0);
        !           551: }
        !           552:
        !           553: int
        !           554: umct_open(void *addr, int portno)
        !           555: {
        !           556:        struct umct_softc *sc = addr;
        !           557:        int err, lcr_data;
        !           558:
        !           559:        if (sc->sc_dying)
        !           560:                return (EIO);
        !           561:
        !           562:        DPRINTF(("umct_open: sc=%p\n", sc));
        !           563:
        !           564:        /* initialize LCR */
        !           565:         lcr_data = LCR_DATA_BITS_8 | LCR_PARITY_NONE |
        !           566:            LCR_STOP_BITS_1;
        !           567:         umct_set_lcr(sc, lcr_data);
        !           568:
        !           569:        if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
        !           570:                sc->sc_status = 0; /* clear status bit */
        !           571:                sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
        !           572:                err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_intr_number,
        !           573:                        USBD_SHORT_XFER_OK, &sc->sc_intr_pipe, sc,
        !           574:                        sc->sc_intr_buf, sc->sc_isize,
        !           575:                        umct_intr, USBD_DEFAULT_INTERVAL);
        !           576:                if (err) {
        !           577:                        DPRINTF(("%s: cannot open interrupt pipe (addr %d)\n",
        !           578:                                sc->sc_dev.dv_xname, sc->sc_intr_number));
        !           579:                                        return (EIO);
        !           580:                }
        !           581:        }
        !           582:
        !           583:        return (0);
        !           584: }
        !           585:
        !           586: void
        !           587: umct_close(void *addr, int portno)
        !           588: {
        !           589:        struct umct_softc *sc = addr;
        !           590:        int err;
        !           591:
        !           592:        if (sc->sc_dying)
        !           593:                return;
        !           594:
        !           595:        DPRINTF(("umct_close: close\n"));
        !           596:
        !           597:        if (sc->sc_intr_pipe != NULL) {
        !           598:                err = usbd_abort_pipe(sc->sc_intr_pipe);
        !           599:                if (err)
        !           600:                        printf("%s: abort interrupt pipe failed: %s\n",
        !           601:                                sc->sc_dev.dv_xname, usbd_errstr(err));
        !           602:                err = usbd_close_pipe(sc->sc_intr_pipe);
        !           603:                if (err)
        !           604:                        printf("%s: close interrupt pipe failed: %s\n",
        !           605:                                sc->sc_dev.dv_xname, usbd_errstr(err));
        !           606:                free(sc->sc_intr_buf, M_USBDEV);
        !           607:                sc->sc_intr_pipe = NULL;
        !           608:        }
        !           609: }
        !           610:
        !           611: void
        !           612: umct_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
        !           613: {
        !           614:        struct umct_softc *sc = priv;
        !           615:        u_char *buf = sc->sc_intr_buf;
        !           616:        u_char mstatus;
        !           617:
        !           618:        if (sc->sc_dying)
        !           619:                return;
        !           620:
        !           621:        if (status != USBD_NORMAL_COMPLETION) {
        !           622:                if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
        !           623:                        return;
        !           624:
        !           625:                DPRINTF(("%s: abnormal status: %s\n", sc->sc_dev.dv_xname,
        !           626:                        usbd_errstr(status)));
        !           627:                usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
        !           628:                return;
        !           629:        }
        !           630:
        !           631:        DPRINTF(("%s: umct status = MSR:%02x, LSR:%02x\n",
        !           632:                 sc->sc_dev.dv_xname, buf[0],buf[1]));
        !           633:
        !           634:        sc->sc_lsr = sc->sc_msr = 0;
        !           635:        mstatus = buf[0];
        !           636:        if (ISSET(mstatus, MSR_DSR))
        !           637:                sc->sc_msr |= UMSR_DSR;
        !           638:        if (ISSET(mstatus, MSR_DCD))
        !           639:                sc->sc_msr |= UMSR_DCD;
        !           640:        ucom_status_change((struct ucom_softc *)sc->sc_subdev);
        !           641: }
        !           642:
        !           643: void
        !           644: umct_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
        !           645: {
        !           646:        struct umct_softc *sc = addr;
        !           647:
        !           648:        DPRINTF(("umct_get_status:\n"));
        !           649:
        !           650:        if (lsr != NULL)
        !           651:                *lsr = sc->sc_lsr;
        !           652:        if (msr != NULL)
        !           653:                *msr = sc->sc_msr;
        !           654: }

CVSweb