Linux USB驱动源代码分析
+ -

fusb300_udc

2025-08-13 0 0

usb\gadget\udc

fusb300_udc是平台设备驱动程序

static struct platform_driver fusb300_driver = {
    .remove =    fusb300_remove,
    .driver        = {
        .name =    (char *) udc_name,
    },
};
module_platform_driver_probe(fusb300_driver, fusb300_probe);

module_platform_driver_probe展开

static int __init fusb300_driver_init(void) 
{ 
    return platform_driver_probe(&(fusb300_driver),fusb300_probe);    
} 
module_init(fusb300_driver_init); 
static void __exit fusb300_driver_exit(void) 
{ 
    platform_driver_unregister(&(fusb300_driver)); 
} 
module_exit(fusb300_driver_exit);

其probe函数为fusb300_probe

struct usb_gadget_ops {
    int    (*get_frame)(struct usb_gadget *);
    int    (*wakeup)(struct usb_gadget *);
    int    (*set_selfpowered) (struct usb_gadget *, int is_selfpowered);
    int    (*vbus_session) (struct usb_gadget *, int is_active);
    int    (*vbus_draw) (struct usb_gadget *, unsigned mA);
    int    (*pullup) (struct usb_gadget *, int is_on);
    int    (*ioctl)(struct usb_gadget *,unsigned code, unsigned long param);
    void (*get_config_params)(struct usb_gadget *, struct usb_dcd_config_params *);
    int    (*udc_start)(struct usb_gadget *,struct usb_gadget_driver *);
    int    (*udc_stop)(struct usb_gadget *);
    void (*udc_set_speed)(struct usb_gadget *, enum usb_device_speed);
    struct usb_ep *(*match_ep)(struct usb_gadget *,    struct usb_endpoint_descriptor *,struct usb_ss_ep_comp_descriptor *);
};

udc设备结构体为fusb300

struct fusb300 {
    spinlock_t        lock;
    void __iomem        *reg;

    unsigned long        irq_trigger;

    struct usb_gadget        gadget;//fusb300_probe中初始化
    struct usb_gadget_driver    *driver;//start回调时绑定

    struct fusb300_ep    *ep[FUSB300_MAX_NUM_EP];

    struct usb_request    *ep0_req;    /* for internal request */
    __le16            ep0_data;
    u32            ep0_length;    /* for internal request */
    u8            ep0_dir;    /* 0/0x80  out/in */

    u8            fifo_entry_num;    /* next start fifo entry */
    u32            addrofs;    /* next fifo address offset */
    u8            reenum;        /* if re-enumeration */
};

static const struct usb_gadget_ops fusb300_gadget_ops = {
    .pullup        = fusb300_udc_pullup,
    .udc_start    = fusb300_udc_start,
    .udc_stop    = fusb300_udc_stop,
};

其初始化usb_gadget设备

static int fusb300_probe(struct platform_device *pdev)
{
    struct fusb300 *fusb300 = NULL;
    ...
    fusb300 = kzalloc(sizeof(struct fusb300), GFP_KERNEL);
    platform_set_drvdata(pdev, fusb300);//平台设备的私有数据

    fusb300->gadget.ops = &fusb300_gadget_ops;//gadget实质是udc的代表
    fusb300->gadget.max_speed = USB_SPEED_HIGH;
    fusb300->gadget.name = udc_name;//"fusb300_udc"
    fusb300->reg = reg;
    ...
    init_controller(fusb300);
    ret = usb_add_gadget_udc(&pdev->dev, &fusb300->gadget); //注册 UDC 设备对象 到系统,实质是创建usb_udc
    ...
}

usb_add_gadget_udc中创建udc设备,并将其设备挂入udc_list中

