~ubuntu-core-dev/update-notifier/ubuntu

« back to all changes in this revision

Viewing changes to src/uevent.c

  • Committer: seb128
  • Date: 2009-06-26 16:07:39 UTC
  • mto: This revision was merged to the branch mainline in revision 465.
  • Revision ID: seb128@seb128-laptop-20090626160739-hs300xxw3o75mz4s
clean libglade use

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#ifdef HAVE_CONFIG_H
2
 
#include "config.h"
3
 
#endif
4
 
#ifdef HAVE_GUDEV
5
 
#include <sys/wait.h>
6
 
 
7
 
#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
8
 
#include <gudev/gudev.h>
9
 
#include <sys/utsname.h>
10
 
 
11
 
/* search path for firmare; second and fourth element are dynamically constructed
12
 
 * in uevent_init(). */
13
 
const gchar* firmware_search_path[] = {
14
 
    "/lib/firmware", NULL,
15
 
    "/lib/firmware/updates", NULL,
16
 
    NULL };
17
 
 
18
 
gchar *hplip_helper[] = { "/usr/bin/hp-plugin-ubuntu", NULL };
19
 
 
20
 
static inline void
21
 
g_debug_uevent(const char *msg, ...)
22
 
{
23
 
   va_list va;
24
 
   va_start(va, msg);
25
 
   g_logv("uevent",G_LOG_LEVEL_DEBUG, msg, va);
26
 
   va_end(va);
27
 
}
28
 
 
29
 
static gboolean
30
 
deal_with_hplip_firmware(GUdevDevice *device)
31
 
{
32
 
    const gchar *id_vendor, *id_product, *id_model;
33
 
    GError *error = NULL;
34
 
    gint ret = 0;
35
 
 
36
 
    id_vendor = g_udev_device_get_sysfs_attr (device, "idVendor");
37
 
    id_product = g_udev_device_get_sysfs_attr (device, "idProduct");
38
 
    id_model = g_udev_device_get_property (device, "ID_MODEL");
39
 
    g_debug_uevent ("uevent.c id_vendor=%s, id_product=%s", id_vendor, id_product);
40
 
 
41
 
    // only idVendor=03f0, idProduct="??17" requires firmware
42
 
    if (g_strcmp0 (id_vendor, "03f0") != 0 || id_product == NULL || g_utf8_strlen(id_product, -1) != 4)
43
 
       return FALSE;
44
 
    if (id_product[2] != '1' || id_product[3] != '7')
45
 
       return FALSE;
46
 
 
47
 
    // firmware is only required if "hp-mkuri -c" returns 2 or 5
48
 
    const gchar *cmd = "/usr/bin/hp-mkuri -c";
49
 
    g_setenv("hp_model", id_model, TRUE);
50
 
    if (!g_spawn_command_line_sync (cmd, NULL, NULL, &ret, &error))
51
 
    {
52
 
       g_warning("error calling hp-mkuri");
53
 
       return FALSE;
54
 
    }
55
 
 
56
 
    // check return codes, 2 & 5 indicate that it has the firmware already
57
 
    if (WEXITSTATUS(ret) != 2 && WEXITSTATUS(ret) != 5) 
58
 
    {
59
 
       g_debug_uevent ("hp-mkuri indicates no firmware needed");
60
 
       return TRUE;
61
 
    }
62
 
 
63
 
    if (!g_spawn_async("/", hplip_helper, NULL, 0, NULL, NULL, NULL, NULL))
64
 
    {
65
 
       g_warning("error calling hplip_helper");
66
 
       return FALSE;
67
 
    }
68
 
    return TRUE;
69
 
}
70
 
 
71
 
static gboolean
72
 
deal_with_missing_firmware(GUdevDevice *device)
73
 
{
74
 
    gchar *path;
75
 
    const gchar **i;
76
 
    gboolean found = FALSE;
77
 
    const gchar* firmware_file;
78
 
 
79
 
    firmware_file = g_udev_device_get_property (device, "FIRMWARE");
80
 
 
81
 
    if (!firmware_file) {
82
 
        g_debug_uevent ("deal_with_missing_firmware: discarding, no FIRMWARE property");
83
 
        return FALSE;
84
 
    }
85
 
 
86
 
    for (i = firmware_search_path; *i && !found; ++i) {
87
 
        path = g_build_path("/", *i, firmware_file, NULL);
88
 
        g_debug_uevent ("deal_with_missing_firmware: searching for %s", path);
89
 
        if (g_file_test (path, G_FILE_TEST_EXISTS)) {
90
 
            g_debug_uevent ("deal_with_missing_firmware: found");
91
 
            found = TRUE;
92
 
        }
93
 
        g_free (path);
94
 
    }
95
 
 
96
 
    if (found)
97
 
        return TRUE;
98
 
 
99
 
    g_debug_uevent ("calling jockey");
100
 
    gchar* argv[] = {"jockey-gtk", "-c", NULL };
101
 
    GError* error = NULL;
102
 
    if (!g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error)) {
103
 
        g_warning("jockey could not be called: %s", error->message);
104
 
        g_error_free (error);
105
 
    }
