Commit e0a22486 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://linuxusb.bkbits.net/linus-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 42197830 f5683a63
......@@ -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
......
......@@ -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.
......
......@@ -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\"",
......
......@@ -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);
......
......@@ -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))
......
......@@ -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
......
......@@ -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;
}
......
......@@ -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:
......
......@@ -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;
......
......@@ -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 */
......
......@@ -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);
}
......
......@@ -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);
}
......
......@@ -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;
}
......
......@@ -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;
};
......
......@@ -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;
}
......
/* 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;
}
......
#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
/* (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);
......
......@@ -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;
......
......@@ -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;
......
......@@ -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) {
......
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment