Skip to content

Commit b86617d

Browse files
DevZillionNotNoelChannel
authored andcommitted
usb: HID patch
1 parent 1e824b2 commit b86617d

File tree

6 files changed

+237
-6
lines changed

6 files changed

+237
-6
lines changed

drivers/usb/gadget/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ g_nokia-y := nokia.o
6767
g_webcam-y := webcam.o
6868
g_ncm-y := ncm.o
6969
g_acm_ms-y := acm_ms.o
70-
g_android-y := android.o
70+
g_android-y := android.o f_hid.o
7171
g_tcm_usb_gadget-y := tcm_usb_gadget.o
7272

7373
obj-$(CONFIG_USB_ZERO) += g_zero.o

drivers/usb/gadget/android.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@
5858
#include "f_ccid.c"
5959
#include "f_mtp.c"
6060
#include "f_accessory.c"
61+
#include "f_hid.h"
62+
#include "f_hid_android_keyboard.c"
63+
#include "f_hid_android_mouse.c"
6164
#include "f_rndis.c"
6265
#include "rndis.c"
6366
#include "f_qc_ecm.c"
@@ -2796,6 +2799,41 @@ static struct android_usb_function uasp_function = {
27962799
.bind_config = uasp_function_bind_config,
27972800
};
27982801

2802+
static int hid_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
2803+
{
2804+
return ghid_setup(cdev->gadget, 2);
2805+
}
2806+
2807+
static void hid_function_cleanup(struct android_usb_function *f)
2808+
{
2809+
ghid_cleanup();
2810+
}
2811+
2812+
static int hid_function_bind_config(struct android_usb_function *f, struct usb_configuration *c)
2813+
{
2814+
int ret;
2815+
printk(KERN_INFO "hid keyboard\n");
2816+
ret = hidg_bind_config(c, &ghid_device_android_keyboard, 0);
2817+
if (ret) {
2818+
pr_info("%s: hid_function_bind_config keyboard failed: %d\n", __func__, ret);
2819+
return ret;
2820+
}
2821+
printk(KERN_INFO "hid mouse\n");
2822+
ret = hidg_bind_config(c, &ghid_device_android_mouse, 1);
2823+
if (ret) {
2824+
pr_info("%s: hid_function_bind_config mouse failed: %d\n", __func__, ret);
2825+
return ret;
2826+
}
2827+
return 0;
2828+
}
2829+
2830+
static struct android_usb_function hid_function = {
2831+
.name = "hid",
2832+
.init = hid_function_init,
2833+
.cleanup = hid_function_cleanup,
2834+
.bind_config = hid_function_bind_config,
2835+
};
2836+
27992837
static struct android_usb_function *supported_functions[] = {
28002838
&ffs_function,
28012839
&mbim_function,
@@ -2824,6 +2862,7 @@ static struct android_usb_function *supported_functions[] = {
28242862
#endif
28252863
&uasp_function,
28262864
&charger_function,
2865+
&hid_function,
28272866
NULL
28282867
};
28292868

@@ -3203,6 +3242,8 @@ functions_store(struct device *pdev, struct device_attribute *attr,
32033242
struct android_configuration, list_item);
32043243
free_android_config(dev, conf);
32053244
}
3245+
/* HID driver always enabled, it's the whole point of this kernel patch */
3246+
android_enable_function(dev, "hid");
32063247

32073248
mutex_unlock(&dev->mutex);
32083249

drivers/usb/gadget/f_hid.c

Lines changed: 95 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
#include <linux/poll.h>
1818
#include <linux/uaccess.h>
1919
#include <linux/wait.h>
20+
#include <linux/delay.h>
2021
#include <linux/sched.h>
2122
#include <linux/usb/g_hid.h>
23+
#include "f_hid.h"
2224

2325
static int major, minors;
2426
static struct class *hidg_class;
@@ -60,6 +62,43 @@ struct f_hidg {
6062
struct usb_ep *out_ep;
6163
};
6264

