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>
27 #include "bluetooth-api.h"
28 #include "bt-internal-types.h"
30 #include "bt-service-common.h"
31 #include "bt-service-event.h"
32 #include "bt-service-util.h"
33 #include "bt-service-rfcomm-client.h"
34 #include "bt-service-rfcomm-server.h"
41 DBusGProxy *rfcomm_proxy;
42 } rfcomm_function_data_t;
44 rfcomm_function_data_t *rfcomm_info;
47 static bt_rfcomm_info_t *__bt_rfcomm_get_client_info(int socket_fd)
50 bt_rfcomm_info_t *client_info;
52 for (l = client_list; l != NULL; l = l->next) {
53 client_info = l->data;
55 if (client_info == NULL)
58 if (socket_fd == client_info->fd)
65 static int __bt_rfcomm_open_socket(char *dev_node)
69 socket_fd = open(dev_node, O_RDWR | O_NOCTTY);
72 BT_ERR("\nCan't open TTY : %s(%d)");
76 BT_DBG("/dev/rfcomm fd = %d", socket_fd);
78 if (_bt_set_non_blocking_tty(socket_fd) < 0) {
79 /* Even if setting the tty fails we will continue */
80 BT_ERR("Unable to set /dev/rfcomm fd = %d", socket_fd);
86 static int __bt_rfcomm_disconnect_request(int socket_fd)
88 DBusGConnection *conn;
89 DBusGProxy *adapter_proxy;
90 DBusGProxy *rfcomm_proxy;
92 bt_rfcomm_info_t *client_info;
93 gchar *device_path = NULL;
94 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
96 retv_if(address == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
98 adapter_proxy = _bt_get_adapter_proxy();
99 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
101 conn = _bt_get_system_gconn();
102 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
104 client_info = __bt_rfcomm_get_client_info(socket_fd);
105 retv_if(client_info == NULL, BLUETOOTH_ERROR_INTERNAL);
107 dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL,
108 G_TYPE_STRING, client_info->address, G_TYPE_INVALID,
109 DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID);
111 retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED);
113 rfcomm_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
114 device_path, BT_SERIAL_INTERFACE);
116 BT_DBG("device path: %s", device_path);
119 retv_if(rfcomm_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
121 BT_DBG("device node: %s", client_info->dev_node);
122 if (!dbus_g_proxy_call(rfcomm_proxy, "Disconnect",
124 G_TYPE_STRING, client_info->dev_node,
125 G_TYPE_INVALID, G_TYPE_INVALID)) {
127 BT_ERR("Disconnect Call Error, %s", error->message);
130 g_object_unref(rfcomm_proxy);
131 return BLUETOOTH_ERROR_INTERNAL;
133 g_object_unref(rfcomm_proxy);
135 return BLUETOOTH_ERROR_NONE;
138 static int __bt_rfcomm_disconnect_cb(void *data)
140 int result = BLUETOOTH_ERROR_NONE;
141 bt_rfcomm_info_t *client_info = data;
143 retv_if(client_info == NULL, BLUETOOTH_ERROR_INTERNAL);
145 _bt_send_event(BT_RFCOMM_CLIENT_EVENT,
146 BLUETOOTH_EVENT_RFCOMM_DISCONNECTED,
147 DBUS_TYPE_INT32, &result,
148 DBUS_TYPE_STRING, &client_info->address,
149 DBUS_TYPE_STRING, &client_info->uuid,
150 DBUS_TYPE_INT16, &client_info->fd,
153 client_list = g_slist_remove(client_list, client_info);
155 g_source_remove(client_info->io_event);
156 close(client_info->fd);
157 g_free(client_info->dev_node);
158 g_free(client_info->address);
159 g_free(client_info->uuid);
162 return BLUETOOTH_ERROR_NONE;
165 static int __bt_rfcomm_cancel_connect_cb(void *data)
167 int result = BLUETOOTH_ERROR_CANCEL_BY_USER;
168 bluetooth_rfcomm_connection_t conn_info;
169 request_info_t *req_info;
173 retv_if(rfcomm_info == NULL, BLUETOOTH_ERROR_INTERNAL);
175 req_info = _bt_get_request_info(rfcomm_info->req_id);
177 retv_if(req_info == NULL, BLUETOOTH_ERROR_INTERNAL);
178 retv_if(req_info->context == NULL, BLUETOOTH_ERROR_INTERNAL);
180 memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t));
181 conn_info.device_role = RFCOMM_ROLE_CLIENT;
182 g_strlcpy(conn_info.uuid, rfcomm_info->uuid,
183 BLUETOOTH_UUID_STRING_MAX);
184 conn_info.socket_fd = -1;
185 _bt_convert_addr_string_to_type(conn_info.device_addr.addr,
186 rfcomm_info->address);
188 out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
189 out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
191 g_array_append_vals(out_param1, &conn_info,
192 sizeof(bluetooth_rfcomm_connection_t));
193 g_array_append_vals(out_param2, &result, sizeof(int));
195 dbus_g_method_return(req_info->context, out_param1, out_param2);
197 g_array_free(out_param1, TRUE);
198 g_array_free(out_param2, TRUE);
200 _bt_delete_request_list(req_info->req_id);
202 g_object_unref(rfcomm_info->rfcomm_proxy);
203 g_free(rfcomm_info->address);
204 g_free(rfcomm_info->uuid);
205 g_free(rfcomm_info->channel);
209 return BLUETOOTH_ERROR_NONE;
212 static int __bt_rfcomm_terminate_client(int socket_fd)
217 bt_rfcomm_info_t *client_info;
219 client_info = __bt_rfcomm_get_client_info(socket_fd);
220 retv_if(client_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
222 result = __bt_rfcomm_disconnect_request(socket_fd);
224 if (result != BLUETOOTH_ERROR_NONE) {
225 BT_ERR("Fail to disconnect socket");
229 /* Send the disconnected event after return the function */
230 g_idle_add((GSourceFunc)__bt_rfcomm_disconnect_cb, client_info);
232 return BLUETOOTH_ERROR_NONE;
235 static gboolean __bt_rfcomm_client_data_received_cb(GIOChannel *chan,
241 int result = BLUETOOTH_ERROR_NONE;
242 bt_rfcomm_info_t *client_info = data;
244 BT_DBG("condition: %d", cond);
246 retv_if(client_info == NULL, FALSE);
248 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
249 BT_ERR("Unix client disconnected (fd=%d)\n", client_info->fd);
250 __bt_rfcomm_terminate_client(client_info->fd);
254 buffer = g_malloc0(BT_RFCOMM_BUFFER_MAX + 1);
256 if (g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_MAX,
257 &len, NULL) == G_IO_STATUS_ERROR) {
258 BT_ERR("IO Channel read error client");
260 __bt_rfcomm_terminate_client(client_info->fd);
265 BT_ERR("Read failed len=%d, fd=%d\n", len, client_info->fd);
267 __bt_rfcomm_terminate_client(client_info->fd);
271 BT_DBG("%s - clientfd = %d", buffer, client_info->fd);
273 _bt_send_event(BT_RFCOMM_CLIENT_EVENT,
274 BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED,
275 DBUS_TYPE_INT32, &result,
276 DBUS_TYPE_INT16, &client_info->fd,
277 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
286 static void __bt_rfcomm_connected_cb(DBusGProxy *proxy, DBusGProxyCall *call,
291 gchar *rfcomm_device_node;
293 int result = BLUETOOTH_ERROR_NONE;
294 bt_rfcomm_info_t *client_info = NULL;
295 request_info_t *req_info;
296 bluetooth_rfcomm_connection_t conn_info;
300 dbus_g_proxy_end_call(proxy, call, &err,
301 G_TYPE_STRING, &rfcomm_device_node, G_TYPE_INVALID);
303 g_object_unref(proxy);
305 if (rfcomm_info == NULL) {
306 BT_ERR("rfcomm_info == NULL");
311 BT_ERR("Error occured in connecting port [%s]", err->message);
313 if (!strcmp("Host is down", err->message))
314 result = BLUETOOTH_ERROR_HOST_DOWN;
316 result = BLUETOOTH_ERROR_CONNECTION_ERROR;
321 BT_DBG("Succss Connect REMOTE Device RFCOMM Node[%s]", rfcomm_device_node);
323 socket_fd = __bt_rfcomm_open_socket(rfcomm_device_node);
326 BT_ERR("Fail to open socket: %d", socket_fd);
330 client_info = g_malloc0(sizeof(bt_rfcomm_info_t));
332 client_info->fd = socket_fd;
333 client_info->dev_node = g_strdup(rfcomm_device_node);
334 client_info->address = g_strdup(rfcomm_info->address);
335 client_info->uuid = g_strdup(rfcomm_info->uuid);
336 client_info->io_channel = g_io_channel_unix_new(socket_fd);
337 client_info->io_event = g_io_add_watch(client_info->io_channel,
338 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
339 __bt_rfcomm_client_data_received_cb,
342 g_io_channel_set_close_on_unref(client_info->io_channel, TRUE);
343 g_io_channel_set_flags(client_info->io_channel,
344 G_IO_FLAG_NONBLOCK, NULL);
346 client_list = g_slist_append(client_list, client_info);
348 _bt_send_event(BT_RFCOMM_CLIENT_EVENT,
349 BLUETOOTH_EVENT_RFCOMM_CONNECTED,
350 DBUS_TYPE_INT32, &result,
351 DBUS_TYPE_STRING, &rfcomm_info->address,
352 DBUS_TYPE_STRING, &rfcomm_info->uuid,
353 DBUS_TYPE_INT16, &socket_fd,
357 req_info = _bt_get_request_info(rfcomm_info->req_id);
359 if (req_info == NULL || req_info->context == NULL)
362 memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t));
363 conn_info.device_role = RFCOMM_ROLE_CLIENT;
364 g_strlcpy(conn_info.uuid, rfcomm_info->uuid,
365 BLUETOOTH_UUID_STRING_MAX);
368 conn_info.socket_fd = client_info->fd;
370 conn_info.socket_fd = -1;
372 _bt_convert_addr_string_to_type(conn_info.device_addr.addr,
373 rfcomm_info->address);
375 out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
376 out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
378 g_array_append_vals(out_param1, &conn_info,
379 sizeof(bluetooth_rfcomm_connection_t));
380 g_array_append_vals(out_param2, &result, sizeof(int));
381 dbus_g_method_return(req_info->context, out_param1, out_param2);
383 g_array_free(out_param1, TRUE);
384 g_array_free(out_param2, TRUE);
385 _bt_delete_request_list(req_info->req_id);
390 ret_if(rfcomm_info == NULL);
392 g_free(rfcomm_info->address);
393 g_free(rfcomm_info->uuid);
394 g_free(rfcomm_info->channel);
399 static void __bt_rfcomm_discover_services_cb(DBusGProxy *proxy, DBusGProxyCall *call,
403 GHashTable *hash = NULL;
404 const char *dev_path = NULL;
405 DBusGConnection *conn;
406 DBusGProxy *rfcomm_proxy;
407 int result = BLUETOOTH_ERROR_NONE;
410 request_info_t *req_info;
411 bluetooth_rfcomm_connection_t conn_info;
413 dbus_g_proxy_end_call(proxy, call, &err,
414 dbus_g_type_get_map("GHashTable",
415 G_TYPE_UINT, G_TYPE_STRING),
416 &hash, G_TYPE_INVALID);
419 BT_ERR("Error occured in Proxy call [%s]\n", err->message);
420 result = BLUETOOTH_ERROR_CONNECTION_ERROR;
425 g_hash_table_destroy(hash);
427 if (rfcomm_info == NULL) {
428 result = BLUETOOTH_ERROR_INTERNAL;
432 conn = _bt_get_system_gconn();
434 BT_ERR("ERROR: Can't get on system bus");
435 result = BLUETOOTH_ERROR_INTERNAL;
439 dev_path = dbus_g_proxy_get_path(proxy);
441 rfcomm_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
443 BT_SERIAL_INTERFACE);
445 g_object_unref(proxy);
448 if (rfcomm_proxy == NULL) {
449 BT_ERR("Failed to get the rfcomm proxy\n");
450 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
454 rfcomm_info->rfcomm_proxy = rfcomm_proxy;
456 if (!dbus_g_proxy_begin_call(rfcomm_proxy, "Connect",
457 (DBusGProxyCallNotify)__bt_rfcomm_connected_cb,
460 G_TYPE_STRING, rfcomm_info->uuid,
462 BT_ERR("RFCOMM connect Dbus Call Error");
463 g_object_unref(rfcomm_proxy);
464 result = BLUETOOTH_ERROR_INTERNAL;
473 g_object_unref(proxy);
475 ret_if(rfcomm_info == NULL);
477 req_info = _bt_get_request_info(rfcomm_info->req_id);
479 if (req_info && req_info->context) {
480 memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t));
482 conn_info.device_role = RFCOMM_ROLE_CLIENT;
483 g_strlcpy(conn_info.uuid, rfcomm_info->uuid,
484 BLUETOOTH_UUID_STRING_MAX);
486 conn_info.socket_fd = -1;
487 _bt_convert_addr_string_to_type(conn_info.device_addr.addr,
488 rfcomm_info->address);
490 out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
491 out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
493 g_array_append_vals(out_param1, &conn_info,
494 sizeof(bluetooth_rfcomm_connection_t));
495 g_array_append_vals(out_param2, &result, sizeof(int));
497 dbus_g_method_return(req_info->context, out_param1, out_param2);
499 g_array_free(out_param1, TRUE);
500 g_array_free(out_param2, TRUE);
501 _bt_delete_request_list(req_info->req_id);
504 g_free(rfcomm_info->address);
505 g_free(rfcomm_info->uuid);
510 int _bt_rfcomm_connect_using_uuid(int request_id,
511 bluetooth_device_address_t *device_address,
514 DBusGConnection *conn;
515 DBusGProxy *adapter_proxy;
516 DBusGProxy *device_proxy;
517 gchar *device_path = NULL;
518 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
520 BT_CHECK_PARAMETER(address, return);
521 BT_CHECK_PARAMETER(remote_uuid, return);
522 retv_if(rfcomm_info != NULL, BLUETOOTH_ERROR_DEVICE_BUSY);
524 adapter_proxy = _bt_get_adapter_proxy();
525 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
527 conn = _bt_get_system_gconn();
528 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
530 _bt_convert_addr_type_to_string(address, device_address->addr);
532 dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL,
533 G_TYPE_STRING, address, G_TYPE_INVALID,
534 DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID);
536 retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED);
538 device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
539 device_path, BT_DEVICE_INTERFACE);
541 retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
543 rfcomm_info = g_malloc0(sizeof(rfcomm_function_data_t));
544 rfcomm_info->address = g_strdup(address);
545 rfcomm_info->uuid = g_strdup(remote_uuid);
546 rfcomm_info->req_id = request_id;
548 if (!dbus_g_proxy_begin_call(device_proxy, "DiscoverServices",
549 (DBusGProxyCallNotify)__bt_rfcomm_discover_services_cb,
551 G_TYPE_STRING, rfcomm_info->uuid,
553 BT_ERR("Could not call dbus proxy\n");
554 g_object_unref(device_proxy);
555 g_free(rfcomm_info->address);
556 g_free(rfcomm_info->uuid);
559 return BLUETOOTH_ERROR_INTERNAL;
562 return BLUETOOTH_ERROR_NONE;
565 /* Range of the Channel : 0 <= channel <= 30 */
566 int _bt_rfcomm_connect_using_channel(int request_id,
567 bluetooth_device_address_t *device_address,
570 DBusGConnection *conn;
571 DBusGProxy *adapter_proxy;
572 DBusGProxy *device_proxy;
573 gchar *device_path = NULL;
574 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
576 BT_CHECK_PARAMETER(address, return);
577 retv_if(rfcomm_info != NULL, BLUETOOTH_ERROR_DEVICE_BUSY);
579 adapter_proxy = _bt_get_adapter_proxy();
580 retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
582 conn = _bt_get_system_gconn();
583 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
585 _bt_convert_addr_type_to_string(address, device_address->addr);
587 dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL,
588 G_TYPE_STRING, address, G_TYPE_INVALID,
589 DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID);
591 retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED);
593 device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME,
595 BT_SERIAL_INTERFACE);
597 retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
599 rfcomm_info = g_malloc0(sizeof(rfcomm_function_data_t));
600 rfcomm_info->address = g_strdup(address);
601 rfcomm_info->channel = g_strdup(channel);
602 rfcomm_info->req_id = request_id;
603 rfcomm_info->rfcomm_proxy = device_proxy;
605 if (!dbus_g_proxy_begin_call(device_proxy, "Connect",
606 (DBusGProxyCallNotify)__bt_rfcomm_connected_cb,
609 G_TYPE_STRING, channel,
611 BT_ERR("RFCOMM connect Dbus Call Error");
612 g_object_unref(device_proxy);
613 return BLUETOOTH_ERROR_INTERNAL;
618 return BLUETOOTH_ERROR_NONE;
621 /* Be used in RFCOMM client /server */
622 int _bt_rfcomm_disconnect(int socket_fd)
624 bt_rfcomm_info_t *socket_info;
626 socket_info = __bt_rfcomm_get_client_info(socket_fd);
627 if (socket_info == NULL)
628 return _bt_rfcomm_server_disconnect(socket_fd);
630 return __bt_rfcomm_terminate_client(socket_fd);
633 /* Be used in RFCOMM client /server */
634 int _bt_rfcomm_write(int socket_fd, char *buf, int length)
641 retv_if(buf == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
643 /* Check the utf8 validation & Fill the NULL in the invalid location*/
644 if (!g_utf8_validate(buf, -1, (const char **)&ptr))
647 /* After calling g_utf8_validate, it is possible to be NULL */
648 retv_if(buf == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
650 new_length = strlen(buf);
651 if (new_length < length) {
655 /*some times user may send huge data */
656 while (wbytes < length) {
657 written = write(socket_fd, buf + 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;