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