65+
/* Hacky device list to fix f_hidg_write being called after device destroyed.
66+
It covers only most common race conditions, there will be rare crashes anyway. */
67+
enum { HACKY_DEVICE_LIST_SIZE = 4 };
68+
static struct f_hidg *hacky_device_list[HACKY_DEVICE_LIST_SIZE];
69+
static void hacky_device_list_add(struct f_hidg *hidg)
70+
{
71+
int i;
72+
for (i = 0; i < HACKY_DEVICE_LIST_SIZE; i++) {
73+
if (!hacky_device_list[i]) {
74+
hacky_device_list[i] = hidg;
75+
return;
76+
}
77+
}
78+
pr_err("%s: too many devices, not adding device %p\n", __func__, hidg);
79+
}
80+
static void hacky_device_list_remove(struct f_hidg *hidg)
81+
{
82+
int i;
83+
for (i = 0; i < HACKY_DEVICE_LIST_SIZE; i++) {
84+
if (hacky_device_list[i] == hidg) {
85+
hacky_device_list[i] = NULL;
86+
return;
87+
}
88+
}
89+
pr_err("%s: cannot find device %p\n", __func__, hidg);
90+
}
91+
static int hacky_device_list_check(struct f_hidg *hidg)
92+
{
93+
int i;
94+
for (i = 0; i < HACKY_DEVICE_LIST_SIZE; i++) {
95+
if (hacky_device_list[i] == hidg) {
96+
return 0;
97+
}
98+
}
99+
return 1;
100+
}
101+
63102
static inline struct f_hidg *func_to_hidg(struct usb_function *f)
64103
{
65104
return container_of(f, struct f_hidg, func);
@@ -176,6 +215,11 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer,
176215
if (!access_ok(VERIFY_WRITE, buffer, count))
177216
return -EFAULT;
178217

218+
if (hacky_device_list_check(hidg)) {
219+
pr_err("%s: trying to read from device %p that was destroyed\n", __func__, hidg);
220+
return -EIO;
221+
}
222+
179223
spin_lock_irqsave(&hidg->spinlock, flags);
180224

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

293+
if (hacky_device_list_check(hidg)) {
294+
pr_err("%s: trying to write to device %p that was destroyed\n", __func__, hidg);
295+
return -EIO;
296+
}
297+
249298
mutex_lock(&hidg->lock);
250299

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

312+
if (hacky_device_list_check(hidg)) {
313+
pr_err("%s: trying to write to device %p that was destroyed\n", __func__, hidg);
314+
return -EIO;
315+
}
316+
263317
mutex_lock(&hidg->lock);
264318
}
265319

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

357+
if (hacky_device_list_check(hidg)) {
358+
pr_err("%s: trying to poll device %p that was destroyed\n", __func__, hidg);
359+
return -EIO;
360+
}
361+
303362
poll_wait(file, &hidg->read_queue, wait);
363+
364+
if (hacky_device_list_check(hidg)) {
365+
pr_err("%s: trying to poll device %p that was destroyed\n", __func__, hidg);
366+
return -EIO;
367+
}
368+
304369
poll_wait(file, &hidg->write_queue, wait);
305370

306371
if (WRITE_COND)
@@ -399,7 +464,12 @@ static int hidg_setup(struct usb_function *f,
399464
case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
400465
| HID_REQ_GET_PROTOCOL):
401466
VDBG(cdev, "get_protocol\n");
402-
goto stall;
467+
length = min_t(unsigned, length, 1);
468+
if (hidg->bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT)
469+
((u8 *) req->buf)[0] = 0; /* Boot protocol */
470+
else
471+
((u8 *) req->buf)[0] = 1; /* Report protocol */
472+
goto respond;
403473
break;
404474

405475
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
@@ -411,6 +481,14 @@ static int hidg_setup(struct usb_function *f,
411481
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
412482
| HID_REQ_SET_PROTOCOL):
413483
VDBG(cdev, "set_protocol\n");
484+
length = 0;
485+
if (hidg->bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) {
486+
if (value == 0) /* Boot protocol */
487+
goto respond;
488+
} else {
489+
if (value == 1) /* Report protocol */
490+
goto respond;
491+
}
414492
goto stall;
415493
break;
416494

@@ -560,13 +638,15 @@ const struct file_operations f_hidg_fops = {
560638
.llseek = noop_llseek,
561639
};
562640

