Add support for trixie.
Apparently things start differently with trixie, so modified the system monitor code to keep trying to allocate the resources it needs (and adapter and a client to the i2c bus). This mades the code work, and startup is not affected.
This commit is contained in:
@@ -1,14 +1,8 @@
|
|||||||
|
|
||||||
sudo cp -vf oneUpPower.ko /lib/modules/`uname -r`/kernel/drivers/power/supply/oneUpPower.ko
|
sudo cp -vf oneUpPower.ko /lib/modules/`uname -r`/kernel/drivers/power/supply/oneUpPower.ko
|
||||||
|
sudo depmod -a
|
||||||
ls /lib/modules/`uname -r`/kernel/drivers/power/supply/
|
ls /lib/modules/`uname -r`/kernel/drivers/power/supply/
|
||||||
sudo insmod oneUpPower.ko
|
sudo insmod oneUpPower.ko
|
||||||
|
sync
|
||||||
#ls -l /sys/class/power_supply/BAT0
|
|
||||||
#cat /sys/class/power_supply/BAT0/uevent
|
|
||||||
#cat /sys/class/power_supply/BAT0/capacity
|
|
||||||
#cat /sys/class/power_supply/BAT0/status
|
|
||||||
#
|
|
||||||
#ls -l /sys/class/power_supply/AC0
|
|
||||||
#cat /sys/class/power_supply/AC0/ueven
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -33,21 +33,21 @@ enum test_power_id {
|
|||||||
//
|
//
|
||||||
// Useful definitions. Note that the TOTAL_* definitions need to be worked out...
|
// Useful definitions. Note that the TOTAL_* definitions need to be worked out...
|
||||||
//
|
//
|
||||||
#define DRV_NAME "oneUpPower"
|
#define DRV_NAME "oneUpPower"
|
||||||
#define PR_INFO( fmt, arg...) printk( KERN_INFO DRV_NAME ":" fmt, ##arg )
|
#define PR_INFO( fmt, arg...) printk( KERN_INFO DRV_NAME ":" fmt, ##arg )
|
||||||
#define PR_ERR( fmt, arg... ) printk( KERN_ERR DRV_NAME ":" fmt, ##arg )
|
#define PR_ERR( fmt, arg... ) printk( KERN_ERR DRV_NAME ":" fmt, ##arg )
|
||||||
#define TOTAL_LIFE_SECONDS (6 * 60 * 60) // Time in seconds
|
#define TOTAL_LIFE_SECONDS (6 * 60 * 60) // Time in seconds
|
||||||
#define TOTAL_CHARGE (4800 * 1000) // Power in micro Amp Hours, uAH
|
#define TOTAL_CHARGE (4800 * 1000) // Power in micro Amp Hours, uAH
|
||||||
#define TOTAL_CHARGE_FULL_SECONDS (((2*60)+30) * 60) // Time to full charge in seconds
|
#define TOTAL_CHARGE_FULL_SECONDS (((2*60)+30) * 60) // Time to full charge in seconds
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// I2C Addresses
|
// I2C Addresses
|
||||||
//
|
//
|
||||||
#define I2C_BUS 0x01
|
#define I2C_BUS 0x01
|
||||||
#define BATTERY_ADDR 0x64
|
#define BATTERY_ADDR 0x64
|
||||||
#define CURRENT_HIGH_REG 0x0E
|
#define CURRENT_HIGH_REG 0x0E
|
||||||
#define CURRENT_LOW_REG 0x0F
|
#define CURRENT_LOW_REG 0x0F
|
||||||
#define SOC_HIGH_REG 0x04
|
#define SOC_HIGH_REG 0x04
|
||||||
#define SOC_LOW_REG 0x05
|
#define SOC_LOW_REG 0x05
|
||||||
|
|
||||||
@@ -55,20 +55,20 @@ enum test_power_id {
|
|||||||
// Needed data structures
|
// Needed data structures
|
||||||
//
|
//
|
||||||
struct PowerStatus {
|
struct PowerStatus {
|
||||||
int status; // Status of the power supply
|
int status; // Status of the power supply
|
||||||
int capacity; // Capacity in percentage
|
int capacity; // Capacity in percentage
|
||||||
int capacity_level; // What level are we at, CRITICAL,LOW,NORMAL,HIGH,FULL
|
int capacity_level; // What level are we at, CRITICAL,LOW,NORMAL,HIGH,FULL
|
||||||
int health; // State of the battery
|
int health; // State of the battery
|
||||||
int present; // Is the battery present (always YES)
|
int present; // Is the battery present (always YES)
|
||||||
int technology; // What technology is the battery (LION)
|
int technology; // What technology is the battery (LION)
|
||||||
int timeleft; // How much time to we have left in seconds
|
int timeleft; // How much time to we have left in seconds
|
||||||
int temperature; // What is the battery temperature
|
int temperature; // What is the battery temperature
|
||||||
int voltage; // What is the current voltage of the battery
|
int voltage; // What is the current voltage of the battery
|
||||||
|
|
||||||
} battery = {
|
} battery = {
|
||||||
.status = POWER_SUPPLY_STATUS_DISCHARGING,
|
.status = POWER_SUPPLY_STATUS_DISCHARGING,
|
||||||
.capacity = 90,
|
.capacity = 100,
|
||||||
.capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_HIGH,
|
.capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_HIGH,
|
||||||
.health = POWER_SUPPLY_HEALTH_GOOD,
|
.health = POWER_SUPPLY_HEALTH_GOOD,
|
||||||
.present = 1,
|
.present = 1,
|
||||||
.technology = POWER_SUPPLY_TECHNOLOGY_LION,
|
.technology = POWER_SUPPLY_TECHNOLOGY_LION,
|
||||||
@@ -81,18 +81,18 @@ struct PowerStatus {
|
|||||||
// Forward declairations
|
// Forward declairations
|
||||||
//
|
//
|
||||||
static int get_battery_property(struct power_supply *psy,
|
static int get_battery_property(struct power_supply *psy,
|
||||||
enum power_supply_property psp,
|
enum power_supply_property psp,
|
||||||
union power_supply_propval *val);
|
union power_supply_propval *val);
|
||||||
static int get_ac_property(struct power_supply *psy,
|
static int get_ac_property(struct power_supply *psy,
|
||||||
enum power_supply_property psp,
|
enum power_supply_property psp,
|
||||||
union power_supply_propval *val );
|
union power_supply_propval *val );
|
||||||
|
|
||||||
//
|
//
|
||||||
// Globals
|
// Globals
|
||||||
//
|
//
|
||||||
static int critical_power_level = 5; // Default setting is 5% of power left for critical
|
static int critical_power_level = 5; // Default setting is 5% of power left for critical
|
||||||
static int ac_online = 1; // Are we connected to an external power source?
|
static int ac_online = 1; // Are we connected to an external power source?
|
||||||
static bool module_initialized = false; // Has the driver been initialized?
|
static bool module_initialized = false; // Has the driver been initialized?
|
||||||
static struct task_struct *monitor_task = NULL; // Place to store the monito task...
|
static struct task_struct *monitor_task = NULL; // Place to store the monito task...
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -239,7 +239,13 @@ static int check_ac_power( struct i2c_client *client )
|
|||||||
if( ac_online != plugged_in ){
|
if( ac_online != plugged_in ){
|
||||||
ac_online = plugged_in;
|
ac_online = plugged_in;
|
||||||
set_power_states();
|
set_power_states();
|
||||||
//power_supply_changed( power_supplies[ONEUP_AC] );
|
if( ac_online ){
|
||||||
|
PR_INFO( "AC Power is connected.\n" );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PR_INFO( "AC Power is disconnected.\n" );
|
||||||
|
}
|
||||||
|
power_supply_changed( power_supplies[ONEUP_AC] );
|
||||||
}
|
}
|
||||||
|
|
||||||
return plugged_in;
|
return plugged_in;
|
||||||
@@ -317,46 +323,44 @@ static int system_monitor( void *args )
|
|||||||
int plugged_in;
|
int plugged_in;
|
||||||
|
|
||||||
PR_INFO( "Starting system monitor...\n" );
|
PR_INFO( "Starting system monitor...\n" );
|
||||||
|
|
||||||
//
|
|
||||||
// Get an adapter so we can make an i2c client...
|
|
||||||
//
|
|
||||||
adapter = i2c_get_adapter( I2C_BUS );
|
|
||||||
if( adapter == NULL ){
|
|
||||||
PR_ERR( "Unable to get i2c adapter!\n" );
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
PR_INFO( "Created an I2C adapter...\n" );
|
|
||||||
|
|
||||||
//
|
|
||||||
// Build the i2c client...
|
|
||||||
//
|
|
||||||
client = i2c_new_client_device( adapter, &board_info );
|
|
||||||
if( client == NULL ){
|
|
||||||
PR_ERR( "Unable to create i2c client!\n" );
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PR_INFO( "Created an I2C client device...\n" );
|
|
||||||
|
|
||||||
//
|
|
||||||
// Monitor until we are done...
|
|
||||||
//
|
|
||||||
while( true ){
|
while( true ){
|
||||||
set_current_state( TASK_UNINTERRUPTIBLE );
|
//
|
||||||
if( kthread_should_stop() )
|
// Get an adapter so we can make an i2c client...
|
||||||
break;
|
//
|
||||||
|
if( adapter == NULL ){
|
||||||
|
//
|
||||||
|
// get an adapter
|
||||||
|
//
|
||||||
|
set_current_state( TASK_INTERRUPTIBLE );
|
||||||
|
adapter = i2c_get_adapter( I2C_BUS );
|
||||||
|
PR_INFO( "Adapter = %p\n",adapter);
|
||||||
|
}
|
||||||
|
else if( client == NULL ){
|
||||||
|
//
|
||||||
|
// Get a i2c client
|
||||||
|
//
|
||||||
|
set_current_state( TASK_INTERRUPTIBLE );
|
||||||
|
client = i2c_new_client_device( adapter, &board_info );
|
||||||
|
PR_INFO( "Client = %p\n",client);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
set_current_state( TASK_UNINTERRUPTIBLE );
|
||||||
|
if( kthread_should_stop() ){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
plugged_in = check_ac_power( client );
|
plugged_in = check_ac_power( client );
|
||||||
soc = check_battery_state( client );
|
soc = check_battery_state( client );
|
||||||
|
|
||||||
set_current_state( TASK_INTERRUPTIBLE );
|
set_current_state( TASK_INTERRUPTIBLE );
|
||||||
if( !plugged_in && (soc <= critical_power_level) ){
|
if( !plugged_in && (soc < critical_power_level) ){
|
||||||
// not pluggged in and below critical state, shutdown.
|
// not pluggged in and below critical state, shutdown
|
||||||
PR_INFO( "Performing system shutdown unplugged and power is at %d\n",soc);
|
PR_INFO( "Performing system shutdown unplugged and power is at %d\n",soc);
|
||||||
shutdown_helper();
|
shutdown_helper();
|
||||||
}
|
}
|
||||||
schedule_timeout( HZ );
|
}
|
||||||
|
schedule_timeout( HZ );
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -370,8 +374,8 @@ static int system_monitor( void *args )
|
|||||||
|
|
||||||
if( adapter )
|
if( adapter )
|
||||||
{
|
{
|
||||||
i2c_put_adapter( adapter );
|
i2c_put_adapter( adapter );
|
||||||
adapter = NULL;
|
adapter = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
PR_INFO( "System monitor is stopping...\n" );
|
PR_INFO( "System monitor is stopping...\n" );
|
||||||
@@ -394,15 +398,15 @@ static int system_monitor( void *args )
|
|||||||
// 0 - Successfuly located the data
|
// 0 - Successfuly located the data
|
||||||
//
|
//
|
||||||
static int get_ac_property(struct power_supply *psy,
|
static int get_ac_property(struct power_supply *psy,
|
||||||
enum power_supply_property psp,
|
enum power_supply_property psp,
|
||||||
union power_supply_propval *val)
|
union power_supply_propval *val)
|
||||||
{
|
{
|
||||||
switch (psp) {
|
switch (psp) {
|
||||||
case POWER_SUPPLY_PROP_ONLINE:
|
case POWER_SUPPLY_PROP_ONLINE:
|
||||||
val->intval = ac_online;
|
val->intval = ac_online;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -425,57 +429,56 @@ static int get_ac_property(struct power_supply *psy,
|
|||||||
// 0 - Succssfully located the data
|
// 0 - Succssfully located the data
|
||||||
//
|
//
|
||||||
static int get_battery_int_property( struct power_supply *psy,
|
static int get_battery_int_property( struct power_supply *psy,
|
||||||
enum power_supply_property psp,
|
enum power_supply_property psp,
|
||||||
union power_supply_propval *val )
|
union power_supply_propval *val )
|
||||||
{
|
{
|
||||||
switch( psp ) {
|
switch( psp ) {
|
||||||
case POWER_SUPPLY_PROP_STATUS:
|
case POWER_SUPPLY_PROP_STATUS:
|
||||||
val->intval = battery.status;
|
val->intval = battery.status;
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_CHARGE_TYPE:
|
case POWER_SUPPLY_PROP_CHARGE_TYPE:
|
||||||
val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
|
val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_HEALTH:
|
case POWER_SUPPLY_PROP_HEALTH:
|
||||||
val->intval = battery.health;
|
val->intval = battery.health;
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_PRESENT:
|
case POWER_SUPPLY_PROP_PRESENT:
|
||||||
val->intval = battery.present;
|
val->intval = battery.present;
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_TECHNOLOGY:
|
case POWER_SUPPLY_PROP_TECHNOLOGY:
|
||||||
val->intval = battery.technology;
|
val->intval = battery.technology;
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
|
case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
|
||||||
val->intval = battery.capacity_level;
|
val->intval = battery.capacity_level;
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_CAPACITY:
|
case POWER_SUPPLY_PROP_CAPACITY:
|
||||||
val->intval = battery.capacity;
|
val->intval = battery.capacity;
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_CHARGE_EMPTY:
|
case POWER_SUPPLY_PROP_CHARGE_EMPTY:
|
||||||
val->intval = 0;
|
val->intval = 0;
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_CHARGE_NOW:
|
case POWER_SUPPLY_PROP_CHARGE_NOW:
|
||||||
val->intval = battery.capacity * TOTAL_CHARGE / 100;
|
val->intval = battery.capacity * TOTAL_CHARGE / 100;
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
|
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
|
||||||
case POWER_SUPPLY_PROP_CHARGE_FULL:
|
case POWER_SUPPLY_PROP_CHARGE_FULL:
|
||||||
val->intval = TOTAL_CHARGE;
|
val->intval = TOTAL_CHARGE;
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
|
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
|
||||||
val->intval = battery.timeleft;
|
val->intval = battery.timeleft;
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
|
case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
|
||||||
val->intval = (100 - battery.capacity) * TOTAL_CHARGE_FULL_SECONDS / 100;
|
val->intval = (100 - battery.capacity) * TOTAL_CHARGE_FULL_SECONDS / 100;
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_TEMP:
|
case POWER_SUPPLY_PROP_TEMP:
|
||||||
val->intval = battery.temperature;
|
val->intval = battery.temperature;
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||||
val->intval = battery.voltage;
|
val->intval = battery.voltage;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PR_INFO("%s: some properties deliberately report errors.\n",
|
PR_INFO("%s: some properties deliberately report errors.\n",__func__);
|
||||||
__func__);
|
return -EINVAL;
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -497,21 +500,21 @@ static int get_battery_int_property( struct power_supply *psy,
|
|||||||
// 0 - Successfuly located the data
|
// 0 - Successfuly located the data
|
||||||
//
|
//
|
||||||
static int get_battery_property(struct power_supply *psy,
|
static int get_battery_property(struct power_supply *psy,
|
||||||
enum power_supply_property psp,
|
enum power_supply_property psp,
|
||||||
union power_supply_propval *val)
|
union power_supply_propval *val)
|
||||||
{
|
{
|
||||||
switch (psp) {
|
switch (psp) {
|
||||||
case POWER_SUPPLY_PROP_MODEL_NAME:
|
case POWER_SUPPLY_PROP_MODEL_NAME:
|
||||||
val->strval = "oneUp Battery";
|
val->strval = "oneUp Battery";
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_MANUFACTURER:
|
case POWER_SUPPLY_PROP_MANUFACTURER:
|
||||||
val->strval = "Argon40";
|
val->strval = "Argon40";
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_SERIAL_NUMBER:
|
case POWER_SUPPLY_PROP_SERIAL_NUMBER:
|
||||||
val->strval = UTS_RELEASE;
|
val->strval = UTS_RELEASE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return get_battery_int_property( psy, psp, val );
|
return get_battery_int_property( psy, psp, val );
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -537,11 +540,10 @@ static int __init oneup_power_init(void)
|
|||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(power_supplies); i++) {
|
for (i = 0; i < ARRAY_SIZE(power_supplies); i++) {
|
||||||
power_supplies[i] = power_supply_register(NULL,
|
power_supplies[i] = power_supply_register(NULL,
|
||||||
&power_descriptions[i],
|
&power_descriptions[i],
|
||||||
&power_configs[i]);
|
&power_configs[i]);
|
||||||
if (IS_ERR(power_supplies[i])) {
|
if (IS_ERR(power_supplies[i])) {
|
||||||
PR_ERR("%s: failed to register %s\n", __func__,
|
PR_ERR("%s: failed to register %s\n", __func__, power_descriptions[i].name);
|
||||||
power_descriptions[i].name);
|
|
||||||
ret = PTR_ERR(power_supplies[i]);
|
ret = PTR_ERR(power_supplies[i]);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
@@ -550,7 +552,7 @@ static int __init oneup_power_init(void)
|
|||||||
monitor_task = kthread_run( system_monitor, NULL, "argon40_monitor" );
|
monitor_task = kthread_run( system_monitor, NULL, "argon40_monitor" );
|
||||||
if( monitor_task == NULL ){
|
if( monitor_task == NULL ){
|
||||||
PR_ERR( "Could not start system_monitor, terminating.\n" );
|
PR_ERR( "Could not start system_monitor, terminating.\n" );
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -559,13 +561,14 @@ static int __init oneup_power_init(void)
|
|||||||
return 0;
|
return 0;
|
||||||
failed:
|
failed:
|
||||||
if( monitor_task ){
|
if( monitor_task ){
|
||||||
kthread_stop( monitor_task );
|
kthread_stop( monitor_task );
|
||||||
monitor_task = NULL;
|
monitor_task = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (--i >= 0)
|
while (--i >= 0){
|
||||||
power_supply_unregister(power_supplies[i]);
|
power_supply_unregister(power_supplies[i]);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
module_init(oneup_power_init);
|
module_init(oneup_power_init);
|
||||||
@@ -594,8 +597,8 @@ static void __exit oneup_power_exit(void)
|
|||||||
for (i = 0; i < ARRAY_SIZE(power_supplies); i++)
|
for (i = 0; i < ARRAY_SIZE(power_supplies); i++)
|
||||||
power_supply_changed(power_supplies[i]);
|
power_supply_changed(power_supplies[i]);
|
||||||
|
|
||||||
PR_INFO("%s: 'changed' event sent, sleeping for 10 seconds...\n", __func__);
|
//PR_INFO("%s: 'changed' event sent, sleeping for 10 seconds...\n", __func__);
|
||||||
ssleep(10);
|
//ssleep(10);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(power_supplies); i++)
|
for (i = 0; i < ARRAY_SIZE(power_supplies); i++)
|
||||||
power_supply_unregister(power_supplies[i]);
|
power_supply_unregister(power_supplies[i]);
|
||||||
|
|||||||
Reference in New Issue
Block a user