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);
694 value[1] = ((tm->tm_year+1900) >> 8) & 0xFF;
695 value[0] = (tm->tm_year+1900) & 0xFF;
696 value[2] = (tm->tm_mon+1) & 0xFF;
697 value[3] = tm->tm_mday & 0xFF;
698 value[4] = tm->tm_hour & 0xFF;
699 value[5] = tm->tm_min & 0xFF;
700 value[6] = tm->tm_sec & 0xFF;
702 } else if (!g_strcmp0(type, "id")) {
704 value[5] = (object->id >> 48) & 0xFF;
705 value[4] = (object->id >> 32) & 0xFF;
706 value[3] = (object->id >> 24) & 0xFF;
707 value[2] = (object->id >> 16) & 0xFF;
708 value[1] = (object->id >> 8) & 0xFF;
709 value[0] = object->id & 0xFF;
711 } else if (!g_strcmp0(type, "props")) {
712 value[3] = (object->props >> 24) & 0xFF;
713 value[2] = (object->props >> 16) & 0xFF;
714 value[1] = (object->props >> 8) & 0xFF;
715 value[0] = object->props & 0xFF;
719 void update_obj_metadata_charc_value(struct object_metadata *object)
721 /* Value can be of maximum eight bytes */
724 _bt_otp_set_char_value(otp_object_name_obj_path, object->name,
725 strlen(object->name));
726 _bt_otp_set_char_value(otp_object_type_obj_path, object->type,
727 strlen(object->type));
729 convert_to_hex(object, "size", value);
730 _bt_otp_set_char_value(otp_object_size_obj_path, value, 8);
732 convert_to_hex(object, "date", value);
733 _bt_otp_set_char_value(otp_object_first_created_obj_path, value, 7);
734 _bt_otp_set_char_value(otp_object_last_modified_obj_path, value, 7);
736 /* Object ID is optonal for single object server */
737 if (mutiple_obj_support) {
738 convert_to_hex(object, "id", value);
739 _bt_otp_set_char_value(otp_object_id_obj_path, value, 6);
742 convert_to_hex(object, "props", value);
743 _bt_otp_set_char_value(otp_object_prop_obj_path, value, 4);
746 int _bt_otp_olcp_write_cb(char *value, int len, int offset,
747 struct indicate_info *info)
749 int ret = OLCP_SUCCESS;
750 int opcode = value[0];
751 struct object_metadata *object;
753 BT_INFO("OLCP Opcode 0x%d", opcode);
755 if (!otp_object_list) {
762 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, 0);
764 ret = OLCP_OUT_OF_BOUNDS;
767 update_obj_metadata_charc_value(object);
768 selected_object = object;
772 len = g_slist_length(otp_object_list);
773 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, len-1);
775 ret = OLCP_OUT_OF_BOUNDS;
778 update_obj_metadata_charc_value(object);
779 selected_object = object;
780 obj_curr_index = len-1;
782 case OLCP_PREVIOUS: {
783 if (obj_curr_index == 0) {
784 ret = OLCP_OUT_OF_BOUNDS;
787 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, obj_curr_index-1);
789 ret = OLCP_OUT_OF_BOUNDS;
792 update_obj_metadata_charc_value(object);
793 selected_object = object;
797 object = (struct object_metadata *) g_slist_nth_data(otp_object_list, obj_curr_index+1);
799 ret = OLCP_OUT_OF_BOUNDS;
802 update_obj_metadata_charc_value(object);
803 selected_object = object;
808 case OLCP_REQ_NO_OBJ:
809 case OLCP_CLEAR_MARKING:
811 ret = OLCP_OPCODE_NOT_SUPPORTED;
815 info->resp_opcode = OLCP_RESPONSE;
816 info->req_opcode = opcode;
817 info->result_code = ret;
818 info->resp_param = NULL;
819 return BLUETOOTH_ERROR_NONE;
822 static struct otp_char_info *otp_get_char_value(const char *path)
826 for (tmp = otp_char_list; tmp != NULL; tmp = tmp->next) {
828 struct otp_char_info *char_info = tmp->data;
829 if (!g_strcmp0(char_info->char_path, path))
837 int _bt_otp_read_cb(const char *obj_path, char **value, int *len)
839 struct otp_char_info *info = NULL;
842 BT_ERR("Wrong Obj path");
843 return BLUETOOTH_ERROR_INTERNAL;
846 if (g_strcmp0(obj_path, otp_feature_obj_path)) {
847 if (!selected_object) {
848 return BLUETOOTH_ERROR_OBJECT_NOT_SELECTED;
852 info = otp_get_char_value(obj_path);
854 if (info->char_value == NULL || info->value_length == 0)
855 return BLUETOOTH_ERROR_INTERNAL;
857 *len = info->value_length;
858 *value = (char *)malloc(sizeof(char)*(*len));
859 memcpy(*value, info->char_value, *len);
861 return BLUETOOTH_ERROR_NONE;
863 return BLUETOOTH_ERROR_INTERNAL;
867 static void _otp_convert_address_to_hex(bluetooth_device_address_t *addr_hex,
868 const char *addr_str)
871 unsigned int addr[BLUETOOTH_ADDRESS_LENGTH] = { 0, };
873 if (addr_str == NULL || addr_str[0] == '\0')
876 i = sscanf(addr_str, "%X:%X:%X:%X:%X:%X", &addr[0], &addr[1],
877 &addr[2], &addr[3], &addr[4], &addr[5]);
878 if (i != BLUETOOTH_ADDRESS_LENGTH)
879 BT_ERR("Invalid format string - [%s]", addr_str);
881 for (i = 0; i < BLUETOOTH_ADDRESS_LENGTH; i++)
882 addr_hex->addr[i] = (unsigned char)addr[i];
885 static void _bt_otp_send_indication(const char *obj_path,
886 struct indicate_info *info,
887 bluetooth_device_address_t *remote_address)
889 int ret = BLUETOOTH_ERROR_NONE;
890 char value[7] = {0x00};
894 value[0] = info->resp_opcode & 0xFF;
895 value[1] = info->req_opcode & 0xFF;
896 value[2] = info->result_code & 0xFF;
897 if (info->resp_param) {
898 value[6] = (info->resp_param[3] >> 24) & 0xFF;
899 value[5] = (info->resp_param[4] >> 16) & 0xFF;
900 value[4] = (info->resp_param[5] >> 8) & 0xFF;
901 value[3] = info->resp_param[6] & 0xFF;
904 BT_DBG("Opcode: %d", value[1]);
906 /* Store the status value */
907 _bt_otp_set_char_value(obj_path, value, 7);
909 /* Send indication */
910 ret = bluetooth_gatt_server_set_notification(obj_path, remote_address);
911 if (ret != BLUETOOTH_ERROR_NONE) {
912 BT_ERR("_bt_otp_send_control_point_indication failed");
915 ret = bluetooth_gatt_update_characteristic(obj_path, value, 7);
916 if (ret != BLUETOOTH_ERROR_NONE) {
917 BT_ERR("_bt_otp_send_control_point_indication failed");
922 void _bt_otp_gatt_char_property_changed_event(GVariant *msg,
925 int result = BLUETOOTH_ERROR_NONE;
926 GVariantIter value_iter;
927 const char *property = NULL;
928 const char *char_path = NULL;
929 const char *svc_handle = NULL;
930 GVariant *var = NULL;
931 GVariant *val = NULL;
932 g_variant_iter_init(&value_iter, msg);
934 while ((g_variant_iter_loop(&value_iter, "{sv}", &property, &var))) {
936 if (property == NULL) {
937 BT_ERR("Property NULL");
941 if (!g_strcmp0(property, "WriteValue")) {
943 BT_INFO("WriteValue");
944 BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
947 bluetooth_device_address_t addr_hex = { {0,} };
952 struct indicate_info info;
953 g_variant_get(var, "(&s&s&syq@ay)",
954 &char_path, &svc_handle,
955 &addr, &req_id, &offset, &val);
957 len = g_variant_get_size(val);
959 BT_DBG("Len = %d, BT_ADDR = %s", len, addr);
961 value = (char *) g_variant_get_data(val);
962 _otp_convert_address_to_hex(&addr_hex, addr);
965 if (!g_strcmp0(char_path, otp_oacp_obj_path)) {
966 /* TODO: Handle OACP Control
969 } else if (!g_strcmp0(char_path, otp_olcp_obj_path)) {
970 result = _bt_otp_olcp_write_cb(value, len, offset, &info);
972 BT_ERR("Wrong Object Path %s", char_path);
973 result = BLUETOOTH_ERROR_INTERNAL;
975 bluetooth_gatt_send_response(req_id,
976 BLUETOOTH_GATT_ATT_REQUEST_TYPE_WRITE,
979 /* Send indication for CPs */
980 if (!g_strcmp0(char_path, otp_oacp_obj_path)) {
981 /* Handle OACP Indication */
982 } else if (!g_strcmp0(char_path, otp_olcp_obj_path)) {
984 _bt_otp_send_indication(char_path, &info, &addr_hex);
988 BT_ERR("Array Len 0");
993 } else if (!g_strcmp0(property, "ReadValue")) {
999 result = BLUETOOTH_ERROR_NONE;
1001 BT_INFO("ReadValue");
1002 BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
1004 g_variant_get(var, "(&s&s&syq)", &char_path,
1005 &svc_handle, &addr, &req_id, &offset);
1007 result = _bt_otp_read_cb(char_path, &value, &len);
1009 if (result != BLUETOOTH_ERROR_NONE) {
1010 BT_ERR("ReadValue failed %s", char_path);
1011 bluetooth_gatt_send_response(req_id,
1012 BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1013 result, offset, NULL, 0);
1015 bluetooth_gatt_send_response(req_id,
1016 BLUETOOTH_GATT_ATT_REQUEST_TYPE_READ,
1017 result, offset, value, len);
1021 } else if (!g_strcmp0(property, "NotificationStateChanged")) {
1022 gboolean indicate = FALSE;
1024 g_variant_get(var, "(&s&sb)", &char_path,
1025 &svc_handle, &indicate);
1027 BT_INFO("%s : [%s]", property,
1028 indicate ? "StartNotify" : "StopNotify");
1029 BT_INFO("Type '%s'\n", g_variant_get_type_string(var));
1031 if (!g_strcmp0(char_path, otp_oacp_obj_path)) {
1032 /* Handle OACP notification */
1033 } else if (!g_strcmp0(char_path, otp_olcp_obj_path)) {
1034 OLCP_indicate = indicate;
1041 void _bt_otp_property_event_filter(GDBusConnection *connection,
1042 const gchar *sender_name,
1043 const gchar *object_path,
1044 const gchar *interface_name,
1045 const gchar *signal_name,
1046 GVariant *parameters,
1051 if (signal_name == NULL) {
1052 BT_ERR("Wrong Signal");
1056 if (g_strcmp0(signal_name, PROPERTIES_CHANGED) == 0) {
1058 g_variant_get(parameters, "(@a{sv}@as)", &value, NULL);
1059 _bt_otp_gatt_char_property_changed_event(value, object_path);
1063 void _bt_otp_adapter_event_filter(GDBusConnection *connection,
1064 const gchar *sender_name,
1065 const gchar *object_path,
1066 const gchar *interface_name,
1067 const gchar *signal_name,
1068 GVariant *parameters,
1071 if (signal_name == NULL) {
1072 BT_ERR("Wrong Signal");
1076 BT_INFO("Interface %s, Signal %s", interface_name, signal_name);
1078 if (g_strcmp0(interface_name, BT_OTP_INTERFACE_NAME) == 0) {
1079 if (strcasecmp(signal_name, BLE_DISABLED) == 0) {
1085 int _bt_otp_init_event_receiver()
1088 GError *error = NULL;
1091 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
1092 if (error != NULL) {
1093 BT_ERR("ERROR: Can't get on system bus [%s]",
1095 g_clear_error(&error);
1099 property_sub_id = g_dbus_connection_signal_subscribe(conn,
1101 BT_OTP_INTERFACE_NAME,
1103 BT_OTP_OBJECT_PATH, NULL, 0,
1104 _bt_otp_property_event_filter,
1107 adapter_sub_id = g_dbus_connection_signal_subscribe(conn,
1109 BT_OTP_INTERFACE_NAME,
1111 BT_OTP_OBJECT_PATH, NULL, 0,
1112 _bt_otp_adapter_event_filter,
1119 void _bt_otp_deinit_event_receiver(void)
1123 g_dbus_connection_signal_unsubscribe(conn, property_sub_id);
1124 g_dbus_connection_signal_unsubscribe(conn, adapter_sub_id);
1130 static void _bt_otp_sig_handler(int sig)
1135 BT_DBG("caught signal - sigterm\n");
1138 BT_DBG("caught signal - sigint\n");
1141 BT_DBG("caught signal - sigkill\n");
1144 BT_DBG("caught signal %d and ignored\n", sig);
1150 /* OTP Service Main loop */
1153 struct sigaction sa;
1154 BT_ERR("Starting the bt-otp daemon");
1156 memset(&sa, 0, sizeof(sa));
1157 sa.sa_handler = _bt_otp_sig_handler;
1158 sa.sa_flags = SA_SIGINFO;
1159 sigaction(SIGINT, &sa, NULL);
1160 sigaction(SIGTERM, &sa, NULL);
1161 sigaction(SIGKILL, &sa, NULL);
1163 if (_bt_otp_register_interface() != BLUETOOTH_ERROR_NONE) {
1164 BT_ERR("Fail to register otp service");
1168 if (_bt_otp_init_event_receiver() != BLUETOOTH_ERROR_NONE) {
1169 BT_ERR("Fail to init event reciever");
1173 main_loop = g_main_loop_new(NULL, FALSE);
1175 g_main_loop_run(main_loop);
1177 BT_DBG("g_main_loop_quit called!");
1179 if (main_loop != NULL) {
1180 g_main_loop_unref(main_loop);