精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

從軟件角度分析linux內核USB子系統的熱插拔過程

嵌入式小生 ? 來源:嵌入式小生 ? 2023-01-15 09:28 ? 次閱讀

本文從軟件角度分析linux內核USB子系統的熱插拔過程,以實際分析思路和過程行文,基于linux內核版本:4.19.4,記錄分析USB子系統時的所得。

導讀

一、USB核心初始化

二、USB設備的枚舉過程

(2-1)USB鼠標插入后日志分析

(2-2)USB鼠標移除/拔下后日志分析

三、 USB host控制器的初始化

四、USB設備插入后的硬件過程

五、USB設備插入后的軟件過程

一、USB核心初始化

如果linux內核開啟了對USB的支持,在內核啟動過程中,首先會對USB核心進行初始化,該過程則會打印出如下日志信息

(1)[ 0.476223] usbcore: registered new interface driver usbfs

(2)[ 0.476286] usbcore: registered new interface driver hub

(3)[ 0.476337] usbcore: registered new device driver usb

上述(1)、(2)兩條信息是調用usb_register_driver()函數時打印出的,從而可以知道在linux內核啟動過程中,usb核心會注冊usbfs、hub接口驅動程序。從內核源碼角度,以上hub接口驅動程序的注冊過程是在usb_init()中調用usb_hub_init()完成的,除此之外還創建了hub_wq工作隊列:

上述第(3)條信息是在usb_init()中調用:

usb_register_device_driver(&usb_generic_driver,THIS_MODULE);

當在成功注冊usb設備驅動后打印出的日志信息。

二、USB設備的枚舉過程

本小節以低速USB鼠標設備插入為例,查看linux內核對USB設備的枚舉過程。

(2-1)USB鼠標插入后日志分析

我們都知道USB支持熱插拔,在linux系統中,這個熱插拔是怎樣的一個過程,本小節將描述這個話題

當USB設備接入系統時(熱插拔探測過程),文本以插入一個USB鼠標為例,則會打印出類似下述的信息:

[ 3122.476846] usb 4-1: new low-speed USB device number 5 using ohci-platform

[ 3122.702408] usb 4-1: New USB device found, idVendor=17ef, idProduct=6019, bcdDevice= 1.00

[ 3122.702503] usb 4-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0

[ 3122.702537] usb 4-1: Product: Lenovo Optical USB Mouse

[ 3122.702568] usb 4-1: Manufacturer: PixArt

[ 3122.713317] input: PixArt Lenovo Optical USB Mouse as /devices/platform/fd8c0000.usb/usb4/4-1/4-1:1.0/00036019.0004/input/input8

[ 3122.771015] hid-generic 00036019.0004: input,hidraw0: USB HID v1.11 Mouse [PixArt Lenovo Optical USB Mouse] on usb-fd8c0000.usb-1/input0

[1058.921] event5 - PixArt Lenovo Optical USB Mouse: is tagged by udev as: Mouse

[1058.923] event5 - PixArt Lenovo Optical USB Mouse: device is a pointer

[1058.930] libinput: configuring device "PixArt Lenovo Optical USB Mouse".

[1058.937] associating input device event5 with output LVDS-1 (none by udev)

從上述內容可道,linux內核提示識別到了一個新的low-speedUSB(低速設備),并且得到了關于該USB鼠標相關的參數信息。然后input輸入子系統打印出了兩條信息:

[ 3122.713317] input: PixArt Lenovo Optical USB Mouse as /devices/platform/fd8c0000.usb/usb4/4-1/4-1:1.0/00036019.0004/input/input8

[ 3122.771015] hid-generic 00036019.0004: input,hidraw0: USB HID v1.11 Mouse [PixArt Lenovo Optical USB Mouse] on usb-fd8c0000.usb-1/input0

接著用戶空間程序打印出了幾條信息:

[1058.921] event5 - PixArt Lenovo Optical USB Mouse: is tagged by udev as: Mouse

[1058.923] event5 - PixArt Lenovo Optical USB Mouse: device is a pointer

[1058.930] libinput: configuring device "PixArt Lenovo Optical USB Mouse".

[1058.937] associating input device event5 with output LVDS-1 (none by udev)

