I've replaced simple_select in v4l1-compat.c: the current implementation is just way to ugly to remain in the kernel. Unfortunately I don't have a test setup. Could someone test that the patch doesn't break the compatibility layer? The patch is against 2.5.58. Thanks, -- Manfred
--- 2.5/drivers/media/video/v4l1-compat.c 2003-01-15 20:30:20.000000000 +0100 +++ build-2.5/drivers/media/video/v4l1-compat.c 2003-01-16 23:50:26.000000000 +0100 @@ -199,66 +199,33 @@ return palette; } -/* Do an 'in' (wait for input) select on a single file descriptor */ -/* This stuff plaigarized from linux/fs/select.c */ -#define __FD_IN(fds, n) (fds->in + n) -#define BIT(i) (1UL << ((i)&(__NFDBITS-1))) -#define SET(i,m) (*(m) |= (i)) -extern int do_select(int n, fd_set_bits *fds, long *timeout); - - static int simple_select(struct file *file) { - fd_set_bits fds; - char *bits; - long timeout; - int i, fd, n, ret, size; - - for (i = 0; i < current->files->max_fds; ++i) - if (file == current->files->fd[i]) - break; - if (i == current->files->max_fds) - return -EINVAL; - fd = i; - n = fd + 1; - - timeout = MAX_SCHEDULE_TIMEOUT; - /* - * We need 6 bitmaps (in/out/ex for both incoming and outgoing), - * since we used fdset we need to allocate memory in units of - * long-words. - */ - ret = -ENOMEM; - size = FDS_BYTES(n); - bits = kmalloc(6 * size, GFP_KERNEL); - if (!bits) - goto out_nofds; - fds.in = (unsigned long *) bits; - fds.out = (unsigned long *) (bits + size); - fds.ex = (unsigned long *) (bits + 2*size); - fds.res_in = (unsigned long *) (bits + 3*size); - fds.res_out = (unsigned long *) (bits + 4*size); - fds.res_ex = (unsigned long *) (bits + 5*size); - - /* All zero except our one file descriptor bit, for input */ - memset(bits, 0, 6 * size); - SET(BIT(fd), __FD_IN((&fds), fd / __NFDBITS)); - - ret = do_select(n, &fds, &timeout); - - if (ret < 0) - goto out; - if (!ret) { - ret = -ERESTARTNOHAND; - if (signal_pending(current)) - goto out; - ret = 0; - } -out: - kfree(bits); -out_nofds: - return ret; + int retval = 1; + struct poll_wqueues wait_table; + poll_table *table; + + poll_initwait(&wait_table); + table = &wait_table.pt; + for (;;) { + int mask; + set_current_state(TASK_INTERRUPTIBLE); + mask = POLLIN; + if (file->f_op && file->f_op->poll) + mask = file->f_op->poll(file, table); + if (mask & POLLIN) + break; + table = NULL; + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + schedule(); + } + current->state = TASK_RUNNING; + poll_freewait(&wait_table); + return retval; } static int count_inputs(struct inode *inode,