4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hocheol Seo <hocheol.seo@samsung.com>
7 * Girishashok Joshi <girish.joshi@samsung.com>
8 * Chanyeol Park <chanyeol.park@samsung.com>
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
24 #include <dbus/dbus-glib.h>
25 #include <dbus/dbus.h>
29 #include <sys/socket.h>
32 #include "bluetooth-api.h"
33 #include "bt-internal-types.h"
35 #include "bt-service-common.h"
36 #include "bt-service-event.h"
37 #include "bt-service-util.h"
38 #include "bt-service-rfcomm-client.h"
39 #include "bt-service-rfcomm-server.h"
40 #include "bt-service-agent.h"
42 /* Range of RFCOMM server ID : 0 ~ 244 */
43 #define BT_RFCOMM_SERVER_ID_MAX 245
45 #define BT_RFCOMM_PROXY_ADDRESS "x00/bluez/rfcomm"
46 #define BT_RFCOMM_SOCKET_ADDRESS "/bluez/rfcomm"
52 } bt_rfcomm_event_info_t;
55 static int latest_id = -1;
56 static gboolean server_id_used[BT_RFCOMM_SERVER_ID_MAX];
58 int __bt_rfcomm_assign_server_id(void)
62 BT_DBG("latest_id: %d", latest_id);
64 index = latest_id + 1;
66 if (index >= BT_RFCOMM_SERVER_ID_MAX)
69 BT_DBG("index: %d", index);
71 while (server_id_used[index] == TRUE) {
72 if (index == latest_id) {
74 BT_ERR("All request ID is used");
80 if (index >= BT_RFCOMM_SERVER_ID_MAX)
85 server_id_used[index] = TRUE;
87 BT_DBG("Assigned Id: %d", latest_id);
92 void __bt_rfcomm_delete_server_id(int server_id)
94 ret_if(server_id >= BT_RFCOMM_SERVER_ID_MAX);
95 ret_if(server_id < 0);
97 server_id_used[server_id] = FALSE;
99 /* Next server will use this ID */
100 latest_id = server_id - 1;
104 static bt_rfcomm_server_info_t *__bt_rfcomm_get_server_info(int control_fd)
107 bt_rfcomm_server_info_t *server_info;
109 retv_if(control_fd <= 0, NULL);
111 for (l = server_list; l != NULL; l = l->next) {
112 server_info = l->data;
114 if (server_info == NULL)
117 if (control_fd == server_info->control_fd)
124 static bt_rfcomm_server_info_t *__bt_rfcomm_get_server_info_using_data_fd(int data_fd)
127 bt_rfcomm_server_info_t *server_info;
129 retv_if(data_fd <= 0, NULL);
131 for (l = server_list; l != NULL; l = l->next) {
132 server_info = l->data;
134 if (server_info == NULL)
137 if (data_fd == server_info->data_fd)
144 static DBusGProxy *__bt_rfcomm_get_serial_manager_proxy(void)
147 DBusGConnection *g_conn;
152 g_conn = _bt_get_system_gconn();
153 retv_if(g_conn == NULL, NULL);
155 adapter_path = _bt_get_adapter_path();
156 retv_if(adapter_path == NULL, NULL);
158 proxy = dbus_g_proxy_new_for_name(g_conn, BT_BLUEZ_NAME,
159 adapter_path, BT_SERIAL_MANAGER_INTERFACE);
161 g_free(adapter_path);
168 static DBusGProxy *__bt_get_serial_proxy(char *serial_path)
171 DBusGConnection *g_conn;
173 g_conn = _bt_get_system_gconn();
174 retv_if(g_conn == NULL, NULL);
176 proxy = dbus_g_proxy_new_for_name(g_conn, BT_BLUEZ_NAME,
177 serial_path, BT_SERIAL_PROXY_INTERFACE);
182 static char *__bt_rfcomm_get_proxy_address(int server_id)
186 return g_strdup_printf("%s%d",
187 BT_RFCOMM_PROXY_ADDRESS,
191 int __bt_rfcomm_get_socket(int server_id)
195 char *socket_address = NULL;
196 struct sockaddr_un server_addr;
198 retv_if(server_id < 0, -1);
200 socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
201 retv_if(socket_fd < 0, -1);
203 memset(&server_addr, 0, sizeof(server_addr));
204 server_addr.sun_family = PF_UNIX;
206 socket_address = g_strdup_printf("%s%d",
207 BT_RFCOMM_SOCKET_ADDRESS,
210 BT_DBG("socket_address: %s", socket_address);
212 g_strlcpy(server_addr.sun_path + 1, socket_address,
213 sizeof(server_addr.sun_path));
215 if (bind(socket_fd, (struct sockaddr *)&server_addr,
216 sizeof(server_addr)) < 0) {
217 BT_ERR("Can't Bind Sock");
221 BT_DBG("socket_fd = %d", socket_fd);
223 result = _bt_set_socket_non_blocking(socket_fd);
225 if (result != BLUETOOTH_ERROR_NONE) {
226 BT_ERR("Cannot set the tty");
230 g_free(socket_address);
233 g_free(socket_address);
238 int _bt_rfcomm_create_socket(char *sender, char *uuid)
240 DBusGProxy *serial_manager = NULL;
241 DBusGProxy *serial_proxy = NULL;
242 GError *error = NULL;
243 char *proxy_address = NULL;
244 char *serial_path = NULL;
247 bt_rfcomm_server_info_t *server_info;
249 BT_CHECK_PARAMETER(uuid, return);
251 server_id = __bt_rfcomm_assign_server_id();
252 retv_if(server_id < 0, BLUETOOTH_ERROR_INTERNAL);
254 serial_manager = __bt_rfcomm_get_serial_manager_proxy();
255 if (serial_manager == NULL)
258 proxy_address = __bt_rfcomm_get_proxy_address(server_id);
259 if (proxy_address == NULL)
262 dbus_g_proxy_call(serial_manager, "CreateProxy", NULL,
264 G_TYPE_STRING, proxy_address,
266 G_TYPE_STRING, &serial_path,
269 if (serial_path == NULL)
272 BT_DBG("serial_path: %s", serial_path);
274 serial_proxy = __bt_get_serial_proxy(serial_path);
275 if (serial_proxy == NULL)
278 if (!dbus_g_proxy_call(serial_proxy, "Enable", &error,
279 G_TYPE_INVALID, G_TYPE_INVALID)) {
281 BT_ERR("Enable Error: %s\n", error->message);
287 socket_fd = __bt_rfcomm_get_socket(server_id);
289 BT_ERR("Can't get socket");
293 server_info = g_malloc0(sizeof(bt_rfcomm_server_info_t));
294 server_info->server_id = server_id;
295 server_info->serial_proxy = serial_proxy;
296 server_info->manager_proxy = serial_manager;
297 server_info->serial_path = g_strdup(serial_path);
298 server_info->uuid = g_strdup(uuid);
299 server_info->sender = g_strdup(sender);
300 server_info->control_fd = socket_fd;
302 server_list = g_slist_append(server_list, server_info);
304 g_free(proxy_address);
308 __bt_rfcomm_delete_server_id(server_id);
309 g_free(proxy_address);
311 if (serial_manager) {
313 dbus_g_proxy_call(serial_manager, "RemoveProxy", NULL,
314 G_TYPE_STRING, serial_path,
318 g_object_unref(serial_manager);
322 g_object_unref(serial_proxy);
324 return BLUETOOTH_ERROR_INTERNAL;
327 static gboolean __bt_rfcomm_server_data_received_cb(GIOChannel *chan,
333 int result = BLUETOOTH_ERROR_NONE;
334 bt_rfcomm_server_info_t *server_info = data;
336 retv_if(server_info == NULL, FALSE);
338 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
339 BT_ERR("Unix server disconnected: %d", server_info->data_fd);
340 _bt_rfcomm_server_disconnect(server_info->data_fd);
344 buffer = g_malloc0(BT_RFCOMM_BUFFER_MAX + 1);
346 if (g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_MAX, &len, NULL) ==
348 BT_ERR("IO Channel read error server");
350 _bt_rfcomm_server_disconnect(server_info->data_fd);
355 BT_ERR("Read failed len=%d, fd=%d\n",
356 len, server_info->data_fd);
358 _bt_rfcomm_server_disconnect(server_info->data_fd);
362 _bt_send_event(BT_RFCOMM_SERVER_EVENT,
363 BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED,
364 DBUS_TYPE_INT32, &result,
365 DBUS_TYPE_INT16, &server_info->data_fd,
366 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
375 int __bt_rfcomm_server_get_address(bt_rfcomm_server_info_t *server_info)
380 DBusMessageIter reply_iter;
381 DBusMessageIter reply_iter_entry;
382 DBusConnection *conn;
383 const char *property;
385 BT_CHECK_PARAMETER(server_info, return);
387 /* GetInfo Proxy Part */
388 msg = dbus_message_new_method_call(BT_BLUEZ_NAME,
389 server_info->serial_path,
390 BT_SERIAL_PROXY_INTERFACE,
393 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
395 dbus_error_init(&error);
397 conn = _bt_get_system_conn();
399 reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &error);
400 dbus_message_unref(msg);
403 BT_ERR("Can't Call GetInfo Proxy");
404 if (dbus_error_is_set(&error)) {
405 BT_ERR("%s", error.message);
406 dbus_error_free(&error);
408 return BLUETOOTH_ERROR_INTERNAL;
411 dbus_message_iter_init(reply, &reply_iter);
413 if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
414 BT_ERR("Can't get reply arguments - DBUS_TYPE_ARRAY");
418 dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
421 while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
422 DBUS_TYPE_DICT_ENTRY) {
423 DBusMessageIter dict_entry;
424 DBusMessageIter dict_entry_val;
426 dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
428 dbus_message_iter_get_basic(&dict_entry, &property);
430 if (g_strcmp0("connected", property) == 0) {
433 dbus_message_iter_next(&dict_entry);
434 dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
435 dbus_message_iter_get_basic(&dict_entry_val, &value);
440 /*Parsing the address */
441 dbus_message_iter_next(&reply_iter_entry);
442 dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
443 dbus_message_iter_get_basic(&dict_entry, &property);
444 BT_DBG("String received...... = %s", property);
446 if (g_strcmp0("address", property) == 0) {
447 if (!dbus_message_iter_next(&dict_entry)) {
448 BT_ERR("Failed getting next dict entry\n");
452 if (dbus_message_iter_get_arg_type(&dict_entry) !=
454 BT_ERR("Failed get arg type varient\n");
458 /*Getting the value of the varient*/
459 dbus_message_iter_recurse(&dict_entry,
462 if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
464 BT_ERR("Failed get arg type string\n");
468 /*get value string address*/
469 dbus_message_iter_get_basic(&dict_entry_val, &property);
471 BT_DBG("Address = %s\n", property);
473 g_free(server_info->remote_address);
474 server_info->remote_address = g_strdup(property);
479 dbus_message_iter_next(&reply_iter_entry);
482 dbus_message_unref(reply);
484 return BLUETOOTH_ERROR_NONE;
487 dbus_message_unref(reply);
488 return BLUETOOTH_ERROR_INTERNAL;
491 static gboolean __bt_rfcomm_server_connected_cb(GIOChannel *chan,
495 bt_rfcomm_server_info_t *server_info;
496 request_info_t *req_info;
499 struct sockaddr_un sock_addr;
500 int result = BLUETOOTH_ERROR_NONE;
502 BT_DBG("rfcomm_server.server_io_channel has %d", cond);
505 retv_if(server_info == NULL, FALSE);
507 if (cond & G_IO_NVAL)
510 if (cond & (G_IO_HUP | G_IO_ERR)) {
511 _bt_rfcomm_remove_socket(server_info->control_fd);
515 memset(&sock_addr, 0, sizeof(struct sockaddr_un));
516 addr_len = sizeof(struct sockaddr_un);
518 client_sock = accept(server_info->control_fd,
519 (struct sockaddr *)&sock_addr,
520 (socklen_t *)&addr_len);
522 if (client_sock < 0) {
523 BT_ERR("Server Accept Error");
527 BT_DBG("Accept Client Sock.(%d)\n", client_sock);
531 if (_bt_set_non_blocking_tty(client_sock) < 0) {
532 /* Even if setting the tty fails we will continue */
533 BT_ERR("Setting the tty properties failed(%d)\n", client_sock);
536 server_info->data_fd = client_sock;
537 server_info->data_io = g_io_channel_unix_new(client_sock);
539 g_io_channel_set_encoding(server_info->data_io, NULL, NULL);
540 g_io_channel_set_flags(server_info->data_io, G_IO_FLAG_NONBLOCK, NULL);
541 g_io_channel_set_close_on_unref(server_info->data_io, TRUE);
543 server_info->data_id =
544 g_io_add_watch(server_info->data_io,
545 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
546 __bt_rfcomm_server_data_received_cb, server_info);
548 g_io_channel_unref(server_info->data_io);
550 __bt_rfcomm_server_get_address(server_info);
552 if (server_info->remote_address == NULL)
553 server_info->remote_address = g_strdup("");
555 if (server_info->server_type == BT_CUSTOM_SERVER) {
560 req_info = _bt_get_request_info(server_info->accept_id);
561 if (req_info == NULL || req_info->context == NULL) {
562 BT_ERR("info is NULL");
566 server_info->accept_id = 0;
567 result = BLUETOOTH_ERROR_NONE;
569 out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
570 out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
572 g_array_append_vals(out_param1, &server_info->data_fd,
574 g_array_append_vals(out_param2, &result, sizeof(int));
576 dbus_g_method_return(req_info->context, out_param1, out_param2);
578 g_array_free(out_param1, TRUE);
579 g_array_free(out_param2, TRUE);
581 _bt_delete_request_list(req_info->req_id);
585 _bt_send_event(BT_RFCOMM_SERVER_EVENT,
586 BLUETOOTH_EVENT_RFCOMM_CONNECTED,
587 DBUS_TYPE_INT32, &result,
588 DBUS_TYPE_STRING, &server_info->remote_address,
589 DBUS_TYPE_STRING, &server_info->uuid,
590 DBUS_TYPE_INT16, &server_info->data_fd,
598 int _bt_rfcomm_listen(int socket_fd, int max_pending, gboolean is_native)
601 bt_rfcomm_server_info_t *server_info;
602 GIOChannel *io_channel;
604 server_info = __bt_rfcomm_get_server_info(socket_fd);
605 retv_if(server_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
606 retv_if(server_info->control_io != NULL, BLUETOOTH_ERROR_DEVICE_BUSY);
608 if (listen(socket_fd, max_pending) != 0) {
609 BT_ERR("Fail to listen");
610 return BLUETOOTH_ERROR_INTERNAL;
613 io_channel = g_io_channel_unix_new(socket_fd);
614 server_info->control_io = io_channel;
616 g_io_channel_set_close_on_unref(io_channel, TRUE);
617 g_io_channel_set_encoding(io_channel, NULL, NULL);
618 g_io_channel_set_flags(io_channel, G_IO_FLAG_NONBLOCK, NULL);
620 io_id = g_io_add_watch(io_channel,
621 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
622 __bt_rfcomm_server_connected_cb,
625 server_info->control_id = io_id;
626 g_io_channel_unref(io_channel);
628 /* BT_CUSTOM_SERVER / BT_NATIVE_SERVER*/
630 server_info->server_type = BT_NATIVE_SERVER;
632 server_info->server_type = BT_CUSTOM_SERVER;
633 _bt_register_osp_server_in_agent(BT_RFCOMM_SERVER,
634 server_info->uuid, NULL, -1);
637 return BLUETOOTH_ERROR_NONE;
640 int _bt_rfcomm_remove_socket(int socket_fd)
642 bt_rfcomm_server_info_t *server_info;
643 int result = BLUETOOTH_ERROR_NONE;
647 server_info = __bt_rfcomm_get_server_info(socket_fd);
648 retv_if(server_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
650 if (server_info->serial_proxy) {
651 if (!dbus_g_proxy_call(server_info->serial_proxy, "Disable",
655 BT_ERR("Fail to disable");
659 if (server_info->manager_proxy && server_info->serial_path) {
660 if (!dbus_g_proxy_call(server_info->manager_proxy,
662 G_TYPE_STRING, server_info->serial_path,
665 BT_ERR("Fail to remove proxy");
669 if (server_info->server_type == BT_CUSTOM_SERVER) {
670 _bt_unregister_osp_server_in_agent(BT_RFCOMM_SERVER,
674 _bt_send_event(BT_RFCOMM_SERVER_EVENT,
675 BLUETOOTH_EVENT_RFCOMM_SERVER_REMOVED,
676 DBUS_TYPE_INT32, &result,
677 DBUS_TYPE_INT16, &server_info->data_fd,
680 _bt_rfcomm_server_disconnect(server_info->data_fd);
682 if (server_info->control_id > 0)
683 g_source_remove(server_info->control_id);
685 if (server_info->control_fd > 0)
686 close(server_info->control_fd);
688 server_list = g_slist_remove(server_list, server_info);
690 __bt_rfcomm_delete_server_id(server_info->server_id);
692 g_free(server_info->serial_path);
693 g_free(server_info->uuid);
694 g_free(server_info->sender);
699 return BLUETOOTH_ERROR_NONE;
702 static int __bt_rfcomm_server_disconnect_cb(void *data)
704 bt_rfcomm_event_info_t *event_info = data;
705 int result = BLUETOOTH_ERROR_NONE;
707 retv_if(event_info == NULL, BLUETOOTH_ERROR_NONE);
708 retv_if(event_info->uuid == NULL, BLUETOOTH_ERROR_NONE);
710 if (event_info->remote_address == NULL)
711 event_info->remote_address = g_strdup("");
713 _bt_send_event(BT_RFCOMM_SERVER_EVENT,
714 BLUETOOTH_EVENT_RFCOMM_DISCONNECTED,
715 DBUS_TYPE_INT32, &result,
716 DBUS_TYPE_STRING, &event_info->remote_address,
717 DBUS_TYPE_STRING, &event_info->uuid,
718 DBUS_TYPE_INT16, &event_info->data_fd,
721 g_free(event_info->uuid);
722 g_free(event_info->remote_address);
725 return BLUETOOTH_ERROR_NONE;
728 int _bt_rfcomm_server_disconnect(int data_fd)
730 bt_rfcomm_server_info_t *server_info;
731 bt_rfcomm_event_info_t *event_info;
735 retv_if(data_fd <= 0, BLUETOOTH_ERROR_INVALID_PARAM);
737 server_info = __bt_rfcomm_get_server_info_using_data_fd(data_fd);
738 retv_if(server_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
740 if (server_info->data_id > 0)
741 g_source_remove(server_info->data_id);
743 if (server_info->data_fd > 0)
744 close(server_info->data_fd);
746 event_info = g_malloc0(sizeof(bt_rfcomm_event_info_t));
747 event_info->data_fd = server_info->data_fd;
748 event_info->remote_address = g_strdup(server_info->remote_address);
749 event_info->uuid = g_strdup(server_info->uuid);
751 /* Send the disconnected event after return the function */
752 g_idle_add((GSourceFunc)__bt_rfcomm_server_disconnect_cb, event_info);
754 g_free(server_info->remote_address);
755 server_info->remote_address = NULL;
756 server_info->data_fd = -1;
757 server_info->data_id = 0;
758 server_info->data_io = NULL;
762 return BLUETOOTH_ERROR_NONE;
765 /* To support the BOT */
766 int _bt_rfcomm_is_uuid_available(char *uuid, gboolean *available)
769 bt_rfcomm_server_info_t *server_info;
771 BT_CHECK_PARAMETER(uuid, return);
772 BT_CHECK_PARAMETER(available, return);
776 for (l = server_list; l != NULL; l = l->next) {
777 server_info = l->data;
779 if (server_info == NULL)
782 if (g_ascii_strcasecmp(uuid, server_info->uuid) == 0) {
784 return BLUETOOTH_ERROR_NONE;
788 return BLUETOOTH_ERROR_NONE;
791 /* To support the BOT */
792 int _bt_rfcomm_accept_connection(void)
795 if (!_bt_agent_reply_authorize(TRUE))
796 return BLUETOOTH_ERROR_INTERNAL;
799 return BLUETOOTH_ERROR_NONE;
802 /* To support the BOT */
803 int _bt_rfcomm_reject_connection(void)
806 if (!_bt_agent_reply_authorize(FALSE))
807 return BLUETOOTH_ERROR_INTERNAL;
810 return BLUETOOTH_ERROR_NONE;
813 bt_rfcomm_server_info_t *_bt_rfcomm_get_server_info_using_uuid(char *uuid)
816 bt_rfcomm_server_info_t *server_info;
818 retv_if(uuid == NULL, NULL);
820 for (l = server_list; l != NULL; l = l->next) {
821 server_info = l->data;
823 if (server_info == NULL)
826 if (g_strcmp0(server_info->uuid, uuid) == 0)
833 int _bt_rfcomm_server_disconnect_all_connection(void)
836 bt_rfcomm_server_info_t *server_info;
838 for (l = server_list; l != NULL; l = l->next) {
839 server_info = l->data;
841 if (server_info == NULL)
844 _bt_rfcomm_disconnect(server_info->data_fd);
847 return BLUETOOTH_ERROR_NONE;
850 int _bt_rfcomm_server_check_existence(gboolean *existence)
852 BT_CHECK_PARAMETER(existence, return);
854 if (server_list && g_slist_length(server_list) > 0) {
860 return BLUETOOTH_ERROR_NONE;
863 int _bt_rfcomm_server_check_termination(char *name)
866 bt_rfcomm_server_info_t *server_info;
868 BT_CHECK_PARAMETER(name, return);
870 for (l = server_list; l != NULL; l = l->next) {
871 server_info = l->data;
873 if (server_info == NULL)
876 if (g_strcmp0(server_info->sender, name) == 0) {
877 _bt_rfcomm_remove_socket(server_info->control_fd);
881 return BLUETOOTH_ERROR_NONE;