至此,可以知道當USB鼠標插入usb接口后,linux內核會識別到usb設備插入并且打印出識別到的信息,然后會交給input輸入子系統識別,因為鼠標是一個輸入設備,應歸屬于輸入子系統下,輸入子系統會向用戶空間暴露出操作接口。接著用戶空間程序檢測到用戶的輸入識別進而打印出相關的識別信息,從而完成整個識別過程。

從內核源碼角度,usb內核識別階段打印設備描述符信息的操作函數是announce_device(),實現如下:

static void announce_device(struct usb_device *udev)

{

u16 bcdDevice = le16_to_cpu(udev->descriptor.bcdDevice);

dev_info(&udev->dev,

"New USB device found, idVendor=%04x, idProduct=%04x, bcdDevice=%2x.%02x

",

le16_to_cpu(udev->descriptor.idVendor),

le16_to_cpu(udev->descriptor.idProduct),

bcdDevice >> 8, bcdDevice & 0xff);

dev_info(&udev->dev,

"New USB device strings: Mfr=%d, Product=%d, SerialNumber=%d

",

udev->descriptor.iManufacturer,

udev->descriptor.iProduct,

udev->descriptor.iSerialNumber);

show_string(udev, "Product", udev->product);

show_string(udev, "Manufacturer", udev->manufacturer);

show_string(udev, "SerialNumber", udev->serial);

}

#elsestatic inline void announce_device(struct usb_device *udev) { }

#endif

(2-2)USB鼠標移除/拔下后日志分析

當usb設備移除后,則會打印出類似以下的信息:

(1)[ 2791.684059] usb 4-1: USB disconnect, device number 4

(2)[1027.777] event5 - PixArt Lenovo Optical USB Mouse: device removed

第(1)條信息是linux內核usb核心識別到usb設備被移除/拔出后,打印出的信息,這個過程是內核空間的過程。

第(2)條信息是用戶空間程序識別到usb鼠標設備被拔出后打印出的信息,這個過程是用戶空間程序的操作過程。

三、 usb host控制器的初始化

一般情況下,處理器平臺內部都集成了USB host主機控制器,linux內核中,對usb host控制器的初始化發生在內核啟動階段,從內核啟動打印出的日志中,可以找到類似如下的信息(輸出中加有標記信息):

[ 0.779954] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1

[ 0.779969] usb usb1: Product: EHCI Host Controller

[ 0.779978] usb usb1: Manufacturer: Linux 4.19.232 ehci_hcd

[ 0.779991] usb usb1: SerialNumber: fd800000.usb

[ 0.780002]

[ 0.780002] ================usb_new_device==============

[ 0.780432] ==================================enter hub_probe=============================

[ 0.780453] hub 1-0 USB hub found

[ 0.780493] hub 1-0 1 port detected

[ 0.783005] ehci-platform fd880000.usb: EHCI Host Controller

[ 0.783186] ehci-platform fd880000.usb: new USB bus registered, assigned bus number 2

[ 0.783503] ehci-platform fd880000.usb: irq 14, io mem 0xfd880000

[ 0.796390] ehci-platform fd880000.usb: USB 2.0 started, EHCI 1.00

[ 0.796606] usb usb2: New USB device found, idVendor=1d6b, idProduct=0002, bcdDevice= 4.19

[ 0.796626] usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1

[ 0.796641] usb usb2: Product: EHCI Host Controller

[ 0.796655] usb usb2: Manufacturer: Linux 4.19.232 ehci_hcd

[ 0.796669] usb usb2: SerialNumber: fd880000.usb

[ 0.796680]

[ 0.796680] ================usb_new_device==============

[ 0.797080] ==================================enter hub_probe=============================

[ 0.797100] hub 2-0 USB hub found

[ 0.797142] hub 2-0 1 port detected

[ 0.797861] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver

[ 0.797892] ohci-platform: OHCI generic platform driver

[ 0.798121] ohci-platform fd840000.usb: Generic Platform OHCI controller

[ 0.798290] ohci-platform fd840000.usb: new USB bus registered, assigned bus number 3

[ 0.798541] ohci-platform fd840000.usb: irq 13, io mem 0xfd840000

[ 0.857203] usb usb3: New USB device found, idVendor=1d6b, idProduct=0001, bcdDevice= 4.19

[ 0.857224] usb usb3: New USB device strings: Mfr=3, Product=2, SerialNumber=1

