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