由于工作需要:
orangepi zero 需要otg device支持两个hid设备与一个tty串口设备,使用官网代码发现usb otg device 不满足需要
经过一番探索,做了以下修改
在此聊聊记下
首先修改了gadget的设备驱动serial代码,在serial中增加两个hid设备,关键代码如下
static bool use_acm = false;//禁用acm使用gs代码
#include "f_hid.c"//包含hidgadget的相关代码
serial_config_driver.bConfigurationValue = 3;//修改配置个数为3
device_desc.bDeviceClass = 0;//修改设备类为0(为什么设置为0,在usb设备描述符中去找原因)
//增加一个键盘的数据描述,用于注册hid设备
static struct hidg_func_descriptor my_hid_data = {
.subclass = 0, /* No 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 */
}
};
//在gs_bind中增加下面先关代码,为了标明增加位置 特多复制了几行代码
/* register our configuration */
status = usb_add_config(cdev, &serial_config_driver,
serial_bind_config);
if (status < 0)
goto fail;
status = ghid_setup(cdev->gadget, 2);
if (status < 0)
return status;
status = hidg_bind_config(&serial_config_driver, &my_hid_data,0);
if (status < 0)
return status;
status = hidg_bind_config(&serial_config_driver, &my_hid_data,1);
if (status < 0)
return status;
usb_gadget_connect(cdev->gadget);
按照正常逻辑在增加以上代码后设备应该能够正常枚举,枚举出两个hid键盘与一个串口设备,但是经过多次测试发现还是有问题,设备枚举失败,一个设备都没有正常枚举,经过一番苦查,发现问题出现在hidg_bind_config,在bind hid设备的时候出现的问题,在bind的时候发现有debug信息显示 hid的endpoint 申请失败,于是开始怀疑是cpu本身提供的endpoint不够,又去查cpu手册,发现手册上显示的allwinner H2的作为device时有8个endpoint,所以这个疑点又排除了
又经过一番苦查发现H2的usb otg的endpoint 类型在代码中直接定义死了,不能在代码运行时进行修改,修改了相关代码后出现了我想要的结果修改了以下代码,虽然有些瑕疵,但是已经满足了现在的需要
--- a/OrangePi-Kernel/linux-3.4/drivers/usb/sunxi_usb/include/sunxi_udc.h
+++ b/OrangePi-Kernel/linux-3.4/drivers/usb/sunxi_usb/include/sunxi_udc.h
@@ -71,7 +71,8 @@ static const char ep1in_bulk_name [] = "ep1in-bulk";
static const char ep1out_bulk_name [] = "ep1out-bulk";
static const char ep2in_bulk_name [] = "ep2in-bulk";
static const char ep2out_bulk_name [] = "ep2out-bulk";
-static const char ep3_iso_name [] = "ep3-iso";
+//static const char ep3_iso_name [] = "ep3-iso";
+static const char ep3_iso_name [] = "ep3-int";//不要被变量名迷惑,这里根据字符串进行查找的
static const char ep4_int_name [] = "ep4-int";
static const char ep5in_bulk_name [] = "ep5in-bulk";
static const char ep5out_bulk_name [] = "ep5out-bulk";
--- a/OrangePi-Kernel/linux-3.4/drivers/usb/sunxi_usb/udc/sunxi_udc.c
+++ b/OrangePi-Kernel/linux-3.4/drivers/usb/sunxi_usb/udc/sunxi_udc.c
@@ -2777,12 +2777,12 @@ static struct sunxi_udc sunxi_udc = {
.ep = {
.name = ep3_iso_name,
.ops = &sunxi_udc_ep_ops,
- .maxpacket = SW_UDC_EP_ISO_FIFO_SIZE,
+ .maxpacket = SW_UDC_EP_FIFO_SIZE,//修改最大值(这个修改在sunxi_udc.h中有个size的定义,不知道会不会有潜在的问题,暂时可以满足我的需求)
},
.dev = &sunxi_udc,
//.fifo_size = SW_UDC_EP_FIFO_SIZE,
.bEndpointAddress = 3,
- .bmAttributes = USB_ENDPOINT_XFER_ISOC,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,//修改相关的类型
},
代码没有整理,应该可以修改相关的变量名,已经最大值的适配,该工作暂时告一段落,日后有问题的话再去查找
全部的diff 如下
diff --git a/OrangePi-Kernel/linux-3.4/drivers/usb/gadget/f_serial.c b/OrangePi-Kernel/linux-3.4/drivers/usb/gadget/f_serial.c
index 07197d63..3ef2589a 100644
--- a/OrangePi-Kernel/linux-3.4/drivers/usb/gadget/f_serial.c
+++ b/OrangePi-Kernel/linux-3.4/drivers/usb/gadget/f_serial.c
@@ -47,8 +47,8 @@ static struct usb_interface_descriptor gser_interface_desc __initdata = {
.bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */
.bNumEndpoints = 2,
- .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
- .bInterfaceSubClass = 0,
+ .bInterfaceClass = 2,
+ .bInterfaceSubClass = 2,
.bInterfaceProtocol = 0,
/* .iInterface = DYNAMIC */
};
diff --git a/OrangePi-Kernel/linux-3.4/drivers/usb/gadget/serial.c b/OrangePi-Kernel/linux-3.4/drivers/usb/gadget/serial.c
index 665c0742..bc00d988 100644
--- a/OrangePi-Kernel/linux-3.4/drivers/usb/gadget/serial.c
+++ b/OrangePi-Kernel/linux-3.4/drivers/usb/gadget/serial.c
@@ -18,6 +18,7 @@
#include "u_serial.h"
#include "gadget_chips.h"
+#include "f_hid.c"
/* Defines */
@@ -97,7 +98,7 @@ static struct usb_device_descriptor device_desc = {
/* .bcdDevice = f(hardware) */
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
- .bNumConfigurations = 1,
+ .bNumConfigurations = 3,
};
static struct usb_otg_descriptor otg_descriptor = {
@@ -123,7 +124,7 @@ MODULE_AUTHOR("Al Borchers");
MODULE_AUTHOR("David Brownell");
MODULE_LICENSE("GPL");
-static bool use_acm = true;
+static bool use_acm = false;
module_param(use_acm, bool, 0);
MODULE_PARM_DESC(use_acm, "Use CDC ACM, default=yes");
@@ -159,6 +160,49 @@ static struct usb_configuration serial_config_driver = {
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
};
+/* hid descriptor for a keyboard */
+static struct hidg_func_descriptor my_hid_data = {
+ .subclass = 0, /* No 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 */
+ }
+};
+
+
static int __init gs_bind(struct usb_composite_dev *cdev)
{
@@ -229,6 +273,14 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
if (status < 0)
goto fail;
+ status = ghid_setup(cdev->gadget, 2);
+ if (status < 0)
+ return status;
+ status = hidg_bind_config(&serial_config_driver, &my_hid_data,0);
+ status = hidg_bind_config(&serial_config_driver, &my_hid_data,1);
+ usb_gadget_connect(cdev->gadget);
+
+
INFO(cdev, "%s\n", GS_VERSION_NAME);
return 0;
@@ -264,8 +316,9 @@ static int __init init(void)
cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID);
} else {
serial_config_driver.label = "Generic Serial config";
- serial_config_driver.bConfigurationValue = 1;
- device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
+ serial_config_driver.bConfigurationValue = 3;
+ //device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
+ device_desc.bDeviceClass = 0;
device_desc.idProduct =
cpu_to_le16(GS_PRODUCT_ID);
}
diff --git a/OrangePi-Kernel/linux-3.4/drivers/usb/sunxi_usb/include/sunxi_udc.h b/OrangePi-Kernel/linux-3.4/drivers/usb/sunxi_usb/include/sunxi_udc.h
index f9cabe94..974f0ae2 100755
--- a/OrangePi-Kernel/linux-3.4/drivers/usb/sunxi_usb/include/sunxi_udc.h
+++ b/OrangePi-Kernel/linux-3.4/drivers/usb/sunxi_usb/include/sunxi_udc.h
@@ -71,7 +71,8 @@ static const char ep1in_bulk_name [] = "ep1in-bulk";
static const char ep1out_bulk_name [] = "ep1out-bulk";
static const char ep2in_bulk_name [] = "ep2in-bulk";
static const char ep2out_bulk_name [] = "ep2out-bulk";
-static const char ep3_iso_name [] = "ep3-iso";
+//static const char ep3_iso_name [] = "ep3-iso";
+static const char ep3_iso_name [] = "ep3-int";
static const char ep4_int_name [] = "ep4-int";
static const char ep5in_bulk_name [] = "ep5in-bulk";
static const char ep5out_bulk_name [] = "ep5out-bulk";
diff --git a/OrangePi-Kernel/linux-3.4/drivers/usb/sunxi_usb/udc/sunxi_udc.c b/OrangePi-Kernel/linux-3.4/drivers/usb/sunxi_usb/udc/sunxi_udc.c
index f24298c7..3c05f810 100755
--- a/OrangePi-Kernel/linux-3.4/drivers/usb/sunxi_usb/udc/sunxi_udc.c
+++ b/OrangePi-Kernel/linux-3.4/drivers/usb/sunxi_usb/udc/sunxi_udc.c
@@ -2777,12 +2777,12 @@ static struct sunxi_udc sunxi_udc = {
.ep = {
.name = ep3_iso_name,
.ops = &sunxi_udc_ep_ops,
- .maxpacket = SW_UDC_EP_ISO_FIFO_SIZE,
+ .maxpacket = SW_UDC_EP_FIFO_SIZE,
},
.dev = &sunxi_udc,
//.fifo_size = SW_UDC_EP_FIFO_SIZE,
.bEndpointAddress = 3,
- .bmAttributes = USB_ENDPOINT_XFER_ISOC,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
},
.ep[6] = {