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

« back to all changes in this revision

Viewing changes to src/uevent.c

  • Committer: Michael Vogt
  • Date: 2012-01-18 08:35:33 UTC
  • Revision ID: michael.vogt@ubuntu.com-20120118083533-o80f4tfc13k9e587
add support to apply patches when running the release upgrader

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