9501f3eeba7be5d97cd12205b16c6e5a5aaed974
[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                 if (tm) {
695                         value[1] = ((tm->tm_year+1900) >> 8) & 0xFF;
696                         value[0] = (tm->tm_year+1900) & 0xFF;
697                         value[2] = (tm->tm_mon+1) & 0xFF;
698                         value[3] = tm->tm_mday & 0xFF;
699                         value[4] = tm->tm_hour & 0xFF;
700                         value[5] = tm->tm_min & 0xFF;
701                         value[6] = tm->tm_sec & 0xFF;
702                 }
703
704         } else if (!g_strcmp0(type, "id")) {
705
706                 value[5] = (object->id >> 48) & 0xFF;
707                 value[4] = (object->id >> 32) & 0xFF;
708                 value[3] = (object->id >> 24) & 0xFF;
709                 value[2] = (object->id >> 16) & 0xFF;
710                 value[1] = (object->id >> 8) & 0xFF;
711                 value[0] = object->id & 0xFF;
712
713         } else if (!g_strcmp0(type, "props")) {
714                 value[3] = (object->props >> 24) & 0xFF;
715                 value[2] = (object->props >> 16) & 0xFF;
716                 value[1] = (object->props >> 8) & 0xFF;
717                 value[0] = object->props & 0xFF;
718         }
719 }
720
721 void update_obj_metadata_charc_value(struct object_metadata *object)
722 {
723         /* Value can be of maximum eight bytes */
724         char value[8];
725
726         _bt_otp_set_char_value(otp_object_name_obj_path, object->name,
727                                                         strlen(object->name));
728         _bt_otp_set_char_value(otp_object_type_obj_path, object->type,
729                                                         strlen(object->type));
730
731         convert_to_hex(object, "size", value);
732         _bt_otp_set_char_value(otp_object_size_obj_path, value, 8);
733
734         convert_to_hex(object, "date", value);
735         _bt_otp_set_char_value(otp_object_first_created_obj_path, value, 7);
736         _bt_otp_set_char_value(otp_object_last_modified_obj_path, value, 7);
737
738         /* Object ID is optonal for single object server */
739         if (mutiple_obj_support) {
740                 convert_to_hex(object, "id", value);
741                 _bt_otp_set_char_value(otp_object_id_obj_path, value, 6);
742         }
743
744         convert_to_hex(object, "props", value);
745         _bt_otp_set_char_value(otp_object_prop_obj_path, value, 4);
746 }
747
748 int _bt_otp_olcp_write_cb(char *value, int len, int offset,
749                                         struct indicate_info *info)
750 {
751         int ret = OLCP_SUCCESS;
752         int opcode = value[0];
753         struct object_metadata *object;
754
755         BT_INFO("OLCP Opcode 0x%d", opcode);
756
757         if (!otp_object_list) {
758                 ret = OLCP_NO_OBJ;
759                 goto fail;
760         }
761
762         switch (opcode) {
763         case OLCP_FIRST: {
764                 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, 0);
765                 if (!object) {
766                         ret = OLCP_OUT_OF_BOUNDS;
767                         goto fail;
768                 }
769                 update_obj_metadata_charc_value(object);
770                 selected_object = object;
771                 obj_curr_index = 0;
772         } break;
773         case OLCP_LAST: {
774                 len = g_slist_length(otp_object_list);
775                 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, len-1);
776                 if (!object) {
777                         ret = OLCP_OUT_OF_BOUNDS;
778                         goto fail;
779                 }
780                 update_obj_metadata_charc_value(object);
781                 selected_object = object;
782                 obj_curr_index = len-1;
783         } break;
784         case OLCP_PREVIOUS: {
785                 if (obj_curr_index == 0) {
786                         ret = OLCP_OUT_OF_BOUNDS;
787                         goto fail;
788                 }
789                 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, obj_curr_index-1);
790                 if (!object) {
791                         ret = OLCP_OUT_OF_BOUNDS;
792                         goto fail;
793                 }
794                 update_obj_metadata_charc_value(object);
795                 selected_object = object;
796                 obj_curr_index -= 1;
797         } break;
798         case OLCP_NEXT: {
799                 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, obj_curr_index+1);
800                 if (!object) {
801                         ret = OLCP_OUT_OF_BOUNDS;
802                         goto fail;
803                 }
804                 update_obj_metadata_charc_value(object);
805                 selected_object = object;
806                 obj_curr_index += 1;
807         } break;
808         case OLCP_GOTO:
809         case OLCP_ORDER:
810         case OLCP_REQ_NO_OBJ:
811         case OLCP_CLEAR_MARKING:
812         default:
813                 ret = OLCP_OPCODE_NOT_SUPPORTED;
814                 break;
815         }
816 fail:
817         info->resp_opcode = OLCP_RESPONSE;
818         info->req_opcode = opcode;
819         info->result_code = ret;
820         info->resp_param = NULL;
821         return BLUETOOTH_ERROR_NONE;
822 }
823
824 static struct otp_char_info *otp_get_char_value(const char *path)
825 {
826         GSList *tmp = NULL;
827
828         for (tmp = otp_char_list; tmp != NULL; tmp = tmp->next) {
829                 if (tmp->data) {
830                         struct otp_char_info *char_info = tmp->data;
831                         if (!g_strcmp0(char_info->char_path, path))
832                                 return char_info;
833                 }
834         }
835
836         return NULL;
837 }
838
839 int _bt_otp_read_cb(const char *obj_path, char **value, int *len)
840 {
841         struct otp_char_info *info = NULL;
842
843         if (!obj_path) {
844                 BT_ERR("Wrong Obj path");
845                 return BLUETOOTH_ERROR_INTERNAL;
846         }
847
848         if (g_strcmp0(obj_path, otp_feature_obj_path)) {
849                 if (!selected_object) {
850                         return BLUETOOTH_ERROR_OBJECT_NOT_SELECTED;
851                 }
852         }
853
854         info = otp_get_char_value(obj_path);
855         if (info) {
856                 if (info->char_value == NULL || info->value_length == 0)
857                         return BLUETOOTH_ERROR_INTERNAL;
858
859                 *len = info->value_length;
860                 *value = (char *)malloc(sizeof(char)*(*len));
861                 memcpy(*value, info->char_value, *len);
862
863                 return BLUETOOTH_ERROR_NONE;
864         } else {
865                 return BLUETOOTH_ERROR_INTERNAL;
866         }
867 }
868
869 static void _otp_convert_address_to_hex(bluetooth_device_address_t *addr_hex,
870                                                         const char *addr_str)
871 {
872         int i = 0;
873         unsigned int addr[BLUETOOTH_ADDRESS_LENGTH] = { 0, };
874
875         if (addr_str == NULL || addr_str[0] == '\0')
876                 return;
877
878         i = sscanf(addr_str, "%X:%X:%X:%X:%X:%X", &addr[0], &addr[1],
879                                 &addr[2], &addr[3], &addr[4], &addr[5]);
880         if (i != BLUETOOTH_ADDRESS_LENGTH)
881                 BT_ERR("Invalid format string - [%s]", addr_str);
882
883         for (i = 0; i < BLUETOOTH_ADDRESS_LENGTH; i++)
884                 addr_hex->addr[i] = (unsigned char)addr[i];
885 }
886
887 static void _bt_otp_send_indication(const char *obj_path,
888                                 struct indicate_info *info,
889                                 bluetooth_device_address_t *remote_address)
890 {
891         int ret = BLUETOOTH_ERROR_NONE;
892         char value[7] = {0x00};
893
894         BT_DBG("");
895
896         value[0] = info->resp_opcode & 0xFF;
897         value[1] = info->req_opcode & 0xFF;
898         value[2] = info->result_code & 0xFF;
899         if (info->resp_param) {
900                 value[6] = (info->resp_param[3] >> 24) & 0xFF;
901                 value[5] = (info->resp_param[4] >> 16) & 0xFF;
902                 value[4] = (info->resp_param[5] >> 8) & 0xFF;
903                 value[3] = info->resp_param[6] & 0xFF;
904         }
905
906         BT_DBG("Opcode: %d", value[1]);
907
908         /* Store the status value */
909         _bt_otp_set_char_value(obj_path, value, 7);
910
911         /* Send indication */
912         ret = bluetooth_gatt_server_set_notification(obj_path, remote_address);
913         if (ret != BLUETOOTH_ERROR_NONE) {
914                 BT_ERR("_bt_otp_send_control_point_indication failed");
915                 return;
916         }
917         ret = bluetooth_gatt_update_characteristic(obj_path, value, 7);
918         if (ret != BLUETOOTH_ERROR_NONE) {
919                 BT_ERR("_bt_otp_send_control_point_indication failed");
920                 return;
921         }
922 }
923
924 void _bt_otp_gatt_char_property_changed_event(GVariant *msg,
925                                 const char *path)
926 {
927         int result = BLUETOOTH_ERROR_NONE;
928         GVariantIter value_iter;
929         const char *property = NULL;
930         const char *char_path = NULL;
931         const char *svc_handle = NULL;
932         GVariant *var = NULL;
933         GVariant *val = NULL;
934         g_variant_iter_init(&value_iter, msg);
935
936         while ((g_variant_iter_loop(&value_iter, "{sv}", &property, &var))) {
937
938                 if (property == NULL) {
939                         BT_ERR("Property NULL");
940                         return;
941                 }
942
943                 if (!g_strcmp0(property, "WriteValue")) {
944                         int len = 0;
945                         BT_INFO("WriteValue");
946                         BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
947
948                         if (var) {
949                                 bluetooth_device_address_t addr_hex = { {0,} };
950                                 gchar *addr = NULL;
951                                 guint8 req_id = 1;
952                                 guint16 offset = 0;
953                                 char *value = NULL;
954                                 struct indicate_info info;
955                                 g_variant_get(var, "(&s&s&syq@ay)",
956                                                 &char_path, &svc_handle,
957                                                 &addr, &req_id, &offset, &val);
958
959                                 len = g_variant_get_size(val);
960
961                                 BT_DBG("Len = %d, BT_ADDR = %s", len, addr);
962
963                                 value = (char *) g_variant_get_data(val);
964                                 _otp_convert_address_to_hex(&addr_hex, addr);
965
966                                 if (len != 0) {
967                                         if (!g_strcmp0(char_path, otp_oacp_obj_path)) {
968                                                 /* TODO: Handle OACP Control
969                                                  * Point requests
970                                                  */
971                                         } else if (!g_strcmp0(char_path, otp_olcp_obj_path)) {
972                                                 result = _bt_otp_olcp_write_cb(value, len, offset, &info);
973                                         } else {
974                                                 BT_ERR("Wrong Object Path %s", char_path);
975                                                 result = BLUETOOTH_ERROR_INTERNAL;
976                                         }
977                                         bluetooth_gatt_send_response(req_id,
978                                         BLUETOOTH_GATT_ATT_REQUEST_TYPE_WRITE,
979                                                         result, 0, NULL, 0);
980
981                                         /* Send indication for CPs */
982                                         if (!g_strcmp0(char_path, otp_oacp_obj_path)) {
983                                                 /* Handle OACP Indication */
984                                         } else if (!g_strcmp0(char_path, otp_olcp_obj_path)) {
985                                                 if (OLCP_indicate) {
986                                                         _bt_otp_send_indication(char_path, &info, &addr_hex);
987                                                 }
988                                         }
989                                 } else {
990                                         BT_ERR("Array Len 0");
991                                 }
992                         } else {
993                                 BT_ERR("var==NULL");
994                         }
995                 } else if (!g_strcmp0(property, "ReadValue")) {
996                         gchar *addr = NULL;
997                         guint8 req_id = 1;
998                         guint16 offset = 0;
999                         char *value = NULL;
1000                         int len = 0;
1001                         result = BLUETOOTH_ERROR_NONE;
1002
1003                         BT_INFO("ReadValue");
1004                         BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
1005
1006                         g_variant_get(var, "(&s&s&syq)", &char_path,
1007                                         &svc_handle, &addr, &req_id, &offset);
1008
1009                         result = _bt_otp_read_cb(char_path, &value, &len);
1010
1011                         if (result != BLUETOOTH_ERROR_NONE) {
1012                                 BT_ERR("ReadValue failed %s", char_path);
1013                                 bluetooth_gatt_send_response(req_id,
1014                                 BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1015                                                 result, offset, NULL, 0);
1016                         } else {
1017                                 bluetooth_gatt_send_response(req_id,
1018                                 BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1019                                                 result, offset, value, len);
1020                                 if (value)
1021                                         g_free(value);
1022                         }
1023                 } else if (!g_strcmp0(property, "NotificationStateChanged")) {
1024                         gboolean indicate = FALSE;
1025
1026                         g_variant_get(var, "(&s&sb)", &char_path,
1027                                                 &svc_handle, &indicate);
1028
1029                         BT_INFO("%s : [%s]", property,
1030                                 indicate ? "StartNotify" : "StopNotify");
1031                         BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
1032
1033                         if (!g_strcmp0(char_path, otp_oacp_obj_path)) {
1034                                 /* Handle OACP notification */
1035                         } else if (!g_strcmp0(char_path, otp_olcp_obj_path)) {
1036                                 OLCP_indicate = indicate;
1037                         }
1038                 }
1039         }
1040         return;
1041 }
1042
1043 void _bt_otp_property_event_filter(GDBusConnection *connection,
1044                                         const gchar *sender_name,
1045                                         const gchar *object_path,
1046                                         const gchar *interface_name,
1047                                         const gchar *signal_name,
1048                                         GVariant *parameters,
1049                                         gpointer user_data)
1050 {
1051         GVariant *value;
1052
1053         if (signal_name == NULL) {
1054                 BT_ERR("Wrong Signal");
1055                 return;
1056         }
1057
1058         if (g_strcmp0(signal_name, PROPERTIES_CHANGED) == 0) {
1059
1060                 g_variant_get(parameters, "(@a{sv}@as)", &value, NULL);
1061                 _bt_otp_gatt_char_property_changed_event(value, object_path);
1062         }
1063 }
1064
1065 void _bt_otp_adapter_event_filter(GDBusConnection *connection,
1066                                         const gchar *sender_name,
1067                                         const gchar *object_path,
1068                                         const gchar *interface_name,
1069                                         const gchar *signal_name,
1070                                         GVariant *parameters,
1071                                         gpointer user_data)
1072 {
1073         if (signal_name == NULL) {
1074                 BT_ERR("Wrong Signal");
1075                 return;
1076         }
1077
1078         BT_INFO("Interface %s, Signal %s", interface_name, signal_name);
1079
1080         if (g_strcmp0(interface_name, BT_OTP_INTERFACE_NAME) == 0) {
1081                 if (strcasecmp(signal_name, BLE_DISABLED) == 0) {
1082                         _bt_otp_exit();
1083                 }
1084         }
1085 }
1086
1087 int _bt_otp_init_event_receiver()
1088 {
1089         BT_DBG("+");
1090         GError *error = NULL;
1091
1092         if (conn == NULL) {
1093                 conn =  g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
1094                 if (error != NULL) {
1095                         BT_ERR("ERROR: Can't get on system bus [%s]",
1096                                                         error->message);
1097                         g_clear_error(&error);
1098                 }
1099         }
1100
1101         property_sub_id = g_dbus_connection_signal_subscribe(conn,
1102                                 NULL,
1103                                 BT_OTP_INTERFACE_NAME,
1104                                 PROPERTIES_CHANGED,
1105                                 BT_OTP_OBJECT_PATH, NULL, 0,
1106                                 _bt_otp_property_event_filter,
1107                                 NULL, NULL);
1108
1109         adapter_sub_id = g_dbus_connection_signal_subscribe(conn,
1110                                 NULL,
1111                                 BT_OTP_INTERFACE_NAME,
1112                                 BLE_DISABLED,
1113                                 BT_OTP_OBJECT_PATH, NULL, 0,
1114                                 _bt_otp_adapter_event_filter,
1115                                 NULL, NULL);
1116
1117         BT_DBG("-");
1118         return 0;
1119 }
1120
1121 void _bt_otp_deinit_event_receiver(void)
1122 {
1123         BT_DBG("+");
1124
1125         g_dbus_connection_signal_unsubscribe(conn, property_sub_id);
1126         g_dbus_connection_signal_unsubscribe(conn, adapter_sub_id);
1127         conn = NULL;
1128
1129         BT_DBG("-");
1130 }
1131
1132 static void _bt_otp_sig_handler(int sig)
1133 {
1134         BT_DBG("+");
1135         switch (sig) {
1136         case SIGTERM:
1137                 BT_DBG("caught signal - sigterm\n");
1138                 break;
1139         case SIGINT:
1140                 BT_DBG("caught signal - sigint\n");
1141                 break;
1142         case SIGKILL:
1143                 BT_DBG("caught signal - sigkill\n");
1144                 break;
1145         default:
1146                 BT_DBG("caught signal %d and ignored\n", sig);
1147                 break;
1148         }
1149         BT_DBG("-");
1150 }
1151
1152 /* OTP Service Main loop */
1153 int main(void)
1154 {
1155         struct sigaction sa;
1156         BT_ERR("Starting the bt-otp daemon");
1157
1158         memset(&sa, 0, sizeof(sa));
1159         sa.sa_handler = _bt_otp_sig_handler;
1160         sa.sa_flags = SA_SIGINFO;
1161         sigaction(SIGINT, &sa, NULL);
1162         sigaction(SIGTERM, &sa, NULL);
1163         sigaction(SIGKILL, &sa, NULL);
1164
1165         if (_bt_otp_register_interface() != BLUETOOTH_ERROR_NONE) {
1166                 BT_ERR("Fail to register otp service");
1167                 return -4;
1168         }
1169
1170         if (_bt_otp_init_event_receiver() != BLUETOOTH_ERROR_NONE) {
1171                 BT_ERR("Fail to init event reciever");
1172                 return -5;
1173         }
1174
1175         main_loop = g_main_loop_new(NULL, FALSE);
1176
1177         g_main_loop_run(main_loop);
1178
1179         BT_DBG("g_main_loop_quit called!");
1180
1181         if (main_loop != NULL) {
1182                 g_main_loop_unref(main_loop);
1183         }
1184
1185         return 0;
1186 }