Skip to content

Commit

Permalink
Apply add-HID-km-support-google_angler_3.10 patch
Browse files Browse the repository at this point in the history
Signed-off-by: Re4son <3520622-re4son@users.noreply.gitlab.com>
  • Loading branch information
CharlesForson committed Apr 25, 2020
1 parent 27cd84e commit ebd218a
Show file tree
Hide file tree
Showing 6 changed files with 242 additions and 7 deletions.
2 changes: 1 addition & 1 deletion drivers/usb/gadget/Makefile
Expand Up @@ -67,7 +67,7 @@ g_nokia-y := nokia.o
g_webcam-y := webcam.o
g_ncm-y := ncm.o
g_acm_ms-y := acm_ms.o
g_android-y := android.o
g_android-y := android.o f_hid.o
g_tcm_usb_gadget-y := tcm_usb_gadget.o

obj-$(CONFIG_USB_ZERO) += g_zero.o
Expand Down
43 changes: 43 additions & 0 deletions drivers/usb/gadget/android.c
Expand Up @@ -77,6 +77,9 @@ static void eject_cdrom_timer_work(struct work_struct *w);
#include "f_ccid.c"
#include "f_mtp.c"
#include "f_accessory.c"
#include "f_hid.h"
#include "f_hid_android_keyboard.c"
#include "f_hid_android_mouse.c"
#include "f_rndis.c"
#include "rndis.c"
#include "f_qc_ecm.c"
Expand Down Expand Up @@ -3034,6 +3037,42 @@ static struct android_usb_function midi_function = {
.attributes = midi_function_attributes,
};
#endif

static int hid_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
{
return ghid_setup(cdev->gadget, 2);
}

static void hid_function_cleanup(struct android_usb_function *f)
{
ghid_cleanup();
}

static int hid_function_bind_config(struct android_usb_function *f, struct usb_configuration *c)
{
int ret;
printk(KERN_INFO "hid keyboard\n");
ret = hidg_bind_config(c, &ghid_device_android_keyboard, 0);
if (ret) {
pr_info("%s: hid_function_bind_config keyboard failed: %d\n", __func__, ret);
return ret;
}
printk(KERN_INFO "hid mouse\n");
ret = hidg_bind_config(c, &ghid_device_android_mouse, 1);
if (ret) {
pr_info("%s: hid_function_bind_config mouse failed: %d\n", __func__, ret);
return ret;
}
return 0;
}

static struct android_usb_function hid_function = {
.name = "hid",
.init = hid_function_init,
.cleanup = hid_function_cleanup,
.bind_config = hid_function_bind_config,
};