563-
static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
641+
static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
564642
{
565643
struct usb_ep *ep;
566644
struct f_hidg *hidg = func_to_hidg(f);
567645
int status;
568646
dev_t dev;
569647

648+
pr_info("%s: creating device %p\n", __func__, hidg);
649+
570650
/* allocate instance-specific interface IDs, and patch descriptors */
571651
status = usb_interface_id(c, f);
572652
if (status < 0)
@@ -632,6 +712,7 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
632712
goto fail;
633713

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

636717
return 0;
637718

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

735+
pr_info("%s: destroying device %p\n", __func__, hidg);
736+
/* This does not cover all race conditions, only most common one */
737+
mutex_lock(&hidg->lock);
738+
hacky_device_list_remove(hidg);
739+
mutex_unlock(&hidg->lock);
740+
654741
device_destroy(hidg_class, MKDEV(major, hidg->minor));
655742
cdev_del(&hidg->cdev);
656743

657744
/* disable/free request and end point */
658745
usb_ep_disable(hidg->in_ep);
659-
usb_ep_dequeue(hidg->in_ep, hidg->req);
746+
/* TODO: calling this function crash kernel,
747+
not calling this funct ion crash kernel inside f_hidg_write */
748+
/* usb_ep_dequeue(hidg->in_ep, hidg->req); */
749+
660750
kfree(hidg->req->buf);
661751
usb_ep_free_request(hidg->in_ep, hidg->req);
662752

@@ -689,7 +779,7 @@ static struct usb_gadget_strings *ct_func_strings[] = {
689779
/*-------------------------------------------------------------------------*/
690780
/* usb_configuration */
691781

692-
int __init hidg_bind_config(struct usb_configuration *c,
782+
int hidg_bind_config(struct usb_configuration *c,
693783
struct hidg_func_descriptor *fdesc, int index)
694784
{
695785
struct f_hidg *hidg;
@@ -743,7 +833,7 @@ int __init hidg_bind_config(struct usb_configuration *c,
743833
return status;
744834
}
745835

746-
int __init ghid_setup(struct usb_gadget *g, int count)
836+
int ghid_setup(struct usb_gadget *g, int count)
747837
{
748838
int status;
749839
dev_t dev;

drivers/usb/gadget/f_hid.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef _GADGET_F_HID_H
2+
#define _GADGET_F_HID_H
3+
4+
#include <linux/hid.h>
5+
#include <linux/usb/composite.h>
6+
#include <linux/usb/gadget.h>
7+
#include <linux/usb/g_hid.h>
8+
9+
int hidg_bind_config(struct usb_configuration *c,
10+
struct hidg_func_descriptor *fdesc, int index);
11+
12+
int ghid_setup(struct usb_gadget *g, int count);
13+
14+
void ghid_cleanup(void);
15+
16+
#endif
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include <linux/platform_device.h>
2+
#include <linux/usb/g_hid.h>
3+
4+
/* hid descriptor for a keyboard */
5+
static struct hidg_func_descriptor ghid_device_android_keyboard = {
6+
.subclass = 1, /* Boot Interface Subclass */
7+
.protocol = 1, /* Keyboard */
8+
.report_length = 8,
9+
.report_desc_length = 63,
10+
.report_desc = {
11+
0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
12+
0x09, 0x06, /* USAGE (Keyboard) */
13+
0xa1, 0x01, /* COLLECTION (Application) */
14+
0x05, 0x07, /* USAGE_PAGE (Keyboard) */
15+
0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */
16+
0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */
17+
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
18+
0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
19+
0x75, 0x01, /* REPORT_SIZE (1) */
20+
0x95, 0x08, /* REPORT_COUNT (8) */
21+
0x81, 0x02, /* INPUT (Data,Var,Abs) */
22+
0x95, 0x01, /* REPORT_COUNT (1) */
23+
0x75, 0x08, /* REPORT_SIZE (8) */
24+
0x81, 0x03, /* INPUT (Cnst,Var,Abs) */
25+
0x95, 0x05, /* REPORT_COUNT (5) */
26+
0x75, 0x01, /* REPORT_SIZE (1) */
27+
0x05, 0x08, /* USAGE_PAGE (LEDs) */
28+
0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */
29+
0x29, 0x05, /* USAGE_MAXIMUM (Kana) */
30+
0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
31+
0x95, 0x01, /* REPORT_COUNT (1) */
32+
0x75, 0x03, /* REPORT_SIZE (3) */
33+
0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */
34+
0x95, 0x06, /* REPORT_COUNT (6) */
35+
0x75, 0x08, /* REPORT_SIZE (8) */
36+
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
37+
0x25, 0x65, /* LOGICAL_MAXIMUM (101) */
38+
0x05, 0x07, /* USAGE_PAGE (Keyboard) */
39+
0x19, 0x00, /* USAGE_MINIMUM (Reserved) */
40+
0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */
41+
0x81, 0x00, /* INPUT (Data,Ary,Abs) */
42+
0xc0 /* END_COLLECTION */
43+
}
44+
};
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#include <linux/platform_device.h>
2+
#include <linux/usb/g_hid.h>
3+
4+
/* HID descriptor for a mouse */
5+
static struct hidg_func_descriptor ghid_device_android_mouse = {
6+
.subclass = 1, /* Boot Interface Subclass */
7+
.protocol = 2, /* Mouse */
8+
.report_length = 4,
9+
.report_desc_length = 52,
10+
.report_desc = {
11+
0x05, 0x01, //Usage Page(Generic Desktop Controls)
12+
0x09, 0x02, //Usage (Mouse)
13+
0xa1, 0x01, //Collection (Application)
14+
0x09, 0x01, //Usage (pointer)
15+
0xa1, 0x00, //Collection (Physical)
16+
0x05, 0x09, //Usage Page (Button)
17+
0x19, 0x01, //Usage Minimum(1)
18+
0x29, 0x05, //Usage Maximum(5)
19+
0x15, 0x00, //Logical Minimum(1)
20+
0x25, 0x01, //Logical Maximum(1)
21+
0x95, 0x05, //Report Count(5)
22+
0x75, 0x01, //Report Size(1)
23+
0x81, 0x02, //Input(Data,Variable,Absolute,BitField)
24+
0x95, 0x01, //Report Count(1)
25+
0x75, 0x03, //Report Size(3)
26+
0x81, 0x01, //Input(Constant,Array,Absolute,BitField)
27+
0x05, 0x01, //Usage Page(Generic Desktop Controls)
28+
0x09, 0x30, //Usage(x)
29+
0x09, 0x31, //Usage(y)
30+
0x09, 0x38, //Usage(Wheel)
31+
0x15, 0x81, //Logical Minimum(-127)
32+
0x25, 0x7F, //Logical Maximum(127)
33+
0x75, 0x08, //Report Size(8)
34+
0x95, 0x03, //Report Count(3)
35+
0x81, 0x06, //Input(Data,Variable,Relative,BitField)
36+
0xc0, //End Collection
37+
0xc0 //End Collection
38+
}
39+
};
40+

0 commit comments

Comments
 (0)