2 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
26 #include "ss_launch.h"
29 #include "device-node.h"
30 #include "include/ss_data.h"
32 #define BAT_MON_INTERVAL 30
33 #define BAT_MON_INTERVAL_MIN 2
35 #define BATTERY_CHARGING 65535
36 #define BATTERY_UNKNOWN -1
37 #define BATTERY_FULL 100
38 #define BATTERY_NORMAL 100
39 #define BATTERY_WARNING_LOW 15
40 #define BATTERY_CRITICAL_LOW 5
41 #define BATTERY_POWER_OFF 1
42 #define BATTERY_REAL_POWER_OFF 0
44 #define MAX_BATTERY_ERROR 10
45 #define RESET_RETRY_COUNT 3
47 #define LOWBAT_EXEC_PATH PREFIX"/bin/lowbatt-popup"
49 #define BATTERY_LEVEL_CHECK_FULL 95
50 #define BATTERY_LEVEL_CHECK_HIGH 15
51 #define BATTERY_LEVEL_CHECK_LOW 5
52 #define BATTERY_LEVEL_CHECK_CRITICAL 1
54 #define _SYS_LOW_POWER "LOW_POWER"
56 struct lowbat_process_entry {
57 unsigned cur_bat_state;
58 unsigned new_bat_state;
59 int (*action) (void *);
62 static Ecore_Timer *lowbat_timer;
63 static int cur_bat_state = BATTERY_UNKNOWN;
64 static int cur_bat_capacity = -1;
66 static int bat_err_count = 0;
68 static int battery_warning_low_act(void *ad);
69 static int battery_critical_low_act(void *ad);
70 static int battery_power_off_act(void *ad);
72 static struct lowbat_process_entry lpe[] = {
73 {BATTERY_NORMAL, BATTERY_WARNING_LOW, battery_warning_low_act},
74 {BATTERY_WARNING_LOW, BATTERY_CRITICAL_LOW, battery_critical_low_act},
75 {BATTERY_CRITICAL_LOW, BATTERY_POWER_OFF, battery_critical_low_act},
76 {BATTERY_POWER_OFF, BATTERY_REAL_POWER_OFF, battery_power_off_act},
77 {BATTERY_NORMAL, BATTERY_CRITICAL_LOW, battery_critical_low_act},
78 {BATTERY_WARNING_LOW, BATTERY_POWER_OFF, battery_critical_low_act},
79 {BATTERY_CRITICAL_LOW, BATTERY_REAL_POWER_OFF, battery_power_off_act},
80 {BATTERY_NORMAL, BATTERY_POWER_OFF, battery_critical_low_act},
81 {BATTERY_WARNING_LOW, BATTERY_REAL_POWER_OFF, battery_power_off_act},
82 {BATTERY_NORMAL, BATTERY_REAL_POWER_OFF, battery_power_off_act},
86 * TODO: remove this function
88 static void print_lowbat_state(unsigned int bat_percent)
92 for (i = 0; i < BAT_MON_SAMPLES; i++)
93 PRT_TRACE("\t%d", recent_bat_percent[i]);
97 static int battery_warning_low_act(void *data)
99 char lowbat_noti_name[NAME_MAX];
101 heynoti_get_snoti_name(_SYS_LOW_POWER, lowbat_noti_name, NAME_MAX);
102 ss_noti_send(lowbat_noti_name);
104 ss_action_entry_call_internal(PREDEF_LOWBAT, 1, WARNING_LOW_BAT_ACT);
108 static int battery_critical_low_act(void *data)
110 ss_action_entry_call_internal(PREDEF_LOWBAT, 1, CRITICAL_LOW_BAT_ACT);
114 static int battery_power_off_act(void *data)
116 ss_action_entry_call_internal(PREDEF_LOWBAT, 1, POWER_OFF_BAT_ACT);
120 static int battery_charge_act(void *data)
125 int ss_lowbat_set_charge_on(int onoff)
127 if(vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, onoff)!=0) {
128 PRT_TRACE_ERR("fail to set charge vconf value");
134 int ss_lowbat_is_charge_in_now()
137 if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_NOW, &val) < 0) {
138 PRT_TRACE_ERR("fail to read charge now from kernel");
139 ss_lowbat_set_charge_on(0);
144 ss_lowbat_set_charge_on(1);
147 ss_lowbat_set_charge_on(0);
152 static int lowbat_process(int bat_percent, void *ad)
154 int new_bat_capacity;
156 int vconf_state = -1;
160 new_bat_capacity = bat_percent;
161 if (new_bat_capacity < 0)
163 if (new_bat_capacity != cur_bat_capacity) {
164 PRT_TRACE("[BAT_MON] cur = %d new = %d", cur_bat_capacity, new_bat_capacity);
165 if (vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY, new_bat_capacity) == 0)
166 cur_bat_capacity = new_bat_capacity;
170 if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &vconf_state) < 0) {
171 PRT_TRACE_ERR("vconf_get_int() failed");
175 if (new_bat_capacity <= BATTERY_REAL_POWER_OFF) {
176 if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_NOW, &val) < 0) {
177 PRT_TRACE_ERR("fail to read charge now from kernel");
179 PRT_TRACE("charge_now status %d",val);
181 new_bat_state = BATTERY_POWER_OFF;
182 if (vconf_state != VCONFKEY_SYSMAN_BAT_POWER_OFF)
183 ret=vconf_set_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, VCONFKEY_SYSMAN_BAT_POWER_OFF);
185 new_bat_state = BATTERY_REAL_POWER_OFF;
186 if (vconf_state != VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF)
187 ret=vconf_set_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF);
189 } else if (new_bat_capacity <= BATTERY_POWER_OFF) {
190 new_bat_state = BATTERY_POWER_OFF;
191 if (vconf_state != VCONFKEY_SYSMAN_BAT_POWER_OFF)
192 ret=vconf_set_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, VCONFKEY_SYSMAN_BAT_POWER_OFF);
193 } else if (new_bat_capacity <= BATTERY_CRITICAL_LOW) {
194 new_bat_state = BATTERY_CRITICAL_LOW;
195 if (vconf_state != VCONFKEY_SYSMAN_BAT_CRITICAL_LOW)
196 ret=vconf_set_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, VCONFKEY_SYSMAN_BAT_CRITICAL_LOW);
197 } else if (new_bat_capacity <= BATTERY_WARNING_LOW) {
198 new_bat_state = BATTERY_WARNING_LOW;
199 if (vconf_state != VCONFKEY_SYSMAN_BAT_WARNING_LOW)
200 ret=vconf_set_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, VCONFKEY_SYSMAN_BAT_WARNING_LOW);
202 new_bat_state = BATTERY_NORMAL;
203 if (new_bat_capacity == BATTERY_FULL) {
204 device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_FULL, &bat_full);
206 if (vconf_state != VCONFKEY_SYSMAN_BAT_FULL)
207 ret=vconf_set_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, VCONFKEY_SYSMAN_BAT_FULL);
209 if (vconf_state != VCONFKEY_SYSMAN_BAT_NORMAL)
210 ret=vconf_set_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, VCONFKEY_SYSMAN_BAT_NORMAL);
213 if (vconf_state != VCONFKEY_SYSMAN_BAT_NORMAL)
214 ret=vconf_set_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, VCONFKEY_SYSMAN_BAT_NORMAL);
221 ss_lowbat_is_charge_in_now();
223 if (cur_bat_state == new_bat_state) {
227 if (cur_bat_state == BATTERY_UNKNOWN) {
229 i < sizeof(lpe) / sizeof(struct lowbat_process_entry);
231 if (new_bat_state == lpe[i].new_bat_state) {
233 cur_bat_state = new_bat_state;
239 i < sizeof(lpe) / sizeof(struct lowbat_process_entry);
241 if ((cur_bat_state == lpe[i].cur_bat_state)
242 && (new_bat_state == lpe[i].new_bat_state)) {
244 cur_bat_state = new_bat_state;
250 if (new_bat_capacity == cur_bat_capacity)
253 PRT_TRACE("[BATMON] Unknown battery state cur:%d new:%d",cur_bat_state,new_bat_state);
254 cur_bat_state = new_bat_state;
258 static int lowbat_read()
262 device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CAPACITY, &bat_percent);
267 static void __ss_change_lowbat_level(int bat_percent)
271 if (cur_bat_capacity == bat_percent)
274 if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_LEVEL_STATUS, &prev) < 0) {
275 PRT_TRACE_ERR("vconf_get_int() failed");
280 if (bat_percent > BATTERY_LEVEL_CHECK_FULL) {
281 now = VCONFKEY_SYSMAN_BAT_LEVEL_FULL;
282 } else if (bat_percent > BATTERY_LEVEL_CHECK_HIGH) {
283 now = VCONFKEY_SYSMAN_BAT_LEVEL_HIGH;
284 } else if (bat_percent > BATTERY_LEVEL_CHECK_LOW) {
285 now = VCONFKEY_SYSMAN_BAT_LEVEL_LOW;
286 } else if (bat_percent > BATTERY_LEVEL_CHECK_CRITICAL) {
287 now = VCONFKEY_SYSMAN_BAT_LEVEL_CRITICAL;
289 now = VCONFKEY_SYSMAN_BAT_LEVEL_EMPTY;
293 vconf_set_int(VCONFKEY_SYSMAN_BATTERY_LEVEL_STATUS, now);
296 static int __check_lowbat_percent(void)
300 bat_percent = lowbat_read();
301 if (bat_percent < 0) {
302 ecore_timer_interval_set(lowbat_timer, BAT_MON_INTERVAL_MIN);
304 if (bat_err_count > MAX_BATTERY_ERROR) {
306 ("[BATMON] Cannot read battery gage. stop read fuel gage");
311 if (bat_percent > 100)
313 __ss_change_lowbat_level(bat_percent);
317 int ss_lowbat_monitor(void *data)
320 struct ss_main_data *ad = (struct ss_main_data *)data;
322 bat_percent = __check_lowbat_percent();
323 print_lowbat_state(bat_percent);
325 if (lowbat_process(bat_percent, ad) < 0)
326 ecore_timer_interval_set(lowbat_timer, BAT_MON_INTERVAL_MIN);
328 ecore_timer_interval_set(lowbat_timer, BAT_MON_INTERVAL);
333 static int wakeup_cb(keynode_t *key_nodes, void *data)
338 vconf_keynode_get_int(key_nodes)) == VCONFKEY_PM_STATE_LCDOFF)
339 ss_lowbat_monitor(NULL);
344 /* for debugging (request by kernel) */
345 static int check_battery()
350 if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_PRESENT, &ret) < 0) {
351 PRT_TRACE_ERR("[BATMON] battery check : %d", ret);
353 PRT_TRACE("[BATMON] battery check : %d", ret);
358 int ss_lowbat_init(struct ss_main_data *ad)
362 /* need check battery */
364 ecore_timer_add(BAT_MON_INTERVAL_MIN, ss_lowbat_monitor, ad);
366 __check_lowbat_percent();
368 ss_lowbat_is_charge_in_now();
370 vconf_notify_key_changed(VCONFKEY_PM_STATE, (void *)wakeup_cb, NULL);