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