*** linux/arch/i386/kernel/apm.c.orig 2004-05-08 13:56:30.000000000 +0100 --- linux/arch/i386/kernel/apm.c 2004-07-15 22:25:35.968559752 +0100 *************** *** 41,46 **** --- 41,47 ---- * Oct 2001, Version 1.15 * Jan 2002, Version 1.16 * Oct 2002, Version 1.16ac + * Jul 2004, Version 1.16acd * * History: * 0.6b: first version in official kernel, Linux 1.3.46 *************** *** 181,186 **** --- 182,188 ---- * 1.16ac: Fix up SMP support somewhat. You can now force SMP on and we * make _all_ APM calls on the CPU#0. Fix unsafe sign bug. * TODO: determine if its "boot CPU" or "CPU0" we want to lock to. + * 1.16acd: Add multiple battery support to /proc/apm * * APM 1.1 Reference: * *************** *** 426,432 **** static spinlock_t user_list_lock = SPIN_LOCK_UNLOCKED; static struct desc_struct bad_bios_desc = { 0, 0x00409200 }; ! static char driver_version[] = "1.16ac"; /* no spaces */ /* * APM event names taken from the APM 1.2 specification. These are --- 428,434 ---- static spinlock_t user_list_lock = SPIN_LOCK_UNLOCKED; static struct desc_struct bad_bios_desc = { 0, 0x00409200 }; ! static char driver_version[] = "1.16acd"; /* no spaces */ /* * APM event names taken from the APM 1.2 specification. These are *************** *** 990,996 **** return APM_SUCCESS; } - #if 0 static int apm_get_battery_status(u_short which, u_short *status, u_short *bat, u_short *life, u_short *nbat) { --- 992,997 ---- *************** *** 1017,1023 **** *nbat = esi; return APM_SUCCESS; } - #endif /** * apm_engage_power_management - enable PM on a device --- 1018,1023 ---- *************** *** 1617,1622 **** --- 1617,1625 ---- int percentage = -1; int time_units = -1; char *units = "?"; + u_short status, bat, life, nbat, tmp; + int bpercent, blife, bflags = 0, i; + char *bunits; p = buf; *************** *** 1685,1690 **** --- 1688,1737 ---- time_units, units); + + /* + * Look for details of multiple batteries + * If it finds any info then it will all a line with + * just nbat and follow that with one or more lines of + * bat_index status flags percent life units + * + * We always check at least 2 batteries and more if moer are indicated. + */ + apm_get_battery_status(1, &status, &bat, &life, &nbat); + // if ((nbat > 1) && (nbat <= APM_MAX_BATTERIES)) + { + int done_a_battery = 0; + if (((p - buf) + nbat * 30 + 10) > length) + return p - buf; + for (i = 1; i<=((nbat < 2)?2:nbat); i++) { + apm_get_battery_status(i, &status, &bat, &life, &tmp); + status &= 0xff; + if ((bat &0xff) != 0xff) + bpercent = bat & 0xff; + else + bpercent = -1; + if (apm_info.connection_version > 0x100) { + bflags = (bat >> 8) & 0xff; + if (life != 0xffff) { + blife = life & 0x7fff; + bunits = (life & 0x8000) ? "min" : "sec"; + } else { + if (bpercent == -1) // don't bother to report if nothing worth knowing. + continue; + blife = -1; + bunits = "?"; + } + } + + if (!done_a_battery) { + p += sprintf(p, "%d\n", nbat); + done_a_battery++; + } + p+= sprintf(p, "%d 0x%02x 0x%02x %d%% %d %s\n", i, status, bflags, bpercent, blife, bunits); + } + } + + return p - buf; }