linux/drivers/usb/gadget/legacy/ether.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * ether.c -- Ethernet gadget driver, with CDC and non-CDC options
 *
 * Copyright (C) 2003-2005,2008 David Brownell
 * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
 * Copyright (C) 2008 Nokia Corporation
 */

/* #define VERBOSE_DEBUG */

#include <linux/kernel.h>
#include <linux/netdevice.h>

#if defined USB_ETH_RNDIS
#  undef USB_ETH_RNDIS
#endif
#ifdef CONFIG_USB_ETH_RNDIS
#define USB_ETH_RNDIS
#endif

#include "u_ether.h"


/*
 * Ethernet gadget driver -- with CDC and non-CDC options
 * Builds on hardware support for a full duplex link.
 *
 * CDC Ethernet is the standard USB solution for sending Ethernet frames
 * using USB.  Real hardware tends to use the same framing protocol but look
 * different for control features.  This driver strongly prefers to use
 * this USB-IF standard as its open-systems interoperability solution;
 * most host side USB stacks (except from Microsoft) support it.
 *
 * This is sometimes called "CDC ECM" (Ethernet Control Model) to support
 * TLA-soup.  "CDC ACM" (Abstract Control Model) is for modems, and a new
 * "CDC EEM" (Ethernet Emulation Model) is starting to spread.
 *
 * There's some hardware that can't talk CDC ECM.  We make that hardware
 * implement a "minimalist" vendor-agnostic CDC core:  same framing, but
 * link-level setup only requires activating the configuration.  Only the
 * endpoint descriptors, and product/vendor IDs, are relevant; no control
 * operations are available.  Linux supports it, but other host operating
 * systems may not.  (This is a subset of CDC Ethernet.)
 *
 * It turns out that if you add a few descriptors to that "CDC Subset",
 * (Windows) host side drivers from MCCI can treat it as one submode of
 * a proprietary scheme called "SAFE" ... without needing to know about
 * specific product/vendor IDs.  So we do that, making it easier to use
 * those MS-Windows drivers.  Those added descriptors make it resemble a
 * CDC MDLM device, but they don't change device behavior at all.  (See
 * MCCI Engineering report 950198 "SAFE Networking Functions".)
 *
 * A third option is also in use.  Rather than CDC Ethernet, or something
 * simpler, Microsoft pushes their own approach: RNDIS.  The published
 * RNDIS specs are ambiguous and appear to be incomplete, and are also
 * needlessly complex.  They borrow more from CDC ACM than CDC ECM.
 */

#define DRIVER_DESC
#define DRIVER_VERSION

#ifdef USB_ETH_RNDIS
#define PREFIX
#else
#define PREFIX
#endif

/*
 * This driver aims for interoperability by using CDC ECM unless
 *
 *		can_support_ecm()
 *
 * returns false, in which case it supports the CDC Subset.  By default,
 * that returns true; most hardware has no problems with CDC ECM, that's
 * a good default.  Previous versions of this driver had no default; this
 * version changes that, removing overhead for new controller support.
 *
 *	IF YOUR HARDWARE CAN'T SUPPORT CDC ECM, UPDATE THAT ROUTINE!
 */

static inline bool has_rndis(void)
{}

#include <linux/module.h>

#include "u_ecm.h"
#include "u_gether.h"
#ifdef	USB_ETH_RNDIS
#include "u_rndis.h"
#include "rndis.h"
#else
#define rndis_borrow_net
#endif
#include "u_eem.h"

/*-------------------------------------------------------------------------*/
USB_GADGET_COMPOSITE_OPTIONS();

USB_ETHERNET_MODULE_PARAMETERS();

/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
 * Instead:  allocate your own, using normal USB-IF procedures.
 */

/* Thanks to NetChip Technologies for donating this product ID.
 * It's for devices with only CDC Ethernet configurations.
 */
#define CDC_VENDOR_NUM
#define CDC_PRODUCT_NUM

/* For hardware that can't talk CDC, we use the same vendor ID that
 * ARM Linux has used for ethernet-over-usb, both with sa1100 and
 * with pxa250.  We're protocol-compatible, if the host-side drivers
 * use the endpoint descriptors.  bcdDevice (version) is nonzero, so
 * drivers that need to hard-wire endpoint numbers have a hook.
 *
 * The protocol is a minimal subset of CDC Ether, which works on any bulk
 * hardware that's not deeply broken ... even on hardware that can't talk
 * RNDIS (like SA-1100, with no interrupt endpoint, or anything that
 * doesn't handle control-OUT).
 */
#define SIMPLE_VENDOR_NUM
#define SIMPLE_PRODUCT_NUM

/* For hardware that can talk RNDIS and either of the above protocols,
 * use this ID ... the windows INF files will know it.  Unless it's
 * used with CDC Ethernet, Linux 2.4 hosts will need updates to choose
 * the non-RNDIS configuration.
 */
#define RNDIS_VENDOR_NUM
#define RNDIS_PRODUCT_NUM

/* For EEM gadgets */
#define EEM_VENDOR_NUM
#define EEM_PRODUCT_NUM

/*-------------------------------------------------------------------------*/

static struct usb_device_descriptor device_desc =;

static const struct usb_descriptor_header *otg_desc[2];

static struct usb_string strings_dev[] =;

static struct usb_gadget_strings stringtab_dev =;

static struct usb_gadget_strings *dev_strings[] =;

static struct usb_function_instance *fi_ecm;
static struct usb_function *f_ecm;

static struct usb_function_instance *fi_eem;
static struct usb_function *f_eem;

static struct usb_function_instance *fi_geth;
static struct usb_function *f_geth;

static struct usb_function_instance *fi_rndis;
static struct usb_function *f_rndis;

/*-------------------------------------------------------------------------*/

/*
 * We may not have an RNDIS configuration, but if we do it needs to be
 * the first one present.  That's to make Microsoft's drivers happy,
 * and to follow DOCSIS 1.0 (cable modem standard).
 */
static int rndis_do_config(struct usb_configuration *c)
{}

static struct usb_configuration rndis_config_driver =;

/*-------------------------------------------------------------------------*/

#ifdef CONFIG_USB_ETH_EEM
static bool use_eem =;
#else
static bool use_eem;
#endif
module_param(use_eem, bool, 0);
MODULE_PARM_DESC();

/*
 * We _always_ have an ECM, CDC Subset, or EEM configuration.
 */
static int eth_do_config(struct usb_configuration *c)
{}

static struct usb_configuration eth_config_driver =;

/*-------------------------------------------------------------------------*/

static int eth_bind(struct usb_composite_dev *cdev)
{}

static int eth_unbind(struct usb_composite_dev *cdev)
{}

static struct usb_composite_driver eth_driver =;

module_usb_composite_driver();

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();