3.0 specific patch: fix build error
[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_AV_SOURCE_CONNECT:
179                 *event_type = BT_A2DP_SOURCE_EVENT;
180                 *event = BLUETOOTH_EVENT_AV_SOURCE_CONNECTED;
181                 ret_if(output == NULL);
182                 *param_data = &g_array_index(output, char, 0);
183                 break;
184         case BT_AV_SOURCE_DISCONNECT:
185                 *event_type = BT_A2DP_SOURCE_EVENT;
186                 *event = BLUETOOTH_EVENT_AV_SOURCE_DISCONNECTED;
187                 ret_if (output == NULL);
188                 *param_data = &g_array_index (output, char, 0);
189                 break;
190         case BT_HF_CONNECT:
191                 *event_type = BT_HF_AGENT_EVENT;
192                 *event = BLUETOOTH_EVENT_HF_CONNECTED;
193                 ret_if(output == NULL);
194                 *param_data = &g_array_index(output, char, 0);
195                 break;
196         case BT_HF_DISCONNECT:
197                 *event_type = BT_HF_AGENT_EVENT;
198                 *event = BLUETOOTH_EVENT_HF_DISCONNECTED;
199                 ret_if(output == NULL);
200                 *param_data = &g_array_index(output, char, 0);
201                 break;
202         case BT_NETWORK_CONNECT:
203                 *event_type = BT_ADAPTER_EVENT;
204                 *event = BLUETOOTH_EVENT_NETWORK_CONNECTED;
205                 ret_if(output == NULL);
206                 *param_data = &g_array_index(output,
207                                 bluetooth_device_address_t, 0);
208                 break;
209         case BT_NETWORK_DISCONNECT:
210                 *event_type = BT_ADAPTER_EVENT;
211                 *event = BLUETOOTH_EVENT_NETWORK_DISCONNECTED;
212                 ret_if(output == NULL);
213                 *param_data = &g_array_index(output,
214                                 bluetooth_device_address_t, 0);
215                 break;
216         case BT_RFCOMM_CLIENT_CONNECT:
217                 *event_type = BT_RFCOMM_CLIENT_EVENT;
218                 *event = BLUETOOTH_EVENT_RFCOMM_CONNECTED;
219                 ret_if(output == NULL);
220                 *param_data = &g_array_index(output,
221                                 bluetooth_rfcomm_connection_t, 0);
222                 break;
223         case BT_AVRCP_CONTROL_CONNECT:
224                 *event_type = BT_AVRCP_CONTROL_EVENT;
225                 *event = BLUETOOTH_EVENT_AVRCP_CONTROL_CONNECTED;
226                 ret_if(output == NULL);
227                 *param_data = &g_array_index(output, char, 0);
228                 break;
229         case BT_AVRCP_CONTROL_DISCONNECT:
230                 *event_type = BT_AVRCP_CONTROL_EVENT;
231                 *event = BLUETOOTH_EVENT_AVRCP_CONTROL_DISCONNECTED;
232                 ret_if(output == NULL);
233                 *param_data = &g_array_index(output, char, 0);
234                 break;
235         default:
236                 BT_ERR("Unknown function");
237                 return;
238         }
239 }
240
241 /*
242 out param1: API result
243 out param2: return paramter
244 out param3:
245 */
246 static void __bt_fill_garray_from_variant(GVariant *var, GArray *param)
247 {
248         char *data;
249         int size;
250
251         size = g_variant_get_size(var);
252         if (size > 0) {
253                 data = (char *)g_variant_get_data(var);
254                 if (data)
255                         param = g_array_append_vals(param, data, size);
256
257         }
258 }
259
260 static void __send_request_cb(GDBusProxy *proxy,
261                      GAsyncResult *res,
262                      gpointer      user_data)
263 {
264         bluetooth_event_param_t bt_event;
265         bt_req_info_t *cb_data = user_data;
266         int result = BLUETOOTH_ERROR_NONE;
267         int event_type = BT_ADAPTER_EVENT;
268         int request_id;
269         GError *error = NULL;
270         GVariant *value;
271         GVariant *param1;
272 //      GVariant *param2;
273         GArray *out_param1 = NULL;
274 //      GArray *out_param2 = NULL;
275
276         BT_DBG("+");
277         memset(&bt_event, 0x00, sizeof(bluetooth_event_param_t));
278
279         value = g_dbus_proxy_call_finish(proxy, res, &error);
280         if (value == NULL) {
281                 if (error) {
282                         /* dBUS gives error cause */
283                         BT_ERR("D-Bus API failure: message[%s]",
284                                                         error->message);
285                         g_clear_error(&error);
286                 }
287                 result = BLUETOOTH_ERROR_TIMEOUT;
288
289                 ret_if(cb_data == NULL);
290
291                 __bt_get_event_info(cb_data->service_function, NULL,
292                                 &bt_event.event, &event_type,
293                                 &bt_event.param_data);
294         } else {
295                 g_variant_get(value, "(iv)", &result, &param1);
296                 g_variant_unref(value);
297
298                 if (param1) {
299                         out_param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
300                         __bt_fill_garray_from_variant(param1, out_param1);
301                         g_variant_unref(param1);
302                 }
303
304 //              if (param2) {
305 //                      out_param2 = g_array_new(TRUE, TRUE, sizeof(gchar));
306 //                      __bt_fill_garray_from_variant(param2, out_param2);
307 //                      result = g_array_index(out_param2, int, 0);
308 //                      g_variant_unref(param2);
309 //                      g_array_free(out_param2, TRUE);
310 //              } else {
311 //                      result = BLUETOOTH_ERROR_INTERNAL;
312 //              }
313
314                 ret_if(cb_data == NULL);
315
316                 __bt_get_event_info(cb_data->service_function, out_param1,
317                                 &bt_event.event, &event_type,
318                                 &bt_event.param_data);
319
320                 if (result == BLUETOOTH_ERROR_NONE && out_param1) {
321                         if (cb_data->service_function == BT_OPP_PUSH_FILES) {
322                                 request_id = g_array_index(out_param1, int, 0);
323                                 BT_DBG("request_id : %d", request_id);
324                                 _bt_add_push_request_id(request_id);
325                         }
326
327                         goto done;
328                 }
329
330         }
331
332         if (cb_data->cb == NULL)
333                 goto done;
334
335         /* Only if fail case, call the callback function*/
336         bt_event.result = result;
337         BT_INFO("event_type[%d], result=[%d]", event_type, result);
338
339         if (event_type == BT_ADAPTER_EVENT || event_type == BT_RFCOMM_CLIENT_EVENT) {
340                 ((bluetooth_cb_func_ptr)cb_data->cb)(bt_event.event,
341                                 &bt_event,
342                                 cb_data->user_data);
343         } else if (event_type == BT_HID_EVENT) {
344                 ((hid_cb_func_ptr)cb_data->cb)(bt_event.event,
345                                 (hid_event_param_t *)&bt_event,
346                                 cb_data->user_data);
347         } else if (event_type == BT_HEADSET_EVENT) {
348                 ((bt_audio_func_ptr)cb_data->cb)(bt_event.event,
349                                 (bt_audio_event_param_t *)&bt_event,
350                                 cb_data->user_data);
351         } else if (event_type == BT_HF_AGENT_EVENT) {
352                 ((bt_audio_func_ptr)cb_data->cb)(bt_event.event,
353                                 (bt_audio_event_param_t *)&bt_event,
354                                 cb_data->user_data);
355         } else if (event_type == BT_AVRCP_CONTROL_EVENT) {
356                 ((media_cb_func_ptr)cb_data->cb)(bt_event.event,
357                                 (media_event_param_t *)&bt_event,
358                                 cb_data->user_data);
359         } else if (event_type == BT_A2DP_SOURCE_EVENT) {
360                 ((bt_audio_func_ptr)cb_data->cb)(bt_event.event,
361                                 (bt_audio_event_param_t *)&bt_event,
362                                 cb_data->user_data);
363         } else {
364                 BT_INFO("Not handled event type : %d", event_type);
365         }
366 done:
367         if (out_param1)
368                 g_array_free(out_param1, TRUE);
369
370         sending_requests = g_slist_remove(sending_requests, (void *)cb_data);
371
372         g_free(cb_data);
373         BT_DBG("-");
374 }
375
376 int _bt_sync_send_request(int service_type, int service_function,
377                         GArray *in_param1, GArray *in_param2,
378                         GArray *in_param3, GArray *in_param4,
379                         GArray **out_param1)
380 {
381         int result = BLUETOOTH_ERROR_NONE;
382         GError *error = NULL;
383         GArray *in_param5 = NULL;
384 //      GArray *out_param2 = NULL;
385
386         GDBusProxy  *proxy;
387         GVariant *ret;
388         GVariant *param1;
389         GVariant *param2;
390         GVariant *param3;
391         GVariant *param4;
392         GVariant *param5;
393
394         switch (service_type) {
395         case BT_BLUEZ_SERVICE:
396         case BT_OBEX_SERVICE:
397         case BT_AGENT_SERVICE:
398         case BT_CHECK_PRIVILEGE:
399                 proxy = __bt_gdbus_get_service_proxy();
400                 if (!proxy)
401                         return BLUETOOTH_ERROR_INTERNAL;
402
403                 in_param5 = g_array_new(TRUE, TRUE, sizeof(gchar));
404
405                 param1 = g_variant_new_from_data((const GVariantType *)"ay",
406                                         in_param1->data, in_param1->len,
407                                         TRUE, NULL, NULL);
408                 param2 = g_variant_new_from_data((const GVariantType *)"ay",
409                                         in_param2->data, in_param2->len,
410                                         TRUE, NULL, NULL);
411                 param3 = g_variant_new_from_data((const GVariantType *)"ay",
412                                         in_param3->data, in_param3->len,
413                                         TRUE, NULL, NULL);
414                 param4 = g_variant_new_from_data((const GVariantType *)"ay",
415                                         in_param4->data, in_param4->len,
416                                         TRUE, NULL, NULL);
417                 param5 = g_variant_new_from_data((const GVariantType *)"ay",
418                                         in_param5->data,        in_param5->len,
419                                         TRUE, NULL, NULL);
420
421                 ret = g_dbus_proxy_call_sync(proxy, "service_request",
422                                         g_variant_new("(iii@ay@ay@ay@ay@ay)",
423                                                 service_type, service_function,
424                                                 BT_SYNC_REQ, param1,
425                                                 param2, param3,
426                                                 param4, param5),
427                                         G_DBUS_CALL_FLAGS_NONE, -1,
428                                         NULL, &error);
429
430                 g_array_free(in_param5, TRUE);
431
432                 if (ret == NULL) {
433                         /* dBUS-RPC is failed */
434                         BT_ERR("dBUS-RPC is failed");
435
436                         if (error != NULL) {
437                                 /* dBUS gives error cause */
438                                 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
439                                        error->code, error->message);
440
441                                 g_clear_error(&error);
442                         } else {
443                                 /* dBUS does not give error cause dBUS-RPC is failed */
444                                 BT_ERR("error returned was NULL");
445                         }
446
447                         return BLUETOOTH_ERROR_INTERNAL;
448                 }
449
450                 param1 = NULL;
451 //              param2 = NULL;
452
453                 g_variant_get(ret, "(iv)", &result, &param1);
454
455                 if (param1) {
456                         *out_param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
457                         __bt_fill_garray_from_variant(param1, *out_param1);
458                         g_variant_unref(param1);
459                 }
460
461 //              if (param2) {
462 //                      out_param2 = g_array_new(TRUE, TRUE, sizeof(gchar));
463 //                      __bt_fill_garray_from_variant(param2, out_param2);
464 //                      result = g_array_index(out_param2, int, 0);
465 //                      g_variant_unref(param2);
466 //                      g_array_free(out_param2, TRUE);
467 //              } else {
468 //                      result = BLUETOOTH_ERROR_INTERNAL;
469 //              }
470
471                 g_variant_unref(ret);
472                 break;
473         default:
474                 BT_ERR("Unknown service type");
475                 return BLUETOOTH_ERROR_INTERNAL;
476         }
477
478         return result;
479 }
480
481 int _bt_async_send_request(int service_type, int service_function,
482                         GArray *in_param1, GArray *in_param2,
483                         GArray *in_param3, GArray *in_param4,
484                         void *callback, void *user_data)
485 {
486         GArray* in_param5 = NULL;
487         bt_req_info_t *cb_data;
488
489         GDBusProxy *proxy;
490         int timeout;
491         GVariant *param1;
492         GVariant *param2;
493         GVariant *param3;
494         GVariant *param4;
495         GVariant *param5;
496
497         BT_DBG("service_function : %x", service_function);
498
499         cb_data = g_new0(bt_req_info_t, 1);
500
501         cb_data->service_function = service_function;
502         cb_data->cb = callback;
503         cb_data->user_data = user_data;
504
505         switch (service_type) {
506         case BT_BLUEZ_SERVICE:
507         case BT_OBEX_SERVICE:
508                 proxy =  __bt_gdbus_get_service_proxy();
509                 if (!proxy) {
510                         g_free(cb_data);
511                         return BLUETOOTH_ERROR_INTERNAL;
512                 }
513
514                 /* Do not timeout the request in certain cases. Sometime the
515                  * request may take undeterministic time to reponse.
516                  * (for ex: pairing retry) */
517                 if (service_function == BT_BOND_DEVICE ||
518                         service_function == BT_BOND_DEVICE_BY_TYPE)
519                         timeout = INT_MAX;
520                 else
521                         timeout = BT_DBUS_TIMEOUT_MAX;
522
523                 in_param5 = g_array_new(TRUE, TRUE, sizeof(gchar));
524
525                 param1 = g_variant_new_from_data((const GVariantType *)"ay",
526                                         in_param1->data, in_param1->len,
527                                         TRUE, NULL, NULL);
528                 param2 = g_variant_new_from_data((const GVariantType *)"ay",
529                                         in_param2->data, in_param2->len,
530                                         TRUE, NULL, NULL);
531                 param3 = g_variant_new_from_data((const GVariantType *)"ay",
532                                         in_param3->data, in_param3->len,
533                                         TRUE, NULL, NULL);
534                 param4 = g_variant_new_from_data((const GVariantType *)"ay",
535                                         in_param4->data, in_param4->len,
536                                         TRUE, NULL, NULL);
537                 param5 = g_variant_new_from_data((const GVariantType *)"ay",
538                                         in_param5->data, in_param5->len,
539                                         TRUE, NULL, NULL);
540
541                 g_dbus_proxy_call(proxy, "service_request",
542                                         g_variant_new("(iii@ay@ay@ay@ay@ay)",
543                                                 service_type, service_function,
544                                                 BT_ASYNC_REQ, param1, param2,
545                                                 param3, param4, param5),
546                                         G_DBUS_CALL_FLAGS_NONE,
547                                         timeout, NULL,
548                                         (GAsyncReadyCallback)__send_request_cb,
549                                         (gpointer)cb_data);
550                 sending_requests = g_slist_append(sending_requests, cb_data);
551
552                 g_array_free(in_param5, TRUE);
553                 break;
554         }
555
556         return BLUETOOTH_ERROR_NONE;
557 }
558