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 "bt_vendor_brcm.h"
32 #include "upio.h"
33 #include "userial_vendor.h"
34 
35 #ifndef BTVND_DBG
36 #define BTVND_DBG FALSE
37 #endif
38 
39 #if (BTVND_DBG == TRUE)
40 #define BTVNDDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
41 #else
42 #define BTVNDDBG(param, ...) {}
43 #endif
44 
45 /******************************************************************************
46 **  Externs
47 ******************************************************************************/
48 
49 void hw_config_start(void);
50 uint8_t hw_lpm_enable(uint8_t turn_on);
51 uint32_t hw_lpm_get_idle_timeout(void);
52 void hw_lpm_set_wake_state(uint8_t wake_assert);
53 #if (SCO_CFG_INCLUDED == TRUE)
54 void hw_sco_config(void);
55 #endif
56 void vnd_load_conf(const char *p_path);
57 #if (HW_END_WITH_HCI_RESET == TRUE)
58 void hw_epilog_process(void);
59 #endif
60 
61 #if (BRCM_A2DP_OFFLOAD == TRUE)
62 void brcm_vnd_a2dp_init(bt_vendor_callbacks_t *callback);
63 int brcm_vnd_a2dp_execute(bt_vendor_opcode_t, void *ev_data);
64 #endif
65 
66 /******************************************************************************
67 **  Variables
68 ******************************************************************************/
69 
70 bt_vendor_callbacks_t *bt_vendor_cbacks = NULL;
71 uint8_t vnd_local_bd_addr[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
72 
73 /******************************************************************************
74 **  Local type definitions
75 ******************************************************************************/
76 
77 /******************************************************************************
78 **  Static Variables
79 ******************************************************************************/
80 
81 static const tUSERIAL_CFG userial_init_cfg =
82 {
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 
init(const bt_vendor_callbacks_t * p_cb,unsigned char * local_bdaddr)97 static int init(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr)
98 {
99     ALOGI("init");
100 
101     if (p_cb == NULL)
102     {
103         ALOGE("init failed with no user callbacks!");
104         return -1;
105     }
106 
107 #if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
108     ALOGW("*****************************************************************");
109     ALOGW("*****************************************************************");
110     ALOGW("** Warning - BT Vendor Lib is loaded in debug tuning mode!");
111     ALOGW("**");
112     ALOGW("** If this is not intentional, rebuild libbt-vendor.so ");
113     ALOGW("** with VENDOR_LIB_RUNTIME_TUNING_ENABLED=FALSE and ");
114     ALOGW("** check if any run-time tuning parameters needed to be");
115     ALOGW("** carried to the build-time configuration accordingly.");
116     ALOGW("*****************************************************************");
117     ALOGW("*****************************************************************");
118 #endif
119 
120     userial_vendor_init();
121     upio_init();
122 
123     vnd_load_conf(VENDOR_LIB_CONF_FILE);
124 
125     /* store reference to user callbacks */
126     bt_vendor_cbacks = (bt_vendor_callbacks_t *) p_cb;
127 
128     /* This is handed over from the stack */
129     memcpy(vnd_local_bd_addr, local_bdaddr, 6);
130 
131 #if (BRCM_A2DP_OFFLOAD == TRUE)
132     brcm_vnd_a2dp_init(bt_vendor_cbacks);
133 #endif
134 
135     return 0;
136 }
137 
138 
139 /** Requested operations */
op(bt_vendor_opcode_t opcode,void * param)140 static int op(bt_vendor_opcode_t opcode, void *param)
141 {
142     int retval = 0;
143 
144     BTVNDDBG("op for %d", opcode);
145 
146     switch(opcode)
147     {
148         case BT_VND_OP_POWER_CTRL:
149             {
150                 int *state = (int *) param;
151                 upio_set_bluetooth_power(UPIO_BT_POWER_OFF);
152                 if (*state == BT_VND_PWR_ON)
153                 {
154                     ALOGW("NOTE: BT_VND_PWR_ON now forces power-off first");
155                     upio_set_bluetooth_power(UPIO_BT_POWER_ON);
156                 } else {
157                     /* Make sure wakelock is released */
158                     hw_lpm_set_wake_state(false);
159                 }
160             }
161             break;
162 
163         case BT_VND_OP_FW_CFG:
164             {
165                 hw_config_start();
166             }
167             break;
168 
169         case BT_VND_OP_SCO_CFG:
170             {
171 #if (SCO_CFG_INCLUDED == TRUE)
172                 hw_sco_config();
173 #else
174                 retval = -1;
175 #endif
176             }
177             break;
178 
179         case BT_VND_OP_USERIAL_OPEN:
180             {
181                 int (*fd_array)[] = (int (*)[]) param;
182                 int fd, idx;
183                 fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg);
184                 if (fd != -1)
185                 {
186                     for (idx=0; idx < CH_MAX; idx++)
187                         (*fd_array)[idx] = fd;
188 
189                     retval = 1;
190                 }
191                 /* retval contains numbers of open fd of HCI channels */
192             }
193             break;
194 
195         case BT_VND_OP_USERIAL_CLOSE:
196             {
197                 userial_vendor_close();
198             }
199             break;
200 
201         case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:
202             {
203                 uint32_t *timeout_ms = (uint32_t *) param;
204                 *timeout_ms = hw_lpm_get_idle_timeout();
205             }
206             break;
207 
208         case BT_VND_OP_LPM_SET_MODE:
209             {
210                 uint8_t *mode = (uint8_t *) param;
211                 retval = hw_lpm_enable(*mode);
212             }
213             break;
214 
215         case BT_VND_OP_LPM_WAKE_SET_STATE:
216             {
217                 uint8_t *state = (uint8_t *) param;
218                 uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \
219                                         TRUE : FALSE;
220 
221                 hw_lpm_set_wake_state(wake_assert);
222             }
223             break;
224 
225          case BT_VND_OP_SET_AUDIO_STATE:
226             {
227                 retval = hw_set_audio_state((bt_vendor_op_audio_state_t *)param);
228             }
229             break;
230 
231         case BT_VND_OP_EPILOG:
232             {
233 #if (HW_END_WITH_HCI_RESET == FALSE)
234                 if (bt_vendor_cbacks)
235                 {
236                     bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
237                 }
238 #else
239                 hw_epilog_process();
240 #endif
241             }
242             break;
243 #if (BRCM_A2DP_OFFLOAD == TRUE)
244         case BT_VND_OP_A2DP_OFFLOAD_START:
245         case BT_VND_OP_A2DP_OFFLOAD_STOP:
246             retval = brcm_vnd_a2dp_execute(opcode, param);
247             break;
248 #endif
249     }
250 
251     return retval;
252 }
253 
254 /** Closes the interface */
cleanup(void)255 static void cleanup( void )
256 {
257     BTVNDDBG("cleanup");
258 
259     upio_cleanup();
260 
261     bt_vendor_cbacks = NULL;
262 }
263 
264 // Entry point of DLib
265 const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
266     sizeof(bt_vendor_interface_t),
267     init,
268     op,
269     cleanup
270 };
271