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.
20 #include "usb-client.h"
21 #include "core/device-handler.h"
22 #include "core/edbus-handler.h"
24 #define USB_POPUP_NAME "usb-syspopup"
32 static bool client_mode = false;
33 static char *driver_version = NULL;
34 static bool wait_configured = false;
36 void launch_syspopup(char *str)
38 struct popup_data params;
39 static const struct device_ops *apps = NULL;
41 FIND_DEVICE_VOID(apps, "apps");
42 params.name = USB_POPUP_NAME;
43 params.key = POPUP_KEY_CONTENT;
50 bool get_wait_configured(void)
52 return wait_configured;
55 int get_debug_mode(void)
58 if (vconf_get_bool(VCONFKEY_SETAPPL_USB_DEBUG_MODE_BOOL, &debug) != 0)
59 return 1; /* 0 means debug mode is on */
64 int get_default_mode(void)
66 if (get_debug_mode() == 0)
67 return SET_USB_DEFAULT;
72 int update_usb_state(int state)
76 ret = vconf_set_int(VCONFKEY_SYSMAN_USB_STATUS, state);
78 send_msg_usb_state_changed();
83 int update_current_usb_mode(int mode)
85 /*************************************************/
86 /* TODO: This legacy vconf key should be removed */
87 /* The legacy vconf key is used by mtp and OSP */
93 case SET_USB_SDB_DIAG:
94 legacy = SETTING_USB_SAMSUNG_KIES;
97 case SET_USB_RNDIS_DIAG:
98 case SET_USB_RNDIS_SDB:
99 legacy = SETTING_USB_DEBUG_MODE;
101 case SET_USB_RNDIS_TETHERING:
102 legacy = SETTING_USB_TETHERING_MODE;
106 legacy = SETTING_USB_NONE_MODE;
110 if (vconf_set_int(VCONFKEY_SETAPPL_USB_MODE_INT, legacy) != 0)
111 _E("Failed to set legacy vconf key for current usb mode");
112 /****************************************************/
114 ret = vconf_set_int(VCONFKEY_USB_CUR_MODE, mode);
116 send_msg_usb_mode_changed();
117 send_msg_usb_state_changed();
122 int get_current_usb_logical_state(void)
126 if (vconf_get_int(VCONFKEY_SYSMAN_USB_STATUS, &value) != 0)
132 int get_current_usb_physical_state(void)
136 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_USB_ONLINE, &state) != 0
137 || (state != 0 && state != 1))
138 state = get_usb_state_direct();
143 int get_current_usb_mode(void)
148 ret = vconf_get_int(VCONFKEY_USB_CUR_MODE, &mode);
155 int get_selected_usb_mode(void)
160 ret = vconf_get_int(VCONFKEY_USB_SEL_MODE, &mode);
167 int change_selected_usb_mode(int mode)
169 if (mode <= SET_USB_NONE)
171 return vconf_set_int(VCONFKEY_USB_SEL_MODE, mode);
174 static void reconfigure_boot_usb_mode(void)
178 prev = get_selected_usb_mode();
182 case SET_USB_RNDIS_TETHERING:
183 now = SET_USB_DEFAULT;
185 case SET_USB_RNDIS_DIAG:
186 now = SET_USB_SDB_DIAG;
188 case SET_USB_RNDIS_SDB:
195 if (change_selected_usb_mode(now) != 0)
196 _E("Failed to set selected usb mode");
199 static int notify_vconf_keys(void)
203 ret = vconf_notify_key_changed(
204 VCONFKEY_USB_SEL_MODE,
205 client_mode_changed, NULL);
207 _E("FAIL: vconf_notify_key_changed()");
211 ret = vconf_notify_key_changed(
212 VCONFKEY_SETAPPL_USB_DEBUG_MODE_BOOL,
213 debug_mode_changed, NULL);
215 _E("FAIL: vconf_notify_key_changed()");
217 ret = vconf_notify_key_changed(
218 VCONFKEY_MOBILE_HOTSPOT_MODE,
219 tethering_status_changed, NULL);
221 _E("FAIL: vconf_notify_key_changed()");
226 static int ignore_vconf_keys(void)
230 ret = vconf_ignore_key_changed(
231 VCONFKEY_USB_SEL_MODE,
232 client_mode_changed);
234 _E("FAIL: vconf_ignore_key_changed()");
238 ret = vconf_ignore_key_changed(
239 VCONFKEY_SETAPPL_USB_DEBUG_MODE_BOOL,
242 _E("FAIL: vconf_ignore_key_changed()");
244 ret = vconf_ignore_key_changed(
245 VCONFKEY_MOBILE_HOTSPOT_MODE,
246 tethering_status_changed);
248 _E("FAIL: vconf_ignore_key_changed()");
254 static int register_client_handlers(void)
258 ret = notify_vconf_keys();
262 /* TODO: register other handler (ex. dbus, ... ) */
267 static int unregister_client_handlers(void)
271 ret = ignore_vconf_keys();
275 /* TODO: unregister other handler (ex. dbus, ... ) */
280 static void deinit_client_values(void)
284 sel_mode = get_selected_usb_mode();
286 case SET_USB_RNDIS_TETHERING:
287 case SET_USB_RNDIS_DIAG:
288 if (change_selected_usb_mode(get_default_mode()) != 0)
289 _E("Failed to set selected usb mode");
296 static int init_client(void)
302 ret = register_client_handlers();
309 static int deinit_client(void)
315 ret = unregister_client_handlers();
317 _E("FAIL: unregister_client_handlers()");
319 deinit_client_values();
324 void act_usb_connected(void)
326 wait_configured = false;
328 if (vconf_set_int(VCONFKEY_USB_CONFIGURATION_ENABLED, USB_CONF_ENABLED) != 0)
329 _E("Failed to set vconf key (%s)", VCONFKEY_USB_CONFIGURATION_ENABLED);
331 if (init_client() < 0)
332 _E("FAIL: init_client()");
334 change_client_setting(SET_CONFIGURATION | SET_OPERATION | SET_NOTIFICATION);
336 pm_lock_internal(getpid(), LCD_OFF, STAY_CUR_STATE, 0);
339 static void act_usb_disconnected(void)
343 wait_configured = false;
345 if (vconf_set_int(VCONFKEY_USB_CONFIGURATION_ENABLED, USB_CONF_DISABLED) != 0)
346 _E("Failed to set vconf key (%s)", VCONFKEY_USB_CONFIGURATION_ENABLED);
348 pm_unlock_internal(getpid(), LCD_OFF, STAY_CUR_STATE);
350 cur_mode = get_current_usb_mode();
351 if (cur_mode > SET_USB_NONE)
352 unset_client_mode(cur_mode, false);
354 if (deinit_client() < 0)
355 _E("FAIL: deinit_client()");
357 if (update_usb_state(VCONFKEY_SYSMAN_USB_DISCONNECTED) < 0)
358 _E("FAIL: update_usb_state(%d)", VCONFKEY_SYSMAN_USB_DISCONNECTED);
361 static void subsystem_switch_changed (struct udev_device *dev)
363 const char *name = NULL;
364 const char *state = NULL;
368 name = udev_device_get_property_value(dev, UDEV_PROP_KEY_SWITCH_NAME);
372 if (strncmp(name, UDEV_PROP_VALUE_USB_CABLE, strlen(UDEV_PROP_VALUE_USB_CABLE)))
375 state = udev_device_get_property_value(dev, UDEV_PROP_KEY_SWITCH_STATE);
379 /* USB cable disconnected */
380 if (!strncmp(state, UDEV_PROP_VALUE_DISCON, strlen(UDEV_PROP_VALUE_DISCON))) {
381 _I("USB cable is disconnected");
382 act_usb_disconnected();
386 /* USB cable connected */
387 if (!strncmp(state, UDEV_PROP_VALUE_CON, strlen(UDEV_PROP_VALUE_CON))) {
388 _I("USB cable is connected");
394 static void subsystem_platform_changed (struct udev_device *dev)
396 const char *chgdet = NULL;
400 chgdet = udev_device_get_property_value(dev, UDEV_PROP_KEY_CHGDET);
404 if (strncmp(chgdet, UDEV_PROP_VALUE_USB, strlen(UDEV_PROP_VALUE_USB)))
407 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_USB_ONLINE, &state) != 0
408 || (state != 0 && state != 1)) {
409 _E("cannot get the usb cable connection status");
410 state = get_usb_state_direct();
413 /* USB cable disconnected */
415 _I("USB cable is disconnected");
416 act_usb_disconnected();
420 /* USB cable connected */
422 _I("USB cable is connected");
427 _E("USB state is unknown(%d)", state);
430 static void subsystem_usbmode_changed (struct udev_device *dev)
432 const char *state = NULL;
434 if (!wait_configured)
437 wait_configured = false;
439 state = udev_device_get_property_value(dev, UDEV_PROP_KEY_USB_STATE);
443 if (strncmp(state, UDEV_PROP_VALUE_CONFIGURED, strlen(state)))
446 _I("Real USB cable is connected");
447 change_client_setting(SET_OPERATION | SET_NOTIFICATION);
450 const static struct uevent_handler uhs[] = {
451 { SWITCH_SUBSYSTEM , subsystem_switch_changed , NULL },
452 { USBMODE_SUBSYSTEM , subsystem_usbmode_changed , NULL },
453 { PLATFORM_SUBSYSTEM , subsystem_platform_changed , NULL },
456 void usbclient_init_booting_done(void)
460 reconfigure_boot_usb_mode();
462 for (i = 0 ; i < ARRAY_SIZE(uhs) ; i++) {
463 ret = register_kernel_uevent_control(&uhs[i]);
465 _E("FAIL: reg_uevent_control()");
468 if (register_usb_client_change_request() < 0)
469 _E("Failed to register the request to change usb mode");
471 if (register_usbclient_dbus_methods() < 0)
472 _E("Failed to register dbus handler for usbclient");
475 static void usbclient_init(void *data)
477 wait_until_booting_done();
480 static void usbclient_exit(void *data)
484 for (i = 0 ; i < ARRAY_SIZE(uhs) ; i++) {
485 unregister_kernel_uevent_control(&uhs[i]);
489 static const struct device_ops usbclient_device_ops = {
490 .priority = DEVICE_PRIORITY_NORMAL,
492 .init = usbclient_init,
493 .exit = usbclient_exit,
494 .start = control_start,
495 .stop = control_stop,
496 .status = control_status,
499 DEVICE_OPS_REGISTER(&usbclient_device_ops)