7
#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
8
#include <gudev/gudev.h>
9
#include <sys/utsname.h>
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,
18
gchar *hplip_helper[] = { "/usr/bin/hp-plugin-ubuntu", NULL };
21
g_debug_uevent(const char *msg, ...)
25
g_logv("uevent",G_LOG_LEVEL_DEBUG, msg, va);
30
deal_with_hplip_firmware(GUdevDevice *device)
32
const gchar *id_vendor, *id_product, *id_model;
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);
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)
44
if (id_product[2] != '1' || id_product[3] != '7')
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))
52
g_warning("error calling hp-mkuri");
56
// check return codes, 2 & 5 indicate that it has the firmware already
57
if (WEXITSTATUS(ret) != 2 && WEXITSTATUS(ret) != 5)
59
g_debug_uevent ("hp-mkuri indicates no firmware needed");
63
if (!g_spawn_async("/", hplip_helper, NULL, 0, NULL, NULL, NULL, NULL))
65
g_warning("error calling hplip_helper");
72
deal_with_missing_firmware(GUdevDevice *device)
76
gboolean found = FALSE;
77
const gchar* firmware_file;
79
firmware_file = g_udev_device_get_property (device, "FIRMWARE");
82
g_debug_uevent ("deal_with_missing_firmware: discarding, no FIRMWARE property");
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");
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);
110
static gboolean scp_checked = FALSE;
113
deal_with_scp(GUdevDevice *device)
115
GError *error = NULL;
117
/* only do this once */
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));
129
g_debug_uevent ("deal_with_scp: devpath=%s: printer identified", g_udev_device_get_sysfs_path(device));
133
gchar* ps_argv[] = {"ps", "h", "-ocommand", "-Cpython", NULL};
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);
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");
147
g_debug_uevent ("deal_with_scp: launching system-config-printer");
148
gchar* scp_argv[] = {"system-config-printer-applet", 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);
159
on_uevent (GUdevClient *client,
164
g_debug_uevent ("uevent.c on_uevent: action=%s, devpath=%s", action, g_udev_device_get_sysfs_path(device));
166
if (g_strcmp0 (action, "add") != 0 && g_strcmp0 (action, "change") != 0)
169
/* handle firmware */
170
if (deal_with_hplip_firmware(device))
173
if (deal_with_missing_firmware(device))
177
if (deal_with_scp(device))
185
const gchar* subsytems[] = {"firmware", "usb", NULL};
187
/* build firmware search path */
189
if (uname (&u) != 0) {
190
g_warning("uname() failed, not monitoring firmware");
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);
196
GUdevClient* gudev = g_udev_client_new (subsytems);
197
g_signal_connect (gudev, "uevent", G_CALLBACK (on_uevent), NULL);
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);
205
deal_with_scp(elem->data);
207
g_object_unref(elem->data);
209
g_list_free(usb_devices);
216
g_warning("Installation of firmware disabled.");