V4L/DVB (3835): [PATCH] update pwc driver

Add v4l2 compatibility
Include the decompressor (legal problem has been resolv by Alan Cox)
Faster decoder and easier to maintain, optimize, ...
Can export to userland compressed stream
Support more cameras, lot of bugs are fixed.

Signed-off-by: Luc Saillard <luc@saillard.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
Luc Saillard 2006-04-24 10:29:46 -03:00 committed by Mauro Carvalho Chehab
parent d9e12f25cf
commit 2b455db6d4
18 changed files with 5553 additions and 1265 deletions

View File

@ -7,6 +7,7 @@ config USB_PWC
* 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'
@ -19,10 +20,18 @@ config USB_PWC
and never will be, but the 665 and 720/20 are supported by other
drivers.
See <file:Documentation/usb/philips.txt> for more information and
installation instructions.
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 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.

View File

@ -1,3 +1,12 @@
pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o pwc-timon.o pwc-kiara.o
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
ifeq ($(CONFIG_USB_PWC_DEBUG),y)
EXTRA_CFLAGS += -DCONFIG_PWC_DEBUG=1
else
EXTRA_CFLAGS += -DCONFIG_PWC_DEBUG=0
endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,50 @@
/* 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-dec1.h"
void pwc_dec1_init(int type, int release, void *buffer, void *table)
{
}
void pwc_dec1_exit(void)
{
}
int pwc_dec1_alloc(struct pwc_device *pwc)
{
pwc->decompress_data = kmalloc(sizeof(struct pwc_dec1_private), GFP_KERNEL);
if (pwc->decompress_data == NULL)
return -ENOMEM;
return 0;
}

View File

@ -0,0 +1,43 @@
/* 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 "pwc.h"
struct pwc_dec1_private
{
int version;
};
int pwc_dec1_alloc(struct pwc_device *pwc);
void pwc_dec1_init(int type, int release, void *buffer, void *private_data);
void pwc_dec1_exit(void);
#endif

View File

@ -0,0 +1,941 @@
/* 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 <media/pwc-ioctl.h>
#include <linux/string.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
/*
* ENABLE_BAYER_DECODER
* 0: bayer decoder is not build (save some space)
* 1: bayer decoder is build and can be used
*/
#define ENABLE_BAYER_DECODER 0
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 */
int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd)
{
int flags, version, shift, i;
struct pwc_dec23_private *pdec;
if (pwc->decompress_data == NULL) {
pdec = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
if (pdec == NULL)
return -ENOMEM;
pwc->decompress_data = pdec;
}
pdec = pwc->decompress_data;
if (DEVICE_USE_CODEC3(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
return 0;
}
/*
* 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
}
#if ENABLE_BAYER_DECODER
/*
* Format: 8x2 pixels
* . G . G . G . G . G . G . G
* . . . . . . . . . . . . . .
* . G . G . G . G . G . G . G
* . . . . . . . . . . . . . .
* or
* . . . . . . . . . . . . . .
* G . G . G . G . G . G . G .
* . . . . . . . . . . . . . .
* G . G . G . G . G . G . G .
*/
static void copy_image_block_Green(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;
unsigned char *d = dst;
const int *c = src;
d[0] = cm[c[0] >> scalebits];
d[2] = cm[c[1] >> scalebits];
d[4] = cm[c[2] >> scalebits];
d[6] = cm[c[3] >> scalebits];
d[8] = cm[c[4] >> scalebits];
d[10] = cm[c[5] >> scalebits];
d[12] = cm[c[6] >> scalebits];
d[14] = cm[c[7] >> scalebits];
d = dst + bytes_per_line;
d[0] = cm[c[8] >> scalebits];
d[2] = cm[c[9] >> scalebits];
d[4] = cm[c[10] >> scalebits];
d[6] = cm[c[11] >> scalebits];
d[8] = cm[c[12] >> scalebits];
d[10] = cm[c[13] >> scalebits];
d[12] = cm[c[14] >> scalebits];
d[14] = cm[c[15] >> scalebits];
#else
int i;
unsigned char *d;
const int *c = src;
d = dst;
for (i = 0; i < 8; i++, c++)
d[i*2] = CLAMP((*c) >> scalebits);
d = dst + bytes_per_line;
for (i = 0; i < 8; i++, c++)
d[i*2] = CLAMP((*c) >> scalebits);
#endif
}
#endif
#if ENABLE_BAYER_DECODER
/*
* Format: 4x4 pixels
* R . R . R . R
* . B . B . B .
* R . R . R . R
* . B . B . B .
*/
static void copy_image_block_RedBlue(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;
unsigned char *d = dst;
const int *c = src;
d[0] = cm[c[0] >> scalebits];
d[2] = cm[c[1] >> scalebits];
d[4] = cm[c[2] >> scalebits];
d[6] = cm[c[3] >> scalebits];
d = dst + bytes_per_line;
d[1] = cm[c[4] >> scalebits];
d[3] = cm[c[5] >> scalebits];
d[5] = cm[c[6] >> scalebits];
d[7] = cm[c[7] >> scalebits];
d = dst + bytes_per_line*2;
d[0] = cm[c[8] >> scalebits];
d[2] = cm[c[9] >> scalebits];
d[4] = cm[c[10] >> scalebits];
d[6] = cm[c[11] >> scalebits];
d = dst + bytes_per_line*3;
d[1] = cm[c[12] >> scalebits];
d[3] = cm[c[13] >> scalebits];
d[5] = cm[c[14] >> scalebits];
d[7] = cm[c[15] >> scalebits];
#else
int i;
unsigned char *d;
const int *c = src;
d = dst;
for (i = 0; i < 4; i++, c++)
d[i*2] = CLAMP((*c) >> scalebits);
d = dst + bytes_per_line;
for (i = 0; i < 4; i++, c++)
d[i*2+1] = CLAMP((*c) >> scalebits);
d = dst + bytes_per_line*2;
for (i = 0; i < 4; i++, c++)
d[i*2] = CLAMP((*c) >> scalebits);
d = dst + bytes_per_line*3;
for (i = 0; i < 4; i++, c++)
d[i*2+1] = CLAMP((*c) >> scalebits);
#endif
}
#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;
}
}
#if ENABLE_BAYER_DECODER
/*
* Size need to be a multiple of 8 in width
*
* Return a block of four line encoded like this:
*
* G R G R G R G R G R G R G R G R
* B G B G B G B G B G B G B G B G
* G R G R G R G R G R G R G R G R
* B G B G B G B G B G B G B G B G
*
*/
static void DecompressBandBayer(struct pwc_dec23_private *pdec,
const unsigned char *rawyuv,
unsigned char *rgbbayer,
unsigned int compressed_image_width,
unsigned int real_image_width)
{
int compression_index, nblocks;
const unsigned char *ptable0004;
const unsigned char *ptable8004;
unsigned char *dest;
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 RB component */
nblocks = compressed_image_width / 4;
ptable0004 = pdec->table_0004_pass1[compression_index];
ptable8004 = pdec->table_8004_pass1[compression_index];
dest = rgbbayer;
/* Each block decode a square of 4x4 */
while (nblocks) {
decode_block(pdec, ptable0004, ptable8004);
copy_image_block_RedBlue(pdec->temp_colors, rgbbayer, real_image_width, pdec->scalebits);
dest += 8;
nblocks--;
}
/* pass 2: uncompress G 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_Green(pdec->temp_colors, rgbbayer+1, real_image_width, pdec->scalebits);
decode_block(pdec, ptable0004, ptable8004);
copy_image_block_Green(pdec->temp_colors, rgbbayer+real_image_width, real_image_width, pdec->scalebits);
rgbbayer += 16;
nblocks -= 2;
}
}
#endif
/**
*
* Uncompress a pwc23 buffer.
*
* pwc.view: size of the image wanted
* pwc.image: size of the image returned by the camera
* pwc.offset: (x,y) to displayer image in the view
*
* src: raw data
* dst: image output
* flags: PWCX_FLAG_PLANAR or PWCX_FLAG_BAYER
*/
void pwc_dec23_decompress(const struct pwc_device *pwc,
const void *src,
void *dst,
int flags)
{
int bandlines_left, stride, bytes_per_block;
bandlines_left = pwc->image.y / 4;
bytes_per_block = pwc->view.x * 4;
if (flags & PWCX_FLAG_BAYER) {
#if ENABLE_BAYER_DECODER
/* RGB Bayer format */
unsigned char *rgbout;
stride = pwc->view.x * pwc->offset.y;
rgbout = dst + stride + pwc->offset.x;
while (bandlines_left--) {
DecompressBandBayer(pwc->decompress_data,
src,
rgbout,
pwc->image.x, pwc->view.x);
src += pwc->vbandlength;
rgbout += bytes_per_block;
}
#else
memcpy(dst, 0, pwc->view.x * pwc->view.y);
#endif
} else {
/* YUV420P image format */
unsigned char *pout_planar_y;
unsigned char *pout_planar_u;
unsigned char *pout_planar_v;
unsigned int plane_size;
plane_size = pwc->view.x * pwc->view.y;
/* offset in Y plane */
stride = pwc->view.x * pwc->offset.y;
pout_planar_y = dst + stride + pwc->offset.x;
/* offsets in U/V planes */
stride = (pwc->view.x * pwc->offset.y) / 4 + pwc->offset.x / 2;
pout_planar_u = dst + plane_size + stride;
pout_planar_v = dst + plane_size + plane_size / 4 + stride;
while (bandlines_left--) {
DecompressBand23(pwc->decompress_data,
src,
pout_planar_y, pout_planar_u, pout_planar_v,
pwc->image.x, pwc->view.x);
src += pwc->vbandlength;
pout_planar_y += bytes_per_block;
pout_planar_u += pwc->view.x;
pout_planar_v += pwc->view.x;
}
}
}
void pwc_dec23_exit(void)
{
/* Do nothing */
}
/**
* Allocate a private structure used by lookup table.
* You must call kfree() to free the memory allocated.
*/
int pwc_dec23_alloc(struct pwc_device *pwc)
{
pwc->decompress_data = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
if (pwc->decompress_data == NULL)
return -ENOMEM;
return 0;
}
/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */

View File

@ -0,0 +1,67 @@
/* 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
#include "pwc.h"
struct pwc_dec23_private
{
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];
};
int pwc_dec23_alloc(struct pwc_device *pwc);
int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd);
void pwc_dec23_exit(void);
void pwc_dec23_decompress(const struct pwc_device *pwc,
const void *src,
void *dst,
int flags);
#endif
/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* Linux driver for Philips webcam
(C) 2004 Luc Saillard (luc@saillard.org)
(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.
@ -316,3 +316,576 @@ const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
},
};
/*
* 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

@ -1,5 +1,5 @@
/* Linux driver for Philips webcam
(C) 2004 Luc Saillard (luc@saillard.org)
(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.
@ -27,7 +27,7 @@
#ifndef PWC_KIARA_H
#define PWC_KIARA_H
#include "pwc-ioctl.h"
#include <media/pwc-ioctl.h>
struct Kiara_table_entry
{
@ -37,8 +37,8 @@ struct Kiara_table_entry
unsigned char mode[12]; /* precomputed mode settings for cam */
};
const extern struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4];
const extern unsigned int KiaraRomTable[8][2][16][8];
extern const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4];
extern const unsigned int KiaraRomTable[8][2][16][8];
#endif

