Code Sync [Tizen3.0]: Merged the tizen_2.4 Spin code to tizen.org
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-request-sender.c
1 /*
2  * Bluetooth-frwk
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:  Hocheol Seo <hocheol.seo@samsung.com>
7  *               Girishashok Joshi <girish.joshi@samsung.com>
8  *               Chanyeol Park <chanyeol.park@samsung.com>
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *              http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */
23
24 #include <dbus/dbus-glib.h>
25 #include <glib.h>
26 #include <dlog.h>
27 #include <string.h>
28
29 #include "bluetooth-api.h"
30 #include "bluetooth-hid-api.h"
31 #include "bluetooth-audio-api.h"
32 #include "bt-internal-types.h"
33
34 #include "bt-common.h"
35 #include "bt-request-sender.h"
36 #include "bt-event-handler.h"
37 #include "bluetooth-media-control.h"
38
39 /* auto generated header by bt-request-service.xml*/
40 #include "bt-request-service.h"
41
42 static GSList *sending_requests;
43
44 DBusGConnection *service_conn;
45 DBusGConnection *system_conn;
46 DBusGProxy *service_proxy;
47
48 static GDBusConnection *service_gconn;
49 static GDBusProxy *service_gproxy;
50
51 static GDBusProxy *__bt_gdbus_init_service_proxy(void)
52 {
53         GDBusProxy *proxy;
54         GError *err = NULL;
55
56         g_type_init();
57
58         if (service_gconn == NULL)
59                 service_gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
60
61         if (!service_gconn) {
62                 if (err) {
63                         BT_ERR("Unable to connect to dbus: %s", err->message);
64                         g_clear_error(&err);
65                 }
66                 return NULL;
67         }
68
69         proxy =  g_dbus_proxy_new_sync(service_gconn,
70                         G_DBUS_PROXY_FLAGS_NONE, NULL,
71                         BT_DBUS_NAME,
72                         BT_SERVICE_PATH,
73                         BT_DBUS_NAME,
74                         NULL, &err);
75         if (!proxy) {
76                 if (err) {
77                          BT_ERR("Unable to create proxy: %s", err->message);
78                          g_clear_error(&err);
79                 }
80
81                 g_object_unref(service_gconn);
82                 service_gconn = NULL;
83                 return NULL;
84         }
85
86         service_gproxy = proxy;
87
88         return proxy;
89 }
90
91 static GDBusProxy *__bt_gdbus_get_service_proxy(void)
92 {
93         return (service_gproxy) ? service_gproxy : __bt_gdbus_init_service_proxy();
94 }
95
96 void _bt_gdbus_deinit_proxys(void)
97 {
98         if (service_gproxy) {
99                 g_object_unref(service_proxy);
100                 service_proxy = NULL;
101         }
102
103         if (service_gconn) {
104                 g_object_unref(service_gconn);
105                 service_gconn = NULL;
106         }
107 }
108
109 static void __bt_get_event_info(int service_function, GArray *output,
110                         int *event, int *event_type, void **param_data)
111 {
112         ret_if(event == NULL);
113
114         BT_DBG("service_function : %x", service_function);
115         switch (service_function) {
116         case BT_BOND_DEVICE:
117         case BT_BOND_DEVICE_BY_TYPE:
118                 *event_type = BT_ADAPTER_EVENT;
119                 *event = BLUETOOTH_EVENT_BONDING_FINISHED;
120                 ret_if(output == NULL);
121                 *param_data = &g_array_index(output,
122                                 bluetooth_device_info_t, 0);
123                 break;
124         case BT_UNBOND_DEVICE:
125                 *event_type = BT_ADAPTER_EVENT;
126                 *event = BLUETOOTH_EVENT_BONDED_DEVICE_REMOVED;
127                 ret_if(output == NULL);
128                 *param_data = &g_array_index(output,
129                                 bluetooth_device_info_t, 0);
130                 break;
131         case BT_SEARCH_SERVICE:
132                 *event_type = BT_ADAPTER_EVENT;
133                 *event = BLUETOOTH_EVENT_SERVICE_SEARCHED;
134                 ret_if(output == NULL);
135                 *param_data = &g_array_index(output,
136                                 bluetooth_device_info_t, 0);
137                 break;
138         case BT_HID_CONNECT:
139                 *event_type = BT_HID_EVENT;
140                 *event = BLUETOOTH_HID_CONNECTED;
141                 ret_if(output == NULL);
142                 *param_data = &g_array_index(output,
143                                 bluetooth_device_address_t, 0);
144                 break;
145         case BT_HID_DISCONNECT:
146                 *event_type = BT_HID_EVENT;
147                 *event = BLUETOOTH_HID_DISCONNECTED;
148                 ret_if(output == NULL);
149                 *param_data = &g_array_index(output,
150                                 bluetooth_device_address_t, 0);
151                 break;
152         case BT_AUDIO_CONNECT:
153         case BT_AG_CONNECT:
154                 *event_type = BT_HEADSET_EVENT;
155                 *event = BLUETOOTH_EVENT_AG_CONNECTED;
156                 ret_if(output == NULL);
157                 *param_data = &g_array_index(output, char, 0);
158                 break;
159         case BT_AUDIO_DISCONNECT:
160         case BT_AG_DISCONNECT:
161                 *event_type = BT_HEADSET_EVENT;
162                 *event = BLUETOOTH_EVENT_AG_DISCONNECTED;
163                 ret_if(output == NULL);
164                 *param_data = &g_array_index(output, char, 0);
165                 break;
166         case BT_AV_CONNECT:
167                 *event_type = BT_HEADSET_EVENT;
168                 *event = BLUETOOTH_EVENT_AV_CONNECTED;
169                 ret_if(output == NULL);
170                 *param_data = &g_array_index(output, char, 0);
171                 break;
172         case BT_AV_DISCONNECT:
173                 *event_type = BT_HEADSET_EVENT;
174                 *event = BLUETOOTH_EVENT_AV_DISCONNECTED;
175                 ret_if(output == NULL);
176                 *param_data = &g_array_index(output, char, 0);
177                 break;
178         case BT_HF_CONNECT:
179                 *event_type = BT_HF_AGENT_EVENT;
180                 *event = BLUETOOTH_EVENT_HF_CONNECTED;
181                 ret_if(output == NULL);
182                 *param_data = &g_array_index(output, char, 0);
183                 break;
184         case BT_HF_DISCONNECT:
185                 *event_type = BT_HF_AGENT_EVENT;
186                 *event = BLUETOOTH_EVENT_HF_DISCONNECTED;
187                 ret_if(output == NULL);
188                 *param_data = &g_array_index(output, char, 0);
189                 break;
190         case BT_NETWORK_CONNECT:
191                 *event_type = BT_ADAPTER_EVENT;
192                 *event = BLUETOOTH_EVENT_NETWORK_CONNECTED;
193                 ret_if(output == NULL);
194                 *param_data = &g_array_index(output,
195                                 bluetooth_device_address_t, 0);
196                 break;
197         case BT_NETWORK_DISCONNECT:
198                 *event_type = BT_ADAPTER_EVENT;
199                 *event = BLUETOOTH_EVENT_NETWORK_DISCONNECTED;
200                 ret_if(output == NULL);
201                 *param_data = &g_array_index(output,
202                                 bluetooth_device_address_t, 0);
203                 break;
204         case BT_RFCOMM_CLIENT_CONNECT:
205                 *event_type = BT_RFCOMM_CLIENT_EVENT;
206                 *event = BLUETOOTH_EVENT_RFCOMM_CONNECTED;
207                 ret_if(output == NULL);
208                 *param_data = &g_array_index(output,
209                                 bluetooth_rfcomm_connection_t, 0);
210                 break;
211         case BT_AVRCP_CONTROL_CONNECT:
212                 *event_type = BT_AVRCP_CONTROL_EVENT;
213                 *event = BLUETOOTH_EVENT_AVRCP_CONTROL_CONNECTED;
214                 ret_if(output == NULL);
215                 *param_data = &g_array_index(output, char, 0);
216                 break;
217         case BT_AVRCP_CONTROL_DISCONNECT:
218                 *event_type = BT_AVRCP_CONTROL_EVENT;
219                 *event = BLUETOOTH_EVENT_AVRCP_CONTROL_DISCONNECTED;
220                 ret_if(output == NULL);
221                 *param_data = &g_array_index(output, char, 0);
222                 break;
223         default:
224                 BT_ERR("Unknown function");
225                 return;
226         }
227 }
228
229 /*
230 out param1: API result
231 out param2: return paramter
232 out param3:
233 */
234 static void __bt_fill_garray_from_variant(GVariant *var, GArray *param)
235 {
236         char *data;
237         int size;
238
239         size = g_variant_get_size(var);
240         if (size > 0) {
241                 data = (char *)g_variant_get_data(var);
242                 if (data)
243                         param = g_array_append_vals(param, data, size);
244
245         }
246 }
247
248 static void __send_request_cb(GDBusProxy *proxy,
249                      GAsyncResult *res,
250                      gpointer      user_data)
251 {
252         bluetooth_event_param_t bt_event;
253         bt_req_info_t *cb_data = user_data;
254         int result = BLUETOOTH_ERROR_NONE;
255         int event_type = BT_ADAPTER_EVENT;
256         int request_id;
257         GError *error = NULL;
258         GVariant *value;
259         GVariant *param1;
260         GVariant *param2;
261         GArray *out_param1 = NULL;
262         GArray *out_param2 = NULL;
263
264         BT_DBG("+");
265         memset(&bt_event, 0x00, sizeof(bluetooth_event_param_t));
266
267         value = g_dbus_proxy_call_finish(proxy, res, &error);
268         if (value == NULL) {
269                 if (error) {
270                         /* dBUS gives error cause */
271                         BT_ERR("D-Bus API failure: message[%s]",
272                                                         error->message);
273                         g_clear_error(&error);
274                 }
275                 result = BLUETOOTH_ERROR_TIMEOUT;
276
277                 ret_if(cb_data == NULL);
278
279                 __bt_get_event_info(cb_data->service_function, NULL,
280                                 &bt_event.event, &event_type,
281                                 &bt_event.param_data);
282         } else {
283                 g_variant_get(value, "(@ay@ay)", &param1, &param2);
284                 g_variant_unref(value);
285
286                 if (param1) {
287                         out_param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
288                         __bt_fill_garray_from_variant(param1, out_param1);
289                         g_variant_unref(param1);
290                 }
291
292                 if (param2) {
293                         out_param2 = g_array_new(TRUE, TRUE, sizeof(gchar));
294                         __bt_fill_garray_from_variant(param2, out_param2);
295                         result = g_array_index(out_param2, int, 0);
296                         g_variant_unref(param2);
297                         g_array_free(out_param2, TRUE);
298                 } else {
299                         result = BLUETOOTH_ERROR_INTERNAL;
300                 }
301
302                 ret_if(cb_data == NULL);
303
304                 __bt_get_event_info(cb_data->service_function, out_param1,
305                                 &bt_event.event, &event_type,
306                                 &bt_event.param_data);
307
308                 if (result == BLUETOOTH_ERROR_NONE && out_param1) {
309                         if (cb_data->service_function == BT_OPP_PUSH_FILES) {
310                                 request_id = g_array_index(out_param1, int, 0);
311                                 BT_DBG("request_id : %d", request_id);
312                                 _bt_add_push_request_id(request_id);
313                         }
314
315                         goto done;
316                 }
317
318         }
319
320         if (cb_data->cb == NULL)
321                 goto done;
322
323         /* Only if fail case, call the callback function*/
324         bt_event.result = result;
325         BT_INFO("event_type[%d], result=[%d]", event_type, result);
326
327         if (event_type == BT_ADAPTER_EVENT || event_type == BT_RFCOMM_CLIENT_EVENT) {
328                 ((bluetooth_cb_func_ptr)cb_data->cb)(bt_event.event,
329                                 &bt_event,
330                                 cb_data->user_data);
331         } else if (event_type == BT_HID_EVENT) {
332                 ((hid_cb_func_ptr)cb_data->cb)(bt_event.event,
333                                 (hid_event_param_t *)&bt_event,
334                                 cb_data->user_data);
335         } else if (event_type == BT_HEADSET_EVENT) {
336                 ((bt_audio_func_ptr)cb_data->cb)(bt_event.event,
337                                 (bt_audio_event_param_t *)&bt_event,
338                                 cb_data->user_data);
339         } else if (event_type == BT_HF_AGENT_EVENT) {
340                 ((bt_audio_func_ptr)cb_data->cb)(bt_event.event,
341                                 (bt_audio_event_param_t *)&bt_event,
342                                 cb_data->user_data);
343         } else if (event_type == BT_AVRCP_CONTROL_EVENT) {
344                 ((media_cb_func_ptr)cb_data->cb)(bt_event.event,
345                                 (media_event_param_t *)&bt_event,
346                                 cb_data->user_data);
347         } else {
348                 BT_INFO("Not handled event type : %d", event_type);
349         }
350 done:
351         if (out_param1)
352                 g_array_free(out_param1, TRUE);
353
354         sending_requests = g_slist_remove(sending_requests, (void *)cb_data);
355
356         g_free(cb_data);
357         BT_DBG("-");
358 }
359
360 int _bt_sync_send_request(int service_type, int service_function,
361                         GArray *in_param1, GArray *in_param2,
362                         GArray *in_param3, GArray *in_param4,
363                         GArray **out_param1)
364 {
365         int result = BLUETOOTH_ERROR_NONE;
366         char *cookie;
367         GError *error = NULL;
368         GArray *in_param5 = NULL;
369         GArray *out_param2 = NULL;
370
371         GDBusProxy  *proxy;
372         GVariant *ret;
373         GVariant *param1;
374         GVariant *param2;
375         GVariant *param3;
376         GVariant *param4;
377         GVariant *param5;
378
379         switch (service_type) {
380         case BT_BLUEZ_SERVICE:
381         case BT_OBEX_SERVICE:
382         case BT_AGENT_SERVICE:
383         case BT_CHECK_PRIVILEGE:
384                 proxy = __bt_gdbus_get_service_proxy();
385                 if (!proxy)
386                         return BLUETOOTH_ERROR_INTERNAL;
387
388                 in_param5 = g_array_new(TRUE, TRUE, sizeof(gchar));
389
390                 cookie = _bt_get_cookie();
391
392                 if (cookie) {
393                         g_array_append_vals(in_param5, cookie,
394                                         _bt_get_cookie_size());
395                 }
396
397                 param1 = g_variant_new_from_data((const GVariantType *)"ay",
398                                         in_param1->data, in_param1->len,
399                                         TRUE, NULL, NULL);
400                 param2 = g_variant_new_from_data((const GVariantType *)"ay",
401                                         in_param2->data, in_param2->len,
402                                         TRUE, NULL, NULL);
403                 param3 = g_variant_new_from_data((const GVariantType *)"ay",
404                                         in_param3->data, in_param3->len,
405                                         TRUE, NULL, NULL);
406                 param4 = g_variant_new_from_data((const GVariantType *)"ay",
407                                         in_param4->data, in_param4->len,
408                                         TRUE, NULL, NULL);
409                 param5 = g_variant_new_from_data((const GVariantType *)"ay",
410                                         in_param5->data,        in_param5->len,
411                                         TRUE, NULL, NULL);
412
413                 ret = g_dbus_proxy_call_sync(proxy, "service_request",
414                                         g_variant_new("(iii@ay@ay@ay@ay@ay)",
415                                                 service_type, service_function,
416                                                 BT_SYNC_REQ, param1,
417                                                 param2, param3,
418                                                 param4, param5),
419                                         G_DBUS_CALL_FLAGS_NONE, -1,
420                                         NULL, &error);
421
422                 g_array_free(in_param5, TRUE);
423
424                 if (ret == NULL) {
425                         /* dBUS-RPC is failed */
426                         BT_ERR("dBUS-RPC is failed");
427
428                         if (error != NULL) {
429                                 /* dBUS gives error cause */
430                                 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
431                                        error->code, error->message);
432
433                                 g_clear_error(&error);
434                         } else {
435                                 /* dBUS does not give error cause dBUS-RPC is failed */
436                                 BT_ERR("error returned was NULL");
437                         }
438
439                         return BLUETOOTH_ERROR_INTERNAL;
440                 }
441
442                 param1 = NULL;
443                 param2 = NULL;
444
445                 g_variant_get(ret, "(@ay@ay)", &param1, &param2);
446
447                 if (param1) {
448                         *out_param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
449                         __bt_fill_garray_from_variant(param1, *out_param1);
450                         g_variant_unref(param1);
451                 }
452
453                 if (param2) {
454                         out_param2 = g_array_new(TRUE, TRUE, sizeof(gchar));
455                         __bt_fill_garray_from_variant(param2, out_param2);
456                         result = g_array_index(out_param2, int, 0);
457                         g_variant_unref(param2);
458                         g_array_free(out_param2, TRUE);
459                 } else {
460                         result = BLUETOOTH_ERROR_INTERNAL;
461                 }
462
463                 g_variant_unref(ret);
464                 break;
465         default:
466                 BT_ERR("Unknown service type");
467                 return BLUETOOTH_ERROR_INTERNAL;
468         }
469
470         return result;
471 }
472
473 int _bt_async_send_request(int service_type, int service_function,
474                         GArray *in_param1, GArray *in_param2,
475                         GArray *in_param3, GArray *in_param4,
476                         void *callback, void *user_data)
477 {
478         GArray* in_param5 = NULL;
479         bt_req_info_t *cb_data;
480         char *cookie;
481
482         GDBusProxy *proxy;
483         int timeout;
484         GVariant *param1;
485         GVariant *param2;
486         GVariant *param3;
487         GVariant *param4;
488         GVariant *param5;
489
490         BT_DBG("service_function : %x", service_function);
491
492         cb_data = g_new0(bt_req_info_t, 1);
493
494         cb_data->service_function = service_function;
495         cb_data->cb = callback;
496         cb_data->user_data = user_data;
497
498         switch (service_type) {
499         case BT_BLUEZ_SERVICE:
500         case BT_OBEX_SERVICE:
501                 proxy =  __bt_gdbus_get_service_proxy();
502                 if (!proxy) {
503                         g_free(cb_data);
504                         return BLUETOOTH_ERROR_INTERNAL;
505                 }
506
507                 /* Do not timeout the request in certain cases. Sometime the
508                  * request may take undeterministic time to reponse.
509                  * (for ex: pairing retry) */
510                 if (service_function == BT_BOND_DEVICE ||
511                         service_function == BT_BOND_DEVICE_BY_TYPE)
512                         timeout = INT_MAX;
513                 else
514                         timeout = BT_DBUS_TIMEOUT_MAX;
515
516                 in_param5 = g_array_new(TRUE, TRUE, sizeof(gchar));
517
518                 cookie = _bt_get_cookie();
519
520                 if (cookie) {
521                         g_array_append_vals(in_param5, cookie,
522                                         _bt_get_cookie_size());
523                 }
524                 param1 = g_variant_new_from_data((const GVariantType *)"ay",
525                                         in_param1->data, in_param1->len,
526                                         TRUE, NULL, NULL);
527                 param2 = g_variant_new_from_data((const GVariantType *)"ay",
528                                         in_param2->data, in_param2->len,
529                                         TRUE, NULL, NULL);
530                 param3 = g_variant_new_from_data((const GVariantType *)"ay",
531                                         in_param3->data, in_param3->len,
532                                         TRUE, NULL, NULL);
533                 param4 = g_variant_new_from_data((const GVariantType *)"ay",
534                                         in_param4->data, in_param4->len,
535                                         TRUE, NULL, NULL);
536                 param5 = g_variant_new_from_data((const GVariantType *)"ay",
537                                         in_param5->data, in_param5->len,
538                                         TRUE, NULL, NULL);
539
540                 g_dbus_proxy_call(proxy, "service_request",
541                                         g_variant_new("(iii@ay@ay@ay@ay@ay)",
542                                                 service_type, service_function,
543                                                 BT_ASYNC_REQ, param1, param2,
544                                                 param3, param4, param5),
545                                         G_DBUS_CALL_FLAGS_NONE,
546                                         timeout, NULL,
547                                         (GAsyncReadyCallback)__send_request_cb,
548                                         (gpointer)cb_data);
549                 sending_requests = g_slist_append(sending_requests, cb_data);
550
551                 g_array_free(in_param5, TRUE);
552                 break;
553         }
554
555         return BLUETOOTH_ERROR_NONE;
556 }
557