The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/net/if_cdce.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: if_cdce.c,v 1.4 2004/10/24 12:50:54 augustss Exp $ */
    2 
    3 /*-
    4  * SPDX-License-Identifier: BSD-4-Clause
    5  *
    6  * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wpaul@windriver.com>
    7  * Copyright (c) 2003-2005 Craig Boston
    8  * Copyright (c) 2004 Daniel Hartmeier
    9  * Copyright (c) 2009 Hans Petter Selasky
   10  * All rights reserved.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *      This product includes software developed by Bill Paul.
   23  * 4. Neither the name of the author nor the names of any co-contributors
   24  *    may be used to endorse or promote products derived from this software
   25  *    without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
   28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   30  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul, THE VOICES IN HIS HEAD OR
   31  * THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   32  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   33  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   34  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   35  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   36  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   37  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 /*
   41  * USB Communication Device Class (Ethernet Networking Control Model)
   42  * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf
   43  */
   44 
   45 /*
   46  * USB Network Control Model (NCM)
   47  * http://www.usb.org/developers/devclass_docs/NCM10.zip
   48  */
   49 
   50 #include <sys/cdefs.h>
   51 __FBSDID("$FreeBSD$");
   52 
   53 #include <sys/gsb_crc32.h>
   54 #include <sys/eventhandler.h>
   55 #include <sys/stdint.h>
   56 #include <sys/stddef.h>
   57 #include <sys/queue.h>
   58 #include <sys/systm.h>
   59 #include <sys/socket.h>
   60 #include <sys/kernel.h>
   61 #include <sys/bus.h>
   62 #include <sys/module.h>
   63 #include <sys/lock.h>
   64 #include <sys/mutex.h>
   65 #include <sys/condvar.h>
   66 #include <sys/sysctl.h>
   67 #include <sys/sx.h>
   68 #include <sys/unistd.h>
   69 #include <sys/callout.h>
   70 #include <sys/malloc.h>
   71 #include <sys/priv.h>
   72 
   73 #include <net/if.h>
   74 #include <net/if_var.h>
   75 
   76 #include <dev/usb/usb.h>
   77 #include <dev/usb/usbdi.h>
   78 #include <dev/usb/usbdi_util.h>
   79 #include <dev/usb/usb_cdc.h>
   80 #include "usbdevs.h"
   81 
   82 #define USB_DEBUG_VAR cdce_debug
   83 #include <dev/usb/usb_debug.h>
   84 #include <dev/usb/usb_process.h>
   85 #include <dev/usb/usb_msctest.h>
   86 #include "usb_if.h"
   87 
   88 #include <dev/usb/net/usb_ethernet.h>
   89 #include <dev/usb/net/if_cdcereg.h>
   90 
   91 static device_probe_t cdce_probe;
   92 static device_attach_t cdce_attach;
   93 static device_detach_t cdce_detach;
   94 static device_suspend_t cdce_suspend;
   95 static device_resume_t cdce_resume;
   96 static usb_handle_request_t cdce_handle_request;
   97 
   98 static usb_callback_t cdce_bulk_write_callback;
   99 static usb_callback_t cdce_bulk_read_callback;
  100 static usb_callback_t cdce_intr_read_callback;
  101 static usb_callback_t cdce_intr_write_callback;
  102 
  103 #if CDCE_HAVE_NCM
  104 static usb_callback_t cdce_ncm_bulk_write_callback;
  105 static usb_callback_t cdce_ncm_bulk_read_callback;
  106 #endif
  107 
  108 static uether_fn_t cdce_attach_post;
  109 static uether_fn_t cdce_init;
  110 static uether_fn_t cdce_stop;
  111 static uether_fn_t cdce_start;
  112 static uether_fn_t cdce_setmulti;
  113 static uether_fn_t cdce_setpromisc;
  114 static int cdce_attach_post_sub(struct usb_ether *);
  115 static int cdce_ioctl(struct ifnet *, u_long, caddr_t);
  116 static int cdce_media_change_cb(struct ifnet *);
  117 static void cdce_media_status_cb(struct ifnet *, struct ifmediareq *);
  118 
  119 static uint32_t cdce_m_crc32(struct mbuf *, uint32_t, uint32_t);
  120 static void     cdce_set_filter(struct usb_ether *);
  121 
  122 #ifdef USB_DEBUG
  123 static int cdce_debug = 0;
  124 static int cdce_tx_interval = 0;
  125 
  126 static SYSCTL_NODE(_hw_usb, OID_AUTO, cdce, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
  127     "USB CDC-Ethernet");
  128 SYSCTL_INT(_hw_usb_cdce, OID_AUTO, debug, CTLFLAG_RWTUN, &cdce_debug, 0,
  129     "Debug level");
  130 SYSCTL_INT(_hw_usb_cdce, OID_AUTO, interval, CTLFLAG_RWTUN, &cdce_tx_interval, 0,
  131     "NCM transmit interval in ms");
  132 #else
  133 #define cdce_debug 0
  134 #endif
  135 
  136 static const struct usb_config cdce_config[CDCE_N_TRANSFER] = {
  137         [CDCE_BULK_RX] = {
  138                 .type = UE_BULK,
  139                 .endpoint = UE_ADDR_ANY,
  140                 .direction = UE_DIR_RX,
  141                 .if_index = 0,
  142                 .frames = CDCE_FRAMES_MAX,
  143                 .bufsize = (CDCE_FRAMES_MAX * MCLBYTES),
  144                 .flags = {.pipe_bof = 1,.short_frames_ok = 1,.short_xfer_ok = 1,.ext_buffer = 1,},
  145                 .callback = cdce_bulk_read_callback,
  146                 .timeout = 0,   /* no timeout */
  147                 .usb_mode = USB_MODE_DUAL,      /* both modes */
  148         },
  149 
  150         [CDCE_BULK_TX] = {
  151                 .type = UE_BULK,
  152                 .endpoint = UE_ADDR_ANY,
  153                 .direction = UE_DIR_TX,
  154                 .if_index = 0,
  155                 .frames = CDCE_FRAMES_MAX,
  156                 .bufsize = (CDCE_FRAMES_MAX * MCLBYTES),
  157                 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1,},
  158                 .callback = cdce_bulk_write_callback,
  159                 .timeout = 10000,       /* 10 seconds */
  160                 .usb_mode = USB_MODE_DUAL,      /* both modes */
  161         },
  162 
  163         [CDCE_INTR_RX] = {
  164                 .type = UE_INTERRUPT,
  165                 .endpoint = UE_ADDR_ANY,
  166                 .direction = UE_DIR_RX,
  167                 .if_index = 1,
  168                 .bufsize = CDCE_IND_SIZE_MAX,
  169                 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,},
  170                 .callback = cdce_intr_read_callback,
  171                 .timeout = 0,
  172                 .usb_mode = USB_MODE_HOST,
  173         },
  174 
  175         [CDCE_INTR_TX] = {
  176                 .type = UE_INTERRUPT,
  177                 .endpoint = UE_ADDR_ANY,
  178                 .direction = UE_DIR_TX,
  179                 .if_index = 1,
  180                 .bufsize = CDCE_IND_SIZE_MAX,
  181                 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.no_pipe_ok = 1,},
  182                 .callback = cdce_intr_write_callback,
  183                 .timeout = 10000,       /* 10 seconds */
  184                 .usb_mode = USB_MODE_DEVICE,
  185         },
  186 };
  187 
  188 #if CDCE_HAVE_NCM
  189 static const struct usb_config cdce_ncm_config[CDCE_N_TRANSFER] = {
  190         [CDCE_BULK_RX] = {
  191                 .type = UE_BULK,
  192                 .endpoint = UE_ADDR_ANY,
  193                 .direction = UE_DIR_RX,
  194                 .if_index = 0,
  195                 .frames = CDCE_NCM_RX_FRAMES_MAX,
  196                 .bufsize = (CDCE_NCM_RX_FRAMES_MAX * CDCE_NCM_RX_MAXLEN),
  197                 .flags = {.pipe_bof = 1,.short_frames_ok = 1,.short_xfer_ok = 1,},
  198                 .callback = cdce_ncm_bulk_read_callback,
  199                 .timeout = 0,   /* no timeout */
  200                 .usb_mode = USB_MODE_DUAL,      /* both modes */
  201         },
  202 
  203         [CDCE_BULK_TX] = {
  204                 .type = UE_BULK,
  205                 .endpoint = UE_ADDR_ANY,
  206                 .direction = UE_DIR_TX,
  207                 .if_index = 0,
  208                 .frames = CDCE_NCM_TX_FRAMES_MAX,
  209                 .bufsize = (CDCE_NCM_TX_FRAMES_MAX * CDCE_NCM_TX_MAXLEN),
  210                 .flags = {.pipe_bof = 1,},
  211                 .callback = cdce_ncm_bulk_write_callback,
  212                 .timeout = 10000,       /* 10 seconds */
  213                 .usb_mode = USB_MODE_DUAL,      /* both modes */
  214         },
  215 
  216         [CDCE_INTR_RX] = {
  217                 .type = UE_INTERRUPT,
  218                 .endpoint = UE_ADDR_ANY,
  219                 .direction = UE_DIR_RX,
  220                 .if_index = 1,
  221                 .bufsize = CDCE_IND_SIZE_MAX,
  222                 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,},
  223                 .callback = cdce_intr_read_callback,
  224                 .timeout = 0,
  225                 .usb_mode = USB_MODE_HOST,
  226         },
  227 
  228         [CDCE_INTR_TX] = {
  229                 .type = UE_INTERRUPT,
  230                 .endpoint = UE_ADDR_ANY,
  231                 .direction = UE_DIR_TX,
  232                 .if_index = 1,
  233                 .bufsize = CDCE_IND_SIZE_MAX,
  234                 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.no_pipe_ok = 1,},
  235                 .callback = cdce_intr_write_callback,
  236                 .timeout = 10000,       /* 10 seconds */
  237                 .usb_mode = USB_MODE_DEVICE,
  238         },
  239 };
  240 #endif
  241 
  242 static device_method_t cdce_methods[] = {
  243         /* USB interface */
  244         DEVMETHOD(usb_handle_request, cdce_handle_request),
  245 
  246         /* Device interface */
  247         DEVMETHOD(device_probe, cdce_probe),
  248         DEVMETHOD(device_attach, cdce_attach),
  249         DEVMETHOD(device_detach, cdce_detach),
  250         DEVMETHOD(device_suspend, cdce_suspend),
  251         DEVMETHOD(device_resume, cdce_resume),
  252 
  253         DEVMETHOD_END
  254 };
  255 
  256 static driver_t cdce_driver = {
  257         .name = "cdce",
  258         .methods = cdce_methods,
  259         .size = sizeof(struct cdce_softc),
  260 };
  261 
  262 static eventhandler_tag cdce_etag;
  263 
  264 static int  cdce_driver_loaded(struct module *, int, void *);
  265 
  266 static const STRUCT_USB_HOST_ID cdce_switch_devs[] = {
  267         {USB_VPI(USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E3272_INIT, MSC_EJECT_HUAWEI2)},
  268 };
  269 
  270 static const STRUCT_USB_HOST_ID cdce_host_devs[] = {
  271         {USB_VPI(USB_VENDOR_ACERLABS, USB_PRODUCT_ACERLABS_M5632, CDCE_FLAG_NO_UNION)},
  272         {USB_VPI(USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_NTL_250, CDCE_FLAG_NO_UNION)},
  273         {USB_VPI(USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQLINUX, CDCE_FLAG_NO_UNION)},
  274         {USB_VPI(USB_VENDOR_GMATE, USB_PRODUCT_GMATE_YP3X00, CDCE_FLAG_NO_UNION)},
  275         {USB_VPI(USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
  276         {USB_VPI(USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN2, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
  277         {USB_VPI(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501, CDCE_FLAG_NO_UNION)},
  278         {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500, CDCE_FLAG_ZAURUS)},
  279         {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
  280         {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLA300, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
  281         {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC700, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
  282         {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC750, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
  283         {USB_VPI(USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8156, 0)},
  284 
  285         {USB_VENDOR(USB_VENDOR_HUAWEI), USB_IFACE_CLASS(UICLASS_VENDOR),
  286                 USB_IFACE_SUBCLASS(0x02), USB_IFACE_PROTOCOL(0x16),
  287                 USB_DRIVER_INFO(0)},
  288         {USB_VENDOR(USB_VENDOR_HUAWEI), USB_IFACE_CLASS(UICLASS_VENDOR),
  289                 USB_IFACE_SUBCLASS(0x02), USB_IFACE_PROTOCOL(0x46),
  290                 USB_DRIVER_INFO(0)},
  291         {USB_VENDOR(USB_VENDOR_HUAWEI), USB_IFACE_CLASS(UICLASS_VENDOR),
  292                 USB_IFACE_SUBCLASS(0x02), USB_IFACE_PROTOCOL(0x76),
  293                 USB_DRIVER_INFO(0)},
  294         {USB_VENDOR(USB_VENDOR_HUAWEI), USB_IFACE_CLASS(UICLASS_VENDOR),
  295                 USB_IFACE_SUBCLASS(0x03), USB_IFACE_PROTOCOL(0x16),
  296                 USB_DRIVER_INFO(0)},
  297 };
  298 
  299 static const STRUCT_USB_DUAL_ID cdce_dual_devs[] = {
  300         {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0)},
  301         {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_MOBILE_DIRECT_LINE_MODEL, 0)},
  302         {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_NETWORK_CONTROL_MODEL, 0)},
  303 };
  304 
  305 DRIVER_MODULE(cdce, uhub, cdce_driver, cdce_driver_loaded, NULL);
  306 MODULE_VERSION(cdce, 1);
  307 MODULE_DEPEND(cdce, uether, 1, 1, 1);
  308 MODULE_DEPEND(cdce, usb, 1, 1, 1);
  309 MODULE_DEPEND(cdce, ether, 1, 1, 1);
  310 USB_PNP_DEVICE_INFO(cdce_switch_devs);
  311 USB_PNP_HOST_INFO(cdce_host_devs);
  312 USB_PNP_DUAL_INFO(cdce_dual_devs);
  313 
  314 static const struct usb_ether_methods cdce_ue_methods = {
  315         .ue_attach_post = cdce_attach_post,
  316         .ue_attach_post_sub = cdce_attach_post_sub,
  317         .ue_start = cdce_start,
  318         .ue_init = cdce_init,
  319         .ue_stop = cdce_stop,
  320         .ue_setmulti = cdce_setmulti,
  321         .ue_setpromisc = cdce_setpromisc,
  322 };
  323 
  324 #if CDCE_HAVE_NCM
  325 /*------------------------------------------------------------------------*
  326  *      cdce_ncm_init
  327  *
  328  * Return values:
  329  * 0: Success
  330  * Else: Failure
  331  *------------------------------------------------------------------------*/
  332 static uint8_t
  333 cdce_ncm_init(struct cdce_softc *sc)
  334 {
  335         struct usb_ncm_parameters temp;
  336         struct usb_device_request req;
  337         struct usb_ncm_func_descriptor *ufd;
  338         uint8_t value[8];
  339         int err;
  340 
  341         ufd = usbd_find_descriptor(sc->sc_ue.ue_udev, NULL,
  342             sc->sc_ifaces_index[1], UDESC_CS_INTERFACE, 0xFF,
  343             UCDC_NCM_FUNC_DESC_SUBTYPE, 0xFF);
  344 
  345         /* verify length of NCM functional descriptor */
  346         if (ufd != NULL) {
  347                 if (ufd->bLength < sizeof(*ufd))
  348                         ufd = NULL;
  349                 else
  350                         DPRINTFN(1, "Found NCM functional descriptor.\n");
  351         }
  352 
  353         req.bmRequestType = UT_READ_CLASS_INTERFACE;
  354         req.bRequest = UCDC_NCM_GET_NTB_PARAMETERS;
  355         USETW(req.wValue, 0);
  356         req.wIndex[0] = sc->sc_ifaces_index[1];
  357         req.wIndex[1] = 0;
  358         USETW(req.wLength, sizeof(temp));
  359 
  360         err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req,
  361             &temp, 0, NULL, 1000 /* ms */);
  362         if (err)
  363                 return (1);
  364 
  365         /* Read correct set of parameters according to device mode */
  366 
  367         if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) {
  368                 sc->sc_ncm.rx_max = UGETDW(temp.dwNtbInMaxSize);
  369                 sc->sc_ncm.tx_max = UGETDW(temp.dwNtbOutMaxSize);
  370                 sc->sc_ncm.tx_remainder = UGETW(temp.wNdpOutPayloadRemainder);
  371                 sc->sc_ncm.tx_modulus = UGETW(temp.wNdpOutDivisor);
  372                 sc->sc_ncm.tx_struct_align = UGETW(temp.wNdpOutAlignment);
  373                 sc->sc_ncm.tx_nframe = UGETW(temp.wNtbOutMaxDatagrams);
  374         } else {
  375                 sc->sc_ncm.rx_max = UGETDW(temp.dwNtbOutMaxSize);
  376                 sc->sc_ncm.tx_max = UGETDW(temp.dwNtbInMaxSize);
  377                 sc->sc_ncm.tx_remainder = UGETW(temp.wNdpInPayloadRemainder);
  378                 sc->sc_ncm.tx_modulus = UGETW(temp.wNdpInDivisor);
  379                 sc->sc_ncm.tx_struct_align = UGETW(temp.wNdpInAlignment);
  380                 sc->sc_ncm.tx_nframe = UGETW(temp.wNtbOutMaxDatagrams);
  381         }
  382 
  383         /* Verify maximum receive length */
  384 
  385         if ((sc->sc_ncm.rx_max < 32) || 
  386             (sc->sc_ncm.rx_max > CDCE_NCM_RX_MAXLEN)) {
  387                 DPRINTFN(1, "Using default maximum receive length\n");
  388                 sc->sc_ncm.rx_max = CDCE_NCM_RX_MAXLEN;
  389         }
  390 
  391         /* Verify maximum transmit length */
  392 
  393         if ((sc->sc_ncm.tx_max < 32) ||
  394             (sc->sc_ncm.tx_max > CDCE_NCM_TX_MAXLEN)) {
  395                 DPRINTFN(1, "Using default maximum transmit length\n");
  396                 sc->sc_ncm.tx_max = CDCE_NCM_TX_MAXLEN;
  397         }
  398 
  399         /* 
  400          * Verify that the structure alignment is:
  401          * - power of two
  402          * - not greater than the maximum transmit length
  403          * - not less than four bytes
  404          */
  405         if ((sc->sc_ncm.tx_struct_align < 4) ||
  406             (sc->sc_ncm.tx_struct_align != 
  407              ((-sc->sc_ncm.tx_struct_align) & sc->sc_ncm.tx_struct_align)) ||
  408             (sc->sc_ncm.tx_struct_align >= sc->sc_ncm.tx_max)) {
  409                 DPRINTFN(1, "Using default other alignment: 4 bytes\n");
  410                 sc->sc_ncm.tx_struct_align = 4;
  411         }
  412 
  413         /* 
  414          * Verify that the payload alignment is:
  415          * - power of two
  416          * - not greater than the maximum transmit length
  417          * - not less than four bytes
  418          */
  419         if ((sc->sc_ncm.tx_modulus < 4) ||
  420             (sc->sc_ncm.tx_modulus !=
  421              ((-sc->sc_ncm.tx_modulus) & sc->sc_ncm.tx_modulus)) ||
  422             (sc->sc_ncm.tx_modulus >= sc->sc_ncm.tx_max)) {
  423                 DPRINTFN(1, "Using default transmit modulus: 4 bytes\n");
  424                 sc->sc_ncm.tx_modulus = 4;
  425         }
  426 
  427         /* Verify that the payload remainder */
  428 
  429         if ((sc->sc_ncm.tx_remainder >= sc->sc_ncm.tx_modulus)) {
  430                 DPRINTFN(1, "Using default transmit remainder: 0 bytes\n");
  431                 sc->sc_ncm.tx_remainder = 0;
  432         }
  433 
  434         /*
  435          * Offset the TX remainder so that IP packet payload starts at
  436          * the tx_modulus. This is not too clear in the specification.
  437          */
  438 
  439         sc->sc_ncm.tx_remainder = 
  440             (sc->sc_ncm.tx_remainder - ETHER_HDR_LEN) &
  441             (sc->sc_ncm.tx_modulus - 1);
  442 
  443         /* Verify max datagrams */
  444 
  445         if (sc->sc_ncm.tx_nframe == 0 ||
  446             sc->sc_ncm.tx_nframe > (CDCE_NCM_SUBFRAMES_MAX - 1)) {
  447                 DPRINTFN(1, "Using default max "
  448                     "subframes: %u units\n", CDCE_NCM_SUBFRAMES_MAX - 1);
  449                 /* need to reserve one entry for zero padding */
  450                 sc->sc_ncm.tx_nframe = (CDCE_NCM_SUBFRAMES_MAX - 1);
  451         }
  452 
  453         /* Additional configuration, will fail in device side mode, which is OK. */
  454 
  455         req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  456         req.bRequest = UCDC_NCM_SET_NTB_INPUT_SIZE;
  457         USETW(req.wValue, 0);
  458         req.wIndex[0] = sc->sc_ifaces_index[1];
  459         req.wIndex[1] = 0;
  460 
  461         if (ufd != NULL &&
  462             (ufd->bmNetworkCapabilities & UCDC_NCM_CAP_MAX_DGRAM)) {
  463                 USETW(req.wLength, 8);
  464                 USETDW(value, sc->sc_ncm.rx_max);
  465                 USETW(value + 4, (CDCE_NCM_SUBFRAMES_MAX - 1));
  466                 USETW(value + 6, 0);
  467         } else {
  468                 USETW(req.wLength, 4);
  469                 USETDW(value, sc->sc_ncm.rx_max);
  470         }
  471 
  472         err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req,
  473             &value, 0, NULL, 1000 /* ms */);
  474         if (err) {
  475                 DPRINTFN(1, "Setting input size "
  476                     "to %u failed.\n", sc->sc_ncm.rx_max);
  477         }
  478 
  479         req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  480         req.bRequest = UCDC_NCM_SET_CRC_MODE;
  481         USETW(req.wValue, 0);   /* no CRC */
  482         req.wIndex[0] = sc->sc_ifaces_index[1];
  483         req.wIndex[1] = 0;
  484         USETW(req.wLength, 0);
  485 
  486         err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req,
  487             NULL, 0, NULL, 1000 /* ms */);
  488         if (err) {
  489                 DPRINTFN(1, "Setting CRC mode to off failed.\n");
  490         }
  491 
  492         req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  493         req.bRequest = UCDC_NCM_SET_NTB_FORMAT;
  494         USETW(req.wValue, 0);   /* NTB-16 */
  495         req.wIndex[0] = sc->sc_ifaces_index[1];
  496         req.wIndex[1] = 0;
  497         USETW(req.wLength, 0);
  498 
  499         err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req,
  500             NULL, 0, NULL, 1000 /* ms */);
  501         if (err) {
  502                 DPRINTFN(1, "Setting NTB format to 16-bit failed.\n");
  503         }
  504 
  505         return (0);             /* success */
  506 }
  507 #endif
  508 
  509 static void
  510 cdce_test_autoinst(void *arg, struct usb_device *udev,
  511     struct usb_attach_arg *uaa)
  512 {
  513         struct usb_interface *iface;
  514         struct usb_interface_descriptor *id;
  515 
  516         if (uaa->dev_state != UAA_DEV_READY)
  517                 return;
  518 
  519         iface = usbd_get_iface(udev, 0);
  520         if (iface == NULL)
  521                 return;
  522         id = iface->idesc;
  523         if (id == NULL || id->bInterfaceClass != UICLASS_MASS)
  524                 return;
  525         if (usbd_lookup_id_by_uaa(cdce_switch_devs, sizeof(cdce_switch_devs), uaa))
  526                 return;         /* no device match */
  527 
  528         if (usb_msc_eject(udev, 0, USB_GET_DRIVER_INFO(uaa)) == 0) {
  529                 /* success, mark the udev as disappearing */
  530                 uaa->dev_state = UAA_DEV_EJECTING;
  531         }
  532 }
  533 
  534 static int
  535 cdce_driver_loaded(struct module *mod, int what, void *arg)
  536 {
  537         switch (what) {
  538         case MOD_LOAD:
  539                 /* register our autoinstall handler */
  540                 cdce_etag = EVENTHANDLER_REGISTER(usb_dev_configured,
  541                     cdce_test_autoinst, NULL, EVENTHANDLER_PRI_ANY);
  542                 return (0);
  543         case MOD_UNLOAD:
  544                 EVENTHANDLER_DEREGISTER(usb_dev_configured, cdce_etag);
  545                 return (0);
  546         default:
  547                 return (EOPNOTSUPP);
  548         }
  549 }
  550 
  551 static int
  552 cdce_probe(device_t dev)
  553 {
  554         struct usb_attach_arg *uaa = device_get_ivars(dev);
  555         int error;
  556 
  557         error = usbd_lookup_id_by_uaa(cdce_host_devs, sizeof(cdce_host_devs), uaa);
  558         if (error)
  559                 error = usbd_lookup_id_by_uaa(cdce_dual_devs, sizeof(cdce_dual_devs), uaa);
  560         return (error);
  561 }
  562 
  563 static void
  564 cdce_attach_post(struct usb_ether *ue)
  565 {
  566         /* no-op */
  567         return;
  568 }
  569 
  570 static int
  571 cdce_attach_post_sub(struct usb_ether *ue)
  572 {
  573         struct cdce_softc *sc = uether_getsc(ue);
  574         struct ifnet *ifp = uether_getifp(ue);
  575 
  576         /* mostly copied from usb_ethernet.c */
  577         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  578         ifp->if_start = uether_start;
  579         ifp->if_ioctl = cdce_ioctl;
  580         ifp->if_init = uether_init;
  581         IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
  582         ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
  583         IFQ_SET_READY(&ifp->if_snd);
  584 
  585         if ((sc->sc_flags & CDCE_FLAG_VLAN) == CDCE_FLAG_VLAN)
  586                 if_setcapabilitiesbit(ifp, IFCAP_VLAN_MTU, 0);
  587 
  588         if_setcapabilitiesbit(ifp, IFCAP_LINKSTATE, 0);
  589         if_setcapenable(ifp, if_getcapabilities(ifp));
  590 
  591         ifmedia_init(&sc->sc_media, IFM_IMASK, cdce_media_change_cb,
  592             cdce_media_status_cb);
  593         ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
  594         ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
  595         sc->sc_media.ifm_media = sc->sc_media.ifm_cur->ifm_media;
  596         CDCE_LOCK(sc);
  597         cdce_set_filter(ue);
  598         CDCE_UNLOCK(sc);
  599 
  600         return 0;
  601 }
  602 
  603 static int
  604 cdce_attach(device_t dev)
  605 {
  606         struct cdce_softc *sc = device_get_softc(dev);
  607         struct usb_ether *ue = &sc->sc_ue;
  608         struct usb_attach_arg *uaa = device_get_ivars(dev);
  609         struct usb_interface *iface;
  610         const struct usb_cdc_union_descriptor *ud;
  611         const struct usb_interface_descriptor *id;
  612         const struct usb_cdc_ethernet_descriptor *ued;
  613         const struct usb_config *pcfg;
  614         uint32_t seed;
  615         int error;
  616         uint8_t i;
  617         uint8_t data_iface_no;
  618         char eaddr_str[5 * ETHER_ADDR_LEN];     /* approx */
  619 
  620         sc->sc_flags = USB_GET_DRIVER_INFO(uaa);
  621         sc->sc_ue.ue_udev = uaa->device;
  622 
  623         device_set_usb_desc(dev);
  624 
  625         mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
  626 
  627         ud = usbd_find_descriptor
  628             (uaa->device, NULL, uaa->info.bIfaceIndex,
  629             UDESC_CS_INTERFACE, 0xFF, UDESCSUB_CDC_UNION, 0xFF);
  630 
  631         if ((ud == NULL) || (ud->bLength < sizeof(*ud)) ||
  632             (sc->sc_flags & CDCE_FLAG_NO_UNION)) {
  633                 DPRINTFN(1, "No union descriptor!\n");
  634                 sc->sc_ifaces_index[0] = uaa->info.bIfaceIndex;
  635                 sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex;
  636                 goto alloc_transfers;
  637         }
  638         data_iface_no = ud->bSlaveInterface[0];
  639 
  640         for (i = 0;; i++) {
  641                 iface = usbd_get_iface(uaa->device, i);
  642 
  643                 if (iface) {
  644                         id = usbd_get_interface_descriptor(iface);
  645 
  646                         if (id && (id->bInterfaceNumber == data_iface_no)) {
  647                                 sc->sc_ifaces_index[0] = i;
  648                                 sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex;
  649                                 usbd_set_parent_iface(uaa->device, i, uaa->info.bIfaceIndex);
  650                                 break;
  651                         }
  652                 } else {
  653                         device_printf(dev, "no data interface found\n");
  654                         goto detach;
  655                 }
  656         }
  657 
  658         /*
  659          * <quote>
  660          *
  661          *  The Data Class interface of a networking device shall have
  662          *  a minimum of two interface settings. The first setting
  663          *  (the default interface setting) includes no endpoints and
  664          *  therefore no networking traffic is exchanged whenever the
  665          *  default interface setting is selected. One or more
  666          *  additional interface settings are used for normal
  667          *  operation, and therefore each includes a pair of endpoints
  668          *  (one IN, and one OUT) to exchange network traffic. Select
  669          *  an alternate interface setting to initialize the network
  670          *  aspects of the device and to enable the exchange of
  671          *  network traffic.
  672          *
  673          * </quote>
  674          *
  675          * Some devices, most notably cable modems, include interface
  676          * settings that have no IN or OUT endpoint, therefore loop
  677          * through the list of all available interface settings
  678          * looking for one with both IN and OUT endpoints.
  679          */
  680 
  681 alloc_transfers:
  682 
  683         pcfg = cdce_config;     /* Default Configuration */
  684 
  685         for (i = 0; i != 32; i++) {
  686                 error = usbd_set_alt_interface_index(uaa->device,
  687                     sc->sc_ifaces_index[0], i);
  688                 if (error)
  689                         break;
  690 #if CDCE_HAVE_NCM
  691                 if ((i == 0) && (cdce_ncm_init(sc) == 0))
  692                         pcfg = cdce_ncm_config;
  693 #endif
  694                 error = usbd_transfer_setup(uaa->device,
  695                     sc->sc_ifaces_index, sc->sc_xfer,
  696                     pcfg, CDCE_N_TRANSFER, sc, &sc->sc_mtx);
  697 
  698                 if (error == 0)
  699                         break;
  700         }
  701 
  702         if (error || (i == 32)) {
  703                 device_printf(dev, "No valid alternate "
  704                     "setting found\n");
  705                 goto detach;
  706         }
  707 
  708         ued = usbd_find_descriptor
  709             (uaa->device, NULL, uaa->info.bIfaceIndex,
  710             UDESC_CS_INTERFACE, 0xFF, UDESCSUB_CDC_ENF, 0xFF);
  711 
  712         if ((ued == NULL) || (ued->bLength < sizeof(*ued))) {
  713                 error = USB_ERR_INVAL;
  714         } else {
  715                 /*
  716                  * ECM 1.2 doesn't say it excludes the CRC, but states that it's
  717                  * normally 1514, which excludes the CRC.
  718                  */
  719                 DPRINTF("max segsize: %d\n", UGETW(ued->wMaxSegmentSize));
  720                 if (UGETW(ued->wMaxSegmentSize) >= (ETHER_MAX_LEN - ETHER_CRC_LEN + ETHER_VLAN_ENCAP_LEN))
  721                         sc->sc_flags |= CDCE_FLAG_VLAN;
  722 
  723                 error = usbd_req_get_string_any(uaa->device, NULL, 
  724                     eaddr_str, sizeof(eaddr_str), ued->iMacAddress);
  725         }
  726 
  727         if (error) {
  728                 /* fake MAC address */
  729 
  730                 device_printf(dev, "faking MAC address\n");
  731                 seed = ticks;
  732                 sc->sc_ue.ue_eaddr[0] = 0x2a;
  733                 memcpy(&sc->sc_ue.ue_eaddr[1], &seed, sizeof(uint32_t));
  734                 sc->sc_ue.ue_eaddr[5] = device_get_unit(dev);
  735 
  736         } else {
  737                 memset(sc->sc_ue.ue_eaddr, 0, sizeof(sc->sc_ue.ue_eaddr));
  738 
  739                 for (i = 0; i != (ETHER_ADDR_LEN * 2); i++) {
  740                         char c = eaddr_str[i];
  741 
  742                         if ('' <= c && c <= '9')
  743                                 c -= '';
  744                         else if (c != 0)
  745                                 c -= 'A' - 10;
  746                         else
  747                                 break;
  748 
  749                         c &= 0xf;
  750 
  751                         if ((i & 1) == 0)
  752                                 c <<= 4;
  753                         sc->sc_ue.ue_eaddr[i / 2] |= c;
  754                 }
  755 
  756                 if (uaa->usb_mode == USB_MODE_DEVICE) {
  757                         /*
  758                          * Do not use the same MAC address like the peer !
  759                          */
  760                         sc->sc_ue.ue_eaddr[5] ^= 0xFF;
  761                 }
  762         }
  763 
  764         ue->ue_sc = sc;
  765         ue->ue_dev = dev;
  766         ue->ue_udev = uaa->device;
  767         ue->ue_mtx = &sc->sc_mtx;
  768         ue->ue_methods = &cdce_ue_methods;
  769 
  770         error = uether_ifattach(ue);
  771         if (error) {
  772                 device_printf(dev, "could not attach interface\n");
  773                 goto detach;
  774         }
  775         return (0);                     /* success */
  776 
  777 detach:
  778         cdce_detach(dev);
  779         return (ENXIO);                 /* failure */
  780 }
  781 
  782 static int
  783 cdce_detach(device_t dev)
  784 {
  785         struct cdce_softc *sc = device_get_softc(dev);
  786         struct usb_ether *ue = &sc->sc_ue;
  787 
  788         /* stop all USB transfers first */
  789         usbd_transfer_unsetup(sc->sc_xfer, CDCE_N_TRANSFER);
  790         uether_ifdetach(ue);
  791         mtx_destroy(&sc->sc_mtx);
  792 
  793         ifmedia_removeall(&sc->sc_media);
  794 
  795         return (0);
  796 }
  797 
  798 static void
  799 cdce_start(struct usb_ether *ue)
  800 {
  801         struct cdce_softc *sc = uether_getsc(ue);
  802 
  803         /*
  804          * Start the USB transfers, if not already started:
  805          */
  806         usbd_transfer_start(sc->sc_xfer[CDCE_BULK_TX]);
  807         usbd_transfer_start(sc->sc_xfer[CDCE_BULK_RX]);
  808 }
  809 
  810 static int
  811 cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
  812 {
  813         struct usb_ether *ue = ifp->if_softc;
  814         struct cdce_softc *sc = uether_getsc(ue);
  815         struct ifreq *ifr = (struct ifreq *)data;
  816         int error;
  817 
  818         error = 0;
  819 
  820         switch(command) {
  821         case SIOCGIFMEDIA:
  822         case SIOCSIFMEDIA:
  823                 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
  824                 break;
  825         default:
  826                 error = uether_ioctl(ifp, command, data);
  827                 break;
  828         }
  829 
  830         return (error);
  831 }
  832 
  833 static void
  834 cdce_free_queue(struct mbuf **ppm, uint8_t n)
  835 {
  836         uint8_t x;
  837         for (x = 0; x != n; x++) {
  838                 if (ppm[x] != NULL) {
  839                         m_freem(ppm[x]);
  840                         ppm[x] = NULL;
  841                 }
  842         }
  843 }
  844 
  845 static int
  846 cdce_media_change_cb(struct ifnet *ifp)
  847 {
  848 
  849         return (EOPNOTSUPP);
  850 }
  851 
  852 static void
  853 cdce_media_status_cb(struct ifnet *ifp, struct ifmediareq *ifmr)
  854 {
  855 
  856         if ((if_getflags(ifp) & IFF_UP) == 0)
  857                 return;
  858 
  859         ifmr->ifm_active = IFM_ETHER;
  860         ifmr->ifm_status = IFM_AVALID;
  861         ifmr->ifm_status |=
  862             ifp->if_link_state == LINK_STATE_UP ? IFM_ACTIVE : 0;
  863 }
  864 
  865 static void
  866 cdce_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
  867 {
  868         struct cdce_softc *sc = usbd_xfer_softc(xfer);
  869         struct ifnet *ifp = uether_getifp(&sc->sc_ue);
  870         struct mbuf *m;
  871         struct mbuf *mt;
  872         uint32_t crc;
  873         uint8_t x;
  874         int actlen, aframes;
  875 
  876         usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
  877 
  878         DPRINTFN(1, "\n");
  879 
  880         switch (USB_GET_STATE(xfer)) {
  881         case USB_ST_TRANSFERRED:
  882                 DPRINTFN(11, "transfer complete: %u bytes in %u frames\n",
  883                     actlen, aframes);
  884 
  885                 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
  886 
  887                 /* free all previous TX buffers */
  888                 cdce_free_queue(sc->sc_tx_buf, CDCE_FRAMES_MAX);
  889 
  890                 /* FALLTHROUGH */
  891         case USB_ST_SETUP:
  892 tr_setup:
  893                 for (x = 0; x != CDCE_FRAMES_MAX; x++) {
  894                         IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
  895 
  896                         if (m == NULL)
  897                                 break;
  898 
  899                         if (sc->sc_flags & CDCE_FLAG_ZAURUS) {
  900                                 /*
  901                                  * Zaurus wants a 32-bit CRC appended
  902                                  * to every frame
  903                                  */
  904 
  905                                 crc = cdce_m_crc32(m, 0, m->m_pkthdr.len);
  906                                 crc = htole32(crc);
  907 
  908                                 if (!m_append(m, 4, (void *)&crc)) {
  909                                         m_freem(m);
  910                                         if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
  911                                         continue;
  912                                 }
  913                         }
  914                         if (m->m_len != m->m_pkthdr.len) {
  915                                 mt = m_defrag(m, M_NOWAIT);
  916                                 if (mt == NULL) {
  917                                         m_freem(m);
  918                                         if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
  919                                         continue;
  920                                 }
  921                                 m = mt;
  922                         }
  923                         if (m->m_pkthdr.len > MCLBYTES) {
  924                                 m->m_pkthdr.len = MCLBYTES;
  925                         }
  926                         sc->sc_tx_buf[x] = m;
  927                         usbd_xfer_set_frame_data(xfer, x, m->m_data, m->m_len);
  928 
  929                         /*
  930                          * If there's a BPF listener, bounce a copy of
  931                          * this frame to him:
  932                          */
  933                         BPF_MTAP(ifp, m);
  934                 }
  935                 if (x != 0) {
  936                         usbd_xfer_set_frames(xfer, x);
  937 
  938                         usbd_transfer_submit(xfer);
  939                 }
  940                 break;
  941 
  942         default:                        /* Error */
  943                 DPRINTFN(11, "transfer error, %s\n",
  944                     usbd_errstr(error));
  945 
  946                 /* free all previous TX buffers */
  947                 cdce_free_queue(sc->sc_tx_buf, CDCE_FRAMES_MAX);
  948 
  949                 /* count output errors */
  950                 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
  951 
  952                 if (error != USB_ERR_CANCELLED) {
  953                         if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) {
  954                                 /* try to clear stall first */
  955                                 usbd_xfer_set_stall(xfer);
  956                         }
  957                         goto tr_setup;
  958                 }
  959                 break;
  960         }
  961 }
  962 
  963 static int32_t
  964 cdce_m_crc32_cb(void *arg, void *src, uint32_t count)
  965 {
  966         uint32_t *p_crc = arg;
  967 
  968         *p_crc = crc32_raw(src, count, *p_crc);
  969         return (0);
  970 }
  971 
  972 static uint32_t
  973 cdce_m_crc32(struct mbuf *m, uint32_t src_offset, uint32_t src_len)
  974 {
  975         uint32_t crc = 0xFFFFFFFF;
  976 
  977         (void)m_apply(m, src_offset, src_len, cdce_m_crc32_cb, &crc);
  978         return (crc ^ 0xFFFFFFFF);
  979 }
  980 
  981 static void
  982 cdce_init(struct usb_ether *ue)
  983 {
  984         struct cdce_softc *sc = uether_getsc(ue);
  985         struct ifnet *ifp = uether_getifp(ue);
  986 
  987         CDCE_LOCK_ASSERT(sc, MA_OWNED);
  988 
  989         ifp->if_drv_flags |= IFF_DRV_RUNNING;
  990 
  991         /* start interrupt transfer */
  992         usbd_transfer_start(sc->sc_xfer[CDCE_INTR_RX]);
  993         usbd_transfer_start(sc->sc_xfer[CDCE_INTR_TX]);
  994 
  995         /*
  996          * Stall data write direction, which depends on USB mode.
  997          *
  998          * Some USB host stacks (e.g. Mac OS X) don't clears stall
  999          * bit as it should, so set it in our host mode only.
 1000          */
 1001         if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST)
 1002                 usbd_xfer_set_stall(sc->sc_xfer[CDCE_BULK_TX]);
 1003 
 1004         /* start data transfers */
 1005         cdce_start(ue);
 1006 }
 1007 
 1008 static void
 1009 cdce_stop(struct usb_ether *ue)
 1010 {
 1011         struct cdce_softc *sc = uether_getsc(ue);
 1012         struct ifnet *ifp = uether_getifp(ue);
 1013 
 1014         CDCE_LOCK_ASSERT(sc, MA_OWNED);
 1015 
 1016         ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
 1017 
 1018         /*
 1019          * stop all the transfers, if not already stopped:
 1020          */
 1021         usbd_transfer_stop(sc->sc_xfer[CDCE_BULK_RX]);
 1022         usbd_transfer_stop(sc->sc_xfer[CDCE_BULK_TX]);
 1023         usbd_transfer_stop(sc->sc_xfer[CDCE_INTR_RX]);
 1024         usbd_transfer_stop(sc->sc_xfer[CDCE_INTR_TX]);
 1025 }
 1026 
 1027 static void
 1028 cdce_setmulti(struct usb_ether *ue)
 1029 {
 1030 
 1031         cdce_set_filter(ue);
 1032 }
 1033 
 1034 static void
 1035 cdce_setpromisc(struct usb_ether *ue)
 1036 {
 1037 
 1038         cdce_set_filter(ue);
 1039 }
 1040 
 1041 static void
 1042 cdce_set_filter(struct usb_ether *ue)
 1043 {
 1044         struct cdce_softc *sc = uether_getsc(ue);
 1045         struct ifnet *ifp = uether_getifp(ue);
 1046         struct usb_device_request req;
 1047         uint16_t value;
 1048 
 1049         value = CDC_PACKET_TYPE_DIRECTED | CDC_PACKET_TYPE_BROADCAST;
 1050         if (if_getflags(ifp) & IFF_PROMISC)
 1051                 value |= CDC_PACKET_TYPE_PROMISC;
 1052         if (if_getflags(ifp) & IFF_ALLMULTI)
 1053                 value |= CDC_PACKET_TYPE_ALL_MULTICAST;
 1054 
 1055         req.bmRequestType = UT_CLASS | UT_INTERFACE;
 1056         req.bRequest = CDC_SET_ETHERNET_PACKET_FILTER;
 1057         USETW(req.wValue, value);
 1058         req.wIndex[0] = sc->sc_ifaces_index[1];
 1059         req.wIndex[1] = 0;
 1060         USETW(req.wLength, 0);
 1061 
 1062         /*
 1063          * Function below will drop the sc mutex.
 1064          * We can do that since we're called from a separate task,
 1065          * that simply wraps the setpromisc/setmulti methods.
 1066          */
 1067         usbd_do_request(sc->sc_ue.ue_udev, &sc->sc_mtx, &req, NULL);
 1068 }
 1069 
 1070 static int
 1071 cdce_suspend(device_t dev)
 1072 {
 1073         device_printf(dev, "Suspending\n");
 1074         return (0);
 1075 }
 1076 
 1077 static int
 1078 cdce_resume(device_t dev)
 1079 {
 1080         device_printf(dev, "Resuming\n");
 1081         return (0);
 1082 }
 1083 
 1084 static void
 1085 cdce_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
 1086 {
 1087         struct cdce_softc *sc = usbd_xfer_softc(xfer);
 1088         struct mbuf *m;
 1089         uint8_t x;
 1090         int actlen;
 1091         int aframes;
 1092         int len;
 1093 
 1094         usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
 1095 
 1096         switch (USB_GET_STATE(xfer)) {
 1097         case USB_ST_TRANSFERRED:
 1098 
 1099                 DPRINTF("received %u bytes in %u frames\n", actlen, aframes);
 1100 
 1101                 for (x = 0; x != aframes; x++) {
 1102                         m = sc->sc_rx_buf[x];
 1103                         sc->sc_rx_buf[x] = NULL;
 1104                         len = usbd_xfer_frame_len(xfer, x);
 1105 
 1106                         /* Strip off CRC added by Zaurus, if any */
 1107                         if ((sc->sc_flags & CDCE_FLAG_ZAURUS) && len >= 14)
 1108                                 len -= 4;
 1109 
 1110                         if (len < (int)sizeof(struct ether_header)) {
 1111                                 m_freem(m);
 1112                                 continue;
 1113                         }
 1114                         /* queue up mbuf */
 1115                         uether_rxmbuf(&sc->sc_ue, m, len);
 1116                 }
 1117 
 1118                 /* FALLTHROUGH */
 1119         case USB_ST_SETUP:
 1120                 /* 
 1121                  * TODO: Implement support for multi frame transfers,
 1122                  * when the USB hardware supports it.
 1123                  */
 1124                 for (x = 0; x != 1; x++) {
 1125                         if (sc->sc_rx_buf[x] == NULL) {
 1126                                 m = uether_newbuf();
 1127                                 if (m == NULL)
 1128                                         goto tr_stall;
 1129                                 sc->sc_rx_buf[x] = m;
 1130                         } else {
 1131                                 m = sc->sc_rx_buf[x];
 1132                         }
 1133 
 1134                         usbd_xfer_set_frame_data(xfer, x, m->m_data, m->m_len);
 1135                 }
 1136                 /* set number of frames and start hardware */
 1137                 usbd_xfer_set_frames(xfer, x);
 1138                 usbd_transfer_submit(xfer);
 1139                 /* flush any received frames */
 1140                 uether_rxflush(&sc->sc_ue);
 1141                 break;
 1142 
 1143         default:                        /* Error */
 1144                 DPRINTF("error = %s\n",
 1145                     usbd_errstr(error));
 1146 
 1147                 if (error != USB_ERR_CANCELLED) {
 1148 tr_stall:
 1149                         if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) {
 1150                                 /* try to clear stall first */
 1151                                 usbd_xfer_set_stall(xfer);
 1152                                 usbd_xfer_set_frames(xfer, 0);
 1153                                 usbd_transfer_submit(xfer);
 1154                         }
 1155                         break;
 1156                 }
 1157 
 1158                 /* need to free the RX-mbufs when we are cancelled */
 1159                 cdce_free_queue(sc->sc_rx_buf, CDCE_FRAMES_MAX);
 1160                 break;
 1161         }
 1162 }
 1163 
 1164 static void
 1165 cdce_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
 1166 {
 1167         u_char buf[CDCE_IND_SIZE_MAX];
 1168         struct usb_cdc_notification ucn;
 1169         struct cdce_softc *sc;
 1170         struct ifnet *ifp;
 1171         struct usb_page_cache *pc;
 1172         int off, actlen;
 1173         uint32_t downrate, uprate;
 1174 
 1175         sc = usbd_xfer_softc(xfer);
 1176         ifp = uether_getifp(&sc->sc_ue);
 1177         pc = usbd_xfer_get_frame(xfer, 0);
 1178 
 1179         usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
 1180 
 1181         switch (USB_GET_STATE(xfer)) {
 1182         case USB_ST_TRANSFERRED:
 1183                 if (USB_DEBUG_VAR)
 1184                         usbd_copy_out(pc, 0, buf, MIN(actlen, sizeof buf));
 1185                 DPRINTF("Received %d bytes: %*D\n", actlen,
 1186                     (int)MIN(actlen, sizeof buf), buf, "");
 1187 
 1188                 off = 0;
 1189                 while (actlen - off >= UCDC_NOTIFICATION_LENGTH) {
 1190                         usbd_copy_out(pc, off, &ucn, UCDC_NOTIFICATION_LENGTH);
 1191 
 1192                         do {
 1193                                 if (ucn.bmRequestType != 0xa1)
 1194                                         break;
 1195 
 1196                                 switch (ucn.bNotification) {
 1197                                 case UCDC_N_NETWORK_CONNECTION:
 1198                                         DPRINTF("changing link state: %d\n",
 1199                                             UGETW(ucn.wValue));
 1200                                         if_link_state_change(ifp,
 1201                                             UGETW(ucn.wValue) ? LINK_STATE_UP :
 1202                                             LINK_STATE_DOWN);
 1203                                         break;
 1204 
 1205                                 case UCDC_N_CONNECTION_SPEED_CHANGE:
 1206                                         if (UGETW(ucn.wLength) != 8)
 1207                                                 break;
 1208 
 1209                                         usbd_copy_out(pc, off +
 1210                                             UCDC_NOTIFICATION_LENGTH,
 1211                                             &ucn.data, UGETW(ucn.wLength));
 1212                                         downrate = UGETDW(ucn.data);
 1213                                         uprate = UGETDW(ucn.data);
 1214                                         if (downrate != uprate)
 1215                                                 break;
 1216 
 1217                                         /* set rate */
 1218                                         DPRINTF("changing baudrate: %u\n",
 1219                                             downrate);
 1220                                         if_setbaudrate(ifp, downrate);
 1221                                         break;
 1222 
 1223                                 default:
 1224                                         break;
 1225                                 }
 1226                         } while (0);
 1227 
 1228                         off += UCDC_NOTIFICATION_LENGTH + UGETW(ucn.wLength);
 1229                 }
 1230 
 1231                 /* FALLTHROUGH */
 1232         case USB_ST_SETUP:
 1233 tr_setup:
 1234                 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
 1235                 usbd_transfer_submit(xfer);
 1236                 break;
 1237 
 1238         default:                        /* Error */
 1239                 if (error != USB_ERR_CANCELLED) {
 1240                         /* start clear stall */
 1241                         if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST)
 1242                                 usbd_xfer_set_stall(xfer);
 1243                         goto tr_setup;
 1244                 }
 1245                 break;
 1246         }
 1247 }
 1248 
 1249 static void
 1250 cdce_intr_write_callback(struct usb_xfer *xfer, usb_error_t error)
 1251 {
 1252         struct cdce_softc *sc = usbd_xfer_softc(xfer);
 1253         struct usb_cdc_notification req;
 1254         struct usb_page_cache *pc;
 1255         uint32_t speed;
 1256         int actlen;
 1257 
 1258         usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
 1259 
 1260         switch (USB_GET_STATE(xfer)) {
 1261         case USB_ST_TRANSFERRED:
 1262 
 1263                 DPRINTF("Transferred %d bytes\n", actlen);
 1264 
 1265                 switch (sc->sc_notify_state) {
 1266                 case CDCE_NOTIFY_NETWORK_CONNECTION:
 1267                         sc->sc_notify_state = CDCE_NOTIFY_SPEED_CHANGE;
 1268                         break;
 1269                 case CDCE_NOTIFY_SPEED_CHANGE:
 1270                         sc->sc_notify_state = CDCE_NOTIFY_DONE;
 1271                         break;
 1272                 default:
 1273                         break;
 1274                 }
 1275 
 1276                 /* FALLTHROUGH */
 1277         case USB_ST_SETUP:
 1278 tr_setup:
 1279                 /*
 1280                  * Inform host about connection. Required according to USB CDC
 1281                  * specification and communicating to Mac OS X USB host stack.
 1282                  * Some of the values seems ignored by Mac OS X though.
 1283                  */
 1284                 if (sc->sc_notify_state == CDCE_NOTIFY_NETWORK_CONNECTION) {
 1285                         req.bmRequestType = UCDC_NOTIFICATION;
 1286                         req.bNotification = UCDC_N_NETWORK_CONNECTION;
 1287                         req.wIndex[0] = sc->sc_ifaces_index[1];
 1288                         req.wIndex[1] = 0;
 1289                         USETW(req.wValue, 1); /* Connected */
 1290                         USETW(req.wLength, 0);
 1291 
 1292                         pc = usbd_xfer_get_frame(xfer, 0);
 1293                         usbd_copy_in(pc, 0, &req, sizeof(req));
 1294                         usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
 1295                         usbd_xfer_set_frames(xfer, 1);
 1296                         usbd_transfer_submit(xfer); 
 1297 
 1298                 } else if (sc->sc_notify_state == CDCE_NOTIFY_SPEED_CHANGE) {
 1299                         req.bmRequestType = UCDC_NOTIFICATION;
 1300                         req.bNotification = UCDC_N_CONNECTION_SPEED_CHANGE;
 1301                         req.wIndex[0] = sc->sc_ifaces_index[1];
 1302                         req.wIndex[1] = 0;
 1303                         USETW(req.wValue, 0);
 1304                         USETW(req.wLength, 8);
 1305 
 1306                         /* Peak theoretical bulk trasfer rate in bits/s */
 1307                         if (usbd_get_speed(sc->sc_ue.ue_udev) != USB_SPEED_FULL)
 1308                                 speed = (13 * 512 * 8 * 1000 * 8);
 1309                         else
 1310                                 speed = (19 * 64 * 1 * 1000 * 8);
 1311 
 1312                         USETDW(req.data + 0, speed); /* Upstream bit rate */
 1313                         USETDW(req.data + 4, speed); /* Downstream bit rate */
 1314 
 1315                         pc = usbd_xfer_get_frame(xfer, 0);
 1316                         usbd_copy_in(pc, 0, &req, sizeof(req));
 1317                         usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
 1318                         usbd_xfer_set_frames(xfer, 1);
 1319                         usbd_transfer_submit(xfer); 
 1320                 }
 1321                 break;
 1322 
 1323         default:                        /* Error */
 1324                 if (error != USB_ERR_CANCELLED) {
 1325                         if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) {
 1326                                 /* start clear stall */
 1327                                 usbd_xfer_set_stall(xfer);
 1328                         }
 1329                         goto tr_setup;
 1330                 }
 1331                 break;
 1332         }
 1333 }
 1334 
 1335 static int
 1336 cdce_handle_request(device_t dev,
 1337     const void *preq, void **pptr, uint16_t *plen,
 1338     uint16_t offset, uint8_t *pstate)
 1339 {
 1340         struct cdce_softc *sc = device_get_softc(dev);
 1341         const struct usb_device_request *req = preq;
 1342         uint8_t is_complete = *pstate;
 1343 
 1344         /*
 1345          * When Mac OS X resumes after suspending it expects
 1346          * to be notified again after this request.
 1347          */
 1348         if (req->bmRequestType == UT_WRITE_CLASS_INTERFACE && \
 1349             req->bRequest == UCDC_NCM_SET_ETHERNET_PACKET_FILTER) {
 1350                 if (is_complete == 1) {
 1351                         mtx_lock(&sc->sc_mtx);
 1352                         sc->sc_notify_state = CDCE_NOTIFY_SPEED_CHANGE;
 1353                         usbd_transfer_start(sc->sc_xfer[CDCE_INTR_TX]);
 1354                         mtx_unlock(&sc->sc_mtx);
 1355                 }
 1356 
 1357                 return (0);
 1358         }
 1359 
 1360         return (ENXIO);                 /* use builtin handler */
 1361 }
 1362 
 1363 #if CDCE_HAVE_NCM
 1364 static void
 1365 cdce_ncm_tx_zero(struct usb_page_cache *pc,
 1366     uint32_t start, uint32_t end)
 1367 {
 1368         if (start >= CDCE_NCM_TX_MAXLEN)
 1369                 return;
 1370         if (end > CDCE_NCM_TX_MAXLEN)
 1371                 end = CDCE_NCM_TX_MAXLEN;
 1372 
 1373         usbd_frame_zero(pc, start, end - start);
 1374 }
 1375 
 1376 static uint8_t
 1377 cdce_ncm_fill_tx_frames(struct usb_xfer *xfer, uint8_t index)
 1378 {
 1379         struct cdce_softc *sc = usbd_xfer_softc(xfer);
 1380         struct ifnet *ifp = uether_getifp(&sc->sc_ue);
 1381         struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, index);
 1382         struct mbuf *m;
 1383         uint32_t rem;
 1384         uint32_t offset;
 1385         uint32_t last_offset;
 1386         uint16_t n;
 1387         uint8_t retval;
 1388 
 1389         usbd_xfer_set_frame_offset(xfer, index * CDCE_NCM_TX_MAXLEN, index);
 1390 
 1391         offset = sizeof(sc->sc_ncm.hdr) +
 1392             sizeof(sc->sc_ncm.dpt) + sizeof(sc->sc_ncm.dp);
 1393 
 1394         /* Store last valid offset before alignment */
 1395         last_offset = offset;
 1396 
 1397         /* Align offset */
 1398         offset = CDCE_NCM_ALIGN(sc->sc_ncm.tx_remainder,
 1399             offset, sc->sc_ncm.tx_modulus);
 1400 
 1401         /* Zero pad */
 1402         cdce_ncm_tx_zero(pc, last_offset, offset);
 1403 
 1404         /* buffer full */
 1405         retval = 2;
 1406 
 1407         for (n = 0; n != sc->sc_ncm.tx_nframe; n++) {
 1408                 /* check if end of transmit buffer is reached */
 1409 
 1410                 if (offset >= sc->sc_ncm.tx_max)
 1411                         break;
 1412 
 1413                 /* compute maximum buffer size */
 1414 
 1415                 rem = sc->sc_ncm.tx_max - offset;
 1416 
 1417                 IFQ_DRV_DEQUEUE(&(ifp->if_snd), m);
 1418 
 1419                 if (m == NULL) {
 1420                         /* buffer not full */
 1421                         retval = 1;
 1422                         break;
 1423                 }
 1424 
 1425                 if (m->m_pkthdr.len > (int)rem) {
 1426                         if (n == 0) {
 1427                                 /* The frame won't fit in our buffer */
 1428                                 DPRINTFN(1, "Frame too big to be transmitted!\n");
 1429                                 m_freem(m);
 1430                                 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 1431                                 n--;
 1432                                 continue;
 1433                         }
 1434                         /* Wait till next buffer becomes ready */
 1435                         IFQ_DRV_PREPEND(&(ifp->if_snd), m);
 1436                         break;
 1437                 }
 1438                 usbd_m_copy_in(pc, offset, m, 0, m->m_pkthdr.len);
 1439 
 1440                 USETW(sc->sc_ncm.dp[n].wFrameLength, m->m_pkthdr.len);
 1441                 USETW(sc->sc_ncm.dp[n].wFrameIndex, offset);
 1442 
 1443                 /* Update offset */
 1444                 offset += m->m_pkthdr.len;
 1445 
 1446                 /* Store last valid offset before alignment */
 1447                 last_offset = offset;
 1448 
 1449                 /* Align offset */
 1450                 offset = CDCE_NCM_ALIGN(sc->sc_ncm.tx_remainder,
 1451                     offset, sc->sc_ncm.tx_modulus);
 1452 
 1453                 /* Zero pad */
 1454                 cdce_ncm_tx_zero(pc, last_offset, offset);
 1455 
 1456                 /*
 1457                  * If there's a BPF listener, bounce a copy
 1458                  * of this frame to him:
 1459                  */
 1460                 BPF_MTAP(ifp, m);
 1461 
 1462                 /* Free mbuf */
 1463 
 1464                 m_freem(m);
 1465 
 1466                 /* Pre-increment interface counter */
 1467 
 1468                 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
 1469         }
 1470 
 1471         if (n == 0)
 1472                 return (0);
 1473 
 1474         rem = (sizeof(sc->sc_ncm.dpt) + (4 * n) + 4);
 1475 
 1476         USETW(sc->sc_ncm.dpt.wLength, rem);
 1477 
 1478         /* zero the rest of the data pointer entries */
 1479         for (; n != CDCE_NCM_SUBFRAMES_MAX; n++) {
 1480                 USETW(sc->sc_ncm.dp[n].wFrameLength, 0);
 1481                 USETW(sc->sc_ncm.dp[n].wFrameIndex, 0);
 1482         }
 1483 
 1484         offset = last_offset;
 1485 
 1486         /* Align offset */
 1487         offset = CDCE_NCM_ALIGN(0, offset, CDCE_NCM_TX_MINLEN);
 1488 
 1489         /* Optimise, save bandwidth and force short termination */
 1490         if (offset >= sc->sc_ncm.tx_max)
 1491                 offset = sc->sc_ncm.tx_max;
 1492         else
 1493                 offset ++;
 1494 
 1495         /* Zero pad */
 1496         cdce_ncm_tx_zero(pc, last_offset, offset);
 1497 
 1498         /* set frame length */
 1499         usbd_xfer_set_frame_len(xfer, index, offset);
 1500 
 1501         /* Fill out 16-bit header */
 1502         sc->sc_ncm.hdr.dwSignature[0] = 'N';
 1503         sc->sc_ncm.hdr.dwSignature[1] = 'C';
 1504         sc->sc_ncm.hdr.dwSignature[2] = 'M';
 1505         sc->sc_ncm.hdr.dwSignature[3] = 'H';
 1506         USETW(sc->sc_ncm.hdr.wHeaderLength, sizeof(sc->sc_ncm.hdr));
 1507         USETW(sc->sc_ncm.hdr.wBlockLength, offset);
 1508         USETW(sc->sc_ncm.hdr.wSequence, sc->sc_ncm.tx_seq);
 1509         USETW(sc->sc_ncm.hdr.wDptIndex, sizeof(sc->sc_ncm.hdr));
 1510 
 1511         sc->sc_ncm.tx_seq++;
 1512 
 1513         /* Fill out 16-bit frame table header */
 1514         sc->sc_ncm.dpt.dwSignature[0] = 'N';
 1515         sc->sc_ncm.dpt.dwSignature[1] = 'C';
 1516         sc->sc_ncm.dpt.dwSignature[2] = 'M';
 1517         sc->sc_ncm.dpt.dwSignature[3] = '';
 1518         USETW(sc->sc_ncm.dpt.wNextNdpIndex, 0);         /* reserved */
 1519 
 1520         usbd_copy_in(pc, 0, &(sc->sc_ncm.hdr), sizeof(sc->sc_ncm.hdr));
 1521         usbd_copy_in(pc, sizeof(sc->sc_ncm.hdr), &(sc->sc_ncm.dpt),
 1522             sizeof(sc->sc_ncm.dpt));
 1523         usbd_copy_in(pc, sizeof(sc->sc_ncm.hdr) + sizeof(sc->sc_ncm.dpt),
 1524             &(sc->sc_ncm.dp), sizeof(sc->sc_ncm.dp));
 1525         return (retval);
 1526 }
 1527 
 1528 static void
 1529 cdce_ncm_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
 1530 {
 1531         struct cdce_softc *sc = usbd_xfer_softc(xfer);
 1532         struct ifnet *ifp = uether_getifp(&sc->sc_ue);
 1533         uint16_t x;
 1534         uint8_t temp;
 1535         int actlen;
 1536         int aframes;
 1537 
 1538         switch (USB_GET_STATE(xfer)) {
 1539         case USB_ST_TRANSFERRED:
 1540 
 1541                 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
 1542 
 1543                 DPRINTFN(10, "transfer complete: "
 1544                     "%u bytes in %u frames\n", actlen, aframes);
 1545 
 1546         case USB_ST_SETUP:
 1547                 for (x = 0; x != CDCE_NCM_TX_FRAMES_MAX; x++) {
 1548                         temp = cdce_ncm_fill_tx_frames(xfer, x);
 1549                         if (temp == 0)
 1550                                 break;
 1551                         if (temp == 1) {
 1552                                 x++;
 1553                                 break;
 1554                         }
 1555                 }
 1556 
 1557                 if (x != 0) {
 1558 #ifdef USB_DEBUG
 1559                         usbd_xfer_set_interval(xfer, cdce_tx_interval);
 1560 #endif
 1561                         usbd_xfer_set_frames(xfer, x);
 1562                         usbd_transfer_submit(xfer);
 1563                 }
 1564                 break;
 1565 
 1566         default:                        /* Error */
 1567                 DPRINTFN(10, "Transfer error: %s\n",
 1568                     usbd_errstr(error));
 1569 
 1570                 /* update error counter */
 1571                 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 1572 
 1573                 if (error != USB_ERR_CANCELLED) {
 1574                         if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) {
 1575                                 /* try to clear stall first */
 1576                                 usbd_xfer_set_stall(xfer);
 1577                                 usbd_xfer_set_frames(xfer, 0);
 1578                                 usbd_transfer_submit(xfer);
 1579                         }
 1580                 }
 1581                 break;
 1582         }
 1583 }
 1584 
 1585 static void
 1586 cdce_ncm_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
 1587 {
 1588         struct cdce_softc *sc = usbd_xfer_softc(xfer);
 1589         struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, 0);
 1590         struct ifnet *ifp = uether_getifp(&sc->sc_ue);
 1591         struct mbuf *m;
 1592         int sumdata __usbdebug_used;
 1593         int sumlen;
 1594         int actlen;
 1595         int aframes;
 1596         int temp;
 1597         int nframes;
 1598         int x;
 1599         int offset;
 1600 
 1601         switch (USB_GET_STATE(xfer)) {
 1602         case USB_ST_TRANSFERRED:
 1603 
 1604                 usbd_xfer_status(xfer, &actlen, &sumlen, &aframes, NULL);
 1605 
 1606                 DPRINTFN(1, "received %u bytes in %u frames\n",
 1607                     actlen, aframes);
 1608 
 1609                 if (actlen < (int)(sizeof(sc->sc_ncm.hdr) +
 1610                     sizeof(sc->sc_ncm.dpt))) {
 1611                         DPRINTFN(1, "frame too short\n");
 1612                         goto tr_setup;
 1613                 }
 1614                 usbd_copy_out(pc, 0, &(sc->sc_ncm.hdr),
 1615                     sizeof(sc->sc_ncm.hdr));
 1616 
 1617                 if ((sc->sc_ncm.hdr.dwSignature[0] != 'N') ||
 1618                     (sc->sc_ncm.hdr.dwSignature[1] != 'C') ||
 1619                     (sc->sc_ncm.hdr.dwSignature[2] != 'M') ||
 1620                     (sc->sc_ncm.hdr.dwSignature[3] != 'H')) {
 1621                         DPRINTFN(1, "invalid HDR signature: "
 1622                             "0x%02x:0x%02x:0x%02x:0x%02x\n",
 1623                             sc->sc_ncm.hdr.dwSignature[0],
 1624                             sc->sc_ncm.hdr.dwSignature[1],
 1625                             sc->sc_ncm.hdr.dwSignature[2],
 1626                             sc->sc_ncm.hdr.dwSignature[3]);
 1627                         goto tr_stall;
 1628                 }
 1629                 temp = UGETW(sc->sc_ncm.hdr.wBlockLength);
 1630                 if (temp > sumlen) {
 1631                         DPRINTFN(1, "unsupported block length %u/%u\n",
 1632                             temp, sumlen);
 1633                         goto tr_stall;
 1634                 }
 1635                 temp = UGETW(sc->sc_ncm.hdr.wDptIndex);
 1636                 if ((int)(temp + sizeof(sc->sc_ncm.dpt)) > actlen) {
 1637                         DPRINTFN(1, "invalid DPT index: 0x%04x\n", temp);
 1638                         goto tr_stall;
 1639                 }
 1640                 usbd_copy_out(pc, temp, &(sc->sc_ncm.dpt),
 1641                     sizeof(sc->sc_ncm.dpt));
 1642 
 1643                 if ((sc->sc_ncm.dpt.dwSignature[0] != 'N') ||
 1644                     (sc->sc_ncm.dpt.dwSignature[1] != 'C') ||
 1645                     (sc->sc_ncm.dpt.dwSignature[2] != 'M') ||
 1646                     (sc->sc_ncm.dpt.dwSignature[3] != '')) {
 1647                         DPRINTFN(1, "invalid DPT signature"
 1648                             "0x%02x:0x%02x:0x%02x:0x%02x\n",
 1649                             sc->sc_ncm.dpt.dwSignature[0],
 1650                             sc->sc_ncm.dpt.dwSignature[1],
 1651                             sc->sc_ncm.dpt.dwSignature[2],
 1652                             sc->sc_ncm.dpt.dwSignature[3]);
 1653                         goto tr_stall;
 1654                 }
 1655                 nframes = UGETW(sc->sc_ncm.dpt.wLength) / 4;
 1656 
 1657                 /* Subtract size of header and last zero padded entry */
 1658                 if (nframes >= (2 + 1))
 1659                         nframes -= (2 + 1);
 1660                 else
 1661                         nframes = 0;
 1662 
 1663                 DPRINTFN(1, "nframes = %u\n", nframes);
 1664 
 1665                 temp += sizeof(sc->sc_ncm.dpt);
 1666 
 1667                 if ((temp + (4 * nframes)) > actlen)
 1668                         goto tr_stall;
 1669 
 1670                 if (nframes > CDCE_NCM_SUBFRAMES_MAX) {
 1671                         DPRINTFN(1, "Truncating number of frames from %u to %u\n",
 1672                             nframes, CDCE_NCM_SUBFRAMES_MAX);
 1673                         nframes = CDCE_NCM_SUBFRAMES_MAX;
 1674                 }
 1675                 usbd_copy_out(pc, temp, &(sc->sc_ncm.dp), (4 * nframes));
 1676 
 1677                 sumdata = 0;
 1678 
 1679                 for (x = 0; x != nframes; x++) {
 1680                         offset = UGETW(sc->sc_ncm.dp[x].wFrameIndex);
 1681                         temp = UGETW(sc->sc_ncm.dp[x].wFrameLength);
 1682 
 1683                         if ((offset == 0) ||
 1684                             (temp < (int)sizeof(struct ether_header)) ||
 1685                             (temp > (MCLBYTES - ETHER_ALIGN))) {
 1686                                 DPRINTFN(1, "NULL frame detected at %d\n", x);
 1687                                 m = NULL;
 1688                                 /* silently ignore this frame */
 1689                                 continue;
 1690                         } else if ((offset + temp) > actlen) {
 1691                                 DPRINTFN(1, "invalid frame "
 1692                                     "detected at %d\n", x);
 1693                                 m = NULL;
 1694                                 /* silently ignore this frame */
 1695                                 continue;
 1696                         } else if (temp > (int)(MHLEN - ETHER_ALIGN)) {
 1697                                 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
 1698                         } else {
 1699                                 m = m_gethdr(M_NOWAIT, MT_DATA);
 1700                         }
 1701 
 1702                         DPRINTFN(16, "frame %u, offset = %u, length = %u \n",
 1703                             x, offset, temp);
 1704 
 1705                         /* check if we have a buffer */
 1706                         if (m) {
 1707                                 m->m_len = m->m_pkthdr.len = temp + ETHER_ALIGN;
 1708                                 m_adj(m, ETHER_ALIGN);
 1709 
 1710                                 usbd_copy_out(pc, offset, m->m_data, temp);
 1711 
 1712                                 /* enqueue */
 1713                                 uether_rxmbuf(&sc->sc_ue, m, temp);
 1714 
 1715                                 sumdata += temp;
 1716                         } else {
 1717                                 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
 1718                         }
 1719                 }
 1720 
 1721                 DPRINTFN(1, "Efficiency: %u/%u bytes\n", sumdata, actlen);
 1722 
 1723         case USB_ST_SETUP:
 1724 tr_setup:
 1725                 usbd_xfer_set_frame_len(xfer, 0, sc->sc_ncm.rx_max);
 1726                 usbd_xfer_set_frames(xfer, 1);
 1727                 usbd_transfer_submit(xfer);
 1728                 uether_rxflush(&sc->sc_ue);     /* must be last */
 1729                 break;
 1730 
 1731         default:                        /* Error */
 1732                 DPRINTFN(1, "error = %s\n",
 1733                     usbd_errstr(error));
 1734 
 1735                 if (error != USB_ERR_CANCELLED) {
 1736 tr_stall:
 1737                         if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) {
 1738                                 /* try to clear stall first */
 1739                                 usbd_xfer_set_stall(xfer);
 1740                                 usbd_xfer_set_frames(xfer, 0);
 1741                                 usbd_transfer_submit(xfer);
 1742                         }
 1743                 }
 1744                 break;
 1745         }
 1746 }
 1747 #endif

Cache object: e43a39162e6e964f91fa29a46412d4cf


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.