Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 16 Jun 2014 21:27:48 +0000 (UTC)
From:      Jakub Wojciech Klama <jceel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r267556 - user/jceel/soc2014_evdev/head/sys/dev/evdev
Message-ID:  <201406162127.s5GLRmoq038368@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jceel
Date: Mon Jun 16 21:27:48 2014
New Revision: 267556
URL: http://svnweb.freebsd.org/changeset/base/267556

Log:
  Changes as follows:
  - Unified ioctls handling (some have fixed data length encoded,
    other may have variable data length)
  - Added preliminary support for repeating devices with two modes:
    DRIVER_REPEAT (key repeating done internally by driver) and
    EVDEV_REPEAT (repeating done by evdev layer). For now, only
    former is supported.
  - Added real EVIOCGID support with automatic guessing of device id's
    in evdev layer - currently supported for PCI and USB devices.

Modified:
  user/jceel/soc2014_evdev/head/sys/dev/evdev/cdev.c
  user/jceel/soc2014_evdev/head/sys/dev/evdev/evdev.c
  user/jceel/soc2014_evdev/head/sys/dev/evdev/evdev.h

Modified: user/jceel/soc2014_evdev/head/sys/dev/evdev/cdev.c
==============================================================================
--- user/jceel/soc2014_evdev/head/sys/dev/evdev/cdev.c	Mon Jun 16 20:43:43 2014	(r267555)
+++ user/jceel/soc2014_evdev/head/sys/dev/evdev/cdev.c	Mon Jun 16 21:27:48 2014	(r267556)
@@ -40,7 +40,7 @@
 #include <dev/evdev/input.h>
 #include <dev/evdev/evdev.h>
 
-#define	DEBUG
+//#define	DEBUG
 #ifdef DEBUG
 #define	debugf(fmt, args...)	printf("evdev: " fmt "\n", ##args);
 #else
@@ -91,12 +91,17 @@ struct evdev_cdev_softc
 	LIST_ENTRY(evdev_cdev_softc) ecs_link;
 };
 
-struct evdev_cdev_state
+struct uinput_cdev_state
 {
-	struct mtx		ecs_mtx;
-	struct evdev_client *	ecs_client;
-	struct selinfo		ecs_selp;
-	struct sigio *		ecs_sigio;
+	struct mtx		ucs_mtx;
+	struct evdev_dev *	ucs_dev;
+	struct selinfo		ucs_selp;
+	struct sigio *		ucs_sigio;
+
+	struct input_event *	ucs_buffer;
+	int			ucs_buffer_size;
+	int			ucs_buffer_head;
+	int			ucs_buffer_tail;
 };
 
 static int evdev_cdev_count = 0;
