Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 103890
b: refs/heads/master
c: e2997a7
h: refs/heads/master
v: v3
  • Loading branch information
Hans de Goede authored and Mauro Carvalho Chehab committed Jul 20, 2008
1 parent ecf12f2 commit df71b3b
Show file tree
Hide file tree
Showing 5 changed files with 1,019 additions and 63 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 63eb9546dcb5e9dc39ab88a603dede8fdd18e717
refs/heads/master: e2997a72ddfafc25bd0c8f1f52bcf41979d5a559
3 changes: 2 additions & 1 deletion trunk/drivers/media/video/gspca/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
obj-$(CONFIG_GSPCA) += gspca_main.o gspca_stk014.o
obj-$(CONFIG_GSPCA) += gspca_main.o gspca_pac207.o gspca_stk014.o

gspca_main-objs := gspca.o
gspca_pac207-objs := pac207.o
gspca_stk014-objs := stk014.o
121 changes: 69 additions & 52 deletions trunk/drivers/media/video/gspca/gspca.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
MODULE_DESCRIPTION("GSPCA USB Camera Driver");
MODULE_LICENSE("GPL");

#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 0, 26)
static const char version[] = "0.0.26";
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 0, 30)
static const char version[] = "0.0.30";

static int video_nr = -1;

Expand Down Expand Up @@ -172,8 +172,7 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
{
int i, j;

PDEBUG(D_PACK, "add t:%d l:%d %02x %02x %02x %02x...",
packet_type, len, data[0], data[1], data[2], data[3]);
PDEBUG(D_PACK, "add t:%d l:%d", packet_type, len);

/* when start of a new frame, if the current frame buffer
* is not queued, discard the whole frame */
Expand Down Expand Up @@ -346,7 +345,6 @@ static int gspca_kill_transfer(struct gspca_dev *gspca_dev)
unsigned int i;

PDEBUG(D_STREAM, "kill transfer");
gspca_dev->streaming = 0;
for (i = 0; i < NURBS; ++i) {
urb = gspca_dev->pktbuf[i].urb;
if (urb == NULL)
Expand Down Expand Up @@ -501,9 +499,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
struct usb_host_endpoint *ep;
int n, ret;

ret = mutex_lock_interruptible(&gspca_dev->usb_lock);
if (ret < 0)
return ret;
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;

/* set the max alternate setting and loop until urb submit succeeds */
intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
Expand Down Expand Up @@ -531,6 +528,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
if (ret < 0) {
PDEBUG(D_ERR|D_STREAM,
"usb_submit_urb [%d] err %d", n, ret);
gspca_dev->streaming = 0;
gspca_kill_transfer(gspca_dev);
if (ret == -ENOSPC)
break; /* try the previous alt */
Expand All @@ -555,9 +553,9 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev)
return ret;
}

/* Note both the queue and the usb lock should be hold when calling this */
static void gspca_stream_off(struct gspca_dev *gspca_dev)
{
mutex_lock_interruptible(&gspca_dev->usb_lock);
gspca_dev->streaming = 0;
if (gspca_dev->present) {
gspca_dev->sd_desc->stopN(gspca_dev);
Expand All @@ -571,7 +569,6 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev)
wake_up_interruptible(&gspca_dev->wq);
PDEBUG(D_ERR|D_STREAM, "stream off no device ??");
}
mutex_unlock(&gspca_dev->usb_lock);
}

static int gspca_set_default_mode(struct gspca_dev *gspca_dev)
Expand Down Expand Up @@ -791,9 +788,7 @@ static int vidioc_try_fmt_cap(struct file *file,
{
int ret;

/* mutex_lock_interruptible(&gspca_dev->queue_lock); */
ret = try_fmt_cap(file, priv, fmt);
/* mutex_unlock(&gspca_dev->queue_lock); */
if (ret < 0)
return ret;
return 0;
Expand All @@ -812,16 +807,23 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
fmt->fmt.pix.width, fmt->fmt.pix.height);
}
#endif
mutex_lock_interruptible(&gspca_dev->queue_lock);
if (mutex_lock_interruptible(&gspca_dev->queue_lock))
return -ERESTARTSYS;
ret = try_fmt_cap(file, priv, fmt);
if (ret < 0)
goto out;

