Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 739570bb authored by Jean-Francois Moine's avatar Jean-Francois Moine Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB (8352): gspca: Buffers for USB exchanges cannot be in the stack.



gspca:    Protect dq_callback() against simultaneous USB exchanges.
          Temporary buffer for USB exchanges added in the device struct.
(all)     Use a temporary buffer for all USB exchanges.

Signed-off-by: default avatarJean-Francois Moine <moinejf@free.fr>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 5b77ae77
Loading
Loading
Loading
Loading
+176 −209
Original line number Diff line number Diff line
@@ -25,8 +25,8 @@
#define CONEX_CAM 1		/* special JPEG header */
#include "jpeg.h"

#define DRIVER_VERSION_NUMBER	KERNEL_VERSION(2, 1, 5)
static const char version[] = "2.1.5";
#define DRIVER_VERSION_NUMBER	KERNEL_VERSION(2, 1, 7)
static const char version[] = "2.1.7";

MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
@@ -119,40 +119,67 @@ static struct v4l2_pix_format vga_mode[] = {
		.priv = 0},
};

static void reg_r(struct usb_device *dev,
/* the read bytes are found in gspca_dev->usb_buf */
static void reg_r(struct gspca_dev *gspca_dev,
		  __u16 index,
			   __u8 *buffer, __u16 length)
		  __u16 len)
{
	struct usb_device *dev = gspca_dev->dev;

#ifdef CONFIG_VIDEO_ADV_DEBUG
	if (len > sizeof gspca_dev->usb_buf) {
		err("reg_r: buffer overflow");
		return;
	}
#endif
	usb_control_msg(dev,
			usb_rcvctrlpipe(dev, 0),
			0,
			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
			0,
			index, buffer, length,
			index, gspca_dev->usb_buf, len,
			500);
	PDEBUG(D_USBI, "reg read [%02x] -> %02x ..", index, *buffer);
	PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
			index, gspca_dev->usb_buf[0]);
}

/* the bytes to write are in gspca_dev->usb_buf */
static void reg_w_val(struct gspca_dev *gspca_dev,
			__u16 index,
			__u8 val)
{
	struct usb_device *dev = gspca_dev->dev;

	gspca_dev->usb_buf[0] = val;
	usb_control_msg(dev,
			usb_sndctrlpipe(dev, 0),
			0,
			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
			0,
			index, gspca_dev->usb_buf, 1, 500);
}

static void reg_w(struct usb_device *dev,
static void reg_w(struct gspca_dev *gspca_dev,
		  __u16 index,
		  const __u8 *buffer, __u16 len)
		  const __u8 *buffer,
		  __u16 len)
{
	__u8 tmpbuf[8];
	struct usb_device *dev = gspca_dev->dev;

#ifdef CONFIG_VIDEO_ADV_DEBUG
	if (len > sizeof tmpbuf) {
		PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
	if (len > sizeof gspca_dev->usb_buf) {
		err("reg_w: buffer overflow");
		return;
	}
	PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
#endif
	memcpy(tmpbuf, buffer, len);
	memcpy(gspca_dev->usb_buf, buffer, len);
	usb_control_msg(dev,
			usb_sndctrlpipe(dev, 0),
			0,
			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
			0,
			index, tmpbuf, len, 500);
			index, gspca_dev->usb_buf, len, 500);
}

static const __u8 cx_sensor_init[][4] = {
@@ -232,17 +259,14 @@ static const __u8 cx11646_fw1[][3] = {
};
static void cx11646_fw(struct gspca_dev*gspca_dev)
{
	__u8 val;
	int i = 0;

	val = 0x02;
	reg_w(gspca_dev->dev, 0x006a, &val, 1);
	reg_w_val(gspca_dev, 0x006a, 0x02);
	while (cx11646_fw1[i][1]) {
		reg_w(gspca_dev->dev, 0x006b, cx11646_fw1[i], 3);
		reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
		i++;
	}
	val = 0x00;
	reg_w(gspca_dev->dev, 0x006a, &val, 1);
	reg_w_val(gspca_dev, 0x006a, 0x00);
}

static const __u8 cxsensor[] = {
@@ -273,52 +297,47 @@ static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };

static void cx_sensor(struct gspca_dev*gspca_dev)
{
	__u8 val;
	int i = 0;
	__u8 bufread[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
	int length;
	const __u8 *ptsensor = cxsensor;

	reg_w(gspca_dev->dev, 0x0020, reg20, 8);
	reg_w(gspca_dev->dev, 0x0028, reg28, 8);
	reg_w(gspca_dev->dev, 0x0010, reg10, 8);
	val = 0x03;
	reg_w(gspca_dev->dev, 0x0092, &val, 1);
	reg_w(gspca_dev, 0x0020, reg20, 8);
	reg_w(gspca_dev, 0x0028, reg28, 8);
	reg_w(gspca_dev, 0x0010, reg10, 8);
	reg_w_val(gspca_dev, 0x0092, 0x03);

	switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
	case 0:
		reg_w(gspca_dev->dev, 0x0071, reg71a, 4);
		reg_w(gspca_dev, 0x0071, reg71a, 4);
		break;
	case 1:
		reg_w(gspca_dev->dev, 0x0071, reg71b, 4);
		reg_w(gspca_dev, 0x0071, reg71b, 4);
		break;
	default:
/*	case 2: */
		reg_w(gspca_dev->dev, 0x0071, reg71c, 4);
		reg_w(gspca_dev, 0x0071, reg71c, 4);
		break;
	case 3:
		reg_w(gspca_dev->dev, 0x0071, reg71d, 4);
		reg_w(gspca_dev, 0x0071, reg71d, 4);
		break;
	}
	reg_w(gspca_dev->dev, 0x007b, reg7b, 6);
	val = 0x00;
	reg_w(gspca_dev->dev, 0x00f8, &val, 1);
	reg_w(gspca_dev->dev, 0x0010, reg10, 8);
	val = 0x41;
	reg_w(gspca_dev->dev, 0x0098, &val, 1);
	reg_w(gspca_dev, 0x007b, reg7b, 6);
	reg_w_val(gspca_dev, 0x00f8, 0x00);
	reg_w(gspca_dev, 0x0010, reg10, 8);
	reg_w_val(gspca_dev, 0x0098, 0x41);
	for (i = 0; i < 11; i++) {
		if (i == 3 || i == 5 || i == 8)
			length = 8;
		else
			length = 4;
		reg_w(gspca_dev->dev, 0x00e5, ptsensor, length);
		reg_w(gspca_dev, 0x00e5, ptsensor, length);
		if (length == 4)
			reg_r(gspca_dev->dev, 0x00e8, &val, 1);
			reg_r(gspca_dev, 0x00e8, 1);
		else
			reg_r(gspca_dev->dev, 0x00e8, bufread, length);
			reg_r(gspca_dev, 0x00e8, length);
		ptsensor += length;
	}
	reg_r(gspca_dev->dev, 0x00e7, bufread, 8);
	reg_r(gspca_dev, 0x00e7, 8);
}

static const __u8 cx_inits_176[] = {
@@ -358,10 +377,9 @@ static const __u8 cx_inits_640[] = {
	0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

static int cx11646_initsize(struct gspca_dev *gspca_dev)
static void cx11646_initsize(struct gspca_dev *gspca_dev)
{
	const __u8 *cxinit;
	__u8 val;
	static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
	static const __u8 reg17[] =
			{ 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
@@ -381,35 +399,29 @@ static int cx11646_initsize(struct gspca_dev *gspca_dev)
		cxinit = cx_inits_176;
		break;
	}
	val = 0x01;
	reg_w(gspca_dev->dev, 0x009a, &val, 1);
	val = 0x10;
	reg_w(gspca_dev->dev, 0x0010, &val, 1);
	reg_w(gspca_dev->dev, 0x0012, reg12, 5);
	reg_w(gspca_dev->dev, 0x0017, reg17, 8);
	val = 0x00;
	reg_w(gspca_dev->dev, 0x00c0, &val, 1);
	val = 0x04;
	reg_w(gspca_dev->dev, 0x00c1, &val, 1);
	val = 0x04;
	reg_w(gspca_dev->dev, 0x00c2, &val, 1);

	reg_w(gspca_dev->dev, 0x0061, cxinit, 8);
	reg_w_val(gspca_dev, 0x009a, 0x01);
	reg_w_val(gspca_dev, 0x0010, 0x10);
	reg_w(gspca_dev, 0x0012, reg12, 5);
	reg_w(gspca_dev, 0x0017, reg17, 8);
	reg_w_val(gspca_dev, 0x00c0, 0x00);
	reg_w_val(gspca_dev, 0x00c1, 0x04);
	reg_w_val(gspca_dev, 0x00c2, 0x04);

	reg_w(gspca_dev, 0x0061, cxinit, 8);
	cxinit += 8;
	reg_w(gspca_dev->dev, 0x00ca, cxinit, 8);
	reg_w(gspca_dev, 0x00ca, cxinit, 8);
	cxinit += 8;
	reg_w(gspca_dev->dev, 0x00d2, cxinit, 8);
	reg_w(gspca_dev, 0x00d2, cxinit, 8);
	cxinit += 8;
	reg_w(gspca_dev->dev, 0x00da, cxinit, 6);
	reg_w(gspca_dev, 0x00da, cxinit, 6);
	cxinit += 8;
	reg_w(gspca_dev->dev, 0x0041, cxinit, 8);
	reg_w(gspca_dev, 0x0041, cxinit, 8);
	cxinit += 8;
	reg_w(gspca_dev->dev, 0x0049, cxinit, 8);
	reg_w(gspca_dev, 0x0049, cxinit, 8);
	cxinit += 8;
	reg_w(gspca_dev->dev, 0x0051, cxinit, 2);
	reg_w(gspca_dev, 0x0051, cxinit, 2);

	reg_r(gspca_dev->dev, 0x0010, &val, 1);
	return val;
	reg_r(gspca_dev, 0x0010, 1);
}

static const __u8 cx_jpeg_init[][8] = {
@@ -636,26 +648,21 @@ static const __u8 cxjpeg_qtable[][8] = {

static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
{
	__u8 val;
	int i;
	int length;

	val = 0x01;
	reg_w(gspca_dev->dev, 0x00c0, &val, 1);
	val = 0x00;
	reg_w(gspca_dev->dev, 0x00c3, &val, 1);
	val = 0x00;
	reg_w(gspca_dev->dev, 0x00c0, &val, 1);
	reg_r(gspca_dev->dev, 0x0001, &val, 1);
	reg_w_val(gspca_dev, 0x00c0, 0x01);
	reg_w_val(gspca_dev, 0x00c3, 0x00);
	reg_w_val(gspca_dev, 0x00c0, 0x00);
	reg_r(gspca_dev, 0x0001, 1);
	length = 8;
	for (i = 0; i < 79; i++) {
		if (i == 78)
			length = 6;
		reg_w(gspca_dev->dev, 0x0008, cx_jpeg_init[i], length);
		reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
	}
	reg_r(gspca_dev->dev, 0x0002, &val, 1);
	val = 0x14;
	reg_w(gspca_dev->dev, 0x0055, &val, 1);
	reg_r(gspca_dev, 0x0002, 1);
	reg_w_val(gspca_dev, 0x0055, 0x14);
}

static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
@@ -665,31 +672,26 @@ static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
static const __u8 reg51[] = { 0x77, 0x03 };
static const __u8 reg70 = 0x03;
#define reg70 0x03

static void cx11646_jpeg(struct gspca_dev*gspca_dev)
{
	__u8 val;
	int i;
	int length;
	__u8 Reg55;
	__u8 bufread[8];
	int retry;

	val = 0x01;
	reg_w(gspca_dev->dev, 0x00c0, &val, 1);
	val = 0x00;
	reg_w(gspca_dev->dev, 0x00c3, &val, 1);
	val = 0x00;
	reg_w(gspca_dev->dev, 0x00c0, &val, 1);
	reg_r(gspca_dev->dev, 0x0001, &val, 1);
	reg_w_val(gspca_dev, 0x00c0, 0x01);
	reg_w_val(gspca_dev, 0x00c3, 0x00);
	reg_w_val(gspca_dev, 0x00c0, 0x00);
	reg_r(gspca_dev, 0x0001, 1);
	length = 8;
	switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
	case 0:
		for (i = 0; i < 27; i++) {
			if (i == 26)
				length = 2;
			reg_w(gspca_dev->dev, 0x0008, cxjpeg_640[i], length);
			reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
		}
		Reg55 = 0x28;
		break;
@@ -697,7 +699,7 @@ static void cx11646_jpeg(struct gspca_dev*gspca_dev)
		for (i = 0; i < 27; i++) {
			if (i == 26)
				length = 2;
			reg_w(gspca_dev->dev, 0x0008, cxjpeg_352[i], length);
			reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
		}
		Reg55 = 0x16;
		break;
@@ -706,7 +708,7 @@ static void cx11646_jpeg(struct gspca_dev*gspca_dev)
		for (i = 0; i < 27; i++) {
			if (i == 26)
				length = 2;
			reg_w(gspca_dev->dev, 0x0008, cxjpeg_320[i], length);
			reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
		}
		Reg55 = 0x14;
		break;
@@ -714,124 +716,98 @@ static void cx11646_jpeg(struct gspca_dev*gspca_dev)
		for (i = 0; i < 27; i++) {
			if (i == 26)
				length = 2;
			reg_w(gspca_dev->dev, 0x0008, cxjpeg_176[i], length);
			reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
		}
		Reg55 = 0x0B;
		break;
	}

	reg_r(gspca_dev->dev, 0x0002, &val, 1);
	val = Reg55;
	reg_w(gspca_dev->dev, 0x0055, &val, 1);
	reg_r(gspca_dev->dev, 0x0002, &val, 1);
	reg_w(gspca_dev->dev, 0x0010, reg10, 2);
	val = 0x02;
	reg_w(gspca_dev->dev, 0x0054, &val, 1);
	val = 0x01;
	reg_w(gspca_dev->dev, 0x0054, &val, 1);
	val = 0x94;
	reg_w(gspca_dev->dev, 0x0000, &val, 1);
	val = 0xc0;
	reg_w(gspca_dev->dev, 0x0053, &val, 1);
	val = 0xe1;
	reg_w(gspca_dev->dev, 0x00fc, &val, 1);
	val = 0x00;
	reg_w(gspca_dev->dev, 0x0000, &val, 1);
	reg_r(gspca_dev, 0x0002, 1);
	reg_w_val(gspca_dev, 0x0055, Reg55);
	reg_r(gspca_dev, 0x0002, 1);
	reg_w(gspca_dev, 0x0010, reg10, 2);
	reg_w_val(gspca_dev, 0x0054, 0x02);
	reg_w_val(gspca_dev, 0x0054, 0x01);
	reg_w_val(gspca_dev, 0x0000, 0x94);
	reg_w_val(gspca_dev, 0x0053, 0xc0);
	reg_w_val(gspca_dev, 0x00fc, 0xe1);
	reg_w_val(gspca_dev, 0x0000, 0x00);
	/* wait for completion */
	retry = 50;
	while (retry--) {
		reg_r(gspca_dev->dev, 0x0002, &val, 1);
		reg_r(gspca_dev, 0x0002, 1);
							/* 0x07 until 0x00 */
		if (val == 0x00)
		if (gspca_dev->usb_buf[0] == 0x00)
			break;
		val = 0x00;
		reg_w(gspca_dev->dev, 0x0053, &val, 1);
		reg_w_val(gspca_dev, 0x0053, 0x00);
	}
	if (retry == 0)
		PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
	/* send the qtable now */
	reg_r(gspca_dev->dev, 0x0001, &val, 1);		/* -> 0x18 */
	reg_r(gspca_dev, 0x0001, 1);		/* -> 0x18 */
	length = 8;
	for (i = 0; i < 18; i++) {
		if (i == 17)
			length = 2;
		reg_w(gspca_dev->dev, 0x0008, cxjpeg_qtable[i], length);
		reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);

	}
	reg_r(gspca_dev->dev, 0x0002, &val, 1);	/* 0x00 */
	reg_r(gspca_dev->dev, 0x0053, &val, 1);	/* 0x00 */
	val = 0x02;
	reg_w(gspca_dev->dev, 0x0054, &val, 1);
	val = 0x01;
	reg_w(gspca_dev->dev, 0x0054, &val, 1);
	val = 0x94;
	reg_w(gspca_dev->dev, 0x0000, &val, 1);
	val = 0xc0;
	reg_w(gspca_dev->dev, 0x0053, &val, 1);

	reg_r(gspca_dev->dev, 0x0038, &val, 1);	/* 0x40 */
	reg_r(gspca_dev->dev, 0x0038, &val, 1);	/* 0x40 */
	reg_r(gspca_dev->dev, 0x001f, &val, 1);	/* 0x38 */
	reg_w(gspca_dev->dev, 0x0012, reg12, 5);
	reg_w(gspca_dev->dev, 0x00e5, regE5_8, 8);
	reg_r(gspca_dev->dev, 0x00e8, bufread, 8);
	reg_w(gspca_dev->dev, 0x00e5, regE5a, 4);
	reg_r(gspca_dev->dev, 0x00e8, &val, 1);	/* 0x00 */
	val = 0x01;
	reg_w(gspca_dev->dev, 0x009a, &val, 1);
	reg_w(gspca_dev->dev, 0x00e5, regE5b, 4);
	reg_r(gspca_dev->dev, 0x00e8, &val, 1);	/* 0x00 */
	reg_w(gspca_dev->dev, 0x00e5, regE5c, 4);
	reg_r(gspca_dev->dev, 0x00e8, &val, 1);	/* 0x00 */

	reg_w(gspca_dev->dev, 0x0051, reg51, 2);
	reg_w(gspca_dev->dev, 0x0010, reg10, 2);
	reg_w(gspca_dev->dev, 0x0070, &reg70, 1);
	reg_r(gspca_dev, 0x0002, 1);	/* 0x00 */
	reg_r(gspca_dev, 0x0053, 1);	/* 0x00 */
	reg_w_val(gspca_dev, 0x0054, 0x02);
	reg_w_val(gspca_dev, 0x0054, 0x01);
	reg_w_val(gspca_dev, 0x0000, 0x94);
	reg_w_val(gspca_dev, 0x0053, 0xc0);

	reg_r(gspca_dev, 0x0038, 1);		/* 0x40 */
	reg_r(gspca_dev, 0x0038, 1);		/* 0x40 */
	reg_r(gspca_dev, 0x001f, 1);		/* 0x38 */
	reg_w(gspca_dev, 0x0012, reg12, 5);
	reg_w(gspca_dev, 0x00e5, regE5_8, 8);
	reg_r(gspca_dev, 0x00e8, 8);
	reg_w(gspca_dev, 0x00e5, regE5a, 4);
	reg_r(gspca_dev, 0x00e8, 1);		/* 0x00 */
	reg_w_val(gspca_dev, 0x009a, 0x01);
	reg_w(gspca_dev, 0x00e5, regE5b, 4);
	reg_r(gspca_dev, 0x00e8, 1);		/* 0x00 */
	reg_w(gspca_dev, 0x00e5, regE5c, 4);
	reg_r(gspca_dev, 0x00e8, 1);		/* 0x00 */

	reg_w(gspca_dev, 0x0051, reg51, 2);
	reg_w(gspca_dev, 0x0010, reg10, 2);
	reg_w_val(gspca_dev, 0x0070, reg70);
}

static void cx11646_init1(struct gspca_dev *gspca_dev)
{
	__u8 val;
	int i = 0;

	val = 0;
	reg_w(gspca_dev->dev, 0x0010, &val, 1);
	reg_w(gspca_dev->dev, 0x0053, &val, 1);
	reg_w(gspca_dev->dev, 0x0052, &val, 1);
	val = 0x2f;
	reg_w(gspca_dev->dev, 0x009b, &val, 1);
	val = 0x10;
	reg_w(gspca_dev->dev, 0x009c, &val, 1);
	reg_r(gspca_dev->dev, 0x0098, &val, 1);
	val = 0x40;
	reg_w(gspca_dev->dev, 0x0098, &val, 1);
	reg_r(gspca_dev->dev, 0x0099, &val, 1);
	val = 0x07;
	reg_w(gspca_dev->dev, 0x0099, &val, 1);
	val = 0x40;
	reg_w(gspca_dev->dev, 0x0039, &val, 1);
	val = 0xff;
	reg_w(gspca_dev->dev, 0x003c, &val, 1);
	val = 0x1f;
	reg_w(gspca_dev->dev, 0x003f, &val, 1);
	val = 0x40;
	reg_w(gspca_dev->dev, 0x003d, &val, 1);
/*	val= 0x60; */
/*	reg_w(gspca_dev->dev, 0x00, 0x00, 0x003d, &val, 1); */
	reg_r(gspca_dev->dev, 0x0099, &val, 1);			/* ->0x07 */
	reg_w_val(gspca_dev, 0x0010, 0x00);
	reg_w_val(gspca_dev, 0x0053, 0x00);
	reg_w_val(gspca_dev, 0x0052, 0x00);
	reg_w_val(gspca_dev, 0x009b, 0x2f);
	reg_w_val(gspca_dev, 0x009c, 0x10);
	reg_r(gspca_dev, 0x0098, 1);
	reg_w_val(gspca_dev, 0x0098, 0x40);
	reg_r(gspca_dev, 0x0099, 1);
	reg_w_val(gspca_dev, 0x0099, 0x07);
	reg_w_val(gspca_dev, 0x0039, 0x40);
	reg_w_val(gspca_dev, 0x003c, 0xff);
	reg_w_val(gspca_dev, 0x003f, 0x1f);
	reg_w_val(gspca_dev, 0x003d, 0x40);
/*	reg_w_val(gspca_dev, 0x003d, 0x60); */
	reg_r(gspca_dev, 0x0099, 1);			/* ->0x07 */

	while (cx_sensor_init[i][0]) {
		reg_w(gspca_dev->dev, 0x00e5, cx_sensor_init[i], 1);
		reg_r(gspca_dev->dev, 0x00e8, &val, 1);		/* -> 0x00 */
		reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
		reg_r(gspca_dev, 0x00e8, 1);		/* -> 0x00 */
		if (i == 1) {
			val = 1;
			reg_w(gspca_dev->dev, 0x00ed, &val, 1);
			reg_r(gspca_dev->dev, 0x00ed, &val, 1);	/* -> 0x01 */
			reg_w_val(gspca_dev, 0x00ed, 0x01);
			reg_r(gspca_dev, 0x00ed, 1);	/* -> 0x01 */
		}
		i++;
	}
	val = 0x00;
	reg_w(gspca_dev->dev, 0x00c3, &val, 1);
	reg_w_val(gspca_dev, 0x00c3, 0x00);
}

/* this function is called at probe time */
@@ -880,29 +856,23 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
static void sd_stop0(struct gspca_dev *gspca_dev)
{
	int retry = 50;
	__u8 val;

	val = 0;
	reg_w(gspca_dev->dev, 0x0000, &val, 1);
	reg_r(gspca_dev->dev, 0x0002, &val, 1);
	val = 0;
	reg_w(gspca_dev->dev, 0x0053, &val, 1);
	reg_w_val(gspca_dev, 0x0000, 0x00);
	reg_r(gspca_dev, 0x0002, 1);
	reg_w_val(gspca_dev, 0x0053, 0x00);

	while (retry--) {
/*		reg_r(gspca_dev->dev, 0x0002, &val, 1);*/
		reg_r(gspca_dev->dev, 0x0053, &val, 1);
		if (val == 0)
/*		reg_r(gspca_dev, 0x0002, 1);*/
		reg_r(gspca_dev, 0x0053, 1);
		if (gspca_dev->usb_buf[0] == 0)
			break;
	}
	val = 0;
	reg_w(gspca_dev->dev, 0x0000, &val, 1);
	reg_r(gspca_dev->dev, 0x0002, &val, 1);

	val = 0;
	reg_w(gspca_dev->dev, 0x0010, &val, 1);
	reg_r(gspca_dev->dev, 0x0033, &val, 1);
	val = 0xe0;
	reg_w(gspca_dev->dev, 0x00fc, &val, 1);
	reg_w_val(gspca_dev, 0x0000, 0x00);
	reg_r(gspca_dev, 0x0002, 1);

	reg_w_val(gspca_dev, 0x0010, 0x00);
	reg_r(gspca_dev, 0x0033, 1);
	reg_w_val(gspca_dev, 0x00fc, 0xe0);
}

static void sd_close(struct gspca_dev *gspca_dev)
@@ -937,22 +907,20 @@ static void setbrightness(struct gspca_dev*gspca_dev)
	__u8 reg51c[2];
	__u8 bright;
	__u8 colors;
	__u8 val;
	__u8 bufread[8];

	bright = sd->brightness;
	regE5cbx[2] = bright;
	reg_w(gspca_dev->dev, 0x00e5, regE5cbx, 8);
	reg_r(gspca_dev->dev, 0x00e8, bufread, 8);
	reg_w(gspca_dev->dev, 0x00e5, regE5c, 4);
	reg_r(gspca_dev->dev, 0x00e8, &val, 1);	/* 0x00 */
	reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
	reg_r(gspca_dev, 0x00e8, 8);
	reg_w(gspca_dev, 0x00e5, regE5c, 4);
	reg_r(gspca_dev, 0x00e8, 1);		/* 0x00 */

	colors = sd->colors;
	reg51c[0] = 0x77;
	reg51c[1] = colors;
	reg_w(gspca_dev->dev, 0x0051, reg51c, 2);
	reg_w(gspca_dev->dev, 0x0010, reg10, 2);
	reg_w(gspca_dev->dev, 0x0070, &reg70, 1);
	reg_w(gspca_dev, 0x0051, reg51c, 2);
	reg_w(gspca_dev, 0x0010, reg10, 2);
	reg_w_val(gspca_dev, 0x0070, reg70);
}

static void setcontrast(struct gspca_dev*gspca_dev)
@@ -961,16 +929,15 @@ static void setcontrast(struct gspca_dev*gspca_dev)
	__u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 };	/* seem MSB */
/*	__u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01};	 * LSB */
	__u8 reg51c[2];
	__u8 val;

	regE5acx[2] = sd->contrast;
	reg_w(gspca_dev->dev, 0x00e5, regE5acx, 4);
	reg_r(gspca_dev->dev, 0x00e8, &val, 1);	/* 0x00 */
	reg_w(gspca_dev, 0x00e5, regE5acx, 4);
	reg_r(gspca_dev, 0x00e8, 1);		/* 0x00 */
	reg51c[0] = 0x77;
	reg51c[1] = sd->colors;
	reg_w(gspca_dev->dev, 0x0051, reg51c, 2);
	reg_w(gspca_dev->dev, 0x0010, reg10, 2);
	reg_w(gspca_dev->dev, 0x0070, &reg70, 1);
	reg_w(gspca_dev, 0x0051, reg51c, 2);
	reg_w(gspca_dev, 0x0010, reg10, 2);
	reg_w_val(gspca_dev, 0x0070, reg70);
}

