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 <cutils/properties.h>
42#include <stdlib.h>
43#include <string.h>
44#include "bt_hci_bdroid.h"
45#include "bt_vendor_brcm.h"
46#include "hci_audio.h"
47#include "userial.h"
48#include "userial_vendor.h"
49#include "upio.h"
50
51/******************************************************************************
52**  Constants & Macros
53******************************************************************************/
54
55#ifndef BTHW_DBG
56#define BTHW_DBG FALSE
57#endif
58
59#if (BTHW_DBG == TRUE)
60#define BTHWDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
61#else
62#define BTHWDBG(param, ...) {}
63#endif
64
65#define FW_PATCHFILE_EXTENSION      ".hcd"
66#define FW_PATCHFILE_EXTENSION_LEN  4
67#define FW_PATCHFILE_PATH_MAXLEN    248 /* Local_Name length of return of
68                                           HCI_Read_Local_Name */
69
70#define HCI_CMD_MAX_LEN             258
71
72#define HCI_RESET                               0x0C03
73#define HCI_VSC_WRITE_UART_CLOCK_SETTING        0xFC45
74#define HCI_VSC_UPDATE_BAUDRATE                 0xFC18
75#define HCI_READ_LOCAL_NAME                     0x0C14
76#define HCI_VSC_DOWNLOAD_MINIDRV                0xFC2E
77#define HCI_VSC_WRITE_BD_ADDR                   0xFC01
78#define HCI_VSC_WRITE_SLEEP_MODE                0xFC27
79#define HCI_VSC_WRITE_SCO_PCM_INT_PARAM         0xFC1C
80#define HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM     0xFC1E
81#define HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM    0xFC6D
82#define HCI_VSC_ENABLE_WBS                      0xFC7E
83#define HCI_VSC_LAUNCH_RAM                      0xFC4E
84#define HCI_READ_LOCAL_BDADDR                   0x1009
85
86#define HCI_EVT_CMD_CMPL_STATUS_RET_BYTE        5
87#define HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING      6
88#define HCI_EVT_CMD_CMPL_LOCAL_BDADDR_ARRAY     6
89#define HCI_EVT_CMD_CMPL_OPCODE                 3
90#define LPM_CMD_PARAM_SIZE                      12
91#define UPDATE_BAUDRATE_CMD_PARAM_SIZE          6
92#define HCI_CMD_PREAMBLE_SIZE                   3
93#define HCD_REC_PAYLOAD_LEN_BYTE                2
94#define BD_ADDR_LEN                             6
95#define LOCAL_NAME_BUFFER_LEN                   32
96#define LOCAL_BDADDR_PATH_BUFFER_LEN            256
97
98#define STREAM_TO_UINT16(u16, p) {u16 = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); (p) += 2;}
99#define UINT8_TO_STREAM(p, u8)   {*(p)++ = (uint8_t)(u8);}
100#define UINT16_TO_STREAM(p, u16) {*(p)++ = (uint8_t)(u16); *(p)++ = (uint8_t)((u16) >> 8);}
101#define UINT32_TO_STREAM(p, u32) {*(p)++ = (uint8_t)(u32); *(p)++ = (uint8_t)((u32) >> 8); *(p)++ = (uint8_t)((u32) >> 16); *(p)++ = (uint8_t)((u32) >> 24);}
102
103#define SCO_INTERFACE_PCM  0
104#define SCO_INTERFACE_I2S  1
105
106/* one byte is for enable/disable
107      next 2 bytes are for codec type */
108#define SCO_CODEC_PARAM_SIZE                    3
109
110/******************************************************************************
111**  Local type definitions
112******************************************************************************/
113
114/* Hardware Configuration State */
115enum {
116    HW_CFG_START = 1,
117    HW_CFG_SET_UART_CLOCK,
118    HW_CFG_SET_UART_BAUD_1,
119    HW_CFG_READ_LOCAL_NAME,
120    HW_CFG_DL_MINIDRIVER,
121    HW_CFG_DL_FW_PATCH,
122    HW_CFG_SET_UART_BAUD_2,
123    HW_CFG_SET_BD_ADDR
124#if (USE_CONTROLLER_BDADDR == TRUE)
125    , HW_CFG_READ_BD_ADDR
126#endif
127};
128
129/* h/w config control block */
130typedef struct
131{
132    uint8_t state;                          /* Hardware configuration state */
133    int     fw_fd;                          /* FW patch file fd */
134    uint8_t f_set_baud_2;                   /* Baud rate switch state */
135    char    local_chip_name[LOCAL_NAME_BUFFER_LEN];
136} bt_hw_cfg_cb_t;
137
138/* low power mode parameters */
139typedef struct
140{
141    uint8_t sleep_mode;                     /* 0(disable),1(UART),9(H5) */
142    uint8_t host_stack_idle_threshold;      /* Unit scale 300ms/25ms */
143    uint8_t host_controller_idle_threshold; /* Unit scale 300ms/25ms */
144    uint8_t bt_wake_polarity;               /* 0=Active Low, 1= Active High */
145    uint8_t host_wake_polarity;             /* 0=Active Low, 1= Active High */
146    uint8_t allow_host_sleep_during_sco;
147    uint8_t combine_sleep_mode_and_lpm;
148    uint8_t enable_uart_txd_tri_state;      /* UART_TXD Tri-State */
149    uint8_t sleep_guard_time;               /* sleep guard time in 12.5ms */
150    uint8_t wakeup_guard_time;              /* wakeup guard time in 12.5ms */
151    uint8_t txd_config;                     /* TXD is high in sleep state */
152    uint8_t pulsed_host_wake;               /* pulsed host wake if mode = 1 */
153} bt_lpm_param_t;
154
155/* Firmware re-launch settlement time */
156typedef struct {
157    const char *chipset_name;
158    const uint32_t delay_time;
159} fw_settlement_entry_t;
160
161
162/******************************************************************************
163**  Externs
164******************************************************************************/
165
166void hw_config_cback(void *p_evt_buf);
167extern uint8_t vnd_local_bd_addr[BD_ADDR_LEN];
168
169
170/******************************************************************************
171**  Static variables
172******************************************************************************/
173
174static char fw_patchfile_path[256] = FW_PATCHFILE_LOCATION;
175static char fw_patchfile_name[128] = { 0 };
176#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
177static int fw_patch_settlement_delay = -1;
178#endif
179
180static int wbs_sample_rate = SCO_WBS_SAMPLE_RATE;
181static bt_hw_cfg_cb_t hw_cfg_cb;
182
183static bt_lpm_param_t lpm_param =
184{
185    LPM_SLEEP_MODE,
186    LPM_IDLE_THRESHOLD,
187    LPM_HC_IDLE_THRESHOLD,
188    LPM_BT_WAKE_POLARITY,
189    LPM_HOST_WAKE_POLARITY,
190    LPM_ALLOW_HOST_SLEEP_DURING_SCO,
191    LPM_COMBINE_SLEEP_MODE_AND_LPM,
192    LPM_ENABLE_UART_TXD_TRI_STATE,
193    0,  /* not applicable */
194    0,  /* not applicable */
195    0,  /* not applicable */
196    LPM_PULSED_HOST_WAKE
197};
198
199/* need to update the bt_sco_i2spcm_param as well
200   bt_sco_i2spcm_param will be used for WBS setting
201   update the bt_sco_param and bt_sco_i2spcm_param */
202static uint8_t bt_sco_param[SCO_PCM_PARAM_SIZE] =
203{
204    SCO_PCM_ROUTING,
205    SCO_PCM_IF_CLOCK_RATE,
206    SCO_PCM_IF_FRAME_TYPE,
207    SCO_PCM_IF_SYNC_MODE,
208    SCO_PCM_IF_CLOCK_MODE
209};
210
211static uint8_t bt_pcm_data_fmt_param[PCM_DATA_FORMAT_PARAM_SIZE] =
212{
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{
222    SCO_I2SPCM_IF_MODE,
223    SCO_I2SPCM_IF_ROLE,
224    SCO_I2SPCM_IF_SAMPLE_RATE,
225    SCO_I2SPCM_IF_CLOCK_RATE
226};
227
228/*
229 * The look-up table of recommended firmware settlement delay (milliseconds) on
230 * known chipsets.
231 */
232static const fw_settlement_entry_t fw_settlement_table[] = {
233    {"BCM43241", 200},
234    {"BCM43341", 100},
235    {(const char *) NULL, 100}  // Giving the generic fw settlement delay setting.
236};
237
238
239/*
240 * NOTICE:
241 *     If the platform plans to run I2S interface bus over I2S/PCM port of the
242 *     BT Controller with the Host AP, explicitly set "SCO_USE_I2S_INTERFACE = TRUE"
243 *     in the correspodning include/vnd_<target>.txt file.
244 *     Otherwise, leave SCO_USE_I2S_INTERFACE undefined in the vnd_<target>.txt file.
245 *     And, PCM interface will be set as the default bus format running over I2S/PCM
246 *     port.
247 */
248#if (defined(SCO_USE_I2S_INTERFACE) && SCO_USE_I2S_INTERFACE == TRUE)
249static uint8_t sco_bus_interface = SCO_INTERFACE_I2S;
250#else
251static uint8_t sco_bus_interface = SCO_INTERFACE_PCM;
252#endif
253
254#define INVALID_SCO_CLOCK_RATE  0xFF
255static uint8_t sco_bus_clock_rate = INVALID_SCO_CLOCK_RATE;
256static uint8_t sco_bus_wbs_clock_rate = INVALID_SCO_CLOCK_RATE;
257
258/******************************************************************************
259**  Static functions
260******************************************************************************/
261static void hw_sco_i2spcm_config(uint16_t codec);
262static void hw_sco_i2spcm_config_from_command(void *p_mem, uint16_t codec);
263
264/******************************************************************************
265**  Controller Initialization Static Functions
266******************************************************************************/
267
268/*******************************************************************************
269**
270** Function        look_up_fw_settlement_delay
271**
272** Description     If FW_PATCH_SETTLEMENT_DELAY_MS has not been explicitly
273**                 re-defined in the platform specific build-time configuration
274**                 file, we will search into the look-up table for a
275**                 recommended firmware settlement delay value.
276**
277**                 Although the settlement time might be also related to board
278**                 configurations such as the crystal clocking speed.
279**
280** Returns         Firmware settlement delay
281**
282*******************************************************************************/
283uint32_t look_up_fw_settlement_delay (void)
284{
285    uint32_t ret_value;
286    fw_settlement_entry_t *p_entry;
287
288    if (FW_PATCH_SETTLEMENT_DELAY_MS > 0)
289    {
290        ret_value = FW_PATCH_SETTLEMENT_DELAY_MS;
291    }
292#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
293    else if (fw_patch_settlement_delay >= 0)
294    {
295        ret_value = fw_patch_settlement_delay;
296    }
297#endif
298    else
299    {
300        p_entry = (fw_settlement_entry_t *)fw_settlement_table;
301
302        while (p_entry->chipset_name != NULL)
303        {
304            if (strstr(hw_cfg_cb.local_chip_name, p_entry->chipset_name)!=NULL)
305            {
306                break;
307            }
308
309            p_entry++;
310        }
311
312        ret_value = p_entry->delay_time;
313    }
314
315    BTHWDBG( "Settlement delay -- %d ms", ret_value);
316
317    return (ret_value);
318}
319
320/*******************************************************************************
321**
322** Function        ms_delay
323**
324** Description     sleep unconditionally for timeout milliseconds
325**
326** Returns         None
327**
328*******************************************************************************/
329void ms_delay (uint32_t timeout)
330{
331    struct timespec delay;
332    int err;
333
334    if (timeout == 0)
335        return;
336
337    delay.tv_sec = timeout / 1000;
338    delay.tv_nsec = 1000 * 1000 * (timeout%1000);
339
340    /* [u]sleep can't be used because it uses SIGALRM */
341    do {
342        err = nanosleep(&delay, &delay);
343    } while (err < 0 && errno ==EINTR);
344}
345
346/*******************************************************************************
347**
348** Function        line_speed_to_userial_baud
349**
350** Description     helper function converts line speed number into USERIAL baud
351**                 rate symbol
352**
353** Returns         unit8_t (USERIAL baud symbol)
354**
355*******************************************************************************/
356uint8_t line_speed_to_userial_baud(uint32_t line_speed)
357{
358    uint8_t baud;
359
360    if (line_speed == 4000000)
361        baud = USERIAL_BAUD_4M;
362    else if (line_speed == 3000000)
363        baud = USERIAL_BAUD_3M;
364    else if (line_speed == 2000000)
365        baud = USERIAL_BAUD_2M;
366    else if (line_speed == 1000000)
367        baud = USERIAL_BAUD_1M;
368    else if (line_speed == 921600)
369        baud = USERIAL_BAUD_921600;
370    else if (line_speed == 460800)
371        baud = USERIAL_BAUD_460800;
372    else if (line_speed == 230400)
373        baud = USERIAL_BAUD_230400;
374    else if (line_speed == 115200)
375        baud = USERIAL_BAUD_115200;
376    else if (line_speed == 57600)
377        baud = USERIAL_BAUD_57600;
378    else if (line_speed == 19200)
379        baud = USERIAL_BAUD_19200;
380    else if (line_speed == 9600)
381        baud = USERIAL_BAUD_9600;
382    else if (line_speed == 1200)
383        baud = USERIAL_BAUD_1200;
384    else if (line_speed == 600)
385        baud = USERIAL_BAUD_600;
386    else
387    {
388        ALOGE( "userial vendor: unsupported baud speed %d", line_speed);
389        baud = USERIAL_BAUD_115200;
390    }
391
392    return baud;
393}
394
395
396/*******************************************************************************
397**
398** Function         hw_strncmp
399**
400** Description      Used to compare two strings in caseless
401**
402** Returns          0: match, otherwise: not match
403**
404*******************************************************************************/
405static int hw_strncmp (const char *p_str1, const char *p_str2, const int len)
406{
407    int i;
408
409    if (!p_str1 || !p_str2)
410        return (1);
411
412    for (i = 0; i < len; i++)
413    {
414        if (toupper(p_str1[i]) != toupper(p_str2[i]))
415            return (i+1);
416    }
417
418    return 0;
419}
420
421/*******************************************************************************
422**
423** Function         hw_config_findpatch
424**
425** Description      Search for a proper firmware patch file
426**                  The selected firmware patch file name with full path
427**                  will be stored in the input string parameter, i.e.
428**                  p_chip_id_str, when returns.
429**
430** Returns          TRUE when found the target patch file, otherwise FALSE
431**
432*******************************************************************************/
433static uint8_t hw_config_findpatch(char *p_chip_id_str)
434{
435    DIR *dirp;
436    struct dirent *dp;
437    int filenamelen;
438    uint8_t retval = FALSE;
439
440    BTHWDBG("Target name = [%s]", p_chip_id_str);
441
442    if (strlen(fw_patchfile_name)> 0)
443    {
444        /* If specific filepath and filename have been given in run-time
445         * configuration /etc/bluetooth/bt_vendor.conf file, we will use them
446         * to concatenate the filename to open rather than searching a file
447         * matching to chipset name in the fw_patchfile_path folder.
448         */
449        sprintf(p_chip_id_str, "%s", fw_patchfile_path);
450        if (fw_patchfile_path[strlen(fw_patchfile_path)- 1] != '/')
451        {
452            strcat(p_chip_id_str, "/");
453        }
454        strcat(p_chip_id_str, fw_patchfile_name);
455
456        ALOGI("FW patchfile: %s", p_chip_id_str);
457        return TRUE;
458    }
459
460    if ((dirp = opendir(fw_patchfile_path)) != NULL)
461    {
462        /* Fetch next filename in patchfile directory */
463        while ((dp = readdir(dirp)) != NULL)
464        {
465            /* Check if filename starts with chip-id name */
466            if ((hw_strncmp(dp->d_name, p_chip_id_str, strlen(p_chip_id_str)) \
467                ) == 0)
468            {
469                /* Check if it has .hcd extenstion */
470                filenamelen = strlen(dp->d_name);
471                if ((filenamelen >= FW_PATCHFILE_EXTENSION_LEN) &&
472                    ((hw_strncmp(
473                          &dp->d_name[filenamelen-FW_PATCHFILE_EXTENSION_LEN], \
474                          FW_PATCHFILE_EXTENSION, \
475                          FW_PATCHFILE_EXTENSION_LEN) \
476                     ) == 0))
477                {
478                    ALOGI("Found patchfile: %s/%s", \
479                        fw_patchfile_path, dp->d_name);
480
481                    /* Make sure length does not exceed maximum */
482                    if ((filenamelen + strlen(fw_patchfile_path)) > \
483                         FW_PATCHFILE_PATH_MAXLEN)
484                    {
485                        ALOGE("Invalid patchfile name (too long)");
486                    }
487                    else
488                    {
489                        memset(p_chip_id_str, 0, FW_PATCHFILE_PATH_MAXLEN);
490                        /* Found patchfile. Store location and name */
491                        strcpy(p_chip_id_str, fw_patchfile_path);
492                        if (fw_patchfile_path[ \
493                            strlen(fw_patchfile_path)- 1 \
494                            ] != '/')
495                        {
496                            strcat(p_chip_id_str, "/");
497                        }
498                        strcat(p_chip_id_str, dp->d_name);
499                        retval = TRUE;
500                    }
501                    break;
502                }
503            }
504        }
505
506        closedir(dirp);
507
508        if (retval == FALSE)
509        {
510            /* Try again chip name without revision info */
511
512            int len = strlen(p_chip_id_str);
513            char *p = p_chip_id_str + len - 1;
514
515            /* Scan backward and look for the first alphabet
516               which is not M or m
517            */
518            while (len > 3) // BCM****
519            {
520                if ((isdigit(*p)==0) && (*p != 'M') && (*p != 'm'))
521                    break;
522
523                p--;
524                len--;
525            }
526
527            if (len > 3)
528            {
529                *p = 0;
530                retval = hw_config_findpatch(p_chip_id_str);
531            }
532        }
533    }
534    else
535    {
536        ALOGE("Could not open %s", fw_patchfile_path);
537    }
538
539    return (retval);
540}
541
542/*******************************************************************************
543**
544** Function         hw_config_set_bdaddr
545**
546** Description      Program controller's Bluetooth Device Address
547**
548** Returns          TRUE, if valid address is sent
549**                  FALSE, otherwise
550**
551*******************************************************************************/
552static uint8_t hw_config_set_bdaddr(HC_BT_HDR *p_buf)
553{
554    uint8_t retval = FALSE;
555    uint8_t *p = (uint8_t *) (p_buf + 1);
556
557    ALOGI("Setting local bd addr to %02X:%02X:%02X:%02X:%02X:%02X",
558        vnd_local_bd_addr[0], vnd_local_bd_addr[1], vnd_local_bd_addr[2],
559        vnd_local_bd_addr[3], vnd_local_bd_addr[4], vnd_local_bd_addr[5]);
560
561    UINT16_TO_STREAM(p, HCI_VSC_WRITE_BD_ADDR);
562    *p++ = BD_ADDR_LEN; /* parameter length */
563    *p++ = vnd_local_bd_addr[5];
564    *p++ = vnd_local_bd_addr[4];
565    *p++ = vnd_local_bd_addr[3];
566    *p++ = vnd_local_bd_addr[2];
567    *p++ = vnd_local_bd_addr[1];
568    *p = vnd_local_bd_addr[0];
569
570    p_buf->len = HCI_CMD_PREAMBLE_SIZE + BD_ADDR_LEN;
571    hw_cfg_cb.state = HW_CFG_SET_BD_ADDR;
572
573    retval = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_BD_ADDR, p_buf, \
574                                 hw_config_cback);
575
576    return (retval);
577}
578
579#if (USE_CONTROLLER_BDADDR == TRUE)
580/*******************************************************************************
581**
582** Function         hw_config_read_bdaddr
583**
584** Description      Read controller's Bluetooth Device Address
585**
586** Returns          TRUE, if valid address is sent
587**                  FALSE, otherwise
588**
589*******************************************************************************/
590static uint8_t hw_config_read_bdaddr(HC_BT_HDR *p_buf)
591{
592    uint8_t retval = FALSE;
593    uint8_t *p = (uint8_t *) (p_buf + 1);
594
595    UINT16_TO_STREAM(p, HCI_READ_LOCAL_BDADDR);
596    *p = 0; /* parameter length */
597
598    p_buf->len = HCI_CMD_PREAMBLE_SIZE;
599    hw_cfg_cb.state = HW_CFG_READ_BD_ADDR;
600
601    retval = bt_vendor_cbacks->xmit_cb(HCI_READ_LOCAL_BDADDR, p_buf, \
602                                 hw_config_cback);
603
604    return (retval);
605}
606#endif // (USE_CONTROLLER_BDADDR == TRUE)
607
608/*******************************************************************************
609**
610** Function         hw_config_cback
611**
612** Description      Callback function for controller configuration
613**
614** Returns          None
615**
616*******************************************************************************/
617void hw_config_cback(void *p_mem)
618{
619    HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
620    char        *p_name, *p_tmp;
621    uint8_t     *p, status;
622    uint16_t    opcode;
623    HC_BT_HDR  *p_buf=NULL;
624    uint8_t     is_proceeding = FALSE;
625    int         i;
626    int         delay=100;
627#if (USE_CONTROLLER_BDADDR == TRUE)
628    const uint8_t null_bdaddr[BD_ADDR_LEN] = {0,0,0,0,0,0};
629#endif
630
631    status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
632    p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
633    STREAM_TO_UINT16(opcode,p);
634
635    /* Ask a new buffer big enough to hold any HCI commands sent in here */
636    if ((status == 0) && bt_vendor_cbacks)
637        p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
638                                                       HCI_CMD_MAX_LEN);
639
640    if (p_buf != NULL)
641    {
642        p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
643        p_buf->offset = 0;
644        p_buf->len = 0;
645        p_buf->layer_specific = 0;
646
647        p = (uint8_t *) (p_buf + 1);
648
649        switch (hw_cfg_cb.state)
650        {
651            case HW_CFG_SET_UART_BAUD_1:
652                /* update baud rate of host's UART port */
653                ALOGI("bt vendor lib: set UART baud %i", UART_TARGET_BAUD_RATE);
654                userial_vendor_set_baud( \
655                    line_speed_to_userial_baud(UART_TARGET_BAUD_RATE) \
656                );
657
658                /* read local name */
659                UINT16_TO_STREAM(p, HCI_READ_LOCAL_NAME);
660                *p = 0; /* parameter length */
661
662                p_buf->len = HCI_CMD_PREAMBLE_SIZE;
663                hw_cfg_cb.state = HW_CFG_READ_LOCAL_NAME;
664
665                is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_READ_LOCAL_NAME, \
666                                                    p_buf, hw_config_cback);
667                break;
668
669            case HW_CFG_READ_LOCAL_NAME:
670                p_tmp = p_name = (char *) (p_evt_buf + 1) + \
671                         HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING;
672
673                for (i=0; (i < LOCAL_NAME_BUFFER_LEN)||(*(p_name+i) != 0); i++)
674                    *(p_name+i) = toupper(*(p_name+i));
675
676                if ((p_name = strstr(p_name, "BCM")) != NULL)
677                {
678                    strncpy(hw_cfg_cb.local_chip_name, p_name, \
679                            LOCAL_NAME_BUFFER_LEN-1);
680                }
681#ifdef USE_BLUETOOTH_BCM4343
682                else if ((p_name = strstr(p_tmp, "4343")) != NULL)
683                {
684                    snprintf(hw_cfg_cb.local_chip_name,
685                             LOCAL_NAME_BUFFER_LEN-1, "BCM%s", p_name);
686                    strncpy(p_name, hw_cfg_cb.local_chip_name,
687                            LOCAL_NAME_BUFFER_LEN-1);
688                }
689#endif
690                else
691                {
692                    strncpy(hw_cfg_cb.local_chip_name, "UNKNOWN", \
693                            LOCAL_NAME_BUFFER_LEN-1);
694                    p_name = p_tmp;
695                }
696
697                hw_cfg_cb.local_chip_name[LOCAL_NAME_BUFFER_LEN-1] = 0;
698
699                BTHWDBG("Chipset %s", hw_cfg_cb.local_chip_name);
700
701                if ((status = hw_config_findpatch(p_name)) == TRUE)
702                {
703                    if ((hw_cfg_cb.fw_fd = open(p_name, O_RDONLY)) == -1)
704                    {
705                        ALOGE("vendor lib preload failed to open [%s]", p_name);
706                    }
707                    else
708                    {
709                        /* vsc_download_minidriver */
710                        UINT16_TO_STREAM(p, HCI_VSC_DOWNLOAD_MINIDRV);
711                        *p = 0; /* parameter length */
712
713                        p_buf->len = HCI_CMD_PREAMBLE_SIZE;
714                        hw_cfg_cb.state = HW_CFG_DL_MINIDRIVER;
715
716                        is_proceeding = bt_vendor_cbacks->xmit_cb( \
717                                            HCI_VSC_DOWNLOAD_MINIDRV, p_buf, \
718                                            hw_config_cback);
719                    }
720                }
721                else
722                {
723                    ALOGE( \
724                    "vendor lib preload failed to locate firmware patch file" \
725                    );
726                }
727
728                if (is_proceeding == FALSE)
729                {
730                    is_proceeding = hw_config_set_bdaddr(p_buf);
731                }
732                break;
733
734            case HW_CFG_DL_MINIDRIVER:
735                /* give time for placing firmware in download mode */
736                ms_delay(50);
737                hw_cfg_cb.state = HW_CFG_DL_FW_PATCH;
738                /* fall through intentionally */
739            case HW_CFG_DL_FW_PATCH:
740                p_buf->len = read(hw_cfg_cb.fw_fd, p, HCI_CMD_PREAMBLE_SIZE);
741                if (p_buf->len > 0)
742                {
743                    if ((p_buf->len < HCI_CMD_PREAMBLE_SIZE) || \
744                        (opcode == HCI_VSC_LAUNCH_RAM))
745                    {
746                        ALOGW("firmware patch file might be altered!");
747                    }
748                    else
749                    {
750                        p_buf->len += read(hw_cfg_cb.fw_fd, \
751                                           p+HCI_CMD_PREAMBLE_SIZE,\
752                                           *(p+HCD_REC_PAYLOAD_LEN_BYTE));
753                        STREAM_TO_UINT16(opcode,p);
754                        is_proceeding = bt_vendor_cbacks->xmit_cb(opcode, \
755                                                p_buf, hw_config_cback);
756                        break;
757                    }
758                }
759
760                close(hw_cfg_cb.fw_fd);
761                hw_cfg_cb.fw_fd = -1;
762
763                /* Normally the firmware patch configuration file
764                 * sets the new starting baud rate at 115200.
765                 * So, we need update host's baud rate accordingly.
766                 */
767                ALOGI("bt vendor lib: set UART baud 115200");
768                userial_vendor_set_baud(USERIAL_BAUD_115200);
769
770                /* Next, we would like to boost baud rate up again
771                 * to desired working speed.
772                 */
773                hw_cfg_cb.f_set_baud_2 = TRUE;
774
775                /* Check if we need to pause a few hundred milliseconds
776                 * before sending down any HCI command.
777                 */
778                delay = look_up_fw_settlement_delay();
779                ALOGI("Setting fw settlement delay to %d ", delay);
780                ms_delay(delay);
781
782                p_buf->len = HCI_CMD_PREAMBLE_SIZE;
783                UINT16_TO_STREAM(p, HCI_RESET);
784                *p = 0; /* parameter length */
785                hw_cfg_cb.state = HW_CFG_START;
786                is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf, hw_config_cback);
787                break;
788
789            case HW_CFG_START:
790                if (UART_TARGET_BAUD_RATE > 3000000)
791                {
792                    /* set UART clock to 48MHz */
793                    UINT16_TO_STREAM(p, HCI_VSC_WRITE_UART_CLOCK_SETTING);
794                    *p++ = 1; /* parameter length */
795                    *p = 1; /* (1,"UART CLOCK 48 MHz")(2,"UART CLOCK 24 MHz") */
796
797                    p_buf->len = HCI_CMD_PREAMBLE_SIZE + 1;
798                    hw_cfg_cb.state = HW_CFG_SET_UART_CLOCK;
799
800                    is_proceeding = bt_vendor_cbacks->xmit_cb( \
801                                        HCI_VSC_WRITE_UART_CLOCK_SETTING, \
802                                        p_buf, hw_config_cback);
803                    break;
804                }
805                /* fall through intentionally */
806            case HW_CFG_SET_UART_CLOCK:
807                /* set controller's UART baud rate to 3M */
808                UINT16_TO_STREAM(p, HCI_VSC_UPDATE_BAUDRATE);
809                *p++ = UPDATE_BAUDRATE_CMD_PARAM_SIZE; /* parameter length */
810                *p++ = 0; /* encoded baud rate */
811                *p++ = 0; /* use encoded form */
812                UINT32_TO_STREAM(p, UART_TARGET_BAUD_RATE);
813
814                p_buf->len = HCI_CMD_PREAMBLE_SIZE + \
815                             UPDATE_BAUDRATE_CMD_PARAM_SIZE;
816                hw_cfg_cb.state = (hw_cfg_cb.f_set_baud_2) ? \
817                            HW_CFG_SET_UART_BAUD_2 : HW_CFG_SET_UART_BAUD_1;
818
819                is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_VSC_UPDATE_BAUDRATE, \
820                                                    p_buf, hw_config_cback);
821                break;
822
823            case HW_CFG_SET_UART_BAUD_2:
824                /* update baud rate of host's UART port */
825                ALOGI("bt vendor lib: set UART baud %i", UART_TARGET_BAUD_RATE);
826                userial_vendor_set_baud( \
827                    line_speed_to_userial_baud(UART_TARGET_BAUD_RATE) \
828                );
829
830#if (USE_CONTROLLER_BDADDR == TRUE)
831                if ((is_proceeding = hw_config_read_bdaddr(p_buf)) == TRUE)
832                    break;
833#else
834                if ((is_proceeding = hw_config_set_bdaddr(p_buf)) == TRUE)
835                    break;
836#endif
837                /* fall through intentionally */
838            case HW_CFG_SET_BD_ADDR:
839                ALOGI("vendor lib fwcfg completed");
840                bt_vendor_cbacks->dealloc(p_buf);
841                bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
842
843                hw_cfg_cb.state = 0;
844
845                if (hw_cfg_cb.fw_fd != -1)
846                {
847                    close(hw_cfg_cb.fw_fd);
848                    hw_cfg_cb.fw_fd = -1;
849                }
850
851                is_proceeding = TRUE;
852                break;
853
854#if (USE_CONTROLLER_BDADDR == TRUE)
855            case HW_CFG_READ_BD_ADDR:
856                p_tmp = (char *) (p_evt_buf + 1) + \
857                         HCI_EVT_CMD_CMPL_LOCAL_BDADDR_ARRAY;
858
859                if (memcmp(p_tmp, null_bdaddr, BD_ADDR_LEN) == 0)
860                {
861                    // Controller does not have a valid OTP BDADDR!
862                    // Set the BTIF initial BDADDR instead.
863                    if ((is_proceeding = hw_config_set_bdaddr(p_buf)) == TRUE)
864                        break;
865                }
866                else
867                {
868                    ALOGI("Controller OTP bdaddr %02X:%02X:%02X:%02X:%02X:%02X",
869                        *(p_tmp+5), *(p_tmp+4), *(p_tmp+3),
870                        *(p_tmp+2), *(p_tmp+1), *p_tmp);
871                }
872
873                ALOGI("vendor lib fwcfg completed");
874                bt_vendor_cbacks->dealloc(p_buf);
875                bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
876
877                hw_cfg_cb.state = 0;
878
879                if (hw_cfg_cb.fw_fd != -1)
880                {
881                    close(hw_cfg_cb.fw_fd);
882                    hw_cfg_cb.fw_fd = -1;
883                }
884
885                is_proceeding = TRUE;
886                break;
887#endif // (USE_CONTROLLER_BDADDR == TRUE)
888        } // switch(hw_cfg_cb.state)
889    } // if (p_buf != NULL)
890
891    /* Free the RX event buffer */
892    if (bt_vendor_cbacks)
893        bt_vendor_cbacks->dealloc(p_evt_buf);
894
895    if (is_proceeding == FALSE)
896    {
897        ALOGE("vendor lib fwcfg aborted!!!");
898        if (bt_vendor_cbacks)
899        {
900            if (p_buf != NULL)
901                bt_vendor_cbacks->dealloc(p_buf);
902
903            bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
904        }
905
906        if (hw_cfg_cb.fw_fd != -1)
907        {
908            close(hw_cfg_cb.fw_fd);
909            hw_cfg_cb.fw_fd = -1;
910        }
911
912        hw_cfg_cb.state = 0;
913    }
914}
915
916/******************************************************************************
917**   LPM Static Functions
918******************************************************************************/
919
920/*******************************************************************************
921**
922** Function         hw_lpm_ctrl_cback
923**
924** Description      Callback function for lpm enable/disable rquest
925**
926** Returns          None
927**
928*******************************************************************************/
929void hw_lpm_ctrl_cback(void *p_mem)
930{
931    HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
932    bt_vendor_op_result_t status = BT_VND_OP_RESULT_FAIL;
933
934    if (*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0)
935    {
936        status = BT_VND_OP_RESULT_SUCCESS;
937    }
938
939    if (bt_vendor_cbacks)
940    {
941        bt_vendor_cbacks->lpm_cb(status);
942        bt_vendor_cbacks->dealloc(p_evt_buf);
943    }
944}
945
946
947#if (SCO_CFG_INCLUDED == TRUE)
948/*****************************************************************************
949**   SCO Configuration Static Functions
950*****************************************************************************/
951
952/*******************************************************************************
953**
954** Function         hw_sco_i2spcm_cfg_cback
955**
956** Description      Callback function for SCO I2S/PCM configuration rquest
957**
958** Returns          None
959**
960*******************************************************************************/
961static void hw_sco_i2spcm_cfg_cback(void *p_mem)
962{
963    HC_BT_HDR   *p_evt_buf = (HC_BT_HDR *)p_mem;
964    uint8_t     *p;
965    uint16_t    opcode;
966    HC_BT_HDR   *p_buf = NULL;
967    bt_vendor_op_result_t status = BT_VND_OP_RESULT_FAIL;
968
969    p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
970    STREAM_TO_UINT16(opcode,p);
971
972    if (*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0)
973    {
974        status = BT_VND_OP_RESULT_SUCCESS;
975    }
976
977    /* Free the RX event buffer */
978    if (bt_vendor_cbacks)
979        bt_vendor_cbacks->dealloc(p_evt_buf);
980
981    if (status == BT_VND_OP_RESULT_SUCCESS)
982    {
983        if ((opcode == HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM) &&
984            (SCO_INTERFACE_PCM == sco_bus_interface))
985        {
986            uint8_t ret = FALSE;
987
988            /* Ask a new buffer to hold WRITE_SCO_PCM_INT_PARAM command */
989            if (bt_vendor_cbacks)
990                p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(
991                        BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + SCO_PCM_PARAM_SIZE);
992            if (p_buf)
993            {
994                p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
995                p_buf->offset = 0;
996                p_buf->layer_specific = 0;
997                p_buf->len = HCI_CMD_PREAMBLE_SIZE + SCO_PCM_PARAM_SIZE;
998                p = (uint8_t *)(p_buf + 1);
999
1000                /* do we need this VSC for I2S??? */
1001                UINT16_TO_STREAM(p, HCI_VSC_WRITE_SCO_PCM_INT_PARAM);
1002                *p++ = SCO_PCM_PARAM_SIZE;
1003                memcpy(p, &bt_sco_param, SCO_PCM_PARAM_SIZE);
1004                ALOGI("SCO PCM configure {0x%x, 0x%x, 0x%x, 0x%x, 0x%x}",
1005                        bt_sco_param[0], bt_sco_param[1], bt_sco_param[2], bt_sco_param[3],
1006                        bt_sco_param[4]);
1007                if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_SCO_PCM_INT_PARAM, p_buf,
1008                        hw_sco_i2spcm_cfg_cback)) == FALSE)
1009                {
1010                    bt_vendor_cbacks->dealloc(p_buf);
1011                }
1012                else
1013                    return;
1014            }
1015            status = BT_VND_OP_RESULT_FAIL;
1016        }
1017        else if ((opcode == HCI_VSC_WRITE_SCO_PCM_INT_PARAM) &&
1018                 (SCO_INTERFACE_PCM == sco_bus_interface))
1019        {
1020            uint8_t ret = FALSE;
1021
1022            /* Ask a new buffer to hold WRITE_PCM_DATA_FORMAT_PARAM command */
1023            if (bt_vendor_cbacks)
1024                p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(
1025                        BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + PCM_DATA_FORMAT_PARAM_SIZE);
1026            if (p_buf)
1027            {
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 + PCM_DATA_FORMAT_PARAM_SIZE;
1032
1033                p = (uint8_t *)(p_buf + 1);
1034                UINT16_TO_STREAM(p, HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM);
1035                *p++ = PCM_DATA_FORMAT_PARAM_SIZE;
1036                memcpy(p, &bt_pcm_data_fmt_param, PCM_DATA_FORMAT_PARAM_SIZE);
1037
1038                ALOGI("SCO PCM data format {0x%x, 0x%x, 0x%x, 0x%x, 0x%x}",
1039                        bt_pcm_data_fmt_param[0], bt_pcm_data_fmt_param[1],
1040                        bt_pcm_data_fmt_param[2], bt_pcm_data_fmt_param[3],
1041                        bt_pcm_data_fmt_param[4]);
1042
1043                if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM,
1044                        p_buf, hw_sco_i2spcm_cfg_cback)) == FALSE)
1045                {
1046                    bt_vendor_cbacks->dealloc(p_buf);
1047                }
1048                else
1049                    return;
1050            }
1051            status = BT_VND_OP_RESULT_FAIL;
1052        }
1053    }
1054
1055    ALOGI("sco I2S/PCM config result %d [0-Success, 1-Fail]", status);
1056    if (bt_vendor_cbacks)
1057    {
1058        bt_vendor_cbacks->audio_state_cb(status);
1059    }
1060}
1061
1062/*******************************************************************************
1063**
1064** Function         hw_set_MSBC_codec_cback
1065**
1066** Description      Callback function for setting WBS codec
1067**
1068** Returns          None
1069**
1070*******************************************************************************/
1071static void hw_set_MSBC_codec_cback(void *p_mem)
1072{
1073    /* whenever update the codec enable/disable, need to update I2SPCM */
1074    ALOGI("SCO I2S interface change the sample rate to 16K");
1075    hw_sco_i2spcm_config_from_command(p_mem, SCO_CODEC_MSBC);
1076}
1077
1078/*******************************************************************************
1079**
1080** Function         hw_set_CVSD_codec_cback
1081**
1082** Description      Callback function for setting NBS codec
1083**
1084** Returns          None
1085**
1086*******************************************************************************/
1087static void hw_set_CVSD_codec_cback(void *p_mem)
1088{
1089    /* whenever update the codec enable/disable, need to update I2SPCM */
1090    ALOGI("SCO I2S interface change the sample rate to 8K");
1091    hw_sco_i2spcm_config_from_command(p_mem, SCO_CODEC_CVSD);
1092}
1093
1094#endif // SCO_CFG_INCLUDED
1095
1096/*****************************************************************************
1097**   Hardware Configuration Interface Functions
1098*****************************************************************************/
1099
1100
1101/*******************************************************************************
1102**
1103** Function        hw_config_start
1104**
1105** Description     Kick off controller initialization process
1106**
1107** Returns         None
1108**
1109*******************************************************************************/
1110void hw_config_start(void)
1111{
1112    HC_BT_HDR  *p_buf = NULL;
1113    uint8_t     *p;
1114
1115    hw_cfg_cb.state = 0;
1116    hw_cfg_cb.fw_fd = -1;
1117    hw_cfg_cb.f_set_baud_2 = FALSE;
1118
1119    /* Start from sending HCI_RESET */
1120
1121    if (bt_vendor_cbacks)
1122    {
1123        p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
1124                                                       HCI_CMD_PREAMBLE_SIZE);
1125    }
1126
1127    if (p_buf)
1128    {
1129        p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1130        p_buf->offset = 0;
1131        p_buf->layer_specific = 0;
1132        p_buf->len = HCI_CMD_PREAMBLE_SIZE;
1133
1134        p = (uint8_t *) (p_buf + 1);
1135        UINT16_TO_STREAM(p, HCI_RESET);
1136        *p = 0; /* parameter length */
1137
1138        hw_cfg_cb.state = HW_CFG_START;
1139
1140        bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf, hw_config_cback);
1141    }
1142    else
1143    {
1144        if (bt_vendor_cbacks)
1145        {
1146            ALOGE("vendor lib fw conf aborted [no buffer]");
1147            bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
1148        }
1149    }
1150}
1151
1152/*******************************************************************************
1153**
1154** Function        hw_lpm_enable
1155**
1156** Description     Enalbe/Disable LPM
1157**
1158** Returns         TRUE/FALSE
1159**
1160*******************************************************************************/
1161uint8_t hw_lpm_enable(uint8_t turn_on)
1162{
1163    HC_BT_HDR  *p_buf = NULL;
1164    uint8_t     *p;
1165    uint8_t     ret = FALSE;
1166
1167    if (bt_vendor_cbacks)
1168        p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
1169                                                       HCI_CMD_PREAMBLE_SIZE + \
1170                                                       LPM_CMD_PARAM_SIZE);
1171
1172    if (p_buf)
1173    {
1174        p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1175        p_buf->offset = 0;
1176        p_buf->layer_specific = 0;
1177        p_buf->len = HCI_CMD_PREAMBLE_SIZE + LPM_CMD_PARAM_SIZE;
1178
1179        p = (uint8_t *) (p_buf + 1);
1180        UINT16_TO_STREAM(p, HCI_VSC_WRITE_SLEEP_MODE);
1181        *p++ = LPM_CMD_PARAM_SIZE; /* parameter length */
1182
1183        if (turn_on)
1184        {
1185            memcpy(p, &lpm_param, LPM_CMD_PARAM_SIZE);
1186            upio_set(UPIO_LPM_MODE, UPIO_ASSERT, 0);
1187        }
1188        else
1189        {
1190            memset(p, 0, LPM_CMD_PARAM_SIZE);
1191            upio_set(UPIO_LPM_MODE, UPIO_DEASSERT, 0);
1192        }
1193
1194        if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_SLEEP_MODE, p_buf, \
1195                                        hw_lpm_ctrl_cback)) == FALSE)
1196        {
1197            bt_vendor_cbacks->dealloc(p_buf);
1198        }
1199    }
1200
1201    if ((ret == FALSE) && bt_vendor_cbacks)
1202        bt_vendor_cbacks->lpm_cb(BT_VND_OP_RESULT_FAIL);
1203
1204    return ret;
1205}
1206
1207/*******************************************************************************
1208**
1209** Function        hw_lpm_get_idle_timeout
1210**
1211** Description     Calculate idle time based on host stack idle threshold
1212**
1213** Returns         idle timeout value
1214**
1215*******************************************************************************/
1216uint32_t hw_lpm_get_idle_timeout(void)
1217{
1218    uint32_t timeout_ms;
1219
1220    /* set idle time to be LPM_IDLE_TIMEOUT_MULTIPLE times of
1221     * host stack idle threshold (in 300ms/25ms)
1222     */
1223    timeout_ms = (uint32_t)lpm_param.host_stack_idle_threshold \
1224                            * LPM_IDLE_TIMEOUT_MULTIPLE;
1225    if (strstr(hw_cfg_cb.local_chip_name, "BCM4325") != NULL)
1226        timeout_ms *= 25; // 12.5 or 25 ?
1227    else if (strstr(hw_cfg_cb.local_chip_name, "BCM4358") != NULL)
1228        timeout_ms *= 50;
1229    else
1230        timeout_ms *= 300;
1231
1232    return timeout_ms;
1233}
1234
1235/*******************************************************************************
1236**
1237** Function        hw_lpm_set_wake_state
1238**
1239** Description     Assert/Deassert BT_WAKE
1240**
1241** Returns         None
1242**
1243*******************************************************************************/
1244void hw_lpm_set_wake_state(uint8_t wake_assert)
1245{
1246    uint8_t state = (wake_assert) ? UPIO_ASSERT : UPIO_DEASSERT;
1247
1248    upio_set(UPIO_BT_WAKE, state, lpm_param.bt_wake_polarity);
1249}
1250
1251#if (SCO_CFG_INCLUDED == TRUE)
1252/*******************************************************************************
1253**
1254** Function         hw_sco_config
1255**
1256** Description      Configure SCO related hardware settings
1257**
1258** Returns          None
1259**
1260*******************************************************************************/
1261void hw_sco_config(void)
1262{
1263    if (SCO_INTERFACE_I2S == sco_bus_interface)
1264    {
1265        /* 'Enable' I2S mode */
1266        bt_sco_i2spcm_param[0] = 1;
1267
1268        /* set nbs clock rate as the value in SCO_I2SPCM_IF_CLOCK_RATE field */
1269        sco_bus_clock_rate = bt_sco_i2spcm_param[3];
1270    }
1271    else
1272    {
1273        /* 'Disable' I2S mode */
1274        bt_sco_i2spcm_param[0] = 0;
1275
1276        /* set nbs clock rate as the value in SCO_PCM_IF_CLOCK_RATE field */
1277        sco_bus_clock_rate = bt_sco_param[1];
1278
1279        /* sync up clock mode setting */
1280        bt_sco_i2spcm_param[1] = bt_sco_param[4];
1281    }
1282
1283    if (sco_bus_wbs_clock_rate == INVALID_SCO_CLOCK_RATE)
1284    {
1285        /* set default wbs clock rate */
1286        sco_bus_wbs_clock_rate = SCO_I2SPCM_IF_CLOCK_RATE4WBS;
1287
1288        if (sco_bus_wbs_clock_rate < sco_bus_clock_rate)
1289            sco_bus_wbs_clock_rate = sco_bus_clock_rate;
1290    }
1291
1292    /*
1293     *  To support I2S/PCM port multiplexing signals for sharing Bluetooth audio
1294     *  and FM on the same PCM pins, we defer Bluetooth audio (SCO/eSCO)
1295     *  configuration till SCO/eSCO is being established;
1296     *  i.e. in hw_set_audio_state() call.
1297     *  When configured as I2S only, Bluetooth audio configuration is executed
1298     *  immediately with SCO_CODEC_CVSD by default.
1299     */
1300
1301    if (SCO_INTERFACE_I2S == sco_bus_interface) {
1302        hw_sco_i2spcm_config(SCO_CODEC_CVSD);
1303    }
1304
1305    if (bt_vendor_cbacks)
1306    {
1307        bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_SUCCESS);
1308    }
1309}
1310
1311static void hw_sco_i2spcm_config_from_command(void *p_mem, uint16_t codec) {
1312    HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem;
1313    bool command_success = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0;
1314
1315    /* Free the RX event buffer */
1316    if (bt_vendor_cbacks)
1317        bt_vendor_cbacks->dealloc(p_evt_buf);
1318
1319    if (command_success)
1320        hw_sco_i2spcm_config(codec);
1321    else if (bt_vendor_cbacks)
1322        bt_vendor_cbacks->audio_state_cb(BT_VND_OP_RESULT_FAIL);
1323}
1324
1325
1326/*******************************************************************************
1327**
1328** Function         hw_sco_i2spcm_config
1329**
1330** Description      Configure SCO over I2S or PCM
1331**
1332** Returns          None
1333**
1334*******************************************************************************/
1335static void hw_sco_i2spcm_config(uint16_t codec)
1336{
1337    HC_BT_HDR *p_buf = NULL;
1338    uint8_t *p, ret;
1339    uint16_t cmd_u16 = HCI_CMD_PREAMBLE_SIZE + SCO_I2SPCM_PARAM_SIZE;
1340
1341    if (bt_vendor_cbacks)
1342        p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + cmd_u16);
1343
1344    if (p_buf)
1345    {
1346        p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1347        p_buf->offset = 0;
1348        p_buf->layer_specific = 0;
1349        p_buf->len = cmd_u16;
1350
1351        p = (uint8_t *)(p_buf + 1);
1352
1353        UINT16_TO_STREAM(p, HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM);
1354        *p++ = SCO_I2SPCM_PARAM_SIZE;
1355        if (codec == SCO_CODEC_CVSD)
1356        {
1357            bt_sco_i2spcm_param[2] = 0; /* SCO_I2SPCM_IF_SAMPLE_RATE  8k */
1358            bt_sco_i2spcm_param[3] = bt_sco_param[1] = sco_bus_clock_rate;
1359        }
1360        else if (codec == SCO_CODEC_MSBC)
1361        {
1362            bt_sco_i2spcm_param[2] = wbs_sample_rate; /* SCO_I2SPCM_IF_SAMPLE_RATE 16K */
1363            bt_sco_i2spcm_param[3] = bt_sco_param[1] = sco_bus_wbs_clock_rate;
1364        }
1365        else
1366        {
1367            bt_sco_i2spcm_param[2] = 0; /* SCO_I2SPCM_IF_SAMPLE_RATE  8k */
1368            bt_sco_i2spcm_param[3] = bt_sco_param[1] = sco_bus_clock_rate;
1369            ALOGE("wrong codec is use in hw_sco_i2spcm_config, goes default NBS");
1370        }
1371        memcpy(p, &bt_sco_i2spcm_param, SCO_I2SPCM_PARAM_SIZE);
1372        cmd_u16 = HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM;
1373        ALOGI("I2SPCM config {0x%x, 0x%x, 0x%x, 0x%x}",
1374                bt_sco_i2spcm_param[0], bt_sco_i2spcm_param[1],
1375                bt_sco_i2spcm_param[2], bt_sco_i2spcm_param[3]);
1376
1377        if ((ret = bt_vendor_cbacks->xmit_cb(cmd_u16, p_buf, hw_sco_i2spcm_cfg_cback)) == FALSE)
1378        {
1379            bt_vendor_cbacks->dealloc(p_buf);
1380        }
1381        else
1382            return;
1383    }
1384
1385    bt_vendor_cbacks->audio_state_cb(BT_VND_OP_RESULT_FAIL);
1386}
1387
1388/*******************************************************************************
1389**
1390** Function         hw_set_SCO_codec
1391**
1392** Description      This functgion sends command to the controller to setup
1393**                              WBS/NBS codec for the upcoming eSCO connection.
1394**
1395** Returns          -1 : Failed to send VSC
1396**                   0 : Success
1397**
1398*******************************************************************************/
1399static int hw_set_SCO_codec(uint16_t codec)
1400{
1401    HC_BT_HDR   *p_buf = NULL;
1402    uint8_t     *p;
1403    uint8_t     ret;
1404    int         ret_val = 0;
1405    tINT_CMD_CBACK p_set_SCO_codec_cback;
1406
1407    BTHWDBG( "hw_set_SCO_codec 0x%x", codec);
1408
1409    if (bt_vendor_cbacks)
1410        p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(
1411                BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + SCO_CODEC_PARAM_SIZE);
1412
1413    if (p_buf)
1414    {
1415        p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1416        p_buf->offset = 0;
1417        p_buf->layer_specific = 0;
1418        p = (uint8_t *)(p_buf + 1);
1419
1420        UINT16_TO_STREAM(p, HCI_VSC_ENABLE_WBS);
1421
1422        if (codec == SCO_CODEC_MSBC)
1423        {
1424            /* Enable mSBC */
1425            *p++ = SCO_CODEC_PARAM_SIZE; /* set the parameter size */
1426            UINT8_TO_STREAM(p,1); /* enable */
1427            UINT16_TO_STREAM(p, codec);
1428
1429            /* set the totall size of this packet */
1430            p_buf->len = HCI_CMD_PREAMBLE_SIZE + SCO_CODEC_PARAM_SIZE;
1431
1432            p_set_SCO_codec_cback = hw_set_MSBC_codec_cback;
1433        }
1434        else
1435        {
1436            /* Disable mSBC */
1437            *p++ = (SCO_CODEC_PARAM_SIZE - 2); /* set the parameter size */
1438            UINT8_TO_STREAM(p,0); /* disable */
1439
1440            /* set the totall size of this packet */
1441            p_buf->len = HCI_CMD_PREAMBLE_SIZE + SCO_CODEC_PARAM_SIZE - 2;
1442
1443            p_set_SCO_codec_cback = hw_set_CVSD_codec_cback;
1444            if ((codec != SCO_CODEC_CVSD) && (codec != SCO_CODEC_NONE))
1445            {
1446                ALOGW("SCO codec setting is wrong: codec: 0x%x", codec);
1447            }
1448        }
1449
1450        if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_ENABLE_WBS, p_buf, p_set_SCO_codec_cback))\
1451              == FALSE)
1452        {
1453            bt_vendor_cbacks->dealloc(p_buf);
1454            ret_val = -1;
1455        }
1456    }
1457    else
1458    {
1459        ret_val = -1;
1460    }
1461
1462    return ret_val;
1463}
1464
1465/*******************************************************************************
1466**
1467** Function         hw_set_audio_state
1468**
1469** Description      This function configures audio base on provided audio state
1470**
1471** Paramters        pointer to audio state structure
1472**
1473** Returns          0: ok, -1: error
1474**
1475*******************************************************************************/
1476int hw_set_audio_state(bt_vendor_op_audio_state_t *p_state)
1477{
1478    int ret_val = -1;
1479
1480    if (!bt_vendor_cbacks)
1481        return ret_val;
1482
1483    ret_val = hw_set_SCO_codec(p_state->peer_codec);
1484    return ret_val;
1485}
1486
1487#else  // SCO_CFG_INCLUDED
1488int hw_set_audio_state(bt_vendor_op_audio_state_t *p_state)
1489{
1490    return -256;
1491}
1492#endif
1493/*******************************************************************************
1494**
1495** Function        hw_set_patch_file_path
1496**
1497** Description     Set the location of firmware patch file
1498**
1499** Returns         0 : Success
1500**                 Otherwise : Fail
1501**
1502*******************************************************************************/
1503int hw_set_patch_file_path(char *p_conf_name, char *p_conf_value, int param)
1504{
1505
1506    strcpy(fw_patchfile_path, p_conf_value);
1507
1508    return 0;
1509}
1510
1511/*******************************************************************************
1512**
1513** Function        hw_set_patch_file_name
1514**
1515** Description     Give the specific firmware patch filename
1516**
1517** Returns         0 : Success
1518**                 Otherwise : Fail
1519**
1520*******************************************************************************/
1521int hw_set_patch_file_name(char *p_conf_name, char *p_conf_value, int param)
1522{
1523
1524    strcpy(fw_patchfile_name, p_conf_value);
1525
1526    return 0;
1527}
1528
1529#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
1530/*******************************************************************************
1531**
1532** Function        hw_set_patch_settlement_delay
1533**
1534** Description     Give the specific firmware patch settlement time in milliseconds
1535**
1536** Returns         0 : Success
1537**                 Otherwise : Fail
1538**
1539*******************************************************************************/
1540int hw_set_patch_settlement_delay(char *p_conf_name, char *p_conf_value, int param)
1541{
1542    fw_patch_settlement_delay = atoi(p_conf_value);
1543
1544    return 0;
1545}
1546#endif  //VENDOR_LIB_RUNTIME_TUNING_ENABLED
1547
1548/*****************************************************************************
1549**   Sample Codes Section
1550*****************************************************************************/
1551
1552#if (HW_END_WITH_HCI_RESET == TRUE)
1553/*******************************************************************************
1554**
1555** Function         hw_epilog_cback
1556**
1557** Description      Callback function for Command Complete Events from HCI
1558**                  commands sent in epilog process.
1559**
1560** Returns          None
1561**
1562*******************************************************************************/
1563void hw_epilog_cback(void *p_mem)
1564{
1565    HC_BT_HDR   *p_evt_buf = (HC_BT_HDR *) p_mem;
1566    uint8_t     *p, status;
1567    uint16_t    opcode;
1568
1569    status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
1570    p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
1571    STREAM_TO_UINT16(opcode,p);
1572
1573    BTHWDBG("%s Opcode:0x%04X Status: %d", __FUNCTION__, opcode, status);
1574
1575    if (bt_vendor_cbacks)
1576    {
1577        /* Must free the RX event buffer */
1578        bt_vendor_cbacks->dealloc(p_evt_buf);
1579
1580        /* Once epilog process is done, must call epilog_cb callback
1581           to notify caller */
1582        bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
1583    }
1584}
1585
1586/*******************************************************************************
1587**
1588** Function         hw_epilog_process
1589**
1590** Description      Sample implementation of epilog process
1591**
1592** Returns          None
1593**
1594*******************************************************************************/
1595void hw_epilog_process(void)
1596{
1597    HC_BT_HDR  *p_buf = NULL;
1598    uint8_t     *p;
1599
1600    BTHWDBG("hw_epilog_process");
1601
1602    /* Sending a HCI_RESET */
1603    if (bt_vendor_cbacks)
1604    {
1605        /* Must allocate command buffer via HC's alloc API */
1606        p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
1607                                                       HCI_CMD_PREAMBLE_SIZE);
1608    }
1609
1610    if (p_buf)
1611    {
1612        p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1613        p_buf->offset = 0;
1614        p_buf->layer_specific = 0;
1615        p_buf->len = HCI_CMD_PREAMBLE_SIZE;
1616
1617        p = (uint8_t *) (p_buf + 1);
1618        UINT16_TO_STREAM(p, HCI_RESET);
1619        *p = 0; /* parameter length */
1620
1621        /* Send command via HC's xmit_cb API */
1622        bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf, hw_epilog_cback);
1623    }
1624    else
1625    {
1626        if (bt_vendor_cbacks)
1627        {
1628            ALOGE("vendor lib epilog process aborted [no buffer]");
1629            bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_FAIL);
1630        }
1631    }
1632}
1633#endif // (HW_END_WITH_HCI_RESET == TRUE)
1634