Disallow HFP multi connection
[platform/core/connectivity/bluetooth-frwk.git] / bt-service-adaptation / services / audio / hf / bt-service-hf-client.c
1 /*
2  * Bluetooth-frwk
3  *
4  * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
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 <sys/errno.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <vconf.h>
24
25 #include "oal-hardware.h"
26 #include "oal-manager.h"
27 #include "oal-audio-src.h"
28 #include "oal-device-mgr.h"
29 #include "oal-hf-client.h"
30 #include "bt-service-common.h"
31
32 #include <bt-service-audio-common.h>
33 #include <bt-service-hf-client.h>
34 #include <bt-service-event.h>
35
36 static void __bt_reply_hf_client_disconnection_pending_request(bt_address_t *address)
37 {
38         char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
39         bluetooth_device_address_t device_address;
40         GArray *out_param;
41         invocation_info_t *req_info;
42         int result = BLUETOOTH_ERROR_NONE;
43
44         ret_if(NULL == address);
45
46         memcpy(device_address.addr, address->addr, BLUETOOTH_ADDRESS_LENGTH);
47         _bt_convert_addr_type_to_string(addr, address->addr);
48
49         BT_DBG("HF Client Disconnection remote device [%s]", addr);
50
51         /* Find Async request information*/
52         req_info = _bt_get_request_info_data(BT_HF_DISCONNECT, addr);
53         if (NULL == req_info) {
54                 BT_INFO("HF DisConnect request not found or possibly already replied..");
55
56                 /* if HF Connect call fails on Bluez DBUS, Async callback from bluez will be received
57                    __bt_hf_client_connect_cb) which will internally trigger HF DISCONNECTED event */
58                 req_info = _bt_get_request_info_data(BT_HF_CONNECT, addr);
59                 if (NULL == req_info) {
60                         BT_DBG("HF Connect request not found..");
61                         return;
62                 } else {
63                         BT_DBG("HF Connect request found..reply this request");
64                 }
65         } else {
66                 BT_DBG("HF DisConnect request found..reply this request");
67         }
68
69         /* In any of the above cases, reply DBUS context */
70         out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
71         g_array_append_vals(out_param, &device_address, sizeof(bluetooth_device_address_t));
72         _bt_service_method_return(req_info->context, out_param, result);
73         g_array_free(out_param, TRUE);
74         _bt_free_info_from_invocation_list(req_info);
75 }
76
77 static void __bt_reply_hf_client_connection_pending_request(bt_address_t *address)
78 {
79         char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
80         bluetooth_device_address_t device_address;
81         GArray *out_param;
82         invocation_info_t *req_info;
83         int result = BLUETOOTH_ERROR_NONE;
84
85         ret_if(NULL == address);
86
87         memcpy(device_address.addr, address->addr, BLUETOOTH_ADDRESS_LENGTH);
88         _bt_convert_addr_type_to_string(addr, address->addr);
89
90         BT_DBG("HF Client Connection remote device [%s]", addr);
91
92         /* Find Async request information*/
93         req_info = _bt_get_request_info_data(BT_HF_CONNECT, addr);
94         if (NULL == req_info) {
95                 BT_DBG("HF Connect request not found or possibly already replied..");
96                 return;
97
98         } else {
99                 BT_DBG("HF Connect request found..");
100         }
101
102         /* In any of the above cases, reply DBUS context */
103         out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
104         g_array_append_vals(out_param, &device_address, sizeof(bluetooth_device_address_t));
105         _bt_service_method_return(req_info->context, out_param, result);
106         g_array_free(out_param, TRUE);
107         _bt_free_info_from_invocation_list(req_info);
108
109 }
110
111
112 /* This event handler process events for HF Client role */
113 void _bt_hf_client_event_handler(int oal_event, gpointer event_data)
114 {
115         bt_address_t *bt_addr = event_data;
116         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
117
118         switch (oal_event) {
119         case OAL_EVENT_HF_CLIENT_DISCONNECTED:
120                 /* Reply to async request for HF Client connect or disconnect request, if any */
121                 BT_INFO("HF client Profile disconnected, reply pending DBUS request and check waiting device");
122                 __bt_reply_hf_client_disconnection_pending_request(bt_addr);
123                 BT_PERMANENT_LOG("Disconnected HF");
124
125                 _bt_convert_addr_type_to_string(address, bt_addr->addr);
126                 _bt_remove_headset_from_list(BT_AUDIO_AG, address);
127                 break;
128         case OAL_EVENT_HF_CLIENT_CONNECTED:
129                 BT_INFO("HF Client Profile connected, Event & DBUS context will be handled at finalizing SCO connect..");
130                 __bt_reply_hf_client_connection_pending_request(bt_addr);
131                 BT_PERMANENT_LOG("Connected HF");
132
133                 _bt_convert_addr_type_to_string(address, bt_addr->addr);
134                 _bt_add_headset_to_list(BT_AUDIO_AG, BT_STATE_CONNECTED, address);
135                 break;
136         case OAL_EVENT_HF_CLIENT_CONNECTING:
137                 BT_INFO("HF Client Profile connection successful, wait for Audio connect..");
138                 break;
139         case OAL_EVENT_HF_CLIENT_DISCONNECTING:
140                 BT_INFO("HF Client Connecting or Disconnecting..No need to send event to app");
141                 break;
142         default:
143                 break;
144         }
145 }
146
147 int _bt_connect_remote_ag(bluetooth_device_address_t *device_address)
148 {
149         oal_status_t status = OAL_STATUS_SUCCESS;
150         int result = BLUETOOTH_ERROR_NONE;
151         gboolean is_connected = FALSE;
152
153         is_connected = device_get_svc_conn_state((bt_address_t*)device_address, HFP_SERVICE_ID);
154         if (is_connected == TRUE) {
155                 BT_ERR("HF Client is already connected");
156                 return BLUETOOTH_ERROR_ALREADY_CONNECT;
157         }
158
159         status = hf_client_connect((bt_address_t *)device_address);
160         if (status != OAL_STATUS_SUCCESS) {
161                 BT_ERR("HF Client Connection could not be established, err: [%d]", status);
162                 result = _bt_convert_oal_status_to_bt_error(status);
163         }
164         return result;
165 }
166
167 int _bt_disconnect_remote_ag(bluetooth_device_address_t *device_address)
168 {
169         oal_status_t status = OAL_STATUS_SUCCESS;
170         int result = BLUETOOTH_ERROR_NONE;
171
172         status = hf_client_disconnect((bt_address_t *)device_address);
173         if (status != OAL_STATUS_SUCCESS) {
174                 BT_ERR("HF Client DisConnection err: [%d]", status);
175                 result = _bt_convert_oal_status_to_bt_error(status);
176         }
177         return result;
178 }
179