⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spca5xx.c

📁 linux下的摄像头驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
  struct usb_spca50x *spca50x = data;  *start = page;  /* check whether the buffer exists */  if (spca50x->rawBuffer == NULL)    {      *eof = 1;      return 0;    }  /* check offset is valid */  if (off > spca50x->rawBufferSize)    {      *eof = 1;      return 0;    }  /* can't read more than exists in the buffer, either */  if ((count + off) > spca50x->rawBufferSize)    {      count = spca50x->rawBufferSize - off;    }  /* can't read more than is available in the output buffer */  if (count > PAGE_SIZE)    {      count = PAGE_SIZE;    }  if (count == 0)    {      *eof = 1;      return 0;    }  /* populate the output buffer */  memcpy (page, spca50x->rawBuffer + off, count);  /* return read count */  return count;}static intspca50x_rawwrite_proc (struct file *file,		       const char *buffer, unsigned long count, void *data){  struct usb_spca50x *spca50x = data;  /* if anything is written, flush the buffer */  PDEBUG (3, "flushed raw proc entry buffer");  spca50x->rawBufferSize = 0;  return count;}#endif /* SPCA50X_ENABLE_RAWPROCENTRY *//* * Try to calculate value from string (atoi). Converts   * decimal integer */static inline intatoi (const char *str){  int result = 0;		//result of the function  int i;			//just an index variable  for (i = 0; str[i] >= '0' && str[i] <= '9'; i++)    {      result *= 10;      result += str[i] - '0';    }  return result;}static intspca50x_ctlwrite_proc (struct file *file, const char *buffer,		       unsigned long count, void *data){  int off;			//where look for a value  struct usb_spca50x *spca50x = data;  if ((off = match ("lum_level=", buffer, count)) >= 0)    spca50x->lum_level = atoi (buffer + off);  if ((off = match ("min_bpp=", buffer, count)) >= 0)    spca50x->min_bpp = atoi (buffer + off);  if ((off = match ("force_rgb=", buffer, count)) >= 0)    spca50x->force_rgb = atoi (buffer + off);  if ((off = match ("debug=", buffer, count)) >= 0)    debug = atoi (buffer + off);  return count;}static voidcreate_proc_spca50x_cam (struct usb_spca50x *spca50x){  char name[PROC_NAME_LEN];  struct proc_dir_entry *ent;  if (!spca50x_proc_entry || !spca50x)    return;//Create videoxx proc entry  sprintf (name, "video%d", spca50x->vdev->minor);  PDEBUG (4, "creating /proc/video/spca50x/%s", name);  ent =    create_proc_entry (name, S_IFREG | S_IRUGO | S_IWUSR, spca50x_proc_entry);  if (!ent)    return;  ent->data = spca50x;  ent->read_proc = spca50x_read_proc;  ent->write_proc = spca50x_write_proc;  spca50x->proc_entry = ent;// Create the controlxx proc entry  sprintf (name, "control%d", spca50x->vdev->minor);  PDEBUG (4, "creating /proc/video/spca50x/%s", name);  ent = create_proc_entry (name, S_IFREG | S_IRUGO | S_IWUSR,			   spca50x_proc_entry);  if (!ent)    return;  ent->data = spca50x;  ent->read_proc = spca50x_ctlread_proc;  ent->write_proc = spca50x_ctlwrite_proc;  spca50x->ctl_proc_entry = ent;#ifdef SPCA50X_ENABLE_RAWPROCENTRY// Create the rawxx proc entry  sprintf (name, "raw%d", spca50x->vdev.minor);  PDEBUG (4, "creating /proc/video/spca50x/%s", name);  ent = create_proc_entry (name, S_IFREG | S_IRUGO | S_IWUSR,			   spca50x_proc_entry);  if (!ent)    return;  ent->data = spca50x;  ent->read_proc = spca50x_rawread_proc;  ent->write_proc = spca50x_rawwrite_proc;  spca50x->raw_proc_entry = ent;  spca50x->rawBufferSize = 0;  spca50x->rawBuffer = vmalloc (10 * 1024 * 1024);  if (spca50x->rawBuffer != NULL)    {      spca50x->rawBufferMax = 10 * 1024 * 1024;      PDEBUG (3, "allocated 10Mb raw proc entry buffer");    }  else    {      PDEBUG (3, "vmalloc of raw proc entry buffer failed");      spca50x->rawBufferMax = 0;    }#endif /* SPCA50X_ENABLE_RAWPROCENTRY */}static voiddestroy_proc_spca50x_cam (struct usb_spca50x *spca50x){  char name[PROC_NAME_LEN];  if (!spca50x || !spca50x_proc_entry)    return;  /* destroy videoxx proc entry */  if (spca50x->proc_entry != NULL)    {      sprintf (name, "video%d", spca50x->vdev->minor);      PDEBUG (4, "destroying %s", name);      remove_proc_entry (name, spca50x_proc_entry);      spca50x->proc_entry = NULL;    }  /* destroy controlxx proc entry */  if (spca50x->ctl_proc_entry != NULL)    {      sprintf (name, "control%d", spca50x->vdev->minor);      PDEBUG (4, "destroying %s", name);      remove_proc_entry (name, spca50x_proc_entry);      spca50x->ctl_proc_entry = NULL;    }#ifdef SPCA50X_ENABLE_RAWPROCENTRY  /* destroy rawxx proc entry */  if (spca50x->raw_proc_entry != NULL)    {      sprintf (name, "raw%d", spca50x->vdev.minor);      remove_proc_entry (name, spca50x_proc_entry);      spca50x->raw_proc_entry = NULL;      vfree (spca50x->rawBuffer);    }#endif /* SPCA50X_ENABLE_RAWPROCENTRY */}static voidproc_spca50x_create (void){  /* No current standard here. Alan prefers /proc/video/ as it keeps   * /proc "less cluttered than /proc/randomcardifoundintheshed/"   * -claudio   */#ifdef CONFIG_VIDEO_PROC_FS  if (video_proc_entry == NULL)    {      err ("Unable to initialise /proc/video/spca50x");      return;    }  spca50x_proc_entry =    create_proc_entry ("spca50x", S_IFDIR, video_proc_entry);#else /* CONFIG_VIDEO_PROC_FS */  spca50x_proc_entry = create_proc_entry ("spca50x", S_IFDIR, 0);#endif /* CONFIG_VIDEO_PROC_FS */#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)  if (spca50x_proc_entry)    spca50x_proc_entry->owner = THIS_MODULE;  else#ifdef CONFIG_VIDEO_PROC_FS    err ("Unable to initialise /proc/video/spca50x");#else /* CONFIG_VIDEO_PROC_FS */    err ("Unable to initialise /proc/spca50x");#endif /* CONFIG_VIDEO_PROC_FS */#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) */}static voidproc_spca50x_destroy (void){#ifdef CONFIG_VIDEO_PROC_FS  PDEBUG (3, "removing /proc/video/spca50x");#else /* CONFIG_VIDEO_PROC_FS */  PDEBUG (3, "removing /proc/spca50x");#endif /* CONFIG_VIDEO_PROC_FS */  if (spca50x_proc_entry == NULL)    return;#ifdef CONFIG_VIDEO_PROC_FS  remove_proc_entry ("spca50x", video_proc_entry);#else /* CONFIG_VIDEO_PROC_FS */  remove_proc_entry ("spca50x", 0);#endif /* CONFIG_VIDEO_PROC_FS */}#endif /* CONFIG_PROC_FS *//********************************************************************** * * Camera interface * **********************************************************************//* Read a value from the I2C bus. Returns the value read */static intspca50x_read_i2c (struct usb_spca50x *spca50x, __u16 device, __u16 address){  struct usb_device *dev = spca50x->dev;  int err_code;  int retry;  int ctrl = spca50x->i2c_ctrl_reg;	//The I2C control register  int base = spca50x->i2c_base;	//The I2C base address  err_code = spca50x_reg_write (dev, ctrl, base + SPCA50X_I2C_DEVICE, device);  err_code =    spca50x_reg_write (dev, ctrl, base + SPCA50X_I2C_SUBADDR, address);  err_code =    spca50x_reg_write (dev, ctrl, base + SPCA50X_I2C_TRIGGER,		       SPCA50X_I2C_TRIGGER_BIT);  /* Hmm. 506 docs imply we should poll the ready register before reading the return value */  /* Poll the status register for a ready status */  /* Doesn't look like the windows driver does tho' */  retry = 60;  while (--retry)    {      err_code = spca50x_reg_read (dev, ctrl, base + SPCA50X_I2C_STATUS, 1);      if (err_code < 0)	PDEBUG (1, "Error reading I2C status register");      if (!err_code)	break;    }  if (!retry)    PDEBUG (1, "Too many retries polling I2C status after write to register");  err_code = spca50x_reg_read (dev, ctrl, base + SPCA50X_I2C_READ, 1);  if (err_code < 0)    PDEBUG (1, "Failed to read I2C register at %d:%d", device, address);  PDEBUG (3, "Read %d from %d:%d", err_code, device, address);  return err_code;}static intspca50x_read_SAA7113_status (struct usb_spca50x *spca50x){  int value = 0;  value =    spca50x_read_i2c (spca50x, SAA7113_I2C_BASE_READ, SAA7113_REG_STATUS);  if (value < 0)    PDEBUG (1, "Failed to read SAA7113 status");  PDEBUG (1, "7113 status : ");  PDEBUG (1, "  READY %s", (SAA7113_STATUS_READY (value) ? "YES" : "NO"));  PDEBUG (1, "  COPRO %s", (SAA7113_STATUS_COPRO (value) ? "YES" : "NO"));  /*PDEBUG(1,"  SLTCA %s",(SAA7113_STATUS_SLTCA(value)?"YES":"NO")); */  PDEBUG (1, "  WIPA  %s", (SAA7113_STATUS_WIPA (value) ? "YES" : "NO"));  PDEBUG (1, "  GLIMB %s", (SAA7113_STATUS_GLIMB (value) ? "YES" : "NO"));  PDEBUG (1, "  GLIMT %s", (SAA7113_STATUS_GLIMT (value) ? "YES" : "NO"));  PDEBUG (1, "  FIDT  %s", (SAA7113_STATUS_FIDT (value) ? "YES" : "NO"));  PDEBUG (1, "  HLVLN %s", (SAA7113_STATUS_HLVLN (value) ? "YES" : "NO"));  PDEBUG (1, "  INTL  %s", (SAA7113_STATUS_INTL (value) ? "YES" : "NO"));  return value;}static intspca50x_write_i2c (struct usb_spca50x *spca50x, __u16 device,		   __u16 subaddress, __u16 data){  struct usb_device *dev = spca50x->dev;  int err_code;  int retry;  int ctrl = spca50x->i2c_ctrl_reg;	//The I2C control register  int base = spca50x->i2c_base;	//The I2C base address  /* Tell the SPCA50x i2c subsystem the device address of the i2c device */  err_code = spca50x_reg_write (dev, ctrl, base + SPCA50X_I2C_DEVICE, device);  /* Poll the status register for a ready status */  retry = 60;			// Arbitrary  while (--retry)    {      err_code = spca50x_reg_read (dev, ctrl, base + SPCA50X_I2C_STATUS, 1);      if (err_code < 0)	PDEBUG (1, "Error reading I2C status register");      if (!err_code)	break;    }  if (!retry)    PDEBUG (1, "Too many retries polling I2C status");  err_code =    spca50x_reg_write (dev, ctrl, base + SPCA50X_I2C_SUBADDR, subaddress);  err_code = spca50x_reg_write (dev, ctrl, base + SPCA50X_I2C_VALUE, data);  if (spca50x->i2c_trigger_on_write)    err_code = spca50x_reg_write (dev, ctrl, base + SPCA50X_I2C_TRIGGER,				  SPCA50X_I2C_TRIGGER_BIT);  /* Poll the status register for a ready status */  retry = 60;  while (--retry)    {      err_code = spca50x_reg_read (dev, ctrl, SPCA50X_I2C_STATUS, 2);      if (err_code < 0)	PDEBUG (1, "Error reading I2C status register");      if (!err_code)	break;    }  if (!retry)    PDEBUG (1, "Too many retries polling I2C status after write to register");  if (debug > 2)    {      err_code = spca50x_read_i2c (spca50x, device, subaddress);      if (err_code < 0)	{	  PDEBUG (3, "Can't read back I2C register value for %d:%d",		  device, subaddress);	}      else if ((err_code & 0xff) != (data & 0xff))	PDEBUG (3, "Read back %x should be %x at subaddr %x",		err_code, data, subaddress);    }  return 0;}static intspca50x_write_i2c_vector (struct usb_spca50x *spca50x, __u16 device,			  __u16 data[][2]){  int I = 0;  while (data[I][0])    {      spca50x_write_i2c (spca50x, device, data[I][0], data[I][1]);      I++;    }  return 0;}static intspca50x_set_packet_size (struct usb_spca50x *spca50x, int size){  int alt;	/**********************************************************************/	/******** Try to find real Packet size from usb struct ****************/  struct usb_device *dev = spca50x->dev;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)  struct usb_interface_descriptor *interface = NULL;  struct usb_config_descriptor *config = dev->actconfig;#else  struct usb_host_interface *interface = NULL;  struct usb_interface *intf;#endif  int mysize = 0;  	/**********************************************************************/  if (size == 0)    alt = SPCA50X_ALT_SIZE_0;  else if (size == 128)    alt = SPCA50X_ALT_SIZE_128;  else if (size == 256)    alt = SPCA50X_ALT_SIZE_256;  else if (size == 384)    alt = SPCA50X_ALT_SIZE_384;  else if (size == 512)    alt = SPCA50X_ALT_SIZE_512;  else if (size == 640)    alt = SPCA50X_ALT_SIZE_640;  else if (size == 768)    alt = SPCA50X_ALT_SIZE_768;  else if (size == 896)    alt = SPCA50X_ALT_SIZE_896;  else if (size == 1023)    if (spca50x->bridge == BRIDGE_SONIX)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -