drivers/media/usb/gspca/touptek.c

Source file repositories/reference/linux-study-clean/drivers/media/usb/gspca/touptek.c

File Facts

System
Linux kernel
Corpus path
drivers/media/usb/gspca/touptek.c
Extension
.c
Size
20846 bytes
Lines
713
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct sd {
	struct gspca_dev gspca_dev;	/* !! must be the first item */
	/* How many bytes this frame */
	unsigned int this_f;

	/*
	Device has separate gains for each Bayer quadrant
	V4L supports master gain which is referenced to G1/G2 and supplies
	individual balance controls for R/B
	*/
	struct v4l2_ctrl *blue;
	struct v4l2_ctrl *red;
};

/* Used to simplify reg write error handling */
struct cmd {
	u16 value;
	u16 index;
};

static const struct v4l2_pix_format vga_mode[] = {
	{800, 600,
		V4L2_PIX_FMT_SGRBG8,
		V4L2_FIELD_NONE,
		.bytesperline = 800,
		.sizeimage = 800 * 600,
		.colorspace = V4L2_COLORSPACE_SRGB},
	{1600, 1200,
		V4L2_PIX_FMT_SGRBG8,
		V4L2_FIELD_NONE,
		.bytesperline = 1600,
		.sizeimage = 1600 * 1200,
		.colorspace = V4L2_COLORSPACE_SRGB},
	{3264, 2448,
		V4L2_PIX_FMT_SGRBG8,
		V4L2_FIELD_NONE,
		.bytesperline = 3264,
		.sizeimage = 3264 * 2448,
		.colorspace = V4L2_COLORSPACE_SRGB},
};

/*
 * As there's no known frame sync, the only way to keep synced is to try hard
 * to never miss any packets
 */
#if MAX_NURBS < 4
#error "Not enough URBs in the gspca table"
#endif

static int val_reply(struct gspca_dev *gspca_dev, const char *reply, int rc)
{
	if (rc < 0) {
		gspca_err(gspca_dev, "reply has error %d\n", rc);
		return -EIO;
	}
	if (rc != 1) {
		gspca_err(gspca_dev, "Bad reply size %d\n", rc);
		return -EIO;
	}
	if (reply[0] != 0x08) {
		gspca_err(gspca_dev, "Bad reply 0x%02x\n", (int)reply[0]);
		return -EIO;
	}
	return 0;
}

static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index)
{
	char *buff = gspca_dev->usb_buf;
	int rc;

	gspca_dbg(gspca_dev, D_USBO,
		  "reg_w bReq=0x0B, bReqT=0xC0, wVal=0x%04X, wInd=0x%04X\n\n",
		  value, index);
	rc = usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0),
		0x0B, 0xC0, value, index, buff, 1, 500);
	gspca_dbg(gspca_dev, D_USBO, "rc=%d, ret={0x%02x}\n", rc, (int)buff[0]);
	if (rc < 0) {
		gspca_err(gspca_dev, "Failed reg_w(0x0B, 0xC0, 0x%04X, 0x%04X) w/ rc %d\n",
			  value, index, rc);
		gspca_dev->usb_err = rc;
		return;
	}
	if (val_reply(gspca_dev, buff, rc)) {
		gspca_err(gspca_dev, "Bad reply to reg_w(0x0B, 0xC0, 0x%04X, 0x%04X\n",
			  value, index);
		gspca_dev->usb_err = -EIO;
	}
}

Annotation

Implementation Notes