if (ret == gspca_dev->curr_mode)
goto out; /* same mode */
was_streaming = gspca_dev->streaming;
if (was_streaming != 0)
if (was_streaming != 0) {
if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
ret = -ERESTARTSYS;
goto out;
}
gspca_stream_off(gspca_dev);
mutex_unlock(&gspca_dev->usb_lock);
}
gspca_dev->width = (int) fmt->fmt.pix.width;
gspca_dev->height = (int) fmt->fmt.pix.height;
gspca_dev->pixfmt = fmt->fmt.pix.pixelformat;
Expand All @@ -840,26 +842,26 @@ static int dev_open(struct inode *inode, struct file *file)

PDEBUG(D_STREAM, "opening");
gspca_dev = (struct gspca_dev *) video_devdata(file);
ret = mutex_lock_interruptible(&gspca_dev->queue_lock);
if (ret < 0)
return ret;
if (mutex_lock_interruptible(&gspca_dev->queue_lock))
return -ERESTARTSYS;
if (!gspca_dev->present) {
ret = -ENODEV;
goto out;
}

/* if not done yet, initialize the sensor */
if (gspca_dev->users == 0) {
ret = mutex_lock_interruptible(&gspca_dev->usb_lock);
if (ret < 0)
if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
ret = -ERESTARTSYS;
goto out;
}
ret = gspca_dev->sd_desc->open(gspca_dev);
mutex_unlock(&gspca_dev->usb_lock);
if (ret != 0) {
PDEBUG(D_ERR|D_CONF, "init device failed %d", ret);
goto out;
}
} else if (gspca_dev->users > 8) { /* (arbitrary value) */
} else if (gspca_dev->users > 4) { /* (arbitrary value) */
ret = -EBUSY;
goto out;
}
Expand All @@ -886,21 +888,20 @@ static int dev_close(struct inode *inode, struct file *file)
struct gspca_dev *gspca_dev = file->private_data;

