9
#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
10
#include <gudev/gudev.h>
11
#include <sys/utsname.h>
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,
20
gchar *hplip_helper[] = { "/usr/bin/hp-plugin-ubuntu", NULL };
23
g_debug_uevent(const char *msg, ...)
27
g_logv("uevent",G_LOG_LEVEL_DEBUG, msg, va);
32
deal_with_hplip_firmware(GUdevDevice *device)
34
const gchar *id_vendor, *id_product, *id_model;
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);
43
// only idVendor=03f0, idProduct="??{17,2a}" requires firmware
44
if (g_strcmp0 (id_vendor, "03f0") != 0 ||
46
g_utf8_strlen(id_product, -1) != 4)
48
if (! ( ((id_product[2] == '1') && (id_product[3] == '7')) ||
49
((id_product[2] == '2') && (tolower(id_product[3]) == 'a')) ))
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))
57
g_warning("error calling hp-mkuri");
61
// check return codes, 2 & 5 indicate that it has the firmware already
62
if (WEXITSTATUS(ret) != 2 && WEXITSTATUS(ret) != 5)
64
g_debug_uevent ("hp-mkuri indicates no firmware needed");
68
if (!g_spawn_async("/", hplip_helper, NULL, 0, NULL, NULL, NULL, NULL))
70
g_warning("error calling hplip_helper");
77
deal_with_missing_firmware(GUdevDevice *device)
81
gboolean found = FALSE;
82
const gchar* firmware_file;
84
firmware_file = g_udev_device_get_property (device, "FIRMWARE");
87
g_debug_uevent ("deal_with_missing_firmware: discarding, no FIRMWARE property");
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");
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);
115
static gboolean scp_checked = FALSE;
118
deal_with_scp(GUdevDevice *device)
120
GError *error = NULL;
122
/* only do this once */
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));
134
g_debug_uevent ("deal_with_scp: devpath=%s: printer identified", g_udev_device_get_sysfs_path(device));
138
gchar* ps_argv[] = {"ps", "h", "-ocommand", "-Cpython", NULL};
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);
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");
152
g_debug_uevent ("deal_with_scp: launching system-config-printer");
153
gchar* scp_argv[] = {"system-config-printer-applet", 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);
164
on_uevent (GUdevClient *client,
169
g_debug_uevent ("uevent.c on_uevent: action=%s, devpath=%s", action, g_udev_device_get_sysfs_path(device));
171
if (g_strcmp0 (action, "add") != 0 && g_strcmp0 (action, "change") != 0)
174
/* handle firmware */
175
if (deal_with_hplip_firmware(device))
178
if (deal_with_missing_firmware(device))
182
if (deal_with_scp(device))
190
const gchar* subsytems[] = {"firmware", "usb", NULL};
192
/* build firmware search path */
194
if (uname (&u) != 0) {
195
g_warning("uname() failed, not monitoring firmware");
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);
201
GUdevClient* gudev = g_udev_client_new (subsytems);
202
g_signal_connect (gudev, "uevent", G_CALLBACK (on_uevent), NULL);
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);
210
deal_with_scp(elem->data);
212
g_object_unref(elem->data);
214
g_list_free(usb_devices);
221
g_warning("Installation of firmware disabled.");