4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Atul Kumar Rai <a.rai@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
26 #include <sys/types.h>
27 #include <sys/socket.h>
29 #include <dbus/dbus-glib.h>
30 #include <dbus/dbus.h>
36 #include "bt-hal-rfcomm-dbus-handler.h"
37 #include "bt-hal-dbus-common-utils.h"
39 #define BT_HAL_RFCOMM_ID_MAX 245
40 #define BT_HAL_RFCOMM_MAX_BUFFER_SIZE 1024
43 char uuid[BT_HAL_UUID_STRING_LEN];
52 char remote_addr[BT_HAL_ADDRESS_STRING_SIZE];
54 unsigned int hal_watch;
56 unsigned int bt_watch;
59 static GSList *rfcomm_clients;
60 static int latest_id = -1;
61 static gboolean id_used[BT_HAL_RFCOMM_ID_MAX];
63 int __rfcomm_assign_id(void)
67 DBG("latest_id: %d", latest_id);
69 index = latest_id + 1;
70 if (index >= BT_HAL_RFCOMM_ID_MAX)
73 DBG("index: %d", index);
75 while (id_used[index] == TRUE) {
76 if (index == latest_id) {
78 ERR("All request ID is used");
83 if (index >= BT_HAL_RFCOMM_ID_MAX)
88 id_used[index] = TRUE;
89 DBG("Assigned Id: %d", latest_id);
94 void __rfcomm_delete_id(int id)
96 if (id >= BT_HAL_RFCOMM_ID_MAX || id < 0) {
97 ERR("Invalid id %d", id);
103 DBG("id: %d, latest_id: %d", id, latest_id);
106 static rfcomm_cb_data_t *__find_rfcomm_info_from_uuid(const char *uuid)
110 for (l = rfcomm_clients; l != NULL; l = l->next) {
111 rfcomm_cb_data_t *info = l->data;
113 if (g_strcmp0(info->uuid, uuid) == 0)
120 static rfcomm_cb_data_t *__find_rfcomm_info_from_path(const char *path)
124 for (l = rfcomm_clients; l != NULL; l = l->next) {
125 rfcomm_cb_data_t *info = l->data;
128 if (g_strcmp0(info->obj_path, path) == 0)
135 static void __bt_free_cb_data(rfcomm_cb_data_t *cb_data)
139 if (cb_data->id >= 0)
140 __rfcomm_delete_id(cb_data->id);
142 if (cb_data->object_id > 0)
143 _bt_unregister_gdbus_object(cb_data->object_id);
145 if (cb_data->obj_path) {
146 INFO("Unregister profile");
147 _bt_unregister_profile(cb_data->obj_path);
150 g_free(cb_data->obj_path);
152 g_free(cb_data->device_path);
158 static void __rfcomm_cb_data_remove(rfcomm_cb_data_t *info)
165 if (info->rfcomm_conns == NULL) {
166 INFO("No more device connected remove info");
167 rfcomm_clients = g_slist_remove(rfcomm_clients, info);
168 __bt_free_cb_data(info);
172 static rfcomm_conn_info_t *__find_conn_info_with_stack_fd(rfcomm_cb_data_t *info, int fd)
176 for (l = info->rfcomm_conns; l != NULL; l = l->next) {
177 rfcomm_conn_info_t *conn_info = l->data;
179 if (conn_info && (conn_info->stack_fd == fd))
186 static rfcomm_conn_info_t *__find_conn_info_with_hal_fd(rfcomm_cb_data_t *info, int fd)
189 for (l = info->rfcomm_conns; l != NULL; l = l->next) {
190 rfcomm_conn_info_t *conn_info = l->data;
192 if (conn_info && (conn_info->hal_fd == fd))
199 static gint compare(gpointer *a, gpointer *b)
201 rfcomm_conn_info_t *node = (rfcomm_conn_info_t *)a;
202 char *address = (char *)b;
203 return g_strcmp0(node->remote_addr, address);
206 static rfcomm_conn_info_t *__get_conn_info_from_address(rfcomm_cb_data_t *info,
210 rfcomm_conn_info_t *conn_info = NULL;
211 l = g_slist_find_custom(info->rfcomm_conns, dev_address,
212 (GCompareFunc)compare);
218 static void __bt_free_conn(rfcomm_conn_info_t *conn)
225 if (0 < conn->hal_fd)
228 if (conn->hal_watch > 0) {
229 g_source_remove(conn->hal_watch);
233 if (0 < conn->stack_fd)
234 close(conn->stack_fd);
236 if (conn->bt_watch > 0) {
237 g_source_remove(conn->bt_watch);
245 static void __rfcomm_remove_conn_info_t(rfcomm_cb_data_t *info, char *address)
247 rfcomm_conn_info_t *conn_info;
249 conn_info = __get_conn_info_from_address(info, address);
251 info->rfcomm_conns = g_slist_remove(info->rfcomm_conns, conn_info);
252 __bt_free_conn(conn_info);
256 static int write_all(int fd, unsigned char *buf, int len)
263 written = write(fd, buf, len);
265 if (errno == EINTR || errno == EAGAIN)
273 len -= written; buf += written; sent += written;
279 static gboolean app_event_cb(GIOChannel *io, GIOCondition cond, gpointer data)
283 rfcomm_cb_data_t *info = data;
284 rfcomm_conn_info_t *conn_info;
285 unsigned char buff[BT_HAL_RFCOMM_MAX_BUFFER_SIZE];
290 fd = g_io_channel_unix_get_fd(io);
291 conn_info = __find_conn_info_with_hal_fd(info, fd);
293 if (cond & G_IO_HUP) {
294 ERR("Socket %d hang up", fd);
298 if (cond & (G_IO_ERR | G_IO_NVAL)) {
299 ERR("Socket %d error", fd);
304 ERR("conn_info is NULL");
308 /* Read data from application */
309 if (g_io_channel_read_chars(io, (gchar *)buff,
310 BT_HAL_RFCOMM_MAX_BUFFER_SIZE,
311 &len, &err) == G_IO_STATUS_ERROR) {
313 ERR("IO Channel read error: %s", err->message);
315 ERR("IO Channel read error client");
321 ERR("Other end of socket is closed");
325 /* Send data to remote device */
326 sent = write_all(conn_info->stack_fd, buff, len);
328 ERR("write(): %s", strerror(errno));
335 __rfcomm_remove_conn_info_t(info, conn_info->remote_addr);
336 __rfcomm_cb_data_remove(info);
340 static gboolean stack_event_cb(GIOChannel *io, GIOCondition cond, gpointer data)
344 rfcomm_cb_data_t *info = data;
345 rfcomm_conn_info_t *conn_info;
346 unsigned char buff[BT_HAL_RFCOMM_MAX_BUFFER_SIZE];
352 fd = g_io_channel_unix_get_fd(io);
353 conn_info = __find_conn_info_with_stack_fd(info, fd);
355 if (cond & G_IO_HUP) {
356 ERR("Socket %d hang up", fd);
360 if (cond & (G_IO_ERR | G_IO_NVAL)) {
361 ERR("Socket %d error", fd);
366 ERR("conn_info is NULL");
370 /* Read data from remote device */
371 if (g_io_channel_read_chars(io, (gchar *)buff,
372 BT_HAL_RFCOMM_MAX_BUFFER_SIZE,
373 &len, &err) == G_IO_STATUS_ERROR) {
375 ERR("IO Channel read error: %s", err->message);
377 ERR("IO Channel read error client");
383 ERR("Other end of socket is closed");
387 /* Send data to application */
388 sent = write_all(conn_info->hal_fd, buff, len);
390 ERR("write(): %s", strerror(errno));
397 __rfcomm_remove_conn_info_t(info, conn_info->remote_addr);
398 __rfcomm_cb_data_remove(info);
402 static int __new_connection(const char *path, int fd, bt_bdaddr_t *addr)
404 char address[BT_HAL_ADDRESS_STRING_SIZE];
405 rfcomm_cb_data_t *info;
406 rfcomm_conn_info_t *conn_info;
407 struct hal_ev_sock_connect ev;
412 /* TODO: Temperary, later need to fill correct channel form correct place */
415 if (NULL == path || NULL == addr) {
416 ERR("NULL == path || NULL = addr");
420 _bt_convert_addr_type_to_string(address, addr->address);
421 info = __find_rfcomm_info_from_path(path);
425 conn_info = __get_conn_info_from_address(info, address);
426 if (conn_info == NULL) {
427 ERR("Device Address %s not found in connection list", address);
431 if (write(conn_info->hal_fd, &chan, sizeof(chan)) != sizeof(chan)) {
432 ERR("Error sending RFCOMM channel");
436 conn_info->stack_fd = fd;
437 DBG("Remote address: %s, RFCOMM fd: %d", address, conn_info->stack_fd);
439 /* Send rfcomm connected event */
440 memset(&ev, 0, sizeof(ev));
441 ev.size = sizeof(ev);
442 memcpy(ev.bdaddr, addr->address, 6);
443 ev.status = BT_STATUS_SUCCESS;
444 len = write_all(conn_info->hal_fd, (unsigned char *)&ev, sizeof(ev));
446 ERR("%s", strerror(errno));
450 if (len != sizeof(ev)) {
451 ERR("Error sending connect event");
455 /* Handle events from App */
456 cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
457 io = g_io_channel_unix_new(conn_info->hal_fd);
458 conn_info->hal_watch = g_io_add_watch(io, cond, app_event_cb, info);
459 g_io_channel_unref(io);
461 /* Handle rfcomm events from bluez */
462 cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
463 io = g_io_channel_unix_new(conn_info->stack_fd);
464 conn_info->bt_watch = g_io_add_watch(io, cond, stack_event_cb, info);
465 g_io_channel_unref(io);
469 __rfcomm_remove_conn_info_t(info, address);
470 __rfcomm_cb_data_remove(info);
474 static void __bt_connect_response_cb(GDBusProxy *proxy,
475 GAsyncResult *res, gpointer user_data)
477 GError *error = NULL;
478 rfcomm_cb_data_t *cb_data;
479 char dev_address[BT_HAL_ADDRESS_STRING_SIZE];
485 if (cb_data == NULL) {
486 ERR("cb_data == NULL");
490 if (!g_dbus_proxy_call_finish(proxy, res, &error)) {
491 ERR("Error : %s \n", error->message);
492 path = g_dbus_proxy_get_object_path(proxy);
493 _bt_convert_device_path_to_address(path, dev_address);
494 __rfcomm_remove_conn_info_t(cb_data, dev_address);
495 __rfcomm_cb_data_remove(cb_data);
500 g_object_unref(proxy);
505 static void __bt_discover_service_response_cb(GDBusProxy *proxy,
506 GAsyncResult *res, gpointer user_data)
508 rfcomm_cb_data_t *cb_data;
511 bt_hal_register_profile_info_t info = {0};
512 char dev_address[BT_HAL_ADDRESS_STRING_SIZE];
519 ERR("cb_data == NULL");
523 path = g_dbus_proxy_get_object_path(proxy);
524 _bt_convert_device_path_to_address(path, dev_address);
525 DBG("Device Adress [%s]", dev_address);
527 g_dbus_proxy_call_finish(proxy, res, &err);
529 g_object_unref(proxy);
531 ERR("Error occured in Proxy call [%s]\n", err->message);
532 __rfcomm_remove_conn_info_t(cb_data, dev_address);
533 __rfcomm_cb_data_remove(cb_data);
536 INFO("Services are Updated checking required uuid is there");
537 /* Check here for uuid present */
538 ret = _bt_discover_service_uuids(dev_address, cb_data->uuid);
539 if (ret == BT_STATUS_SUCCESS) {
540 info.uuid = (char *)cb_data->uuid;
541 info.obj_path = cb_data->obj_path;
542 info.role = "client";
544 ret = _bt_register_profile(&info, FALSE);
546 DBG("Error: register profile");
547 ret = _bt_connect_profile(dev_address, cb_data->uuid,
548 __bt_connect_response_cb, cb_data);
549 if (ret != BT_STATUS_SUCCESS) {
550 ERR("ConnectProfile failed");
551 __rfcomm_remove_conn_info_t(cb_data, dev_address);
552 __rfcomm_cb_data_remove(cb_data);
556 ERR("remote uuid not found");
557 __rfcomm_remove_conn_info_t(cb_data, dev_address);
558 __rfcomm_cb_data_remove(cb_data);
566 static rfcomm_cb_data_t *__get_rfcomm_cb_data(char *remote_uuid)
571 rfcomm_cb_data_t *cb_data;
575 cb_data = __find_rfcomm_info_from_uuid(remote_uuid);
577 id = __rfcomm_assign_id();
579 ERR("__rfcomm_assign_id failed");
583 path = g_strdup_printf("/org/socket/client/%d/%d", getpid(), id);
584 object_id = _bt_register_new_gdbus_object(path, __new_connection);
586 ERR("_bt_register_new_gdbus_object failed");
587 __rfcomm_delete_id(id);
591 cb_data = g_malloc0(sizeof(rfcomm_cb_data_t));
592 g_strlcpy(cb_data->uuid, remote_uuid, BT_HAL_UUID_STRING_LEN);
593 cb_data->obj_path = path;
594 cb_data->object_id = object_id;
602 static rfcomm_conn_info_t *__rfcomm_create_conn_info(char *addr, int *sock)
604 int fds[2] = {-1, -1};
605 rfcomm_conn_info_t *conn;
607 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
608 ERR("socketpair(): %s", strerror(errno));
613 conn = g_malloc0(sizeof(rfcomm_conn_info_t));
614 g_strlcpy(conn->remote_addr, addr, BT_HAL_ADDRESS_STRING_SIZE);
615 conn->hal_fd = fds[0];
619 DBG("hal_fd: %d, sock: %d", conn->hal_fd, *sock);
624 int _bt_hal_dbus_handler_rfcomm_connect(unsigned char *addr, unsigned char *uuid, int *sock)
627 rfcomm_cb_data_t *cb_data;
628 rfcomm_conn_info_t *conn;
629 char remote_addr[BT_HAL_ADDRESS_STRING_SIZE];
630 char remote_uuid[BT_HAL_UUID_SIZE];
633 ERR("remote_addr is NULL");
634 return BT_STATUS_PARM_INVALID;
638 ERR("remote_uuid is NULL");
639 return BT_STATUS_PARM_INVALID;
644 return BT_STATUS_PARM_INVALID;
647 _bt_convert_uuid_type_to_string(remote_uuid, uuid);
648 cb_data = __get_rfcomm_cb_data(remote_uuid);
650 return BT_STATUS_FAIL;
652 _bt_convert_addr_type_to_string(remote_addr, addr);
653 DBG("Connecting to %s, uuid %s", remote_addr, remote_uuid);
654 conn = __rfcomm_create_conn_info(remote_addr, sock);
656 return BT_STATUS_FAIL;
658 cb_data->rfcomm_conns = g_slist_append(cb_data->rfcomm_conns, conn);
659 ret = _bt_discover_services(remote_addr, (char *)remote_uuid,
660 __bt_discover_service_response_cb, cb_data);
661 if (ret != BT_STATUS_SUCCESS) {
662 ERR("Error returned while service discovery");
663 __rfcomm_remove_conn_info_t(cb_data, conn->remote_addr);
664 __rfcomm_cb_data_remove(cb_data);
665 return BT_STATUS_FAIL;
668 if (g_slist_find(rfcomm_clients, cb_data) == NULL) {
669 INFO("Adding callback information to rfcomm_clients");
670 rfcomm_clients = g_slist_append(rfcomm_clients, cb_data);
672 INFO("Callback information is already added");
674 return BT_STATUS_SUCCESS;