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