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