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.
24 #include <sys/types.h>
26 #include <sys/mount.h>
27 #include <syspopup_caller.h>
32 #include <device-node.h>
35 #include "device-handler.h"
38 #include "sys_pci_noti/sys_pci_noti.h"
39 #include "predefine.h"
40 #include "display/poll.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 */
73 SND_JACK_HEADPHONE = 0x0001,
74 SND_JACK_MICROPHONE = 0x0002,
75 SND_JACK_HEADSET = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE,
76 SND_JACK_LINEOUT = 0x0004,
77 SND_JACK_MECHANICAL = 0x0008, /* If detected separately */
78 SND_JACK_VIDEOOUT = 0x0010,
79 SND_JACK_AVOUT = SND_JACK_LINEOUT | SND_JACK_VIDEOOUT,
82 #define CHANGE_ACTION "change"
83 #define ENV_FILTER "CHGDET"
84 #define ENV_VALUE_USB "usb"
85 #define ENV_VALUE_CHARGER "charger"
86 #define ENV_VALUE_EARJACK "earjack"
87 #define ENV_VALUE_EARKEY "earkey"
88 #define ENV_VALUE_TVOUT "tvout"
89 #define ENV_VALUE_HDMI "hdmi"
90 #define ENV_VALUE_KEYBOARD "keyboard"
93 #define ABNORMAL_POPUP_COUNTER 5
95 static int input_device_number;
97 static struct udev_monitor *mon = NULL;
98 static struct udev *udev = NULL;
99 static Ecore_Fd_Handler *ufdh = NULL;
101 static int uevent_control_cb(void *data, Ecore_Fd_Handler *fd_handler);
103 static int check_lowbat_charge_device(int bInserted)
105 static int bChargeDeviceInserted = 0;
109 if (bInserted == 1) {
110 if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_NOW, &val) == 0) {
112 bChargeDeviceInserted = 1;
115 } else if (bInserted == 0) {
116 if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_NOW, &val) == 0) {
117 if (val == 0 && bChargeDeviceInserted == 1) {
118 bChargeDeviceInserted = 0;
119 //low bat popup during charging device removing
120 if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat_state) == 0) {
121 if(bat_state < VCONFKEY_SYSMAN_BAT_NORMAL
122 || bat_state == VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF) {
125 if(bat_state == VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF)
126 bundle_add(b,"_SYSPOPUP_CONTENT_", "poweroff");
128 bundle_add(b, "_SYSPOPUP_CONTENT_", "warning");
129 ret = syspopup_launch("lowbat-syspopup", b);
131 _I("popup lauch failed\n");
136 _E("failed to get vconf key");
146 static void usb_chgdet_cb(struct ss_main_data *ad)
149 char params[BUFF_MAX];
151 predefine_pm_change_state(LCD_NORMAL);
153 /* check charging now */
154 ss_lowbat_is_charge_in_now();
155 /* check current battery level */
156 ss_lowbat_monitor(NULL);
157 ss_action_entry_call_internal(PREDEF_USBCON, 0);
158 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_USB_ONLINE, &val) == 0) {
159 _D("jack - usb changed %d",val);
160 check_lowbat_charge_device(val);
162 snprintf(params, sizeof(params), "%d", CB_NOTI_BATT_CHARGE);
163 ss_launch_if_noexist("/usr/bin/sys_device_noti", params);
164 _D("usb device notification");
167 _E("fail to get usb_online status");
171 static void __sync_usb_status(void)
175 if ((device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_USB_ONLINE, &val) != 0) ||
176 vconf_get_int(VCONFKEY_SYSMAN_USB_STATUS,&status) != 0)
178 if ((val == 1 && status == VCONFKEY_SYSMAN_USB_DISCONNECTED) ||
179 (val == 0 && status == VCONFKEY_SYSMAN_USB_AVAILABLE))
180 ss_action_entry_call_internal(PREDEF_USBCON, 0);
183 static void ta_chgdet_cb(struct ss_main_data *ad)
187 int bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
188 char params[BUFF_MAX];
190 predefine_pm_change_state(LCD_NORMAL);
192 /* check charging now */
193 ss_lowbat_is_charge_in_now();
194 /* check current battery level */
195 ss_lowbat_monitor(NULL);
197 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_TA_ONLINE, &val) == 0) {
198 _D("jack - ta changed %d",val);
199 check_lowbat_charge_device(val);
200 vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, val);
202 pm_unlock_internal(getpid(), LCD_OFF, STAY_CUR_STATE);
204 pm_lock_internal(getpid(), LCD_OFF, STAY_CUR_STATE, 0);
205 snprintf(params, sizeof(params), "%d", CB_NOTI_BATT_CHARGE);
206 ss_launch_if_noexist("/usr/bin/sys_device_noti", params);
207 _D("ta device notification");
212 _E("failed to get ta status\n");
215 static void earjack_chgdet_cb(struct ss_main_data *ad)
217 _D("jack - earjack changed\n");
218 ss_action_entry_call_internal(PREDEF_EARJACKCON, 0);
221 static void earkey_chgdet_cb(struct ss_main_data *ad)
224 _D("jack - earkey changed\n");
225 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_EARKEY_ONLINE, &val) == 0)
226 vconf_set_int(VCONFKEY_SYSMAN_EARJACKKEY, val);
229 static void tvout_chgdet_cb(struct ss_main_data *ad)
231 _D("jack - tvout changed\n");
232 pm_change_internal(getpid(), LCD_NORMAL);
235 static void hdmi_chgdet_cb(struct ss_main_data *ad)
240 pm_change_internal(getpid(), LCD_NORMAL);
241 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_HDMI_SUPPORT, &val) == 0) {
243 _E("target is not support HDMI");
244 vconf_set_int(VCONFKEY_SYSMAN_HDMI, HDMI_NOT_SUPPORTED);
248 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_HDMI_ONLINE, &val) == 0) {
249 _D("jack - hdmi changed %d",val);
250 vconf_set_int(VCONFKEY_SYSMAN_HDMI,val);
252 pm_lock_internal(getpid(), LCD_NORMAL, GOTO_STATE_NOW, 0);
254 pm_unlock_internal(getpid(), LCD_NORMAL, PM_SLEEP_MARGIN);
256 _E("failed to get hdmi_online status");
260 static void keyboard_chgdet_cb(struct ss_main_data *ad)
264 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_KEYBOARD_ONLINE, &val) == 0) {
265 _D("jack - keyboard changed %d",val);
268 vconf_set_int(VCONFKEY_SYSMAN_SLIDING_KEYBOARD, val);
270 vconf_set_int(VCONFKEY_SYSMAN_SLIDING_KEYBOARD, VCONFKEY_SYSMAN_SLIDING_KEYBOARD_NOT_SUPPORTED);
274 static void mmc_chgdet_cb(void *data)
276 static bool first, inserted;
281 /* at first time, this part will be judge mmc is already inserted or not. */
283 vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &mmc_status);
284 if (mmc_status == VCONFKEY_SYSMAN_MMC_MOUNTED)
290 /* when removed mmc, emul kernel notify twice
291 * So this code ignores second event */
298 /* when inserted mmc, emul kernel notify twice(insert, changed)
299 * So this code ignores second event */
304 ret = ss_mmc_inserted();
306 vconf_get_int(VCONFKEY_SYSMAN_MMC_MOUNT,&val);
307 if (val == VCONFKEY_SYSMAN_MMC_MOUNT_FAILED) {
311 _E("error bundle_create()");
314 bundle_add(b, "_SYSPOPUP_CONTENT_", "mounterr");
315 ret = syspopup_launch("mmc-syspopup", b);
317 _E("popup launch failed");
320 } else if (val == VCONFKEY_SYSMAN_MMC_MOUNT_COMPLETED) {
324 _E("error bundle_create()");
327 bundle_add(b, "_SYSPOPUP_CONTENT_", "mountrdonly");
328 ret = syspopup_launch("mmc-syspopup", b);
330 _E("popup launch failed");
338 static void ums_unmount_cb(void *data)
340 umount(MOVINAND_MOUNT_POINT);
343 static int __check_abnormal_popup_launch(void)
345 static int noti_count = 0;
346 if (noti_count >= ABNORMAL_POPUP_COUNTER) {
355 static void charge_cb(struct ss_main_data *ad)
360 char params[BUFF_MAX];
361 static int bat_full_noti = 0;
363 ss_lowbat_monitor(NULL);
365 if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_NOW, &charge_now) != 0 ||
366 device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CAPACITY, &capacity) != 0)
367 _E("fail to get battery node value");
368 if (charge_now == 0 && capacity == 0) {
369 _E("target will be shut down");
370 ss_action_entry_call_internal(PREDEF_LOWBAT, 1, POWER_OFF_BAT_ACT);
374 if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_HEALTH, &val) == 0) {
375 if (val==BATTERY_OVERHEAT || val==BATTERY_COLD) {
376 _E("Battery health status is not good (%d)", val);
378 if (__check_abnormal_popup_launch() != 0)
381 if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CAPACITY, &val) == 0 && val <= 0)
382 ss_action_entry_call_internal(PREDEF_LOWBAT, 1, POWER_OFF_BAT_ACT);
384 ss_action_entry_call_internal(PREDEF_LOWBAT, 1, CHARGE_ERROR_ACT);
388 _E("failed to get battery health status");
390 device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_FULL, &val);
392 if (bat_full_noti==1) {
393 snprintf(params, sizeof(params), "%d %d", CB_NOTI_BATT_FULL, CB_NOTI_OFF);
394 ss_launch_if_noexist("/usr/bin/sys_device_noti", params);
398 if (val==1 && bat_full_noti==0) {
400 _D("battery full noti");
401 snprintf(params, sizeof(params), "%d %d", CB_NOTI_BATT_FULL, CB_NOTI_ON);
402 ss_launch_if_noexist("/usr/bin/sys_device_noti", params);
407 #ifdef ENABLE_EDBUS_USE
408 static void cb_xxxxx_signaled(void *data, DBusMessage * msg)
412 struct ss_main_data *ad;
416 dbus_error_init(&err);
417 if (dbus_message_get_args
418 (msg, &err, DBUS_TYPE_STRING, &args, DBUS_TYPE_INVALID)) {
419 if (!strcmp(args, "action")) ; /* action */
424 #endif /* ENABLE_EDBUS_USE */
426 static void usb_host_chgdet_cb(keynode_t *in_key, struct ss_main_data *ad)
428 _D("ENTER: usb_host_chgdet_cb()");
430 int ret = vconf_get_int(VCONFKEY_SYSMAN_USB_HOST_STATUS, &status);
432 _E("vconf get failed(VCONFKEY_SYSMAN_USB_HOST_STATUS)\n");
436 if(VCONFKEY_SYSMAN_USB_HOST_CONNECTED == status) {
437 int pid = ss_launch_if_noexist(USBCON_EXEC_PATH, NULL);
439 _D("usb-server launching failed\n");
443 _D("EXIT: usb_host_chgdet_cb()");
446 static void usb_host_add_cb()
448 _D("ENTER: usb_host_add_cb()\n");
450 int ret = vconf_get_int(VCONFKEY_SYSMAN_USB_HOST_STATUS, &status);
452 _D("vconf get failed ()\n");
456 if (-1 == status) { /* '-1' means that USB host mode is not loaded yet */
457 _D("This usb device is connected defaultly\n");
459 ret = system(STORE_DEFAULT_USB_INFO);
460 _D("Return value of usb-devices: %d\n", ret);
461 if (0 != access(DEFAULT_USB_INFO_PATH, F_OK)) {
462 ret = system(STORE_DEFAULT_USB_INFO);
463 _D("Return value of usb-devices: %d\n", ret);
466 _D("EXIT: usb_host_add_cb()\n");
469 static int uevent_control_stop(int ufd)
472 ecore_main_fd_handler_del(ufdh);
480 udev_monitor_unref(mon);
490 static int uevent_control_start(void)
496 _E("error create udev");
500 mon = udev_monitor_new_from_netlink(udev, "kernel");
502 _E("error udev_monitor create");
503 uevent_control_stop(-1);
507 udev_monitor_set_receive_buffer_size(mon, 1024);
508 if (udev_monitor_filter_add_match_subsystem_devtype(mon, "platform", NULL) < 0) {
509 _E("error apply subsystem filter");
510 uevent_control_stop(-1);
514 ufd = udev_monitor_get_fd(mon);
516 _E("error udev_monitor_get_fd");
517 uevent_control_stop(ufd);
521 ufdh = ecore_main_fd_handler_add(ufd, ECORE_FD_READ, uevent_control_cb, NULL, NULL, NULL);
523 _E("error ecore_main_fd_handler_add");
524 uevent_control_stop(ufd);
528 if (udev_monitor_enable_receiving(mon) < 0) {
529 _E("error unable to subscribe to udev events");
530 uevent_control_stop(ufd);
537 static int uevent_control_cb(void *data, Ecore_Fd_Handler *fd_handler)
539 struct udev_device *dev = NULL;
540 struct udev_list_entry *list_entry = NULL;
541 char *env_name = NULL;
542 char *env_value = NULL;
546 if (!ecore_main_fd_handler_active_get(fd_handler,ECORE_FD_READ))
548 if ((ufd = ecore_main_fd_handler_fd_get(fd_handler)) == -1)
550 if ((dev = udev_monitor_receive_device(mon)) == NULL)
553 udev_list_entry_foreach(list_entry,udev_device_get_properties_list_entry(dev)) {
554 env_name = udev_list_entry_get_name(list_entry);
555 if (strncmp(env_name, ENV_FILTER, strlen(ENV_FILTER)) == 0) {
556 env_value = udev_list_entry_get_value(list_entry);
563 udev_device_unref(dev);
567 _D("UEVENT DETECTED (%s)",env_value);
568 ss_action_entry_call_internal(PREDEF_DEVICE_CHANGED,1,env_value);
570 udev_device_unref(dev);
571 uevent_control_stop(ufd);
572 uevent_control_start();
577 int changed_device_def_predefine_action(int argc, char **argv)
579 if (argc != 1 || argv[0] == NULL) {
580 _E("param is failed");
584 if (strncmp(argv[0], ENV_VALUE_USB, strlen(ENV_VALUE_USB)) == 0)
586 if (strncmp(argv[0], ENV_VALUE_CHARGER, strlen(ENV_VALUE_CHARGER)) == 0)
588 if (strncmp(argv[0], ENV_VALUE_EARJACK, strlen(ENV_VALUE_EARJACK)) == 0)
589 earjack_chgdet_cb(NULL);
590 if (strncmp(argv[0], ENV_VALUE_EARKEY, strlen(ENV_VALUE_EARKEY)) == 0)
591 earkey_chgdet_cb(NULL);
592 if (strncmp(argv[0], ENV_VALUE_TVOUT, strlen(ENV_VALUE_TVOUT)) == 0)
593 tvout_chgdet_cb(NULL);
594 if (strncmp(argv[0], ENV_VALUE_HDMI, strlen(ENV_VALUE_HDMI)) == 0)
595 hdmi_chgdet_cb(NULL);
596 if (strncmp(argv[0], ENV_VALUE_KEYBOARD, strlen(ENV_VALUE_KEYBOARD)) == 0)
597 keyboard_chgdet_cb(NULL);
602 static void pci_keyboard_add_cb(struct ss_main_data *ad)
604 char params[BUFF_MAX];
605 _D("pci- keyboard inserted\n");
606 pm_change_internal(getpid(), LCD_NORMAL);
608 snprintf(params, sizeof(params), "%d", CB_NOTI_PCI_INSERTED);
609 ss_launch_if_noexist("/usr/bin/sys_pci_noti", params);
612 static void pci_keyboard_remove_cb(struct ss_main_data *ad)
614 char params[BUFF_MAX];
615 _D("pci- keyboard removed\n");
616 pm_change_internal(getpid(), LCD_NORMAL);
618 snprintf(params, sizeof(params), "%d", CB_NOTI_PCI_REMOVED);
619 ss_launch_if_noexist("/usr/bin/sys_pci_noti", params);
621 int ss_device_change_init(struct ss_main_data *ad)
623 ss_action_entry_add_internal(PREDEF_DEVICE_CHANGED, changed_device_def_predefine_action, NULL, NULL);
625 if (uevent_control_start() == -1) {
626 _E("fail uevent control init");
629 /* for simple noti change cb */
630 ss_noti_add("device_usb_chgdet", (void *)usb_chgdet_cb, (void *)ad);
631 ss_noti_add("device_ta_chgdet", (void *)ta_chgdet_cb, (void *)ad);
632 ss_noti_add("device_earjack_chgdet", (void *)earjack_chgdet_cb, (void *)ad);
633 ss_noti_add("device_earkey_chgdet", (void *)earkey_chgdet_cb, (void *)ad);
634 ss_noti_add("device_tvout_chgdet", (void *)tvout_chgdet_cb, (void *)ad);
635 ss_noti_add("device_hdmi_chgdet", (void *)hdmi_chgdet_cb, (void *)ad);
636 ss_noti_add("device_keyboard_chgdet", (void *)keyboard_chgdet_cb, (void *)ad);
638 ss_noti_add("device_usb_host_add", (void *)usb_host_add_cb, (void *)ad);
639 ss_noti_add("mmcblk_add", (void *)mmc_chgdet_cb, (void *)1);
640 ss_noti_add("mmcblk_remove", (void *)mmc_chgdet_cb, NULL);
642 ss_noti_add("unmount_ums", (void *)ums_unmount_cb, NULL);
643 ss_noti_add("device_charge_chgdet", (void *)charge_cb, (void *)ad);
645 ss_noti_add("device_pci_keyboard_add", (void *)pci_keyboard_add_cb, (void *)ad);
646 ss_noti_add("device_pci_keyboard_remove", (void *)pci_keyboard_remove_cb, (void *)ad);
648 if (vconf_notify_key_changed(VCONFKEY_SYSMAN_USB_HOST_STATUS, usb_host_chgdet_cb, NULL) < 0) {
649 _E("vconf key notify failed(VCONFKEY_SYSMAN_USB_HOST_STATUS)");
651 /* dbus noti change cb */
652 #ifdef ENABLE_EDBUS_USE
654 conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
656 _E("check system dbus running!\n");
658 e_dbus_signal_handler_add(conn, NULL, "/system/uevent/xxxxx",
659 "system.uevent.xxxxx",
660 "Change", cb_xxxxx_signaled, ad);
661 #endif /* ENABLE_EDBUS_USE */
663 /* set initial state for devices */
664 input_device_number = 0;
665 keyboard_chgdet_cb(NULL);
666 hdmi_chgdet_cb(NULL);
667 system(STORE_DEFAULT_USB_INFO);