diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2006-03-13 10:27:32 +0000 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-03-13 10:27:32 +0000 |
commit | 7371b8e3bf96f28003582afb5f76182b7a9c4062 (patch) | |
tree | f2780b6029998e080850e96e6e67ca4fe60fd51c /usb | |
parent | 1b558141db8b06c61edebaaf5e3394ed98540ac7 (diff) | |
download | patches-7371b8e3bf96f28003582afb5f76182b7a9c4062.tar.gz |
refresh for 2.6.16-rc6
Diffstat (limited to 'usb')
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 @@ |