static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
+222 −221

File changed.

Preview size limit exceeded, changes collapsed.

+4 −2
Original line number Diff line number Diff line
@@ -1347,9 +1347,11 @@ static int frame_wait(struct gspca_dev *gspca_dev,
		gspca_dev->fr_i,
		gspca_dev->fr_o);

	if (gspca_dev->sd_desc->dq_callback)
	if (gspca_dev->sd_desc->dq_callback) {
		mutex_lock(&gspca_dev->usb_lock);
		gspca_dev->sd_desc->dq_callback(gspca_dev);

		mutex_unlock(&gspca_dev->usb_lock);
	}
	return j;
}

+1 −0
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@ struct gspca_dev {
	struct cam cam;				/* device information */
	const struct sd_desc *sd_desc;		/* subdriver description */

	__u8 usb_buf[8];			/* buffer for USB exchanges */
	struct urb *urb[MAX_NURBS];

	__u8 *frbuf;				/* buffer for nframes */
+85 −73
Original line number Diff line number Diff line
@@ -24,8 +24,8 @@
#include "gspca.h"
#include "jpeg.h"

#define DRIVER_VERSION_NUMBER	KERNEL_VERSION(2, 1, 5)
static const char version[] = "2.1.5";
#define DRIVER_VERSION_NUMBER	KERNEL_VERSION(2, 1, 7)
static const char version[] = "2.1.7";

MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver");
@@ -83,39 +83,53 @@ enum {
	REG_HW_MI_63,
	REG_HW_MI_64,
	REG_HW_MI_F1 = 0xf1,
	ATTR_TOTAL_MI_REG = 242
	ATTR_TOTAL_MI_REG = 0xf2
};

static int pcam_reg_write(struct usb_device *dev,
			  __u16 index, __u8 *value, int len)
/* the bytes to write are in gspca_dev->usb_buf */
static int reg_w(struct gspca_dev *gspca_dev,
		 __u16 index, int len)
{
	int rc;

	rc = usb_control_msg(dev,
			 usb_sndbulkpipe(dev, 4),
	rc = usb_control_msg(gspca_dev->dev,
			 usb_sndbulkpipe(gspca_dev->dev, 4),
			 0x12,
/*		?? 0xc8 = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_??? !? */
			 0xc8,
			 0xc8,		/* ?? */
			 0,		/* value */
			 index, value, len, 500);
			 index, gspca_dev->usb_buf, len, 500);
	if (rc < 0)
		PDEBUG(D_ERR, "reg write [%02x] error %d", index, rc);
	return rc;
}

static void MISensor_BulkWrite(struct usb_device *dev,
				unsigned short *pch,
				char Address)
static int reg_w_buf(struct gspca_dev *gspca_dev,
			__u16 index, __u8 *buf, int len)
{
	__u8 data[6];
	int rc;

	rc = usb_control_msg(gspca_dev->dev,
			 usb_sndbulkpipe(gspca_dev->dev, 4),
			 0x12,
			 0xc8,		/* ?? */
			 0,		/* value */
			 index, buf, len, 500);
	if (rc < 0)
		PDEBUG(D_ERR, "reg write [%02x] error %d", index, rc);
	return rc;
}

	data[0] = 0x1f;
	data[1] = 0;			/* control byte */
	data[2] = Address;
	data[3] = *pch >> 8;		/* high byte */
	data[4] = *pch;			/* low byte */
static void bulk_w(struct gspca_dev *gspca_dev,
		   __u16 *pch,
		   __u16 Address)
{
	gspca_dev->usb_buf[0] = 0x1f;
	gspca_dev->usb_buf[1] = 0;			/* control byte */
	gspca_dev->usb_buf[2] = Address;
	gspca_dev->usb_buf[3] = *pch >> 8;		/* high byte */
	gspca_dev->usb_buf[4] = *pch;			/* low byte */

	pcam_reg_write(dev, Address, data, 5);
	reg_w(gspca_dev, Address, 5);
}

/* this function is called at probe time */
@@ -142,33 +156,30 @@ static int sd_open(struct gspca_dev *gspca_dev)

static void sd_start(struct gspca_dev *gspca_dev)
{
	struct usb_device *dev = gspca_dev->dev;
	int err_code;
	__u8 data[12];
	__u16 MI_buf[242];
	__u8 *data;
	__u16 *MI_buf;
	int h_size, v_size;
	int intpipe;
/*	struct usb_device *dev = pcam->dev; */

	memset(data, 0, sizeof data);
	memset(MI_buf, 0, sizeof MI_buf);

	PDEBUG(D_STREAM, "camera start, iface %d, alt 8", gspca_dev->iface);
	if (usb_set_interface(dev, gspca_dev->iface, 8) < 0) {
	if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 8) < 0) {
		PDEBUG(D_ERR|D_STREAM, "Set packet size: set interface error");
		return;
	}

	data = gspca_dev->usb_buf;
	data[0] = 0x01;		/* address */
	data[1] = 0x01;

	err_code = pcam_reg_write(dev, data[0], data, 2);
	err_code = reg_w(gspca_dev, data[0], 2);
	if (err_code < 0)
		return;

	/*
	   Initialize the MR97113 chip register
	 */
	data = kmalloc(16, GFP_KERNEL);
	data[0] = 0x00;		/* address */
	data[1] = 0x0c | 0x01;	/* reg 0 */
	data[2] = 0x01;		/* reg 1 */
@@ -188,27 +199,27 @@ static void sd_start(struct gspca_dev *gspca_dev)
	data[10] = 0x5d;	/* reg 9, I2C device address
				 *	[for PAS5101 (0x40)] [for MI (0x5d)] */

	err_code = pcam_reg_write(dev, data[0], data, 11);
	err_code = reg_w_buf(gspca_dev, data[0], data, 11);
	kfree(data);
	if (err_code < 0)
		return;

	data = gspca_dev->usb_buf;
	data[0] = 0x23;		/* address */
	data[1] = 0x09;		/* reg 35, append frame header */

	err_code = pcam_reg_write(dev, data[0], data, 2);
	if (err_code < 0) {
		PDEBUG(D_ERR, "Register write failed");
	err_code = reg_w(gspca_dev, data[0], 2);
	if (err_code < 0)
		return;
	}

	data[0] = 0x3C;		/* address */
/*	if (pcam->width == 1280) */
	data[0] = 0x3c;		/* address */
/*	if (gspca_dev->width == 1280) */
/*		data[1] = 200;	 * reg 60, pc-cam frame size
				 *	(unit: 4KB) 800KB */
/*	else */
	data[1] = 50;		/* 50 reg 60, pc-cam frame size
				 *	(unit: 4KB) 200KB */
	err_code = pcam_reg_write(dev, data[0], data, 2);
	err_code = reg_w(gspca_dev, data[0], 2);
	if (err_code < 0)
		return;

@@ -250,19 +261,20 @@ static void sd_start(struct gspca_dev *gspca_dev)
	/* auto dark-gain */
	data[0] = 0x5e;		/* address */

	err_code = pcam_reg_write(dev, data[0], data, 6);
	err_code = reg_w(gspca_dev, data[0], 6);
	if (err_code < 0)
		return;

	data[0] = 0x67;
	data[1] = 0x13;		/* reg 103, first pixel B, disable sharpness */
	err_code = pcam_reg_write(dev, data[0], data, 2);
	err_code = reg_w(gspca_dev, data[0], 2);
	if (err_code < 0)
		return;

	/*
	 * initialize the value of MI sensor...
	 */
	MI_buf = kzalloc(ATTR_TOTAL_MI_REG * sizeof *MI_buf, GFP_KERNEL);
	MI_buf[REG_HW_MI_1] = 0x000a;
	MI_buf[REG_HW_MI_2] = 0x000c;
	MI_buf[REG_HW_MI_3] = 0x0405;
@@ -304,48 +316,48 @@ static void sd_start(struct gspca_dev *gspca_dev)
	}
	MI_buf[0x20] = 0x1104;

	MISensor_BulkWrite(dev, MI_buf + 1, 1);
	MISensor_BulkWrite(dev, MI_buf + 2, 2);
	MISensor_BulkWrite(dev, MI_buf + 3, 3);
	MISensor_BulkWrite(dev, MI_buf + 4, 4);
	MISensor_BulkWrite(dev, MI_buf + 5, 5);
	MISensor_BulkWrite(dev, MI_buf + 6, 6);
	MISensor_BulkWrite(dev, MI_buf + 7, 7);
	MISensor_BulkWrite(dev, MI_buf + 9, 9);
	MISensor_BulkWrite(dev, MI_buf + 0x0b, 0x0b);
	MISensor_BulkWrite(dev, MI_buf + 0x0c, 0x0c);
	MISensor_BulkWrite(dev, MI_buf + 0x0d, 0x0d);
	MISensor_BulkWrite(dev, MI_buf + 0x1e, 0x1e);
	MISensor_BulkWrite(dev, MI_buf + 0x20, 0x20);
	MISensor_BulkWrite(dev, MI_buf + 0x2b, 0x2b);
	MISensor_BulkWrite(dev, MI_buf + 0x2c, 0x2c);
	MISensor_BulkWrite(dev, MI_buf + 0x2d, 0x2d);
	MISensor_BulkWrite(dev, MI_buf + 0x2e, 0x2e);
	MISensor_BulkWrite(dev, MI_buf + 0x35, 0x35);
	MISensor_BulkWrite(dev, MI_buf + 0x5f, 0x5f);
	MISensor_BulkWrite(dev, MI_buf + 0x60, 0x60);
	MISensor_BulkWrite(dev, MI_buf + 0x61, 0x61);
	MISensor_BulkWrite(dev, MI_buf + 0x62, 0x62);
	MISensor_BulkWrite(dev, MI_buf + 0x63, 0x63);
	MISensor_BulkWrite(dev, MI_buf + 0x64, 0x64);
	MISensor_BulkWrite(dev, MI_buf + 0xf1, 0xf1);

	intpipe = usb_sndintpipe(dev, 0);
	err_code = usb_clear_halt(dev, intpipe);
	bulk_w(gspca_dev, MI_buf + 1, 1);
	bulk_w(gspca_dev, MI_buf + 2, 2);
	bulk_w(gspca_dev, MI_buf + 3, 3);
	bulk_w(gspca_dev, MI_buf + 4, 4);
	bulk_w(gspca_dev, MI_buf + 5, 5);
	bulk_w(gspca_dev, MI_buf + 6, 6);
	bulk_w(gspca_dev, MI_buf + 7, 7);
	bulk_w(gspca_dev, MI_buf + 9, 9);
	bulk_w(gspca_dev, MI_buf + 0x0b, 0x0b);
	bulk_w(gspca_dev, MI_buf + 0x0c, 0x0c);
	bulk_w(gspca_dev, MI_buf + 0x0d, 0x0d);
	bulk_w(gspca_dev, MI_buf + 0x1e, 0x1e);
	bulk_w(gspca_dev, MI_buf + 0x20, 0x20);
	bulk_w(gspca_dev, MI_buf + 0x2b, 0x2b);
	bulk_w(gspca_dev, MI_buf + 0x2c, 0x2c);
	bulk_w(gspca_dev, MI_buf + 0x2d, 0x2d);
	bulk_w(gspca_dev, MI_buf + 0x2e, 0x2e);
	bulk_w(gspca_dev, MI_buf + 0x35, 0x35);
	bulk_w(gspca_dev, MI_buf + 0x5f, 0x5f);
	bulk_w(gspca_dev, MI_buf + 0x60, 0x60);
	bulk_w(gspca_dev, MI_buf + 0x61, 0x61);
	bulk_w(gspca_dev, MI_buf + 0x62, 0x62);
	bulk_w(gspca_dev, MI_buf + 0x63, 0x63);
	bulk_w(gspca_dev, MI_buf + 0x64, 0x64);
	bulk_w(gspca_dev, MI_buf + 0xf1, 0xf1);
	kfree(MI_buf);

	intpipe = usb_sndintpipe(gspca_dev->dev, 0);
	err_code = usb_clear_halt(gspca_dev->dev, intpipe);

	data[0] = 0x00;
	data[1] = 0x4d;		/* ISOC transfering enable... */
	pcam_reg_write(dev, data[0], data, 2);
	reg_w(gspca_dev, data[0], 2);
}

static void sd_stopN(struct gspca_dev *gspca_dev)
{
	int result;
	__u8 data[2];

	data[0] = 1;
	data[1] = 0;
	result = pcam_reg_write(gspca_dev->dev, data[0], data, 2);
	gspca_dev->usb_buf[0] = 1;
	gspca_dev->usb_buf[1] = 0;
	result = reg_w(gspca_dev, gspca_dev->usb_buf[0], 2);
	if (result < 0)
		PDEBUG(D_ERR, "Camera Stop failed");
}
Loading