3 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * Licensed under the Apache License, Version 2.0 (the License);
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 #include <dbus/dbus.h>
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
27 #include "mobileap_softap.h"
28 #include "mobileap_common.h"
29 #include "mobileap_usb.h"
31 static GDBusMethodInvocation *g_context = NULL;
32 static gboolean in_progress = FALSE;
33 static GDBusConnection *conn = NULL;
34 static guint subscription_id = 0;
35 static int usb_client_state = 0;
37 #define USB_SYSTEM_DEVICE_PATH "/Org/Tizen/System/DeviceD/Usb"
38 #define USB_SYSTEM_DEVICE_IFACE "org.tizen.system.deviced.Usb"
39 #define USB_STATE_CHANGE_SIGNAL "StateChanged"
41 enum usbclient_state {
42 USBCLIENT_STATE_DISCONNECTED = 0x00, /* usb cable is detached */
43 USBCLIENT_STATE_CONNECTED = 0x01, /* usb cable is attached */
44 /* usb cable is attached and available (ready to use) */
45 USBCLIENT_STATE_AVAILABLE = 0x02,
48 /* GDbus Signal Handler for USB Device State Changes */
49 static void __usb_device_state_change_cb(GDBusConnection *connection,
50 const gchar *sender_name, const gchar *object_path,
51 const gchar *interface_name, const gchar *signal_name,
52 GVariant *parameters, gpointer user_data)
54 unsigned int value = 0;
55 Tethering *obj = (Tethering *)user_data;
57 if (NULL == parameters || NULL == obj) {
58 ERR("Paramters Invalid \n");
62 if (strcmp(object_path, USB_SYSTEM_DEVICE_PATH) ||
63 strcmp(interface_name, USB_SYSTEM_DEVICE_IFACE) ||
64 strcmp(signal_name, USB_STATE_CHANGE_SIGNAL)) {
65 ERR("Unknown DBUS Signal\n");
68 g_variant_get(parameters, "(u)", &value);
69 DBG("Received signal(%s), value: (%u)", signal_name, value);
70 DBG("USB connected ? (%s)", value & USBCLIENT_STATE_CONNECTED? "Yes":"No");
71 DBG("USB available ? (%s)", value & USBCLIENT_STATE_AVAILABLE? "Yes":"No");
73 if (USBCLIENT_STATE_DISCONNECTED == value) {
74 _disable_usb_tethering(obj);
77 tethering_complete_enable_usb_tethering(obj, g_context, MOBILE_AP_ERROR_RESOURCE);
80 tethering_emit_usb_off(obj, SIGNAL_MSG_NOT_AVAIL_INTERFACE);
84 usb_client_state = value;
87 int _dbus_register_usb_state_change_signal(void *data)
89 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
92 #if !GLIB_CHECK_VERSION(2,36,0)
96 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
98 ERR("Error occurred (%s)", error->message);
100 ret = MOBILE_AP_ERROR_RESOURCE;
104 ERR("Failed to get gdbus connection");
105 ret = MOBILE_AP_ERROR_RESOURCE;
109 subscription_id = g_dbus_connection_signal_subscribe(
110 conn, NULL, USB_SYSTEM_DEVICE_IFACE,
111 USB_STATE_CHANGE_SIGNAL, USB_SYSTEM_DEVICE_PATH, NULL,
112 G_DBUS_SIGNAL_FLAGS_NONE, __usb_device_state_change_cb,
115 if (subscription_id == 0) {
116 ERR("Failed to subscribe signal (%d)", USB_STATE_CHANGE_SIGNAL);
117 ret = MOBILE_AP_ERROR_RESOURCE;
121 usb_client_state = -1;
122 DBG("Successfully Subscribed USB State Signal Handler");
127 g_object_unref(conn);
131 static void __handle_usb_disconnect_cb(keynode_t *key, void *data)
133 if (key == NULL || data == NULL) {
134 ERR("Parameter is NULL\n");
138 char *vconf_name = NULL;
140 Tethering *obj = (Tethering *)data;
142 if (!_mobileap_is_enabled(MOBILE_AP_STATE_USB)) {
143 ERR("USB tethering is not enabled\n");
147 if (vconf_keynode_get_type(key) != VCONF_TYPE_INT) {
148 ERR("Invalid vconf key type\n");
152 vconf_name = vconf_keynode_get_name(key);
153 if (vconf_name == NULL) {
154 ERR("vconf_keynode_get_name is failed\n");
157 vconf_key = vconf_keynode_get_int(key);
159 ERR("vconf_keynode_get_int is failed\n");
162 SDBG("key = %s, value = %d(int)\n", vconf_name, vconf_key);
165 * P140305-02551: Disconnected State is implemented from DBUS instead of
168 if (usb_client_state == USBCLIENT_STATE_DISCONNECTED)
169 DBG("USB is disconnected\n");
170 else if (vconf_name && !strcmp(vconf_name, VCONFKEY_SETAPPL_USB_MODE_INT) &&
171 vconf_key != SETTING_USB_TETHERING_MODE)
172 SDBG("USB Mode is changed [%d]\n", vconf_key);
176 _disable_usb_tethering(obj);
179 g_dbus_method_invocation_return_value(g_context,
180 g_variant_new("(uu)", MOBILE_AP_ENABLE_USB_TETHERING_CFM,
181 MOBILE_AP_ERROR_RESOURCE));
184 tethering_emit_usb_off(obj, SIGNAL_MSG_NOT_AVAIL_INTERFACE);
190 static void __handle_usb_mode_change(keynode_t *key, void *data)
192 if (key == NULL || data == NULL) {
193 ERR("Parameter is NULL\n");
197 Tethering *obj = (Tethering *)data;
202 if (vconf_keynode_get_type(key) != VCONF_TYPE_INT) {
203 ERR("Invalid vconf key\n");
207 vconf_key = vconf_keynode_get_int(key);
208 SDBG("key = %s, value = %d(int)\n",
209 vconf_keynode_get_name(key), vconf_key);
211 if (_mobileap_is_enabled(MOBILE_AP_STATE_USB)) {
212 if (vconf_key != SETTING_USB_TETHERING_MODE) {
213 DBG("Is progressing for usb mode change\n");
217 DBG("USB tethering is enabled\n");
218 vconf_ignore_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
219 __handle_usb_mode_change);
221 /* USB Mode change is handled while USB tethering is enabled */
222 vconf_notify_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
223 __handle_usb_disconnect_cb, (void *)obj);
224 ret = vconf_get_int(VCONFKEY_SETAPPL_USB_MODE_INT, &vconf_key);
226 ERR("vconf_get_int is failed. but ignored [%d]\n", ret);
229 if (vconf_key != SETTING_USB_TETHERING_MODE) {
230 ERR("USB Mode is changed suddenly\n");
231 _disable_usb_tethering(obj);
233 tethering_complete_enable_usb_tethering(obj, g_context, MOBILE_AP_ERROR_RESOURCE);
238 _add_interface_routing(USB_IF, IP_ADDRESS_USB);
239 _add_routing_rule(USB_IF);
240 tethering_emit_usb_on(obj);
241 _create_tethering_active_noti();
243 tethering_complete_enable_usb_tethering(obj, g_context, MOBILE_AP_ERROR_NONE);
247 if (vconf_key == SETTING_USB_TETHERING_MODE) {
248 DBG("Is progressing for usb mode change\n");
252 DBG("USB tethering is disabled\n");
253 vconf_ignore_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
254 __handle_usb_mode_change);
255 tethering_emit_usb_off(obj, NULL);
257 tethering_complete_disable_usb_tethering(obj, g_context, MOBILE_AP_DISABLE_USB_TETHERING_CFM, NULL);
262 idle_id = g_idle_add(_terminate_mobileap_agent, NULL);
264 ERR("g_idle_add is failed\n");
268 mobile_ap_error_code_e _enable_usb_tethering(Tethering *obj)
270 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
272 int usb_mode = SETTING_USB_NONE_MODE;
274 if (_mobileap_is_enabled(MOBILE_AP_STATE_USB)) {
275 ERR("USB tethering is already enabled\n");
276 ret = MOBILE_AP_ERROR_ALREADY_ENABLED;
280 if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
281 ERR("Wi-Fi AP is enabled\n");
282 ret = MOBILE_AP_ERROR_RESOURCE;
286 /* Register DBus Signal Handler for USB Client State */
287 if (_dbus_register_usb_state_change_signal(obj) != MOBILE_AP_ERROR_NONE) {
288 ERR("Failed to register dbus signal(%d)", ret);
289 ret = MOBILE_AP_ERROR_RESOURCE;
293 if (!_mobileap_set_state(MOBILE_AP_STATE_USB)) {
294 ret = MOBILE_AP_ERROR_RESOURCE;
298 ret = _init_tethering();
299 if (ret != MOBILE_AP_ERROR_NONE) {
303 vconf_notify_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
304 __handle_usb_mode_change, (void *)obj);
306 vconf_ret = vconf_get_int(VCONFKEY_SETAPPL_USB_MODE_INT, &usb_mode);
307 if (vconf_ret != 0) {
308 ERR("Error getting vconf\n");
309 vconf_ignore_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
310 __handle_usb_mode_change);
312 ret = MOBILE_AP_ERROR_RESOURCE;
316 if (usb_mode == SETTING_USB_TETHERING_MODE) {
317 vconf_ignore_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
318 __handle_usb_mode_change);
319 _add_interface_routing(USB_IF, IP_ADDRESS_USB);
320 _add_routing_rule(USB_IF);
324 return MOBILE_AP_ERROR_NONE;
327 /* Clear DBus Signal Handler for USB Client State */
329 if (subscription_id > 0) {
330 g_dbus_connection_signal_unsubscribe(conn, subscription_id);
333 g_object_unref(conn);
336 _mobileap_clear_state(MOBILE_AP_STATE_USB);
341 mobile_ap_error_code_e _disable_usb_tethering(Tethering *obj)
343 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
345 if (!_mobileap_is_enabled(MOBILE_AP_STATE_USB)) {
346 ERR("USB tethering has not been enabled\n");
347 ret = MOBILE_AP_ERROR_NOT_ENABLED;
353 if (_remove_station_info_all(MOBILE_AP_TYPE_USB) != MOBILE_AP_ERROR_NONE) {
354 ERR("_remove_station_info_all is failed. Ignore it\n");
357 /* Clear DBus Signal Handler for USB Client State */
359 if (subscription_id > 0) {
360 g_dbus_connection_signal_unsubscribe(conn, subscription_id);
363 g_object_unref(conn);
367 vconf_ignore_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
368 __handle_usb_disconnect_cb);
370 _mobileap_clear_state(MOBILE_AP_STATE_USB);
371 _del_routing_rule(USB_IF);
372 _del_interface_routing(USB_IF, IP_ADDRESS_USB);
374 DBG("_disable_usb_tethering is done\n");
379 gboolean tethering_enable_usb_tethering(Tethering *obj, GDBusMethodInvocation *context)
381 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
382 gboolean ret_val = FALSE;
386 g_assert(obj != NULL);
387 g_assert(context != NULL);
390 DBG("It is turnning on\n");
391 tethering_complete_enable_usb_tethering(obj, g_context, MOBILE_AP_ERROR_IN_PROGRESS);
397 ret = _enable_usb_tethering(obj);
398 if (ret != MOBILE_AP_ERROR_NONE) {
399 ERR("_enable_usb_tethering() is failed : %d\n", ret);
402 DBG("Don't need to wait for usb-setting\n");
403 tethering_emit_usb_on(obj);
404 _create_tethering_active_noti();
409 tethering_complete_enable_usb_tethering(obj, g_context, ret);
416 gboolean tethering_disable_usb_tethering(Tethering *obj,
417 GDBusMethodInvocation *context)
419 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
420 int usb_mode = SETTING_USB_NONE_MODE;
425 g_assert(obj != NULL);
426 g_assert(context != NULL);
429 DBG("It is turnning on\n");
430 tethering_complete_disable_usb_tethering(obj, context,
431 MOBILE_AP_DISABLE_USB_TETHERING_CFM,
432 MOBILE_AP_ERROR_IN_PROGRESS);
438 ret = _disable_usb_tethering(obj);
439 if (ret != MOBILE_AP_ERROR_NONE) {
440 tethering_complete_disable_usb_tethering(obj, g_context,
441 MOBILE_AP_DISABLE_USB_TETHERING_CFM, ret);
446 vconf_notify_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
447 __handle_usb_mode_change, (void *)obj);
448 vconf_ret = vconf_get_int(VCONFKEY_SETAPPL_USB_MODE_INT, &usb_mode);
449 if (vconf_ret != 0) {
450 ERR("Error getting vconf : %d. This error is ignored\n", vconf_ret);
454 if (usb_mode != SETTING_USB_TETHERING_MODE) {
455 DBG("Don't need to wait for usb-setting\n");
465 vconf_ignore_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
466 __handle_usb_mode_change);
467 tethering_emit_usb_off(obj, NULL);
468 tethering_complete_disable_usb_tethering(obj, g_context,
469 MOBILE_AP_DISABLE_USB_TETHERING_CFM, ret);
475 gboolean _is_trying_usb_operation(void)
477 return (g_context ? TRUE : FALSE || in_progress);