Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb Add urndis(4) driver for USB networking devices ...



details:   https://anonhg.NetBSD.org/src/rev/21367d730742
branches:  trunk
changeset: 767515:21367d730742
user:      jakllsch <jakllsch%NetBSD.org@localhost>
date:      Wed Jul 20 19:59:49 2011 +0000

description:
Add urndis(4) driver for USB networking devices implementing the
Microsoft RNDIS specification.  From OpenBSD.

diffstat:

 sys/dev/usb/if_urndis.c    |  1544 ++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/usb/if_urndisreg.h |   307 ++++++++
 2 files changed, 1851 insertions(+), 0 deletions(-)

diffs (truncated from 1859 to 300 lines):

diff -r 56ce4fbb6b10 -r 21367d730742 sys/dev/usb/if_urndis.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/usb/if_urndis.c   Wed Jul 20 19:59:49 2011 +0000
@@ -0,0 +1,1544 @@
+/*     $NetBSD: if_urndis.c,v 1.1 2011/07/20 19:59:49 jakllsch Exp $ */
+/*     $OpenBSD: if_urndis.c,v 1.31 2011/07/03 15:47:17 matthew Exp $ */
+
+/*
+ * Copyright (c) 2010 Jonathan Armani <armani%openbsd.org@localhost>
+ * Copyright (c) 2010 Fabien Romano <fabien%openbsd.org@localhost>
+ * Copyright (c) 2010 Michael Knudsen <mk%openbsd.org@localhost>
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: if_urndis.c,v 1.1 2011/07/20 19:59:49 jakllsch Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+#include <sys/rwlock.h>
+#include <sys/mbuf.h>
+#include <sys/kmem.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/socket.h>
+#include <sys/device.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_ether.h>
+
+#include <net/bpf.h>
+
+#include <sys/bus.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usbdevs.h>
+#include <dev/usb/usbcdc.h>
+
+#include <dev/usb/if_urndisreg.h>
+
+#ifdef URNDIS_DEBUG
+#define DPRINTF(x)      do { printf x; } while (0)
+#else
+#define DPRINTF(x)
+#endif
+
+#define DEVNAME(sc)    (device_xname(sc->sc_dev))
+
+#define ETHER_ALIGN 2
+#define URNDIS_RESPONSE_LEN 0x400
+
+
+static int urndis_newbuf(struct urndis_softc *, struct urndis_chain *);
+
+static int urndis_ioctl(struct ifnet *, unsigned long, void *);
+#if 0
+static void urndis_watchdog(struct ifnet *);
+#endif
+
+static void urndis_start(struct ifnet *);
+static void urndis_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
+static void urndis_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
+static int urndis_rx_list_init(struct urndis_softc *);
+static int urndis_tx_list_init(struct urndis_softc *);
+
+static void urndis_init(struct ifnet *);
+static void urndis_stop(struct ifnet *);
+
+static usbd_status urndis_ctrl_msg(struct urndis_softc *, uint8_t, uint8_t,
+    uint16_t, uint16_t, void *, size_t);
+static usbd_status urndis_ctrl_send(struct urndis_softc *, void *, size_t);
+static struct urndis_comp_hdr *urndis_ctrl_recv(struct urndis_softc *);
+
+static uint32_t urndis_ctrl_handle(struct urndis_softc *,
+    struct urndis_comp_hdr *, void **, size_t *);
+static uint32_t urndis_ctrl_handle_init(struct urndis_softc *,
+    const struct urndis_comp_hdr *);
+static uint32_t urndis_ctrl_handle_query(struct urndis_softc *,
+    const struct urndis_comp_hdr *, void **, size_t *);
+static uint32_t urndis_ctrl_handle_reset(struct urndis_softc *,
+    const struct urndis_comp_hdr *);
+
+static uint32_t urndis_ctrl_init(struct urndis_softc *);
+#if 0
+static uint32_t urndis_ctrl_halt(struct urndis_softc *);
+#endif
+static uint32_t urndis_ctrl_query(struct urndis_softc *, uint32_t, void *,
+    size_t, void **, size_t *);
+static uint32_t urndis_ctrl_set(struct urndis_softc *, uint32_t, void *, size_t);
+#if 0
+static uint32_t urndis_ctrl_set_param(struct urndis_softc *, const char *,
+    uint32_t, void *, size_t);
+static uint32_t urndis_ctrl_reset(struct urndis_softc *);
+static uint32_t urndis_ctrl_keepalive(struct urndis_softc *);
+#endif
+
+static int urndis_encap(struct urndis_softc *, struct mbuf *, int);
+static void urndis_decap(struct urndis_softc *, struct urndis_chain *, uint32_t);
+
+static int urndis_match(device_t, cfdata_t, void *);
+static void urndis_attach(device_t, device_t, void *);
+static int urndis_detach(device_t, int);
+static int urndis_activate(device_t, enum devact);
+
+CFATTACH_DECL_NEW(urndis, sizeof(struct urndis_softc),
+    urndis_match, urndis_attach, urndis_detach, urndis_activate);
+
+/*
+ * Supported devices that we can't match by class IDs.
+ */
+static const struct usb_devno urndis_devs[] = {
+       { USB_VENDOR_HTC,       USB_PRODUCT_HTC_ANDROID },
+       { USB_VENDOR_SAMSUNG,   USB_PRODUCT_SAMSUNG_ANDROID2 },
+       { 0, 0 }
+};
+
+static usbd_status
+urndis_ctrl_msg(struct urndis_softc *sc, uint8_t rt, uint8_t r,
+    uint16_t index, uint16_t value, void *buf, size_t buflen)
+{
+       usb_device_request_t req;
+
+       req.bmRequestType = rt;
+       req.bRequest = r;
+       USETW(req.wValue, value);
+       USETW(req.wIndex, index);
+       USETW(req.wLength, buflen);
+
+       return usbd_do_request(sc->sc_udev, &req, buf);
+}
+
+static usbd_status
+urndis_ctrl_send(struct urndis_softc *sc, void *buf, size_t len)
+{
+       usbd_status err;
+
+       if (sc->sc_dying)
+               return(0);
+
+       err = urndis_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE, UR_GET_STATUS,
+           sc->sc_ifaceno_ctl, 0, buf, len);
+
+       if (err != USBD_NORMAL_COMPLETION)
+               printf("%s: %s\n", DEVNAME(sc), usbd_errstr(err));
+
+       return err;
+}
+
+static struct urndis_comp_hdr *
+urndis_ctrl_recv(struct urndis_softc *sc)
+{
+       struct urndis_comp_hdr  *hdr;
+       char                    *buf;
+       usbd_status              err;
+
+       buf = kmem_alloc(URNDIS_RESPONSE_LEN, KM_SLEEP);
+       if (buf == NULL) {
+               printf("%s: out of memory\n", DEVNAME(sc));
+               return NULL;
+       }
+
+       err = urndis_ctrl_msg(sc, UT_READ_CLASS_INTERFACE, UR_CLEAR_FEATURE,
+           sc->sc_ifaceno_ctl, 0, buf, URNDIS_RESPONSE_LEN);
+
+       if (err != USBD_NORMAL_COMPLETION && err != USBD_SHORT_XFER) {
+               printf("%s: %s\n", DEVNAME(sc), usbd_errstr(err));
+               kmem_free(buf, URNDIS_RESPONSE_LEN);
+               return NULL;
+       }
+
+       hdr = (struct urndis_comp_hdr *)buf;
+       DPRINTF(("%s: urndis_ctrl_recv: type 0x%x len %u\n",
+           DEVNAME(sc),
+           le32toh(hdr->rm_type),
+           le32toh(hdr->rm_len)));
+
+       if (le32toh(hdr->rm_len) > URNDIS_RESPONSE_LEN) {
+               printf("%s: ctrl message error: wrong size %u > %u\n",
+                   DEVNAME(sc),
+                   le32toh(hdr->rm_len),
+                   URNDIS_RESPONSE_LEN);
+               kmem_free(buf, URNDIS_RESPONSE_LEN);
+               return NULL;
+       }
+
+       return hdr;
+}
+
+static uint32_t
+urndis_ctrl_handle(struct urndis_softc *sc, struct urndis_comp_hdr *hdr,
+    void **buf, size_t *bufsz)
+{
+       uint32_t rval;
+
+       DPRINTF(("%s: urndis_ctrl_handle\n", DEVNAME(sc)));
+
+       if (buf && bufsz) {
+               *buf = NULL;
+               *bufsz = 0;
+       }
+
+       switch (le32toh(hdr->rm_type)) {
+               case REMOTE_NDIS_INITIALIZE_CMPLT:
+                       rval = urndis_ctrl_handle_init(sc, hdr);
+                       break;
+
+               case REMOTE_NDIS_QUERY_CMPLT:
+                       rval = urndis_ctrl_handle_query(sc, hdr, buf, bufsz);
+                       break;
+
+               case REMOTE_NDIS_RESET_CMPLT:
+                       rval = urndis_ctrl_handle_reset(sc, hdr);
+                       break;
+
+               case REMOTE_NDIS_KEEPALIVE_CMPLT:
+               case REMOTE_NDIS_SET_CMPLT:
+                       rval = le32toh(hdr->rm_status);
+                       break;
+
+               default:
+                       printf("%s: ctrl message error: unknown event 0x%x\n",
+                           DEVNAME(sc), le32toh(hdr->rm_type));
+                       rval = RNDIS_STATUS_FAILURE;
+       }
+
+       kmem_free(hdr, URNDIS_RESPONSE_LEN);
+
+       return rval;
+}
+
+static uint32_t
+urndis_ctrl_handle_init(struct urndis_softc *sc,
+    const struct urndis_comp_hdr *hdr)
+{
+       const struct urndis_init_comp   *msg;
+
+       msg = (const struct urndis_init_comp *) hdr;
+
+       DPRINTF(("%s: urndis_ctrl_handle_init: len %u rid %u status 0x%x "
+           "ver_major %u ver_minor %u devflags 0x%x medium 0x%x pktmaxcnt %u "
+           "pktmaxsz %u align %u aflistoffset %u aflistsz %u\n",
+           DEVNAME(sc),
+           le32toh(msg->rm_len),
+           le32toh(msg->rm_rid),
+           le32toh(msg->rm_status),
+           le32toh(msg->rm_ver_major),
+           le32toh(msg->rm_ver_minor),
+           le32toh(msg->rm_devflags),
+           le32toh(msg->rm_medium),
+           le32toh(msg->rm_pktmaxcnt),
+           le32toh(msg->rm_pktmaxsz),
+           le32toh(msg->rm_align),
+           le32toh(msg->rm_aflistoffset),
+           le32toh(msg->rm_aflistsz)));
+
+       if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
+               printf("%s: init failed 0x%x\n",
+                   DEVNAME(sc),
+                   le32toh(msg->rm_status));
+
+               return le32toh(msg->rm_status);
+       }
+
+       if (le32toh(msg->rm_devflags) != RNDIS_DF_CONNECTIONLESS) {
+               printf("%s: wrong device type (current type: 0x%x)\n",
+                   DEVNAME(sc),
+                   le32toh(msg->rm_devflags));
+
+               return RNDIS_STATUS_FAILURE;
+       }
+
+       if (le32toh(msg->rm_medium) != RNDIS_MEDIUM_802_3) {
+               printf("%s: medium not 802.3 (current medium: 0x%x)\n",
+                   DEVNAME(sc), le32toh(msg->rm_medium));
+
+               return RNDIS_STATUS_FAILURE;
+       }
+
+       sc->sc_lim_pktsz = le32toh(msg->rm_pktmaxsz);
+
+       return le32toh(msg->rm_status);
+}
+



Home | Main Index | Thread Index | Old Index