linux/drivers/media/usb/s2255/s2255drv.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  s2255drv.c - a driver for the Sensoray 2255 USB video capture device
 *
 *   Copyright (C) 2007-2014 by Sensoray Company Inc.
 *                              Dean Anderson
 *
 * Some video buffer code based on vivi driver:
 *
 * Sensoray 2255 device supports 4 simultaneous channels.
 * The channels are not "crossbar" inputs, they are physically
 * attached to separate video decoders.
 *
 * Because of USB2.0 bandwidth limitations. There is only a
 * certain amount of data which may be transferred at one time.
 *
 * Example maximum bandwidth utilization:
 *
 * -full size, color mode YUYV or YUV422P: 2 channels at once
 * -full or half size Grey scale: all 4 channels at once
 * -half size, color mode YUYV or YUV422P: all 4 channels at once
 * -full size, color mode YUYV or YUV422P 1/2 frame rate: all 4 channels
 *  at once.
 */

#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/usb.h>
#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-vmalloc.h>
#include <media/v4l2-common.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h>

#define S2255_VERSION
#define FIRMWARE_FILE_NAME

/* default JPEG quality */
#define S2255_DEF_JPEG_QUAL
/* vendor request in */
#define S2255_VR_IN
/* vendor request out */
#define S2255_VR_OUT
/* firmware query */
#define S2255_VR_FW
/* USB endpoint number for configuring the device */
#define S2255_CONFIG_EP
/* maximum time for DSP to start responding after last FW word loaded(ms) */
#define S2255_DSP_BOOTTIME
/* maximum time to wait for firmware to load (ms) */
#define S2255_LOAD_TIMEOUT
#define S2255_MIN_BUFS
#define S2255_SETMODE_TIMEOUT
#define S2255_VIDSTATUS_TIMEOUT
#define S2255_MARKER_FRAME
#define S2255_MARKER_RESPONSE
#define S2255_RESPONSE_SETMODE
#define S2255_RESPONSE_FW
#define S2255_RESPONSE_STATUS
#define S2255_USB_XFER_SIZE
#define MAX_CHANNELS
#define SYS_FRAMES
/* maximum size is PAL full size plus room for the marker header(s) */
#define SYS_FRAMES_MAXSIZE
#define DEF_USB_BLOCK
#define LINE_SZ_4CIFS_NTSC
#define LINE_SZ_2CIFS_NTSC
#define LINE_SZ_1CIFS_NTSC
#define LINE_SZ_4CIFS_PAL
#define LINE_SZ_2CIFS_PAL
#define LINE_SZ_1CIFS_PAL
#define NUM_LINES_4CIFS_NTSC
#define NUM_LINES_2CIFS_NTSC
#define NUM_LINES_1CIFS_NTSC
#define NUM_LINES_4CIFS_PAL
#define NUM_LINES_2CIFS_PAL
#define NUM_LINES_1CIFS_PAL
#define LINE_SZ_DEF
#define NUM_LINES_DEF


/* predefined settings */
#define FORMAT_NTSC
#define FORMAT_PAL

#define SCALE_4CIFS
#define SCALE_2CIFS
#define SCALE_1CIFS
/* SCALE_4CIFSI is the 2 fields interpolated into one */
#define SCALE_4CIFSI

#define COLOR_YUVPL
#define COLOR_YUVPK
#define COLOR_Y8
#define COLOR_JPG

#define MASK_COLOR
#define MASK_JPG_QUALITY
#define MASK_INPUT_TYPE
/* frame decimation. */
#define FDEC_1
#define FDEC_2
#define FDEC_3
#define FDEC_5

/*-------------------------------------------------------
 * Default mode parameters.
 *-------------------------------------------------------*/
#define DEF_SCALE
#define DEF_COLOR
#define DEF_FDEC
#define DEF_BRIGHT
#define DEF_CONTRAST
#define DEF_SATURATION
#define DEF_HUE

/* usb config commands */
#define IN_DATA_TOKEN
#define CMD_2255
#define CMD_SET_MODE
#define CMD_START
#define CMD_STOP
#define CMD_STATUS

