[Adapt: HAL] Implement rfcomm socket connect
[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 uuid[BT_HAL_UUID_STRING_LEN];
44         char *device_path;
45         char *obj_path;
46         int object_id;
47         int id;
48         GSList *rfcomm_conns;
49 } rfcomm_cb_data_t;
50
51 typedef struct {
52         char remote_addr[BT_HAL_ADDRESS_STRING_SIZE];
53         int hal_fd;
54         unsigned int hal_watch;
55         int stack_fd;
56         unsigned int bt_watch;
57 } rfcomm_conn_info_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_uuid(const char *uuid)
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 (g_strcmp0(info->uuid, uuid) == 0)
114                         return info;
115         }
116
117         return NULL;
118 }
119
120 static rfcomm_cb_data_t *__find_rfcomm_info_from_path(const char *path)
121 {
122         GSList *l;
123
124         for (l = rfcomm_clients; l != NULL; l = l->next) {
125                 rfcomm_cb_data_t *info = l->data;
126
127                 if (info != NULL)
128                         if (g_strcmp0(info->obj_path, path) == 0)
129                                 return info;
130         }
131
132         return NULL;
133 }
134
135 static void __bt_free_cb_data(rfcomm_cb_data_t *cb_data)
136 {
137         DBG("+");
138
139         if (cb_data->id >= 0)
140                 __rfcomm_delete_id(cb_data->id);
141
142         if (cb_data->object_id > 0)
143                 _bt_unregister_gdbus_object(cb_data->object_id);
144
145         if (cb_data->obj_path) {
146                 INFO("Unregister profile");
147                 _bt_unregister_profile(cb_data->obj_path);
148         }
149
150         g_free(cb_data->obj_path);
151
152         g_free(cb_data->device_path);
153         g_free(cb_data);
154
155         DBG("-");
156 }
157
158 static void __rfcomm_cb_data_remove(rfcomm_cb_data_t *info)
159 {
160         if (!info) {
161                 ERR("info == NULL");
162                 return;
163         }
164
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);
169         }
170 }
171
172 static rfcomm_conn_info_t *__find_conn_info_with_stack_fd(rfcomm_cb_data_t *info, int fd)
173 {
174         GSList *l;
175
176         for (l = info->rfcomm_conns; l != NULL; l = l->next) {
177                 rfcomm_conn_info_t *conn_info = l->data;
178
179                 if (conn_info && (conn_info->stack_fd == fd))
180                         return conn_info;
181         }
182
183         return NULL;
184 }
185
186 static rfcomm_conn_info_t *__find_conn_info_with_hal_fd(rfcomm_cb_data_t *info, int fd)
187 {
188         GSList *l;
189         for (l = info->rfcomm_conns; l != NULL; l = l->next) {
190                 rfcomm_conn_info_t *conn_info = l->data;
191
192                 if (conn_info && (conn_info->hal_fd == fd))
193                         return conn_info;
194         }
195
196         return NULL;
197 }
198
199 static gint compare(gpointer *a, gpointer *b)
200 {
201         rfcomm_conn_info_t *node = (rfcomm_conn_info_t *)a;
202         char *address = (char *)b;
203         return g_strcmp0(node->remote_addr, address);
204 }
205
206 static rfcomm_conn_info_t *__get_conn_info_from_address(rfcomm_cb_data_t *info,
207                 char *dev_address)
208 {
209         GSList *l = NULL;
210         rfcomm_conn_info_t *conn_info = NULL;
211         l = g_slist_find_custom(info->rfcomm_conns, dev_address,
212                         (GCompareFunc)compare);
213         if (l)
214                 conn_info = l->data;
215         return conn_info;
216 }
217
218 static void __bt_free_conn(rfcomm_conn_info_t *conn)
219 {
220         DBG("+");
221
222         if (conn == NULL)
223                 return;
224
225         if (0 < conn->hal_fd)
226                 close(conn->hal_fd);
227
228         if (conn->hal_watch > 0) {
229                 g_source_remove(conn->hal_watch);
230                 conn->hal_watch = 0;
231         }
232
233         if (0 < conn->stack_fd)
234                 close(conn->stack_fd);
235
236         if (conn->bt_watch > 0) {
237                 g_source_remove(conn->bt_watch);
238                 conn->bt_watch = 0;
239         }
240
241         g_free(conn);
242         DBG("-");
243 }
244
245 static void __rfcomm_remove_conn_info_t(rfcomm_cb_data_t *info, char *address)
246 {
247         rfcomm_conn_info_t *conn_info;
248
249         conn_info = __get_conn_info_from_address(info, address);
250         if (conn_info) {
251                 info->rfcomm_conns = g_slist_remove(info->rfcomm_conns, conn_info);
252                 __bt_free_conn(conn_info);
253         }
254 }
255
256 static int write_all(int fd, unsigned char *buf, int len)
257 {
258         int sent = 0;
259
260         while (len > 0) {
261                 int written;
262
263                 written = write(fd, buf, len);
264                 if (written < 0) {
265                         if (errno == EINTR || errno == EAGAIN)
266                                 continue;
267                         return -1;
268                 }
269
270                 if (!written)
271                         return 0;
272
273                 len -= written; buf += written; sent += written;
274         }
275
276         return sent;
277 }
278
279 static gboolean app_event_cb(GIOChannel *io, GIOCondition cond, gpointer data)
280 {
281         gsize len;
282         unsigned int sent;
283         rfcomm_cb_data_t *info = data;
284         rfcomm_conn_info_t *conn_info;
285         unsigned char buff[BT_HAL_RFCOMM_MAX_BUFFER_SIZE];
286         GError *err = NULL;
287         int fd;
288
289         DBG("+");
290         fd = g_io_channel_unix_get_fd(io);
291         conn_info = __find_conn_info_with_hal_fd(info, fd);
292
293         if (cond & G_IO_HUP) {
294                 ERR("Socket %d hang up", fd);
295                 goto fail;
296         }
297
298         if (cond & (G_IO_ERR | G_IO_NVAL)) {
299                 ERR("Socket %d error", fd);
300                 goto fail;
301         }
302
303         if (!conn_info) {
304                 ERR("conn_info is NULL");
305                 return TRUE;
306         }
307
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) {
312                 if( err )
313                         ERR("IO Channel read error: %s", err->message);
314                 else
315                         ERR("IO Channel read error client");
316                 goto fail;
317         }
318
319         DBG("len: %d", len);
320         if (0 == len) {
321                 ERR("Other end of socket is closed");
322                 goto fail;
323         }
324
325         /* Send data to remote device */
326         sent = write_all(conn_info->stack_fd, buff, len);
327         if (sent < 0) {
328                 ERR("write(): %s", strerror(errno));
329                 goto fail;
330         }
331
332         DBG("-");
333         return TRUE;
334 fail:
335         __rfcomm_remove_conn_info_t(info, conn_info->remote_addr);
336         __rfcomm_cb_data_remove(info);
337         return FALSE;
338 }
339
340 static gboolean stack_event_cb(GIOChannel *io, GIOCondition cond, gpointer data)
341 {
342         unsigned int len;
343         unsigned int sent;
344         rfcomm_cb_data_t *info = data;
345         rfcomm_conn_info_t *conn_info;
346         unsigned char buff[BT_HAL_RFCOMM_MAX_BUFFER_SIZE];
347         GError *err = NULL;
348         int fd;
349
350         DBG("+");
351
352         fd = g_io_channel_unix_get_fd(io);
353         conn_info = __find_conn_info_with_stack_fd(info, fd);
354
355         if (cond & G_IO_HUP) {
356                 ERR("Socket %d hang up", fd);
357                 goto fail;
358         }
359
360         if (cond & (G_IO_ERR | G_IO_NVAL)) {
361                 ERR("Socket %d error", fd);
362                 goto fail;
363         }
364
365         if (!conn_info) {
366                 ERR("conn_info is NULL");
367                 return TRUE;
368         }
369
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) {
374                 if( err )
375                         ERR("IO Channel read error: %s", err->message);
376                 else
377                         ERR("IO Channel read error client");
378                 goto fail;
379         }
380
381         DBG("len: %d", len);
382         if (0 == len) {
383                 ERR("Other end of socket is closed");
384                 goto fail;
385         }
386
387         /* Send data to application */
388         sent = write_all(conn_info->hal_fd, buff, len);
389         if (sent < 0) {
390                 ERR("write(): %s", strerror(errno));
391                 goto fail;
392         }
393
394         DBG("-");
395         return TRUE;
396 fail:
397         __rfcomm_remove_conn_info_t(info, conn_info->remote_addr);
398         __rfcomm_cb_data_remove(info);
399         return FALSE;
400 }
401
402 static int __new_connection(const char *path, int fd, bt_bdaddr_t *addr)
403 {
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;
408         GIOCondition cond;
409         int len;
410         GIOChannel *io;
411
412         /* TODO: Temperary, later need to fill correct channel form correct place */
413         int chan = 0;
414
415         if (NULL == path || NULL == addr) {
416                 ERR("NULL == path || NULL = addr");
417                 return -1;
418         }
419
420         _bt_convert_addr_type_to_string(address, addr->address);
421         info = __find_rfcomm_info_from_path(path);
422         if (info == NULL)
423                 return -1;
424
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);
428                 return -1;
429         }
430
431         if (write(conn_info->hal_fd, &chan, sizeof(chan)) != sizeof(chan)) {
432                 ERR("Error sending RFCOMM channel");
433                 goto fail;
434         }
435
436         conn_info->stack_fd = fd;
437         DBG("Remote address: %s, RFCOMM fd: %d", address, conn_info->stack_fd);
438
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));
445         if (len < 0) {
446                 ERR("%s", strerror(errno));
447                 goto fail;
448         }
449
450         if (len != sizeof(ev)) {
451                 ERR("Error sending connect event");
452                 goto fail;;
453         }
454
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);
460
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);
466
467         return 0;
468 fail:
469         __rfcomm_remove_conn_info_t(info, address);
470         __rfcomm_cb_data_remove(info);
471         return -1;
472 }
473
474 static void __bt_connect_response_cb(GDBusProxy *proxy,
475                 GAsyncResult *res, gpointer user_data)
476 {
477         GError *error = NULL;
478         rfcomm_cb_data_t *cb_data;
479         char dev_address[BT_HAL_ADDRESS_STRING_SIZE];
480         const char *path;
481
482         DBG("+");
483
484         cb_data = user_data;
485         if (cb_data == NULL) {
486                 ERR("cb_data == NULL");
487                 return;
488         }
489
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);
496                 g_error_free(error);
497         }
498
499         if (proxy)
500                 g_object_unref(proxy);
501
502         DBG("-");
503 }
504
505 static void __bt_discover_service_response_cb(GDBusProxy *proxy,
506                 GAsyncResult *res, gpointer user_data)
507 {
508         rfcomm_cb_data_t *cb_data;
509         int ret = 0;
510         GError *err = NULL;
511         bt_hal_register_profile_info_t info = {0};
512         char dev_address[BT_HAL_ADDRESS_STRING_SIZE];
513         const char *path;
514
515         DBG("+");
516
517         cb_data = user_data;
518         if (!cb_data) {
519                 ERR("cb_data == NULL");
520                 return;
521         }
522
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);
526
527         g_dbus_proxy_call_finish(proxy, res, &err);
528         if (proxy)
529                 g_object_unref(proxy);
530         if (err != NULL) {
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);
534                 goto done;
535         } else {
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";
543
544                         ret = _bt_register_profile(&info, FALSE);
545                         if (ret < 0)
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);
553                                 goto done;
554                         }
555                 } else {
556                         ERR("remote uuid not found");
557                         __rfcomm_remove_conn_info_t(cb_data, dev_address);
558                         __rfcomm_cb_data_remove(cb_data);
559                 }
560         }
561 done:
562         if (err)
563                 g_clear_error(&err);
564 }
565
566 static rfcomm_cb_data_t *__get_rfcomm_cb_data(char *remote_uuid)
567 {
568         int id;
569         int object_id;
570         char *path;
571         rfcomm_cb_data_t *cb_data;
572
573         DBG("+");
574
575         cb_data = __find_rfcomm_info_from_uuid(remote_uuid);
576         if (!cb_data) {
577                 id = __rfcomm_assign_id();
578                 if (id < 0) {
579                         ERR("__rfcomm_assign_id failed");
580                         return NULL;
581                 }
582
583                 path = g_strdup_printf("/org/socket/client/%d/%d", getpid(), id);
584                 object_id = _bt_register_new_gdbus_object(path, __new_connection);
585                 if (object_id < 0) {
586                         ERR("_bt_register_new_gdbus_object failed");
587                         __rfcomm_delete_id(id);
588                         return NULL;
589                 }
590
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;
595                 cb_data->id = id;
596         }
597
598         DBG("-");
599         return cb_data;
600 }
601
602 static rfcomm_conn_info_t *__rfcomm_create_conn_info(char *addr, int *sock)
603 {
604         int fds[2] = {-1, -1};
605         rfcomm_conn_info_t *conn;
606
607         if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
608                 ERR("socketpair(): %s", strerror(errno));
609                 *sock = -1;
610                 return NULL;
611         }
612
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];
616         conn->stack_fd = -1;
617         *sock = fds[1];
618
619         DBG("hal_fd: %d, sock: %d", conn->hal_fd, *sock);
620
621         return conn;
622 }
623
624 int _bt_hal_dbus_handler_rfcomm_connect(unsigned char *addr, unsigned char *uuid, int *sock)
625 {
626         int ret;
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];
631
632         if (!addr) {
633                 ERR("remote_addr is NULL");
634                 return BT_STATUS_PARM_INVALID;
635         }
636
637         if (!uuid) {
638                 ERR("remote_uuid is NULL");
639                 return BT_STATUS_PARM_INVALID;
640         }
641
642         if (!sock) {
643                 ERR("sock is NULL");
644                 return BT_STATUS_PARM_INVALID;
645         }
646
647         _bt_convert_uuid_type_to_string(remote_uuid, uuid);
648         cb_data = __get_rfcomm_cb_data(remote_uuid);
649         if (!cb_data)
650                 return BT_STATUS_FAIL;
651
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);
655         if (!conn)
656                 return BT_STATUS_FAIL;
657
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;
666         }
667
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);
671         } else
672                 INFO("Callback information is already added");
673
674         return BT_STATUS_SUCCESS;
675 }