Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d88bdcc8 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: gadget: gsi: Add a debugfs entry to simulate remote wakeup"

parents e3ae942e ca4e65a6
Loading
Loading
Loading
Loading
+216 −0
Original line number Diff line number Diff line
@@ -7,6 +7,12 @@
#include "f_gsi.h"
#include "rndis.h"

struct usb_gsi_debugfs {
	struct dentry *debugfs_root;
};

static struct usb_gsi_debugfs debugfs;

static bool qti_packet_debug;
module_param(qti_packet_debug, bool, 0644);
MODULE_PARM_DESC(qti_packet_debug, "Print QTI Packet's Raw Data");
@@ -173,6 +179,212 @@ static int gsi_wakeup_host(struct f_gsi *gsi)
	return ret;
}

static void gsi_rw_timer_func(struct timer_list *t)
{
	struct f_gsi *gsi = from_timer(gsi, t, gsi_rw_timer);

	if (!atomic_read(&gsi->connected)) {
		log_event_dbg("%s: gsi not connected.. bail-out\n", __func__);
		gsi->debugfs_rw_timer_enable = 0;
		return;
	}

	log_event_dbg("%s: calling gsi_wakeup_host\n", __func__);
	gsi_wakeup_host(gsi);

	if (gsi->debugfs_rw_timer_enable) {
		log_event_dbg("%s: re-arm the timer\n", __func__);
		mod_timer(&gsi->gsi_rw_timer,
			jiffies + msecs_to_jiffies(gsi->gsi_rw_timer_interval));
	}
}

static struct f_gsi *get_connected_gsi(void)
{
	struct f_gsi *connected_gsi;
	bool gsi_connected = false;
	int i;

	for (i = 0; i < IPA_USB_MAX_TETH_PROT_SIZE; i++) {
		if (inst_status[i].opts)
			connected_gsi = inst_status[i].opts->gsi;
		else
			continue;

		if (connected_gsi && atomic_read(&connected_gsi->connected)) {
			gsi_connected = true;
			break;
		}
	}

	if (!gsi_connected)
		connected_gsi = NULL;

	return connected_gsi;
}

#define DEFAULT_RW_TIMER_INTERVAL 500 /* in ms */
static ssize_t usb_gsi_rw_write(struct file *file,
			const char __user *ubuf, size_t count, loff_t *ppos)
{
	struct f_gsi *gsi;
	u8 input;
	int ret;

	gsi = get_connected_gsi();
	if (!gsi) {
		log_event_dbg("%s: gsi not connected\n", __func__);
		goto err;
	}

	if (ubuf == NULL) {
		log_event_dbg("%s: buffer is Null.\n", __func__);
		goto err;
	}

	ret = kstrtou8_from_user(ubuf, count, 0, &input);
	if (ret) {
		log_event_err("%s: Invalid value. err:%d\n", __func__, ret);
		goto err;
	}

	if (gsi->debugfs_rw_timer_enable == !!input) {
		if (!!input)
			log_event_dbg("%s: RW already enabled\n", __func__);
		else
			log_event_dbg("%s: RW already disabled\n", __func__);
		goto err;
	}

	gsi->debugfs_rw_timer_enable = !!input;

	if (gsi->debugfs_rw_timer_enable) {
		mod_timer(&gsi->gsi_rw_timer, jiffies +
			  msecs_to_jiffies(gsi->gsi_rw_timer_interval));
		log_event_dbg("%s: timer initialized\n", __func__);
	} else {
		del_timer_sync(&gsi->gsi_rw_timer);
		log_event_dbg("%s: timer deleted\n", __func__);
	}

err:
	return count;
}

static int usb_gsi_rw_show(struct seq_file *s, void *unused)
{

	struct f_gsi *gsi;

	gsi = get_connected_gsi();
	if (!gsi) {
		log_event_dbg("%s: gsi not connected\n", __func__);
		return 0;
	}

	seq_printf(s, "%d\n", gsi->debugfs_rw_timer_enable);

	return 0;
}

static int usb_gsi_rw_open(struct inode *inode, struct file *f)
{
	return single_open(f, usb_gsi_rw_show, inode->i_private);
}

static const struct file_operations fops_usb_gsi_rw = {
	.open = usb_gsi_rw_open,
	.read = seq_read,
	.write = usb_gsi_rw_write,
	.owner = THIS_MODULE,
	.llseek = seq_lseek,
	.release = seq_release,
};

