📄 zc030x_main.c
字号:
/* Implementation file for kernel spec *//* Zc030x -- Driver -- Zc030x *//* This file is under GPL *//* Copyright : Martin Braun Arnaud Patard Andre Freitas Tommy Andrew Birkett Cyril Russo---------------------------------------*//* Include the kernel headers */#include <linux/config.h>#include <linux/version.h>/* Declare module versions specific */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)#define MODVERSIONS#endif#ifdef MODVERSIONS#include <linux/modversions.h>#endif#endif/* Module insertion + scheduler + usb */#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/usb.h>#include <linux/slab.h> /* This module specific declarations */ /* Include kernel definitions */#include "zc030x_kerneldef.h"/* Jpeg decoding to RGB/YUV */#include "zc030x_jpeg.h"/* V4L specific */#include "zc030x_v4l.h"/* Proc fs specific */#include "zc030x_proc.h"/* Memory management */#include "zc030x_mm.h"/* I2C register reading */#include "zc030x_i2c.h"/* Bridge chip registers */#include "zc030x_reg.h"/* Camera specific */#include "zc030x_cameras.h"/* Isochronous transfers */#include "zc030x_isochron.h"/* Matrix stuff */#include "zc030x_matrix.h"/* Module paramaters */int debug = 5;int width = 320;int currentwidth = 0;int height = 232;int currentheight = 0;int quality = 1;int sensoraccept = 90;char * sensor = (char*)"auto";/* Debug level */MODULE_PARM (debug, "i");MODULE_PARM_DESC (debug, "Debug level 1:Release -> 5:All messages");/* Default width */MODULE_PARM (width, "i");MODULE_PARM_DESC (width, "Default width of the frame");/* Default height */MODULE_PARM (height, "i");MODULE_PARM_DESC (height, "Default height of the frame");/* Default quality */MODULE_PARM (quality, "i");MODULE_PARM_DESC (quality, "Picture quality 1:Normal 5:Very high (CPU intensive)");/* Sensor accept level */MODULE_PARM (sensoraccept, "i");MODULE_PARM_DESC (sensoraccept, "Sensor signature accept level (in percent) 0:Accept any unmatching sensors -> 100: Accept sensor only if its signature match");/* Sensor accept level */MODULE_PARM (sensor, "s");MODULE_PARM_DESC (sensor, "Sensor name (to avoid detection)");/* Needed declarations */MODULE_AUTHOR("Martin Braun <martinbraun at gmx.net>, Arnaud Patard <thertp at users.sourceforge.net>, Andre Freitas <linux at uninet.com.br>, Cyril Russo<>, Andrew Birkett <andy@nobugs.org>");MODULE_DESCRIPTION("ZC030X USB Camera Driver");MODULE_LICENSE("GPL");/* Device table */MODULE_DEVICE_TABLE (usb, zc030x_table);/* USB device functions */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) static void *zc030x_probe (struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id);static void zc030x_disconnect (struct usb_device *dev, void *ptr);#elsestatic int zc030x_probe (struct usb_interface *interface, const struct usb_device_id *id);static void zc030x_disconnect (struct usb_interface *interface);#endif/* Exported read function */ ssize_t zc030x_read (struct file *file, char *buffer, size_t count, loff_t * ppos);/* Exported ioctl function */ int zc030x_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);/* Exported mmap function */ int zc030x_mmap(struct file *file, struct vm_area_struct *vma);/* Exported open function */ int zc030x_open (struct inode *inode, struct file *file);/* Exported release function */ int zc030x_release (struct inode *inode, struct file *file);/* File operations supported by this device */struct file_operations zc030x_fops = { .owner = THIS_MODULE, .open = zc030x_open, .release = zc030x_release, .read = zc030x_read, .ioctl = zc030x_ioctl, .mmap = zc030x_mmap, .llseek = no_llseek,};/* Lock to protect the minor_table structure */static DECLARE_MUTEX (disconnect_sem);/* USB specific object needed to register this driver with the USB subsystem */static struct usb_driver zc030x_driver = { .owner = THIS_MODULE, .name = "zc030x", .probe = zc030x_probe, .disconnect = zc030x_disconnect, .id_table = zc030x_table,};/* Probe for a device matching the ID given in the table */#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)static int zc030x_probe(struct usb_interface *intf, const struct usb_device_id *id)#elsestatic void *zc030x_probe (struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id)#endif{ /* Zc030x device pointer */ struct usb_zc030x *dev = NULL; /* Interface descriptor */ struct usb_interface_descriptor *iface; /* Iterator */ int i;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* Actual alternate settings */ int actalt = 0;#else struct usb_device *udev = interface_to_usbdev(intf);#endif /* Debug this probing */ PDEBUG(1,"probe!!\n"); /* Removed the following line */ // probe_calls++; /* Check for multiconfiguration devices */ if (udev->descriptor.bNumConfigurations != 1) { PDEBUG(1,"ERROR: Can't handle camera: multiconfiguration device"); goto nodevice; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) if (ifnum > 0) goto nodevice; /* Skip probe for alternate settings (fixed)*/ actalt = udev->actconfig->interface[ifnum].act_altsetting; if (actalt > 0) goto nodevice; #endif /*** If we reach this point, we found our interface/altsetting */ PDEBUG(3, ">> zc030x_probe");#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) MOD_INC_USE_COUNT;#endif /* Allocate memory for our device object and intialize it */ dev = kmalloc (sizeof (struct usb_zc030x), GFP_KERNEL); /* Check allocation */ if (dev == NULL) { err ("Couldn't kalloc zc030x device struct!"); goto error; } /* Clear it */ memset (dev, 0x00, sizeof (struct usb_zc030x)); /* Start filling it */ dev->udev = udev; /* Detect our camera ! */ if ((zc030x_detect_camera (dev)) < 0) { PDEBUG(1,"ERROR: Device not supported !"); goto error; } /* Init mutexes */ init_MUTEX (&dev->sem); init_MUTEX (&dev->buf_lock); /* USB specific initialization... */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) PDEBUG (3, "Set device configuration to %d\n", DEFAULT_CONFIGURATION); usb_set_configuration (udev, DEFAULT_CONFIGURATION);#endif PDEBUG (3, "Set interface to %d\n", VIDEO_INTERFACE); PDEBUG (3, "Set alternate configuration %d\n", dev->alt); usb_set_interface (udev, VIDEO_INTERFACE, dev->alt); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) iface = &udev->actconfig->interface[ifnum].altsetting[dev->alt];#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,6) iface = &intf->cur_altsetting->desc;#else iface = &intf->altsetting[dev->alt].desc;#endif dev->iface_desc = iface; /* Endpoint scan procedure was removed, think we can stick with fixed values */ dev->isocend = 0x01; dev->intrend = 0x02; /* Create the Video For Linux device */ if (zc030x_v4l_initdev(&zc030x_fops, dev, CamList[dev->type_id].Name, udev) == V4L_Error) { PDEBUG(1, "Error while registering the camera!"); goto error; } /* Init device queue */ init_waitqueue_head(&dev->wq); /* Init frame queue */ for (i = 0; i < ZC030X_NUMFRAMES; i++) { init_waitqueue_head(&dev->frame[i].wq); /* Reset the frame sequence number */ dev->frame[i].SeqNumber=0; /* And init its lock too */ init_MUTEX(&dev->frame[i].Lock); } /* Set the default brightness contrast and gamma */ dev->Brightness = DefaultBrightness; dev->Contrast = DefaultContrast; dev->Gamma = DefaultGamma; /* Create a gamma array and debug it */ zc030x_gamma_init(); /* Initialize the pseudo-JPEG decoder */ zc030x_jpeg_init(); /* Configure the zc030x camera */ if (zc030x_configure_camera(dev, width, height, quality) != 0 ) { PDEBUG(1, "Error while configuring the camera!"); goto error; } /* Allow device read, ioctl, mmap */ dev->present = 1; //PDEBUG(1,"Probe was called %d times", probe_calls); /* Okay, return */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) MOD_DEC_USE_COUNT; return dev;#else usb_set_intfdata(intf, dev); return 0;#endif nodevice: /* Quit */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) return NULL; #else return -ENODEV;#endif error: /* Release video device */ zc030x_v4l_releasedev(dev->pVideoDevice); /* Release the driver it self */ if (dev != NULL) kfree(dev); /* And quit */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) MOD_DEC_USE_COUNT; return NULL;#else return -ENOMEM;#endif }/* Handle disconnected device */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)static void zc030x_disconnect(struct usb_interface *interface){ struct usb_zc030x *dev = usb_get_intfdata (interface); usb_set_intfdata (interface, NULL);#else static void zc030x_disconnect (struct usb_device *udev, void *ptr){ struct usb_zc030x *dev = (struct usb_zc030x *) ptr;#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) MOD_INC_USE_COUNT;#endif PDEBUG(3,">> zc030x_disconnect()"); /* prevent races with open */ down (&disconnect_sem); /* prevent device read, write and ioctl */ dev->present = 0; /* We don't want people trying to open up the device */ zc030x_v4l_releasedev(dev->pVideoDevice); /* Stop stream (if any) and unlink & free urbs */ zc030x_isoc_stop(dev); /* Dellocate buffers */ zc030x_unallocate_buffers(dev); /* Deregister interrupt urb */ usb_unlink_urb(dev->inturb); usb_free_urb(dev->inturb); /* Take up the lock */ down (&dev->sem); /* if the device is not opened, then we clean up right now */ if (!dev->open) { up (&dev->sem); kfree (dev); } else { dev->udev = NULL; up (&dev->sem); } /* Release the lock */ up (&disconnect_sem); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) MOD_DEC_USE_COUNT;#endif}/* Open the device from its /dev/videoX structure */int zc030x_open (struct inode *inode, struct file *file){ /* Get the video device */ struct video_device *vdev = video_devdata(file); /* And the USB device too */ struct usb_zc030x *dev; /* Debug this function */ PDEBUG(3,">> zc030x_open()"); /* Check argument */ if (vdev == NULL) { PDEBUG (2, "vdev is NULL, returning"); return 0; } /* Get driver data */ dev = video_get_drvdata(vdev); if (dev == NULL) { PDEBUG (2, "dev is NULL, returning"); return 0; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) MOD_INC_USE_COUNT;#endif /* Lock this device before modifying it */ down (&dev->sem); /* Increment our usage count for the driver */ ++dev->open; /* Save our object in the file's private structure */ file->private_data = vdev; /* Check the current video format */ if (!dev->VideoFormat) dev->VideoFormat = VIDEO_PALETTE_RGB24; /* Set the default brightness contrast and gamma */ dev->Brightness = DefaultBrightness; dev->Contrast = DefaultContrast; dev->Gamma = DefaultGamma; /* Init the isochronous transfers */ zc030x_isoc_start(dev); /* unlock this device */ up (&dev->sem); /* Return */ PDEBUG(3,"<< zc030x_open()"); return 0;}/* Release the device through its /dev/videoX file */int zc030x_release (struct inode *inode, struct file *file){ /* Get the video device */ struct video_device *vdev = video_devdata(file); /* And the USB device too */ struct usb_zc030x *dev; /* Iterator */ int i = 0; /* Debug this function */ PDEBUG(3,">> zc030x_release()"); /* Check parameter */ if (vdev == NULL) { PDEBUG (2, "vdev is NULL, returning"); return 0; } /* Get USB device too */ dev = video_get_drvdata(vdev); if (dev == NULL) { PDEBUG (2, "dev is NULL, returning"); return 0; } /* Lock our device */ down (&dev->sem); /* Check if the device is opened */ if (dev->open <= 0) { PDEBUG (5, "%s - device not opened", __FUNCTION__);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -