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>