~elementary-os/elementaryos/os-patch-gnome-settings-daemon-xenial

« back to all changes in this revision

Viewing changes to plugins/wacom/gsd-wacom-led-helper.c

  • Committer: RabbitBot
  • Date: 2016-05-13 19:33:51 UTC
  • Revision ID: rabbitbot@elementary.io-20160513193351-owr76om3z9f4mvv3
Initial import, version 3.18.2-0ubuntu3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010-2011 Richard Hughes <richard@hughsie.com>
 
3
 * Copyright (C) 2012      Bastien Nocera <hadess@hadess.net>
 
4
 *
 
5
 * Licensed under the GNU General Public License Version 2
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as published by
 
9
 * the Free Software Foundation; either version 2 of the License, or
 
10
 * (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
20
 */
 
21
 
 
22
#include "config.h"
 
23
 
 
24
#include <glib.h>
 
25
#include <locale.h>
 
26
#include <unistd.h>
 
27
#include <sys/types.h>
 
28
#include <sys/stat.h>
 
29
#include <fcntl.h>
 
30
#include <string.h>
 
31
#include <gudev/gudev.h>
 
32
 
 
33
#define LED_BRIGHTNESS 127 /* maximum brightness accepted by led on wacom Intuos4 connected over Bluetooth */
 
34
 
 
35
static int
 
36
gsd_wacom_led_helper_write (const gchar *filename, gint value, GError **error)
 
37
{
 
38
        gchar *text = NULL;
 
39
        gint retval;
 
40
        gint length;
 
41
        gint fd = -1;
 
42
        int ret = 1;
 
43
 
 
44
        fd = open (filename, O_WRONLY);
 
45
        if (fd < 0) {
 
46
                g_set_error (error, 1, 0, "failed to open filename: %s", filename);
 
47
                goto out;
 
48
        }
 
49
 
 
50
        /* convert to text */
 
51
        text = g_strdup_printf ("%i", value);
 
52
        length = strlen (text);
 
53
 
 
54
        /* write to device file */
 
55
        retval = write (fd, text, length);
 
56
        if (retval != length) {
 
57
                g_set_error (error, 1, 0, "writing '%s' to %s failed", text, filename);
 
58
                goto out;
 
59
        } else
 
60
                ret = 0;
 
61
out:
 
62
        if (fd >= 0)
 
63
                close (fd);
 
64
        g_free (text);
 
65
        return ret;
 
66
}
 
67
 
 
68
static char *
 
69
get_led_sys_path (GUdevClient *client,
 
70
                  GUdevDevice *device,
 
71
                  int          group_num,
 
72
                  int          led_num,
 
73
                  gboolean     usb,
 
74
                  int         *write_value)
 
75
{
 
76
        GUdevDevice *parent;
 
77
        char *status = NULL;
 
78
        char *filename = NULL;
 
79
        GUdevDevice *hid_dev;
 
80
        const char *dev_uniq;
 
81
        GList *hid_list;
 
82
        GList *element;
 
83
        const char *dev_hid_uniq;
 
84
 
 
85
        /* check for new unified hid implementation first */
 
86
        parent = g_udev_device_get_parent_with_subsystem (device, "hid", NULL);
 
87
        if (parent) {
 
88
                status = g_strdup_printf ("status_led%d_select", group_num);
 
89
                filename = g_build_filename (g_udev_device_get_sysfs_path (parent), "wacom_led", status, NULL);
 
90
                g_free (status);
 
91
                g_object_unref (parent);
 
92
                if(g_file_test (filename, G_FILE_TEST_EXISTS)) {
 
93
                        *write_value = led_num;
 
94
                        return filename;
 
95
                }
 
96
                g_clear_pointer (&filename, g_free);
 
97
        }
 
98
 
 
99
        /* old kernel */
 
100
        if (usb) {
 
101
                parent = g_udev_device_get_parent_with_subsystem (device, "usb", "usb_interface");
 
102
                if (!parent)
 
103
                        goto no_parent;
 
104
                status = g_strdup_printf ("status_led%d_select", group_num);
 
105
                filename = g_build_filename (g_udev_device_get_sysfs_path (parent), "wacom_led", status, NULL);
 
106
                g_free (status);
 
107
 
 
108
                *write_value = led_num;
 
109
         } else {
 
110
                parent = g_udev_device_get_parent_with_subsystem (device, "input", NULL);
 
111
                if (!parent)
 
112
                        goto no_parent;
 
113
                dev_uniq = g_udev_device_get_property (parent, "UNIQ");
 
114
 
 
115
                hid_list =  g_udev_client_query_by_subsystem (client, "hid");
 
116
                element = g_list_first(hid_list);
 
117
                while (element) {
 
118
                        hid_dev = (GUdevDevice*)element->data;
 
119
                        dev_hid_uniq = g_udev_device_get_property (hid_dev, "HID_UNIQ");
 
120
                        if (g_strrstr (dev_uniq, dev_hid_uniq)){
 
121
                                status = g_strdup_printf ("/leds/%s:selector:%i/brightness", g_udev_device_get_name (hid_dev), led_num);
 
122
                                filename = g_build_filename (g_udev_device_get_sysfs_path (hid_dev), status, NULL);
 
123
                                g_free (status);
 
124
                                break;
 
125
                        }
 
126
                        element = g_list_next(element);
 
127
                }
 
128
                g_list_free_full(hid_list, g_object_unref);
 
129
 
 
130
                *write_value = LED_BRIGHTNESS;
 
131
        }
 
132
 
 
133
        g_object_unref (parent);
 
134
 
 
135
        return filename;
 
136
 
 
137
no_parent:
 
138
        g_debug ("Could not find proper parent device for '%s'",
 
139
                 g_udev_device_get_device_file (device));
 
140
 
 
141
        return NULL;
 
142
}
 
143
 
 
144
int main (int argc, char **argv)
 
145
{
 
146
        GOptionContext *context;
 
147
        GUdevClient *client;
 
148
        GUdevDevice *device;
 
149
        int uid, euid;
 
150
        char *filename;
 
151
        gboolean usb;
 
152
        int value;
 
153
        GError *error = NULL;
 
154
        const char * const subsystems[] = { "hid", "input", NULL };
 
155
        int ret = 1;
 
156
 
 
157
        char *path = NULL;
 
158
        int group_num = -1;
 
159
        int led_num = -1;
 
160
 
 
161
        const GOptionEntry options[] = {
 
162
                { "path", '\0', 0, G_OPTION_ARG_FILENAME, &path, "Device path for the Wacom device", NULL },
 
163
                { "group", '\0', 0, G_OPTION_ARG_INT, &group_num, "Which LED group to set", NULL },
 
164
                { "led", '\0', 0, G_OPTION_ARG_INT, &led_num, "Which LED to set", NULL },
 
165
                { NULL}
 
166
        };
 
167
 
 
168
        /* get calling process */
 
169
        uid = getuid ();
 
170
        euid = geteuid ();
 
171
        if (uid != 0 || euid != 0) {
 
172
                g_print ("This program can only be used by the root user\n");
 
173
                return 1;
 
174
        }
 
175
 
 
176
        context = g_option_context_new (NULL);
 
177
        g_option_context_set_summary (context, "GNOME Settings Daemon Wacom LED Helper");
 
178
        g_option_context_add_main_entries (context, options, NULL);
 
179
        g_option_context_parse (context, &argc, &argv, NULL);
 
180
 
 
181
        if (path == NULL ||
 
182
            group_num < 0 ||
 
183
            led_num < 0) {
 
184
                char *txt;
 
185
 
 
186
                txt = g_option_context_get_help (context, FALSE, NULL);
 
187
                g_print ("%s", txt);
 
188
                g_free (txt);
 
189
 
 
190
                g_option_context_free (context);
 
191
 
 
192
                return 1;
 
193
        }
 
194
        g_option_context_free (context);
 
195
 
 
196
        client = g_udev_client_new (subsystems);
 
197
        device = g_udev_client_query_by_device_file (client, path);
 
198
        if (device == NULL) {
 
199
                g_debug ("Could not find device '%s' in udev database", path);
 
200
                goto out;
 
201
        }
 
202
 
 
203
        if (g_udev_device_get_property_as_boolean (device, "ID_INPUT_TABLET") == FALSE &&
 
204
            g_udev_device_get_property_as_boolean (device, "ID_INPUT_TOUCHPAD") == FALSE) {
 
205
                g_debug ("Device '%s' is not a Wacom tablet", path);
 
206
                goto out;
 
207
        }
 
208
 
 
209
        if (g_strcmp0 (g_udev_device_get_property (device, "ID_BUS"), "usb") != 0)
 
210
                usb = FALSE;
 
211
        else
 
212
                usb = TRUE;
 
213
 
 
214
        filename = get_led_sys_path (client, device, group_num, led_num, usb, &value);
 
215
        if (!filename)
 
216
                goto out;
 
217
 
 
218
        if (gsd_wacom_led_helper_write (filename, value, &error)) {
 
219
                g_debug ("Could not set LED status for '%s': %s", path, error->message);
 
220
                g_error_free (error);
 
221
                g_free (filename);
 
222
                goto out;
 
223
        }
 
224
        g_free (filename);
 
225
 
 
226
        g_debug ("Successfully set LED status for '%s', group %d to %d",
 
227
                 path, group_num, led_num);
 
228
 
 
229
        ret = 0;
 
230
 
 
231
out:
 
232
        g_free (path);
 
233
        g_clear_object (&device);
 
234
        g_clear_object (&client);
 
235
 
 
236
        return ret;
 
237
}