Gern, Rolf: Okay, we need to come to some to decision as to what the ioctl's do. If the answer is that VIDIOCMCAPTURE does *NOT* capture, then we have a new problem because the API doc specifically states to start streaming data after a call to VIDIOCMCAPTURE. In fact if I read usbvideo.c right, any mini driver based on it will start streaming after a call to VIDIOCMCAPTURE. If you start streaming after a VIDIOCMCAPTURE ioctl, and block on VIDIOCSYNC we have a problem. That would mean either a) The API doc is 100% WRONG and VIDIOCSYNC does NOT indicate that a frame is free - in which case several drivers and at least one well regarded application mis-use v4l - *or* VIDIOCSYNC does free the frame for reuse in which case there is a chance that the driver could be writing to the buffer while the application is trying to read from it. Now as far bttv, this is what I'm seeing in bttv-driver.c (this is in 2.4.17 with no patches applied): case VIDIOCMCAPTURE: { struct video_mmap vm; int ret; if(copy_from_user((void *) &vm, (void *) arg, sizeof(vm))) return -EFAULT; down(&btv->lock); ret = vgrab(btv, &vm); up(&btv->lock); return ret; } If I read that correctly, it looks like its MCAPTURE ioctl locks the device, grabs a frame, then unlocks the device. I'm not 100% sure as vgrab was a little confusing as to what it does. For bttv's VIDIOCSYNC: case VIDIOCSYNC: { DECLARE_WAITQUEUE(wait, current); if(copy_from_user((void *)&i,arg,sizeof(int))) return -EFAULT; if (i < 0 || i >= gbuffers) return -EINVAL; switch (btv->gbuf[i].stat) { case GBUFFER_UNUSED: ret = -EINVAL; break; case GBUFFER_GRABBING: add_wait_queue(&btv->capq, &wait); current->state = TASK_INTERRUPTIBLE; while(btv->gbuf[i].stat==GBUFFER_GRABBING) { if (bttv_debug) printk("bttv%d: cap sync: sleep on %d\n",btv->nr,i); schedule(); if(signal_pending(current)) { remove_wait_queue(&btv->capq, &wait); current->state = TASK_RUNNING; return -EINTR; } } remove_wait_queue(&btv->capq, &wait); current->state = TASK_RUNNING; /* fall throuth */ case GBUFFER_DONE: case GBUFFER_ERROR: ret = (btv->gbuf[i].stat == GBUFFER_ERROR) ? -EIO : 0; if (bttv_debug) printk("bttv%d: cap sync: buffer %d, retval %d\n",btv->nr,i,ret); btv->gbuf[i].stat = GBUFFER_UNUSED; } if (btv->needs_restart) { down(&btv->lock); bt848_restart(btv); up(&btv->lock); } return ret; } Looks to me like the only time the VIDIOCSYNC ioctl will wait is if you are trying to free the frame that is currently grabbing. If the frame has already been grabbed (GBUFFER_DONE), the buffer is immediately marked as unused and the function promptly returns. If the frame *was* grabbing, it waits for the frame to be *done* grabbing then falls through at marks the buffer unused. So, if the answer is you call VIDIOCMCAPTURE to queue a frame to be read, and you call VIDIOCSYNC to wait for the frame to come in... Then the API doc is not just unclear but arguably completely incorrect, the bttv driver looks like it is broken, and the zapping application looks like it is broken too.