patch-2.4.10 linux/drivers/usb/se401.c
Next file: linux/drivers/usb/se401.h
Previous file: linux/drivers/usb/scanner.h
Back to the patch index
Back to the overall index
- Lines: 213
- Date:
Fri Sep 14 14:27:10 2001
- Orig file:
v2.4.9/linux/drivers/usb/se401.c
- Orig date:
Sun Aug 12 13:28:00 2001
diff -u --recursive --new-file v2.4.9/linux/drivers/usb/se401.c linux/drivers/usb/se401.c
@@ -25,7 +25,7 @@
* - Jeroen Vreeken
*/
-static const char version[] = "0.22";
+static const char version[] = "0.23";
#include <linux/config.h>
#include <linux/module.h>
@@ -66,6 +66,7 @@
MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>");
MODULE_DESCRIPTION("SE401 USB Camera Driver");
+MODULE_LICENSE("GPL");
MODULE_PARM(flickerless, "i");
MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)");
MODULE_PARM(video_nr, "i");
@@ -1034,8 +1035,8 @@
}
}
}
-
- if (se401->frame[framenr].grabstate==FRAME_DONE)
+
+ if (se401->frame[framenr].grabstate==FRAME_DONE)
if (se401->enhance)
enhance_picture(se401->frame[framenr].data, se401->cheight*se401->cwidth*3);
return 0;
@@ -1054,32 +1055,27 @@
struct usb_se401 *se401 = (struct usb_se401 *)dev;
int err = 0;
+ /* we are called with the BKL held */
MOD_INC_USE_COUNT;
- down(&se401->lock);
+ se401->user=1;
se401->fbuf=rvmalloc(se401->maxframesize * SE401_NUMFRAMES);
if(!se401->fbuf) err=-ENOMEM;
if (err) {
MOD_DEC_USE_COUNT;
- up(&se401->lock);
- return err;
+ se401->user = 0;
}
-
- se401->user=1;
- up(&se401->lock);
-
- return 0;
+ return err;
}
static void se401_close(struct video_device *dev)
{
+ /* called with BKL held */
struct usb_se401 *se401 = (struct usb_se401 *)dev;
int i;
- down(&se401->lock);
-
for (i=0; i<SE401_NUMFRAMES; i++)
se401->frame[i].grabstate=FRAME_UNUSED;
if (se401->streaming)
@@ -1087,9 +1083,8 @@
rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES);
se401->user=0;
- up(&se401->lock);
- if (!se401->dev) {
+ if (se401->removed) {
video_unregister_device(&se401->vdev);
kfree(se401->width);
kfree(se401->height);
@@ -1205,7 +1200,7 @@
return -EINVAL;
if (se401_set_size(se401, vw.width, vw.height))
return -EINVAL;
-
+
return 0;
}
case VIDIOCGWIN:
@@ -1280,7 +1275,7 @@
if(frame <0 || frame >= SE401_NUMFRAMES)
return -EINVAL;
-
+
ret=se401_newframe(se401, frame);
se401->frame[frame].grabstate=FRAME_UNUSED;
return ret;
@@ -1350,12 +1345,11 @@
ret=se401_newframe(se401, 0);
- if (!ret) {
- copy_to_user(buf, se401->frame[0].data, realcount);
- } else {
- realcount=ret;
- }
se401->frame[0].grabstate=FRAME_UNUSED;
+ if (ret)
+ return ret;
+ if (copy_to_user(buf, se401->frame[0].data, realcount))
+ return -EFAULT;
return realcount;
}
@@ -1368,7 +1362,7 @@
unsigned long page, pos;
down(&se401->lock);
-
+
if (se401->dev == NULL) {
up(&se401->lock);
return -EIO;
@@ -1487,7 +1481,7 @@
info("int urb burned down");
return 1;
}
-
+
/* Flash the led */
se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
@@ -1555,33 +1549,45 @@
info("firmware version: %02x", dev->descriptor.bcdDevice & 255);
- if (se401_init(se401))
+ if (se401_init(se401)) {
+ kfree(se401);
return NULL;
+ }
+
memcpy(&se401->vdev, &se401_template, sizeof(se401_template));
memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name));
+ init_waitqueue_head(&se401->wq);
+ init_MUTEX(&se401->lock);
+ wmb();
+
if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+ kfree(se401);
err("video_register_device failed");
return NULL;
}
info("registered new video device: video%d", se401->vdev.minor);
- init_waitqueue_head(&se401->wq);
- init_MUTEX(&se401->lock);
-
return se401;
}
static void se401_disconnect(struct usb_device *dev, void *ptr)
{
- int i;
struct usb_se401 *se401 = (struct usb_se401 *) ptr;
+ lock_kernel();
/* We don't want people trying to open up the device */
- if (!se401->user)
- video_unregister_device(&se401->vdev);
+ if (!se401->user){
+ video_unregister_device(&se401->vdev);
+ usb_se401_remove_disconnected(se401);
+ } else {
+ se401->removed = 1;
+ }
+ unlock_kernel();
+}
- usb_driver_release_interface(&se401_driver,
- &se401->dev->actconfig->interface[se401->iface]);
+static inline void usb_se401_remove_disconnected (struct usb_se401 *se401)
+{
+ int i;
se401->dev = NULL;
se401->frame[0].grabstate = FRAME_ERROR;
@@ -1589,8 +1595,7 @@
se401->streaming = 0;
- if (waitqueue_active(&se401->wq))
- wake_up_interruptible(&se401->wq);
+ wake_up_interruptible(&se401->wq);
for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) {
se401->urb[i]->next = NULL;
@@ -1613,14 +1618,10 @@
#endif
/* Free the memory */
- if (!se401->user) {
- kfree(se401->width);
- kfree(se401->height);
- kfree(se401);
- se401 = NULL;
- }
+ kfree(se401->width);
+ kfree(se401->height);
+ kfree(se401);
}
-
static struct usb_driver se401_driver = {
name: "se401",
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)