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