DPM: Add Error code for device policy restriction.
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-rfcomm-client.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *              http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 #include <string.h>
19 #ifdef RFCOMM_DIRECT
20 #include <errno.h>
21 #include <gio/gunixfdlist.h>
22 #endif
23
24 #include "bluetooth-api.h"
25 #include "bt-internal-types.h"
26
27 #include "bt-common.h"
28 #include "bt-request-sender.h"
29 #include "bt-event-handler.h"
30
31 #ifdef TIZEN_DPM_ENABLE
32 #include "bt-dpm.h"
33 #endif
34
35 #ifdef RFCOMM_DIRECT
36
37 #define BT_TIMEOUT_MESSAGE "Did not receive a reply. Possible causes include: " \
38                         "the remote application did not send a reply, " \
39                         "the message bus security policy blocked the reply, " \
40                         "the reply timeout expired, or the network connection " \
41                         "was broken."
42
43 static GSList *rfcomm_clients;
44
45 /* Variable for privilege, only for write API,
46   before we should reduce time to bt-service dbus calling
47   -1 : Don't have a permission to access API
48   0 : Initial value, not yet check
49   1 : Have a permission to access API
50 */
51 static int privilege_token;
52
53 typedef struct {
54         char bt_addr[BT_ADDRESS_STRING_SIZE];
55         int fd;
56         int watch_id;
57         gboolean disconnected;
58 } rfcomm_conn_info_t;
59
60 typedef struct {
61         char uuid[BLUETOOTH_UUID_STRING_MAX];
62         char *device_path;
63         char *obj_path;
64         int object_id;
65         int id;
66         GSList *rfcomm_conns;
67         unsigned int idle_id;
68 } rfcomm_cb_data_t;
69
70 static void __client_connected_cb(rfcomm_cb_data_t *cb_data,
71         char *dev_address, int result);
72
73 static void __bt_free_cb_data(rfcomm_cb_data_t *cb_data)
74 {
75         BT_DBG("+");
76
77         if (cb_data->id >= 0)
78                 __rfcomm_delete_id(cb_data->id);
79
80         if (cb_data->object_id > 0)
81                 _bt_unregister_gdbus(cb_data->object_id);
82
83         if (cb_data->obj_path) {
84                 BT_INFO("Unregister profile");
85                 _bt_unregister_profile(cb_data->obj_path);
86         }
87
88         if (cb_data->idle_id != 0) {
89                 BT_INFO("Removing idle source");
90                 g_source_remove(cb_data->idle_id);
91         }
92
93         g_free(cb_data->obj_path);
94
95         g_free(cb_data->device_path);
96         g_free(cb_data);
97         BT_DBG("-");
98 }
99
100 static void rfcomm_cb_data_remove(rfcomm_cb_data_t *info)
101 {
102         if (info) {
103                 BT_INFO("No more device connected remove info");
104                 rfcomm_clients = g_slist_remove(rfcomm_clients, info);
105                 __bt_free_cb_data(info);
106         }
107 }
108
109 gint compare(gpointer *a, gpointer *b)
110 {
111         rfcomm_conn_info_t *node = (rfcomm_conn_info_t *)a;
112         char *address = (char *)b;
113         return g_strcmp0(node->bt_addr, address);
114 }
115
116 gint compare_fd(gpointer *a, gpointer *b)
117 {
118         rfcomm_conn_info_t *node = (rfcomm_conn_info_t *)a;
119         int *fd = (int *)b;
120         if (node->fd == *fd)
121                 return 0;
122
123         return 1;
124 }
125 static void __bt_free_conn(rfcomm_conn_info_t *conn)
126 {
127         BT_DBG("+");
128
129         if (conn == NULL)
130                 return;
131
132         if (conn->fd > 0)
133                 close(conn->fd);
134         if (conn->watch_id > 0) {
135                 g_source_remove(conn->watch_id);
136                 conn->watch_id = 0;
137         }
138         g_free(conn);
139
140         BT_DBG("-");
141 }
142
143 static void __rfcomm_remove_conn_info_t(rfcomm_cb_data_t *info, char *address)
144 {
145         GSList *l = NULL;
146         rfcomm_conn_info_t *conn_info = NULL;
147         l = g_slist_find_custom(info->rfcomm_conns, address, (GCompareFunc)compare);
148         if (l)
149                 conn_info = l->data;
150         if (conn_info) {
151                 info->rfcomm_conns = g_slist_remove(info->rfcomm_conns, conn_info);
152                 __bt_free_conn(conn_info);
153         }
154 }
155
156 static rfcomm_conn_info_t *__get_conn_info_from_fd(rfcomm_cb_data_t *info,
157         int fd)
158 {
159         GSList *l;
160         rfcomm_conn_info_t *device_node = NULL;
161         for(l = info->rfcomm_conns; l != NULL; l = l->next) {
162                 device_node = l->data;
163                 if ( device_node && device_node->fd == fd)
164                         return device_node;
165         }
166         return NULL;
167 }
168
169 static rfcomm_conn_info_t *__get_conn_info_from_address(rfcomm_cb_data_t *info,
170                 char *dev_address)
171 {
172         GSList *l = NULL;
173         rfcomm_conn_info_t *conn_info = NULL;
174         l = g_slist_find_custom(info->rfcomm_conns, dev_address,
175                 (GCompareFunc)compare);
176         if (l)
177                 conn_info = l->data;
178         return conn_info;
179 }
180
181 static void __rfcomm_client_connected_cb(rfcomm_cb_data_t *info,
182         char *dev_address, int result)
183 {
184         __client_connected_cb(info, dev_address, result);
185         __rfcomm_remove_conn_info_t(info, dev_address);
186
187         if (info->rfcomm_conns == NULL)
188                 rfcomm_cb_data_remove(info);
189 }
190
191 static rfcomm_cb_data_t *__find_rfcomm_info_with_fd(int fd)
192 {
193         GSList *l;
194         GSList *device_fd;
195         for (l = rfcomm_clients; l != NULL; l = l->next) {
196                 rfcomm_cb_data_t *info = l->data;
197                 device_fd = g_slist_find_custom(info->rfcomm_conns, &fd,
198                         (GCompareFunc)compare_fd);
199                 if (device_fd)
200                         return info;
201         }
202
203         return NULL;
204 }
205
206 static rfcomm_cb_data_t *__find_rfcomm_info_from_path(const char *path)
207 {
208         GSList *l;
209
210         for (l = rfcomm_clients; l != NULL; l = l->next) {
211                 rfcomm_cb_data_t *info = l->data;
212
213                 if (info != NULL)
214                         if (g_strcmp0(info->obj_path, path) == 0)
215                                 return info;
216         }
217
218         return NULL;
219 }
220
221 static rfcomm_cb_data_t *__find_rfcomm_info_from_uuid(const char *uuid)
222 {
223         GSList *l;
224
225         for (l = rfcomm_clients; l != NULL; l = l->next) {
226                 rfcomm_cb_data_t *info = l->data;
227
228                 if (g_strcmp0(info->uuid, uuid) == 0)
229                         return info;
230         }
231
232         return NULL;
233 }
234
235 static void _bt_rfcomm_disconnect_conn_info(rfcomm_conn_info_t *conn_info,
236         rfcomm_cb_data_t *info)
237 {
238         if (conn_info == NULL)
239                 return;
240
241         bluetooth_rfcomm_disconnection_t disconn_info;
242         bt_event_info_t *event_info = NULL;
243         if (conn_info->disconnected == FALSE)
244                 return;
245         event_info = _bt_event_get_cb_data(BT_RFCOMM_CLIENT_EVENT);
246         if (event_info == NULL) {
247                 if (info->rfcomm_conns == NULL)
248                         rfcomm_cb_data_remove(info);
249                 return;
250         }
251         memset(&disconn_info, 0x00, sizeof(bluetooth_rfcomm_disconnection_t));
252         disconn_info.device_role = RFCOMM_ROLE_CLIENT;
253         g_strlcpy(disconn_info.uuid, info->uuid, BLUETOOTH_UUID_STRING_MAX);
254         BT_DBG("Disconnected FD [%d]", conn_info->fd);
255         _bt_convert_addr_string_to_type(disconn_info.device_addr.addr,
256                                         conn_info->bt_addr);
257
258         disconn_info.socket_fd = conn_info->fd;
259
260         BT_DBG("Disconnection Result[%d] BT_ADDRESS[%s] UUID[%s] FD[%d]",
261                         BLUETOOTH_ERROR_NONE, conn_info->bt_addr,
262                         info->uuid, conn_info->fd);
263         _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DISCONNECTED,
264                         BLUETOOTH_ERROR_NONE, &disconn_info,
265                         event_info->cb, event_info->user_data);
266
267         if(conn_info) {
268                 BT_DBG("List is present deleting it");
269                 __rfcomm_remove_conn_info_t(info, conn_info->bt_addr);
270         }
271         if (info->rfcomm_conns == NULL)
272                 rfcomm_cb_data_remove(info);
273
274         BT_DBG("-");
275 }
276
277 static gboolean __rfcomm_client_disconnect(gpointer user_data)
278 {
279         rfcomm_cb_data_t *info = (rfcomm_cb_data_t *) user_data;
280         BT_INFO_C("Disconnected [RFCOMM Client]");
281         retv_if(info == NULL, FALSE);
282
283         if (g_slist_find(rfcomm_clients, info) == NULL) {
284                 BT_INFO("rfcomm resource is already freed");
285                 return FALSE;
286         }
287         info->idle_id = 0;
288         g_slist_foreach(info->rfcomm_conns,
289                 (GFunc) _bt_rfcomm_disconnect_conn_info, info);
290         BT_DBG("-");
291         return FALSE;
292 }
293
294 static gboolean __is_error_by_disconnect(GError *err)
295 {
296         return !g_strcmp0(err->message, "Connection reset by peer") ||
297                         !g_strcmp0(err->message, "Connection timed out") ||
298                         !g_strcmp0(err->message, "Software caused connection abort");
299 }
300
301 static gboolean __client_data_received_cb(GIOChannel *chan, GIOCondition cond,
302                                                                 gpointer data)
303 {
304         char *buffer = NULL;
305         gsize len = 0;
306         int result = BLUETOOTH_ERROR_NONE;
307         rfcomm_cb_data_t *info = data;
308         rfcomm_conn_info_t *conn_info = NULL;
309         bt_event_info_t *event_info;
310         bluetooth_rfcomm_received_data_t data_r;
311         GIOStatus status = G_IO_STATUS_NORMAL;
312         GError *err = NULL;
313         int fd;
314         BT_DBG("");
315
316         retv_if(info == NULL, FALSE);
317         fd = g_io_channel_unix_get_fd(chan);
318         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
319                 BT_ERR_C("RFComm Client  disconnected: %d", fd);
320                 conn_info = __get_conn_info_from_fd(info, fd);
321                 if (conn_info == NULL) {
322                         BT_ERR("No Connection info found with FD [%d]", fd);
323                         return FALSE;
324                 }
325                 conn_info->disconnected = TRUE;
326                 __rfcomm_client_disconnect(info);
327                 return FALSE;
328         }
329
330         buffer = g_malloc0(BT_RFCOMM_BUFFER_LEN + 1);
331
332         status = g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_LEN,
333                         &len, &err);
334         if (status != G_IO_STATUS_NORMAL) {
335                 BT_ERR("IO Channel read is failed with %d", status);
336
337                 g_free(buffer);
338                 if (err) {
339                         BT_ERR("IO Channel read error [%s]", err->message);
340                         if (status == G_IO_STATUS_ERROR &&
341                                         __is_error_by_disconnect(err)) {
342                                 BT_ERR("cond : %d", cond);
343                                 g_error_free(err);
344                                 conn_info = __get_conn_info_from_fd(info, fd);
345                                 if (conn_info == NULL) {
346                                         BT_ERR("No Connection info found with FD [%d]", fd);
347                                         return FALSE;
348                                 }
349                                 conn_info->disconnected = TRUE;
350                                 __rfcomm_client_disconnect(info);
351                                 return FALSE;
352                         }
353                         g_error_free(err);
354                 }
355                 return TRUE;
356         }
357
358         event_info = _bt_event_get_cb_data(BT_RFCOMM_CLIENT_EVENT);
359         if (event_info == NULL) {
360                 g_free(buffer);
361                 return TRUE;
362         }
363
364         data_r.socket_fd = fd;
365         data_r.buffer_size = len;
366         data_r.buffer = buffer;
367
368         _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED,
369                         result, &data_r,
370                         event_info->cb, event_info->user_data);
371
372         g_free(buffer);
373         return TRUE;
374 }
375
376 static void __client_connected_cb(rfcomm_cb_data_t *cb_data, char *dev_address,
377         int result)
378 {
379         bluetooth_rfcomm_connection_t conn_info;
380         bt_event_info_t *event_info;
381         rfcomm_conn_info_t *conn_list_info = NULL;
382         BT_INFO_C("Connected [RFCOMM Client]");
383
384         event_info = _bt_event_get_cb_data(BT_RFCOMM_CLIENT_EVENT);
385         if (event_info == NULL)
386                 return;
387
388         memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t));
389         conn_info.device_role = RFCOMM_ROLE_CLIENT;
390         g_strlcpy(conn_info.uuid, cb_data->uuid, BLUETOOTH_UUID_STRING_MAX);
391         _bt_convert_addr_string_to_type(conn_info.device_addr.addr,
392                         dev_address);
393         conn_list_info = __get_conn_info_from_address(cb_data, dev_address);
394         if (conn_list_info == NULL) {
395                 BT_ERR("Device addres %s not found in connection list", dev_address);
396                 return;
397         }
398         conn_info.socket_fd = conn_list_info->fd;
399         conn_info.server_id = -1;
400
401         BT_DBG("Connection Result[%d] BT_ADDRESS[%s] UUID[%s] FD[%d]",
402                         result, conn_list_info->bt_addr, cb_data->uuid, conn_list_info->fd);
403         _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_CONNECTED,
404                         result, &conn_info,
405                         event_info->cb, event_info->user_data);
406         BT_DBG("-");
407 }
408
409 #endif
410
411 int new_connection(const char *path, int fd, bluetooth_device_address_t *addr)
412 {
413         rfcomm_cb_data_t *info;
414         GIOChannel *data_io;
415         rfcomm_conn_info_t *conn_info = NULL;
416         BT_DBG("%s %d", path, fd);
417         char address[BT_ADDRESS_STRING_SIZE];
418         _bt_convert_addr_type_to_string(address,
419                                 (unsigned char *)addr);
420         info = __find_rfcomm_info_from_path(path);
421         if (info == NULL)
422                 return -1;
423         conn_info = __get_conn_info_from_address(info, address);
424
425         if (conn_info == NULL) {
426                 BT_ERR("Device Address %s not found in connection list", address);
427                 return -1;
428         }
429         conn_info->fd = fd;
430         BT_DBG("connection info fd %d", conn_info->fd);
431         data_io = g_io_channel_unix_new(fd);
432         g_io_channel_set_encoding(data_io, NULL, NULL);
433         g_io_channel_set_flags(data_io, G_IO_FLAG_NONBLOCK, NULL);
434         conn_info->watch_id = g_io_add_watch(data_io,
435                                 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
436                                 __client_data_received_cb, info);
437
438         g_io_channel_unref(data_io);
439
440         __client_connected_cb(info, address,BLUETOOTH_ERROR_NONE);
441
442         return 0;
443 }
444
445 static void __bt_connect_response_cb(GDBusProxy *proxy, GAsyncResult *res,
446                                                         gpointer user_data)
447
448 {
449         GError *error = NULL;
450         rfcomm_cb_data_t *cb_data;
451         char dev_address[BT_ADDRESS_STRING_SIZE];
452         const char *path;
453         BT_DBG("+");
454
455         ret_if(user_data == NULL);
456
457         cb_data = user_data;
458
459         if (!g_dbus_proxy_call_finish(proxy, res, &error)) {
460                 int result;
461                 g_dbus_error_strip_remote_error(error);
462                 BT_ERR("Error : %s \n", error->message);
463
464                 if (g_strcmp0(error->message, "In Progress") == 0)
465                         result = BLUETOOTH_ERROR_DEVICE_BUSY;
466                 else
467                         result = BLUETOOTH_ERROR_INTERNAL;
468                 path = g_dbus_proxy_get_object_path(proxy);
469                 _bt_convert_device_path_to_address(path, dev_address);
470                 __rfcomm_client_connected_cb(cb_data, dev_address, result);
471
472                 g_error_free(error);
473         }
474         if (proxy)
475                 g_object_unref(proxy);
476
477         BT_DBG("-");
478 }
479
480 static void __bt_discover_service_response_cb(GDBusProxy *proxy,
481                                 GAsyncResult *res, gpointer user_data)
482 {
483         rfcomm_cb_data_t *cb_data;
484         int ret = 0;
485         GError *err = NULL;
486         bt_register_profile_info_t info = {0};
487         int result = BLUETOOTH_ERROR_NONE;
488         char dev_address[BT_ADDRESS_STRING_SIZE];
489         const char *path;
490
491         BT_DBG("+");
492
493         ret_if(user_data == NULL);
494
495         cb_data = user_data;
496
497         path = g_dbus_proxy_get_object_path(proxy);
498
499         _bt_convert_device_path_to_address(path, dev_address);
500         BT_DBG("Device Adress [%s]", dev_address);
501         g_dbus_proxy_call_finish(proxy, res, &err);
502         if (proxy)
503                 g_object_unref(proxy);
504
505         if (err != NULL) {
506                 g_dbus_error_strip_remote_error(err);
507                 BT_ERR("Error occured in Proxy call [%s]\n", err->message);
508                 if (!strcmp("Operation canceled", err->message)) {
509                         result = BLUETOOTH_ERROR_CANCEL_BY_USER;
510                 } else if (!strcmp("In Progress", err->message)) {
511                         result = BLUETOOTH_ERROR_IN_PROGRESS;
512                 } else if (!strcmp("Host is down", err->message)) {
513                         result = BLUETOOTH_ERROR_HOST_DOWN;
514                 } else if (!strcmp(BT_TIMEOUT_MESSAGE, err->message)) {
515                         result = BLUETOOTH_ERROR_SERVICE_SEARCH_ERROR;
516                         ret = _bt_cancel_discovers(dev_address);
517                         if (ret != BLUETOOTH_ERROR_NONE)
518                                 BT_ERR("Error: While CancelDiscovery");
519                 } else {
520                         result = BLUETOOTH_ERROR_CONNECTION_ERROR;
521                 }
522                 __rfcomm_client_connected_cb(cb_data, dev_address, result);
523                 goto done;
524         } else {
525                 BT_INFO("Services are Updated checking required uuid is there");
526                 /* Check here for uuid present */
527                 ret = _bt_discover_service_uuids(dev_address, (char *)cb_data->uuid);
528                 if (ret == BLUETOOTH_ERROR_NONE) {
529                         info.uuid = (char *)cb_data->uuid;
530                         info.obj_path = cb_data->obj_path;
531                         info.role = "client";
532
533                         ret = _bt_register_profile(&info, FALSE);
534                         if (ret < 0)
535                                 BT_DBG("Error: register profile");
536                         ret = _bt_connect_profile(dev_address, cb_data->uuid,
537                                                 __bt_connect_response_cb, cb_data);
538
539                         if (ret != BLUETOOTH_ERROR_NONE) {
540                                 BT_ERR("ConnectProfile failed");
541                                 result = BLUETOOTH_ERROR_CONNECTION_ERROR;
542                                 __rfcomm_client_connected_cb(cb_data, dev_address, result);
543                                 goto done;
544                         }
545                 } else {
546                         BT_ERR("remote uuid not found");
547                         result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
548                         __rfcomm_client_connected_cb(cb_data, dev_address, result);
549                 }
550         }
551 done:
552         if (err)
553                 g_clear_error(&err);
554 }
555
556 BT_EXPORT_API int bluetooth_rfcomm_connect(
557                 const bluetooth_device_address_t *remote_bt_address,
558                 const char *remote_uuid)
559 {
560
561 #ifdef RFCOMM_DIRECT
562         rfcomm_cb_data_t *cb_data = NULL;
563         rfcomm_conn_info_t *conn = NULL;
564 #else
565         int result;
566         int connect_type;
567         bt_user_info_t *user_info;
568         char uuid[BLUETOOTH_UUID_STRING_MAX];
569 #endif
570         BT_CHECK_PARAMETER(remote_bt_address, return);
571         BT_CHECK_PARAMETER(remote_uuid, return);
572         BT_CHECK_ENABLED(return);
573
574 #ifdef TIZEN_DPM_ENABLE
575         if (_bt_check_dpm(BT_DPM_ADDRESS, (void *)remote_bt_address) == BT_DPM_RESTRICTED) {
576                 BT_ERR("Blacklist device");
577                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
578         }
579
580         if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED ||
581                 _bt_check_dpm(BT_DPM_HF_ONLY, NULL) == BT_DPM_RESTRICTED) {
582                 BT_ERR("Not allow to connect the RFCOMM service");
583                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
584         }
585
586         if (_bt_check_dpm(BT_DPM_DESKTOP, NULL) == BT_DPM_RESTRICTED) {
587                 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
588                 bluetooth_device_class_t dev_class;
589
590                 _bt_convert_addr_type_to_string(address, (unsigned char *)remote_bt_address->addr);
591                 _bt_get_cod_by_address(address, &dev_class);
592
593                 if (dev_class.major_class == BLUETOOTH_DEVICE_MAJOR_CLASS_COMPUTER) {
594                         BT_ERR("Reject a authorization due to MDM Policy");
595                         return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
596                 }
597         }
598 #endif
599
600 #ifdef RFCOMM_DIRECT
601         BT_INFO_C("<<<<<<<<< RFCOMM Connect request from app >>>>>>>>>>>");
602         int ret;
603         int id, object_id;
604         char *path;
605
606         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_CLIENT_CONNECT)
607              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
608                 BT_ERR("Don't have a privilege to use this API");
609                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
610         }
611
612         id = __rfcomm_assign_id();
613         if (id < 0)
614                 return BLUETOOTH_ERROR_INTERNAL;
615
616         cb_data = __find_rfcomm_info_from_uuid(remote_uuid);
617         if (!cb_data) {
618                 path = g_strdup_printf("/org/socket/client/%d/%d", getpid(), id);
619
620                 object_id = _bt_register_new_conn(path, new_connection);
621                 if (object_id < 0) {
622                         __rfcomm_delete_id(id);
623                         return BLUETOOTH_ERROR_INTERNAL;
624                 }
625
626                 cb_data = g_new0(rfcomm_cb_data_t, 1);
627                 g_strlcpy(cb_data->uuid, remote_uuid, BLUETOOTH_UUID_STRING_MAX);
628                 cb_data->obj_path = path;
629                 cb_data->object_id = object_id;
630                 cb_data->id = id;
631         }
632         conn = g_new0(rfcomm_conn_info_t, 1);
633         conn->fd = -1;
634         _bt_convert_addr_type_to_string(conn->bt_addr,
635                                 (unsigned char *)remote_bt_address->addr);
636
637         BT_DBG("Connecting to %s uuid %s", conn->bt_addr, remote_uuid);
638         cb_data->rfcomm_conns = g_slist_append(cb_data->rfcomm_conns, conn);
639         ret = _bt_discover_services(conn->bt_addr, (char *)remote_uuid,
640                                 __bt_discover_service_response_cb, cb_data);
641         if (ret != BLUETOOTH_ERROR_NONE) {
642                 BT_ERR("Error returned while service discovery");
643                 __rfcomm_remove_conn_info_t(cb_data, conn->bt_addr);
644                 if (cb_data->rfcomm_conns == NULL)
645                         rfcomm_cb_data_remove(cb_data);
646                 return BLUETOOTH_ERROR_INTERNAL;
647         }
648         if (g_slist_find(rfcomm_clients, cb_data) == NULL) {
649                 BT_INFO("Adding callback information to rfcomm_clients");
650                 rfcomm_clients = g_slist_append(rfcomm_clients, cb_data);
651         } else
652                 BT_INFO("Callback information is already added");
653
654         return BLUETOOTH_ERROR_NONE;
655 #else
656         user_info = _bt_get_user_data(BT_COMMON);
657         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
658
659         /* connect_type:  BT_RFCOMM_UUID / BT_RFCOMM_CHANNEL*/
660         /* In now, we only support to connecty using UUID */
661         connect_type = BT_RFCOMM_UUID;
662
663         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_CLIENT_CONNECT)
664              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
665                 BT_ERR("Don't have a privilege to use this API");
666                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
667         }
668
669         BT_INIT_PARAMS();
670         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
671
672         g_array_append_vals(in_param1, remote_bt_address,
673                                 sizeof(bluetooth_device_address_t));
674
675         g_strlcpy(uuid, remote_uuid, sizeof(uuid));
676         g_array_append_vals(in_param2, uuid, BLUETOOTH_UUID_STRING_MAX);
677
678         g_array_append_vals(in_param3, &connect_type, sizeof(int));
679
680         result = _bt_send_request_async(BT_BLUEZ_SERVICE,
681                                 BT_RFCOMM_CLIENT_CONNECT,
682                                 in_param1, in_param2,
683                                 in_param3, in_param4,
684                                 user_info->cb, user_info->user_data);
685
686         BT_DBG("result: %x", result);
687
688         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
689
690         return result;
691 #endif
692 }
693
694 BT_EXPORT_API int bluetooth_rfcomm_client_is_connected(const bluetooth_device_address_t *device_address, gboolean *connected)
695 {
696         GSList *l;
697         GSList *conn_list = NULL;
698         rfcomm_cb_data_t *client_info;
699         rfcomm_conn_info_t *conn_info;
700         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
701
702         BT_CHECK_PARAMETER(device_address, return);
703         BT_CHECK_PARAMETER(connected, return);
704
705         _bt_convert_addr_type_to_string(address, (unsigned char *)device_address->addr);
706         *connected = FALSE;
707
708         for (l = rfcomm_clients; l != NULL; l = l->next) {
709                 client_info = l->data;
710                 if (client_info == NULL)
711                         continue;
712                 for(conn_list = client_info->rfcomm_conns;
713                         conn_list != NULL; conn_list = conn_list->next) {
714                         conn_info = conn_list->data;
715                         if(conn_info == NULL)
716                                 continue;
717
718                         if (g_strcmp0(address, conn_info->bt_addr) == 0) {
719                                 *connected = TRUE;
720                                 return BLUETOOTH_ERROR_NONE;
721                         }
722                 }
723         }
724
725         return BLUETOOTH_ERROR_NONE;
726 }
727
728 BT_EXPORT_API gboolean bluetooth_rfcomm_is_client_connected(void)
729 {
730         int result;
731         int connected = FALSE;
732
733         BT_CHECK_ENABLED(return);
734
735         BT_INIT_PARAMS();
736         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
737
738         result = _bt_send_request(BT_BLUEZ_SERVICE,
739                         BT_RFCOMM_CLIENT_IS_CONNECTED,
740                         in_param1, in_param2, in_param3,
741                         in_param4, &out_param);
742
743         BT_DBG("result: %x", result);
744
745         if (result == BLUETOOTH_ERROR_NONE) {
746                 connected = g_array_index(out_param,
747                                 int, 0);
748         } else {
749                 BT_ERR("Fail to send request");
750         }
751
752         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
753
754         return connected;
755 }
756
757 BT_EXPORT_API int bluetooth_rfcomm_disconnect(int socket_fd)
758 {
759 #ifdef RFCOMM_DIRECT
760         rfcomm_cb_data_t *info;
761         rfcomm_conn_info_t *conn_info;
762         BT_INFO_C("<<<<<<<<< RFCOMM Disconnect request from app >>>>>>>>");
763         BT_CHECK_ENABLED(return);
764
765         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_SOCKET_DISCONNECT)
766              == BLUETOOTH_ERROR_PERMISSION_DEINED) {
767                 BT_ERR("Don't have a privilege to use this API");
768                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
769         }
770
771         if (socket_fd < 0) {
772                 BT_ERR("Invalid FD");
773                 return BLUETOOTH_ERROR_INVALID_PARAM;
774         }
775         BT_DBG("FDD %d", socket_fd);
776
777         info = __find_rfcomm_info_with_fd(socket_fd);
778         if (info == NULL) {
779                 BT_DBG("Could not find in client, so check in server");
780                 return bluetooth_rfcomm_server_disconnect(socket_fd);
781         }
782         conn_info = __get_conn_info_from_fd(info, socket_fd);
783         if (conn_info == NULL) {
784                 BT_ERR("FATAL Error");
785                 return BLUETOOTH_ERROR_INTERNAL;
786         }
787         if (conn_info->watch_id <= 0) {
788                 BT_ERR("Invalid state");
789                 return BLUETOOTH_ERROR_NOT_CONNECTED;
790         }
791         conn_info->disconnected = TRUE;
792         close(socket_fd);
793         BT_INFO("conn_info %s", conn_info->bt_addr);
794         _bt_disconnect_profile(conn_info->bt_addr, info->uuid, NULL,NULL);
795         if (info->idle_id == 0)
796                 info->idle_id = g_idle_add(__rfcomm_client_disconnect, info);
797
798         return BLUETOOTH_ERROR_NONE;
799 #else
800         int result;
801         int service_function;
802
803         BT_CHECK_ENABLED(return);
804
805         BT_INIT_PARAMS();
806         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
807
808         /* Support the OSP */
809         if (socket_fd == -1) {
810                 /* Cancel connect */
811                 service_function = BT_RFCOMM_CLIENT_CANCEL_CONNECT;
812         } else {
813                 g_array_append_vals(in_param1, &socket_fd, sizeof(int));
814                 service_function = BT_RFCOMM_SOCKET_DISCONNECT;
815         }
816
817         result = _bt_send_request(BT_BLUEZ_SERVICE, service_function,
818                 in_param1, in_param2, in_param3, in_param4, &out_param);
819
820         BT_DBG("result: %x", result);
821
822         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
823
824         return result;
825 #endif
826 }
827
828 BT_EXPORT_API int bluetooth_rfcomm_write(int fd, const char *buf, int length)
829 {
830 #ifdef RFCOMM_DIRECT
831         int written;
832 #else
833         char *buffer;
834 #endif
835         int result;
836
837         BT_CHECK_PARAMETER(buf, return);
838         if (fd < 0) {
839                 BT_ERR("Invalid FD");
840                 return BLUETOOTH_ERROR_INVALID_PARAM;
841         }
842
843         BT_DBG("FD : %d", fd);
844
845 #ifndef RFCOMM_DIRECT
846         BT_CHECK_ENABLED(return);
847 #endif
848         retv_if(length <= 0, BLUETOOTH_ERROR_INVALID_PARAM);
849
850 #ifdef TIZEN_DPM_ENABLE
851         if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED ||
852                 _bt_check_dpm(BT_DPM_HF_ONLY, NULL) == BT_DPM_RESTRICTED) {
853                 BT_ERR("Not allow to write RFCOMM data");
854                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
855         }
856 #endif
857
858 #ifdef RFCOMM_DIRECT
859         switch (privilege_token) {
860         case 0:
861                 result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_SOCKET_WRITE);
862
863                 if (result == BLUETOOTH_ERROR_NONE) {
864                         privilege_token = 1; /* Have a permission */
865                 } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) {
866                         BT_ERR("Don't have a privilege to use this API");
867                         privilege_token = -1; /* Don't have a permission */
868                         return BLUETOOTH_ERROR_PERMISSION_DEINED;
869                 } else {
870                         /* Just break - It is not related with permission error */
871                 }
872                 break;
873         case 1:
874                 /* Already have a privilege */
875                 break;
876         case -1:
877                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
878         default:
879                 /* Invalid privilge token value */
880                 return BLUETOOTH_ERROR_INTERNAL;
881         }
882
883         written = write(fd, buf, length);
884         /*BT_DBG("Length %d, written = %d, balance(%d)",
885                          length, written, length - written); */
886         return written;
887 #else
888         BT_INIT_PARAMS();
889         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
890
891         buffer = g_malloc0(length + 1);
892
893         memcpy(buffer, buf, length);
894
895         g_array_append_vals(in_param1, &fd, sizeof(int));
896         g_array_append_vals(in_param2, &length, sizeof(int));
897         g_array_append_vals(in_param3, buffer, length);
898
899         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_SOCKET_WRITE,
900                 in_param1, in_param2, in_param3, in_param4, &out_param);
901
902         BT_DBG("result: %x", result);
903
904         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
905
906         g_free(buffer);
907
908         return result;
909 #endif
910 }
911