unsigned zlp:1;
unsigned cdc:1;
unsigned rndis:1;
+ unsigned suspended:1;
u16 cdc_filter;
unsigned long todo;
#define WORK_RX_MEMORY 0
static void rndis_response_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 response complete --> %d, %d/%d\n",
req->status, req->actual, req->length);
/* done sending after CDC_GET_ENCAPSULATED_RESPONSE */
- rndis_free_response (dev->rndis_config, req->buf);
}
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 CDC_SEND_ENCAPSULATED_COMMAND */
spin_lock(&dev->lock);
- if (rndis_msg_parser (dev->rndis_config, (u8 *) req->buf))
- ERROR(dev, "%s: rndis parse error\n", __FUNCTION__ );
+ status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf);
+ if (status < 0)
+ ERROR(dev, "%s: rndis parse error %d\n", __FUNCTION__, status);
spin_unlock(&dev->lock);
}
if (buf) {
memcpy (req->buf, buf, value);
req->complete = rndis_response_complete;
+ rndis_free_response(dev->rndis_config, buf);
}
/* else stalls ... spec says to avoid that */
}
return &((struct eth_dev *) net->priv)->stats;
}
-static int eth_ethtool_ioctl (struct net_device *net, void *useraddr)
+static int eth_ethtool_ioctl (struct net_device *net, void __user *useraddr)
{
struct eth_dev *dev = (struct eth_dev *) net->priv;
u32 cmd;
- if (get_user (cmd, (u32 *)useraddr))
+ if (get_user (cmd, (u32 __user *)useraddr))
return -EFAULT;
switch (cmd) {
{
switch (cmd) {
case SIOCETHTOOL:
- return eth_ethtool_ioctl (net, (void *)rq->ifr_data);
+ return eth_ethtool_ioctl(net, rq->ifr_data);
default:
return -EOPNOTSUPP;
}
}
}
+static void rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req)
+{
+ if (req->status || req->actual != req->length)
+ DEBUG (dev, "rndis control ack complete --> %d, %d/%d\n",
+ req->status, req->actual, req->length);
+
+ usb_ep_free_buffer(ep, req->buf, req->dma, 8);
+ usb_ep_free_request(ep, req);
+}
+
static int rndis_control_ack (struct net_device *net)
{
struct eth_dev *dev = (struct eth_dev *) net->priv;
* CDC_NOTIFY_RESPONSE_AVAILABLE should work too
*/
resp->length = 8;
- resp->complete = rndis_response_complete;
+ resp->complete = rndis_control_ack_complete;
*((u32 *) resp->buf) = __constant_cpu_to_le32 (1);
*((u32 *) 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_response_complete (dev->status_ep, resp);
+ rndis_control_ack_complete (dev->status_ep, resp);
}
return 0;
UTS_SYSNAME " " UTS_RELEASE "/%s",
gadget->name);
- /* CDC subset ... recognized by Linux since 2.4.10, but Windows
- * drivers aren't widely available.
- */
- if (!cdc) {
- device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
- device_desc.idVendor =
- __constant_cpu_to_le16(SIMPLE_VENDOR_NUM);
- device_desc.idProduct =
- __constant_cpu_to_le16(SIMPLE_PRODUCT_NUM);
- }
-
/* If there's an RNDIS configuration, that's what Windows wants to
* be using ... so use these product IDs here and in the "linux.inf"
* needed to install MSFT drivers. Current Linux kernels will use
__constant_cpu_to_le16(RNDIS_PRODUCT_NUM);
snprintf (product_desc, sizeof product_desc,
"RNDIS/%s", driver_desc);
+
+ /* CDC subset ... recognized by Linux since 2.4.10, but Windows
+ * drivers aren't widely available.
+ */
+ } else if (!cdc) {
+ device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
+ device_desc.idVendor =
+ __constant_cpu_to_le16(SIMPLE_VENDOR_NUM);
+ device_desc.idProduct =
+ __constant_cpu_to_le16(SIMPLE_PRODUCT_NUM);
}
/* support optional vendor/distro customization */
/*-------------------------------------------------------------------------*/
+static void
+eth_suspend (struct usb_gadget *gadget)
+{
+ struct eth_dev *dev = get_gadget_data (gadget);
+
+ DEBUG (dev, "suspend\n");
+ dev->suspended = 1;
+}
+
+static void
+eth_resume (struct usb_gadget *gadget)
+{
+ struct eth_dev *dev = get_gadget_data (gadget);
+
+ DEBUG (dev, "resume\n");
+ dev->suspended = 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
static struct usb_gadget_driver eth_driver = {
#ifdef CONFIG_USB_GADGET_DUALSPEED
.speed = USB_SPEED_HIGH,
.setup = eth_setup,
.disconnect = eth_disconnect,
+ .suspend = eth_suspend,
+ .resume = eth_resume,
+
.driver = {
.name = (char *) shortname,
// .shutdown = ...