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