2 * Copyright (c) 2015 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Atul Rai <a.rai@samsung.com>
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
26 /*bt-service headers */
27 #include "bt-internal-types.h"
28 #include "bt-service-common.h"
29 #include "bt-service-util.h"
30 #include "bt-service-event-receiver.h"
31 #include "bt-request-handler.h"
32 #include "bt-service-event.h"
33 #include "bt-service-core-adapter.h"
34 #include "bt-service-core-device.h"
35 #include "bt-service-device-internal.h"
38 #include <oal-event.h>
39 #include <oal-manager.h>
41 static GSList *paired_list;
42 static GSList *bonded_addr_list;
43 static unsigned int bonded_list_index = 0;
44 static gboolean bonded_list_retrieved = FALSE;
46 static void __bt_service_get_bonded_dev_list(GArray **dev_list)
52 ret_if(NULL == dev_list);
54 for (l = paired_list; NULL != l; l = g_slist_next(l)) {
55 bt_remote_dev_info_t *rem_info = l->data;
56 bluetooth_device_info_t dev_info;
61 _bt_copy_remote_device(rem_info, &dev_info);
62 g_array_append_vals(*dev_list, &dev_info, sizeof(bluetooth_device_info_t));
69 bt_remote_dev_info_t *_bt_service_get_remote_dev_info(const char *address)
74 retv_if(NULL == address, NULL);
76 for (l = paired_list; NULL != l; l = g_slist_next(l)) {
77 bt_remote_dev_info_t *rem_info = l->data;
82 if (!strncasecmp(rem_info->address, address, BT_ADDRESS_STRING_SIZE)) {
83 BT_DBG("Device found");
92 static void __bt_handle_pending_request(int result, int service_function)
96 invocation_info_t *req_info = NULL;
100 /* Get method invocation context */
101 for (l = _bt_get_invocation_list(); l != NULL; l = g_slist_next(l)) {
103 if (req_info == NULL || req_info->service_function != service_function)
106 switch (service_function) {
107 case BT_GET_BONDED_DEVICE: {
109 bt_remote_dev_info_t *rem_info;
110 bluetooth_device_info_t dev_info;
112 address = (char *)req_info->user_data;
114 BT_ERR_C("Unexpected: address is NULL");
118 BT_DBG("BT_GET_BONDED_DEVICE for [%s] found", address);
119 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
120 rem_info = _bt_service_get_remote_dev_info(address);
122 result = BLUETOOTH_ERROR_NONE;
123 _bt_copy_remote_device(rem_info, &dev_info);
124 g_array_append_vals(out_param, &dev_info,
125 sizeof(bluetooth_device_info_t));
127 BT_DBG("Device not found in paired list");
128 result = BLUETOOTH_ERROR_NOT_PAIRED;
131 _bt_service_method_return(req_info->context, out_param, result);
132 _bt_free_info_from_invocation_list(req_info);
133 g_array_free(out_param, TRUE);
136 case BT_GET_BONDED_DEVICES: {
137 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
138 __bt_service_get_bonded_dev_list(&out_param);
139 _bt_service_method_return(req_info->context, out_param, result);
140 _bt_free_info_from_invocation_list(req_info);
141 g_array_free(out_param, TRUE);
144 case BT_GET_IS_ALIAS_SET: {
146 bt_remote_dev_info_t *rem_info;
148 address = (char *)req_info->user_data;
150 BT_ERR_C("Unexpected: address is NULL");
154 BT_DBG("BT_GET_IS_ALIAS_SET for [%s] found", address);
155 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
156 rem_info = _bt_service_get_remote_dev_info(address);
158 result = BLUETOOTH_ERROR_NONE;
159 g_array_append_vals(out_param, &(rem_info->is_alias_set),
162 BT_DBG("Device not found in paired list");
163 result = BLUETOOTH_ERROR_NOT_PAIRED;
166 _bt_service_method_return(req_info->context, out_param, result);
167 _bt_free_info_from_invocation_list(req_info);
168 g_array_free(out_param, TRUE);
171 case BT_GET_CONNECTED_LINK_TYPE: {
173 bt_remote_dev_info_t *rem_info;
175 address = (char *)req_info->user_data;
177 BT_ERR_C("Unexpected: address is NULL");
181 BT_DBG("BT_GET_CONNECTED_LINK_TYPE for [%s] found", address);
182 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
183 rem_info = _bt_service_get_remote_dev_info(address);
185 result = BLUETOOTH_ERROR_NONE;
186 g_array_append_vals(out_param, &(rem_info->connected),
187 sizeof(bluetooth_connected_link_t));
189 BT_DBG("Device not found in paired list");
190 result = BLUETOOTH_ERROR_NOT_PAIRED;
193 _bt_service_method_return(req_info->context, out_param, result);
194 _bt_free_info_from_invocation_list(req_info);
195 g_array_free(out_param, TRUE);
199 BT_ERR_C("Unknown service function %d", service_function);
204 static void __bt_service_fetch_dev_info_for_bonded_addr_list(void)
206 unsigned int count = g_slist_length(bonded_addr_list);
210 BT_INFO("bonded_list_index: %d", bonded_list_index);
211 for (; bonded_list_index < count; bonded_list_index++) {
212 GSList *l = g_slist_nth(bonded_addr_list, bonded_list_index);
213 bluetooth_device_address_t *dev_addr = l->data;
218 if (BLUETOOTH_ERROR_NONE != _bt_device_get_bonded_device_info(dev_addr)) {
219 char address[BT_ADDRESS_STRING_SIZE];
220 _bt_convert_addr_type_to_string(address, dev_addr->addr);
221 BT_ERR("_bt_device_get_bonded_device_info Failed for [%s]", address);
227 /* Retrieval of bonded device list completed */
228 bonded_list_index = 0;
229 bonded_list_retrieved = TRUE;
230 g_slist_free_full(bonded_addr_list, g_free);
231 bonded_addr_list = NULL;
233 /* Send reply if request for BT_GET_BONDED_DEVICES is pending */
234 __bt_handle_pending_request(
235 BLUETOOTH_ERROR_NONE, BT_GET_BONDED_DEVICES);
237 /* Send reply if request for BT_GET_BONDED_DEVICE is pending */
238 __bt_handle_pending_request(
239 BLUETOOTH_ERROR_NONE, BT_GET_BONDED_DEVICE);
241 __bt_handle_pending_request(
242 BLUETOOTH_ERROR_NONE, BT_GET_IS_ALIAS_SET);
243 __bt_handle_pending_request(
244 BLUETOOTH_ERROR_NONE, BT_GET_CONNECTED_LINK_TYPE);
248 static void __bt_update_connected_status(bt_remote_dev_info_t *rem_info, gboolean connected, unsigned char type)
254 switch (rem_info->connected) {
255 case BLUETOOTH_CONNECTED_LINK_NONE:
256 rem_info->connected = BLUETOOTH_CONNECTED_LINK_BREDR;
258 case BLUETOOTH_CONNECTED_LINK_LE:
259 rem_info->connected = BLUETOOTH_CONNECTED_LINK_BREDR_LE;
262 BT_ERR_C("rem_info->connected is already set to desired value: %d",
263 rem_info->connected);
266 switch (rem_info->connected) {
267 case BLUETOOTH_CONNECTED_LINK_NONE:
268 rem_info->connected = BLUETOOTH_CONNECTED_LINK_LE;
270 case BLUETOOTH_CONNECTED_LINK_BREDR:
271 rem_info->connected = BLUETOOTH_CONNECTED_LINK_BREDR_LE;
274 BT_ERR_C("rem_info->connected is already set to desired value: %d",
275 rem_info->connected);
280 switch (rem_info->connected) {
281 case BLUETOOTH_CONNECTED_LINK_BREDR:
282 rem_info->connected = BLUETOOTH_CONNECTED_LINK_NONE;
284 case BLUETOOTH_CONNECTED_LINK_BREDR_LE:
285 rem_info->connected = BLUETOOTH_CONNECTED_LINK_LE;
288 BT_ERR_C("rem_info->connected is already set to desired value: %d",
289 rem_info->connected);
292 switch (rem_info->connected) {
293 case BLUETOOTH_CONNECTED_LINK_LE:
294 rem_info->connected = BLUETOOTH_CONNECTED_LINK_NONE;
296 case BLUETOOTH_CONNECTED_LINK_BREDR_LE:
297 rem_info->connected = BLUETOOTH_CONNECTED_LINK_BREDR;
300 BT_ERR_C("rem_info->connected is already set to desired value: %d",
301 rem_info->connected);
309 void _bt_update_remote_dev_property(
310 const char *address, bt_device_prop_type_e type, void *value)
312 bt_remote_dev_info_t *rem_info;
316 BT_DBG("Property type: %d", type);
317 rem_info = _bt_service_get_remote_dev_info(address);
318 ret_if(NULL == rem_info);
321 case DEV_PROP_CONNECTED: {
322 bt_device_conn_info_t *conn_info = value;
324 __bt_update_connected_status(
325 rem_info, conn_info->connected, conn_info->type);
328 case DEV_PROP_NAME: {
331 if (name && strlen(name) > 0) {
332 g_free(rem_info->name);
333 rem_info->name = g_strdup(name);
337 case DEV_PROP_ALIAS: {
340 g_free(rem_info->alias);
341 rem_info->alias = NULL;
342 rem_info->is_alias_set = FALSE;
344 if (alias && strlen(alias) > 0) {
345 rem_info->alias = g_strdup(alias);
346 rem_info->is_alias_set = TRUE;
350 case DEV_PROP_TRUST: {
351 gboolean *trusted = value;
352 rem_info->trust = *trusted;
355 case DEV_PROP_SERVICES: {
356 bt_remote_dev_info_t *src = value;
358 if (src->uuid_count > 0 && src->uuids) {
361 /* Release previously allocated UUIDs */
362 if (rem_info->uuid_count > 0 && rem_info->uuids)
363 for (i = 0; i < rem_info->uuid_count; i++)
364 g_free(rem_info->uuids[i]);
365 g_free(rem_info->uuids);
367 /* Copy new UUID list */
368 rem_info->uuids = g_malloc0(src->uuid_count * sizeof(char *));
369 for (i = 0; i < src->uuid_count; i++)
370 rem_info->uuids[i] = g_strdup(src->uuids[i]);
372 rem_info->uuid_count = src->uuid_count;
373 BT_DBG("UUID count: %d", rem_info->uuid_count);
378 BT_DBG("Unknown property");
385 void _bt_service_add_device_to_bonded_list(bt_remote_dev_info_t *rem_info)
387 bt_remote_dev_info_t *dev_info;
390 ret_if(NULL == rem_info);
392 dev_info = _bt_service_get_remote_dev_info(rem_info->address);
394 BT_DBG("Device info not present, allocate memory");
395 dev_info = g_malloc0(sizeof(bt_remote_dev_info_t));
396 paired_list = g_slist_append(paired_list, dev_info);
399 _bt_copy_remote_dev_info(dev_info, rem_info);
401 if (!bonded_list_retrieved) {
402 char addr_str[BT_ADDRESS_STRING_SIZE];
403 bluetooth_device_address_t *dev_addr;
406 l = g_slist_nth(bonded_addr_list, bonded_list_index);
408 BT_ERR_C("l is NULL unexpectedly, need to check");
414 BT_ERR_C("dev_addr is NULL unexpectedly, need to check");
418 _bt_convert_addr_type_to_string(addr_str, dev_addr->addr);
419 if (!strncasecmp(addr_str, rem_info->address, BT_ADDRESS_STRING_SIZE)) {
421 __bt_service_fetch_dev_info_for_bonded_addr_list();
428 void _bt_service_remove_device_from_bonded_list(const char *address)
430 bt_remote_dev_info_t *rem_info;
433 ret_if(NULL == address);
435 rem_info = _bt_service_get_remote_dev_info(address);
437 BT_DBG("Device not found in list");
441 paired_list = g_slist_remove(paired_list, rem_info);
442 _bt_free_remote_dev(rem_info);
446 void _bt_device_handle_paired_address_list(bluetooth_device_address_t *addr_list, int count)
452 if (bonded_list_retrieved) {
453 BT_ERR_C("Unexpected bonded address list received");
458 BT_DBG("No paired device found");
459 bonded_list_index = 0;
460 bonded_list_retrieved = TRUE;
464 ret_if(NULL == addr_list);
466 for (indx = 0; indx < count; indx++) {
467 bluetooth_device_address_t *dev_addr;
469 dev_addr = g_memdup(&(addr_list[indx]), sizeof(bluetooth_device_address_t));
470 bonded_addr_list = g_slist_append(bonded_addr_list, dev_addr);
473 __bt_service_fetch_dev_info_for_bonded_addr_list();
477 static gboolean __check_bonded_devices(gpointer data)
481 retv_if(bonded_list_retrieved, FALSE);
483 /* Bonded devices are not yet retrived, retry */
484 if (BLUETOOTH_ERROR_NONE != _bt_adapter_get_bonded_devices())
485 BT_ERR_C("_bt_adapter_get_bonded_devices failed");
491 void _bt_device_handle_adapter_state(gboolean enabled)
496 BT_DBG("Adapter disabled");
497 g_slist_free_full(paired_list, g_free);
499 bonded_list_retrieved = FALSE;
503 if (BLUETOOTH_ERROR_NONE != _bt_adapter_get_bonded_devices())
504 BT_ERR_C("_bt_adapter_get_bonded_devices failed");
506 g_timeout_add_seconds(5, __check_bonded_devices, NULL);
510 static gboolean __reply_pending_request(gpointer data)
514 BT_INFO("Request: %d", *request);
515 __bt_handle_pending_request(BLUETOOTH_ERROR_NONE, *request);
520 int _bt_get_bonded_device_info(bluetooth_device_address_t *dev_addr)
522 char address[BT_ADDRESS_STRING_SIZE];
523 bt_remote_dev_info_t *rem_info;
524 int request = BT_GET_BONDED_DEVICE;
528 retv_if(!dev_addr, BLUETOOTH_ERROR_INVALID_PARAM);
530 if (!bonded_list_retrieved) {
532 * Blonded list retrival is in progress, return BLUETOOTH_ERROR_NONE here.
533 * reply will be sent once bonded list is retrieved completely.
535 return BLUETOOTH_ERROR_NONE;
538 _bt_convert_addr_type_to_string(address, dev_addr->addr);
539 rem_info = _bt_service_get_remote_dev_info(address);
541 BT_ERR("Bonded device not found in the list, return error");
542 return BLUETOOTH_ERROR_NOT_PAIRED;
545 g_idle_add(__reply_pending_request, g_memdup(&request, sizeof(int)));
547 return BLUETOOTH_ERROR_NONE;
550 int _bt_get_bonded_devices(void)
552 int request = BT_GET_BONDED_DEVICES;
555 if (!bonded_list_retrieved) {
557 * Blonded list retrival is in progress, return BLUETOOTH_ERROR_NONE here.
558 * reply will be sent once bonded list is retrieved completely.
560 return BLUETOOTH_ERROR_NONE;
563 g_idle_add(__reply_pending_request, g_memdup(&request, sizeof(int)));
565 return BLUETOOTH_ERROR_NONE;
568 int _bt_is_alias_set(bluetooth_device_address_t *device_address)
570 char address[BT_ADDRESS_STRING_SIZE];
571 bt_remote_dev_info_t *rem_info;
572 int request = BT_GET_IS_ALIAS_SET;
575 if (!bonded_list_retrieved) {
577 * Blonded list retrival is in progress, return BLUETOOTH_ERROR_NONE here.
578 * reply will be sent once bonded list is retrieved completely.
580 return BLUETOOTH_ERROR_NONE;
583 _bt_convert_addr_type_to_string(address, device_address->addr);
584 rem_info = _bt_service_get_remote_dev_info(address);
586 BT_ERR("Bonded device not found in the list, return error");
587 return BLUETOOTH_ERROR_NOT_PAIRED;
590 g_idle_add(__reply_pending_request, g_memdup(&request, sizeof(int)));
592 return BLUETOOTH_ERROR_NONE;
595 int _bt_get_connected_link(bluetooth_device_address_t *device_address)
597 char address[BT_ADDRESS_STRING_SIZE];
598 bt_remote_dev_info_t *rem_info;
599 int request = BT_GET_CONNECTED_LINK_TYPE;
602 if (!bonded_list_retrieved) {
604 * Blonded list retrival is in progress, return BLUETOOTH_ERROR_NONE here.
605 * reply will be sent once bonded list is retrieved completely.
607 return BLUETOOTH_ERROR_NONE;
610 _bt_convert_addr_type_to_string(address, device_address->addr);
611 rem_info = _bt_service_get_remote_dev_info(address);
613 BT_ERR("Bonded device not found in the list, return error");
614 return BLUETOOTH_ERROR_NOT_PAIRED;
617 g_idle_add(__reply_pending_request, g_memdup(&request, sizeof(int)));
619 return BLUETOOTH_ERROR_NONE;
622 gboolean _bt_is_bonded_devices_retrived(void)
624 return bonded_list_retrieved;