Запись драйвера контроллера порта USB Type-C
Необходимо написать драйвер контроллера порта USB Type-C, если оборудование USB Type-C реализует физический уровень USB-C или power delivery (PD), но не реализует конечные компьютеры, необходимые для доставки питания.
В Windows 10 версии 1703 архитектура USB Type-C была улучшена для поддержки аппаратных конструкций, которые реализуют физический уровень USB-C или Power Delivery (PD), но не имеют соответствующей реализации политики PD или уровня протокола. Для этих проектов Windows 10 версии 1703 предоставляет программный модуль политики PD и диспетчер политик устройств с помощью нового расширения класса " Usb Connector Manager Type-C Port Controller Interface Interface Interface Interface Extension" (UcmTcpciCx). Драйвер клиента, написанный IHV или OEM/ODM, взаимодействует с UcmTcpciCx для предоставления сведений об аппаратных событиях, необходимых для работы обработчика политик PD и диспетчера политик устройств в UcmTcpciCx. Эта связь включается с помощью набора программных интерфейсов, описанных в этой статье и в справочном разделе.
Расширение класса UcmTcpciCx само по себе является клиентским драйвером UcmCx. Политики, касающиеся контрактов питания и ролей данных, принимаются в UcmCx и перенаправляются в UcmTcpciCx. UcmTcpciCx реализует эти политики и управляет компьютерами состояний Type-C и PD, используя интерфейс контроллера порта, предоставляемый драйвером клиента UcmTcpciCx.
Сводка
- Службы, предоставляемые расширением класса UcmTcpci
- Ожидаемое поведение драйвера клиента
Официальные спецификации
- Спецификация интерфейса контроллера порта USB Type-C
- Спецификации USB 3.1 и USB Type-C
- USB Power Delivery
Важные API
Справочник по расширениям класса драйвера интерфейса контроллера порта USB Type-C
Шаблон драйвера клиента UcmTcpciCx
Шаблон драйвера клиента UcmTcpciCx
Подготовка к работе
Определите тип драйвера, необходимого для записи, в зависимости от того, реализует ли ваш аппаратный или встроенное ПО конечный автомат PD. Дополнительные сведения см. в статье Разработка драйверов Windows для соединителей USB Type-C.
Установите Windows 10 для настольных компьютеров (Домашняя, Pro, Корпоративная и для образовательных учреждений) на целевом компьютере или Windows 10 Mobile с соединителем USB Type-C.
Установите последнюю версию пакета драйверов Windows (WDK) на компьютере разработчика. В комплекте есть необходимые файлы заголовков и библиотеки для записи драйвера клиента. В частности, вам потребуется:
- Библиотека заглушки (UcmTcpciCxStub.lib). Библиотека преобразует вызовы, сделанные драйвером клиента, и передает их в расширение класса.
- Файл заголовка UcmTcpciCx.h.
Драйвер клиента работает в режиме ядра и привязывается к библиотеке KMDF 1.15.
Решите, поддерживает ли драйвер клиента оповещения.
Контроллер порта не обязательно должен быть совместим с TCPCI. Интерфейс фиксирует возможности любого контроллера порта Type-C. Написание клиентского драйвера UcmTcpciCx для оборудования, не совместимого с TCPCI, включает сопоставление значений регистров и команд в спецификации TCPCI с значениями оборудования.
Большинство контроллеров TCPCI подключены к I2C. Драйвер клиента использует ресурс подключения последовательной периферийной шины (SPB) и линию прерывания для связи с оборудованием. Драйвер использует программный интерфейс расширения SPB Framework (SpbCx). Ознакомьтесь с SpbCx, прочитав следующие статьи:
- [Руководство по проектированию драйвера простой периферийной шины (SPB)]
- [Справочник по программированию драйверов SPB]
Ознакомьтесь с Windows Driver Foundation (WDF). Рекомендуемое чтение: Разработка драйверов с помощью Windows Driver Foundation, написанная Пенни Орвик и Гай Смит.
Поведение расширения класса 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. Это статическое описание возможностей системы и каждого из ее соединителей USB Type-C, которое DPM использует для определения политик для реализации.
Отделяя описание возможностей системы от драйвера клиента для контроллеров портов, конструкция позволяет использовать драйвер в разных системах с различными возможностями. UcmCx, а не UcmTcpciCx, взаимодействует с хранилищем возможностей. UcmTcpciCx (или его клиентский драйвер) не взаимодействует с хранилищем возможностей.
Везде, где это применимо, информация из хранилища возможностей переопределяет сведения, поступающие непосредственно из драйвера клиента контроллера порта. Например, контроллер порта может выполнять операции только приемника, и драйвер клиента сообщает эти сведения. Однако в остальной части системы может быть неправильно настроена операция только для приемника. В этом случае изготовитель системы может сообщить, что соединители могут выполнять операции только для источника в хранилище возможностей. Параметр в хранилище возможностей имеет приоритет над сообщаемой информацией о драйвере.
Уведомите UcmTcpciCx всеми соответствующими данными, связанными с оповещениями.
Необязательный элемент. Выполните дополнительную обработку после ввода или выхода из альтернативного режима. Драйвер информируется об этих состояниях расширением класса через запросы IOCTL.
Регистрация драйвера клиента с помощью UcmTcpciCx
Пример справки: см. EvtPrepareHardware
в Device.cpp
.
В реализации EVT_WDF_DRIVER_DEVICE_ADD вызовите UcmTcpciDeviceInitInitialize, чтобы инициализировать WDFDEVICE_INIT непрозрачную структуру. Вызов связывает драйвер клиента с платформой.
После создания объекта устройства платформы (WDFDEVICE) вызовите UcmTcpciDeviceInitialize, чтобы зарегистрировать делитель клиента в UcmTcpciCx.
Инициализация канала связи I2C с оборудованием контроллера порта
Пример справки: см. EvtCreateDevice
в Device.cpp
.
В реализации EVT_WDF_DEVICE_PREPARE_HARDWARE ознакомьтесь с аппаратными ресурсами, чтобы открыть коммуникационный канал. Это необходимо для получения возможностей PD и получения уведомлений об оповещениях.
Большинство контроллеров TCPCI подключены к I2C. В эталонном примере драйвер клиента открывает канал I2 с помощью программного интерфейса расширения SPB Framework (SpbCx).
Драйвер клиента перечисляет аппаратные ресурсы, вызывая WdfCmResourceListGetDescriptor.
Оповещения принимаются в виде прерываний. Таким образом, драйвер создает объект прерывания платформы и регистрирует ISR, обрабатывающий оповещения. ISR выполняет аппаратные операции чтения и записи, которые блокируются до завершения доступа к оборудованию. Поскольку ожидание в DIRQL неприемлемо, драйвер выполняет ISR на PASSIVE_LEVEL.
Инициализация возможностей type-C и PD контроллера порта
Пример справки: см. EvtDeviceD0Entry
в Device.cpp
.
В реализации EVT_WDF_DEVICE_D0_EXIT:
Обмен данными с оборудованием контроллера порта и получение сведений об идентификации и возможностях устройства путем чтения различных регистров.
Инициализируйте UCMTCPCI_PORT_CONTROLLER_IDENTIFICATION и UCMTCPCI_PORT_CONTROLLER_CAPABILITIES с помощью полученных сведений.
Инициализируйте UCMTCPCI_PORT_CONTROLLER_CONFIG структуру с приведенными выше сведениями, передавая инициализированные структуры в UCMTCPCI_PORT_CONTROLLER_CONFIG_INIT.
Вызовите UcmTcpciPortControllerCreate, чтобы создать объект контроллера порта и получить дескриптор UCMTCPCIPORTCONTROLLER.
Настройка объекта очереди платформы для получения запросов от UcmTcpciCx
Пример справки: см. EvtDeviceD0Entry
в Device.cpp
и HardwareRequestQueueInitialize
в Queue.cpp
.
В реализации EVT_WDF_DEVICE_D0_EXIT создайте объект очереди платформы, вызвав WdfIoQueueCreate. В этом вызове необходимо зарегистрировать реализацию обратного вызова для обработки запросов IOCTL, отправленных UcmTpciCx. Драйвер клиента может использовать управляемую питанием очередь.
Во время выполнения конечных машин Type-C и PD UcmTpciCx отправляет команды драйверу клиента для выполнения. UcmTcpciCx гарантирует не более одного запроса контроллера порта в любой момент времени.
Вызовите UcmTcpciPortControllerSetHardwareRequestQueue, чтобы зарегистрировать новый объект очереди платформы в UcmTpciCx. После успешного вызова UcmTcpciCx помещает объекты очереди платформы (WDFREQUEST) в эту очередь, когда требуется действие от драйвера.
Реализуйте функцию обратного вызова EvtIoDeviceControl для обработки этих ioCTL.
Код элемента управления | Описание |
---|---|
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. |
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_TRANSMIT_BUFFER | Задает регистр TRANSMIT_BUFER, определенный в соответствии со спецификацией интерфейса контроллера порта Типа C универсальной последовательной шины. |
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_RECEIVE_DETECT | Задает регистр RECEIVE_DETECT, определенный в соответствии со спецификацией интерфейса контроллера порта Универсальной последовательной шины типа C. |
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_CONFIG_STANDARD_OUTPUT | Задает регистр CONFIG_STANDARD_OUTPUT, определенный в соответствии со спецификацией интерфейса контроллера порта Типа C универсальной последовательной шины. |
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_COMMAND | Задает значение регистра команд, определенное в соответствии со спецификацией интерфейса контроллера порта Универсальной последовательной шины типа C. |
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_MESSAGE_HEADER_INFO | Задает значение MESSAGE_HEADER_INFO Register, определенное в соответствии со спецификацией интерфейса контроллера порта Типа C универсальной последовательной шины. |
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 изменилось, чтобы драйвер смог выполнять другие задачи. |
- Вызовите UcmTcpciPortControllerStart, чтобы указать UcmTcpciCx запустить контроллер порта. UcmTcpciCx предполагает управление USB Type-C и питанием. После запуска контроллера порта UcmTcpciCx может начать помещать запросы в очередь запросов оборудования.
Обработка оповещений с оборудования контроллера порта
Пример справочника: см. ProcessAndSendAlerts
в Alert.cpp
Драйвер клиента должен обрабатывать оповещения (или события), полученные от оборудования контроллера портов, и отправлять их в UcmTcpciCx с данными, связанными с событием.
При возникновении аппаратного оповещения контроллер порта обеспечивает высокий уровень пин-кода ALERT. Это приводит к вызову ISR драйвера клиента (зарегистрированного на шаге 2). Обычное обслуживание аппаратного прерывания на PASSIVE_LEVEL. Подпрограмма определяет, является ли прерывание оповещением от оборудования контроллера порта; Если да, он завершает обработку оповещения и уведомляет UcmTcpciCx путем вызова UcmTcpciPortControllerAlert.
Перед вызовом UcmTcpciPortControllerAlert клиент отвечает за включение всех соответствующих данных, связанных с оповещением, в структуру UCMTCPCI_PORT_CONTROLLER_ALERT_DATA. Клиент предоставляет массив всех активных оповещений, так как существует вероятность того, что оборудование может одновременно утверждать несколько оповещений.
Ниже приведен пример потока задач для отчета об изменениях в статусе CC.
Клиент получает оповещение оборудования.
Клиент считывает регистр ALERT и определяет активные типы оповещений.
Клиент считывает регистр CC STATUS и описывает содержимое регистра CC STATUS в UCMTCPCI_PORT_CONTROLLER_ALERT_DATA. Драйвер задает для элемента AlertType значение UcmTcpciPortControllerAlertCCStatus и ccStatus, являющегося членом регистра.
Клиент вызывает UcmPortControllerAlert для отправки оповещений оборудования массива в UcmTcpciCx.
Клиент очищает оповещение (это может произойти в любое время после получения клиентом сведений об оповещении).
Обработка запросов, полученных от UcmTcpciCx
Пример справочника: см. раздел PortControllerInterface.cpp
В рамках выполнения конечного автомата UcmTcpciCx должен отправлять запросы на контроллер порта. Например, необходимо задать TRANSMIT_BUFFER. Этот запрос передается драйверу клиента. Драйвер задает буфер передачи со сведениями, предоставленными UcmTcpciCx. Большинство этих запросов преобразуются в аппаратное чтение или запись клиентским драйвером. Команды должны быть асинхронными, так как DPM не может блокировать ожидание завершения передачи оборудования.
UcmTcpciCx отправляет команды в виде управляющего кода ввода-вывода, описывающего операцию get/set, необходимую драйвером клиента. При настройке очереди драйвера клиента драйвер зарегистрировал свою очередь с помощью UcmTcpciCx. UcmTcpciCx начинает размещать объекты запросов платформы в очереди, требуемой от драйвера. Коды элементов управления вводом-выводом перечислены в таблице на шаге 4.
Ответственность за своевременное выполнение запросов лежит на драйвере клиента.
Драйвер клиента вызывает WdfRequestComplete для объекта запроса платформы с состоянием завершения после завершения запрошенной операции.
Драйверу клиента может потребоваться отправить запрос ввода-вывода другому драйверу для выполнения аппаратной операции. Например, в примере драйвер отправляет запрос SPB контроллеру порта, подключенного к I2C. В этом случае драйвер не может переслать объект запроса платформы, полученный из UcmTcpciCx, так как объект запроса может иметь неправильное количество расположений стека в WDM IRP. Драйвер клиента должен создать другой объект запроса платформы и перенаправить его другому драйверу. Драйвер клиента может предварительно выделить объекты запроса, необходимые ему во время инициализации, а не создавать каждый раз, когда получает запрос от UcmTcpciCx. Это возможно, так как UcmTcpciCx гарантирует, что в любой момент времени будет не выполнен только один запрос.