|
|
int version; /* PMU version */ | int version; /* PMU version */ |
char *identity; /* Identity string of this laptop */ | char *identity; /* Identity string of this laptop */ |
struct modflags_pmac flags; | struct modflags_pmac flags; |
|
int flagschanged; /* PMU flags that have changed recently */ |
int oharevolbutton; /* level of volume button on OHARE PBs scaled to 0..100 */ | int oharevolbutton; /* level of volume button on OHARE PBs scaled to 0..100 */ |
int oharebrightbutton; /* level of brightness button on OHARE PBs scaled to 0..15 */ | int oharebrightbutton; /* level of brightness button on OHARE PBs scaled to 0..15 */ |
| |
|
|
base->identity = identitystring; | base->identity = identitystring; |
ioctl(base->fd_pmu, PMU_IOC_CAN_SLEEP, &val); | ioctl(base->fd_pmu, PMU_IOC_CAN_SLEEP, &val); |
base->flags.sleepsupported = val == 1 ? 1 : 0; /* check if sleep is supported on this system */ | base->flags.sleepsupported = val == 1 ? 1 : 0; /* check if sleep is supported on this system */ |
val = pmac_update_flags (); |
|
pmac_update_batteryinfo (val); |
pmac_update_flags (); |
|
pmac_update_batteryinfo (); |
|
base->flagschanged = 0; |
| |
/* Every frame buffer driver could register a backlight controller, | /* Every frame buffer driver could register a backlight controller, |
* but only the right one is accepted. Verification is done by checking | * but only the right one is accepted. Verification is done by checking |
|
|
pmac_secure (struct tagitem *taglist) | pmac_secure (struct tagitem *taglist) |
{ | { |
struct moddata_pmac *base = &modbase_pmac; | struct moddata_pmac *base = &modbase_pmac; |
int cf; |
|
| |
if (base->flags.set_tpmode == 1) { | if (base->flags.set_tpmode == 1) { |
base->flags.set_tpmode = 0; | base->flags.set_tpmode = 0; |
|
|
process_queue_single (CONFIGQUEUE, TAG_PREPAREFORSLEEP, 0); | process_queue_single (CONFIGQUEUE, TAG_PREPAREFORSLEEP, 0); |
#ifdef WITH_PMUD | #ifdef WITH_PMUD |
activate_sleepmode (); | activate_sleepmode (); |
cf = pmac_update_flags (); |
base->flagschanged = pmac_update_flags (); |
#else | #else |
do { | do { |
activate_sleepmode (); | activate_sleepmode (); |
cf = pmac_update_flags (); |
base->flagschanged = pmac_update_flags (); |
} while (cf != -1 && base->flags.coveropen == 0); |
} while (base->flags.coveropen == 0); |
#endif | #endif |
base->timeleft = 7200; /* reset time value so that the */ | base->timeleft = 7200; /* reset time value so that the */ |
/* filter approximate the real value from top. Otherwise */ | /* filter approximate the real value from top. Otherwise */ |
|
|
/* thresholds quick enough. This problem occours only */ | /* thresholds quick enough. This problem occours only */ |
/* after wakeup on battery after the battery had been */ | /* after wakeup on battery after the battery had been */ |
/* recharged during sleep. */ | /* recharged during sleep. */ |
pmac_update_batteryinfo (cf); |
pmac_update_batteryinfo (); |
process_queue_single (CONFIGQUEUE, TAG_WAKEUPFROMSLEEP, 0); | process_queue_single (CONFIGQUEUE, TAG_WAKEUPFROMSLEEP, 0); |
base->batlog_cycle = batlog_setup(); | base->batlog_cycle = batlog_setup(); |
} | } |
|
|
{ | { |
struct moddata_pmac *base = &modbase_pmac; | struct moddata_pmac *base = &modbase_pmac; |
struct tagitem args[6]; | struct tagitem args[6]; |
int val, cf; |
int val; |
| |
taglist_init (args); | taglist_init (args); |
| |
val = base->timeleft; | val = base->timeleft; |
cf = pmac_update_flags (); /* ac power and cover status */ |
if (base->flagschanged == 0) /* check if anybody else has already read the flags */ |
pmac_update_batteryinfo (cf); |
base->flagschanged = pmac_update_flags (); /* if not, get ac power and cover status */ |
|
pmac_update_batteryinfo (); |
| |
if (cf & PMU_ENV_AC_POWER) { |
if (base->flagschanged & PMU_ENV_AC_POWER) { |
taglist_add (args, TAG_POWERCHANGED, base->flags.ac_power); | taglist_add (args, TAG_POWERCHANGED, base->flags.ac_power); |
if (!base->flags.ac_power) /* running on Battery */ | if (!base->flags.ac_power) /* running on Battery */ |
base->batlog_cycle++; /* then increase cycle */ | base->batlog_cycle++; /* then increase cycle */ |
|
|
} | } |
| |
#ifndef WITH_PMUD | #ifndef WITH_PMUD |
if ((cf != -1) && (cf & PMU_ENV_LID_CLOSED)) |
if (base->flagschanged & PMU_ENV_LID_CLOSED) |
taglist_add (args, TAG_COVERSTATUS, base->flags.coveropen); | taglist_add (args, TAG_COVERSTATUS, base->flags.coveropen); |
#endif | #endif |
if (base->version == OHARE_PMU) { /* PowerBook 3400, etc */ | if (base->version == OHARE_PMU) { /* PowerBook 3400, etc */ |
|
|
| |
if (args[0].tag != TAG_END) | if (args[0].tag != TAG_END) |
process_queue (CONFIGQUEUE, args); /* distribute changes to other modules */ | process_queue (CONFIGQUEUE, args); /* distribute changes to other modules */ |
|
base->flagschanged = 0; |
} | } |
| |
| |
|
|
* ac_power, bat_present and charging. | * ac_power, bat_present and charging. |
*/ | */ |
void | void |
pmac_update_batteryinfo (int cf) |
pmac_update_batteryinfo () |
{ | { |
struct moddata_pmac *base = &modbase_pmac; | struct moddata_pmac *base = &modbase_pmac; |
FILE *fd; | FILE *fd; |
|
|
int val, n, syscurrent, time_rem = 0; | int val, n, syscurrent, time_rem = 0; |
int charge, chargemax, current, voltage, timeleft[MAX_BATTERIES]; | int charge, chargemax, current, voltage, timeleft[MAX_BATTERIES]; |
| |
/* use /proc/pmu/info as fallback, if PMU_GET_COVER did't work |
|
* As I know this has not happend yet and it is doubtable that |
|
* /proc/pmu/info will work correctly in this case. So this |
|
* routine may be removed in future versions. |
|
*/ |
|
if (cf == -1) { |
|
print_error(_("WARNING: Couldn't get AC plug status from hardware, use /proc/pmu/info as fallback.\n")); |
|
print_error(_(" Please send a message to the author if this ever happens.\n")); |
|
if ((fd = fopen ("/proc/pmu/info","r"))) { |
|
while (fgets (buffer, sizeof (buffer), fd)) |
|
if ((token = strtok (buffer,":\n"))) { |
|
if (!strncmp ("AC Power", token, 8)) |
|
base->flags.ac_power = atoi (strtok(0,":\n")); |
|
else |
|
strtok (0,":\n"); |
|
} |
|
fclose(fd); |
|
} |
|
} |
|
|
|
syscurrent = 0; | syscurrent = 0; |
for (n=0; n < MAX_BATTERIES; n++) { | for (n=0; n < MAX_BATTERIES; n++) { |
charge = chargemax = current = voltage = timeleft[n] = 0; | charge = chargemax = current = voltage = timeleft[n] = 0; |
|
|
} | } |
} | } |
| |
|
/* use /proc/pmu/info as fallback, if PMU_GET_COVER did't work |
|
* As I know this has not happend yet and it is doubtable that |
|
* /proc/pmu/info will work correctly in this case. So this |
|
* routine may be removed in future versions. |
|
*/ |
|
int |
|
pmac_get_procac () |
|
{ |
|
FILE *fd; |
|
char buffer[100], *token; |
|
int ac = 0; /* return battery if anything fails */ |
|
|
|
print_error(_("WARNING: Couldn't get AC plug status from hardware, use /proc/pmu/info as fallback.\n")); |
|
print_error(_(" Please send a message to the author if this ever happens.\n")); |
|
if ((fd = fopen ("/proc/pmu/info","r"))) { |
|
while (fgets (buffer, sizeof (buffer), fd)) |
|
if ((token = strtok (buffer,":\n"))) { |
|
if (!strncmp ("AC Power", token, 8)) |
|
ac = atoi (strtok(0,":\n")); |
|
else |
|
strtok (0,":\n"); |
|
} |
|
fclose(fd); |
|
} |
|
return ac; |
|
} |
|
|
|
/* This funtion gets some important flags from the PMU driver. If the |
|
* driver doesn't support the ioctl or reports an error, power source |
|
* will be read from /proc/pmu/info as fallback, so that power source |
|
* should always be set correctly. |
|
*/ |
int | int |
pmac_update_flags() | pmac_update_flags() |
{ | { |
|
|
envnew = base->flags.ac_power ? PMU_ENV_AC_POWER : 0; | envnew = base->flags.ac_power ? PMU_ENV_AC_POWER : 0; |
envnew |= base->flags.coveropen ? PMU_ENV_LID_CLOSED : 0; | envnew |= base->flags.coveropen ? PMU_ENV_LID_CLOSED : 0; |
} else | } else |
return -1; |
base->flags.ac_power = pmac_get_procac(); |
|
|
return (envold ^ envnew); | return (envold ^ envnew); |
} | } |
| |
|
|
| |
/* This function tries to find the I2C device that controls the keyboard | /* This function tries to find the I2C device that controls the keyboard |
* illumination and the ambient light sensor used in alluminum PowerBooks | * illumination and the ambient light sensor used in alluminum PowerBooks |
* It returns the device number on success, otherwise a negative error code |
* It returns the device number on success, otherwise a negative error code. |
|
* The loop starts with device 4 because that's the correct device on |
|
* 17" alluminum PowerBooks. Device 0 could be errornous detected because |
|
* the function uses only circumstantial evidence to detect the correct |
|
* device. |
*/ | */ |
int | int |
lmu_find_bus () | lmu_find_bus () |
|
|
char i2cdevice[20], buf[4]; | char i2cdevice[20], buf[4]; |
int n, fd, rc = -E_NOCHAR; | int n, fd, rc = -E_NOCHAR; |
| |
for(n=0; n < 256; n++) { |
for(n=4; n < 260; n++) { |
snprintf(i2cdevice, 19, "/dev/i2c-%d", n ); |
snprintf(i2cdevice, 19, "/dev/i2c-%d", (n & 255) ); |
if ((fd = open (i2cdevice, O_RDWR)) >= 0 ) { | if ((fd = open (i2cdevice, O_RDWR)) >= 0 ) { |
if (ioctl (fd, I2C_SLAVE, LMU_ADDR) >= 0 ) { | if (ioctl (fd, I2C_SLAVE, LMU_ADDR) >= 0 ) { |
if (read (fd, buf, 4) == 4 ) { | if (read (fd, buf, 4) == 4 ) { |
|
|
rc = n; | rc = n; |
break; | break; |
} | } |
} else |
} |
close (fd); |
close (fd); |
} else if (errno == ENODEV) { | } else if (errno == ENODEV) { |
rc = -E_NOCHAR; | rc = -E_NOCHAR; |
break; | break; |