/* Driver for Philips webcam
Functions that send various control messages to the webcam, including
video modes.
(C) 1999-2003 Nemosoft Unv.
(C) 2004-2006 Luc Saillard (luc@saillard.org)
(C) 2011 Hans de Goede <hdegoede@redhat.com>
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
Changes
2001/08/03 Alvarado Added methods for changing white balance and
red/green gains
*/
/* Control functions for the cam; brightness, contrast, video mode, etc. */
#ifdef __KERNEL__
#include <asm/uaccess.h>
#endif
#include <asm/errno.h>
#include "pwc.h"
#include "pwc-kiara.h"
#include "pwc-timon.h"
#include "pwc-dec1.h"
#include "pwc-dec23.h"
/* Selectors for status controls used only in this file */
#define GET_STATUS_B00 0x0B00
#define SENSOR_TYPE_FORMATTER1 0x0C00
#define GET_STATUS_3000 0x3000
#define READ_RAW_Y_MEAN_FORMATTER 0x3100
#define SET_POWER_SAVE_MODE_FORMATTER 0x3200
#define MIRROR_IMAGE_FORMATTER 0x3300
#define LED_FORMATTER 0x3400
#define LOWLIGHT 0x3500
#define GET_STATUS_3600 0x3600
#define SENSOR_TYPE_FORMATTER2 0x3700
#define GET_STATUS_3800 0x3800
#define GET_STATUS_4000 0x4000
#define GET_STATUS_4100 0x4100 /* Get */
#define CTL_STATUS_4200 0x4200 /* [GS] 1 */
/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100
static const char *size2name[PSZ_MAX] =
{
"subQCIF",
"QSIF",
"QCIF",
"SIF",
"CIF",
"VGA",
};
/********/
/* Entries for the Nala (645/646) camera; the Nala doesn't have compression
preferences, so you either get compressed or non-compressed streams.
An alternate value of 0 means this mode is not available at all.
*/
#define PWC_FPS_MAX_NALA 8
struct Nala_table_entry {
char alternate; /* USB alternate setting */
int compressed; /* Compressed yes/no */
unsigned char mode[3]; /* precomputed mode table */
};
static unsigned int Nala_fps_vector[PWC_FPS_MAX_NALA] = { 4, 5, 7, 10, 12, 15, 20, 24 };
static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] =
{
#include "pwc-nala.h"
};
static void pwc_set_image_buffer_size(struct pwc_device *pdev);
/****************************************************************************/
static int _send_control_msg(struct pwc_device *pdev,
u8 request, u16 value, int index, void *buf, int buflen)
{
int rc;
void *kbuf = NULL;
if (buflen) {
kbuf = kmemdup(buf, buflen, GFP_KERNEL); /* not allowed on stack */
if (kbuf == NULL)
return -ENOMEM;
}
rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
request,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value,
index,
kbuf, buflen, USB_CTRL_SET_TIMEOUT);
kfree(kbuf);
return rc;
}
static int recv_control_msg(struct pwc_device *pdev,
u8 request, u16 value, void *buf, int buflen)
{
int rc;
void *kbuf = kmalloc(buflen, GFP_KERNEL); /* not allowed on stack */
if (kbuf == NULL)
return -ENOMEM;
rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
request,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value,
pdev->vcinterface,
kbuf, buflen, USB_CTRL_GET_TIMEOUT);
memcpy(buf, kbuf, buflen);
kfree(kbuf);