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