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