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.
19 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
21 #include <gio/gunixfdlist.h>
22 #include <sys/socket.h>
25 #include "bluetooth-api.h"
26 #include "bt-internal-types.h"
28 #include "bt-common.h"
29 #include "bt-request-sender.h"
30 #include "bt-event-handler.h"
32 #ifdef TIZEN_FEATURE_BT_DPM
36 #define BLUETOOTH_SOCK_CONNECT_INFO_LEN 16
38 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
40 static GSList *rfcomm_nodes;
43 bluetooth_device_address_t addr;
46 gboolean disconnected;
55 guint disconnect_idle_id;
58 static rfcomm_info_t *__find_rfcomm_info_with_id(int id)
62 for (l = rfcomm_nodes; l != NULL; l = l->next) {
63 rfcomm_info_t *info = l->data;
72 static rfcomm_info_t *__find_rfcomm_info_with_fd(int fd)
77 for (l = rfcomm_nodes; l != NULL; l = l->next) {
78 rfcomm_info_t *info = l->data;
80 for (ll = info->rfcomm_conns; ll; ll = ll->next) {
81 rfcomm_conn_t *conn = ll->data;
83 if (conn && conn->fd == fd)
91 static rfcomm_info_t *__find_rfcomm_info_with_path(const gchar *path)
95 for (l = rfcomm_nodes; l != NULL; l = l->next) {
96 rfcomm_info_t *info = l->data;
98 if (g_strcmp0(info->path, path) == 0)
105 static rfcomm_info_t *__find_rfcomm_info_with_uuid(const char *uuid)
109 for (l = rfcomm_nodes; l != NULL; l = l->next) {
110 rfcomm_info_t *info = l->data;
112 if (g_strcmp0(info->uuid, uuid) == 0)
119 static rfcomm_conn_t *__find_rfcomm_conn_with_fd(rfcomm_info_t *info,
125 for (l = info->rfcomm_conns; l; l = l->next) {
128 if (conn && conn->fd == fd)
135 static void __rfcomm_remove_conn(rfcomm_info_t *info, int fd)
139 conn = __find_rfcomm_conn_with_fd(info, fd);
143 info->rfcomm_conns = g_slist_remove(info->rfcomm_conns, conn);
145 if (conn->watch_id > 0)
146 g_source_remove(conn->watch_id);
150 gboolean _check_uuid_path(char *path, char *uuid)
152 rfcomm_info_t *info = NULL;
153 info = __find_rfcomm_info_with_path(path);
157 if (strcmp(info->uuid, uuid) == 0)
163 static void __connected_cb(rfcomm_info_t *info, rfcomm_conn_t *conn,
164 bt_event_info_t *event_info)
166 bluetooth_rfcomm_connection_t conn_info;
168 memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t));
170 conn_info.device_role = RFCOMM_ROLE_SERVER;
171 g_strlcpy(conn_info.uuid, info->uuid, BLUETOOTH_UUID_STRING_MAX);
172 conn_info.socket_fd = conn->fd;
173 conn_info.device_addr = conn->addr;
174 conn_info.server_id = info->id;
176 BT_INFO_C("### Connected [RFCOMM Server]");
177 _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_CONNECTED,
178 BLUETOOTH_ERROR_NONE, &conn_info,
179 event_info->cb, event_info->user_data);
182 static void __rfcomm_server_disconnect_conn(rfcomm_conn_t *conn,
185 bluetooth_rfcomm_disconnection_t disconn_info;
186 bt_event_info_t *event_info;
191 if (conn->disconnected == FALSE)
194 if (conn->watch_id > 0) {
195 g_source_remove(conn->watch_id);
199 event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT);
200 if (event_info == NULL) {
201 BT_ERR("event_info is NULL");
202 __rfcomm_remove_conn(info, conn->fd);
206 memset(&disconn_info, 0x00, sizeof(bluetooth_rfcomm_disconnection_t));
207 disconn_info.device_role = RFCOMM_ROLE_SERVER;
208 g_strlcpy(disconn_info.uuid, info->uuid, BLUETOOTH_UUID_STRING_MAX);
209 disconn_info.device_addr = conn->addr;
211 BT_INFO("Disconnected FD [%d]", conn->fd);
212 disconn_info.socket_fd = conn->fd;
214 _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DISCONNECTED,
215 BLUETOOTH_ERROR_NONE, &disconn_info,
216 event_info->cb, event_info->user_data);
218 __rfcomm_remove_conn(info, conn->fd);
221 static gboolean __rfcomm_server_disconnect(rfcomm_info_t *info)
223 BT_INFO_C("### Disconnected [RFCOMM Server]");
225 if (g_slist_find(rfcomm_nodes, info) == NULL) {
226 BT_INFO("rfcomm resource is already freed");
230 info->disconnect_idle_id = 0;
232 g_slist_foreach(info->rfcomm_conns,
233 (GFunc)__rfcomm_server_disconnect_conn, info);
239 static gboolean __is_error_by_disconnect(GError *err)
241 return !g_strcmp0(err->message, "Connection reset by peer") ||
242 !g_strcmp0(err->message, "Connection timed out") ||
243 !g_strcmp0(err->message, "Software caused connection abort");
246 static gboolean __data_received_cb(GIOChannel *chan, GIOCondition cond,
251 int result = BLUETOOTH_ERROR_NONE;
252 rfcomm_info_t *info = data;
254 bt_event_info_t *event_info;
255 bluetooth_rfcomm_received_data_t data_r;
256 GIOStatus status = G_IO_STATUS_NORMAL;
260 retv_if(info == NULL, FALSE);
262 fd = g_io_channel_unix_get_fd(chan);
263 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
264 BT_ERR_C("RFComm Server disconnected: %d", fd);
266 if (info->disconnect_idle_id > 0) {
267 BT_INFO("Disconnect idle still not process remove source");
268 g_source_remove(info->disconnect_idle_id);
269 info->disconnect_idle_id = 0;
272 conn = __find_rfcomm_conn_with_fd(info, fd);
274 BT_ERR("No Connection info found with FD [%d]", fd);
278 if (conn->disconnected == FALSE) {
280 conn->disconnected = TRUE;
282 __rfcomm_server_disconnect(info);
286 buffer = g_malloc0(BT_RFCOMM_BUFFER_LEN + 1);
288 status = g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_LEN,
290 if (status != G_IO_STATUS_NORMAL) {
291 BT_ERR("IO Channel read is failed with %d", status);
297 BT_ERR("IO Channel read error [%s]", err->message);
298 if (status == G_IO_STATUS_ERROR &&
299 __is_error_by_disconnect(err)) {
300 BT_ERR("cond : %d", cond);
303 if (info->disconnect_idle_id > 0) {
304 BT_INFO("Disconnect idle still not process remove source");
305 g_source_remove(info->disconnect_idle_id);
306 info->disconnect_idle_id = 0;
309 conn = __find_rfcomm_conn_with_fd(info, fd);
311 BT_ERR("No Connection info found with FD [%d]", fd);
315 if (conn->disconnected == FALSE) {
317 conn->disconnected = TRUE;
319 __rfcomm_server_disconnect(info);
327 BT_ERR("Length is zero");
329 event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT);
330 if (event_info == NULL) {
331 BT_ERR("event_info is NULL. Unable to invoke the callback");
336 data_r.socket_fd = fd;
337 data_r.buffer_size = len;
338 data_r.buffer = buffer;
340 _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED,
342 event_info->cb, event_info->user_data);
344 if (bluetooth_get_battery_monitor_state()) {
345 int ret = _bt_common_send_rfcomm_rx_details(&data_r);
346 if (ret != BLUETOOTH_ERROR_NONE)
347 BT_ERR("RFCOMM received data details not sent to battery monitor frwk");
355 int new_server_connection(const char *path, int fd, bluetooth_device_address_t *addr)
360 bt_event_info_t *event_info;
362 BT_INFO("%s %d", path, fd);
364 info = __find_rfcomm_info_with_path(path);
366 BT_ERR("rfcomm info is NULL");
370 #ifdef TIZEN_FEATURE_BT_DPM
371 if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
374 BT_ERR("Not allow to use SPP profile");
377 _bt_convert_addr_type_to_string(addr_str, addr->addr);
378 _bt_disconnect_ext_profile(addr_str, info->path);
384 conn = g_new0(rfcomm_conn_t, 1);
386 memcpy(&conn->addr, addr, sizeof(bluetooth_device_address_t));
387 info->rfcomm_conns = g_slist_append(info->rfcomm_conns, conn);
389 data_io = g_io_channel_unix_new(conn->fd);
391 g_io_channel_set_encoding(data_io, NULL, NULL);
392 g_io_channel_set_flags(data_io, G_IO_FLAG_NONBLOCK, NULL);
394 conn->watch_id = g_io_add_watch(data_io,
395 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
396 __data_received_cb, info);
398 g_io_channel_unref(data_io);
400 event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT);
402 __connected_cb(info, conn, event_info);
407 static rfcomm_info_t *__register_method()
414 id = __rfcomm_assign_id();
418 path = g_strdup_printf("/org/socket/server/%d/%d", getpid(), id);
420 object_id = _bt_register_new_conn(path, new_server_connection);
422 __rfcomm_delete_id(id);
425 info = g_new0(rfcomm_info_t, 1);
426 info->object_id = (guint)object_id;
430 rfcomm_nodes = g_slist_append(rfcomm_nodes, info);
435 static rfcomm_info_t *__register_method_2(const char *path, const char *bus_name)
440 object_id = _bt_register_new_conn_ex(path, bus_name, new_server_connection);
444 info = g_new0(rfcomm_info_t, 1);
445 info->object_id = (guint)object_id;
446 info->path = g_strdup(path);
449 rfcomm_nodes = g_slist_append(rfcomm_nodes, info);
454 void free_rfcomm_conn(rfcomm_conn_t *conn, rfcomm_info_t *info)
456 if (conn->disconnected == FALSE) {
458 conn->disconnected = TRUE;
460 __rfcomm_server_disconnect_conn(conn, info);
463 void free_rfcomm_info(rfcomm_info_t *info)
467 if (info->disconnect_idle_id > 0) {
468 BT_INFO("Disconnect idle still not process remove source");
469 g_source_remove(info->disconnect_idle_id);
470 info->disconnect_idle_id = 0;
473 __rfcomm_delete_id(info->id);
474 _bt_unregister_gdbus(info->object_id);
476 g_slist_foreach(info->rfcomm_conns, (GFunc)free_rfcomm_conn, info);
483 void _bt_rfcomm_server_free_all(void)
485 BT_DBG("Free all the servers");
487 g_slist_free_full(rfcomm_nodes, (GDestroyNotify)free_rfcomm_info);
491 void _bt_rfcomm_server_disconnect_all(void)
497 BT_INFO(" ### Disconnect all RFCOMM server connections");
499 for (server = rfcomm_nodes; server; ) {
500 rfcomm_info_t *info = server->data;
502 for (conn = info->rfcomm_conns; conn; conn = conn->next) {
503 rfcomm_conn_t *conn_info = conn->data;
505 if (conn_info == NULL)
508 if (conn_info->watch_id == 0 || conn_info->disconnected)
511 close(conn_info->fd);
512 conn_info->disconnected = TRUE;
514 _bt_convert_addr_type_to_string(addr,
515 conn_info->addr.addr);
516 _bt_disconnect_ext_profile(addr, info->path);
519 server = server->next;
520 __rfcomm_server_disconnect(info);
527 #define BT_RFCOMM_SERVER_ID_MAX 254
530 char addr[BT_ADDRESS_STRING_SIZE];
534 } rfcomm_remote_client_info_t;
537 char uuid[BLUETOOTH_UUID_STRING_MAX];
541 int max_pending_conn;
542 gboolean auto_accept;
543 char pending_addr[BT_ADDRESS_STRING_SIZE];
545 } rfcomm_server_info_t;
547 static GSList *rfcomm_servers;
548 static gboolean id_used[BT_RFCOMM_SERVER_ID_MAX];
551 int __rfcomm_assign_server_id(void)
555 BT_DBG("latest_id: %d", latest_id);
557 index = latest_id + 1;
559 if (index >= BT_RFCOMM_SERVER_ID_MAX)
562 BT_DBG("index: %d", index);
564 while (id_used[index] == TRUE) {
565 if (index == latest_id) {
566 /* No available ID */
567 BT_ERR("All request ID is used");
573 if (index >= BT_RFCOMM_SERVER_ID_MAX)
578 id_used[index] = TRUE;
580 BT_DBG("Assigned Id: %d", latest_id);
585 void __rfcomm_delete_server_id(int id)
587 ret_if(id >= BT_RFCOMM_SERVER_ID_MAX);
592 /* Next server will use this ID */
596 static rfcomm_server_info_t *__get_rfcomm_server_info_with_uuid(const char *uuid)
603 for (l = rfcomm_servers; l != NULL; l = l->next) {
604 rfcomm_server_info_t *info = l->data;
606 if (!strncasecmp(info->uuid, uuid, strlen(info->uuid)))
613 int _get_rfcomm_server_id(char *uuid, gboolean *auto_accept)
615 rfcomm_server_info_t *server_info;
617 server_info = __get_rfcomm_server_info_with_uuid(uuid);
621 *auto_accept = server_info->auto_accept;
622 return server_info->server_id;
625 static rfcomm_server_info_t *__get_rfcomm_server_info_with_id(int server_id)
629 for (l = rfcomm_servers; l != NULL; l = l->next) {
630 rfcomm_server_info_t *info = l->data;
634 BT_DBG("info->server_fd: %d, sock_fd:%d", info->server_id, server_id);
635 if (info->server_id == server_id)
642 void _bt_rfcomm_server_set_pending_conn(int server_id, char *address)
644 rfcomm_server_info_t *server_info;
650 server_info = __get_rfcomm_server_info_with_id(server_id);
654 g_strlcpy(server_info->pending_addr, address, BT_ADDRESS_STRING_SIZE);
657 static rfcomm_remote_client_info_t *__get_rfcomm_rem_client_info_with_fd(int sock_fd)
662 for (l = rfcomm_servers; l != NULL; l = l->next) {
663 rfcomm_server_info_t *info = l->data;
668 for (l1 = info->conn_list; l1 != NULL; l1 = l1->next) {
669 rfcomm_remote_client_info_t *client_info = l1->data;
673 if (client_info->sock_fd == sock_fd)
681 static rfcomm_remote_client_info_t *__get_rfcomm_rem_client_info_with_addr(char *addr)
686 retv_if(NULL == addr, NULL);
688 for (l = rfcomm_servers; l != NULL; l = l->next) {
689 rfcomm_server_info_t *info = l->data;
694 for (l1 = info->conn_list; l1 != NULL; l1 = l1->next) {
695 rfcomm_remote_client_info_t *client_info = l1->data;
699 if (!strncasecmp(client_info->addr, addr, strlen(client_info->addr)))
707 static void __remove_remote_client_info(rfcomm_remote_client_info_t *rem_client)
711 if (rem_client == NULL)
714 if (0 < rem_client->sock_fd) {
715 shutdown(rem_client->sock_fd, SHUT_RDWR);
716 close(rem_client->sock_fd);
719 if (rem_client->watch_id > 0)
720 g_source_remove(rem_client->watch_id);
727 static void __handle_rfcomm_client_disconnected(rfcomm_server_info_t *server_info,
728 rfcomm_remote_client_info_t *rem_client)
730 bluetooth_rfcomm_disconnection_t disconn_info;
731 bt_event_info_t *event_info;
735 if (rem_client == NULL || server_info == NULL)
738 event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT);
739 if (event_info == NULL)
742 memset(&disconn_info, 0x00, sizeof(bluetooth_rfcomm_disconnection_t));
743 disconn_info.device_role = RFCOMM_ROLE_SERVER;
744 g_strlcpy(disconn_info.uuid, server_info->uuid, BLUETOOTH_UUID_STRING_MAX);
745 _bt_convert_addr_string_to_type(disconn_info.device_addr.addr, rem_client->addr);
746 BT_DBG("Disconnected FD [%d]", rem_client->sock_fd);
747 disconn_info.socket_fd = rem_client->sock_fd;
749 _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DISCONNECTED,
750 BLUETOOTH_ERROR_NONE, &disconn_info,
751 event_info->cb, event_info->user_data);
754 static void __remove_rfcomm_server(rfcomm_server_info_t *info)
756 rfcomm_remote_client_info_t *client_info;
763 rfcomm_servers = g_slist_remove(rfcomm_servers, info);
764 if (info->conn_list) {
766 client_info = info->conn_list->data;
770 info->conn_list = g_slist_remove(info->conn_list, client_info);
771 __handle_rfcomm_client_disconnected(info, client_info);
772 __remove_remote_client_info(client_info);
773 } while (info->conn_list);
776 if (info->server_fd) {
777 shutdown(info->server_fd, SHUT_RDWR);
778 close(info->server_fd);
782 g_source_remove(info->watch_id);
784 __rfcomm_delete_server_id(info->server_id);
790 static void __connected_cb(rfcomm_remote_client_info_t *client_info, bt_event_info_t *event_info)
792 bluetooth_rfcomm_connection_t conn_info;
793 rfcomm_server_info_t *server_info;
795 server_info = __get_rfcomm_server_info_with_id(client_info->server_id);
796 ret_if(server_info == NULL);
798 memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t));
799 conn_info.device_role = RFCOMM_ROLE_SERVER;
800 g_strlcpy(conn_info.uuid, server_info->uuid, BLUETOOTH_UUID_STRING_MAX);
801 conn_info.socket_fd = client_info->sock_fd;
802 _bt_convert_addr_string_to_type(conn_info.device_addr.addr, client_info->addr);
803 conn_info.server_id = server_info->server_id;
805 BT_INFO_C("Connected [RFCOMM Server]");
806 _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_CONNECTED,
807 BLUETOOTH_ERROR_NONE, &conn_info,
808 event_info->cb, event_info->user_data);
811 static int __process_cmsg(struct msghdr *msg)
814 struct cmsghdr *cmsg_ptr = NULL;
816 for (cmsg_ptr = CMSG_FIRSTHDR(msg); cmsg_ptr != NULL;
817 cmsg_ptr = CMSG_NXTHDR(msg, cmsg_ptr)) {
819 if (cmsg_ptr->cmsg_level != SOL_SOCKET)
822 if (cmsg_ptr->cmsg_type == SCM_RIGHTS) {
823 //int *desc = (int *)CMSG_DATA(cmsg_ptr);
825 = ((cmsg_ptr->cmsg_len - CMSG_LEN(0)) / sizeof(int));
828 BT_ERR("ERROR Invalid count of descriptors");
833 memcpy(&sock_fd, CMSG_DATA(cmsg_ptr), sizeof(sock_fd));
834 BT_DBG("Remote client fd: %d", sock_fd);
841 static int __read_incomming_client_connection(
842 int server_fd, char *buf, unsigned int len, int *client_fd)
847 struct cmsghdr cmsgbuf[2 * sizeof(struct cmsghdr) + 4];
850 retv_if(0 > server_fd, -1);
851 retv_if(NULL == client_fd, -1);
853 BT_INFO("server_fd = %d", server_fd);
855 memset(&msg, 0, sizeof(msg));
856 memset(&iv, 0, sizeof(iv));
862 msg.msg_control = cmsgbuf;
863 msg.msg_controllen = sizeof(cmsgbuf);
865 for (retryCount = 0; retryCount < 5; retryCount++) {
866 ret = recvmsg(server_fd, &msg, 0);
867 BT_DBG("recvmsg ret = %d", ret);
868 if (ret < 0 && errno == EINTR)
874 if (ret < 0 && errno == EPIPE) {
875 /* End of stream, server listining stopped */
876 BT_ERR("EOS errno: %d", errno);
881 BT_ERR("Ret errno: %d", errno);
885 if ((msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) != 0) {
886 BT_ERR("MSG Flags errno: %d", errno);
890 BT_INFO("Connection received");
891 *client_fd = __process_cmsg(&msg);
893 BT_ERR("Invalid client_fd received");
898 static gboolean __data_received_cb(GIOChannel *chan, GIOCondition cond,
903 int result = BLUETOOTH_ERROR_NONE;
904 bt_event_info_t *event_info;
905 bluetooth_rfcomm_received_data_t data_r;
906 GIOStatus status = G_IO_STATUS_NORMAL;
908 rfcomm_remote_client_info_t *client_info = data;
909 rfcomm_server_info_t *server_info;
911 retv_if(client_info == NULL, FALSE);
913 server_info = __get_rfcomm_server_info_with_id(client_info->server_id);
915 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
916 BT_ERR_C("RFComm Server disconnected: %d", client_info->sock_fd);
920 buffer = g_malloc0(BT_RFCOMM_BUFFER_LEN + 1);
921 status = g_io_channel_read_chars(chan, buffer,
922 BT_RFCOMM_BUFFER_LEN, &len, &err);
923 if (status != G_IO_STATUS_NORMAL) {
924 BT_ERR("IO Channel read is failed with %d", status);
927 BT_ERR("IO Channel read error [%s]", err->message);
928 if (status == G_IO_STATUS_ERROR &&
929 !g_strcmp0(err->message, "Connection reset by peer")) {
930 BT_ERR("cond : %d", cond);
940 BT_ERR("Length is zero, remote end hang up");
944 event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT);
945 if (event_info == NULL) {
950 data_r.socket_fd = client_info->sock_fd;
951 data_r.buffer_size = len;
952 data_r.buffer = buffer;
954 _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED,
956 event_info->cb, event_info->user_data);
963 BT_ERR("Failure occured, remove client connection");
964 server_info->conn_list = g_slist_remove(
965 server_info->conn_list, client_info);
966 __handle_rfcomm_client_disconnected(server_info, client_info);
967 __remove_remote_client_info(client_info);
971 static gboolean __new_connection_request_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
978 char buf[BLUETOOTH_SOCK_CONNECT_INFO_LEN];
979 unsigned char addr[BT_ADDRESS_LENGTH_MAX];
981 bt_event_info_t *event_info;
983 rfcomm_remote_client_info_t *rem_client;
984 rfcomm_server_info_t *server_info = data;
987 BT_ERR("Server info is invalid");
991 if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
992 BT_INFO("RFCOMM Server with fd:%d is closed with cond:0x%X",
993 server_info->server_fd, cond);
997 BT_INFO("Server fd: %d", server_info->server_fd);
998 len = __read_incomming_client_connection(
999 server_info->server_fd, buf, BLUETOOTH_SOCK_CONNECT_INFO_LEN, &client_fd);
1000 BT_DBG("Socket Read len: %d", len);
1002 BT_ERR("Listen stopped");
1004 } else if (len != BLUETOOTH_SOCK_CONNECT_INFO_LEN) {
1005 BT_ERR("Read length is not same as socket info length");
1010 /* Read size of data */
1011 size = buf[len] | (buf[len + 1] << 8);
1014 /* Read bluetooth address */
1015 memcpy(addr, buf + len, BT_ADDRESS_LENGTH_MAX);
1016 len += BT_ADDRESS_LENGTH_MAX;
1019 channel = buf[len] | (buf[len + 1] << 8) |
1020 (buf[len + 2] << 16) | (buf[len + 3] << 24);
1024 status = buf[len] | (buf[len + 1] << 8) |
1025 (buf[len + 2] << 16) | (buf[len + 3] << 24);
1028 BT_DBG("size: %d, channel: %d, status: %d", size, channel, status);
1030 rem_client = g_malloc0(sizeof(rfcomm_remote_client_info_t));
1031 rem_client->sock_fd = client_fd;
1032 rem_client->server_id = server_info->server_id;
1033 _bt_convert_addr_type_to_string(rem_client->addr, addr);
1035 BT_INFO("New client [%s] connection with socket_fd: %d, server_id: %d",
1036 rem_client->addr, rem_client->sock_fd, rem_client->server_id);
1038 io = g_io_channel_unix_new(rem_client->sock_fd);
1039 g_io_channel_set_encoding(io, NULL, NULL);
1040 g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL);
1041 rem_client->watch_id = g_io_add_watch(io,
1042 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
1043 __data_received_cb, rem_client);
1044 g_io_channel_unref(io);
1046 server_info->conn_list = g_slist_append(server_info->conn_list, rem_client);
1047 event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT);
1049 __connected_cb(rem_client, event_info);
1054 /* Error occurred, Remove RFCOMM server*/
1055 __remove_rfcomm_server(server_info);
1059 static int __rfcomm_listen(rfcomm_server_info_t *server_info, bool accept)
1062 GUnixFDList *out_fd_list = NULL;
1063 GIOChannel *server_io;
1065 retv_if(server_info == NULL, BLUETOOTH_ERROR_INTERNAL);
1068 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1070 if (accept == false) {
1071 g_array_append_vals(in_param1, server_info->uuid, BLUETOOTH_UUID_STRING_MAX);
1072 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_RFCOMM_LISTEN,
1073 in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
1075 g_array_append_vals(in_param1, server_info->uuid, BLUETOOTH_UUID_STRING_MAX);
1076 result = _bt_send_request_with_unix_fd_list(BT_BLUEZ_SERVICE, BT_RFCOMM_LISTEN_AND_ACCEPT,
1077 in_param1, in_param2, in_param3, in_param4, NULL, &out_param, &out_fd_list);
1080 BT_DBG("result: %x", result);
1081 if (result != BLUETOOTH_ERROR_NONE) {
1082 BT_ERR("Fail to send request");
1084 } else if (NULL == out_fd_list) {
1085 BT_ERR("out_fd_list is NULL");
1086 return BLUETOOTH_ERROR_INTERNAL;
1092 return BLUETOOTH_ERROR_INTERNAL;
1094 fd_list_array = g_unix_fd_list_steal_fds(out_fd_list, &len);
1095 BT_INFO("Num fds in fd_list is : %d, fd_list[0]: %d", len, fd_list_array[0]);
1096 server_info->server_fd = fd_list_array[0];
1097 BT_INFO("Socket fd: %d", server_info->server_fd);
1099 g_free(fd_list_array);
1100 g_object_unref(out_fd_list);
1103 server_io = g_io_channel_unix_new(server_info->server_fd);
1104 g_io_channel_set_encoding(server_io, NULL, NULL);
1105 g_io_channel_set_flags(server_io, G_IO_FLAG_NONBLOCK, NULL);
1106 server_info->watch_id = g_io_add_watch(server_io,
1107 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
1108 __new_connection_request_cb, server_info);
1109 g_io_channel_unref(server_io);
1111 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1113 return BLUETOOTH_ERROR_NONE;
1117 BT_EXPORT_API int bluetooth_rfcomm_create_socket(const char *uuid)
1119 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1120 rfcomm_info_t *info;
1122 rfcomm_server_info_t *server_info;
1125 BT_CHECK_ENABLED(return);
1126 BT_CHECK_PARAMETER(uuid, return);
1127 BT_INFO("UUID Provided %s", uuid);
1129 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_RFCOMM_CREATE_SOCKET)
1130 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1131 BT_ERR("Don't have a privilege to use this API");
1132 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1135 #ifdef TIZEN_FEATURE_BT_DPM
1136 if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
1137 BT_ERR("Not allow to use SPP profile");
1138 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
1142 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1143 BT_INFO("<<<<<<<<< RFCOMM Create socket from app >>>>>>>>>");
1144 info = __register_method();
1148 info->uuid = g_strdup(uuid);
1149 info->disconnect_idle_id = 0;
1152 BT_INFO("<<<<<<<<< RFCOMM Create socket from app >>>>>>>>>");
1154 server_info = __get_rfcomm_server_info_with_uuid(uuid);
1156 server_info = g_malloc0(sizeof(rfcomm_server_info_t));
1157 g_strlcpy(server_info->uuid, uuid, BLUETOOTH_UUID_STRING_MAX);
1158 server_info->server_id = __rfcomm_assign_server_id();
1159 server_info->server_fd = -1;
1160 server_info->watch_id = -1;
1161 server_info->auto_accept = FALSE;
1162 rfcomm_servers = g_slist_append(rfcomm_servers, server_info);
1164 return server_info->server_id;
1168 BT_EXPORT_API int bluetooth_rfcomm_create_socket_ex(const char *uuid, const char *bus_name, const char *path)
1170 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1171 rfcomm_info_t *info;
1173 BT_CHECK_ENABLED(return);
1174 BT_CHECK_PARAMETER(path, return);
1175 BT_INFO("PATH Provided %s", path);
1177 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_RFCOMM_CREATE_SOCKET_EX)
1178 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1179 BT_ERR("Don't have a privilege to use this API");
1180 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1183 #ifdef TIZEN_FEATURE_BT_DPM
1184 if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
1185 BT_ERR("Not allow to use SPP profile");
1186 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
1190 BT_INFO("<<<<<<<<< RFCOMM Create socket from app >>>>>>>>>");
1191 info = __register_method_2(path, bus_name);
1193 return BLUETOOTH_ERROR_IN_PROGRESS;
1194 info->uuid = g_strdup(uuid);
1195 info->disconnect_idle_id = 0;
1197 return BLUETOOTH_ERROR_NONE;
1199 return BLUETOOTH_ERROR_NOT_SUPPORT;
1204 BT_EXPORT_API int bluetooth_rfcomm_remove_socket(int id)
1206 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1207 rfcomm_info_t *info;
1209 rfcomm_server_info_t *server_info;
1212 BT_CHECK_ENABLED(return);
1214 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_RFCOMM_REMOVE_SOCKET)
1215 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1216 BT_ERR("Don't have a privilege to use this API");
1217 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1221 BT_ERR("Invalid ID");
1222 return BLUETOOTH_ERROR_INVALID_PARAM;
1225 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1226 BT_INFO("RFCOMM Remove socket request from app, ID [%d]", id);
1228 info = __find_rfcomm_info_with_id(id);
1230 return BLUETOOTH_ERROR_INVALID_PARAM;
1232 _bt_unregister_osp_server_in_agent(BT_RFCOMM_SERVER, info->uuid);
1233 _bt_unregister_profile(info->path);
1235 rfcomm_nodes = g_slist_remove(rfcomm_nodes, info);
1236 free_rfcomm_info(info);
1238 return BLUETOOTH_ERROR_NONE;
1240 BT_INFO("<<<<<<<<< RFCOMM Remove socket request from app, fd=[%d] >>>>>>>>>>>", socket_fd);
1242 server_info = __get_rfcomm_server_info_with_id(id);
1244 BT_ERR("server_info not found for socket_fd: %d", id);
1245 return BLUETOOTH_ERROR_INVALID_PARAM;
1248 __remove_rfcomm_server(server_info);
1250 return BLUETOOTH_ERROR_NONE;
1254 BT_EXPORT_API int bluetooth_rfcomm_remove_socket_ex(const char *uuid)
1256 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1257 rfcomm_info_t *info;
1259 BT_CHECK_ENABLED(return);
1261 if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_RFCOMM_REMOVE_SOCKET)
1262 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
1263 BT_ERR("Don't have a privilege to use this API");
1264 return BLUETOOTH_ERROR_PERMISSION_DEINED;
1267 BT_INFO("RFCOMM Remove socket request from app, uuid=[%s]", uuid);
1269 info = __find_rfcomm_info_with_uuid(uuid);
1271 return BLUETOOTH_ERROR_INVALID_PARAM;
1273 _bt_unregister_osp_server_in_agent(BT_RFCOMM_SERVER, info->uuid);
1274 _bt_unregister_profile(info->path);
1276 rfcomm_nodes = g_slist_remove(rfcomm_nodes, info);
1277 free_rfcomm_info(info);
1279 return BLUETOOTH_ERROR_NONE;
1281 return BLUETOOTH_ERROR_NOT_SUPPORT;
1285 BT_EXPORT_API int bluetooth_rfcomm_server_disconnect(int socket_fd)
1287 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1288 rfcomm_info_t *info;
1289 rfcomm_conn_t *conn;
1293 BT_INFO(" ### Disconnect RFCOMM server");
1294 if (socket_fd < 0) {
1295 BT_ERR("Invalid FD");
1296 return BLUETOOTH_ERROR_INVALID_PARAM;
1299 info = __find_rfcomm_info_with_fd(socket_fd);
1301 return BLUETOOTH_ERROR_INVALID_PARAM;
1303 conn = __find_rfcomm_conn_with_fd(info, socket_fd);
1305 return BLUETOOTH_ERROR_INVALID_PARAM;
1307 if (conn->watch_id == 0 || conn->disconnected)
1308 return BLUETOOTH_ERROR_NOT_CONNECTED;
1311 conn->disconnected = TRUE;
1313 _bt_convert_addr_type_to_string(address, conn->addr.addr);
1315 BT_DBG("Address %s", address);
1316 _bt_disconnect_ext_profile(address, info->path);
1318 if (info->disconnect_idle_id == 0)
1319 info->disconnect_idle_id = g_idle_add(
1320 (GSourceFunc)__rfcomm_server_disconnect, info);
1323 return BLUETOOTH_ERROR_NONE;
1325 rfcomm_remote_client_info_t *client_info;
1327 BT_CHECK_ENABLED(return);
1329 BT_INFO(">>>>>>>>RFCOMM server disconnect request from APP>>>>>>>>>");
1330 if (socket_fd < 0) {
1331 BT_ERR("Invalid FD");
1332 return BLUETOOTH_ERROR_INVALID_PARAM;
1335 client_info = __get_rfcomm_rem_client_info_with_fd(socket_fd);
1337 BT_ERR("client_info not found for socket_fd: %d", socket_fd);
1338 return BLUETOOTH_ERROR_NOT_CONNECTED;
1341 if (client_info->sock_fd) {
1342 shutdown(client_info->sock_fd, SHUT_RDWR);
1343 close(client_info->sock_fd);
1344 client_info->sock_fd = -1;
1347 return BLUETOOTH_ERROR_NONE;
1351 BT_EXPORT_API gboolean bluetooth_rfcomm_is_server_uuid_available(const char *uuid)
1354 gboolean available = TRUE;
1355 char uuid_str[BLUETOOTH_UUID_STRING_MAX];
1357 retv_if(uuid == NULL, FALSE);
1358 retv_if(bluetooth_check_adapter() ==
1359 BLUETOOTH_ADAPTER_DISABLED, FALSE);
1362 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1364 g_strlcpy(uuid_str, uuid, sizeof(uuid_str));
1365 g_array_append_vals(in_param1, uuid_str, BLUETOOTH_UUID_STRING_MAX);
1367 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_IS_UUID_AVAILABLE,
1368 in_param1, in_param2, in_param3, in_param4, &out_param);
1370 BT_DBG("result: %x", result);
1372 if (result == BLUETOOTH_ERROR_NONE)
1373 available = g_array_index(out_param, gboolean, 0);
1375 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1377 BT_DBG("available: %d", available);
1382 BT_EXPORT_API int bluetooth_rfcomm_server_is_connected(const bluetooth_device_address_t *device_address, gboolean *connected)
1384 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1387 rfcomm_info_t *info;
1388 rfcomm_conn_t *conn;
1390 char input_addr[BT_ADDRESS_STRING_SIZE] = { 0 };
1391 rfcomm_remote_client_info_t *info;
1394 BT_CHECK_PARAMETER(device_address, return);
1395 BT_CHECK_PARAMETER(connected, return);
1399 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1400 for (l = rfcomm_nodes; l; l = l->next) {
1403 if (info == NULL || info->rfcomm_conns == NULL)
1406 for (ll = info->rfcomm_conns; ll; ll = ll->next) {
1409 if (memcmp(device_address, &conn->addr,
1410 sizeof(bluetooth_device_address_t)))
1414 return BLUETOOTH_ERROR_NONE;
1418 return BLUETOOTH_ERROR_NONE;
1420 _bt_convert_addr_type_to_string(input_addr, (unsigned char *)device_address->addr);
1421 info = __get_rfcomm_rem_client_info_with_addr(input_addr);
1425 return BLUETOOTH_ERROR_NONE;
1429 BT_EXPORT_API int bluetooth_rfcomm_listen_and_accept(int id, int max_pending_connection)
1431 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1432 rfcomm_info_t *info;
1434 rfcomm_server_info_t *server_info;
1437 BT_CHECK_ENABLED(return);
1439 BT_ERR("Invalid ID");
1440 return BLUETOOTH_ERROR_INVALID_PARAM;
1443 #ifdef TIZEN_FEATURE_BT_DPM
1444 if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
1445 BT_ERR("Not allow to use SPP profile");
1446 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
1450 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1451 BT_INFO("RFCOMM Listen & accept from app");
1453 info = __find_rfcomm_info_with_id(id);
1455 return BLUETOOTH_ERROR_INVALID_PARAM;
1457 bt_register_profile_info_t profile_info;
1460 profile_info.authentication = TRUE;
1461 profile_info.authorization = TRUE;
1462 profile_info.obj_path = info->path;
1463 profile_info.role = NULL;
1464 profile_info.service = info->uuid;
1465 profile_info.uuid = info->uuid;
1467 BT_INFO("uuid %s", profile_info.uuid);
1468 result = _bt_register_profile(&profile_info, TRUE);
1472 BT_INFO("<<<<<<<<< RFCOMM Listen & accept from app >>>>>>>>>>>");
1474 server_info = __get_rfcomm_server_info_with_id(id);
1476 BT_ERR("server_info not found for id: %d", id);
1477 return BLUETOOTH_ERROR_INVALID_PARAM;
1480 if (server_info->server_fd >= 0) {
1481 BT_ERR("server already listining");
1482 return BLUETOOTH_ERROR_DEVICE_BUSY;
1485 server_info->max_pending_conn = max_pending_connection;
1486 server_info->auto_accept = TRUE;
1488 return __rfcomm_listen(server_info, true);
1492 BT_EXPORT_API int bluetooth_rfcomm_listen_and_accept_ex(const char *uuid,
1493 int max_pending_connection,
1494 const char *bus_name, const char *path)
1496 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1497 rfcomm_info_t *info;
1499 BT_CHECK_ENABLED(return);
1501 #ifdef TIZEN_FEATURE_BT_DPM
1502 if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
1503 BT_ERR("Not allow to use SPP profile");
1504 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
1508 BT_INFO("RFCOMM Listen & accept from app");
1510 info = __find_rfcomm_info_with_uuid(uuid);
1512 return BLUETOOTH_ERROR_INVALID_PARAM;
1514 bt_register_profile_info_t profile_info;
1517 profile_info.authentication = TRUE;
1518 profile_info.authorization = TRUE;
1519 profile_info.obj_path = info->path;
1520 profile_info.role = NULL;
1521 profile_info.service = info->uuid;
1522 profile_info.uuid = info->uuid;
1524 BT_INFO("uuid %s", profile_info.uuid);
1525 result = _bt_register_profile_ex(&profile_info, TRUE, bus_name, path);
1529 return BLUETOOTH_ERROR_NOT_SUPPORT;
1533 BT_EXPORT_API int bluetooth_rfcomm_listen(int id, int max_pending_connection)
1535 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1536 rfcomm_info_t *info;
1538 rfcomm_server_info_t *server_info;
1541 BT_CHECK_ENABLED(return);
1543 BT_ERR("Invalid ID");
1544 return BLUETOOTH_ERROR_INVALID_PARAM;
1547 #ifdef TIZEN_FEATURE_BT_DPM
1548 if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
1549 BT_ERR("Not allow to use SPP profile");
1550 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
1554 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1555 BT_INFO("RFCOMM Listen");
1557 info = __find_rfcomm_info_with_id(id);
1559 return BLUETOOTH_ERROR_INVALID_PARAM;
1561 bt_register_profile_info_t profile_info;
1564 profile_info.authentication = TRUE;
1565 profile_info.authorization = TRUE;
1566 profile_info.obj_path = info->path;
1567 profile_info.role = NULL;
1568 profile_info.service = info->uuid;
1569 profile_info.uuid = info->uuid;
1570 BT_INFO("UUID %s", info->uuid);
1571 BT_INFO("PATH %s", info->path);
1572 result = _bt_register_profile_platform(&profile_info, TRUE);
1573 if (result != BLUETOOTH_ERROR_NONE)
1576 return _bt_register_osp_server_in_agent(BT_RFCOMM_SERVER, info->uuid,
1580 BT_INFO("<<<<<<<<< RFCOMM Listen >>>>>>>>>>>");
1582 server_info = __get_rfcomm_server_info_with_id(id);
1584 BT_ERR("server_info not found for id: %d", id);
1585 return BLUETOOTH_ERROR_INVALID_PARAM;
1588 if (server_info->server_fd >= 0) {
1589 BT_ERR("server already listining");
1590 return BLUETOOTH_ERROR_DEVICE_BUSY;
1593 server_info->max_pending_conn = max_pending_connection;
1594 server_info->auto_accept = FALSE;
1595 return __rfcomm_listen(server_info, false);
1599 BT_EXPORT_API int bluetooth_rfcomm_accept_connection(int server_fd)
1602 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1604 rfcomm_server_info_t *server_info;
1607 BT_CHECK_ENABLED(return);
1609 #ifdef TIZEN_FEATURE_BT_DPM
1610 if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
1611 BT_ERR("Not allow to use SPP profile");
1612 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
1616 if (server_fd < 0) {
1617 BT_ERR("Invalid FD");
1618 return BLUETOOTH_ERROR_INVALID_PARAM;
1622 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1624 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1625 g_array_append_vals(in_param1, &server_fd, sizeof(int));
1627 server_info = __get_rfcomm_server_info_with_id(server_fd);
1629 BT_ERR("No server with fd: %d", server_fd);
1630 return BLUETOOTH_ERROR_INVALID_PARAM;
1633 g_array_append_vals(in_param1, server_info->pending_addr, BT_ADDRESS_STRING_SIZE);
1636 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_ACCEPT_CONNECTION,
1637 in_param1, in_param2, in_param3, in_param4, &out_param);
1639 BT_DBG("result: %x", result);
1641 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1646 BT_EXPORT_API int bluetooth_rfcomm_reject_connection(int server_fd)
1649 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1651 rfcomm_server_info_t *server_info;
1654 BT_CHECK_ENABLED(return);
1656 if (server_fd < 0) {
1657 BT_ERR("Invalid FD");
1658 return BLUETOOTH_ERROR_INVALID_PARAM;
1664 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1666 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
1667 g_array_append_vals(in_param1, &server_fd, sizeof(int));
1669 server_info = __get_rfcomm_server_info_with_id(server_fd);
1671 BT_ERR("No server with fd: %d", server_fd);
1672 return BLUETOOTH_ERROR_INVALID_PARAM;
1675 g_array_append_vals(in_param1, server_info->pending_addr, BT_ADDRESS_STRING_SIZE);
1677 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_REJECT_CONNECTION,
1678 in_param1, in_param2, in_param3, in_param4, &out_param);
1680 BT_DBG("result: %x", result);
1682 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);