merge with master
[platform/core/system/system-server.git] / ss_device_change_handler.c
1 /*
2  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17
18 #include <stdlib.h>
19 #include <fcntl.h>
20 #include <dirent.h>
21 #include <errno.h>
22 #include <vconf.h>
23 #include <sysman.h>
24 #include <pmapi.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <sys/mount.h>
28 #include <syspopup_caller.h>
29 #include <aul.h>
30 #include <bundle.h>
31 #include <dirent.h>
32
33 #include "ss_queue.h"
34 #include "ss_log.h"
35 #include "ss_device_handler.h"
36 #include "device-node.h"
37 #include "ss_noti.h"
38 #include "include/ss_data.h"
39 #include "sys_device_noti/sys_device_noti.h"
40 #include "sys_pci_noti/sys_pci_noti.h"
41
42 #define BUFF_MAX                255
43 #define SYS_CLASS_INPUT         "/sys/class/input"
44 #define USBCON_EXEC_PATH        PREFIX"/bin/usb-server"
45 #define DEFAULT_USB_INFO_PATH   "/tmp/usb_default"
46 #define STORE_DEFAULT_USB_INFO  "usb-devices > "DEFAULT_USB_INFO_PATH
47 #define HDMI_NOT_SUPPORTED      (-1)
48
49 struct input_event {
50         long dummy[2];
51         unsigned short type;
52         unsigned short code;
53         int value;
54 };
55
56 enum snd_jack_types {
57         SND_JACK_HEADPHONE = 0x0001,
58         SND_JACK_MICROPHONE = 0x0002,
59         SND_JACK_HEADSET = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE,
60         SND_JACK_LINEOUT = 0x0004,
61         SND_JACK_MECHANICAL = 0x0008,   /* If detected separately */
62         SND_JACK_VIDEOOUT = 0x0010,
63         SND_JACK_AVOUT = SND_JACK_LINEOUT | SND_JACK_VIDEOOUT,
64 };
65
66
67 static int input_device_number;
68 static int check_lowbat_charge_device(int bInserted)
69 {
70         static int bChargeDeviceInserted = 0;
71         int val = -1;
72         int bat_state = -1;
73         int ret = -1;
74         if (bInserted == 1) {
75                 if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_NOW, &val) == 0) {
76                         if (val == 1)
77                                 bChargeDeviceInserted = 1;
78                         return 0;
79                 }
80         } else if (bInserted == 0) {
81                 if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_NOW, &val) == 0) {
82                         if (val == 0 && bChargeDeviceInserted == 1) {
83                                 bChargeDeviceInserted = 0;
84                                 //low bat popup during charging device removing
85                                 if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat_state) == 0) {
86                                         if (bat_state < VCONFKEY_SYSMAN_BAT_NORMAL ||
87                                             bat_state == VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF) {
88                                                 bundle *b = NULL;
89                                                 b = bundle_create();
90                                                 if(bat_state == VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF)
91                                                         bundle_add(b,"_SYSPOPUP_CONTENT_", "poweroff");
92                                                 else
93                                                         bundle_add(b, "_SYSPOPUP_CONTENT_", "warning");
94                                                 ret = syspopup_launch("lowbat-syspopup", b);
95                                                 if (ret < 0) {
96                                                         PRT_TRACE_EM("popup lauch failed\n");
97                                                 }
98                                                 bundle_free(b);
99                                         }
100                                 } else {
101                                         PRT_TRACE_ERR("failed to get vconf key");
102                                         return -1;
103                                 }
104                         }
105                         return 0;
106                 }
107         }
108         return -1;
109 }
110
111 static void usb_chgdet_cb(struct ss_main_data *ad)
112 {
113         int val = -1;
114         char params[BUFF_MAX];
115         PRT_TRACE("jack - usb changed\n");
116         pm_change_state(LCD_NORMAL);
117         /* check charging now */
118         ss_lowbat_is_charge_in_now();
119         /* check current battery level */
120         ss_lowbat_monitor(NULL);
121         ss_action_entry_call_internal(PREDEF_USBCON, 0);
122
123         if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_USB_ONLINE, &val) == 0) {
124                 PRT_TRACE("jack - usb changed %d",val);
125                 check_lowbat_charge_device(val);
126                 if (val==1) {
127                         snprintf(params, sizeof(params), "%d", CB_NOTI_BATT_CHARGE);
128                         ss_launch_if_noexist("/usr/bin/sys_device_noti", params);
129                         PRT_TRACE("usb device notification");
130                 }
131         }
132 }
133
134 static void ta_chgdet_cb(struct ss_main_data *ad)
135 {
136         PRT_TRACE("jack - ta changed\n");
137         pm_change_state(LCD_NORMAL);
138         /* check charging now */
139         ss_lowbat_is_charge_in_now();
140         /* check current battery level */
141         ss_lowbat_monitor(NULL);
142
143         int val = -1;
144         int ret = -1;
145         int bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
146         char params[BUFF_MAX];
147
148         if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_TA_ONLINE, &val) == 0) {
149                 PRT_TRACE("jack - ta changed %d",val);
150                 check_lowbat_charge_device(val);
151                 vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, val);
152                 if (val == 0) {
153                         pm_unlock_state(LCD_OFF, STAY_CUR_STATE);
154                 } else {
155                         pm_lock_state(LCD_OFF, STAY_CUR_STATE, 0);
156                         snprintf(params, sizeof(params), "%d", CB_NOTI_BATT_CHARGE);
157                         ss_launch_if_noexist("/usr/bin/sys_device_noti", params);
158                         PRT_TRACE("ta device notification");
159                 }
160         }
161         else
162                 PRT_TRACE_ERR("failed to get ta status\n");
163 }
164
165 static void earjack_chgdet_cb(struct ss_main_data *ad)
166 {
167         PRT_TRACE("jack - earjack changed\n");
168         ss_action_entry_call_internal(PREDEF_EARJACKCON, 0);
169 }
170
171 static void earkey_chgdet_cb(struct ss_main_data *ad)
172 {
173         int val;
174         PRT_TRACE("jack - earkey changed\n");
175         if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_EARKEY_ONLINE, &val) == 0)
176                 vconf_set_int(VCONFKEY_SYSMAN_EARJACKKEY, val);
177 }
178
179 static void tvout_chgdet_cb(struct ss_main_data *ad)
180 {
181         PRT_TRACE("jack - tvout changed\n");
182         pm_change_state(LCD_NORMAL);
183 }
184
185 static void hdmi_chgdet_cb(struct ss_main_data *ad)
186 {
187         PRT_TRACE("jack - hdmi changed\n");
188         int val;
189         pm_change_state(LCD_NORMAL);
190         if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_HDMI_SUPPORT, &val) == 0) {
191                 if (val!=1) {
192                         PRT_TRACE_ERR("target is not support HDMI");
193                         vconf_set_int(VCONFKEY_SYSMAN_HDMI, HDMI_NOT_SUPPORTED);
194                         return;
195                 }
196         }
197         if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_HDMI_ONLINE, &val) == 0) {
198                 PRT_TRACE("jack - hdmi changed %d",val);
199                 vconf_set_int(VCONFKEY_SYSMAN_HDMI,val);
200                 if(val == 1)
201                         pm_lock_state(LCD_NORMAL, GOTO_STATE_NOW, 0);
202                 else
203                         pm_unlock_state(LCD_NORMAL, PM_SLEEP_MARGIN);
204         }
205 }
206
207 static void keyboard_chgdet_cb(struct ss_main_data *ad)
208 {
209         int val = -1;
210         int ret = -1;
211         PRT_TRACE("jack - keyboard changed\n");
212
213         if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_KEYBOARD_ONLINE, &val) == 0) {
214                 PRT_TRACE("jack - keyboard changed %d",val);
215                 if(val != 1)
216                         val = 0;
217                 vconf_set_int(VCONFKEY_SYSMAN_SLIDING_KEYBOARD, val);
218         } else {
219                 vconf_set_int(VCONFKEY_SYSMAN_SLIDING_KEYBOARD, VCONFKEY_SYSMAN_SLIDING_KEYBOARD_NOT_SUPPORTED);
220         }
221 }
222
223 static void mmc_chgdet_cb(void *data)
224 {
225         int ret = -1;
226         int val = -1;
227         if (data == NULL) {
228                 PRT_TRACE("mmc removed");
229                 ss_mmc_removed();
230         } else {
231                 PRT_TRACE("mmc added");
232                 ret = ss_mmc_inserted();
233                 if (ret == -1) {
234                         vconf_get_int(VCONFKEY_SYSMAN_MMC_MOUNT,&val);
235                         if (val == VCONFKEY_SYSMAN_MMC_MOUNT_FAILED) {
236                                 bundle *b = NULL;
237                                 b = bundle_create();
238                                 bundle_add(b, "_SYSPOPUP_CONTENT_", "mounterr");
239                                 ret = syspopup_launch("mmc-syspopup", b);
240                                 if (ret < 0) {
241                                         PRT_TRACE_ERR("popup launch failed");
242                                 }
243                                 bundle_free(b);
244                         }
245                 }
246         }
247 }
248
249 static void ums_unmount_cb(void *data)
250 {
251         umount(MOVINAND_MOUNT_POINT);
252 }
253
254 static void charge_cb(struct ss_main_data *ad)
255 {
256         int val = -1;
257         char params[BUFF_MAX];
258         static int bat_full_noti = 0;
259         ss_lowbat_monitor(NULL);
260
261         if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_HEALTH, &val) == 0) {
262                 if (val==BATTERY_OVERHEAT || val==BATTERY_COLD) {
263                         PRT_TRACE_ERR("Battery health status is not good (%d)", val);
264                         ss_action_entry_call_internal(PREDEF_LOWBAT, 1, CHARGE_ERROR_ACT);
265
266                         return;
267                 }
268         } else {
269                 PRT_TRACE_ERR("failed to get battery health status");
270         }
271         device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_FULL, &val);
272         if (val==0) {
273                 if (bat_full_noti==1) {
274                         snprintf(params, sizeof(params), "%d %d", CB_NOTI_BATT_FULL, CB_NOTI_OFF);
275                         ss_launch_if_noexist("/usr/bin/sys_device_noti", params);
276                 }
277                 bat_full_noti = 0;
278         } else {
279                 if (val==1 && bat_full_noti==0) {
280                         bat_full_noti = 1;
281                         PRT_TRACE("battery full noti");
282                         snprintf(params, sizeof(params), "%d %d", CB_NOTI_BATT_FULL, CB_NOTI_ON);
283                         ss_launch_if_noexist("/usr/bin/sys_device_noti", params);
284                 }
285         }
286 }
287
288 static void usb_host_chgdet_cb(keynode_t *in_key, struct ss_main_data *ad)
289 {
290         PRT_TRACE("ENTER: usb_host_chgdet_cb()");
291         int status;
292         int ret = vconf_get_int(VCONFKEY_SYSMAN_USB_HOST_STATUS, &status);
293         if (ret != 0) {
294                 PRT_TRACE_ERR("vconf get failed(VCONFKEY_SYSMAN_USB_HOST_STATUS)\n");
295                 return ;
296         }
297
298         if(VCONFKEY_SYSMAN_USB_HOST_CONNECTED == status) {
299                 int pid = ss_launch_if_noexist(USBCON_EXEC_PATH, NULL);
300                 if (pid < 0) {
301                         PRT_TRACE("usb-server launching failed\n");
302                         return;
303                 }
304         }
305         PRT_TRACE("EXIT: usb_host_chgdet_cb()");
306 }
307
308 static void usb_host_add_cb()
309 {
310         PRT_TRACE("ENTER: usb_host_add_cb()\n");
311         int status;
312         int ret = vconf_get_int(VCONFKEY_SYSMAN_USB_HOST_STATUS, &status);
313         if (ret != 0) {
314                 PRT_TRACE("vconf get failed ()\n");
315                 return;
316         }
317
318         if (-1 == status) { /* '-1' means that USB host mode is not loaded yet */
319                 PRT_TRACE("This usb device is connected defaultly\n");
320
321                 ret = system(STORE_DEFAULT_USB_INFO);
322                 PRT_TRACE("Return value of usb-devices: %d\n", ret);
323                 if (0 != access(DEFAULT_USB_INFO_PATH, F_OK)) {
324                         ret = system(STORE_DEFAULT_USB_INFO);
325                         PRT_TRACE("Return value of usb-devices: %d\n", ret);
326                 }
327         }
328         PRT_TRACE("EXIT: usb_host_add_cb()\n");
329 }
330
331 static void pci_keyboard_add_cb(struct ss_main_data *ad)
332 {
333         char params[BUFF_MAX];
334         PRT_TRACE("pci- keyboard inserted\n");
335         pm_change_state(LCD_NORMAL);
336
337         snprintf(params, sizeof(params), "%d", CB_NOTI_PCI_INSERTED);
338         ss_launch_if_noexist("/usr/bin/sys_pci_noti", params);
339
340 }
341 static void pci_keyboard_remove_cb(struct ss_main_data *ad)
342 {
343         char params[BUFF_MAX];
344         PRT_TRACE("pci- keyboard removed\n");
345         pm_change_state(LCD_NORMAL);
346
347         snprintf(params, sizeof(params), "%d", CB_NOTI_PCI_REMOVED);
348         ss_launch_if_noexist("/usr/bin/sys_pci_noti", params);
349 }
350 int ss_device_change_init(struct ss_main_data *ad)
351 {
352         /* for simple noti change cb */
353         ss_noti_add("device_usb_chgdet", (void *)usb_chgdet_cb, (void *)ad);
354         ss_noti_add("device_ta_chgdet", (void *)ta_chgdet_cb, (void *)ad);
355         ss_noti_add("device_earjack_chgdet", (void *)earjack_chgdet_cb, (void *)ad);
356         ss_noti_add("device_earkey_chgdet", (void *)earkey_chgdet_cb, (void *)ad);
357         ss_noti_add("device_tvout_chgdet", (void *)tvout_chgdet_cb, (void *)ad);
358         ss_noti_add("device_hdmi_chgdet", (void *)hdmi_chgdet_cb, (void *)ad);
359         ss_noti_add("device_keyboard_chgdet", (void *)keyboard_chgdet_cb, (void *)ad);
360
361         ss_noti_add("device_usb_host_add", (void *)usb_host_add_cb, (void *)ad);
362         ss_noti_add("mmcblk_add", (void *)mmc_chgdet_cb, (void *)1);
363         ss_noti_add("mmcblk_remove", (void *)mmc_chgdet_cb, NULL);
364
365         ss_noti_add("unmount_ums", (void *)ums_unmount_cb, NULL);
366         ss_noti_add("device_charge_chgdet", (void *)charge_cb, (void *)ad);
367
368         ss_noti_add("device_pci_keyboard_add", (void *)pci_keyboard_add_cb, (void *)ad);
369         ss_noti_add("device_pci_keyboard_remove", (void *)pci_keyboard_remove_cb, (void *)ad);
370
371         if (vconf_notify_key_changed(VCONFKEY_SYSMAN_USB_HOST_STATUS, usb_host_chgdet_cb, NULL) < 0) {
372                 PRT_TRACE_ERR("vconf key notify failed(VCONFKEY_SYSMAN_USB_HOST_STATUS)");
373         }
374
375         /* set initial state for devices */
376         input_device_number = 0;
377         keyboard_chgdet_cb(NULL);
378         hdmi_chgdet_cb(NULL);
379         system(STORE_DEFAULT_USB_INFO);
380
381         return 0;
382 }