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