[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

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