diff options
| author | Wei Mao <[email protected]> | 2017-03-17 19:47:04 -0700 |
|---|---|---|
| committer | Wei Mao <[email protected]> | 2017-03-17 19:47:04 -0700 |
| commit | 1a3e0d580380e58bf336a242d2affc8a1e2d1ddf (patch) | |
| tree | bf5d9c5b0b4cba1b81726b9f78c4d5ff5c636fea /SPB/SpbTestTool/sys | |
| parent | da21c8784c83c5fd614f3030323e229d6a5fb10e (diff) | |
Fix cases
Diffstat (limited to 'SPB/SpbTestTool/sys')
| -rw-r--r-- | SPB/SpbTestTool/sys/SpbTestTool.vcxproj | 197 | ||||
| -rw-r--r-- | SPB/SpbTestTool/sys/SpbTestTool.vcxproj.Filters | 42 | ||||
| -rw-r--r-- | SPB/SpbTestTool/sys/device.cpp | 848 | ||||
| -rw-r--r-- | SPB/SpbTestTool/sys/device.h | 43 | ||||
| -rw-r--r-- | SPB/SpbTestTool/sys/driver.cpp | 414 | ||||
| -rw-r--r-- | SPB/SpbTestTool/sys/driver.h | 36 | ||||
| -rw-r--r-- | SPB/SpbTestTool/sys/internal.h | 144 | ||||
| -rw-r--r-- | SPB/SpbTestTool/sys/peripheral.cpp | 1683 | ||||
| -rw-r--r-- | SPB/SpbTestTool/sys/peripheral.h | 104 | ||||
| -rw-r--r-- | SPB/SpbTestTool/sys/resource.rc | 11 | ||||
| -rw-r--r-- | SPB/SpbTestTool/sys/spbtestioctl.h | 50 | ||||
| -rw-r--r-- | SPB/SpbTestTool/sys/spbtesttool.asl | 26 | ||||
| -rw-r--r-- | SPB/SpbTestTool/sys/spbtesttool.inx | bin | 0 -> 4688 bytes | |||
| -rw-r--r-- | SPB/SpbTestTool/sys/trace.h | 54 |
14 files changed, 3652 insertions, 0 deletions
diff --git a/SPB/SpbTestTool/sys/SpbTestTool.vcxproj b/SPB/SpbTestTool/sys/SpbTestTool.vcxproj new file mode 100644 index 00000000..48b8d23c --- /dev/null +++ b/SPB/SpbTestTool/sys/SpbTestTool.vcxproj @@ -0,0 +1,197 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{028ED946-EE58-43F7-834B-297119CE4720}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{775D4A74-74A0-4CBD-B20E-06D7EAEEAB7C}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems"> + <ClCompile Include="driver.cpp; device.cpp; peripheral.cpp"> + <WppEnabled>true</WppEnabled> + <WppKernelMode>true</WppKernelMode> + <WppScanConfigurationData>trace.h</WppScanConfigurationData> + <WppTraceFunction>Trace(LEVEL,FLAGS,MSG,...)</WppTraceFunction> + </ClCompile> + <Inf Include=".\SpbTestTool.inx"> + <Architecture>$(InfArch)</Architecture> + <SpecifyArchitecture>true</SpecifyArchitecture> + <CopyOutput>.\$(IntDir)\SpbTestTool.inf</CopyOutput> + </Inf> + <OtherWpp Include="resource.rc"> + <WppEnabled>true</WppEnabled> + <WppKernelMode>true</WppKernelMode> + <WppScanConfigurationData>trace.h</WppScanConfigurationData> + <WppTraceFunction>Trace(LEVEL,FLAGS,MSG,...)</WppTraceFunction> + </OtherWpp> + </ItemGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>SpbTestTool</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>SpbTestTool</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>SpbTestTool</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>SpbTestTool</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SPB_INC_PATH)\$(SPB_VERSION_MAJOR).$(SPB_VERSION_MINOR)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SPB_INC_PATH)\$(SPB_VERSION_MAJOR).$(SPB_VERSION_MINOR)</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SPB_INC_PATH)\$(SPB_VERSION_MAJOR).$(SPB_VERSION_MINOR)</AdditionalIncludeDirectories> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SPB_INC_PATH)\$(SPB_VERSION_MAJOR).$(SPB_VERSION_MINOR)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SPB_INC_PATH)\$(SPB_VERSION_MAJOR).$(SPB_VERSION_MINOR)</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SPB_INC_PATH)\$(SPB_VERSION_MAJOR).$(SPB_VERSION_MINOR)</AdditionalIncludeDirectories> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SPB_INC_PATH)\$(SPB_VERSION_MAJOR).$(SPB_VERSION_MINOR)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SPB_INC_PATH)\$(SPB_VERSION_MAJOR).$(SPB_VERSION_MINOR)</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SPB_INC_PATH)\$(SPB_VERSION_MAJOR).$(SPB_VERSION_MINOR)</AdditionalIncludeDirectories> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SPB_INC_PATH)\$(SPB_VERSION_MAJOR).$(SPB_VERSION_MINOR)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SPB_INC_PATH)\$(SPB_VERSION_MAJOR).$(SPB_VERSION_MINOR)</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SPB_INC_PATH)\$(SPB_VERSION_MAJOR).$(SPB_VERSION_MINOR)</AdditionalIncludeDirectories> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ResourceCompile Include="resource.rc" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/SPB/SpbTestTool/sys/SpbTestTool.vcxproj.Filters b/SPB/SpbTestTool/sys/SpbTestTool.vcxproj.Filters new file mode 100644 index 00000000..5c06c882 --- /dev/null +++ b/SPB/SpbTestTool/sys/SpbTestTool.vcxproj.Filters @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{758F79B8-0F82-4FC8-8C5B-0875A36D16C8}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{BB2FE3BE-C3C8-4C98-A8FA-CE4AE906C0BC}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{B0A30E36-D110-468D-A945-84112CBE25B8}</UniqueIdentifier> + </Filter> + <Filter Include="Driver Files"> + <Extensions>inf;inv;inx;mof;mc;</Extensions> + <UniqueIdentifier>{A2DE30AB-8982-454D-976D-E8F3EB8B4777}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="device.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="driver.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="peripheral.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <Inf Include=".\SpbTestTool.inx"> + <Filter>Driver Files</Filter> + </Inf> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="resource.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/SPB/SpbTestTool/sys/device.cpp b/SPB/SpbTestTool/sys/device.cpp new file mode 100644 index 00000000..28455aa6 --- /dev/null +++ b/SPB/SpbTestTool/sys/device.cpp @@ -0,0 +1,848 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + device.cpp + +Abstract: + + This module contains WDF device initialization + functions for the peripheral driver. + +Environment: + + kernel-mode only + +Revision History: + +--*/ + +#include "internal.h" +#include "peripheral.h" +#include "device.h" + +#include "device.tmh" + + +///////////////////////////////////////////////// +// +// WDF callbacks. +// +///////////////////////////////////////////////// + +NTSTATUS +OnPrepareHardware( + _In_ WDFDEVICE FxDevice, + _In_ WDFCMRESLIST FxResourcesRaw, + _In_ WDFCMRESLIST FxResourcesTranslated + ) +/*++ + + Routine Description: + + This routine caches the SPB resource connection ID. + + Arguments: + + FxDevice - a handle to the framework device object + FxResourcesRaw - list of translated hardware resources that + the PnP manager has assigned to the device + FxResourcesTranslated - list of raw hardware resources that + the PnP manager has assigned to the device + + Return Value: + + Status + +--*/ +{ + FuncEntry(TRACE_FLAG_WDFLOADING); + + PDEVICE_CONTEXT pDevice = GetDeviceContext(FxDevice); + BOOLEAN fSpbResourceFound = FALSE; + BOOLEAN fInterruptResourceFound = FALSE; + ULONG interruptIndex = 0; + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(FxResourcesRaw); + + // + // Parse the peripheral's resources. + // + + ULONG resourceCount = WdfCmResourceListGetCount(FxResourcesTranslated); + + for(ULONG i = 0; i < resourceCount; i++) + { + PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor; + UCHAR Class; + UCHAR Type; + + pDescriptor = WdfCmResourceListGetDescriptor( + FxResourcesTranslated, i); + + switch (pDescriptor->Type) + { + case CmResourceTypeConnection: + + // + // Look for I2C or SPI resource and save connection ID. + // + + Class = pDescriptor->u.Connection.Class; + Type = pDescriptor->u.Connection.Type; + + if ((Class == CM_RESOURCE_CONNECTION_CLASS_SERIAL) && + ((Type == CM_RESOURCE_CONNECTION_TYPE_SERIAL_I2C) || + (Type == CM_RESOURCE_CONNECTION_TYPE_SERIAL_SPI))) + { + if (fSpbResourceFound == FALSE) + { + pDevice->PeripheralId.LowPart = + pDescriptor->u.Connection.IdLowPart; + pDevice->PeripheralId.HighPart = + pDescriptor->u.Connection.IdHighPart; + + fSpbResourceFound = TRUE; + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_WDFLOADING, + "SPB resource found with ID=0x%llx", + pDevice->PeripheralId.QuadPart); + } + else + { + Trace( + TRACE_LEVEL_WARNING, + TRACE_FLAG_WDFLOADING, + "Duplicate SPB resource found with ID=0x%llx", + pDevice->PeripheralId.QuadPart); + } + } + + break; + + case CmResourceTypeInterrupt: + + if (fInterruptResourceFound == FALSE) + { + fInterruptResourceFound = TRUE; + interruptIndex = i; + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_WDFLOADING, + "Interrupt resource found"); + } + else + { + Trace( + TRACE_LEVEL_WARNING, + TRACE_FLAG_WDFLOADING, + "Duplicate interrupt resource found"); + } + + break; + + default: + + // + // Ignoring all other resource types. + // + + break; + } + } + + // + // An SPB resource is required. + // + + if (fSpbResourceFound == FALSE) + { + status = STATUS_NOT_FOUND; + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_WDFLOADING, + "SPB resource not found - %!STATUS!", + status); + } + + // + // Create the interrupt if an interrupt + // resource was found. + // + + if (NT_SUCCESS(status)) + { + if ((pDevice->ConnectInterrupt == TRUE) && + (fInterruptResourceFound == TRUE)) + { + WDF_INTERRUPT_CONFIG interruptConfig; + WDF_INTERRUPT_CONFIG_INIT( + &interruptConfig, + OnInterruptIsr, + NULL); + + interruptConfig.PassiveHandling = TRUE; + interruptConfig.InterruptTranslated = WdfCmResourceListGetDescriptor( + FxResourcesTranslated, + interruptIndex); + interruptConfig.InterruptRaw = WdfCmResourceListGetDescriptor( + FxResourcesRaw, + interruptIndex); + + status = WdfInterruptCreate( + pDevice->FxDevice, + &interruptConfig, + WDF_NO_OBJECT_ATTRIBUTES, + &pDevice->Interrupt); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_WDFLOADING, + "WdfInterruptCreate failed - %!STATUS!", + status); + } + + if (NT_SUCCESS(status)) + { + KeInitializeEvent( + &pDevice->IsrWaitEvent, + SynchronizationEvent, + FALSE); + } + } + } + + FuncExit(TRACE_FLAG_WDFLOADING); + + return status; +} + +NTSTATUS +OnReleaseHardware( + _In_ WDFDEVICE FxDevice, + _In_ WDFCMRESLIST FxResourcesTranslated + ) +/*++ + + Routine Description: + + Arguments: + + FxDevice - a handle to the framework device object + FxResourcesTranslated - list of raw hardware resources that + the PnP manager has assigned to the device + + Return Value: + + Status + +--*/ +{ + FuncEntry(TRACE_FLAG_WDFLOADING); + + PDEVICE_CONTEXT pDevice = GetDeviceContext(FxDevice); + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(FxResourcesTranslated); + + if (pDevice->Interrupt != nullptr) + { + WdfObjectDelete(pDevice->Interrupt); + } + + FuncExit(TRACE_FLAG_WDFLOADING); + + return status; +} + +NTSTATUS +OnD0Entry( + _In_ WDFDEVICE FxDevice, + _In_ WDF_POWER_DEVICE_STATE FxPreviousState + ) +/*++ + + Routine Description: + + This routine allocates objects needed by the driver. + + Arguments: + + FxDevice - a handle to the framework device object + FxPreviousState - previous power state + + Return Value: + + Status + +--*/ +{ + FuncEntry(TRACE_FLAG_WDFLOADING); + + UNREFERENCED_PARAMETER(FxPreviousState); + + PDEVICE_CONTEXT pDevice = GetDeviceContext(FxDevice); + NTSTATUS status; + + // + // Create the SPB target. + // + + WDF_OBJECT_ATTRIBUTES targetAttributes; + WDF_OBJECT_ATTRIBUTES_INIT(&targetAttributes); + + status = WdfIoTargetCreate( + pDevice->FxDevice, + &targetAttributes, + &pDevice->SpbController); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_WDFLOADING, + "Failed to create IO target - %!STATUS!", + status); + } + + // + // InputMemory will be created when an SPB request is about to be + // sent. Indicate that it is not yet initialized. + // + + pDevice->InputMemory = WDF_NO_HANDLE; + + // + // Create the SPB request. + // + + if (NT_SUCCESS(status)) + { + WDF_OBJECT_ATTRIBUTES requestAttributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&requestAttributes, REQUEST_CONTEXT); + + status = WdfRequestCreate( + &requestAttributes, + nullptr, + &pDevice->SpbRequest); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_WDFLOADING, + "Failed to create IO request - %!STATUS!", + status); + } + + if (NT_SUCCESS(status)) + { + PREQUEST_CONTEXT pRequest = GetRequestContext( + pDevice->SpbRequest); + + pRequest->FxDevice = pDevice->FxDevice; + pRequest->IsSpbSequenceRequest = FALSE; + pRequest->SequenceWriteLength = 0; + } + } + + FuncExit(TRACE_FLAG_WDFLOADING); + + return status; +} + +NTSTATUS +OnD0Exit( + _In_ WDFDEVICE FxDevice, + _In_ WDF_POWER_DEVICE_STATE FxPreviousState + ) +/*++ + + Routine Description: + + This routine destroys objects needed by the driver. + + Arguments: + + FxDevice - a handle to the framework device object + FxPreviousState - previous power state + + Return Value: + + Status + +--*/ +{ + FuncEntry(TRACE_FLAG_WDFLOADING); + + UNREFERENCED_PARAMETER(FxPreviousState); + + PDEVICE_CONTEXT pDevice = GetDeviceContext(FxDevice); + + if (pDevice->SpbController != WDF_NO_HANDLE) + { + WdfObjectDelete(pDevice->SpbController); + pDevice->SpbController = WDF_NO_HANDLE; + } + + if (pDevice->SpbRequest != WDF_NO_HANDLE) + { + WdfObjectDelete(pDevice->SpbRequest); + pDevice->SpbRequest = WDF_NO_HANDLE; + } + + if (pDevice->InputMemory != WDF_NO_HANDLE) + { + WdfObjectDelete(pDevice->InputMemory); + pDevice->InputMemory = WDF_NO_HANDLE; + } + + FuncExit(TRACE_FLAG_WDFLOADING); + + return STATUS_SUCCESS; +} + +VOID +OnFileCleanup( + _In_ WDFFILEOBJECT FileObject + ) +/*++ + + Routine Description: + + This routine is called before a device is stopped. + + Arguments: + + FileObject - a handle to the framework file object + + Return Value: + + None + +--*/ +{ + FuncEntry(TRACE_FLAG_WDFLOADING); + + WDFDEVICE device; + PDEVICE_CONTEXT pDevice; + + device = WdfFileObjectGetDevice(FileObject); + pDevice = GetDeviceContext(device); + + // + // The client app has closed the device handle, + // make sure the SPB target is closed. + // + + SpbPeripheralClose(pDevice); + + // + // Signal the ISR wait event just + // in case the callback is stalled. + // + + if (pDevice->Interrupt != nullptr) + { + KeSetEvent( + &pDevice->IsrWaitEvent, + IO_NO_INCREMENT, + FALSE); + } + + FuncExit(TRACE_FLAG_WDFLOADING); +} + +VOID +OnTopLevelIoDefault( + _In_ WDFQUEUE FxQueue, + _In_ WDFREQUEST FxRequest + ) +/*++ + + Routine Description: + + Accepts all incoming requests and pends or forwards appropriately. + + Arguments: + + FxQueue - Handle to the framework queue object that is associated with the + I/O request. + FxRequest - Handle to a framework request object. + + Return Value: + + None. + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + UNREFERENCED_PARAMETER(FxQueue); + + WDFDEVICE device; + PDEVICE_CONTEXT pDevice; + WDF_REQUEST_PARAMETERS params; + NTSTATUS status; + + device = WdfIoQueueGetDevice(FxQueue); + pDevice = GetDeviceContext(device); + + WDF_REQUEST_PARAMETERS_INIT(¶ms); + + WdfRequestGetParameters(FxRequest, ¶ms); + + if ((params.Type == WdfRequestTypeDeviceControl) && + (params.Parameters.DeviceIoControl.IoControlCode == + IOCTL_SPBTESTTOOL_WAIT_ON_INTERRUPT)) + { + SpbPeripheralWaitOnInterrupt(pDevice, FxRequest); + } + else + { + status = WdfRequestForwardToIoQueue(FxRequest, pDevice->SpbQueue); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to forward WDFREQUEST %p to SPB queue %p - %!STATUS!", + FxRequest, + pDevice->SpbQueue, + status); + + WdfRequestComplete(FxRequest, status); + } + } + + FuncExit(TRACE_FLAG_SPBAPI); +} + +VOID +OnIoRead ( + _In_ WDFQUEUE FxQueue, + _In_ WDFREQUEST FxRequest, + _In_ size_t Length + ) +/*++ + + Routine Description: + + Performs read from the toaster device. This event is called when the + framework receives IRP_MJ_READ requests. + + Arguments: + + FxQueue - Handle to the framework queue object that is associated with the + I/O request. + FxRequest - Handle to a framework request object. + Length - Length of the data buffer associated with the request. + By default, the queue does not dispatch zero length read & write + requests to the driver and instead to complete such requests with + status success. So we will never get a zero length request. + + Return Value: + + None. + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + UNREFERENCED_PARAMETER(Length); + + WDFDEVICE device; + PDEVICE_CONTEXT pDevice; + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Read request %p received", + FxRequest); + + device = WdfIoQueueGetDevice(FxQueue); + pDevice = GetDeviceContext(device); + + // + // Send the read request. + // + + SpbPeripheralRead(pDevice,FxRequest); + + FuncExit(TRACE_FLAG_SPBAPI); +} + +VOID +OnIoWrite ( + _In_ WDFQUEUE FxQueue, + _In_ WDFREQUEST FxRequest, + _In_ size_t Length + ) +/*++ + +Routine Description: + + Performs write to the toaster device. This event is called when the + framework receives IRP_MJ_WRITE requests. + +Arguments: + + Queue - Handle to the framework queue object that is associated + with the I/O request. + Request - Handle to a framework request object. + Lenght - Length of the data buffer associated with the request. + The default property of the queue is to not dispatch + zero lenght read & write requests to the driver and + complete is with status success. So we will never get + a zero length request. + +Return Value: + + None +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + UNREFERENCED_PARAMETER(Length); + + WDFDEVICE device; + PDEVICE_CONTEXT pDevice; + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Write request %p received", + FxRequest); + + device = WdfIoQueueGetDevice(FxQueue); + pDevice = GetDeviceContext(device); + + // + // Send the write request. + // + + SpbPeripheralWrite(pDevice,FxRequest); + + FuncExit(TRACE_FLAG_SPBAPI); +} + +VOID +OnIoDeviceControl( + _In_ WDFQUEUE FxQueue, + _In_ WDFREQUEST FxRequest, + _In_ size_t OutputBufferLength, + _In_ size_t InputBufferLength, + _In_ ULONG IoControlCode + ) +/*++ +Routine Description: + + This event is called when the framework receives IRP_MJ_DEVICE_CONTROL + requests from the system. + +Arguments: + + FxQueue - Handle to the framework queue object that is associated + with the I/O request. + FxRequest - Handle to a framework request object. + OutputBufferLength - length of the request's output buffer, + if an output buffer is available. + InputBufferLength - length of the request's input buffer, + if an input buffer is available. + IoControlCode - the driver-defined or system-defined I/O control code + (IOCTL) that is associated with the request. + +Return Value: + + VOID + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + WDFDEVICE device; + PDEVICE_CONTEXT pDevice; + BOOLEAN fSync = FALSE; + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(OutputBufferLength); + UNREFERENCED_PARAMETER(InputBufferLength); + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "DeviceIoControl request %p received with IOCTL=%lu", + FxRequest, + IoControlCode); + + device = WdfIoQueueGetDevice(FxQueue); + pDevice = GetDeviceContext(device); + + // + // Translate the test IOCTL into the appropriate + // SPB API method. Open and close are completed + // synchronously. + // + + switch (IoControlCode) + { + case IOCTL_SPBTESTTOOL_OPEN: + fSync = TRUE; + status = SpbPeripheralOpen(pDevice); + break; + + case IOCTL_SPBTESTTOOL_CLOSE: + fSync = TRUE; + status = SpbPeripheralClose(pDevice); + break; + + case IOCTL_SPBTESTTOOL_LOCK: + SpbPeripheralLock(pDevice, FxRequest); + break; + + case IOCTL_SPBTESTTOOL_UNLOCK: + SpbPeripheralUnlock(pDevice, FxRequest); + break; + + case IOCTL_SPBTESTTOOL_LOCK_CONNECTION: + SpbPeripheralLockConnection(pDevice, FxRequest); + break; + + case IOCTL_SPBTESTTOOL_UNLOCK_CONNECTION: + SpbPeripheralUnlockConnection(pDevice, FxRequest); + break; + + case IOCTL_SPBTESTTOOL_WRITEREAD: + SpbPeripheralWriteRead(pDevice, FxRequest); + break; + + case IOCTL_SPBTESTTOOL_FULL_DUPLEX: + SpbPeripheralFullDuplex(pDevice, FxRequest); + break; + + case IOCTL_SPBTESTTOOL_SIGNAL_INTERRUPT: + SpbPeripheralSignalInterrupt(pDevice, FxRequest); + break; + + default: + fSync = TRUE; + status = STATUS_INVALID_DEVICE_REQUEST; + Trace( + TRACE_LEVEL_WARNING, + TRACE_FLAG_SPBAPI, + "Request %p received with unexpected IOCTL=%lu", + FxRequest, + IoControlCode); + } + + // + // Complete the request if necessary. + // + + if (fSync) + { + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Completing request %p with %!STATUS!", + FxRequest, + status); + + WdfRequestComplete(FxRequest, status); + } + + FuncExit(TRACE_FLAG_SPBAPI); +} + +BOOLEAN +OnInterruptIsr( + _In_ WDFINTERRUPT FxInterrupt, + _In_ ULONG MessageID + ) +/*++ + + Routine Description: + + This routine responds to interrupts generated by the H/W. + It then waits indefinitely for the user to signal that + the interrupt has been acknowledged, allowing the ISR to + return. This ISR is called at PASSIVE_LEVEL. + + Arguments: + + Interrupt - a handle to a framework interrupt object + MessageID - message number identifying the device's + hardware interrupt message (if using MSI) + + Return Value: + + TRUE if interrupt recognized. + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + BOOLEAN fInterruptRecognized = TRUE; + BOOLEAN fNotificationSent; + WDFDEVICE device; + PDEVICE_CONTEXT pDevice; + + UNREFERENCED_PARAMETER(MessageID); + + device = WdfInterruptGetDevice(FxInterrupt); + pDevice = GetDeviceContext(device); + + // + // Notify the app that an interrupt has occurred. + // + + fNotificationSent = SpbPeripheralInterruptNotify(pDevice); + + if (fNotificationSent) + { + // + // Stall in ISR until acknowledged by user. + // + // Note: In a 'real' driver, the ISR should directly + // acknowledge the interrupt and then queue + // a workitem to carry out any additional + // processing. The ISR should never call + // KeWaitForSingleObject as done below. + // + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Stalling in ISR until continue command received"); + + KeClearEvent(&pDevice->IsrWaitEvent); + + KeWaitForSingleObject( + &pDevice->IsrWaitEvent, + Executive, + KernelMode, + FALSE, + NULL + ); + } + else + { + Trace( + TRACE_LEVEL_WARNING, + TRACE_FLAG_SPBAPI, + "Interrupt detected, but failed to send notification, ignoring"); + } + + FuncExit(TRACE_FLAG_SPBAPI); + + return fInterruptRecognized; +} diff --git a/SPB/SpbTestTool/sys/device.h b/SPB/SpbTestTool/sys/device.h new file mode 100644 index 00000000..40ec9904 --- /dev/null +++ b/SPB/SpbTestTool/sys/device.h @@ -0,0 +1,43 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + device.h + +Abstract: + + This module contains the function definitions for + the WDF device. + +Environment: + + kernel-mode only + +Revision History: + +--*/ + +#ifndef _DEVICE_H_ +#define _DEVICE_H_ + +// +// WDF event callbacks. +// + +EVT_WDF_DEVICE_PREPARE_HARDWARE OnPrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE OnReleaseHardware; +EVT_WDF_DEVICE_D0_ENTRY OnD0Entry; +EVT_WDF_DEVICE_D0_EXIT OnD0Exit; + +EVT_WDF_FILE_CLEANUP OnFileCleanup; + +EVT_WDF_IO_QUEUE_IO_DEFAULT OnTopLevelIoDefault; +EVT_WDF_IO_QUEUE_IO_READ OnIoRead; +EVT_WDF_IO_QUEUE_IO_WRITE OnIoWrite; +EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL OnIoDeviceControl; + +EVT_WDF_INTERRUPT_ISR OnInterruptIsr; + +#endif
\ No newline at end of file diff --git a/SPB/SpbTestTool/sys/driver.cpp b/SPB/SpbTestTool/sys/driver.cpp new file mode 100644 index 00000000..253a8858 --- /dev/null +++ b/SPB/SpbTestTool/sys/driver.cpp @@ -0,0 +1,414 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + driver.cpp + +Abstract: + + This module contains the WDF driver initialization + functions for the peripheral driver. + +Environment: + + kernel-mode only + +Revision History: + +--*/ + +#include "internal.h" +#include "driver.h" +#include "device.h" +#include "ntstrsafe.h" + +#include "driver.tmh" + +NTSTATUS +#pragma prefast(suppress:__WARNING_DRIVER_FUNCTION_TYPE, "thanks, i know this already") +DriverEntry( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING RegistryPath + ) +{ + WDF_DRIVER_CONFIG driverConfig; + WDF_OBJECT_ATTRIBUTES driverAttributes; + + WDFDRIVER fxDriver; + + NTSTATUS status; + + WPP_INIT_TRACING(DriverObject, RegistryPath); + + FuncEntry(TRACE_FLAG_WDFLOADING); + + WDF_DRIVER_CONFIG_INIT(&driverConfig, OnDeviceAdd); + driverConfig.DriverPoolTag = SPBT_POOL_TAG; + + WDF_OBJECT_ATTRIBUTES_INIT(&driverAttributes); + driverAttributes.EvtCleanupCallback = OnDriverCleanup; + + status = WdfDriverCreate( + DriverObject, + RegistryPath, + &driverAttributes, + &driverConfig, + &fxDriver); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_WDFLOADING, + "Error creating WDF driver object - %!STATUS!", + status); + + goto exit; + } + + Trace( + TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WDFLOADING, + "Created WDF driver object"); + +exit: + + FuncExit(TRACE_FLAG_WDFLOADING); + + return status; +} + +VOID +OnDriverCleanup( + _In_ WDFOBJECT Object + ) +{ + FuncEntry(TRACE_FLAG_WDFLOADING); + + UNREFERENCED_PARAMETER(Object); + + WPP_CLEANUP(nullptr); + + FuncExit(TRACE_FLAG_WDFLOADING); +} + +NTSTATUS +OnDeviceAdd( + _In_ WDFDRIVER FxDriver, + _Inout_ PWDFDEVICE_INIT FxDeviceInit + ) +/*++ + + Routine Description: + + This routine creates the device object for an SPB + controller and the device's child objects. + + Arguments: + + FxDriver - the WDF driver object handle + FxDeviceInit - information about the PDO that we are loading on + + Return Value: + + Status + +--*/ +{ + FuncEntry(TRACE_FLAG_WDFLOADING); + + PDEVICE_CONTEXT pDevice; + NTSTATUS status; + + UNREFERENCED_PARAMETER(FxDriver); + + // + // Setup PNP/Power callbacks. + // + + { + WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks; + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks); + + pnpCallbacks.EvtDevicePrepareHardware = OnPrepareHardware; + pnpCallbacks.EvtDeviceReleaseHardware = OnReleaseHardware; + pnpCallbacks.EvtDeviceD0Entry = OnD0Entry; + pnpCallbacks.EvtDeviceD0Exit = OnD0Exit; + + WdfDeviceInitSetPnpPowerEventCallbacks(FxDeviceInit, &pnpCallbacks); + } + + // + // Prepare for file object handling. + // + + { + WDF_FILEOBJECT_CONFIG fileObjectConfig; + + WDF_FILEOBJECT_CONFIG_INIT( + &fileObjectConfig, + nullptr, + nullptr, + OnFileCleanup); + + WDF_OBJECT_ATTRIBUTES fileObjectAttributes; + WDF_OBJECT_ATTRIBUTES_INIT(&fileObjectAttributes); + + WdfDeviceInitSetFileObjectConfig( + FxDeviceInit, + &fileObjectConfig, + &fileObjectAttributes); + } + + // + // Set request attributes. + // + + { + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( + &attributes, + REQUEST_CONTEXT); + + WdfDeviceInitSetRequestAttributes(FxDeviceInit, &attributes); + } + + // + // Create the device. + // + + { + WDFDEVICE fxDevice; + WDF_OBJECT_ATTRIBUTES deviceAttributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); + + status = WdfDeviceCreate( + &FxDeviceInit, + &deviceAttributes, + &fxDevice); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_WDFLOADING, + "Error creating WDFDEVICE - %!STATUS!", + status); + + goto exit; + } + + pDevice = GetDeviceContext(fxDevice); + NT_ASSERT(pDevice != nullptr); + + pDevice->FxDevice = fxDevice; + } + + // + // Ensure device is disable-able + // + + { + WDF_DEVICE_STATE deviceState; + WDF_DEVICE_STATE_INIT(&deviceState); + + deviceState.NotDisableable = WdfFalse; + WdfDeviceSetDeviceState(pDevice->FxDevice, &deviceState); + } + + // + // Create queues to handle IO + // + + { + WDF_IO_QUEUE_CONFIG queueConfig; + WDFQUEUE queue; + + // + // Top-level queue + // + + WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( + &queueConfig, + WdfIoQueueDispatchParallel); + + queueConfig.EvtIoDefault = OnTopLevelIoDefault; + queueConfig.PowerManaged = WdfFalse; + + status = WdfIoQueueCreate( + pDevice->FxDevice, + &queueConfig, + WDF_NO_OBJECT_ATTRIBUTES, + &queue + ); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_WDFLOADING, + "Error creating top-level IO queue - %!STATUS!", + status); + + goto exit; + } + + // + // Sequential SPB queue + // + + WDF_IO_QUEUE_CONFIG_INIT( + &queueConfig, + WdfIoQueueDispatchSequential); + + queueConfig.EvtIoRead = OnIoRead; + queueConfig.EvtIoWrite = OnIoWrite; + queueConfig.EvtIoDeviceControl = OnIoDeviceControl; + queueConfig.PowerManaged = WdfFalse; + + status = WdfIoQueueCreate( + pDevice->FxDevice, + &queueConfig, + WDF_NO_OBJECT_ATTRIBUTES, + &pDevice->SpbQueue + ); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_WDFLOADING, + "Error creating SPB IO queue - %!STATUS!", + status); + + goto exit; + } + } + + // + // Create a symbolic link. + // + + { + DECLARE_UNICODE_STRING_SIZE(symbolicLinkName, 128); + + status = RtlUnicodeStringPrintf( + &symbolicLinkName, L"%ws", + SPBTESTTOOL_SYMBOLIC_NAME); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_WDFLOADING, + "Error creating symbolic link string for device " + "- %!STATUS!", + status); + + goto exit; + } + + status = WdfDeviceCreateSymbolicLink( + pDevice->FxDevice, + &symbolicLinkName); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_WDFLOADING, + "Error creating symbolic link for device " + "- %!STATUS!", + status); + + goto exit; + } + } + + // + // Retrieve registry settings. + // + + { + WDFKEY key = NULL; + WDFKEY subkey = NULL; + ULONG connectInterrupt = 0; + NTSTATUS settingStatus; + + DECLARE_CONST_UNICODE_STRING(subkeyName, L"Settings"); + DECLARE_CONST_UNICODE_STRING(connectInterruptName, L"ConnectInterrupt"); + + settingStatus = WdfDeviceOpenRegistryKey( + pDevice->FxDevice, + PLUGPLAY_REGKEY_DEVICE, + KEY_READ, + WDF_NO_OBJECT_ATTRIBUTES, + &key); + + if (!NT_SUCCESS(settingStatus)) + { + Trace( + TRACE_LEVEL_WARNING, + TRACE_FLAG_WDFLOADING, + "Error opening device registry key - %!STATUS!", + settingStatus); + } + + if (NT_SUCCESS(settingStatus)) + { + settingStatus = WdfRegistryOpenKey( + key, + &subkeyName, + KEY_READ, + WDF_NO_OBJECT_ATTRIBUTES, + &subkey); + + if (!NT_SUCCESS(settingStatus)) + { + Trace( + TRACE_LEVEL_WARNING, + TRACE_FLAG_WDFLOADING, + "Error opening registry subkey for 'Settings' - %!STATUS!", + settingStatus); + } + } + + if (NT_SUCCESS(settingStatus)) + { + + settingStatus = WdfRegistryQueryULong( + subkey, + &connectInterruptName, + &connectInterrupt); + + if (!NT_SUCCESS(settingStatus)) + { + Trace( + TRACE_LEVEL_WARNING, + TRACE_FLAG_WDFLOADING, + "Error querying registry value for 'ConnectInterrupt' - %!STATUS!", + settingStatus); + } + } + + if (key != NULL) + { + WdfRegistryClose(key); + } + + if (subkey != NULL) + { + WdfRegistryClose(subkey); + } + + pDevice->ConnectInterrupt = (connectInterrupt == 1); + } + +exit: + + FuncExit(TRACE_FLAG_WDFLOADING); + + return status; +} diff --git a/SPB/SpbTestTool/sys/driver.h b/SPB/SpbTestTool/sys/driver.h new file mode 100644 index 00000000..1029377c --- /dev/null +++ b/SPB/SpbTestTool/sys/driver.h @@ -0,0 +1,36 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + driver.h + +Abstract: + + This module contains the function definitions for + the WDF driver. + +Environment: + + kernel-mode only + +Revision History: + +--*/ + +#ifndef _DRIVER_H_ +#define _DRIVER_H_ + +extern "C" + +NTSTATUS +DriverEntry( + _In_ PDRIVER_OBJECT pDriverObject, + _In_ PUNICODE_STRING pRegistryPath + ); + +EVT_WDF_DRIVER_DEVICE_ADD OnDeviceAdd; +EVT_WDF_OBJECT_CONTEXT_CLEANUP OnDriverCleanup; + +#endif diff --git a/SPB/SpbTestTool/sys/internal.h b/SPB/SpbTestTool/sys/internal.h new file mode 100644 index 00000000..7e40560b --- /dev/null +++ b/SPB/SpbTestTool/sys/internal.h @@ -0,0 +1,144 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + internal.h + +Abstract: + + This module contains the common internal type and function + definitions for the SPB peripheral driver. + +Environment: + + kernel-mode only + +Revision History: + +--*/ + +#ifndef _INTERNAL_H_ +#define _INTERNAL_H_ + +#pragma warning(push) +#pragma warning(disable:4512) +#pragma warning(disable:4480) + +#define SPBT_POOL_TAG ((ULONG) 'TBPS') + +///////////////////////////////////////////////// +// +// Common includes. +// +///////////////////////////////////////////////// + +#include <ntddk.h> +#include <wdm.h> +#include <wdf.h> +#include <ntstrsafe.h> + +#include "spb.h" +#include "spbtestioctl.h" + +#define RESHUB_USE_HELPER_ROUTINES +#include "reshub.h" + +#include "trace.h" + +// +// Forward Declarations +// + +typedef struct _DEVICE_CONTEXT DEVICE_CONTEXT, *PDEVICE_CONTEXT; +typedef struct _REQUEST_CONTEXT REQUEST_CONTEXT, *PREQUEST_CONTEXT; + +struct _DEVICE_CONTEXT +{ + // + // Handle back to the WDFDEVICE + // + + WDFDEVICE FxDevice; + + // + // Handle to the sequential SPB queue + // + + WDFQUEUE SpbQueue; + + // + // Connection ID for SPB peripheral + // + + LARGE_INTEGER PeripheralId; + + // + // Interrupt object and wait event + // + + WDFINTERRUPT Interrupt; + KEVENT IsrWaitEvent; + + // + // Setting indicating whether the interrupt should be connected + // + + BOOLEAN ConnectInterrupt; + + // + // SPB controller target + // + + WDFIOTARGET SpbController; + + // + // SPB request object + // + + WDFREQUEST SpbRequest; + + // + // Input memory for request. Valid while request in progress. + // + + WDFMEMORY InputMemory; + + // + // Client request object + // + + WDFREQUEST ClientRequest; + + // + // WaitOnInterrupt request object + // + + WDFREQUEST WaitOnInterruptRequest; +}; + +struct _REQUEST_CONTEXT +{ + // + // Associated framework device object + // + + WDFDEVICE FxDevice; + + // + // Variables to track write length for a sequence request. + // There are needed to complete the client request with + // correct bytesReturned value. + // + + BOOLEAN IsSpbSequenceRequest; + ULONG_PTR SequenceWriteLength; +}; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, GetDeviceContext); +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(REQUEST_CONTEXT, GetRequestContext); + +#pragma warning(pop) + +#endif // _INTERNAL_H_ diff --git a/SPB/SpbTestTool/sys/peripheral.cpp b/SPB/SpbTestTool/sys/peripheral.cpp new file mode 100644 index 00000000..c6966ada --- /dev/null +++ b/SPB/SpbTestTool/sys/peripheral.cpp @@ -0,0 +1,1683 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + peripheral.cpp + +Abstract: + + This module contains the function for interaction + with the SPB API. + +Environment: + + kernel-mode only + +Revision History: + +--*/ + +#include "internal.h" +#include "peripheral.h" + +#include "peripheral.tmh" + +NTSTATUS +SpbPeripheralOpen( + _In_ PDEVICE_CONTEXT pDevice + ) +/*++ + + Routine Description: + + This routine opens a handle to the SPB controller. + + Arguments: + + pDevice - a pointer to the device context + + Return Value: + + Status + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + WDF_IO_TARGET_OPEN_PARAMS openParams; + NTSTATUS status; + + // + // Create the device path using the connection ID. + // + + DECLARE_UNICODE_STRING_SIZE(DevicePath, RESOURCE_HUB_PATH_SIZE); + + RESOURCE_HUB_CREATE_PATH_FROM_ID( + &DevicePath, + pDevice->PeripheralId.LowPart, + pDevice->PeripheralId.HighPart); + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Opening handle to SPB target via %wZ", + &DevicePath); + + // + // Open a handle to the SPB controller. + // + + WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME( + &openParams, + &DevicePath, + (GENERIC_READ | GENERIC_WRITE)); + + openParams.ShareAccess = 0; + openParams.CreateDisposition = FILE_OPEN; + openParams.FileAttributes = FILE_ATTRIBUTE_NORMAL; + + status = WdfIoTargetOpen( + pDevice->SpbController, + &openParams); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to open SPB target - %!STATUS!", + status); + } + + FuncExit(TRACE_FLAG_SPBAPI); + + return status; +} + +NTSTATUS +SpbPeripheralClose( + _In_ PDEVICE_CONTEXT pDevice + ) +/*++ + + Routine Description: + + This routine closes a handle to the SPB controller. + + Arguments: + + pDevice - a pointer to the device context + + Return Value: + + Status + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Closing handle to SPB target"); + + WdfIoTargetClose(pDevice->SpbController); + + FuncExit(TRACE_FLAG_SPBAPI); + + return STATUS_SUCCESS; +} + +VOID +SpbPeripheralLock( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest + ) +/*++ + + Routine Description: + + This routine sends a lock command to the SPB controller. + + Arguments: + + pDevice - a pointer to the device context + FxRequest - the framework request object + + Return Value: + + None + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + UNREFERENCED_PARAMETER(FxRequest); + + NTSTATUS status; + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Formatting SPB request %p for IOCTL_SPB_LOCK_CONTROLLER", + pDevice->SpbRequest); + + // + // Save the client request. + // + + pDevice->ClientRequest = FxRequest; + + // + // Initialize the SPB request for lock and send. + // + + status = WdfIoTargetFormatRequestForIoctl( + pDevice->SpbController, + pDevice->SpbRequest, + IOCTL_SPB_LOCK_CONTROLLER, + nullptr, + nullptr, + nullptr, + nullptr); + + if (NT_SUCCESS(status)) + { + status = SpbPeripheralSendRequest( + pDevice, + pDevice->SpbRequest, + FxRequest); + } + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to send SPB request %p for " + "IOCTL_SPB_LOCK_CONTROLLER - %!STATUS!", + pDevice->SpbRequest, + status); + + SpbPeripheralCompleteRequestPair( + pDevice, + status, + 0); + } + + FuncExit(TRACE_FLAG_SPBAPI); +} + +VOID +SpbPeripheralUnlock( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest + ) +/*++ + + Routine Description: + + This routine sends an unlock command to the SPB controller. + + Arguments: + + pDevice - a pointer to the device context + FxRequest - the framework request object + + Return Value: + + None + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + UNREFERENCED_PARAMETER(FxRequest); + + NTSTATUS status; + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Formatting SPB request %p for IOCTL_SPB_UNLOCK_CONTROLLER", + pDevice->SpbRequest); + + // + // Save the client request. + // + + pDevice->ClientRequest = FxRequest; + + // + // Initialize the SPB request for unlock and send. + // + + status = WdfIoTargetFormatRequestForIoctl( + pDevice->SpbController, + pDevice->SpbRequest, + IOCTL_SPB_UNLOCK_CONTROLLER, + nullptr, + nullptr, + nullptr, + nullptr); + + if (NT_SUCCESS(status)) + { + status = SpbPeripheralSendRequest( + pDevice, + pDevice->SpbRequest, + FxRequest); + } + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to send SPB request %p for " + "IOCTL_SPB_UNLOCK_CONTROLLER - %!STATUS!", + pDevice->SpbRequest, + status); + + SpbPeripheralCompleteRequestPair( + pDevice, + status, + 0); + } + + FuncExit(TRACE_FLAG_SPBAPI); +} + +VOID +SpbPeripheralLockConnection( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest + ) +/*++ + + Routine Description: + + This routine sends a lock connection command to the SPB controller. + + Arguments: + + pDevice - a pointer to the device context + FxRequest - the framework request object + + Return Value: + + None + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + UNREFERENCED_PARAMETER(FxRequest); + + NTSTATUS status; + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Formatting SPB request %p for IOCTL_SPB_LOCK_CONNECTION", + pDevice->SpbRequest); + + // + // Save the client request. + // + + pDevice->ClientRequest = FxRequest; + + // + // Initialize the SPB request for lock and send. + // + + status = WdfIoTargetFormatRequestForIoctl( + pDevice->SpbController, + pDevice->SpbRequest, + IOCTL_SPB_LOCK_CONNECTION, + nullptr, + nullptr, + nullptr, + nullptr); + + if (NT_SUCCESS(status)) + { + status = SpbPeripheralSendRequest( + pDevice, + pDevice->SpbRequest, + FxRequest); + } + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to send SPB request %p for " + "IOCTL_SPB_LOCK_CONNECTION - %!STATUS!", + pDevice->SpbRequest, + status); + + SpbPeripheralCompleteRequestPair( + pDevice, + status, + 0); + } + + FuncExit(TRACE_FLAG_SPBAPI); +} + +VOID +SpbPeripheralUnlockConnection( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest + ) +/*++ + + Routine Description: + + This routine sends an unlock connection command to the SPB controller. + + Arguments: + + pDevice - a pointer to the device context + FxRequest - the framework request object + + Return Value: + + None + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + UNREFERENCED_PARAMETER(FxRequest); + + NTSTATUS status; + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Formatting SPB request %p for IOCTL_SPB_UNLOCK_CONNECTION", + pDevice->SpbRequest); + + // + // Save the client request. + // + + pDevice->ClientRequest = FxRequest; + + // + // Initialize the SPB request for unlock and send. + // + + status = WdfIoTargetFormatRequestForIoctl( + pDevice->SpbController, + pDevice->SpbRequest, + IOCTL_SPB_UNLOCK_CONNECTION, + nullptr, + nullptr, + nullptr, + nullptr); + + if (NT_SUCCESS(status)) + { + status = SpbPeripheralSendRequest( + pDevice, + pDevice->SpbRequest, + FxRequest); + } + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to send SPB request %p for " + "IOCTL_SPB_UNLOCK_CONNECTION - %!STATUS!", + pDevice->SpbRequest, + status); + + SpbPeripheralCompleteRequestPair( + pDevice, + status, + 0); + } + + FuncExit(TRACE_FLAG_SPBAPI); +} + +VOID +SpbPeripheralRead( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest + ) +/*++ + + Routine Description: + + This routine reads from the SPB controller. + + Arguments: + + pDevice - a pointer to the device context + FxRequest - the framework request object + + Return Value: + + None + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + UNREFERENCED_PARAMETER(FxRequest); + + WDFMEMORY memory = nullptr; + NTSTATUS status; + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Formatting SPB request %p for read", + pDevice->SpbRequest); + + // + // Save the client request. + // + + pDevice->ClientRequest = FxRequest; + + // + // Initialize the SPB request for read and send. + // + + status = WdfRequestRetrieveOutputMemory( + FxRequest, + &memory); + + if (NT_SUCCESS(status)) + { + status = WdfIoTargetFormatRequestForRead( + pDevice->SpbController, + pDevice->SpbRequest, + memory, + nullptr, + nullptr); + + if (NT_SUCCESS(status)) + { + status = SpbPeripheralSendRequest( + pDevice, + pDevice->SpbRequest, + FxRequest); + } + } + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to send SPB request %p for " + "read - %!STATUS!", + pDevice->SpbRequest, + status); + + SpbPeripheralCompleteRequestPair( + pDevice, + status, + 0); + } + + FuncExit(TRACE_FLAG_SPBAPI); +} + +VOID +SpbPeripheralWrite( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest + ) +/*++ + + Routine Description: + + This routine writes to the SPB controller. + + Arguments: + + pDevice - a pointer to the device context + FxRequest - the framework request object + + Return Value: + + None + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + UNREFERENCED_PARAMETER(FxRequest); + + WDFMEMORY memory = nullptr; + NTSTATUS status; + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Formatting SPB request %p for write", + pDevice->SpbRequest); + + // + // Save the client request. + // + + pDevice->ClientRequest = FxRequest; + + // + // Initialize the SPB request for write and send. + // + + status = WdfRequestRetrieveInputMemory( + FxRequest, + &memory); + + if (NT_SUCCESS(status)) + { + status = WdfIoTargetFormatRequestForWrite( + pDevice->SpbController, + pDevice->SpbRequest, + memory, + nullptr, + nullptr); + + if (NT_SUCCESS(status)) + { + status = SpbPeripheralSendRequest( + pDevice, + pDevice->SpbRequest, + FxRequest); + } + } + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to send SPB request %p for " + "write - %!STATUS!", + pDevice->SpbRequest, + status); + + SpbPeripheralCompleteRequestPair( + pDevice, + status, + 0); + } + + FuncExit(TRACE_FLAG_SPBAPI); +} + +VOID +SpbPeripheralWriteRead( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest + ) +/*++ + + Routine Description: + + This routine sends a write-read sequence to the SPB controller. + + Arguments: + + pDevice - a pointer to the device context + FxRequest - the framework request object + + Return Value: + + None + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + UNREFERENCED_PARAMETER(FxRequest); + + PVOID pInputBuffer = nullptr; + PVOID pOutputBuffer = nullptr; + size_t inputBufferLength = 0; + size_t outputBufferLength = 0; + WDF_OBJECT_ATTRIBUTES attributes; + PREQUEST_CONTEXT pRequest; + NTSTATUS status; + + pRequest = GetRequestContext(pDevice->SpbRequest); + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Formatting SPB request %p for IOCTL_SPB_EXECUTE_SEQUENCE", + pDevice->SpbRequest); + + // + // Save the client request. + // + + pDevice->ClientRequest = FxRequest; + + // + // Get input and output buffers. + // + + status = WdfRequestRetrieveInputBuffer( + FxRequest, + 0, + &pInputBuffer, + &inputBufferLength); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to retrieve input buffer - %!STATUS!", + status); + + goto Done; + } + + status = WdfRequestRetrieveOutputBuffer( + FxRequest, + 0, + &pOutputBuffer, + &outputBufferLength); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to retrieve output buffer - %!STATUS!", + status); + + goto Done; + } + + // + // Build SPB sequence. + // + + const ULONG transfers = 2; + + SPB_TRANSFER_LIST_AND_ENTRIES(transfers) seq; + SPB_TRANSFER_LIST_INIT(&(seq.List), transfers); + + { + // + // PreFAST cannot figure out the SPB_TRANSFER_LIST_ENTRY + // "struct hack" size but using an index variable quiets + // the warning. This is a false positive from OACR. + // + + ULONG index = 0; + seq.List.Transfers[index] = SPB_TRANSFER_LIST_ENTRY_INIT_SIMPLE( + SpbTransferDirectionToDevice, + 0, + pInputBuffer, + (ULONG)inputBufferLength); + + seq.List.Transfers[index + 1] = SPB_TRANSFER_LIST_ENTRY_INIT_SIMPLE( + SpbTransferDirectionFromDevice, + 0, + pOutputBuffer, + (ULONG)outputBufferLength); + } + + // + // Create preallocated WDFMEMORY. The IOCTL is METHOD_BUFFERED, + // so the memory doesn't have to persist until the request is + // completed. + // + + NT_ASSERT(pDevice->InputMemory == WDF_NO_HANDLE); + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + status = WdfMemoryCreatePreallocated( + &attributes, + (PVOID)&seq, + sizeof(seq), + &pDevice->InputMemory); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to create WDFMEMORY - %!STATUS!", + status); + + goto Done; + } + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Built write-read sequence %p with byte length=%lu", + &seq, + (ULONG)(inputBufferLength + outputBufferLength)); + + // + // Send sequence IOCTL. + // + + // + // Mark SPB request as sequence and save length. + // These will be used in the completion callback + // to complete the client request with the correct + // number of bytes + // + + pRequest->IsSpbSequenceRequest = TRUE; + pRequest->SequenceWriteLength = (ULONG_PTR)inputBufferLength; + + // + // Format and send the SPB sequence request. + // + + status = WdfIoTargetFormatRequestForIoctl( + pDevice->SpbController, + pDevice->SpbRequest, + IOCTL_SPB_EXECUTE_SEQUENCE, + pDevice->InputMemory, + nullptr, + nullptr, + nullptr); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to format request - %!STATUS!", + status); + + goto Done; + } + + status = SpbPeripheralSendRequest( + pDevice, + pDevice->SpbRequest, + FxRequest); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to send SPB request %p for " + "IOCTL_SPB_EXECUTE_SEQUENCE - %!STATUS!", + pDevice->SpbRequest, + status); + + goto Done; + } + +Done: + + if (!NT_SUCCESS(status)) + { + SpbPeripheralCompleteRequestPair( + pDevice, + status, + 0); + } + + FuncExit(TRACE_FLAG_SPBAPI); +} + +VOID +SpbPeripheralFullDuplex( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest + ) +/*++ + + Routine Description: + + This routine sends a full duplex transfer to the SPB controller. + + Arguments: + + pDevice - a pointer to the device context + FxRequest - the framework request object + + Return Value: + + None + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + UNREFERENCED_PARAMETER(FxRequest); + + PVOID pInputBuffer = nullptr; + PVOID pOutputBuffer = nullptr; + size_t inputBufferLength = 0; + size_t outputBufferLength = 0; + WDF_OBJECT_ATTRIBUTES attributes; + PREQUEST_CONTEXT pRequest; + NTSTATUS status; + + pRequest = GetRequestContext(pDevice->SpbRequest); + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Formatting SPB request %p for IOCTL_SPB_FULL_DUPLEX", + pDevice->SpbRequest); + + // + // Save the client request. + // + + pDevice->ClientRequest = FxRequest; + + // + // Get input and output buffers. + // + + status = WdfRequestRetrieveInputBuffer( + FxRequest, + 0, + &pInputBuffer, + &inputBufferLength); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to retrieve input buffer - %!STATUS!", + status); + + goto Done; + } + + status = WdfRequestRetrieveOutputBuffer( + FxRequest, + 0, + &pOutputBuffer, + &outputBufferLength); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to retrieve output buffer - %!STATUS!", + status); + + goto Done; + } + + // + // Build full duplex transfer using SPB transfer list. + // + + const ULONG transfers = 2; + + SPB_TRANSFER_LIST_AND_ENTRIES(transfers) seq; + SPB_TRANSFER_LIST_INIT(&(seq.List), transfers); + + { + // + // PreFAST cannot figure out the SPB_TRANSFER_LIST_ENTRY + // "struct hack" size but using an index variable quiets + // the warning. This is a false positive from OACR. + // + + ULONG index = 0; + seq.List.Transfers[index] = SPB_TRANSFER_LIST_ENTRY_INIT_SIMPLE( + SpbTransferDirectionToDevice, + 0, + pInputBuffer, + (ULONG)inputBufferLength); + + seq.List.Transfers[index + 1] = SPB_TRANSFER_LIST_ENTRY_INIT_SIMPLE( + SpbTransferDirectionFromDevice, + 0, + pOutputBuffer, + (ULONG)outputBufferLength); + } + + // + // Create preallocated WDFMEMORY. The IOCTL is METHOD_BUFFERED, + // so the memory doesn't have to persist until the request is + // completed. + // + + NT_ASSERT(pDevice->InputMemory == WDF_NO_HANDLE); + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + status = WdfMemoryCreatePreallocated( + &attributes, + (PVOID)&seq, + sizeof(seq), + &pDevice->InputMemory); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to create WDFMEMORY - %!STATUS!", + status); + + goto Done; + } + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Built full duplex transfer %p with byte length=%lu", + &seq, + (ULONG)(inputBufferLength + outputBufferLength)); + + // + // Send full duplex IOCTL. + // + + // + // Mark SPB request as full duplex (sequence format) + // and save length. These will be used in the completion + // callback to complete the client request with the correct + // number of bytes + // + + pRequest->IsSpbSequenceRequest = TRUE; + pRequest->SequenceWriteLength = (ULONG_PTR)inputBufferLength; + + // + // Format and send the full duplex request. + // + + status = WdfIoTargetFormatRequestForIoctl( + pDevice->SpbController, + pDevice->SpbRequest, + IOCTL_SPB_FULL_DUPLEX, + pDevice->InputMemory, + nullptr, + nullptr, + nullptr); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to format request - %!STATUS!", + status); + + goto Done; + } + + status = SpbPeripheralSendRequest( + pDevice, + pDevice->SpbRequest, + FxRequest); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to send SPB request %p for " + "IOCTL_SPB_FULL_DUPLEX - %!STATUS!", + pDevice->SpbRequest, + status); + + goto Done; + } + +Done: + + if (!NT_SUCCESS(status)) + { + SpbPeripheralCompleteRequestPair( + pDevice, + status, + 0); + } + + FuncExit(TRACE_FLAG_SPBAPI); +} + +VOID +SpbPeripheralSignalInterrupt( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest + ) +/*++ +Routine Description: + + This routine signals the interrupt service routine + to continue. + +Arguments: + + pDevice - the device context + FxRequest - the framework request object + +Return Value: + + None. + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + NTSTATUS status = STATUS_SUCCESS; + + if (pDevice->Interrupt != nullptr) + { + // + // Signal ISR to continue. + // + + KeSetEvent( + &pDevice->IsrWaitEvent, + IO_NO_INCREMENT, + FALSE); + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Setting ISR wait event"); + } + else + { + status = STATUS_NOT_FOUND; + Trace( + TRACE_LEVEL_WARNING, + TRACE_FLAG_SPBAPI, + "No interrupt object found, ignoring - %!STATUS!", + status); + } + + WdfRequestComplete(FxRequest, status); + + FuncExit(TRACE_FLAG_SPBAPI); +} + +VOID +SpbPeripheralWaitOnInterrupt( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest + ) +/*++ +Routine Description: + + This routine pends the WaitOnInterrupt request. + +Arguments: + + pDevice - the device context + FxRequest - the framework request object + +Return Value: + + None. + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + PREQUEST_CONTEXT pRequest = GetRequestContext(FxRequest); + NTSTATUS status = STATUS_SUCCESS; + + if (pDevice->WaitOnInterruptRequest == nullptr) + { + // + // Mark request cancellable. + // + + pRequest->FxDevice = pDevice->FxDevice; + + status = WdfRequestMarkCancelableEx( + FxRequest, + SpbPeripheralOnWaitOnInterruptCancel); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to mark WaitOnInterrupt request %p cancellable - %!STATUS!", + FxRequest, + status); + } + + // + // Pend the WaitOnInterrupt request. + // + + if (NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "WaitOnInterrupt request %p pended", + FxRequest); + + pDevice->WaitOnInterruptRequest = FxRequest; + } + } + else + { + status = STATUS_INVALID_DEVICE_STATE; + Trace( + TRACE_LEVEL_WARNING, + TRACE_FLAG_SPBAPI, + "Cannont pend multiple WaitOnInterrupt requests, ignoring - %!STATUS!", + status); + } + + if (!NT_SUCCESS(status)) + { + WdfRequestComplete(FxRequest, status); + } + + FuncExit(TRACE_FLAG_SPBAPI); +} + +VOID +SpbPeripheralOnWaitOnInterruptCancel( + _In_ WDFREQUEST FxRequest + ) +/*++ +Routine Description: + + This event is called when the WaitOnInterrupt request is cancelled. + +Arguments: + + FxRequest - the framework request object + +Return Value: + + VOID + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + PREQUEST_CONTEXT pRequest; + PDEVICE_CONTEXT pDevice; + + pRequest = GetRequestContext(FxRequest); + pDevice = GetDeviceContext(pRequest->FxDevice); + + // + // Complete the request as cancelled + // + + if (FxRequest == pDevice->WaitOnInterruptRequest) + { + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "WaitOnInterrupt request %p cancelled", + FxRequest); + + pDevice->WaitOnInterruptRequest = nullptr; + WdfRequestComplete(FxRequest, STATUS_CANCELLED); + } + else + { + Trace( + TRACE_LEVEL_WARNING, + TRACE_FLAG_SPBAPI, + "Cancel for WDFREQUEST %p without WaitOnInterrupt request pended," + "will complete as cancelled anyway", + FxRequest); + + WdfRequestComplete(FxRequest, STATUS_CANCELLED); + } + + FuncExit(TRACE_FLAG_SPBAPI); +} + +BOOLEAN +SpbPeripheralInterruptNotify( + _In_ PDEVICE_CONTEXT pDevice + ) +/*++ +Routine Description: + + This routine completes the pending WaitOnInterrupt request. + +Arguments: + + pDevice - the device context + +Return Value: + + TRUE if notification sent, false otherwise. + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + WDFREQUEST request; + BOOLEAN fNotificationSent = FALSE; + NTSTATUS status; + + if (pDevice->WaitOnInterruptRequest != nullptr) + { + // + // Complete the WaitOnInterrupt request. + // + + request = pDevice->WaitOnInterruptRequest; + pDevice->WaitOnInterruptRequest = nullptr; + + status = WdfRequestUnmarkCancelable(request); + + if (NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Interrupt detected, WaitOnInterrupt request %p completed", + pDevice->WaitOnInterruptRequest); + + WdfRequestComplete(request, STATUS_SUCCESS); + fNotificationSent = TRUE; + } + else if (status == STATUS_CANCELLED) + { + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Interrupt detected with WaitOnInterrupt request %p " + "already completed - %!STATUS!", + pDevice->WaitOnInterruptRequest, + status); + } + else + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Interrupt detected but failed to unmark WaitOnInterrupt " + "request %p as cancellable - %!STATUS!", + pDevice->WaitOnInterruptRequest, + status); + } + } + else + { + Trace( + TRACE_LEVEL_WARNING, + TRACE_FLAG_SPBAPI, + "Interrupt detected without a pended WaitOnInterrupt request"); + } + + FuncExit(TRACE_FLAG_SPBAPI); + + return fNotificationSent; +} + +NTSTATUS +SpbPeripheralSendRequest( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST SpbRequest, + _In_ WDFREQUEST ClientRequest + ) +/*++ + + Routine Description: + + This routine sends a write-read sequence to the SPB controller. + + Arguments: + + pDevice - a pointer to the device context + SpbRequest - the SPB request object + ClientRequest - the client request object + + Return Value: + + Status + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + PREQUEST_CONTEXT pRequest = GetRequestContext(ClientRequest); + NTSTATUS status = STATUS_SUCCESS; + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Saving client request %p, and " + "sending SPB request %p", + ClientRequest, + SpbRequest); + + // + // Init client request context. + // + + pRequest->FxDevice = pDevice->FxDevice; + pRequest->IsSpbSequenceRequest = FALSE; + pRequest->SequenceWriteLength = 0; + + // + // Mark the client request as cancellable. + // + + if (NT_SUCCESS(status)) + { + status = WdfRequestMarkCancelableEx( + ClientRequest, + SpbPeripheralOnCancel); + } + + // + // Send the SPB request. + // + + if (NT_SUCCESS(status)) + { + WdfRequestSetCompletionRoutine( + SpbRequest, + SpbPeripheralOnCompletion, + GetRequestContext(SpbRequest)); + + BOOLEAN fSent = WdfRequestSend( + SpbRequest, + pDevice->SpbController, + WDF_NO_SEND_OPTIONS); + + if (!fSent) + { + status = WdfRequestGetStatus(SpbRequest); + + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPBAPI, + "Failed to send SPB request %p - %!STATUS!", + SpbRequest, + status); + + NTSTATUS cancelStatus; + cancelStatus = WdfRequestUnmarkCancelable(ClientRequest); + + if (!NT_SUCCESS(cancelStatus)) + { + NT_ASSERTMSG("WdfRequestUnmarkCancelable should only fail if request has already been cancelled", + cancelStatus == STATUS_CANCELLED); + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Client request %p has already been cancelled - " + "%!STATUS!", + ClientRequest, + cancelStatus); + } + } + } + + FuncExit(TRACE_FLAG_SPBAPI); + + return status; +} + +VOID +SpbPeripheralOnCompletion( + _In_ WDFREQUEST FxRequest, + _In_ WDFIOTARGET FxTarget, + _In_ PWDF_REQUEST_COMPLETION_PARAMS Params, + _In_ WDFCONTEXT Context + ) +/*++ + + Routine Description: + + This routine is called when a request completes. + + Arguments: + + FxRequest - the framework request object + FxTarget - the framework IO target object + Params - a pointer to the request completion parameters + Context - the request context + + Return Value: + + None + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + UNREFERENCED_PARAMETER(FxTarget); + UNREFERENCED_PARAMETER(Context); + + PREQUEST_CONTEXT pRequest; + PDEVICE_CONTEXT pDevice; + NTSTATUS status; + NTSTATUS cancelStatus; + ULONG_PTR bytesCompleted; + + pRequest = GetRequestContext(FxRequest); + pDevice = GetDeviceContext(pRequest->FxDevice); + + status = Params->IoStatus.Status; + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Completion callback received for SPB request %p with %!STATUS!", + FxRequest, + status); + + // + // Unmark the client request as cancellable + // + + cancelStatus = WdfRequestUnmarkCancelable(pDevice->ClientRequest); + + if (!NT_SUCCESS(cancelStatus)) + { + NT_ASSERTMSG("WdfRequestUnmarkCancelable should only fail if request has already been cancelled", + cancelStatus == STATUS_CANCELLED); + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Client request %p has already been cancelled - %!STATUS!", + pDevice->ClientRequest, + cancelStatus); + } + + // + // Complete the request pair + // + + if (pRequest->IsSpbSequenceRequest == TRUE) + { + // + // The client DeviceIoControl should only be + // completed with bytesReturned and not total + // bytes transferred. Here we infer the number + // of bytes read by substracting the write + // length from the total. + // + + bytesCompleted = + Params->IoStatus.Information < pRequest->SequenceWriteLength ? + 0 : Params->IoStatus.Information - pRequest->SequenceWriteLength; + } + else + { + bytesCompleted = Params->IoStatus.Information; + } + + SpbPeripheralCompleteRequestPair( + pDevice, + status, + bytesCompleted); + + FuncExit(TRACE_FLAG_SPBAPI); +} + +VOID +SpbPeripheralOnCancel( + _In_ WDFREQUEST FxRequest + ) +/*++ +Routine Description: + + This event is called when the client request is cancelled. + +Arguments: + + FxRequest - the framework request object + +Return Value: + + VOID + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + PREQUEST_CONTEXT pRequest; + PDEVICE_CONTEXT pDevice; + + pRequest = GetRequestContext(FxRequest); + pDevice = GetDeviceContext(pRequest->FxDevice); + + // + // Attempt to cancel the SPB request + // + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Cancel received for client request %p, " + "attempting to cancel SPB request %p", + FxRequest, + pDevice->SpbRequest); + + WdfRequestCancelSentRequest(pDevice->SpbRequest); + + FuncExit(TRACE_FLAG_SPBAPI); +} + +VOID +SpbPeripheralCompleteRequestPair( + _In_ PDEVICE_CONTEXT pDevice, + _In_ NTSTATUS status, + _In_ ULONG_PTR bytesCompleted + ) +/*++ +Routine Description: + + This routine marks the SpbRequest as reuse + and completes the client request. + +Arguments: + + pDevice - the device context + status - the client completion status + bytesCompleted - the number of bytes completed + for the client request + +Return Value: + + VOID + +--*/ +{ + FuncEntry(TRACE_FLAG_SPBAPI); + + PREQUEST_CONTEXT pRequest; + pRequest = GetRequestContext(pDevice->SpbRequest); + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_SPBAPI, + "Marking SPB request %p for reuse, and completing " + "client request %p with %!STATUS! and bytes=%lu", + pDevice->SpbRequest, + pDevice->ClientRequest, + status, + (ULONG)bytesCompleted); + + // + // Mark the SPB request as reuse + // + + pRequest->IsSpbSequenceRequest = FALSE; + pRequest->SequenceWriteLength = 0; + + WDF_REQUEST_REUSE_PARAMS params; + WDF_REQUEST_REUSE_PARAMS_INIT( + ¶ms, + WDF_REQUEST_REUSE_NO_FLAGS, + STATUS_SUCCESS); + + WdfRequestReuse(pDevice->SpbRequest, ¶ms); + + if (pDevice->InputMemory != WDF_NO_HANDLE) + { + WdfObjectDelete(pDevice->InputMemory); + pDevice->InputMemory = WDF_NO_HANDLE; + } + + // + // Complete the client request + // + + if (pDevice->ClientRequest != nullptr) + { + WDFREQUEST clientRequest = pDevice->ClientRequest; + pDevice->ClientRequest = nullptr; + + // + // In order to satisfy SDV, assume clientRequest + // is equal to pDevice->ClientRequest. This suppresses + // a warning in the driver's cancellation path. + // + // Typically when WdfRequestUnmarkCancelable returns + // STATUS_CANCELLED a driver does not go on to complete + // the request in that context. This sample, however, + // driver has handled this condition appropriately by + // not completing the cancelled request in its + // EvtRequestCancel callback. Developers should be + // cautious when copying code from this sample, paying + // close attention to the cancellation logic. + // + _Analysis_assume_(clientRequest == pDevice->ClientRequest); + + WdfRequestCompleteWithInformation( + clientRequest, + status, + bytesCompleted); + } + + FuncExit(TRACE_FLAG_SPBAPI); +} diff --git a/SPB/SpbTestTool/sys/peripheral.h b/SPB/SpbTestTool/sys/peripheral.h new file mode 100644 index 00000000..fc1fc806 --- /dev/null +++ b/SPB/SpbTestTool/sys/peripheral.h @@ -0,0 +1,104 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + peripheral.h + +Abstract: + + This module contains the function definitions for + interaction with the SPB API. + +Environment: + + kernel-mode only + +Revision History: + +--*/ + +#ifndef _PERIPHERAL_H_ +#define _PERIPHERAL_H_ + +EVT_WDF_REQUEST_COMPLETION_ROUTINE SpbPeripheralOnCompletion; +EVT_WDF_REQUEST_CANCEL SpbPeripheralOnCancel; + +EVT_WDF_REQUEST_CANCEL SpbPeripheralOnWaitOnInterruptCancel; + +NTSTATUS +SpbPeripheralOpen( + _In_ PDEVICE_CONTEXT pDevice); + +NTSTATUS +SpbPeripheralClose( + _In_ PDEVICE_CONTEXT pDevice); + +VOID +SpbPeripheralLock( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest); + +VOID +SpbPeripheralUnlock( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest); + +VOID +SpbPeripheralLockConnection( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest); + +VOID +SpbPeripheralUnlockConnection( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest); + +VOID +SpbPeripheralRead( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest); + +VOID +SpbPeripheralWrite( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest); + +VOID +SpbPeripheralWriteRead( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest); + +VOID +SpbPeripheralFullDuplex( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest); + +VOID +SpbPeripheralSignalInterrupt( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest); + +VOID +SpbPeripheralWaitOnInterrupt( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST FxRequest); + +BOOLEAN +SpbPeripheralInterruptNotify( + _In_ PDEVICE_CONTEXT pDevice); + +NTSTATUS +SpbPeripheralSendRequest( + _In_ PDEVICE_CONTEXT pDevice, + _In_ WDFREQUEST SpbRequest, + _In_ WDFREQUEST ClientRequest); + +VOID +SpbPeripheralCompleteRequestPair( + _In_ PDEVICE_CONTEXT pDevice, + _In_ NTSTATUS status, + _In_ ULONG_PTR bytesCompleted); + +#endif // _PERIPHERAL_H_ diff --git a/SPB/SpbTestTool/sys/resource.rc b/SPB/SpbTestTool/sys/resource.rc new file mode 100644 index 00000000..24dd5368 --- /dev/null +++ b/SPB/SpbTestTool/sys/resource.rc @@ -0,0 +1,11 @@ +#include <windows.h> + +#include <ntverp.h> + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM +#define VER_FILEDESCRIPTION_STR "SPB Test Tool Peripheral Driver" +#define VER_INTERNALNAME_STR "SpbTestTool.sys" +#define VER_ORIGINALFILENAME_STR "SpbTestTool.sys" + +#include "common.ver" diff --git a/SPB/SpbTestTool/sys/spbtestioctl.h b/SPB/SpbTestTool/sys/spbtestioctl.h new file mode 100644 index 00000000..5a0f7b7e --- /dev/null +++ b/SPB/SpbTestTool/sys/spbtestioctl.h @@ -0,0 +1,50 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + spbtestioctl.h + +Abstract: + + This module contains the public device path names and + IOCTL definitions for the SpbTestTool. + +Environment: + +Revision History: + +--*/ + +#ifndef _SPBTESTIOCTL_H_ +#define _SPBTESTIOCTL_H_ + +// +// Device path names +// + +#define SPBTESTTOOL_NAME L"SPBTESTTOOL" + +#define SPBTESTTOOL_SYMBOLIC_NAME L"\\DosDevices\\" SPBTESTTOOL_NAME +#define SPBTESTTOOL_USERMODE_PATH L"\\\\.\\" SPBTESTTOOL_NAME +#define SPBTESTTOOL_USERMODE_PATH_SIZE sizeof(SPBTESTTOOL_USERMODE_PATH) + +// +// Priavte SpbTestTool IOCTLs +// + +#define FILE_DEVICE_SPB_PERIPHERAL 0x400 + +#define IOCTL_SPBTESTTOOL_OPEN CTL_CODE(FILE_DEVICE_SPB_PERIPHERAL, 0x700, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SPBTESTTOOL_CLOSE CTL_CODE(FILE_DEVICE_SPB_PERIPHERAL, 0x701, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SPBTESTTOOL_LOCK CTL_CODE(FILE_DEVICE_SPB_PERIPHERAL, 0x702, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SPBTESTTOOL_UNLOCK CTL_CODE(FILE_DEVICE_SPB_PERIPHERAL, 0x703, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SPBTESTTOOL_WRITEREAD CTL_CODE(FILE_DEVICE_SPB_PERIPHERAL, 0x704, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SPBTESTTOOL_LOCK_CONNECTION CTL_CODE(FILE_DEVICE_SPB_PERIPHERAL, 0x705, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SPBTESTTOOL_UNLOCK_CONNECTION CTL_CODE(FILE_DEVICE_SPB_PERIPHERAL, 0x706, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SPBTESTTOOL_SIGNAL_INTERRUPT CTL_CODE(FILE_DEVICE_SPB_PERIPHERAL, 0x707, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SPBTESTTOOL_WAIT_ON_INTERRUPT CTL_CODE(FILE_DEVICE_SPB_PERIPHERAL, 0x708, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SPBTESTTOOL_FULL_DUPLEX CTL_CODE(FILE_DEVICE_SPB_PERIPHERAL, 0x709, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#endif _SPBTESTIOCTL_H_
\ No newline at end of file diff --git a/SPB/SpbTestTool/sys/spbtesttool.asl b/SPB/SpbTestTool/sys/spbtesttool.asl new file mode 100644 index 00000000..fcf3c9ac --- /dev/null +++ b/SPB/SpbTestTool/sys/spbtesttool.asl @@ -0,0 +1,26 @@ +// +// Test peripheral device node +// +Device(SPBT) +{ + Name(_HID, "SpbTestTool") + Name(_UID, 1) + Method(_CRS, 0x0, NotSerialized) + { + Name (RBUF, ResourceTemplate () + { + // + // Sample I2C and GPIO resources. Modify to match your + // platform's underlying controllers and connections. + // \_SB.I2C and \_SB.GPIO are paths to predefined I2C + // and GPIO controller instances. + // + // Note: SpbTestTool does not require a GPIO resource. + // Remove as necessary. + // + I2CSerialBus(0x1D, ControllerInitiated, 400000, AddressingMode7Bit, "\\_SB.I2C", , ) + GpioInt(Level, ActiveHigh, Exclusive, PullDown, 0, "\\_SB.GPIO") {1} + }) + Return(RBUF) + } +}
\ No newline at end of file diff --git a/SPB/SpbTestTool/sys/spbtesttool.inx b/SPB/SpbTestTool/sys/spbtesttool.inx Binary files differnew file mode 100644 index 00000000..ae1a4fe4 --- /dev/null +++ b/SPB/SpbTestTool/sys/spbtesttool.inx diff --git a/SPB/SpbTestTool/sys/trace.h b/SPB/SpbTestTool/sys/trace.h new file mode 100644 index 00000000..00601dc8 --- /dev/null +++ b/SPB/SpbTestTool/sys/trace.h @@ -0,0 +1,54 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + trace.h + +Abstract: + + This module contains the trace definitions for the SPB + peripheral driver. + +Environment: + + kernel-mode only + +Revision History: + +--*/ + +#ifndef _TRACE_H_ +#define _TRACE_H_ + +extern "C" +{ +// +// Tracing Definitions: +// +// Control GUID: +// {73e3b785-f5fb-423e-94a9-56627fea9053} +// + +#define WPP_CONTROL_GUIDS \ + WPP_DEFINE_CONTROL_GUID( \ + SpbTestToolTraceGuid, \ + (73e3b785,f5fb,423e,94a9,56627fea9053), \ + WPP_DEFINE_BIT(TRACE_FLAG_WDFLOADING) \ + WPP_DEFINE_BIT(TRACE_FLAG_SPBAPI) \ + WPP_DEFINE_BIT(TRACE_FLAG_OTHER) \ + ) +} + +#define WPP_LEVEL_FLAGS_LOGGER(level,flags) WPP_LEVEL_LOGGER(flags) +#define WPP_LEVEL_FLAGS_ENABLED(level, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= level) + +// begin_wpp config +// FUNC FuncEntry{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS); +// FUNC FuncExit{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS); +// USEPREFIX(FuncEntry, "%!STDPREFIX! [%!FUNC!] --> entry"); +// USEPREFIX(FuncExit, "%!STDPREFIX! [%!FUNC!] <--"); +// end_wpp + +#endif _TRACE_H_ |
