Disconnect rfcomm connections
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-rfcomm-server.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 <gio/gio.h>
21 #include <gio/gunixfdlist.h>
22 #include <sys/socket.h>
23 #endif
24
25 #include "bluetooth-api.h"
26 #include "bt-internal-types.h"
27
28 #include "bt-common.h"
29 #include "bt-request-sender.h"
30 #include "bt-event-handler.h"
31
32 #ifdef TIZEN_DPM_ENABLE
33 #include "bt-dpm.h"
34 #endif
35
36 #ifdef RFCOMM_DIRECT
37
38 static GSList *rfcomm_nodes;
39
40 typedef struct {
41         bluetooth_device_address_t addr;
42         int fd;
43         guint watch_id;
44         gboolean disconnected;
45 } rfcomm_conn_t;
46
47 typedef struct {
48         guint object_id;
49         gchar *path;
50         int id;
51         char *uuid;
52         GSList *rfcomm_conns;
53         guint disconnect_idle_id;
54 } rfcomm_info_t;
55
56 static rfcomm_info_t *__find_rfcomm_info_with_id(int id)
57 {
58         GSList *l;
59
60         for (l = rfcomm_nodes; l != NULL; l = l->next) {
61                 rfcomm_info_t *info = l->data;
62
63                 if (info->id == id)
64                         return info;
65         }
66
67         return NULL;
68 }
69
70 static rfcomm_info_t *__find_rfcomm_info_with_fd(int fd)
71 {
72         GSList *l;
73         GSList *ll;
74
75         for (l = rfcomm_nodes; l != NULL; l = l->next) {
76                 rfcomm_info_t *info = l->data;
77
78                 for (ll = info->rfcomm_conns; ll; ll = ll->next) {
79                         rfcomm_conn_t *conn = ll->data;
80
81                         if (conn && conn->fd == fd)
82                                 return info;
83                 }
84         }
85
86         return NULL;
87 }
88
89 static rfcomm_info_t *__find_rfcomm_info_with_path(const gchar *path)
90 {
91         GSList *l;
92
93         for (l = rfcomm_nodes; l != NULL; l = l->next) {
94                 rfcomm_info_t *info = l->data;
95
96                 if (g_strcmp0(info->path, path) == 0)
97                         return info;
98         }
99
100         return NULL;
101 }
102
103 static rfcomm_info_t *__find_rfcomm_info_with_uuid(const char *uuid)
104 {
105         GSList *l;
106
107         for (l = rfcomm_nodes; l != NULL; l = l->next) {
108                 rfcomm_info_t *info = l->data;
109
110                 if (g_strcmp0(info->uuid, uuid) == 0)
111                         return info;
112         }
113
114         return NULL;
115 }
116
117 static rfcomm_conn_t *__find_rfcomm_conn_with_fd(rfcomm_info_t *info,
118                                                       int fd)
119 {
120         GSList *l;
121         rfcomm_conn_t *conn;
122
123         for (l = info->rfcomm_conns; l; l = l->next) {
124                 conn = l->data;
125
126                 if (conn && conn->fd == fd)
127                         return conn;
128         }
129
130         return NULL;
131 }
132
133 static void __rfcomm_remove_conn(rfcomm_info_t *info, int fd)
134 {
135         rfcomm_conn_t *conn;
136
137         conn = __find_rfcomm_conn_with_fd(info, fd);
138         if (conn == NULL)
139                 return;
140
141         info->rfcomm_conns = g_slist_remove(info->rfcomm_conns, conn);
142
143         if (conn->watch_id > 0)
144                 g_source_remove(conn->watch_id);
145         g_free(conn);
146 }
147
148 gboolean _check_uuid_path(char *path, char *uuid)
149 {
150         rfcomm_info_t *info = NULL;
151         info = __find_rfcomm_info_with_path(path);
152         if (!info)
153                 return FALSE;
154
155         if (strcmp(info->uuid, uuid) == 0)
156                 return TRUE;
157
158         return FALSE;
159 }
160
161 static void __connected_cb(rfcomm_info_t *info, rfcomm_conn_t *conn,
162                            bt_event_info_t *event_info)
163 {
164         bluetooth_rfcomm_connection_t conn_info;
165
166         memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t));
167
168         conn_info.device_role = RFCOMM_ROLE_SERVER;
169         g_strlcpy(conn_info.uuid, info->uuid, BLUETOOTH_UUID_STRING_MAX);
170         conn_info.socket_fd = conn->fd;
171         conn_info.device_addr = conn->addr;
172         conn_info.server_id = info->id;
173
174         BT_INFO_C("### Connected [RFCOMM Server]");
175         _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_CONNECTED,
176                         BLUETOOTH_ERROR_NONE, &conn_info,
177                         event_info->cb, event_info->user_data);
178 }
179
180 static void __rfcomm_server_disconnect_conn(rfcomm_conn_t *conn,
181                                             rfcomm_info_t *info)
182 {
183         bluetooth_rfcomm_disconnection_t disconn_info;
184         bt_event_info_t *event_info;
185
186         if (conn == NULL)
187                 return;
188
189         if (conn->disconnected == FALSE)
190                 return;
191
192         if (conn->watch_id > 0) {
193                 g_source_remove(conn->watch_id);
194                 conn->watch_id = 0;
195         }
196
197         event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT);
198         if (event_info == NULL) {
199                 __rfcomm_remove_conn(info, conn->fd);
200                 return;
201         }
202
203         memset(&disconn_info, 0x00, sizeof(bluetooth_rfcomm_disconnection_t));
204         disconn_info.device_role = RFCOMM_ROLE_SERVER;
205         g_strlcpy(disconn_info.uuid, info->uuid, BLUETOOTH_UUID_STRING_MAX);
206         disconn_info.device_addr = conn->addr;
207
208         BT_DBG("Disconnected FD [%d]", conn->fd);
209         disconn_info.socket_fd = conn->fd;
210
211         _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DISCONNECTED,
212                         BLUETOOTH_ERROR_NONE, &disconn_info,
213                         event_info->cb, event_info->user_data);
214
215         __rfcomm_remove_conn(info, conn->fd);
216 }
217
218 static gboolean __rfcomm_server_disconnect(rfcomm_info_t *info)
219 {
220         BT_INFO_C("### Disconnected [RFCOMM Server]");
221
222         if (g_slist_find(rfcomm_nodes, info) == NULL) {
223                 BT_INFO("rfcomm resource is already freed");
224                 return FALSE;
225         }
226
227         info->disconnect_idle_id = 0;
228
229         g_slist_foreach(info->rfcomm_conns,
230                         (GFunc)__rfcomm_server_disconnect_conn, info);
231
232         BT_DBG("-");
233         return FALSE;
234 }
235
236 static gboolean __is_error_by_disconnect(GError *err)
237 {
238         return !g_strcmp0(err->message, "Connection reset by peer") ||
239                         !g_strcmp0(err->message, "Connection timed out") ||
240                         !g_strcmp0(err->message, "Software caused connection abort");
241 }
242
243 static gboolean __data_received_cb(GIOChannel *chan, GIOCondition cond,
244                                                                 gpointer data)
245 {
246         char *buffer = NULL;
247         gsize len = 0;
248         int result = BLUETOOTH_ERROR_NONE;
249         rfcomm_info_t *info = data;
250         rfcomm_conn_t *conn;
251         bt_event_info_t *event_info;
252         bluetooth_rfcomm_received_data_t data_r;
253         GIOStatus status = G_IO_STATUS_NORMAL;
254         GError *err = NULL;
255         int fd;
256
257         retv_if(info == NULL, FALSE);
258
259         fd = g_io_channel_unix_get_fd(chan);
260         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
261                 BT_ERR_C("RFComm Server disconnected: %d", fd);
262
263                 if (info->disconnect_idle_id > 0) {
264                         BT_INFO("Disconnect idle still not process remove source");
265                         g_source_remove(info->disconnect_idle_id);
266                         info->disconnect_idle_id = 0;
267                 }
268
269                 conn = __find_rfcomm_conn_with_fd(info, fd);
270                 if (conn == NULL) {
271                         BT_ERR("No Connection info found with FD [%d]", fd);
272                         return FALSE;
273                 }
274
275                 if (conn->disconnected == FALSE) {
276                         close(conn->fd);
277                         conn->disconnected = TRUE;
278                 }
279                 __rfcomm_server_disconnect(info);
280                 return FALSE;
281         }
282
283         buffer = g_malloc0(BT_RFCOMM_BUFFER_LEN + 1);
284
285         status =  g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_LEN,
286                                                 &len, &err);
287         if (status != G_IO_STATUS_NORMAL) {
288                 BT_ERR("IO Channel read is failed with %d", status);
289
290                 g_free(buffer);
291                 if (!err)
292                         return TRUE;
293
294                 BT_ERR("IO Channel read error [%s]", err->message);
295                 if (status == G_IO_STATUS_ERROR &&
296                     __is_error_by_disconnect(err)) {
297                         BT_ERR("cond : %d", cond);
298                         g_error_free(err);
299
300                         if (info->disconnect_idle_id > 0) {
301                                 BT_INFO("Disconnect idle still not process remove source");
302                                 g_source_remove(info->disconnect_idle_id);
303                                 info->disconnect_idle_id = 0;
304                         }
305
306                         conn = __find_rfcomm_conn_with_fd(info, fd);
307                         if (conn == NULL) {
308                                 BT_ERR("No Connection info found with FD [%d]", fd);
309                                 return FALSE;
310                         }
311
312                         if (conn->disconnected == FALSE) {
313                                 close(conn->fd);
314                                 conn->disconnected = TRUE;
315                         }
316                         __rfcomm_server_disconnect(info);
317                         return FALSE;
318                 }
319                 g_error_free(err);
320                 return TRUE;
321         }
322
323         if (len == 0)
324                 BT_ERR("Length is zero");
325
326         event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT);
327         if (event_info == NULL) {
328                 g_free(buffer);
329                 return TRUE;
330         }
331
332         data_r.socket_fd = fd;
333         data_r.buffer_size = len;
334         data_r.buffer = buffer;
335
336         _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED,
337                         result, &data_r,
338                         event_info->cb, event_info->user_data);
339
340         g_free(buffer);
341
342         return TRUE;
343 }
344
345 int new_server_connection(const char *path, int fd, bluetooth_device_address_t *addr)
346 {
347         rfcomm_info_t *info;
348         rfcomm_conn_t *conn;
349         GIOChannel *data_io;
350         bt_event_info_t *event_info;
351
352         BT_DBG("%s %d", path, fd);
353
354         info = __find_rfcomm_info_with_path(path);
355         if (info == NULL)
356                 return -1;
357
358         conn = g_new0(rfcomm_conn_t, 1);
359         conn->fd = fd;
360         memcpy(&conn->addr, addr, sizeof(bluetooth_device_address_t));
361         info->rfcomm_conns = g_slist_append(info->rfcomm_conns, conn);
362
363         data_io = g_io_channel_unix_new(conn->fd);
364
365         g_io_channel_set_encoding(data_io, NULL, NULL);
366         g_io_channel_set_flags(data_io, G_IO_FLAG_NONBLOCK, NULL);
367
368         conn->watch_id = g_io_add_watch(data_io,
369                            G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
370                            __data_received_cb, info);
371
372         g_io_channel_unref(data_io);
373
374         event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT);
375         if (event_info)
376                 __connected_cb(info, conn, event_info);
377
378         return 0;
379 }
380
381 static rfcomm_info_t *__register_method()
382 {
383         gchar *path;
384         rfcomm_info_t *info;
385         int object_id;
386         int id;
387
388         id = __rfcomm_assign_id();
389         if (id < 0)
390                 return NULL;
391
392         path = g_strdup_printf("/org/socket/server/%d/%d", getpid(), id);
393
394         object_id = _bt_register_new_conn(path, new_server_connection);
395         if (object_id < 0) {
396                 __rfcomm_delete_id(id);
397                 return NULL;
398         }
399         info = g_new0(rfcomm_info_t, 1);
400         info->object_id = (guint)object_id;
401         info->path = path;
402         info->id = id;
403
404         rfcomm_nodes = g_slist_append(rfcomm_nodes, info);
405
406         return info;
407 }
408
409 static rfcomm_info_t *__register_method_2(const char *path, const char *bus_name)
410 {
411         rfcomm_info_t *info;
412         int object_id;
413
414         object_id = _bt_register_new_conn_ex(path, bus_name, new_server_connection);
415         if (object_id < 0)
416                 return NULL;
417
418         info = g_new0(rfcomm_info_t, 1);
419         info->object_id = (guint)object_id;
420         info->path = g_strdup(path);
421         info->id = -1;
422
423         rfcomm_nodes = g_slist_append(rfcomm_nodes, info);
424
425         return info;
426 }
427
428 void free_rfcomm_conn(rfcomm_conn_t *conn, rfcomm_info_t *info)
429 {
430         if (conn->disconnected == FALSE) {
431                 close(conn->fd);
432                 conn->disconnected = TRUE;
433         }
434         __rfcomm_server_disconnect_conn(conn, info);
435 }
436
437 void free_rfcomm_info(rfcomm_info_t *info)
438 {
439         BT_DBG("");
440
441         if (info->disconnect_idle_id > 0) {
442                 BT_INFO("Disconnect idle still not process remove source");
443                 g_source_remove(info->disconnect_idle_id);
444                 info->disconnect_idle_id = 0;
445         }
446
447         __rfcomm_delete_id(info->id);
448         _bt_unregister_gdbus(info->object_id);
449
450         g_slist_foreach(info->rfcomm_conns, (GFunc)free_rfcomm_conn, info);
451
452         g_free(info->path);
453         g_free(info->uuid);
454         g_free(info);
455 }
456
457 void _bt_rfcomm_server_free_all(void)
458 {
459         BT_DBG("Free all the servers");
460
461         g_slist_free_full(rfcomm_nodes, (GDestroyNotify)free_rfcomm_info);
462         rfcomm_nodes = NULL;
463 }
464
465 void _bt_rfcomm_server_disconnect_all(void)
466 {
467         GSList *server;
468         GSList *conn;
469         char addr[20];
470
471         BT_INFO("### Disconnect all RFCOMM server connections");
472
473         for (server = rfcomm_nodes; server; ) {
474                 rfcomm_info_t *info = server->data;
475
476                 for (conn = info->rfcomm_conns; conn; conn = conn->next) {
477                         rfcomm_conn_t *conn_info = conn->data;
478
479                         if (conn_info == NULL)
480                                 continue;
481
482                         if (conn_info->watch_id == 0 || conn_info->disconnected)
483                                 continue;
484
485                         close(conn_info->fd);
486                         conn_info->disconnected = TRUE;
487
488                         _bt_convert_addr_type_to_string(addr,
489                                                         conn_info->addr.addr);
490                         _bt_disconnect_profile(addr, info->uuid, NULL,NULL);
491                 }
492
493                 server = server->next;
494                 __rfcomm_server_disconnect(info);
495         }
496
497         return;
498 }
499 #endif
500
501 BT_EXPORT_API int bluetooth_rfcomm_create_socket(const char *uuid)
502 {
503 #ifdef RFCOMM_DIRECT
504         rfcomm_info_t *info;
505 #else
506         int result;
507         int socket_fd = -1;
508         char uuid_str[BLUETOOTH_UUID_STRING_MAX];
509 #endif
510
511         BT_CHECK_ENABLED(return);
512         BT_CHECK_PARAMETER(uuid, return);
513         BT_INFO("UUID Provided %s", uuid);
514
515         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_CREATE_SOCKET)
516                 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
517                 BT_ERR("Don't have a privilege to use this API");
518                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
519         }
520
521 #ifdef TIZEN_DPM_ENABLE
522         if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
523                 BT_ERR("Not allow to use SPP profile");
524                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
525         }
526 #endif
527
528 #ifdef RFCOMM_DIRECT
529         BT_INFO("<<<<<<<<< RFCOMM Create socket from app >>>>>>>>>");
530         info = __register_method();
531         if (info == NULL)
532                 return -1;
533
534         info->uuid = g_strdup(uuid);
535         info->disconnect_idle_id = 0;
536         return info->id;
537 #else
538
539         BT_INIT_PARAMS();
540         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
541
542         g_strlcpy(uuid_str, uuid, sizeof(uuid_str));
543         g_array_append_vals(in_param1, uuid_str, BLUETOOTH_UUID_STRING_MAX);
544
545         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_CREATE_SOCKET,
546                 in_param1, in_param2, in_param3, in_param4, &out_param);
547
548         BT_DBG("result: %x", result);
549
550         if (result == BLUETOOTH_ERROR_NONE)
551                 socket_fd = g_array_index(out_param, int, 0);
552         else
553                 BT_ERR("Fail to send request");
554
555         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
556
557         return socket_fd;
558 #endif
559 }
560
561 BT_EXPORT_API int bluetooth_rfcomm_create_socket_ex(const char *uuid, const char *bus_name, const char *path)
562 {
563 #ifdef RFCOMM_DIRECT
564         rfcomm_info_t *info;
565
566         BT_CHECK_ENABLED(return);
567         BT_CHECK_PARAMETER(path, return);
568         BT_INFO("PATH Provided %s", path);
569
570         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_CREATE_SOCKET_EX)
571                 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
572                 BT_ERR("Don't have a privilege to use this API");
573                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
574         }
575
576 #ifdef TIZEN_DPM_ENABLE
577         if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
578                 BT_ERR("Not allow to use SPP profile");
579                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
580         }
581 #endif
582
583         BT_INFO("<<<<<<<<< RFCOMM Create socket from app >>>>>>>>>");
584         info = __register_method_2(path, bus_name);
585         if (info == NULL)
586                 return BLUETOOTH_ERROR_IN_PROGRESS;
587         info->uuid = g_strdup(uuid);
588         info->disconnect_idle_id = 0;
589
590         return BLUETOOTH_ERROR_NONE;
591 #else
592         return BLUETOOTH_ERROR_NOT_SUPPORT;
593 #endif
594 }
595
596
597 BT_EXPORT_API int bluetooth_rfcomm_remove_socket(int id)
598 {
599 #ifdef RFCOMM_DIRECT
600         rfcomm_info_t *info;
601 #else
602         int result;
603 #endif
604
605         BT_CHECK_ENABLED(return);
606
607         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_REMOVE_SOCKET)
608                 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
609                 BT_ERR("Don't have a privilege to use this API");
610                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
611         }
612
613         if (id < 0) {
614                 BT_ERR("Invalid ID");
615                 return BLUETOOTH_ERROR_INVALID_PARAM;
616         }
617
618 #ifdef RFCOMM_DIRECT
619         BT_INFO("RFCOMM Remove socket request from app, ID [%d]", id);
620
621         info = __find_rfcomm_info_with_id(id);
622         if (info == NULL)
623                 return BLUETOOTH_ERROR_INVALID_PARAM;
624
625         _bt_unregister_osp_server_in_agent(BT_RFCOMM_SERVER, info->uuid);
626         _bt_unregister_profile(info->path);
627
628         rfcomm_nodes = g_slist_remove(rfcomm_nodes, info);
629         free_rfcomm_info(info);
630
631         return BLUETOOTH_ERROR_NONE;
632 #else
633         BT_INIT_PARAMS();
634         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
635
636         g_array_append_vals(in_param1, &id, sizeof(int));
637
638         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_REMOVE_SOCKET,
639                 in_param1, in_param2, in_param3, in_param4, &out_param);
640
641         BT_DBG("result: %x", result);
642
643         if (result == BLUETOOTH_ERROR_NONE)
644                 _bt_remove_server(id);
645
646         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
647
648         return result;
649 #endif
650 }
651
652 BT_EXPORT_API int bluetooth_rfcomm_remove_socket_ex(const char *uuid)
653 {
654 #ifdef RFCOMM_DIRECT
655         rfcomm_info_t *info;
656
657         BT_CHECK_ENABLED(return);
658
659         if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_REMOVE_SOCKET)
660                 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
661                 BT_ERR("Don't have a privilege to use this API");
662                 return BLUETOOTH_ERROR_PERMISSION_DEINED;
663         }
664
665         BT_INFO("RFCOMM Remove socket request from app, uuid=[%s]", uuid);
666
667         info = __find_rfcomm_info_with_uuid(uuid);
668         if (info == NULL)
669                 return BLUETOOTH_ERROR_INVALID_PARAM;
670
671         _bt_unregister_osp_server_in_agent(BT_RFCOMM_SERVER, info->uuid);
672         _bt_unregister_profile(info->path);
673
674         rfcomm_nodes = g_slist_remove(rfcomm_nodes, info);
675         free_rfcomm_info(info);
676
677         return BLUETOOTH_ERROR_NONE;
678 #else
679         return BLUETOOTH_ERROR_NOT_SUPPORT;
680 #endif
681 }
682
683 BT_EXPORT_API int bluetooth_rfcomm_server_disconnect(int socket_fd)
684 {
685 #ifdef RFCOMM_DIRECT
686         rfcomm_info_t *info;
687         rfcomm_conn_t *conn;
688
689         char address[20];
690
691         BT_INFO("### Disconnect RFCOMM server");
692         if (socket_fd < 0) {
693                 BT_ERR("Invalid FD");
694                 return BLUETOOTH_ERROR_INVALID_PARAM;
695         }
696
697         info = __find_rfcomm_info_with_fd(socket_fd);
698         if (info == NULL)
699                 return BLUETOOTH_ERROR_INVALID_PARAM;
700
701         conn = __find_rfcomm_conn_with_fd(info, socket_fd);
702         if (conn == NULL)
703                 return BLUETOOTH_ERROR_INVALID_PARAM;
704
705         if (conn->watch_id == 0 || conn->disconnected)
706                 return BLUETOOTH_ERROR_NOT_CONNECTED;
707
708         close(conn->fd);
709         conn->disconnected = TRUE;
710
711         _bt_convert_addr_type_to_string(address, conn->addr.addr);
712
713         BT_DBG("Address %s", address);
714         _bt_disconnect_profile(address, info->uuid, NULL, NULL);
715
716         if (info->disconnect_idle_id == 0)
717                 info->disconnect_idle_id = g_idle_add(
718                                 (GSourceFunc)__rfcomm_server_disconnect, info);
719         BT_DBG("-");
720
721         return BLUETOOTH_ERROR_NONE;
722 #else
723         int result;
724
725         BT_CHECK_ENABLED(return);
726
727         BT_INIT_PARAMS();
728         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
729
730         g_array_append_vals(in_param1, &socket_fd, sizeof(int));
731
732         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_SOCKET_DISCONNECT,
733                 in_param1, in_param2, in_param3, in_param4, &out_param);
734
735         BT_DBG("result: %x", result);
736
737         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
738
739         return result;
740 #endif
741 }
742
743 BT_EXPORT_API gboolean bluetooth_rfcomm_is_server_uuid_available(const char *uuid)
744 {
745         int result;
746         gboolean available = TRUE;
747         char uuid_str[BLUETOOTH_UUID_STRING_MAX];
748
749         retv_if(uuid == NULL, FALSE);
750         retv_if(bluetooth_check_adapter() ==
751                                 BLUETOOTH_ADAPTER_DISABLED, FALSE);
752
753         BT_INIT_PARAMS();
754         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
755
756         g_strlcpy(uuid_str, uuid, sizeof(uuid_str));
757         g_array_append_vals(in_param1, uuid_str, BLUETOOTH_UUID_STRING_MAX);
758
759         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_IS_UUID_AVAILABLE,
760                 in_param1, in_param2, in_param3, in_param4, &out_param);
761
762         BT_DBG("result: %x", result);
763
764         if (result == BLUETOOTH_ERROR_NONE)
765                 available = g_array_index(out_param, gboolean, 0);
766
767         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
768
769         BT_DBG("available: %d", available);
770
771         return available;
772 }
773
774 BT_EXPORT_API int bluetooth_rfcomm_server_is_connected(const bluetooth_device_address_t *device_address, gboolean *connected)
775 {
776         GSList *l;
777         GSList *ll;
778         rfcomm_info_t *info;
779         rfcomm_conn_t *conn;
780
781         BT_CHECK_PARAMETER(device_address, return);
782         BT_CHECK_PARAMETER(connected, return);
783
784         *connected = FALSE;
785
786         for (l = rfcomm_nodes; l; l = l->next) {
787                 info = l->data;
788
789                 if (info == NULL || info->rfcomm_conns == NULL)
790                         continue;
791
792                 for (ll = info->rfcomm_conns; ll; ll = ll->next) {
793                         conn = ll->data;
794
795                         if (memcmp(device_address, &conn->addr,
796                                         sizeof(bluetooth_device_address_t)))
797                                 continue;
798
799                         *connected = TRUE;
800                         return BLUETOOTH_ERROR_NONE;
801                 }
802         }
803
804         return BLUETOOTH_ERROR_NONE;
805 }
806
807 BT_EXPORT_API int bluetooth_rfcomm_listen_and_accept(int id, int max_pending_connection)
808 {
809 #ifdef RFCOMM_DIRECT
810         rfcomm_info_t *info;
811 #else
812         int result;
813         gboolean native_service = TRUE;
814 #endif
815
816         BT_CHECK_ENABLED(return);
817         if (id < 0) {
818                 BT_ERR("Invalid ID");
819                 return BLUETOOTH_ERROR_INVALID_PARAM;
820         }
821
822 #ifdef TIZEN_DPM_ENABLE
823         if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
824                 BT_ERR("Not allow to use SPP profile");
825                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
826         }
827 #endif
828
829 #ifdef RFCOMM_DIRECT
830         BT_INFO("RFCOMM Listen & accept from app");
831
832         info = __find_rfcomm_info_with_id(id);
833         if (info == NULL)
834                 return BLUETOOTH_ERROR_INVALID_PARAM;
835
836         bt_register_profile_info_t profile_info;
837         int result;
838
839         profile_info.authentication = TRUE;
840         profile_info.authorization = TRUE;
841         profile_info.obj_path = info->path;
842         profile_info.role = NULL;
843         profile_info.service = info->uuid;
844         profile_info.uuid = info->uuid;
845
846         BT_INFO("uuid %s", profile_info.uuid);
847         result = _bt_register_profile(&profile_info, TRUE);
848
849         return result;
850 #else
851         BT_INIT_PARAMS();
852         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
853
854         g_array_append_vals(in_param1, &id, sizeof(int));
855         g_array_append_vals(in_param2, &max_pending_connection, sizeof(int));
856         g_array_append_vals(in_param3, &native_service, sizeof(gboolean));
857
858         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_LISTEN,
859                 in_param1, in_param2, in_param3, in_param4, &out_param);
860
861         BT_DBG("result: %x", result);
862
863         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
864
865         return result;
866 #endif
867 }
868
869 BT_EXPORT_API int bluetooth_rfcomm_listen_and_accept_ex(const char *uuid,
870                                         int max_pending_connection,
871                                         const char *bus_name, const char *path)
872 {
873 #ifdef RFCOMM_DIRECT
874         rfcomm_info_t *info;
875
876         BT_CHECK_ENABLED(return);
877
878 #ifdef TIZEN_DPM_ENABLE
879         if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
880                 BT_ERR("Not allow to use SPP profile");
881                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
882         }
883 #endif
884
885         BT_INFO("RFCOMM Listen & accept from app");
886
887         info = __find_rfcomm_info_with_uuid(uuid);
888         if (info == NULL)
889                 return BLUETOOTH_ERROR_INVALID_PARAM;
890
891         bt_register_profile_info_t profile_info;
892         int result;
893
894         profile_info.authentication = TRUE;
895         profile_info.authorization = TRUE;
896         profile_info.obj_path = info->path;
897         profile_info.role = NULL;
898         profile_info.service = info->uuid;
899         profile_info.uuid = info->uuid;
900
901         BT_INFO("uuid %s", profile_info.uuid);
902         result = _bt_register_profile_ex(&profile_info, TRUE, bus_name, path);
903
904         return result;
905 #else
906         return BLUETOOTH_ERROR_NOT_SUPPORT;
907 #endif
908 }
909
910 BT_EXPORT_API int bluetooth_rfcomm_listen(int id, int max_pending_connection)
911 {
912 #ifdef RFCOMM_DIRECT
913         rfcomm_info_t *info;
914 #else
915         int result;
916         gboolean native_service = FALSE;
917 #endif
918
919         BT_CHECK_ENABLED(return);
920         if (id < 0) {
921                 BT_ERR("Invalid ID");
922                 return BLUETOOTH_ERROR_INVALID_PARAM;
923         }
924
925 #ifdef TIZEN_DPM_ENABLE
926         if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
927                 BT_ERR("Not allow to use SPP profile");
928                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
929         }
930 #endif
931
932 #ifdef RFCOMM_DIRECT
933         BT_INFO("RFCOMM Listen");
934
935         info = __find_rfcomm_info_with_id(id);
936         if (info == NULL)
937                 return BLUETOOTH_ERROR_INVALID_PARAM;
938
939         bt_register_profile_info_t profile_info;
940         int result;
941
942         profile_info.authentication = TRUE;
943         profile_info.authorization = TRUE;
944         profile_info.obj_path = info->path;
945         profile_info.role = NULL;
946         profile_info.service = info->uuid;
947         profile_info.uuid = info->uuid;
948         BT_INFO("UUID %s", info->uuid);
949         BT_INFO("PATH %s", info->path);
950         result = _bt_register_profile_platform(&profile_info, TRUE);
951         if (result != BLUETOOTH_ERROR_NONE)
952                 return result;
953
954         return _bt_register_osp_server_in_agent(BT_RFCOMM_SERVER, info->uuid,
955                                                 info->path, id);
956
957 #else
958         BT_INIT_PARAMS();
959         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
960
961         g_array_append_vals(in_param1, &id, sizeof(int));
962         g_array_append_vals(in_param2, &max_pending_connection, sizeof(int));
963         g_array_append_vals(in_param3, &native_service, sizeof(gboolean));
964
965         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_LISTEN,
966                 in_param1, in_param2, in_param3, in_param4, &out_param);
967
968         BT_DBG("result: %x", result);
969
970         if (result == BLUETOOTH_ERROR_NONE)
971                 _bt_add_server(id);
972
973         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
974
975         return result;
976 #endif
977 }
978
979 BT_EXPORT_API int bluetooth_rfcomm_accept_connection(int server_fd)
980 {
981         int result;
982
983         BT_CHECK_ENABLED(return);
984
985 #ifdef TIZEN_DPM_ENABLE
986         if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED) {
987                 BT_ERR("Not allow to use SPP profile");
988                 return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
989         }
990 #endif
991
992         if (server_fd < 0) {
993                 BT_ERR("Invalid FD");
994                 return BLUETOOTH_ERROR_INVALID_PARAM;
995         }
996
997         BT_INIT_PARAMS();
998         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
999
1000         g_array_append_vals(in_param1, &server_fd, sizeof(int));
1001
1002         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_ACCEPT_CONNECTION,
1003                 in_param1, in_param2, in_param3, in_param4, &out_param);
1004
1005         BT_DBG("result: %x", result);
1006
1007         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1008
1009         return result;
1010 }
1011
1012 BT_EXPORT_API int bluetooth_rfcomm_reject_connection(int server_fd)
1013 {
1014         int result;
1015
1016         BT_CHECK_ENABLED(return);
1017
1018         if (server_fd < 0) {
1019                 BT_ERR("Invalid FD");
1020                 return BLUETOOTH_ERROR_INVALID_PARAM;
1021         }
1022
1023         BT_INFO("+");
1024
1025         BT_INIT_PARAMS();
1026         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1027
1028         g_array_append_vals(in_param1, &server_fd, sizeof(int));
1029
1030         result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_REJECT_CONNECTION,
1031                 in_param1, in_param2, in_param3, in_param4, &out_param);
1032
1033         BT_DBG("result: %x", result);
1034
1035         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
1036
1037         return result;
1038 }
1039