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