struct s2255_mode {};


#define S2255_READ_IDLE
#define S2255_READ_FRAME

/* frame structure */
struct s2255_framei {};

/* image buffer structure */
struct s2255_bufferi {};

#define DEF_MODEI_NTSC_CONT

/* for firmware loading, fw_state */
#define S2255_FW_NOTLOADED
#define S2255_FW_LOADED_DSPWAIT
#define S2255_FW_SUCCESS
#define S2255_FW_FAILED
#define S2255_FW_DISCONNECTING
#define S2255_FW_MARKER
/* 2255 read states */
#define S2255_READ_IDLE
#define S2255_READ_FRAME
struct s2255_fw {};

struct s2255_pipeinfo {};

struct s2255_fmt; /*forward declaration */
struct s2255_dev;

/* 2255 video channel */
struct s2255_vc {};


struct s2255_dev {};

static inline struct s2255_dev *to_s2255_dev(struct v4l2_device *v4l2_dev)
{}

struct s2255_fmt {};

/* buffer for one video frame */
struct s2255_buffer {};


/* current cypress EEPROM firmware version */
#define S2255_CUR_USB_FWVER
/* current DSP FW version */
#define S2255_CUR_DSP_FWVER
/* Need DSP version 5+ for video status feature */
#define S2255_MIN_DSP_STATUS
#define S2255_MIN_DSP_COLORFILTER
#define S2255_NORMS

/* private V4L2 controls */

/*
 * The following chart displays how COLORFILTER should be set
 *  =========================================================
 *  =     fourcc              =     COLORFILTER             =
 *  =                         ===============================
 *  =                         =   0             =    1      =
 *  =========================================================
 *  =  V4L2_PIX_FMT_GREY(Y8)  = monochrome from = monochrome=
 *  =                         = s-video or      = composite =
 *  =                         = B/W camera      = input     =
 *  =========================================================
 *  =    other                = color, svideo   = color,    =
 *  =                         =                 = composite =
 *  =========================================================
 *
 * Notes:
 *   channels 0-3 on 2255 are composite
 *   channels 0-1 on 2257 are composite, 2-3 are s-video
 * If COLORFILTER is 0 with a composite color camera connected,
 * the output will appear monochrome but hatching
 * will occur.
 * COLORFILTER is different from "color killer" and "color effects"
 * for reasons above.
 */
#define S2255_V4L2_YC_ON
#define S2255_V4L2_YC_OFF
#define V4L2_CID_S2255_COLORFILTER

/* frame prefix size (sent once every frame) */
#define PREFIX_SIZE

/* Channels on box are in reverse order */
static unsigned long G_chnmap[MAX_CHANNELS] =;

static int debug;

static int s2255_start_readpipe(struct s2255_dev *dev);
static void s2255_stop_readpipe(struct s2255_dev *dev);
static int s2255_start_acquire(struct s2255_vc *vc);
static int s2255_stop_acquire(struct s2255_vc *vc);
static void s2255_fillbuff(struct s2255_vc *vc, struct s2255_buffer *buf,
			   int jpgsize);
static int s2255_set_mode(struct s2255_vc *vc, struct s2255_mode *mode);
static int s2255_board_shutdown(struct s2255_dev *dev);
static void s2255_fwload_start(struct s2255_dev *dev);
static void s2255_destroy(struct s2255_dev *dev);
static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req,
			     u16 index, u16 value, void *buf,
			     s32 buf_len, int bOut);

/* dev_err macro with driver name */
#define S2255_DRIVER_NAME
#define s2255_dev_err(dev, fmt, arg...)

#define dprintk(dev, level, fmt, arg...)

static struct usb_driver s2255_driver;

/* start video number */
static int video_nr =;	/* /dev/videoN, -1 for autodetect */

/* Enable jpeg capture. */
static int jpeg_enable =;

module_param(debug, int, 0644);
MODULE_PARM_DESC();
module_param(video_nr, int, 0644);
MODULE_PARM_DESC();
module_param(jpeg_enable, int, 0644);
MODULE_PARM_DESC();

