0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

linux-usb子系統(tǒng)的核心描述

嵌入式小生 ? 來(lái)源:嵌入式小生 ? 2023-01-14 09:37 ? 次閱讀

一、導(dǎo)讀

本文將描述linux-usb子系統(tǒng)的核心,主要分析其核心的初始化流程,文中源碼基于內(nèi)核版本:4.1.15。

linux usb子系統(tǒng)框架的核心位于/drivers/usb/core/目錄中,文件結(jié)構(gòu)如下圖所示:

ad39d590-93a3-11ed-bfe3-dac502259ad0.png

目錄中各文件功能大致如下:

ad63df16-93a3-11ed-bfe3-dac502259ad0.png

二、USB核心的初始化

在linux內(nèi)核的啟動(dòng)階段USB模塊最早輸出日志信息如下:

(1)[0.475284]usbcore:registerednewinterfacedriverusbfs
(2)[0.475348]usbcore:registerednewinterfacedriverhub
(3)[0.475400]usbcore:registerednewdevicedriverusb

從上述輸出日志可知:第(1)行表示成功注冊(cè)USB文件系統(tǒng),且在系統(tǒng)正常啟動(dòng)后,會(huì)生成對(duì)應(yīng)的/sys/bus/usb/目錄。第(2)行表示成功注冊(cè)USB HUB驅(qū)動(dòng)。第(3)行表明成功注冊(cè)USB通用設(shè)備驅(qū)動(dòng),即usb_generic_driver。通常USB設(shè)備都是以設(shè)備的身份先與usb_generic_driver匹配,匹配成功后,會(huì)分裂出接口,當(dāng)對(duì)接口調(diào)用 device_add()后,會(huì)觸發(fā)USB接口和USB驅(qū)動(dòng)的匹配。

USB核心由/drivers/usb/core/usb.c文件描述。該文件以linux內(nèi)核模塊的方式設(shè)計(jì),使用subsys_initcall(usb_init);將usb核心模塊導(dǎo)出。其中,usb核心的初始化由usb_init()完成,實(shí)現(xiàn)如下:

