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