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