static struct android_usb_function *supported_functions[] = {
&ffs_function,
&mbim_function,
Expand Down Expand Up @@ -3061,6 +3100,7 @@ static struct android_usb_function *supported_functions[] = {
#ifdef CONFIG_SND_PCM
&audio_source_function,
#endif
&hid_function,
&uasp_function,
&charger_function,
#ifdef CONFIG_SND_RAWMIDI
Expand Down Expand Up @@ -3424,6 +3464,9 @@ functions_store(struct device *pdev, struct device_attribute *attr,
}
}

/* HID driver always enabled, it's the whole point of this kernel patch */
android_enable_function(dev, conf, "hid");

/* Free uneeded configurations if exists */
while (curr_conf->next != &dev->configs) {
conf = list_entry(curr_conf->next,
Expand Down
102 changes: 96 additions & 6 deletions drivers/usb/gadget/f_hid.c
Expand Up @@ -17,8 +17,10 @@
#include <linux/poll.h>
#include <linux/uaccess.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/usb/g_hid.h>
#include "f_hid.h"

static int major, minors;
static struct class *hidg_class;
Expand Down Expand Up @@ -60,6 +62,43 @@ struct f_hidg {
struct usb_ep *out_ep;
};

/* Hacky device list to fix f_hidg_write being called after device destroyed.
It covers only most common race conditions, there will be rare crashes anyway. */
enum { HACKY_DEVICE_LIST_SIZE = 4 };
static struct f_hidg *hacky_device_list[HACKY_DEVICE_LIST_SIZE];
static void hacky_device_list_add(struct f_hidg *hidg)
{
int i;
for (i = 0; i < HACKY_DEVICE_LIST_SIZE; i++) {
if (!hacky_device_list[i]) {
hacky_device_list[i] = hidg;
return;
}
}
pr_err("%s: too many devices, not adding device %p\n", __func__, hidg);
}
static void hacky_device_list_remove(struct f_hidg *hidg)
{
int i;
for (i = 0; i < HACKY_DEVICE_LIST_SIZE; i++) {
if (hacky_device_list[i] == hidg) {
hacky_device_list[i] = NULL;
return;
}
}
pr_err("%s: cannot find device %p\n", __func__, hidg);
}
static int hacky_device_list_check(struct f_hidg *hidg)
{
int i;
for (i = 0; i < HACKY_DEVICE_LIST_SIZE; i++) {
if (hacky_device_list[i] == hidg) {
return 0;
}
}
return 1;
}

static inline struct f_hidg *func_to_hidg(struct usb_function *f)
{
return container_of(f, struct f_hidg, func);
Expand Down Expand Up @@ -176,6 +215,11 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer,
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;

if (hacky_device_list_check(hidg)) {
pr_err("%s: trying to read from device %p that was destroyed\n", __func__, hidg);
return -EIO;
}

spin_lock_irqsave(&hidg->spinlock, flags);

#define READ_COND (!list_empty(&hidg->completed_out_req))
Expand Down Expand Up @@ -246,6 +290,11 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer,
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;

if (hacky_device_list_check(hidg)) {
pr_err("%s: trying to write to device %p that was destroyed\n", __func__, hidg);
return -EIO;
}

mutex_lock(&hidg->lock);

#define WRITE_COND (!hidg->write_pending)
Expand All @@ -260,6 +309,11 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer,
hidg->write_queue, WRITE_COND))
return -ERESTARTSYS;

if (hacky_device_list_check(hidg)) {
pr_err("%s: trying to write to device %p that was destroyed\n", __func__, hidg);
return -EIO;
}

mutex_lock(&hidg->lock);
}

Expand Down Expand Up @@ -300,7 +354,18 @@ static unsigned int f_hidg_poll(struct file *file, poll_table *wait)
struct f_hidg *hidg = file->private_data;
unsigned int ret = 0;

if (hacky_device_list_check(hidg)) {
pr_err("%s: trying to poll device %p that was destroyed\n", __func__, hidg);
return -EIO;
}

poll_wait(file, &hidg->read_queue, wait);

if (hacky_device_list_check(hidg)) {
pr_err("%s: trying to poll device %p that was destroyed\n", __func__, hidg);
return -EIO;
}

poll_wait(file, &hidg->write_queue, wait);

if (WRITE_COND)
Expand Down Expand Up @@ -399,7 +464,12 @@ static int hidg_setup(struct usb_function *f,
case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
| HID_REQ_GET_PROTOCOL):
VDBG(cdev, "get_protocol\n");
goto stall;
length = min_t(unsigned, length, 1);
if (hidg->bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT)
((u8 *) req->buf)[0] = 0; /* Boot protocol */
else
((u8 *) req->buf)[0] = 1; /* Report protocol */
goto respond;
break;

case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
Expand All @@ -411,6 +481,14 @@ static int hidg_setup(struct usb_function *f,
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
| HID_REQ_SET_PROTOCOL):
VDBG(cdev, "set_protocol\n");
length = 0;
if (hidg->bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) {
if (value == 0) /* Boot protocol */
goto respond;
} else {
if (value == 1) /* Report protocol */
goto respond;
}
goto stall;
break;

Expand Down Expand Up @@ -560,13 +638,15 @@ const struct file_operations f_hidg_fops = {
.llseek = noop_llseek,
};

static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_ep *ep;
struct f_hidg *hidg = func_to_hidg(f);
int status;
dev_t dev;

pr_info("%s: creating device %p\n", __func__, hidg);

/* allocate instance-specific interface IDs, and patch descriptors */
status = usb_interface_id(c, f);
if (status < 0)
Expand Down Expand Up @@ -632,6 +712,7 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
goto fail;

device_create(hidg_class, NULL, dev, NULL, "%s%d", "hidg", hidg->minor);
hacky_device_list_add(hidg);

return 0;

Expand All @@ -651,12 +732,21 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_hidg *hidg = func_to_hidg(f);

pr_info("%s: destroying device %p\n", __func__, hidg);
/* This does not cover all race conditions, only most common one */
mutex_lock(&hidg->lock);
hacky_device_list_remove(hidg);
mutex_unlock(&hidg->lock);

device_destroy(hidg_class, MKDEV(major, hidg->minor));
cdev_del(&hidg->cdev);

/* disable/free request and end point */
usb_ep_disable(hidg->in_ep);
usb_ep_dequeue(hidg->in_ep, hidg->req);
usb_ep_disable(hidg->in_ep);
/* TODO: calling this function crash kernel,
not calling this funct ion crash kernel inside f_hidg_write */
/* usb_ep_dequeue(hidg->in_ep, hidg->req); */

kfree(hidg->req->buf);
usb_ep_free_request(hidg->in_ep, hidg->req);

Expand Down Expand Up @@ -689,7 +779,7 @@ static struct usb_gadget_strings *ct_func_strings[] = {
/*-------------------------------------------------------------------------*/
/* usb_configuration */

int __init hidg_bind_config(struct usb_configuration *c,
int hidg_bind_config(struct usb_configuration *c,
struct hidg_func_descriptor *fdesc, int index)
{
struct f_hidg *hidg;
Expand Down Expand Up @@ -743,7 +833,7 @@ int __init hidg_bind_config(struct usb_configuration *c,
return status;
}

int __init ghid_setup(struct usb_gadget *g, int count)
int ghid_setup(struct usb_gadget *g, int count)
{
int status;
dev_t dev;
Expand Down
17 changes: 17 additions & 0 deletions drivers/usb/gadget/f_hid.h
@@ -0,0 +1,17 @@
#ifndef _GADGET_F_HID_H
#define _GADGET_F_HID_H

#include <linux/hid.h>
#include <linux/usb/composite.h>
#include <linux/usb/gadget.h>
#include <linux/usb/g_hid.h>

int hidg_bind_config(struct usb_configuration *c,
struct hidg_func_descriptor *fdesc, int index);

int ghid_setup(struct usb_gadget *g, int count);

void ghid_cleanup(void);

#endif

45 changes: 45 additions & 0 deletions drivers/usb/gadget/f_hid_android_keyboard.c
@@ -0,0 +1,45 @@
#include <linux/platform_device.h>
#include <linux/usb/g_hid.h>

/* hid descriptor for a keyboard */
static struct hidg_func_descriptor ghid_device_android_keyboard = {
.subclass = 1, /* Boot Interface Subclass */
.protocol = 1, /* Keyboard */
.report_length = 8,
.report_desc_length = 63,
.report_desc = {
0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
0x09, 0x06, /* USAGE (Keyboard) */
0xa1, 0x01, /* COLLECTION (Application) */
0x05, 0x07, /* USAGE_PAGE (Keyboard) */
0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */
0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
0x75, 0x01, /* REPORT_SIZE (1) */
0x95, 0x08, /* REPORT_COUNT (8) */
0x81, 0x02, /* INPUT (Data,Var,Abs) */
0x95, 0x01, /* REPORT_COUNT (1) */
0x75, 0x08, /* REPORT_SIZE (8) */
0x81, 0x03, /* INPUT (Cnst,Var,Abs) */
0x95, 0x05, /* REPORT_COUNT (5) */
0x75, 0x01, /* REPORT_SIZE (1) */
0x05, 0x08, /* USAGE_PAGE (LEDs) */
0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */
0x29, 0x05, /* USAGE_MAXIMUM (Kana) */
0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
0x95, 0x01, /* REPORT_COUNT (1) */
0x75, 0x03, /* REPORT_SIZE (3) */
0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */
0x95, 0x06, /* REPORT_COUNT (6) */
0x75, 0x08, /* REPORT_SIZE (8) */
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
0x25, 0x65, /* LOGICAL_MAXIMUM (101) */
0x05, 0x07, /* USAGE_PAGE (Keyboard) */
0x19, 0x00, /* USAGE_MINIMUM (Reserved) */
0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */
0x81, 0x00, /* INPUT (Data,Ary,Abs) */
0xc0 /* END_COLLECTION */
}
};

40 changes: 40 additions & 0 deletions drivers/usb/gadget/f_hid_android_mouse.c
@@ -0,0 +1,40 @@
#include <linux/platform_device.h>
#include <linux/usb/g_hid.h>

/* HID descriptor for a mouse */
static struct hidg_func_descriptor ghid_device_android_mouse = {
.subclass = 1, /* Boot Interface Subclass */
.protocol = 2, /* Mouse */
.report_length = 4,
.report_desc_length = 52,
.report_desc = {
0x05, 0x01, //Usage Page(Generic Desktop Controls)
0x09, 0x02, //Usage (Mouse)
0xa1, 0x01, //Collection (Application)
0x09, 0x01, //Usage (pointer)
0xa1, 0x00, //Collection (Physical)
0x05, 0x09, //Usage Page (Button)
0x19, 0x01, //Usage Minimum(1)
0x29, 0x05, //Usage Maximum(5)
0x15, 0x00, //Logical Minimum(1)
0x25, 0x01, //Logical Maximum(1)
0x95, 0x05, //Report Count(5)
0x75, 0x01, //Report Size(1)
0x81, 0x02, //Input(Data,Variable,Absolute,BitField)
0x95, 0x01, //Report Count(1)
0x75, 0x03, //Report Size(3)
0x81, 0x01, //Input(Constant,Array,Absolute,BitField)
0x05, 0x01, //Usage Page(Generic Desktop Controls)
0x09, 0x30, //Usage(x)
0x09, 0x31, //Usage(y)
0x09, 0x38, //Usage(Wheel)
0x15, 0x81, //Logical Minimum(-127)
0x25, 0x7F, //Logical Maximum(127)
0x75, 0x08, //Report Size(8)
0x95, 0x03, //Report Count(3)
0x81, 0x06, //Input(Data,Variable,Relative,BitField)
0xc0, //End Collection
0xc0 //End Collection
}
};

0 comments on commit ebd218a

Please sign in to comment.