10b966c5eSopenharmony_ci/****************************************************************************** 20b966c5eSopenharmony_ci * 30b966c5eSopenharmony_ci * Copyright (C) 2009-2012 Broadcom Corporation 40b966c5eSopenharmony_ci * 50b966c5eSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 60b966c5eSopenharmony_ci * you may not use this file except in compliance with the License. 70b966c5eSopenharmony_ci * You may obtain a copy of the License at: 80b966c5eSopenharmony_ci * 90b966c5eSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 100b966c5eSopenharmony_ci * 110b966c5eSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 120b966c5eSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 130b966c5eSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 140b966c5eSopenharmony_ci * See the License for the specific language governing permissions and 150b966c5eSopenharmony_ci * limitations under the License. 160b966c5eSopenharmony_ci * 170b966c5eSopenharmony_ci ******************************************************************************/ 180b966c5eSopenharmony_ci 190b966c5eSopenharmony_ci/****************************************************************************** 200b966c5eSopenharmony_ci * 210b966c5eSopenharmony_ci * Filename: upio.c 220b966c5eSopenharmony_ci * 230b966c5eSopenharmony_ci * Description: Contains I/O functions, like 240b966c5eSopenharmony_ci * rfkill control 250b966c5eSopenharmony_ci * BT_WAKE/HOST_WAKE control 260b966c5eSopenharmony_ci * 270b966c5eSopenharmony_ci ******************************************************************************/ 280b966c5eSopenharmony_ci 290b966c5eSopenharmony_ci#define LOG_TAG "bt_upio" 300b966c5eSopenharmony_ci 310b966c5eSopenharmony_ci#include <fcntl.h> 320b966c5eSopenharmony_ci#include <errno.h> 330b966c5eSopenharmony_ci#include <string.h> 340b966c5eSopenharmony_ci#include <stdio.h> 350b966c5eSopenharmony_ci#include <unistd.h> 360b966c5eSopenharmony_ci#include <time.h> 370b966c5eSopenharmony_ci#include <utils/Log.h> 380b966c5eSopenharmony_ci#include "bt_vendor_brcm.h" 390b966c5eSopenharmony_ci#include "userial_vendor.h" 400b966c5eSopenharmony_ci#include "upio.h" 410b966c5eSopenharmony_ci 420b966c5eSopenharmony_ci/****************************************************************************** 430b966c5eSopenharmony_ci** Constants & Macros 440b966c5eSopenharmony_ci******************************************************************************/ 450b966c5eSopenharmony_ci 460b966c5eSopenharmony_ci#ifndef UPIO_DBG 470b966c5eSopenharmony_ci#define UPIO_DBG FALSE 480b966c5eSopenharmony_ci#endif 490b966c5eSopenharmony_ci 500b966c5eSopenharmony_ci#if (UPIO_DBG == TRUE) 510b966c5eSopenharmony_ci#define UPIODBG(param, ...) \ 520b966c5eSopenharmony_ci { \ 530b966c5eSopenharmony_ci HILOGD(param, ##__VA_ARGS__); \ 540b966c5eSopenharmony_ci } 550b966c5eSopenharmony_ci#else 560b966c5eSopenharmony_ci#define UPIODBG(param, ...) \ 570b966c5eSopenharmony_ci { \ 580b966c5eSopenharmony_ci HILOGD(param, ##__VA_ARGS__); \ 590b966c5eSopenharmony_ci } 600b966c5eSopenharmony_ci#endif 610b966c5eSopenharmony_ci 620b966c5eSopenharmony_ci/****************************************************************************** 630b966c5eSopenharmony_ci** Local type definitions 640b966c5eSopenharmony_ci******************************************************************************/ 650b966c5eSopenharmony_ci 660b966c5eSopenharmony_ci#if (BT_WAKE_VIA_PROC == TRUE) 670b966c5eSopenharmony_ci 680b966c5eSopenharmony_ci/* proc fs node for enable/disable lpm mode */ 690b966c5eSopenharmony_ci#ifndef VENDOR_LPM_PROC_NODE 700b966c5eSopenharmony_ci#define VENDOR_LPM_PROC_NODE "/proc/bluetooth/sleep/lpm" 710b966c5eSopenharmony_ci#endif 720b966c5eSopenharmony_ci 730b966c5eSopenharmony_ci/* proc fs node for notifying write request */ 740b966c5eSopenharmony_ci#ifndef VENDOR_BTWRITE_PROC_NODE 750b966c5eSopenharmony_ci#define VENDOR_BTWRITE_PROC_NODE "/proc/bluetooth/sleep/btwrite" 760b966c5eSopenharmony_ci#endif 770b966c5eSopenharmony_ci 780b966c5eSopenharmony_ci/* 790b966c5eSopenharmony_ci * Maximum btwrite assertion holding time without consecutive btwrite kicking. 800b966c5eSopenharmony_ci * This value is correlative(shorter) to the in-working timeout period set in 810b966c5eSopenharmony_ci * the bluesleep LPM code. The current value used in bluesleep is 10sec. 820b966c5eSopenharmony_ci */ 830b966c5eSopenharmony_ci#ifndef PROC_BTWRITE_TIMER_TIMEOUT_MS 840b966c5eSopenharmony_ci#define PROC_BTWRITE_TIMER_TIMEOUT_MS 8000 850b966c5eSopenharmony_ci#endif 860b966c5eSopenharmony_ci 870b966c5eSopenharmony_ci/* lpm proc control block */ 880b966c5eSopenharmony_citypedef struct { 890b966c5eSopenharmony_ci uint8_t btwrite_active; 900b966c5eSopenharmony_ci uint8_t timer_created; 910b966c5eSopenharmony_ci timer_t timer_id; 920b966c5eSopenharmony_ci uint32_t timeout_ms; 930b966c5eSopenharmony_ci} vnd_lpm_proc_cb_t; 940b966c5eSopenharmony_ci 950b966c5eSopenharmony_cistatic vnd_lpm_proc_cb_t lpm_proc_cb; 960b966c5eSopenharmony_ci#endif 970b966c5eSopenharmony_ci 980b966c5eSopenharmony_ci/****************************************************************************** 990b966c5eSopenharmony_ci** Static variables 1000b966c5eSopenharmony_ci******************************************************************************/ 1010b966c5eSopenharmony_ci 1020b966c5eSopenharmony_cistatic uint8_t upio_state[UPIO_MAX_COUNT]; 1030b966c5eSopenharmony_cistatic int rfkill_id = -1; 1040b966c5eSopenharmony_cistatic int bt_emul_enable = 0; 1050b966c5eSopenharmony_cistatic char rfkill_state_path[128]; 1060b966c5eSopenharmony_ci 1070b966c5eSopenharmony_ci/****************************************************************************** 1080b966c5eSopenharmony_ci** Static functions 1090b966c5eSopenharmony_ci******************************************************************************/ 1100b966c5eSopenharmony_ci 1110b966c5eSopenharmony_ci/* for friendly debugging outpout string */ 1120b966c5eSopenharmony_cistatic char *lpm_mode[] = { 1130b966c5eSopenharmony_ci "UNKNOWN", 1140b966c5eSopenharmony_ci "disabled", 1150b966c5eSopenharmony_ci "enabled" 1160b966c5eSopenharmony_ci}; 1170b966c5eSopenharmony_ci 1180b966c5eSopenharmony_cistatic char *lpm_state[] = { 1190b966c5eSopenharmony_ci "UNKNOWN", 1200b966c5eSopenharmony_ci "de-asserted", 1210b966c5eSopenharmony_ci "asserted" 1220b966c5eSopenharmony_ci}; 1230b966c5eSopenharmony_ci 1240b966c5eSopenharmony_ci/***************************************************************************** 1250b966c5eSopenharmony_ci** Bluetooth On/Off Static Functions 1260b966c5eSopenharmony_ci*****************************************************************************/ 1270b966c5eSopenharmony_cistatic int is_emulator_context(void) 1280b966c5eSopenharmony_ci{ 1290b966c5eSopenharmony_ci return 0; 1300b966c5eSopenharmony_ci} 1310b966c5eSopenharmony_ci 1320b966c5eSopenharmony_cistatic int is_rfkill_disabled(void) 1330b966c5eSopenharmony_ci{ 1340b966c5eSopenharmony_ci return UPIO_BT_POWER_OFF; 1350b966c5eSopenharmony_ci} 1360b966c5eSopenharmony_ci 1370b966c5eSopenharmony_cistatic int init_rfkill(void) 1380b966c5eSopenharmony_ci{ 1390b966c5eSopenharmony_ci char path[64]; 1400b966c5eSopenharmony_ci char buf[16]; 1410b966c5eSopenharmony_ci int fd, sz, id; 1420b966c5eSopenharmony_ci 1430b966c5eSopenharmony_ci for (id = 0;; id++) { 1440b966c5eSopenharmony_ci if (snprintf_s(path, sizeof(path), sizeof(path), "/sys/class/rfkill/rfkill%d/type", id) < 0) { 1450b966c5eSopenharmony_ci return -1; 1460b966c5eSopenharmony_ci } 1470b966c5eSopenharmony_ci 1480b966c5eSopenharmony_ci fd = open(path, O_RDONLY); 1490b966c5eSopenharmony_ci if (fd < 0) { 1500b966c5eSopenharmony_ci HILOGE("init_rfkill : open(%s) failed: %s (%d)\n", 1510b966c5eSopenharmony_ci path, strerror(errno), errno); 1520b966c5eSopenharmony_ci return -1; 1530b966c5eSopenharmony_ci } 1540b966c5eSopenharmony_ci 1550b966c5eSopenharmony_ci sz = read(fd, &buf, sizeof(buf)); 1560b966c5eSopenharmony_ci close(fd); 1570b966c5eSopenharmony_ci 1580b966c5eSopenharmony_ci if (sz >= (int)strlen("bluetooth") && memcmp(buf, "bluetooth", strlen("bluetooth")) == 0) { 1590b966c5eSopenharmony_ci rfkill_id = id; 1600b966c5eSopenharmony_ci break; 1610b966c5eSopenharmony_ci } 1620b966c5eSopenharmony_ci } 1630b966c5eSopenharmony_ci 1640b966c5eSopenharmony_ci (void)sprintf_s(rfkill_state_path, sizeof(rfkill_state_path), "/sys/class/rfkill/rfkill%d/state", rfkill_id); 1650b966c5eSopenharmony_ci return 0; 1660b966c5eSopenharmony_ci} 1670b966c5eSopenharmony_ci 1680b966c5eSopenharmony_ci/***************************************************************************** 1690b966c5eSopenharmony_ci** LPM Static Functions 1700b966c5eSopenharmony_ci*****************************************************************************/ 1710b966c5eSopenharmony_ci 1720b966c5eSopenharmony_ci#if (BT_WAKE_VIA_PROC == TRUE) 1730b966c5eSopenharmony_ci/******************************************************************************* 1740b966c5eSopenharmony_ci** 1750b966c5eSopenharmony_ci** Function proc_btwrite_timeout 1760b966c5eSopenharmony_ci** 1770b966c5eSopenharmony_ci** Description Timeout thread of proc/.../btwrite assertion holding timer 1780b966c5eSopenharmony_ci** 1790b966c5eSopenharmony_ci** Returns None 1800b966c5eSopenharmony_ci** 1810b966c5eSopenharmony_ci*******************************************************************************/ 1820b966c5eSopenharmony_cistatic void proc_btwrite_timeout(union sigval arg) 1830b966c5eSopenharmony_ci{ 1840b966c5eSopenharmony_ci UPIODBG("..%s..", __FUNCTION__); 1850b966c5eSopenharmony_ci lpm_proc_cb.btwrite_active = FALSE; 1860b966c5eSopenharmony_ci /* drive LPM down; this timer should fire only when BT is awake; */ 1870b966c5eSopenharmony_ci upio_set(UPIO_BT_WAKE, UPIO_DEASSERT, 1); 1880b966c5eSopenharmony_ci} 1890b966c5eSopenharmony_ci 1900b966c5eSopenharmony_ci/****************************************************************************** 1910b966c5eSopenharmony_ci ** 1920b966c5eSopenharmony_ci ** Function upio_start_stop_timer 1930b966c5eSopenharmony_ci ** 1940b966c5eSopenharmony_ci ** Description Arm user space timer in case lpm is left asserted 1950b966c5eSopenharmony_ci ** 1960b966c5eSopenharmony_ci ** Returns None 1970b966c5eSopenharmony_ci ** 1980b966c5eSopenharmony_ci *****************************************************************************/ 1990b966c5eSopenharmony_civoid upio_start_stop_timer(int action) 2000b966c5eSopenharmony_ci{ 2010b966c5eSopenharmony_ci struct itimerspec ts; 2020b966c5eSopenharmony_ci 2030b966c5eSopenharmony_ci if (action == UPIO_ASSERT) { 2040b966c5eSopenharmony_ci lpm_proc_cb.btwrite_active = TRUE; 2050b966c5eSopenharmony_ci if (lpm_proc_cb.timer_created == TRUE) { 2060b966c5eSopenharmony_ci ts.it_value.tv_sec = PROC_BTWRITE_TIMER_TIMEOUT_MS / BT_VENDOR_TIME_RAIDX; 2070b966c5eSopenharmony_ci ts.it_value.tv_nsec = BT_VENDOR_TIME_RAIDX * BT_VENDOR_TIME_RAIDX * 2080b966c5eSopenharmony_ci (PROC_BTWRITE_TIMER_TIMEOUT_MS % BT_VENDOR_TIME_RAIDX); 2090b966c5eSopenharmony_ci ts.it_interval.tv_sec = 0; 2100b966c5eSopenharmony_ci ts.it_interval.tv_nsec = 0; 2110b966c5eSopenharmony_ci } 2120b966c5eSopenharmony_ci } else { 2130b966c5eSopenharmony_ci /* unarm timer if writing 0 to lpm; reduce unnecessary user space wakeup */ 2140b966c5eSopenharmony_ci (void)memset_s(&ts, sizeof(ts), 0, sizeof(ts)); 2150b966c5eSopenharmony_ci } 2160b966c5eSopenharmony_ci 2170b966c5eSopenharmony_ci if (timer_settime(lpm_proc_cb.timer_id, 0, &ts, 0) == 0) { 2180b966c5eSopenharmony_ci UPIODBG("%s : timer_settime success", __FUNCTION__); 2190b966c5eSopenharmony_ci } else { 2200b966c5eSopenharmony_ci UPIODBG("%s : timer_settime failed", __FUNCTION__); 2210b966c5eSopenharmony_ci } 2220b966c5eSopenharmony_ci} 2230b966c5eSopenharmony_ci#endif 2240b966c5eSopenharmony_ci 2250b966c5eSopenharmony_ci/***************************************************************************** 2260b966c5eSopenharmony_ci** UPIO Interface Functions 2270b966c5eSopenharmony_ci*****************************************************************************/ 2280b966c5eSopenharmony_ci 2290b966c5eSopenharmony_ci/******************************************************************************* 2300b966c5eSopenharmony_ci** 2310b966c5eSopenharmony_ci** Function upio_init 2320b966c5eSopenharmony_ci** 2330b966c5eSopenharmony_ci** Description Initialization 2340b966c5eSopenharmony_ci** 2350b966c5eSopenharmony_ci** Returns None 2360b966c5eSopenharmony_ci** 2370b966c5eSopenharmony_ci*******************************************************************************/ 2380b966c5eSopenharmony_civoid upio_init(void) 2390b966c5eSopenharmony_ci{ 2400b966c5eSopenharmony_ci memset_s(upio_state, sizeof(upio_state), UPIO_UNKNOWN, UPIO_MAX_COUNT); 2410b966c5eSopenharmony_ci#if (BT_WAKE_VIA_PROC == TRUE) 2420b966c5eSopenharmony_ci memset_s(&lpm_proc_cb, sizeof(vnd_lpm_proc_cb_t), 0, sizeof(vnd_lpm_proc_cb_t)); 2430b966c5eSopenharmony_ci#endif 2440b966c5eSopenharmony_ci} 2450b966c5eSopenharmony_ci 2460b966c5eSopenharmony_ci/******************************************************************************* 2470b966c5eSopenharmony_ci** 2480b966c5eSopenharmony_ci** Function upio_cleanup 2490b966c5eSopenharmony_ci** 2500b966c5eSopenharmony_ci** Description Clean up 2510b966c5eSopenharmony_ci** 2520b966c5eSopenharmony_ci** Returns None 2530b966c5eSopenharmony_ci** 2540b966c5eSopenharmony_ci*******************************************************************************/ 2550b966c5eSopenharmony_civoid upio_cleanup(void) 2560b966c5eSopenharmony_ci{ 2570b966c5eSopenharmony_ci#if (BT_WAKE_VIA_PROC == TRUE) 2580b966c5eSopenharmony_ci if (lpm_proc_cb.timer_created == TRUE) 2590b966c5eSopenharmony_ci timer_delete(lpm_proc_cb.timer_id); 2600b966c5eSopenharmony_ci 2610b966c5eSopenharmony_ci lpm_proc_cb.timer_created = FALSE; 2620b966c5eSopenharmony_ci#endif 2630b966c5eSopenharmony_ci} 2640b966c5eSopenharmony_ci 2650b966c5eSopenharmony_ci/******************************************************************************* 2660b966c5eSopenharmony_ci** 2670b966c5eSopenharmony_ci** Function upio_set_bluetooth_power 2680b966c5eSopenharmony_ci** 2690b966c5eSopenharmony_ci** Description Interact with low layer driver to set Bluetooth power 2700b966c5eSopenharmony_ci** on/off. 2710b966c5eSopenharmony_ci** 2720b966c5eSopenharmony_ci** Returns 0 : SUCCESS or Not-Applicable 2730b966c5eSopenharmony_ci** <0 : ERROR 2740b966c5eSopenharmony_ci** 2750b966c5eSopenharmony_ci*******************************************************************************/ 2760b966c5eSopenharmony_ciint upio_set_bluetooth_power(int on) 2770b966c5eSopenharmony_ci{ 2780b966c5eSopenharmony_ci int sz; 2790b966c5eSopenharmony_ci int fd = -1; 2800b966c5eSopenharmony_ci int ret = -1; 2810b966c5eSopenharmony_ci char buffer = '0'; 2820b966c5eSopenharmony_ci 2830b966c5eSopenharmony_ci switch (on) { 2840b966c5eSopenharmony_ci case UPIO_BT_POWER_OFF: 2850b966c5eSopenharmony_ci buffer = '0'; 2860b966c5eSopenharmony_ci break; 2870b966c5eSopenharmony_ci 2880b966c5eSopenharmony_ci case UPIO_BT_POWER_ON: 2890b966c5eSopenharmony_ci buffer = '1'; 2900b966c5eSopenharmony_ci break; 2910b966c5eSopenharmony_ci default: 2920b966c5eSopenharmony_ci return 0; 2930b966c5eSopenharmony_ci } 2940b966c5eSopenharmony_ci 2950b966c5eSopenharmony_ci if (is_emulator_context()) { 2960b966c5eSopenharmony_ci /* if new value is same as current, return -1 */ 2970b966c5eSopenharmony_ci if (bt_emul_enable == on) { 2980b966c5eSopenharmony_ci return ret; 2990b966c5eSopenharmony_ci } 3000b966c5eSopenharmony_ci 3010b966c5eSopenharmony_ci UPIODBG("set_bluetooth_power [emul] %d", on); 3020b966c5eSopenharmony_ci bt_emul_enable = on; 3030b966c5eSopenharmony_ci return 0; 3040b966c5eSopenharmony_ci } 3050b966c5eSopenharmony_ci 3060b966c5eSopenharmony_ci /* check if we have rfkill interface */ 3070b966c5eSopenharmony_ci if (is_rfkill_disabled()) { 3080b966c5eSopenharmony_ci return 0; 3090b966c5eSopenharmony_ci } 3100b966c5eSopenharmony_ci 3110b966c5eSopenharmony_ci if (rfkill_id == -1) { 3120b966c5eSopenharmony_ci if (init_rfkill()) { 3130b966c5eSopenharmony_ci return ret; 3140b966c5eSopenharmony_ci } 3150b966c5eSopenharmony_ci } 3160b966c5eSopenharmony_ci 3170b966c5eSopenharmony_ci fd = open(rfkill_state_path, O_WRONLY); 3180b966c5eSopenharmony_ci if (fd < 0) { 3190b966c5eSopenharmony_ci HILOGE("set_bluetooth_power : open(%s) for write failed: %s (%d)", 3200b966c5eSopenharmony_ci rfkill_state_path, strerror(errno), errno); 3210b966c5eSopenharmony_ci return ret; 3220b966c5eSopenharmony_ci } 3230b966c5eSopenharmony_ci 3240b966c5eSopenharmony_ci sz = write(fd, &buffer, 1); 3250b966c5eSopenharmony_ci if (sz < 0) { 3260b966c5eSopenharmony_ci HILOGE("set_bluetooth_power : write(%s) failed: %s (%d)", 3270b966c5eSopenharmony_ci rfkill_state_path, strerror(errno), errno); 3280b966c5eSopenharmony_ci } else { 3290b966c5eSopenharmony_ci ret = 0; 3300b966c5eSopenharmony_ci } 3310b966c5eSopenharmony_ci 3320b966c5eSopenharmony_ci if (fd >= 0) { 3330b966c5eSopenharmony_ci close(fd); 3340b966c5eSopenharmony_ci } 3350b966c5eSopenharmony_ci 3360b966c5eSopenharmony_ci return ret; 3370b966c5eSopenharmony_ci} 3380b966c5eSopenharmony_ci 3390b966c5eSopenharmony_ci/******************************************************************************* 3400b966c5eSopenharmony_ci** 3410b966c5eSopenharmony_ci** Function upio_set 3420b966c5eSopenharmony_ci** 3430b966c5eSopenharmony_ci** Description Set i/o based on polarity 3440b966c5eSopenharmony_ci** 3450b966c5eSopenharmony_ci** Returns None 3460b966c5eSopenharmony_ci** 3470b966c5eSopenharmony_ci*******************************************************************************/ 3480b966c5eSopenharmony_civoid upio_set(uint8_t pio, uint8_t action, uint8_t polarity) 3490b966c5eSopenharmony_ci{ 3500b966c5eSopenharmony_ci int rc; 3510b966c5eSopenharmony_ci#if (BT_WAKE_VIA_PROC == TRUE) 3520b966c5eSopenharmony_ci int fd = -1; 3530b966c5eSopenharmony_ci char buffer; 3540b966c5eSopenharmony_ci#endif 3550b966c5eSopenharmony_ci 3560b966c5eSopenharmony_ci UPIODBG("%s : pio %d action %d, polarity %d", __FUNCTION__, pio, action, polarity); 3570b966c5eSopenharmony_ci switch (pio) { 3580b966c5eSopenharmony_ci case UPIO_LPM_MODE: 3590b966c5eSopenharmony_ci if (upio_state[UPIO_LPM_MODE] == action) { 3600b966c5eSopenharmony_ci UPIODBG("LPM is %s already", lpm_mode[action]); 3610b966c5eSopenharmony_ci return; 3620b966c5eSopenharmony_ci } 3630b966c5eSopenharmony_ci 3640b966c5eSopenharmony_ci upio_state[UPIO_LPM_MODE] = action; 3650b966c5eSopenharmony_ci 3660b966c5eSopenharmony_ci#if (BT_WAKE_VIA_PROC == TRUE) 3670b966c5eSopenharmony_ci fd = open(VENDOR_LPM_PROC_NODE, O_WRONLY); 3680b966c5eSopenharmony_ci if (fd < 0) { 3690b966c5eSopenharmony_ci LOGE("upio_set : open(%s) for write failed: %s (%d)", 3700b966c5eSopenharmony_ci VENDOR_LPM_PROC_NODE, strerror(errno), errno); 3710b966c5eSopenharmony_ci return; 3720b966c5eSopenharmony_ci } 3730b966c5eSopenharmony_ci 3740b966c5eSopenharmony_ci if (action == UPIO_ASSERT) { 3750b966c5eSopenharmony_ci buffer = '1'; 3760b966c5eSopenharmony_ci } else { 3770b966c5eSopenharmony_ci buffer = '0'; 3780b966c5eSopenharmony_ci 3790b966c5eSopenharmony_ci // delete btwrite assertion holding timer 3800b966c5eSopenharmony_ci if (lpm_proc_cb.timer_created == TRUE) { 3810b966c5eSopenharmony_ci timer_delete(lpm_proc_cb.timer_id); 3820b966c5eSopenharmony_ci lpm_proc_cb.timer_created = FALSE; 3830b966c5eSopenharmony_ci } 3840b966c5eSopenharmony_ci } 3850b966c5eSopenharmony_ci 3860b966c5eSopenharmony_ci if (write(fd, &buffer, 1) < 0) { 3870b966c5eSopenharmony_ci LOGE("upio_set : write(%s) failed: %s (%d)", 3880b966c5eSopenharmony_ci VENDOR_LPM_PROC_NODE, strerror(errno),errno); 3890b966c5eSopenharmony_ci } 3900b966c5eSopenharmony_ci#if (PROC_BTWRITE_TIMER_TIMEOUT_MS != 0) 3910b966c5eSopenharmony_ci else { 3920b966c5eSopenharmony_ci if (action == UPIO_ASSERT) { 3930b966c5eSopenharmony_ci // create btwrite assertion holding timer 3940b966c5eSopenharmony_ci if (lpm_proc_cb.timer_created == FALSE) { 3950b966c5eSopenharmony_ci int status; 3960b966c5eSopenharmony_ci struct sigevent se; 3970b966c5eSopenharmony_ci 3980b966c5eSopenharmony_ci se.sigev_notify = SIGEV_THREAD; 3990b966c5eSopenharmony_ci se.sigev_value.sival_ptr = &lpm_proc_cb.timer_id; 4000b966c5eSopenharmony_ci se.sigev_notify_function = proc_btwrite_timeout; 4010b966c5eSopenharmony_ci se.sigev_notify_attributes = NULL; 4020b966c5eSopenharmony_ci 4030b966c5eSopenharmony_ci status = timer_create(CLOCK_MONOTONIC, &se, 4040b966c5eSopenharmony_ci &lpm_proc_cb.timer_id); 4050b966c5eSopenharmony_ci if (status == 0) 4060b966c5eSopenharmony_ci lpm_proc_cb.timer_created = TRUE; 4070b966c5eSopenharmony_ci } 4080b966c5eSopenharmony_ci } 4090b966c5eSopenharmony_ci } 4100b966c5eSopenharmony_ci#endif 4110b966c5eSopenharmony_ci 4120b966c5eSopenharmony_ci if (fd >= 0) 4130b966c5eSopenharmony_ci close(fd); 4140b966c5eSopenharmony_ci#endif 4150b966c5eSopenharmony_ci break; 4160b966c5eSopenharmony_ci 4170b966c5eSopenharmony_ci case UPIO_BT_WAKE: 4180b966c5eSopenharmony_ci if (upio_state[UPIO_BT_WAKE] == action) { 4190b966c5eSopenharmony_ci UPIODBG("BT_WAKE is %s already", lpm_state[action]); 4200b966c5eSopenharmony_ci 4210b966c5eSopenharmony_ci#if (BT_WAKE_VIA_PROC == TRUE) 4220b966c5eSopenharmony_ci if (lpm_proc_cb.btwrite_active == TRUE) 4230b966c5eSopenharmony_ci /* 4240b966c5eSopenharmony_ci * The proc btwrite node could have not been updated for 4250b966c5eSopenharmony_ci * certain time already due to heavy downstream path flow. 4260b966c5eSopenharmony_ci * In this case, we want to explicity touch proc btwrite 4270b966c5eSopenharmony_ci * node to keep the bt_wake assertion in the LPM kernel 4280b966c5eSopenharmony_ci * driver. The current kernel bluesleep LPM code starts 4290b966c5eSopenharmony_ci * a 10sec internal in-activity timeout timer before it 4300b966c5eSopenharmony_ci * attempts to deassert BT_WAKE line. 4310b966c5eSopenharmony_ci */ 4320b966c5eSopenharmony_ci return; 4330b966c5eSopenharmony_ci#else 4340b966c5eSopenharmony_ci return; 4350b966c5eSopenharmony_ci#endif 4360b966c5eSopenharmony_ci } 4370b966c5eSopenharmony_ci 4380b966c5eSopenharmony_ci upio_state[UPIO_BT_WAKE] = action; 4390b966c5eSopenharmony_ci 4400b966c5eSopenharmony_ci#if (BT_WAKE_VIA_USERIAL_IOCTL == TRUE) 4410b966c5eSopenharmony_ci 4420b966c5eSopenharmony_ci userial_vendor_ioctl( ( (action==UPIO_ASSERT) ? \ 4430b966c5eSopenharmony_ci USERIAL_OP_ASSERT_BT_WAKE : USERIAL_OP_DEASSERT_BT_WAKE),\ 4440b966c5eSopenharmony_ci NULL); 4450b966c5eSopenharmony_ci 4460b966c5eSopenharmony_ci#elif (BT_WAKE_VIA_PROC == TRUE) 4470b966c5eSopenharmony_ci 4480b966c5eSopenharmony_ci /* 4490b966c5eSopenharmony_ci * Kick proc btwrite node only at UPIO_ASSERT 4500b966c5eSopenharmony_ci */ 4510b966c5eSopenharmony_ci#if (BT_WAKE_VIA_PROC_NOTIFY_DEASSERT == FALSE) 4520b966c5eSopenharmony_ci if (action == UPIO_DEASSERT) 4530b966c5eSopenharmony_ci return; 4540b966c5eSopenharmony_ci#endif 4550b966c5eSopenharmony_ci fd = open(VENDOR_BTWRITE_PROC_NODE, O_WRONLY); 4560b966c5eSopenharmony_ci if (fd < 0) { 4570b966c5eSopenharmony_ci LOGE("upio_set : open(%s) for write failed: %s (%d)", 4580b966c5eSopenharmony_ci VENDOR_BTWRITE_PROC_NODE, strerror(errno), errno); 4590b966c5eSopenharmony_ci return; 4600b966c5eSopenharmony_ci } 4610b966c5eSopenharmony_ci#if (BT_WAKE_VIA_PROC_NOTIFY_DEASSERT == TRUE) 4620b966c5eSopenharmony_ci if (action == UPIO_DEASSERT) 4630b966c5eSopenharmony_ci buffer = '0'; 4640b966c5eSopenharmony_ci else 4650b966c5eSopenharmony_ci#endif 4660b966c5eSopenharmony_ci buffer = '1'; 4670b966c5eSopenharmony_ci 4680b966c5eSopenharmony_ci if (write(fd, &buffer, 1) < 0) { 4690b966c5eSopenharmony_ci LOGE("upio_set : write(%s) failed: %s (%d)", 4700b966c5eSopenharmony_ci VENDOR_BTWRITE_PROC_NODE, strerror(errno), errno); 4710b966c5eSopenharmony_ci } 4720b966c5eSopenharmony_ci#if (PROC_BTWRITE_TIMER_TIMEOUT_MS != 0) 4730b966c5eSopenharmony_ci else { 4740b966c5eSopenharmony_ci /* arm user space timer based on action */ 4750b966c5eSopenharmony_ci upio_start_stop_timer(action); 4760b966c5eSopenharmony_ci } 4770b966c5eSopenharmony_ci#endif 4780b966c5eSopenharmony_ci 4790b966c5eSopenharmony_ci#if (BT_WAKE_VIA_PROC_NOTIFY_DEASSERT == TRUE) 4800b966c5eSopenharmony_ci lpm_proc_cb.btwrite_active = TRUE; 4810b966c5eSopenharmony_ci#endif 4820b966c5eSopenharmony_ci 4830b966c5eSopenharmony_ci UPIODBG("%s: proc btwrite assertion, buffer: %c, timer_armed %d %d", 4840b966c5eSopenharmony_ci __FUNCTION__, buffer, lpm_proc_cb.btwrite_active, lpm_proc_cb.timer_created); 4850b966c5eSopenharmony_ci 4860b966c5eSopenharmony_ci if (fd >= 0) 4870b966c5eSopenharmony_ci close(fd); 4880b966c5eSopenharmony_ci#endif 4890b966c5eSopenharmony_ci 4900b966c5eSopenharmony_ci break; 4910b966c5eSopenharmony_ci 4920b966c5eSopenharmony_ci case UPIO_HOST_WAKE: 4930b966c5eSopenharmony_ci UPIODBG("upio_set: UPIO_HOST_WAKE"); 4940b966c5eSopenharmony_ci break; 4950b966c5eSopenharmony_ci } 4960b966c5eSopenharmony_ci} 497