@@ -296,6 +301,7 @@ evdev_ioctl(struct cdev *dev, u_long cmd
 	struct evdev_dev *evdev = sc->ecs_evdev;
 	struct evdev_cdev_state *state;
 	struct input_keymap_entry *ke;
+	int rep_params[2];
 	int ret, len, num, limit;
 
 	len = IOCPARM_LEN(cmd);
@@ -309,24 +315,42 @@ evdev_ioctl(struct cdev *dev, u_long cmd
 	debugf("cdev: ioctl called: cmd=0x%08lx, data=%p", cmd, data);
 
 	switch (cmd) {
-	case EVIOCGVERSION:
+	case IOCBASECMD(EVIOCGVERSION):
 		data = (caddr_t)EV_VERSION;
 		break;
 
-	case EVIOCGID:
+	case IOCBASECMD(EVIOCGID):
+		debugf("cdev: EVIOCGID: bus=%d vendor=0x%04x product=0x%04x",
+		    evdev->ev_id.bustype, evdev->ev_id.vendor,
+		    evdev->ev_id.product);
 		memcpy(data, &evdev->ev_id, sizeof(struct input_id));
 		break;
 
-	case EVIOCGREP:
-		return ENOTSUP;
+	case IOCBASECMD(EVIOCGREP):
+		if (evdev->ev_repeat_mode == NO_REPEAT)
+			return ENOTSUP;
+
+		rep_params[0] = evdev->ev_rep[REP_DELAY];
+		rep_params[1] = evdev->ev_rep[REP_PERIOD];
+		memcpy(data, rep_params, sizeof(rep_params));
+		break;
+
+	case IOCBASECMD(EVIOCSREP):
+		if (evdev->ev_repeat_mode == NO_REPEAT)
+			return ENOTSUP;
+
+		memcpy(rep_params, data, sizeof(rep_params));
+		evdev->ev_rep[REP_DELAY] = rep_params[0];
+		evdev->ev_rep[REP_PERIOD] = rep_params[1];
 
-	case EVIOCSREP:
-		return ENOTSUP;
+		if (evdev->ev_repeat_mode == DRIVER_REPEAT) {
+			evdev_inject_event(evdev, EV_REP, REP_DELAY, rep_params[0]);
+			evdev_inject_event(evdev, EV_REP, REP_PERIOD, rep_params[1]);
+		}
 
-	case EVIOCGKEYCODE:
-		return ENOTSUP;
+		break;
 
-	case EVIOCGKEYCODE_V2:
+	case IOCBASECMD(EVIOCGKEYCODE_V2):
 		if (evdev->ev_methods->ev_get_keycode == NULL)
 			return ENOTSUP;
 
@@ -334,10 +358,7 @@ evdev_ioctl(struct cdev *dev, u_long cmd
 		evdev->ev_methods->ev_get_keycode(evdev, evdev->ev_softc, ke);
 		break;
 
-	case EVIOCSKEYCODE:
-		return ENOTSUP;
-
-	case EVIOCSKEYCODE_V2:
+	case IOCBASECMD(EVIOCSKEYCODE_V2):
 		if (evdev->ev_methods->ev_set_keycode == NULL)
 			return ENOTSUP;
 
@@ -388,14 +409,14 @@ evdev_ioctl(struct cdev *dev, u_long cmd
 		memcpy(data, evdev->ev_sw_states, limit);
 		break;
 
-	case EVIOCGRAB:
+	case IOCBASECMD(EVIOCGRAB):
 		if (data)
 			evdev_grab_client(state->ecs_client);
 		else
 			evdev_release_client(state->ecs_client);
 		break;
 
-	case EVIOCREVOKE:
+	case IOCBASECMD(EVIOCREVOKE):
 		break;
 	}
 

Modified: user/jceel/soc2014_evdev/head/sys/dev/evdev/evdev.c
==============================================================================
--- user/jceel/soc2014_evdev/head/sys/dev/evdev/evdev.c	Mon Jun 16 20:43:43 2014	(r267555)
+++ user/jceel/soc2014_evdev/head/sys/dev/evdev/evdev.c	Mon Jun 16 21:27:48 2014	(r267556)
@@ -34,10 +34,15 @@
 #include <sys/conf.h>
 #include <sys/malloc.h>
 
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+
 #include <dev/evdev/input.h>
 #include <dev/evdev/evdev.h>
 
-#define	DEBUG
+//#define	DEBUG
 #ifdef DEBUG
 #define	debugf(fmt, args...)	printf("evdev: " fmt "\n", ##args)
 #else
@@ -50,6 +55,9 @@ MALLOC_DEFINE(M_EVDEV, "evdev", "evdev m
 
 static inline void changebit(uint32_t *array, int, int);
 static struct evdev_client *evdev_client_alloc(void);
+static void evdev_assign_id(struct evdev_dev *);
+static void evdev_start_repeat(struct evdev_dev *, int32_t);
+static void evdev_stop_repeat(struct evdev_dev *);
 static void evdev_client_push(struct evdev_client *, uint16_t, uint16_t,
     int32_t);
 
@@ -65,6 +73,7 @@ changebit(uint32_t *array, int bit, int 
 struct evdev_dev *
 evdev_alloc(void)
 {
+
 	return malloc(sizeof(struct evdev_dev), M_EVDEV, M_WAITOK | M_ZERO);
 }
 
@@ -82,6 +91,21 @@ evdev_register(device_t dev, struct evde
 	strlcpy(evdev->ev_shortname, device_get_nameunit(dev), NAMELEN);
 	LIST_INIT(&evdev->ev_clients);
 
+	if (evdev->ev_repeat_mode == EVDEV_REPEAT) {
+		/* Initialize callout */
+		callout_init(&evdev->ev_rep_callout, 1);
+
+		if (evdev->ev_rep[REP_DELAY] == 0 &&
+		    evdev->ev_rep[REP_PERIOD] == 0) {
+			/* Supply default values */
+			evdev->ev_rep[REP_DELAY] = 300;
+			evdev->ev_rep[REP_PERIOD] = 50;
+		}
+	}
+
+	/* Retrieve bus info */
+	evdev_assign_id(evdev);
+
 	/* Create char device node */
 	ret = evdev_cdev_create(evdev);
 	if (ret != 0)
@@ -186,6 +210,17 @@ evdev_support_sw(struct evdev_dev *evdev
 }
 
 inline void
+evdev_support_repeat(struct evdev_dev *evdev, enum evdev_repeat_mode mode)
+{
+
+	if (mode != NO_REPEAT)
+		setbit(&evdev->ev_type_flags, EV_REP)
+
+	evdev->ev_repeat_mode = mode;
+}
+
+
+inline void
 evdev_set_absinfo(struct evdev_dev *evdev, uint16_t axis,
     struct input_absinfo *absinfo)
 {
@@ -193,6 +228,15 @@ evdev_set_absinfo(struct evdev_dev *evde
 	memcpy(&evdev->ev_absinfo[axis], absinfo, sizeof(struct input_absinfo));
 }
 
+inline void
+evdev_set_repeat_params(struct evdev_dev *evdev, uint16_t property, int value)
+{
+
+	KASSERT(property < REP_CNT, ("invalid evdev repeat property"));
+	evdev->ev_rep[property] = value;
+}
+
+
 int
 evdev_push_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
     int32_t value)
@@ -349,6 +393,60 @@ evdev_release_client(struct evdev_client
 }
 
 static void
+evdev_assign_id(struct evdev_dev *dev)
+{
+	device_t parent;
+	devclass_t devclass;
+	const char *classname;
+
+	if (dev->ev_dev == NULL) {
+		dev->ev_id.bustype = BUS_VIRTUAL;
+		return;
+	}
+
+	parent = device_get_parent(dev->ev_dev);
+	if (parent == NULL) {
+		dev->ev_id.bustype = BUS_HOST;
+		return;
+	}
+
+	devclass = device_get_devclass(parent);
+	classname = devclass_get_name(devclass);
+
+	debugf("parent bus classname: %s", classname);
+
+	if (strcmp(classname, "pci") == 0) {
+		dev->ev_id.bustype = BUS_PCI;
+		dev->ev_id.vendor = pci_get_vendor(dev->ev_dev);
+		dev->ev_id.product = pci_get_device(dev->ev_dev);
+		dev->ev_id.version = pci_get_revid(dev->ev_dev);
+		return;
+	}
+
+	if (strcmp(classname, "uhub") == 0) {
+		struct usb_attach_arg *uaa = device_get_ivars(dev->ev_dev);
+		dev->ev_id.bustype = BUS_USB;
+		dev->ev_id.vendor = uaa->info.idVendor;
+		dev->ev_id.product = uaa->info.idProduct;
+		return;
+	}
+
+	dev->ev_id.bustype = BUS_HOST;
+}
+
+static void
+evdev_start_repeat(struct evdev_dev *dev, int32_t key)
+{
+	
+}
+
+static void
+evdev_stop_repeat(struct evdev_dev *dev)
+{
+
+}
+
+static void
 evdev_client_push(struct evdev_client *client, uint16_t type, uint16_t code,
     int32_t value)
 {

Modified: user/jceel/soc2014_evdev/head/sys/dev/evdev/evdev.h
==============================================================================
--- user/jceel/soc2014_evdev/head/sys/dev/evdev/evdev.h	Mon Jun 16 20:43:43 2014	(r267555)
+++ user/jceel/soc2014_evdev/head/sys/dev/evdev/evdev.h	Mon Jun 16 21:27:48 2014	(r267556)
@@ -48,6 +48,13 @@ typedef void (evdev_keycode_t)(struct ev
     struct input_keymap_entry *);
 typedef void (evdev_client_event_t)(struct evdev_client *, void *);
 
+enum evdev_repeat_mode
+{
+	NO_REPEAT,
+	DRIVER_REPEAT,
+	EVDEV_REPEAT
+};
+
 struct evdev_methods
 {
 	evdev_open_t		*ev_open;
@@ -68,6 +75,7 @@ struct evdev_dev
 	struct mtx		ev_mtx;
 	struct input_id		ev_id;
 	bool			ev_grabbed;
+	enum evdev_repeat_mode	ev_repeat_mode;
 
 	/* Supported features: */
 	uint32_t		ev_type_flags[howmany(EV_CNT, 32)];
@@ -80,16 +88,16 @@ struct evdev_dev
 	uint32_t		ev_sw_flags[howmany(SW_CNT, 32)];
 	struct input_absinfo	ev_absinfo[ABS_CNT];
 
+	/* Repeat parameters & callout: */
+	int			ev_rep[REP_CNT];
+	struct callout		ev_rep_callout;
+
 	/* State: */
 	uint32_t		ev_key_states[howmany(KEY_CNT, 32)];
 	uint32_t		ev_led_states[howmany(LED_CNT, 32)];
 	uint32_t		ev_snd_states[howmany(SND_CNT, 32)];
 	uint32_t		ev_sw_states[howmany(SW_CNT, 32)];
 
-	/* Keyboard delay/repeat: */
-	int			ev_kbd_delay;
-	int			ev_kbd_repeat;
-
 	/* Counters: */
 	uint64_t		ev_event_count;
 	int			ev_clients_count;
@@ -146,7 +154,9 @@ void evdev_support_msc(struct evdev_dev 
 void evdev_support_led(struct evdev_dev *, uint16_t);
 void evdev_support_snd(struct evdev_dev *, uint16_t);
 void evdev_support_sw(struct evdev_dev *, uint16_t);
+void evdev_support_repeat(struct evdev_dev *, enum evdev_repeat_mode);
 void evdev_set_absinfo(struct evdev_dev *, uint16_t, struct input_absinfo *);
+void evdev_set_repeat_params(struct evdev_dev *, uint16_t, int);
 
 /* Client interface: */
 int evdev_register_client(struct evdev_dev *, struct evdev_client **);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201406162127.s5GLRmoq038368>