drivers/media/v4l2-core/v4l2-dev.c

Source file repositories/reference/linux-study-clean/drivers/media/v4l2-core/v4l2-dev.c

File Facts

System
Linux kernel
Corpus path
drivers/media/v4l2-core/v4l2-dev.c
Extension
.c
Size
38737 bytes
Lines
1264
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations v4l2_fops = {
	.owner = THIS_MODULE,
	.read = v4l2_read,
	.write = v4l2_write,
	.open = v4l2_open,
	.get_unmapped_area = v4l2_get_unmapped_area,
	.mmap = v4l2_mmap,
	.unlocked_ioctl = v4l2_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl = v4l2_compat_ioctl32,
#endif
	.release = v4l2_release,
	.poll = v4l2_poll,
};

/**
 * get_index - assign stream index number based on v4l2_dev
 * @vdev: video_device to assign index number to, vdev->v4l2_dev should be assigned
 *
 * Note that when this is called the new device has not yet been registered
 * in the video_device array, but it was able to obtain a minor number.
 *
 * This means that we can always obtain a free stream index number since
 * the worst case scenario is that there are VIDEO_NUM_DEVICES - 1 slots in
 * use of the video_device array.
 *
 * Returns a free index number.
 */
static int get_index(struct video_device *vdev)
{
	/* This can be static since this function is called with the global
	   videodev_lock held. */
	static DECLARE_BITMAP(used, VIDEO_NUM_DEVICES);
	int i;

	bitmap_zero(used, VIDEO_NUM_DEVICES);

	for (i = 0; i < VIDEO_NUM_DEVICES; i++) {
		if (video_devices[i] != NULL &&
		    video_devices[i]->v4l2_dev == vdev->v4l2_dev) {
			__set_bit(video_devices[i]->index, used);
		}
	}

	return find_first_zero_bit(used, VIDEO_NUM_DEVICES);
}

#define SET_VALID_IOCTL(ops, cmd, op) \
	do { if ((ops)->op) __set_bit(_IOC_NR(cmd), valid_ioctls); } while (0)

/* This determines which ioctls are actually implemented in the driver.
   It's a one-time thing which simplifies video_ioctl2 as it can just do
   a bit test.

   Note that drivers can override this by setting bits to 1 in
   vdev->valid_ioctls. If an ioctl is marked as 1 when this function is
   called, then that ioctl will actually be marked as unimplemented.

   It does that by first setting up the local valid_ioctls bitmap, and
   at the end do a:

   vdev->valid_ioctls = valid_ioctls & ~(vdev->valid_ioctls)
 */
static void determine_valid_ioctls(struct video_device *vdev)
{
	const u32 vid_caps = V4L2_CAP_VIDEO_CAPTURE |
			     V4L2_CAP_VIDEO_CAPTURE_MPLANE |
			     V4L2_CAP_VIDEO_OUTPUT |
			     V4L2_CAP_VIDEO_OUTPUT_MPLANE |
			     V4L2_CAP_VIDEO_M2M | V4L2_CAP_VIDEO_M2M_MPLANE;
	const u32 meta_caps = V4L2_CAP_META_CAPTURE |
			      V4L2_CAP_META_OUTPUT;
	DECLARE_BITMAP(valid_ioctls, BASE_VIDIOC_PRIVATE);
	const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
	bool is_vid = vdev->vfl_type == VFL_TYPE_VIDEO &&
		      (vdev->device_caps & vid_caps);
	bool is_vbi = vdev->vfl_type == VFL_TYPE_VBI;
	bool is_radio = vdev->vfl_type == VFL_TYPE_RADIO;
	bool is_sdr = vdev->vfl_type == VFL_TYPE_SDR;
	bool is_tch = vdev->vfl_type == VFL_TYPE_TOUCH;
	bool is_meta = vdev->vfl_type == VFL_TYPE_VIDEO &&
		       (vdev->device_caps & meta_caps);
	bool is_rx = vdev->vfl_dir != VFL_DIR_TX;
	bool is_tx = vdev->vfl_dir != VFL_DIR_RX;
	bool is_io_mc = vdev->device_caps & V4L2_CAP_IO_MC;
	bool has_streaming = vdev->device_caps & V4L2_CAP_STREAMING;
	bool is_edid =  vdev->device_caps & V4L2_CAP_EDID;

	bitmap_zero(valid_ioctls, BASE_VIDIOC_PRIVATE);

Annotation

Implementation Notes