M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
config USB_PWC
tristate "USB Philips Cameras"
depends on VIDEO_V4L2
select VIDEOBUF2_VMALLOC
---help---
Say Y or M here if you want to use one of these Philips & OEM
webcams:
* Philips PCA645, PCA646
* Philips PCVC675, PCVC680, PCVC690
* Philips PCVC720/40, PCVC730, PCVC740, PCVC750
* Philips SPC900NC
* Askey VC010
* Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro'
and 'Orbit'/'Sphere'
* Samsung MPC-C10, MPC-C30
* Creative Webcam 5, Pro Ex
* SOTEC Afina Eye
* Visionite VCS-UC300, VCS-UM100
The PCA635, PCVC665 and PCVC720/20 are not supported by this driver
and never will be, but the 665 and 720/20 are supported by other
drivers.
Some newer logitech webcams are not handled by this driver but by the
Usb Video Class driver (linux-uvc).
The built-in microphone is enabled by selecting USB Audio support.
To compile this driver as a module, choose M here: the
module will be called pwc.
config USB_PWC_DEBUG
bool "USB Philips Cameras verbose debug"
depends on USB_PWC
help
Say Y here in order to have the pwc driver generate verbose debugging
messages.
A special module options 'trace' is used to control the verbosity.
config USB_PWC_INPUT_EVDEV
bool "USB Philips Cameras input events device support"
default y
depends on USB_PWC && (USB_PWC=INPUT || INPUT=y)
---help---
This option makes USB Philips cameras register the snapshot button as
an input device to report button events.
If you are in doubt, say Y.

View File

@@ -0,0 +1,4 @@
pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-v4l.o pwc-uncompress.o
pwc-objs += pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o
obj-$(CONFIG_USB_PWC) += pwc.o

View File

@@ -0,0 +1,236 @@
This file contains some additional information for the Philips and OEM webcams.
E-mail: webcam@smcc.demon.nl Last updated: 2004-01-19
Site: http://www.smcc.demon.nl/webcam/
As of this moment, the following cameras are supported:
* Philips PCA645
* Philips PCA646
* Philips PCVC675
* Philips PCVC680
* Philips PCVC690
* Philips PCVC720/40
* Philips PCVC730
* Philips PCVC740
* Philips PCVC750
* Askey VC010
* Creative Labs Webcam 5
* Creative Labs Webcam Pro Ex
* Logitech QuickCam 3000 Pro
* Logitech QuickCam 4000 Pro
* Logitech QuickCam Notebook Pro
* Logitech QuickCam Zoom
* Logitech QuickCam Orbit
* Logitech QuickCam Sphere
* Samsung MPC-C10
* Samsung MPC-C30
* Sotec Afina Eye
* AME CU-001
* Visionite VCS-UM100
* Visionite VCS-UC300
The main webpage for the Philips driver is at the address above. It contains
a lot of extra information, a FAQ, and the binary plugin 'PWCX'. This plugin
contains decompression routines that allow you to use higher image sizes and
framerates; in addition the webcam uses less bandwidth on the USB bus (handy
if you want to run more than 1 camera simultaneously). These routines fall
under a NDA, and may therefore not be distributed as source; however, its use
is completely optional.
You can build this code either into your kernel, or as a module. I recommend
the latter, since it makes troubleshooting a lot easier. The built-in
microphone is supported through the USB Audio class.
When you load the module you can set some default settings for the
camera; some programs depend on a particular image-size or -format and
don't know how to set it properly in the driver. The options are:
size
Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or
'vga', for an image size of resp. 128x96, 160x120, 176x144,
320x240, 352x288 and 640x480 (of course, only for those cameras that
support these resolutions).
fps
Specifies the desired framerate. Is an integer in the range of 4-30.
fbufs
This parameter specifies the number of internal buffers to use for storing
frames from the cam. This will help if the process that reads images from
the cam is a bit slow or momentarily busy. However, on slow machines it
only introduces lag, so choose carefully. The default is 3, which is
reasonable. You can set it between 2 and 5.
mbufs
This is an integer between 1 and 10. It will tell the module the number of
buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends.
The default is 2, which is adequate for most applications (double
buffering).
Should you experience a lot of 'Dumping frame...' messages during
grabbing with a tool that uses mmap(), you might want to increase if.
However, it doesn't really buffer images, it just gives you a bit more
slack when your program is behind. But you need a multi-threaded or
forked program to really take advantage of these buffers.
The absolute maximum is 10, but don't set it too high! Every buffer takes
up 460 KB of RAM, so unless you have a lot of memory setting this to
something more than 4 is an absolute waste. This memory is only
allocated during open(), so nothing is wasted when the camera is not in
use.
power_save
When power_save is enabled (set to 1), the module will try to shut down
the cam on close() and re-activate on open(). This will save power and
turn off the LED. Not all cameras support this though (the 645 and 646
don't have power saving at all), and some models don't work either (they
will shut down, but never wake up). Consider this experimental. By
default this option is disabled.
compression (only useful with the plugin)
With this option you can control the compression factor that the camera
uses to squeeze the image through the USB bus. You can set the
parameter between 0 and 3:
0 = prefer uncompressed images; if the requested mode is not available
in an uncompressed format, the driver will silently switch to low
compression.
1 = low compression.
2 = medium compression.
3 = high compression.
High compression takes less bandwidth of course, but it could also
introduce some unwanted artefacts. The default is 2, medium compression.
See the FAQ on the website for an overview of which modes require
compression.
The compression parameter does not apply to the 645 and 646 cameras
and OEM models derived from those (only a few). Most cams honour this
parameter.
leds
This settings takes 2 integers, that define the on/off time for the LED
(in milliseconds). One of the interesting things that you can do with
this is let the LED blink while the camera is in use. This:
leds=500,500
will blink the LED once every second. But with:
leds=0,0
the LED never goes on, making it suitable for silent surveillance.
By default the camera's LED is on solid while in use, and turned off
when the camera is not used anymore.
This parameter works only with the ToUCam range of cameras (720, 730, 740,
750) and OEMs. For other cameras this command is silently ignored, and
the LED cannot be controlled.
Finally: this parameters does not take effect UNTIL the first time you
open the camera device. Until then, the LED remains on.
dev_hint
A long standing problem with USB devices is their dynamic nature: you
never know what device a camera gets assigned; it depends on module load
order, the hub configuration, the order in which devices are plugged in,
and the phase of the moon (i.e. it can be random). With this option you
can give the driver a hint as to what video device node (/dev/videoX) it
should use with a specific camera. This is also handy if you have two
cameras of the same model.
A camera is specified by its type (the number from the camera model,
like PCA645, PCVC750VC, etc) and optionally the serial number (visible
in /proc/bus/usb/devices). A hint consists of a string with the following
format:
[type[.serialnumber]:]node
The square brackets mean that both the type and the serialnumber are
optional, but a serialnumber cannot be specified without a type (which
would be rather pointless). The serialnumber is separated from the type
by a '.'; the node number by a ':'.
This somewhat cryptic syntax is best explained by a few examples:
dev_hint=3,5 The first detected cam gets assigned
/dev/video3, the second /dev/video5. Any
other cameras will get the first free
available slot (see below).
dev_hint=645:1,680:2 The PCA645 camera will get /dev/video1,
and a PCVC680 /dev/video2.
dev_hint=645.0123:3,645.4567:0 The PCA645 camera with serialnumber
0123 goes to /dev/video3, the same
camera model with the 4567 serial
gets /dev/video0.
dev_hint=750:1,4,5,6 The PCVC750 camera will get /dev/video1, the
next 3 Philips cams will use /dev/video4
through /dev/video6.
Some points worth knowing:
- Serialnumbers are case sensitive and must be written full, including
leading zeroes (it's treated as a string).
- If a device node is already occupied, registration will fail and
the webcam is not available.
- You can have up to 64 video devices; be sure to make enough device
nodes in /dev if you want to spread the numbers.
After /dev/video9 comes /dev/video10 (not /dev/videoA).
- If a camera does not match any dev_hint, it will simply get assigned
the first available device node, just as it used to be.
trace
In order to better detect problems, it is now possible to turn on a
'trace' of some of the calls the module makes; it logs all items in your
kernel log at debug level.
The trace variable is a bitmask; each bit represents a certain feature.
If you want to trace something, look up the bit value(s) in the table
below, add the values together and supply that to the trace variable.
Value Value Description Default
(dec) (hex)
1 0x1 Module initialization; this will log messages On
while loading and unloading the module
2 0x2 probe() and disconnect() traces On
4 0x4 Trace open() and close() calls Off
8 0x8 read(), mmap() and associated ioctl() calls Off
16 0x10 Memory allocation of buffers, etc. Off
32 0x20 Showing underflow, overflow and Dumping frame On
messages
64 0x40 Show viewport and image sizes Off
128 0x80 PWCX debugging Off
For example, to trace the open() & read() functions, sum 8 + 4 = 12,
so you would supply trace=12 during insmod or modprobe. If
you want to turn the initialization and probing tracing off, set trace=0.
The default value for trace is 35 (0x23).
Example:
# modprobe pwc size=cif fps=15 power_save=1
The fbufs, mbufs and trace parameters are global and apply to all connected
cameras. Each camera has its own set of buffers.
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.
The compression parameter is semiglobal; it sets the initial compression
preference for all camera's, but this parameter can be set per camera with
the VIDIOCPWCSCQUAL ioctl() call.
All parameters are optional.

View File

@@ -0,0 +1,553 @@
/* 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 int recv_control_msg(struct pwc_device *pdev,
u8 request, u16 value, int recv_count)
{
int rc;
rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
request,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value, pdev->vcinterface,
pdev->ctrl_buf, recv_count, USB_CTRL_GET_TIMEOUT);
if (rc < 0)
PWC_ERROR("recv_control_msg error %d req %02x val %04x\n",
rc, request, value);
return rc;
}
static inline int send_video_command(struct pwc_device *pdev,
int index, const unsigned char *buf, int buflen)
{
int rc;
memcpy(pdev->ctrl_buf, buf, buflen);
rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
SET_EP_STREAM_CTL,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
VIDEO_OUTPUT_CONTROL_FORMATTER, index,
pdev->ctrl_buf, buflen, USB_CTRL_SET_TIMEOUT);
if (rc >= 0)
memcpy(pdev->cmd_buf, buf, buflen);
else
PWC_ERROR("send_video_command error %d\n", rc);
return rc;
}
int send_control_msg(struct pwc_device *pdev,
u8 request, u16 value, void *buf, int buflen)
{
return 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, USB_CTRL_SET_TIMEOUT);
}
static int set_video_mode_Nala(struct pwc_device *pdev, int size, int pixfmt,
int frames, int *compression, int send_to_cam)
{
int fps, ret = 0;
struct Nala_table_entry *pEntry;
int frames2frames[31] =
{ /* closest match of framerate */
0, 0, 0, 0, 4, /* 0-4 */
5, 5, 7, 7, 10, /* 5-9 */
10, 10, 12, 12, 15, /* 10-14 */
15, 15, 15, 20, 20, /* 15-19 */
20, 20, 20, 24, 24, /* 20-24 */
24, 24, 24, 24, 24, /* 25-29 */
24 /* 30 */
};
int frames2table[31] =
{ 0, 0, 0, 0, 0, /* 0-4 */
1, 1, 1, 2, 2, /* 5-9 */
3, 3, 4, 4, 4, /* 10-14 */
5, 5, 5, 5, 5, /* 15-19 */
6, 6, 6, 6, 7, /* 20-24 */
7, 7, 7, 7, 7, /* 25-29 */
7 /* 30 */
};
if (size < 0 || size > PSZ_CIF)
return -EINVAL;
if (frames < 4)
frames = 4;
else if (frames > 25)
frames = 25;
frames = frames2frames[frames];
fps = frames2table[frames];
pEntry = &Nala_table[size][fps];
if (pEntry->alternate == 0)
return -EINVAL;
if (send_to_cam)
ret = send_video_command(pdev, pdev->vendpoint,
pEntry->mode, 3);
if (ret < 0)
return ret;
if (pEntry->compressed && pixfmt == V4L2_PIX_FMT_YUV420)
pwc_dec1_init(pdev, pEntry->mode);
/* Set various parameters */
pdev->pixfmt = pixfmt;
pdev->vframes = frames;
pdev->valternate = pEntry->alternate;
pdev->width = pwc_image_sizes[size][0];
pdev->height = pwc_image_sizes[size][1];
pdev->frame_size = (pdev->width * pdev->height * 3) / 2;
if (pEntry->compressed) {
if (pdev->release < 5) { /* 4 fold compression */
pdev->vbandlength = 528;
pdev->frame_size /= 4;
}
else {
pdev->vbandlength = 704;
pdev->frame_size /= 3;
}
}
else
pdev->vbandlength = 0;
/* Let pwc-if.c:isoc_init know we don't support higher compression */
*compression = 3;
return 0;
}
static int set_video_mode_Timon(struct pwc_device *pdev, int size, int pixfmt,
int frames, int *compression, int send_to_cam)
{
const struct Timon_table_entry *pChoose;
int fps, ret = 0;
if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
return -EINVAL;
if (frames < 5)
frames = 5;
else if (size == PSZ_VGA && frames > 15)
frames = 15;
else if (frames > 30)
frames = 30;
fps = (frames / 5) - 1;
/* Find a supported framerate with progressively higher compression */
pChoose = NULL;
while (*compression <= 3) {
pChoose = &Timon_table[size][fps][*compression];
if (pChoose->alternate != 0)
break;
(*compression)++;
}
if (pChoose == NULL || pChoose->alternate == 0)
return -ENOENT; /* Not supported. */
if (send_to_cam)
ret = send_video_command(pdev, pdev->vendpoint,
pChoose->mode, 13);
if (ret < 0)
return ret;
if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
pwc_dec23_init(pdev, pChoose->mode);
/* Set various parameters */
pdev->pixfmt = pixfmt;
pdev->vframes = (fps + 1) * 5;
pdev->valternate = pChoose->alternate;
pdev->width = pwc_image_sizes[size][0];
pdev->height = pwc_image_sizes[size][1];
pdev->vbandlength = pChoose->bandlength;
if (pChoose->bandlength > 0)
pdev->frame_size = (pChoose->bandlength * pdev->height) / 4;
else
pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
return 0;
}
static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int pixfmt,
int frames, int *compression, int send_to_cam)
{
const struct Kiara_table_entry *pChoose = NULL;
int fps, ret = 0;
if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
return -EINVAL;
if (frames < 5)
frames = 5;
else if (size == PSZ_VGA && frames > 15)
frames = 15;
else if (frames > 30)
frames = 30;
fps = (frames / 5) - 1;
/* Find a supported framerate with progressively higher compression */
while (*compression <= 3) {
pChoose = &Kiara_table[size][fps][*compression];
if (pChoose->alternate != 0)
break;
(*compression)++;
}
if (pChoose == NULL || pChoose->alternate == 0)
return -ENOENT; /* Not supported. */
/* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
if (send_to_cam)
ret = send_video_command(pdev, 4, pChoose->mode, 12);
if (ret < 0)
return ret;
if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
pwc_dec23_init(pdev, pChoose->mode);
/* All set and go */
pdev->pixfmt = pixfmt;
pdev->vframes = (fps + 1) * 5;
pdev->valternate = pChoose->alternate;
pdev->width = pwc_image_sizes[size][0];
pdev->height = pwc_image_sizes[size][1];
pdev->vbandlength = pChoose->bandlength;
if (pdev->vbandlength > 0)
pdev->frame_size = (pdev->vbandlength * pdev->height) / 4;
else
pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vbandlength=%d\n",
pdev->frame_size, pdev->vframes, size, pdev->vbandlength);
return 0;
}
int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
int pixfmt, int frames, int *compression, int send_to_cam)
{
int ret, size;
PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n",
width, height, frames, pixfmt);
size = pwc_get_size(pdev, width, height);
PWC_TRACE("decode_size = %d.\n", size);
if (DEVICE_USE_CODEC1(pdev->type)) {
ret = set_video_mode_Nala(pdev, size, pixfmt, frames,
compression, send_to_cam);
} else if (DEVICE_USE_CODEC3(pdev->type)) {
ret = set_video_mode_Kiara(pdev, size, pixfmt, frames,
compression, send_to_cam);
} else {
ret = set_video_mode_Timon(pdev, size, pixfmt, frames,
compression, send_to_cam);
}
if (ret < 0) {
PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
return ret;
}
pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
PWC_DEBUG_SIZE("Set resolution to %dx%d\n", pdev->width, pdev->height);
return 0;
}
static unsigned int pwc_get_fps_Nala(struct pwc_device *pdev, unsigned int index, unsigned int size)
{
unsigned int i;
for (i = 0; i < PWC_FPS_MAX_NALA; i++) {
if (Nala_table[size][i].alternate) {
if (index--==0) return Nala_fps_vector[i];
}
}
return 0;
}
static unsigned int pwc_get_fps_Kiara(struct pwc_device *pdev, unsigned int index, unsigned int size)
{
unsigned int i;
for (i = 0; i < PWC_FPS_MAX_KIARA; i++) {
if (Kiara_table[size][i][3].alternate) {
if (index--==0) return Kiara_fps_vector[i];
}
}
return 0;
}
static unsigned int pwc_get_fps_Timon(struct pwc_device *pdev, unsigned int index, unsigned int size)
{
unsigned int i;
for (i=0; i < PWC_FPS_MAX_TIMON; i++) {
if (Timon_table[size][i][3].alternate) {
if (index--==0) return Timon_fps_vector[i];
}
}
return 0;
}
unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size)
{
unsigned int ret;
if (DEVICE_USE_CODEC1(pdev->type)) {
ret = pwc_get_fps_Nala(pdev, index, size);
} else if (DEVICE_USE_CODEC3(pdev->type)) {
ret = pwc_get_fps_Kiara(pdev, index, size);
} else {
ret = pwc_get_fps_Timon(pdev, index, size);
}
return ret;
}
int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
{
int ret;
ret = recv_control_msg(pdev, request, value, 1);
if (ret < 0)
return ret;
*data = pdev->ctrl_buf[0];
return 0;
}
int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data)
{
int ret;
pdev->ctrl_buf[0] = data;
ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 1);
if (ret < 0)
return ret;
return 0;
}
int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
{
int ret;
ret = recv_control_msg(pdev, request, value, 1);
if (ret < 0)
return ret;
*data = ((s8 *)pdev->ctrl_buf)[0];
return 0;
}
int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
{
int ret;
ret = recv_control_msg(pdev, request, value, 2);
if (ret < 0)
return ret;
*data = (pdev->ctrl_buf[1] << 8) | pdev->ctrl_buf[0];
return 0;
}
int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data)
{
int ret;
pdev->ctrl_buf[0] = data & 0xff;
pdev->ctrl_buf[1] = data >> 8;
ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 2);
if (ret < 0)
return ret;
return 0;
}
int pwc_button_ctrl(struct pwc_device *pdev, u16 value)
{
int ret;
ret = send_control_msg(pdev, SET_STATUS_CTL, value, NULL, 0);
if (ret < 0)
return ret;
return 0;
}
/* POWER */
void pwc_camera_power(struct pwc_device *pdev, int power)
{
int r;
if (!pdev->power_save)
return;
if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
return; /* Not supported by Nala or Timon < release 6 */
if (power)
pdev->ctrl_buf[0] = 0x00; /* active */
else
pdev->ctrl_buf[0] = 0xFF; /* power save */
r = send_control_msg(pdev, SET_STATUS_CTL,
SET_POWER_SAVE_MODE_FORMATTER, pdev->ctrl_buf, 1);
if (r < 0)
PWC_ERROR("Failed to power %s camera (%d)\n",
power ? "on" : "off", r);
}
int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
{
int r;
if (pdev->type < 730)
return 0;
on_value /= 100;
off_value /= 100;
if (on_value < 0)
on_value = 0;
if (on_value > 0xff)
on_value = 0xff;
if (off_value < 0)
off_value = 0;
if (off_value > 0xff)
off_value = 0xff;
pdev->ctrl_buf[0] = on_value;
pdev->ctrl_buf[1] = off_value;
r = send_control_msg(pdev,
SET_STATUS_CTL, LED_FORMATTER, pdev->ctrl_buf, 2);
if (r < 0)
PWC_ERROR("Failed to set LED on/off time (%d)\n", r);
return r;
}
#ifdef CONFIG_USB_PWC_DEBUG
int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
{
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 = recv_control_msg(pdev, GET_STATUS_CTL, request, 1);
if (ret < 0)
return ret;
if (pdev->type < 675)
*sensor = pdev->ctrl_buf[0] | 0x100;
else
*sensor = pdev->ctrl_buf[0];
return 0;
}
#endif

