Created attachment 181752 [details] patch to change type of EVIOCGRAB and EVIOCREVOKE ioctls to _IO EVIOCGRAB and EVIOCREVOKE from dev/evdev/input.h are defined as _IOWINT. Those ioctls don't actually write an integer, though. What matters is the value of the data pointer. Cuse, however, only passes along the value of the data pointer when the length of the ioctl is 0 (see https://github.com/freebsd/freebsd/blob/master/sys/fs/cuse/cuse.c#L1669). One solution would be to define those two ioctls as _IO (see attached patch). I've tested this with my cuse-based evdev implementation (https://github.com/jiixyj/evdevfbsd).
Notify committer of original file.
(In reply to Jan Kokemüller from comment #0) > Cuse, however, only passes along the value of the data > pointer when the length of the ioctl is 0 Hopefully, this have been fixed with r302381 https://svnweb.freebsd.org/base?view=revision&revision=302381
(In reply to Vladimir Kondratyev from comment #2) This doesn't fix the issue, sadly. With the current definition of EVIOCGRAB, when you do something like this on a cuse-based Evdev device: ioctl(dev->fd, EVIOCGRAB, (void *)1); /* grab device */ ioctl(dev->fd, EVIOCGRAB, (void *)0); /* ungrab device */ ...both times you get 10000 (CUSE_BUF_MIN_PTR) inside the ioctl handler. So you cannot ungrab a device again. The value 10000 comes from here: https://github.com/freebsd/freebsd/blob/master/sys/fs/cuse/cuse.c#L1676 I don't know if this is cuse specific behavior, or if FreeBSD in general behaves like this.
(In reply to Jan Kokemüller from comment #3) > I don't know if this is cuse specific behavior, > or if FreeBSD in general behaves like this. IOWINT ioctl passes int value in internal buffer and provide pointer to that buffer to handler exactly like IOW(NNN, ###, int) Following is IOWINT->IO convertor from webcamd internals, AFAIR, it is working: /* * Copy in the _IOWINT parameter and pass it as arg pointer * similar to what Linux is doing: */ if ((cmd & IOC_DIRMASK) == IOC_VOID && IOCPARM_LEN(cmd) == sizeof(int)) { if (copy_from_user(&iowint, arg, sizeof(iowint)) != 0) { retval = -EFAULT; goto done; } arg = (void *)(intptr_t)iowint; }
Great, this works! Thank you for the hint.