Linux USB gadget設(shè)備驅(qū)動解析(4)--編寫一個gadget驅(qū)動
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_config_descriptor loopback_config = { //配置描述符
.bLength = sizeof loopback_config,
.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) //打開設(shè)備
{
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) //關(guān)閉設(shè)備
{
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)//請求完成函數(shù)
{
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);//返回數(shù)據(jù)拷貝到req->buf中, //dev->data_size=req->length;
dev->data_size=req->actual; //實際長度為req-> actual;需要確認
req –>short_not_ok為0。參考gadget.h中關(guān)于usb_request結(jié)構(gòu)的注釋
}
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); //喚醒讀函數(shù)
}
static struct usb_request *source_sink_start_ep(struct usb_ep *ep)//構(gòu)造并發(fā)送讀請求
{
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; //請求完成函數(shù)
status = usb_ep_queue(ep, req, GFP_ATOMIC); //遞交請求
if (status) {
struct zero_dev *dev = ep->driver_data;
printk(start %s --> %dn, ep->name, status);
free_ep_req(ep, req);
req = NULL;
}
linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)linux相關(guān)文章:linux教程
評論