[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

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