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: hardware.c
22 *
23 * Description: Contains controller-specific functions, like
24 * firmware patch download
25 * low power mode operations
26 *
27 ******************************************************************************/
28
29 #define LOG_TAG "bt_hwcfg"
30
31 #include <utils/Log.h>
32 #include <sys/types.h>
33 #include <stdbool.h>
34 #include <sys/stat.h>
35 #include <signal.h>
36 #include <time.h>
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <dirent.h>
40 #include <ctype.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <stdio.h>
44 #include <unistd.h>
45 #include "bt_hci_bdroid.h"
46 #include "bt_vendor_brcm.h"
47 #include "esco_parameters.h"
48 #include "userial.h"
49 #include "userial_vendor.h"
50 #include "upio.h"
51
52 /******************************************************************************
53 ** Constants & Macros
54 ******************************************************************************/
55
56 #ifndef BTHW_DBG
57 #define BTHW_DBG FALSE
58 #endif
59
60 #if (BTHW_DBG == TRUE)
61 #define BTHWDBG(param, ...) \
62 { \
63 HILOGD(param, ##__VA_ARGS__); \
64 }
65 #else
66 #define BTHWDBG(param, ...) \
67 { \
68 HILOGD(param, ##__VA_ARGS__); \
69 }
70 #endif
71
72 #define FW_PATCHFILE_EXTENSION ".hcd"
73 #define FW_PATCHFILE_EXTENSION_LEN 4
74 #define FW_PATCHFILE_PATH_MAXLEN 248 /* Local_Name length of return of \
75 HCI_Read_Local_Name */
76
77 #define HCI_CMD_MAX_LEN 258
78
79 #define HCI_RESET 0x0C03
80 #define HCI_VSC_WRITE_UART_CLOCK_SETTING 0xFC45
81 #define HCI_VSC_UPDATE_BAUDRATE 0xFC18
82 #define HCI_READ_LOCAL_NAME 0x0C14
83 #define HCI_VSC_DOWNLOAD_MINIDRV 0xFC2E
84 #define HCI_VSC_WRITE_FIRMWARE 0xFC4C
85 #define HCI_VSC_WRITE_BD_ADDR 0xFC01
86 #define HCI_VSC_WRITE_SLEEP_MODE 0xFC27
87 #define HCI_VSC_WRITE_SCO_PCM_INT_PARAM 0xFC1C
88 #define HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM 0xFC1E
89 #define HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM 0xFC6D
90 #define HCI_VSC_ENABLE_WBS 0xFC7E
91 #define HCI_VSC_LAUNCH_RAM 0xFC4E
92 #define HCI_READ_LOCAL_BDADDR 0x1009
93
94 #define HCI_EVT_CMD_CMPL_STATUS_RET_BYTE 5
95 #define HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING 6
96 #define HCI_EVT_CMD_CMPL_LOCAL_BDADDR_ARRAY 6
97 #define HCI_EVT_CMD_CMPL_OPCODE 3
98 #define LPM_CMD_PARAM_SIZE 12
99 #define UPDATE_BAUDRATE_CMD_PARAM_SIZE 6
100 #define HCI_CMD_PREAMBLE_SIZE 3
101 #define HCD_REC_PAYLOAD_LEN_BYTE 2
102 #define LOCAL_NAME_BUFFER_LEN 32
103 #define LOCAL_BDADDR_PATH_BUFFER_LEN 256
104
105 #define STREAM_TO_UINT16(u16, p) \
106 do \
107 { \
108 u16 = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); \
109 (p) += 2; \
110 } while (0)
111 #define UINT8_TO_STREAM(p, u8) \
112 do \
113 { \
114 *(p)++ = (uint8_t)(u8); \
115 } while (0)
116 #define UINT16_TO_STREAM(p, u16) \
117 do \
118 { \
119 *(p)++ = (uint8_t)(u16); \
120 *(p)++ = (uint8_t)((u16) >> 8); \
121 } while (0)
122 #define UINT32_TO_STREAM(p, u32) \
123 do \
124 { \
125 *(p)++ = (uint8_t)(u32); \
126 *(p)++ = (uint8_t)((u32) >> 8); \
127 *(p)++ = (uint8_t)((u32) >> 16); \
128 *(p)++ = (uint8_t)((u32) >> 24); \
129 } while (0)
130
131 #define SCO_INTERFACE_PCM 0
132 #define SCO_INTERFACE_I2S 1
133
134 /* one byte is for enable/disable
135 next 2 bytes are for codec type */
136 #define SCO_CODEC_PARAM_SIZE 3
137
138 #define BT_VENDOR_CFG_TIMEDELAY_ 40
139 #define BT_VENDOR_LDM_DEFAULT_IDLE 300
140 /******************************************************************************
141 ** Local type definitions
142 ******************************************************************************/
143
144 /* Hardware Configuration State */
145 enum {
146 HW_CFG_START = 1,
147 HW_CFG_SET_UART_CLOCK,
148 HW_CFG_SET_UART_BAUD_1,
149 HW_CFG_READ_LOCAL_NAME,
150 HW_CFG_DL_MINIDRIVER,
151 HW_CFG_DL_FW_PATCH,
152 HW_CFG_SET_UART_BAUD_2,
153 HW_CFG_SET_BD_ADDR,
154 HW_CFG_READ_BD_ADDR
155 };
156
157 /* h/w config control block */
158 typedef struct {
159 uint8_t state; /* Hardware configuration state */
160 int fw_fd; /* FW patch file fd */
161 uint8_t f_set_baud_2; /* Baud rate switch state */
162 char local_chip_name[LOCAL_NAME_BUFFER_LEN];
163 } bt_hw_cfg_cb_t;
164
165 /* low power mode parameters */
166 typedef struct {
167 uint8_t sleep_mode; /* 0(disable),1(UART),9(H5) */
168 uint8_t host_stack_idle_threshold; /* Unit scale 300ms/25ms */
169 uint8_t host_controller_idle_threshold; /* Unit scale 300ms/25ms */
170 uint8_t bt_wake_polarity; /* 0=Active Low, 1= Active High */
171 uint8_t host_wake_polarity; /* 0=Active Low, 1= Active High */
172 uint8_t allow_host_sleep_during_sco;
173 uint8_t combine_sleep_mode_and_lpm;
174 uint8_t enable_uart_txd_tri_state; /* UART_TXD Tri-State */
175 uint8_t sleep_guard_time; /* sleep guard time in 12.5ms */
176 uint8_t wakeup_guard_time; /* wakeup guard time in 12.5ms */
177 uint8_t txd_config; /* TXD is high in sleep state */
178 uint8_t pulsed_host_wake; /* pulsed host wake if mode = 1 */
179 } bt_lpm_param_t;
180
181 /* Firmware re-launch settlement time */
182 typedef struct {
183 const char *chipset_name;
184 const uint32_t delay_time;
185 } fw_settlement_entry_t;
186
187 #if (FW_AUTO_DETECTION == TRUE)
188 /* AMPAK FW auto detection table */
189 typedef struct {
190 char *chip_id;
191 char *updated_chip_id;
192 } fw_auto_detection_entry_t;
193 #endif
194
195 /******************************************************************************
196 ** Externs
197 ******************************************************************************/
198
199 void hw_config_cback(void *p_mem);
200
201 /******************************************************************************
202 ** Static variables
203 ******************************************************************************/
204
205 static char fw_patchfile_path[256] = FW_PATCHFILE_LOCATION;
206 static char fw_patchfile_name[128] = {0};
207 #if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
208 static int fw_patch_settlement_delay = -1;
209 #endif
210
211 static int wbs_sample_rate = SCO_WBS_SAMPLE_RATE;
212 static bt_hw_cfg_cb_t hw_cfg_cb;
213
214 static bt_lpm_param_t lpm_param = {
215 LPM_SLEEP_MODE,
216 LPM_IDLE_THRESHOLD,
217 LPM_HC_IDLE_THRESHOLD,
218 LPM_BT_WAKE_POLARITY,
219 LPM_HOST_WAKE_POLARITY,
220 LPM_ALLOW_HOST_SLEEP_DURING_SCO,
221 LPM_COMBINE_SLEEP_MODE_AND_LPM,
222 LPM_ENABLE_UART_TXD_TRI_STATE,
223 0, /* not applicable */
224 0, /* not applicable */
225 0, /* not applicable */
226 LPM_PULSED_HOST_WAKE
227 };
228
229 /* need to update the bt_sco_i2spcm_param as well
230 bt_sco_i2spcm_param will be used for WBS setting
231 update the bt_sco_param and bt_sco_i2spcm_param */
232 static uint8_t bt_sco_param[SCO_PCM_PARAM_SIZE] = {
233 SCO_PCM_ROUTING,
234 SCO_PCM_IF_CLOCK_RATE,
235 SCO_PCM_IF_FRAME_TYPE,
236 SCO_PCM_IF_SYNC_MODE,
237 SCO_PCM_IF_CLOCK_MODE
238 };
239
240 static uint8_t bt_pcm_data_fmt_param[PCM_DATA_FORMAT_PARAM_SIZE] = {
241 PCM_DATA_FMT_SHIFT_MODE,
242 PCM_DATA_FMT_FILL_BITS,
243 PCM_DATA_FMT_FILL_METHOD,
244 PCM_DATA_FMT_FILL_NUM,
245 PCM_DATA_FMT_JUSTIFY_MODE
246 };
247
248 static uint8_t bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_SIZE] = {
249 SCO_I2SPCM_IF_MODE,
250 SCO_I2SPCM_IF_ROLE,
251 SCO_I2SPCM_IF_SAMPLE_RATE,
252 SCO_I2SPCM_IF_CLOCK_RATE
253 };
254
255 /*
256 * The look-up table of recommended firmware settlement delay (milliseconds) on
257 * known chipsets.
258 */
259 static const fw_settlement_entry_t fw_settlement_table[] = {
260 {"BCM43241", 200},
261 {"BCM43341", 100},
262 {(const char *)NULL, 200} // Giving the generic fw settlement delay setting.
263 };
264
265 /*
266 * NOTICE:
267 * If the platform plans to run I2S interface bus over I2S/PCM port of the
268 * BT Controller with the Host AP, explicitly set "SCO_USE_I2S_INTERFACE = TRUE"
269 * in the correspodning include/vnd_<target>.txt file.
270 * Otherwise, leave SCO_USE_I2S_INTERFACE undefined in the vnd_<target>.txt file.
271 * And, PCM interface will be set as the default bus format running over I2S/PCM
272 * port.
273 */
274 #if (defined(SCO_USE_I2S_INTERFACE) && SCO_USE_I2S_INTERFACE == TRUE)
275 static uint8_t sco_bus_interface = SCO_INTERFACE_I2S;
276 #else
277 static uint8_t sco_bus_interface = SCO_INTERFACE_PCM;
278 #endif
279
280 #define INVALID_SCO_CLOCK_RATE 0xFF
281 static uint8_t sco_bus_clock_rate = INVALID_SCO_CLOCK_RATE;
282 static uint8_t sco_bus_wbs_clock_rate = INVALID_SCO_CLOCK_RATE;
283
284 #if (FW_AUTO_DETECTION == TRUE)
285 #define FW_TABLE_VERSION "v1.1 20161117"
286 static const fw_auto_detection_entry_t fw_auto_detection_table[] = {
287 {"4343A0", "BCM43438A0"}, // AP6212
288 {"BCM43430A1", "BCM43438A1"}, // AP6212A
289 {"BCM20702A", "BCM20710A1"}, // AP6210B
290 {"BCM4335C0", "BCM4339A0"}, // AP6335
291 {"BCM4330B1", "BCM40183B2"}, // AP6330
292 {"BCM4324B3", "BCM43241B4"}, // AP62X2
293 {"BCM4350C0", "BCM4354A1"}, // AP6354
294 {"BCM4354A2", "BCM4356A2"}, // AP6356
295 {"BCM4345C0", "BCM4345C0"}, // AP6255
296 {"BCM4345C5", "BCM4345C5"}, // AP6256
297 {"BCM43430B0", "BCM4343B0"}, // AP6236
298 {"BCM4359C0", "BCM4359C0"}, // AP6359
299 {"BCM4349B1", "BCM4359B1"}, // AP6359
300 {NULL, NULL}
301 };
302 #endif
303
304 /******************************************************************************
305 ** Static functions
306 ******************************************************************************/
307 static void hw_sco_i2spcm_config(uint16_t codec);
308 static void hw_sco_i2spcm_config_from_command(void *p_mem, uint16_t codec);
309
310 /******************************************************************************
311 ** Controller Initialization Static Functions
312 ******************************************************************************/
313
314 /*******************************************************************************
315 **
316 ** Function look_up_fw_settlement_delay
317 **
318 ** Description If FW_PATCH_SETTLEMENT_DELAY_MS has not been explicitly
319 ** re-defined in the platform specific build-time configuration
320 ** file, we will search into the look-up table for a
321 ** recommended firmware settlement delay value.
322 **
323 ** Although the settlement time might be also related to board
324 ** configurations such as the crystal clocking speed.
325 **
326 ** Returns Firmware settlement delay
327 **
328 *******************************************************************************/
look_up_fw_settlement_delay(void)329 uint32_t look_up_fw_settlement_delay(void)
330 {
331 uint32_t ret_value;
332 fw_settlement_entry_t *p_entry;
333
334 if (FW_PATCH_SETTLEMENT_DELAY_MS > 0)
335 ret_value = FW_PATCH_SETTLEMENT_DELAY_MS;
336 #if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
337 else if (fw_patch_settlement_delay >= 0) {
338 ret_value = fw_patch_settlement_delay;
339 }
340 #endif
341 else {
342 p_entry = (fw_settlement_entry_t *)fw_settlement_table;
343
344 while (p_entry->chipset_name != NULL) {
345 if (strstr(hw_cfg_cb.local_chip_name, p_entry->chipset_name) != NULL) {
346 break;
347 }
348
349 p_entry++;
350 }
351
352 ret_value = p_entry->delay_time;
353 }
354
355 BTHWDBG("Settlement delay -- %d ms", ret_value);
356
357 return (ret_value);
358 }
359
360 /*******************************************************************************
361 **
362 ** Function ms_delay
363 **
364 ** Description sleep unconditionally for timeout milliseconds
365 **
366 ** Returns None
367 **
368 *******************************************************************************/
ms_delay(uint32_t timeout)369 void ms_delay(uint32_t timeout)
370 {
371 struct timespec delay;
372 int err;
373
374 if (timeout == 0)
375 return;
376
377 delay.tv_sec = timeout / BT_VENDOR_TIME_RAIDX;
378 delay.tv_nsec = BT_VENDOR_TIME_RAIDX * BT_VENDOR_TIME_RAIDX * (timeout % BT_VENDOR_TIME_RAIDX);
379
380 /* [u]sleep can't be used because it uses SIGALRM */
381 do {
382 err = nanosleep(&delay, &delay);
383 } while (err < 0 && errno == EINTR);
384 }
385
386 /*******************************************************************************
387 **
388 ** Function line_speed_to_userial_baud
389 **
390 ** Description helper function converts line speed number into USERIAL baud
391 ** rate symbol
392 **
393 ** Returns unit8_t (USERIAL baud symbol)
394 **
395 *******************************************************************************/
line_speed_to_userial_baud(uint32_t line_speed)396 uint8_t line_speed_to_userial_baud(uint32_t line_speed)
397 {
398 uint8_t baud;
399
400 if (line_speed == USERIAL_LINESPEED_4M)
401 baud = USERIAL_BAUD_4M;
402 else if (line_speed == USERIAL_LINESPEED_3M)
403 baud = USERIAL_BAUD_3M;
404 else if (line_speed == USERIAL_LINESPEED_2M)
405 baud = USERIAL_BAUD_2M;
406 else if (line_speed == USERIAL_LINESPEED_1_5M)
407 baud = USERIAL_BAUD_1_5M;
408 else if (line_speed == USERIAL_LINESPEED_1M)
409 baud = USERIAL_BAUD_1M;
410 else if (line_speed == USERIAL_LINESPEED_921600)
411 baud = USERIAL_BAUD_921600;
412 else if (line_speed == USERIAL_LINESPEED_460800)
413 baud = USERIAL_BAUD_460800;
414 else if (line_speed == USERIAL_LINESPEED_230400)
415 baud = USERIAL_BAUD_230400;
416 else if (line_speed == USERIAL_LINESPEED_115200)
417 baud = USERIAL_BAUD_115200;
418 else if (line_speed == USERIAL_LINESPEED_57600)
419 baud = USERIAL_BAUD_57600;
420 else if (line_speed == USERIAL_LINESPEED_19200)
421 baud = USERIAL_BAUD_19200;
422 else if (line_speed == USERIAL_LINESPEED_9600)
423 baud = USERIAL_BAUD_9600;
424 else if (line_speed == USERIAL_LINESPEED_1200)
425 baud = USERIAL_BAUD_1200;
426 else if (line_speed == USERIAL_LINESPEED_600)
427 baud = USERIAL_BAUD_600;
428 else {
429 HILOGE("userial vendor: unsupported baud speed %d", line_speed);
430 baud = USERIAL_BAUD_115200;
431 }
432
433 return baud;
434 }
435
436 /*******************************************************************************
437 **
438 ** Function hw_strncmp
439 **
440 ** Description Used to compare two strings in caseless
441 **
442 ** Returns 0: match, otherwise: not match
443 **
444 *******************************************************************************/
hw_strncmp(const char * p_str1,const char * p_str2,const int len)445 static int hw_strncmp(const char *p_str1, const char *p_str2, const int len)
446 {
447 int i;
448
449 if (!p_str1 || !p_str2) {
450 return (1);
451 }
452
453 for (i = 0; i < len; i++) {
454 if (toupper(p_str1[i]) != toupper(p_str2[i])) {
455 return (i + 1);
456 }
457 }
458
459 return 0;
460 }
461
462 /*******************************************************************************
463 **
464 ** Function hw_config_set_bdaddr
465 **
466 ** Description Program controller's Bluetooth Device Address
467 **
468 ** Returns xmit bytes
469 **
470 *******************************************************************************/
hw_config_set_bdaddr(HC_BT_HDR * p_buf)471 static ssize_t hw_config_set_bdaddr(HC_BT_HDR *p_buf)
472 {
473 uint8_t retval = FALSE;
474 uint8_t *p = (uint8_t *)(p_buf + 1);
475 int i = BD_ADDR_LEN;
476
477 UINT16_TO_STREAM(p, HCI_VSC_WRITE_BD_ADDR);
478 *p++ = BD_ADDR_LEN; /* parameter length */
479 *p++ = vnd_local_bd_addr[--i];
480 *p++ = vnd_local_bd_addr[--i];
481 *p++ = vnd_local_bd_addr[--i];
482 *p++ = vnd_local_bd_addr[--i];
483 *p++ = vnd_local_bd_addr[--i];
484 *p = vnd_local_bd_addr[--i];
485
486 p_buf->len = HCI_CMD_PREAMBLE_SIZE + BD_ADDR_LEN;
487 hw_cfg_cb.state = HW_CFG_SET_BD_ADDR;
488
489 retval = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_BD_ADDR, p_buf);
490
491 return (retval);
492 }
493
494 #if (USE_CONTROLLER_BDADDR == TRUE)
495 /*******************************************************************************
496 **
497 ** Function hw_config_read_bdaddr
498 **
499 ** Description Read controller's Bluetooth Device Address
500 **
501 ** Returns xmit bytes
502 **
503 *******************************************************************************/
hw_config_read_bdaddr(HC_BT_HDR * p_buf)504 static ssize_t hw_config_read_bdaddr(HC_BT_HDR *p_buf)
505 {
506 uint8_t retval = FALSE;
507 uint8_t *p = (uint8_t *)(p_buf + 1);
508
509 UINT16_TO_STREAM(p, HCI_READ_LOCAL_BDADDR);
510 *p = 0; /* parameter length */
511
512 p_buf->len = HCI_CMD_PREAMBLE_SIZE;
513 hw_cfg_cb.state = HW_CFG_READ_BD_ADDR;
514
515 retval = bt_vendor_cbacks->xmit_cb(HCI_READ_LOCAL_BDADDR, p_buf);
516
517 return (retval);
518 }
519 #endif // (USE_CONTROLLER_BDADDR == TRUE)
520
521 typedef void (*tTIMER_HANDLE_CBACK)(union sigval sigval_value);
522
OsAllocateTimer(tTIMER_HANDLE_CBACK timer_callback)523 static timer_t OsAllocateTimer(tTIMER_HANDLE_CBACK timer_callback)
524 {
525 struct sigevent sigev;
526 timer_t timerid;
527
528 (void)memset_s(&sigev, sizeof(struct sigevent), 0, sizeof(struct sigevent));
529 // Create the POSIX timer to generate signo
530 sigev.sigev_notify = SIGEV_THREAD;
531 sigev.sigev_notify_function = timer_callback;
532 sigev.sigev_value.sival_ptr = &timerid;
533
534 // Create the Timer using timer_create signal
535
536 if (timer_create(CLOCK_REALTIME, &sigev, &timerid) == 0) {
537 return timerid;
538 } else {
539 HILOGE("timer_create error!");
540 return (timer_t)-1;
541 }
542 }
543
OsFreeTimer(timer_t timerid)544 int OsFreeTimer(timer_t timerid)
545 {
546 int ret = 0;
547 ret = timer_delete(timerid);
548 if (ret != 0) {
549 HILOGE("timer_delete fail with errno(%d)", errno);
550 }
551
552 return ret;
553 }
554
OsStartTimer(timer_t timerid,int msec,int mode)555 static int OsStartTimer(timer_t timerid, int msec, int mode)
556 {
557 struct itimerspec itval;
558
559 itval.it_value.tv_sec = msec / BT_VENDOR_TIME_RAIDX;
560 itval.it_value.tv_nsec = (long)(msec % BT_VENDOR_TIME_RAIDX) * (BT_VENDOR_TIME_RAIDX * BT_VENDOR_TIME_RAIDX);
561
562 if (mode == 1) {
563 itval.it_interval.tv_sec = itval.it_value.tv_sec;
564 itval.it_interval.tv_nsec = itval.it_value.tv_nsec;
565 } else {
566 itval.it_interval.tv_sec = 0;
567 itval.it_interval.tv_nsec = 0;
568 }
569
570 // Set the Timer when to expire through timer_settime
571
572 if (timer_settime(timerid, 0, &itval, NULL) != 0) {
573 HILOGE("time_settime error!");
574 return -1;
575 }
576
577 return 0;
578 }
579
580 static timer_t localtimer = 0;
local_timer_handler(union sigval sigev_value)581 static void local_timer_handler(union sigval sigev_value)
582 {
583 bt_vendor_cbacks->init_cb(BTC_OP_RESULT_SUCCESS);
584 OsFreeTimer(localtimer);
585 }
start_fwcfg_cbtimer(void)586 static void start_fwcfg_cbtimer(void)
587 {
588 if (localtimer == 0) {
589 localtimer = OsAllocateTimer(local_timer_handler);
590 }
591 OsStartTimer(localtimer, BT_VENDOR_CFG_TIMEDELAY_, 0);
592 }
593
594 void hw_sco_config(void);
595
596 /*******************************************************************************
597 **
598 ** Function hw_config_cback
599 **
600 ** Description Callback function for controller configuration
601 **
602 ** Returns None
603 **
604 *******************************************************************************/
hw_config_cback(void * p_mem)605 void hw_config_cback(void *p_mem)
606 {
607 HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem;
608 char *p_name, *p_tmp;
609 uint8_t *p, status;
610 uint16_t opcode;
611 HC_BT_HDR *p_buf = NULL;
612 ssize_t xmit_bytes = 0;
613 int i;
614 int delay = 100;
615 #if (USE_CONTROLLER_BDADDR == TRUE)
616 const uint8_t null_bdaddr[BD_ADDR_LEN] = {0, 0, 0, 0, 0, 0};
617 #endif
618
619 status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
620 p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
621 STREAM_TO_UINT16(opcode, p);
622
623 /* Ask a new buffer big enough to hold any HCI commands sent in here */
624 if ((status == 0) && bt_vendor_cbacks)
625 p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + HCI_CMD_MAX_LEN);
626
627 if (p_buf != NULL) {
628 p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
629 p_buf->offset = 0;
630 p_buf->len = 0;
631 p_buf->layer_specific = 0;
632
633 p = (uint8_t *)(p_buf + 1);
634 switch (hw_cfg_cb.state) {
635 case HW_CFG_SET_UART_BAUD_1:
636 /* update baud rate of host's UART port */
637 HILOGI("bt vendor lib: set UART baud %i", UART_TARGET_BAUD_RATE);
638 userial_vendor_set_baud(line_speed_to_userial_baud(UART_TARGET_BAUD_RATE));
639 #if 0
640 /* read local name */
641 UINT16_TO_STREAM(p, HCI_READ_LOCAL_NAME);
642 *p = 0; /* parameter length */
643
644 p_buf->len = HCI_CMD_PREAMBLE_SIZE;
645 hw_cfg_cb.state = HW_CFG_READ_LOCAL_NAME;
646
647 xmit_bytes = bt_vendor_cbacks->xmit_cb(HCI_READ_LOCAL_NAME, p_buf);
648 break;
649 #endif
650 case HW_CFG_READ_LOCAL_NAME:
651 #if 0
652 p_tmp = p_name = (char *)(p_evt_buf + 1) +
653 HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING;
654
655 for (i = 0; (i < LOCAL_NAME_BUFFER_LEN) || (*(p_name + i) != 0); i++)
656 *(p_name + i) = toupper(*(p_name + i));
657
658 if ((p_name = strstr(p_name, "BCM")) != NULL) {
659 strncpy(hw_cfg_cb.local_chip_name, p_name,
660 LOCAL_NAME_BUFFER_LEN - 1);
661 #ifdef USE_BLUETOOTH_BCM4343
662 } else if ((p_name = strstr(p_tmp, "4343")) != NULL) {
663 snprintf(hw_cfg_cb.local_chip_name,
664 LOCAL_NAME_BUFFER_LEN - 1, "BCM%s", p_name);
665 strncpy(p_name, hw_cfg_cb.local_chip_name,
666 LOCAL_NAME_BUFFER_LEN - 1);
667 }
668 #endif
669 else {
670 strncpy(hw_cfg_cb.local_chip_name, "UNKNOWN",
671 LOCAL_NAME_BUFFER_LEN - 1);
672 p_name = p_tmp;
673 }
674
675 hw_cfg_cb.local_chip_name[LOCAL_NAME_BUFFER_LEN - 1] = 0;
676
677 BTHWDBG("Chipset %s", hw_cfg_cb.local_chip_name);
678 #endif
679 {
680 // /vendor/etc/firmware
681 p_name = FW_PATCHFILE_LOCATION "BCM4362A2.hcd";
682 if ((hw_cfg_cb.fw_fd = open(p_name, O_RDONLY)) == -1) {
683 HILOGE("vendor lib preload failed to open [%s]", p_name);
684 } else {
685 /* vsc_download_minidriver */
686 UINT16_TO_STREAM(p, HCI_VSC_DOWNLOAD_MINIDRV);
687 *p = 0; /* parameter length */
688
689 p_buf->len = HCI_CMD_PREAMBLE_SIZE;
690 hw_cfg_cb.state = HW_CFG_DL_MINIDRIVER;
691
692 xmit_bytes = bt_vendor_cbacks->xmit_cb(HCI_VSC_DOWNLOAD_MINIDRV, p_buf);
693 }
694 }
695
696 if (xmit_bytes <= 0) {
697 HILOGE("vendor lib preload failed to locate firmware patch file and set bdaddr");
698 xmit_bytes = hw_config_set_bdaddr(p_buf);
699 }
700 break;
701
702 case HW_CFG_DL_MINIDRIVER:
703 /* give time for placing firmware in download mode */
704 ms_delay(50);
705 hw_cfg_cb.state = HW_CFG_DL_FW_PATCH;
706 /* fall through intentionally */
707 case HW_CFG_DL_FW_PATCH:
708 // HILOGD("HW_CFG_DL_FW_PATCH, opcode:0x%02x", opcode);
709 p_buf->len = read(hw_cfg_cb.fw_fd, p, HCI_CMD_PREAMBLE_SIZE);
710 if (p_buf->len > 0) {
711 if ((p_buf->len < HCI_CMD_PREAMBLE_SIZE) ||
712 (opcode == HCI_VSC_LAUNCH_RAM)) {
713 HILOGW("firmware patch file might be altered!");
714 } else {
715 p_buf->len += read(hw_cfg_cb.fw_fd,
716 p + HCI_CMD_PREAMBLE_SIZE,
717 *(p + HCD_REC_PAYLOAD_LEN_BYTE));
718 STREAM_TO_UINT16(opcode, p);
719 xmit_bytes = bt_vendor_cbacks->xmit_cb(opcode, p_buf);
720 break;
721 }
722 }
723
724 close(hw_cfg_cb.fw_fd);
725 hw_cfg_cb.fw_fd = -1;
726
727 /* Normally the firmware patch configuration file
728 * sets the new starting baud rate at 115200.
729 * So, we need update host's baud rate accordingly.
730 */
731 HILOGI("bt vendor lib: set UART baud 115200");
732 userial_vendor_set_baud(USERIAL_BAUD_115200);
733
734 /* Next, we would like to boost baud rate up again
735 * to desired working speed.
736 */
737 hw_cfg_cb.f_set_baud_2 = TRUE;
738
739 /* Check if we need to pause a few hundred milliseconds
740 * before sending down any HCI command.
741 */
742 delay = look_up_fw_settlement_delay();
743 HILOGI("Setting fw settlement delay to %d ", delay);
744 ms_delay(delay);
745
746 p_buf->len = HCI_CMD_PREAMBLE_SIZE;
747 UINT16_TO_STREAM(p, HCI_RESET);
748 *p = 0; /* parameter length */
749 hw_cfg_cb.state = HW_CFG_START;
750 xmit_bytes = bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf);
751 break;
752
753 case HW_CFG_START:
754 if (UART_TARGET_BAUD_RATE > 3000000) { /* 3000000 */
755 /* set UART clock to 48MHz */
756 UINT16_TO_STREAM(p, HCI_VSC_WRITE_UART_CLOCK_SETTING);
757 *p++ = 1; /* parameter length */
758 *p = 1; /* (1,"UART CLOCK 48 MHz")(2,"UART CLOCK 24 MHz") */
759
760 p_buf->len = HCI_CMD_PREAMBLE_SIZE + 1;
761 hw_cfg_cb.state = HW_CFG_SET_UART_CLOCK;
762
763 xmit_bytes = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_UART_CLOCK_SETTING, p_buf);
764 break;
765 }
766 /* fall through intentionally */
767 case HW_CFG_SET_UART_CLOCK:
768 /* set controller's UART baud rate to 3M */
769 UINT16_TO_STREAM(p, HCI_VSC_UPDATE_BAUDRATE);
770 *p++ = UPDATE_BAUDRATE_CMD_PARAM_SIZE; /* parameter length */
771 *p++ = 0; /* encoded baud rate */
772 *p++ = 0; /* use encoded form */
773 UINT32_TO_STREAM(p, UART_TARGET_BAUD_RATE);
774
775 p_buf->len = HCI_CMD_PREAMBLE_SIZE +
776 UPDATE_BAUDRATE_CMD_PARAM_SIZE;
777 hw_cfg_cb.state = (hw_cfg_cb.f_set_baud_2) ? HW_CFG_SET_UART_BAUD_2 : HW_CFG_SET_UART_BAUD_1;
778
779 xmit_bytes = bt_vendor_cbacks->xmit_cb(HCI_VSC_UPDATE_BAUDRATE, p_buf);
780 break;
781
782 case HW_CFG_SET_UART_BAUD_2:
783 /* update baud rate of host's UART port */
784 HILOGI("bt vendor lib: set UART baud %i", UART_TARGET_BAUD_RATE);
785 userial_vendor_set_baud(
786 line_speed_to_userial_baud(UART_TARGET_BAUD_RATE));
787
788 #if (USE_CONTROLLER_BDADDR == TRUE)
789 if ((xmit_bytes = hw_config_read_bdaddr(p_buf)) > 0)
790 break;
791 #else
792 if ((xmit_bytes = hw_config_set_bdaddr(p_buf)) > 0)
793 break;
794 #endif
795 /* fall through intentionally */
796 case HW_CFG_SET_BD_ADDR:
797 HILOGI("vendor lib fwcfg completed");
798 // bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
799 hw_sco_config();
800 start_fwcfg_cbtimer();
801
802 hw_cfg_cb.state = 0;
803
804 if (hw_cfg_cb.fw_fd != -1) {
805 close(hw_cfg_cb.fw_fd);
806 hw_cfg_cb.fw_fd = -1;
807 }
808
809 xmit_bytes = 1;
810 break;
811
812 #if (USE_CONTROLLER_BDADDR == TRUE)
813 case HW_CFG_READ_BD_ADDR:
814 p_tmp = (char *)(p_evt_buf + 1) +
815 HCI_EVT_CMD_CMPL_LOCAL_BDADDR_ARRAY;
816 HILOGI("entering HW_CFG_READ_BD_ADDR");
817 if (memcmp(p_tmp, null_bdaddr, BD_ADDR_LEN) == 0) {
818 HILOGI("entering HW_CFG_READ_BD_ADDR");
819 // Controller does not have a valid OTP BDADDR!
820 // Set the BTIF initial BDADDR instead.
821 if ((xmit_bytes = hw_config_set_bdaddr(p_buf)) > 0)
822 break;
823 } else {
824 HILOGI("Controller OTP bdaddr %02X:%02X:%02X:%02X:%02X:%02X",
825 *(p_tmp + 5), *(p_tmp + 4), *(p_tmp + 3),
826 *(p_tmp + 2), *(p_tmp + 1), *p_tmp);
827 }
828
829 HILOGI("vendor lib fwcfg completed2");
830 // bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
831 hw_sco_config();
832 start_fwcfg_cbtimer();
833
834 hw_cfg_cb.state = 0;
835
836 if (hw_cfg_cb.fw_fd != -1) {
837 close(hw_cfg_cb.fw_fd);
838 hw_cfg_cb.fw_fd = -1;
839 }
840
841 xmit_bytes = 1;
842 break;
843 #endif // (USE_CONTROLLER_BDADDR == TRUE)
844 } // switch(hw_cfg_cb.state)
845
846 bt_vendor_cbacks->dealloc(p_buf);
847 } // if (p_buf != NULL)
848
849 /* Free the RX event buffer */
850 // if (bt_vendor_cbacks)
851 // bt_vendor_cbacks->dealloc(p_evt_buf);
852
853 if (xmit_bytes <= 0) {
854 HILOGE("vendor lib fwcfg aborted!!!");
855 if (bt_vendor_cbacks) {
856 bt_vendor_cbacks->init_cb(BTC_OP_RESULT_FAIL);
857 }
858
859 if (hw_cfg_cb.fw_fd != -1) {
860 close(hw_cfg_cb.fw_fd);
861 hw_cfg_cb.fw_fd = -1;
862 }
863
864 hw_cfg_cb.state = 0;
865 }
866 }
867
868 /******************************************************************************
869 ** LPM Static Functions
870 ******************************************************************************/
871
872 /*******************************************************************************
873 **
874 ** Function hw_lpm_ctrl_cback
875 **
876 ** Description Callback function for lpm enable/disable request
877 **
878 ** Returns None
879 **
880 *******************************************************************************/
hw_lpm_ctrl_cback(void * p_mem)881 void hw_lpm_ctrl_cback(void *p_mem)
882 {
883 HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem;
884 bt_op_result_t status = BTC_OP_RESULT_FAIL;
885
886 if (*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0) {
887 status = BTC_OP_RESULT_SUCCESS;
888 }
889
890 if (bt_vendor_cbacks) {
891 // bt_vendor_cbacks->dealloc(p_evt_buf);
892 }
893 }
894
895 #if (SCO_CFG_INCLUDED == TRUE)
896 /*****************************************************************************
897 ** SCO Configuration Static Functions
898 *****************************************************************************/
899
hw_sco_i2spcm_proc_interface_param(void)900 static void hw_sco_i2spcm_proc_interface_param(void)
901 {
902 bt_op_result_t status = BTC_OP_RESULT_FAIL;
903 uint8_t ret = FALSE;
904 uint8_t *p;
905 HC_BT_HDR *p_buf = NULL;
906
907 /* Ask a new buffer to hold WRITE_SCO_PCM_INT_PARAM command */
908 if (bt_vendor_cbacks) {
909 p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE
910 + HCI_CMD_PREAMBLE_SIZE + SCO_PCM_PARAM_SIZE);
911 }
912 if (p_buf) {
913 p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
914 p_buf->offset = 0;
915 p_buf->layer_specific = 0;
916 p_buf->len = HCI_CMD_PREAMBLE_SIZE + SCO_PCM_PARAM_SIZE;
917 p = (uint8_t *)(p_buf + 1);
918
919 /* do we need this VSC for I2S??? */
920 UINT16_TO_STREAM(p, HCI_VSC_WRITE_SCO_PCM_INT_PARAM);
921 *p++ = SCO_PCM_PARAM_SIZE;
922 memcpy_s(p, &bt_sco_param, SCO_PCM_PARAM_SIZE);
923 ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_SCO_PCM_INT_PARAM, p_buf);
924 bt_vendor_cbacks->dealloc(p_buf);
925 if (ret) {
926 return;
927 }
928 }
929 status = BTC_OP_RESULT_FAIL;
930
931 HILOGI("sco I2S/PCM config interface result %d [0-Success, 1-Fail]", status);
932 }
933
hw_sco_i2spcm_proc_int_param(void)934 static void hw_sco_i2spcm_proc_int_param(void)
935 {
936 bt_op_result_t status = BTC_OP_RESULT_FAIL;
937 uint8_t ret = FALSE;
938 uint8_t *p;
939 HC_BT_HDR *p_buf = NULL;
940
941 /* Ask a new buffer to hold WRITE_PCM_DATA_FORMAT_PARAM command */
942 if (bt_vendor_cbacks)
943 p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(
944 BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + PCM_DATA_FORMAT_PARAM_SIZE);
945 if (p_buf) {
946 p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
947 p_buf->offset = 0;
948 p_buf->layer_specific = 0;
949 p_buf->len = HCI_CMD_PREAMBLE_SIZE + PCM_DATA_FORMAT_PARAM_SIZE;
950
951 p = (uint8_t *)(p_buf + 1);
952 UINT16_TO_STREAM(p, HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM);
953 *p++ = PCM_DATA_FORMAT_PARAM_SIZE;
954 memcpy_s(p, &bt_pcm_data_fmt_param, PCM_DATA_FORMAT_PARAM_SIZE);
955
956 ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM, p_buf);
957 bt_vendor_cbacks->dealloc(p_buf);
958 if (ret) {
959 return;
960 }
961 }
962 status = BTC_OP_RESULT_FAIL;
963
964 HILOGI("sco I2S/PCM config int result %d [0-Success, 1-Fail]", status);
965 }
966
967 /*******************************************************************************
968 **
969 ** Function hw_sco_i2spcm_cfg_cback
970 **
971 ** Description Callback function for SCO I2S/PCM configuration request
972 **
973 ** Returns None
974 **
975 *******************************************************************************/
hw_sco_i2spcm_cfg_cback(void * p_mem)976 static void hw_sco_i2spcm_cfg_cback(void *p_mem)
977 {
978 HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem;
979 uint8_t *p;
980 uint16_t opcode;
981 HC_BT_HDR *p_buf = NULL;
982 bt_op_result_t status = BTC_OP_RESULT_FAIL;
983
984 p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
985 STREAM_TO_UINT16(opcode, p);
986
987 if (*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0) {
988 status = BTC_OP_RESULT_SUCCESS;
989 }
990
991 /* Free the RX event buffer */
992 if (bt_vendor_cbacks) {
993 // bt_vendor_cbacks->dealloc(p_evt_buf);
994 }
995
996 if (status != BTC_OP_RESULT_SUCCESS) {
997 return;
998 }
999
1000 if ((opcode == HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM) &&
1001 (sco_bus_interface == SCO_INTERFACE_PCM)) {
1002 hw_sco_i2spcm_proc_interface_param();
1003 } else if ((opcode == HCI_VSC_WRITE_SCO_PCM_INT_PARAM) &&
1004 (sco_bus_interface == SCO_INTERFACE_PCM)) {
1005 hw_sco_i2spcm_proc_int_param();
1006 }
1007 }
1008
1009 /*******************************************************************************
1010 **
1011 ** Function hw_set_MSBC_codec_cback
1012 **
1013 ** Description Callback function for setting WBS codec
1014 **
1015 ** Returns None
1016 **
1017 *******************************************************************************/
hw_set_MSBC_codec_cback(void * p_mem)1018 static void hw_set_MSBC_codec_cback(void *p_mem)
1019 {
1020 /* whenever update the codec enable/disable, need to update I2SPCM */
1021 HILOGI("SCO I2S interface change the sample rate to 16K");
1022 hw_sco_i2spcm_config_from_command(p_mem, SCO_CODEC_MSBC);
1023 }
1024
1025 /*******************************************************************************
1026 **
1027 ** Function hw_set_CVSD_codec_cback
1028 **
1029 ** Description Callback function for setting NBS codec
1030 **
1031 ** Returns None
1032 **
1033 *******************************************************************************/
hw_set_CVSD_codec_cback(void * p_mem)1034 static void hw_set_CVSD_codec_cback(void *p_mem)
1035 {
1036 /* whenever update the codec enable/disable, need to update I2SPCM */
1037 HILOGI("SCO I2S interface change the sample rate to 8K");
1038 hw_sco_i2spcm_config_from_command(p_mem, SCO_CODEC_CVSD);
1039 }
1040
1041 #endif // SCO_CFG_INCLUDED
1042
1043 /*****************************************************************************
1044 ** Hardware Configuration Interface Functions
1045 *****************************************************************************/
1046
1047 /*******************************************************************************
1048 **
1049 ** Function hw_config_start
1050 **
1051 ** Description Kick off controller initialization process
1052 **
1053 ** Returns None
1054 **
1055 *******************************************************************************/
hw_config_start(void)1056 void hw_config_start(void)
1057 {
1058 HC_BT_HDR *p_buf = NULL;
1059 uint8_t *p;
1060
1061 hw_cfg_cb.state = 0;
1062 hw_cfg_cb.fw_fd = -1;
1063 hw_cfg_cb.f_set_baud_2 = FALSE;
1064
1065 // bt_vendor_cbacks->init_cb(BTC_OP_RESULT_SUCCESS);
1066 // Start from sending HCI_RESET
1067
1068 if (bt_vendor_cbacks) {
1069 p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE +
1070 HCI_CMD_PREAMBLE_SIZE);
1071 }
1072
1073 if (p_buf) {
1074 p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1075 p_buf->offset = 0;
1076 p_buf->layer_specific = 0;
1077 p_buf->len = HCI_CMD_PREAMBLE_SIZE;
1078
1079 p = (uint8_t *)(p_buf + 1);
1080 UINT16_TO_STREAM(p, HCI_RESET);
1081 *p = 0;
1082
1083 hw_cfg_cb.state = HW_CFG_START;
1084 bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf);
1085 bt_vendor_cbacks->dealloc(p_buf);
1086 } else {
1087 if (bt_vendor_cbacks) {
1088 HILOGE("vendor lib fw conf aborted [no buffer]");
1089 bt_vendor_cbacks->init_cb(BTC_OP_RESULT_FAIL);
1090 }
1091 }
1092 }
1093
1094 /*******************************************************************************
1095 **
1096 ** Function hw_lpm_enable
1097 **
1098 ** Description Enalbe/Disable LPM
1099 **
1100 ** Returns TRUE/FALSE
1101 **
1102 *******************************************************************************/
hw_lpm_enable(uint8_t turn_on)1103 uint8_t hw_lpm_enable(uint8_t turn_on)
1104 {
1105 HILOGD("entering hw_lpm_enable11");
1106 HC_BT_HDR *p_buf = NULL;
1107 uint8_t *p;
1108 uint8_t ret = FALSE;
1109
1110 if (bt_vendor_cbacks)
1111 p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE +
1112 HCI_CMD_PREAMBLE_SIZE +
1113 LPM_CMD_PARAM_SIZE);
1114
1115 if (p_buf) {
1116 p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1117 p_buf->offset = 0;
1118 p_buf->layer_specific = 0;
1119 p_buf->len = HCI_CMD_PREAMBLE_SIZE + LPM_CMD_PARAM_SIZE;
1120
1121 p = (uint8_t *)(p_buf + 1);
1122 UINT16_TO_STREAM(p, HCI_VSC_WRITE_SLEEP_MODE);
1123 *p++ = LPM_CMD_PARAM_SIZE; /* parameter length */
1124
1125 if (turn_on) {
1126 memcpy(p, &lpm_param, LPM_CMD_PARAM_SIZE);
1127 upio_set(UPIO_LPM_MODE, UPIO_ASSERT, 0);
1128 } else {
1129 memset(p, 0, LPM_CMD_PARAM_SIZE);
1130 upio_set(UPIO_LPM_MODE, UPIO_DEASSERT, 0);
1131 }
1132
1133 ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_SLEEP_MODE, p_buf);
1134 bt_vendor_cbacks->dealloc(p_buf);
1135 }
1136
1137 if ((ret <= 0) && bt_vendor_cbacks) {
1138 // bt_vendor_cbacks->lpm_cb(BT_VND_OP_RESULT_FAIL);
1139 }
1140 HILOGD("hw_lpm_enable ret:%d", ret);
1141 return ret;
1142 }
1143
1144 /*******************************************************************************
1145 **
1146 ** Function hw_lpm_get_idle_timeout
1147 **
1148 ** Description Calculate idle time based on host stack idle threshold
1149 **
1150 ** Returns idle timeout value
1151 **
1152 *******************************************************************************/
hw_lpm_get_idle_timeout(void)1153 uint32_t hw_lpm_get_idle_timeout(void)
1154 {
1155 uint32_t timeout_ms;
1156
1157 /* set idle time to be LPM_IDLE_TIMEOUT_MULTIPLE times of
1158 * host stack idle threshold (in 300ms/25ms)
1159 */
1160 timeout_ms = (uint32_t)lpm_param.host_stack_idle_threshold * LPM_IDLE_TIMEOUT_MULTIPLE;
1161 timeout_ms *= BT_VENDOR_LDM_DEFAULT_IDLE;
1162 return timeout_ms;
1163 }
1164
1165 /*******************************************************************************
1166 **
1167 ** Function hw_lpm_set_wake_state
1168 **
1169 ** Description Assert/Deassert BT_WAKE
1170 **
1171 ** Returns None
1172 **
1173 *******************************************************************************/
hw_lpm_set_wake_state(uint8_t wake_assert)1174 void hw_lpm_set_wake_state(uint8_t wake_assert)
1175 {
1176 uint8_t state = (wake_assert) ? UPIO_ASSERT : UPIO_DEASSERT;
1177
1178 upio_set(UPIO_BT_WAKE, state, lpm_param.bt_wake_polarity);
1179 }
1180
1181 #if (SCO_CFG_INCLUDED == TRUE)
1182 /*******************************************************************************
1183 **
1184 ** Function hw_sco_config
1185 **
1186 ** Description Configure SCO related hardware settings
1187 **
1188 ** Returns None
1189 **
1190 *******************************************************************************/
hw_sco_config(void)1191 void hw_sco_config(void)
1192 {
1193 if (sco_bus_interface == SCO_INTERFACE_I2S) {
1194 /* 'Enable' I2S mode */
1195 bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_MODE] = 1;
1196
1197 /* set nbs clock rate as the value in SCO_I2SPCM_IF_CLOCK_RATE field */
1198 sco_bus_clock_rate = bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_CLOCK_RATE];
1199 } else {
1200 /* 'Disable' I2S mode */
1201 bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_MODE] = 0;
1202
1203 /* set nbs clock rate as the value in SCO_PCM_IF_CLOCK_RATE field */
1204 sco_bus_clock_rate = bt_sco_param[SCO_PCM_PARAM_IF_CLOCK_RATE];
1205
1206 /* sync up clock mode setting */
1207 bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_MODE] = bt_sco_param[SCO_PCM_PARAM_IF_CLOCK_MODE];
1208 }
1209
1210 if (sco_bus_wbs_clock_rate == INVALID_SCO_CLOCK_RATE) {
1211 /* set default wbs clock rate */
1212 sco_bus_wbs_clock_rate = SCO_I2SPCM_IF_CLOCK_RATE4WBS;
1213
1214 if (sco_bus_wbs_clock_rate < sco_bus_clock_rate)
1215 sco_bus_wbs_clock_rate = sco_bus_clock_rate;
1216 }
1217
1218 /*
1219 * To support I2S/PCM port multiplexing signals for sharing Bluetooth audio
1220 * and FM on the same PCM pins, we defer Bluetooth audio (SCO/eSCO)
1221 * configuration till SCO/eSCO is being established;
1222 * i.e. in hw_set_audio_state() call.
1223 * When configured as I2S only, Bluetooth audio configuration is executed
1224 * immediately with SCO_CODEC_CVSD by default.
1225 */
1226
1227 if (sco_bus_interface == SCO_INTERFACE_I2S) {
1228 hw_sco_i2spcm_config(SCO_CODEC_CVSD);
1229 } else {
1230 hw_sco_i2spcm_config(SCO_CODEC_NONE);
1231 }
1232
1233 if (bt_vendor_cbacks) {
1234 // bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_SUCCESS);
1235 }
1236 }
1237
hw_sco_i2spcm_config_from_command(void * p_mem,uint16_t codec)1238 static void hw_sco_i2spcm_config_from_command(void *p_mem, uint16_t codec)
1239 {
1240 HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem;
1241 bool command_success = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0;
1242
1243 /* Free the RX event buffer */
1244 if (bt_vendor_cbacks) {
1245 // bt_vendor_cbacks->dealloc(p_evt_buf);
1246 }
1247
1248 if (command_success) {
1249 hw_sco_i2spcm_config(codec);
1250 } else if (bt_vendor_cbacks) {
1251 // bt_vendor_cbacks->audio_state_cb(BT_VND_OP_RESULT_FAIL);
1252 }
1253 }
1254
1255 /*******************************************************************************
1256 **
1257 ** Function hw_sco_i2spcm_config
1258 **
1259 ** Description Configure SCO over I2S or PCM
1260 **
1261 ** Returns None
1262 **
1263 *******************************************************************************/
hw_sco_i2spcm_config(uint16_t codec)1264 static void hw_sco_i2spcm_config(uint16_t codec)
1265 {
1266 HC_BT_HDR *p_buf = NULL;
1267 uint8_t *p, ret;
1268 uint16_t cmd_u16 = HCI_CMD_PREAMBLE_SIZE + SCO_I2SPCM_PARAM_SIZE;
1269
1270 if (bt_vendor_cbacks) {
1271 p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + cmd_u16);
1272 }
1273
1274 if (p_buf) {
1275 p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1276 p_buf->offset = 0;
1277 p_buf->layer_specific = 0;
1278 p_buf->len = cmd_u16;
1279
1280 p = (uint8_t *)(p_buf + 1);
1281
1282 UINT16_TO_STREAM(p, HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM);
1283 *p++ = SCO_I2SPCM_PARAM_SIZE;
1284 if (codec == SCO_CODEC_CVSD) {
1285 bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_SAMPLE_RATE] = 0; /* SCO_I2SPCM_IF_SAMPLE_RATE 8k */
1286 bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_CLOCK_RATE] =
1287 bt_sco_param[SCO_PCM_PARAM_IF_CLOCK_RATE] = sco_bus_clock_rate;
1288 } else if (codec == SCO_CODEC_MSBC) {
1289 bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_SAMPLE_RATE] = wbs_sample_rate; /* SCO_I2SPCM_IF_SAMPLE_RATE 16K */
1290 bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_CLOCK_RATE] =
1291 bt_sco_param[SCO_PCM_PARAM_IF_CLOCK_RATE] = sco_bus_wbs_clock_rate;
1292 } else {
1293 bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_SAMPLE_RATE] = 0; /* SCO_I2SPCM_IF_SAMPLE_RATE 8k */
1294 bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_CLOCK_RATE] =
1295 bt_sco_param[SCO_PCM_PARAM_IF_CLOCK_RATE] = sco_bus_clock_rate;
1296 HILOGE("wrong codec is use in hw_sco_i2spcm_config, goes default NBS");
1297 }
1298 memcpy_s(p, &bt_sco_i2spcm_param, SCO_I2SPCM_PARAM_SIZE);
1299 cmd_u16 = HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM;
1300 HILOGI("I2SPCM config {0x%x, 0x%x, 0x%x, 0x%x}",
1301 bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_MODE], bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_ROLE],
1302 bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_SAMPLE_RATE],
1303 bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_CLOCK_RATE]);
1304
1305 bt_vendor_cbacks->xmit_cb(cmd_u16, p_buf);
1306 bt_vendor_cbacks->dealloc(p_buf);
1307 }
1308 // bt_vendor_cbacks->audio_state_cb(BT_VND_OP_RESULT_FAIL);
1309 }
1310
1311 /*******************************************************************************
1312 **
1313 ** Function hw_set_SCO_codec
1314 **
1315 ** Description This functgion sends command to the controller to setup
1316 ** WBS/NBS codec for the upcoming eSCO connection.
1317 **
1318 ** Returns -1 : Failed to send VSC
1319 ** 0 : Success
1320 **
1321 *******************************************************************************/
hw_set_SCO_codec(uint16_t codec)1322 static int hw_set_SCO_codec(uint16_t codec)
1323 {
1324 HC_BT_HDR *p_buf = NULL;
1325 uint8_t *p;
1326 uint8_t ret;
1327 int ret_val = 0;
1328 return ret_val;
1329 }
1330
1331 /*******************************************************************************
1332 **
1333 ** Function hw_set_audio_state
1334 **
1335 ** Description This function configures audio base on provided audio state
1336 **
1337 ** Paramters pointer to audio state structure
1338 **
1339 ** Returns 0: ok, -1: error
1340 **
1341 *******************************************************************************/
hw_set_audio_state(bt_vendor_op_audio_state_t * p_state)1342 int hw_set_audio_state(bt_vendor_op_audio_state_t *p_state)
1343 {
1344 int ret_val = -1;
1345
1346 if (!bt_vendor_cbacks) {
1347 return ret_val;
1348 }
1349
1350 ret_val = hw_set_SCO_codec(p_state->peer_codec);
1351 return ret_val;
1352 }
1353 #endif
1354 /*******************************************************************************
1355 **
1356 ** Function hw_set_patch_file_path
1357 **
1358 ** Description Set the location of firmware patch file
1359 **
1360 ** Returns 0 : Success
1361 ** Otherwise : Fail
1362 **
1363 *******************************************************************************/
hw_set_patch_file_path(char * p_conf_name,char * p_conf_value,int param)1364 int hw_set_patch_file_path(char *p_conf_name, char *p_conf_value, int param)
1365 {
1366 if (strcpy_s(fw_patchfile_path, sizeof(fw_patchfile_path), p_conf_value) != 0) {
1367 return -1;
1368 }
1369 return 0;
1370 }
1371
1372 /*******************************************************************************
1373 **
1374 ** Function hw_set_patch_file_name
1375 **
1376 ** Description Give the specific firmware patch filename
1377 **
1378 ** Returns 0 : Success
1379 ** Otherwise : Fail
1380 **
1381 *******************************************************************************/
hw_set_patch_file_name(char * p_conf_name,char * p_conf_value,int param)1382 int hw_set_patch_file_name(char *p_conf_name, char *p_conf_value, int param)
1383 {
1384 if (strcpy_s(fw_patchfile_name, sizeof(fw_patchfile_name), p_conf_value) != 0) {
1385 return -1;
1386 }
1387 return 0;
1388 }
1389
1390 #if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
1391 /*******************************************************************************
1392 **
1393 ** Function hw_set_patch_settlement_delay
1394 **
1395 ** Description Give the specific firmware patch settlement time in milliseconds
1396 **
1397 ** Returns 0 : Success
1398 ** Otherwise : Fail
1399 **
1400 *******************************************************************************/
hw_set_patch_settlement_delay(char * p_conf_name,char * p_conf_value,int param)1401 int hw_set_patch_settlement_delay(char *p_conf_name, char *p_conf_value, int param)
1402 {
1403 fw_patch_settlement_delay = atoi(p_conf_value);
1404 return 0;
1405 }
1406 #endif // VENDOR_LIB_RUNTIME_TUNING_ENABLED
1407
1408 /*****************************************************************************
1409 ** Sample Codes Section
1410 *****************************************************************************/
1411
1412 #if (HW_END_WITH_HCI_RESET == TRUE)
1413 /*******************************************************************************
1414 **
1415 ** Function hw_epilog_cback
1416 **
1417 ** Description Callback function for Command Complete Events from HCI
1418 ** commands sent in epilog process.
1419 **
1420 ** Returns None
1421 **
1422 *******************************************************************************/
hw_epilog_cback(void * p_mem)1423 void hw_epilog_cback(void *p_mem)
1424 {
1425 HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem;
1426 uint8_t *p, status;
1427 uint16_t opcode;
1428
1429 status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
1430 p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
1431 STREAM_TO_UINT16(opcode, p);
1432
1433 BTHWDBG("%s Opcode:0x%04X Status: %d", __FUNCTION__, opcode, status);
1434
1435 if (bt_vendor_cbacks) {
1436 /* Must free the RX event buffer */
1437 // bt_vendor_cbacks->dealloc(p_evt_buf);
1438 /* Once epilog process is done, must call epilog_cb callback
1439 to notify caller */
1440 // bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
1441 }
1442 }
1443
1444 /*******************************************************************************
1445 **
1446 ** Function hw_epilog_process
1447 **
1448 ** Description Sample implementation of epilog process
1449 **
1450 ** Returns None
1451 **
1452 *******************************************************************************/
hw_epilog_process(void)1453 void hw_epilog_process(void)
1454 {
1455 HC_BT_HDR *p_buf = NULL;
1456 uint8_t *p;
1457
1458 BTHWDBG("hw_epilog_process");
1459
1460 /* Sending a HCI_RESET */
1461 if (bt_vendor_cbacks) {
1462 /* Must allocate command buffer via HC's alloc API */
1463 p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE +
1464 HCI_CMD_PREAMBLE_SIZE);
1465 }
1466
1467 if (p_buf) {
1468 p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1469 p_buf->offset = 0;
1470 p_buf->layer_specific = 0;
1471 p_buf->len = HCI_CMD_PREAMBLE_SIZE;
1472
1473 p = (uint8_t *)(p_buf + 1);
1474 UINT16_TO_STREAM(p, HCI_RESET);
1475 *p = 0; /* parameter length */
1476
1477 /* Send command via HC's xmit_cb API */
1478 bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf);
1479 bt_vendor_cbacks->dealloc(p_buf);
1480 } else {
1481 if (bt_vendor_cbacks) {
1482 HILOGE("vendor lib epilog process aborted [no buffer]");
1483 }
1484 }
1485 }
1486 #endif // (HW_END_WITH_HCI_RESET == TRUE)
1487
hw_process_event(HC_BT_HDR * p_buf)1488 void hw_process_event(HC_BT_HDR *p_buf)
1489 {
1490 uint16_t opcode;
1491 uint8_t *p = (uint8_t *)(p_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
1492 STREAM_TO_UINT16(opcode, p);
1493
1494 HILOGI("%s, opcode:0x%04x", __FUNCTION__, opcode);
1495 switch (opcode) {
1496 case HCI_VSC_WRITE_BD_ADDR:
1497 #if (USE_CONTROLLER_BDADDR == TRUE)
1498 case HCI_READ_LOCAL_BDADDR:
1499 #endif
1500 case HCI_READ_LOCAL_NAME:
1501 case HCI_VSC_DOWNLOAD_MINIDRV:
1502 case HCI_VSC_WRITE_FIRMWARE:
1503 case HCI_VSC_LAUNCH_RAM:
1504 case HCI_RESET:
1505 case HCI_VSC_WRITE_UART_CLOCK_SETTING:
1506 case HCI_VSC_UPDATE_BAUDRATE:
1507 hw_config_cback(p_buf);
1508 break;
1509
1510 case HCI_VSC_WRITE_SCO_PCM_INT_PARAM:
1511 case HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM:
1512 case HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM:
1513 hw_sco_i2spcm_cfg_cback(p_buf);
1514 break;
1515
1516 case HCI_VSC_WRITE_SLEEP_MODE:
1517 hw_lpm_ctrl_cback(p_buf);
1518 break;
1519
1520 case HCI_VSC_ENABLE_WBS:
1521 break;
1522 }
1523
1524 HILOGI("%s, Complete", __FUNCTION__);
1525 }
1526