Commit 4aa0d037 authored by Jean-Francois Moine's avatar Jean-Francois Moine Committed by Mauro Carvalho Chehab

V4L/DVB (8154): Fix protection problems in the main driver.

- Protect format change when streaming active.
- Protect USB exchanges on close.
- Set a timeout in frame wait.
- Have only one capture file and free the resources when closing this file.
- Simplify the URB buffer.
- Don't reset the control values at open time in pac207.
- Fix compilation warnings of stk014.
Signed-off-by: default avatarJean-Francois Moine <moinejf@free.fr>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent e2997a72
...@@ -39,8 +39,8 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); ...@@ -39,8 +39,8 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
MODULE_DESCRIPTION("GSPCA USB Camera Driver"); MODULE_DESCRIPTION("GSPCA USB Camera Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 0, 30) #define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 1, 1)
static const char version[] = "0.0.30"; static const char version[] = "0.1.1";
static int video_nr = -1; static int video_nr = -1;
...@@ -346,22 +346,17 @@ static int gspca_kill_transfer(struct gspca_dev *gspca_dev) ...@@ -346,22 +346,17 @@ static int gspca_kill_transfer(struct gspca_dev *gspca_dev)
PDEBUG(D_STREAM, "kill transfer"); PDEBUG(D_STREAM, "kill transfer");
for (i = 0; i < NURBS; ++i) { for (i = 0; i < NURBS; ++i) {
urb = gspca_dev->pktbuf[i].urb; urb = gspca_dev->urb[i];
if (urb == NULL) if (urb == NULL)
continue; continue;
gspca_dev->pktbuf[i].urb = NULL; gspca_dev->urb[i] = NULL;
usb_kill_urb(urb); usb_kill_urb(urb);
if (urb->transfer_buffer != 0)
/* urb->transfer_buffer_length is not touched by USB core,
* so we can use it here as the buffer length */
if (gspca_dev->pktbuf[i].data) {
usb_buffer_free(gspca_dev->dev, usb_buffer_free(gspca_dev->dev,
urb->transfer_buffer_length, urb->transfer_buffer_length,
gspca_dev->pktbuf[i].data, urb->transfer_buffer,
urb->transfer_dma); urb->transfer_dma);
gspca_dev->pktbuf[i].data = NULL;
}
usb_free_urb(urb); usb_free_urb(urb);
} }
return 0; return 0;
...@@ -460,25 +455,25 @@ static int create_urbs(struct gspca_dev *gspca_dev, ...@@ -460,25 +455,25 @@ static int create_urbs(struct gspca_dev *gspca_dev,
err("usb_alloc_urb failed"); err("usb_alloc_urb failed");
return -ENOMEM; return -ENOMEM;
} }
gspca_dev->pktbuf[n].data = usb_buffer_alloc(gspca_dev->dev, urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev,
bsize, bsize,
GFP_KERNEL, GFP_KERNEL,
&urb->transfer_dma); &urb->transfer_dma);
if (gspca_dev->pktbuf[n].data == NULL) { if (urb->transfer_buffer == NULL) {
usb_free_urb(urb); usb_free_urb(urb);
gspca_kill_transfer(gspca_dev); gspca_kill_transfer(gspca_dev);
err("usb_buffer_urb failed"); err("usb_buffer_urb failed");
return -ENOMEM; return -ENOMEM;
} }
gspca_dev->pktbuf[n].urb = urb; gspca_dev->urb[n] = urb;
urb->dev = gspca_dev->dev; urb->dev = gspca_dev->dev;
urb->context = gspca_dev; urb->context = gspca_dev;
urb->pipe = usb_rcvisocpipe(gspca_dev->dev, urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
ep->desc.bEndpointAddress); ep->desc.bEndpointAddress);
urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; urb->transfer_flags = URB_ISO_ASAP
| URB_NO_TRANSFER_DMA_MAP;
urb->interval = ep->desc.bInterval; urb->interval = ep->desc.bInterval;
urb->transfer_buffer = gspca_dev->pktbuf[n].data;
urb->complete = isoc_irq; urb->complete = isoc_irq;
urb->number_of_packets = npkt; urb->number_of_packets = npkt;
urb->transfer_buffer_length = bsize; urb->transfer_buffer_length = bsize;
...@@ -523,8 +518,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) ...@@ -523,8 +518,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
/* submit the URBs */ /* submit the URBs */
for (n = 0; n < NURBS; n++) { for (n = 0; n < NURBS; n++) {
ret = usb_submit_urb(gspca_dev->pktbuf[n].urb, ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL);
GFP_KERNEL);
if (ret < 0) { if (ret < 0) {
PDEBUG(D_ERR|D_STREAM, PDEBUG(D_ERR|D_STREAM,
"usb_submit_urb [%d] err %d", n, ret); "usb_submit_urb [%d] err %d", n, ret);
...@@ -732,15 +726,13 @@ static int vidioc_g_fmt_cap(struct file *file, void *priv, ...@@ -732,15 +726,13 @@ static int vidioc_g_fmt_cap(struct file *file, void *priv,
return 0; return 0;
} }
static int try_fmt_cap(struct file *file, static int try_fmt_cap(struct gspca_dev *gspca_dev,
void *priv,
struct v4l2_format *fmt) struct v4l2_format *fmt)
{ {
struct gspca_dev *gspca_dev = priv;
int w, h, mode, mode2, frsz; int w, h, mode, mode2, frsz;
w = (int) fmt->fmt.pix.width; w = fmt->fmt.pix.width;
h = (int) fmt->fmt.pix.height; h = fmt->fmt.pix.height;
#ifdef GSPCA_DEBUG #ifdef GSPCA_DEBUG
if (gspca_debug & D_CONF) if (gspca_debug & D_CONF)
PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h); PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h);
...@@ -786,9 +778,10 @@ static int vidioc_try_fmt_cap(struct file *file, ...@@ -786,9 +778,10 @@ static int vidioc_try_fmt_cap(struct file *file,
void *priv, void *priv,
struct v4l2_format *fmt) struct v4l2_format *fmt)
{ {
struct gspca_dev *gspca_dev = priv;
int ret; int ret;
ret = try_fmt_cap(file, priv, fmt); ret = try_fmt_cap(gspca_dev, fmt);
if (ret < 0) if (ret < 0)
return ret; return ret;
return 0; return 0;
...@@ -809,14 +802,19 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, ...@@ -809,14 +802,19 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
#endif #endif
if (mutex_lock_interruptible(&gspca_dev->queue_lock)) if (mutex_lock_interruptible(&gspca_dev->queue_lock))
return -ERESTARTSYS; return -ERESTARTSYS;
ret = try_fmt_cap(file, priv, fmt); ret = try_fmt_cap(gspca_dev, fmt);
if (ret < 0) if (ret < 0)
goto out; goto out;
if (ret == gspca_dev->curr_mode) if (ret == gspca_dev->curr_mode)
goto out; /* same mode */ goto out; /* same mode */
was_streaming = gspca_dev->streaming; was_streaming = gspca_dev->streaming;
if (was_streaming != 0) { if (was_streaming) {
if (gspca_dev->capt_file != 0
&& gspca_dev->capt_file != file) {
ret = -EBUSY;
goto out;
}
if (mutex_lock_interruptible(&gspca_dev->usb_lock)) { if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
ret = -ERESTARTSYS; ret = -ERESTARTSYS;
goto out; goto out;
...@@ -824,8 +822,8 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, ...@@ -824,8 +822,8 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
gspca_stream_off(gspca_dev); gspca_stream_off(gspca_dev);
mutex_unlock(&gspca_dev->usb_lock); mutex_unlock(&gspca_dev->usb_lock);
} }
gspca_dev->width = (int) fmt->fmt.pix.width; gspca_dev->width = fmt->fmt.pix.width;
gspca_dev->height = (int) fmt->fmt.pix.height; gspca_dev->height = fmt->fmt.pix.height;
gspca_dev->pixfmt = fmt->fmt.pix.pixelformat; gspca_dev->pixfmt = fmt->fmt.pix.pixelformat;
gspca_dev->curr_mode = ret; gspca_dev->curr_mode = ret;
if (was_streaming) if (was_streaming)
...@@ -891,17 +889,18 @@ static int dev_close(struct inode *inode, struct file *file) ...@@ -891,17 +889,18 @@ static int dev_close(struct inode *inode, struct file *file)
if (mutex_lock_interruptible(&gspca_dev->queue_lock)) if (mutex_lock_interruptible(&gspca_dev->queue_lock))
return -ERESTARTSYS; return -ERESTARTSYS;
gspca_dev->users--; gspca_dev->users--;
if (gspca_dev->users > 0) {
mutex_unlock(&gspca_dev->queue_lock);
return 0;
}
if (gspca_dev->streaming) /* if the file did capture, free the streaming resources */
gspca_stream_off(gspca_dev); if (gspca_dev->capt_file == file) {
gspca_dev->sd_desc->close(gspca_dev); mutex_lock(&gspca_dev->usb_lock);
if (gspca_dev->streaming)
frame_free(gspca_dev); gspca_stream_off(gspca_dev);
file->private_data = NULL; gspca_dev->sd_desc->close(gspca_dev);
mutex_unlock(&gspca_dev->usb_lock);
frame_free(gspca_dev);
file->private_data = NULL;
gspca_dev->capt_file = 0;
}
mutex_unlock(&gspca_dev->queue_lock); mutex_unlock(&gspca_dev->queue_lock);
PDEBUG(D_STREAM, "closed"); PDEBUG(D_STREAM, "closed");
return 0; return 0;
...@@ -1052,12 +1051,19 @@ static int vidioc_reqbufs(struct file *file, void *priv, ...@@ -1052,12 +1051,19 @@ static int vidioc_reqbufs(struct file *file, void *priv,
return frsz; return frsz;
if (mutex_lock_interruptible(&gspca_dev->queue_lock)) if (mutex_lock_interruptible(&gspca_dev->queue_lock))
return -ERESTARTSYS; return -ERESTARTSYS;
if (gspca_dev->capt_file != 0) { /* only one file may do capture */
ret = -EBUSY;
goto out;
}
ret = frame_alloc(gspca_dev, ret = frame_alloc(gspca_dev,
rb->count, rb->count,
(unsigned int) frsz, (unsigned int) frsz,
rb->memory); rb->memory);
if (ret == 0) if (ret == 0) {
rb->count = gspca_dev->nframes; rb->count = gspca_dev->nframes;
gspca_dev->capt_file = file;
}
out:
mutex_unlock(&gspca_dev->queue_lock); mutex_unlock(&gspca_dev->queue_lock);
PDEBUG(D_STREAM, "reqbufs st:%d c:%d", ret, rb->count); PDEBUG(D_STREAM, "reqbufs st:%d c:%d", ret, rb->count);
return ret; return ret;
...@@ -1099,6 +1105,10 @@ static int vidioc_streamon(struct file *file, void *priv, ...@@ -1099,6 +1105,10 @@ static int vidioc_streamon(struct file *file, void *priv,
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
if (gspca_dev->capt_file != file) {
ret = -EINVAL;
goto out;
}
if (!gspca_dev->streaming) { if (!gspca_dev->streaming) {
ret = gspca_init_transfer(gspca_dev); ret = gspca_init_transfer(gspca_dev);
if (ret < 0) if (ret < 0)
...@@ -1122,22 +1132,30 @@ static int vidioc_streamoff(struct file *file, void *priv, ...@@ -1122,22 +1132,30 @@ static int vidioc_streamoff(struct file *file, void *priv,
enum v4l2_buf_type buf_type) enum v4l2_buf_type buf_type)
{ {
struct gspca_dev *gspca_dev = priv; struct gspca_dev *gspca_dev = priv;
int ret;
PDEBUG(D_STREAM, "stream off"); PDEBUG(D_STREAM, "stream off");
if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL; return -EINVAL;
if (gspca_dev->streaming) { if (!gspca_dev->streaming)
if (mutex_lock_interruptible(&gspca_dev->queue_lock)) return 0;
return -ERESTARTSYS; if (mutex_lock_interruptible(&gspca_dev->queue_lock))
if (mutex_lock_interruptible(&gspca_dev->usb_lock)) { return -ERESTARTSYS;
mutex_unlock(&gspca_dev->queue_lock); if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
return -ERESTARTSYS; ret = -ERESTARTSYS;
} goto out;
gspca_stream_off(gspca_dev);
mutex_unlock(&gspca_dev->usb_lock);
mutex_unlock(&gspca_dev->queue_lock);
} }
return 0; if (gspca_dev->capt_file != file) {
ret = -EINVAL;
goto out2;
}
gspca_stream_off(gspca_dev);
ret = 0;
out2:
mutex_unlock(&gspca_dev->usb_lock);
out:
mutex_unlock(&gspca_dev->queue_lock);
return ret;
} }
static int vidioc_g_jpegcomp(struct file *file, void *priv, static int vidioc_g_jpegcomp(struct file *file, void *priv,
...@@ -1187,14 +1205,11 @@ static int vidioc_s_parm(struct file *filp, void *priv, ...@@ -1187,14 +1205,11 @@ static int vidioc_s_parm(struct file *filp, void *priv,
struct gspca_dev *gspca_dev = priv; struct gspca_dev *gspca_dev = priv;
int n; int n;
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;
n = parm->parm.capture.readbuffers; n = parm->parm.capture.readbuffers;
if (n == 0 || n > GSPCA_MAX_FRAMES) if (n == 0 || n > GSPCA_MAX_FRAMES)
parm->parm.capture.readbuffers = gspca_dev->nbufread; parm->parm.capture.readbuffers = gspca_dev->nbufread;
else else
gspca_dev->nbufread = n; gspca_dev->nbufread = n;
mutex_unlock(&gspca_dev->usb_lock);
return 0; return 0;
} }
...@@ -1245,7 +1260,11 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -1245,7 +1260,11 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma)
return -ERESTARTSYS; return -ERESTARTSYS;
if (!gspca_dev->present) { if (!gspca_dev->present) {
ret = -ENODEV; ret = -ENODEV;
goto done; goto out;
}
if (gspca_dev->capt_file != file) {
ret = -EINVAL;
goto out;
} }
for (i = 0; i < gspca_dev->nframes; ++i) { for (i = 0; i < gspca_dev->nframes; ++i) {
...@@ -1262,7 +1281,7 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -1262,7 +1281,7 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma)
if (frame == 0) { if (frame == 0) {
PDEBUG(D_STREAM, "mmap no frame buffer found"); PDEBUG(D_STREAM, "mmap no frame buffer found");
ret = -EINVAL; ret = -EINVAL;
goto done; goto out;
} }
#ifdef CONFIG_VIDEO_V4L1_COMPAT #ifdef CONFIG_VIDEO_V4L1_COMPAT
if (i == 0 && size == frame->v4l2_buf.length * gspca_dev->nframes) if (i == 0 && size == frame->v4l2_buf.length * gspca_dev->nframes)
...@@ -1272,7 +1291,7 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -1272,7 +1291,7 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma)
if (size != frame->v4l2_buf.length) { if (size != frame->v4l2_buf.length) {
PDEBUG(D_STREAM, "mmap bad size"); PDEBUG(D_STREAM, "mmap bad size");
ret = -EINVAL; ret = -EINVAL;
goto done; goto out;
} }
/* /*
...@@ -1286,7 +1305,7 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -1286,7 +1305,7 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma)
page = vmalloc_to_page((void *) addr); page = vmalloc_to_page((void *) addr);
ret = vm_insert_page(vma, start, page); ret = vm_insert_page(vma, start, page);
if (ret < 0) if (ret < 0)
goto done; goto out;
start += PAGE_SIZE; start += PAGE_SIZE;
addr += PAGE_SIZE; addr += PAGE_SIZE;
size -= PAGE_SIZE; size -= PAGE_SIZE;
...@@ -1304,7 +1323,7 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -1304,7 +1323,7 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma)
} }
#endif #endif
ret = 0; ret = 0;
done: out:
mutex_unlock(&gspca_dev->queue_lock); mutex_unlock(&gspca_dev->queue_lock);
return ret; return ret;
} }
...@@ -1356,10 +1375,14 @@ static int gspca_frame_wait(struct gspca_dev *gspca_dev, ...@@ -1356,10 +1375,14 @@ static int gspca_frame_wait(struct gspca_dev *gspca_dev,
/* wait till a frame is ready */ /* wait till a frame is ready */
for (;;) { for (;;) {
ret = wait_event_interruptible(gspca_dev->wq, ret = wait_event_interruptible_timeout(gspca_dev->wq,
atomic_read(&gspca_dev->nevent) > 0); atomic_read(&gspca_dev->nevent) > 0,
if (ret != 0) msecs_to_jiffies(3000));
return ret; if (ret <= 0) {
if (ret < 0)
return ret;
return -EIO;
}
if (!gspca_dev->streaming || !gspca_dev->present) if (!gspca_dev->streaming || !gspca_dev->present)
return -EIO; return -EIO;
i = gspca_dev->fr_o; i = gspca_dev->fr_o;
...@@ -1402,6 +1425,10 @@ static int vidioc_dqbuf(struct file *file, void *priv, ...@@ -1402,6 +1425,10 @@ static int vidioc_dqbuf(struct file *file, void *priv,
return -EINVAL; return -EINVAL;
if (!gspca_dev->streaming) if (!gspca_dev->streaming)
return -EINVAL; return -EINVAL;
if (gspca_dev->capt_file != file) {
ret = -EINVAL;
goto out;
}
/* only one read */ /* only one read */
if (mutex_lock_interruptible(&gspca_dev->read_lock)) if (mutex_lock_interruptible(&gspca_dev->read_lock))
...@@ -1409,14 +1436,14 @@ static int vidioc_dqbuf(struct file *file, void *priv, ...@@ -1409,14 +1436,14 @@ static int vidioc_dqbuf(struct file *file, void *priv,
ret = gspca_frame_wait(gspca_dev, file->f_flags & O_NONBLOCK); ret = gspca_frame_wait(gspca_dev, file->f_flags & O_NONBLOCK);
if (ret < 0) if (ret < 0)
goto done; goto out;
i = ret; /* frame index */ i = ret; /* frame index */
frame = &gspca_dev->frame[i]; frame = &gspca_dev->frame[i];
frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf); memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
PDEBUG(D_FRAM, "dqbuf %d", i); PDEBUG(D_FRAM, "dqbuf %d", i);
ret = 0; ret = 0;
done: out:
mutex_unlock(&gspca_dev->read_lock); mutex_unlock(&gspca_dev->read_lock);
return ret; return ret;
} }
...@@ -1450,6 +1477,8 @@ static int vidioc_qbuf(struct file *file, void *priv, ...@@ -1450,6 +1477,8 @@ static int vidioc_qbuf(struct file *file, void *priv,
PDEBUG(D_STREAM, "qbuf bad memory type"); PDEBUG(D_STREAM, "qbuf bad memory type");
return -EINVAL; return -EINVAL;
} }
if (gspca_dev->capt_file != file)
return -EINVAL;
if (mutex_lock_interruptible(&gspca_dev->queue_lock)) if (mutex_lock_interruptible(&gspca_dev->queue_lock))
return -ERESTARTSYS; return -ERESTARTSYS;
...@@ -1524,7 +1553,9 @@ static ssize_t dev_read(struct file *file, char __user *data, ...@@ -1524,7 +1553,9 @@ static ssize_t dev_read(struct file *file, char __user *data,
return ret; return ret;
} }
} }
} } else if (gspca_dev->capt_file != file)
return -EINVAL;
if (!gspca_dev->streaming) { if (!gspca_dev->streaming) {
ret = vidioc_streamon(file, gspca_dev, ret = vidioc_streamon(file, gspca_dev,
V4L2_BUF_TYPE_VIDEO_CAPTURE); V4L2_BUF_TYPE_VIDEO_CAPTURE);
...@@ -1719,7 +1750,7 @@ EXPORT_SYMBOL(gspca_dev_probe); ...@@ -1719,7 +1750,7 @@ EXPORT_SYMBOL(gspca_dev_probe);
*/ */
void gspca_disconnect(struct usb_interface *intf) void gspca_disconnect(struct usb_interface *intf)
{ {
struct gspca_dev *gspca_dev = usb_get_intfdata(intf); struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
if (!gspca_dev) if (!gspca_dev)
return; return;
......
...@@ -108,11 +108,6 @@ struct sd_desc { ...@@ -108,11 +108,6 @@ struct sd_desc {
cam_qmnu_op querymenu; cam_qmnu_op querymenu;
}; };
struct gspca_pktbuf {
char *data;
struct urb *urb;
};
/* packet types when moving from iso buf to frame buf */ /* packet types when moving from iso buf to frame buf */
#define DISCARD_PACKET 0 #define DISCARD_PACKET 0
#define FIRST_PACKET 1 #define FIRST_PACKET 1
...@@ -121,19 +116,20 @@ struct gspca_pktbuf { ...@@ -121,19 +116,20 @@ struct gspca_pktbuf {
struct gspca_frame { struct gspca_frame {
unsigned char *data; /* frame buffer */ unsigned char *data; /* frame buffer */
unsigned char *data_end; /* current end of frame while filling */ unsigned char *data_end; /* end of frame while filling */
int vma_use_count; int vma_use_count;
struct v4l2_buffer v4l2_buf; struct v4l2_buffer v4l2_buf;
}; };
struct gspca_dev { struct gspca_dev {
struct video_device vdev; /* !! must be the first item */ struct video_device vdev; /* !! must be the first item */
struct usb_device *dev; struct usb_device *dev;
struct file *capt_file; /* file doing video capture */
struct cam cam; /* device information */ struct cam cam; /* device information */
const struct sd_desc *sd_desc; /* subdriver description */ const struct sd_desc *sd_desc; /* subdriver description */
struct gspca_pktbuf pktbuf[NURBS]; struct urb *urb[NURBS];
__u8 *frbuf; /* buffer for nframes */ __u8 *frbuf; /* buffer for nframes */
struct gspca_frame frame[GSPCA_MAX_FRAMES]; struct gspca_frame frame[GSPCA_MAX_FRAMES];
...@@ -147,7 +143,7 @@ struct gspca_dev { ...@@ -147,7 +143,7 @@ struct gspca_dev {
__u8 iface; /* USB interface number */ __u8 iface; /* USB interface number */
__u8 alt; /* USB alternate setting */ __u8 alt; /* USB alternate setting */
char curr_mode; /* current camera mode */ unsigned char curr_mode; /* current camera mode */
__u32 pixfmt; /* current mode parameters */ __u32 pixfmt; /* current mode parameters */
short width; short width;
short height; short height;
...@@ -158,7 +154,7 @@ struct gspca_dev { ...@@ -158,7 +154,7 @@ struct gspca_dev {
struct mutex read_lock; /* read protection */ struct mutex read_lock; /* read protection */
struct mutex queue_lock; /* ISOC queue protection */ struct mutex queue_lock; /* ISOC queue protection */
__u32 sequence; /* frame sequence number */ __u32 sequence; /* frame sequence number */
signed char streaming; char streaming;
char users; /* # open */ char users; /* # open */
char present; /* device connected */ char present; /* device connected */
char nbufread; /* number of buffers for read() */ char nbufread; /* number of buffers for read() */
......
...@@ -27,8 +27,8 @@ ...@@ -27,8 +27,8 @@
#include "gspca.h" #include "gspca.h"
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 0, 30) #define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 1, 1)
static const char version[] = "0.0.30"; static const char version[] = "0.1.1";
MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>"); MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
MODULE_DESCRIPTION("Pixart PAC207"); MODULE_DESCRIPTION("Pixart PAC207");
...@@ -251,6 +251,7 @@ int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index) ...@@ -251,6 +251,7 @@ int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
static int sd_config(struct gspca_dev *gspca_dev, static int sd_config(struct gspca_dev *gspca_dev,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct sd *sd = (struct sd *) gspca_dev;
struct cam *cam; struct cam *cam;
u8 idreg[2]; u8 idreg[2];
...@@ -282,6 +283,9 @@ static int sd_config(struct gspca_dev *gspca_dev, ...@@ -282,6 +283,9 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam->epaddr = 0x05; cam->epaddr = 0x05;
cam->cam_mode = sif_mode; cam->cam_mode = sif_mode;
cam->nmodes = ARRAY_SIZE(sif_mode); cam->nmodes = ARRAY_SIZE(sif_mode);
sd->brightness = PAC207_BRIGHTNESS_DEFAULT;
sd->exposure = PAC207_EXPOSURE_DEFAULT;
sd->gain = PAC207_GAIN_DEFAULT;
return 0; return 0;
} }
...@@ -291,9 +295,6 @@ static int sd_open(struct gspca_dev *gspca_dev) ...@@ -291,9 +295,6 @@ static int sd_open(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
sd->brightness = PAC207_BRIGHTNESS_DEFAULT;
sd->exposure = PAC207_EXPOSURE_DEFAULT;
sd->gain = PAC207_GAIN_DEFAULT;
sd->autogain = 1; sd->autogain = 1;
return 0; return 0;
......
...@@ -24,8 +24,8 @@ ...@@ -24,8 +24,8 @@
#include "gspca.h" #include "gspca.h"
#include "jpeg.h" #include "jpeg.h"
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 0, 22) #define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 1, 0)
static const char version[] = "0.0.22"; static const char version[] = "0.1.0";
MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver"); MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver");
...@@ -390,6 +390,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, ...@@ -390,6 +390,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
int len) /* iso packet length */ int len) /* iso packet length */
{ {
int l; int l;
static unsigned char ffd9[] = {0xff, 0xd9};
/* a frame starts with: /* a frame starts with:
* - 0xff 0xfe * - 0xff 0xfe
...@@ -445,7 +446,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, ...@@ -445,7 +446,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
if (len > frame->v4l2_buf.bytesused - 2 - l) if (len > frame->v4l2_buf.bytesused - 2 - l)
len = frame->v4l2_buf.bytesused - 2 - l; len = frame->v4l2_buf.bytesused - 2 - l;
gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
gspca_frame_add(gspca_dev, LAST_PACKET, frame, "\xff\xd9", 2); gspca_frame_add(gspca_dev, LAST_PACKET, frame, ffd9, 2);
} }
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment