~ubuntu-branches/ubuntu/maverick/hal/maverick

« back to all changes in this revision

Viewing changes to hald/linux/acpi.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2007-10-23 12:33:58 UTC
  • mto: (1.5.1 sid)
  • mto: This revision was merged to the branch mainline in revision 90.
  • 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:
28
28
#include <string.h>
29
29
 
30
30
#include "../device_info.h"
 
31
#include "../device_pm.h"
31
32
#include "../hald_dbus.h"
32
33
#include "../logger.h"
33
34
#include "../util.h"
66
67
 
67
68
/** 
68
69
 *  ac_adapter_refresh_poll
69
 
 *  @d:         valid ac_adaptor HalDevice
 
70
 *  @d:         valid ac_adapter HalDevice
70
71
 *
71
72
 * Just sets the ac_adapter.present key when called 
72
73
 */
84
85
battery_refresh_poll (HalDevice *d)
85
86
{
86
87
        const char *path;
87
 
        const char *reporting_unit;
88
 
        int reporting_current;
89
 
        int reporting_lastfull;
90
 
        int reporting_rate;
91
 
        int normalised_current;
92
 
        int normalised_lastfull;
93
 
        int normalised_rate;
94
 
        int design_voltage;
95
 
        int voltage;
96
 
        int remaining_time;
97
 
        int remaining_percentage;
98
 
        gboolean charging;
99
 
        gboolean discharging;
100
 
 
101
88
        path = hal_device_property_get_string (d, "linux.acpi_path");
102
89
        if (path == NULL)
103
90
                return;
124
111
         */
125
112
        hal_util_set_int_elem_from_file (d, "battery.voltage.current", path,
126
113
                                         "state", "present voltage", 0, 10, TRUE);
127
 
        /* get all the data we know */
128
 
        reporting_unit = hal_device_property_get_string (d,
129
 
                                        "battery.reporting.unit");
130
 
        reporting_current = hal_device_property_get_int (d,
131
 
                                        "battery.reporting.current");
132
 
        reporting_lastfull = hal_device_property_get_int (d,
133
 
                                        "battery.reporting.last_full");
134
 
        reporting_rate = hal_device_property_get_int (d,
135
 
                                        "battery.reporting.rate");
136
 
 
137
 
        /*
138
 
         * ACPI gives out the special 'Ones' value for rate when it's unable
139
 
         * to calculate the true rate. We should set the rate zero, and wait
140
 
         * for the BIOS to stabilise.
141
 
         *
142
 
         * full details here: http://bugzilla.gnome.org/show_bug.cgi?id=348201
143
 
         */
144
 
        if (reporting_rate == 0xffff) {
145
 
                reporting_rate = 0;
146
 
        }
147
 
 
148
 
        /*
149
 
         * We are converting the unknown units into mWh because of ACPI's nature
150
 
         * of not having a standard "energy" unit.
151
 
         *
152
 
         * full details here: http://bugzilla.gnome.org/show_bug.cgi?id=309944
153
 
         */
154
 
        if (reporting_unit && strcmp (reporting_unit, "mAh") == 0) {
155
 
                /* convert mAh to mWh by multiplying by voltage.  due to the
156
 
                 * general wonkiness of ACPI implementations, this is a lot
157
 
                 * harder than it should have to be...
158
 
                 */
159
 
 
160
 
                design_voltage = hal_device_property_get_int (d, "battery.voltage.design");
161
 
                voltage = hal_device_property_get_int (d, "battery.voltage.current");
162
 
 
163
 
                /* Just in case we don't get design voltage information, then
164
 
                 * this will pretend that we have 1V.  This degrades our
165
 
                 * ability to report accurate times on multi-battery systems
166
 
                 * but will always prevent negative charge levels and allow
167
 
                 * accurate reporting on single-battery systems.
168
 
                 */
169
 
                if (design_voltage <= 0)
170
 
                        design_voltage = 1000; /* mV */
171
 
 
172
 
                /* If the current voltage is unknown, smaller than 50% of design voltage (fd.o #8593) 
173
 
                 * or greater than design, then use design voltage.
174
 
                 */
175
 
                if (voltage < (design_voltage/2)  || voltage > design_voltage) {
176
 
                        HAL_DEBUG (("Current voltage is unknown, smaller than 50%% or greater than design"));
177
 
                        voltage = design_voltage;
178
 
                }
179
 
 
180
 
                normalised_current = (reporting_current * voltage) / 1000;
181
 
                normalised_lastfull = (reporting_lastfull * voltage) / 1000;
182
 
                normalised_rate = (reporting_rate * voltage) / 1000;
183
 
        } else {
184
 
                /*
185
 
                 * handle as if mWh (which don't need conversion), which is the most common case.
186
 
                 */
187
 
                normalised_current = reporting_current;
188
 
                normalised_lastfull = reporting_lastfull;
189
 
                normalised_rate = reporting_rate;
190
 
        }
191
 
 
192
 
        /*
193
 
         * Set the normalised keys.
194
 
         */
195
 
        if (normalised_current < 0)
196
 
                normalised_current = 0;
197
 
        if (normalised_lastfull < 0)
198
 
                normalised_lastfull = 0;
199
 
        if (normalised_rate < 0)
200
 
                normalised_rate = 0;
201
 
 
202
 
        /*
203
 
         * Some laptops report a rate even when not charging or discharging.
204
 
         * If not charging and not discharging force rate to be zero.
205
 
         *
206
 
         * http://bugzilla.gnome.org/show_bug.cgi?id=323186
207
 
         */
208
 
        charging = hal_device_property_get_bool (d, "battery.rechargeable.is_charging");
209
 
        discharging = hal_device_property_get_bool (d, "battery.rechargeable.is_discharging");
210
 
 
211
 
        if (!charging && !discharging)
212
 
                normalised_rate = 0;
213
 
 
214
 
        /*
215
 
         * Some laptops report current charge much larger than
216
 
         * full charge when at 100%.  Clamp back down to 100%.
217
 
         */
218
 
        if (normalised_current > normalised_lastfull)
219
 
                normalised_current = normalised_lastfull;
220
 
 
221
 
        hal_device_property_set_int (d, "battery.charge_level.current", normalised_current);
222
 
        hal_device_property_set_int (d, "battery.charge_level.last_full", normalised_lastfull);
223
 
        hal_device_property_set_int (d, "battery.charge_level.rate", normalised_rate);
224
 
 
225
 
        remaining_time = util_compute_time_remaining (
226
 
                hal_device_get_udi (d), 
227
 
                normalised_rate, normalised_current, normalised_lastfull,
228
 
                hal_device_property_get_bool (d, "battery.rechargeable.is_discharging"),
229
 
                hal_device_property_get_bool (d, "battery.rechargeable.is_charging"),
230
 
                hal_device_property_get_bool (d, "battery.remaining_time.calculate_per_time"));
231
 
        remaining_percentage = util_compute_percentage_charge (hal_device_get_udi (d), normalised_current, normalised_lastfull);
232
 
        /*
233
 
         * Only set keys if no error (signified with negative return value)
234
 
         * Scrict checking is needed to ensure that the values presented by HAL
235
 
         * are 100% acurate.
236
 
         */
237
 
 
238
 
        if (remaining_time > 0)
239
 
                hal_device_property_set_int (d, "battery.remaining_time", remaining_time);
240
 
        else
241
 
                hal_device_property_remove (d, "battery.remaining_time");
242
 
 
243
 
        if (remaining_percentage > 0)
244
 
                hal_device_property_set_int (d, "battery.charge_level.percentage", remaining_percentage);
245
 
        else
246
 
                hal_device_property_remove (d, "battery.charge_level.percentage");
 
114
 
 
115
        /* we've now got the 'reporting' keys, now we need to populate the
 
116
         * processed 'charge_level' keys so stuff like desktop power managers
 
117
         * do not have to deal with odd quirks */
 
118
        device_pm_abstract_props (d);
 
119
 
 
120
        /* we calculate this more precisely */
 
121
        device_pm_calculate_percentage (d);     
 
122
 
 
123
        /* try to calculate the time accurately (sic) using the rate */
 
124
        device_pm_calculate_time (d);
247
125
}
248
126
 
