例程
官方例程..\freertos\example\usb\device\gadget_generic_bulk.c,代码如下:
#include <common.h>
#include <usb/gadget_bulk.h>
#include <os.h>
static const struct gadget_id bulk_id = {
.vendor_id = 0x1CBE,
.product_id = 0x0003
};
static void bulk_connect_callback(int connect)
{
printf("generic_bulk_connect_callback %d\n", connect);
}
static unsigned char usb_test_buf[1024];
static const char *usb_test_char = "hello world!\r\n";
static void usb_gadget_bulk_thread(void *data)
{
int len, i;
while (1) {
msleep(1000);
gadget_bulk_write((const unsigned char *)usb_test_char, strlen(usb_test_char), 1, THREAD_COND_TIMEOUT_NO_LIMIT_MS);
len = gadget_bulk_read(usb_test_buf, sizeof(usb_test_buf), 0, 0);
if (len > 0) {
for(i = 0; i < len; i++)
printf("usb bulk read data %d\n", usb_test_buf[i]);
}
}
}
int gadget_usb_bulk_test(void)
{
gadget_bulk_init(&bulk_id, bulk_connect_callback);
thread_create("usb gadget bulk thread", 4096, usb_gadget_bulk_thread, NULL);
return 0;
}
只能修改vendor_id和product_id,描述的内容是固定的,如需修改描述符等信息,需要..\freertos\drivers\usb\gadget\generic_bulk\generic_bulk.c文件,代码如下:
#include <common.h>
#include <os.h>
#include <usb/gadget_bulk.h>
#include "../composite.h"
#define DRIVER_DESC "Generic Bulk Device"
extern struct usb_function *generic_bulk_device_alloc(connect_callback_t connect_cb);
extern void generic_bulk_device_free(void);
/*-------------------------------------------------------------------------*/
/*
* DESCRIPTORS ... most are static, but strings and (full) configuration
* descriptors are built on demand.
*/
static struct usb_device_descriptor device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
/* .bcdUSB = DYNAMIC */
.bDeviceClass = USB_CLASS_VENDOR_SPEC,
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
/* .idVendor = DYNAMIC */
/* .idProduct = DYNAMIC */
.bNumConfigurations = 1
};
/*-------------------------------------------------------------------------*/
/* static strings, in UTF-8 */
static struct usb_string strings [] = {
[USB_GADGET_MANUFACTURER_IDX].s = "INGENIC",
[USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC,
[USB_GADGET_SERIAL_IDX].s = "ingenic",
{ } /* end of list */
};
static struct usb_gadget_strings stringtab_dev = {
.language = 0x0409, /* en-us */
.strings = strings,
};
static struct usb_gadget_strings *dev_strings[] = {
&stringtab_dev,
NULL,
};
static struct usb_configuration generic_bulk_cfg_driver = {
.label = DRIVER_DESC,
.bConfigurationValue = 1,
};
static connect_callback_t bulk_connect_cb;
static int generic_bulk_do_config(struct usb_configuration *c)
{
static struct usb_function *f_bulk;
int status = 0;
f_bulk = generic_bulk_device_alloc(bulk_connect_cb);
if (IS_ERR(f_bulk))
return PTR_ERR(f_bulk);
status = usb_add_function(c, f_bulk);
if (status < 0)
generic_bulk_device_free();
return status;
}
static int generic_bulk_bind(struct usb_composite_dev *cdev)
{
int ret;
ret = usb_string_ids_tab(cdev, strings);
if (ret < 0)
return ret;
device_desc.iManufacturer = strings[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings[USB_GADGET_PRODUCT_IDX].id;
device_desc.iSerialNumber = strings[USB_GADGET_SERIAL_IDX].id;
ret = usb_add_config(cdev, &generic_bulk_cfg_driver, generic_bulk_do_config);
return ret;
}
static int generic_bulk_unbind(struct usb_composite_dev *cdev)
{
generic_bulk_device_free();
return 0;
}
static struct usb_composite_driver generic_bulk_driver = {
.name = "generic_bulk",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_HIGH,
.bind = generic_bulk_bind,
.unbind = generic_bulk_unbind,
};
int gadget_bulk_init(const struct gadget_id *id, connect_callback_t connect_cb)
{
int ret;
if (id == NULL)
panic("gadget_generic_bulk_init param id is NULL! \n");
device_desc.idVendor = id->vendor_id;
device_desc.idProduct = id ->product_id;
bulk_connect_cb = connect_cb;
ret = usb_composite_probe(&generic_bulk_driver);
return ret;
}
void gadget_bulk_cleanup(void)
{
usb_composite_unregister(&generic_bulk_driver);
}
驱动的头文件为..\freertos\include\usb\gadget_bulk.h,内容如下:
#ifndef _GADGET_BULK_H_
#define _GADGET_BULK_H_
#include "gadget_common.h"
#ifdef CONFIG_USB_GADGET_BULK
extern int gadget_bulk_init(const struct gadget_id *id, connect_callback_t connect_cb);
extern void gadget_bulk_cleanup(void);
extern int gadget_bulk_read(uint8_t *buffer, uint32_t len, uint8_t block, uint32_t timeout_ms);
extern int gadget_bulk_write(const uint8_t *buffer, uint32_t len, uint8_t block, uint32_t timeout_ms);
extern int gadget_bulk_flush_data(uint32_t timeout_ms)
;
extern int gadget_bulk_get_connect_status(void);
extern int gadget_bulk_wait_connect(uint32_t timeout_ms);
#endif
#endif /* _GADGET_BULK_H_ */
需要定义CONFIG_USB_GADGET_BULK宏才能使用驱动函数。
config文件中定义CONFIG_USB_GADGET_BULK宏
保存配置文件,退出。
测试
将例程gadget_generic_bulk.c中的代码加入主代码,然后编译、下载。设备启动后连接到电脑的USB口,可以看到电脑的设备管理中出现了一个"Generic Bulk Device"设备。
可以用zadig工具为其生成驱动。
安装驱动后,在电脑的设备管理器中可以看到一个libusb的设备:
查看描述符
可运行testlibusb-win.exe应用查看USB配置信息:
从描述符显示有一个接口,包含两个端点,一个输入端点0x81,一个输出端点0x01,数据包长度最大为512字节。