淺談 USB 通訊架構之定義(一)

USB(Universal Serial Bus) 的應用範疇以及價值已經不需要再多做說明,其身影從 HID(Human Interface Device)、隨身碟(USB Stick、Flash drive、Pen drive)到各種類比式或非連續訊號接收器(如: Webcam、Microphone、DVB Receiver),更進一步可以講到各種通訊裝置或外接設備,甚至是取代和模擬舊式通訊傳輸線(Serial Port)。USB 所有的 Spec 和相關資訊 ,可參考 http://www.usb.org/

USB 整體運作模式

一般來說 USB 的通訊結構有如 Server/Client,以 PC 上的情形為例,位於主機上的 USB 裝置稱為『USB Host』,我們可以在上面外接上數個裝置(與 USB Host 相連的裝置通常被稱為 USB Device 或 USB Client)。

底層上,『Host 負責主導整個 USB 結構的通訊』,它會輪詢所有的 USB Deivce 以檢查是否有裝置需要傳送資料,所有 USB Device 都必需要等待 Host 的命令,唯有 Host 同意時,USB Device 才可以開始傳送資料。



Host 的行為通常是由 USB Host Controller 在做控制,其控制器是一組控制晶片,而對於現代 PC ,USB Host Controller 的晶片通常都被 Layout 在主機板上,以 PCI Bus 的形式存在供作業系統控制,我們可以使用 lspci 看到它的存在:
00:1a.0 USB Controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #4 (rev 03)
00:1a.1 USB Controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #5 (rev 03)
00:1a.2 USB Controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #6 (rev 03)
00:1a.7 USB Controller: Intel Corporation 82801I (ICH9 Family) USB2 EHCI Controller #2 (rev 03)

註:UHCI 全名為 Universal Host Controller Interface。

USB Device 的結構

瞭解了整體的運作模式後,便可以開始解析 USB 裝置的架構,其囊括了模式(Configurations)、介面(Interfaces)、設定值(Settings)和端點(Endpoints),其架構圖如下:


以上示意圖只是說明 USB 架構的規範,至於細節部份可由硬體設計者自由發揮。比較常見的『模式(Configurations)』和『介面(Interfaces)』定義的應用。
  • 模式(Configurations):

    一次只能使用一種模式,不可能同時有兩種模式並行的運作狀態,常見的應用是將 USB 裝置切換至 Firmware 的更新模式,做韌體升級,此時該硬體的一般模式將沒有作用。

  • 介面(Interfaces):

    一個 USB 裝置可能有很多個輸入或輸出介面,舉例來說,若是有一個帶麥克風的耳機,就會有兩個介面,分別為『聲音 Input』和『聲音 Output』所使用。用一個特殊的例子『3G Modem』可更容易說明:

    3G Modem 擁有至少三個介面:
    • Serial for modem
    • Serial for information update
    • Mass Storage

    這也是為什麼尚未安裝驅動程式前,OS Kernel(無論是 MS Windows 還是 Linux) 會預設將 3G Modem 視為一個儲存媒體。而在驅動程式安裝設定後,驅動程式才會使 USB 裝置的其他介面,此時才可開始藉由這些介面做 3G 撥號。
從 sysfs 觀察 USB 裝置

若想要驗證以上的定義,在 Linux 下可以很輕易透過 sysfs 達成。以下是以 USB 3G Modom 所產生的 sys 路徑為例:
/sys/devices/pci0000:00/0000:00:1d.0/usb6/6-2/6-2:1.0
/sys/devices/pci0000:00/0000:00:1d.0/usb6/6-2/6-2:1.1
/sys/devices/pci0000:00/0000:00:1d.0/usb6/6-2/6-2:1.2

