新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > Linux USB gadget設(shè)備驅(qū)動(dòng)解析(4)--編寫一個(gè)gadget驅(qū)動(dòng)

Linux USB gadget設(shè)備驅(qū)動(dòng)解析(4)--編寫一個(gè)gadget驅(qū)動(dòng)

作者: 時(shí)間:2012-08-06 來源:網(wǎng)絡(luò) 收藏

.bmAttributes = _ENDPOINT_XFER_BULK,

};

static struct usb_config_descriptor loopback_config = { //配置描述符

.bLength = sizeof loopback_config,

.bDescriptorType = _DT_CONFIG,

/* compute wTotalLength on the fly */

.bNumInterfaces = 1,

.bConfigurationValue = CONFIG_LOOPBACK,

.iConfiguration = STRING_LOOPBACK,

.bmAttributes = _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__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)//分配請(qǐng)求

{

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)//請(qǐng)求完成函數(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);//返回?cái)?shù)據(jù)拷貝到req->buf中, //dev->data_size=req->length;

dev->data_size=req->actual; //實(shí)際長(zhǎng)度為req-> actual;需要確認(rèn)

req –>short_not_ok為0。參考.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ā)送讀請(qǐng)求

{

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; //請(qǐng)求完成函數(shù)

status = usb_ep_queue(ep, req, GFP_ATOMIC); //遞交請(qǐng)求

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教程




評(píng)論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