chiark / gitweb /
udev: Add builtin/rule to export evdev information as udev properties
[elogind.git] / src / udev / udev-builtin-evdev_id.c
1 /*
2  * evdev_id - extracts miscellaneous information from evdev devices
3  *
4  * Copyright (C) 2014 Red Hat
5  * Author:
6  *   Carlos Garnacho  <carlosg@gnome.org>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with keymap; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21  */
22
23 #include <linux/input.h>
24 #include "udev.h"
25 #include "util.h"
26
27 static inline int abs_size_mm(const struct input_absinfo *absinfo) {
28         /* Resolution is defined to be in units/mm for ABS_X/Y */
29         return (absinfo->maximum - absinfo->minimum) / absinfo->resolution;
30 }
31
32 static void extract_info(struct udev_device *dev, const char *devpath, bool test) {
33         char width[DECIMAL_STR_MAX(int)], height[DECIMAL_STR_MAX(int)];
34         struct input_absinfo xabsinfo = {}, yabsinfo = {};
35         _cleanup_close_ int fd = -1;
36
37         fd = open(devpath, O_RDONLY|O_CLOEXEC);
38         if (fd < 0)
39                 return;
40
41         if (ioctl(fd, EVIOCGABS(ABS_X), &xabsinfo) < 0 ||
42             ioctl(fd, EVIOCGABS(ABS_Y), &yabsinfo) < 0)
43                 return;
44
45         if (xabsinfo.resolution <= 0 || yabsinfo.resolution <= 0)
46                 return;
47
48         snprintf(width, sizeof(width), "%d", abs_size_mm(&xabsinfo));
49         snprintf(height, sizeof(height), "%d", abs_size_mm(&yabsinfo));
50
51         udev_builtin_add_property(dev, test, "ID_INPUT_WIDTH_MM", width);
52         udev_builtin_add_property(dev, test, "ID_INPUT_HEIGHT_MM", height);
53 }
54
55 static int builtin_evdev_id(struct udev_device *dev, int argc, char *argv[], bool test) {
56         const char *subsystem;
57         const char *devnode;
58
59         subsystem = udev_device_get_subsystem(dev);
60
61         if (!subsystem || !streq(subsystem, "input"))
62                 return EXIT_SUCCESS;
63
64         devnode = udev_device_get_devnode(dev);
65         /* not an evdev node */
66         if (!devnode)
67                 return EXIT_SUCCESS;
68
69         extract_info(dev, devnode, test);
70
71         return EXIT_SUCCESS;
72 }
73
74 const struct udev_builtin udev_builtin_evdev_id = {
75         .name = "evdev_id",
76         .cmd = builtin_evdev_id,
77         .help = "evdev devices information",
78 };