From 2e7bd41e4e8ab3d1efdabd9e263a2f7fe79bff8c Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 20 Nov 2023 10:14:59 +0000
Subject: [PATCH] otg change to host
---
kernel/net/rfkill/rfkill-bt.c | 248 ++++++++++++++++++++++++++-----------------------
1 files changed, 132 insertions(+), 116 deletions(-)
diff --git a/kernel/net/rfkill/rfkill-bt.c b/kernel/net/rfkill/rfkill-bt.c
index 378fdc9..a2d31bc 100644
--- a/kernel/net/rfkill/rfkill-bt.c
+++ b/kernel/net/rfkill/rfkill-bt.c
@@ -25,6 +25,7 @@
#include <linux/rfkill-bt.h>
#include <linux/rfkill-wlan.h>
#include <linux/wakelock.h>
+#include <linux/input.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
#include <linux/suspend.h>
@@ -69,9 +70,11 @@
struct wake_lock bt_irq_wl;
struct delayed_work bt_sleep_delay_work;
int irq_req;
+ bool enable_power_key;
};
static struct rfkill_rk_data *g_rfkill = NULL;
+static struct input_dev *power_key_dev;
static const char bt_name[] =
#if defined(CONFIG_BCM4330)
@@ -113,6 +116,20 @@
#endif
;
+static int rfkill_rk_power_key_up(void)
+{
+ if (!power_key_dev)
+ return -ENODEV;
+
+ input_report_key(power_key_dev, KEY_POWER, 1);
+ input_sync(power_key_dev);
+ msleep(20);
+ input_report_key(power_key_dev, KEY_POWER, 0);
+ input_sync(power_key_dev);
+
+ return 0;
+}
+
static irqreturn_t rfkill_rk_wake_host_irq(int irq, void *dev)
{
struct rfkill_rk_data *rfkill = dev;
@@ -123,6 +140,16 @@
wake_lock_timeout(&rfkill->bt_irq_wl,
msecs_to_jiffies(BT_IRQ_WAKELOCK_TIMEOUT));
+
+ if (rfkill->enable_power_key)
+ return IRQ_WAKE_THREAD;
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t rfkill_rk_wake_host_irq_thread(int irq, void *dev)
+{
+ rfkill_rk_power_key_up();
return IRQ_HANDLED;
}
@@ -165,11 +192,12 @@
LOG("Request irq for bt wakeup host\n");
irq->irq = gpio_to_irq(irq->gpio.io);
sprintf(irq->name, "%s_irq", irq->gpio.name);
- ret = request_irq(irq->irq, rfkill_rk_wake_host_irq,
- (irq->gpio.enable == GPIO_ACTIVE_LOW) ?
- IRQF_TRIGGER_FALLING :
- IRQF_TRIGGER_RISING,
- irq->name, rfkill);
+ ret = request_threaded_irq(irq->irq, rfkill_rk_wake_host_irq,
+ rfkill_rk_wake_host_irq_thread,
+ IRQF_ONESHOT | ((irq->gpio.enable == GPIO_ACTIVE_LOW) ?
+ IRQF_TRIGGER_FALLING :
+ IRQF_TRIGGER_RISING),
+ irq->name, rfkill);
if (ret)
goto fail2;
rfkill->irq_req = 1;
@@ -271,7 +299,8 @@
return 0;
}
-static int proc_rk_set_power(void *data, bool blocked)
+
+static int rfkill_rk_set_power(void *data, bool blocked)
{
struct rfkill_rk_data *rfkill = data;
struct rfkill_rk_gpio *wake_host = &rfkill->pdata->wake_host_irq.gpio;
@@ -363,113 +392,6 @@
LOG("%s: cannot get wifi power state!\n", __func__);
return -EPERM;
}
- if (!wifi_power) {
- LOG("%s: bt will set vbat to low\n", __func__);
- rfkill_set_wifi_bt_power(0);
- } else {
- LOG("%s: bt shouldn't control the vbat\n", __func__);
- }
- }
- }
-
- return 0;
-}
-
-
-static int rfkill_rk_set_power(void *data, bool blocked)
-{
- struct rfkill_rk_data *rfkill = data;
- struct rfkill_rk_gpio *wake_host = &rfkill->pdata->wake_host_irq.gpio;
- struct rfkill_rk_gpio *poweron = &rfkill->pdata->poweron_gpio;
- struct rfkill_rk_gpio *reset = &rfkill->pdata->reset_gpio;
- struct rfkill_rk_gpio *rts = &rfkill->pdata->rts_gpio;
- struct pinctrl *pinctrl = rfkill->pdata->pinctrl;
- int wifi_power = 0;
- bool toggle = false;
-
- DBG("Enter %s\n", __func__);
-
- DBG("Set blocked:%d\n", blocked);
-
- toggle = rfkill->pdata->power_toggle;
-
- if (toggle) {
- if (rfkill_get_wifi_power_state(&wifi_power)) {
- LOG("%s: cannot get wifi power state!\n", __func__);
- return -1;
- }
- }
-
- DBG("%s: toggle = %s\n", __func__, toggle ? "true" : "false");
-
- if (!blocked) {
- if (toggle) {
- rfkill_set_wifi_bt_power(1);
- msleep(100);
- }
-
- rfkill_rk_sleep_bt(BT_WAKEUP); // ensure bt is wakeup
-
- if (gpio_is_valid(wake_host->io)) {
- LOG("%s: set bt wake_host high!\n", __func__);
- gpio_direction_output(wake_host->io, 1);
- msleep(20);
- }
-
- if (gpio_is_valid(poweron->io)) {
- if (gpio_get_value(poweron->io) == !poweron->enable) {
- gpio_direction_output(poweron->io,
- !poweron->enable);
- msleep(20);
- gpio_direction_output(poweron->io,
- poweron->enable);
- msleep(20);
- if (gpio_is_valid(wake_host->io))
- gpio_direction_input(wake_host->io);
- }
- }
-
- if (gpio_is_valid(reset->io)) {
- if (gpio_get_value(reset->io) == !reset->enable) {
- gpio_direction_output(reset->io,
- !reset->enable);
- msleep(20);
- gpio_direction_output(reset->io, reset->enable);
- }
- }
-
- if (pinctrl && gpio_is_valid(rts->io)) {
- pinctrl_select_state(pinctrl, rts->gpio_state);
- LOG("ENABLE UART_RTS\n");
- gpio_direction_output(rts->io, rts->enable);
- msleep(100);
- LOG("DISABLE UART_RTS\n");
- gpio_direction_output(rts->io, !rts->enable);
- pinctrl_select_state(pinctrl, rts->default_state);
- }
-
- bt_power_state = 1;
- LOG("bt turn on power\n");
- rfkill_rk_setup_wake_irq(rfkill, 1);
- } else {
- if (gpio_is_valid(poweron->io)) {
- if (gpio_get_value(poweron->io) == poweron->enable) {
- gpio_direction_output(poweron->io,
- poweron->enable);
- msleep(20);
- }
- }
-
- bt_power_state = 0;
- LOG("bt shut off power\n");
- if (gpio_is_valid(reset->io)) {
- if (gpio_get_value(reset->io) == reset->enable) {
- gpio_direction_output(reset->io,
- reset->enable);
- msleep(20);
- }
- }
- if (toggle) {
if (!wifi_power) {
LOG("%s: bt will set vbat to low\n", __func__);
rfkill_set_wifi_bt_power(0);
@@ -592,11 +514,56 @@
return -EFAULT;
DBG("btwrite %c\n", b);
- /* HCI_DEV_WRITE */
if (b != '0')
- proc_rk_set_power(g_rfkill, 0);
+ rfkill_rk_sleep_bt(BT_WAKEUP);
else
- proc_rk_set_power(g_rfkill, 1);
+ rfkill_rk_sleep_bt(BT_SLEEP);
+
+ return count;
+}
+
+static ssize_t bluesleep_read_proc_powerupkey(struct file *file,
+ char __user *buffer, size_t count,
+ loff_t *data)
+{
+ struct rfkill_rk_data *rfkill = g_rfkill;
+ char src[2];
+
+ if (*data >= 1)
+ return 0;
+
+ if (!rfkill)
+ return -EFAULT;
+
+ src[0] = rfkill->enable_power_key ? '1' : '0';
+ src[1] = '\n';
+ if (copy_to_user(buffer, src, 2))
+ return -EFAULT;
+ *data = 1;
+
+ return 2;
+}
+
+static ssize_t bluesleep_write_proc_powerupkey(struct file *file,
+ const char __user *buffer,
+ size_t count, loff_t *data)
+{
+ char b;
+ struct rfkill_rk_data *rfkill = g_rfkill;
+
+ if (!rfkill)
+ return -EFAULT;
+
+ if (count < 1)
+ return -EINVAL;
+
+ if (copy_from_user(&b, buffer, 1))
+ return -EFAULT;
+
+ if (b != '0')
+ rfkill->enable_power_key = true;
+ else
+ rfkill->enable_power_key = false;
return count;
}
@@ -700,6 +667,39 @@
.write = bluesleep_write_proc_btwrite,
};
+static const struct file_operations bluesleep_powerupkey = {
+ .owner = THIS_MODULE,
+ .read = bluesleep_read_proc_powerupkey,
+ .write = bluesleep_write_proc_powerupkey,
+};
+
+static int rfkill_rk_register_power_key(void)
+{
+ int ret = 0;
+
+ /* register input device */
+ power_key_dev = input_allocate_device();
+ if (!power_key_dev) {
+ LOG("ir_dev: not enough memory for input device\n");
+ return -ENOMEM;
+ }
+
+ power_key_dev->name = "bt-powerkey";
+ power_key_dev->id.bustype = BUS_HOST;
+
+ power_key_dev->evbit[0] = BIT_MASK(EV_KEY);
+ set_bit(KEY_POWER, power_key_dev->keybit);
+
+ ret = input_register_device(power_key_dev);
+ if (ret) {
+ input_free_device(power_key_dev);
+ LOG("ir_rx_init: register input device exception, exit\n");
+ return -EBUSY;
+ }
+
+ return ret;
+}
+
static int rfkill_rk_probe(struct platform_device *pdev)
{
struct rfkill_rk_data *rfkill;
@@ -766,6 +766,14 @@
goto fail_alloc;
}
+ /* read/write proc entries */
+ ent = proc_create("powerupkey", 0, sleep_dir, &bluesleep_powerupkey);
+ if (!ent) {
+ LOG("Unable to create /proc/%s/powerupkey entry", PROC_DIR);
+ ret = -ENOMEM;
+ goto fail_alloc;
+ }
+
DBG("init gpio\n");
ret = rfkill_rk_setup_gpio(pdev, &pdata->poweron_gpio, pdata->name,
@@ -824,12 +832,16 @@
LOG("%s device registered.\n", pdata->name);
+ if (rfkill_rk_register_power_key() != 0)
+ goto fail_rfkill;
+
return 0;
fail_rfkill:
rfkill_destroy(rfkill->rfkill_dev);
fail_alloc:
+ remove_proc_entry("powerupkey", sleep_dir);
remove_proc_entry("btwrite", sleep_dir);
remove_proc_entry("lpm", sleep_dir);
fail_setup_wake_irq:
@@ -848,7 +860,11 @@
rfkill_unregister(rfkill->rfkill_dev);
rfkill_destroy(rfkill->rfkill_dev);
+ remove_proc_entry("powerupkey", sleep_dir);
+ remove_proc_entry("btwrite", sleep_dir);
+ remove_proc_entry("lpm", sleep_dir);
+ input_unregister_device(power_key_dev);
cancel_delayed_work_sync(&rfkill->bt_sleep_delay_work);
// free gpio
--
Gitblit v1.6.2