View File

@ -1,7 +1,7 @@
/* Linux driver for Philips webcam
Various miscellaneous functions and tables.
(C) 1999-2003 Nemosoft Unv.
(C) 2004 Luc Saillard (luc@saillard.org)
(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.
@ -24,18 +24,17 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/slab.h>
#include "pwc.h"
struct pwc_coord pwc_image_sizes[PSZ_MAX] =
const struct pwc_coord pwc_image_sizes[PSZ_MAX] =
{
{ 128, 96, 0 },
{ 160, 120, 0 },
{ 176, 144, 0 },
{ 320, 240, 0 },
{ 352, 288, 0 },
{ 640, 480, 0 },
{ 128, 96, 0 }, /* sqcif */
{ 160, 120, 0 }, /* qsif */
{ 176, 144, 0 }, /* qcif */
{ 320, 240, 0 }, /* sif */
{ 352, 288, 0 }, /* cif */
{ 640, 480, 0 }, /* vga */
};
/* x,y -> PSZ_ */
@ -52,7 +51,7 @@ int pwc_decode_size(struct pwc_device *pdev, int width, int height)
{
if (width > pdev->abs_max.x || height > pdev->abs_max.y)
{
Debug("VIDEO_PALETTE_RAW: going beyond abs_max.\n");
PWC_DEBUG_SIZE("VIDEO_PALETTE_RAW: going beyond abs_max.\n");
return -1;
}
}
@ -60,7 +59,7 @@ int pwc_decode_size(struct pwc_device *pdev, int width, int height)
{
if (width > pdev->view_max.x || height > pdev->view_max.y)
{
Debug("VIDEO_PALETTE_ not RAW: going beyond view_max.\n");
PWC_DEBUG_SIZE("VIDEO_PALETTE_not RAW: going beyond view_max.\n");
return -1;
}
}
@ -81,9 +80,8 @@ int pwc_decode_size(struct pwc_device *pdev, int width, int height)
/* initialize variables depending on type and decompressor*/
void pwc_construct(struct pwc_device *pdev)
{
switch(pdev->type) {
case 645:
case 646:
if (DEVICE_USE_CODEC1(pdev->type)) {
pdev->view_min.x = 128;
pdev->view_min.y = 96;
pdev->view_max.x = 352;
@ -95,10 +93,23 @@ void pwc_construct(struct pwc_device *pdev)
pdev->vendpoint = 4;
pdev->frame_header_size = 0;
pdev->frame_trailer_size = 0;
break;
case 675:
case 680:
case 690:
} else if (DEVICE_USE_CODEC3(pdev->type)) {
pdev->view_min.x = 160;
pdev->view_min.y = 120;
pdev->view_max.x = 640;
pdev->view_max.y = 480;
pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
pdev->abs_max.x = 640;
pdev->abs_max.y = 480;
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->view_min.x = 128;
pdev->view_min.y = 96;
/* Anthill bug #38: PWC always reports max size, even without PWCX */
@ -111,30 +122,12 @@ void pwc_construct(struct pwc_device *pdev)
pdev->vendpoint = 4;
pdev->frame_header_size = 0;
pdev->frame_trailer_size = 0;
break;
case 720:
case 730:
case 740:
case 750:
pdev->view_min.x = 160;
pdev->view_min.y = 120;
pdev->view_max.x = 640;
pdev->view_max.y = 480;
pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
pdev->abs_max.x = 640;
pdev->abs_max.y = 480;
pdev->vcinterface = 3;
pdev->vendpoint = 5;
pdev->frame_header_size = TOUCAM_HEADER_SIZE;
pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE;
break;
}
Debug("type = %d\n",pdev->type);
pdev->vpalette = VIDEO_PALETTE_YUV420P; /* default */
pdev->view_min.size = pdev->view_min.x * pdev->view_min.y;
pdev->view_max.size = pdev->view_max.x * pdev->view_max.y;
/* length of image, in YUV format; always allocate enough memory. */
pdev->len_per_image = (pdev->abs_max.x * pdev->abs_max.y * 3) / 2;
pdev->len_per_image = PAGE_ALIGN((pdev->abs_max.x * pdev->abs_max.y * 3) / 2);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* Linux driver for Philips webcam
(C) 2004 Luc Saillard (luc@saillard.org)
(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.
@ -42,7 +42,7 @@
#ifndef PWC_TIMON_H
#define PWC_TIMON_H
#include "pwc-ioctl.h"
#include <media/pwc-ioctl.h>
struct Timon_table_entry
{
@ -52,8 +52,8 @@ struct Timon_table_entry
unsigned char mode[13]; /* precomputed mode settings for cam */
};
const extern struct Timon_table_entry Timon_table[PSZ_MAX][6][4];
const extern unsigned int TimonRomTable [16][2][16][8];
extern const struct Timon_table_entry Timon_table[PSZ_MAX][6][4];
extern const unsigned int TimonRomTable [16][2][16][8];
#endif

View File

@ -1,7 +1,7 @@
/* Linux driver for Philips webcam
Decompression frontend.
(C) 1999-2003 Nemosoft Unv.
(C) 2004 Luc Saillard (luc@saillard.org)
(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.
@ -22,6 +22,8 @@
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>
@ -29,6 +31,8 @@
#include "pwc.h"
#include "pwc-uncompress.h"
#include "pwc-dec1.h"
#include "pwc-dec23.h"
int pwc_decompress(struct pwc_device *pdev)
{
@ -40,107 +44,95 @@ int pwc_decompress(struct pwc_device *pdev)
if (pdev == NULL)
return -EFAULT;
#if defined(__KERNEL__) && defined(PWC_MAGIC)
if (pdev->magic != PWC_MAGIC) {
Err("pwc_decompress(): magic failed.\n");
return -EFAULT;
}
#endif
fbuf = pdev->read_frame;
if (fbuf == NULL)
return -EFAULT;
image = pdev->image_ptr[pdev->fill_image];
if (!image)
return -EFAULT;
image = pdev->image_data;
image += pdev->images[pdev->fill_image].offset;
yuv = fbuf->data + pdev->frame_header_size; /* Skip header */
/* Raw format; that's easy... */
if (pdev->vpalette == VIDEO_PALETTE_RAW)
{
memcpy(image, yuv, pdev->frame_size);
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);
return 0;
}
if (pdev->vbandlength == 0) {
/* Uncompressed mode. We copy the data into the output buffer,
using the viewport size (which may be larger than the image
size). Unfortunately we have to do a bit of byte stuffing
to get the desired output format/size.
/* Uncompressed mode.
* We copy the data into the output buffer, using the viewport
* size (which may be larger than the image size).
* Unfortunately we have to do a bit of byte stuffing to get
* the desired output format/size.
*
* We do some byte shuffling here to go from the
* native format to YUV420P.
*/
/*
* We do some byte shuffling here to go from the
* native format to YUV420P.
*/
src = (u16 *)yuv;
n = pdev->view.x * pdev->view.y;
src = (u16 *)yuv;
n = pdev->view.x * pdev->view.y;
/* offset in Y plane */
stride = pdev->view.x * pdev->offset.y + pdev->offset.x;
dsty = (u16 *)(image + stride);
/* offset in Y plane */
stride = pdev->view.x * pdev->offset.y + pdev->offset.x;
dsty = (u16 *)(image + stride);
/* offsets in U/V planes */
stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2;
dstu = (u16 *)(image + n + stride);
dstv = (u16 *)(image + n + n / 4 + stride);
/* offsets in U/V planes */
stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2;
dstu = (u16 *)(image + n + stride);
dstv = (u16 *)(image + n + n / 4 + stride);
/* increment after each line */
stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */
/* increment after each line */
stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */
for (line = 0; line < pdev->image.y; line++) {
for (col = 0; col < pdev->image.x; col += 4) {
*dsty++ = *src++;
*dsty++ = *src++;
if (line & 1)
*dstv++ = *src++;
else
*dstu++ = *src++;
}
dsty += stride;
for (line = 0; line < pdev->image.y; line++) {
for (col = 0; col < pdev->image.x; col += 4) {
*dsty++ = *src++;
*dsty++ = *src++;
if (line & 1)
dstv += (stride >> 1);
*dstv++ = *src++;
else
dstu += (stride >> 1);
*dstu++ = *src++;
}
dsty += stride;
if (line & 1)
dstv += (stride >> 1);
else
dstu += (stride >> 1);
}
return 0;
}
else {
/* Compressed; the decompressor routines will write the data
in planar format immediately.
*/
int flags;
flags = PWCX_FLAG_PLANAR;
if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot)
{
printk(KERN_ERR "pwc: Mode Bayer is not supported for now\n");
flags |= PWCX_FLAG_BAYER;
return -ENXIO; /* No such device or address: missing decompressor */
}
/*
* Compressed;
* the decompressor routines will write the data in planar format
* immediately.
*/
if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) {
PWC_ERROR("Mode Bayer is not supported for now\n");
/* flags |= PWCX_FLAG_BAYER; */
return -ENXIO; /* No such device or address: missing decompressor */
}
#if 0
switch (pdev->type)
{
case 675:
case 680:
case 690:
case 720:
case 730:
case 740:
case 750:
pwc_dec23_decompress(&pdev->image, &pdev->view,
&pdev->offset, yuv, image, flags,
pdev->decompress_data, pdev->vbandlength);
break;
case 645:
case 646:
/* TODO & FIXME */
return -ENXIO; /* Missing decompressor */
break;
}
#endif
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, PWCX_FLAG_PLANAR);
}
return 0;
}
/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */

