svn commit: r267556 - user/jceel/soc2014_evdev/head/sys/dev/evdev
Jakub Wojciech Klama
jceel at FreeBSD.org
Mon Jun 16 21:27:49 UTC 2014
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 **);
More information about the svn-src-user
mailing list