ChangeSet 1.1005.1.11, 2003/06/27 16:01:00-07:00, oliver@neukum.org [PATCH] USB: disconnect of v4l devices in 2.4 in 2.4 video_unregister_device() has lost its magic properties breaking most USB v4l drivers. IMHO they should be converted to delayed freeing resources just like ordinary character devices. Here's the change for vicam.c. drivers/usb/vicam.c | 43 +++++++++++++++++++++++++++++++++---------- 1 files changed, 33 insertions(+), 10 deletions(-) diff -Nru a/drivers/usb/vicam.c b/drivers/usb/vicam.c --- a/drivers/usb/vicam.c Fri Jun 27 16:27:04 2003 +++ b/drivers/usb/vicam.c Fri Jun 27 16:27:04 2003 @@ -367,7 +367,8 @@ struct semaphore busy_lock; // guard against SMP multithreading bool is_initialized; - u8 open_count; + bool is_removed; + bool is_opened; u8 bulkEndpoint; bool needsDummyRead; @@ -704,6 +705,7 @@ { struct vicam_camera *cam = (struct vicam_camera *) dev->priv; + int intr; DBG("open\n"); if (!cam) { @@ -711,9 +713,11 @@ "vicam video_device improperly initialized"); } - down_interruptible(&cam->busy_lock); + intr = down_interruptible(&cam->busy_lock); + if (intr) + return -EINTR; - if (cam->open_count > 0) { + if (cam->is_opened) { printk(KERN_INFO "vicam_open called on already opened camera"); up(&cam->busy_lock); @@ -748,7 +752,7 @@ set_camera_power(cam, 1); cam->needsDummyRead = 1; - cam->open_count++; + cam->is_opened = 1; up(&cam->busy_lock); @@ -759,9 +763,13 @@ vicam_close(struct video_device *dev) { DBG("close\n"); - set_camera_power((struct vicam_camera *) dev->priv, 0); + struct vicam_camera *cam = (struct vicam_camera *) dev->priv; - ((struct vicam_camera *) dev->priv)->open_count--; + set_camera_power(cam, 0); + if (cam->is_removed) + vicam_purge(cam); + else + cam->is_opened = 0; } inline int pin(int x) @@ -772,7 +780,7 @@ inline void writepixel(char *rgb, int Y, int Cr, int Cb) { Y = 1160 * (Y - 16); - + rgb[2] = pin( ( ( Y + ( 1594 * Cr ) ) + 500 ) / 1300 ); rgb[1] = pin( ( ( Y - ( 392 * Cb ) - ( 813 * Cr ) ) + 500 ) / 1000 ); rgb[0] = pin( ( ( Y + ( 2017 * Cb ) ) + 500 ) / 900 ); @@ -939,6 +947,7 @@ unsigned long count, int noblock) { struct vicam_camera *cam = dev->priv; + int intr; DBG("read %d bytes.\n", (int) count); if (!buf) @@ -975,7 +984,9 @@ } } - down_interruptible(&cam->busy_lock); + intr = down_interruptible(&cam->busy_lock); + if (intr) + return -EINTR; if (cam->needsDummyRead) { read_frame(cam, 0); @@ -1306,10 +1317,10 @@ return cam; } + static void -vicam_disconnect(struct usb_device *dev, void *ptr) +vicam_purge(struct vicam_camera *cam) { - struct vicam_camera *cam = ptr; video_unregister_device(&cam->vdev); #ifdef CONFIG_PROC_FS @@ -1325,6 +1336,18 @@ kfree(cam); printk(KERN_DEBUG "ViCam-based WebCam disconnected\n"); +} + +static void +vicam_disconnect(struct usb_device *dev, void *ptr) +{ + struct vicam_camera *cam = ptr; + + if (cam->is_opened) { + cam->is_removed = 1; + } else { + vicam_purge(cam); + } } /*