View File

@ -1,5 +1,5 @@
/* (C) 1999-2003 Nemosoft Unv.
(C) 2004 Luc Saillard (luc@saillard.org)
(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.
@ -32,7 +32,7 @@
#include <linux/config.h>
#include "pwc-ioctl.h"
#include <media/pwc-ioctl.h>
/* from pwc-dec.h */
#define PWCX_FLAG_PLANAR 0x0001

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* (C) 1999-2003 Nemosoft Unv.
(C) 2004 Luc Saillard (luc@saillard.org)
(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.
@ -29,51 +29,87 @@
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/spinlock.h>
#include <linux/videodev.h>
#include <linux/wait.h>
#include <linux/smp_lock.h>
#include <linux/version.h>
#include <asm/semaphore.h>
#include <asm/errno.h>
#include <linux/videodev.h>
#include <linux/videodev2.h>
#include "pwc-uncompress.h"
#include "pwc-ioctl.h"
/* Defines and structures for the Philips webcam */
/* Used for checking memory corruption/pointer validation */
#define PWC_MAGIC 0x89DC10ABUL
#undef PWC_MAGIC
#include <media/pwc-ioctl.h>
/* Turn some debugging options on/off */
#define PWC_DEBUG 0
#ifndef CONFIG_PWC_DEBUG
#define CONFIG_PWC_DEBUG 1
#endif
/* Version block */
#define PWC_MAJOR 10
#define PWC_MINOR 0
#define PWC_EXTRAMINOR 12
#define PWC_VERSION_CODE KERNEL_VERSION(PWC_MAJOR,PWC_MINOR,PWC_EXTRAMINOR)
#define PWC_VERSION "10.0.12"
#define PWC_NAME "pwc"
#define PFX PWC_NAME ": "
/* Trace certain actions in the driver */
#define TRACE_MODULE 0x0001
#define TRACE_PROBE 0x0002
#define TRACE_OPEN 0x0004
#define TRACE_READ 0x0008
#define TRACE_MEMORY 0x0010
#define TRACE_FLOW 0x0020
#define TRACE_SIZE 0x0040
#define TRACE_PWCX 0x0080
#define TRACE_SEQUENCE 0x1000
#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 Trace(R, A...) if (pwc_trace & R) printk(KERN_DEBUG PWC_NAME " " A)
#define Debug(A...) printk(KERN_DEBUG PWC_NAME " " A)
#define Info(A...) printk(KERN_INFO PWC_NAME " " A)
#define Err(A...) printk(KERN_ERR PWC_NAME " " A)
#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)
#if CONFIG_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_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
/* Version block */
#define PWC_MAJOR 9
#define PWC_MINOR 0
#define PWC_VERSION "9.0.2-unofficial"
#define PWC_NAME "pwc"
#define FEATURE_CODEC1 0x0002
#define FEATURE_CODEC2 0x0004
/* Turn certain features on/off */
#define PWC_INT_PIPE 0
@ -95,6 +131,18 @@
/* Absolute maximum number of buffers available for mmap() */
#define MAX_IMAGES 10
/* 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)
#ifndef V4L2_PIX_FMT_PWC1
#define V4L2_PIX_FMT_PWC1 v4l2_fourcc('P','W','C','1')
#define V4L2_PIX_FMT_PWC2 v4l2_fourcc('P','W','C','2')
#endif
/* The following structures were based on cpia.h. Why reinvent the wheel? :-) */
struct pwc_iso_buf
{
@ -110,17 +158,19 @@ struct pwc_frame_buf
void *data;
volatile int filled; /* number of bytes filled */
struct pwc_frame_buf *next; /* list */
#if PWC_DEBUG
int sequence; /* Sequence number */
#endif
};
/* additionnal informations used when dealing image between kernel and userland */
struct pwc_imgbuf
{
unsigned long offset; /* offset of this buffer in the big array of image_data */
int vma_use_count; /* count the number of time this memory is mapped */
};
struct pwc_device
{
struct video_device *vdev;
#ifdef PWC_MAGIC
int magic;
#endif
/* Pointer to our usb_device */
struct usb_device *udev;
@ -177,12 +227,8 @@ struct pwc_device
int frame_size;
int frame_total_size; /* including header & trailer */
int drop_frames;
#if PWC_DEBUG
int sequence; /* Debugging aid */
#endif
/* 3: decompression */
struct pwc_decompressor *decompressor; /* function block with decompression routines */
void *decompress_data; /* private data for decompression engine */
/* 4: image */
@ -198,7 +244,7 @@ struct pwc_device
struct pwc_coord offset; /* offset within the viewport */
void *image_data; /* total buffer, which is subdivided into ... */
void *image_ptr[MAX_IMAGES]; /* ...several images... */
struct pwc_imgbuf images[MAX_IMAGES];/* ...several images... */
int fill_image; /* ...which are rotated. */
int len_per_image; /* length per image */
int image_read_pos; /* In case we read data in pieces, keep track of were we are in the imagebuffer */
@ -211,6 +257,7 @@ struct pwc_device
struct pwc_mpt_range angle_range;
int pan_angle; /* in degrees * 100 */
int tilt_angle; /* absolute angle; 0,0 is home position */
int snapshot_button_status; /* set to 1 when the user push the button, reset to 0 when this value is read */
/*** Misc. data ***/
wait_queue_head_t frameq; /* When waiting for a frame to finish... */
@ -219,20 +266,27 @@ struct pwc_device
#endif
};
#ifdef __cplusplus
extern "C" {
#endif
/* Global variable */
/* Global variables */
#if CONFIG_PWC_DEBUG
extern int pwc_trace;
#endif
extern int pwc_preferred_compression;
extern int pwc_mbufs;
/** functions in pwc-if.c */
int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot);
int pwc_handle_frame(struct pwc_device *pdev);
void pwc_next_image(struct pwc_device *pdev);
int pwc_isoc_init(struct pwc_device *pdev);
void pwc_isoc_cleanup(struct pwc_device *pdev);
/** Functions in pwc-misc.c */
/* sizes in pixels */
extern struct pwc_coord pwc_image_sizes[PSZ_MAX];
extern const struct pwc_coord pwc_image_sizes[PSZ_MAX];
int pwc_decode_size(struct pwc_device *pdev, int width, int height);
void pwc_construct(struct pwc_device *pdev);
@ -240,6 +294,9 @@ 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 frames, int compression, int snapshot);
/* Calculate the number of bytes per image (not frame) */
extern int pwc_mpt_reset(struct pwc_device *pdev, int flags);
extern int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt);
/* Various controls; should be obvious. Value 0..65535, or < 0 on error */
extern int pwc_get_brightness(struct pwc_device *pdev);
@ -248,10 +305,37 @@ extern int pwc_get_contrast(struct pwc_device *pdev);
extern int pwc_set_contrast(struct pwc_device *pdev, int value);
extern int pwc_get_gamma(struct pwc_device *pdev);
extern int pwc_set_gamma(struct pwc_device *pdev, int value);
extern int pwc_get_saturation(struct pwc_device *pdev);
extern int pwc_get_saturation(struct pwc_device *pdev, int *value);
extern int pwc_set_saturation(struct pwc_device *pdev, int value);
extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
extern int pwc_get_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 pwc_restore_user(struct pwc_device *pdev);
extern int pwc_save_user(struct pwc_device *pdev);
extern int pwc_restore_factory(struct pwc_device *pdev);
/* exported for use by v4l2 controls */
extern int pwc_get_red_gain(struct pwc_device *pdev, int *value);
extern int pwc_set_red_gain(struct pwc_device *pdev, int value);
extern int pwc_get_blue_gain(struct pwc_device *pdev, int *value);
extern int pwc_set_blue_gain(struct pwc_device *pdev, int value);
extern int pwc_get_awb(struct pwc_device *pdev);
extern int pwc_set_awb(struct pwc_device *pdev, int mode);
extern int pwc_set_agc(struct pwc_device *pdev, int mode, int value);
extern int pwc_get_agc(struct pwc_device *pdev, int *value);
extern int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value);
extern int pwc_get_shutter_speed(struct pwc_device *pdev, int *value);
extern int pwc_set_colour_mode(struct pwc_device *pdev, int colour);
extern int pwc_get_colour_mode(struct pwc_device *pdev, int *colour);
extern int pwc_set_contour(struct pwc_device *pdev, int contour);
extern int pwc_get_contour(struct pwc_device *pdev, int *contour);
extern int pwc_set_backlight(struct pwc_device *pdev, int backlight);
extern int pwc_get_backlight(struct pwc_device *pdev, int *backlight);
extern int pwc_set_flicker(struct pwc_device *pdev, int flicker);
extern int pwc_get_flicker(struct pwc_device *pdev, int *flicker);
extern int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise);
extern int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise);
/* Power down or up the camera; not supported by all models */
extern int pwc_camera_power(struct pwc_device *pdev, int power);
@ -259,6 +343,9 @@ extern int pwc_camera_power(struct pwc_device *pdev, int power);
/* Private ioctl()s; see pwc-ioctl.h */
extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
/** Functions in pwc-v4l.c */
extern int pwc_video_do_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *arg);
/** pwc-uncompress.c */
/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
@ -270,3 +357,4 @@ extern int pwc_decompress(struct pwc_device *pdev);
#endif
/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */

