-#ifdef CONFIG_USB_ETH_RNDIS
-static const struct usb_descriptor_header *fs_rndis_function [] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- /* control interface matches ACM, not Ethernet */
- (struct usb_descriptor_header *) &rndis_control_intf,
- (struct usb_descriptor_header *) &header_desc,
- (struct usb_descriptor_header *) &call_mgmt_descriptor,
- (struct usb_descriptor_header *) &acm_descriptor,
- (struct usb_descriptor_header *) &union_desc,
- (struct usb_descriptor_header *) &fs_status_desc,
- /* data interface has no altsetting */
- (struct usb_descriptor_header *) &rndis_data_intf,
- (struct usb_descriptor_header *) &fs_source_desc,
- (struct usb_descriptor_header *) &fs_sink_desc,
- NULL,
-};
-#endif
-
-/*
- * usb 2.0 devices need to expose both high speed and full speed
- * descriptors, unless they only run at full speed.
- */
-
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-static struct usb_endpoint_descriptor
-hs_status_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
-
- .bmAttributes = USB_ENDPOINT_XFER_INT,
- .wMaxPacketSize = __constant_cpu_to_le16 (STATUS_BYTECOUNT),
- .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
-};
-#endif /* DEV_CONFIG_CDC */
-
-static struct usb_endpoint_descriptor
-hs_source_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
-
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = __constant_cpu_to_le16 (512),
-};
-
-static struct usb_endpoint_descriptor
-hs_sink_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
-
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = __constant_cpu_to_le16 (512),
-};
-
-static struct usb_qualifier_descriptor
-dev_qualifier = {
- .bLength = sizeof dev_qualifier,
- .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
-
- .bcdUSB = __constant_cpu_to_le16 (0x0200),
- .bDeviceClass = USB_CLASS_COMM,
-
- .bNumConfigurations = 1,
-};
-
-static const struct usb_descriptor_header *hs_eth_function [11] = {
- (struct usb_descriptor_header *) &otg_descriptor,
-#ifdef DEV_CONFIG_CDC
- /* "cdc" mode descriptors */
- (struct usb_descriptor_header *) &control_intf,
- (struct usb_descriptor_header *) &header_desc,
- (struct usb_descriptor_header *) &union_desc,
- (struct usb_descriptor_header *) ðer_desc,
- /* NOTE: status endpoint may need to be removed */
- (struct usb_descriptor_header *) &hs_status_desc,
- /* data interface, with altsetting */
- (struct usb_descriptor_header *) &data_nop_intf,
- (struct usb_descriptor_header *) &data_intf,
- (struct usb_descriptor_header *) &hs_source_desc,
- (struct usb_descriptor_header *) &hs_sink_desc,
- NULL,
-#endif /* DEV_CONFIG_CDC */
-};
-
-static inline void __init hs_subset_descriptors(void)
-{
-#ifdef DEV_CONFIG_SUBSET
- /* behavior is "CDC Subset"; extra descriptors say "SAFE" */
- hs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf;
- hs_eth_function[2] = (struct usb_descriptor_header *) &header_desc;
- hs_eth_function[3] = (struct usb_descriptor_header *) &mdlm_desc;
- hs_eth_function[4] = (struct usb_descriptor_header *) &mdlm_detail_desc;
- hs_eth_function[5] = (struct usb_descriptor_header *) ðer_desc;
- hs_eth_function[6] = (struct usb_descriptor_header *) &hs_source_desc;
- hs_eth_function[7] = (struct usb_descriptor_header *) &hs_sink_desc;
- hs_eth_function[8] = NULL;
-#else
- hs_eth_function[1] = NULL;
-#endif
-}
-
-#ifdef CONFIG_USB_ETH_RNDIS
-static const struct usb_descriptor_header *hs_rndis_function [] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- /* control interface matches ACM, not Ethernet */
- (struct usb_descriptor_header *) &rndis_control_intf,
- (struct usb_descriptor_header *) &header_desc,
- (struct usb_descriptor_header *) &call_mgmt_descriptor,
- (struct usb_descriptor_header *) &acm_descriptor,
- (struct usb_descriptor_header *) &union_desc,
- (struct usb_descriptor_header *) &hs_status_desc,
- /* data interface has no altsetting */
- (struct usb_descriptor_header *) &rndis_data_intf,
- (struct usb_descriptor_header *) &hs_source_desc,
- (struct usb_descriptor_header *) &hs_sink_desc,
- NULL,
-};
-#endif
-
-
-/* maxpacket and other transfer characteristics vary by speed. */
-static inline struct usb_endpoint_descriptor *
-ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
- struct usb_endpoint_descriptor *fs)
-{
- if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
- return hs;
- return fs;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* descriptors that are built on-demand */
-
-static char manufacturer [50];
-static char product_desc [40] = DRIVER_DESC;
-static char serial_number [20];
-
-/* address that the host will use ... usually assigned at random */
-static char ethaddr [2 * ETH_ALEN + 1];
-
-/* static strings, in UTF-8 */
-static struct usb_string strings [] = {
- { STRING_MANUFACTURER, manufacturer, },
- { STRING_PRODUCT, product_desc, },
- { STRING_SERIALNUMBER, serial_number, },
- { STRING_DATA, "Ethernet Data", },
- { STRING_ETHADDR, ethaddr, },
-#ifdef DEV_CONFIG_CDC
- { STRING_CDC, "CDC Ethernet", },
- { STRING_CONTROL, "CDC Communications Control", },
-#endif
-#ifdef DEV_CONFIG_SUBSET
- { STRING_SUBSET, "CDC Ethernet Subset", },
-#endif
-#ifdef CONFIG_USB_ETH_RNDIS
- { STRING_RNDIS, "RNDIS", },
- { STRING_RNDIS_CONTROL, "RNDIS Communications Control", },
-#endif
- { } /* end of list */
-};
-
-static struct usb_gadget_strings stringtab = {
- .language = 0x0409, /* en-us */
- .strings = strings,
-};
-
-/*
- * one config, two interfaces: control, data.
- * complications: class descriptors, and an altsetting.
- */
-static int
-config_buf(struct usb_gadget *g, u8 *buf, u8 type, unsigned index, int is_otg)
-{
- int len;
- const struct usb_config_descriptor *config;
- const struct usb_descriptor_header **function;
- int hs = 0;
-
- if (gadget_is_dualspeed(g)) {
- hs = (g->speed == USB_SPEED_HIGH);
- if (type == USB_DT_OTHER_SPEED_CONFIG)
- hs = !hs;
- }
-#define which_fn(t) (hs ? hs_ ## t ## _function : fs_ ## t ## _function)
-
- if (index >= device_desc.bNumConfigurations)
- return -EINVAL;
-
-#ifdef CONFIG_USB_ETH_RNDIS
- /* list the RNDIS config first, to make Microsoft's drivers
- * happy. DOCSIS 1.0 needs this too.
- */
- if (device_desc.bNumConfigurations == 2 && index == 0) {
- config = &rndis_config;
- function = which_fn (rndis);
- } else
-#endif
- {
- config = ð_config;
- function = which_fn (eth);
- }
-
- /* for now, don't advertise srp-only devices */
- if (!is_otg)
- function++;
-
- len = usb_gadget_config_buf (config, buf, USB_BUFSIZ, function);
- if (len < 0)
- return len;
- ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
- return len;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void eth_start (struct eth_dev *dev, gfp_t gfp_flags);
-static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags);
-
-static int
-set_ether_config (struct eth_dev *dev, gfp_t gfp_flags)
-{
- int result = 0;
- struct usb_gadget *gadget = dev->gadget;
-
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
- /* status endpoint used for RNDIS and (optionally) CDC */
- if (!subset_active(dev) && dev->status_ep) {
- dev->status = ep_desc (gadget, &hs_status_desc,
- &fs_status_desc);
- dev->status_ep->driver_data = dev;
-
- result = usb_ep_enable (dev->status_ep, dev->status);
- if (result != 0) {
- DEBUG (dev, "enable %s --> %d\n",
- dev->status_ep->name, result);
- goto done;
- }
- }
-#endif
-
- dev->in = ep_desc(gadget, &hs_source_desc, &fs_source_desc);
- dev->in_ep->driver_data = dev;
-
- dev->out = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc);
- dev->out_ep->driver_data = dev;
-
- /* With CDC, the host isn't allowed to use these two data
- * endpoints in the default altsetting for the interface.
- * so we don't activate them yet. Reset from SET_INTERFACE.
- *
- * Strictly speaking RNDIS should work the same: activation is
- * a side effect of setting a packet filter. Deactivation is
- * from REMOTE_NDIS_HALT_MSG, reset from REMOTE_NDIS_RESET_MSG.
- */
- if (!cdc_active(dev)) {
- result = usb_ep_enable (dev->in_ep, dev->in);
- if (result != 0) {
- DEBUG(dev, "enable %s --> %d\n",
- dev->in_ep->name, result);
- goto done;
- }
-
- result = usb_ep_enable (dev->out_ep, dev->out);
- if (result != 0) {
- DEBUG (dev, "enable %s --> %d\n",
- dev->out_ep->name, result);
- goto done;
- }
- }
-
-done:
- if (result == 0)
- result = alloc_requests (dev, qlen (gadget), gfp_flags);
-
- /* on error, disable any endpoints */
- if (result < 0) {
- if (!subset_active(dev) && dev->status_ep)
- (void) usb_ep_disable (dev->status_ep);
- dev->status = NULL;
- (void) usb_ep_disable (dev->in_ep);
- (void) usb_ep_disable (dev->out_ep);
- dev->in = NULL;
- dev->out = NULL;
- }
-
- /* activate non-CDC configs right away
- * this isn't strictly according to the RNDIS spec
- */
- else if (!cdc_active (dev)) {
- netif_carrier_on (dev->net);
- if (netif_running (dev->net)) {
- spin_unlock (&dev->lock);
- eth_start (dev, GFP_ATOMIC);
- spin_lock (&dev->lock);
- }
- }
-
- if (result == 0)
- DEBUG (dev, "qlen %d\n", qlen (gadget));
-
- /* caller is responsible for cleanup on error */
- return result;
-}
-
-static void eth_reset_config (struct eth_dev *dev)
-{
- struct usb_request *req;
-
- if (dev->config == 0)
- return;
-
- DEBUG (dev, "%s\n", __func__);
-
- netif_stop_queue (dev->net);
- netif_carrier_off (dev->net);
-
- /* RNDIS enters RNDIS_UNINITIALIZED state */
- rndis_uninit(dev->rndis_config);
-
- /* disable endpoints, forcing (synchronous) completion of
- * pending i/o. then free the requests.
- */
- if (dev->in) {
- usb_ep_disable (dev->in_ep);
- spin_lock(&dev->req_lock);
- while (likely (!list_empty (&dev->tx_reqs))) {
- req = container_of (dev->tx_reqs.next,
- struct usb_request, list);
- list_del (&req->list);
-
- spin_unlock(&dev->req_lock);
- usb_ep_free_request (dev->in_ep, req);
- spin_lock(&dev->req_lock);
- }
- spin_unlock(&dev->req_lock);
- }
- if (dev->out) {
- usb_ep_disable (dev->out_ep);
- spin_lock(&dev->req_lock);
- while (likely (!list_empty (&dev->rx_reqs))) {
- req = container_of (dev->rx_reqs.next,
- struct usb_request, list);
- list_del (&req->list);
-
- spin_unlock(&dev->req_lock);
- usb_ep_free_request (dev->out_ep, req);
- spin_lock(&dev->req_lock);
- }
- spin_unlock(&dev->req_lock);
- }
-
- if (dev->status) {
- usb_ep_disable (dev->status_ep);
- }
- dev->rndis = 0;
- dev->cdc_filter = 0;
- dev->config = 0;
-}
-
-/* change our operational config. must agree with the code
- * that returns config descriptors, and altsetting code.
- */
-static int
-eth_set_config (struct eth_dev *dev, unsigned number, gfp_t gfp_flags)
-{
- int result = 0;
- struct usb_gadget *gadget = dev->gadget;
-
- if (gadget_is_sa1100 (gadget)
- && dev->config
- && atomic_read (&dev->tx_qlen) != 0) {
- /* tx fifo is full, but we can't clear it...*/
- INFO (dev, "can't change configurations\n");
- return -ESPIPE;
- }
- eth_reset_config (dev);
-
- switch (number) {
- case DEV_CONFIG_VALUE:
- result = set_ether_config (dev, gfp_flags);
- break;
-#ifdef CONFIG_USB_ETH_RNDIS
- case DEV_RNDIS_CONFIG_VALUE:
- dev->rndis = 1;
- result = set_ether_config (dev, gfp_flags);
- break;
-#endif
- default:
- result = -EINVAL;
- /* FALL THROUGH */
- case 0:
- break;
- }
-
- if (result) {
- if (number)
- eth_reset_config (dev);
- usb_gadget_vbus_draw(dev->gadget,
- gadget_is_otg(dev->gadget) ? 8 : 100);
- } else {
- char *speed;
- unsigned power;
-
- power = 2 * eth_config.bMaxPower;
- usb_gadget_vbus_draw(dev->gadget, power);
-
- switch (gadget->speed) {
- case USB_SPEED_FULL: speed = "full"; break;
-#ifdef CONFIG_USB_GADGET_DUALSPEED
- case USB_SPEED_HIGH: speed = "high"; break;
-#endif
- default: speed = "?"; break;
- }
-
- dev->config = number;
- INFO (dev, "%s speed config #%d: %d mA, %s, using %s\n",
- speed, number, power, driver_desc,
- rndis_active(dev)
- ? "RNDIS"
- : (cdc_active(dev)
- ? "CDC Ethernet"
- : "CDC Ethernet Subset"));
- }
- return result;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef DEV_CONFIG_CDC
-
-/* The interrupt endpoint is used in CDC networking models (Ethernet, ATM)
- * only to notify the host about link status changes (which we support) or
- * report completion of some encapsulated command (as used in RNDIS). Since
- * we want this CDC Ethernet code to be vendor-neutral, we don't use that
- * command mechanism; and only one status request is ever queued.
- */
-
-static void eth_status_complete (struct usb_ep *ep, struct usb_request *req)
-{
- struct usb_cdc_notification *event = req->buf;
- int value = req->status;
- struct eth_dev *dev = ep->driver_data;
-
- /* issue the second notification if host reads the first */
- if (event->bNotificationType == USB_CDC_NOTIFY_NETWORK_CONNECTION
- && value == 0) {
- __le32 *data = req->buf + sizeof *event;
-
- event->bmRequestType = 0xA1;
- event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
- event->wValue = __constant_cpu_to_le16 (0);
- event->wIndex = __constant_cpu_to_le16 (1);
- event->wLength = __constant_cpu_to_le16 (8);
-
- /* SPEED_CHANGE data is up/down speeds in bits/sec */
- data [0] = data [1] = cpu_to_le32 (BITRATE (dev->gadget));
-
- req->length = STATUS_BYTECOUNT;
- value = usb_ep_queue (ep, req, GFP_ATOMIC);
- DEBUG (dev, "send SPEED_CHANGE --> %d\n", value);
- if (value == 0)
- return;
- } else if (value != -ECONNRESET)
- DEBUG (dev, "event %02x --> %d\n",
- event->bNotificationType, value);
- req->context = NULL;
-}
-
-static void issue_start_status (struct eth_dev *dev)
-{
- struct usb_request *req = dev->stat_req;
- struct usb_cdc_notification *event;
- int value;
-
- DEBUG (dev, "%s, flush old status first\n", __func__);
-
- /* flush old status
- *
- * FIXME ugly idiom, maybe we'd be better with just
- * a "cancel the whole queue" primitive since any
- * unlink-one primitive has way too many error modes.
- * here, we "know" toggle is already clear...
- *
- * FIXME iff req->context != null just dequeue it
- */
- usb_ep_disable (dev->status_ep);
- usb_ep_enable (dev->status_ep, dev->status);
-
- /* 3.8.1 says to issue first NETWORK_CONNECTION, then
- * a SPEED_CHANGE. could be useful in some configs.
- */
- event = req->buf;
- event->bmRequestType = 0xA1;
- event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
- event->wValue = __constant_cpu_to_le16 (1); /* connected */
- event->wIndex = __constant_cpu_to_le16 (1);
- event->wLength = 0;
-
- req->length = sizeof *event;
- req->complete = eth_status_complete;
- req->context = dev;
-
- value = usb_ep_queue (dev->status_ep, req, GFP_ATOMIC);
- if (value < 0)
- DEBUG (dev, "status buf queue --> %d\n", value);
-}
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-static void eth_setup_complete (struct usb_ep *ep, struct usb_request *req)
-{
- if (req->status || req->actual != req->length)
- DEBUG ((struct eth_dev *) ep->driver_data,
- "setup complete --> %d, %d/%d\n",
- req->status, req->actual, req->length);
-}
-
-#ifdef CONFIG_USB_ETH_RNDIS
-
-static void rndis_response_complete (struct usb_ep *ep, struct usb_request *req)
-{
- if (req->status || req->actual != req->length)
- DEBUG ((struct eth_dev *) ep->driver_data,
- "rndis response complete --> %d, %d/%d\n",
- req->status, req->actual, req->length);
-
- /* done sending after USB_CDC_GET_ENCAPSULATED_RESPONSE */
-}
-
-static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req)
-{
- struct eth_dev *dev = ep->driver_data;
- int status;
-
- /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
- spin_lock(&dev->lock);
- status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf);
- if (status < 0)
- ERROR(dev, "%s: rndis parse error %d\n", __func__, status);
- spin_unlock(&dev->lock);
-}
-
-#endif /* RNDIS */
-
-/*
- * The setup() callback implements all the ep0 functionality that's not
- * handled lower down. CDC has a number of less-common features:
- *
- * - two interfaces: control, and ethernet data
- * - Ethernet data interface has two altsettings: default, and active
- * - class-specific descriptors for the control interface
- * - class-specific control requests
- */
-static int
-eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
-{
- struct eth_dev *dev = get_gadget_data (gadget);
- struct usb_request *req = dev->req;
- int value = -EOPNOTSUPP;
- u16 wIndex = le16_to_cpu(ctrl->wIndex);
- u16 wValue = le16_to_cpu(ctrl->wValue);
- u16 wLength = le16_to_cpu(ctrl->wLength);
-
- /* descriptors just go into the pre-allocated ep0 buffer,
- * while config change events may enable network traffic.
- */
- req->complete = eth_setup_complete;
- switch (ctrl->bRequest) {
-
- case USB_REQ_GET_DESCRIPTOR:
- if (ctrl->bRequestType != USB_DIR_IN)
- break;
- switch (wValue >> 8) {
-
- case USB_DT_DEVICE:
- value = min (wLength, (u16) sizeof device_desc);
- memcpy (req->buf, &device_desc, value);
- break;
- case USB_DT_DEVICE_QUALIFIER:
- if (!gadget_is_dualspeed(gadget))
- break;
- value = min (wLength, (u16) sizeof dev_qualifier);
- memcpy (req->buf, &dev_qualifier, value);
- break;
-
- case USB_DT_OTHER_SPEED_CONFIG:
- if (!gadget_is_dualspeed(gadget))
- break;
- // FALLTHROUGH
- case USB_DT_CONFIG:
- value = config_buf(gadget, req->buf,
- wValue >> 8,
- wValue & 0xff,
- gadget_is_otg(gadget));
- if (value >= 0)
- value = min (wLength, (u16) value);
- break;
-
- case USB_DT_STRING:
- value = usb_gadget_get_string (&stringtab,
- wValue & 0xff, req->buf);
- if (value >= 0)
- value = min (wLength, (u16) value);
- break;
- }
- break;
-
- case USB_REQ_SET_CONFIGURATION:
- if (ctrl->bRequestType != 0)
- break;
- if (gadget->a_hnp_support)
- DEBUG (dev, "HNP available\n");
- else if (gadget->a_alt_hnp_support)
- DEBUG (dev, "HNP needs a different root port\n");
- spin_lock (&dev->lock);
- value = eth_set_config (dev, wValue, GFP_ATOMIC);
- spin_unlock (&dev->lock);
- break;
- case USB_REQ_GET_CONFIGURATION:
- if (ctrl->bRequestType != USB_DIR_IN)
- break;
- *(u8 *)req->buf = dev->config;
- value = min (wLength, (u16) 1);
- break;
-
- case USB_REQ_SET_INTERFACE:
- if (ctrl->bRequestType != USB_RECIP_INTERFACE
- || !dev->config
- || wIndex > 1)
- break;
- if (!cdc_active(dev) && wIndex != 0)
- break;
- spin_lock (&dev->lock);
-
- /* PXA hardware partially handles SET_INTERFACE;
- * we need to kluge around that interference.
- */
- if (gadget_is_pxa (gadget)) {
- value = eth_set_config (dev, DEV_CONFIG_VALUE,
- GFP_ATOMIC);
- goto done_set_intf;
- }
-
-#ifdef DEV_CONFIG_CDC
- switch (wIndex) {
- case 0: /* control/master intf */
- if (wValue != 0)
- break;
- if (dev->status) {
- usb_ep_disable (dev->status_ep);
- usb_ep_enable (dev->status_ep, dev->status);
- }
- value = 0;
- break;
- case 1: /* data intf */
- if (wValue > 1)
- break;
- usb_ep_disable (dev->in_ep);
- usb_ep_disable (dev->out_ep);
-
- /* CDC requires the data transfers not be done from
- * the default interface setting ... also, setting
- * the non-default interface resets filters etc.
- */
- if (wValue == 1) {
- if (!cdc_active (dev))
- break;
- usb_ep_enable (dev->in_ep, dev->in);
- usb_ep_enable (dev->out_ep, dev->out);
- dev->cdc_filter = DEFAULT_FILTER;
- netif_carrier_on (dev->net);
- if (dev->status)
- issue_start_status (dev);
- if (netif_running (dev->net)) {
- spin_unlock (&dev->lock);
- eth_start (dev, GFP_ATOMIC);
- spin_lock (&dev->lock);
- }
- } else {
- netif_stop_queue (dev->net);
- netif_carrier_off (dev->net);
- }
- value = 0;
- break;
- }
-#else
- /* FIXME this is wrong, as is the assumption that
- * all non-PXA hardware talks real CDC ...
- */
- dev_warn (&gadget->dev, "set_interface ignored!\n");
-#endif /* DEV_CONFIG_CDC */
-
-done_set_intf:
- spin_unlock (&dev->lock);
- break;
- case USB_REQ_GET_INTERFACE:
- if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)
- || !dev->config
- || wIndex > 1)
- break;
- if (!(cdc_active(dev) || rndis_active(dev)) && wIndex != 0)
- break;
-
- /* for CDC, iff carrier is on, data interface is active. */
- if (rndis_active(dev) || wIndex != 1)
- *(u8 *)req->buf = 0;
- else
- *(u8 *)req->buf = netif_carrier_ok (dev->net) ? 1 : 0;
- value = min (wLength, (u16) 1);
- break;
-
-#ifdef DEV_CONFIG_CDC
- case USB_CDC_SET_ETHERNET_PACKET_FILTER:
- /* see 6.2.30: no data, wIndex = interface,
- * wValue = packet filter bitmap
- */
- if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE)
- || !cdc_active(dev)
- || wLength != 0
- || wIndex > 1)
- break;
- DEBUG (dev, "packet filter %02x\n", wValue);
- dev->cdc_filter = wValue;
- value = 0;
- break;
-
- /* and potentially:
- * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS:
- * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER:
- * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER:
- * case USB_CDC_GET_ETHERNET_STATISTIC:
- */
-
-#endif /* DEV_CONFIG_CDC */
-
-#ifdef CONFIG_USB_ETH_RNDIS
- /* RNDIS uses the CDC command encapsulation mechanism to implement
- * an RPC scheme, with much getting/setting of attributes by OID.
- */
- case USB_CDC_SEND_ENCAPSULATED_COMMAND:
- if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE)
- || !rndis_active(dev)
- || wLength > USB_BUFSIZ
- || wValue
- || rndis_control_intf.bInterfaceNumber
- != wIndex)
- break;
- /* read the request, then process it */
- value = wLength;
- req->complete = rndis_command_complete;
- /* later, rndis_control_ack () sends a notification */
- break;
-
- case USB_CDC_GET_ENCAPSULATED_RESPONSE:
- if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE)
- == ctrl->bRequestType
- && rndis_active(dev)
- // && wLength >= 0x0400
- && !wValue
- && rndis_control_intf.bInterfaceNumber
- == wIndex) {
- u8 *buf;
- u32 n;
-
- /* return the result */
- buf = rndis_get_next_response(dev->rndis_config, &n);
- if (buf) {
- memcpy(req->buf, buf, n);
- req->complete = rndis_response_complete;
- rndis_free_response(dev->rndis_config, buf);
- value = n;
- }
- /* else stalls ... spec says to avoid that */
- }
- break;
-#endif /* RNDIS */
-
- default:
- VDEBUG (dev,
- "unknown control req%02x.%02x v%04x i%04x l%d\n",
- ctrl->bRequestType, ctrl->bRequest,
- wValue, wIndex, wLength);
- }
-
- /* respond with data transfer before status phase? */
- if (value >= 0) {
- req->length = value;
- req->zero = value < wLength
- && (value % gadget->ep0->maxpacket) == 0;
- value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
- if (value < 0) {
- DEBUG (dev, "ep_queue --> %d\n", value);
- req->status = 0;
- eth_setup_complete (gadget->ep0, req);
- }
- }
-
- /* host either stalls (value < 0) or reports success */
- return value;
-}
-
-static void
-eth_disconnect (struct usb_gadget *gadget)
-{
- struct eth_dev *dev = get_gadget_data (gadget);
- unsigned long flags;
-
- spin_lock_irqsave (&dev->lock, flags);
- netif_stop_queue (dev->net);
- netif_carrier_off (dev->net);
- eth_reset_config (dev);
- spin_unlock_irqrestore (&dev->lock, flags);
-
- /* next we may get setup() calls to enumerate new connections;
- * or an unbind() during shutdown (including removing module).
- */
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* NETWORK DRIVER HOOKUP (to the layer above this driver) */
-
-static int eth_change_mtu (struct net_device *net, int new_mtu)
-{
- struct eth_dev *dev = netdev_priv(net);
-
- if (dev->rndis)
- return -EBUSY;
-
- if (new_mtu <= ETH_HLEN || new_mtu > ETH_FRAME_LEN)
- return -ERANGE;
- /* no zero-length packet read wanted after mtu-sized packets */
- if (((new_mtu + sizeof (struct ethhdr)) % dev->in_ep->maxpacket) == 0)
- return -EDOM;
- net->mtu = new_mtu;
- return 0;
-}
-
-static struct net_device_stats *eth_get_stats (struct net_device *net)
-{
- return &((struct eth_dev *)netdev_priv(net))->stats;
-}
-
-static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
-{
- struct eth_dev *dev = netdev_priv(net);
- strlcpy(p->driver, shortname, sizeof p->driver);
- strlcpy(p->version, DRIVER_VERSION, sizeof p->version);
- strlcpy(p->fw_version, dev->gadget->name, sizeof p->fw_version);
- strlcpy (p->bus_info, dev_name(&dev->gadget->dev), sizeof p->bus_info);
-}
-
-static u32 eth_get_link(struct net_device *net)
-{
- struct eth_dev *dev = netdev_priv(net);
- return dev->gadget->speed != USB_SPEED_UNKNOWN;
-}
-
-static struct ethtool_ops ops = {
- .get_drvinfo = eth_get_drvinfo,
- .get_link = eth_get_link
-};
-
-static void defer_kevent (struct eth_dev *dev, int flag)
-{
- if (test_and_set_bit (flag, &dev->todo))
- return;
- if (!schedule_work (&dev->work))
- ERROR (dev, "kevent %d may have been dropped\n", flag);
- else
- DEBUG (dev, "kevent %d scheduled\n", 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)
-{
- struct sk_buff *skb;
- int retval = -ENOMEM;
- size_t size;
-
- /* Padding up to RX_EXTRA handles minor disagreements with host.
- * Normally we use the USB "terminate on short read" convention;
- * so allow up to (N*maxpacket), since that memory is normally
- * already allocated. Some hardware doesn't deal well with short
- * reads (e.g. DMA must be N*maxpacket), so for now don't trim a
- * byte off the end (to force hardware errors on overflow).
- *
- * RNDIS uses internal framing, and explicitly allows senders to
- * pad to end-of-packet. That's potentially nice for speed,
- * but means receivers can't recover synch on their own.
- */
- size = (sizeof (struct ethhdr) + dev->net->mtu + RX_EXTRA);
- size += dev->out_ep->maxpacket - 1;
- if (rndis_active(dev))
- size += sizeof (struct rndis_packet_msg_type);
- size -= size % dev->out_ep->maxpacket;
-
- skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags);
- if (skb == NULL) {
- DEBUG (dev, "no rx skb\n");
- goto enomem;
- }
-
- /* Some platforms perform better when IP packets are aligned,
- * but on at least one, checksumming fails otherwise. Note:
- * RNDIS headers involve variable numbers of LE32 values.
- */
- skb_reserve(skb, NET_IP_ALIGN);
-
- req->buf = skb->data;
- req->length = size;
- req->complete = rx_complete;
- req->context = skb;
-
- retval = usb_ep_queue (dev->out_ep, req, gfp_flags);
- if (retval == -ENOMEM)
-enomem:
- defer_kevent (dev, WORK_RX_MEMORY);
- if (retval) {
- DEBUG (dev, "rx submit --> %d\n", retval);
- if (skb)
- dev_kfree_skb_any(skb);
- spin_lock(&dev->req_lock);
- list_add (&req->list, &dev->rx_reqs);
- spin_unlock(&dev->req_lock);
- }
- return retval;
-}
-
-static void rx_complete (struct usb_ep *ep, struct usb_request *req)
-{
- struct sk_buff *skb = req->context;
- struct eth_dev *dev = ep->driver_data;
- int status = req->status;
-
- switch (status) {
-
- /* normal completion */
- case 0:
- skb_put (skb, req->actual);
- /* we know MaxPacketsPerTransfer == 1 here */
- if (rndis_active(dev))
- status = rndis_rm_hdr (skb);
- if (status < 0
- || ETH_HLEN > skb->len
- || skb->len > ETH_FRAME_LEN) {
- dev->stats.rx_errors++;
- dev->stats.rx_length_errors++;
- DEBUG (dev, "rx length %d\n", skb->len);
- break;
- }
-
- skb->protocol = eth_type_trans (skb, dev->net);
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += skb->len;
-
- /* no buffer copies needed, unless hardware can't
- * use skb buffers.
- */
- status = netif_rx (skb);
- skb = NULL;
- break;
-
- /* software-driven interface shutdown */
- case -ECONNRESET: // unlink
- case -ESHUTDOWN: // disconnect etc
- VDEBUG (dev, "rx shutdown, code %d\n", status);
- goto quiesce;
-
- /* for hardware automagic (such as pxa) */
- case -ECONNABORTED: // endpoint reset
- DEBUG (dev, "rx %s reset\n", ep->name);
- defer_kevent (dev, WORK_RX_MEMORY);
-quiesce:
- dev_kfree_skb_any (skb);
- goto clean;
-
- /* data overrun */
- case -EOVERFLOW:
- dev->stats.rx_over_errors++;
- // FALLTHROUGH
-
- default:
- dev->stats.rx_errors++;
- DEBUG (dev, "rx status %d\n", status);
- break;
- }
-
- if (skb)
- dev_kfree_skb_any (skb);
- if (!netif_running (dev->net)) {
-clean:
- spin_lock(&dev->req_lock);
- list_add (&req->list, &dev->rx_reqs);
- spin_unlock(&dev->req_lock);
- req = NULL;
- }
- if (req)
- rx_submit (dev, req, GFP_ATOMIC);
-}
-
-static int prealloc (struct list_head *list, struct usb_ep *ep,
- unsigned n, gfp_t gfp_flags)
-{
- unsigned i;
- struct usb_request *req;
-
- if (!n)
- return -ENOMEM;
-
- /* queue/recycle up to N requests */
- i = n;
- list_for_each_entry (req, list, list) {
- if (i-- == 0)
- goto extra;
- }
- while (i--) {
- req = usb_ep_alloc_request (ep, gfp_flags);
- if (!req)
- return list_empty (list) ? -ENOMEM : 0;
- list_add (&req->list, list);
- }
- return 0;
-
-extra:
- /* free extras */
- for (;;) {
- struct list_head *next;
-
- next = req->list.next;
- list_del (&req->list);
- usb_ep_free_request (ep, req);
-
- if (next == list)
- break;
-
- req = container_of (next, struct usb_request, list);
- }
- return 0;
-}
-
-static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags)
-{
- int status;
-
- spin_lock(&dev->req_lock);
- status = prealloc (&dev->tx_reqs, dev->in_ep, n, gfp_flags);
- if (status < 0)
- goto fail;
- status = prealloc (&dev->rx_reqs, dev->out_ep, n, gfp_flags);
- if (status < 0)
- goto fail;
- goto done;
-fail:
- DEBUG (dev, "can't alloc requests\n");
-done:
- spin_unlock(&dev->req_lock);
- return status;
-}
-
-static void rx_fill (struct eth_dev *dev, gfp_t gfp_flags)
-{
- struct usb_request *req;
- unsigned long flags;
-
- /* fill unused rxq slots with some skb */
- spin_lock_irqsave(&dev->req_lock, flags);
- while (!list_empty (&dev->rx_reqs)) {
- req = container_of (dev->rx_reqs.next,
- struct usb_request, list);
- list_del_init (&req->list);
- spin_unlock_irqrestore(&dev->req_lock, flags);
-
- if (rx_submit (dev, req, gfp_flags) < 0) {
- defer_kevent (dev, WORK_RX_MEMORY);
- return;
- }
-
- spin_lock_irqsave(&dev->req_lock, flags);
- }
- spin_unlock_irqrestore(&dev->req_lock, flags);
-}
-
-static void eth_work (struct work_struct *work)
-{
- struct eth_dev *dev = container_of(work, struct eth_dev, work);
-
- if (test_and_clear_bit (WORK_RX_MEMORY, &dev->todo)) {
- if (netif_running (dev->net))
- rx_fill (dev, GFP_KERNEL);
- }
-
- if (dev->todo)
- DEBUG (dev, "work done, flags = 0x%lx\n", dev->todo);
-}
-
-static void tx_complete (struct usb_ep *ep, struct usb_request *req)
-{
- struct sk_buff *skb = req->context;
- struct eth_dev *dev = ep->driver_data;
-
- switch (req->status) {
- default:
- dev->stats.tx_errors++;
- VDEBUG (dev, "tx err %d\n", req->status);
- /* FALLTHROUGH */
- case -ECONNRESET: // unlink
- case -ESHUTDOWN: // disconnect etc
- break;
- case 0:
- dev->stats.tx_bytes += skb->len;
- }
- dev->stats.tx_packets++;
-
- spin_lock(&dev->req_lock);
- list_add (&req->list, &dev->tx_reqs);
- spin_unlock(&dev->req_lock);
- dev_kfree_skb_any (skb);
-
- atomic_dec (&dev->tx_qlen);
- if (netif_carrier_ok (dev->net))
- netif_wake_queue (dev->net);
-}
-
-static inline int eth_is_promisc (struct eth_dev *dev)
-{
- /* no filters for the CDC subset; always promisc */
- if (subset_active (dev))
- return 1;
- return dev->cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS;
-}
-
-static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
-{
- struct eth_dev *dev = netdev_priv(net);
- int length = skb->len;
- int retval;
- struct usb_request *req = NULL;
- unsigned long flags;
-
- /* apply outgoing CDC or RNDIS filters */
- if (!eth_is_promisc (dev)) {
- u8 *dest = skb->data;
-
- if (is_multicast_ether_addr(dest)) {
- u16 type;
-
- /* ignores USB_CDC_PACKET_TYPE_MULTICAST and host
- * SET_ETHERNET_MULTICAST_FILTERS requests
- */
- if (is_broadcast_ether_addr(dest))
- type = USB_CDC_PACKET_TYPE_BROADCAST;
- else
- type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;
- if (!(dev->cdc_filter & type)) {
- dev_kfree_skb_any (skb);
- return 0;
- }
- }
- /* ignores USB_CDC_PACKET_TYPE_DIRECTED */
- }
-
- spin_lock_irqsave(&dev->req_lock, flags);
- /*
- * this freelist can be empty if an interrupt triggered disconnect()
- * and reconfigured the gadget (shutting down this queue) after the
- * network stack decided to xmit but before we got the spinlock.
- */
- if (list_empty(&dev->tx_reqs)) {
- spin_unlock_irqrestore(&dev->req_lock, flags);
- return 1;
- }
-
- req = container_of (dev->tx_reqs.next, struct usb_request, list);
- list_del (&req->list);
-
- /* temporarily stop TX queue when the freelist empties */
- if (list_empty (&dev->tx_reqs))
- netif_stop_queue (net);
- spin_unlock_irqrestore(&dev->req_lock, flags);
-
- /* no buffer copies needed, unless the network stack did it
- * or the hardware can't use skb buffers.
- * or there's not enough space for any RNDIS headers we need
- */
- if (rndis_active(dev)) {
- struct sk_buff *skb_rndis;
-
- skb_rndis = skb_realloc_headroom (skb,
- sizeof (struct rndis_packet_msg_type));
- if (!skb_rndis)
- goto drop;
-
- dev_kfree_skb_any (skb);
- skb = skb_rndis;
- rndis_add_hdr (skb);
- length = skb->len;
- }
- req->buf = skb->data;
- req->context = skb;
- req->complete = tx_complete;
-
- /* use zlp framing on tx for strict CDC-Ether conformance,
- * though any robust network rx path ignores extra padding.
- * and some hardware doesn't like to write zlps.
- */
- req->zero = 1;
- if (!dev->zlp && (length % dev->in_ep->maxpacket) == 0)
- length++;
-
- req->length = length;
-
- /* throttle highspeed IRQ rate back slightly */
- if (gadget_is_dualspeed(dev->gadget))
- req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH)
- ? ((atomic_read(&dev->tx_qlen) % qmult) != 0)
- : 0;
-
- retval = usb_ep_queue (dev->in_ep, req, GFP_ATOMIC);
- switch (retval) {
- default:
- DEBUG (dev, "tx queue err %d\n", retval);
- break;
- case 0:
- net->trans_start = jiffies;
- atomic_inc (&dev->tx_qlen);
- }
-
- if (retval) {
-drop:
- dev->stats.tx_dropped++;
- dev_kfree_skb_any (skb);
- spin_lock_irqsave(&dev->req_lock, flags);
- if (list_empty (&dev->tx_reqs))
- netif_start_queue (net);
- list_add (&req->list, &dev->tx_reqs);
- spin_unlock_irqrestore(&dev->req_lock, flags);
- }
- return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_USB_ETH_RNDIS
-
-/* The interrupt endpoint is used in RNDIS to notify the host when messages
- * other than data packets are available ... notably the REMOTE_NDIS_*_CMPLT
- * messages, but also REMOTE_NDIS_INDICATE_STATUS_MSG and potentially even
- * REMOTE_NDIS_KEEPALIVE_MSG.
- *
- * The RNDIS control queue is processed by GET_ENCAPSULATED_RESPONSE, and
- * normally just one notification will be queued.
- */
-
-static struct usb_request *eth_req_alloc (struct usb_ep *, unsigned, gfp_t);
-static void eth_req_free (struct usb_ep *ep, struct usb_request *req);
-
-static void
-rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req)
-{
- struct eth_dev *dev = ep->driver_data;
-
- if (req->status || req->actual != req->length)
- DEBUG (dev,
- "rndis control ack complete --> %d, %d/%d\n",
- req->status, req->actual, req->length);
- req->context = NULL;
-
- if (req != dev->stat_req)
- eth_req_free(ep, req);
-}
-
-static void rndis_resp_avail(void *_dev)
-{
- struct eth_dev *dev = _dev;
- int length;
- struct usb_request *resp = dev->stat_req;
-
- /* in case RNDIS calls this after disconnect */
- if (!dev->status) {
- DEBUG (dev, "status ENODEV\n");
- return;
- }
-
- /* in case queue length > 1 */
- if (resp->context) {
- resp = eth_req_alloc (dev->status_ep, 8, GFP_ATOMIC);
- if (!resp)
- return;
- }
-
- /* Send RNDIS RESPONSE_AVAILABLE notification;
- * USB_CDC_NOTIFY_RESPONSE_AVAILABLE should work too
- */
- resp->length = 8;
- resp->complete = rndis_control_ack_complete;
- resp->context = dev;
-
- *((__le32 *) resp->buf) = __constant_cpu_to_le32 (1);
- *((__le32 *) resp->buf + 1) = __constant_cpu_to_le32 (0);
-
- length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC);
- if (length < 0) {
- resp->status = 0;
- rndis_control_ack_complete (dev->status_ep, resp);
- }
-}
-
-#else
-
-#define rndis_resp_avail NULL
-
-#endif /* RNDIS */
-
-static void eth_start (struct eth_dev *dev, gfp_t gfp_flags)
-{
- DEBUG (dev, "%s\n", __func__);
-
- /* fill the rx queue */
- rx_fill (dev, gfp_flags);
-
- /* and open the tx floodgates */
- atomic_set (&dev->tx_qlen, 0);
- netif_wake_queue (dev->net);
- if (rndis_active(dev)) {
- rndis_set_param_medium (dev->rndis_config,
- NDIS_MEDIUM_802_3,
- BITRATE(dev->gadget)/100);
- (void) rndis_signal_connect (dev->rndis_config);
- }
-}
-
-static int eth_open (struct net_device *net)
-{
- struct eth_dev *dev = netdev_priv(net);
-
- DEBUG (dev, "%s\n", __func__);
- if (netif_carrier_ok (dev->net))
- eth_start (dev, GFP_KERNEL);
- return 0;
-}
-
-static int eth_stop (struct net_device *net)
-{
- struct eth_dev *dev = netdev_priv(net);
-
- VDEBUG (dev, "%s\n", __func__);
- netif_stop_queue (net);
-
- DEBUG (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
- dev->stats.rx_packets, dev->stats.tx_packets,
- dev->stats.rx_errors, dev->stats.tx_errors
- );
-
- /* ensure there are no more active requests */
- if (dev->config) {
- usb_ep_disable (dev->in_ep);
- usb_ep_disable (dev->out_ep);
- if (netif_carrier_ok (dev->net)) {
- DEBUG (dev, "host still using in/out endpoints\n");
- // FIXME idiom may leave toggle wrong here
- usb_ep_enable (dev->in_ep, dev->in);
- usb_ep_enable (dev->out_ep, dev->out);
- }
- if (dev->status_ep) {
- usb_ep_disable (dev->status_ep);
- usb_ep_enable (dev->status_ep, dev->status);
- }
- }
-
- if (rndis_active(dev)) {
- rndis_set_param_medium(dev->rndis_config, NDIS_MEDIUM_802_3, 0);
- (void) rndis_signal_disconnect (dev->rndis_config);
- }
-
- return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_request *
-eth_req_alloc (struct usb_ep *ep, unsigned size, gfp_t gfp_flags)
-{
- struct usb_request *req;
-
- req = usb_ep_alloc_request (ep, gfp_flags);
- if (!req)
- return NULL;
-
- req->buf = kmalloc (size, gfp_flags);
- if (!req->buf) {
- usb_ep_free_request (ep, req);
- req = NULL;
- }
- return req;
-}
-
-static void
-eth_req_free (struct usb_ep *ep, struct usb_request *req)
-{
- kfree (req->buf);
- usb_ep_free_request (ep, req);
-}
-
-
-static void /* __init_or_exit */
-eth_unbind (struct usb_gadget *gadget)