但是我就是想当成usb设备,来实现数据的通信呢?这个驱动和测试程序应该如何来写
时间: 2024-03-17 11:41:13 浏览: 208
usb_hid_vc_简单读写测试程序+源码+驱动
4星 · 用户满意度95%
好的,如果您想将Zynq平台模拟成一个USB设备,可以使用USB Gadget驱动中的`gadgetfs`模块来实现。具体来说,`gadgetfs`模块可以将USB设备的文件系统映射到Linux文件系统中,从而可以通过文件的方式来进行USB数据的读写操作。
以下是一个基于Zynq平台USB Gadget驱动的C测试程序,可以将Zynq平台模拟成一个USB HID设备,通过USB接口向主机发送键盘按键信息:
驱动部分:
```c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/hid.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/composite.h>
#include <linux/string.h>
#include <linux/slab.h>
#define GADGET_NAME "g_hid"
#define GADGET_STRING_MANUFACTURER "Manufacturer"
#define GADGET_STRING_PRODUCT "Product"
#define GADGET_STRING_SERIAL "SerialNumber"
#define GADGET_STRING_CONFIG "Config"
#define GADGET_STRING_INTERFACE "Interface"
#define GADGET_VENDOR_ID 0x1234
#define GADGET_PRODUCT_ID 0x5678
#define GADGET_PRODUCT_NAME "Gadget HID Keyboard"
#define GADGET_SERIAL_NUMBER "1234567890"
#define GADGET_REPORT_LENGTH 8
static struct usb_device_descriptor gadget_device_desc = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = 0,
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
.bMaxPacketSize0 = 64,
.idVendor = cpu_to_le16(GADGET_VENDOR_ID),
.idProduct = cpu_to_le16(GADGET_PRODUCT_ID),
.bcdDevice = cpu_to_le16(0x0100),
.iManufacturer = 1,
.iProduct = 2,
.iSerialNumber = 3,
.bNumConfigurations = 1,
};
static struct usb_string gadget_strings[] = {
[0] = {
.id = 0x0409,
.s = GADGET_STRING_MANUFACTURER,
},
[1] = {
.id = 0x0409,
.s = GADGET_STRING_PRODUCT,
},
[2] = {
.id = 0x0409,
.s = GADGET_STRING_SERIAL,
},
[3] = {
.id = 0x0409,
.s = GADGET_STRING_CONFIG,
},
[4] = {
.id = 0x0409,
.s = GADGET_STRING_INTERFACE,
},
{},
};
static struct usb_gadget_strings gadget_stringtab = {
.language = 0x0409,
.strings = gadget_strings,
};
static struct usb_string *gadget_find_string(struct usb_gadget_strings *table, int id) {
struct usb_string *str;
int i;
for (i = 0; i < table->count; i++) {
str = &table->strings[i];
if (str->id == id) {
return str;
}
}
return NULL;
}
static struct usb_interface_descriptor gadget_hid_intf_desc = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 1,
.bInterfaceClass = USB_CLASS_HID,
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 1,
.iInterface = 4,
};
static struct usb_endpoint_descriptor gadget_hid_endpoint_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x81,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(GADGET_REPORT_LENGTH),
.bInterval = 10,
};
static struct usb_descriptor_header *gadget_hid_descs[] = {
(struct usb_descriptor_header *)&gadget_hid_intf_desc,
(struct usb_descriptor_header *)&gadget_hid_endpoint_desc,
NULL,
};
static struct usb_interface_descriptor gadget_data_intf_desc = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 1,
.bAlternateSetting = 0,
.bNumEndpoints = 0,
.bInterfaceClass = USB_CLASS_DATA,
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
.iInterface = 0,
};
static struct usb_descriptor_header *gadget_data_descs[] = {
(struct usb_descriptor_header *)&gadget_data_intf_desc,
NULL,
};
static struct usb_config_descriptor gadget_config_desc = {
.bLength = USB_DT_CONFIGURATION_SIZE,
.bDescriptorType = USB_DT_CONFIGURATION,
.wTotalLength = cpu_to_le16(sizeof(struct usb_config_descriptor) +
sizeof(struct usb_interface_descriptor) +
sizeof(struct usb_endpoint_descriptor)),
.bNumInterfaces = 2,
.bConfigurationValue = 1,
.iConfiguration = 3,
.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
.bMaxPower = 0x00,
.interface = (struct usb_interface_descriptor **)gadget_hid_descs,
};
static struct usb_descriptor_header *gadget_config_descs[] = {
(struct usb_descriptor_header *)&gadget_config_desc,
NULL,
};
static struct usb_composite_driver gadget_driver = {
.name = GADGET_NAME,
.dev = &gadget_device_desc,
.strings = &gadget_stringtab,
.configs = gadget_config_descs,
.bind = gadget_bind,
.unbind = gadget_unbind,
.setup = gadget_setup,
.disconnect = gadget_disconnect,
};
```
测试程序部分:
```c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mount.h>
#include <sys/stat.h>
#define GADGET_ENDPOINT "/dev/hidg0"
int main() {
int fd, ret;
char buf[8];
// 打开USB HID设备
fd = open(GADGET_ENDPOINT, O_WRONLY);
if (fd < 0) {
printf("Open failed.\n");
return -1;
} else {
printf("Open succeeded.\n");
}
// 发送键盘按键信息
buf[0] = 0;
buf[1] = 0x04;
buf[2] = 0;
buf[3] = 0;
buf[4] = 0;
buf[5] = 0;
buf[6] = 0;
buf[7] = 0;
write(fd, buf, sizeof(buf));
buf[0] = 0;
buf[1] = 0;
buf[2] = 0;
buf[3] = 0;
buf[4] = 0;
buf[5] = 0;
buf[6] = 0;
buf[7] = 0;
write(fd, buf, sizeof(buf));
// 关闭USB HID设备
close(fd);
return 0;
}
```
需要注意的是,该程序需要在PetaLinux环境中进行编译,并需要将生成的可执行文件复制到Zynq板子上进行测试。同时,需要确保USB Gadget驱动模块已经成功加载,并且USB设备已经正确连接到主机。
阅读全文