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:      bt_vendor_brcm.c
220b966c5eSopenharmony_ci *
230b966c5eSopenharmony_ci *  Description:   Broadcom vendor specific library implementation
240b966c5eSopenharmony_ci *
250b966c5eSopenharmony_ci ******************************************************************************/
260b966c5eSopenharmony_ci
270b966c5eSopenharmony_ci#define LOG_TAG "bt_vendor"
280b966c5eSopenharmony_ci
290b966c5eSopenharmony_ci#include <utils/Log.h>
300b966c5eSopenharmony_ci#include <string.h>
310b966c5eSopenharmony_ci#include "upio.h"
320b966c5eSopenharmony_ci#include "userial_vendor.h"
330b966c5eSopenharmony_ci#include "bt_vendor_brcm.h"
340b966c5eSopenharmony_ci
350b966c5eSopenharmony_ci#ifndef BTVND_DBG
360b966c5eSopenharmony_ci#define BTVND_DBG FALSE
370b966c5eSopenharmony_ci#endif
380b966c5eSopenharmony_ci
390b966c5eSopenharmony_ci#if (BTVND_DBG == TRUE)
400b966c5eSopenharmony_ci#define BTVNDDBG(param, ...)        \
410b966c5eSopenharmony_ci    {                               \
420b966c5eSopenharmony_ci        HILOGD(param, ##__VA_ARGS__); \
430b966c5eSopenharmony_ci    }
440b966c5eSopenharmony_ci#else
450b966c5eSopenharmony_ci#define BTVNDDBG(param, ...)        \
460b966c5eSopenharmony_ci    {                               \
470b966c5eSopenharmony_ci        HILOGD(param, ##__VA_ARGS__); \
480b966c5eSopenharmony_ci    }
490b966c5eSopenharmony_ci#endif
500b966c5eSopenharmony_ci
510b966c5eSopenharmony_ci/******************************************************************************
520b966c5eSopenharmony_ci**  Externs
530b966c5eSopenharmony_ci******************************************************************************/
540b966c5eSopenharmony_ci
550b966c5eSopenharmony_civoid hw_config_start(void);
560b966c5eSopenharmony_ciuint8_t hw_lpm_enable(uint8_t turn_on);
570b966c5eSopenharmony_ciuint32_t hw_lpm_get_idle_timeout(void);
580b966c5eSopenharmony_civoid hw_lpm_set_wake_state(uint8_t wake_assert);
590b966c5eSopenharmony_ci#if (SCO_CFG_INCLUDED == TRUE)
600b966c5eSopenharmony_civoid hw_sco_config(void);
610b966c5eSopenharmony_ci#endif
620b966c5eSopenharmony_civoid vnd_load_conf(const char *p_path);
630b966c5eSopenharmony_ci#if (HW_END_WITH_HCI_RESET == TRUE)
640b966c5eSopenharmony_civoid hw_epilog_process(void);
650b966c5eSopenharmony_ci#endif
660b966c5eSopenharmony_ci
670b966c5eSopenharmony_ci/******************************************************************************
680b966c5eSopenharmony_ci**  Variables
690b966c5eSopenharmony_ci******************************************************************************/
700b966c5eSopenharmony_ci
710b966c5eSopenharmony_cibt_vendor_callbacks_t *bt_vendor_cbacks = NULL;
720b966c5eSopenharmony_ciuint8_t vnd_local_bd_addr[BD_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
730b966c5eSopenharmony_ci
740b966c5eSopenharmony_ci/******************************************************************************
750b966c5eSopenharmony_ci**  Local type definitions
760b966c5eSopenharmony_ci******************************************************************************/
770b966c5eSopenharmony_ci
780b966c5eSopenharmony_ci/******************************************************************************
790b966c5eSopenharmony_ci**  Static Variables
800b966c5eSopenharmony_ci******************************************************************************/
810b966c5eSopenharmony_ci
820b966c5eSopenharmony_cistatic const tUSERIAL_CFG userial_init_cfg = {
830b966c5eSopenharmony_ci    (USERIAL_DATABITS_8 | USERIAL_PARITY_NONE | USERIAL_STOPBITS_1),
840b966c5eSopenharmony_ci    USERIAL_BAUD_115200
850b966c5eSopenharmony_ci};
860b966c5eSopenharmony_ci
870b966c5eSopenharmony_ci/******************************************************************************
880b966c5eSopenharmony_ci**  Functions
890b966c5eSopenharmony_ci******************************************************************************/
900b966c5eSopenharmony_ci
910b966c5eSopenharmony_ci/*****************************************************************************
920b966c5eSopenharmony_ci**
930b966c5eSopenharmony_ci**   BLUETOOTH VENDOR INTERFACE LIBRARY FUNCTIONS
940b966c5eSopenharmony_ci**
950b966c5eSopenharmony_ci*****************************************************************************/
960b966c5eSopenharmony_ci/** LPM disable/enable request */
970b966c5eSopenharmony_citypedef enum {
980b966c5eSopenharmony_ci    BT_VND_LPM_DISABLE,
990b966c5eSopenharmony_ci    BT_VND_LPM_ENABLE,
1000b966c5eSopenharmony_ci} bt_vendor_lpm_mode_t;
1010b966c5eSopenharmony_ci
1020b966c5eSopenharmony_cistatic int init(const bt_vendor_callbacks_t *p_cb, unsigned char *local_bdaddr)
1030b966c5eSopenharmony_ci{
1040b966c5eSopenharmony_ci    HILOGI("init, bdaddr:%02x%02x:%02x%02x:%02x%02x", local_bdaddr[0], local_bdaddr[1], local_bdaddr[2],
1050b966c5eSopenharmony_ci        local_bdaddr[3], local_bdaddr[4], local_bdaddr[5]);
1060b966c5eSopenharmony_ci
1070b966c5eSopenharmony_ci    if (p_cb == NULL) {
1080b966c5eSopenharmony_ci        HILOGE("init failed with no user callbacks!");
1090b966c5eSopenharmony_ci        return -1;
1100b966c5eSopenharmony_ci    }
1110b966c5eSopenharmony_ci
1120b966c5eSopenharmony_ci#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
1130b966c5eSopenharmony_ci    HILOGW("*****************************************************************");
1140b966c5eSopenharmony_ci    HILOGW("*****************************************************************");
1150b966c5eSopenharmony_ci    HILOGW("** Warning - BT Vendor Lib is loaded in debug tuning mode!");
1160b966c5eSopenharmony_ci    HILOGW("**");
1170b966c5eSopenharmony_ci    HILOGW("** If this is not intentional, rebuild libbt-vendor.so ");
1180b966c5eSopenharmony_ci    HILOGW("** with VENDOR_LIB_RUNTIME_TUNING_ENABLED=FALSE and ");
1190b966c5eSopenharmony_ci    HILOGW("** check if any run-time tuning parameters needed to be");
1200b966c5eSopenharmony_ci    HILOGW("** carried to the build-time configuration accordingly.");
1210b966c5eSopenharmony_ci    HILOGW("*****************************************************************");
1220b966c5eSopenharmony_ci    HILOGW("*****************************************************************");
1230b966c5eSopenharmony_ci#endif
1240b966c5eSopenharmony_ci
1250b966c5eSopenharmony_ci    userial_vendor_init();
1260b966c5eSopenharmony_ci    upio_init();
1270b966c5eSopenharmony_ci
1280b966c5eSopenharmony_ci    vnd_load_conf(VENDOR_LIB_CONF_FILE);
1290b966c5eSopenharmony_ci
1300b966c5eSopenharmony_ci    /* store reference to user callbacks */
1310b966c5eSopenharmony_ci    bt_vendor_cbacks = (bt_vendor_callbacks_t *)p_cb;
1320b966c5eSopenharmony_ci
1330b966c5eSopenharmony_ci#if (BRCM_A2DP_OFFLOAD == TRUE)
1340b966c5eSopenharmony_ci    brcm_vnd_a2dp_init(bt_vendor_cbacks);
1350b966c5eSopenharmony_ci#endif
1360b966c5eSopenharmony_ci
1370b966c5eSopenharmony_ci    /* This is handed over from the stack */
1380b966c5eSopenharmony_ci    return memcpy_s(vnd_local_bd_addr, BD_ADDR_LEN, local_bdaddr, BD_ADDR_LEN);
1390b966c5eSopenharmony_ci}
1400b966c5eSopenharmony_ci
1410b966c5eSopenharmony_ci/** Requested operations */
1420b966c5eSopenharmony_cistatic int op(bt_opcode_t opcode, void *param)
1430b966c5eSopenharmony_ci{
1440b966c5eSopenharmony_ci    int retval = 0;
1450b966c5eSopenharmony_ci
1460b966c5eSopenharmony_ci    switch (opcode) {
1470b966c5eSopenharmony_ci        case BT_OP_POWER_ON: // BT_VND_OP_POWER_CTRL
1480b966c5eSopenharmony_ci            upio_set_bluetooth_power(UPIO_BT_POWER_OFF);
1490b966c5eSopenharmony_ci            upio_set_bluetooth_power(UPIO_BT_POWER_ON);
1500b966c5eSopenharmony_ci            break;
1510b966c5eSopenharmony_ci
1520b966c5eSopenharmony_ci        case BT_OP_POWER_OFF: // BT_VND_OP_POWER_CTRL
1530b966c5eSopenharmony_ci            upio_set_bluetooth_power(UPIO_BT_POWER_OFF);
1540b966c5eSopenharmony_ci            hw_lpm_set_wake_state(false);
1550b966c5eSopenharmony_ci            break;
1560b966c5eSopenharmony_ci
1570b966c5eSopenharmony_ci        case BT_OP_HCI_CHANNEL_OPEN: { // BT_VND_OP_USERIAL_OPEN
1580b966c5eSopenharmony_ci            int(*fd_array)[] = (int(*)[])param;
1590b966c5eSopenharmony_ci            int fd, idx;
1600b966c5eSopenharmony_ci            fd = userial_vendor_open((tUSERIAL_CFG *)&userial_init_cfg);
1610b966c5eSopenharmony_ci            if (fd != -1) {
1620b966c5eSopenharmony_ci                for (idx = 0; idx < HCI_MAX_CHANNEL; idx++)
1630b966c5eSopenharmony_ci                    (*fd_array)[idx] = fd;
1640b966c5eSopenharmony_ci
1650b966c5eSopenharmony_ci                retval = 1;
1660b966c5eSopenharmony_ci            }
1670b966c5eSopenharmony_ci            /* retval contains numbers of open fd of HCI channels */
1680b966c5eSopenharmony_ci            break;
1690b966c5eSopenharmony_ci        }
1700b966c5eSopenharmony_ci        case BT_OP_HCI_CHANNEL_CLOSE: // BT_VND_OP_USERIAL_CLOSE
1710b966c5eSopenharmony_ci            userial_vendor_close();
1720b966c5eSopenharmony_ci            break;
1730b966c5eSopenharmony_ci
1740b966c5eSopenharmony_ci        case BT_OP_INIT: // BT_VND_OP_FW_CFG
1750b966c5eSopenharmony_ci            hw_config_start();
1760b966c5eSopenharmony_ci            break;
1770b966c5eSopenharmony_ci
1780b966c5eSopenharmony_ci        case BT_OP_GET_LPM_TIMER: { // BT_VND_OP_GET_LPM_IDLE_TIMEOUT
1790b966c5eSopenharmony_ci            uint32_t *timeout_ms = (uint32_t *)param;
1800b966c5eSopenharmony_ci            *timeout_ms = hw_lpm_get_idle_timeout();
1810b966c5eSopenharmony_ci            break;
1820b966c5eSopenharmony_ci        }
1830b966c5eSopenharmony_ci
1840b966c5eSopenharmony_ci        case BT_OP_LPM_ENABLE:
1850b966c5eSopenharmony_ci            retval = hw_lpm_enable(BT_VND_LPM_ENABLE);
1860b966c5eSopenharmony_ci            break;
1870b966c5eSopenharmony_ci
1880b966c5eSopenharmony_ci        case BT_OP_LPM_DISABLE:
1890b966c5eSopenharmony_ci            retval = hw_lpm_enable(BT_VND_LPM_DISABLE);
1900b966c5eSopenharmony_ci            break;
1910b966c5eSopenharmony_ci
1920b966c5eSopenharmony_ci        case BT_OP_WAKEUP_LOCK:
1930b966c5eSopenharmony_ci            hw_lpm_set_wake_state(TRUE);
1940b966c5eSopenharmony_ci            break;
1950b966c5eSopenharmony_ci        case BT_OP_WAKEUP_UNLOCK:
1960b966c5eSopenharmony_ci            hw_lpm_set_wake_state(FALSE);
1970b966c5eSopenharmony_ci            break;
1980b966c5eSopenharmony_ci        case BT_OP_EVENT_CALLBACK:
1990b966c5eSopenharmony_ci            hw_process_event((HC_BT_HDR *)param);
2000b966c5eSopenharmony_ci            break;
2010b966c5eSopenharmony_ci    }
2020b966c5eSopenharmony_ci
2030b966c5eSopenharmony_ci    return retval;
2040b966c5eSopenharmony_ci}
2050b966c5eSopenharmony_ci
2060b966c5eSopenharmony_ci/** Closes the interface */
2070b966c5eSopenharmony_cistatic void cleanup(void)
2080b966c5eSopenharmony_ci{
2090b966c5eSopenharmony_ci    BTVNDDBG("cleanup");
2100b966c5eSopenharmony_ci    upio_cleanup();
2110b966c5eSopenharmony_ci    bt_vendor_cbacks = NULL;
2120b966c5eSopenharmony_ci}
2130b966c5eSopenharmony_ci
2140b966c5eSopenharmony_ci// Entry point of DLib
2150b966c5eSopenharmony_ciconst bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
2160b966c5eSopenharmony_ci    sizeof(bt_vendor_interface_t),
2170b966c5eSopenharmony_ci    init,
2180b966c5eSopenharmony_ci    op,
2190b966c5eSopenharmony_ci    cleanup};
220