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

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

1.1     ! nbrk        1: /*     $OpenBSD: ucycom.c,v 1.11 2007/06/14 10:11:15 mbalmer Exp $     */
        !             2: /*     $NetBSD: ucycom.c,v 1.3 2005/08/05 07:27:47 skrll Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 2005 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Nick Hudson
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. All advertising materials mentioning features or use of this software
        !            20:  *    must display the following acknowledgement:
        !            21:  *     This product includes software developed by the NetBSD
        !            22:  *     Foundation, Inc. and its contributors.
        !            23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            24:  *    contributors may be used to endorse or promote products derived
        !            25:  *    from this software without specific prior written permission.
        !            26:  *
        !            27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            37:  * POSSIBILITY OF SUCH DAMAGE.
        !            38:  */
        !            39: /*
        !            40:  * This code is based on the ucom driver.
        !            41:  */
        !            42:
        !            43: /*
        !            44:  * Device driver for Cypress CY7C637xx and CY7C640/1xx series USB to
        !            45:  * RS232 bridges.
        !            46:  */
        !            47:
        !            48: #include <sys/param.h>
        !            49: #include <sys/systm.h>
        !            50: #include <sys/conf.h>
        !            51: #include <sys/kernel.h>
        !            52: #include <sys/malloc.h>
        !            53: #include <sys/device.h>
        !            54: #include <sys/sysctl.h>
        !            55: #include <sys/tty.h>
        !            56: #include <sys/file.h>
        !            57: #include <sys/vnode.h>
        !            58:
        !            59: #include <dev/usb/usb.h>
        !            60: #include <dev/usb/usbhid.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/uhidev.h>
        !            66: #include <dev/usb/hid.h>
        !            67:
        !            68: #include <dev/usb/ucomvar.h>
        !            69:
        !            70: #ifdef UCYCOM_DEBUG
        !            71: #define DPRINTF(x)     if (ucycomdebug) printf x
        !            72: #define DPRINTFN(n, x) if (ucycomdebug > (n)) printf x
        !            73: int    ucycomdebug = 200;
        !            74: #else
        !            75: #define DPRINTF(x)
        !            76: #define DPRINTFN(n,x)
        !            77: #endif
        !            78:
        !            79: /* Configuration Byte */
        !            80: #define UCYCOM_RESET           0x80
        !            81: #define UCYCOM_PARITY_TYPE_MASK        0x20
        !            82: #define  UCYCOM_PARITY_ODD      0x20
        !            83: #define  UCYCOM_PARITY_EVEN     0x00
        !            84: #define UCYCOM_PARITY_MASK     0x10
        !            85: #define  UCYCOM_PARITY_ON       0x10
        !            86: #define  UCYCOM_PARITY_OFF      0x00
        !            87: #define UCYCOM_STOP_MASK       0x08
        !            88: #define  UCYCOM_STOP_BITS_2     0x08
        !            89: #define  UCYCOM_STOP_BITS_1     0x00
        !            90: #define UCYCOM_DATA_MASK       0x03
        !            91: #define  UCYCOM_DATA_BITS_8     0x03
        !            92: #define  UCYCOM_DATA_BITS_7     0x02
        !            93: #define  UCYCOM_DATA_BITS_6     0x01
        !            94: #define  UCYCOM_DATA_BITS_5     0x00
        !            95:
        !            96: /* Modem (Input) status byte */
        !            97: #define UCYCOM_RI      0x80
        !            98: #define UCYCOM_DCD     0x40
        !            99: #define UCYCOM_DSR     0x20
        !           100: #define UCYCOM_CTS     0x10
        !           101: #define UCYCOM_ERROR   0x08
        !           102: #define UCYCOM_LMASK   0x07
        !           103:
        !           104: /* Modem (Output) control byte */
        !           105: #define UCYCOM_DTR     0x20
        !           106: #define UCYCOM_RTS     0x10
        !           107: #define UCYCOM_ORESET  0x08
        !           108:
        !           109: struct ucycom_softc {
        !           110:        struct uhidev            sc_hdev;
        !           111:        usbd_device_handle       sc_udev;
        !           112:
        !           113:        /* uhidev parameters */
        !           114:        size_t                   sc_flen;       /* feature report length */
        !           115:        size_t                   sc_ilen;       /* input report length */
        !           116:        size_t                   sc_olen;       /* output report length */
        !           117:
        !           118:        uint8_t                 *sc_obuf;
        !           119:
        !           120:        uint8_t                 *sc_ibuf;
        !           121:        uint32_t                 sc_icnt;
        !           122:
        !           123:        /* settings */
        !           124:        uint32_t                 sc_baud;
        !           125:        uint8_t                  sc_cfg;        /* Data format */
        !           126:        uint8_t                  sc_mcr;        /* Modem control */
        !           127:        uint8_t                  sc_msr;        /* Modem status */
        !           128:        uint8_t                  sc_newmsr;     /* from HID intr */
        !           129:        int                      sc_swflags;
        !           130:
        !           131:        struct device           *sc_subdev;
        !           132:
        !           133:        /* flags */
        !           134:        u_char                   sc_dying;
        !           135: };
        !           136:
        !           137: /* Callback routines */
        !           138: void   ucycom_set(void *, int, int, int);
        !           139: int    ucycom_param(void *, int, struct termios *);
        !           140: void   ucycom_get_status(void *, int, u_char *, u_char *);
        !           141: int    ucycom_open(void *, int);
        !           142: void   ucycom_close(void *, int);
        !           143: void   ucycom_write(void *, int, u_char *, u_char *, u_int32_t *);
        !           144: void   ucycom_read(void *, int, u_char **, u_int32_t *);
        !           145:
        !           146: struct ucom_methods ucycom_methods = {
        !           147:        NULL, /* ucycom_get_status, */
        !           148:        ucycom_set,
        !           149:        ucycom_param,
        !           150:        NULL,
        !           151:        ucycom_open,
        !           152:        ucycom_close,
        !           153:        ucycom_read,
        !           154:        ucycom_write,
        !           155: };
        !           156:
        !           157: void ucycom_intr(struct uhidev *, void *, u_int);
        !           158:
        !           159: void ucycom_get_cfg(struct ucycom_softc *);
        !           160:
        !           161: const struct usb_devno ucycom_devs[] = {
        !           162:        { USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_USBRS232 },
        !           163:        { USB_VENDOR_DELORME, USB_PRODUCT_DELORME_EMUSB },
        !           164:        { USB_VENDOR_DELORME, USB_PRODUCT_DELORME_EMLT20 },
        !           165: };
        !           166: #define ucycom_lookup(v, p) usb_lookup(ucycom_devs, v, p)
        !           167:
        !           168: int ucycom_match(struct device *, void *, void *);
        !           169: void ucycom_attach(struct device *, struct device *, void *);
        !           170: int ucycom_detach(struct device *, int);
        !           171: int ucycom_activate(struct device *, enum devact);
        !           172:
        !           173: struct cfdriver ucycom_cd = {
        !           174:        NULL, "ucycom", DV_DULL
        !           175: };
        !           176:
        !           177: const struct cfattach ucycom_ca = {
        !           178:        sizeof(struct ucycom_softc),
        !           179:        ucycom_match,
        !           180:        ucycom_attach,
        !           181:        ucycom_detach,
        !           182:        ucycom_activate,
        !           183: };
        !           184:
        !           185: int
        !           186: ucycom_match(struct device *parent, void *match, void *aux)
        !           187: {
        !           188:        struct uhidev_attach_arg *uha = aux;
        !           189:
        !           190:        DPRINTF(("ucycom match\n"));
        !           191:        return (ucycom_lookup(uha->uaa->vendor, uha->uaa->product) != NULL ?
        !           192:            UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
        !           193: }
        !           194:
        !           195: void
        !           196: ucycom_attach(struct device *parent, struct device *self, void *aux)
        !           197: {
        !           198:        struct ucycom_softc *sc = (struct ucycom_softc *)self;
        !           199:        struct usb_attach_arg *uaa = aux;
        !           200:        struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
        !           201:        usbd_device_handle dev = uha->parent->sc_udev;
        !           202:        struct ucom_attach_args uca;
        !           203:        int size, repid, err;
        !           204:        void *desc;
        !           205:
        !           206:        sc->sc_hdev.sc_intr = ucycom_intr;
        !           207:        sc->sc_hdev.sc_parent = uha->parent;
        !           208:        sc->sc_hdev.sc_report_id = uha->reportid;
        !           209:
        !           210:        uhidev_get_report_desc(uha->parent, &desc, &size);
        !           211:        repid = uha->reportid;
        !           212:        sc->sc_ilen = hid_report_size(desc, size, hid_input, repid);
        !           213:        sc->sc_olen = hid_report_size(desc, size, hid_output, repid);
        !           214:        sc->sc_flen = hid_report_size(desc, size, hid_feature, repid);
        !           215:
        !           216:        DPRINTF(("ucycom_open: olen %d ilen %d flen %d\n", sc->sc_ilen,
        !           217:            sc->sc_olen, sc->sc_flen));
        !           218:
        !           219:        printf("\n");
        !           220:
        !           221:        sc->sc_udev = dev;
        !           222:
        !           223:        sc->sc_msr = sc->sc_mcr = 0;
        !           224:
        !           225:        err = uhidev_open(&sc->sc_hdev);
        !           226:        if (err) {
        !           227:                DPRINTF(("ucycom_open: uhidev_open %d\n", err));
        !           228:                return;
        !           229:        }
        !           230:
        !           231:        DPRINTF(("ucycom attach: sc %p opipe %p ipipe %p report_id %d\n",
        !           232:            sc, sc->sc_hdev.sc_parent->sc_opipe, sc->sc_hdev.sc_parent->sc_ipipe,
        !           233:            uha->reportid));
        !           234:
        !           235:        /* bulkin, bulkout set above */
        !           236:        bzero(&uca, sizeof uca);
        !           237:        uca.bulkin = uca.bulkout = -1;
        !           238:        uca.uhidev = sc->sc_hdev.sc_parent;
        !           239:        uca.ibufsize = sc->sc_ilen - 1;
        !           240:        uca.obufsize = sc->sc_olen - 1;
        !           241:        uca.ibufsizepad = 1;
        !           242:        uca.opkthdrlen = 0;
        !           243:        uca.device = uaa->device;
        !           244:        uca.iface = uaa->iface;
        !           245:        uca.methods = &ucycom_methods;
        !           246:        uca.arg = sc;
        !           247:        uca.info = NULL;
        !           248:
        !           249:        usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
        !           250:                           &sc->sc_hdev.sc_dev);
        !           251:
        !           252:        sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
        !           253:        DPRINTF(("ucycom_attach: complete %p\n", sc->sc_subdev));
        !           254: }
        !           255:
        !           256: void
        !           257: ucycom_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
        !           258: {
        !           259:        struct ucycom_softc *sc = addr;
        !           260:
        !           261:        DPRINTF(("ucycom_get_status:\n"));
        !           262:
        !           263: #if 0
        !           264:        if (lsr != NULL)
        !           265:                *lsr = sc->sc_lsr;
        !           266: #endif
        !           267:        if (msr != NULL)
        !           268:                *msr = sc->sc_msr;
        !           269: }
        !           270:
        !           271: int
        !           272: ucycom_open(void *addr, int portno)
        !           273: {
        !           274:        struct ucycom_softc *sc = addr;
        !           275:        struct termios t;
        !           276:        int err;
        !           277:
        !           278:        DPRINTF(("ucycom_open: complete\n"));
        !           279:
        !           280:        if (sc->sc_dying)
        !           281:                return (EIO);
        !           282:
        !           283:        /* Allocate an output report buffer */
        !           284:        sc->sc_obuf = malloc(sc->sc_olen, M_USBDEV, M_WAITOK);
        !           285:
        !           286:        /* Allocate an input report buffer */
        !           287:        sc->sc_ibuf = malloc(sc->sc_ilen, M_USBDEV, M_WAITOK);
        !           288:
        !           289:        DPRINTF(("ucycom_open: sc->sc_ibuf=%p sc->sc_obuf=%p \n",
        !           290:            sc->sc_ibuf, sc->sc_obuf));
        !           291:
        !           292:        t.c_ospeed = 9600;
        !           293:        t.c_cflag = CSTOPB | CS8;
        !           294:        (void)ucycom_param(sc, portno, &t);
        !           295:
        !           296:        sc->sc_mcr = UCYCOM_DTR | UCYCOM_RTS;
        !           297:        memset(sc->sc_obuf, 0, sc->sc_olen);
        !           298:        sc->sc_obuf[0] = sc->sc_mcr;
        !           299:        err = uhidev_write(sc->sc_hdev.sc_parent, sc->sc_obuf, sc->sc_olen);
        !           300:        if (err) {
        !           301:                DPRINTF(("ucycom_open: set RTS err=%d\n", err));
        !           302:                return (EIO);
        !           303:        }
        !           304:
        !           305:        return (0);
        !           306: }
        !           307:
        !           308: void
        !           309: ucycom_close(void *addr, int portno)
        !           310: {
        !           311:        struct ucycom_softc *sc = addr;
        !           312:        int s;
        !           313:
        !           314:        if (sc->sc_dying)
        !           315:                return;
        !           316:
        !           317:        s = splusb();
        !           318:        if (sc->sc_obuf != NULL) {
        !           319:                free(sc->sc_obuf, M_USBDEV);
        !           320:                sc->sc_obuf = NULL;
        !           321:        }
        !           322:        if (sc->sc_ibuf != NULL) {
        !           323:                free(sc->sc_ibuf, M_USBDEV);
        !           324:                sc->sc_ibuf = NULL;
        !           325:        }
        !           326:        splx(s);
        !           327: }
        !           328:
        !           329: void
        !           330: ucycom_read(void *addr, int portno, u_char **ptr, u_int32_t *count)
        !           331: {
        !           332:        struct ucycom_softc *sc = addr;
        !           333:
        !           334:        if (sc->sc_newmsr ^ sc->sc_msr) {
        !           335:                DPRINTF(("ucycom_read: msr %d new %d\n",
        !           336:                    sc->sc_msr, sc->sc_newmsr));
        !           337:                sc->sc_msr = sc->sc_newmsr;
        !           338:                ucom_status_change((struct ucom_softc *)sc->sc_subdev);
        !           339:        }
        !           340:
        !           341:        DPRINTF(("ucycom_read: buf %p chars %d\n", sc->sc_ibuf, sc->sc_icnt));
        !           342:        *ptr = sc->sc_ibuf;
        !           343:        *count = sc->sc_icnt;
        !           344: }
        !           345:
        !           346: void
        !           347: ucycom_write(void *addr, int portno, u_char *to, u_char *data, u_int32_t *cnt)
        !           348: {
        !           349:        struct ucycom_softc *sc = addr;
        !           350:        u_int32_t len;
        !           351: #ifdef UCYCOM_DEBUG
        !           352:        u_int32_t want = *cnt;
        !           353: #endif
        !           354:
        !           355:        /*
        !           356:         * The 8 byte output report uses byte 0 for control and byte
        !           357:         * count.
        !           358:         *
        !           359:         * The 32 byte output report uses byte 0 for control. Byte 1
        !           360:         * is used for byte count.
        !           361:         */
        !           362:        len = sc->sc_olen;
        !           363:        memset(to, 0, len);
        !           364:        switch (sc->sc_olen) {
        !           365:        case 8:
        !           366:                to[0] = *cnt | sc->sc_mcr;
        !           367:                memcpy(&to[1], data, *cnt);
        !           368:                DPRINTF(("ucycomstart(8): to[0] = %d | %d = %d\n",
        !           369:                    *cnt, sc->sc_mcr, to[0]));
        !           370:                break;
        !           371:
        !           372:        case 32:
        !           373:                to[0] = sc->sc_mcr;
        !           374:                to[1] = *cnt;
        !           375:                memcpy(&to[2], data, *cnt);
        !           376:                DPRINTF(("ucycomstart(32): to[0] = %d\nto[1] = %d\n",
        !           377:                    to[0], to[1]));
        !           378:                break;
        !           379:        }
        !           380:
        !           381: #ifdef UCYCOM_DEBUG
        !           382:        if (ucycomdebug > 5) {
        !           383:                int i;
        !           384:
        !           385:                if (len != 0) {
        !           386:                        DPRINTF(("ucycomstart: to[0..%d) =", len-1));
        !           387:                        for (i = 0; i < len; i++)
        !           388:                                DPRINTF((" %02x", to[i]));
        !           389:                        DPRINTF(("\n"));
        !           390:                }
        !           391:        }
        !           392: #endif
        !           393:        *cnt = len;
        !           394:
        !           395: #if 0
        !           396:        ucycom_get_cfg(sc);
        !           397: #endif
        !           398:        DPRINTFN(4,("ucycomstart: req %d chars did %d chars\n", want, len));
        !           399: }
        !           400:
        !           401: int
        !           402: ucycom_param(void *addr, int portno, struct termios *t)
        !           403: {
        !           404:        struct ucycom_softc *sc = addr;
        !           405:        uint8_t report[5];
        !           406:        uint32_t baud = 0;
        !           407:        uint8_t cfg;
        !           408:        int err;
        !           409:
        !           410:        if (sc->sc_dying)
        !           411:                return (EIO);
        !           412:
        !           413:        switch (t->c_ospeed) {
        !           414:        case 600:
        !           415:        case 1200:
        !           416:        case 2400:
        !           417:        case 4800:
        !           418:        case 9600:
        !           419:        case 19200:
        !           420:        case 38400:
        !           421:        case 57600:
        !           422: #if 0
        !           423:        /*
        !           424:         * Stock chips only support standard baud rates in the 600 - 57600
        !           425:         * range, but higher rates can be achieved using custom firmware.
        !           426:         */
        !           427:        case 115200:
        !           428:        case 153600:
        !           429:        case 192000:
        !           430: #endif
        !           431:                baud = t->c_ospeed;
        !           432:                break;
        !           433:        default:
        !           434:                return (EINVAL);
        !           435:        }
        !           436:
        !           437:        if (t->c_cflag & CIGNORE) {
        !           438:                cfg = sc->sc_cfg;
        !           439:        } else {
        !           440:                cfg = 0;
        !           441:                switch (t->c_cflag & CSIZE) {
        !           442:                case CS8:
        !           443:                        cfg |= UCYCOM_DATA_BITS_8;
        !           444:                        break;
        !           445:                case CS7:
        !           446:                        cfg |= UCYCOM_DATA_BITS_7;
        !           447:                        break;
        !           448:                case CS6:
        !           449:                        cfg |= UCYCOM_DATA_BITS_6;
        !           450:                        break;
        !           451:                case CS5:
        !           452:                        cfg |= UCYCOM_DATA_BITS_5;
        !           453:                        break;
        !           454:                default:
        !           455:                        return (EINVAL);
        !           456:                }
        !           457:                cfg |= ISSET(t->c_cflag, CSTOPB) ?
        !           458:                    UCYCOM_STOP_BITS_2 : UCYCOM_STOP_BITS_1;
        !           459:                cfg |= ISSET(t->c_cflag, PARENB) ?
        !           460:                    UCYCOM_PARITY_ON : UCYCOM_PARITY_OFF;
        !           461:                cfg |= ISSET(t->c_cflag, PARODD) ?
        !           462:                    UCYCOM_PARITY_ODD : UCYCOM_PARITY_EVEN;
        !           463:        }
        !           464:
        !           465:        DPRINTF(("ucycom_param: setting %d baud, %d-%c-%d (%d)\n", baud,
        !           466:            5 + (cfg & UCYCOM_DATA_MASK),
        !           467:            (cfg & UCYCOM_PARITY_MASK) ?
        !           468:                ((cfg & UCYCOM_PARITY_TYPE_MASK) ? 'O' : 'E') : 'N',
        !           469:            (cfg & UCYCOM_STOP_MASK) ? 2 : 1, cfg));
        !           470:
        !           471:        report[0] = baud & 0xff;
        !           472:        report[1] = (baud >> 8) & 0xff;
        !           473:        report[2] = (baud >> 16) & 0xff;
        !           474:        report[3] = (baud >> 24) & 0xff;
        !           475:        report[4] = cfg;
        !           476:        err = uhidev_set_report(&sc->sc_hdev, UHID_FEATURE_REPORT,
        !           477:            report, sc->sc_flen);
        !           478:        if (err != 0) {
        !           479:                DPRINTF(("ucycom_param: uhidev_set_report %d %s\n",
        !           480:                    err, usbd_errstr(err)));
        !           481:                return EIO;
        !           482:        }
        !           483:        sc->sc_baud = baud;
        !           484:        return (err);
        !           485: }
        !           486:
        !           487: void
        !           488: ucycom_intr(struct uhidev *addr, void *ibuf, u_int len)
        !           489: {
        !           490:        extern void ucomreadcb(usbd_xfer_handle, usbd_private_handle, usbd_status);
        !           491:        struct ucycom_softc *sc = (struct ucycom_softc *)addr;
        !           492:        uint8_t *cp = ibuf;
        !           493:        int n, st, s;
        !           494:
        !           495:        /* not accepting data anymore.. */
        !           496:        if (sc->sc_ibuf == NULL)
        !           497:                return;
        !           498:
        !           499:        /* We understand 8 byte and 32 byte input records */
        !           500:        switch (len) {
        !           501:        case 8:
        !           502:                n = cp[0] & UCYCOM_LMASK;
        !           503:                st = cp[0] & ~UCYCOM_LMASK;
        !           504:                cp++;
        !           505:                break;
        !           506:
        !           507:        case 32:
        !           508:                st = cp[0];
        !           509:                n = cp[1];
        !           510:                cp += 2;
        !           511:                break;
        !           512:
        !           513:        default:
        !           514:                DPRINTFN(3,("ucycom_intr: Unknown input report length\n"));
        !           515:                return;
        !           516:        }
        !           517:
        !           518: #ifdef UCYCOM_DEBUG
        !           519:        if (ucycomdebug > 5) {
        !           520:                u_int32_t i;
        !           521:
        !           522:                if (n != 0) {
        !           523:                        DPRINTF(("ucycom_intr: ibuf[0..%d) =", n));
        !           524:                        for (i = 0; i < n; i++)
        !           525:                                DPRINTF((" %02x", cp[i]));
        !           526:                        DPRINTF(("\n"));
        !           527:                }
        !           528:        }
        !           529: #endif
        !           530:
        !           531:        if (n > 0 || st != sc->sc_msr) {
        !           532:                s = spltty();
        !           533:                sc->sc_newmsr = st;
        !           534:                bcopy(cp, sc->sc_ibuf, n);
        !           535:                sc->sc_icnt = n;
        !           536:                ucomreadcb(addr->sc_parent->sc_ixfer, sc->sc_subdev,
        !           537:                    USBD_NORMAL_COMPLETION);
        !           538:                splx(s);
        !           539:        }
        !           540: }
        !           541:
        !           542: void
        !           543: ucycom_set(void *addr, int portno, int reg, int onoff)
        !           544: {
        !           545:        struct ucycom_softc *sc = addr;
        !           546:        int err;
        !           547:
        !           548:        switch (reg) {
        !           549:        case UCOM_SET_DTR:
        !           550:                if (onoff)
        !           551:                        SET(sc->sc_mcr, UCYCOM_DTR);
        !           552:                else
        !           553:                        CLR(sc->sc_mcr, UCYCOM_DTR);
        !           554:                break;
        !           555:        case UCOM_SET_RTS:
        !           556:                if (onoff)
        !           557:                        SET(sc->sc_mcr, UCYCOM_RTS);
        !           558:                else
        !           559:                        CLR(sc->sc_mcr, UCYCOM_RTS);
        !           560:                break;
        !           561:        case UCOM_SET_BREAK:
        !           562:                break;
        !           563:        }
        !           564:
        !           565:        memset(sc->sc_obuf, 0, sc->sc_olen);
        !           566:        sc->sc_obuf[0] = sc->sc_mcr;
        !           567:
        !           568:        err = uhidev_write(sc->sc_hdev.sc_parent, sc->sc_obuf, sc->sc_olen);
        !           569:        if (err)
        !           570:                DPRINTF(("ucycom_set_status: err=%d\n", err));
        !           571: }
        !           572:
        !           573: void
        !           574: ucycom_get_cfg(struct ucycom_softc *sc)
        !           575: {
        !           576:        int err, cfg, baud;
        !           577:        uint8_t report[5];
        !           578:
        !           579:        err = uhidev_get_report(&sc->sc_hdev, UHID_FEATURE_REPORT,
        !           580:            report, sc->sc_flen);
        !           581:        cfg = report[4];
        !           582:        baud = (report[3] << 24) + (report[2] << 16) + (report[1] << 8) + report[0];
        !           583:        DPRINTF(("ucycom_configure: device reports %d baud, %d-%c-%d (%d)\n", baud,
        !           584:            5 + (cfg & UCYCOM_DATA_MASK),
        !           585:            (cfg & UCYCOM_PARITY_MASK) ?
        !           586:                ((cfg & UCYCOM_PARITY_TYPE_MASK) ? 'O' : 'E') : 'N',
        !           587:            (cfg & UCYCOM_STOP_MASK) ? 2 : 1, cfg));
        !           588: }
        !           589:
        !           590: int
        !           591: ucycom_detach(struct device *self, int flags)
        !           592: {
        !           593:        struct ucycom_softc *sc = (struct ucycom_softc *)self;
        !           594:
        !           595:        DPRINTF(("ucycom_detach: sc=%p flags=%d\n", sc, flags));
        !           596:        sc->sc_dying = 1;
        !           597:        if (sc->sc_subdev != NULL) {
        !           598:                config_detach(sc->sc_subdev, flags);
        !           599:                sc->sc_subdev = NULL;
        !           600:        }
        !           601:        return (0);
        !           602: }
        !           603:
        !           604: int
        !           605: ucycom_activate(struct device *self, enum devact act)
        !           606: {
        !           607:        struct ucycom_softc *sc = (struct ucycom_softc *)self;
        !           608:        int rv = 0;
        !           609:
        !           610:        DPRINTFN(5,("ucycom_activate: %d\n", act));
        !           611:
        !           612:        switch (act) {
        !           613:        case DVACT_ACTIVATE:
        !           614:                break;
        !           615:
        !           616:        case DVACT_DEACTIVATE:
        !           617:                if (sc->sc_subdev != NULL)
        !           618:                        rv = config_deactivate(sc->sc_subdev);
        !           619:                sc->sc_dying = 1;
        !           620:                break;
        !           621:        }
        !           622:        return (rv);
        !           623: }

CVSweb