svn commit: r270139 - in user/jceel/soc2014_evdev/head/sys: amd64/conf dev/evdev

Jakub Wojciech Klama jceel at FreeBSD.org
Mon Aug 18 16:55:19 UTC 2014


Author: jceel
Date: Mon Aug 18 16:55:18 2014
New Revision: 270139
URL: http://svnweb.freebsd.org/changeset/base/270139

Log:
  Bulk update of evdev code:
  * Implemented async and non-blocking I/O mode in evdev characted
    device driver
  * Fixed crash when closing not-yet-registered uinput device
  * Added UI_DEV_GETPATH ioctl to uinput which provides newly created
    evdev node path
  * Implemented UI_SET_PHYS ioctl in uinput
  * Implemented EVIOCREVOKE ioctl
  * Added uep(4) to EVDEV kernel config

Modified:
  user/jceel/soc2014_evdev/head/sys/amd64/conf/EVDEV
  user/jceel/soc2014_evdev/head/sys/dev/evdev/cdev.c
  user/jceel/soc2014_evdev/head/sys/dev/evdev/evdev.h
  user/jceel/soc2014_evdev/head/sys/dev/evdev/input.h
  user/jceel/soc2014_evdev/head/sys/dev/evdev/uinput.c
  user/jceel/soc2014_evdev/head/sys/dev/evdev/uinput.h

Modified: user/jceel/soc2014_evdev/head/sys/amd64/conf/EVDEV
==============================================================================
--- user/jceel/soc2014_evdev/head/sys/amd64/conf/EVDEV	Mon Aug 18 16:08:07 2014	(r270138)
+++ user/jceel/soc2014_evdev/head/sys/amd64/conf/EVDEV	Mon Aug 18 16:55:18 2014	(r270139)
@@ -322,6 +322,7 @@ device		umass			# Disks/Mass storage - R
 device		ums
 device		uhid
 device		utouch
+device		uep
 
 # Sound support
 device		sound			# Generic sound driver (required)

Modified: user/jceel/soc2014_evdev/head/sys/dev/evdev/cdev.c
==============================================================================
--- user/jceel/soc2014_evdev/head/sys/dev/evdev/cdev.c	Mon Aug 18 16:08:07 2014	(r270138)
+++ user/jceel/soc2014_evdev/head/sys/dev/evdev/cdev.c	Mon Aug 18 16:55:18 2014	(r270139)
@@ -34,6 +34,8 @@
 #include <sys/uio.h>
 #include <sys/proc.h>
 #include <sys/poll.h>
+#include <sys/filio.h>
+#include <sys/fcntl.h>
 #include <sys/selinfo.h>
 #include <sys/malloc.h>
 
@@ -97,6 +99,8 @@ struct evdev_cdev_state
 	struct evdev_client *	ecs_client;
 	struct selinfo		ecs_selp;
 	struct sigio *		ecs_sigio;
+	bool			ecs_async;
+	bool			ecs_revoked;
 };
 
 static int evdev_cdev_count = 0;
@@ -141,6 +145,7 @@ evdev_dtor(void *data)
 	struct evdev_cdev_state *state = (struct evdev_cdev_state *)data;
 
 	seldrain(&state->ecs_selp);
+	funsetown(&state->ecs_sigio);
 	evdev_dispose_client(state->ecs_client);
 	free(data, M_EVDEV);
 }
