蘋果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 USB\Class_06SubClass_01Prot_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 USB\VID_xxxxPID_yyyyMI_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最近作為微軟商店應用程序的發布,這種限制可能會減少。
Recommended Comments