ALSA
+ -

UAC1数据结构关系由f_audio_bind函数引出的struct f_uac1_opts和struct f_uac1之间的联系解读

2022-06-12 376 1

前面看到了分别通过f_audio_alloc_inst和f_audio_alloc函数申请struct f_uac1_opts和struct f_uac1结构体,而我们在看UAC1源代码的时候,就需要这些结构体之间进行转换。

首先我们先看struct f_uac1_opts和struct f_uac1之间的联系。由于我们在前面一切并未再展开结构体来讲,所以从草较来看struct f_uac1_opts和struct f_uac1好像没有关系。不过我们在看f_audio_bind函数时,有这么一句话:

static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
{
    struct f_uac1_opts* audio_opts;
    ...
    audio_opts = container_of(f->fi, struct f_uac1_opts, func_inst)= container_of(f->fi, struct f_uac1_opts, func_inst);
}

可以看到,实现了从usb_function(struct f_uac1)到struct f_uac1_opts之间的转换。它们之间的联系竟然是struct usb_function func,所以我们需要深入地分析,并再次完善这个草图。
先看struct usb_function结构体。

struct usb_function {
    const char            *name;
    struct usb_gadget_strings    **strings;
    struct usb_descriptor_header    **fs_descriptors;
    struct usb_descriptor_header    **hs_descriptors;
    struct usb_descriptor_header    **ss_descriptors;
    struct usb_descriptor_header    **ssp_descriptors;

    struct usb_configuration    *config;

    struct usb_os_desc_table    *os_desc_table;
    unsigned            os_desc_n;

    /* REVISIT:  bind() functions can be marked __init, which
     * makes trouble for section mismatch analysis.  See if
     * we can't restructure things to avoid mismatching.
     * Related:  unbind() may kfree() but bind() won't...
     */

    /* configuration management:  bind/unbind */
    int            (*bind)(struct usb_configuration *,
                    struct usb_function *);
    void            (*unbind)(struct usb_configuration *,
                    struct usb_function *);
    void            (*free_func)(struct usb_function *f);
    struct module        *mod;

    /* runtime state management */
    int            (*set_alt)(struct usb_function *,
                    unsigned interface, unsigned alt);
    int            (*get_alt)(struct usb_function *,
                    unsigned interface);
    void            (*disable)(struct usb_function *);
    int            (*setup)(struct usb_function *,
                    const struct usb_ctrlrequest *);
    bool            (*req_match)(struct usb_function *,
                    const struct usb_ctrlrequest *,
                    bool config0);
    void            (*suspend)(struct usb_function *);
    void            (*resume)(struct usb_function *);

    /* USB 3.0 additions */
    int            (*get_status)(struct usb_function *);
    int            (*func_suspend)(struct usb_function *,
                        u8 suspend_opt);
    /* private: */
    /* internals */
    struct list_head        list;
    DECLARE_BITMAP(endpoints, 32);
    const struct usb_function_instance *fi;

    unsigned int        bind_deactivated:1;
};

注意倒数第二个成员:

const struct usb_function_instance *fi;

可以看到,里面有了指示usb_function_instance的指针。
所以我们完善后的图如下:
struct f_uac1_opts和struct f_uac1之间的联系

图片,可以右键在新窗口打开放大。

所以对于任何的入口函数,由于传入的指针为struct usb_function *f,故:

  • 当知道了struct usb_function *f,其也就是struct g_audio的指针,也是struct f_uac1的指针。
  • 同样当我们需要获取struct f_uac1_opts指针时,只需要先通过usb_function的成员fi获取struct usb_function_instance的指针,而该指针其实也是struct f_uac1_opts的提针。
    所以上面从struct usb_function指针指化为struct f_uac1_opts指针时,代码就很简单:
    audio_opts = container_of(f->fi, struct f_uac1_opts, func_inst);
    

而至于它们之间的关联,是通过usb_get_function函数实现的。

struct usb_function *usb_get_function(struct usb_function_instance *fi)
{
    struct usb_function *f;

    f = fi->fd->alloc_func(fi);
    if (IS_ERR(f))
        return f;
    f->fi = fi;
    return f;
}
EXPORT_SYMBOL_GPL(usb_get_function);

这里先调用alloc_func指针,也就是我们在驱动入口指针的函数指针f_audio_alloc,该返回返回usb_function的指针,这时将其成员fi与usb_function_instance关联。

题外话,LINUX复杂的数据结构指针会让人头晕,不过我们在看代码时,需要梳理出它们之间的数据结构关系,再结合各函数调用流程来理解LINUX驱动源代码。这也帮助我们理解LINUX内核数据结构的组保方式,同时也能提高我们自己代码数据的设计能力。

HID人机交互QQ群:564808376    UAC音频QQ群:218581009    UVC相机QQ群:331552032    BOT&UASP大容量存储QQ群:258159197    STC-USB单片机QQ群:315457461    USB技术交流QQ群2:580684376    USB技术交流QQ群:952873936   

0 篇笔记 写笔记

ALSA框架UAC1驱动程序入口宏DECLARE_USB_FUNCTION分析
题外话:为了学习看LINUX驱动,我也是拼了。对于LINUX源代码,虽然以前了解过LINUX的字符串驱动,不过突然跳到一个复杂的LINUX设备驱动,还是有点迷茫,自己什么不会。不过还是要狠下心来,像看了7天的UVC规范一样,强行让自己翻译。自己看的Linux UAC源代码位于https://eli......
UAC1数据结构关系由f_audio_bind函数引出的struct f_uac1_opts和struct f_uac1之间的联系解读
前面看到了分别通过f_audio_alloc_inst和f_audio_alloc函数申请struct f_uac1_opts和struct f_uac1结构体,而我们在看UAC1源代码的时候,就需要这些结构体之间进行转换。首先我们先看struct f_uac1_opts和struct f_uac......
关注公众号
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

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

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