2438cb363f8dce4b18b94388be5c2495570f5552
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-request-sender.c
1 /*
2  * bluetooth-frwk
3  *
4  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *              http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <dbus/dbus-glib.h>
21 #include <glib.h>
22 #include <dlog.h>
23 #include <string.h>
24
25 #include "bluetooth-api.h"
26 #include "bluetooth-hid-api.h"
27 #include "bluetooth-audio-api.h"
28 #include "bt-internal-types.h"
29
30 #include "bt-common.h"
31 #include "bt-request-sender.h"
32 #include "bt-event-handler.h"
33
34 /* auto generated header by bt-request-service.xml*/
35 #include "bt-request-service.h"
36
37 static GSList *sending_requests;
38
39 DBusGConnection *service_conn;
40 DBusGConnection *system_conn;
41 DBusGProxy *service_proxy;
42
43 static void __bt_remove_all_sending_requests(void)
44 {
45         GSList *l;
46         bt_req_info_t *info;
47
48         for (l = sending_requests; l != NULL; l = g_slist_next(l)) {
49                 info = l->data;
50
51                 if (info && info->proxy && info->proxy_call)
52                         dbus_g_proxy_cancel_call(info->proxy, info->proxy_call);
53         }
54
55         g_slist_free(sending_requests);
56         sending_requests = NULL;
57 }
58
59 DBusGProxy *_bt_init_service_proxy(void)
60 {
61         DBusGProxy *proxy;
62
63         g_type_init();
64
65         if (service_conn == NULL) {
66                 service_conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL);
67                 retv_if(service_conn == NULL, NULL);
68         }
69
70         proxy = dbus_g_proxy_new_for_name(service_conn, BT_DBUS_NAME, BT_SERVICE_PATH,
71                         BT_DBUS_NAME);
72
73         if (proxy == NULL) {
74                 dbus_g_connection_unref(service_conn);
75                 service_conn = NULL;
76                 return NULL;
77         }
78
79         service_proxy = proxy;
80
81         return proxy;
82 }
83
84 void _bt_deinit_proxys(void)
85 {
86         __bt_remove_all_sending_requests();
87
88         if (service_proxy) {
89                 g_object_unref(service_proxy);
90                 service_proxy = NULL;
91         }
92
93         if (service_conn) {
94                 dbus_g_connection_unref(service_conn);
95                 service_conn = NULL;
96         }
97
98         if (system_conn) {
99                 dbus_g_connection_unref(system_conn);
100                 system_conn = NULL;
101         }
102 }
103
104 static DBusGProxy *__bt_get_service_proxy(void)
105 {
106         return (service_proxy) ? service_proxy : _bt_init_service_proxy();
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         switch (service_function) {
115         case BT_BOND_DEVICE:
116                 *event_type = BT_ADAPTER_EVENT;
117                 *event = BLUETOOTH_EVENT_BONDING_FINISHED;
118                 ret_if(output == NULL);
119                 *param_data = &g_array_index(output,
120                                 bluetooth_device_info_t, 0);
121                 break;
122         case BT_UNBOND_DEVICE:
123                 *event_type = BT_ADAPTER_EVENT;
124                 *event = BLUETOOTH_EVENT_BONDED_DEVICE_REMOVED;
125                 ret_if(output == NULL);
126                 *param_data = &g_array_index(output,
127                                 bluetooth_device_info_t, 0);
128                 break;
129         case BT_SEARCH_SERVICE:
130                 *event_type = BT_ADAPTER_EVENT;
131                 *event = BLUETOOTH_EVENT_SERVICE_SEARCHED;
132                 ret_if(output == NULL);
133                 *param_data = &g_array_index(output,
134                                 bluetooth_device_info_t, 0);
135                 break;
136         case BT_HID_CONNECT:
137                 *event_type = BT_HID_EVENT;
138                 *event = BLUETOOTH_HID_CONNECTED;
139                 ret_if(output == NULL);
140                 *param_data = &g_array_index(output,
141                                 bluetooth_device_address_t, 0);
142                 break;
143         case BT_HID_DISCONNECT:
144                 *event_type = BT_HID_EVENT;
145                 *event = BLUETOOTH_HID_DISCONNECTED;
146                 ret_if(output == NULL);
147                 *param_data = &g_array_index(output,
148                                 bluetooth_device_address_t, 0);
149                 break;
150         case BT_AUDIO_CONNECT:
151         case BT_AG_CONNECT:
152                 *event_type = BT_HEADSET_EVENT;
153                 *event = BLUETOOTH_EVENT_AG_CONNECTED;
154                 ret_if(output == NULL);
155                 *param_data = &g_array_index(output, char, 0);
156                 break;
157         case BT_AUDIO_DISCONNECT:
158         case BT_AG_DISCONNECT:
159                 *event_type = BT_HEADSET_EVENT;
160                 *event = BLUETOOTH_EVENT_AG_DISCONNECTED;
161                 ret_if(output == NULL);
162                 *param_data = &g_array_index(output, char, 0);
163                 break;
164         case BT_AV_CONNECT:
165                 *event_type = BT_HEADSET_EVENT;
166                 *event = BLUETOOTH_EVENT_AV_CONNECTED;
167                 ret_if(output == NULL);
168                 *param_data = &g_array_index(output, char, 0);
169                 break;
170         case BT_AV_DISCONNECT:
171                 *event_type = BT_HEADSET_EVENT;
172                 *event = BLUETOOTH_EVENT_AV_DISCONNECTED;
173                 ret_if(output == NULL);
174                 *param_data = &g_array_index(output, char, 0);
175                 break;
176         case BT_NETWORK_CONNECT:
177                 *event_type = BT_ADAPTER_EVENT;
178                 *event = BLUETOOTH_EVENT_NETWORK_CONNECTED;
179                 ret_if(output == NULL);
180                 *param_data = &g_array_index(output,
181                                 bluetooth_device_address_t, 0);
182                 break;
183         case BT_NETWORK_DISCONNECT:
184                 *event_type = BT_ADAPTER_EVENT;
185                 *event = BLUETOOTH_EVENT_NETWORK_DISCONNECTED;
186                 ret_if(output == NULL);
187                 *param_data = &g_array_index(output,
188                                 bluetooth_device_address_t, 0);
189                 break;
190         case BT_RFCOMM_CLIENT_CONNECT:
191                 *event_type = BT_RFCOMM_CLIENT_EVENT;
192                 *event = BLUETOOTH_EVENT_RFCOMM_CONNECTED;
193                 ret_if(output == NULL);
194                 *param_data = &g_array_index(output,
195                                 bluetooth_rfcomm_connection_t, 0);
196
197                 break;
198         default:
199                 BT_ERR("Unknown function");
200                 return;
201         }
202 }
203
204 /*
205 out param1: API result
206 out param2: return paramter
207 out param3:
208 */
209 void __send_request_cb(DBusGProxy *proxy, GArray *out_param1,
210                         GArray *out_param2, GError *error,
211                         gpointer userdata)
212 {
213         bluetooth_event_param_t bt_event;
214         bt_req_info_t *cb_data = userdata;
215         int result = BLUETOOTH_ERROR_NONE;
216         int event_type = BT_ADAPTER_EVENT;
217         int request_id;
218
219         memset(&bt_event, 0x00, sizeof(bluetooth_event_param_t));
220
221         if (error != NULL) {
222                 /* dBUS gives error cause */
223                 BT_ERR("D-Bus API failure: message[%s]", error->message);
224                 g_error_free(error);
225                 result = BLUETOOTH_ERROR_TIMEOUT;
226
227                 ret_if(cb_data == NULL);
228
229                 __bt_get_event_info(cb_data->service_function, NULL,
230                                 &bt_event.event, &event_type,
231                                 &bt_event.param_data);
232         } else {
233                 ret_if(out_param2 == NULL);
234
235                 result = g_array_index(out_param2, int, 0);
236
237                 ret_if(cb_data == NULL);
238
239                 __bt_get_event_info(cb_data->service_function, out_param1,
240                                 &bt_event.event, &event_type,
241                                 &bt_event.param_data);
242
243                 if (result == BLUETOOTH_ERROR_NONE) {
244                         if (cb_data->service_function == BT_OPP_PUSH_FILES) {
245                                 request_id = g_array_index(out_param1, int, 0);
246                                 _bt_add_push_request_id(request_id);
247                         }
248
249                         if (out_param1)
250                                 g_array_free(out_param1, FALSE);
251
252                         if (out_param2)
253                                 g_array_free(out_param2, FALSE);
254
255                         goto done;
256                 }
257
258                 if (out_param1)
259                         g_array_free(out_param1, FALSE);
260
261                 if (out_param2)
262                         g_array_free(out_param2, FALSE);
263         }
264
265         if (cb_data->cb == NULL)
266                 goto done;
267
268         /* Only if fail case, call the callback function*/
269         bt_event.result = result;
270
271         if (event_type == BT_ADAPTER_EVENT || event_type == BT_RFCOMM_CLIENT_EVENT) {
272                 ((bluetooth_cb_func_ptr)cb_data->cb)(bt_event.event,
273                                 &bt_event,
274                                 cb_data->user_data);
275         } else if (event_type == BT_HID_EVENT) {
276                 ((hid_cb_func_ptr)cb_data->cb)(bt_event.event,
277                                 (hid_event_param_t *)&bt_event,
278                                 cb_data->user_data);
279         } else if (event_type == BT_HEADSET_EVENT) {
280                 ((bt_audio_func_ptr)cb_data->cb)(bt_event.event,
281                                 (bt_audio_event_param_t *)&bt_event,
282                                 cb_data->user_data);
283         }
284 done:
285         sending_requests = g_slist_remove(sending_requests, (void *)cb_data);
286
287         g_free(cb_data);
288 }
289
290 int _bt_send_request(int service_type, int service_function,
291                         GArray *in_param1, GArray *in_param2,
292                         GArray *in_param3, GArray *in_param4,
293                         GArray **out_param1)
294 {
295         int result = BLUETOOTH_ERROR_NONE;
296         gboolean ret;
297         GError *error = NULL;
298         GArray *in_param5 = NULL;
299         GArray *out_param2 = NULL;
300         DBusGProxy *proxy;
301
302         switch (service_type) {
303         case BT_BLUEZ_SERVICE:
304         case BT_OBEX_SERVICE:
305                 proxy = __bt_get_service_proxy();
306                 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
307
308                 in_param5 = g_array_new(FALSE, FALSE, sizeof(gchar));
309
310                 ret = org_projectx_bt_service_request(proxy,
311                                         service_type, service_function,
312                                         BT_SYNC_REQ, in_param1, in_param2,
313                                         in_param3, in_param4, in_param5,
314                                         out_param1, &out_param2, &error);
315
316                 g_array_free(in_param5, TRUE);
317                 break;
318         default:
319                 BT_ERR("Unknown service type");
320                 return BLUETOOTH_ERROR_INTERNAL;
321         }
322
323         if (out_param2) {
324                 result = g_array_index(out_param2, int, 0);
325                 g_array_free(out_param2, TRUE);
326         } else {
327                 result = BLUETOOTH_ERROR_INTERNAL;
328         }
329
330         if (ret != TRUE) {
331                 /* dBUS-RPC is failed */
332                 BT_ERR("dBUS-RPC is failed");
333
334                 if (error != NULL) {
335                         /* dBUS gives error cause */
336                         BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
337                                error->code, error->message);
338
339                         g_error_free(error);
340                 }
341                 else {
342                         /* dBUS does not give error cause dBUS-RPC is failed */
343                         BT_ERR("error returned was NULL");
344                 }
345
346                 return result;
347         }
348
349         BT_DBG("dBUS RPC is successfully done. type=%d, function=0x%x",
350                         service_type, service_function);
351
352         return result;
353 }
354
355 int _bt_send_request_async(int service_type, int service_function,
356                         GArray *in_param1, GArray *in_param2,
357                         GArray *in_param3, GArray *in_param4,
358                         void *callback, void *user_data)
359 {
360         GArray* in_param5 = NULL;
361         bt_req_info_t *cb_data;
362         DBusGProxy *proxy;
363         DBusGProxyCall *proxy_call;
364
365         cb_data = g_new0(bt_req_info_t, 1);
366
367         cb_data->service_function = service_function;
368         cb_data->cb = callback;
369         cb_data->user_data = user_data;
370
371         switch (service_type) {
372         case BT_BLUEZ_SERVICE:
373         case BT_OBEX_SERVICE:
374                 proxy = __bt_get_service_proxy();
375                 retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
376
377                 dbus_g_proxy_set_default_timeout(proxy, BT_DBUS_TIMEOUT_MAX);
378
379                 in_param5 = g_array_new(FALSE, FALSE, sizeof(gchar));
380
381                 proxy_call = org_projectx_bt_service_request_async(proxy, service_type,
382                         service_function, BT_ASYNC_REQ, in_param1, in_param2,
383                         in_param3, in_param4, in_param5,
384                         (org_projectx_bt_service_request_reply)__send_request_cb,
385                         (gpointer)cb_data);
386
387                 if (proxy_call == NULL) {
388
389                         BT_ERR("dBUS-RPC is failed");
390                         g_array_free(in_param5, TRUE);
391                         g_free(cb_data);
392                         return BLUETOOTH_ERROR_INTERNAL;
393                 }
394
395                 sending_requests = g_slist_append(sending_requests, cb_data);
396
397                 g_array_free(in_param5, TRUE);
398                 break;
399         }
400
401         BT_DBG("dBUS RPC is successfully done. type=%d, function=0x%x",
402                          service_type, service_function);
403
404         return BLUETOOTH_ERROR_NONE;
405 }
406