diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-07-12 01:43:08 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-07-12 01:43:08 +0000 |
commit | f4ae78d536e6dfaeb24c01b331fc38d950ed062b (patch) | |
tree | 6930a78aa7cc4ee1829d50d3bcbaf0dbe9e2e905 /drivers/usb | |
parent | 66f20d0f9bd86dc11f3869d78f3c5749789323ee (diff) |
Merge with 2.4.0-test4-pre2.
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/bluetooth.c | 1 | ||||
-rw-r--r-- | drivers/usb/hub.c | 2 | ||||
-rw-r--r-- | drivers/usb/ov511.c | 336 | ||||
-rw-r--r-- | drivers/usb/ov511.h | 16 |
4 files changed, 231 insertions, 124 deletions
diff --git a/drivers/usb/bluetooth.c b/drivers/usb/bluetooth.c index dc3b54ed1..aaea67a4c 100644 --- a/drivers/usb/bluetooth.c +++ b/drivers/usb/bluetooth.c @@ -33,7 +33,6 @@ */ -#include <linux/config.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/signal.h> diff --git a/drivers/usb/hub.c b/drivers/usb/hub.c index 75794f3ca..71d6aabb9 100644 --- a/drivers/usb/hub.c +++ b/drivers/usb/hub.c @@ -588,6 +588,8 @@ static int usb_hub_thread(void *__hub) * so get rid of all our resources */ exit_files(current); /* daemonize doesn't do exit_files */ + current->files = init_task.files; + atomic_inc(¤t->files->count); daemonize(); /* Setup a nice name */ diff --git a/drivers/usb/ov511.c b/drivers/usb/ov511.c index 66f73d3c1..1862415fa 100644 --- a/drivers/usb/ov511.c +++ b/drivers/usb/ov511.c @@ -30,7 +30,7 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static const char version[] = "1.18"; +static const char version[] = "1.19"; #define __NO_VERSION__ @@ -98,6 +98,9 @@ static int aperture = -1; * programs that expect RGB data (e.g. gqcam) to work with this driver. */ static int force_rgb = 0; +/* Number of seconds before inactive buffers are deallocated */ +static int buf_timeout = 5; + MODULE_PARM(autoadjust, "i"); MODULE_PARM(debug, "i"); MODULE_PARM(fix_rgb_offset, "i"); @@ -106,6 +109,7 @@ MODULE_PARM(sensor, "i"); MODULE_PARM(i2c_detect_tries, "i"); MODULE_PARM(aperture, "i"); MODULE_PARM(force_rgb, "i"); +MODULE_PARM(buf_timeout, "i"); MODULE_AUTHOR("Mark McClelland <mmcclelland@delphi.com> & Bret Wallach & Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha <cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>"); MODULE_DESCRIPTION("OV511 USB Camera Driver"); @@ -132,6 +136,7 @@ static struct cam_list clist[] = { { -1, NULL } }; +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) static struct palette_list plist[] = { { VIDEO_PALETTE_GREY, "GREY" }, { VIDEO_PALETTE_HI240, "HI240" }, @@ -151,6 +156,7 @@ static struct palette_list plist[] = { { VIDEO_PALETTE_YUV410P,"YUV410P" }, { -1, NULL } }; +#endif /********************************************************************** * @@ -432,7 +438,7 @@ static int ov511_reg_write(struct usb_device *dev, PDEBUG(5, "reg write: 0x%02X:0x%02X, 0x%x", reg, value, rc); if (rc < 0) - err("ov511_reg_write: error %d", rc); + err("reg write: error %d", rc); return rc; } @@ -452,7 +458,7 @@ static int ov511_reg_read(struct usb_device *dev, unsigned char reg) PDEBUG(5, "reg read: 0x%02X:0x%02X", reg, buffer[0]); if (rc < 0) { - err("ov511_reg_read: error %d", rc); + err("reg read: error %d", rc); return rc; } else { return buffer[0]; @@ -501,7 +507,7 @@ static int ov511_i2c_write(struct usb_device *dev, return 0; error: - err("ov511_i2c_write: error %d", rc); + err("i2c write: error %d", rc); return rc; } @@ -573,7 +579,7 @@ static int ov511_i2c_read(struct usb_device *dev, unsigned char reg) return value; error: - err("ov511_i2c_read: error %d", rc); + err("i2c read: error %d", rc); return rc; } @@ -601,7 +607,7 @@ static int ov511_write_regvals(struct usb_device *dev, return 0; error: - err("ov511_write_regvals: error %d", rc); + err("write regvals: error %d", rc); return rc; } @@ -699,11 +705,8 @@ static int ov511_set_packet_size(struct usb_ov511 *ov511, int size) if (ov511->bridge == BRG_OV511) { if (size == 0) alt = OV511_ALT_SIZE_0; else if (size == 257) alt = OV511_ALT_SIZE_257; -// else if (size == 512) alt = OV511_ALT_SIZE_512; else if (size == 513) alt = OV511_ALT_SIZE_513; -// else if (size == 768) alt = OV511_ALT_SIZE_768; else if (size == 769) alt = OV511_ALT_SIZE_769; -// else if (size == 992) alt = OV511_ALT_SIZE_992; else if (size == 993) alt = OV511_ALT_SIZE_993; else { err("Set packet size: invalid size (%d)", size); @@ -1673,7 +1676,7 @@ static void ov511_isoc_irq(struct urb *urb) static int ov511_init_isoc(struct usb_ov511 *ov511) { urb_t *urb; - int fx, err; + int fx, err, n; PDEBUG(3, "*** Initializing capture ***"); @@ -1689,55 +1692,37 @@ static int ov511_init_isoc(struct usb_ov511 *ov511) else err("invalid bridge type"); - /* We double buffer the Iso lists */ - urb = usb_alloc_urb(FRAMES_PER_DESC); + for (n = 0; n < OV511_NUMSBUF; n++) { + urb = usb_alloc_urb(FRAMES_PER_DESC); - if (!urb) { - err("ov511_init_isoc: usb_alloc_urb ret. NULL"); - return -ENOMEM; - } - ov511->sbuf[0].urb = urb; - urb->dev = ov511->dev; - urb->context = ov511; - urb->pipe = usb_rcvisocpipe(ov511->dev, OV511_ENDPOINT_ADDRESS); - urb->transfer_flags = USB_ISO_ASAP; - urb->transfer_buffer = ov511->sbuf[0].data; - urb->complete = ov511_isoc_irq; - urb->number_of_packets = FRAMES_PER_DESC; - urb->transfer_buffer_length = ov511->packet_size * FRAMES_PER_DESC; - for (fx = 0; fx < FRAMES_PER_DESC; fx++) { - urb->iso_frame_desc[fx].offset = ov511->packet_size * fx; - urb->iso_frame_desc[fx].length = ov511->packet_size; - } - - urb = usb_alloc_urb(FRAMES_PER_DESC); - if (!urb) { - err("ov511_init_isoc: usb_alloc_urb ret. NULL"); - return -ENOMEM; - } - ov511->sbuf[1].urb = urb; - urb->dev = ov511->dev; - urb->context = ov511; - urb->pipe = usb_rcvisocpipe(ov511->dev, OV511_ENDPOINT_ADDRESS); - urb->transfer_flags = USB_ISO_ASAP; - urb->transfer_buffer = ov511->sbuf[1].data; - urb->complete = ov511_isoc_irq; - urb->number_of_packets = FRAMES_PER_DESC; - urb->transfer_buffer_length = ov511->packet_size * FRAMES_PER_DESC; - for (fx = 0; fx < FRAMES_PER_DESC; fx++) { - urb->iso_frame_desc[fx].offset = ov511->packet_size * fx; - urb->iso_frame_desc[fx].length = ov511->packet_size; + if (!urb) { + err("init isoc: usb_alloc_urb ret. NULL"); + return -ENOMEM; + } + ov511->sbuf[n].urb = urb; + urb->dev = ov511->dev; + urb->context = ov511; + urb->pipe = usb_rcvisocpipe(ov511->dev, OV511_ENDPOINT_ADDRESS); + urb->transfer_flags = USB_ISO_ASAP; + urb->transfer_buffer = ov511->sbuf[n].data; + urb->complete = ov511_isoc_irq; + urb->number_of_packets = FRAMES_PER_DESC; + urb->transfer_buffer_length = ov511->packet_size * FRAMES_PER_DESC; + for (fx = 0; fx < FRAMES_PER_DESC; fx++) { + urb->iso_frame_desc[fx].offset = ov511->packet_size * fx; + urb->iso_frame_desc[fx].length = ov511->packet_size; + } } - ov511->sbuf[1].urb->next = ov511->sbuf[0].urb; - ov511->sbuf[0].urb->next = ov511->sbuf[1].urb; + ov511->sbuf[OV511_NUMSBUF - 1].urb->next = ov511->sbuf[0].urb; + for (n = 0; n < OV511_NUMSBUF - 1; n++) + ov511->sbuf[n].urb->next = ov511->sbuf[n+1].urb; - err = usb_submit_urb(ov511->sbuf[0].urb); - if (err) - err("ov511_init_isoc: usb_submit_urb(0) ret %d", err); - err = usb_submit_urb(ov511->sbuf[1].urb); - if (err) - err("ov511_init_isoc: usb_submit_urb(1) ret %d", err); + for (n = 0; n < OV511_NUMSBUF; n++) { + err = usb_submit_urb(ov511->sbuf[n].urb); + if (err) + err("init isoc: usb_submit_urb(%d) ret %d", n, err); + } ov511->streaming = 1; @@ -1746,6 +1731,8 @@ static int ov511_init_isoc(struct usb_ov511 *ov511) static void ov511_stop_isoc(struct usb_ov511 *ov511) { + int n; + if (!ov511->streaming || !ov511->dev) return; @@ -1756,17 +1743,13 @@ static void ov511_stop_isoc(struct usb_ov511 *ov511) ov511->streaming = 0; /* Unschedule all of the iso td's */ - if (ov511->sbuf[1].urb) { - ov511->sbuf[1].urb->next = NULL; - usb_unlink_urb(ov511->sbuf[1].urb); - usb_free_urb(ov511->sbuf[1].urb); - ov511->sbuf[1].urb = NULL; - } - if (ov511->sbuf[0].urb) { - ov511->sbuf[0].urb->next = NULL; - usb_unlink_urb(ov511->sbuf[0].urb); - usb_free_urb(ov511->sbuf[0].urb); - ov511->sbuf[0].urb = NULL; + for (n = OV511_NUMSBUF - 1; n >= 0; n--) { + if (ov511->sbuf[n].urb) { + ov511->sbuf[n].urb->next = NULL; + usb_unlink_urb(ov511->sbuf[n].urb); + usb_free_urb(ov511->sbuf[n].urb); + ov511->sbuf[n].urb = NULL; + } } } @@ -1818,6 +1801,127 @@ static int ov511_new_frame(struct usb_ov511 *ov511, int framenum) /**************************************************************************** * + * Buffer management + * + ***************************************************************************/ +static int ov511_alloc(struct usb_ov511 *ov511) +{ + int i; + + PDEBUG(4, "entered"); + down(&ov511->buf_lock); + + if (ov511->buf_state == BUF_PEND_DEALLOC) { + ov511->buf_state = BUF_ALLOCATED; + del_timer(&ov511->buf_timer); + } + + if (ov511->buf_state == BUF_ALLOCATED) + goto out; + + ov511->fbuf = rvmalloc(OV511_NUMFRAMES * MAX_DATA_SIZE); + if (!ov511->fbuf) + goto error; + + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov511->frame[i].grabstate = FRAME_UNUSED; + ov511->frame[i].data = ov511->fbuf + i * MAX_DATA_SIZE; + PDEBUG(4, "frame[%d] @ %p", i, ov511->frame[i].data); + + ov511->sbuf[i].data = kmalloc(FRAMES_PER_DESC * + MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL); + if (!ov511->sbuf[i].data) { + while (--i) { + kfree(ov511->sbuf[i].data); + ov511->sbuf[i].data = NULL; + } + rvfree(ov511->fbuf, OV511_NUMFRAMES * MAX_DATA_SIZE); + ov511->fbuf = NULL; + goto error; + } + PDEBUG(4, "sbuf[%d] @ %p", i, ov511->sbuf[i].data); + } + ov511->buf_state = BUF_ALLOCATED; +out: + up(&ov511->buf_lock); + PDEBUG(4, "leaving"); + return 0; +error: + ov511->buf_state = BUF_NOT_ALLOCATED; + up(&ov511->buf_lock); + PDEBUG(4, "errored"); + return -ENOMEM; +} + +/* + * - You must acquire buf_lock before entering this function. + * - Because this code will free any non-null pointer, you must be sure to null + * them if you explicitly free them somewhere else! + */ +static void ov511_do_dealloc(struct usb_ov511 *ov511) +{ + int i; + PDEBUG(4, "entered"); + + if (ov511->fbuf) { + rvfree(ov511->fbuf, OV511_NUMFRAMES * MAX_DATA_SIZE); + ov511->fbuf = NULL; + } + + for (i = 0; i < OV511_NUMFRAMES; i++) { + if (ov511->sbuf[i].data) { + kfree(ov511->sbuf[i].data); + ov511->sbuf[i].data = NULL; + } + } + + PDEBUG(4, "buffer memory deallocated"); + ov511->buf_state = BUF_NOT_ALLOCATED; + PDEBUG(4, "leaving"); +} + +static void ov511_buf_callback(unsigned long data) +{ + struct usb_ov511 *ov511 = (struct usb_ov511 *)data; + PDEBUG(4, "entered"); + down(&ov511->buf_lock); + + if (ov511->buf_state == BUF_PEND_DEALLOC) + ov511_do_dealloc(ov511); + + up(&ov511->buf_lock); + PDEBUG(4, "leaving"); +} + +static void ov511_dealloc(struct usb_ov511 *ov511, int now) +{ + struct timer_list *bt = &(ov511->buf_timer); + PDEBUG(4, "entered"); + down(&ov511->buf_lock); + + PDEBUG(4, "deallocating buffer memory %s", now ? "now" : "later"); + + if (ov511->buf_state == BUF_PEND_DEALLOC) { + ov511->buf_state = BUF_ALLOCATED; + del_timer(bt); + } + + if (now) + ov511_do_dealloc(ov511); + else { + ov511->buf_state = BUF_PEND_DEALLOC; + init_timer(bt); + bt->function = ov511_buf_callback; + bt->data = (unsigned long)ov511; + bt->expires = jiffies + buf_timeout * HZ; + add_timer(bt); + } + up(&ov511->buf_lock); + PDEBUG(4, "leaving"); +} + +/**************************************************************************** + * * V4L API * ***************************************************************************/ @@ -1825,7 +1929,7 @@ static int ov511_new_frame(struct usb_ov511 *ov511, int framenum) static int ov511_open(struct video_device *dev, int flags) { struct usb_ov511 *ov511 = (struct usb_ov511 *)dev; - int i, err = 0; + int err = 0; MOD_INC_USE_COUNT; PDEBUG(4, "opening"); @@ -1836,33 +1940,16 @@ static int ov511_open(struct video_device *dev, int flags) goto out; err = -ENOMEM; - - /* Allocate memory for the frame buffers */ - ov511->fbuf = rvmalloc(OV511_NUMFRAMES * MAX_DATA_SIZE); - if (!ov511->fbuf) + if (ov511_alloc(ov511)) goto out; ov511->sub_flag = 0; - for (i = 0; i < OV511_NUMFRAMES; i++) { - ov511->frame[i].grabstate = FRAME_UNUSED; - ov511->frame[i].data = ov511->fbuf + i * MAX_DATA_SIZE; - PDEBUG(4, "frame [%d] @ %p", i, ov511->frame[0].data); - - ov511->sbuf[i].data = kmalloc(FRAMES_PER_DESC * - MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL); - if (!ov511->sbuf[i].data) { -open_free_ret: - while (--i) kfree(ov511->sbuf[i].data); - rvfree(ov511->fbuf, 2 * MAX_DATA_SIZE); - goto out; - } - PDEBUG(4, "sbuf[%d] @ %p", i, ov511->sbuf[i].data); - } - err = ov511_init_isoc(ov511); - if (err) - goto open_free_ret; + if (err) { + ov511_dealloc(ov511, 0); + goto out; + } ov511->user++; @@ -1878,7 +1965,6 @@ out: static void ov511_close(struct video_device *dev) { struct usb_ov511 *ov511 = (struct usb_ov511 *)dev; - int i; PDEBUG(4, "ov511_close"); @@ -1887,15 +1973,13 @@ static void ov511_close(struct video_device *dev) ov511_stop_isoc(ov511); - rvfree(ov511->fbuf, OV511_NUMFRAMES * MAX_DATA_SIZE); - for (i = 0; i < OV511_NUMFRAMES; i++) - kfree(ov511->sbuf[i].data); - + ov511_dealloc(ov511, 0); up(&ov511->lock); if (!ov511->dev) { video_unregister_device(&ov511->vdev); kfree(ov511); + ov511 = NULL; } MOD_DEC_USE_COUNT; @@ -2118,8 +2202,8 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) struct video_mbuf vm; memset(&vm, 0, sizeof(vm)); - vm.size = 2 * MAX_DATA_SIZE; - vm.frames = 2; + vm.size = OV511_NUMFRAMES * MAX_DATA_SIZE; + vm.frames = OV511_NUMFRAMES; vm.offsets[0] = 0; vm.offsets[1] = MAX_FRAME_SIZE + sizeof (struct timeval); @@ -2329,7 +2413,7 @@ restart: frame->bytes_read = 0; err("** ick! ** Errored frame %d", ov511->curframe); if (ov511_new_frame(ov511, frmx)) - err("ov511_read: ov511_new_frame error"); + err("read: ov511_new_frame error"); goto restart; } @@ -2531,15 +2615,24 @@ static int ov76xx_configure(struct usb_ov511 *ov511) /* Reset the 76xx */ if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1; +#if 1 /* Maybe this will fix detection problems? MM */ + /* Wait for it to initialize */ + schedule_timeout (1 + 150 * HZ / 1000); +#endif + for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) { if ((ov511_i2c_read(dev, OV7610_REG_ID_HIGH) == 0x7F) && - (ov511_i2c_read(dev, OV7610_REG_ID_LOW) == 0xA2)) + (ov511_i2c_read(dev, OV7610_REG_ID_LOW) == 0xA2)) { success = 1; + continue; + } - /* Dummy read to sync I2C */ - if (ov511_i2c_read(dev, 0x00) < 0) return -1; + /* Reset the 76xx */ + if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1; /* Wait for it to initialize */ schedule_timeout (1 + 150 * HZ / 1000); + /* Dummy read to sync I2C */ + if (ov511_i2c_read(dev, 0x00) < 0) return -1; } if (success) { @@ -2647,8 +2740,9 @@ static int ov511_configure(struct usb_ov511 *ov511) memcpy(&ov511->vdev, &ov511_template, sizeof(ov511_template)); - init_waitqueue_head(&ov511->frame[0].wq); - init_waitqueue_head(&ov511->frame[1].wq); + for (i = 0; i < OV511_NUMFRAMES; i++) + init_waitqueue_head(&ov511->frame[i].wq); + init_waitqueue_head(&ov511->wq); if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER) == -1) { @@ -2790,6 +2884,8 @@ static void* ov511_probe(struct usb_device *dev, unsigned int ifnum) if (!ov511_configure(ov511)) { ov511->user = 0; init_MUTEX(&ov511->lock); /* to 1 == available */ + init_MUTEX(&ov511->buf_lock); + ov511->buf_state = BUF_NOT_ALLOCATED; } else { err("Failed to configure camera"); goto error; @@ -2812,6 +2908,7 @@ error: static void ov511_disconnect(struct usb_device *dev, void *ptr) { struct usb_ov511 *ov511 = (struct usb_ov511 *) ptr; + int n; MOD_INC_USE_COUNT; @@ -2823,38 +2920,37 @@ static void ov511_disconnect(struct usb_device *dev, void *ptr) &ov511->dev->actconfig->interface[ov511->iface]); ov511->dev = NULL; - ov511->frame[0].grabstate = FRAME_ERROR; - ov511->frame[1].grabstate = FRAME_ERROR; + for (n = 0; n < OV511_NUMFRAMES; n++) + ov511->frame[n].grabstate = FRAME_ERROR; + ov511->curframe = -1; /* This will cause the process to request another frame */ - if (waitqueue_active(&ov511->frame[0].wq)) - wake_up_interruptible(&ov511->frame[0].wq); - if (waitqueue_active(&ov511->frame[1].wq)) - wake_up_interruptible(&ov511->frame[1].wq); + for (n = 0; n < OV511_NUMFRAMES; n++) + if (waitqueue_active(&ov511->frame[n].wq)) + wake_up_interruptible(&ov511->frame[n].wq); if (waitqueue_active(&ov511->wq)) wake_up_interruptible(&ov511->wq); ov511->streaming = 0; /* Unschedule all of the iso td's */ - if (ov511->sbuf[1].urb) { - ov511->sbuf[1].urb->next = NULL; - usb_unlink_urb(ov511->sbuf[1].urb); - usb_free_urb(ov511->sbuf[1].urb); - ov511->sbuf[1].urb = NULL; - } - if (ov511->sbuf[0].urb) { - ov511->sbuf[0].urb->next = NULL; - usb_unlink_urb(ov511->sbuf[0].urb); - usb_free_urb(ov511->sbuf[0].urb); - ov511->sbuf[0].urb = NULL; + for (n = OV511_NUMSBUF - 1; n >= 0; n--) { + if (ov511->sbuf[n].urb) { + ov511->sbuf[n].urb->next = NULL; + usb_unlink_urb(ov511->sbuf[n].urb); + usb_free_urb(ov511->sbuf[n].urb); + ov511->sbuf[n].urb = NULL; + } } #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) destroy_proc_ov511_cam(ov511); #endif + /* FIXME - is this correct/safe? Should we acquire ov511->lock? */ + ov511_dealloc(ov511, 1); + /* Free the memory */ if (ov511 && !ov511->user) { kfree(ov511); @@ -2895,7 +2991,7 @@ static int __init usb_ov511_init(void) static void __exit usb_ov511_exit(void) { usb_deregister(&ov511_driver); - info("ov511 driver deregistered"); + info("driver deregistered"); #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) proc_ov511_destroy(); diff --git a/drivers/usb/ov511.h b/drivers/usb/ov511.h index 92827afb3..f4499b2be 100644 --- a/drivers/usb/ov511.h +++ b/drivers/usb/ov511.h @@ -171,9 +171,7 @@ if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args #define OV7610_REG_COM_K 0x38 /* misc registers */ -#define STREAM_BUF_SIZE (PAGE_SIZE * 4) - -#define SCRATCH_BUF_SIZE 384 +#define SCRATCH_BUF_SIZE 512 #define FRAMES_PER_DESC 10 /* FIXME - What should this be? */ #define FRAME_SIZE_PER_DESC 993 /* FIXME - Deprecated */ @@ -213,6 +211,13 @@ enum { STATE_LINES, /* Parsing lines */ }; +/* Buffer states */ +enum { + BUF_NOT_ALLOCATED, + BUF_ALLOCATED, + BUF_PEND_DEALLOC, /* ov511->buf_timer is set */ +}; + struct usb_device; struct ov511_sbuf { @@ -324,6 +329,11 @@ struct usb_ov511 { /* proc interface */ struct semaphore param_lock; /* params lock for this camera */ struct proc_dir_entry *proc_entry; /* /proc/ov511/videoX */ + + /* Framebuffer/sbuf management */ + int buf_state; + struct semaphore buf_lock; + struct timer_list buf_timer; }; struct cam_list { |