diff options
Diffstat (limited to 'libbt')
33 files changed, 3077 insertions, 0 deletions
diff --git a/libbt/Android.mk b/libbt/Android.mk new file mode 100644 index 0000000..4b5ce4d --- /dev/null +++ b/libbt/Android.mk @@ -0,0 +1,46 @@ +LOCAL_PATH := $(call my-dir) + +ifneq ($(BOARD_HAVE_BLUETOOTH_BCM),) + +include $(CLEAR_VARS) + +BDROID_DIR := $(TOP_DIR)external/bluetooth/bluedroid + +LOCAL_SRC_FILES := \ + src/bt_vendor_brcm.c \ + src/hardware.c \ + src/userial_vendor.c \ + src/upio.c \ + src/conf.c + +LOCAL_C_INCLUDES += \ + $(LOCAL_PATH)/include \ + $(BDROID_DIR)/hci/include + +LOCAL_SHARED_LIBRARIES := \ + libcutils + +LOCAL_MODULE := libbt-vendor +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_CLASS := SHARED_LIBRARIES +LOCAL_MODULE_OWNER := broadcom +LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_SHARED_LIBRARIES) + +include $(LOCAL_PATH)/vnd_buildcfg.mk + +include $(BUILD_SHARED_LIBRARY) + +ifeq ($(TARGET_PRODUCT), full_maguro) + include $(LOCAL_PATH)/conf/samsung/maguro/Android.mk +endif +ifeq ($(TARGET_PRODUCT), full_crespo) + include $(LOCAL_PATH)/conf/samsung/crespo/Android.mk +endif +ifeq ($(TARGET_PRODUCT), full_crespo4g) + include $(LOCAL_PATH)/conf/samsung/crespo4g/Android.mk +endif +ifeq ($(TARGET_PRODUCT), full_wingray) + include $(LOCAL_PATH)/conf/moto/wingray/Android.mk +endif + +endif # BOARD_HAVE_BLUETOOTH_BCM diff --git a/libbt/conf/asus/grouper/Android.mk b/libbt/conf/asus/grouper/Android.mk new file mode 100644 index 0000000..974e213 --- /dev/null +++ b/libbt/conf/asus/grouper/Android.mk @@ -0,0 +1,14 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := bt_vendor.conf +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/bluetooth + +LOCAL_MODULE_TAGS := eng + +LOCAL_SRC_FILES := $(LOCAL_MODULE) + +include $(BUILD_PREBUILT) + diff --git a/libbt/conf/asus/grouper/bt_vendor.conf b/libbt/conf/asus/grouper/bt_vendor.conf new file mode 100644 index 0000000..94fa0cd --- /dev/null +++ b/libbt/conf/asus/grouper/bt_vendor.conf @@ -0,0 +1,5 @@ +# UART device port where Bluetooth controller is attached +UartPort = /dev/ttyHS2 + +# Firmware patch file location +FwPatchFilePath = /etc/firmware/ diff --git a/libbt/conf/moto/wingray/Android.mk b/libbt/conf/moto/wingray/Android.mk new file mode 100644 index 0000000..974e213 --- /dev/null +++ b/libbt/conf/moto/wingray/Android.mk @@ -0,0 +1,14 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := bt_vendor.conf +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/bluetooth + +LOCAL_MODULE_TAGS := eng + +LOCAL_SRC_FILES := $(LOCAL_MODULE) + +include $(BUILD_PREBUILT) + diff --git a/libbt/conf/moto/wingray/bt_vendor.conf b/libbt/conf/moto/wingray/bt_vendor.conf new file mode 100644 index 0000000..94fa0cd --- /dev/null +++ b/libbt/conf/moto/wingray/bt_vendor.conf @@ -0,0 +1,5 @@ +# UART device port where Bluetooth controller is attached +UartPort = /dev/ttyHS2 + +# Firmware patch file location +FwPatchFilePath = /etc/firmware/ diff --git a/libbt/conf/samsung/crespo/Android.mk b/libbt/conf/samsung/crespo/Android.mk new file mode 100644 index 0000000..974e213 --- /dev/null +++ b/libbt/conf/samsung/crespo/Android.mk @@ -0,0 +1,14 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := bt_vendor.conf +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/bluetooth + +LOCAL_MODULE_TAGS := eng + +LOCAL_SRC_FILES := $(LOCAL_MODULE) + +include $(BUILD_PREBUILT) + diff --git a/libbt/conf/samsung/crespo/bt_vendor.conf b/libbt/conf/samsung/crespo/bt_vendor.conf new file mode 100644 index 0000000..1f471ca --- /dev/null +++ b/libbt/conf/samsung/crespo/bt_vendor.conf @@ -0,0 +1,5 @@ +# UART device port where Bluetooth controller is attached +UartPort = /dev/s3c2410_serial0 + +# Firmware patch file location +FwPatchFilePath = /vendor/firmware/ diff --git a/libbt/conf/samsung/crespo4g/Android.mk b/libbt/conf/samsung/crespo4g/Android.mk new file mode 100644 index 0000000..974e213 --- /dev/null +++ b/libbt/conf/samsung/crespo4g/Android.mk @@ -0,0 +1,14 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := bt_vendor.conf +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/bluetooth + +LOCAL_MODULE_TAGS := eng + +LOCAL_SRC_FILES := $(LOCAL_MODULE) + +include $(BUILD_PREBUILT) + diff --git a/libbt/conf/samsung/crespo4g/bt_vendor.conf b/libbt/conf/samsung/crespo4g/bt_vendor.conf new file mode 100644 index 0000000..1f471ca --- /dev/null +++ b/libbt/conf/samsung/crespo4g/bt_vendor.conf @@ -0,0 +1,5 @@ +# UART device port where Bluetooth controller is attached +UartPort = /dev/s3c2410_serial0 + +# Firmware patch file location +FwPatchFilePath = /vendor/firmware/ diff --git a/libbt/conf/samsung/maguro/Android.mk b/libbt/conf/samsung/maguro/Android.mk new file mode 100644 index 0000000..974e213 --- /dev/null +++ b/libbt/conf/samsung/maguro/Android.mk @@ -0,0 +1,14 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := bt_vendor.conf +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/bluetooth + +LOCAL_MODULE_TAGS := eng + +LOCAL_SRC_FILES := $(LOCAL_MODULE) + +include $(BUILD_PREBUILT) + diff --git a/libbt/conf/samsung/maguro/bt_vendor.conf b/libbt/conf/samsung/maguro/bt_vendor.conf new file mode 100644 index 0000000..d5547eb --- /dev/null +++ b/libbt/conf/samsung/maguro/bt_vendor.conf @@ -0,0 +1,5 @@ +# UART device port where Bluetooth controller is attached +UartPort = /dev/ttyO1 + +# Firmware patch file location +FwPatchFilePath = /vendor/firmware/ diff --git a/libbt/include/bt_vendor_brcm.h b/libbt/include/bt_vendor_brcm.h new file mode 100644 index 0000000..2ecc21e --- /dev/null +++ b/libbt/include/bt_vendor_brcm.h @@ -0,0 +1,334 @@ +/****************************************************************************** + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Filename: bt_vendor_brcm.h + * + * Description: A wrapper header file of bt_vendor_lib.h + * + * Contains definitions specific for interfacing with Broadcom + * Bluetooth chipsets + * + ******************************************************************************/ + +#ifndef BT_VENDOR_BRCM_H +#define BT_VENDOR_BRCM_H + +#include "bt_vendor_lib.h" +#include "vnd_buildcfg.h" + +/****************************************************************************** +** Constants & Macros +******************************************************************************/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +#ifndef VENDOR_LIB_RUNTIME_TUNING_ENABLED +#define VENDOR_LIB_RUNTIME_TUNING_ENABLED FALSE +#endif + +/* Run-time configuration file */ +#ifndef VENDOR_LIB_CONF_FILE +#define VENDOR_LIB_CONF_FILE "/etc/bluetooth/bt_vendor.conf" +#endif + +/* Device port name where Bluetooth controller attached */ +#ifndef BLUETOOTH_UART_DEVICE_PORT +#define BLUETOOTH_UART_DEVICE_PORT "/dev/ttyO1" /* maguro */ +#endif + +/* Location of firmware patch files */ +#ifndef FW_PATCHFILE_LOCATION +#define FW_PATCHFILE_LOCATION "/vendor/firmware/" /* maguro */ +#endif + +#ifndef UART_TARGET_BAUD_RATE +#define UART_TARGET_BAUD_RATE 3000000 +#endif + +/* The millisecond delay pauses on HCI transport after firmware patches + * were downloaded. This gives some time for firmware to restart with + * patches before host attempts to send down any HCI commands. + * + * Note: It has been discovered that BCM43241B0 needs at least 200ms + * settlement delay in here. Without the delay, a Hardware Error event + * from BCM43241B0 had been seen in HCI upstream path right after the + * host sent the HCI_VSC_SET_BDADDR commad to the controller at higher + * baud. + */ +#ifndef FW_PATCH_SETTLEMENT_DELAY_MS +#define FW_PATCH_SETTLEMENT_DELAY_MS 0 +#endif + +/* sleep mode + + 0: disable + 1: UART with Host wake/BT wake out of band signals +*/ +#ifndef LPM_SLEEP_MODE +#define LPM_SLEEP_MODE 1 +#endif + +/* Host Stack Idle Threshold in 300ms or 25ms + + In sleep mode 1, this is the number of firmware loops executed with no + activity before the Host wake line is deasserted. Activity includes HCI + traffic excluding certain sleep mode commands and the presence of SCO + connections if the "Allow Host Sleep During SCO" flag is not set to 1. + Each count of this parameter is roughly equivalent to 300ms or 25ms. +*/ +#ifndef LPM_IDLE_THRESHOLD +#define LPM_IDLE_THRESHOLD 1 +#endif + +/* Host Controller Idle Threshold in 300ms or 25ms + + This is the number of firmware loops executed with no activity before the + HC is considered idle. Depending on the mode, HC may then attempt to sleep. + Activity includes HCI traffic excluding certain sleep mode commands and + the presence of ACL/SCO connections. +*/ +#ifndef LPM_HC_IDLE_THRESHOLD +#define LPM_HC_IDLE_THRESHOLD 1 +#endif + +/* BT_WAKE Polarity - 0=Active Low, 1= Active High */ +#ifndef LPM_BT_WAKE_POLARITY +#define LPM_BT_WAKE_POLARITY 1 /* maguro */ +#endif + +/* HOST_WAKE Polarity - 0=Active Low, 1= Active High */ +#ifndef LPM_HOST_WAKE_POLARITY +#define LPM_HOST_WAKE_POLARITY 1 /* maguro */ +#endif + +/* LPM_ALLOW_HOST_SLEEP_DURING_SCO + + When this flag is set to 0, the host is not allowed to sleep while + an SCO is active. In sleep mode 1, the device will keep the host + wake line asserted while an SCO is active. + When this flag is set to 1, the host can sleep while an SCO is active. + This flag should only be set to 1 if SCO traffic is directed to the PCM + interface. +*/ +#ifndef LPM_ALLOW_HOST_SLEEP_DURING_SCO +#define LPM_ALLOW_HOST_SLEEP_DURING_SCO 1 +#endif + +/* LPM_COMBINE_SLEEP_MODE_AND_LPM + + In Mode 0, always set byte 7 to 0. In sleep mode 1, device always + requires permission to sleep between scans / periodic inquiries regardless + of the setting of this byte. In sleep mode 1, if byte is set, device must + have "permission" to sleep during the low power modes of sniff, hold, and + park. If byte is not set, device can sleep without permission during these + modes. Permission to sleep in Mode 1 is obtained if the BT_WAKE signal is + not asserted. +*/ +#ifndef LPM_COMBINE_SLEEP_MODE_AND_LPM +#define LPM_COMBINE_SLEEP_MODE_AND_LPM 1 +#endif + +/* LPM_ENABLE_UART_TXD_TRI_STATE + + When set to 0, the device will not tristate its UART TX line before going + to sleep. + When set to 1, the device will tristate its UART TX line before going to + sleep. +*/ +#ifndef LPM_ENABLE_UART_TXD_TRI_STATE +#define LPM_ENABLE_UART_TXD_TRI_STATE 0 +#endif + +/* LPM_PULSED_HOST_WAKE +*/ +#ifndef LPM_PULSED_HOST_WAKE +#define LPM_PULSED_HOST_WAKE 0 +#endif + +/* LPM_IDLE_TIMEOUT_MULTIPLE + + The multiple factor of host stack idle threshold in 300ms/25ms +*/ +#ifndef LPM_IDLE_TIMEOUT_MULTIPLE +#define LPM_IDLE_TIMEOUT_MULTIPLE 10 +#endif + +/* BT_WAKE_VIA_USERIAL_IOCTL + + Use userial ioctl function to control BT_WAKE signal +*/ +#ifndef BT_WAKE_VIA_USERIAL_IOCTL +#define BT_WAKE_VIA_USERIAL_IOCTL FALSE +#endif + + +/* SCO_CFG_INCLUDED + + Do SCO configuration by default. If the firmware patch had been embedded + with desired SCO configuration, set this FALSE to bypass configuration + from host software. +*/ +#ifndef SCO_CFG_INCLUDED +#define SCO_CFG_INCLUDED TRUE +#endif + +#ifndef SCO_USE_I2S_INTERFACE +#define SCO_USE_I2S_INTERFACE FALSE +#endif + +#if (SCO_USE_I2S_INTERFACE == TRUE) +#define SCO_I2SPCM_PARAM_SIZE 4 + +/* SCO_I2SPCM_IF_MODE - 0=Disable, 1=Enable */ +#ifndef SCO_I2SPCM_IF_MODE +#define SCO_I2SPCM_IF_MODE 1 +#endif + +/* SCO_I2SPCM_IF_ROLE - 0=Slave, 1=Master */ +#ifndef SCO_I2SPCM_IF_ROLE +#define SCO_I2SPCM_IF_ROLE 1 +#endif + +/* SCO_I2SPCM_IF_SAMPLE_RATE + + 0 : 8K + 1 : 16K + 2 : 4K +*/ +#ifndef SCO_I2SPCM_IF_SAMPLE_RATE +#define SCO_I2SPCM_IF_SAMPLE_RATE 0 +#endif + +/* SCO_I2SPCM_IF_CLOCK_RATE + + 0 : 128K + 1 : 256K + 2 : 512K + 3 : 1024K + 4 : 2048K +*/ +#ifndef SCO_I2SPCM_IF_CLOCK_RATE +#define SCO_I2SPCM_IF_CLOCK_RATE 1 +#endif +#endif // SCO_USE_I2S_INTERFACE + + +#define SCO_PCM_PARAM_SIZE 5 + +/* SCO_PCM_ROUTING + + 0 : PCM + 1 : Transport + 2 : Codec + 3 : I2S +*/ +#ifndef SCO_PCM_ROUTING +#define SCO_PCM_ROUTING 0 +#endif + +/* SCO_PCM_IF_CLOCK_RATE + + 0 : 128K + 1 : 256K + 2 : 512K + 3 : 1024K + 4 : 2048K +*/ +#ifndef SCO_PCM_IF_CLOCK_RATE +#define SCO_PCM_IF_CLOCK_RATE 4 +#endif + +/* SCO_PCM_IF_FRAME_TYPE - 0=Short, 1=Long */ +#ifndef SCO_PCM_IF_FRAME_TYPE +#define SCO_PCM_IF_FRAME_TYPE 0 +#endif + +/* SCO_PCM_IF_SYNC_MODE - 0=Slave, 1=Master */ +#ifndef SCO_PCM_IF_SYNC_MODE +#define SCO_PCM_IF_SYNC_MODE 0 +#endif + +/* SCO_PCM_IF_CLOCK_MODE - 0=Slave, 1=Master */ +#ifndef SCO_PCM_IF_CLOCK_MODE +#define SCO_PCM_IF_CLOCK_MODE 0 +#endif + +#define PCM_DATA_FORMAT_PARAM_SIZE 5 + +/* PCM_DATA_FMT_SHIFT_MODE + + 0 : MSB first + 1 : LSB first +*/ +#ifndef PCM_DATA_FMT_SHIFT_MODE +#define PCM_DATA_FMT_SHIFT_MODE 0 +#endif + +/* PCM_DATA_FMT_FILL_BITS + + Specifies the value with which to fill unused bits + if Fill_Method is set to programmable +*/ +#ifndef PCM_DATA_FMT_FILL_BITS +#define PCM_DATA_FMT_FILL_BITS 0 +#endif + +/* PCM_DATA_FMT_FILL_METHOD + + 0 : 0's + 1 : 1's + 2 : Signed + 3 : Programmable +*/ +#ifndef PCM_DATA_FMT_FILL_METHOD +#define PCM_DATA_FMT_FILL_METHOD 3 +#endif + +/* PCM_DATA_FMT_FILL_NUM + + Specifies the number of bits to be filled +*/ +#ifndef PCM_DATA_FMT_FILL_NUM +#define PCM_DATA_FMT_FILL_NUM 3 +#endif + +/* PCM_DATA_FMT_JUSTIFY_MODE + + 0 : Left justify (fill data shifted out last) + 1 : Right justify (fill data shifted out first) +*/ +#ifndef PCM_DATA_FMT_JUSTIFY_MODE +#define PCM_DATA_FMT_JUSTIFY_MODE 0 +#endif + +/****************************************************************************** +** Extern variables and functions +******************************************************************************/ + +extern bt_vendor_callbacks_t *bt_vendor_cbacks; + +#endif /* BT_VENDOR_BRCM_H */ + diff --git a/libbt/include/upio.h b/libbt/include/upio.h new file mode 100644 index 0000000..32920e6 --- /dev/null +++ b/libbt/include/upio.h @@ -0,0 +1,106 @@ +/****************************************************************************** + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Filename: upio.h + * + * Description: Contains definitions used for I/O controls + * + ******************************************************************************/ + +#ifndef UPIO_H +#define UPIO_H + +/****************************************************************************** +** Constants & Macros +******************************************************************************/ + +#define UPIO_BT_POWER_OFF 0 +#define UPIO_BT_POWER_ON 1 + +/* UPIO signals */ +enum { + UPIO_BT_WAKE = 0, + UPIO_HOST_WAKE, + UPIO_MAX_COUNT +}; + +/* UPIO assertion/deassertion */ +enum { + UPIO_UNKNOWN = 0, + UPIO_DEASSERT, + UPIO_ASSERT +}; + +/****************************************************************************** +** Extern variables and functions +******************************************************************************/ + +/****************************************************************************** +** Functions +******************************************************************************/ + +/******************************************************************************* +** +** Function upio_init +** +** Description Initialization +** +** Returns None +** +*******************************************************************************/ +void upio_init(void); + +/******************************************************************************* +** +** Function upio_cleanup +** +** Description Clean up +** +** Returns None +** +*******************************************************************************/ +void upio_cleanup(void); + +/******************************************************************************* +** +** Function upio_set_bluetooth_power +** +** Description Interact with low layer driver to set Bluetooth power +** on/off. +** +** Returns 0 : SUCCESS or Not-Applicable +** <0 : ERROR +** +*******************************************************************************/ +int upio_set_bluetooth_power(int on); + +/******************************************************************************* +** +** Function upio_set +** +** Description Set i/o based on polarity +** +** Returns None +** +*******************************************************************************/ +void upio_set(uint8_t pio, uint8_t action, uint8_t polarity); + +#endif /* UPIO_H */ + diff --git a/libbt/include/userial_vendor.h b/libbt/include/userial_vendor.h new file mode 100644 index 0000000..8e8b84f --- /dev/null +++ b/libbt/include/userial_vendor.h @@ -0,0 +1,175 @@ +/****************************************************************************** + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Filename: userial_vendor.h + * + * Description: Contains vendor-specific definitions used in serial port + * controls + * + ******************************************************************************/ + +#ifndef USERIAL_VENDOR_H +#define USERIAL_VENDOR_H + +#include "bt_vendor_brcm.h" +#include "userial.h" + +/****************************************************************************** +** Constants & Macros +******************************************************************************/ + +/**** baud rates ****/ +#define USERIAL_BAUD_300 0 +#define USERIAL_BAUD_600 1 +#define USERIAL_BAUD_1200 2 +#define USERIAL_BAUD_2400 3 +#define USERIAL_BAUD_9600 4 +#define USERIAL_BAUD_19200 5 +#define USERIAL_BAUD_57600 6 +#define USERIAL_BAUD_115200 7 +#define USERIAL_BAUD_230400 8 +#define USERIAL_BAUD_460800 9 +#define USERIAL_BAUD_921600 10 +#define USERIAL_BAUD_1M 11 +#define USERIAL_BAUD_1_5M 12 +#define USERIAL_BAUD_2M 13 +#define USERIAL_BAUD_3M 14 +#define USERIAL_BAUD_4M 15 +#define USERIAL_BAUD_AUTO 16 + +/**** Data Format ****/ +/* Stop Bits */ +#define USERIAL_STOPBITS_1 1 +#define USERIAL_STOPBITS_1_5 (1<<1) +#define USERIAL_STOPBITS_2 (1<<2) + +/* Parity Bits */ +#define USERIAL_PARITY_NONE (1<<3) +#define USERIAL_PARITY_EVEN (1<<4) +#define USERIAL_PARITY_ODD (1<<5) + +/* Data Bits */ +#define USERIAL_DATABITS_5 (1<<6) +#define USERIAL_DATABITS_6 (1<<7) +#define USERIAL_DATABITS_7 (1<<8) +#define USERIAL_DATABITS_8 (1<<9) + + +#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) +/* These are the ioctl values used for bt_wake ioctl via UART driver. you may + * need to redefine them on you platform! + * Logically they need to be unique and not colide with existing uart ioctl's. + */ +#ifndef USERIAL_IOCTL_BT_WAKE_ASSERT +#define USERIAL_IOCTL_BT_WAKE_ASSERT 0x8003 +#endif +#ifndef USERIAL_IOCTL_BT_WAKE_DEASSERT +#define USERIAL_IOCTL_BT_WAKE_DEASSERT 0x8004 +#endif +#ifndef USERIAL_IOCTL_BT_WAKE_GET_ST +#define USERIAL_IOCTL_BT_WAKE_GET_ST 0x8005 +#endif +#endif // (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) + +/****************************************************************************** +** Type definitions +******************************************************************************/ + +/* Structure used to configure serial port during open */ +typedef struct +{ + uint16_t fmt; /* Data format */ + uint8_t baud; /* Baud rate */ +} tUSERIAL_CFG; + +typedef enum { +#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) + USERIAL_OP_ASSERT_BT_WAKE, + USERIAL_OP_DEASSERT_BT_WAKE, + USERIAL_OP_GET_BT_WAKE_STATE, +#endif + USERIAL_OP_NOP, +} userial_vendor_ioctl_op_t; + +/****************************************************************************** +** Extern variables and functions +******************************************************************************/ + +/****************************************************************************** +** Functions +******************************************************************************/ + +/******************************************************************************* +** +** Function userial_vendor_init +** +** Description Initialize userial vendor-specific control block +** +** Returns None +** +*******************************************************************************/ +void userial_vendor_init(void); + +/******************************************************************************* +** +** Function userial_vendor_open +** +** Description Open the serial port with the given configuration +** +** Returns device fd +** +*******************************************************************************/ +int userial_vendor_open(tUSERIAL_CFG *p_cfg); + +/******************************************************************************* +** +** Function userial_vendor_close +** +** Description Conduct vendor-specific close work +** +** Returns None +** +*******************************************************************************/ +void userial_vendor_close(void); + +/******************************************************************************* +** +** Function userial_vendor_set_baud +** +** Description Set new baud rate +** +** Returns None +** +*******************************************************************************/ +void userial_vendor_set_baud(uint8_t userial_baud); + +/******************************************************************************* +** +** Function userial_vendor_ioctl +** +** Description ioctl inteface +** +** Returns None +** +*******************************************************************************/ +void userial_vendor_ioctl(userial_vendor_ioctl_op_t op, void *p_data); + +#endif /* USERIAL_VENDOR_H */ + diff --git a/libbt/include/vnd_crespo.txt b/libbt/include/vnd_crespo.txt new file mode 100644 index 0000000..3596b6f --- /dev/null +++ b/libbt/include/vnd_crespo.txt @@ -0,0 +1,9 @@ +BLUETOOTH_UART_DEVICE_PORT = "/dev/s3c2410_serial0" +FW_PATCHFILE_LOCATION = "/vendor/firmware/" +BT_WAKE_VIA_USERIAL_IOCTL = TRUE +LPM_IDLE_TIMEOUT_MULTIPLE = 5 +SCO_PCM_IF_CLOCK_RATE = 0 +BTVND_DBG = FALSE +BTHW_DBG = TRUE +VNDUSERIAL_DBG = FALSE +UPIO_DBG = FALSE diff --git a/libbt/include/vnd_crespo4g.txt b/libbt/include/vnd_crespo4g.txt new file mode 100644 index 0000000..3596b6f --- /dev/null +++ b/libbt/include/vnd_crespo4g.txt @@ -0,0 +1,9 @@ +BLUETOOTH_UART_DEVICE_PORT = "/dev/s3c2410_serial0" +FW_PATCHFILE_LOCATION = "/vendor/firmware/" +BT_WAKE_VIA_USERIAL_IOCTL = TRUE +LPM_IDLE_TIMEOUT_MULTIPLE = 5 +SCO_PCM_IF_CLOCK_RATE = 0 +BTVND_DBG = FALSE +BTHW_DBG = TRUE +VNDUSERIAL_DBG = FALSE +UPIO_DBG = FALSE diff --git a/libbt/include/vnd_generic.txt b/libbt/include/vnd_generic.txt new file mode 100644 index 0000000..43e790c --- /dev/null +++ b/libbt/include/vnd_generic.txt @@ -0,0 +1,9 @@ +BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyO1" +FW_PATCHFILE_LOCATION = "/vendor/firmware/" +BT_WAKE_VIA_USERIAL_IOCTL = TRUE +LPM_IDLE_TIMEOUT_MULTIPLE = 5 +SCO_USE_I2S_INTERFACE = TRUE +BTVND_DBG = FALSE +BTHW_DBG = TRUE +VNDUSERIAL_DBG = FALSE +UPIO_DBG = FALSE diff --git a/libbt/include/vnd_generic_x86.txt b/libbt/include/vnd_generic_x86.txt new file mode 100644 index 0000000..43e790c --- /dev/null +++ b/libbt/include/vnd_generic_x86.txt @@ -0,0 +1,9 @@ +BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyO1" +FW_PATCHFILE_LOCATION = "/vendor/firmware/" +BT_WAKE_VIA_USERIAL_IOCTL = TRUE +LPM_IDLE_TIMEOUT_MULTIPLE = 5 +SCO_USE_I2S_INTERFACE = TRUE +BTVND_DBG = FALSE +BTHW_DBG = TRUE +VNDUSERIAL_DBG = FALSE +UPIO_DBG = FALSE diff --git a/libbt/include/vnd_grouper.txt b/libbt/include/vnd_grouper.txt new file mode 100755 index 0000000..3667e65 --- /dev/null +++ b/libbt/include/vnd_grouper.txt @@ -0,0 +1,9 @@ +BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyHS2" +FW_PATCHFILE_LOCATION = "/etc/firmware/" +BT_WAKE_VIA_USERIAL_IOCTL = TRUE +LPM_IDLE_TIMEOUT_MULTIPLE = 5 +BTVND_DBG = FALSE +BTHW_DBG = TRUE +VNDUSERIAL_DBG = FALSE +UPIO_DBG = FALSE +SCO_PCM_IF_CLOCK_RATE = 2 diff --git a/libbt/include/vnd_maguro.txt b/libbt/include/vnd_maguro.txt new file mode 100644 index 0000000..43e790c --- /dev/null +++ b/libbt/include/vnd_maguro.txt @@ -0,0 +1,9 @@ +BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyO1" +FW_PATCHFILE_LOCATION = "/vendor/firmware/" +BT_WAKE_VIA_USERIAL_IOCTL = TRUE +LPM_IDLE_TIMEOUT_MULTIPLE = 5 +SCO_USE_I2S_INTERFACE = TRUE +BTVND_DBG = FALSE +BTHW_DBG = TRUE +VNDUSERIAL_DBG = FALSE +UPIO_DBG = FALSE diff --git a/libbt/include/vnd_mako.txt b/libbt/include/vnd_mako.txt new file mode 100644 index 0000000..43e790c --- /dev/null +++ b/libbt/include/vnd_mako.txt @@ -0,0 +1,9 @@ +BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyO1" +FW_PATCHFILE_LOCATION = "/vendor/firmware/" +BT_WAKE_VIA_USERIAL_IOCTL = TRUE +LPM_IDLE_TIMEOUT_MULTIPLE = 5 +SCO_USE_I2S_INTERFACE = TRUE +BTVND_DBG = FALSE +BTHW_DBG = TRUE +VNDUSERIAL_DBG = FALSE +UPIO_DBG = FALSE diff --git a/libbt/include/vnd_manta.txt b/libbt/include/vnd_manta.txt new file mode 100644 index 0000000..53f9542 --- /dev/null +++ b/libbt/include/vnd_manta.txt @@ -0,0 +1,9 @@ +BLUETOOTH_UART_DEVICE_PORT = "/dev/ttySAC0" +FW_PATCHFILE_LOCATION = "/vendor/firmware/" +UART_TARGET_BAUD_RATE = 921600 +BT_WAKE_VIA_USERIAL_IOCTL = TRUE +LPM_IDLE_TIMEOUT_MULTIPLE = 5 +BTVND_DBG = FALSE +BTHW_DBG = TRUE +VNDUSERIAL_DBG = FALSE +UPIO_DBG = FALSE diff --git a/libbt/include/vnd_phantasm.txt b/libbt/include/vnd_phantasm.txt new file mode 100644 index 0000000..43e790c --- /dev/null +++ b/libbt/include/vnd_phantasm.txt @@ -0,0 +1,9 @@ +BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyO1" +FW_PATCHFILE_LOCATION = "/vendor/firmware/" +BT_WAKE_VIA_USERIAL_IOCTL = TRUE +LPM_IDLE_TIMEOUT_MULTIPLE = 5 +SCO_USE_I2S_INTERFACE = TRUE +BTVND_DBG = FALSE +BTHW_DBG = TRUE +VNDUSERIAL_DBG = FALSE +UPIO_DBG = FALSE diff --git a/libbt/include/vnd_stingray.txt b/libbt/include/vnd_stingray.txt new file mode 100755 index 0000000..3667e65 --- /dev/null +++ b/libbt/include/vnd_stingray.txt @@ -0,0 +1,9 @@ +BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyHS2" +FW_PATCHFILE_LOCATION = "/etc/firmware/" +BT_WAKE_VIA_USERIAL_IOCTL = TRUE +LPM_IDLE_TIMEOUT_MULTIPLE = 5 +BTVND_DBG = FALSE +BTHW_DBG = TRUE +VNDUSERIAL_DBG = FALSE +UPIO_DBG = FALSE +SCO_PCM_IF_CLOCK_RATE = 2 diff --git a/libbt/include/vnd_toro.txt b/libbt/include/vnd_toro.txt new file mode 100644 index 0000000..43e790c --- /dev/null +++ b/libbt/include/vnd_toro.txt @@ -0,0 +1,9 @@ +BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyO1" +FW_PATCHFILE_LOCATION = "/vendor/firmware/" +BT_WAKE_VIA_USERIAL_IOCTL = TRUE +LPM_IDLE_TIMEOUT_MULTIPLE = 5 +SCO_USE_I2S_INTERFACE = TRUE +BTVND_DBG = FALSE +BTHW_DBG = TRUE +VNDUSERIAL_DBG = FALSE +UPIO_DBG = FALSE diff --git a/libbt/include/vnd_tuna.txt b/libbt/include/vnd_tuna.txt new file mode 100644 index 0000000..43e790c --- /dev/null +++ b/libbt/include/vnd_tuna.txt @@ -0,0 +1,9 @@ +BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyO1" +FW_PATCHFILE_LOCATION = "/vendor/firmware/" +BT_WAKE_VIA_USERIAL_IOCTL = TRUE +LPM_IDLE_TIMEOUT_MULTIPLE = 5 +SCO_USE_I2S_INTERFACE = TRUE +BTVND_DBG = FALSE +BTHW_DBG = TRUE +VNDUSERIAL_DBG = FALSE +UPIO_DBG = FALSE diff --git a/libbt/include/vnd_wingray.txt b/libbt/include/vnd_wingray.txt new file mode 100755 index 0000000..3667e65 --- /dev/null +++ b/libbt/include/vnd_wingray.txt @@ -0,0 +1,9 @@ +BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyHS2" +FW_PATCHFILE_LOCATION = "/etc/firmware/" +BT_WAKE_VIA_USERIAL_IOCTL = TRUE +LPM_IDLE_TIMEOUT_MULTIPLE = 5 +BTVND_DBG = FALSE +BTHW_DBG = TRUE +VNDUSERIAL_DBG = FALSE +UPIO_DBG = FALSE +SCO_PCM_IF_CLOCK_RATE = 2 diff --git a/libbt/src/bt_vendor_brcm.c b/libbt/src/bt_vendor_brcm.c new file mode 100644 index 0000000..d17baa2 --- /dev/null +++ b/libbt/src/bt_vendor_brcm.c @@ -0,0 +1,227 @@ +/****************************************************************************** + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Filename: bt_vendor_brcm.c + * + * Description: Broadcom vendor specific library implementation + * + ******************************************************************************/ + +#define LOG_TAG "bt_vendor" + +#include <utils/Log.h> +#include "bt_vendor_brcm.h" +#include "upio.h" +#include "userial_vendor.h" + +#ifndef BTVND_DBG +#define BTVND_DBG FALSE +#endif + +#if (BTVND_DBG == TRUE) +#define BTVNDDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);} +#else +#define BTVNDDBG(param, ...) {} +#endif + +/****************************************************************************** +** Externs +******************************************************************************/ + +void hw_config_start(void); +uint8_t hw_lpm_enable(uint8_t turn_on); +uint32_t hw_lpm_get_idle_timeout(void); +void hw_lpm_set_wake_state(uint8_t wake_assert); +#if (SCO_CFG_INCLUDED == TRUE) +void hw_sco_config(void); +#endif +void vnd_load_conf(const char *p_path); + +/****************************************************************************** +** Variables +******************************************************************************/ + +bt_vendor_callbacks_t *bt_vendor_cbacks = NULL; +uint8_t vnd_local_bd_addr[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +/****************************************************************************** +** Local type definitions +******************************************************************************/ + +/****************************************************************************** +** Static Variables +******************************************************************************/ + +static const tUSERIAL_CFG userial_init_cfg = +{ + (USERIAL_DATABITS_8 | USERIAL_PARITY_NONE | USERIAL_STOPBITS_1), + USERIAL_BAUD_115200 +}; + +/****************************************************************************** +** Functions +******************************************************************************/ + +/***************************************************************************** +** +** BLUETOOTH VENDOR INTERFACE LIBRARY FUNCTIONS +** +*****************************************************************************/ + +static int init(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr) +{ + ALOGI("init"); + + if (p_cb == NULL) + { + ALOGE("init failed with no user callbacks!"); + return -1; + } + +#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE) + ALOGW("*****************************************************************"); + ALOGW("*****************************************************************"); + ALOGW("** Warning - BT Vendor Lib is loaded in debug tuning mode!"); + ALOGW("**"); + ALOGW("** If this is not intentional, rebuild libbt-vendor.so "); + ALOGW("** with VENDOR_LIB_RUNTIME_TUNING_ENABLED=FALSE and "); + ALOGW("** check if any run-time tuning parameters needed to be"); + ALOGW("** carried to the build-time configuration accordingly."); + ALOGW("*****************************************************************"); + ALOGW("*****************************************************************"); +#endif + + userial_vendor_init(); + upio_init(); + + vnd_load_conf(VENDOR_LIB_CONF_FILE); + + /* store reference to user callbacks */ + bt_vendor_cbacks = (bt_vendor_callbacks_t *) p_cb; + + /* This is handed over from the stack */ + memcpy(vnd_local_bd_addr, local_bdaddr, 6); + + return 0; +} + + +/** Requested operations */ +static int op(bt_vendor_opcode_t opcode, void *param) +{ + int retval = 0; + + BTVNDDBG("op for %d", opcode); + + switch(opcode) + { + case BT_VND_OP_POWER_CTRL: + { + int *state = (int *) param; + if (*state == BT_VND_PWR_OFF) + upio_set_bluetooth_power(UPIO_BT_POWER_OFF); + else if (*state == BT_VND_PWR_ON) + upio_set_bluetooth_power(UPIO_BT_POWER_ON); + } + 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 + retval = -1; +#endif + } + break; + + case BT_VND_OP_USERIAL_OPEN: + { + int (*fd_array)[] = (int (*)[]) param; + int fd, idx; + fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg); + 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 */ + } + break; + + case BT_VND_OP_USERIAL_CLOSE: + { + userial_vendor_close(); + } + 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; + retval = hw_lpm_enable(*mode); + } + 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; + + hw_lpm_set_wake_state(wake_assert); + } + break; + } + + return retval; +} + +/** Closes the interface */ +static void cleanup( void ) +{ + BTVNDDBG("cleanup"); + + upio_cleanup(); + + bt_vendor_cbacks = NULL; +} + +// Entry point of DLib +const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = { + sizeof(bt_vendor_interface_t), + init, + op, + cleanup +}; diff --git a/libbt/src/conf.c b/libbt/src/conf.c new file mode 100644 index 0000000..39ac12e --- /dev/null +++ b/libbt/src/conf.c @@ -0,0 +1,147 @@ +/****************************************************************************** + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Filename: conf.c + * + * Description: Contains functions to conduct run-time module configuration + * based on entries present in the .conf file + * + ******************************************************************************/ + +#define LOG_TAG "bt_vnd_conf" + +#include <utils/Log.h> +#include <string.h> +#include "bt_vendor_brcm.h" + +/****************************************************************************** +** Externs +******************************************************************************/ +int userial_set_port(char *p_conf_name, char *p_conf_value, int param); +int hw_set_patch_file_path(char *p_conf_name, char *p_conf_value, int param); +int hw_set_patch_file_name(char *p_conf_name, char *p_conf_value, int param); +#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE) +int hw_set_patch_settlement_delay(char *p_conf_name, char *p_conf_value, int param); +#endif + + +/****************************************************************************** +** Local type definitions +******************************************************************************/ + +#define CONF_COMMENT '#' +#define CONF_DELIMITERS " =\n\r\t" +#define CONF_VALUES_DELIMITERS "=\n\r\t" +#define CONF_MAX_LINE_LEN 255 + +typedef int (conf_action_t)(char *p_conf_name, char *p_conf_value, int param); + +typedef struct { + const char *conf_entry; + conf_action_t *p_action; + int param; +} conf_entry_t; + +/****************************************************************************** +** Static variables +******************************************************************************/ + +/* + * Current supported entries and corresponding action functions + */ +static const conf_entry_t conf_table[] = { + {"UartPort", userial_set_port, 0}, + {"FwPatchFilePath", hw_set_patch_file_path, 0}, + {"FwPatchFileName", hw_set_patch_file_name, 0}, +#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE) + {"FwPatchSettlementDelay", hw_set_patch_settlement_delay, 0}, +#endif + {(const char *) NULL, NULL, 0} +}; + +/***************************************************************************** +** CONF INTERFACE FUNCTIONS +*****************************************************************************/ + +/******************************************************************************* +** +** Function vnd_load_conf +** +** Description Read conf entry from p_path file one by one and call +** the corresponding config function +** +** Returns None +** +*******************************************************************************/ +void vnd_load_conf(const char *p_path) +{ + FILE *p_file; + char *p_name; + char *p_value; + conf_entry_t *p_entry; + char line[CONF_MAX_LINE_LEN+1]; /* add 1 for \0 char */ + + ALOGI("Attempt to load conf from %s", p_path); + + if ((p_file = fopen(p_path, "r")) != NULL) + { + /* read line by line */ + while (fgets(line, CONF_MAX_LINE_LEN+1, p_file) != NULL) + { + if (line[0] == CONF_COMMENT) + continue; + + p_name = strtok(line, CONF_DELIMITERS); + + if (NULL == p_name) + { + continue; + } + + p_value = strtok(NULL, CONF_DELIMITERS); + + if (NULL == p_value) + { + ALOGW("vnd_load_conf: missing value for name: %s", p_name); + continue; + } + + p_entry = (conf_entry_t *)conf_table; + + while (p_entry->conf_entry != NULL) + { + if (strcmp(p_entry->conf_entry, (const char *)p_name) == 0) + { + p_entry->p_action(p_name, p_value, p_entry->param); + break; + } + + p_entry++; + } + } + + fclose(p_file); + } + else + { + ALOGI( "vnd_load_conf file >%s< not found", p_path); + } +} + diff --git a/libbt/src/hardware.c b/libbt/src/hardware.c new file mode 100644 index 0000000..a6868e1 --- /dev/null +++ b/libbt/src/hardware.c @@ -0,0 +1,1155 @@ +/****************************************************************************** + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Filename: hardware.c + * + * Description: Contains controller-specific functions, like + * firmware patch download + * low power mode operations + * + ******************************************************************************/ + +#define LOG_TAG "bt_hwcfg" + +#include <utils/Log.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <signal.h> +#include <time.h> +#include <errno.h> +#include <fcntl.h> +#include <dirent.h> +#include <ctype.h> +#include <cutils/properties.h> +#include <stdlib.h> +#include "bt_hci_bdroid.h" +#include "bt_vendor_brcm.h" +#include "userial.h" +#include "userial_vendor.h" +#include "upio.h" + +/****************************************************************************** +** Constants & Macros +******************************************************************************/ + +#ifndef BTHW_DBG +#define BTHW_DBG FALSE +#endif + +#if (BTHW_DBG == TRUE) +#define BTHWDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);} +#else +#define BTHWDBG(param, ...) {} +#endif + +#define FW_PATCHFILE_EXTENSION ".hcd" +#define FW_PATCHFILE_EXTENSION_LEN 4 +#define FW_PATCHFILE_PATH_MAXLEN 248 /* Local_Name length of return of + HCI_Read_Local_Name */ + +#define HCI_CMD_MAX_LEN 258 + +#define HCI_RESET 0x0C03 +#define HCI_VSC_WRITE_UART_CLOCK_SETTING 0xFC45 +#define HCI_VSC_UPDATE_BAUDRATE 0xFC18 +#define HCI_READ_LOCAL_NAME 0x0C14 +#define HCI_VSC_DOWNLOAD_MINIDRV 0xFC2E +#define HCI_VSC_WRITE_BD_ADDR 0xFC01 +#define HCI_VSC_WRITE_SLEEP_MODE 0xFC27 +#define HCI_VSC_WRITE_SCO_PCM_INT_PARAM 0xFC1C +#define HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM 0xFC1E +#define HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM 0xFC6D +#define HCI_VSC_LAUNCH_RAM 0xFC4E + +#define HCI_EVT_CMD_CMPL_STATUS_RET_BYTE 5 +#define HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING 6 +#define HCI_EVT_CMD_CMPL_OPCODE 3 +#define LPM_CMD_PARAM_SIZE 12 +#define UPDATE_BAUDRATE_CMD_PARAM_SIZE 6 +#define HCI_CMD_PREAMBLE_SIZE 3 +#define HCD_REC_PAYLOAD_LEN_BYTE 2 +#define BD_ADDR_LEN 6 +#define LOCAL_NAME_BUFFER_LEN 32 +#define LOCAL_BDADDR_PATH_BUFFER_LEN 256 + +#define STREAM_TO_UINT16(u16, p) {u16 = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); (p) += 2;} +#define UINT16_TO_STREAM(p, u16) {*(p)++ = (uint8_t)(u16); *(p)++ = (uint8_t)((u16) >> 8);} +#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);} + +/****************************************************************************** +** Local type definitions +******************************************************************************/ + +/* Hardware Configuration State */ +enum { + HW_CFG_START = 1, + HW_CFG_SET_UART_CLOCK, + HW_CFG_SET_UART_BAUD_1, + HW_CFG_READ_LOCAL_NAME, + HW_CFG_DL_MINIDRIVER, + HW_CFG_DL_FW_PATCH, + HW_CFG_SET_UART_BAUD_2, + HW_CFG_SET_BD_ADDR +}; + +/* h/w config control block */ +typedef struct +{ + uint8_t state; /* Hardware configuration state */ + int fw_fd; /* FW patch file fd */ + uint8_t f_set_baud_2; /* Baud rate switch state */ + char local_chip_name[LOCAL_NAME_BUFFER_LEN]; +} bt_hw_cfg_cb_t; + +/* low power mode parameters */ +typedef struct +{ + uint8_t sleep_mode; /* 0(disable),1(UART),9(H5) */ + uint8_t host_stack_idle_threshold; /* Unit scale 300ms/25ms */ + uint8_t host_controller_idle_threshold; /* Unit scale 300ms/25ms */ + uint8_t bt_wake_polarity; /* 0=Active Low, 1= Active High */ + uint8_t host_wake_polarity; /* 0=Active Low, 1= Active High */ + uint8_t allow_host_sleep_during_sco; + uint8_t combine_sleep_mode_and_lpm; + uint8_t enable_uart_txd_tri_state; /* UART_TXD Tri-State */ + uint8_t sleep_guard_time; /* sleep guard time in 12.5ms */ + uint8_t wakeup_guard_time; /* wakeup guard time in 12.5ms */ + uint8_t txd_config; /* TXD is high in sleep state */ + uint8_t pulsed_host_wake; /* pulsed host wake if mode = 1 */ +} bt_lpm_param_t; + +/* Firmware re-launch settlement time */ +typedef struct { + const char *chipset_name; + const uint32_t delay_time; +} fw_settlement_entry_t; + + +/****************************************************************************** +** Externs +******************************************************************************/ + +void hw_config_cback(void *p_evt_buf); +extern uint8_t vnd_local_bd_addr[BD_ADDR_LEN]; + + +/****************************************************************************** +** Static variables +******************************************************************************/ + +static char fw_patchfile_path[256] = FW_PATCHFILE_LOCATION; +static char fw_patchfile_name[128] = { 0 }; +#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE) +static int fw_patch_settlement_delay = -1; +#endif + +static bt_hw_cfg_cb_t hw_cfg_cb; + +static bt_lpm_param_t lpm_param = +{ + LPM_SLEEP_MODE, + LPM_IDLE_THRESHOLD, + LPM_HC_IDLE_THRESHOLD, + LPM_BT_WAKE_POLARITY, + LPM_HOST_WAKE_POLARITY, + LPM_ALLOW_HOST_SLEEP_DURING_SCO, + LPM_COMBINE_SLEEP_MODE_AND_LPM, + LPM_ENABLE_UART_TXD_TRI_STATE, + 0, /* not applicable */ + 0, /* not applicable */ + 0, /* not applicable */ + LPM_PULSED_HOST_WAKE +}; + +#if (!defined(SCO_USE_I2S_INTERFACE) || (SCO_USE_I2S_INTERFACE == FALSE)) +static uint8_t bt_sco_param[SCO_PCM_PARAM_SIZE] = +{ + SCO_PCM_ROUTING, + SCO_PCM_IF_CLOCK_RATE, + SCO_PCM_IF_FRAME_TYPE, + SCO_PCM_IF_SYNC_MODE, + SCO_PCM_IF_CLOCK_MODE +}; + +static uint8_t bt_pcm_data_fmt_param[PCM_DATA_FORMAT_PARAM_SIZE] = +{ + PCM_DATA_FMT_SHIFT_MODE, + PCM_DATA_FMT_FILL_BITS, + PCM_DATA_FMT_FILL_METHOD, + PCM_DATA_FMT_FILL_NUM, + PCM_DATA_FMT_JUSTIFY_MODE +}; +#else +static uint8_t bt_sco_param[SCO_I2SPCM_PARAM_SIZE] = +{ + SCO_I2SPCM_IF_MODE, + SCO_I2SPCM_IF_ROLE, + SCO_I2SPCM_IF_SAMPLE_RATE, + SCO_I2SPCM_IF_CLOCK_RATE +}; +#endif + +/* + * The look-up table of recommended firmware settlement delay (milliseconds) on + * known chipsets. + */ +static const fw_settlement_entry_t fw_settlement_table[] = { + {"BCM43241", 200}, + {(const char *) NULL, 100} // Giving the generic fw settlement delay setting. +}; + +/****************************************************************************** +** Static functions +******************************************************************************/ + +/****************************************************************************** +** Controller Initialization Static Functions +******************************************************************************/ + +/******************************************************************************* +** +** Function look_up_fw_settlement_delay +** +** Description If FW_PATCH_SETTLEMENT_DELAY_MS has not been explicitly +** re-defined in the platform specific build-time configuration +** file, we will search into the look-up table for a +** recommended firmware settlement delay value. +** +** Although the settlement time might be also related to board +** configurations such as the crystal clocking speed. +** +** Returns Firmware settlement delay +** +*******************************************************************************/ +uint32_t look_up_fw_settlement_delay (void) +{ + uint32_t ret_value; + fw_settlement_entry_t *p_entry; + + if (FW_PATCH_SETTLEMENT_DELAY_MS > 0) + { + ret_value = FW_PATCH_SETTLEMENT_DELAY_MS; + } +#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE) + else if (fw_patch_settlement_delay >= 0) + { + ret_value = fw_patch_settlement_delay; + } +#endif + else + { + p_entry = (fw_settlement_entry_t *)fw_settlement_table; + + while (p_entry->chipset_name != NULL) + { + if (strstr(hw_cfg_cb.local_chip_name, p_entry->chipset_name)!=NULL) + { + break; + } + + p_entry++; + } + + ret_value = p_entry->delay_time; + } + + BTHWDBG( "Settlement delay -- %d ms", ret_value); + + return (ret_value); +} + +/******************************************************************************* +** +** Function ms_delay +** +** Description sleep unconditionally for timeout milliseconds +** +** Returns None +** +*******************************************************************************/ +void ms_delay (uint32_t timeout) +{ + struct timespec delay; + int err; + + if (timeout == 0) + return; + + delay.tv_sec = timeout / 1000; + delay.tv_nsec = 1000 * 1000 * (timeout%1000); + + /* [u]sleep can't be used because it uses SIGALRM */ + do { + err = nanosleep(&delay, &delay); + } while (err < 0 && errno ==EINTR); +} + +/******************************************************************************* +** +** Function line_speed_to_userial_baud +** +** Description helper function converts line speed number into USERIAL baud +** rate symbol +** +** Returns unit8_t (USERIAL baud symbol) +** +*******************************************************************************/ +uint8_t line_speed_to_userial_baud(uint32_t line_speed) +{ + uint8_t baud; + + if (line_speed == 4000000) + baud = USERIAL_BAUD_4M; + else if (line_speed == 3000000) + baud = USERIAL_BAUD_3M; + else if (line_speed == 2000000) + baud = USERIAL_BAUD_2M; + else if (line_speed == 1000000) + baud = USERIAL_BAUD_1M; + else if (line_speed == 921600) + baud = USERIAL_BAUD_921600; + else if (line_speed == 460800) + baud = USERIAL_BAUD_460800; + else if (line_speed == 230400) + baud = USERIAL_BAUD_230400; + else if (line_speed == 115200) + baud = USERIAL_BAUD_115200; + else if (line_speed == 57600) + baud = USERIAL_BAUD_57600; + else if (line_speed == 19200) + baud = USERIAL_BAUD_19200; + else if (line_speed == 9600) + baud = USERIAL_BAUD_9600; + else if (line_speed == 1200) + baud = USERIAL_BAUD_1200; + else if (line_speed == 600) + baud = USERIAL_BAUD_600; + else + { + ALOGE( "userial vendor: unsupported baud speed %d", line_speed); + baud = USERIAL_BAUD_115200; + } + + return baud; +} + + +/******************************************************************************* +** +** Function hw_strncmp +** +** Description Used to compare two strings in caseless +** +** Returns 0: match, otherwise: not match +** +*******************************************************************************/ +static int hw_strncmp (const char *p_str1, const char *p_str2, const int len) +{ + int i; + + if (!p_str1 || !p_str2) + return (1); + + for (i = 0; i < len; i++) + { + if (toupper(p_str1[i]) != toupper(p_str2[i])) + return (i+1); + } + + return 0; +} + +/******************************************************************************* +** +** Function hw_config_findpatch +** +** Description Search for a proper firmware patch file +** The selected firmware patch file name with full path +** will be stored in the input string parameter, i.e. +** p_chip_id_str, when returns. +** +** Returns TRUE when found the target patch file, otherwise FALSE +** +*******************************************************************************/ +static uint8_t hw_config_findpatch(char *p_chip_id_str) +{ + DIR *dirp; + struct dirent *dp; + int filenamelen; + uint8_t retval = FALSE; + + BTHWDBG("Target name = [%s]", p_chip_id_str); + + if (strlen(fw_patchfile_name)> 0) + { + /* If specific filepath and filename have been given in run-time + * configuration /etc/bluetooth/bt_vendor.conf file, we will use them + * to concatenate the filename to open rather than searching a file + * matching to chipset name in the fw_patchfile_path folder. + */ + sprintf(p_chip_id_str, "%s", fw_patchfile_path); + if (fw_patchfile_path[strlen(fw_patchfile_path)- 1] != '/') + { + strcat(p_chip_id_str, "/"); + } + strcat(p_chip_id_str, fw_patchfile_name); + + ALOGI("FW patchfile: %s", p_chip_id_str); + return TRUE; + } + + if ((dirp = opendir(fw_patchfile_path)) != NULL) + { + /* Fetch next filename in patchfile directory */ + while ((dp = readdir(dirp)) != NULL) + { + /* Check if filename starts with chip-id name */ + if ((hw_strncmp(dp->d_name, p_chip_id_str, strlen(p_chip_id_str)) \ + ) == 0) + { + /* Check if it has .hcd extenstion */ + filenamelen = strlen(dp->d_name); + if ((filenamelen >= FW_PATCHFILE_EXTENSION_LEN) && + ((hw_strncmp( + &dp->d_name[filenamelen-FW_PATCHFILE_EXTENSION_LEN], \ + FW_PATCHFILE_EXTENSION, \ + FW_PATCHFILE_EXTENSION_LEN) \ + ) == 0)) + { + ALOGI("Found patchfile: %s/%s", \ + fw_patchfile_path, dp->d_name); + + /* Make sure length does not exceed maximum */ + if ((filenamelen + strlen(fw_patchfile_path)) > \ + FW_PATCHFILE_PATH_MAXLEN) + { + ALOGE("Invalid patchfile name (too long)"); + } + else + { + memset(p_chip_id_str, 0, FW_PATCHFILE_PATH_MAXLEN); + /* Found patchfile. Store location and name */ + strcpy(p_chip_id_str, fw_patchfile_path); + if (fw_patchfile_path[ \ + strlen(fw_patchfile_path)- 1 \ + ] != '/') + { + strcat(p_chip_id_str, "/"); + } + strcat(p_chip_id_str, dp->d_name); + retval = TRUE; + } + break; + } + } + } + + closedir(dirp); + + if (retval == FALSE) + { + /* Try again chip name without revision info */ + + int len = strlen(p_chip_id_str); + char *p = p_chip_id_str + len - 1; + + /* Scan backward and look for the first alphabet + which is not M or m + */ + while (len > 3) // BCM**** + { + if ((isdigit(*p)==0) && (*p != 'M') && (*p != 'm')) + break; + + p--; + len--; + } + + if (len > 3) + { + *p = 0; + retval = hw_config_findpatch(p_chip_id_str); + } + } + } + else + { + ALOGE("Could not open %s", fw_patchfile_path); + } + + return (retval); +} + +/******************************************************************************* +** +** Function hw_config_set_bdaddr +** +** Description Program controller's Bluetooth Device Address +** +** Returns TRUE, if valid address is sent +** FALSE, otherwise +** +*******************************************************************************/ +static uint8_t hw_config_set_bdaddr(HC_BT_HDR *p_buf) +{ + uint8_t retval = FALSE; + uint8_t *p = (uint8_t *) (p_buf + 1); + + ALOGI("Setting local bd addr to %02X:%02X:%02X:%02X:%02X:%02X", + vnd_local_bd_addr[0], vnd_local_bd_addr[1], vnd_local_bd_addr[2], + vnd_local_bd_addr[3], vnd_local_bd_addr[4], vnd_local_bd_addr[5]); + + UINT16_TO_STREAM(p, HCI_VSC_WRITE_BD_ADDR); + *p++ = BD_ADDR_LEN; /* parameter length */ + *p++ = vnd_local_bd_addr[5]; + *p++ = vnd_local_bd_addr[4]; + *p++ = vnd_local_bd_addr[3]; + *p++ = vnd_local_bd_addr[2]; + *p++ = vnd_local_bd_addr[1]; + *p = vnd_local_bd_addr[0]; + + p_buf->len = HCI_CMD_PREAMBLE_SIZE + BD_ADDR_LEN; + hw_cfg_cb.state = HW_CFG_SET_BD_ADDR; + + retval = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_BD_ADDR, p_buf, \ + hw_config_cback); + + return (retval); +} + +/******************************************************************************* +** +** Function hw_config_cback +** +** Description Callback function for controller configuration +** +** Returns None +** +*******************************************************************************/ +void hw_config_cback(void *p_mem) +{ + HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem; + char *p_name, *p_tmp; + uint8_t *p, status; + uint16_t opcode; + HC_BT_HDR *p_buf=NULL; + uint8_t is_proceeding = FALSE; + int i; + + status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE); + p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE; + STREAM_TO_UINT16(opcode,p); + + /* Ask a new buffer big enough to hold any HCI commands sent in here */ + if ((status == 0) && bt_vendor_cbacks) + p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \ + HCI_CMD_MAX_LEN); + + if (p_buf != NULL) + { + p_buf->event = MSG_STACK_TO_HC_HCI_CMD; + p_buf->offset = 0; + p_buf->len = 0; + p_buf->layer_specific = 0; + + p = (uint8_t *) (p_buf + 1); + + switch (hw_cfg_cb.state) + { + case HW_CFG_SET_UART_BAUD_1: + /* update baud rate of host's UART port */ + ALOGI("bt vendor lib: set UART baud %i", UART_TARGET_BAUD_RATE); + userial_vendor_set_baud( \ + line_speed_to_userial_baud(UART_TARGET_BAUD_RATE) \ + ); + + /* read local name */ + UINT16_TO_STREAM(p, HCI_READ_LOCAL_NAME); + *p = 0; /* parameter length */ + + p_buf->len = HCI_CMD_PREAMBLE_SIZE; + hw_cfg_cb.state = HW_CFG_READ_LOCAL_NAME; + + is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_READ_LOCAL_NAME, \ + p_buf, hw_config_cback); + break; + + case HW_CFG_READ_LOCAL_NAME: + p_tmp = p_name = (char *) (p_evt_buf + 1) + \ + HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING; + + for (i=0; (i < LOCAL_NAME_BUFFER_LEN)||(*(p_name+i) != 0); i++) + *(p_name+i) = toupper(*(p_name+i)); + + if ((p_name = strstr(p_name, "BCM")) != NULL) + { + strncpy(hw_cfg_cb.local_chip_name, p_name, \ + LOCAL_NAME_BUFFER_LEN-1); + } + else + { + strncpy(hw_cfg_cb.local_chip_name, "UNKNOWN", \ + LOCAL_NAME_BUFFER_LEN-1); + p_name = p_tmp; + } + + hw_cfg_cb.local_chip_name[LOCAL_NAME_BUFFER_LEN-1] = 0; + + BTHWDBG("Chipset %s", hw_cfg_cb.local_chip_name); + + if ((status = hw_config_findpatch(p_name)) == TRUE) + { + if ((hw_cfg_cb.fw_fd = open(p_name, O_RDONLY)) == -1) + { + ALOGE("vendor lib preload failed to open [%s]", p_name); + } + else + { + /* vsc_download_minidriver */ + UINT16_TO_STREAM(p, HCI_VSC_DOWNLOAD_MINIDRV); + *p = 0; /* parameter length */ + + p_buf->len = HCI_CMD_PREAMBLE_SIZE; + hw_cfg_cb.state = HW_CFG_DL_MINIDRIVER; + + is_proceeding = bt_vendor_cbacks->xmit_cb( \ + HCI_VSC_DOWNLOAD_MINIDRV, p_buf, \ + hw_config_cback); + } + } + else + { + ALOGE( \ + "vendor lib preload failed to locate firmware patch file" \ + ); + } + + if (is_proceeding == FALSE) + { + is_proceeding = hw_config_set_bdaddr(p_buf); + } + break; + + case HW_CFG_DL_MINIDRIVER: + /* give time for placing firmware in download mode */ + ms_delay(50); + hw_cfg_cb.state = HW_CFG_DL_FW_PATCH; + /* fall through intentionally */ + case HW_CFG_DL_FW_PATCH: + p_buf->len = read(hw_cfg_cb.fw_fd, p, HCI_CMD_PREAMBLE_SIZE); + if (p_buf->len > 0) + { + if ((p_buf->len < HCI_CMD_PREAMBLE_SIZE) || \ + (opcode == HCI_VSC_LAUNCH_RAM)) + { + ALOGW("firmware patch file might be altered!"); + } + else + { + p_buf->len += read(hw_cfg_cb.fw_fd, \ + p+HCI_CMD_PREAMBLE_SIZE,\ + *(p+HCD_REC_PAYLOAD_LEN_BYTE)); + STREAM_TO_UINT16(opcode,p); + is_proceeding = bt_vendor_cbacks->xmit_cb(opcode, \ + p_buf, hw_config_cback); + break; + } + } + + close(hw_cfg_cb.fw_fd); + hw_cfg_cb.fw_fd = -1; + + /* Normally the firmware patch configuration file + * sets the new starting baud rate at 115200. + * So, we need update host's baud rate accordingly. + */ + ALOGI("bt vendor lib: set UART baud 115200"); + userial_vendor_set_baud(USERIAL_BAUD_115200); + + /* Next, we would like to boost baud rate up again + * to desired working speed. + */ + hw_cfg_cb.f_set_baud_2 = TRUE; + + /* Check if we need to pause a few hundred milliseconds + * before sending down any HCI command. + */ + ms_delay(look_up_fw_settlement_delay()); + + /* fall through intentionally */ + case HW_CFG_START: + if (UART_TARGET_BAUD_RATE > 3000000) + { + /* set UART clock to 48MHz */ + UINT16_TO_STREAM(p, HCI_VSC_WRITE_UART_CLOCK_SETTING); + *p++ = 1; /* parameter length */ + *p = 1; /* (1,"UART CLOCK 48 MHz")(2,"UART CLOCK 24 MHz") */ + + p_buf->len = HCI_CMD_PREAMBLE_SIZE + 1; + hw_cfg_cb.state = HW_CFG_SET_UART_CLOCK; + + is_proceeding = bt_vendor_cbacks->xmit_cb( \ + HCI_VSC_WRITE_UART_CLOCK_SETTING, \ + p_buf, hw_config_cback); + break; + } + /* fall through intentionally */ + case HW_CFG_SET_UART_CLOCK: + /* set controller's UART baud rate to 3M */ + UINT16_TO_STREAM(p, HCI_VSC_UPDATE_BAUDRATE); + *p++ = UPDATE_BAUDRATE_CMD_PARAM_SIZE; /* parameter length */ + *p++ = 0; /* encoded baud rate */ + *p++ = 0; /* use encoded form */ + UINT32_TO_STREAM(p, UART_TARGET_BAUD_RATE); + + p_buf->len = HCI_CMD_PREAMBLE_SIZE + \ + UPDATE_BAUDRATE_CMD_PARAM_SIZE; + hw_cfg_cb.state = (hw_cfg_cb.f_set_baud_2) ? \ + HW_CFG_SET_UART_BAUD_2 : HW_CFG_SET_UART_BAUD_1; + + is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_VSC_UPDATE_BAUDRATE, \ + p_buf, hw_config_cback); + break; + + case HW_CFG_SET_UART_BAUD_2: + /* update baud rate of host's UART port */ + ALOGI("bt vendor lib: set UART baud %i", UART_TARGET_BAUD_RATE); + userial_vendor_set_baud( \ + line_speed_to_userial_baud(UART_TARGET_BAUD_RATE) \ + ); + + if ((is_proceeding = hw_config_set_bdaddr(p_buf)) == TRUE) + break; + + /* fall through intentionally */ + case HW_CFG_SET_BD_ADDR: + ALOGI("vendor lib fwcfg completed"); + bt_vendor_cbacks->dealloc(p_buf); + bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS); + + hw_cfg_cb.state = 0; + + if (hw_cfg_cb.fw_fd != -1) + { + close(hw_cfg_cb.fw_fd); + hw_cfg_cb.fw_fd = -1; + } + + is_proceeding = TRUE; + break; + } // switch(hw_cfg_cb.state) + } // if (p_buf != NULL) + + /* Free the RX event buffer */ + if (bt_vendor_cbacks) + bt_vendor_cbacks->dealloc(p_evt_buf); + + if (is_proceeding == FALSE) + { + ALOGE("vendor lib fwcfg aborted!!!"); + if (bt_vendor_cbacks) + { + if (p_buf != NULL) + bt_vendor_cbacks->dealloc(p_buf); + + bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL); + } + + if (hw_cfg_cb.fw_fd != -1) + { + close(hw_cfg_cb.fw_fd); + hw_cfg_cb.fw_fd = -1; + } + + hw_cfg_cb.state = 0; + } +} + +/****************************************************************************** +** LPM Static Functions +******************************************************************************/ + +/******************************************************************************* +** +** Function hw_lpm_ctrl_cback +** +** Description Callback function for lpm enable/disable rquest +** +** Returns None +** +*******************************************************************************/ +void hw_lpm_ctrl_cback(void *p_mem) +{ + HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem; + bt_vendor_op_result_t status = BT_VND_OP_RESULT_FAIL; + + if (*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0) + { + status = BT_VND_OP_RESULT_SUCCESS; + } + + if (bt_vendor_cbacks) + { + bt_vendor_cbacks->lpm_cb(status); + bt_vendor_cbacks->dealloc(p_evt_buf); + } +} + + +#if (SCO_CFG_INCLUDED == TRUE) +/***************************************************************************** +** SCO Configuration Static Functions +*****************************************************************************/ + +/******************************************************************************* +** +** Function hw_sco_cfg_cback +** +** Description Callback function for SCO configuration rquest +** +** Returns None +** +*******************************************************************************/ +void hw_sco_cfg_cback(void *p_mem) +{ + HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem; + uint8_t *p; + uint16_t opcode; + HC_BT_HDR *p_buf=NULL; + + p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE; + STREAM_TO_UINT16(opcode,p); + + /* Free the RX event buffer */ + if (bt_vendor_cbacks) + bt_vendor_cbacks->dealloc(p_evt_buf); + +#if (!defined(SCO_USE_I2S_INTERFACE) || (SCO_USE_I2S_INTERFACE == FALSE)) + if (opcode == HCI_VSC_WRITE_SCO_PCM_INT_PARAM) + { + uint8_t ret = FALSE; + + /* Ask a new buffer to hold WRITE_PCM_DATA_FORMAT_PARAM command */ + if (bt_vendor_cbacks) + p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \ + HCI_CMD_PREAMBLE_SIZE + \ + PCM_DATA_FORMAT_PARAM_SIZE); + if (p_buf) + { + p_buf->event = MSG_STACK_TO_HC_HCI_CMD; + p_buf->offset = 0; + p_buf->layer_specific = 0; + p_buf->len = HCI_CMD_PREAMBLE_SIZE + PCM_DATA_FORMAT_PARAM_SIZE; + + p = (uint8_t *) (p_buf + 1); + UINT16_TO_STREAM(p, HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM); + *p++ = PCM_DATA_FORMAT_PARAM_SIZE; + memcpy(p, &bt_pcm_data_fmt_param, PCM_DATA_FORMAT_PARAM_SIZE); + + if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM,\ + p_buf, hw_sco_cfg_cback)) == FALSE) + { + bt_vendor_cbacks->dealloc(p_buf); + } + else + return; + } + } +#endif // !SCO_USE_I2S_INTERFACE + +if (bt_vendor_cbacks) + bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_SUCCESS); +} +#endif // SCO_CFG_INCLUDED + +/***************************************************************************** +** Hardware Configuration Interface Functions +*****************************************************************************/ + + +/******************************************************************************* +** +** Function hw_config_start +** +** Description Kick off controller initialization process +** +** Returns None +** +*******************************************************************************/ +void hw_config_start(void) +{ + HC_BT_HDR *p_buf = NULL; + uint8_t *p; + + hw_cfg_cb.state = 0; + hw_cfg_cb.fw_fd = -1; + hw_cfg_cb.f_set_baud_2 = FALSE; + + /* Start from sending HCI_RESET */ + + if (bt_vendor_cbacks) + { + p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \ + HCI_CMD_PREAMBLE_SIZE); + } + + if (p_buf) + { + p_buf->event = MSG_STACK_TO_HC_HCI_CMD; + p_buf->offset = 0; + p_buf->layer_specific = 0; + p_buf->len = HCI_CMD_PREAMBLE_SIZE; + + p = (uint8_t *) (p_buf + 1); + UINT16_TO_STREAM(p, HCI_RESET); + *p = 0; /* parameter length */ + + hw_cfg_cb.state = HW_CFG_START; + + bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf, hw_config_cback); + } + else + { + if (bt_vendor_cbacks) + { + ALOGE("vendor lib fw conf aborted [no buffer]"); + bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL); + } + } +} + +/******************************************************************************* +** +** Function hw_lpm_enable +** +** Description Enalbe/Disable LPM +** +** Returns TRUE/FALSE +** +*******************************************************************************/ +uint8_t hw_lpm_enable(uint8_t turn_on) +{ + HC_BT_HDR *p_buf = NULL; + uint8_t *p; + uint8_t ret = FALSE; + + if (bt_vendor_cbacks) + p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \ + HCI_CMD_PREAMBLE_SIZE + \ + LPM_CMD_PARAM_SIZE); + + if (p_buf) + { + p_buf->event = MSG_STACK_TO_HC_HCI_CMD; + p_buf->offset = 0; + p_buf->layer_specific = 0; + p_buf->len = HCI_CMD_PREAMBLE_SIZE + LPM_CMD_PARAM_SIZE; + + p = (uint8_t *) (p_buf + 1); + UINT16_TO_STREAM(p, HCI_VSC_WRITE_SLEEP_MODE); + *p++ = LPM_CMD_PARAM_SIZE; /* parameter length */ + + if (turn_on) + { + memcpy(p, &lpm_param, LPM_CMD_PARAM_SIZE); + } + else + { + memset(p, 0, LPM_CMD_PARAM_SIZE); + } + + if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_SLEEP_MODE, p_buf, \ + hw_lpm_ctrl_cback)) == FALSE) + { + bt_vendor_cbacks->dealloc(p_buf); + } + } + + if ((ret == FALSE) && bt_vendor_cbacks) + bt_vendor_cbacks->lpm_cb(BT_VND_OP_RESULT_FAIL); + + return ret; +} + +/******************************************************************************* +** +** Function hw_lpm_get_idle_timeout +** +** Description Calculate idle time based on host stack idle threshold +** +** Returns idle timeout value +** +*******************************************************************************/ +uint32_t hw_lpm_get_idle_timeout(void) +{ + uint32_t timeout_ms; + + /* set idle time to be LPM_IDLE_TIMEOUT_MULTIPLE times of + * host stack idle threshold (in 300ms/25ms) + */ + timeout_ms = (uint32_t)lpm_param.host_stack_idle_threshold \ + * LPM_IDLE_TIMEOUT_MULTIPLE; + + if (strstr(hw_cfg_cb.local_chip_name, "BCM4325") != NULL) + timeout_ms *= 25; // 12.5 or 25 ? + else + timeout_ms *= 300; + + return timeout_ms; +} + +/******************************************************************************* +** +** Function hw_lpm_set_wake_state +** +** Description Assert/Deassert BT_WAKE +** +** Returns None +** +*******************************************************************************/ +void hw_lpm_set_wake_state(uint8_t wake_assert) +{ + uint8_t state = (wake_assert) ? UPIO_ASSERT : UPIO_DEASSERT; + + upio_set(UPIO_BT_WAKE, state, lpm_param.bt_wake_polarity); +} + +#if (SCO_CFG_INCLUDED == TRUE) +/******************************************************************************* +** +** Function hw_sco_config +** +** Description Configure SCO related hardware settings +** +** Returns None +** +*******************************************************************************/ +void hw_sco_config(void) +{ + HC_BT_HDR *p_buf = NULL; + uint8_t *p, ret; + +#if (!defined(SCO_USE_I2S_INTERFACE) || (SCO_USE_I2S_INTERFACE == FALSE)) + uint16_t cmd_u16 = HCI_CMD_PREAMBLE_SIZE + SCO_PCM_PARAM_SIZE; +#else + uint16_t cmd_u16 = HCI_CMD_PREAMBLE_SIZE + SCO_I2SPCM_PARAM_SIZE; +#endif + + if (bt_vendor_cbacks) + p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE+cmd_u16); + + if (p_buf) + { + p_buf->event = MSG_STACK_TO_HC_HCI_CMD; + p_buf->offset = 0; + p_buf->layer_specific = 0; + p_buf->len = cmd_u16; + + p = (uint8_t *) (p_buf + 1); +#if (!defined(SCO_USE_I2S_INTERFACE) || (SCO_USE_I2S_INTERFACE == FALSE)) + UINT16_TO_STREAM(p, HCI_VSC_WRITE_SCO_PCM_INT_PARAM); + *p++ = SCO_PCM_PARAM_SIZE; + memcpy(p, &bt_sco_param, SCO_PCM_PARAM_SIZE); + cmd_u16 = HCI_VSC_WRITE_SCO_PCM_INT_PARAM; + ALOGI("SCO PCM configure {%d, %d, %d, %d, %d}", + bt_sco_param[0], bt_sco_param[1], bt_sco_param[2], bt_sco_param[3], \ + bt_sco_param[4]); + +#else + UINT16_TO_STREAM(p, HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM); + *p++ = SCO_I2SPCM_PARAM_SIZE; + memcpy(p, &bt_sco_param, SCO_I2SPCM_PARAM_SIZE); + cmd_u16 = HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM; + ALOGI("SCO over I2SPCM interface {%d, %d, %d, %d}", + bt_sco_param[0], bt_sco_param[1], bt_sco_param[2], bt_sco_param[3]); +#endif + + if ((ret=bt_vendor_cbacks->xmit_cb(cmd_u16, p_buf, hw_sco_cfg_cback)) \ + == FALSE) + { + bt_vendor_cbacks->dealloc(p_buf); + } + else + return; + } + + if (bt_vendor_cbacks) + { + ALOGE("vendor lib scocfg aborted"); + bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_FAIL); + } +} +#endif // SCO_CFG_INCLUDED + +/******************************************************************************* +** +** Function hw_set_patch_file_path +** +** Description Set the location of firmware patch file +** +** Returns 0 : Success +** Otherwise : Fail +** +*******************************************************************************/ +int hw_set_patch_file_path(char *p_conf_name, char *p_conf_value, int param) +{ + + strcpy(fw_patchfile_path, p_conf_value); + + return 0; +} + +/******************************************************************************* +** +** Function hw_set_patch_file_name +** +** Description Give the specific firmware patch filename +** +** Returns 0 : Success +** Otherwise : Fail +** +*******************************************************************************/ +int hw_set_patch_file_name(char *p_conf_name, char *p_conf_value, int param) +{ + + strcpy(fw_patchfile_name, p_conf_value); + + return 0; +} + +#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE) +/******************************************************************************* +** +** Function hw_set_patch_settlement_delay +** +** Description Give the specific firmware patch settlement time in milliseconds +** +** Returns 0 : Success +** Otherwise : Fail +** +*******************************************************************************/ +int hw_set_patch_settlement_delay(char *p_conf_name, char *p_conf_value, int param) +{ + fw_patch_settlement_delay = atoi(p_conf_value); + + return 0; +} +#endif //VENDOR_LIB_RUNTIME_TUNING_ENABLED + diff --git a/libbt/src/upio.c b/libbt/src/upio.c new file mode 100644 index 0000000..d32f334 --- /dev/null +++ b/libbt/src/upio.c @@ -0,0 +1,298 @@ +/****************************************************************************** + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Filename: upio.c + * + * Description: Contains I/O functions, like + * rfkill control + * BT_WAKE/HOST_WAKE control + * + ******************************************************************************/ + +#define LOG_TAG "bt_upio" + +#include <utils/Log.h> +#include <fcntl.h> +#include <errno.h> +#include <cutils/properties.h> +#include "bt_vendor_brcm.h" +#include "upio.h" +#include "userial_vendor.h" + +/****************************************************************************** +** Constants & Macros +******************************************************************************/ + +#ifndef UPIO_DBG +#define UPIO_DBG FALSE +#endif + +#if (UPIO_DBG == TRUE) +#define UPIODBG(param, ...) {ALOGD(param, ## __VA_ARGS__);} +#else +#define UPIODBG(param, ...) {} +#endif + +/****************************************************************************** +** Local type definitions +******************************************************************************/ + +/****************************************************************************** +** Static variables +******************************************************************************/ + +static uint8_t upio_state[UPIO_MAX_COUNT]; +static int rfkill_id = -1; +static int bt_emul_enable = 0; +static char *rfkill_state_path = NULL; + +/****************************************************************************** +** Static functions +******************************************************************************/ + +/* for friendly debugging outpout string */ +static char *lpm_state[] = { + "UNKNOWN", + "de-asserted", + "asserted" +}; + +/***************************************************************************** +** Bluetooth On/Off Static Functions +*****************************************************************************/ +static int is_emulator_context(void) +{ + char value[PROPERTY_VALUE_MAX]; + + property_get("ro.kernel.qemu", value, "0"); + UPIODBG("is_emulator_context : %s", value); + if (strcmp(value, "1") == 0) { + return 1; + } + return 0; +} + +static int is_rfkill_disabled(void) +{ + char value[PROPERTY_VALUE_MAX]; + + property_get("ro.rfkilldisabled", value, "0"); + UPIODBG("is_rfkill_disabled ? [%s]", value); + + if (strcmp(value, "1") == 0) { + return UPIO_BT_POWER_ON; + } + + return UPIO_BT_POWER_OFF; +} + +static int init_rfkill() +{ + char path[64]; + char buf[16]; + int fd, sz, id; + + if (is_rfkill_disabled()) + return -1; + + for (id = 0; ; id++) + { + snprintf(path, sizeof(path), "/sys/class/rfkill/rfkill%d/type", id); + fd = open(path, O_RDONLY); + if (fd < 0) + { + ALOGE("init_rfkill : open(%s) failed: %s (%d)\n", \ + path, strerror(errno), errno); + return -1; + } + + sz = read(fd, &buf, sizeof(buf)); + close(fd); + + if (sz >= 9 && memcmp(buf, "bluetooth", 9) == 0) + { + rfkill_id = id; + break; + } + } + + asprintf(&rfkill_state_path, "/sys/class/rfkill/rfkill%d/state", rfkill_id); + return 0; +} + +/***************************************************************************** +** LPM Static Functions +*****************************************************************************/ + +/***************************************************************************** +** UPIO Interface Functions +*****************************************************************************/ + +/******************************************************************************* +** +** Function upio_init +** +** Description Initialization +** +** Returns None +** +*******************************************************************************/ +void upio_init(void) +{ + memset(upio_state, UPIO_UNKNOWN, UPIO_MAX_COUNT); +} + +/******************************************************************************* +** +** Function upio_cleanup +** +** Description Clean up +** +** Returns None +** +*******************************************************************************/ +void upio_cleanup(void) +{ +} + +/******************************************************************************* +** +** Function upio_set_bluetooth_power +** +** Description Interact with low layer driver to set Bluetooth power +** on/off. +** +** Returns 0 : SUCCESS or Not-Applicable +** <0 : ERROR +** +*******************************************************************************/ +int upio_set_bluetooth_power(int on) +{ + int sz; + int fd = -1; + int ret = -1; + char buffer = '0'; + + switch(on) + { + case UPIO_BT_POWER_OFF: + buffer = '0'; + break; + + case UPIO_BT_POWER_ON: + buffer = '1'; + break; + } + + if (is_emulator_context()) + { + /* if new value is same as current, return -1 */ + if (bt_emul_enable == on) + return ret; + + UPIODBG("set_bluetooth_power [emul] %d", on); + + bt_emul_enable = on; + return 0; + } + + /* check if we have rfkill interface */ + if (is_rfkill_disabled()) + return 0; + + if (rfkill_id == -1) + { + if (init_rfkill()) + return ret; + } + + fd = open(rfkill_state_path, O_WRONLY); + + if (fd < 0) + { + ALOGE("set_bluetooth_power : open(%s) for write failed: %s (%d)", + rfkill_state_path, strerror(errno), errno); + return ret; + } + + sz = write(fd, &buffer, 1); + + if (sz < 0) { + ALOGE("set_bluetooth_power : write(%s) failed: %s (%d)", + rfkill_state_path, strerror(errno),errno); + } + else + ret = 0; + + if (fd >= 0) + close(fd); + + return ret; +} + + +/******************************************************************************* +** +** 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; + + switch (pio) + { + case UPIO_BT_WAKE: + + if (upio_state[UPIO_BT_WAKE] == action) + { + UPIODBG("BT_WAKE is %s already", lpm_state[action]); + return; + } + + upio_state[UPIO_BT_WAKE] = action; + + /**************************************** + * !!! TODO !!! + * + * === Custom Porting Required === + * + * Platform dependent user-to-kernel + * interface is required to set output + * state of physical BT_WAKE pin. + ****************************************/ +#if (BT_WAKE_VIA_USERIAL_IOCTL == TRUE) + userial_vendor_ioctl( ( (action==UPIO_ASSERT) ? \ + USERIAL_OP_ASSERT_BT_WAKE : USERIAL_OP_DEASSERT_BT_WAKE),\ + NULL); +#endif + break; + + case UPIO_HOST_WAKE: + UPIODBG("upio_set: UPIO_HOST_WAKE"); + break; + } +} + + diff --git a/libbt/src/userial_vendor.c b/libbt/src/userial_vendor.c new file mode 100755 index 0000000..1a745b5 --- /dev/null +++ b/libbt/src/userial_vendor.c @@ -0,0 +1,361 @@ +/****************************************************************************** + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Filename: userial_vendor.c + * + * Description: Contains vendor-specific userial functions + * + ******************************************************************************/ + +#define LOG_TAG "bt_userial_vendor" + +#include <utils/Log.h> +#include <termios.h> +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include "bt_vendor_brcm.h" +#include "userial.h" +#include "userial_vendor.h" + +/****************************************************************************** +** Constants & Macros +******************************************************************************/ + +#ifndef VNDUSERIAL_DBG +#define VNDUSERIAL_DBG FALSE +#endif + +#if (VNDUSERIAL_DBG == TRUE) +#define VNDUSERIALDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);} +#else +#define VNDUSERIALDBG(param, ...) {} +#endif + +#define VND_PORT_NAME_MAXLEN 256 + +/****************************************************************************** +** Local type definitions +******************************************************************************/ + +/* vendor serial control block */ +typedef struct +{ + int fd; /* fd to Bluetooth device */ + struct termios termios; /* serial terminal of BT port */ + char port_name[VND_PORT_NAME_MAXLEN]; +} vnd_userial_cb_t; + +/****************************************************************************** +** Static variables +******************************************************************************/ + +static vnd_userial_cb_t vnd_userial; + +/***************************************************************************** +** Helper Functions +*****************************************************************************/ + +/******************************************************************************* +** +** Function userial_to_tcio_baud +** +** Description helper function converts USERIAL baud rates into TCIO +** conforming baud rates +** +** Returns TRUE/FALSE +** +*******************************************************************************/ +uint8_t userial_to_tcio_baud(uint8_t cfg_baud, uint32_t *baud) +{ + if (cfg_baud == USERIAL_BAUD_115200) + *baud = B115200; + else if (cfg_baud == USERIAL_BAUD_4M) + *baud = B4000000; + else if (cfg_baud == USERIAL_BAUD_3M) + *baud = B3000000; + else if (cfg_baud == USERIAL_BAUD_2M) + *baud = B2000000; + else if (cfg_baud == USERIAL_BAUD_1M) + *baud = B1000000; + else if (cfg_baud == USERIAL_BAUD_921600) + *baud = B921600; + else if (cfg_baud == USERIAL_BAUD_460800) + *baud = B460800; + else if (cfg_baud == USERIAL_BAUD_230400) + *baud = B230400; + else if (cfg_baud == USERIAL_BAUD_57600) + *baud = B57600; + else if (cfg_baud == USERIAL_BAUD_19200) + *baud = B19200; + else if (cfg_baud == USERIAL_BAUD_9600) + *baud = B9600; + else if (cfg_baud == USERIAL_BAUD_1200) + *baud = B1200; + else if (cfg_baud == USERIAL_BAUD_600) + *baud = B600; + else + { + ALOGE( "userial vendor open: unsupported baud idx %i", cfg_baud); + *baud = B115200; + return FALSE; + } + + return TRUE; +} + +#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) +/******************************************************************************* +** +** Function userial_ioctl_init_bt_wake +** +** Description helper function to set the open state of the bt_wake if ioctl +** is used. it should not hurt in the rfkill case but it might +** be better to compile it out. +** +** Returns none +** +*******************************************************************************/ +void userial_ioctl_init_bt_wake(int fd) +{ + uint32_t bt_wake_state; + + /* assert BT_WAKE through ioctl */ + ioctl(fd, USERIAL_IOCTL_BT_WAKE_ASSERT, NULL); + ioctl(fd, USERIAL_IOCTL_BT_WAKE_GET_ST, &bt_wake_state); + VNDUSERIALDBG("userial_ioctl_init_bt_wake read back BT_WAKE state=%i", \ + bt_wake_state); +} +#endif // (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) + + +/***************************************************************************** +** Userial Vendor API Functions +*****************************************************************************/ + +/******************************************************************************* +** +** Function userial_vendor_init +** +** Description Initialize userial vendor-specific control block +** +** Returns None +** +*******************************************************************************/ +void userial_vendor_init(void) +{ + vnd_userial.fd = -1; + snprintf(vnd_userial.port_name, VND_PORT_NAME_MAXLEN, "%s", \ + BLUETOOTH_UART_DEVICE_PORT); +} + +/******************************************************************************* +** +** Function userial_vendor_open +** +** Description Open the serial port with the given configuration +** +** Returns device fd +** +*******************************************************************************/ +int userial_vendor_open(tUSERIAL_CFG *p_cfg) +{ + uint32_t baud; + uint8_t data_bits; + uint16_t parity; + uint8_t stop_bits; + + vnd_userial.fd = -1; + + if (!userial_to_tcio_baud(p_cfg->baud, &baud)) + { + return -1; + } + + if(p_cfg->fmt & USERIAL_DATABITS_8) + data_bits = CS8; + else if(p_cfg->fmt & USERIAL_DATABITS_7) + data_bits = CS7; + else if(p_cfg->fmt & USERIAL_DATABITS_6) + data_bits = CS6; + else if(p_cfg->fmt & USERIAL_DATABITS_5) + data_bits = CS5; + else + { + ALOGE("userial vendor open: unsupported data bits"); + return -1; + } + + if(p_cfg->fmt & USERIAL_PARITY_NONE) + parity = 0; + else if(p_cfg->fmt & USERIAL_PARITY_EVEN) + parity = PARENB; + else if(p_cfg->fmt & USERIAL_PARITY_ODD) + parity = (PARENB | PARODD); + else + { + ALOGE("userial vendor open: unsupported parity bit mode"); + return -1; + } + + if(p_cfg->fmt & USERIAL_STOPBITS_1) + stop_bits = 0; + else if(p_cfg->fmt & USERIAL_STOPBITS_2) + stop_bits = CSTOPB; + else + { + ALOGE("userial vendor open: unsupported stop bits"); + return -1; + } + + ALOGI("userial vendor open: opening %s", vnd_userial.port_name); + + if ((vnd_userial.fd = open(vnd_userial.port_name, O_RDWR)) == -1) + { + ALOGE("userial vendor open: unable to open %s", vnd_userial.port_name); + return -1; + } + + tcflush(vnd_userial.fd, TCIOFLUSH); + + tcgetattr(vnd_userial.fd, &vnd_userial.termios); + cfmakeraw(&vnd_userial.termios); + vnd_userial.termios.c_cflag |= (CRTSCTS | stop_bits); + tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios); + tcflush(vnd_userial.fd, TCIOFLUSH); + + tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios); + tcflush(vnd_userial.fd, TCIOFLUSH); + tcflush(vnd_userial.fd, TCIOFLUSH); + + /* set input/output baudrate */ + cfsetospeed(&vnd_userial.termios, baud); + cfsetispeed(&vnd_userial.termios, baud); + tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios); + +#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) + userial_ioctl_init_bt_wake(vnd_userial.fd); +#endif + + ALOGI("device fd = %d open", vnd_userial.fd); + + return vnd_userial.fd; +} + +/******************************************************************************* +** +** Function userial_vendor_close +** +** Description Conduct vendor-specific close work +** +** Returns None +** +*******************************************************************************/ +void userial_vendor_close(void) +{ + int result; + + if (vnd_userial.fd == -1) + return; + +#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) + /* de-assert bt_wake BEFORE closing port */ + ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL); +#endif + + ALOGI("device fd = %d close", vnd_userial.fd); + + if ((result = close(vnd_userial.fd)) < 0) + ALOGE( "close(fd:%d) FAILED result:%d", vnd_userial.fd, result); + + vnd_userial.fd = -1; +} + +/******************************************************************************* +** +** Function userial_vendor_set_baud +** +** Description Set new baud rate +** +** Returns None +** +*******************************************************************************/ +void userial_vendor_set_baud(uint8_t userial_baud) +{ + uint32_t tcio_baud; + + userial_to_tcio_baud(userial_baud, &tcio_baud); + + cfsetospeed(&vnd_userial.termios, tcio_baud); + cfsetispeed(&vnd_userial.termios, tcio_baud); + tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios); +} + +/******************************************************************************* +** +** Function userial_vendor_ioctl +** +** Description ioctl inteface +** +** Returns None +** +*******************************************************************************/ +void userial_vendor_ioctl(userial_vendor_ioctl_op_t op, void *p_data) +{ + switch(op) + { +#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) + case USERIAL_OP_ASSERT_BT_WAKE: + VNDUSERIALDBG("## userial_vendor_ioctl: Asserting BT_Wake ##"); + ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_ASSERT, NULL); + break; + + case USERIAL_OP_DEASSERT_BT_WAKE: + VNDUSERIALDBG("## userial_vendor_ioctl: De-asserting BT_Wake ##"); + ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL); + break; + + case USERIAL_OP_GET_BT_WAKE_STATE: + ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_GET_ST, p_data); + break; +#endif // (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) + + default: + break; + } +} + +/******************************************************************************* +** +** Function userial_set_port +** +** Description Configure UART port name +** +** Returns 0 : Success +** Otherwise : Fail +** +*******************************************************************************/ +int userial_set_port(char *p_conf_name, char *p_conf_value, int param) +{ + strcpy(vnd_userial.port_name, p_conf_value); + + return 0; +} + diff --git a/libbt/vnd_buildcfg.mk b/libbt/vnd_buildcfg.mk new file mode 100644 index 0000000..b65033a --- /dev/null +++ b/libbt/vnd_buildcfg.mk @@ -0,0 +1,16 @@ +intermediates := $(local-intermediates-dir) + +SRC := $(call my-dir)/include/$(addprefix vnd_, $(addsuffix .txt,$(basename $(TARGET_DEVICE)))) +ifeq (,$(wildcard $(SRC))) +# configuration file does not exist. Use default one +SRC := $(call my-dir)/include/vnd_generic.txt +endif +GEN := $(intermediates)/vnd_buildcfg.h +TOOL := $(TOP_DIR)external/bluetooth/bluedroid/tools/gen-buildcfg.sh + +$(GEN): PRIVATE_PATH := $(call my-dir) +$(GEN): PRIVATE_CUSTOM_TOOL = $(TOOL) $< $@ +$(GEN): $(SRC) $(TOOL) + $(transform-generated-source) + +LOCAL_GENERATED_SOURCES += $(GEN) |