新聞中心

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

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

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

        return req;

        }

        ssize_t

        usb_zero_read (struct file * file, const char __user * buf, size_t count,loff_t * f_pos) //讀設備

        {

        struct zero_dev *dev =file->private_data;

        struct usb_request *req;

        int status;

        struct usb_ep *ep;

        struct usb_ * = dev->;

        ssize_t ret = 0;

        int result;

        ep=dev->out_ep;

        source_sink_start_ep(ep);//構造、遞交讀請求

        if (count 0)

        return -EINVAL;

        interruptible_sleep_on (dev->bulkrq);//睡眠,等到請求完成

        if (copy_to_user (buf,dev->data,dev->data_size)) //拷貝讀取的數據到用戶空間

        {

        ret = -EFAULT;

        }

        else

        {

        ret = dev->data_size;

        }

        return ret;

        }

        struct file_operations usb_zero_fops = {

        .owner = THIS_MODULE,

        .read = usb_zero_read,

        .open = usb_zero_open,

        .release = usb_zero_release,

        };

        static void

        usb_zero_setup_cdev (struct zero_dev *dev, int minor)//注冊字符設備

        {

        int err, devno = MKDEV (usb_zero_major, minor);

        cdev_init(dev->cdev, usb_zero_fops);

        dev->cdev.owner = THIS_MODULE;

        err = cdev_add (dev->cdev, devno, 1);

        if (err)

        printk (Error adding usb_rcvn);

        }

        static void zero_setup_complete(struct usb_ep *ep, struct usb_request *req)//配置端點0的請求

        完成處理

        {

        if (req->status || req->actual != req->length)

        printk(setup complete --> %d, %d/%dn,

        req->status, req->actual, req->length);

        }

        static void zero_reset_config(struct zero_dev *dev) //復位配置

        {

        usb_ep_disable(dev->out_ep);

        dev->out_ep = NULL;

        }

        static void zero_disconnect(struct usb_gadget *gadget)//卸載時被調用,做一些注銷工作

        {

        struct zero_dev *dev = get_gadget_data(gadget);

        unsigned long flags;

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

        cdev_del ((dev->cdev));

        zero_reset_config(dev);

        printk(in %sn,__FUNCTION__);

        }

        static int config_buf(struct usb_gadget *gadget,

        u8 *buf, u8 type, unsigned index)

        {

        //int is_source_sink;

        int len;

        const struct usb_descriptor_header **function;

        int hs = 0;

        function =fs_loopback_function;//根據fs_loopback_function,得到長度,

        //此處len=配置(9)+1個接口(9)+1個端點(7)=25

        len = usb_gadget_config_buf(loopback_config,

        buf, _BUFSIZ, function);

        if (len 0)

        return len;

        ((struct usb_config_descriptor *) buf)->bDescriptorType = type;

        return len;

        }

        static int set_loopback_config(struct zero_dev *dev)

        {

        int result = 0;

        struct usb_ep *ep;

        struct usb_gadget *gadget = dev->gadget;

        ep=dev->out_ep;

        const struct usb_endpoint_descriptor *d;

        d = fs_sink_desc;

        result = usb_ep_enable(ep, d); //激活端點

        //printk();

        if (result == 0) {

        printk(connectedn); //如果成功,打印“connected”

        }

        else

        printk(can't enable %s, result %dn, ep->name, result);

        return result;

        }

        static int zero_set_config(struct zero_dev *dev, unsigned number)

        {

        int result = 0;

        struct usb_gadget *gadget = dev->gadget;

        result = set_loopback_config(dev);//激活設備

        if (result)

        zero_reset_config(dev); //復位設備

        else {

        char *speed;

        switch (gadget->speed) {

        case _SPEED_LOW: speed = low; break;

        case _SPEED_FULL: speed = full; break;

        case USB_SPEED_HIGH: speed = high; break;

        default: speed = ; break;

        }

        }

        return result;

        }

        /***

        zero_setup完成USB設置階段和具體功能相關的交互部分

        ***/

        static int

        zero_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)

        {

        struct zero_dev *dev = get_gadget_data(gadget);

        struct usb_request *req = dev->req;

        int value = -EOPNOTSUPP;

        u16 w_index = le16_to_cpu(ctrl->wIndex);

        u16 w_value = le16_to_cpu(ctrl->wValue);

        u16 w_length = le16_to_cpu(ctrl->wLength);

        /* usually this stores reply data in the pre-allocated ep0 buffer,

        * but config change events will reconfigure hardware.

        */

        req->zero = 0;

        switch (ctrl->bRequest) {

        case USB_REQ_GET_DESCRIPTOR: //獲取描述符

        if (ctrl->bRequestType != USB_DIR_IN)

        goto unknown;

        switch (w_value >> 8) {

        case USB_DT_DEVICE: //獲取設備描述符

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

        linux相關文章:linux教程




        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 邢台市| 铁岭市| 开鲁县| 桐城市| 天津市| 新宾| 甘南县| 道孚县| 迁安市| 沭阳县| 依兰县| 吴堡县| 忻城县| 贡嘎县| 深水埗区| 大渡口区| 肥西县| 宣武区| 大冶市| 隆化县| 武城县| 石屏县| 昭苏县| 泉州市| 钦州市| 南皮县| 阿尔山市| 钟祥市| 鲁甸县| 扎囊县| 平凉市| 越西县| 措美县| 玉林市| 商城县| 定南县| 绥中县| 开远市| 德化县| 巩留县| 洛宁县|