共用方式為


寫入USB Type-C埠控制器驅動程式

如果您的USB Type-C硬體實作USB Type-C或Power Delivery (PD) 實體層,但未實作電源傳遞所需的狀態機器,您需要撰寫 USB Type-C 埠控制器驅動程式。

在 Windows 10 1703 版中,USB Type-C 架構已改善,以支援實作 USB Type-C 或 Power Delivery (PD) 實體層的硬體設計,但沒有對應的 PD 原則引擎或通訊協定層實作。 針對這些設計,Windows 10 1703 版透過稱為「USB 連接器管理員 Type-C 埠控制器介面類別延伸模組」的新類別擴充功能,提供軟體型 PD 原則引擎和裝置原則管理員, (UcmTcpciCx) 。 由 IHV 或 OEM/ODM 所撰寫的用戶端驅動程式會與 UcmTcpciCx 通訊,以提供 UcmTcpciCx 中 PD 原則引擎和裝置原則管理員所需的硬體事件相關信息以運作。 該通訊是透過本文和參考一節中所述的一組程序設計介面來啟用。

USB 連接器管理員的圖表。

UcmTcpciCx 類別延伸模組本身是 UcmCx 的用戶端驅動程式。 有關電源合約、數據角色的原則決策是在UcmCx中建立,並轉送到UcmTcpciCx。 UcmTcpciCx 會實作這些原則,並使用UcmTcpciCx用戶端驅動程式所提供的埠控制器介面來管理 Type-C 和 PD 狀態機器。

摘要

  • UcmTcpci 類別延伸模組所提供的服務
  • 用戶端驅動程式的預期行為

官方規格

重要 API

USB Type-C 埠控制器介面驅動程序類別延伸模組參考

UcmTcpciCx 用戶端驅動程式範本

UcmTcpciCx 用戶端驅動程式範本

開始之前

  • 根據硬體或韌體是否實作 PD 狀態機器,判斷您需要撰寫的驅動程序類型。 如需詳細資訊,請參閱 開發適用於USB Type-C連接器的 Windows 驅動程式

  • Windows 10 在您的目標計算機上安裝傳統型版本 (家用版、專業版、企業版和教育版) ,或使用 USB Type-C 連接器 Windows 10 行動裝置版。

  • 開發電腦上安裝最新的 Windows 驅動程式套件 (WDK) 。 套件具有撰寫客戶端驅動程式所需的頭檔與連結庫,特別是您需要:

    • stub 連結庫, (UcmTcpciCxStub.lib) 。 連結庫會轉譯客戶端驅動程式所進行的呼叫,並將其傳遞至類別延伸模組。
    • 頭檔 UcmTcpciCx.h。

    用戶端驅動程式會在核心模式中執行,並系結至 KMDF 1.15 連結庫。

    適用於UCM的Visual Studio 設定螢幕快照。

  • 決定客戶端驅動程式是否支援警示。

  • 您的埠控制器不需要符合 TCPCI 規範。 介面會擷取任何 Type-C 埠控制器的功能。 針對不符合 TCPCI 規範的硬體撰寫 UcmTcpciCx 用戶端驅動程式,牽涉到將 TCPCI 規格中的緩存器和命令的意義對應到硬體的意義。

  • 大部分的 TCPCI 控制器都是 I2C 連線。 您的客戶端驅動程式會使用序列周邊總線 (SPB) 連線資源和中斷線來與硬體通訊。 驅動程式會使用SPB Framework擴充功能 (SpbCx) 程式設計介面。 閱讀下列文章,以熟悉SpbCx:

    • [簡單周邊總線 (SPB) 驅動程序設計指南]
    • [SPB 驅動程式程序設計參考]
  • 熟悉 Windows Driver Foundation (WDF) 。 建議閱讀: 使用 Windows Driver Foundation 開發驅動程式,其作者為一位作者,作者:Orwick 和 Guy Smith。

UcmTcpci 類別延伸的行為

  • 在狀態機器執行過程中,UcmTcpciCx 會將IOCTL要求傳送至埠控制器。 例如,在 PD 傳訊中,它會傳送IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_TRANSMIT_BUFFER要求來設定傳輸緩衝區。 該要求 (TRANSMIT_BUFFER) 交給客戶端驅動程式。 驅動程式接著會使用類別延伸模組所提供的詳細數據來設定傳輸緩衝區。

  • UcmTcpciCx 會實作有關電源合約、數據角色等的原則。