staticint__initusb_init(void)
{
intretval;
if(usb_disabled()){
pr_info("%s:USBsupportdisabled
",usbcore_name);
return0;
}
usb_init_pool_max();//初始化pool_max參數(shù)

usb_debugfs_init();//初始化usb的調(diào)試文件系統(tǒng)debugfs

usb_acpi_register();//初始化acpi
retval=bus_register(&usb_bus_type);//向linux內(nèi)核注冊(cè)u(píng)sb總線類型
if(retval)
gotobus_register_failed;
//注冊(cè)u(píng)sb通知器
retval=bus_register_notifier(&usb_bus_type,&usb_bus_nb);
if(retval)
gotobus_notifier_failed;
//usb設(shè)備號(hào)初始化
retval=usb_major_init();
if(retval)
gotomajor_init_failed;
//注冊(cè)u(píng)sbfs驅(qū)動(dòng)程序
retval=usb_register(&usbfs_driver);
if(retval)
gotodriver_register_failed;
//初始化usb的devio
retval=usb_devio_init();
if(retval)
gotousb_devio_init_failed;
//初始化usb的hub
retval=usb_hub_init();
if(retval)
gotohub_init_failed;
//注冊(cè)通用usb設(shè)備驅(qū)動(dòng)
retval=usb_register_device_driver(&usb_generic_driver,THIS_MODULE);
if(!retval)
gotoout;

usb_hub_cleanup();
hub_init_failed:
usb_devio_cleanup();
usb_devio_init_failed:
usb_deregister(&usbfs_driver);
driver_register_failed:
usb_major_cleanup();
major_init_failed:
bus_unregister_notifier(&usb_bus_type,&usb_bus_nb);
bus_notifier_failed:
bus_unregister(&usb_bus_type);
bus_register_failed:
usb_acpi_unregister();
usb_debugfs_cleanup();
out:
returnretval;
}

從上述代碼可見(jiàn),usb_init()中執(zhí)行了如下操作:

(1)判斷l(xiāng)inux內(nèi)核是否開(kāi)啟了對(duì)USB的支持,如果不支持則直接返回。

(2)初始化調(diào)試文件系統(tǒng)關(guān)于usb的目錄和文件:

staticintusb_debugfs_init(void)
{
//創(chuàng)建usb目錄
usb_debug_root=debugfs_create_dir("usb",NULL);
if(!usb_debug_root)
return-ENOENT;
//在usb目錄下創(chuàng)建devices文件
usb_debug_devices=debugfs_create_file("devices",0444,
usb_debug_root,NULL,
&usbfs_devices_fops);
if(!usb_debug_devices)
{
debugfs_remove(usb_debug_root);
usb_debug_root=NULL;
return-ENOENT;
}

return0;
}

(3)初始化usb與acpi相關(guān)的參數(shù):

ad8a6500-93a3-11ed-bfe3-dac502259ad0.png

(4)向linux內(nèi)核注冊(cè)u(píng)sb總線類型,usb總線類型定義如下:

structbus_typeusb_bus_type={
.name="usb",
.match=usb_device_match,
.uevent=usb_uevent,
};

(5)注冊(cè)u(píng)sb總線通知器

(6)初始化usb主設(shè)備號(hào):

intusb_major_init(void)
{
interror;
//注冊(cè)u(píng)sb字符設(shè)備
error=register_chrdev(USB_MAJOR,"usb",&usb_fops);
if(error)
printk(KERN_ERR"Unabletogetmajor%dforusbdevices
",
USB_MAJOR);

returnerror;
}

(7)注冊(cè)u(píng)sbfs驅(qū)動(dòng)程序,usbfs以u(píng)sb驅(qū)動(dòng)程序的形式進(jìn)行定義:

structusb_driverusbfs_driver={
.name="usbfs",
.probe=driver_probe,
.disconnect=driver_disconnect,
.suspend=driver_suspend,
.resume=driver_resume,
};

(8)初始化usb的devio,實(shí)質(zhì)上是初始化USB字符設(shè)備,devio用于USB設(shè)備與用戶空間進(jìn)行通信

int__initusb_devio_init(void)
{
intretval;

retval=register_chrdev_region(USB_DEVICE_DEV,USB_DEVICE_MAX,
"usb_device");
if(retval){
printk(KERN_ERR"Unabletoregisterminorsforusb_device
");
gotoout;
}
cdev_init(&usb_device_cdev,&usbdev_file_operations);
retval=cdev_add(&usb_device_cdev,USB_DEVICE_DEV,USB_DEVICE_MAX);
if(retval){
printk(KERN_ERR"Unabletogetusb_devicemajor%d
",
USB_DEVICE_MAJOR);
gotoerror_cdev;
}
//注冊(cè)u(píng)sbdev_nb通知器
usb_register_notify(&usbdev_nb);
out:
returnretval;

error_cdev:
unregister_chrdev_region(USB_DEVICE_DEV,USB_DEVICE_MAX);
gotoout;
}

(9)初始化usb的hub,hub也是以USB驅(qū)動(dòng)方式進(jìn)行設(shè)計(jì)(/drivers/usb/core/hub.c):

staticstructusb_driverhub_driver={
.name="hub",
.probe=hub_probe,
.disconnect=hub_disconnect,
.suspend=hub_suspend,
.resume=hub_resume,
.reset_resume=hub_reset_resume,
.pre_reset=hub_pre_reset,
.post_reset=hub_post_reset,
.unlocked_ioctl=hub_ioctl,
.id_table=hub_id_table,
.supports_autosuspend=1,
};

intusb_hub_init(void)
{
if(usb_register(&hub_driver)

(10)注冊(cè)通用usb設(shè)備驅(qū)動(dòng)usb_generic_driver,定義如下(/drivers/usb/core/generic.c):

structusb_device_driverusb_generic_driver={
.name="usb",
.probe=generic_probe,
.disconnect=generic_disconnect,
#ifdefCONFIG_PM
.suspend=generic_suspend,
.resume=generic_resume,
#endif
.supports_autosuspend=1,
};

?從前文描述可知:在linux啟動(dòng)過(guò)程中或者是在插入U(xiǎn)SB設(shè)備后,通常USB設(shè)備都是以設(shè)備的身份先與usb_generic_driver匹配,這時(shí)候由.probe指向的generic_peobe()會(huì)執(zhí)行,當(dāng)匹配成功后,會(huì)分裂出接口,當(dāng)對(duì)接口調(diào)用device_add()后,會(huì)觸發(fā)USB接口和USB接口驅(qū)動(dòng)的匹配。

generic_probe()函數(shù)實(shí)現(xiàn)如下:

staticintgeneric_probe(structusb_device*udev)
{
interr,c;

/*Chooseandsettheconfiguration.Thisregisterstheinterfaces
*withthedrivercoreandletsinterfacedriversbindtothem.
*/
if(udev->authorized==0)
dev_err(&udev->dev,"Deviceisnotauthorizedforusage
");
else{
//選擇配置
c=usb_choose_configuration(udev);
if(c>=0){
//設(shè)置配置
err=usb_set_configuration(udev,c);
if(err&&err!=-ENODEV){
dev_err(&udev->dev,"can'tsetconfig#%d,error%d
",
c,err);
/*Thisneednotbefatal.Theusercantryto
*setotherconfigurations.*/
}
}
}
/*USBdevicestate==configured...usable*/
usb_notify_add_device(udev);//通知usb設(shè)備添加,對(duì)應(yīng)注冊(cè)的回調(diào)函數(shù)會(huì)被執(zhí)行。

return0;
}

三、總結(jié)

本文主要描述linux-usb核心的初始化,usb核心是usb子系統(tǒng)的內(nèi)層,其他的usb模塊都基于這個(gè)內(nèi)層再設(shè)計(jì)。除此之外,著重描述了usb_init()函數(shù)的具體執(zhí)行步驟,如下圖所示:

ada72064-93a3-11ed-bfe3-dac502259ad0.jpg





審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • USB接口
    +關(guān)注

    關(guān)注

    9

    文章

    701

    瀏覽量

    55652
  • ACPI
    +關(guān)注

    關(guān)注

    1

    文章

    11

    瀏覽量

    8956
  • LINUX內(nèi)核
    +關(guān)注

    關(guān)注

    1

    文章

    316

    瀏覽量

    21651

原文標(biāo)題:Linux-USB驅(qū)動(dòng)框架 | usb核心

文章出處:【微信號(hào):嵌入式小生,微信公眾號(hào):嵌入式小生】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    關(guān)于Linux設(shè)備驅(qū)動(dòng)中input子系統(tǒng)的介紹

    對(duì)于輸入類設(shè)備如鍵盤、鼠標(biāo)、觸摸屏之類的Linux驅(qū)動(dòng),內(nèi)核提供input子系統(tǒng),使得這類設(shè)備的處理變得非常便捷??傮w上來(lái)講,input子系統(tǒng)由三部分組成: 事件驅(qū)動(dòng)input核心設(shè)備
    發(fā)表于 01-09 16:06 ?2705次閱讀

    Linux下輸入子系統(tǒng)上報(bào)觸摸屏坐標(biāo)

    ??在 Linux 中,輸入子系統(tǒng)是由輸入子系統(tǒng)設(shè)備驅(qū)動(dòng)層、輸入子系統(tǒng)核心層(Input Core)和輸入
    的頭像 發(fā)表于 09-25 08:56 ?2500次閱讀
    <b class='flag-5'>Linux</b>下輸入<b class='flag-5'>子系統(tǒng)</b>上報(bào)觸摸屏坐標(biāo)

    Linux LED子系統(tǒng)詳解

    Linux LED子系統(tǒng)詳解
    的頭像 發(fā)表于 06-10 10:37 ?1554次閱讀
    <b class='flag-5'>Linux</b> LED<b class='flag-5'>子系統(tǒng)</b>詳解

    嵌入式技術(shù):Linux驅(qū)動(dòng)USB必須了解的四個(gè)描述

    module_init,只不過(guò)因?yàn)檫@部分代碼是核心,開(kāi)發(fā)者通常把它看作一個(gè)子系統(tǒng),而不僅僅是一個(gè)模塊。因?yàn)?b class='flag-5'>USB core模塊代表的不是某一個(gè)設(shè)備,而是所有USB設(shè)備賴以生存的模塊。因
    發(fā)表于 05-09 09:06

    輸入子系統(tǒng)的作用與框架

    了一個(gè)底層驅(qū)動(dòng)(成為serio)的集合,支持對(duì)串口和鍵盤控制器等硬件輸入的訪問(wèn)  輸入子系統(tǒng)使得應(yīng)用編程人員和驅(qū)動(dòng)編程人員編程的時(shí)候變得簡(jiǎn)單統(tǒng)一。3、輸入子系統(tǒng)框架linux輸入子系統(tǒng)
    發(fā)表于 10-19 17:13

    基于USB設(shè)備的Linux網(wǎng)絡(luò)驅(qū)動(dòng)程序開(kāi)發(fā)

    介紹Linux 的體系結(jié)構(gòu)及其網(wǎng)絡(luò)子系統(tǒng),并結(jié)合USB 設(shè)備在Linux 下的訪問(wèn)機(jī)制,給出了一種USB 網(wǎng)絡(luò)驅(qū)動(dòng)程序的設(shè)計(jì)方法。該設(shè)計(jì)方法
    發(fā)表于 08-11 11:23 ?20次下載

    基于Linux內(nèi)核輸入子系統(tǒng)的驅(qū)動(dòng)研究

    Linux因其完全開(kāi)放的特性和穩(wěn)定優(yōu)良的性能深受歡迎,當(dāng)推出了內(nèi)核輸入子系統(tǒng)后,更方便了嵌入式領(lǐng)域的驅(qū)動(dòng)開(kāi)放。介紹了Linux的設(shè)備驅(qū)動(dòng)基礎(chǔ),詳細(xì)闡述了基于Linux內(nèi)核輸入
    發(fā)表于 09-12 16:38 ?23次下載

    Linux內(nèi)核輸入子系統(tǒng)的驅(qū)動(dòng)研究

    Linux內(nèi)核輸入子系統(tǒng)的驅(qū)動(dòng)研究
    發(fā)表于 10-31 14:41 ?14次下載
    <b class='flag-5'>Linux</b>內(nèi)核輸入<b class='flag-5'>子系統(tǒng)</b>的驅(qū)動(dòng)研究

    Linux usb子系統(tǒng)子系統(tǒng)架構(gòu)

    USB 分為主從兩大體系,一般而言, PC 中的 USB 系統(tǒng)就是作主,而一般的 USB 鼠標(biāo), U 盤則是典型的 USB
    發(fā)表于 05-07 10:35 ?1323次閱讀

    詳細(xì)了解Linux設(shè)備模型中的input子系統(tǒng)

    linux輸入子系統(tǒng)linux input subsystem)從上到下由三層實(shí)現(xiàn),分別為:輸入子系統(tǒng)事件處理層(EventHandler)、輸入
    發(fā)表于 05-12 09:04 ?1052次閱讀
    詳細(xì)了解<b class='flag-5'>Linux</b>設(shè)備模型中的input<b class='flag-5'>子系統(tǒng)</b>

    Windows 子系統(tǒng)助力 Linux 2.0

    Windows 子系統(tǒng)助力 Linux 2.0
    的頭像 發(fā)表于 01-04 11:17 ?656次閱讀

    從軟件角度分析linux內(nèi)核USB子系統(tǒng)的熱插拔過(guò)程

    本文從軟件角度分析linux內(nèi)核USB子系統(tǒng)的熱插拔過(guò)程,以實(shí)際分析思路和過(guò)程行文,基于linux內(nèi)核版本:4.19.4,記錄分析USB
    的頭像 發(fā)表于 01-15 09:28 ?5650次閱讀

    Linux中內(nèi)存管理子系統(tǒng)開(kāi)發(fā)必知的3個(gè)結(jié)構(gòu)概念

    Linux中內(nèi)存管理子系統(tǒng)使用節(jié)點(diǎn)(node)、區(qū)域(zone)和頁(yè)(page)三級(jí)結(jié)構(gòu)描述物理內(nèi)存。
    的頭像 發(fā)表于 08-28 09:34 ?900次閱讀
    <b class='flag-5'>Linux</b>中內(nèi)存管理<b class='flag-5'>子系統(tǒng)</b>開(kāi)發(fā)必知的3個(gè)結(jié)構(gòu)概念

    Linux內(nèi)核之LED子系統(tǒng)(二)

    這里說(shuō)一說(shuō)LED子系統(tǒng)的一些核心源代碼文件,是如何實(shí)現(xiàn)LED子系統(tǒng)
    發(fā)表于 10-02 16:55 ?951次閱讀
    <b class='flag-5'>Linux</b>內(nèi)核之LED<b class='flag-5'>子系統(tǒng)</b>(二)

    深度解析linux時(shí)鐘子系統(tǒng)

    linux內(nèi)核中實(shí)現(xiàn)了一個(gè)CLK子系統(tǒng),用于對(duì)上層提供各模塊(例如需要時(shí)鐘信號(hào)的外設(shè),USB等)的時(shí)鐘驅(qū)動(dòng)接口,對(duì)下層提供具體SOC的時(shí)鐘操作細(xì)節(jié)。
    的頭像 發(fā)表于 09-29 16:46 ?469次閱讀
    深度解析<b class='flag-5'>linux</b>時(shí)鐘<b class='flag-5'>子系統(tǒng)</b>