-
Notifications
You must be signed in to change notification settings - Fork 0
/
usb_display.c
132 lines (109 loc) · 3.74 KB
/
usb_display.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/usb/composite.h>
#include "f_display.h"
#include "f_hid.h"
/* Defines */
#define GS_VERSION_STR "v0.1"
#define GS_VERSION_NUM 0x0200
#define GS_LONG_NAME "USB display"
#define GS_VERSION_NAME GS_LONG_NAME " " GS_VERSION_STR
/*-------------------------------------------------------------------------*/
USB_GADGET_COMPOSITE_OPTIONS();
#define RP_DISP_DRIVER_NAME "usb_display"
#define RP_DISP_USB_VENDOR_ID 0xFCCF // RP Pseudo vendor id
#define RP_DISP_USB_PRODUCT_ID 0xA001
/* string IDs are assigned dynamically */
#define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX
static struct usb_string strings_dev[] = {
[USB_GADGET_MANUFACTURER_IDX].s = "",
[USB_GADGET_PRODUCT_IDX].s = GS_VERSION_NAME,
[USB_GADGET_SERIAL_IDX].s = "",
[STRING_DESCRIPTION_IDX].s = GS_LONG_NAME,
{ } /* end of list */
};
static struct usb_gadget_strings stringtab_dev = {
.language = 0x0409, /* en-us */
.strings = strings_dev,
};
static struct usb_gadget_strings *dev_strings[] = {
&stringtab_dev,
NULL,
};
static struct usb_device_descriptor device_desc = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = cpu_to_le16(0x0200),
//.bDeviceClass = USB_CLASS_VENDOR_SPEC,
.bDeviceClass = USB_CLASS_PER_INTERFACE,
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
/* .bMaxPacketSize0 = f(hardware) */
.idVendor = cpu_to_le16(RP_DISP_USB_VENDOR_ID),
.idProduct = cpu_to_le16(RP_DISP_USB_PRODUCT_ID),
.bcdDevice = cpu_to_le16(GS_VERSION_NUM),
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
.bNumConfigurations = 1,
};
static struct usb_configuration serial_config_driver = {
.label = RP_DISP_DRIVER_NAME,
.bConfigurationValue = 1,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
};
static int __init gs_bind(struct usb_composite_dev *cdev)
{
/* Allocate string descriptor numbers ... note that string
* contents can be overridden by the composite_dev glue.
*/
int status = usb_string_ids_tab(cdev, strings_dev);
if (status < 0)
return status;
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
device_desc.iSerialNumber = strings_dev[USB_GADGET_SERIAL_IDX].id;
// linux的一个BUG,如果不设置usb_composite_dev的desc的bcdDevice的话,默认会设置成内核版本号,参见composite.c的
// update_unchanged_dev_desc(&cdev->desc, composite->dev);
// 如果版本小于1.04协议会不同
cdev->desc.bcdDevice = cpu_to_le16(GS_VERSION_NUM);
serial_config_driver.iConfiguration = strings_dev[STRING_DESCRIPTION_IDX].id;
/* support autoresume for remote wakeup testing */
serial_config_driver.bmAttributes &= ~USB_CONFIG_ATT_WAKEUP;
serial_config_driver.descriptors = NULL;
//if (autoresume) {
// serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
//}
usb_add_config_only(cdev, &serial_config_driver);
//return add_hid_function(&serial_config_driver);
status = add_hid_function(&serial_config_driver);
if (status)
return status;
return add_display_function(&serial_config_driver);
}
static int gs_unbind(struct usb_composite_dev *cdev)
{
return 0;
}
static __refdata struct usb_composite_driver usb_display_driver = {
.name = RP_DISP_DRIVER_NAME,
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_HIGH,
.bind = gs_bind,
.unbind = gs_unbind,
};
static int __init init(void)
{
return usb_composite_probe(&usb_display_driver);
}
module_init(init);
static void __exit cleanup(void)
{
usb_composite_unregister(&usb_display_driver);
}
module_exit(cleanup);
MODULE_DESCRIPTION(GS_VERSION_NAME);
MODULE_AUTHOR("bobo");
MODULE_LICENSE("GPL");