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>
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"
46 DBusGProxy *rfcomm_proxy;
47 } rfcomm_function_data_t;
49 rfcomm_function_data_t *rfcomm_info;
52 static bt_rfcomm_info_t *__bt_rfcomm_get_client_info(int socket_fd)
55 bt_rfcomm_info_t *client_info;
57 for (l = client_list; l != NULL; l = l->next) {
58 client_info = l->data;
60 if (client_info == NULL)
63 if (socket_fd == client_info->fd)
70 static int __bt_rfcomm_open_socket(char *dev_node)
74 socket_fd = open(dev_node, O_RDWR | O_NOCTTY);
77 BT_ERR("Can't open TTY : %s(%d)", dev_node, socket_fd);
81 BT_DBG("/dev/rfcomm fd = %d", socket_fd);
83 if (_bt_set_non_blocking_tty(socket_fd) < 0) {
84 /* Even if setting the tty fails we will continue */
85 BT_ERR("Unable to set /dev/rfcomm fd = %d", socket_fd);
91 static int __bt_rfcomm_disconnect_request(int socket_fd)
93 DBusGConnection *conn;
94 DBusGProxy *adapter_proxy;
95 DBusGProxy *rfcomm_proxy;
97 bt_rfcomm_info_t *client_info;
98 gchar *device_path = NULL;
99 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
101 retv_if(address == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
103 adapter_proxy = _bt_get_adapter_proxy();
104 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
106 conn = _bt_get_system_gconn();
107 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
109 client_info = __bt_rfcomm_get_client_info(socket_fd);
110 retv_if(client_info == NULL, BLUETOOTH_ERROR_INTERNAL);
112 dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL,
113 G_TYPE_STRING, client_info->address, G_TYPE_INVALID,
114 DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID);
116 retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED);
118 rfcomm_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
119 device_path, BT_SERIAL_INTERFACE);
121 BT_DBG("device path: %s", device_path);
124 retv_if(rfcomm_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
126 BT_DBG("device node: %s", client_info->dev_node);
127 if (!dbus_g_proxy_call(rfcomm_proxy, "Disconnect",
129 G_TYPE_STRING, client_info->dev_node,
130 G_TYPE_INVALID, G_TYPE_INVALID)) {
132 BT_ERR("Disconnect Call Error, %s", error->message);
135 g_object_unref(rfcomm_proxy);
136 return BLUETOOTH_ERROR_INTERNAL;
138 g_object_unref(rfcomm_proxy);
140 return BLUETOOTH_ERROR_NONE;
143 static int __bt_rfcomm_disconnect_cb(void *data)
145 int result = BLUETOOTH_ERROR_NONE;
146 bt_rfcomm_info_t *client_info = data;
148 retv_if(client_info == NULL, BLUETOOTH_ERROR_INTERNAL);
150 _bt_send_event(BT_RFCOMM_CLIENT_EVENT,
151 BLUETOOTH_EVENT_RFCOMM_DISCONNECTED,
152 DBUS_TYPE_INT32, &result,
153 DBUS_TYPE_STRING, &client_info->address,
154 DBUS_TYPE_STRING, &client_info->uuid,
155 DBUS_TYPE_INT16, &client_info->fd,
158 client_list = g_slist_remove(client_list, client_info);
160 g_source_remove(client_info->io_event);
161 close(client_info->fd);
162 g_free(client_info->dev_node);
163 g_free(client_info->address);
164 g_free(client_info->uuid);
167 return BLUETOOTH_ERROR_NONE;
170 static int __bt_rfcomm_cancel_connect_cb(void *data)
172 int result = BLUETOOTH_ERROR_CANCEL_BY_USER;
173 bluetooth_rfcomm_connection_t conn_info;
174 request_info_t *req_info;
178 retv_if(rfcomm_info == NULL, BLUETOOTH_ERROR_INTERNAL);
180 req_info = _bt_get_request_info(rfcomm_info->req_id);
182 retv_if(req_info == NULL, BLUETOOTH_ERROR_INTERNAL);
183 retv_if(req_info->context == NULL, BLUETOOTH_ERROR_INTERNAL);
185 memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t));
186 conn_info.device_role = RFCOMM_ROLE_CLIENT;
187 g_strlcpy(conn_info.uuid, rfcomm_info->uuid,
188 BLUETOOTH_UUID_STRING_MAX);
189 conn_info.socket_fd = -1;
190 _bt_convert_addr_string_to_type(conn_info.device_addr.addr,
191 rfcomm_info->address);
193 out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
194 out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
196 g_array_append_vals(out_param1, &conn_info,
197 sizeof(bluetooth_rfcomm_connection_t));
198 g_array_append_vals(out_param2, &result, sizeof(int));
200 dbus_g_method_return(req_info->context, out_param1, out_param2);
202 g_array_free(out_param1, TRUE);
203 g_array_free(out_param2, TRUE);
205 _bt_delete_request_list(req_info->req_id);
207 g_object_unref(rfcomm_info->rfcomm_proxy);
208 g_free(rfcomm_info->address);
209 g_free(rfcomm_info->uuid);
210 g_free(rfcomm_info->channel);
214 return BLUETOOTH_ERROR_NONE;
217 static int __bt_rfcomm_terminate_client(int socket_fd)
222 bt_rfcomm_info_t *client_info;
224 client_info = __bt_rfcomm_get_client_info(socket_fd);
225 retv_if(client_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
227 result = __bt_rfcomm_disconnect_request(socket_fd);
229 if (result != BLUETOOTH_ERROR_NONE) {
230 BT_ERR("Fail to disconnect socket");
234 /* Send the disconnected event after return the function */
235 g_idle_add((GSourceFunc)__bt_rfcomm_disconnect_cb, client_info);
237 return BLUETOOTH_ERROR_NONE;
240 static gboolean __bt_rfcomm_client_data_received_cb(GIOChannel *chan,
246 int result = BLUETOOTH_ERROR_NONE;
247 bt_rfcomm_info_t *client_info = data;
249 BT_DBG("condition: %d", cond);
251 retv_if(client_info == NULL, FALSE);
253 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
254 BT_ERR("Unix client disconnected (fd=%d)\n", client_info->fd);
255 __bt_rfcomm_terminate_client(client_info->fd);
259 buffer = g_malloc0(BT_RFCOMM_BUFFER_MAX + 1);
261 if (g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_MAX,
262 &len, NULL) == G_IO_STATUS_ERROR) {
263 BT_ERR("IO Channel read error client");
265 __bt_rfcomm_terminate_client(client_info->fd);
270 BT_ERR("Read failed len=%d, fd=%d\n", len, client_info->fd);
272 __bt_rfcomm_terminate_client(client_info->fd);
276 BT_DBG("%s - clientfd = %d", buffer, client_info->fd);
278 _bt_send_event(BT_RFCOMM_CLIENT_EVENT,
279 BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED,
280 DBUS_TYPE_INT32, &result,
281 DBUS_TYPE_INT16, &client_info->fd,
282 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
291 static void __bt_rfcomm_connected_cb(DBusGProxy *proxy, DBusGProxyCall *call,
296 gchar *rfcomm_device_node;
298 int result = BLUETOOTH_ERROR_NONE;
299 bt_rfcomm_info_t *client_info = NULL;
300 request_info_t *req_info;
301 bluetooth_rfcomm_connection_t conn_info;
305 dbus_g_proxy_end_call(proxy, call, &err,
306 G_TYPE_STRING, &rfcomm_device_node, G_TYPE_INVALID);
308 g_object_unref(proxy);
310 if (rfcomm_info == NULL) {
311 BT_ERR("rfcomm_info == NULL");
316 BT_ERR("Error occured in connecting port [%s]", err->message);
318 if (!strcmp("Host is down", err->message))
319 result = BLUETOOTH_ERROR_HOST_DOWN;
321 result = BLUETOOTH_ERROR_CONNECTION_ERROR;
326 BT_DBG("Success Connect REMOTE Device RFCOMM Node[%s]", rfcomm_device_node);
328 socket_fd = __bt_rfcomm_open_socket(rfcomm_device_node);
331 int retry_count = 10;
333 BT_ERR("Fail to open socket[%d] retry_count[%d]", socket_fd, retry_count);
334 usleep(10*1000); /* 10 ms */
335 socket_fd = __bt_rfcomm_open_socket(rfcomm_device_node);
336 } while (socket_fd < 0 && retry_count-- > 0);
339 BT_ERR("Fail to open socket: %d", socket_fd);
344 client_info = g_malloc0(sizeof(bt_rfcomm_info_t));
346 client_info->fd = socket_fd;
347 client_info->dev_node = g_strdup(rfcomm_device_node);
348 client_info->address = g_strdup(rfcomm_info->address);
349 client_info->uuid = g_strdup(rfcomm_info->uuid);
350 client_info->io_channel = g_io_channel_unix_new(socket_fd);
351 g_io_channel_set_encoding(client_info->io_channel, NULL, NULL);
352 client_info->io_event = g_io_add_watch(client_info->io_channel,
353 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
354 __bt_rfcomm_client_data_received_cb,
357 g_io_channel_set_close_on_unref(client_info->io_channel, TRUE);
358 g_io_channel_set_flags(client_info->io_channel,
359 G_IO_FLAG_NONBLOCK, NULL);
361 client_list = g_slist_append(client_list, client_info);
363 _bt_send_event(BT_RFCOMM_CLIENT_EVENT,
364 BLUETOOTH_EVENT_RFCOMM_CONNECTED,
365 DBUS_TYPE_INT32, &result,
366 DBUS_TYPE_STRING, &rfcomm_info->address,
367 DBUS_TYPE_STRING, &rfcomm_info->uuid,
368 DBUS_TYPE_INT16, &socket_fd,
372 req_info = _bt_get_request_info(rfcomm_info->req_id);
374 if (req_info == NULL || req_info->context == NULL)
377 memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t));
378 conn_info.device_role = RFCOMM_ROLE_CLIENT;
379 g_strlcpy(conn_info.uuid, rfcomm_info->uuid,
380 BLUETOOTH_UUID_STRING_MAX);
383 conn_info.socket_fd = client_info->fd;
385 conn_info.socket_fd = -1;
387 _bt_convert_addr_string_to_type(conn_info.device_addr.addr,
388 rfcomm_info->address);
390 out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
391 out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
393 g_array_append_vals(out_param1, &conn_info,
394 sizeof(bluetooth_rfcomm_connection_t));
395 g_array_append_vals(out_param2, &result, sizeof(int));
396 dbus_g_method_return(req_info->context, out_param1, out_param2);
398 g_array_free(out_param1, TRUE);
399 g_array_free(out_param2, TRUE);
400 _bt_delete_request_list(req_info->req_id);
405 ret_if(rfcomm_info == NULL);
407 g_free(rfcomm_info->address);
408 g_free(rfcomm_info->uuid);
409 g_free(rfcomm_info->channel);
414 static void __bt_rfcomm_discover_services_cb(DBusGProxy *proxy, DBusGProxyCall *call,
418 GHashTable *hash = NULL;
419 const char *dev_path = NULL;
420 DBusGConnection *conn;
421 DBusGProxy *rfcomm_proxy;
422 int result = BLUETOOTH_ERROR_NONE;
425 request_info_t *req_info;
426 bluetooth_rfcomm_connection_t conn_info;
428 dbus_g_proxy_end_call(proxy, call, &err,
429 dbus_g_type_get_map("GHashTable",
430 G_TYPE_UINT, G_TYPE_STRING),
431 &hash, G_TYPE_INVALID);
434 BT_ERR("Error occured in Proxy call [%s]\n", err->message);
435 result = BLUETOOTH_ERROR_CONNECTION_ERROR;
440 g_hash_table_destroy(hash);
442 if (rfcomm_info == NULL) {
443 result = BLUETOOTH_ERROR_INTERNAL;
447 conn = _bt_get_system_gconn();
449 BT_ERR("ERROR: Can't get on system bus");
450 result = BLUETOOTH_ERROR_INTERNAL;
454 dev_path = dbus_g_proxy_get_path(proxy);
456 rfcomm_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
458 BT_SERIAL_INTERFACE);
460 g_object_unref(proxy);
463 if (rfcomm_proxy == NULL) {
464 BT_ERR("Failed to get the rfcomm proxy\n");
465 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
469 rfcomm_info->rfcomm_proxy = rfcomm_proxy;
471 if (!dbus_g_proxy_begin_call(rfcomm_proxy, "Connect",
472 (DBusGProxyCallNotify)__bt_rfcomm_connected_cb,
475 G_TYPE_STRING, rfcomm_info->uuid,
477 BT_ERR("RFCOMM connect Dbus Call Error");
478 g_object_unref(rfcomm_proxy);
479 result = BLUETOOTH_ERROR_INTERNAL;
488 g_object_unref(proxy);
490 ret_if(rfcomm_info == NULL);
492 req_info = _bt_get_request_info(rfcomm_info->req_id);
494 if (req_info && req_info->context) {
495 memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t));
497 conn_info.device_role = RFCOMM_ROLE_CLIENT;
498 g_strlcpy(conn_info.uuid, rfcomm_info->uuid,
499 BLUETOOTH_UUID_STRING_MAX);
501 conn_info.socket_fd = -1;
502 _bt_convert_addr_string_to_type(conn_info.device_addr.addr,
503 rfcomm_info->address);
505 out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
506 out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
508 g_array_append_vals(out_param1, &conn_info,
509 sizeof(bluetooth_rfcomm_connection_t));
510 g_array_append_vals(out_param2, &result, sizeof(int));
512 dbus_g_method_return(req_info->context, out_param1, out_param2);
514 g_array_free(out_param1, TRUE);
515 g_array_free(out_param2, TRUE);
516 _bt_delete_request_list(req_info->req_id);
519 g_free(rfcomm_info->address);
520 g_free(rfcomm_info->uuid);
525 int _bt_rfcomm_connect_using_uuid(int request_id,
526 bluetooth_device_address_t *device_address,
529 DBusGConnection *conn;
530 DBusGProxy *adapter_proxy;
531 DBusGProxy *device_proxy;
532 gchar *device_path = NULL;
533 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
535 BT_CHECK_PARAMETER(address, return);
536 BT_CHECK_PARAMETER(remote_uuid, return);
537 retv_if(rfcomm_info != NULL, BLUETOOTH_ERROR_DEVICE_BUSY);
539 adapter_proxy = _bt_get_adapter_proxy();
540 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
542 conn = _bt_get_system_gconn();
543 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
545 _bt_convert_addr_type_to_string(address, device_address->addr);
547 dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL,
548 G_TYPE_STRING, address, G_TYPE_INVALID,
549 DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID);
551 retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED);
553 device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
554 device_path, BT_DEVICE_INTERFACE);
556 retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
558 rfcomm_info = g_malloc0(sizeof(rfcomm_function_data_t));
559 rfcomm_info->address = g_strdup(address);
560 rfcomm_info->uuid = g_strdup(remote_uuid);
561 rfcomm_info->req_id = request_id;
563 if (!dbus_g_proxy_begin_call(device_proxy, "DiscoverServices",
564 (DBusGProxyCallNotify)__bt_rfcomm_discover_services_cb,
566 G_TYPE_STRING, rfcomm_info->uuid,
568 BT_ERR("Could not call dbus proxy\n");
569 g_object_unref(device_proxy);
570 g_free(rfcomm_info->address);
571 g_free(rfcomm_info->uuid);
574 return BLUETOOTH_ERROR_INTERNAL;
577 return BLUETOOTH_ERROR_NONE;
580 /* Range of the Channel : 0 <= channel <= 30 */
581 int _bt_rfcomm_connect_using_channel(int request_id,
582 bluetooth_device_address_t *device_address,
585 DBusGConnection *conn;
586 DBusGProxy *adapter_proxy;
587 DBusGProxy *device_proxy;
588 gchar *device_path = NULL;
589 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
591 BT_CHECK_PARAMETER(address, return);
592 retv_if(rfcomm_info != NULL, BLUETOOTH_ERROR_DEVICE_BUSY);
594 adapter_proxy = _bt_get_adapter_proxy();
595 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
597 conn = _bt_get_system_gconn();
598 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
600 _bt_convert_addr_type_to_string(address, device_address->addr);
602 dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL,
603 G_TYPE_STRING, address, G_TYPE_INVALID,
604 DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID);
606 retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED);
608 device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
610 BT_SERIAL_INTERFACE);
612 retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
614 rfcomm_info = g_malloc0(sizeof(rfcomm_function_data_t));
615 rfcomm_info->address = g_strdup(address);
616 rfcomm_info->channel = g_strdup(channel);
617 rfcomm_info->req_id = request_id;
618 rfcomm_info->rfcomm_proxy = device_proxy;
620 if (!dbus_g_proxy_begin_call(device_proxy, "Connect",
621 (DBusGProxyCallNotify)__bt_rfcomm_connected_cb,
624 G_TYPE_STRING, channel,
626 BT_ERR("RFCOMM connect Dbus Call Error");
627 g_object_unref(device_proxy);
628 return BLUETOOTH_ERROR_INTERNAL;
633 return BLUETOOTH_ERROR_NONE;
636 /* Be used in RFCOMM client /server */
637 int _bt_rfcomm_disconnect(int socket_fd)
639 bt_rfcomm_info_t *socket_info;
641 socket_info = __bt_rfcomm_get_client_info(socket_fd);
642 if (socket_info == NULL)
643 return _bt_rfcomm_server_disconnect(socket_fd);
645 return __bt_rfcomm_terminate_client(socket_fd);
648 /* Be used in RFCOMM client /server */
649 int _bt_rfcomm_write(int socket_fd, char *buf, int length)
654 retv_if(buf == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
656 /* Sometimes user may send huge data */
657 while (wbytes < length) {
658 written = write(socket_fd, buf + wbytes, length - wbytes);
660 BT_ERR("write failed..\n");
661 return BLUETOOTH_ERROR_NOT_IN_OPERATION;
664 /* Synchronize the sending buffer */
671 return BLUETOOTH_ERROR_NONE;
674 int _bt_rfcomm_cancel_connect(void)
676 GError *error = NULL;
681 retv_if(rfcomm_info == NULL, BLUETOOTH_ERROR_NOT_IN_OPERATION);
682 retv_if(rfcomm_info->rfcomm_proxy == NULL,
683 BLUETOOTH_ERROR_INTERNAL);
685 if (rfcomm_info->uuid)
686 input_param = rfcomm_info->uuid;
688 input_param = rfcomm_info->channel;
690 retv_if(input_param == NULL, BLUETOOTH_ERROR_INTERNAL);
692 if (!dbus_g_proxy_call(rfcomm_info->rfcomm_proxy,
695 G_TYPE_STRING, input_param,
696 G_TYPE_INVALID, G_TYPE_INVALID)) {
698 BT_ERR("Disconnect Dbus Call Error, %s", error->message);
701 return BLUETOOTH_ERROR_INTERNAL;
704 /* Send the connected event after return the function */
705 g_idle_add((GSourceFunc) __bt_rfcomm_cancel_connect_cb, NULL);
709 return BLUETOOTH_ERROR_NONE;
712 int _bt_rfcomm_is_connected(gboolean *connected)
714 BT_CHECK_PARAMETER(connected, return);
716 *connected = (client_list == NULL || g_slist_length(client_list) == 0) ?
719 return BLUETOOTH_ERROR_NONE;
722 int _bt_rfcomm_is_device_connected(bluetooth_device_address_t *device_address,
726 bt_rfcomm_info_t *client_info;
727 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
729 BT_CHECK_PARAMETER(device_address, return);
730 BT_CHECK_PARAMETER(connected, return);
732 _bt_convert_addr_type_to_string(address, device_address->addr);
736 for (l = client_list; l != NULL; l = l->next) {
737 client_info = l->data;
739 if (client_info == NULL)
742 if (g_strcmp0(address, client_info->address) == 0) {
744 return BLUETOOTH_ERROR_NONE;
748 return BLUETOOTH_ERROR_NONE;
751 int _bt_rfcomm_client_disconnect_all(void)
754 bt_rfcomm_info_t *client_info;
756 for (l = client_list; l != NULL; l = l->next) {
757 client_info = l->data;
759 if (client_info == NULL)
762 _bt_rfcomm_disconnect(client_info->fd);
765 return BLUETOOTH_ERROR_NONE;