summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2002-06-11 01:30:23 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-06-11 01:30:23 -0700
commite0a224865173d64eb6e69baaa6f8a4d33954694b (patch)
tree0742b064f747905a6daf497fd2434a28eab941cd
parent42197830aa03a35ef951eae52f03f8020e8e8c66 (diff)
parentf5683a632207f573dbd2673ace013530ae83f786 (diff)
Merge bk://linuxusb.bkbits.net/linus-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
-rw-r--r--Documentation/usb/philips.txt8
-rw-r--r--drivers/usb/class/Config.help20
-rw-r--r--drivers/usb/class/printer.c13
-rw-r--r--drivers/usb/core/devices.c4
-rw-r--r--drivers/usb/core/devio.c19
-rw-r--r--drivers/usb/core/hcd-pci.c2
-rw-r--r--drivers/usb/host/hc_simple.c25
-rw-r--r--drivers/usb/host/ohci-hcd.c8
-rw-r--r--drivers/usb/host/ohci-q.c32
-rw-r--r--drivers/usb/host/ohci.h18
-rw-r--r--drivers/usb/host/uhci-hcd.c6
-rw-r--r--drivers/usb/host/uhci.c6
-rw-r--r--drivers/usb/image/hpusbscsi.c3
-rw-r--r--drivers/usb/image/hpusbscsi.h14
-rw-r--r--drivers/usb/media/dabusb.c4
-rw-r--r--drivers/usb/media/pwc-ctrl.c451
-rw-r--r--drivers/usb/media/pwc-ioctl.h65
-rw-r--r--drivers/usb/media/pwc.h7
-rw-r--r--drivers/usb/media/se401.c6
-rw-r--r--drivers/usb/net/cdc-ether.c1
-rw-r--r--drivers/usb/serial/ipaq.c3
-rw-r--r--drivers/usb/serial/keyspan_pda.c37
22 files changed, 598 insertions, 154 deletions
diff --git a/Documentation/usb/philips.txt b/Documentation/usb/philips.txt
index 16477ef62de3..926e17dfb975 100644
--- a/Documentation/usb/philips.txt
+++ b/Documentation/usb/philips.txt
@@ -189,10 +189,10 @@ trace
The fbufs, mbufs and trace parameters are global and apply to all connected
cameras. Each camera has its own set of buffers.
-size, fps, palette only specify defaults when you open() the device; this is
-to accommodate some tools that don't set the size or colour palette. You can
-change these settings after open() with the Video4Linux ioctl() calls. The
-default of defaults is QCIF size at 10 fps, BGR order.
+size and fps only specify defaults when you open() the device; this is to
+accommodate some tools that don't set the size. You can change these
+settings after open() with the Video4Linux ioctl() calls. The default of
+defaults is QCIF size at 10 fps, BGR order.
The compression parameter is semiglobal; it sets the initial compression
preference for all camera's, but this parameter can be set per camera with
diff --git a/drivers/usb/class/Config.help b/drivers/usb/class/Config.help
index c963c4748b41..8387ea4b8f77 100644
--- a/drivers/usb/class/Config.help
+++ b/drivers/usb/class/Config.help
@@ -34,6 +34,26 @@ CONFIG_USB_BLUETOOTH_TTY
The module will be called bluetty.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
+CONFIG_USB_MIDI
+ Say Y here if you want to connect a USB MIDI device to your
+ computer's USB port. This driver is for devices that comply with
+ 'Universal Serial Bus Device Class Definition for MIDI Device'.
+
+ The following devices are known to work:
+ * Steinberg USB2MIDI
+ * Roland MPU64
+ * Roland PC-300
+ * Roland SC8850
+ * Roland UM-1
+ * Roland UM-2
+ * Roland UA-100
+ * Yamaha MU1000
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called usb-midi.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
CONFIG_USB_PRINTER
Say Y here if you want to connect a USB printer to your computer's
USB port.
diff --git a/drivers/usb/class/printer.c b/drivers/usb/class/printer.c
index fbb4353a3a1b..06f256f0c2db 100644
--- a/drivers/usb/class/printer.c
+++ b/drivers/usb/class/printer.c
@@ -64,7 +64,7 @@
#define DRIVER_DESC "USB Printer Device Class driver"
#define USBLP_BUF_SIZE 8192
-#define DEVICE_ID_SIZE 1024
+#define USBLP_DEVICE_ID_SIZE 1024
/* ioctls: */
#define LPGETSTATUS 0x060b /* same as in drivers/char/lp.c */
@@ -722,7 +722,8 @@ static ssize_t usblp_read(struct file *file, char *buffer, size_t count, loff_t
usblp->minor, usblp->readurb->status);
usblp->readurb->dev = usblp->dev;
usblp->readcount = 0;
- usb_submit_urb(usblp->readurb, GFP_KERNEL);
+ if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0)
+ dbg("error submitting urb");
count = -EIO;
goto done;
}
@@ -839,7 +840,7 @@ static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
/* Malloc device ID string buffer to the largest expected length,
* since we can re-query it on an ioctl and a dynamic string
* could change in length. */
- if (!(usblp->device_id_string = kmalloc(DEVICE_ID_SIZE, GFP_KERNEL))) {
+ if (!(usblp->device_id_string = kmalloc(USBLP_DEVICE_ID_SIZE, GFP_KERNEL))) {
err("out of memory for device_id_string");
goto abort_minor;
}
@@ -1045,7 +1046,7 @@ static int usblp_cache_device_id_string(struct usblp *usblp)
{
int err, length;
- err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
+ err = usblp_get_id(usblp, 0, usblp->device_id_string, USBLP_DEVICE_ID_SIZE - 1);
if (err < 0) {
dbg("usblp%d: error = %d reading IEEE-1284 Device ID string",
usblp->minor, err);
@@ -1059,8 +1060,8 @@ static int usblp_cache_device_id_string(struct usblp *usblp)
length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1];
if (length < 2)
length = 2;
- else if (length >= DEVICE_ID_SIZE)
- length = DEVICE_ID_SIZE - 1;
+ else if (length >= USBLP_DEVICE_ID_SIZE)
+ length = USBLP_DEVICE_ID_SIZE - 1;
usblp->device_id_string[length] = '\0';
dbg("usblp%d Device ID string [len=%d]=\"%s\"",
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 1ad0f76756c5..c15f5f4e60b2 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -574,8 +574,10 @@ static ssize_t usb_device_read(struct file *file, char *buf, size_t nbytes, loff
bus = list_entry(buslist, struct usb_bus, bus_list);
/* recurse through all children of the root hub */
ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0);
- if (ret < 0)
+ if (ret < 0) {
+ up(&usb_bus_list_lock);
return ret;
+ }
total_written += ret;
}
up (&usb_bus_list_lock);
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index e6217fba77ba..f0f04849f8fb 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -215,8 +215,7 @@ extern __inline__ void async_removepending(struct async *as)
unsigned long flags;
spin_lock_irqsave(&ps->lock, flags);
- list_del(&as->asynclist);
- INIT_LIST_HEAD(&as->asynclist);
+ list_del_init(&as->asynclist);
spin_unlock_irqrestore(&ps->lock, flags);
}
@@ -228,8 +227,7 @@ extern __inline__ struct async *async_getcompleted(struct dev_state *ps)
spin_lock_irqsave(&ps->lock, flags);
if (!list_empty(&ps->async_completed)) {
as = list_entry(ps->async_completed.next, struct async, asynclist);
- list_del(&as->asynclist);
- INIT_LIST_HEAD(&as->asynclist);
+ list_del_init(&as->asynclist);
}
spin_unlock_irqrestore(&ps->lock, flags);
return as;
@@ -247,8 +245,7 @@ extern __inline__ struct async *async_getpending(struct dev_state *ps, void *use
p = p->next;
if (as->userurb != userurb)
continue;
- list_del(&as->asynclist);
- INIT_LIST_HEAD(&as->asynclist);
+ list_del_init(&as->asynclist);
spin_unlock_irqrestore(&ps->lock, flags);
return as;
}
@@ -263,8 +260,7 @@ static void async_completed(struct urb *urb)
struct siginfo sinfo;
spin_lock(&ps->lock);
- list_del(&as->asynclist);
- list_add_tail(&as->asynclist, &ps->async_completed);
+ list_move_tail(&as->asynclist, &ps->async_completed);
spin_unlock(&ps->lock);
wake_up(&ps->wait);
if (as->signr) {
@@ -284,8 +280,7 @@ static void destroy_all_async(struct dev_state *ps)
spin_lock_irqsave(&ps->lock, flags);
while (!list_empty(&ps->async_pending)) {
as = list_entry(ps->async_pending.next, struct async, asynclist);
- list_del(&as->asynclist);
- INIT_LIST_HEAD(&as->asynclist);
+ list_del_init(&as->asynclist);
spin_unlock_irqrestore(&ps->lock, flags);
/* usb_unlink_urb calls the completion handler with status == -ENOENT */
usb_unlink_urb(as->urb);
@@ -528,8 +523,8 @@ static int usbdev_release(struct inode *inode, struct file *file)
unsigned int i;
lock_kernel();
- list_del(&ps->list);
- INIT_LIST_HEAD(&ps->list);
+ list_del_init(&ps->list);
+
if (ps->dev) {
for (i = 0; ps->ifclaimed && i < 8*sizeof(ps->ifclaimed); i++)
if (test_bit(i, &ps->ifclaimed))
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 49aab9aa679f..446e7870c348 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -20,6 +20,8 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/irq.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
diff --git a/drivers/usb/host/hc_simple.c b/drivers/usb/host/hc_simple.c
index 1170cbd86b9a..3a7218442adb 100644
--- a/drivers/usb/host/hc_simple.c
+++ b/drivers/usb/host/hc_simple.c
@@ -220,14 +220,12 @@ static int hci_unlink_urb (struct urb * urb)
/* URB active? */
if (urb->transfer_flags & (USB_ASYNC_UNLINK | USB_TIMEOUT_KILLED)) {
- /* asynchron with callback */
-
- list_del (&urb->urb_list); /* relink the urb to the del list */
- list_add (&urb->urb_list, &hci->del_list);
+ /* asynchronous with callback */
+ /* relink the urb to the del list */
+ list_move (&urb->urb_list, &hci->del_list);
spin_unlock_irqrestore (&usb_urb_lock, flags);
-
} else {
- /* synchron without callback */
+ /* synchronous without callback */
add_wait_queue (&hci->waitq, &wait);
@@ -235,8 +233,8 @@ static int hci_unlink_urb (struct urb * urb)
comp = urb->complete;
urb->complete = NULL;
- list_del (&urb->urb_list); /* relink the urb to the del list */
- list_add (&urb->urb_list, &hci->del_list);
+ /* relink the urb to the del list */
+ list_move(&urb->urb_list, &hci->del_list);
spin_unlock_irqrestore (&usb_urb_lock, flags);
@@ -560,10 +558,9 @@ static struct urb *qu_next_urb (hci_t * hci, struct urb * urb, int resub_ok)
epd_t *ed = &hci_dev->ed[qu_pipeindex (urb->pipe)];
DBGFUNC ("enter qu_next_urb\n");
- list_del (&urb->urb_list);
- INIT_LIST_HEAD (&urb->urb_list);
- if (ed->pipe_head == urb) {
+ list_del_init(&urb->urb_list);
+ if (ed->pipe_head == urb) {
#ifdef HC_URB_TIMEOUT
if (urb->timeout)
del_timer (&ed->timeout);
@@ -574,8 +571,7 @@ static struct urb *qu_next_urb (hci_t * hci, struct urb * urb, int resub_ok)
if (!list_empty (&ed->urb_queue)) {
urb = list_entry (ed->urb_queue.next, struct urb, urb_list);
- list_del (&urb->urb_list);
- INIT_LIST_HEAD (&urb->urb_list);
+ list_del_init (&urb->urb_list);
ed->pipe_head = urb;
qu_queue_active_urb (hci, urb, ed);
} else {
@@ -756,8 +752,7 @@ static int sh_schedule_trans (hci_t * hci, int isSOF)
* only when the new SOF happens */
lh = hci->bulk_list.next;
- list_del (&hci->bulk_list);
- list_add (&hci->bulk_list, lh);
+ list_move (&hci->bulk_list, lh);
}
return 0;
}
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index ef9ac3c5efcc..177296bf987e 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -100,7 +100,7 @@
* - lots more testing!!
*/
-#define DRIVER_VERSION "2002-Jun-01"
+#define DRIVER_VERSION "2002-Jun-10"
#define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell"
#define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver"
@@ -307,7 +307,6 @@ ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
spin_lock_irqsave (&ohci->lock, flags);
for (i = 0; i < 32; i++) {
struct ed *ed = dev->ep [i];
- struct td *tdTailP;
if (!ed)
continue;
@@ -319,10 +318,7 @@ ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
case ED_NEW:
break;
case ED_UNLINK:
- tdTailP = dma_to_td (ohci,
- le32_to_cpup (&ed->hwTailP) & 0xfffffff0);
- td_free (ohci, tdTailP); /* free dummy td */
- hash_free_ed (ohci, ed);
+ td_free (ohci, ed->dummy);
break;
case ED_OPER:
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index 6eed4fb5fdaa..837210e9a0f4 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -440,14 +440,16 @@ static struct ed *ep_add_ed (
spin_unlock_irqrestore (&ohci->lock, flags);
return NULL;
}
+ ed->dummy = td;
ed->hwTailP = cpu_to_le32 (td->td_dma);
- ed->hwHeadP = ed->hwTailP;
+ ed->hwHeadP = ed->hwTailP; /* ED_C, ED_H zeroed */
ed->state = ED_UNLINK;
ed->type = usb_pipetype (pipe);
}
-// FIXME: don't do this if it's linked to the HC,
-// we might clobber data toggle or other state ...
+// FIXME: don't do this if it's linked to the HC, or without knowing it's
+// safe to clobber state/mode info tied to (previous) config/altsetting.
+// (but dev0/ep0, used by set_address, must get clobbered)
ed->hwINFO = cpu_to_le32 (usb_pipedevice (pipe)
| usb_pipeendpoint (pipe) << 7
@@ -523,27 +525,31 @@ td_fill (struct ohci_hcd *ohci, unsigned int info,
dma_addr_t data, int len,
struct urb *urb, int index)
{
- volatile struct td *td, *td_pt;
+ struct td *td, *td_pt;
urb_priv_t *urb_priv = urb->hcpriv;
+ int is_iso = info & TD_ISO;
if (index >= urb_priv->length) {
err ("internal OHCI error: TD index > length");
return;
}
-#if 0
- /* no interrupt needed except for URB's last TD */
+ /* aim for only one interrupt per urb. mostly applies to control
+ * and iso; other urbs rarely need more than one TD per urb.
+ *
+ * NOTE: could delay interrupts even for the last TD, and get fewer
+ * interrupts ... increasing per-urb latency by sharing interrupts.
+ */
if (index != (urb_priv->length - 1))
- info |= TD_DI;
-#endif
+ info |= is_iso ? TD_DI_SET (7) : TD_DI_SET (1);
/* use this td as the next dummy */
td_pt = urb_priv->td [index];
td_pt->hwNextTD = 0;
/* fill the old dummy TD */
- td = urb_priv->td [index] = dma_to_td (ohci,
- le32_to_cpup (&urb_priv->ed->hwTailP));
+ td = urb_priv->td [index] = urb_priv->ed->dummy;
+ urb_priv->ed->dummy = td_pt;
td->ed = urb_priv->ed;
td->next_dl_td = NULL;
@@ -554,7 +560,7 @@ td_fill (struct ohci_hcd *ohci, unsigned int info,
data = 0;
td->hwINFO = cpu_to_le32 (info);
- if ((td->ed->type) == PIPE_ISOCHRONOUS) {
+ if (is_iso) {
td->hwCBP = cpu_to_le32 (data & 0xFFFFF000);
td->ed->intriso.last_iso = info & 0xffff;
} else {
@@ -901,6 +907,7 @@ static void finish_unlinks (struct ohci_hcd *ohci, u16 tick)
* [a2] some (earlier) URBs still linked, re-enable
* (b) finishing ED unlink
* [b1] no URBs queued, ED is truly idle now
+ * ... we could set state ED_NEW and free dummy
* [b2] URBs now queued, link ED back into schedule
* right now we only have (a)
*/
@@ -910,9 +917,6 @@ static void finish_unlinks (struct ohci_hcd *ohci, u16 tick)
if (tdHeadP == tdTailP) {
if (ed->state == ED_OPER)
start_ed_unlink (ohci, ed);
- td_free (ohci, tdTailP);
- ed->hwINFO = ED_SKIP;
- ed->state = ED_NEW;
} else
ed->hwINFO &= ~ED_SKIP;
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 57e51b0298d7..a5bbe43fb75f 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -29,6 +29,7 @@ struct ed {
/* rest are purely for the driver's use */
dma_addr_t dma; /* addr of ED */
struct ed *ed_prev; /* for non-interrupt EDs */
+ struct td *dummy;
u8 type; /* PIPE_{BULK,...} */
u8 interval; /* interrupt, isochronous */
@@ -63,24 +64,33 @@ struct ed {
struct td {
/* first fields are hardware-specified, le32 */
__u32 hwINFO; /* transfer info bitmask */
+
+ /* hwINFO bits for both general and iso tds: */
#define TD_CC 0xf0000000 /* condition code */
#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
//#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
+#define TD_DI 0x00E00000 /* frames before interrupt */
+#define TD_DI_SET(X) (((X) & 0x07)<< 21)
+ /* these two bits are available for definition/use by HCDs in both
+ * general and iso tds ... others are available for only one type
+ */
+//#define TD____ 0x00020000
+#define TD_ISO 0x00010000 /* copy of ED_ISO */
+
+ /* hwINFO bits for general tds: */
#define TD_EC 0x0C000000 /* error count */
#define TD_T 0x03000000 /* data toggle state */
#define TD_T_DATA0 0x02000000 /* DATA0 */
#define TD_T_DATA1 0x03000000 /* DATA1 */
#define TD_T_TOGGLE 0x00000000 /* uses ED_C */
-#define TD_DI 0x00E00000 /* frames before interrupt */
-//#define TD_DI_SET(X) (((X) & 0x07)<< 21)
#define TD_DP 0x00180000 /* direction/pid */
#define TD_DP_SETUP 0x00000000 /* SETUP pid */
#define TD_DP_IN 0x00100000 /* IN pid */
#define TD_DP_OUT 0x00080000 /* OUT pid */
/* 0x00180000 rsvd */
#define TD_R 0x00040000 /* round: short packets OK? */
- /* bits 0x1ffff are defined by HCD */
-#define TD_ISO 0x00010000 /* copy of ED_ISO */
+
+ /* (no hwINFO #defines yet for iso tds) */
__u32 hwCBP; /* Current Buffer Pointer (or 0) */
__u32 hwNextTD; /* Next TD Pointer */
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 5efc85cf5e2a..23919dfb7c84 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -1773,10 +1773,8 @@ static void stall_callback(unsigned long ptr)
uhci_fsbr_timeout(uhci, u);
/* Check if the URB timed out */
- if (u->timeout && time_after_eq(jiffies, up->inserttime + u->timeout)) {
- list_del(&up->urb_list);
- list_add_tail(&up->urb_list, &list);
- }
+ if (u->timeout && time_after_eq(jiffies, up->inserttime + u->timeout))
+ list_move_tail(&up->urb_list, &list);
spin_unlock(&u->lock);
}
diff --git a/drivers/usb/host/uhci.c b/drivers/usb/host/uhci.c
index 7ced42fb6022..e3325b7b23a0 100644
--- a/drivers/usb/host/uhci.c
+++ b/drivers/usb/host/uhci.c
@@ -2008,10 +2008,8 @@ static void rh_int_timer_do(unsigned long ptr)
uhci_fsbr_timeout(uhci, u);
/* Check if the URB timed out */
- if (u->timeout && time_after_eq(jiffies, up->inserttime + u->timeout)) {
- list_del(&u->urb_list);
- list_add_tail(&u->urb_list, &list);
- }
+ if (u->timeout && time_after_eq(jiffies, up->inserttime + u->timeout))
+ list_move_tail(&u->urb_list, &list);
spin_unlock(&u->lock);
}
diff --git a/drivers/usb/image/hpusbscsi.c b/drivers/usb/image/hpusbscsi.c
index 2a262566558b..58c311db3c4e 100644
--- a/drivers/usb/image/hpusbscsi.c
+++ b/drivers/usb/image/hpusbscsi.c
@@ -273,8 +273,6 @@ static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback)
usb_urb_callback usb_callback;
int res;
- hpusbscsi->use_count++;
-
/* we don't answer for anything but our single device on any faked host controller */
if ( srb->device->lun || srb->device->id || srb->device->channel ) {
if (callback) {
@@ -341,7 +339,6 @@ static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback)
}
out:
- hpusbscsi->use_count--;
return 0;
}
diff --git a/drivers/usb/image/hpusbscsi.h b/drivers/usb/image/hpusbscsi.h
index 87d1d7efa168..878b31ae0c4c 100644
--- a/drivers/usb/image/hpusbscsi.h
+++ b/drivers/usb/image/hpusbscsi.h
@@ -20,25 +20,25 @@ struct hpusbscsi
int ep_in;
int ep_int;
int interrupt_interval;
-
+ int number;
+ int fragment;
struct Scsi_Host *host;
- Scsi_Host_Template ctempl;
- int number;
+
scsi_callback scallback;
Scsi_Cmnd *srb;
- u8 sense_command[SENSE_COMMAND_SIZE];
- int use_count;
+
wait_queue_head_t pending;
wait_queue_head_t deathrow;
struct urb *dataurb;
struct urb *controlurb;
- int fragment;
+
int state;
int current_data_pipe;
-
+ Scsi_Host_Template ctempl;
+ u8 sense_command[SENSE_COMMAND_SIZE];
u8 scsi_state_byte;
};
diff --git a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c
index 208337fa61e7..7df4e9eaba47 100644
--- a/drivers/usb/media/dabusb.c
+++ b/drivers/usb/media/dabusb.c
@@ -80,8 +80,7 @@ static int dabusb_add_buf_tail (pdabusb_t s, struct list_head *dst, struct list_
goto err;
}
tmp = src->next;
- list_del (tmp);
- list_add_tail (tmp, dst);
+ list_move_tail (tmp, dst);
err: spin_unlock_irqrestore (&s->lock, flags);
return ret;
@@ -609,6 +608,7 @@ static int dabusb_open (struct inode *inode, struct file *file)
down (&s->mutex);
}
if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
+ up(&s->mutex);
err("set_interface failed");
return -EINVAL;
}
diff --git a/drivers/usb/media/pwc-ctrl.c b/drivers/usb/media/pwc-ctrl.c
index ca83ee4275c8..71337853115d 100644
--- a/drivers/usb/media/pwc-ctrl.c
+++ b/drivers/usb/media/pwc-ctrl.c
@@ -1,7 +1,7 @@
/* Driver for Philips webcam
Functions that send various control messages to the webcam, including
video modes.
- (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+ (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl)
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
@@ -78,10 +78,12 @@
#define READ_SHUTTER_FORMATTER 0x0600
#define READ_RED_GAIN_FORMATTER 0x0700
#define READ_BLUE_GAIN_FORMATTER 0x0800
+#define SENSOR_TYPE_FORMATTER1 0x0C00
#define READ_RAW_Y_MEAN_FORMATTER 0x3100
#define SET_POWER_SAVE_MODE_FORMATTER 0x3200
#define MIRROR_IMAGE_FORMATTER 0x3300
#define LED_FORMATTER 0x3400
+#define SENSOR_TYPE_FORMATTER2 0x3700
/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100
@@ -162,6 +164,21 @@ static struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
/****************************************************************************/
+#define SendControlMsg(request, value, buflen) \
+ usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), \
+ request, \
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \
+ value, \
+ pdev->vcinterface, \
+ &buf, buflen, HZ / 2)
+
+#define RecvControlMsg(request, value, buflen) \
+ usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), \
+ request, \
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \
+ value, \
+ pdev->vcinterface, \
+ &buf, buflen, HZ / 2)
#if PWC_DEBUG
@@ -241,7 +258,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
if (ret < 0)
return ret;
- if (pEntry->compressed)
+ if (pEntry->compressed && pdev->decompressor != NULL)
pdev->decompressor->init(pdev->release, buf, pdev->decompress_data);
/* Set various parameters */
@@ -911,7 +928,7 @@ static inline int pwc_get_red_gain(struct pwc_device *pdev)
int ret;
ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
- GET_STATUS_CTL,
+ GET_CHROM_CTL,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
PRESET_MANUAL_RED_GAIN_FORMATTER,
pdev->vcinterface,
@@ -950,7 +967,7 @@ static inline int pwc_get_blue_gain(struct pwc_device *pdev)
int ret;
ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
- GET_STATUS_CTL,
+ GET_CHROM_CTL,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
PRESET_MANUAL_BLUE_GAIN_FORMATTER,
pdev->vcinterface,
@@ -962,6 +979,7 @@ static inline int pwc_get_blue_gain(struct pwc_device *pdev)
return (buf << 8);
}
+
/* The following two functions are different, since they only read the
internal red/blue gains, which may be different from the manual
gains set or read above.
@@ -979,7 +997,7 @@ static inline int pwc_read_red_gain(struct pwc_device *pdev)
&buf, 1, HZ / 2);
if (ret < 0)
- return ret;
+ return ret;
return (buf << 8);
}
@@ -997,11 +1015,74 @@ static inline int pwc_read_blue_gain(struct pwc_device *pdev)
&buf, 1, HZ / 2);
if (ret < 0)
- return ret;
+ return ret;
return (buf << 8);
}
+
+static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
+{
+ unsigned char buf;
+
+ /* useful range is 0x01..0x20 */
+ buf = speed / 0x7f0;
+ return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ SET_CHROM_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ AWB_CONTROL_SPEED_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+}
+
+static inline int pwc_get_wb_speed(struct pwc_device *pdev)
+{
+ unsigned char buf;
+ int ret;
+
+ ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+ GET_CHROM_CTL,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ AWB_CONTROL_SPEED_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+ if (ret < 0)
+ return ret;
+ return (buf * 0x7f0);
+}
+
+
+static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
+{
+ unsigned char buf;
+
+ /* useful range is 0x01..0x3F */
+ buf = (delay >> 10);
+ return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ SET_CHROM_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ AWB_CONTROL_DELAY_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+}
+
+static inline int pwc_get_wb_delay(struct pwc_device *pdev)
+{
+ unsigned char buf;
+ int ret;
+
+ ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+ GET_CHROM_CTL,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ AWB_CONTROL_DELAY_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+ if (ret < 0)
+ return ret;
+ return (buf << 10);
+}
+
+
int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
{
unsigned char buf[2];
@@ -1055,61 +1136,248 @@ int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
return 0;
}
+static inline int pwc_set_contour(struct pwc_device *pdev, int contour)
+{
+ unsigned char buf;
+ int ret;
+
+ if (contour < 0)
+ buf = 0xff; /* auto contour on */
+ else
+ buf = 0x0; /* auto contour off */
+ ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ SET_LUM_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ AUTO_CONTOUR_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+ if (ret < 0)
+ return ret;
+
+ if (contour < 0)
+ return 0;
+ if (contour > 0xffff)
+ contour = 0xffff;
+
+ buf = (contour >> 10); /* contour preset is [0..3f] */
+ ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ SET_LUM_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ PRESET_CONTOUR_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+static inline int pwc_get_contour(struct pwc_device *pdev, int *contour)
+{
+ unsigned char buf;
+ int ret;
+
+ ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+ GET_LUM_CTL,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ AUTO_CONTOUR_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+ if (ret < 0)
+ return ret;
+
+ if (buf == 0) {
+ /* auto mode off, query current preset value */
+ ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+ GET_LUM_CTL,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ PRESET_CONTOUR_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+ if (ret < 0)
+ return ret;
+ *contour = (buf << 10);
+ }
+ else
+ *contour = -1;
+ return 0;
+}
+
+
+static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight)
+{
+ unsigned char buf;
+
+ if (backlight)
+ buf = 0xff;
+ else
+ buf = 0x0;
+ return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ SET_LUM_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ BACK_LIGHT_COMPENSATION_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+}
+
+static inline int pwc_get_backlight(struct pwc_device *pdev)
+{
+ int ret;
+ unsigned char buf;
+
+ ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+ GET_LUM_CTL,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ BACK_LIGHT_COMPENSATION_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+ if (ret < 0)
+ return ret;
+ return buf;
+}
+
+
+static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker)
+{
+ unsigned char buf;
+
+ if (flicker)
+ buf = 0xff;
+ else
+ buf = 0x0;
+ return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
+}
+
+static inline int pwc_get_flicker(struct pwc_device *pdev)
+{
+ int ret;
+ unsigned char buf;
+
+ ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+ return buf;
+}
+
+
+static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
+{
+ unsigned char buf;
+
+ if (noise < 0)
+ noise = 0;
+ if (noise > 3)
+ noise = 3;
+ buf = noise;
+ return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
+}
+
+static inline int pwc_get_dynamic_noise(struct pwc_device *pdev)
+{
+ int ret;
+ unsigned char buf;
+
+ ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+//Debug("pwc_get_dynamic_noise = %d\n", buf);
+ return buf;
+}
+
+
+int pwc_get_cmos_sensor(struct pwc_device *pdev)
+{
+ unsigned char buf;
+ int ret = -1, request;
+
+ if (pdev->type < 675)
+ request = SENSOR_TYPE_FORMATTER1;
+ else if (pdev->type < 730)
+ return -1; /* The Vesta series doesn't have this call */
+ else
+ request = SENSOR_TYPE_FORMATTER2;
+
+ ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+ GET_STATUS_CTL,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ request,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+ if (ret < 0)
+ return ret;
+ if (pdev->type < 675)
+ return buf | 0x100;
+ else
+ return buf;
+}
+
+
/* End of Add-Ons */
/* ************************************************* */
int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
{
+ int ret = 0;
+
switch(cmd) {
case VIDIOCPWCRUSER:
{
if (pwc_restore_user(pdev))
- return -EINVAL;
+ ret = -EINVAL;
break;
}
case VIDIOCPWCSUSER:
{
if (pwc_save_user(pdev))
- return -EINVAL;
+ ret = -EINVAL;
break;
}
case VIDIOCPWCFACTORY:
{
if (pwc_restore_factory(pdev))
- return -EINVAL;
+ ret = -EINVAL;
break;
}
case VIDIOCPWCSCQUAL:
{
int *qual = arg;
- int ret;
if (*qual < 0 || *qual > 3)
- return -EINVAL;
- ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, *qual, pdev->vsnapshot);
- if (ret < 0)
- return ret;
- pdev->vcompression = *qual;
+ ret = -EINVAL;
+ else
+ ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, *qual, pdev->vsnapshot);
+ if (ret >= 0)
+ pdev->vcompression = *qual;
break;
}
case VIDIOCPWCGCQUAL:
{
int *qual = arg;
-
+
*qual = pdev->vcompression;
break;
}
+ case VIDIOCPWCPROBE:
+ {
+ struct pwc_probe probe;
+
+ strcpy(probe.name, pdev->vdev->name);
+ probe.type = pdev->type;
+ if (copy_to_user(arg, &probe, sizeof(probe)))
+ ret = -EFAULT;
+ break;
+ }
+
case VIDIOCPWCSAGC:
{
int *agc = arg;
-
+
if (pwc_set_agc(pdev, *agc < 0 ? 1 : 0, *agc))
- return -EINVAL;
+ ret = -EINVAL;
break;
}
@@ -1118,29 +1386,21 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
int *agc = arg;
if (pwc_get_agc(pdev, agc))
- return -EINVAL;
+ ret = -EINVAL;
break;
}
case VIDIOCPWCSSHUTTER:
{
int *shutter_speed = arg;
- int ret;
ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed);
- if (ret < 0)
- return ret;
break;
}
-
- /* ************************************************* */
- /* Begin of Add-Ons for color compensation */
-
case VIDIOCPWCSAWB:
{
struct pwc_whitebalance *wb = arg;
- int ret;
ret = pwc_set_awb(pdev, wb->mode);
if (ret >= 0 && wb->mode == PWC_WB_MANUAL) {
@@ -1153,52 +1413,149 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
case VIDIOCPWCGAWB:
{
struct pwc_whitebalance *wb = arg;
-
+
memset(wb, 0, sizeof(*wb));
wb->mode = pwc_get_awb(pdev);
if (wb->mode < 0)
- return -EINVAL;
- wb->manual_red = pwc_get_red_gain(pdev);
- wb->manual_blue = pwc_get_blue_gain(pdev);
- if (wb->mode == PWC_WB_AUTO) {
- wb->read_red = pwc_read_red_gain(pdev);
- wb->read_blue = pwc_read_blue_gain(pdev);
+ ret = -EINVAL;
+ else {
+ if (wb->mode == PWC_WB_MANUAL) {
+ wb->manual_red = pwc_get_red_gain(pdev);
+ wb->manual_blue = pwc_get_blue_gain(pdev);
+ }
+ if (wb->mode == PWC_WB_AUTO) {
+ wb->read_red = pwc_read_red_gain(pdev);
+ wb->read_blue = pwc_read_blue_gain(pdev);
+ }
}
break;
}
+
+ case VIDIOCPWCSAWBSPEED:
+ {
+ struct pwc_wb_speed *wbs = arg;
+
+ if (wbs->control_speed > 0) {
+ ret = pwc_set_wb_speed(pdev, wbs->control_speed);
+ }
+ if (wbs->control_delay > 0) {
+ ret = pwc_set_wb_delay(pdev, wbs->control_delay);
+ }
+ break;
+ }
+
+ case VIDIOCPWCGAWBSPEED:
+ {
+ struct pwc_wb_speed *wbs = arg;
+
+ ret = pwc_get_wb_speed(pdev);
+ if (ret < 0)
+ break;
+ wbs->control_speed = ret;
+ ret = pwc_get_wb_delay(pdev);
+ if (ret < 0)
+ break;
+ wbs->control_delay = ret;
+ break;
+ }
case VIDIOCPWCSLED:
{
- int ret;
struct pwc_leds *leds = arg;
ret = pwc_set_leds(pdev, leds->led_on, leds->led_off);
- if (ret<0)
- return ret;
- break;
+ break;
}
-
case VIDIOCPWCGLED:
{
- int led;
struct pwc_leds *leds = arg;
- led = pwc_get_leds(pdev, &leds->led_on, &leds->led_off);
- if (led < 0)
- return -EINVAL;
+ ret = pwc_get_leds(pdev, &leds->led_on, &leds->led_off);
break;
}
- /* End of Add-Ons */
- /* ************************************************* */
+ case VIDIOCPWCSCONTOUR:
+ {
+ int *contour = arg;
+
+ ret = pwc_set_contour(pdev, *contour);
+ break;
+ }
+
+ case VIDIOCPWCGCONTOUR:
+ {
+ int *contour = arg;
+
+ ret = pwc_get_contour(pdev, contour);
+ break;
+ }
+
+ case VIDIOCPWCSBACKLIGHT:
+ {
+ int *backlight = arg;
+
+ ret = pwc_set_backlight(pdev, *backlight);
+ break;
+ }
+
+ case VIDIOCPWCGBACKLIGHT:
+ {
+ int *backlight = arg;
+
+ ret = pwc_get_backlight(pdev);
+ if (ret >= 0)
+ *backlight = ret;
+ break;
+ }
+
+ case VIDIOCPWCSFLICKER:
+ {
+ int *flicker = arg;
+
+ ret = pwc_set_flicker(pdev, *flicker);
+ break;
+ }
+
+ case VIDIOCPWCGFLICKER:
+ {
+ int *flicker = arg;
+
+ ret = pwc_get_flicker(pdev);
+ if (ret >= 0)
+ *flicker = ret;
+ break;
+ }
+
+ case VIDIOCPWCSDYNNOISE:
+ {
+ int *dynnoise = arg;
+
+ ret = pwc_set_dynamic_noise(pdev, *dynnoise);
+ break;
+ }
+
+ case VIDIOCPWCGDYNNOISE:
+ {
+ int *dynnoise = arg;
+
+ ret = pwc_get_dynamic_noise(pdev);
+ if (ret < 0)
+ break;
+ *dynnoise = ret;
+ break;
+ }
+
default:
- return -ENOIOCTLCMD;
+ ret = -ENOIOCTLCMD;
break;
}
- return 0;
+
+ if (ret > 0)
+ return 0;
+ return ret;
}
diff --git a/drivers/usb/media/pwc-ioctl.h b/drivers/usb/media/pwc-ioctl.h
index 6807cab91e8c..d7306635fa06 100644
--- a/drivers/usb/media/pwc-ioctl.h
+++ b/drivers/usb/media/pwc-ioctl.h
@@ -1,7 +1,7 @@
#ifndef PWC_IOCTL_H
#define PWC_IOCTL_H
-/* (C) 2001 Nemosoft Unv. webcam@smcc.demon.nl
+/* (C) 2001-2002 Nemosoft Unv. webcam@smcc.demon.nl
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
@@ -18,7 +18,9 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/*
+/* This is pwc-ioctl.h belonging to PWC 8.7 */
+
+/*
Changes
2001/08/03 Alvarado Added ioctl constants to access methods for
changing white balance and red/blue gains
@@ -52,6 +54,14 @@
#define PWC_FPS_SNAPSHOT 0x00400000
+
+struct pwc_probe
+{
+ char name[32];
+ int type;
+};
+
+
/* pwc_whitebalance.mode values */
#define PWC_WB_INDOOR 0
#define PWC_WB_OUTDOOR 1
@@ -63,9 +73,9 @@
Set mode to one of the PWC_WB_* values above.
*red and *blue are the respective gains of these colour components inside
the camera; range 0..65535
- When mode == PWC_WB_MANUAL, manual_red and manual_blue are set or read;
+ When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read;
otherwise undefined.
- read_red and read_blue are read-only.
+ 'read_red' and 'read_blue' are read-only.
*/
struct pwc_whitebalance
@@ -75,6 +85,17 @@ struct pwc_whitebalance
int read_red, read_blue; /* R/O */
};
+/*
+ 'control_speed' and 'control_delay' are used in automatic whitebalance mode,
+ and tell the camera how fast it should react to changes in lighting, and
+ with how much delay. Valid values are 0..65535.
+*/
+struct pwc_wb_speed
+{
+ int control_speed;
+ int control_delay;
+
+};
/* Used with VIDIOCPWC[SG]LED */
struct pwc_leds
@@ -104,6 +125,19 @@ struct pwc_leds
/* Get preferred compression quality */
#define VIDIOCPWCGCQUAL _IOR('v', 195, int)
+
+ /* This is a probe function; since so many devices are supported, it
+ becomes difficult to include all the names in programs that want to
+ check for the enhanced Philips stuff. So in stead, try this PROBE;
+ it returns a structure with the original name, and the corresponding
+ Philips type.
+ To use, fill the structure with zeroes, call PROBE and if that succeeds,
+ compare the name with that returned from VIDIOCGCAP; they should be the
+ same. If so, you can be assured it is a Philips (OEM) cam and the type
+ is valid.
+ */
+#define VIDIOCPWCPROBE _IOR('v', 199, struct pwc_probe)
+
/* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
#define VIDIOCPWCSAGC _IOW('v', 200, int)
/* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
@@ -115,9 +149,28 @@ struct pwc_leds
#define VIDIOCPWCSAWB _IOW('v', 202, struct pwc_whitebalance)
#define VIDIOCPWCGAWB _IOR('v', 202, struct pwc_whitebalance)
- /* Turn LED on/off ; int range 0..65535 */
+ /* Auto WB speed */
+#define VIDIOCPWCSAWBSPEED _IOW('v', 203, struct pwc_wb_speed)
+#define VIDIOCPWCGAWBSPEED _IOR('v', 203, struct pwc_wb_speed)
+
+ /* LEDs on/off/blink; int range 0..65535 */
#define VIDIOCPWCSLED _IOW('v', 205, struct pwc_leds)
- /* Get state of LED; int range 0..65535 */
#define VIDIOCPWCGLED _IOR('v', 205, struct pwc_leds)
+ /* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */
+#define VIDIOCPWCSCONTOUR _IOW('v', 206, int)
+#define VIDIOCPWCGCONTOUR _IOR('v', 206, int)
+
+ /* Backlight compensation; 0 = off, otherwise on */
+#define VIDIOCPWCSBACKLIGHT _IOW('v', 207, int)
+#define VIDIOCPWCGBACKLIGHT _IOR('v', 207, int)
+
+ /* Flickerless mode; = 0 off, otherwise on */
+#define VIDIOCPWCSFLICKER _IOW('v', 208, int)
+#define VIDIOCPWCGFLICKER _IOR('v', 208, int)
+
+ /* Dynamic noise reduction; 0 off, 3 = high noise reduction */
+#define VIDIOCPWCSDYNNOISE _IOW('v', 209, int)
+#define VIDIOCPWCGDYNNOISE _IOR('v', 209, int)
+
#endif
diff --git a/drivers/usb/media/pwc.h b/drivers/usb/media/pwc.h
index 28ebbb6c7215..63856cb7b8a0 100644
--- a/drivers/usb/media/pwc.h
+++ b/drivers/usb/media/pwc.h
@@ -1,4 +1,4 @@
-/* (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+/* (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl)
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
@@ -60,8 +60,8 @@
/* Version block */
#define PWC_MAJOR 8
-#define PWC_MINOR 5
-#define PWC_VERSION "8.5"
+#define PWC_MINOR 7
+#define PWC_VERSION "8.7"
#define PWC_NAME "pwc"
/* Turn certain features on/off */
@@ -247,6 +247,7 @@ extern int pwc_get_saturation(struct pwc_device *pdev);
extern int pwc_set_saturation(struct pwc_device *pdev, int value);
extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
extern int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value);
+extern int pwc_get_cmos_sensor(struct pwc_device *pdev);
/* Power down or up the camera; not supported by all models */
extern int pwc_camera_power(struct pwc_device *pdev, int power);
diff --git a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c
index da3d7a27b841..90108c2aa301 100644
--- a/drivers/usb/media/se401.c
+++ b/drivers/usb/media/se401.c
@@ -1330,7 +1330,13 @@ static int se401_init(struct usb_se401 *se401)
se401->sizes=cp[4]+cp[5]*256;
se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
+ if (!se401->width)
+ return 1;
se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
+ if (!se401->height) {
+ kfree(se401->width);
+ return 1;
+ }
for (i=0; i<se401->sizes; i++) {
se401->width[i]=cp[6+i*4+0]+cp[6+i*4+1]*256;
se401->height[i]=cp[6+i*4+2]+cp[6+i*4+3]*256;
diff --git a/drivers/usb/net/cdc-ether.c b/drivers/usb/net/cdc-ether.c
index b4613e9c41b9..1d3ac4508363 100644
--- a/drivers/usb/net/cdc-ether.c
+++ b/drivers/usb/net/cdc-ether.c
@@ -426,6 +426,7 @@ static void CDC_SetEthernetPacketFilter (ether_dev_t *ether_dev)
}
#endif
+
static void CDCEther_set_multicast( struct net_device *net )
{
ether_dev_t *ether_dev = net->priv;
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 5ce3bd4f2cf4..be4a000926ff 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -401,8 +401,7 @@ static void ipaq_write_gather(struct usb_serial_port *port)
pkt->written += count;
priv->queue_len -= count;
if (pkt->written == pkt->len) {
- list_del(&pkt->list);
- list_add(&pkt->list, &priv->freelist);
+ list_move(&pkt->list, &priv->freelist);
priv->free_len += PACKET_SIZE;
}
if (room == 0) {
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index e5fa265db9b7..c1880dd6789a 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -194,20 +194,24 @@ static void keyspan_pda_wakeup_write( struct usb_serial_port *port )
static void keyspan_pda_request_unthrottle( struct usb_serial *serial )
{
+ int result;
dbg(" request_unthrottle");
/* ask the device to tell us when the tx buffer becomes
sufficiently empty */
- usb_control_msg(serial->dev,
- usb_sndctrlpipe(serial->dev, 0),
- 7, /* request_unthrottle */
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE
- | USB_DIR_OUT,
- 16, /* value: threshold */
- 0, /* index */
- NULL,
- 0,
- 2*HZ);
+ result = usb_control_msg(serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ 7, /* request_unthrottle */
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE
+ | USB_DIR_OUT,
+ 16, /* value: threshold */
+ 0, /* index */
+ NULL,
+ 0,
+ 2*HZ);
+ if (result < 0)
+ dbg("%s - error %d from usb_control_msg",
+ __FUNCTION__, result);
}
@@ -334,14 +338,19 @@ static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state
{
struct usb_serial *serial = port->serial;
int value;
+ int result;
+
if (break_state == -1)
value = 1; /* start break */
else
value = 0; /* clear break */
- usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- 4, /* set break */
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- value, 0, NULL, 0, 2*HZ);
+ result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ 4, /* set break */
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ value, 0, NULL, 0, 2*HZ);
+ if (result < 0)
+ dbg("%s - error %d from usb_control_msg",
+ __FUNCTION__, result);
/* there is something funky about this.. the TCSBRK that 'cu' performs
ought to translate into a break_ctl(-1),break_ctl(0) pair HZ/4
seconds apart, but it feels like the break sent isn't as long as it