PDEBUG(D_STREAM, "closing");
if (gspca_dev->streaming) {
mutex_lock_interruptible(&gspca_dev->queue_lock);
gspca_stream_off(gspca_dev);
if (mutex_lock_interruptible(&gspca_dev->queue_lock))
return -ERESTARTSYS;
gspca_dev->users--;
if (gspca_dev->users > 0) {
mutex_unlock(&gspca_dev->queue_lock);
return 0;
}
mutex_lock_interruptible(&gspca_dev->usb_lock);

if (gspca_dev->streaming)
gspca_stream_off(gspca_dev);
gspca_dev->sd_desc->close(gspca_dev);
mutex_unlock(&gspca_dev->usb_lock);
atomic_inc(&gspca_dev->nevent);
wake_up_interruptible(&gspca_dev->wq); /* wake blocked processes */
schedule();
mutex_lock_interruptible(&gspca_dev->queue_lock);

frame_free(gspca_dev);
file->private_data = NULL;
gspca_dev->users--;
mutex_unlock(&gspca_dev->queue_lock);
PDEBUG(D_STREAM, "closed");
return 0;
Expand Down Expand Up @@ -964,7 +965,8 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
&& ctrl->value > ctrls->qctrl.maximum)
return -ERANGE;
PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
mutex_lock_interruptible(&gspca_dev->usb_lock);
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;
ret = ctrls->set(gspca_dev, ctrl->value);
mutex_unlock(&gspca_dev->usb_lock);
return ret;
Expand All @@ -985,7 +987,8 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
i++, ctrls++) {
if (ctrl->id != ctrls->qctrl.id)
continue;
mutex_lock_interruptible(&gspca_dev->usb_lock);
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;
ret = ctrls->get(gspca_dev, &ctrl->value);
mutex_unlock(&gspca_dev->usb_lock);
return ret;
Expand Down Expand Up @@ -1047,9 +1050,8 @@ static int vidioc_reqbufs(struct file *file, void *priv,
frsz = gspca_get_buff_size(gspca_dev);
if (frsz < 0)
return frsz;
ret = mutex_lock_interruptible(&gspca_dev->queue_lock);
if (ret < 0)
return ret;
if (mutex_lock_interruptible(&gspca_dev->queue_lock))
return -ERESTARTSYS;
ret = frame_alloc(gspca_dev,
rb->count,
(unsigned int) frsz,
Expand Down Expand Up @@ -1087,9 +1089,8 @@ static int vidioc_streamon(struct file *file, void *priv,
PDEBUG(D_STREAM, "stream on");
if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
ret = mutex_lock_interruptible(&gspca_dev->queue_lock);
if (ret < 0)
return ret;
if (mutex_lock_interruptible(&gspca_dev->queue_lock))
return -ERESTARTSYS;
if (!gspca_dev->present) {
ret = -ENODEV;
goto out;
Expand All @@ -1111,6 +1112,7 @@ static int vidioc_streamon(struct file *file, void *priv,
gspca_dev->height);
}
#endif
ret = 0;
out:
mutex_unlock(&gspca_dev->queue_lock);
return ret;
Expand All @@ -1125,8 +1127,14 @@ static int vidioc_streamoff(struct file *file, void *priv,
if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
if (gspca_dev->streaming) {
mutex_lock_interruptible(&gspca_dev->queue_lock);
if (mutex_lock_interruptible(&gspca_dev->queue_lock))
return -ERESTARTSYS;
if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
mutex_unlock(&gspca_dev->queue_lock);
return -ERESTARTSYS;
}
gspca_stream_off(gspca_dev);
mutex_unlock(&gspca_dev->usb_lock);
mutex_unlock(&gspca_dev->queue_lock);
}
return 0;
Expand All @@ -1140,7 +1148,8 @@ static int vidioc_g_jpegcomp(struct file *file, void *priv,

if (!gspca_dev->sd_desc->get_jcomp)
return -EINVAL;
mutex_lock_interruptible(&gspca_dev->usb_lock);
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;
ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp);
mutex_unlock(&gspca_dev->usb_lock);
return ret;
Expand All @@ -1152,7 +1161,8 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv,
struct gspca_dev *gspca_dev = priv;
int ret;

mutex_lock_interruptible(&gspca_dev->usb_lock);
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;
if (!gspca_dev->sd_desc->set_jcomp)
return -EINVAL;
ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp);
Expand All @@ -1177,7 +1187,8 @@ static int vidioc_s_parm(struct file *filp, void *priv,
struct gspca_dev *gspca_dev = priv;
int n;

mutex_lock_interruptible(&gspca_dev->usb_lock);
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;
n = parm->parm.capture.readbuffers;
if (n == 0 || n > GSPCA_MAX_FRAMES)
parm->parm.capture.readbuffers = gspca_dev->nbufread;
Expand Down Expand Up @@ -1230,10 +1241,8 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma)
size = vma->vm_end - vma->vm_start;
PDEBUG(D_STREAM, "mmap start:%08x size:%d", (int) start, (int) size);

ret = mutex_lock_interruptible(&gspca_dev->queue_lock);
if (ret < 0)
return ret;
/* sanity check disconnect, in use, no memory available */
if (mutex_lock_interruptible(&gspca_dev->queue_lock))
return -ERESTARTSYS;
if (!gspca_dev->present) {
ret = -ENODEV;
goto done;
Expand Down Expand Up @@ -1294,6 +1303,7 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma)
V4L2_BUF_FLAG_MAPPED;
}
#endif
ret = 0;
done:
mutex_unlock(&gspca_dev->queue_lock);
return ret;
Expand Down Expand Up @@ -1350,6 +1360,8 @@ static int gspca_frame_wait(struct gspca_dev *gspca_dev,
atomic_read(&gspca_dev->nevent) > 0);
if (ret != 0)
return ret;
if (!gspca_dev->streaming || !gspca_dev->present)
return -EIO;
i = gspca_dev->fr_o;
j = gspca_dev->fr_queue[i];
frame = &gspca_dev->frame[j];
Expand All @@ -1364,6 +1376,10 @@ static int gspca_frame_wait(struct gspca_dev *gspca_dev,
gspca_dev->fr_q,
gspca_dev->fr_i,
gspca_dev->fr_o);

if (gspca_dev->sd_desc->dq_callback)
gspca_dev->sd_desc->dq_callback(gspca_dev);

return j;
}

Expand Down Expand Up @@ -1435,9 +1451,9 @@ static int vidioc_qbuf(struct file *file, void *priv,
return -EINVAL;
}

ret = mutex_lock_interruptible(&gspca_dev->queue_lock);
if (ret < 0)
return ret;
if (mutex_lock_interruptible(&gspca_dev->queue_lock))
return -ERESTARTSYS;

if (frame->v4l2_buf.flags
& (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)) {
PDEBUG(D_STREAM, "qbuf bad state");
Expand Down Expand Up @@ -1708,11 +1724,12 @@ void gspca_disconnect(struct usb_interface *intf)
if (!gspca_dev)
return;
gspca_dev->present = 0;
mutex_lock_interruptible(&gspca_dev->queue_lock);
mutex_lock_interruptible(&gspca_dev->usb_lock);
mutex_lock(&gspca_dev->queue_lock);
mutex_lock(&gspca_dev->usb_lock);
gspca_dev->streaming = 0;
gspca_kill_transfer(gspca_dev);
mutex_unlock(&gspca_dev->queue_lock);
mutex_unlock(&gspca_dev->usb_lock);
mutex_unlock(&gspca_dev->queue_lock);
while (gspca_dev->users != 0) { /* wait until fully closed */
atomic_inc(&gspca_dev->nevent);
wake_up_interruptible(&gspca_dev->wq); /* wake processes */
Expand Down
17 changes: 8 additions & 9 deletions trunk/drivers/media/video/gspca/gspca.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,17 +90,18 @@ struct ctrl {
/* subdriver description */
struct sd_desc {
/* information */
char *name; /* sub-driver name */
char *name; /* sub-driver name */
/* controls */
struct ctrl *ctrls;
int nctrls;
/* operations */
cam_cf_op config; /* called on probe */
cam_op open; /* called on open */
cam_v_op start; /* called on stream on */
cam_v_op stopN; /* called on stream off - main alt */
cam_v_op stop0; /* called on stream off - alt 0 */
cam_v_op close; /* called on close */
cam_cf_op config; /* called on probe */
cam_op open; /* called on open */
cam_v_op start; /* called on stream on */
cam_v_op stopN; /* called on stream off - main alt */
cam_v_op stop0; /* called on stream off - alt 0 */
cam_v_op close; /* called on close */
cam_v_op dq_callback; /* called when a frame has been dequeued */
cam_pkt_op pkt_scan;
cam_jpg_op get_jcomp;
cam_jpg_op set_jcomp;
Expand Down Expand Up @@ -167,8 +168,6 @@ int gspca_dev_probe(struct usb_interface *intf,
const struct usb_device_id *id,
const struct sd_desc *sd_desc,
int dev_size);
int gspca_dev_init(struct gspca_dev *gspca_dev,
struct usb_interface *intf);
void gspca_disconnect(struct usb_interface *intf);
struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
int packet_type,
Expand Down
Loading

0 comments on commit df71b3b

Please sign in to comment.