Bug 218625 - [PATCH] Evdev ioctls EVIOCGRAB and EVIOCREVOKE don't work together with cuse
Summary: [PATCH] Evdev ioctls EVIOCGRAB and EVIOCREVOKE don't work together with cuse
Status: Closed Works As Intended
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Only Me
Assignee: freebsd-bugs (Nobody)
URL:
Keywords: patch
Depends on:
Blocks:
 
Reported: 2017-04-13 10:45 UTC by Jan Kokemüller
Modified: 2017-04-17 14:33 UTC (History)
2 users (show)

See Also:


Attachments
patch to change type of EVIOCGRAB and EVIOCREVOKE ioctls to _IO (810 bytes, patch)
2017-04-13 10:45 UTC, Jan Kokemüller
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jan Kokemüller 2017-04-13 10:45:01 UTC
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).
Comment 1 Mark Linimon freebsd_committer freebsd_triage 2017-04-13 19:06:15 UTC
Notify committer of original file.
Comment 2 Vladimir Kondratyev freebsd_committer freebsd_triage 2017-04-17 12:19:17 UTC
(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
Comment 3 Jan Kokemüller 2017-04-17 12:48:12 UTC
(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.
Comment 4 Vladimir Kondratyev freebsd_committer freebsd_triage 2017-04-17 13:06:13 UTC
(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;
        }
Comment 5 Jan Kokemüller 2017-04-17 14:33:43 UTC
Great, this works! Thank you for the hint.