10b966c5eSopenharmony_ci/****************************************************************************** 20b966c5eSopenharmony_ci * 30b966c5eSopenharmony_ci * Copyright (C) 2009-2012 Broadcom Corporation 40b966c5eSopenharmony_ci * 50b966c5eSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 60b966c5eSopenharmony_ci * you may not use this file except in compliance with the License. 70b966c5eSopenharmony_ci * You may obtain a copy of the License at: 80b966c5eSopenharmony_ci * 90b966c5eSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 100b966c5eSopenharmony_ci * 110b966c5eSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 120b966c5eSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 130b966c5eSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 140b966c5eSopenharmony_ci * See the License for the specific language governing permissions and 150b966c5eSopenharmony_ci * limitations under the License. 160b966c5eSopenharmony_ci * 170b966c5eSopenharmony_ci ******************************************************************************/ 180b966c5eSopenharmony_ci 190b966c5eSopenharmony_ci/****************************************************************************** 200b966c5eSopenharmony_ci * 210b966c5eSopenharmony_ci * Filename: hardware.c 220b966c5eSopenharmony_ci * 230b966c5eSopenharmony_ci * Description: Contains controller-specific functions, like 240b966c5eSopenharmony_ci * firmware patch download 250b966c5eSopenharmony_ci * low power mode operations 260b966c5eSopenharmony_ci * 270b966c5eSopenharmony_ci ******************************************************************************/ 280b966c5eSopenharmony_ci 290b966c5eSopenharmony_ci#define LOG_TAG "bt_hwcfg" 300b966c5eSopenharmony_ci 310b966c5eSopenharmony_ci#include <utils/Log.h> 320b966c5eSopenharmony_ci#include <sys/types.h> 330b966c5eSopenharmony_ci#include <stdbool.h> 340b966c5eSopenharmony_ci#include <sys/stat.h> 350b966c5eSopenharmony_ci#include <signal.h> 360b966c5eSopenharmony_ci#include <time.h> 370b966c5eSopenharmony_ci#include <errno.h> 380b966c5eSopenharmony_ci#include <fcntl.h> 390b966c5eSopenharmony_ci#include <dirent.h> 400b966c5eSopenharmony_ci#include <ctype.h> 410b966c5eSopenharmony_ci#include <stdlib.h> 420b966c5eSopenharmony_ci#include <string.h> 430b966c5eSopenharmony_ci#include <stdio.h> 440b966c5eSopenharmony_ci#include <unistd.h> 450b966c5eSopenharmony_ci#include "bt_hci_bdroid.h" 460b966c5eSopenharmony_ci#include "bt_vendor_brcm.h" 470b966c5eSopenharmony_ci#include "esco_parameters.h" 480b966c5eSopenharmony_ci#include "userial.h" 490b966c5eSopenharmony_ci#include "userial_vendor.h" 500b966c5eSopenharmony_ci#include "upio.h" 510b966c5eSopenharmony_ci 520b966c5eSopenharmony_ci/****************************************************************************** 530b966c5eSopenharmony_ci** Constants & Macros 540b966c5eSopenharmony_ci******************************************************************************/ 550b966c5eSopenharmony_ci 560b966c5eSopenharmony_ci#ifndef BTHW_DBG 570b966c5eSopenharmony_ci#define BTHW_DBG FALSE 580b966c5eSopenharmony_ci#endif 590b966c5eSopenharmony_ci 600b966c5eSopenharmony_ci#if (BTHW_DBG == TRUE) 610b966c5eSopenharmony_ci#define BTHWDBG(param, ...) \ 620b966c5eSopenharmony_ci{ \ 630b966c5eSopenharmony_ci HILOGD(param, ##__VA_ARGS__); \ 640b966c5eSopenharmony_ci} 650b966c5eSopenharmony_ci#else 660b966c5eSopenharmony_ci#define BTHWDBG(param, ...) \ 670b966c5eSopenharmony_ci{ \ 680b966c5eSopenharmony_ci HILOGD(param, ##__VA_ARGS__); \ 690b966c5eSopenharmony_ci} 700b966c5eSopenharmony_ci#endif 710b966c5eSopenharmony_ci 720b966c5eSopenharmony_ci#define FW_PATCHFILE_EXTENSION ".hcd" 730b966c5eSopenharmony_ci#define FW_PATCHFILE_EXTENSION_LEN 4 740b966c5eSopenharmony_ci#define FW_PATCHFILE_PATH_MAXLEN 248 /* Local_Name length of return of \ 750b966c5eSopenharmony_ci HCI_Read_Local_Name */ 760b966c5eSopenharmony_ci 770b966c5eSopenharmony_ci#define HCI_CMD_MAX_LEN 258 780b966c5eSopenharmony_ci 790b966c5eSopenharmony_ci#define HCI_RESET 0x0C03 800b966c5eSopenharmony_ci#define HCI_VSC_WRITE_UART_CLOCK_SETTING 0xFC45 810b966c5eSopenharmony_ci#define HCI_VSC_UPDATE_BAUDRATE 0xFC18 820b966c5eSopenharmony_ci#define HCI_READ_LOCAL_NAME 0x0C14 830b966c5eSopenharmony_ci#define HCI_VSC_DOWNLOAD_MINIDRV 0xFC2E 840b966c5eSopenharmony_ci#define HCI_VSC_WRITE_FIRMWARE 0xFC4C 850b966c5eSopenharmony_ci#define HCI_VSC_WRITE_BD_ADDR 0xFC01 860b966c5eSopenharmony_ci#define HCI_VSC_WRITE_SLEEP_MODE 0xFC27 870b966c5eSopenharmony_ci#define HCI_VSC_WRITE_SCO_PCM_INT_PARAM 0xFC1C 880b966c5eSopenharmony_ci#define HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM 0xFC1E 890b966c5eSopenharmony_ci#define HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM 0xFC6D 900b966c5eSopenharmony_ci#define HCI_VSC_ENABLE_WBS 0xFC7E 910b966c5eSopenharmony_ci#define HCI_VSC_LAUNCH_RAM 0xFC4E 920b966c5eSopenharmony_ci#define HCI_READ_LOCAL_BDADDR 0x1009 930b966c5eSopenharmony_ci 940b966c5eSopenharmony_ci#define HCI_EVT_CMD_CMPL_STATUS_RET_BYTE 5 950b966c5eSopenharmony_ci#define HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING 6 960b966c5eSopenharmony_ci#define HCI_EVT_CMD_CMPL_LOCAL_BDADDR_ARRAY 6 970b966c5eSopenharmony_ci#define HCI_EVT_CMD_CMPL_OPCODE 3 980b966c5eSopenharmony_ci#define LPM_CMD_PARAM_SIZE 12 990b966c5eSopenharmony_ci#define UPDATE_BAUDRATE_CMD_PARAM_SIZE 6 1000b966c5eSopenharmony_ci#define HCI_CMD_PREAMBLE_SIZE 3 1010b966c5eSopenharmony_ci#define HCD_REC_PAYLOAD_LEN_BYTE 2 1020b966c5eSopenharmony_ci#define LOCAL_NAME_BUFFER_LEN 32 1030b966c5eSopenharmony_ci#define LOCAL_BDADDR_PATH_BUFFER_LEN 256 1040b966c5eSopenharmony_ci 1050b966c5eSopenharmony_ci#define STREAM_TO_UINT16(u16, p) \ 1060b966c5eSopenharmony_cido \ 1070b966c5eSopenharmony_ci{ \ 1080b966c5eSopenharmony_ci u16 = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); \ 1090b966c5eSopenharmony_ci (p) += 2; \ 1100b966c5eSopenharmony_ci} while (0) 1110b966c5eSopenharmony_ci#define UINT8_TO_STREAM(p, u8) \ 1120b966c5eSopenharmony_cido \ 1130b966c5eSopenharmony_ci{ \ 1140b966c5eSopenharmony_ci *(p)++ = (uint8_t)(u8); \ 1150b966c5eSopenharmony_ci} while (0) 1160b966c5eSopenharmony_ci#define UINT16_TO_STREAM(p, u16) \ 1170b966c5eSopenharmony_cido \ 1180b966c5eSopenharmony_ci{ \ 1190b966c5eSopenharmony_ci *(p)++ = (uint8_t)(u16); \ 1200b966c5eSopenharmony_ci *(p)++ = (uint8_t)((u16) >> 8); \ 1210b966c5eSopenharmony_ci} while (0) 1220b966c5eSopenharmony_ci#define UINT32_TO_STREAM(p, u32) \ 1230b966c5eSopenharmony_cido \ 1240b966c5eSopenharmony_ci{ \ 1250b966c5eSopenharmony_ci *(p)++ = (uint8_t)(u32); \ 1260b966c5eSopenharmony_ci *(p)++ = (uint8_t)((u32) >> 8); \ 1270b966c5eSopenharmony_ci *(p)++ = (uint8_t)((u32) >> 16); \ 1280b966c5eSopenharmony_ci *(p)++ = (uint8_t)((u32) >> 24); \ 1290b966c5eSopenharmony_ci} while (0) 1300b966c5eSopenharmony_ci 1310b966c5eSopenharmony_ci#define SCO_INTERFACE_PCM 0 1320b966c5eSopenharmony_ci#define SCO_INTERFACE_I2S 1 1330b966c5eSopenharmony_ci 1340b966c5eSopenharmony_ci/* one byte is for enable/disable 1350b966c5eSopenharmony_ci next 2 bytes are for codec type */ 1360b966c5eSopenharmony_ci#define SCO_CODEC_PARAM_SIZE 3 1370b966c5eSopenharmony_ci 1380b966c5eSopenharmony_ci#define BT_VENDOR_CFG_TIMEDELAY_ 40 1390b966c5eSopenharmony_ci#define BT_VENDOR_LDM_DEFAULT_IDLE 300 1400b966c5eSopenharmony_ci/****************************************************************************** 1410b966c5eSopenharmony_ci** Local type definitions 1420b966c5eSopenharmony_ci******************************************************************************/ 1430b966c5eSopenharmony_ci 1440b966c5eSopenharmony_ci/* Hardware Configuration State */ 1450b966c5eSopenharmony_cienum { 1460b966c5eSopenharmony_ci HW_CFG_START = 1, 1470b966c5eSopenharmony_ci HW_CFG_SET_UART_CLOCK, 1480b966c5eSopenharmony_ci HW_CFG_SET_UART_BAUD_1, 1490b966c5eSopenharmony_ci HW_CFG_READ_LOCAL_NAME, 1500b966c5eSopenharmony_ci HW_CFG_DL_MINIDRIVER, 1510b966c5eSopenharmony_ci HW_CFG_DL_FW_PATCH, 1520b966c5eSopenharmony_ci HW_CFG_SET_UART_BAUD_2, 1530b966c5eSopenharmony_ci HW_CFG_SET_BD_ADDR, 1540b966c5eSopenharmony_ci HW_CFG_READ_BD_ADDR 1550b966c5eSopenharmony_ci}; 1560b966c5eSopenharmony_ci 1570b966c5eSopenharmony_ci/* h/w config control block */ 1580b966c5eSopenharmony_citypedef struct { 1590b966c5eSopenharmony_ci uint8_t state; /* Hardware configuration state */ 1600b966c5eSopenharmony_ci int fw_fd; /* FW patch file fd */ 1610b966c5eSopenharmony_ci uint8_t f_set_baud_2; /* Baud rate switch state */ 1620b966c5eSopenharmony_ci char local_chip_name[LOCAL_NAME_BUFFER_LEN]; 1630b966c5eSopenharmony_ci} bt_hw_cfg_cb_t; 1640b966c5eSopenharmony_ci 1650b966c5eSopenharmony_ci/* low power mode parameters */ 1660b966c5eSopenharmony_citypedef struct { 1670b966c5eSopenharmony_ci uint8_t host_stack_idle_threshold; /* Unit scale 300ms/25ms */ 1680b966c5eSopenharmony_ci uint8_t bt_wake_polarity; /* 0=Active Low, 1= Active High */ 1690b966c5eSopenharmony_ci} bt_lpm_param_t; 1700b966c5eSopenharmony_ci 1710b966c5eSopenharmony_ci/* Firmware re-launch settlement time */ 1720b966c5eSopenharmony_citypedef struct { 1730b966c5eSopenharmony_ci const char *chipset_name; 1740b966c5eSopenharmony_ci const uint32_t delay_time; 1750b966c5eSopenharmony_ci} fw_settlement_entry_t; 1760b966c5eSopenharmony_ci 1770b966c5eSopenharmony_ci/****************************************************************************** 1780b966c5eSopenharmony_ci** Externs 1790b966c5eSopenharmony_ci******************************************************************************/ 1800b966c5eSopenharmony_ci 1810b966c5eSopenharmony_civoid hw_config_cback(void *p_mem); 1820b966c5eSopenharmony_ci 1830b966c5eSopenharmony_ci/****************************************************************************** 1840b966c5eSopenharmony_ci** Static variables 1850b966c5eSopenharmony_ci******************************************************************************/ 1860b966c5eSopenharmony_ci 1870b966c5eSopenharmony_cistatic char fw_patchfile_path[256] = FW_PATCHFILE_LOCATION; 1880b966c5eSopenharmony_cistatic char fw_patchfile_name[128] = {0}; 1890b966c5eSopenharmony_ci#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE) 1900b966c5eSopenharmony_cistatic int fw_patch_settlement_delay = -1; 1910b966c5eSopenharmony_ci#endif 1920b966c5eSopenharmony_ci 1930b966c5eSopenharmony_cistatic int wbs_sample_rate = SCO_WBS_SAMPLE_RATE; 1940b966c5eSopenharmony_cistatic bt_hw_cfg_cb_t hw_cfg_cb; 1950b966c5eSopenharmony_ci 1960b966c5eSopenharmony_cistatic bt_lpm_param_t lpm_param = { 1970b966c5eSopenharmony_ci LPM_IDLE_THRESHOLD, 1980b966c5eSopenharmony_ci LPM_BT_WAKE_POLARITY, 1990b966c5eSopenharmony_ci}; 2000b966c5eSopenharmony_ci 2010b966c5eSopenharmony_ci/* need to update the bt_sco_i2spcm_param as well 2020b966c5eSopenharmony_ci bt_sco_i2spcm_param will be used for WBS setting 2030b966c5eSopenharmony_ci update the bt_sco_param and bt_sco_i2spcm_param */ 2040b966c5eSopenharmony_cistatic uint8_t bt_sco_param[SCO_PCM_PARAM_SIZE] = { 2050b966c5eSopenharmony_ci SCO_PCM_ROUTING, 2060b966c5eSopenharmony_ci SCO_PCM_IF_CLOCK_RATE, 2070b966c5eSopenharmony_ci SCO_PCM_IF_FRAME_TYPE, 2080b966c5eSopenharmony_ci SCO_PCM_IF_SYNC_MODE, 2090b966c5eSopenharmony_ci SCO_PCM_IF_CLOCK_MODE 2100b966c5eSopenharmony_ci}; 2110b966c5eSopenharmony_ci 2120b966c5eSopenharmony_cistatic uint8_t bt_pcm_data_fmt_param[PCM_DATA_FORMAT_PARAM_SIZE] = { 2130b966c5eSopenharmony_ci PCM_DATA_FMT_SHIFT_MODE, 2140b966c5eSopenharmony_ci PCM_DATA_FMT_FILL_BITS, 2150b966c5eSopenharmony_ci PCM_DATA_FMT_FILL_METHOD, 2160b966c5eSopenharmony_ci PCM_DATA_FMT_FILL_NUM, 2170b966c5eSopenharmony_ci PCM_DATA_FMT_JUSTIFY_MODE 2180b966c5eSopenharmony_ci}; 2190b966c5eSopenharmony_ci 2200b966c5eSopenharmony_cistatic uint8_t bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_SIZE] = { 2210b966c5eSopenharmony_ci SCO_I2SPCM_IF_MODE, 2220b966c5eSopenharmony_ci SCO_I2SPCM_IF_ROLE, 2230b966c5eSopenharmony_ci SCO_I2SPCM_IF_SAMPLE_RATE, 2240b966c5eSopenharmony_ci SCO_I2SPCM_IF_CLOCK_RATE 2250b966c5eSopenharmony_ci}; 2260b966c5eSopenharmony_ci 2270b966c5eSopenharmony_ci/* 2280b966c5eSopenharmony_ci * The look-up table of recommended firmware settlement delay (milliseconds) on 2290b966c5eSopenharmony_ci * known chipsets. 2300b966c5eSopenharmony_ci */ 2310b966c5eSopenharmony_cistatic const fw_settlement_entry_t fw_settlement_table[] = { 2320b966c5eSopenharmony_ci {"BCM43241", 200}, 2330b966c5eSopenharmony_ci {"BCM43341", 100}, 2340b966c5eSopenharmony_ci {(const char *)NULL, 200} // Giving the generic fw settlement delay setting. 2350b966c5eSopenharmony_ci}; 2360b966c5eSopenharmony_ci 2370b966c5eSopenharmony_ci/* 2380b966c5eSopenharmony_ci * NOTICE: 2390b966c5eSopenharmony_ci * If the platform plans to run I2S interface bus over I2S/PCM port of the 2400b966c5eSopenharmony_ci * BT Controller with the Host AP, explicitly set "SCO_USE_I2S_INTERFACE = TRUE" 2410b966c5eSopenharmony_ci * in the correspodning include/vnd_<target>.txt file. 2420b966c5eSopenharmony_ci * Otherwise, leave SCO_USE_I2S_INTERFACE undefined in the vnd_<target>.txt file. 2430b966c5eSopenharmony_ci * And, PCM interface will be set as the default bus format running over I2S/PCM 2440b966c5eSopenharmony_ci * port. 2450b966c5eSopenharmony_ci */ 2460b966c5eSopenharmony_ci#if (defined(SCO_USE_I2S_INTERFACE) && SCO_USE_I2S_INTERFACE == TRUE) 2470b966c5eSopenharmony_cistatic uint8_t sco_bus_interface = SCO_INTERFACE_I2S; 2480b966c5eSopenharmony_ci#else 2490b966c5eSopenharmony_cistatic uint8_t sco_bus_interface = SCO_INTERFACE_PCM; 2500b966c5eSopenharmony_ci#endif 2510b966c5eSopenharmony_ci 2520b966c5eSopenharmony_ci#define INVALID_SCO_CLOCK_RATE 0xFF 2530b966c5eSopenharmony_cistatic uint8_t sco_bus_clock_rate = INVALID_SCO_CLOCK_RATE; 2540b966c5eSopenharmony_cistatic uint8_t sco_bus_wbs_clock_rate = INVALID_SCO_CLOCK_RATE; 2550b966c5eSopenharmony_ci 2560b966c5eSopenharmony_ci/****************************************************************************** 2570b966c5eSopenharmony_ci** Static functions 2580b966c5eSopenharmony_ci******************************************************************************/ 2590b966c5eSopenharmony_cistatic void hw_sco_i2spcm_config(uint16_t codec); 2600b966c5eSopenharmony_cistatic void hw_sco_i2spcm_config_from_command(void *p_mem, uint16_t codec); 2610b966c5eSopenharmony_ci 2620b966c5eSopenharmony_ci/****************************************************************************** 2630b966c5eSopenharmony_ci** Controller Initialization Static Functions 2640b966c5eSopenharmony_ci******************************************************************************/ 2650b966c5eSopenharmony_ci 2660b966c5eSopenharmony_ci/******************************************************************************* 2670b966c5eSopenharmony_ci** 2680b966c5eSopenharmony_ci** Function look_up_fw_settlement_delay 2690b966c5eSopenharmony_ci** 2700b966c5eSopenharmony_ci** Description If FW_PATCH_SETTLEMENT_DELAY_MS has not been explicitly 2710b966c5eSopenharmony_ci** re-defined in the platform specific build-time configuration 2720b966c5eSopenharmony_ci** file, we will search into the look-up table for a 2730b966c5eSopenharmony_ci** recommended firmware settlement delay value. 2740b966c5eSopenharmony_ci** 2750b966c5eSopenharmony_ci** Although the settlement time might be also related to board 2760b966c5eSopenharmony_ci** configurations such as the crystal clocking speed. 2770b966c5eSopenharmony_ci** 2780b966c5eSopenharmony_ci** Returns Firmware settlement delay 2790b966c5eSopenharmony_ci** 2800b966c5eSopenharmony_ci*******************************************************************************/ 2810b966c5eSopenharmony_ciuint32_t look_up_fw_settlement_delay(void) 2820b966c5eSopenharmony_ci{ 2830b966c5eSopenharmony_ci uint32_t ret_value; 2840b966c5eSopenharmony_ci fw_settlement_entry_t *p_entry; 2850b966c5eSopenharmony_ci 2860b966c5eSopenharmony_ci if (FW_PATCH_SETTLEMENT_DELAY_MS > 0) 2870b966c5eSopenharmony_ci ret_value = FW_PATCH_SETTLEMENT_DELAY_MS; 2880b966c5eSopenharmony_ci#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE) 2890b966c5eSopenharmony_ci else if (fw_patch_settlement_delay >= 0) { 2900b966c5eSopenharmony_ci ret_value = fw_patch_settlement_delay; 2910b966c5eSopenharmony_ci } 2920b966c5eSopenharmony_ci#endif 2930b966c5eSopenharmony_ci else { 2940b966c5eSopenharmony_ci p_entry = (fw_settlement_entry_t *)fw_settlement_table; 2950b966c5eSopenharmony_ci 2960b966c5eSopenharmony_ci while (p_entry->chipset_name != NULL) { 2970b966c5eSopenharmony_ci if (strstr(hw_cfg_cb.local_chip_name, p_entry->chipset_name) != NULL) { 2980b966c5eSopenharmony_ci break; 2990b966c5eSopenharmony_ci } 3000b966c5eSopenharmony_ci 3010b966c5eSopenharmony_ci p_entry++; 3020b966c5eSopenharmony_ci } 3030b966c5eSopenharmony_ci 3040b966c5eSopenharmony_ci ret_value = p_entry->delay_time; 3050b966c5eSopenharmony_ci } 3060b966c5eSopenharmony_ci 3070b966c5eSopenharmony_ci BTHWDBG("Settlement delay -- %d ms", ret_value); 3080b966c5eSopenharmony_ci 3090b966c5eSopenharmony_ci return (ret_value); 3100b966c5eSopenharmony_ci} 3110b966c5eSopenharmony_ci 3120b966c5eSopenharmony_ci/******************************************************************************* 3130b966c5eSopenharmony_ci** 3140b966c5eSopenharmony_ci** Function ms_delay 3150b966c5eSopenharmony_ci** 3160b966c5eSopenharmony_ci** Description sleep unconditionally for timeout milliseconds 3170b966c5eSopenharmony_ci** 3180b966c5eSopenharmony_ci** Returns None 3190b966c5eSopenharmony_ci** 3200b966c5eSopenharmony_ci*******************************************************************************/ 3210b966c5eSopenharmony_civoid ms_delay(uint32_t timeout) 3220b966c5eSopenharmony_ci{ 3230b966c5eSopenharmony_ci struct timespec delay; 3240b966c5eSopenharmony_ci int err; 3250b966c5eSopenharmony_ci 3260b966c5eSopenharmony_ci if (timeout == 0) 3270b966c5eSopenharmony_ci return; 3280b966c5eSopenharmony_ci 3290b966c5eSopenharmony_ci delay.tv_sec = timeout / BT_VENDOR_TIME_RAIDX; 3300b966c5eSopenharmony_ci delay.tv_nsec = BT_VENDOR_TIME_RAIDX * BT_VENDOR_TIME_RAIDX * (timeout % BT_VENDOR_TIME_RAIDX); 3310b966c5eSopenharmony_ci 3320b966c5eSopenharmony_ci /* [u]sleep can't be used because it uses SIGALRM */ 3330b966c5eSopenharmony_ci do { 3340b966c5eSopenharmony_ci err = nanosleep(&delay, &delay); 3350b966c5eSopenharmony_ci } while (err < 0 && errno == EINTR); 3360b966c5eSopenharmony_ci} 3370b966c5eSopenharmony_ci 3380b966c5eSopenharmony_ci/******************************************************************************* 3390b966c5eSopenharmony_ci** 3400b966c5eSopenharmony_ci** Function line_speed_to_userial_baud 3410b966c5eSopenharmony_ci** 3420b966c5eSopenharmony_ci** Description helper function converts line speed number into USERIAL baud 3430b966c5eSopenharmony_ci** rate symbol 3440b966c5eSopenharmony_ci** 3450b966c5eSopenharmony_ci** Returns unit8_t (USERIAL baud symbol) 3460b966c5eSopenharmony_ci** 3470b966c5eSopenharmony_ci*******************************************************************************/ 3480b966c5eSopenharmony_ciuint8_t line_speed_to_userial_baud(uint32_t line_speed) 3490b966c5eSopenharmony_ci{ 3500b966c5eSopenharmony_ci uint8_t baud; 3510b966c5eSopenharmony_ci 3520b966c5eSopenharmony_ci if (line_speed == USERIAL_LINESPEED_4M) 3530b966c5eSopenharmony_ci baud = USERIAL_BAUD_4M; 3540b966c5eSopenharmony_ci else if (line_speed == USERIAL_LINESPEED_3M) 3550b966c5eSopenharmony_ci baud = USERIAL_BAUD_3M; 3560b966c5eSopenharmony_ci else if (line_speed == USERIAL_LINESPEED_2M) 3570b966c5eSopenharmony_ci baud = USERIAL_BAUD_2M; 3580b966c5eSopenharmony_ci else if (line_speed == USERIAL_LINESPEED_1_5M) 3590b966c5eSopenharmony_ci baud = USERIAL_BAUD_1_5M; 3600b966c5eSopenharmony_ci else if (line_speed == USERIAL_LINESPEED_1M) 3610b966c5eSopenharmony_ci baud = USERIAL_BAUD_1M; 3620b966c5eSopenharmony_ci else if (line_speed == USERIAL_LINESPEED_921600) 3630b966c5eSopenharmony_ci baud = USERIAL_BAUD_921600; 3640b966c5eSopenharmony_ci else if (line_speed == USERIAL_LINESPEED_460800) 3650b966c5eSopenharmony_ci baud = USERIAL_BAUD_460800; 3660b966c5eSopenharmony_ci else if (line_speed == USERIAL_LINESPEED_230400) 3670b966c5eSopenharmony_ci baud = USERIAL_BAUD_230400; 3680b966c5eSopenharmony_ci else if (line_speed == USERIAL_LINESPEED_115200) 3690b966c5eSopenharmony_ci baud = USERIAL_BAUD_115200; 3700b966c5eSopenharmony_ci else if (line_speed == USERIAL_LINESPEED_57600) 3710b966c5eSopenharmony_ci baud = USERIAL_BAUD_57600; 3720b966c5eSopenharmony_ci else if (line_speed == USERIAL_LINESPEED_19200) 3730b966c5eSopenharmony_ci baud = USERIAL_BAUD_19200; 3740b966c5eSopenharmony_ci else if (line_speed == USERIAL_LINESPEED_9600) 3750b966c5eSopenharmony_ci baud = USERIAL_BAUD_9600; 3760b966c5eSopenharmony_ci else if (line_speed == USERIAL_LINESPEED_1200) 3770b966c5eSopenharmony_ci baud = USERIAL_BAUD_1200; 3780b966c5eSopenharmony_ci else if (line_speed == USERIAL_LINESPEED_600) 3790b966c5eSopenharmony_ci baud = USERIAL_BAUD_600; 3800b966c5eSopenharmony_ci else { 3810b966c5eSopenharmony_ci HILOGE("userial vendor: unsupported baud speed %d", line_speed); 3820b966c5eSopenharmony_ci baud = USERIAL_BAUD_115200; 3830b966c5eSopenharmony_ci } 3840b966c5eSopenharmony_ci 3850b966c5eSopenharmony_ci return baud; 3860b966c5eSopenharmony_ci} 3870b966c5eSopenharmony_ci 3880b966c5eSopenharmony_ci/******************************************************************************* 3890b966c5eSopenharmony_ci** 3900b966c5eSopenharmony_ci** Function hw_strncmp 3910b966c5eSopenharmony_ci** 3920b966c5eSopenharmony_ci** Description Used to compare two strings in caseless 3930b966c5eSopenharmony_ci** 3940b966c5eSopenharmony_ci** Returns 0: match, otherwise: not match 3950b966c5eSopenharmony_ci** 3960b966c5eSopenharmony_ci*******************************************************************************/ 3970b966c5eSopenharmony_cistatic int hw_strncmp(const char *p_str1, const char *p_str2, const int len) 3980b966c5eSopenharmony_ci{ 3990b966c5eSopenharmony_ci int i; 4000b966c5eSopenharmony_ci 4010b966c5eSopenharmony_ci if (!p_str1 || !p_str2) { 4020b966c5eSopenharmony_ci return (1); 4030b966c5eSopenharmony_ci } 4040b966c5eSopenharmony_ci 4050b966c5eSopenharmony_ci for (i = 0; i < len; i++) { 4060b966c5eSopenharmony_ci if (toupper(p_str1[i]) != toupper(p_str2[i])) { 4070b966c5eSopenharmony_ci return (i + 1); 4080b966c5eSopenharmony_ci } 4090b966c5eSopenharmony_ci } 4100b966c5eSopenharmony_ci 4110b966c5eSopenharmony_ci return 0; 4120b966c5eSopenharmony_ci} 4130b966c5eSopenharmony_ci 4140b966c5eSopenharmony_ci/******************************************************************************* 4150b966c5eSopenharmony_ci** 4160b966c5eSopenharmony_ci** Function hw_config_set_bdaddr 4170b966c5eSopenharmony_ci** 4180b966c5eSopenharmony_ci** Description Program controller's Bluetooth Device Address 4190b966c5eSopenharmony_ci** 4200b966c5eSopenharmony_ci** Returns xmit bytes 4210b966c5eSopenharmony_ci** 4220b966c5eSopenharmony_ci*******************************************************************************/ 4230b966c5eSopenharmony_cistatic ssize_t hw_config_set_bdaddr(HC_BT_HDR *p_buf) 4240b966c5eSopenharmony_ci{ 4250b966c5eSopenharmony_ci uint8_t retval = FALSE; 4260b966c5eSopenharmony_ci uint8_t *p = (uint8_t *)(p_buf + 1); 4270b966c5eSopenharmony_ci int i = BD_ADDR_LEN; 4280b966c5eSopenharmony_ci 4290b966c5eSopenharmony_ci UINT16_TO_STREAM(p, HCI_VSC_WRITE_BD_ADDR); 4300b966c5eSopenharmony_ci *p++ = BD_ADDR_LEN; /* parameter length */ 4310b966c5eSopenharmony_ci *p++ = vnd_local_bd_addr[--i]; 4320b966c5eSopenharmony_ci *p++ = vnd_local_bd_addr[--i]; 4330b966c5eSopenharmony_ci *p++ = vnd_local_bd_addr[--i]; 4340b966c5eSopenharmony_ci *p++ = vnd_local_bd_addr[--i]; 4350b966c5eSopenharmony_ci *p++ = vnd_local_bd_addr[--i]; 4360b966c5eSopenharmony_ci *p = vnd_local_bd_addr[--i]; 4370b966c5eSopenharmony_ci 4380b966c5eSopenharmony_ci p_buf->len = HCI_CMD_PREAMBLE_SIZE + BD_ADDR_LEN; 4390b966c5eSopenharmony_ci hw_cfg_cb.state = HW_CFG_SET_BD_ADDR; 4400b966c5eSopenharmony_ci 4410b966c5eSopenharmony_ci retval = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_BD_ADDR, p_buf); 4420b966c5eSopenharmony_ci 4430b966c5eSopenharmony_ci return (retval); 4440b966c5eSopenharmony_ci} 4450b966c5eSopenharmony_ci 4460b966c5eSopenharmony_ci#if (USE_CONTROLLER_BDADDR == TRUE) 4470b966c5eSopenharmony_ci/******************************************************************************* 4480b966c5eSopenharmony_ci** 4490b966c5eSopenharmony_ci** Function hw_config_read_bdaddr 4500b966c5eSopenharmony_ci** 4510b966c5eSopenharmony_ci** Description Read controller's Bluetooth Device Address 4520b966c5eSopenharmony_ci** 4530b966c5eSopenharmony_ci** Returns xmit bytes 4540b966c5eSopenharmony_ci** 4550b966c5eSopenharmony_ci*******************************************************************************/ 4560b966c5eSopenharmony_cistatic ssize_t hw_config_read_bdaddr(HC_BT_HDR *p_buf) 4570b966c5eSopenharmony_ci{ 4580b966c5eSopenharmony_ci uint8_t retval = FALSE; 4590b966c5eSopenharmony_ci uint8_t *p = (uint8_t *)(p_buf + 1); 4600b966c5eSopenharmony_ci 4610b966c5eSopenharmony_ci UINT16_TO_STREAM(p, HCI_READ_LOCAL_BDADDR); 4620b966c5eSopenharmony_ci *p = 0; /* parameter length */ 4630b966c5eSopenharmony_ci 4640b966c5eSopenharmony_ci p_buf->len = HCI_CMD_PREAMBLE_SIZE; 4650b966c5eSopenharmony_ci hw_cfg_cb.state = HW_CFG_READ_BD_ADDR; 4660b966c5eSopenharmony_ci 4670b966c5eSopenharmony_ci retval = bt_vendor_cbacks->xmit_cb(HCI_READ_LOCAL_BDADDR, p_buf); 4680b966c5eSopenharmony_ci 4690b966c5eSopenharmony_ci return (retval); 4700b966c5eSopenharmony_ci} 4710b966c5eSopenharmony_ci#endif // (USE_CONTROLLER_BDADDR == TRUE) 4720b966c5eSopenharmony_ci 4730b966c5eSopenharmony_citypedef void (*tTIMER_HANDLE_CBACK)(union sigval sigval_value); 4740b966c5eSopenharmony_ci 4750b966c5eSopenharmony_cistatic timer_t OsAllocateTimer(tTIMER_HANDLE_CBACK timer_callback) 4760b966c5eSopenharmony_ci{ 4770b966c5eSopenharmony_ci struct sigevent sigev; 4780b966c5eSopenharmony_ci timer_t timerid; 4790b966c5eSopenharmony_ci 4800b966c5eSopenharmony_ci (void)memset_s(&sigev, sizeof(struct sigevent), 0, sizeof(struct sigevent)); 4810b966c5eSopenharmony_ci // Create the POSIX timer to generate signo 4820b966c5eSopenharmony_ci sigev.sigev_notify = SIGEV_THREAD; 4830b966c5eSopenharmony_ci sigev.sigev_notify_function = timer_callback; 4840b966c5eSopenharmony_ci sigev.sigev_value.sival_ptr = &timerid; 4850b966c5eSopenharmony_ci 4860b966c5eSopenharmony_ci // Create the Timer using timer_create signal 4870b966c5eSopenharmony_ci 4880b966c5eSopenharmony_ci if (timer_create(CLOCK_REALTIME, &sigev, &timerid) == 0) { 4890b966c5eSopenharmony_ci return timerid; 4900b966c5eSopenharmony_ci } else { 4910b966c5eSopenharmony_ci HILOGE("timer_create error!"); 4920b966c5eSopenharmony_ci return (timer_t)-1; 4930b966c5eSopenharmony_ci } 4940b966c5eSopenharmony_ci} 4950b966c5eSopenharmony_ci 4960b966c5eSopenharmony_ciint OsFreeTimer(timer_t timerid) 4970b966c5eSopenharmony_ci{ 4980b966c5eSopenharmony_ci int ret = 0; 4990b966c5eSopenharmony_ci ret = timer_delete(timerid); 5000b966c5eSopenharmony_ci if (ret != 0) { 5010b966c5eSopenharmony_ci HILOGE("timer_delete fail with errno(%d)", errno); 5020b966c5eSopenharmony_ci } 5030b966c5eSopenharmony_ci 5040b966c5eSopenharmony_ci return ret; 5050b966c5eSopenharmony_ci} 5060b966c5eSopenharmony_ci 5070b966c5eSopenharmony_cistatic int OsStartTimer(timer_t timerid, int msec, int mode) 5080b966c5eSopenharmony_ci{ 5090b966c5eSopenharmony_ci struct itimerspec itval; 5100b966c5eSopenharmony_ci 5110b966c5eSopenharmony_ci itval.it_value.tv_sec = msec / BT_VENDOR_TIME_RAIDX; 5120b966c5eSopenharmony_ci itval.it_value.tv_nsec = (long)(msec % BT_VENDOR_TIME_RAIDX) * (BT_VENDOR_TIME_RAIDX * BT_VENDOR_TIME_RAIDX); 5130b966c5eSopenharmony_ci 5140b966c5eSopenharmony_ci if (mode == 1) { 5150b966c5eSopenharmony_ci itval.it_interval.tv_sec = itval.it_value.tv_sec; 5160b966c5eSopenharmony_ci itval.it_interval.tv_nsec = itval.it_value.tv_nsec; 5170b966c5eSopenharmony_ci } else { 5180b966c5eSopenharmony_ci itval.it_interval.tv_sec = 0; 5190b966c5eSopenharmony_ci itval.it_interval.tv_nsec = 0; 5200b966c5eSopenharmony_ci } 5210b966c5eSopenharmony_ci 5220b966c5eSopenharmony_ci // Set the Timer when to expire through timer_settime 5230b966c5eSopenharmony_ci 5240b966c5eSopenharmony_ci if (timer_settime(timerid, 0, &itval, NULL) != 0) { 5250b966c5eSopenharmony_ci HILOGE("time_settime error!"); 5260b966c5eSopenharmony_ci return -1; 5270b966c5eSopenharmony_ci } 5280b966c5eSopenharmony_ci 5290b966c5eSopenharmony_ci return 0; 5300b966c5eSopenharmony_ci} 5310b966c5eSopenharmony_ci 5320b966c5eSopenharmony_cistatic timer_t localtimer = 0; 5330b966c5eSopenharmony_cistatic void local_timer_handler(union sigval sigev_value) 5340b966c5eSopenharmony_ci{ 5350b966c5eSopenharmony_ci bt_vendor_cbacks->init_cb(BTC_OP_RESULT_SUCCESS); 5360b966c5eSopenharmony_ci OsFreeTimer(localtimer); 5370b966c5eSopenharmony_ci} 5380b966c5eSopenharmony_cistatic void start_fwcfg_cbtimer(void) 5390b966c5eSopenharmony_ci{ 5400b966c5eSopenharmony_ci if (localtimer == 0) { 5410b966c5eSopenharmony_ci localtimer = OsAllocateTimer(local_timer_handler); 5420b966c5eSopenharmony_ci } 5430b966c5eSopenharmony_ci OsStartTimer(localtimer, BT_VENDOR_CFG_TIMEDELAY_, 0); 5440b966c5eSopenharmony_ci} 5450b966c5eSopenharmony_ci 5460b966c5eSopenharmony_civoid hw_sco_config(void); 5470b966c5eSopenharmony_ci 5480b966c5eSopenharmony_ci/******************************************************************************* 5490b966c5eSopenharmony_ci** 5500b966c5eSopenharmony_ci** Function hw_config_cback 5510b966c5eSopenharmony_ci** 5520b966c5eSopenharmony_ci** Description Callback function for controller configuration 5530b966c5eSopenharmony_ci** 5540b966c5eSopenharmony_ci** Returns None 5550b966c5eSopenharmony_ci** 5560b966c5eSopenharmony_ci*******************************************************************************/ 5570b966c5eSopenharmony_civoid hw_config_cback(void *p_mem) 5580b966c5eSopenharmony_ci{ 5590b966c5eSopenharmony_ci HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem; 5600b966c5eSopenharmony_ci uint8_t *p, status; 5610b966c5eSopenharmony_ci uint16_t opcode; 5620b966c5eSopenharmony_ci HC_BT_HDR *p_buf = NULL; 5630b966c5eSopenharmony_ci ssize_t xmit_bytes = 0; 5640b966c5eSopenharmony_ci int i; 5650b966c5eSopenharmony_ci#if (USE_CONTROLLER_BDADDR == TRUE) 5660b966c5eSopenharmony_ci const uint8_t null_bdaddr[BD_ADDR_LEN] = {0, 0, 0, 0, 0, 0}; 5670b966c5eSopenharmony_ci#endif 5680b966c5eSopenharmony_ci 5690b966c5eSopenharmony_ci status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE); 5700b966c5eSopenharmony_ci p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE; 5710b966c5eSopenharmony_ci STREAM_TO_UINT16(opcode, p); 5720b966c5eSopenharmony_ci 5730b966c5eSopenharmony_ci /* Ask a new buffer big enough to hold any HCI commands sent in here */ 5740b966c5eSopenharmony_ci if ((status == 0) && bt_vendor_cbacks) 5750b966c5eSopenharmony_ci p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + HCI_CMD_MAX_LEN); 5760b966c5eSopenharmony_ci 5770b966c5eSopenharmony_ci if (p_buf != NULL) { 5780b966c5eSopenharmony_ci p_buf->event = MSG_STACK_TO_HC_HCI_CMD; 5790b966c5eSopenharmony_ci p_buf->offset = 0; 5800b966c5eSopenharmony_ci p_buf->len = 0; 5810b966c5eSopenharmony_ci p_buf->layer_specific = 0; 5820b966c5eSopenharmony_ci 5830b966c5eSopenharmony_ci p = (uint8_t *)(p_buf + 1); 5840b966c5eSopenharmony_ci switch (hw_cfg_cb.state) { 5850b966c5eSopenharmony_ci case HW_CFG_SET_UART_BAUD_1: 5860b966c5eSopenharmony_ci /* update baud rate of host's UART port */ 5870b966c5eSopenharmony_ci HILOGI("bt vendor lib: set UART baud %i", UART_TARGET_BAUD_RATE); 5880b966c5eSopenharmony_ci userial_vendor_set_baud(line_speed_to_userial_baud(UART_TARGET_BAUD_RATE)); 5890b966c5eSopenharmony_ci#if 0 5900b966c5eSopenharmony_ci /* read local name */ 5910b966c5eSopenharmony_ci UINT16_TO_STREAM(p, HCI_READ_LOCAL_NAME); 5920b966c5eSopenharmony_ci *p = 0; /* parameter length */ 5930b966c5eSopenharmony_ci 5940b966c5eSopenharmony_ci p_buf->len = HCI_CMD_PREAMBLE_SIZE; 5950b966c5eSopenharmony_ci hw_cfg_cb.state = HW_CFG_READ_LOCAL_NAME; 5960b966c5eSopenharmony_ci 5970b966c5eSopenharmony_ci xmit_bytes = bt_vendor_cbacks->xmit_cb(HCI_READ_LOCAL_NAME, p_buf); 5980b966c5eSopenharmony_ci break; 5990b966c5eSopenharmony_ci#endif 6000b966c5eSopenharmony_ci case HW_CFG_READ_LOCAL_NAME: 6010b966c5eSopenharmony_ci#if 0 6020b966c5eSopenharmony_ci p_tmp = p_name = (char *)(p_evt_buf + 1) + 6030b966c5eSopenharmony_ci HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING; 6040b966c5eSopenharmony_ci 6050b966c5eSopenharmony_ci for (i = 0; (i < LOCAL_NAME_BUFFER_LEN) || (*(p_name + i) != 0); i++) 6060b966c5eSopenharmony_ci *(p_name + i) = toupper(*(p_name + i)); 6070b966c5eSopenharmony_ci 6080b966c5eSopenharmony_ci if ((p_name = strstr(p_name, "BCM")) != NULL) { 6090b966c5eSopenharmony_ci strncpy(hw_cfg_cb.local_chip_name, p_name, 6100b966c5eSopenharmony_ci LOCAL_NAME_BUFFER_LEN - 1); 6110b966c5eSopenharmony_ci#ifdef USE_BLUETOOTH_BCM4343 6120b966c5eSopenharmony_ci } else if ((p_name = strstr(p_tmp, "4343")) != NULL) { 6130b966c5eSopenharmony_ci snprintf(hw_cfg_cb.local_chip_name, 6140b966c5eSopenharmony_ci LOCAL_NAME_BUFFER_LEN - 1, "BCM%s", p_name); 6150b966c5eSopenharmony_ci strncpy(p_name, hw_cfg_cb.local_chip_name, 6160b966c5eSopenharmony_ci LOCAL_NAME_BUFFER_LEN - 1); 6170b966c5eSopenharmony_ci } 6180b966c5eSopenharmony_ci#endif 6190b966c5eSopenharmony_ci else { 6200b966c5eSopenharmony_ci strncpy(hw_cfg_cb.local_chip_name, "UNKNOWN", 6210b966c5eSopenharmony_ci LOCAL_NAME_BUFFER_LEN - 1); 6220b966c5eSopenharmony_ci p_name = p_tmp; 6230b966c5eSopenharmony_ci } 6240b966c5eSopenharmony_ci 6250b966c5eSopenharmony_ci hw_cfg_cb.local_chip_name[LOCAL_NAME_BUFFER_LEN - 1] = 0; 6260b966c5eSopenharmony_ci 6270b966c5eSopenharmony_ci BTHWDBG("Chipset %s", hw_cfg_cb.local_chip_name); 6280b966c5eSopenharmony_ci#endif 6290b966c5eSopenharmony_ci { 6300b966c5eSopenharmony_ci // /vendor/etc/firmware 6310b966c5eSopenharmony_ci char *p_name; 6320b966c5eSopenharmony_ci p_name = FW_PATCHFILE_LOCATION "BCM4362A2.hcd"; 6330b966c5eSopenharmony_ci if ((hw_cfg_cb.fw_fd = open(p_name, O_RDONLY)) == -1) { 6340b966c5eSopenharmony_ci HILOGE("vendor lib preload failed to open [%s]", p_name); 6350b966c5eSopenharmony_ci } else { 6360b966c5eSopenharmony_ci /* vsc_download_minidriver */ 6370b966c5eSopenharmony_ci UINT16_TO_STREAM(p, HCI_VSC_DOWNLOAD_MINIDRV); 6380b966c5eSopenharmony_ci *p = 0; /* parameter length */ 6390b966c5eSopenharmony_ci 6400b966c5eSopenharmony_ci p_buf->len = HCI_CMD_PREAMBLE_SIZE; 6410b966c5eSopenharmony_ci hw_cfg_cb.state = HW_CFG_DL_MINIDRIVER; 6420b966c5eSopenharmony_ci 6430b966c5eSopenharmony_ci xmit_bytes = bt_vendor_cbacks->xmit_cb(HCI_VSC_DOWNLOAD_MINIDRV, p_buf); 6440b966c5eSopenharmony_ci } 6450b966c5eSopenharmony_ci } 6460b966c5eSopenharmony_ci 6470b966c5eSopenharmony_ci if (xmit_bytes <= 0) { 6480b966c5eSopenharmony_ci HILOGE("vendor lib preload failed to locate firmware patch file and set bdaddr"); 6490b966c5eSopenharmony_ci xmit_bytes = hw_config_set_bdaddr(p_buf); 6500b966c5eSopenharmony_ci } 6510b966c5eSopenharmony_ci break; 6520b966c5eSopenharmony_ci 6530b966c5eSopenharmony_ci case HW_CFG_DL_MINIDRIVER: 6540b966c5eSopenharmony_ci /* give time for placing firmware in download mode */ 6550b966c5eSopenharmony_ci ms_delay(50); 6560b966c5eSopenharmony_ci hw_cfg_cb.state = HW_CFG_DL_FW_PATCH; 6570b966c5eSopenharmony_ci /* fall through intentionally */ 6580b966c5eSopenharmony_ci case HW_CFG_DL_FW_PATCH: 6590b966c5eSopenharmony_ci // HILOGD("HW_CFG_DL_FW_PATCH, opcode:0x%02x", opcode); 6600b966c5eSopenharmony_ci p_buf->len = read(hw_cfg_cb.fw_fd, p, HCI_CMD_PREAMBLE_SIZE); 6610b966c5eSopenharmony_ci if (p_buf->len > 0) { 6620b966c5eSopenharmony_ci if ((p_buf->len < HCI_CMD_PREAMBLE_SIZE) || 6630b966c5eSopenharmony_ci (opcode == HCI_VSC_LAUNCH_RAM)) { 6640b966c5eSopenharmony_ci HILOGW("firmware patch file might be altered!"); 6650b966c5eSopenharmony_ci } else { 6660b966c5eSopenharmony_ci p_buf->len += read(hw_cfg_cb.fw_fd, 6670b966c5eSopenharmony_ci p + HCI_CMD_PREAMBLE_SIZE, 6680b966c5eSopenharmony_ci *(p + HCD_REC_PAYLOAD_LEN_BYTE)); 6690b966c5eSopenharmony_ci STREAM_TO_UINT16(opcode, p); 6700b966c5eSopenharmony_ci xmit_bytes = bt_vendor_cbacks->xmit_cb(opcode, p_buf); 6710b966c5eSopenharmony_ci break; 6720b966c5eSopenharmony_ci } 6730b966c5eSopenharmony_ci } 6740b966c5eSopenharmony_ci 6750b966c5eSopenharmony_ci close(hw_cfg_cb.fw_fd); 6760b966c5eSopenharmony_ci hw_cfg_cb.fw_fd = -1; 6770b966c5eSopenharmony_ci 6780b966c5eSopenharmony_ci /* Normally the firmware patch configuration file 6790b966c5eSopenharmony_ci * sets the new starting baud rate at 115200. 6800b966c5eSopenharmony_ci * So, we need update host's baud rate accordingly. 6810b966c5eSopenharmony_ci */ 6820b966c5eSopenharmony_ci HILOGI("bt vendor lib: set UART baud 115200"); 6830b966c5eSopenharmony_ci userial_vendor_set_baud(USERIAL_BAUD_115200); 6840b966c5eSopenharmony_ci 6850b966c5eSopenharmony_ci /* Next, we would like to boost baud rate up again 6860b966c5eSopenharmony_ci * to desired working speed. 6870b966c5eSopenharmony_ci */ 6880b966c5eSopenharmony_ci hw_cfg_cb.f_set_baud_2 = TRUE; 6890b966c5eSopenharmony_ci 6900b966c5eSopenharmony_ci /* Check if we need to pause a few hundred milliseconds 6910b966c5eSopenharmony_ci * before sending down any HCI command. 6920b966c5eSopenharmony_ci */ 6930b966c5eSopenharmony_ci int delay = 0; 6940b966c5eSopenharmony_ci delay = look_up_fw_settlement_delay(); 6950b966c5eSopenharmony_ci HILOGI("Setting fw settlement delay to %d ", delay); 6960b966c5eSopenharmony_ci ms_delay(delay); 6970b966c5eSopenharmony_ci 6980b966c5eSopenharmony_ci p_buf->len = HCI_CMD_PREAMBLE_SIZE; 6990b966c5eSopenharmony_ci UINT16_TO_STREAM(p, HCI_RESET); 7000b966c5eSopenharmony_ci *p = 0; /* parameter length */ 7010b966c5eSopenharmony_ci hw_cfg_cb.state = HW_CFG_START; 7020b966c5eSopenharmony_ci xmit_bytes = bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf); 7030b966c5eSopenharmony_ci break; 7040b966c5eSopenharmony_ci 7050b966c5eSopenharmony_ci case HW_CFG_START: 7060b966c5eSopenharmony_ci if (UART_TARGET_BAUD_RATE > 3000000) { /* 3000000 */ 7070b966c5eSopenharmony_ci /* set UART clock to 48MHz */ 7080b966c5eSopenharmony_ci UINT16_TO_STREAM(p, HCI_VSC_WRITE_UART_CLOCK_SETTING); 7090b966c5eSopenharmony_ci *p++ = 1; /* parameter length */ 7100b966c5eSopenharmony_ci *p = 1; /* (1,"UART CLOCK 48 MHz")(2,"UART CLOCK 24 MHz") */ 7110b966c5eSopenharmony_ci 7120b966c5eSopenharmony_ci p_buf->len = HCI_CMD_PREAMBLE_SIZE + 1; 7130b966c5eSopenharmony_ci hw_cfg_cb.state = HW_CFG_SET_UART_CLOCK; 7140b966c5eSopenharmony_ci 7150b966c5eSopenharmony_ci xmit_bytes = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_UART_CLOCK_SETTING, p_buf); 7160b966c5eSopenharmony_ci break; 7170b966c5eSopenharmony_ci } 7180b966c5eSopenharmony_ci /* fall through intentionally */ 7190b966c5eSopenharmony_ci case HW_CFG_SET_UART_CLOCK: 7200b966c5eSopenharmony_ci /* set controller's UART baud rate to 3M */ 7210b966c5eSopenharmony_ci UINT16_TO_STREAM(p, HCI_VSC_UPDATE_BAUDRATE); 7220b966c5eSopenharmony_ci *p++ = UPDATE_BAUDRATE_CMD_PARAM_SIZE; /* parameter length */ 7230b966c5eSopenharmony_ci *p++ = 0; /* encoded baud rate */ 7240b966c5eSopenharmony_ci *p++ = 0; /* use encoded form */ 7250b966c5eSopenharmony_ci UINT32_TO_STREAM(p, UART_TARGET_BAUD_RATE); 7260b966c5eSopenharmony_ci 7270b966c5eSopenharmony_ci p_buf->len = HCI_CMD_PREAMBLE_SIZE + 7280b966c5eSopenharmony_ci UPDATE_BAUDRATE_CMD_PARAM_SIZE; 7290b966c5eSopenharmony_ci hw_cfg_cb.state = (hw_cfg_cb.f_set_baud_2) ? HW_CFG_SET_UART_BAUD_2 : HW_CFG_SET_UART_BAUD_1; 7300b966c5eSopenharmony_ci 7310b966c5eSopenharmony_ci xmit_bytes = bt_vendor_cbacks->xmit_cb(HCI_VSC_UPDATE_BAUDRATE, p_buf); 7320b966c5eSopenharmony_ci break; 7330b966c5eSopenharmony_ci 7340b966c5eSopenharmony_ci case HW_CFG_SET_UART_BAUD_2: 7350b966c5eSopenharmony_ci /* update baud rate of host's UART port */ 7360b966c5eSopenharmony_ci HILOGI("bt vendor lib: set UART baud %i", UART_TARGET_BAUD_RATE); 7370b966c5eSopenharmony_ci userial_vendor_set_baud( 7380b966c5eSopenharmony_ci line_speed_to_userial_baud(UART_TARGET_BAUD_RATE)); 7390b966c5eSopenharmony_ci 7400b966c5eSopenharmony_ci#if (USE_CONTROLLER_BDADDR == TRUE) 7410b966c5eSopenharmony_ci if ((xmit_bytes = hw_config_read_bdaddr(p_buf)) > 0) 7420b966c5eSopenharmony_ci break; 7430b966c5eSopenharmony_ci#else 7440b966c5eSopenharmony_ci if ((xmit_bytes = hw_config_set_bdaddr(p_buf)) > 0) 7450b966c5eSopenharmony_ci break; 7460b966c5eSopenharmony_ci#endif 7470b966c5eSopenharmony_ci /* fall through intentionally */ 7480b966c5eSopenharmony_ci case HW_CFG_SET_BD_ADDR: 7490b966c5eSopenharmony_ci HILOGI("vendor lib fwcfg completed"); 7500b966c5eSopenharmony_ci bt_vendor_cbacks->dealloc(p_buf); 7510b966c5eSopenharmony_ci // bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS); 7520b966c5eSopenharmony_ci hw_sco_config(); 7530b966c5eSopenharmony_ci start_fwcfg_cbtimer(); 7540b966c5eSopenharmony_ci 7550b966c5eSopenharmony_ci hw_cfg_cb.state = 0; 7560b966c5eSopenharmony_ci 7570b966c5eSopenharmony_ci if (hw_cfg_cb.fw_fd != -1) { 7580b966c5eSopenharmony_ci close(hw_cfg_cb.fw_fd); 7590b966c5eSopenharmony_ci hw_cfg_cb.fw_fd = -1; 7600b966c5eSopenharmony_ci } 7610b966c5eSopenharmony_ci 7620b966c5eSopenharmony_ci xmit_bytes = 1; 7630b966c5eSopenharmony_ci break; 7640b966c5eSopenharmony_ci 7650b966c5eSopenharmony_ci#if (USE_CONTROLLER_BDADDR == TRUE) 7660b966c5eSopenharmony_ci case HW_CFG_READ_BD_ADDR: 7670b966c5eSopenharmony_ci { 7680b966c5eSopenharmony_ci char *p_tmp; 7690b966c5eSopenharmony_ci p_tmp = (char *)(p_evt_buf + 1) + 7700b966c5eSopenharmony_ci HCI_EVT_CMD_CMPL_LOCAL_BDADDR_ARRAY; 7710b966c5eSopenharmony_ci HILOGI("entering HW_CFG_READ_BD_ADDR"); 7720b966c5eSopenharmony_ci if (memcmp(p_tmp, null_bdaddr, BD_ADDR_LEN) == 0) { 7730b966c5eSopenharmony_ci HILOGI("entering HW_CFG_READ_BD_ADDR"); 7740b966c5eSopenharmony_ci // Controller does not have a valid OTP BDADDR! 7750b966c5eSopenharmony_ci // Set the BTIF initial BDADDR instead. 7760b966c5eSopenharmony_ci if ((xmit_bytes = hw_config_set_bdaddr(p_buf)) > 0) 7770b966c5eSopenharmony_ci break; 7780b966c5eSopenharmony_ci } else { 7790b966c5eSopenharmony_ci HILOGI("Controller OTP bdaddr %02X:%02X:%02X:%02X:%02X:%02X", 7800b966c5eSopenharmony_ci *(p_tmp + 5), *(p_tmp + 4), *(p_tmp + 3), 7810b966c5eSopenharmony_ci *(p_tmp + 2), *(p_tmp + 1), *p_tmp); 7820b966c5eSopenharmony_ci } 7830b966c5eSopenharmony_ci } 7840b966c5eSopenharmony_ci 7850b966c5eSopenharmony_ci HILOGI("vendor lib fwcfg completed"); 7860b966c5eSopenharmony_ci bt_vendor_cbacks->dealloc(p_buf); 7870b966c5eSopenharmony_ci // bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS); 7880b966c5eSopenharmony_ci hw_sco_config(); 7890b966c5eSopenharmony_ci start_fwcfg_cbtimer(); 7900b966c5eSopenharmony_ci 7910b966c5eSopenharmony_ci hw_cfg_cb.state = 0; 7920b966c5eSopenharmony_ci 7930b966c5eSopenharmony_ci if (hw_cfg_cb.fw_fd != -1) { 7940b966c5eSopenharmony_ci close(hw_cfg_cb.fw_fd); 7950b966c5eSopenharmony_ci hw_cfg_cb.fw_fd = -1; 7960b966c5eSopenharmony_ci } 7970b966c5eSopenharmony_ci 7980b966c5eSopenharmony_ci xmit_bytes = 1; 7990b966c5eSopenharmony_ci break; 8000b966c5eSopenharmony_ci#endif // (USE_CONTROLLER_BDADDR == TRUE) 8010b966c5eSopenharmony_ci } // switch(hw_cfg_cb.state) 8020b966c5eSopenharmony_ci } // if (p_buf != NULL) 8030b966c5eSopenharmony_ci 8040b966c5eSopenharmony_ci /* Free the RX event buffer */ 8050b966c5eSopenharmony_ci // if (bt_vendor_cbacks) 8060b966c5eSopenharmony_ci // bt_vendor_cbacks->dealloc(p_evt_buf); 8070b966c5eSopenharmony_ci 8080b966c5eSopenharmony_ci if (xmit_bytes <= 0) { 8090b966c5eSopenharmony_ci HILOGE("vendor lib fwcfg aborted!!!"); 8100b966c5eSopenharmony_ci if (bt_vendor_cbacks) { 8110b966c5eSopenharmony_ci if (p_buf != NULL) 8120b966c5eSopenharmony_ci bt_vendor_cbacks->dealloc(p_buf); 8130b966c5eSopenharmony_ci 8140b966c5eSopenharmony_ci bt_vendor_cbacks->init_cb(BTC_OP_RESULT_FAIL); 8150b966c5eSopenharmony_ci } 8160b966c5eSopenharmony_ci 8170b966c5eSopenharmony_ci if (hw_cfg_cb.fw_fd != -1) { 8180b966c5eSopenharmony_ci close(hw_cfg_cb.fw_fd); 8190b966c5eSopenharmony_ci hw_cfg_cb.fw_fd = -1; 8200b966c5eSopenharmony_ci } 8210b966c5eSopenharmony_ci 8220b966c5eSopenharmony_ci hw_cfg_cb.state = 0; 8230b966c5eSopenharmony_ci } 8240b966c5eSopenharmony_ci} 8250b966c5eSopenharmony_ci 8260b966c5eSopenharmony_ci/****************************************************************************** 8270b966c5eSopenharmony_ci** LPM Static Functions 8280b966c5eSopenharmony_ci******************************************************************************/ 8290b966c5eSopenharmony_ci 8300b966c5eSopenharmony_ci/******************************************************************************* 8310b966c5eSopenharmony_ci** 8320b966c5eSopenharmony_ci** Function hw_lpm_ctrl_cback 8330b966c5eSopenharmony_ci** 8340b966c5eSopenharmony_ci** Description Callback function for lpm enable/disable request 8350b966c5eSopenharmony_ci** 8360b966c5eSopenharmony_ci** Returns None 8370b966c5eSopenharmony_ci** 8380b966c5eSopenharmony_ci*******************************************************************************/ 8390b966c5eSopenharmony_civoid hw_lpm_ctrl_cback(void *p_mem) 8400b966c5eSopenharmony_ci{ 8410b966c5eSopenharmony_ci HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem; 8420b966c5eSopenharmony_ci bt_op_result_t status = BTC_OP_RESULT_FAIL; 8430b966c5eSopenharmony_ci 8440b966c5eSopenharmony_ci if (*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0) { 8450b966c5eSopenharmony_ci status = BTC_OP_RESULT_SUCCESS; 8460b966c5eSopenharmony_ci HILOGI("%d", status); 8470b966c5eSopenharmony_ci } 8480b966c5eSopenharmony_ci 8490b966c5eSopenharmony_ci if (bt_vendor_cbacks) { 8500b966c5eSopenharmony_ci // bt_vendor_cbacks->dealloc(p_evt_buf); 8510b966c5eSopenharmony_ci } 8520b966c5eSopenharmony_ci} 8530b966c5eSopenharmony_ci 8540b966c5eSopenharmony_ci#if (SCO_CFG_INCLUDED == TRUE) 8550b966c5eSopenharmony_ci/***************************************************************************** 8560b966c5eSopenharmony_ci** SCO Configuration Static Functions 8570b966c5eSopenharmony_ci*****************************************************************************/ 8580b966c5eSopenharmony_ci 8590b966c5eSopenharmony_cistatic void hw_sco_i2spcm_proc_interface_param(void) 8600b966c5eSopenharmony_ci{ 8610b966c5eSopenharmony_ci bt_op_result_t status = BTC_OP_RESULT_FAIL; 8620b966c5eSopenharmony_ci uint8_t ret = FALSE; 8630b966c5eSopenharmony_ci HC_BT_HDR *p_buf = NULL; 8640b966c5eSopenharmony_ci 8650b966c5eSopenharmony_ci /* Ask a new buffer to hold WRITE_SCO_PCM_INT_PARAM command */ 8660b966c5eSopenharmony_ci if (bt_vendor_cbacks) { 8670b966c5eSopenharmony_ci p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE 8680b966c5eSopenharmony_ci + HCI_CMD_PREAMBLE_SIZE + SCO_PCM_PARAM_SIZE); 8690b966c5eSopenharmony_ci } 8700b966c5eSopenharmony_ci if (p_buf) { 8710b966c5eSopenharmony_ci p_buf->event = MSG_STACK_TO_HC_HCI_CMD; 8720b966c5eSopenharmony_ci p_buf->offset = 0; 8730b966c5eSopenharmony_ci p_buf->layer_specific = 0; 8740b966c5eSopenharmony_ci p_buf->len = HCI_CMD_PREAMBLE_SIZE + SCO_PCM_PARAM_SIZE; 8750b966c5eSopenharmony_ci uint8_t *p = (uint8_t *)(p_buf + 1); 8760b966c5eSopenharmony_ci 8770b966c5eSopenharmony_ci /* do we need this VSC for I2S??? */ 8780b966c5eSopenharmony_ci UINT16_TO_STREAM(p, HCI_VSC_WRITE_SCO_PCM_INT_PARAM); 8790b966c5eSopenharmony_ci *p++ = SCO_PCM_PARAM_SIZE; 8800b966c5eSopenharmony_ci memcpy_s(p, &bt_sco_param, SCO_PCM_PARAM_SIZE); 8810b966c5eSopenharmony_ci if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_SCO_PCM_INT_PARAM, p_buf)) == FALSE) { 8820b966c5eSopenharmony_ci bt_vendor_cbacks->dealloc(p_buf); 8830b966c5eSopenharmony_ci } else 8840b966c5eSopenharmony_ci return; 8850b966c5eSopenharmony_ci } 8860b966c5eSopenharmony_ci status = BTC_OP_RESULT_FAIL; 8870b966c5eSopenharmony_ci 8880b966c5eSopenharmony_ci HILOGI("sco I2S/PCM config interface result %d [0-Success, 1-Fail]", status); 8890b966c5eSopenharmony_ci} 8900b966c5eSopenharmony_ci 8910b966c5eSopenharmony_cistatic void hw_sco_i2spcm_proc_int_param(void) 8920b966c5eSopenharmony_ci{ 8930b966c5eSopenharmony_ci bt_op_result_t status = BTC_OP_RESULT_FAIL; 8940b966c5eSopenharmony_ci uint8_t ret = FALSE; 8950b966c5eSopenharmony_ci HC_BT_HDR *p_buf = NULL; 8960b966c5eSopenharmony_ci 8970b966c5eSopenharmony_ci /* Ask a new buffer to hold WRITE_PCM_DATA_FORMAT_PARAM command */ 8980b966c5eSopenharmony_ci if (bt_vendor_cbacks) 8990b966c5eSopenharmony_ci p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc( 9000b966c5eSopenharmony_ci BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + PCM_DATA_FORMAT_PARAM_SIZE); 9010b966c5eSopenharmony_ci if (p_buf) { 9020b966c5eSopenharmony_ci p_buf->event = MSG_STACK_TO_HC_HCI_CMD; 9030b966c5eSopenharmony_ci p_buf->offset = 0; 9040b966c5eSopenharmony_ci p_buf->layer_specific = 0; 9050b966c5eSopenharmony_ci p_buf->len = HCI_CMD_PREAMBLE_SIZE + PCM_DATA_FORMAT_PARAM_SIZE; 9060b966c5eSopenharmony_ci 9070b966c5eSopenharmony_ci uint8_t *p = (uint8_t *)(p_buf + 1); 9080b966c5eSopenharmony_ci UINT16_TO_STREAM(p, HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM); 9090b966c5eSopenharmony_ci *p++ = PCM_DATA_FORMAT_PARAM_SIZE; 9100b966c5eSopenharmony_ci memcpy_s(p, &bt_pcm_data_fmt_param, PCM_DATA_FORMAT_PARAM_SIZE); 9110b966c5eSopenharmony_ci 9120b966c5eSopenharmony_ci if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM, p_buf)) == FALSE) { 9130b966c5eSopenharmony_ci bt_vendor_cbacks->dealloc(p_buf); 9140b966c5eSopenharmony_ci } else 9150b966c5eSopenharmony_ci return; 9160b966c5eSopenharmony_ci } 9170b966c5eSopenharmony_ci status = BTC_OP_RESULT_FAIL; 9180b966c5eSopenharmony_ci 9190b966c5eSopenharmony_ci HILOGI("sco I2S/PCM config int result %d [0-Success, 1-Fail]", status); 9200b966c5eSopenharmony_ci} 9210b966c5eSopenharmony_ci 9220b966c5eSopenharmony_ci/******************************************************************************* 9230b966c5eSopenharmony_ci** 9240b966c5eSopenharmony_ci** Function hw_sco_i2spcm_cfg_cback 9250b966c5eSopenharmony_ci** 9260b966c5eSopenharmony_ci** Description Callback function for SCO I2S/PCM configuration request 9270b966c5eSopenharmony_ci** 9280b966c5eSopenharmony_ci** Returns None 9290b966c5eSopenharmony_ci** 9300b966c5eSopenharmony_ci*******************************************************************************/ 9310b966c5eSopenharmony_cistatic void hw_sco_i2spcm_cfg_cback(void *p_mem) 9320b966c5eSopenharmony_ci{ 9330b966c5eSopenharmony_ci HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem; 9340b966c5eSopenharmony_ci uint8_t *p; 9350b966c5eSopenharmony_ci uint16_t opcode; 9360b966c5eSopenharmony_ci HC_BT_HDR *p_buf = NULL; 9370b966c5eSopenharmony_ci bt_op_result_t status = BTC_OP_RESULT_FAIL; 9380b966c5eSopenharmony_ci 9390b966c5eSopenharmony_ci p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE; 9400b966c5eSopenharmony_ci STREAM_TO_UINT16(opcode, p); 9410b966c5eSopenharmony_ci 9420b966c5eSopenharmony_ci if (*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0) { 9430b966c5eSopenharmony_ci status = BTC_OP_RESULT_SUCCESS; 9440b966c5eSopenharmony_ci } 9450b966c5eSopenharmony_ci 9460b966c5eSopenharmony_ci /* Free the RX event buffer */ 9470b966c5eSopenharmony_ci if (bt_vendor_cbacks) { 9480b966c5eSopenharmony_ci // bt_vendor_cbacks->dealloc(p_evt_buf); 9490b966c5eSopenharmony_ci } 9500b966c5eSopenharmony_ci 9510b966c5eSopenharmony_ci if (status != BTC_OP_RESULT_SUCCESS) { 9520b966c5eSopenharmony_ci return; 9530b966c5eSopenharmony_ci } 9540b966c5eSopenharmony_ci 9550b966c5eSopenharmony_ci if ((opcode == HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM) && 9560b966c5eSopenharmony_ci (sco_bus_interface == SCO_INTERFACE_PCM)) { 9570b966c5eSopenharmony_ci hw_sco_i2spcm_proc_interface_param(); 9580b966c5eSopenharmony_ci } else if ((opcode == HCI_VSC_WRITE_SCO_PCM_INT_PARAM) && 9590b966c5eSopenharmony_ci (sco_bus_interface == SCO_INTERFACE_PCM)) { 9600b966c5eSopenharmony_ci hw_sco_i2spcm_proc_int_param(); 9610b966c5eSopenharmony_ci } 9620b966c5eSopenharmony_ci} 9630b966c5eSopenharmony_ci 9640b966c5eSopenharmony_ci/******************************************************************************* 9650b966c5eSopenharmony_ci** 9660b966c5eSopenharmony_ci** Function hw_set_MSBC_codec_cback 9670b966c5eSopenharmony_ci** 9680b966c5eSopenharmony_ci** Description Callback function for setting WBS codec 9690b966c5eSopenharmony_ci** 9700b966c5eSopenharmony_ci** Returns None 9710b966c5eSopenharmony_ci** 9720b966c5eSopenharmony_ci*******************************************************************************/ 9730b966c5eSopenharmony_cistatic void hw_set_MSBC_codec_cback(void *p_mem) 9740b966c5eSopenharmony_ci{ 9750b966c5eSopenharmony_ci /* whenever update the codec enable/disable, need to update I2SPCM */ 9760b966c5eSopenharmony_ci HILOGI("SCO I2S interface change the sample rate to 16K"); 9770b966c5eSopenharmony_ci hw_sco_i2spcm_config_from_command(p_mem, SCO_CODEC_MSBC); 9780b966c5eSopenharmony_ci} 9790b966c5eSopenharmony_ci 9800b966c5eSopenharmony_ci/******************************************************************************* 9810b966c5eSopenharmony_ci** 9820b966c5eSopenharmony_ci** Function hw_set_CVSD_codec_cback 9830b966c5eSopenharmony_ci** 9840b966c5eSopenharmony_ci** Description Callback function for setting NBS codec 9850b966c5eSopenharmony_ci** 9860b966c5eSopenharmony_ci** Returns None 9870b966c5eSopenharmony_ci** 9880b966c5eSopenharmony_ci*******************************************************************************/ 9890b966c5eSopenharmony_cistatic void hw_set_CVSD_codec_cback(void *p_mem) 9900b966c5eSopenharmony_ci{ 9910b966c5eSopenharmony_ci /* whenever update the codec enable/disable, need to update I2SPCM */ 9920b966c5eSopenharmony_ci HILOGI("SCO I2S interface change the sample rate to 8K"); 9930b966c5eSopenharmony_ci hw_sco_i2spcm_config_from_command(p_mem, SCO_CODEC_CVSD); 9940b966c5eSopenharmony_ci} 9950b966c5eSopenharmony_ci 9960b966c5eSopenharmony_ci#endif // SCO_CFG_INCLUDED 9970b966c5eSopenharmony_ci 9980b966c5eSopenharmony_ci/***************************************************************************** 9990b966c5eSopenharmony_ci** Hardware Configuration Interface Functions 10000b966c5eSopenharmony_ci*****************************************************************************/ 10010b966c5eSopenharmony_ci 10020b966c5eSopenharmony_ci/******************************************************************************* 10030b966c5eSopenharmony_ci** 10040b966c5eSopenharmony_ci** Function hw_config_start 10050b966c5eSopenharmony_ci** 10060b966c5eSopenharmony_ci** Description Kick off controller initialization process 10070b966c5eSopenharmony_ci** 10080b966c5eSopenharmony_ci** Returns None 10090b966c5eSopenharmony_ci** 10100b966c5eSopenharmony_ci*******************************************************************************/ 10110b966c5eSopenharmony_civoid hw_config_start(void) 10120b966c5eSopenharmony_ci{ 10130b966c5eSopenharmony_ci HC_BT_HDR *p_buf = NULL; 10140b966c5eSopenharmony_ci 10150b966c5eSopenharmony_ci hw_cfg_cb.state = 0; 10160b966c5eSopenharmony_ci hw_cfg_cb.fw_fd = -1; 10170b966c5eSopenharmony_ci hw_cfg_cb.f_set_baud_2 = FALSE; 10180b966c5eSopenharmony_ci 10190b966c5eSopenharmony_ci // bt_vendor_cbacks->init_cb(BTC_OP_RESULT_SUCCESS); 10200b966c5eSopenharmony_ci // Start from sending HCI_RESET 10210b966c5eSopenharmony_ci 10220b966c5eSopenharmony_ci if (bt_vendor_cbacks) { 10230b966c5eSopenharmony_ci p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + 10240b966c5eSopenharmony_ci HCI_CMD_PREAMBLE_SIZE); 10250b966c5eSopenharmony_ci } 10260b966c5eSopenharmony_ci 10270b966c5eSopenharmony_ci if (p_buf) { 10280b966c5eSopenharmony_ci p_buf->event = MSG_STACK_TO_HC_HCI_CMD; 10290b966c5eSopenharmony_ci p_buf->offset = 0; 10300b966c5eSopenharmony_ci p_buf->layer_specific = 0; 10310b966c5eSopenharmony_ci p_buf->len = HCI_CMD_PREAMBLE_SIZE; 10320b966c5eSopenharmony_ci 10330b966c5eSopenharmony_ci uint8_t *p = (uint8_t *)(p_buf + 1); 10340b966c5eSopenharmony_ci UINT16_TO_STREAM(p, HCI_RESET); 10350b966c5eSopenharmony_ci *p = 0; 10360b966c5eSopenharmony_ci 10370b966c5eSopenharmony_ci hw_cfg_cb.state = HW_CFG_START; 10380b966c5eSopenharmony_ci bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf); 10390b966c5eSopenharmony_ci } else { 10400b966c5eSopenharmony_ci if (bt_vendor_cbacks) { 10410b966c5eSopenharmony_ci HILOGE("vendor lib fw conf aborted [no buffer]"); 10420b966c5eSopenharmony_ci bt_vendor_cbacks->init_cb(BTC_OP_RESULT_FAIL); 10430b966c5eSopenharmony_ci } 10440b966c5eSopenharmony_ci } 10450b966c5eSopenharmony_ci} 10460b966c5eSopenharmony_ci 10470b966c5eSopenharmony_ci/******************************************************************************* 10480b966c5eSopenharmony_ci** 10490b966c5eSopenharmony_ci** Function hw_lpm_enable 10500b966c5eSopenharmony_ci** 10510b966c5eSopenharmony_ci** Description Enalbe/Disable LPM 10520b966c5eSopenharmony_ci** 10530b966c5eSopenharmony_ci** Returns TRUE/FALSE 10540b966c5eSopenharmony_ci** 10550b966c5eSopenharmony_ci*******************************************************************************/ 10560b966c5eSopenharmony_ciuint8_t hw_lpm_enable(uint8_t turn_on) 10570b966c5eSopenharmony_ci{ 10580b966c5eSopenharmony_ci HILOGD("entering hw_lpm_enable11"); 10590b966c5eSopenharmony_ci HC_BT_HDR *p_buf = NULL; 10600b966c5eSopenharmony_ci uint8_t ret = FALSE; 10610b966c5eSopenharmony_ci 10620b966c5eSopenharmony_ci if (bt_vendor_cbacks) 10630b966c5eSopenharmony_ci p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + 10640b966c5eSopenharmony_ci HCI_CMD_PREAMBLE_SIZE + 10650b966c5eSopenharmony_ci LPM_CMD_PARAM_SIZE); 10660b966c5eSopenharmony_ci 10670b966c5eSopenharmony_ci if (p_buf) { 10680b966c5eSopenharmony_ci p_buf->event = MSG_STACK_TO_HC_HCI_CMD; 10690b966c5eSopenharmony_ci p_buf->offset = 0; 10700b966c5eSopenharmony_ci p_buf->layer_specific = 0; 10710b966c5eSopenharmony_ci p_buf->len = HCI_CMD_PREAMBLE_SIZE + LPM_CMD_PARAM_SIZE; 10720b966c5eSopenharmony_ci 10730b966c5eSopenharmony_ci uint8_t *p = (uint8_t *)(p_buf + 1); 10740b966c5eSopenharmony_ci UINT16_TO_STREAM(p, HCI_VSC_WRITE_SLEEP_MODE); 10750b966c5eSopenharmony_ci *p++ = LPM_CMD_PARAM_SIZE; /* parameter length */ 10760b966c5eSopenharmony_ci 10770b966c5eSopenharmony_ci if (turn_on) { 10780b966c5eSopenharmony_ci memcpy(p, &lpm_param, LPM_CMD_PARAM_SIZE); 10790b966c5eSopenharmony_ci upio_set(UPIO_LPM_MODE, UPIO_ASSERT, 0); 10800b966c5eSopenharmony_ci } else { 10810b966c5eSopenharmony_ci memset(p, 0, LPM_CMD_PARAM_SIZE); 10820b966c5eSopenharmony_ci upio_set(UPIO_LPM_MODE, UPIO_DEASSERT, 0); 10830b966c5eSopenharmony_ci } 10840b966c5eSopenharmony_ci 10850b966c5eSopenharmony_ci if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_SLEEP_MODE, p_buf)) == FALSE) { 10860b966c5eSopenharmony_ci bt_vendor_cbacks->dealloc(p_buf); 10870b966c5eSopenharmony_ci } 10880b966c5eSopenharmony_ci } 10890b966c5eSopenharmony_ci 10900b966c5eSopenharmony_ci if ((ret == 0) && bt_vendor_cbacks) { 10910b966c5eSopenharmony_ci // bt_vendor_cbacks->lpm_cb(BT_VND_OP_RESULT_FAIL); 10920b966c5eSopenharmony_ci } 10930b966c5eSopenharmony_ci HILOGD("hw_lpm_enable ret:%d", ret); 10940b966c5eSopenharmony_ci return ret; 10950b966c5eSopenharmony_ci} 10960b966c5eSopenharmony_ci 10970b966c5eSopenharmony_ci/******************************************************************************* 10980b966c5eSopenharmony_ci** 10990b966c5eSopenharmony_ci** Function hw_lpm_get_idle_timeout 11000b966c5eSopenharmony_ci** 11010b966c5eSopenharmony_ci** Description Calculate idle time based on host stack idle threshold 11020b966c5eSopenharmony_ci** 11030b966c5eSopenharmony_ci** Returns idle timeout value 11040b966c5eSopenharmony_ci** 11050b966c5eSopenharmony_ci*******************************************************************************/ 11060b966c5eSopenharmony_ciuint32_t hw_lpm_get_idle_timeout(void) 11070b966c5eSopenharmony_ci{ 11080b966c5eSopenharmony_ci uint32_t timeout_ms; 11090b966c5eSopenharmony_ci 11100b966c5eSopenharmony_ci /* set idle time to be LPM_IDLE_TIMEOUT_MULTIPLE times of 11110b966c5eSopenharmony_ci * host stack idle threshold (in 300ms/25ms) 11120b966c5eSopenharmony_ci */ 11130b966c5eSopenharmony_ci timeout_ms = (uint32_t)lpm_param.host_stack_idle_threshold * LPM_IDLE_TIMEOUT_MULTIPLE; 11140b966c5eSopenharmony_ci timeout_ms *= BT_VENDOR_LDM_DEFAULT_IDLE; 11150b966c5eSopenharmony_ci return timeout_ms; 11160b966c5eSopenharmony_ci} 11170b966c5eSopenharmony_ci 11180b966c5eSopenharmony_ci/******************************************************************************* 11190b966c5eSopenharmony_ci** 11200b966c5eSopenharmony_ci** Function hw_lpm_set_wake_state 11210b966c5eSopenharmony_ci** 11220b966c5eSopenharmony_ci** Description Assert/Deassert BT_WAKE 11230b966c5eSopenharmony_ci** 11240b966c5eSopenharmony_ci** Returns None 11250b966c5eSopenharmony_ci** 11260b966c5eSopenharmony_ci*******************************************************************************/ 11270b966c5eSopenharmony_civoid hw_lpm_set_wake_state(uint8_t wake_assert) 11280b966c5eSopenharmony_ci{ 11290b966c5eSopenharmony_ci uint8_t state = (wake_assert) ? UPIO_ASSERT : UPIO_DEASSERT; 11300b966c5eSopenharmony_ci 11310b966c5eSopenharmony_ci upio_set(UPIO_BT_WAKE, state, lpm_param.bt_wake_polarity); 11320b966c5eSopenharmony_ci} 11330b966c5eSopenharmony_ci 11340b966c5eSopenharmony_ci#if (SCO_CFG_INCLUDED == TRUE) 11350b966c5eSopenharmony_ci/******************************************************************************* 11360b966c5eSopenharmony_ci** 11370b966c5eSopenharmony_ci** Function hw_sco_config 11380b966c5eSopenharmony_ci** 11390b966c5eSopenharmony_ci** Description Configure SCO related hardware settings 11400b966c5eSopenharmony_ci** 11410b966c5eSopenharmony_ci** Returns None 11420b966c5eSopenharmony_ci** 11430b966c5eSopenharmony_ci*******************************************************************************/ 11440b966c5eSopenharmony_civoid hw_sco_config(void) 11450b966c5eSopenharmony_ci{ 11460b966c5eSopenharmony_ci if (sco_bus_interface == SCO_INTERFACE_I2S) { 11470b966c5eSopenharmony_ci /* 'Enable' I2S mode */ 11480b966c5eSopenharmony_ci bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_MODE] = 1; 11490b966c5eSopenharmony_ci 11500b966c5eSopenharmony_ci /* set nbs clock rate as the value in SCO_I2SPCM_IF_CLOCK_RATE field */ 11510b966c5eSopenharmony_ci sco_bus_clock_rate = bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_CLOCK_RATE]; 11520b966c5eSopenharmony_ci } else { 11530b966c5eSopenharmony_ci /* 'Disable' I2S mode */ 11540b966c5eSopenharmony_ci bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_MODE] = 0; 11550b966c5eSopenharmony_ci 11560b966c5eSopenharmony_ci /* set nbs clock rate as the value in SCO_PCM_IF_CLOCK_RATE field */ 11570b966c5eSopenharmony_ci sco_bus_clock_rate = bt_sco_param[SCO_PCM_PARAM_IF_CLOCK_RATE]; 11580b966c5eSopenharmony_ci 11590b966c5eSopenharmony_ci /* sync up clock mode setting */ 11600b966c5eSopenharmony_ci bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_MODE] = bt_sco_param[SCO_PCM_PARAM_IF_CLOCK_MODE]; 11610b966c5eSopenharmony_ci } 11620b966c5eSopenharmony_ci 11630b966c5eSopenharmony_ci if (sco_bus_wbs_clock_rate == INVALID_SCO_CLOCK_RATE) { 11640b966c5eSopenharmony_ci /* set default wbs clock rate */ 11650b966c5eSopenharmony_ci sco_bus_wbs_clock_rate = SCO_I2SPCM_IF_CLOCK_RATE4WBS; 11660b966c5eSopenharmony_ci 11670b966c5eSopenharmony_ci if (sco_bus_wbs_clock_rate < sco_bus_clock_rate) 11680b966c5eSopenharmony_ci sco_bus_wbs_clock_rate = sco_bus_clock_rate; 11690b966c5eSopenharmony_ci } 11700b966c5eSopenharmony_ci 11710b966c5eSopenharmony_ci /* 11720b966c5eSopenharmony_ci * To support I2S/PCM port multiplexing signals for sharing Bluetooth audio 11730b966c5eSopenharmony_ci * and FM on the same PCM pins, we defer Bluetooth audio (SCO/eSCO) 11740b966c5eSopenharmony_ci * configuration till SCO/eSCO is being established; 11750b966c5eSopenharmony_ci * i.e. in hw_set_audio_state() call. 11760b966c5eSopenharmony_ci * When configured as I2S only, Bluetooth audio configuration is executed 11770b966c5eSopenharmony_ci * immediately with SCO_CODEC_CVSD by default. 11780b966c5eSopenharmony_ci */ 11790b966c5eSopenharmony_ci 11800b966c5eSopenharmony_ci if (sco_bus_interface == SCO_INTERFACE_I2S) { 11810b966c5eSopenharmony_ci hw_sco_i2spcm_config(SCO_CODEC_CVSD); 11820b966c5eSopenharmony_ci } else { 11830b966c5eSopenharmony_ci hw_sco_i2spcm_config(SCO_CODEC_NONE); 11840b966c5eSopenharmony_ci } 11850b966c5eSopenharmony_ci 11860b966c5eSopenharmony_ci if (bt_vendor_cbacks) { 11870b966c5eSopenharmony_ci // bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_SUCCESS); 11880b966c5eSopenharmony_ci } 11890b966c5eSopenharmony_ci} 11900b966c5eSopenharmony_ci 11910b966c5eSopenharmony_cistatic void hw_sco_i2spcm_config_from_command(void *p_mem, uint16_t codec) 11920b966c5eSopenharmony_ci{ 11930b966c5eSopenharmony_ci HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem; 11940b966c5eSopenharmony_ci bool command_success = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0; 11950b966c5eSopenharmony_ci 11960b966c5eSopenharmony_ci /* Free the RX event buffer */ 11970b966c5eSopenharmony_ci if (bt_vendor_cbacks) { 11980b966c5eSopenharmony_ci // bt_vendor_cbacks->dealloc(p_evt_buf); 11990b966c5eSopenharmony_ci } 12000b966c5eSopenharmony_ci 12010b966c5eSopenharmony_ci if (command_success) { 12020b966c5eSopenharmony_ci hw_sco_i2spcm_config(codec); 12030b966c5eSopenharmony_ci } else if (bt_vendor_cbacks) { 12040b966c5eSopenharmony_ci // bt_vendor_cbacks->audio_state_cb(BT_VND_OP_RESULT_FAIL); 12050b966c5eSopenharmony_ci } 12060b966c5eSopenharmony_ci} 12070b966c5eSopenharmony_ci 12080b966c5eSopenharmony_ci/******************************************************************************* 12090b966c5eSopenharmony_ci** 12100b966c5eSopenharmony_ci** Function hw_sco_i2spcm_config 12110b966c5eSopenharmony_ci** 12120b966c5eSopenharmony_ci** Description Configure SCO over I2S or PCM 12130b966c5eSopenharmony_ci** 12140b966c5eSopenharmony_ci** Returns None 12150b966c5eSopenharmony_ci** 12160b966c5eSopenharmony_ci*******************************************************************************/ 12170b966c5eSopenharmony_cistatic void hw_sco_i2spcm_config(uint16_t codec) 12180b966c5eSopenharmony_ci{ 12190b966c5eSopenharmony_ci HC_BT_HDR *p_buf = NULL; 12200b966c5eSopenharmony_ci uint16_t cmd_u16 = HCI_CMD_PREAMBLE_SIZE + SCO_I2SPCM_PARAM_SIZE; 12210b966c5eSopenharmony_ci 12220b966c5eSopenharmony_ci if (bt_vendor_cbacks) { 12230b966c5eSopenharmony_ci p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + cmd_u16); 12240b966c5eSopenharmony_ci } 12250b966c5eSopenharmony_ci 12260b966c5eSopenharmony_ci if (p_buf) { 12270b966c5eSopenharmony_ci p_buf->event = MSG_STACK_TO_HC_HCI_CMD; 12280b966c5eSopenharmony_ci p_buf->offset = 0; 12290b966c5eSopenharmony_ci p_buf->layer_specific = 0; 12300b966c5eSopenharmony_ci p_buf->len = cmd_u16; 12310b966c5eSopenharmony_ci uint8_t ret; 12320b966c5eSopenharmony_ci uint8_t *p = (uint8_t *)(p_buf + 1); 12330b966c5eSopenharmony_ci 12340b966c5eSopenharmony_ci UINT16_TO_STREAM(p, HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM); 12350b966c5eSopenharmony_ci *p++ = SCO_I2SPCM_PARAM_SIZE; 12360b966c5eSopenharmony_ci if (codec == SCO_CODEC_CVSD) { 12370b966c5eSopenharmony_ci bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_SAMPLE_RATE] = 0; /* SCO_I2SPCM_IF_SAMPLE_RATE 8k */ 12380b966c5eSopenharmony_ci bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_CLOCK_RATE] = 12390b966c5eSopenharmony_ci bt_sco_param[SCO_PCM_PARAM_IF_CLOCK_RATE] = sco_bus_clock_rate; 12400b966c5eSopenharmony_ci } else if (codec == SCO_CODEC_MSBC) { 12410b966c5eSopenharmony_ci bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_SAMPLE_RATE] = wbs_sample_rate; /* SCO_I2SPCM_IF_SAMPLE_RATE 16K */ 12420b966c5eSopenharmony_ci bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_CLOCK_RATE] = 12430b966c5eSopenharmony_ci bt_sco_param[SCO_PCM_PARAM_IF_CLOCK_RATE] = sco_bus_wbs_clock_rate; 12440b966c5eSopenharmony_ci } else { 12450b966c5eSopenharmony_ci bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_SAMPLE_RATE] = 0; /* SCO_I2SPCM_IF_SAMPLE_RATE 8k */ 12460b966c5eSopenharmony_ci bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_CLOCK_RATE] = 12470b966c5eSopenharmony_ci bt_sco_param[SCO_PCM_PARAM_IF_CLOCK_RATE] = sco_bus_clock_rate; 12480b966c5eSopenharmony_ci HILOGE("wrong codec is use in hw_sco_i2spcm_config, goes default NBS"); 12490b966c5eSopenharmony_ci } 12500b966c5eSopenharmony_ci memcpy_s(p, &bt_sco_i2spcm_param, SCO_I2SPCM_PARAM_SIZE); 12510b966c5eSopenharmony_ci cmd_u16 = HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM; 12520b966c5eSopenharmony_ci HILOGI("I2SPCM config {0x%x, 0x%x, 0x%x, 0x%x}", 12530b966c5eSopenharmony_ci bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_MODE], bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_ROLE], 12540b966c5eSopenharmony_ci bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_SAMPLE_RATE], 12550b966c5eSopenharmony_ci bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_CLOCK_RATE]); 12560b966c5eSopenharmony_ci 12570b966c5eSopenharmony_ci if ((ret = bt_vendor_cbacks->xmit_cb(cmd_u16, p_buf)) == FALSE) { 12580b966c5eSopenharmony_ci bt_vendor_cbacks->dealloc(p_buf); 12590b966c5eSopenharmony_ci } else { 12600b966c5eSopenharmony_ci return; 12610b966c5eSopenharmony_ci } 12620b966c5eSopenharmony_ci } 12630b966c5eSopenharmony_ci // bt_vendor_cbacks->audio_state_cb(BT_VND_OP_RESULT_FAIL); 12640b966c5eSopenharmony_ci} 12650b966c5eSopenharmony_ci 12660b966c5eSopenharmony_ci/******************************************************************************* 12670b966c5eSopenharmony_ci** 12680b966c5eSopenharmony_ci** Function hw_set_SCO_codec 12690b966c5eSopenharmony_ci** 12700b966c5eSopenharmony_ci** Description This functgion sends command to the controller to setup 12710b966c5eSopenharmony_ci** WBS/NBS codec for the upcoming eSCO connection. 12720b966c5eSopenharmony_ci** 12730b966c5eSopenharmony_ci** Returns -1 : Failed to send VSC 12740b966c5eSopenharmony_ci** 0 : Success 12750b966c5eSopenharmony_ci** 12760b966c5eSopenharmony_ci*******************************************************************************/ 12770b966c5eSopenharmony_cistatic int hw_set_SCO_codec(uint16_t codec) 12780b966c5eSopenharmony_ci{ 12790b966c5eSopenharmony_ci HC_BT_HDR *p_buf = NULL; 12800b966c5eSopenharmony_ci int ret_val = 0; 12810b966c5eSopenharmony_ci return ret_val; 12820b966c5eSopenharmony_ci} 12830b966c5eSopenharmony_ci 12840b966c5eSopenharmony_ci/******************************************************************************* 12850b966c5eSopenharmony_ci** 12860b966c5eSopenharmony_ci** Function hw_set_audio_state 12870b966c5eSopenharmony_ci** 12880b966c5eSopenharmony_ci** Description This function configures audio base on provided audio state 12890b966c5eSopenharmony_ci** 12900b966c5eSopenharmony_ci** Paramters pointer to audio state structure 12910b966c5eSopenharmony_ci** 12920b966c5eSopenharmony_ci** Returns 0: ok, -1: error 12930b966c5eSopenharmony_ci** 12940b966c5eSopenharmony_ci*******************************************************************************/ 12950b966c5eSopenharmony_ciint hw_set_audio_state(bt_vendor_op_audio_state_t *p_state) 12960b966c5eSopenharmony_ci{ 12970b966c5eSopenharmony_ci int ret_val = -1; 12980b966c5eSopenharmony_ci 12990b966c5eSopenharmony_ci if (!bt_vendor_cbacks) { 13000b966c5eSopenharmony_ci return ret_val; 13010b966c5eSopenharmony_ci } 13020b966c5eSopenharmony_ci 13030b966c5eSopenharmony_ci ret_val = hw_set_SCO_codec(p_state->peer_codec); 13040b966c5eSopenharmony_ci return ret_val; 13050b966c5eSopenharmony_ci} 13060b966c5eSopenharmony_ci#endif 13070b966c5eSopenharmony_ci/******************************************************************************* 13080b966c5eSopenharmony_ci** 13090b966c5eSopenharmony_ci** Function hw_set_patch_file_path 13100b966c5eSopenharmony_ci** 13110b966c5eSopenharmony_ci** Description Set the location of firmware patch file 13120b966c5eSopenharmony_ci** 13130b966c5eSopenharmony_ci** Returns 0 : Success 13140b966c5eSopenharmony_ci** Otherwise : Fail 13150b966c5eSopenharmony_ci** 13160b966c5eSopenharmony_ci*******************************************************************************/ 13170b966c5eSopenharmony_ciint hw_set_patch_file_path(char *p_conf_name, char *p_conf_value, int param) 13180b966c5eSopenharmony_ci{ 13190b966c5eSopenharmony_ci if (strcpy_s(fw_patchfile_path, sizeof(fw_patchfile_path), p_conf_value) != 0) { 13200b966c5eSopenharmony_ci return -1; 13210b966c5eSopenharmony_ci } 13220b966c5eSopenharmony_ci return 0; 13230b966c5eSopenharmony_ci} 13240b966c5eSopenharmony_ci 13250b966c5eSopenharmony_ci/******************************************************************************* 13260b966c5eSopenharmony_ci** 13270b966c5eSopenharmony_ci** Function hw_set_patch_file_name 13280b966c5eSopenharmony_ci** 13290b966c5eSopenharmony_ci** Description Give the specific firmware patch filename 13300b966c5eSopenharmony_ci** 13310b966c5eSopenharmony_ci** Returns 0 : Success 13320b966c5eSopenharmony_ci** Otherwise : Fail 13330b966c5eSopenharmony_ci** 13340b966c5eSopenharmony_ci*******************************************************************************/ 13350b966c5eSopenharmony_ciint hw_set_patch_file_name(char *p_conf_name, char *p_conf_value, int param) 13360b966c5eSopenharmony_ci{ 13370b966c5eSopenharmony_ci if (strcpy_s(fw_patchfile_name, sizeof(fw_patchfile_name), p_conf_value) != 0) { 13380b966c5eSopenharmony_ci return -1; 13390b966c5eSopenharmony_ci } 13400b966c5eSopenharmony_ci return 0; 13410b966c5eSopenharmony_ci} 13420b966c5eSopenharmony_ci 13430b966c5eSopenharmony_ci#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE) 13440b966c5eSopenharmony_ci/******************************************************************************* 13450b966c5eSopenharmony_ci** 13460b966c5eSopenharmony_ci** Function hw_set_patch_settlement_delay 13470b966c5eSopenharmony_ci** 13480b966c5eSopenharmony_ci** Description Give the specific firmware patch settlement time in milliseconds 13490b966c5eSopenharmony_ci** 13500b966c5eSopenharmony_ci** Returns 0 : Success 13510b966c5eSopenharmony_ci** Otherwise : Fail 13520b966c5eSopenharmony_ci** 13530b966c5eSopenharmony_ci*******************************************************************************/ 13540b966c5eSopenharmony_ciint hw_set_patch_settlement_delay(char *p_conf_name, char *p_conf_value, int param) 13550b966c5eSopenharmony_ci{ 13560b966c5eSopenharmony_ci fw_patch_settlement_delay = atoi(p_conf_value); 13570b966c5eSopenharmony_ci return 0; 13580b966c5eSopenharmony_ci} 13590b966c5eSopenharmony_ci#endif // VENDOR_LIB_RUNTIME_TUNING_ENABLED 13600b966c5eSopenharmony_ci 13610b966c5eSopenharmony_ci/***************************************************************************** 13620b966c5eSopenharmony_ci** Sample Codes Section 13630b966c5eSopenharmony_ci*****************************************************************************/ 13640b966c5eSopenharmony_ci 13650b966c5eSopenharmony_ci#if (HW_END_WITH_HCI_RESET == TRUE) 13660b966c5eSopenharmony_ci/******************************************************************************* 13670b966c5eSopenharmony_ci** 13680b966c5eSopenharmony_ci** Function hw_epilog_cback 13690b966c5eSopenharmony_ci** 13700b966c5eSopenharmony_ci** Description Callback function for Command Complete Events from HCI 13710b966c5eSopenharmony_ci** commands sent in epilog process. 13720b966c5eSopenharmony_ci** 13730b966c5eSopenharmony_ci** Returns None 13740b966c5eSopenharmony_ci** 13750b966c5eSopenharmony_ci*******************************************************************************/ 13760b966c5eSopenharmony_civoid hw_epilog_cback(void *p_mem) 13770b966c5eSopenharmony_ci{ 13780b966c5eSopenharmony_ci HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem; 13790b966c5eSopenharmony_ci uint8_t *p, status; 13800b966c5eSopenharmony_ci uint16_t opcode; 13810b966c5eSopenharmony_ci 13820b966c5eSopenharmony_ci status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE); 13830b966c5eSopenharmony_ci p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE; 13840b966c5eSopenharmony_ci STREAM_TO_UINT16(opcode, p); 13850b966c5eSopenharmony_ci 13860b966c5eSopenharmony_ci BTHWDBG("%s Opcode:0x%04X Status: %d", __FUNCTION__, opcode, status); 13870b966c5eSopenharmony_ci 13880b966c5eSopenharmony_ci if (bt_vendor_cbacks) { 13890b966c5eSopenharmony_ci /* Must free the RX event buffer */ 13900b966c5eSopenharmony_ci // bt_vendor_cbacks->dealloc(p_evt_buf); 13910b966c5eSopenharmony_ci /* Once epilog process is done, must call epilog_cb callback 13920b966c5eSopenharmony_ci to notify caller */ 13930b966c5eSopenharmony_ci // bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS); 13940b966c5eSopenharmony_ci } 13950b966c5eSopenharmony_ci} 13960b966c5eSopenharmony_ci 13970b966c5eSopenharmony_ci/******************************************************************************* 13980b966c5eSopenharmony_ci** 13990b966c5eSopenharmony_ci** Function hw_epilog_process 14000b966c5eSopenharmony_ci** 14010b966c5eSopenharmony_ci** Description Sample implementation of epilog process 14020b966c5eSopenharmony_ci** 14030b966c5eSopenharmony_ci** Returns None 14040b966c5eSopenharmony_ci** 14050b966c5eSopenharmony_ci*******************************************************************************/ 14060b966c5eSopenharmony_civoid hw_epilog_process(void) 14070b966c5eSopenharmony_ci{ 14080b966c5eSopenharmony_ci HC_BT_HDR *p_buf = NULL; 14090b966c5eSopenharmony_ci 14100b966c5eSopenharmony_ci BTHWDBG("hw_epilog_process"); 14110b966c5eSopenharmony_ci 14120b966c5eSopenharmony_ci /* Sending a HCI_RESET */ 14130b966c5eSopenharmony_ci if (bt_vendor_cbacks) { 14140b966c5eSopenharmony_ci /* Must allocate command buffer via HC's alloc API */ 14150b966c5eSopenharmony_ci p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + 14160b966c5eSopenharmony_ci HCI_CMD_PREAMBLE_SIZE); 14170b966c5eSopenharmony_ci } 14180b966c5eSopenharmony_ci 14190b966c5eSopenharmony_ci if (p_buf) { 14200b966c5eSopenharmony_ci p_buf->event = MSG_STACK_TO_HC_HCI_CMD; 14210b966c5eSopenharmony_ci p_buf->offset = 0; 14220b966c5eSopenharmony_ci p_buf->layer_specific = 0; 14230b966c5eSopenharmony_ci p_buf->len = HCI_CMD_PREAMBLE_SIZE; 14240b966c5eSopenharmony_ci 14250b966c5eSopenharmony_ci uint8_t *p = (uint8_t *)(p_buf + 1); 14260b966c5eSopenharmony_ci UINT16_TO_STREAM(p, HCI_RESET); 14270b966c5eSopenharmony_ci *p = 0; /* parameter length */ 14280b966c5eSopenharmony_ci 14290b966c5eSopenharmony_ci /* Send command via HC's xmit_cb API */ 14300b966c5eSopenharmony_ci bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf); 14310b966c5eSopenharmony_ci } else { 14320b966c5eSopenharmony_ci if (bt_vendor_cbacks) { 14330b966c5eSopenharmony_ci HILOGE("vendor lib epilog process aborted [no buffer]"); 14340b966c5eSopenharmony_ci } 14350b966c5eSopenharmony_ci } 14360b966c5eSopenharmony_ci} 14370b966c5eSopenharmony_ci#endif // (HW_END_WITH_HCI_RESET == TRUE) 14380b966c5eSopenharmony_ci 14390b966c5eSopenharmony_civoid hw_process_event(HC_BT_HDR *p_buf) 14400b966c5eSopenharmony_ci{ 14410b966c5eSopenharmony_ci uint16_t opcode; 14420b966c5eSopenharmony_ci uint8_t *p = (uint8_t *)(p_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE; 14430b966c5eSopenharmony_ci STREAM_TO_UINT16(opcode, p); 14440b966c5eSopenharmony_ci 14450b966c5eSopenharmony_ci HILOGI("%s, opcode:0x%04x", __FUNCTION__, opcode); 14460b966c5eSopenharmony_ci switch (opcode) { 14470b966c5eSopenharmony_ci case HCI_VSC_WRITE_BD_ADDR: 14480b966c5eSopenharmony_ci#if (USE_CONTROLLER_BDADDR == TRUE) 14490b966c5eSopenharmony_ci case HCI_READ_LOCAL_BDADDR: 14500b966c5eSopenharmony_ci#endif 14510b966c5eSopenharmony_ci case HCI_READ_LOCAL_NAME: 14520b966c5eSopenharmony_ci case HCI_VSC_DOWNLOAD_MINIDRV: 14530b966c5eSopenharmony_ci case HCI_VSC_WRITE_FIRMWARE: 14540b966c5eSopenharmony_ci case HCI_VSC_LAUNCH_RAM: 14550b966c5eSopenharmony_ci case HCI_RESET: 14560b966c5eSopenharmony_ci case HCI_VSC_WRITE_UART_CLOCK_SETTING: 14570b966c5eSopenharmony_ci case HCI_VSC_UPDATE_BAUDRATE: 14580b966c5eSopenharmony_ci hw_config_cback(p_buf); 14590b966c5eSopenharmony_ci break; 14600b966c5eSopenharmony_ci 14610b966c5eSopenharmony_ci case HCI_VSC_WRITE_SCO_PCM_INT_PARAM: 14620b966c5eSopenharmony_ci case HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM: 14630b966c5eSopenharmony_ci case HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM: 14640b966c5eSopenharmony_ci hw_sco_i2spcm_cfg_cback(p_buf); 14650b966c5eSopenharmony_ci break; 14660b966c5eSopenharmony_ci 14670b966c5eSopenharmony_ci case HCI_VSC_WRITE_SLEEP_MODE: 14680b966c5eSopenharmony_ci hw_lpm_ctrl_cback(p_buf); 14690b966c5eSopenharmony_ci break; 14700b966c5eSopenharmony_ci 14710b966c5eSopenharmony_ci case HCI_VSC_ENABLE_WBS: 14720b966c5eSopenharmony_ci break; 14730b966c5eSopenharmony_ci } 14740b966c5eSopenharmony_ci 14750b966c5eSopenharmony_ci HILOGI("%s, Complete", __FUNCTION__); 14760b966c5eSopenharmony_ci} 1477