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");
213 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_EARKEY_ONLINE, &val) == 0)
214 vconf_set_int(VCONFKEY_SYSMAN_EARJACKKEY, val);
217 static void tvout_chgdet_cb(struct ss_main_data *ad)
219 PRT_TRACE("jack - tvout changed\n");
220 pm_change_state(LCD_NORMAL);
223 static void hdmi_chgdet_cb(struct ss_main_data *ad)
228 pm_change_state(LCD_NORMAL);
229 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_HDMI_SUPPORT, &val) == 0) {
231 PRT_TRACE_ERR("target is not support HDMI");
232 vconf_set_int(VCONFKEY_SYSMAN_HDMI, HDMI_NOT_SUPPORTED);
236 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_HDMI_ONLINE, &val) == 0) {
237 PRT_TRACE("jack - hdmi changed %d",val);
238 vconf_set_int(VCONFKEY_SYSMAN_HDMI,val);
240 pm_lock_state(LCD_NORMAL, GOTO_STATE_NOW, 0);
242 pm_unlock_state(LCD_NORMAL, PM_SLEEP_MARGIN);
244 PRT_TRACE_ERR("failed to get hdmi_online status");
248 static void keyboard_chgdet_cb(struct ss_main_data *ad)
252 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_KEYBOARD_ONLINE, &val) == 0) {
253 PRT_TRACE("jack - keyboard changed %d",val);
256 vconf_set_int(VCONFKEY_SYSMAN_SLIDING_KEYBOARD, val);
258 vconf_set_int(VCONFKEY_SYSMAN_SLIDING_KEYBOARD, VCONFKEY_SYSMAN_SLIDING_KEYBOARD_NOT_SUPPORTED);
262 static void mmc_chgdet_cb(void *data)
269 /* when removed mmc, emul kernel notify twice
270 * So this code ignores second event */
273 PRT_TRACE("mmc removed");
277 /* when inserted mmc, emul kernel notify twice(insert, changed)
278 * So this code ignores second event */
281 PRT_TRACE("mmc added");
283 ret = ss_mmc_inserted();
285 vconf_get_int(VCONFKEY_SYSMAN_MMC_MOUNT,&val);
286 if (val == VCONFKEY_SYSMAN_MMC_MOUNT_FAILED) {
290 PRT_TRACE_ERR("error bundle_create()");
293 bundle_add(b, "_SYSPOPUP_CONTENT_", "mounterr");
294 ret = syspopup_launch("mmc-syspopup", b);
296 PRT_TRACE_ERR("popup launch failed");
299 } else if (val == VCONFKEY_SYSMAN_MMC_MOUNT_COMPLETED) {
303 PRT_TRACE_ERR("error bundle_create()");
306 bundle_add(b, "_SYSPOPUP_CONTENT_", "mountrdonly");
307 ret = syspopup_launch("mmc-syspopup", b);
309 PRT_TRACE_ERR("popup launch failed");
317 static void ums_unmount_cb(void *data)
319 umount(MOVINAND_MOUNT_POINT);
322 static int __check_abnormal_popup_launch(void)
324 static int noti_count = 0;
325 if (noti_count >= ABNORMAL_POPUP_COUNTER) {
334 static void charge_cb(struct ss_main_data *ad)
339 char params[BUFF_MAX];
340 static int bat_full_noti = 0;
342 ss_lowbat_monitor(NULL);
344 if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_NOW, &charge_now) != 0 ||
345 device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CAPACITY, &capacity) != 0)
346 PRT_TRACE_ERR("fail to get battery node value");
347 if (charge_now == 0 && capacity == 0) {
348 PRT_TRACE_ERR("target will be shut down");
349 ss_action_entry_call_internal(PREDEF_LOWBAT, 1, POWER_OFF_BAT_ACT);
353 if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_HEALTH, &val) == 0) {
354 if (val==BATTERY_OVERHEAT || val==BATTERY_COLD) {
355 PRT_TRACE_ERR("Battery health status is not good (%d)", val);
357 if (__check_abnormal_popup_launch() != 0)
360 if (device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CAPACITY, &val) == 0 && val <= 0)
361 ss_action_entry_call_internal(PREDEF_LOWBAT, 1, POWER_OFF_BAT_ACT);
363 ss_action_entry_call_internal(PREDEF_LOWBAT, 1, CHARGE_ERROR_ACT);
367 PRT_TRACE_ERR("failed to get battery health status");
369 device_get_property(DEVICE_TYPE_POWER, PROP_POWER_CHARGE_FULL, &val);
371 if (bat_full_noti==1) {
372 snprintf(params, sizeof(params), "%d %d", CB_NOTI_BATT_FULL, CB_NOTI_OFF);
373 ss_launch_if_noexist("/usr/bin/sys_device_noti", params);
377 if (val==1 && bat_full_noti==0) {
379 PRT_TRACE("battery full noti");
380 snprintf(params, sizeof(params), "%d %d", CB_NOTI_BATT_FULL, CB_NOTI_ON);
381 ss_launch_if_noexist("/usr/bin/sys_device_noti", params);
386 #ifdef ENABLE_EDBUS_USE
387 static void cb_xxxxx_signaled(void *data, DBusMessage * msg)
391 struct ss_main_data *ad;
395 dbus_error_init(&err);
396 if (dbus_message_get_args
397 (msg, &err, DBUS_TYPE_STRING, &args, DBUS_TYPE_INVALID)) {
398 if (!strcmp(args, "action")) ; /* action */
403 #endif /* ENABLE_EDBUS_USE */
405 static void usb_host_chgdet_cb(keynode_t *in_key, struct ss_main_data *ad)
407 PRT_TRACE("ENTER: usb_host_chgdet_cb()");
409 int ret = vconf_get_int(VCONFKEY_SYSMAN_USB_HOST_STATUS, &status);
411 PRT_TRACE_ERR("vconf get failed(VCONFKEY_SYSMAN_USB_HOST_STATUS)\n");
415 if(VCONFKEY_SYSMAN_USB_HOST_CONNECTED == status) {
416 int pid = ss_launch_if_noexist(USBCON_EXEC_PATH, NULL);
418 PRT_TRACE("usb-server launching failed\n");
422 PRT_TRACE("EXIT: usb_host_chgdet_cb()");
425 static void usb_host_add_cb()
427 PRT_TRACE("ENTER: usb_host_add_cb()\n");
429 int ret = vconf_get_int(VCONFKEY_SYSMAN_USB_HOST_STATUS, &status);
431 PRT_TRACE("vconf get failed ()\n");
435 if (-1 == status) { /* '-1' means that USB host mode is not loaded yet */
436 PRT_TRACE("This usb device is connected defaultly\n");
438 ret = system(STORE_DEFAULT_USB_INFO);
439 PRT_TRACE("Return value of usb-devices: %d\n", ret);
440 if (0 != access(DEFAULT_USB_INFO_PATH, F_OK)) {
441 ret = system(STORE_DEFAULT_USB_INFO);
442 PRT_TRACE("Return value of usb-devices: %d\n", ret);
445 PRT_TRACE("EXIT: usb_host_add_cb()\n");
448 static int uevent_control_stop(int ufd)
451 ecore_main_fd_handler_del(ufdh);
459 udev_monitor_unref(mon);
469 static int uevent_control_start(void)
475 PRT_TRACE_ERR("error create udev");
479 mon = udev_monitor_new_from_netlink(udev, "kernel");
481 PRT_TRACE_ERR("error udev_monitor create");
482 uevent_control_stop(-1);
486 udev_monitor_set_receive_buffer_size(mon, 1024);
487 if (udev_monitor_filter_add_match_subsystem_devtype(mon, "platform", NULL) < 0) {
488 PRT_TRACE_ERR("error apply subsystem filter");
489 uevent_control_stop(-1);
493 ufd = udev_monitor_get_fd(mon);
495 PRT_TRACE_ERR("error udev_monitor_get_fd");
496 uevent_control_stop(ufd);
500 ufdh = ecore_main_fd_handler_add(ufd, ECORE_FD_READ, uevent_control_cb, NULL, NULL, NULL);
502 PRT_TRACE_ERR("error ecore_main_fd_handler_add");
503 uevent_control_stop(ufd);
507 if (udev_monitor_enable_receiving(mon) < 0) {
508 PRT_TRACE_ERR("error unable to subscribe to udev events");
509 uevent_control_stop(ufd);
516 static int uevent_control_cb(void *data, Ecore_Fd_Handler *fd_handler)
518 struct udev_device *dev = NULL;
519 struct udev_list_entry *list_entry = NULL;
520 char *env_name = NULL;
521 char *env_value = NULL;
525 if (!ecore_main_fd_handler_active_get(fd_handler,ECORE_FD_READ))
527 if ((ufd = ecore_main_fd_handler_fd_get(fd_handler)) == -1)
529 if ((dev = udev_monitor_receive_device(mon)) == NULL)
532 udev_list_entry_foreach(list_entry,udev_device_get_properties_list_entry(dev)) {
533 env_name = udev_list_entry_get_name(list_entry);
534 if (strncmp(env_name, ENV_FILTER, strlen(ENV_FILTER)) == 0) {
535 env_value = udev_list_entry_get_value(list_entry);
542 udev_device_unref(dev);
546 PRT_TRACE("UEVENT DETECTED (%s)",env_value);
547 ss_action_entry_call_internal(PREDEF_DEVICE_CHANGED,1,env_value);
549 udev_device_unref(dev);
550 uevent_control_stop(ufd);
551 uevent_control_start();
556 int changed_device_def_predefine_action(int argc, char **argv)
558 if (argc != 1 || argv[0] == NULL) {
559 PRT_TRACE_ERR("param is failed");
563 if (strncmp(argv[0], ENV_VALUE_USB, strlen(ENV_VALUE_USB)) == 0)
565 if (strncmp(argv[0], ENV_VALUE_CHARGER, strlen(ENV_VALUE_CHARGER)) == 0)
567 if (strncmp(argv[0], ENV_VALUE_EARJACK, strlen(ENV_VALUE_EARJACK)) == 0)
568 earjack_chgdet_cb(NULL);
569 if (strncmp(argv[0], ENV_VALUE_EARKEY, strlen(ENV_VALUE_EARKEY)) == 0)
570 earkey_chgdet_cb(NULL);
571 if (strncmp(argv[0], ENV_VALUE_TVOUT, strlen(ENV_VALUE_TVOUT)) == 0)
572 tvout_chgdet_cb(NULL);
573 if (strncmp(argv[0], ENV_VALUE_HDMI, strlen(ENV_VALUE_HDMI)) == 0)
574 hdmi_chgdet_cb(NULL);
575 if (strncmp(argv[0], ENV_VALUE_KEYBOARD, strlen(ENV_VALUE_KEYBOARD)) == 0)
576 keyboard_chgdet_cb(NULL);
581 static void pci_keyboard_add_cb(struct ss_main_data *ad)
583 char params[BUFF_MAX];
584 PRT_TRACE("pci- keyboard inserted\n");
585 pm_change_state(LCD_NORMAL);
587 snprintf(params, sizeof(params), "%d", CB_NOTI_PCI_INSERTED);
588 ss_launch_if_noexist("/usr/bin/sys_pci_noti", params);
591 static void pci_keyboard_remove_cb(struct ss_main_data *ad)
593 char params[BUFF_MAX];
594 PRT_TRACE("pci- keyboard removed\n");
595 pm_change_state(LCD_NORMAL);
597 snprintf(params, sizeof(params), "%d", CB_NOTI_PCI_REMOVED);
598 ss_launch_if_noexist("/usr/bin/sys_pci_noti", params);
600 int ss_device_change_init(struct ss_main_data *ad)
602 ss_action_entry_add_internal(PREDEF_DEVICE_CHANGED, changed_device_def_predefine_action, NULL, NULL);
604 if (uevent_control_start() == -1) {
605 PRT_TRACE_ERR("fail uevent control init");
608 /* for simple noti change cb */
609 ss_noti_add("device_usb_chgdet", (void *)usb_chgdet_cb, (void *)ad);
610 ss_noti_add("device_ta_chgdet", (void *)ta_chgdet_cb, (void *)ad);
611 ss_noti_add("device_earjack_chgdet", (void *)earjack_chgdet_cb, (void *)ad);
612 ss_noti_add("device_earkey_chgdet", (void *)earkey_chgdet_cb, (void *)ad);
613 ss_noti_add("device_tvout_chgdet", (void *)tvout_chgdet_cb, (void *)ad);
614 ss_noti_add("device_hdmi_chgdet", (void *)hdmi_chgdet_cb, (void *)ad);
615 ss_noti_add("device_keyboard_chgdet", (void *)keyboard_chgdet_cb, (void *)ad);
617 ss_noti_add("device_usb_host_add", (void *)usb_host_add_cb, (void *)ad);
618 ss_noti_add("mmcblk_add", (void *)mmc_chgdet_cb, (void *)1);
619 ss_noti_add("mmcblk_remove", (void *)mmc_chgdet_cb, NULL);
621 ss_noti_add("unmount_ums", (void *)ums_unmount_cb, NULL);
622 ss_noti_add("device_charge_chgdet", (void *)charge_cb, (void *)ad);
624 ss_noti_add("device_pci_keyboard_add", (void *)pci_keyboard_add_cb, (void *)ad);
625 ss_noti_add("device_pci_keyboard_remove", (void *)pci_keyboard_remove_cb, (void *)ad);
627 if (vconf_notify_key_changed(VCONFKEY_SYSMAN_USB_HOST_STATUS, usb_host_chgdet_cb, NULL) < 0) {
628 PRT_TRACE_ERR("vconf key notify failed(VCONFKEY_SYSMAN_USB_HOST_STATUS)");
630 /* dbus noti change cb */
631 #ifdef ENABLE_EDBUS_USE
633 conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
635 PRT_TRACE_ERR("check system dbus running!\n");
637 e_dbus_signal_handler_add(conn, NULL, "/system/uevent/xxxxx",
638 "system.uevent.xxxxx",
639 "Change", cb_xxxxx_signaled, ad);
640 #endif /* ENABLE_EDBUS_USE */
642 /* set initial state for devices */
643 input_device_number = 0;
644 keyboard_chgdet_cb(NULL);
645 hdmi_chgdet_cb(NULL);
646 system(STORE_DEFAULT_USB_INFO);