View File

@@ -0,0 +1,32 @@
/* Linux driver for Philips webcam
Decompression for chipset version 1
(C) 2004-2006 Luc Saillard (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
*/
#include "pwc.h"
void pwc_dec1_init(struct pwc_device *pdev, const unsigned char *cmd)
{
struct pwc_dec1_private *pdec = &pdev->dec1;
pdec->version = pdev->release;
}

View File

@@ -0,0 +1,39 @@
/* Linux driver for Philips webcam
(C) 2004-2006 Luc Saillard (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
*/
#ifndef PWC_DEC1_H
#define PWC_DEC1_H
#include <linux/mutex.h>
struct pwc_device;
struct pwc_dec1_private
{
int version;
};
void pwc_dec1_init(struct pwc_device *pdev, const unsigned char *cmd);
#endif

View File

@@ -0,0 +1,691 @@
/* Linux driver for Philips webcam
Decompression for chipset version 2 et 3
(C) 2004-2006 Luc Saillard (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
*/
#include "pwc-timon.h"
#include "pwc-kiara.h"
#include "pwc-dec23.h"
#include <linux/string.h>
#include <linux/slab.h>
/*
* USE_LOOKUP_TABLE_TO_CLAMP
* 0: use a C version of this tests: { a<0?0:(a>255?255:a) }
* 1: use a faster lookup table for cpu with a big cache (intel)
*/
#define USE_LOOKUP_TABLE_TO_CLAMP 1
/*
* UNROLL_LOOP_FOR_COPYING_BLOCK
* 0: use a loop for a smaller code (but little slower)
* 1: when unrolling the loop, gcc produces some faster code (perhaps only
* valid for intel processor class). Activating this option, automaticaly
* activate USE_LOOKUP_TABLE_TO_CLAMP
*/
#define UNROLL_LOOP_FOR_COPY 1
#if UNROLL_LOOP_FOR_COPY
# undef USE_LOOKUP_TABLE_TO_CLAMP
# define USE_LOOKUP_TABLE_TO_CLAMP 1
#endif
static void build_subblock_pattern(struct pwc_dec23_private *pdec)
{
static const unsigned int initial_values[12] = {
-0x526500, -0x221200, 0x221200, 0x526500,
-0x3de200, 0x3de200,
-0x6db480, -0x2d5d00, 0x2d5d00, 0x6db480,
-0x12c200, 0x12c200
};
static const unsigned int values_derivated[12] = {
0xa4ca, 0x4424, -0x4424, -0xa4ca,
0x7bc4, -0x7bc4,
0xdb69, 0x5aba, -0x5aba, -0xdb69,
0x2584, -0x2584
};
unsigned int temp_values[12];
int i, j;
memcpy(temp_values, initial_values, sizeof(initial_values));
for (i = 0; i < 256; i++) {
for (j = 0; j < 12; j++) {
pdec->table_subblock[i][j] = temp_values[j];
temp_values[j] += values_derivated[j];
}
}
}
static void build_bit_powermask_table(struct pwc_dec23_private *pdec)
{
unsigned char *p;
unsigned int bit, byte, mask, val;
unsigned int bitpower = 1;
for (bit = 0; bit < 8; bit++) {
mask = bitpower - 1;
p = pdec->table_bitpowermask[bit];
for (byte = 0; byte < 256; byte++) {
val = (byte & mask);
if (byte & bitpower)
val = -val;
*p++ = val;
}
bitpower<<=1;
}
}
static void build_table_color(const unsigned int romtable[16][8],
unsigned char p0004[16][1024],
unsigned char p8004[16][256])
{
int compression_mode, j, k, bit, pw;
unsigned char *p0, *p8;
const unsigned int *r;
/* We have 16 compressions tables */
for (compression_mode = 0; compression_mode < 16; compression_mode++) {
p0 = p0004[compression_mode];
p8 = p8004[compression_mode];
r = romtable[compression_mode];
for (j = 0; j < 8; j++, r++, p0 += 128) {
for (k = 0; k < 16; k++) {
if (k == 0)
bit = 1;
else if (k >= 1 && k < 3)
bit = (r[0] >> 15) & 7;
else if (k >= 3 && k < 6)
bit = (r[0] >> 12) & 7;
else if (k >= 6 && k < 10)
bit = (r[0] >> 9) & 7;
else if (k >= 10 && k < 13)
bit = (r[0] >> 6) & 7;
else if (k >= 13 && k < 15)
bit = (r[0] >> 3) & 7;
else
bit = (r[0]) & 7;
if (k == 0)
*p8++ = 8;
else
*p8++ = j - bit;
*p8++ = bit;
pw = 1 << bit;
p0[k + 0x00] = (1 * pw) + 0x80;
p0[k + 0x10] = (2 * pw) + 0x80;
p0[k + 0x20] = (3 * pw) + 0x80;
p0[k + 0x30] = (4 * pw) + 0x80;
p0[k + 0x40] = (-1 * pw) + 0x80;
p0[k + 0x50] = (-2 * pw) + 0x80;
p0[k + 0x60] = (-3 * pw) + 0x80;
p0[k + 0x70] = (-4 * pw) + 0x80;
} /* end of for (k=0; k<16; k++, p8++) */
} /* end of for (j=0; j<8; j++ , table++) */
} /* end of foreach compression_mode */
}
/*
*
*/
static void fill_table_dc00_d800(struct pwc_dec23_private *pdec)
{
#define SCALEBITS 15
#define ONE_HALF (1UL << (SCALEBITS - 1))
int i;
unsigned int offset1 = ONE_HALF;
unsigned int offset2 = 0x0000;
for (i=0; i<256; i++) {
pdec->table_dc00[i] = offset1 & ~(ONE_HALF);
pdec->table_d800[i] = offset2;
offset1 += 0x7bc4;
offset2 += 0x7bc4;
}
}
/*
* To decode the stream:
* if look_bits(2) == 0: # op == 2 in the lookup table
* skip_bits(2)
* end of the stream
* elif look_bits(3) == 7: # op == 1 in the lookup table
* skip_bits(3)
* yyyy = get_bits(4)
* xxxx = get_bits(8)
* else: # op == 0 in the lookup table
* skip_bits(x)
*
* For speedup processing, we build a lookup table and we takes the first 6 bits.
*
* struct {
* unsigned char op; // operation to execute
* unsigned char bits; // bits use to perform operation
* unsigned char offset1; // offset to add to access in the table_0004 % 16
* unsigned char offset2; // offset to add to access in the table_0004
* }
*
* How to build this table ?
* op == 2 when (i%4)==0
* op == 1 when (i%8)==7
* op == 0 otherwise
*
*/
static const unsigned char hash_table_ops[64*4] = {
0x02, 0x00, 0x00, 0x00,
0x00, 0x03, 0x01, 0x00,
0x00, 0x04, 0x01, 0x10,
0x00, 0x06, 0x01, 0x30,
0x02, 0x00, 0x00, 0x00,
0x00, 0x03, 0x01, 0x40,
0x00, 0x05, 0x01, 0x20,
0x01, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00,
0x00, 0x03, 0x01, 0x00,
0x00, 0x04, 0x01, 0x50,
0x00, 0x05, 0x02, 0x00,
0x02, 0x00, 0x00, 0x00,
0x00, 0x03, 0x01, 0x40,
0x00, 0x05, 0x03, 0x00,
0x01, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00,
0x00, 0x03, 0x01, 0x00,
0x00, 0x04, 0x01, 0x10,
0x00, 0x06, 0x02, 0x10,
0x02, 0x00, 0x00, 0x00,
0x00, 0x03, 0x01, 0x40,
0x00, 0x05, 0x01, 0x60,
0x01, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00,
0x00, 0x03, 0x01, 0x00,
0x00, 0x04, 0x01, 0x50,
0x00, 0x05, 0x02, 0x40,
0x02, 0x00, 0x00, 0x00,
0x00, 0x03, 0x01, 0x40,
0x00, 0x05, 0x03, 0x40,
0x01, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00,
0x00, 0x03, 0x01, 0x00,
0x00, 0x04, 0x01, 0x10,
0x00, 0x06, 0x01, 0x70,
0x02, 0x00, 0x00, 0x00,
0x00, 0x03, 0x01, 0x40,
0x00, 0x05, 0x01, 0x20,
0x01, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00,
0x00, 0x03, 0x01, 0x00,
0x00, 0x04, 0x01, 0x50,
0x00, 0x05, 0x02, 0x00,
0x02, 0x00, 0x00, 0x00,
0x00, 0x03, 0x01, 0x40,
0x00, 0x05, 0x03, 0x00,
0x01, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00,
0x00, 0x03, 0x01, 0x00,
0x00, 0x04, 0x01, 0x10,
0x00, 0x06, 0x02, 0x50,
0x02, 0x00, 0x00, 0x00,
0x00, 0x03, 0x01, 0x40,
0x00, 0x05, 0x01, 0x60,
0x01, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00,
0x00, 0x03, 0x01, 0x00,
0x00, 0x04, 0x01, 0x50,
0x00, 0x05, 0x02, 0x40,
0x02, 0x00, 0x00, 0x00,
0x00, 0x03, 0x01, 0x40,
0x00, 0x05, 0x03, 0x40,
0x01, 0x00, 0x00, 0x00
};
/*
*
*/
static const unsigned int MulIdx[16][16] = {
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,},
{0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,},
{4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,},
{6, 7, 8, 9, 7, 10, 11, 8, 8, 11, 10, 7, 9, 8, 7, 6,},
{4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,},
{1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,},
{0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,},
{0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,},
{1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,},
{7, 10, 11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8, 11, 10, 7,},
{4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,},
{7, 9, 6, 8, 10, 8, 7, 11, 11, 7, 8, 10, 8, 6, 9, 7,},
{1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,},
{1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,},
{10, 8, 7, 11, 8, 6, 9, 7, 7, 9, 6, 8, 11, 7, 8, 10}
};
#if USE_LOOKUP_TABLE_TO_CLAMP
#define MAX_OUTER_CROP_VALUE (512)
static unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE];
#define CLAMP(x) (pwc_crop_table[MAX_OUTER_CROP_VALUE+(x)])
#else
#define CLAMP(x) ((x)>255?255:((x)<0?0:x))
#endif
/* If the type or the command change, we rebuild the lookup table */
void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd)
{
int flags, version, shift, i;
struct pwc_dec23_private *pdec = &pdev->dec23;
mutex_init(&pdec->lock);
if (pdec->last_cmd_valid && pdec->last_cmd == cmd[2])
return;
if (DEVICE_USE_CODEC3(pdev->type)) {
flags = cmd[2] & 0x18;
if (flags == 8)
pdec->nbits = 7; /* More bits, mean more bits to encode the stream, but better quality */
else if (flags == 0x10)
pdec->nbits = 8;
else
pdec->nbits = 6;
version = cmd[2] >> 5;
build_table_color(KiaraRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);
build_table_color(KiaraRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);
} else {
flags = cmd[2] & 6;
if (flags == 2)
pdec->nbits = 7;
else if (flags == 4)
pdec->nbits = 8;
else
pdec->nbits = 6;
version = cmd[2] >> 3;
build_table_color(TimonRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);
build_table_color(TimonRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);
}
/* Informations can be coded on a variable number of bits but never less than 8 */
shift = 8 - pdec->nbits;
pdec->scalebits = SCALEBITS - shift;
pdec->nbitsmask = 0xFF >> shift;
fill_table_dc00_d800(pdec);
build_subblock_pattern(pdec);
build_bit_powermask_table(pdec);
#if USE_LOOKUP_TABLE_TO_CLAMP
/* Build the static table to clamp value [0-255] */
for (i=0;i<MAX_OUTER_CROP_VALUE;i++)
pwc_crop_table[i] = 0;
for (i=0; i<256; i++)
pwc_crop_table[MAX_OUTER_CROP_VALUE+i] = i;
for (i=0; i<MAX_OUTER_CROP_VALUE; i++)
pwc_crop_table[MAX_OUTER_CROP_VALUE+256+i] = 255;
#endif
pdec->last_cmd = cmd[2];
pdec->last_cmd_valid = 1;
}
/*
* Copy the 4x4 image block to Y plane buffer
*/
static void copy_image_block_Y(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
{
#if UNROLL_LOOP_FOR_COPY
const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
const int *c = src;
unsigned char *d = dst;
*d++ = cm[c[0] >> scalebits];
*d++ = cm[c[1] >> scalebits];
*d++ = cm[c[2] >> scalebits];
*d++ = cm[c[3] >> scalebits];
d = dst + bytes_per_line;
*d++ = cm[c[4] >> scalebits];
*d++ = cm[c[5] >> scalebits];
*d++ = cm[c[6] >> scalebits];
*d++ = cm[c[7] >> scalebits];
d = dst + bytes_per_line*2;
*d++ = cm[c[8] >> scalebits];
*d++ = cm[c[9] >> scalebits];
*d++ = cm[c[10] >> scalebits];
*d++ = cm[c[11] >> scalebits];
d = dst + bytes_per_line*3;
*d++ = cm[c[12] >> scalebits];
*d++ = cm[c[13] >> scalebits];
*d++ = cm[c[14] >> scalebits];
*d++ = cm[c[15] >> scalebits];
#else
int i;
const int *c = src;
unsigned char *d = dst;
for (i = 0; i < 4; i++, c++)
*d++ = CLAMP((*c) >> scalebits);
d = dst + bytes_per_line;
for (i = 0; i < 4; i++, c++)
*d++ = CLAMP((*c) >> scalebits);
d = dst + bytes_per_line*2;
for (i = 0; i < 4; i++, c++)
*d++ = CLAMP((*c) >> scalebits);
d = dst + bytes_per_line*3;
for (i = 0; i < 4; i++, c++)
*d++ = CLAMP((*c) >> scalebits);
#endif
}
/*
* Copy the 4x4 image block to a CrCb plane buffer
*
*/
static void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
{
#if UNROLL_LOOP_FOR_COPY
/* Unroll all loops */
const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
const int *c = src;
unsigned char *d = dst;
*d++ = cm[c[0] >> scalebits];
*d++ = cm[c[4] >> scalebits];
*d++ = cm[c[1] >> scalebits];
*d++ = cm[c[5] >> scalebits];
*d++ = cm[c[2] >> scalebits];
*d++ = cm[c[6] >> scalebits];
*d++ = cm[c[3] >> scalebits];
*d++ = cm[c[7] >> scalebits];
d = dst + bytes_per_line;
*d++ = cm[c[12] >> scalebits];
*d++ = cm[c[8] >> scalebits];
*d++ = cm[c[13] >> scalebits];
*d++ = cm[c[9] >> scalebits];
*d++ = cm[c[14] >> scalebits];
*d++ = cm[c[10] >> scalebits];
*d++ = cm[c[15] >> scalebits];
*d++ = cm[c[11] >> scalebits];
#else
int i;
const int *c1 = src;
const int *c2 = src + 4;
unsigned char *d = dst;
for (i = 0; i < 4; i++, c1++, c2++) {
*d++ = CLAMP((*c1) >> scalebits);
*d++ = CLAMP((*c2) >> scalebits);
}
c1 = src + 12;
d = dst + bytes_per_line;
for (i = 0; i < 4; i++, c1++, c2++) {
*d++ = CLAMP((*c1) >> scalebits);
*d++ = CLAMP((*c2) >> scalebits);
}
#endif
}
/*
* To manage the stream, we keep bits in a 32 bits register.
* fill_nbits(n): fill the reservoir with at least n bits
* skip_bits(n): discard n bits from the reservoir
* get_bits(n): fill the reservoir, returns the first n bits and discard the
* bits from the reservoir.
* __get_nbits(n): faster version of get_bits(n), but asumes that the reservoir
* contains at least n bits. bits returned is discarded.
*/
#define fill_nbits(pdec, nbits_wanted) do { \
while (pdec->nbits_in_reservoir<(nbits_wanted)) \
{ \
pdec->reservoir |= (*(pdec->stream)++) << (pdec->nbits_in_reservoir); \
pdec->nbits_in_reservoir += 8; \
} \
} while(0);
#define skip_nbits(pdec, nbits_to_skip) do { \
pdec->reservoir >>= (nbits_to_skip); \
pdec->nbits_in_reservoir -= (nbits_to_skip); \
} while(0);
#define get_nbits(pdec, nbits_wanted, result) do { \
fill_nbits(pdec, nbits_wanted); \
result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
skip_nbits(pdec, nbits_wanted); \
} while(0);
#define __get_nbits(pdec, nbits_wanted, result) do { \
result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
skip_nbits(pdec, nbits_wanted); \
} while(0);
#define look_nbits(pdec, nbits_wanted) \
((pdec->reservoir) & ((1U<<(nbits_wanted))-1))
/*
* Decode a 4x4 pixel block
*/
static void decode_block(struct pwc_dec23_private *pdec,
const unsigned char *ptable0004,
const unsigned char *ptable8004)
{
unsigned int primary_color;
unsigned int channel_v, offset1, op;
int i;
fill_nbits(pdec, 16);
__get_nbits(pdec, pdec->nbits, primary_color);
if (look_nbits(pdec,2) == 0) {
skip_nbits(pdec, 2);
/* Very simple, the color is the same for all pixels of the square */
for (i = 0; i < 16; i++)
pdec->temp_colors[i] = pdec->table_dc00[primary_color];
return;
}
/* This block is encoded with small pattern */
for (i = 0; i < 16; i++)
pdec->temp_colors[i] = pdec->table_d800[primary_color];
__get_nbits(pdec, 3, channel_v);
channel_v = ((channel_v & 1) << 2) | (channel_v & 2) | ((channel_v & 4) >> 2);
ptable0004 += (channel_v * 128);
ptable8004 += (channel_v * 32);
offset1 = 0;
do
{
unsigned int htable_idx, rows = 0;
const unsigned int *block;
/* [ zzzz y x x ]
* xx == 00 :=> end of the block def, remove the two bits from the stream
* yxx == 111
* yxx == any other value
*
*/
fill_nbits(pdec, 16);
htable_idx = look_nbits(pdec, 6);
op = hash_table_ops[htable_idx * 4];
if (op == 2) {
skip_nbits(pdec, 2);
} else if (op == 1) {
/* 15bits [ xxxx xxxx yyyy 111 ]
* yyy => offset in the table8004
* xxx => offset in the tabled004 (tree)
*/
unsigned int mask, shift;
unsigned int nbits, col1;
unsigned int yyyy;
skip_nbits(pdec, 3);
/* offset1 += yyyy */
__get_nbits(pdec, 4, yyyy);
offset1 += 1 + yyyy;
offset1 &= 0x0F;
nbits = ptable8004[offset1 * 2];
/* col1 = xxxx xxxx */
__get_nbits(pdec, nbits+1, col1);
/* Bit mask table */
mask = pdec->table_bitpowermask[nbits][col1];
shift = ptable8004[offset1 * 2 + 1];
rows = ((mask << shift) + 0x80) & 0xFF;
block = pdec->table_subblock[rows];
for (i = 0; i < 16; i++)
pdec->temp_colors[i] += block[MulIdx[offset1][i]];
} else {
/* op == 0
* offset1 is coded on 3 bits
*/
unsigned int shift;
offset1 += hash_table_ops [htable_idx * 4 + 2];
offset1 &= 0x0F;
rows = ptable0004[offset1 + hash_table_ops [htable_idx * 4 + 3]];
block = pdec->table_subblock[rows];
for (i = 0; i < 16; i++)
pdec->temp_colors[i] += block[MulIdx[offset1][i]];
shift = hash_table_ops[htable_idx * 4 + 1];
skip_nbits(pdec, shift);
}
} while (op != 2);
}
static void DecompressBand23(struct pwc_dec23_private *pdec,
const unsigned char *rawyuv,
unsigned char *planar_y,
unsigned char *planar_u,
unsigned char *planar_v,
unsigned int compressed_image_width,
unsigned int real_image_width)
{
int compression_index, nblocks;
const unsigned char *ptable0004;
const unsigned char *ptable8004;
pdec->reservoir = 0;
pdec->nbits_in_reservoir = 0;
pdec->stream = rawyuv + 1; /* The first byte of the stream is skipped */
get_nbits(pdec, 4, compression_index);
/* pass 1: uncompress Y component */
nblocks = compressed_image_width / 4;
ptable0004 = pdec->table_0004_pass1[compression_index];
ptable8004 = pdec->table_8004_pass1[compression_index];
/* Each block decode a square of 4x4 */
while (nblocks) {
decode_block(pdec, ptable0004, ptable8004);
copy_image_block_Y(pdec->temp_colors, planar_y, real_image_width, pdec->scalebits);
planar_y += 4;
nblocks--;
}
/* pass 2: uncompress UV component */
nblocks = compressed_image_width / 8;
ptable0004 = pdec->table_0004_pass2[compression_index];
ptable8004 = pdec->table_8004_pass2[compression_index];
/* Each block decode a square of 4x4 */
while (nblocks) {
decode_block(pdec, ptable0004, ptable8004);
copy_image_block_CrCb(pdec->temp_colors, planar_u, real_image_width/2, pdec->scalebits);
decode_block(pdec, ptable0004, ptable8004);
copy_image_block_CrCb(pdec->temp_colors, planar_v, real_image_width/2, pdec->scalebits);
planar_v += 8;
planar_u += 8;
nblocks -= 2;
}
}
/**
*
* Uncompress a pwc23 buffer.
*
* src: raw data
* dst: image output
*/
void pwc_dec23_decompress(struct pwc_device *pdev,
const void *src,
void *dst)
{
int bandlines_left, bytes_per_block;
struct pwc_dec23_private *pdec = &pdev->dec23;
/* YUV420P image format */
unsigned char *pout_planar_y;
unsigned char *pout_planar_u;
unsigned char *pout_planar_v;
unsigned int plane_size;
mutex_lock(&pdec->lock);
bandlines_left = pdev->height / 4;
bytes_per_block = pdev->width * 4;
plane_size = pdev->height * pdev->width;
pout_planar_y = dst;
pout_planar_u = dst + plane_size;
pout_planar_v = dst + plane_size + plane_size / 4;
while (bandlines_left--) {
DecompressBand23(pdec, src,
pout_planar_y, pout_planar_u, pout_planar_v,
pdev->width, pdev->width);
src += pdev->vbandlength;
pout_planar_y += bytes_per_block;
pout_planar_u += pdev->width;
pout_planar_v += pdev->width;
}
mutex_unlock(&pdec->lock);
}