用戶端驅動程式的預期行為

UcmTcpciCx 的用戶端驅動程式預期如下:

  • 成為電源原則擁有者。 UcmTcpciCx 不會參與埠控制器的電源管理。

  • 將從UcmTcpciCx接收的要求轉譯為硬體讀取或寫入命令。 命令必須是異步的,因為 DPM 無法封鎖等待硬體傳輸完成。

  • 提供包含架構要求對象的架構佇列物件。 針對UcmTcpci類別延伸模組想要傳送至客戶端驅動程式的每個要求,延伸模組會在驅動程式的佇列物件中新增要求物件。 當驅動程式完成處理要求時,它會呼叫 WdfRequestComplete。 用戶端驅動程序必須負責及時完成要求。

  • 探索並報告埠控制器的功能。 這些功能包括埠控制器可在 (中運作的角色等資訊,例如僅限來源、僅限接收、DRP) 。 不過,連接器有其他功能 (請參閱功能存放區) 和整個系統的附註,DPM 必須知道才能正確實作 USB Type-C 和 PD 原則。 例如,DPM 必須知道系統/連接器的來源功能,才能將它公告給埠夥伴。

    功能存放區

    除了客戶端驅動程式相關的功能之外,其他資訊也來自稱為 「功能存放區」的系統全域位置。 此系統全域功能存放區會儲存在 ACPI 中。 這是系統功能的靜態描述,以及 DPM 用來判斷要實作的原則的每個 USB Type-C 連接器。

    藉由將系統功能的描述與埠控制器的用戶端驅動程式 () 區隔,設計可讓驅動程式用於不同功能的不同系統上。 UcmCx,而非UcmTcpciCx,具有功能存放區介面。 UcmTcpciCx (或其用戶端驅動程式) 不會與功能存放區互動。

    如果適用,來自功能存放區的資訊會覆寫來自埠控制器客戶端驅動程序的資訊。 例如,埠控制器能夠進行僅限接收的作業,而用戶端驅動程式會報告該資訊。 不過,系統其餘部分可能無法正確設定為僅限接收的作業。 在此情況下,系統製造商可以報告連接器能夠在功能存放區中執行僅限來源的作業。 功能存放區中的設定優先於驅動程序回報的資訊。

  • 使用與警示相關的所有相關數據通知 UcmTcpciCx。

  • 選擇性。 在進入/結束替代模式之後執行一些額外的處理。 驅動程式會透過IOCTL要求,透過類別延伸模組通知這些狀態。

向UcmTcpciCx註冊客戶端驅動程式

範例參考:請參閱 EvtPrepareHardware 中的 Device.cpp

  1. 在您的EVT_WDF_DRIVER_DEVICE_ADD實作中,呼叫 UcmTcpciDeviceInitInitialize 來初始化WDFDEVICE_INIT不透明結構。 呼叫會將客戶端驅動程式與架構產生關聯。

  2. (WDFDEVICE) 建立架構裝置對象之後,請呼叫 UcmTcpciDeviceInitialize 向 UcmTcpciCx 註冊用戶端 diver。

將 I2C 通道初始化為埠控制器硬體

範例參考:請參閱 EvtCreateDevice 中的 Device.cpp

在您的EVT_WDF_DEVICE_PREPARE_HARDWARE實作中,讀取硬體資源以開啟通道。 這是擷取 PD 功能並取得警示通知的必要專案。

大部分的 TCPCI 控制器都是 I2C 連線。 在參考範例中,用戶端驅動程式會使用SPB Framework擴充功能 (SpbCx) 程式設計介面來開啟I2 通道。

用戶端驅動程式會呼叫 WdfCmResourceListGetDescriptor 來列舉硬體資源。

警示會以中斷的形式接收。 因此,驅動程式會建立架構中斷物件,並註冊處理警示的ISR。 ISR 會執行硬體讀取和寫入作業,直到硬體存取完成為止。 因為等候在 DIRQL 上無法接受,所以驅動程式會在PASSIVE_LEVEL執行 ISR。

