5c859fdf64c92daf54aa9e461f158cbeef43be8f
[platform/core/connectivity/bluetooth-frwk.git] / bt-service-adaptation / services / device / bt-service-bonded-device.c
1 /*
2  * Copyright (c) 2015 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Contact: Atul Rai <a.rai@samsung.com>
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 <stdio.h>
21 #include <gio/gio.h>
22 #include <glib.h>
23 #include <dlog.h>
24 #include <string.h>
25
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"
36
37 /* OAL headers */
38 #include <oal-event.h>
39 #include <oal-manager.h>
40
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;
45
46 static void __bt_service_get_bonded_dev_list(GArray **dev_list)
47 {
48         GSList *l;
49
50         BT_DBG("+");
51
52         ret_if(NULL == dev_list);
53
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;
57
58                 if (!rem_info)
59                         continue;
60
61                 _bt_copy_remote_device(rem_info, &dev_info);
62                 g_array_append_vals(*dev_list, &dev_info, sizeof(bluetooth_device_info_t));
63         }
64
65         BT_DBG("+");
66         return;
67 }
68
69 bt_remote_dev_info_t *_bt_service_get_remote_dev_info(const char *address)
70 {
71         GSList *l;
72
73         BT_DBG("+");
74         retv_if(NULL == address, NULL);
75
76         for (l = paired_list; NULL != l; l = g_slist_next(l)) {
77                 bt_remote_dev_info_t *rem_info = l->data;
78
79                 if (!rem_info)
80                         continue;
81
82                 if (!strncasecmp(rem_info->address, address, BT_ADDRESS_STRING_SIZE)) {
83                         BT_DBG("Device found");
84                         return rem_info;
85                 }
86         }
87
88         BT_DBG("-");
89         return NULL;
90 }
91
92 static void __bt_handle_pending_request(int result, int service_function)
93 {
94         GSList *l;
95         GArray *out_param;
96         invocation_info_t *req_info = NULL;
97
98         BT_DBG("+");
99
100         /* Get method invocation context */
101         for (l = _bt_get_invocation_list(); l != NULL; l = g_slist_next(l)) {
102                 req_info = l->data;
103                 if (req_info == NULL || req_info->service_function != service_function)
104                         continue;
105
106                 switch (service_function) {
107                 case BT_GET_BONDED_DEVICE: {
108                         char *address;
109                         bt_remote_dev_info_t *rem_info;
110                         bluetooth_device_info_t dev_info;
111
112                         address = (char *)req_info->user_data;
113                         if (!address) {
114                                 BT_ERR_C("Unexpected: address is NULL");
115                                 continue;
116                         }
117
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);
121                         if (rem_info) {
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));
126                         } else {
127                                 BT_DBG("Device not found in paired list");
128                                 result = BLUETOOTH_ERROR_NOT_PAIRED;
129                         }
130
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);
134                         break;
135                 }
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);
142                         break;
143                 }
144                 case BT_GET_IS_ALIAS_SET: {
145                         char *address;
146                         bt_remote_dev_info_t *rem_info;
147
148                         address = (char *)req_info->user_data;
149                         if (!address) {
150                                 BT_ERR_C("Unexpected: address is NULL");
151                                 continue;
152                         }
153
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);
157                         if (rem_info) {
158                                 result = BLUETOOTH_ERROR_NONE;
159                                 g_array_append_vals(out_param, &(rem_info->is_alias_set),
160                                                 sizeof(gboolean));
161                         } else {
162                                 BT_DBG("Device not found in paired list");
163                                 result = BLUETOOTH_ERROR_NOT_PAIRED;
164                         }
165
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);
169                         break;
170                 }
171                 case BT_GET_CONNECTED_LINK_TYPE: {
172                         char *address;
173                         bt_remote_dev_info_t *rem_info;
174
175                         address = (char *)req_info->user_data;
176                         if (!address) {
177                                 BT_ERR_C("Unexpected: address is NULL");
178                                 continue;
179                         }
180
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);
184                         if (rem_info) {
185                                 result = BLUETOOTH_ERROR_NONE;
186                                 g_array_append_vals(out_param, &(rem_info->connected),
187                                                 sizeof(bluetooth_connected_link_t));
188                         } else {
189                                 BT_DBG("Device not found in paired list");
190                                 result = BLUETOOTH_ERROR_NOT_PAIRED;
191                         }
192
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);
196                         break;
197                 }
198                 default:
199                         BT_ERR_C("Unknown service function %d", service_function);
200                 }
201         }
202 }
203
204 static void __bt_service_fetch_dev_info_for_bonded_addr_list(void)
205 {
206         unsigned int count = g_slist_length(bonded_addr_list);
207
208         BT_DBG("+");
209
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;
214
215                 if (!dev_addr)
216                         continue;
217
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);
222                         continue;
223                 }
224                 return;
225         }
226
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;
232
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);
236
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);
240
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);
245         BT_DBG("-");
246 }
247
248 static void __bt_update_connected_status(bt_remote_dev_info_t *rem_info, gboolean connected, unsigned char type)
249 {
250         BT_DBG("+");
251
252         if (connected) {
253                 if (0 == type) {
254                         switch (rem_info->connected) {
255                         case BLUETOOTH_CONNECTED_LINK_NONE:
256                                 rem_info->connected = BLUETOOTH_CONNECTED_LINK_BREDR;
257                                 break;
258                         case BLUETOOTH_CONNECTED_LINK_LE:
259                                 rem_info->connected = BLUETOOTH_CONNECTED_LINK_BREDR_LE;
260                                 break;
261                         default:
262                                 BT_ERR_C("rem_info->connected is already set to desired value: %d",
263                                                 rem_info->connected);
264                         }
265                 } else {
266                         switch (rem_info->connected) {
267                         case BLUETOOTH_CONNECTED_LINK_NONE:
268                                 rem_info->connected = BLUETOOTH_CONNECTED_LINK_LE;
269                                 break;
270                         case BLUETOOTH_CONNECTED_LINK_BREDR:
271                                 rem_info->connected = BLUETOOTH_CONNECTED_LINK_BREDR_LE;
272                                 break;
273                         default:
274                                 BT_ERR_C("rem_info->connected is already set to desired value: %d",
275                                                 rem_info->connected);
276                         }
277                 }
278         } else {
279                 if (0 == type) {
280                         switch (rem_info->connected) {
281                         case BLUETOOTH_CONNECTED_LINK_BREDR:
282                                 rem_info->connected = BLUETOOTH_CONNECTED_LINK_NONE;
283                                 break;
284                         case BLUETOOTH_CONNECTED_LINK_BREDR_LE:
285                                 rem_info->connected = BLUETOOTH_CONNECTED_LINK_LE;
286                                 break;
287                         default:
288                                 BT_ERR_C("rem_info->connected is already set to desired value: %d",
289                                                 rem_info->connected);
290                         }
291                 } else {
292                         switch (rem_info->connected) {
293                         case BLUETOOTH_CONNECTED_LINK_LE:
294                                 rem_info->connected = BLUETOOTH_CONNECTED_LINK_NONE;
295                                 break;
296                         case BLUETOOTH_CONNECTED_LINK_BREDR_LE:
297                                 rem_info->connected = BLUETOOTH_CONNECTED_LINK_BREDR;
298                                 break;
299                         default:
300                                 BT_ERR_C("rem_info->connected is already set to desired value: %d",
301                                                 rem_info->connected);
302                         }
303                 }
304         }
305
306         BT_DBG("-");
307 }
308
309 void _bt_update_remote_dev_property(
310                 const char *address, bt_device_prop_type_e type, void *value)
311 {
312         bt_remote_dev_info_t *rem_info;
313
314         BT_DBG("+");
315
316         BT_DBG("Property type: %d", type);
317         rem_info = _bt_service_get_remote_dev_info(address);
318         ret_if(NULL == rem_info);
319
320         switch (type) {
321         case DEV_PROP_CONNECTED: {
322                 bt_device_conn_info_t *conn_info = value;
323
324                 __bt_update_connected_status(
325                         rem_info, conn_info->connected, conn_info->type);
326                 break;
327         }
328         case DEV_PROP_NAME: {
329                 char *name = value;
330
331                 if (name && strlen(name) > 0) {
332                         g_free(rem_info->name);
333                         rem_info->name = g_strdup(name);
334                 }
335                 break;
336         }
337         case DEV_PROP_ALIAS: {
338                 char *alias = value;
339
340                 g_free(rem_info->alias);
341                 rem_info->alias = NULL;
342                 rem_info->is_alias_set = FALSE;
343
344                 if (alias && strlen(alias) > 0) {
345                         rem_info->alias = g_strdup(alias);
346                         rem_info->is_alias_set = TRUE;
347                 }
348                 break;
349         }
350         case DEV_PROP_TRUST: {
351                 gboolean *trusted = value;
352                 rem_info->trust = *trusted;
353                 break;
354         }
355         case DEV_PROP_SERVICES: {
356                 bt_remote_dev_info_t *src = value;
357
358                 if (src->uuid_count > 0 && src->uuids) {
359                         int i;
360
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);
366
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]);
371
372                         rem_info->uuid_count = src->uuid_count;
373                         BT_DBG("UUID count: %d", rem_info->uuid_count);
374                 }
375                 break;
376         }
377         default:
378                 BT_DBG("Unknown property");
379                 return;
380         }
381
382         BT_DBG("-");
383 }
384
385 void _bt_service_add_device_to_bonded_list(bt_remote_dev_info_t *rem_info)
386 {
387         bt_remote_dev_info_t *dev_info;
388
389         BT_DBG("+");
390         ret_if(NULL == rem_info);
391
392         dev_info = _bt_service_get_remote_dev_info(rem_info->address);
393         if (!dev_info) {
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);
397         }
398
399         _bt_copy_remote_dev_info(dev_info, rem_info);
400
401         if (!bonded_list_retrieved) {
402                 char addr_str[BT_ADDRESS_STRING_SIZE];
403                 bluetooth_device_address_t *dev_addr;
404                 GSList *l;
405
406                 l = g_slist_nth(bonded_addr_list, bonded_list_index);
407                 if (!l) {
408                         BT_ERR_C("l is NULL unexpectedly, need to check");
409                         return;
410                 }
411
412                 dev_addr = l->data;
413                 if (!dev_addr) {
414                         BT_ERR_C("dev_addr is NULL unexpectedly, need to check");
415                         return;
416                 }
417
418                 _bt_convert_addr_type_to_string(addr_str, dev_addr->addr);
419                 if (!strncasecmp(addr_str, rem_info->address, BT_ADDRESS_STRING_SIZE)) {
420                         bonded_list_index++;
421                         __bt_service_fetch_dev_info_for_bonded_addr_list();
422                 }
423         }
424
425         BT_DBG("-");
426 }
427
428 void _bt_service_remove_device_from_bonded_list(const char *address)
429 {
430         bt_remote_dev_info_t *rem_info;
431
432         BT_DBG("+");
433         ret_if(NULL == address);
434
435         rem_info = _bt_service_get_remote_dev_info(address);
436         if (!rem_info) {
437                 BT_DBG("Device not found in list");
438                 return;
439         }
440
441         paired_list = g_slist_remove(paired_list, rem_info);
442         _bt_free_remote_dev(rem_info);
443         BT_DBG("-");
444 }
445
446 void _bt_device_handle_paired_address_list(bluetooth_device_address_t *addr_list, int count)
447 {
448         int indx;
449
450         BT_DBG("+");
451
452         if (bonded_list_retrieved) {
453                 BT_ERR_C("Unexpected bonded address list received");
454                 return;
455         }
456
457         if (0 == count) {
458                 BT_DBG("No paired device found");
459                 bonded_list_index = 0;
460                 bonded_list_retrieved = TRUE;
461                 return;
462         }
463
464         ret_if(NULL == addr_list);
465
466         for (indx = 0; indx < count; indx++) {
467                 bluetooth_device_address_t *dev_addr;
468
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);
471         }
472
473         __bt_service_fetch_dev_info_for_bonded_addr_list();
474         BT_DBG("-");
475 }
476
477 static gboolean __check_bonded_devices(gpointer data)
478 {
479         BT_DBG("+");
480
481         retv_if(bonded_list_retrieved, FALSE);
482
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");
486
487         BT_DBG("-");
488         return TRUE;
489 }
490
491 void _bt_device_handle_adapter_state(gboolean enabled)
492 {
493         BT_DBG("+");
494
495         if (!enabled) {
496                 BT_DBG("Adapter disabled");
497                 g_slist_free_full(paired_list, g_free);
498                 paired_list = NULL;
499                 bonded_list_retrieved = FALSE;
500                 return;
501         }
502
503         if (BLUETOOTH_ERROR_NONE != _bt_adapter_get_bonded_devices())
504                 BT_ERR_C("_bt_adapter_get_bonded_devices failed");
505
506         g_timeout_add_seconds(5, __check_bonded_devices, NULL);
507         BT_DBG("-");
508 }
509
510 static gboolean __reply_pending_request(gpointer data)
511 {
512         int *request = data;
513
514         BT_INFO("Request: %d", *request);
515         __bt_handle_pending_request(BLUETOOTH_ERROR_NONE, *request);
516         g_free(request);
517         return FALSE;
518 }
519
520 int _bt_get_bonded_device_info(bluetooth_device_address_t *dev_addr)
521 {
522         char address[BT_ADDRESS_STRING_SIZE];
523         bt_remote_dev_info_t *rem_info;
524         int request = BT_GET_BONDED_DEVICE;
525
526         BT_DBG("+");
527
528         retv_if(!dev_addr, BLUETOOTH_ERROR_INVALID_PARAM);
529
530         if (!bonded_list_retrieved) {
531                 /*
532                  * Blonded list retrival is in progress, return BLUETOOTH_ERROR_NONE here.
533                  * reply will be sent once bonded list is retrieved completely.
534                  */
535                 return BLUETOOTH_ERROR_NONE;
536         }
537
538         _bt_convert_addr_type_to_string(address, dev_addr->addr);
539         rem_info = _bt_service_get_remote_dev_info(address);
540         if (!rem_info) {
541                 BT_ERR("Bonded device not found in the list, return error");
542                 return BLUETOOTH_ERROR_NOT_PAIRED;
543         }
544
545         g_idle_add(__reply_pending_request, g_memdup(&request, sizeof(int)));
546         BT_DBG("-");
547         return BLUETOOTH_ERROR_NONE;
548 }
549
550 int _bt_get_bonded_devices(void)
551 {
552         int request = BT_GET_BONDED_DEVICES;
553
554         BT_DBG("+");
555         if (!bonded_list_retrieved) {
556                 /*
557                  * Blonded list retrival is in progress, return BLUETOOTH_ERROR_NONE here.
558                  * reply will be sent once bonded list is retrieved completely.
559                  */
560                 return BLUETOOTH_ERROR_NONE;
561         }
562
563         g_idle_add(__reply_pending_request, g_memdup(&request, sizeof(int)));
564         BT_DBG("-");
565         return BLUETOOTH_ERROR_NONE;
566 }
567
568 int _bt_is_alias_set(bluetooth_device_address_t *device_address)
569 {
570         char address[BT_ADDRESS_STRING_SIZE];
571         bt_remote_dev_info_t *rem_info;
572         int request = BT_GET_IS_ALIAS_SET;
573
574         BT_DBG("+");
575         if (!bonded_list_retrieved) {
576                 /*
577                  * Blonded list retrival is in progress, return BLUETOOTH_ERROR_NONE here.
578                  * reply will be sent once bonded list is retrieved completely.
579                  */
580                 return BLUETOOTH_ERROR_NONE;
581         }
582
583         _bt_convert_addr_type_to_string(address, device_address->addr);
584         rem_info = _bt_service_get_remote_dev_info(address);
585         if (!rem_info) {
586                 BT_ERR("Bonded device not found in the list, return error");
587                 return BLUETOOTH_ERROR_NOT_PAIRED;
588         }
589
590         g_idle_add(__reply_pending_request, g_memdup(&request, sizeof(int)));
591         BT_DBG("-");
592         return BLUETOOTH_ERROR_NONE;
593 }
594
595 int _bt_get_connected_link(bluetooth_device_address_t *device_address)
596 {
597         char address[BT_ADDRESS_STRING_SIZE];
598         bt_remote_dev_info_t *rem_info;
599         int request = BT_GET_CONNECTED_LINK_TYPE;
600
601         BT_DBG("+");
602         if (!bonded_list_retrieved) {
603                 /*
604                  * Blonded list retrival is in progress, return BLUETOOTH_ERROR_NONE here.
605                  * reply will be sent once bonded list is retrieved completely.
606                  */
607                 return BLUETOOTH_ERROR_NONE;
608         }
609
610         _bt_convert_addr_type_to_string(address, device_address->addr);
611         rem_info = _bt_service_get_remote_dev_info(address);
612         if (!rem_info) {
613                 BT_ERR("Bonded device not found in the list, return error");
614                 return BLUETOOTH_ERROR_NOT_PAIRED;
615         }
616
617         g_idle_add(__reply_pending_request, g_memdup(&request, sizeof(int)));
618         BT_DBG("-");
619         return BLUETOOTH_ERROR_NONE;
620 }
621
622 gboolean _bt_is_bonded_devices_retrived(void)
623 {
624         return bonded_list_retrieved;
625 }