[ 0.857239] usb usb3: Product: Generic Platform OHCI controller

[ 0.857252] usb usb3: Manufacturer: Linux 4.19.232 ohci_hcd

[ 0.857265] usb usb3: SerialNumber: fd840000.usb

[ 0.857276]

[ 0.857276] ================usb_new_device==============

[ 0.857683] ==================================enter hub_probe=============================

[ 0.857703] hub 3-0 USB hub found

[ 0.857750] hub 3-0 1 port detected

[ 0.858206] ohci-platform fd8c0000.usb: Generic Platform OHCI controller

[ 0.858386] ohci-platform fd8c0000.usb: new USB bus registered, assigned bus number 4

[ 0.858624] ohci-platform fd8c0000.usb: irq 15, io mem 0xfd8c0000

[ 0.917200] usb usb4: New USB device found, idVendor=1d6b, idProduct=0001, bcdDevice= 4.19

[ 0.917220] usb usb4: New USB device strings: Mfr=3, Product=2, SerialNumber=1

[ 0.917234] usb usb4: Product: Generic Platform OHCI controller

[ 0.917248] usb usb4: Manufacturer: Linux 4.19.232 ohci_hcd

[ 0.917260] usb usb4: SerialNumber: fd8c0000.usb

[ 0.917271]

[ 0.917271] ================usb_new_device==============

[ 0.917662] ==================================enter hub_probe=============================

[ 0.917683] hub 4-0 USB hub found

[ 0.917740] hub 4-0 1 port detected

[ 0.919175] xhci-hcd xhci-hcd.0.auto: xHCI Host Controller

[ 0.919378] xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 5

[ 0.919920] xhci-hcd xhci-hcd.0.auto: hcc params 0x0220fe64 hci version 0x110 quirks 0x0000011002010010

[ 0.919992] xhci-hcd xhci-hcd.0.auto: irq 81, io mem 0xfd000000

[ 0.920297] usb usb5: New USB device found, idVendor=1d6b, idProduct=0002, bcdDevice= 4.19

[ 0.920316] usb usb5: New USB device strings: Mfr=3, Product=2, SerialNumber=1

[ 0.920331] usb usb5: Product: xHCI Host Controller

[ 0.920344] usb usb5: Manufacturer: Linux 4.19.232 xhci-hcd

[ 0.920357] usb usb5: SerialNumber: xhci-hcd.0.auto

[ 0.920369]

[ 0.920369] ================usb_new_device==============

[ 0.920786] ==================================enter hub_probe================

[ 0.920806] hub 5-0 USB hub found

[ 0.920849] hub 5-0 1 port detected

[ 0.921167] xhci-hcd xhci-hcd.0.auto: xHCI Host Controller

[ 0.921325] xhci-hcd xhci-hcd.0.auto: new USB bus registered, assignStarting syslogd: ed bus number 6

[ 0.921352] xhci-hcd xhci-hcd.0.auto: Host supports OK

USB 3.0 SuperSpeed

[ 0.921433] usb usb6: We don't know the alStarting klogd: gorithms for LPM for this host, disabling LPM.

[ 0.921559] usbOK

usb6: New USB device found, idVendor=1d6b, idProduct=0003, bcdDevice= 4.19

[ 0.921577]Populating /dev using udev: usb usb6: New USB device strings: Mfr=3, Product=2, SerialNumber=1

[ 0.921593] usb usb6: Product: xHCI Host Controller

[ 0.921607] usb usb6: Manufacturer: Linux 4.19.232 xhci-hcd

[ 0.921620] usb usb6: SerialNumber: xhci-hcd.0.auto

[ 0.921630]

[ 0.921630] ================usb_new_device============

[ 0.922028] ====================enter hub_probe=============================

=============

[ 0.922047] hub 6-0 USB hub found

[ 0.922086] hub 6-0 1 port detected

在linux USB子系統中,需使用usb_register_bus()將USB host控制器注冊到USB核心上,該函數由usb_add_hcd()調用,用于完成通用hcd結構的初始化和注冊,并調用驅動程序的reset()和start()。

我們已經知道,在usb通信機制中,處理器內部一般都會集成host控制器,所以同樣需要有對應的驅動程序去驅動。usb_add_hcd()函數則會在usb的主機控制器驅動程序的probe過程中被調用,內核中,幾乎所有的usb host控制器驅動都是這樣的寫法。

在USB Host控制器驅動框架下,有一個重要的數據結構:struct usb_hcd,用于描述一個USB Host Controller Driver(簡寫HCD)。例如通用平臺ohci驅動,驅動文件則是:ohci-platform.c,源碼中有如下代碼:

usb_create_hcd用于創建并初始化一個hcd結構描述符:

usb_add_hcd用于初始化hcd結構和注冊hcd:

調用platform_get_irq()為設備分配中斷號:

在usb_add_hcd()中會調用usb_hcd_request_irqs():

從上圖可知,其會調用request_irq()這個重磅函數為ohci host控制器分配中斷,中斷處理函數為usb_hcd_irq ():

irqreturn_t usb_hcd_irq (int irq, void *__hcd)

{

struct usb_hcd *hcd = __hcd;

irqreturn_t rc;

if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd)))

rc = IRQ_NONE;

else if (hcd->driver->irq(hcd) == IRQ_NONE)

rc = IRQ_NONE;

else

rc = IRQ_HANDLED;

return rc;

}

仔細分析上述代碼,又回去了:在hcd中斷處理函數中則會去調用執行hcd驅動程序指定的irq:

hcd->driver->irq(hcd)

那么對于ohci控制器來說,irq則是ohci_irq(),如下圖所示:

綜上,如果處理器內部usb host控制器符合ohci通用標準,則可以使用ohci-platform.c下的驅動程序,這意味著當ohci類的usb設備插入時,對應的中斷處理函數會被調用執行(小生根據實際源碼運行驗證過,也確實如此)

在linux內核中,對于ehci和xhci的host控制器,同樣有對應的通用驅動程序。只要處理器平臺內部USB host控制器符合linux內核提供的通用驅動即可使用。

四、USB設備插入后的硬件過程

從linux內核源碼反推硬件對插入的USB設備的識別,大概知道這個過程是由處理器內部的host控制器完成的。當插入USB設備后,將觸發對應的usb host控制器的中斷,中斷進而又由中斷控制器捕獲,從而將中斷信息由硬件轉向linux內核的中斷系統,從前面分析可知,USB host控制器驅動程序都為對應的控制器指定了中斷處理函數,那么在中斷處理函數中,則會讀取控制器的寄存器參數值從而獲取控制器狀態,除此之外在中斷處理函數中還做了很多事情(標準xhci控制器驅動程序的寫法與ohci、ehci標準控制器驅動有很大不同,暫不過多深究!),例如調用usb_hcd_poll_rh_status(),但目的只有一個:激活刷新usb hub。

五、USB設備插入后的軟件過程

當usb hub被激活刷新后,其后會調用到hub_event,后續的調用邏輯如下:

hub_events()->hub_port_connect_change()->hub_port_connect()->usb_new_device()

->device_add()->kobject_uevent()

usb_new_device()是創建usb新設備的核心函數,在linux內核啟動過程中或者插入usb設備后,USB核心會調用這個函數。

kobject_uevent()用于向用戶空間發送uevent事件,通知用戶空間的偵聽程序USB設備已經插入。

『筆者在瀏覽查詢資料時,發現了這個問題,在此一并列出』

Q1:如果USB設備的驅動是在設備插入時動態加載的,那這個加載過程,處在這一個過程的哪一個位置?

A1:調用bus_probe_device(dev)完成!

綜上,得出結論:在linux內核中,一個USB設備插入時,其設備驅動是動態加載的

審核編輯:陳陳

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • usb
    usb
    +關注

    關注

    60

    文章

    7773

    瀏覽量

    262392
  • Linux
    +關注

    關注

    87

    文章

    11123

    瀏覽量

    207919
  • 熱插拔
    +關注

    關注

    2

    文章

    208

    瀏覽量

    36311

原文標題:不放過linux-usb的熱插拔過程

