[RFC] libinputmapper: Input device configuration for graphic-servers
Peter Hutterer
peter.hutterer at who-t.net
Wed May 15 22:37:49 PDT 2013
On Sun, May 12, 2013 at 04:20:59PM +0200, David Herrmann wrote:
> [bcc to gnome-shell-list and kwin, to keep discussion on wayland-devel]
> Without a generic graphics-server like xserver, compositors need to
> handle input devices themselves if run as wayland compositors. To
> avoid having several different conflicting implementations, I wrote up
> a small proposal and library API to have a common configuration.
>
> How is it currently handled?
> A compositor uses udev to listen for input devices. For each
> input-device, they use some heuristics (test for KEY_*, ABS_*, ..
> event-bits) to figure out what kind of input is provided by the
> device. Unknown devices and events are ignored, devices that look
> useful are passed to the correct input-driver.
> For keyboard input, libxkbcommon is used. For
> mouse/touchpad/touchscreen input, every compositor has it's own simple
> driver (I am not aware of an attempt to put xf86-input-synaptics into
> an independent library).
fwiw, I tried this once, but the amount of legacy junk in the X driver is
large enough that it would be better writing synaptics from scratch as a
library and hook that up instead.
> For other device types, applications handle
> input themselves (gamepads, joysticks, and so on). And then there are
> devices that have x11 drivers, but I am not aware of external drivers
> for wayland-compositors (like wacom digitizers).
>
> I am not interested in the device-drivers itself (for now in this
> project). I think it would be nice to write a libsynapticscommon,
ftr, please don't name such an effort synaptics. the name in the X driver is
historical and should be changed, so libtouchpad is a better name.
> libmousecommon, .. which provide a libxkbcommon'ish interface for
> other device types independent of the compositor implementation, but
> that's another independent issue.
> Instead, I am more interested in the device-detection and enumeration.
> If I plug in a gamepad device, I don't want _any_ compositor to handle
> it as a mouse, just because it provides REL_X/Y values. I don't want
> compositors to erroneously handle accelerometers as mice because they
> provide ABS_X/Y values. But on the other hand, I want users to be able
> to tell compositors to handle ABS_X/Y input from their custom hardware
> as mouse input, _iff_ they want to.
> Furthermore, if a device has a buggy kernel driver and reports BTN_X
> instead of BTN_A, I want all compositors to detect that and apply a
> simple fixup button-mapping. Or allow users to remap
> buttons/axis/LEDs/EV_WHATEVER arbitrarily.
>
> udev provides some very basic heuristics with device-tags, but talking
> to Kay Sievers, he'd like to avoid having huge detection-tables and
> heuristics in udev (which is understandable).
>
> Dmitry Torokhov is not averse to providing device-type properties in
> the kernel input-subsystem, but on the other hand, it doesn't help us
> much. Generic HID devices might still provide any arbitrary input that
> we would have to write custom drivers/quirks for, if they don't match.
> So if no-one steps up to do all that work, I recommend providing these
> fixups in user-space. This also has the advantage, that users can
> arbitrarily modify these rules if they want crazy setups (which users
> normally want..). And we can ship fixup-rules for new devices, while
> in the meantime writing kernel drivers for them and waiting for the
> next kernel release. And don't forget the kernel drivers with broken
> mappings, which we cannot fix due to backwards-compatibility, but
> still want them to be correctly mapped in new
> compositors/applications.
>
>
> So what is the proposed solution?
> My recommendation is, that compositors still search for devices via
> udev and use device drivers like libxkbcommon. So linux evdev handling
> is still controlled by the compositor. However, I'd like to see
> something like my libinputmapper proposal being used for device
> detection and classification.
>
> libinputmapper provides an "inmap_evdev" object which reads device
> information from an evdev-fd or sysfs /sys/class/input/input<num>
> path, performs some heuristics to classify it and searches it's global
> database for known fixups for broken devices.
> It then provides "capabilities" to the caller, which allow them to see
> what drivers to load on the device. And it provides a very simple
> mapping table that allows to apply fixup mappings for broken devices.
> These mappings are simple 1-to-1 mappings that are supposed to be
> applied before drivers handle the input. This is to avoid
> device-specific fixup in the drivers and move all this to the
> inputmapper. An example would be a remapping for gamepads that report
> BTN_A instead of BTN_NORTH, but we cannot fix them in the kernel for
> backwards-compatibility reasons. The gamepad-driver can then assume
> that if it receives BTN_NORTH, it is guaranteed to be BTN_NORTH and
> doesn't need to special case xbox360/etc. controllers, because they're
> broken.
I think evdev is exactly that interface and apparently it doesn't work.
if you want a mapping table, you need a per-client table because sooner or
later you have a client that needs BTN_FOO when the kernel gives you BTN_BAR
and you can't change the client to fix it.
i.e. the same issue evdev has now, having a global remapping table just
moves the problem down by 2 years.
a mapping table is good, but you probably want two stages of mapping: one
that's used in the compositor for truly broken devices that for some reason
can't be fixed in the kernel, and one that's used on a per-client basis. and
you'll likely want to be able to overide the client-specific from outside
the client too.
> libinputmapper would use some static heuristics for all this, but
> additionally parse user-configuration. A configuration file contains
> "[match]" entries, which specify device-configurations to load on
> mtached devices. The device-configurations then contain different
> blocks which can overwrite the auto-detected capabilities or provide
> fixup-mappings.
> But other configuration-sections can also be provided in the same
> file. For instance an [xkb] group could be specified to set XKB
> layout/variant/options. This won't be parsed by libinputmapper, but it
> would provide the matching and forward the device-configuration to the
> caller, which can pass it on to the driver.
> Additionally, API users can provide separate (local)
> configuration-files that allow users to change the configuration for
> kmscon one way and another way for gnome-shell (or similar).
>
> One can think of these configurations to replace the old
> /etc/X11/xorg.conf.d/*.conf "InputClass" configuration items. Except
> that the "matching" is offloaded to a separate file, and the "to be
> applied configurations" are specified in "rule" files, that are linked
> to from the "match" configurations. See below for syntax-examples.
>
>
> I haven't implemented the library, yet. I am working on this. However,
> I wrote up an API proposal that I attached inline below. kmscon input
> handling is what I need it for, so I want something like this, anyway.
> But I thought other compositors might be interested in this, too.
>
> Comments are welcome!
> Regards
> David
>
>
[...]
> /**
> * @enum inmap_capability
> * Generic device capabilities
> *
> * Device capabilities describe what generic interface is provided by the
> * detected device. A device can support any combination of them (or none).
> * Each interface follows specific rules. If a device does not follow these
> * rules, we must provide a mapping table so the correct data is reported.
> *
> * Capabilities can be added for all kinds of generic devices. However, custom
> * devices with model-specific features do not belong here, as their drivers
> * need to perform device-detection themselves, anyway.
> *
> * Furthermore, each capability needs a well-defined protocol. They are mostly
> * already provided by the kernel. But there are many devices and drivers
> * which provide inconsistent behavior. That's why each capability has to
> * be consistent and coherent and misbehaving devices get fixup mappings, if
> * we cannot fix it in the kernel device driver itself.
> */
> enum inmap_capability {
> /**
> * @INMAP_CAP_KEYBOARD
> * Keyboard interface
> *
> * The device is a real keyboard that is used for normal input.
> * Power-buttons and similar devices which report KEY_* events for
> * non-keyboard buttons are not considered a keyboard in this sense.
> * Only real keyboards and small extension devices (like external
> * NumPads) belong here.
> * The defined KEY_* events are not listed here as normally no
> * mapping is applied. Libraries like libxkbcommon should be used
> * for keyboard handling and mapping.
> */
> INMAP_CAP_KEYBOARD = (1 << 0),
>
> /**
> * @INMAP_CAP_MOUSE
> * Mouse interface
> *
> * The device is a real mouse with relative motion events. Motion
> * is reported as REL_X/Y. Buttons are reported as BTN_0-BTN_9 or
> * BTN_LEFT-BTN_TASK.
> * Other mouse-like devices (especially those with absolute motion
> * events) do not belong here.
> */
> INMAP_CAP_MOUSE = (1 << 1),
>
> /**
> * @INMAP_CAP_TOUCHPAD
> * Touchpad interface
> *
> * Touchpad devices belong here. But only those that are used as
> * pointing devices and are intended to drive a mouse device. That is,
> * the input is interpreted as relative motion, even though the
> * reported data is normally absolute.
> * Hence, touchscreens do not belong here. They are normally
> * interpreted as absolute position input.
> *
> * For multitouch devices, libmtdev defines the protocol.
kernel MT Procol B is a better term here, libmtdev merely converts A to B.
> *
> * @TODO define the protocol (see the synaptics descriptions)
> */
> INMAP_CAP_TOUCHPAD = (1 << 2),
>
> /**
> * @INMAP_CAP_TOUCHSCREEN
> * Touchscreen interface
> *
> * Touchscreens are exactly the same as @INMAP_CAP_TOUCHPAD, but they
> * are normally attached to a single monitor and interpreted as
> * absolute positioning input.
> * Therefore, they are not included in @INMAP_CAP_TOUCHPAD, but are
> * a separate group instead. The reported protocol is the same, though.
> *
> * @sa INMAP_CAP_TOUCHPAD
> */
> INMAP_CAP_TOUCHSCREEN = (1 << 3),
>
> /**
> * @INMAP_CAP_ACCELEROMETER
> * Accelerometer interface
> *
> * Accelerometer devices report linear acceleration data as ABS_X/Y/Z
> * and rotational acceleration as ABS_RX/Y/Z.
> *
> * @TODO this collides with ABS_X/Y of absolute pointing devices
> * introduce ABS_ACCELX/Y/Z
> */
> INMAP_CAP_ACCELEROMETER = (1 << 4),
>
> /**
> * @INMAP_CAP_GAMEPAD
> * Gamepad interface
> *
> * All standard gamepad devices belong here.
> *
> * @TODO define gamepad mapping (see linux-input at vger discussion)
> */
> INMAP_CAP_GAMEPAD = (1 << 5),
>
> /**
> * @INMAP_CAP_JOYSTICK
> * Joystick interface
> *
> * All standard joystick devices belong here.
> *
> * @TODO define joystick mapping
> */
> INMAP_CAP_JOYSTICK = (1 << 6),
> };
why are gamepads and joysticks different? buttons, a few axes that may or
may not map to x/y and the rest is device-specific.
this may be in the thread, but I still haven't gone through all msgs here.
one missing section are graphics tablets but even there you could argue
they're just buttons, x/y and a few extra axes that need client-specific
handling.
> /**
> * @defgroup context Library Context
> * Managing library contexts
> *
> * A context object contains all top-level information. It can be shared
> * between multiple device objects and provides global infrastructure to them.
> *
> * @{
> */
>
> /**
> * @enum inmap_context_flags
> * Context creation and operation flags
> *
> * Different flags that control how a context is created and how it behaves.
> *
> * @memberof inmap_context
> * @sa inmap_context_new()
> */
> enum inmap_context_flags {
> /**
> * @INMAP_CONTEXT_IGNORE_ENVIRONMENT
> * Ignore environment variables
> *
> * The context object will not use any environment variables as
> * default values if they are not explicitly set.
> *
> * @memberof inmap_context
> */
> INMAP_CONTEXT_IGNORE_ENVIRONMENT = (1 << 0),
>
> /**
> * @INMAP_CONTEXT_MONITOR_CONF_FILES
> * Monitor configuration files
> *
> * If set, the context will monitor configuration files for runtime
> * modifications. This allows adapting to changes without restarting
> * the application.
> * Changes are not automatically applied. The application has to
> * react to these events and retrigger device detection for all
> * active devices.
> *
> * @memberof inmap_context
> * @sa inmap_context_dispatch()
> */
> INMAP_CONTEXT_MONITOR_CONF_FILES = (1 << 1),
tbh, I'd make that a required behaviour.
[still thinking about the rest]
Cheers,
Peter
> /**
> * @INMAP_CONTEXT_NO_DEFAULT_CONF
> * Skip default configuration
> *
> * If set, the global default configuration is not parsed.
> *
> * @memberof inmap_context
> */
> INMAP_CONTEXT_NO_DEFAULT_CONF = (1 << 2),
> };
>
> /**
> * Create new context
> *
> * @param[out] out Pointer to the new context is stored here
> * @param[in] caps Capabilities that are used with this context
> * @param[in] flags Optional flags or 0
> *
> * Create a new context and store a pointer to it in @out. You must specify
> * all capabilities that you want to use with this context in @caps. This
> * causes the context to ignore and skip all configuration options for
> * other capabilities to save memory.
> * You cannot modify the capabilities afterwards.
> *
> * You can change the behavior of the context with additional flags. See the
> * @inmap_context_flags for a description of flags.
> *
> * Context objects are reference counted. Initial ref-count is 1. You can
> * modify it via @inmap_context_ref() and @inmap_context_unref().
> *
> * @returns 0 on success, negative error code on failure.
> *
> * @memberof inmap_context
> * @sa inmap_context_flags
> * @sa inmap_context_ref()
> * @sa inmap_context_unref()
> */
> int inmap_context_new(struct inmap_context **out,
> enum inmap_capability caps,
> enum inmap_context_flags flags);
>
> /**
> * Increase context ref-count
> *
> * @param[in] ctx Valid context object or NULL
> *
> * Increase ref-count of the given context by 1. If NULL is passed as
> * context, then nothing is done.
> *
> * @memberof inmap_context
> * @sa inmap_context_new()
> * @sa inmap_context_unref()
> */
> void inmap_context_ref(struct inmap_context *ctx);
>
> /**
> * Decrease context ref-count
> *
> * @param[in] ctx Valid context object or NULL
> *
> * Decrease ref-count of @ctx by 1. You must not access @ctx afterwards if
> * you do not own another reference. This function destroys @ctx if the
> * ref-count drops to 0.
> * If @ctx is NULL, nothing is done.
> *
> * @memberof inmap_context
> * @sa inmap_context_new()
> * @sa inmap_context_ref()
> */
> void inmap_context_unref(struct inmap_context *ctx);
>
> /**
> * Set user-data
> *
> * @param[in] ctx Valid context object
> * @param[in] user_data User-data pointer
> *
> * Set a user-controlled pointer field in @ctx. This allows the user to
> * associate any data with this context. It can be retrieved via
> * @inmap_context_get_user_data() again.
> * This field is set to NULL during context initialization and then never
> * modified by the library code itself. It is a fully user controlled field.
> *
> * @memberof inmap_context
> * @sa inmap_context_get_user_data()
> */
> void inmap_context_set_user_data(struct inmap_context *ctx, void *user_data);
>
> /**
> * Get user-data
> *
> * @param[in] ctx Valid context object
> *
> * @returns user-data field previously set via @inmap_context_set_user_data()
> *
> * @memberof inmap_context
> * @sa inmap_context_set_user_data()
> */
> void *inmap_context_get_user_data(struct inmap_context *ctx);
>
> /**
> * @enum inmap_context_log_level
> * Log-level of context objects
> *
> * The log-levels are exactly the same as the kernel log-levels.
> *
> * @memberof inmap_context
> */
> enum inmap_context_log_level {
> INMAP_CONTEXT_LOG_LEVEL_EMERGENCY,
> INMAP_CONTEXT_LOG_LEVEL_ALERT,
> INMAP_CONTEXT_LOG_LEVEL_CRITICAL,
> INMAP_CONTEXT_LOG_LEVEL_ERROR,
> INMAP_CONTEXT_LOG_LEVEL_WARNING,
> INMAP_CONTEXT_LOG_LEVEL_NOTICE,
> INMAP_CONTEXT_LOG_LEVEL_INFO,
> INMAP_CONTEXT_LOG_LEVEL_DEBUG,
> };
>
> /**
> * Set log level
> *
> * @param[in] ctx Valid context object
> * @param[in] level New log level
> *
> * Change the default log-level to @level. Only log-messages with equal or
> * higher priority are passed to the log-function. Default log-level is
> * @INMAP_CONTEXT_LOG_LEVEL_ERROR.
> *
> * During context creation, the log-level is set to the value of the
> * environment variable INMAP_LOG_LEVEL if set. It may be specified as a
> * number or name.
> *
> * @memberof inmap_context
> * @sa inmap_context_log_level
> * @sa inmap_context_get_log_level()
> * @sa inmap_context_set_log_fn()
> */
> void inmap_context_set_log_level(struct inmap_context *ctx, unsigned int level);
>
> /**
> * Get log level
> *
> * @param[in] ctx Valid context object
> *
> * @returns log-level previously set via inmap_context_log_leve()
> *
> * @memberof inmap_context
> * @sa inmap_context_log_level
> * @sa inmap_context_set_log_level()
> * @sa inmap_context_set_log_fn()
> */
> unsigned int inmap_context_get_log_level(struct inmap_context *ctx);
>
> /**
> * Set log function
> *
> * @param[in] ctx Valid context object
> * @param[in] log_fn Log-function or NULL
> *
> * Change the default log-function to @log_fn. If @log_fn is NULL, no
> * logging will be done.
> * This log-function is called for every log-message that has a higher
> * or equal priority as the currently set log-level.
> *
> * The first argument is the context object, followed by the user_data field
> * which can also be retrieved via inmap_context_get_user_data(). Then the
> * log-level of the message, the file/line/function information where the
> * message originated and the format/args combination with the actual
> * log message.
> *
> * @memberof inmap_context
> * @sa inmap_context_log_level
> * @sa inmap_context_set_log_level()
> */
> void inmap_context_set_log_fn(struct inmap_context *ctx,
> void (*log_fn) (struct inmap_context *ctx,
> void *user_data,
> unsigned int level,
> const char *file,
> int line,
> const char *fn,
> const char *format,
> va_list args));
>
> /**
> * Return the context file-descriptor
> *
> * @param[in] ctx Valid context
> *
> * If the context was created with the @INMAP_CONTEXT_MONITOR_CONF_FILES
> * flag, it will allocate kernel resources to monitor configuration files.
> * These report changes via file-descriptors. You can track these via this
> * function.
> * Whenever the file-descriptor is readable, you must call
> * inmap_context_dispatch() to let the library handle the events.
> *
> * If you didn't use config-file tracking, this will always return -1 and
> * there is no reason to call this or inmap_context_dispatch().
> *
> * @returns file-descriptor or -1 if not used
> *
> * @memberof inmap_context
> * @sa inmap_context_dispatch()
> */
> int inmap_context_get_fd(struct inmap_context *ctx);
>
> /**
> * @enum inmap_context_dispatch_event
> * Dispatch events
> *
> * Events that are handled by the context object and returned to the caller
> * so they can react to it.
> *
> * @memberof inmap_context
> * @sa inmap_context_dispatch()
> */
> enum inmap_context_dispatch_event {
> /**
> * @INMAP_CONTEXT_CONF_CHANGED
> * Configuration changed
> *
> * This is returned whenever a configuration file was modified and
> * @INMAP_CONTEXT_MONITOR_CONF_FILES was used. The library itself
> * does not react to this event, so you need to reread the
> * configuration files yourself via inmap_context_conf_refresh() and
> * recreate the inmap_evdev objects that might have changed.
> *
> * @memberof inmap_context
> */
> INMAP_CONTEXT_CONF_CHANGED = (1 << 0),
> };
>
> /**
> * Dispatch outstanding work
> *
> * @param[in] ctx Valid context object
> *
> * Whenever the internal file-descriptor of this context is readable (see
> * also @inmap_context_get_fd()), you must call this function to dispatch
> * any outstanding work.
> * This is currently only used for the @INMAP_CONTEXT_MONITOR_CONF_FILES
> * implementation. If @inmap_context_get_fd() does not return a valid
> * file-descriptor, you can skip calling this function.
> * All events that were detected are returned as bitmask so the caller can
> * react on them.
> *
> * @returns @inmap_context_dispatch_event event-flags on success, negative
> * error code on failure.
> *
> * @memberof inmap_context
> * @sa inmap_context_get_fd()
> */
> int inmap_context_dispatch(struct inmap_context *ctx);
>
> /** @} */
>
> /**
> * @defgroup context-conf Library Context Configuration Files
> * Managing configuration files
> *
> * Users can supply configuration files to extend the detection logic
> * without modifying the source code. Default configurations are always
> * used (except if INMAP_CONTEXT_NO_DEFAULT_CONF is used) but you can
> * supply additional files for local configurations.
> *
> * If a configuration file is given by path or filename it can be monitored
> * for runtime modifications if INMAP_CONTEXT_MONITOR_CONF_FILES is used.
> * Configurations given via memory cannot be monitored.
> *
> * Configuration files contain matching-rules and filenames of
> * device-configuration-files to apply for matched devices. So the main
> * configuration file simply contains a list of names and IDs for devices
> * that need special fixups.
> *
> * Syntax of configuration files is ini-style like this:
> * @code
> * [match <optional-name>]
> * name = *name*wild*mask
> * bus = <bus-name>,<another-bus-name>,..
> * vid = <vendor-id>,<another-vendor-id>,..
> * pid = <product-id>,..
> * rules = <relative-path-to-device-conf>
> * @endcode
> * You can put as many of these [match] groups into a configuration file. All
> * fields except for "rules" are optional. If a device matches a [match] block,
> * the rules that are found in "rules" are applied to the device. Multiple
> * blocks may match and are applied in the order as specified.
> * Fields are matched with a logical "AND". So if "bus" and "name" are
> * specified, the device must match both. Multiple entries in the same
> * category are matched with a logical "OR". So if multiple "vid" entries
> * are given, only one of them must match.
> * Unknown rules are silently ignored. This allows to easily extend this file
> * with further entries in the future.
> *
> * Rule-files contain rules that are to be applied to a device. Unknown entries
> * are silently ignored. This allows to store additional information in
> * these files for other libraries to use.
> * Supported entries are:
> * @code
> * [capabilities <optional-name>]
> * add = <cap1>,<cap2>,..
> * remove = <cap1>,<cap2>,..
> * set = <cap1>,<cap2>,..
> * @endcode
> * This overwrites the heuristics used to detect device capabilities. "add"
> * causes the library to add the given capabilities to the auto-detected caps.
> * "remove" causes the library to remove them and "set" overwrites all of
> * them. "set" is mutually exclusive to "add" and "remove", obviously.
> * @code
> * [mapping <optional-name>]
> * map = <type>:<code> => [<type>:]<code>,
> * [<type>:]<code> => [<type>:]<code>,
> * ..
> * @endcode
> * This specifies a simple mapping table. <type> must only be specified once
> * and will automatically be kept for following entries that have no explicit
> * <type> prefix.
> * inmap_evdev will create a mapping table from these rules and map the
> * specified type+code combinations to the target type+code. The "value"
> * field cannot be modified for now.
> *
> * @{
> */
>
> /** configuration file parser flags */
> enum inmap_context_conf_flags {
> /** Allow any file type, not only regular files. */
> INMAP_CONTEXT_CONF_ALLOW_ANY = (1 << 0),
> /** Do not monitor this file. */
> INMAP_CONTEXT_CONF_DONT_MONITOR = (1 << 1),
> };
>
> /**
> * Add configuration file from memory buffer
> *
> * @param[in] ctx Valid context object
> * @param[in] buffer Pointer to the memory buffer to read from. Does not
> * have to be zero terminated.
> * @param[in] length Length of @buffer not including any possible
> * terminating zero character.
> * @param[in] flags Optional flags for the parser or 0.
> *
> * Parses the buffer given in @buffer as configuration file and updates the
> * context accordingly.
> *
> * @INMAP_CONTEXT_CONF_ALLOW_ANY has no effect if set and is ignored.
> *
> * Obviously, @INMAP_CONTEXT_MONITOR_CONF_FILES has no effect on
> * configurations that are parsed with this function. If you want to track
> * configuration files for changes, you must use
> * @inmap_context_conf_add_from_path.
> * @INMAP_CONTEXT_CONF_DONT_MONITOR is ignored, too.
> *
> * @returns 0 on success, negative error code on failure.
> *
> * @memberof inmap_context
> * @sa inmap_context_conf_add_from_path()
> */
> int inmap_context_conf_add_from_buffer(struct inmap_context *ctx,
> const void *buffer, size_t length,
> enum inmap_context_conf_flags flags);
>
> /**
> * Add configuration file from file path
> *
> * @param[in] ctx Valid context object
> * @param[in] path Path to the configuration file. Must be a zero-
> * terminated string.
> *
> * Parses the configuration file at @path and updates the context
> * accordingly.
> *
> * @returns 0 on success, negative error code on failure.
> *
> * @memberof inmap_context
> * @sa inmap_context_conf_add_from_buffer()
> */
> int inmap_context_conf_add_from_path(struct inmap_context *ctx,
> const char *path);
>
> /**
> * Parse configuration files
> *
> * @param[in] ctx Valid context object
> *
> * This resets the configuration-file cache and re-reads all files. Use
> * this whenever a configuration file changed. You also must call this
> * after creating the context to read the default configurations.
> *
> * Files added via @inmap_context_conf_add_from_path() are automatically
> * parsed while added, but can be re-parsed by calling this function.
> *
> * @returns 0 on success, negative error code on failure
> *
> * @memberof inmap_context
> */
> int inmap_context_conf_parse(struct inmap_context *ctx);
>
> /** @} */
>
> /**
> * @defgroup evdev Evdev input devices
> * Managing evdev input device detection and rules
> *
> * @{
> */
>
> /**
> * Create new evdev device from fd
> *
> * @param[in] ctx Valid context object
> * @param[out] out Pointer to new evdev object is stored here
> * @param[in] fd File-descriptor of input evdev device
> *
> * Create a new inmap_evdev context and retrieve information via a normal
> * file-descriptor. The file-descriptor is not kept by this function but
> * only used during initialization to retrieve device-name and so on.
> *
> * The new evdev object will be associated with the given context. All
> * matching rules are immediately applied and device detection will be
> * performed.
> *
> * inmap_evdev objects are ref-counted. Initial ref-count will be 1.
> *
> * @returns 0 on success, negative error code on failure
> *
> * @memberof inmap_evdev
> */
> int inmap_evdev_new_from_fd(struct inmap_context *ctx,
> struct inmap_evdev **out,
> int fd);
>
> /**
> * Create new evdev device from sysfs-path
> *
> * @param[in] ctx Valid context object
> * @param[out] out Pointer to new evdev object is stored here
> * @param[in] path Path to sysfs-device directory
> *
> * Create a new inmap_evdev context and retrieve information via sysfs. No
> * file-descriptor to the event-device is needed.
> * The sysfs path @path normally points to a directory like
> * /sys/class/input/input<num>/
> * Note that this must be the input-device directory, not the event/evdev
> * device directory!
> *
> * The new evdev object will be associated with the given context. All
> * matching rules are immediately applied and device detection will be
> * performed.
> *
> * inmap_evdev objects are ref-counted. Initial ref-count will be 1.
> *
> * @returns 0 on success, negative error code on failure
> *
> * @memberof inmap_evdev
> */
> int inmap_evdev_new_from_syspath(struct inmap_context *ctx,
> struct inmap_evdev **out,
> const char *path);
>
> /**
> * Increase inmap_evdev ref-count
> *
> * @param[in] evdev Valid evdev object, or NULL
> *
> * Increase ref-count of @evdev by 1. Does nothing if @evdev is NULL.
> *
> * @memberof inmap_evdev
> */
> void inmap_evdev_ref(struct inmap_evdev *evdev);
>
> /**
> * Decrease inmap_evdev ref-count
> *
> * @param[in] evdev Valid evdev object, or NULL
> *
> * Decrease ref-count of @evdev by 1. This destroys the object immediately,
> * iff the ref-count drops to 0. Does nothing if @evdev is NULL.
> *
> * @memberof inmap_evdev
> */
> void inmap_evdev_unref(struct inmap_evdev *evdev);
>
> /**
> * Get device capabilities
> *
> * @param[in] evdev Valid evdev object
> *
> * Return a bitmask of capabilities of the given device. You can use these
> * to decide which device drivers to load on this input device.
> *
> * @returns bitmask of capabilities
> *
> * @memberof inmap_evdev
> */
> enum inmap_capabilities inmap_evdev_get_capabilities(struct inmap_evdev *evdev);
>
> /**
> * Create mapping table
> *
> * @param[in] evdev Valid evdev object
> * @param[out] out Pointer to new mapping table is stored here
> * @param[in] caps Capability bitmask
> *
> * Create new mapping tables for the capabilities given in @caps. The new
> * table is stored in @out. If no table is available, @out will be NULL
> * afterwards.
> * This combines all required tables for the given capabilities in one
> * single mapping-table. You should apply these mappings before processing
> * the read input events.
> *
> * @returns 0 on success, negative error code on failure
> *
> * @memberof inmap_evdev
> */
> int inmap_evdev_get_mapping(struct inmap_evdev *evdev,
> struct inmap_mapping **out,
> unsigned int caps);
>
> /** @} */
>
> /**
> * @defgroup mapping Event mapping
> * Mapping linux input-events
> *
> * @{
> */
>
> /**
> * Increase ref-count of mapping table
> *
> * @param[in] map Valid mapping table, or NULL
> *
> * Increase ref-count of @map by 1. Does nothing if @map is NULL.
> *
> * @memberof inmap_mapping
> */
> void inmap_mapping_ref(struct inmap_mapping *map);
>
> /**
> * Decrease ref-count of mapping table
> *
> * @param[in] map Valid mapping table, or NULL
> *
> * Decrease ref-count of @map by 1. Destroys the object iff the ref-count
> * drops to 0. Does nothing if @map is NULL.
> *
> * @memberof inmap_mapping
> */
> void inmap_mapping_unref(struct inmap_mapping *map);
>
> /**
> * Map linux input-event
> *
> * @param[in] map Valid mapping table, or NULL
> * @param[in,out] event Linux input event
> *
> * Map the input-event in @event according to the rules in @map. If @map is
> * NULL no mapping is applied.
> * The mapping is performed inline, so @event will be modified by this
> * function.
> *
> * @memberof inmap_mapping
> */
> void inmap_mapping_map(struct inmap_mapping *map,
> struct input_event *event);
>
> /** @} */
>
> #ifdef __cplusplus
> }
> #endif
>
> #endif /* INMAP_H */
More information about the wayland-devel
mailing list