4 * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
26 #include <sys/types.h>
28 #include <sys/mount.h>
31 #include "dd-deviced.h"
34 #include "device-notifier.h"
35 #include "device-handler.h"
36 #include "device-node.h"
39 #include "predefine.h"
40 #include "display/poll.h"
42 #include "hall/hall-handler.h"
47 #include "proc/proc-handler.h"
48 #include "edbus-handler.h"
51 #include "power-supply.h"
52 #include "display/setting.h"
53 #include "display/core.h"
55 #define PREDEF_EARJACKCON "earjack_predef_internal"
56 #define PREDEF_DEVICE_CHANGED "device_changed"
57 #define PREDEF_POWER_CHANGED POWER_SUBSYSTEM
58 #define PREDEF_UDEV_CONTROL UDEV
60 #define TVOUT_X_BIN "/usr/bin/xberc"
61 #define TVOUT_FLAG 0x00000001
63 #define MOVINAND_MOUNT_POINT "/opt/media"
65 #define SYS_CLASS_INPUT "/sys/class/input"
68 #define USB_STATE_PATH "/sys/devices/platform/jack/usb_online"
70 #define USB_STATE_PATH "/sys/devices/virtual/switch/usb_cable/state"
73 #define HDMI_NOT_SUPPORTED (-1)
74 #ifdef ENABLE_EDBUS_USE
76 static E_DBus_Connection *conn;
77 #endif /* ENABLE_EDBUS_USE */
87 SND_JACK_HEADPHONE = 0x0001,
88 SND_JACK_MICROPHONE = 0x0002,
89 SND_JACK_HEADSET = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE,
90 SND_JACK_LINEOUT = 0x0004,
91 SND_JACK_MECHANICAL = 0x0008, /* If detected separately */
92 SND_JACK_VIDEOOUT = 0x0010,
93 SND_JACK_AVOUT = SND_JACK_LINEOUT | SND_JACK_VIDEOOUT,
96 #define CRADLE_APP_NAME "com.samsung.desk-dock"
97 #define VIRTUAL_CONTROLLER_APP_NAME "com.samsung.virtual-controller"
99 #define CHANGE_ACTION "change"
100 #define ENV_FILTER "CHGDET"
101 #define USB_NAME "usb"
102 #define USB_NAME_LEN 3
104 #define CHARGER_NAME "charger"
105 #define CHARGER_NAME_LEN 7
107 #define EARJACK_NAME "earjack"
108 #define EARJACK_NAME_LEN 7
110 #define EARKEY_NAME "earkey"
111 #define EARKEY_NAME_LEN 6
113 #define TVOUT_NAME "tvout"
114 #define TVOUT_NAME_LEN 5
116 #define HDMI_NAME "hdmi"
117 #define HDMI_NAME_LEN 4
119 #define HDCP_NAME "hdcp"
120 #define HDCP_NAME_LEN 4
122 #define HDMI_AUDIO_NAME "ch_hdmi_audio"
123 #define HDMI_AUDIO_LEN 13
125 #define CRADLE_NAME "cradle"
126 #define CRADLE_NAME_LEN 6
128 #define KEYBOARD_NAME "keyboard"
129 #define KEYBOARD_NAME_LEN 8
131 #define POWER_SUPPLY_NAME_LEN 12
133 #define CHARGE_NAME_LEN 17
134 #define BATTERY_NAME "battery"
135 #define BATTERY_NAME_LEN 7
136 #define CHARGEFULL_NAME "Full"
137 #define CHARGEFULL_NAME_LEN 4
138 #define CHARGENOW_NAME "Charging"
139 #define CHARGENOW_NAME_LEN 8
140 #define DISCHARGE_NAME "Discharging"
141 #define DISCHARGE_NAME_LEN 11
142 #define NOTCHARGE_NAME "Not charging"
143 #define NOTCHARGE_NAME_LEN 12
144 #define OVERHEAT_NAME "Overheat"
145 #define OVERHEAT_NAME_LEN 8
146 #define TEMPCOLD_NAME "Cold"
147 #define TEMPCOLD_NAME_LEN 4
148 #define OVERVOLT_NAME "Over voltage"
149 #define OVERVOLT_NAME_LEN 12
151 #define SWITCH_DEVICE_USB "usb_cable"
153 #define LAUNCH_APP "launch-app"
154 #define DESK_DOCK "desk-dock"
156 /* Ticker notification */
157 #define DOCK_CONNECTED "dock-connected"
158 #define HDMI_CONNECTED "hdmi-connected"
159 #define HDMI_DISCONNECTED "hdmi-disconnected"
161 #define METHOD_GET_HDMI "GetHDMI"
162 #define METHOD_GET_HDCP "GetHDCP"
163 #define METHOD_GET_HDMI_AUDIO "GetHDMIAudio"
164 #define SIGNAL_HDMI_STATE "ChangedHDMI"
165 #define SIGNAL_HDCP_STATE "ChangedHDCP"
166 #define SIGNAL_HDMI_AUDIO_STATE "ChangedHDMIAudio"
168 #define HDCP_HDMI_VALUE(HDCP, HDMI) ((HDCP << 1) | HDMI)
170 #define METHOD_GET_CRADLE "GetCradle"
171 #define SIGNAL_CRADLE_STATE "ChangedCradle"
184 static int ss_flags = 0;
186 static int input_device_number;
189 static struct udev *udev = NULL;
191 static struct udev_monitor *mon = NULL;
192 static Ecore_Fd_Handler *ufdh = NULL;
195 static struct udev_monitor *mon_udev = NULL;
196 static Ecore_Fd_Handler *ufdh_udev = NULL;
197 static int ufd_udev = -1;
199 static dd_list *opt_uevent_list = NULL;
200 static dd_list *opt_kernel_uevent_list = NULL;
201 static int hdmi_status = 0;
202 static const struct device_ops *lowbat_ops;
204 enum udev_subsystem_type {
213 static const struct udev_subsystem {
214 const enum udev_subsystem_type type;
217 } udev_subsystems[] = {
218 { UDEV_HALL_IC, HALL_IC_SUBSYSTEM, NULL},
219 { UDEV_INPUT, INPUT_SUBSYSTEM, NULL },
220 { UDEV_LCD_EVENT, LCD_EVENT_SUBSYSTEM, NULL },
221 { UDEV_PLATFORM, PLATFORM_SUBSYSTEM, NULL },
222 { UDEV_POWER, POWER_SUBSYSTEM, NULL},
223 { UDEV_SWITCH, SWITCH_SUBSYSTEM, NULL },
226 static struct extcon_device {
227 const enum extcon_type type;
231 } extcon_devices[] = {
232 { EXTCON_TA, "/csa/factory/batt_cable_count", 0, 0},
233 { EXTCON_EARJACK, "/csa/factory/earjack_count", 0, 0},
236 extern int battery_power_off_act(void *data);
237 extern int battery_charge_err_act(void *data);
239 int extcon_set_count(int index)
245 extcon_devices[index].count++;
247 if (extcon_devices[index].fd < 0) {
248 _E("cannot open file(%s)", extcon_devices[index].str);
251 lseek(extcon_devices[index].fd, 0, SEEK_SET);
252 _I("ext(%d) count %d", index, extcon_devices[index].count);
253 snprintf(buf, sizeof(buf), "%d", extcon_devices[index].count);
255 r = write(extcon_devices[index].fd, buf, strlen(buf));
261 static int extcon_get_count(int index)
268 fd = open(extcon_devices[index].str, O_RDWR);
272 r = read(fd, buf, BUFF_MAX);
273 if ((r >= 0) && (r < BUFF_MAX))
282 extcon_devices[index].fd = fd;
283 extcon_devices[index].count = atoi(buf);
284 _I("get extcon(%d:%x) count %d",
285 index, extcon_devices[index].fd, extcon_devices[index].count);
290 static int extcon_create_count(int index)
296 fd = open(extcon_devices[index].str, O_RDWR | O_CREAT, 0644);
298 _E("cannot open file(%s)", extcon_devices[index].str);
301 snprintf(buf, sizeof(buf), "%d", extcon_devices[index].count);
302 r = write(fd, buf, strlen(buf));
308 _E("cannot write file(%s)", extcon_devices[index].str);
311 extcon_devices[index].fd = fd;
312 _I("create extcon(%d:%x) %s",
313 index, extcon_devices[index].fd, extcon_devices[index].str);
317 static int extcon_count_init(void)
321 for (i = 0; i < ARRAY_SIZE(extcon_devices); i++) {
322 if (extcon_get_count(i) >= 0)
324 ret = extcon_create_count(i);
331 int get_usb_state_direct(void)
337 fp = fopen(USB_STATE_PATH, "r");
339 _E("Cannot open jack node");
343 if (!fgets(str, sizeof(str), fp)) {
344 _E("cannot get string from jack node");
354 static void usb_chgdet_cb(void *data)
358 char params[BUFF_MAX];
361 ret = device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_USB_ONLINE, &val);
366 val = get_usb_state_direct();
368 _I("jack - usb changed %d",val);
369 check_lowbat_charge_device(val);
371 battery_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_ON);
372 _D("usb device notification");
375 _E("fail to get usb_online status");
379 static void show_ticker_notification(char *text, int queue)
381 struct ticker_data t_data;
382 static const struct device_ops *ticker = NULL;
385 ticker = find_device("ticker");
393 ticker->init(&t_data);
396 static void launch_cradle(int val)
398 struct popup_data *params;
399 static const struct device_ops *apps = NULL;
402 apps = find_device("apps");
406 params = malloc(sizeof(struct popup_data));
407 if (params == NULL) {
411 params->name = LAUNCH_APP;
412 params->key = DESK_DOCK;
413 _I("%s %s %x", params->name, params->key, params);
416 apps->exit((void *)params);
418 show_ticker_notification(DOCK_CONNECTED, 0);
420 apps->init((void *)params);
426 static int display_changed(void *data)
428 enum state_t state = (enum state_t)data;
431 if (battery.charge_now == CHARGER_ABNORMAL && battery.health == HEALTH_BAD) {
432 pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, 0);
436 if (state != S_NORMAL)
439 ret = vconf_get_int(VCONFKEY_SYSMAN_CRADLE_STATUS, &cradle);
440 if (ret >= 0 && cradle == DOCK_SOUND) {
441 pm_lock_internal(getpid(), LCD_DIM, STAY_CUR_STATE, 0);
442 _I("sound dock is connected! dim lock is on.");
445 pm_lock_internal(getpid(), LCD_DIM, STAY_CUR_STATE, 0);
446 _I("hdmi is connected! dim lock is on.");
451 static void cradle_send_broadcast(int status)
460 _I("broadcast cradle status %d", status);
462 snprintf(str_status, sizeof(str_status), "%d", status);
465 broadcast_edbus_signal(DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI,
466 SIGNAL_CRADLE_STATE, "i", arr);
469 static int cradle_cb(void *data)
484 cradle_send_broadcast(old);
488 static void cradle_chgdet_cb(void *data)
493 pm_change_internal(getpid(), LCD_NORMAL);
498 ret = device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_CRADLE_ONLINE, &val);
500 _E("failed to get status");
505 _I("jack - cradle changed %d", val);
506 cradle_cb((void *)&val);
507 if (vconf_set_int(VCONFKEY_SYSMAN_CRADLE_STATUS, val) != 0) {
508 _E("failed to set vconf status");
512 if (val == DOCK_SOUND)
513 pm_lock_internal(getpid(), LCD_DIM, STAY_CUR_STATE, 0);
514 else if (val == DOCK_NONE)
515 pm_unlock_internal(getpid(), LCD_DIM, PM_SLEEP_MARGIN);
520 void sync_cradle_status(void)
524 if ((device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_CRADLE_ONLINE, &val) != 0) ||
525 vconf_get_int(VCONFKEY_SYSMAN_CRADLE_STATUS, &status) != 0)
527 if ((val != 0 && status == 0) || (val == 0 && status != 0))
528 cradle_chgdet_cb(NULL);
531 static void ta_chgdet_cb(struct main_data *ad)
535 int bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
536 char params[BUFF_MAX];
538 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_TA_ONLINE, &val) == 0) {
539 _I("jack - ta changed %d",val);
540 check_lowbat_charge_device(val);
541 vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, val);
543 ret = device_get_property(DEVICE_TYPE_POWER, PROP_POWER_INSUSPEND_CHARGING_SUPPORT, &val);
547 pm_unlock_internal(INTERNAL_LOCK_TA, LCD_OFF, STAY_CUR_STATE);
548 device_notify(DEVICE_NOTIFIER_BATTERY_CHARGING, (void*)FALSE);
550 ret = device_get_property(DEVICE_TYPE_POWER, PROP_POWER_INSUSPEND_CHARGING_SUPPORT, &val);
554 pm_lock_internal(INTERNAL_LOCK_TA, LCD_OFF, STAY_CUR_STATE, 0);
555 battery_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_ON);
556 _D("ta device notification");
557 device_notify(DEVICE_NOTIFIER_BATTERY_CHARGING, (void*)TRUE);
559 sync_cradle_status();
562 _E("failed to get ta status");
565 static void earjack_chgdet_cb(void *data)
573 ret = device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_EARJACK_ONLINE, &val);
575 _E("failed to get status");
579 _I("jack - earjack changed %d", val);
580 if (CONNECTED(val)) {
581 extcon_set_count(EXTCON_EARJACK);
582 predefine_pm_change_state(LCD_NORMAL);
584 vconf_set_int(VCONFKEY_SYSMAN_EARJACK, val);
587 static void earkey_chgdet_cb(void *data)
595 ret = device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_EARKEY_ONLINE, &val);
597 _E("failed to get status");
601 _I("jack - earkey changed %d", val);
602 vconf_set_int(VCONFKEY_SYSMAN_EARJACKKEY, val);
605 static void tvout_chgdet_cb(void *data)
607 _I("jack - tvout changed");
608 pm_change_internal(getpid(), LCD_NORMAL);
611 static void hdcp_hdmi_send_broadcast(int status)
620 _I("broadcast hdmi status %d", status);
622 snprintf(str_status, sizeof(str_status), "%d", status);
625 broadcast_edbus_signal(DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI,
626 SIGNAL_HDMI_STATE, "i", arr);
629 static int hdcp_hdmi_cb(void *data)
639 val = HDCP_HDMI_VALUE(val, hdmi_status);
645 hdcp_hdmi_send_broadcast(old);
649 static void hdmi_chgdet_cb(void *data)
654 pm_change_internal(getpid(), LCD_NORMAL);
655 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_HDMI_SUPPORT, &val) == 0) {
657 _I("target is not support HDMI");
658 vconf_set_int(VCONFKEY_SYSMAN_HDMI, HDMI_NOT_SUPPORTED);
666 ret = device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_HDMI_ONLINE, &val);
668 _E("failed to get status");
673 _I("jack - hdmi changed %d", val);
674 vconf_set_int(VCONFKEY_SYSMAN_HDMI, val);
676 device_notify(DEVICE_NOTIFIER_HDMI, (void *)val);
679 pm_lock_internal(INTERNAL_LOCK_HDMI, LCD_DIM, STAY_CUR_STATE, 0);
680 show_ticker_notification(HDMI_CONNECTED, 0);
682 show_ticker_notification(HDMI_DISCONNECTED, 0);
683 pm_unlock_internal(INTERNAL_LOCK_HDMI, LCD_DIM, PM_SLEEP_MARGIN);
687 static void hdcp_send_broadcast(int status)
696 _D("broadcast hdcp status %d", status);
698 snprintf(str_status, sizeof(str_status), "%d", status);
701 broadcast_edbus_signal(DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI,
702 SIGNAL_HDCP_STATE, "i", arr);
705 static int hdcp_chgdet_cb(void *data)
718 hdcp_send_broadcast(old);
722 static void hdmi_audio_send_broadcast(int status)
731 _D("broadcast hdmi audio status %d", status);
733 snprintf(str_status, sizeof(str_status), "%d", status);
736 broadcast_edbus_signal(DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI,
737 SIGNAL_HDMI_AUDIO_STATE, "i", arr);
740 static int hdmi_audio_chgdet_cb(void *data)
753 hdmi_audio_send_broadcast(old);
757 static void keyboard_chgdet_cb(void *data)
765 ret = device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_KEYBOARD_ONLINE, &val);
767 _E("failed to get status");
768 vconf_set_int(VCONFKEY_SYSMAN_SLIDING_KEYBOARD, VCONFKEY_SYSMAN_SLIDING_KEYBOARD_NOT_SUPPORTED);
772 _I("jack - keyboard changed %d", val);
775 vconf_set_int(VCONFKEY_SYSMAN_SLIDING_KEYBOARD, val);
778 static void ums_unmount_cb(void *data)
780 umount(MOVINAND_MOUNT_POINT);
783 #ifdef ENABLE_EDBUS_USE
784 static void cb_xxxxx_signaled(void *data, DBusMessage * msg)
788 struct main_data *ad;
792 dbus_error_init(&err);
793 if (dbus_message_get_args
794 (msg, &err, DBUS_TYPE_STRING, &args, DBUS_TYPE_INVALID)) {
795 if (!strcmp(args, "action")) ; /* action */
800 #endif /* ENABLE_EDBUS_USE */
802 static void check_capacity_status(const char *env_value)
804 if (env_value == NULL)
806 battery.capacity = atoi(env_value);
809 static void check_charge_status(const char *env_value)
811 if (env_value == NULL)
813 if (strncmp(env_value, CHARGEFULL_NAME , CHARGEFULL_NAME_LEN) == 0) {
814 battery.charge_full = CHARGING_FULL;
815 battery.charge_now = CHARGER_DISCHARGING;
816 } else if (strncmp(env_value, CHARGENOW_NAME, CHARGENOW_NAME_LEN) == 0) {
817 battery.charge_full = CHARGING_NOT_FULL;
818 battery.charge_now = CHARGER_CHARGING;
819 } else if (strncmp(env_value, DISCHARGE_NAME, DISCHARGE_NAME_LEN) == 0) {
820 battery.charge_full = CHARGING_NOT_FULL;
821 battery.charge_now = CHARGER_DISCHARGING;
822 } else if (strncmp(env_value, NOTCHARGE_NAME, NOTCHARGE_NAME_LEN) == 0) {
823 battery.charge_full = CHARGING_NOT_FULL;
824 battery.charge_now = CHARGER_ABNORMAL;
826 battery.charge_full = CHARGING_NOT_FULL;
827 battery.charge_now = CHARGER_DISCHARGING;
831 static void check_health_status(const char *env_value)
833 if (env_value == NULL) {
834 battery.health = HEALTH_GOOD;
835 battery.temp = TEMP_LOW;
836 battery.ovp = OVP_NORMAL;
839 if (strncmp(env_value, OVERHEAT_NAME, OVERHEAT_NAME_LEN) == 0) {
840 battery.health = HEALTH_BAD;
841 battery.temp = TEMP_HIGH;
842 battery.ovp = OVP_NORMAL;
843 } else if (strncmp(env_value, TEMPCOLD_NAME, TEMPCOLD_NAME_LEN) == 0) {
844 battery.health = HEALTH_BAD;
845 battery.temp = TEMP_LOW;
846 battery.ovp = OVP_NORMAL;
847 } else if (strncmp(env_value, OVERVOLT_NAME, OVERVOLT_NAME_LEN) == 0) {
848 battery.health = HEALTH_GOOD;
849 battery.temp = TEMP_LOW;
850 battery.ovp = OVP_ABNORMAL;
852 battery.health = HEALTH_GOOD;
853 battery.temp = TEMP_LOW;
854 battery.ovp = OVP_NORMAL;
858 static void check_online_status(const char *env_value)
860 if (env_value == NULL)
862 battery.online = atoi(env_value);
865 static void check_present_status(const char *env_value)
867 if (env_value == NULL) {
868 battery.present = PRESENT_NORMAL;
871 battery.present = atoi(env_value);
874 static Eina_Bool uevent_kernel_control_cb(void *data, Ecore_Fd_Handler *fd_handler)
876 struct udev_device *dev = NULL;
877 struct udev_list_entry *list_entry = NULL;
878 const char *subsystem = NULL;
879 const char *env_name = NULL;
880 const char *env_value = NULL;
884 const char *siop_level;
885 const char *rear_level;
888 struct uevent_handler *uh;
892 if ((dev = udev_monitor_receive_device(mon)) == NULL)
895 subsystem = udev_device_get_subsystem(dev);
897 for (i = 0; i < ARRAY_SIZE(udev_subsystems); i++) {
898 len = strlen(udev_subsystems[i].str);
899 if (!strncmp(subsystem, udev_subsystems[i].str, len))
903 if (i >= ARRAY_SIZE(udev_subsystems))
906 devpath = udev_device_get_devpath(dev);
908 switch (udev_subsystems[i].type) {
910 if (!strncmp(devpath, HALL_IC_PATH, strlen(HALL_IC_PATH))) {
911 notify_action(PREDEF_HALL_IC, 1, HALL_IC_NAME);
916 /* check new input device */
917 if (!fnmatch(INPUT_PATH, devpath, 0)) {
918 action = udev_device_get_action(dev);
919 devnode = udev_device_get_devnode(dev);
920 if (!strcmp(action, UDEV_ADD))
921 device_notify(DEVICE_NOTIFIER_INPUT_ADD, (void *)devnode);
922 else if (!strcmp(action, UDEV_REMOVE))
923 device_notify(DEVICE_NOTIFIER_INPUT_REMOVE, (void *)devnode);
928 /* check new esd device */
929 if (!fnmatch(LCD_ESD_PATH, devpath, 0)) {
930 action = udev_device_get_action(dev);
931 if (!strcmp(action, UDEV_CHANGE))
932 device_notify(DEVICE_NOTIFIER_LCD_ESD, "ESD");
937 env_name = udev_device_get_property_value(dev, "SWITCH_NAME");
938 env_value = udev_device_get_property_value(dev, "SWITCH_STATE");
939 notify_action(PREDEF_DEVICE_CHANGED, 2, env_name, env_value);
942 if (!fnmatch(THERMISTOR_PATH, devpath, 0)) {
943 siop_level = udev_device_get_property_value(dev, "TEMPERATURE");
944 rear_level = udev_device_get_property_value(dev, "REAR_TEMPERATURE");
945 notify_action(SIOP_CHANGED, 2, siop_level, rear_level);
949 env_value = udev_device_get_property_value(dev, ENV_FILTER);
952 notify_action(PREDEF_DEVICE_CHANGED, 1, env_value);
955 udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(dev)) {
956 env_name = udev_list_entry_get_name(list_entry);
957 if (env_name == NULL)
959 if (strncmp(env_name, CHARGE_NAME, CHARGE_NAME_LEN) == 0) {
960 env_value = udev_list_entry_get_value(list_entry);
961 if (env_value == NULL)
963 if (strncmp(env_value, BATTERY_NAME, BATTERY_NAME_LEN) == 0) {
971 env_value = udev_device_get_property_value(dev, CHARGE_STATUS);
972 check_charge_status(env_value);
973 env_value = udev_device_get_property_value(dev, CHARGE_ONLINE);
974 check_online_status(env_value);
975 env_value = udev_device_get_property_value(dev, CHARGE_HEALTH);
976 check_health_status(env_value);
977 env_value = udev_device_get_property_value(dev, CHARGE_PRESENT);
978 check_present_status(env_value);
979 env_value = udev_device_get_property_value(dev, CAPACITY);
980 check_capacity_status(env_value);
981 battery_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_ON);
983 notify_action(PREDEF_DEVICE_CHANGED, 2, subsystem, env_value);
985 notify_action(PREDEF_DEVICE_CHANGED, 1, subsystem);
990 DD_LIST_FOREACH(opt_kernel_uevent_list, l, l_data) {
991 uh = (struct uevent_handler *)l_data;
992 if (strncmp(subsystem, uh->subsystem, strlen(uh->subsystem)))
994 uh->uevent_func(dev);
997 udev_device_unref(dev);
1001 static Eina_Bool uevent_udev_control_cb(void *data, Ecore_Fd_Handler *fd_handler)
1003 struct udev_device *dev = NULL;
1006 struct uevent_handler *uh;
1007 const char *subsystem = NULL;
1009 dev = udev_monitor_receive_device(mon_udev);
1013 subsystem = udev_device_get_subsystem(dev);
1015 _E("Failed to get subsystem from uevent");
1019 DD_LIST_FOREACH(opt_uevent_list, l, l_data) {
1020 uh = (struct uevent_handler *)l_data;
1021 if (strncmp(subsystem, uh->subsystem, strlen(uh->subsystem)))
1023 uh->uevent_func(dev);
1027 udev_device_unref(dev);
1031 static int uevent_kernel_control_stop(void)
1033 struct udev_device *dev = NULL;
1036 ecore_main_fd_handler_del(ufdh);
1044 dev = udev_monitor_receive_device(mon);
1046 udev_device_unref(dev);
1049 udev_monitor_unref(mon);
1052 if (udev && !mon_udev) {
1059 static int uevent_udev_control_stop(void)
1061 struct udev_device *dev = NULL;
1064 ecore_main_fd_handler_del(ufdh_udev);
1067 if (ufd_udev >= 0) {
1072 dev = udev_monitor_receive_device(mon_udev);
1074 udev_device_unref(dev);
1077 udev_monitor_unref(mon_udev);
1087 static int uevent_kernel_control_start(void)
1092 _E("uevent control routine is alreay started");
1099 _E("error create udev");
1104 mon = udev_monitor_new_from_netlink(udev, UDEV);
1106 _E("error udev_monitor create");
1110 if (udev_monitor_set_receive_buffer_size(mon, UDEV_MONITOR_SIZE) != 0) {
1111 _E("fail to set receive buffer size");
1115 for (i = 0; i < ARRAY_SIZE(udev_subsystems); i++) {
1116 ret = udev_monitor_filter_add_match_subsystem_devtype(mon,
1117 udev_subsystems[i].str, udev_subsystems[i].devtype);
1119 _E("error apply subsystem filter");
1124 ret = udev_monitor_filter_update(mon);
1126 _E("error udev_monitor_filter_update");
1128 ufd = udev_monitor_get_fd(mon);
1130 _E("error udev_monitor_get_fd");
1134 ufdh = ecore_main_fd_handler_add(ufd, ECORE_FD_READ,
1135 uevent_kernel_control_cb, NULL, NULL, NULL);
1137 _E("error ecore_main_fd_handler_add");
1141 if (udev_monitor_enable_receiving(mon) < 0) {
1142 _E("error unable to subscribe to udev events");
1148 uevent_kernel_control_stop();
1153 static int uevent_udev_control_start(void)
1157 if (udev && mon_udev) {
1158 _E("uevent control routine is alreay started");
1165 _E("error create udev");
1170 mon_udev = udev_monitor_new_from_netlink(udev, "udev");
1171 if (mon_udev == NULL) {
1172 _E("error udev_monitor create");
1176 if (udev_monitor_set_receive_buffer_size(mon_udev, UDEV_MONITOR_SIZE_LARGE) != 0) {
1177 _E("fail to set receive buffer size");
1181 ufd_udev = udev_monitor_get_fd(mon_udev);
1182 if (ufd_udev == -1) {
1183 _E("error udev_monitor_get_fd");
1187 ufdh_udev = ecore_main_fd_handler_add(ufd_udev, ECORE_FD_READ,
1188 uevent_udev_control_cb, NULL, NULL, NULL);
1190 _E("error ecore_main_fd_handler_add");
1194 if (udev_monitor_enable_receiving(mon_udev) < 0) {
1195 _E("error unable to subscribe to udev events");
1201 uevent_udev_control_stop();
1205 int register_uevent_control(const struct uevent_handler *uh)
1212 ret = udev_monitor_filter_add_match_subsystem_devtype(mon_udev,
1213 uh->subsystem, NULL);
1215 _E("FAIL: udev_monitor_filter_add_match_subsystem_devtype()");
1219 ret = udev_monitor_filter_update(mon_udev);
1221 _E("error udev_monitor_filter_update");
1223 DD_LIST_APPEND(opt_uevent_list, uh);
1228 void unregister_uevent_control(const struct uevent_handler *uh)
1232 struct uevent_handler *handler;
1234 DD_LIST_FOREACH(opt_uevent_list, l, data) {
1235 handler = (struct uevent_handler *)data;
1236 if (strncmp(handler->subsystem, uh->subsystem, strlen(uh->subsystem)))
1238 if (handler->uevent_func != uh->uevent_func)
1241 DD_LIST_REMOVE(opt_uevent_list, handler);
1247 int register_kernel_uevent_control(const struct uevent_handler *uh)
1254 ret = udev_monitor_filter_add_match_subsystem_devtype(mon,
1255 uh->subsystem, NULL);
1257 _E("FAIL: udev_monitor_filter_add_match_subsystem_devtype()");
1261 ret = udev_monitor_filter_update(mon);
1263 _E("error udev_monitor_filter_update");
1265 DD_LIST_APPEND(opt_kernel_uevent_list, uh);
1270 void unregister_kernel_uevent_control(const struct uevent_handler *uh)
1274 struct uevent_handler *handler;
1276 DD_LIST_FOREACH(opt_kernel_uevent_list, l, data) {
1277 handler = (struct uevent_handler *)data;
1278 if (strncmp(handler->subsystem, uh->subsystem, strlen(uh->subsystem)))
1280 if (handler->uevent_func != uh->uevent_func)
1283 DD_LIST_REMOVE(opt_kernel_uevent_list, data);
1288 int uevent_udev_get_path(const char *subsystem, dd_list **list)
1290 struct udev_enumerate *enumerate = NULL;
1291 struct udev_list_entry *devices, *dev_list_entry;
1297 _E("error create udev");
1302 enumerate = udev_enumerate_new(udev);
1306 ret = udev_enumerate_add_match_subsystem(enumerate, subsystem);
1310 ret = udev_enumerate_scan_devices(enumerate);
1314 devices = udev_enumerate_get_list_entry(enumerate);
1316 udev_list_entry_foreach(dev_list_entry, devices) {
1318 path = udev_list_entry_get_name(dev_list_entry);
1319 _D("subsystem : %s, path : %s", subsystem, path);
1320 DD_LIST_APPEND(*list, (void*)path);
1326 static int changed_device(int argc, char **argv)
1332 for (i = 0 ; i < argc ; i++) {
1333 if (argv[i] == NULL) {
1334 _E("param is failed");
1340 if (argv[1] == NULL)
1343 val = atoi(argv[1]);
1347 if (strncmp(argv[0], USB_NAME, USB_NAME_LEN) == 0)
1348 usb_chgdet_cb((void *)state);
1349 else if (strncmp(argv[0], EARJACK_NAME, EARJACK_NAME_LEN) == 0)
1350 earjack_chgdet_cb((void *)state);
1351 else if (strncmp(argv[0], EARKEY_NAME, EARKEY_NAME_LEN) == 0)
1352 earkey_chgdet_cb((void *)state);
1353 else if (strncmp(argv[0], TVOUT_NAME, TVOUT_NAME_LEN) == 0)
1354 tvout_chgdet_cb((void *)state);
1355 else if (strncmp(argv[0], HDMI_NAME, HDMI_NAME_LEN) == 0)
1356 hdmi_chgdet_cb((void *)state);
1357 else if (strncmp(argv[0], HDCP_NAME, HDCP_NAME_LEN) == 0) {
1358 hdcp_chgdet_cb((void *)state);
1359 hdcp_hdmi_cb((void *)state);
1361 else if (strncmp(argv[0], HDMI_AUDIO_NAME, HDMI_AUDIO_LEN) == 0)
1362 hdmi_audio_chgdet_cb((void *)state);
1363 else if (strncmp(argv[0], CRADLE_NAME, CRADLE_NAME_LEN) == 0)
1364 cradle_chgdet_cb((void *)state);
1365 else if (strncmp(argv[0], KEYBOARD_NAME, KEYBOARD_NAME_LEN) == 0)
1366 keyboard_chgdet_cb((void *)state);
1367 else if (strncmp(argv[0], POWER_SUBSYSTEM, POWER_SUPPLY_NAME_LEN) == 0)
1368 power_supply((void *)state);
1373 static int changed_dev_earjack(int argc, char **argv)
1378 * if we can recognize which type of jack is changed,
1379 * should move following code for TVOUT to a new action function */
1381 if(device_get_property(DEVTYPE_JACK,JACK_PROP_TVOUT_ONLINE,&val) == 0)
1384 vconf_get_int(VCONFKEY_SETAPPL_TVOUT_TVSYSTEM_INT, &val) == 0) {
1385 _E("Start TV out %s\n", (val==0)?"NTSC":(val==1)?"PAL":"Unsupported");
1388 launch_after_kill_if_exist(TVOUT_X_BIN, "-connect 2");
1391 launch_after_kill_if_exist(TVOUT_X_BIN, "-connect 3");
1394 _E("Unsupported TV system type:%d \n", val);
1398 launch_evenif_exist(TVOUT_X_BIN, "-clone 1");
1399 ss_flags |= TVOUT_FLAG;
1400 return vconf_set_int(VCONFKEY_SYSMAN_EARJACK, VCONFKEY_SYSMAN_EARJACK_TVOUT);
1404 _E("TV type is not set. Please set the TV type first.\n");
1407 if (ss_flags & TVOUT_FLAG) {
1408 _E("TV out Jack is disconnected.\n");
1410 launch_after_kill_if_exist(TVOUT_X_BIN, "-clone 0");
1411 ss_flags &= ~TVOUT_FLAG;
1412 return vconf_set_int(VCONFKEY_SYSMAN_EARJACK, VCONFKEY_SYSMAN_EARJACK_REMOVED);
1414 // Current event is not TV out event. Fall through
1418 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_EARJACK_ONLINE, &val) == 0) {
1420 extcon_set_count(EXTCON_EARJACK);
1421 return vconf_set_int(VCONFKEY_SYSMAN_EARJACK, val);
1427 static DBusMessage *dbus_cradle_handler(E_DBus_Object *obj, DBusMessage *msg)
1429 DBusMessageIter iter;
1433 ret = cradle_cb(NULL);
1434 _I("cradle %d", ret);
1436 reply = dbus_message_new_method_return(msg);
1437 dbus_message_iter_init_append(reply, &iter);
1438 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
1442 static DBusMessage *dbus_hdcp_hdmi_handler(E_DBus_Object *obj, DBusMessage *msg)
1444 DBusMessageIter iter;
1448 ret = hdcp_hdmi_cb(NULL);
1451 reply = dbus_message_new_method_return(msg);
1452 dbus_message_iter_init_append(reply, &iter);
1453 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
1457 static DBusMessage *dbus_hdcp_handler(E_DBus_Object *obj, DBusMessage *msg)
1459 DBusMessageIter iter;
1463 ret = hdcp_chgdet_cb(NULL);
1466 reply = dbus_message_new_method_return(msg);
1467 dbus_message_iter_init_append(reply, &iter);
1468 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
1472 static DBusMessage *dbus_hdmi_audio_handler(E_DBus_Object *obj, DBusMessage *msg)
1474 DBusMessageIter iter;
1478 ret = hdmi_audio_chgdet_cb(NULL);
1479 _I("hdmi audio %d", ret);
1481 reply = dbus_message_new_method_return(msg);
1482 dbus_message_iter_init_append(reply, &iter);
1483 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
1487 static DBusMessage *dbus_device_handler(E_DBus_Object *obj, DBusMessage *msg)
1490 DBusMessageIter iter;
1498 dbus_error_init(&err);
1500 if (!dbus_message_get_args(msg, &err,
1501 DBUS_TYPE_STRING, &type_str,
1502 DBUS_TYPE_INT32, &argc,
1503 DBUS_TYPE_STRING, &argv[0],
1504 DBUS_TYPE_STRING, &argv[1], DBUS_TYPE_INVALID)) {
1505 _E("there is no message");
1511 _E("message is invalid!");
1516 pid = get_edbus_sender_pid(msg);
1517 if (kill(pid, 0) == -1) {
1518 _E("%d process does not exist, dbus ignored!", pid);
1523 changed_device(argc, (char **)&argv);
1526 reply = dbus_message_new_method_return(msg);
1527 dbus_message_iter_init_append(reply, &iter);
1528 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
1533 static DBusMessage *dbus_battery_handler(E_DBus_Object *obj, DBusMessage *msg)
1536 DBusMessageIter iter;
1544 dbus_error_init(&err);
1546 if (!dbus_message_get_args(msg, &err,
1547 DBUS_TYPE_STRING, &type_str,
1548 DBUS_TYPE_INT32, &argc,
1549 DBUS_TYPE_STRING, &argv[0],
1550 DBUS_TYPE_STRING, &argv[1],
1551 DBUS_TYPE_STRING, &argv[2],
1552 DBUS_TYPE_STRING, &argv[3],
1553 DBUS_TYPE_STRING, &argv[4], DBUS_TYPE_INVALID)) {
1554 _E("there is no message");
1560 _E("message is invalid!");
1565 pid = get_edbus_sender_pid(msg);
1566 if (kill(pid, 0) == -1) {
1567 _E("%d process does not exist, dbus ignored!", pid);
1571 check_capacity_status(argv[0]);
1572 check_charge_status(argv[1]);
1573 check_health_status(argv[2]);
1574 check_online_status(argv[3]);
1575 check_present_status(argv[4]);
1576 _I("%d %d %d %d %d %d %d %d",
1578 battery.charge_full,
1585 battery_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_ON);
1586 notify_action(PREDEF_DEVICE_CHANGED, 2, POWER_SUBSYSTEM, argv[0]);
1588 reply = dbus_message_new_method_return(msg);
1589 dbus_message_iter_init_append(reply, &iter);
1590 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
1595 static DBusMessage *dbus_udev_handler(E_DBus_Object *obj, DBusMessage *msg)
1598 DBusMessageIter iter;
1606 dbus_error_init(&err);
1608 if (!dbus_message_get_args(msg, &err,
1609 DBUS_TYPE_STRING, &type_str,
1610 DBUS_TYPE_INT32, &argc,
1611 DBUS_TYPE_STRING, &argv, DBUS_TYPE_INVALID)) {
1612 _E("there is no message");
1618 _E("message is invalid!");
1623 pid = get_edbus_sender_pid(msg);
1624 if (kill(pid, 0) == -1) {
1625 _E("%d process does not exist, dbus ignored!", pid);
1630 if (strncmp(argv, "start", strlen("start")) == 0) {
1631 uevent_kernel_control_start();
1632 uevent_udev_control_start();
1633 } else if (strncmp(argv, "stop", strlen("stop")) == 0) {
1634 uevent_kernel_control_stop();
1635 uevent_udev_control_stop();
1639 reply = dbus_message_new_method_return(msg);
1640 dbus_message_iter_init_append(reply, &iter);
1641 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
1646 static const struct edbus_method edbus_methods[] = {
1647 { PREDEF_DEVICE_CHANGED,"siss", "i", dbus_device_handler },
1648 { PREDEF_POWER_CHANGED, "sisssss", "i", dbus_battery_handler },
1649 { PREDEF_UDEV_CONTROL, "sis", "i", dbus_udev_handler },
1650 { METHOD_GET_HDCP, NULL, "i", dbus_hdcp_handler },
1651 { METHOD_GET_HDMI_AUDIO,NULL, "i", dbus_hdmi_audio_handler },
1652 { METHOD_GET_HDMI, NULL, "i", dbus_hdcp_hdmi_handler },
1653 { METHOD_GET_CRADLE, NULL, "i", dbus_cradle_handler },
1656 static int booting_done(void *data)
1658 static int done = 0;
1670 register_action(PREDEF_EARJACKCON, changed_dev_earjack, NULL, NULL);
1671 register_action(PREDEF_DEVICE_CHANGED, changed_device, NULL, NULL);
1673 power_supply_timer_stop();
1674 power_supply_init(NULL);
1676 if (uevent_kernel_control_start() != 0) {
1677 _E("fail uevent control init");
1681 if (uevent_udev_control_start() != 0) {
1682 _E("fail uevent control init");
1686 /* set initial state for devices */
1687 input_device_number = 0;
1688 cradle_chgdet_cb(NULL);
1689 keyboard_chgdet_cb(NULL);
1690 hdmi_chgdet_cb(NULL);
1692 ret = vconf_get_int(VCONFKEY_SYSMAN_CRADLE_STATUS, &val);
1693 if (ret == 0 && val != 0)
1698 static int device_change_poweroff(void *data)
1700 uevent_kernel_control_stop();
1701 uevent_udev_control_stop();
1705 static void device_change_init(void *data)
1709 power_supply_timer_start();
1710 if (extcon_count_init() != 0)
1711 _E("fail to init extcon files");
1712 register_notifier(DEVICE_NOTIFIER_POWEROFF, device_change_poweroff);
1713 register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
1714 register_notifier(DEVICE_NOTIFIER_LCD, display_changed);
1715 ret = register_edbus_method(DEVICED_PATH_SYSNOTI, edbus_methods, ARRAY_SIZE(edbus_methods));
1717 _E("fail to init edbus method(%d)", ret);
1719 /* for simple noti change cb */
1720 emulator_add_callback("device_usb_chgdet", (void *)usb_chgdet_cb, NULL);
1721 emulator_add_callback("device_ta_chgdet", (void *)ta_chgdet_cb, data);
1722 emulator_add_callback("device_earjack_chgdet", (void *)earjack_chgdet_cb, data);
1723 emulator_add_callback("device_earkey_chgdet", (void *)earkey_chgdet_cb, data);
1724 emulator_add_callback("device_tvout_chgdet", (void *)tvout_chgdet_cb, data);
1725 emulator_add_callback("device_hdmi_chgdet", (void *)hdmi_chgdet_cb, data);
1726 emulator_add_callback("device_cradle_chgdet", (void *)cradle_chgdet_cb, data);
1727 emulator_add_callback("device_keyboard_chgdet", (void *)keyboard_chgdet_cb, data);
1729 emulator_add_callback("unmount_ums", (void *)ums_unmount_cb, NULL);
1731 /* check and set earjack init status */
1732 changed_dev_earjack(0, NULL);
1733 /* dbus noti change cb */
1734 #ifdef ENABLE_EDBUS_USE
1736 conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
1738 _E("check system dbus running!\n");
1740 e_dbus_signal_handler_add(conn, NULL, "/system/uevent/xxxxx",
1741 "system.uevent.xxxxx",
1742 "Change", cb_xxxxx_signaled, data);
1743 #endif /* ENABLE_EDBUS_USE */
1746 static void device_change_exit(void *data)
1749 unregister_notifier(DEVICE_NOTIFIER_POWEROFF, device_change_poweroff);
1750 unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
1751 unregister_notifier(DEVICE_NOTIFIER_LCD, display_changed);
1752 for (i = 0; i < ARRAY_SIZE(extcon_devices); i++) {
1753 if (extcon_devices[i].fd <= 0)
1755 close(extcon_devices[i].fd);
1760 static const struct device_ops change_device_ops = {
1761 .priority = DEVICE_PRIORITY_NORMAL,
1762 .name = "device change",
1763 .init = device_change_init,
1764 .exit = device_change_exit,
1767 DEVICE_OPS_REGISTER(&change_device_ops)