249
127
/** 
330
208
 * 
331
209
 *  Returns:                    TRUE
332
210
 *
333
 
 *  Fallback polling method to detect if the ac_adaptor is plugged in 
 
211
 *  Fallback polling method to detect if the ac_adapter is plugged in 
334
212
 *
335
213
 *  Note: This just calls ac_adapter_refresh_poll for each ac_adapter
336
214
 */
369
247
 *
370
248
 *  Fallback polling method called every minute. 
371
249
 *
372
 
 *  Note: This just forces a poll refresh for *every* ac_adaptor
 
250
 *  Note: This just forces a poll refresh for *every* ac_adapter
373
251
 *        and primary battery in the system.
374
252
 */
375
253
static gboolean
418
296
}
419
297
 
420
298
/** 
421
 
 *  battery_refresh_remove:
422
 
 *  @d:         Valid battery HalDevice
423
 
 *
424
 
 *  Removes all the possible battery.* keys. 
425
 
 *
426
 
 *  Note: Removing a key that doesn't exist is OK.
427
 
 */
428
 
static void
429
 
battery_refresh_remove (HalDevice *d)
430
 
{
431
 
        hal_device_property_remove (d, "battery.is_rechargeable");
432
 
        hal_device_property_remove (d, "battery.rechargeable.is_charging");
433
 
        hal_device_property_remove (d, "battery.rechargeable.is_discharging");
434
 
        hal_device_property_remove (d, "battery.vendor");
435
 
        hal_device_property_remove (d, "battery.model");
436
 
        hal_device_property_remove (d, "battery.serial");
437
 
        hal_device_property_remove (d, "battery.reporting.technology");
438
 
        hal_device_property_remove (d, "battery.technology");
439
 
        hal_device_property_remove (d, "battery.vendor");
440
 
        hal_device_property_remove (d, "battery.charge_level.unit");
441
 
        hal_device_property_remove (d, "battery.charge_level.current");
442
 
        hal_device_property_remove (d, "battery.charge_level.percentage");
443
 
        hal_device_property_remove (d, "battery.charge_level.last_full");
444
 
        hal_device_property_remove (d, "battery.charge_level.design");
445
 
        hal_device_property_remove (d, "battery.charge_level.capacity_state");
446
 
        hal_device_property_remove (d, "battery.charge_level.warning");
447
 
        hal_device_property_remove (d, "battery.charge_level.low");
448
 
        hal_device_property_remove (d, "battery.charge_level.granularity_1");
449
 
        hal_device_property_remove (d, "battery.charge_level.granularity_2");
450
 
        hal_device_property_remove (d, "battery.charge_level.rate");
451
 
        hal_device_property_remove (d, "battery.voltage.unit");
452
 
        hal_device_property_remove (d, "battery.voltage.design");
453
 
        hal_device_property_remove (d, "battery.voltage.current");
454
 
        hal_device_property_remove (d, "battery.alarm.unit");
455
 
        hal_device_property_remove (d, "battery.alarm.design");
456
 
        hal_device_property_remove (d, "battery.reporting.current");
457
 
        hal_device_property_remove (d, "battery.reporting.last_full");
458
 
        hal_device_property_remove (d, "battery.reporting.design");
459
 
        hal_device_property_remove (d, "battery.reporting.rate");
460
 
        hal_device_property_remove (d, "battery.reporting.warning");
461
 
        hal_device_property_remove (d, "battery.reporting.low");
462
 
        hal_device_property_remove (d, "battery.reporting.granularity_1");
463
 
        hal_device_property_remove (d, "battery.reporting.granularity_2");
464
 
        hal_device_property_remove (d, "battery.reporting.unit");
465
 
        hal_device_property_remove (d, "battery.remaining_time");
466
 
}
467
 
 
468
 
