• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁(yè) > 嵌入式系統(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 來(lái)源:網(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)閉
    主站蜘蛛池模板: 公主岭市| 合江县| 大兴区| 永顺县| 龙泉市| 宝应县| 马关县| 衡山县| 上蔡县| 巨野县| 六枝特区| 休宁县| 上饶市| 河北区| 敦煌市| 仁布县| 阿拉善右旗| 乌海市| 仁化县| 万全县| 蕉岭县| 呈贡县| 岳普湖县| 句容市| 拜城县| 会泽县| 驻马店市| 漾濞| 黄浦区| 资兴市| 井陉县| 韶关市| 台州市| 昌吉市| 婺源县| 南阳市| 昌乐县| 濮阳县| 防城港市| 龙海市| 铜鼓县|