1 /*
2 * Copyright 2012 The Android Open Source Project
3 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
4 * Not a Contribution.
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 *
21 * Filename: bt_vendor_qcom.c
22 *
23 * Description: vendor specific library implementation
24 *
25 ******************************************************************************/
26 #define LOG_TAG "bt_vendor"
27 #define BLUETOOTH_MAC_ADDR_BOOT_PROPERTY "ro.boot.btmacaddr"
28
29 #include <utils/Log.h>
30 #include <cutils/properties.h>
31 #include <fcntl.h>
32 #include <termios.h>
33 #include "bt_vendor_qcom.h"
34 #include "hci_uart.h"
35 #include "hci_smd.h"
36 #include <sys/ioctl.h>
37 #include <sys/socket.h>
38 #include <cutils/sockets.h>
39 #include <linux/un.h>
40 #include "bt_vendor_persist.h"
41 #include "hw_rome.h"
42 #include "bt_vendor_lib.h"
43 #define WAIT_TIMEOUT 200000
44 #define BT_VND_OP_GET_LINESPEED 30
45
46 #define STOP_WCNSS_FILTER 0xDD
47 #define STOP_WAIT_TIMEOUT 1000
48
49 #define SOC_INIT_PROPERTY "wc_transport.soc_initialized"
50
51 #define BT_VND_FILTER_START "wc_transport.start_hci"
52
53 #define CMD_TIMEOUT 0x22
54
55 static void wait_for_patch_download(bool is_ant_req);
56 static bool is_debug_force_special_bytes(void);
57 int connect_to_local_socket(char* name);
58 /******************************************************************************
59 ** Externs
60 ******************************************************************************/
61 extern int hw_config(int nState);
62 extern int is_hw_ready();
63 extern int chipset_ver;
64
65 /******************************************************************************
66 ** Variables
67 ******************************************************************************/
68 struct bt_qcom_struct *q = NULL;
69 pthread_mutex_t q_lock = PTHREAD_MUTEX_INITIALIZER;
70
71 int userial_clock_operation(int fd, int cmd);
72 int ath3k_init(int fd, int speed, int init_speed, char *bdaddr, struct termios *ti);
73 int userial_vendor_get_baud(void);
74 int readTrpState();
75 void lpm_set_ar3k(uint8_t pio, uint8_t action, uint8_t polarity);
76 bool is_download_progress();
77
78 static const tUSERIAL_CFG userial_init_cfg =
79 {
80 (USERIAL_DATABITS_8 | USERIAL_PARITY_NONE | USERIAL_STOPBITS_1),
81 USERIAL_BAUD_115200
82 };
83
84 #if (HW_NEED_END_WITH_HCI_RESET == TRUE)
85 void __hw_epilog_process(void);
86 #endif
87
88 #ifdef WIFI_BT_STATUS_SYNC
89 #include <string.h>
90 #include <errno.h>
91 #include <dlfcn.h>
92 #include "cutils/properties.h"
93
94 static const char WIFI_PROP_NAME[] = "wlan.driver.status";
95 static const char SERVICE_PROP_NAME[] = "bluetooth.hsic_ctrl";
96 static const char BT_STATUS_NAME[] = "bluetooth.enabled";
97 static const char WIFI_SERVICE_PROP[] = "wlan.hsic_ctrl";
98
99 #define WIFI_BT_STATUS_LOCK "/data/connectivity/wifi_bt_lock"
100 int isInit=0;
101 #endif /* WIFI_BT_STATUS_SYNC */
102 bool is_soc_initialized(void);
103
104 /******************************************************************************
105 ** Local type definitions
106 ******************************************************************************/
107
108 /******************************************************************************
109 ** Functions
110 ******************************************************************************/
111 #ifdef WIFI_BT_STATUS_SYNC
bt_semaphore_create(void)112 int bt_semaphore_create(void)
113 {
114 int fd;
115
116 fd = open(WIFI_BT_STATUS_LOCK, O_RDONLY);
117
118 if (fd < 0)
119 ALOGE("can't create file\n");
120
121 return fd;
122 }
123
bt_semaphore_get(int fd)124 int bt_semaphore_get(int fd)
125 {
126 int ret;
127
128 if (fd < 0)
129 return -1;
130
131 ret = flock(fd, LOCK_EX);
132 if (ret != 0) {
133 ALOGE("can't hold lock: %s\n", strerror(errno));
134 return -1;
135 }
136
137 return ret;
138 }
139
bt_semaphore_release(int fd)140 int bt_semaphore_release(int fd)
141 {
142 int ret;
143
144 if (fd < 0)
145 return -1;
146
147 ret = flock(fd, LOCK_UN);
148 if (ret != 0) {
149 ALOGE("can't release lock: %s\n", strerror(errno));
150 return -1;
151 }
152
153 return ret;
154 }
155
bt_semaphore_destroy(int fd)156 int bt_semaphore_destroy(int fd)
157 {
158 if (fd < 0)
159 return -1;
160
161 return close (fd);
162 }
163
bt_wait_for_service_done(void)164 int bt_wait_for_service_done(void)
165 {
166 char service_status[PROPERTY_VALUE_MAX];
167 int count = 30;
168
169 ALOGE("%s: check\n", __func__);
170
171 /* wait for service done */
172 while (count-- > 0) {
173 property_get(WIFI_SERVICE_PROP, service_status, NULL);
174
175 if (strcmp(service_status, "") != 0) {
176 usleep(200000);
177 } else {
178 break;
179 }
180 }
181
182 return 0;
183 }
184
185 #endif /* WIFI_BT_STATUS_SYNC */
186
187 /** Get Bluetooth SoC type from system setting */
get_bt_soc_type()188 static int get_bt_soc_type()
189 {
190 int ret = 0;
191 char bt_soc_type[PROPERTY_VALUE_MAX];
192
193 ALOGI("bt-vendor : get_bt_soc_type");
194
195 ret = property_get("qcom.bluetooth.soc", bt_soc_type, NULL);
196 if (ret != 0) {
197 ALOGI("qcom.bluetooth.soc set to %s\n", bt_soc_type);
198 if (!strncasecmp(bt_soc_type, "rome", sizeof("rome"))) {
199 return BT_SOC_ROME;
200 }
201 else if (!strncasecmp(bt_soc_type, "cherokee", sizeof("cherokee"))) {
202 return BT_SOC_CHEROKEE;
203 }
204 else if (!strncasecmp(bt_soc_type, "ath3k", sizeof("ath3k"))) {
205 return BT_SOC_AR3K;
206 }
207 else if (!strncasecmp(bt_soc_type, "cherokee", sizeof("cherokee"))) {
208 return BT_SOC_CHEROKEE;
209 }
210 else {
211 ALOGI("qcom.bluetooth.soc not set, so using default.\n");
212 return BT_SOC_DEFAULT;
213 }
214 }
215 else {
216 ALOGE("%s: Failed to get soc type", __FUNCTION__);
217 ret = BT_SOC_DEFAULT;
218 }
219
220 return ret;
221 }
222
can_perform_action(char action)223 bool can_perform_action(char action) {
224 bool can_perform = false;
225 char ref_count[PROPERTY_VALUE_MAX];
226 char inProgress[PROPERTY_VALUE_MAX] = {'\0'};
227 int value, ret;
228
229 property_get("wc_transport.ref_count", ref_count, "0");
230
231 value = atoi(ref_count);
232 ALOGV("%s: ref_count: %s\n",__func__, ref_count);
233
234 if(action == '1') {
235 ALOGV("%s: on : value is: %d", __func__, value);
236 if(value == 1)
237 {
238 if ((is_soc_initialized() == true)
239 || is_download_progress() || get_bt_soc_type() == BT_SOC_CHEROKEE)
240 {
241 value++;
242 ALOGV("%s: on : value is incremented to : %d", __func__, value);
243 }
244 }
245 else
246 {
247 value++;
248 }
249
250 if (value == 1)
251 can_perform = true;
252 else if (value > 3)
253 return false;
254 }
255 else {
256 ALOGV("%s: off : value is: %d", __func__, value);
257 if (--value <= 0) {
258 ALOGE("%s: BT turn off twice before BT On(ref_count=%d)\n",
259 __func__, value);
260 value = 0;
261 can_perform = true;
262 }
263 }
264
265 snprintf(ref_count, 3, "%d", value);
266 ALOGV("%s: updated ref_count is: %s", __func__, ref_count);
267
268 ret = property_set("wc_transport.ref_count", ref_count);
269 if (ret < 0) {
270 ALOGE("%s: Error while updating property: %d\n", __func__, ret);
271 return false;
272 }
273 ALOGV("%s returning %d", __func__, can_perform);
274 return can_perform;
275 }
276
stop_hci_filter()277 void stop_hci_filter() {
278 char value[PROPERTY_VALUE_MAX] = {'\0'};
279 int retval, filter_ctrl, i;
280 char stop_val = STOP_WCNSS_FILTER;
281 int soc_type = BT_SOC_DEFAULT;
282
283 ALOGV("%s: Entry ", __func__);
284
285 if ((soc_type = get_bt_soc_type()) == BT_SOC_CHEROKEE) {
286 property_get("wc_transport.hci_filter_status", value, "0");
287 if (strcmp(value, "0") == 0) {
288 ALOGI("%s: hci_filter has been stopped already", __func__);
289 }
290 else {
291 filter_ctrl = connect_to_local_socket("wcnssfilter_ctrl");
292 if (filter_ctrl < 0) {
293 ALOGI("%s: Error while connecting to CTRL_SOCK, filter should stopped: %d",
294 __func__, filter_ctrl);
295 }
296 else {
297 retval = write(filter_ctrl, &stop_val, 1);
298 if (retval != 1) {
299 ALOGI("%s: problem writing to CTRL_SOCK, ignore: %d", __func__, retval);
300 //Ignore and fallback
301 }
302
303 close(filter_ctrl);
304 }
305 }
306
307 /* Ensure Filter is closed by checking the status before
308 RFKILL 0 operation. this should ideally comeout very
309 quick */
310 for(i=0; i<500; i++) {
311 property_get(BT_VND_FILTER_START, value, "false");
312 if (strcmp(value, "false") == 0) {
313 ALOGI("%s: WCNSS_FILTER stopped", __func__);
314 usleep(STOP_WAIT_TIMEOUT * 10);
315 break;
316 } else {
317 /*sleep of 1ms, This should give enough time for FILTER to
318 exit with all necessary cleanup*/
319 usleep(STOP_WAIT_TIMEOUT);
320 }
321 }
322
323 /*Never use SIGKILL to stop the filter*/
324 /* Filter will be stopped by below two conditions
325 - by Itself, When it realizes there are no CONNECTED clients
326 - Or through STOP_WCNSS_FILTER byte on Control socket
327 both of these ensure clean shutdown of chip
328 */
329 //property_set(BT_VND_FILTER_START, "false");
330 } else if (soc_type == BT_SOC_ROME) {
331 property_set(BT_VND_FILTER_START, "false");
332 } else {
333 ALOGI("%s: Unknown soc type %d, Unexpected!", __func__, soc_type);
334 }
335
336 ALOGV("%s: Exit ", __func__);
337 }
338
start_hci_filter()339 int start_hci_filter() {
340 ALOGV("%s: Entry ", __func__);
341 int i, init_success = -1;
342 char value[PROPERTY_VALUE_MAX] = {'\0'};
343
344 property_get(BT_VND_FILTER_START, value, false);
345
346 if (strcmp(value, "true") == 0) {
347 ALOGI("%s: hci_filter has been started already", __func__);
348 //Filter should have been started OR in the process of initializing
349 //Make sure of hci_filter_status and return the state based on it
350 } else {
351 property_set("wc_transport.clean_up","0");
352 property_set("wc_transport.hci_filter_status", "0");
353 property_set(BT_VND_FILTER_START, "true");
354 ALOGV("%s: %s set to true ", __func__, BT_VND_FILTER_START );
355 }
356
357 /*If there are back to back ON requests from different clients,
358 All client should come and stuck in this while loop till FILTER
359 comesup and ready to accept the connections */
360 //sched_yield();
361 for(i=0; i<45; i++) {
362 property_get("wc_transport.hci_filter_status", value, "0");
363 if (strcmp(value, "1") == 0) {
364 init_success = 1;
365 break;
366 } else {
367 usleep(WAIT_TIMEOUT);
368 }
369 }
370 ALOGV("start_hcifilter status:%d after %f seconds \n", init_success, 0.2*i);
371
372 ALOGV("%s: Exit ", __func__);
373 return init_success;
374 }
375
376 /*
377 * Bluetooth Controller power up or shutdown, this function is called with
378 * q_lock held and q is non-NULL
379 */
bt_powerup(int en)380 static int bt_powerup(int en )
381 {
382 char rfkill_type[64], *enable_ldo_path = NULL;
383 char type[16], enable_ldo[6];
384 int fd = 0, size, i, ret, fd_ldo, fd_btpower;
385
386 char disable[PROPERTY_VALUE_MAX];
387 char state;
388 char on = (en)?'1':'0';
389
390 #ifdef WIFI_BT_STATUS_SYNC
391 char wifi_status[PROPERTY_VALUE_MAX];
392 int lock_fd;
393 #endif /*WIFI_BT_STATUS_SYNC*/
394
395 ALOGI("bt_powerup: %c", on);
396
397 /* Check if rfkill has been disabled */
398 ret = property_get("ro.rfkilldisabled", disable, "0");
399 if (!ret ){
400 ALOGE("Couldn't get ro.rfkilldisabled (%d)", ret);
401 return -1;
402 }
403 /* In case rfkill disabled, then no control power*/
404 if (strcmp(disable, "1") == 0) {
405 ALOGI("ro.rfkilldisabled : %s", disable);
406 return -1;
407 }
408
409 #ifdef WIFI_BT_STATUS_SYNC
410 lock_fd = bt_semaphore_create();
411 bt_semaphore_get(lock_fd);
412 bt_wait_for_service_done();
413 #endif
414
415 /* Assign rfkill_id and find bluetooth rfkill state path*/
416 for(i = 0; (q->rfkill_id == -1) && (q->rfkill_state == NULL); i++)
417 {
418 snprintf(rfkill_type, sizeof(rfkill_type), "/sys/class/rfkill/rfkill%d/type", i);
419 if ((fd = open(rfkill_type, O_RDONLY)) < 0)
420 {
421 ALOGE("open(%s) failed: %s (%d)\n", rfkill_type, strerror(errno), errno);
422
423 #ifdef WIFI_BT_STATUS_SYNC
424 bt_semaphore_release(lock_fd);
425 bt_semaphore_destroy(lock_fd);
426 #endif
427 return -1;
428 }
429
430 size = read(fd, &type, sizeof(type));
431 close(fd);
432
433 if ((size >= 9) && !memcmp(type, "bluetooth", 9))
434 {
435 asprintf(&q->rfkill_state, "/sys/class/rfkill/rfkill%d/state", q->rfkill_id = i);
436 break;
437 }
438 }
439
440 /* Get rfkill State to control */
441 if (q->rfkill_state != NULL)
442 {
443 if ((fd = open(q->rfkill_state, O_RDWR)) < 0)
444 {
445 ALOGE("open(%s) for write failed: %s (%d)", q->rfkill_state, strerror(errno), errno);
446 #ifdef WIFI_BT_STATUS_SYNC
447 bt_semaphore_release(lock_fd);
448 bt_semaphore_destroy(lock_fd);
449 #endif
450
451 return -1;
452 }
453 }
454 if(can_perform_action(on) == false) {
455 ALOGE("%s:can't perform action as it is being used by other clients", __func__);
456 #ifdef WIFI_BT_STATUS_SYNC
457 bt_semaphore_release(lock_fd);
458 bt_semaphore_destroy(lock_fd);
459 #endif
460 goto done;
461 }
462 ret = asprintf(&enable_ldo_path, "/sys/class/rfkill/rfkill%d/device/extldo", q->rfkill_id);
463 if( (ret < 0 ) || (enable_ldo_path == NULL) )
464 {
465 ALOGE("Memory Allocation failure");
466 return -1;
467 }
468 if ((fd_ldo = open(enable_ldo_path, O_RDWR)) < 0) {
469 ALOGE("open(%s) failed: %s (%d)", enable_ldo_path, strerror(errno), errno);
470 return -1;
471 }
472 size = read(fd_ldo, &enable_ldo, sizeof(enable_ldo));
473 close(fd_ldo);
474 if (size <= 0) {
475 ALOGE("read(%s) failed: %s (%d)", enable_ldo_path, strerror(errno), errno);
476 return -1;
477 }
478 if (!memcmp(enable_ldo, "true", 4)) {
479 ALOGI("External LDO has been configured");
480 ret = property_set("wc_transport.extldo", "enabled");
481 if (ret < 0) {
482 ALOGI("%s: Not able to set property wc_transport.extldo\n", __func__);
483 }
484 q->enable_extldo = TRUE;
485 }
486
487 if(on == '0'){
488 ALOGE("Stopping HCI filter as part of CTRL:OFF");
489 stop_hci_filter();
490 property_set("wc_transport.soc_initialized", "0");
491 }
492
493 if (q->soc_type >= BT_SOC_CHEROKEE && q->soc_type < BT_SOC_RESERVED) {
494 ALOGI("open bt power devnode,send ioctl power op :%d ",en);
495 fd_btpower = open(BT_PWR_CNTRL_DEVICE, O_RDWR, O_NONBLOCK);
496 if (fd_btpower < 0) {
497 ALOGE("\nfailed to open bt device error = (%s)\n",strerror(errno));
498 #ifdef WIFI_BT_STATUS_SYNC
499 bt_semaphore_release(lock_fd);
500 bt_semaphore_destroy(lock_fd);
501 #endif
502 return -1;
503 }
504 ret = ioctl(fd_btpower, BT_CMD_PWR_CTRL, (unsigned long)en);
505 if (ret < 0) {
506 ALOGE(" ioctl failed to power control:%d error =(%s)",ret,strerror(errno));
507 }
508 close(fd_btpower);
509 } else {
510 ALOGI("Write %c to rfkill\n", on);
511 /* Write value to control rfkill */
512 if(fd >= 0) {
513 if ((size = write(fd, &on, 1)) < 0) {
514 ALOGE("write(%s) failed: %s (%d)", q->rfkill_state, strerror(errno), errno);
515 #ifdef WIFI_BT_STATUS_SYNC
516 bt_semaphore_release(lock_fd);
517 bt_semaphore_destroy(lock_fd);
518 #endif
519 return -1;
520 }
521 }
522 }
523 #ifdef WIFI_BT_STATUS_SYNC
524 /* query wifi status */
525 property_get(WIFI_PROP_NAME, wifi_status, "");
526
527 ALOGE("bt get wifi status: %s, isInit: %d\n", wifi_status, isInit);
528
529 /* If wlan driver is not loaded, and bt is changed from off => on */
530 if (strncmp(wifi_status, "unloaded", strlen("unloaded")) == 0 || strlen(wifi_status) == 0) {
531 if (on == '1') {
532 ALOGI("%s: BT_VND_PWR_ON\n", __func__);
533 if(property_set(SERVICE_PROP_NAME, "load_wlan") < 0) {
534 ALOGE("%s Property setting failed", SERVICE_PROP_NAME);
535 close(fd);
536 bt_semaphore_release(lock_fd);
537 bt_semaphore_destroy(lock_fd);
538 return -1;
539 }
540 }
541 else if (isInit == 0 && on == '0') {
542 ALOGI("%s: BT_VND_PWR_OFF\n", __func__);
543 if(property_set(SERVICE_PROP_NAME, "unbind_hsic") < 0) {
544 ALOGE("%s Property setting failed", SERVICE_PROP_NAME);
545 close(fd);
546 bt_semaphore_release(lock_fd);
547 bt_semaphore_destroy(lock_fd);
548 return -1;
549 }
550 }
551 }
552
553 if (isInit == 0 && on == '0')
554 property_set(BT_STATUS_NAME, "false");
555 else if (on == '1')
556 property_set(BT_STATUS_NAME, "true");
557
558 bt_semaphore_release(lock_fd);
559 bt_semaphore_destroy(lock_fd);
560 #endif /* WIFI_BT_STATUS_SYNC */
561
562 done:
563 if (fd >= 0)
564 close(fd);
565 return 0;
566 }
567
soc_init(int soc_type)568 static inline void soc_init(int soc_type)
569 {
570 switch (soc_type)
571 {
572 case BT_SOC_CHEROKEE:
573 case BT_SOC_ROME:
574 case BT_SOC_AR3K:
575 ALOGI("bt-vendor : Initializing UART transport layer");
576 userial_vendor_init();
577 break;
578 case BT_SOC_DEFAULT:
579 break;
580 default:
581 ALOGE("Unknown soc yype: %d", soc_type);
582 break;
583 }
584 }
585
586 /* Copy BD Address as little-endian byte order */
le2bd(unsigned char * src,unsigned char * dst)587 static inline void le2bd(unsigned char *src, unsigned char *dst)
588 {
589 int i;
590 for (i = 0; i < 6; i++)
591 dst[i] = src[5-i];
592 }
593
print_bdaddr(unsigned char * addr)594 static inline void print_bdaddr(unsigned char *addr)
595 {
596 ALOGI("BD Address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", addr[0], addr[1],
597 addr[2], addr[3], addr[4], addr[5]);
598 }
599
600 /*****************************************************************************
601 **
602 ** BLUETOOTH VENDOR INTERFACE LIBRARY FUNCTIONS
603 **
604 *****************************************************************************/
605
init(const bt_vendor_callbacks_t * cb,unsigned char * bdaddr)606 static int init(const bt_vendor_callbacks_t *cb, unsigned char *bdaddr)
607 {
608 char prop[PROPERTY_VALUE_MAX] = {0};
609 struct bt_qcom_struct *temp = NULL;
610 int ret = BT_STATUS_SUCCESS, i;
611
612 ALOGI("++%s", __FUNCTION__);
613
614 if (!cb || !bdaddr) {
615 ALOGE("Invalid input args cb %p bdaddr %p", cb, bdaddr);
616 ret = -BT_STATUS_INVAL;
617 goto out;
618 }
619
620 temp = (struct bt_qcom_struct *) malloc(sizeof(*q));
621 if (!temp) {
622 ALOGE("Failed to allocate memory. err %s(%d)", strerror(errno), errno);
623 ret = -BT_STATUS_NOMEM;
624 goto out;
625 }
626 memset(temp, 0, sizeof(*temp));
627
628 temp->rfkill_id = -1;
629 temp->enable_extldo = FALSE;
630 temp->cb = (bt_vendor_callbacks_t*)cb;
631 temp->ant_fd = -1;
632 temp->soc_type = get_bt_soc_type();
633 soc_init(temp->soc_type);
634
635 le2bd(bdaddr, temp->bdaddr);
636 print_bdaddr(temp->bdaddr);
637 snprintf(prop, sizeof(prop), "%02x:%02x:%02x:%02x:%02x:%02x",
638 temp->bdaddr[0], temp->bdaddr[1], temp->bdaddr[2],
639 temp->bdaddr[3], temp->bdaddr[4], temp->bdaddr[5]);
640 ret = property_set("wc_transport.stack_bdaddr", prop);
641 if (ret < 0) {
642 ALOGE("Failed to set wc_transport.stack_bdaddr prop, ret = %d", ret);
643 ret = -BT_STATUS_PROP_FAILURE;
644 goto out;
645 }
646
647 /* TODO: Move these fields inside bt_qcom context */
648 #ifdef WIFI_BT_STATUS_SYNC
649 isInit = 1;
650 #endif /* WIFI_BT_STATUS_SYNC */
651
652 /* Everything successful */
653 q = temp;
654 return ret;
655
656 out:
657 if (temp)
658 free(temp);
659 ALOGI("--%s ret %d", __FUNCTION__, ret);
660 return ret;
661 }
662
663 #ifdef READ_BT_ADDR_FROM_PROP
validate_tok(char * bdaddr_tok)664 static bool validate_tok(char* bdaddr_tok) {
665 int i = 0;
666 bool ret;
667
668 if (strlen(bdaddr_tok) != 2) {
669 ret = FALSE;
670 ALOGE("Invalid token length");
671 } else {
672 ret = TRUE;
673 for (i=0; i<2; i++) {
674 if ((bdaddr_tok[i] >= '0' && bdaddr_tok[i] <= '9') ||
675 (bdaddr_tok[i] >= 'A' && bdaddr_tok[i] <= 'F') ||
676 (bdaddr_tok[i] >= 'a' && bdaddr_tok[i] <= 'f')) {
677 ret = TRUE;
678 ALOGV("%s: tok %s @ %d is good", __func__, bdaddr_tok, i);
679 } else {
680 ret = FALSE;
681 ALOGE("invalid character in tok: %s at ind: %d", bdaddr_tok, i);
682 break;
683 }
684 }
685 }
686 return ret;
687 }
688 #endif /*READ_BT_ADDR_FROM_PROP*/
689
connect_to_local_socket(char * name)690 int connect_to_local_socket(char* name) {
691 socklen_t len; int sk = -1;
692
693 ALOGE("%s: ACCEPT ", __func__);
694 sk = socket(AF_LOCAL, SOCK_STREAM, 0);
695 if (sk < 0) {
696 ALOGE("Socket creation failure");
697 return -1;
698 }
699
700 if(socket_local_client_connect(sk, name,
701 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM) < 0)
702 {
703 ALOGE("failed to connect (%s)", strerror(errno));
704 close(sk);
705 sk = -1;
706 } else {
707 ALOGE("%s: Connection succeeded\n", __func__);
708 }
709 return sk;
710 }
711
is_soc_initialized()712 bool is_soc_initialized() {
713 bool init = false;
714 char init_value[PROPERTY_VALUE_MAX];
715 int ret;
716
717 ALOGI("bt-vendor : is_soc_initialized");
718
719 ret = property_get(SOC_INIT_PROPERTY, init_value, NULL);
720 if (ret != 0) {
721 ALOGI("%s set to %s\n", SOC_INIT_PROPERTY, init_value);
722 if (!strncasecmp(init_value, "1", sizeof("1"))) {
723 init = true;
724 }
725 }
726 else {
727 ALOGE("%s: Failed to get %s", __FUNCTION__, SOC_INIT_PROPERTY);
728 }
729
730 return init;
731 }
732
733 /* flavor of op without locks */
op(bt_vendor_opcode_t opcode,void * param)734 static int op(bt_vendor_opcode_t opcode, void *param)
735 {
736 int retval = BT_STATUS_SUCCESS;
737 int nCnt = 0;
738 int nState = -1;
739 bool is_ant_req = false;
740 bool is_fm_req = false;
741 char wipower_status[PROPERTY_VALUE_MAX];
742 char emb_wp_mode[PROPERTY_VALUE_MAX];
743 char bt_version[PROPERTY_VALUE_MAX];
744 char lpm_config[PROPERTY_VALUE_MAX];
745 bool ignore_boot_prop = TRUE;
746 #ifdef READ_BT_ADDR_FROM_PROP
747 int i = 0;
748 static char bd_addr[PROPERTY_VALUE_MAX];
749 uint8_t local_bd_addr_from_prop[6];
750 char* tok;
751 #endif
752 bool skip_init = true;
753 int opcode_init = opcode;
754 ALOGV("++%s opcode %d", __FUNCTION__, opcode);
755
756 switch(opcode_init)
757 {
758 #ifdef FM_OVER_UART
759 case FM_VND_OP_POWER_CTRL:
760 {
761 is_fm_req = true;
762 if (is_soc_initialized()) {
763 // add any FM specific actions if needed in future
764 break;
765 }
766 }
767 #endif
768 case BT_VND_OP_POWER_CTRL:
769 {
770 if (!param) {
771 ALOGE("opcode = %d: param is null", opcode_init);
772 break;
773 }
774 nState = *(int *) param;
775 ALOGI("bt-vendor : BT_VND_OP_POWER_CTRL: %s",
776 (nState == BT_VND_PWR_ON)? "On" : "Off" );
777
778 switch(q->soc_type)
779 {
780 case BT_SOC_DEFAULT:
781 if (readTrpState())
782 {
783 ALOGI("bt-vendor : resetting BT status");
784 hw_config(BT_VND_PWR_OFF);
785 }
786 retval = hw_config(nState);
787 if(nState == BT_VND_PWR_ON
788 && retval == 0
789 && is_hw_ready() == TRUE){
790 retval = 0;
791 }
792 else {
793 retval = -1;
794 }
795 break;
796 case BT_SOC_ROME:
797 case BT_SOC_AR3K:
798 case BT_SOC_CHEROKEE:
799 /* BT Chipset Power Control through Device Tree Node */
800 retval = bt_powerup(nState);
801 default:
802 break;
803 }
804 }
805 break;
806
807 case BT_VND_OP_FW_CFG: {
808 /* call hciattach to initalize the stack */
809 if (q->soc_type == BT_SOC_ROME) {
810 if (is_soc_initialized()) {
811 ALOGI("Bluetooth FW and transport layer are initialized");
812 q->cb->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
813 } else {
814 ALOGE("bt_vendor_cbacks is null or SoC not initialized");
815 ALOGE("Error : hci, smd initialization Error");
816 retval = -1;
817 }
818 } else {
819 ALOGI("Bluetooth FW and transport layer are initialized");
820 q->cb->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
821 }
822 }
823 break;
824
825 case BT_VND_OP_SCO_CFG:
826 q->cb->scocfg_cb(BT_VND_OP_RESULT_SUCCESS); //dummy
827 break;
828 #ifdef ENABLE_ANT
829 case BT_VND_OP_ANT_USERIAL_OPEN:
830 ALOGI("bt-vendor : BT_VND_OP_ANT_USERIAL_OPEN");
831 is_ant_req = true;
832 goto userial_open;
833 #endif
834 #ifdef FM_OVER_UART
835 case BT_VND_OP_FM_USERIAL_OPEN:
836 ALOGI("bt-vendor : BT_VND_OP_FM_USERIAL_OPEN");
837 is_fm_req = true;
838 goto userial_open;
839 #endif
840 userial_open:
841 case BT_VND_OP_USERIAL_OPEN:
842 {
843 if (!param) {
844 ALOGE("opcode = %d: param is null", opcode_init);
845 break;
846 }
847 int (*fd_array)[] = (int (*)[]) param;
848 int idx, fd = -1, fd_filter = -1;
849 ALOGI("bt-vendor : BT_VND_OP_USERIAL_OPEN");
850 switch(q->soc_type)
851 {
852 case BT_SOC_DEFAULT:
853 {
854 if(bt_hci_init_transport(q->fd) != -1){
855 int (*fd_array)[] = (int (*) []) param;
856
857 (*fd_array)[CH_CMD] = q->fd[0];
858 (*fd_array)[CH_EVT] = q->fd[0];
859 (*fd_array)[CH_ACL_OUT] = q->fd[1];
860 (*fd_array)[CH_ACL_IN] = q->fd[1];
861 }
862 else {
863 retval = -1;
864 break;
865 }
866 retval = 2;
867 }
868 break;
869 case BT_SOC_AR3K:
870 {
871 fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg);
872 if (fd != -1) {
873 for (idx=0; idx < CH_MAX; idx++)
874 (*fd_array)[idx] = fd;
875 retval = 1;
876 }
877 else {
878 retval = -1;
879 break;
880 }
881
882 /* Vendor Specific Process should happened during userial_open process
883 After userial_open, rx read thread is running immediately,
884 so it will affect VS event read process.
885 */
886 if(ath3k_init(fd,3000000,115200,NULL,&vnd_userial.termios)<0)
887 retval = -1;
888 }
889 break;
890 case BT_SOC_ROME:
891 {
892 wait_for_patch_download(is_ant_req);
893 property_get("ro.bluetooth.emb_wp_mode", emb_wp_mode, false);
894 if (!is_soc_initialized()) {
895 char* dlnd_inprog = is_ant_req ? "ant" : "bt";
896 if (property_set("wc_transport.patch_dnld_inprog", dlnd_inprog) < 0) {
897 ALOGE("%s: Failed to set dnld_inprog %s", __FUNCTION__, dlnd_inprog);
898 }
899
900 fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg);
901 if (fd < 0) {
902 ALOGE("userial_vendor_open returns err");
903 retval = -1;
904 break;
905 }
906
907 /* Clock on */
908 userial_clock_operation(fd, USERIAL_OP_CLK_ON);
909
910 if(strcmp(emb_wp_mode, "true") == 0) {
911 property_get("ro.bluetooth.wipower", wipower_status, false);
912 if(strcmp(wipower_status, "true") == 0) {
913 check_embedded_mode(fd);
914 } else {
915 ALOGI("Wipower not enabled");
916 }
917 }
918 ALOGV("rome_soc_init is started");
919 property_set("wc_transport.soc_initialized", "0");
920 #ifdef READ_BT_ADDR_FROM_PROP
921 /*Give priority to read BD address from boot property*/
922 ignore_boot_prop = FALSE;
923 if (property_get(BLUETOOTH_MAC_ADDR_BOOT_PROPERTY, bd_addr, NULL)) {
924 ALOGV("BD address read from Boot property: %s\n", bd_addr);
925 tok = strtok(bd_addr, ":");
926 while (tok != NULL) {
927 ALOGV("bd add [%d]: %d ", i, strtol(tok, NULL, 16));
928 if (i>=6) {
929 ALOGE("bd property of invalid length");
930 ignore_boot_prop = TRUE;
931 break;
932 }
933 if (i == 6 && !ignore_boot_prop) {
934 ALOGV("Valid BD address read from prop");
935 memcpy(q->bdaddr, local_bd_addr_from_prop, sizeof(vnd_local_bd_addr));
936 ignore_boot_prop = FALSE;
937 } else {
938 ALOGE("There are not enough tokens in BD addr");
939 ignore_boot_prop = TRUE;
940 break;
941 }
942 local_bd_addr_from_prop[5-i] = strtol(tok, NULL, 16);
943 tok = strtok(NULL, ":");
944 i++;
945 }
946 if (i == 6 && !ignore_boot_prop) {
947 ALOGV("Valid BD address read from prop");
948 memcpy(vnd_local_bd_addr, local_bd_addr_from_prop, sizeof(vnd_local_bd_addr));
949 ignore_boot_prop = FALSE;
950 } else {
951 ALOGE("There are not enough tokens in BD addr");
952 ignore_boot_prop = TRUE;
953 }
954 }
955 else {
956 ALOGE("BD address boot property not set");
957 ignore_boot_prop = TRUE;
958 }
959 #endif //READ_BT_ADDR_FROM_PROP
960 #ifdef BT_NV_SUPPORT
961 /* Always read BD address from NV file */
962 if(ignore_boot_prop && !bt_vendor_nv_read(1, q->bdaddr))
963 {
964 /* Since the BD address is configured in boot time We should not be here */
965 ALOGI("Failed to read BD address. Use the one from bluedroid stack/ftm");
966 }
967 #endif //BT_NV_SUPPORT
968 if(rome_soc_init(fd, (char*)q->bdaddr)<0) {
969 retval = -1;
970 } else {
971 ALOGV("rome_soc_init is completed");
972 property_set("wc_transport.soc_initialized", "1");
973 skip_init = false;
974 }
975 }
976 if (property_set("wc_transport.patch_dnld_inprog", "null") < 0) {
977 ALOGE("%s: Failed to set property", __FUNCTION__);
978 }
979
980 property_set("wc_transport.clean_up","0");
981 if (retval != -1) {
982
983 retval = start_hci_filter();
984 if (retval < 0) {
985 ALOGE("%s: WCNSS_FILTER wouldn't have started in time\n", __func__);
986 } else {
987 #ifdef ENABLE_ANT
988 if (is_ant_req) {
989 ALOGI("%s: connect to ant channel", __func__);
990 q->ant_fd = fd_filter = connect_to_local_socket("ant_sock");
991 }
992 else
993 #endif
994 {
995 ALOGI("%s: connect to bt channel", __func__);
996 vnd_userial.fd = fd_filter = connect_to_local_socket("bt_sock");
997 }
998
999 if (fd_filter != -1) {
1000 ALOGI("%s: received the socket fd: %d is_ant_req: %d is_fm_req: %d\n",
1001 __func__, fd_filter, is_ant_req,is_fm_req);
1002 if((strcmp(emb_wp_mode, "true") == 0) && !is_ant_req && !is_fm_req) {
1003 if (chipset_ver >= ROME_VER_3_0) {
1004 /* get rome supported feature request */
1005 ALOGE("%s: %x08 %0x", __FUNCTION__,chipset_ver, ROME_VER_3_0);
1006 rome_get_addon_feature_list(fd_filter);
1007 }
1008 }
1009 if (!skip_init) {
1010 /*Skip if already sent*/
1011 enable_controller_log(fd_filter, (is_ant_req || is_fm_req) );
1012 skip_init = true;
1013 }
1014 for (idx=0; idx < CH_MAX; idx++)
1015 (*fd_array)[idx] = fd_filter;
1016 retval = 1;
1017 }
1018 else {
1019 if (is_ant_req)
1020 ALOGE("Unable to connect to ANT Server Socket!!!");
1021 else
1022 ALOGE("Unable to connect to BT Server Socket!!!");
1023 retval = -1;
1024 }
1025 }
1026 } else {
1027 if (q->soc_type == BT_SOC_ROME)
1028 ALOGE("Failed to initialize ROME Controller!!!");
1029 }
1030
1031 if (fd >= 0) {
1032 userial_clock_operation(fd, USERIAL_OP_CLK_OFF);
1033 /*Close the UART port*/
1034 close(fd);
1035 }
1036 }
1037 break;
1038 case BT_SOC_CHEROKEE:
1039 {
1040 property_get("ro.bluetooth.emb_wp_mode", emb_wp_mode, false);
1041 retval = start_hci_filter();
1042 if (retval < 0) {
1043 ALOGE("WCNSS_FILTER wouldn't have started in time\n");
1044 /*
1045 Set the following property to -1 so that the SSR cleanup routine
1046 can reset SOC.
1047 */
1048 property_set("wc_transport.hci_filter_status", "-1");
1049 } else {
1050 #ifdef ENABLE_ANT
1051 if (is_ant_req) {
1052 ALOGI("%s: connect to ant channel", __func__);
1053 q->ant_fd = fd_filter = connect_to_local_socket("ant_sock");
1054 }
1055 else
1056 #endif
1057 #ifdef FM_OVER_UART
1058 if (is_fm_req && (q->soc_type >=BT_SOC_ROME && q->soc_type < BT_SOC_RESERVED)) {
1059 ALOGI("%s: connect to fm channel", __func__);
1060 q->fm_fd = fd_filter = connect_to_local_socket("fm_sock");
1061 }
1062 else
1063 #endif
1064 {
1065 ALOGI("%s: connect to bt channel", __func__);
1066 vnd_userial.fd = fd_filter = connect_to_local_socket("bt_sock");
1067
1068 }
1069 if (fd_filter != -1) {
1070 ALOGV("%s: received the socket fd: %d \n",
1071 __func__, fd_filter);
1072
1073 for (idx=0; idx < CH_MAX; idx++) {
1074 (*fd_array)[idx] = fd_filter;
1075 }
1076 retval = 1;
1077 }
1078 else {
1079 #ifdef ENABLE_ANT
1080 if (is_ant_req)
1081 ALOGE("Unable to connect to ANT Server Socket!!!");
1082 else
1083 #endif
1084 #ifdef FM_OVER_UART
1085 if (is_fm_req)
1086 ALOGE("Unable to connect to FM Server Socket!!!");
1087 else
1088 #endif
1089 ALOGE("Unable to connect to BT Server Socket!!!");
1090 retval = -1;
1091 }
1092 }
1093 }
1094 break;
1095 default:
1096 ALOGE("Unknown soc_type: 0x%x", q->soc_type);
1097 break;
1098 }
1099 } break;
1100 #ifdef ENABLE_ANT
1101 case BT_VND_OP_ANT_USERIAL_CLOSE:
1102 {
1103 ALOGI("bt-vendor : BT_VND_OP_ANT_USERIAL_CLOSE");
1104 property_set("wc_transport.clean_up","1");
1105 if (q->ant_fd != -1) {
1106 ALOGE("closing ant_fd");
1107 close(q->ant_fd);
1108 q->ant_fd = -1;
1109 }
1110 }
1111 break;
1112 #endif
1113 #ifdef FM_OVER_UART
1114 case BT_VND_OP_FM_USERIAL_CLOSE:
1115 {
1116 ALOGI("bt-vendor : BT_VND_OP_FM_USERIAL_CLOSE");
1117 property_set("wc_transport.clean_up","1");
1118 if (q->fm_fd != -1) {
1119 ALOGE("closing fm_fd");
1120 close(q->fm_fd);
1121 q->fm_fd = -1;
1122 }
1123 break;
1124 }
1125 #endif
1126 case BT_VND_OP_USERIAL_CLOSE:
1127 {
1128 ALOGI("bt-vendor : BT_VND_OP_USERIAL_CLOSE soc_type: %d", q->soc_type);
1129 switch(q->soc_type)
1130 {
1131 case BT_SOC_DEFAULT:
1132 bt_hci_deinit_transport(q->fd);
1133 break;
1134 case BT_SOC_ROME:
1135 case BT_SOC_AR3K:
1136 case BT_SOC_CHEROKEE:
1137 {
1138 property_set("wc_transport.clean_up","1");
1139 userial_vendor_close();
1140 break;
1141 }
1142 default:
1143 ALOGE("Unknown soc_type: 0x%x", q->soc_type);
1144 break;
1145 }
1146 }
1147 break;
1148
1149 case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:
1150 {
1151 if (!param) {
1152 ALOGE("opcode = %d: param is null", opcode_init);
1153 break;
1154 }
1155 uint32_t *timeout_ms = (uint32_t *) param;
1156 *timeout_ms = 1000;
1157 }
1158
1159 break;
1160
1161 case BT_VND_OP_LPM_SET_MODE:
1162 if (q->soc_type == BT_SOC_AR3K) {
1163 if (!param) {
1164 ALOGE("opcode = %d: param is null", opcode_init);
1165 break;
1166 }
1167 uint8_t *mode = (uint8_t *) param;
1168
1169 if (*mode) {
1170 lpm_set_ar3k(UPIO_LPM_MODE, UPIO_ASSERT, 0);
1171 }
1172 else {
1173 lpm_set_ar3k(UPIO_LPM_MODE, UPIO_DEASSERT, 0);
1174 }
1175 q->cb->lpm_cb(BT_VND_OP_RESULT_SUCCESS);
1176 } else {
1177 int lpm_result = BT_VND_OP_RESULT_SUCCESS;
1178
1179 property_get("persist.service.bdroid.lpmcfg", lpm_config, "all");
1180 ALOGI("%s: property_get: persist.service.bdroid.lpmcfg: %s",
1181 __func__, lpm_config);
1182
1183 if (!strcmp(lpm_config, "all")) {
1184 // respond with success since we want to hold wake lock through LPM
1185 lpm_result = BT_VND_OP_RESULT_SUCCESS;
1186 }
1187 else {
1188 lpm_result = BT_VND_OP_RESULT_FAIL;
1189 }
1190
1191 q->cb->lpm_cb(lpm_result);
1192 }
1193 break;
1194
1195 case BT_VND_OP_LPM_WAKE_SET_STATE: {
1196 switch(q->soc_type) {
1197 case BT_SOC_CHEROKEE:
1198 case BT_SOC_ROME: {
1199 if (!param) {
1200 ALOGE("opcode = %d: param is null", opcode_init);
1201 break;
1202 }
1203 uint8_t *state = (uint8_t *) param;
1204 uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \
1205 BT_VND_LPM_WAKE_ASSERT : BT_VND_LPM_WAKE_DEASSERT;
1206
1207 if (wake_assert == 0)
1208 ALOGV("ASSERT: Waking up BT-Device");
1209 else if (wake_assert == 1)
1210 ALOGV("DEASSERT: Allowing BT-Device to Sleep");
1211
1212 #ifdef QCOM_BT_SIBS_ENABLE
1213 ALOGI("Invoking HCI H4 callback function");
1214 q->cb->lpm_set_state_cb(wake_assert);
1215 #endif
1216 }
1217 break;
1218 case BT_SOC_AR3K: {
1219 if (!param) {
1220 ALOGE("opcode = %d: param is null", opcode_init);
1221 break;
1222 }
1223 uint8_t *state = (uint8_t *) param;
1224 uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \
1225 UPIO_ASSERT : UPIO_DEASSERT;
1226 lpm_set_ar3k(UPIO_BT_WAKE, wake_assert, 0);
1227 }
1228 case BT_SOC_DEFAULT:
1229 break;
1230 default:
1231 ALOGE("Unknown soc_type: 0x%x", q->soc_type);
1232 break;
1233 }
1234 }
1235 break;
1236 case BT_VND_OP_EPILOG: {
1237 #if (HW_NEED_END_WITH_HCI_RESET == FALSE)
1238 q->cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
1239 #else
1240 switch(q->soc_type)
1241 {
1242 case BT_SOC_CHEROKEE:
1243 case BT_SOC_ROME:
1244 {
1245 char value[PROPERTY_VALUE_MAX] = {'\0'};
1246 property_get("wc_transport.hci_filter_status", value, "0");
1247 if(is_soc_initialized()&& (strcmp(value,"1") == 0))
1248 {
1249 __hw_epilog_process();
1250 }
1251 else
1252 {
1253 q->cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
1254 }
1255 }
1256 break;
1257 default:
1258 __hw_epilog_process();
1259 break;
1260 }
1261 #endif
1262 }
1263 break;
1264 case BT_VND_OP_GET_LINESPEED:
1265 {
1266 retval = -1;
1267 if(!is_soc_initialized()) {
1268 ALOGE("BT_VND_OP_GET_LINESPEED: error"
1269 " - transport driver not initialized!");
1270 break;
1271 }
1272
1273 switch(q->soc_type)
1274 {
1275 case BT_SOC_CHEROKEE:
1276 retval = 3200000;
1277 break;
1278 case BT_SOC_ROME:
1279 retval = 3000000;
1280 break;
1281 default:
1282 retval = userial_vendor_get_baud();
1283 break;
1284 }
1285 break;
1286 }
1287 }
1288
1289 out:
1290 ALOGV("--%s", __FUNCTION__);
1291 return retval;
1292 }
1293
ssr_cleanup(int reason)1294 static void ssr_cleanup(int reason)
1295 {
1296 int pwr_state = BT_VND_PWR_OFF;
1297 int ret;
1298 unsigned char trig_ssr = 0xEE;
1299 #ifndef ENABLE_ANT
1300 (void)reason; // unused
1301 #endif
1302
1303 ALOGI("++%s", __FUNCTION__);
1304
1305 pthread_mutex_lock(&q_lock);
1306 if (!q) {
1307 ALOGE("ssr_cleanup called with NULL context");
1308 goto out;
1309 }
1310 if (property_set("wc_transport.patch_dnld_inprog", "null") < 0) {
1311 ALOGE("Failed to set property");
1312 }
1313
1314 if (q->soc_type >= BT_SOC_ROME && q->soc_type < BT_SOC_RESERVED) {
1315 #ifdef ENABLE_ANT
1316 /*Indicate to filter by sending special byte */
1317 if (reason == CMD_TIMEOUT) {
1318 trig_ssr = 0xEE;
1319 ret = write (vnd_userial.fd, &trig_ssr, 1);
1320 ALOGI("Trig_ssr is being sent to BT socket, ret %d err %s",
1321 ret, strerror(errno));
1322
1323 if (is_debug_force_special_bytes()) {
1324 /*
1325 * Then we should send special byte to crash SOC in
1326 * WCNSS_Filter, so we do not need to power off UART here.
1327 */
1328 goto out;
1329 }
1330 }
1331
1332 /* Close both ANT channel */
1333 op(BT_VND_OP_ANT_USERIAL_CLOSE, NULL);
1334 #endif
1335 /* Close both BT channel */
1336 op(BT_VND_OP_USERIAL_CLOSE, NULL);
1337
1338 #ifdef FM_OVER_UART
1339 op(BT_VND_OP_FM_USERIAL_CLOSE, NULL);
1340 #endif
1341 /*CTRL OFF twice to make sure hw
1342 * turns off*/
1343 #ifdef ENABLE_ANT
1344 op(BT_VND_OP_POWER_CTRL, &pwr_state);
1345 #endif
1346 }
1347 /*Generally switching of chip should be enough*/
1348 op(BT_VND_OP_POWER_CTRL, &pwr_state);
1349
1350 out:
1351 pthread_mutex_unlock(&q_lock);
1352 ALOGI("--%s", __FUNCTION__);
1353 }
1354
1355 /** Closes the interface */
cleanup(void)1356 static void cleanup(void)
1357 {
1358 ALOGI("cleanup");
1359
1360 pthread_mutex_lock(&q_lock);
1361 q->cb = NULL;
1362 free(q);
1363 q = NULL;
1364 pthread_mutex_unlock(&q_lock);
1365
1366 #ifdef WIFI_BT_STATUS_SYNC
1367 isInit = 0;
1368 #endif /* WIFI_BT_STATUS_SYNC */
1369 }
1370
1371 /* Check for one of the cients ANT/BT patch download is already in
1372 ** progress if yes wait till complete
1373 */
wait_for_patch_download(bool is_ant_req)1374 void wait_for_patch_download(bool is_ant_req) {
1375 ALOGV("%s:", __FUNCTION__);
1376 char inProgress[PROPERTY_VALUE_MAX] = {'\0'};
1377 while (1) {
1378 property_get("wc_transport.patch_dnld_inprog", inProgress, "null");
1379
1380 if(is_ant_req && !(strcmp(inProgress,"bt"))) {
1381 //ANT request, wait for BT to finish
1382 usleep(50000);
1383 }
1384 else if(!is_ant_req && !(strcmp(inProgress,"ant"))) {
1385 //BT request, wait for ANT to finish
1386 usleep(50000);
1387 }
1388 else {
1389 ALOGI("%s: patch download completed", __FUNCTION__);
1390 break;
1391 }
1392 }
1393 }
1394
is_download_progress()1395 bool is_download_progress () {
1396 char inProgress[PROPERTY_VALUE_MAX] = {'\0'};
1397 bool retval = false;
1398
1399 ALOGV("%s:", __FUNCTION__);
1400
1401 if ((q->soc_type = get_bt_soc_type()) < 0) {
1402 ALOGE("%s: Failed to detect BT SOC Type", __FUNCTION__);
1403 return -1;
1404 }
1405
1406 switch(q->soc_type)
1407 {
1408 case BT_SOC_ROME:
1409 ALOGI("%s: ROME case", __func__);
1410 property_get("wc_transport.patch_dnld_inprog", inProgress, "null");
1411 if(strcmp(inProgress,"null") == 0) {
1412 retval = false;
1413 } else {
1414 retval = true;
1415 }
1416 break;
1417 case BT_SOC_CHEROKEE:
1418 ALOGI("%s: CHEROKEE case", __func__);
1419 break;
1420 case BT_SOC_DEFAULT:
1421 break;
1422 default:
1423 ALOGE("Unknown btSocType: 0x%x", q->soc_type);
1424 break;
1425 }
1426 return retval;
1427 }
1428
is_debug_force_special_bytes()1429 static bool is_debug_force_special_bytes() {
1430 int ret = 0;
1431 char value[PROPERTY_VALUE_MAX] = {'\0'};
1432 bool enabled = false;
1433 #ifdef ENABLE_DBG_FLAGS
1434 enabled = true;
1435 #endif
1436
1437 ret = property_get("wc_transport.force_special_byte", value, NULL);
1438
1439 if (ret) {
1440 enabled = (strcmp(value, "false") ==0) ? false : true;
1441 ALOGV("%s: wc_transport.force_special_byte: %s, enabled: %d ",
1442 __func__, value, enabled);
1443 }
1444
1445 return enabled;
1446 }
1447
1448 // Entry point of DLib
1449 const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
1450 sizeof(bt_vendor_interface_t),
1451 init,
1452 op,
1453 cleanup
1454 };
1455