/** 
469
299
 *  battery_refresh_add:
470
300
 *  @d:         Valid battery HalDevice
471
301
 *
505
335
                                                util_get_battery_technology (technology));
506
336
        }
507
337
 
508
 
        /*
509
 
         * we'll use the .reporting prefix as we don't know
510
 
         * if this data is energy (mWh) or unit enery (mAh)
511
 
         */
 
338
        /* we'll use the .reporting prefix as we don't know
 
339
         * if this data is energy (mWh) or unit enery (mAh) */
512
340
        hal_util_set_string_elem_from_file (d, "battery.reporting.unit", path,
513
341
                                         "info", "design capacity", 1, TRUE);
514
342
        hal_util_set_int_elem_from_file (d, "battery.reporting.last_full", path,
523
351
                                         "info", "capacity granularity 1", 0, 10, TRUE);
524
352
        hal_util_set_int_elem_from_file (d, "battery.reporting.granularity_2", path,
525
353
                                         "info", "capacity granularity 2", 0, 10, TRUE);
526
 
        /*
527
 
         * we'll need this is we want to convert mAh to mWh
528
 
         */
 
354
        /* we'll need this is we want to convert mAh to mWh */
529
355
        hal_util_set_string_elem_from_file (d, "battery.voltage.unit", path, "info",
530
356
                                            "design voltage", 1, TRUE);
