Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Примеры кода в этом разделе показывают, как драйвер User-Mode Driver Framework (UMDF) для периферийного устройства на простой периферийной шине (SPB) получает аппаратные ресурсы, необходимые для работы устройства. В этих ресурсах содержатся сведения, используемые драйвером для установления логического подключения к устройству. Дополнительные ресурсы могут включать прерывание, а также один или несколько входных или выходных пинов GPIO. (Вывод GPIO — это контакт на устройстве контроллера ввода-вывода общего назначения, настроенном в качестве входа или выхода; дополнительные сведения см. в разделе Драйверы контроллера GPIO.) В отличие от устройства, имеющего отображение в памяти, подключенное к SPB периферийное устройство не требует выделения блока адресов системной памяти для отображения его регистров.
Этот драйвер реализует интерфейс IPnpCallbackHardware2 и регистрирует этот интерфейс с помощью UMDF во время вызова метода IDriverEntry::OnDeviceAdd . Платформа вызывает методы в интерфейсе IPnpCallbackHardware2 , чтобы уведомить драйвер изменений в состоянии питания устройства.
При восстановлении питания на периферийном устройстве, подключенном к SPB, платформа драйверов вызывает метод IPnpCallbackHardware2::OnPrepareHardware , чтобы уведомить драйвер о том, что это устройство должно быть подготовлено для использования. Во время этого вызова драйвер получает два списка аппаратных ресурсов в качестве входных параметров. Параметр pWdfResourcesRaw указывает на список необработанных ресурсов, а параметр pWdfResourcesTranslated указывает на список переведенных ресурсов. Оба параметра являются указателями на объекты IWDFCmResourceList . Преобразованные ресурсы включают идентификатор подключения , который требуется драйверу SPB для установки логического соединения с периферийным устройством, подключенным к SPB. Дополнительные сведения см. в разделе идентификаторы подключений для периферийных устройств SPB.
Для того чтобы драйвер UMDF мог получать идентификаторы подключений в списке ресурсов, INF-файл, который устанавливает драйвер, должен содержать следующую директиву в разделе DDInstall, предназначенном для WDF.
UmdfDirectHardwareAccess = AllowDirectHardwareAccess Дополнительные сведения об этой директиве см. в разделе "Указание директив WDF" в INF-файлах.
В следующем примере кода показано, как метод OnPrepareHardware драйвера получает идентификатор подключения из параметра pWdfResourcesTranslated .
BOOLEAN fConnectIdFound = FALSE;
BOOLEAN fDuplicateFound = FALSE;
LARGE_INTEGER connectionId = 0;
ULONG resourceCount;
resourceCount = pWdfResourcesTranslated->GetCount();
// Loop through the resources and save the relevant ones.
for (ULONG ix = 0; ix < resourceCount; ix++)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor;
pDescriptor = pWdfResourcesTranslated->GetDescriptor(ix);
if (pDescriptor == NULL)
{
hr = E_POINTER;
break;
}
// Determine the resource type.
switch (pDescriptor->Type)
{
case CmResourceTypeConnection:
{
// Check against the expected connection types.
UCHAR Class = pDescriptor->u.Connection.Class;
UCHAR Type = pDescriptor->u.Connection.Type;
if (Class == CM_RESOURCE_CONNECTION_CLASS_SERIAL)
{
if (Type == CM_RESOURCE_CONNECTION_TYPE_SERIAL_I2C)
{
if (fConnIdFound == FALSE)
{
// Save the SPB connection ID.
connectionId.LowPart = pDescriptor->u.Connection.IdLowPart;
connectionId.HighPart = pDescriptor->u.Connection.IdHighPart;
fConnectIdFound = TRUE;
}
else
{
fDuplicateFound = TRUE;
}
}
}
if (Class == CM_RESOURCE_CONNECTION_CLASS_GPIO)
{
// Check for GPIO pin resource.
...
}
}
break;
case CmResourceTypeInterrupt:
{
// Check for interrupt resources.
...
}
break;
default:
// Ignore all other resource descriptors.
break;
}
}
Приведенный выше пример кода копирует идентификатор подключения для подключенного к SPB периферийного устройства в переменную с именем connectionId. В следующем примере кода показано, как включить идентификатор подключения в имя пути устройства, которое можно использовать для идентификации периферийного устройства.
WCHAR szTargetPath[100];
HRESULT hres;
// Create the device path using the well-known resource hub
// path name and the connection ID.
//
// TODO: Replace this hardcoded string with the appropriate
// helper method from Reshub.h when available.
hres = StringCbPrintfW(&szTargetPath[0],
sizeof(szTargetPath),
L"\\\\.\\RESOURCE_HUB\\%0*I64x",
(size_t)(sizeof(LARGE_INTEGER) * 2),
connectionId.QuadPart);
if (FAILED(hres))
{
// Error handling
...
}
В приведенном выше примере кода записывается имя пути для подключенного к SPB периферийного устройства в szTargetPath массив. В следующем примере кода используется это имя пути устройства для открытия дескриптора файла на периферийном устройстве, подключенном к SPB.
UMDF_IO_TARGET_OPEN_PARAMS openParams;
openParams.dwShareMode = 0;
openParams.dwCreationDisposition = OPEN_EXISTING;
openParams.dwFlagsAndAttributes = FILE_FLAG_OVERLAPPED;
hres = pRemoteTarget->OpenFileByName(&szTargetPath[0],
(GENERIC_READ | GENERIC_WRITE),
&openParams);
if (FAILED(hres))
{
// Error handling
...
}
В предыдущем примере pRemoteTarget кода переменная является указателем на объект IWDFRemoteTarget . Если вызов метода IWDFRemoteTarget::OpenFileByName выполнен успешно, драйвер для подключенного к SPB периферийного устройства может использовать объект IWDFRemoteTarget для отправки запросов ввода-вывода на периферийное устройство. Прежде чем драйвер отправляет запрос на чтение, запись или IOCTL на периферийное устройство, он вызывает метод IWDFRemoteTarget::FormatRequestForRead, IWDFRemoteTarget::FormatRequestForWrite или IWDFRemoteTarget::FormatRequestForIoctl для форматирования запроса ввода-вывода. Интерфейс IWDFRemoteTarget наследует эти три метода из интерфейса IWDFIoTarget . Затем драйвер вызывает метод IWDFIoRequest::Send для отправки запроса ввода-вывода на периферийное устройство, подключенное к spB.
В следующем примере кода периферийный драйвер SPB вызывает метод Send для отправкизапроса IRP_MJ_WRITE на периферийное устройство, подключенное к SPB.
HRESULT hres;
IWDFMemory *pInputMemory = NULL;
IWDFRemoteTarget *pWdfIoRequest = NULL;
// Create a new I/O request.
if (SUCCEEDED(hres))
{
hres = pWdfDevice->CreateRequest(NULL,
pWdfDevice,
&pWdfIoRequest);
if (FAILED(hres))
{
// Error handling
...
}
}
// Allocate memory for the input buffer.
if (SUCCEEDED(hres))
{
hres = pWdfDriver->CreatePreallocatedWdfMemory(pInBuffer,
inBufferSize,
NULL,
pWdfIoRequest,
&pInputMemory);
if (FAILED(hres))
{
// Error handling
...
}
// After this call, the parent holds the only reference.
pWdfMemory->Release();
}
// Format the I/O request for a write operation.
if (SUCCEEDED(hres))
{
hres = pRemoteTarget->FormatRequestForWrite(pWdfIoRequest,
NULL,
pInputMemory,
NULL,
0);
if (FAILED(hres))
{
// Error handling
...
}
}
// Send the request to the SPB controller.
if (SUCCEEDED(hres))
{
ULONG Flags = fSynchronous ? WDF_REQUEST_SEND_OPTION_SYNCHRONOUS : 0;
// Set the I/O completion callback.
if (!fSynchronous)
{
pWdfIoRequest->SetCompletionCallback(pCallback, NULL);
}
hres = pWdfIoRequest->Send(pRemoteTarget, Flags, 0);
if (FAILED(hres))
{
// Error handling
...
}
}
if (fSynchronous || FAILED(hres))
{
pWdfIoRequest->DeleteWdfObject();
SAFE_RELEASE(pWdfIoRequest);
}
В приведенном выше примере кода выполняется следующее:
- Переменная
pWdfDevice— это указатель на интерфейс IWDFDevice объекта устройства платформы, представляющего подключенное к SPB периферийное устройство. Метод IWDFDevice::CreateRequest создает запрос ввода-вывода и инкапсулирует этот запрос в экземпляре интерфейса IWDFIoRequest , на который указываетpWdfIoRequestпеременная. - Переменная
pWdfDriver— это указатель на интерфейс IWDFDriver объекта драйвера платформы, представляющего периферийный драйвер SPB. ПеременныеpInBufferиinBufferSizeуказывают адрес и размер входного буфера, содержащего данные для запроса на запись. Метод IWDFDriver::CreatePreallocatedWdfMemory создает объект памяти платформы для входного буфера и назначает объект IWDFIoRequest родительским объектом объекта памяти, указанный вpWdfIoRequest(так что объект памяти автоматически освобождается при освобождении его родителя). Когда драйвер вызывает метод Release , чтобы освободить локальную ссылку на объект памяти, родительский объект содержит единственную ссылку на этот объект. - Переменная
pWdfRemoteTarget— это удаленный целевой указатель, полученный из вызова OpenFileByName в предыдущем примере кода. Метод IWDFRemoteTarget::FormatRequestForWrite форматирует запрос ввода-вывода для операции записи. - Переменная
fSynchronousимеет значение TRUE , если запрос на запись отправляется синхронно и имеет значение FALSE , если он должен отправляться асинхронно. ПеременнаяpCallback— это указатель на ранее созданный интерфейс IRequestCallbackRequestCompletion . Если запрос отправляется асинхронно, вызов метода IWDFIoRequest::SetCompletionCallback регистрирует этот интерфейс. Позже вызывается метод IRequestCallbackRequestCompletion::OnCompletion , чтобы уведомить драйвер при асинхронном завершении запроса. - Метод Send отправляет отформатированный запрос на запись на периферийное устройство, подключенное к SPB. Переменная
Flagsуказывает, следует ли отправлять запрос на запись синхронно или асинхронно. - Если запрос отправляется синхронно, метод IWDFIoRequest::DeleteWdfObject удаляет как объект запроса ввода-вывода, на который указывает
pWdfIoRequest, так и дочерний объект, на который указываетpInputMemory. Интерфейс IWDFIoRequest наследует этот метод из интерфейса IWDFObject . Если запрос отправляется асинхронно, вызов метода DeleteWdfObject должен выполняться позже в методе OnCompletion драйвера.
Альтернативная реализация предыдущего примера кода может создавать объекты IWDFIoRequest и IWDFMemory во время инициализации драйвера и многократно использовать эти же объекты вместо создания и удаления новых объектов при каждом отправке запроса ввода-вывода. Дополнительные сведения см. в разделе IWDFIoRequest2::Reuse и IWDFMemory::SetBuffer.
Кроме того, альтернативная реализация может проверить код состояния ввода-вывода из запроса ввода-вывода, если вызов отправки выполнен успешно. Дополнительные сведения см. в разделе IWDFIoRequest::GetCompletionParams.