Index: Mk/Uses/evdev.mk =================================================================== --- Mk/Uses/evdev.mk +++ Mk/Uses/evdev.mk @@ -0,0 +1,122 @@ +# $FreeBSD$ +# +# Handle Input event device headers patches and dependencies +# +# Feature: evdev +# Usage: USES=evdev +# Valid ARGS: ports base bundled +# +# 1. ports - introduces build dependence on devel/libevdev-headers port. +# It has more IOCTL definitions than we support but libevdev handles +# that at runtime. +# 2. base - port compiles with evdev headers from base system. sed script is +# provided for conversion of include paths in source files in that case. +# 3. bundled - port (currently devel/libevdev and devel/libevdev-headers) +# compiles with bundled evdev headers. sed script for header conversion +# from Linux to FreeBSD is provided in that case. +# +# 1 implies 3 for some strange software like libinput that has both bundled +# evdev headers and external evdev headers dependency. +# +# default: ports +# +# EVDEV_WRKSRC top-level path for evdev headers and directory traversal +# default: ${WRKSRC} +# +# Provide support to convert port-supplied copies of evdev headers from Linux +# EVDEV_INCLUDE top-level path for port-supplied evdev headers +# default: ${EVDEV_WRKSRC}/include +# EVDEV_INPUT_H path to port-supplied input.h header +# default: ${EVDEV_INCLUDE}/linux/input.h +# EVDEV_UINPUT_H path to port-supplied uinput.h header +# default: ${EVDEV_INCLUDE}/linux/uinput.h +# +# This variables can be defined to convert sources from using port system supplied +# headers to base system supplied ones. +# EVDEV_SOURCE_REGEX a regular expression to match files that needs to be converted +# EVDEV_SOURCE_FILES list of files relative to ${EVDEV_WRKSRC} +# EVDEV_SOURCE_GLOB list of glob pattern find(1) will match with +# +# MAINTAINER: portmgr@FreeBSD.org + +.if !defined(_INCLUDE_USES_EVDEV_MK) +_INCLUDE_USES_EVDEV_MK= yes + +_valid_ARGS= ports base bundled + +.if empty(evdev_ARGS) +evdev_ARGS= ports +.endif + +# Sanity checks +.for _arg in ${evdev_ARGS} +. if ! ${_valid_ARGS:M${_arg}} +IGNORE= Incorrect 'USES+= evdev:${evdev_ARGS}' usage: argument [${_arg}] is not recognized +. endif +.endfor + +.if ${evdev_ARGS} == ports +BUILD_DEPENDS+= ${LOCALBASE}/include/linux/input.h:devel/libevdev-headers +CFLAGS+= -I${LOCALBASE}/include +CXXFLAGS+= -I${LOCALBASE}/include +.endif + +EVDEV_WRKSRC?= ${WRKSRC} +EVDEV_INCLUDE?= ${EVDEV_WRKSRC}/include +EVDEV_INPUT_H?= ${EVDEV_INCLUDE}/linux/input.h +EVDEV_UINPUT_H?= ${EVDEV_INCLUDE}/linux/uinput.h + +EVDEV_HEADER_PATTERN= '/^ *\# *include/s|[<"]linux(/u?input\.h)[>"]||' + +_USES_patch+= 700:evdev-post-patch + +evdev-post-patch: +.if ${evdev_ARGS} != base +# Patch port-bundled input.h and uinput.h to be FreeBSD-compatible + @if [ -f "${EVDEV_INPUT_H}" ]; then \ + ${REINPLACE_CMD} -i '' -E -e \ + 's/__u([[:digit:]]+)/uint\1_t/g ; \ + s/__s([[:digit:]]+)/int\1_t/g ; \ + /# *include/ s||| ; \ + /# *include[[:space:]]+/d ; \ + /EVIOC(RMFF|GRAB|REVOKE)/ s/_IOW(.*), *int/_IOWINT\1/ ; \ + /EVIOCGKEYCODE/ s/_IOR/_IOWR/ ; \ + /EVIOCGMASK/ s/_IOR/_IOW/ ; \ + /EVIOCGMTSLOTS/ s/_IOC_READ/IOC_INOUT/ ; \ + /#define/ s/_IOC_READ/IOC_OUT/ ; \ + /#define/ s/_IOC_WRITE/IOC_IN/' \ + "${EVDEV_INPUT_H}"; \ + fi + @if [ -f "${EVDEV_UINPUT_H}" ]; then \ + ${REINPLACE_CMD} -i '' -E -e \ + 's/__u([[:digit:]]+)/uint\1_t/g ; \ + s/__s([[:digit:]]+)/int\1_t/g ; \ + /# *include/s||| ; \ + /#define/ s/_IOW(.*), *int/_IOWINT\1/ ; \ + /#define/ s/_IOW(.*), *char\*/_IO\1/ ; \ + /#define/ s/_IOC_READ/IOC_OUT/ ; \ + /UI_GET_SYSNAME/ s/300/44/ ; \ + /UI_GET_VERSION/ s/301/45/' \ + "${EVDEV_UINPUT_H}"; \ + fi +.else +# Patch port sources to include dev/evdev/ files instead of linux/ +. if exists(/usr/include/dev/evdev/input.h) +. if defined(EVDEV_SOURCE_FILES) + @cd ${EVDEV_WRKSRC}; \ + ${REINPLACE_CMD} -i '' -E -e ${EVDEV_HEADER_PATTERN} \ + ${EVDEV_SOURCE_FILES} +. elif defined(EVDEV_SOURCE_REGEX) + @${FIND} -E ${EVDEV_WRKSRC} -type f -iregex '${EVDEV_SOURCE_REGEX}' \ + -print0 | ${XARGS} -0 \ + ${REINPLACE_CMD} -i '' -E -e ${EVDEV_HEADER_PATTERN} +. else +. for f in ${EVDEV_SOURCE_GLOB} + @${FIND} ${EVDEV_WRKSRC} -type f -name '${f}' -print0 | ${XARGS} -0 \ + ${REINPLACE_CMD} -i '' -E -e ${EVDEV_HEADER_PATTERN} +. endfor +. endif +. endif +.endif + +.endif Index: comms/lirc/Makefile =================================================================== --- comms/lirc/Makefile +++ comms/lirc/Makefile @@ -11,10 +11,8 @@ MAINTAINER= ports@FreeBSD.org COMMENT= Linux Infrared Remote Control -BUILD_DEPENDS= v4l_compat>=1.0.20110603:multimedia/v4l_compat - INSTALL_TARGET= install-strip -USES= alias autoreconf gmake libtool python tar:bzip2 +USES= alias autoreconf gmake libtool python tar:bzip2 evdev USE_XORG= sm x11 USE_CSTD= gnu89 USE_LDCONFIG= yes Index: comms/svxlink/Makefile =================================================================== --- comms/svxlink/Makefile +++ comms/svxlink/Makefile @@ -17,14 +17,12 @@ libsigc-2.0.so:devel/libsigc++20 \ libpopt.so:devel/popt \ libopus.so:audio/opus -BUILD_DEPENDS= pkg-config:devel/pkgconf \ - ${LOCALBASE}/include/linux/input.h:multimedia/v4l_compat USE_GITHUB= yes GH_ACCOUNT= sm0svx GH_PROJECT= svxlink -USES= cmake tcl +USES= cmake tcl pkgconfig evdev CMAKE_SOURCE_PATH= ${WRKSRC}/src CMAKE_ARGS+= -DMAN_INSTALL_DIR:FILEPATH=${MANDIRS} \ -DLOCAL_STATE_DIR=/var Index: devel/evemu/Makefile =================================================================== --- devel/evemu/Makefile +++ devel/evemu/Makefile @@ -0,0 +1,43 @@ +# Created by: Vladimir Kondratiev +# $FreeBSD$ + +PORTNAME= evemu +PORTVERSION= 2.4.0 +CATEGORIES= devel +MASTER_SITES= http://www.freedesktop.org/software/${PORTNAME}/ + +MAINTAINER= wulf@cicgroup.ru +COMMENT= Records and replays EVDEV descriptions and events + +LICENSE= GPLv3 + +LIB_DEPENDS= libevdev.so:devel/libevdev + +USES= tar:xz python pathfix libtool pkgconfig evdev + +OPTIONS_DEFINE= MANPAGES +OPTIONS_DEFAULT=MANPAGES +OPTIONS_SUB= yes + +# evemu-event.1, evemu-play.1 and evemu-record.1 manpages are broken +# due to docbook-xsl bug: https://sourceforge.net/p/docbook/bugs/1058/ +MANPAGES_BUILD_DEPENDS= xmlto:textproc/xmlto \ + asciidoc:textproc/asciidoc +MANPAGES_CONFIGURE_ENV_OFF= ac_cv_path_XMLTO="" \ + ac_cv_path_ASCIIDOC="" + +GNU_CONFIGURE= yes +CFLAGS+= -D_WITH_DPRINTF +USE_LDCONFIG= yes +INSTALL_TARGET= install-strip + +TEST_TARGET= check +TEST_WRKSRC= ${WRKSRC}/test + +post-patch: + ${REINPLACE_CMD} -e 's|program_invocation_short_name|getprogname()|' \ + ${WRKSRC}/tools/evemu-event.c ${WRKSRC}/tools/evemu-record.c + ${REINPLACE_CMD} -e 's/versionsort/alphasort/' \ + ${WRKSRC}/tools/find_event_devices.c + +.include Index: devel/evemu/distinfo =================================================================== --- devel/evemu/distinfo +++ devel/evemu/distinfo @@ -0,0 +1,2 @@ +SHA256 (evemu-2.4.0.tar.xz) = 0706ea5a830203f9cdb30c0e10c8c41d2427128ba9041543a5ae157fa3b4a30e +SIZE (evemu-2.4.0.tar.xz) = 505848 Index: devel/evemu/files/patch-src_evemu.c =================================================================== --- devel/evemu/files/patch-src_evemu.c +++ devel/evemu/files/patch-src_evemu.c @@ -0,0 +1,21 @@ +--- src/evemu.c.orig 2016-02-25 09:00:31 UTC ++++ src/evemu.c +@@ -430,16 +430,13 @@ int evemu_write(const struct evemu_devic + static int parse_name(struct evemu_device *dev, const char *line) + { + int matched; +- char *devname = NULL; ++ char devname[UINPUT_MAX_NAME_SIZE]; + +- if ((matched = sscanf(line, "N: %m[^\n]\n", &devname)) > 0) { ++ if ((matched = sscanf(line, "N: %[^\n]\n", devname)) > 0) { + if (strlen(evemu_get_name(dev)) == 0) + evemu_set_name(dev, devname); + } + +- if (devname != NULL) +- free(devname); +- + if (matched <= 0) + error(FATAL, "Expected device name, but got: %s", line); + Index: devel/evemu/pkg-descr =================================================================== --- devel/evemu/pkg-descr +++ devel/evemu/pkg-descr @@ -0,0 +1,8 @@ +Tools and bindings for kernel input event device emulation and data capture +and replay. + +Evemu provides a programmatic API to access the kernel input event devices. +The original and intended purpose is for supporting multi-touch input, +especially with regard to the Ubuntu touch and gesture stack. + +WWW: http://www.freedesktop.org/wiki/Evemu Index: devel/evemu/pkg-plist =================================================================== --- devel/evemu/pkg-plist +++ devel/evemu/pkg-plist @@ -0,0 +1,28 @@ +bin/evemu-describe +bin/evemu-device +bin/evemu-event +bin/evemu-play +bin/evemu-record +include/evemu.h +lib/libevemu.a +lib/libevemu.so +lib/libevemu.so.3 +lib/libevemu.so.3.0.1 +%%PYTHON_SITELIBDIR%%/evemu/__init__.py +%%PYTHON_SITELIBDIR%%/evemu/__init__.pyc +%%PYTHON_SITELIBDIR%%/evemu/__init__.pyo +%%PYTHON_SITELIBDIR%%/evemu/base.py +%%PYTHON_SITELIBDIR%%/evemu/base.pyc +%%PYTHON_SITELIBDIR%%/evemu/base.pyo +%%PYTHON_SITELIBDIR%%/evemu/const.py +%%PYTHON_SITELIBDIR%%/evemu/const.pyc +%%PYTHON_SITELIBDIR%%/evemu/const.pyo +%%PYTHON_SITELIBDIR%%/evemu/exception.py +%%PYTHON_SITELIBDIR%%/evemu/exception.pyc +%%PYTHON_SITELIBDIR%%/evemu/exception.pyo +libdata/pkgconfig/evemu.pc +%%MANPAGES%%man/man1/evemu-describe.1.gz +%%MANPAGES%%man/man1/evemu-device.1.gz +%%MANPAGES%%man/man1/evemu-event.1.gz +%%MANPAGES%%man/man1/evemu-play.1.gz +%%MANPAGES%%man/man1/evemu-record.1.gz Index: devel/libevdev-headers/Makefile =================================================================== --- devel/libevdev-headers/Makefile +++ devel/libevdev-headers/Makefile @@ -0,0 +1,29 @@ +# $FreeBSD$ + +PORTNAME= libevdev +PORTREVISION= 0 +PKGNAMESUFFIX= -headers + +COMMENT= Event device IOCTL header files + +LICENSE= GPLv2 + +NO_BUILD= yes +NO_ARCH= yes + +MASTERDIR= ${.CURDIR}/../../devel/libevdev +DESCR= ${.CURDIR}/pkg-descr +PLIST= ${.CURDIR}/pkg-plist +LIBEVDEV_SLAVE= headers + +HEADERS= input.h input-event-codes.h uinput.h +PLIST_FILES= ${HEADERS:S|^|include/linux/|} + +do-install: + @${MKDIR} ${STAGEDIR}${PREFIX}/include/linux/ +.for i in ${HEADERS} + ${INSTALL_DATA} ${WRKSRC}/include/linux/${i} \ + ${STAGEDIR}${PREFIX}/include/linux/ +.endfor + +.include "${MASTERDIR}/Makefile" Index: devel/libevdev-headers/pkg-descr =================================================================== --- devel/libevdev-headers/pkg-descr +++ devel/libevdev-headers/pkg-descr @@ -0,0 +1 @@ +This port installs the event device header files. Index: devel/libevdev/Makefile =================================================================== --- devel/libevdev/Makefile +++ devel/libevdev/Makefile @@ -1,32 +1,46 @@ # $FreeBSD$ PORTNAME= libevdev -PORTVERSION= 1.4.4 +PORTVERSION= 1.5.2 CATEGORIES= devel MASTER_SITES= http://freedesktop.org/software/${PORTNAME}/ MAINTAINER= hselasky@FreeBSD.org COMMENT= Linux Event Device library -LICENSE= MIT # without linux/*.h -LICENSE_FILE= ${WRKSRC}/COPYING +LICENSE?= MIT # without linux/*.h + +LIBEVDEV_SLAVE?= no -BUILD_DEPENDS= v4l_compat>=1.0.20110603:multimedia/v4l_compat -RUN_DEPENDS= v4l_compat>=1.0.20110603:multimedia/v4l_compat +USES+= tar:xz evdev:bundled -USES= gmake libtool pathfix python:build tar:xz -EXTRACT_AFTER_ARGS= --exclude include # v4l_compat +.if ${LIBEVDEV_SLAVE} != headers +LICENSE_FILE= ${WRKSRC}/COPYING +USES+= gmake libtool pathfix python:build GNU_CONFIGURE= yes CONFIGURE_ENV= ac_cv_path_DOXYGEN="" -CPPFLAGS+= -I${LOCALBASE}/include # v4l_compat INSTALL_TARGET= install-strip USE_LDCONFIG= yes +OPTIONS_DEFINE+= TEST +TEST_USES+= pkgconfig +TEST_LIB_DEPENDS= libcheck.so:devel/libcheck +TEST_TARGET= check +TEST_WRKSRC= ${WRKSRC}/test + +# XXX test requires /dev/uinput and should be run as root +#.if ! exists(/usr/include/dev/evdev/input.h) +# test-libevdev current results: "98%: Checks: 115, Failures: 2, Errors: 0" +OPTIONS_EXCLUDE= TEST +#.endif +.endif + post-patch: - @${REINPLACE_CMD} -e '/input\.h/s,top_srcdir,LOCALBASE,' \ - ${WRKSRC}/libevdev/Makefile.in -# XXX tools require signalfd(2), test require /dev/uinput - @${REINPLACE_CMD} -e '/^SUBDIRS/s,tools test,,' \ + @${REINPLACE_CMD} -e 's|program_invocation_short_name|getprogname()|' \ + ${WRKSRC}/tools/libevdev-tweak-device.c + +post-patch-TEST-off: + ${REINPLACE_CMD} -e '/^SUBDIRS/s,test,,' \ ${WRKSRC}/Makefile.in .include Index: devel/libevdev/distinfo =================================================================== --- devel/libevdev/distinfo +++ devel/libevdev/distinfo @@ -1,2 +1,3 @@ -SHA256 (libevdev-1.4.4.tar.xz) = ed9979369b6a6e28f5897d099538549ecffb2b7c00c1b717eb77c31d85bc45a9 -SIZE (libevdev-1.4.4.tar.xz) = 409856 +TIMESTAMP = 1467541593 +SHA256 (libevdev-1.5.2.tar.xz) = 5ee2163656a61f5703cb5c08a05c9471ffb7b640bfbe2c55194ea50d908f629b +SIZE (libevdev-1.5.2.tar.xz) = 397848 Index: devel/libevdev/files/patch-libevdev_libevdev-uinput.c =================================================================== --- devel/libevdev/files/patch-libevdev_libevdev-uinput.c +++ devel/libevdev/files/patch-libevdev_libevdev-uinput.c @@ -0,0 +1,40 @@ +--- libevdev/libevdev-uinput.c.orig 2016-04-28 00:40:58 UTC ++++ libevdev/libevdev-uinput.c +@@ -182,6 +182,7 @@ libevdev_uinput_get_fd(const struct libe + return uinput_dev->fd; + } + ++#if defined(linux) + static int is_event_device(const struct dirent *dent) { + return strncmp("event", dent->d_name, 5) == 0; + } +@@ -213,10 +214,12 @@ fetch_device_node(const char *path) + static int is_input_device(const struct dirent *dent) { + return strncmp("input", dent->d_name, 5) == 0; + } ++#endif + + static int + fetch_syspath_and_devnode(struct libevdev_uinput *uinput_dev) + { ++#if defined(linux) + struct dirent **namelist; + int ndev, i; + int rc; +@@ -290,6 +293,16 @@ fetch_syspath_and_devnode(struct libevde + free(namelist); + + return uinput_dev->devnode ? 0 : -1; ++#elif defined(__FreeBSD__) ++ char devnode[80]; ++ if (ioctl(uinput_dev->fd, UI_GET_SYSNAME(sizeof(devnode)), devnode) < 0) ++ return -1; ++ asprintf(&uinput_dev->devnode, "/dev/input/%s", devnode); ++ uinput_dev->syspath = strdup(uinput_dev->devnode); ++ return 0; ++#else ++ return -1; ++#endif + } + + static int Index: devel/libevdev/files/patch-test_test-libevdev-events.c =================================================================== --- devel/libevdev/files/patch-test_test-libevdev-events.c +++ devel/libevdev/files/patch-test_test-libevdev-events.c @@ -0,0 +1,20 @@ +--- test/test-libevdev-events.c.orig 2016-04-28 00:40:58 UTC ++++ test/test-libevdev-events.c +@@ -1057,7 +1057,7 @@ START_TEST(test_syn_delta_late_sync) + } while (rc >= 0); + + /* force enough events to trigger a SYN_DROPPED */ +- for (i = 0; i < 100; i++) { ++ for (i = 0; i < 200; i++) { + uinput_device_event(uidev, EV_ABS, ABS_X, 100 + i); + uinput_device_event(uidev, EV_ABS, ABS_Y, 500 + i); + uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_X, 100 + i); +@@ -1152,7 +1152,7 @@ START_TEST(test_syn_delta_late_sync) + } while (rc >= 0); + + /* force enough events to trigger a SYN_DROPPED */ +- for (i = 0; i < 100; i++) { ++ for (i = 0; i < 200; i++) { + uinput_device_event(uidev, EV_ABS, ABS_X, 100 + i); + uinput_device_event(uidev, EV_ABS, ABS_Y, 500 + i); + uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_X, 100 + i); Index: devel/libevdev/files/patch-test_test-libevdev-init.c =================================================================== --- devel/libevdev/files/patch-test_test-libevdev-init.c +++ devel/libevdev/files/patch-test_test-libevdev-init.c @@ -0,0 +1,11 @@ +--- test/test-libevdev-init.c.orig 2016-04-28 00:40:58 UTC ++++ test/test-libevdev-init.c +@@ -490,7 +490,7 @@ START_TEST(test_set_clock_id) + rc = libevdev_set_clock_id(dev, CLOCK_MONOTONIC); + ck_assert_int_eq(rc, 0); + +- rc = libevdev_set_clock_id(dev, CLOCK_MONOTONIC_RAW); ++ rc = libevdev_set_clock_id(dev, CLOCK_MONOTONIC_FAST); + ck_assert_int_eq(rc, -EINVAL); + + uinput_device_free(uidev); Index: devel/libevdev/files/patch-test_test-main.c =================================================================== --- devel/libevdev/files/patch-test_test-main.c +++ devel/libevdev/files/patch-test_test-main.c @@ -0,0 +1,26 @@ +--- test/test-main.c.orig 2015-06-10 04:49:41 UTC ++++ test/test-main.c +@@ -41,6 +41,7 @@ extern Suite *uinput_suite(void); + static int + is_debugger_attached(void) + { ++#if defined (linux) + int status; + int rc; + int pid = fork(); +@@ -64,6 +65,15 @@ is_debugger_attached(void) + } + + return rc; ++#else ++ /* ++ * Skip useless gdb test as setting CK_FORK environment variable in ++ * absence of attached debugger gives no harm to user. ++ * Moreover this test is broken on most nonlinux systems, look at ++ * discussion here: http://stackoverflow.com/questions/3596781/ ++ */ ++ return 1; ++#endif + } + + int main(int argc, char **argv) Index: devel/libevdev/files/patch-tools_mouse-dpi-tool.c =================================================================== --- devel/libevdev/files/patch-tools_mouse-dpi-tool.c +++ devel/libevdev/files/patch-tools_mouse-dpi-tool.c @@ -0,0 +1,59 @@ +--- tools/mouse-dpi-tool.c.orig 2016-04-28 00:40:58 UTC ++++ tools/mouse-dpi-tool.c +@@ -26,7 +26,6 @@ + #endif + + #include +-#include + #include + #include + #include +@@ -47,9 +46,18 @@ struct measurements { + uint64_t us; + }; + ++ ++static volatile int sigint_catched = 0; ++static void ++sigint_handler(int signo) ++{ ++ if (signo == SIGINT) ++ sigint_catched = 1; ++} ++ + static int + usage(void) { +- printf("Usage: %s /dev/input/event0\n", program_invocation_short_name); ++ printf("Usage: %s /dev/input/event0\n", getprogname()); + printf("\n"); + printf("This tool reads relative events from the kernel and calculates\n" + "the distance covered and maximum frequency of the incoming events.\n" +@@ -128,24 +136,18 @@ handle_event(struct measurements *m, con + + static int + mainloop(struct libevdev *dev, struct measurements *m) { +- struct pollfd fds[2]; +- sigset_t mask; ++ struct pollfd fds[1]; + + fds[0].fd = libevdev_get_fd(dev); + fds[0].events = POLLIN; + +- sigemptyset(&mask); +- sigaddset(&mask, SIGINT); +- fds[1].fd = signalfd(-1, &mask, SFD_NONBLOCK); +- fds[1].events = POLLIN; +- +- sigprocmask(SIG_BLOCK, &mask, NULL); ++ signal(SIGINT, sigint_handler); + +- while (poll(fds, 2, -1)) { ++ while (poll(fds, 1, -1)) { + struct input_event ev; + int rc; + +- if (fds[1].revents) ++ if (sigint_catched) + break; + + do { Index: devel/libevdev/files/patch-tools_touchpad-edge-detector.c =================================================================== --- devel/libevdev/files/patch-tools_touchpad-edge-detector.c +++ devel/libevdev/files/patch-tools_touchpad-edge-detector.c @@ -0,0 +1,63 @@ +--- tools/touchpad-edge-detector.c.orig 2016-04-28 00:40:58 UTC ++++ tools/touchpad-edge-detector.c +@@ -26,7 +26,6 @@ + #endif + + #include +-#include + #include + #include + #include +@@ -43,7 +42,7 @@ + + static int + usage(void) { +- printf("Usage: %s /dev/input/event0\n", program_invocation_short_name); ++ printf("Usage: %s /dev/input/event0\n", getprogname()); + printf("\n"); + printf("This tool reads the touchpad events from the kernel and calculates\n " + "the minimum and maximum for the x and y coordinates, respectively.\n"); +@@ -54,6 +53,14 @@ struct dimensions { + int top, bottom, left, right; + }; + ++static volatile int sigint_catched = 0; ++static void ++sigint_handler(int signo) ++{ ++ if (signo == SIGINT) ++ sigint_catched = 1; ++} ++ + static int + print_current_values(const struct dimensions *d) + { +@@ -99,24 +106,18 @@ handle_event(struct dimensions *d, const + + static int + mainloop(struct libevdev *dev, struct dimensions *dim) { +- struct pollfd fds[2]; +- sigset_t mask; ++ struct pollfd fds[1]; + + fds[0].fd = libevdev_get_fd(dev); + fds[0].events = POLLIN; + +- sigemptyset(&mask); +- sigaddset(&mask, SIGINT); +- fds[1].fd = signalfd(-1, &mask, SFD_NONBLOCK); +- fds[1].events = POLLIN; +- +- sigprocmask(SIG_BLOCK, &mask, NULL); ++ signal(SIGINT, sigint_handler); + +- while (poll(fds, 2, -1)) { ++ while (poll(fds, 1, -1)) { + struct input_event ev; + int rc; + +- if (fds[1].revents) ++ if (sigint_catched) + break; + + do { Index: devel/libevdev/pkg-plist =================================================================== --- devel/libevdev/pkg-plist +++ devel/libevdev/pkg-plist @@ -1,8 +1,11 @@ +bin/libevdev-tweak-device +bin/mouse-dpi-tool +bin/touchpad-edge-detector include/libevdev-1.0/libevdev/libevdev-uinput.h include/libevdev-1.0/libevdev/libevdev.h lib/libevdev.a lib/libevdev.so lib/libevdev.so.2 -lib/libevdev.so.2.1.10 +lib/libevdev.so.2.1.14 libdata/pkgconfig/libevdev.pc man/man3/libevdev.3.gz Index: devel/libmtdev/Makefile =================================================================== --- devel/libmtdev/Makefile +++ devel/libmtdev/Makefile @@ -12,12 +12,8 @@ LICENSE= MIT LICENSE_FILE= ${WRKSRC}/COPYING -BUILD_DEPENDS= v4l_compat>=1.0.20110603:multimedia/v4l_compat -RUN_DEPENDS= v4l_compat>=1.0.20110603:multimedia/v4l_compat - -USES= libtool pathfix tar:bz2 +USES= libtool pathfix tar:bz2 evdev GNU_CONFIGURE= yes -CPPFLAGS+= -I${LOCALBASE}/include # v4l_compat INSTALL_TARGET= install-strip USE_LDCONFIG= yes Index: devel/libmtdev/files/patch-test-mtdev-test.c =================================================================== --- devel/libmtdev/files/patch-test-mtdev-test.c +++ devel/libmtdev/files/patch-test-mtdev-test.c @@ -0,0 +1,16 @@ +--- test/mtdev-test.c.orig 2014-02-28 22:48:23.000000000 +0400 ++++ test/mtdev-test.c 2015-04-03 02:57:56.890923000 +0300 +@@ -28,11 +28,12 @@ + + #include + #include ++#include + #include + #include + + /* year-proof millisecond event time */ +-typedef __u64 mstime_t; ++typedef uint64_t mstime_t; + + static int use_event(const struct input_event *ev) + { Index: devel/py-evdev/Makefile =================================================================== --- devel/py-evdev/Makefile +++ devel/py-evdev/Makefile @@ -1,7 +1,7 @@ # $FreeBSD$ PORTNAME= evdev -PORTVERSION= 0.5.0 +PORTVERSION= 0.6.1 CATEGORIES= devel python MASTER_SITES= CHEESESHOP PKGNAMEPREFIX= ${PYTHON_PKGNAMEPREFIX} @@ -12,15 +12,18 @@ LICENSE= BSD3CLAUSE LICENSE_FILE= ${WRKSRC}/LICENSE -BUILD_DEPENDS= v4l_compat>=1.0.20110603:multimedia/v4l_compat - -USES= python +USES= python evdev USE_PYTHON= autoplist distutils -CPPFLAGS+= -I${LOCALBASE}/include # v4l_compat -post-patch: - @${REINPLACE_CMD} -e '/header/s,/usr,${LOCALBASE},' \ - ${WRKSRC}/${PYSETUP} +EVDEV_INCLUDES= ${LOCALBASE}/include + +PYDISTUTILS_BUILD_TARGET= build_ext +PYDISTUTILS_BUILDARGS+= --include-dirs ${EVDEV_INCLUDES}/ \ + --evdev-headers ${EVDEV_INCLUDES}/linux/input.h:${EVDEV_INCLUDES}/linux/input-event-codes.h + +# Supply install target with evdev headers path +PYDISTUTILS_INSTALL_TARGET= ${PYDISTUTILS_BUILD_TARGET} \ + ${PYDISTUTILS_BUILDARGS} install post-install: ${FIND} ${STAGEDIR}${PYTHONPREFIX_SITELIBDIR} \ Index: devel/py-evdev/distinfo =================================================================== --- devel/py-evdev/distinfo +++ devel/py-evdev/distinfo @@ -1,2 +1,3 @@ -SHA256 (evdev-0.5.0.tar.gz) = 509f0f6ce5a12315fcad0b7f9b41cbdfc5c5f49a7cecdd6a88ce5c1d04f6827c -SIZE (evdev-0.5.0.tar.gz) = 23931 +TIMESTAMP = 1469963738 +SHA256 (evdev-0.6.1.tar.gz) = 67b3c71461e5ce191a34cd4ec17f6b3d59e66f6013f98f84c2fba817b8738a3b +SIZE (evdev-0.6.1.tar.gz) = 22034 Index: multimedia/v4l_compat/Makefile =================================================================== --- multimedia/v4l_compat/Makefile +++ multimedia/v4l_compat/Makefile @@ -8,14 +8,15 @@ NO_BUILD= yes NO_ARCH= yes +RUN_DEPENDS= ${LOCALBASE}/include/linux/input.h:devel/libevdev-headers + MASTERDIR= ${.CURDIR}/../../multimedia/libv4l EXTRADIR= ${WRKSRC}/../linux DESCR= ${.CURDIR}/pkg-descr PLIST= ${.CURDIR}/pkg-plist LIBV4L_SLAVE= compat -BASE_HEADERS= input.h uinput.h ivtv.h v4l2-controls.h \ - v4l2-common.h videodev2.h +BASE_HEADERS= ivtv.h v4l2-controls.h v4l2-common.h videodev2.h DVB_HEADERS= audio.h dmx.h frontend.h video.h EXTRA_HEADERS= ca.h osd.h version.h Index: multimedia/v4l_compat/pkg-plist =================================================================== --- multimedia/v4l_compat/pkg-plist +++ multimedia/v4l_compat/pkg-plist @@ -5,9 +5,7 @@ include/linux/dvb/osd.h include/linux/dvb/version.h include/linux/dvb/video.h -include/linux/input.h include/linux/ivtv.h -include/linux/uinput.h include/linux/v4l2-common.h include/linux/v4l2-controls.h include/linux/videodev.h Index: multimedia/webcamd/Makefile =================================================================== --- multimedia/webcamd/Makefile +++ multimedia/webcamd/Makefile @@ -2,7 +2,7 @@ # $FreeBSD$ PORTNAME= webcamd -PORTVERSION= 4.2.0.9 +PORTVERSION= 4.8.0.4 CATEGORIES= multimedia MASTER_SITES= http://www.selasky.org/hans_petter/distfiles/ \ http://home.selasky.org:8192/distfiles/ @@ -21,7 +21,7 @@ SUB_FILES= webcamd.conf USE_LDCONFIG= yes -OPTIONS_DEFINE= CUSE DEBUG HAL VT_CLIENT VT_SERVER DVB INPUT RADIO WEBCAM +OPTIONS_DEFINE= CUSE DEBUG HAL VT_CLIENT VT_SERVER DVB INPUT KEYBOARD MOUSE RADIO WEBCAM OPTIONS_DEFAULT=DVB HAL INPUT RADIO WEBCAM .if exists(/usr/lib/libcuse.so) @@ -59,6 +59,12 @@ INPUT_DESC= Build with USB input support (tablet, joystick, HID, IR, ...) INPUT_MAKE_ARGS= HAVE_INPUT_DRV="YES" +KEYBOARD_DESC= Build with USB keyboard support +KEYBOARD_MAKE_ARGS= HAVE_KEYBOARD_DRV="YES" + +MOUSE_DESC= Build with USB mouse support +MOUSE_MAKE_ARGS= HAVE_MOUSE_DRV="YES" + RADIO_DESC= Build with USB radio support RADIO_MAKE_ARGS= HAVE_RADIO_DRV="YES" Index: multimedia/webcamd/distinfo =================================================================== --- multimedia/webcamd/distinfo +++ multimedia/webcamd/distinfo @@ -1,2 +1,3 @@ -SHA256 (webcamd-4.2.0.9.tar.bz2) = b02958db281be2347b17db8a81604c49eb43802a5fa3a771cccc5904c9e36539 -SIZE (webcamd-4.2.0.9.tar.bz2) = 10983753 +TIMESTAMP = 1472287897 +SHA256 (webcamd-4.8.0.4.tar.bz2) = cab0166ef4df4e00ef775e4e527b1dee6e6b100c6ad002df72663e7ae8380d10 +SIZE (webcamd-4.8.0.4.tar.bz2) = 11700148 Index: x11-drivers/xf86-input-evdev/Makefile =================================================================== --- x11-drivers/xf86-input-evdev/Makefile +++ x11-drivers/xf86-input-evdev/Makefile @@ -1,8 +1,7 @@ # $FreeBSD$ PORTNAME= xf86-input-evdev -PORTVERSION= 2.9.2 -PORTREVISION= 1 +PORTVERSION= 2.10.3 CATEGORIES= x11-drivers MAINTAINER= x11@FreeBSD.org @@ -11,12 +10,10 @@ LICENSE= MIT # various styles LICENSE_FILE= ${WRKSRC}/COPYING -BUILD_DEPENDS= v4l_compat>=1.0.20110603:multimedia/v4l_compat LIB_DEPENDS= libevdev.so:devel/libevdev -RUN_DEPENDS= webcamd>=3.1.0.1:multimedia/webcamd XORG_CAT= driver -USES= pathfix +USES= pathfix evdev CONFIGURE_ENV= UDEV_CFLAGS=" " UDEV_LIBS=" " INSTALL_TARGET= install-strip Index: x11-drivers/xf86-input-evdev/distinfo =================================================================== --- x11-drivers/xf86-input-evdev/distinfo +++ x11-drivers/xf86-input-evdev/distinfo @@ -1,2 +1,3 @@ -SHA256 (xorg/driver/xf86-input-evdev-2.9.2.tar.bz2) = 792329b531afc6928ccda94e4b51a5520d4ddf8ef9a00890a5d0d31898acefec -SIZE (xorg/driver/xf86-input-evdev-2.9.2.tar.bz2) = 387095 +TIMESTAMP = 1467542089 +SHA256 (xorg/driver/xf86-input-evdev-2.10.3.tar.bz2) = 5aa21ba4be8df927e5676a99c7f4f0343abc089f5451b7e73e39536f29b332a2 +SIZE (xorg/driver/xf86-input-evdev-2.10.3.tar.bz2) = 404476 Index: x11-drivers/xf86-input-evdev/pkg-plist =================================================================== --- x11-drivers/xf86-input-evdev/pkg-plist +++ x11-drivers/xf86-input-evdev/pkg-plist @@ -2,3 +2,4 @@ lib/xorg/modules/input/evdev_drv.so libdata/pkgconfig/xorg-evdev.pc man/man4/evdev.4x.gz +share/X11/xorg.conf.d/10-evdev.conf Index: x11-drivers/xf86-input-synaptics/Makefile =================================================================== --- x11-drivers/xf86-input-synaptics/Makefile +++ x11-drivers/xf86-input-synaptics/Makefile @@ -1,17 +1,25 @@ # $FreeBSD$ PORTNAME= xf86-input-synaptics -PORTVERSION= 1.8.2 -PORTREVISION= 1 +PORTVERSION= 1.8.99.1 CATEGORIES= x11-drivers MAINTAINER= x11@FreeBSD.org COMMENT= X.Org synaptics input driver -CONFLICTS= synaptics-[0-9]* +LICENSE= MIT +LICENSE_FILE= ${WRKSRC}/COPYING USES= pathfix USE_XORG= x11 xtst XORG_CAT= driver +INSTALL_TARGET= install-strip + +.if exists(/usr/include/dev/evdev/input.h) +CONFIGURE_ENV+= BUILD_EVENTCOMM=yes +USES+= evdev +LIB_DEPENDS+= libevdev.so:devel/libevdev +.endif + .include Index: x11-drivers/xf86-input-synaptics/distinfo =================================================================== --- x11-drivers/xf86-input-synaptics/distinfo +++ x11-drivers/xf86-input-synaptics/distinfo @@ -1,2 +1,3 @@ -SHA256 (xorg/driver/xf86-input-synaptics-1.8.2.tar.bz2) = 7b0e164ebd02a680e0c695955e783059f37edb0c2656398e0a972adc8e698c80 -SIZE (xorg/driver/xf86-input-synaptics-1.8.2.tar.bz2) = 484261 +TIMESTAMP = 1470662930 +SHA256 (xorg/driver/xf86-input-synaptics-1.8.99.1.tar.bz2) = 4c895339fa10c4f97b27ab62d974cae2a96e19ae8d52f80ef0fa5c202c67ebaa +SIZE (xorg/driver/xf86-input-synaptics-1.8.99.1.tar.bz2) = 500978 Index: x11-drivers/xf86-input-synaptics/files/patch-src_eventcomm.h =================================================================== --- x11-drivers/xf86-input-synaptics/files/patch-src_eventcomm.h +++ x11-drivers/xf86-input-synaptics/files/patch-src_eventcomm.h @@ -0,0 +1,18 @@ +--- src/eventcomm.h.orig 2015-11-24 23:47:05 UTC ++++ src/eventcomm.h +@@ -30,7 +30,15 @@ + #include + + #include ++#ifdef __linux__ + #include ++#else ++#undef BUS_NONE ++#undef BUS_PCI ++#undef BUS_SBUS ++#undef BUS_PLATFORM ++#undef BUS_last ++#endif + #include + #include "synproto.h" + Index: x11-drivers/xf86-input-synaptics/files/patch-src_eventcomm.c =================================================================== --- x11-drivers/xf86-input-synaptics/files/patch-src_eventcomm.c +++ x11-drivers/xf86-input-synaptics/files/patch-src_eventcomm.c @@ -0,0 +1,18 @@ +--- src/eventcomm.c.orig 2016-04-26 23:29:23 UTC ++++ src/eventcomm.c +@@ -421,10 +421,15 @@ event_get_abs(struct libevdev *evdev, in + /* We dont trust a zero fuzz as it probably is just a lazy value */ + if (fuzz && abs->fuzz > 0) + *fuzz = abs->fuzz; ++#ifdef __linux__ + #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30) + if (res) + *res = abs->resolution; + #endif ++#elif defined(__FreeBSD__) ++ if (res) ++ *res = abs->resolution; ++#endif + + return 0; + } Index: x11-drivers/xf86-input-wacom/Makefile =================================================================== --- x11-drivers/xf86-input-wacom/Makefile +++ x11-drivers/xf86-input-wacom/Makefile @@ -10,10 +10,9 @@ LICENSE= GPLv2+ -BUILD_DEPENDS= v4l_compat>=1.0.20110603:multimedia/v4l_compat RUN_DEPENDS= webcamd>=3.1.0.1:multimedia/webcamd -USES= tar:bzip2 pathfix pkgconfig libtool +USES= tar:bzip2 pathfix pkgconfig libtool evdev USE_XORG= xrandr xinerama XORG_CAT= driver USE_RC_SUBR= wacom Index: x11-drivers/xf86-input-wacom/files/patch-src-wcmValidateDevice.c =================================================================== --- x11-drivers/xf86-input-wacom/files/patch-src-wcmValidateDevice.c +++ x11-drivers/xf86-input-wacom/files/patch-src-wcmValidateDevice.c @@ -29,6 +29,15 @@ if (match) xf86Msg(X_WARNING, "%s: device file already in use by %s. " "Ignoring.\n", pInfo->name, pDevices->name); +@@ -123,7 +124,7 @@ ret: + static struct + { + const char* type; +- __u16 tool[3]; /* tool array is terminated by 0 */ ++ uint16_t tool[3]; /* tool array is terminated by 0 */ + } wcmType [] = + { + { "stylus", { BTN_TOOL_PEN, 0 } }, @@ -205,6 +206,10 @@ int wcmDeviceTypeKeys(InputInfoPtr pInfo case 0x314: /* Intuos Pro S */ case 0x315: /* Intuos Pro M */ Index: x11-servers/xorg-server/files/patch-config_devd.c =================================================================== --- x11-servers/xorg-server/files/patch-config_devd.c +++ x11-servers/xorg-server/files/patch-config_devd.c @@ -1,6 +1,6 @@ ---- config/devd.c.orig 2015-05-19 19:41:49 UTC -+++ config/devd.c -@@ -0,0 +1,531 @@ +--- /dev/null 2016-08-20 16:05:18.000000000 +0300 ++++ config/devd.c 2016-08-20 16:09:28.076064000 +0300 +@@ -0,0 +1,892 @@ +/* + * Copyright (c) 2012 Baptiste Daroussin + * Copyright (c) 2013, 2014 Alex Kozlov @@ -33,20 +33,27 @@ +#include +#endif + -+#include ++#include ++#include +#include ++#include +#include +#include +#include +#include + +#include ++#include +#include +#include ++#include ++#include +#include +#include +#include ++#include +#include ++#include + +#include "input.h" +#include "inputstr.h" @@ -56,260 +63,611 @@ + +#define DEVD_SOCK_PATH "/var/run/devd.pipe" + -+#define DEVD_EVENT_ADD '+' -+#define DEVD_EVENT_REMOVE '-' -+ -+#define RECONNECT_DELAY 5 * 1000 ++#define RECONNECT_DELAY (5 * 1000) + +static int sock_devd; -+static bool is_console_kbd = false; +static bool is_kbdmux = false; ++static bool is_kernel_evdev = false; +OsTimerPtr rtimer; + +struct hw_type { + const char *driver; + int flag; + const char *xdriver; ++ const char *sysctldesc; +}; + -+static struct hw_type hw_types[] = { -+ { "ukbd", ATTR_KEYBOARD, "kbd" }, -+ { "atkbd", ATTR_KEYBOARD, "kbd" }, -+ { "kbdmux", ATTR_KEYBOARD, "kbd" }, -+ { "sysmouse", ATTR_POINTER, "mouse" }, -+ { "ums", ATTR_POINTER, "mouse" }, -+ { "psm", ATTR_POINTER, "mouse" }, -+ { "vboxguest", ATTR_POINTER, "vboxmouse" }, -+ { "joy", ATTR_JOYSTICK, NULL }, -+ { "atp", ATTR_TOUCHPAD, NULL }, -+ { "uep", ATTR_TOUCHSCREEN, NULL }, -+ { NULL, -1, NULL }, ++static const struct hw_type hw_types0[] = { ++ { _PATH_DEV "sysmouse", ATTR_POINTER, "mouse", NULL }, ++ { _PATH_DEV "vboxguest", ATTR_POINTER, "vboxmouse", NULL }, ++ { NULL, 0, NULL, NULL }, +}; + -+static bool -+sysctl_exists(const struct hw_type *device, int unit, -+ char *devname, size_t devname_len) ++static const struct hw_type hw_types1[] = { ++ { _PATH_DEV "ukbd%d", ATTR_KEYBOARD, "kbd", "ukbd" }, ++ { _PATH_DEV "atkbd%d", ATTR_KEYBOARD, "kbd", "atkbd" }, ++ { _PATH_DEV "kbdmux%d", ATTR_KEYBOARD, "kbd", NULL }, ++ { _PATH_DEV "ums%d", ATTR_POINTER, "mouse", "ums" }, ++ { _PATH_DEV "psm%d", ATTR_POINTER, "mouse", "psm" }, ++ { _PATH_DEV "joy%d", ATTR_JOYSTICK, "mouse", "joy" }, ++ { _PATH_DEV "atp%d", ATTR_TOUCHPAD, "mouse", "atp" }, ++ { _PATH_DEV "wsp%d", ATTR_TOUCHPAD, "mouse", "wsp" }, ++ { _PATH_DEV "uep%d", ATTR_TOUCHSCREEN, "mouse", "uep" }, ++ { _PATH_DEV "input/event%d", 0, "evdev", NULL }, ++ { NULL, 0, NULL, NULL }, ++}; ++ ++/* like basename() but returns a pointer to incoming string */ ++static char * ++bname(const char *path) +{ -+ char sysctlname[PATH_MAX]; -+ size_t len; -+ int ret; ++ char *slash = NULL; + -+ if (device == NULL || device->driver == NULL) -+ return false; ++ if (path != NULL) ++ slash = strrchr(path, '/'); ++ return (slash == NULL) ? (char *)path : slash + 1; ++} + -+ /* Check if a sysctl exists. */ -+ snprintf(sysctlname, sizeof(sysctlname), "dev.%s.%i.%%desc", -+ device->driver, unit); -+ ret = sysctlbyname(sysctlname, NULL, &len, NULL, 0); ++struct dev_entry { ++ SLIST_ENTRY(dev_entry) next; ++ char name[]; ++}; ++SLIST_HEAD(dev_list, dev_entry); + -+ if (ret == 0 && len > 0) { -+ snprintf(devname, devname_len, "%s%i", device->driver, unit); -+ return true; ++#define dev_list_init(dev_list) SLIST_INIT(dev_list) ++#define dev_list_empty(dev_list) SLIST_EMPTY(dev_list) ++ ++static void ++dev_list_insert(struct dev_list *devs, const char *dev_name) ++{ ++ struct dev_entry *dev; ++ ++ dev = malloc(offsetof(struct dev_entry, name) + strlen(dev_name) + 1); ++ if (dev != NULL) { ++ strcpy(dev->name, dev_name); ++ SLIST_INSERT_HEAD(devs, dev, next); + } ++} + -+ return false; ++static void ++dev_list_destroy(struct dev_list *devs) ++{ ++ struct dev_entry *dev; ++ ++ while (!SLIST_EMPTY(devs)) { ++ dev = SLIST_FIRST(devs); ++ SLIST_REMOVE_HEAD(devs, next); ++ free(dev); ++ } +} + +static bool -+devpath_exists(const struct hw_type *device, -+ char *devname, size_t devname_len) ++dev_list_search(struct dev_list *devs, const char *dev_name) +{ -+ char *devpath; -+ struct stat st; -+ int ret; ++ struct dev_entry *dev; + -+ if (device == NULL || device->driver == NULL) -+ return false; ++ if (dev_name != NULL) ++ SLIST_FOREACH(dev, devs, next) ++ if (strcmp(dev_name, dev->name) == 0) ++ return true; ++ return false; ++} + -+ /* Check if /dev/$driver exists. */ -+ asprintf(&devpath, "/dev/%s", device->driver); -+ if (devpath == NULL) -+ return false; ++/* Some definitions from linux/input.h */ ++struct input_id { ++ uint16_t bustype; ++ uint16_t vendor; ++ uint16_t product; ++ uint16_t version; ++}; + -+ ret = stat(devpath, &st); -+ free(devpath); ++#define EVIOCGBIT(ev,len) _IOC(IOC_OUT, 'E', 0x20 + (ev), len) ++#define EVIOCGID _IOR('E', 0x02, struct input_id) ++#define EVIOCGNAME(len) _IOC(IOC_OUT, 'E', 0x06, len) ++#define EVIOCGPHYS(len) _IOC(IOC_OUT, 'E', 0x07, len) ++ ++#define EV_KEY 0x01 ++#define EV_REL 0x02 ++#define EV_ABS 0x03 ++#define BTN_MISC 0x100 ++#define BTN_LEFT 0x110 ++#define BTN_RIGHT 0x111 ++#define BTN_MIDDLE 0x112 ++#define BTN_JOYSTICK 0x120 ++#define BTN_TOOL_PEN 0x140 ++#define BTN_TOOL_FINGER 0x145 ++#define BTN_TOUCH 0x14a ++#define BTN_STYLUS 0x14b ++#define BTN_STYLUS2 0x14c ++#define KEY_MAX 0x2ff ++#define KEY_CNT (KEY_MAX+1) ++#define REL_X 0x00 ++#define REL_Y 0x01 ++#define REL_MAX 0x0f ++#define REL_CNT (REL_MAX+1) ++#define ABS_X 0x00 ++#define ABS_Y 0x01 ++#define ABS_PRESSURE 0x18 ++#define ABS_MT_SLOT 0x2f ++#define ABS_MAX 0x3f ++#define ABS_CNT (ABS_MAX+1) ++ ++#define LONG_BITS (sizeof(long) * 8) ++#define NLONGS(x) (((x) + LONG_BITS - 1) / LONG_BITS) + -+ if (ret == 0) { -+ strncpy(devname, device->driver, devname_len); -+ return true; -+ } ++static inline bool ++bit_is_set(const unsigned long *array, int bit) ++{ ++ return !!(array[bit / LONG_BITS] & (1LL << (bit % LONG_BITS))); ++} ++ ++static inline bool ++bit_find(const unsigned long *array, int start, int stop) ++{ ++ int i; ++ ++ for (i = start; i < stop; i++) ++ if (bit_is_set(array, i)) ++ return true; + + return false; +} + -+static char * -+sysctl_get_str(const char *sysctlname) ++/* ++ * Event device type detection routine. ++ * Derived from EvdevProbe() function of xf86-input-evdev driver ++ */ ++static void ++get_evdev_attrs(InputAttributes *attrs, const char *devicename) +{ -+ char *dest = NULL; -+ size_t len; ++ int fd, flags; ++ bool has_keys, has_buttons, has_lmr; ++ bool has_rel_axes, has_abs_axes, has_mt; ++ unsigned long key_bits[NLONGS(KEY_CNT)]; ++ unsigned long rel_bits[NLONGS(REL_CNT)]; ++ unsigned long abs_bits[NLONGS(ABS_CNT)]; ++ struct input_id id; ++ char name[80]; ++ char *walk; + -+ if (sysctlname == NULL) -+ return NULL; ++ flags = 0; + -+ if (sysctlbyname(sysctlname, NULL, &len, NULL, 0) == 0) { -+ dest = malloc(len + 1); -+ if (dest) { -+ if (sysctlbyname(sysctlname, dest, &len, NULL, 0) == 0) -+ dest[len] = '\0'; -+ else { -+ free(dest); -+ dest = NULL; ++ fd = open(devicename, O_RDONLY | O_CLOEXEC); ++ if (fd < 0) ++ goto out; ++ if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), name) < 0 || ++ ioctl(fd, EVIOCGID, &id) < 0 || ++ ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bits)), rel_bits) < 0 || ++ ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits) < 0 || ++ ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)), key_bits) < 0) { ++ close(fd); ++ goto out; ++ } ++ close(fd); ++ ++ if ((walk = strchr(name, ',')) != NULL) ++ *walk = '\0'; /* strip name */ ++ ++ attrs->product = strdup(name); ++ asprintf(&attrs->usb_id, "%04x:%04x", id.vendor, id.product); ++ asprintf(&attrs->vendor, "0x%04x", id.vendor); ++ ++ has_keys = bit_find(key_bits, 0, BTN_MISC); ++ has_buttons = bit_find(key_bits, BTN_MISC, BTN_JOYSTICK); ++ has_lmr = bit_find(key_bits, BTN_LEFT, BTN_MIDDLE + 1); ++ has_rel_axes = bit_find(rel_bits, 0, REL_CNT); ++ has_abs_axes = bit_find(abs_bits, 0, ABS_CNT); ++ has_mt = bit_find(abs_bits, ABS_MT_SLOT, ABS_CNT); ++ ++ if (has_abs_axes) { ++ if (has_mt) { ++ if (!has_buttons) { ++ /* ++ * XXX: I'm not sure that joystick detection is ++ * done right. xf86-evdev does not support them. ++ */ ++ if (bit_is_set(key_bits, BTN_JOYSTICK)) { ++ flags = ATTR_JOYSTICK; ++ goto out; ++ } else { ++ has_buttons = true; ++ } ++ } ++ } ++ ++ if (bit_is_set(abs_bits, ABS_X) && ++ bit_is_set(abs_bits, ABS_Y)) { ++ if (bit_is_set(key_bits, BTN_TOOL_PEN) || ++ bit_is_set(key_bits, BTN_STYLUS) || ++ bit_is_set(key_bits, BTN_STYLUS2)) { ++ flags = ATTR_TABLET; ++ goto out; ++ } else if (bit_is_set(abs_bits, ABS_PRESSURE) || ++ bit_is_set(key_bits, BTN_TOUCH)) { ++ if (has_lmr || ++ bit_is_set(key_bits, BTN_TOOL_FINGER)) { ++ flags = ATTR_TOUCHPAD; ++ } else { ++ flags = ATTR_TOUCHSCREEN; ++ } ++ goto out; ++ } else if (!(bit_is_set(rel_bits, REL_X) && ++ bit_is_set(rel_bits, REL_Y)) && ++ has_lmr) { ++ /* some touchscreens use BTN_LEFT rather than BTN_TOUCH */ ++ flags = ATTR_TOUCHSCREEN; ++ goto out; + } + } + } + -+ return dest; ++ if (has_keys) ++ flags = ATTR_KEYBOARD; ++ else if (has_rel_axes || has_abs_axes || has_buttons) ++ flags = ATTR_POINTER; ++ ++out: ++ attrs->flags |= flags; +} + ++/* Returns list of devices supporting evdev protocol */ +static void -+device_added(const char *devname) ++get_evdev_blacklist(struct dev_list *devs) +{ -+ char path[PATH_MAX]; -+ char sysctlname[PATH_MAX]; -+ char *vendor; -+ char *product = NULL; -+ char *config_info = NULL; -+ char *walk; -+ InputOption *options = NULL; -+ InputAttributes attrs = { }; -+ DeviceIntPtr dev = NULL; -+ int i; ++ struct dirent *entry; ++ DIR *dp; ++ static const char ev_dir[] = _PATH_DEV "input"; ++#define EV_LEN nitems(ev_dir) ++ char path[PATH_MAX + 1]; ++ char phys[80]; + int fd; + -+ for (i = 0; hw_types[i].driver != NULL; i++) { -+ size_t len; ++ snprintf(path, sizeof(path), "%s/", ev_dir); ++ if ((dp = opendir(ev_dir)) == NULL) ++ return; + -+ len = strlen(hw_types[i].driver); -+ if (strcmp(devname, hw_types[i].driver) == 0 || -+ (strncmp(devname, hw_types[i].driver, len) == 0 && -+ isnumber(*(devname + len)))) { -+ attrs.flags |= hw_types[i].flag; -+ break; -+ } ++ while ((entry = readdir(dp)) != NULL) { ++ if (entry->d_type != DT_CHR) ++ continue; ++ if (strncmp(entry->d_name, "event", 5) != 0) ++ continue; ++ strlcpy(path + EV_LEN, entry->d_name, sizeof(path) - EV_LEN); ++ fd = open(path, O_RDONLY | O_CLOEXEC); ++ if (fd < 0) ++ continue; ++ /* XXX: Should uinput- and cuse-backed devices be skipped? */ ++ if (ioctl(fd, EVIOCGPHYS(sizeof(phys) - 1), phys) == 0 && ++ phys[0] != 0) ++ dev_list_insert(devs, bname(phys)); ++ close(fd); + } ++ closedir(dp); ++ return; ++} + -+ if (hw_types[i].driver == NULL || hw_types[i].xdriver == NULL) { -+ LogMessage(X_INFO, "config/devd: ignoring device %s\n", -+ devname); -+ return; ++static void ++get_usb_id(char **pptr, int fd) ++{ ++ unsigned short vendor; ++ unsigned short product; ++ unsigned int speed; ++#define WEBCAMD_IOCTL_GET_USB_VENDOR_ID _IOR('q', 250, unsigned short) ++#define WEBCAMD_IOCTL_GET_USB_PRODUCT_ID _IOR('q', 251, unsigned short) ++#define WEBCAMD_IOCTL_GET_USB_SPEED _IOR('q', 252, unsigned int) ++ if (ioctl(fd, WEBCAMD_IOCTL_GET_USB_VENDOR_ID, &vendor) == 0 && ++ ioctl(fd, WEBCAMD_IOCTL_GET_USB_PRODUCT_ID, &product) == 0 && ++ ioctl(fd, WEBCAMD_IOCTL_GET_USB_SPEED, &speed) == 0) { ++ if (asprintf(pptr, "%04x:%04x", vendor, product) == -1) ++ *pptr = NULL; + } ++} + -+ /* Skip keyboard devices if kbdmux is enabled */ -+ if (is_kbdmux && is_console_kbd && hw_types[i].flag & ATTR_KEYBOARD) { -+ LogMessage(X_INFO, "config/devd: kbdmux is enabled, ignoring device %s\n", -+ devname); -+ return; -+ } ++static char * ++get_prop_value(const char *buf, const char *prop, size_t *len) ++{ ++ char *prop_pos, *val_pos, *walk; ++ size_t prop_len; + -+ snprintf(path, sizeof(path), "/dev/%s", devname); ++ prop_len = strlen(prop); ++ prop_pos = strstr(buf, prop); ++ if (prop_pos == NULL || ++ (prop_pos != buf && prop_pos[-1] != ' ') || ++ prop_pos[prop_len] != '=') ++ return (NULL); ++ ++ val_pos = prop_pos + prop_len + 1; ++ if ((walk = strchr(val_pos, ' ')) == NULL) ++ *len = strlen(val_pos); ++ else ++ *len = walk - val_pos; ++ return (val_pos); ++} + -+ options = input_option_new(NULL, "_source", "server/devd"); -+ if (!options) ++static void ++get_sysctl_attrs(InputAttributes *attrs, const char* driver, int unit) ++{ ++ char mib[32], name[80], pnpinfo[1024], *pnp_id, *walk; ++ const char *vendorstr, *prodstr, *devicestr; ++ size_t len, vendorlen, prodlen, devicelen, pnplen; ++ uint32_t product, vendor; ++ ++ snprintf(mib, sizeof(mib), "dev.%s.%d.%%desc", driver, unit); ++ len = sizeof(name); ++ if (sysctlbyname(mib, name, &len, NULL, 0) < 0) ++ return; ++ if ((walk = strchr(name, ',')) != NULL) ++ *walk = '\0'; /* strip name */ ++ attrs->product = strdup(name); ++ ++ snprintf(mib, sizeof(mib), "dev.%s.%d.%%pnpinfo", driver, unit); ++ len = sizeof(pnpinfo); ++ if (sysctlbyname(mib, pnpinfo, &len, NULL, 0) < 0) + return; + -+ snprintf(sysctlname, sizeof(sysctlname), "dev.%s.%s.%%desc", -+ hw_types[i].driver, devname + strlen(hw_types[i].driver)); -+ vendor = sysctl_get_str(sysctlname); -+ if (vendor == NULL) { -+ options = input_option_new(options, "name", devname); -+ } -+ else { -+ if ((walk = strchr(vendor, ' ')) != NULL) { -+ walk[0] = '\0'; -+ walk++; -+ product = walk; -+ if ((walk = strchr(product, ',')) != NULL) -+ walk[0] = '\0'; -+ } ++ vendorstr = get_prop_value(pnpinfo, "vendor", &vendorlen); ++ prodstr = get_prop_value(pnpinfo, "product", &prodlen); ++ devicestr = get_prop_value(pnpinfo, "device", &devicelen); ++ pnp_id = get_prop_value(pnpinfo, "_HID", &pnplen); ++ if (pnp_id != NULL && pnplen == 4 && strncmp(pnp_id, "none", 4) == 0) ++ pnp_id = NULL; ++ if (pnp_id != NULL) { ++ pnp_id[pnplen] = '\0'; ++ attrs->pnp_id = strdup(pnp_id); ++ } ++ if (prodstr != NULL && vendorstr != NULL) { ++ /* bus = BUS_USB; */ ++ vendor = strtol(vendorstr, NULL, 0); ++ product = strtol(prodstr, NULL, 0); ++ } else if (devicestr != NULL && vendorstr != NULL) { ++ /* bus = BUS_PCI; */ ++ vendor = strtol(vendorstr, NULL, 0); ++ product = strtol(devicestr, NULL, 0); ++ } else ++ return; + -+ attrs.vendor = strdup(vendor); -+ if (product) { -+ attrs.product = strdup(product); -+ options = input_option_new(options, "name", product); -+ } -+ else -+ options = input_option_new(options, "name", "(unnamed)"); ++ asprintf(&attrs->usb_id, "%04x:%04x", vendor, product); ++ asprintf(&attrs->vendor, "0x%04x", vendor); + -+ free(vendor); -+ } ++ return; ++} + -+ /* XXX implement usb_id */ -+ attrs.usb_id = NULL; -+ attrs.device = strdup(path); -+ options = input_option_new(options, "driver", hw_types[i].xdriver); ++static const char * ++skip_path_dev(const char *ptr) ++{ ++ if (strstr(ptr, _PATH_DEV) == ptr) ++ ptr += strlen(_PATH_DEV); ++ return (ptr); ++} + -+ fd = open(path, O_RDONLY); -+ if (fd > 0) { -+ close(fd); -+ options = input_option_new(options, "device", path); ++static void ++device_added(const char *devicename, struct dev_list *blacklist) ++{ ++ InputAttributes attrs = { }; ++ InputOption *options = NULL; ++ char *config_info = NULL; ++ DeviceIntPtr dev = NULL; ++ struct hw_type hw_type; ++ int unit = 0; ++ int fd = -1; ++ int i; ++ bool allow_no_device = false; ++ ++ for (i = 0; hw_types0[i].driver != NULL; i++) { ++ if (strcmp(devicename, hw_types0[i].driver) == 0) { ++ hw_type = hw_types0[i]; ++ goto found; ++ } ++ } ++ for (i = 0; hw_types1[i].driver != NULL; i++) { ++ if (sscanf(devicename, hw_types1[i].driver, &unit) == 1) { ++ hw_type = hw_types1[i]; ++ goto found; ++ } + } -+ else { -+ if (attrs.flags & ~ATTR_KEYBOARD) { -+ LogMessage(X_INFO, "config/devd: device %s already opened\n", -+ path); ++ goto ignore; + ++found: ++ if (hw_type.xdriver == NULL) ++ goto ignore; ++ ++ /* set flags, if any */ ++ attrs.flags |= hw_type.flag; ++ ++ if (strcmp(hw_type.xdriver, "evdev") == 0) { ++ get_evdev_attrs(&attrs, devicename); ++ /* Set keyboard rules explicitly for libinput */ ++ if (attrs.flags & ATTR_KEYBOARD) { ++ options = input_option_new(options, "xkb_rules", ++ "evdev"); ++ if (options == NULL) ++ goto error; ++ } ++ } else { ++ if (is_kernel_evdev) { ++ if (dev_list_empty(blacklist)) ++ get_evdev_blacklist(blacklist); + /* -+ * Fail if cannot open device, it breaks AllowMouseOpenFail, -+ * but it should not matter when config/devd enabled ++ * Prefer evdev input kernel interface to native one. ++ * Assume that both evdev 'physical path' and non-evdev ++ * character device path endings are device names so ++ * we can compare them and skip latter. + */ -+ goto unwind; ++ if (dev_list_search(blacklist, bname(devicename))) ++ goto ignore; + } ++ } + -+ if (is_console_kbd) { -+ /* -+ * There can be only one keyboard attached to console and -+ * it is already added. -+ */ -+ LogMessage(X_WARNING, "config/devd: console keyboard is " -+ "already added, ignoring %s (%s)\n", -+ attrs.product, path); -+ goto unwind; ++ if (strcmp(hw_type.xdriver, "kbd") == 0) { ++ bool match = (strstr(hw_type.driver, ++ _PATH_DEV "kbdmux") == hw_type.driver); ++ ++ if (is_kbdmux) { ++ allow_no_device = true; ++ if (!match) ++ goto ignore; ++ } else { ++ if (match) ++ goto ignore; + } -+ else -+ /* -+ * Don't pass "device" option if the keyboard is already -+ * attached to the console (ie. open() fails). -+ * This would activate a special logic in xf86-input-keyboard. -+ * Prevent any other attached to console keyboards being -+ * processed. There can be only one such device. -+ */ -+ is_console_kbd = true; + } + -+ if (asprintf(&config_info, "devd:%s", devname) == -1) { ++ options = input_option_new(options, "_source", "server/devd"); ++ if (options == NULL) ++ goto error; ++ ++ if (hw_type.sysctldesc != NULL) ++ get_sysctl_attrs(&attrs, hw_type.sysctldesc, unit); ++ ++ if (attrs.product == NULL) ++ attrs.product = strdup(skip_path_dev(devicename)); ++ ++ options = input_option_new(options, "name", attrs.product); ++ if (options == NULL) ++ goto error; ++ ++ attrs.device = strdup(devicename); ++ ++ fd = open(devicename, O_RDONLY); ++ if (fd > -1) { ++ if (attrs.usb_id == NULL) ++ get_usb_id(&attrs.usb_id, fd); ++ close(fd); ++ options = input_option_new(options, "device", devicename); ++ if (options == NULL) ++ goto error; ++ } else if (allow_no_device) { ++ /* ++ * Don't pass "device" option if the keyboard is ++ * already attached to the console (ie. open() fails). ++ * This would activate a special logic in ++ * xf86-input-keyboard. Prevent any other attached to ++ * console keyboards being processed. There can be ++ * only one such device. ++ */ ++ } else { ++ goto ignore; ++ } ++ ++ options = input_option_new(options, "driver", hw_type.xdriver); ++ if (options == NULL) ++ goto error; ++ ++ if (asprintf(&config_info, "devd:%s", ++ skip_path_dev(devicename)) == -1) { + config_info = NULL; -+ goto unwind; ++ goto error; + } + -+ if (device_is_duplicate(config_info)) { -+ LogMessage(X_WARNING, "config/devd: device %s (%s) already added. " -+ "ignoring\n", attrs.product, path); -+ goto unwind; -+ } ++ if (device_is_duplicate(config_info)) ++ goto duplicate; + + options = input_option_new(options, "config_info", config_info); -+ LogMessage(X_INFO, "config/devd: adding input device %s (%s)\n", -+ attrs.product, path); ++ if (options == NULL) ++ goto error; ++ ++ LogMessage(X_INFO, "config/devd: adding input device '%s'\n", ++ devicename); + + NewInputDeviceRequest(options, &attrs, &dev); ++ goto done; ++ ++duplicate: ++ LogMessage(X_WARNING, "config/devd: device '%s' already " ++ "added. Ignoring\n", devicename); ++ goto done; ++ ++error: ++ LogMessage(X_INFO, "config/devd: error adding device '%s'\n", ++ devicename); ++ goto done; ++ ++ignore: ++ LogMessage(X_INFO, "config/devd: ignoring device '%s'\n", ++ devicename); ++ goto done; + -+unwind: ++done: + free(config_info); + input_option_free_list(&options); + free(attrs.usb_id); ++ free(attrs.pnp_id); + free(attrs.product); + free(attrs.device); + free(attrs.vendor); +} + +static void -+device_removed(char *devname) ++devpath_scan_sub(char *path, int off, int rem, void *udata) ++{ ++ struct dirent *entry; ++ DIR *dp; ++ ++ if ((dp = opendir(path)) == NULL) { ++ LogMessage(X_INFO, "Cannot open directory '%s'\n", path); ++ return; ++ } ++ while ((entry = readdir(dp)) != NULL) { ++ int len = strlen(entry->d_name); ++ if (len > rem) ++ continue; ++ strcpy(path + off, entry->d_name); ++ off += len; ++ rem -= len; ++ switch (entry->d_type) { ++ case DT_DIR: ++ if (strcmp(entry->d_name, ".") == 0 || ++ strcmp(entry->d_name, "..") == 0) ++ break; ++ if (rem < 1) ++ break; ++ path[off] = '/'; ++ path[off+1] = '\0'; ++ off++; ++ rem--; ++ /* recurse */ ++ devpath_scan_sub(path, off, rem, udata); ++ off--; ++ rem++; ++ break; ++ case DT_SOCK: ++ case DT_FIFO: ++ case DT_LNK: ++ case DT_CHR: ++ /* add device, if any */ ++ device_added(path, udata); ++ break; ++ default: ++ break; ++ } ++ off -= len; ++ rem += len; ++ } ++ closedir(dp); ++} ++ ++static void ++devpath_scan(void *udata) ++{ ++ char path[PATH_MAX + 1]; ++ ++ strlcpy(path, _PATH_DEV, sizeof(path)); ++ ++ devpath_scan_sub(path, strlen(path), PATH_MAX - strlen(path), udata); ++} ++ ++static void ++device_removed(char *devicename) +{ + char *config_info; + -+ if (asprintf(&config_info, "devd:%s", devname) == -1) ++ if (asprintf(&config_info, "devd:%s", ++ skip_path_dev(devicename)) == -1) + return; + ++ if (device_is_duplicate(config_info)) { ++ LogMessage(X_INFO, "config/devd: removing input device '%s'\n", ++ devicename); ++ } + remove_devices("devd", config_info); + + free(config_info); @@ -318,8 +676,7 @@ +static bool is_kbdmux_enabled(void) +{ + /* Xorg uses /dev/ttyv0 as a console device */ -+ /* const char device[]="/dev/console"; */ -+ const char device[]="/dev/ttyv0"; ++ static const char device[]= { _PATH_DEV "ttyv0" }; + keyboard_info_t info; + int fd; + @@ -377,7 +734,7 @@ +} + +static CARD32 -+reconnect_handler(OsTimerPtr timer, CARD32 time, void *arg) ++reconnect_handler(OsTimerPtr timer, CARD32 unused_time, void *arg) +{ + int newsock; + @@ -448,8 +805,13 @@ +static void +wakeup_handler(void *data, int err, void *read_mask) +{ ++ static const char cdev_create[] = { "!system=DEVFS subsystem=CDEV type=CREATE cdev=" }; ++ static const char cdev_destroy[] = { "!system=DEVFS subsystem=CDEV type=DESTROY cdev=" }; ++ static const char cdev_path[] = { _PATH_DEV }; + char *line = NULL; ++ char *devicename; + char *walk; ++ struct dev_list blacklist; + + if (err < 0) + return; @@ -457,20 +819,23 @@ + if (FD_ISSET(sock_devd, (fd_set *) read_mask)) { + if (socket_getline(sock_devd, &line) < 0) + return; -+ -+ walk = strchr(line + 1, ' '); -+ if (walk != NULL) -+ walk[0] = '\0'; -+ -+ switch (*line) { -+ case DEVD_EVENT_ADD: -+ device_added(line + 1); -+ break; -+ case DEVD_EVENT_REMOVE: -+ device_removed(line + 1); -+ break; -+ default: -+ break; ++ if (strstr(line, cdev_create) == line) { ++ devicename = line + strlen(cdev_create) - strlen(cdev_path); ++ memcpy(devicename, cdev_path, strlen(cdev_path)); ++ walk = strchr(devicename, ' '); ++ if (walk != NULL) ++ walk[0] = '\0'; ++ /* Blacklist is lazy-populated in device_added() */ ++ dev_list_init(&blacklist); ++ device_added(devicename, &blacklist); ++ dev_list_destroy(&blacklist); ++ } else if (strstr(line, cdev_destroy) == line) { ++ devicename = line + strlen(cdev_destroy) - strlen(cdev_path); ++ memcpy(devicename, cdev_path, strlen(cdev_path)); ++ walk = strchr(devicename, ' '); ++ if (walk != NULL) ++ walk[0] = '\0'; ++ device_removed(devicename); + } + free(line); + } @@ -484,34 +849,31 @@ +int +config_devd_init(void) +{ -+ char devicename[1024]; -+ int i, j; ++ struct dev_list blacklist; + + LogMessage(X_INFO, "config/devd: probing input devices...\n"); + -+ /* -+ * Add fake keyboard and give up on keyboards management -+ * if kbdmux is enabled -+ */ -+ if ((is_kbdmux = is_kbdmux_enabled()) == true) -+ device_added("kbdmux"); -+ -+ for (i = 0; hw_types[i].driver != NULL; i++) { -+ /* First scan the sysctl to determine the hardware */ -+ for (j = 0; j < 16; j++) { -+ if (sysctl_exists(&hw_types[i], j, -+ devicename, sizeof(devicename)) != 0) -+ device_added(devicename); -+ } ++ /* Blacklist is lazy-populated in device_added() */ ++ dev_list_init(&blacklist); + -+ if (devpath_exists(&hw_types[i], devicename, sizeof(devicename)) != 0) -+ device_added(devicename); -+ } ++ /* Check if kbdmux is enabled */ ++ is_kbdmux = is_kbdmux_enabled(); + ++ /* Check if evdev support is compiled into kernel */ ++ is_kernel_evdev = feature_present("evdev") != 0; ++ ++ /* Connect to devd, so that we don't loose any events */ + if ((sock_devd = connect_devd()) < 0) + return 0; + -+ RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, NULL); ++ /* Scan what is currently connected */ ++ devpath_scan(&blacklist); ++ ++ /* Register wakeup handler */ ++ RegisterBlockAndWakeupHandlers(block_handler, ++ wakeup_handler, NULL); ++ ++ dev_list_destroy(&blacklist); + + return 1; +} @@ -528,7 +890,6 @@ + + disconnect_devd(sock_devd); + -+ RemoveBlockAndWakeupHandlers(block_handler, wakeup_handler, NULL); -+ -+ is_console_kbd = false; ++ RemoveBlockAndWakeupHandlers(block_handler, ++ wakeup_handler, NULL); +}