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