struct usb_udc {
    struct usb_gadget_driver    *driver;
    struct usb_gadget        *gadget;
    struct device            dev;
    struct list_head        list;
    bool                vbus;
};
int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
        void (*release)(struct device *dev))
{
    struct usb_udc    * udc;
    ...
    udc = kzalloc(sizeof(*udc), GFP_KERNEL);
    device_initialize(&udc->dev);
    udc->dev.release = usb_udc_release;
    udc->dev.class = udc_class;
    udc->dev.groups = usb_udc_attr_groups;
    udc->dev.parent = parent;

    ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));

    ret = device_add(&gadget->dev);
    udc->gadget = gadget;
    gadget->udc = udc;
    list_add_tail(&udc->list, &udc_list);  //udc_list global list
    ret = device_add(&udc->dev);
    usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
    udc->vbus = true;

    /* pick up one of pending gadget drivers */
    ret = check_pending_gadget_drivers(udc);
    ...
}

check_pending_gadget_drivers则是通过gadget_driver_pending_list中找到名称匹配的进行绑定

static int check_pending_gadget_drivers(struct usb_udc *udc)
{
    struct usb_gadget_driver *driver;
    int ret = 0;

    list_for_each_entry(driver, &gadget_driver_pending_list, pending)
        if (!driver->udc_name
        || strcmp(driver->udc_name,    dev_name(&udc->dev)) == 0) 
        {
            ret = udc_bind_to_driver(udc, driver);
            if (ret != -EPROBE_DEFER)
                list_del_init(&driver->pending);
            break;
        }

    return ret;
}

而gadget_driver_pending_list中的成员来自于 usb_gadget_probe_driver函数的注册。

static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
{
    int ret;

    dev_dbg(&udc->dev, "registering UDC driver [%s]\n",
            driver->function);

    udc->driver = driver;
    udc->dev.driver = &driver->driver;
    udc->gadget->dev.driver = &driver->driver;

    usb_gadget_udc_set_speed(udc, driver->max_speed);

    //调用usb_gadget_driver的bind
    ret = driver->bind(udc->gadget, driver);
    if (ret)
        goto err1;
    ret = usb_gadget_udc_start(udc);
    if (ret) {
        driver->unbind(udc->gadget);
        goto err1;
    }
    usb_udc_connect_control(udc);

    kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
    return 0;
err1:
    if (ret != -EISNAM)
        dev_err(&udc->dev, "failed to start %s: %d\n",
            udc->driver->function, ret);
    udc->driver = NULL;
    udc->dev.driver = NULL;
    udc->gadget->dev.driver = NULL;
    return ret;
}

usb_gadget_udc_start为初始化usb_udc,即调用fusb300_udc_start

static inline int usb_gadget_udc_start(struct usb_udc *udc)
{
//fusb300_udc_start
    return udc->gadget->ops->udc_start(udc->gadget, udc->driver);
}

fusb300的成员driver

static int fusb300_udc_start(struct usb_gadget *g,
        struct usb_gadget_driver *driver)
{
    struct fusb300 *fusb300 = to_fusb300(g);

    /* hook up the driver */
    driver->driver.bus = NULL;
    fusb300->driver = driver;

    return 0;
}

udc_list

udc_list是一个全局变量

struct list_head {
    struct list_head *next, *prev;
};

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
    struct list_head name = LIST_HEAD_INIT(name)

static LIST_HEAD(udc_list);

最终图下:
15222831634

0 篇笔记 写笔记

fusb300_udc
usbgadgetudcfusb300_udc是平台设备驱动程序static struct platform_driver fusb300_driver = { .remove = fusb300_remove, .driver = { ......
关注公众号
  • HID人机交互
  • Linux&USB
  • UAC音频
  • CDC
  • TYPE-C
  • USB规范
  • USB大容量存储
  • USB百科
  • USB周边
  • UVC摄像头
  • Windows系统USB
  • 音视频博客
  • 取消
    感谢您的支持,我会继续努力的!
    扫码支持
    扫码打赏,你说多少就多少

    打开支付宝扫一扫,即可进行扫码打赏哦

    您的支持,是我们前进的动力!