From owner-svn-src-stable@freebsd.org  Sun Apr 30 06:14:59 2017
Return-Path: <owner-svn-src-stable@freebsd.org>
Delivered-To: svn-src-stable@mailman.ysv.freebsd.org
Received: from mx1.freebsd.org (mx1.freebsd.org
 [IPv6:2001:1900:2254:206a::19:1])
 by mailman.ysv.freebsd.org (Postfix) with ESMTP id 734FFD56128;
 Sun, 30 Apr 2017 06:14:59 +0000 (UTC)
 (envelope-from dchagin@FreeBSD.org)
Received: from repo.freebsd.org (repo.freebsd.org
 [IPv6:2610:1c1:1:6068::e6a:0])
 (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
 (Client did not present a certificate)
 by mx1.freebsd.org (Postfix) with ESMTPS id 4035919F5;
 Sun, 30 Apr 2017 06:14:59 +0000 (UTC)
 (envelope-from dchagin@FreeBSD.org)
Received: from repo.freebsd.org ([127.0.1.37])
 by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v3U6EwiO096940;
 Sun, 30 Apr 2017 06:14:58 GMT (envelope-from dchagin@FreeBSD.org)
Received: (from dchagin@localhost)
 by repo.freebsd.org (8.15.2/8.15.2/Submit) id v3U6EwPT096938;
 Sun, 30 Apr 2017 06:14:58 GMT (envelope-from dchagin@FreeBSD.org)
Message-Id: <201704300614.v3U6EwPT096938@repo.freebsd.org>
X-Authentication-Warning: repo.freebsd.org: dchagin set sender to
 dchagin@FreeBSD.org using -f
From: Dmitry Chagin <dchagin@FreeBSD.org>
Date: Sun, 30 Apr 2017 06:14:58 +0000 (UTC)
To: src-committers@freebsd.org, svn-src-all@freebsd.org,
 svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject: svn commit: r317602 - stable/11/sys/compat/linux
X-SVN-Group: stable-11
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-BeenThere: svn-src-stable@freebsd.org
X-Mailman-Version: 2.1.23
Precedence: list
List-Id: SVN commit messages for all the -stable branches of the src tree
 <svn-src-stable.freebsd.org>
List-Unsubscribe: <https://lists.freebsd.org/mailman/options/svn-src-stable>, 
 <mailto:svn-src-stable-request@freebsd.org?subject=unsubscribe>
List-Archive: <http://lists.freebsd.org/pipermail/svn-src-stable/>
List-Post: <mailto:svn-src-stable@freebsd.org>
List-Help: <mailto:svn-src-stable-request@freebsd.org?subject=help>
List-Subscribe: <https://lists.freebsd.org/mailman/listinfo/svn-src-stable>,
 <mailto:svn-src-stable-request@freebsd.org?subject=subscribe>
X-List-Received-Date: Sun, 30 Apr 2017 06:14:59 -0000

Author: dchagin
Date: Sun Apr 30 06:14:57 2017
New Revision: 317602
URL: https://svnweb.freebsd.org/changeset/base/317602

Log:
  MFC r317323:
  
  Add Evdev ioctl handler to the Linuxulator.
  
  PR:		218627

Modified:
  stable/11/sys/compat/linux/linux_ioctl.c
  stable/11/sys/compat/linux/linux_ioctl.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/compat/linux/linux_ioctl.c
==============================================================================
--- stable/11/sys/compat/linux/linux_ioctl.c	Sun Apr 30 05:56:57 2017	(r317601)
+++ stable/11/sys/compat/linux/linux_ioctl.c	Sun Apr 30 06:14:57 2017	(r317602)
@@ -70,6 +70,7 @@ __FBSDID("$FreeBSD$");
 #include <net/if_dl.h>
 #include <net/if_types.h>
 
+#include <dev/evdev/input.h>
 #include <dev/usb/usb_ioctl.h>
 
 #ifdef COMPAT_LINUX32
@@ -83,6 +84,7 @@ __FBSDID("$FreeBSD$");
 #include <compat/linux/linux_ioctl.h>
 #include <compat/linux/linux_mib.h>
 #include <compat/linux/linux_socket.h>
+#include <compat/linux/linux_timer.h>
 #include <compat/linux/linux_util.h>
 
 #include <contrib/v4l/videodev.h>
@@ -110,6 +112,7 @@ static linux_ioctl_function_t linux_ioct
 static linux_ioctl_function_t linux_ioctl_v4l2;
 static linux_ioctl_function_t linux_ioctl_special;
 static linux_ioctl_function_t linux_ioctl_fbsd_usb;
+static linux_ioctl_function_t linux_ioctl_evdev;
 
 static struct linux_ioctl_handler cdrom_handler =
 { linux_ioctl_cdrom, LINUX_IOCTL_CDROM_MIN, LINUX_IOCTL_CDROM_MAX };
@@ -139,6 +142,8 @@ static struct linux_ioctl_handler video2
 { linux_ioctl_v4l2, LINUX_IOCTL_VIDEO2_MIN, LINUX_IOCTL_VIDEO2_MAX };
 static struct linux_ioctl_handler fbsd_usb =
 { linux_ioctl_fbsd_usb, FBSD_LUSB_MIN, FBSD_LUSB_MAX };
+static struct linux_ioctl_handler evdev_handler =
+{ linux_ioctl_evdev, LINUX_IOCTL_EVDEV_MIN, LINUX_IOCTL_EVDEV_MAX };
 
 DATA_SET(linux_ioctl_handler_set, cdrom_handler);
 DATA_SET(linux_ioctl_handler_set, vfat_handler);
@@ -154,6 +159,7 @@ DATA_SET(linux_ioctl_handler_set, sg_han
 DATA_SET(linux_ioctl_handler_set, video_handler);
 DATA_SET(linux_ioctl_handler_set, video2_handler);
 DATA_SET(linux_ioctl_handler_set, fbsd_usb);
+DATA_SET(linux_ioctl_handler_set, evdev_handler);
 
 struct handler_element
 {
@@ -3573,6 +3579,65 @@ linux_ioctl_fbsd_usb(struct thread *td, 
 }
 
 /*
+ * Some evdev ioctls must be translated.
+ *  - EVIOCGMTSLOTS is a IOC_READ ioctl on Linux although it has input data
+ *    (must be IOC_INOUT on FreeBSD).
+ *  - On Linux, EVIOCGRAB, EVIOCREVOKE and EVIOCRMFF are defined as _IOW with
+ *    an int argument. You don't pass an int pointer to the ioctl(), however,
+ *    but just the int directly. On FreeBSD, they are defined as _IOWINT for
+ *    this to work.
+ */
+static int
+linux_ioctl_evdev(struct thread *td, struct linux_ioctl_args *args)
+{
+	cap_rights_t rights;
+	struct file *fp;
+	clockid_t clock;
+	int error;
+
+	args->cmd = SETDIR(args->cmd);
+
+	switch (args->cmd) {
+	case (EVIOCGRAB & ~IOC_DIRMASK) | IOC_IN:
+		args->cmd = EVIOCGRAB;
+		break;
+	case (EVIOCREVOKE & ~IOC_DIRMASK) | IOC_IN:
+		args->cmd = EVIOCREVOKE;
+		break;
+	case (EVIOCRMFF & ~IOC_DIRMASK) | IOC_IN:
+		args->cmd = EVIOCRMFF;
+		break;
+	case EVIOCSCLOCKID: {
+		error = copyin(PTRIN(args->arg), &clock, sizeof(clock));
+		if (error != 0)
+			return (error);
+		if (clock & ~(LINUX_IOCTL_EVDEV_CLK))
+			return (EINVAL);
+		error = linux_to_native_clockid(&clock, clock);
+		if (error != 0)
+			return (error);
+
+		error = fget(td, args->fd,
+		    cap_rights_init(&rights, CAP_IOCTL), &fp);
+		if (error != 0)
+			return (error);
+
+		error = fo_ioctl(fp, EVIOCSCLOCKID, &clock, td->td_ucred, td);
+		fdrop(fp, td);
+		return (error);
+	}
+	default:
+		break;
+	}
+
+	if (IOCBASECMD(args->cmd) ==
+	    ((EVIOCGMTSLOTS(0) & ~IOC_DIRMASK) | IOC_OUT))
+		args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_INOUT;
+
+	return (sys_ioctl(td, (struct ioctl_args *)args));
+}
+
+/*
  * main ioctl syscall function
  */
 

Modified: stable/11/sys/compat/linux/linux_ioctl.h
==============================================================================
--- stable/11/sys/compat/linux/linux_ioctl.h	Sun Apr 30 05:56:57 2017	(r317601)
+++ stable/11/sys/compat/linux/linux_ioctl.h	Sun Apr 30 06:14:57 2017	(r317602)
@@ -749,7 +749,13 @@
  */
 #define LINUX_BTRFS_IOC_CLONE		0x9409 /* 0x40049409 */
 
-
+/*
+ * Linux evdev ioctl min and max
+ */
+#define LINUX_IOCTL_EVDEV_MIN		0x4500
+#define LINUX_IOCTL_EVDEV_MAX		0x45ff
+#define LINUX_IOCTL_EVDEV_CLK		LINUX_CLOCK_REALTIME |	\
+	    LINUX_CLOCK_MONOTONIC |LINUX_CLOCK_BOOTTIME
 /*
  * Pluggable ioctl handlers
  */