linux/samples/v4l/v4l2-pci-skeleton.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * This is a V4L2 PCI Skeleton Driver. It gives an initial skeleton source
 * for use with other PCI drivers.
 *
 * This skeleton PCI driver assumes that the card has an S-Video connector as
 * input 0 and an HDMI connector as input 1.
 *
 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
 */

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kmod.h>
#include <linux/mutex.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/videodev2.h>
#include <linux/v4l2-dv-timings.h>
#include <media/v4l2-device.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-dv-timings.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h>
#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();

/**
 * struct skeleton - All internal data for one instance of device
 * @pdev: PCI device
 * @v4l2_dev: top-level v4l2 device struct
 * @vdev: video node structure
 * @ctrl_handler: control handler structure
 * @lock: ioctl serialization mutex
 * @std: current SDTV standard
 * @timings: current HDTV timings
 * @format: current pix format
 * @input: current video input (0 = SDTV, 1 = HDTV)
 * @queue: vb2 video capture queue
 * @qlock: spinlock controlling access to buf_list and sequence
 * @buf_list: list of buffers queued for DMA
 * @field: the field (TOP/BOTTOM/other) of the current buffer
 * @sequence: frame sequence counter
 */
struct skeleton {};

struct skel_buffer {};

static inline struct skel_buffer *to_skel_buffer(struct vb2_v4l2_buffer *vbuf)
{}

static const struct pci_device_id skeleton_pci_tbl[] =;
MODULE_DEVICE_TABLE(pci, skeleton_pci_tbl);

/*
 * HDTV: this structure has the capabilities of the HDTV receiver.
 * It is used to constrain the huge list of possible formats based
 * upon the hardware capabilities.
 */
static const struct v4l2_dv_timings_cap skel_timings_cap =;

/*
 * Supported SDTV standards. This does the same job as skel_timings_cap, but
 * for standard TV formats.
 */
#define SKEL_TVNORMS

/*
 * Interrupt handler: typically interrupts happen after a new frame has been
 * captured. It is the job of the handler to remove the new frame from the
 * internal list and give it back to the vb2 framework, updating the sequence
 * counter, field and timestamp at the same time.
 */
static irqreturn_t skeleton_irq(int irq, void *dev_id)
{}

/*
 * Setup the constraints of the queue: besides setting the number of planes
 * per buffer and the size and allocation context of each plane, it also
 * checks if sufficient buffers have been allocated. Usually 3 is a good
 * minimum number: many DMA engines need a minimum of 2 buffers in the
 * queue and you need to have another available for userspace processing.
 */
static int queue_setup(struct vb2_queue *vq,
		       unsigned int *nbuffers, unsigned int *nplanes,
		       unsigned int sizes[], struct device *alloc_devs[])
{}

/*
 * Prepare the buffer for queueing to the DMA engine: check and set the
 * payload size.
 */
static int buffer_prepare(struct vb2_buffer *vb)
{}

/*
 * Queue this buffer to the DMA engine.
 */
static void buffer_queue(struct vb2_buffer *vb)
{}

static void return_all_buffers(struct skeleton *skel,
			       enum vb2_buffer_state state)
{}

/*
 * Start streaming. First check if the minimum number of buffers have been
 * queued. If not, then return -ENOBUFS and the vb2 framework will call
 * this function again the next time a buffer has been queued until enough
 * buffers are available to actually start the DMA engine.
 */
static int start_streaming(struct vb2_queue *vq, unsigned int count)
{}

/*
 * Stop the DMA engine. Any remaining buffers in the DMA queue are dequeued
 * and passed on to the vb2 framework marked as STATE_ERROR.
 */
static void stop_streaming(struct vb2_queue *vq)
{}

/*
 * The vb2 queue ops. Note that since q->lock is set we can use the standard
 * vb2_ops_wait_prepare/finish helper functions. If q->lock would be NULL,
 * then this driver would have to provide these ops.
 */
static const struct vb2_ops skel_qops =;

/*
 * Required ioctl querycap. Note that the version field is prefilled with
 * the version of the kernel.
 */
static int skeleton_querycap(struct file *file, void *priv,
			     struct v4l2_capability *cap)
{}

