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