--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __TIZEN_NETWORK_TETHERING_EXT_H
+#define __TIZEN_NETWORK_TETHERING_EXT_H
+
+#include <tethering_ext_common.h>
+#include <tethering_ext_internal.h>
+
+#define RET_ERR_IF_HANDLE_IS_NOT_VALID_OR_NOT_INITIALIZED(arg) \
+ do { \
+ if (!arg) { \
+ LOGE("Tethering context is null"); \
+ return TETHERING_ERROR_INVALID_PARAMETER; \
+ } \
+ if (!_tethering_ext_check_context(arg)) { \
+ LOGE("Tethering context is not initialized"); \
+ return TETHERING_ERROR_INVALID_PARAMETER; \
+ } \
+ } while (0)
+
+
+int tethering_ext_initialize(tethering_ext_h *th_context);
+int tethering_ext_deinitialize(tethering_ext_h th_context);
+int tethering_ext_activate(tethering_ext_h th_context);
+int tethering_ext_deactivate(tethering_ext_h th_context);
+int tethering_ext_is_enabled(tethering_ext_h th_context, bool *is_enabled);
+int tethering_ext_set_configuration(tethering_ext_h th_context, tethering_ext_config_h *src_config, int config_flags);
+int tethering_ext_set_ssid(tethering_ext_h th_context, const char *ssid);
+int tethering_ext_set_passphrase(tethering_ext_h th_context, const char *passphrase);
+int tethering_ext_set_channel(tethering_ext_h th_context, int channel);
+int tethering_ext_get_tethering_info(tethering_ext_h th_context, void **tethering_info);
+int tethering_ext_get_channel(tethering_ext_h th_context, int *channel);
+int tethering_ext_get_security(tethering_ext_h th_context, int *security);
+int tethering_ext_get_visibility(tethering_ext_h th_context, int *visibility);
+int tethering_ext_get_sharing(tethering_ext_h th_context, bool *sharing);
+
+#endif /* __TIZEN_NETWORK_TETHERING_EXT_H */
--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TIZEN_NETWORK_TETHERING_EXT_COMMON_H
+#define __TIZEN_NETWORK_TETHERING_EXT_COMMON_H
+#include <tizen.h>
+#include <tethering.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TETHERING_EXT_WIFI_SSID_MAX_LEN 32
+#define TETHERING_EXT_WIFI_KEY_MAX_LEN 64
+#define TETHERING_EXT_IPV4_ADDRESS_MAX_LEN 15
+
+typedef void *tethering_ext_h;
+
+typedef enum {
+ TETHERING_EXT_SSID = 1,
+ TETHERING_EXT_PASSPHRASE = 2,
+ TETHERING_EXT_SECURITY_TYPE = 4,
+ TETHERING_EXT_CHANNEL = 8,
+ TETHERING_EXT_VISIBLE = 16,
+ TETHERING_EXT_SHARED = 32,
+ TETHERING_EXT_ALL = 63
+} tethering_ext_config_e;
+
+typedef struct {
+ char ssid[TETHERING_EXT_WIFI_SSID_MAX_LEN + 1];
+ char passphrase[TETHERING_EXT_WIFI_KEY_MAX_LEN + 1];
+ int security_type;
+ int mode_type;
+ bool visibility;
+ bool wifi_sharing;
+ int channel;
+ int wifi_max_connected;
+ char ipaddr[TETHERING_EXT_IPV4_ADDRESS_MAX_LEN + 1];
+} tethering_ext_config_h;
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __TIZEN_NETWORK_TETHERING_EXT_COMMON_H */
--- /dev/null
+/**
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __TIZEN_TETHERING_EXT_DBUS_H_
+#define __TIZEN_TETHERING_EXT_DBUS_H_
+
+#include <glib.h>
+
+#include <tethering_ext_internal.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* tethering-service */
+#define TETHERING_EXT_BUS_NAME "net.wifitethering"
+#define TETHERING_EXT_OBJECT_PATH "/net/wifitethering"
+#define TETHERING_EXT_INTERFACE_NAME TETHERING_EXT_BUS_NAME ".interface"
+
+#define TETHERING_EXT_METHOD_SET_MODE "SetWiFiTetheringMode"
+#define TETHERING_EXT_METHOD_SET_MODE_WITH_PARAMS "SetWiFiTetheringModeWithParams"
+#define TETHERING_EXT_METHOD_GET_MODE "GetWiFiTetheringMode"
+#define TETHERING_EXT_METHOD_GET_INFO "GetWiFiTetheringInfo"
+
+#define SIGNAL_TETHERING_EXT_MODE_CHANGED "WiFiTetheringModeChanged"
+#define SIGNAL_TETHERING_EXT_ENABLED "WiFiTetheringEnabled"
+#define SIGNAL_TETHERING_EXT_DISABLED "WiFiTetheringDisabled"
+#define SIGNAL_TETHERING_CONNECTION_CHANGED "WiFiTetheringConnectionChanged"
+
+/* ntc-service */
+#define NTC_BUS_NAME "net.ntc.service"
+#define NTC_DBUS_OBJECT_PATH "/net/ntc/service"
+#define NTC_DBUS_ITNERFACE_NAME "net.ntc.service.interface"
+
+/* Common */
+#define TETHERING_EXT_SIGNAL_NAME_LEN 64
+
+GVariant *_invoke_dbus_method(_tethering_ext_h *tethering_ctx, const char *dest, const char *path, const char *interface_name,
+ const char *method, GVariant *params, int *dbus_error);
+
+int _tethering_ext_dbus_set_wifi_tethering_mode(_tethering_ext_h *tethering_ctx, bool enable);
+int _tethering_ext_dbus_set_wifi_tethering_mode_with_params(_tethering_ext_h *tethering_ctx, bool enable);
+int _tethering_ext_dbus_get_wifi_tethering_state(_tethering_ext_h *tethering_ctx, _tethering_ext_state_e *tethering_state);
+int _tethering_ext_dbus_get_wifi_tethering_info(_tethering_ext_h *tethering_ctx, _tethering_ext_tethering_info *tethering_info);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TIZEN_TETHERING_EXT_DBUS_H_ */
+
--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __TIZEN_NETWORK_TETHERING_EXT_INTERNAL_H
+#define __TIZEN_NETWORK_TETHERING_EXT_INTERNAL_H
+#include <tethering_ext_common.h>
+#include <gio/gio.h>
+#include <dlog.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef API
+#define API __attribute__ ((visibility("default")))
+#endif
+
+#define TETHERING_EXT_STR_INFO_LEN 40
+
+typedef enum {
+ TETHERING_EXT_STATE_DISABLED = 0,
+ TETHERING_EXT_STATE_ENABLED = 1
+} _tethering_ext_state_e;
+
+typedef enum {
+ TETHERING_EXT_POWER_IND = 0
+} _tethering_ext_event_e;
+
+// Maps in value to tethering_disabled_cause_e
+typedef enum {
+ TETHERING_EXT_DISABLED_BY_FLIGHT_MODE = 1, /**< Disabled due to flight mode */
+ TETHERING_EXT_DISABLED_BY_LOW_BATTERY, /**< Disabled due to low battery */
+ TETHERING_EXT_DISABLED_BY_NETWORK_CLOSE, /**< Disabled due to pdp network close */
+ TETHERING_EXT_DISABLED_BY_TIMEOUT, /**< Disabled due to timeout */
+ TETHERING_EXT_DISABLED_BY_OTHERS, /**< Disabled by other apps */
+ TETHERING_EXT_DISABLED_BY_REQUEST, /**< Disabled by your request */
+ TETHERING_EXT_DISABLED_BY_WIFI_ON, /**< Disabled due to Wi-Fi on */
+} _tethering_ext_disabled_cause_e;
+
+typedef enum {
+ TETHERING_EXT_ERR_NONE = 0x00, /** No error */
+
+ /* Common Error value */
+ TETHERING_EXT_ERR_UNKNOWN = -999, /** Error unknown */
+
+ /* Client Register related Errors used in API return */
+ TETHERING_EXT_ERR_APP_ALREADY_REGISTERED = -990, /** Application is already registered */
+ TETHERING_EXT_ERR_APP_NOT_REGISTERED = -989, /** Application is not registered */
+
+ /* Other Error */
+ TETHERING_EXT_ERR_ACCESS_DENIED = -799, /** Access(permission) denied */
+ TETHERING_EXT_ERR_IN_PROGRESS = -798, /** Operation is in progress */
+ TETHERING_EXT_ERR_OPERATION_ABORTED = -797, /** Operation was aborted by client or network*/
+ TETHERING_EXT_ERR_INVALID_PARAM = -796, /** Invalid value of API parameter */
+ TETHERING_EXT_ERR_INVALID_OPERATION = -795, /** Invalid operation depending on current state */
+ TETHERING_EXT_ERR_NOT_SUPPORTED = -794, /** Feature not supported */
+ TETHERING_EXT_ERR_TIME_OUT = -793, /** TimeOut Error */
+ TETHERING_EXT_ERR_UNKNOWN_METHOD = -792, /** DBus can't find appropriate method */
+ TETHERING_EXT_ERR_ALREADY_EXISTS = -791, /** Already exists */
+ TETHERING_EXT_ERR_OUT_OF_MEMORY = -790, /** Failed to allocate memory */
+ TETHERING_EXT_ERR_SERVICE_UNKNOWN = -789, /** DBus service is unknown */
+ TETHERING_EXT_ERR_OPERATION_FAILED = -788, /** Operation failed */
+ TETHERING_EXT_ERR_NOT_SET = -787, /** Not Set */
+} _tethering_ext_err_e;
+
+
+
+typedef struct {
+ _tethering_ext_event_e Event;
+ _tethering_ext_err_e Error;
+ int Datalength;
+ void *Data;
+} _tethering_ext_event_info_h;
+
+typedef struct {
+ char *tethering_ssid;
+ char *tethering_password;
+} _tethering_ext_tethering_info;
+
+typedef struct {
+ char ip[TETHERING_EXT_STR_INFO_LEN]; /**< assigned IP address */
+ char mac[TETHERING_EXT_STR_INFO_LEN]; /**< MAC Address */
+ char *hostname;
+ time_t tm;
+} _tethering_ext_client_info_h;
+
+
+typedef void *_tethering_ext_client_h;
+typedef void (*_tethering_ext_enabled_cb) (tethering_error_e result, bool is_requested, void *user_data);
+typedef void (*_tethering_ext_disabled_cb) (tethering_error_e result, _tethering_ext_disabled_cause_e cause, void *user_data);
+typedef void (*_tethering_ext_connection_state_changed_cb) (_tethering_ext_client_h client, bool opened, void *user_data);
+
+// Tethering state callbacks
+typedef void(*_tethering_ext_state_changed_cb)(_tethering_ext_state_e state, void *user_data);
+typedef void (*_tethering_ext_event_cb) (const _tethering_ext_event_info_h *tethering_ext_event, void *user_data);
+
+typedef struct {
+ _tethering_ext_enabled_cb enabled_cb;
+ void *enabled_user_data;
+ _tethering_ext_disabled_cb disabled_cb;
+ void *disabled_user_data;
+ _tethering_ext_connection_state_changed_cb changed_cb;
+ void *changed_user_data;
+} _tethering_ext_callback_h;
+
+typedef struct {
+ GDBusConnection *tethering_ext_client;
+ GCancellable *tethering_ext_cancellable;
+ guint subscribe_id_wifi_tethering_state;
+ _tethering_ext_state_e tethering_ext_state;
+ _tethering_ext_state_changed_cb tethering_ext_state_changed_cb;
+ void *tethering_ext_state_changed_user_data;
+ _tethering_ext_event_cb tethering_ext_event_cb;
+ void *tethering_ext_user_data;
+ tethering_ext_config_h tethering_ext_config;
+ _tethering_ext_callback_h *tethering_ext_callbacks;
+} _tethering_ext_h;
+
+int _tethering_ext_create_context(tethering_ext_h *tethering_context);
+void _tethering_ext_destroy_context(tethering_ext_h tethering_context);
+bool _tethering_ext_check_context(tethering_ext_h tethering_context);
+void _tethering_ext_add_context(tethering_ext_h *tethering_context);
+void _tethering_ext_remove_context(tethering_ext_h tethering_context);
+int _tethering_ext_register_dbus(tethering_ext_h tethering_context);
+void _tethering_ext_unregister_dbus(tethering_ext_h tethering_context);
+int _tethering_ext_set_wifi_tethering_mode(tethering_ext_h tethering_context, bool enable);
+int _tethering_ext_set_wifi_tethering_mode_with_params(tethering_ext_h tethering_context, bool enable);
+int _tethering_ext_get_wifi_tethering_mode(tethering_ext_h tethering_context, bool *is_enabled);
+int _tethering_ext_set_config(tethering_ext_h tethering_context, void *src_config, int type);
+int _tethering_ext_get_config(tethering_ext_h tethering_context, void *target_config, int type);
+int _tethering_ext_client_clone(_tethering_ext_client_h *dest, _tethering_ext_client_h origin);
+int _tethering_ext_client_get_name(_tethering_ext_client_h client, char **name);
+int _tethering_ext_client_get_ip_address(_tethering_ext_client_h client, char **ip_address);
+int _tethering_ext_client_get_mac_address(_tethering_ext_client_h client, char **mac_address);
+int _tethering_ext_client_destroy(_tethering_ext_client_h client);
+void _tethering_ext_register_callbacks(tethering_ext_h tethering_context, _tethering_ext_callback_h callbacks);
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __TIZEN_NETWORK_TETHERING_EXT_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdlib.h>
+#include <tethering_ext.h>
+#include <dlog.h>
+
+#define DISABLE_REASON_TEXT_LEN 64
+#define TETHERING_GET_CONFIG(context, value, config, retval)\
+do {\
+ if (!context || !value) {\
+ LOGE("Invalid paramater, exiting");\
+ retval = TETHERING_ERROR_INVALID_PARAMETER;\
+ } else {\
+ int rv = _tethering_ext_get_config(th_context, (void *) (value), config);\
+ if (rv != TETHERING_EXT_ERR_NONE) {\
+ LOGE("%s failed with error code %d", __FUNCTION__, rv);\
+ retval = TETHERING_ERROR_OPERATION_FAILED;\
+ } else {\
+ retval = TETHERING_ERROR_NONE;\
+ }\
+ }\
+} while (0);
+
+/* Tethering callbacks */
+static void __enabled_cb(tethering_error_e result, bool is_requested, void *user_data)
+{
+ if (result != TETHERING_ERROR_NONE) {
+ if (!is_requested)
+ return;
+
+ g_print("P2P Tethering is not enabled. error code[0x%X]\n", result);
+ return;
+ }
+
+ if (is_requested)
+ g_print("P2P Tethering is enabled successfully\n");
+ else
+ g_print("P2P Tethering is enabled by other app\n");
+
+ return;
+}
+
+static const char *__convert_disabled_code_to_str(const _tethering_ext_disabled_cause_e code)
+{
+ static char str_buf[DISABLE_REASON_TEXT_LEN] = {0, };
+
+ switch (code) {
+ case TETHERING_EXT_DISABLED_BY_FLIGHT_MODE:
+ strncpy(str_buf, "disabled due to flight mode on", sizeof(str_buf));
+ break;
+
+ case TETHERING_EXT_DISABLED_BY_LOW_BATTERY:
+ strncpy(str_buf, "disabled due to low battery", sizeof(str_buf));
+ break;
+
+ case TETHERING_EXT_DISABLED_BY_NETWORK_CLOSE:
+ strncpy(str_buf, "disabled due to pdp network close", sizeof(str_buf));
+ break;
+
+ case TETHERING_EXT_DISABLED_BY_TIMEOUT:
+ strncpy(str_buf, "disabled due to timeout", sizeof(str_buf));
+ break;
+
+ case TETHERING_EXT_DISABLED_BY_OTHERS:
+ strncpy(str_buf, "disabled by other apps", sizeof(str_buf));
+ break;
+
+ case TETHERING_EXT_DISABLED_BY_REQUEST:
+ strncpy(str_buf, "disabled by my request", sizeof(str_buf));
+ break;
+
+ case TETHERING_EXT_DISABLED_BY_WIFI_ON:
+ strncpy(str_buf, "disabled by Wi-Fi station on", sizeof(str_buf));
+ break;
+
+ default:
+ strncpy(str_buf, "disabled by unknown reason", sizeof(str_buf));
+ break;
+ }
+
+ return str_buf;
+}
+
+static void __disabled_cb(tethering_error_e result, _tethering_ext_disabled_cause_e cause, void *user_data)
+{
+ if (result != TETHERING_ERROR_NONE) {
+ if (cause != TETHERING_EXT_DISABLED_BY_REQUEST)
+ return;
+
+ g_print("P2P Tethering is not disabled. error code[0x%X]\n", result);
+ return;
+ }
+
+ g_print("P2P Tethering is %s\n", __convert_disabled_code_to_str(cause));
+
+ return;
+}
+
+static void __connection_state_changed_cb(_tethering_ext_client_h client, bool open, void *user_data)
+{
+ _tethering_ext_client_h clone = NULL;
+ // tethering_type_e type;
+ char *ip_address = NULL;
+ char *mac_address = NULL;
+ char *hostname = NULL;
+
+ _tethering_ext_client_clone(&clone, client);
+ if (clone == NULL) {
+ g_print("tetheirng_client_clone is failed\n");
+ return;
+ }
+
+ _tethering_ext_client_get_ip_address(clone, &ip_address);
+ _tethering_ext_client_get_mac_address(clone, &mac_address);
+ _tethering_ext_client_get_name(clone, &hostname);
+
+ if (open) {
+ g_print("## New station Type [P2P Tethering], IP [%s], MAC [%s], hostname [%s]\n",
+ ip_address, mac_address, hostname);
+ } else {
+ g_print("## Disconnected station Type [P2P Tethering], IP [%s], MAC [%s], hostname [%s]\n",
+ ip_address, mac_address, hostname);
+ }
+
+ if (ip_address)
+ free(ip_address);
+ if (mac_address)
+ free(mac_address);
+ if (hostname)
+ free(hostname);
+
+ _tethering_ext_client_destroy(clone);
+
+ return;
+}
+
+
+API int tethering_ext_initialize(tethering_ext_h *tethering_context) {
+ // __TETHERING_EXT_CAPI_FUNC_ENTER__;
+
+ int rv;
+
+ if (tethering_context == NULL) {
+ LOGE("Invalid Parameter");
+ // __TETHERING_EXT_CAPI_FUNC_EXIT__;
+ return TETHERING_ERROR_INVALID_PARAMETER;
+ }
+
+ // TETHERING_EXT_LOCK;
+
+ if (_tethering_ext_check_context(*tethering_context)) {
+ LOGE("Already initialized");
+ // TETHERING_EXT_UNLOCK;
+ // __TETHERING_EXT_CAPI_FUNC_EXIT__;
+ return TETHERING_ERROR_NONE;
+ }
+
+ rv = _tethering_ext_create_context(tethering_context);
+ if (rv != TETHERING_EXT_ERR_NONE) {
+ LOGE("Init failed[%d]", rv);
+ // TETHERING_EXT_UNLOCK;
+ // __TETHERING_EXT_CAPI_FUNC_EXIT__;
+ return TETHERING_ERROR_OUT_OF_MEMORY;
+ }
+
+ rv = _tethering_ext_register_dbus(*tethering_context);
+ if (rv != TETHERING_EXT_ERR_NONE && rv != TETHERING_EXT_ERR_APP_ALREADY_REGISTERED) {
+ LOGE("dbus register failed[%d]", rv);
+ _tethering_ext_destroy_context(*tethering_context);
+ // TETHERING_EXT_UNLOCK;
+ // __TETHERING_EXT_CAPI_FUNC_EXIT__;
+ return TETHERING_ERROR_OPERATION_FAILED;
+ }
+
+ _tethering_ext_callback_h callbacks = {__enabled_cb, NULL, __disabled_cb, NULL, __connection_state_changed_cb, NULL};
+ _tethering_ext_register_callbacks(tethering_context, callbacks);
+
+ _tethering_ext_add_context(tethering_context);
+
+ LOGD("Tethering context successfully initialized");
+
+ // TETHERING_EXT_UNLOCK;
+ // __TETHERING_EXT_CAPI_FUNC_EXIT__;
+ return TETHERING_ERROR_NONE;
+}
+
+API int tethering_ext_deinitialize(tethering_ext_h tethering_context) {
+ // __TETHERING_EXT_CAPI_FUNC_ENTER__;
+
+ // TETHERING_EXT_LOCK;
+
+ RET_ERR_IF_HANDLE_IS_NOT_VALID_OR_NOT_INITIALIZED(tethering_context);
+
+ LOGD("Destroy Tethering context : %p", tethering_context);
+
+ _tethering_ext_remove_context(tethering_context);
+ _tethering_ext_unregister_dbus(tethering_context);
+ _tethering_ext_destroy_context(tethering_context);
+
+ return TETHERING_ERROR_NONE;
+}
+
+API int tethering_ext_activate(tethering_ext_h tethering_context) {
+ // __TETHERING_EXT_CAPI_FUNC_ENTER__;
+
+ int rv = 0;
+
+ RET_ERR_IF_HANDLE_IS_NOT_VALID_OR_NOT_INITIALIZED(tethering_context);
+
+ rv = _tethering_ext_set_wifi_tethering_mode_with_params(tethering_context, true);
+ if (rv == TETHERING_EXT_ERR_ACCESS_DENIED) {
+ LOGE("Access denied");
+ return TETHERING_ERROR_PERMISSION_DENIED;
+ } else if (rv == TETHERING_EXT_ERR_INVALID_OPERATION) {
+ return TETHERING_ERROR_INVALID_OPERATION;
+ } else if (rv != TETHERING_EXT_ERR_NONE) {
+ LOGE("Failed to set tethering mode");
+ return TETHERING_ERROR_OPERATION_FAILED;
+ }
+
+ return TETHERING_ERROR_NONE;
+}
+
+API int tethering_ext_deactivate(tethering_ext_h tethering_context) {
+ // __TETHERING_EXT_CAPI_FUNC_ENTER__;
+
+ int rv = 0;
+
+ RET_ERR_IF_HANDLE_IS_NOT_VALID_OR_NOT_INITIALIZED(tethering_context);
+
+ rv = _tethering_ext_set_wifi_tethering_mode_with_params(tethering_context, false);
+ if (rv == TETHERING_EXT_ERR_ACCESS_DENIED) {
+ LOGE("Access denied");
+ return TETHERING_ERROR_PERMISSION_DENIED;
+ } else if (rv == TETHERING_EXT_ERR_INVALID_OPERATION) {
+ return TETHERING_ERROR_INVALID_OPERATION;
+ } else if (rv != TETHERING_EXT_ERR_NONE) {
+ LOGE("Failed to set tethering mode");
+ return TETHERING_ERROR_OPERATION_FAILED;
+ }
+
+ return TETHERING_ERROR_NONE;
+}
+
+API int tethering_ext_is_enabled(tethering_ext_h tethering_context, bool *is_enabled) {
+ // __TETHERING_EXT_CAPI_FUNC_ENTER__;
+
+ int rv = TETHERING_ERROR_NONE;
+
+ RET_ERR_IF_HANDLE_IS_NOT_VALID_OR_NOT_INITIALIZED(tethering_context);
+
+ if (!is_enabled) {
+ LOGE("Invalid parameter");
+ // __TETHERING_EXT_CAPI_FUNC_EXIT__;
+ return TETHERING_ERROR_INVALID_PARAMETER;
+ }
+
+ rv = _tethering_ext_get_wifi_tethering_mode(tethering_context, is_enabled);
+
+ // __TETHERING_EXT_CAPI_FUNC_EXIT__TETHERING_ERROR_OPERATION_FAILED
+
+ return rv;
+}
+
+API int tethering_ext_set_ssid(tethering_ext_h th_context, const char *ssid) {
+ size_t length = strlen(ssid);
+ if (length > TETHERING_EXT_WIFI_SSID_MAX_LEN) {
+ return TETHERING_ERROR_INVALID_PARAMETER;
+ }
+ return _tethering_ext_set_config(th_context, (void *) ssid, TETHERING_EXT_SSID);
+ return TETHERING_ERROR_NONE;
+}
+
+API int tethering_ext_set_passphrase(tethering_ext_h th_context, const char *passphrase) {
+ size_t length = strlen(passphrase);
+ if (length > TETHERING_EXT_WIFI_KEY_MAX_LEN) {
+ return TETHERING_ERROR_INVALID_PARAMETER;
+ }
+ return _tethering_ext_set_config(th_context, (void *) passphrase, TETHERING_EXT_PASSPHRASE);
+}
+
+API int tethering_ext_set_channel(tethering_ext_h th_context, int channel) {
+ return _tethering_ext_set_config(th_context, (void *) &channel, TETHERING_EXT_CHANNEL);
+}
+
+API int tethering_ext_get_tethering_info(tethering_ext_h th_context, void **tethering_info) {
+ int ret;
+ TETHERING_GET_CONFIG(th_context, *tethering_info, TETHERING_EXT_SSID | TETHERING_EXT_PASSPHRASE, ret);
+ return ret;
+}
+
+API int tethering_ext_get_channel(tethering_ext_h th_context, int *channel) {
+ int ret;
+ TETHERING_GET_CONFIG(th_context, channel, TETHERING_EXT_CHANNEL, ret);
+ return ret;
+}
+
+API int tethering_ext_get_security(tethering_ext_h th_context, int *security) {
+ int ret;
+ TETHERING_GET_CONFIG(th_context, security, TETHERING_EXT_SECURITY_TYPE, ret);
+ return ret;
+}
+
+API int tethering_ext_get_visibility(tethering_ext_h th_context, int *visibility) {
+ int ret;
+ TETHERING_GET_CONFIG(th_context, visibility, TETHERING_EXT_VISIBLE, ret);
+ return ret;
+}
+
+API int tethering_ext_get_sharing(tethering_ext_h th_context, bool *sharing) {
+ int ret;
+ TETHERING_GET_CONFIG(th_context, sharing, TETHERING_EXT_SHARED, ret);
+ return ret;
+}
--- /dev/null
+#include <dlog.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <stdlib.h>
+#include <tethering_ext_dbus.h>
+
+#define DBUS_REPLY_TIMEOUT_SYNC (10 * 1000)
+
+static int __tethering_ext_error_string_to_enum(const char *error)
+{
+ LOGD("Passed error string [%s]", error);
+
+ if (strstr(error, "NoReply"))
+ return TETHERING_EXT_ERR_TIME_OUT;
+ else if (strstr(error, "UnknownMethod"))
+ return TETHERING_EXT_ERR_UNKNOWN_METHOD;
+ else if (strstr(error, "InvalidArgs"))
+ return TETHERING_EXT_ERR_INVALID_PARAM;
+ else if (strstr(error, "AccessDenied"))
+ return TETHERING_EXT_ERR_ACCESS_DENIED;
+ else if (strstr(error, "PermissionDenied"))
+ return TETHERING_EXT_ERR_ACCESS_DENIED;
+ else if (strstr(error, "NotRegistered"))
+ return TETHERING_EXT_ERR_INVALID_OPERATION;
+ else if (strstr(error, "NotSupported"))
+ return TETHERING_EXT_ERR_NOT_SUPPORTED;
+ else if (strstr(error, "InProgress"))
+ return TETHERING_EXT_ERR_IN_PROGRESS;
+ else if (strstr(error, "AlreadyExists"))
+ return TETHERING_EXT_ERR_ALREADY_EXISTS;
+ else if (strstr(error, "AlreadyEnabled"))
+ return TETHERING_EXT_ERR_INVALID_OPERATION;
+ else if (strstr(error, "AlreadyDisabled"))
+ return TETHERING_EXT_ERR_INVALID_OPERATION;
+ else if (strstr(error, "OperationFailed"))
+ return TETHERING_EXT_ERR_OPERATION_FAILED;
+ else if (strstr(error, "OperationAborted"))
+ return TETHERING_EXT_ERR_OPERATION_ABORTED;
+ else if (strstr(error, "OperationTimeout"))
+ return TETHERING_EXT_ERR_TIME_OUT;
+ else if (strstr(error, "OutOfMemory"))
+ return TETHERING_EXT_ERR_OUT_OF_MEMORY;
+ else if (strstr(error, "NotSet"))
+ return TETHERING_EXT_ERR_NOT_SET;
+ else if (strstr(error, "ServiceUnknown"))
+ return TETHERING_EXT_ERR_SERVICE_UNKNOWN;
+
+ return TETHERING_EXT_ERR_NONE;
+}
+
+GVariant *_invoke_dbus_method(_tethering_ext_h *tethering_ctx, const char *dest, const char *path, const char *interface_name,
+ const char *method, GVariant *params, int *dbus_error)
+{
+ //__TETHERING_EXT_CAPI_FUNC_ENTER__;
+
+ GError *error = NULL;
+ GVariant *message = NULL;
+ GDBusConnection *connection = NULL;
+ *dbus_error = TETHERING_EXT_ERR_NONE;
+ gboolean created = FALSE;
+
+ if (!tethering_ctx || tethering_ctx->tethering_ext_client == NULL) {
+ connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+ created = TRUE;
+ } else {
+ connection = tethering_ctx->tethering_ext_client;
+ created = FALSE;
+ }
+
+ if (!connection) {
+ if (error) {
+ LOGE("Failed to connect to the D-BUS daemon [%s]", error->message);
+ g_error_free(error);
+ }
+ return NULL;
+ }
+
+ message = g_dbus_connection_call_sync(connection,
+ dest,
+ path,
+ interface_name,
+ method,
+ params,
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_REPLY_TIMEOUT_SYNC,
+ NULL,
+ &error);
+
+ if (!message) {
+ if (error) {
+ LOGE("g_dbus_connection_call_sync() failed error [%d]: %s", error->code, error->message);
+ *dbus_error = __tethering_ext_error_string_to_enum(error->message);
+ g_error_free(error);
+ } else {
+ LOGE("g_dbus_connection_call_sync() failed");
+ *dbus_error = TETHERING_EXT_ERR_UNKNOWN;
+ }
+
+ if (created)
+ g_object_unref(connection);
+
+ //__TETHERING_WIFI_EXT_CAPI_FUNC_EXIT__;
+ return NULL;
+ }
+
+ if (created)
+ g_object_unref(connection);
+
+ //__TETHERING_WIFI_EXT_CAPI_FUNC_EXIT__;
+ return message;
+}
+
+int _tethering_ext_dbus_set_wifi_tethering_mode(_tethering_ext_h *tethering_ctx, bool enable)
+{
+ //__TETHERING_EXT_CAPI_FUNC_ENTER__;
+
+ GVariant *message = NULL;
+ GVariant *params = NULL;
+ _tethering_ext_err_e Error = TETHERING_EXT_ERR_NONE;
+
+ LOGD("_tethering_ext_dbus_set_wifi_tethering_mode() called : %s", enable ? "Enable" : "Disable");
+
+ params = g_variant_new("(b)", enable);
+
+ message = _invoke_dbus_method(tethering_ctx, TETHERING_EXT_BUS_NAME, TETHERING_EXT_OBJECT_PATH,
+ TETHERING_EXT_INTERFACE_NAME, TETHERING_EXT_METHOD_SET_MODE, params, &Error);
+
+ if (message == NULL) {
+ LOGE("Failed to set tethering %s", enable ? "Enable" : "Disable");
+ //__TETHERING_WIFI_EXT_CAPI_FUNC_EXIT__;
+ return Error;
+ }
+
+ g_variant_unref(message);
+ //__TETHERING_WIFI_EXT_CAPI_FUNC_EXIT__;
+
+ return Error;
+}
+
+int _tethering_ext_dbus_set_wifi_tethering_mode_with_params(_tethering_ext_h *tethering_ctx, bool enable)
+{
+ //__TETHERING_EXT_CAPI_FUNC_ENTER__;
+
+ GVariant *message = NULL;
+ GVariant *params = NULL;
+ _tethering_ext_err_e Error = TETHERING_EXT_ERR_NONE;
+
+ LOGD("_tethering_ext_dbus_set_wifi_tethering_mode() called : %s", enable ? "Enable" : "Disable");
+ char *ssid = tethering_ctx->tethering_ext_config.ssid;
+ char *password = tethering_ctx->tethering_ext_config.passphrase;
+ int channel = tethering_ctx->tethering_ext_config.channel;
+ if (enable == TRUE) {
+ params = g_variant_new("(bssi)", enable, ssid, password, channel);
+ message = _invoke_dbus_method(tethering_ctx, TETHERING_EXT_BUS_NAME, TETHERING_EXT_OBJECT_PATH,
+ TETHERING_EXT_INTERFACE_NAME, TETHERING_EXT_METHOD_SET_MODE_WITH_PARAMS, params, &Error);
+ } else {
+ params = g_variant_new("(b)", enable);
+ message = _invoke_dbus_method(tethering_ctx, TETHERING_EXT_BUS_NAME, TETHERING_EXT_OBJECT_PATH,
+ TETHERING_EXT_INTERFACE_NAME, TETHERING_EXT_METHOD_SET_MODE, params, &Error);
+ }
+
+ if (message == NULL) {
+ LOGE("Failed to set tethering %s", enable ? "Enable" : "Disable");
+ //__TETHERING_WIFI_EXT_CAPI_FUNC_EXIT__;
+ return Error;
+ }
+
+ g_variant_unref(message);
+ //__TETHERING_WIFI_EXT_CAPI_FUNC_EXIT__;
+
+ return Error;
+}
+
+int _tethering_ext_dbus_get_wifi_tethering_state(_tethering_ext_h *tethering_ctx, _tethering_ext_state_e *tethering_state)
+{
+ //__TETHERING_EXT_CAPI_FUNC_ENTER__;
+
+ GVariant *message = NULL;
+ _tethering_ext_err_e Error = TETHERING_EXT_ERR_NONE;
+ gboolean state = 0;
+
+ LOGD("_tethering_ext_dbus_get_wifi_tethering_state() called");
+
+ message = _invoke_dbus_method(tethering_ctx, TETHERING_EXT_BUS_NAME, TETHERING_EXT_OBJECT_PATH,
+ TETHERING_EXT_INTERFACE_NAME, TETHERING_EXT_METHOD_GET_MODE, NULL, &Error);
+
+ if (message == NULL) {
+ LOGE("Failed to get tethering state");
+ //__TETHERING_WIFI_EXT_CAPI_FUNC_EXIT__;
+ return Error;
+ }
+
+ g_variant_get(message, "(b)", &state);
+
+ if (state)
+ *tethering_state = TETHERING_EXT_STATE_ENABLED;
+ else
+ *tethering_state = TETHERING_EXT_STATE_DISABLED;
+
+ LOGD("Tethering mode state : %d", *tethering_state);
+
+ g_variant_unref(message);
+
+ //__TETHERING_WIFI_EXT_CAPI_FUNC_EXIT__;
+ return Error;
+}
+
+int _tethering_ext_dbus_get_wifi_tethering_info(_tethering_ext_h *tethering_ctx, _tethering_ext_tethering_info *tethering_info)
+{
+ //__TETHERING_EXT_CAPI_FUNC_ENTER__;
+
+ GVariant *message = NULL;
+ _tethering_ext_err_e Error = TETHERING_EXT_ERR_NONE;
+
+ LOGD("_tethering_ext_dbus_get_wifi_tethering_info() called");
+
+ message = _invoke_dbus_method(tethering_ctx, TETHERING_EXT_BUS_NAME, TETHERING_EXT_OBJECT_PATH,
+ TETHERING_EXT_INTERFACE_NAME, TETHERING_EXT_METHOD_GET_INFO, NULL, &Error);
+
+ if (message == NULL) {
+ LOGE("Failed to get tethering info");
+ //__TETHERING_WIFI_EXT_CAPI_FUNC_EXIT__;
+ return Error;
+ }
+
+ g_variant_get(message, "(ss)", &tethering_info->tethering_ssid, &tethering_info->tethering_password);
+
+ LOGD("Tethering info : ssid[%s] password[%s]", tethering_info->tethering_ssid, tethering_info->tethering_password);
+
+ g_variant_unref(message);
+
+ //__TETHERING_WIFI_EXT_CAPI_FUNC_EXIT__;
+
+ return Error;
+}
--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define _GNU_SOURCE
+#include <tethering_ext_internal.h>
+#include <tethering_ext_dbus.h>
+#include <vconf.h>
+
+#define tethering_ext_err_to_str(x) #x
+
+static GSList *tethering_ctx_list = NULL;
+
+int _tethering_ext_create_context(tethering_ext_h *tethering_context)
+{
+ _tethering_ext_h *tethering_ctx = g_try_malloc0(sizeof(_tethering_ext_h));
+ if (!tethering_ctx) {
+ LOGE("Failed to create tethering_ctx : %d", TETHERING_ERROR_OUT_OF_MEMORY);
+ return TETHERING_ERROR_OUT_OF_MEMORY;
+ }
+ tethering_ctx->tethering_ext_callbacks = g_try_malloc0(sizeof(_tethering_ext_callback_h));
+ *tethering_context = tethering_ctx;
+
+ LOGD("New tethering_ctx create[%p]", *tethering_context);
+
+ return TETHERING_EXT_ERR_NONE;
+}
+
+void _tethering_ext_destroy_context(tethering_ext_h tethering_context)
+{
+ if (!tethering_context) {
+ return;
+ }
+ _tethering_ext_h *tethering_ctx = (_tethering_ext_h *) tethering_context;
+ if (tethering_ctx->tethering_ext_callbacks) {
+ g_free(tethering_ctx->tethering_ext_callbacks);
+ }
+ g_free(tethering_context);
+}
+
+bool _tethering_ext_check_context(tethering_ext_h tethering_context)
+{
+ if (g_slist_find(tethering_ctx_list, tethering_context) != NULL) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void _tethering_ext_add_context(tethering_ext_h *tethering_context)
+{
+ // TETHERING_EXT_LOCK;
+ tethering_ctx_list = g_slist_append(tethering_ctx_list, *tethering_context);
+ // TETHERING_EXT_UNLOCK;
+}
+
+void _tethering_ext_remove_context(tethering_ext_h tethering_context)
+{
+ // TETHERING_EXT_LOCK;
+ tethering_ctx_list = g_slist_remove(tethering_ctx_list, tethering_context);
+ // TETHERING_EXT_UNLOCK;
+}
+
+
+static void __wifi_tethering_mode_on_off_cb(_tethering_ext_h *tethering_ctx,
+ _tethering_ext_event_info_h *event_cb)
+{
+ tethering_error_e error_code = TETHERING_ERROR_NONE;
+ _tethering_ext_state_e state = TETHERING_EXT_STATE_DISABLED; // out
+ _tethering_ext_state_e *tethering_state = (_tethering_ext_state_e *)event_cb->Data;
+
+ if (tethering_ctx->tethering_ext_state_changed_cb == NULL)
+ return;
+
+ if (event_cb->Error == TETHERING_EXT_ERR_NONE &&
+ event_cb->Datalength == sizeof(_tethering_ext_state_e)) {
+ if (*tethering_state == TETHERING_EXT_STATE_ENABLED) {
+ LOGD("Tethering mode is enabled");
+ state = TETHERING_EXT_STATE_ENABLED;
+ } else if (*tethering_state == TETHERING_EXT_STATE_DISABLED) {
+ LOGD("Tethering mode is disabled");
+ state = TETHERING_EXT_STATE_DISABLED;
+ } else {
+ LOGE("Error Tethering state %d", *tethering_state);
+ error_code = TETHERING_ERROR_OPERATION_FAILED;
+ }
+ } else {
+ LOGE("Tethering power request failed(%d)", event_cb->Error);
+ error_code = TETHERING_ERROR_OPERATION_FAILED;
+ state = TETHERING_EXT_STATE_DISABLED;
+ }
+
+ if (error_code == TETHERING_ERROR_NONE) {
+ if (tethering_ctx->tethering_ext_state_changed_cb)
+ tethering_ctx->tethering_ext_state_changed_cb(state, tethering_ctx->tethering_ext_state_changed_user_data);
+ }
+}
+
+static void __tethering_ext_evt_cb(_tethering_ext_event_info_h *event_cb, void *user_data)
+{
+ // TETHERING_EXT_LOCK;
+ _tethering_ext_h *tethering_ctx = (_tethering_ext_h *)user_data;
+
+ if (!_tethering_ext_check_context(tethering_ctx)) {
+ LOGE("WiFi Extension context is not initialized");
+ // TETHERING_EXT_UNLOCK;
+ return;
+ }
+
+ switch (event_cb->Event) {
+ case TETHERING_EXT_POWER_IND:
+ __wifi_tethering_mode_on_off_cb(tethering_ctx, event_cb);
+ break;
+ default:
+ break;
+ }
+
+ // TETHERING_EXT_UNLOCK;
+}
+
+static int __tethering_ext_mode_changed(_tethering_ext_h *tethering_ctx, GVariant *param)
+{
+ // __TETHERING_EXT_CAPI_FUNC_ENTER__;
+
+ gboolean value = FALSE;
+ _tethering_ext_event_info_h *event_data = NULL;
+
+ g_variant_get(param, "(b)", &value);
+
+ event_data = g_try_malloc0(sizeof(_tethering_ext_event_info_h));
+ if (!event_data) {
+ // __TETHERING_EXT_CAPI_FUNC_EXIT__;
+ return TETHERING_EXT_ERR_OUT_OF_MEMORY;
+ }
+
+ LOGD("Tethering mode changed to %s", value ? "enabled" : "disabled");
+
+ event_data->Event = TETHERING_EXT_POWER_IND;
+ event_data->Error = TETHERING_EXT_ERR_NONE;
+ event_data->Datalength = sizeof(gboolean);
+ event_data->Data = &value;
+
+ if (tethering_ctx->tethering_ext_event_cb)
+ tethering_ctx->tethering_ext_event_cb(event_data, tethering_ctx->tethering_ext_user_data);
+
+ g_free(event_data);
+
+ // __TETHERING_EXT_CAPI_FUNC_EXIT__;
+
+ return TETHERING_EXT_ERR_NONE;
+}
+
+static int __tethering_ext_enabled_callback(_tethering_ext_h *tethering_ctx, GVariant *param) {
+ gboolean is_enabled = FALSE;
+ g_variant_get(param, "(bi)", &is_enabled);
+
+ if (! is_enabled) {
+ return TETHERING_EXT_ERR_INVALID_PARAM;
+ }
+ _tethering_ext_callback_h *callbacks = tethering_ctx->tethering_ext_callbacks;
+ if (callbacks->enabled_cb) {
+ callbacks->enabled_cb(TETHERING_ERROR_NONE, true, callbacks->enabled_user_data);
+ }
+ return TETHERING_EXT_ERR_NONE;
+}
+
+static int __tethering_ext_disabled_callback(_tethering_ext_h *tethering_ctx, GVariant *param) {
+ gboolean is_disabled = FALSE;
+ gint disabled_cause;
+ g_variant_get(param, "(bi)", &is_disabled, &disabled_cause);
+
+ if (! is_disabled) {
+ return TETHERING_EXT_ERR_INVALID_PARAM;
+ }
+ _tethering_ext_callback_h *callbacks = tethering_ctx->tethering_ext_callbacks;
+ if (callbacks->disabled_cb) {
+ callbacks->disabled_cb(TETHERING_ERROR_NONE, disabled_cause, callbacks->disabled_user_data);
+ }
+ return TETHERING_EXT_ERR_NONE;
+}
+
+static int __tethering_ext_connection_state_callback(_tethering_ext_h *tethering_ctx, GVariant *param) {
+ _tethering_ext_err_e ret = TETHERING_EXT_ERR_NONE;
+ char *buf = NULL;
+ char *name = NULL;
+ char *mac = NULL;
+ char *ip = NULL;
+ guint timestamp;
+ bool opened = false;
+ _tethering_ext_client_info_h client;
+ _tethering_ext_callback_h *callbacks = tethering_ctx->tethering_ext_callbacks;
+ memset(&client, 0, sizeof(_tethering_ext_client_info_h));
+ g_variant_get(param, "(ssssu)", &buf, &ip, &mac, &name, ×tamp);
+
+ if (!g_strcmp0(buf, "DhcpConnected")) {
+ opened = true;
+ } else if (!g_strcmp0(buf, "DhcpLeaseDeleted")) {
+ opened = false;
+ } else {
+ LOGE("Unknown event [%s]\n", buf);
+ ret = TETHERING_ERROR_INVALID_PARAMETER;
+ goto DONE;
+ }
+
+ LOGI("P2P tethering type %s, ip %s, mac %s, name %s, timestamp %d",
+ buf, ip, mac, name, timestamp);
+ g_strlcpy(client.ip, ip, sizeof(client.ip));
+ g_strlcpy(client.mac, mac, sizeof(client.mac));
+ if (name != NULL)
+ client.hostname = g_strdup(name);
+ client.tm = (time_t)timestamp;
+ if (callbacks->changed_cb) {
+ callbacks->changed_cb((_tethering_ext_client_h)&client, opened, callbacks->changed_user_data);
+ }
+
+DONE:
+ g_free(buf);
+ g_free(ip);
+ g_free(mac);
+ g_free(name);
+ return ret;
+}
+
+static _tethering_ext_err_e __tethering_ext_dbus_create(_tethering_ext_h *tethering_ctx) {
+ GError *error = NULL;
+ #if !GLIB_CHECK_VERSION(2, 36, 0)
+ g_type_init();
+ #endif
+
+ if (!tethering_ctx) {
+ return TETHERING_EXT_ERR_APP_NOT_REGISTERED;
+ }
+
+ tethering_ctx->tethering_ext_client = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+
+ if (!tethering_ctx->tethering_ext_client) {
+ if (error) {
+ LOGE("Failed to get dbus connection [%s]", error->message);
+ g_error_free(error);
+ }
+ return TETHERING_EXT_ERR_UNKNOWN;
+ }
+
+ tethering_ctx->tethering_ext_cancellable = g_cancellable_new();
+ return TETHERING_EXT_ERR_NONE;
+}
+
+static void __tethering_ext_close_gdbus_call(_tethering_ext_h *tethering_ctx)
+{
+ if (tethering_ctx->tethering_ext_cancellable) {
+ g_cancellable_cancel(tethering_ctx->tethering_ext_cancellable);
+ g_object_unref(tethering_ctx->tethering_ext_cancellable);
+ tethering_ctx->tethering_ext_cancellable = NULL;
+ }
+
+ if (tethering_ctx->tethering_ext_client) {
+ g_object_unref(tethering_ctx->tethering_ext_client);
+ tethering_ctx->tethering_ext_client = NULL;
+ }
+}
+
+static void __tethering_ext_signal_filter(GDBusConnection *conn,
+ const gchar *name, const gchar *path, const gchar *interface,
+ const gchar *sig, GVariant *param, gpointer user_data)
+{
+ // __TETHERING_EXT_CAPI_FUNC_ENTER__;
+ _tethering_ext_h *tethering_ctx = (_tethering_ext_h *)user_data;
+
+ if (!g_strcmp0(sig, SIGNAL_TETHERING_EXT_MODE_CHANGED)) {
+ __tethering_ext_mode_changed(tethering_ctx, param);
+ } else if (!g_strcmp0(sig, SIGNAL_TETHERING_EXT_ENABLED)) {
+ __tethering_ext_enabled_callback(tethering_ctx, param);
+ } else if (!g_strcmp0(sig, SIGNAL_TETHERING_EXT_DISABLED)) {
+ __tethering_ext_disabled_callback(tethering_ctx, param);
+ } else if (!g_strcmp0(sig, SIGNAL_TETHERING_CONNECTION_CHANGED)) {
+ __tethering_ext_connection_state_callback(tethering_ctx, param);
+ }
+
+ // __TETHERING_EXT_CAPI_FUNC_EXIT__;
+}
+
+static void __tethering_ext_unregister_signal(_tethering_ext_h *tethering_ctx)
+{
+ // __TETHERING_EXT_CAPI_FUNC_ENTER__;
+
+ if (tethering_ctx) {
+ g_dbus_connection_signal_unsubscribe(tethering_ctx->tethering_ext_client, tethering_ctx->subscribe_id_wifi_tethering_state);
+ }
+
+ // __TETHERING_EXT_CAPI_FUNC_EXIT__;
+}
+
+static int __tethering_ext_dbus_register_signal(_tethering_ext_h *tethering_ctx)
+{
+ // __TETHERING_EXT_CAPI_FUNC_ENTER__;
+
+ _tethering_ext_err_e Error = TETHERING_EXT_ERR_NONE;
+
+ if (!tethering_ctx) {
+ // __TETHERING_EXT_CAPI_FUNC_EXIT__;
+ return TETHERING_EXT_ERR_APP_NOT_REGISTERED;
+ }
+
+ /* Create wifi-tethering-service connection */
+ tethering_ctx->subscribe_id_wifi_tethering_state = g_dbus_connection_signal_subscribe(
+ tethering_ctx->tethering_ext_client,
+ TETHERING_EXT_BUS_NAME,
+ TETHERING_EXT_INTERFACE_NAME,
+ NULL,
+ TETHERING_EXT_OBJECT_PATH,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ __tethering_ext_signal_filter,
+ tethering_ctx,
+ NULL);
+
+
+ if (tethering_ctx->subscribe_id_wifi_tethering_state == 0) {
+ LOGE("Failed to register signal, subscribe_id_wifi_tethering_state(%d)",
+ tethering_ctx->subscribe_id_wifi_tethering_state);
+ __tethering_ext_unregister_signal(tethering_ctx);
+ Error = TETHERING_EXT_ERR_INVALID_OPERATION;
+ }
+
+ // __TETHERING_EXT_CAPI_FUNC_EXIT__;
+ return Error;
+}
+
+
+int _tethering_ext_register_dbus(tethering_ext_h tethering_context) {
+ // __TETHERING_EXT_CAPI_FUNC_ENTER__
+ _tethering_ext_err_e Error = TETHERING_EXT_ERR_NONE;
+ _tethering_ext_h *tethering_ctx = (_tethering_ext_h *) tethering_context;
+ Error = __tethering_ext_dbus_create(tethering_ctx);
+ if (Error != TETHERING_EXT_ERR_NONE) {
+ return Error;
+ }
+
+ Error = __tethering_ext_dbus_register_signal(tethering_ctx);
+ if (Error != TETHERING_EXT_ERR_NONE) {
+ LOGE("Failed to register DBus signal, Error(%d)", Error);
+ __tethering_ext_close_gdbus_call(tethering_ctx);
+ // __TETHERING_EXT_CAPI_FUNC_EXIT__;
+ return Error;
+ }
+
+ tethering_ctx->tethering_ext_event_cb = (_tethering_ext_event_cb) __tethering_ext_evt_cb;
+ tethering_ctx->tethering_ext_user_data = tethering_ctx;
+ // __TETHERING_EXT_CAPI_FUNC_EXIT__;
+ return TETHERING_EXT_ERR_NONE;
+}
+
+void _tethering_ext_unregister_dbus(tethering_ext_h tethering_context) {
+ // __TETHERING_EXT_CAPI_FUNC_ENTER__;
+
+ _tethering_ext_h *tethering_ctx = (_tethering_ext_h *) tethering_context;
+
+ if (tethering_ctx) {
+ tethering_ctx->tethering_ext_event_cb = NULL;
+ tethering_ctx->tethering_ext_user_data = NULL;
+
+ __tethering_ext_unregister_signal(tethering_ctx);
+ __tethering_ext_close_gdbus_call(tethering_ctx);
+ }
+
+ // __TETHERING_EXT_CAPI_FUNC_EXIT__;
+}
+
+int _tethering_ext_set_wifi_tethering_mode(tethering_ext_h tethering_context, bool enable)
+{
+ // __TETHERING_EXT_CAPI_FUNC_ENTER__;
+
+ _tethering_ext_h *tethering_ctx = (_tethering_ext_h *)tethering_context;
+ _tethering_ext_err_e Error = TETHERING_EXT_ERR_NONE;
+
+ Error = _tethering_ext_dbus_set_wifi_tethering_mode(tethering_ctx, enable);
+ if (Error != TETHERING_EXT_ERR_NONE)
+ LOGE("Failed to set tethering mode(%d), Error[%s])",
+ enable, tethering_ext_err_to_str(Error));
+
+ // __TETHERING_EXT_CAPI_FUNC_EXIT__;
+ return Error;
+}
+
+int _tethering_ext_set_wifi_tethering_mode_with_params(tethering_ext_h tethering_context, bool enable)
+{
+ // __TETHERING_EXT_CAPI_FUNC_ENTER__;
+
+ _tethering_ext_h *tethering_ctx = (_tethering_ext_h *)tethering_context;
+ _tethering_ext_err_e Error = TETHERING_EXT_ERR_NONE;
+
+ Error = _tethering_ext_dbus_set_wifi_tethering_mode_with_params(tethering_ctx, enable);
+ if (Error != TETHERING_EXT_ERR_NONE)
+ LOGE("Failed to set tethering mode(%d), Error[%s])",
+ enable, tethering_ext_err_to_str(Error));
+
+ // __TETHERING_EXT_CAPI_FUNC_EXIT__;
+ return Error;
+}
+
+
+int _tethering_ext_get_wifi_tethering_mode(tethering_ext_h tethering_context, bool *is_enabled) {
+ // __TETHERING_EXT_CAPI_FUNC_ENTER__;
+ _tethering_ext_h *tethering_ctx = (_tethering_ext_h *) tethering_context;
+ _tethering_ext_err_e Error = TETHERING_EXT_ERR_NONE;
+ _tethering_ext_state_e tethering_state = TETHERING_EXT_STATE_DISABLED;
+
+ Error = _tethering_ext_dbus_get_wifi_tethering_state(tethering_ctx, &tethering_state);
+ if (Error != TETHERING_EXT_ERR_NONE)
+ LOGE("Failed to get tethering state [%s]", tethering_ext_err_to_str(Error));
+ else {
+ if (tethering_state == TETHERING_EXT_STATE_ENABLED) {
+ *is_enabled = true;
+ } else {
+ *is_enabled = false;
+ }
+ tethering_ctx->tethering_ext_state = tethering_state;
+ }
+ // __TETHERING_EXT_CAPI_FUNC_EXIT__;
+ return Error;
+}
+
+int _tethering_ext_set_config(tethering_ext_h tethering_context, void *src_config, int type) {
+ int Error = TETHERING_EXT_ERR_NONE;
+ _tethering_ext_h *tethering_ctx = (_tethering_ext_h *) tethering_context;
+ tethering_ext_config_h *target_config = &(tethering_ctx->tethering_ext_config);
+
+ switch (type) {
+ case TETHERING_EXT_SSID | TETHERING_EXT_PASSPHRASE:
+ {
+ const char *ssid = (const char *) src_config;
+ size_t length = sizeof(ssid);
+ strncpy(target_config->ssid, ssid, length);
+ target_config->ssid[length + 1] = 0;
+ break;
+ }
+ case TETHERING_EXT_PASSPHRASE:
+ {
+ const char *passphrase = (const char *) src_config;
+ size_t length = sizeof(passphrase);
+ strncpy(target_config->passphrase, passphrase, length);
+ target_config->passphrase[length + 1] = 0;
+ break;
+ }
+ case TETHERING_EXT_CHANNEL:
+ target_config->channel = *((int *) src_config);
+ break;
+ default:
+ LOGE("Unknown type %d", type);
+ Error = TETHERING_ERROR_INVALID_PARAMETER;
+ break;
+ }
+ return Error;
+}
+
+int _tethering_ext_get_config(tethering_ext_h tethering_context, void *target_config, int type) {
+ int Error = TETHERING_EXT_ERR_NONE;
+ _tethering_ext_h *tethering_ctx = (_tethering_ext_h *) tethering_context;
+ tethering_ext_config_h *src_config = &(tethering_ctx->tethering_ext_config);
+ switch (type) {
+ case TETHERING_EXT_SSID | TETHERING_EXT_PASSPHRASE:
+ {
+ _tethering_ext_tethering_info *t_info = (_tethering_ext_tethering_info *) target_config;
+ size_t ssid_length = strlen(src_config->ssid);
+ memcpy(t_info->tethering_ssid, src_config->ssid, ssid_length);
+ t_info->tethering_ssid[ssid_length + 1] = 0;
+ break;
+ size_t passphrase_length = strlen(src_config->passphrase);
+ memcpy(t_info->tethering_password, src_config->passphrase, passphrase_length);
+ t_info->tethering_password[passphrase_length + 1] = 0;
+ break;
+ }
+ case TETHERING_EXT_SECURITY_TYPE:
+ {
+ int *security_type = (int *) target_config;
+ if (vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_SECURITY, security_type) < 0) {
+ LOGE("vconf_get_int is failed\n");
+ return TETHERING_EXT_ERR_OPERATION_FAILED;
+ }
+ break;
+ }
+ case TETHERING_EXT_CHANNEL:
+ *((int *) target_config) = src_config->channel;
+ break;
+ case TETHERING_EXT_VISIBLE:
+ {
+ int hide = 0;
+ bool *visible = (bool *) target_config;
+ if (vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_HIDE, &hide) < 0) {
+ LOGE("vconf_get_int is failed\n");
+ return TETHERING_EXT_ERR_OPERATION_FAILED;
+ }
+
+ if (hide)
+ *visible = false;
+ else
+ *visible = true;
+ break;
+ }
+ }
+ return Error;
+}
+
+int _tethering_ext_client_clone(_tethering_ext_client_h *dest, _tethering_ext_client_h origin) {
+ // CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE);
+
+ if (dest == NULL) {
+ LOGE("Parameter(dest) is NULL\n");
+ return TETHERING_EXT_ERR_INVALID_PARAM;
+ }
+
+ if (origin == NULL) {
+ LOGE("Parameter(origin) is NULL\n");
+ return TETHERING_EXT_ERR_INVALID_PARAM;
+ }
+
+
+ _tethering_ext_client_info_h *si = NULL;
+ _tethering_ext_client_info_h *source = NULL;
+
+ source = (_tethering_ext_client_info_h *)origin;
+
+ si = malloc(sizeof(_tethering_ext_client_info_h));
+ if (si == NULL) {
+ LOGE("malloc is failed\n");
+ return TETHERING_EXT_ERR_OUT_OF_MEMORY;
+ }
+
+ memcpy(si, source, sizeof(_tethering_ext_client_info_h));
+ si->hostname = g_strdup(source->hostname);
+ if (si->hostname == NULL) {
+ LOGE("malloc is failed\n");
+ free(si);
+ return TETHERING_EXT_ERR_OUT_OF_MEMORY;
+ }
+
+ *dest = (_tethering_ext_client_h)si;
+
+ return TETHERING_EXT_ERR_NONE;
+}
+
+int _tethering_ext_client_get_name(_tethering_ext_client_h client, char **name)
+{
+ if(client == NULL) {
+ LOGE("Parameter(client) is NULL\n");
+ return TETHERING_EXT_ERR_INVALID_PARAM;
+ }
+ if(name == NULL) {
+ LOGE("Parameter(name) is NULL\n");
+ return TETHERING_EXT_ERR_INVALID_PARAM;
+ }
+
+ _tethering_ext_client_info_h *si = (_tethering_ext_client_info_h *)client;
+
+ *name = strdup(si->hostname);
+ if (*name == NULL) {
+ LOGE("strdup is failed\n");
+ return TETHERING_EXT_ERR_OUT_OF_MEMORY;
+ }
+
+ return TETHERING_EXT_ERR_NONE;
+}
+
+int _tethering_ext_client_get_ip_address(_tethering_ext_client_h client, char **ip_address)
+{
+ // CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE);
+
+ if(client == NULL) {
+ LOGE("Parameter(client) is NULL\n");
+ return TETHERING_EXT_ERR_INVALID_PARAM;
+ }
+ if(ip_address == NULL) {
+ LOGE("Parameter(ip_address) is NULL\n");
+ return TETHERING_EXT_ERR_INVALID_PARAM;
+ }
+
+ _tethering_ext_client_info_h *si = (_tethering_ext_client_info_h *)client;
+
+ *ip_address = strdup(si->ip);
+ if (*ip_address == NULL) {
+ LOGE("strdup is failed\n");
+ return TETHERING_EXT_ERR_OUT_OF_MEMORY;
+ }
+
+ return TETHERING_EXT_ERR_NONE;
+}
+
+int _tethering_ext_client_get_mac_address(_tethering_ext_client_h client, char **mac_address)
+{
+ // CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE);
+
+ if(client == NULL) {
+ LOGE("Parameter(client) is NULL\n");
+ return TETHERING_EXT_ERR_INVALID_PARAM;
+ }
+ if(mac_address == NULL) {
+ LOGE("Parameter(mac_address) is NULL\n");
+ return TETHERING_EXT_ERR_INVALID_PARAM;
+ }
+
+ _tethering_ext_client_info_h *si = (_tethering_ext_client_info_h *)client;
+
+ *mac_address = strdup(si->mac);
+ if (*mac_address == NULL) {
+ LOGE("strdup is failed\n");
+ return TETHERING_EXT_ERR_OUT_OF_MEMORY;
+ }
+
+ return TETHERING_EXT_ERR_NONE;
+}
+
+int _tethering_ext_client_destroy(_tethering_ext_client_h client)
+{
+ // CHECK_FEATURE_SUPPORTED(TETHERING_FEATURE);
+
+ if(client == NULL){
+ LOGE("Parameter(client) is NULL\n");
+ return TETHERING_EXT_ERR_INVALID_PARAM;
+ }
+
+ _tethering_ext_client_info_h *si = NULL;
+
+ si = (_tethering_ext_client_info_h *)client;
+
+ g_free(si->hostname);
+
+ free(client);
+
+ return TETHERING_EXT_ERR_NONE;
+}
+
+
+void _tethering_ext_register_callbacks(tethering_ext_h tethering_context, _tethering_ext_callback_h callbacks) {
+ _tethering_ext_h *tethering_ctx = (_tethering_ext_h *)tethering_context;
+ if (! tethering_ctx->tethering_ext_callbacks)
+ {
+ return;
+ }
+ tethering_ctx->tethering_ext_callbacks->enabled_cb = callbacks.enabled_cb;
+ tethering_ctx->tethering_ext_callbacks->enabled_user_data = callbacks.enabled_user_data;
+ tethering_ctx->tethering_ext_callbacks->disabled_cb = callbacks.disabled_cb;
+ tethering_ctx->tethering_ext_callbacks->disabled_user_data = callbacks.disabled_user_data;
+ tethering_ctx->tethering_ext_callbacks->changed_cb = callbacks.changed_cb;
+ tethering_ctx->tethering_ext_callbacks->changed_user_data = callbacks.changed_user_data;
+}
\ No newline at end of file