8d94ec203191a05bbc100a2de87619d36cc986ef
[platform/core/connectivity/bluetooth-frwk.git] / bt-oal / bluez_hal / src / bt-hal-rfcomm-dbus-handler.c
1 /*
2  * Bluetooth-frwk
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Atul Kumar Rai <a.rai@samsung.com>
7  *
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
11  *
12  *              http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stdbool.h>
25 #include <string.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
28
29 #include <dbus/dbus-glib.h>
30 #include <dbus/dbus.h>
31 #include <glib.h>
32 #include <gio/gio.h>
33 #include <dlog.h>
34 #include <vconf.h>
35
36 #include "bt-hal-rfcomm-dbus-handler.h"
37 #include "bt-hal-dbus-common-utils.h"
38
39 #define BT_HAL_RFCOMM_ID_MAX 245
40 #define BT_HAL_RFCOMM_MAX_BUFFER_SIZE 1024
41
42 typedef struct {
43         char remote_addr[BT_HAL_ADDRESS_STRING_SIZE];
44         int hal_fd;
45         unsigned int hal_watch;
46         int stack_fd;
47         unsigned int bt_watch;
48 } rfcomm_conn_info_t;
49
50 typedef struct {
51         char uuid[BT_HAL_UUID_STRING_LEN];
52         char *device_path;
53         char *obj_path;
54         int object_id;
55         int id;
56         rfcomm_conn_info_t *conn_info;
57 } rfcomm_cb_data_t;
58
59 static GSList *rfcomm_clients;
60 static int latest_id = -1;
61 static gboolean id_used[BT_HAL_RFCOMM_ID_MAX];
62
63 int __rfcomm_assign_id(void)
64 {
65         int index;
66
67         DBG("latest_id: %d", latest_id);
68
69         index = latest_id + 1;
70         if (index >= BT_HAL_RFCOMM_ID_MAX)
71                 index = 0;
72
73         DBG("index: %d", index);
74
75         while (id_used[index] == TRUE) {
76                 if (index == latest_id) {
77                         /* No available ID */
78                         ERR("All request ID is used");
79                         return -1;
80                 }
81
82                 index++;
83                 if (index >= BT_HAL_RFCOMM_ID_MAX)
84                         index = 0;
85         }
86
87         latest_id = index;
88         id_used[index] = TRUE;
89         DBG("Assigned Id: %d", latest_id);
90
91         return latest_id;
92 }
93
94 void __rfcomm_delete_id(int id)
95 {
96         if (id >= BT_HAL_RFCOMM_ID_MAX || id < 0) {
97                 ERR("Invalid id %d", id);
98                 return;
99         }
100
101         id_used[id] = FALSE;
102         latest_id = id - 1;
103         DBG("id: %d, latest_id: %d", id, latest_id);
104 }
105
106 static rfcomm_cb_data_t *__find_rfcomm_info_from_path(const char *path)
107 {
108         GSList *l;
109
110         for (l = rfcomm_clients; l != NULL; l = l->next) {
111                 rfcomm_cb_data_t *info = l->data;
112
113                 if (info != NULL)
114                         if (g_strcmp0(info->obj_path, path) == 0)
115                                 return info;
116         }
117
118         return NULL;
119 }
120
121 static void __bt_free_conn(rfcomm_conn_info_t *conn)
122 {
123         DBG("+");
124
125         if (conn == NULL)
126                 return;
127
128         if (0 < conn->hal_fd)
129                 close(conn->hal_fd);
130
131         if (conn->hal_watch > 0) {
132                 g_source_remove(conn->hal_watch);
133                 conn->hal_watch = 0;
134         }
135
136         if (0 < conn->stack_fd)
137                 close(conn->stack_fd);
138
139         if (conn->bt_watch > 0) {
140                 g_source_remove(conn->bt_watch);
141                 conn->bt_watch = 0;
142         }
143
144         g_free(conn);
145         DBG("-");
146 }
147
148 static void __bt_free_cb_data(rfcomm_cb_data_t *cb_data)
149 {
150         DBG("+");
151
152         if (cb_data->id >= 0)
153                 __rfcomm_delete_id(cb_data->id);
154
155         if (cb_data->object_id > 0)
156                 _bt_unregister_gdbus_object(cb_data->object_id);
157
158         if (cb_data->obj_path) {
159                 INFO("Unregister profile");
160                 _bt_unregister_profile(cb_data->obj_path);
161         }
162
163         g_free(cb_data->obj_path);
164
165         g_free(cb_data->device_path);
166         g_free(cb_data);
167
168         DBG("-");
169 }
170
171 static void __rfcomm_cb_data_remove(rfcomm_cb_data_t *info)
172 {
173         if (!info) {
174                 ERR("info == NULL");
175                 return;
176         }
177
178         rfcomm_clients = g_slist_remove(rfcomm_clients, info);
179         __bt_free_conn(info->conn_info);
180         __bt_free_cb_data(info);
181 }
182
183 static int write_all(int fd, unsigned char *buf, int len)
184 {
185         int sent = 0;
186
187         while (len > 0) {
188                 int written;
189
190                 written = write(fd, buf, len);
191                 if (written < 0) {
192                         if (errno == EINTR || errno == EAGAIN)
193                                 continue;
194                         return -1;
195                 }
196
197                 if (!written)
198                         return 0;
199
200                 len -= written; buf += written; sent += written;
201         }
202
203         return sent;
204 }
205
206 static gboolean app_event_cb(GIOChannel *io, GIOCondition cond, gpointer data)
207 {
208         gsize len;
209         unsigned int sent;
210         rfcomm_cb_data_t *info = data;
211         rfcomm_conn_info_t *conn_info;
212         unsigned char buff[BT_HAL_RFCOMM_MAX_BUFFER_SIZE];
213         GError *err = NULL;
214         int fd;
215
216         DBG("+");
217         fd = g_io_channel_unix_get_fd(io);
218         conn_info = info->conn_info;
219
220         if (cond & G_IO_HUP) {
221                 ERR("Socket %d hang up", fd);
222                 goto fail;
223         }
224
225         if (cond & (G_IO_ERR | G_IO_NVAL)) {
226                 ERR("Socket %d error", fd);
227                 goto fail;
228         }
229
230         if (!conn_info) {
231                 ERR("conn_info is NULL");
232                 return TRUE;
233         }
234
235         /* Read data from application */
236         if (g_io_channel_read_chars(io, (gchar *)buff,
237                         BT_HAL_RFCOMM_MAX_BUFFER_SIZE,
238                         &len, &err) == G_IO_STATUS_ERROR) {
239                 if( err )
240                         ERR("IO Channel read error: %s", err->message);
241                 else
242                         ERR("IO Channel read error client");
243                 goto fail;
244         }
245
246         DBG("len: %d", len);
247         if (0 == len) {
248                 ERR("Other end of socket is closed");
249                 goto fail;
250         }
251
252         /* Send data to remote device */
253         sent = write_all(conn_info->stack_fd, buff, len);
254         if (sent < 0) {
255                 ERR("write(): %s", strerror(errno));
256                 goto fail;
257         }
258
259         DBG("-");
260         return TRUE;
261 fail:
262         __rfcomm_cb_data_remove(info);
263         return FALSE;
264 }
265
266 static gboolean stack_event_cb(GIOChannel *io, GIOCondition cond, gpointer data)
267 {
268         unsigned int len;
269         unsigned int sent;
270         rfcomm_cb_data_t *info = data;
271         rfcomm_conn_info_t *conn_info;
272         unsigned char buff[BT_HAL_RFCOMM_MAX_BUFFER_SIZE];
273         GError *err = NULL;
274         int fd;
275
276         DBG("+");
277
278         fd = g_io_channel_unix_get_fd(io);
279         conn_info = info->conn_info;
280
281         if (cond & G_IO_HUP) {
282                 ERR("Socket %d hang up", fd);
283                 goto fail;
284         }
285
286         if (cond & (G_IO_ERR | G_IO_NVAL)) {
287                 ERR("Socket %d error", fd);
288                 goto fail;
289         }
290
291         if (!conn_info) {
292                 ERR("conn_info is NULL");
293                 return TRUE;
294         }
295
296         /* Read data from remote device */
297         if (g_io_channel_read_chars(io, (gchar *)buff,
298                         BT_HAL_RFCOMM_MAX_BUFFER_SIZE,
299                         &len, &err) == G_IO_STATUS_ERROR) {
300                 if( err )
301                         ERR("IO Channel read error: %s", err->message);
302                 else
303                         ERR("IO Channel read error client");
304                 goto fail;
305         }
306
307         DBG("len: %d", len);
308         if (0 == len) {
309                 ERR("Other end of socket is closed");
310                 goto fail;
311         }
312
313         /* Send data to application */
314         sent = write_all(conn_info->hal_fd, buff, len);
315         if (sent < 0) {
316                 ERR("write(): %s", strerror(errno));
317                 goto fail;
318         }
319
320         DBG("-");
321         return TRUE;
322 fail:
323         __rfcomm_cb_data_remove(info);
324         return FALSE;
325 }
326
327 static int __new_connection(const char *path, int fd, bt_bdaddr_t *addr)
328 {
329         char address[BT_HAL_ADDRESS_STRING_SIZE];
330         rfcomm_cb_data_t *info;
331         rfcomm_conn_info_t *conn_info;
332         struct hal_ev_sock_connect ev;
333         GIOCondition cond;
334         int len;
335         GIOChannel *io;
336
337         /* TODO: Temperary, later need to fill correct channel form correct place */
338         int chan = 0;
339
340         if (NULL == path || NULL == addr) {
341                 ERR("NULL == path || NULL = addr");
342                 return -1;
343         }
344
345         info = __find_rfcomm_info_from_path(path);
346         if (info == NULL)
347                 return -1;
348
349         conn_info = info->conn_info;
350         _bt_convert_addr_type_to_string(address, addr->address);
351         if (conn_info == NULL) {
352                 ERR("conn_info is NULL for dev:[%s]", address);
353                 return -1;
354         }
355
356         if (write(conn_info->hal_fd, &chan, sizeof(chan)) != sizeof(chan)) {
357                 ERR("Error sending RFCOMM channel");
358                 goto fail;
359         }
360
361         conn_info->stack_fd = fd;
362         DBG("Remote address: %s, RFCOMM fd: %d", address, conn_info->stack_fd);
363
364         /* Send rfcomm connected event */
365         memset(&ev, 0, sizeof(ev));
366         ev.size = sizeof(ev);
367         memcpy(ev.bdaddr, addr->address, 6);
368         ev.status = BT_STATUS_SUCCESS;
369         len = write_all(conn_info->hal_fd, (unsigned char *)&ev, sizeof(ev));
370         if (len < 0) {
371                 ERR("%s", strerror(errno));
372                 goto fail;
373         }
374
375         if (len != sizeof(ev)) {
376                 ERR("Error sending connect event");
377                 goto fail;;
378         }
379
380         /* Handle events from App */
381         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
382         io = g_io_channel_unix_new(conn_info->hal_fd);
383         conn_info->hal_watch = g_io_add_watch(io, cond, app_event_cb, info);
384         g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL);
385         g_io_channel_unref(io);
386
387         /* Handle rfcomm events from bluez */
388         cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
389         io = g_io_channel_unix_new(conn_info->stack_fd);
390         conn_info->bt_watch = g_io_add_watch(io, cond, stack_event_cb, info);
391         g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL);
392         g_io_channel_unref(io);
393
394         return 0;
395 fail:
396         __rfcomm_cb_data_remove(info);
397         return -1;
398 }
399
400 static void __bt_connect_response_cb(GDBusProxy *proxy,
401                 GAsyncResult *res, gpointer user_data)
402 {
403         GError *error = NULL;
404         rfcomm_cb_data_t *cb_data;
405
406         DBG("+");
407
408         cb_data = user_data;
409         if (cb_data == NULL) {
410                 ERR("cb_data == NULL");
411                 return;
412         }
413
414         if (!g_dbus_proxy_call_finish(proxy, res, &error)) {
415                 ERR("Error : %s \n", error->message);
416                 __rfcomm_cb_data_remove(cb_data);
417                 g_error_free(error);
418         }
419
420         if (proxy)
421                 g_object_unref(proxy);
422
423         DBG("-");
424 }
425
426 static void __bt_discover_service_response_cb(GDBusProxy *proxy,
427                 GAsyncResult *res, gpointer user_data)
428 {
429         rfcomm_cb_data_t *cb_data;
430         int ret = 0;
431         GError *err = NULL;
432         bt_hal_register_profile_info_t info = {0};
433         char dev_address[BT_HAL_ADDRESS_STRING_SIZE];
434         const char *path;
435
436         DBG("+");
437
438         cb_data = user_data;
439         if (!cb_data) {
440                 ERR("cb_data == NULL");
441                 return;
442         }
443
444         path = g_dbus_proxy_get_object_path(proxy);
445         _bt_convert_device_path_to_address(path, dev_address);
446         DBG("Device Adress [%s]", dev_address);
447
448         g_dbus_proxy_call_finish(proxy, res, &err);
449         if (proxy)
450                 g_object_unref(proxy);
451         if (err != NULL) {
452                 ERR("Error occured in Proxy call [%s]\n", err->message);
453                 __rfcomm_cb_data_remove(cb_data);
454                 goto done;
455         } else {
456                 INFO("Services are Updated checking required uuid is there");
457                 /* Check here for uuid present */
458                 ret = _bt_discover_service_uuids(dev_address, cb_data->uuid);
459                 if (ret == BT_STATUS_SUCCESS) {
460                         info.uuid = (char *)cb_data->uuid;
461                         info.obj_path = cb_data->obj_path;
462                         info.role = "client";
463
464                         ret = _bt_register_profile(&info, FALSE);
465                         if (ret < 0)
466                                 DBG("Error: register profile");
467                         ret = _bt_connect_profile(dev_address, cb_data->uuid,
468                                         __bt_connect_response_cb, cb_data);
469                         if (ret != BT_STATUS_SUCCESS) {
470                                 ERR("ConnectProfile failed");
471                                 __rfcomm_cb_data_remove(cb_data);
472                                 goto done;
473                         }
474                 } else {
475                         ERR("remote uuid not found");
476                         __rfcomm_cb_data_remove(cb_data);
477                 }
478         }
479 done:
480         if (err)
481                 g_clear_error(&err);
482 }
483
484 static rfcomm_cb_data_t *__get_rfcomm_cb_data(char *remote_uuid)
485 {
486         int id;
487         int object_id;
488         char *path;
489         rfcomm_cb_data_t *cb_data;
490
491         DBG("+");
492
493         id = __rfcomm_assign_id();
494         if (id < 0) {
495                 ERR("__rfcomm_assign_id failed");
496                 return NULL;
497         }
498
499         path = g_strdup_printf("/org/socket/client/%d/%d", getpid(), id);
500         object_id = _bt_register_new_gdbus_object(path, __new_connection);
501         if (object_id < 0) {
502                 ERR("_bt_register_new_gdbus_object failed");
503                 __rfcomm_delete_id(id);
504                 return NULL;
505         }
506
507         cb_data = g_malloc0(sizeof(rfcomm_cb_data_t));
508         g_strlcpy(cb_data->uuid, remote_uuid, BT_HAL_UUID_STRING_LEN);
509         cb_data->obj_path = path;
510         cb_data->object_id = object_id;
511         cb_data->id = id;
512
513         DBG("-");
514         return cb_data;
515 }
516
517 static rfcomm_conn_info_t *__rfcomm_create_conn_info(char *addr, int *sock)
518 {
519         int fds[2] = {-1, -1};
520         rfcomm_conn_info_t *conn;
521
522         if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
523                 ERR("socketpair(): %s", strerror(errno));
524                 *sock = -1;
525                 return NULL;
526         }
527
528         conn = g_malloc0(sizeof(rfcomm_conn_info_t));
529         g_strlcpy(conn->remote_addr, addr, BT_HAL_ADDRESS_STRING_SIZE);
530         conn->hal_fd = fds[0];
531         conn->stack_fd = -1;
532         *sock = fds[1];
533
534         DBG("hal_fd: %d, sock: %d", conn->hal_fd, *sock);
535
536         return conn;
537 }
538
539 int _bt_hal_dbus_handler_rfcomm_connect(unsigned char *addr, unsigned char *uuid, int *sock)
540 {
541         int ret;
542         rfcomm_cb_data_t *cb_data;
543         rfcomm_conn_info_t *conn;
544         char remote_addr[BT_HAL_ADDRESS_STRING_SIZE];
545         char remote_uuid[BT_HAL_UUID_SIZE];
546
547         if (!addr) {
548                 ERR("remote_addr is NULL");
549                 return BT_STATUS_PARM_INVALID;
550         }
551
552         if (!uuid) {
553                 ERR("remote_uuid is NULL");
554                 return BT_STATUS_PARM_INVALID;
555         }
556
557         if (!sock) {
558                 ERR("sock is NULL");
559                 return BT_STATUS_PARM_INVALID;
560         }
561
562         _bt_convert_uuid_type_to_string(remote_uuid, uuid);
563         cb_data = __get_rfcomm_cb_data(remote_uuid);
564         if (!cb_data)
565                 return BT_STATUS_FAIL;
566
567         _bt_convert_addr_type_to_string(remote_addr, addr);
568         DBG("Connecting to %s, uuid %s", remote_addr, remote_uuid);
569         conn = __rfcomm_create_conn_info(remote_addr, sock);
570         if (!conn) {
571                 __rfcomm_cb_data_remove(cb_data);
572                 return BT_STATUS_FAIL;
573         }
574
575         cb_data->conn_info = conn;
576         ret = _bt_discover_services(remote_addr, (char *)remote_uuid,
577                         __bt_discover_service_response_cb, cb_data);
578         if (ret != BT_STATUS_SUCCESS) {
579                 ERR("Error returned while service discovery");
580                 __bt_free_conn(conn);
581                 __bt_free_cb_data(cb_data);
582                 return BT_STATUS_FAIL;
583         }
584
585         INFO("Adding callback information to rfcomm_clients");
586         rfcomm_clients = g_slist_append(rfcomm_clients, cb_data);
587
588         return BT_STATUS_SUCCESS;
589 }