4 * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Atul Kumar Rai <a.rai@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
28 #include "bt-internal-types.h"
29 #include "bt-request-handler.h"
30 #include "bt-service-util.h"
31 #include "bt-service-event.h"
32 #include "bt-service-event-receiver.h"
33 #include "bt-service-common.h"
34 #include "bt-service-hidhost.h"
35 #include "bt-service-core-device.h"
36 #include "oal-event.h"
37 #include "oal-device-mgr.h"
38 #include "oal-hid-host.h"
41 char address[BT_ADDRESS_STRING_SIZE];
42 unsigned char num_retries;
45 static GSList *g_connected_list;
47 static gboolean __bt_is_hid_device_connected(const char *address)
53 node = g_connected_list;
54 while (node != NULL) {
55 char *addr_str = node->data;
57 if (g_strcmp0(addr_str, address) == 0) {
58 BT_ERR("Device present in the list");
61 node = g_slist_next(node);
68 static void __bt_add_hid_device_to_connected_list(const char *address)
74 if (TRUE == __bt_is_hid_device_connected(address)) {
75 BT_ERR("Device already present in the list");
79 addr_str = g_strdup(address);
80 g_connected_list = g_slist_append(g_connected_list, addr_str);
84 static void __bt_remove_hid_device_from_connected_list(const char *address)
90 node = g_connected_list;
91 while (node != NULL) {
92 char *addr_str = node->data;
93 if (g_strcmp0(addr_str, address) == 0) {
94 BT_DBG("Address match");
95 g_connected_list = g_slist_remove(g_connected_list, addr_str);
100 node = g_slist_next(node);
106 static void __bt_send_hid_connected(const char *address)
108 int result = BLUETOOTH_ERROR_NONE;
113 if (!__bt_is_hid_device_connected(address)) {
114 BT_ERR("HID device [%s] not connected anymore", address);
118 /* Send HID connected event to Application */
119 param = g_variant_new("(is)", result, address);
120 _bt_send_event(BT_HID_EVENT, BLUETOOTH_HID_CONNECTED, param);
121 BT_PERMANENT_LOG("Connected HID Host");
126 static gboolean __hid_get_bonded_info(gpointer data)
128 bt_hid_wait_data_t *wait_data = data;
131 if ((wait_data->num_retries > 0) && !_bt_is_bonded_devices_retrived()) {
132 wait_data->num_retries--;
136 if (wait_data->num_retries <= 0) {
137 BT_ERR_C("Even after all retries, bonded devices stil not retrieved");
141 BT_DBG("bonded info retrival completed, try to get device info");
142 if (NULL == _bt_service_get_remote_dev_info(wait_data->address)) {
143 BT_ERR_C("Unexpected: _bt_service_get_remote_dev_info() returned NULL");
147 __bt_send_hid_connected(wait_data->address);
155 static void __bt_handle_hid_connection(char *address)
159 ret_if(NULL == address);
160 __bt_add_hid_device_to_connected_list(address);
162 if (!_bt_is_bonded_devices_retrived()) {
163 /* Wait till bonded devices retrival is completed */
164 bt_hid_wait_data_t *wait_data = g_malloc0(sizeof(bt_hid_wait_data_t));
165 g_strlcpy(wait_data->address, address, BT_ADDRESS_STRING_SIZE);
166 wait_data->num_retries = 5;
167 g_timeout_add_seconds(1, __hid_get_bonded_info, (gpointer)wait_data);
171 __bt_send_hid_connected(address);
175 static void __bt_handle_hid_disconnection(char *address)
177 int result = BLUETOOTH_ERROR_NONE;
182 ret_if(NULL == address);
184 /* Remove HID device from connected list */
185 __bt_remove_hid_device_from_connected_list(address);
187 /* Send HID disconnected event to Application */
188 param = g_variant_new("(is)", result, address);
189 _bt_send_event(BT_HID_EVENT, BLUETOOTH_HID_DISCONNECTED, param);
190 BT_PERMANENT_LOG("Disconnected HID Host");
195 static void __bt_hid_event_handler(int event_type, gpointer event_data)
197 bluetooth_device_address_t device_address;
198 char address[BT_ADDRESS_STRING_SIZE];
200 int result = BLUETOOTH_ERROR_NONE;
202 invocation_info_t *req_info;
207 switch (event_type) {
208 case OAL_EVENT_HID_CONNECTED: {
209 event_hid_conn_t *event = event_data;
211 memset(&device_address, 0x00, sizeof(bluetooth_device_address_t));
212 memcpy(device_address.addr, event->address.addr, BLUETOOTH_ADDRESS_LENGTH);
214 memset(address, 0x00, BT_ADDRESS_STRING_SIZE);
215 _bt_convert_addr_type_to_string(address, event->address.addr);
217 /* Reply to async request for HID connect, if any */
218 req_info = _bt_get_request_info_data(BT_HID_CONNECT, address);
219 if (NULL != req_info) {
220 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
221 g_array_append_vals(out_param, &device_address,
222 sizeof(bluetooth_device_address_t));
223 _bt_service_method_return(req_info->context,
225 g_array_free(out_param, TRUE);
226 _bt_free_info_from_invocation_list(req_info);
228 __bt_handle_hid_connection(address);
231 case OAL_EVENT_HID_DISCONNECTED: {
232 event_hid_conn_t *event = event_data;
234 memset(&device_address, 0x00, sizeof(bluetooth_device_address_t));
235 memcpy(device_address.addr, event->address.addr, BLUETOOTH_ADDRESS_LENGTH);
237 memset(address, 0x00, BT_ADDRESS_STRING_SIZE);
238 _bt_convert_addr_type_to_string(address, event->address.addr);
240 BT_INFO("HID device [%s] disconnected", address);
241 req_info = _bt_get_request_info_data(BT_HID_DISCONNECT, address);
242 if (NULL == req_info) {
243 BT_DBG("BT_HID_DISCONNECT request not found");
244 req_info = _bt_get_request_info_data(BT_HID_CONNECT, address);
245 if (NULL == req_info) {
246 BT_DBG("BT_HID_CONNECT request also not found");
247 __bt_handle_hid_disconnection(address);
251 * HID_DISCONNECTED event is received in response to hid_connect,
252 * Set result as BLUETOOTH_ERROR_INTERNAL
254 result = BLUETOOTH_ERROR_INTERNAL;
258 if (OAL_STATUS_SUCCESS != event->status)
259 result = _bt_convert_oal_status_to_bt_error(event->status);
261 if (BLUETOOTH_ERROR_NONE == result)
262 __bt_handle_hid_disconnection(address);
264 if (NULL != req_info) {
265 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
266 g_array_append_vals(out_param, &device_address,
267 sizeof(bluetooth_device_address_t));
268 _bt_service_method_return(req_info->context,
270 g_array_free(out_param, TRUE);
271 _bt_free_info_from_invocation_list(req_info);
276 BT_ERR("Unhandled event: %d", event_type);
282 int _bt_hidhost_initialize()
287 /* Enable HID Profile */
288 result = hid_enable();
289 if (result != OAL_STATUS_SUCCESS) {
290 BT_ERR("HID Enable failed");
291 return _bt_convert_oal_status_to_bt_error(result);
294 /* Register HID event handler */
295 _bt_service_register_event_handler_callback(
296 BT_HID_MODULE, __bt_hid_event_handler);
298 return BLUETOOTH_ERROR_NONE;
301 void _bt_hidhost_deinitialize()
305 /* Unregister HID event handler */
306 _bt_service_unregister_event_handler_callback(BT_HID_MODULE);
308 /* Clear connected device list */
309 g_slist_free_full(g_connected_list, g_free);
310 g_connected_list = NULL;
312 /* Disable HID Profile */
318 int _bt_hid_connect(bluetooth_device_address_t *device_address)
321 char address[BT_ADDRESS_STRING_SIZE];
322 bt_address_t bd_addr;
325 _bt_convert_addr_type_to_string(address, device_address->addr);
326 BT_INFO("HID connect called for [%s]", address);
328 if (TRUE == __bt_is_hid_device_connected(address)) {
329 BT_ERR("HID device already connected");
330 return BLUETOOTH_ERROR_ALREADY_CONNECT;
333 memset(&bd_addr, 0x00, sizeof(bt_address_t));
334 memcpy(bd_addr.addr, device_address->addr, BT_ADDRESS_BYTES_NUM);
336 result = hid_connect(&bd_addr);
337 if (result != OAL_STATUS_SUCCESS) {
338 BT_ERR("hid_connect error: [%d]", result);
339 return _bt_convert_oal_status_to_bt_error(result);
341 return BLUETOOTH_ERROR_NONE;
344 int _bt_hid_disconnect(bluetooth_device_address_t *device_address)
347 char address[BT_ADDRESS_STRING_SIZE];
348 bt_address_t bd_addr;
351 _bt_convert_addr_type_to_string(address, device_address->addr);
352 BT_INFO("HID disconnect called for [%s]", address);
354 memset(&bd_addr, 0x00, sizeof(bt_address_t));
355 memcpy(bd_addr.addr, device_address->addr, BT_ADDRESS_BYTES_NUM);
357 result = hid_disconnect(&bd_addr);
358 if (result != OAL_STATUS_SUCCESS) {
359 BT_ERR("hid_disconnect error: [%d]", result);
360 return _bt_convert_oal_status_to_bt_error(result);
362 return BLUETOOTH_ERROR_NONE;