View File

@@ -0,0 +1,61 @@
/* Linux driver for Philips webcam
(C) 2004-2006 Luc Saillard (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
*/
#ifndef PWC_DEC23_H
#define PWC_DEC23_H
struct pwc_device;
struct pwc_dec23_private
{
struct mutex lock;
unsigned char last_cmd, last_cmd_valid;
unsigned int scalebits;
unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */
unsigned int reservoir;
unsigned int nbits_in_reservoir;
const unsigned char *stream;
int temp_colors[16];
unsigned char table_0004_pass1[16][1024];
unsigned char table_0004_pass2[16][1024];
unsigned char table_8004_pass1[16][256];
unsigned char table_8004_pass2[16][256];
unsigned int table_subblock[256][12];
unsigned char table_bitpowermask[8][256];
unsigned int table_d800[256];
unsigned int table_dc00[256];
};
void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd);
void pwc_dec23_decompress(struct pwc_device *pdev,
const void *src,
void *dst);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,892 @@
/* Linux driver for Philips webcam
(C) 2004-2006 Luc Saillard (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
*/
/* This tables contains entries for the 730/740/750 (Kiara) camera, with
4 different qualities (no compression, low, medium, high).
It lists the bandwidth requirements for said mode by its alternate interface
number. An alternate of 0 means that the mode is unavailable.
There are 6 * 4 * 4 entries:
6 different resolutions subqcif, qsif, qcif, sif, cif, vga
6 framerates: 5, 10, 15, 20, 25, 30
4 compression modi: none, low, medium, high
When an uncompressed mode is not available, the next available compressed mode
will be chosen (unless the decompressor is absent). Sometimes there are only
1 or 2 compressed modes available; in that case entries are duplicated.
*/
#include "pwc-kiara.h"
const unsigned int Kiara_fps_vector[PWC_FPS_MAX_KIARA] = { 5, 10, 15, 20, 25, 30 };
const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
{
/* SQCIF */
{
/* 5 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 10 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 15 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 20 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 25 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 30 fps */
{
{0, },
{0, },
{0, },
{0, },
},
},
/* QSIF */
{
/* 5 fps */
{
{1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
{1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
{1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
{1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
},
/* 10 fps */
{
{2, 291, 0, {0x1C, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0x01, 0x80}},
{1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
{1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
{1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
},
/* 15 fps */
{
{3, 437, 0, {0x1B, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x01, 0x80}},
{2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
{2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
{1, 192, 420, {0x13, 0xF4, 0x30, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
},
/* 20 fps */
{
{4, 589, 0, {0x1A, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4D, 0x02, 0x80}},
{3, 448, 730, {0x12, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xC0, 0x01, 0x80}},
{2, 292, 476, {0x12, 0xF4, 0x30, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0x01, 0x80}},
{1, 192, 312, {0x12, 0xF4, 0x50, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
},
/* 25 fps */
{
{5, 703, 0, {0x19, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x02, 0x80}},
{3, 447, 610, {0x11, 0xF4, 0x30, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x28, 0xBF, 0x01, 0x80}},
{2, 292, 398, {0x11, 0xF4, 0x50, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x28, 0x24, 0x01, 0x80}},
{1, 193, 262, {0x11, 0xF4, 0x50, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x28, 0xC1, 0x00, 0x80}},
},
/* 30 fps */
{
{8, 874, 0, {0x18, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x6A, 0x03, 0x80}},
{5, 704, 730, {0x10, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x28, 0xC0, 0x02, 0x80}},
{3, 448, 492, {0x10, 0xF4, 0x30, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x28, 0xC0, 0x01, 0x80}},
{2, 292, 320, {0x10, 0xF4, 0x50, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x28, 0x24, 0x01, 0x80}},
},
},
/* QCIF */
{
/* 5 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 10 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 15 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 20 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 25 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 30 fps */
{
{0, },
{0, },
{0, },
{0, },
},
},
/* SIF */
{
/* 5 fps */
{
{4, 582, 0, {0x0D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x02, 0x80}},
{3, 387, 1276, {0x05, 0xF4, 0x30, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x01, 0x80}},
{2, 291, 960, {0x05, 0xF4, 0x30, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0x01, 0x80}},
{1, 191, 630, {0x05, 0xF4, 0x50, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x18, 0xBF, 0x00, 0x80}},
},
/* 10 fps */
{
{0, },
{6, 775, 1278, {0x04, 0xF4, 0x30, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x03, 0x80}},
{3, 447, 736, {0x04, 0xF4, 0x30, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x28, 0xBF, 0x01, 0x80}},
{2, 292, 480, {0x04, 0xF4, 0x70, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x28, 0x24, 0x01, 0x80}},
},
/* 15 fps */
{
{0, },
{9, 955, 1050, {0x03, 0xF4, 0x30, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x03, 0x80}},
{4, 592, 650, {0x03, 0xF4, 0x30, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x50, 0x02, 0x80}},
{3, 448, 492, {0x03, 0xF4, 0x50, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x38, 0xC0, 0x01, 0x80}},
},
/* 20 fps */
{
{0, },
{9, 958, 782, {0x02, 0xF4, 0x30, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x03, 0x80}},
{5, 703, 574, {0x02, 0xF4, 0x50, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x02, 0x80}},
{3, 446, 364, {0x02, 0xF4, 0x90, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x38, 0xBE, 0x01, 0x80}},
},
/* 25 fps */
{
{0, },
{9, 958, 654, {0x01, 0xF4, 0x30, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x03, 0x80}},
{6, 776, 530, {0x01, 0xF4, 0x50, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x03, 0x80}},
{4, 592, 404, {0x01, 0xF4, 0x70, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x48, 0x50, 0x02, 0x80}},
},
/* 30 fps */
{
{0, },
{9, 957, 526, {0x00, 0xF4, 0x50, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x03, 0x80}},
{6, 775, 426, {0x00, 0xF4, 0x70, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x03, 0x80}},
{4, 590, 324, {0x00, 0x7A, 0x88, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x50, 0x4E, 0x02, 0x80}},
},
},
/* CIF */
{
/* 5 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 10 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 15 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 20 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 25 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 30 fps */
{
{0, },
{0, },
{0, },
{0, },
},
},
/* VGA */
{
/* 5 fps */
{
{0, },
{6, 773, 1272, {0x25, 0xF4, 0x30, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}},
{4, 592, 976, {0x25, 0xF4, 0x50, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x02, 0x80}},
{3, 448, 738, {0x25, 0xF4, 0x90, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x01, 0x80}},
},
/* 10 fps */
{
{0, },
{9, 956, 788, {0x24, 0xF4, 0x70, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x03, 0x80}},
{6, 776, 640, {0x24, 0xF4, 0xB0, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x03, 0x80}},
{4, 592, 488, {0x24, 0x7A, 0xE8, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x02, 0x80}},
},
/* 15 fps */
{
{0, },
{9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
{9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
{8, 895, 492, {0x23, 0x7A, 0xE8, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x03, 0x80}},
},
/* 20 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 25 fps */
{
{0, },
{0, },
{0, },
{0, },
},
/* 30 fps */
{
{0, },
{0, },
{0, },
{0, },
},
},
};
/*
* Rom table for kiara chips
*
* 32 roms tables (one for each resolution ?)
* 2 tables per roms (one for each passes) (Y, and U&V)
* 128 bytes per passes
*/
const unsigned int KiaraRomTable [8][2][16][8] =
{
{ /* version 0 */
{ /* version 0, passes 0 */
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000001,0x00000001},
{0x00000000,0x00000000,0x00000009,0x00000009,
0x00000009,0x00000009,0x00000009,0x00000009},
{0x00000000,0x00000000,0x00000009,0x00000049,
0x00000049,0x00000049,0x00000049,0x00000049},
{0x00000000,0x00000000,0x00000049,0x00000049,
0x00000049,0x00000249,0x0000024a,0x00000049},
{0x00000000,0x00000000,0x00000049,0x00000049,
0x00000249,0x00000249,0x0000024a,0x0000024a},
{0x00000000,0x00000000,0x00000049,0x00000249,
0x00000249,0x0000124a,0x0000024a,0x0000024a},
{0x00000000,0x00000000,0x00000049,0x00000249,
0x0000124a,0x00009252,0x00001252,0x00001252},
{0x00000000,0x00000000,0x00000249,0x00000249,
0x00009252,0x00009292,0x00009292,0x00009292},
{0x00000000,0x00000000,0x00000249,0x00001249,
0x00009292,0x00009292,0x00009493,0x000124db},
{0x00000000,0x00000000,0x00000249,0x0000924a,
0x00009492,0x0000a49b,0x0000a49b,0x000124db},
{0x00000000,0x00000000,0x00001249,0x00009252,
0x0000a493,0x000124db,0x000124db,0x000126dc},
{0x00000000,0x00000000,0x00001249,0x00009493,
0x000124db,0x000126dc,0x000136e4,0x000126dc},
{0x00000000,0x00000000,0x00009292,0x0000a49b,
0x000124db,0x000136e4,0x000136e4,0x000136e4},
{0x00000000,0x00000000,0x00009292,0x0000a49b,
0x000126dc,0x0001b724,0x0001b92d,0x0001b925},
{0x00000000,0x00000000,0x00009492,0x000124db,
0x000136e4,0x0001b925,0x0001c96e,0x0001c92d},
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000}
},
{ /* version 0, passes 1 */
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000},
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000},
{0x00000000,0x00000000,0x00000001,0x00000009,
0x00000009,0x00000009,0x00000009,0x00000001},
{0x00000000,0x00000000,0x00000009,0x00000009,
0x00000049,0x00000049,0x00000049,0x00000049},
{0x00000000,0x00000000,0x00000049,0x00000049,
0x00000049,0x00000049,0x0000024a,0x0000024a},
{0x00000000,0x00000000,0x00000049,0x00000049,
0x00000249,0x00000249,0x0000024a,0x0000024a},
{0x00000000,0x00000000,0x00000049,0x00000249,
0x00000249,0x00000249,0x0000024a,0x00001252},
{0x00000000,0x00000000,0x00000049,0x00001249,
0x0000124a,0x0000124a,0x00001252,0x00009292},
{0x00000000,0x00000000,0x00000249,0x00001249,
0x00009252,0x00009252,0x00009292,0x00009493},
{0x00000000,0x00000000,0x00000249,0x0000924a,
0x00009292,0x00009292,0x00009292,0x00009493},
{0x00000000,0x00000000,0x00000249,0x00009292,
0x00009492,0x00009493,0x0000a49b,0x00009493},
{0x00000000,0x00000000,0x00001249,0x00009292,
0x0000a493,0x000124db,0x000126dc,0x000126dc},
{0x00000000,0x00000000,0x0000924a,0x00009493,
0x0000a493,0x000126dc,0x000136e4,0x000136e4},
{0x00000000,0x00000000,0x00009252,0x00009493,
0x000126dc,0x000126dc,0x000136e4,0x000136e4},
{0x00000000,0x00000000,0x00009292,0x0000a49b,
0x000136e4,0x000136e4,0x0001b725,0x0001b724},
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000}
}
},
{ /* version 1 */
{ /* version 1, passes 0 */
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000001},
{0x00000000,0x00000000,0x00000009,0x00000009,
0x00000009,0x00000009,0x00000009,0x00000009},
{0x00000000,0x00000000,0x00000049,0x00000049,
0x00000049,0x00000049,0x00000049,0x00000049},
{0x00000000,0x00000000,0x00000049,0x00000049,
0x00000049,0x00000249,0x0000024a,0x0000024a},
{0x00000000,0x00000000,0x00000049,0x00000249,
0x00000249,0x00000249,0x0000024a,0x00001252},
{0x00000000,0x00000000,0x00000249,0x00000249,
0x00000249,0x0000124a,0x00001252,0x00001252},
{0x00000000,0x00000000,0x00000249,0x00000249,
0x0000124a,0x0000124a,0x00009292,0x00009292},
{0x00000000,0x00000000,0x00000249,0x00001249,
0x0000124a,0x00009252,0x00009292,0x00009292},
{0x00000000,0x00000000,0x00000249,0x00001249,
0x00009252,0x00009292,0x00009292,0x00009292},
{0x00000000,0x00000000,0x00000249,0x00001249,
0x00009252,0x00009292,0x00009493,0x00009493},
{0x00000000,0x00000000,0x00000249,0x0000924a,
0x00009252,0x00009493,0x00009493,0x00009493},
{0x00000000,0x00000000,0x00000249,0x0000924a,
0x00009292,0x00009493,0x00009493,0x00009493},
{0x00000000,0x00000000,0x00000249,0x00009252,
0x00009492,0x00009493,0x0000a49b,0x0000a49b},
{0x00000000,0x00000000,0x00001249,0x00009292,
0x00009492,0x000124db,0x000124db,0x000124db},
{0x00000000,0x00000000,0x0000924a,0x00009493,
0x0000a493,0x000126dc,0x000126dc,0x000126dc},
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000}
},
{ /* version 1, passes 1 */
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000},
{0x00000000,0x00000000,0x00000049,0x00000009,
0x00000049,0x00000009,0x00000001,0x00000000},
{0x00000000,0x00000000,0x00000049,0x00000049,
0x00000049,0x00000049,0x00000049,0x00000000},
{0x00000000,0x00000000,0x00000249,0x00000049,
0x00000249,0x00000049,0x0000024a,0x00000001},
{0x00000000,0x00000000,0x00000249,0x00000249,
0x00000249,0x00000249,0x0000024a,0x00000001},
{0x00000000,0x00000000,0x00000249,0x00000249,
0x00000249,0x00000249,0x0000024a,0x00000001},
{0x00000000,0x00000000,0x00000249,0x00000249,
0x00000249,0x00000249,0x0000024a,0x00000009},
{0x00000000,0x00000000,0x00000249,0x00000249,
0x0000124a,0x0000124a,0x0000024a,0x00000009},
{0x00000000,0x00000000,0x00000249,0x00000249,
0x0000124a,0x0000124a,0x0000024a,0x00000009},
{0x00000000,0x00000000,0x00001249,0x00001249,
0x0000124a,0x00009252,0x00001252,0x00000049},
{0x00000000,0x00000000,0x00001249,0x00001249,
0x0000124a,0x00009292,0x00001252,0x00000049},
{0x00000000,0x00000000,0x00001249,0x00001249,
0x0000124a,0x00009292,0x00001252,0x00000049},
{0x00000000,0x00000000,0x00001249,0x00001249,
0x00009252,0x00009292,0x00001252,0x0000024a},
{0x00000000,0x00000000,0x00001249,0x00001249,
0x00009292,0x00009292,0x00001252,0x0000024a},
{0x00000000,0x00000000,0x0000924a,0x0000924a,
0x00009492,0x00009493,0x00009292,0x00001252},
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000}
}
},
{ /* version 2 */
{ /* version 2, passes 0 */
{0x00000000,0x00000000,0x00000049,0x00000049,
0x00000049,0x00000049,0x0000024a,0x0000024a},
{0x00000000,0x00000000,0x00000249,0x00000249,
0x00000249,0x0000124a,0x00001252,0x00009292},
{0x00000000,0x00000000,0x00000249,0x00000249,
0x0000124a,0x00009252,0x00009292,0x00009292},
{0x00000000,0x00000000,0x00000249,0x00001249,
0x0000124a,0x00009292,0x00009493,0x00009493},
{0x00000000,0x00000000,0x00000249,0x00001249,
0x00009252,0x00009493,0x00009493,0x0000a49b},
{0x00000000,0x00000000,0x00000249,0x0000924a,
0x00009292,0x00009493,0x0000a49b,0x0000a49b},
{0x00000000,0x00000000,0x00001249,0x0000924a,
0x00009292,0x00009493,0x0000a49b,0x000124db},
{0x00000000,0x00000000,0x00001249,0x00009252,
0x00009492,0x0000a49b,0x0000a49b,0x000124db},
{0x00000000,0x00000000,0x00001249,0x00009292,
0x00009492,0x000124db,0x000124db,0x000126dc},
{0x00000000,0x00000000,0x00001249,0x00009292,
0x0000a493,0x000124db,0x000126dc,0x000126dc},
{0x00000000,0x00000000,0x00001249,0x00009493,
0x0000a493,0x000124db,0x000126dc,0x000136e4},
{0x00000000,0x00000000,0x00001249,0x00009493,
0x0000a493,0x000126dc,0x000136e4,0x000136e4},
{0x00000000,0x00000000,0x0000924a,0x00009493,
0x0001249b,0x000126dc,0x000136e4,0x000136e4},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x000124db,0x000136e4,0x000136e4,0x0001b724},
{0x00000000,0x00000000,0x00009252,0x000124db,
0x000126dc,0x0001b724,0x0001b725,0x0001b925},
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000}
},
{ /* version 2, passes 1 */
{0x00000000,0x00000000,0x00000049,0x00000049,
0x00000049,0x00000049,0x00000049,0x00000049},
{0x00000000,0x00000000,0x00000249,0x00000249,
0x00000249,0x00000249,0x0000024a,0x00000049},
{0x00000000,0x00000000,0x00001249,0x00000249,
0x0000124a,0x0000124a,0x00001252,0x00000049},
{0x00000000,0x00000000,0x00001249,0x00001249,
0x0000124a,0x0000124a,0x00009292,0x0000024a},
{0x00000000,0x00000000,0x00001249,0x00001249,
0x00009252,0x00009292,0x00009292,0x0000024a},
{0x00000000,0x00000000,0x00001249,0x00001249,
0x00009252,0x00009292,0x0000a49b,0x0000024a},
{0x00000000,0x00000000,0x00001249,0x00001249,
0x00009292,0x00009493,0x0000a49b,0x00001252},
{0x00000000,0x00000000,0x00001249,0x00001249,
0x00009292,0x00009493,0x0000a49b,0x00001252},
{0x00000000,0x00000000,0x00001249,0x0000924a,
0x00009492,0x0000a49b,0x0000a49b,0x00001252},
{0x00000000,0x00000000,0x00001249,0x00009252,
0x00009492,0x0000a49b,0x0000a49b,0x00009292},
{0x00000000,0x00000000,0x00001249,0x00009292,
0x00009492,0x0000a49b,0x0000a49b,0x00009292},
{0x00000000,0x00000000,0x00001249,0x00009493,
0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
{0x00000000,0x00000000,0x00001249,0x00009493,
0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
{0x00000000,0x00000000,0x0000924a,0x00009493,
0x0000a493,0x000124db,0x0000a49b,0x00009493},
{0x00000000,0x00000000,0x00009252,0x0000a49b,
0x0001249b,0x000126dc,0x000124db,0x0000a49b},
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000}
}
},
{ /* version 3 */
{ /* version 3, passes 0 */
{0x00000000,0x00000000,0x00000249,0x00000249,
0x0000124a,0x0000124a,0x00009292,0x00009292},
{0x00000000,0x00000000,0x00001249,0x00001249,
0x00009292,0x00009493,0x0000a49b,0x0000a49b},
{0x00000000,0x00000000,0x00001249,0x0000924a,
0x00009492,0x0000a49b,0x0000a49b,0x000124db},
{0x00000000,0x00000000,0x00001249,0x00009292,
0x00009492,0x000124db,0x000126dc,0x000126dc},
{0x00000000,0x00000000,0x00001249,0x00009493,
0x0000a493,0x000124db,0x000126dc,0x000126dc},
{0x00000000,0x00000000,0x00001249,0x00009493,
0x0000a493,0x000126dc,0x000136e4,0x000136e4},
{0x00000000,0x00000000,0x00001249,0x00009493,
0x0000a493,0x000126dc,0x000136e4,0x0001b724},
{0x00000000,0x00000000,0x00001249,0x00009493,
0x0001249b,0x000126dc,0x000136e4,0x0001b724},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0001249b,0x000126dc,0x000136e4,0x0001b724},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0001249b,0x000136e4,0x0001b725,0x0001b724},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x000124db,0x000136e4,0x0001b725,0x0001b925},
{0x00000000,0x00000000,0x00009292,0x0000a49b,
0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
{0x00000000,0x00000000,0x00009292,0x0000a49b,
0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
{0x00000000,0x00000000,0x00009492,0x000124db,
0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
{0x00000000,0x00000000,0x0000a492,0x000126db,
0x000136e4,0x0001b925,0x00025bb6,0x00024b77},
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000}
},
{ /* version 3, passes 1 */
{0x00000000,0x00000000,0x00001249,0x00000249,
0x0000124a,0x0000124a,0x00001252,0x00001252},
{0x00000000,0x00000000,0x00001249,0x00001249,
0x00009252,0x00009292,0x00009292,0x00001252},
{0x00000000,0x00000000,0x00001249,0x0000924a,
0x00009492,0x00009493,0x0000a49b,0x00001252},
{0x00000000,0x00000000,0x00001249,0x00009252,
0x00009492,0x0000a49b,0x0000a49b,0x00009292},
{0x00000000,0x00000000,0x00001249,0x00009292,
0x00009492,0x0000a49b,0x0000a49b,0x00009292},
{0x00000000,0x00000000,0x00001249,0x00009493,
0x0000a493,0x0000a49b,0x000126dc,0x00009292},
{0x00000000,0x00000000,0x0000924a,0x00009493,
0x0000a493,0x0000a49b,0x000126dc,0x00009493},
{0x00000000,0x00000000,0x0000924a,0x00009493,
0x0000a493,0x0000a49b,0x000126dc,0x00009493},
{0x00000000,0x00000000,0x0000924a,0x00009493,
0x0000a493,0x000124db,0x000126dc,0x00009493},
{0x00000000,0x00000000,0x0000924a,0x00009493,
0x0000a493,0x000124db,0x000126dc,0x0000a49b},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0000a493,0x000124db,0x000126dc,0x0000a49b},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x000124db,0x000136e4,0x000126dc,0x000124db},
{0x00000000,0x00000000,0x00009492,0x0000a49b,
0x000136e4,0x000136e4,0x000126dc,0x000124db},
{0x00000000,0x00000000,0x0000a492,0x000124db,
0x0001b724,0x0001b724,0x000136e4,0x000126dc},
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000}
}
},
{ /* version 4 */
{ /* version 4, passes 0 */
{0x00000000,0x00000000,0x00000049,0x00000049,
0x00000049,0x00000049,0x00000049,0x00000049},
{0x00000000,0x00000000,0x00000249,0x00000049,
0x00000249,0x00000249,0x0000024a,0x00000049},
{0x00000000,0x00000000,0x00000249,0x00000249,
0x0000124a,0x00009252,0x00001252,0x0000024a},
{0x00000000,0x00000000,0x00001249,0x00001249,
0x00009252,0x00009292,0x00009493,0x00001252},
{0x00000000,0x00000000,0x00001249,0x0000924a,
0x00009292,0x00009493,0x00009493,0x00001252},
{0x00000000,0x00000000,0x00001249,0x00009292,
0x00009492,0x0000a49b,0x0000a49b,0x00009292},
{0x00000000,0x00000000,0x00001249,0x00009493,
0x0000a493,0x000124db,0x000124db,0x00009493},
{0x00000000,0x00000000,0x0000924a,0x00009493,
0x0000a493,0x000124db,0x000126dc,0x0000a49b},
{0x00000000,0x00000000,0x0000924a,0x00009493,
0x0000a493,0x000124db,0x000126dc,0x0000a49b},
{0x00000000,0x00000000,0x0000924a,0x00009493,
0x0001249b,0x000126dc,0x000126dc,0x000124db},
{0x00000000,0x00000000,0x00009252,0x00009493,
0x000124db,0x000136e4,0x000136e4,0x000126dc},
{0x00000000,0x00000000,0x00009252,0x0000a49b,
0x000124db,0x000136e4,0x000136e4,0x000126dc},
{0x00000000,0x00000000,0x00009292,0x0000a49b,
0x000126dc,0x000136e4,0x000136e4,0x000136e4},
{0x00000000,0x00000000,0x00009492,0x0000a49b,
0x000126dc,0x0001b724,0x0001b725,0x0001b724},
{0x00000000,0x00000000,0x0000a492,0x000124db,
0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000}
},
{ /* version 4, passes 1 */
{0x00000000,0x00000000,0x00000249,0x00000049,
0x00000009,0x00000009,0x00000009,0x00000009},
{0x00000000,0x00000000,0x00000249,0x00000249,
0x00000049,0x00000049,0x00000009,0x00000009},
{0x00000000,0x00000000,0x00001249,0x00001249,
0x0000124a,0x00000249,0x00000049,0x00000049},
{0x00000000,0x00000000,0x00001249,0x00001249,
0x0000124a,0x0000124a,0x00000049,0x00000049},
{0x00000000,0x00000000,0x00001249,0x00001249,
0x00009252,0x0000124a,0x0000024a,0x0000024a},
{0x00000000,0x00000000,0x00001249,0x0000924a,
0x00009252,0x0000124a,0x0000024a,0x0000024a},
{0x00000000,0x00000000,0x00001249,0x00009292,
0x00009492,0x00009252,0x00001252,0x00001252},
{0x00000000,0x00000000,0x00001249,0x00009493,
0x0000a493,0x00009292,0x00009292,0x00001252},
{0x00000000,0x00000000,0x0000924a,0x00009493,
0x0000a493,0x00009292,0x00009292,0x00009292},
{0x00000000,0x00000000,0x0000924a,0x00009493,
0x0000a493,0x00009493,0x00009493,0x00009292},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0000a493,0x0000a49b,0x00009493,0x00009493},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0001249b,0x000124db,0x0000a49b,0x0000a49b},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x000136e4,0x000126dc,0x000124db,0x0000a49b},
{0x00000000,0x00000000,0x00009252,0x000124db,
0x0001b724,0x000136e4,0x000126dc,0x000124db},
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000}
}
},
{ /* version 5 */
{ /* version 5, passes 0 */
{0x00000000,0x00000000,0x00000249,0x00000249,
0x00000249,0x00000249,0x00001252,0x00001252},
{0x00000000,0x00000000,0x00001249,0x00001249,
0x00009252,0x00009292,0x00009292,0x00001252},
{0x00000000,0x00000000,0x00001249,0x0000924a,
0x00009492,0x0000a49b,0x0000a49b,0x00009292},
{0x00000000,0x00000000,0x00001249,0x00009493,
0x0000a493,0x0000a49b,0x000124db,0x00009493},
{0x00000000,0x00000000,0x00001249,0x00009493,
0x0000a493,0x000124db,0x000126dc,0x00009493},
{0x00000000,0x00000000,0x0000924a,0x00009493,
0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0001249b,0x000126dc,0x000136e4,0x000124db},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x000126dc,0x000136e4,0x000136e4,0x000126dc},
{0x00000000,0x00000000,0x00009292,0x0000a49b,
0x000126dc,0x000136e4,0x000136e4,0x000126dc},
{0x00000000,0x00000000,0x00009292,0x0000a49b,
0x000126dc,0x0001b724,0x0001b725,0x000136e4},
{0x00000000,0x00000000,0x00009292,0x0000a49b,
0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
{0x00000000,0x00000000,0x00009492,0x0000a49b,
0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
{0x00000000,0x00000000,0x00009492,0x000124db,
0x000136e4,0x0001b925,0x0001c96e,0x0001b925},
{0x00000000,0x00000000,0x00009492,0x000124db,
0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
{0x00000000,0x00000000,0x0000a492,0x000126db,
0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000}
},
{ /* version 5, passes 1 */
{0x00000000,0x00000000,0x00001249,0x00000249,
0x00000249,0x00000249,0x0000024a,0x0000024a},
{0x00000000,0x00000000,0x00001249,0x00001249,
0x0000124a,0x0000124a,0x0000024a,0x0000024a},
{0x00000000,0x00000000,0x00001249,0x0000924a,
0x00009252,0x00009252,0x0000024a,0x0000024a},
{0x00000000,0x00000000,0x00001249,0x00009292,
0x00009492,0x0000a49b,0x00001252,0x00001252},
{0x00000000,0x00000000,0x0000924a,0x00009493,
0x0000a493,0x0000a49b,0x00001252,0x00001252},
{0x00000000,0x00000000,0x0000924a,0x00009493,
0x0000a493,0x0000a49b,0x00009292,0x00001252},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0000a493,0x0000a49b,0x00009292,0x00009292},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0000a493,0x0000a49b,0x00009493,0x00009292},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0001249b,0x000124db,0x00009493,0x00009292},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0001249b,0x000124db,0x00009493,0x00009493},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x000124db,0x000124db,0x0000a49b,0x00009493},
{0x00000000,0x00000000,0x0000924a,0x000124db,
0x000126dc,0x000126dc,0x0000a49b,0x00009493},
{0x00000000,0x00000000,0x0000924a,0x000124db,
0x000136e4,0x000126dc,0x000124db,0x0000a49b},
{0x00000000,0x00000000,0x00009292,0x000124db,
0x000136e4,0x000126dc,0x000124db,0x0000a49b},
{0x00000000,0x00000000,0x00009492,0x000126db,
0x0001b724,0x000136e4,0x000126dc,0x000124db},
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000}
}
},
{ /* version 6 */
{ /* version 6, passes 0 */
{0x00000000,0x00000000,0x00001249,0x00001249,
0x00009252,0x00009292,0x00009493,0x00009493},
{0x00000000,0x00000000,0x00001249,0x00009292,
0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
{0x00000000,0x00000000,0x00001249,0x00009493,
0x0000a493,0x000124db,0x000124db,0x0000a49b},
{0x00000000,0x00000000,0x0000924a,0x00009493,
0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0001249b,0x000126dc,0x000136e4,0x000124db},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x000126dc,0x000136e4,0x000136e4,0x000126dc},
{0x00000000,0x00000000,0x00009292,0x0000a49b,
0x000126dc,0x0001b724,0x0001b725,0x000126dc},
{0x00000000,0x00000000,0x00009292,0x0000a49b,
0x000136e4,0x0001b724,0x0001b92d,0x000136e4},
{0x00000000,0x00000000,0x00009492,0x0000a49b,
0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
{0x00000000,0x00000000,0x00009492,0x000124db,
0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
{0x00000000,0x00000000,0x00009492,0x000124db,
0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
{0x00000000,0x00000000,0x00009492,0x000124db,
0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
{0x00000000,0x00000000,0x0000a492,0x000124db,
0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d},
{0x00000000,0x00000000,0x0000a492,0x000124db,
0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
{0x00000000,0x00000000,0x00012492,0x000126db,
0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000}
},
{ /* version 6, passes 1 */
{0x00000000,0x00000000,0x00001249,0x00001249,
0x0000124a,0x0000124a,0x00001252,0x00001252},
{0x00000000,0x00000000,0x00001249,0x00009292,
0x00009492,0x00009252,0x00001252,0x00001252},
{0x00000000,0x00000000,0x0000924a,0x00009493,
0x0000a493,0x00009292,0x00001252,0x00001252},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0000a493,0x0000a49b,0x00009292,0x00009292},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0000a493,0x0000a49b,0x00009292,0x00009292},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0001249b,0x0000a49b,0x00009493,0x00009292},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x000124db,0x000124db,0x00009493,0x00009493},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x000124db,0x000124db,0x0000a49b,0x00009493},
{0x00000000,0x00000000,0x0000924a,0x000124db,
0x000126dc,0x000124db,0x0000a49b,0x00009493},
{0x00000000,0x00000000,0x0000924a,0x000124db,
0x000126dc,0x000126dc,0x0000a49b,0x0000a49b},
{0x00000000,0x00000000,0x0000924a,0x000124db,
0x000136e4,0x000126dc,0x000124db,0x0000a49b},
{0x00000000,0x00000000,0x00009492,0x000126db,
0x000136e4,0x000126dc,0x000124db,0x0000a49b},
{0x00000000,0x00000000,0x00009492,0x000126db,
0x0001b724,0x000136e4,0x000126dc,0x000124db},
{0x00000000,0x00000000,0x00009492,0x000126db,
0x0001b724,0x000136e4,0x000126dc,0x000124db},
{0x00000000,0x00000000,0x0000a492,0x000136db,
0x0001c924,0x0001b724,0x000136e4,0x000126dc},
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000}
}
},
{ /* version 7 */
{ /* version 7, passes 0 */
{0x00000000,0x00000000,0x00001249,0x00001249,
0x00009252,0x00009292,0x00009493,0x00009493},
{0x00000000,0x00000000,0x00001249,0x00009493,
0x0000a493,0x000124db,0x000126dc,0x00009493},
{0x00000000,0x00000000,0x00001249,0x0000a49b,
0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x000126dc,0x000136e4,0x0001b725,0x000124db},
{0x00000000,0x00000000,0x00009292,0x0000a49b,
0x000136e4,0x0001b724,0x0001b725,0x000126dc},
{0x00000000,0x00000000,0x00009292,0x000124db,
0x000136e4,0x0001b724,0x0001b725,0x000126dc},
{0x00000000,0x00000000,0x00009492,0x000124db,
0x000136e4,0x0001b724,0x0001c96e,0x000136e4},
{0x00000000,0x00000000,0x00009492,0x000124db,
0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
{0x00000000,0x00000000,0x0000a492,0x000124db,
0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
{0x00000000,0x00000000,0x0000a492,0x000124db,
0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
{0x00000000,0x00000000,0x0000a492,0x000126db,
0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
{0x00000000,0x00000000,0x0000a492,0x000126db,
0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
{0x00000000,0x00000000,0x0000a492,0x000126db,
0x0001b924,0x0001c92d,0x00024b76,0x0002496e},
{0x00000000,0x00000000,0x00012492,0x000136db,
0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf},
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000}
},
{ /* version 7, passes 1 */
{0x00000000,0x00000000,0x00001249,0x00001249,
0x0000124a,0x0000124a,0x00001252,0x00001252},
{0x00000000,0x00000000,0x0000924a,0x00009493,
0x00009492,0x00009292,0x00001252,0x00001252},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0000a493,0x0000a49b,0x00001252,0x00001252},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0000a493,0x0000a49b,0x00009292,0x00009292},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x0000a493,0x0000a49b,0x00009292,0x00009292},
{0x00000000,0x00000000,0x0000924a,0x0000a49b,
0x000126dc,0x0000a49b,0x00009493,0x00009292},
{0x00000000,0x00000000,0x0000924a,0x000124db,
0x000126dc,0x000124db,0x00009493,0x00009493},
{0x00000000,0x00000000,0x0000924a,0x000124db,
0x000136e4,0x000124db,0x0000a49b,0x00009493},
{0x00000000,0x00000000,0x0000924a,0x000136db,
0x0001b724,0x000124db,0x0000a49b,0x00009493},
{0x00000000,0x00000000,0x0000924a,0x000136db,
0x0001b724,0x000126dc,0x0000a49b,0x0000a49b},
{0x00000000,0x00000000,0x00009292,0x000136db,
0x0001b724,0x000126dc,0x000124db,0x0000a49b},
{0x00000000,0x00000000,0x00009492,0x000136db,
0x0001b724,0x000126dc,0x000124db,0x0000a49b},
{0x00000000,0x00000000,0x0000a492,0x000136db,
0x0001b724,0x000136e4,0x000126dc,0x000124db},
{0x00000000,0x00000000,0x0000a492,0x000136db,
0x0001b724,0x000136e4,0x000126dc,0x000124db},
{0x00000000,0x00000000,0x00012492,0x0001b6db,
0x0001c924,0x0001b724,0x000136e4,0x000126dc},
{0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000}
}
}
};

