zoukankan      html  css  js  c++  java
  • UDC (usb device controller) Framework


    http://blog.csdn.net/u011279649/article/details/11059433


    USB gadget driver的框架可分为三部分:UDC-core, composite.c and Android.c,其中 composite.c是核心,其他两部分都要bind 到 composit上。

    1. UDC-core

    结构体usb_gadget中包含指向usb_ep的link head,通过该link head,可以访问
    所有的usb_ep, usb_ep中包含了具体的,最终的ops.

    这些endpoint的ops是何时赋值的?
    我们先看下udc的框架,它提供了一组所有usb device controller都有的属性文件,

    static struct class *udc_class;

    实现为class属性文件组;通过属性文件可以控制udc如:  softconnect

    static struct attribute *usb_udc_attrs[] = {
        &dev_attr_srp.attr,
        &dev_attr_soft_connect.attr,
        &dev_attr_current_speed.attr,
        &dev_attr_maximum_speed.attr,

        &dev_attr_is_dualspeed.attr,
        &dev_attr_is_otg.attr,
        &dev_attr_is_a_peripheral.attr,
        &dev_attr_b_hnp_enable.attr,
        &dev_attr_a_hnp_support.attr,
        &dev_attr_a_alt_hnp_support.attr,
        NULL,
    };

    通过属性文件可以控制udc如:  softconnect

    static ssize_t usb_udc_softconn_store(struct device *dev,
            struct device_attribute *attr, const char *buf, size_t n)
    {
        struct usb_udc        *udc = container_of(dev, struct usb_udc, dev);

        if (sysfs_streq(buf, "connect")) {
            if (udc_is_newstyle(udc))
                usb_gadget_udc_start(udc->gadget, udc->driver);
            usb_gadget_connect(udc->gadget);
        } else if (sysfs_streq(buf, "disconnect")) {
            usb_gadget_disconnect(udc->gadget);
            if (udc_is_newstyle(udc))
                usb_gadget_udc_stop(udc->gadget, udc->driver);
        } else {
            dev_err(dev, "unsupported command '%s' ", buf);
            return -EINVAL;
        }

        return n;
    }


    另外提供static LIST_HEAD(udc_list);
    指向所有的通过函数usb_add_gadget_udc添加的usb_udc,

    向外提供了接口函数usb_add_gadget_udc把具体的usb device controller加入到框架中。

    函数usb_add_gadget_udc的参数是usb_gadget,此时endpoint的ops已经被赋
    值了,可以以此为线索跟踪,就可看明白。


    usb_gadget数据结构间的关系:

    最上层是usb_udc,

    crash> usb_udc
    struct usb_udc {
        struct usb_gadget_driver *driver;
        struct usb_gadget *gadget;
        struct device dev;
        struct list_head list;
    }
    其中包含了 usb_gadget_driver and usb_gadget等

    先看usb_gadget_driver,driver不是应该包含怎样操作设备的方法吗?但它的成员只是包含

    setup/ suspend/resume等。

    usb gadget 的操作方法都是设备本身的属性决定的和自己写的driver没什么关系。但是USB host请求设备描述符等的返回值时,

    usb_gadget_driver是可以决定的。

    crash> usb_gadget_driver
    struct usb_gadget_driver {
        char *function;
        enum usb_device_speed max_speed;
        void (*unbind)(struct usb_gadget *);
        int (*setup)(struct usb_gadget *, const struct usb_ctrlrequest *);
        void (*disconnect)(struct usb_gadget *);
        void (*suspend)(struct usb_gadget *);
        void (*resume)(struct usb_gadget *);
        struct device_driver driver;
    }

    crash> usb_gadget
    struct usb_gadget {
        const struct usb_gadget_ops *ops;
        struct usb_ep *ep0;
        struct list_head ep_list;
        enum usb_device_speed speed;
        enum usb_device_speed max_speed;
        unsigned int sg_supported : 1;
        unsigned int is_otg : 1;
        unsigned int is_a_peripheral : 1;
        unsigned int b_hnp_enable : 1;
        unsigned int a_hnp_support : 1;
        unsigned int a_alt_hnp_support : 1;
        const char *name;
        struct device dev;
    }

    usb_gadget中包含属性的描述如是否具有OTG功能等,还有怎样使用usb_gadget的方法。方法包含两部分:

    1】usb_gadget_ops

    crash> usb_gadget_ops
    struct usb_gadget_ops {
        int (*get_frame)(struct usb_gadget *);
        int (*wakeup)(struct usb_gadget *);
        int (*set_selfpowered)(struct usb_gadget *, int);
        int (*vbus_session)(struct usb_gadget *, int);
        int (*vbus_draw)(struct usb_gadget *, unsigned int);
        int (*pullup)(struct usb_gadget *, int);
        int (*ioctl)(struct usb_gadget *, unsigned int, unsigned long);
        void (*get_config_params)(struct usb_dcd_config_params *);
        int (*udc_start)(struct usb_gadget *, struct usb_gadget_driver *);
        int (*udc_stop)(struct usb_gadget *, struct usb_gadget_driver *);
        int (*start)(struct usb_gadget_driver *, int (*)(struct usb_gadget *));
        int (*stop)(struct usb_gadget_driver *);
    }

    2】有关endpoit的操作

    crash> usb_ep
    struct usb_ep {
        void *driver_data;
        const char *name;
        const struct usb_ep_ops *ops;
        struct list_head ep_list;
        unsigned int maxpacket : 16;
        unsigned int max_streams : 16;
        unsigned int mult : 2;
        unsigned int maxburst : 5;
        u8 address;
        const struct usb_endpoint_descriptor *desc;
        const struct usb_ss_ep_comp_descriptor *comp_desc;
    }

    crash> usb_ep_ops
    struct usb_ep_ops {
        int (*enable)(struct usb_ep *, const struct usb_endpoint_descriptor *);
        int (*disable)(struct usb_ep *);
        struct usb_request *(*alloc_request)(struct usb_ep *, gfp_t);
        void (*free_request)(struct usb_ep *, struct usb_request *);
        int (*queue)(struct usb_ep *, struct usb_request *, gfp_t);
        int (*dequeue)(struct usb_ep *, struct usb_request *);
        int (*set_halt)(struct usb_ep *, int);
        int (*set_wedge)(struct usb_ep *);
        int (*fifo_status)(struct usb_ep *);
        void (*fifo_flush)(struct usb_ep *);
    }


    2.android.c提供用户设置的功能

    android_dev**functions指向该系统能支持的所有功能,而

    Listhead指向所有当前使能的功能;

    android_usb_function是怎样加入到usb_configuration中的那?

    usb_configuation中的成员为usb_function.

    composite/function数据结构间的关系


    根据用户需要的功能设置android_dev, 进而得到 usb_composite_dev

    crash> android_dev
    struct android_dev {
        struct android_usb_function **functions;
        struct list_head enabled_functions;
        struct usb_composite_dev *cdev;
        struct device *dev;
        bool enabled;
        int disable_depth;
        struct mutex mutex;
        bool connected;
        bool sw_connected;
        struct work_struct work;
    }

     从usb_composite_dev得到所有的 usb_configure, 由struct list_head configs管理:
    crash> usb_composite_dev
    struct usb_composite_dev {
        struct usb_gadget *gadget;
        struct usb_request *req;
        unsigned int bufsiz;
        struct usb_configuration *config;
        unsigned int suspended : 1;
        struct usb_device_descriptor desc;
        struct list_head configs;
        struct usb_composite_driver *driver;
        u8 next_string_id;
        u8 manufacturer_override;
        u8 product_override;
        u8 serial_override;
        unsigned int deactivations;
        int delayed_status;
        spinlock_t lock;
    }

    usb_configuration使用struct list_head functions管理所有的usb_function,注意其中的

    struct list_head list是为了接收usb_configuration所在链表的管理。

    crash> usb_configuration
    struct usb_configuration {
        const char *label;
        struct usb_gadget_strings **strings;
        const struct usb_descriptor_header **descriptors;
        void (*unbind)(struct usb_configuration *);
        int (*setup)(struct usb_configuration *, const struct usb_ctrlrequest *);
        u8 bConfigurationValue;
        u8 iConfiguration;
        u8 bmAttributes;
        u8 bMaxPower;
        struct usb_composite_dev *cdev;
        struct list_head list;
        struct list_head functions;
        u8 next_interface_id;
        unsigned int superspeed : 1;
        unsigned int highspeed : 1;
        unsigned int fullspeed : 1;
        struct usb_function *interface[16];
    }

    struct list_head list是为了接收usb_function所在链表的管理。
    crash> usb_function
    struct usb_function {
        const char *name;struct list_head list;
        struct usb_gadget_strings **strings;
        struct usb_descriptor_header **descriptors;
        struct usb_descriptor_header **hs_descriptors;
        struct usb_descriptor_header **ss_descriptors;
        struct usb_configuration *config;
        int (*bind)(struct usb_configuration *, struct usb_function *);
        void (*unbind)(struct usb_configuration *, struct usb_function *);
        int (*set_alt)(struct usb_function *, unsigned int, unsigned int);
        int (*get_alt)(struct usb_function *, unsigned int);
        void (*disable)(struct usb_function *);
        int (*setup)(struct usb_function *, const struct usb_ctrlrequest *);
        void (*suspend)(struct usb_function *);
        void (*resume)(struct usb_function *);
        int (*get_status)(struct usb_function *);
        int (*func_suspend)(struct usb_function *, u8);
        struct list_head list;
        unsigned long endpoints[1];
    }


    3. composite.c

    Composite框架要向外提供两类接口:

    或者说提供这两点的通用性.

    1]用户定义具体的功能;

    2]具体的USBdevice controller


    数据结构上看:usb_composite_dev包含在上层提供具体功能的数据结构

    android_dev中,usb_composite_dev包含了controller具体的usb_gadget

    的成员;

    usb_composite_dev中包含了指向所有usb_configurationlinkhead,

    usb_configuration中包含了指向说有usb_functionlinkhead.


    这里的数据结构的层次,体现了USB的描述的层次关系,注意usb_function

    并没有指向usb_ep的指针。

    4.android.c文件中init函数为线索,看usbgadget driver的初始化过程:


    1.所有的usbdevice都会处理setuppacket。函数composite.c提供了一个common

    usb_gadget_driver: composite_driver,用户定义的function可能增加一些处理;


    2.android.c文件中提供全局变量

    提供了usb_composite_driver , usb_gadget_driver and usb_configure类型的全局变量

    drivers/usb/gadget/android.c

    struct usb_composite_driver

    android_usb_driver = {

        .name        = "android_usb",
        .dev        = &device_desc,
        .strings    = dev_strings,
        .unbind        = android_usb_unbind,
        .max_speed    = USB_SPEED_HIGH,
    };


    static struct usb_configuration

    android_config_driver = {
        .label        = "android",
        .unbind        = android_unbind_config,
        .bConfigurationValue = 1,
        .bmAttributes    = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
        .bMaxPower    = 0xFA, /* 500ma */
    };

    drivers/usb/gadget/composite.c

    static struct usb_gadget_driver

    composite_driver = {

        .unbind        = composite_unbind,

        .setup        = composite_setup,
        .disconnect    = composite_disconnect,

        .suspend    = composite_suspend,
        .resume        = composite_resume,

        .driver    = {
            .owner        = THIS_MODULE,
        },
    };


    3.调用函数usb_composite_probe(&android_usb_driver,android_bind);把上层android.c

    的信息usb_composite_driver类型的android_usb_driver如何绑定 usb_composite_dev

    的函数android_bind 传递到composite.c.


    4.usb_composite_probe ->

    usb_gadget_probe_driver(&composite_driver,composite_bind);

    调用定义在udc-core.c中的函数usb_gadget_probe_driver,把定义在composite.c中的

    usb_gadget_driver类型的composite_driver 和如何绑定usb_gadget的函数composite_bind传递到udc-core.c;


    5.usb_gadget_probe_driverudc_list中得到通过usb_add_gadget_udc注册的usb_udc,

    usb_udc得到usb_gadget,进而调用composite_bind绑定 usb_gadget;


    6.composite_bind(usb_gadget)

    a.创建了核心usb_composite_dev;

    b.调用USBgadget API (就是Endpointops and gadget ops的函数指针封装)处理EP0

    c.调用函数android_bind绑定创建并适当初始化的usb_composite_dev和上层功能配置;


    7.android_bind主要调用了函数android_init_functions(android_usb_function,usb_composite_dev);

    android_init_functions调用所有支持的android_usb_functioninit函数,该函数处理和function

    体相关的初始化;

    8.init函数到此就执行完了.


    1]

    android.c 提供输入参数android_usb_driver and android_bind

    struct usb_composite_driver

    android_usb_driver = {

        .name        = "android_usb",
        .dev        = &device_desc,
        .strings    = dev_strings,
        .unbind        = android_usb_unbind,
        .max_speed    = USB_SPEED_HIGH,
    };

     and

    int android_bind(struct usb_composite_dev *cdev);

    1.1] android.c 然后调用定义在文件 composite.c中的函数

    usb_composite_probe(&android_usb_driver, android_bind);


    2] composite.c会提供输入参数struct usb_gadget_driver composite_driver 和如何绑定 usb_gadget到usb_composite_dev的方法

    composite_bind(struct usb_gadget *gadget)。

    2.1] composite.c然后调用定义在udc-core.c文件中的函数usb_gadget_probe_driver。


    3] 函数usg_gadget_probe_driver从已经注册的udc中得到对应的udc,对udc赋值,并

    3.1] 调用composite.c传入的参数composite_bind绑定usb_gadget[udc->usb_gadget]到composite_dev.


    4] composite.c实现了函数composite_bind,composite创建了usb_composite_dev, 然后调用了实现在 android.c文件中的函数android_bind。

     这个init过程包含两部分:

     上层提过输出参数和回调函数先下调用: android.c/ composite.c/ udc-core.c

     然后根据回调函数从udc-core.c/composite.c/android.c向上回调。



    5.到现在为止,当USBhost发送setuppacketgetconfigure descriptor,怎么上报端点描述符?

    端点和接口是怎样绑定的?


    我们先来看,USBfunction是怎样设置的?

    上层调用sys属性文件function_store->android_enable_function添加android_usb_function

    android_dev:enable_list指向的linklist;


    又是如何enableUSB function的那?

    enable_store->android_enable(android_dev) ->

    usb_add_config(cdev,&android_config_driver,android_bind_config);

    usb_configre加入到usb_composite_dev成员configure_listhead指向的list中,

    调用函数android_bind_config绑定enabledandroid_usb_functionusb_configure

    其中会调用具体android_usb_function相关的bind_config.


    到此,usb_endpoint绑定到usb_interface.


    /*调用函数usb_add_config,add了定义在android.c文件中的usb_configuration。又是如何创建usb_function的那?*/

    /*usb_add_config调用了来自android.c的函数android_bind_config得到使用android_usb_function
     *描述的功能,调用定义在具体功能的函数如acm_bind_config(struct usb_configuration *c, u8 port_num)
     *最后调用函数int usb_add_function(struct usb_configuration *config,struct usb_function *function)
     *关联usb_function 到usb_configuration.
     *又是哪里关联usb_endpoint到usb_function的哪?
     **/

    /*在函数usb_add_function中关联了usb_function和usb_endpoint;
     *调用了具体功能的bind函数如acm_bind
     **/


    一个具体的过程:

    usb_add_config(cdev,&android_config_driver,android_bind_config);

    ->android_bind_config

       ->android_bind_enabled_functions

         ->android_usb_function: bind_config(android_usb_function,usb_configuration);

         ->usb_add_function(struct usb_configuration *config,struct usb_function*function)

            ->usb_function:(*bind)(struct usb_configuration *,structusb_function *);


  • 相关阅读:
    求相同号码一天内的上网流量——mapreduce
    scala初学
    对web日志文件实现按照人员、行为分类
    08 ROS阶段总结——package.xml 和 CMakeLists.txt 详细解读
    06 ROS中的节点、话题和服务
    07 ROS 的常见消息类型
    01 ROS下的三维点云数据处理(一)点云数据来源
    01 Opencv系列(一)ROS和opencv图像数据的转换
    01 ROS的运行架构——环境变量和工作空间
    02 Opencv系列(二)ROS框架下的摄像头调用方法
  • 原文地址:https://www.cnblogs.com/ztguang/p/12645277.html
Copyright © 2011-2022 走看看