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