drivers/media/usb/gspca/finepix.c

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

File Facts

System
Linux kernel
Corpus path
drivers/media/usb/gspca/finepix.c
Extension
.c
Size
7568 bytes
Lines
294
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 usb_fpix {
	struct gspca_dev gspca_dev;	/* !! must be the first item */

	struct work_struct work_struct;
};

/* Delay after which claim the next frame. If the delay is too small,
 * the camera will return old frames. On the 4800Z, 20ms is bad, 25ms
 * will fail every 4 or 5 frames, but 30ms is perfect. On the A210,
 * 30ms is bad while 35ms is perfect. */
#define NEXT_FRAME_DELAY 35

/* These cameras only support 320x200. */
static const struct v4l2_pix_format fpix_mode[1] = {
	{ 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
		.bytesperline = 320,
		.sizeimage = 320 * 240 * 3 / 8 + 590,
		.colorspace = V4L2_COLORSPACE_SRGB,
		.priv = 0}
};

/* send a command to the webcam */
static int command(struct gspca_dev *gspca_dev,
		int order)	/* 0: reset, 1: frame request */
{
	static u8 order_values[2][12] = {
		{0xc6, 0, 0, 0, 0, 0, 0,    0, 0x20, 0, 0, 0},	/* reset */
		{0xd3, 0, 0, 0, 0, 0, 0, 0x01,    0, 0, 0, 0},	/* fr req */
	};

	memcpy(gspca_dev->usb_buf, order_values[order], 12);
	return usb_control_msg(gspca_dev->dev,
			usb_sndctrlpipe(gspca_dev->dev, 0),
			USB_REQ_GET_STATUS,
			USB_DIR_OUT | USB_TYPE_CLASS |
			USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf,
			12, FPIX_TIMEOUT);
}

/*
 * This function is called as a workqueue function and runs whenever the camera
 * is streaming data. Because it is a workqueue function it is allowed to sleep
 * so we can use synchronous USB calls. To avoid possible collisions with other
 * threads attempting to use gspca_dev->usb_buf we take the usb_lock when
 * performing USB operations using it. In practice we don't really need this
 * as the camera doesn't provide any controls.
 */
static void dostream(struct work_struct *work)
{
	struct usb_fpix *dev = container_of(work, struct usb_fpix, work_struct);
	struct gspca_dev *gspca_dev = &dev->gspca_dev;
	struct urb *urb = gspca_dev->urb[0];
	u8 *data = urb->transfer_buffer;
	int ret = 0;
	int len;

	gspca_dbg(gspca_dev, D_STREAM, "dostream started\n");

	/* loop reading a frame */
again:
	while (gspca_dev->present && gspca_dev->streaming) {
#ifdef CONFIG_PM
		if (gspca_dev->frozen)
			break;
#endif

		/* request a frame */
		mutex_lock(&gspca_dev->usb_lock);
		ret = command(gspca_dev, 1);
		mutex_unlock(&gspca_dev->usb_lock);
		if (ret < 0)
			break;
#ifdef CONFIG_PM
		if (gspca_dev->frozen)
			break;
#endif
		if (!gspca_dev->present || !gspca_dev->streaming)
			break;

		/* the frame comes in parts */
		for (;;) {
			ret = usb_bulk_msg(gspca_dev->dev,
					urb->pipe,
					data,
					FPIX_MAX_TRANSFER,
					&len, FPIX_TIMEOUT);
			if (ret < 0) {
				/* Most of the time we get a timeout
				 * error. Just restart. */
				goto again;

Annotation

Implementation Notes