Linux USB gadget设备驱动解析(4)--编写一个gadget驱动
nfig,
.bDescriptorType = USB_DT_CONFIG,
/* compute wTotalLength on the fly */
.bNumInterfaces = 1,
.bConfigurationValue = CONFIG_LOOPBACK,
.iConfiguration = STRING_LOOPBACK,
.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFpower,
.bMaxPower = 1, /* self-powered */
};
static const struct usb_interface_descriptor loopback_intf = { //接口描述符
.bLength = sizeof loopback_intf,
.bDescriptorType = USB_DT_INTERFACE,
.bNumEndpoints = 1,
.bInterfaceClass = USB_CLASS_VENDOR_SPEC,
.iInterface = STRING_LOOPBACK,
};
/* static strings, in UTF-8 */
#define STRING_MANUFACTURER 25
#define STRING_PRODUCT 42
#define STRING_SERIAL 101
#define STRING_SOURCE_SINK 250
#define STRING_LOOPBACK 251
static char manufacturer[50];
/* default serial number takes at least two packets */
static char serial[] = 0123456789.0123456789.0123456789;
static struct usb_string strings[] = { //字符串描述符
{ STRING_MANUFACTURER, manufacturer, },
{ STRING_PRODUCT, longname, },
{ STRING_SERIAL, serial, },
{ STRING_LOOPBACK, loopback, },
{ STRING_SOURCE_SINK, source_sink, },
{ } /* end of list */
};
static struct usb_gadget_strings stringtab = {
.language = 0x0409, /* en-us */
.strings = strings,
};
static const struct usb_descriptor_header *fs_loopback_function[] = {
(struct usb_descriptor_header *) loopback_intf,
(struct usb_descriptor_header *) fs_sink_desc,
NULL,
};
static int
usb_zero_open (struct inode *inode, struct file *file) //打开设备
{
struct zero_dev *dev =
container_of (inode->i_cdev, struct zero_dev, cdev);
file->private_data = dev;
init_waitqueue_head (dev->bulkrq);
return 0;
}
static int
usb_zero_release (struct inode *inode, struct file *file) //关闭设备
{
return 0;
}
static void free_ep_req(struct usb_ep *ep, struct usb_request *req)
{
kfree(req->buf);
usb_ep_free_request(ep, req);
}
static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)//分配请求
{
struct usb_request *req;
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
if (req) {
req->length = length;
req->buf = kmalloc(length, GFP_ATOMIC);
if (!req->buf) {
usb_ep_free_request(ep, req);
req = NULL;
}
}
return req;
}
static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)//请求完成函数
{
struct zero_dev *dev = ep->driver_data;
int status = req->status;
switch (status) {
case 0: /* normal completion */
if (ep == dev->out_ep) {
memcpy(dev->data, req->buf, req-> actual);//返回数据拷贝到req->buf中, //dev->data_size=req->length;
dev->data_size=req->actual; //实际长度为req-> actual;需要确认
req –>short_not_ok为0。参考gadget.h中关于usb_request结构的注释
}
break;
/* this endpoint is normally active while we're configured */
case -ECONNABORTED: /* hardware forced ep reset */
case -ECONNRESET: /* request dequeued */
case -ESHUTDOWN: /* disconnect from host */
printk(%s gone (%d), %d/%dn, ep->name, status,
req->actual, req->length);
case -EOVERFLOW: /* buffer overrun on read means that
* we didn't provide a big enough
* buffer.
*/
default:
#if 1
printk(%s complete --> %d, %d/%dn, ep->name,
status, req->actual, req->length);
#endif
case -EREMOTEIO: /* short read */
break;
}
free_ep_req(ep, req);
wake_up_interruptible (dev->bulkrq); //唤醒读函数
}
static struct usb_request *source_sink_start_ep(struct usb_ep *ep)//构造并发送读请求
{
struct usb_request *req;
int status;
//printk(in %sn,__FUNCTION__);
req = alloc_ep_req(ep, 128);
if (!req)
return NULL;
memset(req->buf, 0, req->length);
req->complete = source_sink_complete; //请求完成函数
status = usb_ep_queue(ep, req, GFP_ATOMIC); //递交请求
if (status) {
struct zero_dev *dev = ep->driver_data;
printk(start %s --> %dn, ep->name, status);
fr
gadget 一个 驱动 编写 设备驱动 USB Linux 解析 相关文章:
- 关于spiflash存储器读写一个字节的问题方案(11-27)
- 第1节:单片机到底是学什么?我的两个比喻和一个规则(11-22)
- 汇编入门学习笔记 (三) —— 第一个程序(11-09)
- DIY一个MSP430F149最小系统的设计(07-22)
- 视频显示卡直接写屏的一个实例(09-14)
- 单片机c语言教程:建立你的第一个KeilC51项目(09-11)