static ssize_t usb_gsi_rw_timer_write(struct file *file,
			const char __user *ubuf, size_t count, loff_t *ppos)
{
	struct f_gsi *gsi;
	u16 timer_val;
	int ret;

	gsi = get_connected_gsi();
	if (!gsi) {
		log_event_dbg("%s: gsi not connected\n", __func__);
		goto err;
	}

	if (ubuf == NULL) {
		log_event_dbg("%s: buffer is NULL.\n", __func__);
		goto err;
	}

	ret = kstrtou16_from_user(ubuf, count, 0, &timer_val);
	if (ret) {
		log_event_err("%s: Invalid value. err:%d\n", __func__, ret);
		goto err;
	}

	if (timer_val <= 0 || timer_val >  10000) {
		log_event_err("%s: value must be > 0 and < 10000.\n", __func__);
		goto err;
	}

	gsi->gsi_rw_timer_interval = timer_val;
err:
	return count;
}

static int usb_gsi_rw_timer_show(struct seq_file *s, void *unused)
{
	struct f_gsi *gsi;

	gsi = get_connected_gsi();
	if (!gsi) {
		log_event_dbg("%s: gsi not connected\n", __func__);
		return 0;
	}

	seq_printf(s, "%ums\n", gsi->gsi_rw_timer_interval);

	return 0;
}

static int usb_gsi_rw_timer_open(struct inode *inode, struct file *f)
{
	return single_open(f, usb_gsi_rw_timer_show, inode->i_private);
}

static const struct file_operations fops_usb_gsi_rw_timer = {
	.open = usb_gsi_rw_timer_open,
	.read = seq_read,
	.write = usb_gsi_rw_timer_write,
	.owner = THIS_MODULE,
	.llseek = seq_lseek,
	.release = seq_release,
};

static int usb_gsi_debugfs_init(void)
{
	debugfs.debugfs_root = debugfs_create_dir("usb_gsi", NULL);
	if (!debugfs.debugfs_root)
		return -ENOMEM;

	debugfs_create_file("remote_wakeup_enable", 0600,
					debugfs.debugfs_root,
					inst_status, &fops_usb_gsi_rw);
	debugfs_create_file("remote_wakeup_interval", 0600,
					debugfs.debugfs_root,
					inst_status,
					&fops_usb_gsi_rw_timer);
	return 0;
}

static void usb_gsi_debugfs_exit(void)
{
	debugfs_remove_recursive(debugfs.debugfs_root);
}

/*
 * Callback for when when network interface is up
 * and userspace is ready to answer DHCP requests,  or remote wakeup
@@ -3083,6 +3295,8 @@ static struct f_gsi *gsi_function_init(enum ipa_usb_teth_prot prot_id)
		kfree(gsi);
		goto error;
	}
	gsi->gsi_rw_timer_interval = DEFAULT_RW_TIMER_INTERVAL;
	timer_setup(&gsi->gsi_rw_timer, gsi_rw_timer_func, 0);

	return gsi;
error:
@@ -3473,6 +3687,7 @@ static int fgsi_init(void)

	major = MAJOR(dev);

	usb_gsi_debugfs_init();
	return usb_function_register(&gsiusb_func);
}
module_init(fgsi_init);
@@ -3489,5 +3704,6 @@ static void __exit fgsi_exit(void)
	}

	class_destroy(gsi_class);
	usb_gsi_debugfs_exit();
}
module_exit(fgsi_exit);
+7 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/debugfs.h>
#include <linux/ipa_usb.h>
#include <linux/ipc_logging.h>
#include <linux/timer.h>

#define GSI_RMNET_CTRL_NAME "rmnet_ctrl"
#define GSI_MBIM_CTRL_NAME "android_mbim"
@@ -274,6 +275,12 @@ struct f_gsi {
	struct gsi_ctrl_port c_port;
	void *ipc_log_ctxt;
	bool rmnet_dtr_status;

	/* To test remote wakeup using debugfs */
	struct timer_list gsi_rw_timer;
	u8 debugfs_rw_timer_enable;
	u16 gsi_rw_timer_interval;

};

static inline struct f_gsi *func_to_gsi(struct usb_function *f)