summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux/drivers/media/common/saa7146_video.c4
-rw-r--r--linux/drivers/media/common/tuners/tuner-simple.c33
-rw-r--r--linux/drivers/media/dvb/dvb-core/dmxdev.c1
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c4
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_frontend.c8
-rw-r--r--linux/drivers/media/dvb/dvb-usb/cxusb.c2
-rw-r--r--linux/drivers/media/radio/radio-maxiradio.c26
-rw-r--r--linux/drivers/media/video/bt8xx/bttv-cards.c70
-rw-r--r--linux/drivers/media/video/bt8xx/bttv-driver.c1
-rw-r--r--linux/drivers/media/video/bt8xx/bttv-risc.c3
-rw-r--r--linux/drivers/media/video/bt8xx/bttvp.h5
-rw-r--r--linux/drivers/media/video/btcx-risc.c4
-rw-r--r--linux/drivers/media/video/btcx-risc.h2
-rw-r--r--linux/drivers/media/video/cpia2/cpia2_v4l.c1
-rw-r--r--linux/drivers/media/video/cx18/cx18-av-firmware.c16
-rw-r--r--linux/drivers/media/video/cx18/cx18-driver.c6
-rw-r--r--linux/drivers/media/video/cx18/cx18-driver.h6
-rw-r--r--linux/drivers/media/video/cx18/cx18-fileops.c47
-rw-r--r--linux/drivers/media/video/cx18/cx18-ioctl.c20
-rw-r--r--linux/drivers/media/video/cx18/cx18-mailbox.c1
-rw-r--r--linux/drivers/media/video/cx18/cx18-queue.c120
-rw-r--r--linux/drivers/media/video/cx18/cx18-streams.c19
-rw-r--r--linux/drivers/media/video/cx18/cx23418.h2
-rw-r--r--linux/drivers/media/video/gspca/gspca.c2
-rw-r--r--linux/drivers/media/video/ks0127.c31
-rw-r--r--linux/drivers/media/video/meye.c4
-rw-r--r--linux/drivers/media/video/mxb.c12
-rw-r--r--linux/drivers/media/video/ov511.c14
-rw-r--r--linux/drivers/media/video/pwc/pwc-ctrl.c18
-rw-r--r--linux/drivers/media/video/s2255drv.c535
-rw-r--r--linux/drivers/media/video/usbvideo/ibmcam.c6
-rw-r--r--linux/drivers/media/video/uvc/uvc_driver.c15
-rw-r--r--linux/drivers/media/video/v4l2-dev.c3
-rw-r--r--linux/drivers/media/video/vivi.c44
-rw-r--r--linux/drivers/media/video/zoran_procfs.c3
-rwxr-xr-xmailimport6
-rw-r--r--v4l/Makefile2
-rw-r--r--v4l/firmware/Makefile6
-rw-r--r--v4l2-apps/lib/libv4l/ChangeLog14
-rw-r--r--v4l2-apps/lib/libv4l/Makefile2
-rw-r--r--v4l2-apps/lib/libv4l/include/libv4l1.h22
-rw-r--r--v4l2-apps/lib/libv4l/include/libv4l2.h28
-rw-r--r--v4l2-apps/lib/libv4l/include/libv4lconvert.h23
-rw-r--r--v4l2-apps/lib/libv4l/libv4l1/Makefile6
-rw-r--r--v4l2-apps/lib/libv4l/libv4l1/libv4l1.c3
-rw-r--r--v4l2-apps/lib/libv4l/libv4l1/log.c7
-rw-r--r--v4l2-apps/lib/libv4l/libv4l1/v4l1compat.c28
-rw-r--r--v4l2-apps/lib/libv4l/libv4l2/Makefile6
-rw-r--r--v4l2-apps/lib/libv4l/libv4l2/libv4l2.c135
-rw-r--r--v4l2-apps/lib/libv4l/libv4l2/log.c6
-rw-r--r--v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c27
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/Makefile8
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/flip.c107
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/jidctflt.c4
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h22
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c150
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/pac207.c2
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c2
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c2
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/spca561-decompress.c1
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg.c348
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg.h1
-rw-r--r--v4l2-apps/util/ivtv-ctl.c8
63 files changed, 1375 insertions, 689 deletions
diff --git a/linux/drivers/media/common/saa7146_video.c b/linux/drivers/media/common/saa7146_video.c
index 1c22c39c2..8804d4e78 100644
--- a/linux/drivers/media/common/saa7146_video.c
+++ b/linux/drivers/media/common/saa7146_video.c
@@ -1069,7 +1069,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
{
v4l2_std_id *id = arg;
int found = 0;
- int i, err;
+ int i;
DEB_EE(("VIDIOC_S_STD\n"));
@@ -1117,7 +1117,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
case VIDIOC_OVERLAY:
{
int on = *(int *)arg;
- int err = 0;
DEB_D(("VIDIOC_OVERLAY on:%d\n",on));
if (on != 0) {
@@ -1193,7 +1192,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
case VIDIOCGMBUF:
{
struct video_mbuf *mbuf = arg;
- struct videobuf_queue *q;
int i;
/* fixme: number of capture buffers and sizes for v4l apps */
diff --git a/linux/drivers/media/common/tuners/tuner-simple.c b/linux/drivers/media/common/tuners/tuner-simple.c
index a709d6bee..a379672cd 100644
--- a/linux/drivers/media/common/tuners/tuner-simple.c
+++ b/linux/drivers/media/common/tuners/tuner-simple.c
@@ -261,7 +261,7 @@ static struct tuner_params *simple_tuner_params(struct dvb_frontend *fe,
static int simple_config_lookup(struct dvb_frontend *fe,
struct tuner_params *t_params,
- int *frequency, u8 *config, u8 *cb)
+ unsigned *frequency, u8 *config, u8 *cb)
{
struct tuner_simple_priv *priv = fe->tuner_priv;
int i;
@@ -609,45 +609,45 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
priv->last_div = div;
if (t_params->has_tda9887) {
struct v4l2_priv_tun_config tda9887_cfg;
- int config = 0;
+ int tda_config = 0;
int is_secam_l = (params->std & (V4L2_STD_SECAM_L |
V4L2_STD_SECAM_LC)) &&
!(params->std & ~(V4L2_STD_SECAM_L |
V4L2_STD_SECAM_LC));
tda9887_cfg.tuner = TUNER_TDA9887;
- tda9887_cfg.priv = &config;
+ tda9887_cfg.priv = &tda_config;
if (params->std == V4L2_STD_SECAM_LC) {
if (t_params->port1_active ^ t_params->port1_invert_for_secam_lc)
- config |= TDA9887_PORT1_ACTIVE;
+ tda_config |= TDA9887_PORT1_ACTIVE;
if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc)
- config |= TDA9887_PORT2_ACTIVE;
+ tda_config |= TDA9887_PORT2_ACTIVE;
} else {
if (t_params->port1_active)
- config |= TDA9887_PORT1_ACTIVE;
+ tda_config |= TDA9887_PORT1_ACTIVE;
if (t_params->port2_active)
- config |= TDA9887_PORT2_ACTIVE;
+ tda_config |= TDA9887_PORT2_ACTIVE;
}
if (t_params->intercarrier_mode)
- config |= TDA9887_INTERCARRIER;
+ tda_config |= TDA9887_INTERCARRIER;
if (is_secam_l) {
if (i == 0 && t_params->default_top_secam_low)
- config |= TDA9887_TOP(t_params->default_top_secam_low);
+ tda_config |= TDA9887_TOP(t_params->default_top_secam_low);
else if (i == 1 && t_params->default_top_secam_mid)
- config |= TDA9887_TOP(t_params->default_top_secam_mid);
+ tda_config |= TDA9887_TOP(t_params->default_top_secam_mid);
else if (t_params->default_top_secam_high)
- config |= TDA9887_TOP(t_params->default_top_secam_high);
+ tda_config |= TDA9887_TOP(t_params->default_top_secam_high);
} else {
if (i == 0 && t_params->default_top_low)
- config |= TDA9887_TOP(t_params->default_top_low);
+ tda_config |= TDA9887_TOP(t_params->default_top_low);
else if (i == 1 && t_params->default_top_mid)
- config |= TDA9887_TOP(t_params->default_top_mid);
+ tda_config |= TDA9887_TOP(t_params->default_top_mid);
else if (t_params->default_top_high)
- config |= TDA9887_TOP(t_params->default_top_high);
+ tda_config |= TDA9887_TOP(t_params->default_top_high);
}
if (t_params->default_pll_gating_18)
- config |= TDA9887_GATING_18;
+ tda_config |= TDA9887_GATING_18;
i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG,
&tda9887_cfg);
}
@@ -835,7 +835,8 @@ static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
static struct tuner_params *t_params;
u8 config, cb;
u32 div;
- int ret, frequency = params->frequency / 62500;
+ int ret;
+ unsigned frequency = params->frequency / 62500;
t_params = simple_tuner_params(fe, TUNER_PARAM_TYPE_DIGITAL);
ret = simple_config_lookup(fe, t_params, &frequency, &config, &cb);
diff --git a/linux/drivers/media/dvb/dvb-core/dmxdev.c b/linux/drivers/media/dvb/dvb-core/dmxdev.c
index 1cf9fcb6f..069d847ba 100644
--- a/linux/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/linux/drivers/media/dvb/dvb-core/dmxdev.c
@@ -641,7 +641,6 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
struct timespec timeout = { 0 };
struct dmx_pes_filter_params *para = &filter->params.pes;
dmx_output_t otype;
- int ret;
int ts_type;
enum dmx_ts_pes ts_pes;
struct dmx_ts_feed **tsfeed = &filter->feed.ts;
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index c2954bf57..f6016feab 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -1033,7 +1033,7 @@ static int dvb_ca_en50221_thread(void *data)
/* we need this extra check for annoying interfaces like the budget-av */
if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
(ca->pub->poll_slot_status)) {
- int status = ca->pub->poll_slot_status(ca->pub, slot, 0);
+ status = ca->pub->poll_slot_status(ca->pub, slot, 0);
if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
dvb_ca_en50221_thread_update_delay(ca);
@@ -1090,7 +1090,7 @@ static int dvb_ca_en50221_thread(void *data)
/* we need this extra check for annoying interfaces like the budget-av */
if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
(ca->pub->poll_slot_status)) {
- int status = ca->pub->poll_slot_status(ca->pub, slot, 0);
+ status = ca->pub->poll_slot_status(ca->pub, slot, 0);
if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
dvb_ca_en50221_thread_update_delay(ca);
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
index 8a9c2283f..60a94dc85 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -900,13 +900,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
* initialization, so parg is 8 bits and does not
* include the initialization or start bit
*/
- unsigned long cmd = ((unsigned long) parg) << 1;
+ unsigned long swcmd = ((unsigned long) parg) << 1;
struct timeval nexttime;
struct timeval tv[10];
int i;
u8 last = 1;
if (dvb_frontend_debug)
- printk("%s switch command: 0x%04lx\n", __func__, cmd);
+ printk("%s switch command: 0x%04lx\n", __func__, swcmd);
do_gettimeofday(&nexttime);
if (dvb_frontend_debug)
memcpy(&tv[0], &nexttime, sizeof(struct timeval));
@@ -919,12 +919,12 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
for (i = 0; i < 9; i++) {
if (dvb_frontend_debug)
do_gettimeofday(&tv[i + 1]);
- if ((cmd & 0x01) != last) {
+ if ((swcmd & 0x01) != last) {
/* set voltage to (last ? 13V : 18V) */
fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
last = (last) ? 0 : 1;
}
- cmd = cmd >> 1;
+ swcmd = swcmd >> 1;
if (i != 8)
dvb_frontend_sleep_until(&nexttime, 8000);
}
diff --git a/linux/drivers/media/dvb/dvb-usb/cxusb.c b/linux/drivers/media/dvb/dvb-usb/cxusb.c
index 49985f992..bffb44380 100644
--- a/linux/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/linux/drivers/media/dvb/dvb-usb/cxusb.c
@@ -232,7 +232,7 @@ static int cxusb_aver_power_ctrl(struct dvb_usb_device *d, int onoff)
if (d->state == DVB_USB_STATE_INIT &&
usb_set_interface(d->udev, 0, 0) < 0)
err("set interface failed");
- do; while (!(ret = cxusb_ctrl_msg(d, CMD_POWER_ON, NULL, 0, NULL, 0)) &&
+ do {} while (!(ret = cxusb_ctrl_msg(d, CMD_POWER_ON, NULL, 0, NULL, 0)) &&
!(ret = cxusb_ctrl_msg(d, 0x15, NULL, 0, NULL, 0)) &&
!(ret = cxusb_ctrl_msg(d, 0x17, NULL, 0, NULL, 0)) && 0);
if (!ret) {
diff --git a/linux/drivers/media/radio/radio-maxiradio.c b/linux/drivers/media/radio/radio-maxiradio.c
index e8991b094..4aea352cb 100644
--- a/linux/drivers/media/radio/radio-maxiradio.c
+++ b/linux/drivers/media/radio/radio-maxiradio.c
@@ -169,28 +169,28 @@ static void set_freq(__u16 io, __u32 freq)
{
unsigned long int si;
int bl;
- int data = FREQ2BITS(freq);
+ int val = FREQ2BITS(freq);
/* TEA5757 shift register bits (see pdf) */
- outbit(0,io); // 24 search
- outbit(1,io); // 23 search up/down
+ outbit(0, io); /* 24 search */
+ outbit(1, io); /* 23 search up/down */
- outbit(0,io); // 22 stereo/mono
+ outbit(0, io); /* 22 stereo/mono */
- outbit(0,io); // 21 band
- outbit(0,io); // 20 band (only 00=FM works I think)
+ outbit(0, io); /* 21 band */
+ outbit(0, io); /* 20 band (only 00=FM works I think) */
- outbit(0,io); // 19 port ?
- outbit(0,io); // 18 port ?
+ outbit(0, io); /* 19 port ? */
+ outbit(0, io); /* 18 port ? */
- outbit(0,io); // 17 search level
- outbit(0,io); // 16 search level
+ outbit(0, io); /* 17 search level */
+ outbit(0, io); /* 16 search level */
si = 0x8000;
- for (bl = 1; bl <= 16 ; bl++) {
- outbit(data & si,io);
- si >>=1;
+ for (bl = 1; bl <= 16; bl++) {
+ outbit(val & si, io);
+ si >>= 1;
}
dprintk(1, "Radio freq set to %d.%02d MHz\n",
diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c
index bf3339436..9c4e77393 100644
--- a/linux/drivers/media/video/bt8xx/bttv-cards.c
+++ b/linux/drivers/media/video/bt8xx/bttv-cards.c
@@ -3201,8 +3201,9 @@ static void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256])
static void flyvideo_gpio(struct bttv *btv)
{
- int gpio,has_remote,has_radio,is_capture_only,is_lr90,has_tda9820_tda9821;
- int tuner=UNSET,ttype;
+ int gpio, has_remote, has_radio, is_capture_only;
+ int is_lr90, has_tda9820_tda9821;
+ int tuner_type = UNSET, ttype;
gpio_inout(0xffffff, 0);
udelay(8); /* without this we would see the 0x1800 mask */
@@ -3220,20 +3221,26 @@ static void flyvideo_gpio(struct bttv *btv)
* xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered
* Note: Some bits are Audio_Mask !
*/
- ttype=(gpio&0x0f0000)>>16;
- switch(ttype) {
- case 0x0: tuner=2; /* NTSC, e.g. TPI8NSR11P */
+ ttype = (gpio & 0x0f0000) >> 16;
+ switch (ttype) {
+ case 0x0:
+ tuner_type = 2; /* NTSC, e.g. TPI8NSR11P */
break;
- case 0x2: tuner=39;/* LG NTSC (newer TAPC series) TAPC-H701P */
+ case 0x2:
+ tuner_type = 39; /* LG NTSC (newer TAPC series) TAPC-H701P */
break;
- case 0x4: tuner=5; /* Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 */
+ case 0x4:
+ tuner_type = 5; /* Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 */
break;
- case 0x6: tuner=37;/* LG PAL (newer TAPC series) TAPC-G702P */
+ case 0x6:
+ tuner_type = 37; /* LG PAL (newer TAPC series) TAPC-G702P */
break;
- case 0xC: tuner=3; /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */
+ case 0xC:
+ tuner_type = 3; /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */
break;
default:
printk(KERN_INFO "bttv%d: FlyVideo_gpio: unknown tuner type.\n", btv->c.nr);
+ break;
}
has_remote = gpio & 0x800000;
@@ -3246,23 +3253,26 @@ static void flyvideo_gpio(struct bttv *btv)
/*
* gpio & 0x001000 output bit for audio routing */
- if(is_capture_only)
- tuner = TUNER_ABSENT; /* No tuner present */
+ if (is_capture_only)
+ tuner_type = TUNER_ABSENT; /* No tuner present */
printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
- btv->c.nr, has_radio? "yes":"no ", has_remote? "yes":"no ", tuner, gpio);
+ btv->c.nr, has_radio ? "yes" : "no ",
+ has_remote ? "yes" : "no ", tuner_type, gpio);
printk(KERN_INFO "bttv%d: FlyVideo LR90=%s tda9821/tda9820=%s capture_only=%s\n",
- btv->c.nr, is_lr90?"yes":"no ", has_tda9820_tda9821?"yes":"no ",
- is_capture_only?"yes":"no ");
+ btv->c.nr, is_lr90 ? "yes" : "no ",
+ has_tda9820_tda9821 ? "yes" : "no ",
+ is_capture_only ? "yes" : "no ");
- if (tuner != UNSET) /* only set if known tuner autodetected, else let insmod option through */
- btv->tuner_type = tuner;
+ if (tuner_type != UNSET) /* only set if known tuner autodetected, else let insmod option through */
+ btv->tuner_type = tuner_type;
btv->has_radio = has_radio;
/* LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80
* LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00
* Audio options: from tuner, from tda9821/tda9821(mono,stereo,sap), from tda9874, ext., mute */
- if(has_tda9820_tda9821) btv->audio_mode_gpio = lt9415_audio;
+ if (has_tda9820_tda9821)
+ btv->audio_mode_gpio = lt9415_audio;
/* todo: if(has_tda9874) btv->audio_mode_gpio = fv2000s_audio; */
}
@@ -4036,7 +4046,7 @@ static int tuner_1_table[] = {
static void __devinit avermedia_eeprom(struct bttv *btv)
{
- int tuner_make,tuner_tv_fm,tuner_format,tuner=0;
+ int tuner_make, tuner_tv_fm, tuner_format, tuner_type = 0;
tuner_make = (eeprom_data[0x41] & 0x7);
tuner_tv_fm = (eeprom_data[0x41] & 0x18) >> 3;
@@ -4044,24 +4054,24 @@ static void __devinit avermedia_eeprom(struct bttv *btv)
btv->has_remote = (eeprom_data[0x42] & 0x01);
if (tuner_make == 0 || tuner_make == 2)
- if(tuner_format <=0x0a)
- tuner = tuner_0_table[tuner_format];
+ if (tuner_format <= 0x0a)
+ tuner_type = tuner_0_table[tuner_format];
if (tuner_make == 1)
- if(tuner_format <=9)
- tuner = tuner_1_table[tuner_format];
+ if (tuner_format <= 9)
+ tuner_type = tuner_1_table[tuner_format];
if (tuner_make == 4)
- if(tuner_format == 0x09)
- tuner = TUNER_LG_NTSC_NEW_TAPC; /* TAPC-G702P */
+ if (tuner_format == 0x09)
+ tuner_type = TUNER_LG_NTSC_NEW_TAPC; /* TAPC-G702P */
printk(KERN_INFO "bttv%d: Avermedia eeprom[0x%02x%02x]: tuner=",
- btv->c.nr,eeprom_data[0x41],eeprom_data[0x42]);
- if(tuner) {
- btv->tuner_type=tuner;
- printk("%d",tuner);
+ btv->c.nr, eeprom_data[0x41], eeprom_data[0x42]);
+ if (tuner_type) {
+ btv->tuner_type = tuner_type;
+ printk(KERN_CONT "%d", tuner_type);
} else
- printk("Unknown type");
- printk(" radio:%s remote control:%s\n",
+ printk(KERN_CONT "Unknown type");
+ printk(KERN_CONT " radio:%s remote control:%s\n",
tuner_tv_fm ? "yes" : "no",
btv->has_remote ? "yes" : "no");
}
diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c
index 012eeba5e..a111df094 100644
--- a/linux/drivers/media/video/bt8xx/bttv-driver.c
+++ b/linux/drivers/media/video/bt8xx/bttv-driver.c
@@ -96,7 +96,6 @@ static unsigned int irq_iswitch;
static unsigned int uv_ratio = 50;
static unsigned int full_luma_range;
static unsigned int coring;
-extern int no_overlay;
/* API features (turn on/off stuff for testing) */
static unsigned int v4l2 = 1;
diff --git a/linux/drivers/media/video/bt8xx/bttv-risc.c b/linux/drivers/media/video/bt8xx/bttv-risc.c
index 0cffd3a72..310924f77 100644
--- a/linux/drivers/media/video/bt8xx/bttv-risc.c
+++ b/linux/drivers/media/video/bt8xx/bttv-risc.c
@@ -244,7 +244,8 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
const struct bttv_format *fmt, struct bttv_overlay *ov,
int skip_even, int skip_odd)
{
- int dwords,rc,line,maxy,start,end,skip,nskips;
+ int dwords, rc, line, maxy, start, end;
+ unsigned skip, nskips;
struct btcx_skiplist *skips;
__le32 *rp;
u32 ri,ra;
diff --git a/linux/drivers/media/video/bt8xx/bttvp.h b/linux/drivers/media/video/bt8xx/bttvp.h
index 63d1d4451..403695f9a 100644
--- a/linux/drivers/media/video/bt8xx/bttvp.h
+++ b/linux/drivers/media/video/bt8xx/bttvp.h
@@ -269,6 +269,11 @@ int bttv_sub_add_device(struct bttv_core *core, char *name);
int bttv_sub_del_devices(struct bttv_core *core);
/* ---------------------------------------------------------- */
+/* bttv-cards.c */
+
+extern int no_overlay;
+
+/* ---------------------------------------------------------- */
/* bttv-driver.c */
/* insmod options */
diff --git a/linux/drivers/media/video/btcx-risc.c b/linux/drivers/media/video/btcx-risc.c
index 3a935fbc3..1c2413571 100644
--- a/linux/drivers/media/video/btcx-risc.c
+++ b/linux/drivers/media/video/btcx-risc.c
@@ -185,12 +185,12 @@ btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips)
}
void
-btcx_calc_skips(int line, int width, unsigned int *maxy,
+btcx_calc_skips(int line, int width, int *maxy,
struct btcx_skiplist *skips, unsigned int *nskips,
const struct v4l2_clip *clips, unsigned int nclips)
{
unsigned int clip,skip;
- int end,maxline;
+ int end, maxline;
skip=0;
maxline = 9999;
diff --git a/linux/drivers/media/video/btcx-risc.h b/linux/drivers/media/video/btcx-risc.h
index 861bc8112..f8bc6e8e7 100644
--- a/linux/drivers/media/video/btcx-risc.h
+++ b/linux/drivers/media/video/btcx-risc.h
@@ -23,7 +23,7 @@ int btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
int btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips,
unsigned int n, int mask);
void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips);
-void btcx_calc_skips(int line, int width, unsigned int *maxy,
+void btcx_calc_skips(int line, int width, int *maxy,
struct btcx_skiplist *skips, unsigned int *nskips,
const struct v4l2_clip *clips, unsigned int nclips);
diff --git a/linux/drivers/media/video/cpia2/cpia2_v4l.c b/linux/drivers/media/video/cpia2/cpia2_v4l.c
index 3bbbdf6fa..897e8d1a5 100644
--- a/linux/drivers/media/video/cpia2/cpia2_v4l.c
+++ b/linux/drivers/media/video/cpia2/cpia2_v4l.c
@@ -1020,7 +1020,6 @@ static int ioctl_queryctrl(void *arg,struct camera_data *cam)
if(cam->params.pnp_id.device_type == DEVICE_STV_672 &&
cam->params.version.sensor_flags==CPIA2_VP_SENSOR_FLAGS_500){
// Maximum 15fps
- int i;
for(i=0; i<c->maximum; ++i) {
if(framerate_controls[i].value ==
CPIA2_VP_FRAMERATE_15) {
diff --git a/linux/drivers/media/video/cx18/cx18-av-firmware.c b/linux/drivers/media/video/cx18/cx18-av-firmware.c
index 834b92482..e996a4e31 100644
--- a/linux/drivers/media/video/cx18/cx18-av-firmware.c
+++ b/linux/drivers/media/video/cx18/cx18-av-firmware.c
@@ -32,7 +32,7 @@ int cx18_av_loadfw(struct cx18 *cx)
u32 v;
const u8 *ptr;
int i;
- int retries = 0;
+ int retries1 = 0;
if (request_firmware(&fw, FWFILE, &cx->dev->dev) != 0) {
CX18_ERR("unable to open firmware %s\n", FWFILE);
@@ -41,7 +41,7 @@ int cx18_av_loadfw(struct cx18 *cx)
/* The firmware load often has byte errors, so allow for several
retries, both at byte level and at the firmware load level. */
- while (retries < 5) {
+ while (retries1 < 5) {
cx18_av_write4(cx, CXADEC_CHIP_CTRL, 0x00010000);
cx18_av_write(cx, CXADEC_STD_DET_CTL, 0xf6);
@@ -57,9 +57,9 @@ int cx18_av_loadfw(struct cx18 *cx)
for (i = 0; i < size; i++) {
u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16);
u32 value = 0;
- int retries;
+ int retries2;
- for (retries = 0; retries < 5; retries++) {
+ for (retries2 = 0; retries2 < 5; retries2++) {
cx18_av_write4(cx, CXADEC_DL_CTL, dl_control);
udelay(10);
value = cx18_av_read4(cx, CXADEC_DL_CTL);
@@ -69,18 +69,18 @@ int cx18_av_loadfw(struct cx18 *cx)
the address. We can only write the lower
address byte of the address. */
if ((value & 0x3F00) != (dl_control & 0x3F00)) {
- retries = 5;
+ retries2 = 5;
break;
}
}
- if (retries >= 5)
+ if (retries2 >= 5)
break;
}
if (i == size)
break;
- retries++;
+ retries1++;
}
- if (retries >= 5) {
+ if (retries1 >= 5) {
CX18_ERR("unable to load firmware %s\n", FWFILE);
release_firmware(fw);
return -EIO;
diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c
index 22434aadd..bd18afebb 100644
--- a/linux/drivers/media/video/cx18/cx18-driver.c
+++ b/linux/drivers/media/video/cx18/cx18-driver.c
@@ -74,9 +74,9 @@ static int radio[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1 };
-static int cardtype_c = 1;
-static int tuner_c = 1;
-static int radio_c = 1;
+static unsigned cardtype_c = 1;
+static unsigned tuner_c = 1;
+static unsigned radio_c = 1;
static char pal[] = "--";
static char secam[] = "--";
static char ntsc[] = "-";
diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h
index 4801bc7fb..26359897d 100644
--- a/linux/drivers/media/video/cx18/cx18-driver.h
+++ b/linux/drivers/media/video/cx18/cx18-driver.h
@@ -216,8 +216,7 @@ struct cx18_buffer {
struct cx18_queue {
struct list_head list;
- u32 buffers;
- u32 length;
+ atomic_t buffers;
u32 bytesused;
};
@@ -237,6 +236,8 @@ struct cx18_dvb {
struct cx18; /* forward reference */
struct cx18_scb; /* forward reference */
+#define CX18_INVALID_TASK_HANDLE 0xffffffff
+
struct cx18_stream {
/* These first four fields are always set, even if the stream
is not actually created. */
@@ -259,7 +260,6 @@ struct cx18_stream {
/* Buffer Stats */
u32 buffers;
u32 buf_size;
- u32 buffers_stolen;
/* Buffer Queues */
struct cx18_queue q_free; /* free buffers */
diff --git a/linux/drivers/media/video/cx18/cx18-fileops.c b/linux/drivers/media/video/cx18/cx18-fileops.c
index 12f9de74d..6ef8a99aa 100644
--- a/linux/drivers/media/video/cx18/cx18-fileops.c
+++ b/linux/drivers/media/video/cx18/cx18-fileops.c
@@ -132,6 +132,7 @@ static void cx18_dualwatch(struct cx18 *cx)
u16 new_stereo_mode;
const u16 stereo_mask = 0x0300;
const u16 dual = 0x0200;
+ u32 h;
new_stereo_mode = cx->params.audio_properties & stereo_mask;
memset(&vt, 0, sizeof(vt));
@@ -143,13 +144,21 @@ static void cx18_dualwatch(struct cx18 *cx)
if (new_stereo_mode == cx->dualwatch_stereo_mode)
return;
- new_bitmap = new_stereo_mode | (cx->params.audio_properties & ~stereo_mask);
+ new_bitmap = new_stereo_mode
+ | (cx->params.audio_properties & ~stereo_mask);
- CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. new audio_bitmask=0x%ux\n",
- cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap);
+ CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. "
+ "new audio_bitmask=0x%ux\n",
+ cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap);
- if (cx18_vapi(cx, CX18_CPU_SET_AUDIO_PARAMETERS, 2,
- cx18_find_handle(cx), new_bitmap) == 0) {
+ h = cx18_find_handle(cx);
+ if (h == CX18_INVALID_TASK_HANDLE) {
+ CX18_DEBUG_INFO("dualwatch: can't find valid task handle\n");
+ return;
+ }
+
+ if (cx18_vapi(cx,
+ CX18_CPU_SET_AUDIO_PARAMETERS, 2, h, new_bitmap) == 0) {
cx->dualwatch_stereo_mode = new_stereo_mode;
return;
}
@@ -258,7 +267,7 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block,
prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
/* New buffers might have become available before we were added
to the waitqueue */
- if (!s->q_full.buffers)
+ if (!atomic_read(&s->q_full.buffers))
schedule();
finish_wait(&s->waitq, &wait);
if (signal_pending(current)) {
@@ -544,7 +553,7 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
CX18_DEBUG_HI_FILE("Encoder poll\n");
poll_wait(filp, &s->waitq, wait);
- if (s->q_full.length || s->q_io.length)
+ if (atomic_read(&s->q_full.buffers) || atomic_read(&s->q_io.buffers))
return POLLIN | POLLRDNORM;
if (eof)
return POLLHUP;
@@ -730,20 +739,28 @@ int cx18_v4l2_open(struct inode *inode, struct file *filp)
void cx18_mute(struct cx18 *cx)
{
- if (atomic_read(&cx->ana_capturing))
- cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
- cx18_find_handle(cx), 1);
+ u32 h;
+ if (atomic_read(&cx->ana_capturing)) {
+ h = cx18_find_handle(cx);
+ if (h != CX18_INVALID_TASK_HANDLE)
+ cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 1);
+ else
+ CX18_ERR("Can't find valid task handle for mute\n");
+ }
CX18_DEBUG_INFO("Mute\n");
}
void cx18_unmute(struct cx18 *cx)
{
+ u32 h;
if (atomic_read(&cx->ana_capturing)) {
- cx18_msleep_timeout(100, 0);
- cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2,
- cx18_find_handle(cx), 12);
- cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
- cx18_find_handle(cx), 0);
+ h = cx18_find_handle(cx);
+ if (h != CX18_INVALID_TASK_HANDLE) {
+ cx18_msleep_timeout(100, 0);
+ cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, h, 12);
+ cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 0);
+ } else
+ CX18_ERR("Can't find valid task handle for unmute\n");
}
CX18_DEBUG_INFO("Unmute\n");
}
diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.c b/linux/drivers/media/video/cx18/cx18-ioctl.c
index e6c2bfa5d..3f5c2d09a 100644
--- a/linux/drivers/media/video/cx18/cx18-ioctl.c
+++ b/linux/drivers/media/video/cx18/cx18-ioctl.c
@@ -727,6 +727,7 @@ static int cx18_encoder_cmd(struct file *file, void *fh,
{
struct cx18_open_id *id = fh;
struct cx18 *cx = id->cx;
+ u32 h;
switch (enc->cmd) {
case V4L2_ENC_CMD_START:
@@ -748,8 +749,14 @@ static int cx18_encoder_cmd(struct file *file, void *fh,
return -EPERM;
if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
return 0;
+ h = cx18_find_handle(cx);
+ if (h == CX18_INVALID_TASK_HANDLE) {
+ CX18_ERR("Can't find valid task handle for "
+ "V4L2_ENC_CMD_PAUSE\n");
+ return -EBADFD;
+ }
cx18_mute(cx);
- cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, cx18_find_handle(cx));
+ cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, h);
break;
case V4L2_ENC_CMD_RESUME:
@@ -759,7 +766,13 @@ static int cx18_encoder_cmd(struct file *file, void *fh,
return -EPERM;
if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
return 0;
- cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, cx18_find_handle(cx));
+ h = cx18_find_handle(cx);
+ if (h == CX18_INVALID_TASK_HANDLE) {
+ CX18_ERR("Can't find valid task handle for "
+ "V4L2_ENC_CMD_RESUME\n");
+ return -EBADFD;
+ }
+ cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, h);
cx18_unmute(cx);
break;
@@ -836,7 +849,8 @@ static int cx18_log_status(struct file *file, void *fh)
continue;
CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n",
s->name, s->s_flags,
- (s->buffers - s->q_free.buffers) * 100 / s->buffers,
+ (s->buffers - atomic_read(&s->q_free.buffers))
+ * 100 / s->buffers,
(s->buffers * s->buf_size) / 1024, s->buffers);
}
CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n",
diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.c b/linux/drivers/media/video/cx18/cx18-mailbox.c
index 93177514e..1b9fbf9a6 100644
--- a/linux/drivers/media/video/cx18/cx18-mailbox.c
+++ b/linux/drivers/media/video/cx18/cx18-mailbox.c
@@ -82,6 +82,7 @@ static const struct cx18_api_info api_info[] = {
API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0),
API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST),
API_ENTRY(CPU, CX18_APU_RESETAI, API_FAST),
+ API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, 0),
API_ENTRY(0, 0, 0),
};
diff --git a/linux/drivers/media/video/cx18/cx18-queue.c b/linux/drivers/media/video/cx18/cx18-queue.c
index 8a4dd821f..a33ba04a2 100644
--- a/linux/drivers/media/video/cx18/cx18-queue.c
+++ b/linux/drivers/media/video/cx18/cx18-queue.c
@@ -37,8 +37,7 @@ void cx18_buf_swap(struct cx18_buffer *buf)
void cx18_queue_init(struct cx18_queue *q)
{
INIT_LIST_HEAD(&q->list);
- q->buffers = 0;
- q->length = 0;
+ atomic_set(&q->buffers, 0);
q->bytesused = 0;
}
@@ -55,8 +54,7 @@ void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf,
}
spin_lock_irqsave(&s->qlock, flags);
list_add_tail(&buf->list, &q->list);
- q->buffers++;
- q->length += s->buf_size;
+ atomic_inc(&q->buffers);
q->bytesused += buf->bytesused - buf->readpos;
spin_unlock_irqrestore(&s->qlock, flags);
}
@@ -70,8 +68,7 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q)
if (!list_empty(&q->list)) {
buf = list_entry(q->list.next, struct cx18_buffer, list);
list_del_init(q->list.next);
- q->buffers--;
- q->length -= s->buf_size;
+ atomic_dec(&q->buffers);
q->bytesused -= buf->bytesused - buf->readpos;
}
spin_unlock_irqrestore(&s->qlock, flags);
@@ -95,10 +92,8 @@ struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id,
/* the transport buffers are handled differently,
they are not moved to the full queue */
if (s->type != CX18_ENC_STREAM_TYPE_TS) {
- s->q_free.buffers--;
- s->q_free.length -= s->buf_size;
- s->q_full.buffers++;
- s->q_full.length += s->buf_size;
+ atomic_dec(&s->q_free.buffers);
+ atomic_inc(&s->q_full.buffers);
s->q_full.bytesused += buf->bytesused;
list_move_tail(&buf->list, &s->q_full.list);
}
@@ -110,99 +105,30 @@ struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id,
return NULL;
}
-static void cx18_queue_move_buf(struct cx18_stream *s, struct cx18_queue *from,
- struct cx18_queue *to, int clear, int full)
-{
- struct cx18_buffer *buf =
- list_entry(from->list.next, struct cx18_buffer, list);
-
- list_move_tail(from->list.next, &to->list);
- from->buffers--;
- from->length -= s->buf_size;
- from->bytesused -= buf->bytesused - buf->readpos;
- /* special handling for q_free */
- if (clear)
- buf->bytesused = buf->readpos = buf->b_flags = 0;
- else if (full) {
- /* special handling for stolen buffers, assume
- all bytes are used. */
- buf->bytesused = s->buf_size;
- buf->readpos = buf->b_flags = 0;
- }
- to->buffers++;
- to->length += s->buf_size;
- to->bytesused += buf->bytesused - buf->readpos;
-}
-
-/* Move 'needed_bytes' worth of buffers from queue 'from' into queue 'to'.
- If 'needed_bytes' == 0, then move all buffers from 'from' into 'to'.
- If 'steal' != NULL, then buffers may also taken from that queue if
- needed.
-
- The buffer is automatically cleared if it goes to the free queue. It is
- also cleared if buffers need to be taken from the 'steal' queue and
- the 'from' queue is the free queue.
-
- When 'from' is q_free, then needed_bytes is compared to the total
- available buffer length, otherwise needed_bytes is compared to the
- bytesused value. For the 'steal' queue the total available buffer
- length is always used.
-
- -ENOMEM is returned if the buffers could not be obtained, 0 if all
- buffers where obtained from the 'from' list and if non-zero then
- the number of stolen buffers is returned. */
-static int cx18_queue_move(struct cx18_stream *s, struct cx18_queue *from,
- struct cx18_queue *steal, struct cx18_queue *to,
- int needed_bytes)
+/* Move all buffers of a queue to q_free, while flushing the buffers */
+static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q)
{
unsigned long flags;
- int rc = 0;
- int from_free = from == &s->q_free;
- int to_free = to == &s->q_free;
- int bytes_available;
-
- spin_lock_irqsave(&s->qlock, flags);
- if (needed_bytes == 0) {
- from_free = 1;
- needed_bytes = from->length;
- }
-
- bytes_available = from_free ? from->length : from->bytesused;
- bytes_available += steal ? steal->length : 0;
+ struct cx18_buffer *buf;
- if (bytes_available < needed_bytes) {
- spin_unlock_irqrestore(&s->qlock, flags);
- return -ENOMEM;
- }
- if (from_free) {
- u32 old_length = to->length;
+ if (q == &s->q_free)
+ return;
- while (to->length - old_length < needed_bytes) {
- if (list_empty(&from->list))
- from = steal;
- if (from == steal)
- rc++; /* keep track of 'stolen' buffers */
- cx18_queue_move_buf(s, from, to, 1, 0);
- }
- } else {
- u32 old_bytesused = to->bytesused;
-
- while (to->bytesused - old_bytesused < needed_bytes) {
- if (list_empty(&from->list))
- from = steal;
- if (from == steal)
- rc++; /* keep track of 'stolen' buffers */
- cx18_queue_move_buf(s, from, to, to_free, rc);
- }
+ spin_lock_irqsave(&s->qlock, flags);
+ while (!list_empty(&q->list)) {
+ buf = list_entry(q->list.next, struct cx18_buffer, list);
+ list_move_tail(q->list.next, &s->q_free.list);
+ buf->bytesused = buf->readpos = buf->b_flags = 0;
+ atomic_inc(&s->q_free.buffers);
}
+ cx18_queue_init(q);
spin_unlock_irqrestore(&s->qlock, flags);
- return rc;
}
void cx18_flush_queues(struct cx18_stream *s)
{
- cx18_queue_move(s, &s->q_io, NULL, &s->q_free, 0);
- cx18_queue_move(s, &s->q_full, NULL, &s->q_free, 0);
+ cx18_queue_flush(s, &s->q_io);
+ cx18_queue_flush(s, &s->q_full);
}
int cx18_stream_alloc(struct cx18_stream *s)
@@ -217,10 +143,10 @@ int cx18_stream_alloc(struct cx18_stream *s)
s->name, s->buffers, s->buf_size,
s->buffers * s->buf_size / 1024);
- if (((char *)&cx->scb->cpu_mdl[cx->mdl_offset + s->buffers] -
- (char *)cx->scb) > SCB_RESERVED_SIZE) {
- unsigned bufsz = (((char *)cx->scb) + SCB_RESERVED_SIZE -
- ((char *)cx->scb->cpu_mdl));
+ if (((char __iomem *)&cx->scb->cpu_mdl[cx->mdl_offset + s->buffers] -
+ (char __iomem *)cx->scb) > SCB_RESERVED_SIZE) {
+ unsigned bufsz = (((char __iomem *)cx->scb) + SCB_RESERVED_SIZE -
+ ((char __iomem *)cx->scb->cpu_mdl));
CX18_ERR("Too many buffers, cannot fit in SCB area\n");
CX18_ERR("Max buffers = %zd\n",
diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c
index 911a97ce3..02a443104 100644
--- a/linux/drivers/media/video/cx18/cx18-streams.c
+++ b/linux/drivers/media/video/cx18/cx18-streams.c
@@ -119,7 +119,7 @@ static void cx18_stream_init(struct cx18 *cx, int type)
s->cx = cx;
s->type = type;
s->name = cx18_stream_info[type].name;
- s->handle = 0xffffffff;
+ s->handle = CX18_INVALID_TASK_HANDLE;
s->dma = cx18_stream_info[type].dma;
s->buf_size = cx->stream_buf_size[type];
@@ -432,7 +432,6 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
default:
return -EINVAL;
}
- s->buffers_stolen = 0;
/* mute/unmute video */
cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2,
@@ -489,7 +488,14 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
/* begin_capture */
if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) {
CX18_DEBUG_WARN("Error starting capture!\n");
+ /* Ensure we're really not capturing before releasing MDLs */
+ if (s->type == CX18_ENC_STREAM_TYPE_MPG)
+ cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, 1);
+ else
+ cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle);
+ cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);
cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
+ /* FIXME - clean-up DSP0_INT mask, i_flags, s_flags, etc. */
return -EINVAL;
}
@@ -568,6 +574,9 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
#endif
}
+ /* Tell the CX23418 it can't use our buffers anymore */
+ cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);
+
if (s->type != CX18_ENC_STREAM_TYPE_TS)
atomic_dec(&cx->ana_capturing);
atomic_dec(&cx->tot_capturing);
@@ -576,7 +585,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
clear_bit(CX18_F_S_STREAMING, &s->s_flags);
cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
- s->handle = 0xffffffff;
+ s->handle = CX18_INVALID_TASK_HANDLE;
if (atomic_read(&cx->tot_capturing) > 0)
return 0;
@@ -595,8 +604,8 @@ u32 cx18_find_handle(struct cx18 *cx)
for (i = 0; i < CX18_MAX_STREAMS; i++) {
struct cx18_stream *s = &cx->streams[i];
- if (s->v4l2dev && s->handle)
+ if (s->v4l2dev && (s->handle != CX18_INVALID_TASK_HANDLE))
return s->handle;
}
- return 0;
+ return CX18_INVALID_TASK_HANDLE;
}
diff --git a/linux/drivers/media/video/cx18/cx23418.h b/linux/drivers/media/video/cx18/cx23418.h
index e7ed05305..668f968d7 100644
--- a/linux/drivers/media/video/cx18/cx23418.h
+++ b/linux/drivers/media/video/cx18/cx23418.h
@@ -351,7 +351,7 @@
Descriptor Lists to the driver
IN[0] - Task handle. Handle of the task to start
ReturnCode - One of the ERR_DE_... */
-/* #define CX18_CPU_DE_ReleaseMDL (CPU_CMD_MASK_DE | 0x0006) */
+#define CX18_CPU_DE_RELEASE_MDL (CPU_CMD_MASK_DE | 0x0006)
/* Description: This command signals the cpu that the dat buffer has been
consumed and ready for re-use.
diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c
index df7c5cb0a..0d705af05 100644
--- a/linux/drivers/media/video/gspca/gspca.c
+++ b/linux/drivers/media/video/gspca/gspca.c
@@ -1408,7 +1408,7 @@ static int vidioc_dqbuf(struct file *file, void *priv,
i = ret; /* frame index */
frame = &gspca_dev->frame[i];
if (gspca_dev->memory == V4L2_MEMORY_USERPTR) {
- if (copy_to_user((__u8 *) frame->v4l2_buf.m.userptr,
+ if (copy_to_user((__u8 __user *) frame->v4l2_buf.m.userptr,
frame->data,
frame->v4l2_buf.bytesused)) {
PDEBUG(D_ERR|D_STREAM,
diff --git a/linux/drivers/media/video/ks0127.c b/linux/drivers/media/video/ks0127.c
index 90451230d..b21b6f097 100644
--- a/linux/drivers/media/video/ks0127.c
+++ b/linux/drivers/media/video/ks0127.c
@@ -680,26 +680,27 @@ static int ks0127_command(struct i2c_client *client,
case DECODER_ENABLE_OUTPUT:
{
+ int enable;
- int *iarg = arg;
- int enable = (*iarg != 0);
- if (enable) {
- dprintk("ks0127: command "
+ iarg = arg;
+ enable = (*iarg != 0);
+ if (enable) {
+ dprintk("ks0127: command "
"DECODER_ENABLE_OUTPUT on "
"(%d)\n", enable);
- /* All output pins on */
- ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x30);
- /* Obey the OEN pin */
- ks0127_and_or(ks, KS_CDEM, 0x7f, 0x00);
- } else {
- dprintk("ks0127: command "
+ /* All output pins on */
+ ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x30);
+ /* Obey the OEN pin */
+ ks0127_and_or(ks, KS_CDEM, 0x7f, 0x00);
+ } else {
+ dprintk("ks0127: command "
"DECODER_ENABLE_OUTPUT off "
"(%d)\n", enable);
- /* Video output pins off */
- ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x00);
- /* Ignore the OEN pin */
- ks0127_and_or(ks, KS_CDEM, 0x7f, 0x80);
- }
+ /* Video output pins off */
+ ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x00);
+ /* Ignore the OEN pin */
+ ks0127_and_or(ks, KS_CDEM, 0x7f, 0x80);
+ }
}
break;
diff --git a/linux/drivers/media/video/meye.c b/linux/drivers/media/video/meye.c
index e9854d5ec..535443887 100644
--- a/linux/drivers/media/video/meye.c
+++ b/linux/drivers/media/video/meye.c
@@ -1778,6 +1778,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
goto outnotdev;
}
+ ret = -ENOMEM;
meye.mchip_dev = pcidev;
meye.video_dev = video_device_alloc();
if (!meye.video_dev) {
@@ -1785,7 +1786,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
goto outnotdev;
}
- ret = -ENOMEM;
meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE);
if (!meye.grab_temp) {
printk(KERN_ERR "meye: grab buffer allocation failed\n");
@@ -1810,6 +1810,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
memcpy(meye.video_dev, &meye_template, sizeof(meye_template));
meye.video_dev->parent = &meye.mchip_dev->dev;
+ ret = -EIO;
if ((ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1))) {
printk(KERN_ERR "meye: unable to power on the camera\n");
printk(KERN_ERR "meye: did you enable the camera in "
@@ -1817,7 +1818,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
goto outsonypienable;
}
- ret = -EIO;
if ((ret = pci_enable_device(meye.mchip_dev))) {
printk(KERN_ERR "meye: pci_enable_device failed\n");
goto outenabledev;
diff --git a/linux/drivers/media/video/mxb.c b/linux/drivers/media/video/mxb.c
index 974505a9e..e0fbbd3a7 100644
--- a/linux/drivers/media/video/mxb.c
+++ b/linux/drivers/media/video/mxb.c
@@ -931,27 +931,29 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
return 0;
}
-static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
+static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)
{
- struct mxb* mxb = (struct mxb*)dev->ext_priv;
+ struct mxb *mxb = (struct mxb *)dev->ext_priv;
int zero = 0;
int one = 1;
- if(V4L2_STD_PAL_I == std->id ) {
+ if (V4L2_STD_PAL_I == standard->id) {
v4l2_std_id std = V4L2_STD_PAL_I;
+
DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n"));
/* set the 7146 gpio register -- I don't know what this does exactly */
saa7146_write(dev, GPIO_CTRL, 0x00404050);
/* unset the 7111 gpio register -- I don't know what this does exactly */
- mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &zero);
+ mxb->saa7111a->driver->command(mxb->saa7111a, DECODER_SET_GPIO, &zero);
mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
} else {
v4l2_std_id std = V4L2_STD_PAL_BG;
+
DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n"));
/* set the 7146 gpio register -- I don't know what this does exactly */
saa7146_write(dev, GPIO_CTRL, 0x00404050);
/* set the 7111 gpio register -- I don't know what this does exactly */
- mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &one);
+ mxb->saa7111a->driver->command(mxb->saa7111a, DECODER_SET_GPIO, &one);
mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
}
return 0;
diff --git a/linux/drivers/media/video/ov511.c b/linux/drivers/media/video/ov511.c
index c693b6fb0..1c5b07566 100644
--- a/linux/drivers/media/video/ov511.c
+++ b/linux/drivers/media/video/ov511.c
@@ -626,9 +626,9 @@ ov511_i2c_write_internal(struct usb_ov511 *ov,
break;
/* Retry until idle */
- do
+ do {
rc = reg_r(ov, R511_I2C_CTL);
- while (rc > 0 && ((rc&1) == 0));
+ } while (rc > 0 && ((rc&1) == 0));
if (rc < 0)
break;
@@ -703,9 +703,9 @@ ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg)
return rc;
/* Retry until idle */
- do
- rc = reg_r(ov, R511_I2C_CTL);
- while (rc > 0 && ((rc&1) == 0));
+ do {
+ rc = reg_r(ov, R511_I2C_CTL);
+ } while (rc > 0 && ((rc & 1) == 0));
if (rc < 0)
return rc;
@@ -729,9 +729,9 @@ ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg)
return rc;
/* Retry until idle */
- do
+ do {
rc = reg_r(ov, R511_I2C_CTL);
- while (rc > 0 && ((rc&1) == 0));
+ } while (rc > 0 && ((rc&1) == 0));
if (rc < 0)
return rc;
diff --git a/linux/drivers/media/video/pwc/pwc-ctrl.c b/linux/drivers/media/video/pwc/pwc-ctrl.c
index 1cccd5c77..dbc560742 100644
--- a/linux/drivers/media/video/pwc/pwc-ctrl.c
+++ b/linux/drivers/media/video/pwc/pwc-ctrl.c
@@ -1635,15 +1635,15 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
case VIDIOCPWCGVIDCMD:
{
- ARG_DEF(struct pwc_video_command, cmd);
-
- ARGR(cmd).type = pdev->type;
- ARGR(cmd).release = pdev->release;
- ARGR(cmd).command_len = pdev->cmd_len;
- memcpy(&ARGR(cmd).command_buf, pdev->cmd_buf, pdev->cmd_len);
- ARGR(cmd).bandlength = pdev->vbandlength;
- ARGR(cmd).frame_size = pdev->frame_size;
- ARG_OUT(cmd)
+ ARG_DEF(struct pwc_video_command, vcmd);
+
+ ARGR(vcmd).type = pdev->type;
+ ARGR(vcmd).release = pdev->release;
+ ARGR(vcmd).command_len = pdev->cmd_len;
+ memcpy(&ARGR(vcmd).command_buf, pdev->cmd_buf, pdev->cmd_len);
+ ARGR(vcmd).bandlength = pdev->vbandlength;
+ ARGR(vcmd).frame_size = pdev->frame_size;
+ ARG_OUT(vcmd)
break;
}
/*
diff --git a/linux/drivers/media/video/s2255drv.c b/linux/drivers/media/video/s2255drv.c
index e745e4f25..279c1e2ae 100644
--- a/linux/drivers/media/video/s2255drv.c
+++ b/linux/drivers/media/video/s2255drv.c
@@ -68,20 +68,21 @@
/* USB endpoint number for configuring the device */
#define S2255_CONFIG_EP 2
/* maximum time for DSP to start responding after last FW word loaded(ms) */
-#define S2255_DSP_BOOTTIME 400
+#define S2255_DSP_BOOTTIME 800
/* maximum time to wait for firmware to load (ms) */
#define S2255_LOAD_TIMEOUT (5000 + S2255_DSP_BOOTTIME)
#define S2255_DEF_BUFS 16
+#define S2255_SETMODE_TIMEOUT 500
#define MAX_CHANNELS 4
-#define FRAME_MARKER 0x2255DA4AL
-#define MAX_PIPE_USBBLOCK (40 * 1024)
-#define DEFAULT_PIPE_USBBLOCK (16 * 1024)
+#define S2255_MARKER_FRAME 0x2255DA4AL
+#define S2255_MARKER_RESPONSE 0x2255ACACL
+#define S2255_USB_XFER_SIZE (16 * 1024)
#define MAX_CHANNELS 4
#define MAX_PIPE_BUFFERS 1
#define SYS_FRAMES 4
/* maximum size is PAL full size plus room for the marker header(s) */
-#define SYS_FRAMES_MAXSIZE (720 * 288 * 2 * 2 + 4096)
-#define DEF_USB_BLOCK (4096)
+#define SYS_FRAMES_MAXSIZE (720*288*2*2 + 4096)
+#define DEF_USB_BLOCK S2255_USB_XFER_SIZE
#define LINE_SZ_4CIFS_NTSC 640
#define LINE_SZ_2CIFS_NTSC 640
#define LINE_SZ_1CIFS_NTSC 320
@@ -109,6 +110,9 @@
#define COLOR_YUVPL 1 /* YUV planar */
#define COLOR_YUVPK 2 /* YUV packed */
#define COLOR_Y8 4 /* monochrome */
+#define COLOR_JPG 5 /* JPEG */
+#define MASK_COLOR 0xff
+#define MASK_JPG_QUALITY 0xff00
/* frame decimation. Not implemented by V4L yet(experimental in V4L) */
#define FDEC_1 1 /* capture every frame. default */
@@ -149,16 +153,14 @@ struct s2255_mode {
u32 restart; /* if DSP requires restart */
};
-/* frame structure */
-#define FRAME_STATE_UNUSED 0
-#define FRAME_STATE_FILLING 1
-#define FRAME_STATE_FULL 2
+#define S2255_READ_IDLE 0
+#define S2255_READ_FRAME 1
+/* frame structure */
struct s2255_framei {
unsigned long size;
-
- unsigned long ulState; /* ulState ==0 unused, 1 being filled, 2 full */
+ unsigned long ulState; /* ulState:S2255_READ_IDLE, S2255_READ_FRAME*/
void *lpvbits; /* image data */
unsigned long cur_size; /* current data copied to it */
};
@@ -189,6 +191,10 @@ struct s2255_dmaqueue {
#define S2255_FW_FAILED 3
#define S2255_FW_DISCONNECTING 4
+#define S2255_FW_MARKER 0x22552f2f
+/* 2255 read states */
+#define S2255_READ_IDLE 0
+#define S2255_READ_FRAME 1
struct s2255_fw {
int fw_loaded;
int fw_size;
@@ -196,7 +202,6 @@ struct s2255_fw {
atomic_t fw_state;
void *pfw_data;
wait_queue_head_t wait_fw;
- struct timer_list dsp_wait;
const struct firmware *fw;
};
@@ -243,10 +248,20 @@ struct s2255_dev {
int last_frame[MAX_CHANNELS];
u32 cc; /* current channel */
int b_acquire[MAX_CHANNELS];
+ /* allocated image size */
unsigned long req_image_size[MAX_CHANNELS];
+ /* received packet size */
+ unsigned long pkt_size[MAX_CHANNELS];
int bad_payload[MAX_CHANNELS];
unsigned long frame_count[MAX_CHANNELS];
int frame_ready;
+ /* if JPEG image */
+ int jpg_size[MAX_CHANNELS];
+ /* if channel configured to default state */
+ int chn_configured[MAX_CHANNELS];
+ wait_queue_head_t wait_setmode[MAX_CHANNELS];
+ int setmode_ready[MAX_CHANNELS];
+ int chn_ready;
struct kref kref;
spinlock_t slock;
};
@@ -307,12 +322,16 @@ static void s2255_stop_readpipe(struct s2255_dev *dev);
static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn);
static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn);
static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
- int chn);
+ int chn, int jpgsize);
static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
struct s2255_mode *mode);
static int s2255_board_shutdown(struct s2255_dev *dev);
static void s2255_exit_v4l(struct s2255_dev *dev);
-static void s2255_fwload_start(struct s2255_dev *dev);
+static void s2255_fwload_start(struct s2255_dev *dev, int reset);
+static void s2255_destroy(struct kref *kref);
+static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req,
+ u16 index, u16 value, void *buf,
+ s32 buf_len, int bOut);
#define dprintk(level, fmt, arg...) \
do { \
@@ -408,6 +427,10 @@ static const struct s2255_fmt formats[] = {
.fourcc = V4L2_PIX_FMT_UYVY,
.depth = 16
}, {
+ .name = "JPG",
+ .fourcc = V4L2_PIX_FMT_JPEG,
+ .depth = 24
+ }, {
.name = "8bpp GREY",
.fourcc = V4L2_PIX_FMT_GREY,
.depth = 8
@@ -465,6 +488,13 @@ static void planar422p_to_yuv_packed(const unsigned char *in,
return;
}
+void s2255_reset_dsppower(struct s2255_dev *dev)
+{
+ s2255_vendor_req(dev, 0x40, 0x0b0b, 0x0b0b, NULL, 0, 1);
+ msleep(10);
+ s2255_vendor_req(dev, 0x50, 0x0000, 0x0000, NULL, 0, 1);
+ return;
+}
/* kickstarts the firmware loading. from probe
*/
@@ -481,18 +511,6 @@ static void s2255_timer(unsigned long user_data)
}
}
-/* called when DSP is up and running. DSP is guaranteed to
- be running after S2255_DSP_BOOTTIME */
-static void s2255_dsp_running(unsigned long user_data)
-{
- struct s2255_fw *data = (struct s2255_fw *)user_data;
- dprintk(1, "dsp running\n");
- atomic_set(&data->fw_state, S2255_FW_SUCCESS);
- wake_up(&data->wait_fw);
- printk(KERN_INFO "s2255: firmware loaded successfully\n");
- return;
-}
-
/* this loads the firmware asynchronously.
Originally this was done synchroously in probe.
@@ -550,19 +568,14 @@ static void s2255_fwchunk_complete(struct urb *urb)
}
data->fw_loaded += len;
} else {
- init_timer(&data->dsp_wait);
- data->dsp_wait.function = s2255_dsp_running;
- data->dsp_wait.data = (unsigned long)data;
atomic_set(&data->fw_state, S2255_FW_LOADED_DSPWAIT);
- mod_timer(&data->dsp_wait, msecs_to_jiffies(S2255_DSP_BOOTTIME)
- + jiffies);
}
dprintk(100, "2255 complete done\n");
return;
}
-static int s2255_got_frame(struct s2255_dev *dev, int chn)
+static int s2255_got_frame(struct s2255_dev *dev, int chn, int jpgsize)
{
struct s2255_dmaqueue *dma_q = &dev->vidq[chn];
struct s2255_buffer *buf;
@@ -587,8 +600,7 @@ static int s2255_got_frame(struct s2255_dev *dev, int chn)
list_del(&buf->vb.queue);
do_gettimeofday(&buf->vb.ts);
dprintk(100, "[%p/%d] wakeup\n", buf, buf->vb.i);
-
- s2255_fillbuff(dev, buf, dma_q->channel);
+ s2255_fillbuff(dev, buf, dma_q->channel, jpgsize);
wake_up(&buf->vb.done);
dprintk(2, "wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i);
unlock:
@@ -622,7 +634,7 @@ static const struct s2255_fmt *format_by_fourcc(int fourcc)
*
*/
static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
- int chn)
+ int chn, int jpgsize)
{
int pos = 0;
struct timeval ts;
@@ -650,6 +662,10 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
case V4L2_PIX_FMT_GREY:
memcpy(vbuf, tmpbuf, buf->vb.width * buf->vb.height);
break;
+ case V4L2_PIX_FMT_JPEG:
+ buf->vb.size = jpgsize;
+ memcpy(vbuf, tmpbuf, buf->vb.size);
+ break;
case V4L2_PIX_FMT_YUV422P:
memcpy(vbuf, tmpbuf,
buf->vb.width * buf->vb.height * 2);
@@ -658,9 +674,6 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
printk(KERN_DEBUG "s2255: unknown format?\n");
}
dev->last_frame[chn] = -1;
- /* done with the frame, free it */
- frm->ulState = 0;
- dprintk(4, "freeing buffer\n");
} else {
printk(KERN_ERR "s2255: =======no frame\n");
return;
@@ -1022,6 +1035,9 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
case V4L2_PIX_FMT_GREY:
fh->mode.color = COLOR_Y8;
break;
+ case V4L2_PIX_FMT_JPEG:
+ fh->mode.color = COLOR_JPG | (50 << 8);
+ break;
case V4L2_PIX_FMT_YUV422P:
fh->mode.color = COLOR_YUVPL;
break;
@@ -1140,7 +1156,7 @@ static u32 get_transfer_size(struct s2255_mode *mode)
}
}
outImageSize = linesPerFrame * pixelsPerLine;
- if (mode->color != COLOR_Y8) {
+ if ((mode->color & MASK_COLOR) != COLOR_Y8) {
/* 2 bytes/pixel if not monochrome */
outImageSize *= 2;
}
@@ -1186,6 +1202,7 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
u32 *buffer;
unsigned long chn_rev;
+ mutex_lock(&dev->lock);
chn_rev = G_chnmap[chn];
dprintk(3, "mode scale [%ld] %p %d\n", chn, mode, mode->scale);
dprintk(3, "mode scale [%ld] %p %d\n", chn, &dev->mode[chn],
@@ -1200,6 +1217,7 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
buffer = kzalloc(512, GFP_KERNEL);
if (buffer == NULL) {
dev_err(&dev->udev->dev, "out of mem\n");
+ mutex_unlock(&dev->lock);
return -ENOMEM;
}
@@ -1215,12 +1233,20 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
dprintk(1, "set mode done chn %lu, %d\n", chn, res);
/* wait at least 3 frames before continuing */
- if (mode->restart)
- msleep(125);
+ if (mode->restart) {
+ dev->setmode_ready[chn] = 0;
+ wait_event_timeout(dev->wait_setmode[chn],
+ (dev->setmode_ready[chn] != 0),
+ msecs_to_jiffies(S2255_SETMODE_TIMEOUT));
+ if (dev->setmode_ready[chn] != 1) {
+ printk(KERN_DEBUG "s2255: no set mode response\n");
+ res = -EFAULT;
+ }
+ }
/* clear the restart flag */
dev->mode[chn].restart = 0;
-
+ mutex_unlock(&dev->lock);
return res;
}
@@ -1270,7 +1296,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
dev->bad_payload[chn] = 0;
dev->cur_frame[chn] = 0;
for (j = 0; j < SYS_FRAMES; j++) {
- dev->buffer[chn].frame[j].ulState = 0;
+ dev->buffer[chn].frame[j].ulState = S2255_READ_IDLE;
dev->buffer[chn].frame[j].cur_size = 0;
}
res = videobuf_streamon(&fh->vb_vidq);
@@ -1455,6 +1481,7 @@ static int s2255_open(struct inode *inode, struct file *file)
enum v4l2_buf_type type = 0;
int i = 0;
int cur_channel = -1;
+ int state;
dprintk(1, "s2255: open called (minor=%d)\n", minor);
lock_kernel();
@@ -1471,47 +1498,77 @@ static int s2255_open(struct inode *inode, struct file *file)
if ((NULL == dev) || (cur_channel == -1)) {
unlock_kernel();
- dprintk(1, "s2255: openv4l no dev\n");
+ printk(KERN_INFO "s2255: openv4l no dev\n");
return -ENODEV;
}
+ if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_DISCONNECTING) {
+ unlock_kernel();
+ printk(KERN_INFO "disconnecting\n");
+ return -ENODEV;
+ }
+ kref_get(&dev->kref);
mutex_lock(&dev->open_lock);
dev->users[cur_channel]++;
dprintk(4, "s2255: open_handles %d\n", dev->users[cur_channel]);
- if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_FAILED) {
+ switch (atomic_read(&dev->fw_data->fw_state)) {
+ case S2255_FW_FAILED:
err("2255 firmware load failed. retrying.\n");
- s2255_fwload_start(dev);
+ s2255_fwload_start(dev, 1);
wait_event_timeout(dev->fw_data->wait_fw,
- (atomic_read(&dev->fw_data->fw_state)
- != S2255_FW_NOTLOADED),
+ ((atomic_read(&dev->fw_data->fw_state)
+ == S2255_FW_SUCCESS) ||
+ (atomic_read(&dev->fw_data->fw_state)
+ == S2255_FW_DISCONNECTING)),
msecs_to_jiffies(S2255_LOAD_TIMEOUT));
- if (atomic_read(&dev->fw_data->fw_state)
- != S2255_FW_SUCCESS) {
- printk(KERN_INFO "2255 FW load failed.\n");
- dev->users[cur_channel]--;
- mutex_unlock(&dev->open_lock);
- unlock_kernel();
- return -EFAULT;
- }
- } else if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_NOTLOADED) {
+ break;
+ case S2255_FW_NOTLOADED:
+ case S2255_FW_LOADED_DSPWAIT:
/* give S2255_LOAD_TIMEOUT time for firmware to load in case
driver loaded and then device immediately opened */
printk(KERN_INFO "%s waiting for firmware load\n", __func__);
wait_event_timeout(dev->fw_data->wait_fw,
- (atomic_read(&dev->fw_data->fw_state)
- != S2255_FW_NOTLOADED),
- msecs_to_jiffies(S2255_LOAD_TIMEOUT));
- if (atomic_read(&dev->fw_data->fw_state)
- != S2255_FW_SUCCESS) {
- printk(KERN_INFO "2255 firmware not loaded"
- "try again\n");
- dev->users[cur_channel]--;
- mutex_unlock(&dev->open_lock);
- unlock_kernel();
- return -EBUSY;
+ ((atomic_read(&dev->fw_data->fw_state)
+ == S2255_FW_SUCCESS) ||
+ (atomic_read(&dev->fw_data->fw_state)
+ == S2255_FW_DISCONNECTING)),
+ msecs_to_jiffies(S2255_LOAD_TIMEOUT));
+ break;
+ case S2255_FW_SUCCESS:
+ default:
+ break;
+ }
+ state = atomic_read(&dev->fw_data->fw_state);
+ if (state != S2255_FW_SUCCESS) {
+ int rc;
+ switch (state) {
+ case S2255_FW_FAILED:
+ printk(KERN_INFO "2255 FW load failed. %d\n", state);
+ rc = -ENODEV;
+ break;
+ case S2255_FW_DISCONNECTING:
+ printk(KERN_INFO "%s: disconnecting\n", __func__);
+ rc = -ENODEV;
+ break;
+ case S2255_FW_LOADED_DSPWAIT:
+ case S2255_FW_NOTLOADED:
+ printk(KERN_INFO "%s: firmware not loaded yet"
+ "please try again later\n",
+ __func__);
+ rc = -EAGAIN;
+ break;
+ default:
+ printk(KERN_INFO "%s: unknown state\n", __func__);
+ rc = -EFAULT;
+ break;
}
+ dev->users[cur_channel]--;
+ mutex_unlock(&dev->open_lock);
+ kref_put(&dev->kref, s2255_destroy);
+ unlock_kernel();
+ return rc;
}
/* allocate + initialize per filehandle data */
@@ -1519,6 +1576,7 @@ static int s2255_open(struct inode *inode, struct file *file)
if (NULL == fh) {
dev->users[cur_channel]--;
mutex_unlock(&dev->open_lock);
+ kref_put(&dev->kref, s2255_destroy);
unlock_kernel();
return -ENOMEM;
}
@@ -1533,6 +1591,13 @@ static int s2255_open(struct inode *inode, struct file *file)
fh->height = NUM_LINES_4CIFS_NTSC * 2;
fh->channel = cur_channel;
+ /* configure channel to default state */
+ if (!dev->chn_configured[cur_channel]) {
+ s2255_set_mode(dev, cur_channel, &fh->mode);
+ dev->chn_configured[cur_channel] = 1;
+ }
+
+
/* Put all controls at a sane state */
for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++)
qctl_regs[i] = s2255_qctrl[i].default_value;
@@ -1551,7 +1616,6 @@ static int s2255_open(struct inode *inode, struct file *file)
V4L2_FIELD_INTERLACED,
sizeof(struct s2255_buffer), fh);
- kref_get(&dev->kref);
mutex_unlock(&dev->open_lock);
unlock_kernel();
return 0;
@@ -1575,30 +1639,24 @@ static unsigned int s2255_poll(struct file *file,
static void s2255_destroy(struct kref *kref)
{
struct s2255_dev *dev = to_s2255_dev(kref);
+ struct list_head *list;
+ int i;
if (!dev) {
printk(KERN_ERR "s2255drv: kref problem\n");
return;
}
-
- /*
- * Wake up any firmware load waiting (only done in .open,
- * which holds the open_lock mutex)
- */
atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING);
wake_up(&dev->fw_data->wait_fw);
-
- /* prevent s2255_disconnect from racing s2255_open */
+ for (i = 0; i < MAX_CHANNELS; i++) {
+ dev->setmode_ready[i] = 1;
+ wake_up(&dev->wait_setmode[i]);
+ }
mutex_lock(&dev->open_lock);
+ /* reset the DSP so firmware can be reload next time */
+ s2255_reset_dsppower(dev);
s2255_exit_v4l(dev);
- /*
- * device unregistered so no longer possible to open. open_mutex
- * can be unlocked and timers deleted afterwards.
- */
- mutex_unlock(&dev->open_lock);
-
/* board shutdown stops the read pipe if it is running */
s2255_board_shutdown(dev);
-
/* make sure firmware still not trying to load */
del_timer(&dev->timer); /* only started in .probe and .open */
@@ -1608,23 +1666,19 @@ static void s2255_destroy(struct kref *kref)
usb_free_urb(dev->fw_data->fw_urb);
dev->fw_data->fw_urb = NULL;
}
-
- /*
- * delete the dsp_wait timer, which sets the firmware
- * state on completion. This is done before fw_data
- * is freed below.
- */
-
- del_timer(&dev->fw_data->dsp_wait); /* only started in .open */
-
if (dev->fw_data->fw)
release_firmware(dev->fw_data->fw);
kfree(dev->fw_data->pfw_data);
kfree(dev->fw_data);
-
usb_put_dev(dev->udev);
dprintk(1, "%s", __func__);
kfree(dev);
+
+ while (!list_empty(&s2255_devlist)) {
+ list = s2255_devlist.next;
+ list_del(list);
+ }
+ mutex_unlock(&dev->open_lock);
}
static int s2255_close(struct inode *inode, struct file *file)
@@ -1760,18 +1814,16 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
static void s2255_exit_v4l(struct s2255_dev *dev)
{
- struct list_head *list;
+
int i;
- /* unregister the video devices */
- while (!list_empty(&s2255_devlist)) {
- list = s2255_devlist.next;
- list_del(list);
- }
for (i = 0; i < MAX_CHANNELS; i++) {
- if (-1 != dev->vdev[i]->minor)
+ if (-1 != dev->vdev[i]->minor) {
video_unregister_device(dev->vdev[i]);
- else
+ printk(KERN_INFO "s2255 unregistered\n");
+ } else {
video_device_release(dev->vdev[i]);
+ printk(KERN_INFO "s2255 released\n");
+ }
}
}
@@ -1781,134 +1833,123 @@ static void s2255_exit_v4l(struct s2255_dev *dev)
* function again).
*
* Received frame structure:
- * bytes 0-3: marker : 0x2255DA4AL (FRAME_MARKER)
+ * bytes 0-3: marker : 0x2255DA4AL (S2255_MARKER_FRAME)
* bytes 4-7: channel: 0-3
* bytes 8-11: payload size: size of the frame
* bytes 12-payloadsize+12: frame data
*/
static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
{
- static int dbgsync; /* = 0; */
char *pdest;
u32 offset = 0;
- int bsync = 0;
- int btrunc = 0;
+ int bframe = 0;
char *psrc;
unsigned long copy_size;
unsigned long size;
s32 idx = -1;
struct s2255_framei *frm;
unsigned char *pdata;
- unsigned long cur_size;
- int bsearch = 0;
- struct s2255_bufferi *buf;
+
dprintk(100, "buffer to user\n");
idx = dev->cur_frame[dev->cc];
- buf = &dev->buffer[dev->cc];
- frm = &buf->frame[idx];
-
- if (frm->ulState == 0) {
- frm->ulState = 1;
- frm->cur_size = 0;
- bsearch = 1;
- } else if (frm->ulState == 2) {
- /* system frame was not freed */
- dprintk(2, "sys frame not free. overrun ringbuf\n");
- bsearch = 1;
- frm->ulState = 1;
- frm->cur_size = 0;
- }
-
- if (bsearch) {
- if (*(s32 *) pipe_info->transfer_buffer != FRAME_MARKER) {
- u32 jj;
- if (dbgsync == 0) {
- dprintk(3, "not synched, discarding all packets"
- "until marker\n");
+ frm = &dev->buffer[dev->cc].frame[idx];
- dbgsync++;
- }
- pdata = (unsigned char *)pipe_info->transfer_buffer;
- for (jj = 0; jj < (pipe_info->cur_transfer_size - 12);
- jj++) {
- if (*(s32 *) pdata == FRAME_MARKER) {
- int cc;
- dprintk(3,
- "found frame marker at offset:"
- " %d [%x %x]\n", jj, pdata[0],
- pdata[1]);
- offset = jj;
- bsync = 1;
- cc = *(u32 *) (pdata + sizeof(u32));
- if (cc >= MAX_CHANNELS) {
- printk(KERN_ERR
- "bad channel\n");
- return -EINVAL;
- }
- /* reverse it */
- dev->cc = G_chnmap[cc];
+ if (frm->ulState == S2255_READ_IDLE) {
+ int jj;
+ unsigned int cc;
+ s32 *pdword;
+ int payload;
+ /* search for marker codes */
+ pdata = (unsigned char *)pipe_info->transfer_buffer;
+ for (jj = 0; jj < (pipe_info->cur_transfer_size - 12); jj++) {
+ switch (*(s32 *) pdata) {
+ case S2255_MARKER_FRAME:
+ pdword = (s32 *)pdata;
+ dprintk(4, "found frame marker at offset:"
+ " %d [%x %x]\n", jj, pdata[0],
+ pdata[1]);
+ offset = jj + PREFIX_SIZE;
+ bframe = 1;
+ cc = pdword[1];
+ if (cc >= MAX_CHANNELS) {
+ printk(KERN_ERR
+ "bad channel\n");
+ return -EINVAL;
+ }
+ /* reverse it */
+ dev->cc = G_chnmap[cc];
+ payload = pdword[3];
+ if (payload > dev->req_image_size[dev->cc]) {
+ dev->bad_payload[dev->cc]++;
+ /* discard the bad frame */
+ return -EINVAL;
+ }
+ dev->pkt_size[dev->cc] = payload;
+ dev->jpg_size[dev->cc] = pdword[4];
+ break;
+ case S2255_MARKER_RESPONSE:
+ pdword = (s32 *)pdata;
+ pdata += DEF_USB_BLOCK;
+ jj += DEF_USB_BLOCK;
+ if (pdword[1] >= MAX_CHANNELS)
+ break;
+ cc = G_chnmap[pdword[1]];
+ if (!(cc >= 0 && cc < MAX_CHANNELS))
+ break;
+ switch (pdword[2]) {
+ case 0x01:
+ /* check if channel valid */
+ /* set mode ready */
+ dev->setmode_ready[cc] = 1;
+ wake_up(&dev->wait_setmode[cc]);
+ dprintk(5, "setmode ready %d\n", cc);
break;
+ case 0x10:
+
+ dev->chn_ready |= (1 << cc);
+ if ((dev->chn_ready & 0x0f) != 0x0f)
+ break;
+ /* all channels ready */
+ printk(KERN_INFO "s2255: fw loaded\n");
+ atomic_set(&dev->fw_data->fw_state,
+ S2255_FW_SUCCESS);
+ wake_up(&dev->fw_data->wait_fw);
+ break;
+ default:
+ printk(KERN_INFO "s2255 unknwn resp\n");
}
+ default:
pdata++;
+ break;
}
- if (bsync == 0)
- return -EINVAL;
- } else {
- u32 *pword;
- u32 payload;
- int cc;
- dbgsync = 0;
- bsync = 1;
- pword = (u32 *) pipe_info->transfer_buffer;
- cc = pword[1];
-
- if (cc >= MAX_CHANNELS) {
- printk("invalid channel found. "
- "throwing out data!\n");
- return -EINVAL;
- }
- dev->cc = G_chnmap[cc];
- payload = pword[2];
- if (payload != dev->req_image_size[dev->cc]) {
- dprintk(1, "[%d][%d]unexpected payload: %d"
- "required: %lu \n", cc, dev->cc,
- payload, dev->req_image_size[dev->cc]);
- dev->bad_payload[dev->cc]++;
- /* discard the bad frame */
- return -EINVAL;
- }
-
- }
- }
- /* search done. now find out if should be acquiring
- on this channel */
- if (!dev->b_acquire[dev->cc]) {
- frm->ulState = 0;
- return -EINVAL;
+ if (bframe)
+ break;
+ } /* for */
+ if (!bframe)
+ return -EINVAL;
}
+
idx = dev->cur_frame[dev->cc];
frm = &dev->buffer[dev->cc].frame[idx];
- if (frm->ulState == 0) {
- frm->ulState = 1;
- frm->cur_size = 0;
- } else if (frm->ulState == 2) {
- /* system frame ring buffer overrun */
- dprintk(2, "sys frame overrun. overwriting frame %d %d\n",
- dev->cc, idx);
- frm->ulState = 1;
- frm->cur_size = 0;
+ /* search done. now find out if should be acquiring on this channel */
+ if (!dev->b_acquire[dev->cc]) {
+ /* we found a frame, but this channel is turned off */
+ frm->ulState = S2255_READ_IDLE;
+ return -EINVAL;
}
- if (bsync) {
- /* skip the marker 512 bytes (and offset if out of sync) */
- psrc = (u8 *)pipe_info->transfer_buffer + offset + PREFIX_SIZE;
- } else {
- psrc = (u8 *)pipe_info->transfer_buffer;
+ if (frm->ulState == S2255_READ_IDLE) {
+ frm->ulState = S2255_READ_FRAME;
+ frm->cur_size = 0;
}
+ /* skip the marker 512 bytes (and offset if out of sync) */
+ psrc = (u8 *)pipe_info->transfer_buffer + offset;
+
+
if (frm->lpvbits == NULL) {
dprintk(1, "s2255 frame buffer == NULL.%p %p %d %d",
frm, dev, dev->cc, idx);
@@ -1917,33 +1958,20 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
pdest = frm->lpvbits + frm->cur_size;
- if (bsync) {
- copy_size =
- (pipe_info->cur_transfer_size - offset) - PREFIX_SIZE;
- if (copy_size > pipe_info->cur_transfer_size) {
- printk("invalid copy size, overflow!\n");
- return -ENOMEM;
- }
- } else {
- copy_size = pipe_info->cur_transfer_size;
- }
+ copy_size = (pipe_info->cur_transfer_size - offset);
- cur_size = frm->cur_size;
- size = dev->req_image_size[dev->cc];
+ size = dev->pkt_size[dev->cc] - PREFIX_SIZE;
- if ((copy_size + cur_size) > size) {
- copy_size = size - cur_size;
- btrunc = 1;
- }
+ /* sanity check on pdest */
+ if ((copy_size + frm->cur_size) < dev->req_image_size[dev->cc])
+ memcpy(pdest, psrc, copy_size);
- memcpy(pdest, psrc, copy_size);
- cur_size += copy_size;
frm->cur_size += copy_size;
- dprintk(50, "cur_size size %lu size %lu \n", cur_size, size);
+ dprintk(4, "cur_size size %lu size %lu \n", frm->cur_size, size);
+
+ if (frm->cur_size >= size) {
- if (cur_size >= (size - PREFIX_SIZE)) {
u32 cc = dev->cc;
- frm->ulState = 2;
dprintk(2, "****************[%d]Buffer[%d]full*************\n",
cc, idx);
dev->last_frame[cc] = dev->cur_frame[cc];
@@ -1952,16 +1980,13 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
if ((dev->cur_frame[cc] == SYS_FRAMES) ||
(dev->cur_frame[cc] == dev->buffer[cc].dwFrames))
dev->cur_frame[cc] = 0;
-
- /* signal the semaphore for this channel */
+ /* frame ready */
if (dev->b_acquire[cc])
- s2255_got_frame(dev, cc);
+ s2255_got_frame(dev, cc, dev->jpg_size[cc]);
dev->frame_count[cc]++;
- }
- /* frame was truncated */
- if (btrunc) {
- /* return more data to process */
- return EAGAIN;
+ frm->ulState = S2255_READ_IDLE;
+ frm->cur_size = 0;
+
}
/* done successfully */
return 0;
@@ -1980,8 +2005,8 @@ static void s2255_read_video_callback(struct s2255_dev *dev,
}
/* otherwise copy to the system buffers */
res = save_frame(dev, pipe_info);
- if (res == EAGAIN)
- save_frame(dev, pipe_info);
+ if (res != 0)
+ dprintk(4, "s2255: read callback failed\n");
dprintk(50, "callback read video done\n");
return;
@@ -2101,11 +2126,9 @@ static int s2255_board_init(struct s2255_dev *dev)
memset(pipe, 0, sizeof(*pipe));
pipe->dev = dev;
- pipe->cur_transfer_size = DEFAULT_PIPE_USBBLOCK;
- pipe->max_transfer_size = MAX_PIPE_USBBLOCK;
+ pipe->cur_transfer_size = S2255_USB_XFER_SIZE;
+ pipe->max_transfer_size = S2255_USB_XFER_SIZE;
- if (pipe->cur_transfer_size > pipe->max_transfer_size)
- pipe->cur_transfer_size = pipe->max_transfer_size;
pipe->transfer_buffer = kzalloc(pipe->max_transfer_size,
GFP_KERNEL);
if (pipe->transfer_buffer == NULL) {
@@ -2329,7 +2352,7 @@ static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn)
kfree(buffer);
dev->b_acquire[chn] = 0;
- return 0;
+ return res;
}
static void s2255_stop_readpipe(struct s2255_dev *dev)
@@ -2365,8 +2388,10 @@ static void s2255_stop_readpipe(struct s2255_dev *dev)
return;
}
-static void s2255_fwload_start(struct s2255_dev *dev)
+static void s2255_fwload_start(struct s2255_dev *dev, int reset)
{
+ if (reset)
+ s2255_reset_dsppower(dev);
dev->fw_data->fw_size = dev->fw_data->fw->size;
atomic_set(&dev->fw_data->fw_state, S2255_FW_NOTLOADED);
memcpy(dev->fw_data->pfw_data,
@@ -2389,6 +2414,8 @@ static int s2255_probe(struct usb_interface *interface,
struct usb_endpoint_descriptor *endpoint;
int i;
int retval = -ENOMEM;
+ __le32 *pdata;
+ int fw_size;
dprintk(2, "s2255: probe\n");
@@ -2443,6 +2470,8 @@ static int s2255_probe(struct usb_interface *interface,
dev->timer.data = (unsigned long)dev->fw_data;
init_waitqueue_head(&dev->fw_data->wait_fw);
+ for (i = 0; i < MAX_CHANNELS; i++)
+ init_waitqueue_head(&dev->wait_setmode[i]);
dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -2462,16 +2491,30 @@ static int s2255_probe(struct usb_interface *interface,
printk(KERN_ERR "sensoray 2255 failed to get firmware\n");
goto error;
}
+ /* check the firmware is valid */
+ fw_size = dev->fw_data->fw->size;
+ pdata = (__le32 *) &dev->fw_data->fw->data[fw_size - 8];
+ if (*pdata != S2255_FW_MARKER) {
+ printk(KERN_INFO "Firmware invalid.\n");
+ retval = -ENODEV;
+ goto error;
+ } else {
+ /* make sure firmware is the latest */
+ __le32 *pRel;
+ pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4];
+ printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel);
+ }
/* loads v4l specific */
s2255_probe_v4l(dev);
+ usb_reset_device(dev->udev);
/* load 2255 board specific */
s2255_board_init(dev);
dprintk(4, "before probe done %p\n", dev);
spin_lock_init(&dev->slock);
- s2255_fwload_start(dev);
+ s2255_fwload_start(dev, 0);
dev_info(&interface->dev, "Sensoray 2255 detected\n");
return 0;
error:
@@ -2482,14 +2525,30 @@ error:
static void s2255_disconnect(struct usb_interface *interface)
{
struct s2255_dev *dev = NULL;
+ int i;
dprintk(1, "s2255: disconnect interface %p\n", interface);
dev = usb_get_intfdata(interface);
+
+ /*
+ * wake up any of the timers to allow open_lock to be
+ * acquired sooner
+ */
+ atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING);
+ wake_up(&dev->fw_data->wait_fw);
+ for (i = 0; i < MAX_CHANNELS; i++) {
+ dev->setmode_ready[i] = 1;
+ wake_up(&dev->wait_setmode[i]);
+ }
+
+ mutex_lock(&dev->open_lock);
+ usb_set_intfdata(interface, NULL);
+ mutex_unlock(&dev->open_lock);
+
if (dev) {
kref_put(&dev->kref, s2255_destroy);
dprintk(1, "s2255drv: disconnect\n");
dev_info(&interface->dev, "s2255usb now disconnected\n");
}
- usb_set_intfdata(interface, NULL);
}
static struct usb_driver s2255_driver = {
diff --git a/linux/drivers/media/video/usbvideo/ibmcam.c b/linux/drivers/media/video/usbvideo/ibmcam.c
index 1afbcc147..697e74a24 100644
--- a/linux/drivers/media/video/usbvideo/ibmcam.c
+++ b/linux/drivers/media/video/usbvideo/ibmcam.c
@@ -736,12 +736,12 @@ static enum ParseState ibmcam_model2_320x240_parse_lines(
* make black color and quit the horizontal scanning loop.
*/
if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) {
- const int j = i * V4L_BYTES_PER_PIXEL;
+ const int offset = i * V4L_BYTES_PER_PIXEL;
#if USES_IBMCAM_PUTPIXEL
/* Refresh 'f' because we don't use it much with PUTPIXEL */
- f = frame->data + (v4l_linesize * frame->curline) + j;
+ f = frame->data + (v4l_linesize * frame->curline) + offset;
#endif
- memset(f, 0, v4l_linesize - j);
+ memset(f, 0, v4l_linesize - offset);
break;
}
diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c
index 7e102034d..4a2d09988 100644
--- a/linux/drivers/media/video/uvc/uvc_driver.c
+++ b/linux/drivers/media/video/uvc/uvc_driver.c
@@ -1663,7 +1663,7 @@ static int uvc_suspend(struct usb_interface *intf, pm_message_t message)
return uvc_video_suspend(&dev->video);
}
-static int uvc_resume(struct usb_interface *intf)
+static int __uvc_resume(struct usb_interface *intf, int reset)
{
struct uvc_device *dev = usb_get_intfdata(intf);
int ret;
@@ -1672,7 +1672,7 @@ static int uvc_resume(struct usb_interface *intf)
intf->cur_altsetting->desc.bInterfaceNumber);
if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) {
- if ((ret = uvc_ctrl_resume_device(dev)) < 0)
+ if (reset && (ret = uvc_ctrl_resume_device(dev)) < 0)
return ret;
return uvc_status_resume(dev);
@@ -1687,6 +1687,16 @@ static int uvc_resume(struct usb_interface *intf)
return uvc_video_resume(&dev->video);
}
+static int uvc_resume(struct usb_interface *intf)
+{
+ return __uvc_resume(intf, 0);
+}
+
+static int uvc_reset_resume(struct usb_interface *intf)
+{
+ return __uvc_resume(intf, 1);
+}
+
/* ------------------------------------------------------------------------
* Driver initialization and cleanup
*/
@@ -1952,6 +1962,7 @@ struct uvc_driver uvc_driver = {
.disconnect = uvc_disconnect,
.suspend = uvc_suspend,
.resume = uvc_resume,
+ .reset_resume = uvc_reset_resume,
.id_table = uvc_ids,
.supports_autosuspend = 1,
},
diff --git a/linux/drivers/media/video/v4l2-dev.c b/linux/drivers/media/video/v4l2-dev.c
index a244c1296..b5a65beca 100644
--- a/linux/drivers/media/video/v4l2-dev.c
+++ b/linux/drivers/media/video/v4l2-dev.c
@@ -271,6 +271,9 @@ int video_register_device_index(struct video_device *vfd, int type, int nr,
/* the release callback MUST be present */
BUG_ON(!vfd->release);
+ if (vfd == NULL)
+ return -EINVAL;
+
switch (type) {
case VFL_TYPE_GRABBER:
base = MINOR_VFL_TYPE_GRABBER_MIN;
diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c
index 2f18381b6..d345aed08 100644
--- a/linux/drivers/media/video/vivi.c
+++ b/linux/drivers/media/video/vivi.c
@@ -1112,19 +1112,29 @@ static struct video_device vivi_template = {
Initialization and module stuff
------------------------------------------------------------------*/
+/* This routine allocates from 1 to n_devs virtual drivers.
+
+ The real maximum number of virtual drivers will depend on how many drivers
+ will succeed. This is limited to the maximum number of devices that
+ videodev supports. Since there are 64 minors for video grabbers, this is
+ currently the theoretical maximum limit. However, a further limit does
+ exist at videodev that forbids any driver to register more than 32 video
+ grabbers.
+ */
static int __init vivi_init(void)
{
int ret = -ENOMEM, i;
struct vivi_dev *dev;
struct video_device *vfd;
+ if (n_devs <= 0)
+ n_devs = 1;
+
for (i = 0; i < n_devs; i++) {
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (NULL == dev)
+ if (!dev)
break;
- list_add_tail(&dev->vivi_devlist, &vivi_devlist);
-
/* init video dma queues */
INIT_LIST_HEAD(&dev->vidq.active);
init_waitqueue_head(&dev->vidq.wq);
@@ -1134,14 +1144,27 @@ static int __init vivi_init(void)
mutex_init(&dev->mutex);
vfd = video_device_alloc();
- if (NULL == vfd)
+ if (!vfd) {
+ kfree(dev);
break;
+ }
*vfd = vivi_template;
ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
- if (ret < 0)
+ if (ret < 0) {
+ video_device_release(vfd);
+ kfree(dev);
+
+ /* If some registers succeeded, keep driver */
+ if (i)
+ ret = 0;
+
break;
+ }
+
+ /* Now that everything is fine, let's add it to device list */
+ list_add_tail(&dev->vivi_devlist, &vivi_devlist);
snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
vivi_template.name, vfd->minor);
@@ -1157,11 +1180,16 @@ static int __init vivi_init(void)
if (ret < 0) {
vivi_release();
printk(KERN_INFO "Error %d while loading vivi driver\n", ret);
- } else
+ } else {
printk(KERN_INFO "Video Technology Magazine Virtual Video "
"Capture Board ver %u.%u.%u successfully loaded.\n",
(VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF,
VIVI_VERSION & 0xFF);
+
+ /* n_devs will reflect the actual number of allocated devices */
+ n_devs = i;
+ }
+
return ret;
}
@@ -1177,10 +1205,10 @@ MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
MODULE_LICENSE("Dual BSD/GPL");
-module_param(video_nr, int, 0);
+module_param(video_nr, uint, 0444);
MODULE_PARM_DESC(video_nr, "video iminor start number");
-module_param(n_devs, int, 0);
+module_param(n_devs, uint, 0444);
MODULE_PARM_DESC(n_devs, "number of video devices to create");
module_param_named(debug, vivi_template.debug, int, 0444);
diff --git a/linux/drivers/media/video/zoran_procfs.c b/linux/drivers/media/video/zoran_procfs.c
index d7bc097da..961950a21 100644
--- a/linux/drivers/media/video/zoran_procfs.c
+++ b/linux/drivers/media/video/zoran_procfs.c
@@ -162,10 +162,11 @@ static ssize_t zoran_write(struct file *file, const char __user *buffer,
return -EFAULT;
}
string[count] = 0;
- dprintk(4, KERN_INFO "%s: write_proc: name=%s count=%zu zr=%p\n",
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ dprintk(4, KERN_INFO "%s: write_proc: name=%s count=%zu zr=%p\n",
ZR_DEVNAME(zr), file->f_dentry->d_name.name, count, zr);
#else
+ dprintk(4, KERN_INFO "%s: write_proc: name=%s count=%zu zr=%p\n",
ZR_DEVNAME(zr), file->f_path.dentry->d_name.name, count, zr);
#endif
ldelim = " \t\n";
diff --git a/mailimport b/mailimport
index bd6d36c2e..8ed624179 100755
--- a/mailimport
+++ b/mailimport
@@ -165,6 +165,12 @@ proccess_patch ()
{
i="$_"
+ CHECK="`cat $i| perl -ne 'if (m/^Subject:.*FOLDER INTERNAL DATA/) { print -1; }'`"
+
+ if [ "$CHECK" != "" ]; then
+ return
+ fi
+
echo $i
if [ "`diffstat -p1 -l "$i"`" == "" ]; then
echo "*** ERROR nothing to commit"
diff --git a/v4l/Makefile b/v4l/Makefile
index 04e74e8e5..2aa856974 100644
--- a/v4l/Makefile
+++ b/v4l/Makefile
@@ -117,7 +117,7 @@ EXTRA_CFLAGS += $(if $(wildcard $(srctree)/.mm), -DMM_KERNEL)
EXTRA_CFLAGS += -include $(obj)/config-compat.h
# Allow kernel version compat tests without adding #include's
-EXTRA_CFLAGS += -include linux/version.h
+EXTRA_CFLAGS += -include include/linux/version.h
#################################################
# Kernel 2.4/2.6 specific rules
diff --git a/v4l/firmware/Makefile b/v4l/firmware/Makefile
index e018ad92a..a1717922d 100644
--- a/v4l/firmware/Makefile
+++ b/v4l/firmware/Makefile
@@ -7,13 +7,13 @@ TARGETS = ihex2fw vicam/firmware.fw dabusb/firmware.fw dabusb/bitstream.bin ttus
default: $(TARGETS)
clean:
- -rm $(TARGETS)
+ @for i in $(TARGETS); do if [ -e $$i ]; then rm $$i; fi; done
distclean: clean
- -rmdir $(DIRS)
+ @for i in $(DIR); do if [ -d $$i ]; then rmdir $$i; fi; done
install: default
- -for i in $(DIRS); do mkdir /lib/firmware/$$i; done
+ -for i in $(DIRS); do if mkdir /lib/firmware/$$i; done
-for i in $(TARGETS); do cp $$i /lib/firmware/$$i; done
diff --git a/v4l2-apps/lib/libv4l/ChangeLog b/v4l2-apps/lib/libv4l/ChangeLog
index 3d4e40ad2..eefe0028b 100644
--- a/v4l2-apps/lib/libv4l/ChangeLog
+++ b/v4l2-apps/lib/libv4l/ChangeLog
@@ -1,8 +1,20 @@
+libv4l-0.4.2
+------------
+* The bayer pixel order in gspca's sonixb driver was different from that in
+ the sn9c102 driver from the mainline kernel, a recent gspca patch fixes
+ this, adjust libv4l to match (and make it work properly with the sn9c102
+ driver).
+
libv4l-0.4.1
------------
* When the driver supports read() and we are not converting let the driver
handle read() instead of emulating it with mmap mode
-
+* Fix errors and warnings when compiling with ICC (Gregor Jasny)
+* Add support to libv4lconvert for rotating images 90 (for Pixart 7302 cams)
+ or 180 (Philips SPC200NC / Philips SPC300NC) degrees
+* Add support for Pixart custom JPEG format
+* Hide non public symbols (Gregor Jasny)
+* Fix and enable x86_64 asm jpeg decompress helper functions (Gregor Jasny)
libv4l-0.4.0
------------
diff --git a/v4l2-apps/lib/libv4l/Makefile b/v4l2-apps/lib/libv4l/Makefile
index 31254a09e..92928271a 100644
--- a/v4l2-apps/lib/libv4l/Makefile
+++ b/v4l2-apps/lib/libv4l/Makefile
@@ -1,5 +1,5 @@
LIB_RELEASE=0
-V4L2_LIB_VERSION=$(LIB_RELEASE).4.1
+V4L2_LIB_VERSION=$(LIB_RELEASE).4.2
all clean install:
$(MAKE) -C libv4lconvert V4L2_LIB_VERSION=$(V4L2_LIB_VERSION) $@
diff --git a/v4l2-apps/lib/libv4l/include/libv4l1.h b/v4l2-apps/lib/libv4l/include/libv4l1.h
index 9036ae869..c878cc198 100644
--- a/v4l2-apps/lib/libv4l/include/libv4l1.h
+++ b/v4l2-apps/lib/libv4l/include/libv4l1.h
@@ -26,9 +26,15 @@ extern "C" {
#include <stdio.h>
#include <unistd.h>
+#if __GNUC__ >= 4
+#define LIBV4L_PUBLIC __attribute__ ((visibility("default")))
+#else
+#define LIBV4L_PUBLIC
+#endif
+
/* Point this to a FILE opened for writing when you want to log error and
status messages to a file, when NULL errors will get send to stderr */
-extern FILE *v4l1_log_file;
+LIBV4L_PUBLIC extern FILE *v4l1_log_file;
/* Just like your regular open/close/etc, except that when opening a v4l2
capture only device, full v4l1 emulation is done including emulating the
@@ -51,14 +57,14 @@ extern FILE *v4l1_log_file;
capture formats, like hw specific bayer compression methods).
*/
-int v4l1_open (const char *file, int oflag, ...);
-int v4l1_close(int fd);
-int v4l1_dup(int fd);
-int v4l1_ioctl (int fd, unsigned long int request, ...);
-ssize_t v4l1_read (int fd, void* buffer, size_t n);
-void *v4l1_mmap(void *start, size_t length, int prot, int flags, int fd,
+LIBV4L_PUBLIC int v4l1_open (const char *file, int oflag, ...);
+LIBV4L_PUBLIC int v4l1_close(int fd);
+LIBV4L_PUBLIC int v4l1_dup(int fd);
+LIBV4L_PUBLIC int v4l1_ioctl (int fd, unsigned long int request, ...);
+LIBV4L_PUBLIC ssize_t v4l1_read (int fd, void* buffer, size_t n);
+LIBV4L_PUBLIC void *v4l1_mmap(void *start, size_t length, int prot, int flags, int fd,
__off64_t offset);
-int v4l1_munmap(void *_start, size_t length);
+LIBV4L_PUBLIC int v4l1_munmap(void *_start, size_t length);
#ifdef __cplusplus
}
diff --git a/v4l2-apps/lib/libv4l/include/libv4l2.h b/v4l2-apps/lib/libv4l/include/libv4l2.h
index 63529cf4b..b05b57cb6 100644
--- a/v4l2-apps/lib/libv4l/include/libv4l2.h
+++ b/v4l2-apps/lib/libv4l/include/libv4l2.h
@@ -26,9 +26,15 @@
extern "C" {
#endif /* __cplusplus */
+#if __GNUC__ >= 4
+#define LIBV4L_PUBLIC __attribute__ ((visibility("default")))
+#else
+#define LIBV4L_PUBLIC
+#endif
+
/* Point this to a FILE opened for writing when you want to log error and
status messages to a file, when NULL errors will get send to stderr */
-extern FILE *v4l2_log_file;
+LIBV4L_PUBLIC extern FILE *v4l2_log_file;
/* Just like your regular open/close/etc, except that format conversion is
done if necessary when capturing. That is if you (try to) set a capture
@@ -52,14 +58,14 @@ extern FILE *v4l2_log_file;
fail.
*/
-int v4l2_open (const char *file, int oflag, ...);
-int v4l2_close(int fd);
-int v4l2_dup(int fd);
-int v4l2_ioctl (int fd, unsigned long int request, ...);
-ssize_t v4l2_read (int fd, void* buffer, size_t n);
-void *v4l2_mmap(void *start, size_t length, int prot, int flags, int fd,
+LIBV4L_PUBLIC int v4l2_open (const char *file, int oflag, ...);
+LIBV4L_PUBLIC int v4l2_close(int fd);
+LIBV4L_PUBLIC int v4l2_dup(int fd);
+LIBV4L_PUBLIC int v4l2_ioctl (int fd, unsigned long int request, ...);
+LIBV4L_PUBLIC ssize_t v4l2_read (int fd, void* buffer, size_t n);
+LIBV4L_PUBLIC void *v4l2_mmap(void *start, size_t length, int prot, int flags, int fd,
__off64_t offset);
-int v4l2_munmap(void *_start, size_t length);
+LIBV4L_PUBLIC int v4l2_munmap(void *_start, size_t length);
/* Misc utility functions */
@@ -70,12 +76,12 @@ int v4l2_munmap(void *_start, size_t length);
Normally returns 0, even if the cid did not exist or was locked, returns
non 0 when an other error occured. */
-int v4l2_set_control(int fd, int cid, int value);
+LIBV4L_PUBLIC int v4l2_set_control(int fd, int cid, int value);
/* This function returns a value of 0 - 65535, scaled to from the actual range
of the given v4l control id. when the cid does not exist, could not be
accessed for some reason, or some error occured 0 is returned. */
-int v4l2_get_control(int fd, int cid);
+LIBV4L_PUBLIC int v4l2_get_control(int fd, int cid);
/* "low level" access functions, these functions allow somewhat lower level
@@ -95,7 +101,7 @@ int v4l2_get_control(int fd, int cid);
Returns fd on success, -1 if the fd is not suitable for use through libv4l2
(note the fd is left open in this case). */
-int v4l2_fd_open(int fd, int v4l2_flags);
+LIBV4L_PUBLIC int v4l2_fd_open(int fd, int v4l2_flags);
#ifdef __cplusplus
}
diff --git a/v4l2-apps/lib/libv4l/include/libv4lconvert.h b/v4l2-apps/lib/libv4l/include/libv4lconvert.h
index d8446dac8..87e41ceaa 100644
--- a/v4l2-apps/lib/libv4l/include/libv4lconvert.h
+++ b/v4l2-apps/lib/libv4l/include/libv4lconvert.h
@@ -31,34 +31,45 @@
extern "C" {
#endif /* __cplusplus */
+#if __GNUC__ >= 4
+#define LIBV4L_PUBLIC __attribute__ ((visibility("default")))
+#else
+#define LIBV4L_PUBLIC
+#endif
+
struct v4lconvert_data;
-struct v4lconvert_data *v4lconvert_create(int fd);
-void v4lconvert_destroy(struct v4lconvert_data *data);
+LIBV4L_PUBLIC struct v4lconvert_data *v4lconvert_create(int fd);
+LIBV4L_PUBLIC void v4lconvert_destroy(struct v4lconvert_data *data);
/* With regards to dest_fmt just like VIDIOC_TRY_FMT, except that the try
format will succeed and return the requested V4L2_PIX_FMT_foo in dest_fmt if
the cam has a format from which v4lconvert can convert to dest_fmt.
The real format to which the cam should be set is returned through src_fmt
when not NULL. */
-int v4lconvert_try_format(struct v4lconvert_data *data,
+LIBV4L_PUBLIC int v4lconvert_try_format(struct v4lconvert_data *data,
struct v4l2_format *dest_fmt, /* in / out */
struct v4l2_format *src_fmt /* out */
);
/* Just like VIDIOC_ENUM_FMT, except that the emulated formats are added at
the end of the list */
-int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *fmt);
+LIBV4L_PUBLIC int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *fmt);
+
+/* Is conversion necessary or can the app use the data directly? */
+LIBV4L_PUBLIC int v4lconvert_needs_conversion(struct v4lconvert_data *data,
+ const struct v4l2_format *src_fmt, /* in */
+ const struct v4l2_format *dest_fmt); /* in */
/* return value of -1 on error, otherwise the amount of bytes written to
dest */
-int v4lconvert_convert(struct v4lconvert_data *data,
+LIBV4L_PUBLIC int v4lconvert_convert(struct v4lconvert_data *data,
const struct v4l2_format *src_fmt, /* in */
const struct v4l2_format *dest_fmt, /* in */
unsigned char *src, int src_size, unsigned char *dest, int dest_size);
/* get a string describing the last error*/
-const char *v4lconvert_get_error_message(struct v4lconvert_data *data);
+LIBV4L_PUBLIC const char *v4lconvert_get_error_message(struct v4lconvert_data *data);
#ifdef __cplusplus
}
diff --git a/v4l2-apps/lib/libv4l/libv4l1/Makefile b/v4l2-apps/lib/libv4l/libv4l1/Makefile
index c92731daa..d12e747fb 100644
--- a/v4l2-apps/lib/libv4l/libv4l1/Makefile
+++ b/v4l2-apps/lib/libv4l/libv4l1/Makefile
@@ -1,7 +1,7 @@
-CPPFLAGS = -I../include -I../../../../linux/include
+override CPPFLAGS += -I../include -I../../../../linux/include -fvisibility=hidden
CFLAGS := -g -O1
-CFLAGS += -Wall -W -Wno-unused -Wpointer-arith -Wstrict-prototypes
+CFLAGS += -Wall -Wno-unused -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes
LIBS = -lpthread
@@ -17,7 +17,7 @@ else
V4L1_LIB = libv4l1.so
V4L1_OBJS += ../libv4l2/libv4l2.so
TARGETS += $(V4L1COMPAT)
-CPPFLAGS += -fPIC
+override CPPFLAGS += -fPIC
endif
ifeq ($(LIB_RELEASE),)
diff --git a/v4l2-apps/lib/libv4l/libv4l1/libv4l1.c b/v4l2-apps/lib/libv4l/libv4l1/libv4l1.c
index 80d2fa09b..39f2d29e0 100644
--- a/v4l2-apps/lib/libv4l/libv4l1/libv4l1.c
+++ b/v4l2-apps/lib/libv4l/libv4l1/libv4l1.c
@@ -59,6 +59,7 @@
#include <linux/videodev.h>
#include <linux/videodev2.h>
#include <libv4l2.h>
+#include "libv4l1.h"
#include "libv4l1-priv.h"
#define V4L1_SUPPORTS_ENUMINPUT 0x01
@@ -582,7 +583,7 @@ int v4l1_ioctl (int fd, unsigned long int request, ...)
input2.index = chan->channel;
result = v4l2_ioctl(fd, VIDIOC_ENUMINPUT, &input2);
if (result == 0) {
- snprintf(chan->name, sizeof(chan->name), "%s", input2.name);
+ snprintf(chan->name, sizeof(chan->name), "%s", (char*)input2.name);
if (input2.type == V4L2_INPUT_TYPE_TUNER) {
chan->tuners = 1;
chan->type = VIDEO_TYPE_TV;
diff --git a/v4l2-apps/lib/libv4l/libv4l1/log.c b/v4l2-apps/lib/libv4l/libv4l1/log.c
index cccc3e6d0..74ce0f20b 100644
--- a/v4l2-apps/lib/libv4l/libv4l1/log.c
+++ b/v4l2-apps/lib/libv4l/libv4l1/log.c
@@ -25,6 +25,7 @@
#include <asm/types.h>
/* end broken header workaround includes */
#include <linux/videodev.h>
+#include "libv4l1-priv.h"
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
@@ -92,9 +93,9 @@ void v4l1_log_ioctl(unsigned long int request, void *arg, int result)
break;
case VIDIOCGWIN:
case VIDIOCSWIN:
- fprintf(v4l1_log_file,"width\t%d\n",
+ fprintf(v4l1_log_file,"width\t%u\n",
((struct video_window *)arg)->width);
- fprintf(v4l1_log_file,"height\t%d\n",
+ fprintf(v4l1_log_file,"height\t%u\n",
((struct video_window *)arg)->height);
break;
@@ -115,7 +116,7 @@ void v4l1_log_ioctl(unsigned long int request, void *arg, int result)
fprintf(v4l1_log_file,"palette %d\n",( (int)((struct video_picture*)arg)->palette) );
break;
- case VIDIOCCAPTURE: fprintf(v4l1_log_file,"on/of? %d\n", *((int *)arg) );
+ case VIDIOCCAPTURE: fprintf(v4l1_log_file,"on/off? %d\n", *((int *)arg) );
break;
case VIDIOCSYNC: fprintf(v4l1_log_file,"sync %d\n", *((int *)arg) );
diff --git a/v4l2-apps/lib/libv4l/libv4l1/v4l1compat.c b/v4l2-apps/lib/libv4l/libv4l1/v4l1compat.c
index f1134fe3b..e4293d2f9 100644
--- a/v4l2-apps/lib/libv4l/libv4l1/v4l1compat.c
+++ b/v4l2-apps/lib/libv4l/libv4l1/v4l1compat.c
@@ -26,12 +26,21 @@
#include <fcntl.h>
#include <libv4l1.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
/* Check that open/read/mmap is not a define */
#if defined open || defined read || defined mmap
#error open/read/mmap is a prepocessor macro !!
#endif
-int open (const char *file, int oflag, ...)
+#if __GNUC__ >= 4
+#define LIBV4L_PUBLIC __attribute__ ((visibility("default")))
+#else
+#define LIBV4L_PUBLIC
+#endif
+
+LIBV4L_PUBLIC int open (const char *file, int oflag, ...)
{
int fd;
@@ -52,7 +61,7 @@ int open (const char *file, int oflag, ...)
return fd;
}
-int open64 (const char *file, int oflag, ...)
+LIBV4L_PUBLIC int open64 (const char *file, int oflag, ...)
{
int fd;
@@ -73,16 +82,16 @@ int open64 (const char *file, int oflag, ...)
return fd;
}
-int close(int fd) {
+LIBV4L_PUBLIC int close(int fd) {
return v4l1_close(fd);
}
-int dup(int fd)
+LIBV4L_PUBLIC int dup(int fd)
{
return v4l1_dup(fd);
}
-int ioctl (int fd, unsigned long int request, ...)
+LIBV4L_PUBLIC int ioctl (int fd, unsigned long int request, ...)
{
void *arg;
va_list ap;
@@ -94,24 +103,25 @@ int ioctl (int fd, unsigned long int request, ...)
return v4l1_ioctl (fd, request, arg);
}
-ssize_t read(int fd, void* buffer, size_t n)
+LIBV4L_PUBLIC ssize_t read(int fd, void* buffer, size_t n)
{
return v4l1_read (fd, buffer, n);
}
-void *mmap(void *start, size_t length, int prot, int flags, int fd,
+LIBV4L_PUBLIC void *mmap(void *start, size_t length, int prot, int flags, int fd,
__off_t offset)
{
return v4l1_mmap(start, length, prot, flags, fd, offset);
}
-void *mmap64(void *start, size_t length, int prot, int flags, int fd,
+LIBV4L_PUBLIC void *mmap64(void *start, size_t length, int prot, int flags, int fd,
__off64_t offset)
{
return v4l1_mmap(start, length, prot, flags, fd, offset);
}
-int munmap(void *start, size_t length)
+LIBV4L_PUBLIC int munmap(void *start, size_t length)
{
return v4l1_munmap(start, length);
}
+
diff --git a/v4l2-apps/lib/libv4l/libv4l2/Makefile b/v4l2-apps/lib/libv4l/libv4l2/Makefile
index d8ac01c34..5ed35934a 100644
--- a/v4l2-apps/lib/libv4l/libv4l2/Makefile
+++ b/v4l2-apps/lib/libv4l/libv4l2/Makefile
@@ -1,7 +1,7 @@
-CPPFLAGS = -I../include -I../../../../linux/include
+override CPPFLAGS += -I../include -I../../../../linux/include -fvisibility=hidden
CFLAGS := -g -O1
-CFLAGS += -Wall -W -Wno-unused -Wpointer-arith -Wstrict-prototypes
+CFLAGS += -Wall -Wno-unused -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes
LIBS = -lpthread
@@ -17,7 +17,7 @@ else
V4L2_LIB = libv4l2.so
V4L2_OBJS += ../libv4lconvert/libv4lconvert.so
TARGETS += $(V4L2CONVERT)
-CPPFLAGS += -fPIC
+override CPPFLAGS += -fPIC
endif
ifeq ($(LIB_RELEASE),)
diff --git a/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c b/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c
index a40ab4ffe..7029f69c3 100644
--- a/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c
+++ b/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c
@@ -252,23 +252,54 @@ static int v4l2_queue_read_buffer(int index, int buffer_index)
return 0;
}
-static int v4l2_dequeue_read_buffer(int index, int *bytesused)
+static int v4l2_dequeue_and_convert(int index, struct v4l2_buffer *buf,
+ unsigned char *dest, int dest_size)
{
- int result;
- struct v4l2_buffer buf;
+ const int max_tries = 10;
+ int result, tries = max_tries;
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- if ((result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_DQBUF, &buf))) {
- int saved_err = errno;
- V4L2_LOG_ERR("dequeuing buf: %s\n", strerror(errno));
- errno = saved_err;
+ /* Make sure we have the real v4l2 buffers mapped */
+ if ((result = v4l2_map_buffers(index)))
return result;
+
+ do {
+ if ((result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_DQBUF, buf))) {
+ int saved_err = errno;
+ V4L2_LOG_ERR("dequeuing buf: %s\n", strerror(errno));
+ errno = saved_err;
+ return result;
+ }
+
+ devices[index].frame_queued &= ~(1 << buf->index);
+
+ result = v4lconvert_convert(devices[index].convert,
+ &devices[index].src_fmt, &devices[index].dest_fmt,
+ devices[index].frame_pointers[buf->index],
+ buf->bytesused, dest ? dest : (devices[index].convert_mmap_buf +
+ buf->index * V4L2_FRAME_BUF_SIZE), dest_size);
+
+ if (result < 0) {
+ int saved_err = errno;
+
+ if(errno == EAGAIN)
+ V4L2_LOG("warning error while converting frame data: %s\n",
+ v4lconvert_get_error_message(devices[index].convert));
+ else
+ V4L2_LOG_ERR("converting / decoding frame data: %s\n",
+ v4lconvert_get_error_message(devices[index].convert));
+
+ v4l2_queue_read_buffer(index, buf->index);
+ errno = saved_err;
+ }
+ tries--;
+ } while (result < 0 && errno == EAGAIN && tries);
+
+ if (result < 0 && errno == EAGAIN) {
+ V4L2_LOG_ERR("got %d consecutive frame decode errors, last error: %s\n",
+ max_tries, v4lconvert_get_error_message(devices[index].convert));
}
- devices[index].frame_queued &= ~(1 << buf.index);
- *bytesused = buf.bytesused;
- return buf.index;
+ return result;
}
static int v4l2_queue_read_buffers(int index)
@@ -614,7 +645,8 @@ int v4l2_ioctl (int fd, unsigned long int request, ...)
is_capture_request = 1;
break;
case VIDIOC_ENUM_FMT:
- if (((struct v4l2_fmtdesc *)arg)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ if (((struct v4l2_fmtdesc *)arg)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ (devices[index].flags & V4L2_ENABLE_ENUM_FMT_EMULATION))
is_capture_request = 1;
break;
case VIDIOC_TRY_FMT:
@@ -663,9 +695,8 @@ int v4l2_ioctl (int fd, unsigned long int request, ...)
if (stream_needs_locking)
pthread_mutex_lock(&devices[index].stream_lock);
- converting = devices[index].src_fmt.fmt.pix.pixelformat !=
- devices[index].dest_fmt.fmt.pix.pixelformat;
-
+ converting = v4lconvert_needs_conversion(devices[index].convert,
+ &devices[index].src_fmt, &devices[index].dest_fmt);
switch (request) {
case VIDIOC_QUERYCAP:
@@ -815,15 +846,16 @@ int v4l2_ioctl (int fd, unsigned long int request, ...)
if ((result = v4l2_deactivate_read_stream(index)))
break;
- result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_DQBUF, buf);
- if (result) {
- V4L2_LOG_ERR("dequeing buffer: %s\n", strerror(errno));
+ if (!converting) {
+ result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_DQBUF, buf);
+ if (result) {
+ int saved_err = errno;
+ V4L2_LOG_ERR("dequeuing buf: %s\n", strerror(errno));
+ errno = saved_err;
+ }
break;
}
- if (!converting)
- break;
-
/* An application can do a DQBUF before mmap-ing in the buffer,
but we need the buffer _now_ to write our converted data
to it! */
@@ -844,23 +876,9 @@ int v4l2_ioctl (int fd, unsigned long int request, ...)
}
}
- /* Make sure we have the real v4l2 buffers mapped before trying to
- read from them */
- if ((result = v4l2_map_buffers(index)))
- break;
-
- result = v4lconvert_convert(devices[index].convert,
- &devices[index].src_fmt, &devices[index].dest_fmt,
- devices[index].frame_pointers[buf->index],
- buf->bytesused,
- devices[index].convert_mmap_buf +
- buf->index * V4L2_FRAME_BUF_SIZE,
- V4L2_FRAME_BUF_SIZE);
- if (result < 0) {
- V4L2_LOG_ERR("converting / decoding frame data: %s\n",
- v4lconvert_get_error_message(devices[index].convert));
+ result = v4l2_dequeue_and_convert(index, buf, 0, V4L2_FRAME_BUF_SIZE);
+ if (result < 0)
break;
- }
buf->bytesused = result;
buf->m.offset = V4L2_MMAP_OFFSET_MAGIC | buf->index;
@@ -901,22 +919,23 @@ int v4l2_ioctl (int fd, unsigned long int request, ...)
}
-ssize_t v4l2_read (int fd, void* buffer, size_t n)
+ssize_t v4l2_read (int fd, void* dest, size_t n)
{
ssize_t result;
- int index, bytesused = 0, frame_index;
+ int index;
+ struct v4l2_buffer buf;
if ((index = v4l2_get_index(fd)) == -1)
- return syscall(SYS_read, fd, buffer, n);
+ return syscall(SYS_read, fd, dest, n);
pthread_mutex_lock(&devices[index].stream_lock);
/* When not converting and the device supports read let the kernel handle
it */
if ((devices[index].flags & V4L2_SUPPORTS_READ) &&
- devices[index].src_fmt.fmt.pix.pixelformat ==
- devices[index].dest_fmt.fmt.pix.pixelformat) {
- result = syscall(SYS_read, fd, buffer, n);
+ !v4lconvert_needs_conversion(devices[index].convert,
+ &devices[index].src_fmt, &devices[index].dest_fmt)) {
+ result = syscall(SYS_read, fd, dest, n);
goto leave;
}
@@ -931,26 +950,12 @@ ssize_t v4l2_read (int fd, void* buffer, size_t n)
goto leave;
}
- if ((frame_index = v4l2_dequeue_read_buffer(index, &bytesused)) < 0) {
- result = -1;
- goto leave;
- }
-
- /* ensure buffers are mapped before using them (they could have been
- unmapped by a s_fmt ioctl) */
- if ((result = v4l2_map_buffers(index)))
- goto leave;
-
- result = v4lconvert_convert(devices[index].convert,
- &devices[index].src_fmt, &devices[index].dest_fmt,
- devices[index].frame_pointers[frame_index], bytesused,
- buffer, n);
-
- v4l2_queue_read_buffer(index, frame_index);
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ result = v4l2_dequeue_and_convert(index, &buf, dest, n);
- if (result < 0)
- V4L2_LOG_ERR("converting / decoding frame data: %s\n",
- v4lconvert_get_error_message(devices[index].convert));
+ if (result >= 0)
+ v4l2_queue_read_buffer(index, buf.index);
leave:
pthread_mutex_unlock(&devices[index].stream_lock);
@@ -988,8 +993,8 @@ void *v4l2_mmap(void *start, size_t length, int prot, int flags, int fd,
buffer_index = offset & 0xff;
if (buffer_index >= devices[index].no_frames ||
/* Got magic offset and not converting ?? */
- devices[index].src_fmt.fmt.pix.pixelformat ==
- devices[index].dest_fmt.fmt.pix.pixelformat) {
+ !v4lconvert_needs_conversion(devices[index].convert,
+ &devices[index].src_fmt, &devices[index].dest_fmt)) {
errno = EINVAL;
result = MAP_FAILED;
goto leave;
diff --git a/v4l2-apps/lib/libv4l/libv4l2/log.c b/v4l2-apps/lib/libv4l/libv4l2/log.c
index 05f6c46d7..6237d55ec 100644
--- a/v4l2-apps/lib/libv4l/libv4l2/log.c
+++ b/v4l2-apps/lib/libv4l/libv4l2/log.c
@@ -25,6 +25,8 @@
#include <asm/types.h>
/* end broken header workaround includes */
#include <linux/videodev2.h>
+#include "libv4l2.h"
+#include "libv4l2-priv.h"
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
@@ -116,7 +118,7 @@ void v4l2_log_ioctl(unsigned long int request, void *arg, int result)
int pixfmt = fmt->fmt.pix.pixelformat;
if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- fprintf(v4l2_log_file, " pixelformat: %c%c%c%c %dx%d\n",
+ fprintf(v4l2_log_file, " pixelformat: %c%c%c%c %ux%u\n",
pixfmt & 0xff,
(pixfmt >> 8) & 0xff,
(pixfmt >> 16) & 0xff,
@@ -136,7 +138,7 @@ void v4l2_log_ioctl(unsigned long int request, void *arg, int result)
struct v4l2_requestbuffers *req = arg;
fprintf(v4l2_log_file, " count: %u type: %d memory: %d\n",
- req->count, req->type, req->memory);
+ req->count, (int)req->type, (int)req->memory);
}
break;
}
diff --git a/v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c b/v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c
index f312828c6..e8756f338 100644
--- a/v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c
+++ b/v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c
@@ -27,6 +27,8 @@
#include <syscall.h>
#include <fcntl.h>
#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
/* These headers are not needed by us, but by linux/videodev2.h,
which is broken on some systems and doesn't include them itself :( */
#include <sys/time.h>
@@ -41,7 +43,13 @@
#error open/read/mmap is a prepocessor macro !!
#endif
-int open (const char *file, int oflag, ...)
+#if __GNUC__ >= 4
+#define LIBV4L_PUBLIC __attribute__ ((visibility("default")))
+#else
+#define LIBV4L_PUBLIC
+#endif
+
+LIBV4L_PUBLIC int open (const char *file, int oflag, ...)
{
int fd;
struct v4l2_capability cap;
@@ -84,7 +92,7 @@ int open (const char *file, int oflag, ...)
return fd;
}
-int open64(const char *file, int oflag, ...)
+LIBV4L_PUBLIC int open64(const char *file, int oflag, ...)
{
int fd;
@@ -107,17 +115,17 @@ int open64(const char *file, int oflag, ...)
return fd;
}
-int close(int fd)
+LIBV4L_PUBLIC int close(int fd)
{
return v4l2_close(fd);
}
-int dup(int fd)
+LIBV4L_PUBLIC int dup(int fd)
{
return v4l2_dup(fd);
}
-int ioctl (int fd, unsigned long int request, ...)
+LIBV4L_PUBLIC int ioctl (int fd, unsigned long int request, ...)
{
void *arg;
va_list ap;
@@ -129,24 +137,25 @@ int ioctl (int fd, unsigned long int request, ...)
return v4l2_ioctl (fd, request, arg);
}
-ssize_t read (int fd, void* buffer, size_t n)
+LIBV4L_PUBLIC ssize_t read (int fd, void* buffer, size_t n)
{
return v4l2_read (fd, buffer, n);
}
-void *mmap(void *start, size_t length, int prot, int flags, int fd,
+LIBV4L_PUBLIC void *mmap(void *start, size_t length, int prot, int flags, int fd,
__off_t offset)
{
return v4l2_mmap(start, length, prot, flags, fd, offset);
}
-void *mmap64(void *start, size_t length, int prot, int flags, int fd,
+LIBV4L_PUBLIC void *mmap64(void *start, size_t length, int prot, int flags, int fd,
__off64_t offset)
{
return v4l2_mmap(start, length, prot, flags, fd, offset);
}
-int munmap(void *start, size_t length)
+LIBV4L_PUBLIC int munmap(void *start, size_t length)
{
return v4l2_munmap(start, length);
}
+
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/Makefile b/v4l2-apps/lib/libv4l/libv4lconvert/Makefile
index c2a5be942..798194434 100644
--- a/v4l2-apps/lib/libv4l/libv4lconvert/Makefile
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/Makefile
@@ -1,16 +1,16 @@
-CPPFLAGS = -I../include -I../../../../linux/include
+override CPPFLAGS += -I../include -I../../../../linux/include -fvisibility=hidden
CFLAGS := -g -O1
-CFLAGS += -Wall -W -Wno-unused -Wpointer-arith -Wstrict-prototypes
+CFLAGS += -Wall -Wno-unused -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes
ifeq ($(LINKTYPE),static)
CONVERT_LIB = libv4lconvert.a
else
CONVERT_LIB = libv4lconvert.so
-CPPFLAGS += -fPIC
+override CPPFLAGS += -fPIC
endif
-CONVERT_OBJS = libv4lconvert.o tinyjpeg.o sn9c10x.o pac207.o \
+CONVERT_OBJS = libv4lconvert.o tinyjpeg.o sn9c10x.o pac207.o flip.o \
jidctflt.o spca561-decompress.o rgbyuv.o spca501.o bayer.o
TARGETS = $(CONVERT_LIB) libv4lconvert.pc
INCLUDES = ../include/libv4lconvert.h
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/flip.c b/v4l2-apps/lib/libv4l/libv4lconvert/flip.c
new file mode 100644
index 000000000..cd3468a89
--- /dev/null
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/flip.c
@@ -0,0 +1,107 @@
+/*
+
+# RGB / YUV flip/rotate routines
+
+# (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl>
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser 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 "libv4lconvert-priv.h"
+
+void v4lconvert_rotate180_rgbbgr24(const unsigned char *src, unsigned char *dst,
+ int width, int height)
+{
+ int i;
+
+ src += 3 * width * height - 3;
+
+ for (i = 0; i < width * height; i++) {
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst += 3;
+ src -= 3;
+ }
+}
+
+void v4lconvert_rotate180_yuv420(const unsigned char *src, unsigned char *dst,
+ int width, int height)
+{
+ int i;
+
+ /* First flip x and y of the Y plane */
+ src += width * height - 1;
+ for (i = 0; i < width * height; i++)
+ *dst++ = *src--;
+
+ /* Now flip the U plane */
+ src += width * height * 5 / 4;
+ for (i = 0; i < width * height / 4; i++)
+ *dst++ = *src--;
+
+ /* Last flip the V plane */
+ src += width * height / 2;
+ for (i = 0; i < width * height / 4; i++)
+ *dst++ = *src--;
+}
+
+void v4lconvert_rotate90_rgbbgr24(const unsigned char *src, unsigned char *dst,
+ int destwidth, int destheight)
+{
+ int x, y;
+#define srcwidth destheight
+#define srcheight destwidth
+
+ for (y = 0; y < destheight; y++)
+ for (x = 0; x < destwidth; x++) {
+ int offset = ((srcheight - x - 1) * srcwidth + y) * 3;
+ *dst++ = src[offset++];
+ *dst++ = src[offset++];
+ *dst++ = src[offset];
+ }
+}
+
+void v4lconvert_rotate90_yuv420(const unsigned char *src, unsigned char *dst,
+ int destwidth, int destheight)
+{
+ int x, y;
+
+ /* Y-plane */
+ for (y = 0; y < destheight; y++)
+ for (x = 0; x < destwidth; x++) {
+ int offset = (srcheight - x - 1) * srcwidth + y;
+ *dst++ = src[offset];
+ }
+
+ /* U-plane */
+ src += srcwidth * srcheight;
+ destwidth /= 2;
+ destheight /= 2;
+ for (y = 0; y < destheight; y++)
+ for (x = 0; x < destwidth; x++) {
+ int offset = (srcheight - x - 1) * srcwidth + y;
+ *dst++ = src[offset];
+ }
+
+ /* V-plane */
+ src += srcwidth * srcheight;
+ for (y = 0; y < destheight; y++)
+ for (x = 0; x < destwidth; x++) {
+ int offset = (srcheight - x - 1) * srcwidth + y;
+ *dst++ = src[offset];
+ }
+}
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/jidctflt.c b/v4l2-apps/lib/libv4l/libv4lconvert/jidctflt.c
index ba70309c9..532abc7ea 100644
--- a/v4l2-apps/lib/libv4l/libv4lconvert/jidctflt.c
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/jidctflt.c
@@ -80,7 +80,7 @@
#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval))
-#if defined(__GNUC__) && (defined(__i686__)) // || defined(__x86_64__))
+#if defined(__GNUC__) && (defined(__i686__) || defined(__x86_64__))
static inline unsigned char descale_and_clamp(int x, int shift)
{
@@ -92,7 +92,7 @@ static inline unsigned char descale_and_clamp(int x, int shift)
"\tcmpl %4,%1\n"
"\tcmovg %4,%1\n"
: "=r"(x)
- : "0"(x), "Ic"((unsigned char)shift), "ir"(1UL<<(shift-1)), "r" (0xff), "r" (0)
+ : "0"(x), "Ic"((unsigned char)shift), "ir"(1U<<(shift-1)), "r" (0xff), "r" (0)
);
return x;
}
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h
index bdf847186..915c33283 100644
--- a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h
@@ -43,6 +43,10 @@
#define V4L2_PIX_FMT_PAC207 v4l2_fourcc('P','2','0','7')
#endif
+#ifndef V4L2_PIX_FMT_PJPG
+#define V4L2_PIX_FMT_PJPG v4l2_fourcc('P', 'J', 'P', 'G')
+#endif
+
#ifndef V4L2_PIX_FMT_SGBRG8
#define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G','B','R','G')
#endif
@@ -61,15 +65,21 @@
snprintf(data->error_msg, V4LCONVERT_ERROR_MSG_SIZE, \
"v4l-convert: error " __VA_ARGS__)
+#define V4LCONVERT_UPSIDE_DOWN 0x01
struct v4lconvert_data {
int fd;
+ int flags; /* bitfield */
int supported_src_formats; /* bitfield */
unsigned int no_formats;
char error_msg[V4LCONVERT_ERROR_MSG_SIZE];
struct jdec_private *jdec;
};
+struct v4lconvert_flags_info {
+ const char *card;
+ int flags;
+};
void v4lconvert_yuv420_to_rgb24(const unsigned char *src, unsigned char *dst,
int width, int height);
@@ -107,4 +117,16 @@ void v4lconvert_bayer_to_bgr24(const unsigned char *bayer,
void v4lconvert_bayer_to_yuv420(const unsigned char *bayer,
unsigned char *yuv, int width, int height, unsigned int pixfmt);
+void v4lconvert_rotate90_rgbbgr24(const unsigned char *src, unsigned char *dst,
+ int destwidth, int destheight);
+
+void v4lconvert_rotate90_yuv420(const unsigned char *src, unsigned char *dst,
+ int destwidth, int destheight);
+
+void v4lconvert_rotate180_rgbbgr24(const unsigned char *src, unsigned char *dst,
+ int width, int height);
+
+void v4lconvert_rotate180_yuv420(const unsigned char *src, unsigned char *dst,
+ int width, int height);
+
#endif
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c
index 4c9e67d52..4b48bfac4 100644
--- a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c
@@ -48,17 +48,26 @@ static const unsigned int supported_src_pixfmts[] = {
V4L2_PIX_FMT_SPCA561,
V4L2_PIX_FMT_SN9C10X,
V4L2_PIX_FMT_PAC207,
+ V4L2_PIX_FMT_PJPG,
};
static const unsigned int supported_dst_pixfmts[] = {
SUPPORTED_DST_PIXFMTS
};
+/* List of cams which need special flags */
+static const struct v4lconvert_flags_info v4lconvert_flags[] = {
+ { "USB Camera (0471:0325)", V4LCONVERT_UPSIDE_DOWN }, /* SPC200NC */
+ { "USB Camera (0471:0326)", V4LCONVERT_UPSIDE_DOWN }, /* SPC300NC */
+ { "SPC 200NC ", V4LCONVERT_UPSIDE_DOWN },
+ { "SPC 300NC ", V4LCONVERT_UPSIDE_DOWN },
+};
struct v4lconvert_data *v4lconvert_create(int fd)
{
int i, j;
struct v4lconvert_data *data = calloc(1, sizeof(struct v4lconvert_data));
+ struct v4l2_capability cap;
if (!data)
return NULL;
@@ -84,6 +93,15 @@ struct v4lconvert_data *v4lconvert_create(int fd)
data->no_formats = i;
+ /* Check if this cam has any special flags */
+ if (syscall(SYS_ioctl, fd, VIDIOC_QUERYCAP, &cap) == 0) {
+ for (i = 0; i < ARRAY_SIZE(v4lconvert_flags); i++)
+ if (!strcmp((const char *)v4lconvert_flags[i].card, (char *)cap.card)) {
+ data->flags = v4lconvert_flags[i].flags;
+ break;
+ }
+ }
+
return data;
}
@@ -214,17 +232,42 @@ int v4lconvert_try_format(struct v4lconvert_data *data,
return 0;
}
+/* Is conversion necessary ? */
+int v4lconvert_needs_conversion(struct v4lconvert_data *data,
+ const struct v4l2_format *src_fmt, /* in */
+ const struct v4l2_format *dest_fmt) /* in */
+{
+ int i;
+
+ if(memcmp(src_fmt, dest_fmt, sizeof(*src_fmt)))
+ return 1; /* Formats differ */
+
+ if (!(data->flags & V4LCONVERT_UPSIDE_DOWN))
+ return 0; /* Formats identical and we don't need flip */
+
+ /* Formats are identical, but we need flip, do we support the dest_fmt? */
+ for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++)
+ if (supported_dst_pixfmts[i] == dest_fmt->fmt.pix.pixelformat)
+ break;
+
+ if (i == ARRAY_SIZE(supported_dst_pixfmts))
+ return 0; /* Needs flip but we cannot do it :( */
+ else
+ return 1; /* Needs flip and thus conversion */
+}
+
int v4lconvert_convert(struct v4lconvert_data *data,
const struct v4l2_format *src_fmt, /* in */
const struct v4l2_format *dest_fmt, /* in */
- unsigned char *src, int src_size, unsigned char *dest, int dest_size)
+ unsigned char *src, int src_size, unsigned char *_dest, int dest_size)
{
unsigned int header_width, header_height;
- int result, needed;
+ int result, needed, rotate = 0, jpeg_flags = TINYJPEG_FLAGS_MJPEG_TABLE;
unsigned char *components[3];
+ unsigned char *dest = _dest;
/* Special case when no conversion is needed */
- if(!memcmp(src_fmt, dest_fmt, sizeof(*src_fmt))) {
+ if (!v4lconvert_needs_conversion(data, src_fmt, dest_fmt)) {
int to_copy = MIN(dest_size, src_size);
memcpy(dest, src, to_copy);
return to_copy;
@@ -251,7 +294,15 @@ int v4lconvert_convert(struct v4lconvert_data *data,
return -1;
}
+ if (data->flags & V4LCONVERT_UPSIDE_DOWN) {
+ rotate = 180;
+ dest = alloca(needed);
+ }
+
switch (src_fmt->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_PJPG:
+ jpeg_flags |= TINYJPEG_FLAGS_PIXART_JPEG;
+ /* Fall through */
case V4L2_PIX_FMT_MJPEG:
case V4L2_PIX_FMT_JPEG:
if (!data->jdec) {
@@ -262,9 +313,7 @@ int v4lconvert_convert(struct v4lconvert_data *data,
return -1;
}
}
- tinyjpeg_set_flags(data->jdec,
- (src_fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)?
- TINYJPEG_FLAGS_MJPEG_TABLE : 0);
+ tinyjpeg_set_flags(data->jdec, jpeg_flags);
if (tinyjpeg_parse_header(data->jdec, src, src_size)) {
V4LCONVERT_ERR("parsing JPEG header: %s\n",
tinyjpeg_get_errorstring(data->jdec));
@@ -273,13 +322,22 @@ int v4lconvert_convert(struct v4lconvert_data *data,
}
tinyjpeg_get_size(data->jdec, &header_width, &header_height);
- if (header_width != dest_fmt->fmt.pix.width || header_height != dest_fmt->fmt.pix.height) {
- V4LCONVERT_ERR("unexpected width / height in JPEG header\n");
- V4LCONVERT_ERR("expected: %dx%d, header: %ux%u\n",
- dest_fmt->fmt.pix.width, dest_fmt->fmt.pix.height,
- header_width, header_height);
- errno = EIO;
- return -1;
+ if (header_width != dest_fmt->fmt.pix.width ||
+ header_height != dest_fmt->fmt.pix.height) {
+ /* Check for (pixart) rotated JPEG */
+ if (header_width == dest_fmt->fmt.pix.height ||
+ header_height == dest_fmt->fmt.pix.width) {
+ if (!rotate)
+ dest = alloca(needed);
+ rotate += 90;
+ } else {
+ V4LCONVERT_ERR("unexpected width / height in JPEG header"
+ "expected: %ux%u, header: %ux%u\n",
+ dest_fmt->fmt.pix.width, dest_fmt->fmt.pix.height,
+ header_width, header_height);
+ errno = EIO;
+ return -1;
+ }
}
components[0] = dest;
@@ -303,13 +361,24 @@ int v4lconvert_convert(struct v4lconvert_data *data,
break;
}
- /* If the JPEG header checked out ok and we get an error during actual
- decompression, log the error, but don't return an errorcode to the
- application, so that the user gets what we managed to decompress */
- if (result)
- fprintf(stderr, "libv4lconvert: Error decompressing JPEG: %s",
- tinyjpeg_get_errorstring(data->jdec));
-
+ if (result) {
+ /* Pixart webcam's seem to regulary generate corrupt frames, which
+ are best thrown away to avoid flashes in the video stream. Tell
+ the upper layer this is an intermediate fault and it should try
+ again with a new buffer by setting errno to EAGAIN */
+ if (src_fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_PJPG) {
+ V4LCONVERT_ERR("Error decompressing JPEG: %s",
+ tinyjpeg_get_errorstring(data->jdec));
+ errno = EAGAIN;
+ return -1;
+ } else {
+ /* If the JPEG header checked out ok and we get an error during actual
+ decompression, log the error, but don't return an errorcode to the
+ application, so that the user gets what we managed to decompress */
+ fprintf(stderr, "libv4lconvert: Error decompressing JPEG: %s",
+ tinyjpeg_get_errorstring(data->jdec));
+ }
+ }
break;
case V4L2_PIX_FMT_SBGGR8:
@@ -387,7 +456,7 @@ int v4lconvert_convert(struct v4lconvert_data *data,
case V4L2_PIX_FMT_SN9C10X:
v4lconvert_decode_sn9c10x(src, tmpbuf, dest_fmt->fmt.pix.width,
dest_fmt->fmt.pix.height);
- bayer_fmt = V4L2_PIX_FMT_SGBRG8;
+ bayer_fmt = V4L2_PIX_FMT_SBGGR8;
break;
case V4L2_PIX_FMT_PAC207:
v4lconvert_decode_pac207(src, tmpbuf, dest_fmt->fmt.pix.width,
@@ -455,6 +524,45 @@ int v4lconvert_convert(struct v4lconvert_data *data,
return -1;
}
+ /* Note when rotating dest is our temporary buffer to which our conversion
+ was done and _dest is the real dest! If the formats are identical no
+ conversion has been done! */
+ if (rotate && dest_fmt->fmt.pix.pixelformat == src_fmt->fmt.pix.pixelformat)
+ dest = src;
+
+ switch (rotate) {
+ case 0:
+ break;
+ case 90:
+ switch (dest_fmt->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_RGB24:
+ case V4L2_PIX_FMT_BGR24:
+ v4lconvert_rotate90_rgbbgr24(dest, _dest, dest_fmt->fmt.pix.width,
+ dest_fmt->fmt.pix.height);
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ v4lconvert_rotate90_yuv420(dest, _dest, dest_fmt->fmt.pix.width,
+ dest_fmt->fmt.pix.height);
+ break;
+ }
+ break;
+ case 180:
+ switch (dest_fmt->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_RGB24:
+ case V4L2_PIX_FMT_BGR24:
+ v4lconvert_rotate180_rgbbgr24(dest, _dest, dest_fmt->fmt.pix.width,
+ dest_fmt->fmt.pix.height);
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ v4lconvert_rotate180_yuv420(dest, _dest, dest_fmt->fmt.pix.width,
+ dest_fmt->fmt.pix.height);
+ break;
+ }
+ break;
+ default:
+ printf("FIXME add %d degrees rotation\n", rotate);
+ }
+
return needed;
}
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/pac207.c b/v4l2-apps/lib/libv4l/libv4lconvert/pac207.c
index 4887c25ee..97ef4ebc0 100644
--- a/v4l2-apps/lib/libv4l/libv4lconvert/pac207.c
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/pac207.c
@@ -38,7 +38,7 @@ static struct {
signed char val;
} table[256];
-void init_pixart_decoder(void)
+static void init_pixart_decoder(void)
{
int i;
int is_abs, val, len;
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c b/v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c
index 742dd06ce..883d62330 100644
--- a/v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c
@@ -20,6 +20,8 @@
*/
+#include "libv4lconvert-priv.h"
+
#define RGB2YUV(r,g,b,y,u,v) \
(y) = (( 8453*(r) + 16594*(g) + 3223*(b) + 524288) >> 15); \
(u) = (( -4878*(r) - 9578*(g) + 14456*(b) + 4210688) >> 15); \
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c b/v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c
index 98a513378..4ea526d49 100644
--- a/v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c
@@ -50,7 +50,7 @@ static int sonix_unknown = 0;
present at the MSB of byte x.
*/
-void sonix_decompress_init(void)
+static void sonix_decompress_init(void)
{
int i;
int is_abs, val, len, unk;
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/spca561-decompress.c b/v4l2-apps/lib/libv4l/libv4lconvert/spca561-decompress.c
index 802345af0..01eed4ec5 100644
--- a/v4l2-apps/lib/libv4l/libv4lconvert/spca561-decompress.c
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/spca561-decompress.c
@@ -28,6 +28,7 @@
* but it might work with other spca561 cameras
*/
#include <string.h>
+#include "libv4lconvert-priv.h"
/*fixme: not reentrant */
static unsigned int bit_bucket;
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg.c b/v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg.c
index 5c3b4e26d..fc9efbeb2 100644
--- a/v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg.c
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg.c
@@ -214,6 +214,28 @@ static const unsigned char val_ac_chrominance[] =
0xf9, 0xfa
};
+const unsigned char pixart_quantization[][64] = {
+ {
+ 0x07, 0x07, 0x08, 0x0a, 0x09, 0x07, 0x0d, 0x0b,
+ 0x0c, 0x0d, 0x11, 0x10, 0x0f, 0x12, 0x17, 0x27,
+ 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
+ 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
+ 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
+ 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
+ 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
+ 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
+ },
+ {
+ 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
+ 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ },
+};
/*
* 4 functions to manage the stream
@@ -246,7 +268,7 @@ static const unsigned char val_ac_chrominance[] =
unsigned char c; \
if (stream >= priv->stream_end) { \
snprintf(priv->error_string, sizeof(priv->error_string), \
- "fill_nbits error: need %d more bits\n", \
+ "fill_nbits error: need %u more bits\n", \
nbits_wanted - nbits_in_reservoir); \
longjmp(priv->jump_state, -EIO); \
} \
@@ -288,6 +310,74 @@ static const unsigned char val_ac_chrominance[] =
} while(0);
+/* Special Pixart versions of the *_nbits functions, these remove the special
+ ff ff ff xx sequences pixart cams insert from the bitstream */
+#define pixart_fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) \
+do { \
+ while (nbits_in_reservoir<nbits_wanted) \
+ { \
+ unsigned char c; \
+ if (stream >= priv->stream_end) { \
+ snprintf(priv->error_string, sizeof(priv->error_string), \
+ "fill_nbits error: need %u more bits\n", \
+ nbits_wanted - nbits_in_reservoir); \
+ longjmp(priv->jump_state, -EIO); \
+ } \
+ c = *stream++; \
+ reservoir <<= 8; \
+ if (c == 0xff) { \
+ switch (stream[0]) { \
+ case 0x00: \
+ stream++; \
+ break; \
+ case 0xd9: /* EOF marker */ \
+ stream++; \
+ if (stream != priv->stream_end) { \
+ snprintf(priv->error_string, sizeof(priv->error_string), \
+ "Pixart JPEG error: premature EOF\n"); \
+ longjmp(priv->jump_state, -EIO); \
+ } \
+ break; \
+ case 0xff: \
+ if (stream[1] == 0xff && (stream[2] < 7 || stream[2] == 0xff)) { \
+ stream += 3; \
+ c = *stream++; \
+ break; \
+ } \
+ /* Error fall through */ \
+ default: \
+ snprintf(priv->error_string, sizeof(priv->error_string), \
+ "Pixart JPEG error: invalid JPEG marker: 0xff 0x%02x 0x%02x 0x%02x\n", \
+ (unsigned int)stream[0], (unsigned int)stream[1], \
+ (unsigned int)stream[2]); \
+ longjmp(priv->jump_state, -EIO); \
+ } \
+ } \
+ reservoir |= c; \
+ nbits_in_reservoir+=8; \
+ } \
+} while(0);
+
+/* Signed version !!!! */
+#define pixart_get_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) \
+do { \
+ pixart_fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \
+ result = ((reservoir)>>(nbits_in_reservoir-(nbits_wanted))); \
+ nbits_in_reservoir -= (nbits_wanted); \
+ reservoir &= ((1U<<nbits_in_reservoir)-1); \
+ if ((unsigned int)result < (1UL<<((nbits_wanted)-1))) \
+ result += (0xFFFFFFFFUL<<(nbits_wanted))+1; \
+} while(0);
+
+#define pixart_look_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) \
+do { \
+ pixart_fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \
+ result = ((reservoir)>>(nbits_in_reservoir-(nbits_wanted))); \
+} while(0);
+
+/* Note skip_nbits is identical for both */
+
+
#define be16_to_cpu(x) (((x)[0]<<8)|(x)[1])
static void resync(struct jdec_private *priv);
@@ -334,9 +424,50 @@ static int get_next_huffman_code(struct jdec_private *priv, struct huffman_table
slowtable+=2;
}
}
+ snprintf(priv->error_string, sizeof(priv->error_string),
+ "unknown huffman code: %08x\n", (unsigned int)hcode);
+ longjmp(priv->jump_state, -EIO);
return 0;
}
+/* identical as above but with *_nbits replaced with pixart_*_nbits */
+static int pixart_get_next_huffman_code(struct jdec_private *priv,
+ struct huffman_table *huffman_table)
+{
+ int value, hcode;
+ unsigned int extra_nbits, nbits;
+ uint16_t *slowtable;
+
+ pixart_look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, HUFFMAN_HASH_NBITS, hcode);
+ value = huffman_table->lookup[hcode];
+ if (value >= 0)
+ {
+ unsigned int code_size = huffman_table->code_size[value];
+ skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, code_size);
+ return value;
+ }
+
+ /* Decode more bits each time ... */
+ for (extra_nbits=0; extra_nbits<16-HUFFMAN_HASH_NBITS; extra_nbits++)
+ {
+ nbits = HUFFMAN_HASH_NBITS + 1 + extra_nbits;
+
+ pixart_look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, nbits, hcode);
+ slowtable = huffman_table->slowtable[extra_nbits];
+ /* Search if the code is in this array */
+ while (slowtable[0]) {
+ if (slowtable[0] == hcode) {
+ skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, nbits);
+ return slowtable[1];
+ }
+ slowtable+=2;
+ }
+ }
+ snprintf(priv->error_string, sizeof(priv->error_string),
+ "unknown huffman code: %08x\n", (unsigned int)hcode);
+ longjmp(priv->jump_state, -EIO);
+ return 0;
+}
@@ -388,15 +519,84 @@ static void process_Huffman_data_unit(struct jdec_private *priv, int component)
else
{
j += count_0; /* skip count_0 zeroes */
- get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, size_val, DCT[j]);
- j++;
+ if (j < 64) {
+ get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, size_val, DCT[j]);
+ j++;
+ }
}
}
+ if (j > 64) {
+ snprintf(priv->error_string, sizeof(priv->error_string),
+ "error: more then 63 AC components (%d) in huffman unit\n", (int)j);
+ longjmp(priv->jump_state, -EIO);
+ }
+
for (j = 0; j < 64; j++)
c->DCT[j] = DCT[zigzag[j]];
}
+/* identical as above both with *_nbits replaced with pixart_*_nbits */
+static void pixart_process_Huffman_data_unit(struct jdec_private *priv, int component)
+{
+ unsigned char j;
+ unsigned int huff_code;
+ unsigned char size_val, count_0;
+
+ struct component *c = &priv->component_infos[component];
+ short int DCT[64];
+
+ /* Initialize the DCT coef table */
+ memset(DCT, 0, sizeof(DCT));
+
+ /* DC coefficient decoding */
+ huff_code = pixart_get_next_huffman_code(priv, c->DC_table);
+ if (huff_code) {
+ pixart_get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, huff_code, DCT[0]);
+ DCT[0] += c->previous_DC;
+ c->previous_DC = DCT[0];
+ } else {
+ DCT[0] = c->previous_DC;
+ }
+
+
+ /* AC coefficient decoding */
+ j = 1;
+ while (j<64)
+ {
+ huff_code = pixart_get_next_huffman_code(priv, c->AC_table);
+
+ size_val = huff_code & 0xF;
+ count_0 = huff_code >> 4;
+
+ if (size_val == 0)
+ { /* RLE */
+ if (count_0 == 0)
+ break; /* EOB found, go out */
+ else if (count_0 == 0xF)
+ j += 16; /* skip 16 zeros */
+ }
+ else
+ {
+ j += count_0; /* skip count_0 zeroes */
+ if (j < 64 ) {
+ pixart_get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, size_val, DCT[j]);
+ j++;
+ }
+ }
+ }
+
+ if (j > 64) {
+ snprintf(priv->error_string, sizeof(priv->error_string),
+ "error: more then 63 AC components (%d) in huffman unit\n", (int)j);
+ longjmp(priv->jump_state, -EIO);
+ }
+
+ for (j = 0; j < 64; j++)
+ c->DCT[j] = DCT[zigzag[j]];
+}
+
+
/*
* Takes two array of bits, and build the huffman table for size, and code
*
@@ -404,12 +604,13 @@ static void process_Huffman_data_unit(struct jdec_private *priv, int component)
* code_size will be used to known how many bits this symbol is encoded.
* slowtable will be used when the first lookup didn't give the result.
*/
-static void build_huffman_table(const unsigned char *bits, const unsigned char *vals, struct huffman_table *table)
+static int build_huffman_table(struct jdec_private *priv, const unsigned char *bits, const unsigned char *vals, struct huffman_table *table)
{
unsigned int i, j, code, code_size, val, nbits;
unsigned char huffsize[257], *hz;
unsigned int huffcode[257], *hc;
int next_free_entry;
+ int slowtable_used[16-HUFFMAN_HASH_NBITS];
/*
* Build a temp array
@@ -425,7 +626,7 @@ static void build_huffman_table(const unsigned char *bits, const unsigned char *
memset(table->lookup, 0xff, sizeof(table->lookup));
for (i=0; i<(16-HUFFMAN_HASH_NBITS); i++)
- table->slowtable[i][0] = 0;
+ slowtable_used[i] = 0;
/* Build a temp array
* huffcode[X] => code used to write vals[X]
@@ -472,32 +673,43 @@ static void build_huffman_table(const unsigned char *bits, const unsigned char *
else
{
/* Perhaps sorting the array will be an optimization */
- uint16_t *slowtable = table->slowtable[code_size-HUFFMAN_HASH_NBITS-1];
- while(slowtable[0])
- slowtable+=2;
- slowtable[0] = code;
- slowtable[1] = val;
- slowtable[2] = 0;
- /* TODO: NEED TO CHECK FOR AN OVERFLOW OF THE TABLE */
- }
+ int slowtable_index = code_size-HUFFMAN_HASH_NBITS-1;
+
+ if (slowtable_used[slowtable_index] == 254)
+ error("slow Huffman table overflow\n");
+ table->slowtable[slowtable_index][slowtable_used[slowtable_index]]
+ = code;
+ table->slowtable[slowtable_index][slowtable_used[slowtable_index] + 1]
+ = val;
+ slowtable_used[slowtable_index] += 2;
+ }
}
+ for (i=0; i<(16-HUFFMAN_HASH_NBITS); i++)
+ table->slowtable[i][slowtable_used[i]] = 0;
+
+ return 0;
}
-static void build_default_huffman_tables(struct jdec_private *priv)
+static int build_default_huffman_tables(struct jdec_private *priv)
{
if ( (priv->flags & TINYJPEG_FLAGS_MJPEG_TABLE)
&& priv->default_huffman_table_initialized)
- return;
+ return 0;
- build_huffman_table(bits_dc_luminance, val_dc_luminance, &priv->HTDC[0]);
- build_huffman_table(bits_ac_luminance, val_ac_luminance, &priv->HTAC[0]);
+ if (build_huffman_table(priv, bits_dc_luminance, val_dc_luminance, &priv->HTDC[0]))
+ return -1;
+ if (build_huffman_table(priv, bits_ac_luminance, val_ac_luminance, &priv->HTAC[0]))
+ return -1;
- build_huffman_table(bits_dc_chrominance, val_dc_chrominance, &priv->HTDC[1]);
- build_huffman_table(bits_ac_chrominance, val_ac_chrominance, &priv->HTAC[1]);
+ if (build_huffman_table(priv, bits_dc_chrominance, val_dc_chrominance, &priv->HTDC[1]))
+ return -1;
+ if (build_huffman_table(priv, bits_ac_chrominance, val_ac_chrominance, &priv->HTAC[1]))
+ return -1;
priv->default_huffman_table_initialized = 1;
+ return 0;
}
@@ -1390,6 +1602,44 @@ static void decode_MCU_2x1_3planes(struct jdec_private *priv)
IDCT(&priv->component_infos[cCr], priv->Cr, 8);
}
+static void pixart_decode_MCU_2x1_3planes(struct jdec_private *priv)
+{
+ unsigned char marker;
+
+ pixart_look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream,
+ 8, marker);
+ /* I think the marker indicates which quantization table to use, iow
+ a Pixart JPEG may have a different quantization table per MCU, most
+ MCU's have 0x44 as marker for which our special Pixart quantization
+ tables are correct. Unfortunately with a 7302 some blocks also have 0x48,
+ and sometimes even other values. As 0x48 is quite common too, we really
+ need to find out the correct table for that, as currently the blocks
+ with a 0x48 marker look wrong. During normal operation the marker stays
+ within the range below, if it gets out of this range we're most likely
+ decoding garbage */
+ if (marker < 0x20 || marker > 0x7f) {
+ snprintf(priv->error_string, sizeof(priv->error_string),
+ "Pixart JPEG error: invalid MCU marker: 0x%02x\n",
+ (unsigned int)marker);
+ longjmp(priv->jump_state, -EIO);
+ }
+ skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, 8);
+
+ // Y
+ pixart_process_Huffman_data_unit(priv, cY);
+ IDCT(&priv->component_infos[cY], priv->Y, 16);
+ pixart_process_Huffman_data_unit(priv, cY);
+ IDCT(&priv->component_infos[cY], priv->Y+8, 16);
+
+ // Cb
+ pixart_process_Huffman_data_unit(priv, cCb);
+ IDCT(&priv->component_infos[cCb], priv->Cb, 8);
+
+ // Cr
+ pixart_process_Huffman_data_unit(priv, cCr);
+ IDCT(&priv->component_infos[cCr], priv->Cr, 8);
+}
+
/*
* Decode a 2x1
* .-------.
@@ -1676,9 +1926,9 @@ static int parse_SOS(struct jdec_private *priv, const unsigned char *stream)
error("We do not support more than %d DC Huffman table\n",
HUFFMAN_TABLES);
if (cid != priv->component_infos[i].cid)
- error("SOS cid order (%d:%d) isn't compatible with the SOF marker (%d:%d)\n",
+ error("SOS cid order (%u:%u) isn't compatible with the SOF marker (%u:%u)\n",
i, cid, i, priv->component_infos[i].cid);
- trace("ComponentId:%d tableAC:%d tableDC:%d\n", cid, table&0xf, table>>4);
+ trace("ComponentId:%u tableAC:%d tableDC:%d\n", cid, table&0xf, table>>4);
#endif
priv->component_infos[i].AC_table = &priv->HTAC[table&0xf];
priv->component_infos[i].DC_table = &priv->HTDC[table>>4];
@@ -1723,10 +1973,13 @@ static int parse_DHT(struct jdec_private *priv, const unsigned char *stream)
trace("Length of the table: %d\n", count);
#endif
- if (index & 0xf0 )
- build_huffman_table(huff_bits, stream, &priv->HTAC[index&0xf]);
- else
- build_huffman_table(huff_bits, stream, &priv->HTDC[index&0xf]);
+ if (index & 0xf0 ) {
+ if (build_huffman_table(priv, huff_bits, stream, &priv->HTAC[index&0xf]))
+ return -1;
+ } else {
+ if (build_huffman_table(priv, huff_bits, stream, &priv->HTDC[index&0xf]))
+ return -1;
+ }
length -= 1;
length -= 16;
@@ -1817,6 +2070,8 @@ static int parse_JFIF(struct jdec_private *priv, const unsigned char *stream)
{
int chuck_len;
int marker;
+ int sof_marker_found = 0;
+ int dqt_marker_found = 0;
int sos_marker_found = 0;
int dht_marker_found = 0;
const unsigned char *next_chunck;
@@ -1838,10 +2093,12 @@ static int parse_JFIF(struct jdec_private *priv, const unsigned char *stream)
case SOF:
if (parse_SOF(priv, stream) < 0)
return -1;
+ sof_marker_found = 1;
break;
case DQT:
if (parse_DQT(priv, stream) < 0)
return -1;
+ dqt_marker_found = 1;
break;
case SOS:
if (parse_SOS(priv, stream) < 0)
@@ -1865,9 +2122,24 @@ static int parse_JFIF(struct jdec_private *priv, const unsigned char *stream)
stream = next_chunck;
}
+ if ( !sof_marker_found ||
+ (!dqt_marker_found && !(priv->flags & TINYJPEG_FLAGS_PIXART_JPEG)))
+ goto bogus_jpeg_format;
+
+ if (priv->flags & TINYJPEG_FLAGS_PIXART_JPEG) {
+ if (!priv->default_huffman_table_initialized) {
+ build_quantization_table(priv->Q_tables[0], pixart_quantization[0]);
+ build_quantization_table(priv->Q_tables[1], pixart_quantization[1]);
+ }
+
+ /* Pixart JPEG data starts with one unknown / unused byte */
+ priv->stream++;
+ }
+
if (!dht_marker_found) {
trace("No Huffman table loaded, using the default one\n");
- build_default_huffman_tables(priv);
+ if (build_default_huffman_tables(priv))
+ return -1;
}
#ifdef SANITY_CHECK
@@ -1962,6 +2234,13 @@ static const decode_MCU_fct decode_mcu_3comp_table[4] = {
decode_MCU_2x2_3planes,
};
+static const decode_MCU_fct pixart_decode_mcu_3comp_table[4] = {
+ NULL,
+ NULL,
+ pixart_decode_MCU_2x1_3planes,
+ NULL,
+};
+
static const decode_MCU_fct decode_mcu_1comp_table[4] = {
decode_MCU_1x1_1plane,
decode_MCU_1x2_1plane,
@@ -2021,6 +2300,9 @@ int tinyjpeg_decode(struct jdec_private *priv, int pixfmt)
bytes_per_blocklines[2] = 0;
decode_mcu_table = decode_mcu_3comp_table;
+ if (priv->flags & TINYJPEG_FLAGS_PIXART_JPEG)
+ decode_mcu_table = pixart_decode_mcu_3comp_table;
+
switch (pixfmt) {
case TINYJPEG_FMT_YUV420P:
colorspace_array_conv = convert_colorspace_yuv420p;
@@ -2056,6 +2338,8 @@ int tinyjpeg_decode(struct jdec_private *priv, int pixfmt)
case TINYJPEG_FMT_GREY:
decode_mcu_table = decode_mcu_1comp_table;
+ if (priv->flags & TINYJPEG_FLAGS_PIXART_JPEG)
+ error("Greyscale output not support for PIXART JPEG's\n");
colorspace_array_conv = convert_colorspace_grey;
if (priv->components[0] == NULL)
priv->components[0] = (uint8_t *)malloc(priv->width * priv->height);
@@ -2064,8 +2348,7 @@ int tinyjpeg_decode(struct jdec_private *priv, int pixfmt)
break;
default:
- trace("Bad pixel format\n");
- return -1;
+ error("Bad pixel format\n");
}
xstride_by_mcu = ystride_by_mcu = 8;
@@ -2091,6 +2374,9 @@ int tinyjpeg_decode(struct jdec_private *priv, int pixfmt)
trace("Use decode 2x1 sampling\n");
}
+ if (decode_MCU == NULL)
+ error("no decode MCU function for this JPEG format (PIXART?)\n");
+
resync(priv);
/* Don't forget to that block can be either 8 or 16 lines */
@@ -2130,6 +2416,12 @@ int tinyjpeg_decode(struct jdec_private *priv, int pixfmt)
}
}
+ if (priv->flags & TINYJPEG_FLAGS_PIXART_JPEG) {
+ /* Additional sanity check for funky Pixart format */
+ if ((priv->stream_end - priv->stream) > 5)
+ error("Pixart JPEG error, stream does not end with EOF marker\n");
+ }
+
return 0;
}
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg.h b/v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg.h
index 42b60c1ee..b0096f0de 100644
--- a/v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg.h
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg.h
@@ -43,6 +43,7 @@ struct jdec_private;
/* Flags that can be set by any applications */
#define TINYJPEG_FLAGS_MJPEG_TABLE (1<<1)
+#define TINYJPEG_FLAGS_PIXART_JPEG (1<<2)
/* Format accepted in outout */
enum tinyjpeg_fmt {
diff --git a/v4l2-apps/util/ivtv-ctl.c b/v4l2-apps/util/ivtv-ctl.c
index ab836e240..af84164e3 100644
--- a/v4l2-apps/util/ivtv-ctl.c
+++ b/v4l2-apps/util/ivtv-ctl.c
@@ -351,9 +351,9 @@ int main(int argc, char **argv)
unsigned short gpio_dir = 0x0; /* GPIO direction bits */
int gpio_set_dir = 0;
int passthrough = 0;
- int audio_mute = 0;
- int stereo_mode = 0;
- int bilingual_mode = 0;
+ long audio_mute = 0;
+ long stereo_mode = 0;
+ long bilingual_mode = 0;
int debug_level = 0;
__u32 reset = 0;
int new_debug_level, gdebug_level;
@@ -621,7 +621,7 @@ int main(int argc, char **argv)
}
if (options[OptPassThrough]) {
- int source = passthrough ? VIDEO_SOURCE_DEMUX : VIDEO_SOURCE_MEMORY;
+ long source = passthrough ? VIDEO_SOURCE_DEMUX : VIDEO_SOURCE_MEMORY;
doioctl(fd, VIDEO_SELECT_SOURCE, (void *)source,
"IVTV_IOC_PASSTHROUGH");