1 /******************************************************************************
2 *
3 * Copyright (C) 2009-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: hardware.c
22 *
23 * Description: Contains controller-specific functions, like
24 * firmware patch download
25 * low power mode operations
26 *
27 ******************************************************************************/
28
29 #define LOG_TAG "bt_hwcfg"
30
31 #include <utils/Log.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <signal.h>
35 #include <time.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <dirent.h>
39 #include <ctype.h>
40 #include <cutils/properties.h>
41 #include <stdlib.h>
42 #include "bt_hci_bdroid.h"
43 #include "bt_vendor_brcm.h"
44 #include "userial.h"
45 #include "userial_vendor.h"
46 #include "upio.h"
47
48 /******************************************************************************
49 ** Constants & Macros
50 ******************************************************************************/
51
52 #ifndef BTHW_DBG
53 #define BTHW_DBG FALSE
54 #endif
55
56 #if (BTHW_DBG == TRUE)
57 #define BTHWDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
58 #else
59 #define BTHWDBG(param, ...) {}
60 #endif
61
62 #define FW_PATCHFILE_EXTENSION ".hcd"
63 #define FW_PATCHFILE_EXTENSION_LEN 4
64 #define FW_PATCHFILE_PATH_MAXLEN 248 /* Local_Name length of return of
65 HCI_Read_Local_Name */
66
67 #define HCI_CMD_MAX_LEN 258
68
69 #define HCI_RESET 0x0C03
70 #define HCI_VSC_WRITE_UART_CLOCK_SETTING 0xFC45
71 #define HCI_VSC_UPDATE_BAUDRATE 0xFC18
72 #define HCI_READ_LOCAL_NAME 0x0C14
73 #define HCI_VSC_DOWNLOAD_MINIDRV 0xFC2E
74 #define HCI_VSC_WRITE_BD_ADDR 0xFC01
75 #define HCI_VSC_WRITE_SLEEP_MODE 0xFC27
76 #define HCI_VSC_WRITE_SCO_PCM_INT_PARAM 0xFC1C
77 #define HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM 0xFC1E
78 #define HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM 0xFC6D
79 #define HCI_VSC_ENABLE_WBS 0xFC7E
80 #define HCI_VSC_LAUNCH_RAM 0xFC4E
81 #define HCI_READ_LOCAL_BDADDR 0x1009
82
83 #define HCI_EVT_CMD_CMPL_STATUS_RET_BYTE 5
84 #define HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING 6
85 #define HCI_EVT_CMD_CMPL_LOCAL_BDADDR_ARRAY 6
86 #define HCI_EVT_CMD_CMPL_OPCODE 3
87 #define LPM_CMD_PARAM_SIZE 12
88 #define UPDATE_BAUDRATE_CMD_PARAM_SIZE 6
89 #define HCI_CMD_PREAMBLE_SIZE 3
90 #define HCD_REC_PAYLOAD_LEN_BYTE 2
91 #define BD_ADDR_LEN 6
92 #define LOCAL_NAME_BUFFER_LEN 32
93 #define LOCAL_BDADDR_PATH_BUFFER_LEN 256
94
95 #define STREAM_TO_UINT16(u16, p) {u16 = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); (p) += 2;}
96 #define UINT8_TO_STREAM(p, u8) {*(p)++ = (uint8_t)(u8);}
97 #define UINT16_TO_STREAM(p, u16) {*(p)++ = (uint8_t)(u16); *(p)++ = (uint8_t)((u16) >> 8);}
98 #define UINT32_TO_STREAM(p, u32) {*(p)++ = (uint8_t)(u32); *(p)++ = (uint8_t)((u32) >> 8); *(p)++ = (uint8_t)((u32) >> 16); *(p)++ = (uint8_t)((u32) >> 24);}
99
100 #define SCO_INTERFACE_PCM 0
101 #define SCO_INTERFACE_I2S 1
102
103 /* one byte is for enable/disable
104 next 2 bytes are for codec type */
105 #define SCO_CODEC_PARAM_SIZE 3
106
107 /******************************************************************************
108 ** Local type definitions
109 ******************************************************************************/
110
111 /* Hardware Configuration State */
112 enum {
113 HW_CFG_START = 1,
114 HW_CFG_SET_UART_CLOCK,
115 HW_CFG_SET_UART_BAUD_1,
116 HW_CFG_READ_LOCAL_NAME,
117 HW_CFG_DL_MINIDRIVER,
118 HW_CFG_DL_FW_PATCH,
119 HW_CFG_SET_UART_BAUD_2,
120 HW_CFG_SET_BD_ADDR
121 #if (USE_CONTROLLER_BDADDR == TRUE)
122 , HW_CFG_READ_BD_ADDR
123 #endif
124 };
125
126 /* h/w config control block */
127 typedef struct
128 {
129 uint8_t state; /* Hardware configuration state */
130 int fw_fd; /* FW patch file fd */
131 uint8_t f_set_baud_2; /* Baud rate switch state */
132 char local_chip_name[LOCAL_NAME_BUFFER_LEN];
133 } bt_hw_cfg_cb_t;
134
135 /* low power mode parameters */
136 typedef struct
137 {
138 uint8_t sleep_mode; /* 0(disable),1(UART),9(H5) */
139 uint8_t host_stack_idle_threshold; /* Unit scale 300ms/25ms */
140 uint8_t host_controller_idle_threshold; /* Unit scale 300ms/25ms */
141 uint8_t bt_wake_polarity; /* 0=Active Low, 1= Active High */
142 uint8_t host_wake_polarity; /* 0=Active Low, 1= Active High */
143 uint8_t allow_host_sleep_during_sco;
144 uint8_t combine_sleep_mode_and_lpm;
145 uint8_t enable_uart_txd_tri_state; /* UART_TXD Tri-State */
146 uint8_t sleep_guard_time; /* sleep guard time in 12.5ms */
147 uint8_t wakeup_guard_time; /* wakeup guard time in 12.5ms */
148 uint8_t txd_config; /* TXD is high in sleep state */
149 uint8_t pulsed_host_wake; /* pulsed host wake if mode = 1 */
150 } bt_lpm_param_t;
151
152 /* Firmware re-launch settlement time */
153 typedef struct {
154 const char *chipset_name;
155 const uint32_t delay_time;
156 } fw_settlement_entry_t;
157
158
159 /******************************************************************************
160 ** Externs
161 ******************************************************************************/
162
163 void hw_config_cback(void *p_evt_buf);
164 extern uint8_t vnd_local_bd_addr[BD_ADDR_LEN];
165
166
167 /******************************************************************************
168 ** Static variables
169 ******************************************************************************/
170
171 static char fw_patchfile_path[256] = FW_PATCHFILE_LOCATION;
172 static char fw_patchfile_name[128] = { 0 };
173 #if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
174 static int fw_patch_settlement_delay = -1;
175 #endif
176
177 static int wbs_sample_rate = SCO_WBS_SAMPLE_RATE;
178 static bt_hw_cfg_cb_t hw_cfg_cb;
179
180 static bt_lpm_param_t lpm_param =
181 {
182 LPM_SLEEP_MODE,
183 LPM_IDLE_THRESHOLD,
184 LPM_HC_IDLE_THRESHOLD,
185 LPM_BT_WAKE_POLARITY,
186 LPM_HOST_WAKE_POLARITY,
187 LPM_ALLOW_HOST_SLEEP_DURING_SCO,
188 LPM_COMBINE_SLEEP_MODE_AND_LPM,
189 LPM_ENABLE_UART_TXD_TRI_STATE,
190 0, /* not applicable */
191 0, /* not applicable */
192 0, /* not applicable */
193 LPM_PULSED_HOST_WAKE
194 };
195
196 /* need to update the bt_sco_i2spcm_param as well
197 bt_sco_i2spcm_param will be used for WBS setting
198 update the bt_sco_param and bt_sco_i2spcm_param */
199 static uint8_t bt_sco_param[SCO_PCM_PARAM_SIZE] =
200 {
201 SCO_PCM_ROUTING,
202 SCO_PCM_IF_CLOCK_RATE,
203 SCO_PCM_IF_FRAME_TYPE,
204 SCO_PCM_IF_SYNC_MODE,
205 SCO_PCM_IF_CLOCK_MODE
206 };
207
208 static uint8_t bt_pcm_data_fmt_param[PCM_DATA_FORMAT_PARAM_SIZE] =
209 {
210 PCM_DATA_FMT_SHIFT_MODE,
211 PCM_DATA_FMT_FILL_BITS,
212 PCM_DATA_FMT_FILL_METHOD,
213 PCM_DATA_FMT_FILL_NUM,
214 PCM_DATA_FMT_JUSTIFY_MODE
215 };
216
217 static uint8_t bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_SIZE] =
218 {
219 SCO_I2SPCM_IF_MODE,
220 SCO_I2SPCM_IF_ROLE,
221 SCO_I2SPCM_IF_SAMPLE_RATE,
222 SCO_I2SPCM_IF_CLOCK_RATE
223 };
224
225 /*
226 * The look-up table of recommended firmware settlement delay (milliseconds) on
227 * known chipsets.
228 */
229 static const fw_settlement_entry_t fw_settlement_table[] = {
230 {"BCM43241", 200},
231 {"BCM43341", 100},
232 {(const char *) NULL, 100} // Giving the generic fw settlement delay setting.
233 };
234
235
236 /*
237 * NOTICE:
238 * If the platform plans to run I2S interface bus over I2S/PCM port of the
239 * BT Controller with the Host AP, explicitly set "SCO_USE_I2S_INTERFACE = TRUE"
240 * in the correspodning include/vnd_<target>.txt file.
241 * Otherwise, leave SCO_USE_I2S_INTERFACE undefined in the vnd_<target>.txt file.
242 * And, PCM interface will be set as the default bus format running over I2S/PCM
243 * port.
244 */
245 #if (defined(SCO_USE_I2S_INTERFACE) && SCO_USE_I2S_INTERFACE == TRUE)
246 static uint8_t sco_bus_interface = SCO_INTERFACE_I2S;
247 #else
248 static uint8_t sco_bus_interface = SCO_INTERFACE_PCM;
249 #endif
250
251 #define INVALID_SCO_CLOCK_RATE 0xFF
252 static uint8_t sco_bus_clock_rate = INVALID_SCO_CLOCK_RATE;
253 static uint8_t sco_bus_wbs_clock_rate = INVALID_SCO_CLOCK_RATE;
254
255 /******************************************************************************
256 ** Static functions
257 ******************************************************************************/
258 static void hw_sco_i2spcm_config(void *p_mem, uint16_t codec);
259
260 /******************************************************************************
261 ** Controller Initialization Static Functions
262 ******************************************************************************/
263
264 /*******************************************************************************
265 **
266 ** Function look_up_fw_settlement_delay
267 **
268 ** Description If FW_PATCH_SETTLEMENT_DELAY_MS has not been explicitly
269 ** re-defined in the platform specific build-time configuration
270 ** file, we will search into the look-up table for a
271 ** recommended firmware settlement delay value.
272 **
273 ** Although the settlement time might be also related to board
274 ** configurations such as the crystal clocking speed.
275 **
276 ** Returns Firmware settlement delay
277 **
278 *******************************************************************************/
look_up_fw_settlement_delay(void)279 uint32_t look_up_fw_settlement_delay (void)
280 {
281 uint32_t ret_value;
282 fw_settlement_entry_t *p_entry;
283
284 if (FW_PATCH_SETTLEMENT_DELAY_MS > 0)
285 {
286 ret_value = FW_PATCH_SETTLEMENT_DELAY_MS;
287 }
288 #if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
289 else if (fw_patch_settlement_delay >= 0)
290 {
291 ret_value = fw_patch_settlement_delay;
292 }
293 #endif
294 else
295 {
296 p_entry = (fw_settlement_entry_t *)fw_settlement_table;
297
298 while (p_entry->chipset_name != NULL)
299 {
300 if (strstr(hw_cfg_cb.local_chip_name, p_entry->chipset_name)!=NULL)
301 {
302 break;
303 }
304
305 p_entry++;
306 }
307
308 ret_value = p_entry->delay_time;
309 }
310
311 BTHWDBG( "Settlement delay -- %d ms", ret_value);
312
313 return (ret_value);
314 }
315
316 /*******************************************************************************
317 **
318 ** Function ms_delay
319 **
320 ** Description sleep unconditionally for timeout milliseconds
321 **
322 ** Returns None
323 **
324 *******************************************************************************/
ms_delay(uint32_t timeout)325 void ms_delay (uint32_t timeout)
326 {
327 struct timespec delay;
328 int err;
329
330 if (timeout == 0)
331 return;
332
333 delay.tv_sec = timeout / 1000;
334 delay.tv_nsec = 1000 * 1000 * (timeout%1000);
335
336 /* [u]sleep can't be used because it uses SIGALRM */
337 do {
338 err = nanosleep(&delay, &delay);
339 } while (err < 0 && errno ==EINTR);
340 }
341
342 /*******************************************************************************
343 **
344 ** Function line_speed_to_userial_baud
345 **
346 ** Description helper function converts line speed number into USERIAL baud
347 ** rate symbol
348 **
349 ** Returns unit8_t (USERIAL baud symbol)
350 **
351 *******************************************************************************/
line_speed_to_userial_baud(uint32_t line_speed)352 uint8_t line_speed_to_userial_baud(uint32_t line_speed)
353 {
354 uint8_t baud;
355
356 if (line_speed == 4000000)
357 baud = USERIAL_BAUD_4M;
358 else if (line_speed == 3000000)
359 baud = USERIAL_BAUD_3M;
360 else if (line_speed == 2000000)
361 baud = USERIAL_BAUD_2M;
362 else if (line_speed == 1000000)
363 baud = USERIAL_BAUD_1M;
364 else if (line_speed == 921600)
365 baud = USERIAL_BAUD_921600;
366 else if (line_speed == 460800)
367 baud = USERIAL_BAUD_460800;
368 else if (line_speed == 230400)
369 baud = USERIAL_BAUD_230400;
370 else if (line_speed == 115200)
371 baud = USERIAL_BAUD_115200;
372 else if (line_speed == 57600)
373 baud = USERIAL_BAUD_57600;
374 else if (line_speed == 19200)
375 baud = USERIAL_BAUD_19200;
376 else if (line_speed == 9600)
377 baud = USERIAL_BAUD_9600;
378 else if (line_speed == 1200)
379 baud = USERIAL_BAUD_1200;
380 else if (line_speed == 600)
381 baud = USERIAL_BAUD_600;
382 else
383 {
384 ALOGE( "userial vendor: unsupported baud speed %d", line_speed);
385 baud = USERIAL_BAUD_115200;
386 }
387
388 return baud;
389 }
390
391
392 /*******************************************************************************
393 **
394 ** Function hw_strncmp
395 **
396 ** Description Used to compare two strings in caseless
397 **
398 ** Returns 0: match, otherwise: not match
399 **
400 *******************************************************************************/
hw_strncmp(const char * p_str1,const char * p_str2,const int len)401 static int hw_strncmp (const char *p_str1, const char *p_str2, const int len)
402 {
403 int i;
404
405 if (!p_str1 || !p_str2)
406 return (1);
407
408 for (i = 0; i < len; i++)
409 {
410 if (toupper(p_str1[i]) != toupper(p_str2[i]))
411 return (i+1);
412 }
413
414 return 0;
415 }
416
417 /*******************************************************************************
418 **
419 ** Function hw_config_findpatch
420 **
421 ** Description Search for a proper firmware patch file
422 ** The selected firmware patch file name with full path
423 ** will be stored in the input string parameter, i.e.
424 ** p_chip_id_str, when returns.
425 **
426 ** Returns TRUE when found the target patch file, otherwise FALSE
427 **
428 *******************************************************************************/
hw_config_findpatch(char * p_chip_id_str)429 static uint8_t hw_config_findpatch(char *p_chip_id_str)
430 {
431 DIR *dirp;
432 struct dirent *dp;
433 int filenamelen;
434 uint8_t retval = FALSE;
435
436 BTHWDBG("Target name = [%s]", p_chip_id_str);
437
438 if (strlen(fw_patchfile_name)> 0)
439 {
440 /* If specific filepath and filename have been given in run-time
441 * configuration /etc/bluetooth/bt_vendor.conf file, we will use them
442 * to concatenate the filename to open rather than searching a file
443 * matching to chipset name in the fw_patchfile_path folder.
444 */
445 sprintf(p_chip_id_str, "%s", fw_patchfile_path);
446 if (fw_patchfile_path[strlen(fw_patchfile_path)- 1] != '/')
447 {
448 strcat(p_chip_id_str, "/");
449 }
450 strcat(p_chip_id_str, fw_patchfile_name);
451
452 ALOGI("FW patchfile: %s", p_chip_id_str);
453 return TRUE;
454 }
455
456 if ((dirp = opendir(fw_patchfile_path)) != NULL)
457 {
458 /* Fetch next filename in patchfile directory */
459 while ((dp = readdir(dirp)) != NULL)
460 {
461 /* Check if filename starts with chip-id name */
462 if ((hw_strncmp(dp->d_name, p_chip_id_str, strlen(p_chip_id_str)) \
463 ) == 0)
464 {
465 /* Check if it has .hcd extenstion */
466 filenamelen = strlen(dp->d_name);
467 if ((filenamelen >= FW_PATCHFILE_EXTENSION_LEN) &&
468 ((hw_strncmp(
469 &dp->d_name[filenamelen-FW_PATCHFILE_EXTENSION_LEN], \
470 FW_PATCHFILE_EXTENSION, \
471 FW_PATCHFILE_EXTENSION_LEN) \
472 ) == 0))
473 {
474 ALOGI("Found patchfile: %s/%s", \
475 fw_patchfile_path, dp->d_name);
476
477 /* Make sure length does not exceed maximum */
478 if ((filenamelen + strlen(fw_patchfile_path)) > \
479 FW_PATCHFILE_PATH_MAXLEN)
480 {
481 ALOGE("Invalid patchfile name (too long)");
482 }
483 else
484 {
485 memset(p_chip_id_str, 0, FW_PATCHFILE_PATH_MAXLEN);
486 /* Found patchfile. Store location and name */
487 strcpy(p_chip_id_str, fw_patchfile_path);
488 if (fw_patchfile_path[ \
489 strlen(fw_patchfile_path)- 1 \
490 ] != '/')
491 {
492 strcat(p_chip_id_str, "/");
493 }
494 strcat(p_chip_id_str, dp->d_name);
495 retval = TRUE;
496 }
497 break;
498 }
499 }
500 }
501
502 closedir(dirp);
503
504 if (retval == FALSE)
505 {
506 /* Try again chip name without revision info */
507
508 int len = strlen(p_chip_id_str);
509 char *p = p_chip_id_str + len - 1;
510
511 /* Scan backward and look for the first alphabet
512 which is not M or m
513 */
514 while (len > 3) // BCM****
515 {
516 if ((isdigit(*p)==0) && (*p != 'M') && (*p != 'm'))
517 break;
518
519 p--;
520 len--;
521 }
522
523 if (len > 3)
524 {
525 *p = 0;
526 retval = hw_config_findpatch(p_chip_id_str);
527 }
528 }
529 }
530 else
531 {
532 ALOGE("Could not open %s", fw_patchfile_path);
533 }
534
535 return (retval);
536 }
537
538 /*******************************************************************************
539 **
540 ** Function hw_config_set_bdaddr
541 **
542 ** Description Program controller's Bluetooth Device Address
543 **
544 ** Returns TRUE, if valid address is sent
545 ** FALSE, otherwise
546 **
547 *******************************************************************************/
hw_config_set_bdaddr(HC_BT_HDR * p_buf)548 static uint8_t hw_config_set_bdaddr(HC_BT_HDR *p_buf)
549 {
550 uint8_t retval = FALSE;
551 uint8_t *p = (uint8_t *) (p_buf + 1);
552
553 ALOGI("Setting local bd addr to %02X:%02X:%02X:%02X:%02X:%02X",
554 vnd_local_bd_addr[0], vnd_local_bd_addr[1], vnd_local_bd_addr[2],
555 vnd_local_bd_addr[3], vnd_local_bd_addr[4], vnd_local_bd_addr[5]);
556
557 UINT16_TO_STREAM(p, HCI_VSC_WRITE_BD_ADDR);
558 *p++ = BD_ADDR_LEN; /* parameter length */
559 *p++ = vnd_local_bd_addr[5];
560 *p++ = vnd_local_bd_addr[4];
561 *p++ = vnd_local_bd_addr[3];
562 *p++ = vnd_local_bd_addr[2];
563 *p++ = vnd_local_bd_addr[1];
564 *p = vnd_local_bd_addr[0];
565
566 p_buf->len = HCI_CMD_PREAMBLE_SIZE + BD_ADDR_LEN;
567 hw_cfg_cb.state = HW_CFG_SET_BD_ADDR;
568
569 retval = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_BD_ADDR, p_buf, \
570 hw_config_cback);
571
572 return (retval);
573 }
574
575 #if (USE_CONTROLLER_BDADDR == TRUE)
576 /*******************************************************************************
577 **
578 ** Function hw_config_read_bdaddr
579 **
580 ** Description Read controller's Bluetooth Device Address
581 **
582 ** Returns TRUE, if valid address is sent
583 ** FALSE, otherwise
584 **
585 *******************************************************************************/
hw_config_read_bdaddr(HC_BT_HDR * p_buf)586 static uint8_t hw_config_read_bdaddr(HC_BT_HDR *p_buf)
587 {
588 uint8_t retval = FALSE;
589 uint8_t *p = (uint8_t *) (p_buf + 1);
590
591 UINT16_TO_STREAM(p, HCI_READ_LOCAL_BDADDR);
592 *p = 0; /* parameter length */
593
594 p_buf->len = HCI_CMD_PREAMBLE_SIZE;
595 hw_cfg_cb.state = HW_CFG_READ_BD_ADDR;
596
597 retval = bt_vendor_cbacks->xmit_cb(HCI_READ_LOCAL_BDADDR, p_buf, \
598 hw_config_cback);
599
600 return (retval);
601 }
602 #endif // (USE_CONTROLLER_BDADDR == TRUE)
603
604 /*******************************************************************************
605 **
606 ** Function hw_config_cback
607 **
608 ** Description Callback function for controller configuration
609 **
610 ** Returns None
611 **
612 *******************************************************************************/
hw_config_cback(void * p_mem)613 void hw_config_cback(void *p_mem)
614 {
615 HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
616 char *p_name, *p_tmp;
617 uint8_t *p, status;
618 uint16_t opcode;
619 HC_BT_HDR *p_buf=NULL;
620 uint8_t is_proceeding = FALSE;
621 int i;
622 int delay=100;
623 #if (USE_CONTROLLER_BDADDR == TRUE)
624 const uint8_t null_bdaddr[BD_ADDR_LEN] = {0,0,0,0,0,0};
625 #endif
626
627 status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
628 p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
629 STREAM_TO_UINT16(opcode,p);
630
631 /* Ask a new buffer big enough to hold any HCI commands sent in here */
632 if ((status == 0) && bt_vendor_cbacks)
633 p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
634 HCI_CMD_MAX_LEN);
635
636 if (p_buf != NULL)
637 {
638 p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
639 p_buf->offset = 0;
640 p_buf->len = 0;
641 p_buf->layer_specific = 0;
642
643 p = (uint8_t *) (p_buf + 1);
644
645 switch (hw_cfg_cb.state)
646 {
647 case HW_CFG_SET_UART_BAUD_1:
648 /* update baud rate of host's UART port */
649 ALOGI("bt vendor lib: set UART baud %i", UART_TARGET_BAUD_RATE);
650 userial_vendor_set_baud( \
651 line_speed_to_userial_baud(UART_TARGET_BAUD_RATE) \
652 );
653
654 /* read local name */
655 UINT16_TO_STREAM(p, HCI_READ_LOCAL_NAME);
656 *p = 0; /* parameter length */
657
658 p_buf->len = HCI_CMD_PREAMBLE_SIZE;
659 hw_cfg_cb.state = HW_CFG_READ_LOCAL_NAME;
660
661 is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_READ_LOCAL_NAME, \
662 p_buf, hw_config_cback);
663 break;
664
665 case HW_CFG_READ_LOCAL_NAME:
666 p_tmp = p_name = (char *) (p_evt_buf + 1) + \
667 HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING;
668
669 for (i=0; (i < LOCAL_NAME_BUFFER_LEN)||(*(p_name+i) != 0); i++)
670 *(p_name+i) = toupper(*(p_name+i));
671
672 if ((p_name = strstr(p_name, "BCM")) != NULL)
673 {
674 strncpy(hw_cfg_cb.local_chip_name, p_name, \
675 LOCAL_NAME_BUFFER_LEN-1);
676 }
677 else
678 {
679 strncpy(hw_cfg_cb.local_chip_name, "UNKNOWN", \
680 LOCAL_NAME_BUFFER_LEN-1);
681 p_name = p_tmp;
682 }
683
684 hw_cfg_cb.local_chip_name[LOCAL_NAME_BUFFER_LEN-1] = 0;
685
686 BTHWDBG("Chipset %s", hw_cfg_cb.local_chip_name);
687
688 if ((status = hw_config_findpatch(p_name)) == TRUE)
689 {
690 if ((hw_cfg_cb.fw_fd = open(p_name, O_RDONLY)) == -1)
691 {
692 ALOGE("vendor lib preload failed to open [%s]", p_name);
693 }
694 else
695 {
696 /* vsc_download_minidriver */
697 UINT16_TO_STREAM(p, HCI_VSC_DOWNLOAD_MINIDRV);
698 *p = 0; /* parameter length */
699
700 p_buf->len = HCI_CMD_PREAMBLE_SIZE;
701 hw_cfg_cb.state = HW_CFG_DL_MINIDRIVER;
702
703 is_proceeding = bt_vendor_cbacks->xmit_cb( \
704 HCI_VSC_DOWNLOAD_MINIDRV, p_buf, \
705 hw_config_cback);
706 }
707 }
708 else
709 {
710 ALOGE( \
711 "vendor lib preload failed to locate firmware patch file" \
712 );
713 }
714
715 if (is_proceeding == FALSE)
716 {
717 is_proceeding = hw_config_set_bdaddr(p_buf);
718 }
719 break;
720
721 case HW_CFG_DL_MINIDRIVER:
722 /* give time for placing firmware in download mode */
723 ms_delay(50);
724 hw_cfg_cb.state = HW_CFG_DL_FW_PATCH;
725 /* fall through intentionally */
726 case HW_CFG_DL_FW_PATCH:
727 p_buf->len = read(hw_cfg_cb.fw_fd, p, HCI_CMD_PREAMBLE_SIZE);
728 if (p_buf->len > 0)
729 {
730 if ((p_buf->len < HCI_CMD_PREAMBLE_SIZE) || \
731 (opcode == HCI_VSC_LAUNCH_RAM))
732 {
733 ALOGW("firmware patch file might be altered!");
734 }
735 else
736 {
737 p_buf->len += read(hw_cfg_cb.fw_fd, \
738 p+HCI_CMD_PREAMBLE_SIZE,\
739 *(p+HCD_REC_PAYLOAD_LEN_BYTE));
740 STREAM_TO_UINT16(opcode,p);
741 is_proceeding = bt_vendor_cbacks->xmit_cb(opcode, \
742 p_buf, hw_config_cback);
743 break;
744 }
745 }
746
747 close(hw_cfg_cb.fw_fd);
748 hw_cfg_cb.fw_fd = -1;
749
750 /* Normally the firmware patch configuration file
751 * sets the new starting baud rate at 115200.
752 * So, we need update host's baud rate accordingly.
753 */
754 ALOGI("bt vendor lib: set UART baud 115200");
755 userial_vendor_set_baud(USERIAL_BAUD_115200);
756
757 /* Next, we would like to boost baud rate up again
758 * to desired working speed.
759 */
760 hw_cfg_cb.f_set_baud_2 = TRUE;
761
762 /* Check if we need to pause a few hundred milliseconds
763 * before sending down any HCI command.
764 */
765 delay = look_up_fw_settlement_delay();
766 ALOGI("Setting fw settlement delay to %d ", delay);
767 ms_delay(delay);
768
769 p_buf->len = HCI_CMD_PREAMBLE_SIZE;
770 UINT16_TO_STREAM(p, HCI_RESET);
771 *p = 0; /* parameter length */
772 hw_cfg_cb.state = HW_CFG_START;
773 is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf, hw_config_cback);
774 break;
775
776 case HW_CFG_START:
777 if (UART_TARGET_BAUD_RATE > 3000000)
778 {
779 /* set UART clock to 48MHz */
780 UINT16_TO_STREAM(p, HCI_VSC_WRITE_UART_CLOCK_SETTING);
781 *p++ = 1; /* parameter length */
782 *p = 1; /* (1,"UART CLOCK 48 MHz")(2,"UART CLOCK 24 MHz") */
783
784 p_buf->len = HCI_CMD_PREAMBLE_SIZE + 1;
785 hw_cfg_cb.state = HW_CFG_SET_UART_CLOCK;
786
787 is_proceeding = bt_vendor_cbacks->xmit_cb( \
788 HCI_VSC_WRITE_UART_CLOCK_SETTING, \
789 p_buf, hw_config_cback);
790 break;
791 }
792 /* fall through intentionally */
793 case HW_CFG_SET_UART_CLOCK:
794 /* set controller's UART baud rate to 3M */
795 UINT16_TO_STREAM(p, HCI_VSC_UPDATE_BAUDRATE);
796 *p++ = UPDATE_BAUDRATE_CMD_PARAM_SIZE; /* parameter length */
797 *p++ = 0; /* encoded baud rate */
798 *p++ = 0; /* use encoded form */
799 UINT32_TO_STREAM(p, UART_TARGET_BAUD_RATE);
800
801 p_buf->len = HCI_CMD_PREAMBLE_SIZE + \
802 UPDATE_BAUDRATE_CMD_PARAM_SIZE;
803 hw_cfg_cb.state = (hw_cfg_cb.f_set_baud_2) ? \
804 HW_CFG_SET_UART_BAUD_2 : HW_CFG_SET_UART_BAUD_1;
805
806 is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_VSC_UPDATE_BAUDRATE, \
807 p_buf, hw_config_cback);
808 break;
809
810 case HW_CFG_SET_UART_BAUD_2:
811 /* update baud rate of host's UART port */
812 ALOGI("bt vendor lib: set UART baud %i", UART_TARGET_BAUD_RATE);
813 userial_vendor_set_baud( \
814 line_speed_to_userial_baud(UART_TARGET_BAUD_RATE) \
815 );
816
817 #if (USE_CONTROLLER_BDADDR == TRUE)
818 if ((is_proceeding = hw_config_read_bdaddr(p_buf)) == TRUE)
819 break;
820 #else
821 if ((is_proceeding = hw_config_set_bdaddr(p_buf)) == TRUE)
822 break;
823 #endif
824 /* fall through intentionally */
825 case HW_CFG_SET_BD_ADDR:
826 ALOGI("vendor lib fwcfg completed");
827 bt_vendor_cbacks->dealloc(p_buf);
828 bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
829
830 hw_cfg_cb.state = 0;
831
832 if (hw_cfg_cb.fw_fd != -1)
833 {
834 close(hw_cfg_cb.fw_fd);
835 hw_cfg_cb.fw_fd = -1;
836 }
837
838 is_proceeding = TRUE;
839 break;
840
841 #if (USE_CONTROLLER_BDADDR == TRUE)
842 case HW_CFG_READ_BD_ADDR:
843 p_tmp = (char *) (p_evt_buf + 1) + \
844 HCI_EVT_CMD_CMPL_LOCAL_BDADDR_ARRAY;
845
846 if (memcmp(p_tmp, null_bdaddr, BD_ADDR_LEN) == 0)
847 {
848 // Controller does not have a valid OTP BDADDR!
849 // Set the BTIF initial BDADDR instead.
850 if ((is_proceeding = hw_config_set_bdaddr(p_buf)) == TRUE)
851 break;
852 }
853 else
854 {
855 ALOGI("Controller OTP bdaddr %02X:%02X:%02X:%02X:%02X:%02X",
856 *(p_tmp+5), *(p_tmp+4), *(p_tmp+3),
857 *(p_tmp+2), *(p_tmp+1), *p_tmp);
858 }
859
860 ALOGI("vendor lib fwcfg completed");
861 bt_vendor_cbacks->dealloc(p_buf);
862 bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
863
864 hw_cfg_cb.state = 0;
865
866 if (hw_cfg_cb.fw_fd != -1)
867 {
868 close(hw_cfg_cb.fw_fd);
869 hw_cfg_cb.fw_fd = -1;
870 }
871
872 is_proceeding = TRUE;
873 break;
874 #endif // (USE_CONTROLLER_BDADDR == TRUE)
875 } // switch(hw_cfg_cb.state)
876 } // if (p_buf != NULL)
877
878 /* Free the RX event buffer */
879 if (bt_vendor_cbacks)
880 bt_vendor_cbacks->dealloc(p_evt_buf);
881
882 if (is_proceeding == FALSE)
883 {
884 ALOGE("vendor lib fwcfg aborted!!!");
885 if (bt_vendor_cbacks)
886 {
887 if (p_buf != NULL)
888 bt_vendor_cbacks->dealloc(p_buf);
889
890 bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
891 }
892
893 if (hw_cfg_cb.fw_fd != -1)
894 {
895 close(hw_cfg_cb.fw_fd);
896 hw_cfg_cb.fw_fd = -1;
897 }
898
899 hw_cfg_cb.state = 0;
900 }
901 }
902
903 /******************************************************************************
904 ** LPM Static Functions
905 ******************************************************************************/
906
907 /*******************************************************************************
908 **
909 ** Function hw_lpm_ctrl_cback
910 **
911 ** Description Callback function for lpm enable/disable rquest
912 **
913 ** Returns None
914 **
915 *******************************************************************************/
hw_lpm_ctrl_cback(void * p_mem)916 void hw_lpm_ctrl_cback(void *p_mem)
917 {
918 HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
919 bt_vendor_op_result_t status = BT_VND_OP_RESULT_FAIL;
920
921 if (*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0)
922 {
923 status = BT_VND_OP_RESULT_SUCCESS;
924 }
925
926 if (bt_vendor_cbacks)
927 {
928 bt_vendor_cbacks->lpm_cb(status);
929 bt_vendor_cbacks->dealloc(p_evt_buf);
930 }
931 }
932
933
934 #if (SCO_CFG_INCLUDED == TRUE)
935 /*****************************************************************************
936 ** SCO Configuration Static Functions
937 *****************************************************************************/
938
939 /*******************************************************************************
940 **
941 ** Function hw_sco_i2spcm_cfg_cback
942 **
943 ** Description Callback function for SCO I2S/PCM configuration rquest
944 **
945 ** Returns None
946 **
947 *******************************************************************************/
hw_sco_i2spcm_cfg_cback(void * p_mem)948 static void hw_sco_i2spcm_cfg_cback(void *p_mem)
949 {
950 HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem;
951 uint8_t *p;
952 uint16_t opcode;
953 HC_BT_HDR *p_buf = NULL;
954 bt_vendor_op_result_t status = BT_VND_OP_RESULT_FAIL;
955
956 p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
957 STREAM_TO_UINT16(opcode,p);
958
959 if (*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0)
960 {
961 status = BT_VND_OP_RESULT_SUCCESS;
962 }
963
964 /* Free the RX event buffer */
965 if (bt_vendor_cbacks)
966 bt_vendor_cbacks->dealloc(p_evt_buf);
967
968 if (status == BT_VND_OP_RESULT_SUCCESS)
969 {
970 if ((opcode == HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM) &&
971 (SCO_INTERFACE_PCM == sco_bus_interface))
972 {
973 uint8_t ret = FALSE;
974
975 /* Ask a new buffer to hold WRITE_SCO_PCM_INT_PARAM command */
976 if (bt_vendor_cbacks)
977 p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(
978 BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + SCO_PCM_PARAM_SIZE);
979 if (p_buf)
980 {
981 p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
982 p_buf->offset = 0;
983 p_buf->layer_specific = 0;
984 p_buf->len = HCI_CMD_PREAMBLE_SIZE + SCO_PCM_PARAM_SIZE;
985 p = (uint8_t *)(p_buf + 1);
986
987 /* do we need this VSC for I2S??? */
988 UINT16_TO_STREAM(p, HCI_VSC_WRITE_SCO_PCM_INT_PARAM);
989 *p++ = SCO_PCM_PARAM_SIZE;
990 memcpy(p, &bt_sco_param, SCO_PCM_PARAM_SIZE);
991 ALOGI("SCO PCM configure {0x%x, 0x%x, 0x%x, 0x%x, 0x%x}",
992 bt_sco_param[0], bt_sco_param[1], bt_sco_param[2], bt_sco_param[3],
993 bt_sco_param[4]);
994 if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_SCO_PCM_INT_PARAM, p_buf,
995 hw_sco_i2spcm_cfg_cback)) == FALSE)
996 {
997 bt_vendor_cbacks->dealloc(p_buf);
998 }
999 else
1000 return;
1001 }
1002 status = BT_VND_OP_RESULT_FAIL;
1003 }
1004 else if ((opcode == HCI_VSC_WRITE_SCO_PCM_INT_PARAM) &&
1005 (SCO_INTERFACE_PCM == sco_bus_interface))
1006 {
1007 uint8_t ret = FALSE;
1008
1009 /* Ask a new buffer to hold WRITE_PCM_DATA_FORMAT_PARAM command */
1010 if (bt_vendor_cbacks)
1011 p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(
1012 BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + PCM_DATA_FORMAT_PARAM_SIZE);
1013 if (p_buf)
1014 {
1015 p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1016 p_buf->offset = 0;
1017 p_buf->layer_specific = 0;
1018 p_buf->len = HCI_CMD_PREAMBLE_SIZE + PCM_DATA_FORMAT_PARAM_SIZE;
1019
1020 p = (uint8_t *)(p_buf + 1);
1021 UINT16_TO_STREAM(p, HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM);
1022 *p++ = PCM_DATA_FORMAT_PARAM_SIZE;
1023 memcpy(p, &bt_pcm_data_fmt_param, PCM_DATA_FORMAT_PARAM_SIZE);
1024
1025 ALOGI("SCO PCM data format {0x%x, 0x%x, 0x%x, 0x%x, 0x%x}",
1026 bt_pcm_data_fmt_param[0], bt_pcm_data_fmt_param[1],
1027 bt_pcm_data_fmt_param[2], bt_pcm_data_fmt_param[3],
1028 bt_pcm_data_fmt_param[4]);
1029
1030 if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM,
1031 p_buf, hw_sco_i2spcm_cfg_cback)) == FALSE)
1032 {
1033 bt_vendor_cbacks->dealloc(p_buf);
1034 }
1035 else
1036 return;
1037 }
1038 status = BT_VND_OP_RESULT_FAIL;
1039 }
1040 }
1041
1042 ALOGI("sco I2S/PCM config result %d [0-Success, 1-Fail]", status);
1043 if (bt_vendor_cbacks)
1044 {
1045 bt_vendor_cbacks->audio_state_cb(status);
1046 }
1047 }
1048
1049 /*******************************************************************************
1050 **
1051 ** Function hw_set_MSBC_codec_cback
1052 **
1053 ** Description Callback function for setting WBS codec
1054 **
1055 ** Returns None
1056 **
1057 *******************************************************************************/
hw_set_MSBC_codec_cback(void * p_mem)1058 static void hw_set_MSBC_codec_cback(void *p_mem)
1059 {
1060 /* whenever update the codec enable/disable, need to update I2SPCM */
1061 ALOGI("SCO I2S interface change the sample rate to 16K");
1062 hw_sco_i2spcm_config(p_mem, SCO_CODEC_MSBC);
1063 }
1064
1065 /*******************************************************************************
1066 **
1067 ** Function hw_set_CVSD_codec_cback
1068 **
1069 ** Description Callback function for setting NBS codec
1070 **
1071 ** Returns None
1072 **
1073 *******************************************************************************/
hw_set_CVSD_codec_cback(void * p_mem)1074 static void hw_set_CVSD_codec_cback(void *p_mem)
1075 {
1076 /* whenever update the codec enable/disable, need to update I2SPCM */
1077 ALOGI("SCO I2S interface change the sample rate to 8K");
1078 hw_sco_i2spcm_config(p_mem, SCO_CODEC_CVSD);
1079 }
1080
1081 #endif // SCO_CFG_INCLUDED
1082
1083 /*****************************************************************************
1084 ** Hardware Configuration Interface Functions
1085 *****************************************************************************/
1086
1087
1088 /*******************************************************************************
1089 **
1090 ** Function hw_config_start
1091 **
1092 ** Description Kick off controller initialization process
1093 **
1094 ** Returns None
1095 **
1096 *******************************************************************************/
hw_config_start(void)1097 void hw_config_start(void)
1098 {
1099 HC_BT_HDR *p_buf = NULL;
1100 uint8_t *p;
1101
1102 hw_cfg_cb.state = 0;
1103 hw_cfg_cb.fw_fd = -1;
1104 hw_cfg_cb.f_set_baud_2 = FALSE;
1105
1106 /* Start from sending HCI_RESET */
1107
1108 if (bt_vendor_cbacks)
1109 {
1110 p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
1111 HCI_CMD_PREAMBLE_SIZE);
1112 }
1113
1114 if (p_buf)
1115 {
1116 p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1117 p_buf->offset = 0;
1118 p_buf->layer_specific = 0;
1119 p_buf->len = HCI_CMD_PREAMBLE_SIZE;
1120
1121 p = (uint8_t *) (p_buf + 1);
1122 UINT16_TO_STREAM(p, HCI_RESET);
1123 *p = 0; /* parameter length */
1124
1125 hw_cfg_cb.state = HW_CFG_START;
1126
1127 bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf, hw_config_cback);
1128 }
1129 else
1130 {
1131 if (bt_vendor_cbacks)
1132 {
1133 ALOGE("vendor lib fw conf aborted [no buffer]");
1134 bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
1135 }
1136 }
1137 }
1138
1139 /*******************************************************************************
1140 **
1141 ** Function hw_lpm_enable
1142 **
1143 ** Description Enalbe/Disable LPM
1144 **
1145 ** Returns TRUE/FALSE
1146 **
1147 *******************************************************************************/
hw_lpm_enable(uint8_t turn_on)1148 uint8_t hw_lpm_enable(uint8_t turn_on)
1149 {
1150 HC_BT_HDR *p_buf = NULL;
1151 uint8_t *p;
1152 uint8_t ret = FALSE;
1153
1154 if (bt_vendor_cbacks)
1155 p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
1156 HCI_CMD_PREAMBLE_SIZE + \
1157 LPM_CMD_PARAM_SIZE);
1158
1159 if (p_buf)
1160 {
1161 p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1162 p_buf->offset = 0;
1163 p_buf->layer_specific = 0;
1164 p_buf->len = HCI_CMD_PREAMBLE_SIZE + LPM_CMD_PARAM_SIZE;
1165
1166 p = (uint8_t *) (p_buf + 1);
1167 UINT16_TO_STREAM(p, HCI_VSC_WRITE_SLEEP_MODE);
1168 *p++ = LPM_CMD_PARAM_SIZE; /* parameter length */
1169
1170 if (turn_on)
1171 {
1172 memcpy(p, &lpm_param, LPM_CMD_PARAM_SIZE);
1173 upio_set(UPIO_LPM_MODE, UPIO_ASSERT, 0);
1174 }
1175 else
1176 {
1177 memset(p, 0, LPM_CMD_PARAM_SIZE);
1178 upio_set(UPIO_LPM_MODE, UPIO_DEASSERT, 0);
1179 }
1180
1181 if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_SLEEP_MODE, p_buf, \
1182 hw_lpm_ctrl_cback)) == FALSE)
1183 {
1184 bt_vendor_cbacks->dealloc(p_buf);
1185 }
1186 }
1187
1188 if ((ret == FALSE) && bt_vendor_cbacks)
1189 bt_vendor_cbacks->lpm_cb(BT_VND_OP_RESULT_FAIL);
1190
1191 return ret;
1192 }
1193
1194 /*******************************************************************************
1195 **
1196 ** Function hw_lpm_get_idle_timeout
1197 **
1198 ** Description Calculate idle time based on host stack idle threshold
1199 **
1200 ** Returns idle timeout value
1201 **
1202 *******************************************************************************/
hw_lpm_get_idle_timeout(void)1203 uint32_t hw_lpm_get_idle_timeout(void)
1204 {
1205 uint32_t timeout_ms;
1206
1207 /* set idle time to be LPM_IDLE_TIMEOUT_MULTIPLE times of
1208 * host stack idle threshold (in 300ms/25ms)
1209 */
1210 timeout_ms = (uint32_t)lpm_param.host_stack_idle_threshold \
1211 * LPM_IDLE_TIMEOUT_MULTIPLE;
1212
1213 if (strstr(hw_cfg_cb.local_chip_name, "BCM4325") != NULL)
1214 timeout_ms *= 25; // 12.5 or 25 ?
1215 else
1216 timeout_ms *= 300;
1217
1218 return timeout_ms;
1219 }
1220
1221 /*******************************************************************************
1222 **
1223 ** Function hw_lpm_set_wake_state
1224 **
1225 ** Description Assert/Deassert BT_WAKE
1226 **
1227 ** Returns None
1228 **
1229 *******************************************************************************/
hw_lpm_set_wake_state(uint8_t wake_assert)1230 void hw_lpm_set_wake_state(uint8_t wake_assert)
1231 {
1232 uint8_t state = (wake_assert) ? UPIO_ASSERT : UPIO_DEASSERT;
1233
1234 upio_set(UPIO_BT_WAKE, state, lpm_param.bt_wake_polarity);
1235 }
1236
1237 #if (SCO_CFG_INCLUDED == TRUE)
1238 /*******************************************************************************
1239 **
1240 ** Function hw_sco_config
1241 **
1242 ** Description Configure SCO related hardware settings
1243 **
1244 ** Returns None
1245 **
1246 *******************************************************************************/
hw_sco_config(void)1247 void hw_sco_config(void)
1248 {
1249 if (SCO_INTERFACE_I2S == sco_bus_interface)
1250 {
1251 /* 'Enable' I2S mode */
1252 bt_sco_i2spcm_param[0] = 1;
1253
1254 /* set nbs clock rate as the value in SCO_I2SPCM_IF_CLOCK_RATE field */
1255 sco_bus_clock_rate = bt_sco_i2spcm_param[3];
1256 }
1257 else
1258 {
1259 /* 'Disable' I2S mode */
1260 bt_sco_i2spcm_param[0] = 0;
1261
1262 /* set nbs clock rate as the value in SCO_PCM_IF_CLOCK_RATE field */
1263 sco_bus_clock_rate = bt_sco_param[1];
1264
1265 /* sync up clock mode setting */
1266 bt_sco_i2spcm_param[1] = bt_sco_param[4];
1267 }
1268
1269 if (sco_bus_wbs_clock_rate == INVALID_SCO_CLOCK_RATE)
1270 {
1271 /* set default wbs clock rate */
1272 sco_bus_wbs_clock_rate = SCO_I2SPCM_IF_CLOCK_RATE4WBS;
1273
1274 if (sco_bus_wbs_clock_rate < sco_bus_clock_rate)
1275 sco_bus_wbs_clock_rate = sco_bus_clock_rate;
1276 }
1277
1278 /*
1279 * To support I2S/PCM port multiplexing signals for sharing Bluetooth audio
1280 * and FM on the same PCM pins, we defer Bluetooth audio (SCO/eSCO)
1281 * configuration till SCO/eSCO is being established;
1282 * i.e. in hw_set_audio_state() call.
1283 */
1284
1285 if (bt_vendor_cbacks)
1286 {
1287 bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_SUCCESS);
1288 }
1289 }
1290
1291 /*******************************************************************************
1292 **
1293 ** Function hw_sco_i2spcm_config
1294 **
1295 ** Description Configure SCO over I2S or PCM
1296 **
1297 ** Returns None
1298 **
1299 *******************************************************************************/
hw_sco_i2spcm_config(void * p_mem,uint16_t codec)1300 static void hw_sco_i2spcm_config(void *p_mem, uint16_t codec)
1301 {
1302 HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem;
1303 bt_vendor_op_result_t status = BT_VND_OP_RESULT_FAIL;
1304
1305 if (*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0)
1306 {
1307 status = BT_VND_OP_RESULT_SUCCESS;
1308 }
1309
1310 /* Free the RX event buffer */
1311 if (bt_vendor_cbacks)
1312 bt_vendor_cbacks->dealloc(p_evt_buf);
1313
1314 if (status == BT_VND_OP_RESULT_SUCCESS)
1315 {
1316 HC_BT_HDR *p_buf = NULL;
1317 uint8_t *p, ret;
1318 uint16_t cmd_u16 = HCI_CMD_PREAMBLE_SIZE + SCO_I2SPCM_PARAM_SIZE;
1319
1320 if (bt_vendor_cbacks)
1321 p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + cmd_u16);
1322
1323 if (p_buf)
1324 {
1325 p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1326 p_buf->offset = 0;
1327 p_buf->layer_specific = 0;
1328 p_buf->len = cmd_u16;
1329
1330 p = (uint8_t *)(p_buf + 1);
1331
1332 UINT16_TO_STREAM(p, HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM);
1333 *p++ = SCO_I2SPCM_PARAM_SIZE;
1334 if (codec == SCO_CODEC_CVSD)
1335 {
1336 bt_sco_i2spcm_param[2] = 0; /* SCO_I2SPCM_IF_SAMPLE_RATE 8k */
1337 bt_sco_i2spcm_param[3] = bt_sco_param[1] = sco_bus_clock_rate;
1338 }
1339 else if (codec == SCO_CODEC_MSBC)
1340 {
1341 bt_sco_i2spcm_param[2] = wbs_sample_rate; /* SCO_I2SPCM_IF_SAMPLE_RATE 16K */
1342 bt_sco_i2spcm_param[3] = bt_sco_param[1] = sco_bus_wbs_clock_rate;
1343 }
1344 else
1345 {
1346 bt_sco_i2spcm_param[2] = 0; /* SCO_I2SPCM_IF_SAMPLE_RATE 8k */
1347 bt_sco_i2spcm_param[3] = bt_sco_param[1] = sco_bus_clock_rate;
1348 ALOGE("wrong codec is use in hw_sco_i2spcm_config, goes default NBS");
1349 }
1350 memcpy(p, &bt_sco_i2spcm_param, SCO_I2SPCM_PARAM_SIZE);
1351 cmd_u16 = HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM;
1352 ALOGI("I2SPCM config {0x%x, 0x%x, 0x%x, 0x%x}",
1353 bt_sco_i2spcm_param[0], bt_sco_i2spcm_param[1],
1354 bt_sco_i2spcm_param[2], bt_sco_i2spcm_param[3]);
1355
1356 if ((ret = bt_vendor_cbacks->xmit_cb(cmd_u16, p_buf, hw_sco_i2spcm_cfg_cback)) == FALSE)
1357 {
1358 bt_vendor_cbacks->dealloc(p_buf);
1359 }
1360 else
1361 return;
1362 }
1363 status = BT_VND_OP_RESULT_FAIL;
1364 }
1365
1366 if (bt_vendor_cbacks)
1367 {
1368 bt_vendor_cbacks->audio_state_cb(status);
1369 }
1370 }
1371
1372 /*******************************************************************************
1373 **
1374 ** Function hw_set_SCO_codec
1375 **
1376 ** Description This functgion sends command to the controller to setup
1377 ** WBS/NBS codec for the upcoming eSCO connection.
1378 **
1379 ** Returns -1 : Failed to send VSC
1380 ** 0 : Success
1381 **
1382 *******************************************************************************/
hw_set_SCO_codec(uint16_t codec)1383 static int hw_set_SCO_codec(uint16_t codec)
1384 {
1385 HC_BT_HDR *p_buf = NULL;
1386 uint8_t *p;
1387 uint8_t ret;
1388 int ret_val = 0;
1389 tINT_CMD_CBACK p_set_SCO_codec_cback;
1390
1391 BTHWDBG( "hw_set_SCO_codec 0x%x", codec);
1392
1393 if (bt_vendor_cbacks)
1394 p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(
1395 BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + SCO_CODEC_PARAM_SIZE);
1396
1397 if (p_buf)
1398 {
1399 p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1400 p_buf->offset = 0;
1401 p_buf->layer_specific = 0;
1402 p = (uint8_t *)(p_buf + 1);
1403
1404 UINT16_TO_STREAM(p, HCI_VSC_ENABLE_WBS);
1405
1406 if (codec == SCO_CODEC_MSBC)
1407 {
1408 /* Enable mSBC */
1409 *p++ = SCO_CODEC_PARAM_SIZE; /* set the parameter size */
1410 UINT8_TO_STREAM(p,1); /* enable */
1411 UINT16_TO_STREAM(p, codec);
1412
1413 /* set the totall size of this packet */
1414 p_buf->len = HCI_CMD_PREAMBLE_SIZE + SCO_CODEC_PARAM_SIZE;
1415
1416 p_set_SCO_codec_cback = hw_set_MSBC_codec_cback;
1417 }
1418 else
1419 {
1420 /* Disable mSBC */
1421 *p++ = (SCO_CODEC_PARAM_SIZE - 2); /* set the parameter size */
1422 UINT8_TO_STREAM(p,0); /* disable */
1423
1424 /* set the totall size of this packet */
1425 p_buf->len = HCI_CMD_PREAMBLE_SIZE + SCO_CODEC_PARAM_SIZE - 2;
1426
1427 p_set_SCO_codec_cback = hw_set_CVSD_codec_cback;
1428 if ((codec != SCO_CODEC_CVSD) && (codec != SCO_CODEC_NONE))
1429 {
1430 ALOGW("SCO codec setting is wrong: codec: 0x%x", codec);
1431 }
1432 }
1433
1434 if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_ENABLE_WBS, p_buf, p_set_SCO_codec_cback))\
1435 == FALSE)
1436 {
1437 bt_vendor_cbacks->dealloc(p_buf);
1438 ret_val = -1;
1439 }
1440 }
1441 else
1442 {
1443 ret_val = -1;
1444 }
1445
1446 return ret_val;
1447 }
1448
1449 /*******************************************************************************
1450 **
1451 ** Function hw_set_audio_state
1452 **
1453 ** Description This function configures audio base on provided audio state
1454 **
1455 ** Paramters pointer to audio state structure
1456 **
1457 ** Returns 0: ok, -1: error
1458 **
1459 *******************************************************************************/
hw_set_audio_state(bt_vendor_op_audio_state_t * p_state)1460 int hw_set_audio_state(bt_vendor_op_audio_state_t *p_state)
1461 {
1462 int ret_val = -1;
1463
1464 if (!bt_vendor_cbacks)
1465 return ret_val;
1466
1467 ret_val = hw_set_SCO_codec(p_state->peer_codec);
1468 return ret_val;
1469 }
1470
1471 #else // SCO_CFG_INCLUDED
hw_set_audio_state(bt_vendor_op_audio_state_t * p_state)1472 int hw_set_audio_state(bt_vendor_op_audio_state_t *p_state)
1473 {
1474 return -256;
1475 }
1476 #endif
1477 /*******************************************************************************
1478 **
1479 ** Function hw_set_patch_file_path
1480 **
1481 ** Description Set the location of firmware patch file
1482 **
1483 ** Returns 0 : Success
1484 ** Otherwise : Fail
1485 **
1486 *******************************************************************************/
hw_set_patch_file_path(char * p_conf_name,char * p_conf_value,int param)1487 int hw_set_patch_file_path(char *p_conf_name, char *p_conf_value, int param)
1488 {
1489
1490 strcpy(fw_patchfile_path, p_conf_value);
1491
1492 return 0;
1493 }
1494
1495 /*******************************************************************************
1496 **
1497 ** Function hw_set_patch_file_name
1498 **
1499 ** Description Give the specific firmware patch filename
1500 **
1501 ** Returns 0 : Success
1502 ** Otherwise : Fail
1503 **
1504 *******************************************************************************/
hw_set_patch_file_name(char * p_conf_name,char * p_conf_value,int param)1505 int hw_set_patch_file_name(char *p_conf_name, char *p_conf_value, int param)
1506 {
1507
1508 strcpy(fw_patchfile_name, p_conf_value);
1509
1510 return 0;
1511 }
1512
1513 #if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
1514 /*******************************************************************************
1515 **
1516 ** Function hw_set_patch_settlement_delay
1517 **
1518 ** Description Give the specific firmware patch settlement time in milliseconds
1519 **
1520 ** Returns 0 : Success
1521 ** Otherwise : Fail
1522 **
1523 *******************************************************************************/
hw_set_patch_settlement_delay(char * p_conf_name,char * p_conf_value,int param)1524 int hw_set_patch_settlement_delay(char *p_conf_name, char *p_conf_value, int param)
1525 {
1526 fw_patch_settlement_delay = atoi(p_conf_value);
1527
1528 return 0;
1529 }
1530 #endif //VENDOR_LIB_RUNTIME_TUNING_ENABLED
1531
1532 /*****************************************************************************
1533 ** Sample Codes Section
1534 *****************************************************************************/
1535
1536 #if (HW_END_WITH_HCI_RESET == TRUE)
1537 /*******************************************************************************
1538 **
1539 ** Function hw_epilog_cback
1540 **
1541 ** Description Callback function for Command Complete Events from HCI
1542 ** commands sent in epilog process.
1543 **
1544 ** Returns None
1545 **
1546 *******************************************************************************/
hw_epilog_cback(void * p_mem)1547 void hw_epilog_cback(void *p_mem)
1548 {
1549 HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
1550 uint8_t *p, status;
1551 uint16_t opcode;
1552
1553 status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
1554 p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
1555 STREAM_TO_UINT16(opcode,p);
1556
1557 BTHWDBG("%s Opcode:0x%04X Status: %d", __FUNCTION__, opcode, status);
1558
1559 if (bt_vendor_cbacks)
1560 {
1561 /* Must free the RX event buffer */
1562 bt_vendor_cbacks->dealloc(p_evt_buf);
1563
1564 /* Once epilog process is done, must call epilog_cb callback
1565 to notify caller */
1566 bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
1567 }
1568 }
1569
1570 /*******************************************************************************
1571 **
1572 ** Function hw_epilog_process
1573 **
1574 ** Description Sample implementation of epilog process
1575 **
1576 ** Returns None
1577 **
1578 *******************************************************************************/
hw_epilog_process(void)1579 void hw_epilog_process(void)
1580 {
1581 HC_BT_HDR *p_buf = NULL;
1582 uint8_t *p;
1583
1584 BTHWDBG("hw_epilog_process");
1585
1586 /* Sending a HCI_RESET */
1587 if (bt_vendor_cbacks)
1588 {
1589 /* Must allocate command buffer via HC's alloc API */
1590 p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
1591 HCI_CMD_PREAMBLE_SIZE);
1592 }
1593
1594 if (p_buf)
1595 {
1596 p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1597 p_buf->offset = 0;
1598 p_buf->layer_specific = 0;
1599 p_buf->len = HCI_CMD_PREAMBLE_SIZE;
1600
1601 p = (uint8_t *) (p_buf + 1);
1602 UINT16_TO_STREAM(p, HCI_RESET);
1603 *p = 0; /* parameter length */
1604
1605 /* Send command via HC's xmit_cb API */
1606 bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf, hw_epilog_cback);
1607 }
1608 else
1609 {
1610 if (bt_vendor_cbacks)
1611 {
1612 ALOGE("vendor lib epilog process aborted [no buffer]");
1613 bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_FAIL);
1614 }
1615 }
1616 }
1617 #endif // (HW_END_WITH_HCI_RESET == TRUE)
1618