0 | |
/*
|
1 | |
* Copyright (C) 2010-2011 Richard Hughes <richard@hughsie.com>
|
2 | |
* Copyright (C) 2012 Bastien Nocera <hadess@hadess.net>
|
3 | |
*
|
4 | |
* Licensed under the GNU General Public License Version 2
|
5 | |
*
|
6 | |
* This program is free software; you can redistribute it and/or modify
|
7 | |
* it under the terms of the GNU General Public License as published by
|
8 | |
* the Free Software Foundation; either version 2 of the License, or
|
9 | |
* (at your option) any later version.
|
10 | |
*
|
11 | |
* This program is distributed in the hope that it will be useful,
|
12 | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14 | |
* GNU General Public License for more details.
|
15 | |
*
|
16 | |
* You should have received a copy of the GNU General Public License
|
17 | |
* along with this program; if not, write to the Free Software
|
18 | |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
19 | |
*/
|
20 | |
|
21 | |
#include "config.h"
|
22 | |
|
23 | |
#include <glib.h>
|
24 | |
#include <locale.h>
|
25 | |
#include <unistd.h>
|
26 | |
#include <sys/types.h>
|
27 | |
#include <sys/stat.h>
|
28 | |
#include <fcntl.h>
|
29 | |
#include <string.h>
|
30 | |
#include <gudev/gudev.h>
|
31 | |
|
32 | |
static gboolean
|
33 | |
csd_wacom_led_helper_write (const gchar *filename, gint value, GError **error)
|
34 | |
{
|
35 | |
gchar *text = NULL;
|
36 | |
gint retval;
|
37 | |
gint length;
|
38 | |
gint fd = -1;
|
39 | |
gboolean ret = TRUE;
|
40 | |
|
41 | |
fd = open (filename, O_WRONLY);
|
42 | |
if (fd < 0) {
|
43 | |
ret = FALSE;
|
44 | |
g_set_error (error, 1, 0, "failed to open filename: %s", filename);
|
45 | |
goto out;
|
46 | |
}
|
47 | |
|
48 | |
/* convert to text */
|
49 | |
text = g_strdup_printf ("%i", value);
|
50 | |
length = strlen (text);
|
51 | |
|
52 | |
/* write to device file */
|
53 | |
retval = write (fd, text, length);
|
54 | |
if (retval != length) {
|
55 | |
ret = FALSE;
|
56 | |
g_set_error (error, 1, 0, "writing '%s' to %s failed", text, filename);
|
57 | |
goto out;
|
58 | |
}
|
59 | |
out:
|
60 | |
if (fd >= 0)
|
61 | |
close (fd);
|
62 | |
g_free (text);
|
63 | |
return ret;
|
64 | |
}
|
65 | |
|
66 | |
static char *
|
67 | |
get_led_sysfs_path (GUdevDevice *device,
|
68 | |
int group_num)
|
69 | |
{
|
70 | |
char *status;
|
71 | |
char *filename;
|
72 | |
|
73 | |
status = g_strdup_printf ("status_led%d_select", group_num);
|
74 | |
filename = g_build_filename (g_udev_device_get_sysfs_path (device), "wacom_led", status, NULL);
|
75 | |
g_free (status);
|
76 | |
|
77 | |
return filename;
|
78 | |
}
|
79 | |
|
80 | |
static char *path = NULL;
|
81 | |
static int group_num = -1;
|
82 | |
static int led_num = -1;
|
83 | |
|
84 | |
const GOptionEntry options[] = {
|
85 | |
{ "path", '\0', 0, G_OPTION_ARG_FILENAME, &path, "Device path for the Wacom device", NULL },
|
86 | |
{ "group", '\0', 0, G_OPTION_ARG_INT, &group_num, "Which LED group to set", NULL },
|
87 | |
{ "led", '\0', 0, G_OPTION_ARG_INT, &led_num, "Which LED to set", NULL },
|
88 | |
{ NULL}
|
89 | |
};
|
90 | |
|
91 | |
|
92 | |
int main (int argc, char **argv)
|
93 | |
{
|
94 | |
GOptionContext *context;
|
95 | |
GUdevClient *client;
|
96 | |
GUdevDevice *device, *parent;
|
97 | |
int uid, euid;
|
98 | |
char *filename;
|
99 | |
GError *error = NULL;
|
100 | |
const char * const subsystems[] = { "input", NULL };
|
101 | |
|
102 | |
/* get calling process */
|
103 | |
uid = getuid ();
|
104 | |
euid = geteuid ();
|
105 | |
if (uid != 0 || euid != 0) {
|
106 | |
g_print ("This program can only be used by the root user\n");
|
107 | |
return 1;
|
108 | |
}
|
109 | |
|
110 | |
context = g_option_context_new (NULL);
|
111 | |
g_option_context_set_summary (context, "Cinnamon Settings Daemon Digitizer LED Helper");
|
112 | |
g_option_context_add_main_entries (context, options, NULL);
|
113 | |
g_option_context_parse (context, &argc, &argv, NULL);
|
114 | |
|
115 | |
if (path == NULL ||
|
116 | |
group_num < 0 ||
|
117 | |
led_num < 0) {
|
118 | |
char *txt;
|
119 | |
|
120 | |
txt = g_option_context_get_help (context, FALSE, NULL);
|
121 | |
g_print ("%s", txt);
|
122 | |
g_free (txt);
|
123 | |
|
124 | |
g_option_context_free (context);
|
125 | |
|
126 | |
return 1;
|
127 | |
}
|
128 | |
g_option_context_free (context);
|
129 | |
|
130 | |
client = g_udev_client_new (subsystems);
|
131 | |
device = g_udev_client_query_by_device_file (client, path);
|
132 | |
if (device == NULL) {
|
133 | |
g_debug ("Could not find device '%s' in udev database", path);
|
134 | |
goto bail;
|
135 | |
}
|
136 | |
|
137 | |
if (g_udev_device_get_property_as_boolean (device, "ID_INPUT_TABLET") == FALSE &&
|
138 | |
g_udev_device_get_property_as_boolean (device, "ID_INPUT_TOUCHPAD") == FALSE) {
|
139 | |
g_debug ("Device '%s' is not a Wacom tablet", path);
|
140 | |
goto bail;
|
141 | |
}
|
142 | |
|
143 | |
if (g_strcmp0 (g_udev_device_get_property (device, "ID_BUS"), "usb") != 0) {
|
144 | |
/* FIXME handle Bluetooth LEDs too */
|
145 | |
g_debug ("Non-USB LEDs setting is not supported");
|
146 | |
goto bail;
|
147 | |
}
|
148 | |
|
149 | |
parent = g_udev_device_get_parent_with_subsystem (device, "usb", "usb_interface");
|
150 | |
if (parent == NULL) {
|
151 | |
g_debug ("Could not find parent USB device for '%s'", path);
|
152 | |
goto bail;
|
153 | |
}
|
154 | |
g_object_unref (device);
|
155 | |
device = parent;
|
156 | |
|
157 | |
filename = get_led_sysfs_path (device, group_num);
|
158 | |
if (csd_wacom_led_helper_write (filename, led_num, &error) == FALSE) {
|
159 | |
g_debug ("Could not set LED status for '%s': %s", path, error->message);
|
160 | |
g_error_free (error);
|
161 | |
g_free (filename);
|
162 | |
goto bail;
|
163 | |
}
|
164 | |
g_free (filename);
|
165 | |
|
166 | |
g_debug ("Successfully set LED status for '%s', group %d to %d",
|
167 | |
path, group_num, led_num);
|
168 | |
|
169 | |
g_object_unref (device);
|
170 | |
g_object_unref (client);
|
171 | |
|
172 | |
return 0;
|
173 | |
|
174 | |
bail:
|
175 | |
if (device != NULL)
|
176 | |
g_object_unref (device);
|
177 | |
if (client != NULL)
|
178 | |
g_object_unref (client);
|
179 | |
return 1;
|
180 | |
}
|