USB gadget driver framework

2024-06-03 16:18
文章标签 usb driver framework gadget

本文主要是介绍USB gadget driver framework,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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'\n", 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 *);

  

这篇关于USB gadget driver framework的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1027487

相关文章

Spring Framework系统框架

序号表示的是学习顺序 IoC(控制反转)/DI(依赖注入): ioc:思想上是控制反转,spring提供了一个容器,称为IOC容器,用它来充当IOC思想中的外部。 我的理解就是spring把这些对象集中管理,放在容器中,这个容器就叫Ioc这些对象统称为Bean 用对象的时候不用new,直接外部提供(bean) 当外部的对象有关系的时候,IOC给它俩绑好(DI) DI和IO

Usb Audio Device Descriptor(10) Hid Device

对于 Standard Interface Descriptor, 当 bInterfaceClass=0x03时,即为HID设备。Standard Interface Descriptor如下 struct usb_standard_interface_descriptor{U8 bLength; /*Size of this descriptor in bytes*/U8 bDescrip

Android rk3399 UAC(USB Audio)开发笔记

一、UAC有1.0和2.0,因Windows对2.0支持不好,我使用的是UAC1.0驱动 内核配置:CONFIG_USB_CONFIGFS_F_UAC1          ---这个宏配置无需物理codec,使用虚拟 alsa codec  驱动路径:"kernel\drivers\usb\gadget\function\f_uac1.c" 内核配置:CONFIG_USB_CONFIGFS_

SQLException: No Suitable Driver Found - 完美解决方法详解

🚨 SQLException: No Suitable Driver Found - 完美解决方法详解 🚨 **🚨 SQLException: No Suitable Driver Found - 完美解决方法详解 🚨****摘要 📝****引言 🎯****正文 📚****1. 问题概述 ❗****2. JDBC 驱动程序的工作原理 🔧****3. 错误的根本原因 🕵️**

多款式随身WiFi如何挑选,USB随身WiFi、无线电池随身WiFi、充电宝随身WiFi哪个好?优缺点分析!

市面上的随身WiFi款式多样琳琅满目,最具代表性的就是USB插电款、无线款和充电宝款。今天就来用一篇文章分析一下这三种款式的优缺点。 USB插电款 优点:便宜,无需充电,在有电源的地方可以随时随地插电使用,比如中兴的USB随身WiFi。 缺点:无电源的情况下,无法带出门使用,部分品牌考虑到这个问题,会配备一个充电仓,这个充电仓相对来说就有点累赘了。网速上也不太稳定,波动比较大。

基于FPGA的开源项目:FOC/SHA/USB/JPEG等

文章目录 [1. USB 1.1控制器](https://github.com/WangXuan95/FPGA-USB-Device)[2. FOC控制算法](https://github.com/WangXuan95/FPGA-FOC)[3. BSV高级硬件描述语言入门指南](https://github.com/WangXuan95/BSV_Tutorial_cn)[4. 基于XDMA的

SpringBoot启动报错Failed to determine a suitable driver class

两种解决办法 1.在Application类上加 ` @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) package com.example.demo3;import org.springframework.boot.SpringApplication;import org.springframewo

linux驱动模型 -- bus,device,device_driver之间的关系

Linux 设备驱动模型中,按照层次的组织结构,抽象成总线(struct bus_type),设备(struct device),驱动(struct device_driver)的层次组织形式,这是最原始的抽象结构,在此基础之上,根据不同类型的总线/设备/驱动,有形成了更高层次的组织结构,如 virtio总线(struct bus_type virtio_bus),virtio设备(

JavaBug系列- Failed to load driver class com.mysql.cj.jdbc.Driver in either of HikariConfig class load

JavaBug系列之Mysql驱动问题 Java医生一、关于错误信息二、如何解决问题 Java医生 本系列记录常见Bug,以及诊断过程和原因 Java/一对一零基础辅导/企业项目一对一辅导/日常Bug解决/代码讲解/毕业设计等 V:study_51ctofx 一、关于错误信息 APPLICATION FAILED TO START Description: Fai

java.lang.ClassNotFoundException: com.mysql.jdbc.Driver问题

执行Class.forName(driverName)时报告此异常! Java项目中明明已经添加了MySQL-connector驱动,还是报java.lang.ClassNotFoundException: com.mysql.jdbc.Driver找不到类文件的异常, 排查了很久,原来是从jdbc.properties配置文件中读取的drivername末尾多了一个空格, 这种错误及其隐蔽,