325
include/media/pwc-ioctl.h Normal file
View File

@ -0,0 +1,325 @@
#ifndef PWC_IOCTL_H
#define PWC_IOCTL_H
/* (C) 2001-2004 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
*/
/* This is pwc-ioctl.h belonging to PWC 10.0.10
It contains structures and defines to communicate from user space
directly to the driver.
*/
/*
Changes
2001/08/03 Alvarado Added ioctl constants to access methods for
changing white balance and red/blue gains
2002/12/15 G. H. Fernandez-Toribio VIDIOCGREALSIZE
2003/12/13 Nemosft Unv. Some modifications to make interfacing to
PWCX easier
2006/01/01 Luc Saillard Add raw format definition
*/
/* These are private ioctl() commands, specific for the Philips webcams.
They contain functions not found in other webcams, and settings not
specified in the Video4Linux API.
The #define names are built up like follows:
VIDIOC VIDeo IOCtl prefix
PWC Philps WebCam
G optional: Get
S optional: Set
... the function
*/
#include <linux/types.h>
#include <linux/version.h>
/* 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
/* The frame rate is encoded in the video_window.flags parameter using
the upper 16 bits, since some flags are defined nowadays. The following
defines provide a mask and shift to filter out this value.
This value can also be passing using the private flag when using v4l2 and
VIDIOC_S_FMT ioctl.
In 'Snapshot' mode the camera freezes its automatic exposure and colour
balance controls.
*/
#define PWC_FPS_SHIFT 16
#define PWC_FPS_MASK 0x00FF0000
#define PWC_FPS_FRMASK 0x003F0000
#define PWC_FPS_SNAPSHOT 0x00400000
#define PWC_QLT_MASK 0x03000000
#define PWC_QLT_SHIFT 24
/* structure for transferring x & y coordinates */
struct pwc_coord
{
int x, y; /* guess what */
int size; /* size, or offset */
};
/* Used with VIDIOCPWCPROBE */
struct pwc_probe
{
char name[32];
int type;
};
struct pwc_serial
{
char serial[30]; /* String with serial number. Contains terminating 0 */
};
/* pwc_whitebalance.mode values */
#define PWC_WB_INDOOR 0
#define PWC_WB_OUTDOOR 1
#define PWC_WB_FL 2
#define PWC_WB_MANUAL 3
#define PWC_WB_AUTO 4
/* Used with VIDIOCPWC[SG]AWB (Auto White Balance).
Set mode to one of the PWC_WB_* values above.
*red and *blue are the respective gains of these colour components inside
the camera; range 0..65535
When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read;
otherwise undefined.
'read_red' and 'read_blue' are read-only.
*/
struct pwc_whitebalance
{
int mode;
int manual_red, manual_blue; /* R/W */
int read_red, read_blue; /* R/O */
};
/*
'control_speed' and 'control_delay' are used in automatic whitebalance mode,
and tell the camera how fast it should react to changes in lighting, and
with how much delay. Valid values are 0..65535.
*/
struct pwc_wb_speed
{
int control_speed;
int control_delay;
};
/* Used with VIDIOCPWC[SG]LED */
struct pwc_leds
{
int led_on; /* Led on-time; range = 0..25000 */
int led_off; /* Led off-time; range = 0..25000 */
};
/* Image size (used with GREALSIZE) */
struct pwc_imagesize
{
int width;
int height;
};
/* Defines and structures for Motorized Pan & Tilt */
#define PWC_MPT_PAN 0x01
#define PWC_MPT_TILT 0x02
#define PWC_MPT_TIMEOUT 0x04 /* for status */
/* Set angles; when absolute != 0, the angle is absolute and the
driver calculates the relative offset for you. This can only
be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns
absolute angles.
*/
struct pwc_mpt_angles
{
int absolute; /* write-only */
int pan; /* degrees * 100 */
int tilt; /* degress * 100 */
};
/* Range of angles of the camera, both horizontally and vertically.
*/
struct pwc_mpt_range
{
int pan_min, pan_max; /* degrees * 100 */
int tilt_min, tilt_max;
};
struct pwc_mpt_status
{
int status;
int time_pan;
int time_tilt;
};
/* This is used for out-of-kernel decompression. With it, you can get
all the necessary information to initialize and use the decompressor
routines in standalone applications.
*/
struct pwc_video_command
{
int type; /* camera type (645, 675, 730, etc.) */
int release; /* release number */
int size; /* one of PSZ_* */
int alternate;
int command_len; /* length of USB video command */
unsigned char command_buf[13]; /* Actual USB video command */
int bandlength; /* >0 = compressed */
int frame_size; /* Size of one (un)compressed frame */
};
/* Flags for PWCX subroutines. Not all modules honour all flags. */
#define PWCX_FLAG_PLANAR 0x0001
#define PWCX_FLAG_BAYER 0x0008
/* IOCTL definitions */
/* Restore user settings */
#define VIDIOCPWCRUSER _IO('v', 192)
/* Save user settings */
#define VIDIOCPWCSUSER _IO('v', 193)
/* Restore factory settings */
#define VIDIOCPWCFACTORY _IO('v', 194)
/* You can manipulate the compression factor. A compression preference of 0
means use uncompressed modes when available; 1 is low compression, 2 is
medium and 3 is high compression preferred. Of course, the higher the
compression, the lower the bandwidth used but more chance of artefacts
in the image. The driver automatically chooses a higher compression when
the preferred mode is not available.
*/
/* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
#define VIDIOCPWCSCQUAL _IOW('v', 195, int)
/* Get preferred compression quality */
#define VIDIOCPWCGCQUAL _IOR('v', 195, int)
/* Retrieve serial number of camera */
#define VIDIOCPWCGSERIAL _IOR('v', 198, struct pwc_serial)
/* This is a probe function; since so many devices are supported, it
becomes difficult to include all the names in programs that want to
check for the enhanced Philips stuff. So in stead, try this PROBE;
it returns a structure with the original name, and the corresponding
Philips type.
To use, fill the structure with zeroes, call PROBE and if that succeeds,
compare the name with that returned from VIDIOCGCAP; they should be the
same. If so, you can be assured it is a Philips (OEM) cam and the type
is valid.
*/
#define VIDIOCPWCPROBE _IOR('v', 199, struct pwc_probe)
/* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
#define VIDIOCPWCSAGC _IOW('v', 200, int)
/* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
#define VIDIOCPWCGAGC _IOR('v', 200, int)
/* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
#define VIDIOCPWCSSHUTTER _IOW('v', 201, int)
/* Color compensation (Auto White Balance) */
#define VIDIOCPWCSAWB _IOW('v', 202, struct pwc_whitebalance)
#define VIDIOCPWCGAWB _IOR('v', 202, struct pwc_whitebalance)
/* Auto WB speed */
#define VIDIOCPWCSAWBSPEED _IOW('v', 203, struct pwc_wb_speed)
#define VIDIOCPWCGAWBSPEED _IOR('v', 203, struct pwc_wb_speed)
/* LEDs on/off/blink; int range 0..65535 */
#define VIDIOCPWCSLED _IOW('v', 205, struct pwc_leds)
#define VIDIOCPWCGLED _IOR('v', 205, struct pwc_leds)
/* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */
#define VIDIOCPWCSCONTOUR _IOW('v', 206, int)
#define VIDIOCPWCGCONTOUR _IOR('v', 206, int)
/* Backlight compensation; 0 = off, otherwise on */
#define VIDIOCPWCSBACKLIGHT _IOW('v', 207, int)
#define VIDIOCPWCGBACKLIGHT _IOR('v', 207, int)
/* Flickerless mode; = 0 off, otherwise on */
#define VIDIOCPWCSFLICKER _IOW('v', 208, int)
#define VIDIOCPWCGFLICKER _IOR('v', 208, int)
/* Dynamic noise reduction; 0 off, 3 = high noise reduction */
#define VIDIOCPWCSDYNNOISE _IOW('v', 209, int)
#define VIDIOCPWCGDYNNOISE _IOR('v', 209, int)
/* Real image size as used by the camera; tells you whether or not there's a gray border around the image */
#define VIDIOCPWCGREALSIZE _IOR('v', 210, struct pwc_imagesize)
/* Motorized pan & tilt functions */
#define VIDIOCPWCMPTRESET _IOW('v', 211, int)
#define VIDIOCPWCMPTGRANGE _IOR('v', 211, struct pwc_mpt_range)
#define VIDIOCPWCMPTSANGLE _IOW('v', 212, struct pwc_mpt_angles)
#define VIDIOCPWCMPTGANGLE _IOR('v', 212, struct pwc_mpt_angles)
#define VIDIOCPWCMPTSTATUS _IOR('v', 213, struct pwc_mpt_status)
/* Get the USB set-video command; needed for initializing libpwcx */
#define VIDIOCPWCGVIDCMD _IOR('v', 215, struct pwc_video_command)
struct pwc_table_init_buffer {
int len;
char *buffer;
};
#define VIDIOCPWCGVIDTABLE _IOR('v', 216, struct pwc_table_init_buffer)
/*
* This is private command used when communicating with v4l2.
* In the future all private ioctl will be remove/replace to
* use interface offer by v4l2.
*/
#define V4L2_CID_PRIVATE_SAVE_USER (V4L2_CID_PRIVATE_BASE + 0)
#define V4L2_CID_PRIVATE_RESTORE_USER (V4L2_CID_PRIVATE_BASE + 1)
#define V4L2_CID_PRIVATE_RESTORE_FACTORY (V4L2_CID_PRIVATE_BASE + 2)
#define V4L2_CID_PRIVATE_COLOUR_MODE (V4L2_CID_PRIVATE_BASE + 3)
#define V4L2_CID_PRIVATE_AUTOCONTOUR (V4L2_CID_PRIVATE_BASE + 4)
#define V4L2_CID_PRIVATE_CONTOUR (V4L2_CID_PRIVATE_BASE + 5)
#define V4L2_CID_PRIVATE_BACKLIGHT (V4L2_CID_PRIVATE_BASE + 6)
#define V4L2_CID_PRIVATE_FLICKERLESS (V4L2_CID_PRIVATE_BASE + 7)
#define V4L2_CID_PRIVATE_NOISE_REDUCTION (V4L2_CID_PRIVATE_BASE + 8)
struct pwc_raw_frame {
__le16 type; /* type of the webcam */
__le16 vbandlength; /* Size of 4lines 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 */
} __attribute__ ((packed));
#endif