xref: /vendor/hihope/dayu210/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 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 */
172typedef struct {
173    const char *chipset_name;
174    const uint32_t delay_time;
175} fw_settlement_entry_t;
176
177/******************************************************************************
178**  Externs
179******************************************************************************/
180
181void hw_config_cback(void *p_mem);
182
183/******************************************************************************
184**  Static variables
185******************************************************************************/
186
187static char fw_patchfile_path[256] = FW_PATCHFILE_LOCATION;
188static char fw_patchfile_name[128] = {0};
189#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
190static int fw_patch_settlement_delay = -1;
191#endif
192
193static int wbs_sample_rate = SCO_WBS_SAMPLE_RATE;
194static bt_hw_cfg_cb_t hw_cfg_cb;
195
196static 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 */
204static 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
212static 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
220static 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 */
231static 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)
247static uint8_t sco_bus_interface = SCO_INTERFACE_I2S;
248#else
249static uint8_t sco_bus_interface = SCO_INTERFACE_PCM;
250#endif
251
252#define INVALID_SCO_CLOCK_RATE 0xFF
253static uint8_t sco_bus_clock_rate = INVALID_SCO_CLOCK_RATE;
254static uint8_t sco_bus_wbs_clock_rate = INVALID_SCO_CLOCK_RATE;
255
256/******************************************************************************
257**  Static functions
258******************************************************************************/
259static void hw_sco_i2spcm_config(uint16_t codec);
260static 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*******************************************************************************/
281uint32_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*******************************************************************************/
321void 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*******************************************************************************/
348uint8_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*******************************************************************************/
397static 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*******************************************************************************/
423static 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*******************************************************************************/
456static 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
473typedef void (*tTIMER_HANDLE_CBACK)(union sigval sigval_value);
474
475static 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
496int 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
507static 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
532static timer_t localtimer = 0;
533static void local_timer_handler(union sigval sigev_value)
534{
535    bt_vendor_cbacks->init_cb(BTC_OP_RESULT_SUCCESS);
536    OsFreeTimer(localtimer);
537}
538static 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
546void 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*******************************************************************************/
557void 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*******************************************************************************/
839void 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
859static 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
891static 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*******************************************************************************/
931static 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*******************************************************************************/
973static 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*******************************************************************************/
989static 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*******************************************************************************/
1011void 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*******************************************************************************/
1056uint8_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*******************************************************************************/
1106uint32_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*******************************************************************************/
1127void 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*******************************************************************************/
1144void 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
1191static 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*******************************************************************************/
1217static 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*******************************************************************************/
1277static 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*******************************************************************************/
1295int 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*******************************************************************************/
1317int 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*******************************************************************************/
1335int 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*******************************************************************************/
1354int 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*******************************************************************************/
1376void 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*******************************************************************************/
1406void 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
1439void 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