/*
 * Helper function to check and correct struct v4l2_pix_format. It's used
 * not only in VIDIOC_TRY/S_FMT, but also elsewhere if changes to the SDTV
 * standard, HDTV timings or the video input would require updating the
 * current format.
 */
static void skeleton_fill_pix_format(struct skeleton *skel,
				     struct v4l2_pix_format *pix)
{}

static int skeleton_try_fmt_vid_cap(struct file *file, void *priv,
				    struct v4l2_format *f)
{}

static int skeleton_s_fmt_vid_cap(struct file *file, void *priv,
				  struct v4l2_format *f)
{}

static int skeleton_g_fmt_vid_cap(struct file *file, void *priv,
				  struct v4l2_format *f)
{}

static int skeleton_enum_fmt_vid_cap(struct file *file, void *priv,
				     struct v4l2_fmtdesc *f)
{}

static int skeleton_s_std(struct file *file, void *priv, v4l2_std_id std)
{}

static int skeleton_g_std(struct file *file, void *priv, v4l2_std_id *std)
{}

/*
 * Query the current standard as seen by the hardware. This function shall
 * never actually change the standard, it just detects and reports.
 * The framework will initially set *std to tvnorms (i.e. the set of
 * supported standards by this input), and this function should just AND
 * this value. If there is no signal, then *std should be set to 0.
 */
static int skeleton_querystd(struct file *file, void *priv, v4l2_std_id *std)
{}

static int skeleton_s_dv_timings(struct file *file, void *_fh,
				 struct v4l2_dv_timings *timings)
{}

static int skeleton_g_dv_timings(struct file *file, void *_fh,
				 struct v4l2_dv_timings *timings)
{}

static int skeleton_enum_dv_timings(struct file *file, void *_fh,
				    struct v4l2_enum_dv_timings *timings)
{}

/*
 * Query the current timings as seen by the hardware. This function shall
 * never actually change the timings, it just detects and reports.
 * If no signal is detected, then return -ENOLINK. If the hardware cannot
 * lock to the signal, then return -ENOLCK. If the signal is out of range
 * of the capabilities of the system (e.g., it is possible that the receiver
 * can lock but that the DMA engine it is connected to cannot handle
 * pixelclocks above a certain frequency), then -ERANGE is returned.
 */
static int skeleton_query_dv_timings(struct file *file, void *_fh,
				     struct v4l2_dv_timings *timings)
{}

static int skeleton_dv_timings_cap(struct file *file, void *fh,
				   struct v4l2_dv_timings_cap *cap)
{}

static int skeleton_enum_input(struct file *file, void *priv,
			       struct v4l2_input *i)
{}

static int skeleton_s_input(struct file *file, void *priv, unsigned int i)
{}

static int skeleton_g_input(struct file *file, void *priv, unsigned int *i)
{}

/* The control handler. */
static int skeleton_s_ctrl(struct v4l2_ctrl *ctrl)
{}

/* ------------------------------------------------------------------
	File operations for the device
   ------------------------------------------------------------------*/

static const struct v4l2_ctrl_ops skel_ctrl_ops =;

/*
 * The set of all supported ioctls. Note that all the streaming ioctls
 * use the vb2 helper functions that take care of all the locking and
 * that also do ownership tracking (i.e. only the filehandle that requested
 * the buffers can call the streaming ioctls, all other filehandles will
 * receive -EBUSY if they attempt to call the same streaming ioctls).
 *
 * The last three ioctls also use standard helper functions: these implement
 * standard behavior for drivers with controls.
 */
static const struct v4l2_ioctl_ops skel_ioctl_ops =;

/*
 * The set of file operations. Note that all these ops are standard core
 * helper functions.
 */
static const struct v4l2_file_operations skel_fops =;

/*
 * The initial setup of this device instance. Note that the initial state of
 * the driver should be complete. So the initial format, standard, timings
 * and video input should all be initialized to some reasonable value.
 */
static int skeleton_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{}

static void skeleton_remove(struct pci_dev *pdev)
{}

static struct pci_driver skeleton_driver =;

module_pci_driver();