/* USB device table */
#define USB_SENSORAY_VID
static const struct usb_device_id s2255_table[] =;
MODULE_DEVICE_TABLE(usb, s2255_table);

#define BUFFER_TIMEOUT

/* image formats.  */
/* JPEG formats must be defined last to support jpeg_enable parameter */
static const struct s2255_fmt formats[] =;

static int norm_maxw(struct s2255_vc *vc)
{}

static int norm_maxh(struct s2255_vc *vc)
{}

static int norm_minw(struct s2255_vc *vc)
{}

static int norm_minh(struct s2255_vc *vc)
{}


/*
 * TODO: fixme: move YUV reordering to hardware
 * converts 2255 planar format to yuyv or uyvy
 */
static void planar422p_to_yuv_packed(const unsigned char *in,
				     unsigned char *out,
				     int width, int height,
				     int fmt)
{}

static void s2255_reset_dsppower(struct s2255_dev *dev)
{}

/* kickstarts the firmware loading. from probe
 */
static void s2255_timer(struct timer_list *t)
{}


/* this loads the firmware asynchronously.
   Originally this was done synchronously in probe.
   But it is better to load it asynchronously here than block
   inside the probe function. Blocking inside probe affects boot time.
   FW loading is triggered by the timer in the probe function
*/
static void s2255_fwchunk_complete(struct urb *urb)
{}

static void s2255_got_frame(struct s2255_vc *vc, int jpgsize)
{}

static const struct s2255_fmt *format_by_fourcc(int fourcc)
{}

/* video buffer vmalloc implementation based partly on VIVI driver which is
 *          Copyright (c) 2006 by
 *                  Mauro Carvalho Chehab <mchehab--a.t--infradead.org>
 *                  Ted Walther <ted--a.t--enumera.com>
 *                  John Sokol <sokol--a.t--videotechnology.com>
 *                  http://v4l.videotechnology.com/
 *
 */
static void s2255_fillbuff(struct s2255_vc *vc,
			   struct s2255_buffer *buf, int jpgsize)
{}


/* ------------------------------------------------------------------
   Videobuf operations
   ------------------------------------------------------------------*/

static int queue_setup(struct vb2_queue *vq,
		       unsigned int *nbuffers, unsigned int *nplanes,
		       unsigned int sizes[], struct device *alloc_devs[])
{}

static int buffer_prepare(struct vb2_buffer *vb)
{}

static void buffer_queue(struct vb2_buffer *vb)
{}

static int start_streaming(struct vb2_queue *vq, unsigned int count);
static void stop_streaming(struct vb2_queue *vq);

static const struct vb2_ops s2255_video_qops =;

static int vidioc_querycap(struct file *file, void *priv,
			   struct v4l2_capability *cap)
{}

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

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

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

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


/* write to the configuration pipe, synchronously */
static int s2255_write_config(struct usb_device *udev, unsigned char *pbuf,
			      int size)
{}

static u32 get_transfer_size(struct s2255_mode *mode)
{}

static void s2255_print_cfg(struct s2255_dev *sdev, struct s2255_mode *mode)
{}

/*
 * set mode is the function which controls the DSP.
 * the restart parameter in struct s2255_mode should be set whenever
 * the image size could change via color format, video system or image
 * size.
 * When the restart parameter is set, we sleep for ONE frame to allow the
 * DSP time to get the new frame
 */
static int s2255_set_mode(struct s2255_vc *vc,
			  struct s2255_mode *mode)
{}

static int s2255_cmd_status(struct s2255_vc *vc, u32 *pstatus)
{}

static int start_streaming(struct vb2_queue *vq, unsigned int count)
{}

/* abort streaming and wait for last buffer */
static void stop_streaming(struct vb2_queue *vq)
{}

static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id i)
{}

static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *i)
{}

/* Sensoray 2255 is a multiple channel capture device.
   It does not have a "crossbar" of inputs.
   We use one V4L device per channel. The user must
   be aware that certain combinations are not allowed.
   For instance, you cannot do full FPS on more than 2 channels(2 videodevs)
   at once in color(you can do full fps on 4 channels with greyscale.
*/
static int vidioc_enum_input(struct file *file, void *priv,
			     struct v4l2_input *inp)
{}

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

