patch-2.4.26 linux-2.4.26/drivers/usb/gadget/zero.c
Next file: linux-2.4.26/drivers/usb/hcd.c
Previous file: linux-2.4.26/drivers/usb/gadget/usbstring.c
Back to the patch index
Back to the overall index
- Lines: 376
- Date:
2004-04-14 06:05:32.000000000 -0700
- Orig file:
linux-2.4.25/drivers/usb/gadget/zero.c
- Orig date:
2004-02-18 05:36:31.000000000 -0800
diff -urN linux-2.4.25/drivers/usb/gadget/zero.c linux-2.4.26/drivers/usb/gadget/zero.c
@@ -1,7 +1,7 @@
/*
* zero.c -- Gadget Zero, for USB development
*
- * Copyright (C) 2003 David Brownell
+ * Copyright (C) 2003-2004 David Brownell
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -101,6 +101,11 @@
/*-------------------------------------------------------------------------*/
/*
+ * driver assumes self-powered hardware, and
+ * has no way for users to trigger remote wakeup.
+ */
+
+/*
* hardware-specific configuration, controlled by which device
* controller driver was configured.
*
@@ -108,11 +113,6 @@
* DRIVER_VERSION_NUM ... alerts the host side driver to differences
* EP_*_NAME ... which endpoints do we use for which purpose?
* EP_*_NUM ... numbers for them (often limited by hardware)
- * HIGHSPEED ... define if ep0 and descriptors need high speed support
- * MAX_USB_POWER ... define if we use other than 100 mA bus current
- * SELFPOWER ... if we can run on bus power, zero
- * WAKEUP ... if hardware supports remote wakeup AND we will issue the
- * usb_gadget_wakeup() call to initiate it, USB_CONFIG_ATT_WAKEUP
*
* add other defines for other portability issues, like hardware that
* for some reason doesn't handle full speed bulk maxpacket of 64.
@@ -136,9 +136,6 @@
#define EP_OUT_NUM 2
static const char EP_IN_NAME [] = "ep-b";
#define EP_IN_NUM 2
-#define HIGHSPEED
-/* specific hardware configs could be bus-powered */
-/* supports remote wakeup, but this driver doesn't */
#endif
/*
@@ -159,8 +156,6 @@
#define EP_OUT_NUM 12
static const char EP_IN_NAME [] = "ep11in-bulk";
#define EP_IN_NUM 11
-/* doesn't support bus-powered operation */
-/* supports remote wakeup, but this driver doesn't */
#endif
/*
@@ -181,8 +176,6 @@
#define EP_OUT_NUM 1
static const char EP_IN_NAME [] = "ep2in-bulk";
#define EP_IN_NUM 2
-/* doesn't support bus-powered operation */
-/* doesn't support remote wakeup? */
#endif
/*
@@ -197,7 +190,6 @@
#define EP_OUT_NUM 1
static const char EP_IN_NAME [] = "ep2-bulk";
#define EP_IN_NUM 2
-/* doesn't support remote wakeup */
#endif
/*-------------------------------------------------------------------------*/
@@ -206,30 +198,6 @@
# error Configure some USB peripheral controller driver!
#endif
-/* power usage is config specific.
- * hardware that supports remote wakeup defaults to disabling it.
- */
-
-#ifndef SELFPOWER
-/* default: say we're self-powered */
-#define SELFPOWER USB_CONFIG_ATT_SELFPOWER
-/* else:
- * - SELFPOWER value must be zero
- * - MAX_USB_POWER may be nonzero.
- */
-#endif
-
-#ifndef MAX_USB_POWER
-/* any hub supports this steady state bus power consumption */
-#define MAX_USB_POWER 100 /* mA */
-#endif
-
-#ifndef WAKEUP
-/* default: this driver won't do remote wakeup */
-#define WAKEUP 0
-/* else value must be USB_CONFIG_ATT_WAKEUP */
-#endif
-
/*-------------------------------------------------------------------------*/
/* big enough to hold our biggest descriptor */
@@ -284,8 +252,8 @@
/*
* Normally the "loopback" configuration is second (index 1) so
* it's not the default. Here's where to change that order, to
- * work better with hosts (like Linux ... for now!) where config
- * changes are problematic.
+ * work better with hosts where config changes are problematic.
+ * Or controllers (like superh) that only support one config.
*/
static int loopdefault = 0;
@@ -306,7 +274,7 @@
/* Thanks to NetChip Technologies for donating this product ID.
*
- * DO NOT REUSE THESE IDs with any other driver!! Ever!!
+ * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
* Instead: allocate your own, using normal USB-IF procedures.
*/
#define DRIVER_VENDOR_NUM 0x0525 /* NetChip */
@@ -358,8 +326,8 @@
.bNumInterfaces = 1,
.bConfigurationValue = CONFIG_SOURCE_SINK,
.iConfiguration = STRING_SOURCE_SINK,
- .bmAttributes = USB_CONFIG_ATT_ONE | SELFPOWER | WAKEUP,
- .bMaxPower = (MAX_USB_POWER + 1) / 2,
+ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+ .bMaxPower = 1, /* self-powered */
};
static const struct usb_config_descriptor
@@ -371,8 +339,8 @@
.bNumInterfaces = 1,
.bConfigurationValue = CONFIG_LOOPBACK,
.iConfiguration = STRING_LOOPBACK,
- .bmAttributes = USB_CONFIG_ATT_ONE | SELFPOWER | WAKEUP,
- .bMaxPower = (MAX_USB_POWER + 1) / 2,
+ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+ .bMaxPower = 1, /* self-powered */
};
/* one interface in each configuration */
@@ -419,7 +387,21 @@
.wMaxPacketSize = __constant_cpu_to_le16 (64),
};
-#ifdef HIGHSPEED
+static const struct usb_descriptor_header *fs_source_sink_function [] = {
+ (struct usb_descriptor_header *) &source_sink_intf,
+ (struct usb_descriptor_header *) &fs_sink_desc,
+ (struct usb_descriptor_header *) &fs_source_desc,
+ 0,
+};
+
+static const struct usb_descriptor_header *fs_loopback_function [] = {
+ (struct usb_descriptor_header *) &loopback_intf,
+ (struct usb_descriptor_header *) &fs_sink_desc,
+ (struct usb_descriptor_header *) &fs_source_desc,
+ 0,
+};
+
+#ifdef CONFIG_USB_GADGET_DUALSPEED
/*
* usb 2.0 devices need to expose both high speed and full speed
@@ -430,22 +412,20 @@
* for the config descriptor.
*/
-static const struct usb_endpoint_descriptor
+static struct usb_endpoint_descriptor
hs_source_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = EP_IN_NUM | USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16 (512),
};
-static const struct usb_endpoint_descriptor
+static struct usb_endpoint_descriptor
hs_sink_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = EP_OUT_NUM,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16 (512),
};
@@ -461,6 +441,20 @@
.bNumConfigurations = 2,
};
+static const struct usb_descriptor_header *hs_source_sink_function [] = {
+ (struct usb_descriptor_header *) &source_sink_intf,
+ (struct usb_descriptor_header *) &hs_source_desc,
+ (struct usb_descriptor_header *) &hs_sink_desc,
+ 0,
+};
+
+static const struct usb_descriptor_header *hs_loopback_function [] = {
+ (struct usb_descriptor_header *) &loopback_intf,
+ (struct usb_descriptor_header *) &hs_source_desc,
+ (struct usb_descriptor_header *) &hs_sink_desc,
+ 0,
+};
+
/* maxpacket and other transfer characteristics vary by speed. */
#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))
@@ -469,13 +463,14 @@
/* if there's no high speed support, maxpacket doesn't change. */
#define ep_desc(g,hs,fs) fs
-#endif /* !HIGHSPEED */
+#endif /* !CONFIG_USB_GADGET_DUALSPEED */
+static char manufacturer [40];
static char serial [40];
/* static strings, in iso 8859/1 */
static struct usb_string strings [] = {
- { STRING_MANUFACTURER, UTS_SYSNAME " " UTS_RELEASE " with " CHIP, },
+ { STRING_MANUFACTURER, manufacturer, },
{ STRING_PRODUCT, longname, },
{ STRING_SERIAL, serial, },
{ STRING_LOOPBACK, loopback, },
@@ -507,60 +502,42 @@
* device?)
*/
static int
-config_buf (enum usb_device_speed speed,
+config_buf (struct usb_gadget *gadget,
u8 *buf, u8 type, unsigned index)
{
- int is_source_sink;
- const unsigned config_len = USB_DT_CONFIG_SIZE
- + USB_DT_INTERFACE_SIZE
- + 2 * USB_DT_ENDPOINT_SIZE;
-#ifdef HIGHSPEED
- int hs;
+ int is_source_sink;
+ int len;
+ const struct usb_descriptor_header **function;
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+ int hs = (gadget->speed == USB_SPEED_HIGH);
#endif
+
/* two configurations will always be index 0 and index 1 */
if (index > 1)
return -EINVAL;
- if (config_len > USB_BUFSIZ)
- return -EDOM;
is_source_sink = loopdefault ? (index == 1) : (index == 0);
- /* config (or other speed config) */
- if (is_source_sink)
- memcpy (buf, &source_sink_config, USB_DT_CONFIG_SIZE);
- else
- memcpy (buf, &loopback_config, USB_DT_CONFIG_SIZE);
- buf [1] = type;
- ((struct usb_config_descriptor *) buf)->wTotalLength
- = __constant_cpu_to_le16 (config_len);
- buf += USB_DT_CONFIG_SIZE;
-
- /* one interface */
- if (is_source_sink)
- memcpy (buf, &source_sink_intf, USB_DT_INTERFACE_SIZE);
- else
- memcpy (buf, &loopback_intf, USB_DT_INTERFACE_SIZE);
- buf += USB_DT_INTERFACE_SIZE;
-
- /* the endpoints in that interface (at that speed) */
-#ifdef HIGHSPEED
- hs = (speed == USB_SPEED_HIGH);
+#ifdef CONFIG_USB_GADGET_DUALSPEED
if (type == USB_DT_OTHER_SPEED_CONFIG)
hs = !hs;
- if (hs) {
- memcpy (buf, &hs_source_desc, USB_DT_ENDPOINT_SIZE);
- buf += USB_DT_ENDPOINT_SIZE;
- memcpy (buf, &hs_sink_desc, USB_DT_ENDPOINT_SIZE);
- buf += USB_DT_ENDPOINT_SIZE;
- } else
+ if (hs)
+ function = is_source_sink
+ ? hs_source_sink_function
+ : hs_loopback_function;
+ else
#endif
- {
- memcpy (buf, &fs_source_desc, USB_DT_ENDPOINT_SIZE);
- buf += USB_DT_ENDPOINT_SIZE;
- memcpy (buf, &fs_sink_desc, USB_DT_ENDPOINT_SIZE);
- buf += USB_DT_ENDPOINT_SIZE;
- }
-
- return config_len;
+ function = is_source_sink
+ ? fs_source_sink_function
+ : fs_loopback_function;
+
+ len = usb_gadget_config_buf (is_source_sink
+ ? &source_sink_config
+ : &loopback_config,
+ buf, USB_BUFSIZ, function);
+ if (len < 0)
+ return len;
+ ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
+ return len;
}
/*-------------------------------------------------------------------------*/
@@ -1024,17 +1001,21 @@
value = min (ctrl->wLength, (u16) sizeof device_desc);
memcpy (req->buf, &device_desc, value);
break;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
case USB_DT_DEVICE_QUALIFIER:
+ if (!gadget->is_dualspeed)
+ break;
value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
memcpy (req->buf, &dev_qualifier, value);
break;
case USB_DT_OTHER_SPEED_CONFIG:
+ if (!gadget->is_dualspeed)
+ break;
// FALLTHROUGH
-#endif /* HIGHSPEED */
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
case USB_DT_CONFIG:
- value = config_buf (gadget->speed, req->buf,
+ value = config_buf (gadget, req->buf,
ctrl->wValue >> 8,
ctrl->wValue & 0xff);
if (value >= 0)
@@ -1217,14 +1198,26 @@
dev->req->complete = zero_setup_complete;
device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
-#ifdef HIGHSPEED
+
+#ifdef CONFIG_USB_GADGET_DUALSPEED
/* assume ep0 uses the same value for both speeds ... */
dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
+
+ /* and that all endpoints are dual-speed */
+ hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
+ hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
#endif
gadget->ep0->driver_data = dev;
INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);
+ INFO (dev, "using %s, OUT %s IN %s\n", gadget->name,
+ EP_OUT_NAME, EP_IN_NAME);
+
+ snprintf (manufacturer, sizeof manufacturer,
+ UTS_SYSNAME " " UTS_RELEASE " with %s",
+ gadget->name);
+
return 0;
enomem:
@@ -1235,7 +1228,7 @@
/*-------------------------------------------------------------------------*/
static struct usb_gadget_driver zero_driver = {
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
.speed = USB_SPEED_HIGH,
#else
.speed = USB_SPEED_FULL,
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)