162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0+ */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * u_ether.h -- interface to USB gadget "ethernet link" utilities 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2003-2005,2008 David Brownell 662306a36Sopenharmony_ci * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger 762306a36Sopenharmony_ci * Copyright (C) 2008 Nokia Corporation 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#ifndef __U_ETHER_H 1162306a36Sopenharmony_ci#define __U_ETHER_H 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/err.h> 1462306a36Sopenharmony_ci#include <linux/if_ether.h> 1562306a36Sopenharmony_ci#include <linux/usb/composite.h> 1662306a36Sopenharmony_ci#include <linux/usb/cdc.h> 1762306a36Sopenharmony_ci#include <linux/netdevice.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define QMULT_DEFAULT 5 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* 2262306a36Sopenharmony_ci * dev_addr: initial value 2362306a36Sopenharmony_ci * changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" 2462306a36Sopenharmony_ci * host_addr: this address is invisible to ifconfig 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_ci#define USB_ETHERNET_MODULE_PARAMETERS() \ 2762306a36Sopenharmony_ci static unsigned qmult = QMULT_DEFAULT; \ 2862306a36Sopenharmony_ci module_param(qmult, uint, S_IRUGO|S_IWUSR); \ 2962306a36Sopenharmony_ci MODULE_PARM_DESC(qmult, "queue length multiplier at high/super speed");\ 3062306a36Sopenharmony_ci \ 3162306a36Sopenharmony_ci static char *dev_addr; \ 3262306a36Sopenharmony_ci module_param(dev_addr, charp, S_IRUGO); \ 3362306a36Sopenharmony_ci MODULE_PARM_DESC(dev_addr, "Device Ethernet Address"); \ 3462306a36Sopenharmony_ci \ 3562306a36Sopenharmony_ci static char *host_addr; \ 3662306a36Sopenharmony_ci module_param(host_addr, charp, S_IRUGO); \ 3762306a36Sopenharmony_ci MODULE_PARM_DESC(host_addr, "Host Ethernet Address") 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistruct eth_dev; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci/* 4262306a36Sopenharmony_ci * This represents the USB side of an "ethernet" link, managed by a USB 4362306a36Sopenharmony_ci * function which provides control and (maybe) framing. Two functions 4462306a36Sopenharmony_ci * in different configurations could share the same ethernet link/netdev, 4562306a36Sopenharmony_ci * using different host interaction models. 4662306a36Sopenharmony_ci * 4762306a36Sopenharmony_ci * There is a current limitation that only one instance of this link may 4862306a36Sopenharmony_ci * be present in any given configuration. When that's a problem, network 4962306a36Sopenharmony_ci * layer facilities can be used to package multiple logical links on this 5062306a36Sopenharmony_ci * single "physical" one. 5162306a36Sopenharmony_ci */ 5262306a36Sopenharmony_cistruct gether { 5362306a36Sopenharmony_ci struct usb_function func; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci /* updated by gether_{connect,disconnect} */ 5662306a36Sopenharmony_ci struct eth_dev *ioport; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci /* endpoints handle full and/or high speeds */ 5962306a36Sopenharmony_ci struct usb_ep *in_ep; 6062306a36Sopenharmony_ci struct usb_ep *out_ep; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci bool is_zlp_ok; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci u16 cdc_filter; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci /* hooks for added framing, as needed for RNDIS and EEM. */ 6762306a36Sopenharmony_ci u32 header_len; 6862306a36Sopenharmony_ci /* NCM requires fixed size bundles */ 6962306a36Sopenharmony_ci bool is_fixed; 7062306a36Sopenharmony_ci u32 fixed_out_len; 7162306a36Sopenharmony_ci u32 fixed_in_len; 7262306a36Sopenharmony_ci bool supports_multi_frame; 7362306a36Sopenharmony_ci struct sk_buff *(*wrap)(struct gether *port, 7462306a36Sopenharmony_ci struct sk_buff *skb); 7562306a36Sopenharmony_ci int (*unwrap)(struct gether *port, 7662306a36Sopenharmony_ci struct sk_buff *skb, 7762306a36Sopenharmony_ci struct sk_buff_head *list); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci /* called on network open/close */ 8062306a36Sopenharmony_ci void (*open)(struct gether *); 8162306a36Sopenharmony_ci void (*close)(struct gether *); 8262306a36Sopenharmony_ci bool is_suspend; 8362306a36Sopenharmony_ci}; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ 8662306a36Sopenharmony_ci |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ 8762306a36Sopenharmony_ci |USB_CDC_PACKET_TYPE_PROMISCUOUS \ 8862306a36Sopenharmony_ci |USB_CDC_PACKET_TYPE_DIRECTED) 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci/* variant of gether_setup that allows customizing network device name */ 9162306a36Sopenharmony_cistruct eth_dev *gether_setup_name(struct usb_gadget *g, 9262306a36Sopenharmony_ci const char *dev_addr, const char *host_addr, 9362306a36Sopenharmony_ci u8 ethaddr[ETH_ALEN], unsigned qmult, const char *netname); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci/* netdev setup/teardown as directed by the gadget driver */ 9662306a36Sopenharmony_ci/* gether_setup - initialize one ethernet-over-usb link 9762306a36Sopenharmony_ci * @g: gadget to associated with these links 9862306a36Sopenharmony_ci * @ethaddr: NULL, or a buffer in which the ethernet address of the 9962306a36Sopenharmony_ci * host side of the link is recorded 10062306a36Sopenharmony_ci * Context: may sleep 10162306a36Sopenharmony_ci * 10262306a36Sopenharmony_ci * This sets up the single network link that may be exported by a 10362306a36Sopenharmony_ci * gadget driver using this framework. The link layer addresses are 10462306a36Sopenharmony_ci * set up using module parameters. 10562306a36Sopenharmony_ci * 10662306a36Sopenharmony_ci * Returns a eth_dev pointer on success, or an ERR_PTR on failure 10762306a36Sopenharmony_ci */ 10862306a36Sopenharmony_cistatic inline struct eth_dev *gether_setup(struct usb_gadget *g, 10962306a36Sopenharmony_ci const char *dev_addr, const char *host_addr, 11062306a36Sopenharmony_ci u8 ethaddr[ETH_ALEN], unsigned qmult) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci return gether_setup_name(g, dev_addr, host_addr, ethaddr, qmult, "usb"); 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci/* 11662306a36Sopenharmony_ci * variant of gether_setup_default that allows customizing 11762306a36Sopenharmony_ci * network device name 11862306a36Sopenharmony_ci */ 11962306a36Sopenharmony_cistruct net_device *gether_setup_name_default(const char *netname); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci/* 12262306a36Sopenharmony_ci * gether_register_netdev - register the net device 12362306a36Sopenharmony_ci * @net: net device to register 12462306a36Sopenharmony_ci * 12562306a36Sopenharmony_ci * Registers the net device associated with this ethernet-over-usb link 12662306a36Sopenharmony_ci * 12762306a36Sopenharmony_ci */ 12862306a36Sopenharmony_ciint gether_register_netdev(struct net_device *net); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci/* gether_setup_default - initialize one ethernet-over-usb link 13162306a36Sopenharmony_ci * Context: may sleep 13262306a36Sopenharmony_ci * 13362306a36Sopenharmony_ci * This sets up the single network link that may be exported by a 13462306a36Sopenharmony_ci * gadget driver using this framework. The link layer addresses 13562306a36Sopenharmony_ci * are set to random values. 13662306a36Sopenharmony_ci * 13762306a36Sopenharmony_ci * Returns negative errno, or zero on success 13862306a36Sopenharmony_ci */ 13962306a36Sopenharmony_cistatic inline struct net_device *gether_setup_default(void) 14062306a36Sopenharmony_ci{ 14162306a36Sopenharmony_ci return gether_setup_name_default("usb"); 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci/** 14562306a36Sopenharmony_ci * gether_set_gadget - initialize one ethernet-over-usb link with a gadget 14662306a36Sopenharmony_ci * @net: device representing this link 14762306a36Sopenharmony_ci * @g: the gadget to initialize with 14862306a36Sopenharmony_ci * 14962306a36Sopenharmony_ci * This associates one ethernet-over-usb link with a gadget. 15062306a36Sopenharmony_ci */ 15162306a36Sopenharmony_civoid gether_set_gadget(struct net_device *net, struct usb_gadget *g); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/** 15462306a36Sopenharmony_ci * gether_set_dev_addr - initialize an ethernet-over-usb link with eth address 15562306a36Sopenharmony_ci * @net: device representing this link 15662306a36Sopenharmony_ci * @dev_addr: eth address of this device 15762306a36Sopenharmony_ci * 15862306a36Sopenharmony_ci * This sets the device-side Ethernet address of this ethernet-over-usb link 15962306a36Sopenharmony_ci * if dev_addr is correct. 16062306a36Sopenharmony_ci * Returns negative errno if the new address is incorrect. 16162306a36Sopenharmony_ci */ 16262306a36Sopenharmony_ciint gether_set_dev_addr(struct net_device *net, const char *dev_addr); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci/** 16562306a36Sopenharmony_ci * gether_get_dev_addr - get an ethernet-over-usb link eth address 16662306a36Sopenharmony_ci * @net: device representing this link 16762306a36Sopenharmony_ci * @dev_addr: place to store device's eth address 16862306a36Sopenharmony_ci * @len: length of the @dev_addr buffer 16962306a36Sopenharmony_ci * 17062306a36Sopenharmony_ci * This gets the device-side Ethernet address of this ethernet-over-usb link. 17162306a36Sopenharmony_ci * Returns zero on success, else negative errno. 17262306a36Sopenharmony_ci */ 17362306a36Sopenharmony_ciint gether_get_dev_addr(struct net_device *net, char *dev_addr, int len); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci/** 17662306a36Sopenharmony_ci * gether_set_host_addr - initialize an ethernet-over-usb link with host address 17762306a36Sopenharmony_ci * @net: device representing this link 17862306a36Sopenharmony_ci * @host_addr: eth address of the host 17962306a36Sopenharmony_ci * 18062306a36Sopenharmony_ci * This sets the host-side Ethernet address of this ethernet-over-usb link 18162306a36Sopenharmony_ci * if host_addr is correct. 18262306a36Sopenharmony_ci * Returns negative errno if the new address is incorrect. 18362306a36Sopenharmony_ci */ 18462306a36Sopenharmony_ciint gether_set_host_addr(struct net_device *net, const char *host_addr); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci/** 18762306a36Sopenharmony_ci * gether_get_host_addr - get an ethernet-over-usb link host address 18862306a36Sopenharmony_ci * @net: device representing this link 18962306a36Sopenharmony_ci * @host_addr: place to store eth address of the host 19062306a36Sopenharmony_ci * @len: length of the @host_addr buffer 19162306a36Sopenharmony_ci * 19262306a36Sopenharmony_ci * This gets the host-side Ethernet address of this ethernet-over-usb link. 19362306a36Sopenharmony_ci * Returns zero on success, else negative errno. 19462306a36Sopenharmony_ci */ 19562306a36Sopenharmony_ciint gether_get_host_addr(struct net_device *net, char *host_addr, int len); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci/** 19862306a36Sopenharmony_ci * gether_get_host_addr_cdc - get an ethernet-over-usb link host address 19962306a36Sopenharmony_ci * @net: device representing this link 20062306a36Sopenharmony_ci * @host_addr: place to store eth address of the host 20162306a36Sopenharmony_ci * @len: length of the @host_addr buffer 20262306a36Sopenharmony_ci * 20362306a36Sopenharmony_ci * This gets the CDC formatted host-side Ethernet address of this 20462306a36Sopenharmony_ci * ethernet-over-usb link. 20562306a36Sopenharmony_ci * Returns zero on success, else negative errno. 20662306a36Sopenharmony_ci */ 20762306a36Sopenharmony_ciint gether_get_host_addr_cdc(struct net_device *net, char *host_addr, int len); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci/** 21062306a36Sopenharmony_ci * gether_get_host_addr_u8 - get an ethernet-over-usb link host address 21162306a36Sopenharmony_ci * @net: device representing this link 21262306a36Sopenharmony_ci * @host_mac: place to store the eth address of the host 21362306a36Sopenharmony_ci * 21462306a36Sopenharmony_ci * This gets the binary formatted host-side Ethernet address of this 21562306a36Sopenharmony_ci * ethernet-over-usb link. 21662306a36Sopenharmony_ci */ 21762306a36Sopenharmony_civoid gether_get_host_addr_u8(struct net_device *net, u8 host_mac[ETH_ALEN]); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci/** 22062306a36Sopenharmony_ci * gether_set_qmult - initialize an ethernet-over-usb link with a multiplier 22162306a36Sopenharmony_ci * @net: device representing this link 22262306a36Sopenharmony_ci * @qmult: queue multiplier 22362306a36Sopenharmony_ci * 22462306a36Sopenharmony_ci * This sets the queue length multiplier of this ethernet-over-usb link. 22562306a36Sopenharmony_ci * For higher speeds use longer queues. 22662306a36Sopenharmony_ci */ 22762306a36Sopenharmony_civoid gether_set_qmult(struct net_device *net, unsigned qmult); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci/** 23062306a36Sopenharmony_ci * gether_get_qmult - get an ethernet-over-usb link multiplier 23162306a36Sopenharmony_ci * @net: device representing this link 23262306a36Sopenharmony_ci * 23362306a36Sopenharmony_ci * This gets the queue length multiplier of this ethernet-over-usb link. 23462306a36Sopenharmony_ci */ 23562306a36Sopenharmony_ciunsigned gether_get_qmult(struct net_device *net); 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci/** 23862306a36Sopenharmony_ci * gether_get_ifname - get an ethernet-over-usb link interface name 23962306a36Sopenharmony_ci * @net: device representing this link 24062306a36Sopenharmony_ci * @name: place to store the interface name 24162306a36Sopenharmony_ci * @len: length of the @name buffer 24262306a36Sopenharmony_ci * 24362306a36Sopenharmony_ci * This gets the interface name of this ethernet-over-usb link. 24462306a36Sopenharmony_ci * Returns zero on success, else negative errno. 24562306a36Sopenharmony_ci */ 24662306a36Sopenharmony_ciint gether_get_ifname(struct net_device *net, char *name, int len); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci/** 24962306a36Sopenharmony_ci * gether_set_ifname - set an ethernet-over-usb link interface name 25062306a36Sopenharmony_ci * @net: device representing this link 25162306a36Sopenharmony_ci * @name: new interface name 25262306a36Sopenharmony_ci * @len: length of @name 25362306a36Sopenharmony_ci * 25462306a36Sopenharmony_ci * This sets the interface name of this ethernet-over-usb link. 25562306a36Sopenharmony_ci * A single terminating newline, if any, is ignored. 25662306a36Sopenharmony_ci * Returns zero on success, else negative errno. 25762306a36Sopenharmony_ci */ 25862306a36Sopenharmony_ciint gether_set_ifname(struct net_device *net, const char *name, int len); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_civoid gether_cleanup(struct eth_dev *dev); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_civoid gether_suspend(struct gether *link); 26362306a36Sopenharmony_civoid gether_resume(struct gether *link); 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci/* connect/disconnect is handled by individual functions */ 26662306a36Sopenharmony_cistruct net_device *gether_connect(struct gether *); 26762306a36Sopenharmony_civoid gether_disconnect(struct gether *); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci/* Some controllers can't support CDC Ethernet (ECM) ... */ 27062306a36Sopenharmony_cistatic inline bool can_support_ecm(struct usb_gadget *gadget) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci if (!gadget_is_altset_supported(gadget)) 27362306a36Sopenharmony_ci return false; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci /* Everything else is *presumably* fine ... but this is a bit 27662306a36Sopenharmony_ci * chancy, so be **CERTAIN** there are no hardware issues with 27762306a36Sopenharmony_ci * your controller. Add it above if it can't handle CDC. 27862306a36Sopenharmony_ci */ 27962306a36Sopenharmony_ci return true; 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci/* peak (theoretical) bulk transfer rate in bits-per-second */ 28362306a36Sopenharmony_cistatic inline unsigned int gether_bitrate(struct usb_gadget *g) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci if (g->speed >= USB_SPEED_SUPER_PLUS) 28662306a36Sopenharmony_ci return 4250000000U; 28762306a36Sopenharmony_ci if (g->speed == USB_SPEED_SUPER) 28862306a36Sopenharmony_ci return 3750000000U; 28962306a36Sopenharmony_ci else if (g->speed == USB_SPEED_HIGH) 29062306a36Sopenharmony_ci return 13 * 512 * 8 * 1000 * 8; 29162306a36Sopenharmony_ci else 29262306a36Sopenharmony_ci return 19 * 64 * 1 * 1000 * 8; 29362306a36Sopenharmony_ci} 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci#endif /* __U_ETHER_H */ 296