因為一個 USB Host Controller 晶片通常可以處理多組 USB 來源,每一組來源都可再分接連上更多的 USB 裝置。因此,在控制晶片內部會有數個『根集線器(Root Hub) 』以供多組 USB 來源連接,而在例子中的 3G Modem 是插在 usb6 (第 6 號『根集線器(Root Hub) 』)的第二個 Port 上(這邊又標示為 6-2)。

而後面的 1.0、1.1、1.2 分別代表了有三組介面(Interfaces),其命名所代表的意義是:
<模式號碼>.<介面號碼>


因為例子中的 3G Modem 是 Huawei E220,硬體上的這三組介面都是 Serial Port,Kernel 會辯識它然後產生三個裝置描述檔:ttyUSB0、ttyUSB1、ttyUSB2 以對應。

後記

會以 3G Modem 當做例子,是因為它確實比一些單純的 HID(單一 Interface)複雜,可以較容易說明 USB 的架構細節。而對於 USB 的東西,到這裡只記錄了一個開頭,真正與驅動程式息息相關的 Endpoint 可還沒上場。

留言

  1. 你拿出 3G modem 當範例,但其實 3G modem 的 pseudo cdrom 功能跟 USB Configuration descriptor 沒有直接關係。

    你恐怕誤解了 Configuration descriptor 所能描述的資料及其功能。

    回覆刪除
  2. 抱歉,之前未真正仔細去查證 3G Modem 的設計,經查證後發現 Huawei E220 其實只有一個 Configuration descriptor,且是使用 3 個 Interface,其中一個是 Mass Storage Class。

    至於它的 Firmwire Upgrade 的功能, 因為小弟手邊沒有完整 Hardware Spec,目前還無法得知是如何使用,只能猜測是由其中一個 Interface 或是單純直接硬幹 Control Transfer 做 Upgrade 也說不定。

    關於這部份的舉例說明,在文中已做修正。

    此外,雖然 3G Modem 是如此設計,但還是不可否認有些硬體是由切換 configuration 去切換 Firmware Mode或選擇不同的運作模式,事實上,USB 會有這樣的定義,本來就是為此而生。因此 Configration Descriptor 部份說明,就沒做修改,維持舊文。

    多謝指點,下次會更仔細查證引用資訊,以免文內錯誤再次發生。:-)

    回覆刪除
  3. 大大您好
    這裡我有疑問想請教有關3G USB卡的問題
    因為我稍微有接觸過3G USB卡
    我們都知道,目前不少3G USB卡都是預設為儲存裝置的型態,而裡面裝有驅動程式(主要是給WINDOWS用的)
    而此張卡如果插上LINUX上,一樣大多也會抓到儲存裝置而非modem裝置
    如果我們想改成modem就要使用一些技巧改變此張USB卡的PID或VID(也就是叫USB卡換另一種型態了)
    而PID與VID是Device Descriptors裡的東西,似乎不是Configuration Descriptors、Interface Descriptors的資訊
    所以這樣看來,從儲存裝置模式跳為modem模式,應該不是驅動其它Interface,而是改為另一種Device了?
    (當然 不同的Device底下又有Configuration、Interface等等)

    我純粹只是從PID與VID的變化而推測的,不知道大大覺得這樣的揣測是不是對的?
    不過我印象中我也遇過一些3G USB卡的PID與VID都不必轉換就可以共存兩個狀態(儲存裝置與modem裝置)
    那應該就是大大提的那種情況了?
    那如果PID與VID必須轉換,應該就不是大大提的那種類型囉?
    那我的推測是對的嗎? 謝謝

    回覆刪除
    回覆
    1. 讓我先確認一下,您指的 PID 和 VID 應該是指 Product ID 和 Vendor ID 吧?

      其實本文內就有提到,一般 USB 3G Modem 是採用三個 interface 去描述 Serial、Serial for updating、Storage。這意思是,其實三個 interface 是同時存在的,使用上無需切換,所以並沒有所謂的『預設』是哪一個模式。至少我目前用過的 USB 3G Modem 都是一樣的設計。

      而系統之所以會識別錯誤,純粹是因為沒有驅動程式告訴系統如何去使用 Mass Storage 以外的 interface,所以系統只懂得使用 Mass Storage Driver 去看待你的 Device。

      至於你說為什麼改 Product ID 和 Vendor ID 系統就可以驅動?我在猜測,因為系統有『可用』的 Driver,但是 Driver 裡所記載的 Product ID 和 Vendor ID 不夠齊全,導致 Driver 不認得你的 Device,當然就不會正確驅動。你可以去可用的 Driver 裡,加入一組新的 Product ID/Vendor ID ,就知道結果了。

      至於在 Linux 上,因為 3G Modem 驅動全都是標準 Serial,其實根本不需要額外的驅動程式,你只要告訴 Linux Kernel 去使用 usb-serial driver 就可以。這也是為什麼只需要去改動 udev 的設定,就可以正常驅動 USB 3G Modem 的原因。

      因此 Linux 上,你看到的主流做法,就只是不停的去更新 Product ID/Vendor ID,因為它們根本是同一支 Driver。如果你插上 USB 3G Modem 發現他可以直接抓到 Serial interface,就是該 Device 的 Product ID/Vendor ID 有被記錄。

      BTW, 我不太清楚怎麼去改動 Product ID/Vendor ID,這點我倒是很好奇你們怎麼改的?

      刪除
  4. 這種功能叫做 ZeroCD[1], 他們需要特別的 USB Command 才能切換不同的功能 (同時硬體也會跟著切換 VID,PID)

    [1] http://en.wikipedia.org/wiki/Virtual_CD-ROM_switching_utility

    回覆刪除
    回覆
    1. Cool! 這樣我有印象了,因為之前想要寫 Network Manager 時有研究過怎麼切換,只是沒想到 VID 和 PID 也會跟著換。

      但我記得,我在以前研究的過程中有發現,我所碰過的 3G Modem,雖然乍看下都要切換,但其實不需要切換就可以用了。
      (那時我直接把 usb-storage driver 拿掉,直接上 usb-serial 就會動了)

      所以我在猜也許只是換 PID/VID?硬體功能其實沒有因此被切換?(到底有哪個 Modem 真的會因為切換而功能不同,我就不知道了。)

      刪除
    2. 我以前玩過
      硬體功能有被切換掉喔
      一開始storage時 我輸入cat proc/bus/usb/devices
      可以看到這張卡有多少個(我猜是interface) 並且被哪些驅動給驅動起來

      而我改了VID與PID後,再下一次cat proc/bus/usb/devices
      發現interface變了(通常變多了),而且他們全部都沒遇到驅動來綁定

      而我也曾經試著不轉他PID與VID
      而是去KERNEL改驅動內容,把USB Storage的ID TABLE裡,把我要用的卡的VID與PID拿掉
      並且填去USB Serial的驅動裡,我印象中是不成功 失敗了

      如果是這樣沒錯,那應該可以推論,換VID與PID是連硬體功能都換掉囉
      而更確切的說,應該是因為硬體功能換掉了,所以VID跟PID才能夠改變
      不過第2個的實驗 我有點忘了 因為那是我好久以前 轉不了ID
      心灰意冷,試著直接暴力餵ID給SERIAL的樣子 但搞不好有做錯還是怎樣

      謝謝

      刪除
  5. 存储装置应该是/dev/sr*,是以模拟CD-ROM存在的。

    /dev/ttyUSB0是3G Modem;
    /dev/ttyUSB1用作语音通话;
    /dev/ttyUSB3用作发送AT指令。

    至少华为的设备一般都是这样的。

    回覆刪除

張貼留言

這個網誌中的熱門文章

Web 技術中的 Session 是什麼?

上手使用 JavaScript 的 Map、Reduce 吧!

淺談 USB 通訊架構之定義(二)

JavaScript async/await 的奇淫技巧