2bc0f60085bdf44b78d174b1442996b9ab94dc2f
[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                         sprintf(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: %s (%d)\n",
513                                                 strerror(errno), errno);
514                                 continue;
515                         }
516
517                         object = g_new0(struct object_metadata, 1);
518
519                         object->name = g_strdup((const gchar *)l->data);
520                         object->type = _otp_convert_uuid_to_uuid128(UNSUPPORTED_OBJECT_TYPE_UUID);
521                         object->first_created = st.st_ctime;
522                         object->last_modified = st.st_ctime;
523                         object->curr_size = (uint32_t) st.st_size;
524                         object->alloc_size = (uint32_t) st.st_size;
525                         object->id = object_id;
526                         object->props = OBJECT_READ | OBJECT_WRITE;
527
528                         otp_object_list = g_slist_append(otp_object_list,
529                                                                 object);
530
531                         object_id++;
532                 }
533
534                 g_dir_close(dir);
535
536                 BT_DBG("preparing");
537                 if (_bt_otp_prepare_ots() != BLUETOOTH_ERROR_NONE) {
538                         BT_ERR("Fail to prepare OTP Proxy");
539                         status = BLUETOOTH_ERROR_INTERNAL;
540                         goto fail;
541                 }
542
543                 BT_DBG("advertsing");
544                 if (_bt_otp_set_advertising_data() != BLUETOOTH_ERROR_NONE) {
545                         BT_ERR("Fail to set advertising data");
546                         status = BLUETOOTH_ERROR_INTERNAL;
547                         goto fail;
548                 }
549 fail:
550                 g_dbus_method_invocation_return_value(invocation,
551                                                 g_variant_new("(i)", status));
552
553         } else if (g_strcmp0(method_name, "disable") == 0) {
554                 g_dbus_method_invocation_return_value(invocation,
555                                                 g_variant_new("(i)", status));
556                 _bt_otp_exit();
557         }
558         BT_DBG("-");
559 }
560
561 static const GDBusInterfaceVTable otp_method_table = {
562         _bt_otp_method,
563         NULL,
564         NULL,
565 };
566
567 static void _bt_otp_on_bus_acquired(GDBusConnection *connection,
568                                 const gchar *name, gpointer user_data)
569 {
570         guint object_id;
571         GError *error = NULL;
572
573         BT_DBG("+");
574
575         g_conn = connection;
576
577         object_id = g_dbus_connection_register_object(connection,
578                                                 BT_OTP_OBJECT_PATH,
579                                                 otp_node_info->interfaces[0],
580                                                 &otp_method_table,
581                                                 NULL, NULL, &error);
582         if (object_id == 0) {
583                 BT_ERR("Failed to register method table: %s", error->message);
584                 g_error_free(error);
585                 g_dbus_node_info_unref(otp_node_info);
586         }
587
588         BT_DBG("-");
589 }
590
591 static void _bt_otp_on_name_acquired(GDBusConnection *connection,
592                                         const gchar     *name,
593                                         gpointer user_data)
594 {
595         BT_DBG("");
596 }
597
598 static void _bt_otp_on_name_lost(GDBusConnection *connection,
599                                 const gchar     *name,
600                                 gpointer user_data)
601 {
602         BT_DBG("");
603         g_object_unref(g_conn);
604         g_conn = NULL;
605         g_dbus_node_info_unref(otp_node_info);
606         g_bus_unown_name(g_owner_id);
607 }
608
609 int _bt_otp_register_interface(void)
610 {
611         BT_DBG("+");
612         GError *error = NULL;
613         guint owner_id;
614
615         otp_node_info = g_dbus_node_info_new_for_xml(otp_introspection_xml, &error);
616         if (!otp_node_info) {
617                 BT_ERR("Failed to install: %s", error->message);
618                 return BLUETOOTH_ERROR_INTERNAL;
619         }
620
621         owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
622                                 BT_OTP_SERVICE_NAME,
623                                 G_BUS_NAME_OWNER_FLAGS_NONE,
624                                 _bt_otp_on_bus_acquired,
625                                 _bt_otp_on_name_acquired,
626                                 _bt_otp_on_name_lost,
627                                 NULL, NULL);
628         g_owner_id = owner_id;
629         BT_DBG("owner_id is [%d]\n", owner_id);
630
631         BT_DBG("-");
632         return BLUETOOTH_ERROR_NONE;
633 }
634
635 void _bt_otp_unregister_interface(void)
636 {
637         BT_DBG("+");
638
639         g_object_unref(g_conn);
640         g_conn = NULL;
641         g_dbus_node_info_unref(otp_node_info);
642         g_bus_unown_name(g_owner_id);
643
644         BT_DBG("-");
645         return;
646 }
647
648
649 void convert_to_hex(struct object_metadata *object, char *type, char *value)
650 {
651         struct tm *tm;
652
653         BT_DBG("type : %s", type);
654
655         memset(value, 0, 8);
656
657         if (!g_strcmp0(type, "size")) {
658
659                 value[3] = (object->curr_size >> 24) & 0xFF;
660                 value[2] = (object->curr_size >> 16) & 0xFF;
661                 value[1] = (object->curr_size >> 8) & 0xFF;
662                 value[0] = object->curr_size & 0xFF;
663
664                 value[7] = (object->alloc_size >> 24) & 0xFF;
665                 value[6] = (object->alloc_size >> 16) & 0xFF;
666                 value[5] = (object->alloc_size >> 8) & 0xFF;
667                 value[4] = object->alloc_size & 0xFF;
668
669         } else if (!g_strcmp0(type, "date")) {
670
671                 tm = localtime(&(object->first_created));
672
673                 value[1] = ((tm->tm_year+1900) >> 8) & 0xFF;
674                 value[0] = (tm->tm_year+1900) & 0xFF;
675                 value[2] = (tm->tm_mon+1) & 0xFF;
676                 value[3] = tm->tm_mday & 0xFF;
677                 value[4] = tm->tm_hour & 0xFF;
678                 value[5] = tm->tm_min & 0xFF;
679                 value[6] = tm->tm_sec & 0xFF;
680
681         } else if (!g_strcmp0(type, "id")) {
682
683                 value[5] = (object->id >> 48) & 0xFF;
684                 value[4] = (object->id >> 32) & 0xFF;
685                 value[3] = (object->id >> 24) & 0xFF;
686                 value[2] = (object->id >> 16) & 0xFF;
687                 value[1] = (object->id >> 8) & 0xFF;
688                 value[0] = object->id & 0xFF;
689
690         } else if (!g_strcmp0(type, "props")) {
691                 value[3] = (object->props >> 24) & 0xFF;
692                 value[2] = (object->props >> 16) & 0xFF;
693                 value[1] = (object->props >> 8) & 0xFF;
694                 value[0] = object->props & 0xFF;
695         }
696 }
697
698 void update_obj_metadata_charc_value(struct object_metadata *object)
699 {
700         /* Value can be of maximum eight bytes */
701         char value[8];
702
703         _bt_otp_set_char_value(otp_object_name_obj_path, object->name,
704                                                         strlen(object->name));
705         _bt_otp_set_char_value(otp_object_type_obj_path, object->type,
706                                                         strlen(object->type));
707
708         convert_to_hex(object, "size", value);
709         _bt_otp_set_char_value(otp_object_size_obj_path, value, 8);
710
711         convert_to_hex(object, "date", value);
712         _bt_otp_set_char_value(otp_object_first_created_obj_path, value, 7);
713         _bt_otp_set_char_value(otp_object_last_modified_obj_path, value, 7);
714
715         convert_to_hex(object, "id", value);
716         _bt_otp_set_char_value(otp_object_id_obj_path, value, 6);
717
718         convert_to_hex(object, "props", value);
719         _bt_otp_set_char_value(otp_object_prop_obj_path, value, 4);
720 }
721
722 int _bt_otp_olcp_write_cb(char *value, int len, int offset,
723                                         struct indicate_info *info)
724 {
725         int ret = OLCP_SUCCESS;
726         int opcode = value[0];
727         struct object_metadata *object;
728
729         BT_INFO("OLCP Opcode 0x%d", opcode);
730
731         if (!otp_object_list) {
732                 ret = OLCP_NO_OBJ;
733                 goto fail;
734         }
735
736         switch (opcode) {
737         case OLCP_FIRST: {
738                 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, 0);
739                 if (!object) {
740                         ret = OLCP_OUT_OF_BOUNDS;
741                         goto fail;
742                 }
743                 update_obj_metadata_charc_value(object);
744                 selected_object = object;
745                 obj_curr_index = 0;
746         } break;
747         case OLCP_LAST: {
748                 len = g_slist_length(otp_object_list);
749                 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, len-1);
750                 if (!object) {
751                         ret = OLCP_OUT_OF_BOUNDS;
752                         goto fail;
753                 }
754                 update_obj_metadata_charc_value(object);
755                 selected_object = object;
756                 obj_curr_index = len-1;
757         } break;
758         case OLCP_PREVIOUS: {
759                 if (obj_curr_index == 0) {
760                         ret = OLCP_OUT_OF_BOUNDS;
761                         goto fail;
762                 }
763                 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, obj_curr_index-1);
764                 if (!object) {
765                         ret = OLCP_OUT_OF_BOUNDS;
766                         goto fail;
767                 }
768                 update_obj_metadata_charc_value(object);
769                 selected_object = object;
770                 obj_curr_index -= 1;
771         } break;
772         case OLCP_NEXT: {
773                 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, obj_curr_index+1);
774                 if (!object) {
775                         ret = OLCP_OUT_OF_BOUNDS;
776                         goto fail;
777                 }
778                 update_obj_metadata_charc_value(object);
779                 selected_object = object;
780                 obj_curr_index += 1;
781         } break;
782         case OLCP_GOTO:
783         case OLCP_ORDER:
784         case OLCP_REQ_NO_OBJ:
785         case OLCP_CLEAR_MARKING:
786         default:
787                 ret = OLCP_OPCODE_NOT_SUPPORTED;
788                 break;
789         }
790 fail:
791         info->resp_opcode = OLCP_RESPONSE;
792         info->req_opcode = opcode;
793         info->result_code = ret;
794         info->resp_param = NULL;
795         return BLUETOOTH_ERROR_NONE;
796 }
797
798 static struct otp_char_info *otp_get_char_value(const char *path)
799 {
800         GSList *tmp = NULL;
801
802         for (tmp = otp_char_list; tmp != NULL; tmp = tmp->next) {
803                 if (tmp->data) {
804                         struct otp_char_info *char_info = tmp->data;
805                         if (!g_strcmp0(char_info->char_path, path))
806                                 return char_info;
807                 }
808         }
809
810         return NULL;
811 }
812
813 int _bt_otp_read_cb(const char *obj_path, char **value, int *len)
814 {
815         struct otp_char_info *info = NULL;
816
817         if (!obj_path) {
818                 BT_ERR("Wrong Obj path");
819                 return BLUETOOTH_ERROR_INTERNAL;
820         }
821
822         if (g_strcmp0(obj_path, otp_feature_obj_path)) {
823                 if (!selected_object) {
824                         return BLUETOOTH_ERROR_OBJECT_NOT_SELECTED;
825                 }
826         }
827
828         info = otp_get_char_value(obj_path);
829         if (info) {
830                 if (info->char_value == NULL || info->value_length == 0)
831                         return BLUETOOTH_ERROR_INTERNAL;
832
833                 *len = info->value_length;
834                 *value = (char *)malloc(sizeof(char *)*(*len));
835                 memcpy(*value, info->char_value, *len);
836
837                 return BLUETOOTH_ERROR_NONE;
838         } else {
839                 return BLUETOOTH_ERROR_INTERNAL;
840         }
841 }
842
843 static void _otp_convert_address_to_hex(bluetooth_device_address_t *addr_hex,
844                                                         const char *addr_str)
845 {
846         int i = 0;
847         unsigned int addr[BLUETOOTH_ADDRESS_LENGTH] = { 0, };
848
849         if (addr_str == NULL || addr_str[0] == '\0')
850                 return;
851
852         i = sscanf(addr_str, "%X:%X:%X:%X:%X:%X", &addr[0], &addr[1],
853                                 &addr[2], &addr[3], &addr[4], &addr[5]);
854         if (i != BLUETOOTH_ADDRESS_LENGTH)
855                 BT_ERR("Invalid format string - [%s]", addr_str);
856
857         for (i = 0; i < BLUETOOTH_ADDRESS_LENGTH; i++)
858                 addr_hex->addr[i] = (unsigned char)addr[i];
859 }
860
861 static void _bt_otp_send_indication(const char *obj_path,
862                                 struct indicate_info *info,
863                                 bluetooth_device_address_t *remote_address)
864 {
865         int ret = BLUETOOTH_ERROR_NONE;
866         char value[7] = {0x00};
867
868         BT_DBG("");
869
870         value[0] = info->resp_opcode & 0xFF;
871         value[1] = info->req_opcode & 0xFF;
872         value[2] = info->result_code & 0xFF;
873         if (info->resp_param) {
874                 value[6] = (info->resp_param[3] >> 24) & 0xFF;
875                 value[5] = (info->resp_param[4] >> 16) & 0xFF;
876                 value[4] = (info->resp_param[5] >> 8) & 0xFF;
877                 value[3] = info->resp_param[6] & 0xFF;
878         }
879
880         BT_DBG("Opcode: %d", value[1]);
881
882         /* Store the status value */
883         _bt_otp_set_char_value(obj_path, value, 7);
884
885         /* Send indication */
886         ret = bluetooth_gatt_server_set_notification(obj_path, remote_address);
887         if (ret != BLUETOOTH_ERROR_NONE) {
888                 BT_ERR("_bt_otp_send_control_point_indication failed");
889                 return;
890         }
891         ret = bluetooth_gatt_update_characteristic(obj_path, value, 7);
892         if (ret != BLUETOOTH_ERROR_NONE) {
893                 BT_ERR("_bt_otp_send_control_point_indication failed");
894                 return;
895         }
896 }
897
898 void _bt_otp_gatt_char_property_changed_event(GVariant *msg,
899                                 const char *path)
900 {
901         int result = BLUETOOTH_ERROR_NONE;
902         GVariantIter value_iter;
903         const char *property = NULL;
904         const char *char_path = NULL;
905         const char *svc_handle = NULL;
906         GVariant *var = NULL;
907         GVariant *val = NULL;
908         g_variant_iter_init(&value_iter, msg);
909
910         while ((g_variant_iter_loop(&value_iter, "{sv}", &property, &var))) {
911
912                 if (property == NULL) {
913                         BT_ERR("Property NULL");
914                         return;
915                 }
916
917                 if (!g_strcmp0(property, "WriteValue")) {
918                         int len = 0;
919                         BT_INFO("WriteValue");
920                         BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
921
922                         if (var) {
923                                 bluetooth_device_address_t addr_hex = { {0,} };
924                                 gchar *addr = NULL;
925                                 guint8 req_id = 1;
926                                 guint16 offset = 0;
927                                 char *value = NULL;
928                                 struct indicate_info info;
929                                 g_variant_get(var, "(&s&s&syq@ay)",
930                                                 &char_path, &svc_handle,
931                                                 &addr, &req_id, &offset, &val);
932
933                                 len = g_variant_get_size(val);
934
935                                 BT_DBG("Len = %d, BT_ADDR = %s", len, addr);
936
937                                 value = (char *) g_variant_get_data(val);
938                                 _otp_convert_address_to_hex(&addr_hex, addr);
939
940                                 if (len != 0) {
941                                         if (!g_strcmp0(char_path, otp_oacp_obj_path)) {
942                                                 /* TODO: Handle OACP Control
943                                                  * Point requests
944                                                  */
945                                         } else if (!g_strcmp0(char_path, otp_olcp_obj_path)) {
946                                                 result = _bt_otp_olcp_write_cb(value, len, offset, &info);
947                                         } else {
948                                                 BT_ERR("Wrong Object Path %s", char_path);
949                                                 result = BLUETOOTH_ERROR_INTERNAL;
950                                         }
951                                         bluetooth_gatt_send_response(req_id,
952                                         BLUETOOTH_GATT_ATT_REQUEST_TYPE_WRITE,
953                                                         result, 0, NULL, 0);
954
955                                         /* Send indication for CPs */
956                                         if (!g_strcmp0(char_path, otp_oacp_obj_path)) {
957                                                 /* Handle OACP Indication */
958                                         } else if (!g_strcmp0(char_path, otp_olcp_obj_path)) {
959                                                 if (OLCP_indicate) {
960                                                         _bt_otp_send_indication(char_path, &info, &addr_hex);
961                                                 }
962                                         }
963                                 } else {
964                                         BT_ERR("Array Len 0");
965                                 }
966                         } else {
967                                 BT_ERR("var==NULL");
968                         }
969                 } else if (!g_strcmp0(property, "ReadValue")) {
970                         gchar *addr = NULL;
971                         guint8 req_id = 1;
972                         guint16 offset = 0;
973                         char *value = NULL;
974                         int len = 0;
975                         result = BLUETOOTH_ERROR_NONE;
976
977                         BT_INFO("ReadValue");
978                         BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
979
980                         g_variant_get(var, "(&s&s&syq)", &char_path,
981                                         &svc_handle, &addr, &req_id, &offset);
982
983                         result = _bt_otp_read_cb(char_path, &value, &len);
984
985                         if (result != BLUETOOTH_ERROR_NONE) {
986                                 BT_ERR("ReadValue failed %s", char_path);
987                                 bluetooth_gatt_send_response(req_id,
988                                 BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
989                                                 result, offset, NULL, 0);
990                         } else {
991                                 bluetooth_gatt_send_response(req_id,
992                                 BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
993                                                 result, offset, value, len);
994                                 if (value)
995                                         g_free(value);
996                         }
997                 } else if (!g_strcmp0(property, "NotificationStateChanged")) {
998                         gboolean indicate = FALSE;
999
1000                         g_variant_get(var, "(&s&sb)", &char_path,
1001                                                 &svc_handle, &indicate);
1002
1003                         BT_INFO("%s : [%s]", property,
1004                                 indicate ? "StartNotify" : "StopNotify");
1005                         BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
1006
1007                         if (!g_strcmp0(char_path, otp_oacp_obj_path)) {
1008                                 /* Handle OACP notification */
1009                         } else if (!g_strcmp0(char_path, otp_olcp_obj_path)) {
1010                                 OLCP_indicate = indicate;
1011                         }
1012                 }
1013         }
1014         return;
1015 }
1016
1017 void _bt_otp_property_event_filter(GDBusConnection *connection,
1018                                         const gchar *sender_name,
1019                                         const gchar *object_path,
1020                                         const gchar *interface_name,
1021                                         const gchar *signal_name,
1022                                         GVariant *parameters,
1023                                         gpointer user_data)
1024 {
1025         GVariant *value;
1026
1027         if (signal_name == NULL) {
1028                 BT_ERR("Wrong Signal");
1029                 return;
1030         }
1031
1032         if (g_strcmp0(signal_name, PROPERTIES_CHANGED) == 0) {
1033
1034                 g_variant_get(parameters, "(@a{sv}@as)", &value, NULL);
1035                 _bt_otp_gatt_char_property_changed_event(value, object_path);
1036         }
1037 }
1038
1039 void _bt_otp_adapter_event_filter(GDBusConnection *connection,
1040                                         const gchar *sender_name,
1041                                         const gchar *object_path,
1042                                         const gchar *interface_name,
1043                                         const gchar *signal_name,
1044                                         GVariant *parameters,
1045                                         gpointer user_data)
1046 {
1047         if (signal_name == NULL) {
1048                 BT_ERR("Wrong Signal");
1049                 return;
1050         }
1051
1052         BT_INFO("Interface %s, Signal %s", interface_name, signal_name);
1053
1054         if (g_strcmp0(interface_name, BT_OTP_INTERFACE_NAME) == 0) {
1055                 if (strcasecmp(signal_name, BLE_DISABLED) == 0) {
1056                         _bt_otp_exit();
1057                 }
1058         }
1059 }
1060
1061 int _bt_otp_init_event_receiver()
1062 {
1063         BT_DBG("+");
1064         GError *error = NULL;
1065
1066         if (conn == NULL) {
1067                 conn =  g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
1068                 if (error != NULL) {
1069                         BT_ERR("ERROR: Can't get on system bus [%s]",
1070                                                         error->message);
1071                         g_clear_error(&error);
1072                 }
1073         }
1074
1075         property_sub_id = g_dbus_connection_signal_subscribe(conn,
1076                                 NULL,
1077                                 BT_OTP_INTERFACE_NAME,
1078                                 PROPERTIES_CHANGED,
1079                                 BT_OTP_OBJECT_PATH, NULL, 0,
1080                                 _bt_otp_property_event_filter,
1081                                 NULL, NULL);
1082
1083         adapter_sub_id = g_dbus_connection_signal_subscribe(conn,
1084                                 NULL,
1085                                 BT_OTP_INTERFACE_NAME,
1086                                 BLE_DISABLED,
1087                                 BT_OTP_OBJECT_PATH, NULL, 0,
1088                                 _bt_otp_adapter_event_filter,
1089                                 NULL, NULL);
1090
1091         BT_DBG("-");
1092         return 0;
1093 }
1094
1095 void _bt_otp_deinit_event_receiver(void)
1096 {
1097         BT_DBG("+");
1098
1099         g_dbus_connection_signal_unsubscribe(conn, property_sub_id);
1100         g_dbus_connection_signal_unsubscribe(conn, adapter_sub_id);
1101         conn = NULL;
1102
1103         BT_DBG("-");
1104 }
1105
1106 static void _bt_otp_sig_handler(int sig)
1107 {
1108         BT_DBG("+");
1109         switch (sig) {
1110         case SIGTERM:
1111                 BT_DBG("caught signal - sigterm\n");
1112                 break;
1113         case SIGINT:
1114                 BT_DBG("caught signal - sigint\n");
1115                 break;
1116         case SIGKILL:
1117                 BT_DBG("caught signal - sigkill\n");
1118                 break;
1119         default:
1120                 BT_DBG("caught signal %d and ignored\n", sig);
1121                 break;
1122         }
1123         BT_DBG("-");
1124 }
1125
1126 /* OTP Service Main loop */
1127 int main(void)
1128 {
1129         struct sigaction sa;
1130         BT_ERR("Starting the bt-otp daemon");
1131
1132         memset(&sa, 0, sizeof(sa));
1133         sa.sa_handler = _bt_otp_sig_handler;
1134         sa.sa_flags = SA_SIGINFO;
1135         sigaction(SIGINT, &sa, NULL);
1136         sigaction(SIGTERM, &sa, NULL);
1137         sigaction(SIGKILL, &sa, NULL);
1138
1139         if (_bt_otp_register_interface() != BLUETOOTH_ERROR_NONE) {
1140                 BT_ERR("Fail to register otp service");
1141                 return -4;
1142         }
1143
1144         if (_bt_otp_init_event_receiver() != BLUETOOTH_ERROR_NONE) {
1145                 BT_ERR("Fail to init event reciever");
1146                 return -5;
1147         }
1148
1149         main_loop = g_main_loop_new(NULL, FALSE);
1150
1151         g_main_loop_run(main_loop);
1152
1153         BT_DBG("g_main_loop_quit called!");
1154
1155         if (main_loop != NULL) {
1156                 g_main_loop_unref(main_loop);
1157         }
1158
1159         return 0;
1160 }