f9d287b4ee6e156ec7a9cb14a79bb50aca3abfa3
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-audio.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 <dbus/dbus.h>
22 #include <glib.h>
23 #include <dlog.h>
24 #include <string.h>
25 #if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT)
26 #include <syspopup_caller.h>
27 #endif
28
29 #include "bluetooth-api.h"
30 #include "bt-internal-types.h"
31
32 #include "bt-service-audio.h"
33 #include "bt-service-adapter.h"
34 #include "bt-service-common.h"
35 #include "bt-service-event.h"
36 #include "bt-service-util.h"
37
38 typedef struct {
39         unsigned int type;
40         int device_state;
41         char device_address[BT_ADDRESS_STRING_SIZE + 1];
42 } bt_connected_headset_data_t;
43
44 static GList *g_connected_list;
45
46 static bt_headset_wait_t *g_wait_data;
47
48 static void __bt_remove_device_from_wait_list();
49
50 static void __bt_free_wait_data();
51
52 static void __bt_audio_request_cb(DBusGProxy *proxy, DBusGProxyCall *call,
53                                     gpointer user_data)
54 {
55         GError *g_error = NULL;
56         GArray *out_param1 = NULL;
57         GArray *out_param2 = NULL;
58         int result = BLUETOOTH_ERROR_NONE;
59         bt_function_data_t *func_data;
60         request_info_t *req_info;
61
62         dbus_g_proxy_end_call(proxy, call, &g_error, G_TYPE_INVALID);
63
64         g_object_unref(proxy);
65
66         func_data = user_data;
67
68         if (func_data == NULL) {
69                 /* Send reply */
70                 BT_ERR("func_data == NULL");
71                 goto done;
72         }
73
74         req_info = _bt_get_request_info(func_data->req_id);
75         if (req_info == NULL) {
76                 BT_ERR("req_info == NULL");
77                 goto done;
78         }
79
80         if (g_error == NULL)
81                 goto dbus_return;
82
83         BT_ERR("Audio Connect Dbus Call Error: %s\n", g_error->message);
84
85         result = BLUETOOTH_ERROR_INTERNAL;
86
87         /* Remove the device from the list */
88         _bt_remove_headset_from_list(BT_AUDIO_ALL, func_data->address);
89
90         /* Error, check if any waiting device is there */
91         if (g_wait_data == NULL)
92                 goto dbus_return;
93
94         if (g_strcmp0(g_wait_data->address, func_data->address) != 0) {
95                 bluetooth_device_address_t device_address;
96                 _bt_convert_addr_string_to_type(device_address.addr,
97                                                         g_wait_data->address);
98                 _bt_audio_connect(g_wait_data->req_id, g_wait_data->type,
99                                 &device_address, g_wait_data->out_param1);
100         }
101
102         /* Event will be sent by the event reciever */
103 dbus_return:
104         if (req_info->context == NULL)
105                 goto done;
106
107         out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
108         out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
109
110         g_array_append_vals(out_param1, func_data->address,
111                                 BT_ADDRESS_STR_LEN);
112         g_array_append_vals(out_param2, &result, sizeof(int));
113
114         dbus_g_method_return(req_info->context, out_param1, out_param2);
115
116         g_array_free(out_param1, TRUE);
117         g_array_free(out_param2, TRUE);
118
119         _bt_delete_request_list(req_info->req_id);
120 done:
121         if (g_error)
122                 g_error_free(g_error);
123
124         if (func_data) {
125                 g_free(func_data->address);
126                 g_free(func_data);
127         }
128 }
129
130 static char *__bt_get_audio_path(bluetooth_device_address_t *address)
131 {
132
133         char *object_path = NULL;
134         char addr_str[BT_ADDRESS_STRING_SIZE + 1] = { 0 };
135         DBusGProxy *audio_proxy;
136         DBusGProxy *adapter_proxy;
137         DBusGConnection *g_conn;
138
139         retv_if(address == NULL, NULL);
140
141         g_conn = _bt_get_system_gconn();
142         retv_if(g_conn == NULL, NULL);
143
144         adapter_proxy = _bt_get_adapter_proxy();
145         retv_if(adapter_proxy == NULL, NULL);
146
147         _bt_convert_addr_type_to_string(addr_str, address->addr);
148
149         object_path = _bt_get_device_object_path(addr_str);
150
151         retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_FOUND);
152
153         audio_proxy = dbus_g_proxy_new_for_name(g_conn,
154                                         BT_BLUEZ_NAME,
155                                         object_path,
156                                         BT_HFP_AGENT_INTERFACE);
157
158         retv_if(audio_proxy == NULL, NULL);
159
160         g_object_unref(audio_proxy);
161
162         return object_path;
163 }
164
165 static char *__bt_get_connected_audio_path(void)
166 {
167         int i;
168         guint size;
169         char *audio_path = NULL;
170         GArray *device_list;
171         bluetooth_device_info_t info;
172
173         /* allocate the g_pointer_array */
174         device_list = g_array_new(FALSE, FALSE, sizeof(gchar));
175
176         if (_bt_get_bonded_devices(&device_list)
177                                         != BLUETOOTH_ERROR_NONE) {
178                 g_array_free(device_list, TRUE);
179                 return NULL;
180         }
181
182         size = (device_list->len) / sizeof(bluetooth_device_info_t);
183
184         for (i = 0; i < size; i++) {
185
186                 info = g_array_index(device_list,
187                                 bluetooth_device_info_t, i);
188
189                 if (info.connected == TRUE) {
190                         audio_path = __bt_get_audio_path(&info.device_address);
191                         if (audio_path)
192                                 break;
193                 }
194         }
195
196         g_array_free(device_list, TRUE);
197
198         return audio_path;
199 }
200
201 static void __bt_free_wait_data()
202 {
203         if (g_wait_data != NULL) {
204                 g_free(g_wait_data->address);
205                 g_free(g_wait_data);
206                 g_wait_data = NULL;
207         }
208 }
209
210 static void __bt_remove_device_from_wait_list()
211 {
212         /* Before deleting the request update the UI */
213         GArray *out_param_1 = NULL;
214         GArray *out_param_2 = NULL;
215         int result = BLUETOOTH_ERROR_INTERNAL;
216         request_info_t *req_info;
217
218         req_info = _bt_get_request_info(g_wait_data->req_id);
219         if (req_info == NULL) {
220                 BT_ERR("req_info == NULL");
221                 return;
222         }
223
224         out_param_1 = g_array_new(FALSE, FALSE, sizeof(gchar));
225         out_param_2 = g_array_new(FALSE, FALSE, sizeof(gchar));
226         g_array_append_vals(out_param_1, g_wait_data->address,
227                                 BT_ADDRESS_STR_LEN);
228         g_array_append_vals(out_param_2, &result, sizeof(int));
229         dbus_g_method_return(req_info->context,
230                                 out_param_1, out_param_2);
231         g_array_free(out_param_1, TRUE);
232         g_array_free(out_param_2, TRUE);
233         _bt_delete_request_list(g_wait_data->req_id);
234 }
235
236 static void __bt_set_headset_disconnection_type(const char *address)
237 {
238         bt_connected_headset_data_t *connected_device;
239         GList *node;
240
241         BT_DBG("__bt_set_headset_disconnection_type \n");
242
243         node = g_list_first(g_connected_list);
244         while (node != NULL) {
245                 connected_device = node->data;
246                 if (g_strcmp0(connected_device->device_address, address) == 0) {
247                         g_wait_data->disconnection_type = connected_device->type;
248                         return;
249                 }
250                 node = g_list_next(node);
251         }
252 }
253
254 gboolean _bt_is_headset_type_connected(int type, char *address)
255 {
256         GList *node;
257
258         BT_DBG("_bt_is_headset_type_connected \n");
259
260         node = g_list_first(g_connected_list);
261         while (node != NULL) {
262                 bt_connected_headset_data_t *connected_device = node->data;
263
264                 if (connected_device->type & type) {
265                         if (address != NULL)
266                                 g_strlcpy(address, connected_device->device_address,
267                                                 BT_ADDRESS_STRING_SIZE + 1);
268                         return TRUE;
269                 }
270
271                 node = g_list_next(node);
272         }
273         return FALSE;
274 }
275
276 static gboolean __bt_is_headset_connected(int type, int req_id,
277                                 const char *address, GArray **out_param1)
278 {
279         gboolean connected;
280         char connected_address[BT_ADDRESS_STRING_SIZE + 1];
281         bluetooth_device_address_t device_address;
282
283         BT_DBG("__bt_is_headset_connected \n");
284
285         /* Check if any other headset is connected */
286         connected = _bt_is_headset_type_connected(type, connected_address);
287
288         if (!connected)
289                 return FALSE;
290
291         /* If already one device is waiting, remove current waiting device and add new */
292         if (g_wait_data != NULL) {
293                 if (g_strcmp0(g_wait_data->address, address) != 0) {
294                         __bt_remove_device_from_wait_list();
295                         __bt_free_wait_data();
296                 }
297         }
298
299         if (g_wait_data == NULL) {
300                 g_wait_data = g_malloc0(sizeof(bt_headset_wait_t));
301                 g_wait_data->address = g_strdup(address);
302                 g_wait_data->req_id = req_id;
303                 g_wait_data->type = type;
304                 g_wait_data->ag_flag = FALSE;
305                 g_wait_data->out_param1 = out_param1;
306
307                 /* Set disconnection type */
308                 __bt_set_headset_disconnection_type(connected_address);
309         }
310
311         /* Convert BD adress from string type */
312         _bt_convert_addr_string_to_type(device_address.addr, connected_address);
313         _bt_audio_disconnect(0, type, &device_address, NULL);
314         return TRUE;
315 }
316
317 void _bt_set_audio_wait_data_flag(gboolean flag)
318 {
319         BT_DBG("_bt_set_audio_wait_data_flag \n");
320         g_wait_data->ag_flag = flag;
321 }
322
323 bt_headset_wait_t *_bt_get_audio_wait_data(void)
324 {
325         BT_DBG("_bt_get_audio_wait_data \n");
326         return g_wait_data;
327 }
328
329 void _bt_add_headset_to_list(int type, int status, const char *address)
330 {
331         bt_connected_headset_data_t *connected_device;
332         bt_connected_headset_data_t *device;
333         GList *node;
334
335         BT_DBG("_bt_add_headset_to_list \n");
336
337         node = g_list_first(g_connected_list);
338         while (node != NULL) {
339                 device = (bt_connected_headset_data_t *)node->data;
340
341                 if (g_strcmp0(device->device_address, address) == 0) {
342                         BT_DBG("Address match, update connection type \n");
343                         device->type |= type;
344                         device->device_state = status;
345                         return;
346                 }
347                 node = g_list_next(node);
348         }
349
350         connected_device = g_malloc0(sizeof(bt_connected_headset_data_t));
351         connected_device->type |= type;
352         connected_device->device_state = status;
353         g_strlcpy(connected_device->device_address, address,
354                                 sizeof(connected_device->device_address));
355         g_connected_list = g_list_append(g_connected_list, connected_device);
356 }
357
358 void _bt_remove_headset_from_list(int type, const char *address)
359 {
360         GList *node;
361
362         BT_DBG("_bt_remove_headset_from_list \n");
363
364         node = g_list_first(g_connected_list);
365         while (node != NULL) {
366                 bt_connected_headset_data_t *connected_device = node->data;
367
368                 if (g_strcmp0(connected_device->device_address, address) != 0) {
369                         node = g_list_next(node);
370                         continue;
371                 }
372
373                 BT_DBG("Address match \n");
374
375                 BT_DBG("Connection type = %x\n", connected_device->type);
376
377                 switch (type) {
378                 case BT_AUDIO_A2DP:
379                         if (connected_device->type & BT_AUDIO_A2DP)
380                                 connected_device->type &= ~(BT_AUDIO_A2DP);
381                         break;
382                 case BT_AUDIO_HSP:
383                         if (connected_device->type & BT_AUDIO_HSP)
384                                 connected_device->type &= ~(BT_AUDIO_HSP);
385                         break;
386                 case BT_AUDIO_ALL:
387                         if (connected_device->type & BT_AUDIO_ALL)
388                                 connected_device->type &= ~(BT_AUDIO_ALL);
389                         break;
390                 }
391
392                 BT_DBG("Connection type = %x\n", connected_device->type);
393
394                 if (connected_device->type == 0x00) {
395                         g_connected_list = g_list_remove(g_connected_list, connected_device);
396                         g_free(connected_device);
397                 }
398
399                 node = g_list_next(node);
400         }
401 }
402
403 int _bt_audio_connect(int request_id, int type,
404                 bluetooth_device_address_t *device_address,
405                 GArray **out_param1)
406 {
407         int result = BLUETOOTH_ERROR_NONE;
408         gchar *device_path = NULL;
409         char *uuid = NULL;
410         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
411         bt_function_data_t *func_data;
412         DBusGProxy *adapter_proxy;
413         DBusGProxy *profile_proxy;
414         DBusGConnection *g_conn;
415
416         BT_CHECK_PARAMETER(device_address, return);
417
418         _bt_convert_addr_type_to_string(address, device_address->addr);
419
420         switch (type) {
421         case BT_AUDIO_HSP:
422                 uuid = HFP_HS_UUID;
423                 break;
424         case BT_AUDIO_A2DP:
425                 uuid = A2DP_SINK_UUID;
426                 break;
427         case BT_AUDIO_ALL:
428                 uuid = GENERIC_AUDIO_UUID;
429                 break;
430         default:
431                 BT_ERR("Unknown role");
432                 result = BLUETOOTH_ERROR_INTERNAL;
433                 goto fail;
434         }
435
436         if (__bt_is_headset_connected(type, request_id, address, out_param1))
437                 return BLUETOOTH_ERROR_NONE;
438
439         adapter_proxy = _bt_get_adapter_proxy();
440         if (adapter_proxy == NULL) {
441                 result = BLUETOOTH_ERROR_INTERNAL;
442                 goto fail;
443         }
444
445         device_path = _bt_get_device_object_path(address);
446         if (device_path == NULL) {
447                 result = BLUETOOTH_ERROR_INTERNAL;
448                 goto fail;
449         }
450
451         g_conn = _bt_get_system_gconn();
452         if (g_conn == NULL) {
453                 result = BLUETOOTH_ERROR_INTERNAL;
454                 goto fail;
455         }
456
457         profile_proxy = dbus_g_proxy_new_for_name(g_conn, BT_BLUEZ_NAME,
458                                         device_path, BT_DEVICE_INTERFACE);
459
460         g_free(device_path);
461
462         if (profile_proxy == NULL) {
463                 result = BLUETOOTH_ERROR_INTERNAL;
464                 goto fail;
465         }
466
467         func_data = g_malloc0(sizeof(bt_function_data_t));
468         func_data->address = g_strdup(address);
469         func_data->req_id = request_id;
470
471         if (g_strcmp0(uuid, GENERIC_AUDIO_UUID) == 0){
472                 if (!dbus_g_proxy_begin_call(profile_proxy, "Connect",
473                                 (DBusGProxyCallNotify)__bt_audio_request_cb,
474                                 func_data, NULL,
475                                 G_TYPE_INVALID)) {
476                         BT_ERR("Audio connect Dbus Call Error");
477                         g_object_unref(profile_proxy);
478
479                         g_free(func_data->address);
480                         g_free(func_data);
481
482                         result = BLUETOOTH_ERROR_INTERNAL;
483                         goto fail;
484                 }
485         }else {
486                 if (!dbus_g_proxy_begin_call(profile_proxy, "ConnectProfile",
487                                 (DBusGProxyCallNotify)__bt_audio_request_cb,
488                                 func_data, NULL,
489                                 G_TYPE_STRING, uuid,
490                                 G_TYPE_INVALID)) {
491                         BT_ERR("Audio connect Dbus Call Error");
492                         g_object_unref(profile_proxy);
493
494                         g_free(func_data->address);
495                         g_free(func_data);
496
497                         result = BLUETOOTH_ERROR_INTERNAL;
498                         goto fail;
499                 }
500         }
501         /* Add data to the connected list */
502         _bt_add_headset_to_list(type, BT_STATE_CONNECTING, address);
503         __bt_free_wait_data();
504
505         return BLUETOOTH_ERROR_NONE;
506 fail:
507         g_array_append_vals(*out_param1, address,
508                                 BT_ADDRESS_STR_LEN);
509
510         return result;
511 }
512
513 int _bt_audio_disconnect(int request_id, int type,
514                 bluetooth_device_address_t *device_address,
515                 GArray **out_param1)
516 {
517         int result = BLUETOOTH_ERROR_NONE;
518         gchar *device_path = NULL;
519         char *uuid = NULL;
520         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
521         bt_function_data_t *func_data;
522         DBusGProxy *adapter_proxy;
523         DBusGProxy *profile_proxy;
524         DBusGConnection *g_conn;
525
526         BT_CHECK_PARAMETER(device_address, return);
527
528         _bt_convert_addr_type_to_string(address, device_address->addr);
529
530         switch (type) {
531         case BT_AUDIO_HSP:
532                 uuid = HFP_HS_UUID;
533                 break;
534         case BT_AUDIO_A2DP:
535                 uuid = A2DP_SINK_UUID;
536                 break;
537         case BT_AUDIO_ALL:
538                 uuid = GENERIC_AUDIO_UUID;
539                 break;
540         default:
541                 BT_ERR("Unknown role");
542                 return BLUETOOTH_ERROR_INTERNAL;
543         }
544
545         adapter_proxy = _bt_get_adapter_proxy();
546         if (adapter_proxy == NULL) {
547                 result = BLUETOOTH_ERROR_INTERNAL;
548                 goto fail;
549         }
550
551         device_path = _bt_get_device_object_path(address);
552         if (device_path == NULL) {
553                 result = BLUETOOTH_ERROR_INTERNAL;
554                 goto fail;
555         }
556
557         g_conn = _bt_get_system_gconn();
558         if (g_conn == NULL) {
559                 result = BLUETOOTH_ERROR_INTERNAL;
560                 goto fail;
561         }
562
563         profile_proxy = dbus_g_proxy_new_for_name(g_conn, BT_BLUEZ_NAME,
564                                         device_path, BT_DEVICE_INTERFACE);
565
566         g_free(device_path);
567
568         if (profile_proxy == NULL) {
569                 result = BLUETOOTH_ERROR_INTERNAL;
570                 goto fail;
571         }
572
573         if (g_wait_data != NULL) {
574                 if (g_strcmp0(uuid, GENERIC_AUDIO_UUID) == 0){
575                         if (!dbus_g_proxy_begin_call(profile_proxy,
576                                 "Disconnect",NULL, NULL, NULL,
577                                 G_TYPE_INVALID)) {
578                                 BT_ERR("Audio disconnect Dbus Call Error");
579                                 g_object_unref(profile_proxy);
580                                 return BLUETOOTH_ERROR_INTERNAL;
581                         }
582                 } else {
583                         if (!dbus_g_proxy_begin_call(profile_proxy,
584                                 "DisconnectProfile",NULL, NULL, NULL,
585                                 G_TYPE_STRING, uuid,
586                                 G_TYPE_INVALID)) {
587                                 BT_ERR("Audio disconnect Dbus Call Error");
588                                 g_object_unref(profile_proxy);
589                                 return BLUETOOTH_ERROR_INTERNAL;
590                         }
591                 }
592         } else {
593                 func_data = g_malloc0(sizeof(bt_function_data_t));
594                 func_data->address = g_strdup(address);
595                 func_data->req_id = request_id;
596                 if (g_strcmp0(uuid, GENERIC_AUDIO_UUID) == 0){
597                         if (!dbus_g_proxy_begin_call(profile_proxy,
598                                 "Disconnect",
599                                 (DBusGProxyCallNotify)__bt_audio_request_cb,
600                                 func_data, NULL,
601                                 G_TYPE_INVALID)) {
602                                 BT_ERR("Audio disconnect Dbus Call Error");
603                                 g_object_unref(profile_proxy);
604
605                                 g_free(func_data->address);
606                                 g_free(func_data);
607
608                                 result = BLUETOOTH_ERROR_INTERNAL;
609                                 goto fail;
610                         }
611                 } else {
612                         if (!dbus_g_proxy_begin_call(profile_proxy,
613                                 "DisconnectProfile",
614                                 (DBusGProxyCallNotify)__bt_audio_request_cb,
615                                 func_data, NULL,
616                                 G_TYPE_STRING, uuid,
617                                 G_TYPE_INVALID)) {
618                                 BT_ERR("Audio disconnect Dbus Call Error");
619                                 g_object_unref(profile_proxy);
620
621                                 g_free(func_data->address);
622                                 g_free(func_data);
623
624                                 result = BLUETOOTH_ERROR_INTERNAL;
625                                 goto fail;
626                         }
627                 }
628         }
629
630         return BLUETOOTH_ERROR_NONE;
631 fail:
632         g_array_append_vals(*out_param1, address,
633                                 BT_ADDRESS_STR_LEN);
634
635         return result;
636 }
637
638 int _bt_audio_get_speaker_gain(unsigned int *gain)
639 {
640         char *device_path = NULL;
641         DBusGProxy *adapter_proxy;
642         DBusGProxy *profile_proxy;
643         DBusGConnection *g_conn;
644         GHashTable *hash = NULL;
645         GValue *value;
646
647         adapter_proxy = _bt_get_adapter_proxy();
648         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
649
650         g_conn = _bt_get_system_gconn();
651         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
652
653         device_path = __bt_get_connected_audio_path();
654         retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
655
656         profile_proxy = dbus_g_proxy_new_for_name(g_conn, BT_BLUEZ_NAME,
657                                       device_path, BT_HFP_AGENT_INTERFACE);
658
659         g_free(device_path);
660
661         retv_if(profile_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
662
663         dbus_g_proxy_call(profile_proxy, "GetProperties", NULL,
664                         G_TYPE_INVALID,
665                         dbus_g_type_get_map("GHashTable",
666                         G_TYPE_STRING, G_TYPE_VALUE),
667                         &hash, G_TYPE_INVALID);
668
669         g_object_unref(profile_proxy);
670
671         retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL);
672
673         value = g_hash_table_lookup(hash, "SpeakerGain");
674         *gain = value ? g_value_get_uint(value) : 0;
675         g_hash_table_destroy(hash);
676         return BLUETOOTH_ERROR_NONE;
677 }
678
679 int _bt_audio_set_speaker_gain(unsigned int gain)
680 {
681         char *device_path = NULL;
682         char *gain_str = "SpeakerGain";
683         char sig[2] = {DBUS_TYPE_UINT16, '\0'};
684         int ret = BLUETOOTH_ERROR_NONE;
685         DBusMessage *msg;
686         DBusMessageIter iter;
687         DBusMessageIter value;
688         DBusConnection *conn;
689
690         conn = _bt_get_system_conn();
691         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
692
693         device_path = __bt_get_connected_audio_path();
694         retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
695
696         msg = dbus_message_new_method_call(BT_BLUEZ_NAME,
697                         device_path, BT_HFP_AGENT_INTERFACE,
698                         "SetProperty");
699
700         g_free(device_path);
701
702         retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
703
704         dbus_message_iter_init_append(msg, &iter);
705         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
706                         &gain_str);
707         dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
708                         sig, &value);
709         dbus_message_iter_append_basic(&value, DBUS_TYPE_UINT16,
710                         &gain);
711         dbus_message_iter_close_container(&iter, &value);
712
713         if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_CALL)
714                 dbus_message_set_no_reply(msg, TRUE);
715
716         if (!dbus_connection_send(conn, msg, NULL)) {
717                 BT_ERR("Dbus sending failed\n");
718                 ret = BLUETOOTH_ERROR_INTERNAL;
719         }
720         dbus_message_unref(msg);
721
722         return ret;
723 }