2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <gio/gunixfdlist.h>
22 #include <sys/socket.h>
25 #include "bluetooth-api.h"
26 #include "bt-internal-types.h"
28 #include "bt-common.h"
29 #include "bt-request-sender.h"
30 #include "bt-event-handler.h"
34 static GSList *rfcomm_nodes;
44 bluetooth_device_address_t addr;
45 guint disconnect_idle_id;
48 static rfcomm_info_t *__find_rfcomm_info_with_id(int id)
52 for (l = rfcomm_nodes; l != NULL; l = l->next) {
53 rfcomm_info_t *info = l->data;
62 static rfcomm_info_t *__find_rfcomm_info_with_fd(int fd)
66 for (l = rfcomm_nodes; l != NULL; l = l->next) {
67 rfcomm_info_t *info = l->data;
76 static rfcomm_info_t *__find_rfcomm_info_with_path(const gchar *path)
80 for (l = rfcomm_nodes; l != NULL; l = l->next) {
81 rfcomm_info_t *info = l->data;
83 if (g_strcmp0(info->path, path) == 0)
90 static rfcomm_info_t *__find_rfcomm_info_with_uuid(const char *uuid)
94 for (l = rfcomm_nodes; l != NULL; l = l->next) {
95 rfcomm_info_t *info = l->data;
97 if (g_strcmp0(info->uuid, uuid) == 0)
104 gboolean _check_uuid_path(char *path, char *uuid)
106 rfcomm_info_t *info = NULL;
107 info = __find_rfcomm_info_with_path(path);
111 if (strcmp(info->uuid, uuid) == 0)
117 static void __connected_cb(rfcomm_info_t *info, bt_event_info_t *event_info)
119 bluetooth_rfcomm_connection_t conn_info;
121 memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t));
122 conn_info.device_role = RFCOMM_ROLE_SERVER;
123 g_strlcpy(conn_info.uuid, info->uuid, BLUETOOTH_UUID_STRING_MAX);
124 conn_info.socket_fd = info->fd;
125 conn_info.device_addr = info->addr;
126 conn_info.server_id = info->id;
128 BT_INFO_C("Connected [RFCOMM Server]");
129 _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_CONNECTED,
130 BLUETOOTH_ERROR_NONE, &conn_info,
131 event_info->cb, event_info->user_data);
134 static gboolean __rfcomm_server_disconnect(rfcomm_info_t *info)
136 bluetooth_rfcomm_disconnection_t disconn_info;
138 bt_event_info_t *event_info;
140 BT_INFO_C("Disconnected [RFCOMM Server]");
142 if (info->data_id > 0) {
143 g_source_remove(info->data_id);
153 g_io_channel_shutdown(info->data_io, TRUE, NULL);
154 g_io_channel_unref(info->data_io);
155 info->data_io = NULL;
157 info->disconnect_idle_id = 0;
158 event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT);
159 if (event_info == NULL)
162 memset(&disconn_info, 0x00, sizeof(bluetooth_rfcomm_disconnection_t));
163 disconn_info.device_role = RFCOMM_ROLE_SERVER;
164 g_strlcpy(disconn_info.uuid, info->uuid, BLUETOOTH_UUID_STRING_MAX);
165 disconn_info.socket_fd = fd;
166 disconn_info.device_addr = info->addr;
168 _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DISCONNECTED,
169 BLUETOOTH_ERROR_NONE, &disconn_info,
170 event_info->cb, event_info->user_data);
176 static gboolean __data_received_cb(GIOChannel *chan, GIOCondition cond,
181 int result = BLUETOOTH_ERROR_NONE;
182 rfcomm_info_t *info = data;
183 bt_event_info_t *event_info;
184 bluetooth_rfcomm_received_data_t data_r;
185 GIOStatus status = G_IO_STATUS_NORMAL;
188 retv_if(info == NULL, FALSE);
190 event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT);
192 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
193 BT_ERR_C("RFComm Server disconnected: %d", info->fd);
195 if (info->disconnect_idle_id > 0) {
196 BT_INFO("Disconnect idle still not process remove source");
197 g_source_remove(info->disconnect_idle_id);
198 info->disconnect_idle_id = 0;
201 __rfcomm_server_disconnect(info);
205 buffer = g_malloc0(BT_RFCOMM_BUFFER_LEN + 1);
207 status = g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_LEN,
209 if (status != G_IO_STATUS_NORMAL) {
210 BT_ERR("IO Channel read is failed with %d", status);
214 BT_ERR("IO Channel read error [%s]", err->message);
215 if (status == G_IO_STATUS_ERROR &&
216 !g_strcmp0(err->message, "Connection reset by peer")) {
217 BT_ERR("cond : %d", cond);
219 if (info->disconnect_idle_id > 0) {
220 BT_INFO("Disconnect idle still not process remove source");
221 g_source_remove(info->disconnect_idle_id);
222 info->disconnect_idle_id = 0;
224 __rfcomm_server_disconnect(info);
233 BT_ERR("Length is zero");
235 if (event_info == NULL) {
240 data_r.socket_fd = info->fd;
241 data_r.buffer_size = len;
242 data_r.buffer = buffer;
244 _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED,
246 event_info->cb, event_info->user_data);
253 int new_server_connection(const char *path, int fd, bluetooth_device_address_t *addr)
256 bt_event_info_t *event_info;
258 BT_DBG("%s %d", path, fd);
260 info = __find_rfcomm_info_with_path(path);
265 memcpy(&info->addr, addr, sizeof(bluetooth_device_address_t));
267 info->data_io = g_io_channel_unix_new(info->fd);
269 g_io_channel_set_encoding(info->data_io, NULL, NULL);
270 g_io_channel_set_flags(info->data_io, G_IO_FLAG_NONBLOCK, NULL);
272 info->data_id = g_io_add_watch(info->data_io,
273 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
274 __data_received_cb, info);
276 event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT);
278 __connected_cb(info, event_info);
284 static rfcomm_info_t *__register_method()
291 id = __rfcomm_assign_id();
295 path = g_strdup_printf("/org/socket/server/%d/%d", getpid(), id);
297 object_id = _bt_register_new_conn(path, new_server_connection);
299 __rfcomm_delete_id(id);
302 info = g_new(rfcomm_info_t, 1);
303 info->object_id = (guint)object_id;
308 rfcomm_nodes = g_slist_append(rfcomm_nodes, info);
313 static rfcomm_info_t *__register_method_2(const char *path,const char *bus_name)
318 object_id = _bt_register_new_conn_ex(path, bus_name, new_server_connection);
322 info = g_new(rfcomm_info_t, 1);
323 info->object_id = (guint)object_id;
324 info->path = g_strdup(path);
328 rfcomm_nodes = g_slist_append(rfcomm_nodes, info);
333 void free_rfcomm_info(rfcomm_info_t *info)
335 bt_event_info_t *event_info;
338 if (info->disconnect_idle_id > 0) {
339 BT_INFO("Disconnect idle still not process remove source");
340 g_source_remove(info->disconnect_idle_id);
341 info->disconnect_idle_id = 0;
344 __rfcomm_delete_id(info->id);
345 _bt_unregister_gdbus(info->object_id);
348 event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT);
350 BT_DBG("event type %d", event_info->event_type);
351 __rfcomm_server_disconnect(info);
359 void _bt_rfcomm_server_free_all()
361 BT_DBG("Free all the servers");
363 g_slist_free_full(rfcomm_nodes, (GDestroyNotify)free_rfcomm_info);
368 BT_EXPORT_API int bluetooth_rfcomm_create_socket(const char *uuid)
375 char uuid_str[BLUETOOTH_UUID_STRING_MAX];
378 BT_CHECK_ENABLED(return);
379 BT_CHECK_PARAMETER(uuid, return);
380 BT_INFO("UUID Provided %s", uuid);
382 if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_CREATE_SOCKET)
383 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
384 BT_ERR("Don't have a privilege to use this API");
385 return BLUETOOTH_ERROR_PERMISSION_DEINED;
389 BT_INFO("<<<<<<<<< RFCOMM Create socket from app >>>>>>>>>");
390 info = __register_method();
394 info->uuid = g_strdup(uuid);
395 info->disconnect_idle_id = 0;
400 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
402 g_strlcpy(uuid_str, uuid, sizeof(uuid_str));
403 g_array_append_vals(in_param1, uuid_str, BLUETOOTH_UUID_STRING_MAX);
405 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_CREATE_SOCKET,
406 in_param1, in_param2, in_param3, in_param4, &out_param);
408 BT_DBG("result: %x", result);
410 if (result == BLUETOOTH_ERROR_NONE) {
411 socket_fd = g_array_index(out_param, int, 0);
413 BT_ERR("Fail to send request");
416 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
422 BT_EXPORT_API int bluetooth_rfcomm_create_socket_ex(const char *uuid, const char *bus_name, const char *path)
427 BT_CHECK_ENABLED(return);
428 BT_CHECK_PARAMETER(path, return);
429 BT_INFO("PATH Provided %s", path);
431 if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_CREATE_SOCKET_EX)
432 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
433 BT_ERR("Don't have a privilege to use this API");
434 return BLUETOOTH_ERROR_PERMISSION_DEINED;
437 BT_INFO("<<<<<<<<< RFCOMM Create socket from app >>>>>>>>>");
438 info = __register_method_2(path, bus_name);
440 return BLUETOOTH_ERROR_IN_PROGRESS;
441 info->uuid = g_strdup(uuid);
442 info->disconnect_idle_id = 0;
444 return BLUETOOTH_ERROR_NONE;
446 return BLUETOOTH_ERROR_NOT_SUPPORT;
451 BT_EXPORT_API int bluetooth_rfcomm_remove_socket(int socket_fd)
459 BT_CHECK_ENABLED(return);
461 if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_REMOVE_SOCKET)
462 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
463 BT_ERR("Don't have a privilege to use this API");
464 return BLUETOOTH_ERROR_PERMISSION_DEINED;
468 BT_ERR("Invalid FD");
469 return BLUETOOTH_ERROR_INVALID_PARAM;
473 BT_INFO("<<<<<<<<< RFCOMM Remove socket request from app, fd=[%d] >>>>>>>>>>>", socket_fd);
475 info = __find_rfcomm_info_with_id(socket_fd);
477 return BLUETOOTH_ERROR_INVALID_PARAM;
479 _bt_unregister_osp_server_in_agent(BT_RFCOMM_SERVER,info->uuid);
480 _bt_unregister_profile(info->path);
482 rfcomm_nodes = g_slist_remove(rfcomm_nodes, info);
483 free_rfcomm_info(info);
485 return BLUETOOTH_ERROR_NONE;
488 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
490 g_array_append_vals(in_param1, &socket_fd, sizeof(int));
492 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_REMOVE_SOCKET,
493 in_param1, in_param2, in_param3, in_param4, &out_param);
495 BT_DBG("result: %x", result);
497 if (result == BLUETOOTH_ERROR_NONE) {
498 _bt_remove_server(socket_fd);
501 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
507 BT_EXPORT_API int bluetooth_rfcomm_remove_socket_ex(const char *uuid)
512 BT_CHECK_ENABLED(return);
514 if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_REMOVE_SOCKET)
515 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
516 BT_ERR("Don't have a privilege to use this API");
517 return BLUETOOTH_ERROR_PERMISSION_DEINED;
520 BT_INFO("<<<<<<<<< RFCOMM Remove socket request from app, uuid=[%s] >>>>>>>>>>>", uuid);
522 info = __find_rfcomm_info_with_uuid(uuid);
524 return BLUETOOTH_ERROR_INVALID_PARAM;
526 _bt_unregister_osp_server_in_agent(BT_RFCOMM_SERVER, info->uuid);
527 _bt_unregister_profile(info->path);
529 rfcomm_nodes = g_slist_remove(rfcomm_nodes, info);
530 free_rfcomm_info(info);
532 return BLUETOOTH_ERROR_NONE;
534 return BLUETOOTH_ERROR_NOT_SUPPORT;
538 BT_EXPORT_API int bluetooth_rfcomm_server_disconnect(int socket_fd)
545 BT_INFO(">>>>>>>>RFCOMM server disconnect request from APP>>>>>>>>>");
547 BT_ERR("Invalid FD");
548 return BLUETOOTH_ERROR_INVALID_PARAM;
551 info = __find_rfcomm_info_with_fd(socket_fd);
553 return BLUETOOTH_ERROR_INVALID_PARAM;
555 if (info->data_io == NULL)
556 return BLUETOOTH_ERROR_NOT_CONNECTED;
558 g_io_channel_shutdown(info->data_io, TRUE, NULL);
559 g_io_channel_unref(info->data_io);
560 info->data_io = NULL;
562 _bt_convert_addr_type_to_string(address, info->addr.addr);
563 BT_DBG("Address %s", address);
564 _bt_disconnect_profile(address, info->uuid, NULL,NULL);
566 info->disconnect_idle_id = g_idle_add((GSourceFunc)
567 __rfcomm_server_disconnect, info);
570 return BLUETOOTH_ERROR_NONE;
574 BT_CHECK_ENABLED(return);
577 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
579 g_array_append_vals(in_param1, &socket_fd, sizeof(int));
581 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_SOCKET_DISCONNECT,
582 in_param1, in_param2, in_param3, in_param4, &out_param);
584 BT_DBG("result: %x", result);
586 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
592 BT_EXPORT_API gboolean bluetooth_rfcomm_is_server_uuid_available(const char *uuid)
595 gboolean available = TRUE;
596 char uuid_str[BLUETOOTH_UUID_STRING_MAX];
598 retv_if(uuid == NULL, FALSE);
599 retv_if(bluetooth_check_adapter() ==
600 BLUETOOTH_ADAPTER_DISABLED, FALSE);
603 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
605 g_strlcpy(uuid_str, uuid, sizeof(uuid_str));
606 g_array_append_vals(in_param1, uuid_str, BLUETOOTH_UUID_STRING_MAX);
608 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_IS_UUID_AVAILABLE,
609 in_param1, in_param2, in_param3, in_param4, &out_param);
611 BT_DBG("result: %x", result);
613 if (result == BLUETOOTH_ERROR_NONE) {
614 available = g_array_index(out_param, gboolean, 0);
617 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
619 BT_DBG("available: %d", available);
624 BT_EXPORT_API int bluetooth_rfcomm_server_is_connected(const bluetooth_device_address_t *device_address, gboolean *connected)
628 char connected_addr[BT_ADDRESS_STRING_SIZE] = { 0 };
629 char input_addr[BT_ADDRESS_STRING_SIZE] = { 0 };
631 BT_CHECK_PARAMETER(device_address, return);
632 BT_CHECK_PARAMETER(connected, return);
634 _bt_convert_addr_type_to_string(input_addr, (unsigned char *)device_address->addr);
638 for (l = rfcomm_nodes; l != NULL; l = l->next) {
643 _bt_convert_addr_type_to_string(connected_addr, info->addr.addr);
645 if (g_strcmp0(connected_addr, input_addr) == 0) {
647 return BLUETOOTH_ERROR_NONE;
651 return BLUETOOTH_ERROR_NONE;
654 BT_EXPORT_API int bluetooth_rfcomm_listen_and_accept(int socket_fd, int max_pending_connection)
660 gboolean native_service = TRUE;
663 BT_CHECK_ENABLED(return);
665 BT_ERR("Invalid FD");
666 return BLUETOOTH_ERROR_INVALID_PARAM;
670 BT_INFO("<<<<<<<<< RFCOMM Listen & accept from app >>>>>>>>>>>");
672 info = __find_rfcomm_info_with_id(socket_fd);
674 return BLUETOOTH_ERROR_INVALID_PARAM;
676 bt_register_profile_info_t profile_info;
679 profile_info.authentication = TRUE;
680 profile_info.authorization = TRUE;
681 profile_info.obj_path = info->path;
682 profile_info.role = NULL;
683 profile_info.service = info->uuid;
684 profile_info.uuid = info->uuid;
686 BT_INFO("uuid %s", profile_info.uuid);
687 result = _bt_register_profile(&profile_info, TRUE);
692 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
694 g_array_append_vals(in_param1, &socket_fd, sizeof(int));
695 g_array_append_vals(in_param2, &max_pending_connection, sizeof(int));
696 g_array_append_vals(in_param3, &native_service, sizeof(gboolean));
698 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_LISTEN,
699 in_param1, in_param2, in_param3, in_param4, &out_param);
701 BT_DBG("result: %x", result);
703 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
709 BT_EXPORT_API int bluetooth_rfcomm_listen_and_accept_ex(const char *uuid, int max_pending_connection, const char *bus_name, const char *path)
714 BT_CHECK_ENABLED(return);
716 BT_INFO("<<<<<<<<< RFCOMM Listen & accept from app >>>>>>>>>>>");
718 info = __find_rfcomm_info_with_uuid(uuid);
720 return BLUETOOTH_ERROR_INVALID_PARAM;
722 bt_register_profile_info_t profile_info;
725 profile_info.authentication = TRUE;
726 profile_info.authorization = TRUE;
727 profile_info.obj_path = info->path;
728 profile_info.role = NULL;
729 profile_info.service = info->uuid;
730 profile_info.uuid = info->uuid;
732 BT_INFO("uuid %s", profile_info.uuid);
733 result = _bt_register_profile_ex(&profile_info, TRUE, bus_name, path);
737 return BLUETOOTH_ERROR_NOT_SUPPORT;
741 BT_EXPORT_API int bluetooth_rfcomm_listen(int socket_fd, int max_pending_connection)
747 gboolean native_service = FALSE;
750 BT_CHECK_ENABLED(return);
752 BT_ERR("Invalid FD");
753 return BLUETOOTH_ERROR_INVALID_PARAM;
757 BT_INFO("<<<<<<<<< RFCOMM Listen >>>>>>>>>>>");
759 info = __find_rfcomm_info_with_id(socket_fd);
761 return BLUETOOTH_ERROR_INVALID_PARAM;
763 bt_register_profile_info_t profile_info;
766 profile_info.authentication = TRUE;
767 profile_info.authorization = TRUE;
768 profile_info.obj_path = info->path;
769 profile_info.role = NULL;
770 profile_info.service = info->uuid;
771 profile_info.uuid = info->uuid;
772 BT_INFO("UUID %s", info->uuid);
773 BT_INFO("PATH %s", info->path);
774 result = _bt_register_profile_platform(&profile_info, TRUE);
775 if (result != BLUETOOTH_ERROR_NONE)
778 return _bt_register_osp_server_in_agent(BT_RFCOMM_SERVER, info->uuid,
779 info->path, socket_fd);
783 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
785 g_array_append_vals(in_param1, &socket_fd, sizeof(int));
786 g_array_append_vals(in_param2, &max_pending_connection, sizeof(int));
787 g_array_append_vals(in_param3, &native_service, sizeof(gboolean));
789 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_LISTEN,
790 in_param1, in_param2, in_param3, in_param4, &out_param);
792 BT_DBG("result: %x", result);
794 if (result == BLUETOOTH_ERROR_NONE) {
795 _bt_add_server(socket_fd);
798 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
804 BT_EXPORT_API int bluetooth_rfcomm_accept_connection(int server_fd)
808 BT_CHECK_ENABLED(return);
810 BT_ERR("Invalid FD");
811 return BLUETOOTH_ERROR_INVALID_PARAM;
815 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
817 g_array_append_vals(in_param1, &server_fd, sizeof(int));
819 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_ACCEPT_CONNECTION,
820 in_param1, in_param2, in_param3, in_param4, &out_param);
822 BT_DBG("result: %x", result);
824 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
829 BT_EXPORT_API int bluetooth_rfcomm_reject_connection(int server_fd)
833 BT_CHECK_ENABLED(return);
836 BT_ERR("Invalid FD");
837 return BLUETOOTH_ERROR_INVALID_PARAM;
843 BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
845 g_array_append_vals(in_param1, &server_fd, sizeof(int));
847 result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_REJECT_CONNECTION,
848 in_param1, in_param2, in_param3, in_param4, &out_param);
850 BT_DBG("result: %x", result);
852 BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);