初始化埠控制器的 Type-C 和 PD 功能

範例參考:請參閱 EvtDeviceD0Entry 中的 Device.cpp

在您的EVT_WDF_DEVICE_D0_EXIT實作中,

  1. 藉由讀取各種緩存器來與埠控制器硬體通訊,並擷取裝置識別和功能。

  2. 使用擷取的資訊初始化UCMTCPCI_PORT_CONTROLLER_IDENTIFICATION和UCMTCPCI_PORT_CONTROLLER_CAPABILITIES。

  3. 藉由將初始化的結構傳遞至UCMTCPCI_PORT_CONTROLLER_CONFIG_INIT,以上述資訊初始化UCMTCPCI_PORT_CONTROLLER_CONFIG結構。

  4. 呼叫 UcmTcpciPortControllerCreate 以建立埠控制器物件,並擷取 UCMTCPCIPORTCONTROLLER 句柄。

設定架構佇列物件以接收來自UcmTcpciCx的要求

範例參考:請參閱 EvtDeviceD0Entry 中的 Device.cppQueue.cppHardwareRequestQueueInitialize

  1. 在您的EVT_WDF_DEVICE_D0_EXIT實作中,呼叫 WdfIoQueueCreate 來建立架構佇列物件。 在該呼叫中,您必須註冊回呼實作,以處理UcmTpciCx所傳送的IOCTL要求。 客戶端驅動程式可以使用電源管理的佇列。

    在執行 Type-C 和 PD 狀態機器期間,UcmTpciCx 會將命令傳送至用戶端驅動程式以執行。 UcmTcpciCx 保證在任何指定時間最多一個未處理的埠控制器要求。

  2. 呼叫 UcmTcpciPortControllerSetHardwareRequestQueue 以向 UcmTpciCx 註冊新的架構佇列物件。 在該呼叫成功之後,UcmTcpciCx 會在需要驅動程序的動作時,將架構佇列物件放在此佇列中 (WDFREQUEST) 。

  3. 實作 EvtIoDeviceControl 回呼函式來處理這些 IOCTLs。

控制程序代碼 Description
IOCTL_UCMTCPCI_PORT_CONTROLLER_GET_STATUS 根據通用序列總線類型-C 埠控制器介面規格,取得所有狀態緩存器的值。 用戶端驅動程序必須擷取CC_STATUS、POWER_STATUS和FAULT_STATUS緩存器的值。
IOCTL_UCMTCPCI_PORT_CONTROLLER_GET_CONTROL 取得根據通用序列總線類型-C 埠控制器介面規格所定義之所有控件緩存器的值。
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_CONTROL 根據通用序列總線類型-C 埠控制器介面規格,設定定義為控件緩存器的值。
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_TRANSMIT 設定根據通用序列總線類型-C 埠控制器介面規格定義的 TRANSMIT 快取器。
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_TRANSMIT_BUFFER 根據通用串行總線類型-C 埠控制器介面規格,設定定義為TRANSMIT_BUFER緩存器。
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_RECEIVE_DETECT 根據通用串行總線類型-C 埠控制器介面規格,設定定義為RECEIVE_DETECT緩存器。
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_CONFIG_STANDARD_OUTPUT 設定根據通用串行總線類型-C 埠控制器介面規格定義的CONFIG_STANDARD_OUTPUT緩存器。
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_COMMAND 根據通用序列總線類型-C 埠控制器介面規格,設定定義為命令緩存器的值。
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_MESSAGE_HEADER_INFO 根據通用串行總線類型-C 埠控制器介面規格,設定定義為 MESSAGE_HEADER_INFO Register 的值。
IOCTL_UCMTCPCI_PORT_CONTROLLER_ALTERNATE_MODE_ENTERED 通知客戶端驅動程式輸入替代模式,讓驅動程式可以執行其他工作。
IOCTL_UCMTCPCI_PORT_CONTROLLER_ALTERNATE_MODE_EXITED 通知客戶端驅動程式已結束替代模式,讓驅動程式可以執行其他工作。
IOCTL_UCMTCPCI_PORT_CONTROLLER_DISPLAYPORT_CONFIGURED 通知客戶端驅動程式,合作夥伴裝置上的 DisplayPort 替代模式已設定針腳指派,讓驅動程式可以執行其他工作。
IOCTL_UCMTCPCI_PORT_CONTROLLER_DISPLAYPORT_HPD_STATUS_CHANGED 通知客戶端驅動程式 DisplayPort 連線的熱插即用偵測狀態已變更,讓驅動程式可以執行其他工作。
  1. 呼叫UcmTcpciPortControllerStart 以指示UcmTcpciCx啟動埠控制器。 UcmTcpciCx 會假設控制 USB Type-C 和 Power Delivery。 啟動埠控制器之後,UcmTcpciCx 可能會開始將要求放入硬體要求佇列。

