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