static int s2255_s_ctrl(struct v4l2_ctrl *ctrl)
{}

static int vidioc_g_jpegcomp(struct file *file, void *priv,
			 struct v4l2_jpegcompression *jc)
{}

static int vidioc_s_jpegcomp(struct file *file, void *priv,
			 const struct v4l2_jpegcompression *jc)
{}

static int vidioc_g_parm(struct file *file, void *priv,
			 struct v4l2_streamparm *sp)
{}

static int vidioc_s_parm(struct file *file, void *priv,
			 struct v4l2_streamparm *sp)
{}

#define NUM_SIZE_ENUMS
static const struct v4l2_frmsize_discrete ntsc_sizes[] =;
static const struct v4l2_frmsize_discrete pal_sizes[] =;

static int vidioc_enum_framesizes(struct file *file, void *priv,
			    struct v4l2_frmsizeenum *fe)
{}

static int vidioc_enum_frameintervals(struct file *file, void *priv,
			    struct v4l2_frmivalenum *fe)
{}

static int s2255_open(struct file *file)
{}

static void s2255_destroy(struct s2255_dev *dev)
{}

static const struct v4l2_file_operations s2255_fops_v4l =;

static const struct v4l2_ioctl_ops s2255_ioctl_ops =;

static void s2255_video_device_release(struct video_device *vdev)
{}

static const struct video_device template =;

static const struct v4l2_ctrl_ops s2255_ctrl_ops =;

static const struct v4l2_ctrl_config color_filter_ctrl =;

static int s2255_probe_v4l(struct s2255_dev *dev)
{}

/* this function moves the usb stream read pipe data
 * into the system buffers.
 * returns 0 on success, EAGAIN if more data to process( call this
 * function again).
 *
 * Received frame structure:
 * bytes 0-3:  marker : 0x2255DA4AL (S2255_MARKER_FRAME)
 * bytes 4-7:  channel: 0-3
 * bytes 8-11: payload size:  size of the frame
 * bytes 12-payloadsize+12:  frame data
 */
static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
{}

static void s2255_read_video_callback(struct s2255_dev *dev,
				      struct s2255_pipeinfo *pipe_info)
{}

static long s2255_vendor_req(struct s2255_dev *dev, unsigned char Request,
			     u16 Index, u16 Value, void *TransferBuffer,
			     s32 TransferBufferLength, int bOut)
{}

/*
 * retrieve FX2 firmware version. future use.
 * @param dev pointer to device extension
 * @return -1 for fail, else returns firmware version as an int(16 bits)
 */
static int s2255_get_fx2fw(struct s2255_dev *dev)
{}

/*
 * Create the system ring buffer to copy frames into from the
 * usb read pipe.
 */
static int s2255_create_sys_buffers(struct s2255_vc *vc)
{}

static int s2255_release_sys_buffers(struct s2255_vc *vc)
{}

static int s2255_board_init(struct s2255_dev *dev)
{}

static int s2255_board_shutdown(struct s2255_dev *dev)
{}

static void read_pipe_completion(struct urb *purb)
{}

static int s2255_start_readpipe(struct s2255_dev *dev)
{}

/* starts acquisition process */
static int s2255_start_acquire(struct s2255_vc *vc)
{}

static int s2255_stop_acquire(struct s2255_vc *vc)
{}

static void s2255_stop_readpipe(struct s2255_dev *dev)
{}

static void s2255_fwload_start(struct s2255_dev *dev)
{}

/* standard usb probe function */
static int s2255_probe(struct usb_interface *interface,
		       const struct usb_device_id *id)
{}

/* disconnect routine. when board is removed physically or with rmmod */
static void s2255_disconnect(struct usb_interface *interface)
{}

static struct usb_driver s2255_driver =;

module_usb_driver();

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();
MODULE_VERSION();
MODULE_FIRMWARE();