文章出處:【微信號:嵌入式小生,微信公眾號:嵌入式小生】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    熱插拔是什么?熱插拔有哪些特點?

    的電腦中一般都有USB接口,這種接口就能夠實現熱插拔。如果沒有熱插拔功能,即使磁盤損壞不會造成數據的丟失,用戶仍然需要暫時關閉系統,以便能夠對硬盤進行更換,而使用
    發表于 12-13 10:53

    即插即用和熱插拔的區別

    關系。即插即用是要重啟機器才能認出來的熱插拔立刻就能認出來 支持即插即用是一種使您可以快速簡易安裝某硬件設備而無需安裝設備驅動程序或重新配置系統的標準。即插即用需要硬件和軟件兩方面支持,Windows
    發表于 10-23 10:26

    如何對BMS單元連接進行熱插拔

    注重序列效果的情況下,重復測試是可能的。這使得能夠測試多個設備。序列有效性減少測試時間,因此人員可以安全的角度出發。最后,測試過程的定時可以擴展到模擬工廠/用戶連接過程中自然發生的延
    發表于 09-07 18:20

    基于Linux的Netlink熱插拔監控

    Linux中Netlink實現熱插拔監控——內核與用戶空間通信
    發表于 03-19 11:42

    熱插拔系統的影響主要有哪些

    現在大多數電子系統都要支持熱插拔功能,所謂熱插拔,也就是在系統正常工作時,帶電對系統的某個單元進行插拔
    發表于 10-29 06:51

    怎么通知應用層cp2102芯片的熱插拔狀態?

    在用iMX6UL開發板,U盤可以內核層面實現熱插拔。我現在有個USB轉串口的設備(cp2102芯片),不知道有沒有朋友知道怎么通知應用層該設備的
    發表于 01-11 06:31

    USB轉串口熱插拔無法實現是為什么?

    在用iMX6UL開發板,U盤可以內核層面實現熱插拔。我現在有個USB轉串口的設備(cp2102芯片),不知道有沒有朋友知道怎么通知應用層該設備的
    發表于 01-11 07:40

    熱插拔裝置軟件

    熱插拔裝置軟件USB Safely Remove是一款支持熱插拔裝置和迅速切斷一個公用的熱插拔裝置的軟件
    發表于 04-23 09:32 ?151次下載

    基于Linux內核輸入子系統的驅動研究

    Linux因其完全開放的特性和穩定優良的性能深受歡迎,當推出了內核輸入子系統后,更方便了嵌入式領域的驅動開放。介紹了Linux的設備驅動基礎,詳細闡述了基于
    發表于 09-12 16:38 ?23次下載

    Linux內核輸入子系統的驅動研究

    Linux內核輸入子系統的驅動研究
    發表于 10-31 14:41 ?14次下載
    <b class='flag-5'>Linux</b><b class='flag-5'>內核</b>輸入<b class='flag-5'>子系統</b>的驅動研究

    熱插拔控制電路的分析和設計過程

    系統其余部分的情況下進行替換,在系統維持運轉的情況下,發生故障的電路板或模塊將被移除,同時替換部件被插入。這個過程被稱為熱插拔(hot swapping)(當模塊與
    發表于 06-05 15:29 ?8583次閱讀
    <b class='flag-5'>熱插拔</b>控制電路的<b class='flag-5'>分析</b>和設計<b class='flag-5'>過程</b>

    如何使用Linux內核實現USB驅動程序框架

    Linux內核提供了完整的USB驅動程序框架。USB總線采用樹形結構,在一條總線上只能有唯一的主機設備。 Linux
    發表于 11-06 17:59 ?19次下載
    如何使用<b class='flag-5'>Linux</b><b class='flag-5'>內核</b>實現<b class='flag-5'>USB</b>驅動程序框架

    linux-usb子系統的核心描述

    本文將描述linux-usb子系統的核心,主要分析其核心的初始化流程,文中源碼基于內核版本:4.1.15。
    的頭像 發表于 01-14 09:37 ?2391次閱讀

    熱插拔和非熱插拔的區別

    系統關閉或待機狀態下進行。 熱插拔技術的出現,極大地方便了電子設備的使用和維護,減少了因為插拔設備而導致的系統的關機和停機時間,并且降低了設備故障和損壞的風險。下面將從硬件和
    的頭像 發表于 12-28 10:01 ?2359次閱讀

    鍵盤熱插拔和非熱插拔的區別

    、電源供應、軟件驅動、使用便利性、設備損壞與安全性、推動產業發展等。 1. 連接方式 熱插拔鍵盤通常使用USB或無線連接方式,插入即可立即生效。非熱插拔鍵盤一般使用PS/2接口連接,插
    的頭像 發表于 02-02 17:34 ?7605次閱讀