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

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

1.1       nbrk        1: /*     $OpenBSD: if_cdcef.c,v 1.17 2007/06/14 06:55:10 mbalmer Exp $   */
                      2:
                      3: /*
                      4:  * Copyright (c) 2007 Dale Rahn <drahn@openbsd.org>
                      5:  * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
                      6:  *
                      7:  * Permission to use, copy, modify, and distribute this software for any
                      8:  * purpose with or without fee is hereby granted, provided that the above
                      9:  * copyright notice and this permission notice appear in all copies.
                     10:  *
                     11:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     13:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     15:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     16:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     17:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     18:  */
                     19:
                     20: /*
                     21:  * USB Communication Device Class Ethernet Emulation Model function driver
                     22:  * (counterpart of the host-side cdce(4) driver)
                     23:  */
                     24: #include <bpfilter.h>
                     25:
                     26:
                     27: #include <sys/param.h>
                     28: #include <sys/device.h>
                     29: #include <sys/socket.h>
                     30: #include <sys/systm.h>
                     31: #include <sys/mbuf.h>
                     32: #include <sys/timeout.h>
                     33:
                     34: #include <net/if.h>
                     35:
                     36: #include <dev/usb/usb.h>
                     37: #include <dev/usb/usbdi.h>
                     38: #include <dev/usb/usbf.h>
                     39: #include <dev/usb/usbcdc.h>
                     40:
                     41: #if NBPFILTER > 0
                     42: #include <net/bpf.h>
                     43: #endif
                     44:
                     45: #include <netinet/in.h>
                     46: #include <netinet/in_systm.h>
                     47: #include <netinet/in_var.h>
                     48: #include <netinet/ip.h>
                     49: #include <netinet/if_ether.h>
                     50:
                     51:
                     52: #define CDCEF_VENDOR_ID                0x0001
                     53: #define CDCEF_PRODUCT_ID       0x0001
                     54: #define CDCEF_DEVICE_CODE      0x0100
                     55: #define CDCEF_VENDOR_STRING    "OpenBSD.org"
                     56: #define CDCEF_PRODUCT_STRING   "CDC Ethernet Emulation"
                     57: #define CDCEF_SERIAL_STRING    "1.00"
                     58:
                     59: #define CDCEF_BUFSZ            1600
                     60:
                     61:
                     62: struct cdcef_softc {
                     63:        struct usbf_function    sc_dev;
                     64:        usbf_config_handle      sc_config;
                     65:        usbf_interface_handle   sc_iface;
                     66:        usbf_endpoint_handle    sc_ep_in;
                     67:        usbf_endpoint_handle    sc_ep_out;
                     68:        usbf_pipe_handle        sc_pipe_in;
                     69:        usbf_pipe_handle        sc_pipe_out;
                     70:        usbf_xfer_handle        sc_xfer_in;
                     71:        usbf_xfer_handle        sc_xfer_out;
                     72:        void                    *sc_buffer_in;
                     73:        void                    *sc_buffer_out;
                     74:
                     75:        struct timeout          start_to;
                     76:
                     77:        struct mbuf             *sc_xmit_mbuf;
                     78:
                     79:        struct arpcom           sc_arpcom;
                     80: #define GET_IFP(sc) (&(sc)->sc_arpcom.ac_if)
                     81:
                     82:        int                     sc_rxeof_errors;
                     83:        int                     sc_unit;
                     84:        int                     sc_attached;
                     85:        int                     sc_listening;
                     86: };
                     87:
                     88: int            cdcef_match(struct device *, void *, void *);
                     89: void           cdcef_attach(struct device *, struct device *, void *);
                     90:
                     91: usbf_status    cdcef_do_request(usbf_function_handle,
                     92:                                 usb_device_request_t *, void **);
                     93:
                     94: void           cdcef_start(struct ifnet *);
                     95:
                     96: void           cdcef_txeof(usbf_xfer_handle, usbf_private_handle,
                     97:                            usbf_status);
                     98: void           cdcef_rxeof(usbf_xfer_handle, usbf_private_handle,
                     99:                            usbf_status);
                    100: int            cdcef_ioctl(struct ifnet *ifp, u_long command, caddr_t data);
                    101: void           cdcef_watchdog(struct ifnet *ifp);
                    102: void           cdcef_init(struct cdcef_softc *);
                    103: void           cdcef_stop(struct cdcef_softc *);
                    104: int            cdcef_encap(struct cdcef_softc *sc, struct mbuf *m, int idx);
                    105: struct mbuf *  cdcef_newbuf(void);
                    106: void           cdcef_start_timeout (void *);
                    107:
                    108: struct cfattach cdcef_ca = {
                    109:        sizeof(struct cdcef_softc), cdcef_match, cdcef_attach
                    110: };
                    111:
                    112: struct cfdriver cdcef_cd = {
                    113:        NULL, "cdcef", DV_DULL
                    114: };
                    115:
                    116: struct usbf_function_methods cdcef_methods = {
                    117:        NULL,                   /* set_config */
                    118:        cdcef_do_request
                    119: };
                    120:
                    121: #ifndef CDCEF_DEBUG
                    122: #define DPRINTF(x)     do {} while (0)
                    123: #else
                    124: #define DPRINTF(x)     printf x
                    125: #endif
                    126:
                    127: #define DEVNAME(sc)    ((sc)->sc_dev.bdev.dv_xname)
                    128:
                    129: /*
                    130:  * USB function match/attach/detach
                    131:  */
                    132:
                    133: int
                    134: cdcef_match(struct device *parent, void *match, void *aux)
                    135: {
                    136:        return UMATCH_GENERIC;
                    137: }
                    138:
                    139: void
                    140: cdcef_attach(struct device *parent, struct device *self, void *aux)
                    141: {
                    142:        struct cdcef_softc *sc = (struct cdcef_softc *)self;
                    143:        struct usbf_attach_arg *uaa = aux;
                    144:        usbf_device_handle dev = uaa->device;
                    145:        char *devinfop;
                    146:        struct ifnet *ifp;
                    147:        usbf_status err;
                    148:        usb_cdc_union_descriptor_t udesc;
                    149:        int s;
                    150:        u_int16_t macaddr_hi;
                    151:
                    152:
                    153:        /* Set the device identification according to the function. */
                    154:        usbf_devinfo_setup(dev, UDCLASS_IN_INTERFACE, 0, 0, CDCEF_VENDOR_ID,
                    155:            CDCEF_PRODUCT_ID, CDCEF_DEVICE_CODE, CDCEF_VENDOR_STRING,
                    156:            CDCEF_PRODUCT_STRING, CDCEF_SERIAL_STRING);
                    157:
                    158:        devinfop = usbf_devinfo_alloc(dev);
                    159:        printf(": %s\n", devinfop);
                    160:        usbf_devinfo_free(devinfop);
                    161:
                    162:        /* Fill in the fields needed by the parent device. */
                    163:        sc->sc_dev.methods = &cdcef_methods;
                    164:
                    165:        /* timeout to start delayed tranfers */
                    166:        timeout_set(&sc->start_to, cdcef_start_timeout, sc);
                    167:
                    168:        /*
                    169:         * Build descriptors according to the device class specification.
                    170:         */
                    171:        err = usbf_add_config(dev, &sc->sc_config);
                    172:        if (err) {
                    173:                printf("%s: usbf_add_config failed\n", DEVNAME(sc));
                    174:                return;
                    175:        }
                    176:        err = usbf_add_interface(sc->sc_config, UICLASS_CDC,
                    177:            UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, NULL,
                    178:            &sc->sc_iface);
                    179:        if (err) {
                    180:                printf("%s: usbf_add_interface failed\n", DEVNAME(sc));
                    181:                return;
                    182:        }
                    183:        /* XXX don't use hard-coded values 128 and 16. */
                    184:        err = usbf_add_endpoint(sc->sc_iface, UE_DIR_IN | 2, UE_BULK,
                    185:            64, 16, &sc->sc_ep_in) ||
                    186:            usbf_add_endpoint(sc->sc_iface, UE_DIR_OUT | 1, UE_BULK,
                    187:            64, 16, &sc->sc_ep_out);
                    188:        if (err) {
                    189:                printf("%s: usbf_add_endpoint failed\n", DEVNAME(sc));
                    190:                return;
                    191:        }
                    192:
                    193:        /* Append a CDC union descriptor. */
                    194:        bzero(&udesc, sizeof udesc);
                    195:        udesc.bLength = sizeof udesc;
                    196:        udesc.bDescriptorType = UDESC_CS_INTERFACE;
                    197:        udesc.bDescriptorSubtype = UDESCSUB_CDC_UNION;
                    198:        udesc.bSlaveInterface[0] = usbf_interface_number(sc->sc_iface);
                    199:        err = usbf_add_config_desc(sc->sc_config,
                    200:            (usb_descriptor_t *)&udesc, NULL);
                    201:        if (err) {
                    202:                printf("%s: usbf_add_config_desc failed\n", DEVNAME(sc));
                    203:                return;
                    204:        }
                    205:
                    206:        /*
                    207:         * Close the configuration and build permanent descriptors.
                    208:         */
                    209:        err = usbf_end_config(sc->sc_config);
                    210:        if (err) {
                    211:                printf("%s: usbf_end_config failed\n", DEVNAME(sc));
                    212:                return;
                    213:        }
                    214:
                    215:        /* Preallocate xfers and data buffers. */
                    216:        sc->sc_xfer_in = usbf_alloc_xfer(dev);
                    217:        sc->sc_xfer_out = usbf_alloc_xfer(dev);
                    218:        sc->sc_buffer_in = usbf_alloc_buffer(sc->sc_xfer_in,
                    219:            CDCEF_BUFSZ);
                    220:        sc->sc_buffer_out = usbf_alloc_buffer(sc->sc_xfer_out,
                    221:            CDCEF_BUFSZ);
                    222:        if (sc->sc_buffer_in == NULL || sc->sc_buffer_out == NULL) {
                    223:                printf("%s: usbf_alloc_buffer failed\n", DEVNAME(sc));
                    224:                return;
                    225:        }
                    226:
                    227:        /* Open the bulk pipes. */
                    228:        err = usbf_open_pipe(sc->sc_iface,
                    229:            usbf_endpoint_address(sc->sc_ep_out), &sc->sc_pipe_out) ||
                    230:            usbf_open_pipe(sc->sc_iface,
                    231:            usbf_endpoint_address(sc->sc_ep_in), &sc->sc_pipe_in);
                    232:        if (err) {
                    233:                printf("%s: usbf_open_pipe failed\n", DEVNAME(sc));
                    234:                return;
                    235:        }
                    236:
                    237:        /* Get ready to receive packets. */
                    238:        usbf_setup_xfer(sc->sc_xfer_out, sc->sc_pipe_out, sc,
                    239:            sc->sc_buffer_out, CDCEF_BUFSZ, USBD_SHORT_XFER_OK, 0, cdcef_rxeof);
                    240:        err = usbf_transfer(sc->sc_xfer_out);
                    241:        if (err && err != USBF_IN_PROGRESS) {
                    242:                printf("%s: usbf_transfer failed\n", DEVNAME(sc));
                    243:                return;
                    244:        }
                    245:
                    246:        s = splnet();
                    247:
                    248:        macaddr_hi = htons(0x2acb);
                    249:        bcopy(&macaddr_hi, &sc->sc_arpcom.ac_enaddr[0], sizeof(u_int16_t));
                    250:        bcopy(&ticks, &sc->sc_arpcom.ac_enaddr[2], sizeof(u_int32_t));
                    251:        sc->sc_arpcom.ac_enaddr[5] = (u_int8_t)(sc->sc_unit);
                    252:
                    253:        printf("%s: address %s\n", DEVNAME(sc),
                    254:            ether_sprintf(sc->sc_arpcom.ac_enaddr));
                    255:
                    256:        ifp = GET_IFP(sc);
                    257:        ifp->if_softc = sc;
                    258:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
                    259:        ifp->if_ioctl = cdcef_ioctl;
                    260:        ifp->if_start = cdcef_start;
                    261:        ifp->if_watchdog = cdcef_watchdog;
                    262:        strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
                    263:
                    264:        IFQ_SET_READY(&ifp->if_snd);
                    265:
                    266:        if_attach(ifp);
                    267:        ether_ifattach(ifp);
                    268:
                    269:        sc->sc_attached = 1;
                    270:        splx(s);
                    271: }
                    272:
                    273: usbf_status
                    274: cdcef_do_request(usbf_function_handle fun, usb_device_request_t *req,
                    275:     void **data)
                    276: {
                    277:        printf("cdcef_do_request\n");
                    278:        return USBF_STALLED;
                    279: }
                    280:
                    281: void
                    282: cdcef_start(struct ifnet *ifp)
                    283: {
                    284:        struct cdcef_softc      *sc = ifp->if_softc;
                    285:        struct mbuf             *m_head = NULL;
                    286:
                    287:        if(ifp->if_flags & IFF_OACTIVE)
                    288:                return;
                    289:
                    290:        IFQ_POLL(&ifp->if_snd, m_head);
                    291:        if (m_head == NULL) {
                    292:                return;
                    293:        }
                    294:
                    295:        if (sc->sc_listening == 0 || m_head->m_pkthdr.len > CDCEF_BUFSZ) {
                    296:                /*
                    297:                 * drop packet because reciever is not listening,
                    298:                 * or if packet is larger than xmit buffer
                    299:                 */
                    300:                IFQ_DEQUEUE(&ifp->if_snd, m_head);
                    301:                m_freem(m_head);
                    302:                return;
                    303:        }
                    304:
                    305:        if (cdcef_encap(sc, m_head, 0)) {
                    306:                ifp->if_flags |= IFF_OACTIVE;
                    307:                return;
                    308:        }
                    309:
                    310:        IFQ_DEQUEUE(&ifp->if_snd, m_head);
                    311:
                    312: #if NBPFILTER > 0
                    313:        if (ifp->if_bpf)
                    314:                bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
                    315: #endif
                    316:
                    317:        ifp->if_flags |= IFF_OACTIVE;
                    318:
                    319:        ifp->if_timer = 6;
                    320: }
                    321:
                    322: void
                    323: cdcef_txeof(usbf_xfer_handle xfer, usbf_private_handle priv,
                    324:     usbf_status err)
                    325: {
                    326:        struct cdcef_softc *sc = priv;
                    327:        struct ifnet *ifp = GET_IFP(sc);
                    328:        int s;
                    329:
                    330:        s = splnet();
                    331: #if 0
                    332:        printf("cdcef_txeof: xfer=%p, priv=%p, %s\n", xfer, priv,
                    333:            usbf_errstr(err));
                    334: #endif
                    335:
                    336:        ifp->if_timer = 0;
                    337:        ifp->if_flags &= ~IFF_OACTIVE;
                    338:
                    339:        if (sc->sc_xmit_mbuf != NULL) {
                    340:                m_freem(sc->sc_xmit_mbuf);
                    341:                sc->sc_xmit_mbuf = NULL;
                    342:        }
                    343:
                    344:        if (err)
                    345:                ifp->if_oerrors++;
                    346:        else
                    347:                ifp->if_opackets++;
                    348:
                    349:        if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
                    350:                timeout_add(&sc->start_to, 1); /* XXX  */
                    351:
                    352:        splx(s);
                    353: }
                    354: void
                    355: cdcef_start_timeout (void *v)
                    356: {
                    357:        struct cdcef_softc *sc = v;
                    358:        struct ifnet *ifp = GET_IFP(sc);
                    359:        int s;
                    360:
                    361:        s = splnet();
                    362:        cdcef_start(ifp);
                    363:        splx(s);
                    364: }
                    365:
                    366:
                    367: void
                    368: cdcef_rxeof(usbf_xfer_handle xfer, usbf_private_handle priv,
                    369:     usbf_status status)
                    370: {
                    371:        struct cdcef_softc      *sc = priv;
                    372:        int total_len = 0;
                    373:        struct ifnet            *ifp = GET_IFP(sc);
                    374:        struct mbuf             *m = NULL;
                    375:
                    376:
                    377:        int s;
                    378:
                    379: #if 0
                    380:        printf("cdcef_rxeof: xfer=%p, priv=%p, %s\n", xfer, priv,
                    381:            usbf_errstr(status));
                    382: #endif
                    383:
                    384:        if (status != USBF_NORMAL_COMPLETION) {
                    385:                if (status == USBF_NOT_STARTED || status == USBF_CANCELLED)
                    386:                        return;
                    387:                if (sc->sc_rxeof_errors == 0)
                    388:                        printf("%s: usb error on rx: %s\n",
                    389:                            DEVNAME(sc), usbf_errstr(status));
                    390:                /* XXX - no stalls on client */
                    391:                if (sc->sc_rxeof_errors++ > 10) {
                    392:                        printf("%s: too many errors, disabling\n",
                    393:                            DEVNAME(sc));
                    394:                        /* sc->sc_dying = 1; */
                    395:                        // return;
                    396:                }
                    397:                goto done;
                    398:        }
                    399:        sc->sc_rxeof_errors = 0;
                    400:
                    401:        /* upon first incoming packet we know the host is listening */
                    402:        if (sc->sc_listening == 0) {
                    403:                sc->sc_listening = 1;
                    404:        }
                    405:
                    406:
                    407:        usbf_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
                    408:
                    409:        /* total_len -= 4; Strip off CRC added for Zaurus - XXX*/
                    410:        if (total_len <= 1)
                    411:                goto done;
                    412:
                    413:        if (total_len < sizeof(struct ether_header)) {
                    414:                ifp->if_ierrors++;
                    415:                goto done;
                    416:        }
                    417:
                    418:        s = splnet();
                    419:        if (ifp->if_flags & IFF_RUNNING) {
                    420:                m = cdcef_newbuf();
                    421:                if (m == NULL) {
                    422:                        /* message? */
                    423:                        ifp->if_ierrors++;
                    424:                        goto done1;
                    425:                }
                    426:
                    427:                m->m_pkthdr.len = m->m_len = total_len;
                    428:                bcopy(sc->sc_buffer_out, mtod(m, char *), total_len);
                    429:                m->m_pkthdr.rcvif = ifp;
                    430:
                    431:                ifp->if_ipackets++;
                    432:
                    433: #if NBPFILTER > 0
                    434:                if (ifp->if_bpf)
                    435:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
                    436: #endif
                    437:
                    438:                ether_input_mbuf(ifp, m);
                    439:        }
                    440:
                    441: done1:
                    442:        splx(s);
                    443:
                    444: done:
                    445:        /* Setup another xfer. */
                    446:        usbf_setup_xfer(xfer, sc->sc_pipe_out, sc, sc->sc_buffer_out,
                    447:            CDCEF_BUFSZ, USBD_SHORT_XFER_OK, 0, cdcef_rxeof);
                    448:
                    449:        status = usbf_transfer(xfer);
                    450:        if (status && status != USBF_IN_PROGRESS) {
                    451:                printf("%s: usbf_transfer failed\n", DEVNAME(sc));
                    452:                return;
                    453:        }
                    454: }
                    455:
                    456: struct mbuf *
                    457: cdcef_newbuf(void)
                    458: {
                    459:        struct mbuf             *m;
                    460:
                    461:        MGETHDR(m, M_DONTWAIT, MT_DATA);
                    462:        if (m == NULL)
                    463:                return (NULL);
                    464:
                    465:        MCLGET(m, M_DONTWAIT);
                    466:        if (!(m->m_flags & M_EXT)) {
                    467:                m_freem(m);
                    468:                return (NULL);
                    469:        }
                    470:
                    471:        m->m_len = m->m_pkthdr.len = MCLBYTES;
                    472:        m_adj(m, ETHER_ALIGN);
                    473:
                    474:        return (m);
                    475: }
                    476:
                    477: int
                    478: cdcef_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
                    479: {
                    480:        struct cdcef_softc      *sc = ifp->if_softc;
                    481:        struct ifaddr           *ifa = (struct ifaddr *)data;
                    482:        struct ifreq            *ifr = (struct ifreq *)data;
                    483:        int                      s, error = 0;
                    484:
                    485:        s = splnet();
                    486:
                    487:        switch (command) {
                    488:        case SIOCSIFADDR:
                    489:                ifp->if_flags |= IFF_UP;
                    490:                cdcef_init(sc);
                    491:                switch (ifa->ifa_addr->sa_family) {
                    492:                case AF_INET:
                    493:                        arp_ifinit(&sc->sc_arpcom, ifa);
                    494:                        break;
                    495:                }
                    496:                break;
                    497:
                    498:        case SIOCSIFMTU:
                    499:                if (ifr->ifr_mtu > ETHERMTU)
                    500:                        error = EINVAL;
                    501:                else
                    502:                        ifp->if_mtu = ifr->ifr_mtu;
                    503:                break;
                    504:
                    505:        case SIOCSIFFLAGS:
                    506:                if (ifp->if_flags & IFF_UP) {
                    507:                        if (!(ifp->if_flags & IFF_RUNNING))
                    508:                                cdcef_init(sc);
                    509:                } else {
                    510:                        if (ifp->if_flags & IFF_RUNNING)
                    511:                                cdcef_stop(sc);
                    512:                }
                    513:                error = 0;
                    514:                break;
                    515:
                    516:        case SIOCADDMULTI:
                    517:        case SIOCDELMULTI:
                    518:                error = (command == SIOCADDMULTI) ?
                    519:                    ether_addmulti(ifr, &sc->sc_arpcom) :
                    520:                    ether_delmulti(ifr, &sc->sc_arpcom);
                    521:
                    522:                if (error == ENETRESET)
                    523:                        error = 0;
                    524:                break;
                    525:
                    526:        default:
                    527:                error = EINVAL;
                    528:                break;
                    529:        }
                    530:
                    531:        splx(s);
                    532:
                    533:        return (error);
                    534: }
                    535:
                    536: void
                    537: cdcef_watchdog(struct ifnet *ifp)
                    538: {
                    539:        struct cdcef_softc      *sc = ifp->if_softc;
                    540:        int s;
                    541:
                    542: #if 0
                    543:        if (sc->sc_dying)
                    544:                return;
                    545: #endif
                    546:
                    547:        ifp->if_oerrors++;
                    548:        printf("%s: watchdog timeout\n", DEVNAME(sc));
                    549:
                    550:        s = splusb();
                    551:        ifp->if_timer = 0;
                    552:        ifp->if_flags &= ~IFF_OACTIVE;
                    553:
                    554:        /* cancel recieve pipe? */
                    555:        usbf_abort_pipe(sc->sc_pipe_in); /* in is tx pipe */
                    556:        splx(s);
                    557: }
                    558:
                    559: void
                    560: cdcef_init(struct cdcef_softc *sc)
                    561: {
                    562:        int s;
                    563:        struct ifnet    *ifp = GET_IFP(sc);
                    564:        if (ifp->if_flags & IFF_RUNNING)
                    565:                return;
                    566:        s = splnet();
                    567:
                    568:        ifp->if_flags |= IFF_RUNNING;
                    569:        ifp->if_flags &= ~IFF_OACTIVE;
                    570:
                    571:        splx(s);
                    572: }
                    573:
                    574: int
                    575: cdcef_encap(struct cdcef_softc *sc, struct mbuf *m, int idx)
                    576: {
                    577:        usbf_status err;
                    578:
                    579:        m_copydata(m, 0, m->m_pkthdr.len, sc->sc_buffer_in);
                    580:        /* NO CRC */
                    581:
                    582:        usbf_setup_xfer(sc->sc_xfer_in, sc->sc_pipe_in, sc, sc->sc_buffer_in,
                    583:            m->m_pkthdr.len, USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
                    584:            10000, cdcef_txeof);
                    585:
                    586:        err = usbf_transfer(sc->sc_xfer_in);
                    587:        if (err && err != USBD_IN_PROGRESS) {
                    588:                printf("encap error\n");
                    589:                cdcef_stop(sc);
                    590:                return (EIO);
                    591:        }
                    592:        sc->sc_xmit_mbuf = m;
                    593:
                    594:        return (0);
                    595: }
                    596:
                    597:
                    598: void
                    599: cdcef_stop(struct cdcef_softc *sc)
                    600: {
                    601:        struct ifnet    *ifp = GET_IFP(sc);
                    602:
                    603:        ifp->if_timer = 0;
                    604:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
                    605:
                    606:        /* cancel recieve pipe? */
                    607:
                    608:        if (sc->sc_xmit_mbuf != NULL) {
                    609:                m_freem(sc->sc_xmit_mbuf);
                    610:                sc->sc_xmit_mbuf = NULL;
                    611:        }
                    612: }

CVSweb