~ubuntu-branches/debian/sid/hal/sid

« back to all changes in this revision

Viewing changes to hald/linux/device.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2007-10-23 12:33:58 UTC
  • Revision ID: james.westby@ubuntu.com-20071023123358-xaf8mjc5n84d5gtz
Tags: upstream-0.5.10
ImportĀ upstreamĀ versionĀ 0.5.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
44
44
#include <dbus/dbus-glib.h>
45
45
 
46
46
#include "../device_info.h"
 
47
#include "../device_pm.h"
47
48
#include "../device_store.h"
48
49
#include "../hald.h"
 
50
#include "../hald_dbus.h"
49
51
#include "../hald_runner.h"
50
52
#include "../logger.h"
51
53
#include "../osspec.h"
52
54
#include "../util.h"
 
55
#include "../util_pm.h"
53
56
#include "../ids.h"
54
57
 
55
58
#include "coldplug.h"
104
107
        long bitmask[NBITS(REL_MAX)];
105
108
        int num_bits;
106
109
 
107
 
        s = hal_util_get_string_from_file (sysfs_path, "../capabilities/rel");
 
110
        s = hal_util_get_string_from_file (sysfs_path, "capabilities/rel");
108
111
        if (s == NULL)
109
112
                goto out;
110
113
 
118
121
        ;
119
122
}
120
123
 
 
124
static gboolean
 
125
input_test_keyboard (long *bitmask)
 
126
{
 
127
        int i;
 
128
 
 
129
        for (i = KEY_Q; i <= KEY_P; i++) {
 
130
                if (!test_bit (i, bitmask))
 
131
                        return FALSE;
 
132
        }
 
133
 
 
134
        return TRUE;
 
135
}
 
136
 
 
137
static gboolean
 
138
input_test_keypad (long *bitmask)
 
139
{
 
140
        int i;
 
141
 
 
142
        for (i = KEY_KP7; i <= KEY_KPDOT; i++) {
 
143
                if (!test_bit (i, bitmask))
 
144
                        return FALSE;
 
145
        }
 
146
 
 
147
        return TRUE;
 
148
}
 
149
 
 
150
static gboolean
 
151
input_test_keys (long *bitmask)
 
152
{
 
153
        int i;
 
154
 
 
155
        /* All keys that are not buttons are less than BTN_MISC */
 
156
        for (i = KEY_RESERVED + 1; i < BTN_MISC; i++) {
 
157
                if (test_bit (i, bitmask))
 
158
                        return TRUE;
 
159
        }
 
160
 
 
161
        return FALSE;
 
162
}
 
163
 
121
164
static void
122
165
input_test_key (HalDevice *d, const char *sysfs_path)
123
166
{
124
 
        int i;
125
167
        char *s;
126
168
        long bitmask[NBITS(KEY_MAX)];
127
169
        int num_bits;
128
170
 
129
 
        s = hal_util_get_string_from_file (sysfs_path, "../capabilities/key");
 
171
        s = hal_util_get_string_from_file (sysfs_path, "capabilities/key");
130
172
        if (s == NULL)
131
173
                goto out;
132
174
 
149
191
                        hal_device_property_set_string (d, "button.type", "hibernate");
150
192
                }
151
193
        } else {
152
 
                /* TODO: we probably should require lots of bits set to classify as keyboard. Oh well */
153
 
 
154
 
                /* All keys that are not buttons are less than BTN_MISC */
155
 
                for (i = KEY_RESERVED + 1; i < BTN_MISC; i++) {
156
 
                        if (test_bit (i, bitmask)) {
157
 
                                hal_device_add_capability (d, "input.keyboard");
158
 
                                break;
159
 
                        }
160
 
                }
 
194
                gboolean is_keyboard = input_test_keyboard (bitmask);
 
195
                gboolean is_keypad = input_test_keypad (bitmask);
 
196
 
 
197
                if (is_keyboard)
 
198
                        hal_device_add_capability (d, "input.keyboard");
 
199
                if (is_keypad)
 
200
                        hal_device_add_capability (d, "input.keypad");
 
201
 
 
202
                if (is_keyboard || is_keypad || input_test_keys (bitmask))
 
203
                        hal_device_add_capability (d, "input.keys");
161
204
        }
162
205
out:
163
206
        ;
170
213
        long bitmask[NBITS(SW_MAX)];
171
214
        int num_bits;
172
215
 
173
 
        s = hal_util_get_string_from_file (sysfs_path, "../capabilities/sw");
 
216
        s = hal_util_get_string_from_file (sysfs_path, "capabilities/sw");
174
217
        if (s == NULL)
175
218
                goto out;
176
219
 
205
248
        long bitmask[NBITS(ABS_MAX)];
206
249
        int num_bits;
207
250
 
208
 
        s = hal_util_get_string_from_file (sysfs_path, "../capabilities/abs");
 
251
        s = hal_util_get_string_from_file (sysfs_path, "capabilities/abs");
209
252
        if (s == NULL)
210
253
                goto out;
211
254
        num_bits = input_str_to_bitmask (s, bitmask, sizeof (bitmask));
212
255
 
 
256
        if (test_bit (ABS_X, bitmask) && test_bit (ABS_Y, bitmask) && test_bit (ABS_PRESSURE, bitmask)) {
 
257
                hal_device_add_capability (d, "input.touchpad");
 
258
                goto out;
 
259
        }
 
260
 
 
261
        /* TODO: Hmm; this code looks sketchy... why do we do !test_bit on the Y axis ?? */
