#include <linux/time.h>
#include <linux/delay.h>
#include <linux/stddef.h>
+#include <linux/compiler.h>
#include <linux/ioctl.h>
#include <linux/poll.h>
#include <linux/stat.h>
/*****************************************************************************/
-typedef char sn9c102_sof_header_t[7];
+typedef char sn9c102_sof_header_t[12];
typedef char sn9c102_eof_header_t[4];
static sn9c102_sof_header_t sn9c102_sof_header[] = {
{0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01},
};
-/* Number of random bytes that complete the SOF above headers */
-#define SN9C102_SOFLEN 5
static sn9c102_eof_header_t sn9c102_eof_header[] = {
{0x00, 0x00, 0x00, 0x00},
u8* buff = cam->control_buffer;
int res;
- if (index == 0x18)
- value = (value & 0xcf) | (cam->reg[0x18] & 0x30);
-
*buff = value;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
static void* sn9c102_find_sof_header(void* mem, size_t len)
{
- size_t soflen=sizeof(sn9c102_sof_header_t), SOFLEN=SN9C102_SOFLEN, i;
+ size_t soflen = sizeof(sn9c102_sof_header_t), i;
u8 j, n = sizeof(sn9c102_sof_header) / soflen;
- for (i = 0; (len >= soflen+SOFLEN) && (i <= len-soflen-SOFLEN); i++)
+ for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
for (j = 0; j < n; j++)
- if (!memcmp(mem + i, sn9c102_sof_header[j], soflen))
+ /* It's enough to compare 7 bytes */
+ if (!memcmp(mem + i, sn9c102_sof_header[j], 7))
/* Skips the header */
- return mem + i + soflen + SOFLEN;
+ return mem + i + soflen;
return NULL;
}
PDBGG("Isochrnous frame: length %u, #%u i", len, i)
- /* NOTE: It is probably correct to assume that SOF and EOF
+ /*
+ NOTE: It is probably correct to assume that SOF and EOF
headers do not occur between two consecutive packets,
but who knows..Whatever is the truth, this assumption
- doesn't introduce bugs. */
+ doesn't introduce bugs.
+ */
redo:
sof = sn9c102_find_sof_header(pos, len);
return (u8)val;
}
-/* NOTE 1: being inside one of the following methods implies that the v4l
+/*
+ NOTE 1: being inside one of the following methods implies that the v4l
device exists for sure (see kobjects and reference counters)
- NOTE 2: buffers are PAGE_SIZE long */
+ NOTE 2: buffers are PAGE_SIZE long
+*/
static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf)
{
}
-static ssize_t
-sn9c102_store_redblue(struct class_device* cd, const char* buf, size_t len)
-{
- ssize_t res = 0;
- u8 value;
- ssize_t count;
-
- value = sn9c102_strtou8(buf, len, &count);
- if (!count)
- return -EINVAL;
-
- if ((res = sn9c102_store_reg(cd, "0x10", 4)) >= 0)
- res = sn9c102_store_val(cd, buf, len);
-
- return res;
-}
-
-
static ssize_t
sn9c102_store_green(struct class_device* cd, const char* buf, size_t len)
{
sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
sn9c102_show_i2c_val, sn9c102_store_i2c_val);
-static CLASS_DEVICE_ATTR(redblue, S_IWUGO, NULL, sn9c102_store_redblue);
static CLASS_DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green);
video_device_create_file(v4ldev, &class_device_attr_reg);
video_device_create_file(v4ldev, &class_device_attr_val);
- video_device_create_file(v4ldev, &class_device_attr_redblue);
video_device_create_file(v4ldev, &class_device_attr_green);
if (cam->sensor->slave_write_id && cam->sensor->slave_read_id) {
video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
ae_endy = v_size / 2;
int err = 0;
- /* These are a sort of stroboscopic signal for some sensors */
- err += sn9c102_write_reg(cam, h_size, 0x1a);
- err += sn9c102_write_reg(cam, v_size, 0x1b);
-
err += sn9c102_write_reg(cam, h_start, 0x12);
err += sn9c102_write_reg(cam, v_start, 0x13);
err += sn9c102_write_reg(cam, h_size, 0x15);
return -EIO;
PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size "
- "%u %u %u %u %u %u", h_start, v_start, h_size, v_size, ho_size,
- vo_size)
+ "%u %u %u %u", h_start, v_start, h_size, v_size)
return 0;
}
struct sn9c102_device* cam;
int err = 0;
- /* This the only safe way to prevent race conditions with disconnect */
+ /*
+ This is the only safe way to prevent race conditions with
+ disconnect
+ */
if (!down_read_trylock(&sn9c102_disconnect))
return -ERESTARTSYS;
return -EINVAL;
}
+ /* Preserve R,G or B origin */
+ rect->left = (s->_rect.left & 1L) ?
+ rect->left | 1L : rect->left & ~1L;
+ rect->top = (s->_rect.top & 1L) ?
+ rect->top | 1L : rect->top & ~1L;
+
if (rect->width < 16)
rect->width = 16;
if (rect->height < 16)
rect->width &= ~15L;
rect->height &= ~15L;
- { /* calculate the scaling factor */
+ if (SN9C102_PRESERVE_IMGSCALE) {
+ /* Calculate the actual scaling factor */
u32 a, b;
a = rect->width * rect->height;
b = pix_format->width * pix_format->height;
- scale = b ? (u8)((a / b) <= 1 ? 1 : ((a / b) == 3 ? 2 :
- ((a / b) > 4 ? 4 : (a / b)))) : 1;
- }
+ scale = b ? (u8)((a / b) < 4 ? 1 :
+ ((a / b) < 16 ? 2 : 4)) : 1;
+ } else
+ scale = 1;
if (cam->stream == STREAM_ON) {
cam->stream = STREAM_INTERRUPT;
memcpy(&rect, &(s->_rect), sizeof(rect));
- { /* calculate the scaling factor */
+ { /* calculate the actual scaling factor */
u32 a, b;
a = rect.width * rect.height;
b = pix->width * pix->height;
- scale = b ? (u8)((a / b) <= 1 ? 1 : ((a / b) == 3 ? 2 :
- ((a / b) > 4 ? 4 : (a / b)))) : 1;
+ scale = b ? (u8)((a / b) < 4 ? 1 :
+ ((a / b) < 16 ? 2 : 4)) : 1;
}
rect.width = scale * pix->width;
if (rect.height < 16)
rect.height = 16;
if (rect.width > bounds->left + bounds->width - rect.left)
- rect.width = bounds->left+bounds->width - rect.left;
+ rect.width = bounds->left + bounds->width - rect.left;
if (rect.height > bounds->top + bounds->height - rect.top)
rect.height = bounds->top + bounds->height - rect.top;
rect.width &= ~15L;
rect.height &= ~15L;
+ { /* adjust the scaling factor */
+ u32 a, b;
+ a = rect.width * rect.height;
+ b = pix->width * pix->height;
+ scale = b ? (u8)((a / b) < 4 ? 1 :
+ ((a / b) < 16 ? 2 : 4)) : 1;
+ }
+
pix->width = rect.width / scale;
pix->height = rect.height / scale;
spin_lock_irqsave(&cam->queue_lock, lock_flags);
f = list_entry(cam->outqueue.next, struct sn9c102_frame_t,
frame);
- list_del(&cam->outqueue);
+ list_del(cam->outqueue.next);
spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
f->state = F_UNUSED;