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.
25 #include <sys/types.h>
27 #include <sys/mount.h>
28 #include <syspopup_caller.h>
35 #include "ss_device_handler.h"
36 #include "device-node.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 #include "ss_predefine.h"
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 #ifdef ENABLE_EDBUS_USE
50 static E_DBus_Connection *conn;
51 #endif /* ENABLE_EDBUS_USE */
61 SND_JACK_HEADPHONE = 0x0001,
62 SND_JACK_MICROPHONE = 0x0002,
63 SND_JACK_HEADSET = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE,
64 SND_JACK_LINEOUT = 0x0004,
65 SND_JACK_MECHANICAL = 0x0008, /* If detected separately */
66 SND_JACK_VIDEOOUT = 0x0010,
67 SND_JACK_AVOUT = SND_JACK_LINEOUT | SND_JACK_VIDEOOUT,
70 #define CHANGE_ACTION "change"
71 #define ENV_FILTER "CHGDET"
72 #define ENV_VALUE_USB "usb"
73 #define ENV_VALUE_CHARGER "charger"
74 #define ENV_VALUE_EARJACK "earjack"
75 #define ENV_VALUE_EARKEY "earkey"
76 #define ENV_VALUE_TVOUT "tvout"
77 #define ENV_VALUE_HDMI "hdmi"
78 #define ENV_VALUE_KEYBOARD "keyboard"
81 #define ABNORMAL_POPUP_COUNTER 5
83 static int input_device_number;
85 static struct udev_monitor *mon = NULL;
86 static struct udev *udev = NULL;
87 static Ecore_Fd_Handler *ufdh = NULL;
89 static int uevent_control_cb(void *data, Ecore_Fd_Handler *fd_handler);
91 static int check_lowbat_charge_device(int bInserted)
93 static int bChargeDeviceInserted = 0;
98 if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_NOW, &val) == 0) {
100 bChargeDeviceInserted = 1;
103 } else if (bInserted == 0) {
104 if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_NOW, &val) == 0) {
105 if (val == 0 && bChargeDeviceInserted == 1) {
106 bChargeDeviceInserted = 0;
107 //low bat popup during charging device removing
108 if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat_state) == 0) {
109 if(bat_state < VCONFKEY_SYSMAN_BAT_NORMAL
110 || bat_state == VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF) {
113 if(bat_state == VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF)
114 bundle_add(b,"_SYSPOPUP_CONTENT_", "poweroff");
116 bundle_add(b, "_SYSPOPUP_CONTENT_", "warning");
117 ret = syspopup_launch("lowbat-syspopup", b);
119 PRT_TRACE_EM("popup lauch failed\n");
124 PRT_TRACE_ERR("failed to get vconf key");
134 static void usb_chgdet_cb(struct ss_main_data *ad)
137 char params[BUFF_MAX];
139 predefine_pm_change_state(LCD_NORMAL);
141 /* check charging now */
142 ss_lowbat_is_charge_in_now();
143 /* check current battery level */
144 ss_lowbat_monitor(NULL);
145 ss_action_entry_call_internal(PREDEF_USBCON, 0);
146 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_USB_ONLINE, &val) == 0) {
147 PRT_TRACE("jack - usb changed %d",val);
148 check_lowbat_charge_device(val);
150 snprintf(params, sizeof(params), "%d", CB_NOTI_BATT_CHARGE);
151 ss_launch_if_noexist("/usr/bin/sys_device_noti", params);
152 PRT_TRACE("usb device notification");
155 PRT_TRACE_ERR("fail to get usb_online status");
159 static void __sync_usb_status(void)
163 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_USB_ONLINE, &val) != 0 ||
164 vconf_get_int(VCONFKEY_SYSMAN_USB_STATUS,&status) != 0)
166 if ((val == 1 && status == VCONFKEY_SYSMAN_USB_DISCONNECTED) ||
167 (val == 0 && status == VCONFKEY_SYSMAN_USB_AVAILABLE))
168 ss_action_entry_call_internal(PREDEF_USBCON, 0);
171 static void ta_chgdet_cb(struct ss_main_data *ad)
175 int bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
176 char params[BUFF_MAX];
178 predefine_pm_change_state(LCD_NORMAL);
180 /* check charging now */
181 ss_lowbat_is_charge_in_now();
182 /* check current battery level */
183 ss_lowbat_monitor(NULL);
185 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_TA_ONLINE, &val) == 0) {
186 PRT_TRACE("jack - ta changed %d",val);
187 check_lowbat_charge_device(val);
188 vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, val);
190 pm_unlock_state(LCD_OFF, STAY_CUR_STATE);
192 pm_lock_state(LCD_OFF, STAY_CUR_STATE, 0);
193 snprintf(params, sizeof(params), "%d", CB_NOTI_BATT_CHARGE);
194 ss_launch_if_noexist("/usr/bin/sys_device_noti", params);
195 PRT_TRACE("ta device notification");
200 PRT_TRACE_ERR("failed to get ta status\n");
203 static void earjack_chgdet_cb(struct ss_main_data *ad)
205 PRT_TRACE("jack - earjack changed\n");
206 ss_action_entry_call_internal(PREDEF_EARJACKCON, 0);
209 static void earkey_chgdet_cb(struct ss_main_data *ad)
212 PRT_TRACE("jack - earkey changed\n");
214 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_EARKEY_ONLINE, &val) == 0)
215 vconf_set_int(VCONFKEY_SYSMAN_EARJACKKEY, val);
218 static void tvout_chgdet_cb(struct ss_main_data *ad)
220 PRT_TRACE("jack - tvout changed\n");
221 pm_change_state(LCD_NORMAL);
224 static void hdmi_chgdet_cb(struct ss_main_data *ad)
229 pm_change_state(LCD_NORMAL);
230 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_HDMI_SUPPORT, &val) == 0) {
232 PRT_TRACE_ERR("target is not support HDMI");
233 vconf_set_int(VCONFKEY_SYSMAN_HDMI, HDMI_NOT_SUPPORTED);
237 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_HDMI_ONLINE, &val) == 0) {
238 PRT_TRACE("jack - hdmi changed %d",val);
239 vconf_set_int(VCONFKEY_SYSMAN_HDMI,val);
241 pm_lock_state(LCD_NORMAL, GOTO_STATE_NOW, 0);
243 pm_unlock_state(LCD_NORMAL, PM_SLEEP_MARGIN);
245 PRT_TRACE_ERR("failed to get hdmi_online status");
249 static void keyboard_chgdet_cb(struct ss_main_data *ad)
253 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_KEYBOARD_ONLINE, &val) == 0) {
254 PRT_TRACE("jack - keyboard changed %d",val);
257 vconf_set_int(VCONFKEY_SYSMAN_SLIDING_KEYBOARD, val);
259 vconf_set_int(VCONFKEY_SYSMAN_SLIDING_KEYBOARD, VCONFKEY_SYSMAN_SLIDING_KEYBOARD_NOT_SUPPORTED);
263 static void mmc_chgdet_cb(void *data)
270 PRT_TRACE("mmc removed");
274 PRT_TRACE("mmc added");
278 ret = ss_mmc_inserted();
280 vconf_get_int(VCONFKEY_SYSMAN_MMC_MOUNT,&val);
281 if (val == VCONFKEY_SYSMAN_MMC_MOUNT_FAILED) {
285 PRT_TRACE_ERR("error bundle_create()");
288 bundle_add(b, "_SYSPOPUP_CONTENT_", "mounterr");
289 ret = syspopup_launch("mmc-syspopup", b);
291 PRT_TRACE_ERR("popup launch failed");
294 } else if (val == VCONFKEY_SYSMAN_MMC_MOUNT_COMPLETED) {
298 PRT_TRACE_ERR("error bundle_create()");
301 bundle_add(b, "_SYSPOPUP_CONTENT_", "mountrdonly");
302 ret = syspopup_launch("mmc-syspopup", b);
304 PRT_TRACE_ERR("popup launch failed");
312 static void ums_unmount_cb(void *data)
314 umount(MOVINAND_MOUNT_POINT);
317 static int __check_abnormal_popup_launch(void)
319 static int noti_count = 0;
320 if (noti_count >= ABNORMAL_POPUP_COUNTER) {
329 static void charge_cb(struct ss_main_data *ad)
334 char params[BUFF_MAX];
335 static int bat_full_noti = 0;
337 ss_lowbat_monitor(NULL);
339 if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_NOW, &charge_now) != 0 ||
340 device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CAPACITY, &capacity) != 0)
341 PRT_TRACE_ERR("fail to get battery node value");
342 if (charge_now == 0 && capacity == 0) {
343 PRT_TRACE_ERR("target will be shut down");
344 ss_action_entry_call_internal(PREDEF_LOWBAT, 1, POWER_OFF_BAT_ACT);
348 if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_HEALTH, &val) == 0) {
349 if (val==BATTERY_OVERHEAT || val==BATTERY_COLD) {
350 PRT_TRACE_ERR("Battery health status is not good (%d)", val);
352 if (__check_abnormal_popup_launch() != 0)
355 if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CAPACITY, &val) == 0 && val <= 0)
356 ss_action_entry_call_internal(PREDEF_LOWBAT, 1, POWER_OFF_BAT_ACT);
358 ss_action_entry_call_internal(PREDEF_LOWBAT, 1, CHARGE_ERROR_ACT);
362 PRT_TRACE_ERR("failed to get battery health status");
364 device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_FULL, &val);
366 if (bat_full_noti==1) {
367 snprintf(params, sizeof(params), "%d %d", CB_NOTI_BATT_FULL, CB_NOTI_OFF);
368 ss_launch_if_noexist("/usr/bin/sys_device_noti", params);
372 if (val==1 && bat_full_noti==0) {
374 PRT_TRACE("battery full noti");
375 snprintf(params, sizeof(params), "%d %d", CB_NOTI_BATT_FULL, CB_NOTI_ON);
376 ss_launch_if_noexist("/usr/bin/sys_device_noti", params);
381 #ifdef ENABLE_EDBUS_USE
382 static void cb_xxxxx_signaled(void *data, DBusMessage * msg)
386 struct ss_main_data *ad;
390 dbus_error_init(&err);
391 if (dbus_message_get_args
392 (msg, &err, DBUS_TYPE_STRING, &args, DBUS_TYPE_INVALID)) {
393 if (!strcmp(args, "action")) ; /* action */
398 #endif /* ENABLE_EDBUS_USE */
400 static void usb_host_chgdet_cb(keynode_t *in_key, struct ss_main_data *ad)
402 PRT_TRACE("ENTER: usb_host_chgdet_cb()");
404 int ret = vconf_get_int(VCONFKEY_SYSMAN_USB_HOST_STATUS, &status);
406 PRT_TRACE_ERR("vconf get failed(VCONFKEY_SYSMAN_USB_HOST_STATUS)\n");
410 if(VCONFKEY_SYSMAN_USB_HOST_CONNECTED == status) {
411 int pid = ss_launch_if_noexist(USBCON_EXEC_PATH, NULL);
413 PRT_TRACE("usb-server launching failed\n");
417 PRT_TRACE("EXIT: usb_host_chgdet_cb()");
420 static void usb_host_add_cb()
422 PRT_TRACE("ENTER: usb_host_add_cb()\n");
424 int ret = vconf_get_int(VCONFKEY_SYSMAN_USB_HOST_STATUS, &status);
426 PRT_TRACE("vconf get failed ()\n");
430 if (-1 == status) { /* '-1' means that USB host mode is not loaded yet */
431 PRT_TRACE("This usb device is connected defaultly\n");
433 ret = system(STORE_DEFAULT_USB_INFO);
434 PRT_TRACE("Return value of usb-devices: %d\n", ret);
435 if (0 != access(DEFAULT_USB_INFO_PATH, F_OK)) {
436 ret = system(STORE_DEFAULT_USB_INFO);
437 PRT_TRACE("Return value of usb-devices: %d\n", ret);
440 PRT_TRACE("EXIT: usb_host_add_cb()\n");
443 static int uevent_control_stop(int ufd)
446 ecore_main_fd_handler_del(ufdh);
454 udev_monitor_unref(mon);
464 static int uevent_control_start(void)
470 PRT_TRACE_ERR("error create udev");
474 mon = udev_monitor_new_from_netlink(udev, "kernel");
476 PRT_TRACE_ERR("error udev_monitor create");
477 uevent_control_stop(-1);
481 udev_monitor_set_receive_buffer_size(mon, 1024);
482 if (udev_monitor_filter_add_match_subsystem_devtype(mon, "platform", NULL) < 0) {
483 PRT_TRACE_ERR("error apply subsystem filter");
484 uevent_control_stop(-1);
488 ufd = udev_monitor_get_fd(mon);
490 PRT_TRACE_ERR("error udev_monitor_get_fd");
491 uevent_control_stop(ufd);
495 ufdh = ecore_main_fd_handler_add(ufd, ECORE_FD_READ, uevent_control_cb, NULL, NULL, NULL);
497 PRT_TRACE_ERR("error ecore_main_fd_handler_add");
498 uevent_control_stop(ufd);
502 if (udev_monitor_enable_receiving(mon) < 0) {
503 PRT_TRACE_ERR("error unable to subscribe to udev events");
504 uevent_control_stop(ufd);
511 static int uevent_control_cb(void *data, Ecore_Fd_Handler *fd_handler)
513 struct udev_device *dev = NULL;
514 struct udev_list_entry *list_entry = NULL;
515 char *env_name = NULL;
516 char *env_value = NULL;
520 if (!ecore_main_fd_handler_active_get(fd_handler,ECORE_FD_READ))
522 if ((ufd = ecore_main_fd_handler_fd_get(fd_handler)) == -1)
524 if ((dev = udev_monitor_receive_device(mon)) == NULL)
527 udev_list_entry_foreach(list_entry,udev_device_get_properties_list_entry(dev)) {
528 env_name = udev_list_entry_get_name(list_entry);
529 if (strncmp(env_name, ENV_FILTER, strlen(ENV_FILTER)) == 0) {
530 env_value = udev_list_entry_get_value(list_entry);
537 udev_device_unref(dev);
541 PRT_TRACE("UEVENT DETECTED (%s)",env_value);
542 ss_action_entry_call_internal(PREDEF_DEVICE_CHANGED,1,env_value);
544 udev_device_unref(dev);
545 uevent_control_stop(ufd);
546 uevent_control_start();
551 int changed_device_def_predefine_action(int argc, char **argv)
553 if (argc != 1 || argv[0] == NULL) {
554 PRT_TRACE_ERR("param is failed");
558 if (strncmp(argv[0], ENV_VALUE_USB, strlen(ENV_VALUE_USB)) == 0)
560 if (strncmp(argv[0], ENV_VALUE_CHARGER, strlen(ENV_VALUE_CHARGER)) == 0)
562 if (strncmp(argv[0], ENV_VALUE_EARJACK, strlen(ENV_VALUE_EARJACK)) == 0)
563 earjack_chgdet_cb(NULL);
564 if (strncmp(argv[0], ENV_VALUE_EARKEY, strlen(ENV_VALUE_EARKEY)) == 0)
565 earkey_chgdet_cb(NULL);
566 if (strncmp(argv[0], ENV_VALUE_TVOUT, strlen(ENV_VALUE_TVOUT)) == 0)
567 tvout_chgdet_cb(NULL);
568 if (strncmp(argv[0], ENV_VALUE_HDMI, strlen(ENV_VALUE_HDMI)) == 0)
569 hdmi_chgdet_cb(NULL);
570 if (strncmp(argv[0], ENV_VALUE_KEYBOARD, strlen(ENV_VALUE_KEYBOARD)) == 0)
571 keyboard_chgdet_cb(NULL);
576 static void pci_keyboard_add_cb(struct ss_main_data *ad)
578 char params[BUFF_MAX];
579 PRT_TRACE("pci- keyboard inserted\n");
580 pm_change_state(LCD_NORMAL);
582 snprintf(params, sizeof(params), "%d", CB_NOTI_PCI_INSERTED);
583 ss_launch_if_noexist("/usr/bin/sys_pci_noti", params);
586 static void pci_keyboard_remove_cb(struct ss_main_data *ad)
588 char params[BUFF_MAX];
589 PRT_TRACE("pci- keyboard removed\n");
590 pm_change_state(LCD_NORMAL);
592 snprintf(params, sizeof(params), "%d", CB_NOTI_PCI_REMOVED);
593 ss_launch_if_noexist("/usr/bin/sys_pci_noti", params);
595 int ss_device_change_init(struct ss_main_data *ad)
597 ss_action_entry_add_internal(PREDEF_DEVICE_CHANGED, changed_device_def_predefine_action, NULL, NULL);
599 if (uevent_control_start() == -1) {
600 PRT_TRACE_ERR("fail uevent control init");
603 /* for simple noti change cb */
604 ss_noti_add("device_usb_chgdet", (void *)usb_chgdet_cb, (void *)ad);
605 ss_noti_add("device_ta_chgdet", (void *)ta_chgdet_cb, (void *)ad);
606 ss_noti_add("device_earjack_chgdet", (void *)earjack_chgdet_cb, (void *)ad);
607 ss_noti_add("device_earkey_chgdet", (void *)earkey_chgdet_cb, (void *)ad);
608 ss_noti_add("device_tvout_chgdet", (void *)tvout_chgdet_cb, (void *)ad);
609 ss_noti_add("device_hdmi_chgdet", (void *)hdmi_chgdet_cb, (void *)ad);
610 ss_noti_add("device_keyboard_chgdet", (void *)keyboard_chgdet_cb, (void *)ad);
612 ss_noti_add("device_usb_host_add", (void *)usb_host_add_cb, (void *)ad);
613 ss_noti_add("mmcblk_add", (void *)mmc_chgdet_cb, (void *)1);
614 ss_noti_add("mmcblk_remove", (void *)mmc_chgdet_cb, NULL);
616 ss_noti_add("unmount_ums", (void *)ums_unmount_cb, NULL);
617 ss_noti_add("device_charge_chgdet", (void *)charge_cb, (void *)ad);
619 ss_noti_add("device_pci_keyboard_add", (void *)pci_keyboard_add_cb, (void *)ad);
620 ss_noti_add("device_pci_keyboard_remove", (void *)pci_keyboard_remove_cb, (void *)ad);
622 if (vconf_notify_key_changed(VCONFKEY_SYSMAN_USB_HOST_STATUS, usb_host_chgdet_cb, NULL) < 0) {
623 PRT_TRACE_ERR("vconf key notify failed(VCONFKEY_SYSMAN_USB_HOST_STATUS)");
625 /* dbus noti change cb */
626 #ifdef ENABLE_EDBUS_USE
628 conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
630 PRT_TRACE_ERR("check system dbus running!\n");
632 e_dbus_signal_handler_add(conn, NULL, "/system/uevent/xxxxx",
633 "system.uevent.xxxxx",
634 "Change", cb_xxxxx_signaled, ad);
635 #endif /* ENABLE_EDBUS_USE */
637 /* set initial state for devices */
638 input_device_number = 0;
639 keyboard_chgdet_cb(NULL);
640 hdmi_chgdet_cb(NULL);
641 system(STORE_DEFAULT_USB_INFO);