新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > Linux USB gadget設備驅動解析(4)--編寫一個gadget驅動

        Linux USB gadget設備驅動解析(4)--編寫一個gadget驅動

        作者: 時間:2012-08-06 來源:網絡 收藏

        .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) //打開設備

        {

        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。參考.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);

        free_ep_req(ep, req);

        req = NULL;

        }

        linux操作系統文章專題:linux操作系統詳解(linux不再難懂)

        linux相關文章:linux教程




        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 九寨沟县| 平度市| 新巴尔虎左旗| 屏边| 武定县| 滦南县| 郎溪县| 海兴县| 安岳县| 藁城市| 聊城市| 莱西市| 临沧市| 安多县| 昔阳县| 武乡县| 财经| 朔州市| 阿克陶县| 渭源县| 湄潭县| 新昌县| 饶河县| 阿城市| 和田市| 桃江县| 潞城市| 鄂州市| 高邑县| 肇庆市| 鄂伦春自治旗| 仁怀市| 祁门县| 吉首市| 望江县| 罗甸县| 秦皇岛市| 江阴市| 永顺县| 察雅县| 宁明县|