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