@@ -161,6 +166,9 @@ evdev_read(struct cdev *dev, struct uio 
 	if (ret != 0)
 		return (ret);
 
+	if (state->ecs_revoked)
+		return (EPERM);
+
 	client = state->ecs_client;
 
 	if (uio->uio_resid % sizeof(struct input_event) != 0) {
@@ -172,8 +180,14 @@ evdev_read(struct cdev *dev, struct uio 
 
 	EVDEV_CLIENT_LOCKQ(client);
 
-	if (EVDEV_CLIENT_EMPTYQ(client))
+	if (EVDEV_CLIENT_EMPTYQ(client)) {
+		if (ioflag & O_NONBLOCK) {
+			EVDEV_CLIENT_UNLOCKQ(client);
+			return (EWOULDBLOCK);
+		}
+
 		mtx_sleep(client, &client->ec_buffer_mtx, 0, "evrea", 0);
+	}
 
 	for (;;) {
 		if (EVDEV_CLIENT_EMPTYQ(client))
@@ -210,6 +224,9 @@ evdev_write(struct cdev *dev, struct uio
 	if (ret != 0)
 		return (ret);
 
+	if (state->ecs_revoked)
+		return (EPERM);
+
 	if (uio->uio_resid % sizeof(struct input_event) != 0) {
 		debugf("write size not multiple of struct input_event size");
 		return (EINVAL);
@@ -232,6 +249,9 @@ evdev_poll(struct cdev *dev, int events,
 	if (ret != 0)
 		return (POLLNVAL);
 
+	if (state->ecs_revoked)
+		return (POLLNVAL);
+
 	client = state->ecs_client;
 
 	if (events & (POLLIN | POLLRDNORM)) {
@@ -299,16 +319,40 @@ evdev_ioctl(struct cdev *dev, u_long cmd
 	int rep_params[2];
 	int ret, len, num, limit;
 
-	len = IOCPARM_LEN(cmd);
-	cmd = IOCBASECMD(cmd);
-	num = IOCNUM(cmd);
-
 	ret = devfs_get_cdevpriv((void **)&state);
 	if (ret != 0)
 		return (ret);
 
+	if (state->ecs_revoked)
+		return (EPERM);
+
+	/* file I/O ioctl handling */
+	switch (cmd) {
+	case FIOSETOWN:
+		return (fsetown(*(int *)data, &state->ecs_sigio));
+
+	case FIOGETOWN:
+		*(int *)data = fgetown(&state->ecs_sigio);
+		return (0);
+
+	case FIONBIO:
+		return (0);
+
+	case FIOASYNC:
+		if (*(int *)data)
+			state->ecs_async = true;
+		else
+			state->ecs_async = false;
+
+		return (0);
+	}
+
+	len = IOCPARM_LEN(cmd);
+	cmd = IOCBASECMD(cmd);
+	num = IOCNUM(cmd);
 	debugf("cdev: ioctl called: cmd=0x%08lx, data=%p", cmd, data);
 
+	/* evdev ioctls handling */
 	switch (cmd) {
 	case IOCBASECMD(EVIOCGVERSION):
 		data = (caddr_t)EV_VERSION;
@@ -412,7 +456,12 @@ evdev_ioctl(struct cdev *dev, u_long cmd
 		break;
 
 	case IOCBASECMD(EVIOCREVOKE):
+		if (*(int *)data != 0)
+			return (EINVAL);
+
+		state->ecs_revoked = true;
 		break;
+
 	}
 
 	if (IOCGROUP(cmd) != 'E')
@@ -511,6 +560,9 @@ evdev_notify_event(struct evdev_client *
 	struct evdev_cdev_state *state = (struct evdev_cdev_state *)data;
 
 	selwakeup(&state->ecs_selp);
+
+	if (state->ecs_async && state->ecs_sigio != NULL)
+		pgsigio(&state->ecs_sigio, SIGIO, 0);
 }
 
 int
@@ -519,10 +571,13 @@ evdev_cdev_create(struct evdev_dev *evde
 	struct evdev_cdev_softc *sc;
 	struct cdev *cdev;
 
+	snprintf(evdev->ev_cdev_name, NAMELEN, "input/event%d",
+	    evdev_cdev_count++);
 	cdev = make_dev(&evdev_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
-	    "input/event%d", evdev_cdev_count++);
+	    evdev->ev_cdev_name, evdev_cdev_count++);
 
-	sc = malloc(sizeof(struct evdev_cdev_softc), M_EVDEV, M_WAITOK | M_ZERO);
+	sc = malloc(sizeof(struct evdev_cdev_softc), M_EVDEV,
+	    M_WAITOK | M_ZERO);
 	
 	sc->ecs_evdev = evdev;
 	evdev->ev_cdev = cdev;

Modified: user/jceel/soc2014_evdev/head/sys/dev/evdev/evdev.h
==============================================================================
--- user/jceel/soc2014_evdev/head/sys/dev/evdev/evdev.h	Mon Aug 18 16:08:07 2014	(r270138)
+++ user/jceel/soc2014_evdev/head/sys/dev/evdev/evdev.h	Mon Aug 18 16:55:18 2014	(r270139)
@@ -74,6 +74,7 @@ struct evdev_dev
 	device_t		ev_dev;
 	void *			ev_softc;
 	struct cdev *		ev_cdev;
+	char			ev_cdev_name[NAMELEN];
 	struct mtx		ev_mtx;
 	struct input_id		ev_id;
 	bool			ev_grabbed;

Modified: user/jceel/soc2014_evdev/head/sys/dev/evdev/input.h
==============================================================================
--- user/jceel/soc2014_evdev/head/sys/dev/evdev/input.h	Mon Aug 18 16:08:07 2014	(r270138)
+++ user/jceel/soc2014_evdev/head/sys/dev/evdev/input.h	Mon Aug 18 16:55:18 2014	(r270139)
@@ -150,7 +150,7 @@ struct input_keymap_entry {
 #define EVIOCGEFFECTS		_IOR('E', 0x84, int)			/* Report number of effects playable at the same time */
 
 #define EVIOCGRAB		_IOW('E', 0x90, int)			/* Grab/Release device */
-#define EVIOCREVOKE		_IOW('E', 0x91, int)			/* Revoke device access */
+#define EVIOCREVOKE		_IOWINT('E', 0x91)			/* Revoke device access */
 
 #define EVIOCSCLOCKID		_IOW('E', 0xa0, int)			/* Set clockid to be used for timestamps */
 

Modified: user/jceel/soc2014_evdev/head/sys/dev/evdev/uinput.c
==============================================================================
--- user/jceel/soc2014_evdev/head/sys/dev/evdev/uinput.c	Mon Aug 18 16:08:07 2014	(r270138)
+++ user/jceel/soc2014_evdev/head/sys/dev/evdev/uinput.c	Mon Aug 18 16:55:18 2014	(r270139)
@@ -120,8 +120,10 @@ uinput_dtor(void *data)
 {
 	struct uinput_cdev_state *state = (struct uinput_cdev_state *)data;
 
-	evdev_unregister(NULL, state->ucs_evdev);
-	evdev_free(state->ucs_evdev);
+	if (state->ucs_connected) {
+		evdev_unregister(NULL, state->ucs_evdev);
+		evdev_free(state->ucs_evdev);
+	}
 
 	free(data, M_EVDEV);
 }
@@ -261,6 +263,11 @@ uinput_ioctl(struct cdev *dev, u_long cm
 		state->ucs_connected = false;
 		break;
 
+	case UI_DEV_GETPATH:
+		strncpy((char *)data, state->ucs_evdev->ev_cdev_name,
+		    UINPUT_MAXLEN);
+		break;
+
 	case UI_SET_EVBIT:
 		evdev_support_event(state->ucs_evdev, (uint16_t)(uintptr_t)data);
 		break;
@@ -290,6 +297,7 @@ uinput_ioctl(struct cdev *dev, u_long cm
 		break;
 
 	case UI_SET_PHYS:
+		evdev_set_phys(state->ucs_evdev, (char *)data);
 		break;
 
 	case UI_SET_SWBIT:

Modified: user/jceel/soc2014_evdev/head/sys/dev/evdev/uinput.h
==============================================================================
--- user/jceel/soc2014_evdev/head/sys/dev/evdev/uinput.h	Mon Aug 18 16:08:07 2014	(r270138)
+++ user/jceel/soc2014_evdev/head/sys/dev/evdev/uinput.h	Mon Aug 18 16:55:18 2014	(r270139)
@@ -36,7 +36,7 @@
 #include <dev/evdev/input.h>
 
 #define UINPUT_VERSION		3
-
+#define	UINPUT_MAXLEN		80
 
 struct uinput_ff_upload {
 	uint32_t		request_id;
@@ -56,6 +56,9 @@ struct uinput_ff_erase {
 #define UI_DEV_CREATE		_IO(UINPUT_IOCTL_BASE, 1)
 #define UI_DEV_DESTROY		_IO(UINPUT_IOCTL_BASE, 2)
 
+/* FreeBSD-specific one */
+#define	UI_DEV_GETPATH		_IOR(UINPUT_IOCTL_BASE, 50, char[UINPUT_MAXLEN])
+
 #define UI_SET_EVBIT		_IOWINT(UINPUT_IOCTL_BASE, 100)
 #define UI_SET_KEYBIT		_IOWINT(UINPUT_IOCTL_BASE, 101)
 #define UI_SET_RELBIT		_IOWINT(UINPUT_IOCTL_BASE, 102)
@@ -64,7 +67,7 @@ struct uinput_ff_erase {
 #define UI_SET_LEDBIT		_IOWINT(UINPUT_IOCTL_BASE, 105)
 #define UI_SET_SNDBIT		_IOWINT(UINPUT_IOCTL_BASE, 106)
 #define UI_SET_FFBIT		_IOWINT(UINPUT_IOCTL_BASE, 107)
-#define UI_SET_PHYS		_IOW(UINPUT_IOCTL_BASE, 108, char*)
+#define UI_SET_PHYS		_IOW(UINPUT_IOCTL_BASE, 108, char[UINPUT_MAXLEN])
 #define UI_SET_SWBIT		_IOWINT(UINPUT_IOCTL_BASE, 109)
 #define UI_SET_PROPBIT		_IOWINT(UINPUT_IOCTL_BASE, 110)
 


More information about the svn-src-user mailing list