106
 
    return TRUE;
107
 
}
108
 
 
109
 
#ifdef ENABLE_SCP
110
 
static gboolean scp_checked = FALSE;
111
 
 
112
 
static gboolean
113
 
deal_with_scp(GUdevDevice *device)
114
 
{
115
 
    GError *error = NULL;
116
 
 
117
 
    /* only do this once */
118
 
    if (scp_checked)
119
 
        return FALSE;
120
 
 
121
 
    /* check if we just added a printer */
122
 
    if ((g_strcmp0(g_udev_device_get_sysfs_attr(device, "bInterfaceClass"), "07") != 0 ||
123
 
                g_strcmp0(g_udev_device_get_sysfs_attr(device, "bInterfaceSubClass"), "01") != 0) &&
124
 
            !g_str_has_prefix(g_udev_device_get_name (device), "lp")) {
125
 
        g_debug_uevent ("deal_with_scp: devpath=%s: not a printer", g_udev_device_get_sysfs_path(device));
126
 
        return FALSE;
127
 
    }
128
 
 
129
 
    g_debug_uevent ("deal_with_scp: devpath=%s: printer identified", g_udev_device_get_sysfs_path(device));
130
 
 
131
 
    scp_checked = TRUE;
132
 
 
133
 
    gchar* ps_argv[] = {"ps", "h", "-ocommand", "-Cpython", NULL};
134
 
    gchar* ps_out;
135
 
    if (!g_spawn_sync (NULL, ps_argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
136
 
                &ps_out, NULL, NULL, &error)) {
137
 
        g_warning ("deal_with_scp: error calling ps: %s", error->message);
138
 
        g_error_free (error);
139
 
        return TRUE;
140
 
    }
141
 
    g_debug_uevent ("deal_with_scp: running python processes:\n%s", ps_out);
142
 
    if (strstr (ps_out, "system-config-printer") != NULL) {
143
 
        g_debug_uevent ("deal_with_scp: system-config-printer already running");
144
 
        return TRUE;
145
 
    }
146
 
 
147
 
    g_debug_uevent ("deal_with_scp: launching system-config-printer");
148
 
    gchar* scp_argv[] = {"system-config-printer-applet", NULL};
149
 
    error = NULL;
150
 
    if (!g_spawn_async(NULL, scp_argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error)) {
151
 
        g_warning("%s could not be called: %s", scp_argv[0], error->message);
152
 
        g_error_free (error);
153
 
    }
154
 
    return TRUE;
155
 
}
156
 
#endif
157
 
 
158
 
static void
159
 
on_uevent (GUdevClient *client,
160
 
           gchar *action,
161
 
           GUdevDevice *device,
162
 
           gpointer user_data)
163
 
{
164
 
    g_debug_uevent ("uevent.c on_uevent: action=%s, devpath=%s", action, g_udev_device_get_sysfs_path(device));
165
 
 
166
 
    if (g_strcmp0 (action, "add") != 0 && g_strcmp0 (action, "change") != 0)
167
 
        return;
168
 
 
169
 
    /* handle firmware */
170
 
    if (deal_with_hplip_firmware(device))
171
 
       return;
172
 
 
173
 
    if (deal_with_missing_firmware(device))
174
 
        return;
175
 
 
176
 
#ifdef ENABLE_SCP
177
 
    if (deal_with_scp(device))
178
 
        return;
179
 
#endif
180
 
}
181
 
 
182
 
void
183
 
uevent_init()
184
 
{
185
 
    const gchar* subsytems[] = {"firmware", "usb", NULL};
186
 
    
187
 
    /* build firmware search path */
188
 
    struct utsname u;
189
 
    if (uname (&u) != 0) {
190
 
        g_warning("uname() failed, not monitoring firmware");
191
 
        return;
192
 
    }
193
 
    firmware_search_path[1] = g_strdup_printf("/lib/firmware/%s", u.release);
194
 
    firmware_search_path[3] = g_strdup_printf("/lib/firmware/updates/%s", u.release);
195
 
 
196
 
    GUdevClient* gudev = g_udev_client_new (subsytems);
197
 
    g_signal_connect (gudev, "uevent", G_CALLBACK (on_uevent), NULL);
198
 
 
199
 
    /* cold plug HPLIP firmware */
200
 
    GList *usb_devices, *elem;
201
 
    usb_devices = g_udev_client_query_by_subsystem (gudev, "usb");
202
 
    for (elem = usb_devices; elem != NULL; elem = g_list_next(elem)) {
203
 
       deal_with_hplip_firmware(elem->data);
204
 
#ifdef ENABLE_SCP
205
 
       deal_with_scp(elem->data);
206
 
#endif
207
 
       g_object_unref(elem->data);
208
 
    }
209
 
    g_list_free(usb_devices);
210
 
}
211
 
#else
212
 
#include <glib.h>
213
 
void
214
 
uevent_init()
215
 
{
216
 
    g_warning("Installation of firmware disabled.");
217
 
}
218
 
#endif // HAVE_GUDEV