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