4 * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
6 * Author: Atul Kumar Rai <a.rai@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
25 #include <gio/gunixfdlist.h>
29 #include "bluetooth-api.h"
30 #include "bt-internal-types.h"
31 #include "bt-request-handler.h"
32 #include "bt-service-util.h"
33 #include "bt-service-event.h"
34 #include "bt-service-common.h"
35 #include "bt-service-rfcomm.h"
36 #include "bt-service-socket.h"
37 #include "bt-service-battery-monitor.h"
43 } bt_rfcomm_conn_info_t;
45 static GSList *rfcomm_conn_list = NULL;
47 static void __bt_rfcomm_reply_pending_request(int result,
48 int service_function, void *user_data, unsigned int size)
52 invocation_info_t *req_info;
54 /* Get method invocation context */
55 for (l = _bt_get_invocation_list(); l != NULL; ) {
58 if (req_info == NULL || req_info->service_function != service_function)
61 /* Create out param */
62 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
64 switch (service_function) {
65 case BT_RFCOMM_CLIENT_CONNECT: {
66 GUnixFDList *fd_list = NULL;
68 char address[BT_ADDRESS_STRING_SIZE];
69 bluetooth_rfcomm_connection_t *ptr = user_data;
71 /* Check if connect address matched with requested address */
72 _bt_convert_addr_type_to_string(address, ptr->device_addr.addr);
73 if (strncasecmp(address, (char *)req_info->user_data,
74 BT_ADDRESS_STRING_SIZE)) {
75 BT_INFO("RFCOMM connected addr: [%s], requested addr: [%s]",
76 address, (char *)req_info->user_data);
80 g_array_append_vals(out_param, user_data, size);
82 if (BLUETOOTH_ERROR_NONE == result) {
83 fd_list = g_unix_fd_list_new();
84 g_unix_fd_list_append(fd_list, ptr->socket_fd, &error);
85 g_assert_no_error(error);
86 close(ptr->socket_fd);
89 _bt_service_method_return_with_unix_fd_list(
90 req_info->context, out_param, result, fd_list);
92 g_object_unref(fd_list);
94 g_free(req_info->user_data);
95 _bt_free_info_from_invocation_list(req_info);
96 g_array_free(out_param, TRUE);
99 case BT_RFCOMM_LISTEN_AND_ACCEPT:
100 case BT_RFCOMM_LISTEN: {
101 GUnixFDList *fd_list = NULL;
102 GError *error = NULL;
103 int *socket_fd = user_data;
105 BT_INFO("Server socket fd: %d", *socket_fd);
107 g_array_append_vals(out_param, user_data, size);
109 /* Add socket fd to unix_fd_list */
110 fd_list = g_unix_fd_list_new();
111 g_unix_fd_list_append(fd_list, *socket_fd, &error);
112 g_assert_no_error(error);
114 _bt_service_method_return_with_unix_fd_list(
115 req_info->context, out_param, result, fd_list);
118 g_object_unref(fd_list);
120 _bt_free_info_from_invocation_list(req_info);
121 g_array_free(out_param, TRUE);
125 BT_ERR("Unknown Service function");
132 static void __bt_rfcomm_socket_conn_cb(int result, int sock_fd, char *address, char *uuid, int chan)
134 bluetooth_rfcomm_connection_t conn_info;
136 ret_if(NULL == address);
137 ret_if(NULL == uuid);
141 BT_INFO("result: %d, socket_fd: %d, address: %s, uuid: %s, chan: %d",
142 result, sock_fd, address, uuid, chan);
144 /* Fill RFCOMM connection structure and send reply to pending request */
145 memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t));
146 conn_info.socket_fd = sock_fd;
147 conn_info.device_role = RFCOMM_ROLE_CLIENT;
148 g_strlcpy(conn_info.uuid, uuid, BLUETOOTH_UUID_STRING_MAX);
149 _bt_convert_addr_string_to_type(conn_info.device_addr.addr, address);
151 __bt_rfcomm_reply_pending_request(
152 result, BT_RFCOMM_CLIENT_CONNECT,
153 (void *)&conn_info, sizeof(bluetooth_rfcomm_connection_t));
158 int _bt_rfcomm_connect_using_uuid(bluetooth_device_address_t *device_address, char *remote_uuid)
161 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
165 retv_if(NULL == device_address, BLUETOOTH_ERROR_INVALID_PARAM);
166 retv_if(NULL == remote_uuid, BLUETOOTH_ERROR_INVALID_PARAM);
168 _bt_convert_addr_type_to_string(address, device_address->addr);
169 BT_INFO("RFCOMM connect called for [%s], uuid: [%s]", address, remote_uuid);
171 result = _bt_socket_client_connect(SOCK_TYPE_RFCOMM,
172 address, remote_uuid, -1, __bt_rfcomm_socket_conn_cb);
173 if (BLUETOOTH_ERROR_NONE != result) {
174 BT_ERR("_bt_socket_client_connect failed");
179 return BLUETOOTH_ERROR_NONE;
182 /* Range of the Channel : 0 <= channel <= 30 */
183 int _bt_rfcomm_connect_using_channel(bluetooth_device_address_t *device_address, char *chan_str)
186 int result = BLUETOOTH_ERROR_NONE;
187 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
191 retv_if(NULL == device_address, BLUETOOTH_ERROR_INVALID_PARAM);
192 retv_if(NULL == chan_str, BLUETOOTH_ERROR_INVALID_PARAM);
194 _bt_convert_addr_type_to_string(address, device_address->addr);
195 channel = atoi(chan_str);
196 BT_INFO("RFCOMM connect called for [%s], channel: %d", address, channel);
198 result = _bt_socket_client_connect(SOCK_TYPE_RFCOMM,
199 address, NULL, channel, __bt_rfcomm_socket_conn_cb);
200 if (BLUETOOTH_ERROR_NONE != result) {
201 BT_ERR("_bt_socket_client_connect failed");
209 gboolean __bt_send_rfcomm_server_fd(gpointer user_data)
213 __bt_rfcomm_reply_pending_request(BLUETOOTH_ERROR_NONE,
214 BT_RFCOMM_LISTEN, user_data, sizeof(int));
221 gboolean __bt_send_rfcomm_server_fd_with_accept(gpointer user_data)
225 __bt_rfcomm_reply_pending_request(BLUETOOTH_ERROR_NONE,
226 BT_RFCOMM_LISTEN_AND_ACCEPT, user_data, sizeof(int));
233 int _bt_rfcomm_socket_listen(char *svc_name, char *uuid, bool accept)
240 retv_if(NULL == svc_name, BLUETOOTH_ERROR_INVALID_PARAM);
241 retv_if(NULL == uuid, BLUETOOTH_ERROR_INVALID_PARAM);
243 BT_INFO("RFCOMM create socket called with svc name: [%s], uuid: [%s]", svc_name, uuid);
244 sock_fd = _bt_socket_listen(SOCK_TYPE_RFCOMM, svc_name, uuid, channel);
246 BT_ERR("_bt_socket_listen failed");
247 return BLUETOOTH_ERROR_INTERNAL;
251 g_idle_add(__bt_send_rfcomm_server_fd, g_memdup(&sock_fd, sizeof(int)));
253 g_idle_add(__bt_send_rfcomm_server_fd_with_accept, g_memdup(&sock_fd, sizeof(int)));
259 static bt_rfcomm_conn_info_t* __bt_find_conn_from_list(const char *sender, int role, int socket_fd)
262 bt_rfcomm_conn_info_t *conn_info;
264 retv_if(NULL == sender, NULL);
266 for (l = rfcomm_conn_list; l != NULL; l = g_slist_next(l)) {
268 if (g_strcmp0(conn_info->sender, sender) == 0) {
269 if (socket_fd == conn_info->socket_fd &&
270 role == conn_info->role)
278 int _bt_rfcomm_conn_added(char *svc_name, int role, int socket_fd)
280 bt_rfcomm_conn_info_t *conn_info = NULL;
282 retv_if(NULL == svc_name, BLUETOOTH_ERROR_INVALID_PARAM);
284 if (__bt_find_conn_from_list(svc_name, role, socket_fd) != NULL) {
285 BT_ERR("Socket fd already exist");
286 return BLUETOOTH_ERROR_INVALID_PARAM;
289 BT_INFO("RFCOMM is connected: [%s], [%d], [%d]", svc_name, role, socket_fd);
291 conn_info = g_malloc0(sizeof(bt_rfcomm_conn_info_t));
293 if (conn_info == NULL)
294 return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
296 _bt_start_connect_time();
298 conn_info->sender = g_strdup(svc_name);
299 conn_info->role = role;
300 conn_info->socket_fd = socket_fd;
302 rfcomm_conn_list = g_slist_append(rfcomm_conn_list, conn_info);
304 return BLUETOOTH_ERROR_NONE;
307 int _bt_rfcomm_conn_removed(char *svc_name, int role, int socket_fd)
309 bt_rfcomm_conn_info_t *conn_info = NULL;
311 retv_if(NULL == svc_name, BLUETOOTH_ERROR_INVALID_PARAM);
313 BT_INFO("RFCOMM is connected: [%s], [%d], [%d]", svc_name, role, socket_fd);
315 /* Find the first connection */
316 conn_info = __bt_find_conn_from_list(svc_name, role, socket_fd);
318 if (conn_info == NULL) {
319 BT_ERR("No socket fd is in list");
320 return BLUETOOTH_ERROR_INVALID_PARAM;
323 _bt_stop_connect_time();
325 rfcomm_conn_list = g_slist_remove(rfcomm_conn_list, conn_info);
326 g_free(conn_info->sender);
329 return BLUETOOTH_ERROR_NONE;
332 void _bt_rfcomm_check_termination(const char *name)
335 bt_rfcomm_conn_info_t *conn_info = NULL;
337 ret_if(NULL == name);
339 for (l = rfcomm_conn_list; l != NULL; ) {
342 if (g_strcmp0(conn_info->sender, name) == 0) {
343 _bt_rfcomm_conn_removed((char *)name,
345 conn_info->socket_fd);
349 /* Cleanup osp server */
350 _bt_unregister_osp_server_in_agent_by_sender(name);
353 static void __bt_free_rfcomm_conn(bt_rfcomm_conn_info_t *conn_info)
355 g_free(conn_info->sender);
359 void _bt_rfcomm_all_conn_removed(void)
361 g_slist_free_full(rfcomm_conn_list, (GDestroyNotify)__bt_free_rfcomm_conn);
362 rfcomm_conn_list = NULL;