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>
20 #include <dbus/dbus-glib.h>
21 #include <dbus/dbus-glib-lowlevel.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
29 #include "mobileap_softap.h"
30 #include "mobileap_common.h"
31 #include "mobileap_usb.h"
33 static DBusGMethodInvocation *g_context = NULL;
34 static gboolean in_progress = FALSE;
35 static GDBusConnection *conn = NULL;
36 static guint subscription_id = 0;
37 static int usb_client_state = 0;
39 #define USB_SYSTEM_DEVICE_PATH "/Org/Tizen/System/DeviceD/Usb"
40 #define USB_SYSTEM_DEVICE_IFACE "org.tizen.system.deviced.Usb"
41 #define USB_STATE_CHANGE_SIGNAL "StateChanged"
43 enum usbclient_state {
44 USBCLIENT_STATE_DISCONNECTED = 0x00, /* usb cable is detached */
45 USBCLIENT_STATE_CONNECTED = 0x01, /* usb cable is attached */
46 /* usb cable is attached and available (ready to use) */
47 USBCLIENT_STATE_AVAILABLE = 0x02,
50 /* GDbus Signal Handler for USB Device State Changes */
51 static void __usb_device_state_change_cb(GDBusConnection *connection,
52 const gchar *sender_name, const gchar *object_path,
53 const gchar *interface_name, const gchar *signal_name,
54 GVariant *parameters, gpointer user_data)
56 unsigned int value = 0;
57 TetheringObject *obj = (TetheringObject *)user_data;
59 if (NULL == parameters || NULL == obj) {
60 ERR("Paramters Invalid \n");
64 if (strcmp(object_path, USB_SYSTEM_DEVICE_PATH) ||
65 strcmp(interface_name, USB_SYSTEM_DEVICE_IFACE) ||
66 strcmp(signal_name, USB_STATE_CHANGE_SIGNAL)) {
67 ERR("Unknown DBUS Signal\n");
70 g_variant_get(parameters, "(u)", &value);
71 DBG("Received signal(%s), value: (%u)", signal_name, value);
72 DBG("USB connected ? (%s)", value & USBCLIENT_STATE_CONNECTED? "Yes":"No");
73 DBG("USB available ? (%s)", value & USBCLIENT_STATE_AVAILABLE? "Yes":"No");
75 if (USBCLIENT_STATE_DISCONNECTED == value) {
76 _disable_usb_tethering(obj);
79 dbus_g_method_return(g_context, MOBILE_AP_ENABLE_USB_TETHERING_CFM,
80 MOBILE_AP_ERROR_RESOURCE);
83 _emit_mobileap_dbus_signal(obj, E_SIGNAL_USB_TETHER_OFF,
84 SIGNAL_MSG_NOT_AVAIL_INTERFACE);
88 usb_client_state = value;
91 int _dbus_register_usb_state_change_signal(void *data)
93 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
96 #if !GLIB_CHECK_VERSION(2,36,0)
100 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
102 ERR("Error occurred (%s)", error->message);
104 ret = MOBILE_AP_ERROR_RESOURCE;
108 ERR("Failed to get gdbus connection");
109 ret = MOBILE_AP_ERROR_RESOURCE;
113 subscription_id = g_dbus_connection_signal_subscribe(
114 conn, NULL, USB_SYSTEM_DEVICE_IFACE,
115 USB_STATE_CHANGE_SIGNAL, USB_SYSTEM_DEVICE_PATH, NULL,
116 G_DBUS_SIGNAL_FLAGS_NONE, __usb_device_state_change_cb,
119 if (subscription_id == 0) {
120 ERR("Failed to subscribe signal (%d)", USB_STATE_CHANGE_SIGNAL);
121 ret = MOBILE_AP_ERROR_RESOURCE;
125 usb_client_state = -1;
126 DBG("Successfully Subscribed USB State Signal Handler");
131 g_object_unref(conn);
135 static void __handle_usb_disconnect_cb(keynode_t *key, void *data)
137 if (key == NULL || data == NULL) {
138 ERR("Parameter is NULL\n");
144 TetheringObject *obj = (TetheringObject *)data;
146 if (!_mobileap_is_enabled(MOBILE_AP_STATE_USB)) {
147 ERR("USB tethering is not enabled\n");
151 if (vconf_keynode_get_type(key) != VCONF_TYPE_INT) {
152 ERR("Invalid vconf key type\n");
156 vconf_name = vconf_keynode_get_name(key);
157 vconf_key = vconf_keynode_get_int(key);
158 SDBG("key = %s, value = %d(int)\n", vconf_name, vconf_key);
161 * P140305-02551: Disconnected State is implemented from DBUS instead of
164 if (usb_client_state == USBCLIENT_STATE_DISCONNECTED)
165 DBG("USB is disconnected\n");
166 else if (vconf_name && !strcmp(vconf_name, VCONFKEY_SETAPPL_USB_MODE_INT) &&
167 vconf_key != SETTING_USB_TETHERING_MODE)
168 SDBG("USB Mode is changed [%d]\n", vconf_key);
172 _disable_usb_tethering(obj);
175 dbus_g_method_return(g_context,
176 MOBILE_AP_ENABLE_USB_TETHERING_CFM,
177 MOBILE_AP_ERROR_RESOURCE);
180 _emit_mobileap_dbus_signal(obj, E_SIGNAL_USB_TETHER_OFF,
181 SIGNAL_MSG_NOT_AVAIL_INTERFACE);
187 static void __handle_usb_mode_change(keynode_t *key, void *data)
189 if (key == NULL || data == NULL) {
190 ERR("Parameter is NULL\n");
194 TetheringObject *obj = (TetheringObject *)data;
199 if (vconf_keynode_get_type(key) != VCONF_TYPE_INT) {
200 ERR("Invalid vconf key\n");
204 vconf_key = vconf_keynode_get_int(key);
205 SDBG("key = %s, value = %d(int)\n",
206 vconf_keynode_get_name(key), vconf_key);
208 if (_mobileap_is_enabled(MOBILE_AP_STATE_USB)) {
209 if (vconf_key != SETTING_USB_TETHERING_MODE) {
210 DBG("Is progressing for usb mode change\n");
214 DBG("USB tethering is enabled\n");
215 vconf_ignore_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
216 __handle_usb_mode_change);
218 /* USB Mode change is handled while USB tethering is enabled */
219 vconf_notify_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
220 __handle_usb_disconnect_cb, (void *)obj);
221 ret = vconf_get_int(VCONFKEY_SETAPPL_USB_MODE_INT, &vconf_key);
223 ERR("vconf_get_int is failed. but ignored [%d]\n", ret);
226 if (vconf_key != SETTING_USB_TETHERING_MODE) {
227 ERR("USB Mode is changed suddenly\n");
228 _disable_usb_tethering(obj);
230 dbus_g_method_return(g_context,
231 MOBILE_AP_ENABLE_USB_TETHERING_CFM,
232 MOBILE_AP_ERROR_RESOURCE);
237 _add_interface_routing(USB_IF, IP_ADDRESS_USB);
238 _add_routing_rule(USB_IF);
240 _emit_mobileap_dbus_signal(obj, E_SIGNAL_USB_TETHER_ON, NULL);
242 dbus_g_method_return(g_context,
243 MOBILE_AP_ENABLE_USB_TETHERING_CFM,
244 MOBILE_AP_ERROR_NONE);
248 if (vconf_key == SETTING_USB_TETHERING_MODE) {
249 DBG("Is progressing for usb mode change\n");
253 DBG("USB tethering is disabled\n");
254 vconf_ignore_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
255 __handle_usb_mode_change);
256 _emit_mobileap_dbus_signal(obj, E_SIGNAL_USB_TETHER_OFF, NULL);
258 dbus_g_method_return(g_context,
259 MOBILE_AP_DISABLE_USB_TETHERING_CFM,
260 MOBILE_AP_ERROR_NONE);
265 idle_id = g_idle_add(_terminate_mobileap_agent, NULL);
267 ERR("g_idle_add is failed\n");
271 mobile_ap_error_code_e _enable_usb_tethering(TetheringObject *obj)
273 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
275 int usb_mode = SETTING_USB_NONE_MODE;
277 if (_mobileap_is_enabled(MOBILE_AP_STATE_USB)) {
278 ERR("USB tethering is already enabled\n");
279 ret = MOBILE_AP_ERROR_ALREADY_ENABLED;
283 if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
284 ERR("Wi-Fi AP is enabled\n");
285 ret = MOBILE_AP_ERROR_RESOURCE;
289 /* Register DBus Signal Handler for USB Client State */
290 if (_dbus_register_usb_state_change_signal(obj) != MOBILE_AP_ERROR_NONE) {
291 ERR("Failed to register dbus signal(%d)", ret);
292 ret = MOBILE_AP_ERROR_RESOURCE;
296 if (!_mobileap_set_state(MOBILE_AP_STATE_USB)) {
297 ret = MOBILE_AP_ERROR_RESOURCE;
301 ret = _init_tethering(obj);
302 if (ret != MOBILE_AP_ERROR_NONE) {
306 vconf_notify_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
307 __handle_usb_mode_change, (void *)obj);
309 vconf_ret = vconf_get_int(VCONFKEY_SETAPPL_USB_MODE_INT, &usb_mode);
310 if (vconf_ret != 0) {
311 ERR("Error getting vconf\n");
312 vconf_ignore_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
313 __handle_usb_mode_change);
314 _deinit_tethering(obj);
315 ret = MOBILE_AP_ERROR_RESOURCE;
319 if (usb_mode == SETTING_USB_TETHERING_MODE) {
320 vconf_ignore_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
321 __handle_usb_mode_change);
322 _add_interface_routing(USB_IF, IP_ADDRESS_USB);
323 _add_routing_rule(USB_IF);
327 return MOBILE_AP_ERROR_NONE;
330 /* Clear DBus Signal Handler for USB Client State */
332 if (subscription_id > 0) {
333 g_dbus_connection_signal_unsubscribe(conn, subscription_id);
336 g_object_unref(conn);
339 _mobileap_clear_state(MOBILE_AP_STATE_USB);
344 mobile_ap_error_code_e _disable_usb_tethering(TetheringObject *obj)
346 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
348 if (!_mobileap_is_enabled(MOBILE_AP_STATE_USB)) {
349 ERR("USB tethering has not been enabled\n");
350 ret = MOBILE_AP_ERROR_NOT_ENABLED;
354 _deinit_tethering(obj);
356 if (_remove_station_info_all(MOBILE_AP_TYPE_USB) != MOBILE_AP_ERROR_NONE) {
357 ERR("_remove_station_info_all is failed. Ignore it\n");
360 /* Clear DBus Signal Handler for USB Client State */
362 if (subscription_id > 0) {
363 g_dbus_connection_signal_unsubscribe(conn, subscription_id);
366 g_object_unref(conn);
370 vconf_ignore_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
371 __handle_usb_disconnect_cb);
373 _mobileap_clear_state(MOBILE_AP_STATE_USB);
374 _del_routing_rule(USB_IF);
375 _del_interface_routing(USB_IF, IP_ADDRESS_USB);
377 DBG("_disable_usb_tethering is done\n");
382 gboolean tethering_enable_usb_tethering(TetheringObject *obj,
383 DBusGMethodInvocation *context)
385 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
386 gboolean ret_val = FALSE;
390 g_assert(obj != NULL);
391 g_assert(context != NULL);
394 DBG("It is turnning on\n");
395 dbus_g_method_return(context,
396 MOBILE_AP_ENABLE_USB_TETHERING_CFM,
397 MOBILE_AP_ERROR_IN_PROGRESS);
403 ret = _enable_usb_tethering(obj);
404 if (ret != MOBILE_AP_ERROR_NONE) {
405 ERR("_enable_usb_tethering() is failed : %d\n", ret);
408 DBG("Don't need to wait for usb-setting\n");
409 _emit_mobileap_dbus_signal(obj, E_SIGNAL_USB_TETHER_ON, NULL);
414 dbus_g_method_return(g_context,
415 MOBILE_AP_ENABLE_USB_TETHERING_CFM, ret);
421 gboolean tethering_disable_usb_tethering(TetheringObject *obj,
422 DBusGMethodInvocation *context)
424 mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
425 int usb_mode = SETTING_USB_NONE_MODE;
430 g_assert(obj != NULL);
431 g_assert(context != NULL);
434 DBG("It is turnning on\n");
435 dbus_g_method_return(context,
436 MOBILE_AP_DISABLE_USB_TETHERING_CFM,
437 MOBILE_AP_ERROR_IN_PROGRESS);
443 ret = _disable_usb_tethering(obj);
444 if (ret != MOBILE_AP_ERROR_NONE) {
445 dbus_g_method_return(g_context,
446 MOBILE_AP_DISABLE_USB_TETHERING_CFM, ret);
451 vconf_notify_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
452 __handle_usb_mode_change, (void *)obj);
453 vconf_ret = vconf_get_int(VCONFKEY_SETAPPL_USB_MODE_INT, &usb_mode);
454 if (vconf_ret != 0) {
455 ERR("Error getting vconf : %d. This error is ignored\n", vconf_ret);
459 if (usb_mode != SETTING_USB_TETHERING_MODE) {
460 DBG("Don't need to wait for usb-setting\n");
470 vconf_ignore_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
471 __handle_usb_mode_change);
472 _emit_mobileap_dbus_signal(obj, E_SIGNAL_USB_TETHER_OFF, NULL);
473 dbus_g_method_return(g_context,
474 MOBILE_AP_DISABLE_USB_TETHERING_CFM, ret);
480 gboolean _is_trying_usb_operation(void)
482 return (g_context ? TRUE : FALSE || in_progress);