2 * Copyright (c) 2011 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.
22 #include <syspopup_caller.h>
24 #include <bundle_internal.h>
26 #include "bluetooth-api.h"
27 #include "bt-internal-types.h"
29 #include "bt-service-common.h"
30 #include "bt-service-adapter-le.h"
31 #include "bt-service-event.h"
32 #include "bt-service-adapter.h"
33 #include "bt-service-util.h"
34 #include "bt-service-tds.h"
36 #define GATT_SERV_INTERFACE "org.bluez.GattService1"
37 #define GATT_CHAR_INTERFACE "org.bluez.GattCharacteristic1"
38 #define GATT_DESC_INTERFACE "org.bluez.GattDescriptor1"
40 #define GATT_DEFAULT_TIMEOUT (6 * 1000) /* Dependent on supervision timeout 6 sec */
41 #define BT_MAX_DBUS_SENDER_PATH 100
42 #define BT_TRANSPORT_ACTIVATION_TIMEOUT_MAX 15000 /* Timeout for Indication from Provider in msec */
44 #define TDS_CONTROL_POINT_RESPONSE_SUCCESS 0x00
45 #define TDS_CONTROL_POINT_RESPONSE_OP_CODE_NOT_SUPPORTED 0x01
46 #define TDS_CONTROL_POINT_RESPONSE_INVALID_PARAMETER 0x02
47 #define TDS_CONTROL_POINT_RESPONSE_UNSUPPORTED_ORG_ID 0x03
48 #define TDS_CONTROL_POINT_RESPONSE_OPERATION_FAILED 0x04
50 #define BT_ADV_FLAG_LEN 3
51 #define TDS_DATA_LEN_MAX 1024
52 #define NUM_TDS_PROVIDER_MAX 10
55 BT_AD_TYPE_LOCAL_NAME = 0x09, /**<Complete local name */
56 BT_AD_TYPE_COD = 0x0D, /**< Class of Device */
57 BT_AD_TYPE_MANUF_DATA = 0xFF, /**< Manufacturer data */
58 } bt_advertising_ad_type_e;
61 TDS_ROLE_UNSPECIFIED = 0,
64 TDS_ROLE_SEEKER_PROVIDER
68 TRANSPORT_DATA_COMPLETE,
69 TRANSPORT_DATA_INCOMPLETE
70 } bt_tds_transport_data_state_t;
73 unsigned int tds_handle;
75 bluetooth_tds_transport_t transport;
76 bluetooth_tds_transport_state_t state;
77 unsigned int data_len;
79 } bt_tds_transport_info_t;
84 unsigned int manuf_data_len;
85 unsigned char *manuf_data;
89 /* TDS Activation Request structure */
93 unsigned int activation_timeout_id;
95 } bt_tds_activation_info;
97 /* TDS transport specific data read Request info structure */
102 } bt_tds_data_read_req_info;
104 GSList *provider_list = NULL;
105 static int assigned_adv_handle;
106 static gboolean adv_handle_used[NUM_TDS_PROVIDER_MAX];
108 #define TDS_MANUF_DATA_LEN_MAX 29
109 static unsigned char manuf_data[TDS_MANUF_DATA_LEN_MAX];
110 static int manuf_data_len;
112 static GSList *tds_activation_info_list = NULL;
113 static GSList *tds_data_read_req_info_list = NULL;
115 /* Forward declarations */
116 static bt_tds_activation_info* __bt_tds_activation_info_by_address(char *address);
117 static bt_tds_data_read_req_info* __bt_tds_data_read_info_by_address(char *address);
118 static void __bt_tds_send_indication_event(bt_tds_activation_info *info, unsigned char *buffer, int len);
119 static void __bt_tds_remove_indication_info(bt_tds_activation_info *info);
120 static void __bt_tds_remove_data_read_req_info(bt_tds_data_read_req_info *info);
122 static void __bt_init_adv_handle(void)
124 assigned_adv_handle = 0;
125 memset(adv_handle_used, 0x00, NUM_TDS_PROVIDER_MAX);
128 static int __bt_provider_get_adv_handle(void)
132 index = assigned_adv_handle + 1;
134 if (index >= NUM_TDS_PROVIDER_MAX)
137 while (adv_handle_used[index] == TRUE) {
138 if (index == assigned_adv_handle) {
139 /* No available ID */
140 BT_ERR("All adv_handles are used");
146 if (index >= NUM_TDS_PROVIDER_MAX)
150 assigned_adv_handle = index;
151 adv_handle_used[index] = TRUE;
153 return assigned_adv_handle;
156 static void __bt_provider_delete_adv_handle(int handle)
158 ret_if(handle >= NUM_TDS_PROVIDER_MAX);
161 adv_handle_used[handle] = FALSE;
164 static unsigned char __bt_tds_get_organization_id(int transport)
166 BT_INFO("transport: %d", transport);
169 case BLUETOOTH_TDS_TRANSPORT_BT:
171 case BLUETOOTH_TDS_TRANSPORT_CUSTOM:
174 BT_ERR("Invaid transport");
179 static int __bt_tds_get_transport(unsigned char org_id)
181 BT_INFO("org_id: %d", org_id);
185 return BLUETOOTH_TDS_TRANSPORT_BT;
187 return BLUETOOTH_TDS_TRANSPORT_CUSTOM;
189 BT_ERR("Invaid org_id");
190 return BLUETOOTH_TDS_TRANSPORT_INVALID;
194 static unsigned char __bt_tds_set_role(unsigned char flag, bt_tds_role_t role)
197 BT_INFO("Flag: %.2X, Role: %d", flag, role);
200 case TDS_ROLE_UNSPECIFIED:
203 case TDS_ROLE_SEEKER:
207 case TDS_ROLE_PROVIDER:
211 case TDS_ROLE_SEEKER_PROVIDER:
216 BT_ERR("Invalid role received");
222 static int __bt_tds_get_role(unsigned char flag)
225 BT_INFO("Flag: %.2X", flag);
227 if (0x03 == (flag & 0x03))
228 return TDS_ROLE_SEEKER_PROVIDER;
229 else if (0x02 == (flag & 0x02))
230 return TDS_ROLE_PROVIDER;
231 else if (0x01 == (flag & 0x01))
232 return TDS_ROLE_SEEKER;
234 return TDS_ROLE_UNSPECIFIED;
237 static unsigned char __bt_tds_set_transport_data_incomplete(
238 unsigned char flag, gboolean state)
240 BT_INFO("Flag: %.2X, Data state: %d", flag, state);
243 flag = flag | 0x04; /* Set incomplete bit to 1 */
245 flag = flag & 0xFB; /* Set incomplete bit to 0 */
250 static unsigned char __bt_tds_set_transport_state(
251 unsigned char flag, bluetooth_tds_transport_state_t state)
253 BT_INFO("Flag: %.2X, Transport state: %d", flag, state);
256 case BLUETOOTH_TDS_TRANSPORT_STATE_OFF:
259 case BLUETOOTH_TDS_TRANSPORT_STATE_ON:
263 case BLUETOOTH_TDS_TRANSPORT_STATE_UNAVAILABLE:
267 case BLUETOOTH_TDS_TRANSPORT_STATE_RESERVED:
272 BT_ERR("Invalid transport state received");
278 static unsigned char __bt_tds_get_activation_response_code(int result)
283 case BLUETOOTH_ERROR_NONE:
284 resp = TDS_CONTROL_POINT_RESPONSE_SUCCESS; /* Success */
286 case BLUETOOTH_ERROR_INVALID_PARAM:
287 resp = TDS_CONTROL_POINT_RESPONSE_INVALID_PARAMETER; /*Invalid Parameter */
289 case BLUETOOTH_ERROR_NOT_SUPPORT:
290 resp = TDS_CONTROL_POINT_RESPONSE_UNSUPPORTED_ORG_ID; /* Unsupported Organization ID*/
292 case BLUETOOTH_ERROR_INTERNAL:
293 resp = TDS_CONTROL_POINT_RESPONSE_OPERATION_FAILED; /* */
296 BT_INFO("Unknown response code: %d received", result);
297 resp = TDS_CONTROL_POINT_RESPONSE_OPERATION_FAILED;
303 static bt_tds_provider_t* __bt_tds_provider_find_from_list(const char *sender)
307 retv_if(NULL == sender, NULL);
309 for (l = provider_list; l != NULL; l = g_slist_next(l)) {
310 bt_tds_provider_t *provider = l->data;
311 if (provider && (g_strcmp0(provider->sender, sender) == 0))
318 static unsigned char* __bt_tds_provider_get_tds_blocks(unsigned int *length)
322 unsigned int len = 0;
323 unsigned char data[TDS_DATA_LEN_MAX];
325 retv_if(NULL == length, NULL);
327 for (l = provider_list; NULL != l; l = g_slist_next(l)) {
328 bt_tds_provider_t *provider = l->data;
333 for (l1 = provider->transports; l1 != NULL; l1 = g_slist_next(l1)) {
334 bt_tds_transport_info_t *transport_info = l1->data;
336 if (!transport_info || !transport_info->data)
339 if (len + transport_info->data_len > sizeof(data)) {
340 BT_ERR("Could not set complete the tds data, size exceeded");
344 memcpy(&(data[len]), transport_info->data, transport_info->data_len);
345 len += transport_info->data_len;
350 BT_INFO("length = %d", *length);
351 return g_memdup(data, *length);
354 static void __bt_tds_set_scan_resp_data(bt_tds_provider_t *provider)
356 bluetooth_scan_resp_data_t scan_resp;
357 char *name = "bt-service";
365 name = provider->sender;
366 adv_handle = provider->adv_handle;
368 if (provider->manuf_data_len > 0) {
369 scan_resp.data[len++] = provider->manuf_data_len + 1;
370 scan_resp.data[len++] = BT_AD_TYPE_MANUF_DATA;
371 memcpy(&(scan_resp.data[len]), provider->manuf_data, provider->manuf_data_len);
372 len += provider->manuf_data_len;
375 if (manuf_data_len > 0) {
376 scan_resp.data[len++] = manuf_data_len + 1;
377 scan_resp.data[len++] = BT_AD_TYPE_MANUF_DATA;
378 memcpy(&(scan_resp.data[len]), manuf_data, manuf_data_len);
379 len += manuf_data_len;
383 if (len <= (BLUETOOTH_SCAN_RESP_DATA_LENGTH_MAX - 2)) {
385 scan_resp.data[len++] = 1;
386 scan_resp.data[len++] = BT_AD_TYPE_LOCAL_NAME;
389 ret = _bt_set_scan_response_data(name, adv_handle, &scan_resp, len, FALSE);
390 if (ret != BLUETOOTH_ERROR_NONE)
391 BT_ERR("Failed to set_scan response data with error: %d", ret);
397 * Multi adv not supported (Lagacy device/chip) then, and it is difficult to add all the
398 * tds block in single adv pkt. So for each supported orgId, add only 1 tds blocks with
399 * incomplte tds flag bit set, in adv data.
401 static int __bt_tds_provider_get_tds_adv_data(guint8 *adv_data)
405 unsigned int len = 0;
406 unsigned int max_adv_len = BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX - BT_ADV_FLAG_LEN;
409 retv_if(NULL == adv_data, -1);
414 for (transport = BLUETOOTH_TDS_TRANSPORT_BT;
415 transport < BLUETOOTH_TDS_TRANSPORT_INVALID; transport++) {
416 gboolean flag = FALSE;
418 if (len > max_adv_len - 3)
421 for (l = provider_list; l != NULL; l = g_slist_next(l)) {
422 bt_tds_provider_t *provider = l->data;
427 for (l1 = provider->transports; l1 != NULL; l1 = g_slist_next(l1)) {
428 bt_tds_transport_info_t *transport_info = l1->data;
430 if (!transport_info || !transport_info->data ||
431 transport_info->transport != transport)
434 adv_data[len++] = transport_info->data[0]; /* Organization Id */
435 adv_data[len++] = __bt_tds_set_transport_data_incomplete(
436 transport_info->data[1], TRUE);
437 adv_data[len++] = 0; /* Set Transport data len = 0 */
447 BT_INFO("len = %d", len);
449 return -1; /* No data */
451 adv_data[0] = len - 1;
455 /* If multi adv supported set each provider's data in seperate adv slot */
456 static int __bt_tds_provider_get_tds_multi_adv_data(bt_tds_provider_t *provider, guint8 *adv_data)
459 unsigned int len = 0;
460 unsigned int max_adv_len = BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX - BT_ADV_FLAG_LEN;
463 retv_if(NULL == provider, -1);
464 retv_if(NULL == adv_data, -1);
466 count = g_slist_length(provider->transports);
470 for (l = provider->transports; l != NULL; l = g_slist_next(l)) {
471 bt_tds_transport_info_t *transport_info = l->data;
473 if (!transport_info || !transport_info->data)
476 if ((len + transport_info->data_len < max_adv_len - 3) ||
477 (count <= 1 && (len + transport_info->data_len < max_adv_len))) {
478 memcpy(&(adv_data[len]), transport_info->data, transport_info->data_len);
479 len += transport_info->data_len;
481 /* Not able to accomodated complete data in adv pkt */
482 adv_data[len++] = transport_info->data[0]; /* Organization Id */
483 adv_data[len++] = __bt_tds_set_transport_data_incomplete(
484 transport_info->data[1], TRUE);
485 adv_data[len++] = 0; /* Set Transport data len = 0 */
492 BT_INFO("len = %d", len);
494 return -1; /* No data */
496 adv_data[0] = len - 1;
500 static int __bt_tds_set_advertising(bt_tds_provider_t *provider)
502 bluetooth_advertising_data_t adv;
503 bluetooth_advertising_params_t param;
504 char *name = "bt-service";
513 name = provider->sender;
514 adv_handle = provider->adv_handle;
516 /* Get updated TDS advertising data */
517 length = __bt_tds_provider_get_tds_multi_adv_data(provider, adv.data);
519 BT_INFO("No adv data found, return");
521 /* No provider is present, no need to enable advertising */
522 if (0 == g_slist_length(provider_list))
523 return BLUETOOTH_ERROR_NONE;
525 /* Get updated TDS advertising data */
526 length = __bt_tds_provider_get_tds_adv_data(adv.data);
528 BT_INFO("No adv data found, return");
531 /* If length <= 0, no need to start advertisement */
533 return BLUETOOTH_ERROR_NONE;
535 for (i = 0; i < length; i++)
536 BT_DBG("adv_data: %.2X", adv.data[i]);
538 ret = _bt_set_advertising_data(name, adv_handle, &adv, length, FALSE);
539 if (ret != BLUETOOTH_ERROR_NONE) {
540 BT_ERR("Failed to set ADV %d", ret);
544 /* set scan response data */
545 __bt_tds_set_scan_resp_data(provider);
547 param.interval_min = 500;
548 param.interval_max = 500;
549 param.filter_policy = BLUETOOTH_ALLOW_SCAN_CONN_ALL;
550 param.type = BLUETOOTH_ADV_CONNECTABLE;
552 ret = _bt_set_custom_advertising(name, adv_handle, TRUE, ¶m, FALSE);
553 if (ret != BLUETOOTH_ERROR_NONE) {
554 BT_ERR("Failed to enable advertising with error: %d", ret);
559 return BLUETOOTH_ERROR_NONE;
562 static int __bt_tds_disable_advertising(bt_tds_provider_t *provider)
564 char *name = "bt-service";
571 name = provider->sender;
572 adv_handle = provider->adv_handle;
575 /* First try to disable adv in case already advertising */
576 ret = _bt_set_advertising(name, adv_handle, FALSE, FALSE);
577 if (ret != BLUETOOTH_ERROR_NONE) {
578 BT_ERR("Failed to disable advertising with error: %d", ret);
579 ret = __bt_tds_set_advertising(provider);
580 if (ret != BLUETOOTH_ERROR_NONE) {
581 BT_ERR("Failed to enable advertising with error: %d", ret);
587 return BLUETOOTH_ERROR_NONE;
590 static int __bt_tds_provider_update_transport_data(bt_tds_provider_t *provider)
593 GDBusConnection *conn;
594 char *adapter_path = NULL;
595 GError *error = NULL;
596 GVariant *result = NULL;
597 GVariantBuilder *builder;
599 unsigned char *buf = NULL;
600 unsigned int length = 0;
605 conn = _bt_gdbus_get_system_gconn();
606 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
608 adapter_path = _bt_get_adapter_path();
609 if (adapter_path == NULL) {
610 BT_ERR("Could not get adapter path\n");
611 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
614 BT_INFO("Adapter path [%s]", adapter_path);
615 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
616 NULL, BT_BLUEZ_NAME, adapter_path,
617 BT_TDS_PROVIDER_INTERFACE, NULL, NULL);
618 g_free(adapter_path);
619 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
621 buf = __bt_tds_provider_get_tds_blocks(&length);
622 retv_if(length == 0, BLUETOOTH_ERROR_NONE);
623 retv_if(NULL == buf, BLUETOOTH_ERROR_INTERNAL);
624 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
625 for (i = 0; i < length; i++)
626 g_variant_builder_add(builder, "y", buf[i]);
629 temp = g_variant_new("ay", builder);
630 g_variant_builder_unref(builder);
631 result = g_dbus_proxy_call_sync(proxy, "SetTdsBlockData",
632 g_variant_new("(@ay)", temp),
633 G_DBUS_CALL_FLAGS_NONE, -1,
635 g_object_unref(proxy);
636 if (result == NULL) {
638 BT_ERR("Error occured in Proxy call [%s]\n", error->message);
641 BT_ERR("Error occured in Proxy call: SetData");
643 return BLUETOOTH_ERROR_INTERNAL;
647 return BLUETOOTH_ERROR_NONE;
650 static void __bt_free_tds_transport_info(gpointer data, gpointer user_data)
652 bt_tds_transport_info_t *transport_info = data;
654 ret_if(NULL == transport_info);
658 g_free(transport_info->data);
659 g_free(transport_info);
664 static bt_tds_transport_info_t * __bt_tds_find_transport_info(
665 bt_tds_provider_t *provider, unsigned int handle)
669 retv_if(!provider, NULL);
671 for (l = provider->transports; l != NULL; l = g_slist_next(l)) {
672 bt_tds_transport_info_t *transport_info = l->data;
677 if (transport_info->tds_handle == handle)
678 return transport_info;
684 int _bt_tds_provider_register(const char *sender)
687 GDBusConnection *conn;
688 char *adapter_path = NULL;
689 GError *error = NULL;
690 GVariant *result = NULL;
691 bt_tds_provider_t *provider;
693 retv_if(NULL == sender, BLUETOOTH_ERROR_INVALID_PARAM);
697 if (__bt_tds_provider_find_from_list(sender))
698 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
700 if (0 == g_slist_length(provider_list)) {
701 /* Init adv_handle list */
702 __bt_init_adv_handle();
704 conn = _bt_gdbus_get_system_gconn();
705 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
707 adapter_path = _bt_get_adapter_path();
708 if (adapter_path == NULL) {
709 BT_ERR("Could not get adapter path\n");
710 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
713 BT_INFO("Adapter path [%s]", adapter_path);
714 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
715 NULL, BT_BLUEZ_NAME, adapter_path,
716 BT_TDS_PROVIDER_INTERFACE, NULL, NULL);
717 g_free(adapter_path);
718 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
720 result = g_dbus_proxy_call_sync(proxy, "RegisterTdsProvider",
721 NULL, G_DBUS_CALL_FLAGS_NONE, -1,
723 g_object_unref(proxy);
724 if (result == NULL) {
726 BT_ERR("Error occured in Proxy call [%s]", error->message);
729 BT_ERR("Error occured in Proxy call: RegisterTdsProvider");
731 return BLUETOOTH_ERROR_INTERNAL;
735 provider = g_malloc0(sizeof(bt_tds_provider_t));
736 provider->sender = g_strdup(sender);
737 provider->adv_handle = __bt_provider_get_adv_handle();
738 if (0 > provider->adv_handle) {
739 g_free(provider->sender);
741 return BLUETOOTH_ERROR_INTERNAL;
744 provider_list = g_slist_append(provider_list, provider);
747 return BLUETOOTH_ERROR_NONE;
750 int _bt_tds_provider_unregister(const char *sender)
753 GDBusConnection *conn;
754 char *adapter_path = NULL;
755 GError *error = NULL;
756 GVariant *result = NULL;
757 bt_tds_provider_t *provider = NULL;
760 retv_if(NULL == sender, BLUETOOTH_ERROR_NOT_INITIALIZED);
764 provider = __bt_tds_provider_find_from_list(sender);
766 return BLUETOOTH_ERROR_NOT_INITIALIZED;
768 if (1 == g_slist_length(provider_list)) {
769 conn = _bt_gdbus_get_system_gconn();
770 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
772 adapter_path = _bt_get_adapter_path();
773 if (adapter_path == NULL) {
774 BT_ERR("Could not get adapter path\n");
775 return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED;
778 BT_INFO("Adapter path [%s]", adapter_path);
779 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
780 NULL, BT_BLUEZ_NAME, adapter_path,
781 BT_TDS_PROVIDER_INTERFACE, NULL, NULL);
783 g_free(adapter_path);
784 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
786 result = g_dbus_proxy_call_sync(proxy, "UnregisterTdsProvider",
787 NULL, G_DBUS_CALL_FLAGS_NONE, -1,
789 g_object_unref(proxy);
790 if (result == NULL) {
792 BT_ERR("Error occured in Proxy call [%s]\n", error->message);
795 BT_ERR("Error occured in Proxy call: UnregisterTdsProvider");
797 return BLUETOOTH_ERROR_INTERNAL;
801 if (_bt_is_multi_adv_supported()) {
802 /* Disable advertisement for sender */
803 ret = _bt_set_advertising(provider->sender, provider->adv_handle, FALSE, FALSE);
804 if (ret != BLUETOOTH_ERROR_NONE)
805 BT_ERR("Failed to disable advertising with error: %d", ret);
808 * Disable advertising here. Later on receiving advertising disabled event,
809 * advertising will be enabled again with updated advertising data
811 ret = __bt_tds_disable_advertising(NULL);
812 if (ret != BLUETOOTH_ERROR_NONE)
813 BT_ERR("Failed to disable advertising with error: %d", ret);
816 provider_list = g_slist_remove(provider_list, provider);
817 g_slist_foreach(provider->transports, __bt_free_tds_transport_info, NULL);
818 g_slist_free(provider->transports);
819 __bt_provider_delete_adv_handle(provider->adv_handle);
820 g_free(provider->sender);
824 return BLUETOOTH_ERROR_NONE;
827 int _bt_tds_provider_transport_create(const char *sender, int transport, unsigned int tds_handle)
829 bt_tds_transport_info_t *transport_info;
830 bt_tds_provider_t *provider = NULL;
832 retv_if(NULL == sender, BLUETOOTH_ERROR_INVALID_PARAM);
834 if (BLUETOOTH_TDS_TRANSPORT_BT > transport ||
835 BLUETOOTH_TDS_TRANSPORT_INVALID <= transport) {
836 BT_ERR("transport value: %d not in range", transport);
837 return BLUETOOTH_ERROR_INVALID_PARAM;
842 provider = __bt_tds_provider_find_from_list(sender);
844 return BLUETOOTH_ERROR_NOT_INITIALIZED;
846 transport_info = g_malloc0(sizeof(bt_tds_transport_info_t));
847 transport_info->transport = transport;
848 transport_info->tds_handle = tds_handle;
849 transport_info->role = TDS_ROLE_PROVIDER;
850 transport_info->state = BLUETOOTH_TDS_TRANSPORT_STATE_OFF;
851 provider->transports = g_slist_append(provider->transports, transport_info);
854 return BLUETOOTH_ERROR_NONE;
857 int _bt_tds_provider_transport_remove(const char *sender, unsigned int tds_handle)
859 bt_tds_provider_t *provider = NULL;
860 bt_tds_transport_info_t *transport_info;
863 retv_if(NULL == sender, BLUETOOTH_ERROR_INVALID_PARAM);
867 provider = __bt_tds_provider_find_from_list(sender);
869 return BLUETOOTH_ERROR_INVALID_PARAM;
871 transport_info = __bt_tds_find_transport_info(provider, tds_handle);
873 return BLUETOOTH_ERROR_INVALID_PARAM;
875 provider->transports = g_slist_remove(provider->transports, transport_info);
876 __bt_free_tds_transport_info(transport_info, NULL);
878 /* Set/update transport data in gatt db */
879 ret = __bt_tds_provider_update_transport_data(provider);
880 if (BLUETOOTH_ERROR_NONE != ret) {
881 BT_ERR("Failed to update transport data with error: %d", ret);
886 * Disable advertising here. Later on receiving advertising disabled event,
887 * advertising will be enabled again with updated advertising data.
889 if (_bt_is_multi_adv_supported())
890 ret = __bt_tds_disable_advertising(provider);
892 ret = __bt_tds_disable_advertising(NULL);
893 if (ret != BLUETOOTH_ERROR_NONE) {
894 BT_ERR("Failed to enable advertising with error: %d", ret);
899 return BLUETOOTH_ERROR_NONE;
902 int _bt_tds_provider_set_manuf_data(char *sender, unsigned char *data, unsigned int len)
904 bt_tds_provider_t *provider;
907 retv_if(NULL == sender, BLUETOOTH_ERROR_INVALID_PARAM);
908 retv_if(len == 0 || len > TDS_MANUF_DATA_LEN_MAX, BLUETOOTH_ERROR_INVALID_PARAM);
909 retv_if(NULL == data, BLUETOOTH_ERROR_INVALID_PARAM);
913 BT_INFO("sender: %s", sender);
914 provider = __bt_tds_provider_find_from_list(sender);
916 return BLUETOOTH_ERROR_INVALID_PARAM;
919 * Set manufacturer data and disable advertising here. Later on receiving advertising
920 * disabled event, advertising will be enabled again with updated advertising data.
922 if (_bt_is_multi_adv_supported()) {
923 g_free(provider->manuf_data);
924 provider->manuf_data_len = len;
925 provider->manuf_data = g_malloc0(provider->manuf_data_len);
926 memcpy(provider->manuf_data, data, len);
928 ret = __bt_tds_disable_advertising(provider);
930 manuf_data_len = len;
931 memcpy(manuf_data, data, len);
932 ret = __bt_tds_disable_advertising(NULL);
934 if (ret != BLUETOOTH_ERROR_NONE) {
935 BT_ERR("Failed to enable advertising with error: %d", ret);
940 return BLUETOOTH_ERROR_NONE;
943 int _bt_tds_provider_set_transport_data(char *sender, int tds_handle,
944 int transport_state, unsigned char *data, unsigned int len)
946 bt_tds_provider_t *provider;
947 bt_tds_transport_info_t *transport_info;
950 retv_if(NULL == sender, BLUETOOTH_ERROR_INVALID_PARAM);
951 retv_if(len > 0 && NULL == data, BLUETOOTH_ERROR_INVALID_PARAM);
955 if (BLUETOOTH_TDS_TRANSPORT_STATE_OFF > transport_state ||
956 BLUETOOTH_TDS_TRANSPORT_STATE_RESERVED <= transport_state) {
957 BT_ERR("transport_state value: %d not in range", transport_state);
958 return BLUETOOTH_ERROR_INVALID_PARAM;
961 BT_INFO("sender: %s, tds_handle: %X", sender, tds_handle);
962 provider = __bt_tds_provider_find_from_list(sender);
964 return BLUETOOTH_ERROR_INVALID_PARAM;
966 transport_info = __bt_tds_find_transport_info(provider, tds_handle);
968 return BLUETOOTH_ERROR_INVALID_PARAM;
970 transport_info->state = transport_state;
971 g_free(transport_info->data);
972 transport_info->data_len = len + 3;
973 transport_info->data = g_malloc0(transport_info->data_len);
974 /* TDS Orgnazition Id */
975 transport_info->data[0] = __bt_tds_get_organization_id(transport_info->transport);
977 if (TDS_ROLE_SEEKER_PROVIDER != __bt_tds_get_role(transport_info->data[1]))
978 transport_info->data[1] = __bt_tds_set_role(transport_info->data[1], transport_info->role);
979 transport_info->data[1] = __bt_tds_set_transport_data_incomplete(transport_info->data[1], FALSE);
980 transport_info->data[1] = __bt_tds_set_transport_state(transport_info->data[1], transport_state);
981 /* TDS block data length */
982 transport_info->data[2] = len;
983 memcpy(&(transport_info->data[3]), data, len);
985 /* Set/update transport data in gatt db */
986 ret = __bt_tds_provider_update_transport_data(provider);
987 if (BLUETOOTH_ERROR_NONE != ret) {
988 BT_ERR("Failed to update transport data with error: %d", ret);
993 * Disable advertising here. Later on receiving advertising disabled event,
994 * advertising will be enabled again with updated advertising data.
996 if (_bt_is_multi_adv_supported())
997 ret = __bt_tds_disable_advertising(provider);
999 ret = __bt_tds_disable_advertising(NULL);
1000 if (ret != BLUETOOTH_ERROR_NONE) {
1001 BT_ERR("Failed to enable advertising with error: %d", ret);
1006 return BLUETOOTH_ERROR_NONE;
1009 static int __bt_tds_send_activation_response(char *address,
1010 unsigned char response, unsigned char *data, unsigned int len)
1013 GDBusConnection *conn;
1015 GError *error = NULL;
1016 GVariant *result = NULL;
1017 GVariantBuilder *builder;
1021 retv_if(NULL == address, BLUETOOTH_ERROR_INVALID_PARAM);
1022 retv_if(len > 0 && NULL == data, BLUETOOTH_ERROR_INVALID_PARAM);
1025 conn = _bt_gdbus_get_system_gconn();
1026 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1028 device_path = _bt_get_device_object_path(address);
1029 if (NULL == device_path) {
1030 BT_ERR("Could not get device path\n");
1031 return BLUETOOTH_ERROR_INTERNAL;
1034 BT_INFO("Device path [%s]", device_path);
1035 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
1036 NULL, BT_BLUEZ_NAME, device_path,
1037 BT_TDS_PROVIDER_INTERFACE, NULL, NULL);
1038 g_free(device_path);
1039 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
1041 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1042 for (i = 0; i < len; i++)
1043 g_variant_builder_add(builder, "y", data[i]);
1045 temp = g_variant_new("ay", builder);
1046 g_variant_builder_unref(builder);
1047 result = g_dbus_proxy_call_sync(proxy, "TdsActivationResponse",
1048 g_variant_new("(y@ay)", response, temp),
1049 G_DBUS_CALL_FLAGS_NONE, -1,
1051 g_object_unref(proxy);
1052 if (result == NULL) {
1053 if (error != NULL) {
1054 BT_ERR("Error occured in Proxy call [%s]\n", error->message);
1055 g_error_free(error);
1057 BT_ERR("Error occured in Proxy call: SetData");
1059 return BLUETOOTH_ERROR_INTERNAL;
1063 return BLUETOOTH_ERROR_NONE;
1066 int _bt_tds_provider_send_activation_response(char *sender, unsigned int tds_handle,
1067 bluetooth_device_address_t *address, int response, unsigned char *data, unsigned int len)
1069 bt_tds_provider_t *provider;
1070 bt_tds_transport_info_t *transport_info;
1072 char addr[BT_ADDRESS_STRING_SIZE];
1075 retv_if(NULL == sender, BLUETOOTH_ERROR_INVALID_PARAM);
1076 retv_if(NULL == address, BLUETOOTH_ERROR_INVALID_PARAM);
1077 retv_if(len > 0 && NULL == data, BLUETOOTH_ERROR_INVALID_PARAM);
1081 BT_INFO("sender: %s, tds_handle: 0x%X", sender, tds_handle);
1082 provider = __bt_tds_provider_find_from_list(sender);
1084 return BLUETOOTH_ERROR_NOT_INITIALIZED;
1086 transport_info = __bt_tds_find_transport_info(provider, tds_handle);
1087 if (!transport_info)
1088 return BLUETOOTH_ERROR_INVALID_PARAM;
1090 if (BLUETOOTH_ERROR_NONE == response) {
1091 /* Activation success, set transport state enabled */
1092 _bt_tds_provider_set_transport_data(provider->sender,
1093 transport_info->transport, BLUETOOTH_TDS_TRANSPORT_STATE_ON,
1094 transport_info->data, transport_info->data_len);
1097 _bt_convert_addr_type_to_string(addr, address->addr);
1098 resp = __bt_tds_get_activation_response_code(response);
1100 ret = __bt_tds_send_activation_response(addr, resp, data, len);
1101 if (ret != BLUETOOTH_ERROR_NONE) {
1102 BT_ERR("Failed to send activation response with error: %d", ret);
1107 return BLUETOOTH_ERROR_NONE;
1110 void _bt_tds_handle_activation_request(const char *path,
1111 unsigned char org_id, unsigned char *buf, int len)
1121 ret_if(NULL == path);
1122 ret_if(len > 0 && NULL == buf);
1126 address = g_malloc0(BT_ADDRESS_STRING_SIZE);
1127 _bt_convert_device_path_to_address(path, address);
1128 transport = __bt_tds_get_transport(org_id);
1129 BT_DBG("Address: %s, transport: %.2X", address, transport);
1131 if (BLUETOOTH_TDS_TRANSPORT_INVALID == transport)
1134 tds_data = g_variant_new_from_data((const GVariantType *)"ay",
1135 buf, len, TRUE, NULL, NULL);
1136 param = g_variant_new("(si@ay)", address, transport, tds_data);
1138 /* Find provider with transport type in list and send event to them */
1139 for (l = provider_list; l != NULL; l = g_slist_next(l)) {
1140 bt_tds_provider_t *provider = l->data;
1145 for (l1 = provider->transports; l1 != NULL; l1 = g_slist_next(l1)) {
1146 bt_tds_transport_info_t *transport_info = l1->data;
1148 if (transport_info && transport_info->transport == transport) {
1149 _bt_send_event_to_dest(provider->sender, BT_TDS_EVENT,
1150 BLUETOOTH_EVENT_TDS_ACTIVATION_REQUESTED, param);
1156 /* If no provider found for transport type, send error */
1163 /* send activation response as error to bluez */
1164 __bt_tds_send_activation_response(address,
1165 TDS_CONTROL_POINT_RESPONSE_UNSUPPORTED_ORG_ID, NULL, 0);
1168 void _bt_tds_stop_by_terminated_process(char *name)
1170 bt_tds_provider_t *provider = NULL;
1172 provider = __bt_tds_provider_find_from_list(name);
1176 _bt_tds_provider_unregister(provider->sender);
1179 void _bt_tds_handle_adv_disabled(const char *sender, int adv_handle)
1181 bt_tds_provider_t *provider = NULL;
1183 BT_INFO("sender: %s, adv_handle:%d", sender, adv_handle);
1185 ret_if(NULL == sender);
1187 if (g_strcmp0(sender, "bt-service") != 0) {
1188 provider = __bt_tds_provider_find_from_list(sender);
1189 if (!provider || provider->adv_handle != adv_handle) {
1190 BT_INFO("Provider not found");
1194 if (adv_handle != 0)
1198 __bt_tds_set_advertising(provider);
1201 static void __bt_tds_transport_data_read_desc_cb(GObject *source_object,
1202 GAsyncResult *res, gpointer user_data)
1204 GError *error = NULL;
1205 bt_gatt_char_descriptor_property_t att_value = { 0, };
1206 GDBusConnection *system_gconn = NULL;
1207 GVariant *value = NULL;
1208 GByteArray *gp_byte_array = NULL;
1209 GVariantIter *iter = NULL;
1211 bt_tds_data_read_req_info *info = NULL;
1212 GVariant *out_param1;
1213 request_info_t *req_info = NULL;
1214 bluetooth_device_address_t device_addr = { {0} };
1215 int result = BLUETOOTH_ERROR_NONE;
1218 GVariant *var_data, *param = NULL;
1219 char *tds_data = NULL;
1223 system_gconn = _bt_gdbus_get_system_gconn();
1225 address = (char *)user_data;
1226 info = __bt_tds_data_read_info_by_address(address);
1228 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1231 BT_ERR("Error : %s \n", error->message);
1234 req_info = _bt_get_request_info(info->req_id);
1235 __bt_tds_remove_data_read_req_info(info);
1237 result = BLUETOOTH_ERROR_INTERNAL;
1241 gp_byte_array = g_byte_array_new();
1242 g_variant_get(value, "(ay)", &iter);
1244 while (g_variant_iter_loop(iter, "y", &g_byte))
1245 g_byte_array_append(gp_byte_array, &g_byte, 1);
1247 if (gp_byte_array->len != 0) {
1248 att_value.val_len = (unsigned int)gp_byte_array->len;
1249 att_value.val = (unsigned char *)gp_byte_array->data;
1252 tds_data = (char *)g_memdup(att_value.val, att_value.val_len);
1254 var_data = g_variant_new_from_data((const GVariantType *)"ay",
1255 tds_data, att_value.val_len, TRUE, NULL, NULL);
1258 param = g_variant_new("(isn@ay)", result, address, att_value.val_len, var_data);
1259 _bt_send_event_to_dest(info->sender, BT_TDS_EVENT,
1260 BLUETOOTH_EVENT_TDS_TRANSPORT_DATA_RECEIVED,
1262 req_info = _bt_get_request_info(info->req_id);
1263 __bt_tds_remove_data_read_req_info(info);
1267 for (k = 0; k < att_value.val_len; k++)
1268 BT_DBG("Transport Data[%d] = [0x%x]", k, att_value.val[k]);
1271 if (req_info == NULL) {
1272 BT_ERR("TDS Complete data read Request is not found!!");
1276 if (req_info->context == NULL)
1279 _bt_convert_addr_string_to_type(device_addr.addr,
1280 (const char *)address);
1282 out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
1283 &device_addr, sizeof(bluetooth_device_address_t), TRUE, NULL, NULL);
1284 g_dbus_method_invocation_return_value(req_info->context,
1285 g_variant_new("(iv)", result, out_param1));
1287 _bt_delete_request_list(req_info->req_id);
1292 g_clear_error(&error);
1294 g_byte_array_free(gp_byte_array, TRUE);
1298 g_variant_unref(value);
1300 g_variant_iter_free(iter);
1306 int _bt_tds_read_transport_data(int request_id, char *sender,
1307 bluetooth_device_address_t *dev_addr, char *handle)
1309 GDBusConnection *conn;
1310 char *address = NULL;
1311 bt_tds_data_read_req_info *info = NULL;
1313 BT_CHECK_PARAMETER(handle, return);
1314 BT_CHECK_PARAMETER(sender, return);
1315 BT_CHECK_PARAMETER(dev_addr, return);
1317 conn = _bt_gdbus_get_system_gconn();
1318 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1320 BT_DBG("Read Complete TDS block from Provider [Handle] [%s]", handle);
1321 address = g_malloc0(BT_ADDRESS_STRING_SIZE);
1322 _bt_convert_addr_type_to_string(address, dev_addr->addr);
1324 /* If TDS data read already pending on same Provider, then return In progress */
1325 if (__bt_tds_data_read_info_by_address(address) != NULL) {
1326 BT_ERR("TDS Data Read Req is ongoing in remote provider [%s]", address);
1328 return BLUETOOTH_ERROR_IN_PROGRESS;
1331 g_dbus_connection_call(conn,
1334 GATT_DESC_INTERFACE,
1337 G_VARIANT_TYPE("(ay)"),
1338 G_DBUS_CALL_FLAGS_NONE,
1341 (GAsyncReadyCallback)__bt_tds_transport_data_read_desc_cb,
1344 /* Save Info in pending list */
1345 info = g_malloc0(sizeof(bt_tds_data_read_req_info));
1346 info->remote_address = g_strdup(address);
1347 info->sender = g_strdup(sender);
1348 info->req_id = request_id;
1349 tds_data_read_req_info_list = g_slist_append(tds_data_read_req_info_list, info);
1352 return BLUETOOTH_ERROR_NONE;
1355 static void __bluetooth_internal_control_point_enable_request_cb(GObject *source_object,
1356 GAsyncResult *res, gpointer user_data)
1358 GError *error = NULL;
1359 GDBusConnection *system_gconn = NULL;
1360 GVariant *value = NULL;
1361 GVariant *param = NULL;
1362 GVariant *out_param1 = NULL;
1363 int result = BLUETOOTH_ERROR_NONE;
1364 char *address = NULL;
1365 bt_tds_activation_info *info = NULL;
1366 request_info_t *req_info = NULL;
1367 bluetooth_device_address_t device_addr = { {0} };
1370 system_gconn = _bt_gdbus_get_system_gconn();
1371 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1374 BT_ERR("Error : %s \n", error->message);
1375 if (g_strrstr(error->message, "Already notifying"))
1376 result = BLUETOOTH_ERROR_NONE;
1377 else if (g_strrstr(error->message, "In Progress"))
1378 result = BLUETOOTH_ERROR_IN_PROGRESS;
1379 else if (g_strrstr(error->message, "Operation is not supported"))
1380 result = BLUETOOTH_ERROR_NOT_SUPPORT;
1381 else if (g_strrstr(error->message, "Write not permitted") ||
1382 g_strrstr(error->message, "Operation Not Authorized"))
1383 result = BLUETOOTH_ERROR_PERMISSION_DEINED;
1384 else if (g_strrstr(error->message, "Not paired"))
1385 result = BLUETOOTH_ERROR_NOT_PAIRED;
1387 result = BLUETOOTH_ERROR_INTERNAL;
1389 BT_DBG("TDS CCCD enable request successful, send event to BT App");
1392 address = (char *)user_data;
1393 info = __bt_tds_activation_info_by_address(address);
1396 req_info = _bt_get_request_info(info->req_id);
1398 /* If CCCD Enable request failed for any reason, reset timer */
1399 if (result != BLUETOOTH_ERROR_NONE && info != NULL) {
1400 BT_ERR("Activation Request failed");
1402 if (info->activation_timeout_id > 0) {
1403 g_source_remove(info->activation_timeout_id);
1404 info->activation_timeout_id = 0;
1407 /* Remove Indication Info */
1408 __bt_tds_remove_indication_info(info);
1410 /* CCCD Enable Request successful */
1412 param = g_variant_new("(is)", result, address);
1413 _bt_send_event_to_dest(info->sender, BT_TDS_EVENT,
1414 BLUETOOTH_EVENT_TDS_CONTROL_POINT_ENABLED,
1419 if (req_info == NULL) {
1420 BT_ERR("TDS Control Point CCCD Enable Request is not found!!");
1424 if (req_info->context == NULL)
1427 _bt_convert_addr_string_to_type(device_addr.addr,
1428 (const char *)address);
1430 out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
1431 &device_addr, sizeof(bluetooth_device_address_t), TRUE, NULL, NULL);
1432 g_dbus_method_invocation_return_value(req_info->context,
1433 g_variant_new("(iv)", result, out_param1));
1435 _bt_delete_request_list(req_info->req_id);
1439 g_variant_unref(value);
1441 g_clear_error(&error);
1449 int _bt_tds_enable_control_point(int request_id, char *sender, bluetooth_device_address_t *dev_addr,
1452 GDBusConnection *conn;
1453 char *address = NULL;
1454 bt_tds_activation_info *info = NULL;
1456 BT_CHECK_PARAMETER(handle, return);
1457 BT_CHECK_PARAMETER(sender, return);
1458 BT_CHECK_PARAMETER(dev_addr, return);
1460 conn = _bt_gdbus_get_system_gconn();
1461 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1463 BT_DBG("TDS Control point CCCD Handle [%s]", handle);
1465 address = g_malloc0(BT_ADDRESS_STRING_SIZE);
1466 _bt_convert_addr_type_to_string(address, dev_addr->addr);
1468 if (__bt_tds_activation_info_by_address(address) != NULL) {
1469 BT_ERR("Activation is already ongoing for same remote provider");
1471 return BLUETOOTH_ERROR_IN_PROGRESS;
1474 BT_INFO("Start Notify to Bluez");
1475 g_dbus_connection_call(conn,
1478 GATT_CHAR_INTERFACE,
1482 G_DBUS_CALL_FLAGS_NONE,
1483 GATT_DEFAULT_TIMEOUT, NULL,
1484 (GAsyncReadyCallback)__bluetooth_internal_control_point_enable_request_cb,
1487 info = g_malloc0(sizeof(bt_tds_activation_info));
1488 info->remote_address = g_strdup(address);
1489 info->sender = g_strdup(sender);
1490 info->req_id = request_id;
1491 tds_activation_info_list = g_slist_append(tds_activation_info_list, info);
1494 return BLUETOOTH_ERROR_NONE;
1497 static void __bluetooth_internal_activation_request_cb(GObject *source_object,
1498 GAsyncResult *res, gpointer user_data)
1500 GError *error = NULL;
1501 GDBusConnection *system_gconn = NULL;
1502 GVariant *value = NULL;
1503 GVariant *param = NULL;
1504 GVariant *out_param1 = NULL;
1505 int result = BLUETOOTH_ERROR_NONE;
1506 guint8 att_ecode = 0;
1507 char *address = NULL;
1508 bt_tds_activation_info *info = NULL;
1509 request_info_t *req_info = NULL;
1510 bluetooth_device_address_t device_addr = { {0} };
1513 system_gconn = _bt_gdbus_get_system_gconn();
1514 value = g_dbus_connection_call_finish(system_gconn, res, &error);
1517 BT_ERR("Error : %s \n", error->message);
1518 result = BLUETOOTH_ERROR_INTERNAL;
1520 g_variant_get(value, "(y)", &att_ecode);
1522 result = BLUETOOTH_ERROR_INTERNAL;
1523 BT_ERR("ATT Error code: %d \n", att_ecode);
1527 address = (char *)user_data;
1528 info = __bt_tds_activation_info_by_address(address);
1530 req_info = _bt_get_request_info(info->req_id);
1532 /* Is Activation request failed for any reason, reset timer */
1533 if (result != BLUETOOTH_ERROR_NONE && info != NULL) {
1534 BT_ERR("Activation Request failed");
1536 if (info->activation_timeout_id > 0) {
1537 g_source_remove(info->activation_timeout_id);
1538 info->activation_timeout_id = 0;
1541 /* Remove Indication Info */
1542 __bt_tds_remove_indication_info(info);
1544 /* Activation Request successful */
1546 param = g_variant_new("(is)", result, address);
1547 _bt_send_event_to_dest(info->sender, BT_TDS_EVENT,
1548 BLUETOOTH_EVENT_TDS_ACTIVATION_RESULT,
1553 if (req_info == NULL) {
1554 BT_ERR("TDS Control Point Activation Request is not found!!");
1558 if (req_info->context == NULL)
1561 _bt_convert_addr_string_to_type(device_addr.addr,
1562 (const char *)address);
1564 out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
1565 &device_addr, sizeof(bluetooth_device_address_t), TRUE, NULL, NULL);
1566 g_dbus_method_invocation_return_value(req_info->context,
1567 g_variant_new("(iv)", result, out_param1));
1569 _bt_delete_request_list(req_info->req_id);
1573 g_variant_unref(value);
1575 g_clear_error(&error);
1583 static bool __bt_tds_indication_timeout_cb(gpointer user_data)
1585 char *address = NULL;
1586 address = (char*) user_data;
1587 bt_tds_activation_info *info = NULL;
1588 /* Indication:Fail*/
1589 unsigned char buffer[2] = {0x01, 0x04};
1591 BT_DBG("Activation timer Expired [Provider] [%s]", address);
1593 info = __bt_tds_activation_info_by_address(address);
1595 __bt_tds_send_indication_event(info, buffer, sizeof(buffer));
1599 int _bt_tds_activate_control_point(int request_id, char *sender, bluetooth_device_address_t *dev_addr,
1600 char *handle, unsigned char *param, int length)
1603 GVariantBuilder *builder;
1605 bt_tds_activation_info *info = NULL;
1606 GDBusConnection *conn;
1607 char *address = NULL;
1610 BT_CHECK_PARAMETER(handle, return);
1611 BT_CHECK_PARAMETER(sender, return);
1612 BT_CHECK_PARAMETER(dev_addr, return);
1613 BT_CHECK_PARAMETER(param, return);
1615 conn = _bt_gdbus_get_system_gconn();
1616 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1618 BT_DBG("TDS Control point Activate handle [%s] data length [%d]", handle, length);
1619 /* Check if activation is ongoing for the same Remote Provider */
1620 address = g_malloc0(BT_ADDRESS_STRING_SIZE);
1621 _bt_convert_addr_type_to_string(address, dev_addr->addr);
1623 info = __bt_tds_activation_info_by_address(address);
1624 if (info && info->activation_timeout_id > 0) {
1625 BT_ERR("Activation is already ongoing in remote provider");
1627 return BLUETOOTH_ERROR_IN_PROGRESS;
1630 builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
1632 for (i = 0; i < length; i++)
1633 g_variant_builder_add(builder, "y", param[i]);
1635 val = g_variant_new("(ay)", builder);
1637 /* Activate Control Point */
1638 g_dbus_connection_call(conn,
1641 GATT_CHAR_INTERFACE,
1644 G_VARIANT_TYPE("(y)"),
1645 G_DBUS_CALL_FLAGS_NONE,
1647 (GAsyncReadyCallback)__bluetooth_internal_activation_request_cb,
1650 g_variant_builder_unref(builder);
1653 info = g_malloc0(sizeof(bt_tds_activation_info));
1654 info->remote_address = g_strdup(address);
1655 info->sender = g_strdup(sender);
1656 tds_activation_info_list = g_slist_append(tds_activation_info_list, info);
1658 info->req_id = request_id;
1659 info->activation_timeout_id = g_timeout_add(BT_TRANSPORT_ACTIVATION_TIMEOUT_MAX,
1660 (GSourceFunc)__bt_tds_indication_timeout_cb, (gpointer)info->remote_address);
1663 return BLUETOOTH_ERROR_NONE;
1666 static bt_tds_activation_info* __bt_tds_activation_info_by_address(char *address)
1669 bt_tds_activation_info *info = NULL;
1671 for (l = tds_activation_info_list; l != NULL; l = g_slist_next(l)) {
1672 info = (bt_tds_activation_info*)l->data;
1676 if (!g_strcmp0(info->remote_address, address)) {
1677 BT_INFO("Seeker found waiting for Ind from Provider addr[%s]",
1678 info->remote_address);
1685 static bt_tds_data_read_req_info* __bt_tds_data_read_info_by_address(char *address)
1688 bt_tds_data_read_req_info *info = NULL;
1690 for (l = tds_data_read_req_info_list; l != NULL; l = g_slist_next(l)) {
1691 info = (bt_tds_data_read_req_info*)l->data;
1695 if (!g_strcmp0(info->remote_address, address)) {
1696 BT_INFO("Found waiting for Transport Data Read from Provider addr[%s]",
1697 info->remote_address);
1704 static void __bt_tds_remove_indication_info(bt_tds_activation_info *info)
1706 BT_DBG("Removing Indication Info [%s]", info->remote_address);
1708 tds_activation_info_list = g_slist_remove(tds_activation_info_list, info);
1709 if (info->remote_address)
1710 g_free(info->remote_address);
1712 g_free(info->sender);
1713 if (info->activation_timeout_id > 0) {
1714 g_source_remove(info->activation_timeout_id);
1715 info->activation_timeout_id = 0;
1720 static void __bt_tds_remove_data_read_req_info(bt_tds_data_read_req_info *info)
1722 BT_DBG("Removing Read Req Info [%s]", info->remote_address);
1724 tds_data_read_req_info_list = g_slist_remove(tds_data_read_req_info_list, info);
1725 if (info->remote_address)
1726 g_free(info->remote_address);
1728 g_free(info->sender);
1732 static void __bt_tds_send_indication_event(bt_tds_activation_info *info,
1733 unsigned char *buffer, int len)
1738 tds_data = g_variant_new_from_data((const GVariantType *)"ay",
1739 buffer, len, TRUE, NULL, NULL);
1741 BT_DBG("Send Indication event to sender");
1742 param = g_variant_new("(s@ay)", info->remote_address, tds_data);
1743 _bt_send_event_to_dest(info->sender, BT_TDS_EVENT,
1744 BLUETOOTH_EVENT_TDS_ACTIVATION_INDICATION,
1747 /* Remove info from list */
1748 __bt_tds_remove_indication_info(info);
1751 void _bt_tds_check_indication(const char *path, GVariant *msg)
1753 char address[BT_ADDRESS_STRING_SIZE] = {0};
1754 bt_tds_activation_info *info = NULL;
1755 unsigned char *buffer = NULL;
1758 GVariant *value = NULL;
1761 _bt_convert_device_path_to_address(path, address);
1762 info = __bt_tds_activation_info_by_address(address);
1765 g_variant_get(msg, "(is@ay)", NULL, NULL, &value);
1766 len = g_variant_get_size(value);
1767 BT_DBG("Indication data from Provider len[%d]", len);
1769 buffer = (unsigned char *)g_variant_get_data(value);
1771 for (i = 0; i < len; i++)
1772 BT_DBG("%.2x", buffer[i]);
1776 if (info->activation_timeout_id > 0)
1777 g_source_remove(info->activation_timeout_id);
1779 /* Send Indication & info removed internally */
1780 __bt_tds_send_indication_event(info, buffer, len);
1781 g_variant_unref(value);