2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
30 #include "bt-otpserver.h"
31 #include "bluetooth-api.h"
35 #define LOG_TAG "BLUETOOTH_OTP"
37 #define BT_INFO(fmt, arg...) SLOGI(fmt, ##arg)
38 #define BT_ERR(fmt, arg...) SLOGE(fmt, ##arg)
39 #define BT_DBG(fmt, arg...) SLOGD(fmt, ##arg)
41 static GMainLoop *main_loop;
42 GDBusNodeInfo *otp_node_info = NULL;
43 static GDBusConnection *conn;
44 static GDBusConnection *g_conn;
46 static int property_sub_id = -1;
47 static guint g_owner_id = 0;
49 char *directory = NULL;
51 static const gchar otp_introspection_xml[] =
53 " <interface name='org.projectx.otp_service'>"
54 " <method name='enable'>"
55 " <arg type='s' name='directory'/>"
56 " <arg type='i' name='status' direction='out'/>"
58 " <method name='disable'>"
59 " <arg type='i' name='status' direction='out'/>"
64 void _bt_otp_deinit_event_receiver(void);
65 void _bt_otp_unregister_interface(void);
67 void _bt_otp_exit(void)
72 ret = bluetooth_gatt_deinit();
73 if (ret != BLUETOOTH_ERROR_NONE)
74 BT_ERR("Failed to Deinit GATT %d", ret);
76 _bt_otp_deinit_event_receiver();
78 _bt_otp_unregister_interface();
80 if (main_loop != NULL) {
81 g_main_loop_quit(main_loop);
85 static void _bt_otp_method(GDBusConnection *connection,
87 const gchar *object_path,
88 const gchar *interface_name,
89 const gchar *method_name,
91 GDBusMethodInvocation *invocation,
95 int status = BLUETOOTH_ERROR_NONE;
97 BT_DBG("Method[%s] Object Path[%s] Interface Name[%s]",
98 method_name, object_path, interface_name);
100 if (g_strcmp0(method_name, "enable") == 0) {
102 GError *error = NULL;
103 const gchar *filename = NULL;
106 g_variant_get(parameters, "(s)", &directory);
107 BT_DBG("Directory = [%s]", directory);
109 dir = g_dir_open(directory, 0, &error);
111 BT_ERR("Failed to open directory: %s", error->message);
113 status = BLUETOOTH_ERROR_INVALID_DIRECTORY;
117 while ((filename = g_dir_read_name(dir))) {
118 list = g_slist_append(list, (gpointer) filename);
121 /* TODO: Extract metadata from these objects and cache it in internal structure */
123 /* TODO: Expose all OTS Characteristics via RegisterApplication */
125 /* TODO: Advertise with OTS_UUID */
127 g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", status));
129 } else if (g_strcmp0(method_name, "disable") == 0) {
130 g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", status));
136 static const GDBusInterfaceVTable otp_method_table = {
142 static void _bt_otp_on_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
145 GError *error = NULL;
151 object_id = g_dbus_connection_register_object(connection, BT_OTP_OBJECT_PATH,
152 otp_node_info->interfaces[0],
155 if (object_id == 0) {
156 BT_ERR("Failed to register method table: %s", error->message);
158 g_dbus_node_info_unref(otp_node_info);
164 static void _bt_otp_on_name_acquired(GDBusConnection *connection,
171 static void _bt_otp_on_name_lost(GDBusConnection *connection,
176 g_object_unref(g_conn);
178 g_dbus_node_info_unref(otp_node_info);
179 g_bus_unown_name(g_owner_id);
182 int _bt_otp_register_interface(void)
185 GError *error = NULL;
188 otp_node_info = g_dbus_node_info_new_for_xml(otp_introspection_xml, &error);
189 if (!otp_node_info) {
190 BT_ERR("Failed to install: %s", error->message);
191 return BLUETOOTH_ERROR_INTERNAL;
194 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
196 G_BUS_NAME_OWNER_FLAGS_NONE,
197 _bt_otp_on_bus_acquired, _bt_otp_on_name_acquired, _bt_otp_on_name_lost,
199 g_owner_id = owner_id;
200 BT_DBG("owner_id is [%d]\n", owner_id);
203 return BLUETOOTH_ERROR_NONE;
206 void _bt_otp_unregister_interface(void)
210 g_object_unref(g_conn);
212 g_dbus_node_info_unref(otp_node_info);
213 g_bus_unown_name(g_owner_id);
219 void _bt_otp_property_event_filter(GDBusConnection *connection,
220 const gchar *sender_name,
221 const gchar *object_path,
222 const gchar *interface_name,
223 const gchar *signal_name,
224 GVariant *parameters,
229 if (signal_name == NULL) {
230 BT_ERR("Wrong Signal");
234 if (g_strcmp0(signal_name, PROPERTIES_CHANGED) == 0) {
236 g_variant_get(parameters, "(@a{sv}@as)", &value, NULL);
237 /* TODO: Handle READ/WRITE request from client */
241 int _bt_otp_init_event_receiver()
244 GError *error = NULL;
247 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
249 BT_ERR("ERROR: Can't get on system bus [%s]", error->message);
250 g_clear_error(&error);
254 property_sub_id = g_dbus_connection_signal_subscribe(conn,
255 NULL, BT_OTP_INTERFACE_NAME,
256 PROPERTIES_CHANGED, BT_OTP_OBJECT_PATH, NULL, 0,
257 _bt_otp_property_event_filter,
259 BT_DBG("property_sub_id = %d", property_sub_id);
265 void _bt_otp_deinit_event_receiver(void)
269 g_dbus_connection_signal_unsubscribe(conn, property_sub_id);
275 static void _bt_otp_sig_handler(int sig)
280 BT_DBG("caught signal - sigterm\n");
283 BT_DBG("caught signal - sigint\n");
286 BT_DBG("caught signal - sigkill\n");
289 BT_DBG("caught signal %d and ignored\n", sig);
295 /* OTP Service Main loop */
299 BT_ERR("Starting the bt-otp daemon");
301 memset(&sa, 0, sizeof(sa));
302 sa.sa_handler = _bt_otp_sig_handler;
303 sa.sa_flags = SA_SIGINFO;
304 sigaction(SIGINT, &sa, NULL);
305 sigaction(SIGTERM, &sa, NULL);
306 sigaction(SIGKILL, &sa, NULL);
308 if (_bt_otp_register_interface() != BLUETOOTH_ERROR_NONE) {
309 BT_ERR("Fail to register otp service");
313 if (_bt_otp_init_event_receiver() != BLUETOOTH_ERROR_NONE) {
314 BT_ERR("Fail to init event reciever");
318 main_loop = g_main_loop_new(NULL, FALSE);
320 g_main_loop_run(main_loop);
322 BT_DBG("g_main_loop_quit called!");
324 if (main_loop != NULL) {
325 g_main_loop_unref(main_loop);