/******************************************************************************* ** ** Function set_fw_config_reg ** ** Description Sets Firmware config register value from bt_vendor.conf configuration ** ** Returns None ** *******************************************************************************/ void set_fw_config_reg(uint8_t val) { if (val == 0xff) { BTVNDDBG("%s Nothing specified.", __func__); } else if (val == 0xf0 || val == 0xf4) { userial_vendor_ioctl(USERIAL_OP_SET_FWCFG_REG, &val); } else if (!(val & 0x20)) { BTVNDERR("%s For turning off signaling, please use the SignalingEnabled flag in bt_vendor.conf" , __func__); } else { BTVNDERR("%s Not allowed to change the specified bit(s), please refer to FW spec for details" , __func__); } }
/******************************************************************************* ** ** Function op ** ** Description This is interface for bluedroid stack to libbt. It exposes ** several functionality to bluedroid stack. ** ** Returns 0 or -1 ** *******************************************************************************/ static int op(bt_vendor_opcode_t opcode, void *param) { int retval = BT_VND_OP_RESULT_SUCCESS; BTVNDDBG("op for %d named: %s", opcode,dump_vendor_op(opcode)); switch(opcode) { case BT_VND_OP_POWER_CTRL: { int *state = (int *) param; if (*state == BT_VND_PWR_OFF) { //moved to userial_vendor_close()since TL power control is done with IOCTL //which required fd before release fd. } else if (*state == BT_VND_PWR_ON) { //power on done after fd acquired through userial_vendor_open() } } break; case BT_VND_OP_FW_CFG: { hw_config_start(); } break; case BT_VND_OP_SCO_CFG: { #if (SCO_CFG_INCLUDED == TRUE) hw_sco_config(); #else bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_SUCCESS); retval = -1; #endif } break; case BT_VND_OP_USERIAL_OPEN: { int (*fd_array)[] = (int (*)[]) param; int fd, idx; fd = userial_vendor_open(); #if (INTEL_HSB_PLATFORM == TRUE) userial_vendor_configure_serial((tUSERIAL_CFG *)&userial_init_cfg, userial_init_cfg.baud); #endif if (fd != -1) { for (idx=0; idx < CH_MAX; idx++) (*fd_array)[idx] = fd; retval = 1; } /* retval contains numbers of open fd of HCI channels */ if(retval) { if(0 < upio_set_bluetooth_power(UPIO_BT_POWER_ON)) retval = -1; else retval = 1; } } break; case BT_VND_OP_USERIAL_CONFIG: { int baud_rate = STANDARD_BAUD, rt = 0; bt_vendor_baud_config_t baud_config = STANDARD_BAUD; if (param) baud_config = *((int*) param); if (baud_config == STANDARD_BAUD) baud_rate = 115200; else if (baud_config == HIGHER_BAUD) baud_rate = hw_operation_baud; rt = userial_vendor_configure_serial\ ((tUSERIAL_CFG *)&userial_init_cfg, \ line_speed_to_userial_baud(baud_rate)); if(rt == 0) { BTVNDDBG("baudrate changed to :%d", baud_rate); } else { BTVNDDBG("failed to change baudrate:%d", baud_rate); } } break; #if (BT_EN_VIA_USERIAL_IOCTL == TRUE) case BT_VND_OP_FW_DL_COMPLETE: { unsigned long fw_cfg_result = FW_SUCCESS; userial_vendor_ioctl(USERIAL_OP_FW_CFG_CMPL, \ (void*)&fw_cfg_result); } break; case BT_VND_OP_FW_DL_STATUS: { int on = UPIO_BT_POWER_ON; retval = userial_vendor_ioctl(USERIAL_OP_BT_EN, &on); ms_delay(100); } break; #endif case BT_VND_OP_USERIAL_CLOSE: { upio_set_bluetooth_power(UPIO_BT_POWER_OFF); userial_vendor_close(); #ifdef BT_FM_MITIGATION bt_fm_deinit(); #endif } break; case BT_VND_OP_GET_LPM_IDLE_TIMEOUT: { uint32_t *timeout_ms = (uint32_t *) param; *timeout_ms = hw_lpm_get_idle_timeout(); } break; case BT_VND_OP_LPM_SET_MODE: { uint8_t mode = *(uint8_t *) param; hw_lpm_enable(((mode)? BT_VND_LPM_ENABLE : BT_VND_LPM_DISABLE)); } break; case BT_VND_OP_LPM_WAKE_SET_STATE: { uint8_t *state = (uint8_t *) param; uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \ TRUE : FALSE; #if (INTEL_AG6XX_UART == TRUE) if(lpm_is_enabled) { upio_set_bt_wake_state(wake_assert); } #endif } break; #if (LNP_LPM_ENABLED == TRUE) case BT_VND_OP_LPM_SET_IDLE_STATE: { if(lpm_is_enabled) { userial_vendor_ioctl(USERIAL_OP_LPM_SET_IDLE_STATE, (void*)param); } } break; #endif #if (HW_END_WITH_HCI_RESET == TRUE) case BT_VND_OP_EPILOG: hw_epilog_process(); break; #endif #if (A2DP_OFFLOAD_INCLUDED == TRUE) case BT_VND_OP_A2DP_STREAM_CONFIG: BTVNDDBG("op: BT_VND_BT_VND_OP_A2DP_STREAM_CONFIG"); a2dp_offload_send_stream_config((A2DP_OFFLOAD_STREAM_CFG_PARAMS *)param); break; case BT_VND_OP_A2DP_SET_STREAM_STATE: BTVNDDBG("op: BT_VND_OP_A2DP_SET_STREAM_STATE"); uint8_t *state = (uint8_t *) param; a2dp_offload_set_stream_state(*state); break; #endif case BT_VND_OP_SET_AUDIO_STATE: // do nothing break; } return retval; }
/******************************************************************************* ** ** Function upio_set ** ** Description Set i/o based on polarity ** ** Returns None ** *******************************************************************************/ void upio_set(uint8_t pio, uint8_t action, uint8_t polarity) { int rc; #if (BT_WAKE_VIA_PROC == TRUE) int fd = -1; char buffer; #endif switch (pio) { case UPIO_LPM_MODE: if (upio_state[UPIO_LPM_MODE] == action) { UPIODBG("LPM is %s already", lpm_mode[action]); return; } upio_state[UPIO_LPM_MODE] = action; #if (BT_WAKE_VIA_PROC == TRUE) fd = open(VENDOR_LPM_PROC_NODE, O_WRONLY); if (fd < 0) { ALOGE("upio_set : open(%s) for write failed: %s (%d)", VENDOR_LPM_PROC_NODE, strerror(errno), errno); return; } if (action == UPIO_ASSERT) { buffer = '1'; } else { buffer = '0'; // delete btwrite assertion holding timer if (lpm_proc_cb.timer_created == TRUE) { timer_delete(lpm_proc_cb.timer_id); lpm_proc_cb.timer_created = FALSE; } } if (write(fd, &buffer, 1) < 0) { ALOGE("upio_set : write(%s) failed: %s (%d)", VENDOR_LPM_PROC_NODE, strerror(errno),errno); } else { if (action == UPIO_ASSERT) { // create btwrite assertion holding timer if (lpm_proc_cb.timer_created == FALSE) { int status; struct sigevent se; se.sigev_notify = SIGEV_THREAD; se.sigev_value.sival_ptr = &lpm_proc_cb.timer_id; se.sigev_notify_function = proc_btwrite_timeout; se.sigev_notify_attributes = NULL; status = timer_create(CLOCK_MONOTONIC, &se, &lpm_proc_cb.timer_id); if (status == 0) lpm_proc_cb.timer_created = TRUE; } } } if (fd >= 0) close(fd); #endif break; case UPIO_BT_WAKE: if (upio_state[UPIO_BT_WAKE] == action) { UPIODBG("BT_WAKE is %s already", lpm_state[action]); #if (BT_WAKE_VIA_PROC == TRUE) if (lpm_proc_cb.btwrite_active == TRUE) /* * The proc btwrite node could have not been updated for * certain time already due to heavy downstream path flow. * In this case, we want to explicity touch proc btwrite * node to keep the bt_wake assertion in the LPM kernel * driver. The current kernel bluesleep LPM code starts * a 10sec internal in-activity timeout timer before it * attempts to deassert BT_WAKE line. */ #endif return; } upio_state[UPIO_BT_WAKE] = action; #if (BT_WAKE_VIA_USERIAL_IOCTL == TRUE) userial_vendor_ioctl( ( (action==UPIO_ASSERT) ? \ USERIAL_OP_ASSERT_BT_WAKE : USERIAL_OP_DEASSERT_BT_WAKE),\ NULL); #elif (BT_WAKE_VIA_PROC == TRUE) /* * Kick proc btwrite node only at UPIO_ASSERT */ if (action == UPIO_DEASSERT) return; fd = open(VENDOR_BTWRITE_PROC_NODE, O_WRONLY); if (fd < 0) { ALOGE("upio_set : open(%s) for write failed: %s (%d)", VENDOR_BTWRITE_PROC_NODE, strerror(errno), errno); return; } buffer = '1'; if (write(fd, &buffer, 1) < 0) { ALOGE("upio_set : write(%s) failed: %s (%d)", VENDOR_BTWRITE_PROC_NODE, strerror(errno),errno); } else { lpm_proc_cb.btwrite_active = TRUE; if (lpm_proc_cb.timer_created == TRUE) { struct itimerspec ts; ts.it_value.tv_sec = PROC_BTWRITE_TIMER_TIMEOUT_MS/1000; ts.it_value.tv_nsec = 1000*(PROC_BTWRITE_TIMER_TIMEOUT_MS%1000); ts.it_interval.tv_sec = 0; ts.it_interval.tv_nsec = 0; timer_settime(lpm_proc_cb.timer_id, 0, &ts, 0); } } UPIODBG("proc btwrite assertion"); if (fd >= 0) close(fd); #endif break; case UPIO_HOST_WAKE: UPIODBG("upio_set: UPIO_HOST_WAKE"); break; } }