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_urndis.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 /*      $OpenBSD: if_urndis.c,v 1.46 2013/12/09 15:45:29 pirofti Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2010 Jonathan Armani <armani@openbsd.org>
    5  * Copyright (c) 2010 Fabien Romano <fabien@openbsd.org>
    6  * Copyright (c) 2010 Michael Knudsen <mk@openbsd.org>
    7  * Copyright (c) 2014 Hans Petter Selasky <hselasky@freebsd.org>
    8  * All rights reserved.
    9  *
   10  * Permission to use, copy, modify, and distribute this software for any
   11  * purpose with or without fee is hereby granted, provided that the above
   12  * copyright notice and this permission notice appear in all copies.
   13  *
   14  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   15  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   16  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   17  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   19  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   20  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   21  */
   22 
   23 #include <sys/cdefs.h>
   24 __FBSDID("$FreeBSD$");
   25 
   26 #include <sys/stdint.h>
   27 #include <sys/stddef.h>
   28 #include <sys/param.h>
   29 #include <sys/queue.h>
   30 #include <sys/types.h>
   31 #include <sys/systm.h>
   32 #include <sys/socket.h>
   33 #include <sys/kernel.h>
   34 #include <sys/bus.h>
   35 #include <sys/module.h>
   36 #include <sys/lock.h>
   37 #include <sys/mutex.h>
   38 #include <sys/condvar.h>
   39 #include <sys/sysctl.h>
   40 #include <sys/sx.h>
   41 #include <sys/unistd.h>
   42 #include <sys/callout.h>
   43 #include <sys/malloc.h>
   44 #include <sys/priv.h>
   45 
   46 #include <net/if.h>
   47 #include <net/if_var.h>
   48 #include <net/rndis.h>
   49 
   50 #include <dev/usb/usb.h>
   51 #include <dev/usb/usbdi.h>
   52 #include <dev/usb/usbdi_util.h>
   53 #include "usbdevs.h"
   54 
   55 #define USB_DEBUG_VAR urndis_debug
   56 #include <dev/usb/usb_debug.h>
   57 #include <dev/usb/usb_process.h>
   58 #include "usb_if.h"
   59 
   60 #include <dev/usb/net/usb_ethernet.h>
   61 #include <dev/usb/net/if_urndisreg.h>
   62 
   63 #include <dev/usb/usb_cdc.h>
   64 
   65 static device_probe_t urndis_probe;
   66 static device_attach_t urndis_attach;
   67 static device_detach_t urndis_detach;
   68 static device_suspend_t urndis_suspend;
   69 static device_resume_t urndis_resume;
   70 
   71 static usb_callback_t urndis_bulk_write_callback;
   72 static usb_callback_t urndis_bulk_read_callback;
   73 static usb_callback_t urndis_intr_read_callback;
   74 
   75 static uether_fn_t urndis_attach_post;
   76 static uether_fn_t urndis_init;
   77 static uether_fn_t urndis_stop;
   78 static uether_fn_t urndis_start;
   79 static uether_fn_t urndis_setmulti;
   80 static uether_fn_t urndis_setpromisc;
   81 
   82 static uint32_t urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid,
   83                     struct rndis_query_req *msg, uint16_t len,
   84                     const void **rbuf, uint16_t *rbufsz);
   85 static uint32_t urndis_ctrl_set(struct urndis_softc *sc, uint32_t oid,
   86                     struct rndis_set_req *msg, uint16_t len);
   87 static uint32_t urndis_ctrl_handle_init(struct urndis_softc *sc,
   88                     const struct rndis_comp_hdr *hdr);
   89 static uint32_t urndis_ctrl_handle_query(struct urndis_softc *sc,
   90                     const struct rndis_comp_hdr *hdr, const void **buf,
   91                     uint16_t *bufsz);
   92 static uint32_t urndis_ctrl_handle_reset(struct urndis_softc *sc,
   93                     const struct rndis_comp_hdr *hdr);
   94 static uint32_t urndis_ctrl_init(struct urndis_softc *sc);
   95 static uint32_t urndis_ctrl_halt(struct urndis_softc *sc);
   96 
   97 #ifdef USB_DEBUG
   98 static int urndis_debug = 0;
   99 static  SYSCTL_NODE(_hw_usb, OID_AUTO, urndis, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
  100     "USB RNDIS-Ethernet");
  101 SYSCTL_INT(_hw_usb_urndis, OID_AUTO, debug, CTLFLAG_RWTUN, &urndis_debug, 0,
  102     "Debug level");
  103 #endif
  104 
  105 static const struct usb_config urndis_config[URNDIS_N_TRANSFER] = {
  106         [URNDIS_BULK_RX] = {
  107                 .type = UE_BULK,
  108                 .endpoint = UE_ADDR_ANY,
  109                 .direction = UE_DIR_RX,
  110                 .if_index = 0,
  111                 .frames = 1,
  112                 .bufsize = RNDIS_RX_MAXLEN,
  113                 .flags = {.short_xfer_ok = 1,},
  114                 .callback = urndis_bulk_read_callback,
  115                 .timeout = 0,           /* no timeout */
  116                 .usb_mode = USB_MODE_HOST,
  117         },
  118 
  119         [URNDIS_BULK_TX] = {
  120                 .type = UE_BULK,
  121                 .endpoint = UE_ADDR_ANY,
  122                 .direction = UE_DIR_TX,
  123                 .if_index = 0,
  124                 .frames = RNDIS_TX_FRAMES_MAX,
  125                 .bufsize = (RNDIS_TX_FRAMES_MAX * RNDIS_TX_MAXLEN),
  126                 .flags = {
  127                         .force_short_xfer = 1,
  128                 },
  129                 .callback = urndis_bulk_write_callback,
  130                 .timeout = 10000,       /* 10 seconds */
  131                 .usb_mode = USB_MODE_HOST,
  132         },
  133 
  134         [URNDIS_INTR_RX] = {
  135                 .type = UE_INTERRUPT,
  136                 .endpoint = UE_ADDR_ANY,
  137                 .direction = UE_DIR_RX,
  138                 .if_index = 1,
  139                 .bufsize = 0,   /* use wMaxPacketSize */
  140                 .flags = {.short_xfer_ok = 1,.no_pipe_ok = 1,},
  141                 .callback = urndis_intr_read_callback,
  142                 .timeout = 0,
  143                 .usb_mode = USB_MODE_HOST,
  144         },
  145 };
  146 
  147 static device_method_t urndis_methods[] = {
  148         /* Device interface */
  149         DEVMETHOD(device_probe, urndis_probe),
  150         DEVMETHOD(device_attach, urndis_attach),
  151         DEVMETHOD(device_detach, urndis_detach),
  152         DEVMETHOD(device_suspend, urndis_suspend),
  153         DEVMETHOD(device_resume, urndis_resume),
  154 
  155         DEVMETHOD_END
  156 };
  157 
  158 static driver_t urndis_driver = {
  159         .name = "urndis",
  160         .methods = urndis_methods,
  161         .size = sizeof(struct urndis_softc),
  162 };
  163 
  164 static const STRUCT_USB_HOST_ID urndis_host_devs[] = {
  165         /* Generic RNDIS class match */
  166         {USB_IFACE_CLASS(UICLASS_CDC),
  167                 USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL),
  168                 USB_IFACE_PROTOCOL(0xff)},
  169         {USB_IFACE_CLASS(UICLASS_WIRELESS), USB_IFACE_SUBCLASS(UISUBCLASS_RF),
  170                 USB_IFACE_PROTOCOL(UIPROTO_RNDIS)},
  171         {USB_IFACE_CLASS(UICLASS_IAD), USB_IFACE_SUBCLASS(UISUBCLASS_SYNC),
  172                 USB_IFACE_PROTOCOL(UIPROTO_ACTIVESYNC)},
  173         /* HP-WebOS */
  174         {USB_VENDOR(USB_VENDOR_PALM), USB_IFACE_CLASS(UICLASS_CDC),
  175                 USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL),
  176                 USB_IFACE_PROTOCOL(0xff)},
  177         /* Nokia 7 plus */
  178         {USB_IFACE_CLASS(UICLASS_IAD), USB_IFACE_SUBCLASS(0x4),
  179                 USB_IFACE_PROTOCOL(UIPROTO_ACTIVESYNC)},
  180         /* Novatel Wireless 8800/8000/etc */
  181         {USB_IFACE_CLASS(UICLASS_IAD), USB_IFACE_SUBCLASS(0xef),
  182                 USB_IFACE_PROTOCOL(UIPROTO_RNDIS)},
  183 };
  184 
  185 DRIVER_MODULE(urndis, uhub, urndis_driver, NULL, NULL);
  186 MODULE_VERSION(urndis, 1);
  187 MODULE_DEPEND(urndis, uether, 1, 1, 1);
  188 MODULE_DEPEND(urndis, usb, 1, 1, 1);
  189 MODULE_DEPEND(urndis, ether, 1, 1, 1);
  190 USB_PNP_HOST_INFO(urndis_host_devs);
  191 
  192 static const struct usb_ether_methods urndis_ue_methods = {
  193         .ue_attach_post = urndis_attach_post,
  194         .ue_start = urndis_start,
  195         .ue_init = urndis_init,
  196         .ue_stop = urndis_stop,
  197         .ue_setmulti = urndis_setmulti,
  198         .ue_setpromisc = urndis_setpromisc,
  199 };
  200 
  201 static int
  202 urndis_probe(device_t dev)
  203 {
  204         struct usb_attach_arg *uaa = device_get_ivars(dev);
  205 
  206         return (usbd_lookup_id_by_uaa(urndis_host_devs, sizeof(urndis_host_devs), uaa));
  207 }
  208 
  209 static void
  210 urndis_attach_post(struct usb_ether *ue)
  211 {
  212 
  213         /* no-op */
  214 }
  215 
  216 static int
  217 urndis_attach(device_t dev)
  218 {
  219         static struct {
  220                 union {
  221                         struct rndis_query_req query;
  222                         struct rndis_set_req set;
  223                 } hdr;
  224                 union {
  225                         uint8_t eaddr[ETHER_ADDR_LEN];
  226                         uint32_t filter;
  227                 } ibuf;
  228         } msg;
  229         struct urndis_softc *sc = device_get_softc(dev);
  230         struct usb_ether *ue = &sc->sc_ue;
  231         struct usb_attach_arg *uaa = device_get_ivars(dev);
  232         struct usb_cdc_cm_descriptor *cmd;
  233         const void *buf;
  234         uint16_t bufsz;
  235         uint8_t iface_index[2] = { uaa->info.bIfaceIndex + 1, uaa->info.bIfaceIndex };
  236         int error;
  237         uint8_t i;
  238 
  239         sc->sc_ue.ue_udev = uaa->device;
  240         sc->sc_ifaceno_ctl = uaa->info.bIfaceNum;
  241 
  242         cmd = usbd_find_descriptor(uaa->device, NULL, uaa->info.bIfaceIndex,
  243             UDESC_CS_INTERFACE, 0xFF, UDESCSUB_CDC_CM, 0xFF);
  244         if (cmd != NULL) {
  245                 DPRINTF("Call Mode Descriptor found, dataif=%d\n", cmd->bDataInterface);
  246                 iface_index[0] = cmd->bDataInterface;
  247         }
  248 
  249         device_set_usb_desc(dev);
  250 
  251         mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
  252 
  253         /* scan the alternate settings looking for a valid one */
  254         for (i = 0; i != 32; i++) {
  255                 error = usbd_set_alt_interface_index(uaa->device,
  256                     iface_index[0], i);
  257 
  258                 if (error != 0)
  259                         break;
  260 
  261                 error = usbd_transfer_setup(uaa->device,
  262                     iface_index, sc->sc_xfer, urndis_config,
  263                     URNDIS_N_TRANSFER, sc, &sc->sc_mtx);
  264 
  265                 if (error == 0)
  266                         break;
  267         }
  268         if ((error != 0) || (i == 32)) {
  269                 device_printf(dev, "No valid alternate setting found\n");
  270                 goto detach;
  271         }
  272 
  273         /* Initialize device - must be done before even querying it */
  274         URNDIS_LOCK(sc);
  275         error = urndis_ctrl_init(sc);
  276         URNDIS_UNLOCK(sc);
  277         if (error != (int)RNDIS_STATUS_SUCCESS) {
  278                 device_printf(dev, "Unable to initialize hardware\n");
  279                 goto detach;
  280         }
  281 
  282         /* Determine MAC address */
  283         memset(msg.ibuf.eaddr, 0, sizeof(msg.ibuf.eaddr));
  284         URNDIS_LOCK(sc);
  285         error = urndis_ctrl_query(sc, OID_802_3_PERMANENT_ADDRESS,
  286             &msg.hdr.query, sizeof(msg.hdr.query) + sizeof(msg.ibuf.eaddr),
  287             &buf, &bufsz);
  288         URNDIS_UNLOCK(sc);
  289         if (error != (int)RNDIS_STATUS_SUCCESS) {
  290                 device_printf(dev, "Unable to get hardware address\n");
  291                 goto detach;
  292         }
  293         if (bufsz != ETHER_ADDR_LEN) {
  294                 device_printf(dev, "Invalid address length: %d bytes\n", bufsz);
  295                 goto detach;
  296         }
  297         memcpy(&sc->sc_ue.ue_eaddr, buf, ETHER_ADDR_LEN);
  298 
  299         /* Initialize packet filter */
  300         sc->sc_filter = NDIS_PACKET_TYPE_BROADCAST |
  301             NDIS_PACKET_TYPE_ALL_MULTICAST;
  302         msg.ibuf.filter = htole32(sc->sc_filter);
  303         URNDIS_LOCK(sc);
  304         error = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
  305             &msg.hdr.set, sizeof(msg.hdr.set) + sizeof(msg.ibuf.filter));
  306         URNDIS_UNLOCK(sc);
  307         if (error != (int)RNDIS_STATUS_SUCCESS) {
  308                 device_printf(dev, "Unable to set data filters\n");
  309                 goto detach;
  310         }
  311 
  312         ue->ue_sc = sc;
  313         ue->ue_dev = dev;
  314         ue->ue_udev = uaa->device;
  315         ue->ue_mtx = &sc->sc_mtx;
  316         ue->ue_methods = &urndis_ue_methods;
  317 
  318         error = uether_ifattach(ue);
  319         if (error) {
  320                 device_printf(dev, "Could not attach interface\n");
  321                 goto detach;
  322         }
  323 
  324         URNDIS_LOCK(sc);
  325         /* start interrupt endpoint, if any */
  326         usbd_transfer_start(sc->sc_xfer[URNDIS_INTR_RX]);
  327         URNDIS_UNLOCK(sc);
  328 
  329         return (0);                     /* success */
  330 
  331 detach:
  332         (void)urndis_detach(dev);
  333         return (ENXIO);                 /* failure */
  334 }
  335 
  336 static int
  337 urndis_detach(device_t dev)
  338 {
  339         struct urndis_softc *sc = device_get_softc(dev);
  340         struct usb_ether *ue = &sc->sc_ue;
  341 
  342         /* stop all USB transfers first */
  343         usbd_transfer_unsetup(sc->sc_xfer, URNDIS_N_TRANSFER);
  344 
  345         uether_ifdetach(ue);
  346 
  347         URNDIS_LOCK(sc);
  348         (void)urndis_ctrl_halt(sc);
  349         URNDIS_UNLOCK(sc);
  350 
  351         mtx_destroy(&sc->sc_mtx);
  352 
  353         return (0);
  354 }
  355 
  356 static void
  357 urndis_start(struct usb_ether *ue)
  358 {
  359         struct urndis_softc *sc = uether_getsc(ue);
  360 
  361         /*
  362          * Start the USB transfers, if not already started:
  363          */
  364         usbd_transfer_start(sc->sc_xfer[URNDIS_BULK_TX]);
  365         usbd_transfer_start(sc->sc_xfer[URNDIS_BULK_RX]);
  366 }
  367 
  368 static void
  369 urndis_init(struct usb_ether *ue)
  370 {
  371         struct urndis_softc *sc = uether_getsc(ue);
  372         struct ifnet *ifp = uether_getifp(ue);
  373 
  374         URNDIS_LOCK_ASSERT(sc, MA_OWNED);
  375 
  376         ifp->if_drv_flags |= IFF_DRV_RUNNING;
  377 
  378         /* stall data write direction, which depends on USB mode */
  379         usbd_xfer_set_stall(sc->sc_xfer[URNDIS_BULK_TX]);
  380 
  381         /* start data transfers */
  382         urndis_start(ue);
  383 }
  384 
  385 static void
  386 urndis_stop(struct usb_ether *ue)
  387 {
  388         struct urndis_softc *sc = uether_getsc(ue);
  389         struct ifnet *ifp = uether_getifp(ue);
  390 
  391         URNDIS_LOCK_ASSERT(sc, MA_OWNED);
  392 
  393         ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
  394 
  395         /*
  396          * stop all the transfers, if not already stopped:
  397          */
  398         usbd_transfer_stop(sc->sc_xfer[URNDIS_BULK_RX]);
  399         usbd_transfer_stop(sc->sc_xfer[URNDIS_BULK_TX]);
  400 }
  401 
  402 static void
  403 urndis_setmulti(struct usb_ether *ue)
  404 {
  405 
  406         /* no-op */
  407 }
  408 
  409 static void
  410 urndis_setpromisc(struct usb_ether *ue)
  411 {
  412 
  413         /* no-op */
  414 }
  415 
  416 static int
  417 urndis_suspend(device_t dev)
  418 {
  419 
  420         device_printf(dev, "Suspending\n");
  421         return (0);
  422 }
  423 
  424 static int
  425 urndis_resume(device_t dev)
  426 {
  427 
  428         device_printf(dev, "Resuming\n");
  429         return (0);
  430 }
  431 
  432 static usb_error_t
  433 urndis_ctrl_msg(struct urndis_softc *sc, uint8_t rt, uint8_t r,
  434     uint16_t index, uint16_t value, void *buf, uint16_t buflen)
  435 {
  436         usb_device_request_t req;
  437 
  438         req.bmRequestType = rt;
  439         req.bRequest = r;
  440         USETW(req.wValue, value);
  441         USETW(req.wIndex, index);
  442         USETW(req.wLength, buflen);
  443 
  444         return (usbd_do_request_flags(sc->sc_ue.ue_udev,
  445             &sc->sc_mtx, &req, buf, (rt & UT_READ) ?
  446             USB_SHORT_XFER_OK : 0, NULL, 2000 /* ms */ ));
  447 }
  448 
  449 static usb_error_t
  450 urndis_ctrl_send(struct urndis_softc *sc, void *buf, uint16_t len)
  451 {
  452         usb_error_t err;
  453 
  454         err = urndis_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE,
  455             UCDC_SEND_ENCAPSULATED_COMMAND, sc->sc_ifaceno_ctl, 0, buf, len);
  456 
  457         DPRINTF("%s\n", usbd_errstr(err));
  458 
  459         return (err);
  460 }
  461 
  462 static struct rndis_comp_hdr *
  463 urndis_ctrl_recv(struct urndis_softc *sc)
  464 {
  465         struct rndis_comp_hdr *hdr;
  466         usb_error_t err;
  467 
  468         err = urndis_ctrl_msg(sc, UT_READ_CLASS_INTERFACE,
  469             UCDC_GET_ENCAPSULATED_RESPONSE, sc->sc_ifaceno_ctl, 0,
  470             sc->sc_response_buf, RNDIS_RESPONSE_LEN);
  471 
  472         if (err != USB_ERR_NORMAL_COMPLETION)
  473                 return (NULL);
  474 
  475         hdr = (struct rndis_comp_hdr *)sc->sc_response_buf;
  476 
  477         DPRINTF("type 0x%x len %u\n", le32toh(hdr->rm_type),
  478             le32toh(hdr->rm_len));
  479 
  480         if (le32toh(hdr->rm_len) > RNDIS_RESPONSE_LEN) {
  481                 DPRINTF("ctrl message error: wrong size %u > %u\n",
  482                     le32toh(hdr->rm_len), RNDIS_RESPONSE_LEN);
  483                 return (NULL);
  484         }
  485         return (hdr);
  486 }
  487 
  488 static uint32_t
  489 urndis_ctrl_handle(struct urndis_softc *sc, struct rndis_comp_hdr *hdr,
  490     const void **buf, uint16_t *bufsz)
  491 {
  492         uint32_t rval;
  493 
  494         DPRINTF("\n");
  495 
  496         if (buf != NULL && bufsz != NULL) {
  497                 *buf = NULL;
  498                 *bufsz = 0;
  499         }
  500         switch (le32toh(hdr->rm_type)) {
  501         case REMOTE_NDIS_INITIALIZE_CMPLT:
  502                 rval = urndis_ctrl_handle_init(sc, hdr);
  503                 break;
  504 
  505         case REMOTE_NDIS_QUERY_CMPLT:
  506                 rval = urndis_ctrl_handle_query(sc, hdr, buf, bufsz);
  507                 break;
  508 
  509         case REMOTE_NDIS_RESET_CMPLT:
  510                 rval = urndis_ctrl_handle_reset(sc, hdr);
  511                 break;
  512 
  513         case REMOTE_NDIS_KEEPALIVE_CMPLT:
  514         case REMOTE_NDIS_SET_CMPLT:
  515                 rval = le32toh(hdr->rm_status);
  516                 break;
  517 
  518         default:
  519                 device_printf(sc->sc_ue.ue_dev,
  520                     "ctrl message error: unknown event 0x%x\n",
  521                     le32toh(hdr->rm_type));
  522                 rval = RNDIS_STATUS_FAILURE;
  523                 break;
  524         }
  525         return (rval);
  526 }
  527 
  528 static uint32_t
  529 urndis_ctrl_handle_init(struct urndis_softc *sc,
  530     const struct rndis_comp_hdr *hdr)
  531 {
  532         const struct rndis_init_comp *msg;
  533 
  534         msg = (const struct rndis_init_comp *)hdr;
  535 
  536         DPRINTF("len %u rid %u status 0x%x "
  537             "ver_major %u ver_minor %u devflags 0x%x medium 0x%x pktmaxcnt %u "
  538             "pktmaxsz %u align %u aflistoffset %u aflistsz %u\n",
  539             le32toh(msg->rm_len),
  540             le32toh(msg->rm_rid),
  541             le32toh(msg->rm_status),
  542             le32toh(msg->rm_ver_major),
  543             le32toh(msg->rm_ver_minor),
  544             le32toh(msg->rm_devflags),
  545             le32toh(msg->rm_medium),
  546             le32toh(msg->rm_pktmaxcnt),
  547             le32toh(msg->rm_pktmaxsz),
  548             le32toh(msg->rm_align),
  549             le32toh(msg->rm_aflistoffset),
  550             le32toh(msg->rm_aflistsz));
  551 
  552         if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
  553                 DPRINTF("init failed 0x%x\n", le32toh(msg->rm_status));
  554                 return (le32toh(msg->rm_status));
  555         }
  556         if (le32toh(msg->rm_devflags) != RNDIS_DF_CONNECTIONLESS) {
  557                 DPRINTF("wrong device type (current type: 0x%x)\n",
  558                     le32toh(msg->rm_devflags));
  559                 return (RNDIS_STATUS_FAILURE);
  560         }
  561         if (le32toh(msg->rm_medium) != RNDIS_MEDIUM_802_3) {
  562                 DPRINTF("medium not 802.3 (current medium: 0x%x)\n",
  563                     le32toh(msg->rm_medium));
  564                 return (RNDIS_STATUS_FAILURE);
  565         }
  566         sc->sc_lim_pktsz = le32toh(msg->rm_pktmaxsz);
  567 
  568         return (le32toh(msg->rm_status));
  569 }
  570 
  571 static uint32_t
  572 urndis_ctrl_handle_query(struct urndis_softc *sc,
  573     const struct rndis_comp_hdr *hdr, const void **buf, uint16_t *bufsz)
  574 {
  575         const struct rndis_query_comp *msg;
  576         uint64_t limit;
  577 
  578         msg = (const struct rndis_query_comp *)hdr;
  579 
  580         DPRINTF("len %u rid %u status 0x%x "
  581             "buflen %u bufoff %u\n",
  582             le32toh(msg->rm_len),
  583             le32toh(msg->rm_rid),
  584             le32toh(msg->rm_status),
  585             le32toh(msg->rm_infobuflen),
  586             le32toh(msg->rm_infobufoffset));
  587 
  588         *buf = NULL;
  589         *bufsz = 0;
  590         if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
  591                 DPRINTF("query failed 0x%x\n", le32toh(msg->rm_status));
  592                 return (le32toh(msg->rm_status));
  593         }
  594         limit = le32toh(msg->rm_infobuflen);
  595         limit += le32toh(msg->rm_infobufoffset);
  596         limit += RNDIS_HEADER_OFFSET;
  597 
  598         if (limit > (uint64_t)le32toh(msg->rm_len)) {
  599                 DPRINTF("ctrl message error: invalid query info "
  600                     "len/offset/end_position(%u/%u/%u) -> "
  601                     "go out of buffer limit %u\n",
  602                     le32toh(msg->rm_infobuflen),
  603                     le32toh(msg->rm_infobufoffset),
  604                     le32toh(msg->rm_infobuflen) +
  605                     le32toh(msg->rm_infobufoffset) + RNDIS_HEADER_OFFSET,
  606                     le32toh(msg->rm_len));
  607                 return (RNDIS_STATUS_FAILURE);
  608         }
  609         *buf = ((const uint8_t *)msg) + RNDIS_HEADER_OFFSET +
  610             le32toh(msg->rm_infobufoffset);
  611         *bufsz = le32toh(msg->rm_infobuflen);
  612 
  613         return (le32toh(msg->rm_status));
  614 }
  615 
  616 static uint32_t
  617 urndis_ctrl_handle_reset(struct urndis_softc *sc,
  618     const struct rndis_comp_hdr *hdr)
  619 {
  620         const struct rndis_reset_comp *msg;
  621         uint32_t rval;
  622 
  623         msg = (const struct rndis_reset_comp *)hdr;
  624 
  625         rval = le32toh(msg->rm_status);
  626 
  627         DPRINTF("len %u status 0x%x "
  628             "adrreset %u\n",
  629             le32toh(msg->rm_len),
  630             rval,
  631             le32toh(msg->rm_adrreset));
  632 
  633         if (rval != RNDIS_STATUS_SUCCESS) {
  634                 DPRINTF("reset failed 0x%x\n", rval);
  635                 return (rval);
  636         }
  637         if (msg->rm_adrreset != 0) {
  638                 struct {
  639                         struct rndis_set_req hdr;
  640                         uint32_t filter;
  641                 } msg_filter;
  642 
  643                 msg_filter.filter = htole32(sc->sc_filter);
  644 
  645                 rval = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
  646                     &msg_filter.hdr, sizeof(msg_filter));
  647 
  648                 if (rval != RNDIS_STATUS_SUCCESS) {
  649                         DPRINTF("unable to reset data filters\n");
  650                         return (rval);
  651                 }
  652         }
  653         return (rval);
  654 }
  655 
  656 static uint32_t
  657 urndis_ctrl_init(struct urndis_softc *sc)
  658 {
  659         struct rndis_init_req msg;
  660         struct rndis_comp_hdr *hdr;
  661         uint32_t rval;
  662 
  663         msg.rm_type = htole32(REMOTE_NDIS_INITIALIZE_MSG);
  664         msg.rm_len = htole32(sizeof(msg));
  665         msg.rm_rid = 0;
  666         msg.rm_ver_major = htole32(RNDIS_VERSION_MAJOR);
  667         msg.rm_ver_minor = htole32(1);
  668         msg.rm_max_xfersz = htole32(RNDIS_RX_MAXLEN);
  669 
  670         DPRINTF("type %u len %u rid %u ver_major %u "
  671             "ver_minor %u max_xfersz %u\n",
  672             le32toh(msg.rm_type),
  673             le32toh(msg.rm_len),
  674             le32toh(msg.rm_rid),
  675             le32toh(msg.rm_ver_major),
  676             le32toh(msg.rm_ver_minor),
  677             le32toh(msg.rm_max_xfersz));
  678 
  679         rval = urndis_ctrl_send(sc, &msg, sizeof(msg));
  680 
  681         if (rval != RNDIS_STATUS_SUCCESS) {
  682                 DPRINTF("init failed\n");
  683                 return (rval);
  684         }
  685         if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
  686                 DPRINTF("unable to get init response\n");
  687                 return (RNDIS_STATUS_FAILURE);
  688         }
  689         rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
  690 
  691         return (rval);
  692 }
  693 
  694 static uint32_t
  695 urndis_ctrl_halt(struct urndis_softc *sc)
  696 {
  697         struct rndis_halt_req msg;
  698         uint32_t rval;
  699 
  700         msg.rm_type = htole32(REMOTE_NDIS_HALT_MSG);
  701         msg.rm_len = htole32(sizeof(msg));
  702         msg.rm_rid = 0;
  703 
  704         DPRINTF("type %u len %u rid %u\n",
  705             le32toh(msg.rm_type),
  706             le32toh(msg.rm_len),
  707             le32toh(msg.rm_rid));
  708 
  709         rval = urndis_ctrl_send(sc, &msg, sizeof(msg));
  710 
  711         if (rval != RNDIS_STATUS_SUCCESS)
  712                 DPRINTF("halt failed\n");
  713 
  714         return (rval);
  715 }
  716 
  717 /*
  718  * NB: Querying a device has the requirement of using an input buffer the size
  719  *     of the expected reply or larger, except for variably sized replies.
  720  */
  721 static uint32_t
  722 urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid,
  723     struct rndis_query_req *msg, uint16_t len, const void **rbuf,
  724     uint16_t *rbufsz)
  725 {
  726         struct rndis_comp_hdr *hdr;
  727         uint32_t datalen, rval;
  728 
  729         msg->rm_type = htole32(REMOTE_NDIS_QUERY_MSG);
  730         msg->rm_len = htole32(len);
  731         msg->rm_rid = 0;                /* XXX */
  732         msg->rm_oid = htole32(oid);
  733         datalen = len - sizeof(*msg);
  734         msg->rm_infobuflen = htole32(datalen);
  735         if (datalen != 0) {
  736                 msg->rm_infobufoffset = htole32(sizeof(*msg) -
  737                     RNDIS_HEADER_OFFSET);
  738         } else {
  739                 msg->rm_infobufoffset = 0;
  740         }
  741         msg->rm_devicevchdl = 0;
  742 
  743         DPRINTF("type %u len %u rid %u oid 0x%x "
  744             "infobuflen %u infobufoffset %u devicevchdl %u\n",
  745             le32toh(msg->rm_type),
  746             le32toh(msg->rm_len),
  747             le32toh(msg->rm_rid),
  748             le32toh(msg->rm_oid),
  749             le32toh(msg->rm_infobuflen),
  750             le32toh(msg->rm_infobufoffset),
  751             le32toh(msg->rm_devicevchdl));
  752 
  753         rval = urndis_ctrl_send(sc, msg, len);
  754 
  755         if (rval != RNDIS_STATUS_SUCCESS) {
  756                 DPRINTF("query failed\n");
  757                 return (rval);
  758         }
  759         if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
  760                 DPRINTF("unable to get query response\n");
  761                 return (RNDIS_STATUS_FAILURE);
  762         }
  763         rval = urndis_ctrl_handle(sc, hdr, rbuf, rbufsz);
  764 
  765         return (rval);
  766 }
  767 
  768 static uint32_t
  769 urndis_ctrl_set(struct urndis_softc *sc, uint32_t oid,
  770     struct rndis_set_req *msg, uint16_t len)
  771 {
  772         struct rndis_comp_hdr *hdr;
  773         uint32_t datalen, rval;
  774 
  775         msg->rm_type = htole32(REMOTE_NDIS_SET_MSG);
  776         msg->rm_len = htole32(len);
  777         msg->rm_rid = 0;                /* XXX */
  778         msg->rm_oid = htole32(oid);
  779         datalen = len - sizeof(*msg);
  780         msg->rm_infobuflen = htole32(datalen);
  781         if (datalen != 0) {
  782                 msg->rm_infobufoffset = htole32(sizeof(*msg) -
  783                     RNDIS_HEADER_OFFSET);
  784         } else {
  785                 msg->rm_infobufoffset = 0;
  786         }
  787         msg->rm_devicevchdl = 0;
  788 
  789         DPRINTF("type %u len %u rid %u oid 0x%x "
  790             "infobuflen %u infobufoffset %u devicevchdl %u\n",
  791             le32toh(msg->rm_type),
  792             le32toh(msg->rm_len),
  793             le32toh(msg->rm_rid),
  794             le32toh(msg->rm_oid),
  795             le32toh(msg->rm_infobuflen),
  796             le32toh(msg->rm_infobufoffset),
  797             le32toh(msg->rm_devicevchdl));
  798 
  799         rval = urndis_ctrl_send(sc, msg, len);
  800 
  801         if (rval != RNDIS_STATUS_SUCCESS) {
  802                 DPRINTF("set failed\n");
  803                 return (rval);
  804         }
  805         if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
  806                 DPRINTF("unable to get set response\n");
  807                 return (RNDIS_STATUS_FAILURE);
  808         }
  809         rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
  810         if (rval != RNDIS_STATUS_SUCCESS)
  811                 DPRINTF("set failed 0x%x\n", rval);
  812 
  813         return (rval);
  814 }
  815 
  816 static void
  817 urndis_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
  818 {
  819         struct urndis_softc *sc = usbd_xfer_softc(xfer);
  820         struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, 0);
  821         struct ifnet *ifp = uether_getifp(&sc->sc_ue);
  822         struct rndis_packet_msg msg;
  823         struct mbuf *m;
  824         int actlen;
  825         int aframes;
  826         int offset;
  827 
  828         switch (USB_GET_STATE(xfer)) {
  829         case USB_ST_TRANSFERRED:
  830                 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
  831 
  832                 DPRINTFN(1, "received %u bytes in %u frames\n", actlen, aframes);
  833 
  834                 for (offset = 0; actlen >= (uint32_t)sizeof(msg);) {
  835                         /* copy out header */
  836                         usbd_copy_out(pc, offset, &msg, sizeof(msg));
  837 
  838                         if (le32toh(0x1234567U) != 0x1234567U) {
  839                                 /* swap endianness */
  840                                 msg.rm_type = le32toh(msg.rm_type);
  841                                 msg.rm_len = le32toh(msg.rm_len);
  842                                 msg.rm_dataoffset = le32toh(msg.rm_dataoffset);
  843                                 msg.rm_datalen = le32toh(msg.rm_datalen);
  844                                 msg.rm_oobdataoffset = le32toh(msg.rm_oobdataoffset);
  845                                 msg.rm_oobdatalen = le32toh(msg.rm_oobdatalen);
  846                                 msg.rm_oobdataelements = le32toh(msg.rm_oobdataelements);
  847                                 msg.rm_pktinfooffset = le32toh(msg.rm_pktinfooffset);
  848                                 msg.rm_pktinfolen = le32toh(msg.rm_pktinfolen);
  849                                 msg.rm_vchandle = le32toh(msg.rm_vchandle);
  850                                 msg.rm_reserved = le32toh(msg.rm_reserved);
  851                         }
  852 
  853                         DPRINTF("len %u data(off:%u len:%u) "
  854                             "oobdata(off:%u len:%u nb:%u) perpacket(off:%u len:%u)\n",
  855                             msg.rm_len, msg.rm_dataoffset, msg.rm_datalen,
  856                             msg.rm_oobdataoffset, msg.rm_oobdatalen,
  857                             msg.rm_oobdataelements, msg.rm_pktinfooffset,
  858                             msg.rm_pktinfooffset);
  859 
  860                         /* sanity check the RNDIS header */
  861                         if (msg.rm_type != REMOTE_NDIS_PACKET_MSG) {
  862                                 DPRINTF("invalid type 0x%x != 0x%x\n",
  863                                     msg.rm_type, REMOTE_NDIS_PACKET_MSG);
  864                                 goto tr_setup;
  865                         } else if (msg.rm_len < (uint32_t)sizeof(msg)) {
  866                                 DPRINTF("invalid msg len %u < %u\n",
  867                                     msg.rm_len, (unsigned)sizeof(msg));
  868                                 goto tr_setup;
  869                         } else if (msg.rm_len > (uint32_t)actlen) {
  870                                 DPRINTF("invalid msg len %u > buffer "
  871                                     "len %u\n", msg.rm_len, actlen);
  872                                 goto tr_setup;
  873                         } else if (msg.rm_dataoffset >= (uint32_t)actlen) {
  874                                 DPRINTF("invalid msg dataoffset %u > buffer "
  875                                     "dataoffset %u\n", msg.rm_dataoffset, actlen);
  876                                 goto tr_setup;
  877                         } else if (msg.rm_datalen > (uint32_t)actlen) {
  878                                 DPRINTF("invalid msg datalen %u > buffer "
  879                                     "datalen %u\n", msg.rm_datalen, actlen);
  880                                 goto tr_setup;
  881                         } else if ((msg.rm_dataoffset + msg.rm_datalen +
  882                             (uint32_t)__offsetof(struct rndis_packet_msg,
  883                             rm_dataoffset)) > (uint32_t)actlen) {
  884                                 DPRINTF("invalid dataoffset %u larger than %u\n",
  885                                     msg.rm_dataoffset + msg.rm_datalen +
  886                                     (uint32_t)__offsetof(struct rndis_packet_msg,
  887                                     rm_dataoffset), actlen);
  888                                 goto tr_setup;
  889                         } else if (msg.rm_datalen < (uint32_t)sizeof(struct ether_header)) {
  890                                 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
  891                                 DPRINTF("invalid ethernet size "
  892                                     "%u < %u\n", msg.rm_datalen, (unsigned)sizeof(struct ether_header));
  893                                 goto tr_setup;
  894                         } else if (msg.rm_datalen > (uint32_t)(MCLBYTES - ETHER_ALIGN)) {
  895                                 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
  896                                 DPRINTF("invalid ethernet size "
  897                                     "%u > %u\n",
  898                                     msg.rm_datalen, (unsigned)MCLBYTES);
  899                                 goto tr_setup;
  900                         } else if (msg.rm_datalen > (uint32_t)(MHLEN - ETHER_ALIGN)) {
  901                                 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
  902                         } else {
  903                                 m = m_gethdr(M_NOWAIT, MT_DATA);
  904                         }
  905 
  906                         /* check if we have a buffer */
  907                         if (m != NULL) {
  908                                 m->m_len = m->m_pkthdr.len = msg.rm_datalen + ETHER_ALIGN;
  909                                 m_adj(m, ETHER_ALIGN);
  910 
  911                                 usbd_copy_out(pc, offset + msg.rm_dataoffset +
  912                                     __offsetof(struct rndis_packet_msg,
  913                                     rm_dataoffset), m->m_data, msg.rm_datalen);
  914 
  915                                 /* enqueue */
  916                                 uether_rxmbuf(&sc->sc_ue, m, msg.rm_datalen);
  917                         } else {
  918                                 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
  919                         }
  920                         offset += msg.rm_len;
  921                         actlen -= msg.rm_len;
  922                 }
  923 
  924         case USB_ST_SETUP:
  925 tr_setup:
  926                 usbd_xfer_set_frame_len(xfer, 0, RNDIS_RX_MAXLEN);
  927                 usbd_xfer_set_frames(xfer, 1);
  928                 usbd_transfer_submit(xfer);
  929                 uether_rxflush(&sc->sc_ue);     /* must be last */
  930                 break;
  931 
  932         default:                        /* Error */
  933                 DPRINTFN(1, "error = %s\n", usbd_errstr(error));
  934 
  935                 if (error != USB_ERR_CANCELLED) {
  936                         /* try to clear stall first */
  937                         usbd_xfer_set_stall(xfer);
  938                         usbd_xfer_set_frames(xfer, 0);
  939                         usbd_transfer_submit(xfer);
  940                 }
  941                 break;
  942         }
  943 }
  944 
  945 static void
  946 urndis_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
  947 {
  948         struct rndis_packet_msg msg;
  949         struct urndis_softc *sc = usbd_xfer_softc(xfer);
  950         struct ifnet *ifp = uether_getifp(&sc->sc_ue);
  951         struct mbuf *m;
  952         unsigned x;
  953         int actlen;
  954         int aframes;
  955 
  956         usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
  957 
  958         DPRINTFN(1, "\n");
  959 
  960         switch (USB_GET_STATE(xfer)) {
  961         case USB_ST_TRANSFERRED:
  962                 DPRINTFN(11, "%u bytes in %u frames\n", actlen, aframes);
  963 
  964                 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
  965 
  966                 /* FALLTHROUGH */
  967         case USB_ST_SETUP:
  968 tr_setup:
  969                 memset(&msg, 0, sizeof(msg));
  970 
  971                 for (x = 0; x != RNDIS_TX_FRAMES_MAX; x++) {
  972                         struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, x);
  973 
  974                         usbd_xfer_set_frame_offset(xfer, x * RNDIS_TX_MAXLEN, x);
  975 
  976 next_pkt:
  977                         IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
  978 
  979                         if (m == NULL)
  980                                 break;
  981 
  982                         if ((m->m_pkthdr.len + sizeof(msg)) > RNDIS_TX_MAXLEN) {
  983                                 DPRINTF("Too big packet\n");
  984                                 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
  985 
  986                                 /* Free buffer */
  987                                 m_freem(m);
  988                                 goto next_pkt;
  989                         }
  990                         msg.rm_type = htole32(REMOTE_NDIS_PACKET_MSG);
  991                         msg.rm_len = htole32(sizeof(msg) + m->m_pkthdr.len);
  992 
  993                         msg.rm_dataoffset = htole32(RNDIS_DATA_OFFSET);
  994                         msg.rm_datalen = htole32(m->m_pkthdr.len);
  995 
  996                         /* copy in all data */
  997                         usbd_copy_in(pc, 0, &msg, sizeof(msg));
  998                         usbd_m_copy_in(pc, sizeof(msg), m, 0, m->m_pkthdr.len);
  999                         usbd_xfer_set_frame_len(xfer, x, sizeof(msg) + m->m_pkthdr.len);
 1000 
 1001                         /*
 1002                          * If there's a BPF listener, bounce a copy of
 1003                          * this frame to him:
 1004                          */
 1005                         BPF_MTAP(ifp, m);
 1006 
 1007                         /* Free buffer */
 1008                         m_freem(m);
 1009                 }
 1010                 if (x != 0) {
 1011                         usbd_xfer_set_frames(xfer, x);
 1012                         usbd_transfer_submit(xfer);
 1013                 }
 1014                 break;
 1015 
 1016         default:                        /* Error */
 1017                 DPRINTFN(11, "transfer error, %s\n", usbd_errstr(error));
 1018 
 1019                 /* count output errors */
 1020                 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 1021 
 1022                 if (error != USB_ERR_CANCELLED) {
 1023                         /* try to clear stall first */
 1024                         usbd_xfer_set_stall(xfer);
 1025                         goto tr_setup;
 1026                 }
 1027                 break;
 1028         }
 1029 }
 1030 
 1031 static void
 1032 urndis_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
 1033 {
 1034         int actlen;
 1035 
 1036         usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
 1037 
 1038         switch (USB_GET_STATE(xfer)) {
 1039         case USB_ST_TRANSFERRED:
 1040 
 1041                 DPRINTF("Received %d bytes\n", actlen);
 1042 
 1043                 /* TODO: decode some indications */
 1044 
 1045                 /* FALLTHROUGH */
 1046         case USB_ST_SETUP:
 1047 tr_setup:
 1048                 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
 1049                 usbd_transfer_submit(xfer);
 1050                 break;
 1051 
 1052         default:                        /* Error */
 1053                 if (error != USB_ERR_CANCELLED) {
 1054                         /* start clear stall */
 1055                         usbd_xfer_set_stall(xfer);
 1056                         goto tr_setup;
 1057                 }
 1058                 break;
 1059         }
 1060 }

Cache object: f1b4a6063639355019abd8356147b2ab


[ 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.