531
357
        hal_util_set_int_elem_from_file (d, "battery.voltage.design", path,
532
358
                                         "info", "design voltage", 0, 10, TRUE);
533
 
        /*
534
 
         * Convert the mWh or mAh units into mWh...
535
 
         * We'll do as many as we can here as the values
536
 
         * are not going to change.
537
 
         * We'll set the correct unit (or unknown) also.
538
 
         */
 
359
 
 
360
        /* Convert the mWh or mAh units into mWh...
 
361
         * We'll do as many as we can here as the values are not going to change.
 
362
         * We'll set the correct unit (or unknown) also. */
539
363
        reporting_unit = hal_device_property_get_string (d, "battery.reporting.unit");
540
364
        reporting_design = hal_device_property_get_int (d, "battery.reporting.design");
541
365
        reporting_warning = hal_device_property_get_int (d, "battery.reporting.warning");
565
389
                /* set unit */
566
390
                hal_device_property_set_string (d, "battery.charge_level.unit", "mWh"); /* not mAh! */
567
391
        } else {
568
 
                /*
569
 
                 * Some ACPI BIOS's do not report the unit, so we'll assume they are mWh.
570
 
                 * We will report the guessing with the battery.charge_level.unit key.
571
 
                 */
 
392
                /* Some ACPI BIOS's do not report the unit, so we'll assume they are mWh.
 
393
                 * We will report the guessing with the battery.charge_level.unit key. */
572
394
                hal_device_property_set_int (d, "battery.charge_level.design", reporting_design);
573
395
                hal_device_property_set_int (d, "battery.charge_level.warning", reporting_warning);
574
396
                hal_device_property_set_int (d, "battery.charge_level.low", reporting_low);
593
415
 
594
416
        /* we are assuming a laptop battery is rechargeable */
595
417
        hal_device_property_set_bool (d, "battery.is_rechargeable", TRUE);
 
418
 
 
419
        /* we need to populate the processed 'charge_level' keys handling odd quirks */
 
420
        device_pm_abstract_props (d);
 
421
 
596
422
        return TRUE;
597
423
}
598
424
 