View File

@@ -0,0 +1,48 @@
/* Linux driver for Philips webcam
(C) 2004-2006 Luc Saillard (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
*/
/* Entries for the Kiara (730/740/750) camera */
#ifndef PWC_KIARA_H
#define PWC_KIARA_H
#include "pwc.h"
#define PWC_FPS_MAX_KIARA 6
struct Kiara_table_entry
{
char alternate; /* USB alternate interface */
unsigned short packetsize; /* Normal packet size */
unsigned short bandlength; /* Bandlength when decompressing */
unsigned char mode[12]; /* precomputed mode settings for cam */
};
extern const struct Kiara_table_entry Kiara_table[PSZ_MAX][PWC_FPS_MAX_KIARA][4];
extern const unsigned int KiaraRomTable[8][2][16][8];
extern const unsigned int Kiara_fps_vector[PWC_FPS_MAX_KIARA];
#endif

View File

@@ -0,0 +1,93 @@
/* Linux driver for Philips webcam
Various miscellaneous functions and tables.
(C) 1999-2003 Nemosoft Unv.
(C) 2004-2006 Luc Saillard (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
*/
#include "pwc.h"
const int pwc_image_sizes[PSZ_MAX][2] =
{
{ 128, 96 }, /* sqcif */
{ 160, 120 }, /* qsif */
{ 176, 144 }, /* qcif */
{ 320, 240 }, /* sif */
{ 352, 288 }, /* cif */
{ 640, 480 }, /* vga */
};
/* x,y -> PSZ_ */
int pwc_get_size(struct pwc_device *pdev, int width, int height)
{
int i;
/* Find the largest size supported by the camera that fits into the
requested size. */
for (i = PSZ_MAX - 1; i >= 0; i--) {
if (!(pdev->image_mask & (1 << i)))
continue;
if (pwc_image_sizes[i][0] <= width &&
pwc_image_sizes[i][1] <= height)
return i;
}
/* No mode found, return the smallest mode we have */
for (i = 0; i < PSZ_MAX; i++) {
if (pdev->image_mask & (1 << i))
return i;
}
/* Never reached there always is atleast one supported mode */
return 0;
}
/* initialize variables depending on type and decompressor */
void pwc_construct(struct pwc_device *pdev)
{
if (DEVICE_USE_CODEC1(pdev->type)) {
pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF;
pdev->vcinterface = 2;
pdev->vendpoint = 4;
pdev->frame_header_size = 0;
pdev->frame_trailer_size = 0;
} else if (DEVICE_USE_CODEC3(pdev->type)) {
pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
pdev->vcinterface = 3;
pdev->vendpoint = 5;
pdev->frame_header_size = TOUCAM_HEADER_SIZE;
pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE;
} else /* if (DEVICE_USE_CODEC2(pdev->type)) */ {
pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA;
pdev->vcinterface = 3;
pdev->vendpoint = 4;
pdev->frame_header_size = 0;
pdev->frame_trailer_size = 0;
}
}

