📄 sn9c102_core.c
字号:
/*************************************************************************** * V4L2 driver for SN9C1xx PC Camera Controllers * * * * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * * * * 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. * ***************************************************************************/#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/param.h>#include <linux/errno.h>#include <linux/slab.h>#include <linux/device.h>#include <linux/fs.h>#include <linux/delay.h>#include <linux/compiler.h>#include <linux/ioctl.h>#include <linux/poll.h>#include <linux/stat.h>#include <linux/mm.h>#include <linux/vmalloc.h>#include <linux/page-flags.h>#include <linux/byteorder/generic.h>#include <asm/page.h>#include <asm/uaccess.h>#include "sn9c102.h"/*****************************************************************************/#define SN9C102_MODULE_NAME "V4L2 driver for SN9C1xx PC Camera Controllers"#define SN9C102_MODULE_ALIAS "sn9c1xx"#define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia"#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"#define SN9C102_MODULE_LICENSE "GPL"#define SN9C102_MODULE_VERSION "1:1.47"#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 47)/*****************************************************************************/MODULE_DEVICE_TABLE(usb, sn9c102_id_table);MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL);MODULE_DESCRIPTION(SN9C102_MODULE_NAME);MODULE_ALIAS(SN9C102_MODULE_ALIAS);MODULE_VERSION(SN9C102_MODULE_VERSION);MODULE_LICENSE(SN9C102_MODULE_LICENSE);static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1};module_param_array(video_nr, short, NULL, 0444);MODULE_PARM_DESC(video_nr, " <-1|n[,...]>" "\nSpecify V4L2 minor mode number." "\n-1 = use next available (default)" "\n n = use minor number n (integer >= 0)" "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES) " cameras this way." "\nFor example:" "\nvideo_nr=-1,2,-1 would assign minor number 2 to" "\nthe second camera and use auto for the first" "\none and for every other camera." "\n");static short force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] = SN9C102_FORCE_MUNMAP};module_param_array(force_munmap, bool, NULL, 0444);MODULE_PARM_DESC(force_munmap, " <0|1[,...]>" "\nForce the application to unmap previously" "\nmapped buffer memory before calling any VIDIOC_S_CROP or" "\nVIDIOC_S_FMT ioctl's. Not all the applications support" "\nthis feature. This parameter is specific for each" "\ndetected camera." "\n0 = do not force memory unmapping" "\n1 = force memory unmapping (save memory)" "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." "\n");static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] = SN9C102_FRAME_TIMEOUT};module_param_array(frame_timeout, uint, NULL, 0644);MODULE_PARM_DESC(frame_timeout, " <0|n[,...]>" "\nTimeout for a video frame in seconds before" "\nreturning an I/O error; 0 for infinity." "\nThis parameter is specific for each detected camera." "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"." "\n");#ifdef SN9C102_DEBUGstatic unsigned short debug = SN9C102_DEBUG_LEVEL;module_param(debug, ushort, 0644);MODULE_PARM_DESC(debug, " <n>" "\nDebugging information level, from 0 to 3:" "\n0 = none (use carefully)" "\n1 = critical errors" "\n2 = significant informations" "\n3 = more verbose messages" "\nLevel 3 is useful for testing only." "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"." "\n");#endif/*****************************************************************************/static u32sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, enum sn9c102_io_method io){ struct v4l2_pix_format* p = &(cam->sensor.pix_format); struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); size_t imagesize = cam->module_param.force_munmap || io == IO_READ ? (p->width * p->height * p->priv) / 8 : (r->width * r->height * p->priv) / 8; void* buff = NULL; u32 i; if (count > SN9C102_MAX_FRAMES) count = SN9C102_MAX_FRAMES; if (cam->bridge == BRIDGE_SN9C105 || cam->bridge == BRIDGE_SN9C120) imagesize += 589 + 2; /* length of JPEG header + EOI marker */ cam->nbuffers = count; while (cam->nbuffers > 0) { if ((buff = vmalloc_32_user(cam->nbuffers * PAGE_ALIGN(imagesize)))) break; cam->nbuffers--; } for (i = 0; i < cam->nbuffers; i++) { cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize); cam->frame[i].buf.index = i; cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize); cam->frame[i].buf.length = imagesize; cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; cam->frame[i].buf.sequence = 0; cam->frame[i].buf.field = V4L2_FIELD_NONE; cam->frame[i].buf.memory = V4L2_MEMORY_MMAP; cam->frame[i].buf.flags = 0; } return cam->nbuffers;}static void sn9c102_release_buffers(struct sn9c102_device* cam){ if (cam->nbuffers) { vfree(cam->frame[0].bufmem); cam->nbuffers = 0; } cam->frame_current = NULL;}static void sn9c102_empty_framequeues(struct sn9c102_device* cam){ u32 i; INIT_LIST_HEAD(&cam->inqueue); INIT_LIST_HEAD(&cam->outqueue); for (i = 0; i < SN9C102_MAX_FRAMES; i++) { cam->frame[i].state = F_UNUSED; cam->frame[i].buf.bytesused = 0; }}static void sn9c102_requeue_outqueue(struct sn9c102_device* cam){ struct sn9c102_frame_t *i; list_for_each_entry(i, &cam->outqueue, frame) { i->state = F_QUEUED; list_add(&i->frame, &cam->inqueue); } INIT_LIST_HEAD(&cam->outqueue);}static void sn9c102_queue_unusedframes(struct sn9c102_device* cam){ unsigned long lock_flags; u32 i; for (i = 0; i < cam->nbuffers; i++) if (cam->frame[i].state == F_UNUSED) { cam->frame[i].state = F_QUEUED; spin_lock_irqsave(&cam->queue_lock, lock_flags); list_add_tail(&cam->frame[i].frame, &cam->inqueue); spin_unlock_irqrestore(&cam->queue_lock, lock_flags); }}/*****************************************************************************//* Write a sequence of count value/register pairs. Returns -1 after the first failed write, or 0 for no errors.*/int sn9c102_write_regs(struct sn9c102_device* cam, const u8 valreg[][2], int count){ struct usb_device* udev = cam->usbdev; u8* buff = cam->control_buffer; int i, res; for (i = 0; i < count; i++) { u8 index = valreg[i][1]; /* index is a u8, so it must be <256 and can't be out of range. If we put in a check anyway, gcc annoys us with a warning hat our check is useless. People get all uppity when they see warnings in the kernel compile. */ *buff = valreg[i][0]; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, index, 0, buff, 1, SN9C102_CTRL_TIMEOUT); if (res < 0) { DBG(3, "Failed to write a register (value 0x%02X, " "index 0x%02X, error %d)", *buff, index, res); return -1; } cam->reg[index] = *buff; } return 0;}int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index){ struct usb_device* udev = cam->usbdev; u8* buff = cam->control_buffer; int res; if (index >= ARRAY_SIZE(cam->reg)) return -1; *buff = value; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, index, 0, buff, 1, SN9C102_CTRL_TIMEOUT); if (res < 0) { DBG(3, "Failed to write a register (value 0x%02X, index " "0x%02X, error %d)", value, index, res); return -1; } cam->reg[index] = value; return 0;}/* NOTE: with the SN9C10[123] reading some registers always returns 0 */int sn9c102_read_reg(struct sn9c102_device* cam, u16 index){ struct usb_device* udev = cam->usbdev; u8* buff = cam->control_buffer; int res; res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, index, 0, buff, 1, SN9C102_CTRL_TIMEOUT); if (res < 0) DBG(3, "Failed to read a register (index 0x%02X, error %d)", index, res); return (res >= 0) ? (int)(*buff) : -1;}int sn9c102_pread_reg(struct sn9c102_device* cam, u16 index){ if (index >= ARRAY_SIZE(cam->reg)) return -1; return cam->reg[index];}static intsn9c102_i2c_wait(struct sn9c102_device* cam, const struct sn9c102_sensor* sensor){ int i, r; for (i = 1; i <= 5; i++) { r = sn9c102_read_reg(cam, 0x08); if (r < 0) return -EIO; if (r & 0x04) return 0; if (sensor->frequency & SN9C102_I2C_400KHZ) udelay(5*16); else udelay(16*16); } return -EBUSY;}static intsn9c102_i2c_detect_read_error(struct sn9c102_device* cam, const struct sn9c102_sensor* sensor){ int r , err = 0; r = sn9c102_read_reg(cam, 0x08); if (r < 0) err += r; if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) { if (!(r & 0x08)) err += -1; } else { if (r & 0x08) err += -1; } return err ? -EIO : 0;}static intsn9c102_i2c_detect_write_error(struct sn9c102_device* cam, const struct sn9c102_sensor* sensor){ int r; r = sn9c102_read_reg(cam, 0x08); return (r < 0 || (r >= 0 && (r & 0x08))) ? -EIO : 0;}intsn9c102_i2c_try_raw_read(struct sn9c102_device* cam, const struct sn9c102_sensor* sensor, u8 data0, u8 data1, u8 n, u8 buffer[]){ struct usb_device* udev = cam->usbdev; u8* data = cam->control_buffer; int i = 0, err = 0, res; /* Write cycle */ data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10; data[1] = data0; /* I2C slave id */ data[2] = data1; /* address */ data[7] = 0x10; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); if (res < 0) err += res; err += sn9c102_i2c_wait(cam, sensor); /* Read cycle - n bytes */ data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | (n << 4) | 0x02; data[1] = data0; data[7] = 0x10; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); if (res < 0) err += res; err += sn9c102_i2c_wait(cam, sensor); /* The first read byte will be placed in data[4] */ res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, 0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT); if (res < 0) err += res; err += sn9c102_i2c_detect_read_error(cam, sensor); PDBGG("I2C read: address 0x%02X, first read byte: 0x%02X", data1, data[4]); if (err) { DBG(3, "I2C read failed for %s image sensor", sensor->name); return -1; } if (buffer) for (i = 0; i < n && i < 5; i++) buffer[n-i-1] = data[4-i]; return (int)data[4];}intsn9c102_i2c_try_raw_write(struct sn9c102_device* cam, const struct sn9c102_sensor* sensor, u8 n, u8 data0, u8 data1, u8 data2, u8 data3, u8 data4, u8 data5){ struct usb_device* udev = cam->usbdev; u8* data = cam->control_buffer; int err = 0, res; /* Write cycle. It usually is address + value */ data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | ((n - 1) << 4); data[1] = data0; data[2] = data1; data[3] = data2; data[4] = data3; data[5] = data4; data[6] = data5; data[7] = 0x17; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); if (res < 0) err += res; err += sn9c102_i2c_wait(cam, sensor); err += sn9c102_i2c_detect_write_error(cam, sensor); if (err) DBG(3, "I2C write failed for %s image sensor", sensor->name); PDBGG("I2C raw write: %u bytes, data0 = 0x%02X, data1 = 0x%02X, " "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X", n, data0, data1, data2, data3, data4, data5); return err ? -1 : 0;}intsn9c102_i2c_try_read(struct sn9c102_device* cam, const struct sn9c102_sensor* sensor, u8 address){ return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id, address, 1, NULL);}intsn9c102_i2c_try_write(struct sn9c102_device* cam, const struct sn9c102_sensor* sensor, u8 address, u8 value){ return sn9c102_i2c_try_raw_write(cam, sensor, 3, sensor->i2c_slave_id, address, value, 0, 0, 0);}int sn9c102_i2c_read(struct sn9c102_device* cam, u8 address){ return sn9c102_i2c_try_read(cam, &cam->sensor, address);}int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value){ return sn9c102_i2c_try_write(cam, &cam->sensor, address, value);}/*****************************************************************************/static size_t sn9c102_sof_length(struct sn9c102_device* cam){ switch (cam->bridge) { case BRIDGE_SN9C101: case BRIDGE_SN9C102: return 12; case BRIDGE_SN9C103: return 18; case BRIDGE_SN9C105: case BRIDGE_SN9C120: return 62; } return 0;}static void*sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len){ static const char marker[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; const char *m = mem; size_t soflen = 0, i, j; soflen = sn9c102_sof_length(cam);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -