--- src/linux/up-device-supply.c 2012-08-29 21:17:42.000000000 +0200 +++ /home/marcello/git/upower/src/linux/up-device-supply.c 2012-09-18 12:26:40.000000000 +0200 @@ -630,11 +630,44 @@ g_warning ("unknown status string: %s", status); state = UP_DEVICE_STATE_UNKNOWN; } + + /* Workaround for Samsung Series 5 Ultrabook: try to detect inconsistencies + between battery status and AC status, as the battery status (charging\discharging) + is not updated when the laptop is turned on. If the AC is online, then we + set the battery status as CHARGING also if the battery reports itself + as discharging; viceversa, if the AC is offline, then the battery has + to be DISCHARGING... */ + + /* If we have any online AC, assume charging, otherwise + * discharging */ + daemon = up_device_get_daemon (device); + devices = up_device_list_get_array (up_daemon_get_device_list (daemon)); + for (i=0; i < devices->len; i++) { + if (up_device_get_online ((UpDevice *) g_ptr_array_index (devices, i), &online)) { + has_ac = TRUE; + if (online) { + ac_online = TRUE; + } else { + } + break; + } + } + g_ptr_array_unref (devices); + + /* if the status isn't consistent, we set them as UNKNOWN so that they + get treated by the original (working) code to manage this... */ + if( (state == UP_DEVICE_STATE_CHARGING && !ac_online) || + (state ==UP_DEVICE_STATE_DISCHARGING && ac_online)) { + state = UP_DEVICE_STATE_UNKNOWN; + } + + /* end of the workaround*/ /* only disable the polling if the kernel tells us we're fully charged, not if we've guessed the state to be fully charged */ supply->priv->enable_poll = (state != UP_DEVICE_STATE_FULLY_CHARGED); + /* reset unknown counter */ if (state != UP_DEVICE_STATE_UNKNOWN) { g_debug ("resetting unknown timeout after %i retries", supply->priv->unknown_retries); @@ -710,21 +743,10 @@ /* the battery isn't charging or discharging, it's just * sitting there half full doing nothing: try to guess a state */ if (state == UP_DEVICE_STATE_UNKNOWN) { - daemon = up_device_get_daemon (device); + /* If we have any online AC, assume charging, otherwise - * discharging */ - devices = up_device_list_get_array (up_daemon_get_device_list (daemon)); - for (i=0; i < devices->len; i++) { - if (up_device_get_online ((UpDevice *) g_ptr_array_index (devices, i), &online)) { - has_ac = TRUE; - if (online) { - ac_online = TRUE; - } - break; - } - } - g_ptr_array_unref (devices); + * discharging: this code has been moved before... (workaround) */ if (has_ac) { if (ac_online) { @@ -755,8 +777,10 @@ g_debug ("guessing battery state '%s': AC present: %i, AC online: %i", up_device_state_to_string (state), has_ac, ac_online); - g_object_unref (daemon); + } + + g_object_unref (daemon); /* if empty, and BIOS does not know what to do */ if (state == UP_DEVICE_STATE_UNKNOWN && energy < 0.01) { @@ -982,12 +1006,11 @@ break; default: ret = up_device_supply_refresh_battery (supply); - - /* Seems that we don't get change uevents from the - * kernel on some BIOS types */ - up_device_supply_setup_poll (device); break; } + /* Seems that we don't get change uevents from the + * kernel on some BIOS types */ + up_device_supply_setup_poll (device); /* To make workaround work, we need to setup poll also for AC devices! */ /* reset time if we got new data */ if (ret) {