• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2009-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /******************************************************************************
20  *
21  *  Filename:      hardware.c
22  *
23  *  Description:   Contains controller-specific functions, like
24  *                      firmware patch download
25  *                      low power mode operations
26  *
27  ******************************************************************************/
28 
29 #define LOG_TAG "bt_hwcfg"
30 
31 #include <utils/Log.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <signal.h>
35 #include <time.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <dirent.h>
39 #include <ctype.h>
40 #include <cutils/properties.h>
41 #include <stdlib.h>
42 #include "bt_hci_bdroid.h"
43 #include "bt_vendor_brcm.h"
44 #include "userial.h"
45 #include "userial_vendor.h"
46 #include "upio.h"
47 
48 /******************************************************************************
49 **  Constants & Macros
50 ******************************************************************************/
51 
52 #ifndef BTHW_DBG
53 #define BTHW_DBG FALSE
54 #endif
55 
56 #if (BTHW_DBG == TRUE)
57 #define BTHWDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
58 #else
59 #define BTHWDBG(param, ...) {}
60 #endif
61 
62 #define FW_PATCHFILE_EXTENSION      ".hcd"
63 #define FW_PATCHFILE_EXTENSION_LEN  4
64 #define FW_PATCHFILE_PATH_MAXLEN    248 /* Local_Name length of return of
65                                            HCI_Read_Local_Name */
66 
67 #define HCI_CMD_MAX_LEN             258
68 
69 #define HCI_RESET                               0x0C03
70 #define HCI_VSC_WRITE_UART_CLOCK_SETTING        0xFC45
71 #define HCI_VSC_UPDATE_BAUDRATE                 0xFC18
72 #define HCI_READ_LOCAL_NAME                     0x0C14
73 #define HCI_VSC_DOWNLOAD_MINIDRV                0xFC2E
74 #define HCI_VSC_WRITE_BD_ADDR                   0xFC01
75 #define HCI_VSC_WRITE_SLEEP_MODE                0xFC27
76 #define HCI_VSC_WRITE_SCO_PCM_INT_PARAM         0xFC1C
77 #define HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM     0xFC1E
78 #define HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM    0xFC6D
79 #define HCI_VSC_LAUNCH_RAM                      0xFC4E
80 #define HCI_READ_LOCAL_BDADDR                   0x1009
81 
82 #define HCI_EVT_CMD_CMPL_STATUS_RET_BYTE        5
83 #define HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING      6
84 #define HCI_EVT_CMD_CMPL_LOCAL_BDADDR_ARRAY     6
85 #define HCI_EVT_CMD_CMPL_OPCODE                 3
86 #define LPM_CMD_PARAM_SIZE                      12
87 #define UPDATE_BAUDRATE_CMD_PARAM_SIZE          6
88 #define HCI_CMD_PREAMBLE_SIZE                   3
89 #define HCD_REC_PAYLOAD_LEN_BYTE                2
90 #define BD_ADDR_LEN                             6
91 #define LOCAL_NAME_BUFFER_LEN                   32
92 #define LOCAL_BDADDR_PATH_BUFFER_LEN            256
93 
94 #define STREAM_TO_UINT16(u16, p) {u16 = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); (p) += 2;}
95 #define UINT16_TO_STREAM(p, u16) {*(p)++ = (uint8_t)(u16); *(p)++ = (uint8_t)((u16) >> 8);}
96 #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);}
97 
98 /******************************************************************************
99 **  Local type definitions
100 ******************************************************************************/
101 
102 /* Hardware Configuration State */
103 enum {
104     HW_CFG_START = 1,
105     HW_CFG_SET_UART_CLOCK,
106     HW_CFG_SET_UART_BAUD_1,
107     HW_CFG_READ_LOCAL_NAME,
108     HW_CFG_DL_MINIDRIVER,
109     HW_CFG_DL_FW_PATCH,
110     HW_CFG_SET_UART_BAUD_2,
111     HW_CFG_SET_BD_ADDR
112 #if (USE_CONTROLLER_BDADDR == TRUE)
113     , HW_CFG_READ_BD_ADDR
114 #endif
115 };
116 
117 /* h/w config control block */
118 typedef struct
119 {
120     uint8_t state;                          /* Hardware configuration state */
121     int     fw_fd;                          /* FW patch file fd */
122     uint8_t f_set_baud_2;                   /* Baud rate switch state */
123     char    local_chip_name[LOCAL_NAME_BUFFER_LEN];
124 } bt_hw_cfg_cb_t;
125 
126 /* low power mode parameters */
127 typedef struct
128 {
129     uint8_t sleep_mode;                     /* 0(disable),1(UART),9(H5) */
130     uint8_t host_stack_idle_threshold;      /* Unit scale 300ms/25ms */
131     uint8_t host_controller_idle_threshold; /* Unit scale 300ms/25ms */
132     uint8_t bt_wake_polarity;               /* 0=Active Low, 1= Active High */
133     uint8_t host_wake_polarity;             /* 0=Active Low, 1= Active High */
134     uint8_t allow_host_sleep_during_sco;
135     uint8_t combine_sleep_mode_and_lpm;
136     uint8_t enable_uart_txd_tri_state;      /* UART_TXD Tri-State */
137     uint8_t sleep_guard_time;               /* sleep guard time in 12.5ms */
138     uint8_t wakeup_guard_time;              /* wakeup guard time in 12.5ms */
139     uint8_t txd_config;                     /* TXD is high in sleep state */
140     uint8_t pulsed_host_wake;               /* pulsed host wake if mode = 1 */
141 } bt_lpm_param_t;
142 
143 /* Firmware re-launch settlement time */
144 typedef struct {
145     const char *chipset_name;
146     const uint32_t delay_time;
147 } fw_settlement_entry_t;
148 
149 
150 /******************************************************************************
151 **  Externs
152 ******************************************************************************/
153 
154 void hw_config_cback(void *p_evt_buf);
155 extern uint8_t vnd_local_bd_addr[BD_ADDR_LEN];
156 
157 
158 /******************************************************************************
159 **  Static variables
160 ******************************************************************************/
161 
162 static char fw_patchfile_path[256] = FW_PATCHFILE_LOCATION;
163 static char fw_patchfile_name[128] = { 0 };
164 #if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
165 static int fw_patch_settlement_delay = -1;
166 #endif
167 
168 static bt_hw_cfg_cb_t hw_cfg_cb;
169 
170 static bt_lpm_param_t lpm_param =
171 {
172     LPM_SLEEP_MODE,
173     LPM_IDLE_THRESHOLD,
174     LPM_HC_IDLE_THRESHOLD,
175     LPM_BT_WAKE_POLARITY,
176     LPM_HOST_WAKE_POLARITY,
177     LPM_ALLOW_HOST_SLEEP_DURING_SCO,
178     LPM_COMBINE_SLEEP_MODE_AND_LPM,
179     LPM_ENABLE_UART_TXD_TRI_STATE,
180     0,  /* not applicable */
181     0,  /* not applicable */
182     0,  /* not applicable */
183     LPM_PULSED_HOST_WAKE
184 };
185 
186 #if (!defined(SCO_USE_I2S_INTERFACE) || (SCO_USE_I2S_INTERFACE == FALSE))
187 static uint8_t bt_sco_param[SCO_PCM_PARAM_SIZE] =
188 {
189     SCO_PCM_ROUTING,
190     SCO_PCM_IF_CLOCK_RATE,
191     SCO_PCM_IF_FRAME_TYPE,
192     SCO_PCM_IF_SYNC_MODE,
193     SCO_PCM_IF_CLOCK_MODE
194 };
195 
196 static uint8_t bt_pcm_data_fmt_param[PCM_DATA_FORMAT_PARAM_SIZE] =
197 {
198     PCM_DATA_FMT_SHIFT_MODE,
199     PCM_DATA_FMT_FILL_BITS,
200     PCM_DATA_FMT_FILL_METHOD,
201     PCM_DATA_FMT_FILL_NUM,
202     PCM_DATA_FMT_JUSTIFY_MODE
203 };
204 #else
205 static uint8_t bt_sco_param[SCO_I2SPCM_PARAM_SIZE] =
206 {
207     SCO_I2SPCM_IF_MODE,
208     SCO_I2SPCM_IF_ROLE,
209     SCO_I2SPCM_IF_SAMPLE_RATE,
210     SCO_I2SPCM_IF_CLOCK_RATE
211 };
212 #endif
213 
214 /*
215  * The look-up table of recommended firmware settlement delay (milliseconds) on
216  * known chipsets.
217  */
218 static const fw_settlement_entry_t fw_settlement_table[] = {
219     {"BCM43241", 200},
220     {(const char *) NULL, 100}  // Giving the generic fw settlement delay setting.
221 };
222 
223 /******************************************************************************
224 **  Static functions
225 ******************************************************************************/
226 
227 /******************************************************************************
228 **  Controller Initialization Static Functions
229 ******************************************************************************/
230 
231 /*******************************************************************************
232 **
233 ** Function        look_up_fw_settlement_delay
234 **
235 ** Description     If FW_PATCH_SETTLEMENT_DELAY_MS has not been explicitly
236 **                 re-defined in the platform specific build-time configuration
237 **                 file, we will search into the look-up table for a
238 **                 recommended firmware settlement delay value.
239 **
240 **                 Although the settlement time might be also related to board
241 **                 configurations such as the crystal clocking speed.
242 **
243 ** Returns         Firmware settlement delay
244 **
245 *******************************************************************************/
look_up_fw_settlement_delay(void)246 uint32_t look_up_fw_settlement_delay (void)
247 {
248     uint32_t ret_value;
249     fw_settlement_entry_t *p_entry;
250 
251     if (FW_PATCH_SETTLEMENT_DELAY_MS > 0)
252     {
253         ret_value = FW_PATCH_SETTLEMENT_DELAY_MS;
254     }
255 #if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
256     else if (fw_patch_settlement_delay >= 0)
257     {
258         ret_value = fw_patch_settlement_delay;
259     }
260 #endif
261     else
262     {
263         p_entry = (fw_settlement_entry_t *)fw_settlement_table;
264 
265         while (p_entry->chipset_name != NULL)
266         {
267             if (strstr(hw_cfg_cb.local_chip_name, p_entry->chipset_name)!=NULL)
268             {
269                 break;
270             }
271 
272             p_entry++;
273         }
274 
275         ret_value = p_entry->delay_time;
276     }
277 
278     BTHWDBG( "Settlement delay -- %d ms", ret_value);
279 
280     return (ret_value);
281 }
282 
283 /*******************************************************************************
284 **
285 ** Function        ms_delay
286 **
287 ** Description     sleep unconditionally for timeout milliseconds
288 **
289 ** Returns         None
290 **
291 *******************************************************************************/
ms_delay(uint32_t timeout)292 void ms_delay (uint32_t timeout)
293 {
294     struct timespec delay;
295     int err;
296 
297     if (timeout == 0)
298         return;
299 
300     delay.tv_sec = timeout / 1000;
301     delay.tv_nsec = 1000 * 1000 * (timeout%1000);
302 
303     /* [u]sleep can't be used because it uses SIGALRM */
304     do {
305         err = nanosleep(&delay, &delay);
306     } while (err < 0 && errno ==EINTR);
307 }
308 
309 /*******************************************************************************
310 **
311 ** Function        line_speed_to_userial_baud
312 **
313 ** Description     helper function converts line speed number into USERIAL baud
314 **                 rate symbol
315 **
316 ** Returns         unit8_t (USERIAL baud symbol)
317 **
318 *******************************************************************************/
line_speed_to_userial_baud(uint32_t line_speed)319 uint8_t line_speed_to_userial_baud(uint32_t line_speed)
320 {
321     uint8_t baud;
322 
323     if (line_speed == 4000000)
324         baud = USERIAL_BAUD_4M;
325     else if (line_speed == 3000000)
326         baud = USERIAL_BAUD_3M;
327     else if (line_speed == 2000000)
328         baud = USERIAL_BAUD_2M;
329     else if (line_speed == 1000000)
330         baud = USERIAL_BAUD_1M;
331     else if (line_speed == 921600)
332         baud = USERIAL_BAUD_921600;
333     else if (line_speed == 460800)
334         baud = USERIAL_BAUD_460800;
335     else if (line_speed == 230400)
336         baud = USERIAL_BAUD_230400;
337     else if (line_speed == 115200)
338         baud = USERIAL_BAUD_115200;
339     else if (line_speed == 57600)
340         baud = USERIAL_BAUD_57600;
341     else if (line_speed == 19200)
342         baud = USERIAL_BAUD_19200;
343     else if (line_speed == 9600)
344         baud = USERIAL_BAUD_9600;
345     else if (line_speed == 1200)
346         baud = USERIAL_BAUD_1200;
347     else if (line_speed == 600)
348         baud = USERIAL_BAUD_600;
349     else
350     {
351         ALOGE( "userial vendor: unsupported baud speed %d", line_speed);
352         baud = USERIAL_BAUD_115200;
353     }
354 
355     return baud;
356 }
357 
358 
359 /*******************************************************************************
360 **
361 ** Function         hw_strncmp
362 **
363 ** Description      Used to compare two strings in caseless
364 **
365 ** Returns          0: match, otherwise: not match
366 **
367 *******************************************************************************/
hw_strncmp(const char * p_str1,const char * p_str2,const int len)368 static int hw_strncmp (const char *p_str1, const char *p_str2, const int len)
369 {
370     int i;
371 
372     if (!p_str1 || !p_str2)
373         return (1);
374 
375     for (i = 0; i < len; i++)
376     {
377         if (toupper(p_str1[i]) != toupper(p_str2[i]))
378             return (i+1);
379     }
380 
381     return 0;
382 }
383 
384 /*******************************************************************************
385 **
386 ** Function         hw_config_findpatch
387 **
388 ** Description      Search for a proper firmware patch file
389 **                  The selected firmware patch file name with full path
390 **                  will be stored in the input string parameter, i.e.
391 **                  p_chip_id_str, when returns.
392 **
393 ** Returns          TRUE when found the target patch file, otherwise FALSE
394 **
395 *******************************************************************************/
hw_config_findpatch(char * p_chip_id_str)396 static uint8_t hw_config_findpatch(char *p_chip_id_str)
397 {
398     DIR *dirp;
399     struct dirent *dp;
400     int filenamelen;
401     uint8_t retval = FALSE;
402 
403     BTHWDBG("Target name = [%s]", p_chip_id_str);
404 
405     if (strlen(fw_patchfile_name)> 0)
406     {
407         /* If specific filepath and filename have been given in run-time
408          * configuration /etc/bluetooth/bt_vendor.conf file, we will use them
409          * to concatenate the filename to open rather than searching a file
410          * matching to chipset name in the fw_patchfile_path folder.
411          */
412         sprintf(p_chip_id_str, "%s", fw_patchfile_path);
413         if (fw_patchfile_path[strlen(fw_patchfile_path)- 1] != '/')
414         {
415             strcat(p_chip_id_str, "/");
416         }
417         strcat(p_chip_id_str, fw_patchfile_name);
418 
419         ALOGI("FW patchfile: %s", p_chip_id_str);
420         return TRUE;
421     }
422 
423     if ((dirp = opendir(fw_patchfile_path)) != NULL)
424     {
425         /* Fetch next filename in patchfile directory */
426         while ((dp = readdir(dirp)) != NULL)
427         {
428             /* Check if filename starts with chip-id name */
429             if ((hw_strncmp(dp->d_name, p_chip_id_str, strlen(p_chip_id_str)) \
430                 ) == 0)
431             {
432                 /* Check if it has .hcd extenstion */
433                 filenamelen = strlen(dp->d_name);
434                 if ((filenamelen >= FW_PATCHFILE_EXTENSION_LEN) &&
435                     ((hw_strncmp(
436                           &dp->d_name[filenamelen-FW_PATCHFILE_EXTENSION_LEN], \
437                           FW_PATCHFILE_EXTENSION, \
438                           FW_PATCHFILE_EXTENSION_LEN) \
439                      ) == 0))
440                 {
441                     ALOGI("Found patchfile: %s/%s", \
442                         fw_patchfile_path, dp->d_name);
443 
444                     /* Make sure length does not exceed maximum */
445                     if ((filenamelen + strlen(fw_patchfile_path)) > \
446                          FW_PATCHFILE_PATH_MAXLEN)
447                     {
448                         ALOGE("Invalid patchfile name (too long)");
449                     }
450                     else
451                     {
452                         memset(p_chip_id_str, 0, FW_PATCHFILE_PATH_MAXLEN);
453                         /* Found patchfile. Store location and name */
454                         strcpy(p_chip_id_str, fw_patchfile_path);
455                         if (fw_patchfile_path[ \
456                             strlen(fw_patchfile_path)- 1 \
457                             ] != '/')
458                         {
459                             strcat(p_chip_id_str, "/");
460                         }
461                         strcat(p_chip_id_str, dp->d_name);
462                         retval = TRUE;
463                     }
464                     break;
465                 }
466             }
467         }
468 
469         closedir(dirp);
470 
471         if (retval == FALSE)
472         {
473             /* Try again chip name without revision info */
474 
475             int len = strlen(p_chip_id_str);
476             char *p = p_chip_id_str + len - 1;
477 
478             /* Scan backward and look for the first alphabet
479                which is not M or m
480             */
481             while (len > 3) // BCM****
482             {
483                 if ((isdigit(*p)==0) && (*p != 'M') && (*p != 'm'))
484                     break;
485 
486                 p--;
487                 len--;
488             }
489 
490             if (len > 3)
491             {
492                 *p = 0;
493                 retval = hw_config_findpatch(p_chip_id_str);
494             }
495         }
496     }
497     else
498     {
499         ALOGE("Could not open %s", fw_patchfile_path);
500     }
501 
502     return (retval);
503 }
504 
505 /*******************************************************************************
506 **
507 ** Function         hw_config_set_bdaddr
508 **
509 ** Description      Program controller's Bluetooth Device Address
510 **
511 ** Returns          TRUE, if valid address is sent
512 **                  FALSE, otherwise
513 **
514 *******************************************************************************/
hw_config_set_bdaddr(HC_BT_HDR * p_buf)515 static uint8_t hw_config_set_bdaddr(HC_BT_HDR *p_buf)
516 {
517     uint8_t retval = FALSE;
518     uint8_t *p = (uint8_t *) (p_buf + 1);
519 
520     ALOGI("Setting local bd addr to %02X:%02X:%02X:%02X:%02X:%02X",
521         vnd_local_bd_addr[0], vnd_local_bd_addr[1], vnd_local_bd_addr[2],
522         vnd_local_bd_addr[3], vnd_local_bd_addr[4], vnd_local_bd_addr[5]);
523 
524     UINT16_TO_STREAM(p, HCI_VSC_WRITE_BD_ADDR);
525     *p++ = BD_ADDR_LEN; /* parameter length */
526     *p++ = vnd_local_bd_addr[5];
527     *p++ = vnd_local_bd_addr[4];
528     *p++ = vnd_local_bd_addr[3];
529     *p++ = vnd_local_bd_addr[2];
530     *p++ = vnd_local_bd_addr[1];
531     *p = vnd_local_bd_addr[0];
532 
533     p_buf->len = HCI_CMD_PREAMBLE_SIZE + BD_ADDR_LEN;
534     hw_cfg_cb.state = HW_CFG_SET_BD_ADDR;
535 
536     retval = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_BD_ADDR, p_buf, \
537                                  hw_config_cback);
538 
539     return (retval);
540 }
541 
542 #if (USE_CONTROLLER_BDADDR == TRUE)
543 /*******************************************************************************
544 **
545 ** Function         hw_config_read_bdaddr
546 **
547 ** Description      Read controller's Bluetooth Device Address
548 **
549 ** Returns          TRUE, if valid address is sent
550 **                  FALSE, otherwise
551 **
552 *******************************************************************************/
hw_config_read_bdaddr(HC_BT_HDR * p_buf)553 static uint8_t hw_config_read_bdaddr(HC_BT_HDR *p_buf)
554 {
555     uint8_t retval = FALSE;
556     uint8_t *p = (uint8_t *) (p_buf + 1);
557 
558     UINT16_TO_STREAM(p, HCI_READ_LOCAL_BDADDR);
559     *p = 0; /* parameter length */
560 
561     p_buf->len = HCI_CMD_PREAMBLE_SIZE;
562     hw_cfg_cb.state = HW_CFG_READ_BD_ADDR;
563 
564     retval = bt_vendor_cbacks->xmit_cb(HCI_READ_LOCAL_BDADDR, p_buf, \
565                                  hw_config_cback);
566 
567     return (retval);
568 }
569 #endif // (USE_CONTROLLER_BDADDR == TRUE)
570 
571 /*******************************************************************************
572 **
573 ** Function         hw_config_cback
574 **
575 ** Description      Callback function for controller configuration
576 **
577 ** Returns          None
578 **
579 *******************************************************************************/
hw_config_cback(void * p_mem)580 void hw_config_cback(void *p_mem)
581 {
582     HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
583     char        *p_name, *p_tmp;
584     uint8_t     *p, status;
585     uint16_t    opcode;
586     HC_BT_HDR  *p_buf=NULL;
587     uint8_t     is_proceeding = FALSE;
588     int         i;
589 #if (USE_CONTROLLER_BDADDR == TRUE)
590     const uint8_t null_bdaddr[BD_ADDR_LEN] = {0,0,0,0,0,0};
591 #endif
592 
593     status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
594     p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
595     STREAM_TO_UINT16(opcode,p);
596 
597     /* Ask a new buffer big enough to hold any HCI commands sent in here */
598     if ((status == 0) && bt_vendor_cbacks)
599         p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
600                                                        HCI_CMD_MAX_LEN);
601 
602     if (p_buf != NULL)
603     {
604         p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
605         p_buf->offset = 0;
606         p_buf->len = 0;
607         p_buf->layer_specific = 0;
608 
609         p = (uint8_t *) (p_buf + 1);
610 
611         switch (hw_cfg_cb.state)
612         {
613             case HW_CFG_SET_UART_BAUD_1:
614                 /* update baud rate of host's UART port */
615                 ALOGI("bt vendor lib: set UART baud %i", UART_TARGET_BAUD_RATE);
616                 userial_vendor_set_baud( \
617                     line_speed_to_userial_baud(UART_TARGET_BAUD_RATE) \
618                 );
619 
620                 /* read local name */
621                 UINT16_TO_STREAM(p, HCI_READ_LOCAL_NAME);
622                 *p = 0; /* parameter length */
623 
624                 p_buf->len = HCI_CMD_PREAMBLE_SIZE;
625                 hw_cfg_cb.state = HW_CFG_READ_LOCAL_NAME;
626 
627                 is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_READ_LOCAL_NAME, \
628                                                     p_buf, hw_config_cback);
629                 break;
630 
631             case HW_CFG_READ_LOCAL_NAME:
632                 p_tmp = p_name = (char *) (p_evt_buf + 1) + \
633                          HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING;
634 
635                 for (i=0; (i < LOCAL_NAME_BUFFER_LEN)||(*(p_name+i) != 0); i++)
636                     *(p_name+i) = toupper(*(p_name+i));
637 
638                 if ((p_name = strstr(p_name, "BCM")) != NULL)
639                 {
640                     strncpy(hw_cfg_cb.local_chip_name, p_name, \
641                             LOCAL_NAME_BUFFER_LEN-1);
642                 }
643                 else
644                 {
645                     strncpy(hw_cfg_cb.local_chip_name, "UNKNOWN", \
646                             LOCAL_NAME_BUFFER_LEN-1);
647                     p_name = p_tmp;
648                 }
649 
650                 hw_cfg_cb.local_chip_name[LOCAL_NAME_BUFFER_LEN-1] = 0;
651 
652                 BTHWDBG("Chipset %s", hw_cfg_cb.local_chip_name);
653 
654                 if ((status = hw_config_findpatch(p_name)) == TRUE)
655                 {
656                     if ((hw_cfg_cb.fw_fd = open(p_name, O_RDONLY)) == -1)
657                     {
658                         ALOGE("vendor lib preload failed to open [%s]", p_name);
659                     }
660                     else
661                     {
662                         /* vsc_download_minidriver */
663                         UINT16_TO_STREAM(p, HCI_VSC_DOWNLOAD_MINIDRV);
664                         *p = 0; /* parameter length */
665 
666                         p_buf->len = HCI_CMD_PREAMBLE_SIZE;
667                         hw_cfg_cb.state = HW_CFG_DL_MINIDRIVER;
668 
669                         is_proceeding = bt_vendor_cbacks->xmit_cb( \
670                                             HCI_VSC_DOWNLOAD_MINIDRV, p_buf, \
671                                             hw_config_cback);
672                     }
673                 }
674                 else
675                 {
676                     ALOGE( \
677                     "vendor lib preload failed to locate firmware patch file" \
678                     );
679                 }
680 
681                 if (is_proceeding == FALSE)
682                 {
683                     is_proceeding = hw_config_set_bdaddr(p_buf);
684                 }
685                 break;
686 
687             case HW_CFG_DL_MINIDRIVER:
688                 /* give time for placing firmware in download mode */
689                 ms_delay(50);
690                 hw_cfg_cb.state = HW_CFG_DL_FW_PATCH;
691                 /* fall through intentionally */
692             case HW_CFG_DL_FW_PATCH:
693                 p_buf->len = read(hw_cfg_cb.fw_fd, p, HCI_CMD_PREAMBLE_SIZE);
694                 if (p_buf->len > 0)
695                 {
696                     if ((p_buf->len < HCI_CMD_PREAMBLE_SIZE) || \
697                         (opcode == HCI_VSC_LAUNCH_RAM))
698                     {
699                         ALOGW("firmware patch file might be altered!");
700                     }
701                     else
702                     {
703                         p_buf->len += read(hw_cfg_cb.fw_fd, \
704                                            p+HCI_CMD_PREAMBLE_SIZE,\
705                                            *(p+HCD_REC_PAYLOAD_LEN_BYTE));
706                         STREAM_TO_UINT16(opcode,p);
707                         is_proceeding = bt_vendor_cbacks->xmit_cb(opcode, \
708                                                 p_buf, hw_config_cback);
709                         break;
710                     }
711                 }
712 
713                 close(hw_cfg_cb.fw_fd);
714                 hw_cfg_cb.fw_fd = -1;
715 
716                 /* Normally the firmware patch configuration file
717                  * sets the new starting baud rate at 115200.
718                  * So, we need update host's baud rate accordingly.
719                  */
720                 ALOGI("bt vendor lib: set UART baud 115200");
721                 userial_vendor_set_baud(USERIAL_BAUD_115200);
722 
723                 /* Next, we would like to boost baud rate up again
724                  * to desired working speed.
725                  */
726                 hw_cfg_cb.f_set_baud_2 = TRUE;
727 
728                 /* Check if we need to pause a few hundred milliseconds
729                  * before sending down any HCI command.
730                  */
731                 ms_delay(look_up_fw_settlement_delay());
732 
733                 /* fall through intentionally */
734             case HW_CFG_START:
735                 if (UART_TARGET_BAUD_RATE > 3000000)
736                 {
737                     /* set UART clock to 48MHz */
738                     UINT16_TO_STREAM(p, HCI_VSC_WRITE_UART_CLOCK_SETTING);
739                     *p++ = 1; /* parameter length */
740                     *p = 1; /* (1,"UART CLOCK 48 MHz")(2,"UART CLOCK 24 MHz") */
741 
742                     p_buf->len = HCI_CMD_PREAMBLE_SIZE + 1;
743                     hw_cfg_cb.state = HW_CFG_SET_UART_CLOCK;
744 
745                     is_proceeding = bt_vendor_cbacks->xmit_cb( \
746                                         HCI_VSC_WRITE_UART_CLOCK_SETTING, \
747                                         p_buf, hw_config_cback);
748                     break;
749                 }
750                 /* fall through intentionally */
751             case HW_CFG_SET_UART_CLOCK:
752                 /* set controller's UART baud rate to 3M */
753                 UINT16_TO_STREAM(p, HCI_VSC_UPDATE_BAUDRATE);
754                 *p++ = UPDATE_BAUDRATE_CMD_PARAM_SIZE; /* parameter length */
755                 *p++ = 0; /* encoded baud rate */
756                 *p++ = 0; /* use encoded form */
757                 UINT32_TO_STREAM(p, UART_TARGET_BAUD_RATE);
758 
759                 p_buf->len = HCI_CMD_PREAMBLE_SIZE + \
760                              UPDATE_BAUDRATE_CMD_PARAM_SIZE;
761                 hw_cfg_cb.state = (hw_cfg_cb.f_set_baud_2) ? \
762                             HW_CFG_SET_UART_BAUD_2 : HW_CFG_SET_UART_BAUD_1;
763 
764                 is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_VSC_UPDATE_BAUDRATE, \
765                                                     p_buf, hw_config_cback);
766                 break;
767 
768             case HW_CFG_SET_UART_BAUD_2:
769                 /* update baud rate of host's UART port */
770                 ALOGI("bt vendor lib: set UART baud %i", UART_TARGET_BAUD_RATE);
771                 userial_vendor_set_baud( \
772                     line_speed_to_userial_baud(UART_TARGET_BAUD_RATE) \
773                 );
774 
775 #if (USE_CONTROLLER_BDADDR == TRUE)
776                 if ((is_proceeding = hw_config_read_bdaddr(p_buf)) == TRUE)
777                     break;
778 #else
779                 if ((is_proceeding = hw_config_set_bdaddr(p_buf)) == TRUE)
780                     break;
781 #endif
782                 /* fall through intentionally */
783             case HW_CFG_SET_BD_ADDR:
784                 ALOGI("vendor lib fwcfg completed");
785                 bt_vendor_cbacks->dealloc(p_buf);
786                 bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
787 
788                 hw_cfg_cb.state = 0;
789 
790                 if (hw_cfg_cb.fw_fd != -1)
791                 {
792                     close(hw_cfg_cb.fw_fd);
793                     hw_cfg_cb.fw_fd = -1;
794                 }
795 
796                 is_proceeding = TRUE;
797                 break;
798 
799 #if (USE_CONTROLLER_BDADDR == TRUE)
800             case HW_CFG_READ_BD_ADDR:
801                 p_tmp = (char *) (p_evt_buf + 1) + \
802                          HCI_EVT_CMD_CMPL_LOCAL_BDADDR_ARRAY;
803 
804                 if (memcmp(p_tmp, null_bdaddr, BD_ADDR_LEN) == 0)
805                 {
806                     // Controller does not have a valid OTP BDADDR!
807                     // Set the BTIF initial BDADDR instead.
808                     if ((is_proceeding = hw_config_set_bdaddr(p_buf)) == TRUE)
809                         break;
810                 }
811                 else
812                 {
813                     ALOGI("Controller OTP bdaddr %02X:%02X:%02X:%02X:%02X:%02X",
814                         *(p_tmp+5), *(p_tmp+4), *(p_tmp+3),
815                         *(p_tmp+2), *(p_tmp+1), *p_tmp);
816                 }
817 
818                 ALOGI("vendor lib fwcfg completed");
819                 bt_vendor_cbacks->dealloc(p_buf);
820                 bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
821 
822                 hw_cfg_cb.state = 0;
823 
824                 if (hw_cfg_cb.fw_fd != -1)
825                 {
826                     close(hw_cfg_cb.fw_fd);
827                     hw_cfg_cb.fw_fd = -1;
828                 }
829 
830                 is_proceeding = TRUE;
831                 break;
832 #endif // (USE_CONTROLLER_BDADDR == TRUE)
833         } // switch(hw_cfg_cb.state)
834     } // if (p_buf != NULL)
835 
836     /* Free the RX event buffer */
837     if (bt_vendor_cbacks)
838         bt_vendor_cbacks->dealloc(p_evt_buf);
839 
840     if (is_proceeding == FALSE)
841     {
842         ALOGE("vendor lib fwcfg aborted!!!");
843         if (bt_vendor_cbacks)
844         {
845             if (p_buf != NULL)
846                 bt_vendor_cbacks->dealloc(p_buf);
847 
848             bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
849         }
850 
851         if (hw_cfg_cb.fw_fd != -1)
852         {
853             close(hw_cfg_cb.fw_fd);
854             hw_cfg_cb.fw_fd = -1;
855         }
856 
857         hw_cfg_cb.state = 0;
858     }
859 }
860 
861 /******************************************************************************
862 **   LPM Static Functions
863 ******************************************************************************/
864 
865 /*******************************************************************************
866 **
867 ** Function         hw_lpm_ctrl_cback
868 **
869 ** Description      Callback function for lpm enable/disable rquest
870 **
871 ** Returns          None
872 **
873 *******************************************************************************/
hw_lpm_ctrl_cback(void * p_mem)874 void hw_lpm_ctrl_cback(void *p_mem)
875 {
876     HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
877     bt_vendor_op_result_t status = BT_VND_OP_RESULT_FAIL;
878 
879     if (*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0)
880     {
881         status = BT_VND_OP_RESULT_SUCCESS;
882     }
883 
884     if (bt_vendor_cbacks)
885     {
886         bt_vendor_cbacks->lpm_cb(status);
887         bt_vendor_cbacks->dealloc(p_evt_buf);
888     }
889 }
890 
891 
892 #if (SCO_CFG_INCLUDED == TRUE)
893 /*****************************************************************************
894 **   SCO Configuration Static Functions
895 *****************************************************************************/
896 
897 /*******************************************************************************
898 **
899 ** Function         hw_sco_cfg_cback
900 **
901 ** Description      Callback function for SCO configuration rquest
902 **
903 ** Returns          None
904 **
905 *******************************************************************************/
hw_sco_cfg_cback(void * p_mem)906 void hw_sco_cfg_cback(void *p_mem)
907 {
908     HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
909     uint8_t     *p;
910     uint16_t    opcode;
911     HC_BT_HDR  *p_buf=NULL;
912 
913     p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
914     STREAM_TO_UINT16(opcode,p);
915 
916     /* Free the RX event buffer */
917     if (bt_vendor_cbacks)
918         bt_vendor_cbacks->dealloc(p_evt_buf);
919 
920 #if (!defined(SCO_USE_I2S_INTERFACE) || (SCO_USE_I2S_INTERFACE == FALSE))
921     if (opcode == HCI_VSC_WRITE_SCO_PCM_INT_PARAM)
922     {
923         uint8_t ret = FALSE;
924 
925         /* Ask a new buffer to hold WRITE_PCM_DATA_FORMAT_PARAM command */
926         if (bt_vendor_cbacks)
927             p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
928                                                 HCI_CMD_PREAMBLE_SIZE + \
929                                                 PCM_DATA_FORMAT_PARAM_SIZE);
930         if (p_buf)
931         {
932             p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
933             p_buf->offset = 0;
934             p_buf->layer_specific = 0;
935             p_buf->len = HCI_CMD_PREAMBLE_SIZE + PCM_DATA_FORMAT_PARAM_SIZE;
936 
937             p = (uint8_t *) (p_buf + 1);
938             UINT16_TO_STREAM(p, HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM);
939             *p++ = PCM_DATA_FORMAT_PARAM_SIZE;
940             memcpy(p, &bt_pcm_data_fmt_param, PCM_DATA_FORMAT_PARAM_SIZE);
941 
942             if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM,\
943                                            p_buf, hw_sco_cfg_cback)) == FALSE)
944             {
945                 bt_vendor_cbacks->dealloc(p_buf);
946             }
947             else
948                 return;
949         }
950     }
951 #endif  // !SCO_USE_I2S_INTERFACE
952 
953 if (bt_vendor_cbacks)
954     bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_SUCCESS);
955 }
956 #endif // SCO_CFG_INCLUDED
957 
958 /*****************************************************************************
959 **   Hardware Configuration Interface Functions
960 *****************************************************************************/
961 
962 
963 /*******************************************************************************
964 **
965 ** Function        hw_config_start
966 **
967 ** Description     Kick off controller initialization process
968 **
969 ** Returns         None
970 **
971 *******************************************************************************/
hw_config_start(void)972 void hw_config_start(void)
973 {
974     HC_BT_HDR  *p_buf = NULL;
975     uint8_t     *p;
976 
977     hw_cfg_cb.state = 0;
978     hw_cfg_cb.fw_fd = -1;
979     hw_cfg_cb.f_set_baud_2 = FALSE;
980 
981     /* Start from sending HCI_RESET */
982 
983     if (bt_vendor_cbacks)
984     {
985         p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
986                                                        HCI_CMD_PREAMBLE_SIZE);
987     }
988 
989     if (p_buf)
990     {
991         p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
992         p_buf->offset = 0;
993         p_buf->layer_specific = 0;
994         p_buf->len = HCI_CMD_PREAMBLE_SIZE;
995 
996         p = (uint8_t *) (p_buf + 1);
997         UINT16_TO_STREAM(p, HCI_RESET);
998         *p = 0; /* parameter length */
999 
1000         hw_cfg_cb.state = HW_CFG_START;
1001 
1002         bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf, hw_config_cback);
1003     }
1004     else
1005     {
1006         if (bt_vendor_cbacks)
1007         {
1008             ALOGE("vendor lib fw conf aborted [no buffer]");
1009             bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
1010         }
1011     }
1012 }
1013 
1014 /*******************************************************************************
1015 **
1016 ** Function        hw_lpm_enable
1017 **
1018 ** Description     Enalbe/Disable LPM
1019 **
1020 ** Returns         TRUE/FALSE
1021 **
1022 *******************************************************************************/
hw_lpm_enable(uint8_t turn_on)1023 uint8_t hw_lpm_enable(uint8_t turn_on)
1024 {
1025     HC_BT_HDR  *p_buf = NULL;
1026     uint8_t     *p;
1027     uint8_t     ret = FALSE;
1028 
1029     if (bt_vendor_cbacks)
1030         p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
1031                                                        HCI_CMD_PREAMBLE_SIZE + \
1032                                                        LPM_CMD_PARAM_SIZE);
1033 
1034     if (p_buf)
1035     {
1036         p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1037         p_buf->offset = 0;
1038         p_buf->layer_specific = 0;
1039         p_buf->len = HCI_CMD_PREAMBLE_SIZE + LPM_CMD_PARAM_SIZE;
1040 
1041         p = (uint8_t *) (p_buf + 1);
1042         UINT16_TO_STREAM(p, HCI_VSC_WRITE_SLEEP_MODE);
1043         *p++ = LPM_CMD_PARAM_SIZE; /* parameter length */
1044 
1045         if (turn_on)
1046         {
1047             memcpy(p, &lpm_param, LPM_CMD_PARAM_SIZE);
1048             upio_set(UPIO_LPM_MODE, UPIO_ASSERT, 0);
1049         }
1050         else
1051         {
1052             memset(p, 0, LPM_CMD_PARAM_SIZE);
1053             upio_set(UPIO_LPM_MODE, UPIO_DEASSERT, 0);
1054         }
1055 
1056         if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_SLEEP_MODE, p_buf, \
1057                                         hw_lpm_ctrl_cback)) == FALSE)
1058         {
1059             bt_vendor_cbacks->dealloc(p_buf);
1060         }
1061     }
1062 
1063     if ((ret == FALSE) && bt_vendor_cbacks)
1064         bt_vendor_cbacks->lpm_cb(BT_VND_OP_RESULT_FAIL);
1065 
1066     return ret;
1067 }
1068 
1069 /*******************************************************************************
1070 **
1071 ** Function        hw_lpm_get_idle_timeout
1072 **
1073 ** Description     Calculate idle time based on host stack idle threshold
1074 **
1075 ** Returns         idle timeout value
1076 **
1077 *******************************************************************************/
hw_lpm_get_idle_timeout(void)1078 uint32_t hw_lpm_get_idle_timeout(void)
1079 {
1080     uint32_t timeout_ms;
1081 
1082     /* set idle time to be LPM_IDLE_TIMEOUT_MULTIPLE times of
1083      * host stack idle threshold (in 300ms/25ms)
1084      */
1085     timeout_ms = (uint32_t)lpm_param.host_stack_idle_threshold \
1086                             * LPM_IDLE_TIMEOUT_MULTIPLE;
1087 
1088     if (strstr(hw_cfg_cb.local_chip_name, "BCM4325") != NULL)
1089         timeout_ms *= 25; // 12.5 or 25 ?
1090     else
1091         timeout_ms *= 300;
1092 
1093     return timeout_ms;
1094 }
1095 
1096 /*******************************************************************************
1097 **
1098 ** Function        hw_lpm_set_wake_state
1099 **
1100 ** Description     Assert/Deassert BT_WAKE
1101 **
1102 ** Returns         None
1103 **
1104 *******************************************************************************/
hw_lpm_set_wake_state(uint8_t wake_assert)1105 void hw_lpm_set_wake_state(uint8_t wake_assert)
1106 {
1107     uint8_t state = (wake_assert) ? UPIO_ASSERT : UPIO_DEASSERT;
1108 
1109     upio_set(UPIO_BT_WAKE, state, lpm_param.bt_wake_polarity);
1110 }
1111 
1112 #if (SCO_CFG_INCLUDED == TRUE)
1113 /*******************************************************************************
1114 **
1115 ** Function         hw_sco_config
1116 **
1117 ** Description      Configure SCO related hardware settings
1118 **
1119 ** Returns          None
1120 **
1121 *******************************************************************************/
hw_sco_config(void)1122 void hw_sco_config(void)
1123 {
1124     HC_BT_HDR  *p_buf = NULL;
1125     uint8_t     *p, ret;
1126 
1127 #if (!defined(SCO_USE_I2S_INTERFACE) || (SCO_USE_I2S_INTERFACE == FALSE))
1128     uint16_t cmd_u16 = HCI_CMD_PREAMBLE_SIZE + SCO_PCM_PARAM_SIZE;
1129 #else
1130     uint16_t cmd_u16 = HCI_CMD_PREAMBLE_SIZE + SCO_I2SPCM_PARAM_SIZE;
1131 #endif
1132 
1133     if (bt_vendor_cbacks)
1134         p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE+cmd_u16);
1135 
1136     if (p_buf)
1137     {
1138         p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1139         p_buf->offset = 0;
1140         p_buf->layer_specific = 0;
1141         p_buf->len = cmd_u16;
1142 
1143         p = (uint8_t *) (p_buf + 1);
1144 #if (!defined(SCO_USE_I2S_INTERFACE) || (SCO_USE_I2S_INTERFACE == FALSE))
1145         UINT16_TO_STREAM(p, HCI_VSC_WRITE_SCO_PCM_INT_PARAM);
1146         *p++ = SCO_PCM_PARAM_SIZE;
1147         memcpy(p, &bt_sco_param, SCO_PCM_PARAM_SIZE);
1148         cmd_u16 = HCI_VSC_WRITE_SCO_PCM_INT_PARAM;
1149         ALOGI("SCO PCM configure {%d, %d, %d, %d, %d}",
1150            bt_sco_param[0], bt_sco_param[1], bt_sco_param[2], bt_sco_param[3], \
1151            bt_sco_param[4]);
1152 
1153 #else
1154         UINT16_TO_STREAM(p, HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM);
1155         *p++ = SCO_I2SPCM_PARAM_SIZE;
1156         memcpy(p, &bt_sco_param, SCO_I2SPCM_PARAM_SIZE);
1157         cmd_u16 = HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM;
1158         ALOGI("SCO over I2SPCM interface {%d, %d, %d, %d}",
1159            bt_sco_param[0], bt_sco_param[1], bt_sco_param[2], bt_sco_param[3]);
1160 #endif
1161 
1162         if ((ret=bt_vendor_cbacks->xmit_cb(cmd_u16, p_buf, hw_sco_cfg_cback)) \
1163              == FALSE)
1164         {
1165             bt_vendor_cbacks->dealloc(p_buf);
1166         }
1167         else
1168             return;
1169     }
1170 
1171     if (bt_vendor_cbacks)
1172     {
1173         ALOGE("vendor lib scocfg aborted");
1174         bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_FAIL);
1175     }
1176 }
1177 #endif  // SCO_CFG_INCLUDED
1178 
1179 /*******************************************************************************
1180 **
1181 ** Function        hw_set_patch_file_path
1182 **
1183 ** Description     Set the location of firmware patch file
1184 **
1185 ** Returns         0 : Success
1186 **                 Otherwise : Fail
1187 **
1188 *******************************************************************************/
hw_set_patch_file_path(char * p_conf_name,char * p_conf_value,int param)1189 int hw_set_patch_file_path(char *p_conf_name, char *p_conf_value, int param)
1190 {
1191 
1192     strcpy(fw_patchfile_path, p_conf_value);
1193 
1194     return 0;
1195 }
1196 
1197 /*******************************************************************************
1198 **
1199 ** Function        hw_set_patch_file_name
1200 **
1201 ** Description     Give the specific firmware patch filename
1202 **
1203 ** Returns         0 : Success
1204 **                 Otherwise : Fail
1205 **
1206 *******************************************************************************/
hw_set_patch_file_name(char * p_conf_name,char * p_conf_value,int param)1207 int hw_set_patch_file_name(char *p_conf_name, char *p_conf_value, int param)
1208 {
1209 
1210     strcpy(fw_patchfile_name, p_conf_value);
1211 
1212     return 0;
1213 }
1214 
1215 #if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
1216 /*******************************************************************************
1217 **
1218 ** Function        hw_set_patch_settlement_delay
1219 **
1220 ** Description     Give the specific firmware patch settlement time in milliseconds
1221 **
1222 ** Returns         0 : Success
1223 **                 Otherwise : Fail
1224 **
1225 *******************************************************************************/
hw_set_patch_settlement_delay(char * p_conf_name,char * p_conf_value,int param)1226 int hw_set_patch_settlement_delay(char *p_conf_name, char *p_conf_value, int param)
1227 {
1228     fw_patch_settlement_delay = atoi(p_conf_value);
1229 
1230     return 0;
1231 }
1232 #endif  //VENDOR_LIB_RUNTIME_TUNING_ENABLED
1233 
1234 /*****************************************************************************
1235 **   Sample Codes Section
1236 *****************************************************************************/
1237 
1238 #if (HW_END_WITH_HCI_RESET == TRUE)
1239 /*******************************************************************************
1240 **
1241 ** Function         hw_epilog_cback
1242 **
1243 ** Description      Callback function for Command Complete Events from HCI
1244 **                  commands sent in epilog process.
1245 **
1246 ** Returns          None
1247 **
1248 *******************************************************************************/
hw_epilog_cback(void * p_mem)1249 void hw_epilog_cback(void *p_mem)
1250 {
1251     HC_BT_HDR   *p_evt_buf = (HC_BT_HDR *) p_mem;
1252     uint8_t     *p, status;
1253     uint16_t    opcode;
1254 
1255     status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
1256     p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
1257     STREAM_TO_UINT16(opcode,p);
1258 
1259     BTHWDBG("%s Opcode:0x%04X Status: %d", __FUNCTION__, opcode, status);
1260 
1261     if (bt_vendor_cbacks)
1262     {
1263         /* Must free the RX event buffer */
1264         bt_vendor_cbacks->dealloc(p_evt_buf);
1265 
1266         /* Once epilog process is done, must call epilog_cb callback
1267            to notify caller */
1268         bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
1269     }
1270 }
1271 
1272 /*******************************************************************************
1273 **
1274 ** Function         hw_epilog_process
1275 **
1276 ** Description      Sample implementation of epilog process
1277 **
1278 ** Returns          None
1279 **
1280 *******************************************************************************/
hw_epilog_process(void)1281 void hw_epilog_process(void)
1282 {
1283     HC_BT_HDR  *p_buf = NULL;
1284     uint8_t     *p;
1285 
1286     BTHWDBG("hw_epilog_process");
1287 
1288     /* Sending a HCI_RESET */
1289     if (bt_vendor_cbacks)
1290     {
1291         /* Must allocate command buffer via HC's alloc API */
1292         p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
1293                                                        HCI_CMD_PREAMBLE_SIZE);
1294     }
1295 
1296     if (p_buf)
1297     {
1298         p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1299         p_buf->offset = 0;
1300         p_buf->layer_specific = 0;
1301         p_buf->len = HCI_CMD_PREAMBLE_SIZE;
1302 
1303         p = (uint8_t *) (p_buf + 1);
1304         UINT16_TO_STREAM(p, HCI_RESET);
1305         *p = 0; /* parameter length */
1306 
1307         /* Send command via HC's xmit_cb API */
1308         bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf, hw_epilog_cback);
1309     }
1310     else
1311     {
1312         if (bt_vendor_cbacks)
1313         {
1314             ALOGE("vendor lib epilog process aborted [no buffer]");
1315             bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_FAIL);
1316         }
1317     }
1318 }
1319 #endif // (HW_END_WITH_HCI_RESET == TRUE)
1320