4 * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
20 #include <dbus/dbus-glib.h>
21 #include <dbus/dbus.h>
28 #include "bluetooth-api.h"
29 #include "bt-internal-types.h"
31 #include "bt-service-common.h"
32 #include "bt-service-event.h"
33 #include "bt-service-util.h"
34 #include "bt-service-rfcomm-client.h"
35 #include "bt-service-rfcomm-server.h"
42 DBusGProxy *rfcomm_proxy;
43 } rfcomm_function_data_t;
45 rfcomm_function_data_t *rfcomm_info;
48 static bt_rfcomm_info_t *__bt_rfcomm_get_client_info(int socket_fd)
51 bt_rfcomm_info_t *client_info;
53 for (l = client_list; l != NULL; l = l->next) {
54 client_info = l->data;
56 if (client_info == NULL)
59 if (socket_fd == client_info->fd)
66 static int __bt_rfcomm_open_socket(char *dev_node)
70 socket_fd = open(dev_node, O_RDWR | O_NOCTTY);
73 BT_ERR("\nCan't open TTY : %s(%d)",dev_node, errno);
77 BT_DBG("/dev/rfcomm fd = %d", socket_fd);
79 if (_bt_set_non_blocking_tty(socket_fd) < 0) {
80 /* Even if setting the tty fails we will continue */
81 BT_ERR("Unable to set /dev/rfcomm fd = %d", socket_fd);
87 static int __bt_rfcomm_disconnect_request(int socket_fd)
89 DBusGConnection *conn;
90 DBusGProxy *adapter_proxy;
91 DBusGProxy *rfcomm_proxy;
93 bt_rfcomm_info_t *client_info;
94 gchar *device_path = NULL;
95 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
97 retv_if(address == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
99 adapter_proxy = _bt_get_adapter_proxy();
100 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
102 conn = _bt_get_system_gconn();
103 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
105 client_info = __bt_rfcomm_get_client_info(socket_fd);
106 retv_if(client_info == NULL, BLUETOOTH_ERROR_INTERNAL);
108 dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL,
109 G_TYPE_STRING, client_info->address, G_TYPE_INVALID,
110 DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID);
112 retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED);
114 rfcomm_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
115 device_path, BT_SERIAL_INTERFACE);
117 BT_DBG("device path: %s", device_path);
120 retv_if(rfcomm_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
122 BT_DBG("device node: %s", client_info->dev_node);
123 if (!dbus_g_proxy_call(rfcomm_proxy, "Disconnect",
125 G_TYPE_STRING, client_info->dev_node,
126 G_TYPE_INVALID, G_TYPE_INVALID)) {
128 BT_ERR("Disconnect Call Error, %s", error->message);
131 g_object_unref(rfcomm_proxy);
132 return BLUETOOTH_ERROR_INTERNAL;
134 g_object_unref(rfcomm_proxy);
136 return BLUETOOTH_ERROR_NONE;
139 static int __bt_rfcomm_disconnect_cb(void *data)
141 int result = BLUETOOTH_ERROR_NONE;
142 bt_rfcomm_info_t *client_info = data;
144 retv_if(client_info == NULL, BLUETOOTH_ERROR_INTERNAL);
146 _bt_send_event(BT_RFCOMM_CLIENT_EVENT,
147 BLUETOOTH_EVENT_RFCOMM_DISCONNECTED,
148 DBUS_TYPE_INT32, &result,
149 DBUS_TYPE_STRING, &client_info->address,
150 DBUS_TYPE_STRING, &client_info->uuid,
151 DBUS_TYPE_INT16, &client_info->fd,
154 client_list = g_slist_remove(client_list, client_info);
156 g_source_remove(client_info->io_event);
157 close(client_info->fd);
158 g_free(client_info->dev_node);
159 g_free(client_info->address);
160 g_free(client_info->uuid);
163 return BLUETOOTH_ERROR_NONE;
166 static int __bt_rfcomm_cancel_connect_cb(void *data)
168 int result = BLUETOOTH_ERROR_CANCEL_BY_USER;
169 bluetooth_rfcomm_connection_t conn_info;
170 request_info_t *req_info;
174 retv_if(rfcomm_info == NULL, BLUETOOTH_ERROR_INTERNAL);
176 req_info = _bt_get_request_info(rfcomm_info->req_id);
178 retv_if(req_info == NULL, BLUETOOTH_ERROR_INTERNAL);
179 retv_if(req_info->context == NULL, BLUETOOTH_ERROR_INTERNAL);
181 memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t));
182 conn_info.device_role = RFCOMM_ROLE_CLIENT;
183 g_strlcpy(conn_info.uuid, rfcomm_info->uuid,
184 BLUETOOTH_UUID_STRING_MAX);
185 conn_info.socket_fd = -1;
186 _bt_convert_addr_string_to_type(conn_info.device_addr.addr,
187 rfcomm_info->address);
189 out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
190 out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
192 g_array_append_vals(out_param1, &conn_info,
193 sizeof(bluetooth_rfcomm_connection_t));
194 g_array_append_vals(out_param2, &result, sizeof(int));
196 dbus_g_method_return(req_info->context, out_param1, out_param2);
198 g_array_free(out_param1, TRUE);
199 g_array_free(out_param2, TRUE);
201 _bt_delete_request_list(req_info->req_id);
203 g_object_unref(rfcomm_info->rfcomm_proxy);
204 g_free(rfcomm_info->address);
205 g_free(rfcomm_info->uuid);
206 g_free(rfcomm_info->channel);
210 return BLUETOOTH_ERROR_NONE;
213 static int __bt_rfcomm_terminate_client(int socket_fd)
218 bt_rfcomm_info_t *client_info;
220 client_info = __bt_rfcomm_get_client_info(socket_fd);
221 retv_if(client_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
223 result = __bt_rfcomm_disconnect_request(socket_fd);
225 if (result != BLUETOOTH_ERROR_NONE) {
226 BT_ERR("Fail to disconnect socket");
230 /* Send the disconnected event after return the function */
231 g_idle_add((GSourceFunc)__bt_rfcomm_disconnect_cb, client_info);
233 return BLUETOOTH_ERROR_NONE;
236 static gboolean __bt_rfcomm_client_data_received_cb(GIOChannel *chan,
242 int result = BLUETOOTH_ERROR_NONE;
243 bt_rfcomm_info_t *client_info = data;
245 BT_DBG("condition: %d", cond);
247 retv_if(client_info == NULL, FALSE);
249 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
250 BT_ERR("Unix client disconnected (fd=%d)\n", client_info->fd);
251 __bt_rfcomm_terminate_client(client_info->fd);
255 buffer = g_malloc0(BT_RFCOMM_BUFFER_MAX + 1);
257 if (g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_MAX,
258 &len, NULL) == G_IO_STATUS_ERROR) {
259 BT_ERR("IO Channel read error client");
261 __bt_rfcomm_terminate_client(client_info->fd);
266 BT_ERR("Read failed len=%d, fd=%d\n", len, client_info->fd);
268 __bt_rfcomm_terminate_client(client_info->fd);
272 BT_DBG("%s - clientfd = %d", buffer, client_info->fd);
274 _bt_send_event(BT_RFCOMM_CLIENT_EVENT,
275 BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED,
276 DBUS_TYPE_INT32, &result,
277 DBUS_TYPE_INT16, &client_info->fd,
278 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
287 static void __bt_rfcomm_connected_cb(DBusGProxy *proxy, DBusGProxyCall *call,
292 gchar *rfcomm_device_node;
294 int result = BLUETOOTH_ERROR_NONE;
295 bt_rfcomm_info_t *client_info = NULL;
296 request_info_t *req_info;
297 bluetooth_rfcomm_connection_t conn_info;
301 dbus_g_proxy_end_call(proxy, call, &err,
302 G_TYPE_STRING, &rfcomm_device_node, G_TYPE_INVALID);
304 g_object_unref(proxy);
306 if (rfcomm_info == NULL) {
307 BT_ERR("rfcomm_info == NULL");
312 BT_ERR("Error occurred in connecting port [%s]", err->message);
314 if (!strcmp("Host is down", err->message))
315 result = BLUETOOTH_ERROR_HOST_DOWN;
317 result = BLUETOOTH_ERROR_CONNECTION_ERROR;
322 BT_DBG("Success Connect REMOTE Device RFCOMM Node[%s]", rfcomm_device_node);
324 socket_fd = __bt_rfcomm_open_socket(rfcomm_device_node);
327 BT_ERR("Fail to open socket: %d", socket_fd);
331 client_info = g_malloc0(sizeof(bt_rfcomm_info_t));
333 client_info->fd = socket_fd;
334 client_info->dev_node = g_strdup(rfcomm_device_node);
335 client_info->address = g_strdup(rfcomm_info->address);
336 client_info->uuid = g_strdup(rfcomm_info->uuid);
337 client_info->io_channel = g_io_channel_unix_new(socket_fd);
338 client_info->io_event = g_io_add_watch(client_info->io_channel,
339 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
340 __bt_rfcomm_client_data_received_cb,
343 g_io_channel_set_close_on_unref(client_info->io_channel, TRUE);
344 g_io_channel_set_flags(client_info->io_channel,
345 G_IO_FLAG_NONBLOCK, NULL);
347 client_list = g_slist_append(client_list, client_info);
349 _bt_send_event(BT_RFCOMM_CLIENT_EVENT,
350 BLUETOOTH_EVENT_RFCOMM_CONNECTED,
351 DBUS_TYPE_INT32, &result,
352 DBUS_TYPE_STRING, &rfcomm_info->address,
353 DBUS_TYPE_STRING, &rfcomm_info->uuid,
354 DBUS_TYPE_INT16, &socket_fd,
358 req_info = _bt_get_request_info(rfcomm_info->req_id);
360 if (req_info == NULL || req_info->context == NULL)
363 memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t));
364 conn_info.device_role = RFCOMM_ROLE_CLIENT;
365 g_strlcpy(conn_info.uuid, rfcomm_info->uuid,
366 BLUETOOTH_UUID_STRING_MAX);
369 conn_info.socket_fd = client_info->fd;
371 conn_info.socket_fd = -1;
373 _bt_convert_addr_string_to_type(conn_info.device_addr.addr,
374 rfcomm_info->address);
376 out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
377 out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
379 g_array_append_vals(out_param1, &conn_info,
380 sizeof(bluetooth_rfcomm_connection_t));
381 g_array_append_vals(out_param2, &result, sizeof(int));
382 dbus_g_method_return(req_info->context, out_param1, out_param2);
384 g_array_free(out_param1, TRUE);
385 g_array_free(out_param2, TRUE);
386 _bt_delete_request_list(req_info->req_id);
391 ret_if(rfcomm_info == NULL);
393 g_free(rfcomm_info->address);
394 g_free(rfcomm_info->uuid);
395 g_free(rfcomm_info->channel);
400 static void __bt_rfcomm_discover_services_cb(DBusGProxy *proxy, DBusGProxyCall *call,
404 GHashTable *hash = NULL;
405 const char *dev_path = NULL;
406 DBusGConnection *conn;
407 DBusGProxy *rfcomm_proxy;
408 int result = BLUETOOTH_ERROR_NONE;
411 request_info_t *req_info;
412 bluetooth_rfcomm_connection_t conn_info;
414 dbus_g_proxy_end_call(proxy, call, &err,
415 dbus_g_type_get_map("GHashTable",
416 G_TYPE_UINT, G_TYPE_STRING),
417 &hash, G_TYPE_INVALID);
420 BT_ERR("Error occured in Proxy call [%s]\n", err->message);
421 result = BLUETOOTH_ERROR_CONNECTION_ERROR;
426 g_hash_table_destroy(hash);
428 if (rfcomm_info == NULL) {
429 result = BLUETOOTH_ERROR_INTERNAL;
433 conn = _bt_get_system_gconn();
435 BT_ERR("ERROR: Can't get on system bus");
436 result = BLUETOOTH_ERROR_INTERNAL;
440 dev_path = dbus_g_proxy_get_path(proxy);
442 rfcomm_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
444 BT_SERIAL_INTERFACE);
446 g_object_unref(proxy);
449 if (rfcomm_proxy == NULL) {
450 BT_ERR("Failed to get the rfcomm proxy\n");
451 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
455 rfcomm_info->rfcomm_proxy = rfcomm_proxy;
457 if (!dbus_g_proxy_begin_call(rfcomm_proxy, "Connect",
458 (DBusGProxyCallNotify)__bt_rfcomm_connected_cb,
461 G_TYPE_STRING, rfcomm_info->uuid,
463 BT_ERR("RFCOMM connect Dbus Call Error");
464 g_object_unref(rfcomm_proxy);
465 result = BLUETOOTH_ERROR_INTERNAL;
474 g_object_unref(proxy);
476 ret_if(rfcomm_info == NULL);
478 req_info = _bt_get_request_info(rfcomm_info->req_id);
480 if (req_info && req_info->context) {
481 memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t));
483 conn_info.device_role = RFCOMM_ROLE_CLIENT;
484 g_strlcpy(conn_info.uuid, rfcomm_info->uuid,
485 BLUETOOTH_UUID_STRING_MAX);
487 conn_info.socket_fd = -1;
488 _bt_convert_addr_string_to_type(conn_info.device_addr.addr,
489 rfcomm_info->address);
491 out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
492 out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
494 g_array_append_vals(out_param1, &conn_info,
495 sizeof(bluetooth_rfcomm_connection_t));
496 g_array_append_vals(out_param2, &result, sizeof(int));
498 dbus_g_method_return(req_info->context, out_param1, out_param2);
500 g_array_free(out_param1, TRUE);
501 g_array_free(out_param2, TRUE);
502 _bt_delete_request_list(req_info->req_id);
505 g_free(rfcomm_info->address);
506 g_free(rfcomm_info->uuid);
511 int _bt_rfcomm_connect_using_uuid(int request_id,
512 bluetooth_device_address_t *device_address,
515 DBusGConnection *conn;
516 DBusGProxy *adapter_proxy;
517 DBusGProxy *device_proxy;
518 gchar *device_path = NULL;
519 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
521 BT_CHECK_PARAMETER(address, return);
522 BT_CHECK_PARAMETER(remote_uuid, return);
523 retv_if(rfcomm_info != NULL, BLUETOOTH_ERROR_DEVICE_BUSY);
525 adapter_proxy = _bt_get_adapter_proxy();
526 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
528 conn = _bt_get_system_gconn();
529 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
531 _bt_convert_addr_type_to_string(address, device_address->addr);
533 dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL,
534 G_TYPE_STRING, address, G_TYPE_INVALID,
535 DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID);
537 retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED);
539 device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
540 device_path, BT_DEVICE_INTERFACE);
542 retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
544 rfcomm_info = g_malloc0(sizeof(rfcomm_function_data_t));
545 rfcomm_info->address = g_strdup(address);
546 rfcomm_info->uuid = g_strdup(remote_uuid);
547 rfcomm_info->req_id = request_id;
549 if (!dbus_g_proxy_begin_call(device_proxy, "DiscoverServices",
550 (DBusGProxyCallNotify)__bt_rfcomm_discover_services_cb,
552 G_TYPE_STRING, rfcomm_info->uuid,
554 BT_ERR("Could not call dbus proxy\n");
555 g_object_unref(device_proxy);
556 g_free(rfcomm_info->address);
557 g_free(rfcomm_info->uuid);
560 return BLUETOOTH_ERROR_INTERNAL;
563 return BLUETOOTH_ERROR_NONE;
566 /* Range of the Channel : 0 <= channel <= 30 */
567 int _bt_rfcomm_connect_using_channel(int request_id,
568 bluetooth_device_address_t *device_address,
571 DBusGConnection *conn;
572 DBusGProxy *adapter_proxy;
573 DBusGProxy *device_proxy;
574 gchar *device_path = NULL;
575 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
577 BT_CHECK_PARAMETER(address, return);
578 retv_if(rfcomm_info != NULL, BLUETOOTH_ERROR_DEVICE_BUSY);
580 adapter_proxy = _bt_get_adapter_proxy();
581 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
583 conn = _bt_get_system_gconn();
584 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
586 _bt_convert_addr_type_to_string(address, device_address->addr);
588 dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL,
589 G_TYPE_STRING, address, G_TYPE_INVALID,
590 DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID);
592 retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED);
594 device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
596 BT_SERIAL_INTERFACE);
598 retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
600 rfcomm_info = g_malloc0(sizeof(rfcomm_function_data_t));
601 rfcomm_info->address = g_strdup(address);
602 rfcomm_info->channel = g_strdup(channel);
603 rfcomm_info->req_id = request_id;
604 rfcomm_info->rfcomm_proxy = device_proxy;
606 if (!dbus_g_proxy_begin_call(device_proxy, "Connect",
607 (DBusGProxyCallNotify)__bt_rfcomm_connected_cb,
610 G_TYPE_STRING, channel,
612 BT_ERR("RFCOMM connect Dbus Call Error");
613 g_object_unref(device_proxy);
614 return BLUETOOTH_ERROR_INTERNAL;
619 return BLUETOOTH_ERROR_NONE;
622 /* Be used in RFCOMM client /server */
623 int _bt_rfcomm_disconnect(int socket_fd)
625 bt_rfcomm_info_t *socket_info;
627 socket_info = __bt_rfcomm_get_client_info(socket_fd);
628 if (socket_info == NULL)
629 return _bt_rfcomm_server_disconnect(socket_fd);
631 return __bt_rfcomm_terminate_client(socket_fd);
634 /* Be used in RFCOMM client /server */
635 int _bt_rfcomm_write(int socket_fd, char *buf, int length)
642 retv_if(buf == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
644 /* Check the utf8 validation & Fill the NULL in the invalid location*/
645 if (!g_utf8_validate(buf, -1, (const char **)&ptr))
648 /* After calling g_utf8_validate, it is possible to be NULL */
649 retv_if(buf == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
651 new_length = strlen(buf);
652 if (new_length < length) {
656 /*some times user may send huge data */
657 while (wbytes < length) {
658 written = write(socket_fd, buf + wbytes,
661 BT_ERR("write failed..\n");
662 return BLUETOOTH_ERROR_NOT_IN_OPERATION;
665 /* Synchronize the sending buffer */
672 return BLUETOOTH_ERROR_NONE;
675 int _bt_rfcomm_cancel_connect(void)
677 GError *error = NULL;
682 retv_if(rfcomm_info == NULL, BLUETOOTH_ERROR_NOT_IN_OPERATION);
683 retv_if(rfcomm_info->rfcomm_proxy == NULL,
684 BLUETOOTH_ERROR_INTERNAL);
686 if (rfcomm_info->uuid)
687 input_param = rfcomm_info->uuid;
689 input_param = rfcomm_info->channel;
691 retv_if(input_param == NULL, BLUETOOTH_ERROR_INTERNAL);
693 if (!dbus_g_proxy_call(rfcomm_info->rfcomm_proxy,
696 G_TYPE_STRING, input_param,
697 G_TYPE_INVALID, G_TYPE_INVALID)) {
699 BT_ERR("Disconnect Dbus Call Error, %s", error->message);
702 return BLUETOOTH_ERROR_INTERNAL;
705 /* Send the connected event after return the function */
706 g_idle_add((GSourceFunc) __bt_rfcomm_cancel_connect_cb, NULL);
710 return BLUETOOTH_ERROR_NONE;
713 int _bt_rfcomm_is_connected(gboolean *connected)
715 BT_CHECK_PARAMETER(connected, return);
717 *connected = (client_list == NULL || g_slist_length(client_list) == 0) ?
720 return BLUETOOTH_ERROR_NONE;
723 int _bt_rfcomm_is_device_connected(bluetooth_device_address_t *device_address,
727 bt_rfcomm_info_t *client_info;
728 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
730 BT_CHECK_PARAMETER(device_address, return);
731 BT_CHECK_PARAMETER(connected, return);
733 _bt_convert_addr_type_to_string(address, device_address->addr);
737 for (l = client_list; l != NULL; l = l->next) {
738 client_info = l->data;
740 if (client_info == NULL)
743 if (g_strcmp0(address, client_info->address) == 0) {
745 return BLUETOOTH_ERROR_NONE;
749 return BLUETOOTH_ERROR_NONE;
752 int _bt_rfcomm_client_disconnect_all(void)
755 bt_rfcomm_info_t *client_info;
757 for (l = client_list; l != NULL; l = l->next) {
758 client_info = l->data;
760 if (client_info == NULL)
763 _bt_rfcomm_disconnect(client_info->fd);
766 return BLUETOOTH_ERROR_NONE;