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