新聞中心

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

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

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

        value = min(w_length, (u16) sizeof device_desc);

        memcpy(req->buf, device_desc, value);

        break;

        case _DT_CONFIG: //獲取配置,注意:會(huì)根據(jù)fs_loopback_function讀取到接口、端點(diǎn)描述符,注意通過(guò)config_buf完成讀取數(shù)據(jù)及數(shù)量的統(tǒng)計(jì)。

        value = config_buf(, req->buf,

        w_value >> 8,

        w_value 0xff);

        if (value >= 0)

        value = min(w_length, (u16) value);

        break;

        case _DT_STRING:

        value = usb__get_string(stringtab,

        w_value 0xff, req->buf);

        if (value >= 0)

        value = min(w_length, (u16) value);

        break;

        }

        break;

        case _REQ_SET_CONFIGURATION:

        if (ctrl->bRequestType != 0)

        goto unknown;

        spin_lock(dev->lock);

        value = zero_set_config(dev, w_value);//激活相應(yīng)的端點(diǎn)

        spin_unlock(dev->lock);

        break;

        default:

        unknown:

        printk(

        unknown control req%02x.%02x v%04x i%04x l%dn,

        ctrl->bRequestType, ctrl->bRequest,

        w_value, w_index, w_length);

        }

        /* respond with data transfer before status phase */

        if (value >= 0) {

        req->length = value;

        req->zero = value w_length;

        value = usb_ep_queue(->ep0, req, GFP_ATOMIC);//通過(guò)端點(diǎn)0完成setup

        if (value 0) {

        printk(ep_queue --> %dn, value);

        req->status = 0;

        zero_setup_complete(gadget->ep0, req);

        }

        }

        /* device either stalls (value 0) or reports success */

        return value;

        }

        static void zero_unbind(struct usb_gadget *gadget) //解除綁定

        {

        struct zero_dev *dev = get_gadget_data(gadget);

        printk(unbindn);

        unregister_chrdev_region (MKDEV (usb_zero_major, 0), 1);

        cdev_del ((dev->cdev));

        /* we've already been disconnected ... no i/o is active */

        if (dev->req) {

        dev->req->length = USB_BUFSIZ;

        free_ep_req(gadget->ep0, dev->req);

        }

        kfree(dev);

        set_gadget_data(gadget, NULL);

        }

        static int __init zero_bind(struct usb_gadget *gadget) //綁定過(guò)程

        {

        struct zero_dev *dev;

        struct usb_ep *ep;

        int gcnum;

        usb_ep_autoconfig_reset(gadget);

        ep = usb_ep_autoconfig(gadget, fs_sink_desc);//根據(jù)端點(diǎn)描述符及控制器端點(diǎn)情況,分配合適的端點(diǎn)。

        if (!ep)

        goto enomem;

        EP_OUT_NAME = ep->name; //記錄名稱

        gcnum = usb_gadget_controller_number(gadget);//獲得控制器代號(hào)

        if (gcnum >= 0)

        device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);//賦值設(shè)備描述符

        else {

        pr_warning(%s: controller '%s' not recognizedn,

        shortname, gadget->name);

        device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);

        }

        dev = kzalloc(sizeof(*dev), GFP_KERNEL); //分配設(shè)備結(jié)構(gòu)體

        if (!dev)

        return -ENOMEM;

        spin_lock_init(dev->lock);

        dev->gadget = gadget;

        set_gadget_data(gadget, dev);

        dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);//分配請(qǐng)求

        if (!dev->req)

        goto enomem;

        dev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);

        if (!dev->req->buf)

        goto enomem;

        dev->req->complete = zero_setup_complete;

        dev->out_ep=ep; //記錄端點(diǎn)(就是接收host端數(shù)據(jù)的端點(diǎn))

        printk(name=%sn,dev->out_ep->name); //打印出這個(gè)端點(diǎn)的名稱

        ep->driver_data=dev;

        device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;

        usb_gadget_set_selfpowered(gadget);

        gadget->ep0->driver_data = dev;

        snprintf(manufacturer, sizeof manufacturer, %s %s with %s,

        init_utsname()->sysname, init_utsname()->release,

        gadget->name);

        /**************************字符設(shè)備注冊(cè)*******************/

        dev_t usb_zero_dev = MKDEV (usb_zero_major, 0);

        int result = register_chrdev_region (usb_zero_dev, 1, usb_zero);

        if (result 0)

        {

        printk (KERN_NOTICE Unable to get usb_transfer region, error %dn,result);

        return 0;

        }

        usb_zero_setup_cdev (dev, 0);

        return 0;

        enomem:

        zero_unbind(gadget);

        return -ENOMEM;

        }

        /*-------------------------------------------------------------------------*/

        static struct usb_gadget_driver zero_driver = { //gadget的核心數(shù)據(jù)結(jié)構(gòu)

        #ifdef CONFIG_USB_GADGET_DUALSPEED

        .speed = USB_SPEED_HIGH,

        #else

        .speed = USB_SPEED_FULL,

        #endif

        .function = (char *) longname,

        .bind = zero_bind,

        .unbind = __exit_p(zero_unbind),

        .setup = zero_setup,

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

        linux相關(guān)文章:linux教程




        評(píng)論


        相關(guān)推薦

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

        關(guān)閉
        主站蜘蛛池模板: 海安县| 利川市| 佛学| 金山区| 甘孜县| 天津市| 扎鲁特旗| 敦化市| 巴南区| 郴州市| 无锡市| 武邑县| 藁城市| 资源县| 嘉兴市| 栾城县| 华容县| 彰武县| 房产| 潜江市| 会泽县| 绥化市| 汕尾市| 桦甸市| 慈利县| 麻栗坡县| 靖宇县| 松阳县| 深圳市| 定结县| 错那县| 罗平县| 南溪县| 曲水县| 北碚区| 开封市| 尚义县| 潼关县| 灌阳县| 锦州市| 绥江县|