View File

@@ -0,0 +1,66 @@
/* SQCIF */
{
{0, 0, {0x04, 0x01, 0x03}},
{8, 0, {0x05, 0x01, 0x03}},
{7, 0, {0x08, 0x01, 0x03}},
{7, 0, {0x0A, 0x01, 0x03}},
{6, 0, {0x0C, 0x01, 0x03}},
{5, 0, {0x0F, 0x01, 0x03}},
{4, 0, {0x14, 0x01, 0x03}},
{3, 0, {0x18, 0x01, 0x03}},
},
/* QSIF */
{
{0},
{0},
{0},
{0},
{0},
{0},
{0},
{0},
},
/* QCIF */
{
{0, 0, {0x04, 0x01, 0x02}},
{8, 0, {0x05, 0x01, 0x02}},
{7, 0, {0x08, 0x01, 0x02}},
{6, 0, {0x0A, 0x01, 0x02}},
{5, 0, {0x0C, 0x01, 0x02}},
{4, 0, {0x0F, 0x01, 0x02}},
{1, 0, {0x14, 0x01, 0x02}},
{1, 0, {0x18, 0x01, 0x02}},
},
/* SIF */
{
{0},
{0},
{0},
{0},
{0},
{0},
{0},
{0},
},
/* CIF */
{
{4, 0, {0x04, 0x01, 0x01}},
{7, 1, {0x05, 0x03, 0x01}},
{6, 1, {0x08, 0x03, 0x01}},
{4, 1, {0x0A, 0x03, 0x01}},
{3, 1, {0x0C, 0x03, 0x01}},
{2, 1, {0x0F, 0x03, 0x01}},
{0},
{0},
},
/* VGA */
{
{0},
{0},
{0},
{0},
{0},
{0},
{0},
{0},
},

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,63 @@
/* Linux driver for Philips webcam
(C) 2004-2006 Luc Saillard (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
*/
/* This tables contains entries for the 675/680/690 (Timon) camera, with
4 different qualities (no compression, low, medium, high).
It lists the bandwidth requirements for said mode by its alternate interface
number. An alternate of 0 means that the mode is unavailable.
There are 6 * 4 * 4 entries:
6 different resolutions subqcif, qsif, qcif, sif, cif, vga
6 framerates: 5, 10, 15, 20, 25, 30
4 compression modi: none, low, medium, high
When an uncompressed mode is not available, the next available compressed mode
will be chosen (unless the decompressor is absent). Sometimes there are only
1 or 2 compressed modes available; in that case entries are duplicated.
*/
#ifndef PWC_TIMON_H
#define PWC_TIMON_H
#include "pwc.h"
#define PWC_FPS_MAX_TIMON 6
struct Timon_table_entry
{
char alternate; /* USB alternate interface */
unsigned short packetsize; /* Normal packet size */
unsigned short bandlength; /* Bandlength when decompressing */
unsigned char mode[13]; /* precomputed mode settings for cam */
};
extern const struct Timon_table_entry Timon_table[PSZ_MAX][PWC_FPS_MAX_TIMON][4];
extern const unsigned int TimonRomTable [16][2][16][8];
extern const unsigned int Timon_fps_vector[PWC_FPS_MAX_TIMON];
#endif

