17
17
with this program. If not, see <http://www.gnu.org/licenses/>.
20
#include <gudev/gudev.h>
20
28
#include "udev-mgr.h"
29
#include "sane-rules.h"
31
static void udevice_mgr_device_list_iterator (gpointer data,
33
static void udev_mgr_uevent_cb (GUdevClient *client,
37
static void udev_mgr_update_menuitems (UdevMgr* self);
38
static void udev_mgr_check_if_usb_device_is_supported (UdevMgr* self,
40
UdevMgrDeviceAction action);
41
static void udev_mgr_handle_webcam (UdevMgr* self,
43
UdevMgrDeviceAction action);
44
static void udev_mgr_handle_scsi_device (UdevMgr* self,
46
UdevMgrDeviceAction action);
48
static void udev_mgr_cleanup_lists(gpointer data, gpointer self);
49
static void udev_mgr_cleanup_entries(gpointer data, gpointer self);
52
static void debug_device (UdevMgr* self,
54
UdevMgrDeviceAction action);
59
GObject parent_instance;
60
DbusmenuMenuitem* scanner_item;
61
DbusmenuMenuitem* webcam_item;
63
GHashTable* supported_usb_scanners;
64
GHashTable* supported_scsi_scanners;
65
GHashTable* scanners_present;
66
GHashTable* webcams_present;
69
const char *subsystems[3] = {"usb", "scsi", "video4linux"};
70
const gchar* usb_subsystem = "usb";
71
const gchar* scsi_subsystem = "scsi";
72
const gchar* video4linux_subsystem = "video4linux";
23
75
G_DEFINE_TYPE (UdevMgr, udev_mgr, G_TYPE_OBJECT);
26
udev_mgr_init (UdevMgr *object)
28
/* TODO: Add initialization code here */
78
udev_mgr_init (UdevMgr* self)
81
self->supported_usb_scanners = NULL;
82
self->scanners_present = NULL;
83
self->webcams_present = NULL;
84
self->client = g_udev_client_new (subsystems);
85
self->supported_usb_scanners = g_hash_table_new_full (g_str_hash,
88
(GDestroyNotify)udev_mgr_cleanup_lists);
89
self->supported_scsi_scanners = g_hash_table_new_full (g_str_hash,
92
(GDestroyNotify)udev_mgr_cleanup_lists);
93
self->scanners_present = g_hash_table_new_full (g_str_hash,
97
self->webcams_present = g_hash_table_new_full (g_str_hash,
102
// load into memory all supported scanners ...
103
populate_usb_scanners (self->supported_usb_scanners);
104
populate_scsi_scanners (self->supported_scsi_scanners);
105
g_signal_connect (G_OBJECT (self->client),
107
G_CALLBACK (udev_mgr_uevent_cb),
112
udev_mgr_cleanup_lists(gpointer data, gpointer self)
114
GList* scanners = (GList*)data;
115
g_list_foreach (scanners, udev_mgr_cleanup_entries, NULL);
116
g_list_free(scanners);
120
udev_mgr_cleanup_entries(gpointer data, gpointer self)
122
gchar* entry = (gchar*)data;
32
127
udev_mgr_finalize (GObject *object)
34
/* TODO: Add deinitalization code here */
129
UdevMgr* self = UDEV_MGR (object);
130
g_hash_table_destroy (self->supported_scsi_scanners);
131
g_hash_table_destroy (self->supported_usb_scanners);
132
g_hash_table_destroy (self->scanners_present);
133
g_hash_table_destroy (self->webcams_present);
36
134
G_OBJECT_CLASS (udev_mgr_parent_class)->finalize (object);
40
138
udev_mgr_class_init (UdevMgrClass *klass)
42
140
GObjectClass* object_class = G_OBJECT_CLASS (klass);
44
141
object_class->finalize = udev_mgr_finalize;
145
udevice_mgr_device_list_iterator (gpointer data, gpointer userdata)
147
g_return_if_fail (G_UDEV_IS_DEVICE (data));
148
g_return_if_fail (UDEV_IS_MGR (userdata));
150
UdevMgr* self = UDEV_MGR (userdata);
152
GUdevDevice* device = G_UDEV_DEVICE (data);
154
const gchar* subsystem = NULL;
155
subsystem = g_udev_device_get_subsystem (device);
157
if (g_strcmp0 (subsystem, "usb") == 0){
158
udev_mgr_check_if_usb_device_is_supported (self, device, ADD);
160
else if (g_strcmp0 (subsystem, "video4linux") == 0){
161
udev_mgr_handle_webcam (self, device, ADD);
163
else if (g_strcmp0 (subsystem, "scsi") == 0){
164
udev_mgr_handle_scsi_device (self, device, ADD);
167
g_object_unref (device);
171
static void udev_mgr_update_menuitems (UdevMgr* self)
173
dbusmenu_menuitem_property_set_bool (self->scanner_item,
174
DBUSMENU_MENUITEM_PROP_VISIBLE,
175
g_hash_table_size (self->scanners_present) > 0);
177
dbusmenu_menuitem_property_set_bool (self->webcam_item,
178
DBUSMENU_MENUITEM_PROP_VISIBLE,
179
g_hash_table_size (self->webcams_present) > 0);
183
static void udev_mgr_uevent_cb (GUdevClient *client,
188
g_return_if_fail (UDEV_IS_MGR (user_data));
189
UdevMgr* self = UDEV_MGR (user_data);
190
g_return_if_fail (device != NULL);
192
g_debug ("just received a UEVENT with an action : %s", action);
194
UdevMgrDeviceAction udev_mgr_action = ADD;
196
if (g_strcmp0 (action, "remove") == 0){
197
udev_mgr_action = REMOVE;
200
const gchar* subsystem = NULL;
201
subsystem = g_udev_device_get_subsystem (device);
203
if (g_strcmp0 (subsystem, "usb") == 0){
204
udev_mgr_check_if_usb_device_is_supported (self,
208
else if (g_strcmp0 (subsystem, "video4linux") == 0){
209
udev_mgr_handle_webcam (self, device, udev_mgr_action);
211
else if (g_strcmp0 (subsystem, "scsi") == 0){
212
udev_mgr_handle_scsi_device (self, device, udev_mgr_action);
218
udev_mgr_handle_webcam (UdevMgr* self,
220
UdevMgrDeviceAction action)
223
debug_device (self, device, action);
226
const gchar* product;
228
vendor = g_udev_device_get_property (device, "ID_VENDOR_ID");
229
product = g_udev_device_get_property (device, "ID_MODEL_ID");
231
if (action == REMOVE){
232
if (g_hash_table_lookup (self->webcams_present, product) == NULL){
233
g_warning ("Got a remove event on a webcam device but we don't have that device in our webcam cache");
236
g_hash_table_remove (self->webcams_present,
241
if (g_hash_table_lookup (self->webcams_present, product) != NULL){
242
g_warning ("Got an ADD event on a webcam device but we already have that device in our webcam cache");
245
g_hash_table_insert (self->webcams_present,
249
udev_mgr_update_menuitems (self);
253
debug_device (UdevMgr* self,
255
UdevMgrDeviceAction action)
258
const gchar* product;
262
vendor = g_udev_device_get_property (device, "ID_VENDOR_ID");
263
product = g_udev_device_get_property (device, "ID_MODEL_ID");
264
number = g_udev_device_get_number (device);
265
name = g_udev_device_get_name (device);
267
g_debug ("device vendor id %s , product id of %s , number of %s and name of %s",
273
const gchar *const *list;
274
const gchar *const *iter;
276
guint32 namelen = 0, i;
278
list = g_udev_device_get_property_keys(device);
280
for (iter = list; iter && *iter; iter++) {
281
if (strlen(*iter) > namelen)
282
namelen = strlen(*iter);
286
for (iter = list; iter && *iter; iter++) {
287
strcpy(propstr, *iter);
288
strcat(propstr, ":");
289
for (i = 0; i < namelen - strlen(*iter); i++)
290
strcat(propstr, " ");
291
strcat(propstr, g_udev_device_get_property(device, *iter));
292
g_debug("%s", propstr);
296
static void udev_mgr_handle_scsi_device (UdevMgr* self,
298
UdevMgrDeviceAction action)
300
const gchar* type = NULL;
301
type = g_udev_device_get_property (device, "TYPE");
302
// apparently anything thats type 3 and SCSI is a Scanner
303
if (g_strcmp0 (type, "6") == 0){
304
gchar* random_scanner_name = g_strdup_printf("%p--scanner", self);
305
g_hash_table_insert (self->scanners_present,
307
g_strdup("Scanner"));
308
udev_mgr_update_menuitems (self);
312
// We only care about type 3 for the special cases below
313
if (g_strcmp0 (type, "3") != 0){
317
const gchar* vendor = NULL;
318
vendor = g_udev_device_get_property (device, "VENDOR");
323
GList* vendor_list = NULL;
324
vendor_list = g_hash_table_lookup (self->supported_scsi_scanners,
326
if (vendor_list == NULL)
329
const gchar* model_id = NULL;
330
model_id = g_udev_device_get_property (device, "MODEL");
332
if (model_id == NULL)
335
GList* model_entry = NULL;
336
model_entry = g_list_find_custom (vendor_list,
338
(GCompareFunc)g_strcmp0);
340
if (model_entry != NULL){
341
if (action == REMOVE){
342
if (g_hash_table_lookup (self->scanners_present, g_strdup(vendor)) == NULL){
343
g_warning ("Got an REMOVE event on a scanner device but we dont have that device in our scanners cache");
346
g_hash_table_remove (self->scanners_present, vendor);
350
if (g_hash_table_lookup (self->scanners_present, g_strdup(vendor)) != NULL){
351
g_warning ("Got an ADD event on a scanner device but we already have that device in our scanners cache");
354
g_hash_table_insert (self->scanners_present,
359
udev_mgr_update_menuitems (self);
364
udev_mgr_check_if_usb_device_is_supported (UdevMgr* self,
366
UdevMgrDeviceAction action)
368
const gchar* vendor = NULL;
369
debug_device (self, device, action);
371
vendor = g_udev_device_get_property (device, "ID_VENDOR_ID");
376
//g_debug ("vendor = %s", vendor);
378
GList* vendor_list = NULL;
379
vendor_list = g_hash_table_lookup (self->supported_usb_scanners,
381
if (vendor_list == NULL)
384
const gchar* model_id = NULL;
385
model_id = g_udev_device_get_property (device, "ID_MODEL_ID");
387
if (model_id == NULL)
390
GList* model_entry = NULL;
391
model_entry = g_list_find_custom(vendor_list, model_id, (GCompareFunc)g_strcmp0);
393
if (model_entry != NULL){
394
if (action == REMOVE){
395
if (g_hash_table_lookup (self->scanners_present, g_strdup(vendor)) == NULL){
396
g_warning ("Got an REMOVE event on a scanner device but we dont have that device in our scanners cache");
399
g_hash_table_remove (self->scanners_present, vendor);
403
if (g_hash_table_lookup (self->scanners_present, g_strdup(vendor)) != NULL){
404
g_warning ("Got an ADD event on a scanner device but we already have that device in our scanners cache");
407
g_hash_table_insert (self->scanners_present,
412
udev_mgr_update_menuitems (self);
416
UdevMgr* udev_mgr_new (DbusmenuMenuitem* scanner,
417
DbusmenuMenuitem* webcam)
419
UdevMgr* mgr = g_object_new (UDEV_TYPE_MGR, NULL);
420
mgr->scanner_item = scanner;
421
mgr->webcam_item = webcam;
423
// Check for USB devices
424
GList* usb_devices_available = NULL;
425
usb_devices_available = g_udev_client_query_by_subsystem (mgr->client,
427
if (usb_devices_available != NULL){
428
g_list_foreach (usb_devices_available,
429
udevice_mgr_device_list_iterator,
432
g_list_free (usb_devices_available);
435
GList* video_devices_available = NULL;
436
video_devices_available = g_udev_client_query_by_subsystem (mgr->client,
437
video4linux_subsystem);
438
if (video_devices_available != NULL){
439
g_list_foreach (video_devices_available,
440
udevice_mgr_device_list_iterator,
443
g_list_free (video_devices_available);
445
// Check for SCSI devices
446
GList* scsi_devices_available = NULL;
447
scsi_devices_available = g_udev_client_query_by_subsystem (mgr->client,
449
if (scsi_devices_available != NULL){
450
g_list_foreach (scsi_devices_available,
451
udevice_mgr_device_list_iterator,
453
g_list_free (scsi_devices_available);