📄 spca5xx.c
字号:
spca50x_write_proc (struct file *file, const char *buffer, unsigned long count, void *data){ return -EINVAL;}/* * Function services read requests to control proc entry * and prints all the static variables */static intspca50x_ctlread_proc (char *page, char **start, off_t off, int count, int *eof, void *data){ char *out = page; int len = 0; struct usb_spca50x *spca50x = data; out += sprintf (out, "force_rgb = %d\n", spca50x->force_rgb); out += sprintf (out, "min_bpp = %d\n", spca50x->min_bpp); out += sprintf (out, "lum_level = %d\n", spca50x->lum_level); out += sprintf (out, "debug = %d\n", debug);#ifdef SPCA50X_ENABLE_OSD out += sprintf (out, "osd = %d\n", osd);#endif /* SPCA50X_ENABLE_OSD */ len = out - page; len -= off; if (len < count) { *eof = 1; if (len <= 0) return 0; } else len = count; *start = page + off; return len;}/* * Function compares two strings. * Return offset in pussy where prick ends if "prick" may penetrate * int "pussy" like prick into pussy, -1 otherwise. */static inline intmatch (const char *prick, const char *pussy, int len2){ int len1 = strlen (prick); //length of male string int i; //just an index variable const char *tmp; //temporary pointer for my own pleasure // We skip all spaces and tabs for (i = 0; i < len2 && (pussy[i] == ' ' || pussy[i] == '\t'); i++) { } tmp = pussy + i; // pointer to pussy with skipped shit (spaces and tabs) len2 = strlen (tmp); //calculate length again if (len1 > len2) return -1; //Fuck off, no fucking if (!strncmp (prick, tmp, len1)) return i + len1; return -1;}#ifdef SPCA50X_ENABLE_RAWPROCENTRYstatic intspca50x_rawread_proc (char *page, char **start, off_t off, int count, int *eof, void *data){ 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -