This is a bug fixing patch against 2.5.44, it contains
John Tyner's simplified vicam_read
Bug fixes per Oliver Neukum
Other assorted bug fixes
--- linux-2.5.44/drivers/usb/media/vicam.c Mon Oct 21 14:09:13 2002
+++ linux-2.5.44-vicam/drivers/usb/media/vicam.c Tue Oct 22 11:18:15
2002
@@ -1,6 +1,7 @@
/*
* USB ViCam WebCam driver
- * Copyright (c) 2002 Joe Burks ([EMAIL PROTECTED])
+ * Copyright (c) 2002 Joe Burks <[EMAIL PROTECTED]>
+ * Copyright (c) 2002 John Tyner <[EMAIL PROTECTED]>
*
* Supports 3COM HomeConnect PC Digital WebCam
*
@@ -39,9 +40,10 @@
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
+#include <linux/ctype.h>
#include "usbvideo.h"
-// #define VICAM_DEBUG
+//#define VICAM_DEBUG
#ifndef MODULE_LICENSE
#define MODULE_LICENSE(a)
@@ -421,9 +423,6 @@
u8 bulkEndpoint;
bool needsDummyRead;
- u32 framebuf_size; // # of valid bytes in framebuf
- u32 framebuf_read_start; // position in frame buf that a
read is happening at.
-
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_entry;
#endif
@@ -748,27 +747,30 @@
struct video_device *dev = video_devdata(file);
struct vicam_camera *cam =
(struct vicam_camera *) dev->priv;
+ int ret = 0;
+
DBG("open\n");
if (!cam) {
printk(KERN_ERR
"vicam video_device improperly initialized");
}
-
- down_interruptible(&cam->busy_lock);
-
+
+ if ( down_interruptible(&cam->busy_lock) )
+ return -EINTR;
+
if (cam->open_count > 0) {
printk(KERN_INFO
"vicam_open called on already opened camera");
- up(&cam->busy_lock);
- return -EBUSY;
+ ret = -EBUSY;
+ goto fail;
}
if (!cam->raw_image) {
cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL);
if (!cam->raw_image) {
- up(&cam->busy_lock);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto fail;
}
}
@@ -776,21 +778,28 @@
cam->framebuf =
rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
if (!cam->framebuf) {
- kfree(cam->raw_image);
- up(&cam->busy_lock);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto fail;
}
}
// First upload firmware, then turn the camera on
-
if (!cam->is_initialized) {
- initialize_camera(cam);
+ if ( initialize_camera(cam) < 0 ) {
+ DBG("Error during firmware upload.\n");
+ ret = -EIO;
+ goto fail;
+ }
+ DBG("Firmware uploaded");
cam->is_initialized = 1;
}
- set_camera_power(cam, 1);
-
+ if ( set_camera_power(cam, 1) < 0 ) {
+ DBG("Could not power camera on.\n");
+ ret = -EIO;
+ goto fail;
+ }
+
cam->needsDummyRead = 1;
cam->open_count++;
@@ -799,6 +808,12 @@
file->private_data = cam;
return 0;
+
+fail:
+ up(&cam->busy_lock);
+ if ( cam->raw_image ) kfree(cam->raw_image) ;
+ if ( cam->framebuf ) rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE *
VICAM_FRAMES);
+ return ret;
}
static int
@@ -924,6 +939,11 @@
int n;
int actual_length;
+ if (cam->needsDummyRead) {
+ cam->needsDummyRead = 0;
+ read_frame(cam, framenum);
+ }
+
memset(request, 0, 16);
request[0] = cam->gain; // 0 = 0% gain, FF = 100% gain
@@ -936,8 +956,9 @@
// Short exposure
realShutter =
((-15631900 / cam->shutter_speed) + 260533) / 1000;
- request[4] = realShutter & 0xFF;
- request[5] = (realShutter >> 8) & 0xFF;
+ *((u16 *)&request[4]) = cpu_to_le16(realShutter);
+ //request[4] = realShutter & 0xFF;
+ //request[5] = (realShutter >> 8) & 0xFF;
request[6] = 0x03;
request[7] = 0x01;
} else {
@@ -945,8 +966,9 @@
realShutter = 15600 / cam->shutter_speed - 1;
request[4] = 0;
request[5] = 0;
- request[6] = realShutter & 0xFF;
- request[7] = realShutter >> 8;
+ *((u16 *)&request[6]) = cpu_to_le16(realShutter);
+ //request[6] = realShutter & 0xFF;
+ //request[7] = realShutter >> 8;
}
// Per John Markus Bjørndalen, byte at index 8 causes problems if
it isn't 0
@@ -974,74 +996,39 @@
vicam_decode_color(cam->raw_image,
cam->framebuf +
framenum * VICAM_MAX_FRAME_SIZE );
-
- cam->framebuf_size =
- 320 * 240 * VICAM_BYTES_PER_PIXEL;
- cam->framebuf_read_start = 0;
-
- return;
-
}
static int
vicam_read( struct file *file, char *buf, size_t count, loff_t *ppos )
{
struct vicam_camera *cam = file->private_data;
- DBG("read %d bytes.\n", (int) count);
- if (!buf)
- return -EINVAL;
+ DBG("read %d bytes.\n", (int) count);
- if (!count)
- return -EINVAL;
+ if ( down_interruptible(&cam->busy_lock) )
+ return -EINTR;
- // This is some code that will hopefully allow us to do shell
copies from
- // the /dev/videoX to a file and have it actually work.
- if (cam->framebuf_size != 0) {
- if (cam->framebuf_read_start == cam->framebuf_size) {
- cam->framebuf_size = cam->framebuf_read_start = 0;
- return 0;
- } else {
- if (cam->framebuf_read_start + count <=
- cam->framebuf_size) {
- // count does not exceed available bytes
- copy_to_user(buf,
- (cam->framebuf) +
- cam->framebuf_read_start, count);
- cam->framebuf_read_start += count;
- return count;
- } else {
- count =
- cam->framebuf_size -
- cam->framebuf_read_start;
- copy_to_user(buf,
- (cam->framebuf) +
- cam->framebuf_read_start, count);
- cam->framebuf_read_start = cam->framebuf_size;
- return count;
- }
- }
+ if (*ppos >= VICAM_MAX_FRAME_SIZE) {
+ *ppos = 0;
+ up(&cam->busy_lock);
+ return 0;
}
- down_interruptible(&cam->busy_lock);
-
- if (cam->needsDummyRead) {
+ if (*ppos == 0) {
read_frame(cam, 0);
- cam->needsDummyRead = 0;
}
- // read_frame twice because the camera doesn't seem to take the
shutter speed for the first one.
-
- read_frame(cam, 0);
- if (count > cam->framebuf_size)
- count = cam->framebuf_size;
+ count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos);
- copy_to_user(buf, cam->framebuf, count);
-
- if (count != cam->framebuf_size)
- cam->framebuf_read_start = count;
- else
- cam->framebuf_size = 0;
+ if (copy_to_user(buf, &cam->framebuf[*ppos], count)) {
+ count = -EFAULT;
+ } else {
+ *ppos += count;
+ }
+
+ if (count == VICAM_MAX_FRAME_SIZE) {
+ *ppos = 0;
+ }
up(&cam->busy_lock);
@@ -1115,7 +1102,6 @@
out +=
sprintf(out, "Vicam-based WebCam Linux Driver.\n");
- out += sprintf(out, "(c) 2002 Joe Burks ([EMAIL PROTECTED])\n");
out += sprintf(out, "vicam stats:\n");
out += sprintf(out, " Shutter Speed: 1/%d\n", cam->shutter_speed);
out += sprintf(out, " Gain: %d\n", cam->gain);
@@ -1134,34 +1120,97 @@
}
static int
-vicam_write_proc(struct file *file, const char *buffer,
+vicam_write_proc(struct file *file, const char *buf,
unsigned long count, void *data)
{
- char *in;
- char *start;
struct vicam_camera *cam = (struct vicam_camera *) data;
+ int retval = 0;
+ int size = count;
+ char *_p,*buffer,*page;
- in = kmalloc(count + 1, GFP_KERNEL);
- if (!in)
- return -ENOMEM;
+ /*
+ * This code to copy from buf to page is shamelessly copied
+ * from the comx driver
+ */
+ if (count > PAGE_SIZE) {
+ printk(KERN_ERR "count is %lu > %d!!!\n", count,
(int)PAGE_SIZE);
+ return -ENOSPC;
+ }
- in[count] = 0; // I'm not sure buffer is gauranteed to be
null terminated
- // so I do this to make sure I have a null in there.
+ if (!(page = (char *)__get_free_page(GFP_KERNEL))) return -ENOMEM;
- strncpy(in, buffer, count);
+ if(copy_from_user(page, buf, count))
+ {
+ retval = -EFAULT;
+ goto out;
+ }
- start = strstr(in, "gain=");
- if (start
- && (start == in || *(start - 1) == ' ' || *(start - 1) == ','))
- cam->gain = simple_strtoul(start + 5, NULL, 10);
-
- start = strstr(in, "shutter=");
- if (start
- && (start == in || *(start - 1) == ' ' || *(start - 1) == ','))
- cam->shutter_speed = simple_strtoul(start + 8, NULL, 10);
+ if (page[count-1] == '\n')
+ page[count-1] = '\0';
+ else if (count < PAGE_SIZE)
+ page[count] = '\0';
+ else if (page[count]) {
+ retval = -EINVAL;
+ goto out;
+ }
+
+ buffer = page;
+
+ while ( count ) {
+ // skip over leading white space
+ while ( count && isspace(*buffer)) {
+ --count;
+ ++buffer;
+ }
- kfree(in);
- return count;
+ if ( count == 0 || *buffer == '\0' ) {
+ retval = size;
+ break;
+ }
+
+ if ( count >= 5 && strncmp(buffer,"gain=",5) == 0 ) {
+ count -= 5;
+ buffer += 5;
+
+ if ( !count ) {
+ retval = -EINVAL;
+ break;
+ }
+
+ cam->gain = simple_strtoul(buffer, &_p, 0);
+ if ( _p == buffer ) {
+ retval = -EINVAL;
+ break;
+ } else {
+ count -= _p - buffer;
+ buffer = _p;
+ }
+ } else if ( count >= 8 && strncmp(buffer, "shutter=", 8) ==
0 ) {
+ count -= 8;
+ buffer += 8;
+
+ if ( !count ) {
+ retval = -EINVAL;
+ break;
+ }
+
+ cam->shutter_speed = simple_strtoul(buffer, &_p, 0);
+ cam->needsDummyRead = 1;
+ if ( _p == buffer ) {
+ retval = -EINVAL;
+ break;
+ } else {
+ count -= _p - buffer;
+ buffer = _p;
+ }
+ } else {
+ retval = -EINVAL;
+ break;
+ }
+ }
+out:
+ free_page((unsigned long)page);
+ return retval;
}
void
@@ -1188,7 +1237,7 @@
{
struct vicam_camera *cam = (struct vicam_camera *) ptr;
- char name[7];
+ char name[15];
struct proc_dir_entry *ent;
DBG(KERN_INFO "vicam: creating proc entry\n");
@@ -1205,8 +1254,10 @@
ent =
create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
vicam_proc_root);
- if (!ent)
+ if (!ent) {
+ printk(KERN_INFO "vicam: could not create proc entry for
%s",name);
return;
+ }
ent->data = cam;
ent->read_proc = vicam_read_proc;
@@ -1219,7 +1270,7 @@
vicam_destroy_proc_entry(void *ptr)
{
struct vicam_camera *cam = (struct vicam_camera *) ptr;
- char name[7];
+ char name[15];
if (!cam || !cam->proc_entry)
return;
@@ -1232,16 +1283,6 @@
#endif
-int
-vicam_video_init(struct video_device *vdev)
-{
- // This would normally create the proc entry for this camera
-#ifdef CONFIG_PROC_FS
- vicam_create_proc_entry(vdev->priv);
-#endif
- return 0;
-}
-
static struct file_operations vicam_fops = {
.owner = THIS_MODULE,
.open = vicam_open,
@@ -1258,7 +1299,6 @@
.type = VID_TYPE_CAPTURE,
.hardware = VID_HARDWARE_VICAM,
.fops = &vicam_fops,
-// .initialize = vicam_video_init,
.minor = -1,
};
@@ -1302,8 +1342,6 @@
interface = &intf->altsetting[0];
- DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n",
- ifnum, (unsigned) (interface->bNumEndpoints));
endpoint = &interface->endpoint[0];
if ((endpoint->bEndpointAddress & 0x80) &&
@@ -1335,12 +1373,16 @@
cam->udev = dev;
cam->bulkEndpoint = bulkEndpoint;
+ usb_set_interface(cam->udev, interface->bInterfaceNumber,0);
+
if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) == -1) {
kfree(cam);
printk(KERN_WARNING "video_register_device failed\n");
return -EIO;
}
+ vicam_create_proc_entry(cam);
+
printk(KERN_INFO "ViCam webcam driver now controlling video device
%d\n",cam->vdev.minor);
dev_set_drvdata(&intf->dev, cam);
@@ -1354,16 +1396,15 @@
struct vicam_camera *cam = dev_get_drvdata(&intf->dev);
dev_set_drvdata ( &intf->dev, NULL );
- usb_put_dev(cam->udev);
cam->udev = NULL;
- video_unregister_device(&cam->vdev);
-
#ifdef CONFIG_PROC_FS
vicam_destroy_proc_entry(cam);
#endif
+ video_unregister_device(&cam->vdev);
+
if (cam->raw_image)
kfree(cam->raw_image);
if (cam->framebuf)
-------------------------------------------------------
This sf.net emial is sponsored by: Influence the future
of Java(TM) technology. Join the Java Community
Process(SM) (JCP(SM)) program now.
http://ad.doubleclick.net/clk;4699841;7576301;v?http://www.sun.com/javavote
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
- [linux-usb-devel] [PATCH] drivers/usb/media/vicam.c: simplif... John Tyner
- [linux-usb-devel] Re: [PATCH] drivers/usb/media/vicam.c... John Tyner
- [linux-usb-devel] Re: [PATCH] drivers/usb/media/vic... Greg KH
- Re: [linux-usb-devel] Re: [PATCH] drivers/usb/media... Joe Burks
- Re: [linux-usb-devel] Re: [PATCH] drivers/usb/m... Joe Burks
- Re: [linux-usb-devel] Re: [PATCH] drivers/usb/m... John Tyner
- Re: [linux-usb-devel] [PATCH] linux-2.5.44/... Joe Burks
- Re: [linux-usb-devel] [PATCH] linux-2.... Oliver Neukum
- Re: [linux-usb-devel] [PATCH] linux-2.... Greg KH
- Re: [linux-usb-devel] [PATCH] linu... Joe Burks
- Re: [linux-usb-devel] [PATCH] ... Greg KH
- Re: [linux-usb-devel] [PATCH] ... Joe Burks
- Re: [linux-usb-devel] [PATCH] ... Greg KH
- [linux-usb-devel] Re: [PATCH] drivers/usb/media/vicam.c... Greg KH