aboutsummaryrefslogtreecommitdiffstats
path: root/usb
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2006-03-13 10:27:32 +0000
committerGreg Kroah-Hartman <gregkh@suse.de>2006-03-13 10:27:32 +0000
commit7371b8e3bf96f28003582afb5f76182b7a9c4062 (patch)
treef2780b6029998e080850e96e6e67ca4fe60fd51c /usb
parent1b558141db8b06c61edebaaf5e3394ed98540ac7 (diff)
downloadpatches-7371b8e3bf96f28003582afb5f76182b7a9c4062.tar.gz
refresh for 2.6.16-rc6
Diffstat (limited to 'usb')
-rw-r--r--usb/recognize-three-more-usb-peripheral-controllers.patch34
-rw-r--r--usb/uhci-improve-debugging-code.patch244
-rw-r--r--usb/uhci-remove-main-list-of-urbs.patch156
-rw-r--r--usb/uhci-use-dummy-tds.patch48
-rw-r--r--usb/uhci-use-one-qh-per-endpoint-not-per-urb.patch1084
-rw-r--r--usb/usb-add-zc0301-video4linux2-driver.patch410
-rw-r--r--usb/usb-convert-a-bunch-of-usb-semaphores-to-mutexes.patch2508
-rw-r--r--usb/usb-core-and-hcds-don-t-put_device-while-atomic.patch74
-rw-r--r--usb/usb-drivers-usb-core-message.c-make-usb_get_string-static.patch22
-rw-r--r--usb/usb-ehci-and-nf2-quirk.patch40
-rw-r--r--usb/usb-et61x51-driver-updates.patch164
-rw-r--r--usb/usb-gadget-driver-section-fixups.patch58
-rw-r--r--usb/usb-gotemp.patch20
-rw-r--r--usb/usb-kzalloc-for-hid.patch30
-rw-r--r--usb/usb-ohci-uses-driver-model-wakeup-flags.patch76
-rw-r--r--usb/usb-remove-obsolete_oss_usb_driver-drivers.patch4894
-rw-r--r--usb/usb-remove-usbcore-specific-wakeup-flags.patch68
-rw-r--r--usb/usb-serial-dynamic-id.patch144
-rw-r--r--usb/usb-sn9c10x-driver-updates.patch142
-rw-r--r--usb/usb-zc0301-driver-updates-2.patch120
-rw-r--r--usb/usb-zc0301-driver-updates.patch22
-rw-r--r--usb/usbip.patch22
22 files changed, 5190 insertions, 5190 deletions
diff --git a/usb/recognize-three-more-usb-peripheral-controllers.patch b/usb/recognize-three-more-usb-peripheral-controllers.patch
index 118bfd93273c3..9878029d095e6 100644
--- a/usb/recognize-three-more-usb-peripheral-controllers.patch
+++ b/usb/recognize-three-more-usb-peripheral-controllers.patch
@@ -34,6 +34,23 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/gadget/gadget_chips.h | 30 ++++++++++++++++++++++++++++--
2 files changed, 36 insertions(+), 2 deletions(-)
+--- gregkh-2.6.orig/drivers/usb/gadget/ether.c
++++ gregkh-2.6/drivers/usb/gadget/ether.c
+@@ -253,6 +253,14 @@ MODULE_PARM_DESC(host_addr, "Host Ethern
+ #define DEV_CONFIG_CDC
+ #endif
+
++#ifdef CONFIG_USB_GADGET_MUSBHSFC
++#define DEV_CONFIG_CDC
++#endif
++
++#ifdef CONFIG_USB_GADGET_MUSBHDRC
++#define DEV_CONFIG_CDC
++#endif
++
+
+ /* For CDC-incapable hardware, choose the simple cdc subset.
+ * Anything that talks bulk (without notable bugs) can do this.
--- gregkh-2.6.orig/drivers/usb/gadget/gadget_chips.h
+++ gregkh-2.6/drivers/usb/gadget/gadget_chips.h
@@ -3,9 +3,9 @@
@@ -87,20 +104,3 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+ return 0x17;
return -ENOENT;
}
---- gregkh-2.6.orig/drivers/usb/gadget/ether.c
-+++ gregkh-2.6/drivers/usb/gadget/ether.c
-@@ -253,6 +253,14 @@ MODULE_PARM_DESC(host_addr, "Host Ethern
- #define DEV_CONFIG_CDC
- #endif
-
-+#ifdef CONFIG_USB_GADGET_MUSBHSFC
-+#define DEV_CONFIG_CDC
-+#endif
-+
-+#ifdef CONFIG_USB_GADGET_MUSBHDRC
-+#define DEV_CONFIG_CDC
-+#endif
-+
-
- /* For CDC-incapable hardware, choose the simple cdc subset.
- * Anything that talks bulk (without notable bugs) can do this.
diff --git a/usb/uhci-improve-debugging-code.patch b/usb/uhci-improve-debugging-code.patch
index 2b8c9e5b2c3b0..77ede9e35bcb8 100644
--- a/usb/uhci-improve-debugging-code.patch
+++ b/usb/uhci-improve-debugging-code.patch
@@ -21,44 +21,94 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/uhci-q.c | 12 --------
4 files changed, 70 insertions(+), 39 deletions(-)
---- gregkh-2.6.orig/drivers/usb/host/uhci-q.c
-+++ gregkh-2.6/drivers/usb/host/uhci-q.c
-@@ -736,7 +736,6 @@ err:
- if (errbuf) {
- /* Print the chain for debugging purposes */
- uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
--
- lprintk(errbuf);
- }
- }
-@@ -924,26 +923,17 @@ td_error:
- ret = uhci_map_status(status, uhci_packetout(td_token(td)));
+--- gregkh-2.6.orig/drivers/usb/host/uhci-debug.c
++++ gregkh-2.6/drivers/usb/host/uhci-debug.c
+@@ -17,10 +17,13 @@
- err:
-- /*
-- * Enable this chunk of code if you want to see some more debugging.
-- * But be careful, it has the tendancy to starve out khubd and prevent
-- * disconnects from happening successfully if you have a slow debug
-- * log interface (like a serial console.
-- */
--#if 0
- if ((debug == 1 && ret != -EPIPE) || debug > 1) {
- /* Some debugging code */
- dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
- __FUNCTION__, status);
+ #include "uhci-hcd.h"
-- if (errbuf) {
-+ if (debug > 1 && errbuf) {
- /* Print the chain for debugging purposes */
- uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
--
- lprintk(errbuf);
- }
+-static struct dentry *uhci_debugfs_root = NULL;
++#define uhci_debug_operations (* (struct file_operations *) NULL)
++static struct dentry *uhci_debugfs_root;
++
++#ifdef DEBUG
+
+ /* Handle REALLY large printks so we don't overflow buffers */
+-static inline void lprintk(char *buf)
++static void lprintk(char *buf)
+ {
+ char *p;
+
+@@ -196,7 +199,6 @@ static int uhci_show_qh(struct uhci_qh *
+ return out - buf;
+ }
+
+-#ifdef CONFIG_PROC_FS
+ static const char * const qh_names[] = {
+ "skel_unlink_qh", "skel_iso_qh",
+ "skel_int128_qh", "skel_int64_qh",
+@@ -393,12 +395,13 @@ static int uhci_sprint_schedule(struct u
+ return out - buf;
+ }
+
++#ifdef CONFIG_DEBUG_FS
++
+ #define MAX_OUTPUT (64 * 1024)
+
+ struct uhci_debug {
+ int size;
+ char *data;
+- struct uhci_hcd *uhci;
+ };
+
+ static int uhci_debug_open(struct inode *inode, struct file *file)
+@@ -419,8 +422,10 @@ static int uhci_debug_open(struct inode
+ goto out;
}
--#endif
- /* Note that the queue has stopped and save the next toggle value */
- urbp->qh->element = UHCI_PTR_TERM;
++ up->size = 0;
+ spin_lock_irqsave(&uhci->lock, flags);
+- up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);
++ if (uhci->is_initialized)
++ up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);
+ spin_unlock_irqrestore(&uhci->lock, flags);
+
+ file->private_data = up;
+@@ -472,15 +477,32 @@ static int uhci_debug_release(struct ino
+ return 0;
+ }
+
++#undef uhci_debug_operations
+ static struct file_operations uhci_debug_operations = {
++ .owner = THIS_MODULE,
+ .open = uhci_debug_open,
+ .llseek = uhci_debug_lseek,
+ .read = uhci_debug_read,
+ .release = uhci_debug_release,
+ };
+
+-#else /* CONFIG_DEBUG_FS */
++#endif /* CONFIG_DEBUG_FS */
+
+-#define uhci_debug_operations (* (struct file_operations *) NULL)
++#else /* DEBUG */
++
++static inline void lprintk(char *buf)
++{}
++
++static inline int uhci_show_qh(struct uhci_qh *qh, char *buf,
++ int len, int space)
++{
++ return 0;
++}
++
++static inline int uhci_sprint_schedule(struct uhci_hcd *uhci,
++ char *buf, int len)
++{
++ return 0;
++}
+
+ #endif
--- gregkh-2.6.orig/drivers/usb/host/uhci-hcd.c
+++ gregkh-2.6/drivers/usb/host/uhci-hcd.c
@@ -68,12 +68,16 @@ Alan Stern"
@@ -185,94 +235,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
uhci_up_cachep = kmem_cache_create("uhci_urb_priv",
sizeof(struct urb_priv), 0, 0, NULL, NULL);
if (!uhci_up_cachep)
---- gregkh-2.6.orig/drivers/usb/host/uhci-debug.c
-+++ gregkh-2.6/drivers/usb/host/uhci-debug.c
-@@ -17,10 +17,13 @@
-
- #include "uhci-hcd.h"
-
--static struct dentry *uhci_debugfs_root = NULL;
-+#define uhci_debug_operations (* (struct file_operations *) NULL)
-+static struct dentry *uhci_debugfs_root;
-+
-+#ifdef DEBUG
-
- /* Handle REALLY large printks so we don't overflow buffers */
--static inline void lprintk(char *buf)
-+static void lprintk(char *buf)
- {
- char *p;
-
-@@ -196,7 +199,6 @@ static int uhci_show_qh(struct uhci_qh *
- return out - buf;
- }
-
--#ifdef CONFIG_PROC_FS
- static const char * const qh_names[] = {
- "skel_unlink_qh", "skel_iso_qh",
- "skel_int128_qh", "skel_int64_qh",
-@@ -393,12 +395,13 @@ static int uhci_sprint_schedule(struct u
- return out - buf;
- }
-
-+#ifdef CONFIG_DEBUG_FS
-+
- #define MAX_OUTPUT (64 * 1024)
-
- struct uhci_debug {
- int size;
- char *data;
-- struct uhci_hcd *uhci;
- };
-
- static int uhci_debug_open(struct inode *inode, struct file *file)
-@@ -419,8 +422,10 @@ static int uhci_debug_open(struct inode
- goto out;
- }
-
-+ up->size = 0;
- spin_lock_irqsave(&uhci->lock, flags);
-- up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);
-+ if (uhci->is_initialized)
-+ up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);
- spin_unlock_irqrestore(&uhci->lock, flags);
-
- file->private_data = up;
-@@ -472,15 +477,32 @@ static int uhci_debug_release(struct ino
- return 0;
- }
-
-+#undef uhci_debug_operations
- static struct file_operations uhci_debug_operations = {
-+ .owner = THIS_MODULE,
- .open = uhci_debug_open,
- .llseek = uhci_debug_lseek,
- .read = uhci_debug_read,
- .release = uhci_debug_release,
- };
-
--#else /* CONFIG_DEBUG_FS */
-+#endif /* CONFIG_DEBUG_FS */
-
--#define uhci_debug_operations (* (struct file_operations *) NULL)
-+#else /* DEBUG */
-+
-+static inline void lprintk(char *buf)
-+{}
-+
-+static inline int uhci_show_qh(struct uhci_qh *qh, char *buf,
-+ int len, int space)
-+{
-+ return 0;
-+}
-+
-+static inline int uhci_sprint_schedule(struct uhci_hcd *uhci,
-+ char *buf, int len)
-+{
-+ return 0;
-+}
-
- #endif
--- gregkh-2.6.orig/drivers/usb/host/uhci-hcd.h
+++ gregkh-2.6/drivers/usb/host/uhci-hcd.h
@@ -411,6 +411,7 @@ struct uhci_hcd {
@@ -283,3 +245,41 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
/* Support for port suspend/resume/reset */
unsigned long port_c_suspend; /* Bit-arrays of ports */
+--- gregkh-2.6.orig/drivers/usb/host/uhci-q.c
++++ gregkh-2.6/drivers/usb/host/uhci-q.c
+@@ -736,7 +736,6 @@ err:
+ if (errbuf) {
+ /* Print the chain for debugging purposes */
+ uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
+-
+ lprintk(errbuf);
+ }
+ }
+@@ -924,26 +923,17 @@ td_error:
+ ret = uhci_map_status(status, uhci_packetout(td_token(td)));
+
+ err:
+- /*
+- * Enable this chunk of code if you want to see some more debugging.
+- * But be careful, it has the tendancy to starve out khubd and prevent
+- * disconnects from happening successfully if you have a slow debug
+- * log interface (like a serial console.
+- */
+-#if 0
+ if ((debug == 1 && ret != -EPIPE) || debug > 1) {
+ /* Some debugging code */
+ dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
+ __FUNCTION__, status);
+
+- if (errbuf) {
++ if (debug > 1 && errbuf) {
+ /* Print the chain for debugging purposes */
+ uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
+-
+ lprintk(errbuf);
+ }
+ }
+-#endif
+
+ /* Note that the queue has stopped and save the next toggle value */
+ urbp->qh->element = UHCI_PTR_TERM;
diff --git a/usb/uhci-remove-main-list-of-urbs.patch b/usb/uhci-remove-main-list-of-urbs.patch
index 01234c586a90c..576b0b0cd447e 100644
--- a/usb/uhci-remove-main-list-of-urbs.patch
+++ b/usb/uhci-remove-main-list-of-urbs.patch
@@ -30,6 +30,84 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/uhci-q.c | 633 ++++++++++++++++++------------------------
4 files changed, 280 insertions(+), 371 deletions(-)
+--- gregkh-2.6.orig/drivers/usb/host/uhci-debug.c
++++ gregkh-2.6/drivers/usb/host/uhci-debug.c
+@@ -114,7 +114,6 @@ static int uhci_show_urbp(struct urb_pri
+ }
+
+ out += sprintf(out, "%s", (urbp->fsbr ? " FSBR" : ""));
+- out += sprintf(out, "%s", (urbp->fsbr_timeout ? " FSBR_TO" : ""));
+
+ if (urbp->urb->status != -EINPROGRESS)
+ out += sprintf(out, " Status=%d", urbp->urb->status);
+--- gregkh-2.6.orig/drivers/usb/host/uhci-hcd.c
++++ gregkh-2.6/drivers/usb/host/uhci-hcd.c
+@@ -491,8 +491,6 @@ static int uhci_start(struct usb_hcd *hc
+ spin_lock_init(&uhci->lock);
+
+ INIT_LIST_HEAD(&uhci->td_remove_list);
+- INIT_LIST_HEAD(&uhci->urb_list);
+- INIT_LIST_HEAD(&uhci->complete_list);
+ INIT_LIST_HEAD(&uhci->idle_qh_list);
+
+ init_waitqueue_head(&uhci->waitqh);
+--- gregkh-2.6.orig/drivers/usb/host/uhci-hcd.h
++++ gregkh-2.6/drivers/usb/host/uhci-hcd.h
+@@ -132,6 +132,10 @@ struct uhci_qh {
+
+ unsigned int unlink_frame; /* When the QH was unlinked */
+ int state; /* QH_STATE_xxx; see above */
++
++ unsigned int initial_toggle:1; /* Endpoint's current toggle value */
++ unsigned int needs_fixup:1; /* Must fix the TD toggle values */
++ unsigned int is_stopped:1; /* Queue was stopped by an error */
+ } __attribute__((aligned(16)));
+
+ /*
+@@ -384,6 +388,7 @@ struct uhci_hcd {
+
+ struct uhci_td *term_td; /* Terminating TD, see UHCI bug */
+ struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QHs */
++ struct uhci_qh *next_qh; /* Next QH to scan */
+
+ spinlock_t lock;
+
+@@ -413,16 +418,10 @@ struct uhci_hcd {
+ unsigned long resuming_ports;
+ unsigned long ports_timeout; /* Time to stop signalling */
+
+- /* Main list of URBs currently controlled by this HC */
+- struct list_head urb_list;
+-
+ /* List of TDs that are done, but waiting to be freed (race) */
+ struct list_head td_remove_list;
+ unsigned int td_remove_age; /* Age in frames */
+
+- /* List of URBs awaiting completion callback */
+- struct list_head complete_list;
+-
+ struct list_head idle_qh_list; /* Where the idle QHs live */
+
+ int rh_numports; /* Number of root-hub ports */
+@@ -448,7 +447,6 @@ static inline struct usb_hcd *uhci_to_hc
+ * Private per-URB data
+ */
+ struct urb_priv {
+- struct list_head urb_list;
+ struct list_head node; /* Node in the QH's urbp list */
+
+ struct urb *urb;
+@@ -456,10 +454,7 @@ struct urb_priv {
+ struct uhci_qh *qh; /* QH for this URB */
+ struct list_head td_list;
+
+- unsigned long fsbrtime; /* In jiffies */
+-
+ unsigned fsbr : 1; /* URB turned on FSBR */
+- unsigned fsbr_timeout : 1; /* URB timed out on FSBR */
+ unsigned short_transfer : 1; /* URB got a short transfer, no
+ * need to rescan */
+ };
--- gregkh-2.6.orig/drivers/usb/host/uhci-q.c
+++ gregkh-2.6/drivers/usb/host/uhci-q.c
@@ -151,53 +151,6 @@ static void uhci_unlink_isochronous_tds(
@@ -847,81 +925,3 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
/* Really disable FSBR */
if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
---- gregkh-2.6.orig/drivers/usb/host/uhci-hcd.h
-+++ gregkh-2.6/drivers/usb/host/uhci-hcd.h
-@@ -132,6 +132,10 @@ struct uhci_qh {
-
- unsigned int unlink_frame; /* When the QH was unlinked */
- int state; /* QH_STATE_xxx; see above */
-+
-+ unsigned int initial_toggle:1; /* Endpoint's current toggle value */
-+ unsigned int needs_fixup:1; /* Must fix the TD toggle values */
-+ unsigned int is_stopped:1; /* Queue was stopped by an error */
- } __attribute__((aligned(16)));
-
- /*
-@@ -384,6 +388,7 @@ struct uhci_hcd {
-
- struct uhci_td *term_td; /* Terminating TD, see UHCI bug */
- struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QHs */
-+ struct uhci_qh *next_qh; /* Next QH to scan */
-
- spinlock_t lock;
-
-@@ -413,16 +418,10 @@ struct uhci_hcd {
- unsigned long resuming_ports;
- unsigned long ports_timeout; /* Time to stop signalling */
-
-- /* Main list of URBs currently controlled by this HC */
-- struct list_head urb_list;
--
- /* List of TDs that are done, but waiting to be freed (race) */
- struct list_head td_remove_list;
- unsigned int td_remove_age; /* Age in frames */
-
-- /* List of URBs awaiting completion callback */
-- struct list_head complete_list;
--
- struct list_head idle_qh_list; /* Where the idle QHs live */
-
- int rh_numports; /* Number of root-hub ports */
-@@ -448,7 +447,6 @@ static inline struct usb_hcd *uhci_to_hc
- * Private per-URB data
- */
- struct urb_priv {
-- struct list_head urb_list;
- struct list_head node; /* Node in the QH's urbp list */
-
- struct urb *urb;
-@@ -456,10 +454,7 @@ struct urb_priv {
- struct uhci_qh *qh; /* QH for this URB */
- struct list_head td_list;
-
-- unsigned long fsbrtime; /* In jiffies */
--
- unsigned fsbr : 1; /* URB turned on FSBR */
-- unsigned fsbr_timeout : 1; /* URB timed out on FSBR */
- unsigned short_transfer : 1; /* URB got a short transfer, no
- * need to rescan */
- };
---- gregkh-2.6.orig/drivers/usb/host/uhci-hcd.c
-+++ gregkh-2.6/drivers/usb/host/uhci-hcd.c
-@@ -491,8 +491,6 @@ static int uhci_start(struct usb_hcd *hc
- spin_lock_init(&uhci->lock);
-
- INIT_LIST_HEAD(&uhci->td_remove_list);
-- INIT_LIST_HEAD(&uhci->urb_list);
-- INIT_LIST_HEAD(&uhci->complete_list);
- INIT_LIST_HEAD(&uhci->idle_qh_list);
-
- init_waitqueue_head(&uhci->waitqh);
---- gregkh-2.6.orig/drivers/usb/host/uhci-debug.c
-+++ gregkh-2.6/drivers/usb/host/uhci-debug.c
-@@ -114,7 +114,6 @@ static int uhci_show_urbp(struct urb_pri
- }
-
- out += sprintf(out, "%s", (urbp->fsbr ? " FSBR" : ""));
-- out += sprintf(out, "%s", (urbp->fsbr_timeout ? " FSBR_TO" : ""));
-
- if (urbp->urb->status != -EINPROGRESS)
- out += sprintf(out, " Status=%d", urbp->urb->status);
diff --git a/usb/uhci-use-dummy-tds.patch b/usb/uhci-use-dummy-tds.patch
index 139f0093ff583..16b02efed5462 100644
--- a/usb/uhci-use-dummy-tds.patch
+++ b/usb/uhci-use-dummy-tds.patch
@@ -27,6 +27,30 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/uhci-q.c | 138 +++++++++++++++++++++++-------------------
3 files changed, 83 insertions(+), 61 deletions(-)
+--- gregkh-2.6.orig/drivers/usb/host/uhci-debug.c
++++ gregkh-2.6/drivers/usb/host/uhci-debug.c
+@@ -189,6 +189,11 @@ static int uhci_show_qh(struct uhci_qh *
+ space, "", nurbs);
+ }
+
++ if (qh->udev) {
++ out += sprintf(out, "%*s Dummy TD\n", space, "");
++ out += uhci_show_td(qh->dummy_td, out, len - (out - buf), 0);
++ }
++
+ return out - buf;
+ }
+
+--- gregkh-2.6.orig/drivers/usb/host/uhci-hcd.h
++++ gregkh-2.6/drivers/usb/host/uhci-hcd.h
+@@ -128,6 +128,7 @@ struct uhci_qh {
+ struct usb_device *udev;
+ struct list_head queue; /* Queue of urbps for this QH */
+ struct uhci_qh *skel; /* Skeleton for this QH */
++ struct uhci_td *dummy_td; /* Dummy TD to end the queue */
+
+ unsigned int unlink_frame; /* When the QH was unlinked */
+ int state; /* QH_STATE_xxx; see above */
--- gregkh-2.6.orig/drivers/usb/host/uhci-q.c
+++ gregkh-2.6/drivers/usb/host/uhci-q.c
@@ -48,10 +48,6 @@ static struct uhci_td *uhci_alloc_td(str
@@ -294,27 +318,3 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
goto done;
err_submit_failed:
---- gregkh-2.6.orig/drivers/usb/host/uhci-hcd.h
-+++ gregkh-2.6/drivers/usb/host/uhci-hcd.h
-@@ -128,6 +128,7 @@ struct uhci_qh {
- struct usb_device *udev;
- struct list_head queue; /* Queue of urbps for this QH */
- struct uhci_qh *skel; /* Skeleton for this QH */
-+ struct uhci_td *dummy_td; /* Dummy TD to end the queue */
-
- unsigned int unlink_frame; /* When the QH was unlinked */
- int state; /* QH_STATE_xxx; see above */
---- gregkh-2.6.orig/drivers/usb/host/uhci-debug.c
-+++ gregkh-2.6/drivers/usb/host/uhci-debug.c
-@@ -189,6 +189,11 @@ static int uhci_show_qh(struct uhci_qh *
- space, "", nurbs);
- }
-
-+ if (qh->udev) {
-+ out += sprintf(out, "%*s Dummy TD\n", space, "");
-+ out += uhci_show_td(qh->dummy_td, out, len - (out - buf), 0);
-+ }
-+
- return out - buf;
- }
-
diff --git a/usb/uhci-use-one-qh-per-endpoint-not-per-urb.patch b/usb/uhci-use-one-qh-per-endpoint-not-per-urb.patch
index 9d9aafeb9c6cd..ed3417ac5b96c 100644
--- a/usb/uhci-use-one-qh-per-endpoint-not-per-urb.patch
+++ b/usb/uhci-use-one-qh-per-endpoint-not-per-urb.patch
@@ -21,6 +21,548 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/uhci-q.c | 987 +++++++++++++++++++-----------------------
4 files changed, 689 insertions(+), 866 deletions(-)
+--- gregkh-2.6.orig/drivers/usb/host/uhci-debug.c
++++ gregkh-2.6/drivers/usb/host/uhci-debug.c
+@@ -90,13 +90,60 @@ static int uhci_show_td(struct uhci_td *
+ return out - buf;
+ }
+
+-static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
++static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space)
+ {
+ char *out = buf;
+- struct urb_priv *urbp;
+- struct list_head *head, *tmp;
+ struct uhci_td *td;
+- int i = 0, checked = 0, prevactive = 0;
++ int i, nactive, ninactive;
++
++ if (len < 200)
++ return 0;
++
++ out += sprintf(out, "urb_priv [%p] ", urbp);
++ out += sprintf(out, "urb [%p] ", urbp->urb);
++ out += sprintf(out, "qh [%p] ", urbp->qh);
++ out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe));
++ out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe),
++ (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT"));
++
++ switch (usb_pipetype(urbp->urb->pipe)) {
++ case PIPE_ISOCHRONOUS: out += sprintf(out, "ISO"); break;
++ case PIPE_INTERRUPT: out += sprintf(out, "INT"); break;
++ case PIPE_BULK: out += sprintf(out, "BLK"); break;
++ case PIPE_CONTROL: out += sprintf(out, "CTL"); break;
++ }
++
++ out += sprintf(out, "%s", (urbp->fsbr ? " FSBR" : ""));
++ out += sprintf(out, "%s", (urbp->fsbr_timeout ? " FSBR_TO" : ""));
++
++ if (urbp->urb->status != -EINPROGRESS)
++ out += sprintf(out, " Status=%d", urbp->urb->status);
++ out += sprintf(out, "\n");
++
++ i = nactive = ninactive = 0;
++ list_for_each_entry(td, &urbp->td_list, list) {
++ if (++i <= 10 || debug > 2) {
++ out += sprintf(out, "%*s%d: ", space + 2, "", i);
++ out += uhci_show_td(td, out, len - (out - buf), 0);
++ } else {
++ if (td_status(td) & TD_CTRL_ACTIVE)
++ ++nactive;
++ else
++ ++ninactive;
++ }
++ }
++ if (nactive + ninactive > 0)
++ out += sprintf(out, "%*s[skipped %d inactive and %d active "
++ "TDs]\n",
++ space, "", ninactive, nactive);
++
++ return out - buf;
++}
++
++static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
++{
++ char *out = buf;
++ int i, nurbs;
+ __le32 element = qh_element(qh);
+
+ /* Try to make sure there's enough memory */
+@@ -118,86 +165,36 @@ static int uhci_show_qh(struct uhci_qh *
+ if (!(element & ~(UHCI_PTR_QH | UHCI_PTR_DEPTH)))
+ out += sprintf(out, "%*s Element is NULL (bug?)\n", space, "");
+
+- if (!qh->urbp) {
+- out += sprintf(out, "%*s urbp == NULL\n", space, "");
+- goto out;
+- }
+-
+- urbp = qh->urbp;
+-
+- head = &urbp->td_list;
+- tmp = head->next;
+-
+- td = list_entry(tmp, struct uhci_td, list);
+-
+- if (cpu_to_le32(td->dma_handle) != (element & ~UHCI_PTR_BITS))
+- out += sprintf(out, "%*s Element != First TD\n", space, "");
+-
+- while (tmp != head) {
+- struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
+-
+- tmp = tmp->next;
+-
+- out += sprintf(out, "%*s%d: ", space + 2, "", i++);
+- out += uhci_show_td(td, out, len - (out - buf), 0);
+-
+- if (i > 10 && !checked && prevactive && tmp != head &&
+- debug <= 2) {
+- struct list_head *ntmp = tmp;
+- struct uhci_td *ntd = td;
+- int active = 1, ni = i;
+-
+- checked = 1;
+-
+- while (ntmp != head && ntmp->next != head && active) {
+- ntd = list_entry(ntmp, struct uhci_td, list);
+-
+- ntmp = ntmp->next;
+-
+- active = td_status(ntd) & TD_CTRL_ACTIVE;
+-
+- ni++;
+- }
+-
+- if (active && ni > i) {
+- out += sprintf(out, "%*s[skipped %d active TDs]\n", space, "", ni - i);
+- tmp = ntmp;
+- td = ntd;
+- i = ni;
+- }
++ if (list_empty(&qh->queue)) {
++ out += sprintf(out, "%*s queue is empty\n", space, "");
++ } else {
++ struct urb_priv *urbp = list_entry(qh->queue.next,
++ struct urb_priv, node);
++ struct uhci_td *td = list_entry(urbp->td_list.next,
++ struct uhci_td, list);
++
++ if (cpu_to_le32(td->dma_handle) != (element & ~UHCI_PTR_BITS))
++ out += sprintf(out, "%*s Element != First TD\n",
++ space, "");
++ i = nurbs = 0;
++ list_for_each_entry(urbp, &qh->queue, node) {
++ if (++i <= 10)
++ out += uhci_show_urbp(urbp, out,
++ len - (out - buf), space + 2);
++ else
++ ++nurbs;
+ }
+-
+- prevactive = td_status(td) & TD_CTRL_ACTIVE;
+- }
+-
+- if (list_empty(&urbp->queue_list) || urbp->queued)
+- goto out;
+-
+- out += sprintf(out, "%*sQueued QHs:\n", -space, "--");
+-
+- head = &urbp->queue_list;
+- tmp = head->next;
+-
+- while (tmp != head) {
+- struct urb_priv *nurbp = list_entry(tmp, struct urb_priv,
+- queue_list);
+- tmp = tmp->next;
+-
+- out += uhci_show_qh(nurbp->qh, out, len - (out - buf), space);
++ if (nurbs > 0)
++ out += sprintf(out, "%*s Skipped %d URBs\n",
++ space, "", nurbs);
+ }
+
+-out:
+ return out - buf;
+ }
+
+-#define show_frame_num() \
+- if (!shown) { \
+- shown = 1; \
+- out += sprintf(out, "- Frame %d\n", i); \
+- }
+-
+ #ifdef CONFIG_PROC_FS
+ static const char * const qh_names[] = {
++ "skel_unlink_qh", "skel_iso_qh",
+ "skel_int128_qh", "skel_int64_qh",
+ "skel_int32_qh", "skel_int16_qh",
+ "skel_int8_qh", "skel_int4_qh",
+@@ -206,12 +203,6 @@ static const char * const qh_names[] = {
+ "skel_bulk_qh", "skel_term_qh"
+ };
+
+-#define show_qh_name() \
+- if (!shown) { \
+- shown = 1; \
+- out += sprintf(out, "- %s\n", qh_names[i]); \
+- }
+-
+ static int uhci_show_sc(int port, unsigned short status, char *buf, int len)
+ {
+ char *out = buf;
+@@ -321,139 +312,29 @@ static int uhci_show_status(struct uhci_
+ return out - buf;
+ }
+
+-static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, char *buf, int len)
+-{
+- struct list_head *tmp;
+- char *out = buf;
+- int count = 0;
+-
+- if (len < 200)
+- return 0;
+-
+- out += sprintf(out, "urb_priv [%p] ", urbp);
+- out += sprintf(out, "urb [%p] ", urbp->urb);
+- out += sprintf(out, "qh [%p] ", urbp->qh);
+- out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe));
+- out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe), (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT"));
+-
+- switch (usb_pipetype(urbp->urb->pipe)) {
+- case PIPE_ISOCHRONOUS: out += sprintf(out, "ISO "); break;
+- case PIPE_INTERRUPT: out += sprintf(out, "INT "); break;
+- case PIPE_BULK: out += sprintf(out, "BLK "); break;
+- case PIPE_CONTROL: out += sprintf(out, "CTL "); break;
+- }
+-
+- out += sprintf(out, "%s", (urbp->fsbr ? "FSBR " : ""));
+- out += sprintf(out, "%s", (urbp->fsbr_timeout ? "FSBR_TO " : ""));
+-
+- if (urbp->urb->status != -EINPROGRESS)
+- out += sprintf(out, "Status=%d ", urbp->urb->status);
+- //out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime);
+-
+- count = 0;
+- list_for_each(tmp, &urbp->td_list)
+- count++;
+- out += sprintf(out, "TDs=%d ",count);
+-
+- if (urbp->queued)
+- out += sprintf(out, "queued\n");
+- else {
+- count = 0;
+- list_for_each(tmp, &urbp->queue_list)
+- count++;
+- out += sprintf(out, "queued URBs=%d\n", count);
+- }
+-
+- return out - buf;
+-}
+-
+-static int uhci_show_lists(struct uhci_hcd *uhci, char *buf, int len)
+-{
+- char *out = buf;
+- struct list_head *head, *tmp;
+- int count;
+-
+- out += sprintf(out, "Main list URBs:");
+- if (list_empty(&uhci->urb_list))
+- out += sprintf(out, " Empty\n");
+- else {
+- out += sprintf(out, "\n");
+- count = 0;
+- head = &uhci->urb_list;
+- tmp = head->next;
+- while (tmp != head) {
+- struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
+-
+- out += sprintf(out, " %d: ", ++count);
+- out += uhci_show_urbp(uhci, urbp, out, len - (out - buf));
+- tmp = tmp->next;
+- }
+- }
+-
+- out += sprintf(out, "Remove list URBs:");
+- if (list_empty(&uhci->urb_remove_list))
+- out += sprintf(out, " Empty\n");
+- else {
+- out += sprintf(out, "\n");
+- count = 0;
+- head = &uhci->urb_remove_list;
+- tmp = head->next;
+- while (tmp != head) {
+- struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
+-
+- out += sprintf(out, " %d: ", ++count);
+- out += uhci_show_urbp(uhci, urbp, out, len - (out - buf));
+- tmp = tmp->next;
+- }
+- }
+-
+- out += sprintf(out, "Complete list URBs:");
+- if (list_empty(&uhci->complete_list))
+- out += sprintf(out, " Empty\n");
+- else {
+- out += sprintf(out, "\n");
+- count = 0;
+- head = &uhci->complete_list;
+- tmp = head->next;
+- while (tmp != head) {
+- struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
+-
+- out += sprintf(out, " %d: ", ++count);
+- out += uhci_show_urbp(uhci, urbp, out, len - (out - buf));
+- tmp = tmp->next;
+- }
+- }
+-
+- return out - buf;
+-}
+-
+ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
+ {
+- unsigned long flags;
+ char *out = buf;
+ int i, j;
+ struct uhci_qh *qh;
+ struct uhci_td *td;
+ struct list_head *tmp, *head;
+
+- spin_lock_irqsave(&uhci->lock, flags);
+-
+ out += uhci_show_root_hub_state(uhci, out, len - (out - buf));
+ out += sprintf(out, "HC status\n");
+ out += uhci_show_status(uhci, out, len - (out - buf));
++ if (debug <= 1)
++ return out - buf;
+
+ out += sprintf(out, "Frame List\n");
+ for (i = 0; i < UHCI_NUMFRAMES; ++i) {
+- int shown = 0;
+ td = uhci->frame_cpu[i];
+ if (!td)
+ continue;
+
+- if (td->dma_handle != (dma_addr_t)uhci->frame[i]) {
+- show_frame_num();
++ out += sprintf(out, "- Frame %d\n", i); \
++ if (td->dma_handle != (dma_addr_t)uhci->frame[i])
+ out += sprintf(out, " frame list does not match td->dma_handle!\n");
+- }
+- show_frame_num();
+
+ head = &td->fl_list;
+ tmp = head;
+@@ -467,14 +348,11 @@ static int uhci_sprint_schedule(struct u
+ out += sprintf(out, "Skeleton QHs\n");
+
+ for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
+- int shown = 0;
++ int cnt = 0;
+
+ qh = uhci->skelqh[i];
+-
+- if (debug > 1) {
+- show_qh_name();
+- out += uhci_show_qh(qh, out, len - (out - buf), 4);
+- }
++ out += sprintf(out, "- %s\n", qh_names[i]); \
++ out += uhci_show_qh(qh, out, len - (out - buf), 4);
+
+ /* Last QH is the Terminating QH, it's different */
+ if (i == UHCI_NUM_SKELQH - 1) {
+@@ -487,44 +365,27 @@ static int uhci_sprint_schedule(struct u
+ continue;
+ }
+
+- j = (i < 7) ? 7 : i+1; /* Next skeleton */
+- if (list_empty(&qh->list)) {
+- if (i < UHCI_NUM_SKELQH - 1) {
+- if (qh->link !=
+- (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH)) {
+- show_qh_name();
+- out += sprintf(out, " skeleton QH not linked to next skeleton QH!\n");
+- }
+- }
+-
+- continue;
+- }
+-
+- show_qh_name();
+-
+- head = &qh->list;
++ j = (i < 9) ? 9 : i+1; /* Next skeleton */
++ head = &qh->node;
+ tmp = head->next;
+
+ while (tmp != head) {
+- qh = list_entry(tmp, struct uhci_qh, list);
+-
++ qh = list_entry(tmp, struct uhci_qh, node);
+ tmp = tmp->next;
+-
+- out += uhci_show_qh(qh, out, len - (out - buf), 4);
++ if (++cnt <= 10)
++ out += uhci_show_qh(qh, out,
++ len - (out - buf), 4);
+ }
++ if ((cnt -= 10) > 0)
++ out += sprintf(out, " Skipped %d QHs\n", cnt);
+
+- if (i < UHCI_NUM_SKELQH - 1) {
++ if (i > 1 && i < UHCI_NUM_SKELQH - 1) {
+ if (qh->link !=
+ (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH))
+ out += sprintf(out, " last QH not linked to next skeleton!\n");
+ }
+ }
+
+- if (debug > 2)
+- out += uhci_show_lists(uhci, out, len - (out - buf));
+-
+- spin_unlock_irqrestore(&uhci->lock, flags);
+-
+ return out - buf;
+ }
+
+@@ -541,6 +402,7 @@ static int uhci_debug_open(struct inode
+ struct uhci_hcd *uhci = inode->u.generic_ip;
+ struct uhci_debug *up;
+ int ret = -ENOMEM;
++ unsigned long flags;
+
+ lock_kernel();
+ up = kmalloc(sizeof(*up), GFP_KERNEL);
+@@ -553,7 +415,9 @@ static int uhci_debug_open(struct inode
+ goto out;
+ }
+
++ spin_lock_irqsave(&uhci->lock, flags);
+ up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);
++ spin_unlock_irqrestore(&uhci->lock, flags);
+
+ file->private_data = up;
+
+--- gregkh-2.6.orig/drivers/usb/host/uhci-hcd.c
++++ gregkh-2.6/drivers/usb/host/uhci-hcd.c
+@@ -54,7 +54,7 @@
+ /*
+ * Version Information
+ */
+-#define DRIVER_VERSION "v2.3"
++#define DRIVER_VERSION "v3.0"
+ #define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \
+ Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \
+ Alan Stern"
+@@ -489,15 +489,11 @@ static int uhci_start(struct usb_hcd *hc
+ uhci->fsbrtimeout = 0;
+
+ spin_lock_init(&uhci->lock);
+- INIT_LIST_HEAD(&uhci->qh_remove_list);
+
+ INIT_LIST_HEAD(&uhci->td_remove_list);
+-
+- INIT_LIST_HEAD(&uhci->urb_remove_list);
+-
+ INIT_LIST_HEAD(&uhci->urb_list);
+-
+ INIT_LIST_HEAD(&uhci->complete_list);
++ INIT_LIST_HEAD(&uhci->idle_qh_list);
+
+ init_waitqueue_head(&uhci->waitqh);
+
+@@ -540,7 +536,7 @@ static int uhci_start(struct usb_hcd *hc
+ }
+
+ for (i = 0; i < UHCI_NUM_SKELQH; i++) {
+- uhci->skelqh[i] = uhci_alloc_qh(uhci);
++ uhci->skelqh[i] = uhci_alloc_qh(uhci, NULL, NULL);
+ if (!uhci->skelqh[i]) {
+ dev_err(uhci_dev(uhci), "unable to allocate QH\n");
+ goto err_alloc_skelqh;
+@@ -557,13 +553,17 @@ static int uhci_start(struct usb_hcd *hc
+ uhci->skel_int16_qh->link =
+ uhci->skel_int8_qh->link =
+ uhci->skel_int4_qh->link =
+- uhci->skel_int2_qh->link =
+- cpu_to_le32(uhci->skel_int1_qh->dma_handle) | UHCI_PTR_QH;
+- uhci->skel_int1_qh->link = cpu_to_le32(uhci->skel_ls_control_qh->dma_handle) | UHCI_PTR_QH;
+-
+- uhci->skel_ls_control_qh->link = cpu_to_le32(uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH;
+- uhci->skel_fs_control_qh->link = cpu_to_le32(uhci->skel_bulk_qh->dma_handle) | UHCI_PTR_QH;
+- uhci->skel_bulk_qh->link = cpu_to_le32(uhci->skel_term_qh->dma_handle) | UHCI_PTR_QH;
++ uhci->skel_int2_qh->link = UHCI_PTR_QH |
++ cpu_to_le32(uhci->skel_int1_qh->dma_handle);
++
++ uhci->skel_int1_qh->link = UHCI_PTR_QH |
++ cpu_to_le32(uhci->skel_ls_control_qh->dma_handle);
++ uhci->skel_ls_control_qh->link = UHCI_PTR_QH |
++ cpu_to_le32(uhci->skel_fs_control_qh->dma_handle);
++ uhci->skel_fs_control_qh->link = UHCI_PTR_QH |
++ cpu_to_le32(uhci->skel_bulk_qh->dma_handle);
++ uhci->skel_bulk_qh->link = UHCI_PTR_QH |
++ cpu_to_le32(uhci->skel_term_qh->dma_handle);
+
+ /* This dummy TD is to work around a bug in Intel PIIX controllers */
+ uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
+@@ -589,15 +589,15 @@ static int uhci_start(struct usb_hcd *hc
+
+ /*
+ * ffs (Find First bit Set) does exactly what we need:
+- * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[6],
+- * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[5], etc.
+- * ffs > 6 => not on any high-period queue, so use
+- * skel_int1_qh = skelqh[7].
++ * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[8],
++ * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc.
++ * ffs >= 7 => not on any high-period queue, so use
++ * skel_int1_qh = skelqh[9].
+ * Add UHCI_NUMFRAMES to insure at least one bit is set.
+ */
+- irq = 6 - (int) __ffs(i + UHCI_NUMFRAMES);
+- if (irq < 0)
+- irq = 7;
++ irq = 8 - (int) __ffs(i + UHCI_NUMFRAMES);
++ if (irq <= 1)
++ irq = 9;
+
+ /* Only place we don't use the frame list routines */
+ uhci->frame[i] = UHCI_PTR_QH |
+@@ -767,13 +767,30 @@ static int uhci_resume(struct usb_hcd *h
+ }
+ #endif
+
+-/* Wait until all the URBs for a particular device/endpoint are gone */
++/* Wait until a particular device/endpoint's QH is idle, and free it */
+ static void uhci_hcd_endpoint_disable(struct usb_hcd *hcd,
+- struct usb_host_endpoint *ep)
++ struct usb_host_endpoint *hep)
+ {
+ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
++ struct uhci_qh *qh;
++
++ spin_lock_irq(&uhci->lock);
++ qh = (struct uhci_qh *) hep->hcpriv;
++ if (qh == NULL)
++ goto done;
+
+- wait_event_interruptible(uhci->waitqh, list_empty(&ep->urb_list));
++ while (qh->state != QH_STATE_IDLE) {
++ ++uhci->num_waiting;
++ spin_unlock_irq(&uhci->lock);
++ wait_event_interruptible(uhci->waitqh,
++ qh->state == QH_STATE_IDLE);
++ spin_lock_irq(&uhci->lock);
++ --uhci->num_waiting;
++ }
++
++ uhci_free_qh(uhci, qh);
++done:
++ spin_unlock_irq(&uhci->lock);
+ }
+
+ static int uhci_hcd_get_frame_number(struct usb_hcd *hcd)
--- gregkh-2.6.orig/drivers/usb/host/uhci-hcd.h
+++ gregkh-2.6/drivers/usb/host/uhci-hcd.h
@@ -28,8 +28,9 @@
@@ -1853,545 +2395,3 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
}
static void check_fsbr(struct uhci_hcd *uhci)
---- gregkh-2.6.orig/drivers/usb/host/uhci-hcd.c
-+++ gregkh-2.6/drivers/usb/host/uhci-hcd.c
-@@ -54,7 +54,7 @@
- /*
- * Version Information
- */
--#define DRIVER_VERSION "v2.3"
-+#define DRIVER_VERSION "v3.0"
- #define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \
- Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \
- Alan Stern"
-@@ -489,15 +489,11 @@ static int uhci_start(struct usb_hcd *hc
- uhci->fsbrtimeout = 0;
-
- spin_lock_init(&uhci->lock);
-- INIT_LIST_HEAD(&uhci->qh_remove_list);
-
- INIT_LIST_HEAD(&uhci->td_remove_list);
--
-- INIT_LIST_HEAD(&uhci->urb_remove_list);
--
- INIT_LIST_HEAD(&uhci->urb_list);
--
- INIT_LIST_HEAD(&uhci->complete_list);
-+ INIT_LIST_HEAD(&uhci->idle_qh_list);
-
- init_waitqueue_head(&uhci->waitqh);
-
-@@ -540,7 +536,7 @@ static int uhci_start(struct usb_hcd *hc
- }
-
- for (i = 0; i < UHCI_NUM_SKELQH; i++) {
-- uhci->skelqh[i] = uhci_alloc_qh(uhci);
-+ uhci->skelqh[i] = uhci_alloc_qh(uhci, NULL, NULL);
- if (!uhci->skelqh[i]) {
- dev_err(uhci_dev(uhci), "unable to allocate QH\n");
- goto err_alloc_skelqh;
-@@ -557,13 +553,17 @@ static int uhci_start(struct usb_hcd *hc
- uhci->skel_int16_qh->link =
- uhci->skel_int8_qh->link =
- uhci->skel_int4_qh->link =
-- uhci->skel_int2_qh->link =
-- cpu_to_le32(uhci->skel_int1_qh->dma_handle) | UHCI_PTR_QH;
-- uhci->skel_int1_qh->link = cpu_to_le32(uhci->skel_ls_control_qh->dma_handle) | UHCI_PTR_QH;
--
-- uhci->skel_ls_control_qh->link = cpu_to_le32(uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH;
-- uhci->skel_fs_control_qh->link = cpu_to_le32(uhci->skel_bulk_qh->dma_handle) | UHCI_PTR_QH;
-- uhci->skel_bulk_qh->link = cpu_to_le32(uhci->skel_term_qh->dma_handle) | UHCI_PTR_QH;
-+ uhci->skel_int2_qh->link = UHCI_PTR_QH |
-+ cpu_to_le32(uhci->skel_int1_qh->dma_handle);
-+
-+ uhci->skel_int1_qh->link = UHCI_PTR_QH |
-+ cpu_to_le32(uhci->skel_ls_control_qh->dma_handle);
-+ uhci->skel_ls_control_qh->link = UHCI_PTR_QH |
-+ cpu_to_le32(uhci->skel_fs_control_qh->dma_handle);
-+ uhci->skel_fs_control_qh->link = UHCI_PTR_QH |
-+ cpu_to_le32(uhci->skel_bulk_qh->dma_handle);
-+ uhci->skel_bulk_qh->link = UHCI_PTR_QH |
-+ cpu_to_le32(uhci->skel_term_qh->dma_handle);
-
- /* This dummy TD is to work around a bug in Intel PIIX controllers */
- uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
-@@ -589,15 +589,15 @@ static int uhci_start(struct usb_hcd *hc
-
- /*
- * ffs (Find First bit Set) does exactly what we need:
-- * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[6],
-- * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[5], etc.
-- * ffs > 6 => not on any high-period queue, so use
-- * skel_int1_qh = skelqh[7].
-+ * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[8],
-+ * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc.
-+ * ffs >= 7 => not on any high-period queue, so use
-+ * skel_int1_qh = skelqh[9].
- * Add UHCI_NUMFRAMES to insure at least one bit is set.
- */
-- irq = 6 - (int) __ffs(i + UHCI_NUMFRAMES);
-- if (irq < 0)
-- irq = 7;
-+ irq = 8 - (int) __ffs(i + UHCI_NUMFRAMES);
-+ if (irq <= 1)
-+ irq = 9;
-
- /* Only place we don't use the frame list routines */
- uhci->frame[i] = UHCI_PTR_QH |
-@@ -767,13 +767,30 @@ static int uhci_resume(struct usb_hcd *h
- }
- #endif
-
--/* Wait until all the URBs for a particular device/endpoint are gone */
-+/* Wait until a particular device/endpoint's QH is idle, and free it */
- static void uhci_hcd_endpoint_disable(struct usb_hcd *hcd,
-- struct usb_host_endpoint *ep)
-+ struct usb_host_endpoint *hep)
- {
- struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-+ struct uhci_qh *qh;
-+
-+ spin_lock_irq(&uhci->lock);
-+ qh = (struct uhci_qh *) hep->hcpriv;
-+ if (qh == NULL)
-+ goto done;
-
-- wait_event_interruptible(uhci->waitqh, list_empty(&ep->urb_list));
-+ while (qh->state != QH_STATE_IDLE) {
-+ ++uhci->num_waiting;
-+ spin_unlock_irq(&uhci->lock);
-+ wait_event_interruptible(uhci->waitqh,
-+ qh->state == QH_STATE_IDLE);
-+ spin_lock_irq(&uhci->lock);
-+ --uhci->num_waiting;
-+ }
-+
-+ uhci_free_qh(uhci, qh);
-+done:
-+ spin_unlock_irq(&uhci->lock);
- }
-
- static int uhci_hcd_get_frame_number(struct usb_hcd *hcd)
---- gregkh-2.6.orig/drivers/usb/host/uhci-debug.c
-+++ gregkh-2.6/drivers/usb/host/uhci-debug.c
-@@ -90,13 +90,60 @@ static int uhci_show_td(struct uhci_td *
- return out - buf;
- }
-
--static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
-+static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space)
- {
- char *out = buf;
-- struct urb_priv *urbp;
-- struct list_head *head, *tmp;
- struct uhci_td *td;
-- int i = 0, checked = 0, prevactive = 0;
-+ int i, nactive, ninactive;
-+
-+ if (len < 200)
-+ return 0;
-+
-+ out += sprintf(out, "urb_priv [%p] ", urbp);
-+ out += sprintf(out, "urb [%p] ", urbp->urb);
-+ out += sprintf(out, "qh [%p] ", urbp->qh);
-+ out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe));
-+ out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe),
-+ (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT"));
-+
-+ switch (usb_pipetype(urbp->urb->pipe)) {
-+ case PIPE_ISOCHRONOUS: out += sprintf(out, "ISO"); break;
-+ case PIPE_INTERRUPT: out += sprintf(out, "INT"); break;
-+ case PIPE_BULK: out += sprintf(out, "BLK"); break;
-+ case PIPE_CONTROL: out += sprintf(out, "CTL"); break;
-+ }
-+
-+ out += sprintf(out, "%s", (urbp->fsbr ? " FSBR" : ""));
-+ out += sprintf(out, "%s", (urbp->fsbr_timeout ? " FSBR_TO" : ""));
-+
-+ if (urbp->urb->status != -EINPROGRESS)
-+ out += sprintf(out, " Status=%d", urbp->urb->status);
-+ out += sprintf(out, "\n");
-+
-+ i = nactive = ninactive = 0;
-+ list_for_each_entry(td, &urbp->td_list, list) {
-+ if (++i <= 10 || debug > 2) {
-+ out += sprintf(out, "%*s%d: ", space + 2, "", i);
-+ out += uhci_show_td(td, out, len - (out - buf), 0);
-+ } else {
-+ if (td_status(td) & TD_CTRL_ACTIVE)
-+ ++nactive;
-+ else
-+ ++ninactive;
-+ }
-+ }
-+ if (nactive + ninactive > 0)
-+ out += sprintf(out, "%*s[skipped %d inactive and %d active "
-+ "TDs]\n",
-+ space, "", ninactive, nactive);
-+
-+ return out - buf;
-+}
-+
-+static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
-+{
-+ char *out = buf;
-+ int i, nurbs;
- __le32 element = qh_element(qh);
-
- /* Try to make sure there's enough memory */
-@@ -118,86 +165,36 @@ static int uhci_show_qh(struct uhci_qh *
- if (!(element & ~(UHCI_PTR_QH | UHCI_PTR_DEPTH)))
- out += sprintf(out, "%*s Element is NULL (bug?)\n", space, "");
-
-- if (!qh->urbp) {
-- out += sprintf(out, "%*s urbp == NULL\n", space, "");
-- goto out;
-- }
--
-- urbp = qh->urbp;
--
-- head = &urbp->td_list;
-- tmp = head->next;
--
-- td = list_entry(tmp, struct uhci_td, list);
--
-- if (cpu_to_le32(td->dma_handle) != (element & ~UHCI_PTR_BITS))
-- out += sprintf(out, "%*s Element != First TD\n", space, "");
--
-- while (tmp != head) {
-- struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
--
-- tmp = tmp->next;
--
-- out += sprintf(out, "%*s%d: ", space + 2, "", i++);
-- out += uhci_show_td(td, out, len - (out - buf), 0);
--
-- if (i > 10 && !checked && prevactive && tmp != head &&
-- debug <= 2) {
-- struct list_head *ntmp = tmp;
-- struct uhci_td *ntd = td;
-- int active = 1, ni = i;
--
-- checked = 1;
--
-- while (ntmp != head && ntmp->next != head && active) {
-- ntd = list_entry(ntmp, struct uhci_td, list);
--
-- ntmp = ntmp->next;
--
-- active = td_status(ntd) & TD_CTRL_ACTIVE;
--
-- ni++;
-- }
--
-- if (active && ni > i) {
-- out += sprintf(out, "%*s[skipped %d active TDs]\n", space, "", ni - i);
-- tmp = ntmp;
-- td = ntd;
-- i = ni;
-- }
-+ if (list_empty(&qh->queue)) {
-+ out += sprintf(out, "%*s queue is empty\n", space, "");
-+ } else {
-+ struct urb_priv *urbp = list_entry(qh->queue.next,
-+ struct urb_priv, node);
-+ struct uhci_td *td = list_entry(urbp->td_list.next,
-+ struct uhci_td, list);
-+
-+ if (cpu_to_le32(td->dma_handle) != (element & ~UHCI_PTR_BITS))
-+ out += sprintf(out, "%*s Element != First TD\n",
-+ space, "");
-+ i = nurbs = 0;
-+ list_for_each_entry(urbp, &qh->queue, node) {
-+ if (++i <= 10)
-+ out += uhci_show_urbp(urbp, out,
-+ len - (out - buf), space + 2);
-+ else
-+ ++nurbs;
- }
--
-- prevactive = td_status(td) & TD_CTRL_ACTIVE;
-- }
--
-- if (list_empty(&urbp->queue_list) || urbp->queued)
-- goto out;
--
-- out += sprintf(out, "%*sQueued QHs:\n", -space, "--");
--
-- head = &urbp->queue_list;
-- tmp = head->next;
--
-- while (tmp != head) {
-- struct urb_priv *nurbp = list_entry(tmp, struct urb_priv,
-- queue_list);
-- tmp = tmp->next;
--
-- out += uhci_show_qh(nurbp->qh, out, len - (out - buf), space);
-+ if (nurbs > 0)
-+ out += sprintf(out, "%*s Skipped %d URBs\n",
-+ space, "", nurbs);
- }
-
--out:
- return out - buf;
- }
-
--#define show_frame_num() \
-- if (!shown) { \
-- shown = 1; \
-- out += sprintf(out, "- Frame %d\n", i); \
-- }
--
- #ifdef CONFIG_PROC_FS
- static const char * const qh_names[] = {
-+ "skel_unlink_qh", "skel_iso_qh",
- "skel_int128_qh", "skel_int64_qh",
- "skel_int32_qh", "skel_int16_qh",
- "skel_int8_qh", "skel_int4_qh",
-@@ -206,12 +203,6 @@ static const char * const qh_names[] = {
- "skel_bulk_qh", "skel_term_qh"
- };
-
--#define show_qh_name() \
-- if (!shown) { \
-- shown = 1; \
-- out += sprintf(out, "- %s\n", qh_names[i]); \
-- }
--
- static int uhci_show_sc(int port, unsigned short status, char *buf, int len)
- {
- char *out = buf;
-@@ -321,139 +312,29 @@ static int uhci_show_status(struct uhci_
- return out - buf;
- }
-
--static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, char *buf, int len)
--{
-- struct list_head *tmp;
-- char *out = buf;
-- int count = 0;
--
-- if (len < 200)
-- return 0;
--
-- out += sprintf(out, "urb_priv [%p] ", urbp);
-- out += sprintf(out, "urb [%p] ", urbp->urb);
-- out += sprintf(out, "qh [%p] ", urbp->qh);
-- out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe));
-- out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe), (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT"));
--
-- switch (usb_pipetype(urbp->urb->pipe)) {
-- case PIPE_ISOCHRONOUS: out += sprintf(out, "ISO "); break;
-- case PIPE_INTERRUPT: out += sprintf(out, "INT "); break;
-- case PIPE_BULK: out += sprintf(out, "BLK "); break;
-- case PIPE_CONTROL: out += sprintf(out, "CTL "); break;
-- }
--
-- out += sprintf(out, "%s", (urbp->fsbr ? "FSBR " : ""));
-- out += sprintf(out, "%s", (urbp->fsbr_timeout ? "FSBR_TO " : ""));
--
-- if (urbp->urb->status != -EINPROGRESS)
-- out += sprintf(out, "Status=%d ", urbp->urb->status);
-- //out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime);
--
-- count = 0;
-- list_for_each(tmp, &urbp->td_list)
-- count++;
-- out += sprintf(out, "TDs=%d ",count);
--
-- if (urbp->queued)
-- out += sprintf(out, "queued\n");
-- else {
-- count = 0;
-- list_for_each(tmp, &urbp->queue_list)
-- count++;
-- out += sprintf(out, "queued URBs=%d\n", count);
-- }
--
-- return out - buf;
--}
--
--static int uhci_show_lists(struct uhci_hcd *uhci, char *buf, int len)
--{
-- char *out = buf;
-- struct list_head *head, *tmp;
-- int count;
--
-- out += sprintf(out, "Main list URBs:");
-- if (list_empty(&uhci->urb_list))
-- out += sprintf(out, " Empty\n");
-- else {
-- out += sprintf(out, "\n");
-- count = 0;
-- head = &uhci->urb_list;
-- tmp = head->next;
-- while (tmp != head) {
-- struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
--
-- out += sprintf(out, " %d: ", ++count);
-- out += uhci_show_urbp(uhci, urbp, out, len - (out - buf));
-- tmp = tmp->next;
-- }
-- }
--
-- out += sprintf(out, "Remove list URBs:");
-- if (list_empty(&uhci->urb_remove_list))
-- out += sprintf(out, " Empty\n");
-- else {
-- out += sprintf(out, "\n");
-- count = 0;
-- head = &uhci->urb_remove_list;
-- tmp = head->next;
-- while (tmp != head) {
-- struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
--
-- out += sprintf(out, " %d: ", ++count);
-- out += uhci_show_urbp(uhci, urbp, out, len - (out - buf));
-- tmp = tmp->next;
-- }
-- }
--
-- out += sprintf(out, "Complete list URBs:");
-- if (list_empty(&uhci->complete_list))
-- out += sprintf(out, " Empty\n");
-- else {
-- out += sprintf(out, "\n");
-- count = 0;
-- head = &uhci->complete_list;
-- tmp = head->next;
-- while (tmp != head) {
-- struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
--
-- out += sprintf(out, " %d: ", ++count);
-- out += uhci_show_urbp(uhci, urbp, out, len - (out - buf));
-- tmp = tmp->next;
-- }
-- }
--
-- return out - buf;
--}
--
- static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
- {
-- unsigned long flags;
- char *out = buf;
- int i, j;
- struct uhci_qh *qh;
- struct uhci_td *td;
- struct list_head *tmp, *head;
-
-- spin_lock_irqsave(&uhci->lock, flags);
--
- out += uhci_show_root_hub_state(uhci, out, len - (out - buf));
- out += sprintf(out, "HC status\n");
- out += uhci_show_status(uhci, out, len - (out - buf));
-+ if (debug <= 1)
-+ return out - buf;
-
- out += sprintf(out, "Frame List\n");
- for (i = 0; i < UHCI_NUMFRAMES; ++i) {
-- int shown = 0;
- td = uhci->frame_cpu[i];
- if (!td)
- continue;
-
-- if (td->dma_handle != (dma_addr_t)uhci->frame[i]) {
-- show_frame_num();
-+ out += sprintf(out, "- Frame %d\n", i); \
-+ if (td->dma_handle != (dma_addr_t)uhci->frame[i])
- out += sprintf(out, " frame list does not match td->dma_handle!\n");
-- }
-- show_frame_num();
-
- head = &td->fl_list;
- tmp = head;
-@@ -467,14 +348,11 @@ static int uhci_sprint_schedule(struct u
- out += sprintf(out, "Skeleton QHs\n");
-
- for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
-- int shown = 0;
-+ int cnt = 0;
-
- qh = uhci->skelqh[i];
--
-- if (debug > 1) {
-- show_qh_name();
-- out += uhci_show_qh(qh, out, len - (out - buf), 4);
-- }
-+ out += sprintf(out, "- %s\n", qh_names[i]); \
-+ out += uhci_show_qh(qh, out, len - (out - buf), 4);
-
- /* Last QH is the Terminating QH, it's different */
- if (i == UHCI_NUM_SKELQH - 1) {
-@@ -487,44 +365,27 @@ static int uhci_sprint_schedule(struct u
- continue;
- }
-
-- j = (i < 7) ? 7 : i+1; /* Next skeleton */
-- if (list_empty(&qh->list)) {
-- if (i < UHCI_NUM_SKELQH - 1) {
-- if (qh->link !=
-- (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH)) {
-- show_qh_name();
-- out += sprintf(out, " skeleton QH not linked to next skeleton QH!\n");
-- }
-- }
--
-- continue;
-- }
--
-- show_qh_name();
--
-- head = &qh->list;
-+ j = (i < 9) ? 9 : i+1; /* Next skeleton */
-+ head = &qh->node;
- tmp = head->next;
-
- while (tmp != head) {
-- qh = list_entry(tmp, struct uhci_qh, list);
--
-+ qh = list_entry(tmp, struct uhci_qh, node);
- tmp = tmp->next;
--
-- out += uhci_show_qh(qh, out, len - (out - buf), 4);
-+ if (++cnt <= 10)
-+ out += uhci_show_qh(qh, out,
-+ len - (out - buf), 4);
- }
-+ if ((cnt -= 10) > 0)
-+ out += sprintf(out, " Skipped %d QHs\n", cnt);
-
-- if (i < UHCI_NUM_SKELQH - 1) {
-+ if (i > 1 && i < UHCI_NUM_SKELQH - 1) {
- if (qh->link !=
- (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH))
- out += sprintf(out, " last QH not linked to next skeleton!\n");
- }
- }
-
-- if (debug > 2)
-- out += uhci_show_lists(uhci, out, len - (out - buf));
--
-- spin_unlock_irqrestore(&uhci->lock, flags);
--
- return out - buf;
- }
-
-@@ -541,6 +402,7 @@ static int uhci_debug_open(struct inode
- struct uhci_hcd *uhci = inode->u.generic_ip;
- struct uhci_debug *up;
- int ret = -ENOMEM;
-+ unsigned long flags;
-
- lock_kernel();
- up = kmalloc(sizeof(*up), GFP_KERNEL);
-@@ -553,7 +415,9 @@ static int uhci_debug_open(struct inode
- goto out;
- }
-
-+ spin_lock_irqsave(&uhci->lock, flags);
- up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);
-+ spin_unlock_irqrestore(&uhci->lock, flags);
-
- file->private_data = up;
-
diff --git a/usb/usb-add-zc0301-video4linux2-driver.patch b/usb/usb-add-zc0301-video4linux2-driver.patch
index a128cdb3ca88f..3e395f248ee79 100644
--- a/usb/usb-add-zc0301-video4linux2-driver.patch
+++ b/usb/usb-add-zc0301-video4linux2-driver.patch
@@ -278,6 +278,23 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+- Initialization values of the ZC0301 connected to the PAS202BCB image sensor
+ have been taken from the SPCA5XX driver maintained by
+ Michel Xhaard <mxhaard@magic.fr>
+--- gregkh-2.6.orig/MAINTAINERS
++++ gregkh-2.6/MAINTAINERS
+@@ -2901,6 +2901,14 @@ L: video4linux-list@redhat.com
+ W: http://www.linux-projects.org
+ S: Maintained
+
++USB ZC0301 DRIVER
++P: Luca Risolia
++M: luca.risolia@studio.unibo.it
++L: linux-usb-devel@lists.sourceforge.net
++L: video4linux-list@redhat.com
++W: http://www.linux-projects.org
++S: Maintained
++
+ USB ZD1201 DRIVER
+ P: Jeroen Vreeken
+ M: pe1rxq@amsat.org
--- gregkh-2.6.orig/drivers/usb/Makefile
+++ gregkh-2.6/drivers/usb/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_USB_SN9C102) += media/
@@ -329,6 +346,194 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+obj-$(CONFIG_USB_ZC0301) += zc0301.o
obj-$(CONFIG_USB_PWC) += pwc/
--- /dev/null
++++ gregkh-2.6/drivers/usb/media/zc0301.h
+@@ -0,0 +1,185 @@
++/***************************************************************************
++ * V4L2 driver for ZC0301 Image Processor and Control Chip *
++ * *
++ * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
++ * *
++ * This program is free software; you can redistribute it and/or modify *
++ * it under the terms of the GNU General Public License as published by *
++ * the Free Software Foundation; either version 2 of the License, or *
++ * (at your option) any later version. *
++ * *
++ * This program is distributed in the hope that it will be useful, *
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
++ * GNU General Public License for more details. *
++ * *
++ * You should have received a copy of the GNU General Public License *
++ * along with this program; if not, write to the Free Software *
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
++ ***************************************************************************/
++
++#ifndef _ZC0301_H_
++#define _ZC0301_H_
++
++#include <linux/version.h>
++#include <linux/usb.h>
++#include <linux/videodev2.h>
++#include <media/v4l2-common.h>
++#include <linux/device.h>
++#include <linux/list.h>
++#include <linux/spinlock.h>
++#include <linux/time.h>
++#include <linux/wait.h>
++#include <linux/types.h>
++#include <linux/param.h>
++#include <linux/mutex.h>
++#include <linux/rwsem.h>
++#include <asm/semaphore.h>
++
++#include "zc0301_sensor.h"
++
++/*****************************************************************************/
++
++#define ZC0301_DEBUG
++#define ZC0301_DEBUG_LEVEL 2
++#define ZC0301_MAX_DEVICES 64
++#define ZC0301_FORCE_MUNMAP 0
++#define ZC0301_MAX_FRAMES 32
++#define ZC0301_COMPRESSION_QUALITY 2
++#define ZC0301_URBS 2
++#define ZC0301_ISO_PACKETS 7
++#define ZC0301_ALTERNATE_SETTING 7
++#define ZC0301_URB_TIMEOUT msecs_to_jiffies(2 * ZC0301_ISO_PACKETS)
++#define ZC0301_CTRL_TIMEOUT 100
++#define ZC0301_FRAME_TIMEOUT 2 * 1000 * msecs_to_jiffies(1)
++
++/*****************************************************************************/
++
++ZC0301_ID_TABLE
++ZC0301_SENSOR_TABLE
++
++enum zc0301_frame_state {
++ F_UNUSED,
++ F_QUEUED,
++ F_GRABBING,
++ F_DONE,
++ F_ERROR,
++};
++
++struct zc0301_frame_t {
++ void* bufmem;
++ struct v4l2_buffer buf;
++ enum zc0301_frame_state state;
++ struct list_head frame;
++ unsigned long vma_use_count;
++};
++
++enum zc0301_dev_state {
++ DEV_INITIALIZED = 0x01,
++ DEV_DISCONNECTED = 0x02,
++ DEV_MISCONFIGURED = 0x04,
++};
++
++enum zc0301_io_method {
++ IO_NONE,
++ IO_READ,
++ IO_MMAP,
++};
++
++enum zc0301_stream_state {
++ STREAM_OFF,
++ STREAM_INTERRUPT,
++ STREAM_ON,
++};
++
++struct zc0301_module_param {
++ u8 force_munmap;
++};
++
++static DECLARE_RWSEM(zc0301_disconnect);
++
++struct zc0301_device {
++ struct video_device* v4ldev;
++
++ struct zc0301_sensor* sensor;
++
++ struct usb_device* usbdev;
++ struct urb* urb[ZC0301_URBS];
++ void* transfer_buffer[ZC0301_URBS];
++ u8* control_buffer;
++
++ struct zc0301_frame_t *frame_current, frame[ZC0301_MAX_FRAMES];
++ struct list_head inqueue, outqueue;
++ u32 frame_count, nbuffers, nreadbuffers;
++
++ enum zc0301_io_method io;
++ enum zc0301_stream_state stream;
++
++ struct v4l2_jpegcompression compression;
++
++ struct zc0301_module_param module_param;
++
++ enum zc0301_dev_state state;
++ u8 users;
++
++ struct mutex dev_mutex, fileop_mutex;
++ spinlock_t queue_lock;
++ wait_queue_head_t open, wait_frame, wait_stream;
++};
++
++/*****************************************************************************/
++
++void
++zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor)
++{
++ cam->sensor = sensor;
++ cam->sensor->usbdev = cam->usbdev;
++}
++
++/*****************************************************************************/
++
++#undef DBG
++#undef KDBG
++#ifdef ZC0301_DEBUG
++# define DBG(level, fmt, args...) \
++do { \
++ if (debug >= (level)) { \
++ if ((level) == 1) \
++ dev_err(&cam->usbdev->dev, fmt "\n", ## args); \
++ else if ((level) == 2) \
++ dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
++ else if ((level) >= 3) \
++ dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
++ __FUNCTION__, __LINE__ , ## args); \
++ } \
++} while (0)
++# define KDBG(level, fmt, args...) \
++do { \
++ if (debug >= (level)) { \
++ if ((level) == 1 || (level) == 2) \
++ pr_info("zc0301: " fmt "\n", ## args); \
++ else if ((level) == 3) \
++ pr_debug("zc0301: [%s:%d] " fmt "\n", __FUNCTION__, \
++ __LINE__ , ## args); \
++ } \
++} while (0)
++# define V4LDBG(level, name, cmd) \
++do { \
++ if (debug >= (level)) \
++ v4l_print_ioctl(name, cmd); \
++} while (0)
++#else
++# define DBG(level, fmt, args...) do {;} while(0)
++# define KDBG(level, fmt, args...) do {;} while(0)
++# define V4LDBG(level, name, cmd) do {;} while(0)
++#endif
++
++#undef PDBG
++#define PDBG(fmt, args...) \
++dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
++ __FUNCTION__, __LINE__ , ## args)
++
++#undef PDBGG
++#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
++
++#endif /* _ZC0301_H_ */
+--- /dev/null
+++ gregkh-2.6/drivers/usb/media/zc0301_core.c
@@ -0,0 +1,2028 @@
+/***************************************************************************
@@ -2360,194 +2565,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+module_init(zc0301_module_init);
+module_exit(zc0301_module_exit);
--- /dev/null
-+++ gregkh-2.6/drivers/usb/media/zc0301.h
-@@ -0,0 +1,185 @@
-+/***************************************************************************
-+ * V4L2 driver for ZC0301 Image Processor and Control Chip *
-+ * *
-+ * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
-+ * *
-+ * This program is free software; you can redistribute it and/or modify *
-+ * it under the terms of the GNU General Public License as published by *
-+ * the Free Software Foundation; either version 2 of the License, or *
-+ * (at your option) any later version. *
-+ * *
-+ * This program is distributed in the hope that it will be useful, *
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
-+ * GNU General Public License for more details. *
-+ * *
-+ * You should have received a copy of the GNU General Public License *
-+ * along with this program; if not, write to the Free Software *
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
-+ ***************************************************************************/
-+
-+#ifndef _ZC0301_H_
-+#define _ZC0301_H_
-+
-+#include <linux/version.h>
-+#include <linux/usb.h>
-+#include <linux/videodev2.h>
-+#include <media/v4l2-common.h>
-+#include <linux/device.h>
-+#include <linux/list.h>
-+#include <linux/spinlock.h>
-+#include <linux/time.h>
-+#include <linux/wait.h>
-+#include <linux/types.h>
-+#include <linux/param.h>
-+#include <linux/mutex.h>
-+#include <linux/rwsem.h>
-+#include <asm/semaphore.h>
-+
-+#include "zc0301_sensor.h"
-+
-+/*****************************************************************************/
-+
-+#define ZC0301_DEBUG
-+#define ZC0301_DEBUG_LEVEL 2
-+#define ZC0301_MAX_DEVICES 64
-+#define ZC0301_FORCE_MUNMAP 0
-+#define ZC0301_MAX_FRAMES 32
-+#define ZC0301_COMPRESSION_QUALITY 2
-+#define ZC0301_URBS 2
-+#define ZC0301_ISO_PACKETS 7
-+#define ZC0301_ALTERNATE_SETTING 7
-+#define ZC0301_URB_TIMEOUT msecs_to_jiffies(2 * ZC0301_ISO_PACKETS)
-+#define ZC0301_CTRL_TIMEOUT 100
-+#define ZC0301_FRAME_TIMEOUT 2 * 1000 * msecs_to_jiffies(1)
-+
-+/*****************************************************************************/
-+
-+ZC0301_ID_TABLE
-+ZC0301_SENSOR_TABLE
-+
-+enum zc0301_frame_state {
-+ F_UNUSED,
-+ F_QUEUED,
-+ F_GRABBING,
-+ F_DONE,
-+ F_ERROR,
-+};
-+
-+struct zc0301_frame_t {
-+ void* bufmem;
-+ struct v4l2_buffer buf;
-+ enum zc0301_frame_state state;
-+ struct list_head frame;
-+ unsigned long vma_use_count;
-+};
-+
-+enum zc0301_dev_state {
-+ DEV_INITIALIZED = 0x01,
-+ DEV_DISCONNECTED = 0x02,
-+ DEV_MISCONFIGURED = 0x04,
-+};
-+
-+enum zc0301_io_method {
-+ IO_NONE,
-+ IO_READ,
-+ IO_MMAP,
-+};
-+
-+enum zc0301_stream_state {
-+ STREAM_OFF,
-+ STREAM_INTERRUPT,
-+ STREAM_ON,
-+};
-+
-+struct zc0301_module_param {
-+ u8 force_munmap;
-+};
-+
-+static DECLARE_RWSEM(zc0301_disconnect);
-+
-+struct zc0301_device {
-+ struct video_device* v4ldev;
-+
-+ struct zc0301_sensor* sensor;
-+
-+ struct usb_device* usbdev;
-+ struct urb* urb[ZC0301_URBS];
-+ void* transfer_buffer[ZC0301_URBS];
-+ u8* control_buffer;
-+
-+ struct zc0301_frame_t *frame_current, frame[ZC0301_MAX_FRAMES];
-+ struct list_head inqueue, outqueue;
-+ u32 frame_count, nbuffers, nreadbuffers;
-+
-+ enum zc0301_io_method io;
-+ enum zc0301_stream_state stream;
-+
-+ struct v4l2_jpegcompression compression;
-+
-+ struct zc0301_module_param module_param;
-+
-+ enum zc0301_dev_state state;
-+ u8 users;
-+
-+ struct mutex dev_mutex, fileop_mutex;
-+ spinlock_t queue_lock;
-+ wait_queue_head_t open, wait_frame, wait_stream;
-+};
-+
-+/*****************************************************************************/
-+
-+void
-+zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor)
-+{
-+ cam->sensor = sensor;
-+ cam->sensor->usbdev = cam->usbdev;
-+}
-+
-+/*****************************************************************************/
-+
-+#undef DBG
-+#undef KDBG
-+#ifdef ZC0301_DEBUG
-+# define DBG(level, fmt, args...) \
-+do { \
-+ if (debug >= (level)) { \
-+ if ((level) == 1) \
-+ dev_err(&cam->usbdev->dev, fmt "\n", ## args); \
-+ else if ((level) == 2) \
-+ dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
-+ else if ((level) >= 3) \
-+ dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
-+ __FUNCTION__, __LINE__ , ## args); \
-+ } \
-+} while (0)
-+# define KDBG(level, fmt, args...) \
-+do { \
-+ if (debug >= (level)) { \
-+ if ((level) == 1 || (level) == 2) \
-+ pr_info("zc0301: " fmt "\n", ## args); \
-+ else if ((level) == 3) \
-+ pr_debug("zc0301: [%s:%d] " fmt "\n", __FUNCTION__, \
-+ __LINE__ , ## args); \
-+ } \
-+} while (0)
-+# define V4LDBG(level, name, cmd) \
-+do { \
-+ if (debug >= (level)) \
-+ v4l_print_ioctl(name, cmd); \
-+} while (0)
-+#else
-+# define DBG(level, fmt, args...) do {;} while(0)
-+# define KDBG(level, fmt, args...) do {;} while(0)
-+# define V4LDBG(level, name, cmd) do {;} while(0)
-+#endif
-+
-+#undef PDBG
-+#define PDBG(fmt, args...) \
-+dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
-+ __FUNCTION__, __LINE__ , ## args)
-+
-+#undef PDBGG
-+#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
-+
-+#endif /* _ZC0301_H_ */
---- /dev/null
+++ gregkh-2.6/drivers/usb/media/zc0301_pas202bcb.c
@@ -0,0 +1,353 @@
+/***************************************************************************
@@ -3004,20 +3021,3 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+};
+
+#endif /* _ZC0301_SENSOR_H_ */
---- gregkh-2.6.orig/MAINTAINERS
-+++ gregkh-2.6/MAINTAINERS
-@@ -2901,6 +2901,14 @@ L: video4linux-list@redhat.com
- W: http://www.linux-projects.org
- S: Maintained
-
-+USB ZC0301 DRIVER
-+P: Luca Risolia
-+M: luca.risolia@studio.unibo.it
-+L: linux-usb-devel@lists.sourceforge.net
-+L: video4linux-list@redhat.com
-+W: http://www.linux-projects.org
-+S: Maintained
-+
- USB ZD1201 DRIVER
- P: Jeroen Vreeken
- M: pe1rxq@amsat.org
diff --git a/usb/usb-convert-a-bunch-of-usb-semaphores-to-mutexes.patch b/usb/usb-convert-a-bunch-of-usb-semaphores-to-mutexes.patch
index 0cf38c189acb6..2df571a82b2fa 100644
--- a/usb/usb-convert-a-bunch-of-usb-semaphores-to-mutexes.patch
+++ b/usb/usb-convert-a-bunch-of-usb-semaphores-to-mutexes.patch
@@ -212,511 +212,38 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
}
static struct usb_device_id usblp_ids [] = {
---- gregkh-2.6.orig/drivers/usb/core/hub.c
-+++ gregkh-2.6/drivers/usb/core/hub.c
-@@ -22,6 +22,7 @@
+--- gregkh-2.6.orig/drivers/usb/core/devices.c
++++ gregkh-2.6/drivers/usb/core/devices.c
+@@ -57,6 +57,7 @@
#include <linux/usb.h>
+ #include <linux/smp_lock.h>
#include <linux/usbdevice_fs.h>
- #include <linux/kthread.h>
+#include <linux/mutex.h>
-
- #include <asm/semaphore.h>
#include <asm/uaccess.h>
-@@ -2162,7 +2163,7 @@ static int
- hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
- int retry_counter)
- {
-- static DECLARE_MUTEX(usb_address0_sem);
-+ static DEFINE_MUTEX(usb_address0_mutex);
-
- struct usb_device *hdev = hub->hdev;
- int i, j, retval;
-@@ -2183,7 +2184,7 @@ hub_port_init (struct usb_hub *hub, stru
- if (oldspeed == USB_SPEED_LOW)
- delay = HUB_LONG_RESET_TIME;
-
-- down(&usb_address0_sem);
-+ mutex_lock(&usb_address0_mutex);
-
- /* Reset the device; full speed may morph to high speed */
- retval = hub_port_reset(hub, port1, udev, delay);
-@@ -2381,7 +2382,7 @@ hub_port_init (struct usb_hub *hub, stru
- fail:
- if (retval)
- hub_port_disable(hub, port1, 0);
-- up(&usb_address0_sem);
-+ mutex_unlock(&usb_address0_mutex);
- return retval;
- }
---- gregkh-2.6.orig/drivers/usb/core/notify.c
-+++ gregkh-2.6/drivers/usb/core/notify.c
-@@ -13,16 +13,17 @@
- #include <linux/kernel.h>
- #include <linux/notifier.h>
- #include <linux/usb.h>
-+#include <linux/mutex.h>
#include "usb.h"
+@@ -570,7 +571,7 @@ static ssize_t usb_device_read(struct fi
+ if (!access_ok(VERIFY_WRITE, buf, nbytes))
+ return -EFAULT;
-
- static struct notifier_block *usb_notifier_list;
--static DECLARE_MUTEX(usb_notifier_lock);
-+static DEFINE_MUTEX(usb_notifier_lock);
-
- static void usb_notifier_chain_register(struct notifier_block **list,
- struct notifier_block *n)
- {
-- down(&usb_notifier_lock);
-+ mutex_lock(&usb_notifier_lock);
- while (*list) {
- if (n->priority > (*list)->priority)
- break;
-@@ -30,13 +31,13 @@ static void usb_notifier_chain_register(
- }
- n->next = *list;
- *list = n;
-- up(&usb_notifier_lock);
-+ mutex_unlock(&usb_notifier_lock);
- }
-
- static void usb_notifier_chain_unregister(struct notifier_block **nl,
- struct notifier_block *n)
- {
-- down(&usb_notifier_lock);
-+ mutex_lock(&usb_notifier_lock);
- while ((*nl)!=NULL) {
- if ((*nl)==n) {
- *nl = n->next;
-@@ -45,7 +46,7 @@ static void usb_notifier_chain_unregiste
- nl=&((*nl)->next);
- }
- exit:
-- up(&usb_notifier_lock);
-+ mutex_unlock(&usb_notifier_lock);
- }
-
- static int usb_notifier_call_chain(struct notifier_block **n,
-@@ -54,7 +55,7 @@ static int usb_notifier_call_chain(struc
- int ret=NOTIFY_DONE;
- struct notifier_block *nb = *n;
-
-- down(&usb_notifier_lock);
-+ mutex_lock(&usb_notifier_lock);
- while (nb) {
- ret = nb->notifier_call(nb,val,v);
- if (ret&NOTIFY_STOP_MASK) {
-@@ -63,7 +64,7 @@ static int usb_notifier_call_chain(struc
- nb = nb->next;
- }
- exit:
-- up(&usb_notifier_lock);
-+ mutex_unlock(&usb_notifier_lock);
- return ret;
- }
-
---- gregkh-2.6.orig/drivers/usb/input/ati_remote.c
-+++ gregkh-2.6/drivers/usb/input/ati_remote.c
-@@ -159,8 +159,6 @@ static const char accel[] = { 1, 2, 4, 6
- */
- #define FILTER_TIME (HZ / 20)
-
--static DECLARE_MUTEX(disconnect_sem);
--
- struct ati_remote {
- struct input_dev *idev;
- struct usb_device *udev;
---- gregkh-2.6.orig/drivers/usb/misc/idmouse.c
-+++ gregkh-2.6/drivers/usb/misc/idmouse.c
-@@ -25,6 +25,7 @@
- #include <linux/module.h>
- #include <linux/smp_lock.h>
- #include <linux/completion.h>
-+#include <linux/mutex.h>
- #include <asm/uaccess.h>
- #include <linux/usb.h>
-
-@@ -121,7 +122,7 @@ static struct usb_driver idmouse_driver
- };
-
- /* prevent races between open() and disconnect() */
--static DECLARE_MUTEX(disconnect_sem);
-+static DEFINE_MUTEX(disconnect_mutex);
-
- static int idmouse_create_image(struct usb_idmouse *dev)
- {
-@@ -213,18 +214,18 @@ static int idmouse_open(struct inode *in
- int result = 0;
-
- /* prevent disconnects */
-- down(&disconnect_sem);
-+ mutex_lock(&disconnect_mutex);
-
- /* get the interface from minor number and driver information */
- interface = usb_find_interface (&idmouse_driver, iminor (inode));
- if (!interface) {
-- up(&disconnect_sem);
-+ mutex_unlock(&disconnect_mutex);
- return -ENODEV;
- }
- /* get the device information block from the interface */
- dev = usb_get_intfdata(interface);
- if (!dev) {
-- up(&disconnect_sem);
-+ mutex_unlock(&disconnect_mutex);
- return -ENODEV;
- }
-
-@@ -258,7 +259,7 @@ error:
- up(&dev->sem);
-
- /* unlock the disconnect semaphore */
-- up(&disconnect_sem);
-+ mutex_unlock(&disconnect_mutex);
- return result;
- }
-
-@@ -267,12 +268,12 @@ static int idmouse_release(struct inode
- struct usb_idmouse *dev;
-
- /* prevent a race condition with open() */
-- down(&disconnect_sem);
-+ mutex_lock(&disconnect_mutex);
-
- dev = (struct usb_idmouse *) file->private_data;
-
- if (dev == NULL) {
-- up(&disconnect_sem);
-+ mutex_unlock(&disconnect_mutex);
- return -ENODEV;
- }
-
-@@ -282,7 +283,7 @@ static int idmouse_release(struct inode
- /* are we really open? */
- if (dev->open <= 0) {
- up(&dev->sem);
-- up(&disconnect_sem);
-+ mutex_unlock(&disconnect_mutex);
- return -ENODEV;
- }
-
-@@ -292,12 +293,12 @@ static int idmouse_release(struct inode
- /* the device was unplugged before the file was released */
- up(&dev->sem);
- idmouse_delete(dev);
-- up(&disconnect_sem);
-+ mutex_unlock(&disconnect_mutex);
- return 0;
- }
-
- up(&dev->sem);
-- up(&disconnect_sem);
-+ mutex_unlock(&disconnect_mutex);
- return 0;
- }
-
-@@ -399,7 +400,7 @@ static void idmouse_disconnect(struct us
- struct usb_idmouse *dev;
-
- /* prevent races with open() */
-- down(&disconnect_sem);
-+ mutex_lock(&disconnect_mutex);
-
- /* get device structure */
- dev = usb_get_intfdata(interface);
-@@ -421,7 +422,7 @@ static void idmouse_disconnect(struct us
- if (!dev->open)
- idmouse_delete(dev);
-
-- up(&disconnect_sem);
-+ mutex_unlock(&disconnect_mutex);
-
- info("%s disconnected", DRIVER_DESC);
- }
---- gregkh-2.6.orig/drivers/usb/misc/ldusb.c
-+++ gregkh-2.6/drivers/usb/misc/ldusb.c
-@@ -33,6 +33,7 @@
- #include <linux/init.h>
- #include <linux/slab.h>
- #include <linux/module.h>
-+#include <linux/mutex.h>
-
- #include <asm/uaccess.h>
- #include <linux/input.h>
-@@ -172,7 +173,7 @@ struct ld_usb {
- };
-
- /* prevent races between open() and disconnect() */
--static DECLARE_MUTEX(disconnect_sem);
-+static DEFINE_MUTEX(disconnect_mutex);
-
- static struct usb_driver ld_usb_driver;
-
-@@ -293,7 +294,7 @@ static int ld_usb_open(struct inode *ino
- nonseekable_open(inode, file);
- subminor = iminor(inode);
-
-- down(&disconnect_sem);
-+ mutex_lock(&disconnect_mutex);
-
- interface = usb_find_interface(&ld_usb_driver, subminor);
-
-@@ -355,7 +356,7 @@ unlock_exit:
- up(&dev->sem);
-
- unlock_disconnect_exit:
-- up(&disconnect_sem);
-+ mutex_unlock(&disconnect_mutex);
-
- return retval;
- }
-@@ -740,7 +741,7 @@ static void ld_usb_disconnect(struct usb
- struct ld_usb *dev;
- int minor;
-
-- down(&disconnect_sem);
-+ mutex_lock(&disconnect_mutex);
-
- dev = usb_get_intfdata(intf);
- usb_set_intfdata(intf, NULL);
-@@ -761,7 +762,7 @@ static void ld_usb_disconnect(struct usb
- up(&dev->sem);
- }
-
-- up(&disconnect_sem);
-+ mutex_unlock(&disconnect_mutex);
-
- dev_info(&intf->dev, "LD USB Device #%d now disconnected\n",
- (minor - USB_LD_MINOR_BASE));
---- gregkh-2.6.orig/drivers/usb/misc/legousbtower.c
-+++ gregkh-2.6/drivers/usb/misc/legousbtower.c
-@@ -83,6 +83,7 @@
- #include <linux/module.h>
- #include <linux/smp_lock.h>
- #include <linux/completion.h>
-+#include <linux/mutex.h>
- #include <asm/uaccess.h>
- #include <linux/usb.h>
- #include <linux/poll.h>
-@@ -256,7 +257,7 @@ static void tower_disconnect (struct usb
-
-
- /* prevent races between open() and disconnect */
--static DECLARE_MUTEX (disconnect_sem);
-+static DEFINE_MUTEX (disconnect_mutex);
-
- /* file operations needed when we register this driver */
- static struct file_operations tower_fops = {
-@@ -349,7 +350,7 @@ static int tower_open (struct inode *ino
- nonseekable_open(inode, file);
- subminor = iminor(inode);
-
-- down (&disconnect_sem);
-+ mutex_lock (&disconnect_mutex);
-
- interface = usb_find_interface (&tower_driver, subminor);
-
-@@ -427,7 +428,7 @@ unlock_exit:
- up (&dev->sem);
-
- unlock_disconnect_exit:
-- up (&disconnect_sem);
-+ mutex_unlock (&disconnect_mutex);
-
- dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval);
-
-@@ -1005,7 +1006,7 @@ static void tower_disconnect (struct usb
-
- dbg(2, "%s: enter", __FUNCTION__);
-
-- down (&disconnect_sem);
-+ mutex_lock (&disconnect_mutex);
-
- dev = usb_get_intfdata (interface);
- usb_set_intfdata (interface, NULL);
-@@ -1027,7 +1028,7 @@ static void tower_disconnect (struct usb
- up (&dev->sem);
- }
-
-- up (&disconnect_sem);
-+ mutex_unlock (&disconnect_mutex);
-
- info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE));
-
---- gregkh-2.6.orig/drivers/usb/mon/mon_main.c
-+++ gregkh-2.6/drivers/usb/mon/mon_main.c
-@@ -12,6 +12,7 @@
- #include <linux/debugfs.h>
- #include <linux/smp_lock.h>
- #include <linux/notifier.h>
-+#include <linux/mutex.h>
-
- #include "usb_mon.h"
- #include "../core/hcd.h"
-@@ -23,7 +24,7 @@ static void mon_dissolve(struct mon_bus
- static void mon_bus_drop(struct kref *r);
- static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus);
-
--DECLARE_MUTEX(mon_lock);
-+DEFINE_MUTEX(mon_lock);
-
- static struct dentry *mon_dir; /* /dbg/usbmon */
- static LIST_HEAD(mon_buses); /* All buses we know: struct mon_bus */
-@@ -196,14 +197,14 @@ static void mon_bus_remove(struct usb_bu
- {
- struct mon_bus *mbus = ubus->mon_bus;
-
-- down(&mon_lock);
-+ mutex_lock(&mon_lock);
- list_del(&mbus->bus_link);
- debugfs_remove(mbus->dent_t);
- debugfs_remove(mbus->dent_s);
-
- mon_dissolve(mbus, ubus);
- kref_put(&mbus->ref, mon_bus_drop);
-- up(&mon_lock);
-+ mutex_unlock(&mon_lock);
- }
-
- static int mon_notify(struct notifier_block *self, unsigned long action,
-@@ -307,9 +308,9 @@ static void mon_bus_init(struct dentry *
- goto err_create_s;
- mbus->dent_s = d;
-
-- down(&mon_lock);
-+ mutex_lock(&mon_lock);
- list_add_tail(&mbus->bus_link, &mon_buses);
-- up(&mon_lock);
-+ mutex_unlock(&mon_lock);
- return;
-
- err_create_s:
-@@ -347,11 +348,11 @@ static int __init mon_init(void)
-
- usb_register_notify(&mon_nb);
-
-- down(&usb_bus_list_lock);
+- down (&usb_bus_list_lock);
+ mutex_lock(&usb_bus_list_lock);
- list_for_each_entry (ubus, &usb_bus_list, bus_list) {
- mon_bus_init(mondir, ubus);
+ /* print devices for all busses */
+ list_for_each_entry(bus, &usb_bus_list, bus_list) {
+ /* recurse through all children of the root hub */
+@@ -580,12 +581,12 @@ static ssize_t usb_device_read(struct fi
+ ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0);
+ usb_unlock_device(bus->root_hub);
+ if (ret < 0) {
+- up(&usb_bus_list_lock);
++ mutex_unlock(&usb_bus_list_lock);
+ return ret;
+ }
+ total_written += ret;
}
-- up(&usb_bus_list_lock);
+- up (&usb_bus_list_lock);
+ mutex_unlock(&usb_bus_list_lock);
- return 0;
- }
-
-@@ -363,7 +364,7 @@ static void __exit mon_exit(void)
- usb_unregister_notify(&mon_nb);
- usb_mon_deregister();
-
-- down(&mon_lock);
-+ mutex_lock(&mon_lock);
- while (!list_empty(&mon_buses)) {
- p = mon_buses.next;
- mbus = list_entry(p, struct mon_bus, bus_link);
-@@ -387,7 +388,7 @@ static void __exit mon_exit(void)
- mon_dissolve(mbus, mbus->u_bus);
- kref_put(&mbus->ref, mon_bus_drop);
- }
-- up(&mon_lock);
-+ mutex_unlock(&mon_lock);
-
- debugfs_remove(mon_dir);
- }
---- gregkh-2.6.orig/drivers/usb/mon/mon_text.c
-+++ gregkh-2.6/drivers/usb/mon/mon_text.c
-@@ -8,6 +8,7 @@
- #include <linux/list.h>
- #include <linux/usb.h>
- #include <linux/time.h>
-+#include <linux/mutex.h>
- #include <asm/uaccess.h>
-
- #include "usb_mon.h"
-@@ -54,7 +55,7 @@ struct mon_reader_text {
- wait_queue_head_t wait;
- int printf_size;
- char *printf_buf;
-- struct semaphore printf_lock;
-+ struct mutex printf_lock;
-
- char slab_name[SLAB_NAME_SZ];
- };
-@@ -208,7 +209,7 @@ static int mon_text_open(struct inode *i
- struct mon_reader_text *rp;
- int rc;
-
-- down(&mon_lock);
-+ mutex_lock(&mon_lock);
- mbus = inode->u.generic_ip;
- ubus = mbus->u_bus;
-
-@@ -220,7 +221,7 @@ static int mon_text_open(struct inode *i
- memset(rp, 0, sizeof(struct mon_reader_text));
- INIT_LIST_HEAD(&rp->e_list);
- init_waitqueue_head(&rp->wait);
-- init_MUTEX(&rp->printf_lock);
-+ mutex_init(&rp->printf_lock);
-
- rp->printf_size = PRINTF_DFL;
- rp->printf_buf = kmalloc(rp->printf_size, GFP_KERNEL);
-@@ -247,7 +248,7 @@ static int mon_text_open(struct inode *i
- mon_reader_add(mbus, &rp->r);
-
- file->private_data = rp;
-- up(&mon_lock);
-+ mutex_unlock(&mon_lock);
- return 0;
-
- // err_busy:
-@@ -257,7 +258,7 @@ err_slab:
- err_alloc_pr:
- kfree(rp);
- err_alloc:
-- up(&mon_lock);
-+ mutex_unlock(&mon_lock);
- return rc;
- }
-
-@@ -301,7 +302,7 @@ static ssize_t mon_text_read(struct file
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&rp->wait, &waita);
-
-- down(&rp->printf_lock);
-+ mutex_lock(&rp->printf_lock);
- cnt = 0;
- pbuf = rp->printf_buf;
- limit = rp->printf_size;
-@@ -358,7 +359,7 @@ static ssize_t mon_text_read(struct file
-
- if (copy_to_user(buf, rp->printf_buf, cnt))
- cnt = -EFAULT;
-- up(&rp->printf_lock);
-+ mutex_unlock(&rp->printf_lock);
- kmem_cache_free(rp->e_slab, ep);
- return cnt;
- }
-@@ -371,12 +372,12 @@ static int mon_text_release(struct inode
- struct list_head *p;
- struct mon_event_text *ep;
-
-- down(&mon_lock);
-+ mutex_lock(&mon_lock);
- mbus = inode->u.generic_ip;
-
- if (mbus->nreaders <= 0) {
- printk(KERN_ERR TAG ": consistency error on close\n");
-- up(&mon_lock);
-+ mutex_unlock(&mon_lock);
- return 0;
- }
- mon_reader_del(mbus, &rp->r);
-@@ -402,7 +403,7 @@ static int mon_text_release(struct inode
- kfree(rp->printf_buf);
- kfree(rp);
-
-- up(&mon_lock);
-+ mutex_unlock(&mon_lock);
- return 0;
+ return total_written;
}
--- gregkh-2.6.orig/drivers/usb/core/hcd.c
@@ -834,6 +361,108 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
extern wait_queue_head_t usb_kill_urb_queue;
extern struct usb_bus *usb_bus_get (struct usb_bus *bus);
+--- gregkh-2.6.orig/drivers/usb/core/hub.c
++++ gregkh-2.6/drivers/usb/core/hub.c
+@@ -22,6 +22,7 @@
+ #include <linux/usb.h>
+ #include <linux/usbdevice_fs.h>
+ #include <linux/kthread.h>
++#include <linux/mutex.h>
+
+ #include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+@@ -2162,7 +2163,7 @@ static int
+ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ int retry_counter)
+ {
+- static DECLARE_MUTEX(usb_address0_sem);
++ static DEFINE_MUTEX(usb_address0_mutex);
+
+ struct usb_device *hdev = hub->hdev;
+ int i, j, retval;
+@@ -2183,7 +2184,7 @@ hub_port_init (struct usb_hub *hub, stru
+ if (oldspeed == USB_SPEED_LOW)
+ delay = HUB_LONG_RESET_TIME;
+
+- down(&usb_address0_sem);
++ mutex_lock(&usb_address0_mutex);
+
+ /* Reset the device; full speed may morph to high speed */
+ retval = hub_port_reset(hub, port1, udev, delay);
+@@ -2381,7 +2382,7 @@ hub_port_init (struct usb_hub *hub, stru
+ fail:
+ if (retval)
+ hub_port_disable(hub, port1, 0);
+- up(&usb_address0_sem);
++ mutex_unlock(&usb_address0_mutex);
+ return retval;
+ }
+
+--- gregkh-2.6.orig/drivers/usb/core/notify.c
++++ gregkh-2.6/drivers/usb/core/notify.c
+@@ -13,16 +13,17 @@
+ #include <linux/kernel.h>
+ #include <linux/notifier.h>
+ #include <linux/usb.h>
++#include <linux/mutex.h>
+ #include "usb.h"
+
+
+ static struct notifier_block *usb_notifier_list;
+-static DECLARE_MUTEX(usb_notifier_lock);
++static DEFINE_MUTEX(usb_notifier_lock);
+
+ static void usb_notifier_chain_register(struct notifier_block **list,
+ struct notifier_block *n)
+ {
+- down(&usb_notifier_lock);
++ mutex_lock(&usb_notifier_lock);
+ while (*list) {
+ if (n->priority > (*list)->priority)
+ break;
+@@ -30,13 +31,13 @@ static void usb_notifier_chain_register(
+ }
+ n->next = *list;
+ *list = n;
+- up(&usb_notifier_lock);
++ mutex_unlock(&usb_notifier_lock);
+ }
+
+ static void usb_notifier_chain_unregister(struct notifier_block **nl,
+ struct notifier_block *n)
+ {
+- down(&usb_notifier_lock);
++ mutex_lock(&usb_notifier_lock);
+ while ((*nl)!=NULL) {
+ if ((*nl)==n) {
+ *nl = n->next;
+@@ -45,7 +46,7 @@ static void usb_notifier_chain_unregiste
+ nl=&((*nl)->next);
+ }
+ exit:
+- up(&usb_notifier_lock);
++ mutex_unlock(&usb_notifier_lock);
+ }
+
+ static int usb_notifier_call_chain(struct notifier_block **n,
+@@ -54,7 +55,7 @@ static int usb_notifier_call_chain(struc
+ int ret=NOTIFY_DONE;
+ struct notifier_block *nb = *n;
+
+- down(&usb_notifier_lock);
++ mutex_lock(&usb_notifier_lock);
+ while (nb) {
+ ret = nb->notifier_call(nb,val,v);
+ if (ret&NOTIFY_STOP_MASK) {
+@@ -63,7 +64,7 @@ static int usb_notifier_call_chain(struc
+ nb = nb->next;
+ }
+ exit:
+- up(&usb_notifier_lock);
++ mutex_unlock(&usb_notifier_lock);
+ return ret;
+ }
+
--- gregkh-2.6.orig/drivers/usb/core/usb.c
+++ gregkh-2.6/drivers/usb/core/usb.c
@@ -33,6 +33,7 @@
@@ -862,208 +491,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
return dev;
}
---- gregkh-2.6.orig/drivers/usb/core/devices.c
-+++ gregkh-2.6/drivers/usb/core/devices.c
-@@ -57,6 +57,7 @@
- #include <linux/usb.h>
- #include <linux/smp_lock.h>
- #include <linux/usbdevice_fs.h>
-+#include <linux/mutex.h>
- #include <asm/uaccess.h>
-
- #include "usb.h"
-@@ -570,7 +571,7 @@ static ssize_t usb_device_read(struct fi
- if (!access_ok(VERIFY_WRITE, buf, nbytes))
- return -EFAULT;
-
-- down (&usb_bus_list_lock);
-+ mutex_lock(&usb_bus_list_lock);
- /* print devices for all busses */
- list_for_each_entry(bus, &usb_bus_list, bus_list) {
- /* recurse through all children of the root hub */
-@@ -580,12 +581,12 @@ static ssize_t usb_device_read(struct fi
- ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0);
- usb_unlock_device(bus->root_hub);
- if (ret < 0) {
-- up(&usb_bus_list_lock);
-+ mutex_unlock(&usb_bus_list_lock);
- return ret;
- }
- total_written += ret;
- }
-- up (&usb_bus_list_lock);
-+ mutex_unlock(&usb_bus_list_lock);
- return total_written;
- }
-
---- gregkh-2.6.orig/drivers/usb/storage/scsiglue.c
-+++ gregkh-2.6/drivers/usb/storage/scsiglue.c
-@@ -47,6 +47,7 @@
-
- #include <linux/slab.h>
- #include <linux/module.h>
-+#include <linux/mutex.h>
-
- #include <scsi/scsi.h>
- #include <scsi/scsi_cmnd.h>
-@@ -271,9 +272,9 @@ static int device_reset(struct scsi_cmnd
- US_DEBUGP("%s called\n", __FUNCTION__);
-
- /* lock the device pointers and do the reset */
-- down(&(us->dev_semaphore));
-+ mutex_lock(&(us->dev_mutex));
- result = us->transport_reset(us);
-- up(&(us->dev_semaphore));
-+ mutex_unlock(&us->dev_mutex);
-
- return result < 0 ? FAILED : SUCCESS;
- }
-@@ -286,9 +287,9 @@ static int bus_reset(struct scsi_cmnd *s
-
- US_DEBUGP("%s called\n", __FUNCTION__);
-
-- down(&(us->dev_semaphore));
-+ mutex_lock(&(us->dev_mutex));
- result = usb_stor_port_reset(us);
-- up(&(us->dev_semaphore));
-+ mutex_unlock(&us->dev_mutex);
-
- return result < 0 ? FAILED : SUCCESS;
- }
---- gregkh-2.6.orig/drivers/usb/storage/usb.c
-+++ gregkh-2.6/drivers/usb/storage/usb.c
-@@ -55,6 +55,7 @@
- #include <linux/init.h>
- #include <linux/slab.h>
- #include <linux/kthread.h>
-+#include <linux/mutex.h>
-
- #include <scsi/scsi.h>
- #include <scsi/scsi_cmnd.h>
-@@ -188,7 +189,7 @@ static int storage_suspend(struct usb_in
- struct us_data *us = usb_get_intfdata(iface);
-
- /* Wait until no command is running */
-- down(&us->dev_semaphore);
-+ mutex_lock(&us->dev_mutex);
-
- US_DEBUGP("%s\n", __FUNCTION__);
- if (us->suspend_resume_hook)
-@@ -198,7 +199,7 @@ static int storage_suspend(struct usb_in
- /* When runtime PM is working, we'll set a flag to indicate
- * whether we should autoresume when a SCSI request arrives. */
-
-- up(&us->dev_semaphore);
-+ mutex_unlock(&us->dev_mutex);
- return 0;
- }
-
-@@ -206,14 +207,14 @@ static int storage_resume(struct usb_int
- {
- struct us_data *us = usb_get_intfdata(iface);
-
-- down(&us->dev_semaphore);
-+ mutex_lock(&us->dev_mutex);
-
- US_DEBUGP("%s\n", __FUNCTION__);
- if (us->suspend_resume_hook)
- (us->suspend_resume_hook)(us, US_RESUME);
- iface->dev.power.power_state.event = PM_EVENT_ON;
-
-- up(&us->dev_semaphore);
-+ mutex_unlock(&us->dev_mutex);
- return 0;
- }
-
-@@ -276,12 +277,12 @@ static int usb_stor_control_thread(void
- US_DEBUGP("*** thread awakened.\n");
-
- /* lock the device pointers */
-- down(&(us->dev_semaphore));
-+ mutex_lock(&(us->dev_mutex));
-
- /* if the device has disconnected, we are free to exit */
- if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
- US_DEBUGP("-- exiting\n");
-- up(&(us->dev_semaphore));
-+ mutex_unlock(&us->dev_mutex);
- break;
- }
-
-@@ -370,7 +371,7 @@ SkipForAbort:
- scsi_unlock(host);
-
- /* unlock the device pointers */
-- up(&(us->dev_semaphore));
-+ mutex_unlock(&us->dev_mutex);
- } /* for (;;) */
-
- scsi_host_put(host);
-@@ -815,8 +816,8 @@ static void quiesce_and_remove_host(stru
- * The thread will exit when it sees the DISCONNECTING flag. */
-
- /* Wait for the current command to finish, then remove the host */
-- down(&us->dev_semaphore);
-- up(&us->dev_semaphore);
-+ mutex_lock(&us->dev_mutex);
-+ mutex_unlock(&us->dev_mutex);
-
- /* queuecommand won't accept any new commands and the control
- * thread won't execute a previously-queued command. If there
-@@ -870,9 +871,9 @@ retry:
- /* For bulk-only devices, determine the max LUN value */
- if (us->protocol == US_PR_BULK &&
- !(us->flags & US_FL_SINGLE_LUN)) {
-- down(&us->dev_semaphore);
-+ mutex_lock(&us->dev_mutex);
- us->max_lun = usb_stor_Bulk_max_lun(us);
-- up(&us->dev_semaphore);
-+ mutex_unlock(&us->dev_mutex);
- }
- scsi_scan_host(us_to_host(us));
- printk(KERN_DEBUG "usb-storage: device scan complete\n");
-@@ -912,7 +913,7 @@ static int storage_probe(struct usb_inte
-
- us = host_to_us(host);
- memset(us, 0, sizeof(struct us_data));
-- init_MUTEX(&(us->dev_semaphore));
-+ mutex_init(&(us->dev_mutex));
- init_MUTEX_LOCKED(&(us->sema));
- init_completion(&(us->notify));
- init_waitqueue_head(&us->delay_wait);
---- gregkh-2.6.orig/drivers/usb/storage/usb.h
-+++ gregkh-2.6/drivers/usb/storage/usb.h
-@@ -49,6 +49,7 @@
- #include <linux/blkdev.h>
- #include <linux/smp_lock.h>
- #include <linux/completion.h>
-+#include <linux/mutex.h>
- #include <scsi/scsi_host.h>
-
- struct us_data;
-@@ -103,9 +104,9 @@ typedef void (*pm_hook)(struct us_data *
- struct us_data {
- /* The device we're working with
- * It's important to note:
-- * (o) you must hold dev_semaphore to change pusb_dev
-+ * (o) you must hold dev_mutex to change pusb_dev
- */
-- struct semaphore dev_semaphore; /* protect pusb_dev */
-+ struct mutex dev_mutex; /* protect pusb_dev */
- struct usb_device *pusb_dev; /* this usb_device */
- struct usb_interface *pusb_intf; /* this interface */
- struct us_unusual_dev *unusual_dev; /* device-filter entry */
---- gregkh-2.6.orig/drivers/usb/mon/usb_mon.h
-+++ gregkh-2.6/drivers/usb/mon/usb_mon.h
-@@ -49,7 +49,7 @@ void mon_reader_del(struct mon_bus *mbus
- */
- extern char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len);
-
--extern struct semaphore mon_lock;
-+extern struct mutex mon_lock;
-
- extern struct file_operations mon_fops_text;
- extern struct file_operations mon_fops_stat;
--- gregkh-2.6.orig/drivers/usb/image/mdc800.c
+++ gregkh-2.6/drivers/usb/image/mdc800.c
@@ -96,6 +96,7 @@
@@ -1332,6 +759,17 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
init_waitqueue_head (&mdc800->irq_wait);
init_waitqueue_head (&mdc800->write_wait);
+--- gregkh-2.6.orig/drivers/usb/input/ati_remote.c
++++ gregkh-2.6/drivers/usb/input/ati_remote.c
+@@ -159,8 +159,6 @@ static const char accel[] = { 1, 2, 4, 6
+ */
+ #define FILTER_TIME (HZ / 20)
+
+-static DECLARE_MUTEX(disconnect_sem);
+-
+ struct ati_remote {
+ struct input_dev *idev;
+ struct usb_device *udev;
--- gregkh-2.6.orig/drivers/usb/media/dabusb.c
+++ gregkh-2.6/drivers/usb/media/dabusb.c
@@ -38,6 +38,7 @@
@@ -1465,6 +903,461 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
struct usb_device *usbdev;
wait_queue_head_t wait;
wait_queue_head_t remove_ok;
+--- gregkh-2.6.orig/drivers/usb/media/ov511.c
++++ gregkh-2.6/drivers/usb/media/ov511.c
+@@ -365,14 +365,14 @@ reg_w(struct usb_ov511 *ov, unsigned cha
+
+ PDEBUG(5, "0x%02X:0x%02X", reg, value);
+
+- down(&ov->cbuf_lock);
++ mutex_lock(&ov->cbuf_lock);
+ ov->cbuf[0] = value;
+ rc = usb_control_msg(ov->dev,
+ usb_sndctrlpipe(ov->dev, 0),
+ (ov->bclass == BCL_OV518)?1:2 /* REG_IO */,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, (__u16)reg, &ov->cbuf[0], 1, 1000);
+- up(&ov->cbuf_lock);
++ mutex_unlock(&ov->cbuf_lock);
+
+ if (rc < 0)
+ err("reg write: error %d: %s", rc, symbolic(urb_errlist, rc));
+@@ -387,7 +387,7 @@ reg_r(struct usb_ov511 *ov, unsigned cha
+ {
+ int rc;
+
+- down(&ov->cbuf_lock);
++ mutex_lock(&ov->cbuf_lock);
+ rc = usb_control_msg(ov->dev,
+ usb_rcvctrlpipe(ov->dev, 0),
+ (ov->bclass == BCL_OV518)?1:3 /* REG_IO */,
+@@ -401,7 +401,7 @@ reg_r(struct usb_ov511 *ov, unsigned cha
+ PDEBUG(5, "0x%02X:0x%02X", reg, ov->cbuf[0]);
+ }
+
+- up(&ov->cbuf_lock);
++ mutex_unlock(&ov->cbuf_lock);
+
+ return rc;
+ }
+@@ -444,7 +444,7 @@ ov518_reg_w32(struct usb_ov511 *ov, unsi
+
+ PDEBUG(5, "0x%02X:%7d, n=%d", reg, val, n);
+
+- down(&ov->cbuf_lock);
++ mutex_lock(&ov->cbuf_lock);
+
+ *((__le32 *)ov->cbuf) = __cpu_to_le32(val);
+
+@@ -453,7 +453,7 @@ ov518_reg_w32(struct usb_ov511 *ov, unsi
+ 1 /* REG_IO */,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, (__u16)reg, ov->cbuf, n, 1000);
+- up(&ov->cbuf_lock);
++ mutex_unlock(&ov->cbuf_lock);
+
+ if (rc < 0)
+ err("reg write multiple: error %d: %s", rc,
+@@ -768,14 +768,14 @@ i2c_r(struct usb_ov511 *ov, unsigned cha
+ {
+ int rc;
+
+- down(&ov->i2c_lock);
++ mutex_lock(&ov->i2c_lock);
+
+ if (ov->bclass == BCL_OV518)
+ rc = ov518_i2c_read_internal(ov, reg);
+ else
+ rc = ov511_i2c_read_internal(ov, reg);
+
+- up(&ov->i2c_lock);
++ mutex_unlock(&ov->i2c_lock);
+
+ return rc;
+ }
+@@ -785,14 +785,14 @@ i2c_w(struct usb_ov511 *ov, unsigned cha
+ {
+ int rc;
+
+- down(&ov->i2c_lock);
++ mutex_lock(&ov->i2c_lock);
+
+ if (ov->bclass == BCL_OV518)
+ rc = ov518_i2c_write_internal(ov, reg, value);
+ else
+ rc = ov511_i2c_write_internal(ov, reg, value);
+
+- up(&ov->i2c_lock);
++ mutex_unlock(&ov->i2c_lock);
+
+ return rc;
+ }
+@@ -842,9 +842,9 @@ i2c_w_mask(struct usb_ov511 *ov,
+ {
+ int rc;
+
+- down(&ov->i2c_lock);
++ mutex_lock(&ov->i2c_lock);
+ rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask);
+- up(&ov->i2c_lock);
++ mutex_unlock(&ov->i2c_lock);
+
+ return rc;
+ }
+@@ -880,7 +880,7 @@ i2c_w_slave(struct usb_ov511 *ov,
+ {
+ int rc = 0;
+
+- down(&ov->i2c_lock);
++ mutex_lock(&ov->i2c_lock);
+
+ /* Set new slave IDs */
+ rc = i2c_set_slave_internal(ov, slave);
+@@ -894,7 +894,7 @@ out:
+ if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0)
+ err("Couldn't restore primary I2C slave");
+
+- up(&ov->i2c_lock);
++ mutex_unlock(&ov->i2c_lock);
+ return rc;
+ }
+
+@@ -906,7 +906,7 @@ i2c_r_slave(struct usb_ov511 *ov,
+ {
+ int rc;
+
+- down(&ov->i2c_lock);
++ mutex_lock(&ov->i2c_lock);
+
+ /* Set new slave IDs */
+ rc = i2c_set_slave_internal(ov, slave);
+@@ -923,7 +923,7 @@ out:
+ if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0)
+ err("Couldn't restore primary I2C slave");
+
+- up(&ov->i2c_lock);
++ mutex_unlock(&ov->i2c_lock);
+ return rc;
+ }
+
+@@ -933,7 +933,7 @@ ov51x_set_slave_ids(struct usb_ov511 *ov
+ {
+ int rc;
+
+- down(&ov->i2c_lock);
++ mutex_lock(&ov->i2c_lock);
+
+ rc = i2c_set_slave_internal(ov, sid);
+ if (rc < 0)
+@@ -942,7 +942,7 @@ ov51x_set_slave_ids(struct usb_ov511 *ov
+ // FIXME: Is this actually necessary?
+ rc = ov51x_reset(ov, OV511_RESET_NOREGS);
+ out:
+- up(&ov->i2c_lock);
++ mutex_unlock(&ov->i2c_lock);
+ return rc;
+ }
+
+@@ -3832,7 +3832,7 @@ ov51x_alloc(struct usb_ov511 *ov)
+ const int raw_bufsize = OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h);
+
+ PDEBUG(4, "entered");
+- down(&ov->buf_lock);
++ mutex_lock(&ov->buf_lock);
+
+ if (ov->buf_state == BUF_ALLOCATED)
+ goto out;
+@@ -3879,12 +3879,12 @@ ov51x_alloc(struct usb_ov511 *ov)
+
+ ov->buf_state = BUF_ALLOCATED;
+ out:
+- up(&ov->buf_lock);
++ mutex_unlock(&ov->buf_lock);
+ PDEBUG(4, "leaving");
+ return 0;
+ error:
+ ov51x_do_dealloc(ov);
+- up(&ov->buf_lock);
++ mutex_unlock(&ov->buf_lock);
+ PDEBUG(4, "errored");
+ return -ENOMEM;
+ }
+@@ -3893,9 +3893,9 @@ static void
+ ov51x_dealloc(struct usb_ov511 *ov)
+ {
+ PDEBUG(4, "entered");
+- down(&ov->buf_lock);
++ mutex_lock(&ov->buf_lock);
+ ov51x_do_dealloc(ov);
+- up(&ov->buf_lock);
++ mutex_unlock(&ov->buf_lock);
+ PDEBUG(4, "leaving");
+ }
+
+@@ -3914,7 +3914,7 @@ ov51x_v4l1_open(struct inode *inode, str
+
+ PDEBUG(4, "opening");
+
+- down(&ov->lock);
++ mutex_lock(&ov->lock);
+
+ err = -EBUSY;
+ if (ov->user)
+@@ -3958,7 +3958,7 @@ ov51x_v4l1_open(struct inode *inode, str
+ ov51x_led_control(ov, 1);
+
+ out:
+- up(&ov->lock);
++ mutex_unlock(&ov->lock);
+ return err;
+ }
+
+@@ -3970,7 +3970,7 @@ ov51x_v4l1_close(struct inode *inode, st
+
+ PDEBUG(4, "ov511_close");
+
+- down(&ov->lock);
++ mutex_lock(&ov->lock);
+
+ ov->user--;
+ ov51x_stop_isoc(ov);
+@@ -3981,15 +3981,15 @@ ov51x_v4l1_close(struct inode *inode, st
+ if (ov->dev)
+ ov51x_dealloc(ov);
+
+- up(&ov->lock);
++ mutex_unlock(&ov->lock);
+
+ /* Device unplugged while open. Only a minimum of unregistration is done
+ * here; the disconnect callback already did the rest. */
+ if (!ov->dev) {
+- down(&ov->cbuf_lock);
++ mutex_lock(&ov->cbuf_lock);
+ kfree(ov->cbuf);
+ ov->cbuf = NULL;
+- up(&ov->cbuf_lock);
++ mutex_unlock(&ov->cbuf_lock);
+
+ ov51x_dealloc(ov);
+ kfree(ov);
+@@ -4449,12 +4449,12 @@ ov51x_v4l1_ioctl(struct inode *inode, st
+ struct usb_ov511 *ov = video_get_drvdata(vdev);
+ int rc;
+
+- if (down_interruptible(&ov->lock))
++ if (mutex_lock_interruptible(&ov->lock))
+ return -EINTR;
+
+ rc = video_usercopy(inode, file, cmd, arg, ov51x_v4l1_ioctl_internal);
+
+- up(&ov->lock);
++ mutex_unlock(&ov->lock);
+ return rc;
+ }
+
+@@ -4468,7 +4468,7 @@ ov51x_v4l1_read(struct file *file, char
+ int i, rc = 0, frmx = -1;
+ struct ov511_frame *frame;
+
+- if (down_interruptible(&ov->lock))
++ if (mutex_lock_interruptible(&ov->lock))
+ return -EINTR;
+
+ PDEBUG(4, "%ld bytes, noblock=%d", count, noblock);
+@@ -4604,11 +4604,11 @@ restart:
+
+ PDEBUG(4, "read finished, returning %ld (sweet)", count);
+
+- up(&ov->lock);
++ mutex_unlock(&ov->lock);
+ return count;
+
+ error:
+- up(&ov->lock);
++ mutex_unlock(&ov->lock);
+ return rc;
+ }
+
+@@ -4631,14 +4631,14 @@ ov51x_v4l1_mmap(struct file *file, struc
+ + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))))
+ return -EINVAL;
+
+- if (down_interruptible(&ov->lock))
++ if (mutex_lock_interruptible(&ov->lock))
+ return -EINTR;
+
+ pos = (unsigned long)ov->fbuf;
+ while (size > 0) {
+ page = vmalloc_to_pfn((void *)pos);
+ if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
+- up(&ov->lock);
++ mutex_unlock(&ov->lock);
+ return -EAGAIN;
+ }
+ start += PAGE_SIZE;
+@@ -4649,7 +4649,7 @@ ov51x_v4l1_mmap(struct file *file, struc
+ size = 0;
+ }
+
+- up(&ov->lock);
++ mutex_unlock(&ov->lock);
+ return 0;
+ }
+
+@@ -5738,11 +5738,10 @@ ov51x_probe(struct usb_interface *intf,
+
+ init_waitqueue_head(&ov->wq);
+
+- init_MUTEX(&ov->lock); /* to 1 == available */
+- init_MUTEX(&ov->buf_lock);
+- init_MUTEX(&ov->param_lock);
+- init_MUTEX(&ov->i2c_lock);
+- init_MUTEX(&ov->cbuf_lock);
++ mutex_init(&ov->lock); /* to 1 == available */
++ mutex_init(&ov->buf_lock);
++ mutex_init(&ov->i2c_lock);
++ mutex_init(&ov->cbuf_lock);
+
+ ov->buf_state = BUF_NOT_ALLOCATED;
+
+@@ -5833,10 +5832,10 @@ error:
+ }
+
+ if (ov->cbuf) {
+- down(&ov->cbuf_lock);
++ mutex_lock(&ov->cbuf_lock);
+ kfree(ov->cbuf);
+ ov->cbuf = NULL;
+- up(&ov->cbuf_lock);
++ mutex_unlock(&ov->cbuf_lock);
+ }
+
+ kfree(ov);
+@@ -5881,10 +5880,10 @@ ov51x_disconnect(struct usb_interface *i
+
+ /* Free the memory */
+ if (ov && !ov->user) {
+- down(&ov->cbuf_lock);
++ mutex_lock(&ov->cbuf_lock);
+ kfree(ov->cbuf);
+ ov->cbuf = NULL;
+- up(&ov->cbuf_lock);
++ mutex_unlock(&ov->cbuf_lock);
+
+ ov51x_dealloc(ov);
+ kfree(ov);
+--- gregkh-2.6.orig/drivers/usb/media/ov511.h
++++ gregkh-2.6/drivers/usb/media/ov511.h
+@@ -5,6 +5,7 @@
+ #include <linux/videodev.h>
+ #include <linux/smp_lock.h>
+ #include <linux/usb.h>
++#include <linux/mutex.h>
+
+ #define OV511_DEBUG /* Turn on debug messages */
+
+@@ -435,7 +436,7 @@ struct usb_ov511 {
+
+ int led_policy; /* LED: off|on|auto; OV511+ only */
+
+- struct semaphore lock; /* Serializes user-accessible operations */
++ struct mutex lock; /* Serializes user-accessible operations */
+ int user; /* user count for exclusive use */
+
+ int streaming; /* Are we streaming Isochronous? */
+@@ -473,11 +474,9 @@ struct usb_ov511 {
+ int packet_size; /* Frame size per isoc desc */
+ int packet_numbering; /* Is ISO frame numbering enabled? */
+
+- struct semaphore param_lock; /* params lock for this camera */
+-
+ /* Framebuffer/sbuf management */
+ int buf_state;
+- struct semaphore buf_lock;
++ struct mutex buf_lock;
+
+ struct ov51x_decomp_ops *decomp_ops;
+
+@@ -494,12 +493,12 @@ struct usb_ov511 {
+ int pal; /* Device is designed for PAL resolution */
+
+ /* I2C interface */
+- struct semaphore i2c_lock; /* Protect I2C controller regs */
++ struct mutex i2c_lock; /* Protect I2C controller regs */
+ unsigned char primary_i2c_slave; /* I2C write id of sensor */
+
+ /* Control transaction stuff */
+ unsigned char *cbuf; /* Buffer for payload */
+- struct semaphore cbuf_lock;
++ struct mutex cbuf_lock;
+ };
+
+ /* Used to represent a list of values and their respective symbolic names */
+--- gregkh-2.6.orig/drivers/usb/media/se401.c
++++ gregkh-2.6/drivers/usb/media/se401.c
+@@ -1157,21 +1157,21 @@ static int se401_mmap(struct file *file,
+ unsigned long size = vma->vm_end-vma->vm_start;
+ unsigned long page, pos;
+
+- down(&se401->lock);
++ mutex_lock(&se401->lock);
+
+ if (se401->dev == NULL) {
+- up(&se401->lock);
++ mutex_unlock(&se401->lock);
+ return -EIO;
+ }
+ if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
+- up(&se401->lock);
++ mutex_unlock(&se401->lock);
+ return -EINVAL;
+ }
+ pos = (unsigned long)se401->fbuf;
+ while (size > 0) {
+ page = vmalloc_to_pfn((void *)pos);
+ if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
+- up(&se401->lock);
++ mutex_unlock(&se401->lock);
+ return -EAGAIN;
+ }
+ start += PAGE_SIZE;
+@@ -1181,7 +1181,7 @@ static int se401_mmap(struct file *file,
+ else
+ size = 0;
+ }
+- up(&se401->lock);
++ mutex_unlock(&se401->lock);
+
+ return 0;
+ }
+@@ -1366,7 +1366,7 @@ static int se401_probe(struct usb_interf
+ memcpy(&se401->vdev, &se401_template, sizeof(se401_template));
+ memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name));
+ init_waitqueue_head(&se401->wq);
+- init_MUTEX(&se401->lock);
++ mutex_init(&se401->lock);
+ wmb();
+
+ if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+--- gregkh-2.6.orig/drivers/usb/media/se401.h
++++ gregkh-2.6/drivers/usb/media/se401.h
+@@ -5,6 +5,7 @@
+ #include <asm/uaccess.h>
+ #include <linux/videodev.h>
+ #include <linux/smp_lock.h>
++#include <linux/mutex.h>
+
+ #define se401_DEBUG /* Turn on debug messages */
+
+@@ -189,7 +190,7 @@ struct usb_se401 {
+ int maxframesize;
+ int cframesize; /* current framesize */
+
+- struct semaphore lock;
++ struct mutex lock;
+ int user; /* user count for exclusive use */
+ int removed; /* device disconnected */
+
--- gregkh-2.6.orig/drivers/usb/media/sn9c102.h
+++ gregkh-2.6/drivers/usb/media/sn9c102.h
@@ -33,6 +33,7 @@
@@ -2111,6 +2004,224 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
if (!cam->users)
kfree(cam);
+--- gregkh-2.6.orig/drivers/usb/media/stv680.c
++++ gregkh-2.6/drivers/usb/media/stv680.c
+@@ -67,6 +67,7 @@
+ #include <linux/errno.h>
+ #include <linux/videodev.h>
+ #include <linux/usb.h>
++#include <linux/mutex.h>
+
+ #include "stv680.h"
+
+@@ -1258,22 +1259,22 @@ static int stv680_mmap (struct file *fil
+ unsigned long size = vma->vm_end-vma->vm_start;
+ unsigned long page, pos;
+
+- down (&stv680->lock);
++ mutex_lock(&stv680->lock);
+
+ if (stv680->udev == NULL) {
+- up (&stv680->lock);
++ mutex_unlock(&stv680->lock);
+ return -EIO;
+ }
+ if (size > (((STV680_NUMFRAMES * stv680->maxframesize) + PAGE_SIZE - 1)
+ & ~(PAGE_SIZE - 1))) {
+- up (&stv680->lock);
++ mutex_unlock(&stv680->lock);
+ return -EINVAL;
+ }
+ pos = (unsigned long) stv680->fbuf;
+ while (size > 0) {
+ page = vmalloc_to_pfn((void *)pos);
+ if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
+- up (&stv680->lock);
++ mutex_unlock(&stv680->lock);
+ return -EAGAIN;
+ }
+ start += PAGE_SIZE;
+@@ -1283,7 +1284,7 @@ static int stv680_mmap (struct file *fil
+ else
+ size = 0;
+ }
+- up (&stv680->lock);
++ mutex_unlock(&stv680->lock);
+
+ return 0;
+ }
+@@ -1409,7 +1410,7 @@ static int stv680_probe (struct usb_inte
+
+ memcpy (stv680->vdev->name, stv680->camera_name, strlen (stv680->camera_name));
+ init_waitqueue_head (&stv680->wq);
+- init_MUTEX (&stv680->lock);
++ mutex_init (&stv680->lock);
+ wmb ();
+
+ if (video_register_device (stv680->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+--- gregkh-2.6.orig/drivers/usb/media/stv680.h
++++ gregkh-2.6/drivers/usb/media/stv680.h
+@@ -118,7 +118,7 @@ struct usb_stv {
+ int origGain;
+ int origMode; /* original camera mode */
+
+- struct semaphore lock; /* to lock the structure */
++ struct mutex lock; /* to lock the structure */
+ int user; /* user count for exclusive use */
+ int removed; /* device disconnected */
+ int streaming; /* Are we streaming video? */
+--- gregkh-2.6.orig/drivers/usb/media/usbvideo.c
++++ gregkh-2.6/drivers/usb/media/usbvideo.c
+@@ -714,7 +714,7 @@ int usbvideo_register(
+ cams->md_module = md;
+ if (cams->md_module == NULL)
+ warn("%s: module == NULL!", __FUNCTION__);
+- init_MUTEX(&cams->lock); /* to 1 == available */
++ mutex_init(&cams->lock); /* to 1 == available */
+
+ for (i = 0; i < num_cams; i++) {
+ struct uvd *up = &cams->cam[i];
+@@ -862,7 +862,7 @@ static void usbvideo_Disconnect(struct u
+ if (uvd->debug > 0)
+ info("%s(%p.)", __FUNCTION__, intf);
+
+- down(&uvd->lock);
++ mutex_lock(&uvd->lock);
+ uvd->remove_pending = 1; /* Now all ISO data will be ignored */
+
+ /* At this time we ask to cancel outstanding URBs */
+@@ -882,7 +882,7 @@ static void usbvideo_Disconnect(struct u
+ info("%s: In use, disconnect pending.", __FUNCTION__);
+ else
+ usbvideo_CameraRelease(uvd);
+- up(&uvd->lock);
++ mutex_unlock(&uvd->lock);
+ info("USB camera disconnected.");
+
+ usbvideo_ClientDecModCount(uvd);
+@@ -929,19 +929,19 @@ static int usbvideo_find_struct(struct u
+ err("No usbvideo handle?");
+ return -1;
+ }
+- down(&cams->lock);
++ mutex_lock(&cams->lock);
+ for (u = 0; u < cams->num_cameras; u++) {
+ struct uvd *uvd = &cams->cam[u];
+ if (!uvd->uvd_used) /* This one is free */
+ {
+ uvd->uvd_used = 1; /* In use now */
+- init_MUTEX(&uvd->lock); /* to 1 == available */
++ mutex_init(&uvd->lock); /* to 1 == available */
+ uvd->dev = NULL;
+ rv = u;
+ break;
+ }
+ }
+- up(&cams->lock);
++ mutex_unlock(&cams->lock);
+ return rv;
+ }
+
+@@ -983,7 +983,7 @@ struct uvd *usbvideo_AllocateDevice(stru
+ /* Not relying upon caller we increase module counter ourselves */
+ usbvideo_ClientIncModCount(uvd);
+
+- down(&uvd->lock);
++ mutex_lock(&uvd->lock);
+ for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+ uvd->sbuf[i].urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
+ if (uvd->sbuf[i].urb == NULL) {
+@@ -1006,7 +1006,7 @@ struct uvd *usbvideo_AllocateDevice(stru
+ * return control to the client's probe function right now.
+ */
+ allocate_done:
+- up (&uvd->lock);
++ mutex_unlock(&uvd->lock);
+ usbvideo_ClientDecModCount(uvd);
+ return uvd;
+ }
+@@ -1120,7 +1120,7 @@ static int usbvideo_v4l_open(struct inod
+ info("%s($%p)", __FUNCTION__, dev);
+
+ usbvideo_ClientIncModCount(uvd);
+- down(&uvd->lock);
++ mutex_lock(&uvd->lock);
+
+ if (uvd->user) {
+ err("%s: Someone tried to open an already opened device!", __FUNCTION__);
+@@ -1201,7 +1201,7 @@ static int usbvideo_v4l_open(struct inod
+ }
+ }
+ }
+- up(&uvd->lock);
++ mutex_unlock(&uvd->lock);
+ if (errCode != 0)
+ usbvideo_ClientDecModCount(uvd);
+ if (uvd->debug > 0)
+@@ -1230,7 +1230,7 @@ static int usbvideo_v4l_close(struct ino
+ if (uvd->debug > 1)
+ info("%s($%p)", __FUNCTION__, dev);
+
+- down(&uvd->lock);
++ mutex_lock(&uvd->lock);
+ GET_CALLBACK(uvd, stopDataPump)(uvd);
+ usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size);
+ uvd->fbuf = NULL;
+@@ -1251,7 +1251,7 @@ static int usbvideo_v4l_close(struct ino
+ info("usbvideo_v4l_close: Final disconnect.");
+ usbvideo_CameraRelease(uvd);
+ }
+- up(&uvd->lock);
++ mutex_unlock(&uvd->lock);
+ usbvideo_ClientDecModCount(uvd);
+
+ if (uvd->debug > 1)
+@@ -1511,7 +1511,7 @@ static ssize_t usbvideo_v4l_read(struct
+ if (uvd->debug >= 1)
+ info("%s: %Zd. bytes, noblock=%d.", __FUNCTION__, count, noblock);
+
+- down(&uvd->lock);
++ mutex_lock(&uvd->lock);
+
+ /* See if a frame is completed, then use it. */
+ for(i = 0; i < USBVIDEO_NUMFRAMES; i++) {
+@@ -1643,7 +1643,7 @@ static ssize_t usbvideo_v4l_read(struct
+ }
+ }
+ read_done:
+- up(&uvd->lock);
++ mutex_unlock(&uvd->lock);
+ return count;
+ }
+
+--- gregkh-2.6.orig/drivers/usb/media/usbvideo.h
++++ gregkh-2.6/drivers/usb/media/usbvideo.h
+@@ -19,6 +19,7 @@
+ #include <linux/config.h>
+ #include <linux/videodev.h>
+ #include <linux/usb.h>
++#include <linux/mutex.h>
+
+ /* Most helpful debugging aid */
+ #define assert(expr) ((void) ((expr) ? 0 : (err("assert failed at line %d",__LINE__))))
+@@ -213,7 +214,7 @@ struct uvd {
+ unsigned long flags; /* FLAGS_USBVIDEO_xxx */
+ unsigned long paletteBits; /* Which palettes we accept? */
+ unsigned short defaultPalette; /* What palette to use for read() */
+- struct semaphore lock;
++ struct mutex lock;
+ int user; /* user count for exclusive use */
+
+ videosize_t videosize; /* Current setting */
+@@ -272,7 +273,7 @@ struct usbvideo {
+ int num_cameras; /* As allocated */
+ struct usb_driver usbdrv; /* Interface to the USB stack */
+ char drvName[80]; /* Driver name */
+- struct semaphore lock; /* Mutex protecting camera structures */
++ struct mutex lock; /* Mutex protecting camera structures */
+ struct usbvideo_cb cb; /* Table of callbacks (virtual methods) */
+ struct video_device vdt; /* Video device template */
+ struct uvd *cam; /* Array of camera structures */
--- gregkh-2.6.orig/drivers/usb/media/vicam.c
+++ gregkh-2.6/drivers/usb/media/vicam.c
@@ -42,6 +42,7 @@
@@ -2524,676 +2635,565 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
spinlock_t urb_lock, /* for submit_urb() and unlink_urb() */
flist_lock; /* for requested frame list accesses */
wait_queue_head_t open, wait_queue;
---- gregkh-2.6.orig/drivers/usb/media/ov511.c
-+++ gregkh-2.6/drivers/usb/media/ov511.c
-@@ -365,14 +365,14 @@ reg_w(struct usb_ov511 *ov, unsigned cha
+--- gregkh-2.6.orig/drivers/usb/misc/idmouse.c
++++ gregkh-2.6/drivers/usb/misc/idmouse.c
+@@ -25,6 +25,7 @@
+ #include <linux/module.h>
+ #include <linux/smp_lock.h>
+ #include <linux/completion.h>
++#include <linux/mutex.h>
+ #include <asm/uaccess.h>
+ #include <linux/usb.h>
- PDEBUG(5, "0x%02X:0x%02X", reg, value);
+@@ -121,7 +122,7 @@ static struct usb_driver idmouse_driver
+ };
-- down(&ov->cbuf_lock);
-+ mutex_lock(&ov->cbuf_lock);
- ov->cbuf[0] = value;
- rc = usb_control_msg(ov->dev,
- usb_sndctrlpipe(ov->dev, 0),
- (ov->bclass == BCL_OV518)?1:2 /* REG_IO */,
- USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0, (__u16)reg, &ov->cbuf[0], 1, 1000);
-- up(&ov->cbuf_lock);
-+ mutex_unlock(&ov->cbuf_lock);
+ /* prevent races between open() and disconnect() */
+-static DECLARE_MUTEX(disconnect_sem);
++static DEFINE_MUTEX(disconnect_mutex);
- if (rc < 0)
- err("reg write: error %d: %s", rc, symbolic(urb_errlist, rc));
-@@ -387,7 +387,7 @@ reg_r(struct usb_ov511 *ov, unsigned cha
+ static int idmouse_create_image(struct usb_idmouse *dev)
{
- int rc;
+@@ -213,18 +214,18 @@ static int idmouse_open(struct inode *in
+ int result = 0;
-- down(&ov->cbuf_lock);
-+ mutex_lock(&ov->cbuf_lock);
- rc = usb_control_msg(ov->dev,
- usb_rcvctrlpipe(ov->dev, 0),
- (ov->bclass == BCL_OV518)?1:3 /* REG_IO */,
-@@ -401,7 +401,7 @@ reg_r(struct usb_ov511 *ov, unsigned cha
- PDEBUG(5, "0x%02X:0x%02X", reg, ov->cbuf[0]);
+ /* prevent disconnects */
+- down(&disconnect_sem);
++ mutex_lock(&disconnect_mutex);
+
+ /* get the interface from minor number and driver information */
+ interface = usb_find_interface (&idmouse_driver, iminor (inode));
+ if (!interface) {
+- up(&disconnect_sem);
++ mutex_unlock(&disconnect_mutex);
+ return -ENODEV;
+ }
+ /* get the device information block from the interface */
+ dev = usb_get_intfdata(interface);
+ if (!dev) {
+- up(&disconnect_sem);
++ mutex_unlock(&disconnect_mutex);
+ return -ENODEV;
}
-- up(&ov->cbuf_lock);
-+ mutex_unlock(&ov->cbuf_lock);
+@@ -258,7 +259,7 @@ error:
+ up(&dev->sem);
- return rc;
+ /* unlock the disconnect semaphore */
+- up(&disconnect_sem);
++ mutex_unlock(&disconnect_mutex);
+ return result;
}
-@@ -444,7 +444,7 @@ ov518_reg_w32(struct usb_ov511 *ov, unsi
-
- PDEBUG(5, "0x%02X:%7d, n=%d", reg, val, n);
-
-- down(&ov->cbuf_lock);
-+ mutex_lock(&ov->cbuf_lock);
- *((__le32 *)ov->cbuf) = __cpu_to_le32(val);
+@@ -267,12 +268,12 @@ static int idmouse_release(struct inode
+ struct usb_idmouse *dev;
-@@ -453,7 +453,7 @@ ov518_reg_w32(struct usb_ov511 *ov, unsi
- 1 /* REG_IO */,
- USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0, (__u16)reg, ov->cbuf, n, 1000);
-- up(&ov->cbuf_lock);
-+ mutex_unlock(&ov->cbuf_lock);
+ /* prevent a race condition with open() */
+- down(&disconnect_sem);
++ mutex_lock(&disconnect_mutex);
- if (rc < 0)
- err("reg write multiple: error %d: %s", rc,
-@@ -768,14 +768,14 @@ i2c_r(struct usb_ov511 *ov, unsigned cha
- {
- int rc;
+ dev = (struct usb_idmouse *) file->private_data;
-- down(&ov->i2c_lock);
-+ mutex_lock(&ov->i2c_lock);
+ if (dev == NULL) {
+- up(&disconnect_sem);
++ mutex_unlock(&disconnect_mutex);
+ return -ENODEV;
+ }
- if (ov->bclass == BCL_OV518)
- rc = ov518_i2c_read_internal(ov, reg);
- else
- rc = ov511_i2c_read_internal(ov, reg);
+@@ -282,7 +283,7 @@ static int idmouse_release(struct inode
+ /* are we really open? */
+ if (dev->open <= 0) {
+ up(&dev->sem);
+- up(&disconnect_sem);
++ mutex_unlock(&disconnect_mutex);
+ return -ENODEV;
+ }
-- up(&ov->i2c_lock);
-+ mutex_unlock(&ov->i2c_lock);
+@@ -292,12 +293,12 @@ static int idmouse_release(struct inode
+ /* the device was unplugged before the file was released */
+ up(&dev->sem);
+ idmouse_delete(dev);
+- up(&disconnect_sem);
++ mutex_unlock(&disconnect_mutex);
+ return 0;
+ }
- return rc;
+ up(&dev->sem);
+- up(&disconnect_sem);
++ mutex_unlock(&disconnect_mutex);
+ return 0;
}
-@@ -785,14 +785,14 @@ i2c_w(struct usb_ov511 *ov, unsigned cha
- {
- int rc;
-- down(&ov->i2c_lock);
-+ mutex_lock(&ov->i2c_lock);
-
- if (ov->bclass == BCL_OV518)
- rc = ov518_i2c_write_internal(ov, reg, value);
- else
- rc = ov511_i2c_write_internal(ov, reg, value);
+@@ -399,7 +400,7 @@ static void idmouse_disconnect(struct us
+ struct usb_idmouse *dev;
-- up(&ov->i2c_lock);
-+ mutex_unlock(&ov->i2c_lock);
+ /* prevent races with open() */
+- down(&disconnect_sem);
++ mutex_lock(&disconnect_mutex);
- return rc;
- }
-@@ -842,9 +842,9 @@ i2c_w_mask(struct usb_ov511 *ov,
- {
- int rc;
+ /* get device structure */
+ dev = usb_get_intfdata(interface);
+@@ -421,7 +422,7 @@ static void idmouse_disconnect(struct us
+ if (!dev->open)
+ idmouse_delete(dev);
-- down(&ov->i2c_lock);
-+ mutex_lock(&ov->i2c_lock);
- rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask);
-- up(&ov->i2c_lock);
-+ mutex_unlock(&ov->i2c_lock);
+- up(&disconnect_sem);
++ mutex_unlock(&disconnect_mutex);
- return rc;
+ info("%s disconnected", DRIVER_DESC);
}
-@@ -880,7 +880,7 @@ i2c_w_slave(struct usb_ov511 *ov,
- {
- int rc = 0;
-
-- down(&ov->i2c_lock);
-+ mutex_lock(&ov->i2c_lock);
+--- gregkh-2.6.orig/drivers/usb/misc/ldusb.c
++++ gregkh-2.6/drivers/usb/misc/ldusb.c
+@@ -33,6 +33,7 @@
+ #include <linux/init.h>
+ #include <linux/slab.h>
+ #include <linux/module.h>
++#include <linux/mutex.h>
- /* Set new slave IDs */
- rc = i2c_set_slave_internal(ov, slave);
-@@ -894,7 +894,7 @@ out:
- if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0)
- err("Couldn't restore primary I2C slave");
+ #include <asm/uaccess.h>
+ #include <linux/input.h>
+@@ -172,7 +173,7 @@ struct ld_usb {
+ };
-- up(&ov->i2c_lock);
-+ mutex_unlock(&ov->i2c_lock);
- return rc;
- }
+ /* prevent races between open() and disconnect() */
+-static DECLARE_MUTEX(disconnect_sem);
++static DEFINE_MUTEX(disconnect_mutex);
-@@ -906,7 +906,7 @@ i2c_r_slave(struct usb_ov511 *ov,
- {
- int rc;
+ static struct usb_driver ld_usb_driver;
-- down(&ov->i2c_lock);
-+ mutex_lock(&ov->i2c_lock);
+@@ -293,7 +294,7 @@ static int ld_usb_open(struct inode *ino
+ nonseekable_open(inode, file);
+ subminor = iminor(inode);
- /* Set new slave IDs */
- rc = i2c_set_slave_internal(ov, slave);
-@@ -923,7 +923,7 @@ out:
- if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0)
- err("Couldn't restore primary I2C slave");
+- down(&disconnect_sem);
++ mutex_lock(&disconnect_mutex);
-- up(&ov->i2c_lock);
-+ mutex_unlock(&ov->i2c_lock);
- return rc;
- }
+ interface = usb_find_interface(&ld_usb_driver, subminor);
-@@ -933,7 +933,7 @@ ov51x_set_slave_ids(struct usb_ov511 *ov
- {
- int rc;
+@@ -355,7 +356,7 @@ unlock_exit:
+ up(&dev->sem);
-- down(&ov->i2c_lock);
-+ mutex_lock(&ov->i2c_lock);
+ unlock_disconnect_exit:
+- up(&disconnect_sem);
++ mutex_unlock(&disconnect_mutex);
- rc = i2c_set_slave_internal(ov, sid);
- if (rc < 0)
-@@ -942,7 +942,7 @@ ov51x_set_slave_ids(struct usb_ov511 *ov
- // FIXME: Is this actually necessary?
- rc = ov51x_reset(ov, OV511_RESET_NOREGS);
- out:
-- up(&ov->i2c_lock);
-+ mutex_unlock(&ov->i2c_lock);
- return rc;
+ return retval;
}
+@@ -740,7 +741,7 @@ static void ld_usb_disconnect(struct usb
+ struct ld_usb *dev;
+ int minor;
-@@ -3832,7 +3832,7 @@ ov51x_alloc(struct usb_ov511 *ov)
- const int raw_bufsize = OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h);
-
- PDEBUG(4, "entered");
-- down(&ov->buf_lock);
-+ mutex_lock(&ov->buf_lock);
+- down(&disconnect_sem);
++ mutex_lock(&disconnect_mutex);
- if (ov->buf_state == BUF_ALLOCATED)
- goto out;
-@@ -3879,12 +3879,12 @@ ov51x_alloc(struct usb_ov511 *ov)
+ dev = usb_get_intfdata(intf);
+ usb_set_intfdata(intf, NULL);
+@@ -761,7 +762,7 @@ static void ld_usb_disconnect(struct usb
+ up(&dev->sem);
+ }
- ov->buf_state = BUF_ALLOCATED;
- out:
-- up(&ov->buf_lock);
-+ mutex_unlock(&ov->buf_lock);
- PDEBUG(4, "leaving");
- return 0;
- error:
- ov51x_do_dealloc(ov);
-- up(&ov->buf_lock);
-+ mutex_unlock(&ov->buf_lock);
- PDEBUG(4, "errored");
- return -ENOMEM;
- }
-@@ -3893,9 +3893,9 @@ static void
- ov51x_dealloc(struct usb_ov511 *ov)
- {
- PDEBUG(4, "entered");
-- down(&ov->buf_lock);
-+ mutex_lock(&ov->buf_lock);
- ov51x_do_dealloc(ov);
-- up(&ov->buf_lock);
-+ mutex_unlock(&ov->buf_lock);
- PDEBUG(4, "leaving");
- }
+- up(&disconnect_sem);
++ mutex_unlock(&disconnect_mutex);
-@@ -3914,7 +3914,7 @@ ov51x_v4l1_open(struct inode *inode, str
+ dev_info(&intf->dev, "LD USB Device #%d now disconnected\n",
+ (minor - USB_LD_MINOR_BASE));
+--- gregkh-2.6.orig/drivers/usb/misc/legousbtower.c
++++ gregkh-2.6/drivers/usb/misc/legousbtower.c
+@@ -83,6 +83,7 @@
+ #include <linux/module.h>
+ #include <linux/smp_lock.h>
+ #include <linux/completion.h>
++#include <linux/mutex.h>
+ #include <asm/uaccess.h>
+ #include <linux/usb.h>
+ #include <linux/poll.h>
+@@ -256,7 +257,7 @@ static void tower_disconnect (struct usb
- PDEBUG(4, "opening");
-- down(&ov->lock);
-+ mutex_lock(&ov->lock);
+ /* prevent races between open() and disconnect */
+-static DECLARE_MUTEX (disconnect_sem);
++static DEFINE_MUTEX (disconnect_mutex);
- err = -EBUSY;
- if (ov->user)
-@@ -3958,7 +3958,7 @@ ov51x_v4l1_open(struct inode *inode, str
- ov51x_led_control(ov, 1);
+ /* file operations needed when we register this driver */
+ static struct file_operations tower_fops = {
+@@ -349,7 +350,7 @@ static int tower_open (struct inode *ino
+ nonseekable_open(inode, file);
+ subminor = iminor(inode);
- out:
-- up(&ov->lock);
-+ mutex_unlock(&ov->lock);
- return err;
- }
+- down (&disconnect_sem);
++ mutex_lock (&disconnect_mutex);
-@@ -3970,7 +3970,7 @@ ov51x_v4l1_close(struct inode *inode, st
+ interface = usb_find_interface (&tower_driver, subminor);
- PDEBUG(4, "ov511_close");
+@@ -427,7 +428,7 @@ unlock_exit:
+ up (&dev->sem);
-- down(&ov->lock);
-+ mutex_lock(&ov->lock);
+ unlock_disconnect_exit:
+- up (&disconnect_sem);
++ mutex_unlock (&disconnect_mutex);
- ov->user--;
- ov51x_stop_isoc(ov);
-@@ -3981,15 +3981,15 @@ ov51x_v4l1_close(struct inode *inode, st
- if (ov->dev)
- ov51x_dealloc(ov);
+ dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval);
-- up(&ov->lock);
-+ mutex_unlock(&ov->lock);
+@@ -1005,7 +1006,7 @@ static void tower_disconnect (struct usb
- /* Device unplugged while open. Only a minimum of unregistration is done
- * here; the disconnect callback already did the rest. */
- if (!ov->dev) {
-- down(&ov->cbuf_lock);
-+ mutex_lock(&ov->cbuf_lock);
- kfree(ov->cbuf);
- ov->cbuf = NULL;
-- up(&ov->cbuf_lock);
-+ mutex_unlock(&ov->cbuf_lock);
+ dbg(2, "%s: enter", __FUNCTION__);
- ov51x_dealloc(ov);
- kfree(ov);
-@@ -4449,12 +4449,12 @@ ov51x_v4l1_ioctl(struct inode *inode, st
- struct usb_ov511 *ov = video_get_drvdata(vdev);
- int rc;
+- down (&disconnect_sem);
++ mutex_lock (&disconnect_mutex);
-- if (down_interruptible(&ov->lock))
-+ if (mutex_lock_interruptible(&ov->lock))
- return -EINTR;
+ dev = usb_get_intfdata (interface);
+ usb_set_intfdata (interface, NULL);
+@@ -1027,7 +1028,7 @@ static void tower_disconnect (struct usb
+ up (&dev->sem);
+ }
- rc = video_usercopy(inode, file, cmd, arg, ov51x_v4l1_ioctl_internal);
+- up (&disconnect_sem);
++ mutex_unlock (&disconnect_mutex);
-- up(&ov->lock);
-+ mutex_unlock(&ov->lock);
- return rc;
- }
+ info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE));
-@@ -4468,7 +4468,7 @@ ov51x_v4l1_read(struct file *file, char
- int i, rc = 0, frmx = -1;
- struct ov511_frame *frame;
+--- gregkh-2.6.orig/drivers/usb/mon/mon_main.c
++++ gregkh-2.6/drivers/usb/mon/mon_main.c
+@@ -12,6 +12,7 @@
+ #include <linux/debugfs.h>
+ #include <linux/smp_lock.h>
+ #include <linux/notifier.h>
++#include <linux/mutex.h>
-- if (down_interruptible(&ov->lock))
-+ if (mutex_lock_interruptible(&ov->lock))
- return -EINTR;
+ #include "usb_mon.h"
+ #include "../core/hcd.h"
+@@ -23,7 +24,7 @@ static void mon_dissolve(struct mon_bus
+ static void mon_bus_drop(struct kref *r);
+ static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus);
- PDEBUG(4, "%ld bytes, noblock=%d", count, noblock);
-@@ -4604,11 +4604,11 @@ restart:
+-DECLARE_MUTEX(mon_lock);
++DEFINE_MUTEX(mon_lock);
- PDEBUG(4, "read finished, returning %ld (sweet)", count);
+ static struct dentry *mon_dir; /* /dbg/usbmon */
+ static LIST_HEAD(mon_buses); /* All buses we know: struct mon_bus */
+@@ -196,14 +197,14 @@ static void mon_bus_remove(struct usb_bu
+ {
+ struct mon_bus *mbus = ubus->mon_bus;
-- up(&ov->lock);
-+ mutex_unlock(&ov->lock);
- return count;
+- down(&mon_lock);
++ mutex_lock(&mon_lock);
+ list_del(&mbus->bus_link);
+ debugfs_remove(mbus->dent_t);
+ debugfs_remove(mbus->dent_s);
- error:
-- up(&ov->lock);
-+ mutex_unlock(&ov->lock);
- return rc;
+ mon_dissolve(mbus, ubus);
+ kref_put(&mbus->ref, mon_bus_drop);
+- up(&mon_lock);
++ mutex_unlock(&mon_lock);
}
-@@ -4631,14 +4631,14 @@ ov51x_v4l1_mmap(struct file *file, struc
- + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))))
- return -EINVAL;
+ static int mon_notify(struct notifier_block *self, unsigned long action,
+@@ -307,9 +308,9 @@ static void mon_bus_init(struct dentry *
+ goto err_create_s;
+ mbus->dent_s = d;
-- if (down_interruptible(&ov->lock))
-+ if (mutex_lock_interruptible(&ov->lock))
- return -EINTR;
+- down(&mon_lock);
++ mutex_lock(&mon_lock);
+ list_add_tail(&mbus->bus_link, &mon_buses);
+- up(&mon_lock);
++ mutex_unlock(&mon_lock);
+ return;
- pos = (unsigned long)ov->fbuf;
- while (size > 0) {
- page = vmalloc_to_pfn((void *)pos);
- if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
-- up(&ov->lock);
-+ mutex_unlock(&ov->lock);
- return -EAGAIN;
- }
- start += PAGE_SIZE;
-@@ -4649,7 +4649,7 @@ ov51x_v4l1_mmap(struct file *file, struc
- size = 0;
- }
+ err_create_s:
+@@ -347,11 +348,11 @@ static int __init mon_init(void)
-- up(&ov->lock);
-+ mutex_unlock(&ov->lock);
+ usb_register_notify(&mon_nb);
+
+- down(&usb_bus_list_lock);
++ mutex_lock(&usb_bus_list_lock);
+ list_for_each_entry (ubus, &usb_bus_list, bus_list) {
+ mon_bus_init(mondir, ubus);
+ }
+- up(&usb_bus_list_lock);
++ mutex_unlock(&usb_bus_list_lock);
return 0;
}
-@@ -5738,11 +5738,10 @@ ov51x_probe(struct usb_interface *intf,
-
- init_waitqueue_head(&ov->wq);
-
-- init_MUTEX(&ov->lock); /* to 1 == available */
-- init_MUTEX(&ov->buf_lock);
-- init_MUTEX(&ov->param_lock);
-- init_MUTEX(&ov->i2c_lock);
-- init_MUTEX(&ov->cbuf_lock);
-+ mutex_init(&ov->lock); /* to 1 == available */
-+ mutex_init(&ov->buf_lock);
-+ mutex_init(&ov->i2c_lock);
-+ mutex_init(&ov->cbuf_lock);
-
- ov->buf_state = BUF_NOT_ALLOCATED;
-
-@@ -5833,10 +5832,10 @@ error:
- }
+@@ -363,7 +364,7 @@ static void __exit mon_exit(void)
+ usb_unregister_notify(&mon_nb);
+ usb_mon_deregister();
- if (ov->cbuf) {
-- down(&ov->cbuf_lock);
-+ mutex_lock(&ov->cbuf_lock);
- kfree(ov->cbuf);
- ov->cbuf = NULL;
-- up(&ov->cbuf_lock);
-+ mutex_unlock(&ov->cbuf_lock);
+- down(&mon_lock);
++ mutex_lock(&mon_lock);
+ while (!list_empty(&mon_buses)) {
+ p = mon_buses.next;
+ mbus = list_entry(p, struct mon_bus, bus_link);
+@@ -387,7 +388,7 @@ static void __exit mon_exit(void)
+ mon_dissolve(mbus, mbus->u_bus);
+ kref_put(&mbus->ref, mon_bus_drop);
}
+- up(&mon_lock);
++ mutex_unlock(&mon_lock);
- kfree(ov);
-@@ -5881,10 +5880,10 @@ ov51x_disconnect(struct usb_interface *i
-
- /* Free the memory */
- if (ov && !ov->user) {
-- down(&ov->cbuf_lock);
-+ mutex_lock(&ov->cbuf_lock);
- kfree(ov->cbuf);
- ov->cbuf = NULL;
-- up(&ov->cbuf_lock);
-+ mutex_unlock(&ov->cbuf_lock);
-
- ov51x_dealloc(ov);
- kfree(ov);
---- gregkh-2.6.orig/drivers/usb/media/ov511.h
-+++ gregkh-2.6/drivers/usb/media/ov511.h
-@@ -5,6 +5,7 @@
- #include <linux/videodev.h>
- #include <linux/smp_lock.h>
+ debugfs_remove(mon_dir);
+ }
+--- gregkh-2.6.orig/drivers/usb/mon/mon_text.c
++++ gregkh-2.6/drivers/usb/mon/mon_text.c
+@@ -8,6 +8,7 @@
+ #include <linux/list.h>
#include <linux/usb.h>
+ #include <linux/time.h>
+#include <linux/mutex.h>
+ #include <asm/uaccess.h>
- #define OV511_DEBUG /* Turn on debug messages */
-
-@@ -435,7 +436,7 @@ struct usb_ov511 {
+ #include "usb_mon.h"
+@@ -54,7 +55,7 @@ struct mon_reader_text {
+ wait_queue_head_t wait;
+ int printf_size;
+ char *printf_buf;
+- struct semaphore printf_lock;
++ struct mutex printf_lock;
- int led_policy; /* LED: off|on|auto; OV511+ only */
+ char slab_name[SLAB_NAME_SZ];
+ };
+@@ -208,7 +209,7 @@ static int mon_text_open(struct inode *i
+ struct mon_reader_text *rp;
+ int rc;
-- struct semaphore lock; /* Serializes user-accessible operations */
-+ struct mutex lock; /* Serializes user-accessible operations */
- int user; /* user count for exclusive use */
+- down(&mon_lock);
++ mutex_lock(&mon_lock);
+ mbus = inode->u.generic_ip;
+ ubus = mbus->u_bus;
- int streaming; /* Are we streaming Isochronous? */
-@@ -473,11 +474,9 @@ struct usb_ov511 {
- int packet_size; /* Frame size per isoc desc */
- int packet_numbering; /* Is ISO frame numbering enabled? */
+@@ -220,7 +221,7 @@ static int mon_text_open(struct inode *i
+ memset(rp, 0, sizeof(struct mon_reader_text));
+ INIT_LIST_HEAD(&rp->e_list);
+ init_waitqueue_head(&rp->wait);
+- init_MUTEX(&rp->printf_lock);
++ mutex_init(&rp->printf_lock);
-- struct semaphore param_lock; /* params lock for this camera */
--
- /* Framebuffer/sbuf management */
- int buf_state;
-- struct semaphore buf_lock;
-+ struct mutex buf_lock;
+ rp->printf_size = PRINTF_DFL;
+ rp->printf_buf = kmalloc(rp->printf_size, GFP_KERNEL);
+@@ -247,7 +248,7 @@ static int mon_text_open(struct inode *i
+ mon_reader_add(mbus, &rp->r);
- struct ov51x_decomp_ops *decomp_ops;
+ file->private_data = rp;
+- up(&mon_lock);
++ mutex_unlock(&mon_lock);
+ return 0;
-@@ -494,12 +493,12 @@ struct usb_ov511 {
- int pal; /* Device is designed for PAL resolution */
+ // err_busy:
+@@ -257,7 +258,7 @@ err_slab:
+ err_alloc_pr:
+ kfree(rp);
+ err_alloc:
+- up(&mon_lock);
++ mutex_unlock(&mon_lock);
+ return rc;
+ }
- /* I2C interface */
-- struct semaphore i2c_lock; /* Protect I2C controller regs */
-+ struct mutex i2c_lock; /* Protect I2C controller regs */
- unsigned char primary_i2c_slave; /* I2C write id of sensor */
+@@ -301,7 +302,7 @@ static ssize_t mon_text_read(struct file
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&rp->wait, &waita);
- /* Control transaction stuff */
- unsigned char *cbuf; /* Buffer for payload */
-- struct semaphore cbuf_lock;
-+ struct mutex cbuf_lock;
- };
+- down(&rp->printf_lock);
++ mutex_lock(&rp->printf_lock);
+ cnt = 0;
+ pbuf = rp->printf_buf;
+ limit = rp->printf_size;
+@@ -358,7 +359,7 @@ static ssize_t mon_text_read(struct file
- /* Used to represent a list of values and their respective symbolic names */
---- gregkh-2.6.orig/drivers/usb/media/se401.c
-+++ gregkh-2.6/drivers/usb/media/se401.c
-@@ -1157,21 +1157,21 @@ static int se401_mmap(struct file *file,
- unsigned long size = vma->vm_end-vma->vm_start;
- unsigned long page, pos;
+ if (copy_to_user(buf, rp->printf_buf, cnt))
+ cnt = -EFAULT;
+- up(&rp->printf_lock);
++ mutex_unlock(&rp->printf_lock);
+ kmem_cache_free(rp->e_slab, ep);
+ return cnt;
+ }
+@@ -371,12 +372,12 @@ static int mon_text_release(struct inode
+ struct list_head *p;
+ struct mon_event_text *ep;
-- down(&se401->lock);
-+ mutex_lock(&se401->lock);
+- down(&mon_lock);
++ mutex_lock(&mon_lock);
+ mbus = inode->u.generic_ip;
- if (se401->dev == NULL) {
-- up(&se401->lock);
-+ mutex_unlock(&se401->lock);
- return -EIO;
- }
- if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
-- up(&se401->lock);
-+ mutex_unlock(&se401->lock);
- return -EINVAL;
- }
- pos = (unsigned long)se401->fbuf;
- while (size > 0) {
- page = vmalloc_to_pfn((void *)pos);
- if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
-- up(&se401->lock);
-+ mutex_unlock(&se401->lock);
- return -EAGAIN;
- }
- start += PAGE_SIZE;
-@@ -1181,7 +1181,7 @@ static int se401_mmap(struct file *file,
- else
- size = 0;
+ if (mbus->nreaders <= 0) {
+ printk(KERN_ERR TAG ": consistency error on close\n");
+- up(&mon_lock);
++ mutex_unlock(&mon_lock);
+ return 0;
}
-- up(&se401->lock);
-+ mutex_unlock(&se401->lock);
+ mon_reader_del(mbus, &rp->r);
+@@ -402,7 +403,7 @@ static int mon_text_release(struct inode
+ kfree(rp->printf_buf);
+ kfree(rp);
- return 0;
+- up(&mon_lock);
++ mutex_unlock(&mon_lock);
+ return 0;
}
-@@ -1366,7 +1366,7 @@ static int se401_probe(struct usb_interf
- memcpy(&se401->vdev, &se401_template, sizeof(se401_template));
- memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name));
- init_waitqueue_head(&se401->wq);
-- init_MUTEX(&se401->lock);
-+ mutex_init(&se401->lock);
- wmb();
-
- if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
---- gregkh-2.6.orig/drivers/usb/media/se401.h
-+++ gregkh-2.6/drivers/usb/media/se401.h
-@@ -5,6 +5,7 @@
- #include <asm/uaccess.h>
- #include <linux/videodev.h>
- #include <linux/smp_lock.h>
-+#include <linux/mutex.h>
- #define se401_DEBUG /* Turn on debug messages */
+--- gregkh-2.6.orig/drivers/usb/mon/usb_mon.h
++++ gregkh-2.6/drivers/usb/mon/usb_mon.h
+@@ -49,7 +49,7 @@ void mon_reader_del(struct mon_bus *mbus
+ */
+ extern char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len);
-@@ -189,7 +190,7 @@ struct usb_se401 {
- int maxframesize;
- int cframesize; /* current framesize */
+-extern struct semaphore mon_lock;
++extern struct mutex mon_lock;
-- struct semaphore lock;
-+ struct mutex lock;
- int user; /* user count for exclusive use */
- int removed; /* device disconnected */
+ extern struct file_operations mon_fops_text;
+ extern struct file_operations mon_fops_stat;
+--- gregkh-2.6.orig/drivers/usb/storage/scsiglue.c
++++ gregkh-2.6/drivers/usb/storage/scsiglue.c
+@@ -47,6 +47,7 @@
---- gregkh-2.6.orig/drivers/usb/media/stv680.c
-+++ gregkh-2.6/drivers/usb/media/stv680.c
-@@ -67,6 +67,7 @@
- #include <linux/errno.h>
- #include <linux/videodev.h>
- #include <linux/usb.h>
+ #include <linux/slab.h>
+ #include <linux/module.h>
+#include <linux/mutex.h>
- #include "stv680.h"
-
-@@ -1258,22 +1259,22 @@ static int stv680_mmap (struct file *fil
- unsigned long size = vma->vm_end-vma->vm_start;
- unsigned long page, pos;
-
-- down (&stv680->lock);
-+ mutex_lock(&stv680->lock);
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_cmnd.h>
+@@ -271,9 +272,9 @@ static int device_reset(struct scsi_cmnd
+ US_DEBUGP("%s called\n", __FUNCTION__);
- if (stv680->udev == NULL) {
-- up (&stv680->lock);
-+ mutex_unlock(&stv680->lock);
- return -EIO;
- }
- if (size > (((STV680_NUMFRAMES * stv680->maxframesize) + PAGE_SIZE - 1)
- & ~(PAGE_SIZE - 1))) {
-- up (&stv680->lock);
-+ mutex_unlock(&stv680->lock);
- return -EINVAL;
- }
- pos = (unsigned long) stv680->fbuf;
- while (size > 0) {
- page = vmalloc_to_pfn((void *)pos);
- if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
-- up (&stv680->lock);
-+ mutex_unlock(&stv680->lock);
- return -EAGAIN;
- }
- start += PAGE_SIZE;
-@@ -1283,7 +1284,7 @@ static int stv680_mmap (struct file *fil
- else
- size = 0;
- }
-- up (&stv680->lock);
-+ mutex_unlock(&stv680->lock);
+ /* lock the device pointers and do the reset */
+- down(&(us->dev_semaphore));
++ mutex_lock(&(us->dev_mutex));
+ result = us->transport_reset(us);
+- up(&(us->dev_semaphore));
++ mutex_unlock(&us->dev_mutex);
- return 0;
+ return result < 0 ? FAILED : SUCCESS;
}
-@@ -1409,7 +1410,7 @@ static int stv680_probe (struct usb_inte
+@@ -286,9 +287,9 @@ static int bus_reset(struct scsi_cmnd *s
- memcpy (stv680->vdev->name, stv680->camera_name, strlen (stv680->camera_name));
- init_waitqueue_head (&stv680->wq);
-- init_MUTEX (&stv680->lock);
-+ mutex_init (&stv680->lock);
- wmb ();
+ US_DEBUGP("%s called\n", __FUNCTION__);
- if (video_register_device (stv680->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
---- gregkh-2.6.orig/drivers/usb/media/stv680.h
-+++ gregkh-2.6/drivers/usb/media/stv680.h
-@@ -118,7 +118,7 @@ struct usb_stv {
- int origGain;
- int origMode; /* original camera mode */
+- down(&(us->dev_semaphore));
++ mutex_lock(&(us->dev_mutex));
+ result = usb_stor_port_reset(us);
+- up(&(us->dev_semaphore));
++ mutex_unlock(&us->dev_mutex);
-- struct semaphore lock; /* to lock the structure */
-+ struct mutex lock; /* to lock the structure */
- int user; /* user count for exclusive use */
- int removed; /* device disconnected */
- int streaming; /* Are we streaming video? */
---- gregkh-2.6.orig/drivers/usb/media/usbvideo.c
-+++ gregkh-2.6/drivers/usb/media/usbvideo.c
-@@ -714,7 +714,7 @@ int usbvideo_register(
- cams->md_module = md;
- if (cams->md_module == NULL)
- warn("%s: module == NULL!", __FUNCTION__);
-- init_MUTEX(&cams->lock); /* to 1 == available */
-+ mutex_init(&cams->lock); /* to 1 == available */
+ return result < 0 ? FAILED : SUCCESS;
+ }
+--- gregkh-2.6.orig/drivers/usb/storage/usb.c
++++ gregkh-2.6/drivers/usb/storage/usb.c
+@@ -55,6 +55,7 @@
+ #include <linux/init.h>
+ #include <linux/slab.h>
+ #include <linux/kthread.h>
++#include <linux/mutex.h>
- for (i = 0; i < num_cams; i++) {
- struct uvd *up = &cams->cam[i];
-@@ -862,7 +862,7 @@ static void usbvideo_Disconnect(struct u
- if (uvd->debug > 0)
- info("%s(%p.)", __FUNCTION__, intf);
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_cmnd.h>
+@@ -188,7 +189,7 @@ static int storage_suspend(struct usb_in
+ struct us_data *us = usb_get_intfdata(iface);
-- down(&uvd->lock);
-+ mutex_lock(&uvd->lock);
- uvd->remove_pending = 1; /* Now all ISO data will be ignored */
+ /* Wait until no command is running */
+- down(&us->dev_semaphore);
++ mutex_lock(&us->dev_mutex);
- /* At this time we ask to cancel outstanding URBs */
-@@ -882,7 +882,7 @@ static void usbvideo_Disconnect(struct u
- info("%s: In use, disconnect pending.", __FUNCTION__);
- else
- usbvideo_CameraRelease(uvd);
-- up(&uvd->lock);
-+ mutex_unlock(&uvd->lock);
- info("USB camera disconnected.");
+ US_DEBUGP("%s\n", __FUNCTION__);
+ if (us->suspend_resume_hook)
+@@ -198,7 +199,7 @@ static int storage_suspend(struct usb_in
+ /* When runtime PM is working, we'll set a flag to indicate
+ * whether we should autoresume when a SCSI request arrives. */
- usbvideo_ClientDecModCount(uvd);
-@@ -929,19 +929,19 @@ static int usbvideo_find_struct(struct u
- err("No usbvideo handle?");
- return -1;
- }
-- down(&cams->lock);
-+ mutex_lock(&cams->lock);
- for (u = 0; u < cams->num_cameras; u++) {
- struct uvd *uvd = &cams->cam[u];
- if (!uvd->uvd_used) /* This one is free */
- {
- uvd->uvd_used = 1; /* In use now */
-- init_MUTEX(&uvd->lock); /* to 1 == available */
-+ mutex_init(&uvd->lock); /* to 1 == available */
- uvd->dev = NULL;
- rv = u;
- break;
- }
- }
-- up(&cams->lock);
-+ mutex_unlock(&cams->lock);
- return rv;
+- up(&us->dev_semaphore);
++ mutex_unlock(&us->dev_mutex);
+ return 0;
}
-@@ -983,7 +983,7 @@ struct uvd *usbvideo_AllocateDevice(stru
- /* Not relying upon caller we increase module counter ourselves */
- usbvideo_ClientIncModCount(uvd);
+@@ -206,14 +207,14 @@ static int storage_resume(struct usb_int
+ {
+ struct us_data *us = usb_get_intfdata(iface);
-- down(&uvd->lock);
-+ mutex_lock(&uvd->lock);
- for (i=0; i < USBVIDEO_NUMSBUF; i++) {
- uvd->sbuf[i].urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
- if (uvd->sbuf[i].urb == NULL) {
-@@ -1006,7 +1006,7 @@ struct uvd *usbvideo_AllocateDevice(stru
- * return control to the client's probe function right now.
- */
- allocate_done:
-- up (&uvd->lock);
-+ mutex_unlock(&uvd->lock);
- usbvideo_ClientDecModCount(uvd);
- return uvd;
+- down(&us->dev_semaphore);
++ mutex_lock(&us->dev_mutex);
+
+ US_DEBUGP("%s\n", __FUNCTION__);
+ if (us->suspend_resume_hook)
+ (us->suspend_resume_hook)(us, US_RESUME);
+ iface->dev.power.power_state.event = PM_EVENT_ON;
+
+- up(&us->dev_semaphore);
++ mutex_unlock(&us->dev_mutex);
+ return 0;
}
-@@ -1120,7 +1120,7 @@ static int usbvideo_v4l_open(struct inod
- info("%s($%p)", __FUNCTION__, dev);
- usbvideo_ClientIncModCount(uvd);
-- down(&uvd->lock);
-+ mutex_lock(&uvd->lock);
+@@ -276,12 +277,12 @@ static int usb_stor_control_thread(void
+ US_DEBUGP("*** thread awakened.\n");
- if (uvd->user) {
- err("%s: Someone tried to open an already opened device!", __FUNCTION__);
-@@ -1201,7 +1201,7 @@ static int usbvideo_v4l_open(struct inod
- }
+ /* lock the device pointers */
+- down(&(us->dev_semaphore));
++ mutex_lock(&(us->dev_mutex));
+
+ /* if the device has disconnected, we are free to exit */
+ if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+ US_DEBUGP("-- exiting\n");
+- up(&(us->dev_semaphore));
++ mutex_unlock(&us->dev_mutex);
+ break;
}
- }
-- up(&uvd->lock);
-+ mutex_unlock(&uvd->lock);
- if (errCode != 0)
- usbvideo_ClientDecModCount(uvd);
- if (uvd->debug > 0)
-@@ -1230,7 +1230,7 @@ static int usbvideo_v4l_close(struct ino
- if (uvd->debug > 1)
- info("%s($%p)", __FUNCTION__, dev);
-- down(&uvd->lock);
-+ mutex_lock(&uvd->lock);
- GET_CALLBACK(uvd, stopDataPump)(uvd);
- usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size);
- uvd->fbuf = NULL;
-@@ -1251,7 +1251,7 @@ static int usbvideo_v4l_close(struct ino
- info("usbvideo_v4l_close: Final disconnect.");
- usbvideo_CameraRelease(uvd);
- }
-- up(&uvd->lock);
-+ mutex_unlock(&uvd->lock);
- usbvideo_ClientDecModCount(uvd);
+@@ -370,7 +371,7 @@ SkipForAbort:
+ scsi_unlock(host);
- if (uvd->debug > 1)
-@@ -1511,7 +1511,7 @@ static ssize_t usbvideo_v4l_read(struct
- if (uvd->debug >= 1)
- info("%s: %Zd. bytes, noblock=%d.", __FUNCTION__, count, noblock);
+ /* unlock the device pointers */
+- up(&(us->dev_semaphore));
++ mutex_unlock(&us->dev_mutex);
+ } /* for (;;) */
-- down(&uvd->lock);
-+ mutex_lock(&uvd->lock);
+ scsi_host_put(host);
+@@ -815,8 +816,8 @@ static void quiesce_and_remove_host(stru
+ * The thread will exit when it sees the DISCONNECTING flag. */
- /* See if a frame is completed, then use it. */
- for(i = 0; i < USBVIDEO_NUMFRAMES; i++) {
-@@ -1643,7 +1643,7 @@ static ssize_t usbvideo_v4l_read(struct
+ /* Wait for the current command to finish, then remove the host */
+- down(&us->dev_semaphore);
+- up(&us->dev_semaphore);
++ mutex_lock(&us->dev_mutex);
++ mutex_unlock(&us->dev_mutex);
+
+ /* queuecommand won't accept any new commands and the control
+ * thread won't execute a previously-queued command. If there
+@@ -870,9 +871,9 @@ retry:
+ /* For bulk-only devices, determine the max LUN value */
+ if (us->protocol == US_PR_BULK &&
+ !(us->flags & US_FL_SINGLE_LUN)) {
+- down(&us->dev_semaphore);
++ mutex_lock(&us->dev_mutex);
+ us->max_lun = usb_stor_Bulk_max_lun(us);
+- up(&us->dev_semaphore);
++ mutex_unlock(&us->dev_mutex);
}
- }
- read_done:
-- up(&uvd->lock);
-+ mutex_unlock(&uvd->lock);
- return count;
- }
+ scsi_scan_host(us_to_host(us));
+ printk(KERN_DEBUG "usb-storage: device scan complete\n");
+@@ -912,7 +913,7 @@ static int storage_probe(struct usb_inte
---- gregkh-2.6.orig/drivers/usb/media/usbvideo.h
-+++ gregkh-2.6/drivers/usb/media/usbvideo.h
-@@ -19,6 +19,7 @@
- #include <linux/config.h>
- #include <linux/videodev.h>
- #include <linux/usb.h>
+ us = host_to_us(host);
+ memset(us, 0, sizeof(struct us_data));
+- init_MUTEX(&(us->dev_semaphore));
++ mutex_init(&(us->dev_mutex));
+ init_MUTEX_LOCKED(&(us->sema));
+ init_completion(&(us->notify));
+ init_waitqueue_head(&us->delay_wait);
+--- gregkh-2.6.orig/drivers/usb/storage/usb.h
++++ gregkh-2.6/drivers/usb/storage/usb.h
+@@ -49,6 +49,7 @@
+ #include <linux/blkdev.h>
+ #include <linux/smp_lock.h>
+ #include <linux/completion.h>
+#include <linux/mutex.h>
+ #include <scsi/scsi_host.h>
- /* Most helpful debugging aid */
- #define assert(expr) ((void) ((expr) ? 0 : (err("assert failed at line %d",__LINE__))))
-@@ -213,7 +214,7 @@ struct uvd {
- unsigned long flags; /* FLAGS_USBVIDEO_xxx */
- unsigned long paletteBits; /* Which palettes we accept? */
- unsigned short defaultPalette; /* What palette to use for read() */
-- struct semaphore lock;
-+ struct mutex lock;
- int user; /* user count for exclusive use */
-
- videosize_t videosize; /* Current setting */
-@@ -272,7 +273,7 @@ struct usbvideo {
- int num_cameras; /* As allocated */
- struct usb_driver usbdrv; /* Interface to the USB stack */
- char drvName[80]; /* Driver name */
-- struct semaphore lock; /* Mutex protecting camera structures */
-+ struct mutex lock; /* Mutex protecting camera structures */
- struct usbvideo_cb cb; /* Table of callbacks (virtual methods) */
- struct video_device vdt; /* Video device template */
- struct uvd *cam; /* Array of camera structures */
+ struct us_data;
+@@ -103,9 +104,9 @@ typedef void (*pm_hook)(struct us_data *
+ struct us_data {
+ /* The device we're working with
+ * It's important to note:
+- * (o) you must hold dev_semaphore to change pusb_dev
++ * (o) you must hold dev_mutex to change pusb_dev
+ */
+- struct semaphore dev_semaphore; /* protect pusb_dev */
++ struct mutex dev_mutex; /* protect pusb_dev */
+ struct usb_device *pusb_dev; /* this usb_device */
+ struct usb_interface *pusb_intf; /* this interface */
+ struct us_unusual_dev *unusual_dev; /* device-filter entry */
diff --git a/usb/usb-core-and-hcds-don-t-put_device-while-atomic.patch b/usb/usb-core-and-hcds-don-t-put_device-while-atomic.patch
index 3b044e60c3e8b..fb56e59c9d5eb 100644
--- a/usb/usb-core-and-hcds-don-t-put_device-while-atomic.patch
+++ b/usb/usb-core-and-hcds-don-t-put_device-while-atomic.patch
@@ -27,24 +27,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/uhci-q.c | 2 --
7 files changed, 5 insertions(+), 14 deletions(-)
---- gregkh-2.6.orig/drivers/usb/host/uhci-q.c
-+++ gregkh-2.6/drivers/usb/host/uhci-q.c
-@@ -179,7 +179,6 @@ static struct uhci_qh *uhci_alloc_qh(str
- qh->hep = hep;
- qh->udev = udev;
- hep->hcpriv = qh;
-- usb_get_dev(udev);
-
- } else { /* Skeleton QH */
- qh->state = QH_STATE_ACTIVE;
-@@ -197,7 +196,6 @@ static void uhci_free_qh(struct uhci_hcd
- list_del(&qh->node);
- if (qh->udev) {
- qh->hep->hcpriv = NULL;
-- usb_put_dev(qh->udev);
- uhci_free_td(uhci, qh->dummy_td);
- }
- dma_pool_free(uhci->qh_pool, qh, qh->dma_handle);
--- gregkh-2.6.orig/drivers/usb/core/hcd.c
+++ gregkh-2.6/drivers/usb/core/hcd.c
@@ -1105,7 +1105,6 @@ static void urb_unlink (struct urb *urb)
@@ -63,25 +45,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
list_add_tail (&urb->urb_list, &ep->urb_list);
status = 0;
break;
---- gregkh-2.6.orig/drivers/usb/host/isp116x-hcd.c
-+++ gregkh-2.6/drivers/usb/host/isp116x-hcd.c
-@@ -724,7 +724,7 @@ static int isp116x_urb_enqueue(struct us
- ep = hep->hcpriv;
- else {
- INIT_LIST_HEAD(&ep->schedule);
-- ep->udev = usb_get_dev(udev);
-+ ep->udev = udev;
- ep->epnum = epnum;
- ep->maxpacket = usb_maxpacket(udev, urb->pipe, is_out);
- usb_settoggle(udev, epnum, is_out, 0);
-@@ -891,7 +891,6 @@ static void isp116x_endpoint_disable(str
- if (!list_empty(&hep->urb_list))
- WARN("ep %p not empty?\n", ep);
-
-- usb_put_dev(ep->udev);
- kfree(ep);
- hep->hcpriv = NULL;
- }
--- gregkh-2.6.orig/drivers/usb/host/ehci-mem.c
+++ gregkh-2.6/drivers/usb/host/ehci-mem.c
@@ -75,7 +75,6 @@ static void qh_destroy (struct kref *kre
@@ -139,6 +102,25 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
return 1;
}
+--- gregkh-2.6.orig/drivers/usb/host/isp116x-hcd.c
++++ gregkh-2.6/drivers/usb/host/isp116x-hcd.c
+@@ -724,7 +724,7 @@ static int isp116x_urb_enqueue(struct us
+ ep = hep->hcpriv;
+ else {
+ INIT_LIST_HEAD(&ep->schedule);
+- ep->udev = usb_get_dev(udev);
++ ep->udev = udev;
+ ep->epnum = epnum;
+ ep->maxpacket = usb_maxpacket(udev, urb->pipe, is_out);
+ usb_settoggle(udev, epnum, is_out, 0);
+@@ -891,7 +891,6 @@ static void isp116x_endpoint_disable(str
+ if (!list_empty(&hep->urb_list))
+ WARN("ep %p not empty?\n", ep);
+
+- usb_put_dev(ep->udev);
+ kfree(ep);
+ hep->hcpriv = NULL;
+ }
--- gregkh-2.6.orig/drivers/usb/host/sl811-hcd.c
+++ gregkh-2.6/drivers/usb/host/sl811-hcd.c
@@ -853,7 +853,7 @@ static int sl811h_urb_enqueue(
@@ -158,3 +140,21 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
kfree(ep);
hep->hcpriv = NULL;
}
+--- gregkh-2.6.orig/drivers/usb/host/uhci-q.c
++++ gregkh-2.6/drivers/usb/host/uhci-q.c
+@@ -179,7 +179,6 @@ static struct uhci_qh *uhci_alloc_qh(str
+ qh->hep = hep;
+ qh->udev = udev;
+ hep->hcpriv = qh;
+- usb_get_dev(udev);
+
+ } else { /* Skeleton QH */
+ qh->state = QH_STATE_ACTIVE;
+@@ -197,7 +196,6 @@ static void uhci_free_qh(struct uhci_hcd
+ list_del(&qh->node);
+ if (qh->udev) {
+ qh->hep->hcpriv = NULL;
+- usb_put_dev(qh->udev);
+ uhci_free_td(uhci, qh->dummy_td);
+ }
+ dma_pool_free(uhci->qh_pool, qh, qh->dma_handle);
diff --git a/usb/usb-drivers-usb-core-message.c-make-usb_get_string-static.patch b/usb/usb-drivers-usb-core-message.c-make-usb_get_string-static.patch
index 3410d727f133a..22986520f932f 100644
--- a/usb/usb-drivers-usb-core-message.c-make-usb_get_string-static.patch
+++ b/usb/usb-drivers-usb-core-message.c-make-usb_get_string-static.patch
@@ -18,17 +18,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
include/linux/usb.h | 2 --
2 files changed, 2 insertions(+), 5 deletions(-)
---- gregkh-2.6.orig/include/linux/usb.h
-+++ gregkh-2.6/include/linux/usb.h
-@@ -1018,8 +1018,6 @@ extern int usb_get_descriptor(struct usb
- unsigned char descindex, void *buf, int size);
- extern int usb_get_status(struct usb_device *dev,
- int type, int target, void *data);
--extern int usb_get_string(struct usb_device *dev,
-- unsigned short langid, unsigned char index, void *buf, int size);
- extern int usb_string(struct usb_device *dev, int index,
- char *buf, size_t size);
-
--- gregkh-2.6.orig/drivers/usb/core/message.c
+++ gregkh-2.6/drivers/usb/core/message.c
@@ -631,8 +631,8 @@ int usb_get_descriptor(struct usb_device
@@ -50,3 +39,14 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
EXPORT_SYMBOL(usb_string);
// synchronous calls that also maintain usbcore state
+--- gregkh-2.6.orig/include/linux/usb.h
++++ gregkh-2.6/include/linux/usb.h
+@@ -1018,8 +1018,6 @@ extern int usb_get_descriptor(struct usb
+ unsigned char descindex, void *buf, int size);
+ extern int usb_get_status(struct usb_device *dev,
+ int type, int target, void *data);
+-extern int usb_get_string(struct usb_device *dev,
+- unsigned short langid, unsigned char index, void *buf, int size);
+ extern int usb_string(struct usb_device *dev, int index,
+ char *buf, size_t size);
+
diff --git a/usb/usb-ehci-and-nf2-quirk.patch b/usb/usb-ehci-and-nf2-quirk.patch
index e9d8d664f975a..3305ef7a7e64d 100644
--- a/usb/usb-ehci-and-nf2-quirk.patch
+++ b/usb/usb-ehci-and-nf2-quirk.patch
@@ -27,6 +27,26 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/ehci.h | 3 ++-
3 files changed, 30 insertions(+), 2 deletions(-)
+--- gregkh-2.6.orig/drivers/usb/host/ehci-hub.c
++++ gregkh-2.6/drivers/usb/host/ehci-hub.c
+@@ -359,6 +359,8 @@ static int ehci_hub_control (
+ case USB_PORT_FEAT_SUSPEND:
+ if (temp & PORT_RESET)
+ goto error;
++ if (ehci->no_selective_suspend)
++ break;
+ if (temp & PORT_SUSPEND) {
+ if ((temp & PORT_PE) == 0)
+ goto error;
+@@ -514,6 +516,8 @@ static int ehci_hub_control (
+ temp &= ~PORT_RWC_BITS;
+ switch (wValue) {
+ case USB_PORT_FEAT_SUSPEND:
++ if (ehci->no_selective_suspend)
++ break;
+ if ((temp & PORT_PE) == 0
+ || (temp & PORT_RESET) != 0)
+ goto error;
--- gregkh-2.6.orig/drivers/usb/host/ehci-pci.c
+++ gregkh-2.6/drivers/usb/host/ehci-pci.c
@@ -106,11 +106,11 @@ static int ehci_pci_setup(struct usb_hcd
@@ -79,26 +99,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
retval = ehci_pci_reinit(ehci, pdev);
done:
return retval;
---- gregkh-2.6.orig/drivers/usb/host/ehci-hub.c
-+++ gregkh-2.6/drivers/usb/host/ehci-hub.c
-@@ -359,6 +359,8 @@ static int ehci_hub_control (
- case USB_PORT_FEAT_SUSPEND:
- if (temp & PORT_RESET)
- goto error;
-+ if (ehci->no_selective_suspend)
-+ break;
- if (temp & PORT_SUSPEND) {
- if ((temp & PORT_PE) == 0)
- goto error;
-@@ -514,6 +516,8 @@ static int ehci_hub_control (
- temp &= ~PORT_RWC_BITS;
- switch (wValue) {
- case USB_PORT_FEAT_SUSPEND:
-+ if (ehci->no_selective_suspend)
-+ break;
- if ((temp & PORT_PE) == 0
- || (temp & PORT_RESET) != 0)
- goto error;
--- gregkh-2.6.orig/drivers/usb/host/ehci.h
+++ gregkh-2.6/drivers/usb/host/ehci.h
@@ -89,6 +89,8 @@ struct ehci_hcd { /* one per controlle
diff --git a/usb/usb-et61x51-driver-updates.patch b/usb/usb-et61x51-driver-updates.patch
index b2b1b194f4af2..27d200d631932 100644
--- a/usb/usb-et61x51-driver-updates.patch
+++ b/usb/usb-et61x51-driver-updates.patch
@@ -59,6 +59,88 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This driver follows the V4L2 API specifications. In particular, it enforces two
rules:
+--- gregkh-2.6.orig/drivers/usb/media/et61x251.h
++++ gregkh-2.6/drivers/usb/media/et61x251.h
+@@ -33,7 +33,9 @@
+ #include <linux/types.h>
+ #include <linux/param.h>
+ #include <linux/rwsem.h>
+-#include <asm/semaphore.h>
++#include <linux/mutex.h>
++#include <linux/stddef.h>
++#include <linux/string.h>
+
+ #include "et61x251_sensor.h"
+
+@@ -51,6 +53,7 @@
+ #define ET61X251_ALTERNATE_SETTING 13
+ #define ET61X251_URB_TIMEOUT msecs_to_jiffies(2 * ET61X251_ISO_PACKETS)
+ #define ET61X251_CTRL_TIMEOUT 100
++#define ET61X251_FRAME_TIMEOUT 2
+
+ /*****************************************************************************/
+
+@@ -127,15 +130,16 @@ struct et61x251_sysfs_attr {
+
+ struct et61x251_module_param {
+ u8 force_munmap;
++ u16 frame_timeout;
+ };
+
+-static DECLARE_MUTEX(et61x251_sysfs_lock);
++static DEFINE_MUTEX(et61x251_sysfs_lock);
+ static DECLARE_RWSEM(et61x251_disconnect);
+
+ struct et61x251_device {
+ struct video_device* v4ldev;
+
+- struct et61x251_sensor* sensor;
++ struct et61x251_sensor sensor;
+
+ struct usb_device* usbdev;
+ struct urb* urb[ET61X251_URBS];
+@@ -157,19 +161,28 @@ struct et61x251_device {
+ enum et61x251_dev_state state;
+ u8 users;
+
+- struct semaphore dev_sem, fileop_sem;
++ struct mutex dev_mutex, fileop_mutex;
+ spinlock_t queue_lock;
+ wait_queue_head_t open, wait_frame, wait_stream;
+ };
+
+ /*****************************************************************************/
+
++struct et61x251_device*
++et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id)
++{
++ if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id))
++ return cam;
++
++ return NULL;
++}
++
++
+ void
+ et61x251_attach_sensor(struct et61x251_device* cam,
+ struct et61x251_sensor* sensor)
+ {
+- cam->sensor = sensor;
+- cam->sensor->usbdev = cam->usbdev;
++ memcpy(&cam->sensor, sensor, sizeof(struct et61x251_sensor));
+ }
+
+ /*****************************************************************************/
+@@ -212,7 +225,8 @@ do {
+
+ #undef PDBG
+ #define PDBG(fmt, args...) \
+-dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args)
++dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
++ __FUNCTION__, __LINE__ , ## args)
+
+ #undef PDBGG
+ #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
--- gregkh-2.6.orig/drivers/usb/media/et61x251_core.c
+++ gregkh-2.6/drivers/usb/media/et61x251_core.c
@@ -25,11 +25,9 @@
@@ -1084,88 +1166,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
if (!cam->users)
kfree(cam);
---- gregkh-2.6.orig/drivers/usb/media/et61x251.h
-+++ gregkh-2.6/drivers/usb/media/et61x251.h
-@@ -33,7 +33,9 @@
- #include <linux/types.h>
- #include <linux/param.h>
- #include <linux/rwsem.h>
--#include <asm/semaphore.h>
-+#include <linux/mutex.h>
-+#include <linux/stddef.h>
-+#include <linux/string.h>
-
- #include "et61x251_sensor.h"
-
-@@ -51,6 +53,7 @@
- #define ET61X251_ALTERNATE_SETTING 13
- #define ET61X251_URB_TIMEOUT msecs_to_jiffies(2 * ET61X251_ISO_PACKETS)
- #define ET61X251_CTRL_TIMEOUT 100
-+#define ET61X251_FRAME_TIMEOUT 2
-
- /*****************************************************************************/
-
-@@ -127,15 +130,16 @@ struct et61x251_sysfs_attr {
-
- struct et61x251_module_param {
- u8 force_munmap;
-+ u16 frame_timeout;
- };
-
--static DECLARE_MUTEX(et61x251_sysfs_lock);
-+static DEFINE_MUTEX(et61x251_sysfs_lock);
- static DECLARE_RWSEM(et61x251_disconnect);
-
- struct et61x251_device {
- struct video_device* v4ldev;
-
-- struct et61x251_sensor* sensor;
-+ struct et61x251_sensor sensor;
-
- struct usb_device* usbdev;
- struct urb* urb[ET61X251_URBS];
-@@ -157,19 +161,28 @@ struct et61x251_device {
- enum et61x251_dev_state state;
- u8 users;
-
-- struct semaphore dev_sem, fileop_sem;
-+ struct mutex dev_mutex, fileop_mutex;
- spinlock_t queue_lock;
- wait_queue_head_t open, wait_frame, wait_stream;
- };
-
- /*****************************************************************************/
-
-+struct et61x251_device*
-+et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id)
-+{
-+ if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id))
-+ return cam;
-+
-+ return NULL;
-+}
-+
-+
- void
- et61x251_attach_sensor(struct et61x251_device* cam,
- struct et61x251_sensor* sensor)
- {
-- cam->sensor = sensor;
-- cam->sensor->usbdev = cam->usbdev;
-+ memcpy(&cam->sensor, sensor, sizeof(struct et61x251_sensor));
- }
-
- /*****************************************************************************/
-@@ -212,7 +225,8 @@ do {
-
- #undef PDBG
- #define PDBG(fmt, args...) \
--dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args)
-+dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
-+ __FUNCTION__, __LINE__ , ## args)
-
- #undef PDBGG
- #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
--- gregkh-2.6.orig/drivers/usb/media/et61x251_sensor.h
+++ gregkh-2.6/drivers/usb/media/et61x251_sensor.h
@@ -42,6 +42,9 @@ static int (*et61x251_sensor_table[])(st
diff --git a/usb/usb-gadget-driver-section-fixups.patch b/usb/usb-gadget-driver-section-fixups.patch
index ff346c59f1164..82ea27ecd63cb 100644
--- a/usb/usb-gadget-driver-section-fixups.patch
+++ b/usb/usb-gadget-driver-section-fixups.patch
@@ -24,35 +24,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
include/linux/usb_gadget.h | 7 +++++--
5 files changed, 15 insertions(+), 12 deletions(-)
---- gregkh-2.6.orig/drivers/usb/gadget/zero.c
-+++ gregkh-2.6/drivers/usb/gadget/zero.c
-@@ -1119,7 +1119,7 @@ zero_autoresume (unsigned long _dev)
-
- /*-------------------------------------------------------------------------*/
-
--static void
-+static void __exit
- zero_unbind (struct usb_gadget *gadget)
- {
- struct zero_dev *dev = get_gadget_data (gadget);
-@@ -1136,7 +1136,7 @@ zero_unbind (struct usb_gadget *gadget)
- set_gadget_data (gadget, NULL);
- }
-
--static int
-+static int __init
- zero_bind (struct usb_gadget *gadget)
- {
- struct zero_dev *dev;
-@@ -1288,7 +1288,7 @@ static struct usb_gadget_driver zero_dri
- #endif
- .function = (char *) longname,
- .bind = zero_bind,
-- .unbind = zero_unbind,
-+ .unbind = __exit_p(zero_unbind),
-
- .setup = zero_setup,
- .disconnect = zero_disconnect,
--- gregkh-2.6.orig/drivers/usb/gadget/ether.c
+++ gregkh-2.6/drivers/usb/gadget/ether.c
@@ -2125,7 +2125,7 @@ eth_req_free (struct usb_ep *ep, struct
@@ -122,6 +93,35 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
{
struct gs_dev *dev = get_gadget_data(gadget);
+--- gregkh-2.6.orig/drivers/usb/gadget/zero.c
++++ gregkh-2.6/drivers/usb/gadget/zero.c
+@@ -1119,7 +1119,7 @@ zero_autoresume (unsigned long _dev)
+
+ /*-------------------------------------------------------------------------*/
+
+-static void
++static void __exit
+ zero_unbind (struct usb_gadget *gadget)
+ {
+ struct zero_dev *dev = get_gadget_data (gadget);
+@@ -1136,7 +1136,7 @@ zero_unbind (struct usb_gadget *gadget)
+ set_gadget_data (gadget, NULL);
+ }
+
+-static int
++static int __init
+ zero_bind (struct usb_gadget *gadget)
+ {
+ struct zero_dev *dev;
+@@ -1288,7 +1288,7 @@ static struct usb_gadget_driver zero_dri
+ #endif
+ .function = (char *) longname,
+ .bind = zero_bind,
+- .unbind = zero_unbind,
++ .unbind = __exit_p(zero_unbind),
+
+ .setup = zero_setup,
+ .disconnect = zero_disconnect,
--- gregkh-2.6.orig/include/linux/usb_gadget.h
+++ gregkh-2.6/include/linux/usb_gadget.h
@@ -801,7 +801,9 @@ struct usb_gadget_driver {
diff --git a/usb/usb-gotemp.patch b/usb/usb-gotemp.patch
index 15b86c9307375..b5dc94381a614 100644
--- a/usb/usb-gotemp.patch
+++ b/usb/usb-gotemp.patch
@@ -5,6 +5,16 @@
4 files changed, 304 insertions(+)
---
+--- gregkh-2.6.orig/drivers/usb/Makefile
++++ gregkh-2.6/drivers/usb/Makefile
+@@ -67,6 +67,7 @@ obj-$(CONFIG_USB_AUERSWALD) += misc/
+ obj-$(CONFIG_USB_CYTHERM) += misc/
+ obj-$(CONFIG_USB_EMI26) += misc/
+ obj-$(CONFIG_USB_EMI62) += misc/
++obj-$(CONFIG_USB_GOTEMP) += misc/
+ obj-$(CONFIG_USB_IDMOUSE) += misc/
+ obj-$(CONFIG_USB_LCD) += misc/
+ obj-$(CONFIG_USB_LD) += misc/
--- gregkh-2.6.orig/drivers/usb/misc/Kconfig
+++ gregkh-2.6/drivers/usb/misc/Kconfig
@@ -101,6 +101,16 @@ config USB_CYTHERM
@@ -329,13 +339,3 @@
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
---- gregkh-2.6.orig/drivers/usb/Makefile
-+++ gregkh-2.6/drivers/usb/Makefile
-@@ -67,6 +67,7 @@ obj-$(CONFIG_USB_AUERSWALD) += misc/
- obj-$(CONFIG_USB_CYTHERM) += misc/
- obj-$(CONFIG_USB_EMI26) += misc/
- obj-$(CONFIG_USB_EMI62) += misc/
-+obj-$(CONFIG_USB_GOTEMP) += misc/
- obj-$(CONFIG_USB_IDMOUSE) += misc/
- obj-$(CONFIG_USB_LCD) += misc/
- obj-$(CONFIG_USB_LD) += misc/
diff --git a/usb/usb-kzalloc-for-hid.patch b/usb/usb-kzalloc-for-hid.patch
index cbb5073b5fa82..3e38e45f75821 100644
--- a/usb/usb-kzalloc-for-hid.patch
+++ b/usb/usb-kzalloc-for-hid.patch
@@ -80,21 +80,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
parser->device = device;
end = start + size;
---- gregkh-2.6.orig/drivers/usb/input/hid-tmff.c
-+++ gregkh-2.6/drivers/usb/input/hid-tmff.c
-@@ -113,11 +113,10 @@ int hid_tmff_init(struct hid_device *hid
- struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
- struct input_dev *input_dev = hidinput->input;
-
-- private = kmalloc(sizeof(struct tmff_device), GFP_KERNEL);
-+ private = kzalloc(sizeof(struct tmff_device), GFP_KERNEL);
- if (!private)
- return -ENOMEM;
-
-- memset(private, 0, sizeof(struct tmff_device));
- hid->ff_private = private;
-
- /* Find the report to use */
--- gregkh-2.6.orig/drivers/usb/input/hid-lgff.c
+++ gregkh-2.6/drivers/usb/input/hid-lgff.c
@@ -154,10 +154,9 @@ int hid_lgff_init(struct hid_device* hid
@@ -124,6 +109,21 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
return ret;
}
+--- gregkh-2.6.orig/drivers/usb/input/hid-tmff.c
++++ gregkh-2.6/drivers/usb/input/hid-tmff.c
+@@ -113,11 +113,10 @@ int hid_tmff_init(struct hid_device *hid
+ struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+ struct input_dev *input_dev = hidinput->input;
+
+- private = kmalloc(sizeof(struct tmff_device), GFP_KERNEL);
++ private = kzalloc(sizeof(struct tmff_device), GFP_KERNEL);
+ if (!private)
+ return -ENOMEM;
+
+- memset(private, 0, sizeof(struct tmff_device));
+ hid->ff_private = private;
+
+ /* Find the report to use */
--- gregkh-2.6.orig/drivers/usb/input/hiddev.c
+++ gregkh-2.6/drivers/usb/input/hiddev.c
@@ -257,9 +257,8 @@ static int hiddev_open(struct inode * in
diff --git a/usb/usb-ohci-uses-driver-model-wakeup-flags.patch b/usb/usb-ohci-uses-driver-model-wakeup-flags.patch
index 19c597db48d6f..e9cbce5a0527f 100644
--- a/usb/usb-ohci-uses-driver-model-wakeup-flags.patch
+++ b/usb/usb-ohci-uses-driver-model-wakeup-flags.patch
@@ -146,44 +146,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
return 0;
}
---- gregkh-2.6.orig/drivers/usb/host/ohci-pci.c
-+++ gregkh-2.6/drivers/usb/host/ohci-pci.c
-@@ -35,7 +35,10 @@ ohci_pci_start (struct usb_hcd *hcd)
- struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- int ret;
-
-- if(hcd->self.controller && hcd->self.controller->bus == &pci_bus_type) {
-+ /* REVISIT this whole block should move to reset(), which handles
-+ * all the other one-time init.
-+ */
-+ if (hcd->self.controller) {
- struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
-
- /* AMD 756, for most chips (early revs), corrupts register
-@@ -45,7 +48,8 @@ ohci_pci_start (struct usb_hcd *hcd)
- && pdev->device == 0x740c) {
- ohci->flags = OHCI_QUIRK_AMD756;
- ohci_dbg (ohci, "AMD756 erratum 4 workaround\n");
-- // also somewhat erratum 10 (suspend/resume issues)
-+ /* also erratum 10 (suspend/resume issues) */
-+ device_init_wakeup(&hcd->self.root_hub->dev, 0);
- }
-
- /* FIXME for some of the early AMD 760 southbridges, OHCI
-@@ -88,6 +92,13 @@ ohci_pci_start (struct usb_hcd *hcd)
- ohci_dbg (ohci,
- "enabled Compaq ZFMicro chipset quirk\n");
- }
-+
-+ /* RWC may not be set for add-in PCI cards, since boot
-+ * firmware probably ignored them. This transfers PCI
-+ * PM wakeup capabilities (once the PCI layer is fixed).
-+ */
-+ if (device_may_wakeup(&pdev->dev))
-+ ohci->hc_control |= OHCI_CTRL_RWC;
- }
-
- /* NOTE: there may have already been a first reset, to
--- gregkh-2.6.orig/drivers/usb/host/ohci-hub.c
+++ gregkh-2.6/drivers/usb/host/ohci-hub.c
@@ -107,7 +107,7 @@ static int ohci_bus_suspend (struct usb_
@@ -226,3 +188,41 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
continue;
can_suspend = 0;
}
+--- gregkh-2.6.orig/drivers/usb/host/ohci-pci.c
++++ gregkh-2.6/drivers/usb/host/ohci-pci.c
+@@ -35,7 +35,10 @@ ohci_pci_start (struct usb_hcd *hcd)
+ struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+ int ret;
+
+- if(hcd->self.controller && hcd->self.controller->bus == &pci_bus_type) {
++ /* REVISIT this whole block should move to reset(), which handles
++ * all the other one-time init.
++ */
++ if (hcd->self.controller) {
+ struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+
+ /* AMD 756, for most chips (early revs), corrupts register
+@@ -45,7 +48,8 @@ ohci_pci_start (struct usb_hcd *hcd)
+ && pdev->device == 0x740c) {
+ ohci->flags = OHCI_QUIRK_AMD756;
+ ohci_dbg (ohci, "AMD756 erratum 4 workaround\n");
+- // also somewhat erratum 10 (suspend/resume issues)
++ /* also erratum 10 (suspend/resume issues) */
++ device_init_wakeup(&hcd->self.root_hub->dev, 0);
+ }
+
+ /* FIXME for some of the early AMD 760 southbridges, OHCI
+@@ -88,6 +92,13 @@ ohci_pci_start (struct usb_hcd *hcd)
+ ohci_dbg (ohci,
+ "enabled Compaq ZFMicro chipset quirk\n");
+ }
++
++ /* RWC may not be set for add-in PCI cards, since boot
++ * firmware probably ignored them. This transfers PCI
++ * PM wakeup capabilities (once the PCI layer is fixed).
++ */
++ if (device_may_wakeup(&pdev->dev))
++ ohci->hc_control |= OHCI_CTRL_RWC;
+ }
+
+ /* NOTE: there may have already been a first reset, to
diff --git a/usb/usb-remove-obsolete_oss_usb_driver-drivers.patch b/usb/usb-remove-obsolete_oss_usb_driver-drivers.patch
index f96dd077f8871..2f3e82d030d85 100644
--- a/usb/usb-remove-obsolete_oss_usb_driver-drivers.patch
+++ b/usb/usb-remove-obsolete_oss_usb_driver-drivers.patch
@@ -21,6 +21,17 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/class/usb-midi.h | 164 -
7 files changed, 6347 deletions(-)
+--- gregkh-2.6.orig/drivers/usb/Makefile
++++ gregkh-2.6/drivers/usb/Makefile
+@@ -17,8 +17,6 @@ obj-$(CONFIG_USB_SL811_HCD) += host/
+ obj-$(CONFIG_ETRAX_USB_HOST) += host/
+
+ obj-$(CONFIG_USB_ACM) += class/
+-obj-$(CONFIG_USB_AUDIO) += class/
+-obj-$(CONFIG_USB_MIDI) += class/
+ obj-$(CONFIG_USB_PRINTER) += class/
+
+ obj-$(CONFIG_USB_STORAGE) += storage/
--- gregkh-2.6.orig/drivers/usb/class/Kconfig
+++ gregkh-2.6/drivers/usb/class/Kconfig
@@ -4,53 +4,6 @@
@@ -77,17 +88,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
config USB_ACM
tristate "USB Modem (CDC ACM) support"
depends on USB
---- gregkh-2.6.orig/drivers/usb/Makefile
-+++ gregkh-2.6/drivers/usb/Makefile
-@@ -17,8 +17,6 @@ obj-$(CONFIG_USB_SL811_HCD) += host/
- obj-$(CONFIG_ETRAX_USB_HOST) += host/
-
- obj-$(CONFIG_USB_ACM) += class/
--obj-$(CONFIG_USB_AUDIO) += class/
--obj-$(CONFIG_USB_MIDI) += class/
- obj-$(CONFIG_USB_PRINTER) += class/
-
- obj-$(CONFIG_USB_STORAGE) += storage/
--- gregkh-2.6.orig/drivers/usb/class/Makefile
+++ gregkh-2.6/drivers/usb/class/Makefile
@@ -4,6 +4,4 @@
@@ -97,2442 +97,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-obj-$(CONFIG_USB_AUDIO) += audio.o
-obj-$(CONFIG_USB_MIDI) += usb-midi.o
obj-$(CONFIG_USB_PRINTER) += usblp.o
---- gregkh-2.6.orig/drivers/usb/class/usb-midi.h
-+++ /dev/null
-@@ -1,164 +0,0 @@
--/*
-- usb-midi.h -- USB-MIDI driver
--
-- Copyright (C) 2001
-- NAGANO Daisuke <breeze.nagano@nifty.ne.jp>
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2, or (at your option)
-- any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-- */
--
--/* ------------------------------------------------------------------------- */
--
--#ifndef _USB_MIDI_H_
--#define _USB_MIDI_H_
--
--#ifndef USB_SUBCLASS_MIDISTREAMING
--#define USB_SUBCLASS_MIDISTREAMING 3
--#endif
--
--/* ------------------------------------------------------------------------- */
--/* Roland MIDI Devices */
--
--#define USB_VENDOR_ID_ROLAND 0x0582
--#define USBMIDI_ROLAND_UA100G 0x0000
--#define USBMIDI_ROLAND_MPU64 0x0002
--#define USBMIDI_ROLAND_SC8850 0x0003
--#define USBMIDI_ROLAND_SC8820 0x0007
--#define USBMIDI_ROLAND_UM2 0x0005
--#define USBMIDI_ROLAND_UM1 0x0009
--#define USBMIDI_ROLAND_PC300 0x0008
--
--/* YAMAHA MIDI Devices */
--#define USB_VENDOR_ID_YAMAHA 0x0499
--#define USBMIDI_YAMAHA_MU1000 0x1001
--
--/* Steinberg MIDI Devices */
--#define USB_VENDOR_ID_STEINBERG 0x0763
--#define USBMIDI_STEINBERG_USB2MIDI 0x1001
--
--/* Mark of the Unicorn MIDI Devices */
--#define USB_VENDOR_ID_MOTU 0x07fd
--#define USBMIDI_MOTU_FASTLANE 0x0001
--
--/* ------------------------------------------------------------------------- */
--/* Supported devices */
--
--struct usb_midi_endpoint {
-- int endpoint;
-- int cableId; /* if bit-n == 1 then cableId-n is enabled (n: 0 - 15) */
--};
--
--struct usb_midi_device {
-- char *deviceName;
--
-- u16 idVendor;
-- u16 idProduct;
-- int interface;
-- int altSetting; /* -1: auto detect */
--
-- struct usb_midi_endpoint in[15];
-- struct usb_midi_endpoint out[15];
--};
--
--static struct usb_midi_device usb_midi_devices[] = {
-- { /* Roland UM-1 */
-- "Roland UM-1",
-- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UM1, 2, -1,
-- { { 0x81, 1 }, {-1, -1} },
-- { { 0x01, 1,}, {-1, -1} },
-- },
--
-- { /* Roland UM-2 */
-- "Roland UM-2" ,
-- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UM2, 2, -1,
-- { { 0x81, 3 }, {-1, -1} },
-- { { 0x01, 3,}, {-1, -1} },
-- },
--
--/** Next entry courtesy research by Michael Minn <michael@michaelminn.com> **/
-- { /* Roland UA-100 */
-- "Roland UA-100",
-- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UA100G, 2, -1,
-- { { 0x82, 7 }, {-1, -1} }, /** cables 0,1 and 2 for SYSEX **/
-- { { 0x02, 7 }, {-1, -1} },
-- },
--
--/** Next entry courtesy research by Michael Minn <michael@michaelminn.com> **/
-- { /* Roland SC8850 */
-- "Roland SC8850",
-- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8850, 2, -1,
-- { { 0x81, 0x3f }, {-1, -1} },
-- { { 0x01, 0x3f }, {-1, -1} },
-- },
--
-- { /* Roland SC8820 */
-- "Roland SC8820",
-- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820, 2, -1,
-- { { 0x81, 0x13 }, {-1, -1} },
-- { { 0x01, 0x13 }, {-1, -1} },
-- },
--
-- { /* Roland SC8820 */
-- "Roland SC8820",
-- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820, 2, -1,
-- { { 0x81, 17 }, {-1, -1} },
-- { { 0x01, 17 }, {-1, -1} },
-- },
--
-- { /* YAMAHA MU1000 */
-- "YAMAHA MU1000",
-- USB_VENDOR_ID_YAMAHA, USBMIDI_YAMAHA_MU1000, 0, -1,
-- { { 0x81, 1 }, {-1, -1} },
-- { { 0x01, 15 }, {-1, -1} },
-- },
-- { /* Roland PC-300 */
-- "Roland PC-300",
-- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_PC300, 2, -1,
-- { { 0x81, 1 }, {-1, -1} },
-- { { 0x01, 1 }, {-1, -1} },
-- },
-- { /* MOTU Fastlane USB */
-- "MOTU Fastlane USB",
-- USB_VENDOR_ID_MOTU, USBMIDI_MOTU_FASTLANE, 1, 0,
-- { { 0x82, 3 }, {-1, -1} },
-- { { 0x02, 3 }, {-1, -1} },
-- }
--};
--
--#define VENDOR_SPECIFIC_USB_MIDI_DEVICES (sizeof(usb_midi_devices)/sizeof(struct usb_midi_device))
--
--/* for Hot-Plugging */
--
--static struct usb_device_id usb_midi_ids [] = {
-- { .match_flags = (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS),
-- .bInterfaceClass = USB_CLASS_AUDIO, .bInterfaceSubClass = USB_SUBCLASS_MIDISTREAMING},
-- { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UM1 ) },
-- { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UM2 ) },
-- { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UA100G ) },
-- { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_PC300 ) },
-- { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8850 ) },
-- { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820 ) },
-- { USB_DEVICE( USB_VENDOR_ID_YAMAHA, USBMIDI_YAMAHA_MU1000 ) },
-- { USB_DEVICE( USB_VENDOR_ID_MOTU, USBMIDI_MOTU_FASTLANE ) },
--/* { USB_DEVICE( USB_VENDOR_ID_STEINBERG, USBMIDI_STEINBERG_USB2MIDI ) },*/
-- { } /* Terminating entry */
--};
--
--MODULE_DEVICE_TABLE (usb, usb_midi_ids);
--
--/* ------------------------------------------------------------------------- */
--#endif /* _USB_MIDI_H_ */
--
--
---- gregkh-2.6.orig/drivers/usb/class/usb-midi.c
-+++ /dev/null
-@@ -1,2153 +0,0 @@
--/*
-- usb-midi.c -- USB-MIDI driver
--
-- Copyright (C) 2001
-- NAGANO Daisuke <breeze.nagano@nifty.ne.jp>
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2, or (at your option)
-- any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--
-- This driver is based on:
-- - 'Universal Serial Bus Device Class Definition for MIDI Device'
-- - linux/drivers/sound/es1371.c, linux/drivers/usb/audio.c
-- - alsa/lowlevel/pci/cs64xx.c
-- - umidi.c for NetBSD
-- */
--
--/* ------------------------------------------------------------------------- */
--
--
--#include <linux/module.h>
--#include <linux/kernel.h>
--#include <linux/sched.h>
--#include <linux/list.h>
--#include <linux/slab.h>
--#include <linux/usb.h>
--#include <linux/poll.h>
--#include <linux/sound.h>
--#include <linux/init.h>
--#include <asm/semaphore.h>
--
--#include "usb-midi.h"
--
--/* ------------------------------------------------------------------------- */
--
--/* More verbose on syslog */
--#undef MIDI_DEBUG
--
--#define MIDI_IN_BUFSIZ 1024
--
--#define HAVE_SUPPORT_USB_MIDI_CLASS
--
--#undef HAVE_SUPPORT_ALSA
--
--/* ------------------------------------------------------------------------- */
--
--static int singlebyte = 0;
--module_param(singlebyte, int, 0);
--MODULE_PARM_DESC(singlebyte,"Enable sending MIDI messages with single message packet");
--
--static int maxdevices = 4;
--module_param(maxdevices, int, 0);
--MODULE_PARM_DESC(maxdevices,"Max number of allocatable MIDI device");
--
--static int uvendor = -1;
--module_param(uvendor, int, 0);
--MODULE_PARM_DESC(uvendor, "The USB Vendor ID of a semi-compliant interface");
--
--static int uproduct = -1;
--module_param(uproduct, int, 0);
--MODULE_PARM_DESC(uproduct, "The USB Product ID of a semi-compliant interface");
--
--static int uinterface = -1;
--module_param(uinterface, int, 0);
--MODULE_PARM_DESC(uinterface, "The Interface number of a semi-compliant interface");
--
--static int ualt = -1;
--module_param(ualt, int, 0);
--MODULE_PARM_DESC(ualt, "The optional alternative setting of a semi-compliant interface");
--
--static int umin = -1;
--module_param(umin, int, 0);
--MODULE_PARM_DESC(umin, "The input endpoint of a semi-compliant interface");
--
--static int umout = -1;
--module_param(umout, int, 0);
--MODULE_PARM_DESC(umout, "The output endpoint of a semi-compliant interface");
--
--static int ucable = -1;
--module_param(ucable, int, 0);
--MODULE_PARM_DESC(ucable, "The cable number used for a semi-compliant interface");
--
--/** Note -- the usb_string() returns only Latin-1 characters.
-- * (unicode chars <= 255). To support Japanese, a unicode16LE-to-EUC or
-- * unicode16LE-to-JIS routine is needed to wrap around usb_get_string().
-- **/
--static unsigned short ulangid = 0x0409; /** 0x0411 for Japanese **/
--module_param(ulangid, ushort, 0);
--MODULE_PARM_DESC(ulangid, "The optional preferred USB Language ID for all devices");
--
--MODULE_AUTHOR("NAGANO Daisuke <breeze.nagano@nifty.ne.jp>");
--MODULE_DESCRIPTION("USB-MIDI driver");
--MODULE_LICENSE("GPL");
--
--/* ------------------------------------------------------------------------- */
--
--/** MIDIStreaming Class-Specific Interface Descriptor Subtypes **/
--
--#define MS_DESCRIPTOR_UNDEFINED 0
--#define MS_HEADER 1
--#define MIDI_IN_JACK 2
--#define MIDI_OUT_JACK 3
--/* Spec reads: ELEMENT */
--#define ELEMENT_DESCRIPTOR 4
--
--#define MS_HEADER_LENGTH 7
--
--/** MIDIStreaming Class-Specific Endpoint Descriptor Subtypes **/
--
--#define DESCRIPTOR_UNDEFINED 0
--/* Spec reads: MS_GENERAL */
--#define MS_GENERAL_ENDPOINT 1
--
--/** MIDIStreaming MIDI IN and OUT Jack Types **/
--
--#define JACK_TYPE_UNDEFINED 0
--/* Spec reads: EMBEDDED */
--#define EMBEDDED_JACK 1
--/* Spec reads: EXTERNAL */
--#define EXTERNAL_JACK 2
--
--
--/* structure summary
--
-- usb_midi_state usb_device
-- | |
-- *| *| per ep
-- in_ep out_ep
-- | |
-- *| *| per cable
-- min mout
-- | | (cable to device pairing magic)
-- | |
-- usb_midi_dev dev_id (major,minor) == file->private_data
--
--*/
--
--/* usb_midi_state: corresponds to a USB-MIDI module */
--struct usb_midi_state {
-- struct list_head mididev;
--
-- struct usb_device *usbdev;
--
-- struct list_head midiDevList;
-- struct list_head inEndpointList;
-- struct list_head outEndpointList;
--
-- spinlock_t lock;
--
-- unsigned int count; /* usage counter */
--};
--
--/* midi_out_endpoint: corresponds to an output endpoint */
--struct midi_out_endpoint {
-- struct list_head list;
--
-- struct usb_device *usbdev;
-- int endpoint;
-- spinlock_t lock;
-- wait_queue_head_t wait;
--
-- unsigned char *buf;
-- int bufWrPtr;
-- int bufSize;
--
-- struct urb *urb;
--};
--
--/* midi_in_endpoint: corresponds to an input endpoint */
--struct midi_in_endpoint {
-- struct list_head list;
--
-- struct usb_device *usbdev;
-- int endpoint;
-- spinlock_t lock;
-- wait_queue_head_t wait;
--
-- struct usb_mididev *cables[16]; // cables open for read
-- int readers; // number of cables open for read
--
-- struct urb *urb;
-- unsigned char *recvBuf;
-- int recvBufSize;
-- int urbSubmitted; //FIXME: == readers > 0
--};
--
--/* usb_mididev: corresponds to a logical device */
--struct usb_mididev {
-- struct list_head list;
--
-- struct usb_midi_state *midi;
-- int dev_midi;
-- mode_t open_mode;
--
-- struct {
-- struct midi_in_endpoint *ep;
-- int cableId;
--
--// as we are pushing data from usb_bulk_read to usb_midi_read,
--// we need a larger, cyclic buffer here.
-- unsigned char buf[MIDI_IN_BUFSIZ];
-- int bufRdPtr;
-- int bufWrPtr;
-- int bufRemains;
-- } min;
--
-- struct {
-- struct midi_out_endpoint *ep;
-- int cableId;
--
-- unsigned char buf[3];
-- int bufPtr;
-- int bufRemains;
--
-- int isInExclusive;
-- unsigned char lastEvent;
-- } mout;
--
-- int singlebyte;
--};
--
--/** Map the high nybble of MIDI voice messages to number of Message bytes.
-- * High nyble ranges from 0x8 to 0xe
-- */
--
--static int remains_80e0[] = {
-- 3, /** 0x8X Note Off **/
-- 3, /** 0x9X Note On **/
-- 3, /** 0xAX Poly-key pressure **/
-- 3, /** 0xBX Control Change **/
-- 2, /** 0xCX Program Change **/
-- 2, /** 0xDX Channel pressure **/
-- 3 /** 0xEX PitchBend Change **/
--};
--
--/** Map the messages to a number of Message bytes.
-- *
-- **/
--static int remains_f0f6[] = {
-- 0, /** 0xF0 **/
-- 2, /** 0XF1 **/
-- 3, /** 0XF2 **/
-- 2, /** 0XF3 **/
-- 2, /** 0XF4 (Undefined by MIDI Spec, and subject to change) **/
-- 2, /** 0XF5 (Undefined by MIDI Spec, and subject to change) **/
-- 1 /** 0XF6 **/
--};
--
--/** Map the messages to a CIN (Code Index Number).
-- *
-- **/
--static int cin_f0ff[] = {
-- 4, /** 0xF0 System Exclusive Message Start (special cases may be 6 or 7) */
-- 2, /** 0xF1 **/
-- 3, /** 0xF2 **/
-- 2, /** 0xF3 **/
-- 2, /** 0xF4 **/
-- 2, /** 0xF5 **/
-- 5, /** 0xF6 **/
-- 5, /** 0xF7 End of System Exclusive Message (May be 6 or 7) **/
-- 5, /** 0xF8 **/
-- 5, /** 0xF9 **/
-- 5, /** 0xFA **/
-- 5, /** 0xFB **/
-- 5, /** 0xFC **/
-- 5, /** 0xFD **/
-- 5, /** 0xFE **/
-- 5 /** 0xFF **/
--};
--
--/** Map MIDIStreaming Event packet Code Index Number (low nybble of byte 0)
-- * to the number of bytes of valid MIDI data.
-- *
-- * CIN of 0 and 1 are NOT USED in MIDIStreaming 1.0.
-- *
-- **/
--static int cin_to_len[] = {
-- 0, 0, 2, 3,
-- 3, 1, 2, 3,
-- 3, 3, 3, 3,
-- 2, 2, 3, 1
--};
--
--
--/* ------------------------------------------------------------------------- */
--
--static struct list_head mididevs = LIST_HEAD_INIT(mididevs);
--
--static DECLARE_MUTEX(open_sem);
--static DECLARE_WAIT_QUEUE_HEAD(open_wait);
--
--
--/* ------------------------------------------------------------------------- */
--
--static void usb_write_callback(struct urb *urb, struct pt_regs *regs)
--{
-- struct midi_out_endpoint *ep = (struct midi_out_endpoint *)urb->context;
--
-- if ( waitqueue_active( &ep->wait ) )
-- wake_up_interruptible( &ep->wait );
--}
--
--
--static int usb_write( struct midi_out_endpoint *ep, unsigned char *buf, int len )
--{
-- struct usb_device *d;
-- int pipe;
-- int ret = 0;
-- int status;
-- int maxretry = 50;
--
-- DECLARE_WAITQUEUE(wait,current);
-- init_waitqueue_head(&ep->wait);
--
-- d = ep->usbdev;
-- pipe = usb_sndbulkpipe(d, ep->endpoint);
-- usb_fill_bulk_urb( ep->urb, d, pipe, (unsigned char*)buf, len,
-- usb_write_callback, ep );
--
-- status = usb_submit_urb(ep->urb, GFP_KERNEL);
--
-- if (status) {
-- printk(KERN_ERR "usbmidi: Cannot submit urb (%d)\n",status);
-- ret = -EIO;
-- goto error;
-- }
--
-- add_wait_queue( &ep->wait, &wait );
-- set_current_state( TASK_INTERRUPTIBLE );
--
-- while( ep->urb->status == -EINPROGRESS ) {
-- if ( maxretry-- < 0 ) {
-- printk(KERN_ERR "usbmidi: usb_bulk_msg timed out\n");
-- ret = -ETIME;
-- break;
-- }
-- interruptible_sleep_on_timeout( &ep->wait, 10 );
-- }
-- set_current_state( TASK_RUNNING );
-- remove_wait_queue( &ep->wait, &wait );
--
--error:
-- return ret;
--}
--
--
--/** Copy data from URB to In endpoint buf.
-- * Discard if CIN == 0 or CIN = 1.
-- *
-- *
-- **/
--
--static void usb_bulk_read(struct urb *urb, struct pt_regs *regs)
--{
-- struct midi_in_endpoint *ep = (struct midi_in_endpoint *)(urb->context);
-- unsigned char *data = urb->transfer_buffer;
-- int i, j, wake;
--
-- if ( !ep->urbSubmitted ) {
-- return;
-- }
--
-- if ( (urb->status == 0) && (urb->actual_length > 0) ) {
-- wake = 0;
-- spin_lock( &ep->lock );
--
-- for(j = 0; j < urb->actual_length; j += 4) {
-- int cin = (data[j]>>0)&0xf;
-- int cab = (data[j]>>4)&0xf;
-- struct usb_mididev *cable = ep->cables[cab];
-- if ( cable ) {
-- int len = cin_to_len[cin]; /** length of MIDI data **/
-- for (i = 0; i < len; i++) {
-- cable->min.buf[cable->min.bufWrPtr] = data[1+i+j];
-- cable->min.bufWrPtr = (cable->min.bufWrPtr+1)%MIDI_IN_BUFSIZ;
-- if (cable->min.bufRemains < MIDI_IN_BUFSIZ)
-- cable->min.bufRemains += 1;
-- else /** need to drop data **/
-- cable->min.bufRdPtr += (cable->min.bufRdPtr+1)%MIDI_IN_BUFSIZ;
-- wake = 1;
-- }
-- }
-- }
--
-- spin_unlock ( &ep->lock );
-- if ( wake ) {
-- wake_up( &ep->wait );
-- }
-- }
--
-- /* urb->dev must be reinitialized on 2.4.x kernels */
-- urb->dev = ep->usbdev;
--
-- urb->actual_length = 0;
-- usb_submit_urb(urb, GFP_ATOMIC);
--}
--
--
--
--/* ------------------------------------------------------------------------- */
--
--/* This routine must be called with spin_lock */
--
--/** Wrapper around usb_write().
-- * This routine must be called with spin_lock held on ep.
-- * Called by midiWrite(), putOneMidiEvent(), and usb_midi_write();
-- **/
--static int flush_midi_buffer( struct midi_out_endpoint *ep )
--{
-- int ret=0;
--
-- if ( ep->bufWrPtr > 0 ) {
-- ret = usb_write( ep, ep->buf, ep->bufWrPtr );
-- ep->bufWrPtr = 0;
-- }
--
-- return ret;
--}
--
--
--/* ------------------------------------------------------------------------- */
--
--
--/** Given a MIDI Event, determine size of data to be attached to
-- * USB-MIDI packet.
-- * Returns 1, 2 or 3.
-- * Called by midiWrite();
-- * Uses remains_80e0 and remains_f0f6;
-- **/
--static int get_remains(int event)
--{
-- int ret;
--
-- if ( event < 0x80 ) {
-- ret = 1;
-- } else if ( event < 0xf0 ) {
-- ret = remains_80e0[((event-0x80)>>4)&0x0f];
-- } else if ( event < 0xf7 ) {
-- ret = remains_f0f6[event-0xf0];
-- } else {
-- ret = 1;
-- }
--
-- return ret;
--}
--
--/** Given the output MIDI data in the output buffer, computes a reasonable
-- * CIN.
-- * Called by putOneMidiEvent().
-- **/
--static int get_CIN( struct usb_mididev *m )
--{
-- int cin;
--
-- if ( m->mout.buf[0] == 0xf7 ) {
-- cin = 5;
-- }
-- else if ( m->mout.buf[1] == 0xf7 ) {
-- cin = 6;
-- }
-- else if ( m->mout.buf[2] == 0xf7 ) {
-- cin = 7;
-- }
-- else {
-- if ( m->mout.isInExclusive == 1 ) {
-- cin = 4;
-- } else if ( m->mout.buf[0] < 0x80 ) {
-- /** One byte that we know nothing about. **/
-- cin = 0xF;
-- } else if ( m->mout.buf[0] < 0xf0 ) {
-- /** MIDI Voice messages 0x8X to 0xEX map to cin 0x8 to 0xE. **/
-- cin = (m->mout.buf[0]>>4)&0x0f;
-- }
-- else {
-- /** Special lookup table exists for real-time events. **/
-- cin = cin_f0ff[m->mout.buf[0]-0xf0];
-- }
-- }
--
-- return cin;
--}
--
--
--/* ------------------------------------------------------------------------- */
--
--
--
--/** Move data to USB endpoint buffer.
-- *
-- **/
--static int put_one_midi_event(struct usb_mididev *m)
--{
-- int cin;
-- unsigned long flags;
-- struct midi_out_endpoint *ep = m->mout.ep;
-- int ret=0;
--
-- cin = get_CIN( m );
-- if ( cin > 0x0f || cin < 0 ) {
-- return -EINVAL;
-- }
--
-- spin_lock_irqsave( &ep->lock, flags );
-- ep->buf[ep->bufWrPtr++] = (m->mout.cableId<<4) | cin;
-- ep->buf[ep->bufWrPtr++] = m->mout.buf[0];
-- ep->buf[ep->bufWrPtr++] = m->mout.buf[1];
-- ep->buf[ep->bufWrPtr++] = m->mout.buf[2];
-- if ( ep->bufWrPtr >= ep->bufSize ) {
-- ret = flush_midi_buffer( ep );
-- }
-- spin_unlock_irqrestore( &ep->lock, flags);
--
-- m->mout.buf[0] = m->mout.buf[1] = m->mout.buf[2] = 0;
-- m->mout.bufPtr = 0;
--
-- return ret;
--}
--
--/** Write the MIDI message v on the midi device.
-- * Called by usb_midi_write();
-- * Responsible for packaging a MIDI data stream into USB-MIDI packets.
-- **/
--
--static int midi_write( struct usb_mididev *m, int v )
--{
-- unsigned long flags;
-- struct midi_out_endpoint *ep = m->mout.ep;
-- int ret=0;
-- unsigned char c = (unsigned char)v;
-- unsigned char sysrt_buf[4];
--
-- if ( m->singlebyte != 0 ) {
-- /** Simple code to handle the single-byte USB-MIDI protocol. */
-- spin_lock_irqsave( &ep->lock, flags );
-- if ( ep->bufWrPtr+4 > ep->bufSize ) {
-- ret = flush_midi_buffer( ep );
-- if ( !ret ) {
-- spin_unlock_irqrestore( &ep->lock, flags );
-- return ret;
-- }
-- }
-- ep->buf[ep->bufWrPtr++] = (m->mout.cableId<<4) | 0x0f; /* single byte */
-- ep->buf[ep->bufWrPtr++] = c;
-- ep->buf[ep->bufWrPtr++] = 0;
-- ep->buf[ep->bufWrPtr++] = 0;
-- if ( ep->bufWrPtr >= ep->bufSize ) {
-- ret = flush_midi_buffer( ep );
-- }
-- spin_unlock_irqrestore( &ep->lock, flags );
--
-- return ret;
-- }
-- /** Normal USB-MIDI protocol begins here. */
--
-- if ( c > 0xf7 ) { /* system: Realtime messages */
-- /** Realtime messages are written IMMEDIATELY. */
-- sysrt_buf[0] = (m->mout.cableId<<4) | 0x0f;
-- sysrt_buf[1] = c;
-- sysrt_buf[2] = 0;
-- sysrt_buf[3] = 0;
-- spin_lock_irqsave( &ep->lock, flags );
-- ret = usb_write( ep, sysrt_buf, 4 );
-- spin_unlock_irqrestore( &ep->lock, flags );
-- /* m->mout.lastEvent = 0; */
--
-- return ret;
-- }
--
-- if ( c >= 0x80 ) {
-- if ( c < 0xf0 ) {
-- m->mout.lastEvent = c;
-- m->mout.isInExclusive = 0;
-- m->mout.bufRemains = get_remains(c);
-- } else if ( c == 0xf0 ) {
-- /* m->mout.lastEvent = 0; */
-- m->mout.isInExclusive = 1;
-- m->mout.bufRemains = get_remains(c);
-- } else if ( c == 0xf7 && m->mout.isInExclusive == 1 ) {
-- /* m->mout.lastEvent = 0; */
-- m->mout.isInExclusive = 0;
-- m->mout.bufRemains = 1;
-- } else if ( c > 0xf0 ) {
-- /* m->mout.lastEvent = 0; */
-- m->mout.isInExclusive = 0;
-- m->mout.bufRemains = get_remains(c);
-- }
--
-- } else if ( m->mout.bufRemains == 0 && m->mout.isInExclusive == 0 ) {
-- if ( m->mout.lastEvent == 0 ) {
-- return 0; /* discard, waiting for the first event */
-- }
-- /** track status **/
-- m->mout.buf[0] = m->mout.lastEvent;
-- m->mout.bufPtr = 1;
-- m->mout.bufRemains = get_remains(m->mout.lastEvent)-1;
-- }
--
-- m->mout.buf[m->mout.bufPtr++] = c;
-- m->mout.bufRemains--;
-- if ( m->mout.bufRemains == 0 || m->mout.bufPtr >= 3) {
-- ret = put_one_midi_event(m);
-- }
--
-- return ret;
--}
--
--
--/* ------------------------------------------------------------------------- */
--
--/** Basic operation on /dev/midiXX as registered through struct file_operations.
-- *
-- * Basic contract: Used to change the current read/write position in a file.
-- * On success, the non-negative position is reported.
-- * On failure, the negative of an error code is reported.
-- *
-- * Because a MIDIStream is not a file, all seek operations are doomed to fail.
-- *
-- **/
--static loff_t usb_midi_llseek(struct file *file, loff_t offset, int origin)
--{
-- /** Tell user you cannot seek on a PIPE-like device. **/
-- return -ESPIPE;
--}
--
--
--/** Basic operation on /dev/midiXX as registered through struct file_operations.
-- *
-- * Basic contract: Block until count bytes have been read or an error occurs.
-- *
-- **/
--
--static ssize_t usb_midi_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
--{
-- struct usb_mididev *m = (struct usb_mididev *)file->private_data;
-- struct midi_in_endpoint *ep = m->min.ep;
-- ssize_t ret;
-- DECLARE_WAITQUEUE(wait, current);
--
-- if ( !access_ok(VERIFY_READ, buffer, count) ) {
-- return -EFAULT;
-- }
-- if ( count == 0 ) {
-- return 0;
-- }
--
-- add_wait_queue( &ep->wait, &wait );
-- ret = 0;
-- while( count > 0 ) {
-- int cnt;
-- int d = (int)count;
--
-- cnt = m->min.bufRemains;
-- if ( cnt > d ) {
-- cnt = d;
-- }
--
-- if ( cnt <= 0 ) {
-- if ( file->f_flags & O_NONBLOCK ) {
-- if (!ret)
-- ret = -EAGAIN;
-- break;
-- }
-- __set_current_state(TASK_INTERRUPTIBLE);
-- schedule();
-- if (signal_pending(current)) {
-- if(!ret)
-- ret=-ERESTARTSYS;
-- break;
-- }
-- continue;
-- }
--
-- {
-- int i;
-- unsigned long flags; /* used to synchronize access to the endpoint */
-- spin_lock_irqsave( &ep->lock, flags );
-- for (i = 0; i < cnt; i++) {
-- if ( copy_to_user( buffer+i, m->min.buf+m->min.bufRdPtr, 1 ) ) {
-- if ( !ret )
-- ret = -EFAULT;
-- break;
-- }
-- m->min.bufRdPtr = (m->min.bufRdPtr+1)%MIDI_IN_BUFSIZ;
-- m->min.bufRemains -= 1;
-- }
-- spin_unlock_irqrestore( &ep->lock, flags );
-- }
--
-- count-=cnt;
-- buffer+=cnt;
-- ret+=cnt;
--
-- break;
-- }
--
-- remove_wait_queue( &ep->wait, &wait );
-- set_current_state(TASK_RUNNING);
--
-- return ret;
--}
--
--
--/** Basic operation on /dev/midiXX as registered through struct file_operations.
-- *
-- * Basic Contract: Take MIDI data byte-by-byte and pass it to
-- * writeMidi() which packages MIDI data into USB-MIDI stream.
-- * Then flushMidiData() is called to ensure all bytes have been written
-- * in a timely fashion.
-- *
-- **/
--
--static ssize_t usb_midi_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
--{
-- struct usb_mididev *m = (struct usb_mididev *)file->private_data;
-- ssize_t ret;
-- unsigned long int flags;
--
-- if ( !access_ok(VERIFY_READ, buffer, count) ) {
-- return -EFAULT;
-- }
-- if ( count == 0 ) {
-- return 0;
-- }
--
-- ret = 0;
-- while( count > 0 ) {
-- unsigned char c;
--
-- if (copy_from_user((unsigned char *)&c, buffer, 1)) {
-- if ( ret == 0 )
-- ret = -EFAULT;
-- break;
-- }
-- if( midi_write(m, (int)c) ) {
-- if ( ret == 0 )
-- ret = -EFAULT;
-- break;
-- }
-- count--;
-- buffer++;
-- ret++;
-- }
--
-- spin_lock_irqsave( &m->mout.ep->lock, flags );
-- if ( flush_midi_buffer(m->mout.ep) < 0 ) {
-- ret = -EFAULT;
-- }
-- spin_unlock_irqrestore( &m->mout.ep->lock, flags );
--
-- return ret;
--}
--
--/** Basic operation on /dev/midiXX as registered through struct file_operations.
-- *
-- * Basic contract: Wait (spin) until ready to read or write on the file.
-- *
-- **/
--static unsigned int usb_midi_poll(struct file *file, struct poll_table_struct *wait)
--{
-- struct usb_mididev *m = (struct usb_mididev *)file->private_data;
-- struct midi_in_endpoint *iep = m->min.ep;
-- struct midi_out_endpoint *oep = m->mout.ep;
-- unsigned long flags;
-- unsigned int mask = 0;
--
-- if ( file->f_mode & FMODE_READ ) {
-- poll_wait( file, &iep->wait, wait );
-- spin_lock_irqsave( &iep->lock, flags );
-- if ( m->min.bufRemains > 0 )
-- mask |= POLLIN | POLLRDNORM;
-- spin_unlock_irqrestore( &iep->lock, flags );
-- }
--
-- if ( file->f_mode & FMODE_WRITE ) {
-- poll_wait( file, &oep->wait, wait );
-- spin_lock_irqsave( &oep->lock, flags );
-- if ( oep->bufWrPtr < oep->bufSize )
-- mask |= POLLOUT | POLLWRNORM;
-- spin_unlock_irqrestore( &oep->lock, flags );
-- }
--
-- return mask;
--}
--
--
--/** Basic operation on /dev/midiXX as registered through struct file_operations.
-- *
-- * Basic contract: This is always the first operation performed on the
-- * device node. If no method is defined, the open succeeds without any
-- * notification given to the module.
-- *
-- **/
--
--static int usb_midi_open(struct inode *inode, struct file *file)
--{
-- int minor = iminor(inode);
-- DECLARE_WAITQUEUE(wait, current);
-- struct usb_midi_state *s;
-- struct usb_mididev *m;
-- unsigned long flags;
-- int succeed = 0;
--
--#if 0
-- printk(KERN_INFO "usb-midi: Open minor= %d.\n", minor);
--#endif
--
-- for(;;) {
-- down(&open_sem);
-- list_for_each_entry(s, &mididevs, mididev) {
-- list_for_each_entry(m, &s->midiDevList, list) {
-- if ( !((m->dev_midi ^ minor) & ~0xf) )
-- goto device_found;
-- }
-- }
-- up(&open_sem);
-- return -ENODEV;
--
-- device_found:
-- if ( !s->usbdev ) {
-- up(&open_sem);
-- return -EIO;
-- }
-- if ( !(m->open_mode & file->f_mode) ) {
-- break;
-- }
-- if ( file->f_flags & O_NONBLOCK ) {
-- up(&open_sem);
-- return -EBUSY;
-- }
-- __set_current_state(TASK_INTERRUPTIBLE);
-- add_wait_queue( &open_wait, &wait );
-- up(&open_sem);
-- schedule();
-- remove_wait_queue( &open_wait, &wait );
-- if ( signal_pending(current) ) {
-- return -ERESTARTSYS;
-- }
-- }
--
-- file->private_data = m;
-- spin_lock_irqsave( &s->lock, flags );
--
-- if ( !(m->open_mode & (FMODE_READ | FMODE_WRITE)) ) {
-- //FIXME: intented semantics unclear here
-- m->min.bufRdPtr = 0;
-- m->min.bufWrPtr = 0;
-- m->min.bufRemains = 0;
-- spin_lock_init(&m->min.ep->lock);
--
-- m->mout.bufPtr = 0;
-- m->mout.bufRemains = 0;
-- m->mout.isInExclusive = 0;
-- m->mout.lastEvent = 0;
-- spin_lock_init(&m->mout.ep->lock);
-- }
--
-- if ( (file->f_mode & FMODE_READ) && m->min.ep != NULL ) {
-- unsigned long int flagsep;
-- spin_lock_irqsave( &m->min.ep->lock, flagsep );
-- m->min.ep->cables[m->min.cableId] = m;
-- m->min.ep->readers += 1;
-- m->min.bufRdPtr = 0;
-- m->min.bufWrPtr = 0;
-- m->min.bufRemains = 0;
-- spin_unlock_irqrestore( &m->min.ep->lock, flagsep );
--
-- if ( !(m->min.ep->urbSubmitted)) {
--
-- /* urb->dev must be reinitialized on 2.4.x kernels */
-- m->min.ep->urb->dev = m->min.ep->usbdev;
--
-- if ( usb_submit_urb(m->min.ep->urb, GFP_ATOMIC) ) {
-- printk(KERN_ERR "usbmidi: Cannot submit urb for MIDI-IN\n");
-- }
-- m->min.ep->urbSubmitted = 1;
-- }
-- m->open_mode |= FMODE_READ;
-- succeed = 1;
-- }
--
-- if ( (file->f_mode & FMODE_WRITE) && m->mout.ep != NULL ) {
-- m->mout.bufPtr = 0;
-- m->mout.bufRemains = 0;
-- m->mout.isInExclusive = 0;
-- m->mout.lastEvent = 0;
-- m->open_mode |= FMODE_WRITE;
-- succeed = 1;
-- }
--
-- spin_unlock_irqrestore( &s->lock, flags );
--
-- s->count++;
-- up(&open_sem);
--
-- /** Changed to prevent extra increments to USE_COUNT. **/
-- if (!succeed) {
-- return -EBUSY;
-- }
--
--#if 0
-- printk(KERN_INFO "usb-midi: Open Succeeded. minor= %d.\n", minor);
--#endif
--
-- return nonseekable_open(inode, file); /** Success. **/
--}
--
--
--/** Basic operation on /dev/midiXX as registered through struct file_operations.
-- *
-- * Basic contract: Close an opened file and deallocate anything we allocated.
-- * Like open(), this can be missing. If open set file->private_data,
-- * release() must clear it.
-- *
-- **/
--
--static int usb_midi_release(struct inode *inode, struct file *file)
--{
-- struct usb_mididev *m = (struct usb_mididev *)file->private_data;
-- struct usb_midi_state *s = (struct usb_midi_state *)m->midi;
--
--#if 0
-- printk(KERN_INFO "usb-midi: Close.\n");
--#endif
--
-- down(&open_sem);
--
-- if ( m->open_mode & FMODE_WRITE ) {
-- m->open_mode &= ~FMODE_WRITE;
-- usb_kill_urb( m->mout.ep->urb );
-- }
--
-- if ( m->open_mode & FMODE_READ ) {
-- unsigned long int flagsep;
-- spin_lock_irqsave( &m->min.ep->lock, flagsep );
-- m->min.ep->cables[m->min.cableId] = NULL; // discard cable
-- m->min.ep->readers -= 1;
-- m->open_mode &= ~FMODE_READ;
-- if ( m->min.ep->readers == 0 &&
-- m->min.ep->urbSubmitted ) {
-- m->min.ep->urbSubmitted = 0;
-- usb_kill_urb(m->min.ep->urb);
-- }
-- spin_unlock_irqrestore( &m->min.ep->lock, flagsep );
-- }
--
-- s->count--;
--
-- up(&open_sem);
-- wake_up(&open_wait);
--
-- file->private_data = NULL;
-- return 0;
--}
--
--static struct file_operations usb_midi_fops = {
-- .owner = THIS_MODULE,
-- .llseek = usb_midi_llseek,
-- .read = usb_midi_read,
-- .write = usb_midi_write,
-- .poll = usb_midi_poll,
-- .open = usb_midi_open,
-- .release = usb_midi_release,
--};
--
--/* ------------------------------------------------------------------------- */
--
--/** Returns filled midi_in_endpoint structure or null on failure.
-- *
-- * Parameters:
-- * d - a usb_device
-- * endPoint - An usb endpoint in the range 0 to 15.
-- * Called by allocUsbMidiDev();
-- *
-- **/
--
--static struct midi_in_endpoint *alloc_midi_in_endpoint( struct usb_device *d, int endPoint )
--{
-- struct midi_in_endpoint *ep;
-- int bufSize;
-- int pipe;
--
-- endPoint &= 0x0f; /* Silently force endPoint to lie in range 0 to 15. */
--
-- pipe = usb_rcvbulkpipe( d, endPoint );
-- bufSize = usb_maxpacket( d, pipe, 0 );
-- /* usb_pipein() = ! usb_pipeout() = true for an in Endpoint */
--
-- ep = (struct midi_in_endpoint *)kmalloc(sizeof(struct midi_in_endpoint), GFP_KERNEL);
-- if ( !ep ) {
-- printk(KERN_ERR "usbmidi: no memory for midi in-endpoint\n");
-- return NULL;
-- }
-- memset( ep, 0, sizeof(struct midi_in_endpoint) );
--// this sets cables[] and readers to 0, too.
--// for (i=0; i<16; i++) ep->cables[i] = 0; // discard cable
--// ep->readers = 0;
--
-- ep->endpoint = endPoint;
--
-- ep->recvBuf = (unsigned char *)kmalloc(sizeof(unsigned char)*(bufSize), GFP_KERNEL);
-- if ( !ep->recvBuf ) {
-- printk(KERN_ERR "usbmidi: no memory for midi in-endpoint buffer\n");
-- kfree(ep);
-- return NULL;
-- }
--
-- ep->urb = usb_alloc_urb(0, GFP_KERNEL); /* no ISO */
-- if ( !ep->urb ) {
-- printk(KERN_ERR "usbmidi: no memory for midi in-endpoint urb\n");
-- kfree(ep->recvBuf);
-- kfree(ep);
-- return NULL;
-- }
-- usb_fill_bulk_urb( ep->urb, d,
-- usb_rcvbulkpipe(d, endPoint),
-- (unsigned char *)ep->recvBuf, bufSize,
-- usb_bulk_read, ep );
--
-- /* ep->bufRdPtr = 0; */
-- /* ep->bufWrPtr = 0; */
-- /* ep->bufRemains = 0; */
-- /* ep->urbSubmitted = 0; */
-- ep->recvBufSize = bufSize;
--
-- init_waitqueue_head(&ep->wait);
--
-- return ep;
--}
--
--static int remove_midi_in_endpoint( struct midi_in_endpoint *min )
--{
-- usb_kill_urb( min->urb );
-- usb_free_urb( min->urb );
-- kfree( min->recvBuf );
-- kfree( min );
--
-- return 0;
--}
--
--/** Returns filled midi_out_endpoint structure or null on failure.
-- *
-- * Parameters:
-- * d - a usb_device
-- * endPoint - An usb endpoint in the range 0 to 15.
-- * Called by allocUsbMidiDev();
-- *
-- **/
--static struct midi_out_endpoint *alloc_midi_out_endpoint( struct usb_device *d, int endPoint )
--{
-- struct midi_out_endpoint *ep = NULL;
-- int pipe;
-- int bufSize;
--
-- endPoint &= 0x0f;
-- pipe = usb_sndbulkpipe( d, endPoint );
-- bufSize = usb_maxpacket( d, pipe, 1 );
--
-- ep = (struct midi_out_endpoint *)kmalloc(sizeof(struct midi_out_endpoint), GFP_KERNEL);
-- if ( !ep ) {
-- printk(KERN_ERR "usbmidi: no memory for midi out-endpoint\n");
-- return NULL;
-- }
-- memset( ep, 0, sizeof(struct midi_out_endpoint) );
--
-- ep->endpoint = endPoint;
-- ep->buf = (unsigned char *)kmalloc(sizeof(unsigned char)*bufSize, GFP_KERNEL);
-- if ( !ep->buf ) {
-- printk(KERN_ERR "usbmidi: no memory for midi out-endpoint buffer\n");
-- kfree(ep);
-- return NULL;
-- }
--
-- ep->urb = usb_alloc_urb(0, GFP_KERNEL); /* no ISO */
-- if ( !ep->urb ) {
-- printk(KERN_ERR "usbmidi: no memory for midi out-endpoint urb\n");
-- kfree(ep->buf);
-- kfree(ep);
-- return NULL;
-- }
--
-- ep->bufSize = bufSize;
-- /* ep->bufWrPtr = 0; */
--
-- init_waitqueue_head(&ep->wait);
--
-- return ep;
--}
--
--
--static int remove_midi_out_endpoint( struct midi_out_endpoint *mout )
--{
-- usb_kill_urb( mout->urb );
-- usb_free_urb( mout->urb );
-- kfree( mout->buf );
-- kfree( mout );
--
-- return 0;
--}
--
--
--/** Returns a filled usb_mididev structure, registered as a Linux MIDI device.
-- *
-- * Returns null if memory is not available or the device cannot be registered.
-- * Called by allocUsbMidiDev();
-- *
-- **/
--static struct usb_mididev *allocMidiDev(
-- struct usb_midi_state *s,
-- struct midi_in_endpoint *min,
-- struct midi_out_endpoint *mout,
-- int inCableId,
-- int outCableId )
--{
-- struct usb_mididev *m;
--
-- m = (struct usb_mididev *)kmalloc(sizeof(struct usb_mididev), GFP_KERNEL);
-- if (!m) {
-- printk(KERN_ERR "usbmidi: no memory for midi device\n");
-- return NULL;
-- }
--
-- memset(m, 0, sizeof(struct usb_mididev));
--
-- if ((m->dev_midi = register_sound_midi(&usb_midi_fops, -1)) < 0) {
-- printk(KERN_ERR "usbmidi: cannot register midi device\n");
-- kfree(m);
-- return NULL;
-- }
--
-- m->midi = s;
-- /* m->open_mode = 0; */
--
-- if ( min ) {
-- m->min.ep = min;
-- m->min.ep->usbdev = s->usbdev;
-- m->min.cableId = inCableId;
-- }
-- /* m->min.bufPtr = 0; */
-- /* m->min.bufRemains = 0; */
--
-- if ( mout ) {
-- m->mout.ep = mout;
-- m->mout.ep->usbdev = s->usbdev;
-- m->mout.cableId = outCableId;
-- }
-- /* m->mout.bufPtr = 0; */
-- /* m->mout.bufRemains = 0; */
-- /* m->mout.isInExclusive = 0; */
-- /* m->mout.lastEvent = 0; */
--
-- m->singlebyte = singlebyte;
--
-- return m;
--}
--
--
--static void release_midi_device( struct usb_midi_state *s )
--{
-- struct usb_mididev *m;
-- struct midi_in_endpoint *min;
-- struct midi_out_endpoint *mout;
--
-- if ( s->count > 0 ) {
-- up(&open_sem);
-- return;
-- }
-- up( &open_sem );
-- wake_up( &open_wait );
--
-- while(!list_empty(&s->inEndpointList)) {
-- min = list_entry(s->inEndpointList.next, struct midi_in_endpoint, list);
-- list_del(&min->list);
-- remove_midi_in_endpoint(min);
-- }
--
-- while(!list_empty(&s->outEndpointList)) {
-- mout = list_entry(s->outEndpointList.next, struct midi_out_endpoint, list);
-- list_del(&mout->list);
-- remove_midi_out_endpoint(mout);
-- }
--
-- while(!list_empty(&s->midiDevList)) {
-- m = list_entry(s->midiDevList.next, struct usb_mididev, list);
-- list_del(&m->list);
-- kfree(m);
-- }
--
-- kfree(s);
--
-- return;
--}
--
--
--/* ------------------------------------------------------------------------- */
--
--/** Utility routine to find a descriptor in a dump of many descriptors.
-- * Returns start of descriptor or NULL if not found.
-- * descStart pointer to list of interfaces.
-- * descLength length (in bytes) of dump
-- * after (ignored if NULL) this routine returns only descriptors after "after"
-- * dtype (mandatory) The descriptor type.
-- * iface (ignored if -1) returns descriptor at/following given interface
-- * altSetting (ignored if -1) returns descriptor at/following given altSetting
-- *
-- *
-- * Called by parseDescriptor(), find_csinterface_descriptor();
-- *
-- */
--static void *find_descriptor( void *descStart, unsigned int descLength, void *after, unsigned char dtype, int iface, int altSetting )
--{
-- unsigned char *p, *end, *next;
-- int interfaceNumber = -1, altSet = -1;
--
-- p = descStart;
-- end = p + descLength;
-- for( ; p < end; ) {
-- if ( p[0] < 2 )
-- return NULL;
-- next = p + p[0];
-- if ( next > end )
-- return NULL;
-- if ( p[1] == USB_DT_INTERFACE ) {
-- if ( p[0] < USB_DT_INTERFACE_SIZE )
-- return NULL;
-- interfaceNumber = p[2];
-- altSet = p[3];
-- }
-- if ( p[1] == dtype &&
-- ( !after || ( p > (unsigned char *)after) ) &&
-- ( ( iface == -1) || (iface == interfaceNumber) ) &&
-- ( (altSetting == -1) || (altSetting == altSet) )) {
-- return p;
-- }
-- p = next;
-- }
-- return NULL;
--}
--
--/** Utility to find a class-specific interface descriptor.
-- * dsubtype is a descriptor subtype
-- * Called by parseDescriptor();
-- **/
--static void *find_csinterface_descriptor(void *descStart, unsigned int descLength, void *after, u8 dsubtype, int iface, int altSetting)
--{
-- unsigned char *p;
--
-- p = find_descriptor( descStart, descLength, after, USB_DT_CS_INTERFACE, iface, altSetting );
-- while ( p ) {
-- if ( p[0] >= 3 && p[2] == dsubtype )
-- return p;
-- p = find_descriptor( descStart, descLength, p, USB_DT_CS_INTERFACE,
-- iface, altSetting );
-- }
-- return NULL;
--}
--
--
--/** The magic of making a new usb_midi_device from config happens here.
-- *
-- * The caller is responsible for free-ing this return value (if not NULL).
-- *
-- **/
--static struct usb_midi_device *parse_descriptor( struct usb_device *d, unsigned char *buffer, int bufSize, unsigned int ifnum , unsigned int altSetting, int quirks)
--{
-- struct usb_midi_device *u;
-- unsigned char *p1;
-- unsigned char *p2;
-- unsigned char *next;
-- int iep, oep;
-- int length;
-- unsigned long longBits;
-- int pins, nbytes, offset, shift, jack;
--#ifdef HAVE_JACK_STRINGS
-- /** Jacks can have associated names. **/
-- unsigned char jack2string[256];
--#endif
--
-- u = NULL;
-- /* find audiocontrol interface */
-- p1 = find_csinterface_descriptor( buffer, bufSize, NULL,
-- MS_HEADER, ifnum, altSetting);
--
-- if ( !p1 ) {
-- goto error_end;
-- }
--
-- if ( p1[0] < MS_HEADER_LENGTH ) {
-- goto error_end;
-- }
--
-- /* Assume success. Since the device corresponds to USB-MIDI spec, we assume
-- that the rest of the USB 2.0 spec is obeyed. */
--
-- u = (struct usb_midi_device *)kmalloc( sizeof(struct usb_midi_device), GFP_KERNEL );
-- if ( !u ) {
-- return NULL;
-- }
-- u->deviceName = NULL;
-- u->idVendor = le16_to_cpu(d->descriptor.idVendor);
-- u->idProduct = le16_to_cpu(d->descriptor.idProduct);
-- u->interface = ifnum;
-- u->altSetting = altSetting;
-- u->in[0].endpoint = -1;
-- u->in[0].cableId = -1;
-- u->out[0].endpoint = -1;
-- u->out[0].cableId = -1;
--
--
-- printk(KERN_INFO "usb-midi: Found MIDIStreaming device corresponding to Release %d.%02d of spec.\n",
-- (p1[4] >> 4) * 10 + (p1[4] & 0x0f ),
-- (p1[3] >> 4) * 10 + (p1[3] & 0x0f )
-- );
--
-- length = p1[5] | (p1[6] << 8);
--
--#ifdef HAVE_JACK_STRINGS
-- memset(jack2string, 0, sizeof(unsigned char) * 256);
--#endif
--
-- length -= p1[0];
-- for (p2 = p1 + p1[0]; length > 0; p2 = next) {
-- next = p2 + p2[0];
-- length -= p2[0];
--
-- if (p2[0] < 2 )
-- break;
-- if (p2[1] != USB_DT_CS_INTERFACE)
-- break;
-- if (p2[2] == MIDI_IN_JACK && p2[0] >= 6 ) {
-- jack = p2[4];
--#ifdef HAVE_JACK_STRINGS
-- jack2string[jack] = p2[5];
--#endif
-- printk(KERN_INFO "usb-midi: Found IN Jack 0x%02x %s\n",
-- jack, (p2[3] == EMBEDDED_JACK)?"EMBEDDED":"EXTERNAL" );
-- } else if ( p2[2] == MIDI_OUT_JACK && p2[0] >= 6) {
-- pins = p2[5];
-- if ( p2[0] < (6 + 2 * pins) )
-- continue;
-- jack = p2[4];
--#ifdef HAVE_JACK_STRINGS
-- jack2string[jack] = p2[5 + 2 * pins];
--#endif
-- printk(KERN_INFO "usb-midi: Found OUT Jack 0x%02x %s, %d pins\n",
-- jack, (p2[3] == EMBEDDED_JACK)?"EMBEDDED":"EXTERNAL", pins );
-- } else if ( p2[2] == ELEMENT_DESCRIPTOR && p2[0] >= 10) {
-- pins = p2[4];
-- if ( p2[0] < (9 + 2 * pins ) )
-- continue;
-- nbytes = p2[8 + 2 * pins ];
-- if ( p2[0] < (10 + 2 * pins + nbytes) )
-- continue;
-- longBits = 0L;
-- for ( offset = 0, shift = 0; offset < nbytes && offset < 8; offset ++, shift += 8) {
-- longBits |= ((long)(p2[9 + 2 * pins + offset])) << shift;
-- }
-- jack = p2[3];
--#ifdef HAVE_JACK_STRINGS
-- jack2string[jack] = p2[9 + 2 * pins + nbytes];
--#endif
-- printk(KERN_INFO "usb-midi: Found ELEMENT 0x%02x, %d/%d pins in/out, bits: 0x%016lx\n",
-- jack, pins, (int)(p2[5 + 2 * pins]), (long)longBits );
-- } else {
-- }
-- }
--
-- iep=0;
-- oep=0;
--
-- if (quirks==0) {
-- /* MIDISTREAM */
-- p2 = NULL;
-- for (p1 = find_descriptor(buffer, bufSize, NULL, USB_DT_ENDPOINT,
-- ifnum, altSetting ); p1; p1 = next ) {
-- next = find_descriptor(buffer, bufSize, p1, USB_DT_ENDPOINT,
-- ifnum, altSetting );
-- p2 = find_descriptor(buffer, bufSize, p1, USB_DT_CS_ENDPOINT,
-- ifnum, altSetting );
--
-- if ( p2 && next && ( p2 > next ) )
-- p2 = NULL;
--
-- if ( p1[0] < 9 || !p2 || p2[0] < 4 )
-- continue;
--
-- if ( (p1[2] & 0x80) == 0x80 ) {
-- if ( iep < 15 ) {
-- pins = p2[3]; /* not pins -- actually "cables" */
-- if ( pins > 16 )
-- pins = 16;
-- u->in[iep].endpoint = p1[2];
-- u->in[iep].cableId = ( 1 << pins ) - 1;
-- if ( u->in[iep].cableId )
-- iep ++;
-- if ( iep < 15 ) {
-- u->in[iep].endpoint = -1;
-- u->in[iep].cableId = -1;
-- }
-- }
-- } else {
-- if ( oep < 15 ) {
-- pins = p2[3]; /* not pins -- actually "cables" */
-- if ( pins > 16 )
-- pins = 16;
-- u->out[oep].endpoint = p1[2];
-- u->out[oep].cableId = ( 1 << pins ) - 1;
-- if ( u->out[oep].cableId )
-- oep ++;
-- if ( oep < 15 ) {
-- u->out[oep].endpoint = -1;
-- u->out[oep].cableId = -1;
-- }
-- }
-- }
--
-- }
-- } else if (quirks==1) {
-- /* YAMAHA quirks */
-- for (p1 = find_descriptor(buffer, bufSize, NULL, USB_DT_ENDPOINT,
-- ifnum, altSetting ); p1; p1 = next ) {
-- next = find_descriptor(buffer, bufSize, p1, USB_DT_ENDPOINT,
-- ifnum, altSetting );
--
-- if ( p1[0] < 7 )
-- continue;
--
-- if ( (p1[2] & 0x80) == 0x80 ) {
-- if ( iep < 15 ) {
-- pins = iep+1;
-- if ( pins > 16 )
-- pins = 16;
-- u->in[iep].endpoint = p1[2];
-- u->in[iep].cableId = ( 1 << pins ) - 1;
-- if ( u->in[iep].cableId )
-- iep ++;
-- if ( iep < 15 ) {
-- u->in[iep].endpoint = -1;
-- u->in[iep].cableId = -1;
-- }
-- }
-- } else {
-- if ( oep < 15 ) {
-- pins = oep+1;
-- u->out[oep].endpoint = p1[2];
-- u->out[oep].cableId = ( 1 << pins ) - 1;
-- if ( u->out[oep].cableId )
-- oep ++;
-- if ( oep < 15 ) {
-- u->out[oep].endpoint = -1;
-- u->out[oep].cableId = -1;
-- }
-- }
-- }
--
-- }
-- }
--
-- if ( !iep && ! oep ) {
-- goto error_end;
-- }
--
-- return u;
--
--error_end:
-- kfree(u);
-- return NULL;
--}
--
--/* ------------------------------------------------------------------------- */
--
--/** Returns number between 0 and 16.
-- *
-- **/
--static int on_bits( unsigned short v )
--{
-- int i;
-- int ret=0;
--
-- for ( i=0 ; i<16 ; i++ ) {
-- if ( v & (1<<i) )
-- ret++;
-- }
--
-- return ret;
--}
--
--
--/** USB-device will be interrogated for altSetting.
-- *
-- * Returns negative on error.
-- * Called by allocUsbMidiDev();
-- *
-- **/
--
--static int get_alt_setting( struct usb_device *d, int ifnum )
--{
-- int alts, alt=0;
-- struct usb_interface *iface;
-- struct usb_host_interface *interface;
-- struct usb_endpoint_descriptor *ep;
-- int epin, epout;
-- int i;
--
-- iface = usb_ifnum_to_if( d, ifnum );
-- alts = iface->num_altsetting;
--
-- for ( alt=0 ; alt<alts ; alt++ ) {
-- interface = &iface->altsetting[alt];
-- epin = -1;
-- epout = -1;
--
-- for ( i=0 ; i<interface->desc.bNumEndpoints ; i++ ) {
-- ep = &interface->endpoint[i].desc;
-- if ( (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ) {
-- continue;
-- }
-- if ( (ep->bEndpointAddress & USB_DIR_IN) && epin < 0 ) {
-- epin = i;
-- } else if ( epout < 0 ) {
-- epout = i;
-- }
-- if ( epin >= 0 && epout >= 0 ) {
-- return interface->desc.bAlternateSetting;
-- }
-- }
-- }
--
-- return -ENODEV;
--}
--
--
--/* ------------------------------------------------------------------------- */
--
--
--/** Returns 0 if successful in allocating and registering internal structures.
-- * Returns negative on failure.
-- * Calls allocMidiDev which additionally registers /dev/midiXX devices.
-- * Writes messages on success to indicate which /dev/midiXX is which physical
-- * endpoint.
-- *
-- **/
--static int alloc_usb_midi_device( struct usb_device *d, struct usb_midi_state *s, struct usb_midi_device *u )
--{
-- struct usb_mididev **mdevs=NULL;
-- struct midi_in_endpoint *mins[15], *min;
-- struct midi_out_endpoint *mouts[15], *mout;
-- int inDevs=0, outDevs=0;
-- int inEndpoints=0, outEndpoints=0;
-- int inEndpoint, outEndpoint;
-- int inCableId, outCableId;
-- int i;
-- int devices = 0;
-- int alt = 0;
--
-- /* Obtain altSetting or die.. */
-- alt = u->altSetting;
-- if ( alt < 0 ) {
-- alt = get_alt_setting( d, u->interface );
-- }
-- if ( alt < 0 )
-- return -ENXIO;
--
-- /* Configure interface */
-- if ( usb_set_interface( d, u->interface, alt ) < 0 ) {
-- return -ENXIO;
-- }
--
-- for ( i = 0 ; i < 15 ; i++ ) {
-- mins[i] = NULL;
-- mouts[i] = NULL;
-- }
--
-- /* Begin Allocation */
-- while( inEndpoints < 15
-- && inDevs < maxdevices
-- && u->in[inEndpoints].cableId >= 0 ) {
-- inDevs += on_bits((unsigned short)u->in[inEndpoints].cableId);
-- mins[inEndpoints] = alloc_midi_in_endpoint( d, u->in[inEndpoints].endpoint );
-- if ( mins[inEndpoints] == NULL )
-- goto error_end;
-- inEndpoints++;
-- }
--
-- while( outEndpoints < 15
-- && outDevs < maxdevices
-- && u->out[outEndpoints].cableId >= 0 ) {
-- outDevs += on_bits((unsigned short)u->out[outEndpoints].cableId);
-- mouts[outEndpoints] = alloc_midi_out_endpoint( d, u->out[outEndpoints].endpoint );
-- if ( mouts[outEndpoints] == NULL )
-- goto error_end;
-- outEndpoints++;
-- }
--
-- devices = inDevs > outDevs ? inDevs : outDevs;
-- devices = maxdevices > devices ? devices : maxdevices;
--
-- /* obtain space for device name (iProduct) if not known. */
-- if ( ! u->deviceName ) {
-- mdevs = (struct usb_mididev **)
-- kmalloc(sizeof(struct usb_mididevs *)*devices
-- + sizeof(char) * 256, GFP_KERNEL);
-- } else {
-- mdevs = (struct usb_mididev **)
-- kmalloc(sizeof(struct usb_mididevs *)*devices, GFP_KERNEL);
-- }
--
-- if ( !mdevs ) {
-- /* devices = 0; */
-- /* mdevs = NULL; */
-- goto error_end;
-- }
-- for ( i=0 ; i<devices ; i++ ) {
-- mdevs[i] = NULL;
-- }
--
-- /* obtain device name (iProduct) if not known. */
-- if ( ! u->deviceName ) {
-- u->deviceName = (char *) (mdevs + devices);
-- if ( ! d->have_langid && d->descriptor.iProduct) {
-- alt = usb_get_string(d, 0, 0, u->deviceName, 250);
-- if (alt < 0) {
-- printk(KERN_INFO "error getting string descriptor 0 (error=%d)\n", alt);
-- } else if (u->deviceName[0] < 4) {
-- printk(KERN_INFO "string descriptor 0 too short (length = %d)\n", alt);
-- } else {
-- printk(KERN_INFO "string descriptor 0 found (length = %d)\n", alt);
-- for(; alt >= 4; alt -= 2) {
-- i = u->deviceName[alt-2] | (u->deviceName[alt-1]<< 8);
-- printk(KERN_INFO "usb-midi: langid(%d) 0x%04x\n",
-- (alt-4) >> 1, i);
-- if ( ( ( i ^ ulangid ) & 0xff ) == 0 ) {
-- d->have_langid = 1;
-- d->string_langid = i;
-- printk(KERN_INFO "usb-midi: langid(match) 0x%04x\n", i);
-- if ( i == ulangid )
-- break;
-- }
-- }
-- }
-- }
-- u->deviceName[0] = (char) 0;
-- if (d->descriptor.iProduct) {
-- printk(KERN_INFO "usb-midi: fetchString(%d)\n", d->descriptor.iProduct);
-- alt = usb_string(d, d->descriptor.iProduct, u->deviceName, 255);
-- if( alt < 0 ) {
-- u->deviceName[0] = (char) 0;
-- }
-- printk(KERN_INFO "usb-midi: fetchString = %d\n", alt);
-- }
-- /* Failsafe */
-- if ( !u->deviceName[0] ) {
-- if (le16_to_cpu(d->descriptor.idVendor) == USB_VENDOR_ID_ROLAND ) {
-- strcpy(u->deviceName, "Unknown Roland");
-- } else if (le16_to_cpu(d->descriptor.idVendor) == USB_VENDOR_ID_STEINBERG ) {
-- strcpy(u->deviceName, "Unknown Steinberg");
-- } else if (le16_to_cpu(d->descriptor.idVendor) == USB_VENDOR_ID_YAMAHA ) {
-- strcpy(u->deviceName, "Unknown Yamaha");
-- } else {
-- strcpy(u->deviceName, "Unknown");
-- }
-- }
-- }
--
-- inEndpoint = 0; inCableId = -1;
-- outEndpoint = 0; outCableId = -1;
--
-- for ( i=0 ; i<devices ; i++ ) {
-- for ( inCableId ++ ;
-- inEndpoint <15
-- && mins[inEndpoint]
-- && !(u->in[inEndpoint].cableId & (1<<inCableId)) ;
-- inCableId++ ) {
-- if ( inCableId >= 16 ) {
-- inEndpoint ++;
-- inCableId = 0;
-- }
-- }
-- min = mins[inEndpoint];
-- for ( outCableId ++ ;
-- outEndpoint <15
-- && mouts[outEndpoint]
-- && !(u->out[outEndpoint].cableId & (1<<outCableId)) ;
-- outCableId++ ) {
-- if ( outCableId >= 16 ) {
-- outEndpoint ++;
-- outCableId = 0;
-- }
-- }
-- mout = mouts[outEndpoint];
--
-- mdevs[i] = allocMidiDev( s, min, mout, inCableId, outCableId );
-- if ( mdevs[i] == NULL )
-- goto error_end;
--
-- }
--
-- /* Success! */
-- for ( i=0 ; i<devices ; i++ ) {
-- list_add_tail( &mdevs[i]->list, &s->midiDevList );
-- }
-- for ( i=0 ; i<inEndpoints ; i++ ) {
-- list_add_tail( &mins[i]->list, &s->inEndpointList );
-- }
-- for ( i=0 ; i<outEndpoints ; i++ ) {
-- list_add_tail( &mouts[i]->list, &s->outEndpointList );
-- }
--
-- printk(KERN_INFO "usbmidi: found [ %s ] (0x%04x:0x%04x), attached:\n", u->deviceName, u->idVendor, u->idProduct );
-- for ( i=0 ; i<devices ; i++ ) {
-- int dm = (mdevs[i]->dev_midi-2)>>4;
-- if ( mdevs[i]->mout.ep != NULL && mdevs[i]->min.ep != NULL ) {
-- printk(KERN_INFO "usbmidi: /dev/midi%02d: in (ep:%02x cid:%2d bufsiz:%2d) out (ep:%02x cid:%2d bufsiz:%2d)\n",
-- dm,
-- mdevs[i]->min.ep->endpoint|USB_DIR_IN, mdevs[i]->min.cableId, mdevs[i]->min.ep->recvBufSize,
-- mdevs[i]->mout.ep->endpoint, mdevs[i]->mout.cableId, mdevs[i]->mout.ep->bufSize);
-- } else if ( mdevs[i]->min.ep != NULL ) {
-- printk(KERN_INFO "usbmidi: /dev/midi%02d: in (ep:%02x cid:%2d bufsiz:%02d)\n",
-- dm,
-- mdevs[i]->min.ep->endpoint|USB_DIR_IN, mdevs[i]->min.cableId, mdevs[i]->min.ep->recvBufSize);
-- } else if ( mdevs[i]->mout.ep != NULL ) {
-- printk(KERN_INFO "usbmidi: /dev/midi%02d: out (ep:%02x cid:%2d bufsiz:%02d)\n",
-- dm,
-- mdevs[i]->mout.ep->endpoint, mdevs[i]->mout.cableId, mdevs[i]->mout.ep->bufSize);
-- }
-- }
--
-- kfree(mdevs);
-- return 0;
--
-- error_end:
-- if ( mdevs != NULL ) {
-- for ( i=0 ; i<devices ; i++ ) {
-- if ( mdevs[i] != NULL ) {
-- unregister_sound_midi( mdevs[i]->dev_midi );
-- kfree(mdevs[i]);
-- }
-- }
-- kfree(mdevs);
-- }
--
-- for ( i=0 ; i<15 ; i++ ) {
-- if ( mins[i] != NULL ) {
-- remove_midi_in_endpoint( mins[i] );
-- }
-- if ( mouts[i] != NULL ) {
-- remove_midi_out_endpoint( mouts[i] );
-- }
-- }
--
-- return -ENOMEM;
--}
--
--/* ------------------------------------------------------------------------- */
--
--/** Attempt to scan YAMAHA's device descriptor and detect correct values of
-- * them.
-- * Return 0 on succes, negative on failure.
-- * Called by usb_midi_probe();
-- **/
--
--static int detect_yamaha_device( struct usb_device *d,
-- struct usb_interface *iface, unsigned int ifnum,
-- struct usb_midi_state *s)
--{
-- struct usb_host_interface *interface;
-- struct usb_midi_device *u;
-- unsigned char *buffer;
-- int bufSize;
-- int i;
-- int alts=-1;
-- int ret;
--
-- if (le16_to_cpu(d->descriptor.idVendor) != USB_VENDOR_ID_YAMAHA) {
-- return -EINVAL;
-- }
--
-- for ( i=0 ; i < iface->num_altsetting; i++ ) {
-- interface = iface->altsetting + i;
--
-- if ( interface->desc.bInterfaceClass != 255 ||
-- interface->desc.bInterfaceSubClass != 0 )
-- continue;
-- alts = interface->desc.bAlternateSetting;
-- }
-- if ( alts == -1 ) {
-- return -EINVAL;
-- }
--
-- printk(KERN_INFO "usb-midi: Found YAMAHA USB-MIDI device on dev %04x:%04x, iface %d\n",
-- le16_to_cpu(d->descriptor.idVendor),
-- le16_to_cpu(d->descriptor.idProduct), ifnum);
--
-- i = d->actconfig - d->config;
-- buffer = d->rawdescriptors[i];
-- bufSize = le16_to_cpu(d->actconfig->desc.wTotalLength);
--
-- u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 1);
-- if ( u == NULL ) {
-- return -EINVAL;
-- }
--
-- ret = alloc_usb_midi_device( d, s, u );
--
-- kfree(u);
--
-- return ret;
--}
--
--
--/** Scan table of known devices which are only partially compliant with
-- * the MIDIStreaming specification.
-- * Called by usb_midi_probe();
-- *
-- **/
--
--static int detect_vendor_specific_device( struct usb_device *d, unsigned int ifnum, struct usb_midi_state *s )
--{
-- struct usb_midi_device *u;
-- int i;
-- int ret = -ENXIO;
--
-- for ( i=0; i<VENDOR_SPECIFIC_USB_MIDI_DEVICES ; i++ ) {
-- u=&(usb_midi_devices[i]);
--
-- if ( le16_to_cpu(d->descriptor.idVendor) != u->idVendor ||
-- le16_to_cpu(d->descriptor.idProduct) != u->idProduct ||
-- ifnum != u->interface )
-- continue;
--
-- ret = alloc_usb_midi_device( d, s, u );
-- break;
-- }
--
-- return ret;
--}
--
--
--/** Attempt to match any config of an interface to a MIDISTREAMING interface.
-- * Returns 0 on success, negative on failure.
-- * Called by usb_midi_probe();
-- **/
--static int detect_midi_subclass(struct usb_device *d,
-- struct usb_interface *iface, unsigned int ifnum,
-- struct usb_midi_state *s)
--{
-- struct usb_host_interface *interface;
-- struct usb_midi_device *u;
-- unsigned char *buffer;
-- int bufSize;
-- int i;
-- int alts=-1;
-- int ret;
--
-- for ( i=0 ; i < iface->num_altsetting; i++ ) {
-- interface = iface->altsetting + i;
--
-- if ( interface->desc.bInterfaceClass != USB_CLASS_AUDIO ||
-- interface->desc.bInterfaceSubClass != USB_SUBCLASS_MIDISTREAMING )
-- continue;
-- alts = interface->desc.bAlternateSetting;
-- }
-- if ( alts == -1 ) {
-- return -EINVAL;
-- }
--
-- printk(KERN_INFO "usb-midi: Found MIDISTREAMING on dev %04x:%04x, iface %d\n",
-- le16_to_cpu(d->descriptor.idVendor),
-- le16_to_cpu(d->descriptor.idProduct), ifnum);
--
--
-- /* From USB Spec v2.0, Section 9.5.
-- If the class or vendor specific descriptors use the same format
-- as standard descriptors (e.g., start with a length byte and
-- followed by a type byte), they must be returned interleaved with
-- standard descriptors in the configuration information returned by
-- a GetDescriptor(Configuration) request. In this case, the class
-- or vendor-specific descriptors must follow a related standard
-- descriptor they modify or extend.
-- */
--
-- i = d->actconfig - d->config;
-- buffer = d->rawdescriptors[i];
-- bufSize = le16_to_cpu(d->actconfig->desc.wTotalLength);
--
-- u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 0);
-- if ( u == NULL ) {
-- return -EINVAL;
-- }
--
-- ret = alloc_usb_midi_device( d, s, u );
--
-- kfree(u);
--
-- return ret;
--}
--
--
--/** When user has requested a specific device, match it exactly.
-- *
-- * Uses uvendor, uproduct, uinterface, ualt, umin, umout and ucable.
-- * Called by usb_midi_probe();
-- *
-- **/
--static int detect_by_hand(struct usb_device *d, unsigned int ifnum, struct usb_midi_state *s)
--{
-- struct usb_midi_device u;
--
-- if ( le16_to_cpu(d->descriptor.idVendor) != uvendor ||
-- le16_to_cpu(d->descriptor.idProduct) != uproduct ||
-- ifnum != uinterface ) {
-- return -EINVAL;
-- }
--
-- if ( ualt < 0 )
-- ualt = -1;
--
-- if ( umin < 0 || umin > 15 )
-- umin = 0x01 | USB_DIR_IN;
-- if ( umout < 0 || umout > 15 )
-- umout = 0x01;
-- if ( ucable < 0 || ucable > 15 )
-- ucable = 0;
--
-- u.deviceName = NULL; /* A flag for alloc_usb_midi_device to get device
-- name from device. */
-- u.idVendor = uvendor;
-- u.idProduct = uproduct;
-- u.interface = uinterface;
-- u.altSetting = ualt;
--
-- u.in[0].endpoint = umin;
-- u.in[0].cableId = (1<<ucable);
--
-- u.out[0].endpoint = umout;
-- u.out[0].cableId = (1<<ucable);
--
-- return alloc_usb_midi_device( d, s, &u );
--}
--
--
--
--/* ------------------------------------------------------------------------- */
--
--static int usb_midi_probe(struct usb_interface *intf,
-- const struct usb_device_id *id)
--{
-- struct usb_midi_state *s;
-- struct usb_device *dev = interface_to_usbdev(intf);
-- int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
--
-- s = (struct usb_midi_state *)kmalloc(sizeof(struct usb_midi_state), GFP_KERNEL);
-- if ( !s )
-- return -ENOMEM;
--
-- memset( s, 0, sizeof(struct usb_midi_state) );
-- INIT_LIST_HEAD(&s->midiDevList);
-- INIT_LIST_HEAD(&s->inEndpointList);
-- INIT_LIST_HEAD(&s->outEndpointList);
-- s->usbdev = dev;
-- s->count = 0;
-- spin_lock_init(&s->lock);
--
-- if (
-- detect_by_hand( dev, ifnum, s ) &&
-- detect_midi_subclass( dev, intf, ifnum, s ) &&
-- detect_vendor_specific_device( dev, ifnum, s ) &&
-- detect_yamaha_device( dev, intf, ifnum, s) ) {
-- kfree(s);
-- return -EIO;
-- }
--
-- down(&open_sem);
-- list_add_tail(&s->mididev, &mididevs);
-- up(&open_sem);
--
-- usb_set_intfdata (intf, s);
-- return 0;
--}
--
--
--static void usb_midi_disconnect(struct usb_interface *intf)
--{
-- struct usb_midi_state *s = usb_get_intfdata (intf);
-- struct usb_mididev *m;
--
-- if ( !s )
-- return;
--
-- if ( s == (struct usb_midi_state *)-1 ) {
-- return;
-- }
-- if ( !s->usbdev ) {
-- return;
-- }
-- down(&open_sem);
-- list_del(&s->mididev);
-- INIT_LIST_HEAD(&s->mididev);
-- s->usbdev = NULL;
-- usb_set_intfdata (intf, NULL);
--
-- list_for_each_entry(m, &s->midiDevList, list) {
-- wake_up(&(m->min.ep->wait));
-- wake_up(&(m->mout.ep->wait));
-- if ( m->dev_midi >= 0 ) {
-- unregister_sound_midi(m->dev_midi);
-- }
-- m->dev_midi = -1;
-- }
-- release_midi_device(s);
-- wake_up(&open_wait);
--}
--
--/* we want to look at all devices by hand */
--static struct usb_device_id id_table[] = {
-- {.driver_info = 42},
-- {}
--};
--
--static struct usb_driver usb_midi_driver = {
-- .name = "midi",
-- .probe = usb_midi_probe,
-- .disconnect = usb_midi_disconnect,
-- .id_table = id_table,
--};
--
--/* ------------------------------------------------------------------------- */
--
--static int __init usb_midi_init(void)
--{
-- return usb_register(&usb_midi_driver);
--}
--
--static void __exit usb_midi_exit(void)
--{
-- usb_deregister(&usb_midi_driver);
--}
--
--module_init(usb_midi_init) ;
--module_exit(usb_midi_exit) ;
--
--#ifdef HAVE_ALSA_SUPPORT
--#define SNDRV_MAIN_OBJECT_FILE
--#include "../../include/driver.h"
--#include "../../include/control.h"
--#include "../../include/info.h"
--#include "../../include/cs46xx.h"
--
--/* ------------------------------------------------------------------------- */
--
--static int snd_usbmidi_input_close(snd_rawmidi_substream_t * substream)
--{
-- return 0;
--}
--
--static int snd_usbmidi_input_open(snd_rawmidi_substream_t * substream )
--{
-- return 0;
--}
--
--static void snd_usbmidi_input_trigger(snd_rawmidi_substream_t * substream, int up)
--{
-- return 0;
--}
--
--
--/* ------------------------------------------------------------------------- */
--
--static int snd_usbmidi_output_close(snd_rawmidi_substream_t * substream)
--{
-- return 0;
--}
--
--static int snd_usbmidi_output_open(snd_rawmidi_substream_t * substream)
--{
-- return 0;
--}
--
--static void snd_usb_midi_output_trigger(snd_rawmidi_substream_t * substream,
-- int up)
--{
-- return 0;
--}
--
--/* ------------------------------------------------------------------------- */
--
--static snd_rawmidi_ops_t snd_usbmidi_output =
--{
-- .open = snd_usbmidi_output_open,
-- .close = snd_usbmidi_output_close,
-- .trigger = snd_usbmidi_output_trigger,
--};
--static snd_rawmidi_ops_t snd_usbmidi_input =
--{
-- .open = snd_usbmidi_input_open,
-- .close = snd_usbmidi_input_close,
-- .trigger = snd_usbmidi_input_trigger,
--};
--
--int snd_usbmidi_midi(cs46xx_t *chip, int device, snd_rawmidi_t **rrawmidi)
--{
-- snd_rawmidi_t *rmidi;
-- int err;
--
-- if (rrawmidi)
-- *rrawmidi = NULL;
-- if ((err = snd_rawmidi_new(chip->card, "USB-MIDI", device, 1, 1, &rmidi)) < 0)
-- return err;
-- strcpy(rmidi->name, "USB-MIDI");
--
-- snd_rawmidi_set_ops( rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_usbmidi_output );
-- snd_rawmidi_set_ops( rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_usbmidi_input );
--
-- rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
--
-- rmidi->private_data = chip;
-- chip->rmidi = rmidi;
-- if (rrawmidi)
-- *rrawmidi = NULL;
--
-- return 0;
--}
--
--int snd_usbmidi_create( snd_card_t * card,
-- struct pci_dev * pci,
-- usbmidi_t ** rchip )
--{
-- usbmidi_t *chip;
-- int err, idx;
-- snd_region_t *region;
-- static snd_device_opt_t ops = {
-- .dev_free = snd_usbmidi_dev_free,
-- };
--
-- *rchip = NULL;
-- chip = snd_magic_kcalloc( usbmidi_t, 0, GFP_KERNEL );
-- if ( chip == NULL )
-- return -ENOMEM;
--}
--
--EXPORT_SYMBOL(snd_usbmidi_create);
--EXPORT_SYMBOL(snd_usbmidi_midi);
--#endif /* HAVE_ALSA_SUPPORT */
--
---- gregkh-2.6.orig/drivers/usb/class/audio.h
-+++ /dev/null
-@@ -1,110 +0,0 @@
--#define CS_AUDIO_UNDEFINED 0x20
--#define CS_AUDIO_DEVICE 0x21
--#define CS_AUDIO_CONFIGURATION 0x22
--#define CS_AUDIO_STRING 0x23
--#define CS_AUDIO_INTERFACE 0x24
--#define CS_AUDIO_ENDPOINT 0x25
--
--#define HEADER 0x01
--#define INPUT_TERMINAL 0x02
--#define OUTPUT_TERMINAL 0x03
--#define MIXER_UNIT 0x04
--#define SELECTOR_UNIT 0x05
--#define FEATURE_UNIT 0x06
--#define PROCESSING_UNIT 0x07
--#define EXTENSION_UNIT 0x08
--
--#define AS_GENERAL 0x01
--#define FORMAT_TYPE 0x02
--#define FORMAT_SPECIFIC 0x03
--
--#define EP_GENERAL 0x01
--
--#define MAX_CHAN 9
--#define MAX_FREQ 16
--#define MAX_IFACE 8
--#define MAX_FORMAT 8
--#define MAX_ALT 32 /* Sorry, we need quite a few for the Philips webcams */
--
--struct usb_audio_terminal
--{
-- u8 flags;
-- u8 assoc;
-- u16 type; /* Mic etc */
-- u8 channels;
-- u8 source;
-- u16 chancfg;
--};
--
--struct usb_audio_format
--{
-- u8 type;
-- u8 channels;
-- u8 num_freq;
-- u8 sfz;
-- u8 bits;
-- u16 freq[MAX_FREQ];
--};
--
--struct usb_audio_interface
--{
-- u8 terminal;
-- u8 delay;
-- u16 num_formats;
-- u16 format_type;
-- u8 flags;
-- u8 idleconf; /* Idle config */
--#define AU_IFACE_FOUND 1
-- struct usb_audio_format format[MAX_FORMAT];
--};
--
--struct usb_audio_device
--{
-- struct list_head list;
-- u8 mixer;
-- u8 selector;
-- void *irq_handle;
-- u8 num_channels;
-- u8 num_dsp_iface;
-- u8 channel_map[MAX_CHAN];
-- struct usb_audio_terminal terminal[MAX_CHAN];
-- struct usb_audio_interface interface[MAX_IFACE][MAX_ALT];
--};
--
--
--
--/* Audio Class specific Request Codes */
--
--#define SET_CUR 0x01
--#define GET_CUR 0x81
--#define SET_MIN 0x02
--#define GET_MIN 0x82
--#define SET_MAX 0x03
--#define GET_MAX 0x83
--#define SET_RES 0x04
--#define GET_RES 0x84
--#define SET_MEM 0x05
--#define GET_MEM 0x85
--#define GET_STAT 0xff
--
--/* Terminal Control Selectors */
--
--#define COPY_PROTECT_CONTROL 0x01
--
--/* Feature Unit Control Selectors */
--
--#define MUTE_CONTROL 0x01
--#define VOLUME_CONTROL 0x02
--#define BASS_CONTROL 0x03
--#define MID_CONTROL 0x04
--#define TREBLE_CONTROL 0x05
--#define GRAPHIC_EQUALIZER_CONTROL 0x06
--#define AUTOMATIC_GAIN_CONTROL 0x07
--#define DELAY_CONTROL 0x08
--#define BASS_BOOST_CONTROL 0x09
--#define LOUDNESS_CONTROL 0x0a
--
--/* Endpoint Control Selectors */
--
--#define SAMPLING_FREQ_CONTROL 0x01
--#define PITCH_CONTROL 0x02
--- gregkh-2.6.orig/drivers/usb/class/audio.c
+++ /dev/null
@@ -1,3869 +0,0 @@
@@ -6405,3 +3969,2439 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
-
+--- gregkh-2.6.orig/drivers/usb/class/audio.h
++++ /dev/null
+@@ -1,110 +0,0 @@
+-#define CS_AUDIO_UNDEFINED 0x20
+-#define CS_AUDIO_DEVICE 0x21
+-#define CS_AUDIO_CONFIGURATION 0x22
+-#define CS_AUDIO_STRING 0x23
+-#define CS_AUDIO_INTERFACE 0x24
+-#define CS_AUDIO_ENDPOINT 0x25
+-
+-#define HEADER 0x01
+-#define INPUT_TERMINAL 0x02
+-#define OUTPUT_TERMINAL 0x03
+-#define MIXER_UNIT 0x04
+-#define SELECTOR_UNIT 0x05
+-#define FEATURE_UNIT 0x06
+-#define PROCESSING_UNIT 0x07
+-#define EXTENSION_UNIT 0x08
+-
+-#define AS_GENERAL 0x01
+-#define FORMAT_TYPE 0x02
+-#define FORMAT_SPECIFIC 0x03
+-
+-#define EP_GENERAL 0x01
+-
+-#define MAX_CHAN 9
+-#define MAX_FREQ 16
+-#define MAX_IFACE 8
+-#define MAX_FORMAT 8
+-#define MAX_ALT 32 /* Sorry, we need quite a few for the Philips webcams */
+-
+-struct usb_audio_terminal
+-{
+- u8 flags;
+- u8 assoc;
+- u16 type; /* Mic etc */
+- u8 channels;
+- u8 source;
+- u16 chancfg;
+-};
+-
+-struct usb_audio_format
+-{
+- u8 type;
+- u8 channels;
+- u8 num_freq;
+- u8 sfz;
+- u8 bits;
+- u16 freq[MAX_FREQ];
+-};
+-
+-struct usb_audio_interface
+-{
+- u8 terminal;
+- u8 delay;
+- u16 num_formats;
+- u16 format_type;
+- u8 flags;
+- u8 idleconf; /* Idle config */
+-#define AU_IFACE_FOUND 1
+- struct usb_audio_format format[MAX_FORMAT];
+-};
+-
+-struct usb_audio_device
+-{
+- struct list_head list;
+- u8 mixer;
+- u8 selector;
+- void *irq_handle;
+- u8 num_channels;
+- u8 num_dsp_iface;
+- u8 channel_map[MAX_CHAN];
+- struct usb_audio_terminal terminal[MAX_CHAN];
+- struct usb_audio_interface interface[MAX_IFACE][MAX_ALT];
+-};
+-
+-
+-
+-/* Audio Class specific Request Codes */
+-
+-#define SET_CUR 0x01
+-#define GET_CUR 0x81
+-#define SET_MIN 0x02
+-#define GET_MIN 0x82
+-#define SET_MAX 0x03
+-#define GET_MAX 0x83
+-#define SET_RES 0x04
+-#define GET_RES 0x84
+-#define SET_MEM 0x05
+-#define GET_MEM 0x85
+-#define GET_STAT 0xff
+-
+-/* Terminal Control Selectors */
+-
+-#define COPY_PROTECT_CONTROL 0x01
+-
+-/* Feature Unit Control Selectors */
+-
+-#define MUTE_CONTROL 0x01
+-#define VOLUME_CONTROL 0x02
+-#define BASS_CONTROL 0x03
+-#define MID_CONTROL 0x04
+-#define TREBLE_CONTROL 0x05
+-#define GRAPHIC_EQUALIZER_CONTROL 0x06
+-#define AUTOMATIC_GAIN_CONTROL 0x07
+-#define DELAY_CONTROL 0x08
+-#define BASS_BOOST_CONTROL 0x09
+-#define LOUDNESS_CONTROL 0x0a
+-
+-/* Endpoint Control Selectors */
+-
+-#define SAMPLING_FREQ_CONTROL 0x01
+-#define PITCH_CONTROL 0x02
+--- gregkh-2.6.orig/drivers/usb/class/usb-midi.c
++++ /dev/null
+@@ -1,2153 +0,0 @@
+-/*
+- usb-midi.c -- USB-MIDI driver
+-
+- Copyright (C) 2001
+- NAGANO Daisuke <breeze.nagano@nifty.ne.jp>
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 2, or (at your option)
+- any later version.
+-
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- GNU General Public License for more details.
+-
+- You should have received a copy of the GNU General Public License
+- along with this program; if not, write to the Free Software
+- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+- This driver is based on:
+- - 'Universal Serial Bus Device Class Definition for MIDI Device'
+- - linux/drivers/sound/es1371.c, linux/drivers/usb/audio.c
+- - alsa/lowlevel/pci/cs64xx.c
+- - umidi.c for NetBSD
+- */
+-
+-/* ------------------------------------------------------------------------- */
+-
+-
+-#include <linux/module.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/list.h>
+-#include <linux/slab.h>
+-#include <linux/usb.h>
+-#include <linux/poll.h>
+-#include <linux/sound.h>
+-#include <linux/init.h>
+-#include <asm/semaphore.h>
+-
+-#include "usb-midi.h"
+-
+-/* ------------------------------------------------------------------------- */
+-
+-/* More verbose on syslog */
+-#undef MIDI_DEBUG
+-
+-#define MIDI_IN_BUFSIZ 1024
+-
+-#define HAVE_SUPPORT_USB_MIDI_CLASS
+-
+-#undef HAVE_SUPPORT_ALSA
+-
+-/* ------------------------------------------------------------------------- */
+-
+-static int singlebyte = 0;
+-module_param(singlebyte, int, 0);
+-MODULE_PARM_DESC(singlebyte,"Enable sending MIDI messages with single message packet");
+-
+-static int maxdevices = 4;
+-module_param(maxdevices, int, 0);
+-MODULE_PARM_DESC(maxdevices,"Max number of allocatable MIDI device");
+-
+-static int uvendor = -1;
+-module_param(uvendor, int, 0);
+-MODULE_PARM_DESC(uvendor, "The USB Vendor ID of a semi-compliant interface");
+-
+-static int uproduct = -1;
+-module_param(uproduct, int, 0);
+-MODULE_PARM_DESC(uproduct, "The USB Product ID of a semi-compliant interface");
+-
+-static int uinterface = -1;
+-module_param(uinterface, int, 0);
+-MODULE_PARM_DESC(uinterface, "The Interface number of a semi-compliant interface");
+-
+-static int ualt = -1;
+-module_param(ualt, int, 0);
+-MODULE_PARM_DESC(ualt, "The optional alternative setting of a semi-compliant interface");
+-
+-static int umin = -1;
+-module_param(umin, int, 0);
+-MODULE_PARM_DESC(umin, "The input endpoint of a semi-compliant interface");
+-
+-static int umout = -1;
+-module_param(umout, int, 0);
+-MODULE_PARM_DESC(umout, "The output endpoint of a semi-compliant interface");
+-
+-static int ucable = -1;
+-module_param(ucable, int, 0);
+-MODULE_PARM_DESC(ucable, "The cable number used for a semi-compliant interface");
+-
+-/** Note -- the usb_string() returns only Latin-1 characters.
+- * (unicode chars <= 255). To support Japanese, a unicode16LE-to-EUC or
+- * unicode16LE-to-JIS routine is needed to wrap around usb_get_string().
+- **/
+-static unsigned short ulangid = 0x0409; /** 0x0411 for Japanese **/
+-module_param(ulangid, ushort, 0);
+-MODULE_PARM_DESC(ulangid, "The optional preferred USB Language ID for all devices");
+-
+-MODULE_AUTHOR("NAGANO Daisuke <breeze.nagano@nifty.ne.jp>");
+-MODULE_DESCRIPTION("USB-MIDI driver");
+-MODULE_LICENSE("GPL");
+-
+-/* ------------------------------------------------------------------------- */
+-
+-/** MIDIStreaming Class-Specific Interface Descriptor Subtypes **/
+-
+-#define MS_DESCRIPTOR_UNDEFINED 0
+-#define MS_HEADER 1
+-#define MIDI_IN_JACK 2
+-#define MIDI_OUT_JACK 3
+-/* Spec reads: ELEMENT */
+-#define ELEMENT_DESCRIPTOR 4
+-
+-#define MS_HEADER_LENGTH 7
+-
+-/** MIDIStreaming Class-Specific Endpoint Descriptor Subtypes **/
+-
+-#define DESCRIPTOR_UNDEFINED 0
+-/* Spec reads: MS_GENERAL */
+-#define MS_GENERAL_ENDPOINT 1
+-
+-/** MIDIStreaming MIDI IN and OUT Jack Types **/
+-
+-#define JACK_TYPE_UNDEFINED 0
+-/* Spec reads: EMBEDDED */
+-#define EMBEDDED_JACK 1
+-/* Spec reads: EXTERNAL */
+-#define EXTERNAL_JACK 2
+-
+-
+-/* structure summary
+-
+- usb_midi_state usb_device
+- | |
+- *| *| per ep
+- in_ep out_ep
+- | |
+- *| *| per cable
+- min mout
+- | | (cable to device pairing magic)
+- | |
+- usb_midi_dev dev_id (major,minor) == file->private_data
+-
+-*/
+-
+-/* usb_midi_state: corresponds to a USB-MIDI module */
+-struct usb_midi_state {
+- struct list_head mididev;
+-
+- struct usb_device *usbdev;
+-
+- struct list_head midiDevList;
+- struct list_head inEndpointList;
+- struct list_head outEndpointList;
+-
+- spinlock_t lock;
+-
+- unsigned int count; /* usage counter */
+-};
+-
+-/* midi_out_endpoint: corresponds to an output endpoint */
+-struct midi_out_endpoint {
+- struct list_head list;
+-
+- struct usb_device *usbdev;
+- int endpoint;
+- spinlock_t lock;
+- wait_queue_head_t wait;
+-
+- unsigned char *buf;
+- int bufWrPtr;
+- int bufSize;
+-
+- struct urb *urb;
+-};
+-
+-/* midi_in_endpoint: corresponds to an input endpoint */
+-struct midi_in_endpoint {
+- struct list_head list;
+-
+- struct usb_device *usbdev;
+- int endpoint;
+- spinlock_t lock;
+- wait_queue_head_t wait;
+-
+- struct usb_mididev *cables[16]; // cables open for read
+- int readers; // number of cables open for read
+-
+- struct urb *urb;
+- unsigned char *recvBuf;
+- int recvBufSize;
+- int urbSubmitted; //FIXME: == readers > 0
+-};
+-
+-/* usb_mididev: corresponds to a logical device */
+-struct usb_mididev {
+- struct list_head list;
+-
+- struct usb_midi_state *midi;
+- int dev_midi;
+- mode_t open_mode;
+-
+- struct {
+- struct midi_in_endpoint *ep;
+- int cableId;
+-
+-// as we are pushing data from usb_bulk_read to usb_midi_read,
+-// we need a larger, cyclic buffer here.
+- unsigned char buf[MIDI_IN_BUFSIZ];
+- int bufRdPtr;
+- int bufWrPtr;
+- int bufRemains;
+- } min;
+-
+- struct {
+- struct midi_out_endpoint *ep;
+- int cableId;
+-
+- unsigned char buf[3];
+- int bufPtr;
+- int bufRemains;
+-
+- int isInExclusive;
+- unsigned char lastEvent;
+- } mout;
+-
+- int singlebyte;
+-};
+-
+-/** Map the high nybble of MIDI voice messages to number of Message bytes.
+- * High nyble ranges from 0x8 to 0xe
+- */
+-
+-static int remains_80e0[] = {
+- 3, /** 0x8X Note Off **/
+- 3, /** 0x9X Note On **/
+- 3, /** 0xAX Poly-key pressure **/
+- 3, /** 0xBX Control Change **/
+- 2, /** 0xCX Program Change **/
+- 2, /** 0xDX Channel pressure **/
+- 3 /** 0xEX PitchBend Change **/
+-};
+-
+-/** Map the messages to a number of Message bytes.
+- *
+- **/
+-static int remains_f0f6[] = {
+- 0, /** 0xF0 **/
+- 2, /** 0XF1 **/
+- 3, /** 0XF2 **/
+- 2, /** 0XF3 **/
+- 2, /** 0XF4 (Undefined by MIDI Spec, and subject to change) **/
+- 2, /** 0XF5 (Undefined by MIDI Spec, and subject to change) **/
+- 1 /** 0XF6 **/
+-};
+-
+-/** Map the messages to a CIN (Code Index Number).
+- *
+- **/
+-static int cin_f0ff[] = {
+- 4, /** 0xF0 System Exclusive Message Start (special cases may be 6 or 7) */
+- 2, /** 0xF1 **/
+- 3, /** 0xF2 **/
+- 2, /** 0xF3 **/
+- 2, /** 0xF4 **/
+- 2, /** 0xF5 **/
+- 5, /** 0xF6 **/
+- 5, /** 0xF7 End of System Exclusive Message (May be 6 or 7) **/
+- 5, /** 0xF8 **/
+- 5, /** 0xF9 **/
+- 5, /** 0xFA **/
+- 5, /** 0xFB **/
+- 5, /** 0xFC **/
+- 5, /** 0xFD **/
+- 5, /** 0xFE **/
+- 5 /** 0xFF **/
+-};
+-
+-/** Map MIDIStreaming Event packet Code Index Number (low nybble of byte 0)
+- * to the number of bytes of valid MIDI data.
+- *
+- * CIN of 0 and 1 are NOT USED in MIDIStreaming 1.0.
+- *
+- **/
+-static int cin_to_len[] = {
+- 0, 0, 2, 3,
+- 3, 1, 2, 3,
+- 3, 3, 3, 3,
+- 2, 2, 3, 1
+-};
+-
+-
+-/* ------------------------------------------------------------------------- */
+-
+-static struct list_head mididevs = LIST_HEAD_INIT(mididevs);
+-
+-static DECLARE_MUTEX(open_sem);
+-static DECLARE_WAIT_QUEUE_HEAD(open_wait);
+-
+-
+-/* ------------------------------------------------------------------------- */
+-
+-static void usb_write_callback(struct urb *urb, struct pt_regs *regs)
+-{
+- struct midi_out_endpoint *ep = (struct midi_out_endpoint *)urb->context;
+-
+- if ( waitqueue_active( &ep->wait ) )
+- wake_up_interruptible( &ep->wait );
+-}
+-
+-
+-static int usb_write( struct midi_out_endpoint *ep, unsigned char *buf, int len )
+-{
+- struct usb_device *d;
+- int pipe;
+- int ret = 0;
+- int status;
+- int maxretry = 50;
+-
+- DECLARE_WAITQUEUE(wait,current);
+- init_waitqueue_head(&ep->wait);
+-
+- d = ep->usbdev;
+- pipe = usb_sndbulkpipe(d, ep->endpoint);
+- usb_fill_bulk_urb( ep->urb, d, pipe, (unsigned char*)buf, len,
+- usb_write_callback, ep );
+-
+- status = usb_submit_urb(ep->urb, GFP_KERNEL);
+-
+- if (status) {
+- printk(KERN_ERR "usbmidi: Cannot submit urb (%d)\n",status);
+- ret = -EIO;
+- goto error;
+- }
+-
+- add_wait_queue( &ep->wait, &wait );
+- set_current_state( TASK_INTERRUPTIBLE );
+-
+- while( ep->urb->status == -EINPROGRESS ) {
+- if ( maxretry-- < 0 ) {
+- printk(KERN_ERR "usbmidi: usb_bulk_msg timed out\n");
+- ret = -ETIME;
+- break;
+- }
+- interruptible_sleep_on_timeout( &ep->wait, 10 );
+- }
+- set_current_state( TASK_RUNNING );
+- remove_wait_queue( &ep->wait, &wait );
+-
+-error:
+- return ret;
+-}
+-
+-
+-/** Copy data from URB to In endpoint buf.
+- * Discard if CIN == 0 or CIN = 1.
+- *
+- *
+- **/
+-
+-static void usb_bulk_read(struct urb *urb, struct pt_regs *regs)
+-{
+- struct midi_in_endpoint *ep = (struct midi_in_endpoint *)(urb->context);
+- unsigned char *data = urb->transfer_buffer;
+- int i, j, wake;
+-
+- if ( !ep->urbSubmitted ) {
+- return;
+- }
+-
+- if ( (urb->status == 0) && (urb->actual_length > 0) ) {
+- wake = 0;
+- spin_lock( &ep->lock );
+-
+- for(j = 0; j < urb->actual_length; j += 4) {
+- int cin = (data[j]>>0)&0xf;
+- int cab = (data[j]>>4)&0xf;
+- struct usb_mididev *cable = ep->cables[cab];
+- if ( cable ) {
+- int len = cin_to_len[cin]; /** length of MIDI data **/
+- for (i = 0; i < len; i++) {
+- cable->min.buf[cable->min.bufWrPtr] = data[1+i+j];
+- cable->min.bufWrPtr = (cable->min.bufWrPtr+1)%MIDI_IN_BUFSIZ;
+- if (cable->min.bufRemains < MIDI_IN_BUFSIZ)
+- cable->min.bufRemains += 1;
+- else /** need to drop data **/
+- cable->min.bufRdPtr += (cable->min.bufRdPtr+1)%MIDI_IN_BUFSIZ;
+- wake = 1;
+- }
+- }
+- }
+-
+- spin_unlock ( &ep->lock );
+- if ( wake ) {
+- wake_up( &ep->wait );
+- }
+- }
+-
+- /* urb->dev must be reinitialized on 2.4.x kernels */
+- urb->dev = ep->usbdev;
+-
+- urb->actual_length = 0;
+- usb_submit_urb(urb, GFP_ATOMIC);
+-}
+-
+-
+-
+-/* ------------------------------------------------------------------------- */
+-
+-/* This routine must be called with spin_lock */
+-
+-/** Wrapper around usb_write().
+- * This routine must be called with spin_lock held on ep.
+- * Called by midiWrite(), putOneMidiEvent(), and usb_midi_write();
+- **/
+-static int flush_midi_buffer( struct midi_out_endpoint *ep )
+-{
+- int ret=0;
+-
+- if ( ep->bufWrPtr > 0 ) {
+- ret = usb_write( ep, ep->buf, ep->bufWrPtr );
+- ep->bufWrPtr = 0;
+- }
+-
+- return ret;
+-}
+-
+-
+-/* ------------------------------------------------------------------------- */
+-
+-
+-/** Given a MIDI Event, determine size of data to be attached to
+- * USB-MIDI packet.
+- * Returns 1, 2 or 3.
+- * Called by midiWrite();
+- * Uses remains_80e0 and remains_f0f6;
+- **/
+-static int get_remains(int event)
+-{
+- int ret;
+-
+- if ( event < 0x80 ) {
+- ret = 1;
+- } else if ( event < 0xf0 ) {
+- ret = remains_80e0[((event-0x80)>>4)&0x0f];
+- } else if ( event < 0xf7 ) {
+- ret = remains_f0f6[event-0xf0];
+- } else {
+- ret = 1;
+- }
+-
+- return ret;
+-}
+-
+-/** Given the output MIDI data in the output buffer, computes a reasonable
+- * CIN.
+- * Called by putOneMidiEvent().
+- **/
+-static int get_CIN( struct usb_mididev *m )
+-{
+- int cin;
+-
+- if ( m->mout.buf[0] == 0xf7 ) {
+- cin = 5;
+- }
+- else if ( m->mout.buf[1] == 0xf7 ) {
+- cin = 6;
+- }
+- else if ( m->mout.buf[2] == 0xf7 ) {
+- cin = 7;
+- }
+- else {
+- if ( m->mout.isInExclusive == 1 ) {
+- cin = 4;
+- } else if ( m->mout.buf[0] < 0x80 ) {
+- /** One byte that we know nothing about. **/
+- cin = 0xF;
+- } else if ( m->mout.buf[0] < 0xf0 ) {
+- /** MIDI Voice messages 0x8X to 0xEX map to cin 0x8 to 0xE. **/
+- cin = (m->mout.buf[0]>>4)&0x0f;
+- }
+- else {
+- /** Special lookup table exists for real-time events. **/
+- cin = cin_f0ff[m->mout.buf[0]-0xf0];
+- }
+- }
+-
+- return cin;
+-}
+-
+-
+-/* ------------------------------------------------------------------------- */
+-
+-
+-
+-/** Move data to USB endpoint buffer.
+- *
+- **/
+-static int put_one_midi_event(struct usb_mididev *m)
+-{
+- int cin;
+- unsigned long flags;
+- struct midi_out_endpoint *ep = m->mout.ep;
+- int ret=0;
+-
+- cin = get_CIN( m );
+- if ( cin > 0x0f || cin < 0 ) {
+- return -EINVAL;
+- }
+-
+- spin_lock_irqsave( &ep->lock, flags );
+- ep->buf[ep->bufWrPtr++] = (m->mout.cableId<<4) | cin;
+- ep->buf[ep->bufWrPtr++] = m->mout.buf[0];
+- ep->buf[ep->bufWrPtr++] = m->mout.buf[1];
+- ep->buf[ep->bufWrPtr++] = m->mout.buf[2];
+- if ( ep->bufWrPtr >= ep->bufSize ) {
+- ret = flush_midi_buffer( ep );
+- }
+- spin_unlock_irqrestore( &ep->lock, flags);
+-
+- m->mout.buf[0] = m->mout.buf[1] = m->mout.buf[2] = 0;
+- m->mout.bufPtr = 0;
+-
+- return ret;
+-}
+-
+-/** Write the MIDI message v on the midi device.
+- * Called by usb_midi_write();
+- * Responsible for packaging a MIDI data stream into USB-MIDI packets.
+- **/
+-
+-static int midi_write( struct usb_mididev *m, int v )
+-{
+- unsigned long flags;
+- struct midi_out_endpoint *ep = m->mout.ep;
+- int ret=0;
+- unsigned char c = (unsigned char)v;
+- unsigned char sysrt_buf[4];
+-
+- if ( m->singlebyte != 0 ) {
+- /** Simple code to handle the single-byte USB-MIDI protocol. */
+- spin_lock_irqsave( &ep->lock, flags );
+- if ( ep->bufWrPtr+4 > ep->bufSize ) {
+- ret = flush_midi_buffer( ep );
+- if ( !ret ) {
+- spin_unlock_irqrestore( &ep->lock, flags );
+- return ret;
+- }
+- }
+- ep->buf[ep->bufWrPtr++] = (m->mout.cableId<<4) | 0x0f; /* single byte */
+- ep->buf[ep->bufWrPtr++] = c;
+- ep->buf[ep->bufWrPtr++] = 0;
+- ep->buf[ep->bufWrPtr++] = 0;
+- if ( ep->bufWrPtr >= ep->bufSize ) {
+- ret = flush_midi_buffer( ep );
+- }
+- spin_unlock_irqrestore( &ep->lock, flags );
+-
+- return ret;
+- }
+- /** Normal USB-MIDI protocol begins here. */
+-
+- if ( c > 0xf7 ) { /* system: Realtime messages */
+- /** Realtime messages are written IMMEDIATELY. */
+- sysrt_buf[0] = (m->mout.cableId<<4) | 0x0f;
+- sysrt_buf[1] = c;
+- sysrt_buf[2] = 0;
+- sysrt_buf[3] = 0;
+- spin_lock_irqsave( &ep->lock, flags );
+- ret = usb_write( ep, sysrt_buf, 4 );
+- spin_unlock_irqrestore( &ep->lock, flags );
+- /* m->mout.lastEvent = 0; */
+-
+- return ret;
+- }
+-
+- if ( c >= 0x80 ) {
+- if ( c < 0xf0 ) {
+- m->mout.lastEvent = c;
+- m->mout.isInExclusive = 0;
+- m->mout.bufRemains = get_remains(c);
+- } else if ( c == 0xf0 ) {
+- /* m->mout.lastEvent = 0; */
+- m->mout.isInExclusive = 1;
+- m->mout.bufRemains = get_remains(c);
+- } else if ( c == 0xf7 && m->mout.isInExclusive == 1 ) {
+- /* m->mout.lastEvent = 0; */
+- m->mout.isInExclusive = 0;
+- m->mout.bufRemains = 1;
+- } else if ( c > 0xf0 ) {
+- /* m->mout.lastEvent = 0; */
+- m->mout.isInExclusive = 0;
+- m->mout.bufRemains = get_remains(c);
+- }
+-
+- } else if ( m->mout.bufRemains == 0 && m->mout.isInExclusive == 0 ) {
+- if ( m->mout.lastEvent == 0 ) {
+- return 0; /* discard, waiting for the first event */
+- }
+- /** track status **/
+- m->mout.buf[0] = m->mout.lastEvent;
+- m->mout.bufPtr = 1;
+- m->mout.bufRemains = get_remains(m->mout.lastEvent)-1;
+- }
+-
+- m->mout.buf[m->mout.bufPtr++] = c;
+- m->mout.bufRemains--;
+- if ( m->mout.bufRemains == 0 || m->mout.bufPtr >= 3) {
+- ret = put_one_midi_event(m);
+- }
+-
+- return ret;
+-}
+-
+-
+-/* ------------------------------------------------------------------------- */
+-
+-/** Basic operation on /dev/midiXX as registered through struct file_operations.
+- *
+- * Basic contract: Used to change the current read/write position in a file.
+- * On success, the non-negative position is reported.
+- * On failure, the negative of an error code is reported.
+- *
+- * Because a MIDIStream is not a file, all seek operations are doomed to fail.
+- *
+- **/
+-static loff_t usb_midi_llseek(struct file *file, loff_t offset, int origin)
+-{
+- /** Tell user you cannot seek on a PIPE-like device. **/
+- return -ESPIPE;
+-}
+-
+-
+-/** Basic operation on /dev/midiXX as registered through struct file_operations.
+- *
+- * Basic contract: Block until count bytes have been read or an error occurs.
+- *
+- **/
+-
+-static ssize_t usb_midi_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+-{
+- struct usb_mididev *m = (struct usb_mididev *)file->private_data;
+- struct midi_in_endpoint *ep = m->min.ep;
+- ssize_t ret;
+- DECLARE_WAITQUEUE(wait, current);
+-
+- if ( !access_ok(VERIFY_READ, buffer, count) ) {
+- return -EFAULT;
+- }
+- if ( count == 0 ) {
+- return 0;
+- }
+-
+- add_wait_queue( &ep->wait, &wait );
+- ret = 0;
+- while( count > 0 ) {
+- int cnt;
+- int d = (int)count;
+-
+- cnt = m->min.bufRemains;
+- if ( cnt > d ) {
+- cnt = d;
+- }
+-
+- if ( cnt <= 0 ) {
+- if ( file->f_flags & O_NONBLOCK ) {
+- if (!ret)
+- ret = -EAGAIN;
+- break;
+- }
+- __set_current_state(TASK_INTERRUPTIBLE);
+- schedule();
+- if (signal_pending(current)) {
+- if(!ret)
+- ret=-ERESTARTSYS;
+- break;
+- }
+- continue;
+- }
+-
+- {
+- int i;
+- unsigned long flags; /* used to synchronize access to the endpoint */
+- spin_lock_irqsave( &ep->lock, flags );
+- for (i = 0; i < cnt; i++) {
+- if ( copy_to_user( buffer+i, m->min.buf+m->min.bufRdPtr, 1 ) ) {
+- if ( !ret )
+- ret = -EFAULT;
+- break;
+- }
+- m->min.bufRdPtr = (m->min.bufRdPtr+1)%MIDI_IN_BUFSIZ;
+- m->min.bufRemains -= 1;
+- }
+- spin_unlock_irqrestore( &ep->lock, flags );
+- }
+-
+- count-=cnt;
+- buffer+=cnt;
+- ret+=cnt;
+-
+- break;
+- }
+-
+- remove_wait_queue( &ep->wait, &wait );
+- set_current_state(TASK_RUNNING);
+-
+- return ret;
+-}
+-
+-
+-/** Basic operation on /dev/midiXX as registered through struct file_operations.
+- *
+- * Basic Contract: Take MIDI data byte-by-byte and pass it to
+- * writeMidi() which packages MIDI data into USB-MIDI stream.
+- * Then flushMidiData() is called to ensure all bytes have been written
+- * in a timely fashion.
+- *
+- **/
+-
+-static ssize_t usb_midi_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
+-{
+- struct usb_mididev *m = (struct usb_mididev *)file->private_data;
+- ssize_t ret;
+- unsigned long int flags;
+-
+- if ( !access_ok(VERIFY_READ, buffer, count) ) {
+- return -EFAULT;
+- }
+- if ( count == 0 ) {
+- return 0;
+- }
+-
+- ret = 0;
+- while( count > 0 ) {
+- unsigned char c;
+-
+- if (copy_from_user((unsigned char *)&c, buffer, 1)) {
+- if ( ret == 0 )
+- ret = -EFAULT;
+- break;
+- }
+- if( midi_write(m, (int)c) ) {
+- if ( ret == 0 )
+- ret = -EFAULT;
+- break;
+- }
+- count--;
+- buffer++;
+- ret++;
+- }
+-
+- spin_lock_irqsave( &m->mout.ep->lock, flags );
+- if ( flush_midi_buffer(m->mout.ep) < 0 ) {
+- ret = -EFAULT;
+- }
+- spin_unlock_irqrestore( &m->mout.ep->lock, flags );
+-
+- return ret;
+-}
+-
+-/** Basic operation on /dev/midiXX as registered through struct file_operations.
+- *
+- * Basic contract: Wait (spin) until ready to read or write on the file.
+- *
+- **/
+-static unsigned int usb_midi_poll(struct file *file, struct poll_table_struct *wait)
+-{
+- struct usb_mididev *m = (struct usb_mididev *)file->private_data;
+- struct midi_in_endpoint *iep = m->min.ep;
+- struct midi_out_endpoint *oep = m->mout.ep;
+- unsigned long flags;
+- unsigned int mask = 0;
+-
+- if ( file->f_mode & FMODE_READ ) {
+- poll_wait( file, &iep->wait, wait );
+- spin_lock_irqsave( &iep->lock, flags );
+- if ( m->min.bufRemains > 0 )
+- mask |= POLLIN | POLLRDNORM;
+- spin_unlock_irqrestore( &iep->lock, flags );
+- }
+-
+- if ( file->f_mode & FMODE_WRITE ) {
+- poll_wait( file, &oep->wait, wait );
+- spin_lock_irqsave( &oep->lock, flags );
+- if ( oep->bufWrPtr < oep->bufSize )
+- mask |= POLLOUT | POLLWRNORM;
+- spin_unlock_irqrestore( &oep->lock, flags );
+- }
+-
+- return mask;
+-}
+-
+-
+-/** Basic operation on /dev/midiXX as registered through struct file_operations.
+- *
+- * Basic contract: This is always the first operation performed on the
+- * device node. If no method is defined, the open succeeds without any
+- * notification given to the module.
+- *
+- **/
+-
+-static int usb_midi_open(struct inode *inode, struct file *file)
+-{
+- int minor = iminor(inode);
+- DECLARE_WAITQUEUE(wait, current);
+- struct usb_midi_state *s;
+- struct usb_mididev *m;
+- unsigned long flags;
+- int succeed = 0;
+-
+-#if 0
+- printk(KERN_INFO "usb-midi: Open minor= %d.\n", minor);
+-#endif
+-
+- for(;;) {
+- down(&open_sem);
+- list_for_each_entry(s, &mididevs, mididev) {
+- list_for_each_entry(m, &s->midiDevList, list) {
+- if ( !((m->dev_midi ^ minor) & ~0xf) )
+- goto device_found;
+- }
+- }
+- up(&open_sem);
+- return -ENODEV;
+-
+- device_found:
+- if ( !s->usbdev ) {
+- up(&open_sem);
+- return -EIO;
+- }
+- if ( !(m->open_mode & file->f_mode) ) {
+- break;
+- }
+- if ( file->f_flags & O_NONBLOCK ) {
+- up(&open_sem);
+- return -EBUSY;
+- }
+- __set_current_state(TASK_INTERRUPTIBLE);
+- add_wait_queue( &open_wait, &wait );
+- up(&open_sem);
+- schedule();
+- remove_wait_queue( &open_wait, &wait );
+- if ( signal_pending(current) ) {
+- return -ERESTARTSYS;
+- }
+- }
+-
+- file->private_data = m;
+- spin_lock_irqsave( &s->lock, flags );
+-
+- if ( !(m->open_mode & (FMODE_READ | FMODE_WRITE)) ) {
+- //FIXME: intented semantics unclear here
+- m->min.bufRdPtr = 0;
+- m->min.bufWrPtr = 0;
+- m->min.bufRemains = 0;
+- spin_lock_init(&m->min.ep->lock);
+-
+- m->mout.bufPtr = 0;
+- m->mout.bufRemains = 0;
+- m->mout.isInExclusive = 0;
+- m->mout.lastEvent = 0;
+- spin_lock_init(&m->mout.ep->lock);
+- }
+-
+- if ( (file->f_mode & FMODE_READ) && m->min.ep != NULL ) {
+- unsigned long int flagsep;
+- spin_lock_irqsave( &m->min.ep->lock, flagsep );
+- m->min.ep->cables[m->min.cableId] = m;
+- m->min.ep->readers += 1;
+- m->min.bufRdPtr = 0;
+- m->min.bufWrPtr = 0;
+- m->min.bufRemains = 0;
+- spin_unlock_irqrestore( &m->min.ep->lock, flagsep );
+-
+- if ( !(m->min.ep->urbSubmitted)) {
+-
+- /* urb->dev must be reinitialized on 2.4.x kernels */
+- m->min.ep->urb->dev = m->min.ep->usbdev;
+-
+- if ( usb_submit_urb(m->min.ep->urb, GFP_ATOMIC) ) {
+- printk(KERN_ERR "usbmidi: Cannot submit urb for MIDI-IN\n");
+- }
+- m->min.ep->urbSubmitted = 1;
+- }
+- m->open_mode |= FMODE_READ;
+- succeed = 1;
+- }
+-
+- if ( (file->f_mode & FMODE_WRITE) && m->mout.ep != NULL ) {
+- m->mout.bufPtr = 0;
+- m->mout.bufRemains = 0;
+- m->mout.isInExclusive = 0;
+- m->mout.lastEvent = 0;
+- m->open_mode |= FMODE_WRITE;
+- succeed = 1;
+- }
+-
+- spin_unlock_irqrestore( &s->lock, flags );
+-
+- s->count++;
+- up(&open_sem);
+-
+- /** Changed to prevent extra increments to USE_COUNT. **/
+- if (!succeed) {
+- return -EBUSY;
+- }
+-
+-#if 0
+- printk(KERN_INFO "usb-midi: Open Succeeded. minor= %d.\n", minor);
+-#endif
+-
+- return nonseekable_open(inode, file); /** Success. **/
+-}
+-
+-
+-/** Basic operation on /dev/midiXX as registered through struct file_operations.
+- *
+- * Basic contract: Close an opened file and deallocate anything we allocated.
+- * Like open(), this can be missing. If open set file->private_data,
+- * release() must clear it.
+- *
+- **/
+-
+-static int usb_midi_release(struct inode *inode, struct file *file)
+-{
+- struct usb_mididev *m = (struct usb_mididev *)file->private_data;
+- struct usb_midi_state *s = (struct usb_midi_state *)m->midi;
+-
+-#if 0
+- printk(KERN_INFO "usb-midi: Close.\n");
+-#endif
+-
+- down(&open_sem);
+-
+- if ( m->open_mode & FMODE_WRITE ) {
+- m->open_mode &= ~FMODE_WRITE;
+- usb_kill_urb( m->mout.ep->urb );
+- }
+-
+- if ( m->open_mode & FMODE_READ ) {
+- unsigned long int flagsep;
+- spin_lock_irqsave( &m->min.ep->lock, flagsep );
+- m->min.ep->cables[m->min.cableId] = NULL; // discard cable
+- m->min.ep->readers -= 1;
+- m->open_mode &= ~FMODE_READ;
+- if ( m->min.ep->readers == 0 &&
+- m->min.ep->urbSubmitted ) {
+- m->min.ep->urbSubmitted = 0;
+- usb_kill_urb(m->min.ep->urb);
+- }
+- spin_unlock_irqrestore( &m->min.ep->lock, flagsep );
+- }
+-
+- s->count--;
+-
+- up(&open_sem);
+- wake_up(&open_wait);
+-
+- file->private_data = NULL;
+- return 0;
+-}
+-
+-static struct file_operations usb_midi_fops = {
+- .owner = THIS_MODULE,
+- .llseek = usb_midi_llseek,
+- .read = usb_midi_read,
+- .write = usb_midi_write,
+- .poll = usb_midi_poll,
+- .open = usb_midi_open,
+- .release = usb_midi_release,
+-};
+-
+-/* ------------------------------------------------------------------------- */
+-
+-/** Returns filled midi_in_endpoint structure or null on failure.
+- *
+- * Parameters:
+- * d - a usb_device
+- * endPoint - An usb endpoint in the range 0 to 15.
+- * Called by allocUsbMidiDev();
+- *
+- **/
+-
+-static struct midi_in_endpoint *alloc_midi_in_endpoint( struct usb_device *d, int endPoint )
+-{
+- struct midi_in_endpoint *ep;
+- int bufSize;
+- int pipe;
+-
+- endPoint &= 0x0f; /* Silently force endPoint to lie in range 0 to 15. */
+-
+- pipe = usb_rcvbulkpipe( d, endPoint );
+- bufSize = usb_maxpacket( d, pipe, 0 );
+- /* usb_pipein() = ! usb_pipeout() = true for an in Endpoint */
+-
+- ep = (struct midi_in_endpoint *)kmalloc(sizeof(struct midi_in_endpoint), GFP_KERNEL);
+- if ( !ep ) {
+- printk(KERN_ERR "usbmidi: no memory for midi in-endpoint\n");
+- return NULL;
+- }
+- memset( ep, 0, sizeof(struct midi_in_endpoint) );
+-// this sets cables[] and readers to 0, too.
+-// for (i=0; i<16; i++) ep->cables[i] = 0; // discard cable
+-// ep->readers = 0;
+-
+- ep->endpoint = endPoint;
+-
+- ep->recvBuf = (unsigned char *)kmalloc(sizeof(unsigned char)*(bufSize), GFP_KERNEL);
+- if ( !ep->recvBuf ) {
+- printk(KERN_ERR "usbmidi: no memory for midi in-endpoint buffer\n");
+- kfree(ep);
+- return NULL;
+- }
+-
+- ep->urb = usb_alloc_urb(0, GFP_KERNEL); /* no ISO */
+- if ( !ep->urb ) {
+- printk(KERN_ERR "usbmidi: no memory for midi in-endpoint urb\n");
+- kfree(ep->recvBuf);
+- kfree(ep);
+- return NULL;
+- }
+- usb_fill_bulk_urb( ep->urb, d,
+- usb_rcvbulkpipe(d, endPoint),
+- (unsigned char *)ep->recvBuf, bufSize,
+- usb_bulk_read, ep );
+-
+- /* ep->bufRdPtr = 0; */
+- /* ep->bufWrPtr = 0; */
+- /* ep->bufRemains = 0; */
+- /* ep->urbSubmitted = 0; */
+- ep->recvBufSize = bufSize;
+-
+- init_waitqueue_head(&ep->wait);
+-
+- return ep;
+-}
+-
+-static int remove_midi_in_endpoint( struct midi_in_endpoint *min )
+-{
+- usb_kill_urb( min->urb );
+- usb_free_urb( min->urb );
+- kfree( min->recvBuf );
+- kfree( min );
+-
+- return 0;
+-}
+-
+-/** Returns filled midi_out_endpoint structure or null on failure.
+- *
+- * Parameters:
+- * d - a usb_device
+- * endPoint - An usb endpoint in the range 0 to 15.
+- * Called by allocUsbMidiDev();
+- *
+- **/
+-static struct midi_out_endpoint *alloc_midi_out_endpoint( struct usb_device *d, int endPoint )
+-{
+- struct midi_out_endpoint *ep = NULL;
+- int pipe;
+- int bufSize;
+-
+- endPoint &= 0x0f;
+- pipe = usb_sndbulkpipe( d, endPoint );
+- bufSize = usb_maxpacket( d, pipe, 1 );
+-
+- ep = (struct midi_out_endpoint *)kmalloc(sizeof(struct midi_out_endpoint), GFP_KERNEL);
+- if ( !ep ) {
+- printk(KERN_ERR "usbmidi: no memory for midi out-endpoint\n");
+- return NULL;
+- }
+- memset( ep, 0, sizeof(struct midi_out_endpoint) );
+-
+- ep->endpoint = endPoint;
+- ep->buf = (unsigned char *)kmalloc(sizeof(unsigned char)*bufSize, GFP_KERNEL);
+- if ( !ep->buf ) {
+- printk(KERN_ERR "usbmidi: no memory for midi out-endpoint buffer\n");
+- kfree(ep);
+- return NULL;
+- }
+-
+- ep->urb = usb_alloc_urb(0, GFP_KERNEL); /* no ISO */
+- if ( !ep->urb ) {
+- printk(KERN_ERR "usbmidi: no memory for midi out-endpoint urb\n");
+- kfree(ep->buf);
+- kfree(ep);
+- return NULL;
+- }
+-
+- ep->bufSize = bufSize;
+- /* ep->bufWrPtr = 0; */
+-
+- init_waitqueue_head(&ep->wait);
+-
+- return ep;
+-}
+-
+-
+-static int remove_midi_out_endpoint( struct midi_out_endpoint *mout )
+-{
+- usb_kill_urb( mout->urb );
+- usb_free_urb( mout->urb );
+- kfree( mout->buf );
+- kfree( mout );
+-
+- return 0;
+-}
+-
+-
+-/** Returns a filled usb_mididev structure, registered as a Linux MIDI device.
+- *
+- * Returns null if memory is not available or the device cannot be registered.
+- * Called by allocUsbMidiDev();
+- *
+- **/
+-static struct usb_mididev *allocMidiDev(
+- struct usb_midi_state *s,
+- struct midi_in_endpoint *min,
+- struct midi_out_endpoint *mout,
+- int inCableId,
+- int outCableId )
+-{
+- struct usb_mididev *m;
+-
+- m = (struct usb_mididev *)kmalloc(sizeof(struct usb_mididev), GFP_KERNEL);
+- if (!m) {
+- printk(KERN_ERR "usbmidi: no memory for midi device\n");
+- return NULL;
+- }
+-
+- memset(m, 0, sizeof(struct usb_mididev));
+-
+- if ((m->dev_midi = register_sound_midi(&usb_midi_fops, -1)) < 0) {
+- printk(KERN_ERR "usbmidi: cannot register midi device\n");
+- kfree(m);
+- return NULL;
+- }
+-
+- m->midi = s;
+- /* m->open_mode = 0; */
+-
+- if ( min ) {
+- m->min.ep = min;
+- m->min.ep->usbdev = s->usbdev;
+- m->min.cableId = inCableId;
+- }
+- /* m->min.bufPtr = 0; */
+- /* m->min.bufRemains = 0; */
+-
+- if ( mout ) {
+- m->mout.ep = mout;
+- m->mout.ep->usbdev = s->usbdev;
+- m->mout.cableId = outCableId;
+- }
+- /* m->mout.bufPtr = 0; */
+- /* m->mout.bufRemains = 0; */
+- /* m->mout.isInExclusive = 0; */
+- /* m->mout.lastEvent = 0; */
+-
+- m->singlebyte = singlebyte;
+-
+- return m;
+-}
+-
+-
+-static void release_midi_device( struct usb_midi_state *s )
+-{
+- struct usb_mididev *m;
+- struct midi_in_endpoint *min;
+- struct midi_out_endpoint *mout;
+-
+- if ( s->count > 0 ) {
+- up(&open_sem);
+- return;
+- }
+- up( &open_sem );
+- wake_up( &open_wait );
+-
+- while(!list_empty(&s->inEndpointList)) {
+- min = list_entry(s->inEndpointList.next, struct midi_in_endpoint, list);
+- list_del(&min->list);
+- remove_midi_in_endpoint(min);
+- }
+-
+- while(!list_empty(&s->outEndpointList)) {
+- mout = list_entry(s->outEndpointList.next, struct midi_out_endpoint, list);
+- list_del(&mout->list);
+- remove_midi_out_endpoint(mout);
+- }
+-
+- while(!list_empty(&s->midiDevList)) {
+- m = list_entry(s->midiDevList.next, struct usb_mididev, list);
+- list_del(&m->list);
+- kfree(m);
+- }
+-
+- kfree(s);
+-
+- return;
+-}
+-
+-
+-/* ------------------------------------------------------------------------- */
+-
+-/** Utility routine to find a descriptor in a dump of many descriptors.
+- * Returns start of descriptor or NULL if not found.
+- * descStart pointer to list of interfaces.
+- * descLength length (in bytes) of dump
+- * after (ignored if NULL) this routine returns only descriptors after "after"
+- * dtype (mandatory) The descriptor type.
+- * iface (ignored if -1) returns descriptor at/following given interface
+- * altSetting (ignored if -1) returns descriptor at/following given altSetting
+- *
+- *
+- * Called by parseDescriptor(), find_csinterface_descriptor();
+- *
+- */
+-static void *find_descriptor( void *descStart, unsigned int descLength, void *after, unsigned char dtype, int iface, int altSetting )
+-{
+- unsigned char *p, *end, *next;
+- int interfaceNumber = -1, altSet = -1;
+-
+- p = descStart;
+- end = p + descLength;
+- for( ; p < end; ) {
+- if ( p[0] < 2 )
+- return NULL;
+- next = p + p[0];
+- if ( next > end )
+- return NULL;
+- if ( p[1] == USB_DT_INTERFACE ) {
+- if ( p[0] < USB_DT_INTERFACE_SIZE )
+- return NULL;
+- interfaceNumber = p[2];
+- altSet = p[3];
+- }
+- if ( p[1] == dtype &&
+- ( !after || ( p > (unsigned char *)after) ) &&
+- ( ( iface == -1) || (iface == interfaceNumber) ) &&
+- ( (altSetting == -1) || (altSetting == altSet) )) {
+- return p;
+- }
+- p = next;
+- }
+- return NULL;
+-}
+-
+-/** Utility to find a class-specific interface descriptor.
+- * dsubtype is a descriptor subtype
+- * Called by parseDescriptor();
+- **/
+-static void *find_csinterface_descriptor(void *descStart, unsigned int descLength, void *after, u8 dsubtype, int iface, int altSetting)
+-{
+- unsigned char *p;
+-
+- p = find_descriptor( descStart, descLength, after, USB_DT_CS_INTERFACE, iface, altSetting );
+- while ( p ) {
+- if ( p[0] >= 3 && p[2] == dsubtype )
+- return p;
+- p = find_descriptor( descStart, descLength, p, USB_DT_CS_INTERFACE,
+- iface, altSetting );
+- }
+- return NULL;
+-}
+-
+-
+-/** The magic of making a new usb_midi_device from config happens here.
+- *
+- * The caller is responsible for free-ing this return value (if not NULL).
+- *
+- **/
+-static struct usb_midi_device *parse_descriptor( struct usb_device *d, unsigned char *buffer, int bufSize, unsigned int ifnum , unsigned int altSetting, int quirks)
+-{
+- struct usb_midi_device *u;
+- unsigned char *p1;
+- unsigned char *p2;
+- unsigned char *next;
+- int iep, oep;
+- int length;
+- unsigned long longBits;
+- int pins, nbytes, offset, shift, jack;
+-#ifdef HAVE_JACK_STRINGS
+- /** Jacks can have associated names. **/
+- unsigned char jack2string[256];
+-#endif
+-
+- u = NULL;
+- /* find audiocontrol interface */
+- p1 = find_csinterface_descriptor( buffer, bufSize, NULL,
+- MS_HEADER, ifnum, altSetting);
+-
+- if ( !p1 ) {
+- goto error_end;
+- }
+-
+- if ( p1[0] < MS_HEADER_LENGTH ) {
+- goto error_end;
+- }
+-
+- /* Assume success. Since the device corresponds to USB-MIDI spec, we assume
+- that the rest of the USB 2.0 spec is obeyed. */
+-
+- u = (struct usb_midi_device *)kmalloc( sizeof(struct usb_midi_device), GFP_KERNEL );
+- if ( !u ) {
+- return NULL;
+- }
+- u->deviceName = NULL;
+- u->idVendor = le16_to_cpu(d->descriptor.idVendor);
+- u->idProduct = le16_to_cpu(d->descriptor.idProduct);
+- u->interface = ifnum;
+- u->altSetting = altSetting;
+- u->in[0].endpoint = -1;
+- u->in[0].cableId = -1;
+- u->out[0].endpoint = -1;
+- u->out[0].cableId = -1;
+-
+-
+- printk(KERN_INFO "usb-midi: Found MIDIStreaming device corresponding to Release %d.%02d of spec.\n",
+- (p1[4] >> 4) * 10 + (p1[4] & 0x0f ),
+- (p1[3] >> 4) * 10 + (p1[3] & 0x0f )
+- );
+-
+- length = p1[5] | (p1[6] << 8);
+-
+-#ifdef HAVE_JACK_STRINGS
+- memset(jack2string, 0, sizeof(unsigned char) * 256);
+-#endif
+-
+- length -= p1[0];
+- for (p2 = p1 + p1[0]; length > 0; p2 = next) {
+- next = p2 + p2[0];
+- length -= p2[0];
+-
+- if (p2[0] < 2 )
+- break;
+- if (p2[1] != USB_DT_CS_INTERFACE)
+- break;
+- if (p2[2] == MIDI_IN_JACK && p2[0] >= 6 ) {
+- jack = p2[4];
+-#ifdef HAVE_JACK_STRINGS
+- jack2string[jack] = p2[5];
+-#endif
+- printk(KERN_INFO "usb-midi: Found IN Jack 0x%02x %s\n",
+- jack, (p2[3] == EMBEDDED_JACK)?"EMBEDDED":"EXTERNAL" );
+- } else if ( p2[2] == MIDI_OUT_JACK && p2[0] >= 6) {
+- pins = p2[5];
+- if ( p2[0] < (6 + 2 * pins) )
+- continue;
+- jack = p2[4];
+-#ifdef HAVE_JACK_STRINGS
+- jack2string[jack] = p2[5 + 2 * pins];
+-#endif
+- printk(KERN_INFO "usb-midi: Found OUT Jack 0x%02x %s, %d pins\n",
+- jack, (p2[3] == EMBEDDED_JACK)?"EMBEDDED":"EXTERNAL", pins );
+- } else if ( p2[2] == ELEMENT_DESCRIPTOR && p2[0] >= 10) {
+- pins = p2[4];
+- if ( p2[0] < (9 + 2 * pins ) )
+- continue;
+- nbytes = p2[8 + 2 * pins ];
+- if ( p2[0] < (10 + 2 * pins + nbytes) )
+- continue;
+- longBits = 0L;
+- for ( offset = 0, shift = 0; offset < nbytes && offset < 8; offset ++, shift += 8) {
+- longBits |= ((long)(p2[9 + 2 * pins + offset])) << shift;
+- }
+- jack = p2[3];
+-#ifdef HAVE_JACK_STRINGS
+- jack2string[jack] = p2[9 + 2 * pins + nbytes];
+-#endif
+- printk(KERN_INFO "usb-midi: Found ELEMENT 0x%02x, %d/%d pins in/out, bits: 0x%016lx\n",
+- jack, pins, (int)(p2[5 + 2 * pins]), (long)longBits );
+- } else {
+- }
+- }
+-
+- iep=0;
+- oep=0;
+-
+- if (quirks==0) {
+- /* MIDISTREAM */
+- p2 = NULL;
+- for (p1 = find_descriptor(buffer, bufSize, NULL, USB_DT_ENDPOINT,
+- ifnum, altSetting ); p1; p1 = next ) {
+- next = find_descriptor(buffer, bufSize, p1, USB_DT_ENDPOINT,
+- ifnum, altSetting );
+- p2 = find_descriptor(buffer, bufSize, p1, USB_DT_CS_ENDPOINT,
+- ifnum, altSetting );
+-
+- if ( p2 && next && ( p2 > next ) )
+- p2 = NULL;
+-
+- if ( p1[0] < 9 || !p2 || p2[0] < 4 )
+- continue;
+-
+- if ( (p1[2] & 0x80) == 0x80 ) {
+- if ( iep < 15 ) {
+- pins = p2[3]; /* not pins -- actually "cables" */
+- if ( pins > 16 )
+- pins = 16;
+- u->in[iep].endpoint = p1[2];
+- u->in[iep].cableId = ( 1 << pins ) - 1;
+- if ( u->in[iep].cableId )
+- iep ++;
+- if ( iep < 15 ) {
+- u->in[iep].endpoint = -1;
+- u->in[iep].cableId = -1;
+- }
+- }
+- } else {
+- if ( oep < 15 ) {
+- pins = p2[3]; /* not pins -- actually "cables" */
+- if ( pins > 16 )
+- pins = 16;
+- u->out[oep].endpoint = p1[2];
+- u->out[oep].cableId = ( 1 << pins ) - 1;
+- if ( u->out[oep].cableId )
+- oep ++;
+- if ( oep < 15 ) {
+- u->out[oep].endpoint = -1;
+- u->out[oep].cableId = -1;
+- }
+- }
+- }
+-
+- }
+- } else if (quirks==1) {
+- /* YAMAHA quirks */
+- for (p1 = find_descriptor(buffer, bufSize, NULL, USB_DT_ENDPOINT,
+- ifnum, altSetting ); p1; p1 = next ) {
+- next = find_descriptor(buffer, bufSize, p1, USB_DT_ENDPOINT,
+- ifnum, altSetting );
+-
+- if ( p1[0] < 7 )
+- continue;
+-
+- if ( (p1[2] & 0x80) == 0x80 ) {
+- if ( iep < 15 ) {
+- pins = iep+1;
+- if ( pins > 16 )
+- pins = 16;
+- u->in[iep].endpoint = p1[2];
+- u->in[iep].cableId = ( 1 << pins ) - 1;
+- if ( u->in[iep].cableId )
+- iep ++;
+- if ( iep < 15 ) {
+- u->in[iep].endpoint = -1;
+- u->in[iep].cableId = -1;
+- }
+- }
+- } else {
+- if ( oep < 15 ) {
+- pins = oep+1;
+- u->out[oep].endpoint = p1[2];
+- u->out[oep].cableId = ( 1 << pins ) - 1;
+- if ( u->out[oep].cableId )
+- oep ++;
+- if ( oep < 15 ) {
+- u->out[oep].endpoint = -1;
+- u->out[oep].cableId = -1;
+- }
+- }
+- }
+-
+- }
+- }
+-
+- if ( !iep && ! oep ) {
+- goto error_end;
+- }
+-
+- return u;
+-
+-error_end:
+- kfree(u);
+- return NULL;
+-}
+-
+-/* ------------------------------------------------------------------------- */
+-
+-/** Returns number between 0 and 16.
+- *
+- **/
+-static int on_bits( unsigned short v )
+-{
+- int i;
+- int ret=0;
+-
+- for ( i=0 ; i<16 ; i++ ) {
+- if ( v & (1<<i) )
+- ret++;
+- }
+-
+- return ret;
+-}
+-
+-
+-/** USB-device will be interrogated for altSetting.
+- *
+- * Returns negative on error.
+- * Called by allocUsbMidiDev();
+- *
+- **/
+-
+-static int get_alt_setting( struct usb_device *d, int ifnum )
+-{
+- int alts, alt=0;
+- struct usb_interface *iface;
+- struct usb_host_interface *interface;
+- struct usb_endpoint_descriptor *ep;
+- int epin, epout;
+- int i;
+-
+- iface = usb_ifnum_to_if( d, ifnum );
+- alts = iface->num_altsetting;
+-
+- for ( alt=0 ; alt<alts ; alt++ ) {
+- interface = &iface->altsetting[alt];
+- epin = -1;
+- epout = -1;
+-
+- for ( i=0 ; i<interface->desc.bNumEndpoints ; i++ ) {
+- ep = &interface->endpoint[i].desc;
+- if ( (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ) {
+- continue;
+- }
+- if ( (ep->bEndpointAddress & USB_DIR_IN) && epin < 0 ) {
+- epin = i;
+- } else if ( epout < 0 ) {
+- epout = i;
+- }
+- if ( epin >= 0 && epout >= 0 ) {
+- return interface->desc.bAlternateSetting;
+- }
+- }
+- }
+-
+- return -ENODEV;
+-}
+-
+-
+-/* ------------------------------------------------------------------------- */
+-
+-
+-/** Returns 0 if successful in allocating and registering internal structures.
+- * Returns negative on failure.
+- * Calls allocMidiDev which additionally registers /dev/midiXX devices.
+- * Writes messages on success to indicate which /dev/midiXX is which physical
+- * endpoint.
+- *
+- **/
+-static int alloc_usb_midi_device( struct usb_device *d, struct usb_midi_state *s, struct usb_midi_device *u )
+-{
+- struct usb_mididev **mdevs=NULL;
+- struct midi_in_endpoint *mins[15], *min;
+- struct midi_out_endpoint *mouts[15], *mout;
+- int inDevs=0, outDevs=0;
+- int inEndpoints=0, outEndpoints=0;
+- int inEndpoint, outEndpoint;
+- int inCableId, outCableId;
+- int i;
+- int devices = 0;
+- int alt = 0;
+-
+- /* Obtain altSetting or die.. */
+- alt = u->altSetting;
+- if ( alt < 0 ) {
+- alt = get_alt_setting( d, u->interface );
+- }
+- if ( alt < 0 )
+- return -ENXIO;
+-
+- /* Configure interface */
+- if ( usb_set_interface( d, u->interface, alt ) < 0 ) {
+- return -ENXIO;
+- }
+-
+- for ( i = 0 ; i < 15 ; i++ ) {
+- mins[i] = NULL;
+- mouts[i] = NULL;
+- }
+-
+- /* Begin Allocation */
+- while( inEndpoints < 15
+- && inDevs < maxdevices
+- && u->in[inEndpoints].cableId >= 0 ) {
+- inDevs += on_bits((unsigned short)u->in[inEndpoints].cableId);
+- mins[inEndpoints] = alloc_midi_in_endpoint( d, u->in[inEndpoints].endpoint );
+- if ( mins[inEndpoints] == NULL )
+- goto error_end;
+- inEndpoints++;
+- }
+-
+- while( outEndpoints < 15
+- && outDevs < maxdevices
+- && u->out[outEndpoints].cableId >= 0 ) {
+- outDevs += on_bits((unsigned short)u->out[outEndpoints].cableId);
+- mouts[outEndpoints] = alloc_midi_out_endpoint( d, u->out[outEndpoints].endpoint );
+- if ( mouts[outEndpoints] == NULL )
+- goto error_end;
+- outEndpoints++;
+- }
+-
+- devices = inDevs > outDevs ? inDevs : outDevs;
+- devices = maxdevices > devices ? devices : maxdevices;
+-
+- /* obtain space for device name (iProduct) if not known. */
+- if ( ! u->deviceName ) {
+- mdevs = (struct usb_mididev **)
+- kmalloc(sizeof(struct usb_mididevs *)*devices
+- + sizeof(char) * 256, GFP_KERNEL);
+- } else {
+- mdevs = (struct usb_mididev **)
+- kmalloc(sizeof(struct usb_mididevs *)*devices, GFP_KERNEL);
+- }
+-
+- if ( !mdevs ) {
+- /* devices = 0; */
+- /* mdevs = NULL; */
+- goto error_end;
+- }
+- for ( i=0 ; i<devices ; i++ ) {
+- mdevs[i] = NULL;
+- }
+-
+- /* obtain device name (iProduct) if not known. */
+- if ( ! u->deviceName ) {
+- u->deviceName = (char *) (mdevs + devices);
+- if ( ! d->have_langid && d->descriptor.iProduct) {
+- alt = usb_get_string(d, 0, 0, u->deviceName, 250);
+- if (alt < 0) {
+- printk(KERN_INFO "error getting string descriptor 0 (error=%d)\n", alt);
+- } else if (u->deviceName[0] < 4) {
+- printk(KERN_INFO "string descriptor 0 too short (length = %d)\n", alt);
+- } else {
+- printk(KERN_INFO "string descriptor 0 found (length = %d)\n", alt);
+- for(; alt >= 4; alt -= 2) {
+- i = u->deviceName[alt-2] | (u->deviceName[alt-1]<< 8);
+- printk(KERN_INFO "usb-midi: langid(%d) 0x%04x\n",
+- (alt-4) >> 1, i);
+- if ( ( ( i ^ ulangid ) & 0xff ) == 0 ) {
+- d->have_langid = 1;
+- d->string_langid = i;
+- printk(KERN_INFO "usb-midi: langid(match) 0x%04x\n", i);
+- if ( i == ulangid )
+- break;
+- }
+- }
+- }
+- }
+- u->deviceName[0] = (char) 0;
+- if (d->descriptor.iProduct) {
+- printk(KERN_INFO "usb-midi: fetchString(%d)\n", d->descriptor.iProduct);
+- alt = usb_string(d, d->descriptor.iProduct, u->deviceName, 255);
+- if( alt < 0 ) {
+- u->deviceName[0] = (char) 0;
+- }
+- printk(KERN_INFO "usb-midi: fetchString = %d\n", alt);
+- }
+- /* Failsafe */
+- if ( !u->deviceName[0] ) {
+- if (le16_to_cpu(d->descriptor.idVendor) == USB_VENDOR_ID_ROLAND ) {
+- strcpy(u->deviceName, "Unknown Roland");
+- } else if (le16_to_cpu(d->descriptor.idVendor) == USB_VENDOR_ID_STEINBERG ) {
+- strcpy(u->deviceName, "Unknown Steinberg");
+- } else if (le16_to_cpu(d->descriptor.idVendor) == USB_VENDOR_ID_YAMAHA ) {
+- strcpy(u->deviceName, "Unknown Yamaha");
+- } else {
+- strcpy(u->deviceName, "Unknown");
+- }
+- }
+- }
+-
+- inEndpoint = 0; inCableId = -1;
+- outEndpoint = 0; outCableId = -1;
+-
+- for ( i=0 ; i<devices ; i++ ) {
+- for ( inCableId ++ ;
+- inEndpoint <15
+- && mins[inEndpoint]
+- && !(u->in[inEndpoint].cableId & (1<<inCableId)) ;
+- inCableId++ ) {
+- if ( inCableId >= 16 ) {
+- inEndpoint ++;
+- inCableId = 0;
+- }
+- }
+- min = mins[inEndpoint];
+- for ( outCableId ++ ;
+- outEndpoint <15
+- && mouts[outEndpoint]
+- && !(u->out[outEndpoint].cableId & (1<<outCableId)) ;
+- outCableId++ ) {
+- if ( outCableId >= 16 ) {
+- outEndpoint ++;
+- outCableId = 0;
+- }
+- }
+- mout = mouts[outEndpoint];
+-
+- mdevs[i] = allocMidiDev( s, min, mout, inCableId, outCableId );
+- if ( mdevs[i] == NULL )
+- goto error_end;
+-
+- }
+-
+- /* Success! */
+- for ( i=0 ; i<devices ; i++ ) {
+- list_add_tail( &mdevs[i]->list, &s->midiDevList );
+- }
+- for ( i=0 ; i<inEndpoints ; i++ ) {
+- list_add_tail( &mins[i]->list, &s->inEndpointList );
+- }
+- for ( i=0 ; i<outEndpoints ; i++ ) {
+- list_add_tail( &mouts[i]->list, &s->outEndpointList );
+- }
+-
+- printk(KERN_INFO "usbmidi: found [ %s ] (0x%04x:0x%04x), attached:\n", u->deviceName, u->idVendor, u->idProduct );
+- for ( i=0 ; i<devices ; i++ ) {
+- int dm = (mdevs[i]->dev_midi-2)>>4;
+- if ( mdevs[i]->mout.ep != NULL && mdevs[i]->min.ep != NULL ) {
+- printk(KERN_INFO "usbmidi: /dev/midi%02d: in (ep:%02x cid:%2d bufsiz:%2d) out (ep:%02x cid:%2d bufsiz:%2d)\n",
+- dm,
+- mdevs[i]->min.ep->endpoint|USB_DIR_IN, mdevs[i]->min.cableId, mdevs[i]->min.ep->recvBufSize,
+- mdevs[i]->mout.ep->endpoint, mdevs[i]->mout.cableId, mdevs[i]->mout.ep->bufSize);
+- } else if ( mdevs[i]->min.ep != NULL ) {
+- printk(KERN_INFO "usbmidi: /dev/midi%02d: in (ep:%02x cid:%2d bufsiz:%02d)\n",
+- dm,
+- mdevs[i]->min.ep->endpoint|USB_DIR_IN, mdevs[i]->min.cableId, mdevs[i]->min.ep->recvBufSize);
+- } else if ( mdevs[i]->mout.ep != NULL ) {
+- printk(KERN_INFO "usbmidi: /dev/midi%02d: out (ep:%02x cid:%2d bufsiz:%02d)\n",
+- dm,
+- mdevs[i]->mout.ep->endpoint, mdevs[i]->mout.cableId, mdevs[i]->mout.ep->bufSize);
+- }
+- }
+-
+- kfree(mdevs);
+- return 0;
+-
+- error_end:
+- if ( mdevs != NULL ) {
+- for ( i=0 ; i<devices ; i++ ) {
+- if ( mdevs[i] != NULL ) {
+- unregister_sound_midi( mdevs[i]->dev_midi );
+- kfree(mdevs[i]);
+- }
+- }
+- kfree(mdevs);
+- }
+-
+- for ( i=0 ; i<15 ; i++ ) {
+- if ( mins[i] != NULL ) {
+- remove_midi_in_endpoint( mins[i] );
+- }
+- if ( mouts[i] != NULL ) {
+- remove_midi_out_endpoint( mouts[i] );
+- }
+- }
+-
+- return -ENOMEM;
+-}
+-
+-/* ------------------------------------------------------------------------- */
+-
+-/** Attempt to scan YAMAHA's device descriptor and detect correct values of
+- * them.
+- * Return 0 on succes, negative on failure.
+- * Called by usb_midi_probe();
+- **/
+-
+-static int detect_yamaha_device( struct usb_device *d,
+- struct usb_interface *iface, unsigned int ifnum,
+- struct usb_midi_state *s)
+-{
+- struct usb_host_interface *interface;
+- struct usb_midi_device *u;
+- unsigned char *buffer;
+- int bufSize;
+- int i;
+- int alts=-1;
+- int ret;
+-
+- if (le16_to_cpu(d->descriptor.idVendor) != USB_VENDOR_ID_YAMAHA) {
+- return -EINVAL;
+- }
+-
+- for ( i=0 ; i < iface->num_altsetting; i++ ) {
+- interface = iface->altsetting + i;
+-
+- if ( interface->desc.bInterfaceClass != 255 ||
+- interface->desc.bInterfaceSubClass != 0 )
+- continue;
+- alts = interface->desc.bAlternateSetting;
+- }
+- if ( alts == -1 ) {
+- return -EINVAL;
+- }
+-
+- printk(KERN_INFO "usb-midi: Found YAMAHA USB-MIDI device on dev %04x:%04x, iface %d\n",
+- le16_to_cpu(d->descriptor.idVendor),
+- le16_to_cpu(d->descriptor.idProduct), ifnum);
+-
+- i = d->actconfig - d->config;
+- buffer = d->rawdescriptors[i];
+- bufSize = le16_to_cpu(d->actconfig->desc.wTotalLength);
+-
+- u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 1);
+- if ( u == NULL ) {
+- return -EINVAL;
+- }
+-
+- ret = alloc_usb_midi_device( d, s, u );
+-
+- kfree(u);
+-
+- return ret;
+-}
+-
+-
+-/** Scan table of known devices which are only partially compliant with
+- * the MIDIStreaming specification.
+- * Called by usb_midi_probe();
+- *
+- **/
+-
+-static int detect_vendor_specific_device( struct usb_device *d, unsigned int ifnum, struct usb_midi_state *s )
+-{
+- struct usb_midi_device *u;
+- int i;
+- int ret = -ENXIO;
+-
+- for ( i=0; i<VENDOR_SPECIFIC_USB_MIDI_DEVICES ; i++ ) {
+- u=&(usb_midi_devices[i]);
+-
+- if ( le16_to_cpu(d->descriptor.idVendor) != u->idVendor ||
+- le16_to_cpu(d->descriptor.idProduct) != u->idProduct ||
+- ifnum != u->interface )
+- continue;
+-
+- ret = alloc_usb_midi_device( d, s, u );
+- break;
+- }
+-
+- return ret;
+-}
+-
+-
+-/** Attempt to match any config of an interface to a MIDISTREAMING interface.
+- * Returns 0 on success, negative on failure.
+- * Called by usb_midi_probe();
+- **/
+-static int detect_midi_subclass(struct usb_device *d,
+- struct usb_interface *iface, unsigned int ifnum,
+- struct usb_midi_state *s)
+-{
+- struct usb_host_interface *interface;
+- struct usb_midi_device *u;
+- unsigned char *buffer;
+- int bufSize;
+- int i;
+- int alts=-1;
+- int ret;
+-
+- for ( i=0 ; i < iface->num_altsetting; i++ ) {
+- interface = iface->altsetting + i;
+-
+- if ( interface->desc.bInterfaceClass != USB_CLASS_AUDIO ||
+- interface->desc.bInterfaceSubClass != USB_SUBCLASS_MIDISTREAMING )
+- continue;
+- alts = interface->desc.bAlternateSetting;
+- }
+- if ( alts == -1 ) {
+- return -EINVAL;
+- }
+-
+- printk(KERN_INFO "usb-midi: Found MIDISTREAMING on dev %04x:%04x, iface %d\n",
+- le16_to_cpu(d->descriptor.idVendor),
+- le16_to_cpu(d->descriptor.idProduct), ifnum);
+-
+-
+- /* From USB Spec v2.0, Section 9.5.
+- If the class or vendor specific descriptors use the same format
+- as standard descriptors (e.g., start with a length byte and
+- followed by a type byte), they must be returned interleaved with
+- standard descriptors in the configuration information returned by
+- a GetDescriptor(Configuration) request. In this case, the class
+- or vendor-specific descriptors must follow a related standard
+- descriptor they modify or extend.
+- */
+-
+- i = d->actconfig - d->config;
+- buffer = d->rawdescriptors[i];
+- bufSize = le16_to_cpu(d->actconfig->desc.wTotalLength);
+-
+- u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 0);
+- if ( u == NULL ) {
+- return -EINVAL;
+- }
+-
+- ret = alloc_usb_midi_device( d, s, u );
+-
+- kfree(u);
+-
+- return ret;
+-}
+-
+-
+-/** When user has requested a specific device, match it exactly.
+- *
+- * Uses uvendor, uproduct, uinterface, ualt, umin, umout and ucable.
+- * Called by usb_midi_probe();
+- *
+- **/
+-static int detect_by_hand(struct usb_device *d, unsigned int ifnum, struct usb_midi_state *s)
+-{
+- struct usb_midi_device u;
+-
+- if ( le16_to_cpu(d->descriptor.idVendor) != uvendor ||
+- le16_to_cpu(d->descriptor.idProduct) != uproduct ||
+- ifnum != uinterface ) {
+- return -EINVAL;
+- }
+-
+- if ( ualt < 0 )
+- ualt = -1;
+-
+- if ( umin < 0 || umin > 15 )
+- umin = 0x01 | USB_DIR_IN;
+- if ( umout < 0 || umout > 15 )
+- umout = 0x01;
+- if ( ucable < 0 || ucable > 15 )
+- ucable = 0;
+-
+- u.deviceName = NULL; /* A flag for alloc_usb_midi_device to get device
+- name from device. */
+- u.idVendor = uvendor;
+- u.idProduct = uproduct;
+- u.interface = uinterface;
+- u.altSetting = ualt;
+-
+- u.in[0].endpoint = umin;
+- u.in[0].cableId = (1<<ucable);
+-
+- u.out[0].endpoint = umout;
+- u.out[0].cableId = (1<<ucable);
+-
+- return alloc_usb_midi_device( d, s, &u );
+-}
+-
+-
+-
+-/* ------------------------------------------------------------------------- */
+-
+-static int usb_midi_probe(struct usb_interface *intf,
+- const struct usb_device_id *id)
+-{
+- struct usb_midi_state *s;
+- struct usb_device *dev = interface_to_usbdev(intf);
+- int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+-
+- s = (struct usb_midi_state *)kmalloc(sizeof(struct usb_midi_state), GFP_KERNEL);
+- if ( !s )
+- return -ENOMEM;
+-
+- memset( s, 0, sizeof(struct usb_midi_state) );
+- INIT_LIST_HEAD(&s->midiDevList);
+- INIT_LIST_HEAD(&s->inEndpointList);
+- INIT_LIST_HEAD(&s->outEndpointList);
+- s->usbdev = dev;
+- s->count = 0;
+- spin_lock_init(&s->lock);
+-
+- if (
+- detect_by_hand( dev, ifnum, s ) &&
+- detect_midi_subclass( dev, intf, ifnum, s ) &&
+- detect_vendor_specific_device( dev, ifnum, s ) &&
+- detect_yamaha_device( dev, intf, ifnum, s) ) {
+- kfree(s);
+- return -EIO;
+- }
+-
+- down(&open_sem);
+- list_add_tail(&s->mididev, &mididevs);
+- up(&open_sem);
+-
+- usb_set_intfdata (intf, s);
+- return 0;
+-}
+-
+-
+-static void usb_midi_disconnect(struct usb_interface *intf)
+-{
+- struct usb_midi_state *s = usb_get_intfdata (intf);
+- struct usb_mididev *m;
+-
+- if ( !s )
+- return;
+-
+- if ( s == (struct usb_midi_state *)-1 ) {
+- return;
+- }
+- if ( !s->usbdev ) {
+- return;
+- }
+- down(&open_sem);
+- list_del(&s->mididev);
+- INIT_LIST_HEAD(&s->mididev);
+- s->usbdev = NULL;
+- usb_set_intfdata (intf, NULL);
+-
+- list_for_each_entry(m, &s->midiDevList, list) {
+- wake_up(&(m->min.ep->wait));
+- wake_up(&(m->mout.ep->wait));
+- if ( m->dev_midi >= 0 ) {
+- unregister_sound_midi(m->dev_midi);
+- }
+- m->dev_midi = -1;
+- }
+- release_midi_device(s);
+- wake_up(&open_wait);
+-}
+-
+-/* we want to look at all devices by hand */
+-static struct usb_device_id id_table[] = {
+- {.driver_info = 42},
+- {}
+-};
+-
+-static struct usb_driver usb_midi_driver = {
+- .name = "midi",
+- .probe = usb_midi_probe,
+- .disconnect = usb_midi_disconnect,
+- .id_table = id_table,
+-};
+-
+-/* ------------------------------------------------------------------------- */
+-
+-static int __init usb_midi_init(void)
+-{
+- return usb_register(&usb_midi_driver);
+-}
+-
+-static void __exit usb_midi_exit(void)
+-{
+- usb_deregister(&usb_midi_driver);
+-}
+-
+-module_init(usb_midi_init) ;
+-module_exit(usb_midi_exit) ;
+-
+-#ifdef HAVE_ALSA_SUPPORT
+-#define SNDRV_MAIN_OBJECT_FILE
+-#include "../../include/driver.h"
+-#include "../../include/control.h"
+-#include "../../include/info.h"
+-#include "../../include/cs46xx.h"
+-
+-/* ------------------------------------------------------------------------- */
+-
+-static int snd_usbmidi_input_close(snd_rawmidi_substream_t * substream)
+-{
+- return 0;
+-}
+-
+-static int snd_usbmidi_input_open(snd_rawmidi_substream_t * substream )
+-{
+- return 0;
+-}
+-
+-static void snd_usbmidi_input_trigger(snd_rawmidi_substream_t * substream, int up)
+-{
+- return 0;
+-}
+-
+-
+-/* ------------------------------------------------------------------------- */
+-
+-static int snd_usbmidi_output_close(snd_rawmidi_substream_t * substream)
+-{
+- return 0;
+-}
+-
+-static int snd_usbmidi_output_open(snd_rawmidi_substream_t * substream)
+-{
+- return 0;
+-}
+-
+-static void snd_usb_midi_output_trigger(snd_rawmidi_substream_t * substream,
+- int up)
+-{
+- return 0;
+-}
+-
+-/* ------------------------------------------------------------------------- */
+-
+-static snd_rawmidi_ops_t snd_usbmidi_output =
+-{
+- .open = snd_usbmidi_output_open,
+- .close = snd_usbmidi_output_close,
+- .trigger = snd_usbmidi_output_trigger,
+-};
+-static snd_rawmidi_ops_t snd_usbmidi_input =
+-{
+- .open = snd_usbmidi_input_open,
+- .close = snd_usbmidi_input_close,
+- .trigger = snd_usbmidi_input_trigger,
+-};
+-
+-int snd_usbmidi_midi(cs46xx_t *chip, int device, snd_rawmidi_t **rrawmidi)
+-{
+- snd_rawmidi_t *rmidi;
+- int err;
+-
+- if (rrawmidi)
+- *rrawmidi = NULL;
+- if ((err = snd_rawmidi_new(chip->card, "USB-MIDI", device, 1, 1, &rmidi)) < 0)
+- return err;
+- strcpy(rmidi->name, "USB-MIDI");
+-
+- snd_rawmidi_set_ops( rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_usbmidi_output );
+- snd_rawmidi_set_ops( rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_usbmidi_input );
+-
+- rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
+-
+- rmidi->private_data = chip;
+- chip->rmidi = rmidi;
+- if (rrawmidi)
+- *rrawmidi = NULL;
+-
+- return 0;
+-}
+-
+-int snd_usbmidi_create( snd_card_t * card,
+- struct pci_dev * pci,
+- usbmidi_t ** rchip )
+-{
+- usbmidi_t *chip;
+- int err, idx;
+- snd_region_t *region;
+- static snd_device_opt_t ops = {
+- .dev_free = snd_usbmidi_dev_free,
+- };
+-
+- *rchip = NULL;
+- chip = snd_magic_kcalloc( usbmidi_t, 0, GFP_KERNEL );
+- if ( chip == NULL )
+- return -ENOMEM;
+-}
+-
+-EXPORT_SYMBOL(snd_usbmidi_create);
+-EXPORT_SYMBOL(snd_usbmidi_midi);
+-#endif /* HAVE_ALSA_SUPPORT */
+-
+--- gregkh-2.6.orig/drivers/usb/class/usb-midi.h
++++ /dev/null
+@@ -1,164 +0,0 @@
+-/*
+- usb-midi.h -- USB-MIDI driver
+-
+- Copyright (C) 2001
+- NAGANO Daisuke <breeze.nagano@nifty.ne.jp>
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 2, or (at your option)
+- any later version.
+-
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- GNU General Public License for more details.
+-
+- You should have received a copy of the GNU General Public License
+- along with this program; if not, write to the Free Software
+- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-/* ------------------------------------------------------------------------- */
+-
+-#ifndef _USB_MIDI_H_
+-#define _USB_MIDI_H_
+-
+-#ifndef USB_SUBCLASS_MIDISTREAMING
+-#define USB_SUBCLASS_MIDISTREAMING 3
+-#endif
+-
+-/* ------------------------------------------------------------------------- */
+-/* Roland MIDI Devices */
+-
+-#define USB_VENDOR_ID_ROLAND 0x0582
+-#define USBMIDI_ROLAND_UA100G 0x0000
+-#define USBMIDI_ROLAND_MPU64 0x0002
+-#define USBMIDI_ROLAND_SC8850 0x0003
+-#define USBMIDI_ROLAND_SC8820 0x0007
+-#define USBMIDI_ROLAND_UM2 0x0005
+-#define USBMIDI_ROLAND_UM1 0x0009
+-#define USBMIDI_ROLAND_PC300 0x0008
+-
+-/* YAMAHA MIDI Devices */
+-#define USB_VENDOR_ID_YAMAHA 0x0499
+-#define USBMIDI_YAMAHA_MU1000 0x1001
+-
+-/* Steinberg MIDI Devices */
+-#define USB_VENDOR_ID_STEINBERG 0x0763
+-#define USBMIDI_STEINBERG_USB2MIDI 0x1001
+-
+-/* Mark of the Unicorn MIDI Devices */
+-#define USB_VENDOR_ID_MOTU 0x07fd
+-#define USBMIDI_MOTU_FASTLANE 0x0001
+-
+-/* ------------------------------------------------------------------------- */
+-/* Supported devices */
+-
+-struct usb_midi_endpoint {
+- int endpoint;
+- int cableId; /* if bit-n == 1 then cableId-n is enabled (n: 0 - 15) */
+-};
+-
+-struct usb_midi_device {
+- char *deviceName;
+-
+- u16 idVendor;
+- u16 idProduct;
+- int interface;
+- int altSetting; /* -1: auto detect */
+-
+- struct usb_midi_endpoint in[15];
+- struct usb_midi_endpoint out[15];
+-};
+-
+-static struct usb_midi_device usb_midi_devices[] = {
+- { /* Roland UM-1 */
+- "Roland UM-1",
+- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UM1, 2, -1,
+- { { 0x81, 1 }, {-1, -1} },
+- { { 0x01, 1,}, {-1, -1} },
+- },
+-
+- { /* Roland UM-2 */
+- "Roland UM-2" ,
+- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UM2, 2, -1,
+- { { 0x81, 3 }, {-1, -1} },
+- { { 0x01, 3,}, {-1, -1} },
+- },
+-
+-/** Next entry courtesy research by Michael Minn <michael@michaelminn.com> **/
+- { /* Roland UA-100 */
+- "Roland UA-100",
+- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UA100G, 2, -1,
+- { { 0x82, 7 }, {-1, -1} }, /** cables 0,1 and 2 for SYSEX **/
+- { { 0x02, 7 }, {-1, -1} },
+- },
+-
+-/** Next entry courtesy research by Michael Minn <michael@michaelminn.com> **/
+- { /* Roland SC8850 */
+- "Roland SC8850",
+- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8850, 2, -1,
+- { { 0x81, 0x3f }, {-1, -1} },
+- { { 0x01, 0x3f }, {-1, -1} },
+- },
+-
+- { /* Roland SC8820 */
+- "Roland SC8820",
+- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820, 2, -1,
+- { { 0x81, 0x13 }, {-1, -1} },
+- { { 0x01, 0x13 }, {-1, -1} },
+- },
+-
+- { /* Roland SC8820 */
+- "Roland SC8820",
+- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820, 2, -1,
+- { { 0x81, 17 }, {-1, -1} },
+- { { 0x01, 17 }, {-1, -1} },
+- },
+-
+- { /* YAMAHA MU1000 */
+- "YAMAHA MU1000",
+- USB_VENDOR_ID_YAMAHA, USBMIDI_YAMAHA_MU1000, 0, -1,
+- { { 0x81, 1 }, {-1, -1} },
+- { { 0x01, 15 }, {-1, -1} },
+- },
+- { /* Roland PC-300 */
+- "Roland PC-300",
+- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_PC300, 2, -1,
+- { { 0x81, 1 }, {-1, -1} },
+- { { 0x01, 1 }, {-1, -1} },
+- },
+- { /* MOTU Fastlane USB */
+- "MOTU Fastlane USB",
+- USB_VENDOR_ID_MOTU, USBMIDI_MOTU_FASTLANE, 1, 0,
+- { { 0x82, 3 }, {-1, -1} },
+- { { 0x02, 3 }, {-1, -1} },
+- }
+-};
+-
+-#define VENDOR_SPECIFIC_USB_MIDI_DEVICES (sizeof(usb_midi_devices)/sizeof(struct usb_midi_device))
+-
+-/* for Hot-Plugging */
+-
+-static struct usb_device_id usb_midi_ids [] = {
+- { .match_flags = (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS),
+- .bInterfaceClass = USB_CLASS_AUDIO, .bInterfaceSubClass = USB_SUBCLASS_MIDISTREAMING},
+- { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UM1 ) },
+- { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UM2 ) },
+- { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UA100G ) },
+- { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_PC300 ) },
+- { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8850 ) },
+- { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820 ) },
+- { USB_DEVICE( USB_VENDOR_ID_YAMAHA, USBMIDI_YAMAHA_MU1000 ) },
+- { USB_DEVICE( USB_VENDOR_ID_MOTU, USBMIDI_MOTU_FASTLANE ) },
+-/* { USB_DEVICE( USB_VENDOR_ID_STEINBERG, USBMIDI_STEINBERG_USB2MIDI ) },*/
+- { } /* Terminating entry */
+-};
+-
+-MODULE_DEVICE_TABLE (usb, usb_midi_ids);
+-
+-/* ------------------------------------------------------------------------- */
+-#endif /* _USB_MIDI_H_ */
+-
+-
diff --git a/usb/usb-remove-usbcore-specific-wakeup-flags.patch b/usb/usb-remove-usbcore-specific-wakeup-flags.patch
index f3894b9574710..a4595fdb4fbdc 100644
--- a/usb/usb-remove-usbcore-specific-wakeup-flags.patch
+++ b/usb/usb-remove-usbcore-specific-wakeup-flags.patch
@@ -20,17 +20,31 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/core/hub.c | 22 ++++++++++++++--------
4 files changed, 48 insertions(+), 27 deletions(-)
---- gregkh-2.6.orig/drivers/usb/core/hcd.h
-+++ gregkh-2.6/drivers/usb/core/hcd.h
-@@ -78,8 +78,6 @@ struct usb_hcd { /* usb_bus.hcpriv point
- #define HCD_FLAG_HW_ACCESSIBLE 0x00000001
- #define HCD_FLAG_SAW_IRQ 0x00000002
-
-- unsigned can_wakeup:1; /* hw supports wakeup? */
-- unsigned remote_wakeup:1;/* sw should use wakeup? */
- unsigned rh_registered:1;/* is root hub registered? */
+--- gregkh-2.6.orig/drivers/usb/core/hcd-pci.c
++++ gregkh-2.6/drivers/usb/core/hcd-pci.c
+@@ -264,14 +264,19 @@ int usb_hcd_pci_suspend (struct pci_dev
+ */
+ retval = pci_set_power_state (dev, PCI_D3hot);
+ if (retval == 0) {
+- dev_dbg (hcd->self.controller, "--> PCI D3\n");
++ int wake = device_can_wakeup(&hcd->self.root_hub->dev);
++
++ wake = wake && device_may_wakeup(hcd->self.controller);
++
++ dev_dbg (hcd->self.controller, "--> PCI D3%s\n",
++ wake ? "/wakeup" : "");
- /* The next flag is a stopgap, to be removed when all the HCDs
+ /* Ignore these return values. We rely on pci code to
+ * reject requests the hardware can't implement, rather
+ * than coding the same thing.
+ */
+- (void) pci_enable_wake (dev, PCI_D3hot, hcd->remote_wakeup);
+- (void) pci_enable_wake (dev, PCI_D3cold, hcd->remote_wakeup);
++ (void) pci_enable_wake (dev, PCI_D3hot, wake);
++ (void) pci_enable_wake (dev, PCI_D3cold, wake);
+ } else {
+ dev_dbg (&dev->dev, "PCI D3 suspend fail, %d\n",
+ retval);
--- gregkh-2.6.orig/drivers/usb/core/hcd.c
+++ gregkh-2.6/drivers/usb/core/hcd.c
@@ -367,21 +367,39 @@ static int rh_call_control (struct usb_h
@@ -106,31 +120,17 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
/* enable irqs just before we start the controller */
if (hcd->driver->irq) {
---- gregkh-2.6.orig/drivers/usb/core/hcd-pci.c
-+++ gregkh-2.6/drivers/usb/core/hcd-pci.c
-@@ -264,14 +264,19 @@ int usb_hcd_pci_suspend (struct pci_dev
- */
- retval = pci_set_power_state (dev, PCI_D3hot);
- if (retval == 0) {
-- dev_dbg (hcd->self.controller, "--> PCI D3\n");
-+ int wake = device_can_wakeup(&hcd->self.root_hub->dev);
-+
-+ wake = wake && device_may_wakeup(hcd->self.controller);
-+
-+ dev_dbg (hcd->self.controller, "--> PCI D3%s\n",
-+ wake ? "/wakeup" : "");
+--- gregkh-2.6.orig/drivers/usb/core/hcd.h
++++ gregkh-2.6/drivers/usb/core/hcd.h
+@@ -78,8 +78,6 @@ struct usb_hcd { /* usb_bus.hcpriv point
+ #define HCD_FLAG_HW_ACCESSIBLE 0x00000001
+ #define HCD_FLAG_SAW_IRQ 0x00000002
- /* Ignore these return values. We rely on pci code to
- * reject requests the hardware can't implement, rather
- * than coding the same thing.
- */
-- (void) pci_enable_wake (dev, PCI_D3hot, hcd->remote_wakeup);
-- (void) pci_enable_wake (dev, PCI_D3cold, hcd->remote_wakeup);
-+ (void) pci_enable_wake (dev, PCI_D3hot, wake);
-+ (void) pci_enable_wake (dev, PCI_D3cold, wake);
- } else {
- dev_dbg (&dev->dev, "PCI D3 suspend fail, %d\n",
- retval);
+- unsigned can_wakeup:1; /* hw supports wakeup? */
+- unsigned remote_wakeup:1;/* sw should use wakeup? */
+ unsigned rh_registered:1;/* is root hub registered? */
+
+ /* The next flag is a stopgap, to be removed when all the HCDs
--- gregkh-2.6.orig/drivers/usb/core/hub.c
+++ gregkh-2.6/drivers/usb/core/hub.c
@@ -1006,12 +1006,18 @@ void usb_set_device_state(struct usb_dev
diff --git a/usb/usb-serial-dynamic-id.patch b/usb/usb-serial-dynamic-id.patch
index 423f4924a27d8..aab7780a1ae00 100644
--- a/usb/usb-serial-dynamic-id.patch
+++ b/usb/usb-serial-dynamic-id.patch
@@ -113,65 +113,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
/**
* usb_match_id - find first usb_device_id matching device or interface
* @interface: the interface of interest
---- gregkh-2.6.orig/include/linux/usb.h
-+++ gregkh-2.6/include/linux/usb.h
-@@ -417,6 +417,8 @@ extern void usb_driver_release_interface
- struct usb_interface *iface);
- const struct usb_device_id *usb_match_id(struct usb_interface *interface,
- const struct usb_device_id *id);
-+extern int usb_match_one_id(struct usb_interface *interface,
-+ const struct usb_device_id *id);
-
- extern struct usb_interface *usb_find_interface(struct usb_driver *drv,
- int minor);
-@@ -531,11 +533,21 @@ static inline int usb_make_path (struct
-
- /* ----------------------------------------------------------------------- */
-
-+/* Stuff for dynamic usb ids */
- struct usb_dynids {
- spinlock_t lock;
- struct list_head list;
- };
-
-+struct usb_dynid {
-+ struct list_head node;
-+ struct usb_device_id id;
-+};
-+
-+extern ssize_t usb_store_new_id(struct usb_dynids *dynids,
-+ struct device_driver *driver,
-+ const char *buf, size_t count);
-+
- /**
- * struct usb_driver - identifies USB driver to usbcore
- * @name: The driver name should be unique among USB drivers,
-@@ -1190,6 +1202,7 @@ usb_maxpacket(struct usb_device *udev, i
- extern void usb_register_notify(struct notifier_block *nb);
- extern void usb_unregister_notify(struct notifier_block *nb);
-
-+
- #ifdef DEBUG
- #define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , \
- __FILE__ , ## arg)
---- gregkh-2.6.orig/drivers/usb/serial/usb-serial.h
-+++ gregkh-2.6/drivers/usb/serial/usb-serial.h
-@@ -203,6 +203,7 @@ struct usb_serial_driver {
-
- struct list_head driver_list;
- struct device_driver driver;
-+ struct usb_dynids dynids;
-
- int (*probe) (struct usb_serial *serial, const struct usb_device_id *id);
- int (*attach) (struct usb_serial *serial);
-@@ -270,6 +271,7 @@ extern int usb_serial_bus_register (stru
- extern void usb_serial_bus_deregister (struct usb_serial_driver *device);
-
- extern struct usb_serial_driver usb_serial_generic_device;
-+extern struct usb_driver usb_serial_driver;
- extern struct bus_type usb_serial_bus_type;
- extern struct tty_driver *usb_serial_tty_driver;
-
--- gregkh-2.6.orig/drivers/usb/serial/bus.c
+++ gregkh-2.6/drivers/usb/serial/bus.c
@@ -104,11 +104,57 @@ exit:
@@ -250,6 +191,19 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
driver_unregister(&driver->driver);
}
+--- gregkh-2.6.orig/drivers/usb/serial/pl2303.c
++++ gregkh-2.6/drivers/usb/serial/pl2303.c
+@@ -56,8 +56,8 @@ static struct usb_device_id id_table []
+ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) },
+ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) },
+ { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
+- { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
+- { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) },
++// { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
++// { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) },
+ { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) },
+ { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) },
+ { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) },
--- gregkh-2.6.orig/drivers/usb/serial/usb-serial.c
+++ gregkh-2.6/drivers/usb/serial/usb-serial.c
@@ -42,7 +42,7 @@
@@ -324,16 +278,62 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
retval = type->probe(serial, id);
module_put(type->driver.owner);
---- gregkh-2.6.orig/drivers/usb/serial/pl2303.c
-+++ gregkh-2.6/drivers/usb/serial/pl2303.c
-@@ -56,8 +56,8 @@ static struct usb_device_id id_table []
- { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) },
- { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) },
- { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
-- { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
-- { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) },
-+// { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
-+// { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) },
- { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) },
- { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) },
- { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) },
+--- gregkh-2.6.orig/drivers/usb/serial/usb-serial.h
++++ gregkh-2.6/drivers/usb/serial/usb-serial.h
+@@ -203,6 +203,7 @@ struct usb_serial_driver {
+
+ struct list_head driver_list;
+ struct device_driver driver;
++ struct usb_dynids dynids;
+
+ int (*probe) (struct usb_serial *serial, const struct usb_device_id *id);
+ int (*attach) (struct usb_serial *serial);
+@@ -270,6 +271,7 @@ extern int usb_serial_bus_register (stru
+ extern void usb_serial_bus_deregister (struct usb_serial_driver *device);
+
+ extern struct usb_serial_driver usb_serial_generic_device;
++extern struct usb_driver usb_serial_driver;
+ extern struct bus_type usb_serial_bus_type;
+ extern struct tty_driver *usb_serial_tty_driver;
+
+--- gregkh-2.6.orig/include/linux/usb.h
++++ gregkh-2.6/include/linux/usb.h
+@@ -417,6 +417,8 @@ extern void usb_driver_release_interface
+ struct usb_interface *iface);
+ const struct usb_device_id *usb_match_id(struct usb_interface *interface,
+ const struct usb_device_id *id);
++extern int usb_match_one_id(struct usb_interface *interface,
++ const struct usb_device_id *id);
+
+ extern struct usb_interface *usb_find_interface(struct usb_driver *drv,
+ int minor);
+@@ -531,11 +533,21 @@ static inline int usb_make_path (struct
+
+ /* ----------------------------------------------------------------------- */
+
++/* Stuff for dynamic usb ids */
+ struct usb_dynids {
+ spinlock_t lock;
+ struct list_head list;
+ };
+
++struct usb_dynid {
++ struct list_head node;
++ struct usb_device_id id;
++};
++
++extern ssize_t usb_store_new_id(struct usb_dynids *dynids,
++ struct device_driver *driver,
++ const char *buf, size_t count);
++
+ /**
+ * struct usb_driver - identifies USB driver to usbcore
+ * @name: The driver name should be unique among USB drivers,
+@@ -1190,6 +1202,7 @@ usb_maxpacket(struct usb_device *udev, i
+ extern void usb_register_notify(struct notifier_block *nb);
+ extern void usb_unregister_notify(struct notifier_block *nb);
+
++
+ #ifdef DEBUG
+ #define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , \
+ __FILE__ , ## arg)
diff --git a/usb/usb-sn9c10x-driver-updates.patch b/usb/usb-sn9c10x-driver-updates.patch
index be6f03ab95963..d90c465bf5847 100644
--- a/usb/usb-sn9c10x-driver-updates.patch
+++ b/usb/usb-sn9c10x-driver-updates.patch
@@ -92,6 +92,77 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o
zc0301-objs := zc0301_core.o zc0301_pas202bcb.o
+--- gregkh-2.6.orig/drivers/usb/media/sn9c102.h
++++ gregkh-2.6/drivers/usb/media/sn9c102.h
+@@ -34,7 +34,8 @@
+ #include <linux/param.h>
+ #include <linux/rwsem.h>
+ #include <linux/mutex.h>
+-#include <asm/semaphore.h>
++#include <linux/string.h>
++#include <linux/stddef.h>
+
+ #include "sn9c102_sensor.h"
+
+@@ -51,6 +52,7 @@
+ #define SN9C102_ALTERNATE_SETTING 8
+ #define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS)
+ #define SN9C102_CTRL_TIMEOUT 300
++#define SN9C102_FRAME_TIMEOUT 2
+
+ /*****************************************************************************/
+
+@@ -108,6 +110,7 @@ struct sn9c102_sysfs_attr {
+
+ struct sn9c102_module_param {
+ u8 force_munmap;
++ u16 frame_timeout;
+ };
+
+ static DEFINE_MUTEX(sn9c102_sysfs_lock);
+@@ -117,7 +120,7 @@ struct sn9c102_device {
+ struct video_device* v4ldev;
+
+ enum sn9c102_bridge bridge;
+- struct sn9c102_sensor* sensor;
++ struct sn9c102_sensor sensor;
+
+ struct usb_device* usbdev;
+ struct urb* urb[SN9C102_URBS];
+@@ -149,12 +152,21 @@ struct sn9c102_device {
+
+ /*****************************************************************************/
+
++struct sn9c102_device*
++sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id)
++{
++ if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id))
++ return cam;
++
++ return NULL;
++}
++
++
+ void
+ sn9c102_attach_sensor(struct sn9c102_device* cam,
+ struct sn9c102_sensor* sensor)
+ {
+- cam->sensor = sensor;
+- cam->sensor->usbdev = cam->usbdev;
++ memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor));
+ }
+
+ /*****************************************************************************/
+@@ -197,7 +209,8 @@ do {
+
+ #undef PDBG
+ #define PDBG(fmt, args...) \
+-dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args)
++dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
++ __FUNCTION__, __LINE__ , ## args)
+
+ #undef PDBGG
+ #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
--- gregkh-2.6.orig/drivers/usb/media/sn9c102_core.c
+++ gregkh-2.6/drivers/usb/media/sn9c102_core.c
@@ -25,11 +25,9 @@
@@ -554,77 +625,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
} else {
cam->state |= DEV_DISCONNECTED;
sn9c102_release_resources(cam);
---- gregkh-2.6.orig/drivers/usb/media/sn9c102.h
-+++ gregkh-2.6/drivers/usb/media/sn9c102.h
-@@ -34,7 +34,8 @@
- #include <linux/param.h>
- #include <linux/rwsem.h>
- #include <linux/mutex.h>
--#include <asm/semaphore.h>
-+#include <linux/string.h>
-+#include <linux/stddef.h>
-
- #include "sn9c102_sensor.h"
-
-@@ -51,6 +52,7 @@
- #define SN9C102_ALTERNATE_SETTING 8
- #define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS)
- #define SN9C102_CTRL_TIMEOUT 300
-+#define SN9C102_FRAME_TIMEOUT 2
-
- /*****************************************************************************/
-
-@@ -108,6 +110,7 @@ struct sn9c102_sysfs_attr {
-
- struct sn9c102_module_param {
- u8 force_munmap;
-+ u16 frame_timeout;
- };
-
- static DEFINE_MUTEX(sn9c102_sysfs_lock);
-@@ -117,7 +120,7 @@ struct sn9c102_device {
- struct video_device* v4ldev;
-
- enum sn9c102_bridge bridge;
-- struct sn9c102_sensor* sensor;
-+ struct sn9c102_sensor sensor;
-
- struct usb_device* usbdev;
- struct urb* urb[SN9C102_URBS];
-@@ -149,12 +152,21 @@ struct sn9c102_device {
-
- /*****************************************************************************/
-
-+struct sn9c102_device*
-+sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id)
-+{
-+ if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id))
-+ return cam;
-+
-+ return NULL;
-+}
-+
-+
- void
- sn9c102_attach_sensor(struct sn9c102_device* cam,
- struct sn9c102_sensor* sensor)
- {
-- cam->sensor = sensor;
-- cam->sensor->usbdev = cam->usbdev;
-+ memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor));
- }
-
- /*****************************************************************************/
-@@ -197,7 +209,8 @@ do {
-
- #undef PDBG
- #define PDBG(fmt, args...) \
--dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args)
-+dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
-+ __FUNCTION__, __LINE__ , ## args)
-
- #undef PDBGG
- #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
--- gregkh-2.6.orig/drivers/usb/media/sn9c102_ov7630.c
+++ gregkh-2.6/drivers/usb/media/sn9c102_ov7630.c
@@ -34,8 +34,8 @@ static int ov7630_init(struct sn9c102_de
diff --git a/usb/usb-zc0301-driver-updates-2.patch b/usb/usb-zc0301-driver-updates-2.patch
index 8ae04c03d3cd0..f64108145e65a 100644
--- a/usb/usb-zc0301-driver-updates-2.patch
+++ b/usb/usb-zc0301-driver-updates-2.patch
@@ -91,6 +91,66 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+- The initialization values of the ZC0301 controller connected to the PAS202BCB
image sensor have been taken from the SPCA5XX driver maintained by
Michel Xhaard <mxhaard@magic.fr>.
+--- gregkh-2.6.orig/drivers/usb/media/zc0301.h
++++ gregkh-2.6/drivers/usb/media/zc0301.h
+@@ -34,7 +34,8 @@
+ #include <linux/param.h>
+ #include <linux/mutex.h>
+ #include <linux/rwsem.h>
+-#include <asm/semaphore.h>
++#include <linux/stddef.h>
++#include <linux/string.h>
+
+ #include "zc0301_sensor.h"
+
+@@ -51,7 +52,7 @@
+ #define ZC0301_ALTERNATE_SETTING 7
+ #define ZC0301_URB_TIMEOUT msecs_to_jiffies(2 * ZC0301_ISO_PACKETS)
+ #define ZC0301_CTRL_TIMEOUT 100
+-#define ZC0301_FRAME_TIMEOUT 2 * 1000 * msecs_to_jiffies(1)
++#define ZC0301_FRAME_TIMEOUT 2
+
+ /*****************************************************************************/
+
+@@ -94,6 +95,7 @@ enum zc0301_stream_state {
+
+ struct zc0301_module_param {
+ u8 force_munmap;
++ u16 frame_timeout;
+ };
+
+ static DECLARE_RWSEM(zc0301_disconnect);
+@@ -101,7 +103,7 @@ static DECLARE_RWSEM(zc0301_disconnect);
+ struct zc0301_device {
+ struct video_device* v4ldev;
+
+- struct zc0301_sensor* sensor;
++ struct zc0301_sensor sensor;
+
+ struct usb_device* usbdev;
+ struct urb* urb[ZC0301_URBS];
+@@ -129,11 +131,19 @@ struct zc0301_device {
+
+ /*****************************************************************************/
+
++struct zc0301_device*
++zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id)
++{
++ if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id))
++ return cam;
++
++ return NULL;
++}
++
+ void
+ zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor)
+ {
+- cam->sensor = sensor;
+- cam->sensor->usbdev = cam->usbdev;
++ memcpy(&cam->sensor, sensor, sizeof(struct zc0301_sensor));
+ }
+
+ /*****************************************************************************/
--- gregkh-2.6.orig/drivers/usb/media/zc0301_core.c
+++ gregkh-2.6/drivers/usb/media/zc0301_core.c
@@ -29,11 +29,9 @@
@@ -301,66 +361,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
} else {
cam->state |= DEV_DISCONNECTED;
zc0301_release_resources(cam);
---- gregkh-2.6.orig/drivers/usb/media/zc0301.h
-+++ gregkh-2.6/drivers/usb/media/zc0301.h
-@@ -34,7 +34,8 @@
- #include <linux/param.h>
- #include <linux/mutex.h>
- #include <linux/rwsem.h>
--#include <asm/semaphore.h>
-+#include <linux/stddef.h>
-+#include <linux/string.h>
-
- #include "zc0301_sensor.h"
-
-@@ -51,7 +52,7 @@
- #define ZC0301_ALTERNATE_SETTING 7
- #define ZC0301_URB_TIMEOUT msecs_to_jiffies(2 * ZC0301_ISO_PACKETS)
- #define ZC0301_CTRL_TIMEOUT 100
--#define ZC0301_FRAME_TIMEOUT 2 * 1000 * msecs_to_jiffies(1)
-+#define ZC0301_FRAME_TIMEOUT 2
-
- /*****************************************************************************/
-
-@@ -94,6 +95,7 @@ enum zc0301_stream_state {
-
- struct zc0301_module_param {
- u8 force_munmap;
-+ u16 frame_timeout;
- };
-
- static DECLARE_RWSEM(zc0301_disconnect);
-@@ -101,7 +103,7 @@ static DECLARE_RWSEM(zc0301_disconnect);
- struct zc0301_device {
- struct video_device* v4ldev;
-
-- struct zc0301_sensor* sensor;
-+ struct zc0301_sensor sensor;
-
- struct usb_device* usbdev;
- struct urb* urb[ZC0301_URBS];
-@@ -129,11 +131,19 @@ struct zc0301_device {
-
- /*****************************************************************************/
-
-+struct zc0301_device*
-+zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id)
-+{
-+ if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id))
-+ return cam;
-+
-+ return NULL;
-+}
-+
- void
- zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor)
- {
-- cam->sensor = sensor;
-- cam->sensor->usbdev = cam->usbdev;
-+ memcpy(&cam->sensor, sensor, sizeof(struct zc0301_sensor));
- }
-
- /*****************************************************************************/
--- gregkh-2.6.orig/drivers/usb/media/zc0301_pas202bcb.c
+++ gregkh-2.6/drivers/usb/media/zc0301_pas202bcb.c
@@ -22,6 +22,14 @@
diff --git a/usb/usb-zc0301-driver-updates.patch b/usb/usb-zc0301-driver-updates.patch
index 0f108dc9d137c..7450846719b59 100644
--- a/usb/usb-zc0301-driver-updates.patch
+++ b/usb/usb-zc0301-driver-updates.patch
@@ -67,6 +67,17 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+- Initialization values of the ZC0301 controller connected to the PAS202BCB
+ image sensor have been taken from the SPCA5XX driver maintained by
+ Michel Xhaard <mxhaard@magic.fr>.
+--- gregkh-2.6.orig/drivers/usb/media/zc0301.h
++++ gregkh-2.6/drivers/usb/media/zc0301.h
+@@ -45,7 +45,7 @@
+ #define ZC0301_MAX_DEVICES 64
+ #define ZC0301_FORCE_MUNMAP 0
+ #define ZC0301_MAX_FRAMES 32
+-#define ZC0301_COMPRESSION_QUALITY 2
++#define ZC0301_COMPRESSION_QUALITY 0
+ #define ZC0301_URBS 2
+ #define ZC0301_ISO_PACKETS 7
+ #define ZC0301_ALTERNATE_SETTING 7
--- gregkh-2.6.orig/drivers/usb/media/zc0301_core.c
+++ gregkh-2.6/drivers/usb/media/zc0301_core.c
@@ -3,9 +3,9 @@
@@ -190,17 +201,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
} else {
cam->state |= DEV_DISCONNECTED;
zc0301_release_resources(cam);
---- gregkh-2.6.orig/drivers/usb/media/zc0301.h
-+++ gregkh-2.6/drivers/usb/media/zc0301.h
-@@ -45,7 +45,7 @@
- #define ZC0301_MAX_DEVICES 64
- #define ZC0301_FORCE_MUNMAP 0
- #define ZC0301_MAX_FRAMES 32
--#define ZC0301_COMPRESSION_QUALITY 2
-+#define ZC0301_COMPRESSION_QUALITY 0
- #define ZC0301_URBS 2
- #define ZC0301_ISO_PACKETS 7
- #define ZC0301_ALTERNATE_SETTING 7
--- gregkh-2.6.orig/drivers/usb/media/zc0301_pas202bcb.c
+++ gregkh-2.6/drivers/usb/media/zc0301_pas202bcb.c
@@ -318,7 +318,7 @@ static struct zc0301_sensor pas202bcb =
diff --git a/usb/usbip.patch b/usb/usbip.patch
index 51f68ea0b984c..249b7d126900a 100644
--- a/usb/usbip.patch
+++ b/usb/usbip.patch
@@ -38,6 +38,17 @@ a link to the userspace tools needed to get this to work.
source "drivers/usb/class/Kconfig"
source "drivers/usb/storage/Kconfig"
+--- gregkh-2.6.orig/drivers/usb/Makefile
++++ gregkh-2.6/drivers/usb/Makefile
+@@ -17,6 +17,8 @@ obj-$(CONFIG_USB_SL811_HCD) += host/
+ obj-$(CONFIG_ETRAX_USB_HOST) += host/
+ obj-$(CONFIG_USB_OHCI_AT91) += host/
+
++obj-$(CONFIG_USB_IP) += ip/
++
+ obj-$(CONFIG_USB_ACM) += class/
+ obj-$(CONFIG_USB_PRINTER) += class/
+
--- /dev/null
+++ gregkh-2.6/drivers/usb/ip/Kconfig
@@ -0,0 +1,32 @@
@@ -73,17 +84,6 @@ a link to the userspace tools needed to get this to work.
+ To compile this driver as a module, choose M here: the
+ module will be called stub.
+
---- gregkh-2.6.orig/drivers/usb/Makefile
-+++ gregkh-2.6/drivers/usb/Makefile
-@@ -17,6 +17,8 @@ obj-$(CONFIG_USB_SL811_HCD) += host/
- obj-$(CONFIG_ETRAX_USB_HOST) += host/
- obj-$(CONFIG_USB_OHCI_AT91) += host/
-
-+obj-$(CONFIG_USB_IP) += ip/
-+
- obj-$(CONFIG_USB_ACM) += class/
- obj-$(CONFIG_USB_PRINTER) += class/
-
--- /dev/null
+++ gregkh-2.6/drivers/usb/ip/Makefile
@@ -0,0 +1,13 @@