2 * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
30 #include "bt-otpserver.h"
31 #include "bluetooth-api.h"
35 #define LOG_TAG "BLUETOOTH_OTP"
37 #define BT_INFO(fmt, arg...) SLOGI(fmt, ##arg)
38 #define BT_ERR(fmt, arg...) SLOGE(fmt, ##arg)
39 #define BT_DBG(fmt, arg...) SLOGD(fmt, ##arg)
41 /* 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;
56 static GMainLoop *main_loop;
57 GDBusNodeInfo *otp_node_info = NULL;
58 static GDBusConnection *conn;
59 static GDBusConnection *g_conn;
61 static int property_sub_id = -1;
62 static int adapter_sub_id = -1;
63 static guint g_owner_id = 0;
65 struct otp_char_info {
71 struct indicate_info {
79 struct object_metadata {
90 static struct object_metadata *selected_object;
91 static uint64_t object_id = OBJECT_START_ID;
92 static GSList *otp_object_list = NULL;
93 static GSList *otp_char_list = NULL;
94 static guint obj_curr_index;
95 static int adv_handle = 0;
96 static gboolean OLCP_indicate = FALSE;
97 char *directory = NULL;
98 gboolean mutiple_obj_support = false;
100 static const gchar otp_introspection_xml[] =
102 " <interface name='org.projectx.otp_service'>"
103 " <method name='enable'>"
104 " <arg type='s' name='directory'/>"
105 " <arg type='i' name='status' direction='out'/>"
107 " <method name='disable'>"
108 " <arg type='i' name='status' direction='out'/>"
113 void _bt_otp_deinit_event_receiver(void);
114 void _bt_otp_unregister_interface(void);
115 void update_obj_metadata_charc_value(struct object_metadata *object);
117 static void delete_all_objects(void)
120 for (tmp = otp_object_list; tmp != NULL; tmp = tmp->next) {
122 struct object_metadata *obj_info = tmp->data;
124 g_free(obj_info->name);
126 g_free(obj_info->type);
127 otp_object_list = g_slist_delete_link(otp_object_list, tmp->data);
130 g_slist_free(otp_object_list);
131 otp_object_list = NULL;
134 static void delete_all_characterisitc(void)
137 for (tmp = otp_char_list; tmp != NULL; tmp = tmp->next) {
139 struct otp_char_info *char_info = tmp->data;
140 if (char_info->char_path)
141 g_free(char_info->char_path);
142 if (char_info->char_value)
143 g_free(char_info->char_value);
144 otp_char_list = g_slist_delete_link(otp_char_list, tmp->data);
147 g_slist_free(otp_char_list);
148 otp_char_list = NULL;
151 void _bt_otp_exit(void)
157 delete_all_characterisitc();
160 delete_all_objects();
162 ret = bluetooth_gatt_deinit();
163 if (ret != BLUETOOTH_ERROR_NONE)
164 BT_ERR("Failed to Deinit GATT %d", ret);
166 _bt_otp_deinit_event_receiver();
168 _bt_otp_unregister_interface();
170 /* TODO: Advertising is not getting stopped by this API.
171 * This is because OTP_SERVER_DEINIT dbus call is blocking
172 * BT_SET_ADVERTISING_DATA dbus call. But now advertisment
173 * is stopped because of terminated process logic.
175 ret = bluetooth_set_advertising(adv_handle, FALSE);
176 if (ret != BLUETOOTH_ERROR_NONE)
177 BT_ERR("Failed to stop ADV %d", ret);
179 if (main_loop != NULL) {
180 g_main_loop_quit(main_loop);
184 static void _bt_otp_set_char_value(const char *obj_path,
185 const char *value, int value_length)
191 for (tmp = otp_char_list; tmp != NULL; tmp = tmp->next) {
193 struct otp_char_info *char_info = tmp->data;
194 if (!g_strcmp0(char_info->char_path, obj_path)) {
195 char_info->char_value = g_try_realloc(char_info->char_value, value_length);
196 if (char_info->char_value) {
197 memcpy(char_info->char_value, value, value_length);
198 char_info->value_length = value_length;
207 int add_new_characteristic(const char *char_uuid, bt_gatt_permission_t perms,
208 bt_gatt_characteristic_property_t props, char **obj_path)
210 int ret = BLUETOOTH_ERROR_NONE;
211 struct otp_char_info *char_info = NULL;
213 ret = bluetooth_gatt_add_new_characteristic(otp_obj_path,
214 char_uuid, perms, props, obj_path);
215 if (ret != BLUETOOTH_ERROR_NONE) {
216 BT_ERR("Failed to add new char %d", ret);
220 char_info = g_new0(struct otp_char_info, 1);
221 char_info->char_path = g_strdup(*obj_path);
222 otp_char_list = g_slist_append(otp_char_list, char_info);
227 static char *_otp_convert_uuid_to_uuid128(const char *uuid)
237 uuid128 = g_strdup_printf("0000%s-0000-1000-8000-00805f9b34fb",
243 uuid128 = g_strdup_printf("%s-0000-1000-8000-00805f9b34fb",
249 uuid128 = strdup(uuid);
259 int _bt_otp_prepare_ots(void)
262 int ret = BLUETOOTH_ERROR_NONE;
266 bt_gatt_characteristic_property_t props;
267 bt_gatt_permission_t perms;
268 char supp_feat[OTP_FEATURE_LENGTH] = { 0x08, 0x00, 0x00, 0x00,
269 0x80, 0x00, 0x00, 0x00 };
271 ret = bluetooth_gatt_init();
272 if (ret != BLUETOOTH_ERROR_NONE) {
273 BT_ERR("Failed to Init GATT %d", ret);
277 service_uuid = _otp_convert_uuid_to_uuid128(OTP_UUID);
278 ret = bluetooth_gatt_add_service(service_uuid, &otp_obj_path);
279 if (ret != BLUETOOTH_ERROR_NONE) {
280 BT_ERR("Failed to add service %d", ret);
284 /* Characteristic OTP Feature */
285 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
286 perms = BLUETOOTH_GATT_PERMISSION_READ;
287 char_uuid = _otp_convert_uuid_to_uuid128(OTP_FEATURE_UUID);
288 ret = add_new_characteristic(char_uuid, perms, props,
289 &otp_feature_obj_path);
290 if (ret != BLUETOOTH_ERROR_NONE)
293 ret = bluetooth_gatt_set_characteristic_value(otp_feature_obj_path,
294 supp_feat, OTP_FEATURE_LENGTH);
295 if (ret != BLUETOOTH_ERROR_NONE) {
296 BT_ERR("Failed to set char value %d", ret);
300 _bt_otp_set_char_value(otp_feature_obj_path, supp_feat,
303 /* Characteristic Object Name */
304 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
305 perms = BLUETOOTH_GATT_PERMISSION_READ;
306 char_uuid = _otp_convert_uuid_to_uuid128(OTP_OBJECT_NAME_UUID);
307 ret = add_new_characteristic(char_uuid, perms, props,
308 &otp_object_name_obj_path);
309 if (ret != BLUETOOTH_ERROR_NONE)
312 /* Characteristic Object Type */
313 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
314 perms = BLUETOOTH_GATT_PERMISSION_READ;
315 char_uuid = _otp_convert_uuid_to_uuid128(OTP_OBJECT_TYPE_UUID);
316 ret = add_new_characteristic(char_uuid, perms, props,
317 &otp_object_type_obj_path);
318 if (ret != BLUETOOTH_ERROR_NONE)
321 /* Characteristic Object Size */
322 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
323 perms = BLUETOOTH_GATT_PERMISSION_READ;
324 char_uuid = _otp_convert_uuid_to_uuid128(OTP_OBJECT_SIZE_UUID);
325 ret = add_new_characteristic(char_uuid, perms, props,
326 &otp_object_size_obj_path);
327 if (ret != BLUETOOTH_ERROR_NONE)
330 /* Characteristic Object First-Created */
331 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
332 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
333 perms = BLUETOOTH_GATT_PERMISSION_READ |
334 BLUETOOTH_GATT_PERMISSION_WRITE;
335 char_uuid = _otp_convert_uuid_to_uuid128(OTP_OBJECT_FIRST_CREATED_UUID);
336 ret = add_new_characteristic(char_uuid, perms, props,
337 &otp_object_first_created_obj_path);
338 if (ret != BLUETOOTH_ERROR_NONE)
341 /* Characteristic Object Last-Modified */
342 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ |
343 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE;
344 perms = BLUETOOTH_GATT_PERMISSION_READ |
345 BLUETOOTH_GATT_PERMISSION_WRITE;
346 char_uuid = _otp_convert_uuid_to_uuid128(OTP_OBJECT_LAST_MODIFIED_UUID);
347 ret = add_new_characteristic(char_uuid, perms, props,
348 &otp_object_last_modified_obj_path);
349 if (ret != BLUETOOTH_ERROR_NONE)
352 /* Object ID is mandatory for mutiple object server */
353 if (mutiple_obj_support) {
354 /* Characteristic Object ID */
355 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
356 perms = BLUETOOTH_GATT_PERMISSION_READ;
357 char_uuid = _otp_convert_uuid_to_uuid128(OTP_OBJECT_ID_UUID);
358 ret = add_new_characteristic(char_uuid, perms, props,
359 &otp_object_id_obj_path);
360 if (ret != BLUETOOTH_ERROR_NONE)
364 /* Characteristic Object Properties */
365 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
366 perms = BLUETOOTH_GATT_PERMISSION_READ;
367 char_uuid = _otp_convert_uuid_to_uuid128(OTP_OBJECT_PROP_UUID);
368 ret = add_new_characteristic(char_uuid, perms, props,
369 &otp_object_prop_obj_path);
370 if (ret != BLUETOOTH_ERROR_NONE)
373 /* Characteristic OACP */
374 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE |
375 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
376 perms = BLUETOOTH_GATT_PERMISSION_WRITE;
377 char_uuid = _otp_convert_uuid_to_uuid128(OTP_OACP_UUID);
378 ret = add_new_characteristic(char_uuid, perms, props,
380 if (ret != BLUETOOTH_ERROR_NONE)
384 desc_uuid = _otp_convert_uuid_to_uuid128(OTP_CP_CCC_DESC_UUID);
385 perms = BLUETOOTH_GATT_PERMISSION_READ |
386 BLUETOOTH_GATT_PERMISSION_WRITE;
387 ret = bluetooth_gatt_add_descriptor(otp_oacp_obj_path, desc_uuid,
388 perms, &otp_oacp_desc_obj_path);
389 if (ret != BLUETOOTH_ERROR_NONE) {
390 BT_ERR("Failed to add new char descriptor %d", ret);
394 /* OLCP Characteristics is not required
395 * for single object server
397 if (mutiple_obj_support) {
398 /* Characteristic OLCP */
399 props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE |
400 BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
401 perms = BLUETOOTH_GATT_PERMISSION_WRITE;
402 char_uuid = _otp_convert_uuid_to_uuid128(OTP_OLCP_UUID);
403 ret = add_new_characteristic(char_uuid, perms, props,
405 if (ret != BLUETOOTH_ERROR_NONE)
409 desc_uuid = _otp_convert_uuid_to_uuid128(OTP_CP_CCC_DESC_UUID);
410 perms = BLUETOOTH_GATT_PERMISSION_READ |
411 BLUETOOTH_GATT_PERMISSION_WRITE;
412 ret = bluetooth_gatt_add_descriptor(otp_olcp_obj_path, desc_uuid,
413 perms, &otp_olcp_desc_obj_path);
414 if (ret != BLUETOOTH_ERROR_NONE) {
415 BT_ERR("Failed to add new char descriptor %d", ret);
420 /* Register service */
421 ret = bluetooth_gatt_register_service(otp_obj_path);
422 if (ret != BLUETOOTH_ERROR_NONE) {
423 BT_ERR("Failed to register service %d", ret);
427 /* Register Application */
428 ret = bluetooth_gatt_register_application();
429 if (ret != BLUETOOTH_ERROR_NONE) {
430 BT_ERR("Failed to register application %d", ret);
438 delete_all_characterisitc();
442 int _bt_otp_set_advertising_data(void)
448 guint8 data[4] = {0x03, 0x02, 0x25, 0x18};
449 bluetooth_advertising_data_t adv;
451 BT_DBG("%x %x %x %x", data[0], data[1], data[2], data[3]);
452 memcpy(adv.data, data, sizeof(data));
453 ret = bluetooth_set_advertising_data(adv_handle, &adv, sizeof(data));
454 if (ret != BLUETOOTH_ERROR_NONE) {
455 BT_ERR("Failed to set ADV data %d", ret);
459 ret = bluetooth_set_advertising(adv_handle, TRUE);
460 if (ret != BLUETOOTH_ERROR_NONE) {
461 BT_ERR("Failed to set ADV %d", ret);
468 static void _bt_otp_method(GDBusConnection *connection,
470 const gchar *object_path,
471 const gchar *interface_name,
472 const gchar *method_name,
473 GVariant *parameters,
474 GDBusMethodInvocation *invocation,
478 int status = BLUETOOTH_ERROR_NONE;
480 BT_DBG("Method[%s] Object Path[%s] Interface Name[%s]",
481 method_name, object_path, interface_name);
483 if (g_strcmp0(method_name, "enable") == 0) {
485 GError *error = NULL;
486 const gchar *filename = NULL;
487 char absolute_path[ABSOLUTE_PATH_MAX_LENGTH];
488 GSList *list = NULL, *l = NULL;
490 struct object_metadata *object = NULL;
492 g_variant_get(parameters, "(s)", &directory);
493 BT_DBG("Directory = [%s]", directory);
495 dir = g_dir_open(directory, 0, &error);
497 BT_ERR("Failed to open directory: %s", error->message);
499 status = BLUETOOTH_ERROR_INVALID_DIRECTORY;
503 while ((filename = g_dir_read_name(dir))) {
504 list = g_slist_append(list, (gpointer) filename);
510 BT_DBG("No object found in given directory");
511 status = BLUETOOTH_ERROR_NO_OBJECTS_FOUND;
515 if (g_slist_length(list) > 1)
516 mutiple_obj_support = true;
518 for (l = list; l != NULL; l = l->next) {
519 if (!l->data) continue;
520 snprintf(absolute_path, sizeof(absolute_path), "%s%s", directory,
523 BT_INFO("filename: %s, absoulte_path: %s",
524 (char *)l->data, absolute_path);
526 if (stat(absolute_path, &st) == -1) {
527 BT_INFO("stat failed: (%d)\n", errno);
531 object = g_new0(struct object_metadata, 1);
533 object->name = g_strdup((const gchar *)l->data);
534 object->type = _otp_convert_uuid_to_uuid128(UNSUPPORTED_OBJECT_TYPE_UUID);
535 object->first_created = st.st_ctime;
536 object->last_modified = st.st_ctime;
537 object->curr_size = (uint32_t) st.st_size;
538 object->alloc_size = (uint32_t) st.st_size;
539 object->id = object_id;
540 object->props = OBJECT_READ | OBJECT_WRITE;
542 otp_object_list = g_slist_append(otp_object_list,
549 if (_bt_otp_prepare_ots() != BLUETOOTH_ERROR_NONE) {
550 BT_ERR("Fail to prepare OTP Proxy");
551 status = BLUETOOTH_ERROR_INTERNAL;
555 /* If single object is supported, make that as
556 * selected object and update the metadata for the same.
558 if (!mutiple_obj_support) {
559 BT_INFO("Server supports single object");
560 selected_object = (struct object_metadata *) g_slist_nth_data(otp_object_list, 0);
561 update_obj_metadata_charc_value(selected_object);
564 BT_DBG("advertsing");
565 if (_bt_otp_set_advertising_data() != BLUETOOTH_ERROR_NONE) {
566 BT_ERR("Fail to set advertising data");
567 status = BLUETOOTH_ERROR_INTERNAL;
571 g_dbus_method_invocation_return_value(invocation,
572 g_variant_new("(i)", status));
574 } else if (g_strcmp0(method_name, "disable") == 0) {
575 g_dbus_method_invocation_return_value(invocation,
576 g_variant_new("(i)", status));
582 static const GDBusInterfaceVTable otp_method_table = {
588 static void _bt_otp_on_bus_acquired(GDBusConnection *connection,
589 const gchar *name, gpointer user_data)
592 GError *error = NULL;
598 object_id = g_dbus_connection_register_object(connection,
600 otp_node_info->interfaces[0],
603 if (object_id == 0) {
604 BT_ERR("Failed to register method table: %s", error->message);
606 g_dbus_node_info_unref(otp_node_info);
612 static void _bt_otp_on_name_acquired(GDBusConnection *connection,
619 static void _bt_otp_on_name_lost(GDBusConnection *connection,
624 g_object_unref(g_conn);
626 g_dbus_node_info_unref(otp_node_info);
627 g_bus_unown_name(g_owner_id);
630 int _bt_otp_register_interface(void)
633 GError *error = NULL;
636 otp_node_info = g_dbus_node_info_new_for_xml(otp_introspection_xml, &error);
637 if (!otp_node_info) {
638 BT_ERR("Failed to install: %s", error->message);
639 return BLUETOOTH_ERROR_INTERNAL;
642 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
644 G_BUS_NAME_OWNER_FLAGS_NONE,
645 _bt_otp_on_bus_acquired,
646 _bt_otp_on_name_acquired,
647 _bt_otp_on_name_lost,
649 g_owner_id = owner_id;
650 BT_DBG("owner_id is [%d]\n", owner_id);
653 return BLUETOOTH_ERROR_NONE;
656 void _bt_otp_unregister_interface(void)
660 g_object_unref(g_conn);
662 g_dbus_node_info_unref(otp_node_info);
663 g_bus_unown_name(g_owner_id);
670 void convert_to_hex(struct object_metadata *object, char *type, char *value)
672 struct tm *tm = NULL;
674 BT_DBG("type : %s", type);
678 if (!g_strcmp0(type, "size")) {
680 value[3] = (object->curr_size >> 24) & 0xFF;
681 value[2] = (object->curr_size >> 16) & 0xFF;
682 value[1] = (object->curr_size >> 8) & 0xFF;
683 value[0] = object->curr_size & 0xFF;
685 value[7] = (object->alloc_size >> 24) & 0xFF;
686 value[6] = (object->alloc_size >> 16) & 0xFF;
687 value[5] = (object->alloc_size >> 8) & 0xFF;
688 value[4] = object->alloc_size & 0xFF;
690 } else if (!g_strcmp0(type, "date")) {
692 localtime_r(&(object->first_created), tm);
695 value[1] = ((tm->tm_year+1900) >> 8) & 0xFF;
696 value[0] = (tm->tm_year+1900) & 0xFF;
697 value[2] = (tm->tm_mon+1) & 0xFF;
698 value[3] = tm->tm_mday & 0xFF;
699 value[4] = tm->tm_hour & 0xFF;
700 value[5] = tm->tm_min & 0xFF;
701 value[6] = tm->tm_sec & 0xFF;
704 } else if (!g_strcmp0(type, "id")) {
706 value[5] = (object->id >> 48) & 0xFF;
707 value[4] = (object->id >> 32) & 0xFF;
708 value[3] = (object->id >> 24) & 0xFF;
709 value[2] = (object->id >> 16) & 0xFF;
710 value[1] = (object->id >> 8) & 0xFF;
711 value[0] = object->id & 0xFF;
713 } else if (!g_strcmp0(type, "props")) {
714 value[3] = (object->props >> 24) & 0xFF;
715 value[2] = (object->props >> 16) & 0xFF;
716 value[1] = (object->props >> 8) & 0xFF;
717 value[0] = object->props & 0xFF;
721 void update_obj_metadata_charc_value(struct object_metadata *object)
723 /* Value can be of maximum eight bytes */
726 _bt_otp_set_char_value(otp_object_name_obj_path, object->name,
727 strlen(object->name));
728 _bt_otp_set_char_value(otp_object_type_obj_path, object->type,
729 strlen(object->type));
731 convert_to_hex(object, "size", value);
732 _bt_otp_set_char_value(otp_object_size_obj_path, value, 8);
734 convert_to_hex(object, "date", value);
735 _bt_otp_set_char_value(otp_object_first_created_obj_path, value, 7);
736 _bt_otp_set_char_value(otp_object_last_modified_obj_path, value, 7);
738 /* Object ID is optonal for single object server */
739 if (mutiple_obj_support) {
740 convert_to_hex(object, "id", value);
741 _bt_otp_set_char_value(otp_object_id_obj_path, value, 6);
744 convert_to_hex(object, "props", value);
745 _bt_otp_set_char_value(otp_object_prop_obj_path, value, 4);
748 int _bt_otp_olcp_write_cb(char *value, int len, int offset,
749 struct indicate_info *info)
751 int ret = OLCP_SUCCESS;
752 int opcode = value[0];
753 struct object_metadata *object;
755 BT_INFO("OLCP Opcode 0x%d", opcode);
757 if (!otp_object_list) {
764 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, 0);
766 ret = OLCP_OUT_OF_BOUNDS;
769 update_obj_metadata_charc_value(object);
770 selected_object = object;
774 len = g_slist_length(otp_object_list);
775 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, len-1);
777 ret = OLCP_OUT_OF_BOUNDS;
780 update_obj_metadata_charc_value(object);
781 selected_object = object;
782 obj_curr_index = len-1;
784 case OLCP_PREVIOUS: {
785 if (obj_curr_index == 0) {
786 ret = OLCP_OUT_OF_BOUNDS;
789 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, obj_curr_index-1);
791 ret = OLCP_OUT_OF_BOUNDS;
794 update_obj_metadata_charc_value(object);
795 selected_object = object;
799 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, obj_curr_index+1);
801 ret = OLCP_OUT_OF_BOUNDS;
804 update_obj_metadata_charc_value(object);
805 selected_object = object;
810 case OLCP_REQ_NO_OBJ:
811 case OLCP_CLEAR_MARKING:
813 ret = OLCP_OPCODE_NOT_SUPPORTED;
817 info->resp_opcode = OLCP_RESPONSE;
818 info->req_opcode = opcode;
819 info->result_code = ret;
820 info->resp_param = NULL;
821 return BLUETOOTH_ERROR_NONE;
824 static struct otp_char_info *otp_get_char_value(const char *path)
828 for (tmp = otp_char_list; tmp != NULL; tmp = tmp->next) {
830 struct otp_char_info *char_info = tmp->data;
831 if (!g_strcmp0(char_info->char_path, path))
839 int _bt_otp_read_cb(const char *obj_path, char **value, int *len)
841 struct otp_char_info *info = NULL;
844 BT_ERR("Wrong Obj path");
845 return BLUETOOTH_ERROR_INTERNAL;
848 if (g_strcmp0(obj_path, otp_feature_obj_path)) {
849 if (!selected_object) {
850 return BLUETOOTH_ERROR_OBJECT_NOT_SELECTED;
854 info = otp_get_char_value(obj_path);
856 if (info->char_value == NULL || info->value_length == 0)
857 return BLUETOOTH_ERROR_INTERNAL;
859 *len = info->value_length;
860 *value = (char *)malloc(sizeof(char)*(*len));
861 memcpy(*value, info->char_value, *len);
863 return BLUETOOTH_ERROR_NONE;
865 return BLUETOOTH_ERROR_INTERNAL;
869 static void _otp_convert_address_to_hex(bluetooth_device_address_t *addr_hex,
870 const char *addr_str)
873 unsigned int addr[BLUETOOTH_ADDRESS_LENGTH] = { 0, };
875 if (addr_str == NULL || addr_str[0] == '\0')
878 i = sscanf(addr_str, "%X:%X:%X:%X:%X:%X", &addr[0], &addr[1],
879 &addr[2], &addr[3], &addr[4], &addr[5]);
880 if (i != BLUETOOTH_ADDRESS_LENGTH)
881 BT_ERR("Invalid format string - [%s]", addr_str);
883 for (i = 0; i < BLUETOOTH_ADDRESS_LENGTH; i++)
884 addr_hex->addr[i] = (unsigned char)addr[i];
887 static void _bt_otp_send_indication(const char *obj_path,
888 struct indicate_info *info,
889 bluetooth_device_address_t *remote_address)
891 int ret = BLUETOOTH_ERROR_NONE;
892 char value[7] = {0x00};
896 value[0] = info->resp_opcode & 0xFF;
897 value[1] = info->req_opcode & 0xFF;
898 value[2] = info->result_code & 0xFF;
899 if (info->resp_param) {
900 value[6] = (info->resp_param[3] >> 24) & 0xFF;
901 value[5] = (info->resp_param[4] >> 16) & 0xFF;
902 value[4] = (info->resp_param[5] >> 8) & 0xFF;
903 value[3] = info->resp_param[6] & 0xFF;
906 BT_DBG("Opcode: %d", value[1]);
908 /* Store the status value */
909 _bt_otp_set_char_value(obj_path, value, 7);
911 /* Send indication */
912 ret = bluetooth_gatt_server_set_notification(obj_path, remote_address);
913 if (ret != BLUETOOTH_ERROR_NONE) {
914 BT_ERR("_bt_otp_send_control_point_indication failed");
917 ret = bluetooth_gatt_update_characteristic(obj_path, value, 7);
918 if (ret != BLUETOOTH_ERROR_NONE) {
919 BT_ERR("_bt_otp_send_control_point_indication failed");
924 void _bt_otp_gatt_char_property_changed_event(GVariant *msg,
927 int result = BLUETOOTH_ERROR_NONE;
928 GVariantIter value_iter;
929 const char *property = NULL;
930 const char *char_path = NULL;
931 const char *svc_handle = NULL;
932 GVariant *var = NULL;
933 GVariant *val = NULL;
934 g_variant_iter_init(&value_iter, msg);
936 while ((g_variant_iter_loop(&value_iter, "{sv}", &property, &var))) {
938 if (property == NULL) {
939 BT_ERR("Property NULL");
943 if (!g_strcmp0(property, "WriteValue")) {
945 BT_INFO("WriteValue");
946 BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
949 bluetooth_device_address_t addr_hex = { {0,} };
954 struct indicate_info info;
955 g_variant_get(var, "(&s&s&syq@ay)",
956 &char_path, &svc_handle,
957 &addr, &req_id, &offset, &val);
959 len = g_variant_get_size(val);
961 BT_DBG("Len = %d, BT_ADDR = %s", len, addr);
963 value = (char *) g_variant_get_data(val);
964 _otp_convert_address_to_hex(&addr_hex, addr);
967 if (!g_strcmp0(char_path, otp_oacp_obj_path)) {
968 /* TODO: Handle OACP Control
971 } else if (!g_strcmp0(char_path, otp_olcp_obj_path)) {
972 result = _bt_otp_olcp_write_cb(value, len, offset, &info);
974 BT_ERR("Wrong Object Path %s", char_path);
975 result = BLUETOOTH_ERROR_INTERNAL;
977 bluetooth_gatt_send_response(req_id,
978 BLUETOOTH_GATT_ATT_REQUEST_TYPE_WRITE,
981 /* Send indication for CPs */
982 if (!g_strcmp0(char_path, otp_oacp_obj_path)) {
983 /* Handle OACP Indication */
984 } else if (!g_strcmp0(char_path, otp_olcp_obj_path)) {
986 _bt_otp_send_indication(char_path, &info, &addr_hex);
990 BT_ERR("Array Len 0");
995 } else if (!g_strcmp0(property, "ReadValue")) {
1001 result = BLUETOOTH_ERROR_NONE;
1003 BT_INFO("ReadValue");
1004 BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
1006 g_variant_get(var, "(&s&s&syq)", &char_path,
1007 &svc_handle, &addr, &req_id, &offset);
1009 result = _bt_otp_read_cb(char_path, &value, &len);
1011 if (result != BLUETOOTH_ERROR_NONE) {
1012 BT_ERR("ReadValue failed %s", char_path);
1013 bluetooth_gatt_send_response(req_id,
1014 BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1015 result, offset, NULL, 0);
1017 bluetooth_gatt_send_response(req_id,
1018 BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1019 result, offset, value, len);
1023 } else if (!g_strcmp0(property, "NotificationStateChanged")) {
1024 gboolean indicate = FALSE;
1026 g_variant_get(var, "(&s&sb)", &char_path,
1027 &svc_handle, &indicate);
1029 BT_INFO("%s : [%s]", property,
1030 indicate ? "StartNotify" : "StopNotify");
1031 BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
1033 if (!g_strcmp0(char_path, otp_oacp_obj_path)) {
1034 /* Handle OACP notification */
1035 } else if (!g_strcmp0(char_path, otp_olcp_obj_path)) {
1036 OLCP_indicate = indicate;
1043 void _bt_otp_property_event_filter(GDBusConnection *connection,
1044 const gchar *sender_name,
1045 const gchar *object_path,
1046 const gchar *interface_name,
1047 const gchar *signal_name,
1048 GVariant *parameters,
1053 if (signal_name == NULL) {
1054 BT_ERR("Wrong Signal");
1058 if (g_strcmp0(signal_name, PROPERTIES_CHANGED) == 0) {
1060 g_variant_get(parameters, "(@a{sv}@as)", &value, NULL);
1061 _bt_otp_gatt_char_property_changed_event(value, object_path);
1065 void _bt_otp_adapter_event_filter(GDBusConnection *connection,
1066 const gchar *sender_name,
1067 const gchar *object_path,
1068 const gchar *interface_name,
1069 const gchar *signal_name,
1070 GVariant *parameters,
1073 if (signal_name == NULL) {
1074 BT_ERR("Wrong Signal");
1078 BT_INFO("Interface %s, Signal %s", interface_name, signal_name);
1080 if (g_strcmp0(interface_name, BT_OTP_INTERFACE_NAME) == 0) {
1081 if (strcasecmp(signal_name, BLE_DISABLED) == 0) {
1087 int _bt_otp_init_event_receiver()
1090 GError *error = NULL;
1093 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
1094 if (error != NULL) {
1095 BT_ERR("ERROR: Can't get on system bus [%s]",
1097 g_clear_error(&error);
1101 property_sub_id = g_dbus_connection_signal_subscribe(conn,
1103 BT_OTP_INTERFACE_NAME,
1105 BT_OTP_OBJECT_PATH, NULL, 0,
1106 _bt_otp_property_event_filter,
1109 adapter_sub_id = g_dbus_connection_signal_subscribe(conn,
1111 BT_OTP_INTERFACE_NAME,
1113 BT_OTP_OBJECT_PATH, NULL, 0,
1114 _bt_otp_adapter_event_filter,
1121 void _bt_otp_deinit_event_receiver(void)
1125 g_dbus_connection_signal_unsubscribe(conn, property_sub_id);
1126 g_dbus_connection_signal_unsubscribe(conn, adapter_sub_id);
1132 static void _bt_otp_sig_handler(int sig)
1137 BT_DBG("caught signal - sigterm\n");
1140 BT_DBG("caught signal - sigint\n");
1143 BT_DBG("caught signal - sigkill\n");
1146 BT_DBG("caught signal %d and ignored\n", sig);
1152 /* OTP Service Main loop */
1155 struct sigaction sa;
1156 BT_ERR("Starting the bt-otp daemon");
1158 memset(&sa, 0, sizeof(sa));
1159 sa.sa_handler = _bt_otp_sig_handler;
1160 sa.sa_flags = SA_SIGINFO;
1161 sigaction(SIGINT, &sa, NULL);
1162 sigaction(SIGTERM, &sa, NULL);
1163 sigaction(SIGKILL, &sa, NULL);
1165 if (_bt_otp_register_interface() != BLUETOOTH_ERROR_NONE) {
1166 BT_ERR("Fail to register otp service");
1170 if (_bt_otp_init_event_receiver() != BLUETOOTH_ERROR_NONE) {
1171 BT_ERR("Fail to init event reciever");
1175 main_loop = g_main_loop_new(NULL, FALSE);
1177 g_main_loop_run(main_loop);
1179 BT_DBG("g_main_loop_quit called!");
1181 if (main_loop != NULL) {
1182 g_main_loop_unref(main_loop);