Commit 8b2ada12 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

merge

parents 7ef17402 6f43b3a3
...@@ -189,10 +189,10 @@ trace ...@@ -189,10 +189,10 @@ trace
The fbufs, mbufs and trace parameters are global and apply to all connected The fbufs, mbufs and trace parameters are global and apply to all connected
cameras. Each camera has its own set of buffers. cameras. Each camera has its own set of buffers.
size, fps, palette only specify defaults when you open() the device; this is size and fps only specify defaults when you open() the device; this is to
to accommodate some tools that don't set the size or colour palette. You can accommodate some tools that don't set the size. You can change these
change these settings after open() with the Video4Linux ioctl() calls. The settings after open() with the Video4Linux ioctl() calls. The default of
default of defaults is QCIF size at 10 fps, BGR order. defaults is QCIF size at 10 fps, BGR order.
The compression parameter is semiglobal; it sets the initial compression The compression parameter is semiglobal; it sets the initial compression
preference for all camera's, but this parameter can be set per camera with preference for all camera's, but this parameter can be set per camera with
......
...@@ -34,6 +34,26 @@ CONFIG_USB_BLUETOOTH_TTY ...@@ -34,6 +34,26 @@ CONFIG_USB_BLUETOOTH_TTY
The module will be called bluetty.o. If you want to compile it as 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>. 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 CONFIG_USB_PRINTER
Say Y here if you want to connect a USB printer to your computer's Say Y here if you want to connect a USB printer to your computer's
USB port. USB port.
......
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
#define DRIVER_DESC "USB Printer Device Class driver" #define DRIVER_DESC "USB Printer Device Class driver"
#define USBLP_BUF_SIZE 8192 #define USBLP_BUF_SIZE 8192
#define DEVICE_ID_SIZE 1024 #define USBLP_DEVICE_ID_SIZE 1024
/* ioctls: */ /* ioctls: */
#define LPGETSTATUS 0x060b /* same as in drivers/char/lp.c */ #define LPGETSTATUS 0x060b /* same as in drivers/char/lp.c */
...@@ -839,7 +839,7 @@ static void *usblp_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -839,7 +839,7 @@ static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
/* Malloc device ID string buffer to the largest expected length, /* Malloc device ID string buffer to the largest expected length,
* since we can re-query it on an ioctl and a dynamic string * since we can re-query it on an ioctl and a dynamic string
* could change in length. */ * 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"); err("out of memory for device_id_string");
goto abort_minor; goto abort_minor;
} }
...@@ -1045,7 +1045,7 @@ static int usblp_cache_device_id_string(struct usblp *usblp) ...@@ -1045,7 +1045,7 @@ static int usblp_cache_device_id_string(struct usblp *usblp)
{ {
int err, length; 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) { if (err < 0) {
dbg("usblp%d: error = %d reading IEEE-1284 Device ID string", dbg("usblp%d: error = %d reading IEEE-1284 Device ID string",
usblp->minor, err); usblp->minor, err);
...@@ -1059,8 +1059,8 @@ static int usblp_cache_device_id_string(struct usblp *usblp) ...@@ -1059,8 +1059,8 @@ static int usblp_cache_device_id_string(struct usblp *usblp)
length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1]; length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1];
if (length < 2) if (length < 2)
length = 2; length = 2;
else if (length >= DEVICE_ID_SIZE) else if (length >= USBLP_DEVICE_ID_SIZE)
length = DEVICE_ID_SIZE - 1; length = USBLP_DEVICE_ID_SIZE - 1;
usblp->device_id_string[length] = '\0'; usblp->device_id_string[length] = '\0';
dbg("usblp%d Device ID string [len=%d]=\"%s\"", 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 ...@@ -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); bus = list_entry(buslist, struct usb_bus, bus_list);
/* recurse through all children of the root hub */ /* recurse through all children of the root hub */
ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0); 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; return ret;
}
total_written += ret; total_written += ret;
} }
up (&usb_bus_list_lock); up (&usb_bus_list_lock);
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <asm/io.h>
#include <asm/irq.h>
#ifdef CONFIG_USB_DEBUG #ifdef CONFIG_USB_DEBUG
#define DEBUG #define DEBUG
......
...@@ -100,7 +100,7 @@ ...@@ -100,7 +100,7 @@
* - lots more testing!! * - 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_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell"
#define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" #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) ...@@ -307,7 +307,6 @@ ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
spin_lock_irqsave (&ohci->lock, flags); spin_lock_irqsave (&ohci->lock, flags);
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
struct ed *ed = dev->ep [i]; struct ed *ed = dev->ep [i];
struct td *tdTailP;
if (!ed) if (!ed)
continue; continue;
...@@ -319,10 +318,7 @@ ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev) ...@@ -319,10 +318,7 @@ ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
case ED_NEW: case ED_NEW:
break; break;
case ED_UNLINK: case ED_UNLINK:
tdTailP = dma_to_td (ohci, td_free (ohci, ed->dummy);
le32_to_cpup (&ed->hwTailP) & 0xfffffff0);
td_free (ohci, tdTailP); /* free dummy td */
hash_free_ed (ohci, ed);
break; break;
case ED_OPER: case ED_OPER:
......
...@@ -440,14 +440,16 @@ static struct ed *ep_add_ed ( ...@@ -440,14 +440,16 @@ static struct ed *ep_add_ed (
spin_unlock_irqrestore (&ohci->lock, flags); spin_unlock_irqrestore (&ohci->lock, flags);
return NULL; return NULL;
} }
ed->dummy = td;
ed->hwTailP = cpu_to_le32 (td->td_dma); 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->state = ED_UNLINK;
ed->type = usb_pipetype (pipe); ed->type = usb_pipetype (pipe);
} }
// FIXME: don't do this if it's linked to the HC, // FIXME: don't do this if it's linked to the HC, or without knowing it's
// we might clobber data toggle or other state ... // 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) ed->hwINFO = cpu_to_le32 (usb_pipedevice (pipe)
| usb_pipeendpoint (pipe) << 7 | usb_pipeendpoint (pipe) << 7
...@@ -523,27 +525,31 @@ td_fill (struct ohci_hcd *ohci, unsigned int info, ...@@ -523,27 +525,31 @@ td_fill (struct ohci_hcd *ohci, unsigned int info,
dma_addr_t data, int len, dma_addr_t data, int len,
struct urb *urb, int index) struct urb *urb, int index)
{ {
volatile struct td *td, *td_pt; struct td *td, *td_pt;
urb_priv_t *urb_priv = urb->hcpriv; urb_priv_t *urb_priv = urb->hcpriv;
int is_iso = info & TD_ISO;
if (index >= urb_priv->length) { if (index >= urb_priv->length) {
err ("internal OHCI error: TD index > length"); err ("internal OHCI error: TD index > length");
return; return;
} }
#if 0 /* aim for only one interrupt per urb. mostly applies to control
/* no interrupt needed except for URB's last TD */ * 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)) if (index != (urb_priv->length - 1))
info |= TD_DI; info |= is_iso ? TD_DI_SET (7) : TD_DI_SET (1);
#endif
/* use this td as the next dummy */ /* use this td as the next dummy */
td_pt = urb_priv->td [index]; td_pt = urb_priv->td [index];
td_pt->hwNextTD = 0; td_pt->hwNextTD = 0;
/* fill the old dummy TD */ /* fill the old dummy TD */
td = urb_priv->td [index] = dma_to_td (ohci, td = urb_priv->td [index] = urb_priv->ed->dummy;
le32_to_cpup (&urb_priv->ed->hwTailP)); urb_priv->ed->dummy = td_pt;
td->ed = urb_priv->ed; td->ed = urb_priv->ed;
td->next_dl_td = NULL; td->next_dl_td = NULL;
...@@ -554,7 +560,7 @@ td_fill (struct ohci_hcd *ohci, unsigned int info, ...@@ -554,7 +560,7 @@ td_fill (struct ohci_hcd *ohci, unsigned int info,
data = 0; data = 0;
td->hwINFO = cpu_to_le32 (info); td->hwINFO = cpu_to_le32 (info);
if ((td->ed->type) == PIPE_ISOCHRONOUS) { if (is_iso) {
td->hwCBP = cpu_to_le32 (data & 0xFFFFF000); td->hwCBP = cpu_to_le32 (data & 0xFFFFF000);
td->ed->intriso.last_iso = info & 0xffff; td->ed->intriso.last_iso = info & 0xffff;
} else { } else {
...@@ -901,6 +907,7 @@ static void finish_unlinks (struct ohci_hcd *ohci, u16 tick) ...@@ -901,6 +907,7 @@ static void finish_unlinks (struct ohci_hcd *ohci, u16 tick)
* [a2] some (earlier) URBs still linked, re-enable * [a2] some (earlier) URBs still linked, re-enable
* (b) finishing ED unlink * (b) finishing ED unlink
* [b1] no URBs queued, ED is truly idle now * [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 * [b2] URBs now queued, link ED back into schedule
* right now we only have (a) * right now we only have (a)
*/ */
...@@ -910,9 +917,6 @@ static void finish_unlinks (struct ohci_hcd *ohci, u16 tick) ...@@ -910,9 +917,6 @@ static void finish_unlinks (struct ohci_hcd *ohci, u16 tick)
if (tdHeadP == tdTailP) { if (tdHeadP == tdTailP) {
if (ed->state == ED_OPER) if (ed->state == ED_OPER)
start_ed_unlink (ohci, ed); start_ed_unlink (ohci, ed);
td_free (ohci, tdTailP);
ed->hwINFO = ED_SKIP;
ed->state = ED_NEW;
} else } else
ed->hwINFO &= ~ED_SKIP; ed->hwINFO &= ~ED_SKIP;
......
...@@ -29,6 +29,7 @@ struct ed { ...@@ -29,6 +29,7 @@ struct ed {
/* rest are purely for the driver's use */ /* rest are purely for the driver's use */
dma_addr_t dma; /* addr of ED */ dma_addr_t dma; /* addr of ED */
struct ed *ed_prev; /* for non-interrupt EDs */ struct ed *ed_prev; /* for non-interrupt EDs */
struct td *dummy;
u8 type; /* PIPE_{BULK,...} */ u8 type; /* PIPE_{BULK,...} */
u8 interval; /* interrupt, isochronous */ u8 interval; /* interrupt, isochronous */
...@@ -63,24 +64,33 @@ struct ed { ...@@ -63,24 +64,33 @@ struct ed {
struct td { struct td {
/* first fields are hardware-specified, le32 */ /* first fields are hardware-specified, le32 */
__u32 hwINFO; /* transfer info bitmask */ __u32 hwINFO; /* transfer info bitmask */
/* hwINFO bits for both general and iso tds: */
#define TD_CC 0xf0000000 /* condition code */ #define TD_CC 0xf0000000 /* condition code */
#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) #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_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_EC 0x0C000000 /* error count */
#define TD_T 0x03000000 /* data toggle state */ #define TD_T 0x03000000 /* data toggle state */
#define TD_T_DATA0 0x02000000 /* DATA0 */ #define TD_T_DATA0 0x02000000 /* DATA0 */
#define TD_T_DATA1 0x03000000 /* DATA1 */ #define TD_T_DATA1 0x03000000 /* DATA1 */
#define TD_T_TOGGLE 0x00000000 /* uses ED_C */ #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 0x00180000 /* direction/pid */
#define TD_DP_SETUP 0x00000000 /* SETUP pid */ #define TD_DP_SETUP 0x00000000 /* SETUP pid */
#define TD_DP_IN 0x00100000 /* IN pid */ #define TD_DP_IN 0x00100000 /* IN pid */
#define TD_DP_OUT 0x00080000 /* OUT pid */ #define TD_DP_OUT 0x00080000 /* OUT pid */
/* 0x00180000 rsvd */ /* 0x00180000 rsvd */
#define TD_R 0x00040000 /* round: short packets OK? */ #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 hwCBP; /* Current Buffer Pointer (or 0) */
__u32 hwNextTD; /* Next TD Pointer */ __u32 hwNextTD; /* Next TD Pointer */
......
...@@ -273,8 +273,6 @@ static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback) ...@@ -273,8 +273,6 @@ static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback)
usb_urb_callback usb_callback; usb_urb_callback usb_callback;
int res; int res;
hpusbscsi->use_count++;
/* we don't answer for anything but our single device on any faked host controller */ /* 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 ( srb->device->lun || srb->device->id || srb->device->channel ) {
if (callback) { if (callback) {
...@@ -341,7 +339,6 @@ static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback) ...@@ -341,7 +339,6 @@ static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback)
} }
out: out:
hpusbscsi->use_count--;
return 0; return 0;
} }
......
...@@ -20,25 +20,25 @@ struct hpusbscsi ...@@ -20,25 +20,25 @@ struct hpusbscsi
int ep_in; int ep_in;
int ep_int; int ep_int;
int interrupt_interval; int interrupt_interval;
int number;
int fragment;
struct Scsi_Host *host; struct Scsi_Host *host;
Scsi_Host_Template ctempl;
int number;
scsi_callback scallback; scsi_callback scallback;
Scsi_Cmnd *srb; Scsi_Cmnd *srb;
u8 sense_command[SENSE_COMMAND_SIZE];
int use_count;
wait_queue_head_t pending; wait_queue_head_t pending;
wait_queue_head_t deathrow; wait_queue_head_t deathrow;
struct urb *dataurb; struct urb *dataurb;
struct urb *controlurb; struct urb *controlurb;
int fragment;
int state; int state;
int current_data_pipe; int current_data_pipe;
Scsi_Host_Template ctempl;
u8 sense_command[SENSE_COMMAND_SIZE];
u8 scsi_state_byte; u8 scsi_state_byte;
}; };
......
...@@ -609,6 +609,7 @@ static int dabusb_open (struct inode *inode, struct file *file) ...@@ -609,6 +609,7 @@ static int dabusb_open (struct inode *inode, struct file *file)
down (&s->mutex); down (&s->mutex);
} }
if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
up(&s->mutex);
err("set_interface failed"); err("set_interface failed");
return -EINVAL; return -EINVAL;
} }
......
/* Driver for Philips webcam /* Driver for Philips webcam
Functions that send various control messages to the webcam, including Functions that send various control messages to the webcam, including
video modes. 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 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 it under the terms of the GNU General Public License as published by
...@@ -78,10 +78,12 @@ ...@@ -78,10 +78,12 @@
#define READ_SHUTTER_FORMATTER 0x0600 #define READ_SHUTTER_FORMATTER 0x0600
#define READ_RED_GAIN_FORMATTER 0x0700 #define READ_RED_GAIN_FORMATTER 0x0700
#define READ_BLUE_GAIN_FORMATTER 0x0800 #define READ_BLUE_GAIN_FORMATTER 0x0800
#define SENSOR_TYPE_FORMATTER1 0x0C00
#define READ_RAW_Y_MEAN_FORMATTER 0x3100 #define READ_RAW_Y_MEAN_FORMATTER 0x3100
#define SET_POWER_SAVE_MODE_FORMATTER 0x3200 #define SET_POWER_SAVE_MODE_FORMATTER 0x3200
#define MIRROR_IMAGE_FORMATTER 0x3300 #define MIRROR_IMAGE_FORMATTER 0x3300
#define LED_FORMATTER 0x3400 #define LED_FORMATTER 0x3400
#define SENSOR_TYPE_FORMATTER2 0x3700
/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */ /* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100 #define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100
...@@ -162,6 +164,21 @@ static struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] = ...@@ -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 #if PWC_DEBUG
...@@ -241,7 +258,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra ...@@ -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); ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (pEntry->compressed) if (pEntry->compressed && pdev->decompressor != NULL)
pdev->decompressor->init(pdev->release, buf, pdev->decompress_data); pdev->decompressor->init(pdev->release, buf, pdev->decompress_data);
/* Set various parameters */ /* Set various parameters */
...@@ -911,7 +928,7 @@ static inline int pwc_get_red_gain(struct pwc_device *pdev) ...@@ -911,7 +928,7 @@ static inline int pwc_get_red_gain(struct pwc_device *pdev)
int ret; int ret;
ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 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, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
PRESET_MANUAL_RED_GAIN_FORMATTER, PRESET_MANUAL_RED_GAIN_FORMATTER,
pdev->vcinterface, pdev->vcinterface,
...@@ -950,7 +967,7 @@ static inline int pwc_get_blue_gain(struct pwc_device *pdev) ...@@ -950,7 +967,7 @@ static inline int pwc_get_blue_gain(struct pwc_device *pdev)
int ret; int ret;
ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 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, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
PRESET_MANUAL_BLUE_GAIN_FORMATTER, PRESET_MANUAL_BLUE_GAIN_FORMATTER,
pdev->vcinterface, pdev->vcinterface,
...@@ -962,6 +979,7 @@ static inline int pwc_get_blue_gain(struct pwc_device *pdev) ...@@ -962,6 +979,7 @@ static inline int pwc_get_blue_gain(struct pwc_device *pdev)
return (buf << 8); return (buf << 8);
} }
/* The following two functions are different, since they only read the /* The following two functions are different, since they only read the
internal red/blue gains, which may be different from the manual internal red/blue gains, which may be different from the manual
gains set or read above. gains set or read above.
...@@ -979,7 +997,7 @@ static inline int pwc_read_red_gain(struct pwc_device *pdev) ...@@ -979,7 +997,7 @@ static inline int pwc_read_red_gain(struct pwc_device *pdev)
&buf, 1, HZ / 2); &buf, 1, HZ / 2);
if (ret < 0) if (ret < 0)
return ret; return ret;
return (buf << 8); return (buf << 8);
} }
...@@ -997,11 +1015,74 @@ static inline int pwc_read_blue_gain(struct pwc_device *pdev) ...@@ -997,11 +1015,74 @@ static inline int pwc_read_blue_gain(struct pwc_device *pdev)
&buf, 1, HZ / 2); &buf, 1, HZ / 2);
if (ret < 0) if (ret < 0)
return ret; return ret;
return (buf << 8); 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) int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
{ {
unsigned char buf[2]; unsigned char buf[2];
...@@ -1055,61 +1136,248 @@ int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value) ...@@ -1055,61 +1136,248 @@ int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
return 0; 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 */ /* End of Add-Ons */
/* ************************************************* */ /* ************************************************* */
int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
{ {
int ret = 0;
switch(cmd) { switch(cmd) {
case VIDIOCPWCRUSER: case VIDIOCPWCRUSER:
{ {
if (pwc_restore_user(pdev)) if (pwc_restore_user(pdev))
return -EINVAL; ret = -EINVAL;
break; break;
} }
case VIDIOCPWCSUSER: case VIDIOCPWCSUSER:
{ {
if (pwc_save_user(pdev)) if (pwc_save_user(pdev))
return -EINVAL; ret = -EINVAL;
break; break;
} }
case VIDIOCPWCFACTORY: case VIDIOCPWCFACTORY:
{ {
if (pwc_restore_factory(pdev)) if (pwc_restore_factory(pdev))
return -EINVAL; ret = -EINVAL;
break; break;
} }
case VIDIOCPWCSCQUAL: case VIDIOCPWCSCQUAL:
{ {
int *qual = arg; int *qual = arg;
int ret;
if (*qual < 0 || *qual > 3) if (*qual < 0 || *qual > 3)
return -EINVAL; ret = -EINVAL;
ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, *qual, pdev->vsnapshot); else
if (ret < 0) ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, *qual, pdev->vsnapshot);
return ret; if (ret >= 0)
pdev->vcompression = *qual; pdev->vcompression = *qual;
break; break;
} }
case VIDIOCPWCGCQUAL: case VIDIOCPWCGCQUAL:
{ {
int *qual = arg; int *qual = arg;
*qual = pdev->vcompression; *qual = pdev->vcompression;
break; 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: case VIDIOCPWCSAGC:
{ {
int *agc = arg; int *agc = arg;
if (pwc_set_agc(pdev, *agc < 0 ? 1 : 0, *agc)) if (pwc_set_agc(pdev, *agc < 0 ? 1 : 0, *agc))
return -EINVAL; ret = -EINVAL;
break; break;
} }
...@@ -1118,29 +1386,21 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) ...@@ -1118,29 +1386,21 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
int *agc = arg; int *agc = arg;
if (pwc_get_agc(pdev, agc)) if (pwc_get_agc(pdev, agc))
return -EINVAL; ret = -EINVAL;
break; break;
} }
case VIDIOCPWCSSHUTTER: case VIDIOCPWCSSHUTTER:
{ {
int *shutter_speed = arg; int *shutter_speed = arg;
int ret;
ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed); ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed);
if (ret < 0)
return ret;
break; break;
} }
/* ************************************************* */
/* Begin of Add-Ons for color compensation */
case VIDIOCPWCSAWB: case VIDIOCPWCSAWB:
{ {
struct pwc_whitebalance *wb = arg; struct pwc_whitebalance *wb = arg;
int ret;
ret = pwc_set_awb(pdev, wb->mode); ret = pwc_set_awb(pdev, wb->mode);
if (ret >= 0 && wb->mode == PWC_WB_MANUAL) { if (ret >= 0 && wb->mode == PWC_WB_MANUAL) {
...@@ -1153,52 +1413,149 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) ...@@ -1153,52 +1413,149 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
case VIDIOCPWCGAWB: case VIDIOCPWCGAWB:
{ {
struct pwc_whitebalance *wb = arg; struct pwc_whitebalance *wb = arg;
memset(wb, 0, sizeof(*wb)); memset(wb, 0, sizeof(*wb));
wb->mode = pwc_get_awb(pdev); wb->mode = pwc_get_awb(pdev);
if (wb->mode < 0) if (wb->mode < 0)
return -EINVAL; ret = -EINVAL;
wb->manual_red = pwc_get_red_gain(pdev); else {
wb->manual_blue = pwc_get_blue_gain(pdev); if (wb->mode == PWC_WB_MANUAL) {
if (wb->mode == PWC_WB_AUTO) { wb->manual_red = pwc_get_red_gain(pdev);
wb->read_red = pwc_read_red_gain(pdev); wb->manual_blue = pwc_get_blue_gain(pdev);
wb->read_blue = pwc_read_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; 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: case VIDIOCPWCSLED:
{ {
int ret;
struct pwc_leds *leds = arg; struct pwc_leds *leds = arg;
ret = pwc_set_leds(pdev, leds->led_on, leds->led_off); ret = pwc_set_leds(pdev, leds->led_on, leds->led_off);
if (ret<0) break;
return ret;
break;
} }
case VIDIOCPWCGLED: case VIDIOCPWCGLED:
{ {
int led;
struct pwc_leds *leds = arg; struct pwc_leds *leds = arg;
led = pwc_get_leds(pdev, &leds->led_on, &leds->led_off); ret = pwc_get_leds(pdev, &leds->led_on, &leds->led_off);
if (led < 0)
return -EINVAL;
break; 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: default:
return -ENOIOCTLCMD; ret = -ENOIOCTLCMD;
break; break;
} }
return 0;
if (ret > 0)
return 0;
return ret;
} }
......
#ifndef PWC_IOCTL_H #ifndef PWC_IOCTL_H
#define 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 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 it under the terms of the GNU General Public License as published by
...@@ -18,7 +18,9 @@ ...@@ -18,7 +18,9 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
/* /* This is pwc-ioctl.h belonging to PWC 8.7 */
/*
Changes Changes
2001/08/03 Alvarado Added ioctl constants to access methods for 2001/08/03 Alvarado Added ioctl constants to access methods for
changing white balance and red/blue gains changing white balance and red/blue gains
...@@ -52,6 +54,14 @@ ...@@ -52,6 +54,14 @@
#define PWC_FPS_SNAPSHOT 0x00400000 #define PWC_FPS_SNAPSHOT 0x00400000
struct pwc_probe
{
char name[32];
int type;
};
/* pwc_whitebalance.mode values */ /* pwc_whitebalance.mode values */
#define PWC_WB_INDOOR 0 #define PWC_WB_INDOOR 0
#define PWC_WB_OUTDOOR 1 #define PWC_WB_OUTDOOR 1
...@@ -63,9 +73,9 @@ ...@@ -63,9 +73,9 @@
Set mode to one of the PWC_WB_* values above. Set mode to one of the PWC_WB_* values above.
*red and *blue are the respective gains of these colour components inside *red and *blue are the respective gains of these colour components inside
the camera; range 0..65535 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. otherwise undefined.
read_red and read_blue are read-only. 'read_red' and 'read_blue' are read-only.
*/ */
struct pwc_whitebalance struct pwc_whitebalance
...@@ -75,6 +85,17 @@ struct pwc_whitebalance ...@@ -75,6 +85,17 @@ struct pwc_whitebalance
int read_red, read_blue; /* R/O */ 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 */ /* Used with VIDIOCPWC[SG]LED */
struct pwc_leds struct pwc_leds
...@@ -104,6 +125,19 @@ struct pwc_leds ...@@ -104,6 +125,19 @@ struct pwc_leds
/* Get preferred compression quality */ /* Get preferred compression quality */
#define VIDIOCPWCGCQUAL _IOR('v', 195, int) #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 */ /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
#define VIDIOCPWCSAGC _IOW('v', 200, int) #define VIDIOCPWCSAGC _IOW('v', 200, int)
/* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */ /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
...@@ -115,9 +149,28 @@ struct pwc_leds ...@@ -115,9 +149,28 @@ struct pwc_leds
#define VIDIOCPWCSAWB _IOW('v', 202, struct pwc_whitebalance) #define VIDIOCPWCSAWB _IOW('v', 202, struct pwc_whitebalance)
#define VIDIOCPWCGAWB _IOR('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) #define VIDIOCPWCSLED _IOW('v', 205, struct pwc_leds)
/* Get state of LED; int range 0..65535 */
#define VIDIOCPWCGLED _IOR('v', 205, struct pwc_leds) #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 #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 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 it under the terms of the GNU General Public License as published by
...@@ -60,8 +60,8 @@ ...@@ -60,8 +60,8 @@
/* Version block */ /* Version block */
#define PWC_MAJOR 8 #define PWC_MAJOR 8
#define PWC_MINOR 5 #define PWC_MINOR 7
#define PWC_VERSION "8.5" #define PWC_VERSION "8.7"
#define PWC_NAME "pwc" #define PWC_NAME "pwc"
/* Turn certain features on/off */ /* Turn certain features on/off */
...@@ -247,6 +247,7 @@ extern int pwc_get_saturation(struct pwc_device *pdev); ...@@ -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_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_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_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 */ /* Power down or up the camera; not supported by all models */
extern int pwc_camera_power(struct pwc_device *pdev, int power); extern int pwc_camera_power(struct pwc_device *pdev, int power);
......
...@@ -1330,7 +1330,13 @@ static int se401_init(struct usb_se401 *se401) ...@@ -1330,7 +1330,13 @@ static int se401_init(struct usb_se401 *se401)
se401->sizes=cp[4]+cp[5]*256; se401->sizes=cp[4]+cp[5]*256;
se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
if (!se401->width)
return 1;
se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
if (!se401->height) {
kfree(se401->width);
return 1;
}
for (i=0; i<se401->sizes; i++) { for (i=0; i<se401->sizes; i++) {
se401->width[i]=cp[6+i*4+0]+cp[6+i*4+1]*256; 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; 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) ...@@ -426,6 +426,7 @@ static void CDC_SetEthernetPacketFilter (ether_dev_t *ether_dev)
} }
#endif #endif
static void CDCEther_set_multicast( struct net_device *net ) static void CDCEther_set_multicast( struct net_device *net )
{ {
ether_dev_t *ether_dev = net->priv; ether_dev_t *ether_dev = net->priv;
......
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