蘋果 USB 低級過濾器,可幫助控制操作系統使用 USB 配置(上)
PTP 還是 MTP?
本文中,我們将重點讨論爲什麽 iphone 沒有像我們期望的使用 MTP 協議的設備那樣提供一整套存儲操作,還将研究 USB 接口類 / 子類和 WPD_DEVICE_PROTOCOL 屬性之間不匹配的原因。爲了回答這些問題,我們将了解如何創建 WPD 設備、如何 " 挂載 " 存儲以及如何設置 WPD 屬性。
首先對比一下使用 PTP 連接的 Android 設備和 iPhone 之間 WPD 設備協議屬性的差異:
考慮到 iPhone 中的 WPD 協議屬性,我們期望有一組更豐富的選項來與設備交互,可以通過查看設備的接口描述符來快速回答爲什麽 iPhone 表現爲 PTP 設備。
iPhone 和小米在 PTP 和 MTP 模式下的描述如下:iPhone 有多種配置,但無論選擇哪一種,創建 WPD 的接口 PDO 總是包含類 6 和子類 1 的接口。
盡管已經回答了最大的問題,但仍然有一些細節,比如爲什麽 iPhone 不允許創建或複制任何東西到它,而另一方面,小米即使使用 PTP 也允許創建對象,所以對于喜歡深入了解事物的人來說,僅僅浏覽界面描述是不夠的。
由于此描述符将生成 CompatibleId USBClass_06&SubClass_01&Prot_01,因此尋找與此 ID 匹配的 INF,我們找到 wpdmtp.inf。在此 INF 中,可以獲得 WPD 設備的 UMDF 部分的以下組件:
WpdMtp.dll:MTP 核心協議組件;
WpdMtpUS.dll:Usbscan MTP 驅動程序的傳輸層;
WpdMtpDr.dll:Windows 便攜式設備媒體傳輸協議驅動程序;
作爲内核方面的一部分,INF 将添加 WinUSB.sys 作爲 LowerFilter,并添加反射器 WUDFRd.sys 作爲函數驅動程序。
從上面提到的三個二進制文件中,WpdMtpDr 是将在 WUDFHost 中運行的主要 WPD MTP 驅動程序。這是一個 UMDFv1 驅動程序,它将基于 COM 并用 C++ 編寫,基于 WpdWudfSampleDriver,幾乎就不需要逆轉,但該驅動程序沒有更新爲使用 UMDFv2,因爲 UMDFv1 幾乎已經被棄用,并且幾乎不支持新功能。
如上所述,入口點是 OnDeviceAdd 例程。在這個函數中,創建了 CDevice 對象,它将我們帶到 CDevice::OnPrepareHardware 例程,在該例程中,通過調用 WpdBaseDriver::Initialize 來初始化 WpdBaseDriver。不幸的是,這是 Sample 代碼和 WpdMtpDr 開始出現差異的部分。示例代碼沒有真正的設備可以通信,但在本文的示例中,WpdMtp.dll 的作用所在,充當 WpdMtpDr 和真正設備之間的粘合劑。MTP 核心庫包含 CMtpDevice 類,它表示真實的設備。在 WpdBaseDriver 初始化期間,加載 MTP 核心庫,并打開與設備的會話,如以下簡化代碼片段所示:
加載 MTP 核心模塊後,觸發初始化例程來檢索 MTP DeviceInfo Dataset。這是發送到設備的初始 MTP 請求之一,DeviceInfo 結構在其返回時填充。值得注意的是,該結構包含關鍵信息,如模型、制造商和各種 MTP 版本标識符。這些信息在稍後設置 WPD 屬性時起着至關重要的作用。
MTP 核心發送請求并将響應解析爲 CDeviceInfo 結構,而 WpdMtpDr 利用緩存系統存儲指向 WpdMtp 返回的類的 COM 指針。這種方法可以防止頻繁地向設備重新發出 PTP/MTP 請求,從而優化 I/O 操作。
下面的堆棧顯示了這個函數第一次被調用 :
在 UM 中,WPD 應用程序通常使用 WPD API 構建 WPD 命令,WPD API 将序列化該 WPD 命令并将其打包到 IOCTL 請求中,這将到達驅動程序,驅動程序将反序列化命令并相應地采取行動。
一旦設備準備好接收 I/O 操作,操作系統将嘗試檢索 WPD 設備屬性,該信息存在于 device objectID 中 ( 此 objectID 是預定義的,始終表示 device 對象 ) 。這個請求将到達 WPD 驅動程序,它将用 CDeviceInfo 的信息填充 WPD 設備屬性。對于 WPD_DEVICE_PROTOCOL 的情況,該值将如何設置 :
現在如果看一下 iPhone 返回的 DeviceInfo Dataset,可以看 VendorExtId 和 VendorExtVersion,可以最終回答爲什麽 WPD_DEVICE_PROTOCOL 被設置爲 MTP 15.20。MICROSOFT_VENDOR_EXT_ID 是由 MS 作爲 WMDRM 協議的一部分定義的,這是 MTP 響應器需要在 DeviceInfo Dataset 中設置的值之一,以告訴 MTP 啓動器它支持 AAVT,令人驚訝的是,iPhone 隻添加了這個必需的值,而不是其他值。
該屬性将在函數 CDevicePropContext::GetDeviceType 上檢索,該函數将使用 SetupAPI 獲得 compatibleid,無論協議是 PTP 還是 MTP,設備中的每個存儲對象 ( 由以 s 開頭的 storageid 表示 ) 都有自己的屬性。同樣,當設備上開始 I/O 操作時,操作系統使用兩個關鍵操作從存儲對象中檢索信息 :getstorageid ( 0x1004 ) ( 檢索 storageid 列表 ) 和 GetStorageInfo ( 0x1005 ) ( 定義存儲對象的行爲方式 ) 。我們将重點關注後者,因爲它返回一個包含以下三個關鍵字段的 StorageInfo 數據集。
存儲類型
文件系統類型
訪問功能
當 WPD 驅動程序第一次嘗試獲取設備的 StorageInfo 時,該請求将通過 MTP 核心模塊。該模塊向設備發送 PTP/MTP 操作請求,并将結果 StorageInfo 數據集返回給驅動程序。
因此,如果看一下 iPhone 是如何響應這個請求的,将能夠根據上面提到的三個字段來确定 Storage 對象的行爲。
我們可以從上圖得到以下信息:存儲類型 == 固定 RAM,這是相當标準的移動設備。文件系統類型 == DCF, DCF 代表 Camera FS 的設計規則,你可以會從著名的 DCIM 根目錄中認出它。DCF 标準定義了在目錄和文件上設置隻讀屬性的選項。訪問能力 == 隻讀,不能删除對象,這是緻命的。這将定義對 Storage 對象的訪問限制,操作系統将遵守這些限制。例如,這将影響 iPhone 的上下文菜單中顯示的選項。
這就是爲什麽 iPhone 上的文件選項如此有限。爲了便于比較,下圖顯示了使用 PTP 插入小米設備時的 StorageInfo 數據集。
事實證明,這就是爲什麽即使使用 PTP 協議連接,也能夠在小米設備上創建對象的原因。然而,值得注意的是小米的 MTP 響應器似乎有問題,無論在設備上選擇 PTP 還是 MTP,在響應 GetStorageInfo 請求時都會返回相同的 Dataset,至少在紅米 Note 8 模型上是這樣。
這樣,我們就可以更清楚地理解 Apple 設備的運行方式,以及如何爲設備配置 WPD 屬性。
蘋果軟件對蘋果設備棧的影響
接下來總結一下,當我們在主機上安裝 iTunes 時會發生什麽,以及它是如何實現諸如從設備複制文件之類的操作的。
如上所述,由于 Storage 對象中的限制,WPD API 将僅在 iPhone 上提供有限的操作子集,然而,當安裝 iTunes 後,它增加了一個不同的層,可以更全面地訪問設備。
正如我們在 AppleLowerFilter 中看到的,一旦 iTunes 被安裝,它将允許設備選擇一個不同的 USB 配置描述符。沒有 iTunes,我們被限制在配置 1,另一方面,一旦 iTunes 被默認安裝,選擇的配置将是 3。以下是這兩種配置及其接口:
選擇配置 3,将使 usbccgp 生成 deviceID USBVID_xxxx&PID_yyyy&MI_01 ( 01 從 bInterfaceNumber 中提取 ) 。這些 deviceid 是在 appleusb 中定義的。它定義了以下文件的副本:
這兩個驅動程序将成爲被蘋果公司稱爲 " 蘋果移動設備 USB 設備 " 設備的一部分,該設備使用專有協議而不是 MTP 或 PTP 與 iPhone 進行通信,可以通過查看 libimobiledevice 的源代碼來了解有關該協議的更多信息。一旦驅動程序安裝并運行,iTunes 本身就會使用标準 WPD API 調用和定制的蘋果特定命令的組合與 iPhone 進行通信。這使得 iTunes 能夠提供從設備中複制文件、管理應用程序和備份以及更新設備固件等功能。
下圖提供了 iPhone 的整個設備堆棧的簡化概述,包括安裝 iTunes 和創建 AppleUsbMux 設備的場景:
總結
在本文中,我們探讨了蘋果的 USB 低級過濾器是如何在 Windows 設備上工作的,以及它在提供不同體驗方面的作用,還深入研究了 Windows 便攜式設備 ( WPD ) 和用戶模式驅動程序框架 ( UMDF ) 等主題,以更好地理解蘋果設備堆棧的内部工作原理。
我們談到 WPD 設備是如何初始化和設置的,這幫助我們了解了爲什麽 WPD 設備協議屬性和 Apple 設備中接口描述符定義的類之間存在不匹配。我們還研究了 WPD 設備的 Storage 對象是如何設置的,以及它如何在不使用第三方軟件的情況下在 iPhone 上操作的限制中發揮作用。最後,我們簡要讨論了安裝 iTunes 對蘋果移動設備棧的影響,以及 iTunes 如何妥善管理設備内容。
蘋果希望保護某些信息,限制與 iPhone 存儲交互的現成選項,但如果有一個更混合的解決方案,用戶可以在一定的限制下擁有更大的靈活性。雖然 iTunes 爲管理 iPhone 内容提供了一個強大的解決方案,但有時安裝第三方軟件可能不是一個選擇。然而,随着 iTunes 最近作爲微軟商店應用程序的發布,這種限制可能會減少。