626
452
        if (!hal_device_property_get_bool (d, "battery.present")) {
627
453
                /* remove battery.* tags as battery not present */
628
454
                device_property_atomic_update_begin ();
629
 
                battery_refresh_remove (d);
 
455
                device_pm_remove_optional_props (d);
630
456
                device_property_atomic_update_end ();           
631
457
        } else {
632
458
                /* battery is present */
811
637
                br_levels = 8;
812
638
        } else if (acpi_type == ACPI_TYPE_OMNIBOOK_DISPLAY) {
813
639
                gchar *proc_lcd;
814
 
                gchar proc_path[HAL_PATH_MAX];  
815
640
                int current = -1;
816
641
                int max = -1;
817
642
 
821
646
                 * There are different support brightness level, depending on 
822
647
                 * the hardware and the kernel module version.
823
648
                 */
824
 
                snprintf (proc_path, sizeof (proc_path), "%s/%s", get_hal_proc_path (), "omnibook");
825
 
                proc_lcd = hal_util_grep_file(proc_path, "lcd", "LCD brightness:", FALSE);
 
649
                proc_lcd = hal_util_grep_file("/proc/omnibook", "lcd", "LCD brightness:", FALSE);
826
650
                proc_lcd = g_strstrip (proc_lcd);
827
651
                if (sscanf (proc_lcd, "%d (max value: %d)", &current, &max) == 2) {     
828
652
                        br_levels = max + 1;
915
739
 *  acpi_synthesize:
916
740
 *  @path:              The ACPI path, e.g. "/proc/acpi/battery"
917
741
 *  @acpi_type:         The type of device, e.g. ACPI_TYPE_BATTERY
 
742
 *  @synthesize:        If a device should get synthesized
918
743
 *
919
744
 *  Synthesizes generic acpi objects, i.e. registers all the objects of type
920
745
 *  into HAL. This lets us have more than one type of device e.g. BATx
921
746
 *  in the same battery class. 
922
747
 */
923
748
static void
924
 
acpi_synthesize (const gchar *path, int acpi_type)
 
749
acpi_synthesize (const gchar *path, int acpi_type, gboolean synthesize)
925
750
{
926
751
        const gchar *f;
927
 
        gchar _path[HAL_PATH_MAX];
928
752
        gboolean is_laptop = FALSE;
929
753
        GDir *dir;
930
754
        GError *error = NULL;
945
769
                        if ( acpi_type == ACPI_TYPE_BATTERY ) { 
946
770
                                is_laptop = TRUE;
947
771
                        } else if ( acpi_type == ACPI_TYPE_BUTTON ) {
948
 
                                snprintf (_path, sizeof (_path), "%s/acpi/button/lid", get_hal_proc_path ());
949
 
                                if ( strcmp (path, _path) == 0 )
 
772
                                if ( strcmp (path, "/proc/acpi/button/lid") == 0 )
950
773
                                        is_laptop = TRUE;
951
774
                        } else if (_have_sysfs_lid_button) {
952
775
                                is_laptop = TRUE;
964
787
                        }
965
788
                }
966
789
 
967
 
                snprintf (buf, sizeof (buf), "%s/%s", path, f);
968
 
                acpi_synthesize_item (buf, acpi_type);
 
790
                if (synthesize) {
 
791
                        snprintf (buf, sizeof (buf), "%s/%s", path, f);
 
792
                        acpi_synthesize_item (buf, acpi_type);
 
793
                }
969
794
        }
970
795
 
971
796
        /* close directory */
985
810
acpi_synthesize_display (char *vendor, char *display, int method)
986
811
{
987
812
        gchar path[HAL_PATH_MAX];
988
 
        snprintf (path, sizeof (path), "%s/%s/%s", get_hal_proc_path (), vendor, display);
 
813
        snprintf (path, sizeof (path), "/proc/%s/%s", vendor, display);
989
814
        /*
990
815
         * We do not use acpi_synthesize as the target is not a directory full
991
816
         * of directories, but a flat file list.
1053
878
acpi_synthesize_hotplug_events (void)
1054
879
{
1055
880
        HalDevice *computer;
1056
 
        gchar path[HAL_PATH_MAX];
1057
881
 
1058
882
        if (!g_file_test ("/proc/acpi/", G_FILE_TEST_IS_DIR))
1059
883
                return FALSE;
1070
894
                hal_util_set_string_elem_from_file (computer, "power_management.acpi.linux.version",
1071
895
                                                    "/proc/acpi", "info", "version", 0, FALSE);
1072
896
        } else {
1073
 
                gchar *firmware_path;
1074
 
                firmware_path = g_strdup_printf ("%s/firmware/acpi", get_hal_sysfs_path ());
1075
 
                hal_util_set_string_elem_from_file (computer, "power_management.acpi.linux.version",
1076
 
                                                    firmware_path, "info", "version", 0, FALSE);
1077
 
                g_free (firmware_path);
 
897
                if (!hal_util_set_string_from_file (computer, "power_management.acpi.linux.version",
 
898
                                                    "/sys/module/acpi/parameters", "acpica_version"))
 
899
                        /* Fallback for some older kernel version, can get removed if HAL depends on >= 2.6.21 */
 
900
                        hal_util_set_string_elem_from_file (computer, "power_management.acpi.linux.version",
 
901
                                                            "/sys/firmware/acpi", "info", "version", 0, FALSE);
1078
902
        }
1079
903
 
1080
904
        /* collect batteries */
1081
 
        snprintf (path, sizeof (path), "%s/acpi/battery", get_hal_proc_path ());
1082
 
        acpi_synthesize (path, ACPI_TYPE_BATTERY);
1083
 
 
 
905
        acpi_synthesize ("/proc/acpi/battery", ACPI_TYPE_BATTERY, TRUE);
1084
906
        /* collect processors */
1085
 
        snprintf (path, sizeof (path), "%s/acpi/processor", get_hal_proc_path ());
1086
 
        acpi_synthesize (path, ACPI_TYPE_PROCESSOR);
1087
 
 
 
907
        acpi_synthesize ("/proc/acpi/processor", ACPI_TYPE_PROCESSOR, TRUE);
1088
908
        /* collect fans */
1089
 
        snprintf (path, sizeof (path), "%s/acpi/fan", get_hal_proc_path ());
1090
 
        acpi_synthesize (path, ACPI_TYPE_FAN);
1091
 
 
 
909
        acpi_synthesize ("/proc/acpi/fan", ACPI_TYPE_FAN, TRUE);
1092
910
        /* collect AC adapters */
1093
 
        snprintf (path, sizeof (path), "%s/acpi/ac_adapter", get_hal_proc_path ());
1094
 
        acpi_synthesize (path, ACPI_TYPE_AC_ADAPTER);
 
911
        acpi_synthesize ("/proc/acpi/ac_adapter", ACPI_TYPE_AC_ADAPTER, TRUE);
1095
912
 
1096
913
        /* collect buttons */
1097
 
        snprintf (path, sizeof (path), "%s/acpi/button/lid", get_hal_proc_path ());
1098
 
        acpi_synthesize (path, ACPI_TYPE_BUTTON);
1099
 
        snprintf (path, sizeof (path), "%s/acpi/button/power", get_hal_proc_path ());
1100
 
        acpi_synthesize (path, ACPI_TYPE_BUTTON);
1101
 
        snprintf (path, sizeof (path), "%s/acpi/button/sleep", get_hal_proc_path ());
1102
 
        acpi_synthesize (path, ACPI_TYPE_BUTTON);
 
914
        acpi_synthesize ("/proc/acpi/button/lid", ACPI_TYPE_BUTTON, TRUE);
 
915
        acpi_synthesize ("/proc/acpi/button/power", ACPI_TYPE_BUTTON, TRUE);
 
916
        acpi_synthesize ("/proc/acpi/button/sleep", ACPI_TYPE_BUTTON, TRUE);
1103
917
 
1104
918
        /*
1105
919
         * Collect video adaptors (from vendor added modules)
1464
1278
        hotplug_event->acpi.acpi_type = acpi_type;
1465
1279
        return hotplug_event;
1466
1280
}
 
1281
 
 
1282
void 
 
1283
acpi_check_is_laptop (const gchar *acpi_type) 
 
1284
{
 
1285
        if (acpi_type != NULL) {
 
1286
 
 
1287
                if (strcmp (acpi_type, "BATTERY") == 0) {
 
1288
                        acpi_synthesize ("/proc/acpi/battery", ACPI_TYPE_BATTERY, FALSE);
 
1289
                } else if (strcmp (acpi_type, "LID") == 0) {
 
1290
                        acpi_synthesize ("/proc/acpi/button/lid", ACPI_TYPE_BUTTON, FALSE);
 
1291
                } 
 
1292
        }
 
1293
}