Path: blob/master/drivers/media/video/cpia2/cpia2_v4l.c
17656 views
/****************************************************************************1*2* Filename: cpia2_v4l.c3*4* Copyright 2001, STMicrolectronics, Inc.5* Contact: [email protected]6* Copyright 2001,2005, Scott J. Bertin <[email protected]>7*8* Description:9* This is a USB driver for CPia2 based video cameras.10* The infrastructure of this driver is based on the cpia usb driver by11* Jochen Scharrlach and Johannes Erdfeldt.12*13* This program is free software; you can redistribute it and/or modify14* it under the terms of the GNU General Public License as published by15* the Free Software Foundation; either version 2 of the License, or16* (at your option) any later version.17*18* This program is distributed in the hope that it will be useful,19* but WITHOUT ANY WARRANTY; without even the implied warranty of20* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the21* GNU General Public License for more details.22*23* You should have received a copy of the GNU General Public License24* along with this program; if not, write to the Free Software25* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.26*27* Stripped of 2.4 stuff ready for main kernel submit by28* Alan Cox <[email protected]>29****************************************************************************/3031#include <linux/version.h>323334#include <linux/module.h>35#include <linux/time.h>36#include <linux/sched.h>37#include <linux/slab.h>38#include <linux/init.h>39#include <linux/videodev2.h>40#include <linux/stringify.h>41#include <media/v4l2-ioctl.h>4243#include "cpia2.h"44#include "cpia2dev.h"4546static int video_nr = -1;47module_param(video_nr, int, 0);48MODULE_PARM_DESC(video_nr,"video device to register (0=/dev/video0, etc)");4950static int buffer_size = 68*1024;51module_param(buffer_size, int, 0);52MODULE_PARM_DESC(buffer_size, "Size for each frame buffer in bytes (default 68k)");5354static int num_buffers = 3;55module_param(num_buffers, int, 0);56MODULE_PARM_DESC(num_buffers, "Number of frame buffers (1-"57__stringify(VIDEO_MAX_FRAME) ", default 3)");5859static int alternate = DEFAULT_ALT;60module_param(alternate, int, 0);61MODULE_PARM_DESC(alternate, "USB Alternate (" __stringify(USBIF_ISO_1) "-"62__stringify(USBIF_ISO_6) ", default "63__stringify(DEFAULT_ALT) ")");6465static int flicker_freq = 60;66module_param(flicker_freq, int, 0);67MODULE_PARM_DESC(flicker_freq, "Flicker frequency (" __stringify(50) "or"68__stringify(60) ", default "69__stringify(60) ")");7071static int flicker_mode = NEVER_FLICKER;72module_param(flicker_mode, int, 0);73MODULE_PARM_DESC(flicker_mode,74"Flicker supression (" __stringify(NEVER_FLICKER) "or"75__stringify(ANTI_FLICKER_ON) ", default "76__stringify(NEVER_FLICKER) ")");7778MODULE_AUTHOR("Steve Miller (STMicroelectronics) <[email protected]>");79MODULE_DESCRIPTION("V4L-driver for STMicroelectronics CPiA2 based cameras");80MODULE_SUPPORTED_DEVICE("video");81MODULE_LICENSE("GPL");8283#define ABOUT "V4L-Driver for Vision CPiA2 based cameras"8485struct control_menu_info {86int value;87char name[32];88};8990static struct control_menu_info framerate_controls[] =91{92{ CPIA2_VP_FRAMERATE_6_25, "6.25 fps" },93{ CPIA2_VP_FRAMERATE_7_5, "7.5 fps" },94{ CPIA2_VP_FRAMERATE_12_5, "12.5 fps" },95{ CPIA2_VP_FRAMERATE_15, "15 fps" },96{ CPIA2_VP_FRAMERATE_25, "25 fps" },97{ CPIA2_VP_FRAMERATE_30, "30 fps" },98};99#define NUM_FRAMERATE_CONTROLS (ARRAY_SIZE(framerate_controls))100101static struct control_menu_info flicker_controls[] =102{103{ NEVER_FLICKER, "Off" },104{ FLICKER_50, "50 Hz" },105{ FLICKER_60, "60 Hz" },106};107#define NUM_FLICKER_CONTROLS (ARRAY_SIZE(flicker_controls))108109static struct control_menu_info lights_controls[] =110{111{ 0, "Off" },112{ 64, "Top" },113{ 128, "Bottom" },114{ 192, "Both" },115};116#define NUM_LIGHTS_CONTROLS (ARRAY_SIZE(lights_controls))117#define GPIO_LIGHTS_MASK 192118119static struct v4l2_queryctrl controls[] = {120{121.id = V4L2_CID_BRIGHTNESS,122.type = V4L2_CTRL_TYPE_INTEGER,123.name = "Brightness",124.minimum = 0,125.maximum = 255,126.step = 1,127.default_value = DEFAULT_BRIGHTNESS,128},129{130.id = V4L2_CID_CONTRAST,131.type = V4L2_CTRL_TYPE_INTEGER,132.name = "Contrast",133.minimum = 0,134.maximum = 255,135.step = 1,136.default_value = DEFAULT_CONTRAST,137},138{139.id = V4L2_CID_SATURATION,140.type = V4L2_CTRL_TYPE_INTEGER,141.name = "Saturation",142.minimum = 0,143.maximum = 255,144.step = 1,145.default_value = DEFAULT_SATURATION,146},147{148.id = V4L2_CID_HFLIP,149.type = V4L2_CTRL_TYPE_BOOLEAN,150.name = "Mirror Horizontally",151.minimum = 0,152.maximum = 1,153.step = 1,154.default_value = 0,155},156{157.id = V4L2_CID_VFLIP,158.type = V4L2_CTRL_TYPE_BOOLEAN,159.name = "Flip Vertically",160.minimum = 0,161.maximum = 1,162.step = 1,163.default_value = 0,164},165{166.id = CPIA2_CID_TARGET_KB,167.type = V4L2_CTRL_TYPE_INTEGER,168.name = "Target KB",169.minimum = 0,170.maximum = 255,171.step = 1,172.default_value = DEFAULT_TARGET_KB,173},174{175.id = CPIA2_CID_GPIO,176.type = V4L2_CTRL_TYPE_INTEGER,177.name = "GPIO",178.minimum = 0,179.maximum = 255,180.step = 1,181.default_value = 0,182},183{184.id = CPIA2_CID_FLICKER_MODE,185.type = V4L2_CTRL_TYPE_MENU,186.name = "Flicker Reduction",187.minimum = 0,188.maximum = NUM_FLICKER_CONTROLS-1,189.step = 1,190.default_value = 0,191},192{193.id = CPIA2_CID_FRAMERATE,194.type = V4L2_CTRL_TYPE_MENU,195.name = "Framerate",196.minimum = 0,197.maximum = NUM_FRAMERATE_CONTROLS-1,198.step = 1,199.default_value = NUM_FRAMERATE_CONTROLS-1,200},201{202.id = CPIA2_CID_USB_ALT,203.type = V4L2_CTRL_TYPE_INTEGER,204.name = "USB Alternate",205.minimum = USBIF_ISO_1,206.maximum = USBIF_ISO_6,207.step = 1,208.default_value = DEFAULT_ALT,209},210{211.id = CPIA2_CID_LIGHTS,212.type = V4L2_CTRL_TYPE_MENU,213.name = "Lights",214.minimum = 0,215.maximum = NUM_LIGHTS_CONTROLS-1,216.step = 1,217.default_value = 0,218},219{220.id = CPIA2_CID_RESET_CAMERA,221.type = V4L2_CTRL_TYPE_BUTTON,222.name = "Reset Camera",223.minimum = 0,224.maximum = 0,225.step = 0,226.default_value = 0,227},228};229#define NUM_CONTROLS (ARRAY_SIZE(controls))230231232/******************************************************************************233*234* cpia2_open235*236*****************************************************************************/237static int cpia2_open(struct file *file)238{239struct camera_data *cam = video_drvdata(file);240struct cpia2_fh *fh;241242if (!cam) {243ERR("Internal error, camera_data not found!\n");244return -ENODEV;245}246247if (!cam->present)248return -ENODEV;249250if (cam->open_count == 0) {251if (cpia2_allocate_buffers(cam))252return -ENOMEM;253254/* reset the camera */255if (cpia2_reset_camera(cam) < 0)256return -EIO;257258cam->APP_len = 0;259cam->COM_len = 0;260}261262fh = kmalloc(sizeof(*fh), GFP_KERNEL);263if (!fh)264return -ENOMEM;265file->private_data = fh;266fh->prio = V4L2_PRIORITY_UNSET;267v4l2_prio_open(&cam->prio, &fh->prio);268fh->mmapped = 0;269270++cam->open_count;271272cpia2_dbg_dump_registers(cam);273return 0;274}275276/******************************************************************************277*278* cpia2_close279*280*****************************************************************************/281static int cpia2_close(struct file *file)282{283struct video_device *dev = video_devdata(file);284struct camera_data *cam = video_get_drvdata(dev);285struct cpia2_fh *fh = file->private_data;286287if (cam->present &&288(cam->open_count == 1 || fh->prio == V4L2_PRIORITY_RECORD)) {289cpia2_usb_stream_stop(cam);290291if (cam->open_count == 1) {292/* save camera state for later open */293cpia2_save_camera_state(cam);294295cpia2_set_low_power(cam);296cpia2_free_buffers(cam);297}298}299300if (fh->mmapped)301cam->mmapped = 0;302v4l2_prio_close(&cam->prio, fh->prio);303file->private_data = NULL;304kfree(fh);305306if (--cam->open_count == 0) {307cpia2_free_buffers(cam);308if (!cam->present) {309video_unregister_device(dev);310kfree(cam);311return 0;312}313}314315return 0;316}317318/******************************************************************************319*320* cpia2_v4l_read321*322*****************************************************************************/323static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count,324loff_t *off)325{326struct camera_data *cam = video_drvdata(file);327int noblock = file->f_flags&O_NONBLOCK;328329struct cpia2_fh *fh = file->private_data;330331if(!cam)332return -EINVAL;333334/* Priority check */335if(fh->prio != V4L2_PRIORITY_RECORD) {336return -EBUSY;337}338339return cpia2_read(cam, buf, count, noblock);340}341342343/******************************************************************************344*345* cpia2_v4l_poll346*347*****************************************************************************/348static unsigned int cpia2_v4l_poll(struct file *filp, struct poll_table_struct *wait)349{350struct camera_data *cam = video_drvdata(filp);351struct cpia2_fh *fh = filp->private_data;352353if(!cam)354return POLLERR;355356/* Priority check */357if(fh->prio != V4L2_PRIORITY_RECORD) {358return POLLERR;359}360361return cpia2_poll(cam, filp, wait);362}363364365static int sync(struct camera_data *cam, int frame_nr)366{367struct framebuf *frame = &cam->buffers[frame_nr];368369while (1) {370if (frame->status == FRAME_READY)371return 0;372373if (!cam->streaming) {374frame->status = FRAME_READY;375frame->length = 0;376return 0;377}378379mutex_unlock(&cam->v4l2_lock);380wait_event_interruptible(cam->wq_stream,381!cam->streaming ||382frame->status == FRAME_READY);383mutex_lock(&cam->v4l2_lock);384if (signal_pending(current))385return -ERESTARTSYS;386if(!cam->present)387return -ENOTTY;388}389}390391/******************************************************************************392*393* ioctl_set_gpio394*395*****************************************************************************/396397static long cpia2_default(struct file *file, void *fh, bool valid_prio,398int cmd, void *arg)399{400struct camera_data *cam = video_drvdata(file);401__u32 gpio_val;402403if (cmd != CPIA2_CID_GPIO)404return -EINVAL;405406gpio_val = *(__u32*) arg;407408if (gpio_val &~ 0xFFU)409return -EINVAL;410411return cpia2_set_gpio(cam, (unsigned char)gpio_val);412}413414/******************************************************************************415*416* ioctl_querycap417*418* V4L2 device capabilities419*420*****************************************************************************/421422static int cpia2_querycap(struct file *file, void *fh, struct v4l2_capability *vc)423{424struct camera_data *cam = video_drvdata(file);425426strcpy(vc->driver, "cpia2");427428if (cam->params.pnp_id.product == 0x151)429strcpy(vc->card, "QX5 Microscope");430else431strcpy(vc->card, "CPiA2 Camera");432switch (cam->params.pnp_id.device_type) {433case DEVICE_STV_672:434strcat(vc->card, " (672/");435break;436case DEVICE_STV_676:437strcat(vc->card, " (676/");438break;439default:440strcat(vc->card, " (XXX/");441break;442}443switch (cam->params.version.sensor_flags) {444case CPIA2_VP_SENSOR_FLAGS_404:445strcat(vc->card, "404)");446break;447case CPIA2_VP_SENSOR_FLAGS_407:448strcat(vc->card, "407)");449break;450case CPIA2_VP_SENSOR_FLAGS_409:451strcat(vc->card, "409)");452break;453case CPIA2_VP_SENSOR_FLAGS_410:454strcat(vc->card, "410)");455break;456case CPIA2_VP_SENSOR_FLAGS_500:457strcat(vc->card, "500)");458break;459default:460strcat(vc->card, "XXX)");461break;462}463464if (usb_make_path(cam->dev, vc->bus_info, sizeof(vc->bus_info)) <0)465memset(vc->bus_info,0, sizeof(vc->bus_info));466467vc->version = KERNEL_VERSION(CPIA2_MAJ_VER, CPIA2_MIN_VER,468CPIA2_PATCH_VER);469470vc->capabilities = V4L2_CAP_VIDEO_CAPTURE |471V4L2_CAP_READWRITE |472V4L2_CAP_STREAMING;473474return 0;475}476477/******************************************************************************478*479* ioctl_input480*481* V4L2 input get/set/enumerate482*483*****************************************************************************/484485static int cpia2_enum_input(struct file *file, void *fh, struct v4l2_input *i)486{487if (i->index)488return -EINVAL;489strcpy(i->name, "Camera");490i->type = V4L2_INPUT_TYPE_CAMERA;491return 0;492}493494static int cpia2_g_input(struct file *file, void *fh, unsigned int *i)495{496*i = 0;497return 0;498}499500static int cpia2_s_input(struct file *file, void *fh, unsigned int i)501{502return i ? -EINVAL : 0;503}504505/******************************************************************************506*507* ioctl_enum_fmt508*509* V4L2 format enumerate510*511*****************************************************************************/512513static int cpia2_enum_fmt_vid_cap(struct file *file, void *fh,514struct v4l2_fmtdesc *f)515{516int index = f->index;517518if (index < 0 || index > 1)519return -EINVAL;520521memset(f, 0, sizeof(*f));522f->index = index;523f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;524f->flags = V4L2_FMT_FLAG_COMPRESSED;525switch(index) {526case 0:527strcpy(f->description, "MJPEG");528f->pixelformat = V4L2_PIX_FMT_MJPEG;529break;530case 1:531strcpy(f->description, "JPEG");532f->pixelformat = V4L2_PIX_FMT_JPEG;533break;534default:535return -EINVAL;536}537538return 0;539}540541/******************************************************************************542*543* ioctl_try_fmt544*545* V4L2 format try546*547*****************************************************************************/548549static int cpia2_try_fmt_vid_cap(struct file *file, void *fh,550struct v4l2_format *f)551{552struct camera_data *cam = video_drvdata(file);553554if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG &&555f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG)556return -EINVAL;557558f->fmt.pix.field = V4L2_FIELD_NONE;559f->fmt.pix.bytesperline = 0;560f->fmt.pix.sizeimage = cam->frame_size;561f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;562f->fmt.pix.priv = 0;563564switch (cpia2_match_video_size(f->fmt.pix.width, f->fmt.pix.height)) {565case VIDEOSIZE_VGA:566f->fmt.pix.width = 640;567f->fmt.pix.height = 480;568break;569case VIDEOSIZE_CIF:570f->fmt.pix.width = 352;571f->fmt.pix.height = 288;572break;573case VIDEOSIZE_QVGA:574f->fmt.pix.width = 320;575f->fmt.pix.height = 240;576break;577case VIDEOSIZE_288_216:578f->fmt.pix.width = 288;579f->fmt.pix.height = 216;580break;581case VIDEOSIZE_256_192:582f->fmt.pix.width = 256;583f->fmt.pix.height = 192;584break;585case VIDEOSIZE_224_168:586f->fmt.pix.width = 224;587f->fmt.pix.height = 168;588break;589case VIDEOSIZE_192_144:590f->fmt.pix.width = 192;591f->fmt.pix.height = 144;592break;593case VIDEOSIZE_QCIF:594default:595f->fmt.pix.width = 176;596f->fmt.pix.height = 144;597break;598}599600return 0;601}602603/******************************************************************************604*605* ioctl_set_fmt606*607* V4L2 format set608*609*****************************************************************************/610611static int cpia2_s_fmt_vid_cap(struct file *file, void *_fh,612struct v4l2_format *f)613{614struct camera_data *cam = video_drvdata(file);615struct cpia2_fh *fh = _fh;616int err, frame;617618err = v4l2_prio_check(&cam->prio, fh->prio);619if (err)620return err;621err = cpia2_try_fmt_vid_cap(file, _fh, f);622if(err != 0)623return err;624625/* Ensure that only this process can change the format. */626err = v4l2_prio_change(&cam->prio, &fh->prio, V4L2_PRIORITY_RECORD);627if(err != 0) {628return err;629}630631cam->pixelformat = f->fmt.pix.pixelformat;632633/* NOTE: This should be set to 1 for MJPEG, but some apps don't handle634* the missing Huffman table properly. */635cam->params.compression.inhibit_htables = 0;636/*f->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG;*/637638/* we set the video window to something smaller or equal to what639* is requested by the user???640*/641DBG("Requested width = %d, height = %d\n",642f->fmt.pix.width, f->fmt.pix.height);643if (f->fmt.pix.width != cam->width ||644f->fmt.pix.height != cam->height) {645cam->width = f->fmt.pix.width;646cam->height = f->fmt.pix.height;647cam->params.roi.width = f->fmt.pix.width;648cam->params.roi.height = f->fmt.pix.height;649cpia2_set_format(cam);650}651652for (frame = 0; frame < cam->num_frames; ++frame) {653if (cam->buffers[frame].status == FRAME_READING)654if ((err = sync(cam, frame)) < 0)655return err;656657cam->buffers[frame].status = FRAME_EMPTY;658}659660return 0;661}662663/******************************************************************************664*665* ioctl_get_fmt666*667* V4L2 format get668*669*****************************************************************************/670671static int cpia2_g_fmt_vid_cap(struct file *file, void *fh,672struct v4l2_format *f)673{674struct camera_data *cam = video_drvdata(file);675676f->fmt.pix.width = cam->width;677f->fmt.pix.height = cam->height;678f->fmt.pix.pixelformat = cam->pixelformat;679f->fmt.pix.field = V4L2_FIELD_NONE;680f->fmt.pix.bytesperline = 0;681f->fmt.pix.sizeimage = cam->frame_size;682f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;683f->fmt.pix.priv = 0;684685return 0;686}687688/******************************************************************************689*690* ioctl_cropcap691*692* V4L2 query cropping capabilities693* NOTE: cropping is currently disabled694*695*****************************************************************************/696697static int cpia2_cropcap(struct file *file, void *fh, struct v4l2_cropcap *c)698{699struct camera_data *cam = video_drvdata(file);700701if (c->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)702return -EINVAL;703704c->bounds.left = 0;705c->bounds.top = 0;706c->bounds.width = cam->width;707c->bounds.height = cam->height;708c->defrect.left = 0;709c->defrect.top = 0;710c->defrect.width = cam->width;711c->defrect.height = cam->height;712c->pixelaspect.numerator = 1;713c->pixelaspect.denominator = 1;714715return 0;716}717718/******************************************************************************719*720* ioctl_queryctrl721*722* V4L2 query possible control variables723*724*****************************************************************************/725726static int cpia2_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *c)727{728struct camera_data *cam = video_drvdata(file);729int i;730731for(i=0; i<NUM_CONTROLS; ++i) {732if(c->id == controls[i].id) {733memcpy(c, controls+i, sizeof(*c));734break;735}736}737738if(i == NUM_CONTROLS)739return -EINVAL;740741/* Some devices have additional limitations */742switch(c->id) {743case V4L2_CID_BRIGHTNESS:744/***745* Don't let the register be set to zero - bug in VP4746* flash of full brightness747***/748if (cam->params.pnp_id.device_type == DEVICE_STV_672)749c->minimum = 1;750break;751case V4L2_CID_VFLIP:752// VP5 Only753if(cam->params.pnp_id.device_type == DEVICE_STV_672)754c->flags |= V4L2_CTRL_FLAG_DISABLED;755break;756case CPIA2_CID_FRAMERATE:757if(cam->params.pnp_id.device_type == DEVICE_STV_672 &&758cam->params.version.sensor_flags==CPIA2_VP_SENSOR_FLAGS_500){759// Maximum 15fps760for(i=0; i<c->maximum; ++i) {761if(framerate_controls[i].value ==762CPIA2_VP_FRAMERATE_15) {763c->maximum = i;764c->default_value = i;765}766}767}768break;769case CPIA2_CID_FLICKER_MODE:770// Flicker control only valid for 672.771if(cam->params.pnp_id.device_type != DEVICE_STV_672)772c->flags |= V4L2_CTRL_FLAG_DISABLED;773break;774case CPIA2_CID_LIGHTS:775// Light control only valid for the QX5 Microscope.776if(cam->params.pnp_id.product != 0x151)777c->flags |= V4L2_CTRL_FLAG_DISABLED;778break;779default:780break;781}782783return 0;784}785786/******************************************************************************787*788* ioctl_querymenu789*790* V4L2 query possible control variables791*792*****************************************************************************/793794static int cpia2_querymenu(struct file *file, void *fh, struct v4l2_querymenu *m)795{796struct camera_data *cam = video_drvdata(file);797798switch(m->id) {799case CPIA2_CID_FLICKER_MODE:800if (m->index >= NUM_FLICKER_CONTROLS)801return -EINVAL;802803strcpy(m->name, flicker_controls[m->index].name);804break;805case CPIA2_CID_FRAMERATE:806{807int maximum = NUM_FRAMERATE_CONTROLS - 1;808if(cam->params.pnp_id.device_type == DEVICE_STV_672 &&809cam->params.version.sensor_flags==CPIA2_VP_SENSOR_FLAGS_500){810// Maximum 15fps811int i;812for(i=0; i<maximum; ++i) {813if(framerate_controls[i].value ==814CPIA2_VP_FRAMERATE_15)815maximum = i;816}817}818if (m->index > maximum)819return -EINVAL;820821strcpy(m->name, framerate_controls[m->index].name);822break;823}824case CPIA2_CID_LIGHTS:825if (m->index >= NUM_LIGHTS_CONTROLS)826return -EINVAL;827828strcpy(m->name, lights_controls[m->index].name);829break;830default:831return -EINVAL;832}833834return 0;835}836837/******************************************************************************838*839* ioctl_g_ctrl840*841* V4L2 get the value of a control variable842*843*****************************************************************************/844845static int cpia2_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)846{847struct camera_data *cam = video_drvdata(file);848849switch(c->id) {850case V4L2_CID_BRIGHTNESS:851cpia2_do_command(cam, CPIA2_CMD_GET_VP_BRIGHTNESS,852TRANSFER_READ, 0);853c->value = cam->params.color_params.brightness;854break;855case V4L2_CID_CONTRAST:856cpia2_do_command(cam, CPIA2_CMD_GET_CONTRAST,857TRANSFER_READ, 0);858c->value = cam->params.color_params.contrast;859break;860case V4L2_CID_SATURATION:861cpia2_do_command(cam, CPIA2_CMD_GET_VP_SATURATION,862TRANSFER_READ, 0);863c->value = cam->params.color_params.saturation;864break;865case V4L2_CID_HFLIP:866cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS,867TRANSFER_READ, 0);868c->value = (cam->params.vp_params.user_effects &869CPIA2_VP_USER_EFFECTS_MIRROR) != 0;870break;871case V4L2_CID_VFLIP:872cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS,873TRANSFER_READ, 0);874c->value = (cam->params.vp_params.user_effects &875CPIA2_VP_USER_EFFECTS_FLIP) != 0;876break;877case CPIA2_CID_TARGET_KB:878c->value = cam->params.vc_params.target_kb;879break;880case CPIA2_CID_GPIO:881cpia2_do_command(cam, CPIA2_CMD_GET_VP_GPIO_DATA,882TRANSFER_READ, 0);883c->value = cam->params.vp_params.gpio_data;884break;885case CPIA2_CID_FLICKER_MODE:886{887int i, mode;888cpia2_do_command(cam, CPIA2_CMD_GET_FLICKER_MODES,889TRANSFER_READ, 0);890if(cam->params.flicker_control.cam_register &891CPIA2_VP_FLICKER_MODES_NEVER_FLICKER) {892mode = NEVER_FLICKER;893} else {894if(cam->params.flicker_control.cam_register &895CPIA2_VP_FLICKER_MODES_50HZ) {896mode = FLICKER_50;897} else {898mode = FLICKER_60;899}900}901for(i=0; i<NUM_FLICKER_CONTROLS; i++) {902if(flicker_controls[i].value == mode) {903c->value = i;904break;905}906}907if(i == NUM_FLICKER_CONTROLS)908return -EINVAL;909break;910}911case CPIA2_CID_FRAMERATE:912{913int maximum = NUM_FRAMERATE_CONTROLS - 1;914int i;915for(i=0; i<= maximum; i++) {916if(cam->params.vp_params.frame_rate ==917framerate_controls[i].value)918break;919}920if(i > maximum)921return -EINVAL;922c->value = i;923break;924}925case CPIA2_CID_USB_ALT:926c->value = cam->params.camera_state.stream_mode;927break;928case CPIA2_CID_LIGHTS:929{930int i;931cpia2_do_command(cam, CPIA2_CMD_GET_VP_GPIO_DATA,932TRANSFER_READ, 0);933for(i=0; i<NUM_LIGHTS_CONTROLS; i++) {934if((cam->params.vp_params.gpio_data&GPIO_LIGHTS_MASK) ==935lights_controls[i].value) {936break;937}938}939if(i == NUM_LIGHTS_CONTROLS)940return -EINVAL;941c->value = i;942break;943}944case CPIA2_CID_RESET_CAMERA:945return -EINVAL;946default:947return -EINVAL;948}949950DBG("Get control id:%d, value:%d\n", c->id, c->value);951952return 0;953}954955/******************************************************************************956*957* ioctl_s_ctrl958*959* V4L2 set the value of a control variable960*961*****************************************************************************/962963static int cpia2_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)964{965struct camera_data *cam = video_drvdata(file);966int i;967int retval = 0;968969DBG("Set control id:%d, value:%d\n", c->id, c->value);970971/* Check that the value is in range */972for(i=0; i<NUM_CONTROLS; i++) {973if(c->id == controls[i].id) {974if(c->value < controls[i].minimum ||975c->value > controls[i].maximum) {976return -EINVAL;977}978break;979}980}981if(i == NUM_CONTROLS)982return -EINVAL;983984switch(c->id) {985case V4L2_CID_BRIGHTNESS:986cpia2_set_brightness(cam, c->value);987break;988case V4L2_CID_CONTRAST:989cpia2_set_contrast(cam, c->value);990break;991case V4L2_CID_SATURATION:992cpia2_set_saturation(cam, c->value);993break;994case V4L2_CID_HFLIP:995cpia2_set_property_mirror(cam, c->value);996break;997case V4L2_CID_VFLIP:998cpia2_set_property_flip(cam, c->value);999break;1000case CPIA2_CID_TARGET_KB:1001retval = cpia2_set_target_kb(cam, c->value);1002break;1003case CPIA2_CID_GPIO:1004retval = cpia2_set_gpio(cam, c->value);1005break;1006case CPIA2_CID_FLICKER_MODE:1007retval = cpia2_set_flicker_mode(cam,1008flicker_controls[c->value].value);1009break;1010case CPIA2_CID_FRAMERATE:1011retval = cpia2_set_fps(cam, framerate_controls[c->value].value);1012break;1013case CPIA2_CID_USB_ALT:1014retval = cpia2_usb_change_streaming_alternate(cam, c->value);1015break;1016case CPIA2_CID_LIGHTS:1017retval = cpia2_set_gpio(cam, lights_controls[c->value].value);1018break;1019case CPIA2_CID_RESET_CAMERA:1020cpia2_usb_stream_pause(cam);1021cpia2_reset_camera(cam);1022cpia2_usb_stream_resume(cam);1023break;1024default:1025retval = -EINVAL;1026}10271028return retval;1029}10301031/******************************************************************************1032*1033* ioctl_g_jpegcomp1034*1035* V4L2 get the JPEG compression parameters1036*1037*****************************************************************************/10381039static int cpia2_g_jpegcomp(struct file *file, void *fh, struct v4l2_jpegcompression *parms)1040{1041struct camera_data *cam = video_drvdata(file);10421043memset(parms, 0, sizeof(*parms));10441045parms->quality = 80; // TODO: Can this be made meaningful?10461047parms->jpeg_markers = V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI;1048if(!cam->params.compression.inhibit_htables) {1049parms->jpeg_markers |= V4L2_JPEG_MARKER_DHT;1050}10511052parms->APPn = cam->APPn;1053parms->APP_len = cam->APP_len;1054if(cam->APP_len > 0) {1055memcpy(parms->APP_data, cam->APP_data, cam->APP_len);1056parms->jpeg_markers |= V4L2_JPEG_MARKER_APP;1057}10581059parms->COM_len = cam->COM_len;1060if(cam->COM_len > 0) {1061memcpy(parms->COM_data, cam->COM_data, cam->COM_len);1062parms->jpeg_markers |= JPEG_MARKER_COM;1063}10641065DBG("G_JPEGCOMP APP_len:%d COM_len:%d\n",1066parms->APP_len, parms->COM_len);10671068return 0;1069}10701071/******************************************************************************1072*1073* ioctl_s_jpegcomp1074*1075* V4L2 set the JPEG compression parameters1076* NOTE: quality and some jpeg_markers are ignored.1077*1078*****************************************************************************/10791080static int cpia2_s_jpegcomp(struct file *file, void *fh, struct v4l2_jpegcompression *parms)1081{1082struct camera_data *cam = video_drvdata(file);10831084DBG("S_JPEGCOMP APP_len:%d COM_len:%d\n",1085parms->APP_len, parms->COM_len);10861087cam->params.compression.inhibit_htables =1088!(parms->jpeg_markers & V4L2_JPEG_MARKER_DHT);10891090if(parms->APP_len != 0) {1091if(parms->APP_len > 0 &&1092parms->APP_len <= sizeof(cam->APP_data) &&1093parms->APPn >= 0 && parms->APPn <= 15) {1094cam->APPn = parms->APPn;1095cam->APP_len = parms->APP_len;1096memcpy(cam->APP_data, parms->APP_data, parms->APP_len);1097} else {1098LOG("Bad APPn Params n=%d len=%d\n",1099parms->APPn, parms->APP_len);1100return -EINVAL;1101}1102} else {1103cam->APP_len = 0;1104}11051106if(parms->COM_len != 0) {1107if(parms->COM_len > 0 &&1108parms->COM_len <= sizeof(cam->COM_data)) {1109cam->COM_len = parms->COM_len;1110memcpy(cam->COM_data, parms->COM_data, parms->COM_len);1111} else {1112LOG("Bad COM_len=%d\n", parms->COM_len);1113return -EINVAL;1114}1115}11161117return 0;1118}11191120/******************************************************************************1121*1122* ioctl_reqbufs1123*1124* V4L2 Initiate memory mapping.1125* NOTE: The user's request is ignored. For now the buffers are fixed.1126*1127*****************************************************************************/11281129static int cpia2_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *req)1130{1131struct camera_data *cam = video_drvdata(file);11321133if(req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||1134req->memory != V4L2_MEMORY_MMAP)1135return -EINVAL;11361137DBG("REQBUFS requested:%d returning:%d\n", req->count, cam->num_frames);1138req->count = cam->num_frames;1139memset(&req->reserved, 0, sizeof(req->reserved));11401141return 0;1142}11431144/******************************************************************************1145*1146* ioctl_querybuf1147*1148* V4L2 Query memory buffer status.1149*1150*****************************************************************************/11511152static int cpia2_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)1153{1154struct camera_data *cam = video_drvdata(file);11551156if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||1157buf->index > cam->num_frames)1158return -EINVAL;11591160buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer;1161buf->length = cam->frame_size;11621163buf->memory = V4L2_MEMORY_MMAP;11641165if(cam->mmapped)1166buf->flags = V4L2_BUF_FLAG_MAPPED;1167else1168buf->flags = 0;11691170switch (cam->buffers[buf->index].status) {1171case FRAME_EMPTY:1172case FRAME_ERROR:1173case FRAME_READING:1174buf->bytesused = 0;1175buf->flags = V4L2_BUF_FLAG_QUEUED;1176break;1177case FRAME_READY:1178buf->bytesused = cam->buffers[buf->index].length;1179buf->timestamp = cam->buffers[buf->index].timestamp;1180buf->sequence = cam->buffers[buf->index].seq;1181buf->flags = V4L2_BUF_FLAG_DONE;1182break;1183}11841185DBG("QUERYBUF index:%d offset:%d flags:%d seq:%d bytesused:%d\n",1186buf->index, buf->m.offset, buf->flags, buf->sequence,1187buf->bytesused);11881189return 0;1190}11911192/******************************************************************************1193*1194* ioctl_qbuf1195*1196* V4L2 User is freeing buffer1197*1198*****************************************************************************/11991200static int cpia2_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)1201{1202struct camera_data *cam = video_drvdata(file);12031204if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||1205buf->memory != V4L2_MEMORY_MMAP ||1206buf->index > cam->num_frames)1207return -EINVAL;12081209DBG("QBUF #%d\n", buf->index);12101211if(cam->buffers[buf->index].status == FRAME_READY)1212cam->buffers[buf->index].status = FRAME_EMPTY;12131214return 0;1215}12161217/******************************************************************************1218*1219* find_earliest_filled_buffer1220*1221* Helper for ioctl_dqbuf. Find the next ready buffer.1222*1223*****************************************************************************/12241225static int find_earliest_filled_buffer(struct camera_data *cam)1226{1227int i;1228int found = -1;1229for (i=0; i<cam->num_frames; i++) {1230if(cam->buffers[i].status == FRAME_READY) {1231if(found < 0) {1232found = i;1233} else {1234/* find which buffer is earlier */1235struct timeval *tv1, *tv2;1236tv1 = &cam->buffers[i].timestamp;1237tv2 = &cam->buffers[found].timestamp;1238if(tv1->tv_sec < tv2->tv_sec ||1239(tv1->tv_sec == tv2->tv_sec &&1240tv1->tv_usec < tv2->tv_usec))1241found = i;1242}1243}1244}1245return found;1246}12471248/******************************************************************************1249*1250* ioctl_dqbuf1251*1252* V4L2 User is asking for a filled buffer.1253*1254*****************************************************************************/12551256static int cpia2_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)1257{1258struct camera_data *cam = video_drvdata(file);1259int frame;12601261if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||1262buf->memory != V4L2_MEMORY_MMAP)1263return -EINVAL;12641265frame = find_earliest_filled_buffer(cam);12661267if(frame < 0 && file->f_flags&O_NONBLOCK)1268return -EAGAIN;12691270if(frame < 0) {1271/* Wait for a frame to become available */1272struct framebuf *cb=cam->curbuff;1273mutex_unlock(&cam->v4l2_lock);1274wait_event_interruptible(cam->wq_stream,1275!cam->present ||1276(cb=cam->curbuff)->status == FRAME_READY);1277mutex_lock(&cam->v4l2_lock);1278if (signal_pending(current))1279return -ERESTARTSYS;1280if(!cam->present)1281return -ENOTTY;1282frame = cb->num;1283}128412851286buf->index = frame;1287buf->bytesused = cam->buffers[buf->index].length;1288buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;1289buf->field = V4L2_FIELD_NONE;1290buf->timestamp = cam->buffers[buf->index].timestamp;1291buf->sequence = cam->buffers[buf->index].seq;1292buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer;1293buf->length = cam->frame_size;1294buf->input = 0;1295buf->reserved = 0;1296memset(&buf->timecode, 0, sizeof(buf->timecode));12971298DBG("DQBUF #%d status:%d seq:%d length:%d\n", buf->index,1299cam->buffers[buf->index].status, buf->sequence, buf->bytesused);13001301return 0;1302}13031304static int cpia2_g_priority(struct file *file, void *_fh, enum v4l2_priority *p)1305{1306struct cpia2_fh *fh = _fh;13071308*p = fh->prio;1309return 0;1310}13111312static int cpia2_s_priority(struct file *file, void *_fh, enum v4l2_priority prio)1313{1314struct camera_data *cam = video_drvdata(file);1315struct cpia2_fh *fh = _fh;13161317if (cam->streaming && prio != fh->prio &&1318fh->prio == V4L2_PRIORITY_RECORD)1319/* Can't drop record priority while streaming */1320return -EBUSY;13211322if (prio == V4L2_PRIORITY_RECORD && prio != fh->prio &&1323v4l2_prio_max(&cam->prio) == V4L2_PRIORITY_RECORD)1324/* Only one program can record at a time */1325return -EBUSY;1326return v4l2_prio_change(&cam->prio, &fh->prio, prio);1327}13281329static int cpia2_streamon(struct file *file, void *fh, enum v4l2_buf_type type)1330{1331struct camera_data *cam = video_drvdata(file);13321333DBG("VIDIOC_STREAMON, streaming=%d\n", cam->streaming);1334if (!cam->mmapped || type != V4L2_BUF_TYPE_VIDEO_CAPTURE)1335return -EINVAL;13361337if (!cam->streaming)1338return cpia2_usb_stream_start(cam,1339cam->params.camera_state.stream_mode);1340return -EINVAL;1341}13421343static int cpia2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)1344{1345struct camera_data *cam = video_drvdata(file);13461347DBG("VIDIOC_STREAMOFF, streaming=%d\n", cam->streaming);1348if (!cam->mmapped || type != V4L2_BUF_TYPE_VIDEO_CAPTURE)1349return -EINVAL;13501351if (cam->streaming)1352return cpia2_usb_stream_stop(cam);1353return -EINVAL;1354}13551356/******************************************************************************1357*1358* cpia2_mmap1359*1360*****************************************************************************/1361static int cpia2_mmap(struct file *file, struct vm_area_struct *area)1362{1363struct camera_data *cam = video_drvdata(file);1364int retval;13651366/* Priority check */1367struct cpia2_fh *fh = file->private_data;1368if(fh->prio != V4L2_PRIORITY_RECORD) {1369return -EBUSY;1370}13711372retval = cpia2_remap_buffer(cam, area);13731374if(!retval)1375fh->mmapped = 1;1376return retval;1377}13781379/******************************************************************************1380*1381* reset_camera_struct_v4l1382*1383* Sets all values to the defaults1384*****************************************************************************/1385static void reset_camera_struct_v4l(struct camera_data *cam)1386{1387cam->width = cam->params.roi.width;1388cam->height = cam->params.roi.height;13891390cam->frame_size = buffer_size;1391cam->num_frames = num_buffers;13921393/* FlickerModes */1394cam->params.flicker_control.flicker_mode_req = flicker_mode;1395cam->params.flicker_control.mains_frequency = flicker_freq;13961397/* streamMode */1398cam->params.camera_state.stream_mode = alternate;13991400cam->pixelformat = V4L2_PIX_FMT_JPEG;1401v4l2_prio_init(&cam->prio);1402}14031404static const struct v4l2_ioctl_ops cpia2_ioctl_ops = {1405.vidioc_querycap = cpia2_querycap,1406.vidioc_enum_input = cpia2_enum_input,1407.vidioc_g_input = cpia2_g_input,1408.vidioc_s_input = cpia2_s_input,1409.vidioc_enum_fmt_vid_cap = cpia2_enum_fmt_vid_cap,1410.vidioc_g_fmt_vid_cap = cpia2_g_fmt_vid_cap,1411.vidioc_s_fmt_vid_cap = cpia2_s_fmt_vid_cap,1412.vidioc_try_fmt_vid_cap = cpia2_try_fmt_vid_cap,1413.vidioc_queryctrl = cpia2_queryctrl,1414.vidioc_querymenu = cpia2_querymenu,1415.vidioc_g_ctrl = cpia2_g_ctrl,1416.vidioc_s_ctrl = cpia2_s_ctrl,1417.vidioc_g_jpegcomp = cpia2_g_jpegcomp,1418.vidioc_s_jpegcomp = cpia2_s_jpegcomp,1419.vidioc_cropcap = cpia2_cropcap,1420.vidioc_reqbufs = cpia2_reqbufs,1421.vidioc_querybuf = cpia2_querybuf,1422.vidioc_qbuf = cpia2_qbuf,1423.vidioc_dqbuf = cpia2_dqbuf,1424.vidioc_streamon = cpia2_streamon,1425.vidioc_streamoff = cpia2_streamoff,1426.vidioc_g_priority = cpia2_g_priority,1427.vidioc_s_priority = cpia2_s_priority,1428.vidioc_default = cpia2_default,1429};14301431/***1432* The v4l video device structure initialized for this device1433***/1434static const struct v4l2_file_operations cpia2_fops = {1435.owner = THIS_MODULE,1436.open = cpia2_open,1437.release = cpia2_close,1438.read = cpia2_v4l_read,1439.poll = cpia2_v4l_poll,1440.unlocked_ioctl = video_ioctl2,1441.mmap = cpia2_mmap,1442};14431444static struct video_device cpia2_template = {1445/* I could not find any place for the old .initialize initializer?? */1446.name = "CPiA2 Camera",1447.fops = &cpia2_fops,1448.ioctl_ops = &cpia2_ioctl_ops,1449.release = video_device_release,1450};14511452/******************************************************************************1453*1454* cpia2_register_camera1455*1456*****************************************************************************/1457int cpia2_register_camera(struct camera_data *cam)1458{1459cam->vdev = video_device_alloc();1460if(!cam->vdev)1461return -ENOMEM;14621463memcpy(cam->vdev, &cpia2_template, sizeof(cpia2_template));1464video_set_drvdata(cam->vdev, cam);1465cam->vdev->lock = &cam->v4l2_lock;14661467reset_camera_struct_v4l(cam);14681469/* register v4l device */1470if (video_register_device(cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {1471ERR("video_register_device failed\n");1472video_device_release(cam->vdev);1473return -ENODEV;1474}14751476return 0;1477}14781479/******************************************************************************1480*1481* cpia2_unregister_camera1482*1483*****************************************************************************/1484void cpia2_unregister_camera(struct camera_data *cam)1485{1486if (!cam->open_count) {1487video_unregister_device(cam->vdev);1488} else {1489LOG("%s removed while open, deferring "1490"video_unregister_device\n",1491video_device_node_name(cam->vdev));1492}1493}14941495/******************************************************************************1496*1497* check_parameters1498*1499* Make sure that all user-supplied parameters are sensible1500*****************************************************************************/1501static void __init check_parameters(void)1502{1503if(buffer_size < PAGE_SIZE) {1504buffer_size = PAGE_SIZE;1505LOG("buffer_size too small, setting to %d\n", buffer_size);1506} else if(buffer_size > 1024*1024) {1507/* arbitrary upper limiit */1508buffer_size = 1024*1024;1509LOG("buffer_size ridiculously large, setting to %d\n",1510buffer_size);1511} else {1512buffer_size += PAGE_SIZE-1;1513buffer_size &= ~(PAGE_SIZE-1);1514}15151516if(num_buffers < 1) {1517num_buffers = 1;1518LOG("num_buffers too small, setting to %d\n", num_buffers);1519} else if(num_buffers > VIDEO_MAX_FRAME) {1520num_buffers = VIDEO_MAX_FRAME;1521LOG("num_buffers too large, setting to %d\n", num_buffers);1522}15231524if(alternate < USBIF_ISO_1 || alternate > USBIF_ISO_6) {1525alternate = DEFAULT_ALT;1526LOG("alternate specified is invalid, using %d\n", alternate);1527}15281529if (flicker_mode != NEVER_FLICKER && flicker_mode != ANTI_FLICKER_ON) {1530flicker_mode = NEVER_FLICKER;1531LOG("Flicker mode specified is invalid, using %d\n",1532flicker_mode);1533}15341535if (flicker_freq != FLICKER_50 && flicker_freq != FLICKER_60) {1536flicker_freq = FLICKER_60;1537LOG("Flicker mode specified is invalid, using %d\n",1538flicker_freq);1539}15401541if(video_nr < -1 || video_nr > 64) {1542video_nr = -1;1543LOG("invalid video_nr specified, must be -1 to 64\n");1544}15451546DBG("Using %d buffers, each %d bytes, alternate=%d\n",1547num_buffers, buffer_size, alternate);1548}15491550/************ Module Stuff ***************/155115521553/******************************************************************************1554*1555* cpia2_init/module_init1556*1557*****************************************************************************/1558static int __init cpia2_init(void)1559{1560LOG("%s v%d.%d.%d\n",1561ABOUT, CPIA2_MAJ_VER, CPIA2_MIN_VER, CPIA2_PATCH_VER);1562check_parameters();1563cpia2_usb_init();1564return 0;1565}156615671568/******************************************************************************1569*1570* cpia2_exit/module_exit1571*1572*****************************************************************************/1573static void __exit cpia2_exit(void)1574{1575cpia2_usb_cleanup();1576schedule_timeout(2 * HZ);1577}15781579module_init(cpia2_init);1580module_exit(cpia2_exit);1581158215831584