[Bluetooth][OTP] Add object browsing support
[platform/core/connectivity/bluetooth-frwk.git] / bt-otp / bt-otpserver.c
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *              http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 #include <dlog.h>
19 #include <gio/gio.h>
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdint.h>
24 #include <time.h>
25 #include <sys/stat.h>
26 #include <langinfo.h>
27 #include <inttypes.h>
28 #include <errno.h>
29
30 #include "bt-otpserver.h"
31 #include "bluetooth-api.h"
32
33
34 #undef LOG_TAG
35 #define LOG_TAG "BLUETOOTH_OTP"
36
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)
40
41 /* OTP object paths */
42 char *otp_obj_path = NULL;
43 char *otp_feature_obj_path = NULL;
44 char *otp_object_name_obj_path = NULL;
45 char *otp_object_type_obj_path = NULL;
46 char *otp_object_size_obj_path = NULL;
47 char *otp_object_first_created_obj_path = NULL;
48 char *otp_object_last_modified_obj_path = NULL;
49 char *otp_object_id_obj_path = NULL;
50 char *otp_object_prop_obj_path = NULL;
51 char *otp_oacp_obj_path = NULL;
52 char *otp_olcp_obj_path = NULL;
53 char *otp_oacp_desc_obj_path = NULL;
54 char *otp_olcp_desc_obj_path = NULL;
55
56 static GMainLoop *main_loop;
57 GDBusNodeInfo *otp_node_info = NULL;
58 static GDBusConnection *conn;
59 static GDBusConnection *g_conn;
60
61 static int property_sub_id = -1;
62 static int adapter_sub_id = -1;
63 static guint g_owner_id = 0;
64
65 struct otp_char_info {
66         gchar *char_path;
67         gchar *char_value;
68         int value_length;
69 };
70
71 struct indicate_info {
72         uint8_t resp_opcode;
73         uint8_t req_opcode;
74         uint8_t result_code;
75         uint8_t *resp_param;
76 };
77
78 /* Object metadata */
79 struct object_metadata {
80         gchar *name;
81         gchar *type;
82         uint32_t curr_size;
83         uint32_t alloc_size;
84         time_t first_created;
85         time_t last_modified;
86         uint64_t id;
87         uint32_t props;
88 };
89
90 static struct object_metadata *selected_object;
91 static uint64_t object_id = OBJECT_START_ID;
92 static GSList *otp_object_list = NULL;
93 static GSList *otp_char_list = NULL;
94 static guint obj_curr_index;
95 static int adv_handle = 0;
96 static gboolean OLCP_indicate = FALSE;
97 char *directory = NULL;
98 gboolean mutiple_obj_support = false;
99
100 static const gchar otp_introspection_xml[] =
101 "<node name='/'>"
102 "       <interface name='org.projectx.otp_service'>"
103 "               <method name='enable'>"
104 "                       <arg type='s' name='directory'/>"
105 "                       <arg type='i' name='status' direction='out'/>"
106 "               </method>"
107 "               <method name='disable'>"
108 "                       <arg type='i' name='status' direction='out'/>"
109 "               </method>"
110 "       </interface>"
111 "</node>";
112
113 void _bt_otp_deinit_event_receiver(void);
114 void _bt_otp_unregister_interface(void);
115 void update_obj_metadata_charc_value(struct object_metadata *object);
116
117 static void delete_all_objects(void)
118 {
119         GSList *tmp = NULL;
120         for (tmp = otp_object_list; tmp != NULL; tmp = tmp->next) {
121                 if (tmp->data) {
122                         struct object_metadata *obj_info = tmp->data;
123                         if (obj_info->name)
124                                 g_free(obj_info->name);
125                         if (obj_info->type)
126                                 g_free(obj_info->type);
127                         otp_object_list = g_slist_delete_link(otp_object_list, tmp->data);
128                 }
129         }
130         g_slist_free(otp_object_list);
131         otp_object_list = NULL;
132 }
133
134 static void delete_all_characterisitc(void)
135 {
136         GSList *tmp = NULL;
137         for (tmp = otp_char_list; tmp != NULL; tmp = tmp->next) {
138                 if (tmp->data) {
139                         struct otp_char_info *char_info = tmp->data;
140                         if (char_info->char_path)
141                                 g_free(char_info->char_path);
142                         if (char_info->char_value)
143                                 g_free(char_info->char_value);
144                         otp_char_list = g_slist_delete_link(otp_char_list, tmp->data);
145                 }
146         }
147         g_slist_free(otp_char_list);
148         otp_char_list = NULL;
149 }
150
151 void _bt_otp_exit(void)
152 {
153         int ret;
154         BT_DBG("");
155
156         if (otp_char_list)
157                 delete_all_characterisitc();
158
159         if (otp_object_list)
160                 delete_all_objects();
161
162         ret = bluetooth_gatt_deinit();
163         if (ret != BLUETOOTH_ERROR_NONE)
164                 BT_ERR("Failed to Deinit GATT %d", ret);
165
166         _bt_otp_deinit_event_receiver();
167
168         _bt_otp_unregister_interface();
169
170         /* TODO: Advertising is not getting stopped by this API.
171          * This is because OTP_SERVER_DEINIT dbus call is blocking
172          * BT_SET_ADVERTISING_DATA dbus call. But now advertisment
173          * is stopped because of terminated process logic.
174          */
175         ret = bluetooth_set_advertising(adv_handle, FALSE);
176         if (ret != BLUETOOTH_ERROR_NONE)
177                 BT_ERR("Failed to stop ADV %d", ret);
178
179         if (main_loop != NULL) {
180                 g_main_loop_quit(main_loop);
181         }
182 }
183
184 static void _bt_otp_set_char_value(const char *obj_path,
185                                 const char *value, int value_length)
186 {
187         GSList *tmp = NULL;
188
189         if (!value)
190                 return;
191         for (tmp = otp_char_list; tmp != NULL; tmp = tmp->next) {
192                 if (tmp->data) {
193                         struct otp_char_info *char_info = tmp->data;
194                         if (!g_strcmp0(char_info->char_path, obj_path)) {
195                                 char_info->char_value = g_try_realloc(char_info->char_value, value_length);
196                                 if (char_info->char_value) {
197                                         memcpy(char_info->char_value, value, value_length);
198                                         char_info->value_length = value_length;
199                                 }
200                                 return;
201                         }
202                 }
203         }
204         return;
205 }
206
207 int add_new_characteristic(const char *char_uuid, bt_gatt_permission_t perms,
208                 bt_gatt_characteristic_property_t props, char **obj_path)
209 {
210         int ret = BLUETOOTH_ERROR_NONE;
211         struct otp_char_info *char_info = NULL;
212
213         ret = bluetooth_gatt_add_new_characteristic(otp_obj_path,
214                                         char_uuid, perms, props, obj_path);
215         if (ret != BLUETOOTH_ERROR_NONE) {
216                 BT_ERR("Failed to add new char %d", ret);
217                 return ret;
218         }
219
220         char_info = g_new0(struct otp_char_info, 1);
221         char_info->char_path = g_strdup(*obj_path);
222         otp_char_list = g_slist_append(otp_char_list, char_info);
223
224         return ret;
225 }
226
227 static char *_otp_convert_uuid_to_uuid128(const char *uuid)
228 {
229         int len;
230         char *uuid128;
231
232         len = strlen(uuid);
233
234         switch (len) {
235         case 4:
236                 /* UUID 16bits */
237                 uuid128 = g_strdup_printf("0000%s-0000-1000-8000-00805f9b34fb",
238                                                                         uuid);
239                 break;
240
241         case 8:
242                 /* UUID 32bits */
243                 uuid128 = g_strdup_printf("%s-0000-1000-8000-00805f9b34fb",
244                                                                         uuid);
245                 break;
246
247         case 36:
248                 /* UUID 128bits */
249                 uuid128 = strdup(uuid);
250                 break;
251
252         default:
253                 return NULL;
254         }
255
256         return uuid128;
257 }
258
259 int _bt_otp_prepare_ots(void)
260 {
261         BT_DBG("+");
262         int ret = BLUETOOTH_ERROR_NONE;
263         char *service_uuid;
264         char *char_uuid;
265         char *desc_uuid;
266         bt_gatt_characteristic_property_t props;
267         bt_gatt_permission_t perms;
268         char supp_feat[OTP_FEATURE_LENGTH] = { 0x08, 0x00, 0x00, 0x00,
269                                                 0x80, 0x00, 0x00, 0x00 };
270
271         ret = bluetooth_gatt_init();
272         if (ret != BLUETOOTH_ERROR_NONE) {
273                 BT_ERR("Failed to Init GATT %d", ret);
274                 goto fail;
275         }
276
277         service_uuid = _otp_convert_uuid_to_uuid128(OTP_UUID);
278         ret = bluetooth_gatt_add_service(service_uuid, &otp_obj_path);
279         if (ret != BLUETOOTH_ERROR_NONE) {
280                 BT_ERR("Failed to add service %d", ret);
281                 goto fail;
282         }
283
284         /* Characteristic OTP Feature */
285         props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
286         perms = BLUETOOTH_GATT_PERMISSION_READ;
287         char_uuid = _otp_convert_uuid_to_uuid128(OTP_FEATURE_UUID);
288         ret = add_new_characteristic(char_uuid, perms, props,
289                                                 &otp_feature_obj_path);
290         if (ret != BLUETOOTH_ERROR_NONE)
291                 goto fail;
292
293         ret = bluetooth_gatt_set_characteristic_value(otp_feature_obj_path,
294                                                 supp_feat, OTP_FEATURE_LENGTH);
295         if (ret != BLUETOOTH_ERROR_NONE) {
296                 BT_ERR("Failed to set char value %d", ret);
297                 return ret;
298         }
299
300         _bt_otp_set_char_value(otp_feature_obj_path, supp_feat,
301                                                 OTP_FEATURE_LENGTH);
302
303         /* Characteristic Object Name */
304         props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
305         perms = BLUETOOTH_GATT_PERMISSION_READ;
306         char_uuid = _otp_convert_uuid_to_uuid128(OTP_OBJECT_NAME_UUID);
307         ret = add_new_characteristic(char_uuid, perms, props,
308                                         &otp_object_name_obj_path);
309         if (ret != BLUETOOTH_ERROR_NONE)
310                 goto fail;
311
312         /* Characteristic Object Type */
313         props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
314         perms = BLUETOOTH_GATT_PERMISSION_READ;
315         char_uuid = _otp_convert_uuid_to_uuid128(OTP_OBJECT_TYPE_UUID);
316         ret = add_new_characteristic(char_uuid, perms, props,
317                                         &otp_object_type_obj_path);
318         if (ret != BLUETOOTH_ERROR_NONE)
319                 goto fail;
320
321         /* Characteristic Object Size */
322         props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
323         perms = BLUETOOTH_GATT_PERMISSION_READ;
324         char_uuid = _otp_convert_uuid_to_uuid128(OTP_OBJECT_SIZE_UUID);
325         ret = add_new_characteristic(char_uuid, perms, props,
326                                         &otp_object_size_obj_path);
327         if (ret != BLUETOOTH_ERROR_NONE)
328                 goto fail;
329
330         /* Characteristic Object First-Created */
331         props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
332                 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
333         perms = BLUETOOTH_GATT_PERMISSION_READ |
334                 BLUETOOTH_GATT_PERMISSION_WRITE;
335         char_uuid = _otp_convert_uuid_to_uuid128(OTP_OBJECT_FIRST_CREATED_UUID);
336         ret = add_new_characteristic(char_uuid, perms, props,
337                                         &otp_object_first_created_obj_path);
338         if (ret != BLUETOOTH_ERROR_NONE)
339                 goto fail;
340
341         /* Characteristic Object Last-Modified */
342         props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
343                 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
344         perms = BLUETOOTH_GATT_PERMISSION_READ |
345                 BLUETOOTH_GATT_PERMISSION_WRITE;
346         char_uuid = _otp_convert_uuid_to_uuid128(OTP_OBJECT_LAST_MODIFIED_UUID);
347         ret = add_new_characteristic(char_uuid, perms, props,
348                                 &otp_object_last_modified_obj_path);
349         if (ret != BLUETOOTH_ERROR_NONE)
350                 goto fail;
351
352         /* Object ID is mandatory for mutiple object server */
353         if (mutiple_obj_support) {
354                 /* Characteristic Object ID */
355                 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
356                 perms = BLUETOOTH_GATT_PERMISSION_READ;
357                 char_uuid = _otp_convert_uuid_to_uuid128(OTP_OBJECT_ID_UUID);
358                 ret = add_new_characteristic(char_uuid, perms, props,
359                                                 &otp_object_id_obj_path);
360                 if (ret != BLUETOOTH_ERROR_NONE)
361                         goto fail;
362         }
363
364         /* Characteristic Object Properties */
365         props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
366         perms = BLUETOOTH_GATT_PERMISSION_READ;
367         char_uuid = _otp_convert_uuid_to_uuid128(OTP_OBJECT_PROP_UUID);
368         ret = add_new_characteristic(char_uuid, perms, props,
369                                         &otp_object_prop_obj_path);
370         if (ret != BLUETOOTH_ERROR_NONE)
371                 goto fail;
372
373         /* Characteristic OACP */
374         props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE |
375                 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
376         perms = BLUETOOTH_GATT_PERMISSION_WRITE;
377         char_uuid = _otp_convert_uuid_to_uuid128(OTP_OACP_UUID);
378         ret = add_new_characteristic(char_uuid, perms, props,
379                                                 &otp_oacp_obj_path);
380         if (ret != BLUETOOTH_ERROR_NONE)
381                 goto fail;
382
383         /* CCCD for OACP */
384         desc_uuid = _otp_convert_uuid_to_uuid128(OTP_CP_CCC_DESC_UUID);
385         perms = BLUETOOTH_GATT_PERMISSION_READ |
386                 BLUETOOTH_GATT_PERMISSION_WRITE;
387         ret = bluetooth_gatt_add_descriptor(otp_oacp_obj_path, desc_uuid,
388                                                 perms, &otp_oacp_desc_obj_path);
389         if (ret != BLUETOOTH_ERROR_NONE) {
390                 BT_ERR("Failed to add new char descriptor %d", ret);
391                 goto fail;
392         }
393
394         /* OLCP Characteristics is not required
395          * for single object server
396          */
397         if (mutiple_obj_support) {
398                 /* Characteristic OLCP */
399                 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE |
400                         BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
401                 perms = BLUETOOTH_GATT_PERMISSION_WRITE;
402                 char_uuid = _otp_convert_uuid_to_uuid128(OTP_OLCP_UUID);
403                 ret = add_new_characteristic(char_uuid, perms, props,
404                                                         &otp_olcp_obj_path);
405                 if (ret != BLUETOOTH_ERROR_NONE)
406                         goto fail;
407
408                 /* CCCD for OLCP */
409                 desc_uuid = _otp_convert_uuid_to_uuid128(OTP_CP_CCC_DESC_UUID);
410                 perms = BLUETOOTH_GATT_PERMISSION_READ |
411                         BLUETOOTH_GATT_PERMISSION_WRITE;
412                 ret = bluetooth_gatt_add_descriptor(otp_olcp_obj_path, desc_uuid,
413                                                         perms, &otp_olcp_desc_obj_path);
414                 if (ret != BLUETOOTH_ERROR_NONE) {
415                         BT_ERR("Failed to add new char descriptor %d", ret);
416                         goto fail;
417                 }
418         }
419
420         /* Register service */
421         ret = bluetooth_gatt_register_service(otp_obj_path);
422         if (ret != BLUETOOTH_ERROR_NONE) {
423                 BT_ERR("Failed to register service %d", ret);
424                 goto fail;
425         }
426
427         /* Register Application */
428         ret = bluetooth_gatt_register_application();
429         if (ret != BLUETOOTH_ERROR_NONE) {
430                 BT_ERR("Failed to register application %d", ret);
431                 goto fail;
432         }
433
434         BT_DBG("-");
435         return ret;
436
437 fail:
438         delete_all_characterisitc();
439         return ret;
440 }
441
442 int _bt_otp_set_advertising_data(void)
443 {
444         int ret;
445         BT_DBG("");
446
447         /* OTP UUID */
448         guint8 data[4]  = {0x03, 0x02, 0x25, 0x18};
449         bluetooth_advertising_data_t adv;
450
451         BT_DBG("%x %x %x %x", data[0], data[1], data[2], data[3]);
452         memcpy(adv.data, data, sizeof(data));
453         ret = bluetooth_set_advertising_data(adv_handle, &adv, sizeof(data));
454         if (ret != BLUETOOTH_ERROR_NONE) {
455                 BT_ERR("Failed to set ADV data %d", ret);
456                 return ret;
457         }
458
459         ret = bluetooth_set_advertising(adv_handle, TRUE);
460         if (ret != BLUETOOTH_ERROR_NONE) {
461                 BT_ERR("Failed to set ADV %d", ret);
462                 return ret;
463         }
464
465         return 0;
466 }
467
468 static void _bt_otp_method(GDBusConnection *connection,
469                 const gchar *sender,
470                 const gchar *object_path,
471                 const gchar *interface_name,
472                 const gchar *method_name,
473                 GVariant *parameters,
474                 GDBusMethodInvocation *invocation,
475                 gpointer user_data)
476 {
477         BT_DBG("+");
478         int status = BLUETOOTH_ERROR_NONE;
479
480         BT_DBG("Method[%s] Object Path[%s] Interface Name[%s]",
481                         method_name, object_path, interface_name);
482
483         if (g_strcmp0(method_name, "enable") == 0) {
484                 GDir *dir = NULL;
485                 GError *error = NULL;
486                 const gchar *filename = NULL;
487                 char absolute_path[ABSOLUTE_PATH_MAX_LENGTH];
488                 GSList *list = NULL, *l = NULL;
489                 struct stat st;
490                 struct object_metadata *object = NULL;
491
492                 g_variant_get(parameters, "(s)", &directory);
493                 BT_DBG("Directory = [%s]", directory);
494
495                 dir = g_dir_open(directory, 0, &error);
496                 if (!dir) {
497                         BT_ERR("Failed to open directory: %s", error->message);
498                         g_error_free(error);
499                         status = BLUETOOTH_ERROR_INVALID_DIRECTORY;
500                         goto fail;
501                 }
502
503                 while ((filename = g_dir_read_name(dir))) {
504                         list = g_slist_append(list, (gpointer) filename);
505                 }
506
507                 g_dir_close(dir);
508
509                 if (!list) {
510                         BT_DBG("No object found in given directory");
511                         status = BLUETOOTH_ERROR_NO_OBJECTS_FOUND;
512                         goto fail;
513                 }
514
515                 if (g_slist_length(list) > 1)
516                         mutiple_obj_support = true;
517
518                 for (l = list; l != NULL; l = l->next) {
519                         if (!l->data) continue;
520                         snprintf(absolute_path, sizeof(absolute_path), "%s%s", directory,
521                                                         (char *)l->data);
522
523                         BT_INFO("filename: %s, absoulte_path: %s",
524                                         (char *)l->data, absolute_path);
525
526                         if (stat(absolute_path, &st) == -1) {
527                                 BT_INFO("stat failed: (%d)\n", errno);
528                                 continue;
529                         }
530
531                         object = g_new0(struct object_metadata, 1);
532
533                         object->name = g_strdup((const gchar *)l->data);
534                         object->type = _otp_convert_uuid_to_uuid128(UNSUPPORTED_OBJECT_TYPE_UUID);
535                         object->first_created = st.st_ctime;
536                         object->last_modified = st.st_ctime;
537                         object->curr_size = (uint32_t) st.st_size;
538                         object->alloc_size = (uint32_t) st.st_size;
539                         object->id = object_id;
540                         object->props = OBJECT_READ | OBJECT_WRITE;
541
542                         otp_object_list = g_slist_append(otp_object_list,
543                                                                 object);
544
545                         object_id++;
546                 }
547
548                 BT_DBG("preparing");
549                 if (_bt_otp_prepare_ots() != BLUETOOTH_ERROR_NONE) {
550                         BT_ERR("Fail to prepare OTP Proxy");
551                         status = BLUETOOTH_ERROR_INTERNAL;
552                         goto fail;
553                 }
554
555                 /* If single object is supported, make that as
556                  * selected object and update the metadata for the same.
557                  */
558                 if (!mutiple_obj_support) {
559                         BT_INFO("Server supports single object");
560                         selected_object = (struct object_metadata *) g_slist_nth_data(otp_object_list, 0);
561                         update_obj_metadata_charc_value(selected_object);
562                 }
563
564                 BT_DBG("advertsing");
565                 if (_bt_otp_set_advertising_data() != BLUETOOTH_ERROR_NONE) {
566                         BT_ERR("Fail to set advertising data");
567                         status = BLUETOOTH_ERROR_INTERNAL;
568                         goto fail;
569                 }
570 fail:
571                 g_dbus_method_invocation_return_value(invocation,
572                                                 g_variant_new("(i)", status));
573
574         } else if (g_strcmp0(method_name, "disable") == 0) {
575                 g_dbus_method_invocation_return_value(invocation,
576                                                 g_variant_new("(i)", status));
577                 _bt_otp_exit();
578         }
579         BT_DBG("-");
580 }
581
582 static const GDBusInterfaceVTable otp_method_table = {
583         _bt_otp_method,
584         NULL,
585         NULL,
586 };
587
588 static void _bt_otp_on_bus_acquired(GDBusConnection *connection,
589                                 const gchar *name, gpointer user_data)
590 {
591         guint object_id;
592         GError *error = NULL;
593
594         BT_DBG("+");
595
596         g_conn = connection;
597
598         object_id = g_dbus_connection_register_object(connection,
599                                                 BT_OTP_OBJECT_PATH,
600                                                 otp_node_info->interfaces[0],
601                                                 &otp_method_table,
602                                                 NULL, NULL, &error);
603         if (object_id == 0) {
604                 BT_ERR("Failed to register method table: %s", error->message);
605                 g_error_free(error);
606                 g_dbus_node_info_unref(otp_node_info);
607         }
608
609         BT_DBG("-");
610 }
611
612 static void _bt_otp_on_name_acquired(GDBusConnection *connection,
613                                         const gchar     *name,
614                                         gpointer user_data)
615 {
616         BT_DBG("");
617 }
618
619 static void _bt_otp_on_name_lost(GDBusConnection *connection,
620                                 const gchar     *name,
621                                 gpointer user_data)
622 {
623         BT_DBG("");
624         g_object_unref(g_conn);
625         g_conn = NULL;
626         g_dbus_node_info_unref(otp_node_info);
627         g_bus_unown_name(g_owner_id);
628 }
629
630 int _bt_otp_register_interface(void)
631 {
632         BT_DBG("+");
633         GError *error = NULL;
634         guint owner_id;
635
636         otp_node_info = g_dbus_node_info_new_for_xml(otp_introspection_xml, &error);
637         if (!otp_node_info) {
638                 BT_ERR("Failed to install: %s", error->message);
639                 return BLUETOOTH_ERROR_INTERNAL;
640         }
641
642         owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
643                                 BT_OTP_SERVICE_NAME,
644                                 G_BUS_NAME_OWNER_FLAGS_NONE,
645                                 _bt_otp_on_bus_acquired,
646                                 _bt_otp_on_name_acquired,
647                                 _bt_otp_on_name_lost,
648                                 NULL, NULL);
649         g_owner_id = owner_id;
650         BT_DBG("owner_id is [%d]\n", owner_id);
651
652         BT_DBG("-");
653         return BLUETOOTH_ERROR_NONE;
654 }
655
656 void _bt_otp_unregister_interface(void)
657 {
658         BT_DBG("+");
659
660         g_object_unref(g_conn);
661         g_conn = NULL;
662         g_dbus_node_info_unref(otp_node_info);
663         g_bus_unown_name(g_owner_id);
664
665         BT_DBG("-");
666         return;
667 }
668
669
670 void convert_to_hex(struct object_metadata *object, char *type, char *value)
671 {
672         struct tm *tm = NULL;
673
674         BT_DBG("type : %s", type);
675
676         memset(value, 0, 8);
677
678         if (!g_strcmp0(type, "size")) {
679
680                 value[3] = (object->curr_size >> 24) & 0xFF;
681                 value[2] = (object->curr_size >> 16) & 0xFF;
682                 value[1] = (object->curr_size >> 8) & 0xFF;
683                 value[0] = object->curr_size & 0xFF;
684
685                 value[7] = (object->alloc_size >> 24) & 0xFF;
686                 value[6] = (object->alloc_size >> 16) & 0xFF;
687                 value[5] = (object->alloc_size >> 8) & 0xFF;
688                 value[4] = object->alloc_size & 0xFF;
689
690         } else if (!g_strcmp0(type, "date")) {
691
692                 localtime_r(&(object->first_created), tm);
693
694                 value[1] = ((tm->tm_year+1900) >> 8) & 0xFF;
695                 value[0] = (tm->tm_year+1900) & 0xFF;
696                 value[2] = (tm->tm_mon+1) & 0xFF;
697                 value[3] = tm->tm_mday & 0xFF;
698                 value[4] = tm->tm_hour & 0xFF;
699                 value[5] = tm->tm_min & 0xFF;
700                 value[6] = tm->tm_sec & 0xFF;
701
702         } else if (!g_strcmp0(type, "id")) {
703
704                 value[5] = (object->id >> 48) & 0xFF;
705                 value[4] = (object->id >> 32) & 0xFF;
706                 value[3] = (object->id >> 24) & 0xFF;
707                 value[2] = (object->id >> 16) & 0xFF;
708                 value[1] = (object->id >> 8) & 0xFF;
709                 value[0] = object->id & 0xFF;
710
711         } else if (!g_strcmp0(type, "props")) {
712                 value[3] = (object->props >> 24) & 0xFF;
713                 value[2] = (object->props >> 16) & 0xFF;
714                 value[1] = (object->props >> 8) & 0xFF;
715                 value[0] = object->props & 0xFF;
716         }
717 }
718
719 void update_obj_metadata_charc_value(struct object_metadata *object)
720 {
721         /* Value can be of maximum eight bytes */
722         char value[8];
723
724         _bt_otp_set_char_value(otp_object_name_obj_path, object->name,
725                                                         strlen(object->name));
726         _bt_otp_set_char_value(otp_object_type_obj_path, object->type,
727                                                         strlen(object->type));
728
729         convert_to_hex(object, "size", value);
730         _bt_otp_set_char_value(otp_object_size_obj_path, value, 8);
731
732         convert_to_hex(object, "date", value);
733         _bt_otp_set_char_value(otp_object_first_created_obj_path, value, 7);
734         _bt_otp_set_char_value(otp_object_last_modified_obj_path, value, 7);
735
736         /* Object ID is optonal for single object server */
737         if (mutiple_obj_support) {
738                 convert_to_hex(object, "id", value);
739                 _bt_otp_set_char_value(otp_object_id_obj_path, value, 6);
740         }
741
742         convert_to_hex(object, "props", value);
743         _bt_otp_set_char_value(otp_object_prop_obj_path, value, 4);
744 }
745
746 int _bt_otp_olcp_write_cb(char *value, int len, int offset,
747                                         struct indicate_info *info)
748 {
749         int ret = OLCP_SUCCESS;
750         int opcode = value[0];
751         struct object_metadata *object;
752
753         BT_INFO("OLCP Opcode 0x%d", opcode);
754
755         if (!otp_object_list) {
756                 ret = OLCP_NO_OBJ;
757                 goto fail;
758         }
759
760         switch (opcode) {
761         case OLCP_FIRST: {
762                 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, 0);
763                 if (!object) {
764                         ret = OLCP_OUT_OF_BOUNDS;
765                         goto fail;
766                 }
767                 update_obj_metadata_charc_value(object);
768                 selected_object = object;
769                 obj_curr_index = 0;
770         } break;
771         case OLCP_LAST: {
772                 len = g_slist_length(otp_object_list);
773                 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, len-1);
774                 if (!object) {
775                         ret = OLCP_OUT_OF_BOUNDS;
776                         goto fail;
777                 }
778                 update_obj_metadata_charc_value(object);
779                 selected_object = object;
780                 obj_curr_index = len-1;
781         } break;
782         case OLCP_PREVIOUS: {
783                 if (obj_curr_index == 0) {
784                         ret = OLCP_OUT_OF_BOUNDS;
785                         goto fail;
786                 }
787                 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, obj_curr_index-1);
788                 if (!object) {
789                         ret = OLCP_OUT_OF_BOUNDS;
790                         goto fail;
791                 }
792                 update_obj_metadata_charc_value(object);
793                 selected_object = object;
794                 obj_curr_index -= 1;
795         } break;
796         case OLCP_NEXT: {
797                 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, obj_curr_index+1);
798                 if (!object) {
799                         ret = OLCP_OUT_OF_BOUNDS;
800                         goto fail;
801                 }
802                 update_obj_metadata_charc_value(object);
803                 selected_object = object;
804                 obj_curr_index += 1;
805         } break;
806         case OLCP_GOTO:
807         case OLCP_ORDER:
808         case OLCP_REQ_NO_OBJ:
809         case OLCP_CLEAR_MARKING:
810         default:
811                 ret = OLCP_OPCODE_NOT_SUPPORTED;
812                 break;
813         }
814 fail:
815         info->resp_opcode = OLCP_RESPONSE;
816         info->req_opcode = opcode;
817         info->result_code = ret;
818         info->resp_param = NULL;
819         return BLUETOOTH_ERROR_NONE;
820 }
821
822 static struct otp_char_info *otp_get_char_value(const char *path)
823 {
824         GSList *tmp = NULL;
825
826         for (tmp = otp_char_list; tmp != NULL; tmp = tmp->next) {
827                 if (tmp->data) {
828                         struct otp_char_info *char_info = tmp->data;
829                         if (!g_strcmp0(char_info->char_path, path))
830                                 return char_info;
831                 }
832         }
833
834         return NULL;
835 }
836
837 int _bt_otp_read_cb(const char *obj_path, char **value, int *len)
838 {
839         struct otp_char_info *info = NULL;
840
841         if (!obj_path) {
842                 BT_ERR("Wrong Obj path");
843                 return BLUETOOTH_ERROR_INTERNAL;
844         }
845
846         if (g_strcmp0(obj_path, otp_feature_obj_path)) {
847                 if (!selected_object) {
848                         return BLUETOOTH_ERROR_OBJECT_NOT_SELECTED;
849                 }
850         }
851
852         info = otp_get_char_value(obj_path);
853         if (info) {
854                 if (info->char_value == NULL || info->value_length == 0)
855                         return BLUETOOTH_ERROR_INTERNAL;
856
857                 *len = info->value_length;
858                 *value = (char *)malloc(sizeof(char)*(*len));
859                 memcpy(*value, info->char_value, *len);
860
861                 return BLUETOOTH_ERROR_NONE;
862         } else {
863                 return BLUETOOTH_ERROR_INTERNAL;
864         }
865 }
866
867 static void _otp_convert_address_to_hex(bluetooth_device_address_t *addr_hex,
868                                                         const char *addr_str)
869 {
870         int i = 0;
871         unsigned int addr[BLUETOOTH_ADDRESS_LENGTH] = { 0, };
872
873         if (addr_str == NULL || addr_str[0] == '\0')
874                 return;
875
876         i = sscanf(addr_str, "%X:%X:%X:%X:%X:%X", &addr[0], &addr[1],
877                                 &addr[2], &addr[3], &addr[4], &addr[5]);
878         if (i != BLUETOOTH_ADDRESS_LENGTH)
879                 BT_ERR("Invalid format string - [%s]", addr_str);
880
881         for (i = 0; i < BLUETOOTH_ADDRESS_LENGTH; i++)
882                 addr_hex->addr[i] = (unsigned char)addr[i];
883 }
884
885 static void _bt_otp_send_indication(const char *obj_path,
886                                 struct indicate_info *info,
887                                 bluetooth_device_address_t *remote_address)
888 {
889         int ret = BLUETOOTH_ERROR_NONE;
890         char value[7] = {0x00};
891
892         BT_DBG("");
893
894         value[0] = info->resp_opcode & 0xFF;
895         value[1] = info->req_opcode & 0xFF;
896         value[2] = info->result_code & 0xFF;
897         if (info->resp_param) {
898                 value[6] = (info->resp_param[3] >> 24) & 0xFF;
899                 value[5] = (info->resp_param[4] >> 16) & 0xFF;
900                 value[4] = (info->resp_param[5] >> 8) & 0xFF;
901                 value[3] = info->resp_param[6] & 0xFF;
902         }
903
904         BT_DBG("Opcode: %d", value[1]);
905
906         /* Store the status value */
907         _bt_otp_set_char_value(obj_path, value, 7);
908
909         /* Send indication */
910         ret = bluetooth_gatt_server_set_notification(obj_path, remote_address);
911         if (ret != BLUETOOTH_ERROR_NONE) {
912                 BT_ERR("_bt_otp_send_control_point_indication failed");
913                 return;
914         }
915         ret = bluetooth_gatt_update_characteristic(obj_path, value, 7);
916         if (ret != BLUETOOTH_ERROR_NONE) {
917                 BT_ERR("_bt_otp_send_control_point_indication failed");
918                 return;
919         }
920 }
921
922 void _bt_otp_gatt_char_property_changed_event(GVariant *msg,
923                                 const char *path)
924 {
925         int result = BLUETOOTH_ERROR_NONE;
926         GVariantIter value_iter;
927         const char *property = NULL;
928         const char *char_path = NULL;
929         const char *svc_handle = NULL;
930         GVariant *var = NULL;
931         GVariant *val = NULL;
932         g_variant_iter_init(&value_iter, msg);
933
934         while ((g_variant_iter_loop(&value_iter, "{sv}", &property, &var))) {
935
936                 if (property == NULL) {
937                         BT_ERR("Property NULL");
938                         return;
939                 }
940
941                 if (!g_strcmp0(property, "WriteValue")) {
942                         int len = 0;
943                         BT_INFO("WriteValue");
944                         BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
945
946                         if (var) {
947                                 bluetooth_device_address_t addr_hex = { {0,} };
948                                 gchar *addr = NULL;
949                                 guint8 req_id = 1;
950                                 guint16 offset = 0;
951                                 char *value = NULL;
952                                 struct indicate_info info;
953                                 g_variant_get(var, "(&s&s&syq@ay)",
954                                                 &char_path, &svc_handle,
955                                                 &addr, &req_id, &offset, &val);
956
957                                 len = g_variant_get_size(val);
958
959                                 BT_DBG("Len = %d, BT_ADDR = %s", len, addr);
960
961                                 value = (char *) g_variant_get_data(val);
962                                 _otp_convert_address_to_hex(&addr_hex, addr);
963
964                                 if (len != 0) {
965                                         if (!g_strcmp0(char_path, otp_oacp_obj_path)) {
966                                                 /* TODO: Handle OACP Control
967                                                  * Point requests
968                                                  */
969                                         } else if (!g_strcmp0(char_path, otp_olcp_obj_path)) {
970                                                 result = _bt_otp_olcp_write_cb(value, len, offset, &info);
971                                         } else {
972                                                 BT_ERR("Wrong Object Path %s", char_path);
973                                                 result = BLUETOOTH_ERROR_INTERNAL;
974                                         }
975                                         bluetooth_gatt_send_response(req_id,
976                                         BLUETOOTH_GATT_ATT_REQUEST_TYPE_WRITE,
977                                                         result, 0, NULL, 0);
978
979                                         /* Send indication for CPs */
980                                         if (!g_strcmp0(char_path, otp_oacp_obj_path)) {
981                                                 /* Handle OACP Indication */
982                                         } else if (!g_strcmp0(char_path, otp_olcp_obj_path)) {
983                                                 if (OLCP_indicate) {
984                                                         _bt_otp_send_indication(char_path, &info, &addr_hex);
985                                                 }
986                                         }
987                                 } else {
988                                         BT_ERR("Array Len 0");
989                                 }
990                         } else {
991                                 BT_ERR("var==NULL");
992                         }
993                 } else if (!g_strcmp0(property, "ReadValue")) {
994                         gchar *addr = NULL;
995                         guint8 req_id = 1;
996                         guint16 offset = 0;
997                         char *value = NULL;
998                         int len = 0;
999                         result = BLUETOOTH_ERROR_NONE;
1000
1001                         BT_INFO("ReadValue");
1002                         BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
1003
1004                         g_variant_get(var, "(&s&s&syq)", &char_path,
1005                                         &svc_handle, &addr, &req_id, &offset);
1006
1007                         result = _bt_otp_read_cb(char_path, &value, &len);
1008
1009                         if (result != BLUETOOTH_ERROR_NONE) {
1010                                 BT_ERR("ReadValue failed %s", char_path);
1011                                 bluetooth_gatt_send_response(req_id,
1012                                 BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1013                                                 result, offset, NULL, 0);
1014                         } else {
1015                                 bluetooth_gatt_send_response(req_id,
1016                                 BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1017                                                 result, offset, value, len);
1018                                 if (value)
1019                                         g_free(value);
1020                         }
1021                 } else if (!g_strcmp0(property, "NotificationStateChanged")) {
1022                         gboolean indicate = FALSE;
1023
1024                         g_variant_get(var, "(&s&sb)", &char_path,
1025                                                 &svc_handle, &indicate);
1026
1027                         BT_INFO("%s : [%s]", property,
1028                                 indicate ? "StartNotify" : "StopNotify");
1029                         BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
1030
1031                         if (!g_strcmp0(char_path, otp_oacp_obj_path)) {
1032                                 /* Handle OACP notification */
1033                         } else if (!g_strcmp0(char_path, otp_olcp_obj_path)) {
1034                                 OLCP_indicate = indicate;
1035                         }
1036                 }
1037         }
1038         return;
1039 }
1040
1041 void _bt_otp_property_event_filter(GDBusConnection *connection,
1042                                         const gchar *sender_name,
1043                                         const gchar *object_path,
1044                                         const gchar *interface_name,
1045                                         const gchar *signal_name,
1046                                         GVariant *parameters,
1047                                         gpointer user_data)
1048 {
1049         GVariant *value;
1050
1051         if (signal_name == NULL) {
1052                 BT_ERR("Wrong Signal");
1053                 return;
1054         }
1055
1056         if (g_strcmp0(signal_name, PROPERTIES_CHANGED) == 0) {
1057
1058                 g_variant_get(parameters, "(@a{sv}@as)", &value, NULL);
1059                 _bt_otp_gatt_char_property_changed_event(value, object_path);
1060         }
1061 }
1062
1063 void _bt_otp_adapter_event_filter(GDBusConnection *connection,
1064                                         const gchar *sender_name,
1065                                         const gchar *object_path,
1066                                         const gchar *interface_name,
1067                                         const gchar *signal_name,
1068                                         GVariant *parameters,
1069                                         gpointer user_data)
1070 {
1071         if (signal_name == NULL) {
1072                 BT_ERR("Wrong Signal");
1073                 return;
1074         }
1075
1076         BT_INFO("Interface %s, Signal %s", interface_name, signal_name);
1077
1078         if (g_strcmp0(interface_name, BT_OTP_INTERFACE_NAME) == 0) {
1079                 if (strcasecmp(signal_name, BLE_DISABLED) == 0) {
1080                         _bt_otp_exit();
1081                 }
1082         }
1083 }
1084
1085 int _bt_otp_init_event_receiver()
1086 {
1087         BT_DBG("+");
1088         GError *error = NULL;
1089
1090         if (conn == NULL) {
1091                 conn =  g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
1092                 if (error != NULL) {
1093                         BT_ERR("ERROR: Can't get on system bus [%s]",
1094                                                         error->message);
1095                         g_clear_error(&error);
1096                 }
1097         }
1098
1099         property_sub_id = g_dbus_connection_signal_subscribe(conn,
1100                                 NULL,
1101                                 BT_OTP_INTERFACE_NAME,
1102                                 PROPERTIES_CHANGED,
1103                                 BT_OTP_OBJECT_PATH, NULL, 0,
1104                                 _bt_otp_property_event_filter,
1105                                 NULL, NULL);
1106
1107         adapter_sub_id = g_dbus_connection_signal_subscribe(conn,
1108                                 NULL,
1109                                 BT_OTP_INTERFACE_NAME,
1110                                 BLE_DISABLED,
1111                                 BT_OTP_OBJECT_PATH, NULL, 0,
1112                                 _bt_otp_adapter_event_filter,
1113                                 NULL, NULL);
1114
1115         BT_DBG("-");
1116         return 0;
1117 }
1118
1119 void _bt_otp_deinit_event_receiver(void)
1120 {
1121         BT_DBG("+");
1122
1123         g_dbus_connection_signal_unsubscribe(conn, property_sub_id);
1124         g_dbus_connection_signal_unsubscribe(conn, adapter_sub_id);
1125         conn = NULL;
1126
1127         BT_DBG("-");
1128 }
1129
1130 static void _bt_otp_sig_handler(int sig)
1131 {
1132         BT_DBG("+");
1133         switch (sig) {
1134         case SIGTERM:
1135                 BT_DBG("caught signal - sigterm\n");
1136                 break;
1137         case SIGINT:
1138                 BT_DBG("caught signal - sigint\n");
1139                 break;
1140         case SIGKILL:
1141                 BT_DBG("caught signal - sigkill\n");
1142                 break;
1143         default:
1144                 BT_DBG("caught signal %d and ignored\n", sig);
1145                 break;
1146         }
1147         BT_DBG("-");
1148 }
1149
1150 /* OTP Service Main loop */
1151 int main(void)
1152 {
1153         struct sigaction sa;
1154         BT_ERR("Starting the bt-otp daemon");
1155
1156         memset(&sa, 0, sizeof(sa));
1157         sa.sa_handler = _bt_otp_sig_handler;
1158         sa.sa_flags = SA_SIGINFO;
1159         sigaction(SIGINT, &sa, NULL);
1160         sigaction(SIGTERM, &sa, NULL);
1161         sigaction(SIGKILL, &sa, NULL);
1162
1163         if (_bt_otp_register_interface() != BLUETOOTH_ERROR_NONE) {
1164                 BT_ERR("Fail to register otp service");
1165                 return -4;
1166         }
1167
1168         if (_bt_otp_init_event_receiver() != BLUETOOTH_ERROR_NONE) {
1169                 BT_ERR("Fail to init event reciever");
1170                 return -5;
1171         }
1172
1173         main_loop = g_main_loop_new(NULL, FALSE);
1174
1175         g_main_loop_run(main_loop);
1176
1177         BT_DBG("g_main_loop_quit called!");
1178
1179         if (main_loop != NULL) {
1180                 g_main_loop_unref(main_loop);
1181         }
1182
1183         return 0;
1184 }