1/******************************************************************************
2 *
3 *  Copyright (C) 2009-2012 Broadcom Corporation
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at:
8 *
9 *  http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 ******************************************************************************/
18
19/******************************************************************************
20 *
21 *  Filename:      bt_vendor_brcm.c
22 *
23 *  Description:   Broadcom vendor specific library implementation
24 *
25 ******************************************************************************/
26
27#define LOG_TAG "bt_vendor"
28
29#include <utils/Log.h>
30#include <string.h>
31#include "upio.h"
32#include "userial_vendor.h"
33#include "bt_vendor_brcm.h"
34
35#ifndef BTVND_DBG
36#define BTVND_DBG FALSE
37#endif
38
39#if (BTVND_DBG == TRUE)
40#define BTVNDDBG(param, ...)        \
41    {                               \
42        HILOGD(param, ##__VA_ARGS__); \
43    }
44#else
45#define BTVNDDBG(param, ...)        \
46    {                               \
47        HILOGD(param, ##__VA_ARGS__); \
48    }
49#endif
50
51/******************************************************************************
52**  Externs
53******************************************************************************/
54
55void hw_config_start(void);
56uint8_t hw_lpm_enable(uint8_t turn_on);
57uint32_t hw_lpm_get_idle_timeout(void);
58void hw_lpm_set_wake_state(uint8_t wake_assert);
59#if (SCO_CFG_INCLUDED == TRUE)
60void hw_sco_config(void);
61#endif
62void vnd_load_conf(const char *p_path);
63#if (HW_END_WITH_HCI_RESET == TRUE)
64void hw_epilog_process(void);
65#endif
66
67/******************************************************************************
68**  Variables
69******************************************************************************/
70
71bt_vendor_callbacks_t *bt_vendor_cbacks = NULL;
72uint8_t vnd_local_bd_addr[BD_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
73
74/******************************************************************************
75**  Local type definitions
76******************************************************************************/
77
78/******************************************************************************
79**  Static Variables
80******************************************************************************/
81
82static const tUSERIAL_CFG userial_init_cfg = {
83    (USERIAL_DATABITS_8 | USERIAL_PARITY_NONE | USERIAL_STOPBITS_1),
84    USERIAL_BAUD_115200
85};
86
87/******************************************************************************
88**  Functions
89******************************************************************************/
90
91/*****************************************************************************
92**
93**   BLUETOOTH VENDOR INTERFACE LIBRARY FUNCTIONS
94**
95*****************************************************************************/
96/** LPM disable/enable request */
97typedef enum {
98    BT_VND_LPM_DISABLE,
99    BT_VND_LPM_ENABLE,
100} bt_vendor_lpm_mode_t;
101
102static int init(const bt_vendor_callbacks_t *p_cb, unsigned char *local_bdaddr)
103{
104    HILOGI("init, bdaddr:%02x%02x:%02x%02x:%02x%02x", local_bdaddr[0], local_bdaddr[1], local_bdaddr[2],
105        local_bdaddr[3], local_bdaddr[4], local_bdaddr[5]);
106
107    if (p_cb == NULL) {
108        HILOGE("init failed with no user callbacks!");
109        return -1;
110    }
111
112#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
113    HILOGW("*****************************************************************");
114    HILOGW("*****************************************************************");
115    HILOGW("** Warning - BT Vendor Lib is loaded in debug tuning mode!");
116    HILOGW("**");
117    HILOGW("** If this is not intentional, rebuild libbt-vendor.so ");
118    HILOGW("** with VENDOR_LIB_RUNTIME_TUNING_ENABLED=FALSE and ");
119    HILOGW("** check if any run-time tuning parameters needed to be");
120    HILOGW("** carried to the build-time configuration accordingly.");
121    HILOGW("*****************************************************************");
122    HILOGW("*****************************************************************");
123#endif
124
125    userial_vendor_init();
126    upio_init();
127
128    vnd_load_conf(VENDOR_LIB_CONF_FILE);
129
130    /* store reference to user callbacks */
131    bt_vendor_cbacks = (bt_vendor_callbacks_t *)p_cb;
132
133#if (BRCM_A2DP_OFFLOAD == TRUE)
134    brcm_vnd_a2dp_init(bt_vendor_cbacks);
135#endif
136
137    /* This is handed over from the stack */
138    return memcpy_s(vnd_local_bd_addr, BD_ADDR_LEN, local_bdaddr, BD_ADDR_LEN);
139}
140
141/** Requested operations */
142static int op(bt_opcode_t opcode, void *param)
143{
144    int retval = 0;
145
146    switch (opcode) {
147        case BT_OP_POWER_ON: // BT_VND_OP_POWER_CTRL
148            upio_set_bluetooth_power(UPIO_BT_POWER_OFF);
149            upio_set_bluetooth_power(UPIO_BT_POWER_ON);
150            break;
151
152        case BT_OP_POWER_OFF: // BT_VND_OP_POWER_CTRL
153            upio_set_bluetooth_power(UPIO_BT_POWER_OFF);
154            hw_lpm_set_wake_state(false);
155            break;
156
157        case BT_OP_HCI_CHANNEL_OPEN: { // BT_VND_OP_USERIAL_OPEN
158            int(*fd_array)[] = (int(*)[])param;
159            int fd;
160            fd = userial_vendor_open((tUSERIAL_CFG *)&userial_init_cfg);
161            if (fd != -1) {
162                for (int idx = 0; idx < HCI_MAX_CHANNEL; idx++)
163                    (*fd_array)[idx] = fd;
164
165                retval = 1;
166            }
167            /* retval contains numbers of open fd of HCI channels */
168            break;
169        }
170        case BT_OP_HCI_CHANNEL_CLOSE: // BT_VND_OP_USERIAL_CLOSE
171            userial_vendor_close();
172            break;
173
174        case BT_OP_INIT: // BT_VND_OP_FW_CFG
175            hw_config_start();
176            break;
177
178        case BT_OP_GET_LPM_TIMER: { // BT_VND_OP_GET_LPM_IDLE_TIMEOUT
179            uint32_t *timeout_ms = (uint32_t *)param;
180            *timeout_ms = hw_lpm_get_idle_timeout();
181            break;
182        }
183
184        case BT_OP_LPM_ENABLE:
185            retval = hw_lpm_enable(BT_VND_LPM_ENABLE);
186            break;
187
188        case BT_OP_LPM_DISABLE:
189            retval = hw_lpm_enable(BT_VND_LPM_DISABLE);
190            break;
191
192        case BT_OP_WAKEUP_LOCK:
193            hw_lpm_set_wake_state(TRUE);
194            break;
195        case BT_OP_WAKEUP_UNLOCK:
196            hw_lpm_set_wake_state(FALSE);
197            break;
198        case BT_OP_EVENT_CALLBACK:
199            hw_process_event((HC_BT_HDR *)param);
200            break;
201    }
202
203    return retval;
204}
205
206/** Closes the interface */
207static void cleanup(void)
208{
209    BTVNDDBG("cleanup");
210    upio_cleanup();
211    bt_vendor_cbacks = NULL;
212}
213
214// Entry point of DLib
215const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
216    sizeof(bt_vendor_interface_t),
217    init,
218    op,
219    cleanup};
220