diff options
Diffstat (limited to 'libbt/src/upio.c')
-rw-r--r-- | libbt/src/upio.c | 298 |
1 files changed, 298 insertions, 0 deletions
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; + } +} + + |