處理來自埠控制器硬體的警示

範例參考:請參閱ProcessAndSendAlertsAlert.cpp

用戶端驅動程式必須處理從埠控制器硬體收到的警示 (或事件) ,並使用與事件相關的數據將它們傳送至 UcmTcpciCx。

發生硬體警示時,埠控制器硬體會驅動警示針腳高。 這會導致在步驟 2) 中註冊的用戶端驅動程式 ISR (叫用。 例程會在PASSIVE_LEVEL服務硬體中斷。 例程會判斷中斷是否為來自埠控制器硬體的警示;如果是,它會完成警示的處理,並呼叫 UcmTcpciPortControllerAlert 來通知 UcmTcpciCx。

在呼叫UcmTcpciPortControllerAlert之前,客戶端必須負責在UCMTCPCI_PORT_CONTROLLER_ALERT_DATA結構中包含與警示相關的所有相關數據。 用戶端會提供所有作用中警示的數位,因為硬體可能會同時判斷多個警示。

以下是報告 CC 狀態變更的工作範例流程。

  1. 用戶端會收到硬體警示。

  2. 用戶端會讀取 ALERT 快取器,並判斷作用中的警示類型。

  3. 用戶端會讀取 CC STATUS 快取器,並描述UCMTCPCI_PORT_CONTROLLER_ALERT_DATA中 CC STATUS 快取器的內容。 驅動程式會將 AlertType 成員設定為 UcmTcpciPortControllerAlertCCStatus 和 REGISTER 的 CCStatus 成員。

  4. 用戶端會呼叫UcmPortControllerAlert,將陣列硬體警示傳送至UcmTcpciCx。

  5. 用戶端會在用戶端擷取警示資訊) 之後,隨時清除警示 (

處理從UcmTcpciCx接收的要求

範例參考:請參閱 PortControllerInterface.cpp

在狀態機器執行過程中,UcmTcpciCx 必須將要求傳送至埠控制器。 例如,它必須設定TRANSMIT_BUFFER。 此要求會交給客戶端驅動程式。 驅動程式會使用UcmTcpciCx所提供的詳細數據來設定傳輸緩衝區。 大部分的要求都會轉譯為客戶端驅動程式讀取或寫入的硬體。 命令必須是異步的,因為 DPM 無法封鎖等候硬體傳輸完成。

UcmTcpciCx 會以 I/O 控制項程式代碼的形式傳送命令,描述客戶端驅動程式所需的取得/設定作業。 在客戶端驅動程式的佇列設定中,驅動程式已向 UcmTcpciCx 註冊其佇列。 UcmTcpciCx 會開始將架構要求物件放在需要驅動程序作業的佇列中。 I/O 控制程式代碼會列在步驟 4 的數據表中。

用戶端驅動程序必須負責及時完成要求。

當客戶端驅動程式完成要求的作業完成時,會在架構要求物件上呼叫 WdfRequestComplete,並具有完成狀態。

用戶端驅動程式可能需要傳送 I/O 要求給另一個驅動程式,才能執行硬體作業。 例如,在範例中,驅動程式會將SPB要求傳送至I2C 連線的埠控制器。 在此情況下,驅動程式無法轉送它從UcmTcpciCx收到的架構要求對象,因為要求物件在WDM IRP中可能沒有正確的堆疊位置數目。 用戶端驅動程序必須建立另一個架構要求物件,並將它轉送到另一個驅動程式。 用戶端驅動程式可以在初始化期間預先配置所需的要求物件,而不是每次從UcmTcpciCx取得要求時建立一個。 這是可行的,因為UcmTcpciCx保證在任何指定時間只會有一個未處理的要求。

另請參閱