213
262
        if (test_bit(ABS_X, bitmask) && !test_bit(ABS_Y, bitmask)) {
214
263
                long bitmask_touch[NBITS(KEY_MAX)];
215
264
 
216
265
                hal_device_add_capability (d, "input.joystick");
217
266
 
218
 
                s = hal_util_get_string_from_file (sysfs_path, "../capabilities/key");
 
267
                s = hal_util_get_string_from_file (sysfs_path, "capabilities/key");
219
268
                if (s == NULL)
220
269
                        goto out;
221
270
                input_str_to_bitmask (s, bitmask_touch, sizeof (bitmask_touch));
222
271
 
223
272
                if (test_bit(BTN_TOUCH, bitmask_touch)) {
224
273
                        hal_device_add_capability (d, "input.tablet");
225
 
                }
 
274
                }
226
275
        }
227
276
out:
228
277
        ;
232
281
input_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *parent_dev, const gchar *parent_path)
233
282
{
234
283
        int eventdev_num;
235
 
        HalDevice *d = NULL;
 
284
        HalDevice *d;
 
285
        char *attr_sysfs_path;
 
286
        
 
287
        d = NULL;
 
288
        attr_sysfs_path = NULL;
236
289
 
237
 
        if (device_file == NULL)
 
290
        if (device_file == NULL || device_file[0] == '\0')
238
291
                goto out;
239
292
 
240
293
        /* only care about evdev input devices */
241
294
        if (sscanf (hal_util_get_last_element (sysfs_path), "event%d", &eventdev_num) != 1)
242
295
                goto out;
 
296
        
 
297
        /* Prior to 2.6.23pre event%d was a child of input%d - after that event%d
 
298
         * moved to the same level with a device/ symlink... Handle both cases
 
299
         */
 
300
        attr_sysfs_path = g_strdup_printf ("%s/../capabilities", sysfs_path);
 
301
        if (g_file_test (attr_sysfs_path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
 
302
                g_free (attr_sysfs_path);
 
303
                attr_sysfs_path = g_strdup_printf ("%s/../", sysfs_path);
 
304
        } else {
 
305
                g_free (attr_sysfs_path);
 
306
                attr_sysfs_path = g_strdup_printf ("%s/device/capabilities", sysfs_path);
 
307
                if (g_file_test (attr_sysfs_path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
 
308
                        g_free (attr_sysfs_path);
 
309
                        attr_sysfs_path = g_strdup_printf ("%s/device/", sysfs_path);
 
310
                } else {
 
311
                        goto out;
 
312
                }
 
313
        }
243
314
 
244
315
        d = hal_device_new ();
245
316
        hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
255
326
 
256
327
        hal_device_property_set_string (d, "input.device", device_file);
257
328
 
258
 
        hal_util_set_string_from_file (d, "info.product", sysfs_path, "../name");
259
 
        hal_util_set_string_from_file (d, "input.product", sysfs_path, "../name");
 
329
        hal_util_set_string_from_file (d, "info.product", attr_sysfs_path, "name");
 
330
        hal_util_set_string_from_file (d, "input.product", attr_sysfs_path, "name");
260
331
 
261
332
        /* check for keys */
262
 
        input_test_key (d, sysfs_path);
 
333
        input_test_key (d, attr_sysfs_path);
263
334
 
264
335
        /* check for mice etc. */
265
 
        input_test_rel (d, sysfs_path);
 
336
        input_test_rel (d, attr_sysfs_path);
266
337
 
267
338
        /* check for joysticks etc. */
268
 
        input_test_abs (d, sysfs_path);
 
339
        input_test_abs (d, attr_sysfs_path);
269
340
 
270
341
        /* check for switches */
271
 
        input_test_switch (d, sysfs_path);
 
342
        input_test_switch (d, attr_sysfs_path);
272
343
 
273
344
out:
 
345
        g_free (attr_sysfs_path);
274
346
        return d;
275
347
}
276
348
 
314
386
               const gchar *parent_path)
315
387
{
316
388
        HalDevice *d;
 
389
        const char *type_entry;
 
390
        const char *addr_entry;
 
391
        unsigned int a5, a4, a3, a2, a1, a0;
 
392
        dbus_uint64_t address;
317
393
 
318
394
        d = NULL;
319
395
 
321
397
                goto out;
322
398
        }
323
399
 
 
400
        addr_entry = hal_util_get_string_from_file (sysfs_path, "address");
 
401
        if (addr_entry == NULL)
 
402
                goto out;
 
403
 
 
404
        if (sscanf (addr_entry, "%x:%x:%x:%x:%x:%x", &a5, &a4, &a3, &a2, &a1, &a0) != 6) {
 
405
                goto out;
 
406
        }
 
407
        address = ((dbus_uint64_t)a5<<40) |
 
408
                ((dbus_uint64_t)a4<<32) | 
 
409
                ((dbus_uint64_t)a3<<24) | 
 
410
                ((dbus_uint64_t)a2<<16) | 
 
411
                ((dbus_uint64_t)a1<< 8) | 
 
412
                ((dbus_uint64_t)a0<< 0);
 
413
 
 
414
        type_entry = hal_util_get_string_from_file (sysfs_path, "type");
 
415
        if (type_entry == NULL)
 
416
                goto out;
 
417
 
324
418
        d = hal_device_new ();
325
419
        hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
326
420
        hal_device_property_set_string (d, "info.parent", hal_device_get_udi (parent_dev));
327
421
 
328
 
        hal_device_property_set_string (d, "info.category", "bluetooth_hci");
329
 
        hal_device_add_capability (d, "bluetooth_hci");
330
 
 
331
 
        hal_device_property_set_string (d, "bluetooth_hci.originating_device", hal_device_get_udi (parent_dev));
332
 
        hal_device_property_set_string (d, "bluetooth_hci.physical_device", hal_device_get_udi (parent_dev));
333
 
        hal_util_set_string_from_file (d, "bluetooth_hci.interface_name", sysfs_path, "name");
334
 
 
335
 
        hal_device_property_set_string (d, "info.product", "Bluetooth Host Controller Interface");
 
422
        if (strcmp (type_entry, "ACL") == 0) {
 
423
                hal_device_property_set_string (d, "info.category", "bluetooth_acl");
 
424
                hal_device_add_capability (d, "bluetooth_acl");
 
425
                hal_device_property_set_uint64 (d, "bluetooth_acl.address", address);
 
426
                hal_device_property_set_string (d, "info.product", "Bluetooth Asynchronous Connection-oriented Link");
 
427
                hal_device_property_set_string (d, "bluetooth_acl.originating_device", hal_device_get_udi (parent_dev));
 
428
 
 
429
        } else if (strcmp (type_entry, "SCO") == 0) {
 
430
                hal_device_property_set_string (d, "info.category", "bluetooth_sco");
 
431
                hal_device_add_capability (d, "bluetooth_sco");
 
432
                hal_device_property_set_uint64 (d, "bluetooth_sco.address", address);
 
433
                hal_device_property_set_string (d, "info.product", "Bluetooth Synchronous Connection-oriented Link");
 
434
                hal_device_property_set_string (d, "bluetooth_sco.originating_device", hal_device_get_udi (parent_dev));
 
435
        } else {
 
436
                hal_device_property_set_string (d, "info.category", "bluetooth_hci");
 
437
                hal_device_add_capability (d, "bluetooth_hci");
 
438
                hal_device_property_set_string (d, "info.product", "Bluetooth Host Controller Interface");
 
439
                hal_device_property_set_string (d, "bluetooth_hci.originating_device", hal_device_get_udi (parent_dev));
 
440
                hal_device_property_set_uint64 (d, "bluetooth_hci.address", address);
 
441
        }
336
442
 
337
443
out:
338
444
        return d;
343
449
{
344
450
        gchar udi[256];
345
451
 
346
 
        hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
347
 
                              "%s_bluetooth_hci",
348
 
                              hal_device_property_get_string (d, "info.parent"));
 
452
        if (hal_device_has_capability (d, "bluetooth_acl")) {
 
453
                hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
 
454
                                      "/org/freedesktop/Hal/devices/bluetooth_acl_%0llx",
 
455
                                      hal_device_property_get_uint64 (d, "bluetooth_acl.address"));
 
456
        } else if (hal_device_has_capability (d, "bluetooth_sco")) {
 
457
                hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
 
458
                                      "/org/freedesktop/Hal/devices/bluetooth_acl_%0llx",
 
459
                                      hal_device_property_get_uint64 (d, "bluetooth_acl.address"));
 
