diff options
| author | Linus Torvalds <torvalds@home.transmeta.com> | 2002-06-11 01:30:23 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2002-06-11 01:30:23 -0700 |
| commit | e0a224865173d64eb6e69baaa6f8a4d33954694b (patch) | |
| tree | 0742b064f747905a6daf497fd2434a28eab941cd | |
| parent | 42197830aa03a35ef951eae52f03f8020e8e8c66 (diff) | |
| parent | f5683a632207f573dbd2673ace013530ae83f786 (diff) | |
Merge bk://linuxusb.bkbits.net/linus-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
| -rw-r--r-- | Documentation/usb/philips.txt | 8 | ||||
| -rw-r--r-- | drivers/usb/class/Config.help | 20 | ||||
| -rw-r--r-- | drivers/usb/class/printer.c | 13 | ||||
| -rw-r--r-- | drivers/usb/core/devices.c | 4 | ||||
| -rw-r--r-- | drivers/usb/core/devio.c | 19 | ||||
| -rw-r--r-- | drivers/usb/core/hcd-pci.c | 2 | ||||
| -rw-r--r-- | drivers/usb/host/hc_simple.c | 25 | ||||
| -rw-r--r-- | drivers/usb/host/ohci-hcd.c | 8 | ||||
| -rw-r--r-- | drivers/usb/host/ohci-q.c | 32 | ||||
| -rw-r--r-- | drivers/usb/host/ohci.h | 18 | ||||
| -rw-r--r-- | drivers/usb/host/uhci-hcd.c | 6 | ||||
| -rw-r--r-- | drivers/usb/host/uhci.c | 6 | ||||
| -rw-r--r-- | drivers/usb/image/hpusbscsi.c | 3 | ||||
| -rw-r--r-- | drivers/usb/image/hpusbscsi.h | 14 | ||||
| -rw-r--r-- | drivers/usb/media/dabusb.c | 4 | ||||
| -rw-r--r-- | drivers/usb/media/pwc-ctrl.c | 451 | ||||
| -rw-r--r-- | drivers/usb/media/pwc-ioctl.h | 65 | ||||
| -rw-r--r-- | drivers/usb/media/pwc.h | 7 | ||||
| -rw-r--r-- | drivers/usb/media/se401.c | 6 | ||||
| -rw-r--r-- | drivers/usb/net/cdc-ether.c | 1 | ||||
| -rw-r--r-- | drivers/usb/serial/ipaq.c | 3 | ||||
| -rw-r--r-- | drivers/usb/serial/keyspan_pda.c | 37 |
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 |
