📄 cpia.c
字号:
/* * cpia CPiA driver * * Supports CPiA based Video Camera's. * * (C) Copyright 1999-2000 Peter Pregler * (C) Copyright 1999-2000 Scott J. Bertin * (C) Copyright 1999-2000 Johannes Erdfelt <johannes@erdfelt.com> * (C) Copyright 2000 STMicroelectronics * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) *//* #define _CPIA_DEBUG_ 1 */ #include <linux/config.h>#include <linux/module.h>#include <linux/version.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/vmalloc.h>#include <linux/slab.h>#include <linux/proc_fs.h>#include <linux/ctype.h>#include <linux/pagemap.h>#include <asm/io.h>#include <asm/semaphore.h>#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0))#include <linux/wrapper.h>#endif#ifdef CONFIG_KMOD#include <linux/kmod.h>#endif#include "cpia.h"#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19))#define NEW_V4L_INTERFACE 1#else#undef NEW_V4L_INTERFACE#endif#ifdef CONFIG_VIDEO_CPIA_PPextern int cpia_pp_init(void);#endif#ifdef CONFIG_VIDEO_CPIA_USBextern int cpia_usb_init(void);#endif#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,5))static int video_nr = -1;#endifstatic int usb_alt = DEFAULT_USB_ALT_SETTING;#ifdef MODULEMODULE_PARM(usb_alt,"i");MODULE_PARM_DESC(usb_alt,"initial USB alt setting: 1 (min USB bandwidth use), 2, or 3 (max)");MODULE_AUTHOR("Scott J. Bertin <sbertin@securenym.net> & Peter Pregler <Peter_Pregler@email.com> & Johannes Erdfelt <johannes@erdfeld.com>");MODULE_DESCRIPTION("V4L-driver for Vision CPiA based cameras");#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10))MODULE_LICENSE("GPL");#endifMODULE_SUPPORTED_DEVICE("video");#endif#define ABOUT "V4L-Driver for Vision CPiA based cameras"#ifndef VID_HARDWARE_CPIA#define VID_HARDWARE_CPIA 24 /* FIXME -> from linux/videodev.h */#endif#define CPIA_MODULE_CPIA (0<<5)#define CPIA_MODULE_SYSTEM (1<<5)#define CPIA_MODULE_VP_CTRL (5<<5)#define CPIA_MODULE_CAPTURE (6<<5)#define CPIA_MODULE_DEBUG (7<<5)#define INPUT (DATA_IN << 8)#define OUTPUT (DATA_OUT << 8)#define CPIA_COMMAND_GetCPIAVersion (INPUT | CPIA_MODULE_CPIA | 1)#define CPIA_COMMAND_GetPnPID (INPUT | CPIA_MODULE_CPIA | 2)#define CPIA_COMMAND_GetCameraStatus (INPUT | CPIA_MODULE_CPIA | 3)#define CPIA_COMMAND_GotoHiPower (OUTPUT | CPIA_MODULE_CPIA | 4)#define CPIA_COMMAND_GotoLoPower (OUTPUT | CPIA_MODULE_CPIA | 5)#define CPIA_COMMAND_GotoSuspend (OUTPUT | CPIA_MODULE_CPIA | 7)#define CPIA_COMMAND_GotoPassThrough (OUTPUT | CPIA_MODULE_CPIA | 8)#define CPIA_COMMAND_ModifyCameraStatus (OUTPUT | CPIA_MODULE_CPIA | 10)#define CPIA_COMMAND_ReadVCRegs (INPUT | CPIA_MODULE_SYSTEM | 1)#define CPIA_COMMAND_WriteVCReg (OUTPUT | CPIA_MODULE_SYSTEM | 2)#define CPIA_COMMAND_ReadMCPorts (INPUT | CPIA_MODULE_SYSTEM | 3)#define CPIA_COMMAND_WriteMCPort (OUTPUT | CPIA_MODULE_SYSTEM | 4)#define CPIA_COMMAND_SetBaudRate (OUTPUT | CPIA_MODULE_SYSTEM | 5)#define CPIA_COMMAND_SetECPTiming (OUTPUT | CPIA_MODULE_SYSTEM | 6)#define CPIA_COMMAND_ReadIDATA (INPUT | CPIA_MODULE_SYSTEM | 7)#define CPIA_COMMAND_WriteIDATA (OUTPUT | CPIA_MODULE_SYSTEM | 8)#define CPIA_COMMAND_GenericCall (OUTPUT | CPIA_MODULE_SYSTEM | 9)#define CPIA_COMMAND_I2CStart (OUTPUT | CPIA_MODULE_SYSTEM | 10)#define CPIA_COMMAND_I2CStop (OUTPUT | CPIA_MODULE_SYSTEM | 11)#define CPIA_COMMAND_I2CWrite (OUTPUT | CPIA_MODULE_SYSTEM | 12)#define CPIA_COMMAND_I2CRead (INPUT | CPIA_MODULE_SYSTEM | 13)#define CPIA_COMMAND_GetVPVersion (INPUT | CPIA_MODULE_VP_CTRL | 1)#define CPIA_COMMAND_ResetFrameCounter (INPUT | CPIA_MODULE_VP_CTRL | 2)#define CPIA_COMMAND_SetColourParams (OUTPUT | CPIA_MODULE_VP_CTRL | 3)#define CPIA_COMMAND_SetExposure (OUTPUT | CPIA_MODULE_VP_CTRL | 4)#define CPIA_COMMAND_SetColourBalance (OUTPUT | CPIA_MODULE_VP_CTRL | 6)#define CPIA_COMMAND_SetSensorFPS (OUTPUT | CPIA_MODULE_VP_CTRL | 7)#define CPIA_COMMAND_SetVPDefaults (OUTPUT | CPIA_MODULE_VP_CTRL | 8)#define CPIA_COMMAND_SetApcor (OUTPUT | CPIA_MODULE_VP_CTRL | 9)#define CPIA_COMMAND_SetFlickerCtrl (OUTPUT | CPIA_MODULE_VP_CTRL | 10)#define CPIA_COMMAND_SetVLOffset (OUTPUT | CPIA_MODULE_VP_CTRL | 11)#define CPIA_COMMAND_GetColourParams (INPUT | CPIA_MODULE_VP_CTRL | 16)#define CPIA_COMMAND_GetColourBalance (INPUT | CPIA_MODULE_VP_CTRL | 17)#define CPIA_COMMAND_GetExposure (INPUT | CPIA_MODULE_VP_CTRL | 18)#define CPIA_COMMAND_SetSensorMatrix (OUTPUT | CPIA_MODULE_VP_CTRL | 19)#define CPIA_COMMAND_ColourBars (OUTPUT | CPIA_MODULE_VP_CTRL | 25)#define CPIA_COMMAND_ReadVPRegs (INPUT | CPIA_MODULE_VP_CTRL | 30)#define CPIA_COMMAND_WriteVPReg (OUTPUT | CPIA_MODULE_VP_CTRL | 31)#define CPIA_COMMAND_GrabFrame (OUTPUT | CPIA_MODULE_CAPTURE | 1)#define CPIA_COMMAND_UploadFrame (OUTPUT | CPIA_MODULE_CAPTURE | 2)#define CPIA_COMMAND_SetGrabMode (OUTPUT | CPIA_MODULE_CAPTURE | 3)#define CPIA_COMMAND_InitStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 4)#define CPIA_COMMAND_FiniStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 5)#define CPIA_COMMAND_StartStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 6)#define CPIA_COMMAND_EndStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 7)#define CPIA_COMMAND_SetFormat (OUTPUT | CPIA_MODULE_CAPTURE | 8)#define CPIA_COMMAND_SetROI (OUTPUT | CPIA_MODULE_CAPTURE | 9)#define CPIA_COMMAND_SetCompression (OUTPUT | CPIA_MODULE_CAPTURE | 10)#define CPIA_COMMAND_SetCompressionTarget (OUTPUT | CPIA_MODULE_CAPTURE | 11)#define CPIA_COMMAND_SetYUVThresh (OUTPUT | CPIA_MODULE_CAPTURE | 12)#define CPIA_COMMAND_SetCompressionParams (OUTPUT | CPIA_MODULE_CAPTURE | 13)#define CPIA_COMMAND_DiscardFrame (OUTPUT | CPIA_MODULE_CAPTURE | 14)#define CPIA_COMMAND_GrabReset (OUTPUT | CPIA_MODULE_CAPTURE | 15)#define CPIA_COMMAND_OutputRS232 (OUTPUT | CPIA_MODULE_DEBUG | 1)#define CPIA_COMMAND_AbortProcess (OUTPUT | CPIA_MODULE_DEBUG | 4)#define CPIA_COMMAND_SetDramPage (OUTPUT | CPIA_MODULE_DEBUG | 5)#define CPIA_COMMAND_StartDramUpload (OUTPUT | CPIA_MODULE_DEBUG | 6)#define CPIA_COMMAND_StartDummyDtream (OUTPUT | CPIA_MODULE_DEBUG | 8)#define CPIA_COMMAND_AbortStream (OUTPUT | CPIA_MODULE_DEBUG | 9)#define CPIA_COMMAND_DownloadDRAM (OUTPUT | CPIA_MODULE_DEBUG | 10)#define CPIA_COMMAND_Null (OUTPUT | CPIA_MODULE_DEBUG | 11)enum { FRAME_READY, /* Ready to grab into */ FRAME_GRABBING, /* In the process of being grabbed into */ FRAME_DONE, /* Finished grabbing, but not been synced yet */ FRAME_UNUSED, /* Unused (no MCAPTURE) */};#define COMMAND_NONE 0x0000#define COMMAND_SETCOMPRESSION 0x0001#define COMMAND_SETCOMPRESSIONTARGET 0x0002#define COMMAND_SETCOLOURPARAMS 0x0004#define COMMAND_SETFORMAT 0x0008#define COMMAND_PAUSE 0x0010#define COMMAND_RESUME 0x0020#define COMMAND_SETYUVTHRESH 0x0040#define COMMAND_SETECPTIMING 0x0080 /* for parport */#define COMMAND_SETUSBALT 0x0080 /* for usb */ #define COMMAND_SETCOMPRESSIONPARAMS 0x0100#define COMMAND_SETEXPOSURE 0x0200#define COMMAND_SETCOLOURBALANCE 0x0400#define COMMAND_SETSENSORFPS 0x0800#define COMMAND_SETAPCOR 0x1000#define COMMAND_SETFLICKERCTRL 0x2000#define COMMAND_SETVLOFFSET 0x4000#define COMMAND_SETLIGHTS 0x8000#define ROUND_UP_EXP_FOR_FLICKER 15/* Constants for automatic frame rate adjustment */#define MAX_EXP 302#define MAX_EXP_102 255#define LOW_EXP 140#define VERY_LOW_EXP 70#define TC 94#define EXP_ACC_DARK 50#define EXP_ACC_LIGHT 90#define HIGH_COMP_102 160 #define MAX_COMP 239 #define DARK_TIME 3#define LIGHT_TIME 3/* Maximum number of 10ms loops to wait for the stream to become ready */#define READY_TIMEOUT 100/* Developer's Guide Table 5 p 3-34 * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/static u8 flicker_jumps[2][2][4] ={ { { 76, 38, 19, 9 }, { 92, 46, 23, 11 } }, { { 64, 32, 16, 8 }, { 76, 38, 19, 9} }};/* forward declaration of local function */static void reset_camera_struct(struct cam_data *cam);static int find_over_exposure(int brightness);static void set_flicker(struct cam_params *params, volatile u32 *command_flags, int on);/********************************************************************** * * Memory management * **********************************************************************/#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19))/********************************************************************** * This is a shameless copy from the USB-cpia driver (linux kernel * version 2.3.29 or so, I have no idea what this code actually does ;). * Actually it seems to be a copy of a shameless copy of the bttv-driver. * Or that is a copy of a shameless copy of ... (To the powers: is there * no generic kernel-function to do this sort of stuff?) * * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says * there will be one, but apparentely not yet - jerdfelt * **********************************************************************//* Given PGD from the address space's page table, return the kernel * virtual mapping of the physical memory mapped at ADR. */static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr){ unsigned long ret = 0UL; pmd_t *pmd; pte_t *ptep, pte; if (!pgd_none(*pgd)) { pmd = pmd_offset(pgd, adr); if (!pmd_none(*pmd)) { ptep = pte_offset(pmd, adr); pte = *ptep; if (pte_present(pte)) { ret = (unsigned long) page_address(pte_page(pte)); ret |= (adr & (PAGE_SIZE-1)); } } } return ret;}/* Here we want the physical address of the memory. * This is used when initializing the contents of the * area and marking the pages as reserved. */static inline unsigned long kvirt_to_pa(unsigned long adr){ unsigned long va, kva, ret; va = VMALLOC_VMADDR(adr); kva = uvirt_to_kva(pgd_offset_k(va), va); ret = __pa(kva); return ret;}static void *rvmalloc(unsigned long size){ void *mem; unsigned long adr, page; /* Round it off to PAGE_SIZE */ size += (PAGE_SIZE - 1); size &= ~(PAGE_SIZE - 1); mem = vmalloc_32(size); if (!mem) return NULL; memset(mem, 0, size); /* Clear the ram out, no junk to the user */ adr = (unsigned long) mem; while (size > 0) { page = kvirt_to_pa(adr); mem_map_reserve(virt_to_page(__va(page))); adr += PAGE_SIZE; if (size > PAGE_SIZE) size -= PAGE_SIZE; else size = 0; } return mem;}static void rvfree(void *mem, unsigned long size){ unsigned long adr, page; if (!mem) return; size += (PAGE_SIZE - 1); size &= ~(PAGE_SIZE - 1); adr = (unsigned long) mem; while (size > 0) { page = kvirt_to_pa(adr); mem_map_unreserve(virt_to_page(__va(page))); adr += PAGE_SIZE; if (size > PAGE_SIZE) size -= PAGE_SIZE; else size = 0; } vfree(mem);}#else /*(LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19))*//* Here we want the physical address of the memory. * This is used when initializing the contents of the area. */static inline unsigned long kvirt_to_pa(unsigned long adr){ unsigned long kva, ret; kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); kva |= adr & (PAGE_SIZE-1); /* restore the offset */ ret = __pa(kva); return ret;}static void *rvmalloc(unsigned long size){ void *mem; unsigned long adr; size = PAGE_ALIGN(size); mem = vmalloc_32(size); if (!mem) return NULL; memset(mem, 0, size); /* Clear the ram out, no junk to the user */ adr = (unsigned long) mem; while (size > 0) {#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,69)) mem_map_reserve(vmalloc_to_page((void *)adr));#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,69)*/ SetPageReserved(vmalloc_to_page((void *)adr)); #endif adr += PAGE_SIZE; size -= PAGE_SIZE; } return mem;}static void rvfree(void *mem, unsigned long size){ unsigned long adr; if (!mem) return; adr = (unsigned long) mem; while ((long) size > 0) {#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,69)) mem_map_unreserve(vmalloc_to_page((void *)adr));#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,69)*/ ClearPageReserved(vmalloc_to_page((void *)adr));#endif adr += PAGE_SIZE; size -= PAGE_SIZE; } vfree(mem);}#endif /*(LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19))*//********************************************************************** * * /proc interface * **********************************************************************/#ifdef CONFIG_PROC_FSstatic struct proc_dir_entry *cpia_proc_root=NULL;#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,75))static ssize_t cpia_read_proc(char *page, char **start, off_t off,#elsestatic int cpia_read_proc(char *page, char **start, off_t off,#endif int count, int *eof, void *data){ char *out = page; int len, tmp; struct cam_data *cam = data; char tmpstr[29]; /* IMPORTANT: This output MUST be kept under PAGE_SIZE * or we need to get more sophisticated. */ out += sprintf(out, "read-only\n-----------------------\n"); out += sprintf(out, "V4L Driver version: %d.%d.%d\n", CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER); out += sprintf(out, "CPIA Version: %d.%02d (%d.%d)\n", cam->params.version.firmwareVersion, cam->params.version.firmwareRevision, cam->params.version.vcVersion, cam->params.version.vcRevision); out += sprintf(out, "CPIA PnP-ID: %04x:%04x:%04x\n", cam->params.pnpID.vendor, cam->params.pnpID.product, cam->params.pnpID.deviceRevision); out += sprintf(out, "VP-Version: %d.%d %04x\n", cam->params.vpVersion.vpVersion, cam->params.vpVersion.vpRevision, cam->params.vpVersion.cameraHeadID); out += sprintf(out, "system_state: %#04x\n", cam->params.status.systemState); out += sprintf(out, "grab_state: %#04x\n", cam->params.status.grabState); out += sprintf(out, "stream_state: %#04x\n", cam->params.status.streamState); out += sprintf(out, "fatal_error: %#04x\n", cam->params.status.fatalError); out += sprintf(out, "cmd_error: %#04x\n", cam->params.status.cmdError); out += sprintf(out, "debug_flags: %#04x\n", cam->params.status.debugFlags); out += sprintf(out, "vp_status: %#04x\n", cam->params.status.vpStatus); out += sprintf(out, "error_code: %#04x\n", cam->params.status.errorCode); /* QX3 specific entries */ if (cam->params.qx3.qx3_detected) { out += sprintf(out, "button: %4d\n", cam->params.qx3.button); out += sprintf(out, "cradled: %4d\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -