At 09:52 PM 10/21/2002 -0700, John Tyner wrote:
This is in addition to the previous patch. It should allow any programs
that read entire frames to receive a new frame with each successive read.
Programs that read less than the entire frame will read until they reach
the end of the frame. They will then read 0 bytes (signifying EOF). The
next read will start the next frame.
I like the much simpler code! It has two small, fixable issues in vicam_read:

You no longer check buf against NULL, can a misbehaved program cause a problematic seg fault in the kernel?

from your patch file:

+ down_interruptible(&cam->busy_lock);
[...]
+ if (*ppos >= VICAM_MAX_FRAME_SIZE) {
+ *ppos = 0;
+ return 0;
}

I'm betting that semaphore needs to be upped before returning :)

Also, I fixed the problem with insmod vicam / rmmod vicam / insmod vicam seg faulting.

Here's the patch against 2.5.44:

--- 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 02:25:05 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
*
@@ -41,7 +42,7 @@
#include <linux/proc_fs.h>
#include "usbvideo.h"

-// #define VICAM_DEBUG
+#define VICAM_DEBUG

#ifndef MODULE_LICENSE
#define MODULE_LICENSE(a)
@@ -421,9 +422,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
@@ -754,9 +752,9 @@
printk(KERN_ERR
"vicam video_device improperly initialized");
}
-
+
down_interruptible(&cam->busy_lock);
-
+
if (cam->open_count > 0) {
printk(KERN_INFO
"vicam_open called on already opened camera");
@@ -782,15 +780,15 @@
}
}
// First upload firmware, then turn the camera on
-
if (!cam->is_initialized) {
initialize_camera(cam);
+ DBG("Firmware uploaded");

cam->is_initialized = 1;
}

set_camera_power(cam, 1);
-
+
cam->needsDummyRead = 1;
cam->open_count++;

@@ -924,6 +922,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

@@ -974,74 +977,37 @@
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;
+ down_interruptible(&cam->busy_lock);

- // 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;
+ 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);
+ count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos);

- if (count > cam->framebuf_size)
- count = cam->framebuf_size;
-
- 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);

@@ -1205,8 +1171,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;
@@ -1232,16 +1200,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 +1216,6 @@
.type = VID_TYPE_CAPTURE,
.hardware = VID_HARDWARE_VICAM,
.fops = &vicam_fops,
-// .initialize = vicam_video_init,
.minor = -1,
};

@@ -1302,8 +1259,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 +1290,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 +1313,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


Reply via email to