• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "BCM4343A1.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->dealloc(p_buf);
799                 // bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
800                 hw_sco_config();
801                 start_fwcfg_cbtimer();
802 
803                 hw_cfg_cb.state = 0;
804 
805                 if (hw_cfg_cb.fw_fd != -1) {
806                     close(hw_cfg_cb.fw_fd);
807                     hw_cfg_cb.fw_fd = -1;
808                 }
809 
810                 xmit_bytes = 1;
811                 break;
812 
813 #if (USE_CONTROLLER_BDADDR == TRUE)
814             case HW_CFG_READ_BD_ADDR:
815                 p_tmp = (char *)(p_evt_buf + 1) +
816                         HCI_EVT_CMD_CMPL_LOCAL_BDADDR_ARRAY;
817                 HILOGI("entering HW_CFG_READ_BD_ADDR");
818                 if (memcmp(p_tmp, null_bdaddr, BD_ADDR_LEN) == 0) {
819                     HILOGI("entering HW_CFG_READ_BD_ADDR");
820                     // Controller does not have a valid OTP BDADDR!
821                     // Set the BTIF initial BDADDR instead.
822                     if ((xmit_bytes = hw_config_set_bdaddr(p_buf)) > 0)
823                         break;
824                 } else {
825                     HILOGI("Controller OTP bdaddr %02X:%02X:%02X:%02X:%02X:%02X",
826                            *(p_tmp + 5), *(p_tmp + 4), *(p_tmp + 3),
827                            *(p_tmp + 2), *(p_tmp + 1), *p_tmp);
828                 }
829 
830                 HILOGI("vendor lib fwcfg completed");
831                 bt_vendor_cbacks->dealloc(p_buf);
832                 // bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
833                 hw_sco_config();
834                 start_fwcfg_cbtimer();
835 
836                 hw_cfg_cb.state = 0;
837 
838                 if (hw_cfg_cb.fw_fd != -1) {
839                     close(hw_cfg_cb.fw_fd);
840                     hw_cfg_cb.fw_fd = -1;
841                 }
842 
843                 xmit_bytes = 1;
844                 break;
845 #endif      // (USE_CONTROLLER_BDADDR == TRUE)
846         } // switch(hw_cfg_cb.state)
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             if (p_buf != NULL)
857                 bt_vendor_cbacks->dealloc(p_buf);
858 
859             bt_vendor_cbacks->init_cb(BTC_OP_RESULT_FAIL);
860         }
861 
862         if (hw_cfg_cb.fw_fd != -1) {
863             close(hw_cfg_cb.fw_fd);
864             hw_cfg_cb.fw_fd = -1;
865         }
866 
867         hw_cfg_cb.state = 0;
868     }
869 }
870 
871 /******************************************************************************
872 **   LPM Static Functions
873 ******************************************************************************/
874 
875 /*******************************************************************************
876 **
877 ** Function         hw_lpm_ctrl_cback
878 **
879 ** Description      Callback function for lpm enable/disable rquest
880 **
881 ** Returns          None
882 **
883 *******************************************************************************/
hw_lpm_ctrl_cback(void * p_mem)884 void hw_lpm_ctrl_cback(void *p_mem)
885 {
886     HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem;
887     bt_op_result_t status = BTC_OP_RESULT_FAIL;
888 
889     if (*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0) {
890         status = BTC_OP_RESULT_SUCCESS;
891     }
892 
893     if (bt_vendor_cbacks) {
894         // bt_vendor_cbacks->dealloc(p_evt_buf);
895     }
896 }
897 
898 #if (SCO_CFG_INCLUDED == TRUE)
899 /*****************************************************************************
900 **   SCO Configuration Static Functions
901 *****************************************************************************/
902 
hw_sco_i2spcm_proc_interface_param(void)903 static void hw_sco_i2spcm_proc_interface_param(void)
904 {
905     bt_op_result_t status = BTC_OP_RESULT_FAIL;
906     uint8_t ret = FALSE;
907     uint8_t *p;
908     HC_BT_HDR *p_buf = NULL;
909 
910     /* Ask a new buffer to hold WRITE_SCO_PCM_INT_PARAM command */
911     if (bt_vendor_cbacks) {
912         p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE
913             + HCI_CMD_PREAMBLE_SIZE + SCO_PCM_PARAM_SIZE);
914     }
915     if (p_buf) {
916         p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
917         p_buf->offset = 0;
918         p_buf->layer_specific = 0;
919         p_buf->len = HCI_CMD_PREAMBLE_SIZE + SCO_PCM_PARAM_SIZE;
920         p = (uint8_t *)(p_buf + 1);
921 
922         /* do we need this VSC for I2S??? */
923         UINT16_TO_STREAM(p, HCI_VSC_WRITE_SCO_PCM_INT_PARAM);
924         *p++ = SCO_PCM_PARAM_SIZE;
925         memcpy_s(p, &bt_sco_param, SCO_PCM_PARAM_SIZE);
926         if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_SCO_PCM_INT_PARAM, p_buf)) == FALSE) {
927             bt_vendor_cbacks->dealloc(p_buf);
928         } else
929             return;
930     }
931     status = BTC_OP_RESULT_FAIL;
932 
933     HILOGI("sco I2S/PCM config interface result %d [0-Success, 1-Fail]", status);
934 }
935 
hw_sco_i2spcm_proc_int_param(void)936 static void hw_sco_i2spcm_proc_int_param(void)
937 {
938     bt_op_result_t status = BTC_OP_RESULT_FAIL;
939     uint8_t ret = FALSE;
940     uint8_t *p;
941     HC_BT_HDR *p_buf = NULL;
942 
943     /* Ask a new buffer to hold WRITE_PCM_DATA_FORMAT_PARAM command */
944     if (bt_vendor_cbacks)
945         p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(
946             BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + PCM_DATA_FORMAT_PARAM_SIZE);
947     if (p_buf) {
948         p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
949         p_buf->offset = 0;
950         p_buf->layer_specific = 0;
951         p_buf->len = HCI_CMD_PREAMBLE_SIZE + PCM_DATA_FORMAT_PARAM_SIZE;
952 
953         p = (uint8_t *)(p_buf + 1);
954         UINT16_TO_STREAM(p, HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM);
955         *p++ = PCM_DATA_FORMAT_PARAM_SIZE;
956         memcpy_s(p, &bt_pcm_data_fmt_param, PCM_DATA_FORMAT_PARAM_SIZE);
957 
958         if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM, p_buf)) == TRUE) {
959             return ;
960         }
961         bt_vendor_cbacks->dealloc(p_buf);
962     }
963     status = BTC_OP_RESULT_FAIL;
964 
965     HILOGI("sco I2S/PCM config int result %d [0-Success, 1-Fail]", status);
966 }
967 
968 /*******************************************************************************
969 **
970 ** Function         hw_sco_i2spcm_cfg_cback
971 **
972 ** Description      Callback function for SCO I2S/PCM configuration rquest
973 **
974 ** Returns          None
975 **
976 *******************************************************************************/
hw_sco_i2spcm_cfg_cback(void * p_mem)977 static void hw_sco_i2spcm_cfg_cback(void *p_mem)
978 {
979     HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem;
980     uint8_t *p;
981     uint16_t opcode;
982     HC_BT_HDR *p_buf = NULL;
983     bt_op_result_t status = BTC_OP_RESULT_FAIL;
984 
985     p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
986     STREAM_TO_UINT16(opcode, p);
987 
988     if (*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0) {
989         status = BTC_OP_RESULT_SUCCESS;
990     }
991 
992     /* Free the RX event buffer */
993     if (bt_vendor_cbacks) {
994         // bt_vendor_cbacks->dealloc(p_evt_buf);
995     }
996 
997     if (status != BTC_OP_RESULT_SUCCESS) {
998         return;
999     }
1000 
1001     if ((opcode == HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM) &&
1002         (sco_bus_interface == SCO_INTERFACE_PCM)) {
1003         hw_sco_i2spcm_proc_interface_param();
1004     } else if ((opcode == HCI_VSC_WRITE_SCO_PCM_INT_PARAM) &&
1005              (sco_bus_interface == SCO_INTERFACE_PCM)) {
1006         hw_sco_i2spcm_proc_int_param();
1007     }
1008 }
1009 
1010 /*******************************************************************************
1011 **
1012 ** Function         hw_set_MSBC_codec_cback
1013 **
1014 ** Description      Callback function for setting WBS codec
1015 **
1016 ** Returns          None
1017 **
1018 *******************************************************************************/
hw_set_MSBC_codec_cback(void * p_mem)1019 static void hw_set_MSBC_codec_cback(void *p_mem)
1020 {
1021     /* whenever update the codec enable/disable, need to update I2SPCM */
1022     HILOGI("SCO I2S interface change the sample rate to 16K");
1023     hw_sco_i2spcm_config_from_command(p_mem, SCO_CODEC_MSBC);
1024 }
1025 
1026 /*******************************************************************************
1027 **
1028 ** Function         hw_set_CVSD_codec_cback
1029 **
1030 ** Description      Callback function for setting NBS codec
1031 **
1032 ** Returns          None
1033 **
1034 *******************************************************************************/
hw_set_CVSD_codec_cback(void * p_mem)1035 static void hw_set_CVSD_codec_cback(void *p_mem)
1036 {
1037     /* whenever update the codec enable/disable, need to update I2SPCM */
1038     HILOGI("SCO I2S interface change the sample rate to 8K");
1039     hw_sco_i2spcm_config_from_command(p_mem, SCO_CODEC_CVSD);
1040 }
1041 
1042 #endif // SCO_CFG_INCLUDED
1043 
1044 /*****************************************************************************
1045 **   Hardware Configuration Interface Functions
1046 *****************************************************************************/
1047 
1048 /*******************************************************************************
1049 **
1050 ** Function        hw_config_start
1051 **
1052 ** Description     Kick off controller initialization process
1053 **
1054 ** Returns         None
1055 **
1056 *******************************************************************************/
hw_config_start(void)1057 void hw_config_start(void)
1058 {
1059     HC_BT_HDR *p_buf = NULL;
1060     uint8_t *p;
1061 
1062     hw_cfg_cb.state = 0;
1063     hw_cfg_cb.fw_fd = -1;
1064     hw_cfg_cb.f_set_baud_2 = FALSE;
1065 
1066     // bt_vendor_cbacks->init_cb(BTC_OP_RESULT_SUCCESS);
1067     //    Start from sending HCI_RESET
1068 
1069     if (bt_vendor_cbacks) {
1070         p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE +
1071                                                      HCI_CMD_PREAMBLE_SIZE);
1072     }
1073 
1074     if (p_buf) {
1075         p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1076         p_buf->offset = 0;
1077         p_buf->layer_specific = 0;
1078         p_buf->len = HCI_CMD_PREAMBLE_SIZE;
1079 
1080         p = (uint8_t *)(p_buf + 1);
1081         UINT16_TO_STREAM(p, HCI_RESET);
1082         *p = 0;
1083 
1084         hw_cfg_cb.state = HW_CFG_START;
1085         bt_vendor_cbacks->xmit_cb(HCI_RESET, 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_s(p, LPM_CMD_PARAM_SIZE, &lpm_param, LPM_CMD_PARAM_SIZE);
1127             upio_set(UPIO_LPM_MODE, UPIO_ASSERT, 0);
1128         } else {
1129             memset_s(p, LPM_CMD_PARAM_SIZE, 0, LPM_CMD_PARAM_SIZE);
1130             upio_set(UPIO_LPM_MODE, UPIO_DEASSERT, 0);
1131         }
1132 
1133         if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_SLEEP_MODE, p_buf)) <= 0) {
1134             bt_vendor_cbacks->dealloc(p_buf);
1135         }
1136     }
1137 
1138     if ((ret <= 0) && bt_vendor_cbacks) {
1139         // bt_vendor_cbacks->lpm_cb(BT_VND_OP_RESULT_FAIL);
1140     }
1141     HILOGD("hw_lpm_enable ret:%d", ret);
1142     return ret;
1143 }
1144 
1145 /*******************************************************************************
1146 **
1147 ** Function        hw_lpm_get_idle_timeout
1148 **
1149 ** Description     Calculate idle time based on host stack idle threshold
1150 **
1151 ** Returns         idle timeout value
1152 **
1153 *******************************************************************************/
hw_lpm_get_idle_timeout(void)1154 uint32_t hw_lpm_get_idle_timeout(void)
1155 {
1156     uint32_t timeout_ms;
1157 
1158     /* set idle time to be LPM_IDLE_TIMEOUT_MULTIPLE times of
1159      * host stack idle threshold (in 300ms/25ms)
1160      */
1161     timeout_ms = (uint32_t)lpm_param.host_stack_idle_threshold * LPM_IDLE_TIMEOUT_MULTIPLE;
1162     timeout_ms *= BT_VENDOR_LDM_DEFAULT_IDLE;
1163     return timeout_ms;
1164 }
1165 
1166 /*******************************************************************************
1167 **
1168 ** Function        hw_lpm_set_wake_state
1169 **
1170 ** Description     Assert/Deassert BT_WAKE
1171 **
1172 ** Returns         None
1173 **
1174 *******************************************************************************/
hw_lpm_set_wake_state(uint8_t wake_assert)1175 void hw_lpm_set_wake_state(uint8_t wake_assert)
1176 {
1177     uint8_t state = (wake_assert) ? UPIO_ASSERT : UPIO_DEASSERT;
1178 
1179     upio_set(UPIO_BT_WAKE, state, lpm_param.bt_wake_polarity);
1180 }
1181 
1182 #if (SCO_CFG_INCLUDED == TRUE)
1183 /*******************************************************************************
1184 **
1185 ** Function         hw_sco_config
1186 **
1187 ** Description      Configure SCO related hardware settings
1188 **
1189 ** Returns          None
1190 **
1191 *******************************************************************************/
hw_sco_config(void)1192 void hw_sco_config(void)
1193 {
1194     if (sco_bus_interface == SCO_INTERFACE_I2S) {
1195         /* 'Enable' I2S mode */
1196         bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_MODE] = 1;
1197 
1198         /* set nbs clock rate as the value in SCO_I2SPCM_IF_CLOCK_RATE field */
1199         sco_bus_clock_rate = bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_CLOCK_RATE];
1200     } else {
1201         /* 'Disable' I2S mode */
1202         bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_MODE] = 0;
1203 
1204         /* set nbs clock rate as the value in SCO_PCM_IF_CLOCK_RATE field */
1205         sco_bus_clock_rate = bt_sco_param[SCO_PCM_PARAM_IF_CLOCK_RATE];
1206 
1207         /* sync up clock mode setting */
1208         bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_MODE] = bt_sco_param[SCO_PCM_PARAM_IF_CLOCK_MODE];
1209     }
1210 
1211     if (sco_bus_wbs_clock_rate == INVALID_SCO_CLOCK_RATE) {
1212         /* set default wbs clock rate */
1213         sco_bus_wbs_clock_rate = SCO_I2SPCM_IF_CLOCK_RATE4WBS;
1214 
1215         if (sco_bus_wbs_clock_rate < sco_bus_clock_rate)
1216             sco_bus_wbs_clock_rate = sco_bus_clock_rate;
1217     }
1218 
1219     /*
1220      *  To support I2S/PCM port multiplexing signals for sharing Bluetooth audio
1221      *  and FM on the same PCM pins, we defer Bluetooth audio (SCO/eSCO)
1222      *  configuration till SCO/eSCO is being established;
1223      *  i.e. in hw_set_audio_state() call.
1224      *  When configured as I2S only, Bluetooth audio configuration is executed
1225      *  immediately with SCO_CODEC_CVSD by default.
1226      */
1227 
1228     if (sco_bus_interface == SCO_INTERFACE_I2S) {
1229         hw_sco_i2spcm_config(SCO_CODEC_CVSD);
1230     } else {
1231         hw_sco_i2spcm_config(SCO_CODEC_NONE);
1232     }
1233 
1234     if (bt_vendor_cbacks) {
1235         // bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_SUCCESS);
1236     }
1237 }
1238 
hw_sco_i2spcm_config_from_command(void * p_mem,uint16_t codec)1239 static void hw_sco_i2spcm_config_from_command(void *p_mem, uint16_t codec)
1240 {
1241     HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem;
1242     bool command_success = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0;
1243 
1244     /* Free the RX event buffer */
1245     if (bt_vendor_cbacks) {
1246         // bt_vendor_cbacks->dealloc(p_evt_buf);
1247     }
1248 
1249     if (command_success) {
1250         hw_sco_i2spcm_config(codec);
1251     }
1252 }
1253 
1254 /*******************************************************************************
1255 **
1256 ** Function         hw_sco_i2spcm_config
1257 **
1258 ** Description      Configure SCO over I2S or PCM
1259 **
1260 ** Returns          None
1261 **
1262 *******************************************************************************/
hw_sco_i2spcm_config(uint16_t codec)1263 static void hw_sco_i2spcm_config(uint16_t codec)
1264 {
1265     HC_BT_HDR *p_buf = NULL;
1266     uint8_t *p, ret;
1267     uint16_t cmd_u16 = HCI_CMD_PREAMBLE_SIZE + SCO_I2SPCM_PARAM_SIZE;
1268 
1269     if (bt_vendor_cbacks) {
1270         p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + cmd_u16);
1271     }
1272 
1273     if (p_buf) {
1274         p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1275         p_buf->offset = 0;
1276         p_buf->layer_specific = 0;
1277         p_buf->len = cmd_u16;
1278 
1279         p = (uint8_t *)(p_buf + 1);
1280 
1281         UINT16_TO_STREAM(p, HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM);
1282         *p++ = SCO_I2SPCM_PARAM_SIZE;
1283         if (codec == SCO_CODEC_CVSD) {
1284             bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_SAMPLE_RATE] = 0; /* SCO_I2SPCM_IF_SAMPLE_RATE  8k */
1285             bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_CLOCK_RATE] =
1286                 bt_sco_param[SCO_PCM_PARAM_IF_CLOCK_RATE] = sco_bus_clock_rate;
1287         } else if (codec == SCO_CODEC_MSBC) {
1288             bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_SAMPLE_RATE] = wbs_sample_rate; /* SCO_I2SPCM_IF_SAMPLE_RATE 16K */
1289             bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_CLOCK_RATE] =
1290                 bt_sco_param[SCO_PCM_PARAM_IF_CLOCK_RATE] = sco_bus_wbs_clock_rate;
1291         } else {
1292             bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_SAMPLE_RATE] = 0; /* SCO_I2SPCM_IF_SAMPLE_RATE  8k */
1293             bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_CLOCK_RATE] =
1294                 bt_sco_param[SCO_PCM_PARAM_IF_CLOCK_RATE] = sco_bus_clock_rate;
1295             HILOGE("wrong codec is use in hw_sco_i2spcm_config, goes default NBS");
1296         }
1297         memcpy_s(p, &bt_sco_i2spcm_param, SCO_I2SPCM_PARAM_SIZE);
1298         cmd_u16 = HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM;
1299         HILOGI("I2SPCM config {0x%x, 0x%x, 0x%x, 0x%x}",
1300             bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_MODE], bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_ROLE],
1301             bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_SAMPLE_RATE],
1302             bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_IF_CLOCK_RATE]);
1303 
1304         if ((ret = bt_vendor_cbacks->xmit_cb(cmd_u16, p_buf)) <= 0) {
1305             bt_vendor_cbacks->dealloc(p_buf);
1306         } else {
1307             return;
1308         }
1309     }
1310     // bt_vendor_cbacks->audio_state_cb(BT_VND_OP_RESULT_FAIL);
1311 }
1312 
1313 /*******************************************************************************
1314 **
1315 ** Function         hw_set_SCO_codec
1316 **
1317 ** Description      This functgion sends command to the controller to setup
1318 **                              WBS/NBS codec for the upcoming eSCO connection.
1319 **
1320 ** Returns          -1 : Failed to send VSC
1321 **                   0 : Success
1322 **
1323 *******************************************************************************/
hw_set_SCO_codec(uint16_t codec)1324 static int hw_set_SCO_codec(uint16_t codec)
1325 {
1326     HC_BT_HDR *p_buf = NULL;
1327     uint8_t *p;
1328     uint8_t ret;
1329     int ret_val = 0;
1330     return ret_val;
1331 }
1332 
1333 /*******************************************************************************
1334 **
1335 ** Function         hw_set_audio_state
1336 **
1337 ** Description      This function configures audio base on provided audio state
1338 **
1339 ** Paramters        pointer to audio state structure
1340 **
1341 ** Returns          0: ok, -1: error
1342 **
1343 *******************************************************************************/
hw_set_audio_state(bt_vendor_op_audio_state_t * p_state)1344 int hw_set_audio_state(bt_vendor_op_audio_state_t *p_state)
1345 {
1346     int ret_val = -1;
1347 
1348     if (!bt_vendor_cbacks) {
1349         return ret_val;
1350     }
1351 
1352     ret_val = hw_set_SCO_codec(p_state->peer_codec);
1353     return ret_val;
1354 }
1355 #endif
1356 /*******************************************************************************
1357 **
1358 ** Function        hw_set_patch_file_path
1359 **
1360 ** Description     Set the location of firmware patch file
1361 **
1362 ** Returns         0 : Success
1363 **                 Otherwise : Fail
1364 **
1365 *******************************************************************************/
hw_set_patch_file_path(char * p_conf_name,char * p_conf_value,int param)1366 int hw_set_patch_file_path(char *p_conf_name, char *p_conf_value, int param)
1367 {
1368     if (strcpy_s(fw_patchfile_path, sizeof(fw_patchfile_path), p_conf_value) != 0) {
1369         return -1;
1370     }
1371     return 0;
1372 }
1373 
1374 /*******************************************************************************
1375 **
1376 ** Function        hw_set_patch_file_name
1377 **
1378 ** Description     Give the specific firmware patch filename
1379 **
1380 ** Returns         0 : Success
1381 **                 Otherwise : Fail
1382 **
1383 *******************************************************************************/
hw_set_patch_file_name(char * p_conf_name,char * p_conf_value,int param)1384 int hw_set_patch_file_name(char *p_conf_name, char *p_conf_value, int param)
1385 {
1386     if (strcpy_s(fw_patchfile_name, sizeof(fw_patchfile_name), p_conf_value) != 0) {
1387         return -1;
1388     }
1389     return 0;
1390 }
1391 
1392 #if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
1393 /*******************************************************************************
1394 **
1395 ** Function        hw_set_patch_settlement_delay
1396 **
1397 ** Description     Give the specific firmware patch settlement time in milliseconds
1398 **
1399 ** Returns         0 : Success
1400 **                 Otherwise : Fail
1401 **
1402 *******************************************************************************/
hw_set_patch_settlement_delay(char * p_conf_name,char * p_conf_value,int param)1403 int hw_set_patch_settlement_delay(char *p_conf_name, char *p_conf_value, int param)
1404 {
1405     fw_patch_settlement_delay = atoi(p_conf_value);
1406     return 0;
1407 }
1408 #endif // VENDOR_LIB_RUNTIME_TUNING_ENABLED
1409 
1410 /*****************************************************************************
1411 **   Sample Codes Section
1412 *****************************************************************************/
1413 
1414 #if (HW_END_WITH_HCI_RESET == TRUE)
1415 /*******************************************************************************
1416 **
1417 ** Function         hw_epilog_cback
1418 **
1419 ** Description      Callback function for Command Complete Events from HCI
1420 **                  commands sent in epilog process.
1421 **
1422 ** Returns          None
1423 **
1424 *******************************************************************************/
hw_epilog_cback(void * p_mem)1425 void hw_epilog_cback(void *p_mem)
1426 {
1427     HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem;
1428     uint8_t *p, status;
1429     uint16_t opcode;
1430 
1431     status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
1432     p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
1433     STREAM_TO_UINT16(opcode, p);
1434 
1435     BTHWDBG("%s Opcode:0x%04X Status: %d", __FUNCTION__, opcode, status);
1436 
1437     if (bt_vendor_cbacks) {
1438         /* Must free the RX event buffer */
1439         // bt_vendor_cbacks->dealloc(p_evt_buf);
1440         /* Once epilog process is done, must call epilog_cb callback
1441            to notify caller */
1442         // bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
1443     }
1444 }
1445 
1446 /*******************************************************************************
1447 **
1448 ** Function         hw_epilog_process
1449 **
1450 ** Description      Sample implementation of epilog process
1451 **
1452 ** Returns          None
1453 **
1454 *******************************************************************************/
hw_epilog_process(void)1455 void hw_epilog_process(void)
1456 {
1457     HC_BT_HDR *p_buf = NULL;
1458     uint8_t *p;
1459 
1460     BTHWDBG("hw_epilog_process");
1461 
1462     /* Sending a HCI_RESET */
1463     if (bt_vendor_cbacks) {
1464         /* Must allocate command buffer via HC's alloc API */
1465         p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE +
1466                                                      HCI_CMD_PREAMBLE_SIZE);
1467     }
1468 
1469     if (p_buf) {
1470         p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1471         p_buf->offset = 0;
1472         p_buf->layer_specific = 0;
1473         p_buf->len = HCI_CMD_PREAMBLE_SIZE;
1474 
1475         p = (uint8_t *)(p_buf + 1);
1476         UINT16_TO_STREAM(p, HCI_RESET);
1477         *p = 0; /* parameter length */
1478 
1479         /* Send command via HC's xmit_cb API */
1480         bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf);
1481     } else {
1482         if (bt_vendor_cbacks) {
1483             HILOGE("vendor lib epilog process aborted [no buffer]");
1484         }
1485     }
1486 }
1487 #endif // (HW_END_WITH_HCI_RESET == TRUE)
1488 
hw_process_event(HC_BT_HDR * p_buf)1489 void hw_process_event(HC_BT_HDR *p_buf)
1490 {
1491     uint16_t opcode;
1492     uint8_t *p = (uint8_t *)(p_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
1493     STREAM_TO_UINT16(opcode, p);
1494 
1495     HILOGI("%s, opcode:0x%04x", __FUNCTION__, opcode);
1496     switch (opcode) {
1497         case HCI_VSC_WRITE_BD_ADDR:
1498 #if (USE_CONTROLLER_BDADDR == TRUE)
1499         case HCI_READ_LOCAL_BDADDR:
1500 #endif
1501         case HCI_READ_LOCAL_NAME:
1502         case HCI_VSC_DOWNLOAD_MINIDRV:
1503         case HCI_VSC_WRITE_FIRMWARE:
1504         case HCI_VSC_LAUNCH_RAM:
1505         case HCI_RESET:
1506         case HCI_VSC_WRITE_UART_CLOCK_SETTING:
1507         case HCI_VSC_UPDATE_BAUDRATE:
1508             hw_config_cback(p_buf);
1509             break;
1510 
1511         case HCI_VSC_WRITE_SCO_PCM_INT_PARAM:
1512         case HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM:
1513         case HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM:
1514             hw_sco_i2spcm_cfg_cback(p_buf);
1515             break;
1516 
1517         case HCI_VSC_WRITE_SLEEP_MODE:
1518             hw_lpm_ctrl_cback(p_buf);
1519             break;
1520 
1521         case HCI_VSC_ENABLE_WBS:
1522             break;
1523     }
1524 
1525     HILOGI("%s, Complete", __FUNCTION__);
1526 }
1527