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