微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Linux USB gadget设备驱动解析(4)--编写一个gadget驱动

Linux USB gadget设备驱动解析(4)--编写一个gadget驱动

时间:08-06 来源:互联网 点击:

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

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top