ALSA
+ -

ALSA框架UAC1驱动程序入口宏DECLARE_USB_FUNCTION分析

2022-06-11 775 0

题外话:为了学习看LINUX驱动,我也是拼了。对于LINUX源代码,虽然以前了解过LINUX的字符串驱动,不过突然跳到一个复杂的LINUX设备驱动,还是有点迷茫,自己什么不会。不过还是要狠下心来,像看了7天的UVC规范一样,强行让自己翻译。
自己看的Linux UAC源代码位于https://elixir.bootlin.com/linux/v5.5-rc2/source/drivers/usb/gadget/function 目录下。没有访问过的同学可以看一下,个人觉地很不错。主要是和我的习惯一样,全部WEB化,可随时学习。

UAC1源驱动源代码源文件为:function/f_uac1.c 当然,这个目录下也包括一些通用其它的代码,比如UAC2等。

记得LINUX驱动程序的入口一般是通过module_init和module_exit来指定驱动的出入口的。而ALSA驱动程序框架,对其做了一个封装,使用宏 DECLARE_USB_FUNCTION_INIT来实现。

#define DECLARE_USB_FUNCTION_INIT(_name, _inst_alloc, _func_alloc)    \
    DECLARE_USB_FUNCTION(_name, _inst_alloc, _func_alloc)        \
    static int __init _name ## mod_init(void)            \
    {                                \
        return usb_function_register(&_name ## usb_func);    \
    }                                \
    static void __exit _name ## mod_exit(void)            \
    {                                \
        usb_function_unregister(&_name ## usb_func);        \
    }                                \
    module_init(_name ## mod_init);                    \
    module_exit(_name ## mod_exit)

这里使用了C语言的双#连接符号,如我们定义:

define delare(name)    usbzh_##name

那么我们在使用时可以这样

declare(code)

则实际宏展开为:

usbzh_code

所以我们在f_uac1.c的最底部可以看到:

DECLARE_USB_FUNCTION_INIT(uac1, f_audio_alloc_inst, f_audio_alloc);

那展开就是:

DECLARE_USB_FUNCTION(uac1, f_audio_alloc_inst, f_audio_alloc)

static int __init uac1mod_init(void)
{
    return usb_function_register(&uac1usb_func);
}

static void __exit uac1mod_exit(void)
{
    usb_function_unregister(&uac1usb_func);
}
module_init(uac1mod_init);
module_exit(uac1mod_exit)

而DECLARE_USB_FUNCTION也是一个宏,是UAC驱动基本结构体的实例声名:

#define DECLARE_USB_FUNCTION(_name, _inst_alloc, _func_alloc)        \
    static struct usb_function_driver _name ## usb_func = {        \
        .name = __stringify(_name),                \
        .mod  = THIS_MODULE,                    \
        .alloc_inst = _inst_alloc,                \
        .alloc_func = _func_alloc,                \
    };                                \
    MODULE_ALIAS("usbfunc:"__stringify(_name));

则为:

static struct usb_function_driver uac1usb_func = {
        .name = __stringify(uac1),
        .mod  = THIS_MODULE,
        .alloc_inst = f_audio_alloc_inst,
        .alloc_func = f_audio_alloc,
    };
    MODULE_ALIAS("usbfunc:"__stringify(uac1));

这两个宏的定义位于:https://elixir.bootlin.com/linux/v5.5-rc2/source/include/linux/usb/composite.h#L617

可以看到,其最终落到了f_audio_alloc_inst和f_audio_alloc两个函数上。
而以上的宏通过这种嵌套帮助我们方便地指定驱动的名字和两个回调函数,就帮我们实现了UAC驱动程序的总入口。

至于f_audio_alloc_inst和f_audio_alloc这两个函数是干什么的,当前我还不清楚。不过按我们做驱动的经验,这两个函数是系统对该驱动程序的总入口,并且其是通过usb_function_register和usb_function_unregister通过结构体uac1usb_func实现注册传入的。

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......
ALSA框架UAC1函数f_audio_alloc_instf_audio_alloc
前面大概分析到了UAC1的系统级的入口函数f_audio_alloc_instf_audio_alloc。从代码上来看,会先调用usb_function_instance,再是f_audio_alloc。这是因为f_audio_alloc函数中引用了usb_function_instance申请......
关注公众号
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

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

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