460
        } else {
 
461
                hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
 
462
                                      "%s_bluetooth_hci_%0llx",
 
463
                                      hal_device_property_get_string (d, "info.parent"),
 
464
                                      hal_device_property_get_uint64 (d, "bluetooth_hci.address"));
 
465
        }
349
466
        hal_device_set_udi (d, udi);
350
467
        hal_device_property_set_string (d, "info.udi", udi);
351
468
        return TRUE;
395
512
        media_type = hal_device_property_get_int (d, "net.arp_proto_hw_id");
396
513
        if (media_type == ARPHRD_ETHER) {
397
514
                const char *addr;
 
515
                const char *parent_subsys;
398
516
                char wireless_path[HAL_PATH_MAX];
399
517
                char wiphy_path[HAL_PATH_MAX];
400
 
                gboolean is_wireless;
401
518
                struct stat s;
 
519
                dbus_uint64_t mac_address = 0;
 
520
 
 
521
                addr = hal_device_property_get_string (d, "net.address");
 
522
                if (addr != NULL) {
 
523
                        unsigned int a5, a4, a3, a2, a1, a0;
 
524
 
 
525
                        if (sscanf (addr, "%x:%x:%x:%x:%x:%x",
 
526
                                    &a5, &a4, &a3, &a2, &a1, &a0) == 6) {
 
527
                                mac_address =
 
528
                                        ((dbus_uint64_t)a5<<40) |
 
529
                                        ((dbus_uint64_t)a4<<32) |
 
530
                                        ((dbus_uint64_t)a3<<24) |
 
531
                                        ((dbus_uint64_t)a2<<16) |
 
532
                                        ((dbus_uint64_t)a1<< 8) |
 
533
                                        ((dbus_uint64_t)a0<< 0);
 
534
                        }
 
535
                }
402
536
 
403
537
                snprintf (wireless_path, HAL_PATH_MAX, "%s/wireless", sysfs_path);
404
538
                /* wireless dscape stack e.g. from rt2500pci driver*/
405
539
                snprintf (wiphy_path, HAL_PATH_MAX, "%s/wiphy", sysfs_path);
 
540
                parent_subsys = hal_device_property_get_string (parent_dev, "linux.subsystem");
406
541
 
407
 
                if ((stat (wireless_path, &s) == 0 && (s.st_mode & S_IFDIR)) ||
408
 
                    (stat (wiphy_path, &s) == 0 && (s.st_mode & S_IFDIR))) { 
 
542
                if (parent_subsys && strcmp(parent_subsys, "bluetooth") == 0) {
 
543
                        hal_device_property_set_string (d, "info.product", "Bluetooth Interface");
 
544
                        hal_device_property_set_string (d, "info.category", "net.bluetooth");
 
545
                        hal_device_add_capability (d, "net.bluetooth");
 
546
                        hal_device_property_set_uint64 (d, "net.bluetooth.mac_address", mac_address);
 
547
                } else if ((stat (wireless_path, &s) == 0 && (s.st_mode & S_IFDIR)) ||
 
548
                        (stat (wiphy_path, &s) == 0 && (s.st_mode & S_IFDIR))) {
409
549
                        hal_device_property_set_string (d, "info.product", "WLAN Interface");
410
550
                        hal_device_property_set_string (d, "info.category", "net.80211");
411
551
                        hal_device_add_capability (d, "net.80211");
412
 
                        is_wireless = TRUE;
 
552
                        hal_device_property_set_uint64 (d, "net.80211.mac_address", mac_address);
413
553
                } else {
414
554
                        hal_device_property_set_string (d, "info.product", "Networking Interface");
415
555
                        hal_device_property_set_string (d, "info.category", "net.80203");
416
556
                        hal_device_add_capability (d, "net.80203");
417
 
                        is_wireless = FALSE;
418
 
                }
419
 
 
420
 
                addr = hal_device_property_get_string (d, "net.address");
421
 
                if (addr != NULL) {
422
 
                        unsigned int a5, a4, a3, a2, a1, a0;
423
 
                        
424
 
                        if (sscanf (addr, "%x:%x:%x:%x:%x:%x",
425
 
                                    &a5, &a4, &a3, &a2, &a1, &a0) == 6) {
426
 
                                dbus_uint64_t mac_address;
427
 
                                
428
 
                                mac_address = 
429
 
                                        ((dbus_uint64_t)a5<<40) |
430
 
                                        ((dbus_uint64_t)a4<<32) | 
431
 
                                        ((dbus_uint64_t)a3<<24) | 
432
 
                                        ((dbus_uint64_t)a2<<16) | 
433
 
                                        ((dbus_uint64_t)a1<< 8) | 
434
 
                                        ((dbus_uint64_t)a0<< 0);
435
 
                                
436
 
                                hal_device_property_set_uint64 (d, is_wireless ? "net.80211.mac_address" : 
437
 
                                                                "net.80203.mac_address",
438
 
                                                                mac_address);
439
 
                        }
 
557
                        hal_device_property_set_uint64 (d, "net.80203.mac_address", mac_address);
440
558
                }
441
559
        } else if (media_type == ARPHRD_IRDA) {
442
560
                hal_device_property_set_string (d, "info.product", "Networking Interface");
466
584
}
467
585
 
468
586
static gboolean
 
587
net_refresh (HalDevice *d)
 
588
{
 
589
        const gchar *path, *ifname;
 
590
        
 
591
        path = hal_device_property_get_string (d, "linux.sysfs_path");
 
592
        ifname = hal_util_get_last_element (path);
 
593
        hal_device_property_set_string (d, "net.interface", ifname);
 
594
        return TRUE;
 
595
}
 
596
 
 
597
static const char *
 
598
net_get_prober (HalDevice *d)
 
599
{
 
600
        const char *prober = NULL;
 
601
 
 
602
        /* run prober only for bluetooth devices */
 
603
        if (hal_device_has_capability (d, "net.bluetooth")) {
 
604
                prober = "hald-probe-net-bluetooth";
 
605
        }
 
606
 
 
607
        return prober;
 
608
}
 
609
 
 
610
static gboolean
 
611
net_post_probing (HalDevice *d)
 
612
{
 
613
        return TRUE;
 
614
}
 
615
 
 
616
static gboolean
469
617
net_compute_udi (HalDevice *d)
470
618
{
471
619
        gchar udi[256];
657
805
 
658
806
        d = NULL;
659
807
 
660
 
        if (parent_dev == NULL || parent_path == NULL || device_file == NULL) {
 
808
        if (parent_dev == NULL || parent_path == NULL || device_file == NULL || device_file[0] == '\0') {
661
809
                goto out;
662
810
        }
663
811
 
847
995
static void
848
996
asound_card_id_set (int cardnum, HalDevice *d, const char *propertyname)
849
997
{
850
 
        char aprocdir[256];
851
998
        char linestart[5];
852
999
        gchar *alsaname;
853
1000
 
854
 
        snprintf (aprocdir, sizeof (aprocdir), "%s/asound", get_hal_proc_path ());
855
1001
        snprintf (linestart, sizeof (linestart), "%2d [", cardnum);
856
 
        alsaname = hal_util_grep_file_next_line (aprocdir, "cards", linestart, FALSE);
 
1002
        alsaname = hal_util_grep_file_next_line ("/proc/asound", "cards", linestart, FALSE);
857
1003
        if (alsaname != NULL) {
858
1004
                gchar *end;
859
1005
                end = strstr (alsaname, " at ");
880
1026
 
881
1027
        d = NULL;
882
1028
 
883
 
        if (device_file == NULL) 
884
 
                goto out;       
 
1029
        HAL_INFO (("sound_add: sysfs_path=%s device_file=%s parent_dev=0x%08x parent_path=%s", sysfs_path, device_file, parent_dev, parent_path));
885
1030
 
886
1031
        d = hal_device_new ();
887
1032
        hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
888
1033
        device = hal_util_get_last_element(sysfs_path);
889
1034
 
890
 
        if (parent_dev == NULL || parent_path == NULL) {
 
1035
        if (device_file[0] == '\0' && parent_dev == NULL && parent_path == NULL) {
 
1036
                goto out;
 
1037
        } else if (device_file[0] == '\0' && parent_dev != NULL && parent_path != NULL) {
 
1038
                HAL_INFO(("sound_add: handle sound card %s", sysfs_path));
 
1039
                /* handle card devices */
 
1040
                hal_device_property_set_string (d, "info.category", "sound");
 
1041
                hal_device_add_capability (d, "sound");
 
1042
                hal_device_property_set_string (d, "sound.originating_device", hal_device_get_udi (parent_dev));
 
1043
                hal_device_property_set_string (d, "sound.physical_device", hal_device_get_udi (parent_dev));
 
1044
                hal_device_property_set_string (d, "info.parent", hal_device_get_udi (parent_dev));
 
1045
 
 
1046
                if (sscanf (device, "card%d", &cardnum) == 1) {
 
1047
                        hal_device_property_set_int (d, "sound.card", cardnum);
 
1048
                        asound_card_id_set (cardnum, d, "sound.card_id");
 
1049
                        snprintf (buf, sizeof (buf), "%s Sound Card", hal_device_property_get_string (d, "sound.card_id"));
 
1050
                        hal_device_property_set_string (d, "info.product", buf);
 
1051
                }
 
1052
        } else if (parent_dev == NULL || parent_path == NULL) {
891
1053
                /* handle global ALSA and OSS devices, these devices are for all ALSA/OSS Sound devices
892
1054
                   so we append them to /org/freedesktop/Hal/devices/computer */
893
1055
                hal_device_property_set_string (d, "info.parent", "/org/freedesktop/Hal/devices/computer");
951
1113
                        if (!hal_util_set_string_from_file (d, "alsa.pcm_class", sysfs_path, "pcm_class"))
952
1114
                                 hal_device_property_set_string (d, "alsa.pcm_class", "unknown");
953
1115
        
954
 
                        snprintf (aprocdir, sizeof (aprocdir), "%s/asound/card%d/pcm%d%c", 
955
 
                                get_hal_proc_path (), cardnum, devicenum, type);
 
1116
                        snprintf (aprocdir, sizeof (aprocdir), "/proc/asound/card%d/pcm%d%c", 
 
1117
                                  cardnum, devicenum, type);
956
1118
                        device_id = hal_util_grep_file (aprocdir, "info", "name: ", FALSE);
957
1119
                        if (device_id != NULL) {
958
1120
                                hal_device_property_set_string (d, "alsa.device_id", device_id);
1043
1205
        
1044
1206
                        asound_card_id_set (cardnum, d, "oss.card_id");
1045
1207
        
1046
 
                        snprintf (aprocdir, sizeof (aprocdir), "%s/asound/card%d/pcm0p", 
1047
 
                                get_hal_proc_path (), cardnum);
 
1208
                        snprintf (aprocdir, sizeof (aprocdir), "/proc/asound/card%d/pcm0p", cardnum);
1048
1209
                        device_id = hal_util_grep_file (aprocdir, "info", "name: ", FALSE);
1049
1210
                        if (device_id != NULL) {
1050
1211
                                hal_device_property_set_string (d, "oss.device_id", device_id);
1117
1278
{
1118
1279
        gchar udi[256];
1119
1280
 
1120
 
        if (hal_device_has_property(d, "alsa.card")) {
 
1281
        if (hal_device_has_property(d, "sound.card")) {
 
1282
                /* don't include card number as it may not be persistent across reboots */
 
1283
                hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
 
1284
                                      "%s_sound_card_%i",
 
1285
                                      hal_device_property_get_string (d, "info.parent"),
 
1286
                                      hal_device_property_get_string (d, "sound.card"));
 
1287
        } else if (hal_device_has_property(d, "alsa.card")) {
1121
1288
                /* don't include card number as it may not be persistent across reboots */
1122
1289
                hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
1123
1290
                                      "%s_alsa_%s_%i",
1165
1332
 
1166
1333
        d = NULL;
1167
1334
 
1168
 
        if (parent_dev == NULL || parent_path == NULL || device_file == NULL) {
 
1335
        if (parent_dev == NULL || parent_path == NULL || device_file == NULL || device_file[0] == '\0') {
1169
1336
                goto out;
1170
1337
        }
1171
1338
 
1223
1390
static const gchar *
1224
1391
serial_get_prober (HalDevice *d)
1225
1392
{
 
1393
        const gchar *dev;
 
1394
 
1226
1395
        /* FIXME TODO: check if there is an other way, to call the porber only
1227
 
                 on ttyS* devices, than check the name of the device file */
1228
 
        if (!strncmp(hal_device_property_get_string (d, "linux.device_file"), "/dev/ttyS", 9))
 
1396
                       on ttyS* devices, than check the name of the device file */
 
1397
        dev  = hal_device_property_get_string (d, "linux.device_file");
 
1398
        if (dev && !strncmp(dev, "/dev/ttyS", 9))
1229
1399
                return "hald-probe-serial";
1230
1400
        else 
1231
1401
                return NULL;
2263
2433
        HalDevice *d = NULL;
2264
2434
        gchar buf[64];
2265
2435
 
2266
 
        if (device_file == NULL)
 
2436
        if (device_file == NULL || device_file[0] == '\0')
2267
2437
                goto out;
2268
2438
 
2269
2439
        d = hal_device_new ();
2781
2951
}
2782
2952
 
2783
2953
static gboolean
 
2954
power_supply_compute_udi (HalDevice *d)
 
2955
{
 
2956
        gchar udi[256];
 
2957
        const char *dir;
 
2958
        const char *name;
 
2959
 
 
2960
        dir = hal_device_property_get_string (d, "linux.sysfs_path");
 
2961
 
 
2962
        name = hal_util_get_last_element(dir);
 
2963
        hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
 
2964
                              "%s_power_supply",
 
2965
                              hal_device_property_get_string (d, "info.parent"));
 
2966
        hal_device_set_udi (d, udi);
 
2967
        hal_device_property_set_string (d, "info.udi", udi);
 
2968
        return TRUE;
 
2969
}
 
2970
 
 
2971
static void
 
2972
refresh_ac_adapter (HalDevice *d)
 
2973
{
 
2974
        const char *path;
 
2975
        gboolean present = FALSE;
 
2976
 
 
2977
        path = hal_device_property_get_string (d, "linux.sysfs_path");
 
2978
        if (path == NULL)
 
2979
                return;
 
2980
 
 
2981
        if (hal_util_get_bool_from_file (path, "online", &present, "1") == FALSE) {
 
2982
                /* if we can't read the property, assume on ac */
 
2983
                present = TRUE;
 
2984
        }
 
2985
 
 
2986
        hal_device_property_set_bool (d, "ac_adapter.present", present);
 
2987
}
 
2988
 
 
2989
static void
 
2990
refresh_battery_fast (HalDevice *d)
 
2991
{
 
2992
        gint percentage = 0;
 
2993
        gint voltage_now = 0;
 
2994
        gint voltage_design = 0;
 
2995
        gint current = 0;
 
2996
        gint time = 0;
 
2997
        gint value_now = 0;
 
2998
        gint value_last_full = 0;
 
2999
        gint value_full_design = 0;
 
3000
        gboolean present = FALSE;
 
3001
        gboolean could_be_mah = TRUE;
 
3002
        gboolean could_be_mwh = TRUE;
 
3003
        gboolean is_mah = FALSE;
 
3004
        gboolean is_mwh = FALSE;
 
3005
        gboolean is_charging = FALSE;
 
3006
        gboolean is_discharging = FALSE;
 
3007
        gboolean got_time = FALSE;
 
3008
        gboolean got_percentage = FALSE;
 
3009
        const gchar *path;
 
3010
        const gchar *reporting_unit;
 
3011
        gchar *status;
 
3012
 
 
3013
        path = hal_device_property_get_string (d, "linux.sysfs_path");
 
3014
        if (path == NULL)
 
3015
                return;
 
3016
 
 
3017
        /* PRESENT */
 
3018
        if (hal_util_get_bool_from_file (path, "present", &present, "1")) {
 
3019
                hal_device_property_set_bool (d, "battery.present", present);
 
3020
        }
 
3021
        if (present == FALSE) {
 
3022
                /* remove all the optional keys associated with the cell */
 
3023
                device_pm_remove_optional_props (d);
 
3024
                return;
 
3025
        }
 
3026
 
 
3027
        /* CAPACITY */
 
3028
        if (hal_util_get_int_from_file (path, "capacity", &percentage, 10)) {
 
3029
                /* sanity check */
 
3030
                if (percentage >= 0 && percentage <= 100)
 
3031
                        got_percentage = TRUE;
 
3032
        }
 
3033
 
 
3034
        /* VOLTAGE: we prefer the average if it exists, although present is still pretty good */
 
3035
        if (hal_util_get_int_from_file (path, "voltage_avg", &voltage_now, 10)) {
 
3036
                hal_device_property_set_int (d, "battery.voltage.current", voltage_now / 1000);
 
3037
        } else if (hal_util_get_int_from_file (path, "voltage_now", &voltage_now, 10)) {
 
3038
                hal_device_property_set_int (d, "battery.voltage.current", voltage_now / 1000);
 
3039
        }
 
3040
        if (hal_util_get_int_from_file (path, "voltage_max_design", &voltage_design, 10)) {
 
3041
                hal_device_property_set_int (d, "battery.voltage.design", voltage_design / 1000);
 
3042
        }
 
3043
 
 
3044
        /* CURRENT: we prefer the average if it exists, although present is still pretty good */
 
3045
        if (hal_util_get_int_from_file (path, "current_avg", &current, 10)) {
 
3046
                hal_device_property_set_int (d, "battery.current", current / 1000);
 
3047
        } else if (hal_util_get_int_from_file (path, "current_now", &current, 10)) {
 
3048
                hal_device_property_set_int (d, "battery.current", current / 1000);
 
3049
        }
 
3050
 
 
3051
        /* STATUS: Convert to charging/discharging state */
 
3052
        status = hal_util_get_string_from_file (path, "status");
 
3053
        if (status != NULL) {
 
3054
                if (strcasecmp (status, "charging") == 0) {
 
3055
                        is_charging = TRUE;
 
3056
                } else if (strcasecmp (status, "discharging") == 0) {
 
3057
                        is_discharging = TRUE;
 
3058
                }
 
3059
                hal_device_property_set_bool (d, "battery.rechargeable.is_charging", is_charging);
 
3060
                hal_device_property_set_bool (d, "battery.rechargeable.is_discharging", is_discharging);
 
3061
        }
 
3062
 
 
3063
        /* TIME: Some batteries only provide time to discharge */
 
3064
        if (is_charging == TRUE) {
 
3065
                if (hal_util_get_int_from_file (path, "time_to_full_avg", &time, 10) ||
 
3066
                    hal_util_get_int_from_file (path, "time_to_full_now", &time, 10)) {
 
3067
                        got_time = TRUE;
 
3068
                }
 
3069
        } else if (is_discharging == TRUE) {
 
3070
                if (hal_util_get_int_from_file (path, "time_to_empty_avg", &time, 10) ||
 
3071
                    hal_util_get_int_from_file (path, "time_to_empty_now", &time, 10)) {
 
3072
                        got_time = TRUE;
 
3073
                }
 
3074
        }
 
3075
 
 
3076
        /* Have we already got information about the reporting unit?
 
3077
         * If we have, we can save a lots of file reads */
 
3078
        reporting_unit = hal_device_property_get_string (d, "battery.reporting.unit");
 
3079
        if (reporting_unit != NULL) {
 
3080
                if (strcasecmp (reporting_unit, "mah") == 0) {
 
3081
                        could_be_mwh = FALSE;
 
3082
                } else if (strcasecmp (reporting_unit, "mwh") == 0) {
 
3083
                        could_be_mah = FALSE;
 
3084
                }
 
3085
        }
 
3086
 
 
3087
        /* ENERGY (reported in uWh, so need to convert to mWh) */
 
3088
        if (could_be_mwh) {
 
3089
                if (hal_util_get_int_from_file (path, "energy_avg", &value_now, 10)) {
 
3090
                        hal_device_property_set_int (d, "battery.reporting.current", value_now / 1000);
 
3091
                        is_mwh = TRUE;
 
3092
                } else if (hal_util_get_int_from_file (path, "energy_now", &value_now, 10)) {
 
3093
                        hal_device_property_set_int (d, "battery.reporting.current", value_now / 1000);
 
3094
                        is_mwh = TRUE;
 
3095
                }
 
3096
                if (hal_util_get_int_from_file (path, "energy_full", &value_last_full, 10)) {
 
3097
                        hal_device_property_set_int (d, "battery.reporting.last_full", value_last_full / 1000);
 
3098
                        is_mwh = TRUE;
 
3099
                }
 
3100
                if (hal_util_get_int_from_file (path, "energy_full_design", &value_full_design, 10)) {
 
3101
                        hal_device_property_set_int (d, "battery.reporting.design", value_full_design / 1000);
 
3102
                        is_mwh = TRUE;
 
3103
                }
 
3104
        }
 
3105
 
 
3106
        /* CHARGE (reported in uAh, so need to convert to mAh) */
 
3107
        if (could_be_mah) {
 
3108
                if (hal_util_get_int_from_file (path, "charge_avg", &value_now, 10)) {
 
3109
                        hal_device_property_set_int (d, "battery.reporting.current", value_now / 1000);
 
3110
                        is_mah = TRUE;
 
3111
                } else if (hal_util_get_int_from_file (path, "charge_now", &value_now, 10)) {
 
3112
                        hal_device_property_set_int (d, "battery.reporting.current", value_now / 1000);
 
3113
                        is_mah = TRUE;
 
3114
                }
 
3115
                if (hal_util_get_int_from_file (path, "charge_full", &value_last_full, 10)) {
 
3116
                        hal_device_property_set_int (d, "battery.reporting.last_full", value_last_full / 1000);
 
3117
                        is_mah = TRUE;
 
3118
                }
 
3119
                if (hal_util_get_int_from_file (path, "charge_full_design", &value_full_design, 10)) {
 
3120
                        hal_device_property_set_int (d, "battery.reporting.design", value_full_design / 1000);
 
3121
                        is_mah = TRUE;
 
3122
                }
 
3123
        }
 
3124
 
 
3125
        /* record these for future savings */
 
3126
        if (is_mwh == TRUE) {
 
3127
                hal_device_property_set_string (d, "battery.reporting.unit", "mWh");
 
3128
        } else if (is_mah == TRUE) {
 
3129
                hal_device_property_set_string (d, "battery.reporting.unit", "mAh");
 
3130
        }
 
3131
 
 
3132
        /* we've now got the 'reporting' keys, now we need to populate the
 
3133
         * processed 'charge_level' keys so stuff like desktop power managers
 
3134
         * do not have to deal with odd quirks */
 
3135
        device_pm_abstract_props (d);
 
3136
 
 
3137
        /* if we have not read from the hardware, then calculate */
 
3138
        if (got_percentage) {
 
3139
                hal_device_property_set_int (d, "battery.charge_level.percentage", percentage);
 
3140
        } else {
 
3141
                device_pm_calculate_percentage (d);
 
3142
        }
 
3143
 
 
3144
        /* if we havn't got time from the hardware, then try to calculate it */
 
3145
        if (got_time) {
 
3146
                /* zero time isn't displayed */
 
3147
                if (time > 0)
 
3148
                        hal_device_property_set_int (d, "battery.remaining_time", time);
 
3149
                else
 
3150
                        hal_device_property_remove (d, "battery.remaining_time");
 
3151
        } else {
 
3152
                device_pm_calculate_time (d);
 
3153
        }
 
3154
}
 
3155
 
 
3156
static void
 
3157
refresh_battery_slow (HalDevice *d)
 
3158
{
 
3159
        const char *technology;
 
3160
        char *technology_raw;
 
3161
        char *model_name;
 
3162
        char *manufacturer;
 
3163
        const gchar *path;
 
3164
 
 
3165
        path = hal_device_property_get_string (d, "linux.sysfs_path");
 
3166
        if (path == NULL)
 
3167
                return;
 
3168
 
 
3169
        /* get battery technology */
 
3170
        technology_raw = hal_util_get_string_from_file (path, "technology");
 
3171
        if (technology_raw != NULL) {
 
3172
                hal_device_property_set_string (d, "battery.reporting.technology", technology_raw);
 
3173
        }
 
3174
        /* we set this, even if it's unknown */
 
3175
        technology = util_get_battery_technology (technology_raw);
 
3176
        hal_device_property_set_string (d, "battery.technology", technology);
 
3177
 
 
3178
        /* get product name */
 
3179
        model_name = hal_util_get_string_from_file (path, "technology");
 
3180
        if (model_name != NULL) {
 
3181
                hal_device_property_set_string (d, "info.product", model_name);
 
3182
        } else {
 
3183
                hal_device_property_set_string (d, "info.product", "Generic Battery Device");
 
3184
        }
 
3185
 
 
3186
        /* get manufacturer */
 
3187
        manufacturer = hal_util_get_string_from_file (path, "manufacturer");
 
3188
        if (manufacturer != NULL) {
 
3189
                hal_device_property_set_string (d, "battery.vendor", manufacturer);
 
3190
        }
 
3191
 
 
3192
        /* now do stuff that happens quickly */
 
3193
        refresh_battery_fast (d);
 
3194
}
 
3195
 
 
3196
static gboolean
 
3197
power_supply_refresh (HalDevice *d)
 
3198
{
 
3199
        const gchar *type;
 
3200
        type = hal_device_property_get_string (d, "info.category");
 
3201
        if (type == NULL) {
 
3202
                return FALSE;
 
3203
        }
 
3204
        if (strcmp (type, "ac_adapter") == 0) {
 
3205
                device_property_atomic_update_begin ();
 
3206
                refresh_ac_adapter (d);
 
3207
                device_property_atomic_update_end ();
 
3208
        } else if (strcmp (type, "battery") == 0) {
 
3209
                device_property_atomic_update_begin ();
 
3210
                refresh_battery_slow (d);
 
3211
                device_property_atomic_update_end ();
 
3212
        } else {
 
3213
                HAL_WARNING (("Could not recognise power_supply type!"));
 
3214
                return FALSE;
 
3215
        }
 
3216
        return TRUE;
 
3217
}
 
3218
 
 
3219
static HalDevice *
 
3220
power_supply_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev,
 
3221
                  const gchar *sysfs_path_in_devices)
 
3222
{
 
3223
        HalDevice *d = NULL;
 
3224
        gboolean is_battery = FALSE;
 
3225
        gboolean is_ac_adapter = FALSE;
 
3226
        char *type = NULL;
 
3227
        const char *battery_type = NULL;
 
3228
 
 
3229
        /* power_supply devices are very odd, they might be batteries or ac-adapters */
 
3230
        type = hal_util_get_string_from_file (sysfs_path, "type");
 
3231
        if (type == NULL) {
 
3232
                /* we don't need to free */
 
3233
                goto finish;
 
3234
        }
 
3235
        if (strcasecmp (type, "battery") == 0) {
 
3236
                is_battery = TRUE;
 
3237
                battery_type = "primary";
 
3238
        } else if (strcasecmp (type, "ups") == 0) {
 
3239
                is_battery = TRUE;
 
3240
                battery_type = "ups";
 
3241
        } else if (strcasecmp (type, "usb") == 0) {
 
3242
                is_battery = TRUE;
 
3243
                battery_type = "usb";
 
3244
        } else if (strcasecmp (type, "mains") == 0) {
 
3245
                is_ac_adapter = TRUE;
 
3246
        } else {
 
3247
                HAL_WARNING (("Power supply is neither ac_adapter or battery!"));
 
3248
                goto finish;
 
3249
        }
 
3250
 
 
3251
        d = hal_device_new ();
 
3252
        hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
 
3253
        hal_device_property_set_string (d, "info.parent", "/org/freedesktop/Hal/devices/computer");
 
3254
 
 
3255
        if (is_battery == TRUE) {
 
3256
                hal_device_property_set_string (d, "info.category", "battery");
 
3257
                if (battery_type != NULL)
 
3258
                        hal_device_property_set_string (d, "battery.type", battery_type);
 
3259
                refresh_battery_slow (d);
 
3260
                hal_device_add_capability (d, "battery");
 
3261
        }
 
3262
 
 
3263
        if (is_ac_adapter == TRUE) {
 
3264
                hal_device_property_set_string (d, "info.category", "ac_adapter");
 
3265
                hal_device_property_set_string (d, "info.product", "Generic AC Adapter Device");
 
3266
                refresh_ac_adapter (d);
 
3267
                hal_device_add_capability (d, "ac_adapter");
 
3268
        }
 
3269
finish:
 
3270
        return d;
 
3271
}
 
3272
 
 
3273
static gboolean
2784
3274
backlight_compute_udi (HalDevice *d)
2785
3275
{
2786
3276
        gchar udi[256];
2864
3354
        const gchar *(*get_prober)(HalDevice *d);
2865
3355
        gboolean (*post_probing) (HalDevice *d);
2866
3356
        gboolean (*compute_udi) (HalDevice *d);
 
3357
        gboolean (*refresh) (HalDevice *d);
2867
3358
        gboolean (*remove) (HalDevice *d);
2868
3359
};
2869
3360
 
2893
3384
2894
3385
        .subsystem    = "net",
2895
3386
        .add          = net_add,
2896
 
        .get_prober   = NULL,
2897
 
        .post_probing = NULL,
 
3387
        .refresh      = net_refresh,
 
3388
        .get_prober   = net_get_prober,
 
3389
        .post_probing = net_post_probing,
2898
3390
        .compute_udi  = net_compute_udi,
2899
3391
        .remove       = dev_remove
2900
3392
};
3126
3618
       .remove       = dev_remove
3127
3619
};
3128
3620
 
 
3621
static DevHandler dev_handler_power_supply =
 
3622
{
 
3623
       .subsystem    = "power_supply",
 
3624
       .add          = power_supply_add,
 
3625
       .refresh      = power_supply_refresh,
 
3626
       .compute_udi  = power_supply_compute_udi,
 
3627
       .remove       = dev_remove
 
3628
};
 
3629
 
3129
3630
/* SCSI debug, to test thousends of fake devices */
3130
3631
static DevHandler dev_handler_pseudo = {
3131
3632
        .subsystem   = "pseudo",
3168
3669
        &dev_handler_mmc_host,
3169
3670
        &dev_handler_backlight,
3170
3671
        &dev_handler_firewire,
 
3672
        &dev_handler_power_supply,
3171
3673
        NULL
3172
3674
};
3173
3675
 
3246
3748
        /* Discard device if probing reports failure */
3247
3749
        if (exit_type != HALD_RUN_SUCCESS || return_code != 0) {
3248
3750
                hal_device_store_remove (hald_get_tdl (), d);
 
3751
                HAL_INFO (("device removed due to prober fail"));
 
3752
                hal_device_print (d);
3249
3753
                g_object_unref (d);
3250
3754
                hotplug_event_end (end_token);
3251
3755
                goto out;
3406
3910
        ;
3407
3911
}
3408
3912
 
 
3913
void
 
3914
hotplug_event_refresh_dev (const gchar *subsystem, const gchar *sysfs_path, HalDevice *d, void *end_token)
 
3915
{
 
3916
        guint i;
 
3917
        DevHandler *handler;
 
3918
 
 
3919
        HAL_INFO (("refresh_dev: subsys=%s", subsystem));
 
3920
 
 
3921
        for (i = 0; dev_handlers [i] != NULL; i++) {
 
3922
                handler = dev_handlers[i];
 
3923
                if (strcmp (handler->subsystem, subsystem) == 0) {
 
3924
                        if (handler->refresh != NULL) {
 
3925
                                handler->refresh (d);
 
3926
                        }
 
3927
                        goto out;
 
3928
                }
 
3929
        }
 
3930
 
 
3931
out:
 
3932
        /* done with change event */
 
3933
        hotplug_event_end (end_token);
 
3934
}
 
3935
 
 
3936
 
3409
3937
static void 
3410
3938
dev_rescan_device_done (HalDevice *d, 
3411
3939
                        guint32 exit_type,