// SPDX-License-Identifier: GPL-2.0+ /* * u_ether.c -- Ethernet-over-USB link layer utilities for Gadget stack * * 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/module.h> #include <linux/gfp.h> #include <linux/device.h> #include <linux/ctype.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/if_vlan.h> #include <linux/string_helpers.h> #include <linux/usb/composite.h> #include "u_ether.h" /* * This component encapsulates the Ethernet link glue needed to provide * one (!) network link through the USB gadget stack, normally "usb0". * * The control and data models are handled by the function driver which * connects to this code; such as CDC Ethernet (ECM or EEM), * "CDC Subset", or RNDIS. That includes all descriptor and endpoint * management. * * Link level addressing is handled by this component using module * parameters; if no such parameters are provided, random link level * addresses are used. Each end of the link uses one address. The * host end address is exported in various ways, and is often recorded * in configuration databases. * * The driver which assembles each configuration using such a link is * responsible for ensuring that each configuration includes at most one * instance of is network link. (The network layer provides ways for * this single "physical" link to be used by multiple virtual links.) */ #define UETH__VERSION … /* Experiments show that both Linux and Windows hosts allow up to 16k * frame sizes. Set the max MTU size to 15k+52 to prevent allocating 32k * blocks and still have efficient handling. */ #define GETHER_MAX_MTU_SIZE … #define GETHER_MAX_ETH_FRAME_LEN … struct eth_dev { … }; /*-------------------------------------------------------------------------*/ #define RX_EXTRA … #define DEFAULT_QLEN … /* use deeper queues at high/super speed */ static inline int qlen(struct usb_gadget *gadget, unsigned qmult) { … } /*-------------------------------------------------------------------------*/ /* NETWORK DRIVER HOOKUP (to the layer above this driver) */ static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p) { … } /* REVISIT can also support: * - WOL (by tracking suspends and issuing remote wakeup) * - msglevel (implies updated messaging) * - ... probably more ethtool ops */ static const struct ethtool_ops ops = …; static void defer_kevent(struct eth_dev *dev, int flag) { … } static void rx_complete(struct usb_ep *ep, struct usb_request *req); static int rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) { … } static void rx_complete(struct usb_ep *ep, struct usb_request *req) { … } static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n) { … } static int alloc_requests(struct eth_dev *dev, struct gether *link, unsigned n) { … } static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags) { … } static void eth_work(struct work_struct *work) { … } static void tx_complete(struct usb_ep *ep, struct usb_request *req) { … } static inline int is_promisc(u16 cdc_filter) { … } static int ether_wakeup_host(struct gether *port) { … } static netdev_tx_t eth_start_xmit(struct sk_buff *skb, struct net_device *net) { … } /*-------------------------------------------------------------------------*/ static void eth_start(struct eth_dev *dev, gfp_t gfp_flags) { … } static int eth_open(struct net_device *net) { … } static int eth_stop(struct net_device *net) { … } /*-------------------------------------------------------------------------*/ static int get_ether_addr(const char *str, u8 *dev_addr) { … } static int get_ether_addr_str(u8 dev_addr[ETH_ALEN], char *str, int len) { … } static const struct net_device_ops eth_netdev_ops = …; static const struct device_type gadget_type = …; /* * gether_setup_name - initialize one ethernet-over-usb link * @g: gadget to associated with these links * @ethaddr: NULL, or a buffer in which the ethernet address of the * host side of the link is recorded * @netname: name for network device (for example, "usb") * Context: may sleep * * This sets up the single network link that may be exported by a * gadget driver using this framework. The link layer addresses are * set up using module parameters. * * Returns an eth_dev pointer on success, or an ERR_PTR on failure. */ struct eth_dev *gether_setup_name(struct usb_gadget *g, const char *dev_addr, const char *host_addr, u8 ethaddr[ETH_ALEN], unsigned qmult, const char *netname) { … } EXPORT_SYMBOL_GPL(…); struct net_device *gether_setup_name_default(const char *netname) { … } EXPORT_SYMBOL_GPL(…); int gether_register_netdev(struct net_device *net) { … } EXPORT_SYMBOL_GPL(…); void gether_set_gadget(struct net_device *net, struct usb_gadget *g) { … } EXPORT_SYMBOL_GPL(…); int gether_set_dev_addr(struct net_device *net, const char *dev_addr) { … } EXPORT_SYMBOL_GPL(…); int gether_get_dev_addr(struct net_device *net, char *dev_addr, int len) { … } EXPORT_SYMBOL_GPL(…); int gether_set_host_addr(struct net_device *net, const char *host_addr) { … } EXPORT_SYMBOL_GPL(…); int gether_get_host_addr(struct net_device *net, char *host_addr, int len) { … } EXPORT_SYMBOL_GPL(…); int gether_get_host_addr_cdc(struct net_device *net, char *host_addr, int len) { … } EXPORT_SYMBOL_GPL(…); void gether_get_host_addr_u8(struct net_device *net, u8 host_mac[ETH_ALEN]) { … } EXPORT_SYMBOL_GPL(…); void gether_set_qmult(struct net_device *net, unsigned qmult) { … } EXPORT_SYMBOL_GPL(…); unsigned gether_get_qmult(struct net_device *net) { … } EXPORT_SYMBOL_GPL(…); int gether_get_ifname(struct net_device *net, char *name, int len) { … } EXPORT_SYMBOL_GPL(…); int gether_set_ifname(struct net_device *net, const char *name, int len) { … } EXPORT_SYMBOL_GPL(…); void gether_suspend(struct gether *link) { … } EXPORT_SYMBOL_GPL(…); void gether_resume(struct gether *link) { … } EXPORT_SYMBOL_GPL(…); /* * gether_cleanup - remove Ethernet-over-USB device * Context: may sleep * * This is called to free all resources allocated by @gether_setup(). */ void gether_cleanup(struct eth_dev *dev) { … } EXPORT_SYMBOL_GPL(…); /** * gether_connect - notify network layer that USB link is active * @link: the USB link, set up with endpoints, descriptors matching * current device speed, and any framing wrapper(s) set up. * Context: irqs blocked * * This is called to activate endpoints and let the network layer know * the connection is active ("carrier detect"). It may cause the I/O * queues to open and start letting network packets flow, but will in * any case activate the endpoints so that they respond properly to the * USB host. * * Verify net_device pointer returned using IS_ERR(). If it doesn't * indicate some error code (negative errno), ep->driver_data values * have been overwritten. */ struct net_device *gether_connect(struct gether *link) { … } EXPORT_SYMBOL_GPL(…); /** * gether_disconnect - notify network layer that USB link is inactive * @link: the USB link, on which gether_connect() was called * Context: irqs blocked * * This is called to deactivate endpoints and let the network layer know * the connection went inactive ("no carrier"). * * On return, the state is as if gether_connect() had never been called. * The endpoints are inactive, and accordingly without active USB I/O. * Pointers to endpoint descriptors and endpoint private data are nulled. */ void gether_disconnect(struct gether *link) { … } EXPORT_SYMBOL_GPL(…); MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; MODULE_AUTHOR(…) …;