View File

@@ -0,0 +1,107 @@
/* Linux driver for Philips webcam
Decompression frontend.
(C) 1999-2003 Nemosoft Unv.
(C) 2004-2006 Luc Saillard (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
vim: set ts=8:
*/
#include <asm/current.h>
#include <asm/types.h>
#include "pwc.h"
#include "pwc-dec1.h"
#include "pwc-dec23.h"
int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
{
int n, line, col;
void *yuv, *image;
u16 *src;
u16 *dsty, *dstu, *dstv;
image = vb2_plane_vaddr(&fbuf->vb, 0);
yuv = fbuf->data + pdev->frame_header_size; /* Skip header */
/* Raw format; that's easy... */
if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
{
struct pwc_raw_frame *raw_frame = image;
raw_frame->type = cpu_to_le16(pdev->type);
raw_frame->vbandlength = cpu_to_le16(pdev->vbandlength);
/* cmd_buf is always 4 bytes, but sometimes, only the
* first 3 bytes is filled (Nala case). We can
* determine this using the type of the webcam */
memcpy(raw_frame->cmd, pdev->cmd_buf, 4);
memcpy(raw_frame+1, yuv, pdev->frame_size);
vb2_set_plane_payload(&fbuf->vb, 0,
pdev->frame_size + sizeof(struct pwc_raw_frame));
return 0;
}
vb2_set_plane_payload(&fbuf->vb, 0,
pdev->width * pdev->height * 3 / 2);
if (pdev->vbandlength == 0) {
/* Uncompressed mode.
*
* We do some byte shuffling here to go from the
* native format to YUV420P.
*/
src = (u16 *)yuv;
n = pdev->width * pdev->height;
dsty = (u16 *)(image);
dstu = (u16 *)(image + n);
dstv = (u16 *)(image + n + n / 4);
for (line = 0; line < pdev->height; line++) {
for (col = 0; col < pdev->width; col += 4) {
*dsty++ = *src++;
*dsty++ = *src++;
if (line & 1)
*dstv++ = *src++;
else
*dstu++ = *src++;
}
}
return 0;
}
/*
* Compressed;
* the decompressor routines will write the data in planar format
* immediately.
*/
if (DEVICE_USE_CODEC1(pdev->type)) {
/* TODO & FIXME */
PWC_ERROR("This chipset is not supported for now\n");
return -ENXIO; /* No such device or address: missing decompressor */
} else {
pwc_dec23_decompress(pdev, yuv, image);
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,395 @@
/* (C) 1999-2003 Nemosoft Unv.
(C) 2004-2006 Luc Saillard (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
*/
#ifndef PWC_H
#define PWC_H
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <linux/mutex.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <asm/errno.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-fh.h>
#include <media/v4l2-event.h>
#include <media/videobuf2-vmalloc.h>
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
#include <linux/input.h>
#endif
#include "pwc-dec1.h"
#include "pwc-dec23.h"
/* Version block */
#define PWC_VERSION "10.0.15"
#define PWC_NAME "pwc"
#define PFX PWC_NAME ": "
/* Trace certain actions in the driver */
#define PWC_DEBUG_LEVEL_MODULE (1<<0)
#define PWC_DEBUG_LEVEL_PROBE (1<<1)
#define PWC_DEBUG_LEVEL_OPEN (1<<2)
#define PWC_DEBUG_LEVEL_READ (1<<3)
#define PWC_DEBUG_LEVEL_MEMORY (1<<4)
#define PWC_DEBUG_LEVEL_FLOW (1<<5)
#define PWC_DEBUG_LEVEL_SIZE (1<<6)
#define PWC_DEBUG_LEVEL_IOCTL (1<<7)
#define PWC_DEBUG_LEVEL_TRACE (1<<8)
#define PWC_DEBUG_MODULE(fmt, args...) PWC_DEBUG(MODULE, fmt, ##args)
#define PWC_DEBUG_PROBE(fmt, args...) PWC_DEBUG(PROBE, fmt, ##args)
#define PWC_DEBUG_OPEN(fmt, args...) PWC_DEBUG(OPEN, fmt, ##args)
#define PWC_DEBUG_READ(fmt, args...) PWC_DEBUG(READ, fmt, ##args)
#define PWC_DEBUG_MEMORY(fmt, args...) PWC_DEBUG(MEMORY, fmt, ##args)
#define PWC_DEBUG_FLOW(fmt, args...) PWC_DEBUG(FLOW, fmt, ##args)
#define PWC_DEBUG_SIZE(fmt, args...) PWC_DEBUG(SIZE, fmt, ##args)
#define PWC_DEBUG_IOCTL(fmt, args...) PWC_DEBUG(IOCTL, fmt, ##args)
#define PWC_DEBUG_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args)
#ifdef CONFIG_USB_PWC_DEBUG
#define PWC_DEBUG_LEVEL (PWC_DEBUG_LEVEL_MODULE)
#define PWC_DEBUG(level, fmt, args...) do {\
if ((PWC_DEBUG_LEVEL_ ##level) & pwc_trace) \
printk(KERN_DEBUG PFX fmt, ##args); \
} while (0)
#define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args)
#define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args)
#define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args)
#define PWC_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args)
#else /* if ! CONFIG_USB_PWC_DEBUG */
#define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args)
#define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args)
#define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args)
#define PWC_TRACE(fmt, args...) do { } while(0)
#define PWC_DEBUG(level, fmt, args...) do { } while(0)
#define pwc_trace 0
#endif
/* Defines for ToUCam cameras */
#define TOUCAM_HEADER_SIZE 8
#define TOUCAM_TRAILER_SIZE 4
#define FEATURE_MOTOR_PANTILT 0x0001
#define FEATURE_CODEC1 0x0002
#define FEATURE_CODEC2 0x0004
#define MAX_WIDTH 640
#define MAX_HEIGHT 480
/* Ignore errors in the first N frames, to allow for startup delays */
#define FRAME_LOWMARK 5
/* Size and number of buffers for the ISO pipe. */
#define MAX_ISO_BUFS 3
#define ISO_FRAMES_PER_DESC 10
#define ISO_MAX_FRAME_SIZE 960
#define ISO_BUFFER_SIZE (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE)
/* Maximum size after decompression is 640x480 YUV data, 1.5 * 640 * 480 */
#define PWC_FRAME_SIZE (460800 + TOUCAM_HEADER_SIZE + TOUCAM_TRAILER_SIZE)
/* Absolute minimum and maximum number of buffers available for mmap() */
#define MIN_FRAMES 2
#define MAX_FRAMES 16
/* Some macros to quickly find the type of a webcam */
#define DEVICE_USE_CODEC1(x) ((x)<675)
#define DEVICE_USE_CODEC2(x) ((x)>=675 && (x)<700)
#define DEVICE_USE_CODEC3(x) ((x)>=700)
#define DEVICE_USE_CODEC23(x) ((x)>=675)
/* Request types: video */
#define SET_LUM_CTL 0x01
#define GET_LUM_CTL 0x02
#define SET_CHROM_CTL 0x03
#define GET_CHROM_CTL 0x04
#define SET_STATUS_CTL 0x05
#define GET_STATUS_CTL 0x06
#define SET_EP_STREAM_CTL 0x07
#define GET_EP_STREAM_CTL 0x08
#define GET_XX_CTL 0x09
#define SET_XX_CTL 0x0A
#define GET_XY_CTL 0x0B
#define SET_XY_CTL 0x0C
#define SET_MPT_CTL 0x0D
#define GET_MPT_CTL 0x0E
/* Selectors for the Luminance controls [GS]ET_LUM_CTL */
#define AGC_MODE_FORMATTER 0x2000
#define PRESET_AGC_FORMATTER 0x2100
#define SHUTTER_MODE_FORMATTER 0x2200
#define PRESET_SHUTTER_FORMATTER 0x2300
#define PRESET_CONTOUR_FORMATTER 0x2400
#define AUTO_CONTOUR_FORMATTER 0x2500
#define BACK_LIGHT_COMPENSATION_FORMATTER 0x2600
#define CONTRAST_FORMATTER 0x2700
#define DYNAMIC_NOISE_CONTROL_FORMATTER 0x2800
#define FLICKERLESS_MODE_FORMATTER 0x2900
#define AE_CONTROL_SPEED 0x2A00
#define BRIGHTNESS_FORMATTER 0x2B00
#define GAMMA_FORMATTER 0x2C00
/* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */
#define WB_MODE_FORMATTER 0x1000
#define AWB_CONTROL_SPEED_FORMATTER 0x1100
#define AWB_CONTROL_DELAY_FORMATTER 0x1200
#define PRESET_MANUAL_RED_GAIN_FORMATTER 0x1300
#define PRESET_MANUAL_BLUE_GAIN_FORMATTER 0x1400
#define COLOUR_MODE_FORMATTER 0x1500
#define SATURATION_MODE_FORMATTER1 0x1600
#define SATURATION_MODE_FORMATTER2 0x1700
/* Selectors for the Status controls [GS]ET_STATUS_CTL */
#define SAVE_USER_DEFAULTS_FORMATTER 0x0200
#define RESTORE_USER_DEFAULTS_FORMATTER 0x0300
#define RESTORE_FACTORY_DEFAULTS_FORMATTER 0x0400
#define READ_AGC_FORMATTER 0x0500
#define READ_SHUTTER_FORMATTER 0x0600
#define READ_RED_GAIN_FORMATTER 0x0700
#define READ_BLUE_GAIN_FORMATTER 0x0800
/* Formatters for the motorized pan & tilt [GS]ET_MPT_CTL */
#define PT_RELATIVE_CONTROL_FORMATTER 0x01
#define PT_RESET_CONTROL_FORMATTER 0x02
#define PT_STATUS_FORMATTER 0x03
/* Enumeration of image sizes */
#define PSZ_SQCIF 0x00
#define PSZ_QSIF 0x01
#define PSZ_QCIF 0x02
#define PSZ_SIF 0x03
#define PSZ_CIF 0x04
#define PSZ_VGA 0x05
#define PSZ_MAX 6
struct pwc_raw_frame {
__le16 type; /* type of the webcam */
__le16 vbandlength; /* Size of 4 lines compressed (used by the
decompressor) */
__u8 cmd[4]; /* the four byte of the command (in case of
nala, only the first 3 bytes is filled) */
__u8 rawframe[0]; /* frame_size = H / 4 * vbandlength */
} __packed;
/* intermediate buffers with raw data from the USB cam */
struct pwc_frame_buf
{
struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */
struct list_head list;
void *data;
int filled; /* number of bytes filled */
};
struct pwc_device
{
struct video_device vdev;
struct v4l2_device v4l2_dev;
/* Pointer to our usb_device, may be NULL after unplug */
struct usb_device *udev;
struct mutex udevlock;
/* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
int type;
int release; /* release number */
int features; /* feature bits */
/*** Video data ***/
struct file *capt_file; /* file doing video capture */
struct mutex capt_file_lock;
int vendpoint; /* video isoc endpoint */
int vcinterface; /* video control interface */
int valternate; /* alternate interface needed */
int vframes; /* frames-per-second */
int pixfmt; /* pixelformat: V4L2_PIX_FMT_YUV420 or _PWCX */
int vframe_count; /* received frames */
int vmax_packet_size; /* USB maxpacket size */
int vlast_packet_size; /* for frame synchronisation */
int visoc_errors; /* number of contiguous ISOC errors */
int vbandlength; /* compressed band length; 0 is uncompressed */
char vsync; /* used by isoc handler */
char vmirror; /* for ToUCaM series */
char power_save; /* Do powersaving for this cam */
unsigned char cmd_buf[13];
unsigned char *ctrl_buf;
struct urb *urbs[MAX_ISO_BUFS];
char iso_init;
/* videobuf2 queue and queued buffers list */
struct vb2_queue vb_queue;
struct list_head queued_bufs;
spinlock_t queued_bufs_lock;
/*
* Frame currently being filled, this only gets touched by the
* isoc urb complete handler, and by stream start / stop since
* start / stop touch it before / after starting / killing the urbs
* no locking is needed around this
*/
struct pwc_frame_buf *fill_buf;
int frame_header_size, frame_trailer_size;
int frame_size;
int frame_total_size; /* including header & trailer */
int drop_frames;
union { /* private data for decompression engine */
struct pwc_dec1_private dec1;
struct pwc_dec23_private dec23;
};
/*
* We have an 'image' and a 'view', where 'image' is the fixed-size img
* as delivered by the camera, and 'view' is the size requested by the
* program. The camera image is centered in this viewport, laced with
* a gray or black border. view_min <= image <= view <= view_max;
*/
int image_mask; /* supported sizes */
int width, height; /* current resolution */
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
struct input_dev *button_dev; /* webcam snapshot button input */
char button_phys[64];
#endif
/* controls */
struct v4l2_ctrl_handler ctrl_handler;
u16 saturation_fmt;
struct v4l2_ctrl *brightness;
struct v4l2_ctrl *contrast;
struct v4l2_ctrl *saturation;
struct v4l2_ctrl *gamma;
struct {
/* awb / red-blue balance cluster */
struct v4l2_ctrl *auto_white_balance;
struct v4l2_ctrl *red_balance;
struct v4l2_ctrl *blue_balance;
/* usb ctrl transfers are slow, so we cache things */
int color_bal_valid;
unsigned long last_color_bal_update; /* In jiffies */
s32 last_red_balance;
s32 last_blue_balance;
};
struct {
/* autogain / gain cluster */
struct v4l2_ctrl *autogain;
struct v4l2_ctrl *gain;
int gain_valid;
unsigned long last_gain_update; /* In jiffies */
s32 last_gain;
};
struct {
/* exposure_auto / exposure cluster */
struct v4l2_ctrl *exposure_auto;
struct v4l2_ctrl *exposure;
int exposure_valid;
unsigned long last_exposure_update; /* In jiffies */
s32 last_exposure;
};
struct v4l2_ctrl *colorfx;
struct {
/* autocontour/contour cluster */
struct v4l2_ctrl *autocontour;
struct v4l2_ctrl *contour;
};
struct v4l2_ctrl *backlight;
struct v4l2_ctrl *flicker;
struct v4l2_ctrl *noise_reduction;
struct v4l2_ctrl *save_user;
struct v4l2_ctrl *restore_user;
struct v4l2_ctrl *restore_factory;
struct v4l2_ctrl *awb_speed;
struct v4l2_ctrl *awb_delay;
struct {
/* motor control cluster */
struct v4l2_ctrl *motor_pan;
struct v4l2_ctrl *motor_tilt;
struct v4l2_ctrl *motor_pan_reset;
struct v4l2_ctrl *motor_tilt_reset;
};
/* CODEC3 models have both gain and exposure controlled by autogain */
struct v4l2_ctrl *autogain_expo_cluster[3];
};
/* Global variables */
#ifdef CONFIG_USB_PWC_DEBUG
extern int pwc_trace;
#endif
int pwc_test_n_set_capt_file(struct pwc_device *pdev, struct file *file);
/** Functions in pwc-misc.c */
/* sizes in pixels */
extern const int pwc_image_sizes[PSZ_MAX][2];
int pwc_get_size(struct pwc_device *pdev, int width, int height);
void pwc_construct(struct pwc_device *pdev);
/** Functions in pwc-ctrl.c */
/* Request a certain video mode. Returns < 0 if not possible */
extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
int pixfmt, int frames, int *compression, int send_to_cam);
extern unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size);
extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor);
extern int send_control_msg(struct pwc_device *pdev,
u8 request, u16 value, void *buf, int buflen);
/* Control get / set helpers */
int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data);
int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data);
int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data);
#define pwc_set_s8_ctrl pwc_set_u8_ctrl
int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *dat);
int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data);
int pwc_button_ctrl(struct pwc_device *pdev, u16 value);
int pwc_init_controls(struct pwc_device *pdev);
/* Power down or up the camera; not supported by all models */
extern void pwc_camera_power(struct pwc_device *pdev, int power);
extern const struct v4l2_ioctl_ops pwc_ioctl_ops;
/** pwc-uncompress.c */
/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf);
#endif