[linux-usb-devel] [PATCH 1/6] USB gadget driver

2007-05-19 Thread Ragner Magalhaes
From: Ragner Magalhaes [EMAIL PROTECTED]

Implements support for a gadget function with composite support
to work as a single function.

Signed-off-by: Ragner Magalhaes [EMAIL PROTECTED]
---

 drivers/usb/gadget/gadget.c |  283 +++
 1 files changed, 283 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/gadget/gadget.c b/drivers/usb/gadget/gadget.c
new file mode 100644
index 000..9a4a0e0
--- /dev/null
+++ b/drivers/usb/gadget/gadget.c
@@ -0,0 +1,283 @@
+/*
+ * gadget.c -- USB gadget driver.
+ *
+ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
+ * Developed for INdT by Ragner Magalhaes
+ * Ragner Magalhaes [EMAIL PROTECTED]
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License (GPL) version 2, as published by the Free Software Foundation.
+ *
+ * Implements support for one gadget device with a single function.
+ */
+
+#if 0
+#define DEBUG 1
+#define VERBOSE 1
+#endif
+
+#include linux/module.h
+#include linux/kernel.h
+#include linux/delay.h
+#include linux/ioport.h
+#include linux/sched.h
+#include linux/slab.h
+#include linux/smp_lock.h
+#include linux/errno.h
+#include linux/init.h
+#include linux/timer.h
+#include linux/list.h
+#include linux/interrupt.h
+#include linux/utsname.h
+#include linux/device.h
+#include linux/moduleparam.h
+
+#include asm/byteorder.h
+#include asm/system.h
+#include asm/unaligned.h
+
+#include linux/usb/ch9.h
+#include linux/usb/cdc.h
+#include linux/usb_gadget.h
+#include linux/usb/composite.h
+
+#include gadget_chips.h
+
+/*-*/
+
+#define xprintk(d,level,fmt,args...) \
+   dev_printk(level , (d)-gadget-dev , fmt , ## args)
+
+#ifdef DEBUG
+#define DBG(dev,fmt,args...) \
+   xprintk(dev , KERN_DEBUG , fmt , ## args)
+#else
+#define DBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE
+#define VDBG   DBG
+#else
+#define VDBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* VERBOSE */
+
+#define ERROR(dev,fmt,args...) \
+   xprintk(dev , KERN_ERR , fmt , ## args)
+#define WARN(dev,fmt,args...) \
+   xprintk(dev , KERN_WARNING , fmt , ## args)
+#define INFO(dev,fmt,args...) \
+   xprintk(dev , KERN_INFO , fmt , ## args)
+
+/*-*/
+
+/* big enough to hold our biggest descriptor */
+#define USB_BUFSIZ 256
+
+
+struct usb_function*func;
+
+/*-*/
+
+/* An impossibly large value as file_storage */
+#define DELAYED_STATUS (USB_BUFSIZ + 999)
+
+void usb_func_ep_reset (struct usb_gadget *g, struct usb_function *f)
+{
+   struct usb_ep   *ep;
+
+   list_for_each_entry (ep, g-ep_list, ep_list) {
+   if (ep-driver_data == f-driver_data) {
+   usb_ep_disable (ep);
+   ep-driver_data = NULL;
+   }
+   }
+}
+
+static void
+free_ep_req(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req-buf)
+   kfree (req-buf);
+   usb_ep_free_request(ep, req);
+}
+
+/*-*/
+
+static int
+gadget_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+{
+   struct usb_gadget_dev   *dev = get_gadget_data(gadget);
+   struct usb_request  *req = dev-req;
+   int value = -EOPNOTSUPP;
+   u16 w_index = le16_to_cpu(ctrl-wIndex);
+   u16 w_value = le16_to_cpu(ctrl-wValue);
+   u16 w_length = le16_to_cpu(ctrl-wLength);
+
+   req-zero = 0;
+   req-length = 0;
+   value = dev-func-setup (gadget, ctrl);
+
+   /* respond with data transfer before status phase? */
+   if (value = 0  value != DELAYED_STATUS) {
+   value = min((u16)value, w_length);
+   req-length = value;
+   req-zero = value  w_length;
+
+   value = usb_ep_queue(gadget-ep0, req, GFP_ATOMIC);
+   if (value != 0  value != -ESHUTDOWN) {
+   WARN(dev, error in submission: %s -- %d\n,
+   (ctrl-bRequestType  USB_DIR_IN ?
+ep0-in : ep0-out), value);
+   req-status = 0;
+   }
+   } else {
+   DBG(dev, setup req%02x.%02x v%04x i%04x l%d -- %d\n,
+   ctrl-bRequestType, ctrl-bRequest,
+   w_value, w_index, w_length, value);
+   /* to eliminate compile warnings */
+   w_index = w_value = 0;
+   }
+
+   /* device either stalls (value  0) or reports success */
+   return value;
+}
+
+static void
+gadget_disconnect(struct usb_gadget 

[linux-usb-devel] [PATCH 1/6] USB gadget driver

2007-05-04 Thread Ragner Magalhaes
Implements support for a gadget function with composite support
to work as a single function.

Signed-off-by: Ragner Magalhaes [EMAIL PROTECTED]

:00 100644 000... e6551d9... A  drivers/usb/gadget/gadget.c

diff --git a/drivers/usb/gadget/gadget.c b/drivers/usb/gadget/gadget.c
new file mode 100644
index 000..e6551d9
--- /dev/null
+++ b/drivers/usb/gadget/gadget.c
@@ -0,0 +1,293 @@
+/*
+ * gadget.c -- USB gadget driver.
+ *
+ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
+ * Developed for INdT by Ragner Magalhaes
+ * Ragner Magalhaes [EMAIL PROTECTED]
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License (GPL) version 2, as published by the Free Software Foundation.
+ *
+ * Implements support for one gadget device with a single function.
+ */
+
+#if 0
+#define DEBUG 1
+#define VERBOSE 1
+#endif
+
+#include linux/module.h
+#include linux/kernel.h
+#include linux/delay.h
+#include linux/ioport.h
+#include linux/sched.h
+#include linux/slab.h
+#include linux/smp_lock.h
+#include linux/errno.h
+#include linux/init.h
+#include linux/timer.h
+#include linux/list.h
+#include linux/interrupt.h
+#include linux/utsname.h
+#include linux/device.h
+#include linux/moduleparam.h
+
+#include asm/byteorder.h
+#include asm/system.h
+#include asm/unaligned.h
+
+#include linux/usb/ch9.h
+#include linux/usb/cdc.h
+#include linux/usb_gadget.h
+#include linux/usb/composite.h
+
+#include gadget_chips.h
+
+/*-*/
+
+#define xprintk(d,level,fmt,args...) \
+   dev_printk(level , (d)-gadget-dev , fmt , ## args)
+
+#ifdef DEBUG
+#define DBG(dev,fmt,args...) \
+   xprintk(dev , KERN_DEBUG , fmt , ## args)
+#else
+#define DBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE
+#define VDBG   DBG
+#else
+#define VDBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* VERBOSE */
+
+#define ERROR(dev,fmt,args...) \
+   xprintk(dev , KERN_ERR , fmt , ## args)
+#define WARN(dev,fmt,args...) \
+   xprintk(dev , KERN_WARNING , fmt , ## args)
+#define INFO(dev,fmt,args...) \
+   xprintk(dev , KERN_INFO , fmt , ## args)
+
+/*-*/
+
+/* big enough to hold our biggest descriptor */
+#define USB_BUFSIZ 256
+
+
+struct usb_function*func;
+
+/*-*/
+
+/* An impossibly large value as file_storage */
+#define DELAYED_STATUS (USB_BUFSIZ + 999)
+
+void usb_func_ep_reset (struct usb_gadget *g, struct usb_function *f)
+{
+   struct usb_ep   *ep;
+
+   list_for_each_entry (ep, g-ep_list, ep_list) {
+   if (ep-driver_data == f-driver_data) {
+   usb_ep_disable (ep);
+   ep-driver_data = NULL;
+   }
+   }
+}
+
+static void
+free_ep_req(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req-buf)
+   kfree (req-buf);
+   usb_ep_free_request(ep, req);
+}
+
+/*-*/
+
+static void
+gadget_setup_complete(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req-status || req-actual != req-length)
+   DBG((struct usb_gadget_dev *)ep-driver_data,
+   setup complete -- %d, %u/%u\n,
+   req-status, req-actual, req-length);
+}
+
+static int
+gadget_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+{
+   struct usb_gadget_dev   *dev = get_gadget_data(gadget);
+   struct usb_request  *req = dev-req;
+   int value = -EOPNOTSUPP;
+   u16 w_index = le16_to_cpu(ctrl-wIndex);
+   u16 w_value = le16_to_cpu(ctrl-wValue);
+   u16 w_length = le16_to_cpu(ctrl-wLength);
+
+   req-complete = gadget_setup_complete;
+   req-zero = 0;
+   spin_lock(dev-lock);
+   value = dev-func-setup (gadget, ctrl);
+   spin_unlock(dev-lock);
+
+   /* respond with data transfer before status phase? */
+   if (value = 0  value != DELAYED_STATUS) {
+   req-length = value;
+   req-zero = value  w_length;
+   value = usb_ep_queue(gadget-ep0, req, GFP_ATOMIC);
+   if (value  0) {
+   DBG(dev, ep_queue -- %d\n, value);
+   req-status = 0;
+   gadget_setup_complete(gadget-ep0, req);
+   }
+   } else {
+   DBG(dev, setup req%02x.%02x v%04x i%04x l%d -- %d\n,
+   ctrl-bRequestType, ctrl-bRequest,
+   w_value, w_index, w_length, value);
+   /* to eliminate compile warnings */
+   w_index = w_value = 0;
+   }
+

[linux-usb-devel] [PATCH 1/6] USB gadget driver

2007-05-04 Thread Ragner Magalhaes
Implements support for a gadget function with composite support
to work as a single function.

Signed-off-by: Ragner Magalhaes [EMAIL PROTECTED]

:00 100644 000... e6551d9... A  drivers/usb/gadget/gadget.c

diff --git a/drivers/usb/gadget/gadget.c b/drivers/usb/gadget/gadget.c
new file mode 100644
index 000..e6551d9
--- /dev/null
+++ b/drivers/usb/gadget/gadget.c
@@ -0,0 +1,293 @@
+/*
+ * gadget.c -- USB gadget driver.
+ *
+ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
+ * Developed for INdT by Ragner Magalhaes
+ * Ragner Magalhaes [EMAIL PROTECTED]
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License (GPL) version 2, as published by the Free Software Foundation.
+ *
+ * Implements support for one gadget device with a single function.
+ */
+
+#if 0
+#define DEBUG 1
+#define VERBOSE 1
+#endif
+
+#include linux/module.h
+#include linux/kernel.h
+#include linux/delay.h
+#include linux/ioport.h
+#include linux/sched.h
+#include linux/slab.h
+#include linux/smp_lock.h
+#include linux/errno.h
+#include linux/init.h
+#include linux/timer.h
+#include linux/list.h
+#include linux/interrupt.h
+#include linux/utsname.h
+#include linux/device.h
+#include linux/moduleparam.h
+
+#include asm/byteorder.h
+#include asm/system.h
+#include asm/unaligned.h
+
+#include linux/usb/ch9.h
+#include linux/usb/cdc.h
+#include linux/usb_gadget.h
+#include linux/usb/composite.h
+
+#include gadget_chips.h
+
+/*-*/
+
+#define xprintk(d,level,fmt,args...) \
+   dev_printk(level , (d)-gadget-dev , fmt , ## args)
+
+#ifdef DEBUG
+#define DBG(dev,fmt,args...) \
+   xprintk(dev , KERN_DEBUG , fmt , ## args)
+#else
+#define DBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE
+#define VDBG   DBG
+#else
+#define VDBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* VERBOSE */
+
+#define ERROR(dev,fmt,args...) \
+   xprintk(dev , KERN_ERR , fmt , ## args)
+#define WARN(dev,fmt,args...) \
+   xprintk(dev , KERN_WARNING , fmt , ## args)
+#define INFO(dev,fmt,args...) \
+   xprintk(dev , KERN_INFO , fmt , ## args)
+
+/*-*/
+
+/* big enough to hold our biggest descriptor */
+#define USB_BUFSIZ 256
+
+
+struct usb_function*func;
+
+/*-*/
+
+/* An impossibly large value as file_storage */
+#define DELAYED_STATUS (USB_BUFSIZ + 999)
+
+void usb_func_ep_reset (struct usb_gadget *g, struct usb_function *f)
+{
+   struct usb_ep   *ep;
+
+   list_for_each_entry (ep, g-ep_list, ep_list) {
+   if (ep-driver_data == f-driver_data) {
+   usb_ep_disable (ep);
+   ep-driver_data = NULL;
+   }
+   }
+}
+
+static void
+free_ep_req(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req-buf)
+   kfree (req-buf);
+   usb_ep_free_request(ep, req);
+}
+
+/*-*/
+
+static void
+gadget_setup_complete(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req-status || req-actual != req-length)
+   DBG((struct usb_gadget_dev *)ep-driver_data,
+   setup complete -- %d, %u/%u\n,
+   req-status, req-actual, req-length);
+}
+
+static int
+gadget_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+{
+   struct usb_gadget_dev   *dev = get_gadget_data(gadget);
+   struct usb_request  *req = dev-req;
+   int value = -EOPNOTSUPP;
+   u16 w_index = le16_to_cpu(ctrl-wIndex);
+   u16 w_value = le16_to_cpu(ctrl-wValue);
+   u16 w_length = le16_to_cpu(ctrl-wLength);
+
+   req-complete = gadget_setup_complete;
+   req-zero = 0;
+   spin_lock(dev-lock);
+   value = dev-func-setup (gadget, ctrl);
+   spin_unlock(dev-lock);
+
+   /* respond with data transfer before status phase? */
+   if (value = 0  value != DELAYED_STATUS) {
+   req-length = value;
+   req-zero = value  w_length;
+   value = usb_ep_queue(gadget-ep0, req, GFP_ATOMIC);
+   if (value  0) {
+   DBG(dev, ep_queue -- %d\n, value);
+   req-status = 0;
+   gadget_setup_complete(gadget-ep0, req);
+   }
+   } else {
+   DBG(dev, setup req%02x.%02x v%04x i%04x l%d -- %d\n,
+   ctrl-bRequestType, ctrl-bRequest,
+   w_value, w_index, w_length, value);
+   /* to eliminate compile warnings */
+   w_index = w_value = 0;
+   }
+

[linux-usb-devel] [PATCH 1/6] USB gadget driver

2007-05-04 Thread Ragner Magalhaes
Implements support for a gadget function with composite support
to work as a single function.

Signed-off-by: Ragner Magalhaes [EMAIL PROTECTED]

:00 100644 000... e6551d9... A  drivers/usb/gadget/gadget.c

diff --git a/drivers/usb/gadget/gadget.c b/drivers/usb/gadget/gadget.c
new file mode 100644
index 000..e6551d9
--- /dev/null
+++ b/drivers/usb/gadget/gadget.c
@@ -0,0 +1,293 @@
+/*
+ * gadget.c -- USB gadget driver.
+ *
+ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
+ * Developed for INdT by Ragner Magalhaes
+ * Ragner Magalhaes [EMAIL PROTECTED]
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License (GPL) version 2, as published by the Free Software Foundation.
+ *
+ * Implements support for one gadget device with a single function.
+ */
+
+#if 0
+#define DEBUG 1
+#define VERBOSE 1
+#endif
+
+#include linux/module.h
+#include linux/kernel.h
+#include linux/delay.h
+#include linux/ioport.h
+#include linux/sched.h
+#include linux/slab.h
+#include linux/smp_lock.h
+#include linux/errno.h
+#include linux/init.h
+#include linux/timer.h
+#include linux/list.h
+#include linux/interrupt.h
+#include linux/utsname.h
+#include linux/device.h
+#include linux/moduleparam.h
+
+#include asm/byteorder.h
+#include asm/system.h
+#include asm/unaligned.h
+
+#include linux/usb/ch9.h
+#include linux/usb/cdc.h
+#include linux/usb_gadget.h
+#include linux/usb/composite.h
+
+#include gadget_chips.h
+
+/*-*/
+
+#define xprintk(d,level,fmt,args...) \
+   dev_printk(level , (d)-gadget-dev , fmt , ## args)
+
+#ifdef DEBUG
+#define DBG(dev,fmt,args...) \
+   xprintk(dev , KERN_DEBUG , fmt , ## args)
+#else
+#define DBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE
+#define VDBG   DBG
+#else
+#define VDBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* VERBOSE */
+
+#define ERROR(dev,fmt,args...) \
+   xprintk(dev , KERN_ERR , fmt , ## args)
+#define WARN(dev,fmt,args...) \
+   xprintk(dev , KERN_WARNING , fmt , ## args)
+#define INFO(dev,fmt,args...) \
+   xprintk(dev , KERN_INFO , fmt , ## args)
+
+/*-*/
+
+/* big enough to hold our biggest descriptor */
+#define USB_BUFSIZ 256
+
+
+struct usb_function*func;
+
+/*-*/
+
+/* An impossibly large value as file_storage */
+#define DELAYED_STATUS (USB_BUFSIZ + 999)
+
+void usb_func_ep_reset (struct usb_gadget *g, struct usb_function *f)
+{
+   struct usb_ep   *ep;
+
+   list_for_each_entry (ep, g-ep_list, ep_list) {
+   if (ep-driver_data == f-driver_data) {
+   usb_ep_disable (ep);
+   ep-driver_data = NULL;
+   }
+   }
+}
+
+static void
+free_ep_req(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req-buf)
+   kfree (req-buf);
+   usb_ep_free_request(ep, req);
+}
+
+/*-*/
+
+static void
+gadget_setup_complete(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req-status || req-actual != req-length)
+   DBG((struct usb_gadget_dev *)ep-driver_data,
+   setup complete -- %d, %u/%u\n,
+   req-status, req-actual, req-length);
+}
+
+static int
+gadget_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+{
+   struct usb_gadget_dev   *dev = get_gadget_data(gadget);
+   struct usb_request  *req = dev-req;
+   int value = -EOPNOTSUPP;
+   u16 w_index = le16_to_cpu(ctrl-wIndex);
+   u16 w_value = le16_to_cpu(ctrl-wValue);
+   u16 w_length = le16_to_cpu(ctrl-wLength);
+
+   req-complete = gadget_setup_complete;
+   req-zero = 0;
+   spin_lock(dev-lock);
+   value = dev-func-setup (gadget, ctrl);
+   spin_unlock(dev-lock);
+
+   /* respond with data transfer before status phase? */
+   if (value = 0  value != DELAYED_STATUS) {
+   req-length = value;
+   req-zero = value  w_length;
+   value = usb_ep_queue(gadget-ep0, req, GFP_ATOMIC);
+   if (value  0) {
+   DBG(dev, ep_queue -- %d\n, value);
+   req-status = 0;
+   gadget_setup_complete(gadget-ep0, req);
+   }
+   } else {
+   DBG(dev, setup req%02x.%02x v%04x i%04x l%d -- %d\n,
+   ctrl-bRequestType, ctrl-bRequest,
+   w_value, w_index, w_length, value);
+   /* to eliminate compile warnings */
+   w_index = w_value = 0;
+   }
+

[linux-usb-devel] [PATCH 1/6] USB gadget driver

2007-05-04 Thread Ragner Magalhaes
Implements support for a gadget function with composite support
to work as a single function.

Signed-off-by: Ragner Magalhaes [EMAIL PROTECTED]

:00 100644 000... e6551d9... A  drivers/usb/gadget/gadget.c

diff --git a/drivers/usb/gadget/gadget.c b/drivers/usb/gadget/gadget.c
new file mode 100644
index 000..e6551d9
--- /dev/null
+++ b/drivers/usb/gadget/gadget.c
@@ -0,0 +1,293 @@
+/*
+ * gadget.c -- USB gadget driver.
+ *
+ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
+ * Developed for INdT by Ragner Magalhaes
+ * Ragner Magalhaes [EMAIL PROTECTED]
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License (GPL) version 2, as published by the Free Software Foundation.
+ *
+ * Implements support for one gadget device with a single function.
+ */
+
+#if 0
+#define DEBUG 1
+#define VERBOSE 1
+#endif
+
+#include linux/module.h
+#include linux/kernel.h
+#include linux/delay.h
+#include linux/ioport.h
+#include linux/sched.h
+#include linux/slab.h
+#include linux/smp_lock.h
+#include linux/errno.h
+#include linux/init.h
+#include linux/timer.h
+#include linux/list.h
+#include linux/interrupt.h
+#include linux/utsname.h
+#include linux/device.h
+#include linux/moduleparam.h
+
+#include asm/byteorder.h
+#include asm/system.h
+#include asm/unaligned.h
+
+#include linux/usb/ch9.h
+#include linux/usb/cdc.h
+#include linux/usb_gadget.h
+#include linux/usb/composite.h
+
+#include gadget_chips.h
+
+/*-*/
+
+#define xprintk(d,level,fmt,args...) \
+   dev_printk(level , (d)-gadget-dev , fmt , ## args)
+
+#ifdef DEBUG
+#define DBG(dev,fmt,args...) \
+   xprintk(dev , KERN_DEBUG , fmt , ## args)
+#else
+#define DBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE
+#define VDBG   DBG
+#else
+#define VDBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* VERBOSE */
+
+#define ERROR(dev,fmt,args...) \
+   xprintk(dev , KERN_ERR , fmt , ## args)
+#define WARN(dev,fmt,args...) \
+   xprintk(dev , KERN_WARNING , fmt , ## args)
+#define INFO(dev,fmt,args...) \
+   xprintk(dev , KERN_INFO , fmt , ## args)
+
+/*-*/
+
+/* big enough to hold our biggest descriptor */
+#define USB_BUFSIZ 256
+
+
+struct usb_function*func;
+
+/*-*/
+
+/* An impossibly large value as file_storage */
+#define DELAYED_STATUS (USB_BUFSIZ + 999)
+
+void usb_func_ep_reset (struct usb_gadget *g, struct usb_function *f)
+{
+   struct usb_ep   *ep;
+
+   list_for_each_entry (ep, g-ep_list, ep_list) {
+   if (ep-driver_data == f-driver_data) {
+   usb_ep_disable (ep);
+   ep-driver_data = NULL;
+   }
+   }
+}
+
+static void
+free_ep_req(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req-buf)
+   kfree (req-buf);
+   usb_ep_free_request(ep, req);
+}
+
+/*-*/
+
+static void
+gadget_setup_complete(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req-status || req-actual != req-length)
+   DBG((struct usb_gadget_dev *)ep-driver_data,
+   setup complete -- %d, %u/%u\n,
+   req-status, req-actual, req-length);
+}
+
+static int
+gadget_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+{
+   struct usb_gadget_dev   *dev = get_gadget_data(gadget);
+   struct usb_request  *req = dev-req;
+   int value = -EOPNOTSUPP;
+   u16 w_index = le16_to_cpu(ctrl-wIndex);
+   u16 w_value = le16_to_cpu(ctrl-wValue);
+   u16 w_length = le16_to_cpu(ctrl-wLength);
+
+   req-complete = gadget_setup_complete;
+   req-zero = 0;
+   spin_lock(dev-lock);
+   value = dev-func-setup (gadget, ctrl);
+   spin_unlock(dev-lock);
+
+   /* respond with data transfer before status phase? */
+   if (value = 0  value != DELAYED_STATUS) {
+   req-length = value;
+   req-zero = value  w_length;
+   value = usb_ep_queue(gadget-ep0, req, GFP_ATOMIC);
+   if (value  0) {
+   DBG(dev, ep_queue -- %d\n, value);
+   req-status = 0;
+   gadget_setup_complete(gadget-ep0, req);
+   }
+   } else {
+   DBG(dev, setup req%02x.%02x v%04x i%04x l%d -- %d\n,
+   ctrl-bRequestType, ctrl-bRequest,
+   w_value, w_index, w_length, value);
+   /* to eliminate compile warnings */
+   w_index = w_value = 0;
+   }
+

[linux-usb-devel] [PATCH 1/6] USB gadget driver

2007-05-04 Thread Ragner Magalhaes
Implements support for a gadget function with composite support
to work as a single function.

Signed-off-by: Ragner Magalhaes [EMAIL PROTECTED]

:00 100644 000... e6551d9... A  drivers/usb/gadget/gadget.c

diff --git a/drivers/usb/gadget/gadget.c b/drivers/usb/gadget/gadget.c
new file mode 100644
index 000..e6551d9
--- /dev/null
+++ b/drivers/usb/gadget/gadget.c
@@ -0,0 +1,293 @@
+/*
+ * gadget.c -- USB gadget driver.
+ *
+ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
+ * Developed for INdT by Ragner Magalhaes
+ * Ragner Magalhaes [EMAIL PROTECTED]
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License (GPL) version 2, as published by the Free Software Foundation.
+ *
+ * Implements support for one gadget device with a single function.
+ */
+
+#if 0
+#define DEBUG 1
+#define VERBOSE 1
+#endif
+
+#include linux/module.h
+#include linux/kernel.h
+#include linux/delay.h
+#include linux/ioport.h
+#include linux/sched.h
+#include linux/slab.h
+#include linux/smp_lock.h
+#include linux/errno.h
+#include linux/init.h
+#include linux/timer.h
+#include linux/list.h
+#include linux/interrupt.h
+#include linux/utsname.h
+#include linux/device.h
+#include linux/moduleparam.h
+
+#include asm/byteorder.h
+#include asm/system.h
+#include asm/unaligned.h
+
+#include linux/usb/ch9.h
+#include linux/usb/cdc.h
+#include linux/usb_gadget.h
+#include linux/usb/composite.h
+
+#include gadget_chips.h
+
+/*-*/
+
+#define xprintk(d,level,fmt,args...) \
+   dev_printk(level , (d)-gadget-dev , fmt , ## args)
+
+#ifdef DEBUG
+#define DBG(dev,fmt,args...) \
+   xprintk(dev , KERN_DEBUG , fmt , ## args)
+#else
+#define DBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE
+#define VDBG   DBG
+#else
+#define VDBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* VERBOSE */
+
+#define ERROR(dev,fmt,args...) \
+   xprintk(dev , KERN_ERR , fmt , ## args)
+#define WARN(dev,fmt,args...) \
+   xprintk(dev , KERN_WARNING , fmt , ## args)
+#define INFO(dev,fmt,args...) \
+   xprintk(dev , KERN_INFO , fmt , ## args)
+
+/*-*/
+
+/* big enough to hold our biggest descriptor */
+#define USB_BUFSIZ 256
+
+
+struct usb_function*func;
+
+/*-*/
+
+/* An impossibly large value as file_storage */
+#define DELAYED_STATUS (USB_BUFSIZ + 999)
+
+void usb_func_ep_reset (struct usb_gadget *g, struct usb_function *f)
+{
+   struct usb_ep   *ep;
+
+   list_for_each_entry (ep, g-ep_list, ep_list) {
+   if (ep-driver_data == f-driver_data) {
+   usb_ep_disable (ep);
+   ep-driver_data = NULL;
+   }
+   }
+}
+
+static void
+free_ep_req(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req-buf)
+   kfree (req-buf);
+   usb_ep_free_request(ep, req);
+}
+
+/*-*/
+
+static void
+gadget_setup_complete(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req-status || req-actual != req-length)
+   DBG((struct usb_gadget_dev *)ep-driver_data,
+   setup complete -- %d, %u/%u\n,
+   req-status, req-actual, req-length);
+}
+
+static int
+gadget_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+{
+   struct usb_gadget_dev   *dev = get_gadget_data(gadget);
+   struct usb_request  *req = dev-req;
+   int value = -EOPNOTSUPP;
+   u16 w_index = le16_to_cpu(ctrl-wIndex);
+   u16 w_value = le16_to_cpu(ctrl-wValue);
+   u16 w_length = le16_to_cpu(ctrl-wLength);
+
+   req-complete = gadget_setup_complete;
+   req-zero = 0;
+   spin_lock(dev-lock);
+   value = dev-func-setup (gadget, ctrl);
+   spin_unlock(dev-lock);
+
+   /* respond with data transfer before status phase? */
+   if (value = 0  value != DELAYED_STATUS) {
+   req-length = value;
+   req-zero = value  w_length;
+   value = usb_ep_queue(gadget-ep0, req, GFP_ATOMIC);
+   if (value  0) {
+   DBG(dev, ep_queue -- %d\n, value);
+   req-status = 0;
+   gadget_setup_complete(gadget-ep0, req);
+   }
+   } else {
+   DBG(dev, setup req%02x.%02x v%04x i%04x l%d -- %d\n,
+   ctrl-bRequestType, ctrl-bRequest,
+   w_value, w_index, w_length, value);
+   /* to eliminate compile warnings */
+   w_index = w_value = 0;
+   }
+

[linux-usb-devel] [PATCH 1/6] USB gadget driver

2007-05-04 Thread Ragner Magalhaes
Implements support for a gadget function with composite support
to work as a single function.

Signed-off-by: Ragner Magalhaes [EMAIL PROTECTED]

:00 100644 000... e6551d9... A  drivers/usb/gadget/gadget.c

diff --git a/drivers/usb/gadget/gadget.c b/drivers/usb/gadget/gadget.c
new file mode 100644
index 000..e6551d9
--- /dev/null
+++ b/drivers/usb/gadget/gadget.c
@@ -0,0 +1,293 @@
+/*
+ * gadget.c -- USB gadget driver.
+ *
+ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
+ * Developed for INdT by Ragner Magalhaes
+ * Ragner Magalhaes [EMAIL PROTECTED]
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License (GPL) version 2, as published by the Free Software Foundation.
+ *
+ * Implements support for one gadget device with a single function.
+ */
+
+#if 0
+#define DEBUG 1
+#define VERBOSE 1
+#endif
+
+#include linux/module.h
+#include linux/kernel.h
+#include linux/delay.h
+#include linux/ioport.h
+#include linux/sched.h
+#include linux/slab.h
+#include linux/smp_lock.h
+#include linux/errno.h
+#include linux/init.h
+#include linux/timer.h
+#include linux/list.h
+#include linux/interrupt.h
+#include linux/utsname.h
+#include linux/device.h
+#include linux/moduleparam.h
+
+#include asm/byteorder.h
+#include asm/system.h
+#include asm/unaligned.h
+
+#include linux/usb/ch9.h
+#include linux/usb/cdc.h
+#include linux/usb_gadget.h
+#include linux/usb/composite.h
+
+#include gadget_chips.h
+
+/*-*/
+
+#define xprintk(d,level,fmt,args...) \
+   dev_printk(level , (d)-gadget-dev , fmt , ## args)
+
+#ifdef DEBUG
+#define DBG(dev,fmt,args...) \
+   xprintk(dev , KERN_DEBUG , fmt , ## args)
+#else
+#define DBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE
+#define VDBG   DBG
+#else
+#define VDBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* VERBOSE */
+
+#define ERROR(dev,fmt,args...) \
+   xprintk(dev , KERN_ERR , fmt , ## args)
+#define WARN(dev,fmt,args...) \
+   xprintk(dev , KERN_WARNING , fmt , ## args)
+#define INFO(dev,fmt,args...) \
+   xprintk(dev , KERN_INFO , fmt , ## args)
+
+/*-*/
+
+/* big enough to hold our biggest descriptor */
+#define USB_BUFSIZ 256
+
+
+struct usb_function*func;
+
+/*-*/
+
+/* An impossibly large value as file_storage */
+#define DELAYED_STATUS (USB_BUFSIZ + 999)
+
+void usb_func_ep_reset (struct usb_gadget *g, struct usb_function *f)
+{
+   struct usb_ep   *ep;
+
+   list_for_each_entry (ep, g-ep_list, ep_list) {
+   if (ep-driver_data == f-driver_data) {
+   usb_ep_disable (ep);
+   ep-driver_data = NULL;
+   }
+   }
+}
+
+static void
+free_ep_req(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req-buf)
+   kfree (req-buf);
+   usb_ep_free_request(ep, req);
+}
+
+/*-*/
+
+static void
+gadget_setup_complete(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req-status || req-actual != req-length)
+   DBG((struct usb_gadget_dev *)ep-driver_data,
+   setup complete -- %d, %u/%u\n,
+   req-status, req-actual, req-length);
+}
+
+static int
+gadget_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+{
+   struct usb_gadget_dev   *dev = get_gadget_data(gadget);
+   struct usb_request  *req = dev-req;
+   int value = -EOPNOTSUPP;
+   u16 w_index = le16_to_cpu(ctrl-wIndex);
+   u16 w_value = le16_to_cpu(ctrl-wValue);
+   u16 w_length = le16_to_cpu(ctrl-wLength);
+
+   req-complete = gadget_setup_complete;
+   req-zero = 0;
+   spin_lock(dev-lock);
+   value = dev-func-setup (gadget, ctrl);
+   spin_unlock(dev-lock);
+
+   /* respond with data transfer before status phase? */
+   if (value = 0  value != DELAYED_STATUS) {
+   req-length = value;
+   req-zero = value  w_length;
+   value = usb_ep_queue(gadget-ep0, req, GFP_ATOMIC);
+   if (value  0) {
+   DBG(dev, ep_queue -- %d\n, value);
+   req-status = 0;
+   gadget_setup_complete(gadget-ep0, req);
+   }
+   } else {
+   DBG(dev, setup req%02x.%02x v%04x i%04x l%d -- %d\n,
+   ctrl-bRequestType, ctrl-bRequest,
+   w_value, w_index, w_length, value);
+   /* to eliminate compile warnings */
+   w_index = w_value = 0;
+   }
+

[linux-usb-devel] [PATCH 1/6] USB gadget driver

2007-05-04 Thread Ragner Magalhaes
Implements support for a gadget function with composite support
to work as a single function.

Signed-off-by: Ragner Magalhaes [EMAIL PROTECTED]

:00 100644 000... e6551d9... A  drivers/usb/gadget/gadget.c

diff --git a/drivers/usb/gadget/gadget.c b/drivers/usb/gadget/gadget.c
new file mode 100644
index 000..e6551d9
--- /dev/null
+++ b/drivers/usb/gadget/gadget.c
@@ -0,0 +1,293 @@
+/*
+ * gadget.c -- USB gadget driver.
+ *
+ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
+ * Developed for INdT by Ragner Magalhaes
+ * Ragner Magalhaes [EMAIL PROTECTED]
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License (GPL) version 2, as published by the Free Software Foundation.
+ *
+ * Implements support for one gadget device with a single function.
+ */
+
+#if 0
+#define DEBUG 1
+#define VERBOSE 1
+#endif
+
+#include linux/module.h
+#include linux/kernel.h
+#include linux/delay.h
+#include linux/ioport.h
+#include linux/sched.h
+#include linux/slab.h
+#include linux/smp_lock.h
+#include linux/errno.h
+#include linux/init.h
+#include linux/timer.h
+#include linux/list.h
+#include linux/interrupt.h
+#include linux/utsname.h
+#include linux/device.h
+#include linux/moduleparam.h
+
+#include asm/byteorder.h
+#include asm/system.h
+#include asm/unaligned.h
+
+#include linux/usb/ch9.h
+#include linux/usb/cdc.h
+#include linux/usb_gadget.h
+#include linux/usb/composite.h
+
+#include gadget_chips.h
+
+/*-*/
+
+#define xprintk(d,level,fmt,args...) \
+   dev_printk(level , (d)-gadget-dev , fmt , ## args)
+
+#ifdef DEBUG
+#define DBG(dev,fmt,args...) \
+   xprintk(dev , KERN_DEBUG , fmt , ## args)
+#else
+#define DBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE
+#define VDBG   DBG
+#else
+#define VDBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* VERBOSE */
+
+#define ERROR(dev,fmt,args...) \
+   xprintk(dev , KERN_ERR , fmt , ## args)
+#define WARN(dev,fmt,args...) \
+   xprintk(dev , KERN_WARNING , fmt , ## args)
+#define INFO(dev,fmt,args...) \
+   xprintk(dev , KERN_INFO , fmt , ## args)
+
+/*-*/
+
+/* big enough to hold our biggest descriptor */
+#define USB_BUFSIZ 256
+
+
+struct usb_function*func;
+
+/*-*/
+
+/* An impossibly large value as file_storage */
+#define DELAYED_STATUS (USB_BUFSIZ + 999)
+
+void usb_func_ep_reset (struct usb_gadget *g, struct usb_function *f)
+{
+   struct usb_ep   *ep;
+
+   list_for_each_entry (ep, g-ep_list, ep_list) {
+   if (ep-driver_data == f-driver_data) {
+   usb_ep_disable (ep);
+   ep-driver_data = NULL;
+   }
+   }
+}
+
+static void
+free_ep_req(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req-buf)
+   kfree (req-buf);
+   usb_ep_free_request(ep, req);
+}
+
+/*-*/
+
+static void
+gadget_setup_complete(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req-status || req-actual != req-length)
+   DBG((struct usb_gadget_dev *)ep-driver_data,
+   setup complete -- %d, %u/%u\n,
+   req-status, req-actual, req-length);
+}
+
+static int
+gadget_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+{
+   struct usb_gadget_dev   *dev = get_gadget_data(gadget);
+   struct usb_request  *req = dev-req;
+   int value = -EOPNOTSUPP;
+   u16 w_index = le16_to_cpu(ctrl-wIndex);
+   u16 w_value = le16_to_cpu(ctrl-wValue);
+   u16 w_length = le16_to_cpu(ctrl-wLength);
+
+   req-complete = gadget_setup_complete;
+   req-zero = 0;
+   spin_lock(dev-lock);
+   value = dev-func-setup (gadget, ctrl);
+   spin_unlock(dev-lock);
+
+   /* respond with data transfer before status phase? */
+   if (value = 0  value != DELAYED_STATUS) {
+   req-length = value;
+   req-zero = value  w_length;
+   value = usb_ep_queue(gadget-ep0, req, GFP_ATOMIC);
+   if (value  0) {
+   DBG(dev, ep_queue -- %d\n, value);
+   req-status = 0;
+   gadget_setup_complete(gadget-ep0, req);
+   }
+   } else {
+   DBG(dev, setup req%02x.%02x v%04x i%04x l%d -- %d\n,
+   ctrl-bRequestType, ctrl-bRequest,
+   w_value, w_index, w_length, value);
+   /* to eliminate compile warnings */
+   w_index = w_value = 0;
+   }
+

[linux-usb-devel] [PATCH 1/6] USB gadget driver

2007-05-04 Thread Ragner Magalhaes
Implements support for a gadget function with composite support
to work as a single function.

Signed-off-by: Ragner Magalhaes [EMAIL PROTECTED]

:00 100644 000... e6551d9... A  drivers/usb/gadget/gadget.c

diff --git a/drivers/usb/gadget/gadget.c b/drivers/usb/gadget/gadget.c
new file mode 100644
index 000..e6551d9
--- /dev/null
+++ b/drivers/usb/gadget/gadget.c
@@ -0,0 +1,293 @@
+/*
+ * gadget.c -- USB gadget driver.
+ *
+ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
+ * Developed for INdT by Ragner Magalhaes
+ * Ragner Magalhaes [EMAIL PROTECTED]
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License (GPL) version 2, as published by the Free Software Foundation.
+ *
+ * Implements support for one gadget device with a single function.
+ */
+
+#if 0
+#define DEBUG 1
+#define VERBOSE 1
+#endif
+
+#include linux/module.h
+#include linux/kernel.h
+#include linux/delay.h
+#include linux/ioport.h
+#include linux/sched.h
+#include linux/slab.h
+#include linux/smp_lock.h
+#include linux/errno.h
+#include linux/init.h
+#include linux/timer.h
+#include linux/list.h
+#include linux/interrupt.h
+#include linux/utsname.h
+#include linux/device.h
+#include linux/moduleparam.h
+
+#include asm/byteorder.h
+#include asm/system.h
+#include asm/unaligned.h
+
+#include linux/usb/ch9.h
+#include linux/usb/cdc.h
+#include linux/usb_gadget.h
+#include linux/usb/composite.h
+
+#include gadget_chips.h
+
+/*-*/
+
+#define xprintk(d,level,fmt,args...) \
+   dev_printk(level , (d)-gadget-dev , fmt , ## args)
+
+#ifdef DEBUG
+#define DBG(dev,fmt,args...) \
+   xprintk(dev , KERN_DEBUG , fmt , ## args)
+#else
+#define DBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE
+#define VDBG   DBG
+#else
+#define VDBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* VERBOSE */
+
+#define ERROR(dev,fmt,args...) \
+   xprintk(dev , KERN_ERR , fmt , ## args)
+#define WARN(dev,fmt,args...) \
+   xprintk(dev , KERN_WARNING , fmt , ## args)
+#define INFO(dev,fmt,args...) \
+   xprintk(dev , KERN_INFO , fmt , ## args)
+
+/*-*/
+
+/* big enough to hold our biggest descriptor */
+#define USB_BUFSIZ 256
+
+
+struct usb_function*func;
+
+/*-*/
+
+/* An impossibly large value as file_storage */
+#define DELAYED_STATUS (USB_BUFSIZ + 999)
+
+void usb_func_ep_reset (struct usb_gadget *g, struct usb_function *f)
+{
+   struct usb_ep   *ep;
+
+   list_for_each_entry (ep, g-ep_list, ep_list) {
+   if (ep-driver_data == f-driver_data) {
+   usb_ep_disable (ep);
+   ep-driver_data = NULL;
+   }
+   }
+}
+
+static void
+free_ep_req(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req-buf)
+   kfree (req-buf);
+   usb_ep_free_request(ep, req);
+}
+
+/*-*/
+
+static void
+gadget_setup_complete(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req-status || req-actual != req-length)
+   DBG((struct usb_gadget_dev *)ep-driver_data,
+   setup complete -- %d, %u/%u\n,
+   req-status, req-actual, req-length);
+}
+
+static int
+gadget_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+{
+   struct usb_gadget_dev   *dev = get_gadget_data(gadget);
+   struct usb_request  *req = dev-req;
+   int value = -EOPNOTSUPP;
+   u16 w_index = le16_to_cpu(ctrl-wIndex);
+   u16 w_value = le16_to_cpu(ctrl-wValue);
+   u16 w_length = le16_to_cpu(ctrl-wLength);
+
+   req-complete = gadget_setup_complete;
+   req-zero = 0;
+   spin_lock(dev-lock);
+   value = dev-func-setup (gadget, ctrl);
+   spin_unlock(dev-lock);
+
+   /* respond with data transfer before status phase? */
+   if (value = 0  value != DELAYED_STATUS) {
+   req-length = value;
+   req-zero = value  w_length;
+   value = usb_ep_queue(gadget-ep0, req, GFP_ATOMIC);
+   if (value  0) {
+   DBG(dev, ep_queue -- %d\n, value);
+   req-status = 0;
+   gadget_setup_complete(gadget-ep0, req);
+   }
+   } else {
+   DBG(dev, setup req%02x.%02x v%04x i%04x l%d -- %d\n,
+   ctrl-bRequestType, ctrl-bRequest,
+   w_value, w_index, w_length, value);
+   /* to eliminate compile warnings */
+   w_index = w_value = 0;
+   }
+

[linux-usb-devel] [PATCH 1/6] USB gadget driver

2007-05-04 Thread Ragner Magalhaes
Implements support for a gadget function with composite support
to work as a single function.

Signed-off-by: Ragner Magalhaes [EMAIL PROTECTED]

:00 100644 000... e6551d9... A  drivers/usb/gadget/gadget.c

diff --git a/drivers/usb/gadget/gadget.c b/drivers/usb/gadget/gadget.c
new file mode 100644
index 000..e6551d9
--- /dev/null
+++ b/drivers/usb/gadget/gadget.c
@@ -0,0 +1,293 @@
+/*
+ * gadget.c -- USB gadget driver.
+ *
+ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
+ * Developed for INdT by Ragner Magalhaes
+ * Ragner Magalhaes [EMAIL PROTECTED]
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License (GPL) version 2, as published by the Free Software Foundation.
+ *
+ * Implements support for one gadget device with a single function.
+ */
+
+#if 0
+#define DEBUG 1
+#define VERBOSE 1
+#endif
+
+#include linux/module.h
+#include linux/kernel.h
+#include linux/delay.h
+#include linux/ioport.h
+#include linux/sched.h
+#include linux/slab.h
+#include linux/smp_lock.h
+#include linux/errno.h
+#include linux/init.h
+#include linux/timer.h
+#include linux/list.h
+#include linux/interrupt.h
+#include linux/utsname.h
+#include linux/device.h
+#include linux/moduleparam.h
+
+#include asm/byteorder.h
+#include asm/system.h
+#include asm/unaligned.h
+
+#include linux/usb/ch9.h
+#include linux/usb/cdc.h
+#include linux/usb_gadget.h
+#include linux/usb/composite.h
+
+#include gadget_chips.h
+
+/*-*/
+
+#define xprintk(d,level,fmt,args...) \
+   dev_printk(level , (d)-gadget-dev , fmt , ## args)
+
+#ifdef DEBUG
+#define DBG(dev,fmt,args...) \
+   xprintk(dev , KERN_DEBUG , fmt , ## args)
+#else
+#define DBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE
+#define VDBG   DBG
+#else
+#define VDBG(dev,fmt,args...) \
+   do { } while(0)
+#endif /* VERBOSE */
+
+#define ERROR(dev,fmt,args...) \
+   xprintk(dev , KERN_ERR , fmt , ## args)
+#define WARN(dev,fmt,args...) \
+   xprintk(dev , KERN_WARNING , fmt , ## args)
+#define INFO(dev,fmt,args...) \
+   xprintk(dev , KERN_INFO , fmt , ## args)
+
+/*-*/
+
+/* big enough to hold our biggest descriptor */
+#define USB_BUFSIZ 256
+
+
+struct usb_function*func;
+
+/*-*/
+
+/* An impossibly large value as file_storage */
+#define DELAYED_STATUS (USB_BUFSIZ + 999)
+
+void usb_func_ep_reset (struct usb_gadget *g, struct usb_function *f)
+{
+   struct usb_ep   *ep;
+
+   list_for_each_entry (ep, g-ep_list, ep_list) {
+   if (ep-driver_data == f-driver_data) {
+   usb_ep_disable (ep);
+   ep-driver_data = NULL;
+   }
+   }
+}
+
+static void
+free_ep_req(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req-buf)
+   kfree (req-buf);
+   usb_ep_free_request(ep, req);
+}
+
+/*-*/
+
+static void
+gadget_setup_complete(struct usb_ep *ep, struct usb_request *req)
+{
+   if (req-status || req-actual != req-length)
+   DBG((struct usb_gadget_dev *)ep-driver_data,
+   setup complete -- %d, %u/%u\n,
+   req-status, req-actual, req-length);
+}
+
+static int
+gadget_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+{
+   struct usb_gadget_dev   *dev = get_gadget_data(gadget);
+   struct usb_request  *req = dev-req;
+   int value = -EOPNOTSUPP;
+   u16 w_index = le16_to_cpu(ctrl-wIndex);
+   u16 w_value = le16_to_cpu(ctrl-wValue);
+   u16 w_length = le16_to_cpu(ctrl-wLength);
+
+   req-complete = gadget_setup_complete;
+   req-zero = 0;
+   spin_lock(dev-lock);
+   value = dev-func-setup (gadget, ctrl);
+   spin_unlock(dev-lock);
+
+   /* respond with data transfer before status phase? */
+   if (value = 0  value != DELAYED_STATUS) {
+   req-length = value;
+   req-zero = value  w_length;
+   value = usb_ep_queue(gadget-ep0, req, GFP_ATOMIC);
+   if (value  0) {
+   DBG(dev, ep_queue -- %d\n, value);
+   req-status = 0;
+   gadget_setup_complete(gadget-ep0, req);
+   }
+   } else {
+   DBG(dev, setup req%02x.%02x v%04x i%04x l%d -- %d\n,
+   ctrl-bRequestType, ctrl-bRequest,
+   w_value, w_index, w_length, value);
+   /* to eliminate compile warnings */
+   w_index = w_value = 0;
+   }
+