OSDN Git Service

bt: Fix HCI driver selection logic for Qualcomm Bluetooth
[android-x86/system-bt.git] / utils / src / bt_utils.c
1 /******************************************************************************
2  *
3  *  Copyright (C) 2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18
19 /************************************************************************************
20  *
21  *  Filename:      bt_utils.c
22  *
23  *  Description:   Miscellaneous helper functions
24  *
25  *
26  ***********************************************************************************/
27
28 #define LOG_TAG "bt_utils"
29
30 #include "bt_utils.h"
31
32 #include <errno.h>
33 #include <pthread.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <sys/resource.h>
37 #include <unistd.h>
38
39 #include <utils/ThreadDefs.h>
40 #include <cutils/sched_policy.h>
41
42 #include "bt_types.h"
43 #include "btcore/include/module.h"
44 #include "osi/include/compat.h"
45 #include "osi/include/allocator.h"
46 #include "osi/include/log.h"
47 #include "osi/include/properties.h"
48 #include "osi/include/list.h"
49 #include <string.h>
50
51 /*******************************************************************************
52 **  Local type definitions
53 *******************************************************************************/
54 typedef struct {
55     char header_name[MAX_NAME_LEN];             // name of header in iot_devlist_conf file
56     list_t *devlist;                  // list of BD addresses
57     tBLACKLIST_METHOD method_type;
58 } iot_header_node_t;
59
60 typedef struct {
61     char dev_bd[3];                  // BD address of blacklisted device
62 } iot_devlist_bd_node_t;
63
64 typedef struct {
65     char dev_name[MAX_NAME_LEN];              // Name of blacklisted device
66 } iot_devlist_name_node_t;
67
68 typedef struct {
69     char *header;                   // header name
70     unsigned char *dev_details;              // details of blacklisted device
71     bool device_found;
72 } iot_input_param;
73
74 typedef struct {
75     bt_soc_type soc_type;
76     char* soc_name;
77 } soc_type_node;
78
79 static soc_type_node soc_type_entries[] = {
80                            { BT_SOC_SMD , "smd" },
81                            { BT_SOC_AR3K , "ath3k" },
82                            { BT_SOC_ROME , "rome" },
83                            { BT_SOC_CHEROKEE , "cherokee" },
84                            { BT_SOC_RESERVED , "" }
85                                        };
86
87 static list_t *iot_header_queue = NULL;
88 #define MAX_LINE 2048
89 #define MAX_ADDR_STR_LEN 9
90 static pthread_mutex_t         iot_mutex_lock;
91 /*******************************************************************************
92 **  Type definitions for callback functions
93 ********************************************************************************/
94 static pthread_once_t g_DoSchedulingGroupOnce[TASK_HIGH_MAX];
95 static BOOLEAN g_DoSchedulingGroup[TASK_HIGH_MAX];
96 static pthread_mutex_t         gIdxLock;
97 static int g_TaskIdx;
98 static int g_TaskIDs[TASK_HIGH_MAX];
99 static bt_soc_type soc_type;
100 #define INVALID_TASK_ID  (-1)
101
102 static void init_soc_type();
103
104 static future_t *init(void) {
105   int i;
106   pthread_mutexattr_t lock_attr;
107
108   for(i = 0; i < TASK_HIGH_MAX; i++) {
109     g_DoSchedulingGroupOnce[i] = PTHREAD_ONCE_INIT;
110     g_DoSchedulingGroup[i] = TRUE;
111     g_TaskIDs[i] = INVALID_TASK_ID;
112   }
113
114   pthread_mutexattr_init(&lock_attr);
115   pthread_mutex_init(&gIdxLock, &lock_attr);
116   pthread_mutex_init(&iot_mutex_lock, NULL);
117   init_soc_type();
118   return NULL;
119 }
120
121 static future_t *clean_up(void) {
122   pthread_mutex_destroy(&gIdxLock);
123   pthread_mutex_destroy(&iot_mutex_lock);
124   return NULL;
125 }
126
127 EXPORT_SYMBOL const module_t bt_utils_module = {
128   .name = BT_UTILS_MODULE,
129   .init = init,
130   .start_up = NULL,
131   .shut_down = NULL,
132   .clean_up = clean_up,
133   .dependencies = {
134     NULL
135   }
136 };
137
138 /*****************************************************************************
139 **
140 ** Function        check_do_scheduling_group
141 **
142 ** Description     check if it is ok to change schedule group
143 **
144 ** Returns         void
145 **
146 *******************************************************************************/
147 static void check_do_scheduling_group(void) {
148     char buf[PROPERTY_VALUE_MAX];
149     int len = osi_property_get("debug.sys.noschedgroups", buf, "");
150     if (len > 0) {
151         int temp;
152         if (sscanf(buf, "%d", &temp) == 1) {
153             g_DoSchedulingGroup[g_TaskIdx] = temp == 0;
154         }
155     }
156 }
157
158 /*****************************************************************************
159 **
160 ** Function        raise_priority_a2dp
161 **
162 ** Description     Raise task priority for A2DP streaming
163 **
164 ** Returns         void
165 **
166 *******************************************************************************/
167 void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task) {
168     int rc = 0;
169     int tid = gettid();
170     int priority = ANDROID_PRIORITY_AUDIO;
171
172     pthread_mutex_lock(&gIdxLock);
173     g_TaskIdx = high_task;
174
175     // TODO(armansito): Remove this conditional check once we find a solution
176     // for system/core on non-Android platforms.
177 #if defined(OS_GENERIC)
178     rc = -1;
179 #else  // !defined(OS_GENERIC)
180     pthread_once(&g_DoSchedulingGroupOnce[g_TaskIdx], check_do_scheduling_group);
181     if (g_TaskIdx < TASK_HIGH_MAX && g_DoSchedulingGroup[g_TaskIdx]) {
182         // set_sched_policy does not support tid == 0
183         rc = set_sched_policy(tid, SP_AUDIO_SYS);
184     }
185 #endif  // defined(OS_GENERIC)
186
187     g_TaskIDs[high_task] = tid;
188     pthread_mutex_unlock(&gIdxLock);
189
190     if (rc) {
191         LOG_WARN(LOG_TAG, "failed to change sched policy, tid %d, err: %d", tid, errno);
192     }
193
194     // always use urgent priority for HCI worker thread until we can adjust
195     // its prio individually. All other threads can be dynamically adjusted voa
196     // adjust_priority_a2dp()
197
198     priority = ANDROID_PRIORITY_URGENT_AUDIO;
199
200     if (setpriority(PRIO_PROCESS, tid, priority) < 0) {
201         LOG_WARN(LOG_TAG, "failed to change priority tid: %d to %d", tid, priority);
202     }
203 }
204
205 /*****************************************************************************
206 **
207 ** Function        adjust_priority_a2dp
208 **
209 ** Description     increase the a2dp consumer task priority temporarily when start
210 **                 audio playing, to avoid overflow the audio packet queue, restore
211 **                 the a2dp consumer task priority when stop audio playing.
212 **
213 ** Returns         void
214 **
215 *******************************************************************************/
216 void adjust_priority_a2dp(int start) {
217     int priority = start ? ANDROID_PRIORITY_URGENT_AUDIO : ANDROID_PRIORITY_AUDIO;
218     int tid;
219     int i;
220
221     for (i = 0; i < TASK_HIGH_MAX; i++)
222     {
223         tid = g_TaskIDs[i];
224         if (tid != INVALID_TASK_ID)
225         {
226             if (setpriority(PRIO_PROCESS, tid, priority) < 0)
227             {
228                 LOG_WARN(LOG_TAG, "failed to change priority tid: %d to %d", tid, priority);
229             }
230         }
231     }
232 }
233
234 /*****************************************************************************
235 **
236 ** Function        check_bd_cb
237 **
238 ** Description     Compares the BD address.
239 **
240 ** Returns         returns true if the BD address matches otherwise false
241 **
242 *******************************************************************************/
243 static bool check_bd_cb(void* node, void* cb_data)
244 {
245     iot_devlist_bd_node_t *bd_node = (iot_devlist_bd_node_t*)node;
246     iot_input_param *input_param = (iot_input_param*)cb_data;
247
248     if (input_param->device_found == true)
249         return true;
250
251     if ((bd_node->dev_bd[0] == input_param->dev_details[0]) &&
252         (bd_node->dev_bd[1] == input_param->dev_details[1]) &&
253         (bd_node->dev_bd[2] == input_param->dev_details[2])) {
254         input_param->device_found = true;
255         return true;
256     }
257     return false;
258 }
259
260 /*****************************************************************************
261 **
262 ** Function        check_name_cb
263 **
264 ** Description     Compares the Device name.
265 **
266 ** Returns         returns true if the name matches otherwise false
267 **
268 *******************************************************************************/
269 static bool check_name_cb(void* node, void* cb_data)
270 {
271     iot_devlist_name_node_t *name_node = (iot_devlist_name_node_t*)node;
272     iot_input_param *input_param = (iot_input_param*)cb_data;
273
274     if (input_param->device_found == true)
275         return true;
276
277     if (!strncmp(name_node->dev_name, (const char*)input_param->dev_details,
278                                                 strlen((char *)input_param->dev_details))) {
279         input_param->device_found = true;
280         return true;
281     }
282     return false;
283 }
284
285 /*****************************************************************************
286 **
287 ** Function        check_header_cb
288 **
289 ** Description     Iterates through the each entry in the header list and
290 **                 calls the callback associated to each entry.
291 **
292 ** Returns         boolean
293 **
294 *******************************************************************************/
295 static bool check_header_cb(void* node, void* cb_data)
296 {
297     iot_header_node_t *header_node = (iot_header_node_t*)node;
298     iot_input_param *input_param = (iot_input_param*)cb_data;
299     if (!strcmp(header_node->header_name, input_param->header)) {
300         if(header_node->devlist) {
301             if (header_node->method_type == METHOD_BD)
302                 list_foreach_ext(header_node->devlist, check_bd_cb, cb_data);
303             else if (header_node->method_type == METHOD_NAME)
304                 list_foreach_ext(header_node->devlist, check_name_cb, cb_data);
305         }
306     }
307     return true;
308 }
309
310 /*****************************************************************************
311 **
312 ** Function        is_device_present
313 **
314 ** Description     Checks if the device is already present in the blacklisted
315 **                 device list or not.The input can be address based or name
316 **                 based.
317 **
318 ** Returns         true incase device is present false otherwise.
319 **
320 *******************************************************************************/
321 bool is_device_present(char* header, unsigned char* device_details)
322 {
323     iot_input_param input_param;
324     input_param.dev_details = device_details;
325     input_param.header = header;
326     input_param.device_found = false;
327
328     pthread_mutex_lock(&iot_mutex_lock);
329     if (!iot_header_queue) {
330         pthread_mutex_unlock(&iot_mutex_lock);
331         return false;
332     }
333     list_foreach_ext(iot_header_queue, check_header_cb, &input_param);
334     pthread_mutex_unlock(&iot_mutex_lock);
335
336     if (input_param.device_found)
337         return true;
338     else
339         return false;
340 }
341
342 /*****************************************************************************
343 **
344 ** Function        parse_bd
345 **
346 ** Description     It will read 3 bytes and copy them into node. It also
347 **                 increments header pointer.
348 **
349 ** Returns         void.
350 **
351 *******************************************************************************/
352 static void parse_bd(char **start_ptr, iot_devlist_bd_node_t *bd)
353 {
354     char *p_end;
355     bd->dev_bd[0] = (unsigned char)strtol(*start_ptr, &p_end, 16);
356     (*start_ptr) = p_end + 1;
357     bd->dev_bd[1] = (unsigned char)strtol(*start_ptr, &p_end, 16);
358     (*start_ptr) = p_end + 1;
359     bd->dev_bd[2] = (unsigned char)strtol(*start_ptr, &p_end, 16);
360     (*start_ptr) = p_end;
361 }
362
363 /*****************************************************************************
364 **
365 ** Function        parse_name
366 **
367 ** Description     It will read name and copy them into node. It also
368 **                 increments header pointer.
369 **
370 ** Returns         void.
371 **
372 *******************************************************************************/
373 static void parse_name(char **start_ptr, iot_devlist_name_node_t *name)
374 {
375     char *split = strchr(*start_ptr, ','); // split point to first occurrence of ,
376     int len = 0;
377     if (split == NULL) {
378         // check once for end of line, for the last name in list
379         split = strchr(*start_ptr, '\n');
380         if (split == NULL)
381             return;
382     }
383     len = (((split - (*start_ptr)) >= MAX_NAME_LEN) ? MAX_NAME_LEN - 1 :
384                                             (split - (*start_ptr)));
385     memcpy(name->dev_name, *start_ptr, len);
386     name->dev_name[len] = '\0';
387     *start_ptr = split;
388 }
389
390 /*****************************************************************************
391 **
392 ** Function        is_device_node_exist
393 **
394 ** Description     Checks if the device node is already present in the queue
395 **                 or not.The input can be address based or name  based.
396 **
397 ** Returns         true if the entry found else false.
398 **
399 *******************************************************************************/
400 static bool is_device_node_exist(iot_header_node_t *header_entry, char* device_details,
401                     tBLACKLIST_METHOD method_type)
402 {
403     if(!header_entry || !header_entry->devlist)
404         return false;
405
406     for (const list_node_t *device_node = list_begin(header_entry->devlist);
407             device_node != list_end(header_entry->devlist);
408             device_node = list_next(device_node)) {
409         if(method_type == METHOD_BD) {
410             iot_devlist_bd_node_t *bd_addr_entry = list_node(device_node);
411             if(!memcmp(device_details, bd_addr_entry->dev_bd, 3)) {
412                 return true;
413             }
414         }
415         else if(method_type == METHOD_NAME) {
416             iot_devlist_name_node_t *bd_name_entry = list_node(device_node);
417             if(!strcmp((char *)device_details, bd_name_entry->dev_name)) {
418                 return true;
419             }
420         }
421     }
422     return false;
423 }
424
425 /*****************************************************************************
426 **
427 ** Function        populate_list
428 **
429 ** Description     It goes through the input buffer and add device node to the
430 **                 header list if the valid entry is found.It ignores the
431 **                 duplicated entries.
432 **
433 ** Returns         void.
434 **
435 *******************************************************************************/
436 static void populate_list(char *header_end, iot_header_node_t *node)
437 {
438     if(node->devlist == NULL)
439         node->devlist = list_new(osi_free);
440     while(header_end && (*header_end != '\n')&&(*header_end != '\0')) // till end of line reached
441     {
442         // read from line buffer and copy to list
443         if (node->method_type == METHOD_BD) {
444             iot_devlist_bd_node_t *bd = (iot_devlist_bd_node_t *)osi_malloc(sizeof(iot_devlist_bd_node_t));
445             if(bd == NULL) {
446                 ALOGE(" Unable to allocate memory for addr entry");
447                 return;
448             }
449             header_end++;
450             parse_bd(&header_end, bd);
451             if(is_device_node_exist(node, (char *) bd, node->method_type)) {
452                 osi_free(bd);
453             }
454             else {
455                 list_append(node->devlist, bd);
456             }
457         }
458         else if (node->method_type == METHOD_NAME) {
459             iot_devlist_name_node_t *name = (iot_devlist_name_node_t *)osi_malloc(sizeof(iot_devlist_name_node_t));
460             if(name == NULL) {
461                 ALOGE(" Unable to allocate memory for name entry");
462                 return;
463             }
464             header_end++;
465             parse_name(&header_end, name);
466             if(is_device_node_exist(node, (char *)name, node->method_type)) {
467                 osi_free(name);
468             }
469             else {
470                 list_append(node->devlist, name);
471             }
472         }
473     }
474 }
475
476 /*****************************************************************************
477 **
478 ** Function        create_header_node
479 **
480 ** Description     This function is used to create the header node.
481 **
482 ** Returns         valid pointer incase the node is created otherwise NULL.
483 **
484 *******************************************************************************/
485 static iot_header_node_t *create_header_node(char* name, unsigned int len,
486                         tBLACKLIST_METHOD method_type)
487 {
488     iot_header_node_t *node = NULL;
489     if(len >= MAX_NAME_LEN) {
490         return NULL;
491     }
492     node =(iot_header_node_t *) osi_malloc(sizeof(iot_header_node_t));
493     if (node == NULL) {
494        ALOGE(" Not enough memory to create the header node");
495        return NULL;
496     }
497     memcpy(node->header_name, name, len);
498     node->header_name[len] = '\0';  // header copied
499     node->method_type = method_type;
500     node->devlist = NULL;
501     return node;
502 }
503
504 /*****************************************************************************
505 **
506 ** Function        get_existing_header_node
507 **
508 ** Description     This function is used to get exisiting header node if present.
509 **
510 ** Returns         valid pointer incase the node is already prsent otherwise NULL.
511 **
512 *******************************************************************************/
513 static iot_header_node_t *get_existing_header_node(char* name, unsigned int len)
514 {
515     for (const list_node_t *node = list_begin(iot_header_queue);
516            node != list_end(iot_header_queue); node = list_next(node)) {
517         iot_header_node_t *entry = list_node(node);
518         if (!strncmp(entry->header_name, name, len)) {
519             return entry;
520         }
521     }
522     return NULL;
523 }
524
525 /*****************************************************************************
526 **
527 ** Function        populate_header
528 **
529 ** Description     It goes through the input buffer and add header node to the
530 **                 main queue if the valid entry is found.It ignores the
531 **                 duplicated entries.
532 **
533 ** Returns         void.
534 **
535 *******************************************************************************/
536 static void populate_header(char* line_start, char *header_end)
537 {
538     tBLACKLIST_METHOD method_type;
539     iot_header_node_t *node = NULL;
540
541     if (*(header_end + 3) == ':')
542         method_type = METHOD_BD;
543     else
544         method_type = METHOD_NAME;
545
546     if (!iot_header_queue) {
547         iot_header_queue = list_new(osi_free);
548         if (iot_header_queue == NULL) {
549             ALOGE(" Not enough memory  to create the queue");
550             return;
551         }
552     }
553
554     if( (node = get_existing_header_node(line_start,  header_end - line_start)) == NULL) {
555         node = create_header_node(line_start, header_end - line_start, method_type);
556         if(node)
557             list_append(iot_header_queue, node);
558     }
559     if(node)
560         populate_list(header_end, node);
561 }
562
563 /*****************************************************************************
564 **
565 ** Function        free_header_list
566 **
567 ** Description     This function is used to free all entries under blacklist
568 **                 queue.
569 **
570 ** Returns         boolean
571 **
572 *******************************************************************************/
573 static bool free_header_list(void* node, void *context)
574 {
575     iot_header_node_t *header_node = (iot_header_node_t*)node;
576     list_free(header_node->devlist);
577     return true;
578 }
579
580 /*****************************************************************************
581 **
582 ** Function        unload_iot_devlist
583 **
584 ** Description     This function is used to free the IOT blacklist queue.
585 **
586 ** Returns         void
587 **
588 *******************************************************************************/
589 void unload_iot_devlist()
590 {
591     pthread_mutex_lock(&iot_mutex_lock);
592     if (!iot_header_queue) {
593         ALOGV(" Blacklist queue is not initialized ");
594         pthread_mutex_unlock(&iot_mutex_lock);
595         return;
596     }
597     list_foreach(iot_header_queue, free_header_list, NULL);
598     list_free(iot_header_queue);
599     iot_header_queue = NULL;
600     pthread_mutex_unlock(&iot_mutex_lock);
601 }
602
603 /*****************************************************************************
604 **
605 ** Function        copy_file
606 **
607 ** Description     This function is used to copy one file to other.
608 **
609 ** Returns         true incase copy is successful otherwise false.
610 **
611 *******************************************************************************/
612 static bool copy_file(const char *src, const char *dst)
613 {
614     FILE *src_fp = NULL, *dst_fp = NULL;
615     int ch;
616
617     if( !src || !dst)  {
618         return false;
619     }
620     src_fp = fopen(src, "rt");
621     if(src_fp)
622         dst_fp = fopen(dst, "wt");
623     if(src_fp && dst_fp) {
624         while( ( ch = fgetc(src_fp) ) != EOF ) {
625             fputc(ch, dst_fp);
626         }
627         fclose(dst_fp);
628         fclose(src_fp);
629         return true;
630     }
631     else {
632         if(src_fp)
633             fclose(src_fp);
634         if(dst_fp)
635             fclose(dst_fp);
636         return false;
637     }
638 }
639
640 /*****************************************************************************
641 **
642 ** Function        dump_all_iot_devices
643 **
644 ** Description     This function is used to print all blacklisted devices
645 **                 which are loaded from iot_devlist.conf file..
646 **
647 ** Returns         void.
648 **
649 *******************************************************************************/
650 static void dump_all_iot_devices(void)
651 {
652     tBLACKLIST_METHOD method_type;
653
654     if(!iot_header_queue)
655         return;
656
657     for (const list_node_t *header_node = list_begin(iot_header_queue);
658            header_node != list_end(iot_header_queue);
659            header_node = list_next(header_node)) {
660         iot_header_node_t *header_entry = list_node(header_node);
661         method_type = header_entry->method_type;
662
663         if(!header_entry->devlist)
664             continue;
665
666         ALOGW(" ########### Blacklisted Device summary ##############");
667         for (const list_node_t *device_node = list_begin(header_entry->devlist);
668                 device_node != list_end(header_entry->devlist);
669                 device_node = list_next(device_node)) {
670             if(method_type == METHOD_BD) {
671                 iot_devlist_bd_node_t *bd_addr_entry = list_node(device_node);
672                 ALOGW(" Device  %02X:%02X:%02X Blacklisted under %s",
673                     bd_addr_entry->dev_bd[0], bd_addr_entry->dev_bd[1],
674                     bd_addr_entry->dev_bd[2], header_entry->header_name);
675             }
676             else if(method_type == METHOD_NAME) {
677                 iot_devlist_name_node_t *bd_name_entry = list_node(device_node);
678                 ALOGW(" Device %s Blacklisted under %s", bd_name_entry->dev_name,
679                     header_entry->header_name);
680             }
681         }
682     }
683 }
684
685 /*****************************************************************************
686 **
687 ** Function        load_iot_devlist_from_file
688 **
689 ** Description     This function is used to initialize the queue and load the
690 **                 load the devices from file.
691 **
692 ** Returns         void.
693 **
694 *******************************************************************************/
695 void load_iot_devlist_from_file(const char *filename)
696 {
697     if (!filename) {
698         ALOGE(" Invalid IOT blacklist filename");
699         return;
700     }
701     char line_start[MAX_LINE];
702     int line_number = 0;
703     char *header_end = NULL;
704     FILE *iot_devlist_fp = fopen(filename, "rt");
705     if (iot_devlist_fp == NULL) {
706         if(!strcmp(filename, IOT_DEV_CONF_FILE))  {
707             //load it from system partition
708             if(copy_file(IOT_DEV_BASE_CONF_FILE, IOT_DEV_CONF_FILE) == false) {
709                 ALOGE(" Can't copy it from Base file %s", IOT_DEV_BASE_CONF_FILE);
710                 return;
711             }
712             else {
713                 if((iot_devlist_fp = fopen(filename, "rt")) == NULL)
714                     return;
715             }
716         }
717         else {
718             ALOGE(" File %s does not exist ",filename);
719             return;
720         }
721     }
722     while(fgets(line_start, MAX_LINE, iot_devlist_fp))  {
723         line_number++;
724         if((*line_start == '\n') ||(*line_start == '#')) {
725             ALOGV("line %d is empty",line_number);
726             continue;
727         }
728         header_end = strchr(line_start, '=');
729         if (header_end == NULL) {
730             ALOGV(" NOT A valid line %d", line_number);
731             continue;
732         }
733         populate_header(line_start, header_end);
734     }
735     dump_all_iot_devices();
736     fclose(iot_devlist_fp);
737 }
738
739 /*****************************************************************************
740 **
741 ** Function        load_iot_devlist
742 **
743 ** Description     This function is used to initialize the queue.
744 **
745 ** Returns         void.
746 **
747 *******************************************************************************/
748 void load_iot_devlist(const char *filename)
749 {
750     pthread_mutex_lock(&iot_mutex_lock);
751     load_iot_devlist_from_file(filename);
752     pthread_mutex_unlock(&iot_mutex_lock);
753 }
754
755 /*****************************************************************************
756 **
757 ** Function        add_iot_device
758 **
759 ** Description     This function is used to add the device to the blacklist file
760 **                 as well as queue.
761 **
762 ** Returns         true incase the device is blacklisted otherwise fasle.
763 **
764 *******************************************************************************/
765 bool add_iot_device(const char *filename, char* header,
766     unsigned char* device_details, tBLACKLIST_METHOD method_type)
767 {
768     char line_start[MAX_LINE];
769     FILE *iot_devlist_fp;
770     char *header_end = NULL;
771     int index = 0, i, len = 0;
772
773     if((header == NULL) || (device_details == NULL)) {
774         ALOGE("Error adding device to the list: Invalid input data");
775         return false;
776     }
777     if (is_device_present (header , device_details)) {
778         ALOGW("Device already present in the blacklist");
779         return true;
780     }
781
782     pthread_mutex_lock(&iot_mutex_lock);
783     iot_devlist_fp = fopen(filename, "a");
784
785     if (iot_devlist_fp == NULL) {
786         ALOGE(" File %s does not exist ", filename);
787         pthread_mutex_unlock(&iot_mutex_lock);
788         return false;
789     }
790     /* first copy the header */
791     len = strlcpy(&line_start[index], header, strlen(header)+ 1);
792     index += len;
793
794     line_start[index++] = '=';
795     /* then copy the device addr/device name */
796     if(method_type == METHOD_BD) {
797         /* for addr take first 3 bytes */
798         for(i = 0; i < 3; i++) {
799             if(i < 2) {
800                 len = snprintf(&line_start[index], MAX_LINE - index, "%02X:",
801                                                     *(device_details + i));
802             }
803             else {
804                 len = snprintf(&line_start[index], MAX_LINE - index, "%02X",
805                                             *(device_details + i));
806             }
807             index += len;
808         }
809     }
810     else if(method_type == METHOD_NAME) {
811         len = strlcpy(&line_start[index], (const char*) device_details,
812                         strlen((const char*)device_details) + 1);
813         index += len;
814     }
815     /* append the new line characer at the end */
816     line_start[index++] = '\n';
817     line_start[index++] = '\0';
818
819     header_end = strchr(line_start,'=');
820     if(header_end) {
821         populate_header(line_start, header_end);
822     }
823     if(fputs(line_start, iot_devlist_fp)) {
824         fclose(iot_devlist_fp);
825         pthread_mutex_unlock(&iot_mutex_lock);
826         return true;
827     }
828     else {
829         fclose(iot_devlist_fp);
830         pthread_mutex_unlock(&iot_mutex_lock);
831         return false;
832     }
833 }
834
835 /*****************************************************************************
836 **
837 ** Function        form_bd_addr
838 **
839 ** Description     Adds the colon after 2 bytes to form valid BD address to
840 **                 compare the entry prsent in file.
841 **
842 ** Returns         void
843 **
844 *******************************************************************************/
845 static void form_bd_addr(char *addr, char *new_addr, int max_len)
846 {
847     int i = 0, index = 0, len =0;
848     /* for addr take first 3 bytes */
849     for(i = 0; i < 3; i++) {
850         if(i < 2) {
851             len = snprintf(&new_addr[index], max_len - index, "%02X:",
852                     *(addr + i));
853         }
854         else {
855             len = snprintf(&new_addr[index], max_len - index, "%02X",
856                     *(addr + i));
857         }
858         index += len;
859     }
860     new_addr[max_len - 1]= '\0';
861 }
862
863 /*****************************************************************************
864 **
865 ** Function        remove_iot_device_from_queue
866 **
867 ** Description     This function is used remove the entry from internal queue.
868 **
869 ** Returns         true if the entry removed from queue else false.
870 **
871 *******************************************************************************/
872 bool remove_iot_device_from_queue(unsigned char* device_details, char* header,
873         tBLACKLIST_METHOD method_type)
874 {
875     if(!iot_header_queue)
876         return false;
877     for (const list_node_t *header_node = list_begin(iot_header_queue);
878            header_node != list_end(iot_header_queue);
879            header_node = list_next(header_node)) {
880         iot_header_node_t *header_entry = list_node(header_node);
881
882         if(!header_entry->devlist)
883             continue;
884
885         if((!strcmp(header, header_entry->header_name)) &&
886              method_type == header_entry->method_type) {
887
888             for (const list_node_t *device_node = list_begin(header_entry->devlist);
889                     device_node != list_end(header_entry->devlist);
890                     device_node = list_next(device_node)) {
891                 if(method_type == METHOD_BD) {
892                     iot_devlist_bd_node_t *bd_addr_entry = list_node(device_node);
893                     if(!memcmp(device_details, bd_addr_entry->dev_bd, 3)) {
894                         list_remove(header_entry->devlist, bd_addr_entry);
895                         return true;
896                     }
897                 }
898                 else if(method_type == METHOD_NAME) {
899                     iot_devlist_name_node_t *bd_name_entry = list_node(device_node);
900                     if(!strcmp((char *)device_details, bd_name_entry->dev_name)) {
901                         list_remove(header_entry->devlist, bd_name_entry);
902                         return true;
903                     }
904                 }
905             }
906         }
907     }
908     return false;
909 }
910
911 /*****************************************************************************
912 **
913 ** Function        edit_line
914 **
915 ** Description     This function is used to remove the device entry from the
916 **                 inputted line buffer if the entry present.
917 **
918 ** Returns         true if the entry removed from line else false.
919 **
920 *******************************************************************************/
921 static void edit_line(char *line_start, char *dev_info, int line_len)
922 {
923     char *dev_ptr = strstr(line_start, dev_info);
924     char *comma_ptr = NULL;
925     int len_to_copy = 0;
926     if(dev_ptr) {
927         comma_ptr = strchr(dev_ptr, ',');
928         if(comma_ptr) {
929             len_to_copy = line_len - (comma_ptr - line_start + 1);
930         }
931         else {
932             *(dev_ptr - 1) = '\n';
933             *(dev_ptr) = '\0';
934         }
935     }
936     if(len_to_copy) {
937         memmove(dev_ptr, comma_ptr + 1, len_to_copy);
938     }
939 }
940
941 /*****************************************************************************
942 **
943 ** Function        is_single_entry_line
944 **
945 ** Description     This function is used to check the line consists of single
946 **                 input line if the entry present.
947 **
948 ** Returns         true if the single entry present else false.
949 **
950 *******************************************************************************/
951 static bool is_single_entry_line(char *line_start)
952 {
953     char *comma_ptr = strchr(line_start, ',');
954     // check the char next to ,
955     if( !comma_ptr || (*(comma_ptr + 1) == '\n')) {
956         return true;
957     }
958     else {
959         return false;
960     }
961 }
962
963 /*****************************************************************************
964 **
965 ** Function        get_header_from_line
966 **
967 ** Description     This function is used to get the header from line buffer.
968 **
969 ** Returns         true if the header found else false.
970 **
971 *******************************************************************************/
972 bool get_header_from_line(char *line_start, char* header)
973 {
974     int i = 0;
975     if(!line_start || !header || !strchr(line_start, '=')) {
976         return false;
977     }
978     while (line_start[i] != '=') {
979         header[i] = line_start[i];
980         i++;
981     }
982     header[i] = '\0';
983     return true;
984 }
985
986 /*****************************************************************************
987 **
988 ** Function        remove_iot_device
989 **
990 ** Description     This function is used to remove the device from internal
991 **                 blacklisted queue as well as black list file.
992 **
993 ** Returns         true if the device is removed else false.
994 **
995 *******************************************************************************/
996 bool remove_iot_device(const char *filename, char* header,
997     unsigned char* device_details, tBLACKLIST_METHOD method_type)
998 {
999     char line_start[MAX_LINE];
1000     FILE *iot_devlist_fp, *iot_devlist_new_fp;
1001     char bd_addr[MAX_ADDR_STR_LEN];
1002     char header_name[MAX_NAME_LEN] = { 0 };
1003     char *dev = NULL;
1004     int len = 0;
1005
1006     if((header == NULL) || (device_details == NULL)) {
1007         ALOGE("Invalid input data to add the device");
1008         return false;
1009     }
1010     if (!is_device_present (header , device_details)) {
1011         ALOGW("Device doesn't exist in the list");
1012         return false;
1013     }
1014     pthread_mutex_lock(&iot_mutex_lock);
1015     iot_devlist_fp = fopen(filename, "rt");
1016
1017     if (iot_devlist_fp == NULL) {
1018         ALOGE(" File %s does not exist ", filename);
1019         pthread_mutex_unlock(&iot_mutex_lock);
1020         return false;
1021     }
1022     iot_devlist_new_fp = fopen(IOT_DEV_CONF_BKP_FILE, "wt");
1023
1024     if (iot_devlist_new_fp == NULL) {
1025         ALOGE(" Unable to create backup file %s", IOT_DEV_CONF_BKP_FILE);
1026         fclose(iot_devlist_fp);
1027         pthread_mutex_unlock(&iot_mutex_lock);
1028         return false;
1029     }
1030
1031     /* then copy the device addr/device name */
1032     while (fgets(line_start, sizeof line_start, iot_devlist_fp)) {
1033         len = strlen(line_start);
1034
1035         if (len) {
1036             get_header_from_line(line_start, header_name);
1037             if(method_type == METHOD_BD) {
1038                 form_bd_addr((char*)device_details, bd_addr, MAX_ADDR_STR_LEN);
1039                 dev = bd_addr;
1040             }
1041             else if(method_type == METHOD_NAME) {
1042                 dev = (char *) device_details;
1043             }
1044             // copy as it is if the line consists comments
1045             if( (line_start[0] == '#') || (line_start[0] == '/') ||
1046                     (line_start[0] == ' ') || (line_start[0] == '\n')) {
1047                 fputs(line_start, iot_devlist_new_fp);
1048             }
1049             else if((!strcmp(header_name, header)) && (strstr(line_start, dev))) {
1050                 if(is_single_entry_line(line_start)) {
1051                     if(!remove_iot_device_from_queue(device_details, header, method_type)) {
1052                         // if unable to remove from queue put the same line as it is
1053                         fputs(line_start, iot_devlist_new_fp);
1054                     }
1055                     else
1056                         ALOGE(" Removed %s device from blacklist file %s", dev, IOT_DEV_CONF_FILE);
1057                 }
1058                 else {
1059                     // multi line entry
1060                     if(remove_iot_device_from_queue(device_details, header, method_type)) {
1061                         edit_line(line_start, dev, len + 1);
1062                         fputs(line_start, iot_devlist_new_fp);
1063                         ALOGE(" Removed %s device from blacklist file %s", dev, IOT_DEV_CONF_FILE);
1064                     }
1065                     else {
1066                         fputs(line_start, iot_devlist_new_fp);
1067                     }
1068                 }
1069             }
1070             else {
1071                 fputs(line_start, iot_devlist_new_fp);
1072             }
1073         }
1074     }
1075
1076     fclose(iot_devlist_fp);
1077     fclose(iot_devlist_new_fp);
1078     remove(filename);
1079     rename(IOT_DEV_CONF_BKP_FILE, filename);
1080     pthread_mutex_unlock(&iot_mutex_lock);
1081     return true;
1082 }
1083
1084 /*****************************************************************************
1085 **
1086 ** Function        init_soc_type
1087 **
1088 ** Description     Get Bluetooth SoC type from system setting and stores it
1089 **                 in soc_type.
1090 **
1091 ** Returns         void.
1092 **
1093 *******************************************************************************/
1094 static void init_soc_type()
1095 {
1096     int ret = 0;
1097     char bt_soc_type[PROPERTY_VALUE_MAX];
1098
1099     ALOGI("init_soc_type");
1100
1101     soc_type = BT_SOC_DEFAULT;
1102     ret = property_get("qcom.bluetooth.soc", bt_soc_type, NULL);
1103     if (ret != 0) {
1104         unsigned int i;
1105         ALOGI("qcom.bluetooth.soc set to %s\n", bt_soc_type);
1106         for ( i = 0 ; i < sizeof(soc_type_entries)/sizeof(soc_type_entries[0]) ; i++ )
1107         {
1108             char* soc_name = soc_type_entries[i].soc_name;
1109             if (!strcmp(bt_soc_type, soc_name)) {
1110                 soc_type = soc_type_entries[i].soc_type;
1111                 break;
1112             }
1113         }
1114     }
1115 }
1116
1117 /*****************************************************************************
1118 **
1119 ** Function        get_soc_type
1120 **
1121 ** Description     This function is used to get the Bluetooth SoC type.
1122 **
1123 ** Returns         bt_soc_type.
1124 **
1125 *******************************************************************************/
1126 bt_soc_type get_soc_type()
1127 {
1128     return soc_type;
1129 }