summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDipannita Shaw <[email protected]>2021-04-27 14:26:21 -0700
committerDipannita Shaw <[email protected]>2021-04-27 14:26:21 -0700
commit78a1795995814a0bac43042f7ca68e83ab525bd5 (patch)
tree8e2eb0e8c3a11220f2f119964c6c6e3674eda0da
parent465e27457dd3b47cf64e4b7274705cc6acc011a6 (diff)
parent672fafbcc455cd97172b2df78040c7c405e32d00 (diff)
Merge remote-tracking branch 'upstream/master'
-rw-r--r--.gitmodules3
-rw-r--r--README.md37
-rw-r--r--TrEE/README.md12
-rw-r--r--audio/simpleaudiosample/Package/package.VcxProj128
-rw-r--r--audio/simpleaudiosample/Package/package.VcxProj.Filters21
-rw-r--r--audio/simpleaudiosample/README.md133
-rw-r--r--audio/simpleaudiosample/SimpleAudioSample.sln113
-rw-r--r--audio/simpleaudiosample/Source/Filters/Filters.vcxproj282
-rw-r--r--audio/simpleaudiosample/Source/Filters/Filters.vcxproj.Filters27
-rw-r--r--audio/simpleaudiosample/Source/Filters/micarray1toptable.h210
-rw-r--r--audio/simpleaudiosample/Source/Filters/micarraytopo.cpp825
-rw-r--r--audio/simpleaudiosample/Source/Filters/micarraytopo.h97
-rw-r--r--audio/simpleaudiosample/Source/Filters/micarraywavtable.h292
-rw-r--r--audio/simpleaudiosample/Source/Filters/minipairs.h177
-rw-r--r--audio/simpleaudiosample/Source/Filters/speakertopo.cpp118
-rw-r--r--audio/simpleaudiosample/Source/Filters/speakertopo.h22
-rw-r--r--audio/simpleaudiosample/Source/Filters/speakertoptable.h206
-rw-r--r--audio/simpleaudiosample/Source/Filters/speakerwavtable.h (renamed from audio/sysvad/PhoneAudioSample/FMWavTable.h)152
-rw-r--r--audio/simpleaudiosample/Source/Inc/Inc.vcxproj260
-rw-r--r--audio/simpleaudiosample/Source/Inc/Inc.vcxproj.Filters27
-rw-r--r--audio/simpleaudiosample/Source/Inc/NewDelete.h104
-rw-r--r--audio/simpleaudiosample/Source/Inc/basetopo.h96
-rw-r--r--audio/simpleaudiosample/Source/Inc/common.h477
-rw-r--r--audio/simpleaudiosample/Source/Inc/definitions.h198
-rw-r--r--audio/simpleaudiosample/Source/Inc/endpoints.h133
-rw-r--r--audio/simpleaudiosample/Source/Inc/kshelper.h159
-rw-r--r--audio/simpleaudiosample/Source/Inc/mintopo.h81
-rw-r--r--audio/simpleaudiosample/Source/Main/Main.vcxproj (renamed from audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj)205
-rw-r--r--audio/simpleaudiosample/Source/Main/Main.vcxproj.Filters44
-rw-r--r--audio/simpleaudiosample/Source/Main/NewDelete.cpp141
-rw-r--r--audio/simpleaudiosample/Source/Main/SimpleAudioSample.inxbin0 -> 15164 bytes
-rw-r--r--audio/simpleaudiosample/Source/Main/SimpleAudioSample.rc (renamed from audio/sysvad/PhoneAudioSample/PhoneAudioSample.rc)10
-rw-r--r--audio/simpleaudiosample/Source/Main/adapter.cpp844
-rw-r--r--audio/simpleaudiosample/Source/Main/basetopo.cpp688
-rw-r--r--audio/simpleaudiosample/Source/Main/common.cpp2772
-rw-r--r--audio/simpleaudiosample/Source/Main/mintopo.cpp (renamed from audio/sysvad/PhoneAudioSample/handsetspeakertopo.cpp)170
-rw-r--r--audio/simpleaudiosample/Source/Main/minwavert.cpp1683
-rw-r--r--audio/simpleaudiosample/Source/Main/minwavert.h302
-rw-r--r--audio/simpleaudiosample/Source/Main/minwavertstream.cpp1644
-rw-r--r--audio/simpleaudiosample/Source/Main/minwavertstream.h248
-rw-r--r--audio/simpleaudiosample/Source/Utilities/ToneGenerator.cpp285
-rw-r--r--audio/simpleaudiosample/Source/Utilities/ToneGenerator.h74
-rw-r--r--audio/simpleaudiosample/Source/Utilities/Utilities.vcxproj284
-rw-r--r--audio/simpleaudiosample/Source/Utilities/Utilities.vcxproj.Filters (renamed from audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj.Filters)23
-rw-r--r--audio/simpleaudiosample/Source/Utilities/hw.cpp446
-rw-r--r--audio/simpleaudiosample/Source/Utilities/hw.h105
-rw-r--r--audio/simpleaudiosample/Source/Utilities/kshelper.cpp958
-rw-r--r--audio/simpleaudiosample/Source/Utilities/savedata.cpp1033
-rw-r--r--audio/simpleaudiosample/Source/Utilities/savedata.h189
-rw-r--r--audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj18
-rw-r--r--audio/sysvad/EndpointsCommon/mintopo.cpp3
-rw-r--r--audio/sysvad/EndpointsCommon/mintopo.h18
-rw-r--r--audio/sysvad/EndpointsCommon/minwavertstream.cpp4
-rw-r--r--audio/sysvad/EndpointsCommon/speakertopo.cpp1
-rw-r--r--audio/sysvad/EndpointsCommon/speakertoptable.h13
-rw-r--r--audio/sysvad/Package/package.VcxProj37
-rw-r--r--audio/sysvad/PhoneAudioSample/CellularWave.cpp685
-rw-r--r--audio/sysvad/PhoneAudioSample/CellularWave.h126
-rw-r--r--audio/sysvad/PhoneAudioSample/Cellulartopo.cpp1117
-rw-r--r--audio/sysvad/PhoneAudioSample/Cellulartopo.h184
-rw-r--r--audio/sysvad/PhoneAudioSample/Cellulartoptable.h267
-rw-r--r--audio/sysvad/PhoneAudioSample/Cellularwavtable.h286
-rw-r--r--audio/sysvad/PhoneAudioSample/FMTopTable.h199
-rw-r--r--audio/sysvad/PhoneAudioSample/FMTopo.cpp985
-rw-r--r--audio/sysvad/PhoneAudioSample/FMTopo.h152
-rw-r--r--audio/sysvad/PhoneAudioSample/FMWave.cpp389
-rw-r--r--audio/sysvad/PhoneAudioSample/FMWave.h84
-rw-r--r--audio/sysvad/PhoneAudioSample/handsetmictopo.cpp274
-rw-r--r--audio/sysvad/PhoneAudioSample/handsetmictopo.h21
-rw-r--r--audio/sysvad/PhoneAudioSample/handsetmictoptable.h245
-rw-r--r--audio/sysvad/PhoneAudioSample/handsetmicwavtable.h447
-rw-r--r--audio/sysvad/PhoneAudioSample/handsetspeakertopo.h86
-rw-r--r--audio/sysvad/PhoneAudioSample/handsetspeakertoptable.h156
-rw-r--r--audio/sysvad/PhoneAudioSample/handsetspeakerwavtable.h550
-rw-r--r--audio/sysvad/PhoneAudioSample/michstopo.cpp275
-rw-r--r--audio/sysvad/PhoneAudioSample/michstopo.h21
-rw-r--r--audio/sysvad/PhoneAudioSample/michstoptable.h257
-rw-r--r--audio/sysvad/PhoneAudioSample/michswavtable.h447
-rw-r--r--audio/sysvad/PhoneAudioSample/minipairs.h602
-rw-r--r--audio/sysvad/PhoneAudioSample/phoneaudiosample.inxbin45990 -> 0 bytes
-rw-r--r--audio/sysvad/PhoneAudioSample/speakerhstopo.cpp275
-rw-r--r--audio/sysvad/PhoneAudioSample/speakerhstopo.h21
-rw-r--r--audio/sysvad/PhoneAudioSample/speakerhstoptable.h168
-rw-r--r--audio/sysvad/PhoneAudioSample/speakerhswavtable.h755
-rw-r--r--audio/sysvad/README.md176
-rw-r--r--audio/sysvad/TabletAudioSample/ComponentizedApoSample.inxbin18736 -> 18770 bytes
-rw-r--r--audio/sysvad/TabletAudioSample/ComponentizedAudioSample.inxbin50422 -> 50506 bytes
-rw-r--r--audio/sysvad/TabletAudioSample/ComponentizedAudioSampleExtension.inxbin11338 -> 11262 bytes
-rw-r--r--audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj20
-rw-r--r--audio/sysvad/TabletAudioSample/tabletaudiosample.inxbin72830 -> 72864 bytes
-rw-r--r--audio/sysvad/adapter.cpp2
-rw-r--r--audio/sysvad/common.cpp6
-rw-r--r--audio/sysvad/common.h3
-rw-r--r--audio/sysvad/sysvad.sln22
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/APODeviceTest.cpp1120
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/APODeviceTest.h180
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/APOOSUpgradeTest.cpp96
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/APOOSUpgradeTest.h38
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/APOStressTest.cpp777
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/APOStressTest.h50
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/CAPXHelper.cpp247
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/CAPXHelper.h33
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/CAPXLoggingFrameworkTests.cpp160
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/CAPXLoggingFrameworkTests.h73
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/CAPXNotificationFrameworkTests.cpp168
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/CAPXNotificationFrameworkTests.h84
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/CAPXThreadingFrameworkTests.cpp118
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/CAPXThreadingFrameworkTests.h73
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/FormatHelpers.h330
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/TestEffectsList.cpp225
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/TestMediaType.cpp227
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/TestMediaType.h163
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/TestWasapiUseFromAudioDg.cpp244
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/Wrappers.h121
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/audioconnectionutil.h129
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/sinewave.h60
-rw-r--r--audio/tests/HLK/ThirdPartyApoTests/stdafx.h123
-rw-r--r--audio/tests/KSPosTst/KsPosTestTaef.cpp215
-rw-r--r--audio/tests/KSPosTst/PreComp.h108
-rw-r--r--audio/tests/KSPosTst/TestResourceBuild.cpp522
-rw-r--r--audio/tests/KSPosTst/locallimits.h25
-rw-r--r--audio/tests/KSPosTst/pintest.cpp518
-rw-r--r--audio/tests/KSPosTst/tests.h18
-rw-r--r--audio/tests/KSPosTst/timetest.cpp50
-rw-r--r--audio/tests/PinResourceHelpers/HalfApp.cpp (renamed from audio/tests/wavetest/HalfApp.cpp)73
-rw-r--r--audio/tests/PinResourceHelpers/PreComp.h143
-rw-r--r--audio/tests/PinResourceHelpers/PropertyHelper.cpp (renamed from audio/tests/wavetest/PropertyHelper.cpp)172
-rw-r--r--audio/tests/PinResourceHelpers/TestResource.cpp (renamed from audio/tests/wavetest/TestResource.cpp)6
-rw-r--r--audio/tests/PinResourceHelpers/TestResourceHelper.h (renamed from audio/tests/wavetest/TestResourceHelper.h)4
-rw-r--r--audio/tests/wavetest/HalfApp.h195
-rw-r--r--audio/tests/wavetest/PreComp.h107
-rw-r--r--audio/tests/wavetest/PropertyHelper.h190
-rw-r--r--audio/tests/wavetest/TestResource.h66
-rw-r--r--audio/tests/wavetest/TestResourceBuild.cpp55
-rw-r--r--audio/tests/wavetest/WaveTestTaef.cpp6
-rw-r--r--audio/tests/wavetest/WaveTestTaef.h5
-rw-r--r--audio/tests/wavetest/comptest.cpp15
-rw-r--r--audio/tests/wavetest/tests.h2
-rw-r--r--avstream/avscamera/Package/package.VcxProj24
-rw-r--r--avstream/avscamera/README.md10
-rw-r--r--avstream/avscamera/common/MetadataInternal.h3
-rw-r--r--avstream/avscamera/mft0/MFT0Impl.cpp15
-rw-r--r--avstream/avscamera/mft0/MFT0Impl.h4
-rw-r--r--avstream/avscamera/mft0/README.md33
-rw-r--r--avstream/avscamera/mft0/stdafx.h9
-rw-r--r--avstream/avscamera/sys/AvsCamera.cpp25
-rw-r--r--avstream/avscamera/sys/AvsCamera.vcxproj14
-rw-r--r--avstream/avscamera/sys/AvsCameraFilter.cpp11
-rw-r--r--avstream/avscamera/sys/Capture.cpp17
-rw-r--r--avstream/avscamera/sys/Common.h6
-rw-r--r--avstream/avscamera/sys/Device.cpp22
-rw-r--r--avstream/avscamera/sys/Device.h13
-rw-r--r--avstream/avscamera/sys/PreviewHwSim.cpp32
-rw-r--r--avstream/avscamera/sys/PreviewHwSim.h4
-rw-r--r--avstream/avscamera/sys/Sensor.cpp49
-rw-r--r--avstream/avscamera/sys/Sensor.h14
-rw-r--r--avstream/avscamera/sys/SensorSimulation.cpp82
-rw-r--r--avstream/avscamera/sys/SensorSimulation.h8
-rw-r--r--avstream/avscamera/sys/VideoHwSim.cpp49
-rw-r--r--avstream/avscamera/sys/VideoHwSim.h4
-rw-r--r--avstream/avscamera/sys/avscamera.inx (renamed from avstream/avscamera/sys/avscamera.inf)bin26816 -> 25260 bytes
-rw-r--r--avstream/avscamera/sys/filter.cpp183
-rw-r--r--avstream/avscamera/sys/filter.h8
-rw-r--r--avstream/avscamera/sys/hwsim.cpp46
-rw-r--r--avstream/avscamera/sys/imagecapture.cpp4
-rw-r--r--avstream/avshws/README.md96
-rw-r--r--avstream/avshws/avshws.inf173
-rw-r--r--avstream/avshws/avshws.inxbin0 -> 5974 bytes
-rw-r--r--avstream/avshws/avshws.sln5
-rw-r--r--avstream/avshws/avshws.vcxproj14
-rw-r--r--avstream/avshws/capture.cpp2
-rw-r--r--avstream/avshws/device.cpp25
-rw-r--r--avstream/avshws/hwsim.cpp2
-rw-r--r--avstream/avshws/makefile15
-rw-r--r--avstream/avssamp/Filter.cpp6
-rw-r--r--avstream/avssamp/README.md76
-rw-r--r--avstream/avssamp/avssamp.cpp16
-rw-r--r--avstream/avssamp/avssamp.inf93
-rw-r--r--avstream/avssamp/avssamp.inxbin0 -> 3256 bytes
-rw-r--r--avstream/avssamp/avssamp.vcxproj14
-rw-r--r--avstream/avssamp/avssamp.vcxproj.Filters28
-rw-r--r--avstream/avssamp/makefile15
-rw-r--r--avstream/avssamp/video.cpp6
-rw-r--r--avstream/avssamp/wave.cpp2
-rw-r--r--avstream/sampledevicemft/README.md35
-rw-r--r--avstream/sampledevicemft/basepin.cpp171
-rw-r--r--avstream/sampledevicemft/basepin.h64
-rw-r--r--avstream/sampledevicemft/common.h11
-rw-r--r--avstream/sampledevicemft/contosodevice.h28
-rw-r--r--avstream/sampledevicemft/custompin.cpp2
-rw-r--r--avstream/sampledevicemft/dllmain.cpp24
-rw-r--r--avstream/sampledevicemft/multipinmft.cpp66
-rw-r--r--avstream/sampledevicemft/multipinmft.h20
-rw-r--r--avstream/sampledevicemft/multipinmft.vcxproj23
-rw-r--r--avstream/sampledevicemft/multipinmft.vcxproj.Filters26
-rw-r--r--avstream/sampledevicemft/multipinmfthelpers.cpp396
-rw-r--r--avstream/sampledevicemft/multipinmfthelpers.h211
-rw-r--r--avstream/sampledevicemft/multipinmftutils.cpp86
-rw-r--r--avstream/sampledevicemft/packages.config4
-rw-r--r--avstream/sampledevicemft/stdafx.h8
-rw-r--r--avstream/samplemft0/README.md35
-rw-r--r--biometrics/README.md37
-rw-r--r--bluetooth/bthecho/README.md124
-rw-r--r--bluetooth/bthecho/bthsrv/README.md228
-rw-r--r--bluetooth/serialhcibus/README.md39
-rw-r--r--bluetooth/serialhcibus/WDK/device.c23
-rw-r--r--bluetooth/serialhcibus/driver.h61
-rw-r--r--bluetooth/serialhcibus/pdo.c342
-rw-r--r--filesys/cdfs/README.md10
-rw-r--r--filesys/fastfat/README.md40
-rw-r--r--filesys/fastfat/fsctrl.c44
-rw-r--r--filesys/fastfat/volinfo.c9
-rw-r--r--filesys/miniFilter/MetadataManager/README.md12
-rw-r--r--filesys/miniFilter/NameChanger/README.md77
-rw-r--r--filesys/miniFilter/avscan/README.md10
-rw-r--r--filesys/miniFilter/cancelSafe/README.md15
-rw-r--r--filesys/miniFilter/cdo/README.md15
-rw-r--r--filesys/miniFilter/change/README.md12
-rw-r--r--filesys/miniFilter/ctx/README.md12
-rw-r--r--filesys/miniFilter/delete/README.md15
-rw-r--r--filesys/miniFilter/minispy/README.md12
-rw-r--r--filesys/miniFilter/nullFilter/README.md12
-rw-r--r--filesys/miniFilter/passThrough/README.md12
-rw-r--r--filesys/miniFilter/scanner/README.md12
-rw-r--r--filesys/miniFilter/simrep/README.md12
-rw-r--r--filesys/miniFilter/swapBuffers/README.md12
-rw-r--r--general/DCHU/README.md36
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/driver.c2
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inxbin10266 -> 4248 bytes
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj2
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj2
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj2
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/CppWindowsService.cpp74
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.cpp856
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.h155
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.cpp192
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.h144
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.cpp1217
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.h328
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.cpp254
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.h187
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.cpp794
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.h423
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.cpp375
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.h56
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ThreadPool.h80
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.cpp156
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.h111
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.inxbin3190 -> 0 bytes
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj30
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/stdafx.h26
-rw-r--r--general/PLX9x5x/README.md22
-rw-r--r--general/SimpleMediaSource/README.md43
-rw-r--r--general/SimpleMediaSource/general-SimpleMediaSource.yaml10
-rw-r--r--general/SystemDma/wdm/README.md15
-rw-r--r--general/WinHEC 2017 Lab/README.md12
-rw-r--r--general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.c2
-rw-r--r--general/cancel/README.md19
-rw-r--r--general/echo/kmdf/README.md47
-rw-r--r--general/echo/kmdf/driver/AutoSync/queue.c2
-rw-r--r--general/echo/kmdf/driver/DriverSync/queue.c2
-rw-r--r--general/echo/umdf/README.md52
-rw-r--r--general/echo/umdf2/README.md45
-rw-r--r--general/echo/umdfSocketEcho/README.md85
-rw-r--r--general/event/README.md15
-rw-r--r--general/filehistory/README.md12
-rw-r--r--general/ioctl/kmdf/README.md21
-rw-r--r--general/ioctl/kmdf/sys/nonpnp.c4
-rw-r--r--general/ioctl/wdm/README.md15
-rw-r--r--general/obcallback/README.md16
-rw-r--r--general/pcidrv/README.md60
-rw-r--r--general/perfcounters/kcs/README.md14
-rw-r--r--general/registry/regfltr/README.md22
-rw-r--r--general/toaster/toastDrv/README.md93
-rw-r--r--general/toaster/toastDrv/kmdf/bus/dynamic/busenum.c2
-rw-r--r--general/toaster/toastDrv/kmdf/bus/dynamic/buspdo.c4
-rw-r--r--general/toaster/toastDrv/kmdf/bus/static/busenum.c2
-rw-r--r--general/toaster/toastDrv/kmdf/filter/generic/filter.c2
-rw-r--r--general/toaster/toastDrv/kmdf/func/featured/toaster.c2
-rw-r--r--general/toaster/toastDrv/kmdf/func/featured/wmi.c4
-rw-r--r--general/toaster/toastDrv/kmdf/func/simple/toaster.c2
-rw-r--r--general/toaster/toastDrv/kmdf/toastmon/toastmon.c2
-rw-r--r--general/toaster/toastpkg/README.md91
-rw-r--r--general/toaster/umdf2/README.md27
-rw-r--r--general/toaster/umdf2/filter/generic/filter.c2
-rw-r--r--general/toaster/umdf2/func/featured/toaster.c2
-rw-r--r--general/toaster/umdf2/func/simple/toaster.c2
-rw-r--r--general/tracing/SystemTraceControl/README.md16
-rw-r--r--general/tracing/evntdrv/README.md46
-rw-r--r--general/tracing/tracedriver/README.md37
-rw-r--r--general/umdfSkeleton/README.md10
-rw-r--r--gnss/ReadMe.md113
-rw-r--r--gpio/samples/README.md24
-rw-r--r--gpio/samples/simdevice/umdf/simdeviceumdf.inxbin3958 -> 1929 bytes
-rw-r--r--hid/firefly/README.md55
-rw-r--r--hid/hclient/README.md14
-rw-r--r--hid/hclient/report.c3
-rw-r--r--hid/hidusbfx2/README.md296
-rw-r--r--hid/vhidmini2/README.md18
-rw-r--r--hid/vhidmini2/inc/common.h1
-rw-r--r--input/kbfiltr/README.md76
-rw-r--r--input/kbfiltr/sys/kbfiltr.c2
-rw-r--r--input/layout/README.md53
-rw-r--r--input/moufiltr/README.md10
-rw-r--r--input/moufiltr/moufiltr.c2
-rw-r--r--network/config/bindview/README.md12
-rw-r--r--network/modem/fakemodem/README.md10
-rw-r--r--network/ndis/extension/README.md12
-rw-r--r--network/ndis/filter/README.md136
-rw-r--r--network/ndis/filter/ndislwf.vcxproj12
-rw-r--r--network/ndis/filter/ndislwf.vcxproj.Filters19
-rw-r--r--network/ndis/mux/README.md121
-rw-r--r--network/ndis/ndisprot/6x/README.md73
-rw-r--r--network/ndis/ndisprot/6x/sys/60/ndisprot60.vcxproj12
-rw-r--r--network/ndis/ndisprot/6x/sys/60/ndisprot60.vcxproj.Filters5
-rw-r--r--network/ndis/ndisprot_kmdf/README.md98
-rw-r--r--network/ndis/netvmini/6x/README.md15
-rw-r--r--network/radio/HidSwitchDriverSample/README.md36
-rw-r--r--network/radio/RadioManagerSample/README.md86
-rw-r--r--network/trans/WFPSampler/README.md154
-rw-r--r--network/trans/WFPSampler/sys/Framework_Events.cpp19
-rw-r--r--network/trans/WFPSampler/sys/Framework_PowerStates.cpp145
-rw-r--r--network/trans/WFPSampler/sys/Framework_WFPSamplerCalloutDriver.cpp24
-rw-r--r--network/trans/WFPSampler/sys/Framework_WFPSamplerCalloutDriver.h3
-rw-r--r--network/trans/WFPSampler/sys/WFPSamplerCalloutDriver.InX8
-rw-r--r--network/trans/WFPSampler/syslib/HelperFunctions_Macros.h36
-rw-r--r--network/trans/WFPSampler/syslib/HelperFunctions_WorkItems.cpp65
-rw-r--r--network/trans/ddproxy/README.md70
-rw-r--r--network/trans/ddproxy/sys/DD_proxy.c2
-rw-r--r--network/trans/inspect/README.md59
-rw-r--r--network/trans/inspect/inspect.sln17
-rw-r--r--network/trans/inspect/sys/inspect.c2
-rw-r--r--network/trans/inspect/sys/inspect.vcxproj18
-rw-r--r--network/trans/inspect/sys/inspect.vcxproj.Filters13
-rw-r--r--network/trans/msnmntr/README.md74
-rw-r--r--network/trans/msnmntr/sys/msnmntr.c12
-rw-r--r--network/trans/msnmntr/sys/notify.c6
-rw-r--r--network/trans/stmedit/README.md90
-rw-r--r--network/wlan/WDI/HAL/phydm/phydm.h4
-rw-r--r--network/wlan/WDI/PLATFORM/NDIS6/SDIO/N6SdioPlatformWindows.c30
-rw-r--r--network/wlan/WDI/PLATFORM/NDIS6/SDIO/N6Sdio_main.c7
-rw-r--r--network/wlan/WDI/PLATFORM/NDIS6/SDIO/sdio.vcxproj12
-rw-r--r--network/wlan/WDI/PLATFORM/NDIS6/WDI_Cmds.c10
-rw-r--r--network/wlan/WDI/README.md10
-rw-r--r--network/wlan/ihvsampleui/README.md10
-rw-r--r--network/wsk/echosrv/README.md51
-rw-r--r--nfc/NfcCxSample/README.md3
-rw-r--r--nfp/net/README.md31
-rw-r--r--nfp/net/inc/README.md27
-rw-r--r--pofx/PEP/README.md18
-rw-r--r--pofx/UMDF2/Driver/SingleComp/driver.c2
-rw-r--r--pofx/UMDF2/README.md51
-rw-r--r--pofx/WDF/Driver/MultiComp/WdfMultiComp.mht2807
-rw-r--r--pofx/WDF/Driver/SingleComp/driver.c2
-rw-r--r--pofx/WDF/README.md108
-rw-r--r--pofx/WDF/WdfMultiComp_overview.svg240
-rw-r--r--pos/drivers/MagneticStripeReader/README.md10
-rw-r--r--pos/drivers/MagneticStripeReader/SampleMagneticStripeReaderDrv.inf30
-rw-r--r--pos/drivers/barcodescanner/README.md10
-rw-r--r--pos/drivers/barcodescanner/SampleBarcodeScannerDrv.inf30
-rw-r--r--print/OEM Printer Customization Plug-in Samples/README.md88
-rw-r--r--print/SampleOpenXPS/README.md12
-rw-r--r--print/SampleXPS/README.md12
-rw-r--r--print/SimplePipelineFilter/README.md14
-rw-r--r--print/XPSDrvSmpl/README.md72
-rw-r--r--print/XpsRasFilter/README.md23
-rw-r--r--print/autoconfig/README.md31
-rw-r--r--print/cpsuisam/README.md12
-rw-r--r--print/v4PrintDriverSamples/PrinterExtensionSample/README.md19
-rw-r--r--print/v4PrintDriverSamples/v4PrintDriver-ConstraintScript/README.md26
-rw-r--r--print/v4PrintDriverSamples/v4PrintDriver-HostBasedSampleDriver/HostBasedSampleDriver.vcxproj18
-rw-r--r--print/v4PrintDriverSamples/v4PrintDriver-HostBasedSampleDriver/Package/package.VcxProj30
-rw-r--r--print/v4PrintDriverSamples/v4PrintDriver-HostBasedSampleDriver/README.md50
-rw-r--r--print/v4PrintDriverSamples/v4PrintDriver-USBMon-Bidi-Extension/README.md29
-rw-r--r--print/v4PrintDriverSamples/v4PrintDriver-WSDMon-Bidi-Extension/README.md18
-rw-r--r--sd/miniport/sdhc/README.md18
-rw-r--r--security/elam/README.md24
-rw-r--r--sensors/ADXL345Acc/ADXL345Acc.vcxproj12
-rw-r--r--sensors/ADXL345Acc/readme.md14
-rw-r--r--sensors/Activity/Activity.vcxproj12
-rw-r--r--sensors/Activity/readme.md12
-rw-r--r--sensors/CustomSensors/CustomSensors.vcxproj12
-rw-r--r--sensors/CustomSensors/readme.md14
-rw-r--r--sensors/Fusion/FusionSensor.vcxproj12
-rw-r--r--sensors/Fusion/readme.md14
-rw-r--r--sensors/Pedometer/Pedometer.vcxproj12
-rw-r--r--sensors/Pedometer/readme.md18
-rw-r--r--sensors/SensorsComboDriver/SensorsComboDriver.vcxproj12
-rw-r--r--sensors/SensorsComboDriver/readme.md14
-rw-r--r--sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.vcxproj12
-rw-r--r--sensors/SimpleDeviceOrientationSensor/readme.md16
-rw-r--r--serial/VirtualSerial/README.md25
-rw-r--r--serial/VirtualSerial2/README.md27
-rw-r--r--serial/serenum/README.md33
-rw-r--r--serial/serial/README.md22
-rw-r--r--serial/serial/ioctl.c4
-rw-r--r--serial/serial/openclos.c12
-rw-r--r--serial/serial/wdfserial.vcxproj12
-rw-r--r--setup/devcon/README.md51
-rw-r--r--simbatt/README.md18
-rw-r--r--simbatt/func/simbatt.vcxproj14
-rw-r--r--simbatt/func/simbatt.vcxproj.Filters19
-rw-r--r--smartcrd/README.md20
-rw-r--r--spb/SkeletonI2C/README.md37
-rw-r--r--spb/SkeletonI2C/internal.h4
-rw-r--r--spb/SpbTestTool/README.md126
-rw-r--r--storage/class/cdrom/README.md33
-rw-r--r--storage/class/classpnp/README.md12
-rw-r--r--storage/class/classpnp/src/autorun.c43
-rw-r--r--storage/class/classpnp/src/class.c182
-rw-r--r--storage/class/classpnp/src/classp.h1
-rw-r--r--storage/class/classpnp/src/classwmi.c3
-rw-r--r--storage/class/classpnp/src/debug.c5
-rw-r--r--storage/class/classpnp/src/dictlib.c7
-rw-r--r--storage/class/classpnp/src/lock.c9
-rw-r--r--storage/class/classpnp/src/power.c4
-rw-r--r--storage/class/classpnp/src/srblib.c2
-rw-r--r--storage/class/classpnp/src/utils.c138
-rw-r--r--storage/class/classpnp/src/xferpkt.c69
-rw-r--r--storage/class/disk/README.md20
-rw-r--r--storage/filters/addfilter/README.md17
-rw-r--r--storage/iscsi/README.md12
-rw-r--r--storage/miniports/lsi_u3/README.md17
-rw-r--r--storage/miniports/storahci/README.md12
-rw-r--r--storage/miniports/storahci/src/ahci.h107
-rw-r--r--storage/miniports/storahci/src/common.c1397
-rw-r--r--storage/miniports/storahci/src/common.h137
-rw-r--r--storage/miniports/storahci/src/data.h96
-rw-r--r--storage/miniports/storahci/src/entrypts.c872
-rw-r--r--storage/miniports/storahci/src/entrypts.h159
-rw-r--r--storage/miniports/storahci/src/generic.h2
-rw-r--r--storage/miniports/storahci/src/hbastat.c595
-rw-r--r--storage/miniports/storahci/src/hbastat.h1
-rw-r--r--storage/miniports/storahci/src/inbox/storahci.vcxproj37
-rw-r--r--storage/miniports/storahci/src/io.c639
-rw-r--r--storage/miniports/storahci/src/io.h1
-rw-r--r--storage/miniports/storahci/src/pnppower.c731
-rw-r--r--storage/miniports/storahci/src/pnppower.h4
-rw-r--r--storage/miniports/storahci/src/util.c331
-rw-r--r--storage/miniports/storahci/src/util.h423
-rw-r--r--storage/msdsm/README.md25
-rw-r--r--storage/msdsm/src/SampleDSM.infbin5354 -> 5388 bytes
-rw-r--r--storage/msdsm/src/intrface.c5
-rw-r--r--storage/msdsm/src/precomp.h1
-rw-r--r--storage/msdsm/src/prototypes.h4
-rw-r--r--storage/msdsm/src/utils.c8
-rw-r--r--storage/sfloppy/README.md14
-rw-r--r--storage/sfloppy/src/floppy.c8
-rw-r--r--storage/tools/spti/README.md14
-rw-r--r--thermal/simsensor/README.md14
-rw-r--r--thermal/thermalclient/README.md16
-rw-r--r--tools/dv/samples/DV-FailDriver-WDM/README.md21
-rw-r--r--tools/dv/samples/DV-FailDriver-WDM/driver/defect_toastmon.inf1
-rw-r--r--tools/dv/samples/DV-FailDriver-WDM/driver/defect_toastmon.vcxproj12
-rw-r--r--tools/sdv/samples/SDV-FailDriver-KMDF/README.md44
-rw-r--r--tools/sdv/samples/SDV-FailDriver-KMDF/driver/fail_driver1.vcxproj12
-rw-r--r--tools/sdv/samples/SDV-FailDriver-KMDF/driver/fail_driver1.vcxproj.Filters5
-rw-r--r--tools/sdv/samples/SDV-FailDriver-KMDF/library/fail_library1.vcxproj12
-rw-r--r--tools/sdv/samples/SDV-FailDriver-KMDF/library/fail_library1.vcxproj.Filters5
-rw-r--r--tools/sdv/samples/SDV-FailDriver-NDIS/README.md33
-rw-r--r--tools/sdv/samples/SDV-FailDriver-NDIS/driver/sdvmp.vcxproj12
-rw-r--r--tools/sdv/samples/SDV-FailDriver-NDIS/driver/sdvmp.vcxproj.Filters5
-rw-r--r--tools/sdv/samples/SDV-FailDriver-STORPORT/README.md39
-rw-r--r--tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.c2
-rw-r--r--tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.vcxproj12
-rw-r--r--tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.vcxproj.Filters26
-rw-r--r--tools/sdv/samples/SDV-FailDriver-WDM/README.md33
-rw-r--r--tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.c3
-rw-r--r--tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.vcxproj12
-rw-r--r--tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.vcxproj.Filters5
-rw-r--r--usb/UcmCxUcsi/Acpi.cpp8
-rw-r--r--usb/UcmCxUcsi/README.md37
-rw-r--r--usb/UcmCxUcsi/UcmCxUcsi.vcxproj3
-rw-r--r--usb/UcmTcpciCxClientSample/README.md117
-rw-r--r--usb/UcmUcsiAcpiSample/README.md25
-rw-r--r--usb/UcmUcsiAcpiSample/UcmUcsiAcpiSample/UcmUcsiAcpiSample.vcxproj8
-rw-r--r--usb/kmdf_enumswitches/README.md32
-rw-r--r--usb/kmdf_enumswitches/sys/driver.c2
-rw-r--r--usb/kmdf_enumswitches/sys/kmdf_enumswitches.vcxproj24
-rw-r--r--usb/kmdf_fx2/README.md226
-rw-r--r--usb/kmdf_fx2/driver/driver.c2
-rw-r--r--usb/kmdf_fx2/driver/osrusbfx2.vcxproj24
-rw-r--r--usb/ufxclientsample/README.md17
-rw-r--r--usb/ufxclientsample/device.c4
-rw-r--r--usb/umdf2_fx2/README.md31
-rw-r--r--usb/umdf2_fx2/driver/driver.c2
-rw-r--r--usb/umdf2_fx2/driver/osrusbfx2um.vcxproj14
-rw-r--r--usb/umdf_filter_kmdf/README.md67
-rw-r--r--usb/umdf_filter_kmdf/kmdf_driver/driver.c2
-rw-r--r--usb/umdf_filter_umdf/README.md47
-rw-r--r--usb/umdf_fx2/README.md303
-rw-r--r--usb/usbsamp/README.md59
-rw-r--r--usb/usbsamp/sys/driver.c2
-rw-r--r--usb/usbsamp/sys/private.h5
-rw-r--r--usb/usbsamp/sys/stream.c4
-rw-r--r--usb/usbview/README.md46
-rw-r--r--usb/wdf_osrfx2_lab/README.md408
-rw-r--r--video/IndirectDisplay/IddSampleApp/IddSampleApp.vcxproj276
-rw-r--r--video/IndirectDisplay/IddSampleApp/IddSampleApp.vcxproj.filters22
-rw-r--r--video/IndirectDisplay/IddSampleApp/main.cpp93
-rw-r--r--video/IndirectDisplay/IddSampleDriver.sln69
-rw-r--r--video/IndirectDisplay/IddSampleDriver/Driver.cpp809
-rw-r--r--video/IndirectDisplay/IddSampleDriver/Driver.h122
-rw-r--r--video/IndirectDisplay/IddSampleDriver/IddSampleDriver.infbin0 -> 4580 bytes
-rw-r--r--video/IndirectDisplay/IddSampleDriver/IddSampleDriver.rc10
-rw-r--r--video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj333
-rw-r--r--video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj.filters39
-rw-r--r--video/IndirectDisplay/IddSampleDriver/Trace.h63
-rw-r--r--video/IndirectDisplay/README.md48
-rw-r--r--video/KMDOD/README.md25
-rw-r--r--video/KMDOD/Sample/SampleDisplay.vcxproj12
-rw-r--r--video/KMDOD/Sample/SampleDisplay.vcxproj.Filters2
-rw-r--r--video/pixlib/README.md12
-rw-r--r--wia/README.md14
m---------wil0
-rw-r--r--wmi/wmiacpi/README.md19
-rw-r--r--wmi/wmisamp/README.md21
-rw-r--r--wpd/WpdBasicHardwareDriver/README.md28
-rw-r--r--wpd/WpdHelloWorldDriver/README.md98
-rw-r--r--wpd/WpdMultiTransportDriver/README.md18
-rw-r--r--wpd/WpdServiceSampleDriver/README.md16
-rw-r--r--wpd/WpdWudfSampleDriver/README.md22
522 files changed, 37412 insertions, 22875 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..b0a8d776
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "wil"]
+ path = wil
+ url = https://github.com/microsoft/wil
diff --git a/README.md b/README.md
index 67fc57bd..567ac047 100644
--- a/README.md
+++ b/README.md
@@ -1,42 +1,47 @@
-<!---
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=616507
---->
-
# Driver samples for Windows 10
-These are the official Microsoft Windows Driver Kit (WDK) team driver code samples for Windows 10. They provide a foundation for Universal Windows driver support of all hardware form factors, from phones to desktop PCs. Use these samples with Visual Studio 2015 and Windows Driver Kit (WDK) 10.
+
+These are the official Microsoft Windows Driver Kit (WDK) driver code samples for Windows 10. They provide a foundation for Universal Windows driver support of all hardware form factors, from phones to desktop PCs. Use these samples with Visual Studio 2019 and Windows Driver Kit (WDK) 10.
+
+[Windows Driver Kit documentation](https://docs.microsoft.com/windows-hardware/drivers/)
## Windows 10 driver development
-Use Visual Studio 2015 and Windows Driver Kit (WDK) 10 to build, test, and deploy your drivers. With Windows 10, the driver development environment is integrated into Visual Studio. To get started, download the driver development kits and tools for Windows 10.
-[Download the WDK, WinDbg, and associated tools](https://developer.microsoft.com/en-us/windows/hardware/windows-driver-kit "Download the WDK, WinDbg, and associated tools for Windows 10")
+Use Visual Studio 2019 and Windows Driver Kit (WDK) 10 to build, test, and deploy your drivers. With Windows 10, the driver development environment is integrated into Visual Studio. To get started, download the driver development kits and tools for Windows 10.
+
+[Download the WDK, WinDbg, and associated tools](https://developer.microsoft.com/windows/hardware/windows-driver-kit)
+
+### Windows Driver Kit (WDK)
-### Windows 10 Driver Kit (WDK)
Take a look at the compilation of the new and changed driver-related content for Windows 10. Areas of improvement include camera, print, display, Near Field Communication (NFC), WLAN, Bluetooth, and more.
-[Find out what's new in the WDK](https://go.microsoft.com/fwlink/p/?LinkId=528349 "Find out what's new in the WDK")
+[Find out what's new in the WDK](https://docs.microsoft.com/windows-hardware/drivers/what-s-new-in-driver-development)
### Universal Windows drivers
-Write one driver that runs on both Windows 10 for desktop editions and Windows 10 Mobile devices, as well as other Windows 10 editions that share a common set of interfaces.
-[Getting Started with Universal Windows drivers](https://go.microsoft.com/fwlink/p/?LinkId=524488 "Getting Started with Universal Windows drivers")
+Write one driver that runs on Windows 10 for desktop editions, as well as other Windows 10 editions that share a common set of interfaces.
+
+[Getting Started with Universal Windows drivers](https://docs.microsoft.com/windows-hardware/drivers/develop/getting-started-with-universal-drivers)
### Windows Driver Frameworks
+
The Windows Driver Frameworks (WDF) are a set of libraries that make it simple to write high-quality device drivers.
-[WDF driver development guide](https://go.microsoft.com/fwlink/p/?LinkId=524489 "WDF driver development guide")
+[WDF driver development guide](https://docs.microsoft.com/windows-hardware/drivers/wdf/)
### Samples
+
Use the samples in this repo to guide your Windows driver development. Whether you're just getting started or porting an older driver to the newest version of Windows, code samples are valuable guides on how to write drivers.
### Build your first driver
+
If you're writing your first driver, use these exercises to get started. Each exercise is independent of the others, so you can do them in any order.
-[Write a UMDF driver based on a template](https://go.microsoft.com/fwlink/p/?LinkId=524492 "Write a UMDF driver based on a template")
+[Write a UMDF driver based on a template](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/writing-a-umdf-driver-based-on-a-template)
-[Write a KMDF Hello World driver](https://go.microsoft.com/fwlink/p/?LinkId=524493 "Write a KMDF Hello World driver")
+[Write a KMDF Hello World driver](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/writing-a-very-small-kmdf--driver)
-[Write a KMDF driver based on a template](https://go.microsoft.com/fwlink/p/?LinkId=524494 "Write a KMDF driver based on a template")
+[Write a KMDF driver based on a template](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/writing-a-kmdf-driver-based-on-a-template)
# Microsoft Code of Conduct
-This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [[email protected]](mailto:[email protected]) with any additional questions or comments.
+This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [[email protected]](mailto:[email protected]) with any additional questions or comments.
diff --git a/TrEE/README.md b/TrEE/README.md
index 6c67e24b..066a9812 100644
--- a/TrEE/README.md
+++ b/TrEE/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: TrEE sample
- platform: KMDF
- language: cpp
- category: TrEE
- description: TrEE sample
- samplefwlink: https://go.microsoft.com/fwlink/p/?linkid=869055
---->
-
# TrEE sample
-The Trusted Execution Environment (TrEE) sample. \ No newline at end of file
+The Trusted Execution Environment (TrEE) sample.
diff --git a/audio/simpleaudiosample/Package/package.VcxProj b/audio/simpleaudiosample/Package/package.VcxProj
new file mode 100644
index 00000000..a70e4820
--- /dev/null
+++ b/audio/simpleaudiosample/Package/package.VcxProj
@@ -0,0 +1,128 @@
+<?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|ARM64">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM64">
+ <Configuration>Release</Configuration>
+ <Platform>ARM64</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>
+ <ItemGroup>
+ <ProjectReference Include="..\Source\Main\Main.vcxproj">
+ <Project>{E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <PropertyGroup Label="PropertySheets">
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Utility</ConfigurationType>
+ <DriverType>Package</DriverType>
+ <DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
+ <Configuration>Debug</Configuration>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}</ProjectGuid>
+ <SampleGuid>{E9D167E6-E633-4284-8F02-FF86DF3B6D7F}</SampleGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup />
+ <PropertyGroup>
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ <ImportToStore>False</ImportToStore>
+ <InstallMode>None</InstallMode>
+ <HardwareIdString />
+ <CommandLine />
+ <ScriptPath />
+ <DeployFiles />
+ <ScriptName />
+ <ScriptDeviceQuery>%PathToInf%</ScriptDeviceQuery>
+ <EnableVerifier>False</EnableVerifier>
+ <AllDrivers>False</AllDrivers>
+ <VerifyProjectOutput>True</VerifyProjectOutput>
+ <VerifyDrivers />
+ <VerifyFlags>133563</VerifyFlags>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/audio/simpleaudiosample/Package/package.VcxProj.Filters b/audio/simpleaudiosample/Package/package.VcxProj.Filters
new file mode 100644
index 00000000..63b75548
--- /dev/null
+++ b/audio/simpleaudiosample/Package/package.VcxProj.Filters
@@ -0,0 +1,21 @@
+<?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>{0924612D-FBA7-477E-BBB9-B3B6EA7C6B03}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{97311738-0AD8-4F7E-AC88-9C9BEAF53AEE}</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>{8DC1C4F0-C285-400E-A983-77A339891354}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{9F086F34-79D2-4FAA-87FD-C2DBEFCED0BA}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/audio/simpleaudiosample/README.md b/audio/simpleaudiosample/README.md
new file mode 100644
index 00000000..5309626a
--- /dev/null
+++ b/audio/simpleaudiosample/README.md
@@ -0,0 +1,133 @@
+---
+page_type: sample
+description: "The Microsoft Simple Audio Sample Device Driver shows how to develop a simple WDM audio driver that exposes support for two basic audio devices (a speaker and microphone array).”
+languages:
+- cpp
+products:
+- windows
+- windows-wdk
+---
+
+# Simple Audio Sample Device Driver
+
+## Introduction
+
+The Microsoft Simple Audio Sample Device Driver shows how to develop a simple WDM audio driver that exposes support for two basic audio devices (a speaker and microphone array). These audio devices are embedded in the system (not pluggable) and the driver uses WaveRT for rendering these devices. The driver also uses a "virtual audio device" instead of an actual hardware-based adapter.
+
+Driver developers can use the framework in this sample to provide support for various audio devices without concern for hardware dependencies. The framework includes implementations of the following interfaces:
+
+- The CAdapterCommon interface gives the miniports access to virtual mixer hardware. It also implements the **IAdapterPowerManagement** interface.
+
+- The CMiniportTopologySimpleAudioSample interface is the base class for all sample topologies. It has very basic common functions. In addition, this class contains common topology property handlers.
+
+The following table shows the contents of the various subdirectories of this sample.
+
+| Directory | Description |
+| --- | --- |
+| Source | Contains all of the source code for the Simple Audio Sample driver. |
+| Filters | Contains the definitions of the wave and topology filters of the endpoints that are present in the Simple Audio Sample driver (speaker and microphone array). |
+| Main | Contains the core functionality of the driver. |
+| Utilities | Contains helper files that provide additional functionality, such as a test tone generator and an audio file reader. |
+
+## Build the sample
+
+If you simply want to build this sample driver and don't intend to run or test it, then you do not need a target computer (also called a test computer). If, however, you would like to deploy, run and test this sample driver, then you need a second computer that will serve as your target computer. Instructions are provided in the **Run the sample** section to show you how to set up the target computer - also referred to as *provisioning* a target computer.
+
+Perform the following steps to build this sample driver.
+
+### 1. Open the driver solution in Visual Studio
+
+In Microsoft Visual Studio, Click **File** \> **Open** \> **Project/Solution...** and navigate to the folder that contains the sample files (for example, *C:\Windows-driver-samples\audio\SimpleAudioSample*). Double-click the *SimpleAudioSample* solution file.
+
+In Visual Studio locate the Solution Explorer. (If this is not already open, choose **Solution Explorer** from the **View** menu.) In Solution Explorer, you can see one solution that has five projects.
+
+### 2. Set the sample's configuration and platform
+
+In Solution Explorer, right-click **Solution ‘SimpleAudioSample’ (5 of 5 projects)**, and choose **Configuration Manager**. Make sure that the configuration and platform settings are the same for the five projects. By default, the configuration is set to **Debug**, and the platform is set to **Win32** for all the projects. If you make any configuration and/or platform changes for one project, you must make the same changes for all the remaining projects.
+
+### 3. Build the sample using Visual Studio
+
+In Visual Studio, click **Build** \> **Build Solution**.
+
+### 4. Locate the built driver package
+
+In File Explorer, navigate to the folder that contains the sample files. For example, you would navigate to *C:\\Windows-driver-samples\\audio\\SimpleAudioSample*, if that's the folder you specified in the preceding Step 1.
+
+In the folder, the location of the driver package varies depending on the configuration and platform settings that you selected in the **Configuration Manager**. For example, if you left the default settings unchanged, then the built driver package will be saved to a folder named *Debug* inside the same folder as the sample files. Double-click the folder for the built driver package, and then double-click the folder named *package*.
+
+The package should contain these files:
+
+| File | Description |
+| --- | --- |
+| SimpleAudioSample.sys | The driver file. |
+| SimpleAudioSample.cat | A signed catalog file, which serves as the signature for the entire package. |
+| SimpleAudioSample.inf | A non-componentized information (INF) file that contains information needed to install the driver. |
+
+## Run the sample
+
+The computer where you install the driver is called the *target computer* or the *test computer*. Typically this is a separate computer from the computer on which you develop and build the driver package. The computer where you develop and build the driver is called the *host computer*.
+
+The process of moving the driver package to the target computer and installing the driver is called *deploying* the driver. You can deploy the SimpleAudioSample driver automatically or manually.
+
+### Prepare the target computer
+
+First of all, install the latest [Windows Driver Kit](https://docs.microsoft.com/windows-hardware/drivers/download-the-wdk) (WDK) on the target computer.
+
+Before you manually deploy a driver, you must prepare the target computer by turning on test signing and by installing a certificate. You also need to locate the DevCon tool in your WDK installation. After that you're ready to run the built driver sample.
+
+Open a Command Prompt window as Administrator. Then enter the following command:
+
+`bcdedit /set TESTSIGNING ON`
+
+and reboot the target computer.
+
+> [!IMPORTANT]
+> Before using BCDEdit to change boot information you may need to temporarily suspend Windows security features such as BitLocker and Secure Boot on the test PC.
+
+Re-enable these security features when testing is complete and appropriately manage the test PC, when the security features are disabled.
+
+After rebooting, navigate to the Tools folder in your WDK installation and locate the DevCon tool. For example, look in the following folder:
+
+C:\\Program Files (x86)\\Windows Kits\\10\\Tools\\x64\\devcon.exe
+
+Copy *devcon.exe* to a folder on the target computer where it is easier to find. For example, create a *C:\\Tools* folder and copy *devcon.exe* to that folder.
+
+Create a folder on the target for the built driver package (for example, *C:\\SimpleAudioSampleDriver*). Copy all the files from the built driver package on the host computer and save them to the folder that you created on the target computer.
+
+Create a folder on the target computer for the certificate created by the build process. For example, you could create a folder named *C:\\Certificates* on the target computer, and then copy *package.cer* to it from the host computer. You can find this certificate in the same folder on the host computer, as the *package* folder that contains the built driver files. On the target computer, right-click the certificate file, and click **Install**, then follow the prompts to install the test certificate.
+
+If you need more detailed instructions for setting up the target computer, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
+
+#### A note on signatures
+
+Since most of these binary files are executed in kernel mode, it is important that they are signed and, optionally, to have a kernel debugger attached.
+
+Without any signature or kernel debugger, the driver will not be installed in the target computer. With a kernel debugger attached, the driver can be installed and the driver files (.sys extension) would be loaded. The only way of installing and executing the driver sample without a kernel debugger attached is to have both the .sys and .cat files signed with a trusted certificate.
+
+For more information on the subject, see [Driver signing](https://docs.microsoft.com/windows-hardware/drivers/install/driver-signing).
+
+### Install the driver
+
+To install SimpleAudioSample.inf, open a Command Prompt window as administrator on the target computer, then navigate to your driver package folder and enter the following command:
+
+`devcon install SimpleAudioSample.inf Root\SimpleAudioSample`
+
+If you get an error message about *devcon* not being recognized, try adding the path to the *devcon* tool. For example, if you copied it to a folder called *C:\\Tools*, then try using the following command:
+
+`C:\\tools\\devcon install SimpleAudioSample.inf Root\SimpleAudioSample`
+
+This installs the Simple Audio Sample driver with a hardware ID of "Root\SimpleAudioSample".
+
+Once the INF file is installed, a device should appear in Device Manager named *Microsoft Virtual Audio Device (WDM) - Simple Audio Sample*.
+
+After successfully installing the sample driver, you're now ready to test it.
+
+For more detailed instructions, see [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1).
+
+### Test the driver
+
+On the target computer, in a Command Prompt window, enter **devmgmt.msc** to open Device Manager. In Device Manager, on the **View** menu, choose **Devices by type**. In the device tree, locate *Virtual Audio Device (WDM) – Simple Audio Sample*. This is typically under the **Sound, video and game controllers** node.
+
+On the target computer, open Control Panel and navigate to **Hardware and Sound** \> **Manage audio devices**. In the Sound dialog box, select the speaker icon labeled as *Virtual Audio Device (WDM) – Simple Audio Sample*, then click **Set Default**, but do not click **OK**. This will keep the Sound dialog box open.
+
+Locate an MP3 or other audio file on the target computer and double-click to play it. Then in the Sound dialog box, verify that there is activity in the volume level indicator associated with the *Virtual Audio Device (WDM) – Simple Audio Sample* driver.
diff --git a/audio/simpleaudiosample/SimpleAudioSample.sln b/audio/simpleaudiosample/SimpleAudioSample.sln
new file mode 100644
index 00000000..407838ba
--- /dev/null
+++ b/audio/simpleaudiosample/SimpleAudioSample.sln
@@ -0,0 +1,113 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30503.244
+MinimumVisualStudioVersion = 12.0
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Package", "Package", "{FA56D96B-290B-4C73-A5E1-02C1861D3224}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Filters", "Filters", "{952A7CB1-E516-44AA-AC38-4AEED9874C41}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Utilities", "Utilities", "{0B4B8E51-20A8-43A4-A8DA-42FF90D628AC}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Inc", "Inc", "{C65091AE-E5B7-4359-8984-55852792406E}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Main", "Main", "{C06F6070-75EE-4F57-8D35-4AC2AB08D029}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "package", "Package\package.VcxProj", "{830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Filters", "Source\Filters\Filters.vcxproj", "{771312CF-E5A2-4676-8142-86CEBDF99E2B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Utilities", "Source\Utilities\Utilities.vcxproj", "{33E61864-6F2C-4F9F-BE70-8F8985A4F283}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Inc", "Source\Inc\Inc.vcxproj", "{4B664BA5-057A-41B8-B365-2C99065C4DFA}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Main", "Source\Main\Main.vcxproj", "{E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}"
+ ProjectSection(ProjectDependencies) = postProject
+ {33E61864-6F2C-4F9F-BE70-8F8985A4F283} = {33E61864-6F2C-4F9F-BE70-8F8985A4F283}
+ {771312CF-E5A2-4676-8142-86CEBDF99E2B} = {771312CF-E5A2-4676-8142-86CEBDF99E2B}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM64 = Debug|ARM64
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|ARM64 = Release|ARM64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|ARM64.Build.0 = Debug|ARM64
+ {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|Win32.ActiveCfg = Debug|Win32
+ {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|Win32.Build.0 = Debug|Win32
+ {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|x64.ActiveCfg = Debug|x64
+ {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|x64.Build.0 = Debug|x64
+ {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|ARM64.ActiveCfg = Release|ARM64
+ {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|ARM64.Build.0 = Release|ARM64
+ {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|Win32.ActiveCfg = Release|Win32
+ {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|Win32.Build.0 = Release|Win32
+ {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|x64.ActiveCfg = Release|x64
+ {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|x64.Build.0 = Release|x64
+ {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Debug|ARM64.Build.0 = Debug|ARM64
+ {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Debug|Win32.Build.0 = Debug|Win32
+ {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Debug|x64.ActiveCfg = Debug|x64
+ {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Debug|x64.Build.0 = Debug|x64
+ {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Release|ARM64.ActiveCfg = Release|ARM64
+ {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Release|ARM64.Build.0 = Release|ARM64
+ {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Release|Win32.ActiveCfg = Release|Win32
+ {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Release|Win32.Build.0 = Release|Win32
+ {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Release|x64.ActiveCfg = Release|x64
+ {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Release|x64.Build.0 = Release|x64
+ {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|ARM64.Build.0 = Debug|ARM64
+ {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|Win32.ActiveCfg = Debug|Win32
+ {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|Win32.Build.0 = Debug|Win32
+ {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|x64.ActiveCfg = Debug|x64
+ {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|x64.Build.0 = Debug|x64
+ {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|ARM64.ActiveCfg = Release|ARM64
+ {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|ARM64.Build.0 = Release|ARM64
+ {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|Win32.ActiveCfg = Release|Win32
+ {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|Win32.Build.0 = Release|Win32
+ {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|x64.ActiveCfg = Release|x64
+ {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|x64.Build.0 = Release|x64
+ {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Debug|ARM64.Build.0 = Debug|ARM64
+ {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Debug|Win32.Build.0 = Debug|Win32
+ {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Debug|x64.ActiveCfg = Debug|x64
+ {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Debug|x64.Build.0 = Debug|x64
+ {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Release|ARM64.ActiveCfg = Release|ARM64
+ {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Release|ARM64.Build.0 = Release|ARM64
+ {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Release|Win32.ActiveCfg = Release|Win32
+ {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Release|Win32.Build.0 = Release|Win32
+ {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Release|x64.ActiveCfg = Release|x64
+ {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Release|x64.Build.0 = Release|x64
+ {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|ARM64.Build.0 = Debug|ARM64
+ {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|Win32.Build.0 = Debug|Win32
+ {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|x64.ActiveCfg = Debug|x64
+ {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|x64.Build.0 = Debug|x64
+ {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|ARM64.ActiveCfg = Release|ARM64
+ {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|ARM64.Build.0 = Release|ARM64
+ {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|Win32.ActiveCfg = Release|Win32
+ {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|Win32.Build.0 = Release|Win32
+ {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|x64.ActiveCfg = Release|x64
+ {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A} = {FA56D96B-290B-4C73-A5E1-02C1861D3224}
+ {771312CF-E5A2-4676-8142-86CEBDF99E2B} = {952A7CB1-E516-44AA-AC38-4AEED9874C41}
+ {33E61864-6F2C-4F9F-BE70-8F8985A4F283} = {0B4B8E51-20A8-43A4-A8DA-42FF90D628AC}
+ {4B664BA5-057A-41B8-B365-2C99065C4DFA} = {C65091AE-E5B7-4359-8984-55852792406E}
+ {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF} = {C06F6070-75EE-4F57-8D35-4AC2AB08D029}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {6DB4FE19-4FE0-4DC4-B898-C46E01E6BDF4}
+ EndGlobalSection
+EndGlobal
diff --git a/audio/simpleaudiosample/Source/Filters/Filters.vcxproj b/audio/simpleaudiosample/Source/Filters/Filters.vcxproj
new file mode 100644
index 00000000..82fd07dc
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Filters/Filters.vcxproj
@@ -0,0 +1,282 @@
+<?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|ARM64">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM64">
+ <Configuration>Release</Configuration>
+ <Platform>ARM64</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>{771312CF-E5A2-4676-8142-86CEBDF99E2B}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{F51739CE-5253-42B5-9191-57F28B5842C6}</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>StaticLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>StaticLibrary</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>StaticLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>StaticLibrary</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>StaticLibrary</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>StaticLibrary</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 Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
+ <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 Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
+ <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" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>Filters</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <TargetName>Filters</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>Filters</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <TargetName>Filters</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>Filters</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>Filters</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="micarraytopo.cpp" />
+ <ClCompile Include="speakertopo.cpp" />
+ </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>
diff --git a/audio/simpleaudiosample/Source/Filters/Filters.vcxproj.Filters b/audio/simpleaudiosample/Source/Filters/Filters.vcxproj.Filters
new file mode 100644
index 00000000..b573243b
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Filters/Filters.vcxproj.Filters
@@ -0,0 +1,27 @@
+<?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>{75C3E63D-04EA-4EB3-B9F1-505497C51F71}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{5E8F8D4C-2886-4109-9E78-CE5EA6DB4AC4}</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>{75D3016A-4ED8-4FAF-9817-394BE1112534}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="*.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+</Project>
diff --git a/audio/simpleaudiosample/Source/Filters/micarray1toptable.h b/audio/simpleaudiosample/Source/Filters/micarray1toptable.h
new file mode 100644
index 00000000..3bbd80f3
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Filters/micarray1toptable.h
@@ -0,0 +1,210 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ micarray1toptable.h
+
+Abstract:
+
+ Declaration of topology tables for the mic array.
+
+--*/
+
+#ifndef _SIMPLEAUDIOSAMPLE_MICARRAY1TOPTABLE_H_
+#define _SIMPLEAUDIOSAMPLE_MICARRAY1TOPTABLE_H_
+
+//
+// {6ae81ff4-203e-4fe1-88aa-f2d57775cd4a}
+DEFINE_GUID(MICARRAY1_CUSTOM_NAME,
+ 0x6ae81ff4, 0x203e, 0x4fe1, 0x88, 0xaa, 0xf2, 0xd5, 0x77, 0x75, 0xcd, 0x4a);
+
+//=============================================================================
+static
+KSDATARANGE MicArray1TopoPinDataRangesBridge[] =
+{
+ {
+ sizeof(KSDATARANGE),
+ 0,
+ 0,
+ 0,
+ STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
+ STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
+ STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
+ }
+};
+
+//=============================================================================
+static
+PKSDATARANGE MicArray1TopoPinDataRangePointersBridge[] =
+{
+ &MicArray1TopoPinDataRangesBridge[0]
+};
+
+//=============================================================================
+static
+PCPIN_DESCRIPTOR MicArray1TopoMiniportPins[] =
+{
+ // KSPIN_TOPO_MIC_ELEMENTS
+ {
+ 0,
+ 0,
+ 0, // InstanceCount
+ NULL, // AutomationTable
+ { // KsPinDescriptor
+ 0, // InterfacesCount
+ NULL, // Interfaces
+ 0, // MediumsCount
+ NULL, // Mediums
+ SIZEOF_ARRAY(MicArray1TopoPinDataRangePointersBridge), // DataRangesCount
+ MicArray1TopoPinDataRangePointersBridge, // DataRanges
+ KSPIN_DATAFLOW_IN, // DataFlow
+ KSPIN_COMMUNICATION_NONE, // Communication
+ &KSNODETYPE_MICROPHONE_ARRAY, // Category
+ &MICARRAY1_CUSTOM_NAME, // Name
+ 0 // Reserved
+ }
+ },
+
+ // KSPIN_TOPO_BRIDGE
+ {
+ 0,
+ 0,
+ 0, // InstanceCount
+ NULL, // AutomationTable
+ { // KsPinDescriptor
+ 0, // InterfacesCount
+ NULL, // Interfaces
+ 0, // MediumsCount
+ NULL, // Mediums
+ SIZEOF_ARRAY(MicArray1TopoPinDataRangePointersBridge), // DataRangesCount
+ MicArray1TopoPinDataRangePointersBridge, // DataRanges
+ KSPIN_DATAFLOW_OUT, // DataFlow
+ KSPIN_COMMUNICATION_NONE, // Communication
+ &KSCATEGORY_AUDIO, // Category
+ NULL, // Name
+ 0 // Reserved
+ }
+ }
+};
+
+//=============================================================================
+static
+PCPROPERTY_ITEM MicArray1PropertiesVolume[] =
+{
+ {
+ &KSPROPSETID_Audio,
+ KSPROPERTY_AUDIO_VOLUMELEVEL,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_MicArrayTopology
+ }
+};
+
+DEFINE_PCAUTOMATION_TABLE_PROP(AutomationMicArray1Volume, MicArray1PropertiesVolume);
+
+//=============================================================================
+static
+PCPROPERTY_ITEM MicArray1PropertiesMute[] =
+{
+ {
+ &KSPROPSETID_Audio,
+ KSPROPERTY_AUDIO_MUTE,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_MicArrayTopology
+ }
+};
+
+DEFINE_PCAUTOMATION_TABLE_PROP(AutomationMicArray1Mute, MicArray1PropertiesMute);
+
+//=============================================================================
+static
+PCNODE_DESCRIPTOR MicArray1TopologyNodes[] =
+{
+ // KSNODE_TOPO_VOLUME
+ {
+ 0, // Flags
+ &AutomationMicArray1Volume, // AutomationTable
+ &KSNODETYPE_VOLUME, // Type
+ &KSAUDFNAME_MIC_VOLUME // Name
+ },
+ // KSNODE_TOPO_MUTE
+ {
+ 0, // Flags
+ &AutomationMicArray1Mute, // AutomationTable
+ &KSNODETYPE_MUTE, // Type
+ &KSAUDFNAME_MIC_MUTE // Name
+ }
+};
+
+C_ASSERT(KSNODE_TOPO_VOLUME == 0);
+C_ASSERT(KSNODE_TOPO_MUTE == 1);
+
+static
+PCCONNECTION_DESCRIPTOR MicArray1TopoMiniportConnections[] =
+{
+ // FromNode, FromPin, ToNode, ToPin
+ { PCFILTER_NODE, KSPIN_TOPO_MIC_ELEMENTS, KSNODE_TOPO_VOLUME, 1 },
+ { KSNODE_TOPO_VOLUME, 0, KSNODE_TOPO_MUTE, 1 },
+ { KSNODE_TOPO_MUTE, 0, PCFILTER_NODE, KSPIN_TOPO_BRIDGE }
+};
+
+
+
+//=============================================================================
+static
+PCPROPERTY_ITEM MicArray1PropertiesTopoFilter[] =
+{
+ {
+ &KSPROPSETID_Jack,
+ KSPROPERTY_JACK_DESCRIPTION,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_MicArrayTopoFilter
+ },
+ {
+ &KSPROPSETID_Jack,
+ KSPROPERTY_JACK_DESCRIPTION2,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_MicArrayTopoFilter
+ },
+ {
+ &KSPROPSETID_Audio,
+ KSPROPERTY_AUDIO_MIC_ARRAY_GEOMETRY,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_MicArrayTopoFilter
+ },
+ {
+ &KSPROPSETID_Audio,
+ KSPROPERTY_AUDIO_MIC_SNR,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_MicArrayTopoFilter
+ },
+ {
+ &KSPROPSETID_Audio,
+ KSPROPERTY_AUDIO_MIC_SENSITIVITY2,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_MicArrayTopoFilter
+ }
+};
+
+DEFINE_PCAUTOMATION_TABLE_PROP(AutomationMicArray1TopoFilter, MicArray1PropertiesTopoFilter);
+
+//=============================================================================
+static
+PCFILTER_DESCRIPTOR MicArray1TopoMiniportFilterDescriptor =
+{
+ 0, // Version
+ &AutomationMicArray1TopoFilter, // AutomationTable
+ sizeof(PCPIN_DESCRIPTOR), // PinSize
+ SIZEOF_ARRAY(MicArray1TopoMiniportPins), // PinCount
+ MicArray1TopoMiniportPins, // Pins
+ sizeof(PCNODE_DESCRIPTOR), // NodeSize
+ SIZEOF_ARRAY(MicArray1TopologyNodes), // NodeCount
+ MicArray1TopologyNodes, // Nodes
+ SIZEOF_ARRAY(MicArray1TopoMiniportConnections),// ConnectionCount
+ MicArray1TopoMiniportConnections, // Connections
+ 0, // CategoryCount
+ NULL // Categories
+};
+
+#endif // _SIMPLEAUDIOSAMPLE_MICARRAY1TOPTABLE_H_
diff --git a/audio/simpleaudiosample/Source/Filters/micarraytopo.cpp b/audio/simpleaudiosample/Source/Filters/micarraytopo.cpp
new file mode 100644
index 00000000..66cc7d89
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Filters/micarraytopo.cpp
@@ -0,0 +1,825 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ micarraytopo.cpp
+
+Abstract:
+
+ Implementation of topology miniport for the mic array.
+
+--*/
+
+#pragma warning (disable : 4127)
+
+#include "definitions.h"
+#include "endpoints.h"
+#include "common.h"
+#include "kshelper.h"
+#include "micarraytopo.h"
+#include "micarray1toptable.h"
+
+constexpr float MICARRAY_SENSITIVITY = -46.5f;
+constexpr float MICARRAY_SENSITIVITY2 = -23.5f;
+constexpr float MICARRAY_SNR = 66.0f;
+
+constexpr inline LONG FloatToFixedPoint16_16(float fl)
+{
+ return (static_cast<LONG>((fl) * (65536.0f)));
+}
+
+#pragma code_seg("PAGE")
+
+//=============================================================================
+NTSTATUS
+CreateMicArrayMiniportTopology
+(
+ _Out_ PUNKNOWN* Unknown,
+ _In_ REFCLSID,
+ _In_opt_ PUNKNOWN UnknownOuter,
+ _In_ POOL_FLAGS PoolFlags,
+ _In_ PUNKNOWN UnknownAdapter,
+ _In_opt_ PVOID DeviceContext,
+ _In_ PENDPOINT_MINIPAIR MiniportPair
+)
+/*++
+
+Routine Description:
+
+ Creates a new topology miniport.
+
+Arguments:
+
+ Unknown -
+
+ RefclsId -
+
+ UnknownOuter -
+
+ PoolType -
+
+ UnknownAdapter -
+
+ DeviceContext -
+
+ MiniportPair -
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(Unknown);
+ ASSERT(MiniportPair);
+
+ UNREFERENCED_PARAMETER(UnknownAdapter);
+ UNREFERENCED_PARAMETER(DeviceContext);
+
+ CMicArrayMiniportTopology* obj =
+ new (PoolFlags, MINTOPORT_POOLTAG)
+ CMicArrayMiniportTopology(UnknownOuter,
+ MiniportPair->TopoDescriptor,
+ MiniportPair->DeviceMaxChannels,
+ MiniportPair->DeviceType);
+ if (NULL == obj)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ obj->AddRef();
+
+ *Unknown = reinterpret_cast<IUnknown*>(obj);
+
+ return STATUS_SUCCESS;
+} // CreateMicArrayMiniportTopology
+
+//=============================================================================
+CMicArrayMiniportTopology::~CMicArrayMiniportTopology
+(
+ void
+)
+/*++
+
+Routine Description:
+
+ Topology miniport destructor
+
+Arguments:
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMicArrayMiniportTopology::~CMicArrayMiniportTopology]"));
+} // ~CMicArrayMiniportTopology
+
+//=============================================================================
+NTSTATUS
+CMicArrayMiniportTopology::DataRangeIntersection
+(
+ _In_ ULONG PinId,
+ _In_ PKSDATARANGE ClientDataRange,
+ _In_ PKSDATARANGE MyDataRange,
+ _In_ ULONG OutputBufferLength,
+ _Out_writes_bytes_to_opt_(OutputBufferLength, *ResultantFormatLength)
+ PVOID ResultantFormat OPTIONAL,
+ _Out_ PULONG ResultantFormatLength
+)
+/*++
+
+Routine Description:
+
+ The DataRangeIntersection function determines the highest quality
+ intersection of two data ranges.
+
+Arguments:
+
+ PinId - Pin for which data intersection is being determined.
+
+ ClientDataRange - Pointer to KSDATARANGE structure which contains the data range
+ submitted by client in the data range intersection property
+ request.
+
+ MyDataRange - Pin's data range to be compared with client's data range.
+
+ OutputBufferLength - Size of the buffer pointed to by the resultant format
+ parameter.
+
+ ResultantFormat - Pointer to value where the resultant format should be
+ returned.
+
+ ResultantFormatLength - Actual length of the resultant format that is placed
+ at ResultantFormat. This should be less than or equal
+ to OutputBufferLength.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ return
+ CMiniportTopologySimpleAudioSample::DataRangeIntersection
+ (
+ PinId,
+ ClientDataRange,
+ MyDataRange,
+ OutputBufferLength,
+ ResultantFormat,
+ ResultantFormatLength
+ );
+} // DataRangeIntersection
+
+//=============================================================================
+STDMETHODIMP
+CMicArrayMiniportTopology::GetDescription
+(
+ _Out_ PPCFILTER_DESCRIPTOR* OutFilterDescriptor
+)
+/*++
+
+Routine Description:
+
+ The GetDescription function gets a pointer to a filter description.
+ It provides a location to deposit a pointer in miniport's description
+ structure. This is the placeholder for the FromNode or ToNode fields in
+ connections which describe connections to the filter's pins.
+
+Arguments:
+
+ OutFilterDescriptor - Pointer to the filter description.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(OutFilterDescriptor);
+
+ return CMiniportTopologySimpleAudioSample::GetDescription(OutFilterDescriptor);
+} // GetDescription
+
+//=============================================================================
+STDMETHODIMP
+CMicArrayMiniportTopology::Init
+(
+ _In_ PUNKNOWN UnknownAdapter,
+ _In_ PRESOURCELIST ResourceList,
+ _In_ PPORTTOPOLOGY Port_
+)
+/*++
+
+Routine Description:
+
+ The Init function initializes the miniport. Callers of this function
+ should run at IRQL PASSIVE_LEVEL
+
+Arguments:
+
+ UnknownAdapter - A pointer to the IUnknown interface of the adapter object.
+
+ ResourceList - Pointer to the resource list to be supplied to the miniport
+ during initialization. The port driver is free to examine the
+ contents of the ResourceList. The port driver will not be
+ modify the ResourceList contents.
+
+ Port - Pointer to the topology port object that is linked with this miniport.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ UNREFERENCED_PARAMETER(ResourceList);
+
+ PAGED_CODE();
+
+ ASSERT(UnknownAdapter);
+ ASSERT(Port_);
+
+ DPF_ENTER(("[CMicArrayMiniportTopology::Init]"));
+
+ NTSTATUS ntStatus;
+
+ ntStatus =
+ CMiniportTopologySimpleAudioSample::Init
+ (
+ UnknownAdapter,
+ Port_
+ );
+
+ return ntStatus;
+} // Init
+
+//=============================================================================
+STDMETHODIMP
+CMicArrayMiniportTopology::NonDelegatingQueryInterface
+(
+ _In_ REFIID Interface,
+ _COM_Outptr_ PVOID* Object
+)
+/*++
+
+Routine Description:
+
+ QueryInterface for MiniportTopology
+
+Arguments:
+
+ Interface - GUID of the interface
+
+ Object - interface object to be returned.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(Object);
+
+ if (IsEqualGUIDAligned(Interface, IID_IUnknown))
+ {
+ *Object = PVOID(PUNKNOWN(this));
+ }
+ else if (IsEqualGUIDAligned(Interface, IID_IMiniport))
+ {
+ *Object = PVOID(PMINIPORT(this));
+ }
+ else if (IsEqualGUIDAligned(Interface, IID_IMiniportTopology))
+ {
+ *Object = PVOID(PMINIPORTTOPOLOGY(this));
+ }
+ else
+ {
+ *Object = NULL;
+ }
+
+ if (*Object)
+ {
+ // We reference the interface for the caller.
+ PUNKNOWN(*Object)->AddRef();
+ return(STATUS_SUCCESS);
+ }
+
+ return(STATUS_INVALID_PARAMETER);
+} // NonDelegatingQueryInterface
+
+//=============================================================================
+NTSTATUS
+CMicArrayMiniportTopology::PropertyHandlerMicArrayGeometry
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+/*++
+
+Routine Description:
+
+ Handles ( KSPROPSETID_Audio, KSPROPERTY_AUDIO_MIC_ARRAY_GEOMETRY )
+
+Arguments:
+
+ PropertyRequest -
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(PropertyRequest);
+
+ DPF_ENTER(("[PropertyHandlerMicArrayGeometry]"));
+
+ NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+ ULONG nPinId = (ULONG)-1;
+
+ if (PropertyRequest->InstanceSize >= sizeof(ULONG))
+ {
+ nPinId = *(PULONG(PropertyRequest->Instance));
+
+ if (nPinId == KSPIN_TOPO_MIC_ELEMENTS)
+ {
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ ntStatus =
+ PropertyHandler_BasicSupport
+ (
+ PropertyRequest,
+ KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET,
+ VT_ILLEGAL
+ );
+ }
+ else
+ {
+ ULONG cElements = 2;
+ ULONG cbNeeded = FIELD_OFFSET(KSAUDIO_MIC_ARRAY_GEOMETRY, KsMicCoord) +
+ cElements * sizeof(KSAUDIO_MICROPHONE_COORDINATES);
+
+ if (PropertyRequest->ValueSize == 0)
+ {
+ PropertyRequest->ValueSize = cbNeeded;
+ ntStatus = STATUS_BUFFER_OVERFLOW;
+ }
+ else if (PropertyRequest->ValueSize < cbNeeded)
+ {
+ ntStatus = STATUS_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ PKSAUDIO_MIC_ARRAY_GEOMETRY pMAG = (PKSAUDIO_MIC_ARRAY_GEOMETRY)PropertyRequest->Value;
+ const SHORT MicArray_180_Degrees = 31416; // 10000 * pi
+ const SHORT MicArray_45_Degrees = 7854; // 10000 * pi / 4
+
+ // fill in mic array geometry fields
+ pMAG->usVersion = 0x0100; // Version of Mic array specification (0x0100)
+ pMAG->usMicArrayType = (USHORT)KSMICARRAY_MICARRAYTYPE_LINEAR; // Type of Mic Array
+ pMAG->wVerticalAngleBegin = -MicArray_45_Degrees; // Work Volume Vertical Angle Begin
+ pMAG->wVerticalAngleEnd = MicArray_45_Degrees; // Work Volume Vertical Angle End
+ pMAG->wHorizontalAngleBegin = 0; // Work Volume HorizontalAngle Begin
+ pMAG->wHorizontalAngleEnd = 0; // Work Volume HorizontalAngle End
+ pMAG->usFrequencyBandLo = 100; // Low end of Freq Range
+ pMAG->usFrequencyBandHi = 8000; // High end of Freq Range
+
+ pMAG->usNumberOfMicrophones = 2; // Count of microphone coordinate structures to follow.
+
+ pMAG->KsMicCoord[0].usType = (USHORT)KSMICARRAY_MICTYPE_CARDIOID;
+ pMAG->KsMicCoord[0].wXCoord = 0;
+ pMAG->KsMicCoord[0].wYCoord = 100;
+ pMAG->KsMicCoord[0].wZCoord = 0;
+ pMAG->KsMicCoord[0].wVerticalAngle = 0;
+ pMAG->KsMicCoord[0].wHorizontalAngle = 0;
+
+ pMAG->KsMicCoord[1].usType = (USHORT)KSMICARRAY_MICTYPE_CARDIOID;
+ pMAG->KsMicCoord[1].wXCoord = 0;
+ pMAG->KsMicCoord[1].wYCoord = -100;
+ pMAG->KsMicCoord[1].wZCoord = 0;
+ pMAG->KsMicCoord[1].wVerticalAngle = 0;
+ pMAG->KsMicCoord[1].wHorizontalAngle = 0;
+ ntStatus = STATUS_SUCCESS;
+ }
+ }
+ }
+ }
+ }
+
+ return ntStatus;
+}
+
+//=============================================================================
+NTSTATUS
+CMicArrayMiniportTopology::PropertyHandlerMicProperties
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+/*++
+
+Routine Description:
+
+Handles ( KSPROPSETID_Audio, KSPROPERTY_AUDIO_MIC_SNR )
+Handles ( KSPROPSETID_Audio, KSPROPERTY_AUDIO_MIC_SENSITIVITY2 )
+
+Arguments:
+
+PropertyRequest -
+
+Return Value:
+
+NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(PropertyRequest);
+
+ DPF_ENTER(("[PropertyHandlerMicProperties]"));
+
+ NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+ ULONG nPinId = (ULONG)-1;
+ KFLOATING_SAVE saveData;
+ NTSTATUS fstatus;
+
+ if (PropertyRequest->InstanceSize >= sizeof(ULONG))
+ {
+ nPinId = *(PULONG(PropertyRequest->Instance));
+
+ if (nPinId == KSPIN_TOPO_MIC_ELEMENTS)
+ {
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ ntStatus =
+ PropertyHandler_BasicSupport
+ (
+ PropertyRequest,
+ KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET,
+ VT_ILLEGAL
+ );
+ }
+ else
+ {
+ ntStatus =
+ ValidatePropertyParams
+ (
+ PropertyRequest,
+ sizeof(LONG),
+ 0
+ );
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_MIC_SNR)
+ {
+ LONG* micSNR = (LONG*)PropertyRequest->Value;
+ fstatus = KeSaveFloatingPointState(&saveData);
+ if (NT_SUCCESS(fstatus))
+ {
+ // Return microphone SNR information.
+ *micSNR = FloatToFixedPoint16_16(MICARRAY_SNR); // convert float dB to fixed point arithmetic
+ KeRestoreFloatingPointState(&saveData);
+ }
+ ntStatus = STATUS_SUCCESS;
+ }
+ else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_MIC_SENSITIVITY2)
+ {
+ LONG* micSensitivity2 = (LONG*)PropertyRequest->Value;
+ fstatus = KeSaveFloatingPointState(&saveData);
+ if (NT_SUCCESS(fstatus))
+ {
+ // Return microphone SNR information.
+ *micSensitivity2 = FloatToFixedPoint16_16(MICARRAY_SENSITIVITY2); // convert float dB to fixed point arithmetic
+ KeRestoreFloatingPointState(&saveData);
+ }
+ ntStatus = STATUS_SUCCESS;
+ }
+ }
+ else
+ {
+ ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+ }
+ }
+ }
+ }
+ }
+
+ return ntStatus;
+}
+
+//=============================================================================
+NTSTATUS
+CMicArrayMiniportTopology::PropertyHandlerJackDescription
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+/*++
+
+Routine Description:
+
+ Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION )
+
+Arguments:
+
+ PropertyRequest -
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(PropertyRequest);
+
+ DPF_ENTER(("[PropertyHandlerJackDescription]"));
+
+ NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+ ULONG nPinId = (ULONG)-1;
+
+ if (PropertyRequest->InstanceSize >= sizeof(ULONG))
+ {
+ nPinId = *(PULONG(PropertyRequest->Instance));
+
+ if (nPinId == KSPIN_TOPO_MIC_ELEMENTS)
+ {
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ ntStatus =
+ PropertyHandler_BasicSupport
+ (
+ PropertyRequest,
+ KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET,
+ VT_ILLEGAL
+ );
+ }
+ else
+ {
+ ULONG cbNeeded = sizeof(KSMULTIPLE_ITEM) + sizeof(KSJACK_DESCRIPTION);
+
+ if (PropertyRequest->ValueSize == 0)
+ {
+ PropertyRequest->ValueSize = cbNeeded;
+ ntStatus = STATUS_BUFFER_OVERFLOW;
+ }
+ else if (PropertyRequest->ValueSize < cbNeeded)
+ {
+ ntStatus = STATUS_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value;
+ PKSJACK_DESCRIPTION pDesc = (PKSJACK_DESCRIPTION)(pMI + 1);
+
+ pMI->Size = cbNeeded;
+ pMI->Count = 1;
+
+ pDesc->ChannelMapping = 0; // Don't specify channel mask for array mic
+ pDesc->Color = 0x00000000; // Black. This is an integrated device
+ pDesc->ConnectionType = eConnTypeUnknown; // Integrated.
+ pDesc->GenLocation = eGenLocPrimaryBox;
+ pDesc->GeoLocation = eGeoLocFront;
+ pDesc->PortConnection = ePortConnIntegratedDevice;
+ pDesc->IsConnected = TRUE; // This is an integrated device, so it's always "connected"
+
+ ntStatus = STATUS_SUCCESS;
+ }
+ }
+ }
+ }
+ }
+
+ return ntStatus;
+}
+
+//=============================================================================
+NTSTATUS
+CMicArrayMiniportTopology::PropertyHandlerJackDescription2
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+/*++
+
+Routine Description:
+
+ Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION2 )
+
+Arguments:
+
+ PropertyRequest -
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(PropertyRequest);
+
+ DPF_ENTER(("[PropertyHandlerJackDescription2]"));
+
+ NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+ ULONG nPinId = (ULONG)-1;
+
+ if (PropertyRequest->InstanceSize >= sizeof(ULONG))
+ {
+ nPinId = *(PULONG(PropertyRequest->Instance));
+
+ if (nPinId == KSPIN_TOPO_MIC_ELEMENTS)
+ {
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ ntStatus =
+ PropertyHandler_BasicSupport
+ (
+ PropertyRequest,
+ KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET,
+ VT_ILLEGAL
+ );
+ }
+ else
+ {
+ ULONG cbNeeded = sizeof(KSMULTIPLE_ITEM) + sizeof(KSJACK_DESCRIPTION2);
+
+ if (PropertyRequest->ValueSize == 0)
+ {
+ PropertyRequest->ValueSize = cbNeeded;
+ ntStatus = STATUS_BUFFER_OVERFLOW;
+ }
+ else if (PropertyRequest->ValueSize < cbNeeded)
+ {
+ ntStatus = STATUS_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value;
+ PKSJACK_DESCRIPTION2 pDesc = (PKSJACK_DESCRIPTION2)(pMI + 1);
+
+ pMI->Size = cbNeeded;
+ pMI->Count = 1;
+
+ RtlZeroMemory(pDesc, sizeof(KSJACK_DESCRIPTION2));
+
+ //
+ // Specifies the lower 16 bits of the DWORD parameter. This parameter indicates whether
+ // the jack is currently active, streaming, idle, or hardware not ready.
+ //
+ pDesc->DeviceStateInfo = 0;
+
+ //
+ // From MSDN:
+ // "If an audio device lacks jack presence detection, the IsConnected member of
+ // the KSJACK_DESCRIPTION structure must always be set to TRUE. To remove the
+ // ambiguity that results from this dual meaning of the TRUE value for IsConnected,
+ // a client application can call IKsJackDescription2::GetJackDescription2 to read
+ // the JackCapabilities flag of the KSJACK_DESCRIPTION2 structure. If this flag has
+ // the JACKDESC2_PRESENCE_DETECT_CAPABILITY bit set, it indicates that the endpoint
+ // does in fact support jack presence detection. In that case, the return value of
+ // the IsConnected member can be interpreted to accurately reflect the insertion status
+ // of the jack."
+ //
+ // Bit definitions:
+ // 0x00000001 - JACKDESC2_PRESENCE_DETECT_CAPABILITY
+ // 0x00000002 - JACKDESC2_DYNAMIC_FORMAT_CHANGE_CAPABILITY
+ //
+ pDesc->JackCapabilities = 0;
+
+ ntStatus = STATUS_SUCCESS;
+ }
+ }
+ }
+ }
+ }
+
+ return ntStatus;
+}
+
+//=============================================================================
+NTSTATUS
+PropertyHandler_MicArrayTopoFilter
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+/*++
+
+Routine Description:
+
+ Redirects property request to miniport object
+
+Arguments:
+
+ PropertyRequest -
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(PropertyRequest);
+
+ DPF_ENTER(("[PropertyHandler_MicArrayTopoFilter]"));
+
+ // PropertryRequest structure is filled by portcls.
+ // MajorTarget is a pointer to miniport object for miniports.
+ //
+ NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+ PCMicArrayMiniportTopology pMiniport = (PCMicArrayMiniportTopology)PropertyRequest->MajorTarget;
+
+ if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Audio))
+ {
+ if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_MIC_ARRAY_GEOMETRY)
+ {
+ ntStatus = pMiniport->PropertyHandlerMicArrayGeometry(PropertyRequest);
+ }
+ else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_MIC_SENSITIVITY2)
+ {
+ ntStatus = pMiniport->PropertyHandlerMicProperties(PropertyRequest);
+ }
+ else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_MIC_SNR)
+ {
+ ntStatus = pMiniport->PropertyHandlerMicProperties(PropertyRequest);
+ }
+ }
+ else if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Jack))
+ {
+ if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION)
+ {
+ ntStatus = pMiniport->PropertyHandlerJackDescription(PropertyRequest);
+ }
+ else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION2)
+ {
+ ntStatus = pMiniport->PropertyHandlerJackDescription2(PropertyRequest);
+ }
+ }
+
+ return ntStatus;
+} // PropertyHandler_TopoFilter
+
+//=============================================================================
+NTSTATUS
+PropertyHandler_MicArrayTopology
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+/*++
+
+Routine Description:
+
+ Redirects property request to miniport object
+
+Arguments:
+
+ PropertyRequest -
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(PropertyRequest);
+
+ DPF_ENTER(("[PropertyHandler_MicArrayTopology]"));
+
+ // PropertryRequest structure is filled by portcls.
+ // MajorTarget is a pointer to miniport object for miniports.
+ //
+ PCMicArrayMiniportTopology pMiniport = (PCMicArrayMiniportTopology)PropertyRequest->MajorTarget;
+
+ return pMiniport->PropertyHandlerGeneric(PropertyRequest);
+} // PropertyHandler_MicArrayTopology
+
+#pragma code_seg()
diff --git a/audio/simpleaudiosample/Source/Filters/micarraytopo.h b/audio/simpleaudiosample/Source/Filters/micarraytopo.h
new file mode 100644
index 00000000..4f4a621f
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Filters/micarraytopo.h
@@ -0,0 +1,97 @@
+
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ micarraytopo.h
+
+Abstract:
+
+ Declaration of mic array topology miniport.
+
+--*/
+
+#ifndef _SIMPLEAUDIOSAMPLE_MICARRAYTOPO_H_
+#define _SIMPLEAUDIOSAMPLE_MICARRAYTOPO_H_
+
+#include "basetopo.h"
+
+//=============================================================================
+// Classes
+//=============================================================================
+
+///////////////////////////////////////////////////////////////////////////////
+// CMicArrayMiniportTopology
+//
+
+#pragma code_seg()
+class CMicArrayMiniportTopology :
+ public CMiniportTopologySimpleAudioSample,
+ public IMiniportTopology,
+ public CUnknown
+{
+public:
+ DECLARE_STD_UNKNOWN();
+ CMicArrayMiniportTopology
+ (
+ _In_opt_ PUNKNOWN UnknownOuter,
+ _In_ PCFILTER_DESCRIPTOR* FilterDesc,
+ _In_ USHORT DeviceMaxChannels,
+ _In_ eDeviceType DeviceType
+ )
+ : CUnknown(UnknownOuter),
+ CMiniportTopologySimpleAudioSample(FilterDesc, DeviceMaxChannels),
+ m_DeviceType(DeviceType)
+ {
+ ASSERT(m_DeviceType == eMicArrayDevice1);
+ }
+
+ ~CMicArrayMiniportTopology();
+
+ IMP_IMiniportTopology;
+
+ NTSTATUS PropertyHandlerMicArrayGeometry
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
+
+ NTSTATUS PropertyHandlerMicProperties
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
+
+ NTSTATUS PropertyHandlerJackDescription
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
+
+ NTSTATUS PropertyHandlerJackDescription2
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
+
+protected:
+ eDeviceType m_DeviceType;
+
+};
+
+typedef CMicArrayMiniportTopology* PCMicArrayMiniportTopology;
+
+
+NTSTATUS
+CreateMicArrayMiniportTopology(
+ _Out_ PUNKNOWN* Unknown,
+ _In_ REFCLSID,
+ _In_opt_ PUNKNOWN UnknownOuter,
+ _In_ POOL_FLAGS PoolFlags,
+ _In_ PUNKNOWN UnknownAdapter,
+ _In_opt_ PVOID DeviceContext,
+ _In_ PENDPOINT_MINIPAIR MiniportPair
+);
+
+NTSTATUS PropertyHandler_MicArrayTopoFilter(_In_ PPCPROPERTY_REQUEST PropertyRequest);
+NTSTATUS PropertyHandler_MicArrayTopology(_In_ PPCPROPERTY_REQUEST PropertyRequest);
+
+#endif // _SIMPLEAUDIOSAMPLE_MICARRAYTOPO_H_
diff --git a/audio/simpleaudiosample/Source/Filters/micarraywavtable.h b/audio/simpleaudiosample/Source/Filters/micarraywavtable.h
new file mode 100644
index 00000000..53656038
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Filters/micarraywavtable.h
@@ -0,0 +1,292 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ micarraywavtable.h
+
+Abstract:-
+
+ Declaration of wave miniport tables for the mic array.
+
+--*/
+
+#ifndef _SIMPLEAUDIOSAMPLE_MICARRAYWAVTABLE_H_
+#define _SIMPLEAUDIOSAMPLE_MICARRAYWAVTABLE_H_
+
+//
+// Mic array range.
+//
+#define MICARRAY_RAW_CHANNELS 2 // Channels for raw mode
+#define MICARRAY_DEVICE_MAX_CHANNELS 2 // Max channels overall
+#define MICARRAY_32_BITS_PER_SAMPLE_PCM 32 // 32 Bits Per Sample
+#define MICARRAY_RAW_SAMPLE_RATE 48000 // Raw sample rate
+
+//
+// Max # of pin instances.
+//
+#define MICARRAY_MAX_INPUT_STREAMS 1
+
+//=============================================================================
+static
+KSDATAFORMAT_WAVEFORMATEXTENSIBLE MicArrayPinSupportedDeviceFormats[] =
+{
+ // 48 KHz 32-bit 2 channels
+ {
+ {
+ sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
+ 0,
+ 0,
+ 0,
+ STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
+ STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
+ STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
+ },
+ {
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 2,
+ 48000,
+ 384000,
+ 8,
+ 32,
+ sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
+ },
+ 32,
+ KSAUDIO_SPEAKER_STEREO,
+ STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
+ }
+ }
+};
+
+//
+// Supported modes (only on streaming pins).
+//
+static
+MODE_AND_DEFAULT_FORMAT MicArrayPinSupportedDeviceModes[] =
+{
+ {
+ STATIC_AUDIO_SIGNALPROCESSINGMODE_RAW,
+ &MicArrayPinSupportedDeviceFormats[0].DataFormat
+ }
+};
+
+//
+// The entries here must follow the same order as the filter's pin
+// descriptor array.
+//
+static
+PIN_DEVICE_FORMATS_AND_MODES MicArrayPinDeviceFormatsAndModes[] =
+{
+ {
+ BridgePin,
+ NULL,
+ 0,
+ NULL,
+ 0
+ },
+ {
+ SystemCapturePin,
+ MicArrayPinSupportedDeviceFormats,
+ SIZEOF_ARRAY(MicArrayPinSupportedDeviceFormats),
+ MicArrayPinSupportedDeviceModes,
+ SIZEOF_ARRAY(MicArrayPinSupportedDeviceModes)
+ }
+};
+
+//=============================================================================
+// Data ranges
+//
+// See CMiniportWaveRT::DataRangeIntersection.
+//
+static
+KSDATARANGE_AUDIO MicArrayPinDataRangesRawStream[] =
+{
+ {
+ {
+ sizeof(KSDATARANGE_AUDIO),
+ KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range
+ 0,
+ 0,
+ STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
+ STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
+ STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
+ },
+ MICARRAY_RAW_CHANNELS,
+ MICARRAY_32_BITS_PER_SAMPLE_PCM,
+ MICARRAY_32_BITS_PER_SAMPLE_PCM,
+ MICARRAY_RAW_SAMPLE_RATE,
+ MICARRAY_RAW_SAMPLE_RATE
+ },
+};
+
+static
+PKSDATARANGE MicArrayPinDataRangePointersStream[] =
+{
+ // All supported device formats should be listed in the DataRange.
+ PKSDATARANGE(&MicArrayPinDataRangesRawStream[0]),
+ PKSDATARANGE(&PinDataRangeAttributeList),
+};
+
+//=============================================================================
+static
+KSDATARANGE MicArrayPinDataRangesBridge[] =
+{
+ {
+ sizeof(KSDATARANGE),
+ 0,
+ 0,
+ 0,
+ STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
+ STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
+ STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
+ }
+};
+
+static
+PKSDATARANGE MicArrayPinDataRangePointersBridge[] =
+{
+ &MicArrayPinDataRangesBridge[0]
+};
+
+//=============================================================================
+static
+PCPIN_DESCRIPTOR MicArrayWaveMiniportPins[] =
+{
+ // Wave In Bridge Pin (Capture - From Topology) KSPIN_WAVE_BRIDGE
+ {
+ 0,
+ 0,
+ 0,
+ NULL,
+ {
+ 0,
+ NULL,
+ 0,
+ NULL,
+ SIZEOF_ARRAY(MicArrayPinDataRangePointersBridge),
+ MicArrayPinDataRangePointersBridge,
+ KSPIN_DATAFLOW_IN,
+ KSPIN_COMMUNICATION_NONE,
+ &KSCATEGORY_AUDIO,
+ NULL,
+ 0
+ }
+ },
+ // Wave In Streaming Pin (Capture) KSPIN_WAVE_HOST
+ {
+ MICARRAY_MAX_INPUT_STREAMS,
+ MICARRAY_MAX_INPUT_STREAMS,
+ 0,
+ NULL,
+ {
+ 0,
+ NULL,
+ 0,
+ NULL,
+ SIZEOF_ARRAY(MicArrayPinDataRangePointersStream),
+ MicArrayPinDataRangePointersStream,
+ KSPIN_DATAFLOW_OUT,
+ KSPIN_COMMUNICATION_SINK,
+ &KSCATEGORY_AUDIO,
+ &KSAUDFNAME_RECORDING_CONTROL,
+ 0
+ }
+ }
+};
+
+//=============================================================================
+static
+PCNODE_DESCRIPTOR MicArrayWaveMiniportNodes[] =
+{
+ // KSNODE_WAVE_ADC
+ {
+ 0, // Flags
+ NULL, // AutomationTable
+ &KSNODETYPE_ADC, // Type
+ NULL // Name
+ }
+};
+
+//=============================================================================
+static
+PCCONNECTION_DESCRIPTOR MicArrayWaveMiniportConnections[] =
+{
+ { PCFILTER_NODE, KSPIN_WAVE_BRIDGE, KSNODE_WAVE_ADC, 1 },
+ { KSNODE_WAVE_ADC, 0, PCFILTER_NODE, KSPIN_WAVEIN_HOST },
+};
+
+//=============================================================================
+
+static
+SIMPLEAUDIOSAMPLE_PROPERTY_ITEM PropertiesMicArrayWaveFilter[] =
+{
+ {
+ {
+ &KSPROPSETID_General,
+ KSPROPERTY_GENERAL_COMPONENTID,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_WaveFilter,
+ },
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0
+ },
+ {
+ {
+ &KSPROPSETID_Pin,
+ KSPROPERTY_PIN_PROPOSEDATAFORMAT,
+ KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_WaveFilter,
+ },
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0
+ },
+ {
+ {
+ &KSPROPSETID_Pin,
+ KSPROPERTY_PIN_PROPOSEDATAFORMAT2,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_WaveFilter,
+ },
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0
+ },
+};
+
+DEFINE_PCAUTOMATION_TABLE_PROP(AutomationMicArrayWaveFilter, PropertiesMicArrayWaveFilter);
+
+//=============================================================================
+static
+PCFILTER_DESCRIPTOR MicArrayWaveMiniportFilterDescriptor =
+{
+ 0, // Version
+ &AutomationMicArrayWaveFilter, // AutomationTable
+ sizeof(PCPIN_DESCRIPTOR), // PinSize
+ SIZEOF_ARRAY(MicArrayWaveMiniportPins), // PinCount
+ MicArrayWaveMiniportPins, // Pins
+ sizeof(PCNODE_DESCRIPTOR), // NodeSize
+ SIZEOF_ARRAY(MicArrayWaveMiniportNodes), // NodeCount
+ MicArrayWaveMiniportNodes, // Nodes
+ SIZEOF_ARRAY(MicArrayWaveMiniportConnections), // ConnectionCount
+ MicArrayWaveMiniportConnections, // Connections
+ 0, // CategoryCount
+ NULL // Categories - use defaults (audio, render, capture)
+};
+
+#endif // _SIMPLEAUDIOSAMPLE_MICARRAYWAVTABLE_H_
diff --git a/audio/simpleaudiosample/Source/Filters/minipairs.h b/audio/simpleaudiosample/Source/Filters/minipairs.h
new file mode 100644
index 00000000..b7d8950f
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Filters/minipairs.h
@@ -0,0 +1,177 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ minipairs.h
+
+Abstract:
+
+ Local audio endpoint filter definitions.
+--*/
+
+#ifndef _SIMPLEAUDIOSAMPLE_MINIPAIRS_H_
+#define _SIMPLEAUDIOSAMPLE_MINIPAIRS_H_
+
+#include "speakertopo.h"
+#include "speakertoptable.h"
+#include "speakerwavtable.h"
+
+#include "micarraytopo.h"
+#include "micarray1toptable.h"
+#include "micarraywavtable.h"
+
+
+NTSTATUS
+CreateMiniportWaveRTSimpleAudioSample
+(
+ _Out_ PUNKNOWN *,
+ _In_ REFCLSID,
+ _In_opt_ PUNKNOWN,
+ _In_ POOL_FLAGS,
+ _In_ PUNKNOWN,
+ _In_opt_ PVOID,
+ _In_ PENDPOINT_MINIPAIR
+);
+
+NTSTATUS
+CreateMiniportTopologySimpleAudioSample
+(
+ _Out_ PUNKNOWN *,
+ _In_ REFCLSID,
+ _In_opt_ PUNKNOWN,
+ _In_ POOL_FLAGS,
+ _In_ PUNKNOWN,
+ _In_opt_ PVOID,
+ _In_ PENDPOINT_MINIPAIR
+);
+
+//
+// Render miniports.
+//
+
+/*********************************************************************
+* Topology/Wave bridge connection for speaker (internal) *
+* *
+* +------+ +------+ *
+* | Wave | | Topo | *
+* | | | | *
+* System --->|0 1|--------------->|0 1|---> Line Out *
+* | | | | *
+* +------+ +------+ *
+*********************************************************************/
+static
+PHYSICALCONNECTIONTABLE SpeakerTopologyPhysicalConnections[] =
+{
+ {
+ KSPIN_TOPO_WAVEOUT_SOURCE, // TopologyIn
+ KSPIN_WAVE_RENDER3_SOURCE, // WaveOut
+ CONNECTIONTYPE_WAVE_OUTPUT
+ }
+};
+
+static
+ENDPOINT_MINIPAIR SpeakerMiniports =
+{
+ eSpeakerDevice,
+ L"TopologySpeaker", // make sure this or the template name matches with KSNAME_TopologySpeaker in the inf's [Strings] section
+ NULL, // optional template name
+ CreateMiniportTopologySimpleAudioSample,
+ &SpeakerTopoMiniportFilterDescriptor,
+ 0, NULL, // Interface properties
+ L"WaveSpeaker", // make sure this or the template name matches with KSNAME_WaveSpeaker in the inf's [Strings] section
+ NULL, // optional template name
+ CreateMiniportWaveRTSimpleAudioSample,
+ &SpeakerWaveMiniportFilterDescriptor,
+ 0, // Interface properties
+ NULL,
+ SPEAKER_DEVICE_MAX_CHANNELS,
+ SpeakerPinDeviceFormatsAndModes,
+ SIZEOF_ARRAY(SpeakerPinDeviceFormatsAndModes),
+ SpeakerTopologyPhysicalConnections,
+ SIZEOF_ARRAY(SpeakerTopologyPhysicalConnections),
+ ENDPOINT_NO_FLAGS,
+};
+
+//
+// Capture miniports.
+//
+
+/*********************************************************************
+* Topology/Wave bridge connection for mic array 1 (front) *
+* *
+* +------+ +------+ *
+* | Topo | | Wave | *
+* | | | | *
+* Mic in --->|0 1|===>|0 1|---> Capture Host Pin *
+* | | | | *
+* +------+ +------+ *
+*********************************************************************/
+static
+PHYSICALCONNECTIONTABLE MicArray1TopologyPhysicalConnections[] =
+{
+ {
+ KSPIN_TOPO_BRIDGE, // TopologyOut
+ KSPIN_WAVE_BRIDGE, // WaveIn
+ CONNECTIONTYPE_TOPOLOGY_OUTPUT
+ }
+};
+
+static
+ENDPOINT_MINIPAIR MicArray1Miniports =
+{
+ eMicArrayDevice1,
+ L"TopologyMicArray1", // make sure this or the template name matches with KSNAME_TopologyMicArray1 in the inf's [Strings] section
+ NULL, // optional template name
+ CreateMicArrayMiniportTopology,
+ &MicArray1TopoMiniportFilterDescriptor,
+ 0, NULL, // Interface properties
+ L"WaveMicArray1", // make sure this or the tempalte name matches with KSNAME_WaveMicArray1 in the inf's [Strings] section
+ NULL, // optional template name
+ CreateMiniportWaveRTSimpleAudioSample,
+ &MicArrayWaveMiniportFilterDescriptor,
+ 0, // Interface properties
+ NULL,
+ MICARRAY_DEVICE_MAX_CHANNELS,
+ MicArrayPinDeviceFormatsAndModes,
+ SIZEOF_ARRAY(MicArrayPinDeviceFormatsAndModes),
+ MicArray1TopologyPhysicalConnections,
+ SIZEOF_ARRAY(MicArray1TopologyPhysicalConnections),
+ ENDPOINT_NO_FLAGS,
+};
+
+
+//=============================================================================
+//
+// Render miniport pairs. NOTE: the split of render and capture is arbitrary and
+// unnessary, this array could contain capture endpoints.
+//
+static
+PENDPOINT_MINIPAIR g_RenderEndpoints[] =
+{
+ &SpeakerMiniports,
+};
+
+#define g_cRenderEndpoints (SIZEOF_ARRAY(g_RenderEndpoints))
+
+//=============================================================================
+//
+// Capture miniport pairs. NOTE: the split of render and capture is arbitrary and
+// unnessary, this array could contain render endpoints.
+//
+static
+PENDPOINT_MINIPAIR g_CaptureEndpoints[] =
+{
+ &MicArray1Miniports,
+};
+
+#define g_cCaptureEndpoints (SIZEOF_ARRAY(g_CaptureEndpoints))
+
+//=============================================================================
+//
+// Total miniports = # endpoints * 2 (topology + wave).
+//
+#define g_MaxMiniports ((g_cRenderEndpoints + g_cCaptureEndpoints) * 2)
+
+#endif // _SIMPLEAUDIOSAMPLE_MINIPAIRS_H_
diff --git a/audio/simpleaudiosample/Source/Filters/speakertopo.cpp b/audio/simpleaudiosample/Source/Filters/speakertopo.cpp
new file mode 100644
index 00000000..d1635efa
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Filters/speakertopo.cpp
@@ -0,0 +1,118 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ speakertopo.cpp
+
+Abstract:
+
+ Implementation of topology miniport for the speaker (internal).
+--*/
+
+#pragma warning (disable : 4127)
+
+#include "definitions.h"
+#include "endpoints.h"
+#include "mintopo.h"
+#include "speakertopo.h"
+#include "speakertoptable.h"
+
+
+#pragma code_seg("PAGE")
+//=============================================================================
+NTSTATUS
+PropertyHandler_SpeakerTopoFilter
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+/*++
+
+Routine Description:
+
+ Redirects property request to miniport object
+
+Arguments:
+
+ PropertyRequest -
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(PropertyRequest);
+
+ DPF_ENTER(("[PropertyHandler_SpeakerTopoFilter]"));
+
+ // PropertryRequest structure is filled by portcls.
+ // MajorTarget is a pointer to miniport object for miniports.
+ //
+ NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+ PCMiniportTopology pMiniport = (PCMiniportTopology)PropertyRequest->MajorTarget;
+
+ if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Jack))
+ {
+ if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION)
+ {
+ ntStatus = pMiniport->PropertyHandlerJackDescription(
+ PropertyRequest,
+ ARRAYSIZE(SpeakerJackDescriptions),
+ SpeakerJackDescriptions
+ );
+ }
+ else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION2)
+ {
+ ntStatus = pMiniport->PropertyHandlerJackDescription2(
+ PropertyRequest,
+ ARRAYSIZE(SpeakerJackDescriptions),
+ SpeakerJackDescriptions,
+ 0 // jack capabilities
+ );
+ }
+ }
+
+ return ntStatus;
+} // PropertyHandler_SpeakerTopoFilter
+
+//=============================================================================
+NTSTATUS
+PropertyHandler_SpeakerTopology
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+/*++
+
+Routine Description:
+
+ Redirects property request to miniport object
+
+Arguments:
+
+ PropertyRequest -
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(PropertyRequest);
+
+ DPF_ENTER(("[PropertyHandler_SpeakerTopology]"));
+
+ // PropertryRequest structure is filled by portcls.
+ // MajorTarget is a pointer to miniport object for miniports.
+ //
+ PCMiniportTopology pMiniport = (PCMiniportTopology)PropertyRequest->MajorTarget;
+
+ return pMiniport->PropertyHandlerGeneric(PropertyRequest);
+} // PropertyHandler_SpeakerTopology
+
+#pragma code_seg()
diff --git a/audio/simpleaudiosample/Source/Filters/speakertopo.h b/audio/simpleaudiosample/Source/Filters/speakertopo.h
new file mode 100644
index 00000000..0eff1ebb
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Filters/speakertopo.h
@@ -0,0 +1,22 @@
+
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ speakertopo.h
+
+Abstract:
+
+ Declaration of topology miniport for the speaker (internal).
+--*/
+
+#ifndef _SIMPLEAUDIOSAMPLE_SPEAKERTOPO_H_
+#define _SIMPLEAUDIOSAMPLE_SPEAKERTOPO_H_
+
+NTSTATUS PropertyHandler_SpeakerTopoFilter(_In_ PPCPROPERTY_REQUEST PropertyRequest);
+
+NTSTATUS PropertyHandler_SpeakerTopology(_In_ PPCPROPERTY_REQUEST PropertyRequest);
+
+#endif // _SIMPLEAUDIOSAMPLE_SPEAKERTOPO_H_
diff --git a/audio/simpleaudiosample/Source/Filters/speakertoptable.h b/audio/simpleaudiosample/Source/Filters/speakertoptable.h
new file mode 100644
index 00000000..1b046d96
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Filters/speakertoptable.h
@@ -0,0 +1,206 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ speakertoptable.h
+
+Abstract:
+
+ Declaration of topology tables.
+--*/
+
+#ifndef _SIMPLEAUDIOSAMPLE_SPEAKERTOPTABLE_H_
+#define _SIMPLEAUDIOSAMPLE_SPEAKERTOPTABLE_H_
+
+//=============================================================================
+static
+KSDATARANGE SpeakerTopoPinDataRangesBridge[] =
+{
+ {
+ sizeof(KSDATARANGE),
+ 0,
+ 0,
+ 0,
+ STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
+ STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
+ STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
+ }
+};
+
+//=============================================================================
+static
+PKSDATARANGE SpeakerTopoPinDataRangePointersBridge[] =
+{
+ &SpeakerTopoPinDataRangesBridge[0]
+};
+
+//=============================================================================
+static
+PCPIN_DESCRIPTOR SpeakerTopoMiniportPins[] =
+{
+ // KSPIN_TOPO_WAVEOUT_SOURCE
+ {
+ 0,
+ 0,
+ 0, // InstanceCount
+ NULL, // AutomationTable
+ { // KsPinDescriptor
+ 0, // InterfacesCount
+ NULL, // Interfaces
+ 0, // MediumsCount
+ NULL, // Mediums
+ SIZEOF_ARRAY(SpeakerTopoPinDataRangePointersBridge),// DataRangesCount
+ SpeakerTopoPinDataRangePointersBridge, // DataRanges
+ KSPIN_DATAFLOW_IN, // DataFlow
+ KSPIN_COMMUNICATION_NONE, // Communication
+ &KSCATEGORY_AUDIO, // Category
+ NULL, // Name
+ 0 // Reserved
+ }
+ },
+ // KSPIN_TOPO_LINEOUT_DEST
+ {
+ 0,
+ 0,
+ 0, // InstanceCount
+ NULL, // AutomationTable
+ { // KsPinDescriptor
+ 0, // InterfacesCount
+ NULL, // Interfaces
+ 0, // MediumsCount
+ NULL, // Mediums
+ SIZEOF_ARRAY(SpeakerTopoPinDataRangePointersBridge),// DataRangesCount
+ SpeakerTopoPinDataRangePointersBridge, // DataRanges
+ KSPIN_DATAFLOW_OUT, // DataFlow
+ KSPIN_COMMUNICATION_NONE, // Communication
+ &KSNODETYPE_SPEAKER, // Category
+ NULL, // Name
+ 0 // Reserved
+ }
+ }
+};
+
+//=============================================================================
+static
+KSJACK_DESCRIPTION SpeakerJackDescBridge =
+{
+ KSAUDIO_SPEAKER_STEREO,
+ 0xB3C98C, // Color spec for green
+ eConnTypeUnknown,
+ eGeoLocFront,
+ eGenLocPrimaryBox,
+ ePortConnIntegratedDevice,
+ TRUE
+};
+
+// Only return a KSJACK_DESCRIPTION for the physical bridge pin.
+static
+PKSJACK_DESCRIPTION SpeakerJackDescriptions[] =
+{
+ NULL,
+ &SpeakerJackDescBridge
+};
+
+//=============================================================================
+static
+PCPROPERTY_ITEM SpeakerPropertiesVolume[] =
+{
+ {
+ &KSPROPSETID_Audio,
+ KSPROPERTY_AUDIO_VOLUMELEVEL,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_SpeakerTopology
+ }
+};
+
+DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerVolume, SpeakerPropertiesVolume);
+
+//=============================================================================
+static
+PCPROPERTY_ITEM SpeakerPropertiesMute[] =
+{
+ {
+ &KSPROPSETID_Audio,
+ KSPROPERTY_AUDIO_MUTE,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_SpeakerTopology
+ }
+};
+
+DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerMute, SpeakerPropertiesMute);
+
+//=============================================================================
+static
+PCNODE_DESCRIPTOR SpeakerTopologyNodes[] =
+{
+ // KSNODE_TOPO_VOLUME
+ {
+ 0, // Flags
+ &AutomationSpeakerVolume, // AutomationTable
+ &KSNODETYPE_VOLUME, // Type
+ &KSAUDFNAME_MASTER_VOLUME // Name
+ },
+ // KSNODE_TOPO_MUTE
+ {
+ 0, // Flags
+ &AutomationSpeakerMute, // AutomationTable
+ &KSNODETYPE_MUTE, // Type
+ &KSAUDFNAME_MASTER_MUTE // Name
+ }
+};
+
+C_ASSERT(KSNODE_TOPO_VOLUME == 0);
+C_ASSERT(KSNODE_TOPO_MUTE == 1);
+
+static
+PCCONNECTION_DESCRIPTOR SpeakerTopoMiniportConnections[] =
+{
+ // FromNode, FromPin, ToNode, ToPin
+ { PCFILTER_NODE, KSPIN_TOPO_WAVEOUT_SOURCE, KSNODE_TOPO_VOLUME, 1 },
+ { KSNODE_TOPO_VOLUME, 0, KSNODE_TOPO_MUTE, 1 },
+ { KSNODE_TOPO_MUTE, 0, PCFILTER_NODE, KSPIN_TOPO_LINEOUT_DEST }
+};
+
+//=============================================================================
+static
+PCPROPERTY_ITEM PropertiesSpeakerTopoFilter[] =
+{
+ {
+ &KSPROPSETID_Jack,
+ KSPROPERTY_JACK_DESCRIPTION,
+ KSPROPERTY_TYPE_GET |
+ KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_SpeakerTopoFilter
+ },
+ {
+ &KSPROPSETID_Jack,
+ KSPROPERTY_JACK_DESCRIPTION2,
+ KSPROPERTY_TYPE_GET |
+ KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_SpeakerTopoFilter
+ }
+};
+
+DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerTopoFilter, PropertiesSpeakerTopoFilter);
+
+//=============================================================================
+static
+PCFILTER_DESCRIPTOR SpeakerTopoMiniportFilterDescriptor =
+{
+ 0, // Version
+ &AutomationSpeakerTopoFilter, // AutomationTable
+ sizeof(PCPIN_DESCRIPTOR), // PinSize
+ SIZEOF_ARRAY(SpeakerTopoMiniportPins), // PinCount
+ SpeakerTopoMiniportPins, // Pins
+ sizeof(PCNODE_DESCRIPTOR), // NodeSize
+ SIZEOF_ARRAY(SpeakerTopologyNodes), // NodeCount
+ SpeakerTopologyNodes, // Nodes
+ SIZEOF_ARRAY(SpeakerTopoMiniportConnections), // ConnectionCount
+ SpeakerTopoMiniportConnections, // Connections
+ 0, // CategoryCount
+ NULL // Categories
+};
+
+#endif // _SIMPLEAUDIOSAMPLE_SPEAKERTOPTABLE_H_
diff --git a/audio/sysvad/PhoneAudioSample/FMWavTable.h b/audio/simpleaudiosample/Source/Filters/speakerwavtable.h
index 6ef9fb46..e67a673c 100644
--- a/audio/sysvad/PhoneAudioSample/FMWavTable.h
+++ b/audio/simpleaudiosample/Source/Filters/speakerwavtable.h
@@ -4,34 +4,35 @@ Copyright (c) Microsoft Corporation All Rights Reserved
Module Name:
- fmwavtable.h
+ speakerwavtable.h
Abstract:
- Declaration of wave miniport tables for the fm endpoint.
-
- Note: the FM in this sample shows how to do h/w loopback
- for non-offloaded devices.
-
+ Declaration of wave miniport tables for the render endpoints.
--*/
-#ifndef _SYSVAD_FMWAVTABLE_H_
-#define _SYSVAD_FMWAVTABLE_H_
+#ifndef _SIMPLEAUDIOSAMPLE_SPEAKERWAVTABLE_H_
+#define _SIMPLEAUDIOSAMPLE_SPEAKERWAVTABLE_H_
+// To keep the code simple assume device supports only 48KHz, 16-bit, stereo (PCM and NON-PCM)
-#define FMRX_DEVICE_MAX_CHANNELS 2 // Max Channels.
+#define SPEAKER_DEVICE_MAX_CHANNELS 2 // Max Channels.
-#define FMRX_MAX_CHANNELS 2 // Max Channels.
-#define FMRX_MIN_BITS_PER_SAMPLE 16 // Min Bits Per Sample
-#define FMRX_MAX_BITS_PER_SAMPLE 16 // Max Bits Per Sample
-#define FMRX_MIN_SAMPLE_RATE 48000 // Min Sample Rate
-#define FMRX_MAX_SAMPLE_RATE 48000 // Max Sample Rate
-#define FMRX_MAX_INPUT_SYSTEM_STREAMS 1
+#define SPEAKER_HOST_MAX_CHANNELS 2 // Max Channels.
+#define SPEAKER_HOST_MIN_BITS_PER_SAMPLE 16 // Min Bits Per Sample
+#define SPEAKER_HOST_MAX_BITS_PER_SAMPLE 16 // Max Bits Per Sample
+#define SPEAKER_HOST_MIN_SAMPLE_RATE 48000 // Min Sample Rate
+#define SPEAKER_HOST_MAX_SAMPLE_RATE 48000 // Max Sample Rate
+//
+// Max # of pin instances.
+//
+#define SPEAKER_MAX_INPUT_SYSTEM_STREAMS 1
//=============================================================================
+
static
-KSDATAFORMAT_WAVEFORMATEXTENSIBLE FmRxPinSupportedDeviceFormats[] =
+KSDATAFORMAT_WAVEFORMATEXTENSIBLE SpeakerHostPinSupportedDeviceFormats[] =
{
{ // 0
{
@@ -64,40 +65,40 @@ KSDATAFORMAT_WAVEFORMATEXTENSIBLE FmRxPinSupportedDeviceFormats[] =
// Supported modes (only on streaming pins).
//
static
-MODE_AND_DEFAULT_FORMAT FmRxPinSupportedDeviceModes[] =
+MODE_AND_DEFAULT_FORMAT SpeakerHostPinSupportedDeviceModes[] =
{
{
- STATIC_AUDIO_SIGNALPROCESSINGMODE_RAW,
- &FmRxPinSupportedDeviceFormats[SIZEOF_ARRAY(FmRxPinSupportedDeviceFormats) - 1].DataFormat
+ STATIC_AUDIO_SIGNALPROCESSINGMODE_DEFAULT,
+ &SpeakerHostPinSupportedDeviceFormats[0].DataFormat // 48KHz
}
};
-//=============================================================================
+//
// The entries here must follow the same order as the filter's pin
// descriptor array.
//
-static
-PIN_DEVICE_FORMATS_AND_MODES FmRxPinDeviceFormatsAndModes[] =
+static
+PIN_DEVICE_FORMATS_AND_MODES SpeakerPinDeviceFormatsAndModes[] =
{
- { // RX
- SystemCapturePin,
- FmRxPinSupportedDeviceFormats,
- SIZEOF_ARRAY(FmRxPinSupportedDeviceFormats),
- FmRxPinSupportedDeviceModes,
- SIZEOF_ARRAY(FmRxPinSupportedDeviceModes)
+ {
+ SystemRenderPin,
+ SpeakerHostPinSupportedDeviceFormats,
+ SIZEOF_ARRAY(SpeakerHostPinSupportedDeviceFormats),
+ SpeakerHostPinSupportedDeviceModes,
+ SIZEOF_ARRAY(SpeakerHostPinSupportedDeviceModes)
},
{
BridgePin,
NULL,
0,
NULL,
- 0,
- },
+ 0
+ }
};
//=============================================================================
static
-KSDATARANGE_AUDIO FmPinDataRangesStream[] =
+KSDATARANGE_AUDIO SpeakerPinDataRangesStream[] =
{
{ // 0
{
@@ -109,24 +110,24 @@ KSDATARANGE_AUDIO FmPinDataRangesStream[] =
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
},
- FMRX_MAX_CHANNELS,
- FMRX_MIN_BITS_PER_SAMPLE,
- FMRX_MAX_BITS_PER_SAMPLE,
- FMRX_MIN_SAMPLE_RATE,
- FMRX_MAX_SAMPLE_RATE
- },
+ SPEAKER_HOST_MAX_CHANNELS,
+ SPEAKER_HOST_MIN_BITS_PER_SAMPLE,
+ SPEAKER_HOST_MAX_BITS_PER_SAMPLE,
+ SPEAKER_HOST_MIN_SAMPLE_RATE,
+ SPEAKER_HOST_MAX_SAMPLE_RATE
+ }
};
static
-PKSDATARANGE FmPinDataRangePointersStream[] =
+PKSDATARANGE SpeakerPinDataRangePointersStream[] =
{
- PKSDATARANGE(&FmPinDataRangesStream[0]),
- PKSDATARANGE(&PinDataRangeAttributeList)
+ PKSDATARANGE(&SpeakerPinDataRangesStream[0]),
+ PKSDATARANGE(&PinDataRangeAttributeList),
};
//=============================================================================
static
-KSDATARANGE FmPinDataRangesBridge[] =
+KSDATARANGE SpeakerPinDataRangesBridge[] =
{
{
sizeof(KSDATARANGE),
@@ -140,37 +141,36 @@ KSDATARANGE FmPinDataRangesBridge[] =
};
static
-PKSDATARANGE FmPinDataRangePointersBridge[] =
+PKSDATARANGE SpeakerPinDataRangePointersBridge[] =
{
- &FmPinDataRangesBridge[0]
+ &SpeakerPinDataRangesBridge[0]
};
-
//=============================================================================
static
-PCPIN_DESCRIPTOR FmWaveMiniportPins[] =
+PCPIN_DESCRIPTOR SpeakerWaveMiniportPins[] =
{
- // Wave In Streaming Pin KSPIN_WAVE_FMRX
+ // Wave Out Streaming Pin (Renderer) KSPIN_WAVE_RENDER3_SINK_SYSTEM
{
- FMRX_MAX_INPUT_SYSTEM_STREAMS,
- FMRX_MAX_INPUT_SYSTEM_STREAMS,
+ SPEAKER_MAX_INPUT_SYSTEM_STREAMS,
+ SPEAKER_MAX_INPUT_SYSTEM_STREAMS,
0,
- NULL,
+ NULL, // AutomationTable
{
0,
NULL,
0,
NULL,
- SIZEOF_ARRAY(FmPinDataRangePointersStream),
- FmPinDataRangePointersStream,
- KSPIN_DATAFLOW_OUT,
+ SIZEOF_ARRAY(SpeakerPinDataRangePointersStream),
+ SpeakerPinDataRangePointersStream,
+ KSPIN_DATAFLOW_IN,
KSPIN_COMMUNICATION_SINK,
&KSCATEGORY_AUDIO,
NULL,
0
}
},
- // Wave In Bridge Pin KSPIN_WAVE_FMRX_BRIDGE
+ // Wave Out Bridge Pin (Renderer) KSPIN_WAVE_RENDER3_SOURCE
{
0,
0,
@@ -181,9 +181,9 @@ PCPIN_DESCRIPTOR FmWaveMiniportPins[] =
NULL,
0,
NULL,
- SIZEOF_ARRAY(FmPinDataRangePointersBridge),
- FmPinDataRangePointersBridge,
- KSPIN_DATAFLOW_IN,
+ SIZEOF_ARRAY(SpeakerPinDataRangePointersBridge),
+ SpeakerPinDataRangePointersBridge,
+ KSPIN_DATAFLOW_OUT,
KSPIN_COMMUNICATION_NONE,
&KSCATEGORY_AUDIO,
NULL,
@@ -194,21 +194,20 @@ PCPIN_DESCRIPTOR FmWaveMiniportPins[] =
//=============================================================================
//
-// -----
-// | |
-// FM RX bridge pin 1 -->| |--> 0 FM RX pin
-// | |
-// -----
-
+// ----------------------------
+// | |
+// Host Pin 0-->| |--> 1 KSPIN_WAVE_RENDER3_SOURCE
+// | |
+// ----------------------------
static
-PCCONNECTION_DESCRIPTOR FmWaveMiniportConnections[] =
+PCCONNECTION_DESCRIPTOR SpeakerWaveMiniportConnections[] =
{
- { PCFILTER_NODE, KSPIN_WAVE_FMRX_BRIDGE, PCFILTER_NODE, KSPIN_WAVE_FMRX },
+ { PCFILTER_NODE, KSPIN_WAVE_RENDER3_SINK_SYSTEM, PCFILTER_NODE, KSPIN_WAVE_RENDER3_SOURCE }
};
//=============================================================================
static
-PCPROPERTY_ITEM PropertiesFmWaveFilter[] =
+PCPROPERTY_ITEM PropertiesSpeakerWaveFilter[] =
{
{
&KSPROPSETID_Pin,
@@ -221,34 +220,27 @@ PCPROPERTY_ITEM PropertiesFmWaveFilter[] =
KSPROPERTY_PIN_PROPOSEDATAFORMAT2,
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
PropertyHandler_WaveFilter
- },
- {
- &KSPROPSETID_FMRXControl,
- KSPROPERTY_FMRX_STATE,
- KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_FmRxWaveFilter
}
};
-DEFINE_PCAUTOMATION_TABLE_PROP(AutomationFmWaveFilter, PropertiesFmWaveFilter);
+DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerWaveFilter, PropertiesSpeakerWaveFilter);
//=============================================================================
static
-PCFILTER_DESCRIPTOR FmWaveMiniportFilterDescriptor =
+PCFILTER_DESCRIPTOR SpeakerWaveMiniportFilterDescriptor =
{
0, // Version
- &AutomationFmWaveFilter, // AutomationTable
+ &AutomationSpeakerWaveFilter, // AutomationTable
sizeof(PCPIN_DESCRIPTOR), // PinSize
- SIZEOF_ARRAY(FmWaveMiniportPins), // PinCount
- FmWaveMiniportPins, // Pins
+ SIZEOF_ARRAY(SpeakerWaveMiniportPins), // PinCount
+ SpeakerWaveMiniportPins, // Pins
sizeof(PCNODE_DESCRIPTOR), // NodeSize
0, // NodeCount
NULL, // Nodes
- SIZEOF_ARRAY(FmWaveMiniportConnections), // ConnectionCount
- FmWaveMiniportConnections, // Connections
+ SIZEOF_ARRAY(SpeakerWaveMiniportConnections), // ConnectionCount
+ SpeakerWaveMiniportConnections, // Connections
0, // CategoryCount
NULL // Categories - use defaults (audio, render, capture)
};
-#endif // _SYSVAD_FMWAVTABLE_H_
-
+#endif // _SIMPLEAUDIOSAMPLE_SPEAKERWAVTABLE_H_
diff --git a/audio/simpleaudiosample/Source/Inc/Inc.vcxproj b/audio/simpleaudiosample/Source/Inc/Inc.vcxproj
new file mode 100644
index 00000000..ab768d84
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Inc/Inc.vcxproj
@@ -0,0 +1,260 @@
+<?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|ARM64">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM64">
+ <Configuration>Release</Configuration>
+ <Platform>ARM64</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>{4B664BA5-057A-41B8-B365-2C99065C4DFA}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{F51739CE-5253-42B5-9191-57F28B5842C6}</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>StaticLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>StaticLibrary</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>StaticLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>StaticLibrary</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>StaticLibrary</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>StaticLibrary</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 Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
+ <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 Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
+ <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" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>Inc</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <TargetName>Inc</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>Inc</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <TargetName>Inc</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>Inc</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>Inc</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <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>
diff --git a/audio/simpleaudiosample/Source/Inc/Inc.vcxproj.Filters b/audio/simpleaudiosample/Source/Inc/Inc.vcxproj.Filters
new file mode 100644
index 00000000..353662af
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Inc/Inc.vcxproj.Filters
@@ -0,0 +1,27 @@
+<?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>{54BE0AAC-642F-4D50-80D1-CA3C4BB4BB4C}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{6A00B9EC-DB03-4D51-B351-60DE9C0C51A1}</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>{887357BD-50C0-40E6-85E8-87E0F45862DB}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="*.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+</Project>
diff --git a/audio/simpleaudiosample/Source/Inc/NewDelete.h b/audio/simpleaudiosample/Source/Inc/NewDelete.h
new file mode 100644
index 00000000..ebeab037
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Inc/NewDelete.h
@@ -0,0 +1,104 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+NewDelete.h
+
+Abstract:
+
+Declaration of placement new and delete operators.
+--*/
+#pragma once
+
+#ifdef _NEW_DELETE_OPERATORS_
+
+/*****************************************************************************
+* Functions
+*/
+
+/*****************************************************************************
+* ::new()
+*****************************************************************************
+* New function for creating objects with a specified allocation tag and
+* pool type
+*/
+PVOID operator new
+(
+ size_t iSize,
+ POOL_FLAGS poolFlags,
+ ULONG tag
+);
+
+
+/*****************************************************************************
+* ::new()
+*****************************************************************************
+* New function for creating objects with a specified pool type.
+*/
+PVOID operator new
+(
+ size_t iSize,
+ POOL_FLAGS poolFlags
+);
+
+
+/*****************************************************************************
+* ::delete()
+*****************************************************************************
+* Delete with tag function.
+*/
+void __cdecl operator delete
+(
+ PVOID pVoid,
+ ULONG tag
+);
+
+
+/*****************************************************************************
+* ::delete()
+*****************************************************************************
+* Sized Delete function.
+*/
+void __cdecl operator delete
+(
+ _Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid,
+ _In_ size_t cbSize
+);
+
+
+/*****************************************************************************
+* ::delete()
+*****************************************************************************
+* Basic Delete function.
+*/
+void __cdecl operator delete
+(
+ PVOID pVoid
+);
+
+
+/*****************************************************************************
+* ::delete()
+*****************************************************************************
+* Sized Array Delete function.
+*/
+void __cdecl operator delete[]
+(
+ _Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid,
+ _In_ size_t cbSize
+);
+
+
+/*****************************************************************************
+* ::delete()
+*****************************************************************************
+* Array Delete function.
+*/
+void __cdecl operator delete[]
+(
+ _Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid
+);
+
+#endif//_NEW_DELETE_OPERATORS_
diff --git a/audio/simpleaudiosample/Source/Inc/basetopo.h b/audio/simpleaudiosample/Source/Inc/basetopo.h
new file mode 100644
index 00000000..a893aa3e
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Inc/basetopo.h
@@ -0,0 +1,96 @@
+
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ basetopo.h
+
+Abstract:
+
+ Declaration of topology miniport.
+--*/
+
+#ifndef _SIMPLEAUDIOSAMPLE_BASETOPO_H_
+#define _SIMPLEAUDIOSAMPLE_BASETOPO_H_
+
+//=============================================================================
+// Classes
+//=============================================================================
+
+///////////////////////////////////////////////////////////////////////////////
+// CMiniportTopologySimpleAudioSample
+//
+
+class CMiniportTopologySimpleAudioSample
+{
+ protected:
+ PADAPTERCOMMON m_AdapterCommon; // Adapter common object.
+ PPCFILTER_DESCRIPTOR m_FilterDescriptor; // Filter descriptor.
+ PPORTEVENTS m_PortEvents; // Event interface.
+ USHORT m_DeviceMaxChannels; // Max device channels.
+
+ public:
+ CMiniportTopologySimpleAudioSample(
+ _In_ PCFILTER_DESCRIPTOR *FilterDesc,
+ _In_ USHORT DeviceMaxChannels
+ );
+
+ ~CMiniportTopologySimpleAudioSample();
+
+ NTSTATUS GetDescription
+ (
+ _Out_ PPCFILTER_DESCRIPTOR * Description
+ );
+
+ NTSTATUS DataRangeIntersection
+ (
+ _In_ ULONG PinId,
+ _In_ PKSDATARANGE ClientDataRange,
+ _In_ PKSDATARANGE MyDataRange,
+ _In_ ULONG OutputBufferLength,
+ _Out_writes_bytes_to_opt_(OutputBufferLength, *ResultantFormatLength)
+ PVOID ResultantFormat OPTIONAL,
+ _Out_ PULONG ResultantFormatLength
+ );
+
+ NTSTATUS Init
+ (
+ _In_ PUNKNOWN UnknownAdapter,
+ _In_ PPORTTOPOLOGY Port_
+ );
+
+ // PropertyHandlers.
+ NTSTATUS PropertyHandlerGeneric
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
+
+ NTSTATUS PropertyHandlerMuxSource
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
+
+ NTSTATUS PropertyHandlerDevSpecific
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
+
+ VOID AddEventToEventList
+ (
+ _In_ PKSEVENT_ENTRY EventEntry
+ );
+
+ VOID GenerateEventList
+ (
+ _In_opt_ GUID *Set,
+ _In_ ULONG EventId,
+ _In_ BOOL PinEvent,
+ _In_ ULONG PinId,
+ _In_ BOOL NodeEvent,
+ _In_ ULONG NodeId
+ );
+};
+
+#endif
diff --git a/audio/simpleaudiosample/Source/Inc/common.h b/audio/simpleaudiosample/Source/Inc/common.h
new file mode 100644
index 00000000..2d2db7db
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Inc/common.h
@@ -0,0 +1,477 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ Common.h
+
+Abstract:
+
+ CAdapterCommon class declaration.
+--*/
+
+#ifndef _SIMPLEAUDIOSAMPLE_COMMON_H_
+#define _SIMPLEAUDIOSAMPLE_COMMON_H_
+
+#define HNSTIME_PER_MILLISECOND 10000
+
+//=============================================================================
+// Macros
+//=============================================================================
+
+#define UNREFERENCED_VAR(status) \
+ status = status
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// jump to the given label.
+//
+// Parameters:
+//
+// label - [in] label to jump if condition is met
+//
+#define JUMP(label) \
+ goto label;
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// If the condition evaluates to TRUE, jump to the given label.
+//
+// Parameters:
+//
+// condition - [in] Code that fits in if statement
+// label - [in] label to jump if condition is met
+//
+#define IF_TRUE_JUMP(condition, label) \
+ if (condition) \
+ { \
+ goto label; \
+ }
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// If the condition evaluates to TRUE, perform the given statement
+// then jump to the given label.
+//
+// Parameters:
+//
+// condition - [in] Code that fits in if statement
+// action - [in] action to perform in body of if statement
+// label - [in] label to jump if condition is met
+//
+#define IF_TRUE_ACTION_JUMP(condition, action, label) \
+ if (condition) \
+ { \
+ action; \
+ goto label; \
+ }
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// If the ntStatus is not NT_SUCCESS, perform the given statement then jump to
+// the given label.
+//
+// Parameters:
+//
+// ntStatus - [in] Value to check
+// action - [in] action to perform in body of if statement
+// label - [in] label to jump if condition is met
+//
+#define IF_FAILED_ACTION_JUMP(ntStatus, action, label) \
+ if (!NT_SUCCESS(ntStatus)) \
+ { \
+ action; \
+ goto label; \
+ }
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// If the ntStatus passed is not NT_SUCCESS, jump to the given label.
+//
+// Parameters:
+//
+// ntStatus - [in] Value to check
+// label - [in] label to jump if condition is met
+//
+#define IF_FAILED_JUMP(ntStatus, label) \
+ if (!NT_SUCCESS(ntStatus)) \
+ { \
+ goto label; \
+ }
+
+#define SAFE_RELEASE(p) {if (p) { (p)->Release(); (p) = nullptr; } }
+#define SAFE_DELETE_PTR_WITH_TAG(ptr, tag) if(ptr) { ExFreePoolWithTag((ptr), tag); (ptr) = NULL; }
+
+// JACKDESC_RGB(r, g, b)
+#define JACKDESC_RGB(r, g, b) \
+ ((COLORREF)((r << 16) | (g << 8) | (b)))
+
+// Min/Max defines.
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+
+#define MINWAVERT_POOLTAG 'RWNM'
+#define MINTOPORT_POOLTAG 'RTNM'
+#define MINADAPTER_POOLTAG 'uAyS'
+
+typedef enum
+{
+ eSpeakerDevice = 0,
+ eMicArrayDevice1,
+ eMaxDeviceType,
+} eDeviceType;
+
+//
+// Signal processing modes and default formats structs.
+//
+typedef struct _MODE_AND_DEFAULT_FORMAT {
+ GUID Mode;
+ KSDATAFORMAT* DefaultFormat;
+} MODE_AND_DEFAULT_FORMAT, *PMODE_AND_DEFAULT_FORMAT;
+
+//
+// Enumeration of the various types of pins implemented in this driver.
+//
+typedef enum
+{
+ NoPin,
+ BridgePin,
+ SystemRenderPin,
+ SystemCapturePin,
+} PINTYPE;
+
+//
+// PIN_DEVICE_FORMATS_AND_MODES
+//
+// Used to specify a pin's type (e.g. system, offload, etc.), formats, and
+// modes. Conceptually serves similar purpose as the PCPIN_DESCRIPTOR to
+// define a pin, but is more specific to driver implementation.
+//
+// Arrays of these structures follow the same order as the filter's
+// pin descriptor array so that KS pin IDs can serve as an index.
+//
+typedef struct _PIN_DEVICE_FORMATS_AND_MODES
+{
+ PINTYPE PinType;
+
+ KSDATAFORMAT_WAVEFORMATEXTENSIBLE * WaveFormats;
+ ULONG WaveFormatsCount;
+
+ MODE_AND_DEFAULT_FORMAT * ModeAndDefaultFormat;
+ ULONG ModeAndDefaultFormatCount;
+
+} PIN_DEVICE_FORMATS_AND_MODES, *PPIN_DEVICE_FORMATS_AND_MODES;
+
+// forward declaration.
+typedef struct _ENDPOINT_MINIPAIR *PENDPOINT_MINIPAIR;
+
+// both wave & topology miniport create function prototypes have this form:
+typedef HRESULT (*PFNCREATEMINIPORT)(
+ _Out_ PUNKNOWN * Unknown,
+ _In_ REFCLSID,
+ _In_opt_ PUNKNOWN UnknownOuter,
+ _In_ POOL_FLAGS PoolFlags,
+ _In_ PUNKNOWN UnknownAdapter,
+ _In_opt_ PVOID DeviceContext,
+ _In_ PENDPOINT_MINIPAIR MiniportPair
+);
+
+//=============================================================================
+//
+//=============================================================================
+typedef struct _SIMPLEAUDIOSAMPLE_DEVPROPERTY {
+ const DEVPROPKEY *PropertyKey;
+ DEVPROPTYPE Type;
+ ULONG BufferSize;
+ __field_bcount_opt(BufferSize) PVOID Buffer;
+} SIMPLEAUDIOSAMPLE_DEVPROPERTY, PSIMPLEAUDIOSAMPLE_DEVPROPERTY;
+
+#define ENDPOINT_NO_FLAGS 0x00000000
+#define ENDPOINT_CELLULAR_PROVIDER1 0x00000008
+#define ENDPOINT_CELLULAR_PROVIDER2 0x00000010
+
+//
+// Endpoint miniport pair (wave/topology) descriptor.
+//
+typedef struct _ENDPOINT_MINIPAIR
+{
+ eDeviceType DeviceType;
+
+ // Topology miniport.
+ PWSTR TopoName; // make sure this or the template name matches with SIMPLEAUDIOSAMPLE.<TopoName>.szPname in the inf's [Strings] section
+ PWSTR TemplateTopoName; // optional template name
+ PFNCREATEMINIPORT TopoCreateCallback;
+ PCFILTER_DESCRIPTOR* TopoDescriptor;
+ ULONG TopoInterfacePropertyCount;
+ const SIMPLEAUDIOSAMPLE_DEVPROPERTY* TopoInterfaceProperties;
+
+ // Wave RT miniport.
+ PWSTR WaveName; // make sure this or the template name matches with SIMPLEAUDIOSAMPLE.<WaveName>.szPname in the inf's [Strings] section
+ PWSTR TemplateWaveName; // optional template name
+ PFNCREATEMINIPORT WaveCreateCallback;
+ PCFILTER_DESCRIPTOR* WaveDescriptor;
+ ULONG WaveInterfacePropertyCount;
+ const SIMPLEAUDIOSAMPLE_DEVPROPERTY* WaveInterfaceProperties;
+
+ USHORT DeviceMaxChannels;
+ PIN_DEVICE_FORMATS_AND_MODES* PinDeviceFormatsAndModes;
+ ULONG PinDeviceFormatsAndModesCount;
+
+ // Miniport physical connections.
+ PHYSICALCONNECTIONTABLE* PhysicalConnections;
+ ULONG PhysicalConnectionCount;
+
+ // General endpoint flags (one of more ENDPOINT_<flag-type>, see above)
+ ULONG DeviceFlags;
+} ENDPOINT_MINIPAIR;
+
+//=============================================================================
+// Defines
+//=============================================================================
+
+DEFINE_GUID(IID_IAdapterCommon,
+0x7eda2950, 0xbf9f, 0x11d0, 0x87, 0x1f, 0x0, 0xa0, 0xc9, 0x11, 0xb5, 0x44);
+
+//=============================================================================
+// Interfaces
+//=============================================================================
+
+///////////////////////////////////////////////////////////////////////////////
+// IAdapterCommon
+//
+DECLARE_INTERFACE_(IAdapterCommon, IUnknown)
+{
+ STDMETHOD_(NTSTATUS, Init)
+ (
+ THIS_
+ _In_ PDEVICE_OBJECT DeviceObject
+ ) PURE;
+
+ STDMETHOD_(PDEVICE_OBJECT, GetDeviceObject)
+ (
+ THIS
+ ) PURE;
+
+ STDMETHOD_(PDEVICE_OBJECT, GetPhysicalDeviceObject)
+ (
+ THIS
+ ) PURE;
+
+ STDMETHOD_(WDFDEVICE, GetWdfDevice)
+ (
+ THIS
+ ) PURE;
+
+ STDMETHOD_(VOID, SetWaveServiceGroup)
+ (
+ THIS_
+ _In_ PSERVICEGROUP ServiceGroup
+ ) PURE;
+
+ STDMETHOD_(BOOL, bDevSpecificRead)
+ (
+ THIS_
+ ) PURE;
+
+ STDMETHOD_(VOID, bDevSpecificWrite)
+ (
+ THIS_
+ _In_ BOOL bDevSpecific
+ );
+
+ STDMETHOD_(INT, iDevSpecificRead)
+ (
+ THIS_
+ ) PURE;
+
+ STDMETHOD_(VOID, iDevSpecificWrite)
+ (
+ THIS_
+ _In_ INT iDevSpecific
+ );
+
+ STDMETHOD_(UINT, uiDevSpecificRead)
+ (
+ THIS_
+ ) PURE;
+
+ STDMETHOD_(VOID, uiDevSpecificWrite)
+ (
+ THIS_
+ _In_ UINT uiDevSpecific
+ );
+
+ STDMETHOD_(BOOL, MixerMuteRead)
+ (
+ THIS_
+ _In_ ULONG Index,
+ _In_ ULONG Channel
+ ) PURE;
+
+ STDMETHOD_(VOID, MixerMuteWrite)
+ (
+ THIS_
+ _In_ ULONG Index,
+ _In_ ULONG Channel,
+ _In_ BOOL Value
+ );
+
+ STDMETHOD_(ULONG, MixerMuxRead)
+ (
+ THIS
+ );
+
+ STDMETHOD_(VOID, MixerMuxWrite)
+ (
+ THIS_
+ _In_ ULONG Index
+ );
+
+ STDMETHOD_(LONG, MixerVolumeRead)
+ (
+ THIS_
+ _In_ ULONG Index,
+ _In_ ULONG Channel
+ ) PURE;
+
+ STDMETHOD_(VOID, MixerVolumeWrite)
+ (
+ THIS_
+ _In_ ULONG Index,
+ _In_ ULONG Channel,
+ _In_ LONG Value
+ ) PURE;
+
+ STDMETHOD_(LONG, MixerPeakMeterRead)
+ (
+ THIS_
+ _In_ ULONG Index,
+ _In_ ULONG Channel
+ ) PURE;
+
+ STDMETHOD_(VOID, MixerReset)
+ (
+ THIS
+ ) PURE;
+
+ STDMETHOD_(NTSTATUS, WriteEtwEvent)
+ (
+ THIS_
+ _In_ EPcMiniportEngineEvent miniportEventType,
+ _In_ ULONGLONG ullData1,
+ _In_ ULONGLONG ullData2,
+ _In_ ULONGLONG ullData3,
+ _In_ ULONGLONG ullData4
+ ) PURE;
+
+ STDMETHOD_(VOID, SetEtwHelper)
+ (
+ THIS_
+ PPORTCLSETWHELPER _pPortClsEtwHelper
+ ) PURE;
+
+ STDMETHOD_(NTSTATUS, InstallSubdevice)
+ (
+ _In_opt_ PIRP Irp,
+ _In_ PWSTR Name,
+ _In_opt_ PWSTR TemplateName,
+ _In_ REFGUID PortClassId,
+ _In_ REFGUID MiniportClassId,
+ _In_opt_ PFNCREATEMINIPORT MiniportCreate,
+ _In_ ULONG cPropertyCount,
+ _In_reads_opt_(cPropertyCount) const SIMPLEAUDIOSAMPLE_DEVPROPERTY * pProperties,
+ _In_opt_ PVOID DeviceContext,
+ _In_ PENDPOINT_MINIPAIR MiniportPair,
+ _In_opt_ PRESOURCELIST ResourceList,
+ _In_ REFGUID PortInterfaceId,
+ _Out_opt_ PUNKNOWN * OutPortInterface,
+ _Out_opt_ PUNKNOWN * OutPortUnknown,
+ _Out_opt_ PUNKNOWN * OutMiniportUnknown
+ );
+
+ STDMETHOD_(NTSTATUS, UnregisterSubdevice)
+ (
+ THIS_
+ _In_opt_ PUNKNOWN UnknownPort
+ );
+
+ STDMETHOD_(NTSTATUS, ConnectTopologies)
+ (
+ THIS_
+ _In_ PUNKNOWN UnknownTopology,
+ _In_ PUNKNOWN UnknownWave,
+ _In_ PHYSICALCONNECTIONTABLE* PhysicalConnections,
+ _In_ ULONG PhysicalConnectionCount
+ );
+
+ STDMETHOD_(NTSTATUS, DisconnectTopologies)
+ (
+ THIS_
+ _In_ PUNKNOWN UnknownTopology,
+ _In_ PUNKNOWN UnknownWave,
+ _In_ PHYSICALCONNECTIONTABLE* PhysicalConnections,
+ _In_ ULONG PhysicalConnectionCount
+ );
+
+ STDMETHOD_(NTSTATUS, InstallEndpointFilters)
+ (
+ THIS_
+ _In_opt_ PIRP Irp,
+ _In_ PENDPOINT_MINIPAIR MiniportPair,
+ _In_opt_ PVOID DeviceContext,
+ _Out_opt_ PUNKNOWN * UnknownTopology,
+ _Out_opt_ PUNKNOWN * UnknownWave,
+ _Out_opt_ PUNKNOWN * UnknownMiniportTopology,
+ _Out_opt_ PUNKNOWN * UnknownMiniportWave
+ );
+
+ STDMETHOD_(NTSTATUS, RemoveEndpointFilters)
+ (
+ THIS_
+ _In_ PENDPOINT_MINIPAIR MiniportPair,
+ _In_opt_ PUNKNOWN UnknownTopology,
+ _In_opt_ PUNKNOWN UnknownWave
+ );
+
+ STDMETHOD_(NTSTATUS, GetFilters)
+ (
+ THIS_
+ _In_ PENDPOINT_MINIPAIR MiniportPair,
+ _Out_opt_ PUNKNOWN *UnknownTopologyPort,
+ _Out_opt_ PUNKNOWN *UnknownTopologyMiniport,
+ _Out_opt_ PUNKNOWN *UnknownWavePort,
+ _Out_opt_ PUNKNOWN *UnknownWaveMiniport
+ );
+
+ STDMETHOD_(NTSTATUS, SetIdlePowerManagement)
+ (
+ THIS_
+ _In_ PENDPOINT_MINIPAIR MiniportPair,
+ _In_ BOOL bEnable
+ );
+
+ STDMETHOD_(VOID, Cleanup)();
+
+};
+
+typedef IAdapterCommon *PADAPTERCOMMON;
+
+//=============================================================================
+// Function Prototypes
+//=============================================================================
+NTSTATUS
+NewAdapterCommon
+(
+ _Out_ PUNKNOWN * Unknown,
+ _In_ REFCLSID,
+ _In_opt_ PUNKNOWN UnknownOuter,
+ _In_ POOL_FLAGS PoolFlags
+);
+
+#endif //_SIMPLEAUDIOSAMPLE_COMMON_H_
diff --git a/audio/simpleaudiosample/Source/Inc/definitions.h b/audio/simpleaudiosample/Source/Inc/definitions.h
new file mode 100644
index 00000000..9fb4547a
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Inc/definitions.h
@@ -0,0 +1,198 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ Definitions.h
+
+Abstract:
+
+ Header file for common stuff.
+--*/
+
+#ifndef _SIMPLEAUDIOSAMPLE_DEFINITIONS_H_
+#define _SIMPLEAUDIOSAMPLE_DEFINITIONS_H_
+
+#include <portcls.h>
+#include <stdunk.h>
+#include <ksdebug.h>
+#include <ntintsafe.h>
+#include <wdf.h>
+#include <wdfminiport.h>
+#include <Ntstrsafe.h>
+#include "NewDelete.h"
+
+//=============================================================================
+// Defines
+//=============================================================================
+
+// Product Id
+// {836BA6D1-3FF7-4411-8BCD-469553452DCE}
+#define STATIC_PID_SIMPLEAUDIOSAMPLE\
+ 0x836ba6d1, 0x3ff7, 0x4411, 0x8b, 0xcd, 0x46, 0x95, 0x53, 0x45, 0x2d, 0xce
+DEFINE_GUIDSTRUCT("836BA6D1-3FF7-4411-8BCD-469553452DCE", PID_SIMPLEAUDIOSAMPLE);
+#define PID_SIMPLEAUDIOSAMPLE DEFINE_GUIDNAMED(PID_SIMPLEAUDIOSAMPLE)
+
+// Pool tag used for SIMPLEAUDIOSAMPLE allocations
+#define SIMPLEAUDIOSAMPLE_POOLTAG 'SASM'
+
+// Debug module name
+#define STR_MODULENAME "SIMPLEAUDIOSAMPLE: "
+
+// Debug utility macros
+#define D_FUNC 4
+#define D_BLAB DEBUGLVL_BLAB
+#define D_VERBOSE DEBUGLVL_VERBOSE
+#define D_TERSE DEBUGLVL_TERSE
+#define D_ERROR DEBUGLVL_ERROR
+#define DPF _DbgPrintF
+#define DPF_ENTER(x) DPF(D_FUNC, x)
+
+// Channel orientation
+#define CHAN_LEFT 0
+#define CHAN_RIGHT 1
+#define CHAN_MASTER (-1)
+
+// Dma Settings.
+#define DMA_BUFFER_SIZE 0x16000
+
+#define KSPROPERTY_TYPE_ALL KSPROPERTY_TYPE_BASICSUPPORT | \
+ KSPROPERTY_TYPE_GET | \
+ KSPROPERTY_TYPE_SET
+
+// Specific node numbers
+#define DEV_SPECIFIC_VT_BOOL 9
+#define DEV_SPECIFIC_VT_I4 10
+#define DEV_SPECIFIC_VT_UI4 11
+
+#define _100NS_PER_MILLISECOND 10000 // number of 100ns units per millisecond
+
+// Default volume settings.
+#define VOLUME_STEPPING_DELTA 0x8000
+#define VOLUME_SIGNED_MAXIMUM 0x00000000
+#define VOLUME_SIGNED_MINIMUM (-96 * 0x10000)
+
+// Default peak meter settings
+#define PEAKMETER_STEPPING_DELTA 0x1000
+#define PEAKMETER_SIGNED_MAXIMUM LONG_MAX
+#define PEAKMETER_SIGNED_MINIMUM LONG_MIN
+
+#define VALUE_NORMALIZE_P(v, step) \
+ ((((v) + (step)/2) / (step)) * (step))
+
+#define VALUE_NORMALIZE(v, step) \
+ ((v) > 0 ? VALUE_NORMALIZE_P((v), (step)) : -(VALUE_NORMALIZE_P(-(v), (step))))
+
+#define VALUE_NORMALIZE_IN_RANGE_EX(v, min, max, step) \
+ ((v) > (max) ? (max) : \
+ (v) < (min) ? (min) : \
+ VALUE_NORMALIZE((v), (step)))
+
+// to normalize volume values.
+#define VOLUME_NORMALIZE_IN_RANGE(v) \
+ VALUE_NORMALIZE_IN_RANGE_EX((v), VOLUME_SIGNED_MINIMUM, VOLUME_SIGNED_MAXIMUM, VOLUME_STEPPING_DELTA)
+
+// to normalize sample peak meter.
+#define PEAKMETER_NORMALIZE_IN_RANGE(v) \
+ VALUE_NORMALIZE_IN_RANGE_EX((v), PEAKMETER_SIGNED_MINIMUM, PEAKMETER_SIGNED_MAXIMUM, PEAKMETER_STEPPING_DELTA)
+
+#define ALL_CHANNELS_ID UINT32_MAX
+
+// Macros to assist with pin instance counting
+#define VERIFY_PIN_INSTANCE_RESOURCES_AVAILABLE(status, allocated, max) \
+ status = (allocated < max) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES
+
+#define ALLOCATE_PIN_INSTANCE_RESOURCES(allocated) \
+ allocated++
+
+#define FREE_PIN_INSTANCE_RESOURCES(allocated) \
+ allocated--
+
+// Define the value data type for supported sound detector patterns. Only
+// one pattern type is supported in this sample.
+typedef struct {
+ KSMULTIPLE_ITEM MultipleItem;
+ GUID PatternType[1];
+} CONTOSO_SUPPORTEDPATTERNSVALUE;
+
+//=============================================================================
+// Typedefs
+//=============================================================================
+
+// Flags to identify stream processing mode
+typedef enum {
+ CONNECTIONTYPE_TOPOLOGY_OUTPUT = 0,
+ CONNECTIONTYPE_WAVE_OUTPUT = 1
+} CONNECTIONTYPE;
+
+// Connection table for registering topology/wave bridge connection
+typedef struct _PHYSICALCONNECTIONTABLE
+{
+ ULONG ulTopology;
+ ULONG ulWave;
+ CONNECTIONTYPE eType;
+} PHYSICALCONNECTIONTABLE, *PPHYSICALCONNECTIONTABLE;
+
+//
+// This is the structure of the portclass FDO device extension Nt has created
+// for us. We keep the adapter common object here.
+//
+struct IAdapterCommon;
+typedef struct _PortClassDeviceContext // 32 64 Byte offsets for 32 and 64 bit architectures
+{
+ ULONG_PTR m_pulReserved1[2]; // 0-7 0-15 First two pointers are reserved.
+ PDEVICE_OBJECT m_DoNotUsePhysicalDeviceObject; // 8-11 16-23 Reserved pointer to our Physical Device Object (PDO).
+ PVOID m_pvReserved2; // 12-15 24-31 Reserved pointer to our Start Device function.
+ PVOID m_pvReserved3; // 16-19 32-39 "Out Memory" according to DDK.
+ IAdapterCommon* m_pCommon; // 20-23 40-47 Pointer to our adapter common object.
+ PVOID m_pvUnused1; // 24-27 48-55 Unused space.
+ PVOID m_pvUnused2; // 28-31 56-63 Unused space.
+
+ // Anything after above line should not be used.
+ // This actually goes on for (64*sizeof(ULONG_PTR)) but it is all opaque.
+} PortClassDeviceContext;
+
+//
+// Major/MinorTarget to object casting.
+//
+#define MajorTarget_to_Obj(ptr) \
+ reinterpret_cast<CMiniportWaveRT*>(ptr)
+
+#define MinorTarget_to_Obj(ptr) \
+ static_cast<CMiniportWaveRTStream*>(reinterpret_cast<PMINIPORTWAVERTSTREAM>(ptr))
+
+//
+// Global settings.
+//
+extern DWORD g_DoNotCreateDataFiles;
+extern DWORD g_DisableBthScoBypass;
+extern UNICODE_STRING g_RegistryPath;
+
+//=============================================================================
+// Function prototypes
+//=============================================================================
+
+// Generic topology handler
+NTSTATUS PropertyHandler_Topology
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+);
+
+// Default WaveFilter automation table.
+// Handles the GeneralComponentId request.
+NTSTATUS PropertyHandler_WaveFilter
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+);
+
+NTSTATUS PropertyHandler_GenericPin
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+);
+
+// common.h uses some of the above definitions.
+#include "common.h"
+#include "kshelper.h"
+
+#endif // _SIMPLEAUDIOSAMPLE_DEFINITIONS_H_
diff --git a/audio/simpleaudiosample/Source/Inc/endpoints.h b/audio/simpleaudiosample/Source/Inc/endpoints.h
new file mode 100644
index 00000000..44a858a0
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Inc/endpoints.h
@@ -0,0 +1,133 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ endpoints.h
+
+Abstract:
+
+ Node and Pin numbers and other common definitions for simple audio sample.
+--*/
+
+#ifndef _SIMPLEAUDIOSAMPLE_ENDPOINTS_H_
+#define _SIMPLEAUDIOSAMPLE_ENDPOINTS_H_
+
+// Name Guid
+// {0104947F-82AE-4291-A6F3-5E2DE1AD7DC2}
+#define STATIC_NAME_SIMPLE_AUDIO_SAMPLE\
+ 0x104947f, 0x82ae, 0x4291, 0xa6, 0xf3, 0x5e, 0x2d, 0xe1, 0xad, 0x7d, 0xc2
+DEFINE_GUIDSTRUCT("0104947F-82AE-4291-A6F3-5E2DE1AD7DC2", NAME_SIMPLE_AUDIO_SAMPLE);
+#define NAME_SIMPLE_AUDIO_SAMPLE DEFINE_GUIDNAMED(NAME_SIMPLE_AUDIO_SAMPLE)
+
+//----------------------------------------------------
+// New defines for the render endpoints.
+//----------------------------------------------------
+
+// Default pin instances.
+#define MAX_INPUT_SYSTEM_STREAMS 1
+
+// Wave pins - no mix, no offload
+enum
+{
+ KSPIN_WAVE_RENDER3_SINK_SYSTEM = 0,
+ KSPIN_WAVE_RENDER3_SOURCE
+};
+
+// Wave pins - offloading is NOT supported.
+enum
+{
+ KSPIN_WAVE_RENDER2_SINK_SYSTEM = 0,
+ KSPIN_WAVE_RENDER2_SINK_LOOPBACK,
+ KSPIN_WAVE_RENDER2_SOURCE
+};
+
+// Wave Topology nodes - offloading is NOT supported.
+enum
+{
+ KSNODE_WAVE_SUM = 0,
+ KSNODE_WAVE_VOLUME,
+ KSNODE_WAVE_MUTE,
+ KSNODE_WAVE_PEAKMETER
+};
+
+// Topology pins.
+enum
+{
+ KSPIN_TOPO_WAVEOUT_SOURCE = 0,
+ KSPIN_TOPO_LINEOUT_DEST,
+};
+
+// Topology nodes.
+enum
+{
+ KSNODE_TOPO_WAVEOUT_VOLUME = 0,
+ KSNODE_TOPO_WAVEOUT_MUTE,
+ KSNODE_TOPO_WAVEOUT_PEAKMETER
+};
+
+//----------------------------------------------------
+// New defines for the capture endpoints.
+//----------------------------------------------------
+
+// Default pin instances.
+#define MAX_INPUT_STREAMS 1 // Number of capture streams.
+
+// Wave pins
+enum
+{
+ KSPIN_WAVE_BRIDGE = 0,
+ KSPIN_WAVEIN_HOST,
+};
+
+// Wave Topology nodes.
+enum
+{
+ KSNODE_WAVE_ADC = 0
+};
+
+// Wave Topology nodes.
+enum
+{
+ KSNODE_WAVE_DAC = 0
+};
+
+// topology pins.
+enum
+{
+ KSPIN_TOPO_MIC_ELEMENTS,
+ KSPIN_TOPO_BRIDGE
+};
+
+// topology nodes.
+enum
+{
+ KSNODE_TOPO_VOLUME,
+ KSNODE_TOPO_MUTE,
+ KSNODE_TOPO_PEAKMETER
+};
+
+// data format attribute range definitions.
+static
+KSATTRIBUTE PinDataRangeSignalProcessingModeAttribute =
+{
+ sizeof(KSATTRIBUTE),
+ 0,
+ STATICGUIDOF(KSATTRIBUTEID_AUDIOSIGNALPROCESSING_MODE),
+};
+
+static
+PKSATTRIBUTE PinDataRangeAttributes[] =
+{
+ &PinDataRangeSignalProcessingModeAttribute,
+};
+
+static
+KSATTRIBUTE_LIST PinDataRangeAttributeList =
+{
+ ARRAYSIZE(PinDataRangeAttributes),
+ PinDataRangeAttributes,
+};
+
+#endif // _SIMPLEAUDIOSAMPLE_ENDPOINTS_H_
diff --git a/audio/simpleaudiosample/Source/Inc/kshelper.h b/audio/simpleaudiosample/Source/Inc/kshelper.h
new file mode 100644
index 00000000..023f773a
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Inc/kshelper.h
@@ -0,0 +1,159 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ kshelper.h
+
+Abstract:
+
+ Helper functions for simple audio sample
+--*/
+#ifndef _SIMPLEAUDIOSAMPLE_KSHELPER_H_
+#define _SIMPLEAUDIOSAMPLE_KSHELPER_H_
+
+#include <portcls.h>
+#include <ksdebug.h>
+
+PWAVEFORMATEX
+GetWaveFormatEx
+(
+ _In_ PKSDATAFORMAT pDataFormat
+);
+
+NTSTATUS
+ValidatePropertyParams
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG cbValueSize,
+ _In_ ULONG cbInstanceSize = 0
+);
+
+NTSTATUS
+PropertyHandler_BasicSupport
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG Flags,
+ _In_ DWORD PropTypeSetId
+);
+
+NTSTATUS
+PropertyHandler_BasicSupportVolume
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG MaxChannels
+);
+
+NTSTATUS
+PropertyHandler_BasicSupportMute
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG MaxChannels
+);
+
+NTSTATUS
+PropertyHandler_BasicSupportPeakMeter2
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG MaxChannels
+);
+
+NTSTATUS
+PropertyHandler_CpuResources
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+);
+
+NTSTATUS
+PropertyHandler_Volume
+(
+ _In_ PADAPTERCOMMON AdapterCommon,
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG MaxChannels
+);
+
+NTSTATUS
+PropertyHandler_Mute
+(
+ _In_ PADAPTERCOMMON AdapterCommon,
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG MaxChannels
+);
+
+NTSTATUS
+PropertyHandler_PeakMeter2
+(
+ _In_ PADAPTERCOMMON AdapterCommon,
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG MaxChannels
+);
+
+//=============================================================================
+// Property helpers
+//=============================================================================
+
+NTSTATUS
+SimpleAudioSamplePropertyDispatch
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+);
+
+// Use this structure to define property items with extra data allowing easier
+// definition of separate get, set, and support handlers dispatched through
+// SimpleAudioSamplePropertyDispatch.
+typedef struct
+{
+ PCPROPERTY_ITEM PropertyItem; // Standard PCPROPERTY_ITEM
+ ULONG MinProperty; // Minimum size of the property instance data
+ ULONG MinData; // Minimum size of the property value
+ PCPFNPROPERTY_HANDLER GetHandler; // Property get handler (NULL if GET not supported)
+ PCPFNPROPERTY_HANDLER SetHandler; // Property set handler (NULL if SET not supported)
+ PCPFNPROPERTY_HANDLER SupportHandler; // Property support handler (NULL for common handler)
+ VOID *ContextData; // Optional context information for the handler, NULL for unused
+ ULONG ContextDataSize; // Size of the data held at ContextData, 0 for unused
+} SIMPLEAUDIOSAMPLE_PROPERTY_ITEM;
+
+// The following macros facilitate adding property handlers to a class, allowing
+// easier declaration and definition of a "thunk" routine that directly handles
+// the property request and calls into a class instance method. Note that as
+// written, the thunk routine assumes PAGED_CODE.
+#define DECLARE_CLASSPROPERTYHANDLER(theClass, theMethod) \
+NTSTATUS theClass##_##theMethod \
+( \
+ _In_ PPCPROPERTY_REQUEST PropertyRequest \
+);
+
+#define DECLARE_PROPERTYHANDLER(theMethod) \
+NTSTATUS theMethod \
+( \
+ _In_ PPCPROPERTY_REQUEST PropertyRequest \
+);
+
+#define DEFINE_CLASSPROPERTYHANDLER(theClass, theMethod) \
+NTSTATUS theClass##_##theMethod \
+( \
+ _In_ PPCPROPERTY_REQUEST PropertyRequest \
+) \
+{ \
+ NTSTATUS status; \
+ \
+ PAGED_CODE(); \
+ \
+ theClass* p = reinterpret_cast<theClass*>(PropertyRequest->MajorTarget); \
+ \
+ p->AddRef(); \
+ status = p->theMethod(PropertyRequest); \
+ p->Release(); \
+ \
+ return status; \
+} \
+NTSTATUS theClass::theMethod \
+( \
+ _In_ PPCPROPERTY_REQUEST PropertyRequest \
+)
+
+
+
+
+#endif // _SIMPLEAUDIOSAMPLE_KSHELPER_H_
diff --git a/audio/simpleaudiosample/Source/Inc/mintopo.h b/audio/simpleaudiosample/Source/Inc/mintopo.h
new file mode 100644
index 00000000..5e7fe466
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Inc/mintopo.h
@@ -0,0 +1,81 @@
+
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ minitopo.h
+
+Abstract:
+
+ Declaration of topology miniport.
+--*/
+
+#ifndef _SIMPLEAUDIOSAMPLE_MINTOPO_H_
+#define _SIMPLEAUDIOSAMPLE_MINTOPO_H_
+
+#include "basetopo.h"
+
+//=============================================================================
+// Classes
+//=============================================================================
+
+///////////////////////////////////////////////////////////////////////////////
+// CMiniportTopology
+//
+
+class CMiniportTopology :
+ public CMiniportTopologySimpleAudioSample,
+ public IMiniportTopology,
+ public CUnknown
+{
+ private:
+ eDeviceType m_DeviceType;
+
+ union {
+ PVOID m_DeviceContext;
+ };
+
+public:
+ DECLARE_STD_UNKNOWN();
+ CMiniportTopology
+ (
+ _In_opt_ PUNKNOWN UnknownOuter,
+ _In_ PCFILTER_DESCRIPTOR *FilterDesc,
+ _In_ USHORT DeviceMaxChannels,
+ _In_ eDeviceType DeviceType,
+ _In_opt_ PVOID DeviceContext
+ )
+ : CUnknown(UnknownOuter),
+ CMiniportTopologySimpleAudioSample(FilterDesc, DeviceMaxChannels),
+ m_DeviceType(DeviceType),
+ m_DeviceContext(DeviceContext)
+ {
+ }
+
+ ~CMiniportTopology();
+
+ IMP_IMiniportTopology;
+
+ NTSTATUS PropertyHandlerJackDescription
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG cJackDescriptions,
+ _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION *JackDescriptions
+ );
+
+ NTSTATUS PropertyHandlerJackDescription2
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG cJackDescriptions,
+ _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION *JackDescriptions,
+ _In_ DWORD JackCapabilities
+ );
+
+ PVOID GetDeviceContext() { return m_DeviceContext; }
+};
+
+typedef CMiniportTopology *PCMiniportTopology;
+
+#endif // _SIMPLEAUDIOSAMPLE_MINTOPO_H_
diff --git a/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj b/audio/simpleaudiosample/Source/Main/Main.vcxproj
index 49ccee70..a68d0242 100644
--- a/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj
+++ b/audio/simpleaudiosample/Source/Main/Main.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?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|ARM64">
@@ -27,14 +27,14 @@
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
- <ProjectGuid>{FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}</ProjectGuid>
+ <ProjectGuid>{E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}</ProjectGuid>
<RootNamespace>$(MSBuildProjectName)</RootNamespace>
<KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
<SupportsPackaging>false</SupportsPackaging>
<RequiresPackageProject>true</RequiresPackageProject>
<Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
- <SampleGuid>{791E3C3E-132D-46C6-9624-C868C54139F0}</SampleGuid>
+ <SampleGuid>{2A9A946E-F017-4E0D-BF75-AD81E7E97D64}</SampleGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -129,6 +129,9 @@
<PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions>
<PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<Link>
@@ -151,6 +154,9 @@
<PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions>
<PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Link>
@@ -173,6 +179,9 @@
<PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions>
<PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<Link>
@@ -195,6 +204,9 @@
<PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions>
<PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Link>
@@ -217,6 +229,9 @@
<PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions>
<PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Link>
@@ -239,31 +254,37 @@
<PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions>
<PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <TargetName>PhoneAudioSample</TargetName>
+ <TargetName>SimpleAudioSample</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
- <TargetName>PhoneAudioSample</TargetName>
+ <TargetName>SimpleAudioSample</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <TargetName>PhoneAudioSample</TargetName>
+ <TargetName>SimpleAudioSample</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
- <TargetName>PhoneAudioSample</TargetName>
+ <TargetName>SimpleAudioSample</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <TargetName>PhoneAudioSample</TargetName>
+ <TargetName>SimpleAudioSample</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <TargetName>PhoneAudioSample</TargetName>
+ <TargetName>SimpleAudioSample</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Link>
- <AdditionalDependencies>%(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib</AdditionalDependencies>
+ <AdditionalDependencies>%(AdditionalDependencies);.\..\Utilities\$(IntDir)\Utilities.lib</AdditionalDependencies>
+ </Link>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);.\..\Filters\$(IntDir)\Filters.lib</AdditionalDependencies>
</Link>
<ClCompile>
- <!--
+ <!--
Use one of the following pre-processor defines to select the right power management:
- _USE_IPortClsRuntimePower
- _USE_SingleComponentMultiFxStates
@@ -271,137 +292,175 @@
value set via the INF. The name of the registry value is SingleComponentMultiFxStates.
see INF file for more info.
-->
- <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
<Midl>
- <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
</Midl>
<ResourceCompile>
- <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<Link>
- <AdditionalDependencies>%(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib</AdditionalDependencies>
+ <AdditionalDependencies>%(AdditionalDependencies);.\..\Utilities\$(IntDir)\Utilities.lib</AdditionalDependencies>
+ </Link>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);.\..\Filters\$(IntDir)\Filters.lib</AdditionalDependencies>
</Link>
<ClCompile>
- <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
<ExceptionHandling>
</ExceptionHandling>
- <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Midl>
- <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
</Midl>
<ResourceCompile>
- <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Link>
- <AdditionalDependencies>%(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib</AdditionalDependencies>
+ <AdditionalDependencies>%(AdditionalDependencies);.\..\Utilities\$(IntDir)\Utilities.lib</AdditionalDependencies>
+ </Link>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);.\..\Filters\$(IntDir)\Filters.lib</AdditionalDependencies>
</Link>
<ClCompile>
- <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
<Midl>
- <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
</Midl>
<ResourceCompile>
- <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<Link>
- <AdditionalDependencies>%(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib</AdditionalDependencies>
+ <AdditionalDependencies>%(AdditionalDependencies);.\..\Utilities\$(IntDir)\Utilities.lib</AdditionalDependencies>
+ </Link>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);.\..\Filters\$(IntDir)\Filters.lib</AdditionalDependencies>
</Link>
<ClCompile>
- <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
<ExceptionHandling>
</ExceptionHandling>
- <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Midl>
- <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
</Midl>
<ResourceCompile>
- <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Link>
- <AdditionalDependencies>%(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib</AdditionalDependencies>
+ <AdditionalDependencies>%(AdditionalDependencies);.\..\Utilities\$(IntDir)\Utilities.lib</AdditionalDependencies>
+ </Link>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);.\..\Filters\$(IntDir)\Filters.lib</AdditionalDependencies>
</Link>
<ClCompile>
- <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
<Midl>
- <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
</Midl>
<ResourceCompile>
- <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Link>
- <AdditionalDependencies>%(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib</AdditionalDependencies>
+ <AdditionalDependencies>%(AdditionalDependencies);.\..\Utilities\$(IntDir)\Utilities.lib</AdditionalDependencies>
+ </Link>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);.\..\Filters\$(IntDir)\Filters.lib</AdditionalDependencies>
</Link>
<ClCompile>
- <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
<ExceptionHandling>
</ExceptionHandling>
- <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Midl>
- <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
</Midl>
<ResourceCompile>
- <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Utilities</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Filters</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
- <ClCompile Include="..\adapter.cpp" />
- <ClCompile Include="..\basetopo.cpp" />
- <ClCompile Include="..\BthhfpDevice.cpp" />
- <ClCompile Include="..\usbhsdevice.cpp" />
- <ClCompile Include="..\common.cpp" />
- <ClCompile Include="..\hw.cpp" />
- <ClCompile Include="..\kshelper.cpp" />
- <ClCompile Include="..\savedata.cpp" />
- <ClCompile Include="..\tonegenerator.cpp" />
- <ClCompile Include="cellulartopo.cpp" />
- <ClCompile Include="cellularwave.cpp" />
- <ClCompile Include="fmtopo.cpp" />
- <ClCompile Include="fmwave.cpp" />
- <ClCompile Include="handsetmictopo.cpp" />
- <ClCompile Include="handsetspeakertopo.cpp" />
- <ClCompile Include="michstopo.cpp" />
- <ClCompile Include="speakerhstopo.cpp" />
- <ResourceCompile Include="PhoneAudioSample.rc" />
+ <ClCompile Include="adapter.cpp" />
+ <ClCompile Include="basetopo.cpp" />
+ <ClCompile Include="common.cpp" />
+ <ClCompile Include="mintopo.cpp" />
+ <ClCompile Include="minwavert.cpp" />
+ <ClCompile Include="minwavertstream.cpp" />
+ <ClCompile Include="newdelete.cpp" />
+ <ResourceCompile Include="SimpleAudioSample.rc" />
</ItemGroup>
<ItemGroup>
<Inf Exclude="@(Inx)" Include="*.inx" />
diff --git a/audio/simpleaudiosample/Source/Main/Main.vcxproj.Filters b/audio/simpleaudiosample/Source/Main/Main.vcxproj.Filters
new file mode 100644
index 00000000..0669f019
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Main/Main.vcxproj.Filters
@@ -0,0 +1,44 @@
+<?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>{7FE326AE-6214-4FE0-A27B-F229A098BDBC}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{64C16D2B-849C-4264-A615-18A8E8AC9505}</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>{46FAF4E8-F18C-4797-9CFA-2F3473BCB316}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{EE8F0A00-C1F0-4CB4-80E3-5FCC378E0BF4}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\*.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="*.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="SimpleAudioSample.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Include="*.inx">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
+</Project>
diff --git a/audio/simpleaudiosample/Source/Main/NewDelete.cpp b/audio/simpleaudiosample/Source/Main/NewDelete.cpp
new file mode 100644
index 00000000..8ef3797d
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Main/NewDelete.cpp
@@ -0,0 +1,141 @@
+/*****************************************************************************
+* NewDelete.cpp - CPP placement new and delete operators implementation
+*****************************************************************************
+* Copyright (c) Microsoft Corporation All Rights Reserved
+*
+* Module Name:
+*
+* NewDelete.cpp
+*
+* Abstract:
+*
+* Definition of placement new and delete operators.
+*
+*/
+
+#ifdef _NEW_DELETE_OPERATORS_
+#ifdef __cplusplus
+extern "C" {
+#include <wdm.h>
+}
+#else
+#include <wdm.h>
+#endif
+
+#include "newDelete.h"
+#include "definitions.h"
+
+#pragma code_seg()
+/*****************************************************************************
+* Functions
+*/
+
+/*****************************************************************************
+* ::new()
+*****************************************************************************
+* New function for creating objects with a specified allocation tag.
+*/
+PVOID operator new
+(
+ size_t iSize,
+ POOL_FLAGS poolFlags,
+ ULONG tag
+)
+{
+ PVOID result = ExAllocatePool2(poolFlags, iSize, tag);
+
+ return result;
+}
+
+
+/*****************************************************************************
+* ::new()
+*****************************************************************************
+* New function for creating objects with a specified allocation tag.
+*/
+PVOID operator new
+(
+ size_t iSize,
+ POOL_FLAGS poolFlags
+)
+{
+ PVOID result = ExAllocatePool2(poolFlags, iSize, SIMPLEAUDIOSAMPLE_POOLTAG);
+
+ return result;
+}
+
+
+/*****************************************************************************
+* ::delete()
+*****************************************************************************
+* Delete with tag function.
+*/
+void __cdecl operator delete
+(
+ PVOID pVoid,
+ ULONG tag
+)
+{
+ if (pVoid)
+ {
+ ExFreePoolWithTag(pVoid, tag);
+ }
+}
+
+
+/*****************************************************************************
+* ::delete()
+*****************************************************************************
+* Sized Delete function.
+*/
+void __cdecl operator delete
+(
+ _Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid,
+ _In_ size_t cbSize
+)
+{
+ UNREFERENCED_PARAMETER(cbSize);
+
+ if (pVoid)
+ {
+ ExFreePoolWithTag(pVoid, SIMPLEAUDIOSAMPLE_POOLTAG);
+ }
+}
+
+
+/*****************************************************************************
+* ::delete()
+*****************************************************************************
+* Sized Array Delete function.
+*/
+void __cdecl operator delete[]
+(
+ _Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid,
+ _In_ size_t cbSize
+)
+{
+ UNREFERENCED_PARAMETER(cbSize);
+
+ if (pVoid)
+ {
+ ExFreePoolWithTag(pVoid, SIMPLEAUDIOSAMPLE_POOLTAG);
+ }
+}
+
+
+/*****************************************************************************
+* ::delete()
+*****************************************************************************
+* Array Delete function.
+*/
+void __cdecl operator delete[]
+(
+ _Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid
+)
+{
+ if (pVoid)
+ {
+ ExFreePoolWithTag(pVoid, SIMPLEAUDIOSAMPLE_POOLTAG);
+ }
+}
+#endif//_NEW_DELETE_OPERATORS_
diff --git a/audio/simpleaudiosample/Source/Main/SimpleAudioSample.inx b/audio/simpleaudiosample/Source/Main/SimpleAudioSample.inx
new file mode 100644
index 00000000..a63bb0ba
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Main/SimpleAudioSample.inx
Binary files differ
diff --git a/audio/sysvad/PhoneAudioSample/PhoneAudioSample.rc b/audio/simpleaudiosample/Source/Main/SimpleAudioSample.rc
index b81a3c58..7fbb4893 100644
--- a/audio/sysvad/PhoneAudioSample/PhoneAudioSample.rc
+++ b/audio/simpleaudiosample/Source/Main/SimpleAudioSample.rc
@@ -4,11 +4,10 @@ Copyright (c) Microsoft Corporation All Rights Reserved
Module Name:
- PhoneAudioSample.rc
+ SimpleAudioSample.rc
Abstract:
-
--*/
#include <windows.h>
@@ -17,9 +16,9 @@ Abstract:
#define VER_FILETYPE VFT_DRV
#define VER_FILESUBTYPE VFT2_DRV_SOUND
-#define VER_FILEDESCRIPTION_STR "Microsoft Virtual Audio Phone Sample Driver"
-#define VER_INTERNALNAME_STR "PhoneAudioSample.sys"
-#define VER_ORIGINALFILENAME_STR "PhoneAudioSample.sys"
+#define VER_FILEDESCRIPTION_STR "Microsoft Virtual Simple Audio Sample Driver"
+#define VER_INTERNALNAME_STR "SimpleAudioSample.sys"
+#define VER_ORIGINALFILENAME_STR "SimpleAudioSample.sys"
#define VER_LEGALCOPYRIGHT_YEARS "2013"
#define VER_LEGALCOPYRIGHT_STR "Copyright (C) Microsoft Corp." VER_LEGALCOPYRIGHT_YEARS
@@ -27,4 +26,3 @@ Abstract:
#include "common.ver"
-
diff --git a/audio/simpleaudiosample/Source/Main/adapter.cpp b/audio/simpleaudiosample/Source/Main/adapter.cpp
new file mode 100644
index 00000000..105f7fde
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Main/adapter.cpp
@@ -0,0 +1,844 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ adapter.cpp
+
+Abstract:
+
+ Setup and miniport installation. No resources are used by simple audio sample.
+ This sample is to demonstrate how to develop a full featured audio miniport driver.
+--*/
+
+#pragma warning (disable : 4127)
+
+//
+// All the GUIDS for all the miniports end up in this object.
+//
+#define PUT_GUIDS_HERE
+
+#include "definitions.h"
+#include "endpoints.h"
+#include "minipairs.h"
+
+typedef void (*fnPcDriverUnload) (PDRIVER_OBJECT);
+fnPcDriverUnload gPCDriverUnloadRoutine = NULL;
+extern "C" DRIVER_UNLOAD DriverUnload;
+
+//-----------------------------------------------------------------------------
+// Referenced forward.
+//-----------------------------------------------------------------------------
+
+DRIVER_ADD_DEVICE AddDevice;
+
+NTSTATUS
+StartDevice
+(
+ _In_ PDEVICE_OBJECT,
+ _In_ PIRP,
+ _In_ PRESOURCELIST
+);
+
+_Dispatch_type_(IRP_MJ_PNP)
+DRIVER_DISPATCH PnpHandler;
+
+//
+// Rendering streams are saved to a file by default. Use the registry value
+// DoNotCreateDataFiles (DWORD) > 0 to override this default.
+//
+DWORD g_DoNotCreateDataFiles = 0; // default is off.
+DWORD g_DisableToneGenerator = 0; // default is to generate tones.
+UNICODE_STRING g_RegistryPath; // This is used to store the registry settings path for the driver
+
+//-----------------------------------------------------------------------------
+// Functions
+//-----------------------------------------------------------------------------
+
+#pragma code_seg("PAGE")
+void ReleaseRegistryStringBuffer()
+{
+ if (g_RegistryPath.Buffer != NULL)
+ {
+ ExFreePool(g_RegistryPath.Buffer);
+ g_RegistryPath.Buffer = NULL;
+ g_RegistryPath.Length = 0;
+ g_RegistryPath.MaximumLength = 0;
+ }
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+extern "C"
+void DriverUnload
+(
+ _In_ PDRIVER_OBJECT DriverObject
+)
+/*++
+
+Routine Description:
+
+ Our driver unload routine. This just frees the WDF driver object.
+
+Arguments:
+
+ DriverObject - pointer to the driver object
+
+Environment:
+
+ PASSIVE_LEVEL
+
+--*/
+{
+ PAGED_CODE();
+
+ DPF(D_TERSE, ("[DriverUnload]"));
+
+ ReleaseRegistryStringBuffer();
+
+ if (DriverObject == NULL)
+ {
+ goto Done;
+ }
+
+ //
+ // Invoke first the port unload.
+ //
+ if (gPCDriverUnloadRoutine != NULL)
+ {
+ gPCDriverUnloadRoutine(DriverObject);
+ }
+
+ //
+ // Unload WDF driver object.
+ //
+ if (WdfGetDriver() != NULL)
+ {
+ WdfDriverMiniportUnload(WdfGetDriver());
+ }
+Done:
+ return;
+}
+
+//=============================================================================
+#pragma code_seg("INIT")
+__drv_requiresIRQL(PASSIVE_LEVEL)
+NTSTATUS
+CopyRegistrySettingsPath(
+ _In_ PUNICODE_STRING RegistryPath
+)
+/*++
+
+Routine Description:
+
+Copies the following registry path to a global variable.
+
+\REGISTRY\MACHINE\SYSTEM\ControlSetxxx\Services\<driver>\Parameters
+
+Arguments:
+
+RegistryPath - Registry path passed to DriverEntry
+
+Returns:
+
+NTSTATUS - SUCCESS if able to configure the framework
+
+--*/
+
+{
+ // Initializing the unicode string, so that if it is not allocated it will not be deallocated too.
+ RtlInitUnicodeString(&g_RegistryPath, NULL);
+
+ g_RegistryPath.MaximumLength = RegistryPath->Length + sizeof(WCHAR);
+
+ g_RegistryPath.Buffer = (PWCH)ExAllocatePool2(POOL_FLAG_PAGED, g_RegistryPath.MaximumLength, MINADAPTER_POOLTAG);
+
+ if (g_RegistryPath.Buffer == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlAppendUnicodeToString(&g_RegistryPath, RegistryPath->Buffer);
+
+ return STATUS_SUCCESS;
+}
+
+//=============================================================================
+#pragma code_seg("INIT")
+__drv_requiresIRQL(PASSIVE_LEVEL)
+NTSTATUS
+GetRegistrySettings(
+ _In_ PUNICODE_STRING RegistryPath
+ )
+/*++
+
+Routine Description:
+
+ Initialize Driver Framework settings from the driver
+ specific registry settings under
+
+ \REGISTRY\MACHINE\SYSTEM\ControlSetxxx\Services\<driver>\Parameters
+
+Arguments:
+
+ RegistryPath - Registry path passed to DriverEntry
+
+Returns:
+
+ NTSTATUS - SUCCESS if able to configure the framework
+
+--*/
+
+{
+ NTSTATUS ntStatus;
+ UNICODE_STRING parametersPath;
+ RTL_QUERY_REGISTRY_TABLE paramTable[] = {
+ // QueryRoutine Flags Name EntryContext DefaultType DefaultData DefaultLength
+ { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"DoNotCreateDataFiles", &g_DoNotCreateDataFiles, (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD, &g_DoNotCreateDataFiles, sizeof(ULONG)},
+ { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"DisableToneGenerator", &g_DisableToneGenerator, (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD, &g_DisableToneGenerator, sizeof(ULONG)},
+ { NULL, 0, NULL, NULL, 0, NULL, 0}
+ };
+
+ DPF(D_TERSE, ("[GetRegistrySettings]"));
+
+ PAGED_CODE();
+
+ RtlInitUnicodeString(&parametersPath, NULL);
+
+ parametersPath.MaximumLength =
+ RegistryPath->Length + sizeof(L"\\Parameters") + sizeof(WCHAR);
+
+ parametersPath.Buffer = (PWCH) ExAllocatePool2(POOL_FLAG_PAGED, parametersPath.MaximumLength, MINADAPTER_POOLTAG);
+ if (parametersPath.Buffer == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlAppendUnicodeToString(&parametersPath, RegistryPath->Buffer);
+ RtlAppendUnicodeToString(&parametersPath, L"\\Parameters");
+
+ ntStatus = RtlQueryRegistryValues(
+ RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
+ parametersPath.Buffer,
+ &paramTable[0],
+ NULL,
+ NULL
+ );
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ DPF(D_VERBOSE, ("RtlQueryRegistryValues failed, using default values, 0x%x", ntStatus));
+ //
+ // Don't return error because we will operate with default values.
+ //
+ }
+
+ //
+ // Dump settings.
+ //
+ DPF(D_VERBOSE, ("DoNotCreateDataFiles: %u", g_DoNotCreateDataFiles));
+ DPF(D_VERBOSE, ("DisableToneGenerator: %u", g_DisableToneGenerator));
+
+ //
+ // Cleanup.
+ //
+ ExFreePool(parametersPath.Buffer);
+
+ return STATUS_SUCCESS;
+}
+
+#pragma code_seg("INIT")
+extern "C" DRIVER_INITIALIZE DriverEntry;
+extern "C" NTSTATUS
+DriverEntry
+(
+ _In_ PDRIVER_OBJECT DriverObject,
+ _In_ PUNICODE_STRING RegistryPathName
+)
+{
+/*++
+
+Routine Description:
+
+ Installable driver initialization entry point.
+ This entry point is called directly by the I/O system.
+
+ All audio adapter drivers can use this code without change.
+
+Arguments:
+
+ DriverObject - pointer to the driver object
+
+ RegistryPath - pointer to a unicode string representing the path,
+ to driver-specific key in the registry.
+
+Return Value:
+
+ STATUS_SUCCESS if successful,
+ STATUS_UNSUCCESSFUL otherwise.
+
+--*/
+ NTSTATUS ntStatus;
+ WDF_DRIVER_CONFIG config;
+
+ DPF(D_TERSE, ("[DriverEntry]"));
+
+ // Copy registry Path name in a global variable to be used by modules inside driver.
+ // !! NOTE !! Inside this function we are initializing the registrypath, so we MUST NOT add any failing calls
+ // before the following call.
+ ntStatus = CopyRegistrySettingsPath(RegistryPathName);
+ IF_FAILED_ACTION_JUMP(
+ ntStatus,
+ DPF(D_ERROR, ("Registry path copy error 0x%x", ntStatus)),
+ Done);
+
+ //
+ // Get registry configuration.
+ //
+ ntStatus = GetRegistrySettings(RegistryPathName);
+ IF_FAILED_ACTION_JUMP(
+ ntStatus,
+ DPF(D_ERROR, ("Registry Configuration error 0x%x", ntStatus)),
+ Done);
+
+ WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK);
+ //
+ // Set WdfDriverInitNoDispatchOverride flag to tell the framework
+ // not to provide dispatch routines for the driver. In other words,
+ // the framework must not intercept IRPs that the I/O manager has
+ // directed to the driver. In this case, they will be handled by Audio
+ // port driver.
+ //
+ config.DriverInitFlags |= WdfDriverInitNoDispatchOverride;
+ config.DriverPoolTag = MINADAPTER_POOLTAG;
+
+ ntStatus = WdfDriverCreate(DriverObject,
+ RegistryPathName,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &config,
+ WDF_NO_HANDLE);
+ IF_FAILED_ACTION_JUMP(
+ ntStatus,
+ DPF(D_ERROR, ("WdfDriverCreate failed, 0x%x", ntStatus)),
+ Done);
+
+ //
+ // Tell the class driver to initialize the driver.
+ //
+ ntStatus = PcInitializeAdapterDriver(DriverObject,
+ RegistryPathName,
+ (PDRIVER_ADD_DEVICE)AddDevice);
+ IF_FAILED_ACTION_JUMP(
+ ntStatus,
+ DPF(D_ERROR, ("PcInitializeAdapterDriver failed, 0x%x", ntStatus)),
+ Done);
+
+ //
+ // To intercept stop/remove/surprise-remove.
+ //
+ DriverObject->MajorFunction[IRP_MJ_PNP] = PnpHandler;
+
+ //
+ // Hook the port class unload function
+ //
+ gPCDriverUnloadRoutine = DriverObject->DriverUnload;
+ DriverObject->DriverUnload = DriverUnload;
+
+ //
+ // All done.
+ //
+ ntStatus = STATUS_SUCCESS;
+
+Done:
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ if (WdfGetDriver() != NULL)
+ {
+ WdfDriverMiniportUnload(WdfGetDriver());
+ }
+
+ ReleaseRegistryStringBuffer();
+ }
+
+ return ntStatus;
+} // DriverEntry
+
+#pragma code_seg()
+// disable prefast warning 28152 because
+// DO_DEVICE_INITIALIZING is cleared in PcAddAdapterDevice
+#pragma warning(disable:28152)
+#pragma code_seg("PAGE")
+//=============================================================================
+NTSTATUS AddDevice
+(
+ _In_ PDRIVER_OBJECT DriverObject,
+ _In_ PDEVICE_OBJECT PhysicalDeviceObject
+)
+/*++
+
+Routine Description:
+
+ The Plug & Play subsystem is handing us a brand new PDO, for which we
+ (by means of INF registration) have been asked to provide a driver.
+
+ We need to determine if we need to be in the driver stack for the device.
+ Create a function device object to attach to the stack
+ Initialize that device object
+ Return status success.
+
+ All audio adapter drivers can use this code without change.
+
+Arguments:
+
+ DriverObject - pointer to a driver object
+
+ PhysicalDeviceObject - pointer to a device object created by the
+ underlying bus driver.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ NTSTATUS ntStatus;
+ ULONG maxObjects;
+
+ DPF(D_TERSE, ("[AddDevice]"));
+
+ maxObjects = g_MaxMiniports;
+
+ // Tell the class driver to add the device.
+ //
+ ntStatus =
+ PcAddAdapterDevice
+ (
+ DriverObject,
+ PhysicalDeviceObject,
+ PCPFNSTARTDEVICE(StartDevice),
+ maxObjects,
+ 0
+ );
+
+ return ntStatus;
+} // AddDevice
+
+#pragma code_seg()
+NTSTATUS
+_IRQL_requires_max_(DISPATCH_LEVEL)
+PowerControlCallback
+(
+ _In_ LPCGUID PowerControlCode,
+ _In_opt_ PVOID InBuffer,
+ _In_ SIZE_T InBufferSize,
+ _Out_writes_bytes_to_(OutBufferSize, *BytesReturned) PVOID OutBuffer,
+ _In_ SIZE_T OutBufferSize,
+ _Out_opt_ PSIZE_T BytesReturned,
+ _In_opt_ PVOID Context
+)
+{
+ UNREFERENCED_PARAMETER(PowerControlCode);
+ UNREFERENCED_PARAMETER(InBuffer);
+ UNREFERENCED_PARAMETER(InBufferSize);
+ UNREFERENCED_PARAMETER(OutBuffer);
+ UNREFERENCED_PARAMETER(OutBufferSize);
+ UNREFERENCED_PARAMETER(BytesReturned);
+ UNREFERENCED_PARAMETER(Context);
+
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+#pragma code_seg("PAGE")
+NTSTATUS
+InstallEndpointRenderFilters(
+ _In_ PDEVICE_OBJECT _pDeviceObject,
+ _In_ PIRP _pIrp,
+ _In_ PADAPTERCOMMON _pAdapterCommon,
+ _In_ PENDPOINT_MINIPAIR _pAeMiniports
+ )
+{
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ PUNKNOWN unknownTopology = NULL;
+ PUNKNOWN unknownWave = NULL;
+ PPORTCLSETWHELPER pPortClsEtwHelper = NULL;
+#ifdef _USE_IPortClsRuntimePower
+ PPORTCLSRUNTIMEPOWER pPortClsRuntimePower = NULL;
+#endif // _USE_IPortClsRuntimePower
+ PPORTCLSStreamResourceManager pPortClsResMgr = NULL;
+ PPORTCLSStreamResourceManager2 pPortClsResMgr2 = NULL;
+
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(_pDeviceObject);
+
+ ntStatus = _pAdapterCommon->InstallEndpointFilters(
+ _pIrp,
+ _pAeMiniports,
+ NULL,
+ &unknownTopology,
+ &unknownWave,
+ NULL, NULL);
+
+ if (unknownWave) // IID_IPortClsEtwHelper and IID_IPortClsRuntimePower interfaces are only exposed on the WaveRT port.
+ {
+ ntStatus = unknownWave->QueryInterface (IID_IPortClsEtwHelper, (PVOID *)&pPortClsEtwHelper);
+ if (NT_SUCCESS(ntStatus))
+ {
+ _pAdapterCommon->SetEtwHelper(pPortClsEtwHelper);
+ ASSERT(pPortClsEtwHelper != NULL);
+ pPortClsEtwHelper->Release();
+ }
+
+#ifdef _USE_IPortClsRuntimePower
+ // Let's get the runtime power interface on PortCls.
+ ntStatus = unknownWave->QueryInterface(IID_IPortClsRuntimePower, (PVOID *)&pPortClsRuntimePower);
+ if (NT_SUCCESS(ntStatus))
+ {
+ // This interface would typically be stashed away for later use. Instead,
+ // let's just send an empty control with GUID_NULL.
+ NTSTATUS ntStatusTest =
+ pPortClsRuntimePower->SendPowerControl
+ (
+ _pDeviceObject,
+ &GUID_NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL
+ );
+
+ if (NT_SUCCESS(ntStatusTest) || STATUS_NOT_IMPLEMENTED == ntStatusTest || STATUS_NOT_SUPPORTED == ntStatusTest)
+ {
+ ntStatus = pPortClsRuntimePower->RegisterPowerControlCallback(_pDeviceObject, &PowerControlCallback, NULL);
+ if (NT_SUCCESS(ntStatus))
+ {
+ ntStatus = pPortClsRuntimePower->UnregisterPowerControlCallback(_pDeviceObject);
+ }
+ }
+ else
+ {
+ ntStatus = ntStatusTest;
+ }
+
+ pPortClsRuntimePower->Release();
+ }
+#endif // _USE_IPortClsRuntimePower
+
+ //
+ // Test: add and remove current thread as streaming audio resource.
+ // In a real driver you should only add interrupts and driver-owned threads
+ // (i.e., do NOT add the current thread as streaming resource).
+ //
+ // testing IPortClsStreamResourceManager:
+ ntStatus = unknownWave->QueryInterface(IID_IPortClsStreamResourceManager, (PVOID *)&pPortClsResMgr);
+ if (NT_SUCCESS(ntStatus))
+ {
+ PCSTREAMRESOURCE_DESCRIPTOR res;
+ PCSTREAMRESOURCE hRes = NULL;
+ PDEVICE_OBJECT pdo = NULL;
+
+ PcGetPhysicalDeviceObject(_pDeviceObject, &pdo);
+ PCSTREAMRESOURCE_DESCRIPTOR_INIT(&res);
+ res.Pdo = pdo;
+ res.Type = ePcStreamResourceThread;
+ res.Resource.Thread = PsGetCurrentThread();
+
+ NTSTATUS ntStatusTest = pPortClsResMgr->AddStreamResource(NULL, &res, &hRes);
+ if (NT_SUCCESS(ntStatusTest))
+ {
+ pPortClsResMgr->RemoveStreamResource(hRes);
+ hRes = NULL;
+ }
+
+ pPortClsResMgr->Release();
+ pPortClsResMgr = NULL;
+ }
+
+ // testing IPortClsStreamResourceManager2:
+ ntStatus = unknownWave->QueryInterface(IID_IPortClsStreamResourceManager2, (PVOID *)&pPortClsResMgr2);
+ if (NT_SUCCESS(ntStatus))
+ {
+ PCSTREAMRESOURCE_DESCRIPTOR res;
+ PCSTREAMRESOURCE hRes = NULL;
+ PDEVICE_OBJECT pdo = NULL;
+
+ PcGetPhysicalDeviceObject(_pDeviceObject, &pdo);
+ PCSTREAMRESOURCE_DESCRIPTOR_INIT(&res);
+ res.Pdo = pdo;
+ res.Type = ePcStreamResourceThread;
+ res.Resource.Thread = PsGetCurrentThread();
+
+ NTSTATUS ntStatusTest = pPortClsResMgr2->AddStreamResource2(pdo, NULL, &res, &hRes);
+ if (NT_SUCCESS(ntStatusTest))
+ {
+ pPortClsResMgr2->RemoveStreamResource(hRes);
+ hRes = NULL;
+ }
+
+ pPortClsResMgr2->Release();
+ pPortClsResMgr2 = NULL;
+ }
+ }
+
+ SAFE_RELEASE(unknownTopology);
+ SAFE_RELEASE(unknownWave);
+
+ return ntStatus;
+}
+
+#pragma code_seg("PAGE")
+NTSTATUS
+InstallAllRenderFilters(
+ _In_ PDEVICE_OBJECT _pDeviceObject,
+ _In_ PIRP _pIrp,
+ _In_ PADAPTERCOMMON _pAdapterCommon
+ )
+{
+ NTSTATUS ntStatus;
+ PENDPOINT_MINIPAIR* ppAeMiniports = g_RenderEndpoints;
+
+ PAGED_CODE();
+
+ for(ULONG i = 0; i < g_cRenderEndpoints; ++i, ++ppAeMiniports)
+ {
+ ntStatus = InstallEndpointRenderFilters(_pDeviceObject, _pIrp, _pAdapterCommon, *ppAeMiniports);
+ IF_FAILED_JUMP(ntStatus, Exit);
+ }
+
+ ntStatus = STATUS_SUCCESS;
+
+Exit:
+ return ntStatus;
+}
+
+#pragma code_seg("PAGE")
+NTSTATUS
+InstallEndpointCaptureFilters(
+ _In_ PDEVICE_OBJECT _pDeviceObject,
+ _In_ PIRP _pIrp,
+ _In_ PADAPTERCOMMON _pAdapterCommon,
+ _In_ PENDPOINT_MINIPAIR _pAeMiniports
+)
+{
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(_pDeviceObject);
+
+ ntStatus = _pAdapterCommon->InstallEndpointFilters(
+ _pIrp,
+ _pAeMiniports,
+ NULL,
+ NULL,
+ NULL,
+ NULL, NULL);
+
+ return ntStatus;
+}
+
+#pragma code_seg("PAGE")
+NTSTATUS
+InstallAllCaptureFilters(
+ _In_ PDEVICE_OBJECT _pDeviceObject,
+ _In_ PIRP _pIrp,
+ _In_ PADAPTERCOMMON _pAdapterCommon
+)
+{
+ NTSTATUS ntStatus;
+ PENDPOINT_MINIPAIR* ppAeMiniports = g_CaptureEndpoints;
+
+ PAGED_CODE();
+
+ for (ULONG i = 0; i < g_cCaptureEndpoints; ++i, ++ppAeMiniports)
+ {
+ ntStatus = InstallEndpointCaptureFilters(_pDeviceObject, _pIrp, _pAdapterCommon, *ppAeMiniports);
+ IF_FAILED_JUMP(ntStatus, Exit);
+ }
+
+ ntStatus = STATUS_SUCCESS;
+
+Exit:
+ return ntStatus;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+StartDevice
+(
+ _In_ PDEVICE_OBJECT DeviceObject,
+ _In_ PIRP Irp,
+ _In_ PRESOURCELIST ResourceList
+)
+{
+/*++
+
+Routine Description:
+
+ This function is called by the operating system when the device is
+ started.
+ It is responsible for starting the miniports. This code is specific to
+ the adapter because it calls out miniports for functions that are specific
+ to the adapter.
+
+Arguments:
+
+ DeviceObject - pointer to the driver object
+
+ Irp - pointer to the irp
+
+ ResourceList - pointer to the resource list assigned by PnP manager
+
+Return Value:
+
+ NT status code.
+
+--*/
+ UNREFERENCED_PARAMETER(ResourceList);
+
+ PAGED_CODE();
+
+ ASSERT(DeviceObject);
+ ASSERT(Irp);
+ ASSERT(ResourceList);
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ PADAPTERCOMMON pAdapterCommon = NULL;
+ PUNKNOWN pUnknownCommon = NULL;
+ PortClassDeviceContext* pExtension = static_cast<PortClassDeviceContext*>(DeviceObject->DeviceExtension);
+
+ DPF_ENTER(("[StartDevice]"));
+
+ //
+ // create a new adapter common object
+ //
+ ntStatus = NewAdapterCommon(
+ &pUnknownCommon,
+ IID_IAdapterCommon,
+ NULL,
+ POOL_FLAG_NON_PAGED
+ );
+ IF_FAILED_JUMP(ntStatus, Exit);
+
+ ntStatus = pUnknownCommon->QueryInterface( IID_IAdapterCommon,(PVOID *) &pAdapterCommon);
+ IF_FAILED_JUMP(ntStatus, Exit);
+
+ ntStatus = pAdapterCommon->Init(DeviceObject);
+ IF_FAILED_JUMP(ntStatus, Exit);
+
+ //
+ // register with PortCls for power-management services
+ ntStatus = PcRegisterAdapterPowerManagement( PUNKNOWN(pAdapterCommon), DeviceObject);
+ IF_FAILED_JUMP(ntStatus, Exit);
+
+ //
+ // Install wave+topology filters for render devices
+ //
+ ntStatus = InstallAllRenderFilters(DeviceObject, Irp, pAdapterCommon);
+ IF_FAILED_JUMP(ntStatus, Exit);
+
+ //
+ // Install wave+topology filters for capture devices
+ //
+ ntStatus = InstallAllCaptureFilters(DeviceObject, Irp, pAdapterCommon);
+ IF_FAILED_JUMP(ntStatus, Exit);
+
+Exit:
+
+ //
+ // Stash the adapter common object in the device extension so
+ // we can access it for cleanup on stop/removal.
+ //
+ if (pAdapterCommon)
+ {
+ ASSERT(pExtension != NULL);
+ pExtension->m_pCommon = pAdapterCommon;
+ }
+
+ //
+ // Release the adapter IUnknown interface.
+ //
+ SAFE_RELEASE(pUnknownCommon);
+
+ return ntStatus;
+} // StartDevice
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+PnpHandler
+(
+ _In_ DEVICE_OBJECT *_DeviceObject,
+ _Inout_ IRP *_Irp
+)
+/*++
+
+Routine Description:
+
+ Handles PnP IRPs
+
+Arguments:
+
+ _DeviceObject - Functional Device object pointer.
+
+ _Irp - The Irp being passed
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
+ IO_STACK_LOCATION *stack;
+ PortClassDeviceContext *ext;
+
+ // Documented https://msdn.microsoft.com/en-us/library/windows/hardware/ff544039(v=vs.85).aspx
+ // This method will be called in IRQL PASSIVE_LEVEL
+#pragma warning(suppress: 28118)
+ PAGED_CODE();
+
+ ASSERT(_DeviceObject);
+ ASSERT(_Irp);
+
+ //
+ // Check for the REMOVE_DEVICE irp. If we're being unloaded,
+ // uninstantiate our devices and release the adapter common
+ // object.
+ //
+ stack = IoGetCurrentIrpStackLocation(_Irp);
+
+ switch (stack->MinorFunction)
+ {
+ case IRP_MN_REMOVE_DEVICE:
+ case IRP_MN_SURPRISE_REMOVAL:
+ case IRP_MN_STOP_DEVICE:
+ ext = static_cast<PortClassDeviceContext*>(_DeviceObject->DeviceExtension);
+
+ if (ext->m_pCommon != NULL)
+ {
+ ext->m_pCommon->Cleanup();
+
+ ext->m_pCommon->Release();
+ ext->m_pCommon = NULL;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ ntStatus = PcDispatchIrp(_DeviceObject, _Irp);
+
+ return ntStatus;
+}
+
+#pragma code_seg()
+
diff --git a/audio/simpleaudiosample/Source/Main/basetopo.cpp b/audio/simpleaudiosample/Source/Main/basetopo.cpp
new file mode 100644
index 00000000..b29a9bb1
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Main/basetopo.cpp
@@ -0,0 +1,688 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ basetopo.cpp
+
+Abstract:
+
+ Implementation of topology miniport. This the base class for
+ all simple audio sample drivers
+--*/
+
+//4127: conditional expression is constant
+#pragma warning (disable : 4127)
+
+#include "definitions.h"
+#include "basetopo.h"
+
+//=============================================================================
+#pragma code_seg("PAGE")
+CMiniportTopologySimpleAudioSample::CMiniportTopologySimpleAudioSample
+(
+ _In_ PCFILTER_DESCRIPTOR *FilterDesc,
+ _In_ USHORT DeviceMaxChannels
+)
+/*++
+
+Routine Description:
+
+ Topology miniport constructor
+
+Arguments:
+
+ FilterDesc -
+
+ DeviceMaxChannels -
+
+Return Value:
+
+ void
+
+--*/
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[%s]",__FUNCTION__));
+
+ m_AdapterCommon = NULL;
+
+ ASSERT(FilterDesc != NULL);
+ m_FilterDescriptor = FilterDesc;
+ m_PortEvents = NULL;
+
+ ASSERT(DeviceMaxChannels > 0);
+ m_DeviceMaxChannels = DeviceMaxChannels;
+} // CMiniportTopologySimpleAudioSample
+
+CMiniportTopologySimpleAudioSample::~CMiniportTopologySimpleAudioSample
+(
+ void
+)
+/*++
+
+Routine Description:
+
+ Topology miniport destructor
+
+Arguments:
+
+Return Value:
+
+ void
+
+--*/
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[%s]",__FUNCTION__));
+
+ SAFE_RELEASE(m_AdapterCommon);
+ SAFE_RELEASE(m_PortEvents);
+} // ~CMiniportTopologySimpleAudioSample
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportTopologySimpleAudioSample::DataRangeIntersection
+(
+ _In_ ULONG PinId,
+ _In_ PKSDATARANGE ClientDataRange,
+ _In_ PKSDATARANGE MyDataRange,
+ _In_ ULONG OutputBufferLength,
+ _Out_writes_bytes_to_opt_(OutputBufferLength, *ResultantFormatLength)
+ PVOID ResultantFormat OPTIONAL,
+ _Out_ PULONG ResultantFormatLength
+)
+/*++
+
+Routine Description:
+
+ The DataRangeIntersection function determines the highest
+ quality intersection of two data ranges. Topology miniport does nothing.
+
+Arguments:
+
+ PinId - Pin for which data intersection is being determined.
+
+ ClientDataRange - Pointer to KSDATARANGE structure which contains the data range
+ submitted by client in the data range intersection property
+ request
+
+ MyDataRange - Pin's data range to be compared with client's data range
+
+ OutputBufferLength - Size of the buffer pointed to by the resultant format
+ parameter
+
+ ResultantFormat - Pointer to value where the resultant format should be
+ returned
+
+ ResultantFormatLength - Actual length of the resultant format that is placed
+ at ResultantFormat. This should be less than or equal
+ to OutputBufferLength
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ UNREFERENCED_PARAMETER(PinId);
+ UNREFERENCED_PARAMETER(ClientDataRange);
+ UNREFERENCED_PARAMETER(MyDataRange);
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+ UNREFERENCED_PARAMETER(ResultantFormat);
+ UNREFERENCED_PARAMETER(ResultantFormatLength);
+
+ PAGED_CODE();
+
+ DPF_ENTER(("[%s]",__FUNCTION__));
+
+ return (STATUS_NOT_IMPLEMENTED);
+} // DataRangeIntersection
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportTopologySimpleAudioSample::GetDescription
+(
+ _Out_ PPCFILTER_DESCRIPTOR * OutFilterDescriptor
+)
+/*++
+
+Routine Description:
+
+ The GetDescription function gets a pointer to a filter description.
+ It provides a location to deposit a pointer in miniport's description
+ structure. This is the placeholder for the FromNode or ToNode fields in
+ connections which describe connections to the filter's pins
+
+Arguments:
+
+ OutFilterDescriptor - Pointer to the filter description.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(OutFilterDescriptor);
+
+ DPF_ENTER(("[%s]",__FUNCTION__));
+
+ *OutFilterDescriptor = m_FilterDescriptor;
+
+ return (STATUS_SUCCESS);
+} // GetDescription
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportTopologySimpleAudioSample::Init
+(
+ _In_ PUNKNOWN UnknownAdapter_,
+ _In_ PPORTTOPOLOGY Port_
+)
+/*++
+
+Routine Description:
+
+ Initializes the topology miniport.
+
+Arguments:
+
+ UnknownAdapter -
+
+ Port_ - Pointer to topology port
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(UnknownAdapter_);
+ ASSERT(Port_);
+
+ DPF_ENTER(("[CMiniportTopologySimpleAudioSample::Init]"));
+
+ NTSTATUS ntStatus;
+
+ ntStatus =
+ UnknownAdapter_->QueryInterface(
+ IID_IAdapterCommon,
+ (PVOID *) &m_AdapterCommon);
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ //
+ // Get the port event interface.
+ //
+ ntStatus = Port_->QueryInterface(
+ IID_IPortEvents,
+ (PVOID *)&m_PortEvents);
+ }
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ m_AdapterCommon->MixerReset();
+ }
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ // clean up AdapterCommon
+ SAFE_RELEASE(m_AdapterCommon);
+ SAFE_RELEASE(m_PortEvents);
+ }
+
+ return ntStatus;
+} // Init
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportTopologySimpleAudioSample::PropertyHandlerGeneric
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+/*++
+
+Routine Description:
+
+ Handles all properties for this miniport.
+
+Arguments:
+
+ PropertyRequest - property request structure
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+
+ switch (PropertyRequest->PropertyItem->Id)
+ {
+ case KSPROPERTY_AUDIO_VOLUMELEVEL:
+ ntStatus = PropertyHandler_Volume(
+ m_AdapterCommon,
+ PropertyRequest,
+ m_DeviceMaxChannels);
+ break;
+
+ case KSPROPERTY_AUDIO_MUTE:
+ ntStatus = PropertyHandler_Mute(
+ m_AdapterCommon,
+ PropertyRequest,
+ m_DeviceMaxChannels);
+ break;
+
+ case KSPROPERTY_AUDIO_PEAKMETER2:
+ ntStatus = PropertyHandler_PeakMeter2(
+ m_AdapterCommon,
+ PropertyRequest,
+ m_DeviceMaxChannels);
+ break;
+
+ case KSPROPERTY_AUDIO_CPU_RESOURCES:
+ ntStatus = PropertyHandler_CpuResources(PropertyRequest);
+ break;
+
+ case KSPROPERTY_AUDIO_MUX_SOURCE:
+ ntStatus = PropertyHandlerMuxSource(PropertyRequest);
+ break;
+
+ case KSPROPERTY_AUDIO_DEV_SPECIFIC:
+ ntStatus = PropertyHandlerDevSpecific(PropertyRequest);
+ break;
+
+ default:
+ DPF(D_TERSE, ("[PropertyHandlerGeneric: Invalid Device Request]"));
+ }
+
+ return ntStatus;
+} // PropertyHandlerGeneric
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportTopologySimpleAudioSample::PropertyHandlerMuxSource
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+/*++
+
+Routine Description:
+
+ PropertyHandler for KSPROPERTY_AUDIO_MUX_SOURCE.
+
+Arguments:
+
+ PropertyRequest - property request structure
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[%s]",__FUNCTION__));
+
+ NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+
+ //
+ // Validate node
+ // This property is only valid for WAVEIN_MUX node.
+ //
+ // TODO if (WAVEIN_MUX == PropertyRequest->Node)
+ {
+ if (PropertyRequest->ValueSize >= sizeof(ULONG))
+ {
+ PULONG pulMuxValue = PULONG(PropertyRequest->Value);
+
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ *pulMuxValue = m_AdapterCommon->MixerMuxRead();
+ PropertyRequest->ValueSize = sizeof(ULONG);
+ ntStatus = STATUS_SUCCESS;
+ }
+ else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
+ {
+ m_AdapterCommon->MixerMuxWrite(*pulMuxValue);
+ ntStatus = STATUS_SUCCESS;
+ }
+ else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ ntStatus =
+ PropertyHandler_BasicSupport
+ (
+ PropertyRequest,
+ KSPROPERTY_TYPE_ALL,
+ VT_I4
+ );
+ }
+ }
+ else
+ {
+ DPF(D_TERSE, ("[PropertyHandlerMuxSource - Invalid parameter]"));
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ return ntStatus;
+} // PropertyHandlerMuxSource
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportTopologySimpleAudioSample::PropertyHandlerDevSpecific(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+/*++
+
+Routine Description:
+
+ Property handler for KSPROPERTY_AUDIO_DEV_SPECIFIC
+
+Arguments:
+
+ PropertyRequest - property request structure
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[%s]",__FUNCTION__));
+
+ NTSTATUS ntStatus=STATUS_SUCCESS;
+
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ if( DEV_SPECIFIC_VT_BOOL == PropertyRequest->Node )
+ {
+ ntStatus = PropertyHandler_BasicSupport(PropertyRequest,KSPROPERTY_TYPE_ALL,VT_BOOL);
+ }
+ else
+ {
+ ULONG ExpectedSize = sizeof( KSPROPERTY_DESCRIPTION ) +
+ sizeof( KSPROPERTY_MEMBERSHEADER ) +
+ sizeof( KSPROPERTY_BOUNDS_LONG );
+ DWORD ulPropTypeSetId;
+
+ if( DEV_SPECIFIC_VT_I4 == PropertyRequest->Node )
+ {
+ ulPropTypeSetId = VT_I4;
+ }
+ else if ( DEV_SPECIFIC_VT_UI4 == PropertyRequest->Node )
+ {
+ ulPropTypeSetId = VT_UI4;
+ }
+ else
+ {
+ ulPropTypeSetId = VT_ILLEGAL;
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+
+ if( NT_SUCCESS(ntStatus))
+ {
+ if ( !PropertyRequest->ValueSize )
+ {
+ PropertyRequest->ValueSize = ExpectedSize;
+ ntStatus = STATUS_BUFFER_OVERFLOW;
+ }
+ else if (PropertyRequest->ValueSize >= sizeof(KSPROPERTY_DESCRIPTION))
+ {
+ // if return buffer can hold a KSPROPERTY_DESCRIPTION, return it
+ //
+ PKSPROPERTY_DESCRIPTION PropDesc = PKSPROPERTY_DESCRIPTION(PropertyRequest->Value);
+
+ PropDesc->AccessFlags = KSPROPERTY_TYPE_ALL;
+ PropDesc->DescriptionSize = ExpectedSize;
+ PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General;
+ PropDesc->PropTypeSet.Id = ulPropTypeSetId;
+ PropDesc->PropTypeSet.Flags = 0;
+ PropDesc->MembersListCount = 0;
+ PropDesc->Reserved = 0;
+
+ if ( PropertyRequest->ValueSize >= ExpectedSize )
+ {
+ // Extra information to return
+ PropDesc->MembersListCount = 1;
+
+ PKSPROPERTY_MEMBERSHEADER MembersHeader = ( PKSPROPERTY_MEMBERSHEADER )( PropDesc + 1);
+ MembersHeader->MembersFlags = KSPROPERTY_MEMBER_RANGES;
+ MembersHeader->MembersCount = 1;
+ MembersHeader->MembersSize = sizeof( KSPROPERTY_BOUNDS_LONG );
+ MembersHeader->Flags = 0;
+
+ PKSPROPERTY_BOUNDS_LONG PeakMeterBounds = (PKSPROPERTY_BOUNDS_LONG)( MembersHeader + 1);
+ if(VT_I4 == ulPropTypeSetId )
+ {
+ PeakMeterBounds->SignedMinimum = 0;
+ PeakMeterBounds->SignedMaximum = 0x7fffffff;
+ }
+ else
+ {
+ PeakMeterBounds->UnsignedMinimum = 0;
+ PeakMeterBounds->UnsignedMaximum = 0xffffffff;
+ }
+
+ // set the return value size
+ PropertyRequest->ValueSize = ExpectedSize;
+ }
+ else
+ {
+ // No extra information to return.
+ PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION);
+ }
+
+ ntStatus = STATUS_SUCCESS;
+ }
+ else if (PropertyRequest->ValueSize >= sizeof(ULONG))
+ {
+ // if return buffer can hold a ULONG, return the access flags
+ //
+ *(PULONG(PropertyRequest->Value)) = KSPROPERTY_TYPE_ALL;
+
+ PropertyRequest->ValueSize = sizeof(ULONG);
+ ntStatus = STATUS_SUCCESS;
+ }
+ else
+ {
+ PropertyRequest->ValueSize = 0;
+ ntStatus = STATUS_BUFFER_TOO_SMALL;
+ }
+ }
+ }
+ }
+ else
+ {
+ // switch on node id
+ switch( PropertyRequest->Node )
+ {
+ case DEV_SPECIFIC_VT_BOOL:
+ {
+ PBOOL pbDevSpecific;
+
+ ntStatus = ValidatePropertyParams(PropertyRequest, sizeof(BOOL), 0);
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ pbDevSpecific = PBOOL (PropertyRequest->Value);
+
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ *pbDevSpecific = m_AdapterCommon->bDevSpecificRead();
+ PropertyRequest->ValueSize = sizeof(BOOL);
+ }
+ else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
+ {
+ m_AdapterCommon->bDevSpecificWrite(*pbDevSpecific);
+ }
+ else
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+ }
+ }
+ break;
+ case DEV_SPECIFIC_VT_I4:
+ {
+ INT* piDevSpecific;
+
+ ntStatus = ValidatePropertyParams(PropertyRequest, sizeof(int), 0);
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ piDevSpecific = PINT (PropertyRequest->Value);
+
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ *piDevSpecific = m_AdapterCommon->iDevSpecificRead();
+ PropertyRequest->ValueSize = sizeof(int);
+ }
+ else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
+ {
+ m_AdapterCommon->iDevSpecificWrite(*piDevSpecific);
+ }
+ else
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+ }
+ }
+ break;
+ case DEV_SPECIFIC_VT_UI4:
+ {
+ UINT* puiDevSpecific;
+
+ ntStatus = ValidatePropertyParams(PropertyRequest, sizeof(UINT), 0);
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ puiDevSpecific = PUINT (PropertyRequest->Value);
+
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ *puiDevSpecific = m_AdapterCommon->uiDevSpecificRead();
+ PropertyRequest->ValueSize = sizeof(UINT);
+ }
+ else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
+ {
+ m_AdapterCommon->uiDevSpecificWrite(*puiDevSpecific);
+ }
+ else
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+ }
+ }
+ break;
+ default:
+ ntStatus = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+
+ if( !NT_SUCCESS(ntStatus))
+ {
+ DPF(D_TERSE, ("[%s - ntStatus=0x%08x]",__FUNCTION__,ntStatus));
+ }
+ }
+
+ return ntStatus;
+} // PropertyHandlerDevSpecific
+
+//=============================================================================
+#pragma code_seg("PAGE")
+VOID
+CMiniportTopologySimpleAudioSample::AddEventToEventList
+(
+ _In_ PKSEVENT_ENTRY EventEntry
+)
+/*++
+
+Routine Description:
+
+ The AddEventToEventList method adds an event to the port driver's event list
+
+Arguments:
+
+ EventEntry -
+
+--*/
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CMiniportTopology::AddEventToEventList]"));
+
+ ASSERT(m_PortEvents != NULL);
+
+ m_PortEvents->AddEventToEventList(EventEntry);
+}
+
+//=============================================================================
+#pragma code_seg()
+VOID
+CMiniportTopologySimpleAudioSample::GenerateEventList
+(
+ _In_opt_ GUID *Set,
+ _In_ ULONG EventId,
+ _In_ BOOL PinEvent,
+ _In_ ULONG PinId,
+ _In_ BOOL NodeEvent,
+ _In_ ULONG NodeId
+)
+/*++
+
+Routine Description:
+
+ The GenerateEventList method notifies clients through the port driver's list
+ of event entries that a particular event has occurred.
+
+Arguments:
+
+ Set -
+
+ EventId -
+
+ PinEvent -
+
+ PinId -
+
+ NodeEvent -
+
+ NodeId -
+
+--*/
+{
+ DPF_ENTER(("[CMiniportTopologySimpleAudioSample::GenerateEventList]"));
+
+ ASSERT(m_PortEvents != NULL);
+
+ m_PortEvents->GenerateEventList(
+ Set,
+ EventId,
+ PinEvent,
+ PinId,
+ NodeEvent,
+ NodeId);
+}
+
+#pragma code_seg()
diff --git a/audio/simpleaudiosample/Source/Main/common.cpp b/audio/simpleaudiosample/Source/Main/common.cpp
new file mode 100644
index 00000000..8843d3a4
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Main/common.cpp
@@ -0,0 +1,2772 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ common.cpp
+
+Abstract:
+
+ Implementation of the AdapterCommon class.
+--*/
+
+#pragma warning (disable : 4127)
+
+#include <initguid.h>
+#include "definitions.h"
+#include "hw.h"
+#include "savedata.h"
+#include "endpoints.h"
+
+//-----------------------------------------------------------------------------
+// CSaveData statics
+//-----------------------------------------------------------------------------
+
+PSAVEWORKER_PARAM CSaveData::m_pWorkItems = NULL;
+PDEVICE_OBJECT CSaveData::m_pDeviceObject = NULL;
+//=============================================================================
+// Classes
+//=============================================================================
+
+///////////////////////////////////////////////////////////////////////////////
+// CAdapterCommon
+//
+class CAdapterCommon :
+ public IAdapterCommon,
+ public IAdapterPowerManagement,
+ public CUnknown
+{
+ private:
+ PSERVICEGROUP m_pServiceGroupWave;
+ PDEVICE_OBJECT m_pDeviceObject;
+ PDEVICE_OBJECT m_pPhysicalDeviceObject;
+ WDFDEVICE m_WdfDevice; // Wdf device.
+ DEVICE_POWER_STATE m_PowerState;
+
+ PCSimpleAudioSampleHW m_pHW; // Virtual Simple Audio Sample HW object
+ PPORTCLSETWHELPER m_pPortClsEtwHelper;
+
+ static LONG m_AdapterInstances; // # of adapter objects.
+
+ DWORD m_dwIdleRequests;
+
+ public:
+ //=====================================================================
+ // Default CUnknown
+ DECLARE_STD_UNKNOWN();
+ DEFINE_STD_CONSTRUCTOR(CAdapterCommon);
+ ~CAdapterCommon();
+
+ //=====================================================================
+ // Default IAdapterPowerManagement
+ IMP_IAdapterPowerManagement;
+
+ //=====================================================================
+ // IAdapterCommon methods
+
+ STDMETHODIMP_(NTSTATUS) Init
+ (
+ _In_ PDEVICE_OBJECT DeviceObject
+ );
+
+ STDMETHODIMP_(PDEVICE_OBJECT) GetDeviceObject(void);
+
+ STDMETHODIMP_(PDEVICE_OBJECT) GetPhysicalDeviceObject(void);
+
+ STDMETHODIMP_(WDFDEVICE) GetWdfDevice(void);
+
+ STDMETHODIMP_(void) SetWaveServiceGroup
+ (
+ _In_ PSERVICEGROUP ServiceGroup
+ );
+
+ STDMETHODIMP_(BOOL) bDevSpecificRead();
+
+ STDMETHODIMP_(void) bDevSpecificWrite
+ (
+ _In_ BOOL bDevSpecific
+ );
+ STDMETHODIMP_(INT) iDevSpecificRead();
+
+ STDMETHODIMP_(void) iDevSpecificWrite
+ (
+ _In_ INT iDevSpecific
+ );
+ STDMETHODIMP_(UINT) uiDevSpecificRead();
+
+ STDMETHODIMP_(void) uiDevSpecificWrite
+ (
+ _In_ UINT uiDevSpecific
+ );
+
+ STDMETHODIMP_(BOOL) MixerMuteRead
+ (
+ _In_ ULONG Index,
+ _In_ ULONG Channel
+ );
+
+ STDMETHODIMP_(void) MixerMuteWrite
+ (
+ _In_ ULONG Index,
+ _In_ ULONG Channel,
+ _In_ BOOL Value
+ );
+
+ STDMETHODIMP_(ULONG) MixerMuxRead(void);
+
+ STDMETHODIMP_(void) MixerMuxWrite
+ (
+ _In_ ULONG Index
+ );
+
+ STDMETHODIMP_(void) MixerReset(void);
+
+ STDMETHODIMP_(LONG) MixerVolumeRead
+ (
+ _In_ ULONG Index,
+ _In_ ULONG Channel
+ );
+
+ STDMETHODIMP_(void) MixerVolumeWrite
+ (
+ _In_ ULONG Index,
+ _In_ ULONG Channel,
+ _In_ LONG Value
+ );
+
+ STDMETHODIMP_(LONG) MixerPeakMeterRead
+ (
+ _In_ ULONG Index,
+ _In_ ULONG Channel
+ );
+
+ STDMETHODIMP_(NTSTATUS) WriteEtwEvent
+ (
+ _In_ EPcMiniportEngineEvent miniportEventType,
+ _In_ ULONGLONG ullData1,
+ _In_ ULONGLONG ullData2,
+ _In_ ULONGLONG ullData3,
+ _In_ ULONGLONG ullData4
+ );
+
+ STDMETHODIMP_(VOID) SetEtwHelper
+ (
+ PPORTCLSETWHELPER _pPortClsEtwHelper
+ );
+
+ STDMETHODIMP_(NTSTATUS) InstallSubdevice
+ (
+ _In_opt_ PIRP Irp,
+ _In_ PWSTR Name,
+ _In_opt_ PWSTR TemplateName,
+ _In_ REFGUID PortClassId,
+ _In_ REFGUID MiniportClassId,
+ _In_opt_ PFNCREATEMINIPORT MiniportCreate,
+ _In_ ULONG cPropertyCount,
+ _In_reads_opt_(cPropertyCount) const SIMPLEAUDIOSAMPLE_DEVPROPERTY * pProperties,
+ _In_opt_ PVOID DeviceContext,
+ _In_ PENDPOINT_MINIPAIR MiniportPair,
+ _In_opt_ PRESOURCELIST ResourceList,
+ _In_ REFGUID PortInterfaceId,
+ _Out_opt_ PUNKNOWN * OutPortInterface,
+ _Out_opt_ PUNKNOWN * OutPortUnknown,
+ _Out_opt_ PUNKNOWN * OutMiniportUnknown
+ );
+
+ STDMETHODIMP_(NTSTATUS) UnregisterSubdevice
+ (
+ _In_opt_ PUNKNOWN UnknownPort
+ );
+
+ STDMETHODIMP_(NTSTATUS) ConnectTopologies
+ (
+ _In_ PUNKNOWN UnknownTopology,
+ _In_ PUNKNOWN UnknownWave,
+ _In_ PHYSICALCONNECTIONTABLE* PhysicalConnections,
+ _In_ ULONG PhysicalConnectionCount
+ );
+
+ STDMETHODIMP_(NTSTATUS) DisconnectTopologies
+ (
+ _In_ PUNKNOWN UnknownTopology,
+ _In_ PUNKNOWN UnknownWave,
+ _In_ PHYSICALCONNECTIONTABLE* PhysicalConnections,
+ _In_ ULONG PhysicalConnectionCount
+ );
+
+ STDMETHODIMP_(NTSTATUS) InstallEndpointFilters
+ (
+ _In_opt_ PIRP Irp,
+ _In_ PENDPOINT_MINIPAIR MiniportPair,
+ _In_opt_ PVOID DeviceContext,
+ _Out_opt_ PUNKNOWN * UnknownTopology,
+ _Out_opt_ PUNKNOWN * UnknownWave,
+ _Out_opt_ PUNKNOWN * UnknownMiniportTopology,
+ _Out_opt_ PUNKNOWN * UnknownMiniportWave
+ );
+
+ STDMETHODIMP_(NTSTATUS) RemoveEndpointFilters
+ (
+ _In_ PENDPOINT_MINIPAIR MiniportPair,
+ _In_opt_ PUNKNOWN UnknownTopology,
+ _In_opt_ PUNKNOWN UnknownWave
+ );
+
+ STDMETHODIMP_(NTSTATUS) GetFilters
+ (
+ _In_ PENDPOINT_MINIPAIR MiniportPair,
+ _Out_opt_ PUNKNOWN *UnknownTopologyPort,
+ _Out_opt_ PUNKNOWN *UnknownTopologyMiniport,
+ _Out_opt_ PUNKNOWN *UnknownWavePort,
+ _Out_opt_ PUNKNOWN *UnknownWaveMiniport
+ );
+
+ STDMETHODIMP_(NTSTATUS) SetIdlePowerManagement
+ (
+ _In_ PENDPOINT_MINIPAIR MiniportPair,
+ _In_ BOOL bEnabled
+ );
+
+ STDMETHODIMP_(VOID) Cleanup();
+
+ //=====================================================================
+ // friends
+ friend NTSTATUS NewAdapterCommon
+ (
+ _Out_ PUNKNOWN * Unknown,
+ _In_ REFCLSID,
+ _In_opt_ PUNKNOWN UnknownOuter,
+ _In_ POOL_FLAGS PoolFlags
+ );
+
+ private:
+
+ LIST_ENTRY m_SubdeviceCache;
+
+ NTSTATUS GetCachedSubdevice
+ (
+ _In_ PWSTR Name,
+ _Out_opt_ PUNKNOWN *OutUnknownPort,
+ _Out_opt_ PUNKNOWN *OutUnknownMiniport
+ );
+
+ NTSTATUS CacheSubdevice
+ (
+ _In_ PWSTR Name,
+ _In_ PUNKNOWN UnknownPort,
+ _In_ PUNKNOWN UnknownMiniport
+ );
+
+ NTSTATUS RemoveCachedSubdevice
+ (
+ _In_ PWSTR Name
+ );
+
+ VOID EmptySubdeviceCache();
+
+ NTSTATUS CreateAudioInterfaceWithProperties
+ (
+ _In_ PCWSTR ReferenceString,
+ _In_opt_ PCWSTR TemplateReferenceString,
+ _In_ ULONG cPropertyCount,
+ _In_reads_opt_(cPropertyCount) const SIMPLEAUDIOSAMPLE_DEVPROPERTY *pProperties,
+ _Out_ _At_(AudioSymbolicLinkName->Buffer, __drv_allocatesMem(Mem)) PUNICODE_STRING AudioSymbolicLinkName
+ );
+
+ NTSTATUS MigrateDeviceInterfaceTemplateParameters
+ (
+ _In_ PUNICODE_STRING SymbolicLinkName,
+ _In_opt_ PCWSTR TemplateReferenceString
+ );
+};
+
+typedef struct _MINIPAIR_UNKNOWN
+{
+ LIST_ENTRY ListEntry;
+ WCHAR Name[MAX_PATH];
+ PUNKNOWN PortInterface;
+ PUNKNOWN MiniportInterface;
+ PADAPTERPOWERMANAGEMENT PowerInterface;
+} MINIPAIR_UNKNOWN;
+
+#define MAX_DEVICE_REG_KEY_LENGTH 0x100
+
+//
+// Used to implement the singleton pattern.
+//
+LONG CAdapterCommon::m_AdapterInstances = 0;
+
+
+
+//-----------------------------------------------------------------------------
+// Functions
+//-----------------------------------------------------------------------------
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS SimpleAudioSampleIoSetDeviceInterfacePropertyDataMultiple
+(
+ _In_ PUNICODE_STRING SymbolicLinkName,
+ _In_ ULONG cPropertyCount,
+ _In_reads_opt_(cPropertyCount) const SIMPLEAUDIOSAMPLE_DEVPROPERTY *pProperties
+)
+{
+ NTSTATUS ntStatus;
+
+ PAGED_CODE();
+
+ if (pProperties)
+ {
+ for (ULONG i = 0; i < cPropertyCount; i++)
+ {
+ ntStatus = IoSetDeviceInterfacePropertyData(
+ SymbolicLinkName,
+ pProperties[i].PropertyKey,
+ LOCALE_NEUTRAL,
+ PLUGPLAY_PROPERTY_PERSISTENT,
+ pProperties[i].Type,
+ pProperties[i].BufferSize,
+ pProperties[i].Buffer);
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ return ntStatus;
+ }
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+NewAdapterCommon
+(
+ _Out_ PUNKNOWN * Unknown,
+ _In_ REFCLSID,
+ _In_opt_ PUNKNOWN UnknownOuter,
+ _In_ POOL_FLAGS PoolFlags
+)
+/*++
+
+Routine Description:
+
+ Creates a new CAdapterCommon
+
+Arguments:
+
+ Unknown -
+
+ UnknownOuter -
+
+ PoolType
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(Unknown);
+
+ NTSTATUS ntStatus;
+
+ //
+ // This sample supports only one instance of this object.
+ // (b/c of CSaveData's static members and Bluetooth HFP logic).
+ //
+ if (InterlockedCompareExchange(&CAdapterCommon::m_AdapterInstances, 1, 0) != 0)
+ {
+ ntStatus = STATUS_DEVICE_BUSY;
+ DPF(D_ERROR, ("NewAdapterCommon failed, only one instance is allowed"));
+ goto Done;
+ }
+
+ //
+ // Allocate an adapter object.
+ //
+ CAdapterCommon *p = new(PoolFlags, MINADAPTER_POOLTAG) CAdapterCommon(UnknownOuter);
+ if (p == NULL)
+ {
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ DPF(D_ERROR, ("NewAdapterCommon failed, 0x%x", ntStatus));
+ goto Done;
+ }
+
+ //
+ // Success.
+ //
+ *Unknown = PUNKNOWN((PADAPTERCOMMON)(p));
+ (*Unknown)->AddRef();
+ ntStatus = STATUS_SUCCESS;
+
+Done:
+ return ntStatus;
+} // NewAdapterCommon
+
+//=============================================================================
+#pragma code_seg("PAGE")
+CAdapterCommon::~CAdapterCommon
+(
+ void
+)
+/*++
+
+Routine Description:
+
+ Destructor for CAdapterCommon.
+
+Arguments:
+
+Return Value:
+
+ void
+
+--*/
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::~CAdapterCommon]"));
+
+ if (m_pHW)
+ {
+ delete m_pHW;
+ m_pHW = NULL;
+ }
+
+ CSaveData::DestroyWorkItems();
+ SAFE_RELEASE(m_pPortClsEtwHelper);
+ SAFE_RELEASE(m_pServiceGroupWave);
+
+ if (m_WdfDevice)
+ {
+ WdfObjectDelete(m_WdfDevice);
+ m_WdfDevice = NULL;
+ }
+
+ InterlockedDecrement(&CAdapterCommon::m_AdapterInstances);
+ ASSERT(CAdapterCommon::m_AdapterInstances == 0);
+} // ~CAdapterCommon
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(PDEVICE_OBJECT)
+CAdapterCommon::GetDeviceObject
+(
+ void
+)
+/*++
+
+Routine Description:
+
+ Returns the deviceobject
+
+Arguments:
+
+Return Value:
+
+ PDEVICE_OBJECT
+
+--*/
+{
+ PAGED_CODE();
+
+ return m_pDeviceObject;
+} // GetDeviceObject
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(PDEVICE_OBJECT)
+CAdapterCommon::GetPhysicalDeviceObject
+(
+ void
+)
+/*++
+
+Routine Description:
+
+ Returns the PDO.
+
+Arguments:
+
+Return Value:
+
+ PDEVICE_OBJECT
+
+--*/
+{
+ PAGED_CODE();
+
+ return m_pPhysicalDeviceObject;
+} // GetPhysicalDeviceObject
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(WDFDEVICE)
+CAdapterCommon::GetWdfDevice
+(
+ void
+)
+/*++
+
+Routine Description:
+
+ Returns the associated WDF miniport device. Note that this is NOT an audio
+ miniport. The WDF miniport device is the WDF device associated with the
+ adapter.
+
+Arguments:
+
+Return Value:
+
+ WDFDEVICE
+
+--*/
+{
+ PAGED_CODE();
+
+ return m_WdfDevice;
+} // GetWdfDevice
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CAdapterCommon::Init
+(
+ _In_ PDEVICE_OBJECT DeviceObject
+)
+/*++
+
+Routine Description:
+
+ Initialize adapter common object.
+
+Arguments:
+
+ DeviceObject - pointer to the device object
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::Init]"));
+
+ ASSERT(DeviceObject);
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ m_pServiceGroupWave = NULL;
+ m_pDeviceObject = DeviceObject;
+ m_pPhysicalDeviceObject = NULL;
+ m_WdfDevice = NULL;
+ m_PowerState = PowerDeviceD0;
+ m_pHW = NULL;
+ m_pPortClsEtwHelper = NULL;
+
+ InitializeListHead(&m_SubdeviceCache);
+
+ //
+ // Get the PDO.
+ //
+ ntStatus = PcGetPhysicalDeviceObject(DeviceObject, &m_pPhysicalDeviceObject);
+ IF_FAILED_ACTION_JUMP(
+ ntStatus,
+ DPF(D_ERROR, ("PcGetPhysicalDeviceObject failed, 0x%x", ntStatus)),
+ Done);
+
+ //
+ // Create a WDF miniport to represent the adapter. Note that WDF miniports
+ // are NOT audio miniports. An audio adapter is associated with a single WDF
+ // miniport. This driver uses WDF to simplify the handling of the Bluetooth
+ // SCO HFP Bypass interface.
+ //
+ ntStatus = WdfDeviceMiniportCreate( WdfGetDriver(),
+ WDF_NO_OBJECT_ATTRIBUTES,
+ DeviceObject, // FDO
+ NULL, // Next device.
+ NULL, // PDO
+ &m_WdfDevice);
+ IF_FAILED_ACTION_JUMP(
+ ntStatus,
+ DPF(D_ERROR, ("WdfDeviceMiniportCreate failed, 0x%x", ntStatus)),
+ Done);
+
+ // Initialize HW.
+ //
+ m_pHW = new (POOL_FLAG_NON_PAGED, SIMPLEAUDIOSAMPLE_POOLTAG) CSimpleAudioSampleHW;
+ if (!m_pHW)
+ {
+ DPF(D_TERSE, ("Insufficient memory for Simple Audio Sample HW"));
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ IF_FAILED_JUMP(ntStatus, Done);
+
+ m_pHW->MixerReset();
+
+ //
+ // Initialize SaveData class.
+ //
+ CSaveData::SetDeviceObject(DeviceObject); //device object is needed by CSaveData
+ ntStatus = CSaveData::InitializeWorkItems(DeviceObject);
+ IF_FAILED_JUMP(ntStatus, Done);
+Done:
+
+ return ntStatus;
+} // Init
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(void)
+CAdapterCommon::MixerReset
+(
+ void
+)
+/*++
+
+Routine Description:
+
+ Reset mixer registers from registry.
+
+Arguments:
+
+Return Value:
+
+ void
+
+--*/
+{
+ PAGED_CODE();
+
+ if (m_pHW)
+ {
+ m_pHW->MixerReset();
+ }
+} // MixerReset
+
+//=============================================================================
+/* Here are the definitions of the standard miniport events.
+
+Event type : eMINIPORT_IHV_DEFINED
+Parameter 1 : Defined and used by IHVs
+Parameter 2 : Defined and used by IHVs
+Parameter 3 : Defined and used by IHVs
+Parameter 4 :Defined and used by IHVs
+
+Event type: eMINIPORT_BUFFER_COMPLETE
+Parameter 1: Current linear buffer position
+Parameter 2: the previous WaveRtBufferWritePosition that the drive received
+Parameter 3: Data length completed
+Parameter 4:0
+
+Event type: eMINIPORT_PIN_STATE
+Parameter 1: Current linear buffer position
+Parameter 2: the previous WaveRtBufferWritePosition that the drive received
+Parameter 3: Pin State 0->KS_STOP, 1->KS_ACQUIRE, 2->KS_PAUSE, 3->KS_RUN
+Parameter 4:0
+
+Event type: eMINIPORT_GET_STREAM_POS
+Parameter 1: Current linear buffer position
+Parameter 2: the previous WaveRtBufferWritePosition that the drive received
+Parameter 3: 0
+Parameter 4:0
+
+
+Event type: eMINIPORT_SET_WAVERT_BUFFER_WRITE_POS
+Parameter 1: Current linear buffer position
+Parameter 2: the previous WaveRtBufferWritePosition that the drive received
+Parameter 3: the arget WaveRtBufferWritePosition received from portcls
+Parameter 4:0
+
+Event type: eMINIPORT_GET_PRESENTATION_POS
+Parameter 1: Current linear buffer position
+Parameter 2: the previous WaveRtBufferWritePosition that the drive received
+Parameter 3: Presentation position
+Parameter 4:0
+
+Event type: eMINIPORT_PROGRAM_DMA
+Parameter 1: Current linear buffer position
+Parameter 2: the previous WaveRtBufferWritePosition that the drive received
+Parameter 3: Starting WaveRt buffer offset
+Parameter 4: Data length
+
+Event type: eMINIPORT_GLITCH_REPORT
+Parameter 1: Current linear buffer position
+Parameter 2: the previous WaveRtBufferWritePosition that the drive received
+Parameter 3: major glitch code: 1:WaveRT buffer is underrun,
+ 2:decoder errors,
+ 3:receive the same wavert buffer two in a row in event driven mode
+Parameter 4: minor code for the glitch cause
+
+Event type: eMINIPORT_LAST_BUFFER_RENDERED
+Parameter 1: Current linear buffer position
+Parameter 2: the very last WaveRtBufferWritePosition that the driver received
+Parameter 3: 0
+Parameter 4: 0
+
+*/
+#pragma code_seg()
+STDMETHODIMP
+CAdapterCommon::WriteEtwEvent
+(
+ _In_ EPcMiniportEngineEvent miniportEventType,
+ _In_ ULONGLONG ullData1,
+ _In_ ULONGLONG ullData2,
+ _In_ ULONGLONG ullData3,
+ _In_ ULONGLONG ullData4
+)
+{
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ if (m_pPortClsEtwHelper)
+ {
+ ntStatus = m_pPortClsEtwHelper->MiniportWriteEtwEvent( miniportEventType, ullData1, ullData2, ullData3, ullData4) ;
+ }
+ return ntStatus;
+} // WriteEtwEvent
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(void)
+CAdapterCommon::SetEtwHelper
+(
+ PPORTCLSETWHELPER _pPortClsEtwHelper
+)
+{
+ PAGED_CODE();
+
+ SAFE_RELEASE(m_pPortClsEtwHelper);
+
+ m_pPortClsEtwHelper = _pPortClsEtwHelper;
+
+ if (m_pPortClsEtwHelper)
+ {
+ m_pPortClsEtwHelper->AddRef();
+ }
+} // SetEtwHelper
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP
+CAdapterCommon::NonDelegatingQueryInterface
+(
+ _In_ REFIID Interface,
+ _COM_Outptr_ PVOID * Object
+)
+/*++
+
+Routine Description:
+
+ QueryInterface routine for AdapterCommon
+
+Arguments:
+
+ Interface -
+
+ Object -
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(Object);
+
+ if (IsEqualGUIDAligned(Interface, IID_IUnknown))
+ {
+ *Object = PVOID(PUNKNOWN(PADAPTERCOMMON(this)));
+ }
+ else if (IsEqualGUIDAligned(Interface, IID_IAdapterCommon))
+ {
+ *Object = PVOID(PADAPTERCOMMON(this));
+ }
+ else if (IsEqualGUIDAligned(Interface, IID_IAdapterPowerManagement))
+ {
+ *Object = PVOID(PADAPTERPOWERMANAGEMENT(this));
+ }
+ else
+ {
+ *Object = NULL;
+ }
+
+ if (*Object)
+ {
+ PUNKNOWN(*Object)->AddRef();
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_INVALID_PARAMETER;
+} // NonDelegatingQueryInterface
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(void)
+CAdapterCommon::SetWaveServiceGroup
+(
+ _In_ PSERVICEGROUP ServiceGroup
+)
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::SetWaveServiceGroup]"));
+
+ SAFE_RELEASE(m_pServiceGroupWave);
+
+ m_pServiceGroupWave = ServiceGroup;
+
+ if (m_pServiceGroupWave)
+ {
+ m_pServiceGroupWave->AddRef();
+ }
+} // SetWaveServiceGroup
+
+//=============================================================================
+#pragma code_seg()
+STDMETHODIMP_(BOOL)
+CAdapterCommon::bDevSpecificRead()
+/*++
+
+Routine Description:
+
+ Fetch Device Specific information.
+
+Arguments:
+
+ N/A
+
+Return Value:
+
+ BOOL - Device Specific info
+
+--*/
+{
+ if (m_pHW)
+ {
+ return m_pHW->bGetDevSpecific();
+ }
+
+ return FALSE;
+} // bDevSpecificRead
+
+//=============================================================================
+#pragma code_seg()
+STDMETHODIMP_(void)
+CAdapterCommon::bDevSpecificWrite
+(
+ _In_ BOOL bDevSpecific
+)
+/*++
+
+Routine Description:
+
+ Store the new value in the Device Specific location.
+
+Arguments:
+
+ bDevSpecific - Value to store
+
+Return Value:
+
+ N/A.
+
+--*/
+{
+ if (m_pHW)
+ {
+ m_pHW->bSetDevSpecific(bDevSpecific);
+ }
+} // DevSpecificWrite
+
+//=============================================================================
+#pragma code_seg()
+STDMETHODIMP_(INT)
+CAdapterCommon::iDevSpecificRead()
+/*++
+
+Routine Description:
+
+ Fetch Device Specific information.
+
+Arguments:
+
+ N/A
+
+Return Value:
+
+ INT - Device Specific info
+
+--*/
+{
+ if (m_pHW)
+ {
+ return m_pHW->iGetDevSpecific();
+ }
+
+ return 0;
+} // iDevSpecificRead
+
+//=============================================================================
+#pragma code_seg()
+STDMETHODIMP_(void)
+CAdapterCommon::iDevSpecificWrite
+(
+ _In_ INT iDevSpecific
+)
+/*++
+
+Routine Description:
+
+ Store the new value in the Device Specific location.
+
+Arguments:
+
+ iDevSpecific - Value to store
+
+Return Value:
+
+ N/A.
+
+--*/
+{
+ if (m_pHW)
+ {
+ m_pHW->iSetDevSpecific(iDevSpecific);
+ }
+} // iDevSpecificWrite
+
+//=============================================================================
+#pragma code_seg()
+STDMETHODIMP_(UINT)
+CAdapterCommon::uiDevSpecificRead()
+/*++
+
+Routine Description:
+
+ Fetch Device Specific information.
+
+Arguments:
+
+ N/A
+
+Return Value:
+
+ UINT - Device Specific info
+
+--*/
+{
+ if (m_pHW)
+ {
+ return m_pHW->uiGetDevSpecific();
+ }
+
+ return 0;
+} // uiDevSpecificRead
+
+//=============================================================================
+#pragma code_seg()
+STDMETHODIMP_(void)
+CAdapterCommon::uiDevSpecificWrite
+(
+ _In_ UINT uiDevSpecific
+)
+/*++
+
+Routine Description:
+
+ Store the new value in the Device Specific location.
+
+Arguments:
+
+ uiDevSpecific - Value to store
+
+Return Value:
+
+ N/A.
+
+--*/
+{
+ if (m_pHW)
+ {
+ m_pHW->uiSetDevSpecific(uiDevSpecific);
+ }
+} // uiDevSpecificWrite
+
+//=============================================================================
+#pragma code_seg()
+STDMETHODIMP_(BOOL)
+CAdapterCommon::MixerMuteRead
+(
+ _In_ ULONG Index,
+ _In_ ULONG Channel
+)
+/*++
+
+Routine Description:
+
+ Store the new value in mixer register array.
+
+Arguments:
+
+ Index - node id
+
+Return Value:
+
+ BOOL - mixer mute setting for this node
+
+--*/
+{
+ if (m_pHW)
+ {
+ return m_pHW->GetMixerMute(Index, Channel);
+ }
+
+ return 0;
+} // MixerMuteRead
+
+//=============================================================================
+#pragma code_seg()
+STDMETHODIMP_(void)
+CAdapterCommon::MixerMuteWrite
+(
+ _In_ ULONG Index,
+ _In_ ULONG Channel,
+ _In_ BOOL Value
+)
+/*++
+
+Routine Description:
+
+ Store the new value in mixer register array.
+
+Arguments:
+
+ Index - node id
+
+ Value - new mute settings
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ if (m_pHW)
+ {
+ m_pHW->SetMixerMute(Index, Channel, Value);
+ }
+} // MixerMuteWrite
+
+//=============================================================================
+#pragma code_seg()
+STDMETHODIMP_(ULONG)
+CAdapterCommon::MixerMuxRead()
+/*++
+
+Routine Description:
+
+ Return the mux selection
+
+Arguments:
+
+ Index - node id
+
+ Value - new mute settings
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ if (m_pHW)
+ {
+ return m_pHW->GetMixerMux();
+ }
+
+ return 0;
+} // MixerMuxRead
+
+//=============================================================================
+#pragma code_seg()
+STDMETHODIMP_(void)
+CAdapterCommon::MixerMuxWrite
+(
+ _In_ ULONG Index
+)
+/*++
+
+Routine Description:
+
+ Store the new mux selection
+
+Arguments:
+
+ Index - node id
+
+ Value - new mute settings
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ if (m_pHW)
+ {
+ m_pHW->SetMixerMux(Index);
+ }
+} // MixerMuxWrite
+
+//=============================================================================
+#pragma code_seg()
+STDMETHODIMP_(LONG)
+CAdapterCommon::MixerVolumeRead
+(
+ _In_ ULONG Index,
+ _In_ ULONG Channel
+)
+/*++
+
+Routine Description:
+
+ Return the value in mixer register array.
+
+Arguments:
+
+ Index - node id
+
+ Channel = which channel
+
+Return Value:
+
+ Byte - mixer volume settings for this line
+
+--*/
+{
+ if (m_pHW)
+ {
+ return m_pHW->GetMixerVolume(Index, Channel);
+ }
+
+ return 0;
+} // MixerVolumeRead
+
+//=============================================================================
+#pragma code_seg()
+STDMETHODIMP_(void)
+CAdapterCommon::MixerVolumeWrite
+(
+ _In_ ULONG Index,
+ _In_ ULONG Channel,
+ _In_ LONG Value
+)
+/*++
+
+Routine Description:
+
+ Store the new value in mixer register array.
+
+Arguments:
+
+ Index - node id
+
+ Channel - which channel
+
+ Value - new volume level
+
+Return Value:
+
+ void
+
+--*/
+{
+ if (m_pHW)
+ {
+ m_pHW->SetMixerVolume(Index, Channel, Value);
+ }
+} // MixerVolumeWrite
+
+//=============================================================================
+#pragma code_seg()
+STDMETHODIMP_(LONG)
+CAdapterCommon::MixerPeakMeterRead
+(
+ _In_ ULONG Index,
+ _In_ ULONG Channel
+)
+/*++
+
+Routine Description:
+
+ Return the value in mixer register array.
+
+Arguments:
+
+ Index - node id
+
+ Channel = which channel
+
+Return Value:
+
+ Byte - mixer sample peak meter settings for this line
+
+--*/
+{
+ if (m_pHW)
+ {
+ return m_pHW->GetMixerPeakMeter(Index, Channel);
+ }
+
+ return 0;
+} // MixerVolumeRead
+
+//=============================================================================
+#pragma code_seg()
+STDMETHODIMP_(void)
+CAdapterCommon::PowerChangeState
+(
+ _In_ POWER_STATE NewState
+)
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ NewState - The requested, new power state for the device.
+
+Return Value:
+
+ void
+
+Note:
+ From MSDN:
+
+ To assist the driver, PortCls will pause any active audio streams prior to calling
+ this method to place the device in a sleep state. After calling this method, PortCls
+ will unpause active audio streams, to wake the device up. Miniports can opt for
+ additional notification by utilizing the IPowerNotify interface.
+
+ The miniport driver must perform the requested change to the device's power state
+ before it returns from the PowerChangeState call. If the miniport driver needs to
+ save or restore any device state before a power-state change, the miniport driver
+ should support the IPowerNotify interface, which allows it to receive advance warning
+ of any such change. Before returning from a successful PowerChangeState call, the
+ miniport driver should cache the new power state.
+
+ While the miniport driver is in one of the sleep states (any state other than
+ PowerDeviceD0), it must avoid writing to the hardware. The miniport driver must cache
+ any hardware accesses that need to be deferred until the device powers up again. If
+ the power state is changing from one of the sleep states to PowerDeviceD0, the
+ miniport driver should perform any deferred hardware accesses after it has powered up
+ the device. If the power state is changing from PowerDeviceD0 to a sleep state, the
+ miniport driver can perform any necessary hardware accesses during the PowerChangeState
+ call before it powers down the device.
+
+ While powered down, a miniport driver is never asked to create a miniport driver object
+ or stream object. PortCls always places the device in the PowerDeviceD0 state before
+ calling the miniport driver's NewStream method.
+
+--*/
+{
+ DPF_ENTER(("[CAdapterCommon::PowerChangeState]"));
+
+ // Notify all registered miniports of a power state change
+ PLIST_ENTRY le = NULL;
+ for (le = m_SubdeviceCache.Flink; le != &m_SubdeviceCache; le = le->Flink)
+ {
+ MINIPAIR_UNKNOWN *pRecord = CONTAINING_RECORD(le, MINIPAIR_UNKNOWN, ListEntry);
+
+ if (pRecord->PowerInterface)
+ {
+ pRecord->PowerInterface->PowerChangeState(NewState);
+ }
+ }
+
+ // is this actually a state change??
+ //
+ if (NewState.DeviceState != m_PowerState)
+ {
+ // switch on new state
+ //
+ switch (NewState.DeviceState)
+ {
+ case PowerDeviceD0:
+ case PowerDeviceD1:
+ case PowerDeviceD2:
+ case PowerDeviceD3:
+ m_PowerState = NewState.DeviceState;
+
+ DPF
+ (
+ D_VERBOSE,
+ ("Entering D%u", ULONG(m_PowerState) - ULONG(PowerDeviceD0))
+ );
+
+ break;
+
+ default:
+
+ DPF(D_VERBOSE, ("Unknown Device Power State"));
+ break;
+ }
+ }
+} // PowerStateChange
+
+//=============================================================================
+#pragma code_seg()
+STDMETHODIMP_(NTSTATUS)
+CAdapterCommon::QueryDeviceCapabilities
+(
+ _Inout_updates_bytes_(sizeof(DEVICE_CAPABILITIES)) PDEVICE_CAPABILITIES PowerDeviceCaps
+)
+/*++
+
+Routine Description:
+
+ Called at startup to get the caps for the device. This structure provides
+ the system with the mappings between system power state and device power
+ state. This typically will not need modification by the driver.
+
+Arguments:
+
+ PowerDeviceCaps - The device's capabilities.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ UNREFERENCED_PARAMETER(PowerDeviceCaps);
+
+ DPF_ENTER(("[CAdapterCommon::QueryDeviceCapabilities]"));
+
+ return (STATUS_SUCCESS);
+} // QueryDeviceCapabilities
+
+//=============================================================================
+#pragma code_seg()
+STDMETHODIMP_(NTSTATUS)
+CAdapterCommon::QueryPowerChangeState
+(
+ _In_ POWER_STATE NewStateQuery
+)
+/*++
+
+Routine Description:
+
+ Query to see if the device can change to this power state
+
+Arguments:
+
+ NewStateQuery - The requested, new power state for the device
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ DPF_ENTER(("[CAdapterCommon::QueryPowerChangeState]"));
+
+ // query each miniport for it's power state, we're finished if even one indicates
+ // it cannot go to this power state.
+ PLIST_ENTRY le = NULL;
+ for (le = m_SubdeviceCache.Flink; le != &m_SubdeviceCache && NT_SUCCESS(status); le = le->Flink)
+ {
+ MINIPAIR_UNKNOWN *pRecord = CONTAINING_RECORD(le, MINIPAIR_UNKNOWN, ListEntry);
+
+ if (pRecord->PowerInterface)
+ {
+ status = pRecord->PowerInterface->QueryPowerChangeState(NewStateQuery);
+ }
+ }
+
+ return status;
+} // QueryPowerChangeState
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CAdapterCommon::CreateAudioInterfaceWithProperties
+(
+ _In_ PCWSTR ReferenceString,
+ _In_opt_ PCWSTR TemplateReferenceString,
+ _In_ ULONG cPropertyCount,
+ _In_reads_opt_(cPropertyCount) const SIMPLEAUDIOSAMPLE_DEVPROPERTY *pProperties,
+ _Out_ _At_(AudioSymbolicLinkName->Buffer, __drv_allocatesMem(Mem)) PUNICODE_STRING AudioSymbolicLinkName
+)
+/*++
+
+Routine Description:
+
+Create the audio interface (in disabled mode).
+
+--*/
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::CreateAudioInterfaceWithProperties]"));
+
+ NTSTATUS ntStatus;
+ UNICODE_STRING referenceString;
+
+ RtlInitUnicodeString(&referenceString, ReferenceString);
+
+ //
+ // Reset output value.
+ //
+ RtlZeroMemory(AudioSymbolicLinkName, sizeof(UNICODE_STRING));
+
+ //
+ // Register an audio interface if not already present.
+ //
+ ntStatus = IoRegisterDeviceInterface(
+ GetPhysicalDeviceObject(),
+ &KSCATEGORY_AUDIO,
+ &referenceString,
+ AudioSymbolicLinkName);
+
+ IF_FAILED_ACTION_JUMP(
+ ntStatus,
+ DPF(D_ERROR, ("CreateAudioInterfaceWithProperties: IoRegisterDeviceInterface(KSCATEGORY_AUDIO): failed, 0x%x", ntStatus)),
+ Done);
+
+ //
+ // Migrate optional device interface parameters from the template if it exists
+ // This is done first, so that any additional parameters in pProperties will override the defaults.
+ //
+ if (NULL != TemplateReferenceString)
+ {
+ ntStatus = MigrateDeviceInterfaceTemplateParameters(AudioSymbolicLinkName, TemplateReferenceString);
+
+ IF_FAILED_ACTION_JUMP(
+ ntStatus,
+ DPF(D_ERROR, ("MigrateDeviceInterfaceTempalteParameters: MigrateDeviceInterfaceTemplateParameters(...): failed, 0x%x", ntStatus)),
+ Done);
+ }
+
+ //
+ // Set properties on the interface
+ //
+ ntStatus = SimpleAudioSampleIoSetDeviceInterfacePropertyDataMultiple(AudioSymbolicLinkName, cPropertyCount, pProperties);
+
+ IF_FAILED_ACTION_JUMP(
+ ntStatus,
+ DPF(D_ERROR, ("CreateAudioInterfaceWithProperties: SimpleAudioSampleIoSetDeviceInterfacePropertyDataMultiple(...): failed, 0x%x", ntStatus)),
+ Done);
+
+ //
+ // All done.
+ //
+ ntStatus = STATUS_SUCCESS;
+
+Done:
+ if (!NT_SUCCESS(ntStatus))
+ {
+ RtlFreeUnicodeString(AudioSymbolicLinkName);
+ RtlZeroMemory(AudioSymbolicLinkName, sizeof(UNICODE_STRING));
+ }
+ return ntStatus;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(NTSTATUS)
+CAdapterCommon::InstallSubdevice
+(
+ _In_opt_ PIRP Irp,
+ _In_ PWSTR Name,
+ _In_opt_ PWSTR TemplateName,
+ _In_ REFGUID PortClassId,
+ _In_ REFGUID MiniportClassId,
+ _In_opt_ PFNCREATEMINIPORT MiniportCreate,
+ _In_ ULONG cPropertyCount,
+ _In_reads_opt_(cPropertyCount) const SIMPLEAUDIOSAMPLE_DEVPROPERTY * pProperties,
+ _In_opt_ PVOID DeviceContext,
+ _In_ PENDPOINT_MINIPAIR MiniportPair,
+ _In_opt_ PRESOURCELIST ResourceList,
+ _In_ REFGUID PortInterfaceId,
+ _Out_opt_ PUNKNOWN * OutPortInterface,
+ _Out_opt_ PUNKNOWN * OutPortUnknown,
+ _Out_opt_ PUNKNOWN * OutMiniportUnknown
+)
+{
+/*++
+
+Routine Description:
+
+ This function creates and registers a subdevice consisting of a port
+ driver, a minport driver and a set of resources bound together. It will
+ also optionally place a pointer to an interface on the port driver in a
+ specified location before initializing the port driver. This is done so
+ that a common ISR can have access to the port driver during
+ initialization, when the ISR might fire.
+
+Arguments:
+
+ Irp - pointer to the irp object.
+
+ Name - name of the miniport. Passes to PcRegisterSubDevice
+
+ PortClassId - port class id. Passed to PcNewPort.
+
+ MiniportClassId - miniport class id. Passed to PcNewMiniport.
+
+ MiniportCreate - pointer to a miniport creation function. If NULL,
+ PcNewMiniport is used.
+
+ DeviceContext - deviceType specific.
+
+ MiniportPair - endpoint configuration info.
+
+ ResourceList - pointer to the resource list.
+
+ PortInterfaceId - GUID that represents the port interface.
+
+ OutPortInterface - pointer to store the port interface
+
+ OutPortUnknown - pointer to store the unknown port interface.
+
+ OutMiniportUnknown - pointer to store the unknown miniport interface
+
+Return Value:
+
+ NT status code.
+
+--*/
+ PAGED_CODE();
+ DPF_ENTER(("[InstallSubDevice %S]", Name));
+
+ ASSERT(Name != NULL);
+ ASSERT(m_pDeviceObject != NULL);
+
+ NTSTATUS ntStatus;
+ PPORT port = NULL;
+ PUNKNOWN miniport = NULL;
+ PADAPTERCOMMON adapterCommon = NULL;
+ UNICODE_STRING symbolicLink = { 0 };
+
+ adapterCommon = PADAPTERCOMMON(this);
+
+ ntStatus = CreateAudioInterfaceWithProperties(Name, TemplateName, cPropertyCount, pProperties, &symbolicLink);
+ if (NT_SUCCESS(ntStatus))
+ {
+ // Currently have no use for the symbolic link
+ RtlFreeUnicodeString(&symbolicLink);
+
+ // Create the port driver object
+ //
+ ntStatus = PcNewPort(&port, PortClassId);
+ }
+
+ // Create the miniport object
+ //
+ if (NT_SUCCESS(ntStatus))
+ {
+ if (MiniportCreate)
+ {
+ ntStatus =
+ MiniportCreate
+ (
+ &miniport,
+ MiniportClassId,
+ NULL,
+ POOL_FLAG_NON_PAGED,
+ adapterCommon,
+ DeviceContext,
+ MiniportPair
+ );
+ }
+ else
+ {
+ ntStatus =
+ PcNewMiniport
+ (
+ (PMINIPORT *) &miniport,
+ MiniportClassId
+ );
+ }
+ }
+
+ // Init the port driver and miniport in one go.
+ //
+ if (NT_SUCCESS(ntStatus))
+ {
+#pragma warning(push)
+ // IPort::Init's annotation on ResourceList requires it to be non-NULL. However,
+ // for dynamic devices, we may no longer have the resource list and this should
+ // still succeed.
+ //
+#pragma warning(disable:6387)
+ ntStatus =
+ port->Init
+ (
+ m_pDeviceObject,
+ Irp,
+ miniport,
+ adapterCommon,
+ ResourceList
+ );
+#pragma warning (pop)
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ // Register the subdevice (port/miniport combination).
+ //
+ ntStatus =
+ PcRegisterSubdevice
+ (
+ m_pDeviceObject,
+ Name,
+ port
+ );
+ }
+ }
+
+ // Deposit the port interfaces if it's needed.
+ //
+ if (NT_SUCCESS(ntStatus))
+ {
+ if (OutPortUnknown)
+ {
+ ntStatus =
+ port->QueryInterface
+ (
+ IID_IUnknown,
+ (PVOID *)OutPortUnknown
+ );
+ }
+
+ if (OutPortInterface)
+ {
+ ntStatus =
+ port->QueryInterface
+ (
+ PortInterfaceId,
+ (PVOID *) OutPortInterface
+ );
+ }
+
+ if (OutMiniportUnknown)
+ {
+ ntStatus =
+ miniport->QueryInterface
+ (
+ IID_IUnknown,
+ (PVOID *)OutMiniportUnknown
+ );
+ }
+
+ }
+
+ if (port)
+ {
+ port->Release();
+ }
+
+ if (miniport)
+ {
+ miniport->Release();
+ }
+
+ return ntStatus;
+} // InstallSubDevice
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(NTSTATUS)
+CAdapterCommon::UnregisterSubdevice
+(
+ _In_opt_ PUNKNOWN UnknownPort
+)
+/*++
+
+Routine Description:
+
+ Unregisters and releases the specified subdevice.
+
+Arguments:
+
+ UnknownPort - Wave or topology port interface.
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::UnregisterSubdevice]"));
+
+ ASSERT(m_pDeviceObject != NULL);
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ PUNREGISTERSUBDEVICE unregisterSubdevice = NULL;
+
+ if (NULL == UnknownPort)
+ {
+ return ntStatus;
+ }
+
+ //
+ // Get the IUnregisterSubdevice interface.
+ //
+ ntStatus = UnknownPort->QueryInterface(
+ IID_IUnregisterSubdevice,
+ (PVOID *)&unregisterSubdevice);
+
+ //
+ // Unregister the port object.
+ //
+ if (NT_SUCCESS(ntStatus))
+ {
+ ntStatus = unregisterSubdevice->UnregisterSubdevice(
+ m_pDeviceObject,
+ UnknownPort);
+
+ //
+ // Release the IUnregisterSubdevice interface.
+ //
+ unregisterSubdevice->Release();
+ }
+
+ return ntStatus;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(NTSTATUS)
+CAdapterCommon::ConnectTopologies
+(
+ _In_ PUNKNOWN UnknownTopology,
+ _In_ PUNKNOWN UnknownWave,
+ _In_ PHYSICALCONNECTIONTABLE* PhysicalConnections,
+ _In_ ULONG PhysicalConnectionCount
+)
+/*++
+
+Routine Description:
+
+ Connects the bridge pins between the wave and mixer topologies.
+
+Arguments:
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::ConnectTopologies]"));
+
+ ASSERT(m_pDeviceObject != NULL);
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ //
+ // register wave <=> topology connections
+ // This will connect bridge pins of wave and topology
+ // miniports.
+ //
+ for (ULONG i = 0; i < PhysicalConnectionCount && NT_SUCCESS(ntStatus); i++)
+ {
+
+ switch(PhysicalConnections[i].eType)
+ {
+ case CONNECTIONTYPE_TOPOLOGY_OUTPUT:
+ ntStatus =
+ PcRegisterPhysicalConnection
+ (
+ m_pDeviceObject,
+ UnknownTopology,
+ PhysicalConnections[i].ulTopology,
+ UnknownWave,
+ PhysicalConnections[i].ulWave
+ );
+ if (!NT_SUCCESS(ntStatus))
+ {
+ DPF(D_TERSE, ("ConnectTopologies: PcRegisterPhysicalConnection(render) failed, 0x%x", ntStatus));
+ }
+ break;
+ case CONNECTIONTYPE_WAVE_OUTPUT:
+ ntStatus =
+ PcRegisterPhysicalConnection
+ (
+ m_pDeviceObject,
+ UnknownWave,
+ PhysicalConnections[i].ulWave,
+ UnknownTopology,
+ PhysicalConnections[i].ulTopology
+ );
+ if (!NT_SUCCESS(ntStatus))
+ {
+ DPF(D_TERSE, ("ConnectTopologies: PcRegisterPhysicalConnection(capture) failed, 0x%x", ntStatus));
+ }
+ break;
+ }
+ }
+
+ //
+ // Cleanup in case of error.
+ //
+ if (!NT_SUCCESS(ntStatus))
+ {
+ // disconnect all connections on error, ignore error code because not all
+ // connections may have been made
+ DisconnectTopologies(UnknownTopology, UnknownWave, PhysicalConnections, PhysicalConnectionCount);
+ }
+
+ return ntStatus;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(NTSTATUS)
+CAdapterCommon::DisconnectTopologies
+(
+ _In_ PUNKNOWN UnknownTopology,
+ _In_ PUNKNOWN UnknownWave,
+ _In_ PHYSICALCONNECTIONTABLE* PhysicalConnections,
+ _In_ ULONG PhysicalConnectionCount
+)
+/*++
+
+Routine Description:
+
+ Disconnects the bridge pins between the wave and mixer topologies.
+
+Arguments:
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::DisconnectTopologies]"));
+
+ ASSERT(m_pDeviceObject != NULL);
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ NTSTATUS ntStatus2 = STATUS_SUCCESS;
+ PUNREGISTERPHYSICALCONNECTION unregisterPhysicalConnection = NULL;
+
+ //
+ // Get the IUnregisterPhysicalConnection interface
+ //
+ ntStatus = UnknownTopology->QueryInterface(
+ IID_IUnregisterPhysicalConnection,
+ (PVOID *)&unregisterPhysicalConnection);
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ for (ULONG i = 0; i < PhysicalConnectionCount; i++)
+ {
+ switch(PhysicalConnections[i].eType)
+ {
+ case CONNECTIONTYPE_TOPOLOGY_OUTPUT:
+ ntStatus =
+ unregisterPhysicalConnection->UnregisterPhysicalConnection(
+ m_pDeviceObject,
+ UnknownTopology,
+ PhysicalConnections[i].ulTopology,
+ UnknownWave,
+ PhysicalConnections[i].ulWave
+ );
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ DPF(D_TERSE, ("DisconnectTopologies: UnregisterPhysicalConnection(render) failed, 0x%x", ntStatus));
+ }
+ break;
+ case CONNECTIONTYPE_WAVE_OUTPUT:
+ ntStatus =
+ unregisterPhysicalConnection->UnregisterPhysicalConnection(
+ m_pDeviceObject,
+ UnknownWave,
+ PhysicalConnections[i].ulWave,
+ UnknownTopology,
+ PhysicalConnections[i].ulTopology
+ );
+ if (!NT_SUCCESS(ntStatus2))
+ {
+ DPF(D_TERSE, ("DisconnectTopologies: UnregisterPhysicalConnection(capture) failed, 0x%x", ntStatus2));
+ }
+ break;
+ }
+
+ // cache and return the first error encountered, as it's likely the most relevent
+ if (NT_SUCCESS(ntStatus))
+ {
+ ntStatus = ntStatus2;
+ }
+ }
+ }
+
+ //
+ // Release the IUnregisterPhysicalConnection interface.
+ //
+ SAFE_RELEASE(unregisterPhysicalConnection);
+
+ return ntStatus;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CAdapterCommon::GetCachedSubdevice
+(
+ _In_ PWSTR Name,
+ _Out_opt_ PUNKNOWN *OutUnknownPort,
+ _Out_opt_ PUNKNOWN *OutUnknownMiniport
+)
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::GetCachedSubdevice]"));
+
+ // search list, return interface to device if found, fail if not found
+ PLIST_ENTRY le = NULL;
+ BOOL bFound = FALSE;
+
+ for (le = m_SubdeviceCache.Flink; le != &m_SubdeviceCache && !bFound; le = le->Flink)
+ {
+ MINIPAIR_UNKNOWN *pRecord = CONTAINING_RECORD(le, MINIPAIR_UNKNOWN, ListEntry);
+
+ if (0 == wcscmp(Name, pRecord->Name))
+ {
+ if (OutUnknownPort)
+ {
+ *OutUnknownPort = pRecord->PortInterface;
+ (*OutUnknownPort)->AddRef();
+ }
+
+ if (OutUnknownMiniport)
+ {
+ *OutUnknownMiniport = pRecord->MiniportInterface;
+ (*OutUnknownMiniport)->AddRef();
+ }
+
+ bFound = TRUE;
+ }
+ }
+
+ return bFound?STATUS_SUCCESS:STATUS_OBJECT_NAME_NOT_FOUND;
+}
+
+
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CAdapterCommon::CacheSubdevice
+(
+ _In_ PWSTR Name,
+ _In_ PUNKNOWN UnknownPort,
+ _In_ PUNKNOWN UnknownMiniport
+)
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::CacheSubdevice]"));
+
+ // add the item with this name/interface to the list
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ MINIPAIR_UNKNOWN *pNewSubdevice = NULL;
+
+ pNewSubdevice = new(POOL_FLAG_NON_PAGED, MINADAPTER_POOLTAG) MINIPAIR_UNKNOWN;
+
+ if (!pNewSubdevice)
+ {
+ DPF(D_TERSE, ("Insufficient memory to cache subdevice"));
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ memset(pNewSubdevice, 0, sizeof(MINIPAIR_UNKNOWN));
+
+ ntStatus = RtlStringCchCopyW(pNewSubdevice->Name, SIZEOF_ARRAY(pNewSubdevice->Name), Name);
+ }
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ pNewSubdevice->PortInterface = UnknownPort;
+ pNewSubdevice->PortInterface->AddRef();
+
+ pNewSubdevice->MiniportInterface = UnknownMiniport;
+ pNewSubdevice->MiniportInterface->AddRef();
+
+ // cache the IAdapterPowerManagement interface (if available) from the filter. Some endpoints,
+ // like FM and cellular, have their own power requirements that we must track. If this fails,
+ // it just means this filter doesn't do power management.
+ UnknownMiniport->QueryInterface(IID_IAdapterPowerManagement, (PVOID *)&(pNewSubdevice->PowerInterface));
+
+ InsertTailList(&m_SubdeviceCache, &pNewSubdevice->ListEntry);
+ }
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ if (pNewSubdevice)
+ {
+ delete pNewSubdevice;
+ }
+ }
+
+ return ntStatus;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CAdapterCommon::RemoveCachedSubdevice
+(
+ _In_ PWSTR Name
+)
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::RemoveCachedSubdevice]"));
+
+ // search list, remove the entry from the list
+
+ PLIST_ENTRY le = NULL;
+ BOOL bRemoved = FALSE;
+
+ for (le = m_SubdeviceCache.Flink; le != &m_SubdeviceCache && !bRemoved; le = le->Flink)
+ {
+ MINIPAIR_UNKNOWN *pRecord = CONTAINING_RECORD(le, MINIPAIR_UNKNOWN, ListEntry);
+
+ if (0 == wcscmp(Name, pRecord->Name))
+ {
+ SAFE_RELEASE(pRecord->PortInterface);
+ SAFE_RELEASE(pRecord->MiniportInterface);
+ SAFE_RELEASE(pRecord->PowerInterface);
+ memset(pRecord->Name, 0, sizeof(pRecord->Name));
+ RemoveEntryList(le);
+ bRemoved = TRUE;
+ delete pRecord;
+ break;
+ }
+ }
+
+ return bRemoved?STATUS_SUCCESS:STATUS_OBJECT_NAME_NOT_FOUND;
+}
+
+#pragma code_seg("PAGE")
+VOID
+CAdapterCommon::EmptySubdeviceCache()
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::EmptySubdeviceCache]"));
+
+ while (!IsListEmpty(&m_SubdeviceCache))
+ {
+ PLIST_ENTRY le = RemoveHeadList(&m_SubdeviceCache);
+ MINIPAIR_UNKNOWN *pRecord = CONTAINING_RECORD(le, MINIPAIR_UNKNOWN, ListEntry);
+
+ SAFE_RELEASE(pRecord->PortInterface);
+ SAFE_RELEASE(pRecord->MiniportInterface);
+ SAFE_RELEASE(pRecord->PowerInterface);
+ memset(pRecord->Name, 0, sizeof(pRecord->Name));
+
+ delete pRecord;
+ }
+}
+
+#pragma code_seg("PAGE")
+VOID
+CAdapterCommon::Cleanup()
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::Cleanup]"));
+ EmptySubdeviceCache();
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(NTSTATUS)
+CAdapterCommon::InstallEndpointFilters
+(
+ _In_opt_ PIRP Irp,
+ _In_ PENDPOINT_MINIPAIR MiniportPair,
+ _In_opt_ PVOID DeviceContext,
+ _Out_opt_ PUNKNOWN * UnknownTopology,
+ _Out_opt_ PUNKNOWN * UnknownWave,
+ _Out_opt_ PUNKNOWN * UnknownMiniportTopology,
+ _Out_opt_ PUNKNOWN * UnknownMiniportWave
+)
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::InstallEndpointFilters]"));
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ PUNKNOWN unknownTopology = NULL;
+ PUNKNOWN unknownWave = NULL;
+ BOOL bTopologyCreated = FALSE;
+ BOOL bWaveCreated = FALSE;
+ PUNKNOWN unknownMiniTopo = NULL;
+ PUNKNOWN unknownMiniWave = NULL;
+
+ // Initialize output optional parameters if needed
+ if (UnknownTopology)
+ {
+ *UnknownTopology = NULL;
+ }
+
+ if (UnknownWave)
+ {
+ *UnknownWave = NULL;
+ }
+
+ if (UnknownMiniportTopology)
+ {
+ *UnknownMiniportTopology = NULL;
+ }
+
+ if (UnknownMiniportWave)
+ {
+ *UnknownMiniportWave = NULL;
+ }
+
+ ntStatus = GetCachedSubdevice(MiniportPair->TopoName, &unknownTopology, &unknownMiniTopo);
+ if (!NT_SUCCESS(ntStatus) || NULL == unknownTopology || NULL == unknownMiniTopo)
+ {
+ bTopologyCreated = TRUE;
+
+ // Install Simple Audio Sample topology miniport for the render endpoint.
+ //
+ ntStatus = InstallSubdevice(Irp,
+ MiniportPair->TopoName, // make sure this name matches with SIMPLEAUDIOSAMPLE.<TopoName>.szPname in the inf's [Strings] section
+ MiniportPair->TemplateTopoName,
+ CLSID_PortTopology,
+ CLSID_PortTopology,
+ MiniportPair->TopoCreateCallback,
+ MiniportPair->TopoInterfacePropertyCount,
+ MiniportPair->TopoInterfaceProperties,
+ DeviceContext,
+ MiniportPair,
+ NULL,
+ IID_IPortTopology,
+ NULL,
+ &unknownTopology,
+ &unknownMiniTopo
+ );
+ if (NT_SUCCESS(ntStatus))
+ {
+ ntStatus = CacheSubdevice(MiniportPair->TopoName, unknownTopology, unknownMiniTopo);
+ }
+ }
+
+ ntStatus = GetCachedSubdevice(MiniportPair->WaveName, &unknownWave, &unknownMiniWave);
+ if (!NT_SUCCESS(ntStatus) || NULL == unknownWave || NULL == unknownMiniWave)
+ {
+ bWaveCreated = TRUE;
+
+ // Install Simple Audio Sample wave miniport for the render endpoint.
+ //
+ ntStatus = InstallSubdevice(Irp,
+ MiniportPair->WaveName, // make sure this name matches with SIMPLEAUDIOSAMPLE.<WaveName>.szPname in the inf's [Strings] section
+ MiniportPair->TemplateWaveName,
+ CLSID_PortWaveRT,
+ CLSID_PortWaveRT,
+ MiniportPair->WaveCreateCallback,
+ MiniportPair->WaveInterfacePropertyCount,
+ MiniportPair->WaveInterfaceProperties,
+ DeviceContext,
+ MiniportPair,
+ NULL,
+ IID_IPortWaveRT,
+ NULL,
+ &unknownWave,
+ &unknownMiniWave
+ );
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ ntStatus = CacheSubdevice(MiniportPair->WaveName, unknownWave, unknownMiniWave);
+ }
+ }
+
+ if (unknownTopology && unknownWave)
+ {
+ //
+ // register wave <=> topology connections
+ // This will connect bridge pins of wave and topology
+ // miniports.
+ //
+ ntStatus = ConnectTopologies(
+ unknownTopology,
+ unknownWave,
+ MiniportPair->PhysicalConnections,
+ MiniportPair->PhysicalConnectionCount);
+ }
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ //
+ // Set output parameters.
+ //
+ if (UnknownTopology != NULL && unknownTopology != NULL)
+ {
+ unknownTopology->AddRef();
+ *UnknownTopology = unknownTopology;
+ }
+
+ if (UnknownWave != NULL && unknownWave != NULL)
+ {
+ unknownWave->AddRef();
+ *UnknownWave = unknownWave;
+ }
+ if (UnknownMiniportTopology != NULL && unknownMiniTopo != NULL)
+ {
+ unknownMiniTopo->AddRef();
+ *UnknownMiniportTopology = unknownMiniTopo;
+ }
+
+ if (UnknownMiniportWave != NULL && unknownMiniWave != NULL)
+ {
+ unknownMiniWave->AddRef();
+ *UnknownMiniportWave = unknownMiniWave;
+ }
+
+ }
+ else
+ {
+ if (bTopologyCreated && unknownTopology != NULL)
+ {
+ UnregisterSubdevice(unknownTopology);
+ RemoveCachedSubdevice(MiniportPair->TopoName);
+ }
+
+ if (bWaveCreated && unknownWave != NULL)
+ {
+ UnregisterSubdevice(unknownWave);
+ RemoveCachedSubdevice(MiniportPair->WaveName);
+ }
+ }
+
+ SAFE_RELEASE(unknownMiniTopo);
+ SAFE_RELEASE(unknownTopology);
+ SAFE_RELEASE(unknownMiniWave);
+ SAFE_RELEASE(unknownWave);
+
+ return ntStatus;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(NTSTATUS)
+CAdapterCommon::RemoveEndpointFilters
+(
+ _In_ PENDPOINT_MINIPAIR MiniportPair,
+ _In_opt_ PUNKNOWN UnknownTopology,
+ _In_opt_ PUNKNOWN UnknownWave
+)
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::RemoveEndpointFilters]"));
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ if (UnknownTopology != NULL && UnknownWave != NULL)
+ {
+ ntStatus = DisconnectTopologies(
+ UnknownTopology,
+ UnknownWave,
+ MiniportPair->PhysicalConnections,
+ MiniportPair->PhysicalConnectionCount);
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ DPF(D_VERBOSE, ("RemoveEndpointFilters: DisconnectTopologies failed: 0x%x", ntStatus));
+ }
+ }
+
+
+ RemoveCachedSubdevice(MiniportPair->WaveName);
+
+ ntStatus = UnregisterSubdevice(UnknownWave);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ DPF(D_VERBOSE, ("RemoveEndpointFilters: UnregisterSubdevice(wave) failed: 0x%x", ntStatus));
+ }
+
+ RemoveCachedSubdevice(MiniportPair->TopoName);
+
+ ntStatus = UnregisterSubdevice(UnknownTopology);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ DPF(D_VERBOSE, ("RemoveEndpointFilters: UnregisterSubdevice(topology) failed: 0x%x", ntStatus));
+ }
+
+ //
+ // All Done.
+ //
+ ntStatus = STATUS_SUCCESS;
+
+ return ntStatus;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(NTSTATUS)
+CAdapterCommon::GetFilters
+(
+ _In_ PENDPOINT_MINIPAIR MiniportPair,
+ _Out_opt_ PUNKNOWN * UnknownTopologyPort,
+ _Out_opt_ PUNKNOWN * UnknownTopologyMiniport,
+ _Out_opt_ PUNKNOWN * UnknownWavePort,
+ _Out_opt_ PUNKNOWN * UnknownWaveMiniport
+)
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::GetFilters]"));
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ PUNKNOWN unknownTopologyPort = NULL;
+ PUNKNOWN unknownTopologyMiniport = NULL;
+ PUNKNOWN unknownWavePort = NULL;
+ PUNKNOWN unknownWaveMiniport = NULL;
+
+ // if the client requested the topology filter, find it and return it
+ if (UnknownTopologyPort != NULL || UnknownTopologyMiniport != NULL)
+ {
+ ntStatus = GetCachedSubdevice(MiniportPair->TopoName, &unknownTopologyPort, &unknownTopologyMiniport);
+ if (NT_SUCCESS(ntStatus))
+ {
+ if (UnknownTopologyPort)
+ {
+ *UnknownTopologyPort = unknownTopologyPort;
+ }
+
+ if (UnknownTopologyMiniport)
+ {
+ *UnknownTopologyMiniport = unknownTopologyMiniport;
+ }
+ }
+ }
+
+ // if the client requested the wave filter, find it and return it
+ if (NT_SUCCESS(ntStatus) && (UnknownWavePort != NULL || UnknownWaveMiniport != NULL))
+ {
+ ntStatus = GetCachedSubdevice(MiniportPair->WaveName, &unknownWavePort, &unknownWaveMiniport);
+ if (NT_SUCCESS(ntStatus))
+ {
+ if (UnknownWavePort)
+ {
+ *UnknownWavePort = unknownWavePort;
+ }
+
+ if (UnknownWaveMiniport)
+ {
+ *UnknownWaveMiniport = unknownWaveMiniport;
+ }
+ }
+ }
+
+ return ntStatus;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(NTSTATUS)
+CAdapterCommon::SetIdlePowerManagement
+(
+ _In_ PENDPOINT_MINIPAIR MiniportPair,
+ _In_ BOOL bEnabled
+)
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::SetIdlePowerManagement]"));
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ IUnknown *pUnknown = NULL;
+ PPORTCLSPOWER pPortClsPower = NULL;
+ // refcounting disable requests. Each miniport is responsible for calling this in pairs,
+ // disable on the first request to disable, enable on the last request to enable.
+
+ // make sure that we always call SetIdlePowerManagment using the IPortClsPower
+ // from the requesting port, so we don't cache a reference to a port
+ // indefinitely, preventing it from ever unloading.
+ ntStatus = GetFilters(MiniportPair, NULL, NULL, &pUnknown, NULL);
+ if (NT_SUCCESS(ntStatus))
+ {
+ ntStatus =
+ pUnknown->QueryInterface
+ (
+ IID_IPortClsPower,
+ (PVOID*) &pPortClsPower
+ );
+ }
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ if (bEnabled)
+ {
+ m_dwIdleRequests--;
+
+ if (0 == m_dwIdleRequests)
+ {
+ pPortClsPower->SetIdlePowerManagement(m_pDeviceObject, TRUE);
+ }
+ }
+ else
+ {
+ if (0 == m_dwIdleRequests)
+ {
+ pPortClsPower->SetIdlePowerManagement(m_pDeviceObject, FALSE);
+ }
+
+ m_dwIdleRequests++;
+ }
+ }
+
+ SAFE_RELEASE(pUnknown);
+ SAFE_RELEASE(pPortClsPower);
+
+ return ntStatus;
+}
+
+#pragma code_seg("PAGE")
+NTSTATUS
+CopyRegistryValues(HANDLE _hSourceKey, HANDLE _hDestinationKey)
+/*++
+
+Routine Description:
+
+ This method copies the registry values in _hSourceKey to _hDestinationKey.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ PKEY_VALUE_FULL_INFORMATION kvFullInfo = NULL;
+ ULONG ulFullInfoLength = 0;
+ ULONG ulFullInfoResultLength = 0;
+ PWSTR pwstrKeyValueName = NULL;
+ UNICODE_STRING strKeyValueName;
+ PAGED_CODE();
+ // Allocate the KEY_VALUE_FULL_INFORMATION structure
+ ulFullInfoLength = sizeof(KEY_VALUE_FULL_INFORMATION) + MAX_DEVICE_REG_KEY_LENGTH;
+ kvFullInfo = (PKEY_VALUE_FULL_INFORMATION)ExAllocatePool2(POOL_FLAG_NON_PAGED, ulFullInfoLength, MINADAPTER_POOLTAG);
+ IF_TRUE_ACTION_JUMP(kvFullInfo == NULL, ntStatus = STATUS_INSUFFICIENT_RESOURCES, Exit);
+
+ // Iterate over each value and copy it to the destination
+ for (UINT i = 0; NT_SUCCESS(ntStatus); i++)
+ {
+ // Enumerate the next value
+ ntStatus = ZwEnumerateValueKey(_hSourceKey, i, KeyValueFullInformation, kvFullInfo, ulFullInfoLength, &ulFullInfoResultLength);
+
+ // Jump out of this loop if there are no more values
+ IF_TRUE_ACTION_JUMP(ntStatus == STATUS_NO_MORE_ENTRIES, ntStatus = STATUS_SUCCESS, Exit);
+
+ // Handle incorrect buffer size
+ if (ntStatus == STATUS_BUFFER_TOO_SMALL || ntStatus == STATUS_BUFFER_OVERFLOW)
+ {
+ // Free and re-allocate the KEY_VALUE_FULL_INFORMATION structure with the correct size
+ ExFreePoolWithTag(kvFullInfo, MINADAPTER_POOLTAG);
+
+ ulFullInfoLength = ulFullInfoResultLength;
+
+ kvFullInfo = (PKEY_VALUE_FULL_INFORMATION)ExAllocatePool2(POOL_FLAG_NON_PAGED, ulFullInfoLength, MINADAPTER_POOLTAG);
+ IF_TRUE_ACTION_JUMP(kvFullInfo == NULL, ntStatus = STATUS_INSUFFICIENT_RESOURCES, loop_exit);
+
+ // Try to enumerate the current value again
+ ntStatus = ZwEnumerateValueKey(_hSourceKey, i, KeyValueFullInformation, kvFullInfo, ulFullInfoLength, &ulFullInfoResultLength);
+
+ // Jump out of this loop if there are no more values
+ IF_TRUE_ACTION_JUMP(ntStatus == STATUS_NO_MORE_ENTRIES, ntStatus = STATUS_SUCCESS, Exit);
+ IF_FAILED_JUMP(ntStatus, loop_exit);
+ }
+ else
+ {
+ IF_FAILED_JUMP(ntStatus, loop_exit);
+ }
+
+ // Allocate the key value name string
+ pwstrKeyValueName = (PWSTR)ExAllocatePool2(POOL_FLAG_NON_PAGED, kvFullInfo->NameLength + sizeof(WCHAR)*2, MINADAPTER_POOLTAG);
+ IF_TRUE_ACTION_JUMP(kvFullInfo == NULL, ntStatus = STATUS_INSUFFICIENT_RESOURCES, loop_exit);
+
+ // Copy the key value name from the full information struct
+ RtlStringCbCopyNW(pwstrKeyValueName, kvFullInfo->NameLength + sizeof(WCHAR)*2, kvFullInfo->Name, kvFullInfo->NameLength);
+
+ // Make sure the string is null terminated
+ pwstrKeyValueName[(kvFullInfo->NameLength) / sizeof(WCHAR)] = 0;
+
+ // Copy the key value name string to a UNICODE string
+ RtlInitUnicodeString(&strKeyValueName, pwstrKeyValueName);
+
+ // Write the key value from the source into the destination
+ ntStatus = ZwSetValueKey(_hDestinationKey, &strKeyValueName, 0, kvFullInfo->Type, (PVOID)((PUCHAR)kvFullInfo + kvFullInfo->DataOffset), kvFullInfo->DataLength);
+ IF_FAILED_JUMP(ntStatus, loop_exit);
+
+ loop_exit:
+ // Free the key value name string
+ if (pwstrKeyValueName)
+ {
+ ExFreePoolWithTag(pwstrKeyValueName, MINADAPTER_POOLTAG);
+ }
+
+ // Bail if anything failed
+ IF_FAILED_JUMP(ntStatus, Exit);
+ }
+
+Exit:
+ // Free the KEY_VALUE_FULL_INFORMATION structure
+ if (kvFullInfo)
+ {
+ ExFreePoolWithTag(kvFullInfo, MINADAPTER_POOLTAG);
+ }
+
+ return ntStatus;
+}
+
+NTSTATUS
+CopyRegistryKey(HANDLE _hSourceKey, HANDLE _hDestinationKey, BOOL _bOverwrite = FALSE)
+/*++
+
+Routine Description:
+
+ This method recursively copies the registry values in _hSourceKey to _hDestinationKey.
+ Set _bOverwrite to indicate whether the first level values are copied or not.
+ Normal use is to set false for the initial call, and then all sub paths will be copied.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
+ PKEY_BASIC_INFORMATION kBasicInfo = NULL;
+ ULONG ulBasicInfoLength = 0;
+ ULONG ulBasicInfoResultLength = 0;
+ ULONG ulDisposition = 0;
+ PWSTR pwstrKeyName = NULL;
+ UNICODE_STRING strKeyName;
+ OBJECT_ATTRIBUTES hCurrentSourceKeyAttributes;
+ OBJECT_ATTRIBUTES hNewDestinationKeyAttributes;
+ HANDLE hCurrentSourceKey = NULL;
+ HANDLE hNewDestinationKey = NULL;
+ PAGED_CODE();
+ // Validate parameters
+ IF_TRUE_ACTION_JUMP(_hSourceKey == nullptr, ntStatus = STATUS_INVALID_PARAMETER, Exit);
+ IF_TRUE_ACTION_JUMP(_hDestinationKey == nullptr, ntStatus = STATUS_INVALID_PARAMETER, Exit);
+
+ // Allocate the KEY_BASIC_INFORMATION structure
+ ulBasicInfoLength = sizeof(KEY_BASIC_INFORMATION) + MAX_DEVICE_REG_KEY_LENGTH;
+ kBasicInfo = (PKEY_BASIC_INFORMATION)ExAllocatePool2(POOL_FLAG_NON_PAGED, ulBasicInfoLength, MINADAPTER_POOLTAG);
+ IF_TRUE_ACTION_JUMP(kBasicInfo == NULL, ntStatus = STATUS_INSUFFICIENT_RESOURCES, Exit);
+
+ ntStatus = STATUS_SUCCESS;
+ // Iterate over each key and copy it
+ for (UINT i = 0; NT_SUCCESS(ntStatus); i++)
+ {
+ // Enumerate the next key
+ ntStatus = ZwEnumerateKey(_hSourceKey, i, KeyBasicInformation, kBasicInfo, ulBasicInfoLength, &ulBasicInfoResultLength);
+
+ // Jump out of this loop if there are no more keys
+ IF_TRUE_ACTION_JUMP(ntStatus == STATUS_NO_MORE_ENTRIES, ntStatus = STATUS_SUCCESS, copy_values);
+
+ // Handle incorrect buffer size
+ if (ntStatus == STATUS_BUFFER_TOO_SMALL || ntStatus == STATUS_BUFFER_OVERFLOW)
+ {
+ // Free and re-allocate the KEY_BASIC_INFORMATION structure with the correct size.
+ ExFreePoolWithTag(kBasicInfo, MINADAPTER_POOLTAG);
+ ulBasicInfoLength = ulBasicInfoResultLength;
+ kBasicInfo = (PKEY_BASIC_INFORMATION)ExAllocatePool2(POOL_FLAG_NON_PAGED, ulBasicInfoLength, MINADAPTER_POOLTAG);
+ IF_TRUE_ACTION_JUMP(kBasicInfo == NULL, ntStatus = STATUS_INSUFFICIENT_RESOURCES, loop_exit);
+
+ // Try to enumerate the current key again.
+ ntStatus = ZwEnumerateKey(_hSourceKey, i, KeyBasicInformation, kBasicInfo, ulBasicInfoLength, &ulBasicInfoResultLength);
+
+ // Jump out of this loop if there are no more keys
+ IF_TRUE_ACTION_JUMP(ntStatus == STATUS_NO_MORE_ENTRIES, ntStatus = STATUS_SUCCESS, copy_values);
+ IF_FAILED_JUMP(ntStatus, loop_exit);
+ }
+ else
+ {
+ IF_FAILED_JUMP(ntStatus, loop_exit);
+ }
+
+ // Allocate the key name string
+ pwstrKeyName = (PWSTR)ExAllocatePool2(POOL_FLAG_NON_PAGED, kBasicInfo->NameLength + sizeof(WCHAR), MINADAPTER_POOLTAG);
+ IF_TRUE_ACTION_JUMP(kBasicInfo == NULL, ntStatus = STATUS_INSUFFICIENT_RESOURCES, loop_exit);
+
+ // Copy the key name from the basic information struct
+ RtlStringCbCopyNW(pwstrKeyName, kBasicInfo->NameLength + sizeof(WCHAR), kBasicInfo->Name, kBasicInfo->NameLength);
+
+ // Make sure the string is null terminated
+ pwstrKeyName[(kBasicInfo->NameLength) / sizeof(WCHAR)] = 0;
+
+ // Copy the key name string to a UNICODE string
+ RtlInitUnicodeString(&strKeyName, pwstrKeyName);
+
+ // Initialize attributes to open the currently enumerated source key
+ InitializeObjectAttributes(&hCurrentSourceKeyAttributes, &strKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, _hSourceKey, NULL);
+
+ // Open the currently enumerated source key
+ ntStatus = ZwOpenKey(&hCurrentSourceKey, KEY_READ, &hCurrentSourceKeyAttributes);
+ IF_FAILED_ACTION_JUMP(ntStatus, ZwClose(hCurrentSourceKey), loop_exit);
+
+ // Initialize attributes to create the new destination key
+ InitializeObjectAttributes(&hNewDestinationKeyAttributes, &strKeyName, OBJ_KERNEL_HANDLE, _hDestinationKey, NULL);
+
+ // Create the key at the destination
+ ntStatus = ZwCreateKey(&hNewDestinationKey, KEY_WRITE, &hNewDestinationKeyAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, &ulDisposition);
+ IF_FAILED_ACTION_JUMP(ntStatus, ZwClose(hCurrentSourceKey), loop_exit);
+
+ // Now copy the contents of the currently enumerated key to the destination
+ ntStatus = CopyRegistryKey(hCurrentSourceKey, hNewDestinationKey, TRUE);
+ IF_FAILED_JUMP(ntStatus, loop_exit);
+
+ loop_exit:
+ // Free the key name string
+ if (pwstrKeyName)
+ {
+ ExFreePoolWithTag(pwstrKeyName, MINADAPTER_POOLTAG);
+ }
+
+ // Close the current source key
+ if (hCurrentSourceKey)
+ {
+ ZwClose(hCurrentSourceKey);
+ }
+
+ // Close the new destination key
+ if (hNewDestinationKey)
+ {
+ ZwClose(hNewDestinationKey);
+ }
+
+ // Bail if anything failed
+ IF_FAILED_JUMP(ntStatus, Exit);
+ }
+
+copy_values:
+ // Copy the values
+ if (_bOverwrite)
+ {
+ ntStatus = CopyRegistryValues(_hSourceKey, _hDestinationKey);
+ IF_FAILED_JUMP(ntStatus, Exit);
+ }
+
+Exit:
+ // Free the basic information structure
+ if (kBasicInfo)
+ {
+ ExFreePoolWithTag(kBasicInfo, MINADAPTER_POOLTAG);
+ }
+ return ntStatus;
+}
+
+
+NTSTATUS CAdapterCommon::MigrateDeviceInterfaceTemplateParameters
+(
+ _In_ PUNICODE_STRING SymbolicLinkName,
+ _In_opt_ PCWSTR TemplateReferenceString
+)
+/*++
+
+Routine Description:
+
+ This method copies all of the properties from the template interface,
+ which is specified in the inf, to the actual interface being used which
+ may be dynamically generated at run time. This allows for a driver
+ to reuse a single inf entry for multiple audio endpoints. The primary
+ purpose for this is to allow for sideband audio endpoints to dynamically
+ generate the reference string at run time, tied to the peripheral connected,
+ while still having a simple static inf entry for setting up apo's or other
+ parameters.
+
+ For example, if you have an interface in your inf defined with reference string
+ "SpeakerWave". At runtime you could generate "SpeakerWave-1234ABCDE", and specify
+ "SpeakerWave" as the template name. When "SpeakerWave-1234ABCDE" is installed
+ we will copy all of the parameters that were specified in the inf for "SpeakerWave"
+ over to "SpeakerWave-1234ABCDE". You simply need to specify "SpeakerWave" as the
+ "TemplateName" in the ENDPOINT_MINIPAIRS.
+
+ By default, the first level of registry keys are not copied. Only the 2nd level and
+ deeper are copied. This way the friendly name and other PNP properties will not
+ be modified, but the EP and FX properties will be copied.
+
+Return Value:
+
+ NT status code.
+
+--*/
+
+{
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ HANDLE hDeviceInterfaceParametersKey(NULL);
+ HANDLE hTemplateDeviceInterfaceParametersKey(NULL);
+ UNICODE_STRING TemplateSymbolicLinkName;
+ UNICODE_STRING referenceString;
+
+ RtlInitUnicodeString(&TemplateSymbolicLinkName, NULL);
+ RtlInitUnicodeString(&referenceString, TemplateReferenceString);
+
+ //
+ // Register an audio interface if not already present for the template interface, so we can access
+ // the registry path. If it's already registered, this simply returns the symbolic link name.
+ // No need to unregister it (there is no mechanism to), and we'll never make it active.
+ //
+ ntStatus = IoRegisterDeviceInterface(
+ GetPhysicalDeviceObject(),
+ &KSCATEGORY_AUDIO,
+ &referenceString,
+ &TemplateSymbolicLinkName);
+
+ // Open the template device interface's registry key path
+ ntStatus = IoOpenDeviceInterfaceRegistryKey(&TemplateSymbolicLinkName, GENERIC_READ, &hTemplateDeviceInterfaceParametersKey);
+ IF_FAILED_JUMP(ntStatus, Exit);
+
+ // Open the new device interface's registry key path that we plan to activate
+ ntStatus = IoOpenDeviceInterfaceRegistryKey(SymbolicLinkName, GENERIC_WRITE, &hDeviceInterfaceParametersKey);
+ IF_FAILED_JUMP(ntStatus, Exit);
+
+ // Copy the template device parameters key to the device interface key
+ ntStatus = CopyRegistryKey(hTemplateDeviceInterfaceParametersKey, hDeviceInterfaceParametersKey);
+ IF_FAILED_JUMP(ntStatus, Exit);
+
+Exit:
+ RtlFreeUnicodeString(&TemplateSymbolicLinkName);
+
+ if (hTemplateDeviceInterfaceParametersKey)
+ {
+ ZwClose(hTemplateDeviceInterfaceParametersKey);
+ }
+
+ if (hDeviceInterfaceParametersKey)
+ {
+ ZwClose(hDeviceInterfaceParametersKey);
+ }
+
+ return ntStatus;
+}
diff --git a/audio/sysvad/PhoneAudioSample/handsetspeakertopo.cpp b/audio/simpleaudiosample/Source/Main/mintopo.cpp
index 161e5bf0..6ab1624f 100644
--- a/audio/sysvad/PhoneAudioSample/handsetspeakertopo.cpp
+++ b/audio/simpleaudiosample/Source/Main/mintopo.cpp
@@ -4,37 +4,29 @@ Copyright (c) Microsoft Corporation All Rights Reserved
Module Name:
- handsetspeakertopo.cpp
+ mintopo.cpp
Abstract:
- Implementation of topology miniport for the handsetspeaker endpoint.
-
+ Implementation of topology miniport.
--*/
#pragma warning (disable : 4127)
-#include <sysvad.h>
-#include "simple.h"
+#include "definitions.h"
+#include "endpoints.h"
+#include "minwavert.h"
#include "mintopo.h"
-#include "handsetspeakertopo.h"
-#include "handsetspeakertoptable.h"
-#include <ntstrsafe.h>
-
-
-#pragma code_seg("PAGE")
//=============================================================================
+#pragma code_seg("PAGE")
NTSTATUS
-CreateHandsetSpeakerMiniportTopology
+CreateMiniportTopologySimpleAudioSample
(
- _Out_ PUNKNOWN * Unknown,
+ _Out_ PUNKNOWN * Unknown,
_In_ REFCLSID,
_In_opt_ PUNKNOWN UnknownOuter,
- _When_((PoolType & NonPagedPoolMustSucceed) != 0,
- __drv_reportError("Must succeed pool allocations are forbidden. "
- "Allocation failures cause a system crash"))
- _In_ POOL_TYPE PoolType,
+ _In_ POOL_FLAGS PoolFlags,
_In_ PUNKNOWN UnknownAdapter,
_In_opt_ PVOID DeviceContext,
_In_ PENDPOINT_MINIPAIR MiniportPair
@@ -51,15 +43,13 @@ Arguments:
RefclsId -
+ PoolType -
+
UnknownOuter -
- PoolType -
-
- UnknownAdapter -
-
- DeviceContext -
-
- MiniportPair -
+ DeviceContext -
+
+ MiniportPair -
Return Value:
@@ -69,17 +59,18 @@ Return Value:
{
PAGED_CODE();
+ UNREFERENCED_PARAMETER(UnknownAdapter);
+
ASSERT(Unknown);
ASSERT(MiniportPair);
- UNREFERENCED_PARAMETER(UnknownAdapter);
- UNREFERENCED_PARAMETER(DeviceContext);
-
- CHandsetSpeakerMiniportTopology *obj =
- new (PoolType, MINWAVERT_POOLTAG)
- CHandsetSpeakerMiniportTopology( UnknownOuter,
- MiniportPair->TopoDescriptor,
- MiniportPair->DeviceMaxChannels);
+ CMiniportTopology *obj =
+ new (PoolFlags, MINWAVERT_POOLTAG)
+ CMiniportTopology( UnknownOuter,
+ MiniportPair->TopoDescriptor,
+ MiniportPair->DeviceMaxChannels,
+ MiniportPair->DeviceType,
+ DeviceContext );
if (NULL == obj)
{
return STATUS_INSUFFICIENT_RESOURCES;
@@ -89,10 +80,11 @@ Return Value:
*Unknown = reinterpret_cast<IUnknown*>(obj);
return STATUS_SUCCESS;
-} // CreateHandsetSpeakerMiniportTopology
+} // CreateMiniportTopologySimpleAudioSample
//=============================================================================
-CHandsetSpeakerMiniportTopology::~CHandsetSpeakerMiniportTopology
+#pragma code_seg("PAGE")
+CMiniportTopology::~CMiniportTopology
(
void
)
@@ -112,19 +104,20 @@ Return Value:
{
PAGED_CODE();
- DPF_ENTER(("[CHandsetSpeakerMiniportTopology::~CHandsetSpeakerMiniportTopology]"));
-} // ~CHandsetSpeakerMiniportTopology
+ DPF_ENTER(("[CMiniportTopology::~CMiniportTopology]"));
+} // ~CMiniportTopology
//=============================================================================
+#pragma code_seg("PAGE")
NTSTATUS
-CHandsetSpeakerMiniportTopology::DataRangeIntersection
+CMiniportTopology::DataRangeIntersection
(
_In_ ULONG PinId,
_In_ PKSDATARANGE ClientDataRange,
_In_ PKSDATARANGE MyDataRange,
_In_ ULONG OutputBufferLength,
_Out_writes_bytes_to_opt_(OutputBufferLength, *ResultantFormatLength)
- PVOID ResultantFormat OPTIONAL,
+ PVOID ResultantFormat,
_Out_ PULONG ResultantFormatLength
)
/*++
@@ -163,7 +156,7 @@ Return Value:
PAGED_CODE();
return
- CMiniportTopologySYSVAD::DataRangeIntersection
+ CMiniportTopologySimpleAudioSample::DataRangeIntersection
(
PinId,
ClientDataRange,
@@ -175,8 +168,9 @@ Return Value:
} // DataRangeIntersection
//=============================================================================
+#pragma code_seg("PAGE")
STDMETHODIMP
-CHandsetSpeakerMiniportTopology::GetDescription
+CMiniportTopology::GetDescription
(
_Out_ PPCFILTER_DESCRIPTOR * OutFilterDescriptor
)
@@ -203,12 +197,13 @@ Return Value:
ASSERT(OutFilterDescriptor);
- return CMiniportTopologySYSVAD::GetDescription(OutFilterDescriptor);
+ return CMiniportTopologySimpleAudioSample::GetDescription(OutFilterDescriptor);
} // GetDescription
//=============================================================================
+#pragma code_seg("PAGE")
STDMETHODIMP
-CHandsetSpeakerMiniportTopology::Init
+CMiniportTopology::Init
(
_In_ PUNKNOWN UnknownAdapter,
_In_ PRESOURCELIST ResourceList,
@@ -239,32 +234,39 @@ Return Value:
--*/
{
UNREFERENCED_PARAMETER(ResourceList);
-
+
PAGED_CODE();
ASSERT(UnknownAdapter);
ASSERT(Port_);
- DPF_ENTER(("[CHandsetSpeakerMiniportTopology::Init]"));
+ DPF_ENTER(("[CMiniportTopology::Init]"));
NTSTATUS ntStatus;
ntStatus =
- CMiniportTopologySYSVAD::Init
+ CMiniportTopologySimpleAudioSample::Init
(
UnknownAdapter,
Port_
);
+ IF_FAILED_ACTION_JUMP(
+ ntStatus,
+ DPF(D_ERROR, ("Init: CMiniportTopologySimpleAudioSample::Init failed, 0x%x", ntStatus)),
+ Done);
+
+Done:
return ntStatus;
} // Init
//=============================================================================
+#pragma code_seg("PAGE")
STDMETHODIMP
-CHandsetSpeakerMiniportTopology::NonDelegatingQueryInterface
+CMiniportTopology::NonDelegatingQueryInterface
(
- _In_ REFIID Interface,
- _COM_Outptr_ PVOID * Object
+ _In_ REFIID Interface,
+ _COM_Outptr_ PVOID * Object
)
/*++
@@ -316,10 +318,13 @@ Return Value:
} // NonDelegatingQueryInterface
//=============================================================================
+#pragma code_seg("PAGE")
NTSTATUS
-CHandsetSpeakerMiniportTopology::PropertyHandlerJackDescription
+CMiniportTopology::PropertyHandlerJackDescription
(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG cJackDescriptions,
+ _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION * JackDescriptions
)
/*++
@@ -329,7 +334,9 @@ Routine Description:
Arguments:
- PropertyRequest
+ PropertyRequest -
+ cJackDescriptions - # of elements in the jack descriptions array.
+ JackDescriptions - Array of jack descriptions pointers.
Return Value:
@@ -343,12 +350,9 @@ Return Value:
DPF_ENTER(("[PropertyHandlerJackDescription]"));
- ULONG cJackDescriptions = ARRAYSIZE(HandsetSpeakerJackDescriptions);
- PKSJACK_DESCRIPTION * JackDescriptions = HandsetSpeakerJackDescriptions;
-
NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
ULONG nPinId = (ULONG)-1;
-
+
if (PropertyRequest->InstanceSize >= sizeof(ULONG))
{
nPinId = *(PULONG(PropertyRequest->Instance));
@@ -400,10 +404,14 @@ Return Value:
}
//=============================================================================
+#pragma code_seg("PAGE")
NTSTATUS
-CHandsetSpeakerMiniportTopology::PropertyHandlerJackDescription2
+CMiniportTopology::PropertyHandlerJackDescription2
(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG cJackDescriptions,
+ _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION * JackDescriptions,
+ _In_ DWORD JackCapabilities
)
/*++
@@ -413,7 +421,10 @@ Routine Description:
Arguments:
- PropertyRequest -
+ PropertyRequest -
+ cJackDescriptions - # of elements in the jack descriptions array.
+ JackDescriptions - Array of jack descriptions pointers.
+ JackCapabilities - Jack capabilities flags.
Return Value:
@@ -427,11 +438,8 @@ Return Value:
DPF_ENTER(("[PropertyHandlerJackDescription2]"));
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
- ULONG nPinId = (ULONG)-1;
-
- ULONG cJackDescriptions = ARRAYSIZE(HandsetSpeakerJackDescriptions);
- PKSJACK_DESCRIPTION * JackDescriptions = HandsetSpeakerJackDescriptions;
+ NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+ ULONG nPinId = (ULONG)-1;
if (PropertyRequest->InstanceSize >= sizeof(ULONG))
{
@@ -496,8 +504,8 @@ Return Value:
// 0x00000001 - JACKDESC2_PRESENCE_DETECT_CAPABILITY
// 0x00000002 - JACKDESC2_DYNAMIC_FORMAT_CHANGE_CAPABILITY
//
- pDesc->JackCapabilities = 0;
-
+ pDesc->JackCapabilities = JackCapabilities;
+
ntStatus = STATUS_SUCCESS;
}
}
@@ -509,8 +517,9 @@ Return Value:
}
//=============================================================================
+#pragma code_seg("PAGE")
NTSTATUS
-PropertyHandler_HandsetSpeakerTopoFilter
+PropertyHandler_Topology
(
_In_ PPCPROPERTY_REQUEST PropertyRequest
)
@@ -534,28 +543,15 @@ Return Value:
ASSERT(PropertyRequest);
- DPF_ENTER(("[PropertyHandler_HandsetSpeakerTopoFilter]"));
+ DPF_ENTER(("[PropertyHandler_Topology]"));
// PropertryRequest structure is filled by portcls.
// MajorTarget is a pointer to miniport object for miniports.
//
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
- PCHandsetSpeakerMiniportTopology pMiniport = (PCHandsetSpeakerMiniportTopology)PropertyRequest->MajorTarget;
-
- if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Jack))
- {
- if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION)
- {
- ntStatus = pMiniport->PropertyHandlerJackDescription(PropertyRequest);
- }
- else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION2)
- {
- ntStatus = pMiniport->PropertyHandlerJackDescription2(PropertyRequest);
- }
- }
-
- return ntStatus;
-} // PropertyHandler_HandsetSpeakerTopoFilter
-
-#pragma code_seg()
-
+ return
+ ((PCMiniportTopology)
+ (PropertyRequest->MajorTarget))->PropertyHandlerGeneric
+ (
+ PropertyRequest
+ );
+} // PropertyHandler_Topology
diff --git a/audio/simpleaudiosample/Source/Main/minwavert.cpp b/audio/simpleaudiosample/Source/Main/minwavert.cpp
new file mode 100644
index 00000000..1d92073d
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Main/minwavert.cpp
@@ -0,0 +1,1683 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ minwavert.cpp
+
+Abstract:
+
+ Implementation of wavert miniport.
+--*/
+
+#pragma warning (disable : 4127)
+
+#include "definitions.h"
+#include <limits.h>
+#include "endpoints.h"
+#include "minwavert.h"
+#include "minwavertstream.h"
+#include "micarraywavtable.h"
+
+#define EFFECTS_LIST_COUNT 2
+
+//=============================================================================
+// CMiniportWaveRT
+//=============================================================================
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CreateMiniportWaveRTSimpleAudioSample
+(
+ _Out_ PUNKNOWN * Unknown,
+ _In_ REFCLSID,
+ _In_opt_ PUNKNOWN UnknownOuter,
+ _In_ POOL_FLAGS PoolFlags,
+ _In_ PUNKNOWN UnknownAdapter,
+ _In_opt_ PVOID DeviceContext,
+ _In_ PENDPOINT_MINIPAIR MiniportPair
+)
+/*++
+
+Routine Description:
+
+ Create the wavert miniport.
+
+Arguments:
+
+ Unknown -
+
+ RefClsId -
+
+ UnknownOuter -
+
+ PoolType -
+
+ UnkownAdapter -
+
+ DeviceContext -
+
+ MiniportPair -
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ UNREFERENCED_PARAMETER(UnknownOuter);
+
+ PAGED_CODE();
+
+ ASSERT(Unknown);
+ ASSERT(MiniportPair);
+
+ CMiniportWaveRT *obj = new (PoolFlags, MINWAVERT_POOLTAG) CMiniportWaveRT
+ (
+ UnknownAdapter,
+ MiniportPair,
+ DeviceContext
+ );
+ if (NULL == obj)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ obj->AddRef();
+ *Unknown = reinterpret_cast<IUnknown*>(obj);
+
+ return STATUS_SUCCESS;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+CMiniportWaveRT::~CMiniportWaveRT
+(
+ void
+)
+/*++
+
+Routine Description:
+
+ Destructor for wavert miniport
+
+Arguments:
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMiniportWaveRT::~CMiniportWaveRT]"));
+
+ if (m_pDeviceFormat)
+ {
+ ExFreePoolWithTag( m_pDeviceFormat, MINWAVERT_POOLTAG );
+ m_pDeviceFormat = NULL;
+ }
+
+ if (m_pMixFormat)
+ {
+ ExFreePoolWithTag( m_pMixFormat, MINWAVERT_POOLTAG );
+ m_pMixFormat = NULL;
+ }
+
+ if (m_pbMuted)
+ {
+ ExFreePoolWithTag(m_pbMuted, MINWAVERT_POOLTAG);
+ m_pbMuted = NULL;
+ }
+
+ if (m_plVolumeLevel)
+ {
+ ExFreePoolWithTag(m_plVolumeLevel, MINWAVERT_POOLTAG);
+ m_plVolumeLevel = NULL;
+ }
+
+ if (m_pDrmPort)
+ {
+ m_pDrmPort->Release();
+ m_pDrmPort = NULL;
+ }
+
+ if (m_pPortEvents)
+ {
+ m_pPortEvents->Release();
+ m_pPortEvents = NULL;
+ }
+
+ if (m_SystemStreams)
+ {
+ ExFreePoolWithTag( m_SystemStreams, MINWAVERT_POOLTAG );
+ m_SystemStreams = NULL;
+ }
+
+} // ~CMiniportWaveRT
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(NTSTATUS)
+CMiniportWaveRT::DataRangeIntersection
+(
+ _In_ ULONG PinId,
+ _In_ PKSDATARANGE ClientDataRange,
+ _In_ PKSDATARANGE MyDataRange,
+ _In_ ULONG OutputBufferLength,
+ _Out_writes_bytes_to_opt_(OutputBufferLength, *ResultantFormatLength)
+ PVOID ResultantFormat,
+ _Out_ PULONG ResultantFormatLength
+)
+/*++
+
+Routine Description:
+
+ The DataRangeIntersection function determines the highest quality
+ intersection of two data ranges.
+
+ This sample just sets the ResultantFormat to be the only supported
+ format for the MicArray endpoint.
+
+Arguments:
+
+ PinId - Pin for which data intersection is being determined.
+
+ ClientDataRange - Pointer to KSDATARANGE structure which contains the data
+ range submitted by client in the data range intersection
+ property request.
+
+ MyDataRange - Pin's data range to be compared with client's data
+ range. In this case we actually ignore our own data
+ range, because we know that we only support one range.
+
+ OutputBufferLength - Size of the buffer pointed to by the resultant format
+ parameter.
+
+ ResultantFormat - Pointer to value where the resultant format should be
+ returned.
+
+ ResultantFormatLength - Actual length of the resultant format placed in
+ ResultantFormat. This should be less than or equal
+ to OutputBufferLength.
+
+ Return Value:
+
+ NT status code.
+
+--*/
+{
+ UNREFERENCED_PARAMETER(PinId);
+
+ ULONG requiredSize;
+
+ PAGED_CODE();
+
+ if (!IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX))
+ {
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ //If called for the mic array pin, set ResultantFormat to be the endpoint's only supported format.
+ //Otherwise, allow the class handler to set ResultantFormat.
+ if ((this->m_DeviceType) == eMicArrayDevice1)
+ {
+ requiredSize = sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE);
+
+ //
+ // Validate return buffer size, if the request is only for the
+ // size of the resultant structure, return it now before
+ // returning other types of errors.
+ //
+ if (!OutputBufferLength)
+ {
+ *ResultantFormatLength = requiredSize;
+ return STATUS_BUFFER_OVERFLOW;
+ }
+ else if (OutputBufferLength < requiredSize)
+ {
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ //Set ResultantFormat to be the only supported format for the MicArray endpoint.
+ PKSDATAFORMAT_WAVEFORMATEXTENSIBLE resultantFormat;
+ resultantFormat = (PKSDATAFORMAT_WAVEFORMATEXTENSIBLE)ResultantFormat;
+ *resultantFormat = *MicArrayPinSupportedDeviceFormats;
+ *ResultantFormatLength = requiredSize;
+
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ requiredSize = sizeof(KSDATAFORMAT_WAVEFORMATEX);
+
+ //
+ // Validate return buffer size, if the request is only for the
+ // size of the resultant structure, return it now before
+ // returning other types of errors.
+ //
+ if (!OutputBufferLength)
+ {
+ *ResultantFormatLength = requiredSize;
+ return STATUS_BUFFER_OVERFLOW;
+ }
+ else if (OutputBufferLength < requiredSize)
+ {
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ // Verify channel count is supported. This routine assumes a separate data
+ // range for each supported channel count.
+ if (((PKSDATARANGE_AUDIO)MyDataRange)->MaximumChannels != ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels)
+ {
+ return STATUS_NO_MATCH;
+ }
+
+ //
+ // Ok, let the class handler do the rest.
+ //
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+} // DataRangeIntersection
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(NTSTATUS)
+CMiniportWaveRT::GetDescription
+(
+ _Out_ PPCFILTER_DESCRIPTOR * OutFilterDescriptor
+)
+/*++
+
+Routine Description:
+
+ The GetDescription function gets a pointer to a filter description.
+ It provides a location to deposit a pointer in miniport's description
+ structure.
+
+Arguments:
+
+ OutFilterDescriptor - Pointer to the filter description.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(OutFilterDescriptor);
+
+ *OutFilterDescriptor = &m_FilterDesc;
+
+ return STATUS_SUCCESS;
+} // GetDescription
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(NTSTATUS)
+CMiniportWaveRT::Init
+(
+ _In_ PUNKNOWN UnknownAdapter_,
+ _In_ PRESOURCELIST ResourceList_,
+ _In_ PPORTWAVERT Port_
+)
+/*++
+
+Routine Description:
+
+ The Init function initializes the miniport. Callers of this function
+ should run at IRQL PASSIVE_LEVEL
+
+Arguments:
+
+ UnknownAdapter - A pointer to the Iuknown interface of the adapter object.
+
+ ResourceList - Pointer to the resource list to be supplied to the miniport
+ during initialization. The port driver is free to examine the
+ contents of the ResourceList. The port driver will not be
+ modify the ResourceList contents.
+
+ Port - Pointer to the topology port object that is linked with this miniport.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ UNREFERENCED_PARAMETER(UnknownAdapter_);
+ UNREFERENCED_PARAMETER(ResourceList_);
+ UNREFERENCED_PARAMETER(Port_);
+ PAGED_CODE();
+
+ ASSERT(UnknownAdapter_);
+ ASSERT(Port_);
+
+ DPF_ENTER(("[CMiniportWaveRT::Init]"));
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ size_t size;
+
+ //
+ // Init class data members
+ //
+ m_ulSystemAllocated = 0;
+ m_SystemStreams = NULL;
+ m_bGfxEnabled = FALSE;
+ m_pMixFormat = NULL;
+ m_pDeviceFormat = NULL;
+ m_ulMixDrmContentId = 0;
+ m_pbMuted = NULL;
+ m_plVolumeLevel = NULL;
+ RtlZeroMemory(&m_MixDrmRights, sizeof(m_MixDrmRights));
+
+ //
+ // Init the audio-engine used by the render devices.
+ //
+ if (IsRenderDevice())
+ {
+ if (m_ulMaxSystemStreams == 0 )
+ {
+ return STATUS_INVALID_DEVICE_STATE;
+ }
+
+ // System streams.
+ size = sizeof(PCMiniportWaveRTStream) * m_ulMaxSystemStreams;
+ m_SystemStreams = (PCMiniportWaveRTStream *)ExAllocatePool2(POOL_FLAG_NON_PAGED, size, MINWAVERT_POOLTAG);
+ if (m_SystemStreams == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // For DRM support.
+ //
+ if (!NT_SUCCESS(Port_->QueryInterface(IID_IDrmPort2, (PVOID *)&m_pDrmPort)))
+ {
+ m_pDrmPort = NULL;
+ }
+ }
+
+ //
+ // For KS event support.
+ //
+ if (!NT_SUCCESS(Port_->QueryInterface(IID_IPortEvents, (PVOID *)&m_pPortEvents)))
+ {
+ m_pPortEvents = NULL;
+ }
+
+ return ntStatus;
+} // Init
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(NTSTATUS)
+CMiniportWaveRT::NewStream
+(
+ _Out_ PMINIPORTWAVERTSTREAM * OutStream,
+ _In_ PPORTWAVERTSTREAM OuterUnknown,
+ _In_ ULONG Pin,
+ _In_ BOOLEAN Capture,
+ _In_ PKSDATAFORMAT DataFormat
+)
+/*++
+
+Routine Description:
+
+ The NewStream function creates a new instance of a logical stream
+ associated with a specified physical channel. Callers of NewStream should
+ run at IRQL PASSIVE_LEVEL.
+
+Arguments:
+
+ OutStream -
+
+ OuterUnknown -
+
+ Pin -
+
+ Capture -
+
+ DataFormat -
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(OutStream);
+ ASSERT(DataFormat);
+
+ DPF_ENTER(("[CMiniportWaveRT::NewStream]"));
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ PCMiniportWaveRTStream stream = NULL;
+ GUID signalProcessingMode = AUDIO_SIGNALPROCESSINGMODE_DEFAULT;
+
+ *OutStream = NULL;
+
+ //
+ // If the data format attributes were specified, extract them.
+ //
+ if ( DataFormat->Flags & KSDATAFORMAT_ATTRIBUTES )
+ {
+ // The attributes are aligned (QWORD alignment) after the data format
+ PKSMULTIPLE_ITEM attributes = (PKSMULTIPLE_ITEM) (((PBYTE)DataFormat) + ((DataFormat->FormatSize + FILE_QUAD_ALIGNMENT) & ~FILE_QUAD_ALIGNMENT));
+ ntStatus = GetAttributesFromAttributeList(attributes, attributes->Size, &signalProcessingMode);
+ }
+
+ // Check if we have enough streams.
+ //
+ if (NT_SUCCESS(ntStatus))
+ {
+ ntStatus = ValidateStreamCreate(Pin, Capture);
+ }
+
+ // Determine if the format is valid.
+ //
+ if (NT_SUCCESS(ntStatus))
+ {
+ ntStatus = IsFormatSupported(Pin, Capture, DataFormat);
+ }
+
+ // Instantiate a stream. Stream must be in
+ // NonPagedPool(Nx) because of file saving.
+ //
+ if (NT_SUCCESS(ntStatus))
+ {
+ stream = new (POOL_FLAG_NON_PAGED, MINWAVERT_POOLTAG)
+ CMiniportWaveRTStream(NULL);
+
+ if (stream)
+ {
+ stream->AddRef();
+
+ ntStatus =
+ stream->Init
+ (
+ this,
+ OuterUnknown,
+ Pin,
+ Capture,
+ DataFormat,
+ signalProcessingMode
+ );
+ }
+ else
+ {
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ *OutStream = PMINIPORTWAVERTSTREAM(stream);
+ (*OutStream)->AddRef();
+
+ // The stream has references now for the caller. The caller expects these
+ // references to be there.
+ }
+
+ // This is our private reference to the stream. The caller has
+ // its own, so we can release in any case.
+ //
+ if (stream)
+ {
+ stream->Release();
+ }
+
+ return ntStatus;
+} // NewStream
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(NTSTATUS)
+CMiniportWaveRT::NonDelegatingQueryInterface
+(
+ _In_ REFIID Interface,
+ _COM_Outptr_ PVOID * Object
+)
+/*++
+
+Routine Description:
+
+ QueryInterface
+
+Arguments:
+
+ Interface - GUID
+
+ Object - interface pointer to be returned.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(Object);
+
+ if (IsEqualGUIDAligned(Interface, IID_IUnknown))
+ {
+ *Object = PVOID(PUNKNOWN(PMINIPORTWAVERT(this)));
+ }
+ else if (IsEqualGUIDAligned(Interface, IID_IMiniport))
+ {
+ *Object = PVOID(PMINIPORT(this));
+ }
+ else if (IsEqualGUIDAligned(Interface, IID_IMiniportWaveRT))
+ {
+ *Object = PVOID(PMINIPORTWAVERT(this));
+ }
+ else if (IsEqualGUIDAligned(Interface, IID_IMiniportAudioSignalProcessing))
+ {
+ *Object = PVOID(PMINIPORTAudioSignalProcessing(this));
+ }
+ else
+ {
+ *Object = NULL;
+ }
+
+ if (*Object)
+ {
+ // We reference the interface for the caller.
+
+ PUNKNOWN(*Object)->AddRef();
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_INVALID_PARAMETER;
+} // NonDelegatingQueryInterface
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(NTSTATUS) CMiniportWaveRT::GetDeviceDescription(_Out_ PDEVICE_DESCRIPTION DmaDeviceDescription)
+{
+ PAGED_CODE ();
+
+ ASSERT (DmaDeviceDescription);
+
+ DPF_ENTER(("[CMiniportWaveRT::GetDeviceDescription]"));
+
+ RtlZeroMemory (DmaDeviceDescription, sizeof (DEVICE_DESCRIPTION));
+
+ //
+ // Init device description. This sample is using the same info for all m_DeviceType(s).
+ //
+
+ DmaDeviceDescription->Master = TRUE;
+ DmaDeviceDescription->ScatterGather = TRUE;
+ DmaDeviceDescription->Dma32BitAddresses = TRUE;
+ DmaDeviceDescription->InterfaceType = PCIBus;
+ DmaDeviceDescription->MaximumLength = 0xFFFFFFFF;
+
+ return STATUS_SUCCESS;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRT::GetModes
+(
+ _In_ ULONG Pin,
+ _Out_writes_opt_(*NumSignalProcessingModes) GUID* SignalProcessingModes,
+ _Inout_ ULONG* NumSignalProcessingModes
+)
+/*
+
+1. If Pin is not a valid pin number,
+ return STATUS_INVALID_PARAMETER.
+
+2. If Pin is a valid pin number and it supports n modes (n>0),
+ init out-parameters and return STATUS_SUCCESS.
+
+3. Else this pin doesn't support any mode,
+ return STATUS_NOT_SUPPORTED.
+ example: bridge pins or another mode-not-aware pins.
+
+*/
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMiniportWaveRT::GetModes]"));
+
+ NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
+ ULONG numModes = 0;
+ MODE_AND_DEFAULT_FORMAT *modeInfo = NULL;
+
+ if (Pin >= m_pMiniportPair->WaveDescriptor->PinCount)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // This method is valid only on the following pins:
+ // render is offload capable:
+ // sink (#0) and offload (#1) pins.
+ // render is NOT offload capable:
+ // sink (#0) pin.
+ // capture device:
+ // source (#1) pin.
+ //
+ numModes = GetPinSupportedDeviceModes(Pin, &modeInfo);
+ if (numModes == 0)
+ {
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ // If caller requests the modes, verify sufficient buffer size then return the modes
+ if (SignalProcessingModes != NULL)
+ {
+ if (*NumSignalProcessingModes < numModes)
+ {
+ *NumSignalProcessingModes = numModes;
+ ntStatus = STATUS_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ for (ULONG i=0; i<numModes; ++i)
+ {
+ SignalProcessingModes[i] = modeInfo[i].Mode;
+ }
+ }
+
+ ASSERT(numModes > 0);
+ *NumSignalProcessingModes = numModes;
+ ntStatus = STATUS_SUCCESS;
+
+Done:
+ return ntStatus;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRT::ValidateStreamCreate
+(
+ _In_ ULONG _Pin,
+ _In_ BOOLEAN _Capture
+)
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMiniportWaveRT::ValidateStreamCreate]"));
+
+ NTSTATUS ntStatus = STATUS_NOT_SUPPORTED;
+
+ if (_Capture)
+ {
+
+ if (IsSystemCapturePin(_Pin))
+ {
+ VERIFY_PIN_INSTANCE_RESOURCES_AVAILABLE(ntStatus, m_ulSystemAllocated, m_ulMaxSystemStreams);
+ }
+
+ }
+ else
+ {
+
+ if (IsSystemRenderPin(_Pin))
+ {
+ VERIFY_PIN_INSTANCE_RESOURCES_AVAILABLE(ntStatus, m_ulSystemAllocated, m_ulMaxSystemStreams);
+ }
+ }
+
+ return ntStatus;
+}
+
+//=============================================================================
+#pragma code_seg()
+_Use_decl_annotations_
+VOID CMiniportWaveRT::AcquireFormatsAndModesLock()
+{
+ KeAcquireSpinLock(&m_DeviceFormatsAndModesLock, &m_DeviceFormatsAndModesIrql);
+}
+
+#pragma code_seg()
+_Use_decl_annotations_
+VOID CMiniportWaveRT::ReleaseFormatsAndModesLock()
+{
+ KeReleaseSpinLock(&m_DeviceFormatsAndModesLock, m_DeviceFormatsAndModesIrql);
+}
+
+//---------------------------------------------------------------------------
+// GetPinSupportedDeviceFormats
+//
+// Return supported formats for a given pin.
+//
+// Return value
+// The number of KSDATAFORMAT_WAVEFORMATEXTENSIBLE items.
+//
+// Remarks
+// Supported formats index array follows same order as filter's pin
+// descriptor list.
+//
+#pragma code_seg()
+_Use_decl_annotations_
+ULONG CMiniportWaveRT::GetPinSupportedDeviceFormats(_In_ ULONG PinId, _Outptr_opt_result_buffer_(return) KSDATAFORMAT_WAVEFORMATEXTENSIBLE **ppFormats)
+{
+ PPIN_DEVICE_FORMATS_AND_MODES pDeviceFormatsAndModes = NULL;
+
+ AcquireFormatsAndModesLock();
+
+ pDeviceFormatsAndModes = m_DeviceFormatsAndModes;
+ ASSERT(m_DeviceFormatsAndModesCount > PinId);
+ ASSERT(pDeviceFormatsAndModes[PinId].WaveFormats != NULL);
+ ASSERT(pDeviceFormatsAndModes[PinId].WaveFormatsCount > 0);
+
+ if (ppFormats != NULL)
+ {
+ *ppFormats = pDeviceFormatsAndModes[PinId].WaveFormats;
+ }
+
+ ReleaseFormatsAndModesLock();
+
+ return pDeviceFormatsAndModes[PinId].WaveFormatsCount;
+}
+
+//---------------------------------------------------------------------------
+// GetPinSupportedDeviceModes
+//
+// Return mode information for a given pin.
+//
+// Return value
+// The number of MODE_AND_DEFAULT_FORMAT items or 0 if none.
+//
+// Remarks
+// Supported formats index array follows same order as filter's pin
+// descriptor list.
+//
+#pragma code_seg()
+_Use_decl_annotations_
+ULONG CMiniportWaveRT::GetPinSupportedDeviceModes(_In_ ULONG PinId, _Outptr_opt_result_buffer_(return) _On_failure_(_Deref_post_null_) MODE_AND_DEFAULT_FORMAT **ppModes)
+{
+ PMODE_AND_DEFAULT_FORMAT modes;
+ ULONG numModes;
+
+ AcquireFormatsAndModesLock();
+
+ ASSERT(m_DeviceFormatsAndModesCount > PinId);
+ ASSERT((m_DeviceFormatsAndModes[PinId].ModeAndDefaultFormatCount == 0) == (m_DeviceFormatsAndModes[PinId].ModeAndDefaultFormat == NULL));
+
+ modes = m_DeviceFormatsAndModes[PinId].ModeAndDefaultFormat;
+ numModes = m_DeviceFormatsAndModes[PinId].ModeAndDefaultFormatCount;
+
+ if (ppModes != NULL)
+ {
+ if (numModes > 0)
+ {
+ *ppModes = modes;
+ }
+ else
+ {
+ // ensure that the returned pointer is NULL
+ // in the event of failure (SAL annotation above
+ // indicates that it must be NULL, and OACR sees a possibility
+ // that it might not be).
+ *ppModes = NULL;
+ }
+ }
+
+ ReleaseFormatsAndModesLock();
+ return numModes;
+}
+
+#pragma code_seg()
+BOOL CMiniportWaveRT::IsSystemCapturePin(ULONG nPinId)
+{
+ AcquireFormatsAndModesLock();
+
+ PINTYPE pinType = m_DeviceFormatsAndModes[nPinId].PinType;
+
+ ReleaseFormatsAndModesLock();
+ return (pinType == SystemCapturePin);
+}
+
+#pragma code_seg()
+BOOL CMiniportWaveRT::IsSystemRenderPin(ULONG nPinId)
+{
+ AcquireFormatsAndModesLock();
+
+ PINTYPE pinType = m_DeviceFormatsAndModes[nPinId].PinType;
+
+ ReleaseFormatsAndModesLock();
+ return (pinType == SystemRenderPin);
+}
+
+#pragma code_seg()
+BOOL CMiniportWaveRT::IsBridgePin(ULONG nPinId)
+{
+ AcquireFormatsAndModesLock();
+
+ PINTYPE pinType = m_DeviceFormatsAndModes[nPinId].PinType;
+
+ ReleaseFormatsAndModesLock();
+ return (pinType == BridgePin);
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRT::StreamCreated
+(
+ _In_ ULONG _Pin,
+ _In_ PCMiniportWaveRTStream _Stream
+)
+{
+ PAGED_CODE();
+
+ PCMiniportWaveRTStream * streams = NULL;
+ ULONG count = 0;
+
+ DPF_ENTER(("[CMiniportWaveRT::StreamCreated]"));
+
+ if (IsSystemCapturePin(_Pin))
+ {
+ ALLOCATE_PIN_INSTANCE_RESOURCES(m_ulSystemAllocated);
+ return STATUS_SUCCESS;
+ }
+ else if (IsSystemRenderPin(_Pin))
+ {
+
+ ALLOCATE_PIN_INSTANCE_RESOURCES(m_ulSystemAllocated);
+ streams = m_SystemStreams;
+ count = m_ulMaxSystemStreams;
+
+ }
+
+ //
+ // Cache this stream's ptr.
+ //
+ if (streams != NULL)
+ {
+ ULONG i = 0;
+ for (; i<count; ++i)
+ {
+ if (streams[i] == NULL)
+ {
+ streams[i] = _Stream;
+ break;
+ }
+ }
+ ASSERT(i != count);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRT::StreamClosed
+(
+ _In_ ULONG _Pin,
+ _In_ PCMiniportWaveRTStream _Stream
+)
+{
+ PAGED_CODE();
+
+ bool updateDrmRights = false;
+ PCMiniportWaveRTStream * streams = NULL;
+ ULONG count = 0;
+
+ DPF_ENTER(("[CMiniportWaveRT::StreamClosed]"));
+
+ if (IsSystemCapturePin(_Pin))
+ {
+ FREE_PIN_INSTANCE_RESOURCES(m_ulSystemAllocated);
+ return STATUS_SUCCESS;
+ }
+ else if (IsSystemRenderPin(_Pin))
+ {
+
+ FREE_PIN_INSTANCE_RESOURCES(m_ulSystemAllocated);
+ streams = m_SystemStreams;
+ count = m_ulMaxSystemStreams;
+ updateDrmRights = true;
+
+ }
+
+ //
+ // Cleanup.
+ //
+ if (streams != NULL)
+ {
+ ULONG i = 0;
+ for (; i<count; ++i)
+ {
+ if (streams[i] == _Stream)
+ {
+ streams[i] = NULL;
+ break;
+ }
+ }
+ ASSERT(i != count);
+ }
+
+ //
+ // Update mixed drm rights.
+ //
+ if (updateDrmRights)
+ {
+ UpdateDrmRights();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRT::GetAttributesFromAttributeList
+(
+ _In_ const KSMULTIPLE_ITEM *_pAttributes,
+ _In_ size_t _Size,
+ _Out_ GUID* _pSignalProcessingMode
+)
+/*++
+
+Routine Description:
+
+ Processes attributes list and return known attributes.
+
+Arguments:
+
+ _pAttributes - pointer to KSMULTIPLE_ITEM at head of an attributes list.
+
+ _Size - count of bytes in the buffer pointed to by _pAttributes. The routine
+ verifies sufficient buffer size while processing the attributes.
+
+ _pSignalProcessingMode - returns the signal processing mode extracted from
+ the attribute list, or AUDIO_SIGNALPROCESSINGMODE_DEFAULT if the attribute
+ is not present in the list.
+
+Return Value:
+
+ NT status code.
+
+Remarks
+
+ This function is currently written for a single supported attribute
+ (KSATTRIBUTEID_AUDIOSIGNALPROCESSING_MODE). As additional attributes are defined in the future,
+ this function should be rewritten to be data driven through tables, etc.
+
+--*/
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMiniportWaveRT::GetAttributesFromAttributeList]"));
+
+ size_t cbRemaining = _Size;
+
+ *_pSignalProcessingMode = AUDIO_SIGNALPROCESSINGMODE_DEFAULT;
+
+ if (cbRemaining < sizeof(KSMULTIPLE_ITEM))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+ cbRemaining -= sizeof(KSMULTIPLE_ITEM);
+
+ //
+ // Extract attributes.
+ //
+ PKSATTRIBUTE attributeHeader = (PKSATTRIBUTE)(_pAttributes + 1);
+
+ for (ULONG i = 0; i < _pAttributes->Count; i++)
+ {
+ if (cbRemaining < sizeof(KSATTRIBUTE))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (attributeHeader->Attribute == KSATTRIBUTEID_AUDIOSIGNALPROCESSING_MODE)
+ {
+ KSATTRIBUTE_AUDIOSIGNALPROCESSING_MODE* signalProcessingModeAttribute;
+
+ if (cbRemaining < sizeof(KSATTRIBUTE_AUDIOSIGNALPROCESSING_MODE))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (attributeHeader->Size != sizeof(KSATTRIBUTE_AUDIOSIGNALPROCESSING_MODE))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ signalProcessingModeAttribute = (KSATTRIBUTE_AUDIOSIGNALPROCESSING_MODE*)attributeHeader;
+
+ // Return mode to caller.
+ *_pSignalProcessingMode = signalProcessingModeAttribute->SignalProcessingMode;
+ }
+ else
+ {
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ // Adjust pointer and buffer size to next attribute (QWORD aligned)
+ ULONG cbAttribute = ((attributeHeader->Size + FILE_QUAD_ALIGNMENT) & ~FILE_QUAD_ALIGNMENT);
+
+ attributeHeader = (PKSATTRIBUTE) (((PBYTE)attributeHeader) + cbAttribute);
+ cbRemaining -= cbAttribute;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRT::IsFormatSupported
+(
+ _In_ ULONG _ulPin,
+ _In_ BOOLEAN _bCapture,
+ _In_ PKSDATAFORMAT _pDataFormat
+)
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMiniportWaveRT::IsFormatSupported]"));
+
+ NTSTATUS ntStatus = STATUS_NO_MATCH;
+ PKSDATAFORMAT_WAVEFORMATEXTENSIBLE pPinFormats = NULL;
+ ULONG cPinFormats = 0;
+
+ UNREFERENCED_PARAMETER(_bCapture);
+
+ if (_ulPin >= m_pMiniportPair->WaveDescriptor->PinCount)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ cPinFormats = GetPinSupportedDeviceFormats(_ulPin, &pPinFormats);
+
+ for (UINT iFormat = 0; iFormat < cPinFormats; iFormat++)
+ {
+ PKSDATAFORMAT_WAVEFORMATEXTENSIBLE pFormat = &pPinFormats[iFormat];
+ // KSDATAFORMAT VALIDATION
+ if (!IsEqualGUIDAligned(pFormat->DataFormat.MajorFormat, _pDataFormat->MajorFormat)) { continue; }
+ if (!IsEqualGUIDAligned(pFormat->DataFormat.SubFormat, _pDataFormat->SubFormat)) { continue; }
+ if (!IsEqualGUIDAligned(pFormat->DataFormat.Specifier, _pDataFormat->Specifier)) { continue; }
+ if (pFormat->DataFormat.FormatSize < sizeof(KSDATAFORMAT_WAVEFORMATEX)) { continue; }
+
+ // WAVEFORMATEX VALIDATION
+ PWAVEFORMATEX pWaveFormat = reinterpret_cast<PWAVEFORMATEX>(_pDataFormat + 1);
+
+ if (pWaveFormat->wFormatTag != WAVE_FORMAT_EXTENSIBLE)
+ {
+ if (pWaveFormat->wFormatTag != EXTRACT_WAVEFORMATEX_ID(&(pFormat->WaveFormatExt.SubFormat))) { continue; }
+ }
+ if (pWaveFormat->nChannels != pFormat->WaveFormatExt.Format.nChannels) { continue; }
+ if (pWaveFormat->nSamplesPerSec != pFormat->WaveFormatExt.Format.nSamplesPerSec) { continue; }
+ if (pWaveFormat->nBlockAlign != pFormat->WaveFormatExt.Format.nBlockAlign) { continue; }
+ if (pWaveFormat->wBitsPerSample != pFormat->WaveFormatExt.Format.wBitsPerSample) { continue; }
+ if (pWaveFormat->wFormatTag != WAVE_FORMAT_EXTENSIBLE)
+ {
+ ntStatus = STATUS_SUCCESS;
+ break;
+ }
+
+ // WAVEFORMATEXTENSIBLE VALIDATION
+ if (pWaveFormat->cbSize < sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)) { continue; }
+
+ PWAVEFORMATEXTENSIBLE pWaveFormatExt = reinterpret_cast<PWAVEFORMATEXTENSIBLE>(pWaveFormat);
+ if (pWaveFormatExt->Samples.wValidBitsPerSample != pFormat->WaveFormatExt.Samples.wValidBitsPerSample) { continue; }
+ if (pWaveFormatExt->dwChannelMask != pFormat->WaveFormatExt.dwChannelMask) { continue; }
+ if (!IsEqualGUIDAligned(pWaveFormatExt->SubFormat, pFormat->WaveFormatExt.SubFormat)) { continue; }
+
+ ntStatus = STATUS_SUCCESS;
+ break;
+ }
+
+ return ntStatus;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRT::PropertyHandlerProposedFormat
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+{
+ PKSP_PIN kspPin = NULL;
+ PKSDATAFORMAT pKsFormat = NULL;
+ ULONG cbMinSize = 0;
+ NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
+
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMiniportWaveRT::PropertyHandlerProposedFormat]"));
+
+ // All properties handled by this handler require at least a KSP_PIN descriptor.
+
+ // Verify instance data stores at least KSP_PIN fields beyond KSPPROPERTY.
+ if (PropertyRequest->InstanceSize < (sizeof(KSP_PIN) - RTL_SIZEOF_THROUGH_FIELD(KSP_PIN, Property)))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ // Extract property descriptor from property request instance data
+ kspPin = CONTAINING_RECORD(PropertyRequest->Instance, KSP_PIN, PinId);
+
+ //
+ // This method is valid only on streaming pins.
+ //
+ if (IsSystemRenderPin(kspPin->PinId) ||
+ IsSystemCapturePin(kspPin->PinId))
+ {
+ ntStatus = STATUS_SUCCESS;
+ }
+ else if (IsBridgePin(kspPin->PinId))
+ {
+ ntStatus = STATUS_NOT_SUPPORTED;
+ }
+ else
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ return ntStatus;
+ }
+
+ cbMinSize = sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE);
+
+ // Handle KSPROPERTY_TYPE_BASICSUPPORT query
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ ULONG flags = PropertyRequest->PropertyItem->Flags;
+
+ return PropertyHandler_BasicSupport(PropertyRequest, flags, VT_ILLEGAL);
+ }
+
+ // Verify value size
+ if (PropertyRequest->ValueSize == 0)
+ {
+ PropertyRequest->ValueSize = cbMinSize;
+ return STATUS_BUFFER_OVERFLOW;
+ }
+ if (PropertyRequest->ValueSize < cbMinSize)
+ {
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+ }
+ else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
+ {
+ pKsFormat = (PKSDATAFORMAT)PropertyRequest->Value;
+ ntStatus = IsFormatSupported(kspPin->PinId, IsSystemCapturePin(kspPin->PinId) || FALSE, pKsFormat);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ return ntStatus;
+ }
+ }
+
+ return ntStatus;
+} // PropertyHandlerProposedFormat
+
+//=============================================================================
+#pragma code_seg()
+NTSTATUS
+CMiniportWaveRT_EventHandler_PinCapsChange
+(
+_In_ PPCEVENT_REQUEST EventRequest
+)
+{
+ CMiniportWaveRT* miniport = reinterpret_cast<CMiniportWaveRT*>(EventRequest->MajorTarget);
+ return miniport->EventHandler_PinCapsChange(EventRequest);
+}
+
+//=============================================================================
+#pragma code_seg()
+NTSTATUS
+CMiniportWaveRT::EventHandler_PinCapsChange
+(
+_In_ PPCEVENT_REQUEST EventRequest
+)
+{
+ if (*EventRequest->EventItem->Set != KSEVENTSETID_PinCapsChange)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ switch (EventRequest->Verb)
+ {
+ // Do we support event handling?!?
+ case PCEVENT_VERB_SUPPORT:
+ break;
+ // We should add the event now!
+ case PCEVENT_VERB_ADD:
+ // If we have the interface and EventEntry is defined ...
+ if (EventRequest->EventEntry)
+ {
+ switch (EventRequest->EventItem->Id)
+ {
+ // Add pincaps format change event to support the force sample rate feature
+ case KSEVENT_PINCAPS_FORMATCHANGE:
+ m_pPortEvents->AddEventToEventList(EventRequest->EventEntry);
+ break;
+ default:
+ return STATUS_INVALID_PARAMETER;
+ break;
+ }
+ }
+ else
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+ break;
+
+ case PCEVENT_VERB_REMOVE:
+ // We cannot remove the event but we can stop generating the
+ // events. However, it also doesn't hurt to always generate them ...
+ break;
+
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRT::PropertyHandlerProposedFormat2
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+{
+ PKSP_PIN kspPin = NULL;
+ ULONG cbMinSize = 0;
+ NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
+ ULONG numModes = 0;
+ MODE_AND_DEFAULT_FORMAT *modeInfo = NULL;
+ MODE_AND_DEFAULT_FORMAT *modeTemp = NULL;
+ PKSMULTIPLE_ITEM pKsItemsHeader = NULL;
+ PKSMULTIPLE_ITEM pKsItemsHeaderOut = NULL;
+ size_t cbItemsList = 0;
+ GUID signalProcessingMode = {0};
+ BOOLEAN bFound = FALSE;
+ ULONG i;
+
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMiniportWaveRT::PropertyHandlerProposedFormat2]"));
+
+ // All properties handled by this handler require at least a KSP_PIN descriptor.
+
+ // Verify instance data stores at least KSP_PIN fields beyond KSPPROPERTY.
+ if (PropertyRequest->InstanceSize < (sizeof(KSP_PIN) - RTL_SIZEOF_THROUGH_FIELD(KSP_PIN, Property)))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ // Extract property descriptor from property request instance data
+ kspPin = CONTAINING_RECORD(PropertyRequest->Instance, KSP_PIN, PinId);
+
+ if (kspPin->PinId >= m_pMiniportPair->WaveDescriptor->PinCount)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // This property is supported only on some streaming pins.
+ //
+ numModes = GetPinSupportedDeviceModes(kspPin->PinId, &modeInfo);
+
+ ASSERT((modeInfo != NULL && numModes > 0) || (modeInfo == NULL && numModes == 0));
+
+ if (modeInfo == NULL)
+ {
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ //
+ // Even for pins that support modes, the pin might not support proposed formats
+ //
+ bFound = FALSE;
+ for (i=0, modeTemp=modeInfo; i<numModes; ++i, ++modeTemp)
+ {
+ if (modeTemp->DefaultFormat != NULL)
+ {
+ bFound = TRUE;
+ break;
+ }
+ }
+
+ if (!bFound)
+ {
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ //
+ // The property is generally supported on this pin. Handle basic support request.
+ //
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ return PropertyHandler_BasicSupport(PropertyRequest, PropertyRequest->PropertyItem->Flags, VT_ILLEGAL);
+ }
+
+ //
+ // Get the mode if specified.
+ //
+ pKsItemsHeader = (PKSMULTIPLE_ITEM)(kspPin + 1);
+ cbItemsList = (((PBYTE)PropertyRequest->Instance) + PropertyRequest->InstanceSize) - (PBYTE)pKsItemsHeader;
+
+ ntStatus = GetAttributesFromAttributeList(pKsItemsHeader, cbItemsList, &signalProcessingMode);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ return ntStatus;
+ }
+
+ //
+ // Get the info associated with this mode.
+ //
+ bFound = FALSE;
+ for (i=0; i<numModes; ++i, ++modeInfo)
+ {
+ if (modeInfo->Mode == signalProcessingMode)
+ {
+ bFound = TRUE;
+ break;
+ }
+ }
+
+ // Either the mode isn't supported, or the driver doesn't support a
+ // proprosed format for this specific mode.
+ if (!bFound || modeInfo->DefaultFormat == NULL)
+ {
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ //
+ // Compute output data buffer.
+ //
+ cbMinSize = modeInfo->DefaultFormat->FormatSize;
+ cbMinSize = (cbMinSize + 7) & ~7;
+
+ pKsItemsHeaderOut = (PKSMULTIPLE_ITEM)((PBYTE)PropertyRequest->Value + cbMinSize);
+
+ if (cbItemsList > MAXULONG)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ // Total # of bytes.
+ ntStatus = RtlULongAdd(cbMinSize, (ULONG)cbItemsList, &cbMinSize);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ // Property not supported.
+ if (cbMinSize == 0)
+ {
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ // Verify value size
+ if (PropertyRequest->ValueSize == 0)
+ {
+ PropertyRequest->ValueSize = cbMinSize;
+ return STATUS_BUFFER_OVERFLOW;
+ }
+ if (PropertyRequest->ValueSize < cbMinSize)
+ {
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ // Only GET is supported for this property
+ if ((PropertyRequest->Verb & KSPROPERTY_TYPE_GET) == 0)
+ {
+ return STATUS_INVALID_DEVICE_REQUEST;
+ }
+
+ // Copy the proposed default format.
+ RtlCopyMemory(PropertyRequest->Value, modeInfo->DefaultFormat, modeInfo->DefaultFormat->FormatSize);
+
+ // Copy back the attribute list.
+ ASSERT(cbItemsList > 0);
+ ((KSDATAFORMAT*)PropertyRequest->Value)->Flags = KSDATAFORMAT_ATTRIBUTES;
+ RtlCopyMemory(pKsItemsHeaderOut, pKsItemsHeader, cbItemsList);
+
+ PropertyRequest->ValueSize = cbMinSize;
+
+ return STATUS_SUCCESS;
+} // PropertyHandlerProposedFormat
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRT::UpdateDrmRights
+(
+ void
+)
+/*++
+
+Routine Description:
+
+ Updates the mixed DrmRights. This is done by creating an array of existing
+ content ids and asking DrmPort to create a new contend id with a mixed
+ DrmRights structure.
+ The new DrmRights structure should be enforced, if everything goes well.
+
+Arguments:
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMiniportWaveRT::UpdateDrmRights]"));
+
+ NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
+ ULONG ulMixDrmContentId = 0;
+ BOOL fCreatedContentId = FALSE;
+ DRMRIGHTS MixDrmRights = {FALSE, 0, FALSE};
+ ULONG ulContentIndex = 0;
+ ULONG* ulContentIds = NULL;
+
+ //
+ // This function only runs if IID_DrmPort is implemented in Wave port.
+ //
+ if (!m_pDrmPort)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ ulContentIds = new (POOL_FLAG_NON_PAGED, MINWAVERT_POOLTAG) ULONG[m_ulMaxSystemStreams + m_ulMaxOffloadStreams];
+ if (!ulContentIds)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Create an array of all StreamIds.
+ //
+ for (ULONG i = 0; i < m_ulMaxSystemStreams; i++)
+ {
+ if (m_SystemStreams[i])
+ {
+ ulContentIds[ulContentIndex] = m_SystemStreams[i]->m_ulContentId;
+ ulContentIndex++;
+ }
+ }
+
+ //
+ // Create the new contentId.
+ //
+ if (ulContentIndex)
+ {
+ ntStatus =
+ m_pDrmPort->CreateContentMixed
+ (
+ ulContentIds,
+ ulContentIndex,
+ &ulMixDrmContentId
+ );
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ fCreatedContentId = TRUE;
+ ntStatus =
+ m_pDrmPort->GetContentRights
+ (
+ ulMixDrmContentId,
+ &MixDrmRights
+ );
+ }
+ }
+
+ //
+ // If successful, destroy the old ContentId and update global rights.
+ //
+ if (NT_SUCCESS(ntStatus))
+ {
+ m_pDrmPort->DestroyContent(m_ulMixDrmContentId);
+ m_ulMixDrmContentId = ulMixDrmContentId;
+ RtlCopyMemory(&m_MixDrmRights, &MixDrmRights, sizeof(m_MixDrmRights));
+
+ //
+ // At this point the driver should enforce the new DrmRights.
+ // The sample driver handles DrmRights per stream basis, and
+ // stops writing the stream to disk, if CopyProtect = TRUE.
+ //
+ }
+
+ //
+ // Cleanup if failed
+ //
+ if (!NT_SUCCESS(ntStatus) && fCreatedContentId)
+ {
+ m_pDrmPort->DestroyContent(ulMixDrmContentId);
+ }
+
+ //
+ // Free allocated memory.
+ //
+ ASSERT(ulContentIds);
+ delete [] ulContentIds;
+ ulContentIds = NULL;
+
+ return ntStatus;
+} // UpdateDrmRights
+
+#pragma code_seg("PAGE")
+NTSTATUS
+PropertyHandler_WaveFilter
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+/*++
+
+Routine Description:
+
+ Redirects general property request to miniport object
+
+Arguments:
+
+ PropertyRequest -
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+ CMiniportWaveRT* pWaveHelper = reinterpret_cast<CMiniportWaveRT*>(PropertyRequest->MajorTarget);
+
+ if (pWaveHelper == NULL)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ pWaveHelper->AddRef();
+
+
+ if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Pin))
+ {
+ switch (PropertyRequest->PropertyItem->Id)
+ {
+ case KSPROPERTY_PIN_PROPOSEDATAFORMAT:
+ ntStatus = pWaveHelper->PropertyHandlerProposedFormat(PropertyRequest);
+ break;
+
+ case KSPROPERTY_PIN_PROPOSEDATAFORMAT2:
+ ntStatus = pWaveHelper->PropertyHandlerProposedFormat2(PropertyRequest);
+ break;
+
+ default:
+ DPF(D_TERSE, ("[PropertyHandler_WaveFilter: Invalid Device Request]"));
+ }
+ }
+
+ pWaveHelper->Release();
+
+ return ntStatus;
+} // PropertyHandler_WaveFilter
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+PropertyHandler_GenericPin
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+{
+ NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+ CMiniportWaveRT* pWave = NULL;
+ CMiniportWaveRTStream * pStream = NULL;
+
+ PAGED_CODE();
+
+ if (PropertyRequest->MajorTarget == NULL ||
+ PropertyRequest->MinorTarget == NULL)
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ //
+ // Get a ref to the miniport.
+ //
+ pWave = MajorTarget_to_Obj(PropertyRequest->MajorTarget);
+ pWave->AddRef();
+
+ //
+ // Get a ref to the stream.
+ //
+ pStream = MinorTarget_to_Obj(PropertyRequest->MinorTarget);
+ pStream->AddRef();
+
+exit:
+
+ SAFE_RELEASE(pStream);
+ SAFE_RELEASE(pWave);
+
+ return ntStatus;
+}
+
+#pragma code_seg()
+
diff --git a/audio/simpleaudiosample/Source/Main/minwavert.h b/audio/simpleaudiosample/Source/Main/minwavert.h
new file mode 100644
index 00000000..4c0ccd83
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Main/minwavert.h
@@ -0,0 +1,302 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ minwavert.h
+
+Abstract:
+
+ Definition of wavert miniport class.
+--*/
+
+#ifndef _SIMPLEAUDIOSAMPLE_MINWAVERT_H_
+#define _SIMPLEAUDIOSAMPLE_MINWAVERT_H_
+
+//=============================================================================
+// Referenced Forward
+//=============================================================================
+class CMiniportWaveRTStream;
+typedef CMiniportWaveRTStream *PCMiniportWaveRTStream;
+
+//=============================================================================
+// Classes
+//=============================================================================
+///////////////////////////////////////////////////////////////////////////////
+// CMiniportWaveRT
+//
+class CMiniportWaveRT :
+ public IMiniportWaveRT,
+ public IMiniportAudioSignalProcessing,
+ public CUnknown
+{
+private:
+ ULONG m_ulSystemAllocated;
+
+ ULONG m_ulMaxSystemStreams;
+ ULONG m_ulMaxOffloadStreams;
+ ULONG m_ulMaxLoopbackStreams;
+
+ // weak ref of running streams.
+ PCMiniportWaveRTStream * m_SystemStreams;
+
+ BOOL m_bGfxEnabled;
+ PBOOL m_pbMuted;
+ PLONG m_plVolumeLevel;
+ PKSDATAFORMAT_WAVEFORMATEXTENSIBLE m_pMixFormat;
+ PKSDATAFORMAT_WAVEFORMATEXTENSIBLE m_pDeviceFormat;
+ PCFILTER_DESCRIPTOR m_FilterDesc;
+ PIN_DEVICE_FORMATS_AND_MODES * m_DeviceFormatsAndModes;
+ KSPIN_LOCK m_DeviceFormatsAndModesLock; // To serialize access.
+ KIRQL m_DeviceFormatsAndModesIrql;
+ ULONG m_DeviceFormatsAndModesCount;
+ USHORT m_DeviceMaxChannels;
+ PDRMPORT m_pDrmPort;
+ DRMRIGHTS m_MixDrmRights;
+ ULONG m_ulMixDrmContentId;
+
+ union {
+ PVOID m_DeviceContext;
+ };
+
+protected:
+ PADAPTERCOMMON m_pAdapterCommon;
+ ULONG m_DeviceFlags;
+ eDeviceType m_DeviceType;
+ PPORTEVENTS m_pPortEvents;
+ PENDPOINT_MINIPAIR m_pMiniportPair;
+
+public:
+ NTSTATUS EventHandler_PinCapsChange
+ (
+ _In_ PPCEVENT_REQUEST EventRequest
+ );
+
+ NTSTATUS ValidateStreamCreate
+ (
+ _In_ ULONG _Pin,
+ _In_ BOOLEAN _Capture
+ );
+
+ NTSTATUS StreamCreated
+ (
+ _In_ ULONG _Pin,
+ _In_ PCMiniportWaveRTStream _Stream
+ );
+
+ NTSTATUS StreamClosed
+ (
+ _In_ ULONG _Pin,
+ _In_ PCMiniportWaveRTStream _Stream
+ );
+
+ NTSTATUS IsFormatSupported
+ (
+ _In_ ULONG _ulPin,
+ _In_ BOOLEAN _bCapture,
+ _In_ PKSDATAFORMAT _pDataFormat
+ );
+
+ static NTSTATUS GetAttributesFromAttributeList
+ (
+ _In_ const KSMULTIPLE_ITEM *_pAttributes,
+ _In_ size_t _Size,
+ _Out_ GUID* _pSignalProcessingMode
+ );
+
+protected:
+ NTSTATUS UpdateDrmRights
+ (
+ void
+ );
+
+public:
+ DECLARE_STD_UNKNOWN();
+
+#pragma code_seg("PAGE")
+ CMiniportWaveRT(
+ _In_ PUNKNOWN UnknownAdapter,
+ _In_ PENDPOINT_MINIPAIR MiniportPair,
+ _In_opt_ PVOID DeviceContext
+ )
+ :CUnknown(0),
+ m_ulMaxSystemStreams(0),
+ m_DeviceType(MiniportPair->DeviceType),
+ m_DeviceContext(DeviceContext),
+ m_DeviceMaxChannels(MiniportPair->DeviceMaxChannels),
+ m_DeviceFormatsAndModes(MiniportPair->PinDeviceFormatsAndModes),
+ m_DeviceFormatsAndModesCount(MiniportPair->PinDeviceFormatsAndModesCount),
+ m_DeviceFlags(MiniportPair->DeviceFlags),
+ m_pMiniportPair(MiniportPair)
+ {
+ PAGED_CODE();
+
+ m_pAdapterCommon = (PADAPTERCOMMON)UnknownAdapter; // weak ref.
+
+ if (MiniportPair->WaveDescriptor)
+ {
+ RtlCopyMemory(&m_FilterDesc, MiniportPair->WaveDescriptor, sizeof(m_FilterDesc));
+
+ //
+ // Get the max # of pin instances.
+ //
+ if (IsRenderDevice())
+ {
+ if (m_FilterDesc.PinCount > KSPIN_WAVE_RENDER2_SOURCE)
+ {
+ m_ulMaxSystemStreams = m_FilterDesc.Pins[KSPIN_WAVE_RENDER2_SINK_SYSTEM].MaxFilterInstanceCount;
+ m_ulMaxLoopbackStreams = m_FilterDesc.Pins[KSPIN_WAVE_RENDER2_SINK_LOOPBACK].MaxFilterInstanceCount;
+ }
+ else if(m_FilterDesc.PinCount > KSPIN_WAVE_RENDER3_SOURCE)
+ {
+ m_ulMaxSystemStreams = m_FilterDesc.Pins[KSPIN_WAVE_RENDER3_SINK_SYSTEM].MaxFilterInstanceCount;
+ }
+ }
+ else
+ {
+ //
+ // capture bridge pin comes first in the enumeration
+ //
+ if (m_FilterDesc.PinCount > KSPIN_WAVEIN_HOST)
+ {
+ m_ulMaxSystemStreams = m_FilterDesc.Pins[KSPIN_WAVEIN_HOST].MaxFilterInstanceCount;
+ }
+ }
+ }
+
+ KeInitializeSpinLock(&m_DeviceFormatsAndModesLock);
+ m_DeviceFormatsAndModesIrql = PASSIVE_LEVEL;
+ }
+
+#pragma code_seg()
+
+ ~CMiniportWaveRT();
+
+ IMP_IMiniportWaveRT;
+ IMP_IMiniportAudioSignalProcessing;
+
+ // Friends
+ friend class CMiniportWaveRTStream;
+ friend class CMiniportTopologySimpleAudioSample;
+
+ friend NTSTATUS PropertyHandler_WaveFilter
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
+
+public:
+public:
+ NTSTATUS PropertyHandlerProposedFormat
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
+
+ NTSTATUS PropertyHandlerProposedFormat2
+
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
+
+ PADAPTERCOMMON GetAdapterCommObj()
+ {
+ return m_pAdapterCommon;
+ };
+#pragma code_seg()
+
+ //---------------------------------------------------------------------------------------------------------
+ // volume
+ //---------------------------------------------------------------------------------------------------------
+ NTSTATUS GetVolumeChannelCount
+ (
+ _Out_ UINT32* pulChannelCount
+ );
+
+ NTSTATUS GetVolumeSteppings
+ (
+ _Out_writes_bytes_(_ui32DataSize) PKSPROPERTY_STEPPING_LONG _pKsPropStepLong,
+ _In_ UINT32 _ui32DataSize
+ );
+
+ NTSTATUS GetChannelVolume
+ (
+ _In_ UINT32 _uiChannel,
+ _Out_ LONG* _pVolume
+ );
+
+ NTSTATUS SetChannelVolume
+ (
+ _In_ UINT32 _uiChannel,
+ _In_ LONG _Volume
+ );
+
+ //-----------------------------------------------------------------------------
+ // mute
+ //-----------------------------------------------------------------------------
+ NTSTATUS GetMuteChannelCount
+ (
+ _Out_ UINT32* pulChannelCount
+ );
+
+ NTSTATUS GetMuteSteppings
+ (
+ _Out_writes_bytes_(_ui32DataSize) PKSPROPERTY_STEPPING_LONG _pKsPropStepLong,
+ _In_ UINT32 _ui32DataSize
+ );
+
+ NTSTATUS GetChannelMute
+ (
+ _In_ UINT32 _uiChannel,
+ _Out_ BOOL* _pbMute
+ );
+
+ NTSTATUS SetChannelMute
+ (
+ _In_ UINT32 _uiChannel,
+ _In_ BOOL _bMute
+ );
+
+private:
+ _IRQL_raises_(DISPATCH_LEVEL)
+ _Acquires_lock_(m_DeviceFormatsAndModesLock)
+ _Requires_lock_not_held_(m_DeviceFormatsAndModesLock)
+ _IRQL_saves_global_(SpinLock, m_DeviceFormatsAndModesIrql)
+ VOID AcquireFormatsAndModesLock();
+
+ _Releases_lock_(m_DeviceFormatsAndModesLock)
+ _Requires_lock_held_(m_DeviceFormatsAndModesLock)
+ _IRQL_restores_global_(SpinLock, m_DeviceFormatsAndModesIrql)
+ VOID ReleaseFormatsAndModesLock();
+
+ _Post_satisfies_(return > 0)
+ ULONG GetPinSupportedDeviceFormats(_In_ ULONG PinId, _Outptr_opt_result_buffer_(return) KSDATAFORMAT_WAVEFORMATEXTENSIBLE **ppFormats);
+
+ _Success_(return != 0)
+ ULONG GetPinSupportedDeviceModes(_In_ ULONG PinId, _Outptr_opt_result_buffer_(return) _On_failure_(_Deref_post_null_) MODE_AND_DEFAULT_FORMAT **ppModes);
+
+#pragma code_seg()
+
+protected:
+#pragma code_seg()
+ BOOL IsRenderDevice()
+ {
+ return m_DeviceType == eSpeakerDevice ? TRUE : FALSE;
+ }
+
+ BOOL IsSystemRenderPin(ULONG nPinId);
+
+ BOOL IsSystemCapturePin(ULONG nPinId);
+
+ BOOL IsBridgePin(ULONG nPinId);
+
+ // These three pins are the pins used by the audio engine for host, loopback, and offload.
+ ULONG GetSystemPinId()
+ {
+ ASSERT(IsRenderDevice());
+ return KSPIN_WAVE_RENDER2_SINK_SYSTEM;
+ }
+};
+
+typedef CMiniportWaveRT *PCMiniportWaveRT;
+
+#endif // _SIMPLEAUDIOSAMPLE_MINWAVERT_H_
diff --git a/audio/simpleaudiosample/Source/Main/minwavertstream.cpp b/audio/simpleaudiosample/Source/Main/minwavertstream.cpp
new file mode 100644
index 00000000..27289a0e
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Main/minwavertstream.cpp
@@ -0,0 +1,1644 @@
+#include "definitions.h"
+#include <limits.h>
+#include <ks.h>
+#include "endpoints.h"
+#include "minwavert.h"
+#include "minwavertstream.h"
+#define MINWAVERTSTREAM_POOLTAG 'SRWM'
+
+#pragma warning (disable : 4127)
+
+//=============================================================================
+// CMiniportWaveRTStream
+//=============================================================================
+
+//=============================================================================
+#pragma code_seg("PAGE")
+CMiniportWaveRTStream::~CMiniportWaveRTStream
+(
+ void
+)
+/*++
+
+Routine Description:
+
+ Destructor for wavertstream
+
+Arguments:
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+ if (NULL != m_pMiniport)
+ {
+
+ if (m_bUnregisterStream)
+ {
+ m_pMiniport->StreamClosed(m_ulPin, this);
+ m_bUnregisterStream = FALSE;
+ }
+
+ m_pMiniport->Release();
+ m_pMiniport = NULL;
+ }
+
+ if (m_pDpc)
+ {
+ ExFreePoolWithTag( m_pDpc, MINWAVERTSTREAM_POOLTAG );
+ m_pDpc = NULL;
+ }
+
+ if (m_pTimer)
+ {
+ ExFreePoolWithTag( m_pTimer, MINWAVERTSTREAM_POOLTAG );
+ m_pTimer = NULL;
+ }
+
+ if (m_pbMuted)
+ {
+ ExFreePoolWithTag( m_pbMuted, MINWAVERTSTREAM_POOLTAG );
+ m_pbMuted = NULL;
+ }
+
+ if (m_plVolumeLevel)
+ {
+ ExFreePoolWithTag( m_plVolumeLevel, MINWAVERTSTREAM_POOLTAG );
+ m_plVolumeLevel = NULL;
+ }
+
+ if (m_plPeakMeter)
+ {
+ ExFreePoolWithTag( m_plPeakMeter, MINWAVERTSTREAM_POOLTAG );
+ m_plPeakMeter = NULL;
+ }
+
+ if (m_pWfExt)
+ {
+ ExFreePoolWithTag( m_pWfExt, MINWAVERTSTREAM_POOLTAG );
+ m_pWfExt = NULL;
+ }
+ if (m_pNotificationTimer)
+ {
+ ExDeleteTimer
+ (
+ m_pNotificationTimer,
+ TRUE, // Cancel the timer if it is currently set.
+ TRUE, // Wait for the timer to finish expiring and for any callback to a ExTimerCallback routine to finish.
+ NULL
+ );
+ }
+
+ // Since we just cancelled the notification timer, wait for all queued
+ // DPCs to complete before we free the notification DPC.
+ //
+ KeFlushQueuedDpcs();
+
+ DPF_ENTER(("[CMiniportWaveRTStream::~CMiniportWaveRTStream]"));
+} // ~CMiniportWaveRTStream
+
+//=============================================================================
+#pragma code_seg("PAGE")
+
+NTSTATUS CMiniportWaveRTStream::ReadRegistrySettings()
+{
+ PAGED_CODE();
+
+ NTSTATUS ntStatus;
+ UNICODE_STRING parametersPath;
+
+ RTL_QUERY_REGISTRY_TABLE paramTable[] = {
+ // QueryRoutine Flags Name EntryContext DefaultType DefaultData DefaultLength
+ { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"HostCaptureToneFrequency", &m_ulHostCaptureToneFrequency, (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD, &m_ulHostCaptureToneFrequency, sizeof(DWORD) },
+ { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"HostCaptureToneAmplitude", &m_dwHostCaptureToneAmplitude, (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD, &m_dwHostCaptureToneAmplitude, sizeof(DWORD) },
+ { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"HostCaptureToneDCOffset", &m_dwHostCaptureToneDCOffset, (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD, &m_dwHostCaptureToneDCOffset, sizeof(DWORD) },
+ { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"HostCaptureToneInitialPhase", &m_dwHostCaptureToneInitialPhase, (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD, &m_dwHostCaptureToneInitialPhase, sizeof(DWORD) },
+ { NULL, 0, NULL, NULL, 0, NULL, 0 }
+ };
+
+ RtlInitUnicodeString(&parametersPath, NULL);
+
+ // The sizeof(WCHAR) is added to the maximum length, for allowing a space for null termination of the string.
+ parametersPath.MaximumLength =
+ g_RegistryPath.Length + sizeof(L"\\Parameters") + sizeof(WCHAR);
+
+ parametersPath.Buffer = (PWCH)ExAllocatePool2(POOL_FLAG_PAGED, parametersPath.MaximumLength, MINWAVERT_POOLTAG);
+ if (parametersPath.Buffer == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlAppendUnicodeToString(&parametersPath, g_RegistryPath.Buffer);
+ RtlAppendUnicodeToString(&parametersPath, L"\\Parameters");
+
+ ntStatus = RtlQueryRegistryValues(
+ RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
+ parametersPath.Buffer,
+ &paramTable[0],
+ NULL,
+ NULL
+ );
+
+ ExFreePool(parametersPath.Buffer);
+
+ return ntStatus;
+}
+
+NTSTATUS
+CMiniportWaveRTStream::Init
+(
+ _In_ PCMiniportWaveRT Miniport_,
+ _In_ PPORTWAVERTSTREAM PortStream_,
+ _In_ ULONG Pin_,
+ _In_ BOOLEAN Capture_,
+ _In_ PKSDATAFORMAT DataFormat_,
+ _In_ GUID SignalProcessingMode
+)
+/*++
+
+Routine Description:
+
+ Initializes the stream object.
+
+Arguments:
+
+ Miniport_ -
+
+ Pin_ -
+
+ DataFormat -
+
+ SignalProcessingMode - The driver uses the signalProcessingMode to configure
+ driver and/or hardware specific signal processing to be applied to this new
+ stream.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ PWAVEFORMATEX pWfEx = NULL;
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ m_pMiniport = NULL;
+ m_ulPin = 0;
+ m_bUnregisterStream = FALSE;
+ m_bCapture = FALSE;
+ m_ulDmaBufferSize = 0;
+ m_pDmaBuffer = NULL;
+ m_ulNotificationsPerBuffer = 0;
+ m_KsState = KSSTATE_STOP;
+ m_pTimer = NULL;
+ m_pDpc = NULL;
+ m_llPacketCounter = 0;
+ m_ullPlayPosition = 0;
+ m_ullWritePosition = 0;
+ m_ullDmaTimeStamp = 0;
+ m_hnsElapsedTimeCarryForward = 0;
+ m_ullLastDPCTimeStamp = 0;
+ m_hnsDPCTimeCarryForward = 0;
+ m_ulDmaMovementRate = 0;
+ m_byteDisplacementCarryForward = 0;
+ m_bLfxEnabled = FALSE;
+ m_pbMuted = NULL;
+ m_plVolumeLevel = NULL;
+ m_plPeakMeter = NULL;
+ m_pWfExt = NULL;
+ m_ullLinearPosition = 0;
+ m_ullPresentationPosition = 0;
+ m_ulContentId = 0;
+ m_ulCurrentWritePosition = 0;
+ m_ulLastOsReadPacket = ULONG_MAX;
+ m_ulLastOsWritePacket = ULONG_MAX;
+ m_IsCurrentWritePositionUpdated = 0;
+ m_SignalProcessingMode = SignalProcessingMode;
+ m_bEoSReceived = FALSE;
+ m_bLastBufferRendered = FALSE;
+
+ m_ulHostCaptureToneFrequency = IsEqualGUID(SignalProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) ? 1000 : 2000;
+ m_dwHostCaptureToneAmplitude = 50;
+ m_dwHostCaptureToneDCOffset = 0;
+ m_dwHostCaptureToneInitialPhase = 0;
+
+ m_pPortStream = PortStream_;
+ InitializeListHead(&m_NotificationList);
+ m_ulNotificationIntervalMs = 0;
+
+ // Initialize the spinlock to synchronize position updates
+ KeInitializeSpinLock(&m_PositionSpinLock);
+
+ m_pNotificationTimer = ExAllocateTimer(
+ TimerNotifyRT,
+ this,
+ EX_TIMER_HIGH_RESOLUTION
+ );
+ if (!m_pNotificationTimer)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ pWfEx = GetWaveFormatEx(DataFormat_);
+ if (NULL == pWfEx)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ m_pMiniport = reinterpret_cast<CMiniportWaveRT*>(Miniport_);
+ if (m_pMiniport == NULL)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+ m_pMiniport->AddRef();
+ if (!NT_SUCCESS(ntStatus))
+ {
+ return ntStatus;
+ }
+ m_ulPin = Pin_;
+ m_bCapture = Capture_;
+ m_ulDmaMovementRate = pWfEx->nAvgBytesPerSec;
+
+ m_pDpc = (PRKDPC)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(KDPC), MINWAVERTSTREAM_POOLTAG);
+ if (!m_pDpc)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ m_pWfExt = (PWAVEFORMATEXTENSIBLE)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(WAVEFORMATEX) + pWfEx->cbSize, MINWAVERTSTREAM_POOLTAG);
+ if (m_pWfExt == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlCopyMemory(m_pWfExt, pWfEx, sizeof(WAVEFORMATEX) + pWfEx->cbSize);
+
+ m_pbMuted = (PBOOL)ExAllocatePool2(POOL_FLAG_NON_PAGED, m_pWfExt->Format.nChannels * sizeof(BOOL), MINWAVERTSTREAM_POOLTAG);
+ if (m_pbMuted == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ m_plVolumeLevel = (PLONG)ExAllocatePool2(POOL_FLAG_NON_PAGED, m_pWfExt->Format.nChannels * sizeof(LONG), MINWAVERTSTREAM_POOLTAG);
+ if (m_plVolumeLevel == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ m_plPeakMeter = (PLONG)ExAllocatePool2(POOL_FLAG_NON_PAGED, m_pWfExt->Format.nChannels * sizeof(LONG), MINWAVERTSTREAM_POOLTAG);
+ if (m_plPeakMeter == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ if (m_bCapture)
+ {
+ ReadRegistrySettings();
+ DWORD toneFrequency = 0;
+ DWORD toneAmplitude = 0;
+ DWORD toneDCOffset = 0;
+ DWORD toneInitialPhase = 0;
+
+ double toneAmplitudeDouble = 0;
+ double toneDCOffsetDouble = 0;
+ double toneInitialPhaseDouble = 0;
+
+ toneFrequency = m_ulHostCaptureToneFrequency;
+ toneAmplitude = m_dwHostCaptureToneAmplitude;
+ toneDCOffset = m_dwHostCaptureToneDCOffset;
+ toneInitialPhase = m_dwHostCaptureToneInitialPhase;
+
+ if (labs(toneAmplitude) > 100)
+ {
+ toneAmplitude = toneAmplitude > 0 ? 100 : -100;
+ }
+
+ if (labs(toneDCOffset) > 100)
+ {
+ toneDCOffset = toneDCOffset > 0 ? 100 : -100;
+ }
+
+ DWORD abssum = labs(toneAmplitude) + labs(toneDCOffset);
+
+ if (abssum > 100)
+ {
+ toneAmplitudeDouble = ((double)toneAmplitude) / abssum;
+ toneDCOffsetDouble = ((double)toneDCOffset) / abssum;
+ }
+ else
+ {
+ toneAmplitudeDouble = ((double)toneAmplitude) / 100.0;
+ toneDCOffsetDouble = ((double)toneDCOffset) / 100.0;
+ }
+
+ if (labs(toneInitialPhase) > 31416)
+ {
+ toneInitialPhase = toneInitialPhase > 0 ? 31416 : -31416;
+ }
+
+ toneInitialPhaseDouble = (double)toneInitialPhase / 10000;
+
+ ntStatus = m_ToneGenerator.Init(toneFrequency, toneAmplitudeDouble, toneDCOffsetDouble, toneInitialPhaseDouble, m_pWfExt);
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ return ntStatus;
+ }
+ }
+ else if (!g_DoNotCreateDataFiles)
+ {
+ //
+ // Create an output file for the render data.
+ //
+ DPF(D_TERSE, ("SaveData %p", &m_SaveData));
+ ntStatus = m_SaveData.SetDataFormat(DataFormat_);
+ if (NT_SUCCESS(ntStatus))
+ {
+ ntStatus = m_SaveData.Initialize();
+ }
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ return ntStatus;
+ }
+ }
+
+ //
+ // Register this stream.
+ //
+ ntStatus = m_pMiniport->StreamCreated(m_ulPin, this);
+ if (NT_SUCCESS(ntStatus))
+ {
+ m_bUnregisterStream = TRUE;
+ }
+
+ return ntStatus;
+} // Init
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(NTSTATUS)
+CMiniportWaveRTStream::NonDelegatingQueryInterface
+(
+ _In_ REFIID Interface,
+ _COM_Outptr_ PVOID * Object
+)
+/*++
+
+Routine Description:
+
+ QueryInterface
+
+Arguments:
+
+ Interface - GUID
+
+ Object - interface pointer to be returned
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(Object);
+
+ if (IsEqualGUIDAligned(Interface, IID_IUnknown))
+ {
+ *Object = PVOID(PUNKNOWN(PMINIPORTWAVERTSTREAM(this)));
+ }
+ else if (IsEqualGUIDAligned(Interface, IID_IMiniportWaveRTStream))
+ {
+ *Object = PVOID(PMINIPORTWAVERTSTREAM(this));
+ }
+ else if (IsEqualGUIDAligned(Interface, IID_IMiniportWaveRTStreamNotification))
+ {
+ *Object = PVOID(PMINIPORTWAVERTSTREAMNOTIFICATION(this));
+ }
+ else if (IsEqualGUIDAligned(Interface, IID_IMiniportWaveRTInputStream) && (this->m_bCapture))
+ {
+ // This interface is supported only on capture streams
+ *Object = PVOID(PMINIPORTWAVERTINPUTSTREAM(this));
+ }
+ else if (IsEqualGUIDAligned(Interface, IID_IMiniportWaveRTOutputStream))
+ {
+ // This interface is supported only on host render streams
+ *Object = PVOID(PMINIPORTWAVERTOUTPUTSTREAM(this));
+ }
+ else if (IsEqualGUIDAligned(Interface, IID_IDrmAudioStream))
+ {
+ *Object = (PVOID)(IDrmAudioStream*)this;
+ }
+ else
+ {
+ *Object = NULL;
+ }
+
+ if (*Object)
+ {
+ PUNKNOWN(*Object)->AddRef();
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_INVALID_PARAMETER;
+} // NonDelegatingQueryInterface
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS CMiniportWaveRTStream::AllocateBufferWithNotification
+(
+ _In_ ULONG NotificationCount_,
+ _In_ ULONG RequestedSize_,
+ _Out_ PMDL *AudioBufferMdl_,
+ _Out_ ULONG *ActualSize_,
+ _Out_ ULONG *OffsetFromFirstPage_,
+ _Out_ MEMORY_CACHING_TYPE *CacheType_
+)
+{
+ PAGED_CODE();
+
+ ULONG ulBufferDurationMs = 0;
+
+ if ( (0 == RequestedSize_) || (RequestedSize_ < m_pWfExt->Format.nBlockAlign) )
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if ((NotificationCount_ == 0) || (RequestedSize_ % NotificationCount_ != 0))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ RequestedSize_ -= RequestedSize_ % (m_pWfExt->Format.nBlockAlign);
+
+ if (!m_bCapture && (!g_DoNotCreateDataFiles))
+ {
+ NTSTATUS ntStatus;
+
+ // Simple Audio Sample uses following buffer to hold data before writing to a file.
+ // Allocating larger buffer will reduce File I/O operations.
+ ntStatus = m_SaveData.SetMaxWriteSize(RequestedSize_ * 4);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ return ntStatus;
+ }
+ }
+
+ PHYSICAL_ADDRESS highAddress;
+ highAddress.HighPart = 0;
+ highAddress.LowPart = MAXULONG;
+
+ PMDL pBufferMdl = m_pPortStream->AllocatePagesForMdl (highAddress, RequestedSize_);
+
+ if (NULL == pBufferMdl)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // From MSDN:
+ // "Since the Windows audio stack does not support a mechanism to express memory access
+ // alignment requirements for buffers, audio drivers must select a caching type for mapped
+ // memory buffers that does not impose platform-specific alignment requirements. In other
+ // words, the caching type used by the audio driver for mapped memory buffers, must not make
+ // assumptions about the memory alignment requirements for any specific platform.
+ //
+ // This method maps the physical memory pages in the MDL into kernel-mode virtual memory.
+ // Typically, the miniport driver calls this method if it requires software access to the
+ // scatter-gather list for an audio buffer. In this case, the storage for the scatter-gather
+ // list must have been allocated by the IPortWaveRTStream::AllocatePagesForMdl or
+ // IPortWaveRTStream::AllocateContiguousPagesForMdl method.
+ //
+ // A WaveRT miniport driver should not require software access to the audio buffer itself."
+ //
+ m_pDmaBuffer = (BYTE*)m_pPortStream->MapAllocatedPages(pBufferMdl, MmCached);
+ m_ulNotificationsPerBuffer = NotificationCount_;
+ m_ulDmaBufferSize = RequestedSize_;
+ ulBufferDurationMs = (RequestedSize_ * 1000) / m_ulDmaMovementRate;
+ m_ulNotificationIntervalMs = ulBufferDurationMs / NotificationCount_;
+
+ *AudioBufferMdl_ = pBufferMdl;
+ *ActualSize_ = RequestedSize_;
+ *OffsetFromFirstPage_ = 0;
+ *CacheType_ = MmCached;
+
+ return STATUS_SUCCESS;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+VOID CMiniportWaveRTStream::FreeBufferWithNotification
+(
+ _In_ PMDL Mdl_,
+ _In_ ULONG Size_
+)
+{
+ UNREFERENCED_PARAMETER(Size_);
+
+ PAGED_CODE();
+
+ if (Mdl_ != NULL)
+ {
+ if (m_pDmaBuffer != NULL)
+ {
+ m_pPortStream->UnmapAllocatedPages(m_pDmaBuffer, Mdl_);
+ m_pDmaBuffer = NULL;
+ }
+
+ m_pPortStream->FreePagesFromMdl(Mdl_);
+ }
+
+ m_ulDmaBufferSize = 0;
+ m_ulNotificationsPerBuffer = 0;
+
+ return;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS CMiniportWaveRTStream::RegisterNotificationEvent
+(
+ _In_ PKEVENT NotificationEvent_
+)
+{
+ UNREFERENCED_PARAMETER(NotificationEvent_);
+
+ PAGED_CODE();
+
+ NotificationListEntry *nleNew = (NotificationListEntry*)ExAllocatePool2(
+ POOL_FLAG_NON_PAGED,
+ sizeof(NotificationListEntry),
+ MINWAVERTSTREAM_POOLTAG);
+ if (NULL == nleNew)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ nleNew->NotificationEvent = NotificationEvent_;
+
+ // Fail if the notification event already exists in our list.
+ if (!IsListEmpty(&m_NotificationList))
+ {
+ PLIST_ENTRY leCurrent = m_NotificationList.Flink;
+ while (leCurrent != &m_NotificationList)
+ {
+ NotificationListEntry* nleCurrent = CONTAINING_RECORD( leCurrent, NotificationListEntry, ListEntry);
+ if (nleCurrent->NotificationEvent == NotificationEvent_)
+ {
+ ExFreePoolWithTag( nleNew, MINWAVERTSTREAM_POOLTAG );
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ leCurrent = leCurrent->Flink;
+ }
+ }
+
+ InsertTailList(&m_NotificationList, &(nleNew->ListEntry));
+
+ return STATUS_SUCCESS;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS CMiniportWaveRTStream::UnregisterNotificationEvent
+(
+ _In_ PKEVENT NotificationEvent_
+)
+{
+ UNREFERENCED_PARAMETER(NotificationEvent_);
+
+ PAGED_CODE();
+
+ if (!IsListEmpty(&m_NotificationList))
+ {
+ PLIST_ENTRY leCurrent = m_NotificationList.Flink;
+ while (leCurrent != &m_NotificationList)
+ {
+ NotificationListEntry* nleCurrent = CONTAINING_RECORD( leCurrent, NotificationListEntry, ListEntry);
+ if (nleCurrent->NotificationEvent == NotificationEvent_)
+ {
+ RemoveEntryList( leCurrent );
+ ExFreePoolWithTag( nleCurrent, MINWAVERTSTREAM_POOLTAG );
+ return STATUS_SUCCESS;
+ }
+
+ leCurrent = leCurrent->Flink;
+ }
+ }
+
+ return STATUS_NOT_FOUND;
+}
+
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS CMiniportWaveRTStream::GetClockRegister
+(
+ _Out_ PKSRTAUDIO_HWREGISTER Register_
+)
+{
+ UNREFERENCED_PARAMETER(Register_);
+
+ PAGED_CODE();
+
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS CMiniportWaveRTStream::GetPositionRegister
+(
+ _Out_ PKSRTAUDIO_HWREGISTER Register_
+)
+{
+ UNREFERENCED_PARAMETER(Register_);
+
+ PAGED_CODE();
+
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+VOID CMiniportWaveRTStream::GetHWLatency
+(
+ _Out_ PKSRTAUDIO_HWLATENCY Latency_
+)
+{
+ PAGED_CODE();
+
+ ASSERT(Latency_);
+
+ Latency_->ChipsetDelay = 0;
+ Latency_->CodecDelay = 0;
+ Latency_->FifoSize = 0;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+VOID CMiniportWaveRTStream::FreeAudioBuffer
+(
+_In_opt_ PMDL Mdl_,
+_In_ ULONG Size_
+)
+{
+ UNREFERENCED_PARAMETER(Size_);
+
+ PAGED_CODE();
+
+ if (Mdl_ != NULL)
+ {
+ if (m_pDmaBuffer != NULL)
+ {
+ m_pPortStream->UnmapAllocatedPages(m_pDmaBuffer, Mdl_);
+ m_pDmaBuffer = NULL;
+ }
+
+ m_pPortStream->FreePagesFromMdl(Mdl_);
+ }
+
+ m_ulDmaBufferSize = 0;
+ m_ulNotificationsPerBuffer = 0;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS CMiniportWaveRTStream::AllocateAudioBuffer
+(
+_In_ ULONG RequestedSize_,
+_Out_ PMDL *AudioBufferMdl_,
+_Out_ ULONG *ActualSize_,
+_Out_ ULONG *OffsetFromFirstPage_,
+_Out_ MEMORY_CACHING_TYPE *CacheType_
+)
+{
+ PAGED_CODE();
+
+ if ((0 == RequestedSize_) || (RequestedSize_ < m_pWfExt->Format.nBlockAlign))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ RequestedSize_ -= RequestedSize_ % (m_pWfExt->Format.nBlockAlign);
+
+ PHYSICAL_ADDRESS highAddress;
+ highAddress.HighPart = 0;
+ highAddress.LowPart = MAXULONG;
+
+ PMDL pBufferMdl = m_pPortStream->AllocatePagesForMdl(highAddress, RequestedSize_);
+
+ if (NULL == pBufferMdl)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // From MSDN:
+ // "Since the Windows audio stack does not support a mechanism to express memory access
+ // alignment requirements for buffers, audio drivers must select a caching type for mapped
+ // memory buffers that does not impose platform-specific alignment requirements. In other
+ // words, the caching type used by the audio driver for mapped memory buffers, must not make
+ // assumptions about the memory alignment requirements for any specific platform.
+ //
+ // This method maps the physical memory pages in the MDL into kernel-mode virtual memory.
+ // Typically, the miniport driver calls this method if it requires software access to the
+ // scatter-gather list for an audio buffer. In this case, the storage for the scatter-gather
+ // list must have been allocated by the IPortWaveRTStream::AllocatePagesForMdl or
+ // IPortWaveRTStream::AllocateContiguousPagesForMdl method.
+ //
+ // A WaveRT miniport driver should not require software access to the audio buffer itself."
+ //
+ m_pDmaBuffer = (BYTE*)m_pPortStream->MapAllocatedPages(pBufferMdl, MmCached);
+
+ m_ulDmaBufferSize = RequestedSize_;
+ m_ulNotificationsPerBuffer = 0;
+
+ *AudioBufferMdl_ = pBufferMdl;
+ *ActualSize_ = RequestedSize_;
+ *OffsetFromFirstPage_ = 0;
+ *CacheType_ = MmCached;
+
+ return STATUS_SUCCESS;
+}
+
+//=============================================================================
+#pragma code_seg()
+NTSTATUS CMiniportWaveRTStream::GetPosition
+(
+ _Out_ KSAUDIO_POSITION *Position_
+)
+{
+ NTSTATUS ntStatus;
+
+ KIRQL oldIrql;
+ KeAcquireSpinLock(&m_PositionSpinLock, &oldIrql);
+
+ if (m_KsState == KSSTATE_RUN)
+ {
+ //
+ // Get the current time and update position.
+ //
+ LARGE_INTEGER ilQPC = KeQueryPerformanceCounter(NULL);
+ UpdatePosition(ilQPC);
+ }
+
+ Position_->PlayOffset = m_ullPlayPosition;
+ Position_->WriteOffset = m_ullWritePosition;
+
+ KeReleaseSpinLock(&m_PositionSpinLock, oldIrql);
+
+ ntStatus = STATUS_SUCCESS;
+
+ return ntStatus;
+}
+
+//=============================================================================
+// CMiniportWaveRTStream::GetReadPacket
+//
+// Returns information about the next packet for the OS to read.
+//
+// Return value
+//
+// Returns STATUS_DEVICE_NOT_READY if no new packets are available.
+//
+// IRQL - PASSIVE_LEVEL
+//
+// Remarks
+// Although called at passive level, this routine is non-paged code because
+// it is called in the streaming path where page faults should be avoided.
+//
+// ISSUE-2014/10/4 Will this work correctly across pause/play?
+#pragma code_seg()
+_IRQL_requires_max_(PASSIVE_LEVEL)
+NTSTATUS CMiniportWaveRTStream::GetReadPacket
+(
+ _Out_ ULONG* PacketNumber,
+ _Out_ DWORD* Flags,
+ _Out_ ULONG64* PerformanceCounterValue,
+ _Out_ BOOL* MoreData
+)
+{
+ ULONG availablePacketNumber;
+ ULONG droppedPackets;
+
+ // The call must be from event driven mode
+ if (m_ulNotificationsPerBuffer == 0)
+ {
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ *Flags = 0;
+
+ if (m_KsState < KSSTATE_PAUSE)
+ {
+ return STATUS_INVALID_DEVICE_STATE;
+ }
+
+ KIRQL oldIrql;
+ KeAcquireSpinLock(&m_PositionSpinLock, &oldIrql);
+
+ LONGLONG packetCounter = m_llPacketCounter;
+ ULONGLONG ullLinearPosition = m_ullLinearPosition;
+ ULONGLONG hnsElapsedTimeCarryForward = m_hnsElapsedTimeCarryForward;
+ ULONGLONG ullDmaTimeStamp = m_ullDmaTimeStamp;
+
+ KeReleaseSpinLock(&m_PositionSpinLock, oldIrql);
+
+ // The 0-based number of the last completed packet
+ // FUTURE-2014/10/27 Update to allow different numbers of packets per WaveRT buffer
+ availablePacketNumber = LODWORD(packetCounter - 1); // Note this might be ULONG_MAX if called during the first packet
+
+ // If no new packets are available...
+ if (availablePacketNumber == m_ulLastOsReadPacket)
+ {
+ return STATUS_DEVICE_NOT_READY;
+ }
+
+ // If more than one packet has transferred since the last packet read by
+ // the OS, then those were dropped. That is, a glitch occurred.
+ droppedPackets = availablePacketNumber - m_ulLastOsReadPacket - 1;
+ if (droppedPackets > 0)
+ {
+ // Trace a glitch
+ }
+
+ // Return next packet number to be read
+ *PacketNumber = availablePacketNumber;
+
+ // Compute and return timestamp corresponding to the end of the available packet. In a real hardware
+ // driver, the timestamp would be computed in a driver and hardware specific manner. In this sample
+ // driver, it is extrapolated from the sample driver's internal simulated position correlation
+ // [m_ullLinearPosition @ m_ullDmaTimeStamp] and the sample's internal 64-bit packet counter, subtracting
+ // 1 from the packet counter to compute the time at the start of that last completed packet.
+ ULONGLONG linearPositionOfAvailablePacket = packetCounter * (m_ulDmaBufferSize / m_ulNotificationsPerBuffer);
+ // Need to divide by (1000 * 10000 because m_ulDmaMovementRate is average bytes per sec
+ ULONGLONG carryForwardBytes = (hnsElapsedTimeCarryForward * m_ulDmaMovementRate) / 10000000;
+ ULONGLONG deltaLinearPosition = ullLinearPosition + carryForwardBytes - linearPositionOfAvailablePacket;
+ ULONGLONG deltaTimeInHns = deltaLinearPosition * 10000000 / m_ulDmaMovementRate;
+ ULONGLONG timeOfAvailablePacketInHns = ullDmaTimeStamp - deltaTimeInHns;
+ ULONGLONG timeOfAvailablePacketInQpc = timeOfAvailablePacketInHns * m_ullPerformanceCounterFrequency.QuadPart / 10000000;
+
+ *PerformanceCounterValue = timeOfAvailablePacketInQpc;
+
+ // No flags are defined yet
+ *Flags = 0;
+
+ // This sample does not internally buffer data so there is never more data
+ // than revealed by the results from this routine.
+ *MoreData = FALSE;
+
+ // Update the last packet read by the OS
+ m_ulLastOsReadPacket = availablePacketNumber;
+
+ return STATUS_SUCCESS;
+}
+
+#pragma code_seg()
+_IRQL_requires_max_(PASSIVE_LEVEL)
+NTSTATUS CMiniportWaveRTStream::SetWritePacket
+(
+ _In_ ULONG PacketNumber,
+ _In_ DWORD Flags,
+ _In_ ULONG EosPacketLength
+)
+{
+ UNREFERENCED_PARAMETER(EosPacketLength);
+ NTSTATUS ntStatus;
+
+ // The call must be from event driven mode
+ if (m_ulNotificationsPerBuffer == 0)
+ {
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ ULONG oldLastOsWritePacket = m_ulLastOsWritePacket;
+
+ // This function should not be called once EoS has been set.
+ if (m_bEoSReceived)
+ {
+ return STATUS_INVALID_DEVICE_STATE;
+ }
+
+ KIRQL oldIrql;
+ KeAcquireSpinLock(&m_PositionSpinLock, &oldIrql);
+ // 1-based count of completed packets, 0-based packet number of current packet
+ LONGLONG currentPacket = m_llPacketCounter;
+ KeReleaseSpinLock(&m_PositionSpinLock, oldIrql);
+
+ // If not running, the current packet hasn't actually started transfering so OS should be writing
+ // to the current packet. If running, then the current packing is already transfering to hardware
+ // so the OS should write the packet after the current packet.
+ ULONG expectedPacket = LODWORD(currentPacket);
+ if (m_KsState == KSSTATE_RUN)
+ {
+ expectedPacket++;
+ }
+
+ // Check if OS PacketNumber is behind or too far ahead of current packet
+ LONG deltaFromExpectedPacket = PacketNumber - expectedPacket; // Modulo arithemetic
+ if (deltaFromExpectedPacket < 0)
+ {
+ return STATUS_DATA_LATE_ERROR;
+ }
+ else if (deltaFromExpectedPacket > 0)
+ {
+ return STATUS_DATA_OVERRUN;
+ }
+
+ ULONG packetSize = (m_ulDmaBufferSize / m_ulNotificationsPerBuffer);
+ ULONG packetIndex = PacketNumber % m_ulNotificationsPerBuffer;
+ ULONG ulCurrentWritePosition = packetIndex * packetSize;
+
+ // Check if EOS flag was passed
+ if (Flags & KSSTREAM_HEADER_OPTIONSF_ENDOFSTREAM)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+ else
+ {
+ m_ulLastOsWritePacket = PacketNumber;
+
+ // This function sets the current write position to the specified byte in the DMA buffer.
+ // Will check if the write position is smaller than the DMA buffer size.
+ // Will not return an error when the passed in parameter is 0.
+ // Will also check if this function was called with the same write position(in event mode only)
+ // Underruning will also be checked via timer mechanism
+ KeAcquireSpinLock(&m_PositionSpinLock, &oldIrql);
+ ntStatus = SetCurrentWritePositionInternal(ulCurrentWritePosition);
+ KeReleaseSpinLock(&m_PositionSpinLock, oldIrql);
+ }
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ m_ulLastOsWritePacket = oldLastOsWritePacket;
+ }
+
+ return ntStatus;
+}
+
+//=============================================================================
+#pragma code_seg()
+_IRQL_requires_max_(PASSIVE_LEVEL)
+NTSTATUS CMiniportWaveRTStream::GetOutputStreamPresentationPosition
+(
+ _Out_ KSAUDIO_PRESENTATION_POSITION *pPresentationPosition
+)
+{
+ ASSERT (pPresentationPosition);
+
+ // The call must be from event driven mode
+ if(m_ulNotificationsPerBuffer == 0)
+ {
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ return GetPresentationPosition(pPresentationPosition);
+}
+
+//=============================================================================
+#pragma code_seg()
+_IRQL_requires_max_(PASSIVE_LEVEL)
+NTSTATUS CMiniportWaveRTStream::GetPacketCount
+(
+ _Out_ ULONG *pPacketCount
+)
+{
+ ASSERT(pPacketCount);
+
+ // The call must be from event driven mode
+ if(m_ulNotificationsPerBuffer == 0)
+ {
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ KIRQL oldIrql;
+ KeAcquireSpinLock(&m_PositionSpinLock, &oldIrql);
+
+ if (m_KsState == KSSTATE_RUN)
+ {
+ // Get the current time and update simulated position.
+ LARGE_INTEGER ilQPC = KeQueryPerformanceCounter(NULL);
+ UpdatePosition(ilQPC);
+ }
+
+ *pPacketCount = LODWORD(m_llPacketCounter);
+ KeReleaseSpinLock(&m_PositionSpinLock, oldIrql);
+
+ return STATUS_SUCCESS;
+}
+
+//linear and presentation positions
+#pragma code_seg()
+NTSTATUS CMiniportWaveRTStream::GetPositions(
+ _Out_opt_ ULONGLONG* _pullLinearBufferPosition,
+ _Out_opt_ ULONGLONG* _pullPresentationPosition,
+ _Out_opt_ LARGE_INTEGER* _pliQPCTime
+)
+{
+ DPF_ENTER(("[CMiniportWaveRTStream::GetPositions]"));
+
+ NTSTATUS ntStatus;
+ LARGE_INTEGER ilQPC;
+ KIRQL oldIrql;
+
+ // Update *_pullLinearBufferPosition with the the number of bytes fetched from waveRT ever since a stream got set into RUN
+ // state.
+ // Once the stream is set to STOP state, any further read on this call would return zero.
+
+ //
+ // Get the current time and update position.
+ //
+ KeAcquireSpinLock(&m_PositionSpinLock, &oldIrql);
+ ilQPC = KeQueryPerformanceCounter(NULL);
+ if (m_KsState == KSSTATE_RUN)
+ {
+ UpdatePosition(ilQPC);
+ }
+ if (_pullLinearBufferPosition)
+ {
+ *_pullLinearBufferPosition = m_ullLinearPosition;
+ }
+ if (_pullPresentationPosition)
+ {
+ *_pullPresentationPosition = m_ullPresentationPosition;
+ }
+ KeReleaseSpinLock(&m_PositionSpinLock, oldIrql);
+ if (_pliQPCTime)
+ {
+ *_pliQPCTime = ilQPC;
+ }
+
+ ntStatus = STATUS_SUCCESS;
+
+ return ntStatus;
+}
+
+NTSTATUS CMiniportWaveRTStream::GetPresentationPosition(_Out_ KSAUDIO_PRESENTATION_POSITION* _pPresentationPosition)
+{
+ ASSERT(_pPresentationPosition);
+ LARGE_INTEGER timeStamp;
+
+ DPF_ENTER(("[CMiniportWaveRTStream::GetPresentationPosition]"));
+
+ ULONGLONG ullLinearPosition = { 0 };
+ ULONGLONG ullPresentationPosition = { 0 };
+ NTSTATUS status = STATUS_SUCCESS;
+
+ status = GetPositions(&ullLinearPosition, &ullPresentationPosition, &timeStamp);
+ if (!NT_SUCCESS(status))
+ {
+ return status;
+ }
+
+ _pPresentationPosition->u64PositionInBlocks = ullPresentationPosition * m_pWfExt->Format.nSamplesPerSec / m_pWfExt->Format.nAvgBytesPerSec;
+ _pPresentationPosition->u64QPCPosition = (UINT64)timeStamp.QuadPart;
+
+ return STATUS_SUCCESS;
+}
+
+#pragma code_seg()
+NTSTATUS CMiniportWaveRTStream::SetCurrentWritePositionInternal(_In_ ULONG _ulCurrentWritePosition)
+{
+ DPF_ENTER(("[CMiniportWaveRTStream::SetCurrentWritePositionInternal]"));
+
+ ASSERT(m_bEoSReceived == FALSE);
+
+ if (m_bEoSReceived)
+ {
+ return STATUS_INVALID_DEVICE_REQUEST;
+ }
+
+ if (_ulCurrentWritePosition > m_ulDmaBufferSize)
+ {
+ return STATUS_INVALID_DEVICE_REQUEST;
+ }
+
+ PADAPTERCOMMON pAdapterComm = m_pMiniport->GetAdapterCommObj();
+
+ //Event type: eMINIPORT_SET_WAVERT_BUFFER_WRITE_POSITION
+ //Parameter 1: Current linear buffer position
+ //Parameter 2: Previous WaveRtBufferWritePosition that the driver received
+ //Parameter 3: Target WaveRtBufferWritePosition received from portcls
+ //Parameter 4: 0
+ pAdapterComm->WriteEtwEvent(eMINIPORT_SET_WAVERT_BUFFER_WRITE_POSITION,
+ m_ullLinearPosition, // replace with the correct "Current linear buffer position"
+ m_ulCurrentWritePosition,
+ _ulCurrentWritePosition, // this is new write position
+ 0); // always zero
+
+//
+// Check for eMINIPORT_GLITCH_REPORT - Same WaveRT buffer write during event driven mode.
+//
+ if (m_ulNotificationIntervalMs > 0)
+ {
+ if (m_ulCurrentWritePosition == _ulCurrentWritePosition)
+ {
+ //Event type: eMINIPORT_GLITCH_REPORT
+ //Parameter 1: Current linear buffer position
+ //Parameter 2: Previous WaveRtBufferWritePosition that the driver received
+ //Parameter 3: Major glitch code: 3: Received same WaveRT buffer twice in a row during event driven mode
+ //Parameter 4: Minor code for the glitch cause
+ pAdapterComm->WriteEtwEvent(eMINIPORT_GLITCH_REPORT,
+ m_ullLinearPosition, // replace with the correct "Current linear buffer position"
+ m_ulCurrentWritePosition,
+ 3, // received same WaveRT buffer twice in a row during event driven mode
+ _ulCurrentWritePosition);
+ }
+ }
+
+ m_ulCurrentWritePosition = _ulCurrentWritePosition;
+ InterlockedExchange(&m_IsCurrentWritePositionUpdated, 1);
+
+ return STATUS_SUCCESS;
+}
+
+//=============================================================================
+#pragma code_seg()
+NTSTATUS CMiniportWaveRTStream::SetState
+(
+ _In_ KSSTATE State_
+)
+{
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ KIRQL oldIrql;
+
+ // Spew an event for a pin state change request from portcls
+ //Event type: eMINIPORT_PIN_STATE
+ switch (State_)
+ {
+ case KSSTATE_STOP:
+ if (m_KsState == KSSTATE_ACQUIRE)
+ {
+ // Acquire stream resources
+ }
+ KeAcquireSpinLock(&m_PositionSpinLock, &oldIrql);
+ // Reset DMA
+ m_llPacketCounter = 0;
+ m_ullPlayPosition = 0;
+ m_ullWritePosition = 0;
+ m_ullLinearPosition = 0;
+ m_ullPresentationPosition = 0;
+
+ // Reset OS read/write positions
+ m_ulLastOsReadPacket = ULONG_MAX;
+ m_ulCurrentWritePosition = 0;
+ m_ulLastOsWritePacket = ULONG_MAX;
+ m_bEoSReceived = FALSE;
+ m_bLastBufferRendered = FALSE;
+
+ KeReleaseSpinLock(&m_PositionSpinLock, oldIrql);
+
+ // Wait until all work items are completed.
+ if (!m_bCapture && !g_DoNotCreateDataFiles)
+ {
+ m_SaveData.WaitAllWorkItems();
+ }
+ break;
+
+ case KSSTATE_ACQUIRE:
+ if (m_KsState == KSSTATE_STOP)
+ {
+ // Acquire stream resources
+ }
+ break;
+
+ case KSSTATE_PAUSE:
+
+ if (m_KsState > KSSTATE_PAUSE)
+ {
+ //
+ // Run -> Pause
+ //
+
+ // Pause DMA
+ if (m_ulNotificationIntervalMs > 0)
+ {
+ ExCancelTimer(m_pNotificationTimer, NULL);
+ KeFlushQueuedDpcs();
+
+ // If pin is transitioning from RUN, save the time since last buffer completion event was sent
+ // so if the pin goes to RUN state again we can send the buffer completion event at correct time.
+ if (m_ullLastDPCTimeStamp > 0)
+ {
+ LARGE_INTEGER qpc;
+ LARGE_INTEGER qpcFrequency;
+ LONGLONG hnsCurrentTime;
+
+ qpc = KeQueryPerformanceCounter(&qpcFrequency);
+
+ // Convert ticks to 100ns units.
+ hnsCurrentTime = KSCONVERT_PERFORMANCE_TIME(m_ullPerformanceCounterFrequency.QuadPart, qpc);
+ m_hnsDPCTimeCarryForward = hnsCurrentTime - m_ullLastDPCTimeStamp + m_hnsDPCTimeCarryForward;
+ }
+ }
+ }
+ // This call updates the linear buffer and presentation positions.
+ GetPositions(NULL, NULL, NULL);
+ break;
+
+ case KSSTATE_RUN:
+ // Start DMA
+ LARGE_INTEGER ullPerfCounterTemp;
+ ullPerfCounterTemp = KeQueryPerformanceCounter(&m_ullPerformanceCounterFrequency);
+ m_ullLastDPCTimeStamp = m_ullDmaTimeStamp = KSCONVERT_PERFORMANCE_TIME(m_ullPerformanceCounterFrequency.QuadPart, ullPerfCounterTemp);
+
+ if (m_ulNotificationIntervalMs > 0)
+ {
+ // Set timer for 1 ms. This will cause DPC to run every 1 ms but driver will send out
+ // notification events only after notification interval. This timer is used by Simple Audio Sample to
+ // emulate hardware and send out notification event. Real hardware should not use this
+ // timer to fire notification event as it will drain power if the timer is running at 1 msec.
+ ExSetTimer
+ (
+ m_pNotificationTimer,
+ (-1) * HNSTIME_PER_MILLISECOND,
+ HNSTIME_PER_MILLISECOND, // 1 ms
+ NULL
+ );
+
+ }
+
+ break;
+ }
+
+ m_KsState = State_;
+
+ return ntStatus;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS CMiniportWaveRTStream::SetFormat
+(
+ _In_ KSDATAFORMAT *DataFormat_
+)
+{
+ UNREFERENCED_PARAMETER(DataFormat_);
+
+ PAGED_CODE();
+
+ //if (!m_fCapture && !g_DoNotCreateDataFiles)
+ //{
+ // ntStatus = m_SaveData.SetDataFormat(Format);
+ //}
+
+ return STATUS_NOT_SUPPORTED;
+}
+
+#pragma code_seg()
+
+//=============================================================================
+#pragma code_seg()
+VOID CMiniportWaveRTStream::UpdatePosition
+(
+ _In_ LARGE_INTEGER ilQPC
+)
+{
+ // Convert ticks to 100ns units.
+ LONGLONG hnsCurrentTime = KSCONVERT_PERFORMANCE_TIME(m_ullPerformanceCounterFrequency.QuadPart, ilQPC);
+
+ // Calculate the time elapsed since the last call to GetPosition() or since the
+ // DMA engine started. Note that the division by 10000 to convert to milliseconds
+ // may cause us to lose some of the time, so we will carry the remainder forward
+ // to the next GetPosition() call.
+ //
+ ULONG TimeElapsedInMS = (ULONG)(hnsCurrentTime - m_ullDmaTimeStamp + m_hnsElapsedTimeCarryForward)/10000;
+
+ // Carry forward the remainder of this division so we don't fall behind with our position too much.
+ //
+ m_hnsElapsedTimeCarryForward = (hnsCurrentTime - m_ullDmaTimeStamp + m_hnsElapsedTimeCarryForward) % 10000;
+
+ // Calculate how many bytes in the DMA buffer would have been processed in the elapsed
+ // time. Note that the division by 1000 to convert to milliseconds may cause us to
+ // lose some bytes, so we will carry the remainder forward to the next GetPosition() call.
+ //
+ // need to divide by 1000 because m_ulDmaMovementRate is average bytes per sec.
+
+ ULONG ByteDisplacement = ((m_ulDmaMovementRate * TimeElapsedInMS) + m_byteDisplacementCarryForward) / 1000 ;
+ m_byteDisplacementCarryForward = ((m_ulDmaMovementRate * TimeElapsedInMS) + m_byteDisplacementCarryForward) % 1000;
+
+ // Increment presentation position even after last buffer is rendered.
+ m_ullPresentationPosition += ByteDisplacement;
+
+ if (m_bCapture)
+ {
+ // Write sine wave to buffer.
+ WriteBytes(ByteDisplacement);
+ }
+ else
+ {
+
+ if (m_bEoSReceived)
+ {
+ // since EoS flag is set, we'll need to make sure not to read data beyond EOS position.
+ // If driver's current position is less than EoS position, then make sure not to read data beyond EoS.
+ if (m_ullWritePosition <= m_ulCurrentWritePosition)
+ {
+ ByteDisplacement = min(ByteDisplacement, m_ulCurrentWritePosition - (ULONG)m_ullWritePosition);
+ }
+ // If our current position is ahead of EoS position and we'll wrap around after new position then adjust
+ // new position if it crosses EoS.
+ else if ((m_ullWritePosition + ByteDisplacement) % m_ulDmaBufferSize < m_ullWritePosition)
+ {
+ if ((m_ullWritePosition + ByteDisplacement) % m_ulDmaBufferSize > m_ulCurrentWritePosition)
+ {
+ ByteDisplacement = ByteDisplacement - (((ULONG)m_ullWritePosition + ByteDisplacement) % m_ulDmaBufferSize - m_ulCurrentWritePosition);
+ }
+ }
+ }
+
+ // If the last packet was rendered(read in the sample driver's case), send out an etw event.
+ if (m_bEoSReceived && !m_bLastBufferRendered
+ && (m_ullWritePosition + ByteDisplacement) % m_ulDmaBufferSize == m_ulCurrentWritePosition)
+ {
+ m_bLastBufferRendered = TRUE;
+ }
+
+ if (!g_DoNotCreateDataFiles)
+ {
+ // Read from buffer and write to a file.
+ ReadBytes(ByteDisplacement);
+ }
+ }
+
+ // Increment the DMA position by the number of bytes displaced since the last
+ // call to UpdatePosition() and ensure we properly wrap at buffer length.
+ //
+ m_ullPlayPosition = m_ullWritePosition =
+ (m_ullWritePosition + ByteDisplacement) % m_ulDmaBufferSize;
+
+ // m_ullDmaTimeStamp is updated in both GetPostion and GetLinearPosition calls
+ // so m_ullLinearPosition needs to be updated accordingly here
+ //
+ m_ullLinearPosition += ByteDisplacement;
+
+ // Update the DMA time stamp for the next call to GetPosition()
+ //
+ m_ullDmaTimeStamp = hnsCurrentTime;
+}
+
+//=============================================================================
+#pragma code_seg()
+VOID CMiniportWaveRTStream::WriteBytes
+(
+ _In_ ULONG ByteDisplacement
+)
+/*++
+
+Routine Description:
+
+This function writes the audio buffer using a sine wave generator
+
+Arguments:
+
+ByteDisplacement - # of bytes to process.
+
+--*/
+{
+ ULONG bufferOffset = m_ullLinearPosition % m_ulDmaBufferSize;
+
+ // Normally this will loop no more than once for a single wrap, but if
+ // many bytes have been displaced then this may loops many times.
+ while (ByteDisplacement > 0)
+ {
+ ULONG runWrite = min(ByteDisplacement, m_ulDmaBufferSize - bufferOffset);
+
+ m_ToneGenerator.GenerateSine(m_pDmaBuffer + bufferOffset, runWrite);
+
+ bufferOffset = (bufferOffset + runWrite) % m_ulDmaBufferSize;
+ ByteDisplacement -= runWrite;
+ }
+}
+
+//=============================================================================
+#pragma code_seg()
+VOID CMiniportWaveRTStream::ReadBytes
+(
+ _In_ ULONG ByteDisplacement
+)
+/*++
+
+Routine Description:
+
+This function reads the audio buffer and saves the data in a file.
+
+Arguments:
+
+ByteDisplacement - # of bytes to process.
+
+--*/
+{
+ ULONG bufferOffset = m_ullLinearPosition % m_ulDmaBufferSize;
+
+ // Normally this will loop no more than once for a single wrap, but if
+ // many bytes have been displaced then this may loops many times.
+ while (ByteDisplacement > 0)
+ {
+ ULONG runWrite = min(ByteDisplacement, m_ulDmaBufferSize - bufferOffset);
+ m_SaveData.WriteData(m_pDmaBuffer + bufferOffset, runWrite);
+ bufferOffset = (bufferOffset + runWrite) % m_ulDmaBufferSize;
+ ByteDisplacement -= runWrite;
+ }
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+STDMETHODIMP_(NTSTATUS)
+CMiniportWaveRTStream::SetContentId
+(
+ _In_ ULONG contentId,
+ _In_ PCDRMRIGHTS drmRights
+)
+/*++
+
+Routine Description:
+
+ Sets DRM content Id for this stream. Also updates the Mixed content Id.
+
+Arguments:
+
+ contentId - new content id
+
+ drmRights - rights for this stream.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMiniportWaveRT::SetContentId]"));
+
+ NTSTATUS ntStatus;
+ ULONG ulOldContentId = contentId;
+
+ m_ulContentId = contentId;
+
+ //
+ // Miniport should create a mixed DrmRights.
+ //
+ ntStatus = m_pMiniport->UpdateDrmRights();
+
+ //
+ // Restore the passed-in content Id.
+ //
+ if (!NT_SUCCESS(ntStatus))
+ {
+ m_ulContentId = ulOldContentId;
+ }
+
+ //
+ // Simple Audio Sample writes each stream seperately to disk. If the rights for this
+ // stream indicates that the stream is CopyProtected, stop writing to disk.
+ //
+ m_SaveData.Disable(drmRights->CopyProtect);
+
+ //
+ // From MSDN:
+ //
+ // This sample doesn't forward protected content, but if your driver uses
+ // lower layer drivers or a different stack to properly work, please see the
+ // following info from MSDN:
+ //
+ // "Before allowing protected content to flow through a data path, the system
+ // verifies that the data path is secure. To do so, the system authenticates
+ // each module in the data path beginning at the upstream end of the data path
+ // and moving downstream. As each module is authenticated, that module gives
+ // the system information about the next module in the data path so that it
+ // can also be authenticated. To be successfully authenticated, a module's
+ // binary file must be signed as DRM-compliant.
+ //
+ // Two adjacent modules in the data path can communicate with each other in
+ // one of several ways. If the upstream module calls the downstream module
+ // through IoCallDriver, the downstream module is part of a WDM driver. In
+ // this case, the upstream module calls the DrmForwardContentToDeviceObject
+ // function to provide the system with the device object representing the
+ // downstream module. (If the two modules communicate through the downstream
+ // module's COM interface or content handlers, the upstream module calls
+ // DrmForwardContentToInterface or DrmAddContentHandlers instead.)
+ //
+ // DrmForwardContentToDeviceObject performs the same function as
+ // PcForwardContentToDeviceObject and IDrmPort2::ForwardContentToDeviceObject."
+ //
+ // Other supported DRM DDIs for down-level module validation are:
+ // DrmForwardContentToInterfaces and DrmAddContentHandlers.
+ //
+ // For more information, see MSDN's DRM Functions and Interfaces.
+ //
+
+ return ntStatus;
+} // SetContentId
+
+//=============================================================================
+#pragma code_seg()
+void
+TimerNotifyRT
+(
+ _In_ PEX_TIMER Timer,
+ _In_opt_ PVOID DeferredContext
+)
+{
+ LARGE_INTEGER qpc;
+ LARGE_INTEGER qpcFrequency;
+ BOOL bufferCompleted = FALSE;
+
+ UNREFERENCED_PARAMETER(Timer);
+
+ _IRQL_limited_to_(DISPATCH_LEVEL);
+
+ CMiniportWaveRTStream* _this = (CMiniportWaveRTStream*)DeferredContext;
+
+ if (NULL == _this)
+ {
+ return;
+ }
+
+ KIRQL oldIrql;
+ KeAcquireSpinLock(&_this->m_PositionSpinLock, &oldIrql);
+
+ qpc = KeQueryPerformanceCounter(&qpcFrequency);
+
+ // Convert ticks to 100ns units.
+ LONGLONG hnsCurrentTime = KSCONVERT_PERFORMANCE_TIME(_this->m_ullPerformanceCounterFrequency.QuadPart, qpc);
+
+ // Calculate the time elapsed since the last we ran DPC that matched Notification interval. Note that the division by 10000
+ // to convert to milliseconds may cause us to lose some of the time, so we will carry the remainder forward.
+
+ ULONG TimeElapsedInMS = (ULONG)(hnsCurrentTime - _this->m_ullLastDPCTimeStamp + _this->m_hnsDPCTimeCarryForward)/10000;
+
+ if (TimeElapsedInMS >= _this->m_ulNotificationIntervalMs)
+ {
+ // Carry forward the time greater than notification interval to adjust time to signal next buffer completion event accordingly.
+ _this->m_hnsDPCTimeCarryForward = hnsCurrentTime - _this->m_ullLastDPCTimeStamp + _this->m_hnsDPCTimeCarryForward - (_this->m_ulNotificationIntervalMs * 10000);
+ // Save the last time DPC ran at notification interval
+ _this->m_ullLastDPCTimeStamp = hnsCurrentTime;
+ bufferCompleted = TRUE;
+ }
+
+ if (!bufferCompleted && !_this->m_bEoSReceived)
+ {
+ goto End;
+ }
+
+ _this->UpdatePosition(qpc);
+
+ if (!_this->m_bEoSReceived)
+ {
+ _this->m_llPacketCounter++;
+ }
+
+ if (_this->m_KsState != KSSTATE_RUN)
+ {
+ goto End;
+ }
+
+ PADAPTERCOMMON pAdapterComm = _this->m_pMiniport->GetAdapterCommObj();
+
+ // Simple buffer underrun detection.
+ if (!_this->IsCurrentWaveRTWritePositionUpdated() && !_this->m_bEoSReceived)
+ {
+ //Event type: eMINIPORT_GLITCH_REPORT
+ //Parameter 1: Current linear buffer position
+ //Parameter 2: Previous WaveRtBufferWritePosition that the driver received
+ //Parameter 3: Major glitch code: 1:WaveRT buffer is underrun
+ //Parameter 4: Minor code for the glitch cause
+ pAdapterComm->WriteEtwEvent(eMINIPORT_GLITCH_REPORT,
+ _this->m_ullLinearPosition,
+ _this->GetCurrentWaveRTWritePosition(),
+ 1, // WaveRT buffer is underrun
+ 0);
+ }
+
+ // Send buffer completion event if either of the following is true
+ // 1. Driver consumed a complete buffer for this stream
+ // 2. Driver consumed a partial buffer containing EoS for this stream
+
+ if (!IsListEmpty(&_this->m_NotificationList) &&
+ (bufferCompleted || _this->m_bLastBufferRendered))
+ {
+ PLIST_ENTRY leCurrent = _this->m_NotificationList.Flink;
+ while (leCurrent != &_this->m_NotificationList)
+ {
+ NotificationListEntry* nleCurrent = CONTAINING_RECORD( leCurrent, NotificationListEntry, ListEntry);
+ KeSetEvent(nleCurrent->NotificationEvent, 0, 0);
+
+ leCurrent = leCurrent->Flink;
+ }
+ }
+
+ if (_this->m_bLastBufferRendered)
+ {
+ ExCancelTimer(_this->m_pNotificationTimer, NULL);
+ }
+
+End:
+ KeReleaseSpinLock(&_this->m_PositionSpinLock, oldIrql);
+ return;
+}
+//=============================================================================
+
diff --git a/audio/simpleaudiosample/Source/Main/minwavertstream.h b/audio/simpleaudiosample/Source/Main/minwavertstream.h
new file mode 100644
index 00000000..5545e0d8
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Main/minwavertstream.h
@@ -0,0 +1,248 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ minwavertstream.h
+
+Abstract:
+
+ Definition of wavert miniport class.
+--*/
+
+#ifndef _SIMPLEAUDIOSAMPLE_MINWAVERTSTREAM_H_
+#define _SIMPLEAUDIOSAMPLE_MINWAVERTSTREAM_H_
+
+#include "savedata.h"
+#include "ToneGenerator.h"
+
+//
+// Structure to store notifications events in a protected list
+//
+typedef struct _NotificationListEntry
+{
+ LIST_ENTRY ListEntry;
+ PKEVENT NotificationEvent;
+} NotificationListEntry;
+
+EXT_CALLBACK TimerNotifyRT;
+
+//=============================================================================
+// Referenced Forward
+//=============================================================================
+class CMiniportWaveRT;
+typedef CMiniportWaveRT *PCMiniportWaveRT;
+
+//=============================================================================
+// Classes
+//=============================================================================
+///////////////////////////////////////////////////////////////////////////////
+// CMiniportWaveRTStream
+//
+class CMiniportWaveRTStream :
+ public IDrmAudioStream,
+ public IMiniportWaveRTStreamNotification,
+ public IMiniportWaveRTInputStream,
+ public IMiniportWaveRTOutputStream,
+ public CUnknown
+{
+protected:
+ PPORTWAVERTSTREAM m_pPortStream;
+ LIST_ENTRY m_NotificationList;
+ PEX_TIMER m_pNotificationTimer;
+ ULONG m_ulNotificationIntervalMs;
+ ULONG m_ulCurrentWritePosition;
+ LONG m_IsCurrentWritePositionUpdated;
+
+public:
+ DECLARE_STD_UNKNOWN();
+ DEFINE_STD_CONSTRUCTOR(CMiniportWaveRTStream);
+ ~CMiniportWaveRTStream();
+
+ IMP_IMiniportWaveRTStream;
+ IMP_IMiniportWaveRTStreamNotification;
+ IMP_IMiniportWaveRTInputStream;
+ IMP_IMiniportWaveRTOutputStream;
+ IMP_IMiniportWaveRT;
+ IMP_IDrmAudioStream;
+
+ NTSTATUS Init
+ (
+ _In_ PCMiniportWaveRT Miniport,
+ _In_ PPORTWAVERTSTREAM Stream,
+ _In_ ULONG Channel,
+ _In_ BOOLEAN Capture,
+ _In_ PKSDATAFORMAT DataFormat,
+ _In_ GUID SignalProcessingMode
+ );
+
+ // Friends
+ friend class CMiniportWaveRT;
+ friend EXT_CALLBACK TimerNotifyRT;
+protected:
+ CMiniportWaveRT* m_pMiniport;
+ ULONG m_ulPin;
+ BOOLEAN m_bCapture;
+ BOOLEAN m_bUnregisterStream;
+ ULONG m_ulDmaBufferSize;
+ BYTE* m_pDmaBuffer;
+ ULONG m_ulNotificationsPerBuffer;
+ KSSTATE m_KsState;
+ PKTIMER m_pTimer;
+ PRKDPC m_pDpc;
+ ULONGLONG m_ullPlayPosition;
+ ULONGLONG m_ullWritePosition;
+ ULONGLONG m_ullLinearPosition;
+ ULONGLONG m_ullPresentationPosition;
+ ULONG m_ulLastOsReadPacket;
+ ULONG m_ulLastOsWritePacket;
+ LONGLONG m_llPacketCounter;
+ ULONGLONG m_ullDmaTimeStamp;
+ LARGE_INTEGER m_ullPerformanceCounterFrequency;
+ ULONGLONG m_hnsElapsedTimeCarryForward;
+ ULONGLONG m_ullLastDPCTimeStamp;
+ ULONGLONG m_hnsDPCTimeCarryForward;
+ ULONG m_byteDisplacementCarryForward;
+ ULONG m_ulDmaMovementRate;
+ BOOL m_bLfxEnabled;
+ PBOOL m_pbMuted;
+ PLONG m_plVolumeLevel;
+ PLONG m_plPeakMeter;
+ PWAVEFORMATEXTENSIBLE m_pWfExt;
+ ULONG m_ulContentId;
+ CSaveData m_SaveData;
+ ToneGenerator m_ToneGenerator;
+ GUID m_SignalProcessingMode;
+ BOOLEAN m_bEoSReceived;
+ BOOLEAN m_bLastBufferRendered;
+ KSPIN_LOCK m_PositionSpinLock;
+ // Member variable as config params for tone generator
+ ULONG m_ulHostCaptureToneFrequency;
+ // If abs(m_dwHostCaptureToneAmplitude) + abs(m_dwHostCaptureToneDCValue) > 100
+ // m_dwHostCaptureToneDCValue will be compensated to make the sum equal to 100
+ DWORD m_dwHostCaptureToneAmplitude; // must be between -100 to 100
+ DWORD m_dwLoopbackCaptureToneAmplitude; // must be between -100 to 100
+ DWORD m_dwHostCaptureToneDCOffset; // must be between -100 to 100
+ DWORD m_dwLoopbackCaptureToneDCOffset; // must be between -100 to 100
+ DWORD m_dwHostCaptureToneInitialPhase; // must be between -31416 to 31416
+ DWORD m_dwLoopbackCaptureToneInitialPhase; // must be between -31416 to 31416
+ // Member variable as config params for tone generator
+
+public:
+
+ NTSTATUS GetVolumeChannelCount
+ (
+ _Out_ UINT32* puiChannelCount
+ );
+
+ NTSTATUS GetVolumeSteppings
+ (
+ _Out_writes_bytes_(_ui32DataSize) PKSPROPERTY_STEPPING_LONG _pKsPropStepLong,
+ _In_ UINT32 _ui32DataSize
+ );
+
+ NTSTATUS GetChannelVolume
+ (
+ _In_ UINT32 _uiChannel,
+ _Out_ LONG* _pVolume
+ );
+
+ NTSTATUS SetChannelVolume
+ (
+ _In_ UINT32 _uiChannel,
+ _In_ LONG _Volume
+ );
+
+ NTSTATUS GetMuteChannelCount
+ (
+ _Out_ UINT32* puiChannelCount
+ );
+
+ NTSTATUS GetMuteSteppings
+ (
+ _Out_writes_bytes_(_ui32DataSize) PKSPROPERTY_STEPPING_LONG _pKsPropStepLong,
+ _In_ UINT32 _ui32DataSize
+ );
+
+ NTSTATUS GetChannelMute
+ (
+ _In_ UINT32 _uiChannel,
+ _Out_ BOOL* _pbMute
+ );
+
+ NTSTATUS SetChannelMute
+ (
+ _In_ UINT32 _uiChannel,
+ _In_ BOOL _bMute
+ );
+
+ //presentation
+ NTSTATUS GetPresentationPosition
+ (
+ _Out_ KSAUDIO_PRESENTATION_POSITION *_pPresentationPosition
+ );
+
+ NTSTATUS SetCurrentWritePosition
+ (
+ _In_ ULONG ulCurrentWritePosition
+ );
+
+
+ ULONG GetCurrentWaveRTWritePosition()
+ {
+ return m_ulCurrentWritePosition;
+ };
+
+ // To support simple underrun validation.
+ BOOL IsCurrentWaveRTWritePositionUpdated()
+ {
+ return InterlockedExchange(&m_IsCurrentWritePositionUpdated, 0) ? TRUE : FALSE;
+ };
+
+ GUID GetSignalProcessingMode()
+ {
+ return m_SignalProcessingMode;
+ }
+
+private:
+
+ //
+ // Helper functions.
+ //
+
+#pragma code_seg()
+
+ VOID WriteBytes
+ (
+ _In_ ULONG ByteDisplacement
+ );
+
+ VOID ReadBytes
+ (
+ _In_ ULONG ByteDisplacement
+ );
+
+ VOID UpdatePosition
+ (
+ _In_ LARGE_INTEGER ilQPC
+ );
+
+ NTSTATUS SetCurrentWritePositionInternal
+ (
+ _In_ ULONG ulCurrentWritePosition
+ );
+
+ NTSTATUS GetPositions
+ (
+ _Out_opt_ ULONGLONG * _pullLinearBufferPosition,
+ _Out_opt_ ULONGLONG * _pullPresentationPosition,
+ _Out_opt_ LARGE_INTEGER * _pliQPCTime
+ );
+
+ NTSTATUS ReadRegistrySettings();
+
+};
+typedef CMiniportWaveRTStream *PCMiniportWaveRTStream;
+#endif // _SIMPLEAUDIOSAMPLE_MINWAVERTSTREAM_H_
+
diff --git a/audio/simpleaudiosample/Source/Utilities/ToneGenerator.cpp b/audio/simpleaudiosample/Source/Utilities/ToneGenerator.cpp
new file mode 100644
index 00000000..f50e81e1
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Utilities/ToneGenerator.cpp
@@ -0,0 +1,285 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ ToneGenerator
+
+Abstract:
+
+ Implementation of Simple Audio Sample sine wave generator
+
+--*/
+#include "definitions.h"
+#include "ToneGenerator.h"
+
+const double TWO_PI = M_PI * 2;
+
+extern DWORD g_DisableToneGenerator;
+
+//
+// Double to long conversion.
+//
+long ConvertToLong(double Value)
+{
+ return (long)(Value * _I32_MAX);
+};
+
+//
+// Double to short conversion.
+//
+short ConvertToShort(double Value)
+{
+ return (short)(Value * _I16_MAX);
+};
+
+//
+// Double to char conversion.
+//
+unsigned char ConvertToUChar(double Value)
+{
+ const double F_127_5 = 127.5;
+ return (unsigned char)(Value * F_127_5 + F_127_5);
+};
+
+//
+// Ctor: basic init.
+//
+ToneGenerator::ToneGenerator()
+: m_Frequency(0),
+ m_ChannelCount(0),
+ m_BitsPerSample(0),
+ m_SamplesPerSecond(0),
+ m_Mute(false),
+ m_PartialFrame(NULL),
+ m_PartialFrameBytes(0),
+ m_FrameSize(0)
+{
+ // Theta (double) and SampleIncrement (double) are init in the Init() method
+ // after saving the floating point state.
+}
+
+//
+// Dtor: free resources.
+//
+ToneGenerator::~ToneGenerator()
+{
+ if (m_PartialFrame)
+ {
+ ExFreePoolWithTag(m_PartialFrame, SIMPLEAUDIOSAMPLE_POOLTAG);
+ m_PartialFrame = NULL;
+ m_PartialFrameBytes = 0;
+ }
+}
+
+//
+// Init a new frame.
+// Note: caller will save and restore the floatingpoint state.
+//
+#pragma warning(push)
+// Caller wraps this routine between KeSaveFloatingPointState/KeRestoreFloatingPointState calls.
+#pragma warning(disable: 28110)
+
+VOID ToneGenerator::InitNewFrame
+(
+ _Out_writes_bytes_(FrameSize) BYTE* Frame,
+ _In_ DWORD FrameSize
+)
+{
+ double sinValue = m_ToneDCOffset + m_ToneAmplitude * sin( m_Theta );
+
+ if (FrameSize != (DWORD)m_ChannelCount * m_BitsPerSample/8)
+ {
+ ASSERT(FALSE);
+ RtlZeroMemory(Frame, FrameSize);
+ return;
+ }
+
+ for(ULONG i = 0; i < m_ChannelCount; ++i)
+ {
+ if (m_BitsPerSample == 8)
+ {
+ unsigned char *dataBuffer = reinterpret_cast<unsigned char *>(Frame);
+ dataBuffer[i] = ConvertToUChar(sinValue);
+ }
+ else if (m_BitsPerSample == 16)
+ {
+ short *dataBuffer = reinterpret_cast<short *>(Frame);
+ dataBuffer[i] = ConvertToShort(sinValue);
+ }
+ else if (m_BitsPerSample == 24)
+ {
+ BYTE *dataBuffer = Frame;
+ long val = ConvertToLong(sinValue);
+ val = val >> 8;
+ RtlCopyMemory(dataBuffer, &val, 3);
+ }
+ else if (m_BitsPerSample == 32)
+ {
+ long *dataBuffer = reinterpret_cast<long *>(Frame);
+ dataBuffer[i] = ConvertToLong(sinValue);
+ }
+ }
+
+ m_Theta += m_SampleIncrement;
+ if (m_Theta >= TWO_PI)
+ {
+ m_Theta -= TWO_PI;
+ }
+}
+#pragma warning(pop)
+
+//
+// GenerateSamples()
+//
+// Generate a sine wave that fits into the specified buffer.
+//
+// Buffer - Buffer to hold the samples
+// BufferLength - Length of the buffer.
+//
+//
+void ToneGenerator::GenerateSine
+(
+ _Out_writes_bytes_(BufferLength) BYTE *Buffer,
+ _In_ size_t BufferLength
+)
+{
+ NTSTATUS status;
+ KFLOATING_SAVE saveData;
+ BYTE * buffer;
+ size_t length;
+ size_t copyBytes;
+
+ // if muted, or tone generator disabled via registry,
+ // we deliver silence.
+ if (m_Mute || g_DisableToneGenerator)
+ {
+ goto ZeroBuffer;
+ }
+
+ status = KeSaveFloatingPointState(&saveData);
+ if (!NT_SUCCESS(status))
+ {
+ goto ZeroBuffer;
+ }
+
+ buffer = Buffer;
+ length = BufferLength;
+
+ //
+ // Check if we have any residual frame bytes from the last time.
+ //
+ if (m_PartialFrameBytes)
+ {
+ ASSERT(m_FrameSize > m_PartialFrameBytes);
+ DWORD offset = m_FrameSize - m_PartialFrameBytes;
+ copyBytes = MIN(m_PartialFrameBytes, length);
+ RtlCopyMemory(buffer, m_PartialFrame + offset, copyBytes);
+ RtlZeroMemory(m_PartialFrame + offset, copyBytes);
+ length -= copyBytes;
+ buffer += copyBytes;
+ m_PartialFrameBytes = 0;
+ }
+
+ IF_TRUE_JUMP(length == 0, Done);
+
+ //
+ // Copy all the aligned frames.
+ //
+
+ size_t frames = length/m_FrameSize;
+
+ for (size_t i = 0; i < frames; ++i)
+ {
+ InitNewFrame(buffer, m_FrameSize);
+ buffer += m_FrameSize;
+ length -= m_FrameSize;
+ }
+
+ IF_TRUE_JUMP(length == 0, Done);
+
+ //
+ // Copy any partial frame at the end.
+ //
+ ASSERT(m_FrameSize > length);
+ InitNewFrame(m_PartialFrame, m_FrameSize);
+ RtlCopyMemory(buffer, m_PartialFrame, length);
+ RtlZeroMemory(m_PartialFrame, length);
+ m_PartialFrameBytes = m_FrameSize - (DWORD)length;
+
+Done:
+ KeRestoreFloatingPointState(&saveData);
+ return;
+
+ZeroBuffer:
+ RtlZeroMemory(Buffer, BufferLength);
+ return;
+}
+
+NTSTATUS ToneGenerator::Init
+(
+ _In_ DWORD ToneFrequency,
+ _In_ double ToneAmplitude,
+ _In_ double ToneDCOffset,
+ _In_ double ToneInitialPhase,
+ _In_ PWAVEFORMATEXTENSIBLE WfExt
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ KFLOATING_SAVE saveData;
+
+ //
+ // This sample supports PCM formats only.
+ //
+ if ((WfExt->Format.wFormatTag != WAVE_FORMAT_PCM &&
+ !(WfExt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
+ IsEqualGUIDAligned(WfExt->SubFormat, KSDATAFORMAT_SUBTYPE_PCM))))
+ {
+ status = STATUS_NOT_SUPPORTED;
+ }
+ IF_FAILED_JUMP(status, Done);
+
+ //
+ // Save floating state (just in case).
+ //
+ status = KeSaveFloatingPointState(&saveData);
+ IF_FAILED_JUMP(status, Done);
+
+ //
+ // Basic init.
+ //
+ m_Theta = ToneInitialPhase;
+ m_Frequency = ToneFrequency;
+ m_ToneAmplitude = ToneAmplitude;
+ m_ToneDCOffset = ToneDCOffset;
+
+ m_ChannelCount = WfExt->Format.nChannels; // # channels.
+ m_BitsPerSample = WfExt->Format.wBitsPerSample; // bits per sample.
+ m_SamplesPerSecond = WfExt->Format.nSamplesPerSec; // samples per sec.
+ m_Mute = false;
+ m_SampleIncrement = (m_Frequency * TWO_PI) / (double)m_SamplesPerSecond;
+ m_FrameSize = (DWORD)m_ChannelCount * m_BitsPerSample/8;
+ ASSERT(m_FrameSize == WfExt->Format.nBlockAlign);
+
+ //
+ // Restore floating state.
+ //
+ KeRestoreFloatingPointState(&saveData);
+
+ //
+ // Allocate a buffer to hold a partial frame.
+ //
+ m_PartialFrame = (BYTE*)ExAllocatePool2(
+ POOL_FLAG_NON_PAGED,
+ m_FrameSize,
+ SIMPLEAUDIOSAMPLE_POOLTAG);
+
+ IF_TRUE_ACTION_JUMP(m_PartialFrame == NULL, status = STATUS_INSUFFICIENT_RESOURCES, Done);
+
+ status = STATUS_SUCCESS;
+
+Done:
+ return status;
+}
+
diff --git a/audio/simpleaudiosample/Source/Utilities/ToneGenerator.h b/audio/simpleaudiosample/Source/Utilities/ToneGenerator.h
new file mode 100644
index 00000000..85b1229a
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Utilities/ToneGenerator.h
@@ -0,0 +1,74 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ ToneGenerator.h
+
+Abstract:
+
+ Declaration of Simple Audio Sample sine wave generator.
+--*/
+#ifndef _SIMPLEAUDIOSAMPLE_TONEGENERATOR_H
+#define _SIMPLEAUDIOSAMPLE_TONEGENERATOR_H
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+#include <limits.h>
+
+class ToneGenerator
+{
+public:
+ DWORD m_Frequency;
+ WORD m_ChannelCount;
+ WORD m_BitsPerSample;
+ DWORD m_SamplesPerSecond;
+ double m_Theta;
+ double m_SampleIncrement;
+ bool m_Mute;
+ BYTE* m_PartialFrame;
+ DWORD m_PartialFrameBytes;
+ DWORD m_FrameSize;
+ double m_ToneAmplitude;
+ double m_ToneDCOffset;
+
+public:
+ ToneGenerator();
+ ~ToneGenerator();
+
+ NTSTATUS
+ Init
+ (
+ _In_ DWORD ToneFrequency,
+ _In_ double ToneAmplitude,
+ _In_ double ToneDCOffset,
+ _In_ double ToneInitialPhase,
+ _In_ PWAVEFORMATEXTENSIBLE WfExt
+ );
+
+ VOID
+ GenerateSine
+ (
+ _Out_writes_bytes_(BufferLength) BYTE *Buffer,
+ _In_ size_t BufferLength
+ );
+
+ VOID
+ SetMute
+ (
+ _In_ bool Value
+ )
+ {
+ m_Mute = Value;
+ }
+
+private:
+ VOID InitNewFrame
+ (
+ _Out_writes_bytes_(FrameSize) BYTE* Frame,
+ _In_ DWORD FrameSize
+ );
+};
+
+#endif // _SIMPLEAUDIOSAMPLE_TONEGENERATOR_H
diff --git a/audio/simpleaudiosample/Source/Utilities/Utilities.vcxproj b/audio/simpleaudiosample/Source/Utilities/Utilities.vcxproj
new file mode 100644
index 00000000..0a71bf42
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Utilities/Utilities.vcxproj
@@ -0,0 +1,284 @@
+<?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|ARM64">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM64">
+ <Configuration>Release</Configuration>
+ <Platform>ARM64</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>{33E61864-6F2C-4F9F-BE70-8F8985A4F283}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{F51739CE-5253-42B5-9191-57F28B5842C6}</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>StaticLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>StaticLibrary</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>StaticLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>StaticLibrary</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>StaticLibrary</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>StaticLibrary</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 Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
+ <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 Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
+ <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" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>Utilities</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <TargetName>Utilities</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>Utilities</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <TargetName>Utilities</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>Utilities</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>Utilities</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\Inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_</PreprocessorDefinitions>
+ </Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="hw.cpp" />
+ <ClCompile Include="kshelper.cpp" />
+ <ClCompile Include="savedata.cpp" />
+ <ClCompile Include="tonegenerator.cpp" />
+ </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>
diff --git a/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj.Filters b/audio/simpleaudiosample/Source/Utilities/Utilities.vcxproj.Filters
index c57611a0..7a4ebde2 100644
--- a/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj.Filters
+++ b/audio/simpleaudiosample/Source/Utilities/Utilities.vcxproj.Filters
@@ -1,44 +1,31 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?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>{6BC89CB0-7C76-439F-8D55-E3125E355A42}</UniqueIdentifier>
+ <UniqueIdentifier>{CDBBEDA3-98E9-4C7A-BDB1-25EC47D0B087}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files">
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
- <UniqueIdentifier>{02E55FC1-89F6-4E2D-A10B-A6476FF89B86}</UniqueIdentifier>
+ <UniqueIdentifier>{FA3DF57E-BA19-4783-831B-CF9D4D594F70}</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>{B836489B-8D2E-41DD-A232-0D6C40243B08}</UniqueIdentifier>
+ <UniqueIdentifier>{CB830E4F-01DA-4D35-9789-E7DB0D02A79C}</UniqueIdentifier>
</Filter>
<Filter Include="Driver Files">
<Extensions>inf;inv;inx;mof;mc;</Extensions>
- <UniqueIdentifier>{850E3B99-7C84-454B-9E04-6A7CF9852E6C}</UniqueIdentifier>
+ <UniqueIdentifier>{49F92783-3B39-4D0C-A153-8C346F754749}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
- <ClCompile Include="..\*.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="*.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
- <ResourceCompile Include="PhoneAudioSample.rc">
- <Filter>Resource Files</Filter>
- </ResourceCompile>
- </ItemGroup>
- <ItemGroup>
<ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
- <ItemGroup>
- <Inf Include="*.inx">
- <Filter>Driver Files</Filter>
- </Inf>
- </ItemGroup>
</Project>
diff --git a/audio/simpleaudiosample/Source/Utilities/hw.cpp b/audio/simpleaudiosample/Source/Utilities/hw.cpp
new file mode 100644
index 00000000..133bcc99
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Utilities/hw.cpp
@@ -0,0 +1,446 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ hw.cpp
+
+Abstract:
+
+ Implementation of Simple Audio Sample HW class.
+ Simple Audio Sample HW has an array for storing mixer and volume settings
+ for the topology.
+--*/
+#include "definitions.h"
+#include "hw.h"
+
+//=============================================================================
+// CSimpleAudioSampleHW
+//=============================================================================
+
+//=============================================================================
+#pragma code_seg("PAGE")
+CSimpleAudioSampleHW::CSimpleAudioSampleHW()
+: m_ulMux(0),
+ m_bDevSpecific(FALSE),
+ m_iDevSpecific(0),
+ m_uiDevSpecific(0)
+/*++
+
+Routine Description:
+
+ Constructor for SimpleAudioSampleHW.
+
+Arguments:
+
+Return Value:
+
+ void
+
+--*/
+{
+ PAGED_CODE();
+
+ MixerReset();
+} // SimpleAudioSampleHW
+#pragma code_seg()
+
+
+//=============================================================================
+BOOL
+CSimpleAudioSampleHW::bGetDevSpecific()
+/*++
+
+Routine Description:
+
+ Gets the HW (!) Device Specific info
+
+Arguments:
+
+ N/A
+
+Return Value:
+
+ True or False (in this example).
+
+--*/
+{
+ return m_bDevSpecific;
+} // bGetDevSpecific
+
+//=============================================================================
+void
+CSimpleAudioSampleHW::bSetDevSpecific
+(
+ _In_ BOOL bDevSpecific
+)
+/*++
+
+Routine Description:
+
+ Sets the HW (!) Device Specific info
+
+Arguments:
+
+ fDevSpecific - true or false for this example.
+
+Return Value:
+
+ void
+
+--*/
+{
+ m_bDevSpecific = bDevSpecific;
+} // bSetDevSpecific
+
+//=============================================================================
+INT
+CSimpleAudioSampleHW::iGetDevSpecific()
+/*++
+
+Routine Description:
+
+ Gets the HW (!) Device Specific info
+
+Arguments:
+
+ N/A
+
+Return Value:
+
+ int (in this example).
+
+--*/
+{
+ return m_iDevSpecific;
+} // iGetDevSpecific
+
+//=============================================================================
+void
+CSimpleAudioSampleHW::iSetDevSpecific
+(
+ _In_ INT iDevSpecific
+)
+/*++
+
+Routine Description:
+
+ Sets the HW (!) Device Specific info
+
+Arguments:
+
+ fDevSpecific - true or false for this example.
+
+Return Value:
+
+ void
+
+--*/
+{
+ m_iDevSpecific = iDevSpecific;
+} // iSetDevSpecific
+
+//=============================================================================
+UINT
+CSimpleAudioSampleHW::uiGetDevSpecific()
+/*++
+
+Routine Description:
+
+ Gets the HW (!) Device Specific info
+
+Arguments:
+
+ N/A
+
+Return Value:
+
+ UINT (in this example).
+
+--*/
+{
+ return m_uiDevSpecific;
+} // uiGetDevSpecific
+
+//=============================================================================
+void
+CSimpleAudioSampleHW::uiSetDevSpecific
+(
+ _In_ UINT uiDevSpecific
+)
+/*++
+
+Routine Description:
+
+ Sets the HW (!) Device Specific info
+
+Arguments:
+
+ uiDevSpecific - int for this example.
+
+Return Value:
+
+ void
+
+--*/
+{
+ m_uiDevSpecific = uiDevSpecific;
+} // uiSetDevSpecific
+
+
+//=============================================================================
+BOOL
+CSimpleAudioSampleHW::GetMixerMute
+(
+ _In_ ULONG ulNode,
+ _In_ ULONG ulChannel
+)
+/*++
+
+Routine Description:
+
+ Gets the HW (!) mute levels for Simple Audio Sample
+
+Arguments:
+
+ ulNode - topology node id
+
+ ulChannel - which channel are we reading?
+
+Return Value:
+
+ mute setting
+
+--*/
+{
+ UNREFERENCED_PARAMETER(ulChannel);
+
+ if (ulNode < MAX_TOPOLOGY_NODES)
+ {
+ return m_MuteControls[ulNode];
+ }
+
+ return 0;
+} // GetMixerMute
+
+//=============================================================================
+ULONG
+CSimpleAudioSampleHW::GetMixerMux()
+/*++
+
+Routine Description:
+
+ Return the current mux selection
+
+Arguments:
+
+Return Value:
+
+ ULONG
+
+--*/
+{
+ return m_ulMux;
+} // GetMixerMux
+
+//=============================================================================
+LONG
+CSimpleAudioSampleHW::GetMixerVolume
+(
+ _In_ ULONG ulNode,
+ _In_ ULONG ulChannel
+)
+/*++
+
+Routine Description:
+
+ Gets the HW (!) volume for Simple Audio Sample.
+
+Arguments:
+
+ ulNode - topology node id
+
+ ulChannel - which channel are we reading?
+
+Return Value:
+
+ LONG - volume level
+
+--*/
+{
+ UNREFERENCED_PARAMETER(ulChannel);
+
+ if (ulNode < MAX_TOPOLOGY_NODES)
+ {
+ return m_VolumeControls[ulNode];
+ }
+
+ return 0;
+} // GetMixerVolume
+
+//=============================================================================
+LONG
+CSimpleAudioSampleHW::GetMixerPeakMeter
+(
+ _In_ ULONG ulNode,
+ _In_ ULONG ulChannel
+)
+/*++
+
+Routine Description:
+
+ Gets the HW (!) peak meter for Simple Audio Sample.
+
+Arguments:
+
+ ulNode - topology node id
+
+ ulChannel - which channel are we reading?
+
+Return Value:
+
+ LONG - sample peak meter level
+
+--*/
+{
+ UNREFERENCED_PARAMETER(ulChannel);
+
+ if (ulNode < MAX_TOPOLOGY_NODES)
+ {
+ return m_PeakMeterControls[ulNode];
+ }
+
+ return 0;
+} // GetMixerVolume
+
+//=============================================================================
+#pragma code_seg("PAGE")
+void
+CSimpleAudioSampleHW::MixerReset()
+/*++
+
+Routine Description:
+
+ Resets the mixer registers.
+
+Arguments:
+
+Return Value:
+
+ void
+
+--*/
+{
+ PAGED_CODE();
+
+ RtlFillMemory(m_VolumeControls, sizeof(LONG) * MAX_TOPOLOGY_NODES, 0xFF);
+ // Endpoints are not muted by default.
+ RtlZeroMemory(m_MuteControls, sizeof(BOOL) * MAX_TOPOLOGY_NODES);
+
+ for (ULONG i=0; i<MAX_TOPOLOGY_NODES; ++i)
+ {
+ m_PeakMeterControls[i] = PEAKMETER_SIGNED_MAXIMUM/2;
+ }
+
+ // BUGBUG change this depending on the topology
+ m_ulMux = 2;
+} // MixerReset
+#pragma code_seg()
+
+//=============================================================================
+void
+CSimpleAudioSampleHW::SetMixerMute
+(
+ _In_ ULONG ulNode,
+ _In_ ULONG ulChannel,
+ _In_ BOOL fMute
+)
+/*++
+
+Routine Description:
+
+ Sets the HW (!) mute levels for Simple Audio Sample
+
+Arguments:
+
+ ulNode - topology node id
+
+ ulChannel - which channel are we setting?
+
+ fMute - mute flag
+
+Return Value:
+
+ void
+
+--*/
+{
+ UNREFERENCED_PARAMETER(ulChannel);
+
+ if (ulNode < MAX_TOPOLOGY_NODES)
+ {
+ m_MuteControls[ulNode] = fMute;
+ }
+} // SetMixerMute
+
+//=============================================================================
+void
+CSimpleAudioSampleHW::SetMixerMux
+(
+ _In_ ULONG ulNode
+)
+/*++
+
+Routine Description:
+
+ Sets the HW (!) mux selection
+
+Arguments:
+
+ ulNode - topology node id
+
+Return Value:
+
+ void
+
+--*/
+{
+ m_ulMux = ulNode;
+} // SetMixMux
+
+//=============================================================================
+void
+CSimpleAudioSampleHW::SetMixerVolume
+(
+ _In_ ULONG ulNode,
+ _In_ ULONG ulChannel,
+ _In_ LONG lVolume
+)
+/*++
+
+Routine Description:
+
+ Sets the HW (!) volume for Simple Audio Sample.
+
+Arguments:
+
+ ulNode - topology node id
+
+ ulChannel - which channel are we setting?
+
+ lVolume - volume level
+
+Return Value:
+
+ void
+
+--*/
+{
+ UNREFERENCED_PARAMETER(ulChannel);
+
+ if (ulNode < MAX_TOPOLOGY_NODES)
+ {
+ m_VolumeControls[ulNode] = lVolume;
+ }
+} // SetMixerVolume
diff --git a/audio/simpleaudiosample/Source/Utilities/hw.h b/audio/simpleaudiosample/Source/Utilities/hw.h
new file mode 100644
index 00000000..3360c24a
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Utilities/hw.h
@@ -0,0 +1,105 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ hw.h
+
+Abstract:
+
+ Declaration of Simple Audio Sample HW class.
+ Simple Audio Sample HW has an array for storing mixer and volume settings
+ for the topology.
+--*/
+
+#ifndef _SIMPLEAUDIOSAMPLE_HW_H_
+#define _SIMPLEAUDIOSAMPLE_HW_H_
+
+//=============================================================================
+// Defines
+//=============================================================================
+// BUGBUG we should dynamically allocate this...
+#define MAX_TOPOLOGY_NODES 20
+
+//=============================================================================
+// Classes
+//=============================================================================
+///////////////////////////////////////////////////////////////////////////////
+// CSimpleAudioSampleHW
+// This class represents virtual Simple Audio Sample HW. An array representing volume
+// registers and mute registers.
+
+class CSimpleAudioSampleHW
+{
+public:
+protected:
+ BOOL m_MuteControls[MAX_TOPOLOGY_NODES];
+ LONG m_VolumeControls[MAX_TOPOLOGY_NODES];
+ LONG m_PeakMeterControls[MAX_TOPOLOGY_NODES];
+ ULONG m_ulMux; // Mux selection
+ BOOL m_bDevSpecific;
+ INT m_iDevSpecific;
+ UINT m_uiDevSpecific;
+
+private:
+
+public:
+ CSimpleAudioSampleHW();
+
+ void MixerReset();
+ BOOL bGetDevSpecific();
+ void bSetDevSpecific
+ (
+ _In_ BOOL bDevSpecific
+ );
+ INT iGetDevSpecific();
+ void iSetDevSpecific
+ (
+ _In_ INT iDevSpecific
+ );
+ UINT uiGetDevSpecific();
+ void uiSetDevSpecific
+ (
+ _In_ UINT uiDevSpecific
+ );
+ BOOL GetMixerMute
+ (
+ _In_ ULONG ulNode,
+ _In_ ULONG ulChannel
+ );
+ void SetMixerMute
+ (
+ _In_ ULONG ulNode,
+ _In_ ULONG ulChannel,
+ _In_ BOOL fMute
+ );
+ ULONG GetMixerMux();
+ void SetMixerMux
+ (
+ _In_ ULONG ulNode
+ );
+ LONG GetMixerVolume
+ (
+ _In_ ULONG ulNode,
+ _In_ ULONG ulChannel
+ );
+ void SetMixerVolume
+ (
+ _In_ ULONG ulNode,
+ _In_ ULONG ulChannel,
+ _In_ LONG lVolume
+ );
+
+ LONG GetMixerPeakMeter
+ (
+ _In_ ULONG ulNode,
+ _In_ ULONG ulChannel
+ );
+
+protected:
+private:
+};
+typedef CSimpleAudioSampleHW *PCSimpleAudioSampleHW;
+
+#endif // _SIMPLEAUDIOSAMPLE_HW_H_
diff --git a/audio/simpleaudiosample/Source/Utilities/kshelper.cpp b/audio/simpleaudiosample/Source/Utilities/kshelper.cpp
new file mode 100644
index 00000000..e71c6021
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Utilities/kshelper.cpp
@@ -0,0 +1,958 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ kshelper.cpp
+
+Abstract:
+
+ Helper functions for simple audio sample
+--*/
+
+#include "definitions.h"
+
+//4127: conditional expression is constant
+#pragma warning (disable : 4127)
+
+//-----------------------------------------------------------------------------
+#pragma code_seg("PAGE")
+PWAVEFORMATEX
+GetWaveFormatEx
+(
+ _In_ PKSDATAFORMAT pDataFormat
+)
+/*++
+
+Routine Description:
+
+ Returns the waveformatex for known formats.
+
+Arguments:
+
+ pDataFormat - data format.
+
+Return Value:
+
+ waveformatex in DataFormat.
+ NULL for unknown data formats.
+
+--*/
+{
+ PAGED_CODE();
+
+ PWAVEFORMATEX pWfx = NULL;
+
+ // If this is a known dataformat extract the waveformat info.
+ //
+ if
+ (
+ pDataFormat &&
+ ( IsEqualGUIDAligned(pDataFormat->MajorFormat,
+ KSDATAFORMAT_TYPE_AUDIO) &&
+ ( IsEqualGUIDAligned(pDataFormat->Specifier,
+ KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) ||
+ IsEqualGUIDAligned(pDataFormat->Specifier,
+ KSDATAFORMAT_SPECIFIER_DSOUND) ) )
+ )
+ {
+ pWfx = PWAVEFORMATEX(pDataFormat + 1);
+
+ if (IsEqualGUIDAligned(pDataFormat->Specifier,
+ KSDATAFORMAT_SPECIFIER_DSOUND))
+ {
+ PKSDSOUND_BUFFERDESC pwfxds;
+
+ pwfxds = PKSDSOUND_BUFFERDESC(pDataFormat + 1);
+ pWfx = &pwfxds->WaveFormatEx;
+ }
+ }
+
+ return pWfx;
+} // GetWaveFormatEx
+
+//-----------------------------------------------------------------------------
+#pragma code_seg("PAGE")
+NTSTATUS
+ValidatePropertyParams
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG cbValueSize,
+ _In_ ULONG cbInstanceSize /* = 0 */
+)
+/*++
+
+Routine Description:
+
+ Validates property parameters.
+
+Arguments:
+
+ PropertyRequest -
+ cbValueSize -
+ cbInstanceSize -
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
+
+ if (PropertyRequest && cbValueSize)
+ {
+ // If the caller is asking for ValueSize.
+ //
+ if (0 == PropertyRequest->ValueSize)
+ {
+ PropertyRequest->ValueSize = cbValueSize;
+ ntStatus = STATUS_BUFFER_OVERFLOW;
+ }
+ // If the caller passed an invalid ValueSize.
+ //
+ else if (PropertyRequest->ValueSize < cbValueSize)
+ {
+ ntStatus = STATUS_BUFFER_TOO_SMALL;
+ }
+ else if (PropertyRequest->InstanceSize < cbInstanceSize)
+ {
+ ntStatus = STATUS_BUFFER_TOO_SMALL;
+ }
+ // If all parameters are OK.
+ //
+ else if (PropertyRequest->ValueSize >= cbValueSize)
+ {
+ if (PropertyRequest->Value)
+ {
+ ntStatus = STATUS_SUCCESS;
+ //
+ // Caller should set ValueSize, if the property
+ // call is successful.
+ //
+ }
+ }
+ }
+ else
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+
+ // Clear the ValueSize if unsuccessful.
+ //
+ if (PropertyRequest &&
+ STATUS_SUCCESS != ntStatus &&
+ STATUS_BUFFER_OVERFLOW != ntStatus)
+ {
+ PropertyRequest->ValueSize = 0;
+ }
+
+ return ntStatus;
+} // ValidatePropertyParams
+
+//-----------------------------------------------------------------------------
+#pragma code_seg("PAGE")
+NTSTATUS
+SimpleAudioSamplePropertyDispatch
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+/*++
+ Handles and dispatches a SIMPLEAUDIOSAMPLE_PROPERTY_ITEM.
+
+ Use this as the property handler only if the property item is a
+ SIMPLEAUDIOSAMPLE_PROPERTY_ITEM.
+--*/
+{
+ PAGED_CODE();
+
+ SIMPLEAUDIOSAMPLE_PROPERTY_ITEM* item = (SIMPLEAUDIOSAMPLE_PROPERTY_ITEM*)PropertyRequest->PropertyItem;
+
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ if (item->SupportHandler != nullptr)
+ {
+ return item->SupportHandler(PropertyRequest);
+ }
+ else
+ {
+ return PropertyHandler_BasicSupport(PropertyRequest, PropertyRequest->PropertyItem->Flags, VT_ILLEGAL);
+ }
+ }
+
+ // Verify instance data size
+ if (PropertyRequest->InstanceSize < item->MinProperty)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ ULONG cbMinSize = item->MinData;
+
+ // Verify value size
+ if (PropertyRequest->ValueSize == 0)
+ {
+ PropertyRequest->ValueSize = cbMinSize;
+ return STATUS_BUFFER_OVERFLOW;
+ }
+ if (PropertyRequest->ValueSize < cbMinSize)
+ {
+ PropertyRequest->ValueSize = 0;
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ if (item->GetHandler != nullptr)
+ {
+ return item->GetHandler(PropertyRequest);
+ }
+ else
+ {
+ return STATUS_NOT_SUPPORTED;
+ }
+ }
+
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
+ {
+ if (item->SetHandler != nullptr)
+ {
+ return item->SetHandler(PropertyRequest);
+ }
+ else
+ {
+ return STATUS_NOT_SUPPORTED;
+ }
+ }
+
+ return STATUS_INVALID_DEVICE_REQUEST;
+}
+
+//-----------------------------------------------------------------------------
+#pragma code_seg("PAGE")
+NTSTATUS
+PropertyHandler_BasicSupport
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG Flags,
+ _In_ DWORD PropTypeSetId
+)
+/*++
+
+Routine Description:
+
+ Default basic support handler. Basic processing depends on the size of data.
+ For ULONG it only returns Flags. For KSPROPERTY_DESCRIPTION, the structure
+ is filled.
+
+Arguments:
+
+ PropertyRequest -
+
+ Flags - Support flags.
+
+ PropTypeSetId - PropTypeSetId
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ ASSERT(Flags & KSPROPERTY_TYPE_BASICSUPPORT);
+
+ NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
+
+ if (PropertyRequest->ValueSize >= sizeof(KSPROPERTY_DESCRIPTION))
+ {
+ // if return buffer can hold a KSPROPERTY_DESCRIPTION, return it
+ //
+ PKSPROPERTY_DESCRIPTION PropDesc =
+ PKSPROPERTY_DESCRIPTION(PropertyRequest->Value);
+
+ PropDesc->AccessFlags = Flags;
+ PropDesc->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION);
+ if (VT_ILLEGAL != PropTypeSetId)
+ {
+ PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General;
+ PropDesc->PropTypeSet.Id = PropTypeSetId;
+ }
+ else
+ {
+ PropDesc->PropTypeSet.Set = GUID_NULL;
+ PropDesc->PropTypeSet.Id = 0;
+ }
+ PropDesc->PropTypeSet.Flags = 0;
+ PropDesc->MembersListCount = 0;
+ PropDesc->Reserved = 0;
+
+ PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION);
+ ntStatus = STATUS_SUCCESS;
+ }
+ else if (PropertyRequest->ValueSize >= sizeof(ULONG))
+ {
+ // if return buffer can hold a ULONG, return the access flags
+ //
+ *(PULONG(PropertyRequest->Value)) = Flags;
+
+ PropertyRequest->ValueSize = sizeof(ULONG);
+ ntStatus = STATUS_SUCCESS;
+ }
+ else
+ {
+ PropertyRequest->ValueSize = 0;
+ ntStatus = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ return ntStatus;
+} // PropertyHandler_BasicSupport
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+PropertyHandler_BasicSupportVolume
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG MaxChannels
+)
+/*++
+
+Routine Description:
+
+ Handles BasicSupport for Volume nodes.
+
+Arguments:
+
+ PropertyRequest - property request structure.
+
+ MaxChannels - # of supported channels.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ ULONG cbFullProperty =
+ sizeof(KSPROPERTY_DESCRIPTION) +
+ sizeof(KSPROPERTY_MEMBERSHEADER) +
+ sizeof(KSPROPERTY_STEPPING_LONG) * MaxChannels;
+
+ ASSERT(MaxChannels > 0);
+
+ if (PropertyRequest->ValueSize >= (sizeof(KSPROPERTY_DESCRIPTION)))
+ {
+ PKSPROPERTY_DESCRIPTION PropDesc =
+ PKSPROPERTY_DESCRIPTION(PropertyRequest->Value);
+
+ PropDesc->AccessFlags = KSPROPERTY_TYPE_ALL;
+ PropDesc->DescriptionSize = cbFullProperty;
+ PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General;
+ PropDesc->PropTypeSet.Id = VT_I4;
+ PropDesc->PropTypeSet.Flags = 0;
+ PropDesc->MembersListCount = 1;
+ PropDesc->Reserved = 0;
+
+ // if return buffer can also hold a range description, return it too
+ if(PropertyRequest->ValueSize >= cbFullProperty)
+ {
+ // fill in the members header
+ PKSPROPERTY_MEMBERSHEADER Members =
+ PKSPROPERTY_MEMBERSHEADER(PropDesc + 1);
+
+ Members->MembersFlags = KSPROPERTY_MEMBER_STEPPEDRANGES;
+ Members->MembersSize = sizeof(KSPROPERTY_STEPPING_LONG);
+ Members->MembersCount = MaxChannels;
+ Members->Flags = KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL;
+
+ // fill in the stepped range
+ PKSPROPERTY_STEPPING_LONG Range =
+ PKSPROPERTY_STEPPING_LONG(Members + 1);
+
+ for (ULONG i=0; i<MaxChannels; ++i)
+ {
+ Range[i].Bounds.SignedMaximum = VOLUME_SIGNED_MAXIMUM; // 0 dB
+ Range[i].Bounds.SignedMinimum = VOLUME_SIGNED_MINIMUM; // -96 dB
+ Range[i].SteppingDelta = VOLUME_STEPPING_DELTA; // .5 dB
+ Range[i].Reserved = 0;
+ }
+
+ // set the return value size
+ PropertyRequest->ValueSize = cbFullProperty;
+ }
+ else
+ {
+ PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION);
+ }
+ }
+ else if(PropertyRequest->ValueSize >= sizeof(ULONG))
+ {
+ // if return buffer can hold a ULONG, return the access flags
+ PULONG AccessFlags = PULONG(PropertyRequest->Value);
+
+ PropertyRequest->ValueSize = sizeof(ULONG);
+ *AccessFlags = KSPROPERTY_TYPE_ALL;
+ }
+ else
+ {
+ PropertyRequest->ValueSize = 0;
+ ntStatus = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ return ntStatus;
+} // PropertyHandlerBasicSupportVolume
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+PropertyHandler_BasicSupportMute
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG MaxChannels
+)
+/*++
+
+Routine Description:
+
+ Handles BasicSupport for Mute nodes.
+
+Arguments:
+
+ PropertyRequest - property request structure.
+
+ MaxChannels - # of supported channels.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ ULONG cbFullProperty =
+ sizeof(KSPROPERTY_DESCRIPTION) +
+ sizeof(KSPROPERTY_MEMBERSHEADER) +
+ sizeof(KSPROPERTY_STEPPING_LONG) * MaxChannels;
+
+ ASSERT(MaxChannels > 0);
+
+ if (PropertyRequest->ValueSize >= (sizeof(KSPROPERTY_DESCRIPTION)))
+ {
+ PKSPROPERTY_DESCRIPTION PropDesc =
+ PKSPROPERTY_DESCRIPTION(PropertyRequest->Value);
+
+ PropDesc->AccessFlags = KSPROPERTY_TYPE_ALL;
+ PropDesc->DescriptionSize = cbFullProperty;
+ PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General;
+ PropDesc->PropTypeSet.Id = VT_BOOL;
+ PropDesc->PropTypeSet.Flags = 0;
+ PropDesc->MembersListCount = 1;
+ PropDesc->Reserved = 0;
+
+ // if return buffer can also hold a range description, return it too
+ if(PropertyRequest->ValueSize >= cbFullProperty)
+ {
+ // fill in the members header
+ PKSPROPERTY_MEMBERSHEADER Members =
+ PKSPROPERTY_MEMBERSHEADER(PropDesc + 1);
+
+ Members->MembersFlags = KSPROPERTY_MEMBER_STEPPEDRANGES;
+ Members->MembersSize = sizeof(KSPROPERTY_STEPPING_LONG);
+ Members->MembersCount = MaxChannels;
+ Members->Flags = KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL;
+
+ // fill in the stepped range
+ PKSPROPERTY_STEPPING_LONG Range =
+ PKSPROPERTY_STEPPING_LONG(Members + 1);
+
+ for (ULONG i=0; i<MaxChannels; ++i)
+ {
+ Range[i].Bounds.SignedMaximum = 1; // true
+ Range[i].Bounds.SignedMinimum = 0; // false
+ Range[i].SteppingDelta = 1; // false <- -> true
+ Range[i].Reserved = 0;
+ }
+
+ // set the return value size
+ PropertyRequest->ValueSize = cbFullProperty;
+ }
+ else
+ {
+ PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION);
+ }
+ }
+ else if(PropertyRequest->ValueSize >= sizeof(ULONG))
+ {
+ // if return buffer can hold a ULONG, return the access flags
+ PULONG AccessFlags = PULONG(PropertyRequest->Value);
+
+ PropertyRequest->ValueSize = sizeof(ULONG);
+ *AccessFlags = KSPROPERTY_TYPE_ALL;
+ }
+ else
+ {
+ PropertyRequest->ValueSize = 0;
+ ntStatus = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ return ntStatus;
+} // PropertyHandlerBasicSupportVolume
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+PropertyHandler_BasicSupportPeakMeter2
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG MaxChannels
+)
+/*++
+
+Routine Description:
+
+ Handles BasicSupport for peak meter nodes.
+
+Arguments:
+
+ PropertyRequest - property request structure.
+
+ MaxChannels - # of supported channels.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ ULONG cbFullProperty =
+ sizeof(KSPROPERTY_DESCRIPTION) +
+ sizeof(KSPROPERTY_MEMBERSHEADER) +
+ sizeof(KSPROPERTY_STEPPING_LONG) * MaxChannels;
+
+ ASSERT(MaxChannels > 0);
+
+ if (PropertyRequest->ValueSize >= (sizeof(KSPROPERTY_DESCRIPTION)))
+ {
+ PKSPROPERTY_DESCRIPTION PropDesc =
+ PKSPROPERTY_DESCRIPTION(PropertyRequest->Value);
+
+ PropDesc->AccessFlags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT;
+ PropDesc->DescriptionSize = cbFullProperty;
+ PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General;
+ PropDesc->PropTypeSet.Id = VT_I4;
+ PropDesc->PropTypeSet.Flags = 0;
+ PropDesc->MembersListCount = 1;
+ PropDesc->Reserved = 0;
+
+ // if return buffer can also hold a range description, return it too
+ if(PropertyRequest->ValueSize >= cbFullProperty)
+ {
+ // fill in the members header
+ PKSPROPERTY_MEMBERSHEADER Members =
+ PKSPROPERTY_MEMBERSHEADER(PropDesc + 1);
+
+ Members->MembersFlags = KSPROPERTY_MEMBER_STEPPEDRANGES;
+ Members->MembersSize = sizeof(KSPROPERTY_STEPPING_LONG);
+ Members->MembersCount = MaxChannels;
+ Members->Flags = KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL;
+
+ // fill in the stepped range
+ PKSPROPERTY_STEPPING_LONG Range =
+ PKSPROPERTY_STEPPING_LONG(Members + 1);
+
+ for (ULONG i=0; i<MaxChannels; ++i)
+ {
+ Range[i].Bounds.SignedMaximum = PEAKMETER_SIGNED_MAXIMUM;
+ Range[i].Bounds.SignedMinimum = PEAKMETER_SIGNED_MINIMUM;
+ Range[i].SteppingDelta = PEAKMETER_STEPPING_DELTA;
+ Range[i].Reserved = 0;
+ }
+
+ // set the return value size
+ PropertyRequest->ValueSize = cbFullProperty;
+ }
+ else
+ {
+ PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION);
+ }
+ }
+ else if(PropertyRequest->ValueSize >= sizeof(ULONG))
+ {
+ // if return buffer can hold a ULONG, return the access flags
+ PULONG AccessFlags = PULONG(PropertyRequest->Value);
+
+ PropertyRequest->ValueSize = sizeof(ULONG);
+ *AccessFlags = KSPROPERTY_TYPE_ALL;
+ }
+ else
+ {
+ PropertyRequest->ValueSize = 0;
+ ntStatus = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ return ntStatus;
+} // PropertyHandlerBasicSupportVolume
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+PropertyHandler_CpuResources
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+/*++
+
+Routine Description:
+
+ Processes KSPROPERTY_AUDIO_CPURESOURCES
+
+Arguments:
+
+ PropertyRequest - property request structure.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[%s]",__FUNCTION__));
+
+ NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ ntStatus = ValidatePropertyParams(PropertyRequest, sizeof(ULONG));
+ if (NT_SUCCESS(ntStatus))
+ {
+ *(PULONG(PropertyRequest->Value)) = KSAUDIO_CPU_RESOURCES_NOT_HOST_CPU;
+ PropertyRequest->ValueSize = sizeof(ULONG);
+ }
+ }
+ else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ ntStatus =
+ PropertyHandler_BasicSupport
+ (
+ PropertyRequest,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ VT_UI4
+ );
+ }
+
+ return ntStatus;
+} // PropertyHandlerCpuResources
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+PropertyHandler_Volume
+(
+ _In_ PADAPTERCOMMON AdapterCommon,
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG MaxChannels
+)
+/*++
+
+Routine Description:
+
+ Property handler for KSPROPERTY_AUDIO_VOLUMELEVEL
+
+Arguments:
+
+ AdapterCommon - interface to the common adapter object.
+
+ PropertyRequest - property request structure.
+
+ MaxChannels - # of supported channels.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[%s]",__FUNCTION__));
+
+ NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+ ULONG ulChannel;
+ PLONG plVolume;
+
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ ntStatus = PropertyHandler_BasicSupportVolume(
+ PropertyRequest,
+ MaxChannels);
+ }
+ else
+ {
+ ntStatus =
+ ValidatePropertyParams
+ (
+ PropertyRequest,
+ sizeof(LONG), // volume value is a LONG
+ sizeof(ULONG) // instance is the channel number
+ );
+ if (NT_SUCCESS(ntStatus))
+ {
+ ulChannel = * (PULONG (PropertyRequest->Instance));
+ plVolume = PLONG (PropertyRequest->Value);
+
+ if (ulChannel >= MaxChannels &&
+ ulChannel != ALL_CHANNELS_ID)
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+ else if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ *plVolume =
+ AdapterCommon->MixerVolumeRead
+ (
+ PropertyRequest->Node,
+ ulChannel == ALL_CHANNELS_ID ? 0 : ulChannel
+ );
+ PropertyRequest->ValueSize = sizeof(ULONG);
+ }
+ else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
+ {
+ if (ALL_CHANNELS_ID == ulChannel)
+ {
+ for (ULONG i=0; i<ulChannel; ++i)
+ {
+ AdapterCommon->MixerVolumeWrite
+ (
+ PropertyRequest->Node,
+ i,
+ VOLUME_NORMALIZE_IN_RANGE(*plVolume)
+ );
+ }
+ }
+ else
+ {
+ AdapterCommon->MixerVolumeWrite
+ (
+ PropertyRequest->Node,
+ ulChannel,
+ VOLUME_NORMALIZE_IN_RANGE(*plVolume)
+ );
+ }
+ }
+ }
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ DPF(D_TERSE, ("[%s - ntStatus=0x%08x]",__FUNCTION__,ntStatus));
+ }
+ }
+
+ return ntStatus;
+} // PropertyHandlerVolume
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+PropertyHandler_Mute
+(
+ _In_ PADAPTERCOMMON AdapterCommon,
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG MaxChannels
+)
+/*++
+
+Routine Description:
+
+ Property handler for KSPROPERTY_AUDIO_MUTE
+
+Arguments:
+
+ AdapterCommon - interface to the common adapter object.
+
+ PropertyRequest - property request structure.
+
+ MaxChannels - # of supported channels.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[%s]",__FUNCTION__));
+
+ NTSTATUS ntStatus;
+ ULONG ulChannel;
+ PBOOL pfMute;
+
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ ntStatus = PropertyHandler_BasicSupportMute(
+ PropertyRequest,
+ MaxChannels);
+ }
+ else
+ {
+ ntStatus =
+ ValidatePropertyParams
+ (
+ PropertyRequest,
+ sizeof(BOOL),
+ sizeof(ULONG)
+ );
+ if (NT_SUCCESS(ntStatus))
+ {
+ ulChannel = * (PULONG (PropertyRequest->Instance));
+ pfMute = PBOOL (PropertyRequest->Value);
+
+ if (ulChannel >= MaxChannels &&
+ ulChannel != ALL_CHANNELS_ID)
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+ else if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ *pfMute =
+ AdapterCommon->MixerMuteRead
+ (
+ PropertyRequest->Node,
+ ulChannel == ALL_CHANNELS_ID ? 0 : ulChannel
+ );
+ PropertyRequest->ValueSize = sizeof(BOOL);
+ }
+ else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
+ {
+ if (ALL_CHANNELS_ID == ulChannel)
+ {
+ for (ULONG i=0; i<ulChannel; ++i)
+ {
+ AdapterCommon->MixerMuteWrite
+ (
+ PropertyRequest->Node,
+ i,
+ (*pfMute) ? TRUE : FALSE
+ );
+ }
+ }
+ else
+ {
+ AdapterCommon->MixerMuteWrite
+ (
+ PropertyRequest->Node,
+ ulChannel,
+ (*pfMute) ? TRUE : FALSE
+ );
+ }
+ }
+ }
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ DPF(D_TERSE, ("[%s - ntStatus=0x%08x]",__FUNCTION__,ntStatus));
+ }
+ }
+
+ return ntStatus;
+} // PropertyHandlerMute
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+PropertyHandler_PeakMeter2
+(
+ _In_ PADAPTERCOMMON AdapterCommon,
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG MaxChannels
+)
+/*++
+
+Routine Description:
+
+ Property handler for KSPROPERTY_AUDIO_PEAKMETER2
+
+Arguments:
+
+ AdapterCommon - interface to the common adapter object.
+
+ PropertyRequest - property request structure.
+
+ MaxChannels - # of supported channels.
+
+Return Value:
+
+ NT status code.
+
+--*/
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[%s]",__FUNCTION__));
+
+ NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+ ULONG ulChannel;
+ PLONG plSample;
+
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ ntStatus = PropertyHandler_BasicSupportPeakMeter2(
+ PropertyRequest,
+ MaxChannels);
+ }
+ else
+ {
+ ntStatus =
+ ValidatePropertyParams
+ (
+ PropertyRequest,
+ sizeof(LONG), // sample value is a LONG
+ sizeof(ULONG) // instance is the channel number
+ );
+ if (NT_SUCCESS(ntStatus))
+ {
+ ulChannel = * (PULONG (PropertyRequest->Instance));
+ plSample = PLONG (PropertyRequest->Value);
+
+ if (ulChannel >= MaxChannels &&
+ ulChannel != ALL_CHANNELS_ID)
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+ else if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ *plSample =
+ PEAKMETER_NORMALIZE_IN_RANGE(
+ AdapterCommon->MixerPeakMeterRead
+ (
+ PropertyRequest->Node,
+ ulChannel == ALL_CHANNELS_ID ? 0 : ulChannel
+ ));
+
+ PropertyRequest->ValueSize = sizeof(ULONG);
+ }
+ }
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ DPF(D_TERSE, ("[%s - ntStatus=0x%08x]",__FUNCTION__,ntStatus));
+ }
+ }
+
+ return ntStatus;
+} // PropertyHandlerVolume
+
diff --git a/audio/simpleaudiosample/Source/Utilities/savedata.cpp b/audio/simpleaudiosample/Source/Utilities/savedata.cpp
new file mode 100644
index 00000000..7b2a11e9
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Utilities/savedata.cpp
@@ -0,0 +1,1033 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ savedata.cpp
+
+Abstract:
+
+ Implementation of Simple Audio Sample data saving class.
+
+ To save the playback data to disk, this class maintains a circular data
+ buffer, associated frame structures and worker items to save frames to
+ disk.
+ Each frame structure represents a portion of buffer. When that portion
+ of frame is full, a workitem is scheduled to save it to disk.
+--*/
+#pragma warning (disable : 4127)
+#pragma warning (disable : 26165)
+
+#include "definitions.h"
+#include "savedata.h"
+#include <ntstrsafe.h> // This is for using RtlStringcbPrintf
+
+#define SAVEDATA_POOLTAG 'TDVS'
+#define SAVEDATA_POOLTAG1 '1DVS'
+#define SAVEDATA_POOLTAG2 '2DVS'
+#define SAVEDATA_POOLTAG3 '3DVS'
+#define SAVEDATA_POOLTAG4 '4DVS'
+#define SAVEDATA_POOLTAG5 '5DVS'
+#define SAVEDATA_POOLTAG6 '6DVS'
+#define SAVEDATA_POOLTAG7 '7DVS'
+
+//=============================================================================
+// Defines
+//=============================================================================
+#define RIFF_TAG 0x46464952;
+#define WAVE_TAG 0x45564157;
+#define FMT__TAG 0x20746D66;
+#define DATA_TAG 0x61746164;
+
+#define DEFAULT_FRAME_COUNT 4
+#define DEFAULT_FRAME_SIZE PAGE_SIZE * 4
+#define DEFAULT_BUFFER_SIZE DEFAULT_FRAME_SIZE * DEFAULT_FRAME_COUNT
+
+#define DEFAULT_FILE_NAME L"\\DosDevices\\C:\\STREAM"
+#define OSDATA_FILE_NAME L"\\DosDevices\\O:\\STREAM"
+#define OFFLOAD_FILE_NAME L"OFFLOAD"
+#define HOST_FILE_NAME L"HOST"
+
+#define MAX_WORKER_ITEM_COUNT 15
+
+//=============================================================================
+// Statics
+//=============================================================================
+ULONG CSaveData::m_ulStreamId = 0;
+
+#pragma code_seg("PAGE")
+//=============================================================================
+// CSaveData
+//=============================================================================
+
+//=============================================================================
+CSaveData::CSaveData()
+: m_pDataBuffer(NULL),
+ m_FileHandle(NULL),
+ m_ulFrameCount(DEFAULT_FRAME_COUNT),
+ m_ulBufferSize(DEFAULT_BUFFER_SIZE),
+ m_ulFrameSize(DEFAULT_FRAME_SIZE),
+ m_ulBufferOffset(0),
+ m_ulFrameIndex(0),
+ m_fFrameUsed(NULL),
+ m_waveFormat(NULL),
+ m_pFilePtr(NULL),
+ m_fWriteDisabled(FALSE),
+ m_bInitialized(FALSE)
+{
+ PAGED_CODE();
+
+ m_FileHeader.dwRiff = RIFF_TAG;
+ m_FileHeader.dwFileSize = 0;
+ m_FileHeader.dwWave = WAVE_TAG;
+ m_FileHeader.dwFormat = FMT__TAG;
+ m_FileHeader.dwFormatLength = sizeof(WAVEFORMATEX);
+
+ m_DataHeader.dwData = DATA_TAG;
+ m_DataHeader.dwDataLength = 0;
+
+ RtlZeroMemory(&m_objectAttributes, sizeof(m_objectAttributes));
+} // CSaveData
+
+//=============================================================================
+CSaveData::~CSaveData()
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[CSaveData::~CSaveData]"));
+
+ // Update the wave header in data file with real file size.
+ //
+ if(m_pFilePtr)
+ {
+ m_FileHeader.dwFileSize =
+ (DWORD) m_pFilePtr->QuadPart - 2 * sizeof(DWORD);
+ m_DataHeader.dwDataLength = (DWORD) m_pFilePtr->QuadPart -
+ sizeof(m_FileHeader) -
+ m_FileHeader.dwFormatLength -
+ sizeof(m_DataHeader);
+
+ if (STATUS_SUCCESS == KeWaitForSingleObject
+ (
+ &m_FileSync,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL
+ ))
+ {
+ if (NT_SUCCESS(FileOpen(FALSE)))
+ {
+ FileWriteHeader();
+
+ FileClose();
+ }
+
+ KeReleaseMutex(&m_FileSync, FALSE);
+ }
+ }
+
+ if (m_waveFormat)
+ {
+ ExFreePoolWithTag(m_waveFormat, SAVEDATA_POOLTAG1);
+ m_waveFormat = NULL;
+ }
+
+ if (m_fFrameUsed)
+ {
+ ExFreePoolWithTag(m_fFrameUsed, SAVEDATA_POOLTAG2);
+ m_fFrameUsed = NULL;
+ // NOTE : Do not release m_pFilePtr.
+ }
+
+ if (m_FileName.Buffer)
+ {
+ ExFreePoolWithTag(m_FileName.Buffer, SAVEDATA_POOLTAG3);
+ m_FileName.Buffer = NULL;
+ }
+
+ if (m_pDataBuffer)
+ {
+ ExFreePoolWithTag(m_pDataBuffer, SAVEDATA_POOLTAG4);
+ m_pDataBuffer = NULL;
+ }
+} // CSaveData
+
+//=============================================================================
+void
+CSaveData::DestroyWorkItems
+(
+ void
+)
+{
+ PAGED_CODE();
+
+ if (m_pWorkItems)
+ {
+ for (int i = 0; i < MAX_WORKER_ITEM_COUNT; i++)
+ {
+ if (m_pWorkItems[i].WorkItem!=NULL)
+ {
+ IoFreeWorkItem(m_pWorkItems[i].WorkItem);
+ m_pWorkItems[i].WorkItem = NULL;
+ }
+ }
+ ExFreePoolWithTag(m_pWorkItems, SAVEDATA_POOLTAG);
+ m_pWorkItems = NULL;
+ }
+
+} // DestroyWorkItems
+
+//=============================================================================
+void
+CSaveData::Disable
+(
+ _In_ BOOL fDisable
+)
+{
+ PAGED_CODE();
+
+ m_fWriteDisabled = fDisable;
+} // Disable
+
+//=============================================================================
+NTSTATUS
+CSaveData::FileClose(void)
+{
+ PAGED_CODE();
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ if (m_FileHandle)
+ {
+ ntStatus = ZwClose(m_FileHandle);
+ m_FileHandle = NULL;
+ }
+
+ return ntStatus;
+} // FileClose
+
+//=============================================================================
+NTSTATUS
+CSaveData::FileOpen
+(
+ _In_ BOOL fOverWrite
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ IO_STATUS_BLOCK ioStatusBlock;
+
+ if( FALSE == m_bInitialized )
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if(!m_FileHandle)
+ {
+ ntStatus =
+ ZwCreateFile
+ (
+ &m_FileHandle,
+ GENERIC_WRITE | SYNCHRONIZE,
+ &m_objectAttributes,
+ &ioStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ fOverWrite ? FILE_OVERWRITE_IF : FILE_OPEN_IF,
+ FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0
+ );
+ if (!NT_SUCCESS(ntStatus))
+ {
+ DPF(D_TERSE, ("[CSaveData::FileOpen : Error opening data file]"));
+ }
+ }
+
+ return ntStatus;
+} // FileOpen
+
+//=============================================================================
+NTSTATUS
+CSaveData::FileWrite
+(
+ _In_reads_bytes_(ulDataSize) PBYTE pData,
+ _In_ ULONG ulDataSize
+)
+{
+ PAGED_CODE();
+
+ ASSERT(pData);
+ ASSERT(m_pFilePtr);
+
+ NTSTATUS ntStatus;
+
+ if (m_FileHandle)
+ {
+ IO_STATUS_BLOCK ioStatusBlock;
+
+ ntStatus = ZwWriteFile( m_FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &ioStatusBlock,
+ pData,
+ ulDataSize,
+ m_pFilePtr,
+ NULL);
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ ASSERT(ioStatusBlock.Information == ulDataSize);
+
+ m_pFilePtr->QuadPart += ulDataSize;
+ }
+ else
+ {
+ DPF(D_TERSE, ("[CSaveData::FileWrite : WriteFileError]"));
+ }
+ }
+ else
+ {
+ DPF(D_TERSE, ("[CSaveData::FileWrite : File not open]"));
+ ntStatus = STATUS_INVALID_HANDLE;
+ }
+
+ return ntStatus;
+} // FileWrite
+
+//=============================================================================
+NTSTATUS
+CSaveData::FileWriteHeader(void)
+{
+ PAGED_CODE();
+
+ NTSTATUS ntStatus;
+
+ if (m_FileHandle && m_waveFormat)
+ {
+ IO_STATUS_BLOCK ioStatusBlock;
+
+ m_pFilePtr->QuadPart = 0;
+
+ m_FileHeader.dwFormatLength = (m_waveFormat->wFormatTag == WAVE_FORMAT_PCM) ?
+ sizeof( PCMWAVEFORMAT ) :
+ sizeof( WAVEFORMATEX ) + m_waveFormat->cbSize;
+
+ ntStatus = ZwWriteFile( m_FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &ioStatusBlock,
+ &m_FileHeader,
+ sizeof(m_FileHeader),
+ m_pFilePtr,
+ NULL);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ DPF(D_TERSE, ("[CSaveData::FileWriteHeader : Write File Header Error]"));
+ }
+
+ m_pFilePtr->QuadPart += sizeof(m_FileHeader);
+
+ ntStatus = ZwWriteFile( m_FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &ioStatusBlock,
+ m_waveFormat,
+ m_FileHeader.dwFormatLength,
+ m_pFilePtr,
+ NULL);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ DPF(D_TERSE, ("[CSaveData::FileWriteHeader : Write Format Error]"));
+ }
+
+ m_pFilePtr->QuadPart += m_FileHeader.dwFormatLength;
+
+ ntStatus = ZwWriteFile( m_FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &ioStatusBlock,
+ &m_DataHeader,
+ sizeof(m_DataHeader),
+ m_pFilePtr,
+ NULL);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ DPF(D_TERSE, ("[CSaveData::FileWriteHeader : Write Data Header Error]"));
+ }
+
+ m_pFilePtr->QuadPart += sizeof(m_DataHeader);
+ }
+ else
+ {
+ DPF(D_TERSE, ("[CSaveData::FileWriteHeader : File not open]"));
+ ntStatus = STATUS_INVALID_HANDLE;
+ }
+
+ return ntStatus;
+} // FileWriteHeader
+NTSTATUS
+CSaveData::SetDeviceObject
+(
+ _In_ PDEVICE_OBJECT DeviceObject
+)
+{
+ PAGED_CODE();
+
+ ASSERT(DeviceObject);
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ m_pDeviceObject = DeviceObject;
+ return ntStatus;
+}
+
+PDEVICE_OBJECT
+CSaveData::GetDeviceObject
+(
+ void
+)
+{
+ PAGED_CODE();
+
+ return m_pDeviceObject;
+}
+
+#pragma code_seg()
+//=============================================================================
+PSAVEWORKER_PARAM
+CSaveData::GetNewWorkItem
+(
+ void
+)
+{
+ LARGE_INTEGER timeOut = { 0 };
+ NTSTATUS ntStatus;
+
+ for (int i = 0; i < MAX_WORKER_ITEM_COUNT; i++)
+ {
+ ntStatus =
+ KeWaitForSingleObject
+ (
+ &m_pWorkItems[i].EventDone,
+ Executive,
+ KernelMode,
+ FALSE,
+ &timeOut
+ );
+ if (STATUS_SUCCESS == ntStatus)
+ {
+ if (m_pWorkItems[i].WorkItem)
+ return &(m_pWorkItems[i]);
+ else
+ return NULL;
+ }
+ }
+
+ return NULL;
+} // GetNewWorkItem
+#pragma code_seg("PAGE")
+
+//=============================================================================
+NTSTATUS
+CSaveData::Initialize
+(
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ WCHAR szTemp[MAX_PATH];
+ size_t cLen;
+ OBJECT_ATTRIBUTES objectAttributes;
+ UNICODE_STRING osDataVolumeString;
+ HANDLE osDataFileHandle = NULL;
+ IO_STATUS_BLOCK ioStatusBlock;
+
+ DPF_ENTER(("[CSaveData::Initialize]"));
+
+ m_ulStreamId++;
+
+ // Probe if OSData volume exists.
+ //
+ RtlStringCchPrintfW(szTemp, MAX_PATH, L"%s_probe.txt", OSDATA_FILE_NAME);
+ RtlInitUnicodeString(&osDataVolumeString, szTemp);
+ InitializeObjectAttributes
+ (
+ &objectAttributes,
+ &osDataVolumeString,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ NULL,
+ NULL
+ );
+
+ ntStatus =
+ ZwCreateFile
+ (
+ &osDataFileHandle,
+ GENERIC_WRITE | SYNCHRONIZE,
+ &objectAttributes,
+ &ioStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_OVERWRITE_IF,
+ FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0
+ );
+ if (NT_SUCCESS(ntStatus))
+ {
+ ZwClose(osDataFileHandle);
+ }
+
+ // Allocate data file name.
+ //
+ RtlStringCchPrintfW(szTemp, MAX_PATH, L"%s_%s_%d.wav", NT_SUCCESS(ntStatus) ? OSDATA_FILE_NAME : DEFAULT_FILE_NAME, HOST_FILE_NAME, m_ulStreamId);
+ m_FileName.Length = 0;
+ ntStatus = RtlStringCchLengthW (szTemp, sizeof(szTemp)/sizeof(szTemp[0]), &cLen);
+ if (NT_SUCCESS(ntStatus))
+ {
+ m_FileName.MaximumLength = (USHORT)((cLen * sizeof(WCHAR)) + sizeof(WCHAR));//convert to wchar and add room for NULL
+ m_FileName.Buffer = (PWSTR)
+ ExAllocatePool2
+ (
+ POOL_FLAG_PAGED,
+ m_FileName.MaximumLength,
+ SAVEDATA_POOLTAG3
+ );
+ if (!m_FileName.Buffer)
+ {
+ DPF(D_TERSE, ("[Could not allocate memory for FileName]"));
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ // Allocate memory for data buffer.
+ //
+ if (NT_SUCCESS(ntStatus))
+ {
+ RtlStringCbCopyW(m_FileName.Buffer, m_FileName.MaximumLength, szTemp);
+ m_FileName.Length = (USHORT)wcslen(m_FileName.Buffer) * sizeof(WCHAR);
+ DPF(D_BLAB, ("[New DataFile -- %S", m_FileName.Buffer));
+
+ m_pDataBuffer = (PBYTE)
+ ExAllocatePool2
+ (
+ POOL_FLAG_NON_PAGED,
+ m_ulBufferSize,
+ SAVEDATA_POOLTAG4
+ );
+ if (!m_pDataBuffer)
+ {
+ DPF(D_TERSE, ("[Could not allocate memory for Saving Data]"));
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ // Allocate memory for frame usage flags and m_pFilePtr.
+ //
+ if (NT_SUCCESS(ntStatus))
+ {
+ m_fFrameUsed = (PBOOL)
+ ExAllocatePool2
+ (
+ POOL_FLAG_NON_PAGED,
+ m_ulFrameCount * sizeof(BOOL) +
+ sizeof(LARGE_INTEGER),
+ SAVEDATA_POOLTAG2
+ );
+ if (!m_fFrameUsed)
+ {
+ DPF(D_TERSE, ("[Could not allocate memory for frame flags]"));
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ // Initialize the spinlock to synchronize access to the frames
+ //
+ KeInitializeSpinLock ( &m_FrameInUseSpinLock ) ;
+
+ // Initialize the file mutex
+ //
+ KeInitializeMutex( &m_FileSync, 1 ) ;
+
+ // Open the data file.
+ //
+ if (NT_SUCCESS(ntStatus))
+ {
+ // m_fFrameUsed has additional memory to hold m_pFilePtr
+ //
+ m_pFilePtr = (PLARGE_INTEGER)
+ (((PBYTE) m_fFrameUsed) + m_ulFrameCount * sizeof(BOOL));
+
+ // Create data file.
+ InitializeObjectAttributes
+ (
+ &m_objectAttributes,
+ &m_FileName,
+ OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,
+ NULL,
+ NULL
+ );
+
+ m_bInitialized = TRUE;
+
+ // Write wave header information to data file.
+ ntStatus = KeWaitForSingleObject
+ (
+ &m_FileSync,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+ if (STATUS_SUCCESS == ntStatus)
+ {
+ ntStatus = FileOpen(TRUE);
+ if (NT_SUCCESS(ntStatus))
+ {
+ ntStatus = FileWriteHeader();
+
+ FileClose();
+ }
+
+ KeReleaseMutex( &m_FileSync, FALSE );
+ }
+ }
+
+ return ntStatus;
+} // Initialize
+
+//=============================================================================
+NTSTATUS
+CSaveData::InitializeWorkItems
+(
+ _In_ PDEVICE_OBJECT DeviceObject
+)
+{
+ PAGED_CODE();
+
+ ASSERT(DeviceObject);
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ DPF_ENTER(("[CSaveData::InitializeWorkItems]"));
+
+ if (m_pWorkItems != NULL)
+ {
+ return ntStatus;
+ }
+
+ m_pWorkItems = (PSAVEWORKER_PARAM)
+ ExAllocatePool2
+ (
+ POOL_FLAG_NON_PAGED,
+ sizeof(SAVEWORKER_PARAM) * MAX_WORKER_ITEM_COUNT,
+ SAVEDATA_POOLTAG
+ );
+ if (m_pWorkItems)
+ {
+ for (int i = 0; i < MAX_WORKER_ITEM_COUNT; i++)
+ {
+
+ m_pWorkItems[i].WorkItem = IoAllocateWorkItem(DeviceObject);
+ if(m_pWorkItems[i].WorkItem == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ KeInitializeEvent
+ (
+ &m_pWorkItems[i].EventDone,
+ NotificationEvent,
+ TRUE
+ );
+ }
+ }
+ else
+ {
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ return ntStatus;
+} // InitializeWorkItems
+
+//=============================================================================
+
+IO_WORKITEM_ROUTINE SaveFrameWorkerCallback;
+
+VOID
+SaveFrameWorkerCallback
+(
+ _In_ PDEVICE_OBJECT pDeviceObject,
+ _In_opt_ PVOID Context
+)
+{
+ UNREFERENCED_PARAMETER(pDeviceObject);
+
+ PAGED_CODE();
+
+ ASSERT(Context);
+
+ PSAVEWORKER_PARAM pParam = (PSAVEWORKER_PARAM) Context;
+ PCSaveData pSaveData;
+
+ if (NULL == pParam)
+ {
+ // This is completely unexpected, assert here.
+ //
+ ASSERT(pParam);
+ return;
+ }
+
+ DPF(D_VERBOSE, ("[SaveFrameWorkerCallback], %d", pParam->ulFrameNo));
+
+ ASSERT(pParam->pSaveData);
+ ASSERT(pParam->pSaveData->m_fFrameUsed);
+
+ if (pParam->WorkItem)
+ {
+ pSaveData = pParam->pSaveData;
+
+ if (STATUS_SUCCESS == KeWaitForSingleObject
+ (
+ &pSaveData->m_FileSync,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL
+ ))
+ {
+ if (NT_SUCCESS(pSaveData->FileOpen(FALSE)))
+ {
+ pSaveData->FileWrite(pParam->pData, pParam->ulDataSize);
+ pSaveData->FileClose();
+ }
+ InterlockedExchange( (LONG *)&(pSaveData->m_fFrameUsed[pParam->ulFrameNo]), FALSE );
+
+ KeReleaseMutex( &pSaveData->m_FileSync, FALSE );
+ }
+ }
+
+ KeSetEvent(&pParam->EventDone, 0, FALSE);
+} // SaveFrameWorkerCallback
+
+//=============================================================================
+NTSTATUS
+CSaveData::SetDataFormat
+(
+ _In_ PKSDATAFORMAT pDataFormat
+)
+{
+ PAGED_CODE();
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ DPF_ENTER(("[CSaveData::SetDataFormat]"));
+
+ ASSERT(pDataFormat);
+
+ PWAVEFORMATEX pwfx = NULL;
+
+ if (IsEqualGUIDAligned(pDataFormat->Specifier,
+ KSDATAFORMAT_SPECIFIER_DSOUND))
+ {
+ pwfx =
+ &(((PKSDATAFORMAT_DSOUND) pDataFormat)->BufferDesc.WaveFormatEx);
+ }
+ else if (IsEqualGUIDAligned(pDataFormat->Specifier,
+ KSDATAFORMAT_SPECIFIER_WAVEFORMATEX))
+ {
+ pwfx = &((PKSDATAFORMAT_WAVEFORMATEX) pDataFormat)->WaveFormatEx;
+ }
+
+ if (pwfx)
+ {
+ // Free the previously allocated waveformat
+ if (m_waveFormat)
+ {
+ ExFreePoolWithTag(m_waveFormat, SAVEDATA_POOLTAG1);
+ }
+
+ m_waveFormat = (PWAVEFORMATEX)
+ ExAllocatePool2
+ (
+ POOL_FLAG_NON_PAGED,
+ (pwfx->wFormatTag == WAVE_FORMAT_PCM) ?
+ sizeof( PCMWAVEFORMAT ) :
+ sizeof( WAVEFORMATEX ) + pwfx->cbSize,
+ SAVEDATA_POOLTAG1
+ );
+
+ if(m_waveFormat)
+ {
+ RtlCopyMemory( m_waveFormat,
+ pwfx,
+ (pwfx->wFormatTag == WAVE_FORMAT_PCM) ?
+ sizeof( PCMWAVEFORMAT ) :
+ sizeof( WAVEFORMATEX ) + pwfx->cbSize);
+ }
+ else
+ {
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+ return ntStatus;
+} // SetDataFormat
+
+//=============================================================================
+NTSTATUS
+CSaveData::SetMaxWriteSize
+(
+ _In_ ULONG ulMaxWriteSize
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ ULONG bufferSize = 0;
+ PBYTE buffer = NULL;
+
+ DPF_ENTER(("[CSaveData::SetMaxWriteSize]"));
+
+ //
+ // Compute new buffer size.
+ //
+ ntStatus = RtlULongMult(ulMaxWriteSize, DEFAULT_FRAME_COUNT, &bufferSize);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ DPF(D_TERSE, ("[Could not allocate memory for Saving Data, MaxWriteSize %u is too big]", ulMaxWriteSize));
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Alloc memory for buffer.
+ //
+ buffer = (PBYTE)
+ ExAllocatePool2
+ (
+ POOL_FLAG_NON_PAGED,
+ bufferSize,
+ SAVEDATA_POOLTAG4
+ );
+ if (!buffer)
+ {
+ DPF(D_TERSE, ("[Could not allocate memory for Saving Data]"));
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Free old one.
+ //
+ if (m_pDataBuffer)
+ {
+ ExFreePoolWithTag(m_pDataBuffer, SAVEDATA_POOLTAG4);
+ m_pDataBuffer = NULL;
+ }
+
+ //
+ // Init new buffer settings.
+ //
+ m_pDataBuffer = buffer;
+ m_ulBufferSize = bufferSize;
+ m_ulFrameSize = ulMaxWriteSize;
+
+ ntStatus = STATUS_SUCCESS;
+
+Done:
+ return ntStatus;
+} // SetDataFormat
+
+//=============================================================================
+void
+CSaveData::ReadData
+(
+ _Inout_updates_bytes_all_(ulByteCount) PBYTE pBuffer,
+ _In_ ULONG ulByteCount
+)
+{
+ UNREFERENCED_PARAMETER(pBuffer);
+ UNREFERENCED_PARAMETER(ulByteCount);
+
+ PAGED_CODE();
+
+ // Not implemented yet.
+} // ReadData
+
+//=============================================================================
+#pragma code_seg()
+void
+CSaveData::SaveFrame
+(
+ _In_ ULONG ulFrameNo,
+ _In_ ULONG ulDataSize
+)
+{
+ PSAVEWORKER_PARAM pParam = NULL;
+
+ DPF_ENTER(("[CSaveData::SaveFrame]"));
+
+ pParam = GetNewWorkItem();
+ if (pParam)
+ {
+ pParam->pSaveData = this;
+ pParam->ulFrameNo = ulFrameNo;
+ pParam->ulDataSize = ulDataSize;
+ pParam->pData = m_pDataBuffer + ulFrameNo * m_ulFrameSize;
+ KeResetEvent(&pParam->EventDone);
+ IoQueueWorkItem(pParam->WorkItem, SaveFrameWorkerCallback,
+ CriticalWorkQueue, (PVOID)pParam);
+ }
+} // SaveFrame
+#pragma code_seg("PAGE")
+//=============================================================================
+void
+CSaveData::WaitAllWorkItems
+(
+ void
+)
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[CSaveData::WaitAllWorkItems]"));
+
+ // Save the last partially-filled frame
+ if (m_ulBufferOffset > m_ulFrameIndex * m_ulFrameSize)
+ {
+ ULONG size;
+
+ size = m_ulBufferOffset - m_ulFrameIndex * m_ulFrameSize;
+ SaveFrame(m_ulFrameIndex, size);
+ }
+
+ for (int i = 0; i < MAX_WORKER_ITEM_COUNT; i++)
+ {
+ DPF(D_VERBOSE, ("[Waiting for WorkItem] %d", i));
+ KeWaitForSingleObject
+ (
+ &(m_pWorkItems[i].EventDone),
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+ }
+} // WaitAllWorkItems
+
+#pragma code_seg()
+//=============================================================================
+void
+CSaveData::WriteData
+(
+ _In_reads_bytes_(ulByteCount) PBYTE pBuffer,
+ _In_ ULONG ulByteCount
+)
+{
+ ASSERT(pBuffer);
+
+ BOOL fSaveFrame = FALSE;
+ ULONG ulSaveFrameIndex = 0;
+ KIRQL oldIrql;
+
+ // If stream writing is disabled, then exit.
+ //
+ if (m_fWriteDisabled)
+ {
+ return;
+ }
+
+ DPF_ENTER(("[CSaveData::WriteData ulByteCount=%lu]", ulByteCount));
+
+ if( 0 == ulByteCount )
+ {
+ return;
+ }
+
+ // The logic below assumes that write size is <= than frame size.
+ if (ulByteCount > m_ulFrameSize)
+ {
+ ulByteCount = m_ulFrameSize;
+ }
+
+ // Check to see if this frame is available.
+ KeAcquireSpinLock(&m_FrameInUseSpinLock, &oldIrql);
+ if (!m_fFrameUsed[m_ulFrameIndex])
+ {
+ KeReleaseSpinLock(&m_FrameInUseSpinLock, oldIrql );
+
+ ULONG ulWriteBytes = ulByteCount;
+
+ if( (m_ulBufferSize - m_ulBufferOffset) < ulWriteBytes )
+ {
+ ulWriteBytes = m_ulBufferSize - m_ulBufferOffset;
+ }
+
+ RtlCopyMemory(m_pDataBuffer + m_ulBufferOffset, pBuffer, ulWriteBytes);
+ m_ulBufferOffset += ulWriteBytes;
+
+ // Check to see if we need to save this frame
+ if (m_ulBufferOffset >= ((m_ulFrameIndex + 1) * m_ulFrameSize))
+ {
+ fSaveFrame = TRUE;
+ }
+
+ // Loop the buffer, if we reached the end.
+ if (m_ulBufferOffset == m_ulBufferSize)
+ {
+ fSaveFrame = TRUE;
+ m_ulBufferOffset = 0;
+ }
+
+ if (fSaveFrame)
+ {
+ InterlockedExchange( (LONG *)&(m_fFrameUsed[m_ulFrameIndex]), TRUE );
+ ulSaveFrameIndex = m_ulFrameIndex;
+ m_ulFrameIndex = (m_ulFrameIndex + 1) % m_ulFrameCount;
+ }
+
+ // Write the left over if the next frame is available.
+ if (ulWriteBytes != ulByteCount)
+ {
+ KeAcquireSpinLock(&m_FrameInUseSpinLock, &oldIrql );
+ if (!m_fFrameUsed[m_ulFrameIndex])
+ {
+ KeReleaseSpinLock(&m_FrameInUseSpinLock, oldIrql );
+ RtlCopyMemory
+ (
+ m_pDataBuffer + m_ulBufferOffset,
+ pBuffer + ulWriteBytes,
+ ulByteCount - ulWriteBytes
+ );
+
+ m_ulBufferOffset += ulByteCount - ulWriteBytes;
+ }
+ else
+ {
+ KeReleaseSpinLock(&m_FrameInUseSpinLock, oldIrql);
+ DPF(D_BLAB, ("[Frame overflow, next frame is in use]"));
+ }
+ }
+
+ if (fSaveFrame)
+ {
+ SaveFrame(ulSaveFrameIndex, m_ulFrameSize);
+ }
+ }
+ else
+ {
+ KeReleaseSpinLock(&m_FrameInUseSpinLock, oldIrql );
+ DPF(D_BLAB, ("[Frame %d is in use]", m_ulFrameIndex));
+ }
+
+} // WriteData
+
diff --git a/audio/simpleaudiosample/Source/Utilities/savedata.h b/audio/simpleaudiosample/Source/Utilities/savedata.h
new file mode 100644
index 00000000..c658ec71
--- /dev/null
+++ b/audio/simpleaudiosample/Source/Utilities/savedata.h
@@ -0,0 +1,189 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ savedata.h
+
+Abstract:
+
+ Declaration of Simple Audio Sample data saving class. This class supplies services
+to save data to disk.
+
+--*/
+
+#ifndef _SIMPLEAUDIOSAMPLE_SAVEDATA_H
+#define _SIMPLEAUDIOSAMPLE_SAVEDATA_H
+
+//-----------------------------------------------------------------------------
+// Forward declaration
+//-----------------------------------------------------------------------------
+class CSaveData;
+typedef CSaveData *PCSaveData;
+
+
+//-----------------------------------------------------------------------------
+// Structs
+//-----------------------------------------------------------------------------
+
+// Parameter to workitem.
+#include <pshpack1.h>
+typedef struct _SAVEWORKER_PARAM {
+ PIO_WORKITEM WorkItem;
+ ULONG ulFrameNo;
+ ULONG ulDataSize;
+ PBYTE pData;
+ PCSaveData pSaveData;
+ KEVENT EventDone;
+} SAVEWORKER_PARAM;
+typedef SAVEWORKER_PARAM *PSAVEWORKER_PARAM;
+#include <poppack.h>
+
+// wave file header.
+#include <pshpack1.h>
+typedef struct _OUTPUT_FILE_HEADER
+{
+ DWORD dwRiff;
+ DWORD dwFileSize;
+ DWORD dwWave;
+ DWORD dwFormat;
+ DWORD dwFormatLength;
+} OUTPUT_FILE_HEADER;
+typedef OUTPUT_FILE_HEADER *POUTPUT_FILE_HEADER;
+
+typedef struct _OUTPUT_DATA_HEADER
+{
+ DWORD dwData;
+ DWORD dwDataLength;
+} OUTPUT_DATA_HEADER;
+typedef OUTPUT_DATA_HEADER *POUTPUT_DATA_HEADER;
+
+#include <poppack.h>
+
+//-----------------------------------------------------------------------------
+// Classes
+//-----------------------------------------------------------------------------
+
+///////////////////////////////////////////////////////////////////////////////
+// CSaveData
+// Saves the wave data to disk.
+//
+IO_WORKITEM_ROUTINE SaveFrameWorkerCallback;
+
+class CSaveData
+{
+protected:
+ UNICODE_STRING m_FileName; // DataFile name.
+ HANDLE m_FileHandle; // DataFile handle.
+ PBYTE m_pDataBuffer; // Data buffer.
+ ULONG m_ulBufferSize; // Total buffer size.
+
+ ULONG m_ulFrameIndex; // Current Frame.
+ ULONG m_ulFrameCount; // Frame count.
+ ULONG m_ulFrameSize;
+ ULONG m_ulBufferOffset; // index in buffer.
+ PBOOL m_fFrameUsed; // Frame usage table.
+ KSPIN_LOCK m_FrameInUseSpinLock; // Spinlock for synch.
+ KMUTEX m_FileSync; // Synchronizes file access
+
+ OBJECT_ATTRIBUTES m_objectAttributes; // Used for opening file.
+
+ OUTPUT_FILE_HEADER m_FileHeader;
+ PWAVEFORMATEX m_waveFormat;
+ OUTPUT_DATA_HEADER m_DataHeader;
+ PLARGE_INTEGER m_pFilePtr;
+
+ static PDEVICE_OBJECT m_pDeviceObject;
+ static ULONG m_ulStreamId;
+ static PSAVEWORKER_PARAM m_pWorkItems;
+
+ BOOL m_fWriteDisabled;
+
+ BOOL m_bInitialized;
+
+public:
+ CSaveData();
+ ~CSaveData();
+
+ static NTSTATUS InitializeWorkItems
+ (
+ _In_ PDEVICE_OBJECT DeviceObject
+ );
+ static void DestroyWorkItems
+ (
+ void
+ );
+ void Disable
+ (
+ _In_ BOOL fDisable
+ );
+ static PSAVEWORKER_PARAM GetNewWorkItem
+ (
+ void
+ );
+ NTSTATUS Initialize
+ (
+ );
+ static NTSTATUS SetDeviceObject
+ (
+ _In_ PDEVICE_OBJECT DeviceObject
+ );
+ static PDEVICE_OBJECT GetDeviceObject
+ (
+ void
+ );
+ void ReadData
+ (
+ _Inout_updates_bytes_all_(ulByteCount) PBYTE pBuffer,
+ _In_ ULONG ulByteCount
+ );
+ NTSTATUS SetDataFormat
+ (
+ _In_ PKSDATAFORMAT pDataFormat
+ );
+ NTSTATUS SetMaxWriteSize
+ (
+ _In_ ULONG ulMaxWriteSize
+ );
+ void WaitAllWorkItems
+ (
+ void
+ );
+ void WriteData
+ (
+ _In_reads_bytes_(ulByteCount) PBYTE pBuffer,
+ _In_ ULONG ulByteCount
+ );
+
+private:
+ NTSTATUS FileClose
+ (
+ void
+ );
+ NTSTATUS FileOpen
+ (
+ _In_ BOOL fOverWrite
+ );
+ NTSTATUS FileWrite
+ (
+ _In_reads_bytes_(ulDataSize) PBYTE pData,
+ _In_ ULONG ulDataSize
+ );
+ NTSTATUS FileWriteHeader
+ (
+ void
+ );
+
+ void SaveFrame
+ (
+ _In_ ULONG ulFrameNo,
+ _In_ ULONG ulDataSize
+ );
+
+ friend
+ IO_WORKITEM_ROUTINE SaveFrameWorkerCallback;
+};
+typedef CSaveData *PCSaveData;
+
+#endif
diff --git a/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj
index b4d1c802..6a7a4678 100644
--- a/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj
+++ b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj
@@ -140,6 +140,9 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<ResourceCompile>
@@ -157,6 +160,9 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ResourceCompile>
@@ -174,6 +180,9 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<ResourceCompile>
@@ -191,6 +200,9 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ResourceCompile>
@@ -208,6 +220,9 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ResourceCompile>
@@ -225,6 +240,9 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="AudioModuleHelper.cpp" />
diff --git a/audio/sysvad/EndpointsCommon/mintopo.cpp b/audio/sysvad/EndpointsCommon/mintopo.cpp
index 28ddf419..4e417c4a 100644
--- a/audio/sysvad/EndpointsCommon/mintopo.cpp
+++ b/audio/sysvad/EndpointsCommon/mintopo.cpp
@@ -570,7 +570,7 @@ Return Value:
// 0x00000002 - JACKDESC2_DYNAMIC_FORMAT_CHANGE_CAPABILITY
//
pDesc->JackCapabilities = JackCapabilities;
-
+
ntStatus = STATUS_SUCCESS;
}
}
@@ -581,6 +581,7 @@ Return Value:
return ntStatus;
}
+
#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND)
//=============================================================================
#pragma code_seg()
diff --git a/audio/sysvad/EndpointsCommon/mintopo.h b/audio/sysvad/EndpointsCommon/mintopo.h
index 4aa3d2de..b4eda617 100644
--- a/audio/sysvad/EndpointsCommon/mintopo.h
+++ b/audio/sysvad/EndpointsCommon/mintopo.h
@@ -33,6 +33,8 @@ class CMiniportTopology :
{
private:
eDeviceType m_DeviceType;
+
+
union {
PVOID m_DeviceContext;
#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND)
@@ -55,6 +57,7 @@ public:
m_DeviceType(DeviceType),
m_DeviceContext(DeviceContext)
{
+
#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND)
if (IsSidebandDevice())
{
@@ -73,18 +76,19 @@ public:
NTSTATUS PropertyHandlerJackDescription
(
- _In_ PPCPROPERTY_REQUEST PropertyRequest,
- _In_ ULONG cJackDescriptions,
- _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION * JackDescriptions
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG cJackDescriptions,
+ _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION *JackDescriptions
);
NTSTATUS PropertyHandlerJackDescription2
(
- _In_ PPCPROPERTY_REQUEST PropertyRequest,
- _In_ ULONG cJackDescriptions,
- _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION * JackDescriptions,
- _In_ DWORD JackCapabilities
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ ULONG cJackDescriptions,
+ _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION *JackDescriptions,
+ _In_ DWORD JackCapabilities
);
+
#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND)
BOOL IsSidebandDevice()
diff --git a/audio/sysvad/EndpointsCommon/minwavertstream.cpp b/audio/sysvad/EndpointsCommon/minwavertstream.cpp
index 93ecdcf3..499d5b38 100644
--- a/audio/sysvad/EndpointsCommon/minwavertstream.cpp
+++ b/audio/sysvad/EndpointsCommon/minwavertstream.cpp
@@ -968,12 +968,12 @@ NTSTATUS CMiniportWaveRTStream::GetReadPacket
// Return next packet number to be read
*PacketNumber = availablePacketNumber;
- // Compute and return timestamp corresponding to start of the available packet. In a real hardware
+ // Compute and return timestamp corresponding to the end of the available packet. In a real hardware
// driver, the timestamp would be computed in a driver and hardware specific manner. In this sample
// driver, it is extrapolated from the sample driver's internal simulated position correlation
// [m_ullLinearPosition @ m_ullDmaTimeStamp] and the sample's internal 64-bit packet counter, subtracting
// 1 from the packet counter to compute the time at the start of that last completed packet.
- ULONGLONG linearPositionOfAvailablePacket = (packetCounter - 1) * (m_ulDmaBufferSize / m_ulNotificationsPerBuffer);
+ ULONGLONG linearPositionOfAvailablePacket = packetCounter * (m_ulDmaBufferSize / m_ulNotificationsPerBuffer);
// Need to divide by (1000 * 10000 because m_ulDmaMovementRate is average bytes per sec
ULONGLONG carryForwardBytes = (hnsElapsedTimeCarryForward * m_ulDmaMovementRate) / 10000000;
ULONGLONG deltaLinearPosition = ullLinearPosition + carryForwardBytes - linearPositionOfAvailablePacket;
diff --git a/audio/sysvad/EndpointsCommon/speakertopo.cpp b/audio/sysvad/EndpointsCommon/speakertopo.cpp
index cca4dac9..fee3d542 100644
--- a/audio/sysvad/EndpointsCommon/speakertopo.cpp
+++ b/audio/sysvad/EndpointsCommon/speakertopo.cpp
@@ -22,7 +22,6 @@ Abstract:
#pragma code_seg("PAGE")
-
//=============================================================================
NTSTATUS
PropertyHandler_SpeakerTopoFilter
diff --git a/audio/sysvad/EndpointsCommon/speakertoptable.h b/audio/sysvad/EndpointsCommon/speakertoptable.h
index 50f58c7b..6850c0cf 100644
--- a/audio/sysvad/EndpointsCommon/speakertoptable.h
+++ b/audio/sysvad/EndpointsCommon/speakertoptable.h
@@ -85,7 +85,7 @@ PCPIN_DESCRIPTOR SpeakerTopoMiniportPins[] =
//=============================================================================
static
-KSJACK_DESCRIPTION SpeakerJackDescSpeakers =
+KSJACK_DESCRIPTION SpeakerJackDescBridge =
{
KSAUDIO_SPEAKER_STEREO,
0xB3C98C, // Color spec for green
@@ -101,9 +101,10 @@ static
PKSJACK_DESCRIPTION SpeakerJackDescriptions[] =
{
NULL,
- &SpeakerJackDescSpeakers
+ &SpeakerJackDescBridge
};
+
//=============================================================================
static
PCCONNECTION_DESCRIPTOR SpeakerTopoMiniportConnections[] =
@@ -120,13 +121,15 @@ PCPROPERTY_ITEM PropertiesSpeakerTopoFilter[] =
{
&KSPROPSETID_Jack,
KSPROPERTY_JACK_DESCRIPTION,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ KSPROPERTY_TYPE_GET |
+ KSPROPERTY_TYPE_BASICSUPPORT,
PropertyHandler_SpeakerTopoFilter
},
{
&KSPROPSETID_Jack,
KSPROPERTY_JACK_DESCRIPTION2,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ KSPROPERTY_TYPE_GET |
+ KSPROPERTY_TYPE_BASICSUPPORT,
PropertyHandler_SpeakerTopoFilter
}
};
@@ -152,4 +155,4 @@ PCFILTER_DESCRIPTOR SpeakerTopoMiniportFilterDescriptor =
};
#endif // _SYSVAD_SPEAKERTOPTABLE_H_
-
+
diff --git a/audio/sysvad/Package/package.VcxProj b/audio/sysvad/Package/package.VcxProj
index dba6d6b4..aedc7dc4 100644
--- a/audio/sysvad/Package/package.VcxProj
+++ b/audio/sysvad/Package/package.VcxProj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?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|ARM64">
@@ -30,9 +30,6 @@
<ProjectReference Include="..\KeywordDetectorAdapter\KeywordDetectorContosoAdapter.vcxproj">
<Project>{E0F02048-78A4-4FE8-B863-66E6CB6A2C37}</Project>
</ProjectReference>
- <ProjectReference Include="..\PhoneAudioSample\PhoneAudioSample.vcxproj">
- <Project>{FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}</Project>
- </ProjectReference>
<ProjectReference Include="..\APO\SwapAPO\SwapAPO.vcxproj">
<Project>{691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}</Project>
</ProjectReference>
@@ -107,9 +104,37 @@
<VerifyDrivers />
<VerifyFlags>133563</VerifyFlags>
</PropertyGroup>
- <ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project> \ No newline at end of file
+</Project>
diff --git a/audio/sysvad/PhoneAudioSample/CellularWave.cpp b/audio/sysvad/PhoneAudioSample/CellularWave.cpp
deleted file mode 100644
index 1a999c1e..00000000
--- a/audio/sysvad/PhoneAudioSample/CellularWave.cpp
+++ /dev/null
@@ -1,685 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- cellularwave.cpp
-
-Abstract:
-
- Implementation of wavert miniport for cellular
-
---*/
-
-#pragma warning (disable : 4127)
-
-#include <sysvad.h>
-#include "simple.h"
-#include "CellularWave.h"
-#include "CellularTopo.h"
-#include "CellularToptable.h"
-
-//=============================================================================
-// CCellularMiniportWaveRT
-//=============================================================================
-
-//=============================================================================
-#pragma code_seg("PAGE")
-NTSTATUS
-CreateCellularMiniportWaveRT
-(
- _Out_ PUNKNOWN * Unknown,
- _In_ REFCLSID,
- _In_opt_ PUNKNOWN UnknownOuter,
- _When_((PoolType & NonPagedPoolMustSucceed) != 0,
- __drv_reportError("Must succeed pool allocations are forbidden. "
- "Allocation failures cause a system crash"))
- _In_ POOL_TYPE PoolType,
- _In_ PUNKNOWN UnknownAdapter,
- _In_opt_ PVOID DeviceContext,
- _In_ PENDPOINT_MINIPAIR MiniportPair
-)
-/*++
-
-Routine Description:
-
- Create the wavert miniport.
-
-Arguments:
-
- Unknown -
-
- RefClsId -
-
- UnknownOuter -
-
- PoolType -
-
- UnkownAdapter -
-
- DeviceContext -
-
- MiniportPair -
-
-Return Value:
-
- NT status code.
-
---*/
-{
- UNREFERENCED_PARAMETER(UnknownOuter);
-
- PAGED_CODE();
-
- ASSERT(Unknown);
- ASSERT(MiniportPair);
-
- CMiniportWaveRT *obj = new (PoolType, MINWAVERT_POOLTAG) CCellularMiniportWaveRT
- (
- UnknownAdapter,
- MiniportPair,
- DeviceContext
- );
- if (NULL == obj)
- {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- obj->AddRef();
- *Unknown = reinterpret_cast<IUnknown*>(obj);
-
- return STATUS_SUCCESS;
-}
-
-//=============================================================================
-#pragma code_seg("PAGE")
-CCellularMiniportWaveRT::~CCellularMiniportWaveRT
-(
- void
-)
-/*++
-
-Routine Description:
-
- Destructor for wavert miniport
-
-Arguments:
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- DPF_ENTER(("[CCellularMiniportWaveRT::~CCellularMiniportWaveRT]"));
-
-} // ~CCellularMiniportWaveRT
-
-
-//=============================================================================
-#pragma code_seg("PAGE")
-STDMETHODIMP
-CCellularMiniportWaveRT::NonDelegatingQueryInterface
-(
- _In_ REFIID Interface,
- _COM_Outptr_ PVOID * Object
-)
-/*++
-
-Routine Description:
-
- QueryInterface for CCellularMiniportWaveRT
-
-Arguments:
-
- Interface - GUID of the interface
-
- Object - interface object to be returned.
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(Object);
-
- if (IsEqualGUIDAligned(Interface, IID_IAdapterPowerManagement))
- {
- *Object = PVOID(PADAPTERPOWERMANAGEMENT(this));
- }
- else
- {
- *Object = NULL;
- }
-
- if (*Object)
- {
- // We reference the interface for the caller.
-
- PUNKNOWN(*Object)->AddRef();
- return STATUS_SUCCESS;
- }
-
- return CMiniportWaveRT::NonDelegatingQueryInterface(Interface, Object);
-}
-
-#pragma code_seg("PAGE")
-NTSTATUS
-PropertyHandler_CellularWaveFilter
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
- Redirects general property request to miniport object
-
-Arguments:
-
- PropertyRequest -
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
- CCellularMiniportWaveRT* pWaveHelper = reinterpret_cast<CCellularMiniportWaveRT*>(PropertyRequest->MajorTarget);
-
- if (pWaveHelper == NULL)
- {
- return STATUS_INVALID_PARAMETER;
- }
-
- pWaveHelper->AddRef();
-
- if (pWaveHelper->m_DeviceType == eCellularDevice &&
- IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_TelephonyControl))
- {
- switch (PropertyRequest->PropertyItem->Id)
- {
- case KSPROPERTY_TELEPHONY_PROVIDERID:
- ntStatus = pWaveHelper->PropertyHandler_TelephonyProviderId(PropertyRequest);
- break;
-
- case KSPROPERTY_TELEPHONY_CALLINFO:
- ntStatus = pWaveHelper->PropertyHandler_TelephonyCallInfo(PropertyRequest);
- break;
-
- case KSPROPERTY_TELEPHONY_CALLCONTROL:
- case KSPROPERTY_TELEPHONY_PROVIDERCHANGE:
- ntStatus = pWaveHelper->PropertyHandler_TelephonyCallState(PropertyRequest);
- break;
-
- case KSPROPERTY_TELEPHONY_CALLHOLD:
- ntStatus = pWaveHelper->PropertyHandler_TelephonyCallHold(PropertyRequest);
- break;
-
- case KSPROPERTY_TELEPHONY_MUTE_TX:
- ntStatus = pWaveHelper->PropertyHandler_TelephonyMuteTx(PropertyRequest);
- break;
-
- default:
- DPF(D_TERSE, ("[PropertyHandler_CellularWaveFilter: Invalid Device Request]"));
- }
- }
- else
- {
- ntStatus = PropertyHandler_WaveFilter(PropertyRequest);
- }
-
- pWaveHelper->Release();
-
- return ntStatus;
-} // PropertyHandler_CellularWaveFilter
-
-//=============================================================================
-#pragma code_seg("PAGE")
-NTSTATUS
-CCellularMiniportWaveRT::PropertyHandler_TelephonyProviderId
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-{
- NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
-
- PAGED_CODE();
-
- DPF_ENTER(("[CCellularMiniportWaveRT::PropertyHandler_TelephonyProviderId]"));
-
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ULONG flags = PropertyRequest->PropertyItem->Flags;
- ntStatus = PropertyHandler_BasicSupport(PropertyRequest, flags, VT_ILLEGAL);
- }
- else
- {
- ULONG cbMinSize = sizeof(ULONG);
-
- if (PropertyRequest->ValueSize == 0)
- {
- PropertyRequest->ValueSize = cbMinSize;
- ntStatus = STATUS_BUFFER_OVERFLOW;
- }
- else if (PropertyRequest->ValueSize < cbMinSize)
- {
- ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- ULONG* providerId = (ULONG*)PropertyRequest->Value;
- // Return supported TelephonyProviderId (executor id).
- *providerId = m_TelephonyProviderId;
- ntStatus = STATUS_SUCCESS;
- }
- else
- {
- ntStatus = STATUS_INVALID_PARAMETER;
- }
- }
- }
-
- return ntStatus;
-} // PropertyHandler_TelephonyProviderId
-
-//=============================================================================
-#pragma code_seg("PAGE")
-NTSTATUS
-CCellularMiniportWaveRT::PropertyHandler_TelephonyCallInfo
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-{
- NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
-
- PAGED_CODE();
-
- DPF_ENTER(("[CCellularMiniportWaveRT::PropertyHandler_TelephonyCallInfo]"));
-
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ULONG flags = PropertyRequest->PropertyItem->Flags;
- ntStatus = PropertyHandler_BasicSupport(PropertyRequest, flags, VT_ILLEGAL);
- }
- else
- {
- ULONG cbMinSize = sizeof(KSTELEPHONY_CALLINFO);
-
- if (PropertyRequest->ValueSize == 0)
- {
- PropertyRequest->ValueSize = cbMinSize;
- ntStatus = STATUS_BUFFER_OVERFLOW;
- }
- else if (PropertyRequest->ValueSize < cbMinSize)
- {
- ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- PKSTELEPHONY_CALLINFO TelephonyCallInfo = static_cast<PKSTELEPHONY_CALLINFO>(PropertyRequest->Value);
- // Return current CallType and CallState information. CallType information is not valid when the CallState is disabled.
- TelephonyCallInfo->CallType = m_TelephonyCallType;
- TelephonyCallInfo->CallState = m_TelephonyCallState;
- ntStatus = STATUS_SUCCESS;
- }
- else
- {
- ntStatus = STATUS_INVALID_PARAMETER;
- }
- }
- }
-
- return ntStatus;
-} // PropertyHandler_TelephonyCallInfo
-
-#pragma code_seg("PAGE")
-NTSTATUS
-CCellularMiniportWaveRT::UpdateTopologyJackState
-(
- _In_ ULONG TelephonyId,
- _In_ BOOL NewState
-)
-{
- PAGED_CODE ();
- NTSTATUS ntStatus = STATUS_SUCCESS;
- IUnknown *pUnknown = NULL;
- ICellularTopology *pCellularTopology = NULL;
-
- // GetFilters returns the topology port, then topology miniport, then wave port, then wave miniport.
- // we only need the topology miniport.
- ntStatus = m_pAdapterCommon->GetFilters(m_pMiniportPair, NULL, &pUnknown, NULL, NULL);
- if (NT_SUCCESS(ntStatus))
- {
- ntStatus = pUnknown->QueryInterface(IID_ICellularTopology, (PVOID *)&pCellularTopology);
- if (NT_SUCCESS(ntStatus))
- {
- ntStatus = pCellularTopology->UpdateTopologyJackState(TelephonyId, NewState);
- }
- }
-
- SAFE_RELEASE(pCellularTopology);
- SAFE_RELEASE(pUnknown);
-
- return STATUS_SUCCESS;
-}
-#pragma code_seg()
-
-//=============================================================================
-#pragma code_seg("PAGE")
-NTSTATUS
-CCellularMiniportWaveRT::PropertyHandler_TelephonyCallState
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-{
- NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
-
- PAGED_CODE();
-
- DPF_ENTER(("[CCellularMiniportWaveRT::PropertyHandler_TelephonyCallState]"));
-
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ULONG flags = PropertyRequest->PropertyItem->Flags;
- ntStatus = PropertyHandler_BasicSupport(PropertyRequest, flags, VT_ILLEGAL);
- }
- else
- {
- ULONG cbMinSize = 0;
-
- if (PropertyRequest->PropertyItem->Id == KSPROPERTY_TELEPHONY_CALLCONTROL)
- {
- cbMinSize = sizeof(KSTELEPHONY_CALLCONTROL);
- }
- else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_TELEPHONY_PROVIDERCHANGE)
- {
- cbMinSize = sizeof(KSTELEPHONY_PROVIDERCHANGE);
- }
-
- if (PropertyRequest->ValueSize == 0)
- {
- PropertyRequest->ValueSize = cbMinSize;
- ntStatus = STATUS_BUFFER_OVERFLOW;
- }
- else if (PropertyRequest->ValueSize < cbMinSize)
- {
- ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
- {
- if (PropertyRequest->PropertyItem->Id == KSPROPERTY_TELEPHONY_CALLCONTROL)
- {
- PKSTELEPHONY_CALLCONTROL TelephonyCallControl = static_cast<PKSTELEPHONY_CALLCONTROL>(PropertyRequest->Value);
-
- // KSPROPERTY_TELEPHONY_CALLCONTROL has info about CallType and CallControlOp. TELEPHONY_CALLCONTROLOP_ENABLE will start
- // cellular call from audio driver perspective, update jack state for associated cellular bidi endpoint to active,
- // save call type and update the call state to Enabled. TELEPHONY_CALLCONTROLOP_DISABLE will terminate cellular call
- // from audio driver perspective, update jack state for associated cellular bidi endpoint to unplugged and update
- // call state to Disabled. Call type is ignored in this case.
- switch (TelephonyCallControl->CallControlOp)
- {
- case TELEPHONY_CALLCONTROLOP_DISABLE:
- ASSERT(m_TelephonyCallState != TELEPHONY_CALLSTATE_DISABLED);
- m_TelephonyCallState = TELEPHONY_CALLSTATE_DISABLED;
- UpdateTopologyJackState(m_TelephonyProviderId, FALSE);
- // Release our idle power management requirement
- m_pAdapterCommon->SetIdlePowerManagement(m_pMiniportPair, TRUE);
- ntStatus = STATUS_SUCCESS;
- break;
-
- case TELEPHONY_CALLCONTROLOP_ENABLE:
- ASSERT(m_TelephonyCallState != TELEPHONY_CALLSTATE_ENABLED);
- m_TelephonyCallType = TelephonyCallControl->CallType;
- m_TelephonyCallState = TELEPHONY_CALLSTATE_ENABLED;
- UpdateTopologyJackState(m_TelephonyProviderId, TRUE);
- // When we're in a call, we need idle power management disabled.
- m_pAdapterCommon->SetIdlePowerManagement(m_pMiniportPair, FALSE);
- ntStatus = STATUS_SUCCESS;
- break;
-
- default:
- ntStatus = STATUS_INVALID_PARAMETER;
- break;
- }
- }
- else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_TELEPHONY_PROVIDERCHANGE)
- {
- PKSTELEPHONY_PROVIDERCHANGE TelephonyProviderChange = static_cast<PKSTELEPHONY_PROVIDERCHANGE>(PropertyRequest->Value);
-
- // KSPROPERTY_TELEPHONY_PROVIDERCHANGE has info about CallType and ProviderChangeOp. TELEPHONY_PROVIDERCHANGEOP_BEGIN will indicate
- // start of SRVCC to audio driver. Audio driver will then start the SRVCC and update the call state to ProviderTransition.
- // TELEPHONY_PROVIDERCHANGEOP_END will indicate end of SRVCC to audio driver and driver will end SRVCC process and update
- // call state to Enabled. TELEPHONY_PROVIDERCHANGEOP_CANCEL will indicate SRVCC was aborted and audio driver will revert back to
- // pre SRVCC call.
- switch (TelephonyProviderChange->ProviderChangeOp)
- {
- case TELEPHONY_PROVIDERCHANGEOP_END:
- m_TelephonyCallState = TELEPHONY_CALLSTATE_ENABLED;
- ntStatus = STATUS_SUCCESS;
- break;
-
- case TELEPHONY_PROVIDERCHANGEOP_BEGIN:
- m_PreviousTelephonyCallType = m_TelephonyCallType;
- m_TelephonyCallType = TelephonyProviderChange->CallType;
- m_TelephonyCallState = TELEPHONY_CALLSTATE_PROVIDERTRANSITION;
- ntStatus = STATUS_SUCCESS;
- break;
-
- case TELEPHONY_PROVIDERCHANGEOP_CANCEL:
- m_TelephonyCallType = m_PreviousTelephonyCallType;
- m_TelephonyCallState = TELEPHONY_CALLSTATE_ENABLED;
- ntStatus = STATUS_SUCCESS;
- break;
-
- default:
- ntStatus = STATUS_INVALID_PARAMETER;
- break;
- }
- }
- else
- {
- ntStatus = STATUS_INVALID_PARAMETER;
- }
- }
- else
- {
- ntStatus = STATUS_INVALID_PARAMETER;
- }
- }
- }
-
- return ntStatus;
-} // PropertyHandler_TelephonyCallState
-
-//=============================================================================
-#pragma code_seg("PAGE")
-NTSTATUS
-CCellularMiniportWaveRT::PropertyHandler_TelephonyCallHold
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-{
- NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
-
- PAGED_CODE();
-
- DPF_ENTER(("[CCellularMiniportWaveRT::PropertyHandler_TelephonyCallHold]"));
-
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ULONG flags = PropertyRequest->PropertyItem->Flags;
- ntStatus = PropertyHandler_BasicSupport(PropertyRequest, flags, VT_ILLEGAL);
- }
- else
- {
- ULONG cbMinSize = sizeof(BOOL);
-
- if (PropertyRequest->ValueSize == 0)
- {
- PropertyRequest->ValueSize = cbMinSize;
- ntStatus = STATUS_BUFFER_OVERFLOW;
- }
- else if (PropertyRequest->ValueSize < cbMinSize)
- {
- ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- BOOL* bTelephonyHold = (BOOL*) PropertyRequest->Value;
- // Return if the call is on hold or not
- *bTelephonyHold = m_bTelephonyHold;
- ntStatus = STATUS_SUCCESS;
- }
- else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
- {
- BOOL* bTelephonyHold = (BOOL*) PropertyRequest->Value;
- m_bTelephonyHold = *bTelephonyHold;
-
- // If this property is TRUE, put the call on hold and update the call state to hold.
- // If this property is FALSE, take the call out of hold and update the call state to enabled.
- m_TelephonyCallState = (*bTelephonyHold) ? TELEPHONY_CALLSTATE_HOLD : TELEPHONY_CALLSTATE_ENABLED;
- ntStatus = STATUS_SUCCESS;
- }
- else
- {
- ntStatus = STATUS_INVALID_PARAMETER;
- }
- }
- }
-
- return ntStatus;
-} // PropertyHandler_TelephonyCallHold
-
-//=============================================================================
-#pragma code_seg("PAGE")
-NTSTATUS
-CCellularMiniportWaveRT::PropertyHandler_TelephonyMuteTx
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-{
- NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
-
- PAGED_CODE();
-
- DPF_ENTER(("[CCellularMiniportWaveRT::PropertyHandler_TelephonyMuteTx]"));
-
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ULONG flags = PropertyRequest->PropertyItem->Flags;
- ntStatus = PropertyHandler_BasicSupport(PropertyRequest, flags, VT_ILLEGAL);
- }
- else
- {
- ULONG cbMinSize = sizeof(BOOL);
-
- if (PropertyRequest->ValueSize == 0)
- {
- PropertyRequest->ValueSize = cbMinSize;
- ntStatus = STATUS_BUFFER_OVERFLOW;
- }
- else if (PropertyRequest->ValueSize < cbMinSize)
- {
- ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- BOOL* bTxMute = (BOOL*) PropertyRequest->Value;
- // Return if the cellular Tx is on muted or not
- *bTxMute = m_bTelephonyMuteTx;
- ntStatus = STATUS_SUCCESS;
- }
- else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
- {
- BOOL* bTxMute = (BOOL*) PropertyRequest->Value;
- // If this property is TRUE, mute cellular Tx data. However, it should not mute the data that was injected to KSNODETYPE_TELEPHONY_TX.
- // If this property is FALSE, unmute cellular Tx data.
- m_bTelephonyMuteTx = *bTxMute;
- ntStatus = STATUS_SUCCESS;
- }
- else
- {
- ntStatus = STATUS_INVALID_PARAMETER;
- }
- }
- }
-
- return ntStatus;
-} // PropertyHandler_TelephonyMuteTx
-
-//=============================================================================
-#pragma code_seg()
-STDMETHODIMP_(void)
-CCellularMiniportWaveRT::PowerChangeState
-(
- _In_ POWER_STATE NewState
-)
-{
- DPF_ENTER(("[CCellularMiniportWaveRT::PowerChangeState]"));
- UNREFERENCED_PARAMETER(NewState);
-
- /*
- Turn on and off cellular specific hardware here, if applicable.
- */
-
-} // PowerStateChange
-
-//=============================================================================
-#pragma code_seg()
-STDMETHODIMP_(NTSTATUS)
-CCellularMiniportWaveRT::QueryDeviceCapabilities
-(
- _Inout_updates_bytes_(sizeof(DEVICE_CAPABILITIES)) PDEVICE_CAPABILITIES PowerDeviceCaps
-)
-{
- UNREFERENCED_PARAMETER(PowerDeviceCaps);
-
- /*
- Unused at the miniport layer. Any device capabilities should be reported in CAdapterCommon
- */
-
- return (STATUS_SUCCESS);
-} // QueryDeviceCapabilities
-
-//=============================================================================
-#pragma code_seg()
-STDMETHODIMP_(NTSTATUS)
-CCellularMiniportWaveRT::QueryPowerChangeState
-(
- _In_ POWER_STATE NewStateQuery
-)
-{
- UNREFERENCED_PARAMETER(NewStateQuery);
-
- DPF_ENTER(("[CCellularMiniportWaveRT::QueryPowerChangeState]"));
-
- // if we're in a call state other than disabled, then we need the hardware turned on.
- if (TELEPHONY_CALLSTATE_DISABLED != m_TelephonyCallState)
- {
- return STATUS_RESOURCE_IN_USE;
- }
-
- return STATUS_SUCCESS;
-} // QueryPowerChangeState
-
-
diff --git a/audio/sysvad/PhoneAudioSample/CellularWave.h b/audio/sysvad/PhoneAudioSample/CellularWave.h
deleted file mode 100644
index 1704ff0c..00000000
--- a/audio/sysvad/PhoneAudioSample/CellularWave.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- cellularwave.h
-
-Abstract:
-
- Definition of wavert miniport class for cellular
-
---*/
-
-#include "MinWaveRT.h"
-
-#ifndef _SYSVAD_CELLULARMINWAVERT_H_
-#define _SYSVAD_CELLULARMINWAVERT_H_
-
-NTSTATUS
-CreateCellularMiniportWaveRT
-(
- _Out_ PUNKNOWN * Unknown,
- _In_ REFCLSID,
- _In_opt_ PUNKNOWN UnknownOuter,
- _When_((PoolType & NonPagedPoolMustSucceed) != 0,
- __drv_reportError("Must succeed pool allocations are forbidden. "
- "Allocation failures cause a system crash"))
- _In_ POOL_TYPE PoolType,
- _In_ PUNKNOWN UnknownAdapter,
- _In_opt_ PVOID DeviceContext,
- _In_ PENDPOINT_MINIPAIR MiniportPair
-);
-
-//=============================================================================
-// Classes
-//=============================================================================
-///////////////////////////////////////////////////////////////////////////////
-// CCellularMiniportWaveRT
-//
-class CCellularMiniportWaveRT :
- public CMiniportWaveRT,
- public IAdapterPowerManagement
-{
-private:
- ULONG m_TelephonyProviderId;
- TELEPHONY_CALLTYPE m_TelephonyCallType;
- TELEPHONY_CALLTYPE m_PreviousTelephonyCallType;
- TELEPHONY_CALLSTATE m_TelephonyCallState;
- BOOL m_bTelephonyHold;
- BOOL m_bTelephonyMuteTx;
-
-public:
- DECLARE_STD_UNKNOWN();
- IMP_IAdapterPowerManagement;
-
- CCellularMiniportWaveRT(
- _In_ PUNKNOWN UnknownAdapter,
- _In_ PENDPOINT_MINIPAIR MiniportPair,
- _In_opt_ PVOID DeviceContext
- )
- :CMiniportWaveRT(UnknownAdapter, MiniportPair, DeviceContext),
- m_TelephonyProviderId(0),
- m_TelephonyCallType(TELEPHONY_CALLTYPE_CIRCUITSWITCHED),
- m_PreviousTelephonyCallType(TELEPHONY_CALLTYPE_CIRCUITSWITCHED),
- m_TelephonyCallState(TELEPHONY_CALLSTATE_DISABLED),
- m_bTelephonyHold(FALSE),
- m_bTelephonyMuteTx(FALSE)
- {
- if (IsCellularDevice())
- {
- if (m_DeviceFlags & ENDPOINT_CELLULAR_PROVIDER1)
- {
- m_TelephonyProviderId = 0;
- }
- else if (m_DeviceFlags & ENDPOINT_CELLULAR_PROVIDER2)
- {
- m_TelephonyProviderId = 1;
- }
- }
- }
-
- ~CCellularMiniportWaveRT();
-
- friend NTSTATUS PropertyHandler_CellularWaveFilter
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
-public:
- NTSTATUS PropertyHandler_TelephonyProviderId
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
- NTSTATUS PropertyHandler_TelephonyCallInfo
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
- NTSTATUS PropertyHandler_TelephonyCallState
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
- NTSTATUS PropertyHandler_TelephonyCallHold
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
- NTSTATUS PropertyHandler_TelephonyMuteTx
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
-private:
- NTSTATUS UpdateTopologyJackState
- (
- _In_ ULONG TelephonyId,
- _In_ BOOL NewState
- );
-};
-typedef CCellularMiniportWaveRT *PCCellularMiniportWaveRT;
-
-#endif // _SYSVAD_CELLULARMINWAVERT_H_
-
diff --git a/audio/sysvad/PhoneAudioSample/Cellulartopo.cpp b/audio/sysvad/PhoneAudioSample/Cellulartopo.cpp
deleted file mode 100644
index 7329a9f9..00000000
--- a/audio/sysvad/PhoneAudioSample/Cellulartopo.cpp
+++ /dev/null
@@ -1,1117 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- cellulartopo.cpp
-
-Abstract:
-
- Implementation of topology miniport for the cellular endpoint.
-
---*/
-
-#pragma warning (disable : 4127)
-
-#include <sysvad.h>
-#include "simple.h"
-#include "mintopo.h"
-#include "cellulartopo.h"
-#include "cellulartoptable.h"
-#include <ntstrsafe.h>
-
-
-#pragma code_seg("PAGE")
-
-
-// table of valid render/capture combinations for cellular routing.
-// speaker and mic (speakerphone)
-// headset speaker and headset mic (wired headset)
-// headset speaker and mic (wired headset without microphone)
-// handset speaker and handset mic (handset)
-// HFP speaker and HFP mic (bluetooth hands free)
-// special host routing pair
-KSTOPOLOGY_ENDPOINTIDPAIR g_EndpointList[] =
-{
- { HANDSET_SPEAKER_TOPONAME, KSPIN_TOPO_LINEOUT_DEST, HANDSET_MIC_TOPONAME, KSPIN_TOPO_MIC_ELEMENTS },
- { SPEAKER_TOPONAME, KSPIN_TOPO_LINEOUT_DEST, MIC_ARRAY1_TOPONAME, KSPIN_TOPO_MIC_ELEMENTS },
- { SPEAKER_HEADSET_TOPONAME, KSPIN_TOPO_LINEOUT_DEST, MIC_HEADSET_TOPONAME, KSPIN_TOPO_MIC_ELEMENTS },
- { SPEAKER_HEADSET_TOPONAME, KSPIN_TOPO_LINEOUT_DEST, MIC_ARRAY1_TOPONAME, KSPIN_TOPO_MIC_ELEMENTS },
- { HFP_SPEAKER_TOPONAME, KSPIN_TOPO_LINEOUT_DEST, HFP_MIC_TOPONAME, KSPIN_TOPO_MIC_ELEMENTS },
- { HOSTRENDER_TOPONAME, HOSTRENDER_PIN, HOSTCAPTURE_TOPONAME, HOSTCAPTURE_PIN }
-};
-
-//=============================================================================
-NTSTATUS
-CreateCellularMiniportTopology
-(
- _Out_ PUNKNOWN * Unknown,
- _In_ REFCLSID,
- _In_opt_ PUNKNOWN UnknownOuter,
- _When_((PoolType & NonPagedPoolMustSucceed) != 0,
- __drv_reportError("Must succeed pool allocations are forbidden. "
- "Allocation failures cause a system crash"))
- _In_ POOL_TYPE PoolType,
- _In_ PUNKNOWN UnknownAdapter,
- _In_opt_ PVOID DeviceContext,
- _In_ PENDPOINT_MINIPAIR MiniportPair
-)
-/*++
-
-Routine Description:
-
- Creates a new topology miniport.
-
-Arguments:
-
- Unknown -
-
- RefclsId -
-
- UnknownOuter -
-
- PoolType -
-
- UnknownAdapter -
-
- DeviceContext -
-
- MiniportPair -
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(Unknown);
- ASSERT(MiniportPair);
-
- UNREFERENCED_PARAMETER(UnknownAdapter);
- UNREFERENCED_PARAMETER(DeviceContext);
-
- CCellularMiniportTopology *obj =
- new (PoolType, MINWAVERT_POOLTAG)
- CCellularMiniportTopology( UnknownOuter,
- MiniportPair->TopoDescriptor,
- MiniportPair->DeviceMaxChannels);
- if (NULL == obj)
- {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- obj->AddRef();
- *Unknown = reinterpret_cast<IUnknown*>(obj);
-
- return STATUS_SUCCESS;
-} // CreateCellularMiniportTopology
-
-CCellularMiniportTopology::CCellularMiniportTopology
-(
- _In_opt_ PUNKNOWN UnknownOuter,
- _In_ PCFILTER_DESCRIPTOR *FilterDesc,
- _In_ USHORT DeviceMaxChannels
-)
-: CUnknown(UnknownOuter),
- CMiniportTopologySYSVAD(FilterDesc, DeviceMaxChannels),
- m_CellularVolume(0)
-{
- PAGED_CODE();
-
- InitializeListHead(&m_EndpointPairs);
-
- // populate the initial state
- memcpy(&m_CellularRenderEndpoint, &(g_EndpointList[0].RenderEndpoint), sizeof(m_CellularRenderEndpoint));
- memcpy(&m_CellularCaptureEndpoint, &(g_EndpointList[0].CaptureEndpoint), sizeof(m_CellularCaptureEndpoint));
-}
-
-
-//=============================================================================
-CCellularMiniportTopology::~CCellularMiniportTopology
-(
- void
-)
-/*++
-
-Routine Description:
-
- Topology miniport destructor
-
-Arguments:
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- while (!IsListEmpty(&m_EndpointPairs))
- {
- PLIST_ENTRY le = RemoveHeadList(&m_EndpointPairs);
- ENDPOINT_PAIR_ENTRY *pRecord = CONTAINING_RECORD(le, ENDPOINT_PAIR_ENTRY, ListEntry);
- delete pRecord;
- }
-
- DPF_ENTER(("[CCellularMiniportTopology::~CCellularMiniportTopology]"));
-} // ~CCellularMiniportTopology
-
-//=============================================================================
-NTSTATUS
-CCellularMiniportTopology::DataRangeIntersection
-(
- _In_ ULONG PinId,
- _In_ PKSDATARANGE ClientDataRange,
- _In_ PKSDATARANGE MyDataRange,
- _In_ ULONG OutputBufferLength,
- _Out_writes_bytes_to_opt_(OutputBufferLength, *ResultantFormatLength)
- PVOID ResultantFormat OPTIONAL,
- _Out_ PULONG ResultantFormatLength
-)
-/*++
-
-Routine Description:
-
- The DataRangeIntersection function determines the highest quality
- intersection of two data ranges.
-
-Arguments:
-
- PinId - Pin for which data intersection is being determined.
-
- ClientDataRange - Pointer to KSDATARANGE structure which contains the data range
- submitted by client in the data range intersection property
- request.
-
- MyDataRange - Pin's data range to be compared with client's data range.
-
- OutputBufferLength - Size of the buffer pointed to by the resultant format
- parameter.
-
- ResultantFormat - Pointer to value where the resultant format should be
- returned.
-
- ResultantFormatLength - Actual length of the resultant format that is placed
- at ResultantFormat. This should be less than or equal
- to OutputBufferLength.
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- return
- CMiniportTopologySYSVAD::DataRangeIntersection
- (
- PinId,
- ClientDataRange,
- MyDataRange,
- OutputBufferLength,
- ResultantFormat,
- ResultantFormatLength
- );
-} // DataRangeIntersection
-
-//=============================================================================
-STDMETHODIMP
-CCellularMiniportTopology::GetDescription
-(
- _Out_ PPCFILTER_DESCRIPTOR * OutFilterDescriptor
-)
-/*++
-
-Routine Description:
-
- The GetDescription function gets a pointer to a filter description.
- It provides a location to deposit a pointer in miniport's description
- structure. This is the placeholder for the FromNode or ToNode fields in
- connections which describe connections to the filter's pins.
-
-Arguments:
-
- OutFilterDescriptor - Pointer to the filter description.
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(OutFilterDescriptor);
-
- return CMiniportTopologySYSVAD::GetDescription(OutFilterDescriptor);
-} // GetDescription
-
-//=============================================================================
-STDMETHODIMP
-CCellularMiniportTopology::Init
-(
- _In_ PUNKNOWN UnknownAdapter,
- _In_ PRESOURCELIST ResourceList,
- _In_ PPORTTOPOLOGY Port_
-)
-/*++
-
-Routine Description:
-
- The Init function initializes the miniport. Callers of this function
- should run at IRQL PASSIVE_LEVEL
-
-Arguments:
-
- UnknownAdapter - A pointer to the Iuknown interface of the adapter object.
-
- ResourceList - Pointer to the resource list to be supplied to the miniport
- during initialization. The port driver is free to examine the
- contents of the ResourceList. The port driver will not be
- modify the ResourceList contents.
-
- Port - Pointer to the topology port object that is linked with this miniport.
-
-Return Value:
-
- NT status code.
-
---*/
-{
- UNREFERENCED_PARAMETER(ResourceList);
-
- PAGED_CODE();
-
- ASSERT(UnknownAdapter);
- ASSERT(Port_);
-
- DPF_ENTER(("[CCellularMiniportTopology::Init]"));
-
- NTSTATUS ntStatus = STATUS_SUCCESS;
-
- ExInitializeFastMutex(&m_EndpointFastMutex);
-
- // copy the full static list over to the dynamic list.
- for (int i = 0; i < SIZEOF_ARRAY(g_EndpointList) && NT_SUCCESS(ntStatus); i++)
- {
- ENDPOINT_PAIR_ENTRY *newEntry = new(NonPagedPoolNx, MINADAPTER_POOLTAG) ENDPOINT_PAIR_ENTRY;
-
- if (!newEntry)
- {
- DPF(D_TERSE, ("Insufficient memory to create endpoint pair"));
- ntStatus = STATUS_INSUFFICIENT_RESOURCES;
- }
- else
- {
- memcpy(&(newEntry->data), &(g_EndpointList[i]), sizeof(KSTOPOLOGY_ENDPOINTIDPAIR));
- InsertTailList(&m_EndpointPairs, &newEntry->ListEntry);
- }
- }
-
- if (NT_SUCCESS(ntStatus))
- {
- ntStatus =
- CMiniportTopologySYSVAD::Init
- (
- UnknownAdapter,
- Port_
- );
- }
-
- return ntStatus;
-} // Init
-
-//=============================================================================
-STDMETHODIMP
-CCellularMiniportTopology::NonDelegatingQueryInterface
-(
- _In_ REFIID Interface,
- _COM_Outptr_ PVOID * Object
-)
-/*++
-
-Routine Description:
-
- QueryInterface for MiniportTopology
-
-Arguments:
-
- Interface - GUID of the interface
-
- Object - interface object to be returned.
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(Object);
-
- if (IsEqualGUIDAligned(Interface, IID_IUnknown))
- {
- *Object = PVOID(PUNKNOWN(static_cast<IMiniportTopology*>( this )));
- }
- else if (IsEqualGUIDAligned(Interface, IID_IMiniport))
- {
- *Object = PVOID(PMINIPORT(this));
- }
- else if (IsEqualGUIDAligned(Interface, IID_IMiniportTopology))
- {
- *Object = PVOID(PMINIPORTTOPOLOGY(this));
- }
- else if (IsEqualGUIDAligned(Interface, IID_ICellularTopology))
- {
- *Object = PVOID(PCELLULARTOPOLOGY(this));
- }
- else if (IsEqualGUIDAligned(Interface, IID_IMiniportChange))
- {
- *Object = PVOID(static_cast<PMINIPORTCHANGE>( this ));
- }
- else
- {
- *Object = NULL;
- }
-
- if (*Object)
- {
- // We reference the interface for the caller.
- PUNKNOWN(*Object)->AddRef();
- return(STATUS_SUCCESS);
- }
-
- return(STATUS_INVALID_PARAMETER);
-} // NonDelegatingQueryInterface
-
-//=============================================================================
-NTSTATUS
-CCellularMiniportTopology::PropertyHandlerJackDescription
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
- Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION )
-
-Arguments:
-
- PropertyRequest
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandlerJackDescription]"));
-
- ULONG cJackDescriptions = ARRAYSIZE(CellularJackDescriptions);
- PKSJACK_DESCRIPTION * JackDescriptions = CellularJackDescriptions;
-
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
- ULONG nPinId = (ULONG)-1;
-
- if (PropertyRequest->InstanceSize >= sizeof(ULONG))
- {
- nPinId = *(PULONG(PropertyRequest->Instance));
-
- if ((nPinId < cJackDescriptions) && (JackDescriptions[nPinId] != NULL))
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ntStatus =
- PropertyHandler_BasicSupport
- (
- PropertyRequest,
- KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET,
- VT_ILLEGAL
- );
- }
- else
- {
- ULONG cbNeeded = sizeof(KSMULTIPLE_ITEM) + sizeof(KSJACK_DESCRIPTION);
-
- if (PropertyRequest->ValueSize == 0)
- {
- PropertyRequest->ValueSize = cbNeeded;
- ntStatus = STATUS_BUFFER_OVERFLOW;
- }
- else if (PropertyRequest->ValueSize < cbNeeded)
- {
- ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value;
- PKSJACK_DESCRIPTION pDesc = (PKSJACK_DESCRIPTION)(pMI+1);
-
- pMI->Size = cbNeeded;
- pMI->Count = 1;
-
- RtlCopyMemory(pDesc, JackDescriptions[nPinId], sizeof(KSJACK_DESCRIPTION));
- ntStatus = STATUS_SUCCESS;
- }
- }
- }
- }
- }
-
- return ntStatus;
-}
-
-//=============================================================================
-NTSTATUS
-CCellularMiniportTopology::PropertyHandlerJackDescription2
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
- Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION2 )
-
-Arguments:
-
- PropertyRequest -
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandlerJackDescription2]"));
-
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
- ULONG nPinId = (ULONG)-1;
-
- ULONG cJackDescriptions = ARRAYSIZE(CellularJackDescriptions);
- PKSJACK_DESCRIPTION * JackDescriptions = CellularJackDescriptions;
-
- if (PropertyRequest->InstanceSize >= sizeof(ULONG))
- {
- nPinId = *(PULONG(PropertyRequest->Instance));
-
- if ((nPinId < cJackDescriptions) && (JackDescriptions[nPinId] != NULL))
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ntStatus =
- PropertyHandler_BasicSupport
- (
- PropertyRequest,
- KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET,
- VT_ILLEGAL
- );
- }
- else
- {
- ULONG cbNeeded = sizeof(KSMULTIPLE_ITEM) + sizeof(KSJACK_DESCRIPTION2);
-
- if (PropertyRequest->ValueSize == 0)
- {
- PropertyRequest->ValueSize = cbNeeded;
- ntStatus = STATUS_BUFFER_OVERFLOW;
- }
- else if (PropertyRequest->ValueSize < cbNeeded)
- {
- ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value;
- PKSJACK_DESCRIPTION2 pDesc = (PKSJACK_DESCRIPTION2)(pMI+1);
-
- pMI->Size = cbNeeded;
- pMI->Count = 1;
-
- RtlZeroMemory(pDesc, sizeof(KSJACK_DESCRIPTION2));
-
- //
- // Specifies the lower 16 bits of the DWORD parameter. This parameter indicates whether
- // the jack is currently active, streaming, idle, or hardware not ready.
- //
- pDesc->DeviceStateInfo = 0;
-
- //
- // From MSDN:
- // "If an audio device lacks jack presence detection, the IsConnected member of
- // the KSJACK_DESCRIPTION structure must always be set to TRUE. To remove the
- // ambiguity that results from this dual meaning of the TRUE value for IsConnected,
- // a client application can call IKsJackDescription2::GetJackDescription2 to read
- // the JackCapabilities flag of the KSJACK_DESCRIPTION2 structure. If this flag has
- // the JACKDESC2_PRESENCE_DETECT_CAPABILITY bit set, it indicates that the endpoint
- // does in fact support jack presence detection. In that case, the return value of
- // the IsConnected member can be interpreted to accurately reflect the insertion status
- // of the jack."
- //
- // Bit definitions:
- // 0x00000001 - JACKDESC2_PRESENCE_DETECT_CAPABILITY
- // 0x00000002 - JACKDESC2_DYNAMIC_FORMAT_CHANGE_CAPABILITY
- //
- pDesc->JackCapabilities = JACKDESC2_PRESENCE_DETECT_CAPABILITY;
-
- ntStatus = STATUS_SUCCESS;
- }
- }
- }
- }
- }
-
- return ntStatus;
-}
-
-//=============================================================================
-NTSTATUS
-CCellularMiniportTopology::PropertyHandlerTelephonyEndpointIdPair
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
- Handles ( KSPROPSETID_TelephonyTopology, KSPROPERTY_TELEPHONY_ENDPOINTIDPAIR )
-
-Arguments:
-
- PropertyRequest -
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandlerTelephonyEndpointIdPair]"));
-
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
-
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ntStatus = STATUS_INVALID_PARAMETER;
- ULONG ulExpectedSize = (sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER));
-
- PLIST_ENTRY le = NULL;
- int countOfValidEndpointPairs = 0;
-
- ExAcquireFastMutex(&m_EndpointFastMutex);
-
- for (le = m_EndpointPairs.Flink; le != &m_EndpointPairs; le = le->Flink)
- {
- countOfValidEndpointPairs++;
- }
- ulExpectedSize += (countOfValidEndpointPairs * sizeof(KSTOPOLOGY_ENDPOINTIDPAIR));
-
- if (PropertyRequest->ValueSize >= sizeof(KSPROPERTY_DESCRIPTION))
- {
- // if return buffer can hold a KSPROPERTY_DESCRIPTION, return it
- //
- PKSPROPERTY_DESCRIPTION PropDesc =
- PKSPROPERTY_DESCRIPTION(PropertyRequest->Value);
-
- PropDesc->AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_SET |KSPROPERTY_TYPE_GET;
- PropDesc->DescriptionSize = ulExpectedSize;
- PropDesc->PropTypeSet.Set = KSPROPSETID_TelephonyTopology;
- PropDesc->PropTypeSet.Id = KSPROPERTY_TELEPHONY_ENDPOINTIDPAIR;
- PropDesc->MembersListCount = 0;
- PropDesc->PropTypeSet.Flags = 0;
- PropDesc->Reserved = 0;
-
- // buffer is big enough to hold the full data, add that
- if (PropertyRequest->ValueSize >= ulExpectedSize)
- {
- PKSPROPERTY_MEMBERSHEADER MembersHeader =
- PKSPROPERTY_MEMBERSHEADER(PropDesc + 1);
-
- // we're now adding the members header.
- PropDesc->MembersListCount = 1;
-
- MembersHeader->MembersFlags = KSPROPERTY_MEMBER_VALUES;
- MembersHeader->MembersSize = sizeof(KSTOPOLOGY_ENDPOINTIDPAIR);
- MembersHeader->MembersCount = countOfValidEndpointPairs;
- MembersHeader->Flags = 0;
-
- le = NULL;
- PKSTOPOLOGY_ENDPOINTIDPAIR returnData = (PKSTOPOLOGY_ENDPOINTIDPAIR) (MembersHeader + 1);
-
- for (le = m_EndpointPairs.Flink; le != &m_EndpointPairs; le = le->Flink)
- {
- ENDPOINT_PAIR_ENTRY *pRecord = CONTAINING_RECORD(le, ENDPOINT_PAIR_ENTRY, ListEntry);
- memcpy(returnData, &(pRecord->data), sizeof(pRecord->data));
- returnData++;
- }
-
- // tell them how much space we really used, which controls how much data is copied into the user buffer.
- PropertyRequest->ValueSize = ulExpectedSize;
- }
- else
- {
- // tell them how much space we really used, which controls how much data is copied into the user buffer.
- PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION);
- }
-
- ntStatus = STATUS_SUCCESS;
- }
- else if (PropertyRequest->ValueSize >= sizeof(ULONG))
- {
- // if return buffer can hold a ULONG, return the access flags.
- *(PULONG(PropertyRequest->Value)) = KSPROPERTY_TYPE_SET |KSPROPERTY_TYPE_GET;
- PropertyRequest->ValueSize = sizeof(ULONG);
- ntStatus = STATUS_SUCCESS;
- }
- else if (PropertyRequest->ValueSize == 0)
- {
- PropertyRequest->ValueSize = ulExpectedSize;
- ntStatus = STATUS_BUFFER_OVERFLOW;
- }
- else
- {
- ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
-
- ExReleaseFastMutex(&m_EndpointFastMutex);
- }
- else
- {
- ULONG cbNeeded = sizeof(KSTOPOLOGY_ENDPOINTIDPAIR);
-
- if (PropertyRequest->ValueSize == 0)
- {
- PropertyRequest->ValueSize = cbNeeded;
- ntStatus = STATUS_BUFFER_OVERFLOW;
- }
- else if (PropertyRequest->ValueSize < cbNeeded)
- {
- ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- PKSTOPOLOGY_ENDPOINTIDPAIR EndpointIdPair = static_cast<PKSTOPOLOGY_ENDPOINTIDPAIR>(PropertyRequest->Value);
-
- // Return endpoints (render and capture) info where cellular audio is being routed to.
- memcpy(&(EndpointIdPair->RenderEndpoint), &m_CellularRenderEndpoint, sizeof(m_CellularRenderEndpoint));
- memcpy(&(EndpointIdPair->CaptureEndpoint), &m_CellularCaptureEndpoint, sizeof(m_CellularCaptureEndpoint));
-
- ntStatus = STATUS_SUCCESS;
- }
- else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
- {
- PKSTOPOLOGY_ENDPOINTIDPAIR EndpointIdPair = static_cast<PKSTOPOLOGY_ENDPOINTIDPAIR>(PropertyRequest->Value);
- PLIST_ENTRY le = NULL;
-
- // verify the requested combination is in the list of valid endpoint combinations, fail with
- // invalid parameter if not found.
- ntStatus = STATUS_INVALID_PARAMETER;
-
- ExAcquireFastMutex(&m_EndpointFastMutex);
-
- for (le = m_EndpointPairs.Flink; le != &m_EndpointPairs; le = le->Flink)
- {
- ENDPOINT_PAIR_ENTRY *pRecord = CONTAINING_RECORD(le, ENDPOINT_PAIR_ENTRY, ListEntry);
-
- if (pRecord->data.RenderEndpoint.PinId == EndpointIdPair->RenderEndpoint.PinId &&
- 0 == _wcsnicmp(pRecord->data.RenderEndpoint.TopologyName, EndpointIdPair->RenderEndpoint.TopologyName, MAX_PATH) &&
- pRecord->data.CaptureEndpoint.PinId == EndpointIdPair->CaptureEndpoint.PinId &&
- 0 == _wcsnicmp(pRecord->data.CaptureEndpoint.TopologyName, EndpointIdPair->CaptureEndpoint.TopologyName, MAX_PATH))
- {
- if (HOSTRENDER_PIN == EndpointIdPair->RenderEndpoint.PinId &&
- 0 == _wcsnicmp(HOSTRENDER_TOPONAME, EndpointIdPair->RenderEndpoint.TopologyName, MAX_PATH) &&
- HOSTCAPTURE_PIN == EndpointIdPair->CaptureEndpoint.PinId &&
- 0 == _wcsnicmp(HOSTCAPTURE_TOPONAME, EndpointIdPair->CaptureEndpoint.TopologyName, MAX_PATH))
- {
- // This is an indication that cellular audio is being routed through OS (For example, user plugs in USB headset
- // for cellular audio) and driver must stop rendering cellular audio to any physical audio endpoint. Driver must
- // also stop capturing data from any physical audio endpoint for cellular. This will update audio routing for
- // all the active cellular calls.
- }
- else
- {
- // Route cellular audio to these new endpoints (render and capture). This will update audio routing for
- // all the active cellular calls.
- }
-
- memcpy(&m_CellularRenderEndpoint, &(EndpointIdPair->RenderEndpoint), sizeof(m_CellularRenderEndpoint));
- memcpy(&m_CellularCaptureEndpoint, &(EndpointIdPair->CaptureEndpoint), sizeof(m_CellularCaptureEndpoint));
-
- // we found the entry, so return success
- ntStatus = STATUS_SUCCESS;
- break;
- }
- }
-
- ExReleaseFastMutex(&m_EndpointFastMutex);
- }
- else
- {
- ntStatus = STATUS_INVALID_PARAMETER;
- }
- }
- }
-
- return ntStatus;
-}
-
-//=============================================================================
-NTSTATUS
-CCellularMiniportTopology::PropertyHandlerTelephonyVolume
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
- Handles ( KSPROPSETID_TelephonyTopology, KSPROPERTY_TELEPHONY_VOLUME )
-
-Arguments:
-
- PropertyRequest -
-
-Return Value:
-
- NT status code.
-
---*/
-{
-
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandlerTelephonyVolume]"));
-
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
-
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ntStatus =
- PropertyHandler_BasicSupportVolume
- (
- PropertyRequest,
- 1 // Telephony audio is only ever 1 channel
- );
-
- ULONG cbFullProperty =
- sizeof(KSPROPERTY_DESCRIPTION) +
- sizeof(KSPROPERTY_MEMBERSHEADER) +
- sizeof(KSPROPERTY_STEPPING_LONG);
-
- if (NT_SUCCESS(ntStatus) && PropertyRequest->ValueSize >= cbFullProperty)
- {
- // Access proper values
- PKSPROPERTY_DESCRIPTION PropDesc =
- PKSPROPERTY_DESCRIPTION(PropertyRequest->Value);
- PKSPROPERTY_MEMBERSHEADER Members =
- PKSPROPERTY_MEMBERSHEADER(PropDesc + 1);
- PKSPROPERTY_STEPPING_LONG Range =
- PKSPROPERTY_STEPPING_LONG(Members + 1);
-
- // Telephony volume is only ever single channel, so the
- // MULTICHANNEL and UNIFORM flags are meaningless
- Members->Flags = 0;
-
- // Telephony Values that may be different from standard volume values
- Range->Bounds.SignedMaximum = TELEPHONY_VOLUME_MAXIMUM;
- Range->Bounds.SignedMinimum = TELEPHONY_VOLUME_MINIMUM;
- Range->SteppingDelta = TELEPHONY_VOLUME_STEPPING;
- }
- }
- else
- {
- ntStatus =
- ValidatePropertyParams
- (
- PropertyRequest,
- sizeof(LONG), // volume value is a LONG
- 0 // there is no channel associated with telephony volume
- );
-
-
- if (NT_SUCCESS(ntStatus))
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- LONG* volume = (LONG*)PropertyRequest->Value;
- // Return current cellular volume (Incall volume).
- *volume = m_CellularVolume;
- PropertyRequest->ValueSize = sizeof(LONG);
- ntStatus = STATUS_SUCCESS;
- }
- else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
- {
- LONG* volume = (LONG*)PropertyRequest->Value;
-
- LONG normalizedVolume =
- VALUE_NORMALIZE_IN_RANGE_EX
- (
- *volume,
- TELEPHONY_VOLUME_MINIMUM,
- TELEPHONY_VOLUME_MAXIMUM,
- TELEPHONY_VOLUME_STEPPING
- );
- if (normalizedVolume == *volume)
- {
- // Update the cellular volume (Incall volume). This will update cellular volume for all the active cellular calls.
- m_CellularVolume = *volume;
- ntStatus = STATUS_SUCCESS;
- }
- else
- {
- ntStatus = STATUS_INVALID_PARAMETER;
- }
- }
- else
- {
- ntStatus = STATUS_INVALID_PARAMETER;
- }
- }
- }
-
- return ntStatus;
-}
-
-//=============================================================================
-NTSTATUS
-PropertyHandler_CellularTopoFilter
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
- Redirects property request to miniport object
-
-Arguments:
-
- PropertyRequest -
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandler_CellularTopoFilter]"));
-
- // PropertryRequest structure is filled by portcls.
- // MajorTarget is a pointer to miniport object for miniports.
- //
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
- PCCellularMiniportTopology pMiniport = reinterpret_cast<PCCellularMiniportTopology>(PropertyRequest->MajorTarget);
-
- if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Jack))
- {
- if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION)
- {
- ntStatus = pMiniport->PropertyHandlerJackDescription(PropertyRequest);
- }
- else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION2)
- {
- ntStatus = pMiniport->PropertyHandlerJackDescription2(PropertyRequest);
- }
- }
- else if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_TelephonyTopology))
- {
- if (PropertyRequest->PropertyItem->Id == KSPROPERTY_TELEPHONY_ENDPOINTIDPAIR)
- {
- ntStatus = pMiniport->PropertyHandlerTelephonyEndpointIdPair(PropertyRequest);
- }
- else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_TELEPHONY_VOLUME)
- {
- ntStatus = pMiniport->PropertyHandlerTelephonyVolume(PropertyRequest);
- }
- }
-
- return ntStatus;
-} // PropertyHandler_CellularTopoFilter
-
-#pragma code_seg("PAGE")
-STDMETHODIMP_(NTSTATUS)
-CCellularMiniportTopology::UpdateTopologyJackState
-(
- _In_ ULONG TelephonyId,
- _In_ BOOL NewState
-)
-{
- PAGED_CODE ();
-
- struct JackState
- {
- ULONG TelephonyId;
- ULONG PinId;
- PKSJACK_DESCRIPTION JackControl;
- };
-
- JackState Jacks[] =
- {
- {
- 0,
- KSPIN_TOPO_BIDI1,
- &CellularJackDesc
- },
- {
- 1,
- KSPIN_TOPO_BIDI2,
- &CellularJackDesc2
- }
- };
-
- // Query the registry and update the jack state for all of the pins.
- for (int i = 0; i < SIZEOF_ARRAY(Jacks); i++)
- {
- if (Jacks[i].TelephonyId == TelephonyId)
- {
- Jacks[i].JackControl->IsConnected = NewState;
-
- // we have multiple pins which share the same jack state,
- // notify for every pin using that jack state
- GenerateEventList(
- (GUID*)&KSEVENTSETID_PinCapsChange, // event set. NULL is a wild card for all events.
- KSEVENT_PINCAPS_JACKINFOCHANGE, // event ID.
- TRUE, // use pid ID.
- Jacks[i].PinId, // pin ID.
- FALSE, // do not use node ID.
- ULONG(-1)); // node ID, not used.
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-#pragma code_seg()
-NTSTATUS CCellularMiniportWaveRT_EventHandler_JackState
-(
- _In_ PPCEVENT_REQUEST EventRequest
-)
-{
- CCellularMiniportTopology* miniport = reinterpret_cast<CCellularMiniportTopology*>(EventRequest->MajorTarget);
- return miniport->EventHandler_JackState(EventRequest);
-}
-
-NTSTATUS CCellularMiniportTopology::EventHandler_JackState
-(
- _In_ PPCEVENT_REQUEST EventRequest
-)
-{
- if (EventRequest->Verb == PCEVENT_VERB_ADD)
- {
- m_PortEvents->AddEventToEventList(EventRequest->EventEntry);
- }
-
- return STATUS_SUCCESS;
-}
-
-#pragma code_seg("PAGE")
-STDMETHODIMP_(NTSTATUS)
-CCellularMiniportTopology::NotifyEndpointPair
-(
- _In_ WCHAR *RenderEndpointTopoName,
- _In_ ULONG RenderEndpointNameLen,
- _In_ ULONG RenderPinId,
- _In_ WCHAR *CaptureEndpointTopoName,
- _In_ ULONG CaptureEndpointNameLen,
- _In_ ULONG CapturePinId
-)
-{
- PAGED_CODE ();
-
- NTSTATUS ntStatus = STATUS_SUCCESS;
-
- ENDPOINT_PAIR_ENTRY *newEntry = new(NonPagedPoolNx, MINADAPTER_POOLTAG) ENDPOINT_PAIR_ENTRY;
-
- if (!newEntry)
- {
- DPF(D_TERSE, ("Insufficient memory to create endpoint pair"));
- ntStatus = STATUS_INSUFFICIENT_RESOURCES;
- }
-
- if (NT_SUCCESS(ntStatus))
- {
- KSTOPOLOGY_ENDPOINTIDPAIR *endpointPair = &newEntry->data;
-
- RtlStringCchCopyNW(endpointPair->RenderEndpoint.TopologyName,
- SIZEOF_ARRAY(endpointPair->RenderEndpoint.TopologyName),
- RenderEndpointTopoName,
- RenderEndpointNameLen);
- endpointPair->RenderEndpoint.PinId = RenderPinId;
-
- RtlStringCchCopyNW(endpointPair->CaptureEndpoint.TopologyName,
- SIZEOF_ARRAY(endpointPair->CaptureEndpoint.TopologyName),
- CaptureEndpointTopoName,
- CaptureEndpointNameLen);
- endpointPair->CaptureEndpoint.PinId = CapturePinId;
-
- ExAcquireFastMutex(&m_EndpointFastMutex);
- InsertTailList(&m_EndpointPairs, &newEntry->ListEntry);
- ExReleaseFastMutex(&m_EndpointFastMutex);
-
- GenerateEventList(
- (GUID*)&KSEVENTSETID_Telephony,
- KSEVENT_TELEPHONY_ENDPOINTPAIRS_CHANGED,
- FALSE,
- NULL,
- FALSE,
- ULONG(-1));
- }
-
- return ntStatus;
-}
-
-#pragma code_seg()
-NTSTATUS CCellularMiniportWaveRT_EventHandler_Telephony
-(
- _In_ PPCEVENT_REQUEST EventRequest
-)
-{
- CCellularMiniportTopology* miniport = reinterpret_cast<CCellularMiniportTopology*>(EventRequest->MajorTarget);
- return miniport->EventHandler_Telephony(EventRequest);
-}
-
-NTSTATUS CCellularMiniportTopology::EventHandler_Telephony
-(
- _In_ PPCEVENT_REQUEST EventRequest
-)
-{
- if (EventRequest->Verb == PCEVENT_VERB_ADD)
- {
- m_PortEvents->AddEventToEventList(EventRequest->EventEntry);
- }
-
- return STATUS_SUCCESS;
-}
-
-
diff --git a/audio/sysvad/PhoneAudioSample/Cellulartopo.h b/audio/sysvad/PhoneAudioSample/Cellulartopo.h
deleted file mode 100644
index b898741c..00000000
--- a/audio/sysvad/PhoneAudioSample/Cellulartopo.h
+++ /dev/null
@@ -1,184 +0,0 @@
-
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- cellulartopo.h
-
-Abstract:
-
- Declaration of topology miniport for the cellular endpoint.
-
---*/
-
-#ifndef _SYSVAD_CELLULARTOPO_H_
-#define _SYSVAD_CELLULARTOPO_H_
-
-#include "basetopo.h"
-
-// make sure all of these names matches with KSNAME_* in the inf's [Strings] section
-#define SPEAKER_TOPONAME L"TopologySpeaker"
-#define SPEAKER_HEADSET_TOPONAME L"TopologySpeakerHeadset"
-#define MIC_HEADSET_TOPONAME L"TopologyMicHeadset"
-#define MIC_ARRAY1_TOPONAME L"TopologyMicArray1"
-#define HANDSET_SPEAKER_TOPONAME L"TopologyHandsetSpeaker"
-#define HANDSET_MIC_TOPONAME L"TopologyHandsetMic"
-
-// from bthhfpminipairs.h, static name of bluetooth speaker and mic topologies
-#define HFP_SPEAKER_TOPONAME L"TopologyBthHfpSpeaker"
-#define HFP_MIC_TOPONAME L"TopologyBthHfpMic"
-
-// Special routing endpoints
-#define HOSTRENDER_TOPONAME L"HostRender"
-#define HOSTRENDER_PIN 0
-#define HOSTCAPTURE_TOPONAME L"HostCapture"
-#define HOSTCAPTURE_PIN 0
-
-// Telephony Volume Stepping information
-#define TELEPHONY_VOLUME_MAXIMUM 0 // 0 dB
-#define TELEPHONY_VOLUME_MINIMUM (-30 * 0x10000) // -30 dB
-#define TELEPHONY_VOLUME_STEPPING (3 * 0x10000) // 10 steps
-
-
-typedef struct _ENDPOINT_PAIR_ENTRY
-{
- LIST_ENTRY ListEntry;
- KSTOPOLOGY_ENDPOINTIDPAIR data;
-} ENDPOINT_PAIR_ENTRY;
-
-//=============================================================================
-// Defines
-//=============================================================================
-// {3829F9C3-F341-4B82-976F-A635EB3CEA0D}
-DEFINE_GUID(IID_ICellularTopology,
-0x3829f9c3, 0xf341, 0x4b82, 0x97, 0x6f, 0xa6, 0x35, 0xeb, 0x3c, 0xea, 0xd);
-
-
-//=============================================================================
-// Interfaces
-//=============================================================================
-
-///////////////////////////////////////////////////////////////////////////////
-// ICellularTopology
-//
-DECLARE_INTERFACE_(ICellularTopology, IMiniportTopology)
-{
- STDMETHOD_(NTSTATUS, UpdateTopologyJackState)
- (
- THIS_
- _In_ ULONG TelephonyId,
- _In_ BOOL NewState
- ) PURE;
-};
-
-typedef ICellularTopology *PCELLULARTOPOLOGY;
-
-//=============================================================================
-// Classes
-//=============================================================================
-
-///////////////////////////////////////////////////////////////////////////////
-// CCellularMiniportTopology
-//
-
-class CCellularMiniportTopology :
- public CMiniportTopologySYSVAD,
- public ICellularTopology,
- public IMiniportChange,
- public CUnknown
-{
- private:
- KSTOPOLOGY_ENDPOINTID m_CellularRenderEndpoint;
- KSTOPOLOGY_ENDPOINTID m_CellularCaptureEndpoint;
- ULONG m_CellularVolume;
-
- FAST_MUTEX m_EndpointFastMutex;
- LIST_ENTRY m_EndpointPairs;
-
- public:
- DECLARE_STD_UNKNOWN();
- CCellularMiniportTopology
- (
- _In_opt_ PUNKNOWN UnknownOuter,
- _In_ PCFILTER_DESCRIPTOR *FilterDesc,
- _In_ USHORT DeviceMaxChannels
- );
-
- ~CCellularMiniportTopology();
-
- IMP_IMiniportTopology;
-
- NTSTATUS PropertyHandlerJackSinkInfo
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
- NTSTATUS PropertyHandlerJackDescription
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
- NTSTATUS PropertyHandlerJackDescription2
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
- NTSTATUS PropertyHandlerTelephonyEndpointIdPair
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
- NTSTATUS PropertyHandlerTelephonyVolume
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
- NTSTATUS EventHandler_JackState
- (
- _In_ PPCEVENT_REQUEST _pEventRequest
- );
-
- STDMETHODIMP_(NTSTATUS) UpdateTopologyJackState
- (
- _In_ ULONG TelephonyId,
- _In_ BOOL NewState
- );
-
- NTSTATUS EventHandler_Telephony
- (
- _In_ PPCEVENT_REQUEST _pEventRequest
- );
-
- STDMETHODIMP_(NTSTATUS) NotifyEndpointPair
- (
- _In_ WCHAR *RenderEndpointTopoName,
- _In_ ULONG RenderEndpointNameLen,
- _In_ ULONG RenderPinId,
- _In_ WCHAR *CaptureEndpointTopoName,
- _In_ ULONG CaptureEndpointNameLen,
- _In_ ULONG CapturePinId
- );
-};
-
-typedef CCellularMiniportTopology *PCCellularMiniportTopology;
-
-NTSTATUS
-CreateCellularMiniportTopology(
- _Out_ PUNKNOWN * Unknown,
- _In_ REFCLSID,
- _In_opt_ PUNKNOWN UnknownOuter,
- _When_((PoolType & NonPagedPoolMustSucceed) != 0,
- __drv_reportError("Must succeed pool allocations are forbidden. "
- "Allocation failures cause a system crash"))
- _In_ POOL_TYPE PoolType,
- _In_ PUNKNOWN UnknownAdapter,
- _In_opt_ PVOID DeviceContext,
- _In_ PENDPOINT_MINIPAIR MiniportPair
- );
-
-NTSTATUS PropertyHandler_CellularTopoFilter(_In_ PPCPROPERTY_REQUEST PropertyRequest);
-
-#endif // _SYSVAD_CELLULARTOPO_H_
-
diff --git a/audio/sysvad/PhoneAudioSample/Cellulartoptable.h b/audio/sysvad/PhoneAudioSample/Cellulartoptable.h
deleted file mode 100644
index 53eef9ae..00000000
--- a/audio/sysvad/PhoneAudioSample/Cellulartoptable.h
+++ /dev/null
@@ -1,267 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- cellulartoptable.h
-
-Abstract:
-
- Declaration of topology tables for the cellular endpoint.
-
---*/
-
-#ifndef _SYSVAD_CELLULARTOPTABLE_H_
-#define _SYSVAD_CELLULARTOPTABLE_H_
-
-// {896BC350-BF57-4039-A6B6-64DCEC3AEEB8}
-DEFINE_GUID(CELLULARBIDI1_CUSTOM_NAME,
-0x896bc350, 0xbf57, 0x4039, 0xa6, 0xb6, 0x64, 0xdc, 0xec, 0x3a, 0xee, 0xb8);
-
-// {80CC64DA-166A-4A2C-ADF7-1464C49D3B0E}
-DEFINE_GUID(CELLULARBIDI2_CUSTOM_NAME,
-0x80cc64da, 0x166a, 0x4a2c, 0xad, 0xf7, 0x14, 0x64, 0xc4, 0x9d, 0x3b, 0xe);
-
-//=============================================================================
-static
-KSDATARANGE CellularTopoPinDataRangesBridge[] =
-{
- {
- sizeof(KSDATARANGE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
- }
-};
-
-//=============================================================================
-static
-PKSDATARANGE CellularTopoPinDataRangePointersBridge[] =
-{
- &CellularTopoPinDataRangesBridge[0]
-};
-
-//=============================================================================
-static
-PCPIN_DESCRIPTOR CellularTopoMiniportPins[] =
-{
- // KSPIN_TOPO_BIDI1
- {
- 0,
- 0,
- 0, // InstanceCount
- NULL, // AutomationTable
- { // KsPinDescriptor
- 0, // InterfacesCount
- NULL, // Interfaces
- 0, // MediumsCount
- NULL, // Mediums
- SIZEOF_ARRAY(CellularTopoPinDataRangePointersBridge), // DataRangesCount
- CellularTopoPinDataRangePointersBridge, // DataRanges
- KSPIN_DATAFLOW_IN, // DataFlow
- KSPIN_COMMUNICATION_NONE, // Communication
- &KSNODETYPE_TELEPHONY_BIDI, // Category
- &CELLULARBIDI1_CUSTOM_NAME, // Name
- 0 // Reserved
- }
- },
- // KSPIN_TOPO_BIDI1_BRIDGE
- {
- 0,
- 0,
- 0, // InstanceCount
- NULL, // AutomationTable
- { // KsPinDescriptor
- 0, // InterfacesCount
- NULL, // Interfaces
- 0, // MediumsCount
- NULL, // Mediums
- SIZEOF_ARRAY(CellularTopoPinDataRangePointersBridge), // DataRangesCount
- CellularTopoPinDataRangePointersBridge, // DataRanges
- KSPIN_DATAFLOW_OUT, // DataFlow
- KSPIN_COMMUNICATION_NONE, // Communication
- &KSCATEGORY_AUDIO, // Category
- NULL, // Name
- 0 // Reserved
- }
- },
- // KSPIN_TOPO_BIDI2
- {
- 0,
- 0,
- 0, // InstanceCount
- NULL, // AutomationTable
- { // KsPinDescriptor
- 0, // InterfacesCount
- NULL, // Interfaces
- 0, // MediumsCount
- NULL, // Mediums
- SIZEOF_ARRAY(CellularTopoPinDataRangePointersBridge), // DataRangesCount
- CellularTopoPinDataRangePointersBridge, // DataRanges
- KSPIN_DATAFLOW_IN, // DataFlow
- KSPIN_COMMUNICATION_NONE, // Communication
- &KSNODETYPE_TELEPHONY_BIDI, // Category
- &CELLULARBIDI2_CUSTOM_NAME, // Name
- 0 // Reserved
- }
- },
- // KSPIN_TOPO_BIDI2_BRIDGE
- {
- 0,
- 0,
- 0, // InstanceCount
- NULL, // AutomationTable
- { // KsPinDescriptor
- 0, // InterfacesCount
- NULL, // Interfaces
- 0, // MediumsCount
- NULL, // Mediums
- SIZEOF_ARRAY(CellularTopoPinDataRangePointersBridge), // DataRangesCount
- CellularTopoPinDataRangePointersBridge, // DataRanges
- KSPIN_DATAFLOW_OUT, // DataFlow
- KSPIN_COMMUNICATION_NONE, // Communication
- &KSCATEGORY_AUDIO, // Category
- NULL, // Name
- 0 // Reserved
- }
- }
-};
-
-//=============================================================================
-static
-KSJACK_DESCRIPTION CellularJackDesc =
-{
- KSAUDIO_SPEAKER_MONO,
- 0x0000, // no color
- eConnTypeUnknown,
- eGeoLocNotApplicable,
- eGenLocInternal,
- ePortConnUnknown,
- TRUE // NOTE: cellular jacks should be "unplugged" at boot, and only changed to active during a call.
- // However, for convienience during development, the jack state is set to active at boot for this milestone.
-};
-
-static
-KSJACK_DESCRIPTION CellularJackDesc2 =
-{
- KSAUDIO_SPEAKER_MONO,
- 0x0000, // no color
- eConnTypeUnknown,
- eGeoLocNotApplicable,
- eGenLocInternal,
- ePortConnUnknown,
- TRUE // NOTE: cellular jacks should be "unplugged" at boot, and only changed to active during a call.
- // However, for convienience during development, the jack state is set to active at boot for this milestone.
-};
-
-
-// Only return a KSJACK_DESCRIPTION for the physical bridge pin.
-static
-PKSJACK_DESCRIPTION CellularJackDescriptions[] =
-{
- &CellularJackDesc,
- NULL,
- &CellularJackDesc2,
- NULL
-};
-
-//=============================================================================
-static
-PCCONNECTION_DESCRIPTOR CellularTopoMiniportConnections[] =
-{
- // FromNode, FromPin, ToNode, ToPin
- { PCFILTER_NODE, KSPIN_TOPO_BIDI1, PCFILTER_NODE, KSPIN_TOPO_BIDI1_BRIDGE},
- { PCFILTER_NODE, KSPIN_TOPO_BIDI2, PCFILTER_NODE, KSPIN_TOPO_BIDI2_BRIDGE}
-};
-
-
-//=============================================================================
-static
-PCPROPERTY_ITEM PropertiesCellularTopoFilter[] =
-{
- {
- &KSPROPSETID_Jack,
- KSPROPERTY_JACK_DESCRIPTION,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_CellularTopoFilter
- },
- {
- &KSPROPSETID_Jack,
- KSPROPERTY_JACK_DESCRIPTION2,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_CellularTopoFilter
- },
- {
- &KSPROPSETID_TelephonyTopology,
- KSPROPERTY_TELEPHONY_ENDPOINTIDPAIR,
- KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_CellularTopoFilter
- },
- {
- &KSPROPSETID_TelephonyTopology,
- KSPROPERTY_TELEPHONY_VOLUME,
- KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_CellularTopoFilter
- }
-};
-
-NTSTATUS CCellularMiniportWaveRT_EventHandler_JackState
-(
- _In_ PPCEVENT_REQUEST EventRequest
-);
-
-NTSTATUS CCellularMiniportWaveRT_EventHandler_Telephony
-(
- _In_ PPCEVENT_REQUEST EventRequest
-);
-
-
-static PCEVENT_ITEM TelephonyEvents[] =
-{
- {
- &KSEVENTSETID_PinCapsChange, // Something changed
- KSEVENT_PINCAPS_JACKINFOCHANGE, // Jack Info Changes
- KSEVENT_TYPE_ENABLE | KSEVENT_TYPE_BASICSUPPORT,
- CCellularMiniportWaveRT_EventHandler_JackState
- },
- {
- &KSEVENTSETID_Telephony,
- KSEVENT_TELEPHONY_ENDPOINTPAIRS_CHANGED,
- KSEVENT_TYPE_ENABLE | KSEVENT_TYPE_BASICSUPPORT,
- CCellularMiniportWaveRT_EventHandler_Telephony
- }
-};
-
-/*****************************************************************************
- * PropertiesTopologyFilter
- *****************************************************************************
- * Automation table for jack descripton/detection.
- */
-DEFINE_PCAUTOMATION_TABLE_PROP_EVENT(AutomationCellularTopoFilter, PropertiesCellularTopoFilter, TelephonyEvents);
-
-
-//=============================================================================
-static
-PCFILTER_DESCRIPTOR CellularTopoMiniportFilterDescriptor =
-{
- 0, // Version
- &AutomationCellularTopoFilter, // AutomationTable
- sizeof(PCPIN_DESCRIPTOR), // PinSize
- SIZEOF_ARRAY(CellularTopoMiniportPins), // PinCount
- CellularTopoMiniportPins, // Pins
- sizeof(PCNODE_DESCRIPTOR), // NodeSize
- 0, // NodeCount
- NULL, // Nodes
- SIZEOF_ARRAY(CellularTopoMiniportConnections), // ConnectionCount
- CellularTopoMiniportConnections, // Connections
- 0, // CategoryCount
- NULL // Categories
-};
-
-#endif // _SYSVAD_CELLULARTOPTABLE_H_
-
-
diff --git a/audio/sysvad/PhoneAudioSample/Cellularwavtable.h b/audio/sysvad/PhoneAudioSample/Cellularwavtable.h
deleted file mode 100644
index 806cb05d..00000000
--- a/audio/sysvad/PhoneAudioSample/Cellularwavtable.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- cellularwavtable.h
-
-Abstract:
-
- Declaration of wave miniport tables for the cellular endpoint.
-
---*/
-
-#ifndef _SYSVAD_CELLULARWAVTABLE_H_
-#define _SYSVAD_CELLULARWAVTABLE_H_
-
-
-#define CELLULAR_DEVICE_MAX_CHANNELS 1 // Max Channels.
-
-#define CELLULAR_CAPTURE_MAX_CHANNELS 1 // Max Channels.
-#define CELLULAR_CAPTURE_MIN_BITS_PER_SAMPLE 16 // Min Bits Per Sample
-#define CELLULAR_CAPTURE_MAX_BITS_PER_SAMPLE 16 // Max Bits Per Sample
-#define CELLULAR_CAPTURE_MIN_SAMPLE_RATE 16000 // Min Sample Rate
-#define CELLULAR_CAPTURE_MAX_SAMPLE_RATE 16000 // Max Sample Rate
-
-//
-// Max # of pin instances.
-//
-#define CELLULAR_MAX_INPUT_SYSTEM_STREAMS 1
-
-
-//=============================================================================
-static
-KSDATAFORMAT_WAVEFORMATEXTENSIBLE CellularCapturePinSupportedDeviceFormats[] =
-{
- { // 0
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 1,
- 16000,
- 32000,
- 2,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_MONO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
-};
-
-//
-// Supported modes (only on streaming pins).
-//
-static
-MODE_AND_DEFAULT_FORMAT CellularCapturePinSupportedDeviceModes[] =
-{
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_RAW,
- &CellularCapturePinSupportedDeviceFormats[SIZEOF_ARRAY(CellularCapturePinSupportedDeviceFormats) - 1].DataFormat
- }
-};
-
-//=============================================================================
-// The entries here must follow the same order as the filter's pin
-// descriptor array.
-//
-static
-PIN_DEVICE_FORMATS_AND_MODES CellularPinDeviceFormatsAndModes[] =
-{
- { // BIDI
- TelephonyBidiPin,
- CellularCapturePinSupportedDeviceFormats,
- SIZEOF_ARRAY(CellularCapturePinSupportedDeviceFormats),
- CellularCapturePinSupportedDeviceModes,
- SIZEOF_ARRAY(CellularCapturePinSupportedDeviceModes)
- },
- {
- BridgePin,
- NULL,
- 0,
- NULL,
- 0,
- }
-};
-
-//=============================================================================
-static
-KSDATARANGE_AUDIO CellularPinDataRangesStream[] =
-{
- { // 0
- {
- sizeof(KSDATARANGE_AUDIO),
- KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- CELLULAR_CAPTURE_MAX_CHANNELS,
- CELLULAR_CAPTURE_MIN_BITS_PER_SAMPLE,
- CELLULAR_CAPTURE_MAX_BITS_PER_SAMPLE,
- CELLULAR_CAPTURE_MIN_SAMPLE_RATE,
- CELLULAR_CAPTURE_MAX_SAMPLE_RATE
- }
-};
-
-static
-PKSDATARANGE CellularPinDataRangePointersBiDiStream[] =
-{
- PKSDATARANGE(&CellularPinDataRangesStream[0]),
- PKSDATARANGE(&PinDataRangeAttributeList)
-};
-
-//=============================================================================
-static
-KSDATARANGE CellularPinDataRangesBridge[] =
-{
- {
- sizeof(KSDATARANGE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
- }
-};
-
-static
-PKSDATARANGE CellularPinDataRangePointersBridge[] =
-{
- &CellularPinDataRangesBridge[0]
-};
-
-
-//=============================================================================
-static
-PCPIN_DESCRIPTOR CellularWaveMiniportPins[] =
-{
- // Wave Out Streaming Pin (Renderer) KSPIN_WAVE_BIDI
- {
- CELLULAR_MAX_INPUT_SYSTEM_STREAMS,
- CELLULAR_MAX_INPUT_SYSTEM_STREAMS,
- 0,
- NULL,
- {
- 0,
- NULL,
- 0,
- NULL,
- SIZEOF_ARRAY(CellularPinDataRangePointersBiDiStream),
- CellularPinDataRangePointersBiDiStream,
- KSPIN_DATAFLOW_OUT,
- KSPIN_COMMUNICATION_SINK,
- &KSCATEGORY_AUDIO,
- NULL,
- 0
- }
- },
- // Wave Out Bridge Pin (Renderer) KSPIN_WAVE_BIDI_BRIDGE
- {
- 0,
- 0,
- 0,
- NULL,
- {
- 0,
- NULL,
- 0,
- NULL,
- SIZEOF_ARRAY(CellularPinDataRangePointersBridge),
- CellularPinDataRangePointersBridge,
- KSPIN_DATAFLOW_IN,
- KSPIN_COMMUNICATION_NONE,
- &KSCATEGORY_AUDIO,
- NULL,
- 0
- }
- }
-};
-
-//=============================================================================
-//
-// Note:
-//
-// -----
-// | |
-// BiDi pin 1 <--| |<-- 0 BiDi bridge pin
-// -----
-
-static
-PCCONNECTION_DESCRIPTOR CellularWaveMiniportConnections[] =
-{
- { PCFILTER_NODE, KSPIN_WAVE_BIDI_BRIDGE, PCFILTER_NODE, KSPIN_WAVE_BIDI }
-};
-
-//=============================================================================
-static
-PCPROPERTY_ITEM PropertiesCellularWaveFilter[] =
-{
- {
- &KSPROPSETID_Pin,
- KSPROPERTY_PIN_PROPOSEDATAFORMAT,
- KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_WaveFilter
- },
- {
- &KSPROPSETID_Pin,
- KSPROPERTY_PIN_PROPOSEDATAFORMAT2,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_WaveFilter
- },
- {
- &KSPROPSETID_TelephonyControl,
- KSPROPERTY_TELEPHONY_PROVIDERID,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_CellularWaveFilter
- },
- {
- &KSPROPSETID_TelephonyControl,
- KSPROPERTY_TELEPHONY_CALLINFO,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_CellularWaveFilter
- },
- {
- &KSPROPSETID_TelephonyControl,
- KSPROPERTY_TELEPHONY_CALLCONTROL,
- KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_CellularWaveFilter
- },
- {
- &KSPROPSETID_TelephonyControl,
- KSPROPERTY_TELEPHONY_PROVIDERCHANGE,
- KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_CellularWaveFilter
- },
- {
- &KSPROPSETID_TelephonyControl,
- KSPROPERTY_TELEPHONY_CALLHOLD,
- KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_CellularWaveFilter
- },
- {
- &KSPROPSETID_TelephonyControl,
- KSPROPERTY_TELEPHONY_MUTE_TX,
- KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_CellularWaveFilter
- },
-};
-
-DEFINE_PCAUTOMATION_TABLE_PROP(AutomationCellularWaveFilter, PropertiesCellularWaveFilter);
-
-//=============================================================================
-static
-PCFILTER_DESCRIPTOR CellularWaveMiniportFilterDescriptor =
-{
- 0, // Version
- &AutomationCellularWaveFilter, // AutomationTable
- sizeof(PCPIN_DESCRIPTOR), // PinSize
- SIZEOF_ARRAY(CellularWaveMiniportPins), // PinCount
- CellularWaveMiniportPins, // Pins
- sizeof(PCNODE_DESCRIPTOR), // NodeSize
- 0, // NodeCount
- NULL, // Nodes
- SIZEOF_ARRAY(CellularWaveMiniportConnections), // ConnectionCount
- CellularWaveMiniportConnections, // Connections
- 0, // CategoryCount
- NULL // Categories - use defaults (audio, render, capture)
-};
-
-#endif // _SYSVAD_CELLULARWAVTABLE_H_
-
diff --git a/audio/sysvad/PhoneAudioSample/FMTopTable.h b/audio/sysvad/PhoneAudioSample/FMTopTable.h
deleted file mode 100644
index ae8ddf9e..00000000
--- a/audio/sysvad/PhoneAudioSample/FMTopTable.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- fmtoptable.h
-
-Abstract:
-
- Declaration of topology tables for the fm endpoint.
-
---*/
-
-#ifndef _SYSVAD_FMTOPTABLE_H_
-#define _SYSVAD_FMTOPTABLE_H_
-
-// {344EC7D7-F209-4FC4-B6C1-B324E8309E8D}
-DEFINE_GUID(FMRX_CUSTOM_NAME,
- 0x344ec7d7, 0xf209, 0x4fc4, 0xb6, 0xc1, 0xb3, 0x24, 0xe8, 0x30, 0x9e, 0x8d);
-
-//=============================================================================
-static
-KSDATARANGE FmTopoPinDataRangesBridge[] =
-{
- {
- sizeof(KSDATARANGE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
- }
-};
-
-//=============================================================================
-static
-PKSDATARANGE FmTopoPinDataRangePointersBridge[] =
-{
- &FmTopoPinDataRangesBridge[0]
-};
-
-//=============================================================================
-static
-PCPIN_DESCRIPTOR FmTopoMiniportPins[] =
-{
- // KSPIN_TOPO_FMRX
- {
- 0,
- 0,
- 0, // InstanceCount
- NULL, // AutomationTable
- { // KsPinDescriptor
- 0, // InterfacesCount
- NULL, // Interfaces
- 0, // MediumsCount
- NULL, // Mediums
- SIZEOF_ARRAY(FmTopoPinDataRangePointersBridge), // DataRangesCount
- FmTopoPinDataRangePointersBridge, // DataRanges
- KSPIN_DATAFLOW_IN, // DataFlow
- KSPIN_COMMUNICATION_NONE, // Communication
- &KSNODETYPE_FM_RX, // Category
- &FMRX_CUSTOM_NAME, // Name
- 0 // Reserved
- }
- },
- // KSPIN_TOPO_FMRX_BRIDGE
- {
- 0,
- 0,
- 0, // InstanceCount
- NULL, // AutomationTable
- { // KsPinDescriptor
- 0, // InterfacesCount
- NULL, // Interfaces
- 0, // MediumsCount
- NULL, // Mediums
- SIZEOF_ARRAY(FmTopoPinDataRangePointersBridge), // DataRangesCount
- FmTopoPinDataRangePointersBridge, // DataRanges
- KSPIN_DATAFLOW_OUT, // DataFlow
- KSPIN_COMMUNICATION_NONE, // Communication
- &KSCATEGORY_AUDIO, // Category
- NULL, // Name
- 0 // Reserved
- }
- },
-};
-
-//=============================================================================
-static
-KSJACK_DESCRIPTION FmRxJackDesc =
-{
- KSAUDIO_SPEAKER_STEREO,
- 0x0000, // no color
- eConnTypeOtherAnalog,
- eGeoLocNotApplicable,
- eGenLocInternal,
- ePortConnUnknown,
- FALSE
-};
-
-// Only return a KSJACK_DESCRIPTION for the physical bridge pin.
-static
-PKSJACK_DESCRIPTION FmJackDescriptions[] =
-{
- &FmRxJackDesc,
- NULL,
-};
-
-//=============================================================================
-static
-PCCONNECTION_DESCRIPTOR FmTopoMiniportConnections[] =
-{
- // FromNode, FromPin, ToNode, ToPin
- { PCFILTER_NODE, KSPIN_TOPO_FMRX, PCFILTER_NODE, KSPIN_TOPO_FMRX_BRIDGE},
-};
-
-
-//=============================================================================
-static
-PCPROPERTY_ITEM PropertiesFmTopoFilter[] =
-{
- {
- &KSPROPSETID_Jack,
- KSPROPERTY_JACK_DESCRIPTION,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_FmRxTopoFilter
- },
- {
- &KSPROPSETID_Jack,
- KSPROPERTY_JACK_DESCRIPTION2,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_FmRxTopoFilter
- },
- {
- &KSPROPSETID_FMRXTopology,
- KSPROPERTY_FMRX_ENDPOINTID,
- KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_FmRxTopoFilter
- },
- {
- &KSPROPSETID_FMRXTopology,
- KSPROPERTY_FMRX_VOLUME,
- KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_FmRxTopoFilter
- },
- {
- &KSPROPSETID_FMRXTopology,
- KSPROPERTY_FMRX_ANTENNAENDPOINTID,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_FmRxTopoFilter
- },
-};
-
-NTSTATUS CFmMiniportWaveRT_EventHandler_JackState
-(
- _In_ PPCEVENT_REQUEST EventRequest
-);
-
-static PCEVENT_ITEM FmRxJackInfoChangeEvent[] =
-{
- {
- &KSEVENTSETID_PinCapsChange, // Something changed
- KSEVENT_PINCAPS_JACKINFOCHANGE, // Jack Info Changes
- KSEVENT_TYPE_ENABLE | KSEVENT_TYPE_BASICSUPPORT,
- CFmMiniportWaveRT_EventHandler_JackState
- }
-};
-
-/*****************************************************************************
- * PropertiesTopologyFilter
- *****************************************************************************
- * Automation table for jack descripton/detection.
- */
-DEFINE_PCAUTOMATION_TABLE_PROP_EVENT(AutomationFmTopoFilter, PropertiesFmTopoFilter, FmRxJackInfoChangeEvent);
-
-
-//=============================================================================
-static
-PCFILTER_DESCRIPTOR FmTopoMiniportFilterDescriptor =
-{
- 0, // Version
- &AutomationFmTopoFilter, // AutomationTable
- sizeof(PCPIN_DESCRIPTOR), // PinSize
- SIZEOF_ARRAY(FmTopoMiniportPins), // PinCount
- FmTopoMiniportPins, // Pins
- sizeof(PCNODE_DESCRIPTOR), // NodeSize
- 0, // NodeCount
- NULL, // Nodes
- SIZEOF_ARRAY(FmTopoMiniportConnections), // ConnectionCount
- FmTopoMiniportConnections, // Connections
- 0, // CategoryCount
- NULL // Categories
-};
-
-#endif // _SYSVAD_FMTOPTABLE_H_
-
-
diff --git a/audio/sysvad/PhoneAudioSample/FMTopo.cpp b/audio/sysvad/PhoneAudioSample/FMTopo.cpp
deleted file mode 100644
index 9c43168f..00000000
--- a/audio/sysvad/PhoneAudioSample/FMTopo.cpp
+++ /dev/null
@@ -1,985 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- fmtopo.cpp
-
-Abstract:
-
- Implementation of topology miniport for the fm endpoint.
-
---*/
-
-#pragma warning (disable : 4127)
-
-#include <sysvad.h>
-#include "simple.h"
-#include "mintopo.h"
-#include "fmtopo.h"
-#include "fmtoptable.h"
-#include <ntstrsafe.h>
-
-
-#pragma code_seg("PAGE")
-
-// Table of valid render endpoints for FM
-KSTOPOLOGY_ENDPOINTID g_EndpointList[] =
-{
- { SPEAKER_TOPONAME, KSPIN_TOPO_LINEOUT_DEST },
- { SPEAKER_HEADSET_TOPONAME, KSPIN_TOPO_LINEOUT_DEST },
- { HOSTRENDER_TOPONAME, HOSTRENDER_PIN }
-};
-
-KSTOPOLOGY_ENDPOINTID g_AntennaEndpoint =
-{
- SPEAKER_HEADSET_TOPONAME, KSPIN_TOPO_LINEOUT_DEST
-};
-
-//=============================================================================
-NTSTATUS
-CreateFmMiniportTopology
-(
- _Out_ PUNKNOWN * Unknown,
- _In_ REFCLSID,
- _In_opt_ PUNKNOWN UnknownOuter,
- _When_((PoolType & NonPagedPoolMustSucceed) != 0,
- __drv_reportError("Must succeed pool allocations are forbidden. "
- "Allocation failures cause a system crash"))
- _In_ POOL_TYPE PoolType,
- _In_ PUNKNOWN UnknownAdapter,
- _In_opt_ PVOID DeviceContext,
- _In_ PENDPOINT_MINIPAIR MiniportPair
-)
-/*++
-
-Routine Description:
-
- Creates a new topology miniport.
-
-Arguments:
-
- Unknown -
-
- RefclsId -
-
- UnknownOuter -
-
- PoolType -
-
- UnknownAdapter -
-
- DeviceContext -
-
- MiniportPair -
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(Unknown);
- ASSERT(MiniportPair);
-
- UNREFERENCED_PARAMETER(UnknownAdapter);
- UNREFERENCED_PARAMETER(DeviceContext);
-
- CFmMiniportTopology *obj =
- new (PoolType, MINWAVERT_POOLTAG)
- CFmMiniportTopology( UnknownOuter,
- MiniportPair->TopoDescriptor,
- MiniportPair->DeviceMaxChannels);
- if (NULL == obj)
- {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- obj->AddRef();
- *Unknown = reinterpret_cast<IUnknown*>(obj);
-
- return STATUS_SUCCESS;
-} // CreateFmMiniportTopology
-
-CFmMiniportTopology::CFmMiniportTopology
-(
- _In_opt_ PUNKNOWN UnknownOuter,
- _In_ PCFILTER_DESCRIPTOR *FilterDesc,
- _In_ USHORT DeviceMaxChannels
-)
-: CUnknown(UnknownOuter),
- CMiniportTopologySYSVAD(FilterDesc, DeviceMaxChannels),
- m_FmRxVolume(FMRX_VOLUME_MAXIMUM)
-{
- PAGED_CODE();
-
- memcpy(&m_FmRxTargetEndpoint, &g_EndpointList[0], sizeof(m_FmRxTargetEndpoint));
-}
-
-
-//=============================================================================
-CFmMiniportTopology::~CFmMiniportTopology
-(
- void
-)
-/*++
-
-Routine Description:
-
- Topology miniport destructor
-
-Arguments:
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- DPF_ENTER(("[CFmMiniportTopology::~CFmMiniportTopology]"));
-} // ~CFmMiniportTopology
-
-//=============================================================================
-NTSTATUS
-CFmMiniportTopology::DataRangeIntersection
-(
- _In_ ULONG PinId,
- _In_ PKSDATARANGE ClientDataRange,
- _In_ PKSDATARANGE MyDataRange,
- _In_ ULONG OutputBufferLength,
- _Out_writes_bytes_to_opt_(OutputBufferLength, *ResultantFormatLength)
- PVOID ResultantFormat OPTIONAL,
- _Out_ PULONG ResultantFormatLength
-)
-/*++
-
-Routine Description:
-
- The DataRangeIntersection function determines the highest quality
- intersection of two data ranges.
-
-Arguments:
-
- PinId - Pin for which data intersection is being determined.
-
- ClientDataRange - Pointer to KSDATARANGE structure which contains the data range
- submitted by client in the data range intersection property
- request.
-
- MyDataRange - Pin's data range to be compared with client's data range.
-
- OutputBufferLength - Size of the buffer pointed to by the resultant format
- parameter.
-
- ResultantFormat - Pointer to value where the resultant format should be
- returned.
-
- ResultantFormatLength - Actual length of the resultant format that is placed
- at ResultantFormat. This should be less than or equal
- to OutputBufferLength.
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- return
- CMiniportTopologySYSVAD::DataRangeIntersection
- (
- PinId,
- ClientDataRange,
- MyDataRange,
- OutputBufferLength,
- ResultantFormat,
- ResultantFormatLength
- );
-} // DataRangeIntersection
-
-//=============================================================================
-STDMETHODIMP
-CFmMiniportTopology::GetDescription
-(
- _Out_ PPCFILTER_DESCRIPTOR * OutFilterDescriptor
-)
-/*++
-
-Routine Description:
-
- The GetDescription function gets a pointer to a filter description.
- It provides a location to deposit a pointer in miniport's description
- structure. This is the placeholder for the FromNode or ToNode fields in
- connections which describe connections to the filter's pins.
-
-Arguments:
-
- OutFilterDescriptor - Pointer to the filter description.
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(OutFilterDescriptor);
-
- return CMiniportTopologySYSVAD::GetDescription(OutFilterDescriptor);
-} // GetDescription
-
-//=============================================================================
-STDMETHODIMP
-CFmMiniportTopology::Init
-(
- _In_ PUNKNOWN UnknownAdapter,
- _In_ PRESOURCELIST ResourceList,
- _In_ PPORTTOPOLOGY Port_
-)
-/*++
-
-Routine Description:
-
- The Init function initializes the miniport. Callers of this function
- should run at IRQL PASSIVE_LEVEL
-
-Arguments:
-
- UnknownAdapter - A pointer to the Iuknown interface of the adapter object.
-
- ResourceList - Pointer to the resource list to be supplied to the miniport
- during initialization. The port driver is free to examine the
- contents of the ResourceList. The port driver will not be
- modify the ResourceList contents.
-
- Port - Pointer to the topology port object that is linked with this miniport.
-
-Return Value:
-
- NT status code.
-
---*/
-{
- UNREFERENCED_PARAMETER(ResourceList);
-
- PAGED_CODE();
-
- ASSERT(UnknownAdapter);
- ASSERT(Port_);
-
- DPF_ENTER(("[CFmMiniportTopology::Init]"));
-
- NTSTATUS ntStatus;
-
- ntStatus =
- CMiniportTopologySYSVAD::Init
- (
- UnknownAdapter,
- Port_
- );
-
- return ntStatus;
-} // Init
-
-//=============================================================================
-STDMETHODIMP
-CFmMiniportTopology::NonDelegatingQueryInterface
-(
- _In_ REFIID Interface,
- _COM_Outptr_ PVOID * Object
-)
-/*++
-
-Routine Description:
-
- QueryInterface for MiniportTopology
-
-Arguments:
-
- Interface - GUID of the interface
-
- Object - interface object to be returned.
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(Object);
-
- if (IsEqualGUIDAligned(Interface, IID_IUnknown))
- {
- *Object = PVOID(PUNKNOWN(this));
- }
- else if (IsEqualGUIDAligned(Interface, IID_IMiniport))
- {
- *Object = PVOID(PMINIPORT(this));
- }
- else if (IsEqualGUIDAligned(Interface, IID_IMiniportTopology))
- {
- *Object = PVOID(PMINIPORTTOPOLOGY(this));
- }
- else if (IsEqualGUIDAligned(Interface, IID_IFmTopology))
- {
- *Object = PVOID(PFMTOPOLOGY(this));
- }
- else
- {
- *Object = NULL;
- }
-
- if (*Object)
- {
- // We reference the interface for the caller.
- PUNKNOWN(*Object)->AddRef();
- return(STATUS_SUCCESS);
- }
-
- return(STATUS_INVALID_PARAMETER);
-} // NonDelegatingQueryInterface
-
-//=============================================================================
-NTSTATUS
-CFmMiniportTopology::PropertyHandlerJackDescription
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
- Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION )
-
-Arguments:
-
- PropertyRequest
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandlerJackDescription]"));
-
- ULONG cJackDescriptions = ARRAYSIZE(FmJackDescriptions);
- PKSJACK_DESCRIPTION * JackDescriptions = FmJackDescriptions;
-
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
- ULONG nPinId = (ULONG)-1;
-
- if (PropertyRequest->InstanceSize >= sizeof(ULONG))
- {
- nPinId = *(PULONG(PropertyRequest->Instance));
-
- if ((nPinId < cJackDescriptions) && (JackDescriptions[nPinId] != NULL))
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ntStatus =
- PropertyHandler_BasicSupport
- (
- PropertyRequest,
- KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET,
- VT_ILLEGAL
- );
- }
- else
- {
- ULONG cbNeeded = sizeof(KSMULTIPLE_ITEM) + sizeof(KSJACK_DESCRIPTION);
-
- if (PropertyRequest->ValueSize == 0)
- {
- PropertyRequest->ValueSize = cbNeeded;
- ntStatus = STATUS_BUFFER_OVERFLOW;
- }
- else if (PropertyRequest->ValueSize < cbNeeded)
- {
- ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value;
- PKSJACK_DESCRIPTION pDesc = (PKSJACK_DESCRIPTION)(pMI+1);
-
- pMI->Size = cbNeeded;
- pMI->Count = 1;
-
- RtlCopyMemory(pDesc, JackDescriptions[nPinId], sizeof(KSJACK_DESCRIPTION));
- ntStatus = STATUS_SUCCESS;
- }
- }
- }
- }
- }
-
- return ntStatus;
-}
-
-//=============================================================================
-NTSTATUS
-CFmMiniportTopology::PropertyHandlerJackDescription2
-(
-_In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
-Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION2 )
-
-Arguments:
-
-PropertyRequest -
-
-Return Value:
-
-NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandlerJackDescription2]"));
-
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
- ULONG nPinId = (ULONG)-1;
-
- ULONG cJackDescriptions = ARRAYSIZE(FmJackDescriptions);
- PKSJACK_DESCRIPTION * JackDescriptions = FmJackDescriptions;
-
- if (PropertyRequest->InstanceSize >= sizeof(ULONG))
- {
- nPinId = *(PULONG(PropertyRequest->Instance));
-
- if ((nPinId < cJackDescriptions) && (JackDescriptions[nPinId] != NULL))
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ntStatus =
- PropertyHandler_BasicSupport
- (
- PropertyRequest,
- KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET,
- VT_ILLEGAL
- );
- }
- else
- {
- ULONG cbNeeded = sizeof(KSMULTIPLE_ITEM)+sizeof(KSJACK_DESCRIPTION2);
-
- if (PropertyRequest->ValueSize == 0)
- {
- PropertyRequest->ValueSize = cbNeeded;
- ntStatus = STATUS_BUFFER_OVERFLOW;
- }
- else if (PropertyRequest->ValueSize < cbNeeded)
- {
- ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value;
- PKSJACK_DESCRIPTION2 pDesc = (PKSJACK_DESCRIPTION2)(pMI + 1);
-
- pMI->Size = cbNeeded;
- pMI->Count = 1;
-
- RtlZeroMemory(pDesc, sizeof(KSJACK_DESCRIPTION2));
-
- //
- // Specifies the lower 16 bits of the DWORD parameter. This parameter indicates whether
- // the jack is currently active, streaming, idle, or hardware not ready.
- //
- pDesc->DeviceStateInfo = 0;
-
- //
- // From MSDN:
- // "If an audio device lacks jack presence detection, the IsConnected member of
- // the KSJACK_DESCRIPTION structure must always be set to TRUE. To remove the
- // ambiguity that results from this dual meaning of the TRUE value for IsConnected,
- // a client application can call IKsJackDescription2::GetJackDescription2 to read
- // the JackCapabilities flag of the KSJACK_DESCRIPTION2 structure. If this flag has
- // the JACKDESC2_PRESENCE_DETECT_CAPABILITY bit set, it indicates that the endpoint
- // does in fact support jack presence detection. In that case, the return value of
- // the IsConnected member can be interpreted to accurately reflect the insertion status
- // of the jack."
- //
- // Bit definitions:
- // 0x00000001 - JACKDESC2_PRESENCE_DETECT_CAPABILITY
- // 0x00000002 - JACKDESC2_DYNAMIC_FORMAT_CHANGE_CAPABILITY
- //
- pDesc->JackCapabilities = JACKDESC2_PRESENCE_DETECT_CAPABILITY;
-
- ntStatus = STATUS_SUCCESS;
- }
- }
- }
- }
- }
-
- return ntStatus;
-}
-
-//=============================================================================
-NTSTATUS
-CFmMiniportTopology::PropertyHandlerFmRxEndpointId
-(
-_In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
-Handles ( KSPROPSETID_FMRXTopology, KSPROPERTY_FMRX_ENDPOINTID )
-
-Arguments:
-
-PropertyRequest
-
-Return Value:
-
-NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandlerFmRxEndpointId]"));
-
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
-
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ntStatus = STATUS_INVALID_PARAMETER;
- ULONG ulExpectedSize = (sizeof(KSPROPERTY_DESCRIPTION)+sizeof(KSPROPERTY_MEMBERSHEADER)+sizeof(g_EndpointList));
-
- if (PropertyRequest->ValueSize >= sizeof(KSPROPERTY_DESCRIPTION))
- {
- // if return buffer can hold a KSPROPERTY_DESCRIPTION, return it
- //
- PKSPROPERTY_DESCRIPTION PropDesc =
- PKSPROPERTY_DESCRIPTION(PropertyRequest->Value);
-
- PropDesc->AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_GET;
- PropDesc->DescriptionSize = ulExpectedSize;
- PropDesc->PropTypeSet.Set = KSPROPSETID_FMRXTopology;
- PropDesc->PropTypeSet.Id = KSPROPERTY_FMRX_ENDPOINTID;
- PropDesc->PropTypeSet.Flags = 0;
- PropDesc->MembersListCount = 1;
- PropDesc->Reserved = 0;
-
- // buffer is big enough to hold the full data, add that
- if (PropertyRequest->ValueSize >= ulExpectedSize)
- {
- PKSPROPERTY_MEMBERSHEADER MembersHeader =
- PKSPROPERTY_MEMBERSHEADER(PropDesc + 1);
-
- MembersHeader->MembersFlags = KSPROPERTY_MEMBER_VALUES;
- MembersHeader->MembersSize = sizeof(KSTOPOLOGY_ENDPOINTID);
- MembersHeader->MembersCount = SIZEOF_ARRAY(g_EndpointList);
- MembersHeader->Flags = 0;
-
- memcpy(MembersHeader + 1, g_EndpointList, sizeof(g_EndpointList));
-
- // tell them how much space we really used, which controls how much data is copied into the user buffer.
- PropertyRequest->ValueSize = ulExpectedSize;
- }
- else
- {
- // tell them how much space we really used, which controls how much data is copied into the user buffer.
- PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION);
- }
-
- ntStatus = STATUS_SUCCESS;
- }
- else if (PropertyRequest->ValueSize >= sizeof(ULONG))
- {
- // if return buffer can hold a ULONG, return the access flags.
- *(PULONG(PropertyRequest->Value)) = KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_GET;
- PropertyRequest->ValueSize = sizeof(ULONG);
- ntStatus = STATUS_SUCCESS;
- }
- else if (PropertyRequest->ValueSize == 0)
- {
- PropertyRequest->ValueSize = ulExpectedSize;
- ntStatus = STATUS_BUFFER_OVERFLOW;
- }
- else
- {
- ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- }
- else
- {
- ntStatus =
- ValidatePropertyParams
- (
- PropertyRequest,
- sizeof(KSTOPOLOGY_ENDPOINTID),
- 0
- );
-
- if (NT_SUCCESS(ntStatus))
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- PKSTOPOLOGY_ENDPOINTID EndpointId = static_cast<PKSTOPOLOGY_ENDPOINTID>(PropertyRequest->Value);
-
- memcpy(EndpointId, &m_FmRxTargetEndpoint, sizeof(m_FmRxTargetEndpoint));
-
- ntStatus = STATUS_SUCCESS;
- }
- else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
- {
- PKSTOPOLOGY_ENDPOINTID EndpointId = static_cast<PKSTOPOLOGY_ENDPOINTID>(PropertyRequest->Value);
-
- ntStatus = STATUS_INVALID_PARAMETER;
- for (int i = 0; i < SIZEOF_ARRAY(g_EndpointList); i++)
- {
- if (g_EndpointList[i].PinId == EndpointId->PinId &&
- 0 == _wcsnicmp(g_EndpointList[i].TopologyName, EndpointId->TopologyName, MAX_PATH))
- {
- memcpy(&m_FmRxTargetEndpoint, EndpointId, sizeof(m_FmRxTargetEndpoint));
-
- if (HOSTRENDER_PIN == EndpointId->PinId &&
- 0 == _wcsnicmp(HOSTRENDER_TOPONAME, EndpointId->TopologyName, MAX_PATH))
- {
- // This is an indication that FM audio is being routed through OS (For example, user plugs in
- // USB headset for FM audio) and driver must stop rendering FM audio to any physical audio endpoint.
- }
- else
- {
- // Route FM audio to this new endpoint.
- }
- ntStatus = STATUS_SUCCESS;
- break;
- }
- }
- }
- else
- {
- ntStatus = STATUS_INVALID_PARAMETER;
- }
- }
- }
-
- return ntStatus;
-}
-
-//=============================================================================
-NTSTATUS
-CFmMiniportTopology::PropertyHandlerFmRxVolume
-(
-_In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
-Handles ( KSPROPSETID_FMRXTopology, KSPROPERTY_FMRX_VOLUME )
-
-Arguments:
-
-PropertyRequest
-
-Return Value:
-
-NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandlerFmRxVolume]"));
-
- UNREFERENCED_PARAMETER(PropertyRequest);
-
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
-
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ntStatus =
- PropertyHandler_BasicSupportVolume
- (
- PropertyRequest,
- 1 // FM audio technically supports Stereo, but we only support a single volume
- );
-
- ULONG cbFullProperty =
- sizeof(KSPROPERTY_DESCRIPTION)+
- sizeof(KSPROPERTY_MEMBERSHEADER)+
- sizeof(KSPROPERTY_STEPPING_LONG);
-
- if (NT_SUCCESS(ntStatus) && PropertyRequest->ValueSize >= cbFullProperty)
- {
- // Access proper values
- PKSPROPERTY_DESCRIPTION PropDesc =
- PKSPROPERTY_DESCRIPTION(PropertyRequest->Value);
- PKSPROPERTY_MEMBERSHEADER Members =
- PKSPROPERTY_MEMBERSHEADER(PropDesc + 1);
- PKSPROPERTY_STEPPING_LONG Range =
- PKSPROPERTY_STEPPING_LONG(Members + 1);
-
- Members->Flags = 0;
-
- Range->Bounds.SignedMaximum = FMRX_VOLUME_MAXIMUM;
- Range->Bounds.SignedMinimum = FMRX_VOLUME_MINIMUM;
- Range->SteppingDelta = FMRX_VOLUME_STEPPING;
- }
- }
- else
- {
- ntStatus =
- ValidatePropertyParams
- (
- PropertyRequest,
- sizeof(LONG), // volume value is a LONG
- 0 // No support for channel since this is a property
- // on the topo filter, not a volume node.
- );
-
-
- if (NT_SUCCESS(ntStatus))
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- LONG* volume = (LONG*)PropertyRequest->Value;
- // Return current FM volume
- *volume = m_FmRxVolume;
- ntStatus = STATUS_SUCCESS;
- }
- else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
- {
- LONG* volume = (LONG*)PropertyRequest->Value;
-
- LONG normalizedVolume =
- VALUE_NORMALIZE_IN_RANGE_EX
- (
- *volume,
- FMRX_VOLUME_MINIMUM,
- FMRX_VOLUME_MAXIMUM,
- FMRX_VOLUME_STEPPING
- );
- if (normalizedVolume == *volume)
- {
- m_FmRxVolume = *volume;
- ntStatus = STATUS_SUCCESS;
- }
- else
- {
- ntStatus = STATUS_INVALID_PARAMETER;
- }
- }
- else
- {
- ntStatus = STATUS_INVALID_PARAMETER;
- }
- }
- }
-
- return ntStatus;
-}
-
-//=============================================================================
-NTSTATUS
-CFmMiniportTopology::PropertyHandlerFmRxAntennaEndpointId
-(
-_In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
-Handles ( KSPROPSETID_FMRXTopology, KSPROPERTY_FMRX_ANTENNAENDPOINTID )
-
-Arguments:
-
-PropertyRequest
-
-Return Value:
-
-NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandlerFmRxAntennaEndpoint]"));
-
- UNREFERENCED_PARAMETER(PropertyRequest);
-
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
-
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ULONG flags = PropertyRequest->PropertyItem->Flags;
- ntStatus = PropertyHandler_BasicSupport(PropertyRequest, flags, VT_ILLEGAL);
- }
- else
- {
- ntStatus =
- ValidatePropertyParams
- (
- PropertyRequest,
- sizeof(KSTOPOLOGY_ENDPOINTID),
- 0
- );
-
-
- if (NT_SUCCESS(ntStatus))
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- PKSTOPOLOGY_ENDPOINTID pEndpointId = (PKSTOPOLOGY_ENDPOINTID)PropertyRequest->Value;
- memcpy(pEndpointId, &g_AntennaEndpoint, sizeof(*pEndpointId));
- ntStatus = STATUS_SUCCESS;
- }
- else
- {
- ntStatus = STATUS_INVALID_PARAMETER;
- }
- }
- }
-
- return ntStatus;
-}
-
-//=============================================================================
-NTSTATUS
-PropertyHandler_FmRxTopoFilter
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
- Redirects property request to miniport object
-
-Arguments:
-
- PropertyRequest -
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandler_FmRxTopoFilter]"));
-
- // PropertryRequest structure is filled by portcls.
- // MajorTarget is a pointer to miniport object for miniports.
- //
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
- PCFmMiniportTopology pMiniport = (PCFmMiniportTopology)PropertyRequest->MajorTarget;
-
- if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Jack))
- {
- if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION)
- {
- ntStatus = pMiniport->PropertyHandlerJackDescription(PropertyRequest);
- }
- else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION2)
- {
- ntStatus = pMiniport->PropertyHandlerJackDescription2(PropertyRequest);
- }
- }
- else if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_FMRXTopology))
- {
- if (PropertyRequest->PropertyItem->Id == KSPROPERTY_FMRX_ENDPOINTID)
- {
- ntStatus = pMiniport->PropertyHandlerFmRxEndpointId(PropertyRequest);
- }
- else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_FMRX_VOLUME)
- {
- ntStatus = pMiniport->PropertyHandlerFmRxVolume(PropertyRequest);
- }
- else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_FMRX_ANTENNAENDPOINTID)
- {
- ntStatus = pMiniport->PropertyHandlerFmRxAntennaEndpointId(PropertyRequest);
- }
- }
-
- return ntStatus;
-} // PropertyHandler_FmRxTopoFilter
-
-#pragma code_seg("PAGE")
-STDMETHODIMP_(NTSTATUS)
-CFmMiniportTopology::UpdateTopologyJackState
-(
- _In_ BOOL NewState
-)
-{
- PAGED_CODE ();
-
- FmRxJackDesc.IsConnected = NewState;
-
- // we have multiple pins which share the same jack state,
- // notify for every pin using that jack state
- GenerateEventList(
- (GUID*)&KSEVENTSETID_PinCapsChange, // event set. NULL is a wild card for all events.
- KSEVENT_PINCAPS_JACKINFOCHANGE, // event ID.
- TRUE, // use pid ID.
- KSPIN_TOPO_FMRX, // pin ID.
- FALSE, // do not use node ID.
- ULONG(-1)); // node ID, not used.
-
- return STATUS_SUCCESS;
-}
-
-#pragma code_seg()
-NTSTATUS CFmMiniportWaveRT_EventHandler_JackState
-(
- _In_ PPCEVENT_REQUEST EventRequest
-)
-{
- CFmMiniportTopology* miniport = reinterpret_cast<CFmMiniportTopology*>(EventRequest->MajorTarget);
- return miniport->EventHandler_JackState(EventRequest);
-}
-
-NTSTATUS CFmMiniportTopology::EventHandler_JackState
-(
- _In_ PPCEVENT_REQUEST EventRequest
-)
-{
- if (EventRequest->Verb == PCEVENT_VERB_ADD)
- {
- m_PortEvents->AddEventToEventList(EventRequest->EventEntry);
- }
-
- return STATUS_SUCCESS;
-}
-
-
diff --git a/audio/sysvad/PhoneAudioSample/FMTopo.h b/audio/sysvad/PhoneAudioSample/FMTopo.h
deleted file mode 100644
index ae279bf1..00000000
--- a/audio/sysvad/PhoneAudioSample/FMTopo.h
+++ /dev/null
@@ -1,152 +0,0 @@
-
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- FMtopo.h
-
-Abstract:
-
- Declaration of topology miniport for the fm endpoint.
-
---*/
-
-#ifndef _SYSVAD_FMTOPO_H_
-#define _SYSVAD_FMTOPO_H_
-
-#include "basetopo.h"
-
-// make sure all of these names matches with KSNAME_* in the inf's [Strings] section
-#define SPEAKER_TOPONAME L"TopologySpeaker"
-#define SPEAKER_HEADSET_TOPONAME L"TopologySpeakerHeadset"
-
-// Special routing endpoint
-#define HOSTRENDER_TOPONAME L"HostRender"
-#define HOSTRENDER_PIN 0
-
-// FM Volume Stepping information
-#define FMRX_VOLUME_MAXIMUM 0 // 0 dB
-#define FMRX_VOLUME_MINIMUM (-96 * 0x10000) // -96 dB
-#define FMRX_VOLUME_STEPPING (0x8000) // 0.5 dB steps
-
-
-//=============================================================================
-// Defines
-//=============================================================================
-// {949F42F1-A5F5-4FBD-B4BB-C543ACC24AE0}
-DEFINE_GUID(IID_IFmTopology,
- 0x949f42f1, 0xa5f5, 0x4fbd, 0xb4, 0xbb, 0xc5, 0x43, 0xac, 0xc2, 0x4a, 0xe0);
-
-
-//=============================================================================
-// Interfaces
-//=============================================================================
-
-///////////////////////////////////////////////////////////////////////////////
-// IFmTopology
-//
-DECLARE_INTERFACE_(IFmTopology, IMiniportTopology)
-{
- STDMETHOD_(NTSTATUS, UpdateTopologyJackState)
- (
- THIS_
- _In_ BOOL NewState
- ) PURE;
-};
-
-typedef IFmTopology *PFMTOPOLOGY;
-
-//=============================================================================
-// Classes
-//=============================================================================
-
-///////////////////////////////////////////////////////////////////////////////
-// CFmMiniportTopology
-//
-
-class CFmMiniportTopology :
- public CMiniportTopologySYSVAD,
- public IFmTopology,
- public CUnknown
-{
- private:
- KSTOPOLOGY_ENDPOINTID m_FmRxTargetEndpoint;
- KSTOPOLOGY_ENDPOINTID m_FmRxAntennaEndpoint;
- ULONG m_FmRxVolume;
-
- public:
- DECLARE_STD_UNKNOWN();
- CFmMiniportTopology
- (
- _In_opt_ PUNKNOWN UnknownOuter,
- _In_ PCFILTER_DESCRIPTOR *FilterDesc,
- _In_ USHORT DeviceMaxChannels
- );
-
- ~CFmMiniportTopology();
-
- IMP_IMiniportTopology;
-
- NTSTATUS PropertyHandlerJackSinkInfo
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
- NTSTATUS PropertyHandlerJackDescription
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
- NTSTATUS PropertyHandlerJackDescription2
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
- NTSTATUS PropertyHandlerFmRxEndpointId
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
- NTSTATUS PropertyHandlerFmRxVolume
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
- NTSTATUS PropertyHandlerFmRxAntennaEndpointId
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
- NTSTATUS EventHandler_JackState
- (
- _In_ PPCEVENT_REQUEST _pEventRequest
- );
-
- STDMETHODIMP_(NTSTATUS) UpdateTopologyJackState
- (
- _In_ BOOL NewState
- );
-};
-
-typedef CFmMiniportTopology *PCFmMiniportTopology;
-
-NTSTATUS
-CreateFmMiniportTopology(
- _Out_ PUNKNOWN * Unknown,
- _In_ REFCLSID,
- _In_opt_ PUNKNOWN UnknownOuter,
- _When_((PoolType & NonPagedPoolMustSucceed) != 0,
- __drv_reportError("Must succeed pool allocations are forbidden. "
- "Allocation failures cause a system crash"))
- _In_ POOL_TYPE PoolType,
- _In_ PUNKNOWN UnknownAdapter,
- _In_opt_ PVOID DeviceContext,
- _In_ PENDPOINT_MINIPAIR MiniportPair
- );
-
-NTSTATUS PropertyHandler_FmRxTopoFilter(_In_ PPCPROPERTY_REQUEST PropertyRequest);
-
-#endif // _SYSVAD_FMTOPO_H_
-
diff --git a/audio/sysvad/PhoneAudioSample/FMWave.cpp b/audio/sysvad/PhoneAudioSample/FMWave.cpp
deleted file mode 100644
index 4d571f57..00000000
--- a/audio/sysvad/PhoneAudioSample/FMWave.cpp
+++ /dev/null
@@ -1,389 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- fmwave.cpp
-
-Abstract:
-
- Implementation of wavert miniport for fm
-
---*/
-
-#pragma warning (disable : 4127)
-
-#include <sysvad.h>
-#include "simple.h"
-#include "FmWave.h"
-#include "FmTopo.h"
-#include "FmToptable.h"
-
-//=============================================================================
-// CFmMiniportWaveRT
-//=============================================================================
-
-//=============================================================================
-#pragma code_seg("PAGE")
-NTSTATUS
-CreateFmMiniportWaveRT
-(
- _Out_ PUNKNOWN * Unknown,
- _In_ REFCLSID,
- _In_opt_ PUNKNOWN UnknownOuter,
- _When_((PoolType & NonPagedPoolMustSucceed) != 0,
- __drv_reportError("Must succeed pool allocations are forbidden. "
- "Allocation failures cause a system crash"))
- _In_ POOL_TYPE PoolType,
- _In_ PUNKNOWN UnknownAdapter,
- _In_opt_ PVOID DeviceContext,
- _In_ PENDPOINT_MINIPAIR MiniportPair
-)
-/*++
-
-Routine Description:
-
- Create the wavert miniport.
-
-Arguments:
-
- Unknown -
-
- RefClsId -
-
- UnknownOuter -
-
- PoolType -
-
- UnkownAdapter -
-
- DeviceContext -
-
- MiniportPair -
-
-Return Value:
-
- NT status code.
-
---*/
-{
- UNREFERENCED_PARAMETER(UnknownOuter);
-
- PAGED_CODE();
-
- ASSERT(Unknown);
- ASSERT(MiniportPair);
-
- CMiniportWaveRT *obj = new (PoolType, MINWAVERT_POOLTAG) CFmMiniportWaveRT
- (
- UnknownAdapter,
- MiniportPair,
- DeviceContext
- );
- if (NULL == obj)
- {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- obj->AddRef();
- *Unknown = reinterpret_cast<IUnknown*>(obj);
-
- return STATUS_SUCCESS;
-}
-
-//=============================================================================
-#pragma code_seg("PAGE")
-CFmMiniportWaveRT::~CFmMiniportWaveRT
-(
- void
-)
-/*++
-
-Routine Description:
-
- Destructor for wavert miniport
-
-Arguments:
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- DPF_ENTER(("[CFmMiniportWaveRT::~CFmMiniportWaveRT]"));
-
-} // ~CFmMiniportWaveRT
-
-
-//=============================================================================
-#pragma code_seg("PAGE")
-STDMETHODIMP
-CFmMiniportWaveRT::NonDelegatingQueryInterface
-(
- _In_ REFIID Interface,
- _COM_Outptr_ PVOID * Object
-)
-/*++
-
-Routine Description:
-
- QueryInterface for CFmMiniportWaveRT
-
-Arguments:
-
- Interface - GUID of the interface
-
- Object - interface object to be returned.
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(Object);
-
- if (IsEqualGUIDAligned(Interface, IID_IAdapterPowerManagement))
- {
- *Object = PVOID(PADAPTERPOWERMANAGEMENT(this));
- }
- else
- {
- *Object = NULL;
- }
-
- if (*Object)
- {
- // We reference the interface for the caller.
-
- PUNKNOWN(*Object)->AddRef();
- return STATUS_SUCCESS;
- }
-
- return CMiniportWaveRT::NonDelegatingQueryInterface(Interface, Object);
-}
-
-#pragma code_seg("PAGE")
-NTSTATUS
-PropertyHandler_FmRxWaveFilter
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
- Redirects general property request to miniport object
-
-Arguments:
-
- PropertyRequest -
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
- CFmMiniportWaveRT* pWaveHelper = reinterpret_cast<CFmMiniportWaveRT*>(PropertyRequest->MajorTarget);
-
- if (pWaveHelper == NULL)
- {
- return STATUS_INVALID_PARAMETER;
- }
-
- pWaveHelper->AddRef();
-
- if (pWaveHelper->m_DeviceType == eFmRxDevice &&
- IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_FMRXControl))
- {
- switch (PropertyRequest->PropertyItem->Id)
- {
- case KSPROPERTY_FMRX_STATE:
- ntStatus = pWaveHelper->PropertyHandler_FmRxState(PropertyRequest);
- break;
-
- default:
- DPF(D_TERSE, ("[PropertyHandler_FmRxWaveFilter: Invalid Device Request"));
- }
- }
- else
- {
- ntStatus = PropertyHandler_WaveFilter(PropertyRequest);
- }
-
- pWaveHelper->Release();
-
- return ntStatus;
-} // PropertyHandler_FmRxWaveFilter
-
-//=============================================================================
-#pragma code_seg("PAGE")
-NTSTATUS
-CFmMiniportWaveRT::PropertyHandler_FmRxState
-(
-_In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-{
- NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
-
- PAGED_CODE();
-
- DPF_ENTER(("[CFmMiniportWaveRT::PropertyHandler_FmRxState]"));
-
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ULONG flags = PropertyRequest->PropertyItem->Flags;
- ntStatus = PropertyHandler_BasicSupport(PropertyRequest, flags, VT_ILLEGAL);
- }
- else
- {
- ntStatus =
- ValidatePropertyParams
- (
- PropertyRequest,
- sizeof(BOOL),
- 0
- );
-
- if (NT_SUCCESS(ntStatus))
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- BOOL* fmrxState = (BOOL*)PropertyRequest->Value;
- *fmrxState = m_bFmRxState;
- ntStatus = STATUS_SUCCESS;
- }
- else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
- {
- BOOL fmrxNewState = *(BOOL*)PropertyRequest->Value;
- if (fmrxNewState == m_bFmRxState)
- {
- ntStatus = STATUS_SUCCESS;
- }
- else
- {
- // Turn on FM hardware
- m_bFmRxState = fmrxNewState;
-
- // NOTE: Set the Jack state to Active ONLY if the driver supports
- // recording FM data. If the driver doesn't support recording FM
- // data, the jack state should never be changed to Active
- ntStatus = UpdateTopologyJackState(m_bFmRxState);
-
- // When we're using FM, we need idle power management disabled.
- // passing true here enables power management, false disables.
- // when FM is enabled (true), we want to pass false do disable idle
- // power management
- m_pAdapterCommon->SetIdlePowerManagement(m_pMiniportPair, m_bFmRxState?FALSE:TRUE);
- }
- }
- else
- {
- ntStatus = STATUS_INVALID_PARAMETER;
- }
- }
- }
-
- return ntStatus;
-} // PropertyHandler_FmRxState
-
-
-
-#pragma code_seg("PAGE")
-NTSTATUS
-CFmMiniportWaveRT::UpdateTopologyJackState
-(
- _In_ BOOL NewState
-)
-{
- PAGED_CODE ();
- NTSTATUS ntStatus = STATUS_SUCCESS;
- IUnknown *pUnknown = NULL;
- IFmTopology *pFmTopology = NULL;
-
- // GetFilters returns the topology port, then topology miniport, then wave port, then wave miniport.
- // we only need the topology miniport.
- ntStatus = m_pAdapterCommon->GetFilters(m_pMiniportPair, NULL, &pUnknown, NULL, NULL);
- if (NT_SUCCESS(ntStatus))
- {
- ntStatus = pUnknown->QueryInterface(IID_IFmTopology, (PVOID *)&pFmTopology);
- if (NT_SUCCESS(ntStatus))
- {
- ntStatus = pFmTopology->UpdateTopologyJackState(NewState);
- }
- }
-
- SAFE_RELEASE(pFmTopology);
- SAFE_RELEASE(pUnknown);
-
- return STATUS_SUCCESS;
-}
-#pragma code_seg()
-
-
-//=============================================================================
-#pragma code_seg()
-STDMETHODIMP_(void)
-CFmMiniportWaveRT::PowerChangeState
-(
- _In_ POWER_STATE NewState
-)
-{
- DPF_ENTER(("[CFmMiniportWaveRT::PowerChangeState]"));
- UNREFERENCED_PARAMETER(NewState);
-
- /*
- Turn on and off fm specific hardware here, if applicable.
- */
-
-} // PowerStateChange
-
-//=============================================================================
-#pragma code_seg()
-STDMETHODIMP_(NTSTATUS)
-CFmMiniportWaveRT::QueryDeviceCapabilities
-(
- _Inout_updates_bytes_(sizeof(DEVICE_CAPABILITIES)) PDEVICE_CAPABILITIES PowerDeviceCaps
-)
-{
- UNREFERENCED_PARAMETER(PowerDeviceCaps);
-
- /*
- Unused at the miniport layer. Any device capabilities should be reported in CAdapterCommon
- */
-
- return (STATUS_SUCCESS);
-} // QueryDeviceCapabilities
-
-//=============================================================================
-#pragma code_seg()
-STDMETHODIMP_(NTSTATUS)
-CFmMiniportWaveRT::QueryPowerChangeState
-(
- _In_ POWER_STATE NewStateQuery
-)
-{
- UNREFERENCED_PARAMETER(NewStateQuery);
-
- DPF_ENTER(("[CFmMiniportWaveRT::QueryPowerChangeState]"));
-
- // if we're in a call state other than disabled, then we need the hardware turned on
- if (m_bFmRxState)
- {
- return STATUS_RESOURCE_IN_USE;
- }
-
- return STATUS_SUCCESS;
-} // QueryPowerChangeState
-
-
diff --git a/audio/sysvad/PhoneAudioSample/FMWave.h b/audio/sysvad/PhoneAudioSample/FMWave.h
deleted file mode 100644
index 1134b680..00000000
--- a/audio/sysvad/PhoneAudioSample/FMWave.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- fmwave.h
-
-Abstract:
-
- Definition of wavert miniport class for fm
-
---*/
-
-#include "MinWaveRT.h"
-
-#ifndef _SYSVAD_FMMINWAVERT_H_
-#define _SYSVAD_FMMINWAVERT_H_
-
-NTSTATUS
-CreateFmMiniportWaveRT
-(
- _Out_ PUNKNOWN * Unknown,
- _In_ REFCLSID,
- _In_opt_ PUNKNOWN UnknownOuter,
- _When_((PoolType & NonPagedPoolMustSucceed) != 0,
- __drv_reportError("Must succeed pool allocations are forbidden. "
- "Allocation failures cause a system crash"))
- _In_ POOL_TYPE PoolType,
- _In_ PUNKNOWN UnknownAdapter,
- _In_opt_ PVOID DeviceContext,
- _In_ PENDPOINT_MINIPAIR MiniportPair
-);
-
-//=============================================================================
-// Classes
-//=============================================================================
-///////////////////////////////////////////////////////////////////////////////
-// CFmMiniportWaveRT
-//
-class CFmMiniportWaveRT :
- public CMiniportWaveRT,
- public IAdapterPowerManagement
-{
-private:
- BOOL m_bFmRxState;
-
-public:
- DECLARE_STD_UNKNOWN();
- IMP_IAdapterPowerManagement;
-
- CFmMiniportWaveRT(
- _In_ PUNKNOWN UnknownAdapter,
- _In_ PENDPOINT_MINIPAIR MiniportPair,
- _In_opt_ PVOID DeviceContext
- )
- :CMiniportWaveRT(UnknownAdapter, MiniportPair, DeviceContext),
- m_bFmRxState(FALSE)
- {
- }
-
- ~CFmMiniportWaveRT();
-
- friend NTSTATUS PropertyHandler_FmRxWaveFilter
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
-public:
- NTSTATUS PropertyHandler_FmRxState
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
-private:
- NTSTATUS UpdateTopologyJackState
- (
- _In_ BOOL NewState
- );
-};
-typedef CFmMiniportWaveRT *PCFmMiniportWaveRT;
-
-#endif // _SYSVAD_FMMINWAVERT_H_
-
diff --git a/audio/sysvad/PhoneAudioSample/handsetmictopo.cpp b/audio/sysvad/PhoneAudioSample/handsetmictopo.cpp
deleted file mode 100644
index 4e181c62..00000000
--- a/audio/sysvad/PhoneAudioSample/handsetmictopo.cpp
+++ /dev/null
@@ -1,274 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- handsetmictopo.cpp
-
-Abstract:
-
- Implementation of topology miniport for the handset mic (internal).
-
---*/
-
-#pragma warning (disable : 4127)
-
-#include <sysvad.h>
-#include "simple.h"
-#include "mintopo.h"
-#include "handsetmictopo.h"
-#include "handsetmictoptable.h"
-
-
-#pragma code_seg("PAGE")
-
-//=============================================================================
-NTSTATUS
-PropertyHandler_HandsetMicJackDescription
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
- Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION )
-
-Arguments:
-
- PropertyRequest -
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandler_HandsetMicJackDescription]"));
-
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
- ULONG nPinId = (ULONG)-1;
-
- ULONG cJackDescriptions = ARRAYSIZE(HandsetMicJackDescriptions);
- PKSJACK_DESCRIPTION * JackDescriptions = HandsetMicJackDescriptions;
-
- if (PropertyRequest->InstanceSize >= sizeof(ULONG))
- {
- nPinId = *(PULONG(PropertyRequest->Instance));
-
- if ((nPinId < cJackDescriptions) && (JackDescriptions[nPinId] != NULL))
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ntStatus =
- PropertyHandler_BasicSupport
- (
- PropertyRequest,
- KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET,
- VT_ILLEGAL
- );
- }
- else
- {
- ULONG cbNeeded = sizeof(KSMULTIPLE_ITEM) + sizeof(KSJACK_DESCRIPTION);
-
- if (PropertyRequest->ValueSize == 0)
- {
- PropertyRequest->ValueSize = cbNeeded;
- ntStatus = STATUS_BUFFER_OVERFLOW;
- }
- else if (PropertyRequest->ValueSize < cbNeeded)
- {
- ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value;
- PKSJACK_DESCRIPTION pDesc = (PKSJACK_DESCRIPTION)(pMI+1);
-
- pMI->Size = cbNeeded;
- pMI->Count = 1;
-
- RtlCopyMemory(pDesc, JackDescriptions[nPinId], sizeof(KSJACK_DESCRIPTION));
- ntStatus = STATUS_SUCCESS;
- }
- }
- }
- }
- }
-
- return ntStatus;
-}
-
-//=============================================================================
-NTSTATUS
-PropertyHandler_HandsetMicJackDescription2
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
- Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION2 )
-
-Arguments:
-
- PropertyRequest -
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandler_HandsetMicJackDescription2]"));
-
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
- ULONG nPinId = (ULONG)-1;
-
- ULONG cJackDescriptions = ARRAYSIZE(HandsetMicJackDescriptions);
- PKSJACK_DESCRIPTION * JackDescriptions = HandsetMicJackDescriptions;
-
- if (PropertyRequest->InstanceSize >= sizeof(ULONG))
- {
- nPinId = *(PULONG(PropertyRequest->Instance));
-
- if ((nPinId < cJackDescriptions) && (JackDescriptions[nPinId] != NULL))
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ntStatus =
- PropertyHandler_BasicSupport
- (
- PropertyRequest,
- KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET,
- VT_ILLEGAL
- );
- }
- else
- {
- ULONG cbNeeded = sizeof(KSMULTIPLE_ITEM) + sizeof(KSJACK_DESCRIPTION2);
-
- if (PropertyRequest->ValueSize == 0)
- {
- PropertyRequest->ValueSize = cbNeeded;
- ntStatus = STATUS_BUFFER_OVERFLOW;
- }
- else if (PropertyRequest->ValueSize < cbNeeded)
- {
- ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value;
- PKSJACK_DESCRIPTION2 pDesc = (PKSJACK_DESCRIPTION2)(pMI+1);
-
- pMI->Size = cbNeeded;
- pMI->Count = 1;
-
- RtlZeroMemory(pDesc, sizeof(KSJACK_DESCRIPTION2));
-
- //
- // Specifies the lower 16 bits of the DWORD parameter. This parameter indicates whether
- // the jack is currently active, streaming, idle, or hardware not ready.
- //
- pDesc->DeviceStateInfo = 0;
-
- //
- // From MSDN:
- // "If an audio device lacks jack presence detection, the IsConnected member of
- // the KSJACK_DESCRIPTION structure must always be set to TRUE. To remove the
- // ambiguity that results from this dual meaning of the TRUE value for IsConnected,
- // a client application can call IKsJackDescription2::GetJackDescription2 to read
- // the JackCapabilities flag of the KSJACK_DESCRIPTION2 structure. If this flag has
- // the JACKDESC2_PRESENCE_DETECT_CAPABILITY bit set, it indicates that the endpoint
- // does in fact support jack presence detection. In that case, the return value of
- // the IsConnected member can be interpreted to accurately reflect the insertion status
- // of the jack."
- //
- // Bit definitions:
- // 0x00000001 - JACKDESC2_PRESENCE_DETECT_CAPABILITY
- // 0x00000002 - JACKDESC2_DYNAMIC_FORMAT_CHANGE_CAPABILITY
- //
- pDesc->JackCapabilities = 0;
-
- ntStatus = STATUS_SUCCESS;
- }
- }
- }
- }
- }
-
- return ntStatus;
-}
-
-//=============================================================================
-NTSTATUS
-PropertyHandler_HandsetMicTopoFilter
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
- Redirects property request to miniport object
-
-Arguments:
-
- PropertyRequest -
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandler_HandsetMicTopoFilter]"));
-
- // PropertryRequest structure is filled by portcls.
- // MajorTarget is a pointer to miniport object for miniports.
- //
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
-
- //
- // This line shows how to get a pointer to the miniport topology object.
- //
- PCMiniportTopology pMiniport = (PCMiniportTopology)PropertyRequest->MajorTarget;
- UNREFERENCED_VAR(pMiniport);
-
- if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Jack))
- {
- if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION)
- {
- ntStatus = PropertyHandler_HandsetMicJackDescription(PropertyRequest);
- }
- else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION2)
- {
- ntStatus = PropertyHandler_HandsetMicJackDescription2(PropertyRequest);
- }
- }
-
- return ntStatus;
-} // PropertyHandler_HandsetMicTopoFilter
-
-#pragma code_seg()
-
diff --git a/audio/sysvad/PhoneAudioSample/handsetmictopo.h b/audio/sysvad/PhoneAudioSample/handsetmictopo.h
deleted file mode 100644
index 07c8ba27..00000000
--- a/audio/sysvad/PhoneAudioSample/handsetmictopo.h
+++ /dev/null
@@ -1,21 +0,0 @@
-
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- handsetmictopo.h
-
-Abstract:
-
- Declaration of topology miniport for the handset mic (internal).
-
---*/
-
-#ifndef _SYSVAD_HANDSETMICTOPO_H_
-#define _SYSVAD_HANDSETMICTOPO_H_
-
-NTSTATUS PropertyHandler_HandsetMicTopoFilter(_In_ PPCPROPERTY_REQUEST PropertyRequest);
-
-#endif // _SYSVAD_HANDSETMICTOPO_H_
diff --git a/audio/sysvad/PhoneAudioSample/handsetmictoptable.h b/audio/sysvad/PhoneAudioSample/handsetmictoptable.h
deleted file mode 100644
index 5fd70010..00000000
--- a/audio/sysvad/PhoneAudioSample/handsetmictoptable.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- handsetmictopotable.h
-
-Abstract:
-
- Declaration of topology table for the handset mic (internal)
-
---*/
-
-#ifndef _SYSVAD_HANDSETMICTOPTABLE_H_
-#define _SYSVAD_HANDSETMICTOPTABLE_H_
-
-// Function declarations.
-NTSTATUS
-PropertyHandler_HandsetMicTopoFilter(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
-//=============================================================================
-static
-KSDATARANGE HandsetMicTopoPinDataRangesBridge[] =
-{
- {
- sizeof(KSDATARANGE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
- }
-};
-
-//=============================================================================
-static
-PKSDATARANGE HandsetMicTopoPinDataRangePointersBridge[] =
-{
- &HandsetMicTopoPinDataRangesBridge[0]
-};
-
-//=============================================================================
-static
-PCPIN_DESCRIPTOR HandsetMicTopoMiniportPins[] =
-{
- // KSPIN - topology filter in-pin
- {
- 0,
- 0,
- 0, // InstanceCount
- NULL, // AutomationTable
- { // KsPinDescriptor
- 0, // InterfacesCount
- NULL, // Interfaces
- 0, // MediumsCount
- NULL, // Mediums
- SIZEOF_ARRAY(HandsetMicTopoPinDataRangePointersBridge),// DataRangesCount
- HandsetMicTopoPinDataRangePointersBridge, // DataRanges
- KSPIN_DATAFLOW_IN, // DataFlow
- KSPIN_COMMUNICATION_NONE, // Communication
- &KSNODETYPE_HANDSET, // Category
- NULL, // Name
- 0 // Reserved
- }
- },
-
- // KSPIN - topology filter out-in
- {
- 0,
- 0,
- 0, // InstanceCount
- NULL, // AutomationTable
- { // KsPinDescriptor
- 0, // InterfacesCount
- NULL, // Interfaces
- 0, // MediumsCount
- NULL, // Mediums
- SIZEOF_ARRAY(HandsetMicTopoPinDataRangePointersBridge),// DataRangesCount
- HandsetMicTopoPinDataRangePointersBridge, // DataRanges
- KSPIN_DATAFLOW_OUT, // DataFlow
- KSPIN_COMMUNICATION_NONE, // Communication
- &KSCATEGORY_AUDIO, // Category
- NULL, // Name
- 0 // Reserved
- }
- }
-};
-
-//=============================================================================
-static
-KSJACK_DESCRIPTION HandsetMicJackDesc =
-{
- KSAUDIO_SPEAKER_MONO,
- 0x0000, // no color
- eConnTypeUnknown,
- eGeoLocTop,
- eGenLocInternal,
- ePortConnIntegratedDevice,
- TRUE
-};
-
-//=============================================================================
-// Only return a KSJACK_DESCRIPTION for the physical bridge pin.
-static
-PKSJACK_DESCRIPTION HandsetMicJackDescriptions[] =
-{
- &HandsetMicJackDesc,
- NULL
-};
-
-//=============================================================================
-static
-PCPROPERTY_ITEM HandsetMicPropertiesVolume[] =
-{
- {
- &KSPROPSETID_Audio,
- KSPROPERTY_AUDIO_VOLUMELEVEL,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_Topology
- }
-};
-
-DEFINE_PCAUTOMATION_TABLE_PROP(AutomationHandsetMicVolume, HandsetMicPropertiesVolume);
-
-//=============================================================================
-static
-PCPROPERTY_ITEM HandsetMicPropertiesMute[] =
-{
- {
- &KSPROPSETID_Audio,
- KSPROPERTY_AUDIO_MUTE,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_Topology
- }
-};
-
-DEFINE_PCAUTOMATION_TABLE_PROP(AutomationHandsetMicMute, HandsetMicPropertiesMute);
-
-//=============================================================================
-static
-PCPROPERTY_ITEM HandsetMicPropertiesPeakMeter[] =
-{
- {
- &KSPROPSETID_Audio,
- KSPROPERTY_AUDIO_PEAKMETER2,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_Topology
- },
- {
- &KSPROPSETID_Audio,
- KSPROPERTY_AUDIO_CPU_RESOURCES,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_Topology
- }
-};
-
-DEFINE_PCAUTOMATION_TABLE_PROP(AutomationHandsetMicPeakMeter, HandsetMicPropertiesPeakMeter);
-
-//=============================================================================
-static
-PCNODE_DESCRIPTOR HandsetMicTopologyNodes[] =
-{
- // KSNODE_TOPO_VOLUME
- {
- 0, // Flags
- &AutomationHandsetMicVolume, // AutomationTable
- &KSNODETYPE_VOLUME, // Type
- &KSAUDFNAME_MIC_VOLUME // Name
- },
- // KSNODE_TOPO_MUTE
- {
- 0, // Flags
- &AutomationHandsetMicMute, // AutomationTable
- &KSNODETYPE_MUTE, // Type
- &KSAUDFNAME_MIC_MUTE // Name
- },
- // KSNODE_TOPO_PEAKMETER
- {
- 0, // Flags
- &AutomationHandsetMicPeakMeter, // AutomationTable
- &KSNODETYPE_PEAKMETER, // Type
- &KSAUDFNAME_PEAKMETER // Name
- }
-};
-
-C_ASSERT( KSNODE_TOPO_VOLUME == 0 );
-C_ASSERT( KSNODE_TOPO_MUTE == 1 );
-C_ASSERT( KSNODE_TOPO_PEAKMETER == 2 );
-
-//=============================================================================
-static
-PCCONNECTION_DESCRIPTOR HandsetMicMiniportConnections[] =
-{
- // FromNode, FromPin, ToNode, ToPin
- { PCFILTER_NODE, KSPIN_TOPO_MIC_ELEMENTS, KSNODE_TOPO_VOLUME, 1 },
- { KSNODE_TOPO_VOLUME, 0, KSNODE_TOPO_MUTE, 1 },
- { KSNODE_TOPO_MUTE, 0, KSNODE_TOPO_PEAKMETER, 1 },
- { KSNODE_TOPO_PEAKMETER, 0, PCFILTER_NODE, KSPIN_TOPO_BRIDGE }
-};
-
-
-//=============================================================================
-static
-PCPROPERTY_ITEM HandsetMicPropertiesTopoFilter[] =
-{
- {
- &KSPROPSETID_Jack,
- KSPROPERTY_JACK_DESCRIPTION,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_HandsetMicTopoFilter
- },
- {
- &KSPROPSETID_Jack,
- KSPROPERTY_JACK_DESCRIPTION2,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_HandsetMicTopoFilter
- }
-};
-
-DEFINE_PCAUTOMATION_TABLE_PROP(AutomationHandsetMicTopoFilter, HandsetMicPropertiesTopoFilter);
-
-//=============================================================================
-static
-PCFILTER_DESCRIPTOR HandsetMicTopoMiniportFilterDescriptor =
-{
- 0, // Version
- &AutomationHandsetMicTopoFilter, // AutomationTable
- sizeof(PCPIN_DESCRIPTOR), // PinSize
- SIZEOF_ARRAY(HandsetMicTopoMiniportPins), // PinCount
- HandsetMicTopoMiniportPins, // Pins
- sizeof(PCNODE_DESCRIPTOR), // NodeSize
- SIZEOF_ARRAY(HandsetMicTopologyNodes), // NodeCount
- HandsetMicTopologyNodes, // Nodes
- SIZEOF_ARRAY(HandsetMicMiniportConnections), // ConnectionCount
- HandsetMicMiniportConnections, // Connections
- 0, // CategoryCount
- NULL // Categories
-};
-
-#endif // _SYSVAD_HANDSETMICTOPTABLE_H_
-
diff --git a/audio/sysvad/PhoneAudioSample/handsetmicwavtable.h b/audio/sysvad/PhoneAudioSample/handsetmicwavtable.h
deleted file mode 100644
index 5470e521..00000000
--- a/audio/sysvad/PhoneAudioSample/handsetmicwavtable.h
+++ /dev/null
@@ -1,447 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- handsetmicwavtable.h
-
-Abstract:
-
- Declaration of wave miniport tables for the handset microphone.
-
---*/
-
-#ifndef _SYSVAD_HANDSETMICWAVTABLE_H_
-#define _SYSVAD_HANDSETMICWAVTABLE_H_
-
-//
-// Handset microphone (internal) range.
-//
-#define HANDSETMIC_DEVICE_MAX_CHANNELS 1 // Max Channels.
-#define HANDSETMIC_MIN_BITS_PER_SAMPLE_PCM 16 // Min Bits Per Sample
-#define HANDSETMIC_MAX_BITS_PER_SAMPLE_PCM 16 // Max Bits Per Sample
-#define HANDSETMIC_MIN_SAMPLE_RATE 8000 // Min Sample Rate
-#define HANDSETMIC_MAX_SAMPLE_RATE 48000 // Max Sample Rate
-
-//
-// Max # of pin instances.
-//
-#define HANDSETMIC_MAX_INPUT_STREAMS 4
-
-//=============================================================================
-static
-KSDATAFORMAT_WAVEFORMATEXTENSIBLE HandsetMicPinSupportedDeviceFormats[] =
-{
- { // 0
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 1,
- 8000,
- 16000,
- 2,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_MONO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 1
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 1,
- 11025,
- 22050,
- 2,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_MONO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 2
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 1,
- 16000,
- 32000,
- 2,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_MONO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 3
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 1,
- 22050,
- 44100,
- 2,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_MONO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 4
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 1,
- 24000,
- 48000,
- 2,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_MONO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 5
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 1,
- 32000,
- 64000,
- 2,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_MONO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 6
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 1,
- 44100,
- 88200,
- 2,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_MONO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 7
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 1,
- 48000,
- 96000,
- 2,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_MONO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- }
-};
-
-//
-// Supported modes (only on streaming pins).
-//
-static
-MODE_AND_DEFAULT_FORMAT HandsetMicPinSupportedDeviceModes[] =
-{
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_RAW,
- &HandsetMicPinSupportedDeviceFormats[SIZEOF_ARRAY(HandsetMicPinSupportedDeviceFormats) - 1].DataFormat, // 48KHz
- },
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_DEFAULT,
- &HandsetMicPinSupportedDeviceFormats[SIZEOF_ARRAY(HandsetMicPinSupportedDeviceFormats) - 1].DataFormat, // 48KHz
- },
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_SPEECH,
- &HandsetMicPinSupportedDeviceFormats[2].DataFormat, // 16KHz
- },
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS,
- &HandsetMicPinSupportedDeviceFormats[4].DataFormat, // 24KHz
- }
-};
-
-//
-// The entries here must follow the same order as the filter's pin
-// descriptor array.
-//
-static
-PIN_DEVICE_FORMATS_AND_MODES HandsetMicPinDeviceFormatsAndModes[] =
-{
- {
- BridgePin,
- NULL,
- 0,
- NULL,
- 0
- },
- {
- SystemCapturePin,
- HandsetMicPinSupportedDeviceFormats,
- SIZEOF_ARRAY(HandsetMicPinSupportedDeviceFormats),
- HandsetMicPinSupportedDeviceModes,
- SIZEOF_ARRAY(HandsetMicPinSupportedDeviceModes)
- }
-};
-
-//=============================================================================
-static
-KSDATARANGE_AUDIO HandsetMicPinDataRangesStream[] =
-{
- {
- {
- sizeof(KSDATARANGE_AUDIO),
- KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- HANDSETMIC_DEVICE_MAX_CHANNELS,
- HANDSETMIC_MIN_BITS_PER_SAMPLE_PCM,
- HANDSETMIC_MAX_BITS_PER_SAMPLE_PCM,
- HANDSETMIC_MIN_SAMPLE_RATE,
- HANDSETMIC_MAX_SAMPLE_RATE
- },
-};
-
-static
-PKSDATARANGE HandsetMicPinDataRangePointersStream[] =
-{
- PKSDATARANGE(&HandsetMicPinDataRangesStream[0]),
- PKSDATARANGE(&PinDataRangeAttributeList),
-};
-
-//=============================================================================
-static
-KSDATARANGE HandsetMicPinDataRangesBridge[] =
-{
- {
- sizeof(KSDATARANGE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
- }
-};
-
-static
-PKSDATARANGE HandsetMicPinDataRangePointersBridge[] =
-{
- &HandsetMicPinDataRangesBridge[0]
-};
-
-//=============================================================================
-static
-PCPIN_DESCRIPTOR HandsetMicWaveMiniportPins[] =
-{
- // Wave In Bridge Pin (Capture - From Topology) KSPIN_WAVE_BRIDGE
- {
- 0,
- 0,
- 0,
- NULL,
- {
- 0,
- NULL,
- 0,
- NULL,
- SIZEOF_ARRAY(HandsetMicPinDataRangePointersBridge),
- HandsetMicPinDataRangePointersBridge,
- KSPIN_DATAFLOW_IN,
- KSPIN_COMMUNICATION_NONE,
- &KSCATEGORY_AUDIO,
- NULL,
- 0
- }
- },
-
- // Wave In Streaming Pin (Capture) KSPIN_WAVEIN_HOST
- {
- HANDSETMIC_MAX_INPUT_STREAMS,
- HANDSETMIC_MAX_INPUT_STREAMS,
- 0,
- NULL,
- {
- 0,
- NULL,
- 0,
- NULL,
- SIZEOF_ARRAY(HandsetMicPinDataRangePointersStream),
- HandsetMicPinDataRangePointersStream,
- KSPIN_DATAFLOW_OUT,
- KSPIN_COMMUNICATION_SINK,
- &KSCATEGORY_AUDIO,
- &KSAUDFNAME_RECORDING_CONTROL,
- 0
- }
- }
-};
-
-//=============================================================================
-static
-PCNODE_DESCRIPTOR HandsetMicWaveMiniportNodes[] =
-{
- // KSNODE_WAVE_ADC
- {
- 0, // Flags
- NULL, // AutomationTable
- &KSNODETYPE_ADC, // Type
- NULL // Name
- }
-};
-
-//=============================================================================
-static
-PCCONNECTION_DESCRIPTOR HandsetMicWaveMiniportConnections[] =
-{
- { PCFILTER_NODE, KSPIN_WAVE_BRIDGE, KSNODE_WAVE_ADC, 1 },
- { KSNODE_WAVE_ADC, 0, PCFILTER_NODE, KSPIN_WAVEIN_HOST }
-};
-
-//=============================================================================
-static
-PCPROPERTY_ITEM PropertiesHandsetMicWaveFilter[] =
-{
- {
- &KSPROPSETID_General,
- KSPROPERTY_GENERAL_COMPONENTID,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_WaveFilter
- },
- {
- &KSPROPSETID_Pin,
- KSPROPERTY_PIN_PROPOSEDATAFORMAT,
- KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_WaveFilter
- },
- {
- &KSPROPSETID_Pin,
- KSPROPERTY_PIN_PROPOSEDATAFORMAT2,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_WaveFilter
- }
-};
-
-DEFINE_PCAUTOMATION_TABLE_PROP(AutomationHandsetMicWaveFilter, PropertiesHandsetMicWaveFilter);
-
-//=============================================================================
-static
-PCFILTER_DESCRIPTOR HandsetMicWaveMiniportFilterDescriptor =
-{
- 0, // Version
- &AutomationHandsetMicWaveFilter, // AutomationTable
- sizeof(PCPIN_DESCRIPTOR), // PinSize
- SIZEOF_ARRAY(HandsetMicWaveMiniportPins), // PinCount
- HandsetMicWaveMiniportPins, // Pins
- sizeof(PCNODE_DESCRIPTOR), // NodeSize
- SIZEOF_ARRAY(HandsetMicWaveMiniportNodes), // NodeCount
- HandsetMicWaveMiniportNodes, // Nodes
- SIZEOF_ARRAY(HandsetMicWaveMiniportConnections), // ConnectionCount
- HandsetMicWaveMiniportConnections, // Connections
- 0, // CategoryCount
- NULL // Categories - use defaults (audio, render, capture)
-};
-
-#endif // _SYSVAD_HANDSETMICWAVTABLE_H_
diff --git a/audio/sysvad/PhoneAudioSample/handsetspeakertopo.h b/audio/sysvad/PhoneAudioSample/handsetspeakertopo.h
deleted file mode 100644
index 7b220f70..00000000
--- a/audio/sysvad/PhoneAudioSample/handsetspeakertopo.h
+++ /dev/null
@@ -1,86 +0,0 @@
-
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- handsetspeakertopo.h
-
-Abstract:
-
- Declaration of topology miniport for the handsetspeaker endpoint.
-
---*/
-
-#ifndef _SYSVAD_HANDSETSPEAKERTOPO_H_
-#define _SYSVAD_HANDSETSPEAKERTOPO_H_
-
-#include "basetopo.h"
-
-//=============================================================================
-// Classes
-//=============================================================================
-
-///////////////////////////////////////////////////////////////////////////////
-// CHandsetSpeakerMiniportTopology
-//
-
-class CHandsetSpeakerMiniportTopology :
- public CMiniportTopologySYSVAD,
- public IMiniportTopology,
- public CUnknown
-{
- public:
- DECLARE_STD_UNKNOWN();
- CHandsetSpeakerMiniportTopology
- (
- _In_opt_ PUNKNOWN UnknownOuter,
- _In_ PCFILTER_DESCRIPTOR *FilterDesc,
- _In_ USHORT DeviceMaxChannels
- )
- : CUnknown(UnknownOuter),
- CMiniportTopologySYSVAD(FilterDesc, DeviceMaxChannels)
- {}
-
- ~CHandsetSpeakerMiniportTopology();
-
- IMP_IMiniportTopology;
-
- NTSTATUS PropertyHandlerJackSinkInfo
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
- NTSTATUS PropertyHandlerJackDescription
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
- NTSTATUS PropertyHandlerJackDescription2
- (
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-};
-
-typedef CHandsetSpeakerMiniportTopology *PCHandsetSpeakerMiniportTopology;
-
-
-NTSTATUS
-CreateHandsetSpeakerMiniportTopology(
- _Out_ PUNKNOWN * Unknown,
- _In_ REFCLSID,
- _In_opt_ PUNKNOWN UnknownOuter,
- _When_((PoolType & NonPagedPoolMustSucceed) != 0,
- __drv_reportError("Must succeed pool allocations are forbidden. "
- "Allocation failures cause a system crash"))
- _In_ POOL_TYPE PoolType,
- _In_ PUNKNOWN UnknownAdapter,
- _In_opt_ PVOID DeviceContext,
- _In_ PENDPOINT_MINIPAIR MiniportPair
- );
-
-NTSTATUS PropertyHandler_HandsetSpeakerTopoFilter(_In_ PPCPROPERTY_REQUEST PropertyRequest);
-
-#endif // _SYSVAD_HANDSETSPEAKERTOPO_H_
-
diff --git a/audio/sysvad/PhoneAudioSample/handsetspeakertoptable.h b/audio/sysvad/PhoneAudioSample/handsetspeakertoptable.h
deleted file mode 100644
index 68873e61..00000000
--- a/audio/sysvad/PhoneAudioSample/handsetspeakertoptable.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- handsetspeakertoptable.h
-
-Abstract:
-
- Declaration of topology tables for the handsetspeaker endpoint.
-
---*/
-
-#ifndef _SYSVAD_HANDSETSPEAKERTOPTABLE_H_
-#define _SYSVAD_HANDSETSPEAKERTOPTABLE_H_
-
-//=============================================================================
-static
-KSDATARANGE HandsetSpeakerTopoPinDataRangesBridge[] =
-{
- {
- sizeof(KSDATARANGE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
- }
-};
-
-//=============================================================================
-static
-PKSDATARANGE HandsetSpeakerTopoPinDataRangePointersBridge[] =
-{
- &HandsetSpeakerTopoPinDataRangesBridge[0]
-};
-
-//=============================================================================
-static
-PCPIN_DESCRIPTOR HandsetSpeakerTopoMiniportPins[] =
-{
- // KSPIN_TOPO_WAVEOUT_SOURCE
- {
- 0,
- 0,
- 0, // InstanceCount
- NULL, // AutomationTable
- { // KsPinDescriptor
- 0, // InterfacesCount
- NULL, // Interfaces
- 0, // MediumsCount
- NULL, // Mediums
- SIZEOF_ARRAY(HandsetSpeakerTopoPinDataRangePointersBridge), // DataRangesCount
- HandsetSpeakerTopoPinDataRangePointersBridge, // DataRanges
- KSPIN_DATAFLOW_IN, // DataFlow
- KSPIN_COMMUNICATION_NONE, // Communication
- &KSCATEGORY_AUDIO, // Category
- NULL, // Name
- 0 // Reserved
- }
- },
- // KSPIN_TOPO_LINEOUT_DEST
- {
- 0,
- 0,
- 0, // InstanceCount
- NULL, // AutomationTable
- { // KsPinDescriptor
- 0, // InterfacesCount
- NULL, // Interfaces
- 0, // MediumsCount
- NULL, // Mediums
- SIZEOF_ARRAY(HandsetSpeakerTopoPinDataRangePointersBridge), // DataRangesCount
- HandsetSpeakerTopoPinDataRangePointersBridge, // DataRanges
- KSPIN_DATAFLOW_OUT, // DataFlow
- KSPIN_COMMUNICATION_NONE, // Communication
- &KSNODETYPE_HANDSET, // Category
- NULL, // Name
- 0 // Reserved
- }
- }
-};
-
-//=============================================================================
-static
-KSJACK_DESCRIPTION HandsetSpeakerJackDesc =
-{
- KSAUDIO_SPEAKER_MONO,
- 0x0000, // no color
- eConnTypeUnknown,
- eGeoLocBottom,
- eGenLocInternal,
- ePortConnIntegratedDevice,
- TRUE
-};
-
-// Only return a KSJACK_DESCRIPTION for the physical bridge pin.
-static
-PKSJACK_DESCRIPTION HandsetSpeakerJackDescriptions[] =
-{
- NULL,
- &HandsetSpeakerJackDesc
-};
-
-//=============================================================================
-static
-PCCONNECTION_DESCRIPTOR HandsetSpeakerTopoMiniportConnections[] =
-{
- // FromNode, FromPin, ToNode, ToPin
- { PCFILTER_NODE, KSPIN_TOPO_WAVEOUT_SOURCE, PCFILTER_NODE, KSPIN_TOPO_LINEOUT_DEST}
-};
-
-
-//=============================================================================
-static
-PCPROPERTY_ITEM PropertiesHandsetSpeakerTopoFilter[] =
-{
- {
- &KSPROPSETID_Jack,
- KSPROPERTY_JACK_DESCRIPTION,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_HandsetSpeakerTopoFilter
- },
- {
- &KSPROPSETID_Jack,
- KSPROPERTY_JACK_DESCRIPTION2,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_HandsetSpeakerTopoFilter
- }
-};
-
-DEFINE_PCAUTOMATION_TABLE_PROP(AutomationHandsetSpeakerTopoFilter, PropertiesHandsetSpeakerTopoFilter);
-
-//=============================================================================
-static
-PCFILTER_DESCRIPTOR HandsetSpeakerTopoMiniportFilterDescriptor =
-{
- 0, // Version
- &AutomationHandsetSpeakerTopoFilter, // AutomationTable
- sizeof(PCPIN_DESCRIPTOR), // PinSize
- SIZEOF_ARRAY(HandsetSpeakerTopoMiniportPins), // PinCount
- HandsetSpeakerTopoMiniportPins, // Pins
- sizeof(PCNODE_DESCRIPTOR), // NodeSize
- 0, // NodeCount
- NULL, // Nodes
- SIZEOF_ARRAY(HandsetSpeakerTopoMiniportConnections), // ConnectionCount
- HandsetSpeakerTopoMiniportConnections, // Connections
- 0, // CategoryCount
- NULL // Categories
-};
-
-#endif // _SYSVAD_HANDSETSPEAKERTOPTABLE_H_
-
-
diff --git a/audio/sysvad/PhoneAudioSample/handsetspeakerwavtable.h b/audio/sysvad/PhoneAudioSample/handsetspeakerwavtable.h
deleted file mode 100644
index 73548626..00000000
--- a/audio/sysvad/PhoneAudioSample/handsetspeakerwavtable.h
+++ /dev/null
@@ -1,550 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- handsetspeakerwavtable.h
-
-Abstract:
-
- Declaration of wave miniport tables for the handsetspeaker endpoint.
-
- Note: the HANDSETSPEAKER in this sample shows how to do h/w loopback
- for non-offloaded devices.
-
---*/
-
-#ifndef _SYSVAD_HANDSETSPEAKERWAVTABLE_H_
-#define _SYSVAD_HANDSETSPEAKERWAVTABLE_H_
-
-
-// To keep the code simple assume device supports only 48KHz, 16-bit, stereo (PCM and NON-PCM)
-
-
-#define HANDSETSPEAKER_DEVICE_MAX_CHANNELS 2 // Max Channels.
-
-#define HANDSETSPEAKER_HOST_MAX_CHANNELS 2 // Max Channels.
-#define HANDSETSPEAKER_HOST_MIN_BITS_PER_SAMPLE 16 // Min Bits Per Sample
-#define HANDSETSPEAKER_HOST_MAX_BITS_PER_SAMPLE 16 // Max Bits Per Sample
-#define HANDSETSPEAKER_HOST_MIN_SAMPLE_RATE 24000 // Min Sample Rate
-#define HANDSETSPEAKER_HOST_MAX_SAMPLE_RATE 96000 // Max Sample Rate
-
-#define HANDSETSPEAKER_LOOPBACK_MAX_CHANNELS HANDSETSPEAKER_HOST_MAX_CHANNELS // Must be equal to host pin's Max Channels.
-#define HANDSETSPEAKER_LOOPBACK_MIN_BITS_PER_SAMPLE HANDSETSPEAKER_HOST_MIN_BITS_PER_SAMPLE // Must be equal to host pin's Min Bits Per Sample
-#define HANDSETSPEAKER_LOOPBACK_MAX_BITS_PER_SAMPLE HANDSETSPEAKER_HOST_MAX_BITS_PER_SAMPLE // Must be equal to host pin's Max Bits Per Sample
-#define HANDSETSPEAKER_LOOPBACK_MIN_SAMPLE_RATE HANDSETSPEAKER_HOST_MIN_SAMPLE_RATE // Must be equal to host pin's Min Sample Rate
-#define HANDSETSPEAKER_LOOPBACK_MAX_SAMPLE_RATE HANDSETSPEAKER_HOST_MAX_SAMPLE_RATE // Must be equal to host pin's Max Sample Rate
-
-#define HANDSETSPEAKER_DOLBY_DIGITAL_MAX_CHANNELS 2 // Max Channels.
-#define HANDSETSPEAKER_DOLBY_DIGITAL_MIN_BITS_PER_SAMPLE 16 // Min Bits Per Sample
-#define HANDSETSPEAKER_DOLBY_DIGITAL_MAX_BITS_PER_SAMPLE 16 // Max Bits Per Sample
-#define HANDSETSPEAKER_DOLBY_DIGITAL_MIN_SAMPLE_RATE 44100 // Min Sample Rate
-#define HANDSETSPEAKER_DOLBY_DIGITAL_MAX_SAMPLE_RATE 44100 // Max Sample Rate
-
-//
-// Max # of pin instances.
-//
-#define HANDSETSPEAKER_MAX_INPUT_SYSTEM_STREAMS 3
-#define HANDSETSPEAKER_MAX_OUTPUT_LOOPBACK_STREAMS MAX_OUTPUT_LOOPBACK_STREAMS
-
-//=============================================================================
-static
-KSDATAFORMAT_WAVEFORMATEXTENSIBLE HandsetSpeakerHostPinSupportedDeviceFormats[] =
-{
- { // 0
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 2,
- 24000,
- 96000,
- 4,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_STEREO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 1
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 2,
- 32000,
- 128000,
- 4,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_STEREO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 2
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 2,
- 44100,
- 176400,
- 4,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_STEREO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 3
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 2,
- 48000,
- 192000,
- 4,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_STEREO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 4
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 2,
- 88200,
- 352800,
- 4,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_STEREO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 5
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 2,
- 96000,
- 384000,
- 4,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_STEREO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- }
-};
-
-//
-// Supported modes (only on streaming pins).
-//
-static
-MODE_AND_DEFAULT_FORMAT HandsetSpeakerHostPinSupportedDeviceModes[] =
-{
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_RAW,
- &HandsetSpeakerHostPinSupportedDeviceFormats[3].DataFormat, // 48KHz
- },
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_DEFAULT,
- &HandsetSpeakerHostPinSupportedDeviceFormats[3].DataFormat, // 48KHz
- },
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS,
- &HandsetSpeakerHostPinSupportedDeviceFormats[0].DataFormat, // 24KHz
- }
-};
-
-//
-// The entries here must follow the same order as the filter's pin
-// descriptor array.
-//
-static
-PIN_DEVICE_FORMATS_AND_MODES HandsetSpeakerPinDeviceFormatsAndModes[] =
-{
- {
- SystemRenderPin,
- HandsetSpeakerHostPinSupportedDeviceFormats,
- SIZEOF_ARRAY(HandsetSpeakerHostPinSupportedDeviceFormats),
- HandsetSpeakerHostPinSupportedDeviceModes,
- SIZEOF_ARRAY(HandsetSpeakerHostPinSupportedDeviceModes)
- },
- {
- RenderLoopbackPin,
- HandsetSpeakerHostPinSupportedDeviceFormats, // Must support all the formats supported by host pin
- SIZEOF_ARRAY(HandsetSpeakerHostPinSupportedDeviceFormats),
- NULL, // loopback doesn't support modes.
- 0
- },
- {
- BridgePin,
- NULL,
- 0,
- NULL,
- 0
- }
-};
-
-//=============================================================================
-static
-KSDATARANGE_AUDIO HandsetSpeakerPinDataRangesStream[] =
-{
- { // 0
- {
- sizeof(KSDATARANGE_AUDIO),
- KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- HANDSETSPEAKER_HOST_MAX_CHANNELS,
- HANDSETSPEAKER_HOST_MIN_BITS_PER_SAMPLE,
- HANDSETSPEAKER_HOST_MAX_BITS_PER_SAMPLE,
- HANDSETSPEAKER_HOST_MIN_SAMPLE_RATE,
- HANDSETSPEAKER_HOST_MAX_SAMPLE_RATE
- },
- { // 1
- {
- sizeof(KSDATARANGE_AUDIO),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- HANDSETSPEAKER_LOOPBACK_MAX_CHANNELS,
- HANDSETSPEAKER_LOOPBACK_MIN_BITS_PER_SAMPLE,
- HANDSETSPEAKER_LOOPBACK_MAX_BITS_PER_SAMPLE,
- HANDSETSPEAKER_LOOPBACK_MIN_SAMPLE_RATE,
- HANDSETSPEAKER_LOOPBACK_MAX_SAMPLE_RATE
- }
-};
-
-static
-PKSDATARANGE HandsetSpeakerPinDataRangePointersStream[] =
-{
- PKSDATARANGE(&HandsetSpeakerPinDataRangesStream[0]),
- PKSDATARANGE(&PinDataRangeAttributeList)
-};
-
-static
-PKSDATARANGE HandsetSpeakerPinDataRangePointersLoopbackStream[] =
-{
- PKSDATARANGE(&HandsetSpeakerPinDataRangesStream[1])
-};
-
-//=============================================================================
-static
-KSDATARANGE HandsetSpeakerPinDataRangesBridge[] =
-{
- {
- sizeof(KSDATARANGE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
- }
-};
-
-static
-PKSDATARANGE HandsetSpeakerPinDataRangePointersBridge[] =
-{
- &HandsetSpeakerPinDataRangesBridge[0]
-};
-
-
-//=============================================================================
-static
-PCPIN_DESCRIPTOR HandsetSpeakerWaveMiniportPins[] =
-{
- // Wave Out Streaming Pin (Renderer) KSPIN_WAVE_RENDER2_SINK_SYSTEM
- {
- HANDSETSPEAKER_MAX_INPUT_SYSTEM_STREAMS,
- HANDSETSPEAKER_MAX_INPUT_SYSTEM_STREAMS,
- 0,
- NULL,
- {
- 0,
- NULL,
- 0,
- NULL,
- SIZEOF_ARRAY(HandsetSpeakerPinDataRangePointersStream),
- HandsetSpeakerPinDataRangePointersStream,
- KSPIN_DATAFLOW_IN,
- KSPIN_COMMUNICATION_SINK,
- &KSCATEGORY_AUDIO,
- NULL,
- 0
- }
- },
- // Wave Out Streaming Pin (Renderer) KSPIN_WAVE_RENDER2_SINK_LOOPBACK
- {
- HANDSETSPEAKER_MAX_OUTPUT_LOOPBACK_STREAMS,
- HANDSETSPEAKER_MAX_OUTPUT_LOOPBACK_STREAMS,
- 0,
- NULL,
- {
- 0,
- NULL,
- 0,
- NULL,
- SIZEOF_ARRAY(HandsetSpeakerPinDataRangePointersLoopbackStream),
- HandsetSpeakerPinDataRangePointersLoopbackStream,
- KSPIN_DATAFLOW_OUT,
- KSPIN_COMMUNICATION_SINK,
- &KSNODETYPE_AUDIO_LOOPBACK,
- NULL,
- 0
- }
- },
- // Wave Out Bridge Pin (Renderer) KSPIN_WAVE_RENDER2_SOURCE
- {
- 0,
- 0,
- 0,
- NULL,
- {
- 0,
- NULL,
- 0,
- NULL,
- SIZEOF_ARRAY(HandsetSpeakerPinDataRangePointersBridge),
- HandsetSpeakerPinDataRangePointersBridge,
- KSPIN_DATAFLOW_OUT,
- KSPIN_COMMUNICATION_NONE,
- &KSCATEGORY_AUDIO,
- NULL,
- 0
- }
- },
-};
-
-//=============================================================================
-static
-PCPROPERTY_ITEM HandsetSpeakerPropertiesVolume[] =
-{
- {
- &KSPROPSETID_Audio,
- KSPROPERTY_AUDIO_VOLUMELEVEL,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_WaveFilter
- }
-};
-
-DEFINE_PCAUTOMATION_TABLE_PROP(AutomationHandsetSpeakerVolume, HandsetSpeakerPropertiesVolume);
-
-//=============================================================================
-static
-PCPROPERTY_ITEM HandsetSpeakerPropertiesMute[] =
-{
- {
- &KSPROPSETID_Audio,
- KSPROPERTY_AUDIO_MUTE,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_WaveFilter
- }
-};
-
-DEFINE_PCAUTOMATION_TABLE_PROP(AutomationHandsetSpeakerMute, HandsetSpeakerPropertiesMute);
-
-//=============================================================================
-static
-PCPROPERTY_ITEM HandsetSpeakerPropertiesPeakMeter[] =
-{
- {
- &KSPROPSETID_Audio,
- KSPROPERTY_AUDIO_PEAKMETER2,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_WaveFilter
- },
- {
- &KSPROPSETID_Audio,
- KSPROPERTY_AUDIO_CPU_RESOURCES,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_WaveFilter
- }
-};
-
-DEFINE_PCAUTOMATION_TABLE_PROP(AutomationHandsetSpeakerPeakMeter, HandsetSpeakerPropertiesPeakMeter);
-
-//=============================================================================
-static
-PCNODE_DESCRIPTOR HandsetSpeakerWaveMiniportNodes[] =
-{
- // KSNODE_WAVE_SUM
- {
- 0, // Flags
- NULL, // AutomationTable
- &KSNODETYPE_SUM, // Type
- NULL // Name
- },
- // KSNODE_WAVE_VOLUME
- {
- 0, // Flags
- &AutomationHandsetSpeakerVolume, // AutomationTable
- &KSNODETYPE_VOLUME, // Type
- &KSAUDFNAME_WAVE_VOLUME // Name
- },
- // KSNODE_WAVE_MUTE
- {
- 0, // Flags
- &AutomationHandsetSpeakerMute, // AutomationTable
- &KSNODETYPE_MUTE, // Type
- &KSAUDFNAME_WAVE_MUTE // Name
- },
- // KSNODE_WAVE_PEAKMETER
- {
- 0, // Flags
- &AutomationHandsetSpeakerPeakMeter, // AutomationTable
- &KSNODETYPE_PEAKMETER, // Type
- &KSAUDFNAME_PEAKMETER // Name
- }
-};
-
-C_ASSERT( KSNODE_WAVE_SUM == 0 );
-C_ASSERT( KSNODE_WAVE_VOLUME == 1 );
-C_ASSERT( KSNODE_WAVE_MUTE == 2 );
-C_ASSERT( KSNODE_WAVE_PEAKMETER == 3 );
-
-
-//=============================================================================
-//
-// Note:
-// 1) A sum node can be used to 'sum' multiple streams associated to different
-// instances of the same pin.
-// 2) Any node output has an implicit 'tee' node associated with it. Thus in the
-// scenario below it is ok for the peak meter node to have two identical outputs.
-//
-// ----------------------------------------------------------
-// | |
-// System Pin 0 | |-----| |--------| |------| |-----------| |--> 1 Loopback Pin
-// [instances:0...n]-->| -->| Sum |--->| Volume |-->| Mute |-->| PeakMeter |--> |
-// | |-----| |--------| |------| |-----------| |--> 2 KSPIN_WAVE_RENDER2_SOURCE
-// | |
-// ----------------------------------------------------------
-
-static
-PCCONNECTION_DESCRIPTOR HandsetSpeakerWaveMiniportConnections[] =
-{
- { PCFILTER_NODE, KSPIN_WAVE_RENDER2_SINK_SYSTEM, KSNODE_WAVE_SUM, 1 },
- { KSNODE_WAVE_SUM, 0, KSNODE_WAVE_VOLUME, 1 },
- { KSNODE_WAVE_VOLUME, 0, KSNODE_WAVE_MUTE, 1 },
- { KSNODE_WAVE_MUTE, 0, KSNODE_WAVE_PEAKMETER, 1 },
- { KSNODE_WAVE_PEAKMETER, 2, PCFILTER_NODE, KSPIN_WAVE_RENDER2_SINK_LOOPBACK },
- { KSNODE_WAVE_PEAKMETER, 0, PCFILTER_NODE, KSPIN_WAVE_RENDER2_SOURCE },
-};
-
-//=============================================================================
-static
-PCPROPERTY_ITEM PropertiesHandsetSpeakerWaveFilter[] =
-{
- {
- &KSPROPSETID_Pin,
- KSPROPERTY_PIN_PROPOSEDATAFORMAT,
- KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_WaveFilter
- },
- {
- &KSPROPSETID_Pin,
- KSPROPERTY_PIN_PROPOSEDATAFORMAT2,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_WaveFilter
- }
-};
-
-DEFINE_PCAUTOMATION_TABLE_PROP(AutomationHandsetSpeakerWaveFilter, PropertiesHandsetSpeakerWaveFilter);
-
-//=============================================================================
-static
-PCFILTER_DESCRIPTOR HandsetSpeakerWaveMiniportFilterDescriptor =
-{
- 0, // Version
- &AutomationHandsetSpeakerWaveFilter, // AutomationTable
- sizeof(PCPIN_DESCRIPTOR), // PinSize
- SIZEOF_ARRAY(HandsetSpeakerWaveMiniportPins), // PinCount
- HandsetSpeakerWaveMiniportPins, // Pins
- sizeof(PCNODE_DESCRIPTOR), // NodeSize
- SIZEOF_ARRAY(HandsetSpeakerWaveMiniportNodes), // NodeCount
- HandsetSpeakerWaveMiniportNodes, // Nodes
- SIZEOF_ARRAY(HandsetSpeakerWaveMiniportConnections), // ConnectionCount
- HandsetSpeakerWaveMiniportConnections, // Connections
- 0, // CategoryCount
- NULL // Categories - use defaults (audio, render, capture)
-};
-
-#endif // _SYSVAD_HANDSETSPEAKERWAVTABLE_H_
-
diff --git a/audio/sysvad/PhoneAudioSample/michstopo.cpp b/audio/sysvad/PhoneAudioSample/michstopo.cpp
deleted file mode 100644
index f96a58e5..00000000
--- a/audio/sysvad/PhoneAudioSample/michstopo.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- michstopo.cpp
-
-Abstract:
-
- Implementation of topology miniport for the mic (external: headset).
-
---*/
-
-#pragma warning (disable : 4127)
-
-#include <sysvad.h>
-#include "simple.h"
-#include "mintopo.h"
-#include "michstopo.h"
-#include "michstoptable.h"
-
-
-#pragma code_seg("PAGE")
-
-//=============================================================================
-NTSTATUS
-PropertyHandler_MicHsJackDescription
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
- Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION )
-
-Arguments:
-
- PropertyRequest -
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandler_MicHsJackDescription]"));
-
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
- ULONG nPinId = (ULONG)-1;
-
- ULONG cJackDescriptions = ARRAYSIZE(MicHsJackDescriptions);
- PKSJACK_DESCRIPTION * JackDescriptions = MicHsJackDescriptions;
-
- if (PropertyRequest->InstanceSize >= sizeof(ULONG))
- {
- nPinId = *(PULONG(PropertyRequest->Instance));
-
- if ((nPinId < cJackDescriptions) && (JackDescriptions[nPinId] != NULL))
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ntStatus =
- PropertyHandler_BasicSupport
- (
- PropertyRequest,
- KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET,
- VT_ILLEGAL
- );
- }
- else
- {
- ULONG cbNeeded = sizeof(KSMULTIPLE_ITEM) + sizeof(KSJACK_DESCRIPTION);
-
- if (PropertyRequest->ValueSize == 0)
- {
- PropertyRequest->ValueSize = cbNeeded;
- ntStatus = STATUS_BUFFER_OVERFLOW;
- }
- else if (PropertyRequest->ValueSize < cbNeeded)
- {
- ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value;
- PKSJACK_DESCRIPTION pDesc = (PKSJACK_DESCRIPTION)(pMI+1);
-
- pMI->Size = cbNeeded;
- pMI->Count = 1;
-
- RtlCopyMemory(pDesc, JackDescriptions[nPinId], sizeof(KSJACK_DESCRIPTION));
- ntStatus = STATUS_SUCCESS;
- }
- }
- }
- }
- }
-
- return ntStatus;
-}
-
-//=============================================================================
-NTSTATUS
-PropertyHandler_MicHsJackDescription2
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
- Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION2 )
-
-Arguments:
-
- PropertyRequest -
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandler_MicHsJackDescription2]"));
-
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
- ULONG nPinId = (ULONG)-1;
-
- ULONG cJackDescriptions = ARRAYSIZE(MicHsJackDescriptions);
- PKSJACK_DESCRIPTION * JackDescriptions = MicHsJackDescriptions;
-
- if (PropertyRequest->InstanceSize >= sizeof(ULONG))
- {
- nPinId = *(PULONG(PropertyRequest->Instance));
-
- if ((nPinId < cJackDescriptions) && (JackDescriptions[nPinId] != NULL))
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ntStatus =
- PropertyHandler_BasicSupport
- (
- PropertyRequest,
- KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET,
- VT_ILLEGAL
- );
- }
- else
- {
- ULONG cbNeeded = sizeof(KSMULTIPLE_ITEM) + sizeof(KSJACK_DESCRIPTION2);
-
- if (PropertyRequest->ValueSize == 0)
- {
- PropertyRequest->ValueSize = cbNeeded;
- ntStatus = STATUS_BUFFER_OVERFLOW;
- }
- else if (PropertyRequest->ValueSize < cbNeeded)
- {
- ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value;
- PKSJACK_DESCRIPTION2 pDesc = (PKSJACK_DESCRIPTION2)(pMI+1);
-
- pMI->Size = cbNeeded;
- pMI->Count = 1;
-
- RtlZeroMemory(pDesc, sizeof(KSJACK_DESCRIPTION2));
-
- //
- // Specifies the lower 16 bits of the DWORD parameter. This parameter indicates whether
- // the jack is currently active, streaming, idle, or hardware not ready.
- //
- pDesc->DeviceStateInfo = 0;
-
- //
- // From MSDN:
- // "If an audio device lacks jack presence detection, the IsConnected member of
- // the KSJACK_DESCRIPTION structure must always be set to TRUE. To remove the
- // ambiguity that results from this dual meaning of the TRUE value for IsConnected,
- // a client application can call IKsJackDescription2::GetJackDescription2 to read
- // the JackCapabilities flag of the KSJACK_DESCRIPTION2 structure. If this flag has
- // the JACKDESC2_PRESENCE_DETECT_CAPABILITY bit set, it indicates that the endpoint
- // does in fact support jack presence detection. In that case, the return value of
- // the IsConnected member can be interpreted to accurately reflect the insertion status
- // of the jack."
- //
- // Bit definitions:
- // 0x00000001 - JACKDESC2_PRESENCE_DETECT_CAPABILITY
- // 0x00000002 - JACKDESC2_DYNAMIC_FORMAT_CHANGE_CAPABILITY
- //
- pDesc->JackCapabilities = JACKDESC2_PRESENCE_DETECT_CAPABILITY;
-
- ntStatus = STATUS_SUCCESS;
- }
- }
- }
- }
- }
-
- return ntStatus;
-}
-
-
-//=============================================================================
-NTSTATUS
-PropertyHandler_MicHsTopoFilter
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
- Redirects property request to miniport object
-
-Arguments:
-
- PropertyRequest -
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandler_MicHsTopoFilter]"));
-
- // PropertryRequest structure is filled by portcls.
- // MajorTarget is a pointer to miniport object for miniports.
- //
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
-
- //
- // This line shows how to get a pointer to the miniport topology object.
- //
- PCMiniportTopology pMiniport = (PCMiniportTopology)PropertyRequest->MajorTarget;
- UNREFERENCED_VAR(pMiniport);
-
- if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Jack))
- {
- if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION)
- {
- ntStatus = PropertyHandler_MicHsJackDescription(PropertyRequest);
- }
- else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION2)
- {
- ntStatus = PropertyHandler_MicHsJackDescription2(PropertyRequest);
- }
- }
-
- return ntStatus;
-} // PropertyHandler_MicHsTopoFilter
-
-#pragma code_seg()
-
diff --git a/audio/sysvad/PhoneAudioSample/michstopo.h b/audio/sysvad/PhoneAudioSample/michstopo.h
deleted file mode 100644
index b8f9b106..00000000
--- a/audio/sysvad/PhoneAudioSample/michstopo.h
+++ /dev/null
@@ -1,21 +0,0 @@
-
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- michstopo.h
-
-Abstract:
-
- Declaration of topology miniport for the mic (external: headset).
-
---*/
-
-#ifndef _SYSVAD_MICHSTOPO_H_
-#define _SYSVAD_MICHSTOPO_H_
-
-NTSTATUS PropertyHandler_MicHsTopoFilter(_In_ PPCPROPERTY_REQUEST PropertyRequest);
-
-#endif // _SYSVAD_MICHSTOPO_H_
diff --git a/audio/sysvad/PhoneAudioSample/michstoptable.h b/audio/sysvad/PhoneAudioSample/michstoptable.h
deleted file mode 100644
index 0b4ed73c..00000000
--- a/audio/sysvad/PhoneAudioSample/michstoptable.h
+++ /dev/null
@@ -1,257 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- michstopotable.h
-
-Abstract:
-
- Declaration of topology table for the mic (external: headset)
-
---*/
-
-#ifndef _SYSVAD_MICHSTOPTABLE_H_
-#define _SYSVAD_MICHSTOPTABLE_H_
-
-#include <mintopo.h>
-
-// Function declarations.
-NTSTATUS
-PropertyHandler_MicHsTopoFilter(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
- );
-
-//=============================================================================
-static
-KSDATARANGE MicHsTopoPinDataRangesBridge[] =
-{
- {
- sizeof(KSDATARANGE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
- }
-};
-
-//=============================================================================
-static
-PKSDATARANGE MicHsTopoPinDataRangePointersBridge[] =
-{
- &MicHsTopoPinDataRangesBridge[0]
-};
-
-//=============================================================================
-static
-PCPIN_DESCRIPTOR MicHsTopoMiniportPins[] =
-{
- // KSPIN - topology filter in-pin
- {
- 0,
- 0,
- 0, // InstanceCount
- NULL, // AutomationTable
- { // KsPinDescriptor
- 0, // InterfacesCount
- NULL, // Interfaces
- 0, // MediumsCount
- NULL, // Mediums
- SIZEOF_ARRAY(MicHsTopoPinDataRangePointersBridge),// DataRangesCount
- MicHsTopoPinDataRangePointersBridge, // DataRanges
- KSPIN_DATAFLOW_IN, // DataFlow
- KSPIN_COMMUNICATION_NONE, // Communication
- &KSNODETYPE_HEADSET_MICROPHONE, // Category
- NULL, // Name
- 0 // Reserved
- }
- },
-
- // KSPIN - topology filter out-in
- {
- 0,
- 0,
- 0, // InstanceCount
- NULL, // AutomationTable
- { // KsPinDescriptor
- 0, // InterfacesCount
- NULL, // Interfaces
- 0, // MediumsCount
- NULL, // Mediums
- SIZEOF_ARRAY(MicHsTopoPinDataRangePointersBridge),// DataRangesCount
- MicHsTopoPinDataRangePointersBridge, // DataRanges
- KSPIN_DATAFLOW_OUT, // DataFlow
- KSPIN_COMMUNICATION_NONE, // Communication
- &KSCATEGORY_AUDIO, // Category
- NULL, // Name
- 0 // Reserved
- }
- }
-};
-
-//=============================================================================
-static
-KSJACK_DESCRIPTION MicHsJackDesc =
-{
- KSAUDIO_SPEAKER_MONO,
- JACKDESC_RGB(179, 201, 140),
- eConnTypeCombination,
- eGeoLocRear,
- eGenLocPrimaryBox,
- ePortConnJack,
- FALSE // NOTE: For convenience, wired headset jacks will be "unplugged" at boot.
-};
-
-//=============================================================================
-// Only return a KSJACK_DESCRIPTION for the physical bridge pin.
-static
-PKSJACK_DESCRIPTION MicHsJackDescriptions[] =
-{
- &MicHsJackDesc,
- NULL
-};
-
-//=============================================================================
-static
-PCPROPERTY_ITEM MicHsPropertiesVolume[] =
-{
- {
- &KSPROPSETID_Audio,
- KSPROPERTY_AUDIO_VOLUMELEVEL,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_Topology
- }
-};
-
-DEFINE_PCAUTOMATION_TABLE_PROP(AutomationMicHsVolume, MicHsPropertiesVolume);
-
-//=============================================================================
-static
-PCPROPERTY_ITEM MicHsPropertiesMute[] =
-{
- {
- &KSPROPSETID_Audio,
- KSPROPERTY_AUDIO_MUTE,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_Topology
- }
-};
-
-DEFINE_PCAUTOMATION_TABLE_PROP(AutomationMicHsMute, MicHsPropertiesMute);
-
-//=============================================================================
-static
-PCPROPERTY_ITEM MicHsPropertiesPeakMeter[] =
-{
- {
- &KSPROPSETID_Audio,
- KSPROPERTY_AUDIO_PEAKMETER2,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_Topology
- },
- {
- &KSPROPSETID_Audio,
- KSPROPERTY_AUDIO_CPU_RESOURCES,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_Topology
- }
-};
-
-DEFINE_PCAUTOMATION_TABLE_PROP(AutomationMicHsPeakMeter, MicHsPropertiesPeakMeter);
-
-//=============================================================================
-static
-PCNODE_DESCRIPTOR MicHsTopologyNodes[] =
-{
- // KSNODE_TOPO_VOLUME
- {
- 0, // Flags
- &AutomationMicHsVolume, // AutomationTable
- &KSNODETYPE_VOLUME, // Type
- &KSAUDFNAME_MIC_VOLUME // Name
- },
- // KSNODE_TOPO_MUTE
- {
- 0, // Flags
- &AutomationMicHsMute, // AutomationTable
- &KSNODETYPE_MUTE, // Type
- &KSAUDFNAME_MIC_MUTE // Name
- },
- // KSNODE_TOPO_PEAKMETER
- {
- 0, // Flags
- &AutomationMicHsPeakMeter, // AutomationTable
- &KSNODETYPE_PEAKMETER, // Type
- &KSAUDFNAME_PEAKMETER // Name
- }
-};
-
-C_ASSERT( KSNODE_TOPO_VOLUME == 0 );
-C_ASSERT( KSNODE_TOPO_MUTE == 1 );
-C_ASSERT( KSNODE_TOPO_PEAKMETER == 2 );
-
-//=============================================================================
-static
-PCCONNECTION_DESCRIPTOR MicHsMiniportConnections[] =
-{
- // FromNode, FromPin, ToNode, ToPin
- { PCFILTER_NODE, KSPIN_TOPO_MIC_ELEMENTS, KSNODE_TOPO_VOLUME, 1 },
- { KSNODE_TOPO_VOLUME, 0, KSNODE_TOPO_MUTE, 1 },
- { KSNODE_TOPO_MUTE, 0, KSNODE_TOPO_PEAKMETER, 1 },
- { KSNODE_TOPO_PEAKMETER, 0, PCFILTER_NODE, KSPIN_TOPO_BRIDGE }
-};
-
-
-//=============================================================================
-static
-PCPROPERTY_ITEM MicHsPropertiesTopoFilter[] =
-{
- {
- &KSPROPSETID_Jack,
- KSPROPERTY_JACK_DESCRIPTION,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_MicHsTopoFilter
- },
- {
- &KSPROPSETID_Jack,
- KSPROPERTY_JACK_DESCRIPTION2,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_MicHsTopoFilter
- }
-};
-
-static PCEVENT_ITEM MicHsJackInfoChangeEvent[] =
-{
- {
- &KSEVENTSETID_PinCapsChange, // Something changed
- KSEVENT_PINCAPS_JACKINFOCHANGE, // Jack Info Changes
- KSEVENT_TYPE_ENABLE | KSEVENT_TYPE_BASICSUPPORT,
- CMiniportTopology_EventHandler_JackState
- }
-};
-
-DEFINE_PCAUTOMATION_TABLE_PROP_EVENT(AutomationMicHsTopoFilter, MicHsPropertiesTopoFilter, MicHsJackInfoChangeEvent);
-
-//=============================================================================
-static
-PCFILTER_DESCRIPTOR MicHsTopoMiniportFilterDescriptor =
-{
- 0, // Version
- &AutomationMicHsTopoFilter, // AutomationTable
- sizeof(PCPIN_DESCRIPTOR), // PinSize
- SIZEOF_ARRAY(MicHsTopoMiniportPins), // PinCount
- MicHsTopoMiniportPins, // Pins
- sizeof(PCNODE_DESCRIPTOR), // NodeSize
- SIZEOF_ARRAY(MicHsTopologyNodes), // NodeCount
- MicHsTopologyNodes, // Nodes
- SIZEOF_ARRAY(MicHsMiniportConnections), // ConnectionCount
- MicHsMiniportConnections, // Connections
- 0, // CategoryCount
- NULL // Categories
-};
-
-#endif // _SYSVAD_MICHSTOPTABLE_H_
-
diff --git a/audio/sysvad/PhoneAudioSample/michswavtable.h b/audio/sysvad/PhoneAudioSample/michswavtable.h
deleted file mode 100644
index 4bfa66db..00000000
--- a/audio/sysvad/PhoneAudioSample/michswavtable.h
+++ /dev/null
@@ -1,447 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- michswavtable.h
-
-Abstract:
-
- Declaration of wave miniport tables for the mic (external: headset).
-
---*/
-
-#ifndef _SYSVAD_MICHSWAVTABLE_H_
-#define _SYSVAD_MICHSWAVTABLE_H_
-
-//
-// Mic in (external: headset) range.
-//
-#define MICHS_DEVICE_MAX_CHANNELS 1 // Max Channels.
-#define MICHS_MIN_BITS_PER_SAMPLE_PCM 16 // Min Bits Per Sample
-#define MICHS_MAX_BITS_PER_SAMPLE_PCM 16 // Max Bits Per Sample
-#define MICHS_MIN_SAMPLE_RATE 8000 // Min Sample Rate
-#define MICHS_MAX_SAMPLE_RATE 48000 // Max Sample Rate
-
-//
-// Max # of pin instances.
-//
-#define MICHS_MAX_INPUT_STREAMS 4
-
-//=============================================================================
-static
-KSDATAFORMAT_WAVEFORMATEXTENSIBLE MicHsPinSupportedDeviceFormats[] =
-{
- { // 0
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 1,
- 8000,
- 16000,
- 2,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_MONO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 1
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 1,
- 11025,
- 22050,
- 2,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_MONO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 2
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 1,
- 16000,
- 32000,
- 2,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_MONO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 3
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 1,
- 22050,
- 44100,
- 2,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_MONO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 4
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 1,
- 24000,
- 48000,
- 2,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_MONO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 5
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 1,
- 32000,
- 64000,
- 2,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_MONO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 6
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 1,
- 44100,
- 88200,
- 2,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_MONO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 7
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 1,
- 48000,
- 96000,
- 2,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_MONO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- }
-};
-
-//
-// Supported modes (only on streaming pins).
-//
-static
-MODE_AND_DEFAULT_FORMAT MicHsPinSupportedDeviceModes[] =
-{
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_RAW,
- &MicHsPinSupportedDeviceFormats[SIZEOF_ARRAY(MicHsPinSupportedDeviceFormats) - 1].DataFormat, // 48KHz
- },
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_DEFAULT,
- &MicHsPinSupportedDeviceFormats[SIZEOF_ARRAY(MicHsPinSupportedDeviceFormats) - 1].DataFormat, // 48KHz
- },
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_SPEECH,
- &MicHsPinSupportedDeviceFormats[2].DataFormat, // 16KHz
- },
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS,
- &MicHsPinSupportedDeviceFormats[4].DataFormat, // 24KHz
- }
-};
-
-//
-// The entries here must follow the same order as the filter's pin
-// descriptor array.
-//
-static
-PIN_DEVICE_FORMATS_AND_MODES MicHsPinDeviceFormatsAndModes[] =
-{
- {
- BridgePin,
- NULL,
- 0,
- NULL,
- 0
- },
- {
- SystemCapturePin,
- MicHsPinSupportedDeviceFormats,
- SIZEOF_ARRAY(MicHsPinSupportedDeviceFormats),
- MicHsPinSupportedDeviceModes,
- SIZEOF_ARRAY(MicHsPinSupportedDeviceModes)
- }
-};
-
-//=============================================================================
-static
-KSDATARANGE_AUDIO MicHsPinDataRangesStream[] =
-{
- {
- {
- sizeof(KSDATARANGE_AUDIO),
- KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- MICHS_DEVICE_MAX_CHANNELS,
- MICHS_MIN_BITS_PER_SAMPLE_PCM,
- MICHS_MAX_BITS_PER_SAMPLE_PCM,
- MICHS_MIN_SAMPLE_RATE,
- MICHS_MAX_SAMPLE_RATE
- },
-};
-
-static
-PKSDATARANGE MicHsPinDataRangePointersStream[] =
-{
- PKSDATARANGE(&MicHsPinDataRangesStream[0]),
- PKSDATARANGE(&PinDataRangeAttributeList),
-};
-
-//=============================================================================
-static
-KSDATARANGE MicHsPinDataRangesBridge[] =
-{
- {
- sizeof(KSDATARANGE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
- }
-};
-
-static
-PKSDATARANGE MicHsPinDataRangePointersBridge[] =
-{
- &MicHsPinDataRangesBridge[0]
-};
-
-//=============================================================================
-static
-PCPIN_DESCRIPTOR MicHsWaveMiniportPins[] =
-{
- // Wave In Bridge Pin (Capture - From Topology) KSPIN_WAVE_BRIDGE
- {
- 0,
- 0,
- 0,
- NULL,
- {
- 0,
- NULL,
- 0,
- NULL,
- SIZEOF_ARRAY(MicHsPinDataRangePointersBridge),
- MicHsPinDataRangePointersBridge,
- KSPIN_DATAFLOW_IN,
- KSPIN_COMMUNICATION_NONE,
- &KSCATEGORY_AUDIO,
- NULL,
- 0
- }
- },
-
- // Wave In Streaming Pin (Capture) KSPIN_WAVEIN_HOST
- {
- MICHS_MAX_INPUT_STREAMS,
- MICHS_MAX_INPUT_STREAMS,
- 0,
- NULL,
- {
- 0,
- NULL,
- 0,
- NULL,
- SIZEOF_ARRAY(MicHsPinDataRangePointersStream),
- MicHsPinDataRangePointersStream,
- KSPIN_DATAFLOW_OUT,
- KSPIN_COMMUNICATION_SINK,
- &KSCATEGORY_AUDIO,
- &KSAUDFNAME_RECORDING_CONTROL,
- 0
- }
- }
-};
-
-//=============================================================================
-static
-PCNODE_DESCRIPTOR MicHsWaveMiniportNodes[] =
-{
- // KSNODE_WAVE_ADC
- {
- 0, // Flags
- NULL, // AutomationTable
- &KSNODETYPE_ADC, // Type
- NULL // Name
- }
-};
-
-//=============================================================================
-static
-PCCONNECTION_DESCRIPTOR MicHsWaveMiniportConnections[] =
-{
- { PCFILTER_NODE, KSPIN_WAVE_BRIDGE, KSNODE_WAVE_ADC, 1 },
- { KSNODE_WAVE_ADC, 0, PCFILTER_NODE, KSPIN_WAVEIN_HOST }
-};
-
-//=============================================================================
-static
-PCPROPERTY_ITEM PropertiesMicHsWaveFilter[] =
-{
- {
- &KSPROPSETID_General,
- KSPROPERTY_GENERAL_COMPONENTID,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_WaveFilter
- },
- {
- &KSPROPSETID_Pin,
- KSPROPERTY_PIN_PROPOSEDATAFORMAT,
- KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_WaveFilter
- },
- {
- &KSPROPSETID_Pin,
- KSPROPERTY_PIN_PROPOSEDATAFORMAT2,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_WaveFilter
- }
-};
-
-DEFINE_PCAUTOMATION_TABLE_PROP(AutomationMicHsWaveFilter, PropertiesMicHsWaveFilter);
-
-//=============================================================================
-static
-PCFILTER_DESCRIPTOR MicHsWaveMiniportFilterDescriptor =
-{
- 0, // Version
- &AutomationMicHsWaveFilter, // AutomationTable
- sizeof(PCPIN_DESCRIPTOR), // PinSize
- SIZEOF_ARRAY(MicHsWaveMiniportPins), // PinCount
- MicHsWaveMiniportPins, // Pins
- sizeof(PCNODE_DESCRIPTOR), // NodeSize
- SIZEOF_ARRAY(MicHsWaveMiniportNodes), // NodeCount
- MicHsWaveMiniportNodes, // Nodes
- SIZEOF_ARRAY(MicHsWaveMiniportConnections), // ConnectionCount
- MicHsWaveMiniportConnections, // Connections
- 0, // CategoryCount
- NULL // Categories - use defaults (audio, render, capture)
-};
-
-#endif // _SYSVAD_MICHSWAVTABLE_H_
diff --git a/audio/sysvad/PhoneAudioSample/minipairs.h b/audio/sysvad/PhoneAudioSample/minipairs.h
deleted file mode 100644
index 6b219462..00000000
--- a/audio/sysvad/PhoneAudioSample/minipairs.h
+++ /dev/null
@@ -1,602 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- minipairs.h
-
-Abstract:
-
- Local audio endpoint filter definitions.
-
---*/
-
-#ifndef _SYSVAD_MINIPAIRS_H_
-#define _SYSVAD_MINIPAIRS_H_
-
-#include "speakertopo.h"
-#include "speakertoptable.h"
-#include "speakerwavtable.h"
-
-#include "speakerhstopo.h"
-#include "speakerhstoptable.h"
-#include "speakerhswavtable.h"
-
-#include "michstopo.h"
-#include "michstoptable.h"
-#include "michswavtable.h"
-
-#include "micarraytopo.h"
-#include "micarray1toptable.h"
-#include "micarraywavtable.h"
-
-#include "cellulartopo.h"
-#include "cellularwave.h"
-#include "cellulartoptable.h"
-#include "cellularwavtable.h"
-
-#include "fmtopo.h"
-#include "fmwave.h"
-#include "fmtoptable.h"
-#include "fmwavtable.h"
-
-#include "handsetspeakertopo.h"
-#include "handsetspeakertoptable.h"
-#include "handsetspeakerwavtable.h"
-
-#include "handsetmictopo.h"
-#include "handsetmictoptable.h"
-#include "handsetmicwavtable.h"
-
-
-NTSTATUS
-CreateMiniportWaveRTSYSVAD
-(
- _Out_ PUNKNOWN *,
- _In_ REFCLSID,
- _In_opt_ PUNKNOWN,
- _In_ POOL_TYPE,
- _In_ PUNKNOWN,
- _In_opt_ PVOID,
- _In_ PENDPOINT_MINIPAIR
-);
-
-NTSTATUS
-CreateMiniportTopologySYSVAD
-(
- _Out_ PUNKNOWN *,
- _In_ REFCLSID,
- _In_opt_ PUNKNOWN,
- _In_ POOL_TYPE,
- _In_ PUNKNOWN,
- _In_opt_ PVOID,
- _In_ PENDPOINT_MINIPAIR
-);
-
-//
-// Describe buffer size constraints for WaveRT buffers
-//
-static struct
-{
- KSAUDIO_PACKETSIZE_CONSTRAINTS2 TransportPacketConstraints;
- KSAUDIO_PACKETSIZE_PROCESSINGMODE_CONSTRAINT AdditionalProcessingConstraints[1];
-} SysvadWaveRtPacketSizeConstraintsRender =
-{
- {
- 2 * HNSTIME_PER_MILLISECOND, // 2 ms minimum processing interval
- FILE_BYTE_ALIGNMENT, // 1 byte packet size alignment
- 0, // no maximum packet size constraint
- 2, // 2 processing constraints follow
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_DEFAULT, // constraint for default processing mode
- 128, // 128 samples per processing frame
- 0, // NA hns per processing frame
- },
- },
- {
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_MOVIE, // constraint for movie processing mode
- 1024, // 1024 samples per processing frame
- 0, // NA hns per processing frame
- },
- }
-};
-
-const SYSVAD_DEVPROPERTY SysvadWaveFilterInterfacePropertiesRender[] =
-{
- {
- &DEVPKEY_KsAudio_PacketSize_Constraints2, // Key
- DEVPROP_TYPE_BINARY, // Type
- sizeof(SysvadWaveRtPacketSizeConstraintsRender), // BufferSize
- &SysvadWaveRtPacketSizeConstraintsRender, // Buffer
- },
-};
-
-static struct
-{
- KSAUDIO_PACKETSIZE_CONSTRAINTS2 TransportPacketConstraints;
-} SysvadWaveRtPacketSizeConstraintsCapture =
-{
- {
- 2 * HNSTIME_PER_MILLISECOND, // 2 ms minimum processing interval
- FILE_BYTE_ALIGNMENT, // 1 byte packet size alignment
- 0x100000, // 1 MB maximum packet size
- 1, // 1 processing constraint follows
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS, // constraint for communications processing mode
- 0, // NA samples per processing frame
- 20 * HNSTIME_PER_MILLISECOND, // 200000 hns (20ms) per processing frame
- },
- },
-};
-
-const SYSVAD_DEVPROPERTY SysvadWaveFilterInterfacePropertiesCapture[] =
-{
- {
- &DEVPKEY_KsAudio_PacketSize_Constraints2, // Key
- DEVPROP_TYPE_BINARY, // Type
- sizeof(SysvadWaveRtPacketSizeConstraintsCapture), // BufferSize
- &SysvadWaveRtPacketSizeConstraintsCapture, // Buffer
- },
-};
-
-//
-// Render miniports.
-//
-
-/*********************************************************************
-* Topology/Wave bridge connection for speaker (internal) *
-* *
-* +------+ +------+ *
-* | Wave | | Topo | *
-* | | | | *
-* System --->|0 2|---> Loopback | | *
-* | | | | *
-* Offload --->|1 3|--------------->|0 1|---> Line Out *
-* | | | | *
-* +------+ +------+ *
-*********************************************************************/
-static
-PHYSICALCONNECTIONTABLE SpeakerTopologyPhysicalConnections[] =
-{
- {
- KSPIN_TOPO_WAVEOUT_SOURCE, // TopologyIn
- KSPIN_WAVE_RENDER_SOURCE, // WaveOut
- CONNECTIONTYPE_WAVE_OUTPUT
- }
-};
-
-static
-ENDPOINT_MINIPAIR SpeakerMiniports =
-{
- eSpeakerDevice,
- SPEAKER_TOPONAME, // defined in cellulartopo.h for use with cellular routing control
- NULL, // optional template name
- CreateMiniportTopologySYSVAD,
- &SpeakerTopoMiniportFilterDescriptor,
- 0, NULL, // Interface properties
- L"WaveSpeaker", // make sure this or the template name matches with KSNAME_WaveSpeaker in the inf's [Strings] section
- NULL, // optional template name
- CreateMiniportWaveRTSYSVAD,
- &SpeakerWaveMiniportFilterDescriptor,
- ARRAYSIZE(SysvadWaveFilterInterfacePropertiesRender), // Interface properties
- SysvadWaveFilterInterfacePropertiesRender,
- SPEAKER_DEVICE_MAX_CHANNELS,
- SpeakerPinDeviceFormatsAndModes,
- SIZEOF_ARRAY(SpeakerPinDeviceFormatsAndModes),
- SpeakerTopologyPhysicalConnections,
- SIZEOF_ARRAY(SpeakerTopologyPhysicalConnections),
- ENDPOINT_OFFLOAD_SUPPORTED,
- SpeakerModulesWaveFilter,
- SIZEOF_ARRAY(SpeakerModulesWaveFilter),
- &SpeakerModuleNotificationDeviceId,
-};
-
-/*********************************************************************
-* Topology/Wave bridge connection for speaker (external:headset) *
-* *
-* +------+ +------+ *
-* | Wave | | Topo | *
-* | | | | *
-* System --->|0 2|---> Loopback | | *
-* | | | | *
-* Offload --->|1 3|--------------->|0 1|---> Line Out *
-* | | | | *
-* +------+ +------+ *
-*********************************************************************/
-static
-PHYSICALCONNECTIONTABLE SpeakerHsTopologyPhysicalConnections[] =
-{
- {
- KSPIN_TOPO_WAVEOUT_SOURCE, // TopologyIn
- KSPIN_WAVE_RENDER_SOURCE, // WaveOut
- CONNECTIONTYPE_WAVE_OUTPUT
- }
-};
-
-static
-ENDPOINT_MINIPAIR SpeakerHsMiniports =
-{
- eSpeakerHsDevice,
- SPEAKER_HEADSET_TOPONAME, // defined in cellulartopo.h for use with cellular routing control
- NULL, // optional template name
- CreateMiniportTopologySYSVAD,
- &SpeakerHsTopoMiniportFilterDescriptor, // use the speaker headset topo filter descriptor, not headset.
- 0, NULL, // Interface properties
- L"WaveSpeakerHeadset", // make sure this or the template name matches with KSNAME_WaveSpeakerHeadset in the inf's [Strings] section
- NULL, // optional template name
- CreateMiniportWaveRTSYSVAD,
- &SpeakerHsWaveMiniportFilterDescriptor,
- 0, NULL, // Interface properties
- SPEAKERHS_DEVICE_MAX_CHANNELS,
- SpeakerHsPinDeviceFormatsAndModes,
- SIZEOF_ARRAY(SpeakerHsPinDeviceFormatsAndModes),
- SpeakerHsTopologyPhysicalConnections,
- SIZEOF_ARRAY(SpeakerHsTopologyPhysicalConnections),
- ENDPOINT_OFFLOAD_SUPPORTED,
- NULL, 0, NULL, // audio module settings.
-};
-
-//
-// headset microphone miniports.
-//
-
-/*********************************************************************
-* Topology/Wave bridge connection for mic in *
-* *
-* +------+ +------+ *
-* | Topo | | Wave | *
-* | | | | *
-* Mic in --->|0 1|===>|0 1|---> Capture Host Pin *
-* | | | | *
-* +------+ +------+ *
-*********************************************************************/
-static
-PHYSICALCONNECTIONTABLE MicHsTopologyPhysicalConnections[] =
-{
- {
- KSPIN_TOPO_BRIDGE, // TopologyOut
- KSPIN_WAVE_BRIDGE, // WaveIn
- CONNECTIONTYPE_TOPOLOGY_OUTPUT
- }
-};
-
-static
-ENDPOINT_MINIPAIR MicHsMiniports =
-{
- eMicHsDevice,
- MIC_HEADSET_TOPONAME, // defined in cellulartopo.h for use with cellular routing control
- NULL, // optional template name
- CreateMiniportTopologySYSVAD,
- &MicHsTopoMiniportFilterDescriptor,
- 0, NULL, // Interface properties
- L"WaveMicHeadset", // make sure this or the template name matches with KSNAME_WaveMicHeadset in the inf's [Strings] section
- NULL, // optional template name
- CreateMiniportWaveRTSYSVAD,
- &MicHsWaveMiniportFilterDescriptor,
- 0, NULL, // Interface properties
- MICHS_DEVICE_MAX_CHANNELS,
- MicHsPinDeviceFormatsAndModes,
- SIZEOF_ARRAY(MicHsPinDeviceFormatsAndModes),
- MicHsTopologyPhysicalConnections,
- SIZEOF_ARRAY(MicHsTopologyPhysicalConnections),
- ENDPOINT_NO_FLAGS,
- NULL, 0, NULL, // audio module settings.
-};
-
-
-//
-// Capture miniports.
-//
-
-/*********************************************************************
-* Topology/Wave bridge connection for mic array 1 (front) *
-* *
-* +------+ +------+ *
-* | Topo | | Wave | *
-* | | | | *
-* Mic in --->|0 1|===>|0 1|---> Capture Host Pin *
-* | | | | *
-* +------+ +------+ *
-*********************************************************************/
-static
-PHYSICALCONNECTIONTABLE MicArray1TopologyPhysicalConnections[] =
-{
- {
- KSPIN_TOPO_BRIDGE, // TopologyOut
- KSPIN_WAVE_BRIDGE, // WaveIn
- CONNECTIONTYPE_TOPOLOGY_OUTPUT
- }
-};
-
-static
-ENDPOINT_MINIPAIR MicArray1Miniports =
-{
- eMicArrayDevice1,
- L"TopologyMicArray1", // make sure this or the template name matches with KSNAME_TopologyMicArray1 in the inf's [Strings] section
- NULL, // optional template name
- CreateMicArrayMiniportTopology,
- &MicArray1TopoMiniportFilterDescriptor,
- 0, NULL, // Interface properties
- L"WaveMicArray1", // make sure this or the tempalte name matches with KSNAME_WaveMicArray1 in the inf's [Strings] section
- NULL, // optional template name
- CreateMiniportWaveRTSYSVAD,
- &MicArrayWaveMiniportFilterDescriptor,
- ARRAYSIZE(SysvadWaveFilterInterfacePropertiesCapture), // Interface properties
- SysvadWaveFilterInterfacePropertiesCapture,
- MICARRAY_DEVICE_MAX_CHANNELS,
- MicArrayPinDeviceFormatsAndModes,
- SIZEOF_ARRAY(MicArrayPinDeviceFormatsAndModes),
- MicArray1TopologyPhysicalConnections,
- SIZEOF_ARRAY(MicArray1TopologyPhysicalConnections),
- ENDPOINT_SOUNDDETECTOR_SUPPORTED,
- NULL, 0, NULL, // audio module settings.
-};
-
-/*********************************************************************
-* Topology/Wave bridge connection for cellular endpoint *
-* *
-* +------+ +------+ *
-* | Wave1| | Topo | *
-* | | | | *
-* | | | | *
-* | | | | *
-* System BiDi <--|0 1|<---------------|1 0|<-- BIDI *
-* | | | | *
-* +------+ | | *
-* | | *
-* +------+ | | *
-* | Wave2| | | *
-* | | | | *
-* | | | | *
-* | | | | *
-* System BiDi <--|0 1|<---------------|3 2|<-- BIDI *
-* | | | | *
-* +------+ +------+ *
-* *
-*********************************************************************/
-
-static
-PHYSICALCONNECTIONTABLE CellularTopologyPhysicalConnections[] =
-{
- {
- KSPIN_TOPO_BIDI1_BRIDGE, // TopologyOut
- KSPIN_WAVE_BIDI_BRIDGE, // WaveIn
- CONNECTIONTYPE_TOPOLOGY_OUTPUT
- }
-};
-
-static
-ENDPOINT_MINIPAIR CellularMiniports =
-{
- eCellularDevice,
- L"TopologyCellular", // make sure this or the template name matches with KSNAME_TopologyCellular in the inf's [Strings] section
- NULL, // optional template name
- CreateCellularMiniportTopology,
- &CellularTopoMiniportFilterDescriptor,
- 0, NULL, // Interface properties
- L"WaveCellular", // make sure this or the template name matches with KSNAME_WaveCellular in the inf's [Strings] section
- NULL, // optional template name
- CreateCellularMiniportWaveRT,
- &CellularWaveMiniportFilterDescriptor,
- 0, NULL, // Interface properties
- CELLULAR_DEVICE_MAX_CHANNELS,
- CellularPinDeviceFormatsAndModes,
- SIZEOF_ARRAY(CellularPinDeviceFormatsAndModes),
- CellularTopologyPhysicalConnections,
- SIZEOF_ARRAY(CellularTopologyPhysicalConnections),
- ENDPOINT_CELLULAR_PROVIDER1,
- NULL, 0, NULL, // audio module settings.
-};
-
-
-static
-PHYSICALCONNECTIONTABLE CellularTopologyPhysicalConnections2[] =
-{
- {
- KSPIN_TOPO_BIDI2_BRIDGE, // TopologyOut
- KSPIN_WAVE_BIDI_BRIDGE, // WaveIn
- CONNECTIONTYPE_TOPOLOGY_OUTPUT
- }
-};
-
-static
-ENDPOINT_MINIPAIR CellularMiniports2 =
-{
- eCellularDevice,
- L"TopologyCellular", // make sure this or the template name matches with KSNAME_TopologyCellular in the inf's [Strings] section
- NULL, // optional template name
- CreateCellularMiniportTopology,
- &CellularTopoMiniportFilterDescriptor,
- 0, NULL, // Interface properties
- L"WaveCellular2", // make sure this or the template name matches with KSNAME_WaveCellular in the inf's [Strings] section
- NULL, // optional template name
- CreateCellularMiniportWaveRT,
- &CellularWaveMiniportFilterDescriptor,
- 0, NULL, // Interface properties
- CELLULAR_DEVICE_MAX_CHANNELS,
- CellularPinDeviceFormatsAndModes,
- SIZEOF_ARRAY(CellularPinDeviceFormatsAndModes),
- CellularTopologyPhysicalConnections2,
- SIZEOF_ARRAY(CellularTopologyPhysicalConnections2),
- ENDPOINT_CELLULAR_PROVIDER2,
- NULL, 0, NULL, // audio module settings.
-};
-
-/*********************************************************************
-* Topology/Wave bridge connection for handset speaker endpoint *
-* *
-* +------+ +------+ *
-* | Wave | | Topo | *
-* | | | | *
-* System --->|0 1|---> Loopback | | *
-* | | | | *
-* | 2|--------------->|0 1|---> Line Out *
-* | | | | *
-* +------+ +------+ *
-*********************************************************************/
-static
-PHYSICALCONNECTIONTABLE HandsetSpeakerTopologyPhysicalConnections[] =
-{
- {
- KSPIN_TOPO_WAVEOUT_SOURCE, // TopologyIn
- KSPIN_WAVE_RENDER2_SOURCE, // WaveOut (no offloading)
- CONNECTIONTYPE_WAVE_OUTPUT
- }
-};
-
-static
-ENDPOINT_MINIPAIR HandsetSpeakerMiniports =
-{
- eHandsetSpeakerDevice,
- HANDSET_SPEAKER_TOPONAME, // defined in cellulartopo.h for use with cellular routing control
- NULL, // optional template name
- CreateHandsetSpeakerMiniportTopology,
- &HandsetSpeakerTopoMiniportFilterDescriptor,
- 0, NULL, // Interface properties
- L"WaveHandsetSpeaker", // make sure this or the template name matches with KSNAME_WaveHandsetSpeaker in the inf's [Strings] section
- NULL, // optional template name
- CreateMiniportWaveRTSYSVAD,
- &HandsetSpeakerWaveMiniportFilterDescriptor,
- 0, NULL, // Interface properties
- HANDSETSPEAKER_DEVICE_MAX_CHANNELS,
- HandsetSpeakerPinDeviceFormatsAndModes,
- SIZEOF_ARRAY(HandsetSpeakerPinDeviceFormatsAndModes),
- HandsetSpeakerTopologyPhysicalConnections,
- SIZEOF_ARRAY(HandsetSpeakerTopologyPhysicalConnections),
- ENDPOINT_LOOPBACK_SUPPORTED,
- NULL, 0, NULL, // audio module settings.
-};
-
-//
-// handset microphone miniports.
-//
-
-/*********************************************************************
-* Topology/Wave bridge connection for mic in *
-* *
-* +------+ +------+ *
-* | Topo | | Wave | *
-* | | | | *
-* Mic in --->|0 1|===>|0 1|---> Capture Host Pin *
-* | | | | *
-* +------+ +------+ *
-*********************************************************************/
-static
-PHYSICALCONNECTIONTABLE HandsetMicTopologyPhysicalConnections[] =
-{
- {
- KSPIN_TOPO_BRIDGE, // TopologyOut
- KSPIN_WAVE_BRIDGE, // WaveIn
- CONNECTIONTYPE_TOPOLOGY_OUTPUT
- }
-};
-
-static
-ENDPOINT_MINIPAIR HandsetMicMiniports =
-{
- eHandsetMicDevice,
- HANDSET_MIC_TOPONAME, // defined in cellulartopo.h for use with cellular routing control
- NULL, // optional template name
- CreateMiniportTopologySYSVAD,
- &HandsetMicTopoMiniportFilterDescriptor,
- 0, NULL, // Interface properties
- L"WaveHandsetMic", // make sure this or the template name matches with KSNAME_WaveHandsetMic in the inf's [Strings] section
- NULL, // optional template name
- CreateMiniportWaveRTSYSVAD,
- &HandsetMicWaveMiniportFilterDescriptor,
- 0, NULL, // Interface properties
- HANDSETMIC_DEVICE_MAX_CHANNELS,
- HandsetMicPinDeviceFormatsAndModes,
- SIZEOF_ARRAY(HandsetMicPinDeviceFormatsAndModes),
- HandsetMicTopologyPhysicalConnections,
- SIZEOF_ARRAY(HandsetMicTopologyPhysicalConnections),
- ENDPOINT_NO_FLAGS,
- NULL, 0, NULL, // audio module settings.
-};
-
-/*********************************************************************
-* Topology/Wave bridge connection for FM RX *
-* *
-* +------+ +------+ *
-* | Topo | | Wave | *
-* | | | | *
-* FM RX --->|0 1|===>|1 0|---> Capture Host Pin *
-* | | | | *
-* +------+ +------+ *
-*********************************************************************/
-static
-PHYSICALCONNECTIONTABLE FmRxTopologyPhysicalConnections[] =
-{
- {
- KSPIN_TOPO_FMRX_BRIDGE, // TopologyOut
- KSPIN_WAVE_FMRX_BRIDGE, // WaveIn
- CONNECTIONTYPE_TOPOLOGY_OUTPUT
- }
-};
-
-static
-ENDPOINT_MINIPAIR FmRxMiniports =
-{
- eFmRxDevice,
- L"TopologyFmRx", // make sure this name matches with KSNAME_TopologyFmRx
- NULL, // optional template name
- CreateFmMiniportTopology,
- &FmTopoMiniportFilterDescriptor,
- 0, NULL, // Interface properties
- L"WaveFmRx", // make sure this or the template name matches with KSNAME_WaveFmRx in the inf's [Strings] section
- NULL, // optional template name
- CreateFmMiniportWaveRT,
- &FmWaveMiniportFilterDescriptor,
- 0, NULL, // Interface properties
- FMRX_DEVICE_MAX_CHANNELS,
- FmRxPinDeviceFormatsAndModes,
- SIZEOF_ARRAY(FmRxPinDeviceFormatsAndModes),
- FmRxTopologyPhysicalConnections,
- SIZEOF_ARRAY(FmRxTopologyPhysicalConnections),
- ENDPOINT_NO_FLAGS,
- NULL, 0, NULL, // audio module settings.
-};
-
-//=============================================================================
-//
-// Render miniport pairs. NOTE: the split of render and capture is arbitrary and
-// unnessary, this array could contain capture endpoints.
-//
-static
-PENDPOINT_MINIPAIR g_RenderEndpoints[] =
-{
- &SpeakerMiniports,
- &SpeakerHsMiniports,
- &HandsetSpeakerMiniports,
- &CellularMiniports, // SIM 1
- &CellularMiniports2 // SIM 2
-};
-
-#define g_cRenderEndpoints (SIZEOF_ARRAY(g_RenderEndpoints))
-
-//=============================================================================
-//
-// Capture miniport pairs. NOTE: the split of render and capture is arbitrary and
-// unnessary, this array could contain render endpoints.
-//
-static
-PENDPOINT_MINIPAIR g_CaptureEndpoints[] =
-{
- &MicHsMiniports,
- &MicArray1Miniports,
- &HandsetMicMiniports,
- &FmRxMiniports
-};
-
-#define g_cCaptureEndpoints (SIZEOF_ARRAY(g_CaptureEndpoints))
-
-//=============================================================================
-//
-// Total miniports = # endpoints * 2 (topology + wave).
-//
-#define g_MaxMiniports ((g_cRenderEndpoints + g_cCaptureEndpoints) * 2)
-
-#endif // _SYSVAD_MINIPAIRS_H_
-
diff --git a/audio/sysvad/PhoneAudioSample/phoneaudiosample.inx b/audio/sysvad/PhoneAudioSample/phoneaudiosample.inx
deleted file mode 100644
index a1d45cf4..00000000
--- a/audio/sysvad/PhoneAudioSample/phoneaudiosample.inx
+++ /dev/null
Binary files differ
diff --git a/audio/sysvad/PhoneAudioSample/speakerhstopo.cpp b/audio/sysvad/PhoneAudioSample/speakerhstopo.cpp
deleted file mode 100644
index bbd7a97c..00000000
--- a/audio/sysvad/PhoneAudioSample/speakerhstopo.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- speakerhstopo.cpp
-
-Abstract:
-
- Implementation of topology miniport for the speaker (external: headset).
-
---*/
-
-#pragma warning (disable : 4127)
-
-#include <sysvad.h>
-#include "simple.h"
-#include "mintopo.h"
-#include "speakerhstopo.h"
-#include "speakerhstoptable.h"
-
-
-#pragma code_seg("PAGE")
-
-//=============================================================================
-NTSTATUS
-PropertyHandler_SpeakerHsJackDescription
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
- Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION )
-
-Arguments:
-
- PropertyRequest -
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandler_SpeakerHsJackDescription]"));
-
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
- ULONG nPinId = (ULONG)-1;
-
- ULONG cJackDescriptions = ARRAYSIZE(SpeakerHsJackDescriptions);
- PKSJACK_DESCRIPTION * JackDescriptions = SpeakerHsJackDescriptions;
-
- if (PropertyRequest->InstanceSize >= sizeof(ULONG))
- {
- nPinId = *(PULONG(PropertyRequest->Instance));
-
- if ((nPinId < cJackDescriptions) && (JackDescriptions[nPinId] != NULL))
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ntStatus =
- PropertyHandler_BasicSupport
- (
- PropertyRequest,
- KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET,
- VT_ILLEGAL
- );
- }
- else
- {
- ULONG cbNeeded = sizeof(KSMULTIPLE_ITEM) + sizeof(KSJACK_DESCRIPTION);
-
- if (PropertyRequest->ValueSize == 0)
- {
- PropertyRequest->ValueSize = cbNeeded;
- ntStatus = STATUS_BUFFER_OVERFLOW;
- }
- else if (PropertyRequest->ValueSize < cbNeeded)
- {
- ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value;
- PKSJACK_DESCRIPTION pDesc = (PKSJACK_DESCRIPTION)(pMI+1);
-
- pMI->Size = cbNeeded;
- pMI->Count = 1;
-
- RtlCopyMemory(pDesc, JackDescriptions[nPinId], sizeof(KSJACK_DESCRIPTION));
- ntStatus = STATUS_SUCCESS;
- }
- }
- }
- }
- }
-
- return ntStatus;
-}
-
-//=============================================================================
-NTSTATUS
-PropertyHandler_SpeakerHsJackDescription2
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
- Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION2 )
-
-Arguments:
-
- PropertyRequest -
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandler_SpeakerHsJackDescription2]"));
-
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
- ULONG nPinId = (ULONG)-1;
-
- ULONG cJackDescriptions = ARRAYSIZE(SpeakerHsJackDescriptions);
- PKSJACK_DESCRIPTION * JackDescriptions = SpeakerHsJackDescriptions;
-
- if (PropertyRequest->InstanceSize >= sizeof(ULONG))
- {
- nPinId = *(PULONG(PropertyRequest->Instance));
-
- if ((nPinId < cJackDescriptions) && (JackDescriptions[nPinId] != NULL))
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
- {
- ntStatus =
- PropertyHandler_BasicSupport
- (
- PropertyRequest,
- KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET,
- VT_ILLEGAL
- );
- }
- else
- {
- ULONG cbNeeded = sizeof(KSMULTIPLE_ITEM) + sizeof(KSJACK_DESCRIPTION2);
-
- if (PropertyRequest->ValueSize == 0)
- {
- PropertyRequest->ValueSize = cbNeeded;
- ntStatus = STATUS_BUFFER_OVERFLOW;
- }
- else if (PropertyRequest->ValueSize < cbNeeded)
- {
- ntStatus = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
- {
- PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value;
- PKSJACK_DESCRIPTION2 pDesc = (PKSJACK_DESCRIPTION2)(pMI+1);
-
- pMI->Size = cbNeeded;
- pMI->Count = 1;
-
- RtlZeroMemory(pDesc, sizeof(KSJACK_DESCRIPTION2));
-
- //
- // Specifies the lower 16 bits of the DWORD parameter. This parameter indicates whether
- // the jack is currently active, streaming, idle, or hardware not ready.
- //
- pDesc->DeviceStateInfo = 0;
-
- //
- // From MSDN:
- // "If an audio device lacks jack presence detection, the IsConnected member of
- // the KSJACK_DESCRIPTION structure must always be set to TRUE. To remove the
- // ambiguity that results from this dual meaning of the TRUE value for IsConnected,
- // a client application can call IKsJackDescription2::GetJackDescription2 to read
- // the JackCapabilities flag of the KSJACK_DESCRIPTION2 structure. If this flag has
- // the JACKDESC2_PRESENCE_DETECT_CAPABILITY bit set, it indicates that the endpoint
- // does in fact support jack presence detection. In that case, the return value of
- // the IsConnected member can be interpreted to accurately reflect the insertion status
- // of the jack."
- //
- // Bit definitions:
- // 0x00000001 - JACKDESC2_PRESENCE_DETECT_CAPABILITY
- // 0x00000002 - JACKDESC2_DYNAMIC_FORMAT_CHANGE_CAPABILITY
- //
- pDesc->JackCapabilities = JACKDESC2_PRESENCE_DETECT_CAPABILITY;
-
- ntStatus = STATUS_SUCCESS;
- }
- }
- }
- }
- }
-
- return ntStatus;
-}
-
-
-//=============================================================================
-NTSTATUS
-PropertyHandler_SpeakerHsTopoFilter
-(
- _In_ PPCPROPERTY_REQUEST PropertyRequest
-)
-/*++
-
-Routine Description:
-
- Redirects property request to miniport object
-
-Arguments:
-
- PropertyRequest -
-
-Return Value:
-
- NT status code.
-
---*/
-{
- PAGED_CODE();
-
- ASSERT(PropertyRequest);
-
- DPF_ENTER(("[PropertyHandler_SpeakerHsTopoFilter]"));
-
- // PropertryRequest structure is filled by portcls.
- // MajorTarget is a pointer to miniport object for miniports.
- //
- NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
-
- //
- // This line shows how to get a pointer to the miniport topology object.
- //
- PCMiniportTopology pMiniport = (PCMiniportTopology)PropertyRequest->MajorTarget;
- UNREFERENCED_VAR(pMiniport);
-
- if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Jack))
- {
- if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION)
- {
- ntStatus = PropertyHandler_SpeakerHsJackDescription(PropertyRequest);
- }
- else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION2)
- {
- ntStatus = PropertyHandler_SpeakerHsJackDescription2(PropertyRequest);
- }
- }
-
- return ntStatus;
-} // PropertyHandler_SpeakerHsTopoFilter
-
-#pragma code_seg()
-
diff --git a/audio/sysvad/PhoneAudioSample/speakerhstopo.h b/audio/sysvad/PhoneAudioSample/speakerhstopo.h
deleted file mode 100644
index ea7c760f..00000000
--- a/audio/sysvad/PhoneAudioSample/speakerhstopo.h
+++ /dev/null
@@ -1,21 +0,0 @@
-
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- speakerhstopo.h
-
-Abstract:
-
- Declaration of topology miniport for the speaker (external: headset).
-
---*/
-
-#ifndef _SYSVAD_SPEAKERHSTOPO_H_
-#define _SYSVAD_SPEAKERHSTOPO_H_
-
-NTSTATUS PropertyHandler_SpeakerHsTopoFilter(_In_ PPCPROPERTY_REQUEST PropertyRequest);
-
-#endif // _SYSVAD_SPEAKERHSTOPO_H_
diff --git a/audio/sysvad/PhoneAudioSample/speakerhstoptable.h b/audio/sysvad/PhoneAudioSample/speakerhstoptable.h
deleted file mode 100644
index adb941ff..00000000
--- a/audio/sysvad/PhoneAudioSample/speakerhstoptable.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- speakerhstoptable.h
-
-Abstract:
-
- Declaration of topology tables for the speaker (external: headset).
-
---*/
-
-#ifndef _SYSVAD_SPEAKERHSTOPTABLE_H_
-#define _SYSVAD_SPEAKERHSTOPTABLE_H_
-
-#include <mintopo.h>
-
-//=============================================================================
-static
-KSDATARANGE SpeakerHsTopoPinDataRangesBridge[] =
-{
- {
- sizeof(KSDATARANGE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
- }
-};
-
-//=============================================================================
-static
-PKSDATARANGE SpeakerHsTopoPinDataRangePointersBridge[] =
-{
- &SpeakerHsTopoPinDataRangesBridge[0]
-};
-
-//=============================================================================
-static
-PCPIN_DESCRIPTOR SpeakerHsTopoMiniportPins[] =
-{
- // KSPIN - topology filter in-pin
- {
- 0,
- 0,
- 0, // InstanceCount
- NULL, // AutomationTable
- { // KsPinDescriptor
- 0, // InterfacesCount
- NULL, // Interfaces
- 0, // MediumsCount
- NULL, // Mediums
- SIZEOF_ARRAY(SpeakerHsTopoPinDataRangePointersBridge),// DataRangesCount
- SpeakerHsTopoPinDataRangePointersBridge, // DataRanges
- KSPIN_DATAFLOW_IN, // DataFlow
- KSPIN_COMMUNICATION_NONE, // Communication
- &KSCATEGORY_AUDIO, // Category
- NULL, // Name
- 0 // Reserved
- }
- },
- // KSPIN - topology filter out-pin
- {
- 0,
- 0,
- 0, // InstanceCount
- NULL, // AutomationTable
- { // KsPinDescriptor
- 0, // InterfacesCount
- NULL, // Interfaces
- 0, // MediumsCount
- NULL, // Mediums
- SIZEOF_ARRAY(SpeakerHsTopoPinDataRangePointersBridge),// DataRangesCount
- SpeakerHsTopoPinDataRangePointersBridge, // DataRanges
- KSPIN_DATAFLOW_OUT, // DataFlow
- KSPIN_COMMUNICATION_NONE, // Communication
- &KSNODETYPE_HEADSET_SPEAKERS, // Category
- NULL, // Name
- 0 // Reserved
- }
- }
-};
-
-static
-KSJACK_DESCRIPTION SpeakerHsJackDesc =
-{
- KSAUDIO_SPEAKER_MONO,
- JACKDESC_RGB(179, 201, 140),
- eConnTypeCombination,
- eGeoLocRear,
- eGenLocPrimaryBox,
- ePortConnJack,
- FALSE // NOTE: For convenience, wired headset jacks will be "unplugged" at boot.
-};
-
-//=============================================================================
-// Only return a KSJACK_DESCRIPTION for the physical bridge pin.
-static
-PKSJACK_DESCRIPTION SpeakerHsJackDescriptions[] =
-{
- NULL,
- &SpeakerHsJackDesc
-};
-
-//=============================================================================
-static
-PCCONNECTION_DESCRIPTOR SpeakerHsTopoMiniportConnections[] =
-{
- // FromNode, FromPin, ToNode, ToPin
- { PCFILTER_NODE, KSPIN_TOPO_WAVEOUT_SOURCE, PCFILTER_NODE, KSPIN_TOPO_LINEOUT_DEST}
-};
-
-
-//=============================================================================
-static
-PCPROPERTY_ITEM PropertiesSpeakerHsTopoFilter[] =
-{
- {
- &KSPROPSETID_Jack,
- KSPROPERTY_JACK_DESCRIPTION,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_SpeakerHsTopoFilter
- },
- {
- &KSPROPSETID_Jack,
- KSPROPERTY_JACK_DESCRIPTION2,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_SpeakerHsTopoFilter
- }
-};
-
-static PCEVENT_ITEM SpeakerHsJackInfoChangeEvent[] =
-{
- {
- &KSEVENTSETID_PinCapsChange, // Something changed
- KSEVENT_PINCAPS_JACKINFOCHANGE, // Jack Info Changes
- KSEVENT_TYPE_ENABLE | KSEVENT_TYPE_BASICSUPPORT,
- CMiniportTopology_EventHandler_JackState
- }
-};
-
-DEFINE_PCAUTOMATION_TABLE_PROP_EVENT(AutomationSpeakerHsTopoFilter, PropertiesSpeakerHsTopoFilter, SpeakerHsJackInfoChangeEvent);
-
-//=============================================================================
-static
-PCFILTER_DESCRIPTOR SpeakerHsTopoMiniportFilterDescriptor =
-{
- 0, // Version
- &AutomationSpeakerHsTopoFilter, // AutomationTable
- sizeof(PCPIN_DESCRIPTOR), // PinSize
- SIZEOF_ARRAY(SpeakerHsTopoMiniportPins), // PinCount
- SpeakerHsTopoMiniportPins, // Pins
- sizeof(PCNODE_DESCRIPTOR), // NodeSize
- 0, // NodeCount
- NULL, // Nodes
- SIZEOF_ARRAY(SpeakerHsTopoMiniportConnections), // ConnectionCount
- SpeakerHsTopoMiniportConnections, // Connections
- 0, // CategoryCount
- NULL // Categories
-};
-
-#endif // _SYSVAD_SPEAKERHSTOPTABLE_H_
-
-
diff --git a/audio/sysvad/PhoneAudioSample/speakerhswavtable.h b/audio/sysvad/PhoneAudioSample/speakerhswavtable.h
deleted file mode 100644
index cc7b55fc..00000000
--- a/audio/sysvad/PhoneAudioSample/speakerhswavtable.h
+++ /dev/null
@@ -1,755 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation All Rights Reserved
-
-Module Name:
-
- speakerhswavtable.h
-
-Abstract:
-
- Declaration of wave miniport tables for the speaker (external: headset).
-
---*/
-
-#ifndef _SYSVAD_SPEAKERHSWAVTABLE_H_
-#define _SYSVAD_SPEAKERHSWAVTABLE_H_
-
-
-// To keep the code simple assume device supports only 48KHz, 16-bit, stereo (PCM and NON-PCM)
-
-#define SPEAKERHS_DEVICE_MAX_CHANNELS 2 // Max Channels.
-
-#define SPEAKERHS_HOST_MAX_CHANNELS 2 // Max Channels.
-#define SPEAKERHS_HOST_MIN_BITS_PER_SAMPLE 16 // Min Bits Per Sample
-#define SPEAKERHS_HOST_MAX_BITS_PER_SAMPLE 16 // Max Bits Per Sample
-#define SPEAKERHS_HOST_MIN_SAMPLE_RATE 24000 // Min Sample Rate
-#define SPEAKERHS_HOST_MAX_SAMPLE_RATE 96000 // Max Sample Rate
-
-#define SPEAKERHS_OFFLOAD_MAX_CHANNELS 2 // Max Channels.
-#define SPEAKERHS_OFFLOAD_MIN_BITS_PER_SAMPLE 16 // Min Bits Per Sample
-#define SPEAKERHS_OFFLOAD_MAX_BITS_PER_SAMPLE 16 // Max Bits Per Sample
-#define SPEAKERHS_OFFLOAD_MIN_SAMPLE_RATE 44100 // Min Sample Rate
-#define SPEAKERHS_OFFLOAD_MAX_SAMPLE_RATE 48000 // Max Sample Rate
-
-#define SPEAKERHS_LOOPBACK_MAX_CHANNELS SPEAKERHS_HOST_MAX_CHANNELS // Must be equal to host pin's Max Channels.
-#define SPEAKERHS_LOOPBACK_MIN_BITS_PER_SAMPLE SPEAKERHS_HOST_MIN_BITS_PER_SAMPLE // Must be equal to host pin's Min Bits Per Sample
-#define SPEAKERHS_LOOPBACK_MAX_BITS_PER_SAMPLE SPEAKERHS_HOST_MAX_BITS_PER_SAMPLE // Must be equal to host pin's Max Bits Per Sample
-#define SPEAKERHS_LOOPBACK_MIN_SAMPLE_RATE SPEAKERHS_HOST_MIN_SAMPLE_RATE // Must be equal to host pin's Min Sample Rate
-#define SPEAKERHS_LOOPBACK_MAX_SAMPLE_RATE SPEAKERHS_HOST_MAX_SAMPLE_RATE // Must be equal to host pin's Max Sample Rate
-
-#define SPEAKERHS_DOLBY_DIGITAL_MAX_CHANNELS 2 // Max Channels.
-#define SPEAKERHS_DOLBY_DIGITAL_MIN_BITS_PER_SAMPLE 16 // Min Bits Per Sample
-#define SPEAKERHS_DOLBY_DIGITAL_MAX_BITS_PER_SAMPLE 16 // Max Bits Per Sample
-#define SPEAKERHS_DOLBY_DIGITAL_MIN_SAMPLE_RATE 44100 // Min Sample Rate
-#define SPEAKERHS_DOLBY_DIGITAL_MAX_SAMPLE_RATE 44100 // Max Sample Rate
-
-//
-// Max # of pin instances.
-//
-#define SPEAKERHS_MAX_INPUT_SYSTEM_STREAMS 6
-#define SPEAKERHS_MAX_INPUT_OFFLOAD_STREAMS MAX_INPUT_OFFLOAD_STREAMS
-#define SPEAKERHS_MAX_OUTPUT_LOOPBACK_STREAMS MAX_OUTPUT_LOOPBACK_STREAMS
-
-//=============================================================================
-static
-KSDATAFORMAT_WAVEFORMATEXTENSIBLE SpeakerHsAudioEngineSupportedDeviceFormats[] =
-{
- { // 0 : First entry in htis table is the default format for the audio engine
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 2,
- 44100,
- 176400,
- 4,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_STEREO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 1
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 2,
- 24000,
- 96000,
- 4,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_STEREO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 2
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 2,
- 48000,
- 192000,
- 4,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_STEREO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 3
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 2,
- 88200,
- 352800,
- 4,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_STEREO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 4
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 2,
- 96000,
- 384000,
- 4,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_STEREO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- }
-};
-
-static
-KSDATAFORMAT_WAVEFORMATEXTENSIBLE SpeakerHsHostPinSupportedDeviceFormats[] =
-{
- { // 0
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 2,
- 24000,
- 96000,
- 4,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_STEREO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 1
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 2,
- 32000,
- 128000,
- 4,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_STEREO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 2
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 2,
- 44100,
- 176400,
- 4,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_STEREO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 3
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 2,
- 48000,
- 192000,
- 4,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_STEREO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 4
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 2,
- 88200,
- 352800,
- 4,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_STEREO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 5
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 2,
- 96000,
- 384000,
- 4,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_STEREO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- }
-};
-
-static
-KSDATAFORMAT_WAVEFORMATEXTENSIBLE SpeakerHsOffloadPinSupportedDeviceFormats[] =
-{
- { // 0
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 2,
- 44100,
- 176400,
- 4,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_STEREO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- },
- { // 1
- {
- sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- {
- {
- WAVE_FORMAT_EXTENSIBLE,
- 2,
- 48000,
- 192000,
- 4,
- 16,
- sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
- },
- 16,
- KSAUDIO_SPEAKER_STEREO,
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)
- }
- }
-};
-
-//
-// Supported modes (only on streaming pins).
-//
-static
-MODE_AND_DEFAULT_FORMAT SpeakerHsHostPinSupportedDeviceModes[] =
-{
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_RAW,
- &SpeakerHsHostPinSupportedDeviceFormats[3].DataFormat // 48KHz
- },
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_DEFAULT,
- &SpeakerHsHostPinSupportedDeviceFormats[3].DataFormat // 48KHz
- },
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_MEDIA,
- &SpeakerHsHostPinSupportedDeviceFormats[3].DataFormat // 48KHz
- },
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_MOVIE,
- &SpeakerHsHostPinSupportedDeviceFormats[3].DataFormat // 48KHz
- },
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS,
- &SpeakerHsHostPinSupportedDeviceFormats[0].DataFormat // 24KHz
- },
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_NOTIFICATION,
- &SpeakerHsHostPinSupportedDeviceFormats[3].DataFormat // 48KHz
- }
-};
-
-static
-MODE_AND_DEFAULT_FORMAT SpeakerHsOffloadPinSupportedDeviceModes[] =
-{
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_DEFAULT,
- &SpeakerHsOffloadPinSupportedDeviceFormats[1].DataFormat // 48KHz
- },
- {
- STATIC_AUDIO_SIGNALPROCESSINGMODE_MEDIA,
- &SpeakerHsOffloadPinSupportedDeviceFormats[1].DataFormat // 48KHz
- }
-};
-
-//
-// The entries here must follow the same order as the filter's pin
-// descriptor array.
-//
-static
-PIN_DEVICE_FORMATS_AND_MODES SpeakerHsPinDeviceFormatsAndModes[] =
-{
- {
- SystemRenderPin,
- SpeakerHsHostPinSupportedDeviceFormats,
- SIZEOF_ARRAY(SpeakerHsHostPinSupportedDeviceFormats),
- SpeakerHsHostPinSupportedDeviceModes,
- SIZEOF_ARRAY(SpeakerHsHostPinSupportedDeviceModes)
- },
- {
- OffloadRenderPin,
- SpeakerHsOffloadPinSupportedDeviceFormats,
- SIZEOF_ARRAY(SpeakerHsOffloadPinSupportedDeviceFormats),
- SpeakerHsOffloadPinSupportedDeviceModes,
- SIZEOF_ARRAY(SpeakerHsOffloadPinSupportedDeviceModes),
- },
- {
- RenderLoopbackPin,
- SpeakerHsHostPinSupportedDeviceFormats, // Must support all the formats supported by host pin
- SIZEOF_ARRAY(SpeakerHsHostPinSupportedDeviceFormats),
- NULL, // loopback doesn't support modes.
- 0
- },
- {
- BridgePin,
- NULL,
- 0,
- NULL,
- 0
- },
- {
- NoPin, // For convenience, offload engine device formats appended here
- SpeakerHsAudioEngineSupportedDeviceFormats,
- SIZEOF_ARRAY(SpeakerHsAudioEngineSupportedDeviceFormats),
- NULL, // no modes for this entry.
- 0
- }
-};
-
-//=============================================================================
-static
-KSDATARANGE_AUDIO SpeakerHsPinDataRangesStream[] =
-{
- { // 0
- {
- sizeof(KSDATARANGE_AUDIO),
- KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- SPEAKERHS_HOST_MAX_CHANNELS,
- SPEAKERHS_HOST_MIN_BITS_PER_SAMPLE,
- SPEAKERHS_HOST_MAX_BITS_PER_SAMPLE,
- SPEAKERHS_HOST_MIN_SAMPLE_RATE,
- SPEAKERHS_HOST_MAX_SAMPLE_RATE
- },
- { // 1
- {
- sizeof(KSDATARANGE_AUDIO),
- KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- SPEAKERHS_OFFLOAD_MAX_CHANNELS,
- SPEAKERHS_OFFLOAD_MIN_BITS_PER_SAMPLE,
- SPEAKERHS_OFFLOAD_MAX_BITS_PER_SAMPLE,
- SPEAKERHS_OFFLOAD_MIN_SAMPLE_RATE,
- SPEAKERHS_OFFLOAD_MAX_SAMPLE_RATE
- },
- { // 2
- {
- sizeof(KSDATARANGE_AUDIO),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
- },
- SPEAKERHS_LOOPBACK_MAX_CHANNELS,
- SPEAKERHS_LOOPBACK_MIN_BITS_PER_SAMPLE,
- SPEAKERHS_LOOPBACK_MAX_BITS_PER_SAMPLE,
- SPEAKERHS_LOOPBACK_MIN_SAMPLE_RATE,
- SPEAKERHS_LOOPBACK_MAX_SAMPLE_RATE
- }
-};
-
-static
-PKSDATARANGE SpeakerHsPinDataRangePointersStream[] =
-{
- PKSDATARANGE(&SpeakerHsPinDataRangesStream[0]),
- PKSDATARANGE(&PinDataRangeAttributeList)
-};
-
-static
-PKSDATARANGE SpeakerHsPinDataRangePointersOffloadStream[] =
-{
- PKSDATARANGE(&SpeakerHsPinDataRangesStream[1]),
- PKSDATARANGE(&PinDataRangeAttributeList)
-};
-
-static
-PKSDATARANGE SpeakerHsPinDataRangePointersLoopbackStream[] =
-{
- PKSDATARANGE(&SpeakerHsPinDataRangesStream[2])
-};
-
-//=============================================================================
-static
-KSDATARANGE SpeakerHsPinDataRangesBridge[] =
-{
- {
- sizeof(KSDATARANGE),
- 0,
- 0,
- 0,
- STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
- STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
- STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
- }
-};
-
-static
-PKSDATARANGE SpeakerHsPinDataRangePointersBridge[] =
-{
- &SpeakerHsPinDataRangesBridge[0]
-};
-
-//=============================================================================
-
-static
-PCPROPERTY_ITEM PropertiesSpeakerHsOffloadPin[] =
-{
- {
- &KSPROPSETID_OffloadPin, // define new property set
- KSPROPERTY_OFFLOAD_PIN_GET_STREAM_OBJECT_POINTER, // define properties
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_OffloadPin
- },
- {
- &KSPROPSETID_OffloadPin, // define new property set
- KSPROPERTY_OFFLOAD_PIN_VERIFY_STREAM_OBJECT_POINTER, // define properties
- KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_OffloadPin
- }
-};
-
-DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerHsOffloadPin, PropertiesSpeakerHsOffloadPin);
-
-//=============================================================================
-static
-PCPIN_DESCRIPTOR SpeakerHsWaveMiniportPins[] =
-{
- // Wave Out Streaming Pin (renderer) KSPIN_WAVE_RENDER_SINK_SYSTEM
- {
- SPEAKERHS_MAX_INPUT_SYSTEM_STREAMS,
- SPEAKERHS_MAX_INPUT_SYSTEM_STREAMS,
- 0,
- NULL,
- {
- 0,
- NULL,
- 0,
- NULL,
- SIZEOF_ARRAY(SpeakerHsPinDataRangePointersStream),
- SpeakerHsPinDataRangePointersStream,
- KSPIN_DATAFLOW_IN,
- KSPIN_COMMUNICATION_SINK,
- &KSCATEGORY_AUDIO,
- NULL,
- 0
- }
- },
- // Wave Out Streaming Pin (Renderer) KSPIN_WAVE_RENDER_SINK_OFFLOAD
- {
- SPEAKERHS_MAX_INPUT_OFFLOAD_STREAMS,
- SPEAKERHS_MAX_INPUT_OFFLOAD_STREAMS,
- 0,
- &AutomationSpeakerHsOffloadPin, // AutomationTable
- {
- 0,
- NULL,
- 0,
- NULL,
- SIZEOF_ARRAY(SpeakerHsPinDataRangePointersOffloadStream),
- SpeakerHsPinDataRangePointersOffloadStream,
- KSPIN_DATAFLOW_IN,
- KSPIN_COMMUNICATION_SINK,
- &KSCATEGORY_AUDIO,
- NULL,
- 0
- }
- },
- // Wave Out Streaming Pin (Renderer) KSPIN_WAVE_RENDER_SINK_LOOPBACK
- {
- SPEAKERHS_MAX_OUTPUT_LOOPBACK_STREAMS,
- SPEAKERHS_MAX_OUTPUT_LOOPBACK_STREAMS,
- 0,
- NULL,
- {
- 0,
- NULL,
- 0,
- NULL,
- SIZEOF_ARRAY(SpeakerHsPinDataRangePointersLoopbackStream),
- SpeakerHsPinDataRangePointersLoopbackStream,
- KSPIN_DATAFLOW_OUT,
- KSPIN_COMMUNICATION_SINK,
- &KSNODETYPE_AUDIO_LOOPBACK,
- NULL,
- 0
- }
- },
- // Wave Out Bridge Pin (Renderer) KSPIN_WAVE_RENDER_SOURCE
- {
- 0,
- 0,
- 0,
- NULL,
- {
- 0,
- NULL,
- 0,
- NULL,
- SIZEOF_ARRAY(SpeakerHsPinDataRangePointersBridge),
- SpeakerHsPinDataRangePointersBridge,
- KSPIN_DATAFLOW_OUT,
- KSPIN_COMMUNICATION_NONE,
- &KSCATEGORY_AUDIO,
- NULL,
- 0
- }
- },
-};
-
-//=============================================================================
-static
-PCNODE_DESCRIPTOR SpeakerHsWaveMiniportNodes[] =
-{
- // KSNODE_WAVE_AUDIO_ENGINE
- {
- 0, // Flags
- NULL, // AutomationTable
- &KSNODETYPE_AUDIO_ENGINE, // Type KSNODETYPE_AUDIO_ENGINE
- NULL // Name
- }
-};
-//=============================================================================
-//
-// ----------------------------
-// | |
-// System Pin 0-->| |--> 2 Loopback Pin
-// | HW Audio Engine node |
-// Offload Pin 1-->| |--> 3 KSPIN_WAVE_RENDER_SOURCE
-// | |
-// ----------------------------
-static
-PCCONNECTION_DESCRIPTOR SpeakerHsWaveMiniportConnections[] =
-{
- { PCFILTER_NODE, KSPIN_WAVE_RENDER_SINK_SYSTEM, KSNODE_WAVE_AUDIO_ENGINE, 1 },
- { PCFILTER_NODE, KSPIN_WAVE_RENDER_SINK_OFFLOAD, KSNODE_WAVE_AUDIO_ENGINE, 2 },
- { KSNODE_WAVE_AUDIO_ENGINE, 3, PCFILTER_NODE, KSPIN_WAVE_RENDER_SINK_LOOPBACK },
- { KSNODE_WAVE_AUDIO_ENGINE, 0, PCFILTER_NODE, KSPIN_WAVE_RENDER_SOURCE },
-};
-
-//=============================================================================
-static
-PCPROPERTY_ITEM PropertiesSpeakerHsWaveFilter[] =
-{
- {
- &KSPROPSETID_Pin,
- KSPROPERTY_PIN_PROPOSEDATAFORMAT,
- KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_WaveFilter
- },
- {
- &KSPROPSETID_Pin,
- KSPROPERTY_PIN_PROPOSEDATAFORMAT2,
- KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
- PropertyHandler_WaveFilter
- }
-};
-
-DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerHsWaveFilter, PropertiesSpeakerHsWaveFilter);
-
-//=============================================================================
-static
-PCFILTER_DESCRIPTOR SpeakerHsWaveMiniportFilterDescriptor =
-{
- 0, // Version
- &AutomationSpeakerHsWaveFilter, // AutomationTable
- sizeof(PCPIN_DESCRIPTOR), // PinSize
- SIZEOF_ARRAY(SpeakerHsWaveMiniportPins), // PinCount
- SpeakerHsWaveMiniportPins, // Pins
- sizeof(PCNODE_DESCRIPTOR), // NodeSize
- SIZEOF_ARRAY(SpeakerHsWaveMiniportNodes), // NodeCount
- SpeakerHsWaveMiniportNodes, // Nodes
- SIZEOF_ARRAY(SpeakerHsWaveMiniportConnections), // ConnectionCount
- SpeakerHsWaveMiniportConnections, // Connections
- 0, // CategoryCount
- NULL // Categories - use defaults (audio, render, capture)
-};
-
-#endif // _SYSVAD_SPEAKERHSWAVTABLE_H_
-
diff --git a/audio/sysvad/README.md b/audio/sysvad/README.md
index d2c07a22..3a799ba2 100644
--- a/audio/sysvad/README.md
+++ b/audio/sysvad/README.md
@@ -5,67 +5,62 @@ languages:
- cpp
products:
- windows
+- windows-wdk
urlFragment: sysvad-virtual-audio-device-driver-sample
---
-<!---
- name: SysVAD Virtual Audio Device Driver Sample
- platform: WDM
- language: cpp
- category: Audio
- description: The Microsoft SysVAD Virtual Audio Device Driver (SYSVAD) shows how to develop a WDM audio driver that exposes support for multiple audio devices.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620183
---->
-
# SysVAD Virtual Audio Device Driver Sample
+## Important note
+
+With the [end of support for Windows 10 Mobile](https://support.microsoft.com/help/4484693/windows-10-mobile-end-of-support), the Phone Audio sample has been also removed from the SysVAD driver sample.
+
+## Introduction
+
The Microsoft SysVAD Virtual Audio Device Driver (SYSVAD) shows how to develop a WDM audio driver that exposes support for multiple audio devices.
Some of these audio devices are embedded in the system (for example, speakers, microphone arrays) while others are pluggable (like headphones, Bluetooth headsets etc.). The driver uses WaveRT and audio offloading for rendering devices. The driver uses a "virtual audio device" instead of an actual hardware-based adapter, and highlights the different aspects of the audio offloading WDM audio driver architecture.
Driver developers can use the framework in this sample to provide support for various audio devices without concern for hardware dependencies. The framework includes implementations of the following interfaces:
-- The CAdapterCommon interface gives the miniports access to virtual mixer hardware. It also implements the **IAdapterPowerManagement** interface.
+- The CAdapterCommon interface gives the miniports access to virtual mixer hardware. It also implements the **IAdapterPowerManagement** interface.
-- The CMiniportTopologySYSVAD interface is the base class for all sample topologies. It has very basic common functions. In addition, this class contains common topology property handlers.
+- The CMiniportTopologySYSVAD interface is the base class for all sample topologies. It has very basic common functions. In addition, this class contains common topology property handlers.
The following table shows the features that are implemented in the various subdirectories of this sample.
-Directory | Description
------|------------
-TabletAudioSample | Endpoints that are present in TabletAudioSample driver.
-PhoneAudioSample | Endpoints that are present in PhoneAudioSample driver.
-EndpointsCommon | Endpoints that are present in both TabletAudioSample and PhoneAudioSample. It also contains other common code shared by both sample drivers.
-SwapAPO | Sample APO that installs onto endpoints exposed by the SysVAD sample driver and swaps the left and right channels.
-DelayAPO | Sample APO that adds a delay to the input samples.
-KwsAPO | Sample APO that uses KSPROPERTY_INTERLEAVEDAUDIO_FORMATINFORMATION to determine if the keyword spotter pin is interleaving loopback audio with the microphone audio and identify which channels contain loopback audio. If it is interleaved the APO will strip out the loopback audio and deliver only the microphone audio upstream. Because channel data is removed, the APO negotiates an output format which is different than the input format.
-KeywordDetectorAdapter | Sample Keyword Detector Adapter.
+| Directory | Description |
+| --- | --- |
+| TabletAudioSample | Endpoints that are present in TabletAudioSample driver. |
+| EndpointsCommon | Endpoints that are present in both TabletAudioSample and PhoneAudioSample. It also contains other common code shared by both sample drivers. |
+| SwapAPO | Sample APO that installs onto endpoints exposed by the SysVAD sample driver and swaps the left and right channels. |
+| DelayAPO | Sample APO that adds a delay to the input samples. |
+| KwsAPO | Sample APO that uses KSPROPERTY_INTERLEAVEDAUDIO_FORMATINFORMATION to determine if the keyword spotter pin is interleaving loopback audio with the microphone audio and identify which channels contain loopback audio. If it is interleaved the APO will strip out the loopback audio and deliver only the microphone audio upstream. Because channel data is removed, the APO negotiates an output format which is different than the input format. |
+| KeywordDetectorAdapter | Sample Keyword Detector Adapter. |
-For more information about the Windows audio engine, see [Exposing Hardware-Offloaded Audio Processing in Windows](http://msdn.microsoft.com/en-us/windows/hardware/br259116), and note that audio hardware that is offload-capable replicates the architecture that is presented in the diagram shown in the topic.
+For more information about the Windows audio engine, see [Hardware-Offloaded Audio Processing](https://docs.microsoft.com/windows-hardware/drivers/audio/hardware-offloaded-audio-processing), and note that audio hardware that is offload-capable replicates the architecture that is presented in the diagram shown in the topic.
+## Build the sample
-Build the sample
-----------------
-
-If you simply want to Build this sample driver and don't intend to run or test it, then you do not need a target computer (also called a test computer). If, however, you would like to deploy, run and test this sample driver, then you need a second computer that will server as your target computer. Instructions are provided in the **Run the sample** section to show you how to set up the target computer - also referred to as *provisioning* a target computer.
+If you simply want to Build this sample driver and don't intend to run or test it, then you do not need a target computer (also called a test computer). If, however, you would like to deploy, run and test this sample driver, then you need a second computer that will serve as your target computer. Instructions are provided in the **Run the sample** section to show you how to set up the target computer - also referred to as *provisioning* a target computer.
Perform the following steps to build this sample driver.
-**1. Open the driver solution in Visual Studio**
+### 1. Open the driver solution in Visual Studio
In Microsoft Visual Studio, Click **File** \> **Open** \> **Project/Solution...** and navigate to the folder that contains the sample files (for example, *C:\Windows-driver-samples\audio\sysvad*). Double-click the *sysvad* solution file.
-In Visual Studio locate the Solution Explorer. (If this is not already open, choose **Solution Explorer** from the **View** menu.) In Solution Explorer, you can see one solution that has eight projects.
+In Visual Studio locate the Solution Explorer. (If this is not already open, choose **Solution Explorer** from the **View** menu.) In Solution Explorer, you can see one solution that has seven projects.
-**2. Set the sample's configuration and platform**
+### 2. Set the sample's configuration and platform
-In Solution Explorer, right-click **Solution 'sysvad' (8 projects)**, and choose **Configuration Manager**. Make sure that the configuration and platform settings are the same for the eight projects. By default, the configuration is set to **Debug**, and the platform is set to **Win32** for all the projects. If you make any configuration and/or platform changes for one project, you must make the same changes for the remaining three projects.
+In Solution Explorer, right-click **Solution 'sysvad' (7 of 7 projects)**, and choose **Configuration Manager**. Make sure that the configuration and platform settings are the same for the seven projects. By default, the configuration is set to **Debug**, and the platform is set to **Win32** for all the projects. If you make any configuration and/or platform changes for one project, you must make the same changes for all the remaining projects.
-**3. Build the sample using Visual Studio**
+### 3. Build the sample using Visual Studio
In Visual Studio, click **Build** \> **Build Solution**.
-**4. Locate the built driver package**
+### 4. Locate the built driver package
In File Explorer, navigate to the folder that contains the sample files. For example, you would navigate to *C:\\Windows-driver-samples\\audio\\sysvad*, if that's the folder you specified in the preceding Step 1.
@@ -73,101 +68,118 @@ In the folder, the location of the driver package varies depending on the config
The package should contain these files:
-File | Description
------|------------
-TabletAudioSample.sys OR PhoneAudioSample.sys| The driver file.
-SwapAPO.dll | The swap APO.
-DelayAPO.dll | The delay APO.
-KWSApo.dll | The KWS APO.
-sysvad.cat | A signed catalog file, which serves as the signature for the entire package.
-TabletAudioSample.inf | An information (INF) file that contains information needed to install the driver.
-PhoneAudioSample.inf | An information (INF) file that contains information needed to install the driver.
-KeywordDetectorContosoAdapter.dll | Sample Keyword detector adapter.
+| File | Description |
+| --- | --- |
+| TabletAudioSample.sys | The driver file. |
+| DelayAPO.dll | The delay APO. |
+| KeywordDetectorContosoAdapter.dll | Sample Keyword detector adapter. |
+| KWSApo.dll | The KWS APO. |
+| SwapAPO.dll | The swap APO. |
+| sysvad.cat | A signed catalog file, which serves as the signature for the entire package. |
+| ComponentizedApoSample.inf | A componentized information (INF) file that installs an APO device. |
+| ComponentizedAudioSample.inf | A componentized information (INF) file that contains information needed to install the Tablet Audio Sample driver. |
+| ComponentizedAudioSampleExtension.inf | An extension information (INF) file that extends the Tablet Audio Sample driver functionality by associating an APO device to it. |
+| TabletAudioSample.inf | A non-componentized information (INF) file that contains information needed to install the driver. |
+
+For more information on extension INF files, see [Using an extension INF file](https://docs.microsoft.com/windows-hardware/drivers/install/using-an-extension-inf-file).
-Run the sample
---------------
+## Run the sample
The computer where you install the driver is called the *target computer* or the *test computer*. Typically this is a separate computer from the computer on which you develop and build the driver package. The computer where you develop and build the driver is called the *host computer*.
-The process of moving the driver package to the target computer and installing the driver is called *deploying* the driver. You can deploy the sample driver, TabletAudioSample or PhoneAudioSample, automatically or manually.
+The process of moving the driver package to the target computer and installing the driver is called *deploying* the driver. You can deploy the TabletAudioSample sample driver automatically or manually.
-### Automatic deployment
+### Prepare the target computer
-Before you automatically deploy a driver, you must provision the target computer. Verify that the target computer has an ethernet cable connecting it to your local network, and that your host and target computers can ping each other. Then perform the following steps to prepare your host and target computers.
+First of all, install the latest [Windows Driver Kit](https://docs.microsoft.com/windows-hardware/drivers/download-the-wdk) (WDK) on the target computer.
-**1. Provision the target computer**
+Before you manually deploy a driver, you must prepare the target computer by turning on test signing and by installing a certificate. You also need to locate the DevCon tool in your WDK installation. After that you're ready to run the built driver sample.
-On the target computer install the latest [Windows Driver Kit](http://msdn.microsoft.com/en-us/windows/hardware/gg454513.aspx) (WDK), and then when the installation is completed, navigate to the following folder:
+Open a Command Prompt window as Administrator. Then enter the following command:
-\\Program Files (x86)\\Windows Kits\\10\\Remote\\<*architecture*>\\
+`bcdedit /set TESTSIGNING ON`
-For example, if your target computer is an x64 machine, you would navigate to:
+and reboot the target computer.
-\\Program Files (x86)\\Windows Kits\\10\\Remote\\x64\\
+> [!IMPORTANT]
+> Before using BCDEdit to change boot information you may need to temporarily suspend Windows security features such as BitLocker and Secure Boot on the test PC.
-Double-click the *WDK Test Target Setup x64-x64\_en-us.msi* file to run it. This program prepares the target computer for provisioning.
+Re-enable these security features when testing is complete and appropriately manage the test PC, when the security features are disabled.
-On the host computer, in Visual Studio click **Driver** \> **Test** \> **Configure Computers...**, and then click **Add a new computer**.
+After rebooting, navigate to the Tools folder in your WDK installation and locate the DevCon tool. For example, look in the following folder:
-Type the name of the target computer, select **Provision computer and choose debugger settings**, and click **Next**. In the next window, verify that the **Connection Type** is set to Network. Leave the other (default) settings as they are, and click **Next**. For more information about the settings in this window, see [Getting Set Up for Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/hh450944(v=vs.85).aspx).
+C:\\Program Files (x86)\\Windows Kits\\10\\Tools\\x64\\devcon.exe
-**2. Prepare the host computer**
+Copy *devcon.exe* to a folder on the target computer where it is easier to find. For example, create a *C:\\Tools* folder and copy *devcon.exe* to that folder.
-If you haven't already done so, then preform the steps in the **Build the sample** section, to build the sample driver.
+Create a folder on the target for the built driver package (for example, *C:\\SysvadDriver*). Copy all the files from the built driver package on the host computer and save them to the folder that you created on the target computer.
-In Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties** \> **Driver Install** \> **Deployment**.
+Create a folder on the target computer for the certificate created by the build process. For example, you could create a folder named *C:\\Certificates* on the target computer, and then copy *package.cer* to it from the host computer. You can find this certificate in the same folder on the host computer, as the *package* folder that contains the built driver files. On the target computer, right-click the certificate file, and click **Install**, then follow the prompts to install the test certificate.
-Check , **Enable deployment** and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Hardware ID Driver Update**, and enter *ROOT\Sysvad_TabletAudioSample* for the hardware ID. Click **OK**.
+If you need more detailed instructions for setting up the target computer, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
-On the **Build** menu, choose **Deploy Package** or **Build Solution**. This will deploy the sample driver to your target computer.
+#### A note on signatures
-On the target computer, perform the steps in the **Test the sample** section to test the sample driver.
+Since most of these binary files are executed in kernel mode, it is important that they are signed and, optionally, to have a kernel debugger attached.
-### Manual deployment
+Without any signature or kernel debugger, the driver will not be installed in the target computer. With a kernel debugger attached, the driver can be installed and the driver files (.sys extension) would be loaded, but any user mode files (.dll files) will not be loaded.
-Before you manually deploy a driver, you must prepare the target computer by turning on test signing and by installing a certificate. You also need to locate the DevCon tool in your WDK installation. After that you're ready to run the built driver sample.
+The only way of installing and executing the whole driver sample is to have all the files (.sys, .dll and .cat) signed with a trusted certificate. This will allow the entire driver to be loaded even without a kernel debugger attached.
-**1. Prepare the target computer**
+For more information on the subject, see [Driver signing](https://docs.microsoft.com/windows-hardware/drivers/install/driver-signing).
-Open a Command Prompt window as Administrator. Then enter the following command:
+### Install the driver
-**bcdedit /set TESTSIGNING ON**
+#### Componentized INF files
-Reboot the target computer. Then navigate to the Tools folder in your WDK installation and locate the DevCon tool. For example, look in the following folder:
+The TabletAudioSample driver package contains a sample driver, an extension sample and an APO software component. The following instructions show you how to install and test the sample driver, the APO component and then the extension to apply the software component to the driver.
-*C:\\Program Files (x86)\\Windows Kits\\10\\Tools\\x64\\devcon.exe*
+First, the base INF, *ComponentizedAudioSample.inf*, has to be installed. To install it, open a Command Prompt window as administrator on the target computer, then navigate to your driver package folder and enter the following command:
-Copy *devcon.exe* to a folder on the target computer where it is easier to find. For example, create a *C:\\Tools* folder and copy *devcon.exe* to that folder.
+`devcon install ComponentizedAudioSample.inf Root\Sysvad_ComponentizedAudioSample`
-Create a folder on the target for the built driver package (for example, *C:\\SysvadDriver*). Copy all the files from the built driver package on the host computer and save them to the folder that you created on the target computer.
+If you get an error message about *devcon* not being recognized, try adding the path to the *devcon* tool. For example, if you copied it to a folder called *C:\\Tools*, then try using the following command:
-Create a folder on the target computer for the certificate created by the build process. For example, you could create a folder named *C:\\Certificates* on the target computer, and then copy *package.cer* to it from the host computer. You can find this certificate in the same folder on the host computer, as the *package* folder that contains the built driver files. On the target computer, right-click the certificate file, and click **Install**, then follow the prompts to install the test certificate.
+`C:\\tools\\devcon install ComponentizedAudioSample.inf Root\Sysvad_ComponentizedAudioSample`
-If you need more detailed instructions for setting up the target computer, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
+This installs the base Tablet Audio Sample driver with a hardware ID of "Root\Sysvad_ComponentizedAudioSample".
-**2. Install the driver**
+Then, either the extension INF (*ComponentizedAudioSampleExtension.inf*) or the APO INF (*ComponentizedApoSample.inf*) can be installed.
-The TabletAudioSample or PhoneAudioSample driver package contains a sample driver and 2 driver extension samples. The following instructions show you how to install and test the sample driver.
+If the extension INF is installed first, it will create a new component called *Audio Proxy APO Sample*. Until the APO is installed, this component will appear in Device Manager under the section of Software Components, because it does not have a driver attached yet. The driver is attached by installing the APO INF.
-The INF file required for installing this driver is *TabletAudioSample.inf*.
+If the APO is installed first, it will install a driver, but it will not create a device, so the APO will not be visible in Device Manager until the extension INF creates a software component that will then have the APO driver installed.
-On the target computer, open a Command Prompt window as Administrator. Navigate to your driver package folder, and enter the following command:
+Both extension and APO INFs can be installed by right-clicking on any of the files and selecting "install" from the menu.
-**devcon dp_add TabletAudioSample.inf**
+Once the three componentized INF files are installed, an APO device should appear in Device Manager and the *Microsoft Virtual Audio Device (WDM) - Tablet Audio Sample* device should now be named *SYSVAD (with APO Extensions)*.
-If you get an error message about *devcon* not being recognized, try adding the path to the *devcon* tool. For example, if you copied it to a folder called *C:\\Tools*, then try using the following command:
+For more detailed instructions, see [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1).
+
+#### Single INF files
-**C:\\tools\\devcon dp_add TabletAudioSample.inf**
+TabletAudioSample also contains an INF file, tabletaudiosample.inf, which install the sample driver using a single INF file.
-For more detailed instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/hh698272(v=vs.85).aspx).
+Componentized driver packages are required since Windows 10 1809 release. However, for backward compatibility, instructions on how to install the TabletAudioSample.inf are provided below.
+
+On the target computer, open a Command Prompt window as Administrator. Navigate to your driver package folder, and enter the following command:
+
+`devcon dp_add TabletAudioSample.inf`
After successfully installing the sample driver, you're now ready to test it.
### Test the driver
-On the target computer, in a Command Prompt window, enter **devmgmt** to open Device Manager. In Device Manager, on the **View** menu, choose **Devices by type**. In the device tree, locate *Microsoft Virtual Audio Device (WDM) - Tablet Audio Sample*. This is typically under the **Sound, video and game controllers** node.
+On the target computer, in a Command Prompt window, enter **devmgmt.msc** to open Device Manager. In Device Manager, on the **View** menu, choose **Devices by type**. In the device tree, locate *SYSVAD (with APO Extensions)*. This is typically under the **Sound, video and game controllers** node.
+
+On the target computer, open Control Panel and navigate to **Hardware and Sound** \> **Manage audio devices**. In the Sound dialog box, select the speaker icon labeled as *SYSVAD (with APO Extensions)*, then click **Set Default**, but do not click **OK**. This will keep the Sound dialog box open.
+
+Locate an MP3 or other audio file on the target computer and double-click to play it. Then in the Sound dialog box, verify that there is activity in the volume level indicator associated with the *SYSVAD (with APO Extensions)* driver.
+
+## HLK testing
-On the target computer, open Control Panel and navigate to **Hardware and Sound** \> **Manage audio devices**. In the Sound dialog box, select the speaker icon labeled as *Microsoft Virtual Audio Device (WDM) - Tablet Audio Sample*, then click **Set Default**, but do not click **OK**. This will keep the Sound dialog box open.
+The sample uploaded here is tested using the latest HLK version available to make sure it passes all audio tests in the current playlist. However, since it is a virtual audio driver it does not implement audio mixing and simulates capture and loopback by generating a tone. Given these limitations, there are some HLK tests that are expected to fail because they rely on the described functionality.
-Locate an MP3 or other audio file on the target computer and double-click to play it. Then in the Sound dialog box, verify that there is activity in the volume level indicator associated with the *Microsoft Virtual Audio Device (WDM) - Tablet Audio Sample* driver.
+In the case of audio tests, one of these exceptions is the Hardware Offload of Audio Processing Test. This test is aimed at devices that support offload capabilities and performs checks to make sure that the device complies with the appropiate requirements. In the particular case of SysVAD, this test will fail for endpoints with offload and loopback.
+For endpoints with offload, the test will fail because the driver includes offload pins but it does not implement a mixer with volume, mute and peak meter nodes, etc. For the case of endpoints with loopback, the test will fail because the driver simulates loopback by returning a sine tone instead of performing real mixing of streams in host and/or offload pins. \ No newline at end of file
diff --git a/audio/sysvad/TabletAudioSample/ComponentizedApoSample.inx b/audio/sysvad/TabletAudioSample/ComponentizedApoSample.inx
index 4ee84101..be9428fb 100644
--- a/audio/sysvad/TabletAudioSample/ComponentizedApoSample.inx
+++ b/audio/sysvad/TabletAudioSample/ComponentizedApoSample.inx
Binary files differ
diff --git a/audio/sysvad/TabletAudioSample/ComponentizedAudioSample.inx b/audio/sysvad/TabletAudioSample/ComponentizedAudioSample.inx
index a5e6e73f..8f04a934 100644
--- a/audio/sysvad/TabletAudioSample/ComponentizedAudioSample.inx
+++ b/audio/sysvad/TabletAudioSample/ComponentizedAudioSample.inx
Binary files differ
diff --git a/audio/sysvad/TabletAudioSample/ComponentizedAudioSampleExtension.inx b/audio/sysvad/TabletAudioSample/ComponentizedAudioSampleExtension.inx
index 4f29c985..1c89827a 100644
--- a/audio/sysvad/TabletAudioSample/ComponentizedAudioSampleExtension.inx
+++ b/audio/sysvad/TabletAudioSample/ComponentizedAudioSampleExtension.inx
Binary files differ
diff --git a/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj b/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj
index f7752502..6d60c71a 100644
--- a/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj
+++ b/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj
@@ -263,7 +263,7 @@
<AdditionalDependencies>%(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib</AdditionalDependencies>
</Link>
<ClCompile>
- <!--
+ <!--
Use one of the following pre-processor defines to select the right power management:
- _USE_IPortClsRuntimePower
- _USE_SingleComponentMultiFxStates
@@ -284,6 +284,9 @@
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories>
</ResourceCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<Link>
@@ -303,6 +306,9 @@
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories>
</ResourceCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Link>
@@ -322,6 +328,9 @@
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories>
</ResourceCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<Link>
@@ -341,6 +350,9 @@
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories>
</ResourceCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Link>
@@ -360,6 +372,9 @@
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories>
</ResourceCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Link>
@@ -379,6 +394,9 @@
<PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories>
</ResourceCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\adapter.cpp" />
diff --git a/audio/sysvad/TabletAudioSample/tabletaudiosample.inx b/audio/sysvad/TabletAudioSample/tabletaudiosample.inx
index ba96faee..58ee4d88 100644
--- a/audio/sysvad/TabletAudioSample/tabletaudiosample.inx
+++ b/audio/sysvad/TabletAudioSample/tabletaudiosample.inx
Binary files differ
diff --git a/audio/sysvad/adapter.cpp b/audio/sysvad/adapter.cpp
index 7cfa54ee..cc7960a5 100644
--- a/audio/sysvad/adapter.cpp
+++ b/audio/sysvad/adapter.cpp
@@ -1177,6 +1177,7 @@ Return Value:
switch (stack->MinorFunction)
{
+#ifdef SYSVAD_USB_SIDEBAND
case IRP_MN_QUERY_DEVICE_RELATIONS:
switch (stack->Parameters.QueryDeviceRelations.Type)
@@ -1203,6 +1204,7 @@ Return Value:
break;
}
break;
+#endif // SYSVAD_USB_SIDEBAND
case IRP_MN_REMOVE_DEVICE:
case IRP_MN_SURPRISE_REMOVAL:
diff --git a/audio/sysvad/common.cpp b/audio/sysvad/common.cpp
index f88ca093..9292c96d 100644
--- a/audio/sysvad/common.cpp
+++ b/audio/sysvad/common.cpp
@@ -302,7 +302,9 @@ class CAdapterCommon :
STDMETHODIMP_(VOID) Cleanup();
+#ifdef SYSVAD_USB_SIDEBAND
STDMETHODIMP_(NTSTATUS) UpdatePowerRelations(_In_ PIRP Irp);
+#endif // SYSVAD_USB_SIDEBAND
//=====================================================================
// friends
@@ -608,7 +610,9 @@ Return Value:
InterlockedDecrement(&CAdapterCommon::m_AdapterInstances);
ASSERT(CAdapterCommon::m_AdapterInstances == 0);
+#ifdef SYSVAD_USB_SIDEBAND
ASSERT(IsListEmpty(&m_PowerRelations));
+#endif // SYSVAD_USB_SIDEBAND
} // ~CAdapterCommon
//=============================================================================
@@ -2300,6 +2304,7 @@ CAdapterCommon::Cleanup()
EmptySubdeviceCache();
}
+#ifdef SYSVAD_USB_SIDEBAND
//=============================================================================
#pragma code_seg("PAGE")
NTSTATUS
@@ -2426,6 +2431,7 @@ Exit:
return status;
}
+#endif // SYSVAD_USB_SIDEBAND
//=============================================================================
#pragma code_seg("PAGE")
diff --git a/audio/sysvad/common.h b/audio/sysvad/common.h
index 794b3797..8ce0a866 100644
--- a/audio/sysvad/common.h
+++ b/audio/sysvad/common.h
@@ -206,6 +206,7 @@ typedef struct _PIN_DEVICE_FORMATS_AND_MODES
} PIN_DEVICE_FORMATS_AND_MODES, *PPIN_DEVICE_FORMATS_AND_MODES;
+
//
// Parameter module handler function prototypes.
//
@@ -670,7 +671,9 @@ DECLARE_INTERFACE_(IAdapterCommon, IUnknown)
STDMETHOD_(VOID, Cleanup)();
+#ifdef SYSVAD_USB_SIDEBAND
STDMETHOD_(NTSTATUS, UpdatePowerRelations)(_In_ PIRP Irp);
+#endif // SYSVAD_USB_SIDEBAND
STDMETHOD_(NTSTATUS, NotifyEndpointPair)
(
diff --git a/audio/sysvad/sysvad.sln b/audio/sysvad/sysvad.sln
index 2965165c..6a58b6df 100644
--- a/audio/sysvad/sysvad.sln
+++ b/audio/sysvad/sysvad.sln
@@ -1,4 +1,4 @@
-
+
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27703.2042
@@ -9,8 +9,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "KeywordDetectorAdapter", "K
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EndpointsCommon", "EndpointsCommon", "{0B4B8E51-20A8-43A4-A8DA-42FF90D628AC}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PhoneAudioSample", "PhoneAudioSample", "{D0DBEBE9-0DCC-4EA7-966B-C029C1334D9E}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TabletAudioSample", "TabletAudioSample", "{C06F6070-75EE-4F57-8D35-4AC2AB08D029}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "package", "package\package.VcxProj", "{830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}"
@@ -19,11 +17,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeywordDetectorContosoAdapt
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EndpointsCommon", "EndpointsCommon\EndpointsCommon.vcxproj", "{33E61864-6F2C-4F9F-BE70-8F8985A4F283}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PhoneAudioSample", "PhoneAudioSample\PhoneAudioSample.vcxproj", "{FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}"
- ProjectSection(ProjectDependencies) = postProject
- {33E61864-6F2C-4F9F-BE70-8F8985A4F283} = {33E61864-6F2C-4F9F-BE70-8F8985A4F283}
- EndProjectSection
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TabletAudioSample", "TabletAudioSample\TabletAudioSample.vcxproj", "{E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}"
ProjectSection(ProjectDependencies) = postProject
{33E61864-6F2C-4F9F-BE70-8F8985A4F283} = {33E61864-6F2C-4F9F-BE70-8F8985A4F283}
@@ -83,18 +76,6 @@ Global
{33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|Win32.Build.0 = Release|Win32
{33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|x64.ActiveCfg = Release|x64
{33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|x64.Build.0 = Release|x64
- {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|ARM64.ActiveCfg = Debug|ARM64
- {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|ARM64.Build.0 = Debug|ARM64
- {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|Win32.ActiveCfg = Debug|Win32
- {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|Win32.Build.0 = Debug|Win32
- {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|x64.ActiveCfg = Debug|x64
- {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|x64.Build.0 = Debug|x64
- {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|ARM64.ActiveCfg = Release|ARM64
- {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|ARM64.Build.0 = Release|ARM64
- {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|Win32.ActiveCfg = Release|Win32
- {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|Win32.Build.0 = Release|Win32
- {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|x64.ActiveCfg = Release|x64
- {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|x64.Build.0 = Release|x64
{E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|ARM64.ActiveCfg = Debug|ARM64
{E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|ARM64.Build.0 = Debug|ARM64
{E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|Win32.ActiveCfg = Debug|Win32
@@ -151,7 +132,6 @@ Global
{830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A} = {FA56D96B-290B-4C73-A5E1-02C1861D3224}
{E0F02048-78A4-4FE8-B863-66E6CB6A2C37} = {DBD14E7B-7F95-4743-86E3-4E16FA43F990}
{33E61864-6F2C-4F9F-BE70-8F8985A4F283} = {0B4B8E51-20A8-43A4-A8DA-42FF90D628AC}
- {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE} = {D0DBEBE9-0DCC-4EA7-966B-C029C1334D9E}
{E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF} = {C06F6070-75EE-4F57-8D35-4AC2AB08D029}
{8851AB85-70B3-4798-A149-BA366DF9EC25} = {D86F9A10-C48D-4048-A03C-DD7BCA6E165F}
{691F1D0F-CA50-46CD-8BBA-A59E9E8EB601} = {D86F9A10-C48D-4048-A03C-DD7BCA6E165F}
diff --git a/audio/tests/HLK/ThirdPartyApoTests/APODeviceTest.cpp b/audio/tests/HLK/ThirdPartyApoTests/APODeviceTest.cpp
new file mode 100644
index 00000000..ca3b3a7a
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/APODeviceTest.cpp
@@ -0,0 +1,1120 @@
+#include <stdafx.h>
+
+#include <initguid.h>
+#include "propkey.h"
+#include <AudioClient.h>
+#include <functiondiscoverykeys.h>
+#include <DevPKey.h>
+#include <AudioEngineBaseAPOP.h>
+#include "TestMediaType.h"
+#include "audioconnectionutil.h"
+#include <audioenginebaseapo.h>
+
+#include <WexTestClass.h>
+
+#include <list>
+#include <memory>
+
+#include "APODeviceTest.h"
+#include "Wrappers.h"
+#include "FormatHelpers.h"
+
+
+using namespace std;
+using namespace wil;
+using namespace WEX::Logging;
+using namespace WEX::Common;
+
+#define REGKEY_AUDIOSERVICE L"Software\\Microsoft\\Windows\\CurrentVersion\\Audio"
+#define REGVALUE_SKIPRTHEAP L"SkipRTHeap"
+
+// Forward Declarations
+bool SetupSkipRTHeap();
+bool CleanupSkipRTHeap();
+HRESULT VerifyCustomFormatSupport(CAPODevice * deviceUnderTest);
+HRESULT VerifyValidFrameCount(CAPODevice * deviceUnderTest);
+HRESULT VerifyAPODataStreaming(CAPODevice * deviceUnderTest);
+HRESULT VerifyActivateDeactivate(CAPODevice * deviceUnderTest);
+HRESULT FillConnection
+(
+ UNCOMPRESSEDAUDIOFORMAT* Format,
+ UINT_PTR pBuffer,
+ UINT32 u32ExtraFrameCount,
+ UINT32 u32MaxFrameCount,
+ APO_CONNECTION_DESCRIPTOR* pConnection
+);
+
+bool CApoDeviceTests::setUpMethod()
+{
+ // Populate a vector of each endpoint on the system and wrap it with
+ // an APO test wrapper which will save necessary APO information for
+ // test cases
+ WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
+ com_ptr_nothrow<IMMDeviceEnumerator> spEnumerator;
+ com_ptr_nothrow<IMMDeviceCollection> spDevices;
+
+ UINT32 cDevices;
+ PROPVARIANT var;
+
+ PropVariantInit(&var);
+
+ VERIFY_SUCCEEDED(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&spEnumerator)));
+ VERIFY_SUCCEEDED(spEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &spDevices));
+ VERIFY_SUCCEEDED(spDevices->GetCount(&cDevices));
+
+ // Initialize an APO device list for each device on the system
+ for(UINT32 i = 0; i < cDevices; i++)
+ {
+ com_ptr_nothrow<IMMDevice> spEndpoint;
+ com_ptr_nothrow<IPropertyStore> spPropertyStore;
+
+ VERIFY_SUCCEEDED(spDevices->Item(i, &spEndpoint));
+ VERIFY_SUCCEEDED(spEndpoint->OpenPropertyStore(STGM_READ, &spPropertyStore));
+ VERIFY_SUCCEEDED(spPropertyStore->GetValue(PKEY_Device_FriendlyName, &var));
+ VERIFY_ARE_EQUAL(VT_LPWSTR, var.vt);
+ LOG_OUTPUT(L"Setting Up Endpoint: %s", var.pwszVal);
+
+ unique_ptr<CAPODeviceList> pTestModule(new CAPODeviceList());
+ pTestModule->Initialize(wistd::move(spEndpoint), var.pwszVal);
+ m_testDeviceWrapperList.push_back(move(pTestModule));
+
+ PropVariantClear(&var);
+ }
+
+ return SetupSkipRTHeap();
+}
+
+bool CApoDeviceTests::tearDownMethod()
+{
+ m_testDeviceWrapperList.clear();
+ return CleanupSkipRTHeap();
+}
+
+void CApoDeviceTests::TestAPOInitialize()
+{
+ // In the event that one initialization fails fully, we do not want to fail
+ // the whole test. Instead, mark the test as failed and complete it on all
+ // devices.
+ bool testSucceeded = true;
+
+ m_testDeviceWrapperList.remove_if([&](auto & deviceWrapper) {
+
+ // Print Device Friendly name
+ LOG_OUTPUT(L"Endpoint Under Test: %ls", deviceWrapper->m_deviceName);
+
+ HRESULT hr = deviceWrapper->AddSysFxDevices();
+
+ if (hr == S_FALSE)
+ {
+ // No cause for failure here. Just remove the device from our test list
+ // as it appears to be inactive or has no third party APOs
+ return true;
+ }
+
+ if (FAILED(hr))
+ {
+ LOG_ERROR(L"Device initialization failed with error: %x", hr);
+ testSucceeded = false;
+ }
+ return false;
+
+ });
+
+ VERIFY_IS_TRUE(testSucceeded);
+}
+
+void CApoDeviceTests::TestCustomFormatSupport()
+{
+ bool testSucceeded = true;
+
+ TestAPOInitialize();
+
+ for(auto const& deviceWrapper : m_testDeviceWrapperList)
+ {
+ // Print Device Friendly name
+ LOG_OUTPUT(L"Endpoint Under Test: %ls", deviceWrapper->m_deviceName);
+
+ // Test over each SysFX device on the device
+ for (auto const& apo : deviceWrapper->m_DeviceList)
+ {
+ if (apo->IsProxyApo())
+ {
+ GUID proxyGuid;
+ unique_cotaskmem_string proxyString;
+
+ apo->GetClsID(&proxyGuid);
+ StringFromCLSID(proxyGuid, &proxyString);
+
+ LOG_OUTPUT(L"Proxy APO found. Skipping: %ls", proxyString.get());
+ continue;
+ }
+
+ HRESULT hr = VerifyCustomFormatSupport(apo.get());
+
+ if (hr == S_FALSE)
+ {
+ LOG_OUTPUT(L"\tAPO does not support custom formats. This is not an error");
+ }
+
+ if (FAILED(hr))
+ {
+ LOG_ERROR(L"\tTest Custom Format Support failed with error: (0x%08lx)", hr);
+ testSucceeded = false;
+ }
+ }
+ }
+
+ VERIFY_IS_TRUE(testSucceeded);
+}
+
+void CApoDeviceTests::TestValidFrameCount()
+{
+ bool testSucceeded = true;
+
+ TestAPOInitialize();
+
+ for(auto const& deviceWrapper : m_testDeviceWrapperList)
+ {
+ // Print Device Friendly name
+ LOG_OUTPUT(L"Endpoint Under Test: %ls", deviceWrapper->m_deviceName);
+
+ // Test over each SysFX device on the device
+ for (auto const& apo : deviceWrapper->m_DeviceList)
+ {
+ if (apo->IsProxyApo())
+ {
+ GUID proxyGuid;
+ unique_cotaskmem_string proxyString;
+
+ apo->GetClsID(&proxyGuid);
+ StringFromCLSID(proxyGuid, &proxyString);
+
+ LOG_OUTPUT(L"\tProxy APO found. Skipping: %ls", proxyString.get());
+ continue;
+ }
+
+ HRESULT hr = VerifyValidFrameCount(apo.get());
+
+ if (FAILED(hr))
+ {
+ LOG_ERROR(L"\tTest Valid Frame Count failed with error: (0x%08lx)", hr);
+ testSucceeded = false;
+ }
+ }
+ }
+
+ VERIFY_IS_TRUE(testSucceeded);
+}
+
+void CApoDeviceTests::TestAPODataStreaming()
+{
+ bool testSucceeded = true;
+
+ TestAPOInitialize();
+
+ for(auto const& deviceWrapper : m_testDeviceWrapperList)
+ {
+ // Print Device Friendly name
+ LOG_OUTPUT(L"Endpoint Under Test: %ls", deviceWrapper->m_deviceName);
+
+ // Test over each SysFX device on the device
+ for (auto const& apo : deviceWrapper->m_DeviceList)
+ {
+ if (apo->IsProxyApo())
+ {
+ GUID proxyGuid;
+ unique_cotaskmem_string proxyString;
+
+ apo->GetClsID(&proxyGuid);
+ StringFromCLSID(proxyGuid, &proxyString);
+
+ LOG_OUTPUT(L"\tProxy APO found. Skipping: %ls", proxyString.get());
+ continue;
+ }
+
+ HRESULT hr = VerifyAPODataStreaming(apo.get());
+
+ if (FAILED(hr))
+ {
+ LOG_ERROR(L"\tTest APO Data Streaming failed with error: (0x%08lx)", hr);
+ testSucceeded = false;
+ }
+ }
+ }
+
+ VERIFY_IS_TRUE(testSucceeded);
+}
+
+void CApoDeviceTests::TestActivateDeactivate()
+{
+ bool testSucceeded = true;
+
+ TestAPOInitialize();
+
+ for(auto const& deviceWrapper : m_testDeviceWrapperList)
+ {
+ // Print Device Friendly name
+ LOG_OUTPUT(L"Endpoint Under Test: %ls", deviceWrapper->m_deviceName);
+
+ // Test over each SysFX device on the device
+ for (auto const& apo : deviceWrapper->m_DeviceList)
+ {
+ if (apo->IsProxyApo())
+ {
+ GUID proxyGuid;
+ unique_cotaskmem_string proxyString;
+
+ apo->GetClsID(&proxyGuid);
+ StringFromCLSID(proxyGuid, &proxyString);
+
+ LOG_OUTPUT(L"\tProxy APO found. Skipping: %ls", proxyString.get());
+ continue;
+ }
+
+ HRESULT hr = VerifyActivateDeactivate(apo.get());
+
+ if (FAILED(hr))
+ {
+ LOG_ERROR(L"\tTest Activate and Deactivate failed with error: (0x%08lx)", hr);
+ testSucceeded = false;
+ }
+ }
+ }
+
+ VERIFY_IS_TRUE(testSucceeded);
+}
+
+HRESULT VerifyValidFrameCount(CAPODevice* deviceUnderTest)
+{
+ wil::com_ptr<IAudioProcessingObject> pIAPO;
+ wil::com_ptr<IAudioProcessingObjectRT> pIAPORT;
+ wil::com_ptr<IAudioProcessingObjectConfiguration> pIAPOConfig;
+
+ if (deviceUnderTest == nullptr)
+ {
+ LOG_ERROR(L"\tCould not instantiate SysFx object.\n");
+ return E_NOINTERFACE;
+ }
+
+ LOG_RETURN_IF_FAILED(deviceUnderTest->GetAPOInterfaces(&pIAPO, &pIAPORT, &pIAPOConfig), L"\tCould not instantiate IAudioProcessingObject interface.");
+
+ APO_CONNECTION_PROPERTY inputProperty, outputProperty;
+ APO_CONNECTION_DESCRIPTOR inputDescriptor, outputDescriptor;
+ APO_CONNECTION_PROPERTY *pInputConnProp = &inputProperty, *pOutputConnProp = &outputProperty;
+ APO_CONNECTION_DESCRIPTOR *pInputConnDesc = &inputDescriptor, *pOutputConnDesc = &outputDescriptor;
+ UNCOMPRESSEDAUDIOFORMAT defaultFormat {};
+
+ FillFormat(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 2, sizeof(float), sizeof(float) * 8, static_cast<float>(cFrameRate), KSAUDIO_SPEAKER_STEREO, &defaultFormat);
+
+ LOG_RETURN_IF_FAILED(SetupConnection(pInputConnDesc, pOutputConnDesc, pInputConnProp, pOutputConnProp, &defaultFormat),
+ L"\tSetupConnection failed");
+
+ LOG_RETURN_IF_FAILED(LockForProcess(pIAPOConfig.get(), 1, &pInputConnDesc, 1, &pOutputConnDesc),
+ L"\tLockForProcess failed");
+
+ // setup vectors
+ FLOAT32 *pf32Input, *pf32Output;
+ pf32Input = (FLOAT32*)pInputConnProp->pBuffer;
+ pf32Output = (FLOAT32*)pOutputConnProp->pBuffer;
+ for (UINT32 index = 0; index < cFrameCountToProcess; index++)
+ {
+ pf32Input[index] = 0.5f;
+ pf32Output[index] = 0.0f;
+ }
+
+ APOProcess(pIAPORT.get(), 1, &pInputConnProp, 1, &pOutputConnProp);
+
+ LOG_RETURN_HR_IF(pOutputConnProp->u32ValidFrameCount != cFrameCountToProcess,
+ E_FAIL,
+ L"\tFAIL: APOProcess output(%d) and input(%d) buffer valid frame counts does not match.\n", pOutputConnProp->u32ValidFrameCount, cFrameCountToProcess);
+
+ LOG_RETURN_IF_FAILED(UnlockForProcess(pIAPOConfig.get()),
+ L"\tUnlock for process failed");
+
+ LOG_RETURN_IF_FAILED(DestroyConnection(pInputConnDesc), L"\tFailed to DestroyConnection");
+ LOG_RETURN_IF_FAILED(DestroyConnection(pOutputConnDesc), L"\tFailed to DestroyConnection");
+
+ return S_OK;
+}
+
+HRESULT VerifyCustomFormatSupport(CAPODevice * deviceUnderTest)
+{
+ com_ptr_nothrow<IAudioProcessingObject> pIAPO = nullptr;
+ com_ptr_nothrow<IAudioSystemEffectsCustomFormats> pICustomFormats = nullptr;
+ com_ptr_nothrow<IEndpointUtility> pIEPUtility = nullptr;
+ IMMDevice * pIMMDevice = nullptr;
+ UINT iFormat;
+
+ if (deviceUnderTest == nullptr)
+ {
+ LOG_ERROR(L"\tCould not instantiate SysFx object.");
+ return E_NOINTERFACE;
+ }
+
+ if (nullptr == (pIMMDevice = deviceUnderTest->GetEndpoint()))
+ {
+ LOG_ERROR(L"\tUnable to get endpoint for device.");
+ return E_NOINTERFACE;
+ }
+
+ LOG_RETURN_IF_FAILED(pIMMDevice->Activate(__uuidof(IEndpointUtility), CLSCTX_INPROC_SERVER, NULL, (void**)&pIEPUtility),
+ L"\tUnable to activate utility interface");
+
+ LOG_RETURN_IF_FAILED(deviceUnderTest->GetAPOInterfaces(&pIAPO, nullptr, nullptr), L"\tCould not instantiate IAudioProcessingObject interface.");
+
+ if (pIAPO == nullptr)
+ {
+ LOG_ERROR(L"\tFAIL: Could not instantiate IAudioProcessingObject interface.");
+ return E_NOINTERFACE;
+ }
+
+ HRESULT hrQi = QIInternal(pIAPO.get(), __uuidof(IAudioSystemEffectsCustomFormats), (void**)&pICustomFormats);
+
+ if (E_NOINTERFACE == hrQi)
+ {
+ // This GFX does not support custom formats...
+ LOG_OUTPUT(L"\tSysFx does not support custom formats (QueryInterface for "
+ "IAudioSystemEffectsCustomFormats returns E_NOINTERFACE).");
+ return S_FALSE;
+ }
+
+ LOG_RETURN_IF_FAILED(hrQi, L"\tQueryInterface for IAudioSystemEffectsCustomFormats returned error.");
+
+
+ // Custom formats are available and supported
+ LOG_OUTPUT(L"\tIAudioSystemEffectsCustomFormats available on SysFx.");
+
+ LOG_RETURN_IF_FAILED(pICustomFormats->GetFormatCount(&iFormat),
+ L"\tIAudioSystemEffectsCustomFormats::GetFormatCount failed");
+
+ // No matter what we want to test all formats. However if one fails, make sure we fail
+ // the test as well
+ bool allFormatsSucceeded = true;
+
+ for (; iFormat; --iFormat)
+ {
+ com_ptr_nothrow<IAudioMediaType> pIFormat = nullptr;
+ com_ptr_nothrow<IAudioMediaType> pIFormatSuggested = nullptr;
+ LPWSTR strFormatName = NULL;
+ com_ptr_nothrow<IPartsList> pIParts = nullptr;
+ KSDATAFORMAT_WAVEFORMATEX * pKsFormat = NULL;
+ HRESULT hrFormatSupport = S_OK;
+
+ if (FAILED(hrFormatSupport = pICustomFormats->GetFormat(iFormat - 1, &pIFormat)))
+ {
+ LOG_ERROR(L"\tFAIL: IAudioSystemEffectsCustomFormats::GetFormat returned "
+ "error (0x%08lx).",
+ hrFormatSupport);
+ allFormatsSucceeded = false;
+
+ continue;
+ }
+
+ if (FAILED(hrFormatSupport = pICustomFormats->GetFormatRepresentation(iFormat - 1, &strFormatName)))
+ {
+ LOG_ERROR(L"\tFAIL: IAudioSystemEffectsCustomFormats::"
+ "GetFormatRepresentation returned error (0x%08lx)",
+ hrFormatSupport);
+ allFormatsSucceeded = false;
+
+ continue;
+ }
+
+ LOG_OUTPUT(L"\tVerifying format support for: [%ls]...", strFormatName);
+
+ // Custom format, must be supported on the output side of SysFx...
+ hrFormatSupport = IsOutputFormatSupported(pIAPO.get(), NULL, pIFormat.get(), &pIFormatSuggested);
+ const WAVEFORMATEX* original = pIFormat->GetAudioFormat();
+ const WAVEFORMATEX* suggested = pIFormatSuggested->GetAudioFormat();
+
+ LOG_OUTPUT(L"\tWaveFormatEx pIFormat - tag: %u, channels: %u, samplespersec: %u, avgbytespersec: %u, blockalign: %u, bitspersample: %u, cbsize: %u",
+ original->wFormatTag, original->nChannels, original->nSamplesPerSec, original->nAvgBytesPerSec, original->nBlockAlign,
+ original->wBitsPerSample, original->cbSize);
+
+ LOG_OUTPUT(L"\tWaveFormatEx pIFormatSuggested - tag: %u, channels: %u, samplespersec: %u, avgbytespersec: %u, blockalign: %u, bitspersample: %u, cbsize: %u",
+ suggested->wFormatTag, suggested->nChannels, suggested->nSamplesPerSec, suggested->nAvgBytesPerSec, suggested->nBlockAlign,
+ suggested->wBitsPerSample, suggested->cbSize);
+
+ if (S_FALSE == hrFormatSupport)
+ {
+ LOG_ERROR(L"\tFAIL: IsOutputFormatSupported returns S_FALSE with a suggested format");
+ allFormatsSucceeded = false;
+ }
+ else if (S_OK != hrFormatSupport)
+ {
+ LOG_ERROR(L"\tFAIL: IsOutputFormatSupported returns error (0x%08lx)",
+ hrFormatSupport);
+ allFormatsSucceeded = false;
+ }
+ else
+ {
+ if (pIFormatSuggested == nullptr)
+ {
+ LOG_ERROR(L"\tFAIL: IsOutputFormatSupported returns S_OK, but does not "
+ "suggest format.");
+ allFormatsSucceeded = false;
+ }
+ else
+ {
+ if (!IsEqualFormat(pIFormat.get(), pIFormatSuggested.get()))
+ {
+ LOG_ERROR(L"\tFAIL: IsOutputFormatSupported returns S_OK, but "
+ "returns a different format.");
+ allFormatsSucceeded = false;
+ }
+ else
+ {
+ LOG_OUTPUT(L"\tIsOutputFormatSupported supports custom format.");
+ }
+ }
+ }
+
+ pKsFormat = CreateKSDataFromWFX((WAVEFORMATEX*)pIFormat->GetAudioFormat());
+
+ if (pKsFormat == NULL)
+ {
+ LOG_ERROR(L"\tFAIL: Unable to create KSDATAFORMAT from PWAVEFORMATEX.");
+ allFormatsSucceeded = false;
+
+ continue;
+ }
+
+ {
+ unique_cotaskmem_ptr<KSDATAFORMAT_WAVEFORMATEX> formatBuffer(pKsFormat);
+
+ // Custom format, must be supported by endpoint...
+ hrFormatSupport = pIEPUtility->FindHostConnector(
+ (KSDATAFORMAT*)formatBuffer.get(),
+ formatBuffer->DataFormat.FormatSize,
+ FALSE,
+ &pIParts);
+
+ if (S_OK != hrFormatSupport)
+ {
+ LOG_ERROR(L"\tFAIL: Endpoint does not support custom format with error: (0x%08lx)", hrFormatSupport);
+ allFormatsSucceeded = false;
+ }
+ else
+ {
+ LOG_OUTPUT(L"\tEndpoint supports custom format.");
+ }
+ }
+ }
+
+ return allFormatsSucceeded;
+}
+
+HRESULT VerifyAPODataStreaming(CAPODevice* deviceUnderTest)
+{
+ wil::com_ptr<IAudioProcessingObject> pIAPO;
+ wil::com_ptr<IAudioProcessingObjectRT> pIAPORT;
+ wil::com_ptr<IAudioProcessingObjectConfiguration> pIAPOConfig;
+ APO_REG_PROPERTIES *pRegProperties = NULL;
+
+ if (deviceUnderTest == nullptr)
+ {
+ LOG_ERROR(L"\tCould not instantiate SysFx object.\n");
+ return E_NOINTERFACE;
+ }
+
+ LOG_RETURN_IF_FAILED(deviceUnderTest->GetAPOInterfaces(&pIAPO, &pIAPORT, &pIAPOConfig), L"\tCould not instantiate IAudioProcessingObject interface.");
+
+ APO_CONNECTION_PROPERTY inputProperty, outputProperty;
+ APO_CONNECTION_DESCRIPTOR inputDescriptor, outputDescriptor;
+ APO_CONNECTION_PROPERTY *pInputConnProp = &inputProperty, *pOutputConnProp = &outputProperty;
+ APO_CONNECTION_DESCRIPTOR *pInputConnDesc = &inputDescriptor, *pOutputConnDesc = &outputDescriptor;
+ UNCOMPRESSEDAUDIOFORMAT defaultFormat {};
+
+ FillFormat(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 2, sizeof(float), sizeof(float) * 8, static_cast<float>(cFrameRate), KSAUDIO_SPEAKER_STEREO, &defaultFormat);
+
+ LOG_RETURN_IF_FAILED(SetupConnection(pInputConnDesc, pOutputConnDesc, pInputConnProp, pOutputConnProp, &defaultFormat),
+ L"\tSetupConnection failed");
+
+ LOG_RETURN_IF_FAILED(LockForProcess(pIAPOConfig.get(), 1, &pInputConnDesc, 1, &pOutputConnDesc),
+ L"\tLockForProcess failed");
+
+ // setup vectors
+ FLOAT32 *pf32Input, *pf32Output;
+ pf32Input = (FLOAT32*)pInputConnProp->pBuffer;
+ pf32Output = (FLOAT32*)pOutputConnProp->pBuffer;
+ for (UINT32 index = 0; index < cFrameCountToProcess; index++)
+ {
+ pf32Input[index] = 0.5f;
+ pf32Output[index] = INFINITY;
+ }
+
+ APOProcess(pIAPORT.get(), 1, &pInputConnProp, 1, &pOutputConnProp);
+
+ GetRegistrationProperties(pIAPO.get(), &pRegProperties);
+
+ // Tests to make sure that in place APO have the correct data.
+ for (UINT32 index = 0; index < cFrameCountToProcess; index++)
+ {
+ // This will also check NaN along with INF
+ LOG_RETURN_HR_IF(!isfinite(pf32Output[index]), E_FAIL,
+ L"\tFAIL: APOProcess output(%f) is not a number or infinite.\n", pf32Output[index]);
+ }
+
+ LOG_RETURN_IF_FAILED(UnlockForProcess(pIAPOConfig.get()),
+ L"\tUnlock for process failed");
+
+ if (APO_FLAG_INPLACE == (pRegProperties->Flags & APO_FLAG_INPLACE))
+ {
+ LOG_RETURN_IF_FAILED(LockForProcess(pIAPOConfig.get(), 1, &pInputConnDesc, 1, &pInputConnDesc),
+ L"\tLockForProcess failed");
+
+ // setup vector
+ pf32Input = (FLOAT32 *)pInputConnProp->pBuffer;
+ for (UINT32 index = 0; index < cFrameCountToProcess; index++)
+ {
+ pf32Input[index] = 0.5f;
+ }
+
+ APOProcess(pIAPORT.get(), 1, &pInputConnProp, 1, &pInputConnProp);
+
+ LOG_RETURN_IF_FAILED(UnlockForProcess(pIAPOConfig.get()),
+ L"\tUnlock for process failed");
+ }
+
+ LOG_RETURN_IF_FAILED(DestroyConnection(pInputConnDesc), L"\tFailed to DestroyConnection");
+ LOG_RETURN_IF_FAILED(DestroyConnection(pOutputConnDesc), L"\tFailed to DestroyConnection");
+
+ return S_OK;
+}
+
+HRESULT VerifyActivateDeactivate(CAPODevice* deviceUnderTest)
+{
+ GUID clsid;
+ WCHAR ComRegistrationPath[1024];
+ WCHAR file[1024];
+ PWSTR end;
+ size_t cchRemaining;
+ DWORD dwSize = sizeof(WCHAR) * 1024;
+
+ if (deviceUnderTest == nullptr)
+ {
+ LOG_ERROR(L"\tCould not instantiate SysFx object.\n");
+ return E_NOINTERFACE;
+ }
+
+ deviceUnderTest->GetClsID(&clsid);
+
+ LOG_RETURN_IF_FAILED(StringCchPrintfEx(ComRegistrationPath, ARRAYSIZE(ComRegistrationPath), &end, &cchRemaining, 0, L"CLSID\\{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\\InprocServer32",
+ clsid.Data1, clsid.Data2, clsid.Data3, clsid.Data4[0], clsid.Data4[1], clsid.Data4[2], clsid.Data4[3], clsid.Data4[4], clsid.Data4[5], clsid.Data4[6], clsid.Data4[7]),
+ L"\tFailed to create string to find file name for DLL.");
+
+ LONG error = RegGetValue(HKEY_CLASSES_ROOT, ComRegistrationPath, nullptr, RRF_RT_REG_SZ, nullptr, file, &dwSize);
+
+ if (error != ERROR_SUCCESS)
+ {
+ LOG_RETURN_IF_FAILED(HRESULT_FROM_WIN32(error), L"\tFAILED to get the registry value.");
+ }
+
+ auto loadAPO = LoadLibrary(file);
+
+ if (loadAPO == NULL)
+ {
+ DWORD err = GetLastError();
+ HRESULT hr = HRESULT_FROM_WIN32(err);
+ if (SUCCEEDED(hr))
+ {
+ hr = E_FAIL;
+ }
+ LOG_RETURN_IF_FAILED(hr, L"\tFAILED to load the APO.");
+ }
+
+ BOOL bFreed = FreeLibrary(loadAPO);
+
+ if (!bFreed)
+ {
+ DWORD err = GetLastError();
+ HRESULT hr = HRESULT_FROM_WIN32(err);
+ if (SUCCEEDED(hr))
+ {
+ hr = E_FAIL;
+ }
+ LOG_RETURN_IF_FAILED(hr, L"\tFAILED to free the loaded APO.");
+ }
+
+ return S_OK;
+}
+
+struct APO_PROPERTIES {
+ PROPERTYKEY key;
+ LPARAM apoType;
+ LPCWSTR apoTypeName;
+ DWORD dwMajorVersion;
+ DWORD dwMinorVersion;
+ } PKEY_FX_EFFECTS[] = {
+ {PKEY_FX_PostMixEffectClsid, DT_GFX, L"GFX " ,6, 0},
+ {PKEY_FX_PreMixEffectClsid, DT_LFX, L"LFX ", 6, 0},
+ {PKEY_FX_StreamEffectClsid, DT_SFX, L"SFX ", 6, 3},
+ {PKEY_FX_ModeEffectClsid, DT_MFX, L"MFX ", 6, 3},
+ {PKEY_FX_EndpointEffectClsid, DT_EFX, L"EFX ", 6, 3},
+ // Composite effects
+ {PKEY_CompositeFX_StreamEffectClsid, DT_SFX, L"Composite SFX", 10, 0},
+ {PKEY_CompositeFX_ModeEffectClsid, DT_MFX, L"Composite MFX", 10, 0},
+ {PKEY_CompositeFX_EndpointEffectClsid, DT_EFX, L"Composite EFX", 10, 0},
+ // Offload effects
+ {PKEY_FX_Offload_StreamEffectClsid, DT_SFX, L"Offload SFX", 10, 0},
+ {PKEY_FX_Offload_ModeEffectClsid, DT_MFX, L"Offload MFX", 10, 0},
+ {PKEY_CompositeFX_Offload_StreamEffectClsid, DT_SFX, L"Composite Offload SFX", 10, 0},
+ {PKEY_CompositeFX_Offload_ModeEffectClsid, DT_MFX, L"Composite Offload MFX", 10, 0},
+ // Keyword Detector effects
+ {PKEY_FX_KeywordDetector_StreamEffectClsid, DT_SFX, L"KeywordDetector SFX", 10, 0},
+ {PKEY_FX_KeywordDetector_ModeEffectClsid, DT_MFX, L"KeywordDetector MFX", 10, 0},
+ {PKEY_FX_KeywordDetector_EndpointEffectClsid, DT_EFX, L"KeywordDetector EFX", 10, 0},
+ {PKEY_CompositeFX_KeywordDetector_StreamEffectClsid, DT_SFX, L"Composite KeywordDetector SFX", 10, 0},
+ {PKEY_CompositeFX_KeywordDetector_ModeEffectClsid, DT_MFX, L"Composite KeywordDetector MFX", 10, 0},
+ {PKEY_CompositeFX_KeywordDetector_EndpointEffectClsid, DT_EFX, L"Composite KeywordDetector EFX", 10, 0},
+ };
+
+CAPODevice::CAPODevice
+(
+ IMMDevice *pIEndpoint,
+ LPCWSTR pszClassId,
+ LPCWSTR pszEndpoint,
+ IPropertyStore *pIStoreDevice,
+ IPropertyStore *pIStoreFx,
+ LPARAM apoType,
+ LPCWSTR apoTypeName,
+ LPCWSTR pszAttachedDevice,
+ BOOL bProxyAPO
+)
+: m_pRegProps(NULL), m_fValid(FALSE)
+{
+ {
+ // Getting PnpId from property store...
+ PROPVARIANT pv;
+ com_ptr_nothrow<IMMDeviceEnumerator> pIDeviceEnumerator;
+ com_ptr_nothrow<IMMDevice> pIMMDevNode;
+ com_ptr_nothrow<IPropertyStore> pIDNPropStore;
+
+ LOG_RETURN_VOID_IF_FAILED(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&pIDeviceEnumerator)),
+ L"\tCoCreateInstance for MMDeviceEnumerator returned error");
+
+ PropVariantInit(&pv);
+ auto clearPropVariantOnScopeExit = scope_exit([&]
+ {
+ PropVariantClear(&pv);
+ });
+
+ LOG_RETURN_VOID_IF_FAILED(pIStoreDevice->GetValue(PKEY_Endpoint_Devnode, &pv), L"\tFailed to get endpoint device");
+
+ if (VT_LPWSTR != pv.vt)
+ {
+ LOG_ERROR(L"\tEnpoint Devnode property key is of the incorrect type");
+ return;
+ }
+
+ LOG_RETURN_VOID_IF_FAILED(pIDeviceEnumerator->GetDevice(pv.pwszVal, &pIMMDevNode), L"\tGetting device (%s) from the enumerator failed", pv.pwszVal);
+
+ PropVariantClear(&pv);
+
+ LOG_RETURN_VOID_IF_FAILED(pIMMDevNode->OpenPropertyStore(STGM_READ, &pIDNPropStore), L"\tFailed to open device property store");
+
+ PropVariantInit(&pv);
+
+ LOG_RETURN_VOID_IF_FAILED(pIDNPropStore->GetValue((PROPERTYKEY&)DEVPKEY_Device_InstanceId, &pv), L"\tFailed to get device instance id from device prop store");
+
+ if (VT_LPWSTR != pv.vt)
+ {
+ LOG_ERROR(L"\tDevice instance ID is of the incorrect type");
+ return;
+ }
+
+ m_szPnPId = wil::make_cotaskmem_string_nothrow(pv.pwszVal, sizeof(m_szPnPId));
+ }
+
+ LOG_RETURN_VOID_IF_FAILED(CLSIDFromString((LPOLESTR)pszClassId, &m_gClsID), L"\tCLSIDFromString failed");
+
+ m_szAttachedDevice = wil::make_cotaskmem_string_nothrow(pszAttachedDevice, wcslen(pszAttachedDevice));
+ m_szEndpoint = wil::make_cotaskmem_string_nothrow(pszEndpoint, wcslen(pszEndpoint));
+
+ PROPVARIANT value;
+ PropVariantInit(&value);
+ if (SUCCEEDED(pIStoreFx->GetValue(PKEY_ItemNameDisplay, &value)))
+ {
+ if (value.vt == VT_LPWSTR)
+ {
+ m_sApoName = wil::make_cotaskmem_string_nothrow(value.pwszVal, wcslen(value.pwszVal));
+ }
+ PropVariantClear(&value);
+ }
+
+
+ LOG_RETURN_VOID_IF_FAILED(CoCreateInstance(m_gClsID, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&m_pIUnknown)), L"\tCoCreateInstance for IUnknown returned error");
+
+
+ LOG_RETURN_VOID_IF_FAILED(m_pIUnknown->QueryInterface(__uuidof(IAudioProcessingObject), (void**)&m_pIAPO),
+ L"\tCoCreateInstance for IAudioProcessingObject returned error");
+
+
+ // Getting DeviceCollection
+ {
+ PROPVARIANT pvFormat;
+
+ // the standard KSDATAFORMAT_WAVEFORMATEX only contains a
+ // WAVEFORMATEX, but we need the extensible format so
+ // we define this type here:
+ typedef struct {
+ KSDATAFORMAT DataFormat;
+ WAVEFORMATEXTENSIBLE WFXtensible;
+ } KS_WFExtensible;
+
+ KS_WFExtensible ksWfx;
+
+ // initialize the structure
+ PropVariantInit(&pvFormat);
+
+ // Clear the prop variant on scope exit
+ auto clearFormatOnExit = scope_exit([&] {
+ PropVariantClear(&pvFormat);
+ });
+
+ LOG_RETURN_VOID_IF_FAILED(pIStoreDevice->GetValue(PKEY_AudioEngine_DeviceFormat, &pvFormat), L"\tGet PKEY_AudioEngine_Device format returned error");
+
+ if (pvFormat.vt == VT_BLOB)
+ {
+ if (pvFormat.blob.cbSize != sizeof(WAVEFORMATEXTENSIBLE))
+ {
+ LOG_ERROR(L"\tpvFormat.blob.cbSize (%zu) != sizeof(WAVEFORMATEXTENSIBLE) (%zu)\n", pvFormat.blob.cbSize, sizeof(WAVEFORMATEXTENSIBLE));
+ return;
+ }
+ }
+ else
+ {
+ LOG_ERROR(L"\tFormat is not VT_BLOB, Q != %c\n", VARTYPE(pvFormat.vt));
+ return;
+ }
+
+
+ LPWAVEFORMATEX pbWfxDevice = NULL;
+ ULONG cbWfxDevice = 0;
+
+ pbWfxDevice = (WAVEFORMATEX*)pvFormat.blob.pBlobData;
+ cbWfxDevice = pvFormat.blob.cbSize;
+
+ ksWfx.DataFormat.FormatSize = sizeof(KSDATAFORMAT) + cbWfxDevice;
+ ksWfx.DataFormat.Flags = 0;
+ ksWfx.DataFormat.SampleSize = 0;
+ ksWfx.DataFormat.Reserved = 0;
+ ksWfx.DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
+ ksWfx.DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
+ ksWfx.DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
+ CopyMemory( &(ksWfx.WFXtensible), pbWfxDevice, cbWfxDevice );
+
+ com_ptr_nothrow<IEndpointUtility2> pIEPUtil;
+ LOG_RETURN_VOID_IF_FAILED(pIEndpoint->Activate(__uuidof(IEndpointUtility2), CLSCTX_ALL, NULL, (void**)&pIEPUtil), L"\tpIMMDevice->Activate returned error");
+
+ LOG_RETURN_VOID_IF_FAILED(pIEPUtil->GetHostConnectorDeviceCollection2((PKSDATAFORMAT)&ksWfx, sizeof(ksWfx), TRUE,
+ eHostProcessConnector, &m_pIDevCollection, &m_nSoftwareIoDeviceInCollection, &m_nSoftwareIoConnectorIndex),
+ L"\tGetting device collection returned error");
+ }
+
+ // Saved off for InitializeAPO()
+ m_pIEndpoint = pIEndpoint;
+ m_pIEPStore = pIStoreDevice;
+ m_pIFXStore = pIStoreFx;
+ m_lpType = apoType;
+ m_sApoTypeName = wil::make_cotaskmem_string_nothrow(apoTypeName, wcslen(apoTypeName));;
+ m_bProxyAPO = bProxyAPO;
+
+ // Initialize SysFx!!
+ LOG_RETURN_VOID_IF_FAILED(InitializeAPO(m_pIAPO.get()), L"\tpIAPO->Initialize returned error");
+
+ m_fValid = TRUE;
+}
+
+CAPODevice::~CAPODevice(void)
+{
+ if (NULL != m_pRegProps)
+ {
+ CoTaskMemFree(m_pRegProps);
+ m_pRegProps = NULL;
+ }
+}
+
+
+HRESULT CAPODevice::InitializeAPO
+(
+ IAudioProcessingObject *pIAPO
+)
+{
+ LOG_RETURN_HR_IF(pIAPO == nullptr, E_POINTER, L"IAudioProcessingObject is null");
+
+ if(DT_SMEFX & GetDeviceType())
+ {
+ APOInitSystemEffects2 sysfxInitParams2 = {0};
+ // Setup initialization struct
+ sysfxInitParams2.APOInit.cbSize = sizeof(APOInitSystemEffects2);
+ sysfxInitParams2.APOInit.clsid = m_gClsID;
+ sysfxInitParams2.pReserved = NULL;
+ sysfxInitParams2.pDeviceCollection = m_pIDevCollection.get();
+ sysfxInitParams2.pAPOEndpointProperties = m_pIEPStore.get();
+ sysfxInitParams2.pAPOSystemEffectsProperties = m_pIFXStore.get();
+ sysfxInitParams2.InitializeForDiscoveryOnly = TRUE;
+ sysfxInitParams2.AudioProcessingMode = AUDIO_SIGNALPROCESSINGMODE_DEFAULT;
+ sysfxInitParams2.nSoftwareIoDeviceInCollection = m_nSoftwareIoDeviceInCollection;
+ sysfxInitParams2.nSoftwareIoConnectorIndex = m_nSoftwareIoConnectorIndex;
+
+ return pIAPO->Initialize(sysfxInitParams2.APOInit.cbSize, (BYTE*)(&sysfxInitParams2));
+ }
+ else if (DT_LGFX & GetDeviceType())
+ {
+ APOInitSystemEffects sysfxInitParams = {0};
+ // Setup initialization struct
+ sysfxInitParams.APOInit.cbSize = sizeof(sysfxInitParams);
+ sysfxInitParams.APOInit.clsid = m_gClsID;
+ sysfxInitParams.pAPOEndpointProperties = m_pIEPStore.get();
+ sysfxInitParams.pAPOSystemEffectsProperties = m_pIFXStore.get();
+ sysfxInitParams.pDeviceCollection = m_pIDevCollection.get();
+ sysfxInitParams.pReserved = NULL;
+
+ return (pIAPO->Initialize(sizeof(sysfxInitParams), (BYTE*)&sysfxInitParams));
+ }
+
+ // We should never get here unless we are initializing a first party APO (which we shouldn't be)
+ LOG_ERROR(L"SFX is of unknown type. Type is: %d", GetDeviceType());
+ return E_FAIL;
+}
+
+HRESULT CAPODevice::GetAPOInterfaces
+(
+ IAudioProcessingObject **ppIAPO,
+ IAudioProcessingObjectRT **ppIAPORT,
+ IAudioProcessingObjectConfiguration **ppIAPOConfig
+)
+{
+ if (ppIAPO != nullptr)
+ {
+ LOG_RETURN_IF_FAILED(UnknownQIInternal(m_pIUnknown.get(), __uuidof(IAudioProcessingObject), (void**)ppIAPO),
+ L"\tCoCreateInstance for IAudioProcessingObject failed");
+ }
+
+ if (ppIAPORT != nullptr)
+ {
+ LOG_RETURN_IF_FAILED(UnknownQIInternal(m_pIUnknown.get(), __uuidof(IAudioProcessingObjectRT), (void**)ppIAPORT),
+ L"\tCoCreateInstance for IAudioProcessingObjectRT failed");
+ }
+
+ if (ppIAPOConfig != nullptr)
+ {
+ LOG_RETURN_IF_FAILED(UnknownQIInternal(m_pIUnknown.get(), __uuidof(IAudioProcessingObjectConfiguration), (void**)ppIAPOConfig),
+ L"\tCoCreateInstance for IAudioProcessingObjectConfiguration failed");
+ }
+
+ return S_OK;
+}
+
+//--------------------------------------------------------------------------
+// CAPODeviceList constructor
+CAPODeviceList::CAPODeviceList ()
+{
+}
+
+//--------------------------------------------------------------------------
+// ~CAPODeviceList destructor
+
+CAPODeviceList::~CAPODeviceList(VOID)
+{
+ m_DeviceList.clear();
+
+ RegDeleteKeyValue(HKEY_LOCAL_MACHINE,
+ REGKEY_AUDIO_SOFTWARE,
+ PREVENT_APOTEST_CRASH_OR_REPORT_ON_APO_EXCEPTION);
+}
+
+HRESULT CAPODeviceList::AddSysFxDevices()
+{
+ HRESULT hr = S_OK;
+ bool allApoDevicesValid = true;
+ com_ptr_nothrow<IMMEndpoint> pIMMEndpoint;
+ com_ptr_nothrow<IMMEndpointInternal> pIMMEndpointInt;
+ com_ptr_nothrow<IPropertyStore> pIPropertyStoreDevice;
+ com_ptr_nothrow<IPropertyStore> pIPropertyStoreFX;
+ com_ptr_nothrow<IDeviceTopology> pIDeviceTopology;
+ com_ptr_nothrow<IConnector> pIConnector;
+ LPCWSTR strConnectedDevice = NULL;
+ PROPVARIANT pvName;
+ PROPVARIANT pv;
+ PROPVARIANT pvProxy;
+ BOOL bAPOProxy;
+
+
+ if (FAILED(hr = m_spDevice->Activate(__uuidof(IDeviceTopology), CLSCTX_INPROC_SERVER, NULL, (void**)&pIDeviceTopology)))
+ {
+ if (E_NOINTERFACE == hr)
+ {
+ LOG_OUTPUT(L"\tDevice is not active. Removing from test cases");
+ // There's the possibility that this legit if device is not active.
+ return S_FALSE;
+ }
+
+ return hr;
+ }
+
+ LOG_RETURN_IF_FAILED(pIDeviceTopology->GetConnector(0, &pIConnector),
+ L"\tFailed to get device connector");
+
+ LOG_RETURN_IF_FAILED(pIConnector->GetDeviceIdConnectedTo((LPWSTR *)&strConnectedDevice),
+ L"\tFailed to get connected device ID");
+
+ LOG_RETURN_IF_FAILED(m_spDevice->QueryInterface(__uuidof(IMMEndpoint), (void**)&pIMMEndpoint),
+ L"\tQueryInterfacce for IMMEndpoint failed");
+
+ LOG_RETURN_IF_FAILED(pIMMEndpoint->QueryInterface(__uuidof(IMMEndpointInternal), (void**)&pIMMEndpointInt),
+ L"\tQueryInterface for IMMEndpointInternal failed");
+
+ LOG_RETURN_IF_FAILED(m_spDevice->OpenPropertyStore(STGM_READ, &pIPropertyStoreDevice),
+ L"\tFailed to open property store for device");
+
+ LOG_RETURN_IF_FAILED(pIMMEndpointInt->TryOpenFXPropertyStore(STGM_READ, &pIPropertyStoreFX),
+ L"\tFailed to Open SysFX property store for device");
+
+ if (!pIPropertyStoreFX)
+ {
+ // This device doesn't appear to have any SysFX
+ LOG_OUTPUT(L"\tThis device probably doesn't have any SysFx. Skipping and removing from test");
+ return S_FALSE;
+ }
+
+ PropVariantInit(&pvName);
+ if (SUCCEEDED(pIPropertyStoreDevice->GetValue(PKEY_Device_FriendlyName, &pvName)))
+ {
+ if (VT_LPWSTR != V_VT(&pvName))
+ {
+ LOG_OUTPUT(L"\tFriendlyName value is not a string.");
+ }
+ }
+ else
+ {
+ LOG_OUTPUT(L"\tIPropertyStore::GetValue returned error.");
+ }
+
+
+ OSVERSIONINFO ver = {0};
+ ver.dwOSVersionInfoSize = sizeof(ver);
+
+ GetVersionEx(&ver);
+
+ for(int i = 0; i < ARRAYSIZE(PKEY_FX_EFFECTS); i++)
+ {
+ if (ver.dwMajorVersion < PKEY_FX_EFFECTS[i].dwMajorVersion ||
+ (ver.dwMajorVersion == PKEY_FX_EFFECTS[i].dwMajorVersion &&
+ ver.dwMinorVersion < PKEY_FX_EFFECTS[i].dwMinorVersion))
+ {
+ continue;
+ }
+
+ PropVariantInit(&pv);
+ hr = pIPropertyStoreFX->GetValue(PKEY_FX_EFFECTS[i].key, &pv);
+ LOG_OUTPUT(L"\tPKEY_FX_EFFECTS[%i] - GetValue PKEY_FX_EFFECTS[%i].key - 0x%x", i, i, hr);
+ if (S_OK == hr)
+ {
+ LOG_OUTPUT(L"\tPKEY_FX_EFFECTS[%i] - V_VT(&pv) - %i", i, V_VT(&pv));
+ if (VT_LPWSTR == V_VT(&pv))
+ {
+ bAPOProxy = FALSE;
+ PropVariantInit(&pvProxy);
+
+ // Check if mode effect is proxy
+ if (PKEY_FX_EFFECTS[i].apoType & DT_MFX)
+ {
+ hr = pIPropertyStoreFX->GetValue(PKEY_MFX_ProcessingModes_Supported_For_Streaming, &pvProxy);
+ LOG_OUTPUT(L"\tPKEY_FX_EFFECTS[%i] - GetValue MFX - 0x%x", i, hr);
+ if (S_OK == hr)
+ {
+ bAPOProxy = (pvProxy.vt != (VT_VECTOR | VT_LPWSTR)) ? TRUE : FALSE;
+ }
+ }
+
+ // Check if endpoint effect is proxy
+ if (PKEY_FX_EFFECTS[i].apoType & DT_EFX)
+ {
+ hr = pIPropertyStoreFX->GetValue(PKEY_EFX_ProcessingModes_Supported_For_Streaming, &pvProxy);
+ LOG_OUTPUT(L"\tPKEY_FX_EFFECTS[%i] - GetValue EFX - 0x%x", i, hr);
+ if (S_OK == hr)
+ {
+ bAPOProxy = (pvProxy.vt != (VT_VECTOR | VT_LPWSTR)) ? TRUE : FALSE;
+ }
+ }
+
+ LOG_OUTPUT(L"\tLooking at Audio Processing Object %ls\n", pv.pwszVal);
+
+ unique_ptr<CAPODevice> pSysFxDevice(new CAPODevice(m_spDevice.get(), pv.pwszVal, pvName.pwszVal, pIPropertyStoreDevice.get(),
+ pIPropertyStoreFX.get(), PKEY_FX_EFFECTS[i].apoType, PKEY_FX_EFFECTS[i].apoTypeName,
+ strConnectedDevice, bAPOProxy));
+
+ if (NULL != pSysFxDevice)
+ {
+ if (pSysFxDevice->IsValid())
+ {
+ pSysFxDevice->m_fSelected = TRUE;
+ m_DeviceList.push_back(move(pSysFxDevice));
+ }
+ else
+ {
+ LOG_ERROR(L"\tInvalid sysFX device encountered");
+ }
+ }
+
+ PropVariantClear(&pvProxy);
+ }
+ else if ((VT_LPWSTR | VT_VECTOR) == V_VT(&pv) && pv.calpwstr.cElems > 0)
+ {
+ UINT32 cClsids = pv.calpwstr.cElems;
+ bAPOProxy = FALSE;
+
+ for (UINT32 j = 0; j < cClsids; j++)
+ {
+ LOG_OUTPUT(L"\tLooking at Audio Processing Object %ls\n", pv.calpwstr.pElems[j]);
+
+ unique_ptr<CAPODevice> pSysFxDevice(new CAPODevice(m_spDevice.get(), pv.calpwstr.pElems[j], pvName.pwszVal, pIPropertyStoreDevice.get(),
+ pIPropertyStoreFX.get(), PKEY_FX_EFFECTS[i].apoType, PKEY_FX_EFFECTS[i].apoTypeName,
+ strConnectedDevice, bAPOProxy));
+
+ if (NULL != pSysFxDevice)
+ {
+ if (pSysFxDevice->IsValid())
+ {
+ pSysFxDevice->m_fSelected = TRUE;
+ m_DeviceList.push_back(move(pSysFxDevice));
+ }
+ else
+ {
+ LOG_ERROR(L"\tInvalid sysFX device encountered");
+ }
+ }
+ }
+ }
+ }
+ PropVariantClear(&pv);
+ }
+
+ return allApoDevicesValid ? S_OK : E_FAIL;
+}
+
+HRESULT CAPODeviceList::Initialize(wil::com_ptr_nothrow<IMMDevice> pDevice, LPWSTR deviceName)
+{
+ if (pDevice == nullptr || deviceName == nullptr)
+ {
+ LOG_ERROR(L"\tIMMDevice is null");
+ return E_INVALIDARG;
+ }
+
+ m_spDevice = pDevice;
+
+ wcscat(m_deviceName, deviceName);
+
+ DWORD dwValue = 1;
+ // Set registry entry so AudioDG won't crash during IAudioProcessingObjectRT function calls
+ RETURN_IF_WIN32_ERROR(RegSetKeyValue(HKEY_LOCAL_MACHINE,
+ REGKEY_AUDIO_SOFTWARE,
+ PREVENT_APOTEST_CRASH_OR_REPORT_ON_APO_EXCEPTION,
+ REG_DWORD,
+ &dwValue,
+ sizeof(dwValue)));
+
+ return S_OK;
+}
diff --git a/audio/tests/HLK/ThirdPartyApoTests/APODeviceTest.h b/audio/tests/HLK/ThirdPartyApoTests/APODeviceTest.h
new file mode 100644
index 00000000..31225995
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/APODeviceTest.h
@@ -0,0 +1,180 @@
+#include <stdafx.h>
+
+class CApoDeviceTests;
+
+class CAPODevice
+{
+ public:
+ CAPODevice
+ (
+ IMMDevice *pIEndpoint,
+ LPCWSTR pszClassId,
+ LPCWSTR pszEndpoint,
+ IPropertyStore *pIStoreDevice,
+ IPropertyStore *pIStoreFx,
+ LPARAM apoType,
+ LPCWSTR apoName,
+ LPCWSTR pszAttachedDevice,
+ BOOL bProxyAPO
+ );
+ CAPODevice
+ (
+ IAudioProcessingObject *pIAPO,
+ LPCWSTR pszClassId
+ );
+ ~CAPODevice(void);
+ HRESULT InitializeAPO(IAudioProcessingObject *pIAPO);
+ DWORD GetDeviceType() { return (DWORD)(m_lpType); }
+ BOOL IsValid() { return (m_fValid); }
+ void GetClsID(GUID *pgClsID) { *pgClsID = m_gClsID; }
+ HRESULT GetAPOInterfaces
+ (
+ IAudioProcessingObject **pIAPO,
+ IAudioProcessingObjectRT **pIAPORT,
+ IAudioProcessingObjectConfiguration **pIAPOConfig
+ );
+ IUnknown *GetObject() { return ((IUnknown*)m_pIUnknown.get()); }
+ IMMDevice *GetEndpoint() { return m_pIEndpoint.get(); }
+ IPropertyStore *GetEndpointStore() { return m_pIEPStore.get(); }
+ IPropertyStore *GetFxStore() { return m_pIFXStore.get(); }
+ IMMDeviceCollection *GetDeviceCollection() { return m_pIDevCollection.get(); }
+ UINT GetSoftwareIoDeviceInCollection() { return m_nSoftwareIoDeviceInCollection; }
+ UINT GetSoftwareIoConnectorIndex() { return m_nSoftwareIoConnectorIndex; }
+ PAPO_REG_PROPERTIES GetProperties() { return (m_pRegProps); }
+ LPSTR GetAttachedDevice() { return (LPSTR)(m_szAttachedDevice.get()); }
+ BOOL IsProxyApo() { return m_bProxyAPO; }
+
+ BOOL m_fSelected; // if TRUE, this device will be selected
+ wil::unique_cotaskmem_string m_szEndpoint;
+ wil::unique_cotaskmem_string m_sApoName;
+ wil::unique_cotaskmem_string m_sApoTypeName;
+
+ private:
+ BOOL m_fValid;
+ GUID m_gClsID;
+ wil::com_ptr_nothrow<IUnknown> m_pIUnknown;
+ wil::com_ptr_nothrow<IAudioProcessingObject> m_pIAPO;
+ PAPO_REG_PROPERTIES m_pRegProps;
+
+ // These are only used for SysFx
+ wil::com_ptr_nothrow<IMMDevice> m_pIEndpoint;
+ wil::unique_cotaskmem_string m_szAttachedDevice;
+ wil::com_ptr_nothrow<IPropertyStore> m_pIEPStore;
+ wil::com_ptr_nothrow<IPropertyStore> m_pIFXStore;
+ wil::com_ptr_nothrow<IMMDeviceCollection> m_pIDevCollection;
+ UINT m_nSoftwareIoDeviceInCollection;
+ UINT m_nSoftwareIoConnectorIndex;
+ BOOL m_bProxyAPO;
+ wil::unique_cotaskmem_string m_szPnPId; // a string that represents the PnPId (or other description) of the device under test
+ LPARAM m_lpType; // flags that will be intersected with test case flags
+};
+
+
+// ----------------------------------------------------------
+// Stores a list of APO devices on an endpoint pDevice
+// The list is populated using AddSysFxDevices and accessed
+// using m_DeviceList
+// ----------------------------------------------------------
+class CAPODeviceList
+{
+public:
+ CAPODeviceList();
+ ~CAPODeviceList(VOID);
+
+ HRESULT Initialize(wil::com_ptr_nothrow<IMMDevice> pDevice, LPWSTR deviceName);
+ HRESULT AddSysFxDevices();
+
+protected:
+ friend class CApoDeviceTests;
+
+ std::list<std::unique_ptr<CAPODevice>> m_DeviceList;
+ wil::com_ptr_nothrow<IMMDevice> m_spDevice;
+ WCHAR m_deviceName[MAX_PATH] = { '\0' };
+};
+
+class CApoDeviceTests : public WEX::TestClass<CApoDeviceTests>
+{
+ CApoDeviceTests(){};
+ ~CApoDeviceTests(){};
+
+ BEGIN_TEST_CLASS(CApoDeviceTests)
+ START_APPVERIFIFER
+ TEST_CLASS_PROPERTY(L"Owner", L"auddev")
+ TEST_CLASS_PROPERTY(L"TestClassification", L"Feature")
+ TEST_CLASS_PROPERTY(L"BinaryUnderTest", L"audiodg.exe")
+ TEST_CLASS_PROPERTY(L"ArtifactUnderTest", L"audioenginebaseapop.h")
+ TEST_CLASS_PROPERTY(L"ArtifactUnderTest", L"devicetopologyp.h")
+ TEST_CLASS_PROPERTY(L"RunAs", L"Elevated")
+ TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA")
+ TEST_CLASS_PROPERTY(L"Ignore", L"false")
+ END_APPVERIFIER
+ END_TEST_CLASS()
+
+ public:
+ TEST_METHOD_SETUP(setUpMethod);
+ TEST_METHOD_CLEANUP(tearDownMethod);
+
+ protected:
+ BEGIN_TEST_METHOD(TestAPOInitialize)
+ COMMON_ONECORE_TEST_PROPERTIES
+ TEST_METHOD_PROPERTY(L"Kits.TestId", L"ED37B03B-F091-4C8D-9EDD-FE7EC803BC8E")
+ TEST_METHOD_PROPERTY(L"Kits.TestId2", L"5B0F542E-719A-4949-A9DF-F8BBAC0E9912")
+ TEST_METHOD_PROPERTY(L"Kits.TestName", L"Audio APO - Verify APO Initializes - TestAPOInitialize")
+ TEST_METHOD_PROPERTY(L"Kits.ExpectedRuntime", L"1")
+ TEST_METHOD_PROPERTY(L"Kits.TimeoutInMinutes", L"5")
+ TEST_METHOD_PROPERTY(L"Kits.Description", L"Third Party APO Test: TestAPOInitialize")
+ APO_TEST_PROPERTIES
+ END_TEST_METHOD()
+
+ BEGIN_TEST_METHOD(TestCustomFormatSupport)
+ COMMON_ONECORE_TEST_PROPERTIES
+ TEST_METHOD_PROPERTY(L"Kits.TestId", L"571BD021-64F5-4CD1-9BA4-8ABD0857025F")
+ TEST_METHOD_PROPERTY(L"Kits.TestId2", L"EB313E34-CD9D-410B-9C6F-E7032C74F4D1")
+ TEST_METHOD_PROPERTY(L"Kits.TestName", L"Audio APO - Verify All Formats on Device are Valid - TestCustomFormatSupport")
+ TEST_METHOD_PROPERTY(L"Kits.ExpectedRuntime", L"1")
+ TEST_METHOD_PROPERTY(L"Kits.TimeoutInMinutes", L"5")
+ TEST_METHOD_PROPERTY(L"Kits.Description", L"Third Party APO Test: TestCustomFormatSupport")
+ APO_TEST_PROPERTIES
+ END_TEST_METHOD()
+
+ BEGIN_TEST_METHOD(TestValidFrameCount)
+ COMMON_ONECORE_TEST_PROPERTIES
+ TEST_METHOD_PROPERTY(L"Kits.TestId", L"B9E9F61A-2882-4256-ABA8-D57A46E54B76")
+ TEST_METHOD_PROPERTY(L"Kits.TestId2", L"ABE4D880-7F1A-434C-A7B9-248FFA96D2CF")
+ TEST_METHOD_PROPERTY(L"Kits.TestName", L"Audio APO - Verify Frame Count is Valid - TestValidFrameCount")
+ TEST_METHOD_PROPERTY(L"Kits.ExpectedRuntime", L"1")
+ TEST_METHOD_PROPERTY(L"Kits.TimeoutInMinutes", L"5")
+ TEST_METHOD_PROPERTY(L"Kits.Description", L"Third Party APO Test: TestValidFrameCount")
+ APO_TEST_PROPERTIES
+ END_TEST_METHOD()
+
+ BEGIN_TEST_METHOD(TestAPODataStreaming)
+ COMMON_ONECORE_TEST_PROPERTIES
+ TEST_METHOD_PROPERTY(L"Kits.TestId", L"D327B019-99E4-41BD-BF66-AF1A92801DAC")
+ TEST_METHOD_PROPERTY(L"Kits.TestId2", L"9EBF7FC3-7ADB-49A1-B0E0-C7501841E05A")
+ TEST_METHOD_PROPERTY(L"Kits.TestName", L"Audio APO - Verify APO Streams Data - TestAPODataStreaming")
+ TEST_METHOD_PROPERTY(L"Kits.ExpectedRuntime", L"1")
+ TEST_METHOD_PROPERTY(L"Kits.TimeoutInMinutes", L"5")
+ TEST_METHOD_PROPERTY(L"Kits.Description", L"Third Party APO Test: TestAPODataStreaming")
+ APO_TEST_PROPERTIES
+ END_TEST_METHOD()
+
+ BEGIN_TEST_METHOD(TestActivateDeactivate)
+ COMMON_ONECORE_TEST_PROPERTIES
+ TEST_METHOD_PROPERTY(L"Kits.TestId", L"D1C21041-9080-4990-B6A2-5F718649A3F2")
+ TEST_METHOD_PROPERTY(L"Kits.TestId2", L"F0556EDA-4757-409F-AE89-C5C1B0E31A84")
+ TEST_METHOD_PROPERTY(L"Kits.TestName", L"Audio APO - Verify Proper APO Activation and Deactivation - TestActivateDeactivate")
+ TEST_METHOD_PROPERTY(L"Kits.ExpectedRuntime", L"1")
+ TEST_METHOD_PROPERTY(L"Kits.TimeoutInMinutes", L"5")
+ TEST_METHOD_PROPERTY(L"Kits.Description", L"Third Party APO Test: TestActivateDeactivate")
+ APO_TEST_PROPERTIES
+ END_TEST_METHOD()
+
+ private:
+ std::list<std::unique_ptr<CAPODeviceList>> m_testDeviceWrapperList;
+};
+
+BEGIN_MODULE()
+ MODULE_PROPERTY(L"EtwLogger:WPRProfileFile", L"Audio-Tests.wprp")
+ MODULE_PROPERTY(L"EtwLogger:WPRProfile", L"MultimediaCategory.Verbose.File")
+END_MODULE()
diff --git a/audio/tests/HLK/ThirdPartyApoTests/APOOSUpgradeTest.cpp b/audio/tests/HLK/ThirdPartyApoTests/APOOSUpgradeTest.cpp
new file mode 100644
index 00000000..9fc5ae45
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/APOOSUpgradeTest.cpp
@@ -0,0 +1,96 @@
+#include <stdafx.h>
+
+#include <initguid.h>
+#include "propkey.h"
+#include <AudioClient.h>
+#include <SpatialAudioClient.h>
+#include <functiondiscoverykeys.h>
+#include <DevPKey.h>
+#include <AudioEngineBaseAPOP.h>
+#include "TestMediaType.h"
+#include <audioenginebaseapo.h>
+#include <MMDeviceAPI.h>
+#include <MMDeviceAPIP.h>
+
+#include <WexTestClass.h>
+
+#include <list>
+#include <memory>
+#include <ctime>
+#include <thread>
+#include <future>
+#include <mutex>
+#include <functional>
+#include <atlbase.h>
+
+#include "APOOSUpgradeTest.h"
+#include "APOStressTest.h"
+#include "sinewave.h"
+
+using namespace std;
+using namespace wil;
+using namespace WEX::Logging;
+using namespace WEX::Common;
+
+#define IF_FAILED_RETURN(hr) { HRESULT hrCode = hr; if(FAILED(hrCode)) { return hrCode; } }
+#define IF_SUCCEEDED(hr) { HRESULT hrCode = hr; if (!(hrCode == S_OK || hrCode == AUDCLNT_E_WRONG_ENDPOINT_TYPE)) { VERIFY_SUCCEEDED(hrCode); } }
+
+bool SetupSkipRTHeap();
+bool CleanupSkipRTHeap();
+
+bool CAPOUpgradeTest::setUpMethod()
+{
+ return SetupSkipRTHeap();
+}
+
+bool CAPOUpgradeTest::tearDownMethod()
+{
+ return CleanupSkipRTHeap();
+}
+
+void CAPOUpgradeTest::TestUpgrade()
+{
+ UINT cDevices = 0;
+ com_ptr_nothrow<IMMDeviceEnumerator> spEnumerator;
+ com_ptr_nothrow<IMMDeviceCollection> spDevices;
+
+ VERIFY_SUCCEEDED(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&spEnumerator)));
+ VERIFY_SUCCEEDED(spEnumerator->EnumAudioEndpoints(eAll, DEVICE_STATE_ACTIVE, &spDevices));
+ VERIFY_SUCCEEDED(spDevices->GetCount(&cDevices));
+
+ for (UINT i = 0; i < cDevices; i++)
+ {
+ com_ptr_nothrow<IMMDevice> pDevice = nullptr;
+ com_ptr_nothrow<IAudioClient2> pAudioClient = nullptr;
+ com_ptr_nothrow<IMMEndpoint> pEndpoint = nullptr;
+ BOOL bOffloadCapable = FALSE;
+ EDataFlow eFlow = eAll;
+
+ VERIFY_SUCCEEDED(spDevices->Item(i, &pDevice));
+
+ VERIFY_SUCCEEDED(com_query_to_nothrow(pDevice, &pEndpoint));
+ VERIFY_SUCCEEDED(pEndpoint->GetDataFlow(&eFlow));
+
+ VERIFY_SUCCEEDED(pDevice->Activate(__uuidof(IAudioClient2), CLSCTX_ALL, NULL, (void**)&pAudioClient));
+ VERIFY_SUCCEEDED(pAudioClient->IsOffloadCapable(AudioCategory_Media, &bOffloadCapable));
+
+ if (eFlow == eAll || eFlow == eRender)
+ {
+ VERIFY_SUCCEEDED(BasicAudioStreaming(pDevice.get()));
+
+ VERIFY_SUCCEEDED(BasicSpatialAudio(pDevice.get()));
+
+ VERIFY_SUCCEEDED(BasicAudioLoopback(pDevice.get()));
+
+ if (bOffloadCapable)
+ {
+ VERIFY_SUCCEEDED(BasicOffloadStreaming(pDevice.get()));
+ }
+ }
+
+ if (eFlow == eAll || eFlow == eCapture)
+ {
+ VERIFY_SUCCEEDED(BasicAudioCapture(pDevice.get()));
+ }
+ }
+}
diff --git a/audio/tests/HLK/ThirdPartyApoTests/APOOSUpgradeTest.h b/audio/tests/HLK/ThirdPartyApoTests/APOOSUpgradeTest.h
new file mode 100644
index 00000000..3c61390d
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/APOOSUpgradeTest.h
@@ -0,0 +1,38 @@
+#include <stdafx.h>
+
+class CAPOUpgradeTest
+{
+ CAPOUpgradeTest(){};
+ ~CAPOUpgradeTest(){};
+
+ BEGIN_TEST_CLASS(CAPOUpgradeTest)
+ START_OSUPGRADE
+ START_APPVERIFIFER_UPGRADE
+ TEST_CLASS_PROPERTY(L"Owner", L"auddev")
+ TEST_CLASS_PROPERTY(L"TestClassification", L"Feature")
+ TEST_CLASS_PROPERTY(L"BinaryUnderTest", L"audiodg.exe")
+ TEST_CLASS_PROPERTY(L"ArtifactUnderTest", L"audioenginebaseapop.h")
+ TEST_CLASS_PROPERTY(L"RunAs", L"Elevated")
+ TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA")
+ TEST_CLASS_PROPERTY(L"Ignore", L"false")
+ TEST_CLASS_PROPERTY(L"EtwLogger:WPRProfileFile", L"Audio-Tests.wprp")
+ TEST_CLASS_PROPERTY(L"EtwLogger:WPRProfile", L"MultimediaCategory.Verbose.File")
+ END_APPVERIFIER
+ END_TEST_CLASS()
+
+public:
+ TEST_METHOD_SETUP(setUpMethod);
+ TEST_METHOD_CLEANUP(tearDownMethod);
+
+protected:
+ BEGIN_TEST_METHOD(TestUpgrade)
+ COMMON_ONECORE_TEST_PROPERTIES
+ TEST_METHOD_PROPERTY(L"Kits.TestId", L"B98FD3CB-2E6E-4152-BA85-3021149B8E86")
+ TEST_METHOD_PROPERTY(L"Kits.TestId2", L"C467E942-EB43-477F-8E2A-01D07FEF90C4")
+ TEST_METHOD_PROPERTY(L"Kits.TestName", L"Audio APO - Verify APOs Work After an OS Upgrade - TestUpgrade")
+ TEST_METHOD_PROPERTY(L"Kits.ExpectedRuntime", L"60")
+ TEST_METHOD_PROPERTY(L"Kits.TimeoutInMinutes", L"240")
+ TEST_METHOD_PROPERTY(L"Kits.Description", L"Third Party APO Test: TestUpgrade")
+ APO_TEST_PROPERTIES
+ END_TEST_METHOD()
+}; \ No newline at end of file
diff --git a/audio/tests/HLK/ThirdPartyApoTests/APOStressTest.cpp b/audio/tests/HLK/ThirdPartyApoTests/APOStressTest.cpp
new file mode 100644
index 00000000..160f488b
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/APOStressTest.cpp
@@ -0,0 +1,777 @@
+#include <stdafx.h>
+
+#include <initguid.h>
+#include "propkey.h"
+#include <AudioClient.h>
+#include <SpatialAudioClient.h>
+#include <functiondiscoverykeys.h>
+#include <DevPKey.h>
+#include <AudioEngineBaseAPOP.h>
+#include "TestMediaType.h"
+#include <audioenginebaseapo.h>
+#include <MMDeviceAPI.h>
+#include <MMDeviceAPIP.h>
+
+#include <WexTestClass.h>
+
+#include <list>
+#include <memory>
+#include <ctime>
+#include <thread>
+#include <future>
+#include <mutex>
+#include <functional>
+#include <atlbase.h>
+
+#include "APOStressTest.h"
+#include "sinewave.h"
+#include "util.h"
+
+#include <psapi.h>
+#include <processthreadsapi.h>
+
+using namespace std;
+using namespace wil;
+using namespace WEX::Logging;
+using namespace WEX::Common;
+
+#define NUMBER_OF_TESTS 8
+#define THIRTY_MIN_IN_SEC 1800
+#define SIXTY_SECONDS 60
+#define ONE_SEC_IN_MS 1000
+#define THIRTY_MIN_IN_MS 1800000
+#define MAX_ALLOWED_PAGEFILE_USAGE_IN_BYTES 300000000
+
+#define IF_FAILED_RETURN(hr) { HRESULT hrCode = hr; if(FAILED(hrCode)) { return hrCode; } }
+
+#define REGKEY_AUDIOSERVICE L"Software\\Microsoft\\Windows\\CurrentVersion\\Audio"
+#define REGVALUE_SKIPRTHEAP L"SkipRTHeap"
+
+const DWORD WAIT_TIME_MIN_FOR_THREAD_OPERATION = 3u * 1000u; // 3 seconds
+const DWORD WAIT_TIME_MAX_FOR_THREAD_OPERATION = 10u * 1000u; // 10 seconds
+
+size_t maxAudioDGPagefileUsage = 0;
+std::mutex maxAudioDGPagefileUsage_mutex; // protects maxAudioDGPagefileUsage_mutex
+
+template <typename T>
+inline T RandInRange(T min, T max)
+{
+ // Treat the value span as a double right away. Otherwise if min = 0, and max
+ // is truly the max for the type, the value span could loop to zero.
+ double valueSpan = 1.0f + (double) (max - min);
+
+ // The following had a problem where doubles larger than 0x8000000000000000 were always truncating
+ // to 0x8000000000000000 when cast to a DWORD64. Multiplying by 0.5f and then (T) 2 seemed to
+ // get around this problem.
+ //return min + (T) ((double) (max - min + 1) * (double) rand() / (double) (RAND_MAX + 1));
+
+ // Then the following had a problem where RandInRange(0, 1) could never return 1.
+ //return min + (T) 2 * (T) (0.5f * valueSpan * ((double) rand() / (double) (RAND_MAX + 1)));
+
+ double offset = valueSpan * ((double) rand() / (double) (RAND_MAX + 1));
+
+ if (offset > (double) ((DWORD64) 0x8000000000000000))
+ {
+ return min + (T) 2 * (T) (0.5f * offset);
+ }
+
+ return min + (T) offset;
+}
+
+void WriteToAudioObjectBuffer(FLOAT* buffer, UINT frameCount, FLOAT frequency, UINT samplingRate)
+{
+ const double PI = 4 * atan2(1.0, 1.0);
+ static double _radPhase = 0.0;
+ double step = 2 * PI * frequency / samplingRate;
+
+ for (UINT i = 0; i < frameCount; i++)
+ {
+ double sample = sin(_radPhase);
+ buffer[i] = FLOAT(sample);
+ _radPhase += step; // next frame phase
+
+ if (_radPhase >= 2 * PI)
+ {
+ _radPhase -= 2 * PI;
+ }
+ }
+}
+
+bool SetupSkipRTHeap()
+{
+ DWORD dwValue = 1;
+ DWORD cbData = sizeof(dwValue);
+
+ DWORD result = RegSetKeyValueW(HKEY_LOCAL_MACHINE, REGKEY_AUDIOSERVICE, REGVALUE_SKIPRTHEAP, REG_DWORD, &dwValue, cbData);
+
+ RestartAudioService();
+
+ return (result == ERROR_SUCCESS);
+}
+
+bool CleanupSkipRTHeap()
+{
+ DWORD result = RegDeleteKeyValueW(HKEY_LOCAL_MACHINE, REGKEY_AUDIOSERVICE, REGVALUE_SKIPRTHEAP);
+
+ RestartAudioService();
+
+ return (result == ERROR_SUCCESS);
+}
+
+bool CAPOStressTest::setUpMethod()
+{
+ return SetupSkipRTHeap();
+}
+
+bool CAPOStressTest::tearDownMethod()
+{
+ return CleanupSkipRTHeap();
+}
+
+void CAPOStressTest::AudioAPOStressTest()
+{
+
+ UINT cDevices = 0;
+ com_ptr_nothrow<IMMDeviceEnumerator> spEnumerator;
+ com_ptr_nothrow<IMMDeviceCollection> spDevices;
+ vector<com_ptr<IMMDevice>> sEndpoints;
+
+ VERIFY_SUCCEEDED(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&spEnumerator)));
+ VERIFY_SUCCEEDED(spEnumerator->EnumAudioEndpoints(eAll, DEVICE_STATE_ACTIVE, &spDevices));
+ VERIFY_SUCCEEDED(spDevices->GetCount(&cDevices));
+
+ for (UINT i = 0; i < cDevices; i++)
+ {
+ wil::com_ptr<IMMDevice> pEndpoint = nullptr;
+
+ VERIFY_SUCCEEDED(spDevices->Item(i, &pEndpoint));
+
+ sEndpoints.push_back(pEndpoint);
+ }
+
+ RunStressTest(THIRTY_MIN_IN_SEC, sEndpoints);
+}
+
+std::wstring QueryProcessName(const DWORD pid)
+{
+ wil::unique_handle hProcess(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid));
+ if(NULL == hProcess)
+ {
+ return L"err " + std::to_wstring(GetLastError());
+ }
+ else
+ {
+ WCHAR szProcessName[1024];
+ DWORD cchSize = ARRAYSIZE(szProcessName);
+ if (0 == QueryFullProcessImageNameW(hProcess.get(), 0, szProcessName, &cchSize))
+ {
+ return L"err " + std::to_wstring(GetLastError());
+ }
+
+ PWSTR fileName = szProcessName + cchSize;
+ while (fileName != szProcessName && *fileName != L'\\') fileName--;
+
+ return (*fileName == L'\\') ? fileName + 1 : fileName;
+ }
+}
+
+DWORD GetAudioDGProcessID()
+{
+ // Get the list of process identifiers.
+
+ DWORD aProcesses[1024], cbNeeded, cProcesses;
+ unsigned int i;
+
+ if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
+ {
+ return 0;
+ }
+
+ // Calculate how many process identifiers were returned.
+
+ cProcesses = cbNeeded / sizeof(DWORD);
+
+ // Look for AudioDG name and process identifier on each process.
+
+ for ( i = 0; i < cProcesses; i++ )
+ {
+ if( aProcesses[i] != 0 && 0 == _wcsicmp(QueryProcessName(aProcesses[i]).c_str(), L"AUDIODG.EXE"))
+ {
+ return aProcesses[i];
+ }
+ }
+
+ return 0;
+}
+
+void GetAudioDGMemoryUsageSample()
+{
+ // Get the AudioDG process ID
+ DWORD audioDGProcessID = GetAudioDGProcessID();
+
+ if (audioDGProcessID != 0)
+ {
+ std::lock_guard<std::mutex> autoLock(maxAudioDGPagefileUsage_mutex);
+
+ // Memory PagefileUsage snapshot
+ PROCESS_MEMORY_COUNTERS pmc;
+
+ HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
+ PROCESS_VM_READ,
+ FALSE, audioDGProcessID );
+
+ if (hProcess != NULL && GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)) )
+ {
+ maxAudioDGPagefileUsage = max(maxAudioDGPagefileUsage, pmc.PagefileUsage);
+ }
+
+ VERIFY_IS_TRUE(maxAudioDGPagefileUsage < MAX_ALLOWED_PAGEFILE_USAGE_IN_BYTES);
+
+ CloseHandle( hProcess );
+ }
+ else
+ {
+ Log::Warning(L"Unable to find AudioDG PID");
+ }
+}
+
+HRESULT BasicAudioStreaming(IMMDevice* pEndpoint)
+{
+ com_ptr_nothrow<IAudioClient2> pAudioClient;
+ wil::unique_cotaskmem_ptr<WAVEFORMATEX> mixFormat;
+
+ if (pEndpoint == nullptr)
+ {
+ return E_INVALIDARG;
+ }
+
+ IF_FAILED_RETURN(pEndpoint->Activate(__uuidof(IAudioClient2), CLSCTX_ALL, NULL, (void**)&pAudioClient));
+
+ AudioClientProperties clientProperties = { 0 };
+ clientProperties.cbSize = sizeof(AudioClientProperties);
+ clientProperties.bIsOffload = false;
+ clientProperties.eCategory = (AUDIO_STREAM_CATEGORY) RandInRange(0, 11);
+
+ IF_FAILED_RETURN(pAudioClient->SetClientProperties(&clientProperties));
+
+ IF_FAILED_RETURN(pAudioClient->GetMixFormat(wil::out_param_ptr<WAVEFORMATEX **>(mixFormat)));
+
+ IF_FAILED_RETURN(pAudioClient->Initialize(
+ AUDCLNT_SHAREMODE_SHARED,
+ AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
+ 0,
+ 0,
+ mixFormat.get(),
+ nullptr));
+
+ com_ptr_nothrow<IAudioRenderClient> pRenderClient;
+ IF_FAILED_RETURN(pAudioClient->GetService(_uuidof(IAudioRenderClient), wil::out_param_ptr<void **>(pRenderClient)));
+
+ wil::unique_event bufferCompleteEvent;
+ bufferCompleteEvent.create();
+ IF_FAILED_RETURN(pAudioClient->SetEventHandle(bufferCompleteEvent.get()));
+
+ UINT32 bufferFrameCount;
+ REFERENCE_TIME duration = RandInRange(WAIT_TIME_MIN_FOR_THREAD_OPERATION, WAIT_TIME_MAX_FOR_THREAD_OPERATION);
+ IF_FAILED_RETURN(pAudioClient->GetBufferSize(&bufferFrameCount));
+
+ SineWave sw(mixFormat->nChannels, mixFormat->nSamplesPerSec);
+ for (unsigned i = 0; i < mixFormat->nChannels; ++i)
+ {
+ sw.SetChannel(i, 400, 0.25f);
+ }
+
+ BYTE* data{};
+ IF_FAILED_RETURN(pRenderClient->GetBuffer(bufferFrameCount, &data));
+
+ sw.FillFrames(data, bufferFrameCount);
+ IF_FAILED_RETURN(pRenderClient->ReleaseBuffer(bufferFrameCount, 0));
+
+ IF_FAILED_RETURN(pAudioClient->Start());
+
+ unsigned c = 0;
+ while (c++ < duration)
+ {
+ if (WaitForSingleObject(bufferCompleteEvent.get(), ONE_SEC_IN_MS) != WAIT_OBJECT_0)
+ {
+ break;
+ }
+
+ unsigned numFramesPadding{};
+ IF_FAILED_RETURN(pAudioClient->GetCurrentPadding(&numFramesPadding));
+ auto numFramesAvailable = bufferFrameCount - numFramesPadding;
+
+ IF_FAILED_RETURN(pRenderClient->GetBuffer(numFramesAvailable, &data));
+ sw.FillFrames(data, numFramesAvailable);
+ IF_FAILED_RETURN(pRenderClient->ReleaseBuffer(numFramesAvailable, 0));
+ }
+
+ // Get a sample of the current AudioDG memory usage
+ GetAudioDGMemoryUsageSample();
+
+ IF_FAILED_RETURN(pAudioClient->Stop());
+
+ return S_OK;
+}
+
+HRESULT DisableEnableEndpoint(IMMDevice* pEndpoint)
+{
+ com_ptr_nothrow<IMMEndpointManager> pManager = nullptr;
+
+ if (pEndpoint == nullptr)
+ {
+ return E_INVALIDARG;
+ }
+
+ IF_FAILED_RETURN(CoCreateInstance(__uuidof(MMEndpointManager), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&pManager)));
+
+ IF_FAILED_RETURN(pManager->SetEndpointState(pEndpoint, DEVICE_STATE_DISABLED));
+
+ Sleep(1000);
+
+ IF_FAILED_RETURN(pManager->SetEndpointState(pEndpoint, DEVICE_STATE_ACTIVE));
+
+ return S_OK;
+}
+
+HRESULT BasicAudioCapture(IMMDevice* pEndpoint)
+{
+ com_ptr_nothrow<IAudioClient> pAudioClient;
+ wil::unique_cotaskmem_ptr<WAVEFORMATEX> mixFormat;
+
+ if (pEndpoint == nullptr)
+ {
+ return E_INVALIDARG;
+ }
+
+ IF_FAILED_RETURN(pEndpoint->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, (void**)&pAudioClient));
+
+ IF_FAILED_RETURN(pAudioClient->GetMixFormat(wil::out_param_ptr<WAVEFORMATEX **>(mixFormat)));
+
+ IF_FAILED_RETURN(pAudioClient->Initialize(
+ AUDCLNT_SHAREMODE_SHARED,
+ AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
+ 0,
+ 0,
+ mixFormat.get(),
+ nullptr));
+
+ com_ptr_nothrow<IAudioCaptureClient> pCaptureClient;
+ IF_FAILED_RETURN(pAudioClient->GetService(_uuidof(IAudioCaptureClient), wil::out_param_ptr<void **>(pCaptureClient)));
+
+ wil::unique_event bufferCompleteEvent;
+ bufferCompleteEvent.create();
+ IF_FAILED_RETURN(pAudioClient->SetEventHandle(bufferCompleteEvent.get()));
+
+ UINT32 bufferFrameCount;
+ REFERENCE_TIME duration = RandInRange(WAIT_TIME_MIN_FOR_THREAD_OPERATION, WAIT_TIME_MAX_FOR_THREAD_OPERATION);
+ IF_FAILED_RETURN(pAudioClient->GetBufferSize(&bufferFrameCount));
+
+ BYTE* data{};
+ DWORD dwFlags = 0;
+ UINT32 numFramesInNextPacket = 0;
+
+ IF_FAILED_RETURN(pCaptureClient->GetNextPacketSize(&numFramesInNextPacket));
+ IF_FAILED_RETURN(pCaptureClient->GetBuffer(&data, &numFramesInNextPacket, &dwFlags, NULL, NULL));
+
+ IF_FAILED_RETURN(pAudioClient->Start());
+
+ unsigned c = 0;
+ while (c++ < duration)
+ {
+ if (WaitForSingleObject(bufferCompleteEvent.get(), ONE_SEC_IN_MS) != WAIT_OBJECT_0)
+ {
+ break;
+ }
+
+ IF_FAILED_RETURN(pCaptureClient->ReleaseBuffer(numFramesInNextPacket));
+
+ IF_FAILED_RETURN(pCaptureClient->GetBuffer(&data, &numFramesInNextPacket, &dwFlags, NULL, NULL));
+ }
+
+ // Get a sample of the current AudioDG memory usage
+ GetAudioDGMemoryUsageSample();
+
+ IF_FAILED_RETURN(pAudioClient->Stop());
+
+ return S_OK;
+}
+
+HRESULT BasicAudioLoopback(IMMDevice* pEndpoint)
+{
+ com_ptr_nothrow<IAudioClient> pAudioClient;
+ wil::unique_cotaskmem_ptr<WAVEFORMATEX> mixFormat;
+
+ if (pEndpoint == nullptr)
+ {
+ return E_INVALIDARG;
+ }
+
+ IF_FAILED_RETURN(pEndpoint->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, (void**)&pAudioClient));
+
+ IF_FAILED_RETURN(pAudioClient->GetMixFormat(wil::out_param_ptr<WAVEFORMATEX **>(mixFormat)));
+
+ IF_FAILED_RETURN(pAudioClient->Initialize(
+ AUDCLNT_SHAREMODE_SHARED,
+ AUDCLNT_STREAMFLAGS_LOOPBACK | AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM,
+ 0,
+ 0,
+ mixFormat.get(),
+ nullptr));
+
+ com_ptr_nothrow<IAudioCaptureClient> pCaptureClient;
+ IF_FAILED_RETURN(pAudioClient->GetService(__uuidof(IAudioCaptureClient), wil::out_param_ptr<void **>(pCaptureClient)));
+
+ wil::unique_event bufferCompleteEvent;
+ bufferCompleteEvent.create();
+ IF_FAILED_RETURN(pAudioClient->SetEventHandle(bufferCompleteEvent.get()));
+
+ UINT32 bufferFrameCount;
+ IF_FAILED_RETURN(pAudioClient->GetBufferSize(&bufferFrameCount));
+
+ BYTE* data{};
+ DWORD dwFlags = 0;
+ UINT32 numFramesInNextPacket = 0;
+
+ IF_FAILED_RETURN(pCaptureClient->GetNextPacketSize(&numFramesInNextPacket));
+
+ IF_FAILED_RETURN(pAudioClient->Start());
+
+ while (numFramesInNextPacket != 0)
+ {
+ IF_FAILED_RETURN(pCaptureClient->GetBuffer(&data, &numFramesInNextPacket, &dwFlags, NULL, NULL));
+
+ IF_FAILED_RETURN(pCaptureClient->ReleaseBuffer(numFramesInNextPacket));
+
+ IF_FAILED_RETURN(pCaptureClient->GetNextPacketSize(&numFramesInNextPacket));
+ }
+
+ // Get a sample of the current AudioDG memory usage
+ GetAudioDGMemoryUsageSample();
+
+ IF_FAILED_RETURN(pAudioClient->Stop());
+
+ return S_OK;
+}
+
+HRESULT BasicSpatialAudio(IMMDevice* pEndpoint)
+{
+#ifdef LNM
+ EnableSpatialAudio();
+#endif
+
+ if (pEndpoint == nullptr)
+ {
+ return E_INVALIDARG;
+ }
+
+ com_ptr_nothrow<ISpatialAudioClient> client;
+ IF_FAILED_RETURN(pEndpoint->Activate(__uuidof(ISpatialAudioClient), CLSCTX_ALL, nullptr, wil::out_param_ptr<void **>(client)));
+
+ com_ptr_nothrow<IAudioFormatEnumerator> enumer;
+ IF_FAILED_RETURN(client->GetSupportedAudioObjectFormatEnumerator(&enumer));
+
+ wil::unique_cotaskmem_ptr<WAVEFORMATEX> fmt;
+ IF_FAILED_RETURN(enumer->GetFormat(0, wil::out_param_ptr<WAVEFORMATEX **>(fmt)));
+
+ unique_event event;
+ event.create();
+ if (event == nullptr)
+ {
+ HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ unique_prop_variant pv;
+ auto params = reinterpret_cast<SpatialAudioObjectRenderStreamActivationParams *>(CoTaskMemAlloc(sizeof(SpatialAudioObjectRenderStreamActivationParams)));
+ *params = SpatialAudioObjectRenderStreamActivationParams{fmt.get(), (AudioObjectType)AudioObjectType_FrontLeft, 0, 0, AudioCategory_Other, event.get(), nullptr};
+ pv.vt = VT_BLOB;
+ pv.blob.cbSize = sizeof(*params);
+ pv.blob.pBlobData = reinterpret_cast<BYTE *>(params);
+
+ com_ptr_nothrow<ISpatialAudioObjectRenderStream> stream;
+ IF_FAILED_RETURN(client->ActivateSpatialAudioStream(&pv, __uuidof(ISpatialAudioObjectRenderStream), wil::out_param_ptr<void **>(stream)));
+
+ com_ptr_nothrow<ISpatialAudioObject> audioObjectFrontLeft;
+ IF_FAILED_RETURN(stream->ActivateSpatialAudioObject(AudioObjectType_FrontLeft, &audioObjectFrontLeft));
+
+ IF_FAILED_RETURN(stream->Start());
+
+ UINT totalFrameCount = fmt->nSamplesPerSec * 2;
+
+ bool isRendering = true;
+ while (isRendering)
+ {
+ // Wait for a signal from the audio-engine to start the next processing pass
+ if (WaitForSingleObject(event.get(), 100) != WAIT_OBJECT_0)
+ {
+ IF_FAILED_RETURN(stream->Reset());
+ }
+
+ UINT32 availableDynamicObjectCount = 0;
+ UINT32 frameCount = 0;
+
+ // Begin the process of sending object data and metadata
+ // Get the number of dynamic objects that can be used to send object-data
+ // Get the frame count that each buffer will be filled with
+ IF_FAILED_RETURN(stream->BeginUpdatingAudioObjects(&availableDynamicObjectCount, &frameCount));
+
+ BYTE* buffer = nullptr;
+ UINT32 bufferLength = 0;
+
+ if (audioObjectFrontLeft == nullptr)
+ {
+ IF_FAILED_RETURN(stream->ActivateSpatialAudioObject(AudioObjectType::AudioObjectType_FrontLeft, &audioObjectFrontLeft));
+ }
+
+ // Get the buffer to write audio data
+ IF_FAILED_RETURN(audioObjectFrontLeft->GetBuffer(&buffer, &bufferLength));
+
+ if (totalFrameCount >= frameCount)
+ {
+ // Write audio data to the buffer
+ WriteToAudioObjectBuffer(reinterpret_cast<float*>(buffer), frameCount, 200.0f, fmt->nSamplesPerSec);
+
+ totalFrameCount -= frameCount;
+ }
+ else
+ {
+ // Write audio data to the buffer
+ WriteToAudioObjectBuffer(reinterpret_cast<float*>(buffer), totalFrameCount, 750.0f, fmt->nSamplesPerSec);
+
+ // Get a sample of the current AudioDG memory usage
+ GetAudioDGMemoryUsageSample();
+
+ // Set end of stream for the last buffer
+ IF_FAILED_RETURN(audioObjectFrontLeft->SetEndOfStream(totalFrameCount));
+
+ audioObjectFrontLeft = nullptr; // Release the object
+
+ isRendering = false;
+ }
+
+ // Let the audio engine know that the object data are available for processing now
+ IF_FAILED_RETURN(stream->EndUpdatingAudioObjects());
+ }
+
+ return S_OK;
+}
+
+HRESULT BasicOffloadStreaming(IMMDevice* pEndpoint)
+{
+ com_ptr_nothrow<IAudioClient2> pAudioClient;
+ wil::unique_cotaskmem_ptr<WAVEFORMATEX> mixFormat;
+ BOOL bOffloadCapable = FALSE;
+
+ if (pEndpoint == nullptr)
+ {
+ return E_INVALIDARG;
+ }
+
+ IF_FAILED_RETURN(pEndpoint->Activate(__uuidof(IAudioClient2), CLSCTX_ALL, NULL, (void**)&pAudioClient));
+ IF_FAILED_RETURN(pAudioClient->IsOffloadCapable(AudioCategory_Media, &bOffloadCapable));
+
+ AudioClientProperties clientProperties = { 0 };
+ clientProperties.cbSize = sizeof(AudioClientProperties);
+ clientProperties.bIsOffload = bOffloadCapable ? true : false;
+ clientProperties.eCategory = AudioCategory_Media;
+
+ if (bOffloadCapable)
+ {
+ clientProperties.bIsOffload = true;
+ }
+
+ IF_FAILED_RETURN(pAudioClient->SetClientProperties(&clientProperties));
+
+ IF_FAILED_RETURN(pAudioClient->GetMixFormat(wil::out_param_ptr<WAVEFORMATEX **>(mixFormat)));
+
+ IF_FAILED_RETURN(pAudioClient->Initialize(
+ AUDCLNT_SHAREMODE_SHARED,
+ AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
+ 0,
+ 0,
+ mixFormat.get(),
+ nullptr));
+
+ com_ptr_nothrow<IAudioRenderClient> pRenderClient;
+ IF_FAILED_RETURN(pAudioClient->GetService(_uuidof(IAudioRenderClient), wil::out_param_ptr<void **>(pRenderClient)));
+
+ wil::unique_event bufferCompleteEvent;
+ bufferCompleteEvent.create();
+ IF_FAILED_RETURN(pAudioClient->SetEventHandle(bufferCompleteEvent.get()));
+
+ UINT32 bufferFrameCount;
+ REFERENCE_TIME duration = RandInRange(WAIT_TIME_MIN_FOR_THREAD_OPERATION, WAIT_TIME_MAX_FOR_THREAD_OPERATION);
+ IF_FAILED_RETURN(pAudioClient->GetBufferSize(&bufferFrameCount));
+
+ SineWave sw(mixFormat->nChannels, mixFormat->nSamplesPerSec);
+ for (unsigned i = 0; i < mixFormat->nChannels; ++i)
+ {
+ sw.SetChannel(i, 400, 0.25f);
+ }
+
+ BYTE* data{};
+ IF_FAILED_RETURN(pRenderClient->GetBuffer(bufferFrameCount, &data));
+
+ sw.FillFrames(data, bufferFrameCount);
+ IF_FAILED_RETURN(pRenderClient->ReleaseBuffer(bufferFrameCount, 0));
+
+ IF_FAILED_RETURN(pAudioClient->Start());
+
+ unsigned c = 0;
+ while (c++ < duration)
+ {
+ if (WaitForSingleObject(bufferCompleteEvent.get(), ONE_SEC_IN_MS) != WAIT_OBJECT_0)
+ {
+ break;
+ }
+
+ unsigned numFramesPadding{};
+ IF_FAILED_RETURN(pAudioClient->GetCurrentPadding(&numFramesPadding));
+ auto numFramesAvailable = bufferFrameCount - numFramesPadding;
+
+ IF_FAILED_RETURN(pRenderClient->GetBuffer(numFramesAvailable, &data));
+ sw.FillFrames(data, numFramesAvailable);
+ IF_FAILED_RETURN(pRenderClient->ReleaseBuffer(numFramesAvailable, 0));
+ }
+
+ // Get a sample of the current AudioDG memory usage
+ GetAudioDGMemoryUsageSample();
+
+ IF_FAILED_RETURN(pAudioClient->Stop());
+
+ return S_OK;
+}
+
+void RunStressTest(int timeInSeconds, std::vector<wil::com_ptr<IMMDevice>>& pEndpoints)
+{
+ const UINT num = static_cast<UINT>(pEndpoints.size()) * NUMBER_OF_TESTS;
+
+ std::vector<std::thread> threads(num);
+
+ for (UINT i = 0; i < pEndpoints.size(); i++)
+ {
+ threads[i * NUMBER_OF_TESTS + 0] = std::thread([=](){
+ BasicAudioStreaming(pEndpoints[i].get());
+ });
+
+ threads[i * NUMBER_OF_TESTS + 1] = std::thread([=](){
+ BasicAudioStreaming(pEndpoints[i].get());
+ });
+
+ threads[i * NUMBER_OF_TESTS + 2] = std::thread([=](){
+ BasicAudioStreaming(pEndpoints[i].get());
+ });
+
+ threads[i * NUMBER_OF_TESTS + 3] = std::thread([=](){
+ BasicAudioCapture(pEndpoints[i].get());
+ });
+
+ threads[i * NUMBER_OF_TESTS + 4] = std::thread([=](){
+ BasicAudioLoopback(pEndpoints[i].get());
+ });
+
+ threads[i * NUMBER_OF_TESTS + 5] = std::thread([=](){
+ DisableEnableEndpoint(pEndpoints[i].get());
+ });
+
+ threads[i * NUMBER_OF_TESTS + 6] = std::thread([=](){
+ BasicSpatialAudio(pEndpoints[i].get());
+ });
+
+ threads[i * NUMBER_OF_TESTS + 7] = std::thread([=](){
+ BasicOffloadStreaming(pEndpoints[i].get());
+ });
+ }
+
+ time_t timer;
+ time(&timer);
+
+ time_t endTime = timer + timeInSeconds;
+
+ while (timer < endTime)
+ {
+ for (UINT i = 0; i < num; i++)
+ {
+ if (threads[i].joinable())
+ {
+ UINT testNumber = i % NUMBER_OF_TESTS;
+ UINT k = i / NUMBER_OF_TESTS;
+
+ threads[i].join();
+
+ switch (testNumber)
+ {
+ case 0:
+ threads[i] = std::thread([=]() {
+ Sleep(RandInRange(WAIT_TIME_MIN_FOR_THREAD_OPERATION, WAIT_TIME_MAX_FOR_THREAD_OPERATION));
+ BasicAudioStreaming(pEndpoints[k].get());
+ });
+ break;
+ case 1:
+ threads[i] = std::thread([=]() {
+ Sleep(RandInRange(WAIT_TIME_MIN_FOR_THREAD_OPERATION, WAIT_TIME_MAX_FOR_THREAD_OPERATION));
+ BasicAudioStreaming(pEndpoints[k].get());
+ });
+ break;
+ case 2:
+ threads[i] = std::thread([=]() {
+ Sleep(RandInRange(WAIT_TIME_MIN_FOR_THREAD_OPERATION, WAIT_TIME_MAX_FOR_THREAD_OPERATION));
+ BasicAudioStreaming(pEndpoints[k].get());
+ });
+ break;
+ case 3:
+ threads[i] = std::thread([=]() {
+ Sleep(RandInRange(WAIT_TIME_MIN_FOR_THREAD_OPERATION, WAIT_TIME_MAX_FOR_THREAD_OPERATION));
+ BasicAudioCapture(pEndpoints[k].get());
+ });
+ break;
+ case 4:
+ threads[i] = std::thread([=]() {
+ Sleep(RandInRange(WAIT_TIME_MIN_FOR_THREAD_OPERATION, WAIT_TIME_MAX_FOR_THREAD_OPERATION));
+ BasicAudioLoopback(pEndpoints[k].get());
+ });
+ break;
+ case 5:
+ threads[i] = std::thread([=]() {
+ Sleep(RandInRange(WAIT_TIME_MIN_FOR_THREAD_OPERATION, WAIT_TIME_MAX_FOR_THREAD_OPERATION));
+ DisableEnableEndpoint(pEndpoints[k].get());
+ });
+ break;
+ case 6:
+ threads[i] = std::thread([=]() {
+ Sleep(RandInRange(WAIT_TIME_MIN_FOR_THREAD_OPERATION, WAIT_TIME_MAX_FOR_THREAD_OPERATION));
+ BasicSpatialAudio(pEndpoints[k].get());
+ });
+ break;
+ case 7:
+ threads[i] = std::thread([=]() {
+ Sleep(RandInRange(WAIT_TIME_MIN_FOR_THREAD_OPERATION, WAIT_TIME_MAX_FOR_THREAD_OPERATION));
+ BasicOffloadStreaming(pEndpoints[k].get());
+ });
+ break;
+ }
+ }
+ }
+
+ time(&timer);
+ }
+
+ for (UINT j = 0; j < num; j++)
+ {
+ if (threads[j].joinable())
+ {
+ threads[j].join();
+ }
+ }
+
+ std::lock_guard<std::mutex> autoLock(maxAudioDGPagefileUsage_mutex);
+
+ // If we were not able to open the AudioDG handle process we should have 0 as memory usage
+ VERIFY_IS_TRUE(maxAudioDGPagefileUsage > 0);
+
+ // Adding the maxPagefileUsageValue to the VERIFY as a string
+ wchar_t maxAudioDGPagefileUsageString[32];
+ swprintf_s(maxAudioDGPagefileUsageString, L"%u", maxAudioDGPagefileUsage);
+
+ VERIFY_IS_TRUE(maxAudioDGPagefileUsage < MAX_ALLOWED_PAGEFILE_USAGE_IN_BYTES, maxAudioDGPagefileUsageString);
+} \ No newline at end of file
diff --git a/audio/tests/HLK/ThirdPartyApoTests/APOStressTest.h b/audio/tests/HLK/ThirdPartyApoTests/APOStressTest.h
new file mode 100644
index 00000000..07e74ea9
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/APOStressTest.h
@@ -0,0 +1,50 @@
+#include <stdafx.h>
+
+#define FIVE_MIN_IN_SEC 300
+
+class CAPOStressTest
+{
+ CAPOStressTest(){};
+ ~CAPOStressTest(){};
+
+ BEGIN_TEST_CLASS(CAPOStressTest)
+ START_APPVERIFIFER
+ TEST_CLASS_PROPERTY(L"Owner", L"auddev")
+ TEST_CLASS_PROPERTY(L"TestClassification", L"Feature")
+ TEST_CLASS_PROPERTY(L"BinaryUnderTest", L"audiodg.exe")
+ TEST_CLASS_PROPERTY(L"ArtifactUnderTest", L"audioenginebaseapop.h")
+ TEST_CLASS_PROPERTY(L"RunAs", L"System")
+ TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA")
+ TEST_CLASS_PROPERTY(L"Ignore", L"false")
+ TEST_CLASS_PROPERTY(L"EtwLogger:WPRProfileFile", L"Audio-Tests.wprp")
+ TEST_CLASS_PROPERTY(L"EtwLogger:WPRProfile", L"MultimediaCategory.Verbose.File")
+ END_APPVERIFIER
+ END_TEST_CLASS()
+
+public:
+ TEST_METHOD_SETUP(setUpMethod);
+ TEST_METHOD_CLEANUP(tearDownMethod);
+
+protected:
+ BEGIN_TEST_METHOD(AudioAPOStressTest)
+ COMMON_ONECORE_TEST_PROPERTIES
+ TEST_METHOD_PROPERTY(L"Kits.TestId", L"5C35BC8F-FAE1-434B-B842-6B58353696AB")
+ TEST_METHOD_PROPERTY(L"Kits.TestId2", L"1EB5F7F0-CA62-411E-9006-53A23F488332")
+ TEST_METHOD_PROPERTY(L"Kits.TestName", L"Audio APO - Stress the APO - AudioAPOStressTest")
+ TEST_METHOD_PROPERTY(L"Kits.ExpectedRuntime", L"30")
+ TEST_METHOD_PROPERTY(L"Kits.TimeoutInMinutes", L"60")
+ TEST_METHOD_PROPERTY(L"Kits.Description", L"Third Party APO Test: AudioAPOStressTest")
+ APO_TEST_PROPERTIES
+ END_TEST_METHOD()
+};
+
+HRESULT BasicAudioStreaming(IMMDevice *pEndpoint);
+HRESULT DisableEnableEndpoint(IMMDevice *pEndpoint);
+HRESULT BasicAudioCapture(IMMDevice *pEndpoint);
+HRESULT BasicAudioLoopback(IMMDevice *pEndpoint);
+HRESULT BasicSpatialAudio(IMMDevice *pEndpoint);
+HRESULT BasicOffloadStreaming(IMMDevice *pEndpoint);
+void RunStressTest(int timeInSeconds, std::vector<wil::com_ptr<IMMDevice>>& pEndpoints);
+
+bool SetupSkipRTHeap();
+bool CleanupSkipRTHeap(); \ No newline at end of file
diff --git a/audio/tests/HLK/ThirdPartyApoTests/CAPXHelper.cpp b/audio/tests/HLK/ThirdPartyApoTests/CAPXHelper.cpp
new file mode 100644
index 00000000..5600fb72
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/CAPXHelper.cpp
@@ -0,0 +1,247 @@
+#pragma once
+
+#include "CAPXHelper.h"
+
+bool IsCapXAPO(GUID clsid)
+{
+ bool bIsCapXAPO = false;
+
+ wil::com_ptr_nothrow<IAudioProcessingObject> apo;
+ if(SUCCEEDED(CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, __uuidof(IAudioProcessingObject), reinterpret_cast<void**>(&apo))))
+ {
+ wil::com_ptr_nothrow<IAudioSystemEffects3> capXAPO;
+ bIsCapXAPO = wil::try_com_query_to(apo, &capXAPO);
+ }
+
+ return bIsCapXAPO;
+}
+
+void GetClsidsFromVar(const PROPVARIANT& var, std::vector<GUID>& guids, _Outptr_ PWSTR* ppszFormattedClsids, std::vector<GUID>& capxGuids, _Outptr_ PWSTR* ppszCapXFormattedClsids)
+{
+ WCHAR formattedClsids[1024] = {};
+ PWSTR writeLocation = formattedClsids;
+ size_t remainingChars = ARRAYSIZE(formattedClsids);
+ const PWSTR formatSeparator = L"|%s";
+ bool bIsCapXAPO;
+ WCHAR capXformattedClsids[1024] = {};
+ PWSTR capXwriteLocation = capXformattedClsids;
+ size_t capXremainingChars = ARRAYSIZE(capXformattedClsids);
+
+ for (UINT i = 0; i < var.calpwstr.cElems; i++)
+ {
+ // populate vector
+ GUID clsid = {};
+ if (FAILED(CLSIDFromString(var.calpwstr.pElems[i], &clsid)))
+ {
+ return;
+ }
+
+ bIsCapXAPO = IsCapXAPO(clsid);
+ try
+ {
+ bIsCapXAPO ? capxGuids.push_back(clsid) : guids.push_back(clsid);
+ }
+ CATCH_LOG();
+
+ // build string to log
+ if (FAILED(bIsCapXAPO ? StringCchPrintfEx(capXwriteLocation, capXremainingChars, &capXwriteLocation, &capXremainingChars, 0, formatSeparator, var.calpwstr.pElems[i])
+ : StringCchPrintfEx(writeLocation, remainingChars, &writeLocation, &remainingChars, 0, formatSeparator, var.calpwstr.pElems[i])))
+ {
+ return;
+ }
+ }
+
+ wil::unique_cotaskmem_string spFormattedClsids = wil::make_cotaskmem_string_nothrow(formattedClsids+1);
+ if (spFormattedClsids)
+ {
+ *ppszFormattedClsids = spFormattedClsids.release();
+ }
+
+ wil::unique_cotaskmem_string spCapXFormattedClsids = wil::make_cotaskmem_string_nothrow(capXformattedClsids+1);
+ if (spCapXFormattedClsids)
+ {
+ *ppszCapXFormattedClsids = spCapXFormattedClsids.release();
+ }
+}
+
+
+bool EndpointContainsCapx(IMMDevice* pDevice)
+{
+ // some endpoints have an effects property store
+ // grab properties from that
+
+ GUID clsidSfx = {};
+ bool bIsCapXSfx = false;
+ GUID clsidMfx = {};
+ bool bIsCapXMfx = false;
+ GUID clsidEfx = {};
+ bool bIsCapXEfx = false;
+
+ // legacy drivers
+ GUID clsidLfx = {};
+ bool bIsCapXLfx = false;
+ GUID clsidGfx = {};
+ bool bIsCapXGfx = false;
+
+ // offload pin
+ GUID clsidOffloadSfx = {};
+ bool bIsCapXOffloadSfx = false;
+ GUID clsidOffloadMfx = {};
+ bool bIsCapXOffloadMfx = false;
+
+ // keyword spotter pin
+ GUID clsidKeywordSfx = {};
+ bool bIsCapXKeywordSfx = false;
+ GUID clsidKeywordMfx = {};
+ bool bIsCapXKeywordMfx = false;
+ GUID clsidKeywordEfx = {};
+ bool bIsCapXKeywordEfx = false;
+
+ // // composite effects
+ std::vector<GUID> clsidsCompositeSfx;
+ wil::unique_cotaskmem_string clsidsCompositeSfxStr;
+ std::vector<GUID> clsidsCompositeMfx;
+ wil::unique_cotaskmem_string clsidsCompositeMfxStr;
+ std::vector<GUID> clsidsCompositeEfx;
+ wil::unique_cotaskmem_string clsidsCompositeEfxStr;
+ // // CapX composite effects
+ std::vector<GUID> clsidsCapXCompositeSfx;
+ wil::unique_cotaskmem_string clsidsCapXCompositeSfxStr;
+ std::vector<GUID> clsidsCapXCompositeMfx;
+ wil::unique_cotaskmem_string clsidsCapXCompositeMfxStr;
+ std::vector<GUID> clsidsCapXCompositeEfx;
+ wil::unique_cotaskmem_string clsidsCapXCompositeEfxStr;
+
+ wil::com_ptr_nothrow<IMMEndpointInternal> spMMEndpointInternal;
+ if (wil::try_com_query_to(pDevice, &spMMEndpointInternal))
+ {
+ wil::com_ptr_nothrow<IPropertyStore> spFxProperties;
+ if ((S_OK == spMMEndpointInternal->TryOpenFXPropertyStore(STGM_READ, &spFxProperties)) && spFxProperties)
+ {
+ wil::unique_prop_variant varClsidSfx;
+ if (SUCCEEDED(spFxProperties->GetValue(PKEY_FX_StreamEffectClsid, &varClsidSfx)) && varClsidSfx.vt == VT_LPWSTR)
+ {
+ CLSIDFromString(varClsidSfx.pwszVal, &clsidSfx);
+ bIsCapXSfx = IsCapXAPO(clsidSfx);
+ }
+
+ wil::unique_prop_variant varClsidMfx;
+ if (SUCCEEDED(spFxProperties->GetValue(PKEY_FX_ModeEffectClsid, &varClsidMfx)) && varClsidMfx.vt == VT_LPWSTR)
+ {
+ CLSIDFromString(varClsidMfx.pwszVal, &clsidMfx);
+ bIsCapXMfx = IsCapXAPO(clsidMfx);
+ }
+
+ wil::unique_prop_variant varClsidEfx;
+ if (SUCCEEDED(spFxProperties->GetValue(PKEY_FX_EndpointEffectClsid, &varClsidEfx)) && varClsidEfx.vt == VT_LPWSTR)
+ {
+ CLSIDFromString(varClsidEfx.pwszVal, &clsidEfx);
+ bIsCapXEfx = IsCapXAPO(clsidEfx);
+ }
+
+ // legacy drivers
+ wil::unique_prop_variant varClsidLfx;
+ if (SUCCEEDED(spFxProperties->GetValue(PKEY_FX_PreMixEffectClsid, &varClsidLfx)) && varClsidLfx.vt == VT_LPWSTR)
+ {
+ CLSIDFromString(varClsidLfx.pwszVal, &clsidLfx);
+ bIsCapXLfx = IsCapXAPO(clsidLfx);
+ }
+
+ wil::unique_prop_variant varClsidGfx;
+ if (SUCCEEDED(spFxProperties->GetValue(PKEY_FX_PostMixEffectClsid, &varClsidGfx)) && varClsidGfx.vt == VT_LPWSTR)
+ {
+ CLSIDFromString(varClsidGfx.pwszVal, &clsidGfx);
+ bIsCapXGfx = IsCapXAPO(clsidGfx);
+ }
+
+ // offload
+ wil::unique_prop_variant varClsidOffloadSfx;
+ if (SUCCEEDED(spFxProperties->GetValue(PKEY_FX_Offload_StreamEffectClsid, &varClsidOffloadSfx)) && varClsidOffloadSfx.vt == VT_LPWSTR)
+ {
+ CLSIDFromString(varClsidOffloadSfx.pwszVal, &clsidOffloadSfx);
+ bIsCapXOffloadSfx = IsCapXAPO(clsidOffloadSfx);
+ }
+
+ wil::unique_prop_variant varClsidOffloadMfx;
+ if (SUCCEEDED(spFxProperties->GetValue(PKEY_FX_Offload_ModeEffectClsid, &varClsidOffloadMfx)) && varClsidOffloadMfx.vt == VT_LPWSTR)
+ {
+ CLSIDFromString(varClsidOffloadMfx.pwszVal, &clsidOffloadMfx);
+ bIsCapXOffloadMfx = IsCapXAPO(clsidOffloadMfx);
+ }
+
+ // keyword
+ wil::unique_prop_variant varClsidKeywordSfx;
+ if (SUCCEEDED(spFxProperties->GetValue(PKEY_FX_KeywordDetector_StreamEffectClsid, &varClsidKeywordSfx)) && varClsidKeywordSfx.vt == VT_LPWSTR)
+ {
+ CLSIDFromString(varClsidKeywordSfx.pwszVal, &clsidKeywordSfx);
+ bIsCapXKeywordSfx = IsCapXAPO(clsidKeywordSfx);
+ }
+
+ wil::unique_prop_variant varClsidKeywordMfx;
+ if (SUCCEEDED(spFxProperties->GetValue(PKEY_FX_KeywordDetector_ModeEffectClsid, &varClsidKeywordMfx)) && varClsidKeywordMfx.vt == VT_LPWSTR)
+ {
+ CLSIDFromString(varClsidKeywordMfx.pwszVal, &clsidKeywordMfx);
+ bIsCapXKeywordMfx = IsCapXAPO(clsidKeywordMfx);
+ }
+
+ wil::unique_prop_variant varClsidKeywordEfx;
+ if (SUCCEEDED(spFxProperties->GetValue(PKEY_FX_KeywordDetector_EndpointEffectClsid, &varClsidKeywordEfx)) && varClsidKeywordEfx.vt == VT_LPWSTR)
+ {
+ CLSIDFromString(varClsidKeywordEfx.pwszVal, &clsidKeywordEfx);
+ bIsCapXKeywordEfx = IsCapXAPO(clsidKeywordEfx);
+ }
+
+ // composite effects
+ wil::unique_prop_variant varClsidsCompositeSfx;
+ if (SUCCEEDED(spFxProperties->GetValue(PKEY_CompositeFX_StreamEffectClsid, &varClsidsCompositeSfx))
+ && varClsidsCompositeSfx.vt == (VT_VECTOR | VT_LPWSTR)
+ && varClsidsCompositeSfx.calpwstr.cElems > 0)
+ {
+ GetClsidsFromVar(varClsidsCompositeSfx, clsidsCompositeSfx, &clsidsCompositeSfxStr, clsidsCapXCompositeSfx, &clsidsCapXCompositeSfxStr);
+ }
+
+ wil::unique_prop_variant varClsidsCompositeMfx;
+ if (SUCCEEDED(spFxProperties->GetValue(PKEY_CompositeFX_ModeEffectClsid, &varClsidsCompositeMfx))
+ && varClsidsCompositeMfx.vt == (VT_VECTOR | VT_LPWSTR)
+ && varClsidsCompositeMfx.calpwstr.cElems > 0)
+ {
+ GetClsidsFromVar(varClsidsCompositeMfx, clsidsCompositeMfx, &clsidsCompositeMfxStr, clsidsCapXCompositeMfx, &clsidsCapXCompositeMfxStr);
+ }
+
+ wil::unique_prop_variant varClsidsCompositeEfx;
+ if (SUCCEEDED(spFxProperties->GetValue(PKEY_CompositeFX_EndpointEffectClsid, &varClsidsCompositeEfx))
+ && varClsidsCompositeEfx.vt == (VT_VECTOR | VT_LPWSTR)
+ && varClsidsCompositeEfx.calpwstr.cElems > 0)
+ {
+ GetClsidsFromVar(varClsidsCompositeEfx, clsidsCompositeEfx, &clsidsCompositeEfxStr, clsidsCapXCompositeEfx, &clsidsCapXCompositeEfxStr);
+ }
+ }
+ }
+
+ return ( bIsCapXSfx || bIsCapXMfx || bIsCapXEfx || bIsCapXLfx || bIsCapXGfx ||
+ bIsCapXOffloadSfx || bIsCapXOffloadMfx || bIsCapXKeywordSfx || bIsCapXKeywordMfx || bIsCapXKeywordEfx ||
+ clsidsCapXCompositeSfx.size() > 0 || clsidsCapXCompositeMfx.size() > 0 || clsidsCapXCompositeMfx.size() > 0 );
+}
+
+void EndpointsWithCapx(std::vector<wil::com_ptr<IMMDevice>>& capxEndpoints)
+{
+ UINT cDevices = 0;
+ com_ptr_nothrow<IMMDeviceEnumerator> spEnumerator;
+ com_ptr_nothrow<IMMDeviceCollection> spDevices;
+
+ VERIFY_SUCCEEDED(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&spEnumerator)));
+ VERIFY_SUCCEEDED(spEnumerator->EnumAudioEndpoints(eAll, DEVICE_STATE_ACTIVE, &spDevices));
+ VERIFY_SUCCEEDED(spDevices->GetCount(&cDevices));
+
+ for (UINT i = 0; i < cDevices; i++)
+ {
+ wil::com_ptr<IMMDevice> pEndpoint = nullptr;
+
+ VERIFY_SUCCEEDED(spDevices->Item(i, &pEndpoint));
+
+ if (EndpointContainsCapx(pEndpoint.get()))
+ {
+ capxEndpoints.push_back(pEndpoint.get());
+ }
+ }
+} \ No newline at end of file
diff --git a/audio/tests/HLK/ThirdPartyApoTests/CAPXHelper.h b/audio/tests/HLK/ThirdPartyApoTests/CAPXHelper.h
new file mode 100644
index 00000000..62a5807e
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/CAPXHelper.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <stdafx.h>
+
+#include <wil\resultmacros.h>
+#include <wil\com.h>
+#include <audioclient.h>
+#include <audioclientp.h>
+#include <audiosessiontypesp.h>
+#include <mmdeviceapi.h>
+#include <mmdeviceapip.h>
+#include <endpointvolume.h>
+#include "etwlistener.h"
+#include <functiondiscoverykeys.h>
+#include <slpublic.h>
+
+#include <DevPKey.h>
+#include <AudioEngineBaseAPOP.h>
+#include "TestMediaType.h"
+#include <audioenginebaseapo.h>
+
+#include <list>
+#include <memory>
+
+using namespace std;
+using namespace wil;
+using namespace WEX::Logging;
+using namespace WEX::Common;
+
+bool IsCapXAPO(GUID clsid);
+void GetClsidsFromVar(const PROPVARIANT& var, std::vector<GUID>& guids, _Outptr_ PWSTR* ppszFormattedClsids, std::vector<GUID>& capxGuids, _Outptr_ PWSTR* ppszCapXFormattedClsids);
+bool EndpointContainsCapx(IMMDevice* pDevice);
+void EndpointsWithCapx(std::vector<wil::com_ptr<IMMDevice>>& capxEndpoints); \ No newline at end of file
diff --git a/audio/tests/HLK/ThirdPartyApoTests/CAPXLoggingFrameworkTests.cpp b/audio/tests/HLK/ThirdPartyApoTests/CAPXLoggingFrameworkTests.cpp
new file mode 100644
index 00000000..85f14ad8
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/CAPXLoggingFrameworkTests.cpp
@@ -0,0 +1,160 @@
+#include "CAPXLoggingFrameworkTests.h"
+
+
+bool CAPOLoggingFrameworkTest::setUpMethod()
+{
+ SLGetWindowsInformationDWORD(POLICY_KERNEL_ONECORE_DEVICE_FAMILY_ID, &m_dwPlatform);
+
+ EndpointsWithCapx(m_capxEndpoints);
+
+ return SetupSkipRTHeap();
+}
+
+bool CAPOLoggingFrameworkTest::tearDownMethod()
+{
+ return CleanupSkipRTHeap();
+}
+
+using malloca_deleter = wil::function_deleter<decltype(&::_freea), ::_freea>;
+template <typename T>
+using unique_malloca_ptr = wistd::unique_ptr<T, malloca_deleter>;
+enum QueryState
+{
+ None = 0,
+ ApoLog = 1,
+ PumpYield = 2
+};
+
+class CEventParser : public IEtwEventHandler
+{
+public:
+ int GetCountOfAPOLogging() { return m_countOfAudioProcessingNotifications; }
+ bool WasRTTThreadDetected() { return m_bRTThreadDetected; }
+ DWORD GetCountOfCreateFiles() { return m_dCreateFilesCalled; }
+
+private:
+
+ int m_countOfAudioProcessingNotifications = 0;
+ DWORD m_dLastPid = 0;
+ DWORD m_dLastThreadId = 0;
+ DWORD m_dCreateFilesCalled = 0;
+ bool m_bRTThreadDetected = false;
+ QueryState m_currentState = QueryState::None;
+
+ std::wstring QueryProcessName(const DWORD pid)
+ {
+ wil::unique_handle hProcess(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid));
+ if(NULL == hProcess)
+ {
+ return L"err " + std::to_wstring(GetLastError());
+ }
+ else
+ {
+ WCHAR szProcessName[1024];
+ DWORD cchSize = ARRAYSIZE(szProcessName);
+ if (0 == QueryFullProcessImageNameW(hProcess.get(), 0, szProcessName, &cchSize))
+ {
+ return L"err " + std::to_wstring(GetLastError());
+ }
+
+ PWSTR fileName = szProcessName + cchSize;
+ while (fileName != szProcessName && *fileName != L'\\') fileName--;
+
+ return (*fileName == L'\\') ? fileName + 1 : fileName;
+ }
+ }
+
+ std::wstring QueryTraceLevel(PEVENT_RECORD pEventRecord)
+ {
+ UNREFERENCED_PARAMETER(pEventRecord);
+ return L"err";
+ }
+
+ void OnEvent(PEVENT_RECORD pEventRecord)
+ {
+ WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
+ [&]() {
+ ULONG bufferSize = 0;
+ if (TdhGetEventInformation(pEventRecord, 0, nullptr, nullptr, &bufferSize) == ERROR_INSUFFICIENT_BUFFER)
+ {
+ unique_malloca_ptr<TRACE_EVENT_INFO> eventInfo(reinterpret_cast<PTRACE_EVENT_INFO>(_malloca(bufferSize)));
+ VERIFY_IS_NOT_NULL(eventInfo);
+ RETURN_IF_WIN32_ERROR(TdhGetEventInformation(pEventRecord, 0, nullptr, eventInfo.get(), &bufferSize));
+
+ // ApoLog is the name that the Logging framework uses for each of the logs sent through by the APO
+ if (_wcsicmp(L"ApoLog", reinterpret_cast<PWSTR>(reinterpret_cast<BYTE *>(eventInfo.get()) + eventInfo->EventNameOffset)) == 0)
+ {
+ m_countOfAudioProcessingNotifications++;
+ if (m_currentState == QueryState::PumpYield)
+ {
+ if (m_dLastPid == pEventRecord->EventHeader.ProcessId &&
+ m_dLastThreadId == pEventRecord->EventHeader.ThreadId)
+ {
+ m_bRTThreadDetected = true;
+ }
+ }
+
+ m_dLastPid = pEventRecord->EventHeader.ProcessId;
+ m_dLastThreadId = pEventRecord->EventHeader.ThreadId;
+ m_currentState = QueryState::ApoLog;
+ }
+ if (_wcsicmp(L"PumpYield", reinterpret_cast<PWSTR>(reinterpret_cast<BYTE *>(eventInfo.get()) + eventInfo->EventNameOffset)) == 0)
+ {
+ if (m_currentState == QueryState::ApoLog)
+ {
+ if (m_dLastPid == pEventRecord->EventHeader.ProcessId &&
+ m_dLastThreadId == pEventRecord->EventHeader.ThreadId)
+ {
+ m_bRTThreadDetected = true;
+ }
+ }
+
+ m_dLastPid = pEventRecord->EventHeader.ProcessId;
+ m_dLastThreadId = pEventRecord->EventHeader.ThreadId;
+ m_currentState = QueryState::PumpYield;
+ }
+ if (_wcsicmp(L"CreateFile", reinterpret_cast<PWSTR>(reinterpret_cast<BYTE*>(eventInfo.get()) + eventInfo->EventNameOffset)) == 0)
+ {
+ m_dCreateFilesCalled++;
+ }
+ }
+ return S_OK;
+ }();
+ }
+};
+
+// {6e7b1892-5288-5fe5-8f34-e3b0dc671fd2}
+static const GUID AudioSesTelemetryProvider =
+{ 0x6e7b1892, 0x5288, 0x5fe5, 0x8f, 0x34, 0xe3, 0xb0, 0xdc, 0x67, 0x1f, 0xd2 };
+
+void CAPOLoggingFrameworkTest::LoggingFrameworkTest()
+{
+ WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
+
+ if (m_dwPlatform != DEVICEFAMILYINFOENUM_WINDOWS_CORE && m_capxEndpoints.size() == 0)
+ {
+ Log::Result(TestResults::Skipped, L"There are no CAPX APOs to test");
+ return;
+ }
+
+ CEtwListener listener;
+ CEventParser parser;
+
+ VERIFY_SUCCEEDED(listener.StartTraceSession(L"LoggingFrameworkTest", static_cast<IEtwEventHandler *>(&parser)));
+
+ // Enable Microsoft.Windows.Audio.Client
+ VERIFY_SUCCEEDED(listener.EnableProvider(AudioSesTelemetryProvider, TRACE_LEVEL_INFORMATION, 8));
+
+ auto stopListener = scope_exit([&] {
+ listener.StopTraceSession();
+ });
+
+ wil::com_ptr_nothrow<IMMDeviceEnumerator> spEnumerator;
+ VERIFY_SUCCEEDED(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&spEnumerator)));
+
+ RunStressTest(FIVE_MIN_IN_SEC, m_capxEndpoints);
+
+ VERIFY_IS_FALSE(parser.WasRTTThreadDetected());
+ VERIFY_IS_TRUE(parser.GetCountOfCreateFiles() == 0);
+ LOG_OUTPUT(L"Number of APO logs collected: %d", parser.GetCountOfAPOLogging());
+} \ No newline at end of file
diff --git a/audio/tests/HLK/ThirdPartyApoTests/CAPXLoggingFrameworkTests.h b/audio/tests/HLK/ThirdPartyApoTests/CAPXLoggingFrameworkTests.h
new file mode 100644
index 00000000..939b7554
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/CAPXLoggingFrameworkTests.h
@@ -0,0 +1,73 @@
+#include <stdafx.h>
+
+
+#include <wil\resultmacros.h>
+#include <wil\com.h>
+#include <audioclient.h>
+#include <audioclientp.h>
+#include <audiosessiontypesp.h>
+#include <mmdeviceapi.h>
+#include <endpointvolume.h>
+#include "etwlistener.h"
+#include <functiondiscoverykeys.h>
+#include <slpublic.h>
+
+#include <DevPKey.h>
+#include <AudioEngineBaseAPOP.h>
+#include "TestMediaType.h"
+#include <audioenginebaseapo.h>
+
+#include <WexTestClass.h>
+
+#include <list>
+#include <memory>
+
+#include "APOStressTest.h"
+#include "CAPXHelper.h"
+
+using namespace std;
+using namespace wil;
+using namespace WEX::Logging;
+using namespace WEX::Common;
+
+#define POLICY_KERNEL_ONECORE_DEVICE_FAMILY_ID L"Kernel-OneCore-DeviceFamilyID"
+
+class CAPOLoggingFrameworkTest
+{
+ CAPOLoggingFrameworkTest(){};
+ ~CAPOLoggingFrameworkTest(){};
+
+ BEGIN_TEST_CLASS(CAPOLoggingFrameworkTest)
+ START_APPVERIFIFER
+ TEST_CLASS_PROPERTY(L"Owner", L"auddev")
+ TEST_CLASS_PROPERTY(L"TestClassification", L"Feature")
+ TEST_CLASS_PROPERTY(L"BinaryUnderTest", L"audiodg.exe")
+ TEST_CLASS_PROPERTY(L"ArtifactUnderTest", L"audioenginebaseapop.h")
+ TEST_CLASS_PROPERTY(L"RunAs", L"Elevated")
+ TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA")
+ TEST_CLASS_PROPERTY(L"Ignore", L"false")
+ TEST_CLASS_PROPERTY(L"EtwLogger:WPRProfileFile", L"Audio-Tests.wprp")
+ TEST_CLASS_PROPERTY(L"EtwLogger:WPRProfile", L"MultimediaCategory.Verbose.File")
+ END_APPVERIFIER
+ END_TEST_CLASS()
+
+public:
+ TEST_METHOD_SETUP(setUpMethod);
+ TEST_METHOD_CLEANUP(tearDownMethod);
+
+protected:
+ BEGIN_TEST_METHOD(LoggingFrameworkTest)
+ COMMON_ONECORE_TEST_PROPERTIES
+ TEST_METHOD_PROPERTY(L"Kits.TestId", L"4FF3BA81-2539-4762-9F7D-40547D1DAD95")
+ TEST_METHOD_PROPERTY(L"Kits.TestId2", L"FEEC362D-673C-40B3-BB01-5063C4B33EA4")
+ TEST_METHOD_PROPERTY(L"Kits.TestName", L"Audio APO CAPX - Test the Logging Framework - LoggingFrameworkTest")
+ TEST_METHOD_PROPERTY(L"Kits.ExpectedRuntime", L"30")
+ TEST_METHOD_PROPERTY(L"Kits.TimeoutInMinutes", L"60")
+ TEST_METHOD_PROPERTY(L"Kits.Description", L"Third Party CAPX APO Test: LoggingFrameworkTest")
+ APO_TEST_PROPERTIES
+ END_TEST_METHOD()
+
+private:
+ DWORD m_dwPlatform = DEVICEFAMILYINFOENUM_UAP;
+ std::vector<wil::com_ptr<IMMDevice>> m_capxEndpoints;
+};
diff --git a/audio/tests/HLK/ThirdPartyApoTests/CAPXNotificationFrameworkTests.cpp b/audio/tests/HLK/ThirdPartyApoTests/CAPXNotificationFrameworkTests.cpp
new file mode 100644
index 00000000..e55f9764
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/CAPXNotificationFrameworkTests.cpp
@@ -0,0 +1,168 @@
+#include "CAPXNotificationFrameworkTests.h"
+
+
+bool CAPONotificationFrameworkTest::setUpMethod()
+{
+ SLGetWindowsInformationDWORD(POLICY_KERNEL_ONECORE_DEVICE_FAMILY_ID, &m_dwPlatform);
+
+ EndpointsWithCapx(m_capxEndpoints);
+
+ return true;
+}
+
+bool CAPONotificationFrameworkTest::tearDownMethod()
+{
+ return true;
+}
+
+using malloca_deleter = wil::function_deleter<decltype(&::_freea), ::_freea>;
+template <typename T>
+using unique_malloca_ptr = wistd::unique_ptr<T, malloca_deleter>;
+
+class CEventParser : public IEtwEventHandler
+{
+public:
+ int GetCountOfAPONotifications() { return m_countOfAudioProcessingNotifications; }
+ bool WereOldNotificationsDetected() { return m_bOldNotificationsDetected; }
+
+private:
+
+ int m_countOfAudioProcessingNotifications = 0;
+ DWORD m_dLastPid = 0;
+ DWORD m_dLastThreadId = 0;
+ bool m_bOldNotificationsDetected = false;
+
+ std::wstring QueryProcessName(const DWORD pid)
+ {
+ wil::unique_handle hProcess(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid));
+ if(NULL == hProcess)
+ {
+ return L"err " + std::to_wstring(GetLastError());
+ }
+ else
+ {
+ WCHAR szProcessName[1024];
+ DWORD cchSize = ARRAYSIZE(szProcessName);
+ if (0 == QueryFullProcessImageNameW(hProcess.get(), 0, szProcessName, &cchSize))
+ {
+ return L"err " + std::to_wstring(GetLastError());
+ }
+
+ PWSTR fileName = szProcessName + cchSize;
+ while (fileName != szProcessName && *fileName != L'\\') fileName--;
+
+ return (*fileName == L'\\') ? fileName + 1 : fileName;
+ }
+ }
+
+ void OnEvent(PEVENT_RECORD pEventRecord)
+ {
+ WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
+ [&]() {
+ ULONG bufferSize = 0;
+ if (TdhGetEventInformation(pEventRecord, 0, nullptr, nullptr, &bufferSize) == ERROR_INSUFFICIENT_BUFFER)
+ {
+ unique_malloca_ptr<TRACE_EVENT_INFO> eventInfo(reinterpret_cast<PTRACE_EVENT_INFO>(_malloca(bufferSize)));
+ VERIFY_IS_NOT_NULL(eventInfo);
+ RETURN_IF_WIN32_ERROR(TdhGetEventInformation(pEventRecord, 0, nullptr, eventInfo.get(), &bufferSize));
+
+ // Check for old notification types
+ if (_wcsicmp(L"IAudioProcessingObjectNotifications implemented", reinterpret_cast<PWSTR>(reinterpret_cast<BYTE *>(eventInfo.get()) + eventInfo->EventNameOffset)) == 0)
+ {
+ m_countOfAudioProcessingNotifications++;
+ m_dLastPid = pEventRecord->EventHeader.ProcessId;
+ m_dLastThreadId = pEventRecord->EventHeader.ThreadId;
+ }
+ if (_wcsicmp(L"OnPropertyValueChanged", reinterpret_cast<PWSTR>(reinterpret_cast<BYTE *>(eventInfo.get()) + eventInfo->EventNameOffset)) == 0)
+ {
+ if (m_dLastPid == pEventRecord->EventHeader.ProcessId &&
+ m_dLastThreadId == pEventRecord->EventHeader.ThreadId)
+ {
+ m_bOldNotificationsDetected = true;
+ }
+ }
+ if (_wcsicmp(L"OnEndpointVolumeChanged", reinterpret_cast<PWSTR>(reinterpret_cast<BYTE *>(eventInfo.get()) + eventInfo->EventNameOffset)) == 0)
+ {
+ if (m_dLastPid == pEventRecord->EventHeader.ProcessId &&
+ m_dLastThreadId == pEventRecord->EventHeader.ThreadId)
+ {
+ m_bOldNotificationsDetected = true;
+ }
+ }
+ if (_wcsicmp(L"RegisterEndpointNotificationCallback", reinterpret_cast<PWSTR>(reinterpret_cast<BYTE *>(eventInfo.get()) + eventInfo->EventNameOffset)) == 0 ||
+ _wcsicmp(L"RegisterEndpointNotificationCallbackWithVirtualEnumerator", reinterpret_cast<PWSTR>(reinterpret_cast<BYTE *>(eventInfo.get()) + eventInfo->EventNameOffset)) == 0)
+ {
+ if (m_dLastPid == pEventRecord->EventHeader.ProcessId &&
+ m_dLastThreadId == pEventRecord->EventHeader.ThreadId)
+ {
+ m_bOldNotificationsDetected = true;
+ }
+ }
+ if (_wcsicmp(L"UnregisterEndpointNotificationCallback", reinterpret_cast<PWSTR>(reinterpret_cast<BYTE *>(eventInfo.get()) + eventInfo->EventNameOffset)) == 0 ||
+ _wcsicmp(L"UnregisterEndpointNotificationCallbackWithVirtualEnumerator", reinterpret_cast<PWSTR>(reinterpret_cast<BYTE *>(eventInfo.get()) + eventInfo->EventNameOffset)) == 0)
+ {
+ if (m_dLastPid == pEventRecord->EventHeader.ProcessId &&
+ m_dLastThreadId == pEventRecord->EventHeader.ThreadId)
+ {
+ m_bOldNotificationsDetected = true;
+ }
+ }
+ }
+ return S_OK;
+ }();
+ }
+};
+
+// {6e7b1892-5288-5fe5-8f34-e3b0dc671fd2}
+static const GUID AudioSesTelemetryProvider =
+{ 0x6e7b1892, 0x5288, 0x5fe5, 0x8f, 0x34, 0xe3, 0xb0, 0xdc, 0x67, 0x1f, 0xd2 };
+
+void CAPONotificationFrameworkTest::NotificationFrameworkTest()
+{
+ WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
+
+ if (m_dwPlatform != DEVICEFAMILYINFOENUM_WINDOWS_CORE && m_capxEndpoints.size() == 0)
+ {
+ Log::Result(TestResults::Skipped, L"There are no CAPX APOs to test");
+ return;
+ }
+
+ CEtwListener listener;
+ CEventParser parser;
+
+ VERIFY_SUCCEEDED(listener.StartTraceSession(L"NotificationFrameworkTest", static_cast<IEtwEventHandler *>(&parser)));
+
+ // Enable Microsoft.Windows.Audio.Client
+ VERIFY_SUCCEEDED(listener.EnableProvider(AudioSesTelemetryProvider, TRACE_LEVEL_INFORMATION, 8));
+
+ auto stopListener = scope_exit([&] {
+ listener.StopTraceSession();
+ });
+
+ {
+ for (UINT i = 0; i < m_capxEndpoints.size(); i++)
+ {
+ wil::com_ptr_nothrow<IMMDevice> pEndpoint = m_capxEndpoints.at(i);
+
+ wil::unique_prop_variant var;
+ wil::com_ptr_nothrow<IPropertyStore> spPropertyStore;
+ VERIFY_SUCCEEDED(pEndpoint->OpenPropertyStore(STGM_READ, &spPropertyStore));
+ VERIFY_SUCCEEDED(spPropertyStore->GetValue(PKEY_Device_FriendlyName, &var));
+ VERIFY_ARE_EQUAL(VT_LPWSTR, var.vt);
+ LOG_OUTPUT(L"Testing endpoint: %s", var.pwszVal);
+
+ wil::com_ptr_nothrow<IAudioEndpointVolume> aev;
+ VERIFY_SUCCEEDED(pEndpoint->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (void **)&aev));
+
+ VERIFY_SUCCEEDED(aev->SetMasterVolumeLevelScalar((0.7f), NULL));
+
+ Sleep(500);
+
+ VERIFY_SUCCEEDED(aev->SetMasterVolumeLevelScalar((1.0f), NULL));
+
+ LOG_OUTPUT(L"Number of APO notifications detected: %d", parser.GetCountOfAPONotifications());
+ }
+
+ VERIFY_IS_FALSE(parser.WereOldNotificationsDetected());
+ }
+} \ No newline at end of file
diff --git a/audio/tests/HLK/ThirdPartyApoTests/CAPXNotificationFrameworkTests.h b/audio/tests/HLK/ThirdPartyApoTests/CAPXNotificationFrameworkTests.h
new file mode 100644
index 00000000..0b7244f2
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/CAPXNotificationFrameworkTests.h
@@ -0,0 +1,84 @@
+#include <stdafx.h>
+#include <memory>
+#include <wil\resultmacros.h>
+#include <wil\com.h>
+#include <audioclient.h>
+#include <audioclientp.h>
+#include <audiosessiontypesp.h>
+#include <mmdeviceapi.h>
+#include "etwlistener.h"
+#include <functiondiscoverykeys.h>
+
+#include <wil\resultmacros.h>
+#include <wil\com.h>
+#include <audioclient.h>
+#include <audioclientp.h>
+#include <audiosessiontypesp.h>
+#include <mmdeviceapi.h>
+#include <endpointvolume.h>
+#include "etwlistener.h"
+#include <functiondiscoverykeys.h>
+#include <slpublic.h>
+
+#include <DevPKey.h>
+#include <AudioEngineBaseAPOP.h>
+#include "TestMediaType.h"
+#include <audioenginebaseapo.h>
+
+#include <WexTestClass.h>
+
+#include <list>
+#include <memory>
+
+#include "CAPXHelper.h"
+
+#include <initguid.h>
+#include <guiddef.h>
+DEFINE_GUID(CLSID_TestCapxAPO, 0xA43110A0,0x4D2B,0x4C5B,0x99,0xB0,0xC6,0xF8,0x62,0x08,0x28,0xB1);
+
+using namespace std;
+using namespace wil;
+using namespace WEX::Logging;
+using namespace WEX::Common;
+
+#define POLICY_KERNEL_ONECORE_DEVICE_FAMILY_ID L"Kernel-OneCore-DeviceFamilyID"
+
+class CAPONotificationFrameworkTest
+{
+ CAPONotificationFrameworkTest(){};
+ ~CAPONotificationFrameworkTest(){};
+
+ BEGIN_TEST_CLASS(CAPONotificationFrameworkTest)
+ START_APPVERIFIFER
+ TEST_CLASS_PROPERTY(L"Owner", L"auddev")
+ TEST_CLASS_PROPERTY(L"TestClassification", L"Feature")
+ TEST_CLASS_PROPERTY(L"BinaryUnderTest", L"audiodg.exe")
+ TEST_CLASS_PROPERTY(L"ArtifactUnderTest", L"audioenginebaseapop.h")
+ TEST_CLASS_PROPERTY(L"RunAs", L"Elevated")
+ TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA")
+ TEST_CLASS_PROPERTY(L"Ignore", L"false")
+ TEST_CLASS_PROPERTY(L"EtwLogger:WPRProfileFile", L"Audio-Tests.wprp")
+ TEST_CLASS_PROPERTY(L"EtwLogger:WPRProfile", L"MultimediaCategory.Verbose.File")
+ END_APPVERIFIER
+ END_TEST_CLASS()
+
+public:
+ TEST_METHOD_SETUP(setUpMethod);
+ TEST_METHOD_CLEANUP(tearDownMethod);
+
+protected:
+ BEGIN_TEST_METHOD(NotificationFrameworkTest)
+ COMMON_ONECORE_TEST_PROPERTIES
+ TEST_METHOD_PROPERTY(L"Kits.TestId", L"30F6BEE7-2AC9-4434-B1AD-642055B2E871")
+ TEST_METHOD_PROPERTY(L"Kits.TestId2", L"C53BE546-1188-4167-B426-E291524BCFD9")
+ TEST_METHOD_PROPERTY(L"Kits.TestName", L"Audio APO CAPX - Test the Notification Framework - NotificationFrameworkTest")
+ TEST_METHOD_PROPERTY(L"Kits.ExpectedRuntime", L"30")
+ TEST_METHOD_PROPERTY(L"Kits.TimeoutInMinutes", L"60")
+ TEST_METHOD_PROPERTY(L"Kits.Description", L"Third Party CAPX APO Test: NotificationFrameworkTest")
+ APO_TEST_PROPERTIES
+ END_TEST_METHOD()
+
+private:
+ DWORD m_dwPlatform = DEVICEFAMILYINFOENUM_UAP;
+ std::vector<wil::com_ptr<IMMDevice>> m_capxEndpoints;
+};
diff --git a/audio/tests/HLK/ThirdPartyApoTests/CAPXThreadingFrameworkTests.cpp b/audio/tests/HLK/ThirdPartyApoTests/CAPXThreadingFrameworkTests.cpp
new file mode 100644
index 00000000..e670518c
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/CAPXThreadingFrameworkTests.cpp
@@ -0,0 +1,118 @@
+#include "CAPXThreadingFrameworkTests.h"
+
+
+bool CAPOThreadingFrameworkTest::setUpMethod()
+{
+ SLGetWindowsInformationDWORD(POLICY_KERNEL_ONECORE_DEVICE_FAMILY_ID, &m_dwPlatform);
+
+ EndpointsWithCapx(m_capxEndpoints);
+
+ return SetupSkipRTHeap();
+}
+
+bool CAPOThreadingFrameworkTest::tearDownMethod()
+{
+ return CleanupSkipRTHeap();
+}
+
+using malloca_deleter = wil::function_deleter<decltype(&::_freea), ::_freea>;
+template <typename T>
+using unique_malloca_ptr = wistd::unique_ptr<T, malloca_deleter>;
+int g_mmThreadCount = 0;
+
+class CEventParser : public IEtwEventHandler
+{
+public:
+ int GetCountOfAPOThreads() { return m_countOfAPOThreads; }
+
+private:
+
+ int m_countOfAPOThreads = 0;
+
+ std::wstring QueryProcessName(const DWORD pid)
+ {
+ wil::unique_handle hProcess(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid));
+ if(NULL == hProcess)
+ {
+ return L"err " + std::to_wstring(GetLastError());
+ }
+ else
+ {
+ WCHAR szProcessName[1024];
+ DWORD cchSize = ARRAYSIZE(szProcessName);
+ if (0 == QueryFullProcessImageNameW(hProcess.get(), 0, szProcessName, &cchSize))
+ {
+ return L"err " + std::to_wstring(GetLastError());
+ }
+
+ PWSTR fileName = szProcessName + cchSize;
+ while (fileName != szProcessName && *fileName != L'\\') fileName--;
+
+ return (*fileName == L'\\') ? fileName + 1 : fileName;
+ }
+ }
+
+ void OnEvent(PEVENT_RECORD pEventRecord)
+ {
+ WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
+ [&]() {
+ ULONG bufferSize = 0;
+ if (TdhGetEventInformation(pEventRecord, 0, nullptr, nullptr, &bufferSize) == ERROR_INSUFFICIENT_BUFFER)
+ {
+ unique_malloca_ptr<TRACE_EVENT_INFO> eventInfo(reinterpret_cast<PTRACE_EVENT_INFO>(_malloca(bufferSize)));
+ VERIFY_IS_NOT_NULL(eventInfo);
+ RETURN_IF_WIN32_ERROR(TdhGetEventInformation(pEventRecord, 0, nullptr, eventInfo.get(), &bufferSize));
+
+ // Threading implemented is the temporary name that the threading framework will be called until the final logs are created
+ if (_wcsicmp(L"Threading implemented", reinterpret_cast<PWSTR>(reinterpret_cast<BYTE*>(eventInfo.get()) + eventInfo->EventNameOffset)) == 0)
+ {
+ m_countOfAPOThreads++;
+ }
+ auto mmThreadMock = Mock10::Mock::Function(&AvSetMmThreadCharacteristics, [](LPCWSTR taskName, LPDWORD taskIndex) {
+ g_mmThreadCount++;
+ return AvSetMmThreadCharacteristics(taskName, taskIndex);
+ });
+ if (_wcsicmp(L"CreateThread", reinterpret_cast<PWSTR>(reinterpret_cast<BYTE*>(eventInfo.get()) + eventInfo->EventNameOffset)) == 0)
+ {
+ g_mmThreadCount++;
+ }
+ }
+ return S_OK;
+ }();
+ }
+};
+
+// {6e7b1892-5288-5fe5-8f34-e3b0dc671fd2}
+static const GUID AudioSesTelemetryProvider =
+{ 0x6e7b1892, 0x5288, 0x5fe5, 0x8f, 0x34, 0xe3, 0xb0, 0xdc, 0x67, 0x1f, 0xd2 };
+
+void CAPOThreadingFrameworkTest::ThreadingFrameworkTest()
+{
+ WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
+
+ if (m_dwPlatform != DEVICEFAMILYINFOENUM_WINDOWS_CORE && m_capxEndpoints.size() == 0)
+ {
+ Log::Result(TestResults::Skipped, L"There are no CAPX APOs to test");
+ return;
+ }
+
+ CEtwListener listener;
+ CEventParser parser;
+
+ VERIFY_SUCCEEDED(listener.StartTraceSession(L"ThreadingFrameworkTest", static_cast<IEtwEventHandler *>(&parser)));
+
+ // Enable Microsoft.Windows.Audio.Client
+ VERIFY_SUCCEEDED(listener.EnableProvider(AudioSesTelemetryProvider, TRACE_LEVEL_INFORMATION, 8));
+
+ auto stopListener = scope_exit([&] {
+ listener.StopTraceSession();
+ });
+
+ wil::com_ptr_nothrow<IMMDeviceEnumerator> spEnumerator;
+ VERIFY_SUCCEEDED(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&spEnumerator)));
+
+ RunStressTest(FIVE_MIN_IN_SEC, m_capxEndpoints);
+
+ LOG_OUTPUT(L"Number of APO threads created: %d", parser.GetCountOfAPOThreads());
+ VERIFY_IS_TRUE(g_mmThreadCount == 0);
+} \ No newline at end of file
diff --git a/audio/tests/HLK/ThirdPartyApoTests/CAPXThreadingFrameworkTests.h b/audio/tests/HLK/ThirdPartyApoTests/CAPXThreadingFrameworkTests.h
new file mode 100644
index 00000000..47b63766
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/CAPXThreadingFrameworkTests.h
@@ -0,0 +1,73 @@
+#include <stdafx.h>
+
+#include <avrt.h>
+#include <wil\resultmacros.h>
+#include <wil\com.h>
+#include <audioclient.h>
+#include <audioclientp.h>
+#include <audiosessiontypesp.h>
+#include <mmdeviceapi.h>
+#include <endpointvolume.h>
+#include "etwlistener.h"
+#include <functiondiscoverykeys.h>
+#include <slpublic.h>
+
+#include <DevPKey.h>
+#include <AudioEngineBaseAPOP.h>
+#include "TestMediaType.h"
+#include <audioenginebaseapo.h>
+
+#include <WexTestClass.h>
+
+#include <list>
+#include <memory>
+
+#include "APOStressTest.h"
+#include "CAPXHelper.h"
+
+using namespace std;
+using namespace wil;
+using namespace WEX::Logging;
+using namespace WEX::Common;
+
+#define POLICY_KERNEL_ONECORE_DEVICE_FAMILY_ID L"Kernel-OneCore-DeviceFamilyID"
+
+class CAPOThreadingFrameworkTest
+{
+ CAPOThreadingFrameworkTest(){};
+ ~CAPOThreadingFrameworkTest(){};
+
+ BEGIN_TEST_CLASS(CAPOThreadingFrameworkTest)
+ START_APPVERIFIFER
+ TEST_CLASS_PROPERTY(L"Owner", L"auddev")
+ TEST_CLASS_PROPERTY(L"TestClassification", L"Feature")
+ TEST_CLASS_PROPERTY(L"BinaryUnderTest", L"audiodg.exe")
+ TEST_CLASS_PROPERTY(L"ArtifactUnderTest", L"audioenginebaseapop.h")
+ TEST_CLASS_PROPERTY(L"RunAs", L"Elevated")
+ TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA")
+ TEST_CLASS_PROPERTY(L"Ignore", L"false")
+ TEST_CLASS_PROPERTY(L"EtwLogger:WPRProfileFile", L"Audio-Tests.wprp")
+ TEST_CLASS_PROPERTY(L"EtwLogger:WPRProfile", L"MultimediaCategory.Verbose.File")
+ END_APPVERIFIER
+ END_TEST_CLASS()
+
+public:
+ TEST_METHOD_SETUP(setUpMethod);
+ TEST_METHOD_CLEANUP(tearDownMethod);
+
+protected:
+ BEGIN_TEST_METHOD(ThreadingFrameworkTest)
+ COMMON_ONECORE_TEST_PROPERTIES
+ TEST_METHOD_PROPERTY(L"Kits.TestId", L"392B0972-F7EA-42A7-BA24-6304C3C621DB")
+ TEST_METHOD_PROPERTY(L"Kits.TestId2", L"5A5448AF-9D13-44B2-BC0C-D352A9B37268")
+ TEST_METHOD_PROPERTY(L"Kits.TestName", L"Audio APO CAPX - Test the Threading Framework - ThreadingFrameworkTest")
+ TEST_METHOD_PROPERTY(L"Kits.ExpectedRuntime", L"30")
+ TEST_METHOD_PROPERTY(L"Kits.TimeoutInMinutes", L"60")
+ TEST_METHOD_PROPERTY(L"Kits.Description", L"Third Party CAPX APO Test: ThreadingFrameworkTest")
+ APO_TEST_PROPERTIES
+ END_TEST_METHOD()
+
+private:
+ DWORD m_dwPlatform = DEVICEFAMILYINFOENUM_UAP;
+ std::vector<wil::com_ptr<IMMDevice>> m_capxEndpoints;
+};
diff --git a/audio/tests/HLK/ThirdPartyApoTests/FormatHelpers.h b/audio/tests/HLK/ThirdPartyApoTests/FormatHelpers.h
new file mode 100644
index 00000000..781b9ffb
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/FormatHelpers.h
@@ -0,0 +1,330 @@
+//
+// FormatHelpers.h -- Copyright (c) Microsoft Corporation
+//
+// Author: zaneh
+//
+// Description:
+//
+// Format Helpers for test formats used in APODeviceTest
+//
+#pragma once
+
+#include <MMDeviceAPIp.h>
+#include <DeviceTopologyp.h>
+#include <mfapi.h>
+#include <AVEndpointKeys.h>
+#include <AudioCoreAPO32Params.h>
+#include <ksmedia.h>
+
+// Consts used for APO format creation
+static const int cFrameRate = 48000; // 48kHz
+static const int cProcessingPeriod = 10; // milliseconds
+static const int cMaxFrameCount = cFrameRate * cProcessingPeriod / 1000;
+static const int cFrameCountToProcess = cMaxFrameCount / 2;
+
+// Returns true if the two IAudioMediaType formats are equal.
+// False otherwise
+bool IsEqualFormat
+(
+ IAudioMediaType *pIAMTFormat1,
+ IAudioMediaType *pIAMTFormat2
+)
+{
+ UINT cbBuffer1, cbBuffer2;
+ WAVEFORMATEX const *pwfx1, *pwfx2;
+ UNCOMPRESSEDAUDIOFORMAT format1, format2;
+
+ pwfx1 = pIAMTFormat1->GetAudioFormat();
+ pwfx2 = pIAMTFormat2->GetAudioFormat();
+ cbBuffer1 = ((WAVE_FORMAT_PCM == pwfx1->wFormatTag)?sizeof(PCMWAVEFORMAT):(sizeof(WAVEFORMATEX) + pwfx1->cbSize));
+ cbBuffer2 = ((WAVE_FORMAT_PCM == pwfx2->wFormatTag)?sizeof(PCMWAVEFORMAT):(sizeof(WAVEFORMATEX) + pwfx2->cbSize));
+
+ if (cbBuffer1 != cbBuffer2)
+ {
+ return false;
+ }
+
+ // Two formats don't compare as WAVEFORMATEX...
+ if (0 != memcmp(pwfx1, pwfx2, cbBuffer1))
+ {
+ return false;
+ }
+
+ SecureZeroMemory(&format1, sizeof(format1));
+ SecureZeroMemory(&format2, sizeof(format2));
+
+ if (S_OK != pIAMTFormat1->GetUncompressedAudioFormat(&format1))
+ {
+ return false;
+ }
+
+ if (S_OK != pIAMTFormat2->GetUncompressedAudioFormat(&format2))
+ {
+ return false;
+ }
+
+ // Two formats don't compare as WAVEFORMATEX...
+ if (0 != memcmp(&format1, &format2, sizeof(UNCOMPRESSEDAUDIOFORMAT)))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Creates a KSData format from the given WaveFormatEx
+// Returns a struct containing both the KSData format and WaveFormatEx
+KSDATAFORMAT_WAVEFORMATEX *CreateKSDataFromWFX
+(
+ WAVEFORMATEX *pwfx
+)
+{
+ if (nullptr == pwfx)
+ {
+ return nullptr;
+ }
+
+ UINT cbAlloc;
+ cbAlloc = sizeof(KSDATAFORMAT_WAVEFORMATEX) + pwfx->cbSize;
+
+ wil::unique_cotaskmem_ptr<KSDATAFORMAT_WAVEFORMATEX> pKsFormat((KSDATAFORMAT_WAVEFORMATEX*)(CoTaskMemAlloc(cbAlloc)));
+
+ if (nullptr == pKsFormat)
+ {
+ return nullptr;
+ }
+
+ pKsFormat->DataFormat.FormatSize = cbAlloc;
+ pKsFormat->DataFormat.Flags = 0;
+ pKsFormat->DataFormat.Reserved = 0;
+ pKsFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
+ pKsFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
+
+ CopyMemory(&(pKsFormat->WaveFormatEx), pwfx, sizeof(WAVEFORMATEX) + pwfx->cbSize);
+
+ if (WAVE_FORMAT_EXTENSIBLE == pwfx->wFormatTag)
+ {
+ pKsFormat->DataFormat.SubFormat = ((WAVEFORMATEXTENSIBLE*)(pwfx))->SubFormat;
+ }
+ else
+ {
+ INIT_WAVEFORMATEX_GUID(&(pKsFormat->DataFormat.SubFormat), pwfx->wFormatTag);
+ }
+
+ return (pKsFormat.release());
+}
+
+// Creates an IAudioMediaType given an uncompressed audio format
+HRESULT AECreateAudioMediaTypeFromUncompressedAudioFormat(const UNCOMPRESSEDAUDIOFORMAT* pUncompressedAudioFormat,IAudioMediaType** ppIAudioMediaType)
+{
+ RETURN_IF_FAILED(CTestAudioMediaType::Create(pUncompressedAudioFormat, ppIAudioMediaType));
+
+ return S_OK;
+}
+
+// Creates an IAudioMediaType given a WaveFormatEx
+HRESULT AECreateAudioMediaType(const WAVEFORMATEX* pWfx, IAudioMediaType** ppIAudioMediaType)
+{
+ UNCOMPRESSEDAUDIOFORMAT audioFormat;
+
+ audioFormat.dwBytesPerSampleContainer = pWfx->nBlockAlign / pWfx->nChannels;
+ audioFormat.dwSamplesPerFrame = pWfx->nChannels;
+ if (WAVE_FORMAT_EXTENSIBLE == pWfx->wFormatTag)
+ {
+ audioFormat.dwValidBitsPerSample = ((WAVEFORMATEXTENSIBLE*)pWfx)->Samples.wValidBitsPerSample;
+ audioFormat.fFramesPerSecond = (float)(((WAVEFORMATEXTENSIBLE*)pWfx)->Format.nSamplesPerSec);
+ audioFormat.guidFormatType = ((WAVEFORMATEXTENSIBLE*)pWfx)->SubFormat;
+ }
+ else
+ {
+ audioFormat.dwValidBitsPerSample = pWfx->wBitsPerSample;
+ audioFormat.fFramesPerSecond = (float)(pWfx->nSamplesPerSec);
+ INIT_WAVEFORMATEX_GUID(&(audioFormat.guidFormatType), pWfx->wFormatTag);
+ }
+
+ RETURN_IF_FAILED(CTestAudioMediaType::Create(&audioFormat, ppIAudioMediaType));
+ return S_OK;
+}
+
+// Fills an APO connection using the provided uncompressed format.
+// If pBuffer is NULL, the connection will be created with an APO_CONNECTION_BUFFER_TYPE_ALLOCATED.
+// If pBuffer is not null, APO_CONNECTION_BUFFER_TYPE_EXTERNAL will be used.
+// Outptr pConnection returns an APO_CONNECTION_DESCRIPTOR
+HRESULT FillConnection
+(
+ UNCOMPRESSEDAUDIOFORMAT* Format,
+ UINT_PTR pBuffer,
+ UINT32 /* u32ExtraFrameCount */,
+ UINT32 u32MaxFrameCount,
+ APO_CONNECTION_DESCRIPTOR* pConnection
+)
+{
+ if (Format == nullptr)
+ {
+ LOG_ERROR(L"FillConnection recieved null format");
+ return E_INVALIDARG;
+ }
+ if (pConnection == nullptr)
+ {
+ LOG_ERROR(L"FillConnection recieved null APO connection descriptor");
+ return E_INVALIDARG;
+ }
+
+ IAudioMediaType *pFormat;
+
+ // Attempt to create the AudioMediaType using the standard API
+ HRESULT createFormatHr = CreateAudioMediaTypeFromUncompressedAudioFormat(
+ Format,
+ &pFormat);
+
+ if (FAILED(createFormatHr))
+ {
+ LOG_OUTPUT(L"Standard AudioMediaType creation failed. Attempting creation using TestMediaType");
+ RETURN_IF_FAILED(AECreateAudioMediaTypeFromUncompressedAudioFormat(Format, &pFormat));
+ }
+
+ // set connection type based on pBuffer
+ // this will get re(set) when the actual allocation occurs
+ if (NULL != pBuffer)
+ {
+ pConnection->Type = APO_CONNECTION_BUFFER_TYPE_EXTERNAL;
+ }
+ else
+ {
+ pConnection->Type = APO_CONNECTION_BUFFER_TYPE_ALLOCATED;
+ }
+
+ pConnection->pFormat = pFormat;
+ pConnection->pBuffer = pBuffer;
+ pConnection->u32MaxFrameCount = u32MaxFrameCount;
+ pConnection->u32Signature = APO_CONNECTION_DESCRIPTOR_SIGNATURE;
+
+ return createFormatHr;
+}
+
+// Creates a WaveFormatEx format
+void FillFormat
+(
+ WORD FormatType,
+ DWORD dwSamplesPerFrame,
+ DWORD /* dwBytesPerSampleContainer */,
+ DWORD dwValidBitsPerSample,
+ FLOAT32 fFramesPerSecond,
+ WAVEFORMATEX* pWfx
+)
+{
+ if (pWfx == nullptr)
+ {
+ LOG_ERROR(L"WaveformatEx is null");
+ }
+
+ if (dwSamplesPerFrame >= 0xffff)
+ {
+ LOG_ERROR(L"SamplesPerFrame too great");
+ }
+
+ if (dwValidBitsPerSample >= 0xffff)
+ {
+ LOG_ERROR(L"ValidBitsPerSample too great");
+ }
+
+ pWfx->wFormatTag = FormatType;
+ pWfx->nChannels = (WORD)(dwSamplesPerFrame & 0xffff);
+ pWfx->wBitsPerSample = (WORD)dwValidBitsPerSample;
+ pWfx->nBlockAlign = pWfx->nChannels * (pWfx->wBitsPerSample / 8);
+ pWfx->nSamplesPerSec = (DWORD)fFramesPerSecond;
+ pWfx->nAvgBytesPerSec = pWfx->nSamplesPerSec * pWfx->nBlockAlign;
+ pWfx->cbSize = 0;
+}
+
+// Creates an UncompressedAudioFormat
+void FillFormat
+(
+ GUID FormatType,
+ DWORD dwSamplesPerFrame,
+ DWORD dwBytesPerSampleContainer,
+ DWORD dwValidBitsPerSample,
+ FLOAT32 fFramesPerSecond,
+ DWORD dwChannelMask,
+ UNCOMPRESSEDAUDIOFORMAT* pFormat
+)
+{
+ if (pFormat == nullptr)
+ {
+ LOG_ERROR(L"WaveformatEx is null");
+ }
+
+ if (dwSamplesPerFrame >= 0xffff)
+ {
+ LOG_ERROR(L"SamplesPerFrame too great");
+ }
+
+ if (dwValidBitsPerSample >= 0xffff)
+ {
+ LOG_ERROR(L"ValidBitsPerSample too great");
+ }
+
+ pFormat->guidFormatType = FormatType;
+ pFormat->dwSamplesPerFrame = dwSamplesPerFrame;
+ pFormat->dwBytesPerSampleContainer = dwBytesPerSampleContainer;
+ pFormat->dwValidBitsPerSample = dwValidBitsPerSample;
+ pFormat->fFramesPerSecond = fFramesPerSecond;
+ pFormat->dwChannelMask = dwChannelMask;
+}
+
+HRESULT SetupConnection
+(
+ APO_CONNECTION_DESCRIPTOR* pInputConnDesc,
+ APO_CONNECTION_DESCRIPTOR* pOutputConnDesc,
+ APO_CONNECTION_PROPERTY* pInputConnProp,
+ APO_CONNECTION_PROPERTY* pOutputConnProp,
+ UNCOMPRESSEDAUDIOFORMAT* pDefaultFormat
+)
+{
+ if (pInputConnDesc == nullptr)
+ {
+ LOG_ERROR(L"SetupConnection recieved null APO connection descriptor for input");
+ return E_INVALIDARG;
+ }
+
+ if (pOutputConnDesc == nullptr)
+ {
+ LOG_ERROR(L"SetupConnection recieved null APO connection descriptor for output");
+ return E_INVALIDARG;
+ }
+
+ if (pInputConnProp == nullptr)
+ {
+ LOG_ERROR(L"SetupConnection recieved null APO connection property for input");
+ return E_INVALIDARG;
+ }
+
+ if (pOutputConnProp == nullptr)
+ {
+ LOG_ERROR(L"SetupConnection recieved null APO connection property for output");
+ return E_INVALIDARG;
+ }
+
+ if (pDefaultFormat == nullptr)
+ {
+ LOG_ERROR(L"SetupConnection received null format");
+ return E_INVALIDARG;
+ }
+
+ LOG_RETURN_IF_FAILED(FillConnection(pDefaultFormat, NULL, 0, cMaxFrameCount, pInputConnDesc),
+ L"\tFillConnection for input descriptor failed");
+
+ LOG_RETURN_IF_FAILED(CreateConnection(pInputConnDesc, pInputConnProp),
+ L"\tCreateConnection for input descriptor failed");
+
+ pInputConnProp->u32ValidFrameCount = cFrameCountToProcess;
+ pInputConnProp->u32BufferFlags = BUFFER_VALID;
+
+ LOG_RETURN_IF_FAILED(FillConnection(pDefaultFormat, NULL, 0, cMaxFrameCount, pOutputConnDesc),
+ L"\tFillConnection for output descriptor failed");
+
+ LOG_RETURN_IF_FAILED(CreateConnection(pOutputConnDesc, pOutputConnProp),
+ L"\tCreateConnection for output descriptor failed");
+
+ return S_OK;
+} \ No newline at end of file
diff --git a/audio/tests/HLK/ThirdPartyApoTests/TestEffectsList.cpp b/audio/tests/HLK/ThirdPartyApoTests/TestEffectsList.cpp
new file mode 100644
index 00000000..7b670d28
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/TestEffectsList.cpp
@@ -0,0 +1,225 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+#include <stdafx.h>
+#include <memory>
+#include <wil\resultmacros.h>
+#include <wil\com.h>
+#include <wil\winrt.h>
+#include <wil\wrl.h>
+#include <audioclient.h>
+#include <mmdeviceapi.h>
+#include <functiondiscoverykeys.h>
+#include <windows.media.effects.h>
+#include "avdevqueryhelpers.h"
+#include <AudioStreamCategoryConversions.h>
+
+using namespace Windows::Media::Effects;
+
+class CTestEffectsList
+{
+ BEGIN_TEST_CLASS(CTestEffectsList)
+ START_APPVERIFIFER
+ TEST_CLASS_PROPERTY(L"Owner", L"auddev")
+ TEST_CLASS_PROPERTY(L"TestClassification", L"Feature")
+ TEST_CLASS_PROPERTY(L"BinaryUnderTest", L"audiodg.exe")
+ TEST_CLASS_PROPERTY(L"ArtifactUnderTest", L"audioengineextensionapo.h")
+ TEST_CLASS_PROPERTY(L"RunAs", L"Elevated")
+ TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA")
+ TEST_CLASS_PROPERTY(L"Ignore", L"false")
+ TEST_CLASS_PROPERTY(L"EtwLogger:WPRProfileFile", L"Audio-Tests.wprp")
+ TEST_CLASS_PROPERTY(L"EtwLogger:WPRProfile", L"MultimediaCategory.Verbose.File")
+ END_APPVERIFIER
+ END_TEST_CLASS()
+
+protected:
+ BEGIN_TEST_METHOD(TestGetEffectsList)
+ COMMON_ONECORE_TEST_PROPERTIES
+ TEST_METHOD_PROPERTY(L"Kits.TestId", L"7E8037CA-8670-4170-8EC8-C7B02B22A7B4")
+ TEST_METHOD_PROPERTY(L"Kits.TestId2", L"FD1ED3C6-54E0-432B-B3C9-5EAC5DE2D3E1")
+ TEST_METHOD_PROPERTY(L"Kits.TestName", L"Audio APO - Test IAudioSystemEffects2 and IAudioSystemEffects3 usage from APOs - TestEffectsList")
+ TEST_METHOD_PROPERTY(L"Kits.ExpectedRuntime", L"30")
+ TEST_METHOD_PROPERTY(L"Kits.TimeoutInMinutes", L"60")
+ TEST_METHOD_PROPERTY(L"Kits.Description", L"Third Party APO Test: TestEffectsList")
+ APO_TEST_PROPERTIES
+ END_TEST_METHOD()
+};
+
+GUID AudioEffectTypeToGUID(Windows::Media::Effects::AudioEffectType type)
+{
+ switch(type)
+ {
+ case AudioEffectType_AcousticEchoCancellation:
+ return AUDIO_EFFECT_TYPE_ACOUSTIC_ECHO_CANCELLATION;
+ case AudioEffectType_NoiseSuppression:
+ return AUDIO_EFFECT_TYPE_NOISE_SUPPRESSION;
+ case AudioEffectType_AutomaticGainControl:
+ return AUDIO_EFFECT_TYPE_AUTOMATIC_GAIN_CONTROL;
+ case AudioEffectType_BeamForming:
+ return AUDIO_EFFECT_TYPE_BEAMFORMING;
+ case AudioEffectType_ConstantToneRemoval:
+ return AUDIO_EFFECT_TYPE_CONSTANT_TONE_REMOVAL;
+ case AudioEffectType_Equalizer:
+ return AUDIO_EFFECT_TYPE_EQUALIZER;
+ case AudioEffectType_LoudnessEqualizer:
+ return AUDIO_EFFECT_TYPE_LOUDNESS_EQUALIZER;
+ case AudioEffectType_BassBoost:
+ return AUDIO_EFFECT_TYPE_BASS_BOOST;
+ case AudioEffectType_VirtualSurround:
+ return AUDIO_EFFECT_TYPE_VIRTUAL_SURROUND;
+ case AudioEffectType_VirtualHeadphones:
+ return AUDIO_EFFECT_TYPE_VIRTUAL_HEADPHONES;
+ case AudioEffectType_SpeakerFill:
+ return AUDIO_EFFECT_TYPE_SPEAKER_FILL;
+ case AudioEffectType_RoomCorrection:
+ return AUDIO_EFFECT_TYPE_ROOM_CORRECTION;
+ case AudioEffectType_BassManagement:
+ return AUDIO_EFFECT_TYPE_BASS_MANAGEMENT;
+ case AudioEffectType_EnvironmentalEffects:
+ return AUDIO_EFFECT_TYPE_ENVIRONMENTAL_EFFECTS;
+ case AudioEffectType_SpeakerProtection:
+ return AUDIO_EFFECT_TYPE_SPEAKER_PROTECTION;
+ case AudioEffectType_SpeakerCompensation:
+ return AUDIO_EFFECT_TYPE_SPEAKER_COMPENSATION;
+ case AudioEffectType_DynamicRangeCompression:
+ return AUDIO_EFFECT_TYPE_DYNAMIC_RANGE_COMPRESSION;
+ case AudioEffectType_FarFieldBeamForming:
+ return AUDIO_EFFECT_TYPE_FAR_FIELD_BEAMFORMING;
+ case AudioEffectType_DeepNoiseSuppression:
+ return AUDIO_EFFECT_TYPE_DEEP_NOISE_SUPPRESSION;
+ }
+ return GUID_NULL;
+}
+
+void CTestEffectsList::TestGetEffectsList()
+{
+ WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
+
+ wil::com_ptr_nothrow<IMMDeviceEnumerator> spEnumerator;
+ VERIFY_SUCCEEDED(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&spEnumerator)));
+
+ EDataFlow dataFlows[] = { eRender, eCapture };
+
+ for (EDataFlow dataFlow : dataFlows)
+ {
+ wil::com_ptr_nothrow<IMMDeviceCollection> spDevices;
+ VERIFY_SUCCEEDED(spEnumerator->EnumAudioEndpoints(dataFlow, DEVICE_STATE_ACTIVE, &spDevices));
+
+ UINT cDevices = 0;
+ VERIFY_SUCCEEDED(spDevices->GetCount(&cDevices));
+
+ for (UINT i = 0; i < cDevices; i++)
+ {
+ wil::com_ptr_nothrow<IMMDevice> spEndpoint;
+ VERIFY_SUCCEEDED(spDevices->Item(i, &spEndpoint));
+
+ wil::unique_prop_variant var;
+ wil::com_ptr_nothrow<IPropertyStore> spPropertyStore;
+ VERIFY_SUCCEEDED(spEndpoint->OpenPropertyStore(STGM_READ, &spPropertyStore));
+ VERIFY_SUCCEEDED(spPropertyStore->GetValue(PKEY_Device_FriendlyName, &var));
+ VERIFY_ARE_EQUAL(VT_LPWSTR, var.vt);
+ LOG_OUTPUT(L"Testing endpoint: %s", var.pwszVal);
+
+ wil::unique_cotaskmem_string spDeviceId;
+ VERIFY_SUCCEEDED(spEndpoint->GetId(&spDeviceId));
+ wil::unique_cotaskmem_string spEndpointPnpInstanceId;
+ VERIFY_SUCCEEDED(mmdDevGetInterfaceIdFromMMDeviceId(spDeviceId.get(), &spEndpointPnpInstanceId));
+ HSTRING deviceId;
+ VERIFY_SUCCEEDED(WindowsCreateString(spEndpointPnpInstanceId.get(), (UINT32)wcslen(spEndpointPnpInstanceId.get()), &deviceId));
+
+ // Get effects list using IAudioSystemEffects2
+ wil::com_ptr_nothrow<IAudioEffectsManagerStatics> audioEffectsManagerStatics =
+ wil::GetActivationFactory<IAudioEffectsManagerStatics>(RuntimeClass_Windows_Media_Effects_AudioEffectsManager);
+
+ wil::com_ptr_nothrow<Windows::Foundation::Collections::IVectorView<AudioEffect*>> effects;
+ AUDIO_STREAM_CATEGORY audioCategory;
+
+ if (dataFlow == eRender)
+ {
+ wil::com_ptr_nothrow<IAudioRenderEffectsManager> audioRenderEffectsManager;
+ VERIFY_SUCCEEDED(audioEffectsManagerStatics->CreateAudioRenderEffectsManager(deviceId, Windows::Media::Render::AudioRenderCategory::AudioRenderCategory_Communications, &audioRenderEffectsManager));
+ VERIFY_IS_NOT_NULL(audioRenderEffectsManager);
+ VERIFY_SUCCEEDED(audioRenderEffectsManager->GetAudioRenderEffects(&effects));
+
+ VERIFY_SUCCEEDED(MediaRenderCategory_To_AUDIO_STREAM_CATEGORY(Windows::Media::Render::AudioRenderCategory::AudioRenderCategory_Communications, &audioCategory));
+ }
+ else
+ {
+ wil::com_ptr_nothrow<IAudioCaptureEffectsManager> audioCaptureEffectsManager;
+ VERIFY_SUCCEEDED(audioEffectsManagerStatics->CreateAudioCaptureEffectsManager(deviceId, Windows::Media::Capture::MediaCategory::MediaCategory_Communications, &audioCaptureEffectsManager));
+ VERIFY_IS_NOT_NULL(audioCaptureEffectsManager);
+ VERIFY_SUCCEEDED(audioCaptureEffectsManager->GetAudioCaptureEffects(&effects));
+
+ VERIFY_SUCCEEDED(MediaCaptureCategory_To_AUDIO_STREAM_CATEGORY(Windows::Media::Capture::MediaCategory::MediaCategory_Communications, &audioCategory));
+ }
+
+ UINT32 numEffects = 0;
+ effects->get_Size(&numEffects);
+
+ // Get effects lists using IAudioSystemEffects3
+ wil::com_ptr_nothrow<IAudioClient2> spAudioClient;
+ VERIFY_SUCCEEDED(spEndpoint->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, nullptr, reinterpret_cast<void**>(&spAudioClient)));
+
+ AudioClientProperties clientProperties = {};
+ clientProperties.cbSize = sizeof(AudioClientProperties);
+ clientProperties.bIsOffload = FALSE;
+ clientProperties.eCategory = audioCategory;
+ clientProperties.Options = AUDCLNT_STREAMOPTIONS_NONE;
+ VERIFY_SUCCEEDED(spAudioClient->SetClientProperties(&clientProperties));
+
+ wil::unique_cotaskmem_ptr<WAVEFORMATEX> mixFormat;
+ VERIFY_SUCCEEDED(spAudioClient->GetMixFormat(wil::out_param_ptr<WAVEFORMATEX**>(mixFormat)));
+
+ VERIFY_SUCCEEDED(spAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, 20 * 10000, 0, mixFormat.get(), nullptr));
+
+ wil::com_ptr_nothrow<IAudioEffectsManager> audioEffectsManager;
+ VERIFY_SUCCEEDED(spAudioClient->GetService(IID_PPV_ARGS(&audioEffectsManager)));
+ VERIFY_IS_NOT_NULL(audioEffectsManager);
+
+ wil::unique_cotaskmem_array_ptr<AUDIO_EFFECT> controllableEffects;
+ UINT32 numControllableEffects;
+ VERIFY_SUCCEEDED(audioEffectsManager->GetAudioEffects(&controllableEffects, &numControllableEffects));
+
+ // Verify 'effects' is a subset of 'controllableEffects'
+ VERIFY_IS_GREATER_THAN_OR_EQUAL(numControllableEffects, numEffects);
+ for (UINT32 i = 0; i < numEffects; i++)
+ {
+ bool found = false;
+ for (UINT32 j = 0; j < numControllableEffects && !found; j++)
+ {
+ AudioEffectType effectType;
+ wil::com_ptr_nothrow<IAudioEffect> spEffect;
+ effects->GetAt(i, &spEffect);
+ spEffect->get_AudioEffectType(&effectType);
+ if (IsEqualGUID(AudioEffectTypeToGUID(effectType), controllableEffects[j].id))
+ {
+ found = true;
+ }
+ }
+ VERIFY_IS_TRUE(found);
+ }
+
+ // Verify effects not present in 'effects' are disabled
+ for (UINT32 i = 0; i < numControllableEffects; i++)
+ {
+ bool found = false;
+ for (UINT32 j = 0; j < numEffects && !found; j++)
+ {
+ AudioEffectType effectType;
+ wil::com_ptr_nothrow<IAudioEffect> spEffect;
+ effects->GetAt(j, &spEffect);
+ spEffect->get_AudioEffectType(&effectType);
+ if (IsEqualGUID(controllableEffects[i].id, AudioEffectTypeToGUID(effectType)))
+ {
+ found = true;
+ }
+ }
+ if (!found)
+ {
+ VERIFY_ARE_EQUAL(controllableEffects[i].state, AUDIO_EFFECT_STATE_OFF);
+ }
+ }
+ }
+ }
+}
diff --git a/audio/tests/HLK/ThirdPartyApoTests/TestMediaType.cpp b/audio/tests/HLK/ThirdPartyApoTests/TestMediaType.cpp
new file mode 100644
index 00000000..1627b728
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/TestMediaType.cpp
@@ -0,0 +1,227 @@
+// AudioMediaType.cpp -- Copyright (c) 2003 Microsoft Corporation
+//
+//
+// Description:
+//
+// Implementation of the TestMediaType
+//
+
+#include "TestMediaType.h"
+#include <memory>
+#include <wil\resultmacros.h>
+
+//-----------------------------------------------------------------------------
+// Description:
+//
+// Creates an CTestAudioMediaType object with the given format.
+//
+// Parameters:
+//
+// pFormat - [in] Format for the new AudioMediaType.
+// ppIAudioMediaType - [out] upon success returns the pointer to the
+// new interface.
+//
+// Return values:
+//
+// S_OK Success
+// E_OUTOFMEMORY On memory failure.
+// E_INVALIDARG Null parameter
+//
+// Remarks:
+//
+HRESULT CTestAudioMediaType::Create
+(
+ const UNCOMPRESSEDAUDIOFORMAT* pFormat,
+ IAudioMediaType** ppIAudioMediaType
+)
+{
+ if (!pFormat || !ppIAudioMediaType)
+ {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hResult = S_OK;
+
+ *ppIAudioMediaType = NULL;
+
+ std::unique_ptr<CTestAudioMediaType> pObj(new(std::nothrow) CTestAudioMediaType());
+
+ pObj->m_Format = *pFormat;
+
+ // TODO: iter8 fix this to use WAVEFORMATEXTENSIBLE (commented lines)
+ // after KSCommon lib is fixed
+ if (KSDATAFORMAT_SUBTYPE_PCM == pFormat->guidFormatType)
+ {
+ pObj->m_Wfx.Format.wFormatTag = WAVE_FORMAT_PCM;
+ }
+ else
+ {
+ pObj->m_Wfx.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
+ }
+ pObj->m_Wfx.Format.nChannels = (WORD)pObj->m_Format.dwSamplesPerFrame;
+ pObj->m_Wfx.Format.nSamplesPerSec = (DWORD)pObj->m_Format.fFramesPerSecond;
+ pObj->m_Wfx.Format.nAvgBytesPerSec = (DWORD)(pObj->m_Format.dwBytesPerSampleContainer *
+ pObj->m_Format.fFramesPerSecond * pObj->m_Format.dwSamplesPerFrame);
+ pObj->m_Wfx.Format.nBlockAlign = (WORD)(pObj->m_Format.dwBytesPerSampleContainer * pObj->m_Format.dwSamplesPerFrame);
+ pObj->m_Wfx.Format.wBitsPerSample = (WORD)pObj->m_Format.dwValidBitsPerSample;
+ pObj->m_Wfx.Format.cbSize = 0;
+
+ hResult = pObj->QueryInterface(
+ __uuidof(IAudioMediaType),
+ (LPVOID *) ppIAudioMediaType );
+
+ return( hResult );
+} // Create
+
+//-----------------------------------------------------------------------------
+// Description:
+//
+// Used to addref an interface
+//
+// Results:
+//
+// New reference count
+//
+ULONG STDMETHODCALLTYPE CTestAudioMediaType::AddRef()
+{
+ return (ULONG) InterlockedIncrement( (LONG *) &m_cRef );
+} // AddRef
+
+//-----------------------------------------------------------------------------
+// Description:
+//
+// Used to release an interface
+//
+// Results:
+//
+// New reference count
+//
+ULONG STDMETHODCALLTYPE CTestAudioMediaType::Release()
+{
+ ULONG ulNewRefCount = (ULONG) InterlockedDecrement( (LONG *) &m_cRef );
+
+ //
+ // If our new refcount is zero, then we need to delete ourselves
+ //
+ if( 0 == ulNewRefCount )
+ {
+ delete this;
+ }
+
+ return( ulNewRefCount );
+} // Release
+
+//-----------------------------------------------------------------------------
+// Description:
+//
+// Used to query an interface
+//
+// Parameters:
+//
+// riid - [in] id to look for
+// ppvObject - [out] pointer to object
+//
+// Return Values:
+//
+// S_OK On success.
+// E_POINTER Invalid destination pointer
+// E_NOINTERFACE No interface of that type
+// error Other
+//
+STDMETHODIMP CTestAudioMediaType::QueryInterface(
+ REFIID riid, LPVOID *ppvObject )
+{
+ if (!ppvObject)
+ {
+ return E_POINTER;
+ }
+
+ HRESULT hResult;
+
+ hResult = S_OK;
+ *ppvObject = NULL;
+
+ if( ( riid == __uuidof(IAudioMediaType) ) ||
+ ( riid == __uuidof(IUnknown) ) )
+ {
+ *ppvObject = ( IAudioMediaType *)this;
+ }
+ else
+ {
+ hResult = E_NOINTERFACE;
+ }
+
+ if ( SUCCEEDED( hResult ) )
+ {
+ ((LPUNKNOWN) *ppvObject)->AddRef( );
+ }
+
+ return( hResult );
+} // QueryInterface
+
+//-----------------------------------------------------------------------------
+// Description:
+//
+// Not implemented
+//
+// Parameters:
+//
+// pAudioMediaType - [in] media type
+// pdwFlags - [out] flags
+//
+// Return Values:
+//
+// E_NOTIMPL Not implemented.
+//
+HRESULT STDMETHODCALLTYPE CTestAudioMediaType::IsEqual(
+ IAudioMediaType * /* pAudioMediaType */,
+ DWORD * /* pdwFlags */
+)
+{
+ return E_NOTIMPL;
+} // IsEqual
+
+//-----------------------------------------------------------------------------
+// Description:
+//
+// Returns pointer to internal member variable m_Wfx.
+//
+// Results:
+//
+// Returns pointer to WaveFormatEx representing the format.
+//
+const WAVEFORMATEX *STDMETHODCALLTYPE CTestAudioMediaType::GetAudioFormat( void)
+{
+ return reinterpret_cast<WAVEFORMATEX*>(&m_Wfx);
+} // GetAudioFormat
+
+//-----------------------------------------------------------------------------
+// Description:
+//
+// Copies the uncompressed data to the parameter.
+//
+// Parameters:
+//
+// pUncompressedAudioFormat - [in] format pointer
+//
+// Return Values:
+//
+// S_OK On success
+// E_POINTER Invalid pointer
+//
+HRESULT STDMETHODCALLTYPE CTestAudioMediaType::GetUncompressedAudioFormat(
+ UNCOMPRESSEDAUDIOFORMAT *pUncompressedAudioFormat
+)
+{
+ RETURN_HR_IF(E_FAIL, (KSDATAFORMAT_SUBTYPE_PCM != m_Format.guidFormatType) &&
+ (KSDATAFORMAT_SUBTYPE_IEEE_FLOAT != m_Format.guidFormatType));
+
+ if (!pUncompressedAudioFormat)
+ {
+ return E_POINTER;
+ }
+
+ CopyMemory(pUncompressedAudioFormat, &m_Format, sizeof(UNCOMPRESSEDAUDIOFORMAT));
+
+ return S_OK;
+} // GetUncompressedAudioFormat
diff --git a/audio/tests/HLK/ThirdPartyApoTests/TestMediaType.h b/audio/tests/HLK/ThirdPartyApoTests/TestMediaType.h
new file mode 100644
index 00000000..e213a746
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/TestMediaType.h
@@ -0,0 +1,163 @@
+// Copyright (c) Microsoft Corporation
+//
+// Author: Alper Selcuk
+//
+// Description:
+//
+// Declaration of the AudioMediaType
+// The original code is copied from MF tree.
+//
+// Note that this implementation is only useful for some unit tests that need
+// to pass bogus media types.
+//
+#pragma once
+
+#include <AudioMediaType.h>
+
+//-----------------------------------------------------------------------------
+// Description:
+//
+// Implements a stripped down version of IAudioMediaType.
+
+// Remarks:
+//
+// Most methods are not implemented, because they are not needed by the
+// processor.
+//
+// NOTE: [alper] If this is passed to third party APO's then we may be forced
+// to implement all the methods.
+//
+class CTestAudioMediaType : public IAudioMediaType
+{
+public:
+
+ //--------------------------------------------------------------------------
+ // Description:
+ //
+ // Used during creation
+ //
+ // Parameters:
+ //
+ // pFormat - [in] the format
+ // ppIAudioMediaType - [out] Pointer to the created IAudioMediaType.
+ //
+ // Return Values:
+ //
+ // S_OK On success
+ // error Otherwise
+ //
+ static HRESULT Create( const UNCOMPRESSEDAUDIOFORMAT* pFormat,
+ IAudioMediaType** ppIAudioMediaType);
+
+ // IUnknown methods
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+ STDMETHOD( QueryInterface )( REFIID riid, LPVOID *ppvObject );
+
+ //--------------------------------------------------------------------------
+ // Description:
+ //
+ // Get Major Type
+ //
+ // Parameters:
+ //
+ // pguidMajorType - [out] pointer
+ //
+ // Return Values:
+ //
+ // E_NOTIMPL Not supported
+ //
+ virtual HRESULT STDMETHODCALLTYPE GetMajorType(GUID * /* pguidMajorType */)
+ {
+ return E_NOTIMPL;
+ }
+
+ //--------------------------------------------------------------------------
+ // Description:
+ //
+ // Checks to see if the format is compressed.
+ //
+ // Parameters:
+ //
+ // pfCompressed - [out] On S_OK, this is set TRUE.
+ //
+ // Return Values:
+ //
+ // S_OK On success
+ // E_POINTER Bad pointer
+ //
+ virtual HRESULT STDMETHODCALLTYPE IsCompressedFormat(
+ /* [out] */ BOOL* pfCompressed
+ )
+ {
+ if (NULL == pfCompressed)
+ {
+ return( E_POINTER );
+ }
+
+ *pfCompressed = TRUE;
+
+ return( S_OK );
+ }
+
+ //--------------------------------------------------------------------------
+ // Description:
+ //
+ // Checks to see if the media types are equal.
+ //
+ // Parameters:
+ //
+ // pAudioMediaType - [in] Media type.
+ // pdwFlags - [out] flags
+ //
+ // Return Values:
+ //
+ // S_OK On success
+ // error Otherwise
+ //
+ virtual HRESULT STDMETHODCALLTYPE IsEqual( IAudioMediaType *pAudioMediaType,DWORD *pdwFlags);
+
+ //--------------------------------------------------------------------------
+ // Description:
+ //
+ // Gets the Audio Format.
+ //
+ // Results:
+ //
+ // Returns a WAVEFORMATEX pointer.
+ //
+ virtual const WAVEFORMATEX *STDMETHODCALLTYPE GetAudioFormat( void);
+
+ //--------------------------------------------------------------------------
+ // Description:
+ //
+ // Gets the Uncompressed Audio Format.
+ //
+ // Parameters:
+ //
+ // pUncompressedAudioFormat - [out] gets the format.
+ //
+ // Return Values:
+ //
+ // S_OK On success
+ // error Otherwise
+ //
+ virtual HRESULT STDMETHODCALLTYPE GetUncompressedAudioFormat(
+ UNCOMPRESSEDAUDIOFORMAT* pUncompressedAudioFormat );
+
+protected:
+ CTestAudioMediaType();
+
+protected:
+ LONG m_cRef;
+ UNCOMPRESSEDAUDIOFORMAT m_Format;
+ WAVEFORMATEXTENSIBLE m_Wfx;
+};
+
+//-----------------------------------------------------------------------------
+// Called on creation
+inline CTestAudioMediaType::CTestAudioMediaType()
+{
+ m_cRef = 0;
+} // CTestAudioMediaType
+
diff --git a/audio/tests/HLK/ThirdPartyApoTests/TestWasapiUseFromAudioDg.cpp b/audio/tests/HLK/ThirdPartyApoTests/TestWasapiUseFromAudioDg.cpp
new file mode 100644
index 00000000..3b573f87
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/TestWasapiUseFromAudioDg.cpp
@@ -0,0 +1,244 @@
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+#include <stdafx.h>
+#include <memory>
+#include <wil\resultmacros.h>
+#include <wil\com.h>
+#include <audioclient.h>
+#include <audioclientp.h>
+#include <audiosessiontypesp.h>
+#include <mmdeviceapi.h>
+#include "etwlistener.h"
+#include <functiondiscoverykeys.h>
+
+class CTestWasapiUsageFromAudioDg
+{
+ BEGIN_TEST_CLASS(CTestWasapiUsageFromAudioDg)
+ START_APPVERIFIFER
+ TEST_CLASS_PROPERTY(L"Owner", L"auddev")
+ TEST_CLASS_PROPERTY(L"TestClassification", L"Feature")
+ TEST_CLASS_PROPERTY(L"BinaryUnderTest", L"audiodg.exe")
+ TEST_CLASS_PROPERTY(L"ArtifactUnderTest", L"audioenginebaseapop.h")
+ TEST_CLASS_PROPERTY(L"RunAs", L"Elevated")
+ TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA")
+ TEST_CLASS_PROPERTY(L"Ignore", L"false")
+ TEST_CLASS_PROPERTY(L"EtwLogger:WPRProfileFile", L"Audio-Tests.wprp")
+ TEST_CLASS_PROPERTY(L"EtwLogger:WPRProfile", L"MultimediaCategory.Verbose.File")
+ END_APPVERIFIER
+ END_TEST_CLASS()
+
+protected:
+ BEGIN_TEST_METHOD(TestStreamCreation)
+ COMMON_ONECORE_TEST_PROPERTIES
+ TEST_METHOD_PROPERTY(L"Kits.TestId", L"50B80D35-5E61-4D91-B201-5F89D67E4A5A")
+ TEST_METHOD_PROPERTY(L"Kits.TestId2", L"216ADA42-25DC-4504-9032-16D63704FB08")
+ TEST_METHOD_PROPERTY(L"Kits.TestName", L"Audio APO - Test WASAPI usage from APOs - TestStreamCreation")
+ TEST_METHOD_PROPERTY(L"Kits.ExpectedRuntime", L"30")
+ TEST_METHOD_PROPERTY(L"Kits.TimeoutInMinutes", L"60")
+ TEST_METHOD_PROPERTY(L"Kits.Description", L"Third Party APO Test: Test WASAPI usage")
+ APO_TEST_PROPERTIES
+ END_TEST_METHOD()
+};
+
+using malloca_deleter = wil::function_deleter<decltype(&::_freea), ::_freea>;
+template <typename T>
+using unique_malloca_ptr = wistd::unique_ptr<T, malloca_deleter>;
+
+class CEventParser : public IEtwEventHandler
+{
+public:
+ int GetCountOfAudioClientInits() { return m_countOfAudioClientInits; }
+ int GetCountOfAudioClientInitsFromAudioDg() { return m_countOfAudioClientInitsFromAudioDg; }
+
+private:
+
+ int m_countOfAudioClientInits = 0;
+ int m_countOfAudioClientInitsFromAudioDg = 0;
+
+ std::wstring QueryProcessName(const DWORD pid)
+ {
+ wil::unique_handle hProcess(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid));
+ if(NULL == hProcess)
+ {
+ return L"err " + std::to_wstring(GetLastError());
+ }
+ else
+ {
+ WCHAR szProcessName[1024];
+ DWORD cchSize = ARRAYSIZE(szProcessName);
+ if (0 == QueryFullProcessImageNameW(hProcess.get(), 0, szProcessName, &cchSize))
+ {
+ return L"err " + std::to_wstring(GetLastError());
+ }
+
+ PWSTR fileName = szProcessName + cchSize;
+ while (fileName != szProcessName && *fileName != L'\\') fileName--;
+
+ return (*fileName == L'\\') ? fileName + 1 : fileName;
+ }
+ }
+
+ void OnEvent(PEVENT_RECORD pEventRecord)
+ {
+ WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
+ [&]() {
+ ULONG bufferSize = 0;
+ if (TdhGetEventInformation(pEventRecord, 0, nullptr, nullptr, &bufferSize) == ERROR_INSUFFICIENT_BUFFER)
+ {
+ unique_malloca_ptr<TRACE_EVENT_INFO> eventInfo(reinterpret_cast<PTRACE_EVENT_INFO>(_malloca(bufferSize)));
+ VERIFY_IS_NOT_NULL(eventInfo);
+ RETURN_IF_WIN32_ERROR(TdhGetEventInformation(pEventRecord, 0, nullptr, eventInfo.get(), &bufferSize));
+
+ // LOG_OUTPUT(L"Received event: %s", reinterpret_cast<PWSTR>(reinterpret_cast<BYTE*>(eventInfo.get()) + eventInfo->EventNameOffset));
+ if (_wcsicmp(L"AudioClientInitialize", reinterpret_cast<PWSTR>(reinterpret_cast<BYTE*>(eventInfo.get()) + eventInfo->EventNameOffset)) == 0)
+ {
+ m_countOfAudioClientInits++;
+
+ try
+ {
+ // LOG_OUTPUT(L"Process name: %s", QueryProcessName(pEventRecord->EventHeader.ProcessId).c_str());
+ if (0 == _wcsicmp(QueryProcessName(pEventRecord->EventHeader.ProcessId).c_str(), L"audiodg.exe"))
+ {
+ m_countOfAudioClientInitsFromAudioDg++;
+ }
+ }
+ CATCH_LOG()
+ }
+ }
+ return S_OK;
+ }();
+ }
+};
+
+// {6e7b1892-5288-5fe5-8f34-e3b0dc671fd2}
+static const GUID AudioSesTelemetryProvider =
+{ 0x6e7b1892, 0x5288, 0x5fe5, 0x8f, 0x34, 0xe3, 0xb0, 0xdc, 0x67, 0x1f, 0xd2 };
+
+void CTestWasapiUsageFromAudioDg::TestStreamCreation()
+{
+ WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
+
+ CEtwListener listener;
+ CEventParser parser;
+
+ VERIFY_SUCCEEDED(listener.StartTraceSession(L"TestWasapiUsageFromAudioDg", static_cast<IEtwEventHandler *>(&parser)));
+
+ // Enable Microsoft.Windows.Audio.Client
+ VERIFY_SUCCEEDED(listener.EnableProvider(AudioSesTelemetryProvider, TRACE_LEVEL_INFORMATION, 8));
+
+ wil::com_ptr_nothrow<IMMDeviceEnumerator> spEnumerator;
+ VERIFY_SUCCEEDED(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&spEnumerator)));
+
+ // Test Render endpoints - all stream categories are valid except FarFieldSpeech, UniformSpeech, and VoiceTyping
+ {
+ wil::com_ptr_nothrow<IMMDeviceCollection> spDevices;
+ VERIFY_SUCCEEDED(spEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &spDevices));
+
+ UINT cDevices = 0;
+ VERIFY_SUCCEEDED(spDevices->GetCount(&cDevices));
+
+ for (UINT i = 0; i < cDevices; i++)
+ {
+ wil::com_ptr_nothrow<IMMDevice> pEndpoint;
+ VERIFY_SUCCEEDED(spDevices->Item(i, &pEndpoint));
+
+ wil::unique_prop_variant var;
+ wil::com_ptr_nothrow<IPropertyStore> spPropertyStore;
+ VERIFY_SUCCEEDED(pEndpoint->OpenPropertyStore(STGM_READ, &spPropertyStore));
+ VERIFY_SUCCEEDED(spPropertyStore->GetValue(PKEY_Device_FriendlyName, &var));
+ VERIFY_ARE_EQUAL(VT_LPWSTR, var.vt);
+ LOG_OUTPUT(L"Testing endpoint: %s", var.pwszVal);
+
+ for (int category = ExtendedAudioCategory_Other; category < ExtendedAudioCategory_enum_count; category++)
+ {
+ if (!(category == ExtendedAudioCategory_FarFieldSpeech ||
+ category == ExtendedAudioCategory_UniformSpeech ||
+ category == ExtendedAudioCategory_VoiceTyping))
+ {
+ wil::com_ptr_nothrow<IAudioClient2> ac;
+ VERIFY_SUCCEEDED(pEndpoint->Activate(__uuidof(IAudioClient2), CLSCTX_ALL, NULL, (void **)&ac));
+
+ AudioClientPropertiesPrivate acpp = {0};
+ acpp.ClientProps.cbSize = sizeof(acpp);
+ acpp.extCategory = (AUDIO_STREAM_EXTENDED_CATEGORY)category;
+
+ VERIFY_SUCCEEDED(ac->SetClientProperties(&acpp.ClientProps));
+
+ wil::unique_cotaskmem_ptr<WAVEFORMATEX> mixFormat;
+ VERIFY_SUCCEEDED(ac->GetMixFormat(wil::out_param(mixFormat)));
+
+ LOG_OUTPUT(L"Testing category: %d", acpp.extCategory);
+ VERIFY_SUCCEEDED(ac->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 0, 0, mixFormat.get(), nullptr));
+
+ Sleep(1000);
+ }
+ }
+ }
+ }
+
+ // Test Capture endpoints - only some stream categories are valid
+ {
+ constexpr AUDIO_STREAM_EXTENDED_CATEGORY captureCategories[] = {ExtendedAudioCategory_Other,
+ ExtendedAudioCategory_Communications,
+ ExtendedAudioCategory_Media,
+ ExtendedAudioCategory_GameChat,
+ ExtendedAudioCategory_Speech,
+ ExtendedAudioCategory_PersonalAssistant,
+ ExtendedAudioCategory_FarFieldSpeech,
+ ExtendedAudioCategory_UniformSpeech,
+ ExtendedAudioCategory_VoiceTyping,
+ };
+
+ wil::com_ptr_nothrow<IMMDeviceCollection> spDevices;
+ VERIFY_SUCCEEDED(spEnumerator->EnumAudioEndpoints(eCapture, DEVICE_STATE_ACTIVE, &spDevices));
+
+ UINT cDevices = 0;
+ VERIFY_SUCCEEDED(spDevices->GetCount(&cDevices));
+
+ for (UINT i = 0; i < cDevices; i++)
+ {
+ wil::com_ptr_nothrow<IMMDevice> pEndpoint;
+ VERIFY_SUCCEEDED(spDevices->Item(i, &pEndpoint));
+
+ wil::unique_prop_variant var;
+ wil::com_ptr_nothrow<IPropertyStore> spPropertyStore;
+ VERIFY_SUCCEEDED(pEndpoint->OpenPropertyStore(STGM_READ, &spPropertyStore));
+ VERIFY_SUCCEEDED(spPropertyStore->GetValue(PKEY_Device_FriendlyName, &var));
+ VERIFY_ARE_EQUAL(VT_LPWSTR, var.vt);
+ LOG_OUTPUT(L"Testing endpoint: %s", var.pwszVal);
+
+ for (int idx = 0; idx < ARRAYSIZE(captureCategories); idx++)
+ {
+ wil::com_ptr_nothrow<IAudioClient2> ac;
+ VERIFY_SUCCEEDED(pEndpoint->Activate(__uuidof(IAudioClient2), CLSCTX_ALL, NULL, (void**)&ac));
+
+ AudioClientPropertiesPrivate acpp = { 0 };
+ acpp.ClientProps.cbSize = sizeof(acpp);
+ acpp.extCategory = captureCategories[idx];
+
+ VERIFY_SUCCEEDED(ac->SetClientProperties(&acpp.ClientProps));
+
+ wil::unique_cotaskmem_ptr<WAVEFORMATEX> mixFormat;
+ VERIFY_SUCCEEDED(ac->GetMixFormat(wil::out_param(mixFormat)));
+
+ LOG_OUTPUT(L"Testing category: %d", acpp.extCategory);
+ VERIFY_SUCCEEDED(ac->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 0, 0, mixFormat.get(), nullptr));
+
+ Sleep(1000);
+ }
+ }
+ }
+
+ // Sleep a while to ensure we receive all the events from the above streams
+ Sleep(5000);
+
+ LOG_OUTPUT(L"Number of audio streams created: %d", parser.GetCountOfAudioClientInits());
+ LOG_OUTPUT(L"Number of audio streams created from AudioDg: %d", parser.GetCountOfAudioClientInitsFromAudioDg());
+ VERIFY_ARE_EQUAL(0, parser.GetCountOfAudioClientInitsFromAudioDg());
+
+ // Stop the trace
+ listener.StopTraceSession();
+
+}
diff --git a/audio/tests/HLK/ThirdPartyApoTests/Wrappers.h b/audio/tests/HLK/ThirdPartyApoTests/Wrappers.h
new file mode 100644
index 00000000..82ceedc0
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/Wrappers.h
@@ -0,0 +1,121 @@
+//
+// Wrappers.h -- Copyright (c) Microsoft Corporation
+//
+// Author: zaneh
+//
+// Description:
+//
+// Wrapper methods for APIs which can throw
+//
+
+// Collects exception data and sends it to Watson without crashing Audio DG.
+// This method can only be called from inside the __except condition statement
+// as a filter function.
+inline DWORD CollectExceptionDataAndContinue(LPEXCEPTION_POINTERS exceptionInfo)
+{
+ LONG lResult;
+ DWORD dwType, dwVal, dwSize=sizeof(DWORD);
+
+ // Check to see if we should allow the process create a crash dump
+ lResult = RegGetValue(HKEY_LOCAL_MACHINE, REGKEY_AUDIO_SOFTWARE, PREVENT_APOTEST_CRASH_OR_REPORT_ON_APO_EXCEPTION, RRF_RT_DWORD, &dwType, &dwVal, &dwSize);
+
+ // If we are allowing dumps, report an exception to Watson before continuing
+ if ((lResult != ERROR_SUCCESS) || (dwVal == 0))
+ {
+ RtlReportException(exceptionInfo->ExceptionRecord, exceptionInfo->ContextRecord, RTL_WER_NO_DEBUG | RTL_WER_NON_FATAL);
+ }
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+HRESULT QIInternal(IAudioProcessingObject* pIAPO, _In_ REFIID riid, _COM_Outptr_ void** ppvObject)
+{
+ __try
+ {
+ return pIAPO->QueryInterface(riid, ppvObject);
+ }
+ __except (CollectExceptionDataAndContinue(GetExceptionInformation()))
+ {
+ return __HRESULT_FROM_WIN32(GetExceptionCode());
+ }
+}
+
+HRESULT UnknownQIInternal(IUnknown* pIAPO, _In_ REFIID riid, _COM_Outptr_ void** ppvObject)
+{
+ __try
+ {
+ return pIAPO->QueryInterface(riid, ppvObject);
+ }
+ __except (CollectExceptionDataAndContinue(GetExceptionInformation()))
+ {
+ return __HRESULT_FROM_WIN32(GetExceptionCode());
+ }
+}
+
+HRESULT IsOutputFormatSupported(IAudioProcessingObject* pIAPO, IAudioMediaType* pInputFormat, IAudioMediaType* pRequestedOutputFormat, IAudioMediaType** ppSupportedOutputFormat)
+{
+ __try
+ {
+ return pIAPO->IsOutputFormatSupported(pInputFormat, pRequestedOutputFormat, ppSupportedOutputFormat);
+ }
+ __except (CollectExceptionDataAndContinue(GetExceptionInformation()))
+ {
+ return __HRESULT_FROM_WIN32(GetExceptionCode());
+ }
+}
+
+HRESULT LockForProcess(IAudioProcessingObjectConfiguration* pIAPOConfig,
+ _In_ UINT32 u32NumInputConnections,
+ _In_reads_(u32NumInputConnections) APO_CONNECTION_DESCRIPTOR** ppInputConnections,
+ _In_ UINT32 u32NumOutputConnections,
+ _In_reads_(u32NumOutputConnections) APO_CONNECTION_DESCRIPTOR** ppOutputConnections)
+{
+ __try
+ {
+ return pIAPOConfig->LockForProcess(u32NumInputConnections, ppInputConnections, u32NumOutputConnections, ppOutputConnections);
+ }
+ __except (CollectExceptionDataAndContinue(GetExceptionInformation()))
+ {
+ return __HRESULT_FROM_WIN32(GetExceptionCode());
+ }
+}
+
+HRESULT UnlockForProcess(IAudioProcessingObjectConfiguration* pIAPOConfig)
+{
+ __try
+ {
+ return pIAPOConfig->UnlockForProcess();
+ }
+ __except (CollectExceptionDataAndContinue(GetExceptionInformation()))
+ {
+ return __HRESULT_FROM_WIN32(GetExceptionCode());
+ }
+}
+
+void APOProcess(IAudioProcessingObjectRT* pIAPORT,
+ _In_ UINT32 u32NumInputConnections,
+ _In_reads_(u32NumInputConnections) APO_CONNECTION_PROPERTY** ppInputConnections,
+ _In_ UINT32 u32NumOutputConnections,
+ _Inout_updates_(u32NumOutputConnections) APO_CONNECTION_PROPERTY** ppOutputConnections)
+{
+ __try
+ {
+ pIAPORT->APOProcess(u32NumInputConnections, ppInputConnections, u32NumOutputConnections, ppOutputConnections);
+ }
+ __except (CollectExceptionDataAndContinue(GetExceptionInformation()))
+ {
+ return;
+ }
+}
+
+HRESULT GetRegistrationProperties(IAudioProcessingObject* pIAPO, APO_REG_PROPERTIES** ppRegProps)
+{
+ __try
+ {
+ return pIAPO->GetRegistrationProperties(ppRegProps);
+ }
+ __except (CollectExceptionDataAndContinue(GetExceptionInformation()))
+ {
+ return __HRESULT_FROM_WIN32(GetExceptionCode());
+ }
+} \ No newline at end of file
diff --git a/audio/tests/HLK/ThirdPartyApoTests/audioconnectionutil.h b/audio/tests/HLK/ThirdPartyApoTests/audioconnectionutil.h
new file mode 100644
index 00000000..771d03de
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/audioconnectionutil.h
@@ -0,0 +1,129 @@
+#pragma once
+
+#define IS_2_POW_N(X) (((X)&(X-1)) == 0)
+
+enum class aligned_size_t : size_t {};
+
+void * AllocateAligned(size_t cb, aligned_size_t AlignmentMask)
+{
+ ASSERT(0 != cb);
+ //ASSERT(IS_2_POW_N(AlignmentMask + 1));
+
+ void *res = _aligned_malloc(cb, static_cast<size_t>(AlignmentMask) + 1);
+
+ return res;
+}
+
+void DeallocateAligned(void * p, aligned_size_t /* AlignmentMask */)
+{
+ if (NULL != p)
+ {
+ _aligned_free(p);
+ }
+}
+
+UINT32 CalculateAlignmentMask(APO_CONNECTION_DESCRIPTOR * /* pDescriptor */, UINT32 u32BytesPerFrame)
+{
+ const UINT32 u32AudioAlignment = sizeof(PVOID);
+ UINT32 u32Alignment = u32AudioAlignment - 1;
+
+ // Calculate the new alignment requirement for this buffer.
+ if (u32BytesPerFrame > u32AudioAlignment)
+ {
+ // Use the frame size directly if it is a power of two.
+ if (IS_2_POW_N(u32BytesPerFrame))
+ {
+ u32Alignment = u32BytesPerFrame - 1;
+ }
+ // The new alignment size should be greater than frame
+ // size and should be a power of 2.
+ else
+ {
+ u32Alignment = u32AudioAlignment;
+ while (u32BytesPerFrame / u32Alignment)
+ {
+ u32Alignment *= 2;
+ }
+ u32Alignment = u32Alignment - 1;
+ }
+ }
+
+ // Use default alignment if the frame size is less than the default
+ // alignment.
+ return u32Alignment;
+} // CalculateAlignmentMask
+
+HRESULT
+CreateConnection(APO_CONNECTION_DESCRIPTOR* pDescriptor, APO_CONNECTION_PROPERTY* pProperty)
+{
+ RETURN_HR_IF_NULL(E_POINTER, pDescriptor);
+ RETURN_HR_IF_NULL(E_POINTER, pDescriptor->pFormat);
+ RETURN_HR_IF_NULL(E_POINTER, pProperty);
+
+ UINT32 u32BytesPerFrame;
+ unsigned byteAlignmentMask;
+ BYTE* pAllocatedBuffer;
+ UNCOMPRESSEDAUDIOFORMAT Format;
+
+ RETURN_IF_FAILED(pDescriptor->pFormat->GetUncompressedAudioFormat(&Format));
+
+ u32BytesPerFrame =
+ Format.dwSamplesPerFrame * Format.dwBytesPerSampleContainer;
+
+ // Allocate buffer internally.
+ if (NULL == pDescriptor->pBuffer)
+ {
+ byteAlignmentMask = CalculateAlignmentMask(pDescriptor, u32BytesPerFrame);
+
+ pAllocatedBuffer = (BYTE *)AllocateAligned(pDescriptor->u32MaxFrameCount * u32BytesPerFrame, static_cast<aligned_size_t>(byteAlignmentMask));
+ RETURN_HR_IF_NULL(E_OUTOFMEMORY, pAllocatedBuffer);
+
+ pDescriptor->pBuffer = reinterpret_cast<UINT_PTR>(pAllocatedBuffer);
+ pDescriptor->Type = APO_CONNECTION_BUFFER_TYPE_ALLOCATED;
+ }
+ // Use the given buffer.
+ else
+ {
+ pDescriptor->Type = APO_CONNECTION_BUFFER_TYPE_EXTERNAL;
+ }
+
+ pProperty->pBuffer = pDescriptor->pBuffer;
+ pProperty->u32ValidFrameCount = 0;
+ pProperty->u32Signature = APO_CONNECTION_PROPERTY_SIGNATURE;
+
+ return S_OK;
+} // CreateConnection
+
+HRESULT
+DestroyConnection(APO_CONNECTION_DESCRIPTOR *pDescriptor)
+{
+ HRESULT hResult;
+ UINT32 u32BytesPerFrame;
+ size_t byteAlignmentMask;
+ BYTE* pAllocatedBuffer;
+ UNCOMPRESSEDAUDIOFORMAT Format;
+
+ hResult = pDescriptor->pFormat->GetUncompressedAudioFormat(&Format);
+ //IF_FAILED_JUMP(hResult, Exit);
+
+ if (APO_CONNECTION_BUFFER_TYPE_ALLOCATED == pDescriptor->Type)
+ {
+ u32BytesPerFrame =
+ Format.dwSamplesPerFrame * Format.dwBytesPerSampleContainer;
+
+ byteAlignmentMask = CalculateAlignmentMask(pDescriptor, u32BytesPerFrame);
+
+ if (pDescriptor->pBuffer)
+ {
+ pAllocatedBuffer = reinterpret_cast<BYTE*>(pDescriptor->pBuffer);
+ RETURN_HR_IF_NULL(E_OUTOFMEMORY, pAllocatedBuffer);
+
+ DeallocateAligned((void *) pAllocatedBuffer, static_cast<aligned_size_t>(byteAlignmentMask));
+ }
+ }
+
+ pDescriptor->pFormat->Release();
+ pDescriptor->pFormat = NULL;
+
+ return hResult;
+} // DestroyConnection
diff --git a/audio/tests/HLK/ThirdPartyApoTests/sinewave.h b/audio/tests/HLK/ThirdPartyApoTests/sinewave.h
new file mode 100644
index 00000000..8f0fc03c
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/sinewave.h
@@ -0,0 +1,60 @@
+#pragma once
+
+class SineWave
+{
+ struct wave
+ {
+ float amp{}, freq{}, phase{}, dc{};
+ };
+public:
+ SineWave() {}
+
+ template<typename _ty1, typename _ty2>
+ SineWave(_ty1 numChannels, _ty2 samplingRate) : _channel(unsigned(numChannels)), _sr(float(samplingRate)) {}
+
+ template<typename _ty1, typename _ty2>
+ inline void Initialize(_ty1 numChannels, _ty2 samplingRate)
+ {
+ _channel.resize(unsigned(numChannels));
+ _sr = unsigned(samplingRate);
+ }
+
+ template<typename _ty1>
+ inline void SetChannel(_ty1 channel, float freq, float amplitude = 0.f, float dc = 0.f, float phase = 0.f)
+ {
+ _channel[unsigned(channel)].amp = amplitude;
+ _channel[unsigned(channel)].freq = freq;
+ _channel[unsigned(channel)].phase = phase;
+ _channel[unsigned(channel)].dc = dc;
+ }
+
+
+ template<typename _ty1>
+ void FillFrames(void* buffer, _ty1 numFrames)
+ {
+ auto fb = reinterpret_cast<float*>(buffer);
+ for (unsigned i = 0; i < unsigned(numFrames); ++i)
+ {
+ for (unsigned ch = 0; ch < _channel.size(); ++ch)
+ {
+ fb[i * _channel.size() + ch] = Calculate(ch);
+ }
+ }
+ }
+
+protected:
+ float Calculate(unsigned ch)
+ {
+ auto& w = _channel[ch];
+ float sample = w.amp * sinf(w.phase) + w.dc;
+
+ w.phase += 2 * float(M_PI) * w.freq / _sr;
+ w.phase = fmodf(w.phase, 2 * float(M_PI));
+
+ return sample;
+ }
+
+private:
+ std::vector<wave> _channel;
+ float _sr{};
+}; \ No newline at end of file
diff --git a/audio/tests/HLK/ThirdPartyApoTests/stdafx.h b/audio/tests/HLK/ThirdPartyApoTests/stdafx.h
new file mode 100644
index 00000000..8a836cf0
--- /dev/null
+++ b/audio/tests/HLK/ThirdPartyApoTests/stdafx.h
@@ -0,0 +1,123 @@
+//
+// stdafx.h -- Copyright (c) Microsoft Corporation
+//
+// Author: zaneh
+//
+// Description:
+//
+// Include file for well-known headers
+//
+#pragma once
+
+#define _USE_MATH_DEFINES
+#include <cmath>
+#include <vector>
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+
+#define NO_MOCK_VALIDATION
+#include <mock.h>
+#include <Windows.Media.Devices.h>
+#include <windows.h>
+#include <versionhelpers.h>
+#include <WexTestClass.h>
+
+#include "wil\resource.h"
+#include "wil\com.h"
+
+
+// System Effect Specifiers. These help determine which type of system
+// effect the device is attempting to use in order to test it properly
+#define DT_GFX 0x00000002
+#define DT_LFX 0x00000004
+#define DT_LGFX (DT_LFX | DT_GFX)
+#define DT_SFX 0x00000008
+#define DT_MFX 0x00000010
+#define DT_EFX 0x00000020
+#define DT_SMEFX (DT_SFX | DT_MFX | DT_EFX)
+
+// Reg Key definitions for disabling AudioDG crashing on an APO exception
+#define PREVENT_APOTEST_CRASH_OR_REPORT_ON_APO_EXCEPTION L"PreventAPOTestCrashOrReportOnAPOException"
+#define REGKEY_AUDIO_SOFTWARE L"Software\\Microsoft\\Windows\\CurrentVersion\\Audio"
+#define REGKEY_DEFAULT L"(default)"
+
+// Test logging macros
+#ifndef LOG_ERROR
+#define LOG_ERROR(fmt, ...) WEX::Logging::Log::Error(WEX::Common::String().Format(fmt L"\n\t\tFunction: " \
+ __FUNCTION__ L" Line: %d", __VA_ARGS__, __LINE__))
+#endif
+
+#ifndef LOG_OUTPUT
+#define LOG_OUTPUT(fmt, ...) WEX::Logging::Log::Comment(WEX::Common::String().Format(fmt, __VA_ARGS__))
+#endif
+
+#define LOG_RETURN_IF_FAILED(hr, fmt, ...) if (FAILED(hr)) { LOG_ERROR(fmt, __VA_ARGS__); \
+ WEX::Logging::Log::Error(WEX::Common::String().Format(L"\t\tError Code: (0x%08lx)" \
+ , hr)); return hr; }
+#define LOG_RETURN_VOID_IF_FAILED(hr, fmt, ...) if(FAILED(hr)) { LOG_ERROR(fmt, __VA_ARGS__); \
+ WEX::Logging::Log::Error(WEX::Common::String().Format(L"\t\tError Code: (0x%08lx)" \
+ , hr)); return; }
+#define LOG_RETURN_HR_IF(condition, hr, fmt, ...) if (condition) { LOG_ERROR(fmt, __VA_ARGS__); \
+ WEX::Logging::Log::Error(WEX::Common::String().Format(L"\t\tError Code: (0x%08lx)" \
+ , hr)); return hr; }
+// End Test logging macros
+
+// Begin Metadata defines
+#define COMMON_ONECORE_TEST_PROPERTIES \
+ COMMON_TEST_PROPERTIES \
+ TEST_METHOD_PROPERTY(L"Kits.SupportedOS", L"Windows v10.0 Client x86") \
+ TEST_METHOD_PROPERTY(L"Kits.SupportedOS", L"Windows v10.0 Client x64") \
+ TEST_METHOD_PROPERTY(L"Kits.SupportedOS", L"Windows v10.0 Client ARM") \
+ TEST_METHOD_PROPERTY(L"Kits.SupportedOS", L"Windows v10.0 Client ARM64") \
+ TEST_METHOD_PROPERTY(L"Kits.MinRelease", L"RS5") \
+ TEST_METHOD_PROPERTY(L"Kits.CorePackageComposition", L"OneCoreUAP") \
+ TEST_METHOD_PROPERTY(L"Kits.CorePackageComposition", L"OneCore") \
+ TEST_METHOD_PROPERTY(L"Kits.CorePackageComposition", L"Full") \
+
+#define COMMON_TEST_PROPERTIES \
+ TEST_METHOD_PROPERTY(L"Kits.TestType", L"Development") \
+ TEST_METHOD_PROPERTY(L"Kits.RunElevated", L"True") \
+ TEST_METHOD_PROPERTY(L"Kits.RequiresReboot", L"False") \
+ TEST_METHOD_PROPERTY(L"Kits.PublishingOrganization", L"Microsoft Corporation") \
+ TEST_METHOD_PROPERTY(L"Kits.DevelopmentPhase", L"Development and Integration") \
+ TEST_METHOD_PROPERTY(L"Kits.HasSupplementalContent", L"False") \
+
+#define APO_TEST_PROPERTIES \
+ TEST_METHOD_PROPERTY(L"Kits.Specification", L"Device.Audio.APO.ThirdParty") \
+
+#define START_APPVERIFIFER \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask", L"AppVerifierStart") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.AppVerifierStart.Stage", L"Setup") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.AppVerifierStart.RunElevated", L"True") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.AppVerifierStart.CommandLine", L"cmd.exe /c appverif -enable exceptions handles heaps leak locks memory srwlock threadpool tls -for te.processhost.exe te.exe audiodg.exe") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.AppVerifierStart.Order", L"1") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.AppVerifierStart.ExpectedExitCode", L"0") \
+
+#define END_APPVERIFIER \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask", L"AppVerifierEnd") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.AppVerifierEnd.Stage", L"Cleanup") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.AppVerifierEnd.RunElevated", L"True") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.AppVerifierEnd.CommandLine", L"cmd.exe /c appverif -disable exceptions handles heaps leak locks memory srwlock threadpool tls -for te.processhost.exe te.exe audiodg.exe") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.AppVerifierEnd.Order", L"1") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.AppVerifierEnd.ExpectedExitCode", L"0") \
+
+#define START_OSUPGRADE \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask", L"OSUpgrade") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.OSUpgrade.Stage", L"Setup") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.OSUpgrade.RunElevated", L"True") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.OSUpgrade.CommandLine", L"cmd.exe /c c:\\HLK\\ISO\\setup.exe /auto:upgrade /compat IgnoreWarning /noreboot") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.OSUpgrade.Order", L"1") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.OSUpgrade.ExpectedExitCode", L"0") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.OSUpgrade.TimeoutInMinutes", L"240") \
+
+#define START_APPVERIFIFER_UPGRADE \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask", L"AppVerifierStart") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.AppVerifierStart.Stage", L"Setup") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.AppVerifierStart.RunElevated", L"True") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.AppVerifierStart.CommandLine", L"cmd.exe /c appverif -enable exceptions handles heaps leak locks memory srwlock threadpool tls -for te.processhost.exe te.exe audiodg.exe") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.AppVerifierStart.Order", L"2") \
+ TEST_CLASS_PROPERTY(L"Kits.TestTask.AppVerifierStart.ExpectedExitCode", L"0") \
+
+// End Metadata defines
diff --git a/audio/tests/KSPosTst/KsPosTestTaef.cpp b/audio/tests/KSPosTst/KsPosTestTaef.cpp
new file mode 100644
index 00000000..b92f9e4f
--- /dev/null
+++ b/audio/tests/KSPosTst/KsPosTestTaef.cpp
@@ -0,0 +1,215 @@
+// ------------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// File Name:
+//
+// KsPosTestTaef.cpp
+//
+// Abstract:
+//
+// Implementation file for KsPosTestTaef
+//
+// -------------------------------------------------------------------------------
+#include "PreComp.h"
+#include "KsPosTestTaef.h"
+#include "tests.h"
+
+using namespace WEX::Common;
+using namespace WEX::Logging;
+using namespace WEX::TestExecution;
+
+#define RUN_TEST_CASE(testfn) \
+{ \
+ SetVerifyOutput verifySettings(VerifyOutputSettings::LogOnlyFailures); \
+ testfn(); \
+}
+
+IBasicLog * g_pBasicLog = NULL;
+WDMAudio::KsPosTest* g_pKsPosTst = NULL;
+
+TIMER_MECHANISM g_Timer =
+{
+ tpQPC, "QueryPerformanceCounter"
+};
+
+void LogWaveFormat(WAVEFORMATEX* pwfx)
+{
+ WAVEFORMATEXTENSIBLE* wfex = (WAVEFORMATEXTENSIBLE*)pwfx;
+
+ switch (pwfx->wFormatTag)
+ {
+ case WAVE_FORMAT_PCM:
+ LOG(g_pBasicLog, L" wFormatTag = WAVE_FORMAT_PCM");
+ break;
+ case WAVE_FORMAT_IEEE_FLOAT:
+ LOG(g_pBasicLog, L" wFormatTag = WAVE_FORMAT_IEEE_FLOAT");
+ break;
+ case WAVE_FORMAT_EXTENSIBLE:
+ LOG(g_pBasicLog, L" wFormatTag = WAVE_FORMAT_EXTENSIBLE");
+ if (wfex->SubFormat.Data1 == WAVE_FORMAT_PCM)
+ LOG(g_pBasicLog, L" SubFormat = WAVE_FORMAT_PCM");
+ if (wfex->SubFormat.Data1 == WAVE_FORMAT_IEEE_FLOAT)
+ LOG(g_pBasicLog, L" SubFormat = WAVE_FORMAT_IEEE_FLOAT");
+ break;
+ default:
+ LOG(g_pBasicLog, L" wFormatTag = UNKNOWN!");
+ }
+ LOG(g_pBasicLog, L" nChannel = %d", pwfx->nChannels);
+ LOG(g_pBasicLog, L" nSamplesPerSec = %d", pwfx->nSamplesPerSec);
+ LOG(g_pBasicLog, L" nAvgBytesPerSe = %d", pwfx->nAvgBytesPerSec);
+ LOG(g_pBasicLog, L" nBlockAlign = %d", pwfx->nBlockAlign);
+ LOG(g_pBasicLog, L" wBitsPerSample = %d", pwfx->wBitsPerSample);
+
+
+ if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
+ {
+ LOG(g_pBasicLog, L" wValidBitsPerSample = %d", wfex->Samples.wValidBitsPerSample);
+ LOG(g_pBasicLog, L" dwChannelMask = %hd", wfex->dwChannelMask);
+ }
+}
+
+// -------------------------------------------------------------------------------
+namespace WDMAudio
+{
+ BEGIN_MODULE()
+ MODULE_PROPERTY(L"Feature", L"PortCls HCK Tests")
+ MODULE_PROPERTY(L"TestResourceDependent", L"true")
+ END_MODULE()
+
+ // Create WEXBasicLog, Coinitialize Etc
+ MODULE_SETUP(WDMAudioSetup)
+
+ // Release stuff acquired in WDMAudioSetup
+ MODULE_CLEANUP(WDMAudioCleanup)
+};
+
+bool WDMAudio::WDMAudioSetup()
+{
+ if (NULL == g_pBasicLog)
+ {
+ if (!(VERIFY_SUCCEEDED(CreateWexBasicLog(&g_pBasicLog))))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool WDMAudio::WDMAudioCleanup()
+{
+ if (g_pBasicLog)
+ {
+ g_pBasicLog->Release();
+ }
+
+ return true;
+}
+
+// -------------------------------------------------------------------------------
+bool WDMAudio::KsPosTest::KsPosTestSetup()
+{
+ g_pKsPosTst = this;
+ m_pTimer = &g_Timer;
+ // The histograms can be displayed by using the command line parameter checked below
+ // If the parameter is not specified, the default is to not log anything
+ bool param = true;
+ WEX::TestExecution::RuntimeParameters::TryGetValue(L"logHistograms", param);
+ m_fLogHistograms = param;
+ return true;
+}
+
+bool WDMAudio::KsPosTest::KsPosTestCleanUp()
+{
+ g_pKsPosTst = NULL;
+
+ return true;
+}
+
+// -------------------------------------------------------------------------------
+bool WDMAudio::KsPosTest::TestCaseSetup()
+{
+ CComPtr<ITestResource> spResource;
+ CComQIPtr<IHalfAppContainer> spHalfContainer;
+
+ SetVerifyOutput verifySettings(VerifyOutputSettings::LogOnlyFailures);
+
+ Log::Comment(L"");
+ Log::Comment(L"------------------------------------------------------");
+ Log::Comment(L"Running test case setup");
+
+ size_t count = Resources::Count();
+ if (!VERIFY_ARE_EQUAL(count, (size_t)1)) { return false; }
+ if (!VERIFY_SUCCEEDED(Resources::Item(0, &spResource))) { return false; }
+
+ // 1. Assign m_pHalf
+ spHalfContainer = spResource;
+ if (!VERIFY_IS_NOT_NULL(spHalfContainer)) { return false; }
+ if (!VERIFY_SUCCEEDED(spHalfContainer->GetHalfApp(&m_pHalf))) { return false; }
+
+ // 2. Check if this is a loopback pin. If so, assign the host pin's HalfApp
+ if (m_pHalf->m_ConnectorType == eLoopbackConnector)
+ {
+ VERIFY_SUCCEEDED(m_pHalf->GetHostHalfApp(&m_pHostHalf));
+ }
+ else
+ {
+ m_pHostHalf = NULL;
+ }
+
+ Log::Comment(L"The test will run on the following format:");
+ if (m_pHostHalf != NULL)
+ {
+ LogWaveFormat(m_pHostHalf->m_pCurrentFormat.get());
+ }
+ else
+ {
+ LogWaveFormat(m_pHalf->m_pCurrentFormat.get());
+ }
+
+ return true;
+}
+
+bool WDMAudio::KsPosTest::TestCaseCleanUp()
+{
+ // Stop the timer here, in case any latency test fails
+ NtSetTimerResolution(0, FALSE, &actualTimerResolution);
+
+ if (!CompareWaveFormat(m_pHalf->m_pCurrentFormat.get(), m_pHalf->m_pPreferredFormat.get())) {
+ CloneWaveFormat(m_pHalf->m_pPreferredFormat.get(), wil::out_param(m_pHalf->m_pCurrentFormat));
+ m_pHalf->m_u32CurrentDefaultPeriodicityInFrames = m_pHalf->m_u32DefaultPeriodicityInFrames;
+ m_pHalf->m_u32CurrentFundamentalPeriodicityInFrames = m_pHalf->m_u32FundamentalPeriodicityInFrames;
+ m_pHalf->m_u32CurrentMinPeriodicityInFrames = m_pHalf->m_u32MinPeriodicityInFrames;
+ m_pHalf->m_u32CurrentMaxPeriodicityInFrames = m_pHalf->m_u32MaxPeriodicityInFrames;
+ }
+
+ if (m_pHostHalf != NULL) {
+ if (!VERIFY_SUCCEEDED(m_pHostHalf->CleanupStream())) { return false; }
+ if (!VERIFY_SUCCEEDED(m_pHostHalf->ReleaseEndpoint())) { return false; }
+ if (!VERIFY_SUCCEEDED(m_pHostHalf->ReleaseSineToneDataBuffer())) { return false; }
+ delete m_pHostHalf;
+ m_pHostHalf = NULL;
+ }
+
+ if (m_pHalf != NULL) {
+ if (!VERIFY_SUCCEEDED(m_pHalf->CleanupStream())) { return false; }
+ if (!VERIFY_SUCCEEDED(m_pHalf->ReleaseEndpoint())) { return false; }
+ if (!VERIFY_SUCCEEDED(m_pHalf->ReleaseSineToneDataBuffer())) { return false; }
+
+ m_pHalf = NULL;
+ }
+
+ return true;
+}
+
+// -------------------------------------------------------------------------------
+void WDMAudio::KsPosTest::TAEF_DriftAndJitter()
+{
+ RUN_TEST_CASE(Test_DriftAndJitter_Default);
+}
+
+void WDMAudio::KsPosTest::TAEF_Latency()
+{
+ RUN_TEST_CASE(Test_Latency_Default);
+}
diff --git a/audio/tests/KSPosTst/PreComp.h b/audio/tests/KSPosTst/PreComp.h
new file mode 100644
index 00000000..5fdfc9db
--- /dev/null
+++ b/audio/tests/KSPosTst/PreComp.h
@@ -0,0 +1,108 @@
+// ------------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// File Name:
+//
+// PreComp.h
+//
+// Abstract:
+//
+// Precompiled common headers
+//
+// -------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// Number of milliseconds that the test will be delayed to wait for the stream to stabilize
+#define DELAY_FOR_STABILIZE 100
+
+// Number of milliseconds in a second
+#define MILLISECONDS_PER_SECOND 1000
+
+// Number of HNS units in one second
+#define HNSTIME_UNITS_PER_SECOND 10000000
+
+// Number of HNS units in one millisecond
+#define HNSTIME_UNITS_PER_MILLISECOND 10000
+
+typedef double (*TIMEPROC) (void);
+double tpQPC(void);
+
+typedef struct _tag_tm
+{
+ TIMEPROC Proc;
+ LPCSTR strRep;
+} TIMER_MECHANISM, * PTIMER_MECHANISM;
+
+// ----------------------------------------------------------
+// Timer functions
+extern "C" __kernel_entry NTSYSCALLAPI NTSTATUS NTAPI NtSetTimerResolution(
+ _In_ ULONG DesiredTime, _In_ BOOLEAN SetResolution, _Out_ PULONG ActualTime);
+
+// 1 ms timer resolution
+static ULONG timerResolution = (1 * 10000);
+static ULONG actualTimerResolution;
+
+// ------------------------------------------------------------------------------
+// structs used to hold results of perf tests
+#define DATA_POINTS 100
+
+typedef struct
+{
+ double testTime; // Time the sample was taken, in milliseconds, relative to the start of the sample collection
+ double positionTime; // Time of the reported position, in milliseconds, relative to the start of the sample collection
+ double position; // Position, in seconds, relative to the start of the sample collection
+} POSITION_SET, * PPOSITION_SET;
+
+typedef struct
+{
+ PPOSITION_SET argPosSets;
+ ULONG cPosSets;
+ ULONG ctLatencyMeas;
+ ULONG csBufferMeas;
+ double bytesPerSecond; // measured (in bytes/sec, NOT samples/sec)
+ double dOffset; // measured
+} PERF_RESULTS, * PPERF_RESULTS;
+
+typedef struct
+{
+ WAVEFORMATEXTENSIBLE wfxFormat;
+ PERF_RESULTS perfResults; //
+} FORMAT_ENTRY, * PFORMAT_ENTRY;
diff --git a/audio/tests/KSPosTst/TestResourceBuild.cpp b/audio/tests/KSPosTst/TestResourceBuild.cpp
new file mode 100644
index 00000000..93959089
--- /dev/null
+++ b/audio/tests/KSPosTst/TestResourceBuild.cpp
@@ -0,0 +1,522 @@
+// ------------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// File Name:
+//
+// TestResourceBuild.cpp
+//
+// Abstract:
+//
+// TAEF BuildResourceList implementation
+//
+// ------------------------------------------------------------------------------
+#include "PreComp.h"
+#include <TestResource.h>
+#include <PropertyHelper.h>
+
+using namespace WEX::Common;
+using namespace WEX::Logging;
+using namespace WEX::TestExecution;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// CreateTestResource
+//
+// Create the test resource with MMDevice, device id, device name, data flow, connector type, connector id, mode,
+// list of formats
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+HRESULT CreateTestResource
+(
+ ResourceList& resourceList,
+ DeviceDescriptor descriptor
+)
+{
+ HRESULT hr = S_OK;
+
+ CComHeapPtr<CHalfApp> spHalfApp;
+ wil::com_ptr_nothrow<ITestResource> spTestResource;
+ GUID ResourceGUID;
+ CComBSTR szResourceName;
+
+ // Create HalfApp
+ spHalfApp.Attach(new CHalfApp(descriptor));
+ if (!VERIFY_IS_NOT_NULL(spHalfApp)) {
+ hr = E_OUTOFMEMORY;
+ return hr;
+ }
+
+ // Create PinTestResource
+ if (!VERIFY_SUCCEEDED(hr = CoCreateGuid(&ResourceGUID))) {
+ return hr;
+ }
+ if (!VERIFY_SUCCEEDED(hr = CPinTestResource::CreateInstance(
+ spHalfApp, ResourceGUID, &spTestResource))) {
+ return hr;
+ }
+
+ // Add to resource list
+ spHalfApp.Detach();
+ if (!VERIFY_SUCCEEDED(hr = resourceList.Add(spTestResource.get()))) {
+ return hr;
+ }
+ if (!VERIFY_SUCCEEDED(hr = spTestResource->GetValue(CComBSTR(TestResourceProperty::c_szName), &szResourceName))) {
+ return hr;
+ }
+ Log::Comment(String().Format(L"Test Resource (%s) added", (PCWSTR)szResourceName));
+
+ return hr;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// GetProcessingModesForConnector
+//
+// For host/keyword detector pin, processing mode info is cached in property store and can be directly read. For offload
+// pin, query for ks processing mode property. For loopback pin, it doesn't support any processing modes, return GUID_NULL.
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+HRESULT GetProcessingModesForConnector
+(
+ IMMDevice* pDevice,
+ UINT uConnectorId,
+ EndpointConnectorType eConnectorType,
+ ULONG *pCount,
+ AUDIO_SIGNALPROCESSINGMODE **ppModes
+)
+{
+ HRESULT hr = S_OK;
+
+ *pCount = 0;
+ *ppModes = NULL;
+
+ if (eConnectorType == eHostProcessConnector || eConnectorType == eKeywordDetectorConnector) {
+ if (!VERIFY_SUCCEEDED(hr = GetCachedProcessingModes(pDevice, eConnectorType, pCount, ppModes))) {
+ return hr;
+ }
+ }
+ else if (eConnectorType == eOffloadConnector) {
+ if (!VERIFY_SUCCEEDED(hr = GetProcessingModes(pDevice, uConnectorId, pCount, ppModes))) {
+ return hr;
+ }
+ }
+ else if (eConnectorType == eLoopbackConnector) {
+ // Loopback pin doesn't support any processing modes, so put 1 GUID_NULL
+ CComHeapPtr<AUDIO_SIGNALPROCESSINGMODE> spModes;
+
+ if (!spModes.Allocate(1))
+ return E_OUTOFMEMORY;
+
+ spModes[0] = GUID_NULL;
+
+ *pCount = 1;
+ *ppModes = spModes.Detach();
+ }
+
+ return hr;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// GetDefaultFormatForConnector
+//
+// Read audio engine device format from property store as default format.
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+HRESULT GetDefaultFormatForConnector
+(
+ IMMDevice* pDevice,
+ EndpointConnectorType eConnectorType,
+ WAVEFORMATEX **ppDefaultFormat
+)
+{
+ HRESULT hr = S_OK;
+
+ *ppDefaultFormat = NULL;
+ if (!VERIFY_SUCCEEDED(hr = GetCachedDefaultFormat(pDevice, eConnectorType, ppDefaultFormat))){
+ return hr;
+ }
+
+ return hr;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// GetSupportedFormatsForConnector
+//
+// For host/keyword detector pin, supported formats info is cached in property store and can be directly read. For offload
+// pin, provide with a predefined list of formats and check whether format is supported. For loopback pin, it matches the format
+// of host pin so put 0 format record.
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+HRESULT GetSupportedFormatRecordsForConnector
+(
+ IMMDevice* pDevice,
+ UINT uConnectorId,
+ EndpointConnectorType eConnectorType,
+ AUDIO_SIGNALPROCESSINGMODE mode,
+ STACKWISE_DATAFLOW dataFlow,
+ ULONG *pCount,
+ FORMAT_RECORD **ppFormatRecords
+)
+{
+ HRESULT hr = S_OK;
+
+ *pCount = 0;
+ *ppFormatRecords = NULL;
+
+ if (eConnectorType == eHostProcessConnector || eConnectorType == eKeywordDetectorConnector) {
+ if (!VERIFY_SUCCEEDED(hr = GetCachedSupportedFormatRecords(pDevice, eConnectorType, mode, pCount, ppFormatRecords))) {
+ return hr;
+ }
+ }
+ else if (eConnectorType == eOffloadConnector) {
+ if (!VERIFY_SUCCEEDED(hr = GetSupportedFormatRecords(pDevice, uConnectorId, eConnectorType, mode, dataFlow, pCount, ppFormatRecords))) {
+ return hr;
+ }
+ }
+ else if (eConnectorType == eLoopbackConnector) {
+ *pCount = 0;
+ *ppFormatRecords = NULL;
+ }
+
+ return hr;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// GetPreferredFormatForConnector
+//
+// If KSPROPERTY_PIN_PROPOSEDATAFORMAT2 is supported, use the proposed format for mode as preferred format for mode.
+// Otherwise, use default format as preferred format.
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+HRESULT GetPreferredFormatForConnector
+(
+ IMMDevice* pDevice,
+ UINT uConnectorId,
+ EndpointConnectorType eConnectorType,
+ AUDIO_SIGNALPROCESSINGMODE mode,
+ WAVEFORMATEX **ppPreferredFormat
+)
+{
+ HRESULT hr = S_OK;
+ wil::unique_cotaskmem_ptr<WAVEFORMATEX> pDefaultFormat;
+ wil::unique_cotaskmem_ptr<WAVEFORMATEX> pProposedFormat;
+
+ *ppPreferredFormat = NULL;
+
+
+ // Get default format for connector
+ if (!VERIFY_SUCCEEDED(hr = GetDefaultFormatForConnector(pDevice, eConnectorType, wil::out_param(pDefaultFormat)))) {
+ return hr;
+ }
+
+ // Return the processing mode specific format proposed by the driver
+ hr = GetProposedFormatForProcessingMode(pDevice, uConnectorId, mode, wil::out_param(pProposedFormat));
+ if (hr == S_OK) {
+ CloneWaveFormat(pProposedFormat.get(), ppPreferredFormat);
+ }
+ else {
+ CloneWaveFormat(pDefaultFormat.get(), ppPreferredFormat);
+ hr = S_OK;
+ }
+
+ return hr;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// GetPreferredFormatPeriodicityCharacteristicsForConnector
+//
+// Get periodicity characteristics for format. For host/keyword detector pin, periodicity info is cached along with format
+// in property store and can be searched from supported format list. For offload pin, it should be calculate from
+// DiscoverPeriodicityCharacteristicsForFormat.
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+HRESULT GetPreferredFormatPeriodicityCharacteristicsForConnector
+(
+ IMMDevice* pDevice,
+ EndpointConnectorType eConnectorType,
+ AUDIO_SIGNALPROCESSINGMODE mode,
+ STACKWISE_DATAFLOW dataFlow,
+ WAVEFORMATEX *pPreferredFormat,
+ ULONG cFormatRecords,
+ PFORMAT_RECORD pFormatRecords,
+ UINT32 *pDefaultPeriodicityInFrames,
+ UINT32 *pFundamentalPeriodicityInFrames,
+ UINT32 *pMinPeriodicityInFrames,
+ UINT32 *pMaxPeriodicityInFrames,
+ UINT32 *pMaxPeriodicityInFramesExtended
+)
+{
+ HRESULT hr = S_OK;
+ bool bFormatInList = false;
+
+ for (ULONG i = 0; i < cFormatRecords; i++) {
+ if (CompareWaveFormat((WAVEFORMATEX *)&pFormatRecords[i].wfxEx, pPreferredFormat)) {
+ bFormatInList = true;
+ *pDefaultPeriodicityInFrames = pFormatRecords[i].defaultPeriodInFrames;
+ *pFundamentalPeriodicityInFrames = pFormatRecords[i].fundamentalPeriodInFrames;
+ *pMinPeriodicityInFrames = pFormatRecords[i].minPeriodInFrames;
+ *pMaxPeriodicityInFrames = pFormatRecords[i].maxPeriodInFrames;
+ *pMaxPeriodicityInFramesExtended = pFormatRecords[i].maxPeriodInFramesExtended;
+ break;
+ }
+ }
+
+ if (eConnectorType == eHostProcessConnector || eConnectorType == eKeywordDetectorConnector) {
+ if (!VERIFY_IS_TRUE(bFormatInList)) {
+ hr = E_NOTFOUND;
+ return hr;
+ }
+ }
+ else if (eConnectorType == eOffloadConnector || eConnectorType == eLoopbackConnector) {
+ if (!VERIFY_SUCCEEDED(hr = DiscoverPeriodicityCharacteristicsForFormat(pDevice, eConnectorType, mode, pPreferredFormat, dataFlow, pDefaultPeriodicityInFrames, pFundamentalPeriodicityInFrames, pMinPeriodicityInFrames, pMaxPeriodicityInFrames, pMaxPeriodicityInFramesExtended))) {
+ return hr;
+ }
+ }
+
+ return hr;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// AddTestResourceForConnector
+//
+// For each connector, read connector id, get all processing modes, identify default and preferred format for each mode
+// and also enumerate a list of supported formats for each mode. Store all the infos in test resource.
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+HRESULT AddTestResourceForConnector
+(
+ ResourceList& resourceList,
+ LPWSTR deviceId,
+ LPWSTR deviceName,
+ IMMDevice* pDevice,
+ EndpointConnectorType eConnectorType,
+ STACKWISE_DATAFLOW dataFlow
+)
+{
+ HRESULT hr = S_OK;
+ bool bHasConnector = false;
+ UINT uConnectorId;
+ ULONG cModes = 0;
+ CComHeapPtr<AUDIO_SIGNALPROCESSINGMODE> spModes;
+ AUDIO_SIGNALPROCESSINGMODE mode;
+ ULONG cFormatRecords = 0;
+ CComHeapPtr<FORMAT_RECORD> spFormatRecords;
+ wil::unique_cotaskmem_ptr<WAVEFORMATEX> pPreferredFormat;
+ UINT32 u32DefaultPeriodicityInFrames;
+ UINT32 u32FundamentalPeriodicityInFrames;
+ UINT32 u32MinPeriodicityInFrames;
+ UINT32 u32MaxPeriodicityInFrames;
+ UINT32 u32MaxPeriodicityInFramesExtended;
+ bool isAVStream = false;
+ bool isBluetooth = false;
+ bool isSideband = false;
+
+ // Get connector id
+ if (!VERIFY_SUCCEEDED(hr = GetConnectorId(pDevice, eConnectorType, &bHasConnector, &uConnectorId))) {
+ return hr;
+ }
+ if (!bHasConnector) {
+ return hr;
+ }
+
+ Log::Comment(String().Format(L"Adding Test Resource for pin [%u]:", (uConnectorId & PARTID_MASK)));
+
+
+ // Get all signal processing modes for connector
+ if (!VERIFY_SUCCEEDED(hr = GetProcessingModesForConnector(pDevice, uConnectorId, eConnectorType, &cModes, &spModes))) {
+ return hr;
+ }
+
+ // Loop through each mode, get preferred format and list of formats and create test resource for each mode
+ for (ULONG i = 0; i < cModes; i++) {
+
+ mode = spModes[i];
+
+ if (!VERIFY_SUCCEEDED(hr = GetSupportedFormatRecordsForConnector(pDevice, uConnectorId, eConnectorType, mode, dataFlow, &cFormatRecords, &spFormatRecords))) {
+ return hr;
+ }
+
+ if (!VERIFY_SUCCEEDED(hr = GetPreferredFormatForConnector(pDevice, uConnectorId, eConnectorType, mode, wil::out_param(pPreferredFormat)))) {
+ return hr;
+ }
+
+ if (!VERIFY_SUCCEEDED(hr = GetPreferredFormatPeriodicityCharacteristicsForConnector(pDevice, eConnectorType, mode, dataFlow, pPreferredFormat.get(), cFormatRecords, spFormatRecords, &u32DefaultPeriodicityInFrames, &u32FundamentalPeriodicityInFrames, &u32MinPeriodicityInFrames, &u32MaxPeriodicityInFrames, &u32MaxPeriodicityInFramesExtended))) {
+ return hr;
+ }
+
+ // Check if audio endpoint is AVStream
+ if (!VERIFY_SUCCEEDED(hr = IsAVStream(pDevice, &isAVStream))) {
+ return hr;
+ }
+
+ // Check if audio endpoint is Bluetooth
+ if (!VERIFY_SUCCEEDED(hr = IsBluetooth(pDevice, &isBluetooth))) {
+ return hr;
+ }
+
+ // Check if audio endpoint is side band
+ if (!VERIFY_SUCCEEDED(hr = IsSideband(pDevice, &isSideband))) {
+ return hr;
+ }
+
+ DeviceDescriptor descriptor = { 0 };
+ descriptor.pDevice = pDevice;
+ descriptor.pwstrAudioEndpointId = deviceId;
+ descriptor.pwstrAudioEndpointFriendlyName = deviceName;
+ descriptor.dataFlow = dataFlow;
+ descriptor.eConnectorType = eConnectorType;
+ descriptor.uConnectorId = uConnectorId;
+ descriptor.mode = mode;
+ descriptor.cModes = cModes;
+ descriptor.pModes = spModes;
+ descriptor.cFormatRecords = cFormatRecords;
+ descriptor.pFormatRecords = spFormatRecords;
+ descriptor.pPreferredFormat = pPreferredFormat.get();
+ descriptor.u32DefaultPeriodicityInFrames = u32DefaultPeriodicityInFrames;
+ descriptor.u32FundamentalPeriodicityInFrames = u32FundamentalPeriodicityInFrames;
+ descriptor.u32MinPeriodicityInFrames = u32MinPeriodicityInFrames;
+ descriptor.u32MaxPeriodicityInFrames = u32MaxPeriodicityInFrames;
+ descriptor.bIsAVStream = isAVStream;
+ descriptor.bIsBluetooth = isBluetooth;
+ descriptor.bIsSideband = isSideband;
+
+ if (!VERIFY_SUCCEEDED(hr = CreateTestResource(resourceList, descriptor))) {
+ return hr;
+ }
+
+ spFormatRecords.Free();
+ }
+
+ return hr;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// AddTestResourcesForDevice
+//
+// Identify the existence of all pin types and add test resources for each pin
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+HRESULT AddTestResourcesForDevice
+(
+ ResourceList& resourceList,
+ LPWSTR deviceId,
+ LPWSTR deviceName,
+ STACKWISE_DATAFLOW dataFlow
+)
+{
+ HRESULT hr = S_OK;
+ wil::com_ptr_nothrow<IMMDeviceEnumerator> spEnumerator;
+ wil::com_ptr_nothrow<IMMDevice> spDevice;
+
+ Log::Comment(String().Format(L"Adding Test Resource for Device [%s]:", deviceName));
+
+ // Read the default device format from the property store
+ if (!VERIFY_SUCCEEDED(hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void **)&spEnumerator))) {
+ return hr;
+ }
+ if (!VERIFY_SUCCEEDED(hr = spEnumerator->GetDevice(deviceId, &spDevice))) {
+ return hr;
+ }
+
+ // Identify existence of host pin. Add test resources for host pin.
+ if (!VERIFY_SUCCEEDED(hr = AddTestResourceForConnector(resourceList, deviceId, deviceName, spDevice.get(), eHostProcessConnector, dataFlow))) {
+ return hr;
+ }
+
+ // Identify existence of offload pin. Add test resources for offload pin.
+ if (!VERIFY_SUCCEEDED(hr = AddTestResourceForConnector(resourceList, deviceId, deviceName, spDevice.get(), eOffloadConnector, dataFlow))) {
+ return hr;
+ }
+
+ // Identify existence of loopback pin. Add test resources for loopback pin.
+ if (!VERIFY_SUCCEEDED(hr = AddTestResourceForConnector(resourceList, deviceId, deviceName, spDevice.get(), eLoopbackConnector, capture ))) {
+ return hr;
+ }
+
+ /*
+ // Identify existence of keyword detector pin. Add test resources for keyword detector pin.
+ if (!VERIFY_SUCCEEDED(hr = AddTestResourceForConnector(resourceList, deviceId, deviceName, spDevice.get(), eKeywordDetectorConnector, dataFlow))) {
+ return hr;
+ }
+ */
+
+ return hr;
+}
+
+HRESULT __cdecl BuildResourceList(ResourceList& resourceList)
+{
+ HRESULT hr = S_OK;
+ wil::com_ptr_nothrow<IMMDeviceEnumerator> spEnumerator;
+ wil::com_ptr_nothrow<IMMDeviceCollection> spRenderEndpoints;
+ wil::com_ptr_nothrow<IMMDeviceCollection> spCaptureEndpoints;
+ wil::com_ptr_nothrow<IMMDevice> spEndpoint;
+ UINT cRenderDevices = 0;
+ UINT cCaptureDevices = 0;
+ UINT i = 0;
+ wil::unique_cotaskmem_string id;
+ wil::unique_cotaskmem_string friendlyName;
+
+ SetVerifyOutput verifySettings(VerifyOutputSettings::LogOnlyFailures);
+ DisableVerifyExceptions disable;
+
+ VERIFY_SUCCEEDED(::CoInitializeEx(NULL, COINIT_MULTITHREADED));
+
+ Log::Comment(L"In BuildResourceList");
+
+ // Create IMMDevice Enumerator
+ VERIFY_SUCCEEDED(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void **)&spEnumerator));
+
+ // Enumerate all render endpoints
+ VERIFY_SUCCEEDED(spEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &spRenderEndpoints));
+ VERIFY_SUCCEEDED(spRenderEndpoints->GetCount(&cRenderDevices));
+
+ // Enumerate all capture endpoints
+ VERIFY_SUCCEEDED(spEnumerator->EnumAudioEndpoints(eCapture, DEVICE_STATE_ACTIVE, &spCaptureEndpoints));
+ VERIFY_SUCCEEDED(spCaptureEndpoints->GetCount(&cCaptureDevices));
+
+ if (!VERIFY_IS_TRUE(cRenderDevices | cCaptureDevices))
+ {
+ hr = E_FAIL;
+ Log::Comment(L"No device was found!");
+ goto Exit;
+ }
+
+ Log::Comment(String().Format(L"Found %d viable rendering device!", cRenderDevices));
+ // Add test resources for render endpoints
+ if (cRenderDevices) {
+ for (i = 0; i < cRenderDevices; i++) {
+ VERIFY_SUCCEEDED(spRenderEndpoints->Item(i, &spEndpoint));
+ VERIFY_SUCCEEDED(spEndpoint->GetId(&id));
+ VERIFY_SUCCEEDED(GetEndpointFriendlyName(spEndpoint.get(), &friendlyName));
+
+ Log::Comment(String().Format(L"\\\\ Device: %s (%s)", friendlyName.get(), id.get()));
+ VERIFY_SUCCEEDED(AddTestResourcesForDevice(resourceList, id.get(), friendlyName.get(), render));
+ }
+ }
+
+ Log::Comment(String().Format(L"Found %d viable capture device!", cCaptureDevices));
+ // Add test resources for capture endpoints
+ if (cCaptureDevices) {
+ for (i = 0; i < cCaptureDevices; i++) {
+ VERIFY_SUCCEEDED(spCaptureEndpoints->Item(i, &spEndpoint));
+ VERIFY_SUCCEEDED(spEndpoint->GetId(&id));
+ VERIFY_SUCCEEDED(GetEndpointFriendlyName(spEndpoint.get(), &friendlyName));
+
+ Log::Comment(String().Format(L"\\\\ Device: %s (%s)", friendlyName.get(), id.get()));
+ VERIFY_SUCCEEDED(AddTestResourcesForDevice(resourceList, id.get(), friendlyName.get(), capture));
+ }
+ }
+
+ Log::Comment(L"Resource enumeration complete.");
+ Log::Comment(String().Format(L"Enumerated %u resources", resourceList.Count()));
+
+Exit:
+ return hr;
+}
diff --git a/audio/tests/KSPosTst/locallimits.h b/audio/tests/KSPosTst/locallimits.h
new file mode 100644
index 00000000..60336eb5
--- /dev/null
+++ b/audio/tests/KSPosTst/locallimits.h
@@ -0,0 +1,25 @@
+// ------------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// Module Name:
+//
+// locallimits.h
+//
+// Abstract:
+//
+// defines the tolerances for WHQL failures for this test app
+//
+// -------------------------------------------------------------------------------
+
+// max latency for rendering or capturing is 20 ms
+#define LATENCY_THRESHOLD 20.
+
+// Real time sampling rates must be within 1% of the theoretical rate,
+// per the format, as required by the PC98/PC99 HW Design Guide.
+#define SAMPLERATE_THRESHOLD 1.0
+
+// audio devices are required to be SAMPLEACCURATE (PC9x HW Design Guide)..
+// but for some reason we are making them ms accurate??
+#define JITTER_STD_THRESHOLD 1.0 // 1 ms max allowed for std-deviation
+#define JITTER_MAX_THRESHOLD 4.0 // 4 ms max allowed for max deviation
diff --git a/audio/tests/KSPosTst/pintest.cpp b/audio/tests/KSPosTst/pintest.cpp
new file mode 100644
index 00000000..57e35b07
--- /dev/null
+++ b/audio/tests/KSPosTst/pintest.cpp
@@ -0,0 +1,518 @@
+// ------------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// Module Name:
+//
+// pintest.cpp
+//
+// Abstract:
+//
+// Implementation file for test cases
+//
+// -------------------------------------------------------------------------------
+
+#include "PreComp.h"
+#include "KsPosTestTaef.h"
+#include "tests.h"
+
+#include <bestfit.h>
+#include <cmath>
+
+#define DEFAULT_PERIODICITY 0
+#define DEFAULT_LATENCY_COEFFICIENT 0
+#define xGetTime g_pKsPosTst->m_pTimer->Proc
+
+// ------------------------------------
+// Test_DriftAndJitter helper functions
+// ------------------------------------
+
+HRESULT CollectSampleData
+(
+ CHalfApp* pHalfApp,
+ PFORMAT_ENTRY pFormatEntry,
+ HNSTIME requestedPeriodicity
+)
+{
+ DWORD periodicityInMs = (DWORD)ceil(HNSTIME_TO_MILLISECONDS_DOUBLE(requestedPeriodicity));
+
+ if (!pFormatEntry)
+ {
+ ERR(g_pBasicLog, "FAIL: Current Format Entry is NULL.");
+ return E_INVALIDARG;
+ }
+
+ PPERF_RESULTS pResults = &pFormatEntry->perfResults;
+ PPOSITION_SET pPosSet = pResults->argPosSets;
+ double tStart = 0, tPre = 0, tPost = 0;
+ UINT i = 0;
+ UINT64 u64Position;
+ UINT64 positionHNS;
+ UINT64 u64Frequency;
+ double testStartHns;
+ LARGE_INTEGER liNow;
+ LARGE_INTEGER liFrequency;
+ QueryPerformanceFrequency(&liFrequency);
+
+ VERIFY_SUCCEEDED(pHalfApp->InitializeEndpoint());
+ VERIFY_SUCCEEDED(pHalfApp->CreateSineToneDataBuffer(pHalfApp->m_pCurrentFormat.get()));
+ VERIFY_SUCCEEDED(pHalfApp->InitializeStream(requestedPeriodicity, DEFAULT_LATENCY_COEFFICIENT));
+
+ // run the adapter sink pin
+ VERIFY_SUCCEEDED(pHalfApp->StartStream());
+
+ // Get a HNS reference from the begining of the test so the HNS from system and driver times won't be so large
+ QueryPerformanceCounter(&liNow);
+ testStartHns = (double)liNow.QuadPart * HNSTIME_UNITS_PER_SECOND / (double)liFrequency.QuadPart;
+
+ tStart = xGetTime();
+ Sleep(DELAY_FOR_STABILIZE);
+ // Get the stream frequency in order to determine the time offset
+ VERIFY_SUCCEEDED(pHalfApp->m_pAudioClock->GetFrequency(&u64Frequency));
+
+ // Start collecting the data
+ for (i = 0; i < DATA_POINTS;)
+ {
+ Sleep(periodicityInMs);
+
+ tPre = xGetTime();
+ VERIFY_SUCCEEDED(pHalfApp->GetPosition(&u64Position, &positionHNS));
+ QueryPerformanceCounter(&liNow);
+ tPost = xGetTime();
+
+ if (u64Position > 0)
+ {
+ // only count this result if the GetPosition and GetTime happened relatively atomically
+ if ((tPost - tPre) < 1.)
+ {
+ double testHNS = (double)liNow.QuadPart * HNSTIME_UNITS_PER_SECOND / (double)liFrequency.QuadPart;
+ // In both sampling rate and jitter calculation, the time used is in milliseconds, so we can convert it right here
+ pPosSet[i].testTime = HNSTIME_TO_MILLISECONDS_DOUBLE(testHNS - testStartHns);
+ pPosSet[i].positionTime = HNSTIME_TO_MILLISECONDS_DOUBLE(positionHNS - testStartHns);
+ // We store the values as seconds because it is easier to convert to bytes per second, on sampling rate calculation, and milliseconds, on jitter calculation.
+ pPosSet[i].position = (double)u64Position / (double)u64Frequency;
+
+ // Ignore repeated positions (that means they have the same QPC and should have the same position value)
+ if ((i > 0) && (pPosSet[i - 1].positionTime == pPosSet[i].positionTime))
+ {
+ // If the position is the same, decrement the count so that sample gets discarded by overwriting it
+ i--;
+ WARN(g_pBasicLog, "The same position was reported at %f ms: pos = %f seconds", pPosSet[i].testTime, pPosSet[i].position);
+ }
+ i++;
+ }
+ else
+ {
+ LOG(g_pBasicLog, "GetPosition function too slow");
+ }
+ }
+ // If a non-zero position has not been reported during one second, break the loop and check if there is enough data
+ else if ((tPost - tStart) > MILLISECONDS_PER_SECOND)
+ {
+ break;
+ }
+
+ pResults->cPosSets = i;
+ }
+
+ VERIFY_SUCCEEDED(pHalfApp->StopStream());
+
+ // Did we get enough data?
+ VERIFY_IS_TRUE(pResults->cPosSets >= 30);
+
+ return S_OK;
+}
+
+// --------------------------------------------------------------------------------------------------
+// CalculateSampleRate
+// --------------------------------------------------------------------------------------------------
+HRESULT CalculateSampleRate
+(
+ PFORMAT_ENTRY pFormatEntry
+)
+{
+ WAVEFORMATEX* pwfx = &pFormatEntry->wfxFormat.Format;
+ PPERF_RESULTS pResults = &pFormatEntry->perfResults;
+
+ double dError, dErrorPercent;
+
+ // Pair the positions with test HNS time to find the slope
+ // Alocate memory for this type-specific array
+ wil::unique_cotaskmem_ptr<DPOINT> pointArray((PDPOINT)CoTaskMemAlloc(DATA_POINTS * sizeof(DPOINT)));
+ PDPOINT pArray = pointArray.get();
+ // Get a pointer to the sample set
+ PPOSITION_SET posSet = pResults->argPosSets;
+ for (int i = 0; i < DATA_POINTS; i++)
+ {
+ pArray[i].x = posSet[i].positionTime;
+ pArray[i].y = posSet[i].position * pwfx->nAvgBytesPerSec; // Convert to bytes
+ }
+
+ ULONG cArray = pResults->cPosSets; // number of points
+
+ // calculate the slope and intercept (bytes per second and latency)
+ pResults->bytesPerSecond = SLOPE(pArray, cArray);
+ pResults->dOffset = INTERCEPT(pArray, cArray, pResults->bytesPerSecond);
+
+ // Convert from bytes/ms to bytes/sec
+ pResults->bytesPerSecond *= MILLISECONDS_PER_SECOND;
+
+ // The offset is used in the jitter calculation and it is used in milliseconds, so we can save it in those units
+ pResults->dOffset = pResults->dOffset / pResults->bytesPerSecond * MILLISECONDS_PER_SECOND;
+
+ // calculate errors
+ dError = pResults->bytesPerSecond - (double)pwfx->nAvgBytesPerSec;
+ dErrorPercent = (dError / (double)pwfx->nAvgBytesPerSec) * 100.0;
+
+ if (g_pKsPosTst->m_fLogHistograms)
+ {
+ LOG(g_pBasicLog, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
+ LOG(g_pBasicLog, "SampleRate calculated from histogram (method of least squares)\n");
+
+ LOG(g_pBasicLog, "Collected %d data points", pResults->cPosSets);
+ LOG(g_pBasicLog, "Specified sample rate = %6.3f bytes/sec, %6.3f samples/sec", (double)(pwfx->nBlockAlign * pwfx->nSamplesPerSec), (double)pwfx->nSamplesPerSec);
+ LOG(g_pBasicLog, "Calculated sample rate = %6.3f bytes/sec, %6.3f samples/sec", pResults->bytesPerSecond, pResults->bytesPerSecond / (double)pwfx->nBlockAlign);
+ LOG(g_pBasicLog, "Error = %.3f %%", dErrorPercent);
+ LOG(g_pBasicLog, "Calculated time offset = %f ms", pResults->dOffset);
+ }
+
+ // evaluate the results
+ VERIFY_IS_TRUE(abs(dErrorPercent) <= SAMPLERATE_THRESHOLD);
+
+ return S_OK;
+}
+
+// --------------------------------------------------------------------------------------------------
+// CalculateJitter
+// --------------------------------------------------------------------------------------------------
+HRESULT CalculateJitter
+(
+ PFORMAT_ENTRY pFormatEntry
+)
+{
+ PPERF_RESULTS pResults = &pFormatEntry->perfResults;
+
+ double dError = 0.0;
+ double dErrorAve = 0.0;
+ double dErrorMax = 0.0;
+ double dStdDeviation = 0.0;
+ double reportedPosition;
+ double timeDifference;
+ ULONG i;
+ PPOSITION_SET pPosSet = pResults->argPosSets;
+
+ if (g_pKsPosTst->m_fLogHistograms)
+ {
+ LOG(g_pBasicLog, "Reported QPC Compensated Expected");
+ LOG(g_pBasicLog, "position adjust position position Error");
+ LOG(g_pBasicLog, "(ms) (ms) (ms) (ms) (ms)");
+ LOG(g_pBasicLog, "========== ========== ========== ========== ==========");
+ }
+
+ for (i = 0; i < pResults->cPosSets; i++)
+ {
+ // Convert the time offset from seconds to milliseconds
+ reportedPosition = pPosSet[i].position * MILLISECONDS_PER_SECOND; // milliseconds
+
+ // First, we compensate for the latency of the samples (they were taken 100 ms after stream start)
+ pPosSet[i].position = reportedPosition - pResults->dOffset; // The offset is already in ms
+
+ // Then, before comparing the expected and actual position, adjust the given sample to get the position corresponding to the test time.
+ timeDifference = pPosSet[i].testTime - pPosSet[i].positionTime; // milliseconds
+ // If the difference is positive, the time of the position is behind of what is expected and that position gets increased accordingly.
+ // If the difference is negative, the time of the position is ahead of what is expected and that position gets decreased accordingly.
+ // In the rare case when the QPC and time are the same, the difference is zero because we are on the spot and that is the position that should be compared.
+ pPosSet[i].position += timeDifference; // milliseconds
+
+ dError = pPosSet[i].testTime - pPosSet[i].position;
+ dErrorAve += dError;
+
+ if (g_pKsPosTst->m_fLogHistograms)
+ {
+ LOG(g_pBasicLog, "%10.2f, %10.2f, %10.2f, %10.2f, %10.2f", reportedPosition, timeDifference, pPosSet[i].position, pPosSet[i].testTime, dError);
+ }
+
+ if (dError < 0.)
+ dError = -dError;
+ if (dError > dErrorMax)
+ dErrorMax = dError;
+ }
+
+ dErrorAve /= (double)pResults->cPosSets;
+
+ VERIFY_IS_TRUE((ULONG)dErrorAve < 2); // if this is not true then, there's something wrong with our compensation...
+
+ for (i = 0; i < pResults->cPosSets; i++)
+ {
+ dError = pPosSet[i].testTime - pPosSet[i].position;
+ dStdDeviation += ((dError - dErrorAve) * (dError - dErrorAve));
+ }
+
+ dStdDeviation /= (double)pResults->cPosSets;
+ dStdDeviation = sqrt(dStdDeviation);
+
+ if (g_pKsPosTst->m_fLogHistograms)
+ {
+ LOG(g_pBasicLog, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
+ LOG(g_pBasicLog, "Jitter calculated from histogram (with (samplerate drift and latency) compensation)\n");
+ LOG(g_pBasicLog, "Max deviation = %6.3f ms", dErrorMax);
+ LOG(g_pBasicLog, "Standard deviation = %6.3f ms", dStdDeviation);
+ }
+
+ // evaluate the results ~~~~~~~~~~~~~
+ VERIFY_IS_TRUE(abs(dErrorMax) < JITTER_MAX_THRESHOLD);
+ VERIFY_IS_TRUE(abs(dStdDeviation) < JITTER_STD_THRESHOLD);
+
+ return S_OK;
+}
+
+// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+void Test_DriftAndJitter_Main
+(
+ HNSTIME requestedPeriodicity
+)
+{
+ CHalfApp* pHalfApp = g_pKsPosTst->m_pHalf;
+ CHalfApp* pHostHalfApp = g_pKsPosTst->m_pHostHalf;
+ BOOL isLoopbackPin = pHalfApp->m_ConnectorType == eLoopbackConnector;
+
+ // Test will ignore Bluetooth devices until proper thresholds are in place.
+ if (pHalfApp->m_bIsBluetooth)
+ {
+ SKIP(g_pBasicLog, "Test is not supported for Bluetooth pins");
+ return;
+ }
+
+ // If this is a loobpack pin, start the host pin's stream
+ // This can be done before collecting the samples, since the host pin will keep playing until stopped
+ if (isLoopbackPin)
+ {
+ // Match loopback stream format with host stream format
+ CloneWaveFormat(pHostHalfApp->m_pCurrentFormat.get(), wil::out_param(pHalfApp->m_pCurrentFormat));
+ pHalfApp->m_u32CurrentDefaultPeriodicityInFrames = pHostHalfApp->m_u32CurrentDefaultPeriodicityInFrames;
+ pHalfApp->m_u32CurrentFundamentalPeriodicityInFrames = pHostHalfApp->m_u32CurrentFundamentalPeriodicityInFrames;
+ pHalfApp->m_u32CurrentMinPeriodicityInFrames = pHostHalfApp->m_u32CurrentMinPeriodicityInFrames;
+ pHalfApp->m_u32CurrentMaxPeriodicityInFrames = pHostHalfApp->m_u32CurrentMaxPeriodicityInFrames;
+
+ // Initialize and start host stream
+ VERIFY_SUCCEEDED(pHostHalfApp->InitializeEndpoint());
+ VERIFY_SUCCEEDED(pHostHalfApp->CreateSineToneDataBuffer(pHostHalfApp->m_pCurrentFormat.get()));
+ VERIFY_SUCCEEDED(pHostHalfApp->InitializeStream(requestedPeriodicity, DEFAULT_LATENCY_COEFFICIENT));
+ VERIFY_SUCCEEDED(pHostHalfApp->StartStream());
+ }
+
+ FORMAT_ENTRY results;
+ memset(&results, 0, sizeof(FORMAT_ENTRY));
+ results.wfxFormat.Format = *pHalfApp->m_pCurrentFormat.get();
+ // Alocate memory for the sample data
+ wil::unique_cotaskmem_ptr<POSITION_SET> pPositionSet((PPOSITION_SET)CoTaskMemAlloc(DATA_POINTS * sizeof(POSITION_SET)));
+ results.perfResults.argPosSets = pPositionSet.get();
+
+ // collect the data ~~~~~~~~~~~~~~~~~
+ VERIFY_SUCCEEDED(CollectSampleData(pHalfApp, &results, requestedPeriodicity));
+
+ // Stop and cleanup the host stream since we are done collecting samples
+ if (isLoopbackPin)
+ {
+ VERIFY_SUCCEEDED(pHostHalfApp->StopStream());
+ VERIFY_SUCCEEDED(pHostHalfApp->CleanupStream());
+ VERIFY_SUCCEEDED(pHostHalfApp->ReleaseEndpoint());
+ VERIFY_SUCCEEDED(pHostHalfApp->ReleaseSineToneDataBuffer());
+ }
+
+ // calculate drift ~~~~~~~~~~~~~~~~~~
+ VERIFY_SUCCEEDED(CalculateSampleRate(&results));
+
+ // calculate Jitter ~~~~~~~~~~~~~~~~~
+ VERIFY_SUCCEEDED(CalculateJitter(&results));
+}
+
+// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+void Test_DriftAndJitter_Default(void)
+{
+ HNSTIME requestedTime = FRAMES_TO_HNSTIME_DOUBLE(g_pKsPosTst->m_pHalf->m_u32CurrentDefaultPeriodicityInFrames, g_pKsPosTst->m_pHalf->m_pCurrentFormat->nSamplesPerSec);
+ if (g_pKsPosTst->m_fLogHistograms)
+ {
+ LOG(g_pBasicLog, "Periodicity: %d frames, %f ms", g_pKsPosTst->m_pHalf->m_u32CurrentDefaultPeriodicityInFrames, HNSTIME_TO_MILLISECONDS_DOUBLE(requestedTime));
+ }
+ Test_DriftAndJitter_Main(requestedTime);
+}
+
+/*
+ Perform a cycle of creating a pin, starting a stream, stoping and destroying.
+
+ This is done with the idea of putting the driver and audio hardware in an active state
+ before doing time sensitive tests.
+*/
+void ActivateDriver(CHalfApp* pHalfApp)
+{
+ VERIFY_SUCCEEDED(pHalfApp->InitializeEndpoint());
+ VERIFY_SUCCEEDED(pHalfApp->CreateSineToneDataBuffer(pHalfApp->m_pCurrentFormat.get()));
+ VERIFY_SUCCEEDED(pHalfApp->InitializeStream(DEFAULT_PERIODICITY, DEFAULT_LATENCY_COEFFICIENT));
+ VERIFY_SUCCEEDED(pHalfApp->StartStream());
+ Sleep(100);
+ VERIFY_SUCCEEDED(pHalfApp->StopStream());
+ VERIFY_SUCCEEDED(pHalfApp->CleanupStream());
+ VERIFY_SUCCEEDED(pHalfApp->ReleaseEndpoint());
+ VERIFY_SUCCEEDED(pHalfApp->ReleaseSineToneDataBuffer());
+}
+
+// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+void Test_Latency_Main (HNSTIME requestedPeriodicity)
+{
+ CHalfApp* pHalfApp = g_pKsPosTst->m_pHalf;
+ CHalfApp* pHostHalfApp = g_pKsPosTst->m_pHostHalf;
+ NTSTATUS lTimerResStatus;
+ BOOL isLoopbackPin = pHalfApp->m_ConnectorType == eLoopbackConnector;
+
+ // Test will ignore Bluetooth devices until proper thresholds are in place.
+ if (pHalfApp->m_bIsBluetooth)
+ {
+ SKIP(g_pBasicLog, "Test is not supported for Bluetooth pins");
+ return;
+ }
+
+ lTimerResStatus = NtSetTimerResolution(timerResolution, TRUE, &actualTimerResolution);
+
+ if (!NT_SUCCESS(lTimerResStatus))
+ {
+ SKIP(g_pBasicLog, "Fail to set timer precision. Skip the test.");
+ return;
+ }
+
+ // If it is a loopback pin, get the host pin and start the stream
+ if (isLoopbackPin)
+ {
+ // Match loopback stream format with host stream format
+ CloneWaveFormat(pHostHalfApp->m_pCurrentFormat.get(), wil::out_param(pHalfApp->m_pCurrentFormat));
+ pHalfApp->m_u32CurrentDefaultPeriodicityInFrames = pHostHalfApp->m_u32CurrentDefaultPeriodicityInFrames;
+ pHalfApp->m_u32CurrentFundamentalPeriodicityInFrames = pHostHalfApp->m_u32CurrentFundamentalPeriodicityInFrames;
+ pHalfApp->m_u32CurrentMinPeriodicityInFrames = pHostHalfApp->m_u32CurrentMinPeriodicityInFrames;
+ pHalfApp->m_u32CurrentMaxPeriodicityInFrames = pHostHalfApp->m_u32CurrentMaxPeriodicityInFrames;
+
+ // Initialize and start host stream
+ VERIFY_SUCCEEDED(pHostHalfApp->InitializeEndpoint());
+ VERIFY_SUCCEEDED(pHostHalfApp->CreateSineToneDataBuffer(pHostHalfApp->m_pCurrentFormat.get()));
+ VERIFY_SUCCEEDED(pHostHalfApp->InitializeStream(requestedPeriodicity, DEFAULT_LATENCY_COEFFICIENT));
+ VERIFY_SUCCEEDED(pHostHalfApp->StartStream());
+ }
+
+ // Perform a stream cycle to make sure the driver is on a good state
+ ActivateDriver(pHalfApp);
+
+ // Initialize the stream
+ VERIFY_SUCCEEDED(pHalfApp->InitializeEndpoint());
+ VERIFY_SUCCEEDED(pHalfApp->CreateSineToneDataBuffer(pHalfApp->m_pCurrentFormat.get()));
+ VERIFY_SUCCEEDED(pHalfApp->InitializeStream(requestedPeriodicity, DEFAULT_LATENCY_COEFFICIENT));
+
+ UINT64 u64Position = 0;
+ UINT64 driverHns = 0;
+
+ double tPosPre = 0.0;
+ double tPosPost = 0.0;
+
+ LARGE_INTEGER liFrequency = { 0 };
+ LARGE_INTEGER timeStamp = { 0 };
+ QueryPerformanceFrequency(&liFrequency);
+
+ // mark the time
+ double tRunPre = xGetTime();
+ // Start the stream
+ VERIFY_SUCCEEDED(pHalfApp->StartStream());
+ // mark the time
+ double tRunPost = xGetTime();
+
+ LOG(g_pBasicLog, "Starting the stream took %.03f ms", (tRunPost - tRunPre));
+
+ // loop until we get a non-zero position
+ while (u64Position == 0)
+ {
+ Sleep(1);
+ // timer before position call
+ tPosPre = xGetTime();
+ VERIFY_SUCCEEDED(pHalfApp->GetPosition(&u64Position, &driverHns));
+ QueryPerformanceCounter(&timeStamp);
+ // timer after position call
+ tPosPost = xGetTime();
+ if (g_pKsPosTst->m_fLogHistograms)
+ {
+ LOG(g_pBasicLog, "Testing first non-zero position reported: %u samples, %u HNS at %.03f ms", u64Position, driverHns, tPosPost - tRunPre);
+ }
+
+ // Fail if the cursor does not move within 500 ms
+ VERIFY_IS_TRUE((tPosPost - tRunPost) < 500.0);
+ }
+
+ // Before stopping, get the frequency of the stream
+ UINT64 u64Frequency;
+ VERIFY_SUCCEEDED(pHalfApp->m_pAudioClock->GetFrequency(&u64Frequency));
+
+ // the uncertainty in time is the max possible value minus the min possible value divided by 2 (for +/- purposes)
+ double tMax = tPosPost - tRunPre;
+ double tMin = tPosPre - tRunPost;
+ double tAve = (tMax + tMin) / 2.0;
+ double tUncertainty = (tMax - tMin) / 2.0;
+
+ // Convert the stream position to an offset of milliseconds
+ double tOffset = MILLISECONDS_PER_SECOND * (double)u64Position / (double)u64Frequency;
+
+ // Calculate the difference in time of the position time versus the test time
+ UINT64 testHns = 10000000 * timeStamp.QuadPart / liFrequency.QuadPart;
+ INT64 timeDiff = testHns - driverHns;
+
+ // Compensate the positon to take this difference into account
+ tOffset += (double)timeDiff / HNSTIME_UNITS_PER_MILLISECOND;
+
+ if (g_pKsPosTst->m_fLogHistograms)
+ {
+ LOG(g_pBasicLog, "Times (HNS): %u, %u", testHns, driverHns);
+ LOG(g_pBasicLog, "Time difference: %d HNS (%f ms)", timeDiff, (double)timeDiff / HNSTIME_UNITS_PER_MILLISECOND);
+ LOG(g_pBasicLog, "First non-zero position = %u at %g ms", u64Position, tAve);
+ LOG(g_pBasicLog, "Time offset / max time: %f ms / %f ms", tOffset, tMax);
+ LOG(g_pBasicLog, "Frequency: %lu", u64Frequency);
+ }
+
+ double tLatency;
+ tLatency = tAve - tOffset;
+ if (tLatency < 0)
+ {
+ // This means that the position is between the average and max times, which should be OK (as long as it is not above the max)
+ tLatency *= -1;
+ LOG(g_pBasicLog, "The position is greater than the average time");
+ }
+ LOG(g_pBasicLog, "Adjusted latency = %.03f ms (+/- %.3f ms)", tLatency, tUncertainty);
+
+ // if the reported position is outside the max time for this call (see tUncertainty calculation above), then fail
+ // temp fix until we know how far can be the data in front of the
+ // real time because of buffering
+ VERIFY_IS_FALSE(tOffset > tMax);
+
+ // Verify that the latency is within the threshold
+ VERIFY_IS_TRUE(tLatency <= LATENCY_THRESHOLD); // ms
+
+ // Stop the endpoint
+ VERIFY_SUCCEEDED(pHalfApp->StopStream());
+ // If this was a loopback pin, stop the host stream also
+ if (isLoopbackPin)
+ {
+ VERIFY_SUCCEEDED(pHostHalfApp->StopStream());
+ VERIFY_SUCCEEDED(pHostHalfApp->CleanupStream());
+ VERIFY_SUCCEEDED(pHostHalfApp->ReleaseEndpoint());
+ VERIFY_SUCCEEDED(pHostHalfApp->ReleaseSineToneDataBuffer());
+ }
+
+ // Turn off the higher resolution timer
+ NtSetTimerResolution(0, FALSE, &actualTimerResolution);
+}
+
+// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+void Test_Latency_Default(void)
+{
+ HNSTIME requestedTime = FRAMES_TO_HNSTIME_DOUBLE(g_pKsPosTst->m_pHalf->m_u32CurrentDefaultPeriodicityInFrames, g_pKsPosTst->m_pHalf->m_pCurrentFormat->nSamplesPerSec);
+ LOG(g_pBasicLog, "Periodicity: %d frames, %f ms", g_pKsPosTst->m_pHalf->m_u32CurrentDefaultPeriodicityInFrames, HNSTIME_TO_MILLISECONDS_DOUBLE(requestedTime));
+ Test_Latency_Main(requestedTime);
+}
diff --git a/audio/tests/KSPosTst/tests.h b/audio/tests/KSPosTst/tests.h
new file mode 100644
index 00000000..ec0a68cc
--- /dev/null
+++ b/audio/tests/KSPosTst/tests.h
@@ -0,0 +1,18 @@
+// ------------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// Module Name:
+//
+// tests.h
+//
+// Abstract:
+//
+// Header for testcases
+//
+// -------------------------------------------------------------------------------
+#pragma once
+
+void Test_DriftAndJitter_Default(void);
+
+void Test_Latency_Default(void);
diff --git a/audio/tests/KSPosTst/timetest.cpp b/audio/tests/KSPosTst/timetest.cpp
new file mode 100644
index 00000000..d8026716
--- /dev/null
+++ b/audio/tests/KSPosTst/timetest.cpp
@@ -0,0 +1,50 @@
+// ------------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// Module Name:
+//
+// timetest.cpp
+//
+// Abstract:
+//
+// Functions to precisely measure time.
+//
+// -------------------------------------------------------------------------------
+
+#include "PreComp.h"
+#include <math.h>
+
+// ------------------------------------------------------------------------------
+// returns millisecs
+double tpQPC (void)
+{
+ static LARGE_INTEGER liFrequency = { 0 };
+ static LARGE_INTEGER liStart = { 0 };
+ static bool bInitialized = false;
+
+ if (!bInitialized)
+ {
+ if (!QueryPerformanceFrequency(&liFrequency))
+ {
+ throw ("QueryPerformanceFrequency failed");
+ }
+
+ if (!QueryPerformanceCounter(&liStart))
+ {
+ throw ("QueryPerformanceCounter failed");
+ }
+
+ bInitialized = true;
+ }
+
+ LARGE_INTEGER liNow = { 0 };
+
+ if (!QueryPerformanceCounter(&liNow))
+ {
+ throw ("QueryPerformanceCounter failed");
+ }
+
+ // milliseconds since test start
+ return 1000.0 * (liNow.QuadPart - liStart.QuadPart) / liFrequency.QuadPart;
+}
diff --git a/audio/tests/wavetest/HalfApp.cpp b/audio/tests/PinResourceHelpers/HalfApp.cpp
index 14a15c08..83c9c8f3 100644
--- a/audio/tests/wavetest/HalfApp.cpp
+++ b/audio/tests/PinResourceHelpers/HalfApp.cpp
@@ -12,15 +12,16 @@
//
// -------------------------------------------------------------------------------
-#include "PreComp.h"
-#include "WaveTestTaef.h"
-#include "HalfApp.h"
-#include "TestResourceHelper.h"
-#include "PropertyHelper.h"
-#include <dithering.h>
-#include <signal-source.h>
-#include <sine-signal-source.h>
-#include <dvmodule.h>
+
+
+
+
+
+
+
+
+
+
HRESULT
CHalfApp::InitializeEndpoint
@@ -114,6 +115,9 @@ CHalfApp::InitializeEndpoint
if (!VERIFY_SUCCEEDED(hr = m_pAudioDeviceEndpoint.query_to(&m_pAudioEndpointRT))) {
return hr;
}
+ if (!VERIFY_SUCCEEDED(hr = m_pAudioDeviceEndpoint.query_to(&m_pAudioClock))) {
+ return hr;
+ }
return hr;
}
@@ -134,6 +138,7 @@ CHalfApp::ReleaseEndpoint
m_pAudioEndpointControl.reset();
m_pAudioEndpoint.reset();
m_pAudioEndpointRT.reset();
+ m_pAudioClock.reset();
return hr;
}
@@ -380,6 +385,7 @@ CHalfApp::GetSecondHalfApp
UINT32 u32MinPeriodicityInFrames;
UINT32 u32MaxPeriodicityInFrames;
UINT32 u32MaxPeriodicityInFramesExtended;
+ DeviceDescriptor descriptor = { 0 };
if (!VERIFY_SUCCEEDED(hr = GetSupportedFormatRecordsForConnector(m_pDevice.get(), m_uConnectorId, m_ConnectorType, secondMode, m_DataFlow, &cFormatRecords, &spFormatRecords))) {
return hr;
@@ -393,7 +399,26 @@ CHalfApp::GetSecondHalfApp
return hr;
}
- *ppSecondHalfApp = new CHalfApp(m_pDevice.get(), m_pwstrDeviceId.get(), m_pwstrDeviceFriendlyName.get(), m_DataFlow, m_ConnectorType, m_uConnectorId, secondMode, m_cModes, m_pModes, cFormatRecords, spFormatRecords, pPreferredFormat.get(), u32DefaultPeriodicityInFrames, u32FundamentalPeriodicityInFrames, u32MinPeriodicityInFrames, u32MaxPeriodicityInFrames);
+ descriptor.pDevice = m_pDevice.get();
+ descriptor.pwstrAudioEndpointId = m_pwstrDeviceId.get();
+ descriptor.pwstrAudioEndpointFriendlyName = m_pwstrDeviceFriendlyName.get();
+ descriptor.dataFlow = m_DataFlow;
+ descriptor.eConnectorType = m_ConnectorType;
+ descriptor.uConnectorId = m_uConnectorId;
+ descriptor.mode = secondMode;
+ descriptor.cModes = m_cModes;
+ descriptor.pModes = m_pModes;
+ descriptor.cFormatRecords = cFormatRecords;
+ descriptor.pFormatRecords = spFormatRecords;
+ descriptor.pPreferredFormat = pPreferredFormat.get();
+ descriptor.u32DefaultPeriodicityInFrames = u32DefaultPeriodicityInFrames;
+ descriptor.u32FundamentalPeriodicityInFrames = u32FundamentalPeriodicityInFrames;
+ descriptor.u32MinPeriodicityInFrames = u32MinPeriodicityInFrames;
+ descriptor.u32MaxPeriodicityInFrames = u32MaxPeriodicityInFrames;
+ descriptor.bIsAVStream = m_bIsAVStream;
+ descriptor.bIsBluetooth = m_bIsBluetooth;
+ descriptor.bIsSideband = m_bIsSideband;
+ *ppSecondHalfApp = new CHalfApp(descriptor);
if (*ppSecondHalfApp == NULL) {
hr = E_OUTOFMEMORY;
return hr;
@@ -432,6 +457,7 @@ CHalfApp::GetHostHalfApp
UINT32 u32MinPeriodicityInFrames;
UINT32 u32MaxPeriodicityInFrames;
UINT32 u32MaxPeriodicityInFramesExtended;
+ DeviceDescriptor descriptor = { 0 };
// It is only used when testing on loopback pin. When preparing loopback pin, we also need prepare the host pin.
VERIFY_IS_TRUE(m_ConnectorType == eLoopbackConnector);
@@ -474,7 +500,26 @@ CHalfApp::GetHostHalfApp
return hr;
}
- *ppHostHalfApp = new CHalfApp(m_pDevice.get(), m_pwstrDeviceId.get(), m_pwstrDeviceFriendlyName.get(), render, eHostProcessConnector, uConnectorId, mode, cModes, spModes, cFormatRecords, spFormatRecords, pPreferredFormat.get(), u32DefaultPeriodicityInFrames, u32FundamentalPeriodicityInFrames, u32MinPeriodicityInFrames, u32MaxPeriodicityInFrames);
+ descriptor.pDevice = m_pDevice.get();
+ descriptor.pwstrAudioEndpointId = m_pwstrDeviceId.get();
+ descriptor.pwstrAudioEndpointFriendlyName = m_pwstrDeviceFriendlyName.get();
+ descriptor.dataFlow = render;
+ descriptor.eConnectorType = eHostProcessConnector;
+ descriptor.uConnectorId = uConnectorId;
+ descriptor.mode = mode;
+ descriptor.cModes = cModes;
+ descriptor.pModes = spModes;
+ descriptor.cFormatRecords = cFormatRecords;
+ descriptor.pFormatRecords = spFormatRecords;
+ descriptor.pPreferredFormat = pPreferredFormat.get();
+ descriptor.u32DefaultPeriodicityInFrames = u32DefaultPeriodicityInFrames;
+ descriptor.u32FundamentalPeriodicityInFrames = u32FundamentalPeriodicityInFrames;
+ descriptor.u32MinPeriodicityInFrames = u32MinPeriodicityInFrames;
+ descriptor.u32MaxPeriodicityInFrames = u32MaxPeriodicityInFrames;
+ descriptor.bIsAVStream = m_bIsAVStream;
+ descriptor.bIsBluetooth = m_bIsBluetooth;
+ descriptor.bIsSideband = m_bIsSideband;
+ *ppHostHalfApp = new CHalfApp(descriptor);
if (*ppHostHalfApp == NULL) {
hr = E_OUTOFMEMORY;
return hr;
@@ -987,13 +1032,9 @@ inline void CHalfApp::CancelTimer(HANDLE timer)
HRESULT CHalfApp::GetPosition(UINT64* pu64Position, UINT64* pu64hnsQPCPosition)
{
HRESULT hr = S_OK;
- wil::com_ptr_nothrow<IAudioClock> spAudioClock;
auto lock = m_CritSec.lock();
- if (!VERIFY_SUCCEEDED(m_pAudioDeviceEndpoint.query_to(&spAudioClock))) {
- return hr;
- }
- if (!VERIFY_SUCCEEDED(spAudioClock->GetPosition(pu64Position, pu64hnsQPCPosition))) {
+ if (!VERIFY_SUCCEEDED(m_pAudioClock->GetPosition(pu64Position, pu64hnsQPCPosition))) {
return hr;
}
diff --git a/audio/tests/PinResourceHelpers/PreComp.h b/audio/tests/PinResourceHelpers/PreComp.h
new file mode 100644
index 00000000..85fc4f83
--- /dev/null
+++ b/audio/tests/PinResourceHelpers/PreComp.h
@@ -0,0 +1,143 @@
+// ------------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+// File Name:
+//
+// PreComp.h
+//
+// Abstract:
+//
+// Precompiled common headers
+//
+// -------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// Define custom test resource properties
+namespace WEX {
+ namespace TestExecution {
+ namespace TestResourceProperty
+ {
+ static const wchar_t c_szMode[] = L"Mode";
+ static const wchar_t c_szPin[] = L"Pin";
+ }
+ }
+}
+
+// ----------------------------------------------------------
+// Parameters for test sine tone
+#define TEST_AMPLITUDE 1.0f
+#define TEST_FREQUENCY 200.0f
+
+// ----------------------------------------------------------
+// Predefined format list for offload streaming
+#define COUNT_FORMATS 4
+
+static WAVEFORMATEXTENSIBLE ListofFormats[COUNT_FORMATS] =
+{
+ // 1
+ {
+ // Format
+ {
+ WAVE_FORMAT_EXTENSIBLE, // wFormatTag
+ 2, // nChannels
+ 44100, // nSamplesPerSec
+ 176400, // nAvgBytesPerSec
+ 4, // nBlockAlign
+ 16, // wBitsPerSample
+ 22 // cbSize
+ },
+ // Samples
+ {
+ 16 // wValidBitsPerSample
+ },
+ KSAUDIO_SPEAKER_STEREO, // dwChannelMask
+ KSDATAFORMAT_SUBTYPE_PCM // SubFormat
+ },
+ // 2
+ {
+ // Format
+ {
+ WAVE_FORMAT_EXTENSIBLE, // wFormatTag
+ 2, // nChannels
+ 48000, // nSamplesPerSec
+ 192000, // nAvgBytesPerSec
+ 4, // nBlockAlign
+ 16, // wBitsPerSample
+ 22 // cbSize
+ },
+ // Samples
+ {
+ 16 // wValidBitsPerSample
+ },
+ KSAUDIO_SPEAKER_STEREO, // dwChannelMask
+ KSDATAFORMAT_SUBTYPE_PCM // SubFormat
+ },
+ // 3
+ {
+ // Format
+ {
+ WAVE_FORMAT_EXTENSIBLE, // wFormatTag
+ 2, // nChannels
+ 88200, // nSamplesPerSec
+ 352800, // nAvgBytesPerSec
+ 4, // nBlockAlign
+ 16, // wBitsPerSample
+ 22 // cbSize
+ },
+ // Samples
+ {
+ 16 // wValidBitsPerSample
+ },
+ KSAUDIO_SPEAKER_STEREO, // dwChannelMask
+ KSDATAFORMAT_SUBTYPE_PCM // SubFormat
+ },
+ // 4
+ {
+ // Format
+ {
+ WAVE_FORMAT_EXTENSIBLE, // wFormatTag
+ 2, // nChannels
+ 96000, // nSamplesPerSec
+ 384000, // nAvgBytesPerSec
+ 4, // nBlockAlign
+ 16, // wBitsPerSample
+ 22 // cbSize
+ },
+ // Samples
+ {
+ 16 // wValidBitsPerSample
+ },
+ KSAUDIO_SPEAKER_STEREO, // dwChannelMask
+ KSDATAFORMAT_SUBTYPE_PCM // SubFormat
+ },
+};
diff --git a/audio/tests/wavetest/PropertyHelper.cpp b/audio/tests/PinResourceHelpers/PropertyHelper.cpp
index fb60d3cc..6e85e53e 100644
--- a/audio/tests/wavetest/PropertyHelper.cpp
+++ b/audio/tests/PinResourceHelpers/PropertyHelper.cpp
@@ -4,7 +4,7 @@
//
// Module Name:
//
-// EndpointPropertyHelpers.cpp
+// PropertyHelper.cpp
//
// Abstract:
//
@@ -14,7 +14,8 @@
#include "PreComp.h"
#include <AVEndpointKeys.h>
#include <Functiondiscoverykeys_devpkey.h>
-#include "PropertyHelper.h"
+#include <devpkey.h>
+#include <PropertyHelper.h>
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
@@ -722,6 +723,8 @@ HRESULT IsFormatSupported
return hr;
}
+ CoTaskMemFree(pKsRequestedFormat);
+
return hr;
}
@@ -1093,3 +1096,168 @@ HRESULT GetAvailiablePinInstanceCount
return hr;
}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// IsAVStream
+//
+// Check if audio device is AVStream
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+HRESULT IsAVStream
+(
+ IMMDevice* pDevice,
+ bool* pIsAVStream
+)
+{
+ HRESULT hr = S_OK;
+ wil::com_ptr_nothrow<IMMDevice> spDevnodeDevice;
+ wil::com_ptr_nothrow<IPropertyStore> spPnpProperties;
+ wil::unique_prop_variant varDeviceService;
+
+ *pIsAVStream = false;
+
+ // Find the associated PnP device
+ if (!VERIFY_SUCCEEDED(hr = GetPnpDevnodeFromMMDevice(pDevice, &spDevnodeDevice))) {
+ return hr;
+ }
+
+ // Open pnp device property store
+ if (!VERIFY_SUCCEEDED(hr = spDevnodeDevice->OpenPropertyStore(STGM_READ, &spPnpProperties))) {
+ return hr;
+ }
+
+ // Read the DEVPKEY_Device_Service
+ if (!VERIFY_SUCCEEDED(hr = spPnpProperties->GetValue((REFPROPERTYKEY)DEVPKEY_Device_Service, &varDeviceService))) {
+ return hr;
+ }
+
+ if (!VERIFY_IS_TRUE(varDeviceService.vt == VT_LPWSTR && varDeviceService.pwszVal != nullptr)) {
+ hr = E_FAIL;
+ return hr;
+ }
+
+ if (0 == _wcsicmp(varDeviceService.pwszVal, L"usbaudio") || 0 == _wcsicmp(varDeviceService.pwszVal, L"BthHFAud") || 0 == _wcsicmp(varDeviceService.pwszVal, L"BthA2dp")) {
+ *pIsAVStream = true;
+ }
+
+ return hr;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// IsBluetooth
+//
+// Check if audio device is Bluetooth
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+HRESULT IsBluetooth
+(
+ IMMDevice* pDevice,
+ bool* pIsBluetooth
+)
+{
+ HRESULT hr = S_OK;
+ wil::com_ptr_nothrow<IPropertyStore> spPropertyStore;
+ wil::unique_prop_variant varIsBluetooth;
+
+ *pIsBluetooth = false;
+
+ // Open pnp device property store
+ if (!VERIFY_SUCCEEDED(hr = pDevice->OpenPropertyStore(STGM_READ, &spPropertyStore))) {
+ return hr;
+ }
+
+ // Read the PKEY_Endpoint_IsBluetooth
+ hr = spPropertyStore->GetValue((REFPROPERTYKEY)PKEY_Endpoint_IsBluetooth, &varIsBluetooth);
+ if (hr != S_OK) {
+ return hr;
+ }
+
+ if (varIsBluetooth.vt == VT_BOOL)
+ {
+ *pIsBluetooth = varIsBluetooth.boolVal == VARIANT_TRUE ? true : false;
+ }
+
+ return hr;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// IsSideband
+//
+// Check if audio device is side band
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+HRESULT IsSideband
+(
+ IMMDevice* pDevice,
+ bool* pIsSideband
+)
+{
+ HRESULT hr = S_OK;
+ wil::com_ptr_nothrow<IPropertyStore> spPropertyStore;
+ wil::unique_prop_variant varIsSideband;
+
+ *pIsSideband = false;
+
+ // Open pnp device property store
+ if (!VERIFY_SUCCEEDED(hr = pDevice->OpenPropertyStore(STGM_READ, &spPropertyStore))) {
+ return hr;
+ }
+
+ // Read the PKEY_Endpoint_IsBluetooth
+ hr = spPropertyStore->GetValue((REFPROPERTYKEY)PKEY_Endpoint_IsSideband, &varIsSideband);
+ if (hr != S_OK) {
+ return hr;
+ }
+
+ if (varIsSideband.vt == VT_BOOL)
+ {
+ *pIsSideband = varIsSideband.boolVal == VARIANT_TRUE ? true : false;
+ }
+
+ return hr;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// GetPnpDevnodeFromMMDeivce
+//
+// Get pnp devnode from mm device
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+HRESULT GetPnpDevnodeFromMMDevice
+(
+ IMMDevice* pDevice,
+ IMMDevice** pDevnodeDevice
+)
+{
+ HRESULT hr = S_OK;
+ wil::com_ptr_nothrow<IMMDeviceEnumerator> spEnumerator;
+ wil::com_ptr_nothrow<IPropertyStore> spProps;
+ wil::com_ptr_nothrow<IMMDevice> spDevnodeAsDevice;
+ wil::com_ptr_nothrow<IPropertyStore> spDevnodeProps;
+ wil::unique_prop_variant varDevnode;
+
+ // Create an enumerator
+ if (!VERIFY_SUCCEEDED(hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void **)&spEnumerator))) {
+ return hr;
+ }
+
+ // Read the PKEY_Endpoint_Devnode
+ if (!VERIFY_SUCCEEDED(hr = pDevice->OpenPropertyStore(STGM_READ, &spProps))) {
+ return hr;
+ }
+ if (!VERIFY_SUCCEEDED(hr = spProps->GetValue(PKEY_Endpoint_Devnode, &varDevnode))) {
+ return hr;
+ }
+
+ // Get the devnode as an IMMDevice
+ if (!VERIFY_SUCCEEDED(hr = spEnumerator->GetDevice(varDevnode.pwszVal, &spDevnodeAsDevice))) {
+ return hr;
+ }
+ *pDevnodeDevice = spDevnodeAsDevice.detach();
+
+ return hr;
+}
diff --git a/audio/tests/wavetest/TestResource.cpp b/audio/tests/PinResourceHelpers/TestResource.cpp
index 67f3ca79..f3762b84 100644
--- a/audio/tests/wavetest/TestResource.cpp
+++ b/audio/tests/PinResourceHelpers/TestResource.cpp
@@ -13,8 +13,8 @@
// -------------------------------------------------------------------------------
#include "PreComp.h"
-#include "HalfApp.h"
-#include "TestResource.h"
+#include <HalfApp.h>
+#include <TestResource.h>
using namespace WEX::Logging;
using namespace WEX::TestExecution;
@@ -328,4 +328,4 @@ LPWSTR CPinTestResource::PinName(EndpointConnectorType eConnectorType)
default:
return L"UNKNOWN";
}
-} \ No newline at end of file
+}
diff --git a/audio/tests/wavetest/TestResourceHelper.h b/audio/tests/PinResourceHelpers/TestResourceHelper.h
index 24bae634..08fafa23 100644
--- a/audio/tests/wavetest/TestResourceHelper.h
+++ b/audio/tests/PinResourceHelpers/TestResourceHelper.h
@@ -13,6 +13,8 @@
// -------------------------------------------------------------------------------
#pragma once
+#include <HalfApp.h>
+
// ----------------------------------------------------------------------
HRESULT GetProcessingModesForConnector
(
@@ -68,4 +70,4 @@ HRESULT GetSupportedFormatRecordsForConnector
STACKWISE_DATAFLOW dataFlow,
ULONG* pCount,
FORMAT_RECORD** ppFormatRecords
-); \ No newline at end of file
+);
diff --git a/audio/tests/wavetest/HalfApp.h b/audio/tests/wavetest/HalfApp.h
deleted file mode 100644
index 1bf14de9..00000000
--- a/audio/tests/wavetest/HalfApp.h
+++ /dev/null
@@ -1,195 +0,0 @@
-// ------------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft. All rights reserved.
-//
-// File Name:
-//
-// HalfApp.h
-//
-// Abstract:
-//
-// CHalfApp declarations
-//
-// -------------------------------------------------------------------------------
-#pragma once
-
-#define BUF_LEN_IN_MS 1000 // 1 second
-
-class CHalfApp
-{
-public:
- // Basic pin infos
- wil::com_ptr_nothrow<IMMDevice> m_pDevice;
- wil::unique_cotaskmem_string m_pwstrDeviceId;
- wil::unique_cotaskmem_string m_pwstrDeviceFriendlyName;
- STACKWISE_DATAFLOW m_DataFlow;
- EndpointConnectorType m_ConnectorType;
- UINT m_uConnectorId;
- GUID m_Mode;
- ULONG m_cModes;
- GUID* m_pModes; // All processing modes
-
- // Formats
- wil::unique_cotaskmem_ptr<WAVEFORMATEX> m_pPreferredFormat;
- UINT32 m_u32DefaultPeriodicityInFrames;
- UINT32 m_u32FundamentalPeriodicityInFrames;
- UINT32 m_u32MinPeriodicityInFrames;
- UINT32 m_u32MaxPeriodicityInFrames;
-
- PFORMAT_RECORD m_pFormatRecords;
- ULONG m_cFormatRecords;
-
- wil::unique_cotaskmem_ptr<WAVEFORMATEX> m_pCurrentFormat;
- UINT32 m_u32CurrentDefaultPeriodicityInFrames;
- UINT32 m_u32CurrentFundamentalPeriodicityInFrames;
- UINT32 m_u32CurrentMinPeriodicityInFrames;
- UINT32 m_u32CurrentMaxPeriodicityInFrames;
-
- // Audio endpoint interfaces
- wil::com_ptr_nothrow<IAudioDeviceEndpoint> m_pAudioDeviceEndpoint;
- wil::com_ptr_nothrow<IAudioEndpoint> m_pAudioEndpoint;
- wil::com_ptr_nothrow<IAudioEndpointControl> m_pAudioEndpointControl;
- wil::com_ptr_nothrow<IAudioEndpointRT> m_pAudioEndpointRT;
-
- // Data buffer
- wil::unique_hlocal_ptr<BYTE> m_pbSineToneDataBuffer;
- DWORD m_dwSineToneDataBufferSize;
- DWORD m_dwSineToneDataBufferPosition;
-
- // Stream
- HNSTIME m_hnsPeriod = 0;
- FLOAT32 m_f32EndpointFrameRate = 0.F;
- HNSTIME m_hnsEndpointLatency = 0;
- bool m_bIsEventCapable = false;
- bool m_bStreamInitialized = false;
- volatile bool m_bStreamThreadTerminate = false;
- bool m_bYieldActive = false;
- bool m_bIsBackupTimerRequired = true;
-
- wil::unique_handle m_hStreamThread;
-
- LPTHREAD_START_ROUTINE m_pStreamRoutine = nullptr;
- wil::unique_event_nothrow m_hProcessThreadStartedEvent;
- wil::unique_event_nothrow m_hTerminate;
- wil::unique_event_nothrow m_hEndpointBufferCompleteEvent;
- wil::unique_handle m_hTimer;
-
- wil::critical_section m_CritSec;
-
- typedef enum
- {
- ET_DO_NOTHING = 0x00,
- ET_TERMINATE = 0x01,
- ET_OBJECT_BUFFER_COMPLETE = 0x02,
- ET_CLIENT_RELEASE_BUFFER = 0x04,
- ET_TIMER = 0x08,
- ET_PAUSE_PUMP = 0x10,
- ET_RESUME_PUMP = 0x20,
- } TEventType;
-
- CHalfApp(
- _In_ IMMDevice* pDevice,
- _In_ LPWSTR pwstrAudioEndpointId,
- _In_ LPWSTR pwstrAudioEndpointFriendlyName,
- _In_ STACKWISE_DATAFLOW dataFlow,
- _In_ EndpointConnectorType eConnectorType,
- _In_ UINT uConnectorId,
- _In_ GUID mode,
- _In_ ULONG cModes,
- _In_ GUID* pModes,
- _In_ ULONG cFormatRecords,
- _In_ PFORMAT_RECORD pFormatRecords,
- _In_ PWAVEFORMATEX pPreferredFormat,
- _In_ UINT32 u32DefaultPeriodicityInFrames,
- _In_ UINT32 u32FundamentalPeriodicityInFrames,
- _In_ UINT32 u32MinPeriodicityInFrames,
- _In_ UINT32 u32MaxPeriodicityInFrames
- )
- : m_DataFlow(dataFlow)
- , m_ConnectorType(eConnectorType)
- , m_uConnectorId(uConnectorId)
- , m_cModes(cModes)
- , m_cFormatRecords(cFormatRecords)
- , m_u32DefaultPeriodicityInFrames(u32DefaultPeriodicityInFrames)
- , m_u32FundamentalPeriodicityInFrames(u32FundamentalPeriodicityInFrames)
- , m_u32MinPeriodicityInFrames(u32MinPeriodicityInFrames)
- , m_u32MaxPeriodicityInFrames(u32MaxPeriodicityInFrames)
- , m_u32CurrentDefaultPeriodicityInFrames(u32DefaultPeriodicityInFrames)
- , m_u32CurrentFundamentalPeriodicityInFrames(u32FundamentalPeriodicityInFrames)
- , m_u32CurrentMinPeriodicityInFrames(u32MinPeriodicityInFrames)
- , m_u32CurrentMaxPeriodicityInFrames(u32MaxPeriodicityInFrames)
- {
- m_pDevice = pDevice;
- m_pAudioDeviceEndpoint = nullptr;
- m_pAudioEndpointControl = nullptr;
-
- m_pwstrDeviceId = wil::make_cotaskmem_string_nothrow(pwstrAudioEndpointId, wcslen(pwstrAudioEndpointId));
- m_pwstrDeviceFriendlyName = wil::make_cotaskmem_string_nothrow(pwstrAudioEndpointFriendlyName, wcslen(pwstrAudioEndpointFriendlyName));
- m_Mode = mode;
-
- m_pModes = new GUID[cModes];
- memcpy(m_pModes, pModes, sizeof(GUID)*cModes);
- m_pFormatRecords = new FORMAT_RECORD[cFormatRecords];
- memcpy(m_pFormatRecords, pFormatRecords, sizeof(FORMAT_RECORD)*cFormatRecords);
-
- CloneWaveFormat(pPreferredFormat, wil::out_param(m_pPreferredFormat));
- CloneWaveFormat(pPreferredFormat, wil::out_param(m_pCurrentFormat)); // Use preferred format as current format
- }
-
- ~CHalfApp(void)
- {
- if (m_pModes)
- delete[] m_pModes;
- if (m_pFormatRecords)
- delete[] m_pFormatRecords;
- }
-
- // Audio endpoint interfaces
- HRESULT InitializeEndpoint();
- HRESULT ReleaseEndpoint();
- HRESULT StartEndpoint();
- HRESULT StopEndpoint();
- HRESULT ResetEndpoint();
-
- // Sine tone data buffer
- HRESULT CreateSineToneDataBuffer(WAVEFORMATEX* pWfx);
- HRESULT ReleaseSineToneDataBuffer();
-
-
-
-
- // Stream
- HRESULT InitializeAndSetBuffer(HNSTIME hnsPeriod, UINT32 u32LatencyCoefficient);
- HRESULT InitializeStream(HNSTIME requestedPeriodicity, UINT32 u32LatencyCoefficient);
- HRESULT CleanupStream();
- HRESULT StartStream();
- HRESULT StopStream();
- static DWORD CALLBACK RenderStreamRoutine(PVOID lpParameter);
- static DWORD CALLBACK CaptureStreamRoutine(PVOID lpParameter);
- void SignalAndWaitForThread();
-
-
-
- HRESULT SetTimer(HANDLE timer, HNSTIME timeDuration, bool fireImmediatley);
- void CancelTimer(HANDLE timer);
- HRESULT GetPosition(UINT64* pu64Position, UINT64* pu64hnsQPCPosition);
-
- // Multiple pin instances
- HRESULT GetCurrentAvailiablePinInstanceCount(UINT32* pAvailablePinInstanceCount);
- HRESULT GetSecondHalfApp(AUDIO_SIGNALPROCESSINGMODE secondMode, CHalfApp** ppSecondHalfApp);
-
- // Only for loopback testcases
- HRESULT GetHostHalfApp(CHalfApp** ppHostHalfApp);
-};
-
-// {571BF784-A9D6-420A-BCA0-C579A8710236}
-DEFINE_GUID(IID_IHalfAppContainer,
- 0x571bf784, 0xa9d6, 0x420a, 0xbc, 0xa0, 0xc5, 0x79, 0xa8, 071, 0x02, 0x36);
-
-DECLARE_INTERFACE_IID_(
-IHalfAppContainer,
-IUnknown,
-"571BF784-A9D6-420A-BCA0-C579A8710236")
-{
- STDMETHOD(GetHalfApp)(THIS_ CHalfApp ** ppHalfApp) PURE;
-};
diff --git a/audio/tests/wavetest/PreComp.h b/audio/tests/wavetest/PreComp.h
index 2044d6b1..76210090 100644
--- a/audio/tests/wavetest/PreComp.h
+++ b/audio/tests/wavetest/PreComp.h
@@ -24,13 +24,11 @@
#include <Audioclient.h>
#include <mmdeviceapi.h>
#include <mmdeviceapip.h>
-#include <devicetopology.h>
#include <devicetopologyp.h>
#include <propvarutil.h>
#include <wil\com.h>
-#include <winioctl.h>
#include <KsLib.h>
#include <Waveutil.h>
#include <aecommon.h>
@@ -47,108 +45,3 @@
#define WARN(log, ...) BasicLogPrintf( log, XWARN, 1, __VA_ARGS__ )
#define BLOCK(log, ...) BasicLogPrintf( log, XBLOCK, 1, __VA_ARGS__ )
#define ERR(log, ...) BasicLogPrintf( log, XFAIL, 1, __VA_ARGS__ )
-
-// ------------------------------------------------------------------------------
-// Data flow
-enum STACKWISE_DATAFLOW { render, capture };
-
-// ------------------------------------------------------------------------------
-// Structs used to hold results of format records
-typedef struct
-{
- WAVEFORMATEXTENSIBLE wfxEx;
- UINT32 fundamentalPeriodInFrames;
- UINT32 defaultPeriodInFrames;
- UINT32 minPeriodInFrames;
- UINT32 maxPeriodInFrames;
- UINT32 maxPeriodInFramesExtended;
-} FORMAT_RECORD, *PFORMAT_RECORD;
-
-// ----------------------------------------------------------
-// Parameters for test sine tone
-#define TEST_AMPLITUDE 1.0f
-#define TEST_FREQUENCY 200.0f
-
-// ----------------------------------------------------------
-// Predefined format list for offload streaming
-#define COUNT_FORMATS 4
-
-static WAVEFORMATEXTENSIBLE ListofFormats[COUNT_FORMATS] =
-{
- // 1
- {
- // Format
- {
- WAVE_FORMAT_EXTENSIBLE, // wFormatTag
- 2, // nChannels
- 44100, // nSamplesPerSec
- 176400, // nAvgBytesPerSec
- 4, // nBlockAlign
- 16, // wBitsPerSample
- 22 // cbSize
- },
- // Samples
- {
- 16 // wValidBitsPerSample
- },
- KSAUDIO_SPEAKER_STEREO, // dwChannelMask
- KSDATAFORMAT_SUBTYPE_PCM // SubFormat
- },
- // 2
- {
- // Format
- {
- WAVE_FORMAT_EXTENSIBLE, // wFormatTag
- 2, // nChannels
- 48000, // nSamplesPerSec
- 192000, // nAvgBytesPerSec
- 4, // nBlockAlign
- 16, // wBitsPerSample
- 22 // cbSize
- },
- // Samples
- {
- 16 // wValidBitsPerSample
- },
- KSAUDIO_SPEAKER_STEREO, // dwChannelMask
- KSDATAFORMAT_SUBTYPE_PCM // SubFormat
- },
- // 3
- {
- // Format
- {
- WAVE_FORMAT_EXTENSIBLE, // wFormatTag
- 2, // nChannels
- 88200, // nSamplesPerSec
- 352800, // nAvgBytesPerSec
- 4, // nBlockAlign
- 16, // wBitsPerSample
- 22 // cbSize
- },
- // Samples
- {
- 16 // wValidBitsPerSample
- },
- KSAUDIO_SPEAKER_STEREO, // dwChannelMask
- KSDATAFORMAT_SUBTYPE_PCM // SubFormat
- },
- // 4
- {
- // Format
- {
- WAVE_FORMAT_EXTENSIBLE, // wFormatTag
- 2, // nChannels
- 96000, // nSamplesPerSec
- 384000, // nAvgBytesPerSec
- 4, // nBlockAlign
- 16, // wBitsPerSample
- 22 // cbSize
- },
- // Samples
- {
- 16 // wValidBitsPerSample
- },
- KSAUDIO_SPEAKER_STEREO, // dwChannelMask
- KSDATAFORMAT_SUBTYPE_PCM // SubFormat
- },
-}; \ No newline at end of file
diff --git a/audio/tests/wavetest/PropertyHelper.h b/audio/tests/wavetest/PropertyHelper.h
deleted file mode 100644
index 9f01a9a7..00000000
--- a/audio/tests/wavetest/PropertyHelper.h
+++ /dev/null
@@ -1,190 +0,0 @@
-// ------------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft. All rights reserved.
-//
-// Module Name:
-//
-// PropertyHelpers.h
-//
-// Abstract:
-//
-// Header for common helpers/defines of property
-//
-// -------------------------------------------------------------------------------
-#pragma once
-
-#define kSystemDefaultPeriod 100000 // 10 milliseconds
-#define kSystemMinPeriodForNonRTCapableEndpoints 20000 // 2 milliseconds
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// ----------------------------------------------------------------------
-HRESULT GetConnectorId
-(
- IMMDevice* pDevice,
- EndpointConnectorType eConnectorType,
- bool* hasConnector,
- UINT* pConnectorId
-);
-
-// ----------------------------------------------------------------------
-HRESULT GetEndpointFriendlyName
-(
- IMMDevice* pDevice,
- LPWSTR* ppwszEndpointName
-);
-
-// ----------------------------------------------------------------------
-HRESULT GetAudioFilterAsDevice
-(
- IMMDevice* pDevice,
- IMMDevice** ppAudioFilterAsDevice
-);
-
-// ----------------------------------------------------------------------
-HRESULT GetCachedProcessingModes
-(
- IMMDevice* pDevice,
- EndpointConnectorType eConnectorType,
- ULONG *pCount,
- AUDIO_SIGNALPROCESSINGMODE **ppModes
-);
-
-
-
-
-
-
-
-
-
-
-
-
-// ----------------------------------------------------------------------
-HRESULT GetProcessingModes
-(
- IMMDevice* pDevice,
- UINT pinId,
- ULONG *pCount,
- AUDIO_SIGNALPROCESSINGMODE **ppModes
-);
-
-// ----------------------------------------------------------------------
-HRESULT GetCachedSupportedFormatRecords
-(
- IMMDevice* pDevice,
- EndpointConnectorType eConnectorType,
- AUDIO_SIGNALPROCESSINGMODE mode,
- ULONG *pCount,
- FORMAT_RECORD **ppFormatRecords
-);
-
-
-
-
-
-
-
-
-
-
-
-
-
-// ----------------------------------------------------------------------
-HRESULT GetSupportedFormatRecords
-(
- IMMDevice* pDevice,
- UINT pinId,
- EndpointConnectorType eConnectorType,
- AUDIO_SIGNALPROCESSINGMODE mode,
- STACKWISE_DATAFLOW dataFlow,
- ULONG *pCount,
- FORMAT_RECORD **ppFormatRecords
-);
-
-// ----------------------------------------------------------------------
-HRESULT IsFormatSupported
-(
- IMMDevice* pDevice,
- UINT pinId,
- WAVEFORMATEX *pWfx,
- BOOL* pbSupported
-);
-
-// ----------------------------------------------------------------------
-HRESULT DiscoverPeriodicityCharacteristicsForFormat
-(
- IMMDevice* pDevice,
- EndpointConnectorType eConnectorType,
- AUDIO_SIGNALPROCESSINGMODE mode,
- WAVEFORMATEX *pWfx,
- STACKWISE_DATAFLOW dataFlow,
- UINT32 *pDefaultPeriodicityInFrames,
- UINT32 *pFundamentalPeriodicityInFrames,
- UINT32 *pMinPeriodicityInFrames,
- UINT32 *pMaxPeriodicityInFrames,
- UINT32 *pMaxPeriodicityInFramesExtended
-);
-
-// ----------------------------------------------------------------------
-HRESULT CheckConnectorSupportForPeriodicity
-(
- IMMDevice* pDevice,
- EndpointConnectorType eConnectorType,
- AUDIO_SIGNALPROCESSINGMODE mode,
- WAVEFORMATEX *pWfx,
- STACKWISE_DATAFLOW dataFlow,
- HNSTIME RequestedPeriodicity,
- UINT32 *pActualPeriodicityInFrames
-);
-
-// ----------------------------------------------------------------------
-HRESULT GetCachedDefaultFormat
-(
- IMMDevice* pDevice,
- EndpointConnectorType eConnectorType,
- WAVEFORMATEX** ppDefaultFormat
-);
-
-// ----------------------------------------------------------------------
-HRESULT GetProposedFormatForProcessingMode
-(
- IMMDevice* pDevice,
- UINT pinId,
- AUDIO_SIGNALPROCESSINGMODE mode,
- WAVEFORMATEX **ppProposedFormat
-);
-
-// ----------------------------------------------------------------------
-HRESULT GetAvailiablePinInstanceCount
-(
- IMMDevice* pDevice,
- UINT pinId,
- UINT32* pAvailablePinInstanceCount
-);
diff --git a/audio/tests/wavetest/TestResource.h b/audio/tests/wavetest/TestResource.h
deleted file mode 100644
index 49dee5a5..00000000
--- a/audio/tests/wavetest/TestResource.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// ------------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft. All rights reserved.
-//
-// File Name:
-//
-// TestResource.h
-//
-// Abstract:
-//
-// TAEF Test Resource
-//
-// -------------------------------------------------------------------------------
-#include "WaveTestTaef.h"
-
-class CPinTestResource :
- public WEX::TestExecution::ITestResource,
- public IHalfAppContainer
-{
-public:
- //IUnknown
- STDMETHODIMP_(ULONG) AddRef();
- STDMETHODIMP_(ULONG) Release();
- STDMETHODIMP QueryInterface(
- __in REFIID riid,
- __deref_out VOID **ppvObject
- );
- // ITestResouce
- STDMETHODIMP GetGuid(GUID* pGuid);
- STDMETHODIMP SetGuid(GUID guid);
- STDMETHODIMP GetValue(BSTR name, BSTR* pValue);
- STDMETHODIMP SetValue(BSTR name, BSTR value);
-
- //IHalfAppContainer
- STDMETHODIMP GetHalfApp(CHalfApp ** ppHalfApp);
-
- static HRESULT STDMETHODCALLTYPE CreateInstance(
- CHalfApp * pHalf,
- REFGUID guid,
- WEX::TestExecution::ITestResource ** ppOut
- );
-
-private:
-
- CPinTestResource();
- ~CPinTestResource();
-
- HRESULT STDMETHODCALLTYPE Initialize(
- CHalfApp * pHalf,
- REFGUID guid
- );
-
- LPWSTR ModeName(REFGUID guidMode);
- LPWSTR PinName(EndpointConnectorType eConnectorType);
-
- CComBSTR m_szType;
- CComBSTR m_szName;
- CComBSTR m_szId;
- CComBSTR m_szMode;
- CComBSTR m_szPin;
-
- CAutoPtr<CHalfApp> m_spHalfApp;
-
- ULONG m_cRef;
- GUID m_guid;
-}; \ No newline at end of file
diff --git a/audio/tests/wavetest/TestResourceBuild.cpp b/audio/tests/wavetest/TestResourceBuild.cpp
index 51cce52d..5ca2ff0d 100644
--- a/audio/tests/wavetest/TestResourceBuild.cpp
+++ b/audio/tests/wavetest/TestResourceBuild.cpp
@@ -12,8 +12,8 @@
//
// ------------------------------------------------------------------------------
#include "PreComp.h"
-#include "TestResource.h"
-#include "PropertyHelper.h"
+#include <TestResource.h>
+#include <PropertyHelper.h>
using namespace WEX::Common;
using namespace WEX::Logging;
@@ -30,32 +30,18 @@ using namespace WEX::TestExecution;
HRESULT CreateTestResource
(
ResourceList& resourceList,
- LPWSTR deviceId,
- LPWSTR deviceName,
- IMMDevice* pDevice,
- STACKWISE_DATAFLOW dataFlow,
- EndpointConnectorType eConnectorType,
- UINT uConnectorId,
- AUDIO_SIGNALPROCESSINGMODE mode,
- ULONG cModes,
- AUDIO_SIGNALPROCESSINGMODE* pModes,
- ULONG cFormatRecords,
- PFORMAT_RECORD pFormatRecords,
- PWAVEFORMATEX pPreferredFormat,
- UINT32 defaultPeriodicityInFrames,
- UINT32 fundamentalPeriodicityInFrames,
- UINT32 minPeriodicityInFrames,
- UINT32 maxPeriodicityInFrames
+ DeviceDescriptor descriptor
)
{
HRESULT hr = S_OK;
+
CComHeapPtr<CHalfApp> spHalfApp;
wil::com_ptr_nothrow<ITestResource> spTestResource;
GUID ResourceGUID;
CComBSTR szResourceName;
// Create HalfApp
- spHalfApp.Attach(new CHalfApp(pDevice, deviceId, deviceName, dataFlow, eConnectorType, uConnectorId, mode, cModes, pModes, cFormatRecords, pFormatRecords, pPreferredFormat, defaultPeriodicityInFrames, fundamentalPeriodicityInFrames, minPeriodicityInFrames, maxPeriodicityInFrames));
+ spHalfApp.Attach(new CHalfApp(descriptor));
if (!VERIFY_IS_NOT_NULL(spHalfApp)) {
hr = E_OUTOFMEMORY;
return hr;
@@ -327,6 +313,7 @@ HRESULT AddTestResourceForConnector
UINT32 u32MinPeriodicityInFrames;
UINT32 u32MaxPeriodicityInFrames;
UINT32 u32MaxPeriodicityInFramesExtended;
+ bool isAVStream = false;
// Get connector id
if (!VERIFY_SUCCEEDED(hr = GetConnectorId(pDevice, eConnectorType, &bHasConnector, &uConnectorId))) {
@@ -338,6 +325,7 @@ HRESULT AddTestResourceForConnector
Log::Comment(String().Format(L"Adding Test Resource for pin [%u]:", (uConnectorId & PARTID_MASK)));
+
// Get all signal processing modes for connector
if (!VERIFY_SUCCEEDED(hr = GetProcessingModesForConnector(pDevice, uConnectorId, eConnectorType, &cModes, &spModes))) {
return hr;
@@ -345,6 +333,7 @@ HRESULT AddTestResourceForConnector
// Loop through each mode, get preferred format and list of formats and create test resource for each mode
for (ULONG i = 0; i < cModes; i++) {
+
mode = spModes[i];
if (!VERIFY_SUCCEEDED(hr = GetSupportedFormatRecordsForConnector(pDevice, uConnectorId, eConnectorType, mode, dataFlow, &cFormatRecords, &spFormatRecords))) {
@@ -358,8 +347,32 @@ HRESULT AddTestResourceForConnector
if (!VERIFY_SUCCEEDED(hr = GetPreferredFormatPeriodicityCharacteristicsForConnector(pDevice, eConnectorType, mode, dataFlow, pPreferredFormat.get(), cFormatRecords, spFormatRecords, &u32DefaultPeriodicityInFrames, &u32FundamentalPeriodicityInFrames, &u32MinPeriodicityInFrames, &u32MaxPeriodicityInFrames, &u32MaxPeriodicityInFramesExtended))) {
return hr;
}
-
- if (!VERIFY_SUCCEEDED(hr = CreateTestResource(resourceList, deviceId, deviceName, pDevice, dataFlow, eConnectorType, uConnectorId, mode, cModes, spModes, cFormatRecords, spFormatRecords, pPreferredFormat.get(), u32DefaultPeriodicityInFrames, u32FundamentalPeriodicityInFrames, u32MinPeriodicityInFrames, u32MaxPeriodicityInFrames))) {
+
+ // Check if audio endpoint is AVStream
+ if (!VERIFY_SUCCEEDED(hr = IsAVStream(pDevice, &isAVStream))) {
+ return hr;
+ }
+
+ DeviceDescriptor descriptor = { 0 };
+ descriptor.pDevice = pDevice;
+ descriptor.pwstrAudioEndpointId = deviceId;
+ descriptor.pwstrAudioEndpointFriendlyName = deviceName;
+ descriptor.dataFlow = dataFlow;
+ descriptor.eConnectorType = eConnectorType;
+ descriptor.uConnectorId = uConnectorId;
+ descriptor.mode = mode;
+ descriptor.cModes = cModes;
+ descriptor.pModes = spModes;
+ descriptor.cFormatRecords = cFormatRecords;
+ descriptor.pFormatRecords = spFormatRecords;
+ descriptor.pPreferredFormat = pPreferredFormat.get();
+ descriptor.u32DefaultPeriodicityInFrames = u32DefaultPeriodicityInFrames;
+ descriptor.u32FundamentalPeriodicityInFrames = u32FundamentalPeriodicityInFrames;
+ descriptor.u32MinPeriodicityInFrames = u32MinPeriodicityInFrames;
+ descriptor.u32MaxPeriodicityInFrames = u32MaxPeriodicityInFrames;
+ descriptor.bIsAVStream = isAVStream;
+
+ if (!VERIFY_SUCCEEDED(hr = CreateTestResource(resourceList, descriptor))) {
return hr;
}
}
diff --git a/audio/tests/wavetest/WaveTestTaef.cpp b/audio/tests/wavetest/WaveTestTaef.cpp
index dacf44ab..be5d47f3 100644
--- a/audio/tests/wavetest/WaveTestTaef.cpp
+++ b/audio/tests/wavetest/WaveTestTaef.cpp
@@ -164,7 +164,7 @@ void WDMAudio::WaveTest::TAEF_StreamMultipleModes()
RUN_TEST_CASE(Test_StreamMultipleModes)
}
-void WDMAudio::WaveTest::TAEF_VerifyPinSupportsPullMode()
+void WDMAudio::WaveTest::TAEF_VerifyPinWaveRTConformance()
{
- RUN_TEST_CASE(Test_VerifyPinSupportsPullMode)
-} \ No newline at end of file
+ RUN_TEST_CASE(Test_VerifyPinWaveRTConformance)
+}
diff --git a/audio/tests/wavetest/WaveTestTaef.h b/audio/tests/wavetest/WaveTestTaef.h
index a8d38305..8c87a7f8 100644
--- a/audio/tests/wavetest/WaveTestTaef.h
+++ b/audio/tests/wavetest/WaveTestTaef.h
@@ -13,7 +13,7 @@
// -------------------------------------------------------------------------------
#pragma once
-#include "HalfApp.h"
+#include <HalfApp.h>
extern IBasicLog* g_pBasicLog;
@@ -41,6 +41,7 @@ namespace WDMAudio
TEST_CLASS_PROPERTY(L"Kits.SupportedOS", L"Windows v10.0 Server x64")
TEST_CLASS_PROPERTY(L"Kits.MinRelease", L"19H1")
TEST_CLASS_PROPERTY(L"Kits.CorePackageComposition", L"Full")
+ TEST_CLASS_PROPERTY(L"Kits.CorePackageComposition", L"OnecoreUAP")
TEST_CLASS_PROPERTY(L"Kits.IsInProc", L"True")
TEST_CLASS_PROPERTY(L"Kits.Parameter", L"DeviceID")
TEST_CLASS_PROPERTY(L"Kits.Parameter.DeviceID.Description", L"Device id of device under test")
@@ -109,7 +110,7 @@ namespace WDMAudio
TEST_METHOD_PROPERTY(L"ResourceSelection", L"@Id = '*RAW' OR @Id = '*DEFAULT'")
END_TEST_METHOD()
- BEGIN_TEST_METHOD(TAEF_VerifyPinSupportsPullMode)
+ BEGIN_TEST_METHOD(TAEF_VerifyPinWaveRTConformance)
TEST_METHOD_PROPERTY(L"HCKCategory", L"Functional")
TEST_METHOD_PROPERTY(L"HCKCategory", L"Certification")
TEST_METHOD_PROPERTY(L"TestClassification:Scope", L"Feature")
diff --git a/audio/tests/wavetest/comptest.cpp b/audio/tests/wavetest/comptest.cpp
index ef41972c..db823156 100644
--- a/audio/tests/wavetest/comptest.cpp
+++ b/audio/tests/wavetest/comptest.cpp
@@ -17,8 +17,8 @@
#include "tests.h"
// ------------------------------------------------------------------------------
-// Test_VerifyPinSupportsPullMode: Test the requirement that WaveRT drivers must support pull mode audio streaming technology.
-void Test_VerifyPinSupportsPullMode(void)
+// Test_VerifyPinSupportsPullMode: Test the requirement that new drivers must be WaveRT and WaveRT drivers must support event driven audio streaming technology.
+void Test_VerifyPinWaveRTConformance(void)
{
CHalfApp* pHalfApp = g_pWaveTest->m_pHalf;
BOOL bIsRTCapable = false;
@@ -28,10 +28,17 @@ void Test_VerifyPinSupportsPullMode(void)
VERIFY_SUCCEEDED(pHalfApp->m_pAudioDeviceEndpoint->GetRTCaps(&bIsRTCapable));
- // Only require pull mode for WaveRT drivers
+ // Check for our new requirement - new drivers must be WaveRT. Here we skip the test on AVStream (UAC1/HFP/A2dp)
+ // For other old drivers that are not WaveRT, may issue Errata to cover the failure.
+ if (!pHalfApp->m_bIsAVStream)
+ {
+ VERIFY_IS_TRUE(bIsRTCapable);
+ }
+
+ // Only require event driven for WaveRT drivers
if (bIsRTCapable)
{
VERIFY_SUCCEEDED(pHalfApp->m_pAudioDeviceEndpoint->GetEventDrivenCapable(&bIsEventCapable));
VERIFY_IS_TRUE(bIsEventCapable);
}
-} \ No newline at end of file
+}
diff --git a/audio/tests/wavetest/tests.h b/audio/tests/wavetest/tests.h
index 38a6aaa1..e3ae0691 100644
--- a/audio/tests/wavetest/tests.h
+++ b/audio/tests/wavetest/tests.h
@@ -24,4 +24,4 @@ void Test_LoopbackStreamDifferentFormat(void);
void Test_StreamMultipleModes(void);
// Compliance test
-void Test_VerifyPinSupportsPullMode(void); \ No newline at end of file
+void Test_VerifyPinWaveRTConformance(void); \ No newline at end of file
diff --git a/avstream/avscamera/Package/package.VcxProj b/avstream/avscamera/Package/package.VcxProj
index 5b8aa6ef..32eb3354 100644
--- a/avstream/avscamera/Package/package.VcxProj
+++ b/avstream/avscamera/Package/package.VcxProj
@@ -42,22 +42,18 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
- <DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
- <DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
- <DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
- <DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -83,7 +79,25 @@
<VerifyDrivers />
<VerifyFlags>133563</VerifyFlags>
</PropertyGroup>
- <ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
diff --git a/avstream/avscamera/README.md b/avstream/avscamera/README.md
index 50e2fab1..da8e8d65 100644
--- a/avstream/avscamera/README.md
+++ b/avstream/avscamera/README.md
@@ -6,17 +6,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: AvsCamera - AVStream Camera Sample Driver
- platform: WDM
- language: cpp
- category: Camera AVStream
- description: Provides a pin-centric AVStream capture driver for a simulated front and back camera that performs simulated captures at 320x240 or 640x480 in RGB24, RGB32, YUY2 and NV12 formats at various frame rates.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620184
---->
-
# AvsCamera - AVStream Camera Sample Driver
The AvsCamera sample provides a pin-centric AVStream capture driver for a simulated front and back camera. The driver performs simulated captures at 320x240 or 640x480 in RGB24, RGB32, YUY2 and NV12 formats at various frame rates. The purpose of the sample is to demonstrate how to write a fully functional AVStream camera driver.
diff --git a/avstream/avscamera/common/MetadataInternal.h b/avstream/avscamera/common/MetadataInternal.h
index 2f789a02..0433fda6 100644
--- a/avstream/avscamera/common/MetadataInternal.h
+++ b/avstream/avscamera/common/MetadataInternal.h
@@ -19,7 +19,7 @@
**************************************************************************/
#pragma once
-
+#if (NTDDI_VERSION >= NTDDI_WINBLUE)
enum MetadataId_Custom
{
@@ -373,3 +373,4 @@ struct _KSCAMERA_ATTRIBUTES_HEADER
ULONG PinId; // The Pin this payload affects.
} KSCAMERA_ATTRIBUTES_HEADER, *PKSCAMERA_ATTRIBUTES_HEADER;
#endif
+#endif // (NTDDI_VERSION >= NTDDI_WINBLUE)
diff --git a/avstream/avscamera/mft0/MFT0Impl.cpp b/avstream/avscamera/mft0/MFT0Impl.cpp
index 892160d4..26d40f99 100644
--- a/avstream/avscamera/mft0/MFT0Impl.cpp
+++ b/avstream/avscamera/mft0/MFT0Impl.cpp
@@ -1046,13 +1046,14 @@ STDMETHODIMP CSocMft0::ProcessOutput(
{
return MF_E_TRANSFORM_NEED_MORE_INPUT;
}
-
+#if (NTDDI_VERSION >= NTDDI_WINBLUE)
hr = ProcessMetadata();
if (FAILED(hr))
{
//Log the failure
hr = S_OK;
}
+#endif // (NTDDI_VERSION >= NTDDI_WINBLUE)
hr = CreateOutputSample(&pOutputSamples[0].pSample);
if (FAILED(hr))
{
@@ -1404,6 +1405,7 @@ HRESULT CSocMft0::GetPreviewMediaType(
return MF_E_NOT_FOUND;
}
+#if (NTDDI_VERSION >= NTDDI_WINBLUE)
/////////////////////////////////////////////////////////////////////
//
// Handle the Metadata with the buffer
@@ -1820,7 +1822,7 @@ HRESULT CSocMft0::ParseMetadata_ImageAggregation(
}
return S_OK;
}
-
+#endif // (NTDDI_VERSION >= NTDDI_WINBLUE)
struct HistogramData
{
HistogramDataHeader Header;
@@ -1863,6 +1865,7 @@ struct Histogram
}
};
+#if (NTDDI_VERSION >= NTDDI_WINBLUE)
#define MF_HISTOGRAM_RGB (MF_HISTOGRAM_CHANNEL_R | MF_HISTOGRAM_CHANNEL_G | MF_HISTOGRAM_CHANNEL_B )
#define MF_HISTOGRAM_YCrCb (MF_HISTOGRAM_CHANNEL_Y | MF_HISTOGRAM_CHANNEL_Cr | MF_HISTOGRAM_CHANNEL_Cb)
@@ -1947,14 +1950,14 @@ HRESULT CSocMft0::ParseMetadata_FaceDetection(
}
PMETADATA_FACEDATA pFaceData = (PMETADATA_FACEDATA)(pFaceHeader + 1);
UINT32 cbRectSize = sizeof(FaceRectInfoBlobHeader) + (sizeof(FaceRectInfo) * (pFaceHeader->Count));
- BYTE *pRectBuf = new BYTE[cbRectSize];
+ BYTE *pRectBuf = new (std::nothrow) BYTE[cbRectSize];
if (pRectBuf == NULL)
{
return E_OUTOFMEMORY;
}
UINT32 cbCharSize = sizeof(FaceCharacterizationBlobHeader) + (sizeof(FaceCharacterization) * (pFaceHeader->Count));
- BYTE *pCharBuf = new BYTE[cbCharSize];
+ BYTE *pCharBuf = new (std::nothrow) BYTE[cbCharSize];
if (pCharBuf == NULL)
{
delete[] pRectBuf;
@@ -1999,11 +2002,13 @@ HRESULT CSocMft0::ParseMetadata_FaceDetection(
goto done;
}
+#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
// Include characterization data if any of the associated bits were set.
if (pFaceHeader->Flags & KSCAMERA_EXTENDEDPROP_FACEDETECTION_ADVANCED_MASK)
{
hr = pMetaDataAttributes->SetBlob(MF_CAPTURE_METADATA_FACEROICHARACTERIZATIONS, pCharBuf, cbCharSize);
}
+#endif // (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
done:
delete[] pRectBuf;
@@ -2011,7 +2016,7 @@ done:
return hr;
}
-
+#endif // (NTDDI_VERSION >= NTDDI_WINBLUE)
HRESULT CSocMft0::FillBufferLengthFromMediaType(
_In_ IMFMediaType *pPreviewType,
_Inout_ IMFMediaBuffer *pBuffer
diff --git a/avstream/avscamera/mft0/MFT0Impl.h b/avstream/avscamera/mft0/MFT0Impl.h
index a73e8c0d..9427dd7d 100644
--- a/avstream/avscamera/mft0/MFT0Impl.h
+++ b/avstream/avscamera/mft0/MFT0Impl.h
@@ -246,7 +246,7 @@ protected:
HRESULT GetPreviewMediaType(
_Outptr_result_maybenull_ IMFMediaType **ppType
);
-
+#if (NTDDI_VERSION >= NTDDI_WINBLUE)
HRESULT ProcessMetadata();
HRESULT ParseMetadata_PreviewAggregation(
@@ -268,7 +268,7 @@ protected:
_In_ PKSCAMERA_METADATA_ITEMHEADER pItem,
_In_ IMFAttributes *pMetaDataAttributes
);
-
+#endif // (NTDDI_VERSION >= NTDDI_WINBLUE)
HRESULT FillBufferLengthFromMediaType(
_In_ IMFMediaType *pPreviewType,
_Inout_ IMFMediaBuffer *pBuffer
diff --git a/avstream/avscamera/mft0/README.md b/avstream/avscamera/mft0/README.md
deleted file mode 100644
index e2189bdc..00000000
--- a/avstream/avscamera/mft0/README.md
+++ /dev/null
@@ -1,33 +0,0 @@
----
-page_type: sample
-description: "Provides a pin-centric AVStream capture driver for a simulated front and back camera that performs simulated captures."
-languages:
-- cpp
-products:
-- windows
----
-
-<!---
- name: AvsCamera - AVStream Camera Sample Driver
- platform: WDM
- language: cpp
- category: Camera AVStream
- description: Provides a pin-centric AVStream capture driver for a simulated front and back camera that performs simulated captures at 320x240 or 640x480 in RGB24, RGB32, YUY2 and NV12 formats at various frame rates.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620184
---->
-
-# AvsCamera: AVStream Camera Sample Driver
-
-The AvsCamera sample provides a pin-centric AVStream capture driver for a simulated front and back camera. The driver performs simulated captures at 320x240 or 640x480 in RGB24, RGB32, YUY2 and NV12 formats at various frame rates. The purpose of the sample is to demonstrate how to write a fully functional AVStream camera driver.
-
-This sample features strong parameter validation and overflow detection. It provides validation and simulation logic for all advanced camera controls in the CCaptureFilter class. A real camera driver would replace the filter automation table and CSensor and CSynthesizer class hierarchies to produce a new camera driver.
-
-The sample comes with its own MFT0 called AvsCameraMft0.dll. This MFT0 is used to parse metadata supplied in the AvsCamera driver samples. The metadata communications from the driver is primarily a private channel to its MFT0. The MFT0 is responsible for reformatting that information for the capture pipeline.
-
-## Universal Windows Driver Compliant
-
-This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP. The sample works on 32-bit and 64-bit x86, amd64 and arm platforms. Once installed, the simulated camera should show in the Windows Inbox camera app.
-
-## Building the sample
-
-The AvsCamera sample can be built by opening the AvsCamera.sln solution file. A successful build produces AvsCamera.sys, AvsCameraMft0.dll, AvsCamera.inf and AvsCamera.cat.
diff --git a/avstream/avscamera/mft0/stdafx.h b/avstream/avscamera/mft0/stdafx.h
index ef768c0b..6d784805 100644
--- a/avstream/avscamera/mft0/stdafx.h
+++ b/avstream/avscamera/mft0/stdafx.h
@@ -16,9 +16,16 @@
#endif
#include "targetver.h"
+#if (NTDDI_VERSION >= NTDDI_WIN10_VB)
+#pragma message("MFT0 is deprecated for this target Windows version and beyond- Change project settings to target an older version of Windows")
+#endif
-#include <wrl.h>
+#if (NTDDI_VERSION <= NTDDI_WIN7)
+// TODO: disable the MFT0 conditional to the target system version
+#pragma message("MFT0 is in not supported in this target Windows version - Change project settings to target a newer version of Windows")
+#endif
+#include <wrl.h>
#include <initguid.h>
#include <mfapi.h>
#include <mfidl.h>
diff --git a/avstream/avscamera/sys/AvsCamera.cpp b/avstream/avscamera/sys/AvsCamera.cpp
index 3563b3dd..3c51323f 100644
--- a/avstream/avscamera/sys/AvsCamera.cpp
+++ b/avstream/avscamera/sys/AvsCamera.cpp
@@ -29,13 +29,7 @@ PVOID operator new
POOL_TYPE poolType
)
{
- PVOID result = ExAllocatePoolWithTag(poolType,iSize,'wNCK');
-
- if (result) {
- RtlZeroMemory(result,iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType,iSize,'wNCK');
}
PVOID operator new
@@ -48,13 +42,7 @@ PVOID operator new
ULONG tag
)
{
- PVOID result = ExAllocatePoolWithTag(poolType,iSize,tag);
-
- if (result) {
- RtlZeroMemory(result,iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType,iSize,tag);
}
PVOID
@@ -67,14 +55,7 @@ operator new[](
ULONG tag
)
{
- PVOID result = ExAllocatePoolWithTag(poolType, iSize, tag);
-
- if (result)
- {
- RtlZeroMemory(result, iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType, iSize, tag);
}
/*++
diff --git a/avstream/avscamera/sys/AvsCamera.vcxproj b/avstream/avscamera/sys/AvsCamera.vcxproj
index 326b1848..3c78ef44 100644
--- a/avstream/avscamera/sys/AvsCamera.vcxproj
+++ b/avstream/avscamera/sys/AvsCamera.vcxproj
@@ -167,6 +167,9 @@
<Link>
<AdditionalOptions>%(AdditionalOptions) -merge:PAGECONST=PAGE</AdditionalOptions>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha265</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -178,6 +181,9 @@
<Link>
<AdditionalOptions>%(AdditionalOptions) -merge:PAGECONST=PAGE</AdditionalOptions>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha265</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -189,6 +195,9 @@
<Link>
<AdditionalOptions>%(AdditionalOptions) -merge:PAGECONST=PAGE</AdditionalOptions>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha265</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -200,6 +209,9 @@
<Link>
<AdditionalOptions>%(AdditionalOptions) -merge:PAGECONST=PAGE</AdditionalOptions>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha265</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="AvsCamera.cpp" />
@@ -232,7 +244,7 @@
<ResourceCompile Include="AvsCamera.rc" />
</ItemGroup>
<ItemGroup>
- <Inf Exclude="@(Inf)" Include="*.inf" />
+ <Inf Exclude="@(Inf)" Include="*.inf;*.inx" />
<FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
</ItemGroup>
<ItemGroup>
diff --git a/avstream/avscamera/sys/AvsCameraFilter.cpp b/avstream/avscamera/sys/AvsCameraFilter.cpp
index af25b691..1a41997a 100644
--- a/avstream/avscamera/sys/AvsCameraFilter.cpp
+++ b/avstream/avscamera/sys/AvsCameraFilter.cpp
@@ -221,7 +221,7 @@ DEFINE_KSPROPERTY_TABLE(ExtendedPropertyItems)
CCaptureFilter::SetRoiIspControl,
NULL, 0, NULL, NULL, 0
),
- DEFINE_PROP_ITEM(CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_ZOOM, CExtendedVidProcSetting, Zoom),
+ DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_ZOOM, CExtendedVidProcSetting, Zoom),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOHDR, CExtendedProperty, VideoHDR ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_VFR, CExtendedProperty, VFR ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_ISO_ADVANCED, CExtendedVidProcSetting, IsoAdvanced ),
@@ -230,7 +230,8 @@ DEFINE_KSPROPERTY_TABLE(ExtendedPropertyItems)
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_OIS, CExtendedProperty, OpticalImageStabilization ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_ADVANCEDPHOTO, CExtendedProperty, AdvancedPhoto ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_PROFILE, CExtendedProfile, CameraProfile ),
- DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOTEMPORALDENOISING, CExtendedProperty, VideoTemporalDenoising)
+ DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOTEMPORALDENOISING, CExtendedProperty, VideoTemporalDenoising),
+ DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_RELATIVEPANELOPTIMIZATION, CExtendedProperty, RelativePanel)
};
// Front-facing cameras often have limited capabilities. One way to express that is to use a restricted automation table such as this one.
@@ -244,6 +245,7 @@ DEFINE_KSPROPERTY_TABLE(ExtendedPropertyItemsFFC)
DEFINE_PROP_ITEM_NO_SET( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_MAXVIDFPS_PHOTORES, CExtendedMaxVideoFpsForPhotoRes, MaxVideoFpsForPhotoRes ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_SCENEMODE, CExtendedProperty, SceneMode ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_TORCHMODE, CExtendedProperty, TorchMode ),
+ DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_IRTORCHMODE, CExtendedVidProcSetting, IRTorch ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_OPTIMIZATIONHINT, CExtendedProperty, OptimizationHint ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_WHITEBALANCEMODE, CExtendedVidProcSetting, WhiteBalance ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_EXPOSUREMODE, CExtendedVidProcSetting, Exposure ),
@@ -258,11 +260,12 @@ DEFINE_KSPROPERTY_TABLE(ExtendedPropertyItemsFFC)
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_ISO_ADVANCED, CExtendedVidProcSetting, IsoAdvanced ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOSTABILIZATION, CExtendedProperty, VideoStabilization ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_ADVANCEDPHOTO, CExtendedProperty, AdvancedPhoto ),
- DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_PROFILE, CExtendedProfile, CameraProfile )
+ DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_PROFILE, CExtendedProfile, CameraProfile ),
+ DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_RELATIVEPANELOPTIMIZATION, CExtendedProperty, RelativePanel)
};
//--------------------------------------------------------------
-// Legacy Camera Contorl properties
+// Legacy Camera Control properties
DEFINE_KSPROPERTY_TABLE(CameraControlPropertyTable)
{
DEFINE_PROP_ITEM_WITH_VALUES(CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXPOSURE, KSPROPERTY_CAMERACONTROL_S, Exposure, &ExposureValues),
diff --git a/avstream/avscamera/sys/Capture.cpp b/avstream/avscamera/sys/Capture.cpp
index e5d43ddd..25e6a5f8 100644
--- a/avstream/avscamera/sys/Capture.cpp
+++ b/avstream/avscamera/sys/Capture.cpp
@@ -266,7 +266,7 @@ Return Value:
(m_Pin->ConnectionFormat))->ImageInfoHeader);
m_VideoInfoHeader = reinterpret_cast <PKS_VIDEOINFOHEADER> (
- ExAllocatePoolWithTag (
+ ExAllocatePoolZero (
NonPagedPoolNx,
max(sizeof(KS_VIDEOINFOHEADER), ConnectionHeader->biSize + KS_SIZE_PREHEADER),
AVSHWS_POOLTAG
@@ -308,7 +308,7 @@ Return Value:
VideoInfoHeader);
m_VideoInfoHeader = reinterpret_cast <PKS_VIDEOINFOHEADER> (
- ExAllocatePoolWithTag (
+ ExAllocatePoolZero (
NonPagedPoolNx,
max(sizeof(KS_VIDEOINFOHEADER), KS_SIZE_VIDEOHEADER (ConnectionHeader)),
AVSHWS_POOLTAG
@@ -339,7 +339,7 @@ Return Value:
VideoInfoHeader2);
m_VideoInfoHeader = reinterpret_cast <PKS_VIDEOINFOHEADER> (
- ExAllocatePoolWithTag(
+ ExAllocatePoolZero(
NonPagedPoolNx,
max(sizeof(KS_VIDEOINFOHEADER), ConnectionHeader->bmiHeader.biSize + KS_SIZE_PREHEADER),
AVSHWS_POOLTAG
@@ -2100,7 +2100,18 @@ Return Value:
{
PAGED_CODE( );
+ // If the host process did not stop the pin, we need to do that before
+ // the CCapturePin object gets freed.
+ if (m_Pin->DeviceState != KSSTATE_STOP)
+ {
+ // Skip straight to the STOP state because our simulation doesn't
+ // really need the PAUSE and ACQUIRE transitions when stopping.
+ SetState(KSSTATE_STOP, m_Pin->DeviceState);
+ }
+
// Some reasonable default behavior.
+ GetFilter()->setPin(nullptr, m_Pin->Id);
+
return STATUS_SUCCESS;
}
diff --git a/avstream/avscamera/sys/Common.h b/avstream/avscamera/sys/Common.h
index fdcb1c48..7cde102f 100644
--- a/avstream/avscamera/sys/Common.h
+++ b/avstream/avscamera/sys/Common.h
@@ -23,11 +23,15 @@
#define _NO_SYS_GUID_OPERATOR_EQ_
+#ifdef NTDDI_VERSION
+#undef NTDDI_VERSION
+#endif //NTDDI_VERSION
+#define NTDDI_VERSION NTDDI_WIN10_VB
+
#include <stdio.h>
#include <stdlib.h>
#include <wdm.h>
-#include <wdmguid.h>
#include <windef.h>
#include <unknown.h>
#include <ks.h>
diff --git a/avstream/avscamera/sys/Device.cpp b/avstream/avscamera/sys/Device.cpp
index 99bc60ce..2741da08 100644
--- a/avstream/avscamera/sys/Device.cpp
+++ b/avstream/avscamera/sys/Device.cpp
@@ -33,6 +33,10 @@
#pragma code_seg("PAGE")
#endif // ALLOC_PRAGMA
+#ifndef DEVPKEY_Device_PanelId
+DEFINE_DEVPROPKEY(DEVPKEY_Device_PanelId, 0x8dbc9c86, 0x97a9, 0x4bff, 0x9b, 0xc6, 0xbf, 0xe9, 0x5d, 0x3e, 0x6d, 0xad, 2); // DEVPROP_TYPE_STRING
+#endif
+
CCaptureDevice::
CCaptureDevice (
_In_ PKSDEVICE Device
@@ -616,9 +620,12 @@ Return Value:
pld.Revision = 2;
pld.Panel = m_Context[i].AcpiPosition;
pld.Rotation = m_Context[i].AcpiRotation;
- static
- const
- GUID FFC_Filter = {STATIC_FrontCamera_Filter};
+ pld.CabinetNumber = 0;
+ WCHAR PanelId[MAX_PATH] = { 0 };
+ size_t cchDest = MAX_PATH;
+
+ IFFAILED_EXIT(
+ RtlStringCchPrintfW(PanelId, cchDest, L"{00000000-0000-0000-ffff-ffffffffffff}\\%04X\\%u", pld.CabinetNumber, PnpAcpiPanelSideMap[pld.Panel]));
IFFAILED_EXIT(
IoSetDeviceInterfacePropertyData(SymbolicLinkName,
@@ -629,6 +636,15 @@ Return Value:
sizeof(pld),
(PVOID)&pld)
);
+
+ // Also set Panel ID manually, because PnP does not do this for the interface currently
+ IoSetDeviceInterfacePropertyData(SymbolicLinkName,
+ &DEVPKEY_Device_PanelId,
+ LOCALE_NEUTRAL,
+ PLUGPLAY_PROPERTY_PERSISTENT,
+ DEVPROP_TYPE_STRING,
+ (ULONG)(wcslen(PanelId)+1)*sizeof(WCHAR),
+ (PVOID)PanelId);
}
// On a real device this object would be constructed whenever the sensor hardware is ready...
diff --git a/avstream/avscamera/sys/Device.h b/avstream/avscamera/sys/Device.h
index 95debada..c203f70e 100644
--- a/avstream/avscamera/sys/Device.h
+++ b/avstream/avscamera/sys/Device.h
@@ -34,6 +34,17 @@ struct CSensorContext
AcpiPldRotation AcpiRotation; // How the device is oriented with respect to the panel.
};
+static constexpr ULONG PnpAcpiPanelSideMap[]
+{
+ 1, // AcpiPldPanelTop
+ 2, // AcpiPldPanelBottom
+ 3, // AcpiPldPanelLeft
+ 4, // AcpiPldPanelRight
+ 5, // AcpiPldPanelFront
+ 6, // AcpiPldPanelBack
+ 0, // AcpiPldPanelUnknown
+};
+
class CCaptureDevice
{
protected:
@@ -393,7 +404,7 @@ public:
PDEVICE_OBJECT
GetDeviceObject();
- static IO_COMPLETION_ROUTINE CCaptureDevice::IrpSynchronousCompletion;
+ static IO_COMPLETION_ROUTINE IrpSynchronousCompletion;
virtual
NTSTATUS
diff --git a/avstream/avscamera/sys/PreviewHwSim.cpp b/avstream/avscamera/sys/PreviewHwSim.cpp
index 775c6b8d..f55ffa20 100644
--- a/avstream/avscamera/sys/PreviewHwSim.cpp
+++ b/avstream/avscamera/sys/PreviewHwSim.cpp
@@ -40,6 +40,7 @@ CPreviewHardwareSimulation::CPreviewHardwareSimulation(
_In_ LONG PinID
)
: CHardwareSimulation( Sensor, PinID )
+ , m_Illuminated(FALSE)
{
PAGED_CODE();
}
@@ -299,6 +300,11 @@ Return Value:
BytesLeft -= sizeof(CAMERA_METADATA_INTRINSICS);
}
+ // TODO: This metadata should only be exposed on a sensor category preview pin.
+ // It's possible I should derive a new preview sim to handle this; but for now
+ // we just populate the IR illumination state on every preview pin. Hopefully
+ // the app is smart enough to realize that this is meaningless if they have not
+ // selected an IR mediatype.
if (BytesLeft >= sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION))
{
PKSCAMERA_METADATA_FRAMEILLUMINATION pPreviewIllumination =
@@ -308,7 +314,31 @@ Return Value:
pPreviewIllumination->Header.MetadataId = (ULONG)MetadataId_FrameIllumination;
pPreviewIllumination->Header.Size = sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION);
- pPreviewIllumination->Flags = KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON;
+ // Toggle the Illumination state for an IR frame.
+ CExtendedVidProcSetting State;
+ (void) m_Sensor->GetIRTorch(&State);
+
+ if (State.Flags & KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALWAYS_ON)
+ {
+ m_Illuminated = TRUE;
+ pPreviewIllumination->Flags = KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON;
+ }
+ else if ((State.Flags & KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALTERNATING_FRAME_ILLUMINATION))
+ {
+ m_Illuminated = !m_Illuminated;
+ if (m_Illuminated)
+ {
+ pPreviewIllumination->Flags = KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON;
+ }
+ }
+ else
+ {
+ m_Illuminated = FALSE;
+ }
+
+ DBG_TRACE("Frame Illumination: Flags=0x%016llX, State=%s",
+ State.Flags,
+ (pPreviewIllumination->Flags==KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON ?"ON":"OFF"));
pMetadata->UsedSize += sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION);
BytesLeft -= sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION);
diff --git a/avstream/avscamera/sys/PreviewHwSim.h b/avstream/avscamera/sys/PreviewHwSim.h
index e5a4f536..1d26f692 100644
--- a/avstream/avscamera/sys/PreviewHwSim.h
+++ b/avstream/avscamera/sys/PreviewHwSim.h
@@ -43,7 +43,6 @@ public:
protected:
METADATA_PREVIEWAGGREGATION
- CPreviewHardwareSimulation::
GetMetadata();
VOID GetCaptureStats(
@@ -57,5 +56,8 @@ protected:
_Inout_ PKSSTREAM_HEADER pStreamHeader
);
+private:
+ BOOLEAN m_Illuminated;
+
};
diff --git a/avstream/avscamera/sys/Sensor.cpp b/avstream/avscamera/sys/Sensor.cpp
index 9215f6b6..654ea666 100644
--- a/avstream/avscamera/sys/Sensor.cpp
+++ b/avstream/avscamera/sys/Sensor.cpp
@@ -188,7 +188,7 @@ Initialize()
m_InterruptTime[i] = 0;
m_LastMappingsCompleted[i] = 0;
}
- return STATUS_SUCCESS;
+ return m_Device ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER;
}
void
@@ -356,7 +356,7 @@ CreateSynthesizer(
if( NT_SUCCESS( Status ) )
{
- DBG_TRACE( "Setting Mounting Orientation to %d�", DbgRotation2Degrees(m_MountingOrientation) )
+ DBG_TRACE( "Setting Mounting Orientation to %d°", DbgRotation2Degrees(m_MountingOrientation) )
m_Synthesizer[ Pin->Id ]->SetRotation( m_MountingOrientation );
}
@@ -412,15 +412,17 @@ Return Value:
NTSTATUS Status = STATUS_SUCCESS;
LONG lPindex = Pin->Id;
+
+ // Hold off all image generation while we manipulate the capture pin and synthensizer arrays.
+ KScopedMutex Lock(m_SensorMutex);
+
//
// If we're the first pin to go into acquire (remember we can have
// a filter in another graph going simultaneously), grab the resources for Preview
//
- if( InterlockedCompareExchangePointer(
- (PVOID *) &m_CapturePin[lPindex],
- CapturePin,
- nullptr) == nullptr)
+ if (m_CapturePin[lPindex] == nullptr)
{
+ m_CapturePin[lPindex] = CapturePin;
m_VideoInfoHeader[lPindex] = VideoInfoHeader;
//
@@ -449,7 +451,6 @@ Return Value:
//
// If everything has succeeded thus far, set the capture pin.
//
- m_CapturePin[lPindex] = CapturePin;
*pSim = m_HardwareSimulation[lPindex];
}
@@ -460,6 +461,8 @@ Return Value:
// acquired.
//
ReleaseHardwareResources(Pin);
+ *pSim = nullptr;
+ m_CapturePin[lPindex] = nullptr;
}
}
else
@@ -1088,20 +1091,23 @@ Return Value:
void
CSensor::
-SetSynthesizerAttribute(
- CSynthesizer::Attribute Attrib,
- LONGLONG Info,
- LONG PinId
+SetSynthesizerAttributeList(
+ _In_ size_t Count,
+ _In_ SynthesizerAttributeEntry AttributeList[]
)
{
PAGED_CODE();
-
- for( ULONG Pin=0; IsValidIndex(Pin); Pin++ )
+ // Syncrhonize access to sensor.
+ KScopedMutex Lock(m_SensorMutex);
+ for (size_t item = 0; item < Count; item++)
{
- if( (Pin==(ULONG)PinId || IsStillIndex(Pin)) &&
- m_Synthesizer[Pin] )
+ for (ULONG Pin = 0; IsValidIndex(Pin); Pin++)
{
- m_Synthesizer[Pin]->Set( Attrib, Info );
+ if ((Pin == (ULONG)AttributeList[item].PinId || IsStillIndex(Pin)) &&
+ m_Synthesizer[Pin])
+ {
+ m_Synthesizer[Pin]->Set(AttributeList[item].Attrib, AttributeList[item].Info);
+ }
}
}
}
@@ -1140,11 +1146,15 @@ Return Value:
DBG_ENTER( "( Pin=%d )\n", Pin->Id ) ;
LONG lPindex = Pin->Id;
+
//
// Blow away the image synth.
//
m_HardwareSimulation[lPindex]->Reset();
+ // Hold off all image generation while we free the capture pin and synthensizer arrays.
+ KScopedMutex Lock(m_SensorMutex);
+
SAFE_DELETE( m_Synthesizer[lPindex] );
m_VideoInfoHeader[lPindex] = NULL;
@@ -1152,10 +1162,7 @@ Return Value:
// Release our "lock" on hardware resources. This will allow another
// pin (perhaps in another graph) to acquire them.
//
- InterlockedExchangePointer(
- (PVOID *) &(m_CapturePin[lPindex]),
- nullptr
- );
+ m_CapturePin[lPindex] = nullptr;
DBG_LEAVE( "( Pin=%d )\n", Pin->Id ) ;
}
@@ -1322,6 +1329,7 @@ DEFINE_NULL_PROPERTY_GET(CSensor, KSPROPERTY_CAMERACONTROL_IMAGE_PIN_CAPABILITY_
DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, TriggerTime)
DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, TorchMode)
+DEFINE_NULL_PROPERTY(CSensor, CExtendedVidProcSetting, IRTorch)
DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, ExtendedFlash)
DEFINE_NULL_PROPERTY_GET(CSensor, CExtendedProperty, PhotoFrameRate)
@@ -1352,6 +1360,7 @@ DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, OptimizationHint)
DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, AdvancedPhoto)
DEFINE_NULL_PROPERTY(CSensor, CExtendedVidProcSetting, FaceDetection)
DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, VideoTemporalDenoising)
+DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, RelativePanel)
DEFINE_NULL_PROPERTY(CSensor, KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_S, VideoStabMode)
diff --git a/avstream/avscamera/sys/Sensor.h b/avstream/avscamera/sys/Sensor.h
index 327b860a..31b0f3a2 100644
--- a/avstream/avscamera/sys/Sensor.h
+++ b/avstream/avscamera/sys/Sensor.h
@@ -517,8 +517,18 @@ public:
m_MountingOrientation = Orientation;
}
+ struct SynthesizerAttributeEntry
+ {
+ CSynthesizer::Attribute Attrib;
+ LONGLONG Info;
+ LONG PinId;
+ };
+
void
- SetSynthesizerAttribute( CSynthesizer::Attribute Attrib, LONGLONG Info, LONG PinId );
+ SetSynthesizerAttributeList(
+ _In_ size_t Count,
+ _In_ SynthesizerAttributeEntry AttributeList[]
+ );
protected:
LONG
@@ -554,6 +564,7 @@ public:
DECLARE_PROPERTY( CExtendedProperty, TriggerTime );
DECLARE_PROPERTY( CExtendedProperty, TorchMode );
+ DECLARE_PROPERTY( CExtendedVidProcSetting, IRTorch );
DECLARE_PROPERTY_ASYNC( CExtendedVidProcSetting, Focus );
DECLARE_PROPERTY_ASYNC( CExtendedProperty, Iso );
@@ -576,6 +587,7 @@ public:
DECLARE_PROPERTY( CExtendedProperty, AdvancedPhoto );
DECLARE_PROPERTY( CExtendedVidProcSetting, FaceDetection );
DECLARE_PROPERTY( CExtendedProperty, VideoTemporalDenoising);
+ DECLARE_PROPERTY( CExtendedProperty, RelativePanel);
DECLARE_PROPERTY_VARSIZE_ASYNC( CRoiProperty, Roi );
diff --git a/avstream/avscamera/sys/SensorSimulation.cpp b/avstream/avscamera/sys/SensorSimulation.cpp
index 6ecd9007..e60372c1 100644
--- a/avstream/avscamera/sys/SensorSimulation.cpp
+++ b/avstream/avscamera/sys/SensorSimulation.cpp
@@ -331,6 +331,15 @@ Return Value:
}
m_TorchMode.Flags = KSCAMERA_EXTENDEDPROP_VIDEOTORCH_OFF;
m_TorchMode = 50UL;
+ m_IRTorch.Flags = KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALWAYS_ON;
+ m_IRTorch.Capability =
+ KSCAMERA_EXTENDEDPROP_IRTORCHMODE_OFF |
+ KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALWAYS_ON |
+ KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALTERNATING_FRAME_ILLUMINATION;
+ m_IRTorch = 100UL;
+ m_IRTorch.Min() = 20;
+ m_IRTorch.Max() = 100;
+ m_IRTorch.Step() = 5;
m_OptimizationHint.Flags = KSCAMERA_EXTENDEDPROP_OPTIMIZATION_PHOTO;
@@ -471,6 +480,14 @@ Return Value:
m_PowerLineFreq.Value = POWERLINEFREQ_DEFAULT;
m_PowerLineFreq.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL;
+ // Set up our relative panel.
+ m_RelativePanel.Capability =
+ KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_ON |
+ KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_OFF |
+ KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_DYNAMIC;
+ m_RelativePanel.Flags = KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_OFF;
+ m_RelativePanel = (ULONG)AcpiPldPanelUnknown;
+
m_IsoResult = STATUS_SUCCESS;
m_EvCompResult = STATUS_SUCCESS;
m_WhiteBalanceResult= STATUS_SUCCESS;
@@ -1791,6 +1808,40 @@ SetOpticalImageStabilization(
return STATUS_SUCCESS;
}
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_RELATIVEPANEL.
+NTSTATUS
+CSensorSimulation::
+GetRelativePanel(
+ _Inout_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ *pProperty = m_RelativePanel;
+ pProperty->Flags = m_RelativePanel.Flags;
+ pProperty->Capability = KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_ON |
+ KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_OFF |
+ KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_DYNAMIC;
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_RELATIVEPANEL.
+NTSTATUS
+CSensorSimulation::
+SetRelativePanel(
+ _In_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ m_RelativePanel = *pProperty;
+ m_RelativePanel.Flags = pProperty->Flags;
+ return STATUS_SUCCESS;
+}
+
// Get KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOTEMPORALDENOISING.
NTSTATUS
CSensorSimulation::
@@ -3024,6 +3075,37 @@ SetTorchMode(
return STATUS_SUCCESS;
}
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_IRTORCHMODE
+NTSTATUS
+CSensorSimulation::
+GetIRTorch(
+ _Inout_ CExtendedVidProcSetting *pTorch
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ *pTorch = m_IRTorch;
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_IRTORCHMODE
+NTSTATUS
+CSensorSimulation::
+SetIRTorch(
+ _In_ CExtendedVidProcSetting *pTorch
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ // Only overwrite the IR Torch Flags and value.
+ m_IRTorch.Flags = pTorch->Flags;
+ m_IRTorch = pTorch->GetULONG();
+
+ return STATUS_SUCCESS;
+}
+
// Get KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOMODE
NTSTATUS
CSensorSimulation::
diff --git a/avstream/avscamera/sys/SensorSimulation.h b/avstream/avscamera/sys/SensorSimulation.h
index a2dd1fe7..6124762c 100644
--- a/avstream/avscamera/sys/SensorSimulation.h
+++ b/avstream/avscamera/sys/SensorSimulation.h
@@ -50,6 +50,7 @@ protected:
ULONG m_FaceDetectionCurrentMax;
ULONGLONG m_SceneMode;
CExtendedProperty m_TorchMode;
+ CExtendedVidProcSetting m_IRTorch;
CExtendedProperty m_OptimizationHint;
CExtendedMetadata *m_MetadataInfo;
PKSCAMERA_PERFRAMESETTING_HEADER m_pPerFrameSettings;
@@ -61,7 +62,8 @@ protected:
ULONGLONG m_Histogram;
ULONGLONG m_OpticalImageStabilization;
ULONGLONG m_VideoTemporalDenoising;
- CExtendedProperty m_AdvancedPhoto;
+ CExtendedProperty m_RelativePanel;
+ CExtendedProperty m_AdvancedPhoto;
CWhiteBalanceRoiIspControl m_RoiWhiteBalance;
CExposureRoiIspControl m_RoiExposureMode;
@@ -207,6 +209,7 @@ public:
DECLARE_PROPERTY_GET( KSPROPERTY_CAMERACONTROL_IMAGE_PIN_CAPABILITY_S, PinDependence );
DECLARE_PROPERTY( CExtendedProperty, TriggerTime );
DECLARE_PROPERTY( CExtendedProperty, TorchMode );
+ DECLARE_PROPERTY( CExtendedVidProcSetting, IRTorch );
DECLARE_PROPERTY( CExtendedProperty, ExtendedFlash );
@@ -236,6 +239,7 @@ public:
DECLARE_PROPERTY_GET( CExtendedFieldOfView, FieldOfView );
DECLARE_PROPERTY_GET( CExtendedCameraAngleOffset, CameraAngleOffset );
DECLARE_PROPERTY( CExtendedProperty, VideoTemporalDenoising);
+ DECLARE_PROPERTY( CExtendedProperty, RelativePanel);
DECLARE_PROPERTY_VARSIZE_ASYNC_NOCANCEL( CRoiProperty, Roi );
@@ -288,4 +292,4 @@ const LONG WHITEBALANCE_DEF = 5000;
const LONG EXPOSURE_BILOG_MIN = -10;
const LONG EXPOSURE_BILOG_MAX = 9;
const LONG EXPOSURE_BILOG_STEP = 1;
-const LONG EXPOSURE_BILOG_DEF = -5; \ No newline at end of file
+const LONG EXPOSURE_BILOG_DEF = -5;
diff --git a/avstream/avscamera/sys/VideoHwSim.cpp b/avstream/avscamera/sys/VideoHwSim.cpp
index 33b6de90..839af530 100644
--- a/avstream/avscamera/sys/VideoHwSim.cpp
+++ b/avstream/avscamera/sys/VideoHwSim.cpp
@@ -27,6 +27,7 @@ CVideoHardwareSimulation::CVideoHardwareSimulation(
_In_ LONG PinID
)
: CHardwareSimulation( Sensor, PinID )
+ , m_Illuminated(FALSE)
{}
@@ -50,6 +51,54 @@ EmitMetadata(
if (0 != (pStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_METADATA))
{
+ PKS_FRAME_INFO pFrameInfo = (PKS_FRAME_INFO)(pStreamHeader + 1);
+ PKSSTREAM_METADATA_INFO pMetadata = (PKSSTREAM_METADATA_INFO)(pFrameInfo + 1);
+ ULONG BytesLeft = pMetadata->BufferSize - pMetadata->UsedSize;
+
+ // TODO: This metadata should only be exposed on a sensor category preview pin.
+ // It's possible I should derive a new preview sim to handle this; but for now
+ // we just populate the IR illumination state on every preview pin. Hopefully
+ // the app is smart enough to realize that this is meaningless if they have not
+ // selected an IR mediatype.
+ if (BytesLeft >= sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION))
+ {
+ PKSCAMERA_METADATA_FRAMEILLUMINATION pPreviewIllumination =
+ (PKSCAMERA_METADATA_FRAMEILLUMINATION)(((PBYTE)pMetadata->SystemVa) + pMetadata->UsedSize);
+ RtlZeroMemory(pPreviewIllumination, sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION));
+
+ pPreviewIllumination->Header.MetadataId = (ULONG)MetadataId_FrameIllumination;
+ pPreviewIllumination->Header.Size = sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION);
+
+ // Toggle the Illumination state for an IR frame.
+ CExtendedVidProcSetting State;
+ (void)m_Sensor->GetIRTorch(&State);
+
+ if (State.Flags & KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALWAYS_ON)
+ {
+ m_Illuminated = TRUE;
+ pPreviewIllumination->Flags = KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON;
+ }
+ else if ((State.Flags & KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALTERNATING_FRAME_ILLUMINATION))
+ {
+ m_Illuminated = !m_Illuminated;
+ if (m_Illuminated)
+ {
+ pPreviewIllumination->Flags = KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON;
+ }
+ }
+ else
+ {
+ m_Illuminated = FALSE;
+ }
+
+ DBG_TRACE("Frame Illumination: Flags=0x%016llX, State=%s",
+ State.Flags,
+ (pPreviewIllumination->Flags == KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON ? "ON" : "OFF"));
+
+ pMetadata->UsedSize += sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION);
+ BytesLeft -= sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION);
+ }
+
CExtendedVidProcSetting FaceDetect;
m_Sensor->GetFaceDetection(&FaceDetect);
diff --git a/avstream/avscamera/sys/VideoHwSim.h b/avstream/avscamera/sys/VideoHwSim.h
index 40b0b24b..a576d9a1 100644
--- a/avstream/avscamera/sys/VideoHwSim.h
+++ b/avstream/avscamera/sys/VideoHwSim.h
@@ -38,5 +38,9 @@ public:
EmitMetadata(
_Inout_ PKSSTREAM_HEADER pStreamHeader
);
+
+private:
+ BOOLEAN m_Illuminated;
+
};
diff --git a/avstream/avscamera/sys/avscamera.inf b/avstream/avscamera/sys/avscamera.inx
index 2a17a764..f6f1e846 100644
--- a/avstream/avscamera/sys/avscamera.inf
+++ b/avstream/avscamera/sys/avscamera.inx
Binary files differ
diff --git a/avstream/avscamera/sys/filter.cpp b/avstream/avscamera/sys/filter.cpp
index 2680f503..dfb6ce1f 100644
--- a/avstream/avscamera/sys/filter.cpp
+++ b/avstream/avscamera/sys/filter.cpp
@@ -64,6 +64,7 @@ Return Value:
m_pCaptureDevice(NULL),
m_pPerFrameSettings(nullptr),
m_pinArray(nullptr),
+ m_pMinimumRequestedFrames(nullptr),
m_PhotoModeNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOMODE ),
m_PhotoMaxFrameRateNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOMAXFRAMERATE) ,
m_FocusNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_FOCUSMODE ),
@@ -141,10 +142,12 @@ Return Value:
IFFAILED_EXIT( m_Sensor->AddFilter(m_pKSFilter) );
IFNULL_EXIT(m_pinArray = new (PagedPool, 'sniP') CCapturePin *[m_Sensor->GetPinCount()]);
+ IFNULL_EXIT(m_pMinimumRequestedFrames = new (PagedPool, 'sniP') ULONG[m_Sensor->GetPinCount()]);
for( ULONG i=0; i<m_Sensor->GetPinCount(); i++ )
{
m_pinArray[i] = nullptr;
+ m_pMinimumRequestedFrames[i] = IMAGE_CAPTURE_PIN_MINIMUM_FRAMES;
}
done:
@@ -209,6 +212,7 @@ CCaptureFilter::~CCaptureFilter()
// may need to have some things reset.
m_Sensor->Reset();
+ delete [] m_pMinimumRequestedFrames;
delete [] m_pinArray;
DBG_LEAVE("(%S)", Name);
@@ -352,6 +356,11 @@ Return Value:
// Take out a weak reference to the pin object.
m_pinArray[Id] = pPin;
+ if (m_pinArray[Id] != nullptr)
+ {
+ m_pinArray[Id]->SetDesiredFrames(m_pMinimumRequestedFrames[Id]);
+ (void)m_pinArray[Id]->UpdateAllocatorFraming();
+ }
}
CCapturePin *
@@ -391,7 +400,8 @@ Return Value:
NTSTATUS
CCaptureFilter::
UpdateAllocatorFraming(
- _In_ ULONG PinId
+ _In_ ULONG PinId,
+ _In_ ULONG DesiredFrames
)
/*++
@@ -412,15 +422,20 @@ Return Value:
{
PAGED_CODE();
- NTSTATUS Status = STATUS_INVALID_PARAMETER;
+ NTSTATUS Status = STATUS_SUCCESS;
// Acquire the lock and update the Pin's allocator framing.
LockFilter Lock(m_pKSFilter);
if( m_pinArray[PinId] )
{
+ m_pinArray[PinId]->SetDesiredFrames(DesiredFrames);
Status = m_pinArray[PinId]->UpdateAllocatorFraming();
}
+ else
+ {
+ m_pMinimumRequestedFrames[PinId] = DesiredFrames;
+ }
DBG_LEAVE("()=0x%08X",Status);
return Status;
@@ -636,6 +651,7 @@ SetPhotoMode(
PAGED_CODE();
NTSTATUS Status = STATUS_INVALID_PARAMETER;
+ ULONG TotalFrames = IMAGE_CAPTURE_PIN_MINIMUM_FRAMES;
DBG_ENTER( "()" );
@@ -645,10 +661,6 @@ SetPhotoMode(
{
CExtendedPhotoMode Caps(*pMode);
Status = m_Sensor->GetPhotoMode( &Caps );
- CCapturePin *pPin = getPin(pMode->PinId);
-
- // Should always be valid.
- NT_ASSERT(pPin);
if( NT_SUCCESS(Status) )
{
@@ -686,7 +698,7 @@ SetPhotoMode(
// Assume the normal photo sequence case.
// For normal photo sequence, we provide history frames +1 or at least a minimum of 3 frames.
- ULONG TotalFrames = pMode->RequestedHistoryFrames() + 1;
+ TotalFrames = pMode->RequestedHistoryFrames() + 1;
// Modify TotalFrames for the VPS case.
// For VPS, we need LoopCount * FrameCount; but limit by the minimum(3) and maximum (20) frames.
@@ -708,14 +720,12 @@ SetPhotoMode(
DBG_TRACE( "Advertising Framing requirement: %d", TotalFrames );
- pPin->SetDesiredFrames(TotalFrames);
Status = STATUS_SUCCESS;
break;
}
case KSCAMERA_EXTENDEDPROP_PHOTOMODE_NORMAL:
{
// Set it back to the minimum number of frames.
- pPin->SetDesiredFrames(IMAGE_CAPTURE_PIN_MINIMUM_FRAMES);
Status = STATUS_SUCCESS;
break;
}
@@ -724,7 +734,7 @@ SetPhotoMode(
// Update allocator framing.
if( NT_SUCCESS( Status ) )
{
- Status = UpdateAllocatorFraming( pMode->PinId );
+ Status = UpdateAllocatorFraming( pMode->PinId, TotalFrames );
}
// Update the sensor object...
@@ -1118,13 +1128,13 @@ GetTorchMode(
NTSTATUS Status = STATUS_INVALID_PARAMETER;
- if( pTorchMode->isValid() &&
- pTorchMode->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE )
+ if (pTorchMode->isValid() &&
+ pTorchMode->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE)
{
- Status = m_Sensor->GetTorchMode( pTorchMode );
+ Status = m_Sensor->GetTorchMode(pTorchMode);
}
DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X",
- pTorchMode->PinId, pTorchMode->Flags, pTorchMode->Capability, Status );
+ pTorchMode->PinId, pTorchMode->Flags, pTorchMode->Capability, Status);
return Status;
}
@@ -1139,34 +1149,101 @@ SetTorchMode(
NTSTATUS Status = STATUS_INVALID_PARAMETER;
- if( !(pTorchMode->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) &&
- pTorchMode->isValid() &&
- pTorchMode->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE &&
- pTorchMode->m_Value.Value.ul <= 100 )
+ if (!(pTorchMode->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) &&
+ pTorchMode->isValid() &&
+ pTorchMode->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE &&
+ pTorchMode->m_Value.Value.ul <= 100)
{
CExtendedProperty Caps(*pTorchMode);
Status = m_Sensor->GetTorchMode(&Caps);
- if( NT_SUCCESS(Status) )
+ if (NT_SUCCESS(Status))
{
// Assume an invalid parameter.
Status = STATUS_INVALID_PARAMETER;
- if( pTorchMode->Flags == (pTorchMode->Flags & Caps.Capability) )
+ if (pTorchMode->Flags == (pTorchMode->Flags & Caps.Capability))
{
- switch( pTorchMode->Flags )
+ switch (pTorchMode->Flags)
{
case KSCAMERA_EXTENDEDPROP_VIDEOTORCH_OFF:
case KSCAMERA_EXTENDEDPROP_VIDEOTORCH_ON:
case KSCAMERA_EXTENDEDPROP_VIDEOTORCH_ON_ADJUSTABLEPOWER:
- Status = m_Sensor->SetTorchMode( pTorchMode );
+ Status = m_Sensor->SetTorchMode(pTorchMode);
break;
}
}
}
}
DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X",
- pTorchMode->PinId, pTorchMode->Flags, pTorchMode->Capability, Status );
+ pTorchMode->PinId, pTorchMode->Flags, pTorchMode->Capability, Status);
+ return Status;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_IRTORCHMODE
+NTSTATUS
+CCaptureFilter::
+GetIRTorch(
+ _Inout_ CExtendedVidProcSetting *pTorch
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ if (pTorch->isValid() &&
+ pTorch->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE)
+ {
+ Status = m_Sensor->GetIRTorch(pTorch);
+ }
+ DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X",
+ pTorch->PinId, pTorch->Flags, pTorch->Capability, Status);
+ return Status;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_IRTORCHMODE
+NTSTATUS
+CCaptureFilter::
+SetIRTorch(
+ _In_ CExtendedVidProcSetting *pTorch
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ if (!(pTorch->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) &&
+ pTorch->isValid() &&
+ pTorch->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE)
+ {
+ CExtendedVidProcSetting Caps(*pTorch);
+ Status = m_Sensor->GetIRTorch(&Caps);
+
+ if (NT_SUCCESS(Status))
+ {
+ Status = Caps.BoundsCheck(pTorch->GetULONG());
+
+ if (NT_SUCCESS(Status))
+ {
+ // Assume an invalid parameter.
+ Status = STATUS_INVALID_PARAMETER;
+
+ if (pTorch->Flags == (pTorch->Flags & Caps.Capability))
+ {
+ switch (pTorch->Flags)
+ {
+ case KSCAMERA_EXTENDEDPROP_IRTORCHMODE_OFF:
+ case KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALWAYS_ON:
+ case KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALTERNATING_FRAME_ILLUMINATION:
+ Status = m_Sensor->SetIRTorch(pTorch);
+ break;
+ }
+ }
+ }
+ }
+ }
+ DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X",
+ pTorch->PinId, pTorch->Flags, pTorch->Capability, Status);
return Status;
}
@@ -3494,6 +3571,66 @@ SetOpticalImageStabilization(
return Status;
}
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_RELATIVEPANEL.
+NTSTATUS
+CCaptureFilter::
+GetRelativePanel(
+ _Inout_ CExtendedProperty *pRelativePanel
+)
+{
+ PAGED_CODE();
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ if (pRelativePanel->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE &&
+ pRelativePanel->isValid())
+ {
+ //Get the current state
+ Status = m_Sensor->GetRelativePanel(pRelativePanel);
+ }
+
+ DBG_TRACE("pRelativePanel = %p, PinId = %u, Flags = %llu, Version = %u",
+ pRelativePanel, pRelativePanel->PinId, pRelativePanel->Flags, pRelativePanel->Version);
+
+ return Status;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_RELATIVEPANEL.
+NTSTATUS
+CCaptureFilter::
+SetRelativePanel(
+ _In_ CExtendedProperty *pRelativePanel
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ // Call must be Filter and flags must be supported and version must be 1
+ if (pRelativePanel->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE &&
+ pRelativePanel->isValid() &&
+ (KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_ON == pRelativePanel->Flags ||
+ KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_OFF == pRelativePanel->Flags))
+ {
+ CExtendedProperty Caps(*pRelativePanel);
+ Status = m_Sensor->GetRelativePanel(&Caps);
+
+ if (NT_SUCCESS(Status))
+ {
+ // Assume an invalid parameter.
+ Status = STATUS_INVALID_PARAMETER;
+
+ if (pRelativePanel->Flags == (pRelativePanel->Flags & Caps.Capability))
+ {
+ Status = m_Sensor->SetRelativePanel(pRelativePanel);
+ }
+ }
+ }
+ DBG_TRACE("pOIS = %p, PinId = %u, Flags = %llu, Version = %u",
+ pRelativePanel, pRelativePanel->PinId, pRelativePanel->Flags, pRelativePanel->Version);
+
+ return Status;
+}
+
// Get KSPROPERTY_CAMERACONTROL_EXTENDED_ADVANCEDPHOTO.
NTSTATUS
CCaptureFilter::
diff --git a/avstream/avscamera/sys/filter.h b/avstream/avscamera/sys/filter.h
index 292a6bc7..5b272a9d 100644
--- a/avstream/avscamera/sys/filter.h
+++ b/avstream/avscamera/sys/filter.h
@@ -58,6 +58,7 @@ private:
// The AVStream filter object associated with this CCaptureFilter.
//
CCapturePin **m_pinArray;
+ ULONG *m_pMinimumRequestedFrames;
protected:
//
@@ -331,7 +332,9 @@ DECLARE_PROPERTY_SET_HANDLER( type, name )
DECLARE_PROPERTY_HANDLERS( CExtendedProperty, Thumbnail )
DECLARE_PROPERTY_HANDLERS( CExtendedProperty, TriggerTime )
DECLARE_PROPERTY_HANDLERS( CExtendedProperty, TorchMode )
+ DECLARE_PROPERTY_HANDLERS( CExtendedVidProcSetting, IRTorch )
DECLARE_PROPERTY_HANDLERS( CExtendedProperty, VideoTemporalDenoising)
+ DECLARE_PROPERTY_HANDLERS( CExtendedProperty, RelativePanel)
DECLARE_PROPERTY_HANDLERS( KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_S, VideoStabMode )
DECLARE_PROPERTY_HANDLERS( KSPROPERTY_CAMERACONTROL_FLASH_S, Flash )
@@ -385,7 +388,7 @@ DECLARE_PROPERTY_SET_HANDLER( type, name )
// Make sure the PERFRAMESETTINGs passed to us are valid.
_Success_(return == 0)
NTSTATUS
- CCaptureFilter::ParsePFSBuffer(
+ ParsePFSBuffer(
_In_reads_bytes_(BufferLimit)
PKSCAMERA_PERFRAMESETTING_HEADER pPFS,
_In_ ULONG BufferLimit,
@@ -434,7 +437,8 @@ DECLARE_PROPERTY_SET_HANDLER( type, name )
// Update the pin's allocator to a specific frame count.
NTSTATUS
UpdateAllocatorFraming(
- _In_ ULONG PinId
+ _In_ ULONG PinId,
+ _In_ ULONG DesiredFrames
);
private:
diff --git a/avstream/avscamera/sys/hwsim.cpp b/avstream/avscamera/sys/hwsim.cpp
index 5322cff3..fdf7b367 100644
--- a/avstream/avscamera/sys/hwsim.cpp
+++ b/avstream/avscamera/sys/hwsim.cpp
@@ -1207,7 +1207,7 @@ Return Value:
{
PAGED_CODE();
- KScopedMutex Lock( m_ListLock );
+ KScopedMutex Lock(m_ListLock);
m_InterruptTime++;
@@ -1218,10 +1218,10 @@ Return Value:
//
if (m_PinState == PinRunning)
{
- LONGLONG Qpc = (LONGLONG) ConvertQPCtoTimeStamp(nullptr);
+ LONGLONG Qpc = (LONGLONG)ConvertQPCtoTimeStamp(nullptr);
LARGE_INTEGER Now;
- KeQuerySystemTimePrecise( &Now );
+ KeQuerySystemTimePrecise(&Now);
//
// Generate a "time stamp" just to overlay it onto the capture image.
// It makes it more exciting than bars that do nothing.
@@ -1230,12 +1230,16 @@ Return Value:
// the most recent streaming pin's index.
if (!m_Sensor->IsStillIndex(m_PinID))
{
+ CSensor::SynthesizerAttributeEntry AttributeList[] =
+ {
+ { CSynthesizer::FrameNumber, m_InterruptTime, m_PinID },
+ { CSynthesizer::RelativePts, (m_InterruptTime + 1) * m_TimePerFrame, m_PinID },
+ { CSynthesizer::QpcTime, Qpc, m_PinID }
+ };
DBG_TRACE("QPC=0x%016llX", Qpc);
// Broadcast the preview pin's info to all pin simulations.
- m_Sensor->SetSynthesizerAttribute(CSynthesizer::FrameNumber, m_InterruptTime, m_PinID);
- m_Sensor->SetSynthesizerAttribute(CSynthesizer::RelativePts, (m_InterruptTime + 1) * m_TimePerFrame, m_PinID);
- m_Sensor->SetSynthesizerAttribute(CSynthesizer::QpcTime, Qpc, m_PinID);
+ m_Sensor->SetSynthesizerAttributeList(SIZEOF_ARRAY(AttributeList), AttributeList);
}
m_Synthesizer->DoSynthesize();
@@ -1243,13 +1247,13 @@ Return Value:
CHAR Text[64];
CExtendedProperty Control;
- m_Sensor->GetVideoStabilization( &Control );
+ m_Sensor->GetVideoStabilization(&Control);
RtlStringCbPrintfA(Text, sizeof(Text), "DVS: %s", DVS_Text(Control.Flags));
- m_Synthesizer->OverlayText( 0, m_Height-38, 1, Text, TRANSPARENT, TEXT_COLOR );
+ m_Synthesizer->OverlayText(0, m_Height - 38, 1, Text, TRANSPARENT, TEXT_COLOR);
- m_Sensor->GetOpticalImageStabilization( &Control );
+ m_Sensor->GetOpticalImageStabilization(&Control);
RtlStringCbPrintfA(Text, sizeof(Text), "OIS: %s", OIS_Text(Control.Flags));
- m_Synthesizer->OverlayText( 0, m_Height-48, 1, Text, TRANSPARENT, TEXT_COLOR );
+ m_Synthesizer->OverlayText(0, m_Height - 48, 1, Text, TRANSPARENT, TEXT_COLOR);
//
// Add the Missed frame count
@@ -1257,7 +1261,7 @@ Return Value:
size_t len = 0;
RtlStringCchLengthA(Text, sizeof(Text), &len);
m_Synthesizer->OverlayText(
- (m_Width - (((ULONG)len*8))), // right-adjust text.
+ (m_Width - (((ULONG)len * 8))), // right-adjust text.
(m_Height - 48),
1,
Text,
@@ -1268,12 +1272,12 @@ Return Value:
//
// Add the estimated FPS
LONGLONG Target = NANOSECONDS / m_TimePerFrame;
- LONGLONG FPS = ((LONGLONG)m_InterruptTime * NANOSECONDS) / ( (Now.QuadPart - m_StartTime.QuadPart) + (NANOSECONDS/2) );
+ LONGLONG FPS = ((LONGLONG)m_InterruptTime * NANOSECONDS) / ((Now.QuadPart - m_StartTime.QuadPart) + (NANOSECONDS / 2));
RtlStringCbPrintfA(Text, sizeof(Text), "%lld/%lld FPS", FPS, Target);
len = 0;
RtlStringCchLengthA(Text, sizeof(Text), &len);
- m_Synthesizer->OverlayText (
- (m_Width - (((ULONG)len*8))), // right-adjust text.
+ m_Synthesizer->OverlayText(
+ (m_Width - (((ULONG)len * 8))), // right-adjust text.
(m_Height - 38),
1,
Text,
@@ -1284,7 +1288,7 @@ Return Value:
//
// Fill scatter gather buffers
//
- if (!NT_SUCCESS (FillScatterGatherBuffers ()))
+ if (!NT_SUCCESS(FillScatterGatherBuffers()))
{
m_NumFramesSkipped++;
}
@@ -1294,28 +1298,28 @@ Return Value:
// Issue an interrupt to our hardware sink. This is a "fake" interrupt.
// It will occur at DISPATCH_LEVEL.
//
- m_Sensor -> Interrupt (m_PinID);
+ m_Sensor->Interrupt(m_PinID);
//
// Schedule the timer for the next interrupt time, if the pin is still running.
//
- if( m_PinState == PinRunning )
+ if (m_PinState == PinRunning)
{
LARGE_INTEGER NextTime;
NextTime.QuadPart = m_StartTime.QuadPart +
- (m_TimePerFrame * (m_InterruptTime + 1));
+ (m_TimePerFrame * (m_InterruptTime + 1));
#ifdef ENABLE_TRACING // To keep us from a tight spin when trying to debug this code...
LARGE_INTEGER Now;
KeQuerySystemTime(&Now);
- if( Now.QuadPart >= NextTime.QuadPart )
+ if (Now.QuadPart >= NextTime.QuadPart)
{
- NextTime.QuadPart = 0LL - m_TimePerFrame ;
+ NextTime.QuadPart = 0LL - m_TimePerFrame;
}
#endif
- m_IsrTimer.Set( NextTime );
+ m_IsrTimer.Set(NextTime);
}
}
diff --git a/avstream/avscamera/sys/imagecapture.cpp b/avstream/avscamera/sys/imagecapture.cpp
index 06d334d3..7ba53fa4 100644
--- a/avstream/avscamera/sys/imagecapture.cpp
+++ b/avstream/avscamera/sys/imagecapture.cpp
@@ -121,9 +121,11 @@ Close(
{
PAGED_CODE();
+ // Reset the image sim's counts and queues.
Reset();
- return STATUS_SUCCESS;
+ // Call the base Close operation.
+ return CCapturePin::Close(Irp);
}
// ImageCapturePinDispatch:
diff --git a/avstream/avshws/README.md b/avstream/avshws/README.md
index e905451d..9a222462 100644
--- a/avstream/avshws/README.md
+++ b/avstream/avshws/README.md
@@ -5,89 +5,93 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: AVStream simulated hardware sample driver (Avshws)
- platform: WDM
- language: cpp
- category: Camera
- description: A simulated hardware sample driver providing a pin-centric capture driver to simulate AV capture hardware.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620185
---->
-
# AVStream simulated hardware sample driver (Avshws)
-The AVStream simulated hardware sample driver (Avshws) provides a pin-centric [AVStream](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554240) capture driver for a simulated piece of hardware. This streaming media driver performs video captures at 320 x 240 pixels in either RGB24 or YUV422 format using direct memory access (DMA) into capture buffers. The purpose of the sample is to demonstrate how to write a pin-centric AVStream minidriver. The sample also shows how to implement DMA by using the related functionality provided by the AVStream class driver.
+The AVStream simulated hardware sample driver (Avshws) provides a pin-centric [AVStream](https://docs.microsoft.com/windows-hardware/drivers/stream/avstream-overview) capture driver for a simulated piece of hardware. This streaming media driver performs video captures at 320 x 240 pixels in either RGB24 or YUV422 format using direct memory access (DMA) into capture buffers. The purpose of the sample is to demonstrate how to write a pin-centric AVStream minidriver. The sample also shows how to implement DMA by using the related functionality provided by the AVStream class driver.
This sample features enhanced parameter validation and overflow detection.
-Provision a target computer
----------------------------
+## Provision a target computer
After you've installed the sample on your host computer, run Visual Studio, and from the **File** menu, select **Open**, then **Project/Solution...**, navigate to the directory where you've copied the Avshws sample, then to the C++ folder, and select **avshws.vcxproj** (the VC++ Project).
-In the **Solution Explorer** pane in Visual Studio, at the top is **Solution 'avshws'**. Right-click this and select **Configuration Manager**. Follow the instructions in [Building a Driver with the WDK](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644) to set the platform, operating system, and debug configuration you want to use, and to build the sample. This sample project will automatically sign the driver package.
+In the **Solution Explorer** pane in Visual Studio, at the top is **Solution 'avshws'**. Right-click this and select **Configuration Manager**. Follow the instructions in [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver) to set the platform, operating system, and debug configuration you want to use, and to build the sample. This sample project will automatically sign the driver package.
-Provision your target computer using instructions in, for example, [Preparing a Computer for Provisioning](http://msdn.microsoft.com/en-us/library/windows/hardware/dn265573). Ensure that in the **Network and Sharing Center** control panel your target computer has **Network Discovery** and **File and Printer Sharing** enabled.
+Provision your target computer using instructions in, for example, [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1). Ensure that in the **Network and Sharing Center** control panel your target computer has **Network Discovery** and **File and Printer Sharing** enabled.
-Deploy the driver to the target computer
-----------------------------------------
+## Deploy the driver to the target computer
-Now you can deploy the Avshws driver that you've just built to the target computer, using guidance in [Deploying a Driver to a Test Computer](http://msdn.microsoft.com/en-us/library/windows/hardware/hh454834). Specifically, find the package file under the **Package** folder in the Avshws solution. Right-click **package** and select **Properties**. Under Configuration Properties, click **Driver install** and then **Deployment**. Here you must click the check box for **Enable deployment**, and then click the button to the right of **\<Configure Computer...\>**. In the next dialog you enter the **Target Computer Name** and can let the host computer automatically provision the target computer and set up debugger options.
+Now you can deploy the Avshws driver that you've just built to the target computer, using guidance in [Deploying a Driver to a Test Computer](https://docs.microsoft.com/windows-hardware/drivers/develop/deploying-a-driver-to-a-test-computer). Specifically, find the package file under the **Package** folder in the Avshws solution. Right-click **package** and select **Properties**. Under Configuration Properties, click **Driver install** and then **Deployment**. Here you must click the check box for **Enable deployment**, and then click the button to the right of **\<Configure Computer...\>**. In the next dialog you enter the **Target Computer Name** and can let the host computer automatically provision the target computer and set up debugger options.
Finally, in Visual Studio, from the **Build** menu select **Deploy Solution** to deploy the sample to the target computer. On the target computer, you can see the deployed package in the **%Systemdrive%\\drivertest\\drivers** folder.
-Install the driver
-------------------
+## Install the driver
On the target computer, open Device Manager, and follow these steps:
-1. In the **Action** menu, click **Add Legacy Hardware**, and the **Add Hardware Wizard** appears. Click **Next** and then **Next** again.
-2. In the **Add Hardware** window, select **Show All Devices**.
-3. In the **Manufacturer** list in the left pane, click **Microsoft**.
-4. You should see the **AVStream Simulated Hardware Sample** in the **Model** pane on the right. Click this and then click **Next**.
-5. Click **Next** again to install the driver, and then click **Finish** to exit the wizard.
+1. In the **Action** menu, click **Add Legacy Hardware**, and the **Add Hardware Wizard** appears. Click **Next** and then **Next** again.
+
+1. In the **Add Hardware** window, select **Show All Devices**.
+
+1. In the **Manufacturer** list in the left pane, click **Microsoft**.
+
+1. You should see the **AVStream Simulated Hardware Sample** in the **Model** pane on the right. Click this and then click **Next**.
+
+1. Click **Next** again to install the driver, and then click **Finish** to exit the wizard.
The sample driver now appears in the Device Manager console tree under **Sound, video and game controllers**. The Avshws INF file will be on the system drive at, for example, **...windows\\System32\\DriverStore\\FileRepository\\**.
-Sample code hierarchy
----------------------
+## Sample code hierarchy
-[**DriverEntry**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff558717) in Device.cpp is the initial point of entry into the driver. This routine passes control to AVStream by calling the [**KsInitializeDriver**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff562683) function. In this call, the minidriver passes the device descriptor, an AVStream structure that recursively defines the AVStream object hierarchy for a driver. This is common behavior for an AVStream minidriver.
+[**DriverEntry**](https://docs.microsoft.com/previous-versions//ff558717(v=vs.85)) in Device.cpp is the initial point of entry into the driver. This routine passes control to AVStream by calling the [**KsInitializeDriver**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/nf-ks-ksinitializedriver) function. In this call, the minidriver passes the device descriptor, an AVStream structure that recursively defines the AVStream object hierarchy for a driver. This is common behavior for an AVStream minidriver.
-At device start time, a simulated piece of capture hardware is created (the **CHardwareSimulation** class), and a DMA adapter is acquired from the operating system and is registered with AVStream by calling the [**KsDeviceRegisterAdapterObject**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff561687) function. This call is required for a sample that performs DMA access directly into the capture buffers, instead of using DMA access to write to a common buffer. The driver creates the [KS Filter](http://msdn.microsoft.com/en-us/library/windows/hardware/ff567644) for this device dynamically by calling the [**KsCreateFilterFactory**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff561650) function.
+At device start time, a simulated piece of capture hardware is created (the **CHardwareSimulation** class), and a DMA adapter is acquired from the operating system and is registered with AVStream by calling the [**KsDeviceRegisterAdapterObject**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/nf-ks-ksdeviceregisteradapterobject) function. This call is required for a sample that performs DMA access directly into the capture buffers, instead of using DMA access to write to a common buffer. The driver creates the [KS Filter](https://docs.microsoft.com/windows-hardware/drivers/stream/ks-filters) for this device dynamically by calling the [**KsCreateFilterFactory**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/nf-ks-kscreatefilterfactory) function.
-Filter.cpp is where the sample lays out the [**KSPIN\_DESCRIPTOR\_EX**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff563534) structure for the single video pin. In addition, a [**KSFILTER\_DISPATCH**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff562554) structure and a [**KSFILTER\_DESCRIPTOR**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff562553) structure are provided in this source file. The filter dispatch provides only a create dispatch, a routine that is included in Filter.cpp. The process dispatch is provided on the pin because this is a pin-centric sample.
+Filter.cpp is where the sample lays out the [**KSPIN\_DESCRIPTOR\_EX**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_kspin_descriptor_ex) structure for the single video pin. In addition, a [**KSFILTER\_DISPATCH**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_ksfilter_dispatch) structure and a [**KSFILTER\_DESCRIPTOR**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_ksfilter_descriptor) structure are provided in this source file. The filter dispatch provides only a create dispatch, a routine that is included in Filter.cpp. The process dispatch is provided on the pin because this is a pin-centric sample.
-Capture.cpp contains source for the video capture pin on the capture filter. This is where the [**KSPIN\_DISPATCH**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff563535) structure for the unique pin is provided. This dispatch structure specifies a *Process* callback routine, also defined in this source file. This routine is where stream pointer manipulation and cloning occurs.
+Capture.cpp contains source for the video capture pin on the capture filter. This is where the [**KSPIN\_DISPATCH**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_kspin_dispatch) structure for the unique pin is provided. This dispatch structure specifies a *Process* callback routine, also defined in this source file. This routine is where stream pointer manipulation and cloning occurs.
The process callback is one of two routines of interest in Capture.cpp that demonstrate how to perform DMA transfers with AVStream functionality. The other is the **CCapturePin::CompleteMappings** method. These two methods show how to use the queue, obtain clone pointers, use scatter/gather lists, and perform other DMA-related tasks.
For more information, see the comments in all .cpp files.
-Run the sample
---------------
+## Run the sample
Follow these steps to see how the sample driver functions:
-1. After installation has completed, access the driver through the Graphedt tool. Graphedt.exe is available in the *tools* directory of the WDK.
-2. Before running GraphEdit, use the regsvr32 utility to register the proppage.dll DLL and to enable GraphEdit to display property pages for some of the built-in Microsoft DirectShow filters. Open an elevated command window with Administrator privileges, and navigate to the WDK or SDK *tools* directory that contains proppage.dll.
-3. On the command line, type regsvr32 proppage.dll. If the registration succeeds, you'll get a message, "DllRegisterServer in proppage.dll succeeded." Click OK.
-4. In the Graphedt tool, click the **Graph** menu and click **Insert Filters**. The sample appears under "WDM Streaming Capture Devices" as "avshws Source."
-5. Click **Insert Filter**. The sample appears in the graph as a single filter labeled, "avshws Source." There is one output pin, which is the video capture pin. This pin emits video in YUY2 format.
-6. Attach this filter to either a DirectShow Video Renderer or to the VMR default video renderer. Then click **Play**.
+1. After installation has completed, access the driver through the Graphedt tool. Graphedt.exe is available in the *tools* directory of the WDK.
+
+1. Before running GraphEdit, use the regsvr32 utility to register the proppage.dll DLL and to enable GraphEdit to display property pages for some of the built-in Microsoft DirectShow filters. Open an elevated command window with Administrator privileges, and navigate to the WDK or SDK *tools* directory that contains proppage.dll.
+
+1. On the command line, type regsvr32 proppage.dll. If the registration succeeds, you'll get a message, "DllRegisterServer in proppage.dll succeeded." Click OK.
+
+1. In the Graphedt tool, click the **Graph** menu and click **Insert Filters**. The sample appears under "WDM Streaming Capture Devices" as "avshws Source."
+
+1. Click **Insert Filter**. The sample appears in the graph as a single filter labeled, "avshws Source." There is one output pin, which is the video capture pin. This pin emits video in YUY2 format.
+
+1. Attach this filter to either a DirectShow Video Renderer or to the VMR default video renderer. Then click **Play**.
The output that is produced by the sample is a 320 x 240 pixel image of standard EIA-189-A color bars. In the middle of the image near the bottom, a clock appears over the image. This clock displays the elapsed time since the graph was introduced into the run state following the last stop. The clock display format is MINUTES:SECONDS.HUNDREDTHS.
In the upper-left corner of the image, a counter counts the number of frames that have been dropped since the graph was introduced into the run state after the last stop.
-Code tour
----------
-
-### File Manifest
+## File manifest
-File | Description
------|------------
-Avshws.h | Main header file for the sample
-Avshws.inf | Sample installation file
+| File | Description |
+| --- | --- |
+| Avshws.h | Main header file for the sample |
+| Avshws.inf | Sample installation file |
+Capture.cpp | Capture pin implementation for all capture pins on the sample filter.
+Capture.h | Capture pin level header for all capture pins on the sample filter.
+Device.cpp | Device level implementation of the simulated hardware.
+Device.h | Device level header for the simulated hardware.
+Filter.cpp | Capture filter implementation (including frame synthesis) for the fake capture filter.
+Filter.h | Filter level header for the filter-centric capture filter.
+HWSim.cpp | Hardware simulation implementation, including fake "DMA" transfers, scatter gather mapping handling, ISRs, etc.
+HWSim.h | Hardware simulation header.
+Image.cpp | Image synthesis and overlay code. These objects provide image synthesis (pixel, color-bar, etc) onto RGB24 and UYVY buffers as well as software string overlay into these buffers.
+Image.h | Image synthesis and overlay header.
+Purecall.h | _purecall stub necessary for virtual function usage in drivers.
diff --git a/avstream/avshws/avshws.inf b/avstream/avshws/avshws.inf
deleted file mode 100644
index 9bbbc42a..00000000
--- a/avstream/avshws/avshws.inf
+++ /dev/null
@@ -1,173 +0,0 @@
-;/*++
-;
-;Copyright (c) Microsoft Corporation. All rights reserved.
-;
-; THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
-; KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-; IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
-; PURPOSE.
-;
-;Module Name:
-;
-; AVSHWS.INF
-;
-;Abstract:
-;
-;
-;AVStream pin centric sample mini driver (AVSHWS.sys) installation file.
-;Supports x86, amd64, arm and arm64 platforms
-;
-;--*/
-
-[Version]
-signature="$WINDOWS NT$"
-Class=Camera
-ClassGuid={ca3e7ab9-b4c3-4ae6-8251-579ef933890f}
-Provider=%ProviderName%
-Catalogfile=avshws.cat
-DriverVer=08/31/2006,6.0.5600.0
-
-[SourceDisksNames]
-1000=%cdname%,,,
-
-[SourceDisksFiles]
-avshws.sys=1000
-
-[DestinationDirs]
-DefaultDestDir=12
-avshws.CopyFiles=12
-
-[avshws.CopyFiles]
-avshws.sys
-
-[Manufacturer]
-%ManufacturerName%=Standard,NTx86,NTamd64,ntarm,ntarm64
-
-[Standard.NTx86]
-%avshws.DeviceDesc%=avshws.NTx86,AVSHWS
-
-[Standard.NTamd64]
-%avshws.DeviceDesc%=avshws.NTamd64,AVSHWS
-
-[Standard.NTarm]
-%avshws.DeviceDesc%=avshws.NTarm,AVSHWS
-
-[Standard.NTarm64]
-%avshws.DeviceDesc%=avshws.NTarm64,AVSHWS
-
-;---------------------------------------------------------------
-; x 86 D D I n s t a l l
-;---------------------------------------------------------------
-
-[avshws.NTx86]
-Include=ks.inf, KSCAPTUR.inf
-Needs=KS.Registration,KSCAPTUR.Registration.NT
-CopyFiles=avshws.CopyFiles
-
-;---------------------------------------------------------------
-; A M D 64 D D I n s t a l l
-;---------------------------------------------------------------
-
-[avshws.NTamd64]
-Include=ks.inf,KSCAPTUR.inf
-Needs=KS.Registration,KSCAPTUR.Registration.NT
-CopyFiles=avshws.CopyFiles
-
-;---------------------------------------------------------------
-; A R M D D I n s t a l l
-;---------------------------------------------------------------
-
-[avshws.NTarm]
-Include=ks.inf,KSCAPTUR.inf
-Needs=KS.Registration,KSCAPTUR.Registration.NT
-CopyFiles=avshws.CopyFiles
-
-;---------------------------------------------------------------
-; A R M 64 D D I n s t a l l
-;---------------------------------------------------------------
-
-[avshws.NTarm64]
-Include=ks.inf,KSCAPTUR.inf
-Needs=KS.Registration,KSCAPTUR.Registration.NT
-CopyFiles=avshws.CopyFiles
-
-;---------------------------------------------------------------
-; I n t e r f a c e s
-;---------------------------------------------------------------
-
-[avshws.NTx86.Interfaces]
-AddInterface=%KSCATEGORY_CAPTURE%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO_CAMERA%,"GLOBAL",CaptureInterface.NT,0
-
-[avshws.NTamd64.Interfaces]
-AddInterface=%KSCATEGORY_CAPTURE%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO_CAMERA%,"GLOBAL",CaptureInterface.NT,0
-
-[avshws.NTarm.Interfaces]
-AddInterface=%KSCATEGORY_CAPTURE%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO_CAMERA%,"GLOBAL",CaptureInterface.NT,0
-
-[avshws.NTarm64.Interfaces]
-AddInterface=%KSCATEGORY_CAPTURE%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO_CAMERA%,"GLOBAL",CaptureInterface.NT,0
-
-[CaptureInterface.NT]
-AddReg=avshws.Reader.AddReg
-
-;---------------------------------------------------------------
-; A d d R e g
-;---------------------------------------------------------------
-
-[avshws.Reader.AddReg]
-HKR,,CLSID,,%Proxy.CLSID%
-HKR,,FriendlyName,,%avshws.Reader.FriendlyName%
-
-;---------------------------------------------------------------
-; S e r v i c e s
-;---------------------------------------------------------------
-
-[avshws.NTx86.Services]
-AddService=avshws, 0x00000002, avshws.ServiceInstall
-
-[avshws.NTamd64.Services]
-AddService=avshws, 0x00000002, avshws.ServiceInstall
-
-[avshws.NTarm.Services]
-AddService=avshws, 0x00000002, avshws.ServiceInstall
-
-[avshws.NTarm64.Services]
-AddService=avshws, 0x00000002, avshws.ServiceInstall
-
-[avshws.ServiceInstall]
-DisplayName=%avshws.DeviceDesc%
-ServiceType=%SERVICE_KERNEL_DRIVER%
-StartType=%SERVICE_DEMAND_START%
-ErrorControl=%SERVICE_ERROR_NORMAL%
-ServiceBinary=%12%\avshws.sys
-
-;---------------------------------------------------------------
-; S t r i n g s
-;---------------------------------------------------------------
-
-[Strings]
-; non-localizable
-Proxy.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
-KSCATEGORY_CAPTURE="{65E8773D-8F56-11D0-A3B9-00A0C9223196}"
-KSCATEGORY_VIDEO="{6994AD05-93EF-11D0-A3CC-00A0C9223196}"
-KSCATEGORY_VIDEO_CAMERA="{E5323777-F976-4f5b-9B55-B94699C46E44}"
-
-SERVICE_KERNEL_DRIVER=1
-SERVICE_DEMAND_START=3
-SERVICE_ERROR_NORMAL=1
-REG_DWORD=0x00010001
-
-;localizable
-ProviderName="TODO-Set-Provider"
-ManufacturerName="TODO-Set-Manufacturer"
-avshws.DeviceDesc="AVStream Simulated Hardware Sample"
-avshws.Reader.FriendlyName="avshws Source"
-cdname="AVSHWS Installation Disk" \ No newline at end of file
diff --git a/avstream/avshws/avshws.inx b/avstream/avshws/avshws.inx
new file mode 100644
index 00000000..238ce187
--- /dev/null
+++ b/avstream/avshws/avshws.inx
Binary files differ
diff --git a/avstream/avshws/avshws.sln b/avstream/avshws/avshws.sln
index 877a4ca9..ba4ee493 100644
--- a/avstream/avshws/avshws.sln
+++ b/avstream/avshws/avshws.sln
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.28307.136
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29519.181
MinimumVisualStudioVersion = 12.0
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avshws", "avshws.vcxproj", "{77FA53EC-3637-411C-B708-C8EED64543A4}"
EndProject
@@ -45,4 +45,3 @@ Global
SolutionGuid = {5EBC439F-EC31-448F-B129-434D42485011}
EndGlobalSection
EndGlobal
- \ No newline at end of file
diff --git a/avstream/avshws/avshws.vcxproj b/avstream/avshws/avshws.vcxproj
index 115a05c9..407048b7 100644
--- a/avstream/avshws/avshws.vcxproj
+++ b/avstream/avshws/avshws.vcxproj
@@ -182,6 +182,9 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ResourceCompile>
@@ -200,6 +203,9 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ResourceCompile>
@@ -218,6 +224,9 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
<ResourceCompile>
@@ -272,6 +281,9 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<ResourceCompile>
@@ -319,7 +331,7 @@
<ResourceCompile Include="avshws.rc" />
</ItemGroup>
<ItemGroup>
- <Inf Exclude="@(Inf)" Include="*.inf" />
+ <Inf Exclude="@(Inf)" Include="*.inf;*.inx" />
<FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
</ItemGroup>
<ItemGroup>
diff --git a/avstream/avshws/capture.cpp b/avstream/avshws/capture.cpp
index d68ce1da..13ddbfc0 100644
--- a/avstream/avshws/capture.cpp
+++ b/avstream/avshws/capture.cpp
@@ -265,7 +265,7 @@ Return Value:
VideoInfoHeader);
m_VideoInfoHeader = reinterpret_cast <PKS_VIDEOINFOHEADER> (
- ExAllocatePoolWithTag (
+ ExAllocatePoolZero (
NonPagedPoolNx,
KS_SIZE_VIDEOHEADER (ConnectionHeader),
AVSHWS_POOLTAG
diff --git a/avstream/avshws/device.cpp b/avstream/avshws/device.cpp
index 44fc9704..845e938f 100644
--- a/avstream/avshws/device.cpp
+++ b/avstream/avshws/device.cpp
@@ -31,13 +31,7 @@ PVOID operator new
POOL_TYPE poolType
)
{
- PVOID result = ExAllocatePoolWithTag(poolType,iSize,'wNCK');
-
- if (result) {
- RtlZeroMemory(result,iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType,iSize,'wNCK');
}
PVOID operator new
@@ -50,13 +44,7 @@ PVOID operator new
ULONG tag
)
{
- PVOID result = ExAllocatePoolWithTag(poolType,iSize,tag);
-
- if (result) {
- RtlZeroMemory(result,iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType,iSize,tag);
}
PVOID
@@ -69,14 +57,7 @@ operator new[](
ULONG tag
)
{
- PVOID result = ExAllocatePoolWithTag(poolType, iSize, tag);
-
- if (result)
- {
- RtlZeroMemory(result, iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType, iSize, tag);
}
/*++
diff --git a/avstream/avshws/hwsim.cpp b/avstream/avshws/hwsim.cpp
index 1e813bc2..46d6be62 100644
--- a/avstream/avshws/hwsim.cpp
+++ b/avstream/avshws/hwsim.cpp
@@ -219,7 +219,7 @@ Return Value:
// Allocate a scratch buffer for the synthesizer.
//
m_SynthesisBuffer = reinterpret_cast <PUCHAR> (
- ExAllocatePoolWithTag (
+ ExAllocatePoolZero (
NonPagedPoolNx,
m_ImageSize,
AVSHWS_POOLTAG
diff --git a/avstream/avshws/makefile b/avstream/avshws/makefile
new file mode 100644
index 00000000..e8428c0d
--- /dev/null
+++ b/avstream/avshws/makefile
@@ -0,0 +1,15 @@
+!IF 0
+
+Copyright (C) Microsoft Corporation, 1999 - 1999
+
+Module Name:
+
+ makefile.
+
+!ENDIF
+
+!if "$(DDK_TARGET_OS)"=="Win2K"
+!message This sample is not intended to target the Windows 2000 platform.
+!else
+!INCLUDE $(NTMAKEENV)\makefile.def
+!endif \ No newline at end of file
diff --git a/avstream/avssamp/Filter.cpp b/avstream/avssamp/Filter.cpp
index 524d6ad8..b3b70c30 100644
--- a/avstream/avssamp/Filter.cpp
+++ b/avstream/avssamp/Filter.cpp
@@ -268,17 +268,17 @@ Return Value:
//
PKSDATARANGE_AUDIO DataRangeAudio =
reinterpret_cast <PKSDATARANGE_AUDIO> (
- ExAllocatePoolWithTag (PagedPool, sizeof (KSDATARANGE_AUDIO), AVSSMP_POOLTAG)
+ ExAllocatePoolZero (PagedPool, sizeof (KSDATARANGE_AUDIO), AVSSMP_POOLTAG)
);
PKSDATARANGE_AUDIO *DataRanges =
reinterpret_cast <PKSDATARANGE_AUDIO *> (
- ExAllocatePoolWithTag (PagedPool, sizeof (PKSDATARANGE_AUDIO), AVSSMP_POOLTAG)
+ ExAllocatePoolZero (PagedPool, sizeof (PKSDATARANGE_AUDIO), AVSSMP_POOLTAG)
);
PKSALLOCATOR_FRAMING_EX Framing =
reinterpret_cast <PKSALLOCATOR_FRAMING_EX> (
- ExAllocatePoolWithTag (PagedPool, sizeof (KSALLOCATOR_FRAMING_EX), AVSSMP_POOLTAG)
+ ExAllocatePoolZero (PagedPool, sizeof (KSALLOCATOR_FRAMING_EX), AVSSMP_POOLTAG)
);
if (DataRangeAudio && DataRanges && Framing) {
diff --git a/avstream/avssamp/README.md b/avstream/avssamp/README.md
index 10dee5b9..42f0d393 100644
--- a/avstream/avssamp/README.md
+++ b/avstream/avssamp/README.md
@@ -5,62 +5,54 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: AVStream filter-centric simulated capture sample driver (Avssamp)
- platform: WDM
- language: cpp
- category: Camera
- description: An AVStream filter-centric simulated capture sample driver with functional audio.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620186
---->
-
# AVStream filter-centric simulated capture sample driver (Avssamp)
-The AVStream filter-centric simulated capture sample driver (Avssamp) provides a filter-centric [AVStream](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554240) capture driver with functional audio. This streaming media driver performs video captures at 320 x 240 pixel resolution in RGB24 or YUV422 format while playing a user-provided Pulse Code Modulation (PCM) wave audio file in a loop. The sample demonstrates how to write a filter-centric AVStream minidriver.
+The AVStream filter-centric simulated capture sample driver (Avssamp) provides a filter-centric [AVStream](https://docs.microsoft.com/windows-hardware/drivers/stream/avstream-overview) capture driver with functional audio. This streaming media driver performs video captures at 320 x 240 pixel resolution in RGB24 or YUV422 format while playing a user-provided Pulse Code Modulation (PCM) wave audio file in a loop. The sample demonstrates how to write a filter-centric AVStream minidriver.
+
+## Installation instructions
+
+1. Copy AVssamp.inf to a directory, for example, C:\\Avstream\\.
+
+1. In this directory, create a new subdirectory named objfre\_x86 if the target operating system is x86-based, or objfre\_amd64 for an x64-based target operating system, for example, C:\\AVstream\\objfre\_x86\\.
-Installation instructions
--------------------------
+1. Copy the processor-appropriate Avssamp.sys file to the objfre\_\* directory.
-1. Copy AVssamp.inf to a directory, for example, C:\\Avstream\\.
-2. In this directory, create a new subdirectory named objfre\_x86 if the target operating system is x86-based, or objfre\_amd64 for an x64-based target operating system, for example, C:\\AVstream\\objfre\_x86\\.
-3. Copy the processor-appropriate Avssamp.sys file to the objfre\_\* directory.
-4. Start a command prompt with administrator privilege and run the processor-specific WDK tool Devcon.exe to launch the installation. For example:
+1. Start a command prompt with administrator privilege and run the processor-specific WDK tool Devcon.exe to launch the installation. For example:
`C:\WinDDK\7600.16384.0\tools\devcon\i386\devcon.exe install C:\AVstream\avssamp.inf SW\{20698827-7099-4c4e-861A-4879D639A35F}`
-Programming Tour
-----------------
+## Programming tour
-[**DriverEntry**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff558717) in Avssamp.cpp is the initial point of entry into the driver. This routine passes control to AVStream by calling [**KsInitializeDriver**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff562683). In this call, the minidriver passes the device descriptor, an AVStream structure that recursively defines the AVStream object hierarchy for a driver. This is common behavior for an AVStream minidriver.
+[**DriverEntry**](https://docs.microsoft.com/previous-versions//ff558717(v=vs.85)) in Avssamp.cpp is the initial point of entry into the driver. This routine passes control to AVStream by calling [**KsInitializeDriver**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/nf-ks-ksinitializedriver). In this call, the minidriver passes the device descriptor, an AVStream structure that recursively defines the AVStream object hierarchy for a driver. This is common behavior for an AVStream minidriver.
-Filter.cpp is where the sample lays out the [**KSPIN\_DESCRIPTOR\_EX**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff563534) structure for the single capture pin. Audio.cpp contains the **KSPIN\_DESCRIPTOR\_EX** structure for the audio capture pin. This pin is dynamically created only if C:\\avssamp.wav exists and is a valid and readable PCM format wave file.
+Filter.cpp is where the sample lays out the [**KSPIN\_DESCRIPTOR\_EX**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_kspin_descriptor_ex) structure for the single capture pin. Audio.cpp contains the **KSPIN\_DESCRIPTOR\_EX** structure for the audio capture pin. This pin is dynamically created only if C:\\avssamp.wav exists and is a valid and readable PCM format wave file.
-The filter dispatch structure [**KSFILTER\_DISPATCH**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff562554) in Filter.cpp provides dispatches to create and process data. The **DispatchProcess** method is defined inline in Filter.h. It calls the **Process** method in Filter.cpp in the context of the **CCaptureFilter** class. Be aware that the process dispatch is provided in **KSFILTER\_DISPATCH** because this sample is filter-centric.
+The filter dispatch structure [**KSFILTER\_DISPATCH**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_ksfilter_dispatch) in Filter.cpp provides dispatches to create and process data. The **DispatchProcess** method is defined inline in Filter.h. It calls the **Process** method in Filter.cpp in the context of the **CCaptureFilter** class. Be aware that the process dispatch is provided in **KSFILTER\_DISPATCH** because this sample is filter-centric.
-Audio.cpp lays out a [**KSPIN\_DISPATCH**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff563535) pin dispatch structure, which contains the dispatch table for the audio pin. Be aware that the **Process** member of this structure is **NULL** because the sample is filter-centric. Similarly, Video.cpp contains the **KSPIN\_DISPATCH** structure for the video capture pin, again with the **Process** member set to **NULL**.
+Audio.cpp lays out a [**KSPIN\_DISPATCH**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_kspin_dispatch) pin dispatch structure, which contains the dispatch table for the audio pin. Be aware that the **Process** member of this structure is **NULL** because the sample is filter-centric. Similarly, Video.cpp contains the **KSPIN\_DISPATCH** structure for the video capture pin, again with the **Process** member set to **NULL**.
For more information, see the comments in all .cpp files.
-File Manifest
--------------
+## File manifest
-File | Description
------|----------
-Audio.cpp | Audio capture pin implementation.
-Audio.h | Header file for Audio.cpp.
-Avssamp.cpp | Main file for the AVStream filter-centric sample.
-Avssamp.h | Main header for the AVStream filter-centric sample.
-Avssamp.inf | Installation information for the AVStream sample driver (avssamp.sys).
-Capture.cpp | Capture pin implementation for all capture pins on the sample filter.
-Capture .h | Capture pin level header for all capture pins on the sample filter.
-Filter.cpp | Capture filter implementation (including frame synthesis) for the fake capture filter.
-Filter.h | Filter level header for the filter-centric capture filter.
-Image.cpp | Image synthesis and overlay code. These objects provide image synthesis (pixel, color-bar, etc) onto RGB24 and UYVY buffers as well as software string overlay into these buffers.
-Image.h | Image synthesis and overlay header.
-Purecall.h | _purecall stub necessary for virtual function usage in drivers.
-Video.cpp | Video capture pin implementation.
-Video.h | Video capture pin header.
-Wave.cpp | Wave object implementation
-Wave.h | Wave object header
+| File | Description |
+| --- | --- |
+| Audio.cpp | Audio capture pin implementation |
+| Audio.h | Header file for Audio.cpp |
+| Avssamp.cpp | Main file for the AVStream filter-centric sample. |
+| Avssamp.h | Main header for the AVStream filter-centric sample. |
+| Avssamp.inf | Installation information for the AVStream sample driver (avssamp.sys). |
+| Capture.cpp | Capture pin implementation for all capture pins on the sample filter. |
+| Capture .h | Capture pin level header for all capture pins on the sample filter. |
+| Filter.cpp | Capture filter implementation (including frame synthesis) for the fake capture filter. |
+| Filter.h | Filter level header for the filter-centric capture filter. |
+| Image.cpp | Image synthesis and overlay code. These objects provide image synthesis (pixel, color-bar, etc) onto RGB24 and UYVY buffers as well as software string overlay into these buffers. |
+| Image.h | Image synthesis and overlay header |
+| Purecall.h | _purecall stub necessary for virtual function usage in drivers. |
+| Video.cpp | Video capture pin implementation |
+| Video.h | Video capture pin header |
+| Wave.cpp | Wave object implementation |
+| Wave.h | Wave object header |
diff --git a/avstream/avssamp/avssamp.cpp b/avstream/avssamp/avssamp.cpp
index 68741c9e..1ba03089 100644
--- a/avstream/avssamp/avssamp.cpp
+++ b/avstream/avssamp/avssamp.cpp
@@ -38,13 +38,7 @@ PVOID operator new
POOL_TYPE poolType
)
{
- PVOID result = ExAllocatePoolWithTag(poolType,iSize,'wNCK');
-
- if (result) {
- RtlZeroMemory(result,iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType,iSize,'wNCK');
}
PVOID operator new
@@ -57,13 +51,7 @@ PVOID operator new
ULONG tag
)
{
- PVOID result = ExAllocatePoolWithTag(poolType,iSize,tag);
-
- if (result) {
- RtlZeroMemory(result,iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType,iSize,tag);
}
/*++
diff --git a/avstream/avssamp/avssamp.inf b/avstream/avssamp/avssamp.inf
deleted file mode 100644
index 00003e78..00000000
--- a/avstream/avssamp/avssamp.inf
+++ /dev/null
@@ -1,93 +0,0 @@
-; Copyright (c) Microsoft Corporation. All rights reserved.
-;
-; avssamp.INF -- This file contains installation information for the filter-based
-; AVStream sample driver avssamp.sys
-;
-; Note:
-;
-; This INF expects the following hierarchy in the installation folder:
-;
-; \
-; avssamp.inf
-; avssamp.sys
-;
-
-[Version]
-Signature="$Windows NT$"
-Class=Camera
-ClassGuid={ca3e7ab9-b4c3-4ae6-8251-579ef933890f}
-Provider=%ProviderName%
-CatalogFile=avssamp.cat
-DriverVer=09/30/2004,1.0.0.0
-
-[SourceDisksNames]
-1000 = %cdname%,,,
-
-[SourceDisksFiles]
-avssamp.sys = 1000
-
-[ControlFlags]
-ExcludeFromSelect=*
-
-[DestinationDirs]
-avssamp.CopyFiles=12
-
-[Manufacturer]
-%ManufacturerName%=Standard,NTamd64,NTx86
-
-;---------------------------------------------------------------
-; The preferred method to install as a Root-enumerated device.
-; NOTE: DO NOT INCLUDE THIS FOR A HARDWARE DRIVER!
-;---------------------------------------------------------------
-
-[DeviceInstall32]
-AddDevice = ROOT\SW\{20698827-7099-4c4e-861A-4879D639A35F},,avssamp_RootEnumInstall
-
-[avssamp_RootEnumInstall]
-HardwareIds = SW\{20698827-7099-4c4e-861A-4879D639A35F}
-;---------------------------------------------------------------
-
-[Standard.NTx86]
-%avssamp.DeviceDesc%=avssamp,SW\{20698827-7099-4c4e-861A-4879D639A35F}
-
-[Standard.NTamd64]
-%avssamp.DeviceDesc%=avssamp,SW\{20698827-7099-4c4e-861A-4879D639A35F}
-
-[avssamp.NT]
-include=ks.inf,kscaptur.inf
-needs=KS.Registration,KSCAPTUR.Registration.NT
-CopyFiles=avssamp.CopyFiles
-
-[avssamp.CopyFiles]
-avssamp.sys
-
-[avssamp.NT.Services]
-AddService=avssamp, 0x00000002, avssamp.ServiceInstall
-
-[avssamp.ServiceInstall]
-DisplayName=%avssamp.DeviceDesc%
-ServiceType=%SERVICE_KERNEL_DRIVER%
-StartType=%SERVICE_DEMAND_START%
-ErrorControl=%SERVICE_ERROR_NORMAL%
-ServiceBinary=%12%\avssamp.sys
-
-[Strings]
-; non-localizable
-Proxy.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
-avssamp.DeviceId="{20698827-7099-4c4e-861A-4879D639A35F}"
-KSCATEGORY_CAPTURE="{65E8773D-8F56-11D0-A3B9-00A0C9223196}"
-KSSTRING_Filter="{9B365890-165F-11D0-A195-0020AFD156E4}"
-
-SERVICE_KERNEL_DRIVER=1
-SERVICE_DEMAND_START=3
-SERVICE_ERROR_NORMAL=1
-REG_EXPAND_SZ=0x00020000
-REG_DWORD=0x00010001
-
-;localizable
-ProviderName="TODO-Set-Provider"
-ManufacturerName="TODO-Set-Manufacturer"
-avssamp.DeviceDesc="AVStream Filter-Centric Sample Driver"
-avssamp.Reader.FriendlyName="avssamp Source"
-
-cdname="Disk 1"
diff --git a/avstream/avssamp/avssamp.inx b/avstream/avssamp/avssamp.inx
new file mode 100644
index 00000000..61d66fa3
--- /dev/null
+++ b/avstream/avssamp/avssamp.inx
Binary files differ
diff --git a/avstream/avssamp/avssamp.vcxproj b/avstream/avssamp/avssamp.vcxproj
index 21c292d2..58d7992d 100644
--- a/avstream/avssamp/avssamp.vcxproj
+++ b/avstream/avssamp/avssamp.vcxproj
@@ -108,6 +108,9 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Link>
@@ -130,6 +133,9 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Link>
@@ -152,6 +158,9 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Link>
@@ -174,6 +183,9 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE;DEBUG_LEVEL=DEBUGLVL_BLAB;_WIN2K_COMPAT_SLIST_USAGE;_NO_SYS_GUID_OPERATOR_EQ_</PreprocessorDefinitions>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="audio.cpp" />
@@ -187,7 +199,7 @@
<ResourceCompile Include="avssamp.rc" />
</ItemGroup>
<ItemGroup>
- <Inf Exclude="@(Inf)" Include="*.inf" />
+ <Inf Exclude="@(Inf)" Include="*.inf;*.inx" />
<FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
</ItemGroup>
<ItemGroup>
diff --git a/avstream/avssamp/avssamp.vcxproj.Filters b/avstream/avssamp/avssamp.vcxproj.Filters
index 9b056e4d..8d345831 100644
--- a/avstream/avssamp/avssamp.vcxproj.Filters
+++ b/avstream/avssamp/avssamp.vcxproj.Filters
@@ -49,4 +49,32 @@
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Include="*.inf;*.inx">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/avstream/avssamp/makefile b/avstream/avssamp/makefile
new file mode 100644
index 00000000..ab62d10e
--- /dev/null
+++ b/avstream/avssamp/makefile
@@ -0,0 +1,15 @@
+!IF 0
+
+Copyright (C) Microsoft Corporation, 1999 - 1999
+
+Module Name:
+
+ makefile.
+
+!ENDIF
+
+!if "$(DDK_TARGET_OS)"=="Win2K"
+!message This sample is not intended to target the Windows 2000 platform.
+!else
+!INCLUDE $(NTMAKEENV)\makefile.def
+!endif
diff --git a/avstream/avssamp/video.cpp b/avstream/avssamp/video.cpp
index d2291a24..0f3f7c7d 100644
--- a/avstream/avssamp/video.cpp
+++ b/avstream/avssamp/video.cpp
@@ -210,7 +210,7 @@ Return Value:
VideoInfoHeader);
m_VideoInfoHeader = reinterpret_cast <PKS_VIDEOINFOHEADER> (
- ExAllocatePoolWithTag (
+ ExAllocatePoolZero (
NonPagedPool,
KS_SIZE_VIDEOHEADER (ConnectionHeader),
AVSSMP_POOLTAG
@@ -557,7 +557,7 @@ Routine Description:
selected in order to change the format for the pin. In this case,
OldFormat will not be NULL.
- Validate that the format is acceptible and perform the actions necessary
+ Validate that the format is acceptable and perform the actions necessary
to change format if appropriate.
Arguments:
@@ -864,7 +864,7 @@ Return Value:
if (FromState == KSSTATE_STOP) {
m_SynthesisBuffer = reinterpret_cast <PUCHAR> (
- ExAllocatePoolWithTag (
+ ExAllocatePoolZero (
NonPagedPool,
m_VideoInfoHeader -> bmiHeader.biSizeImage,
AVSSMP_POOLTAG
diff --git a/avstream/avssamp/wave.cpp b/avstream/avssamp/wave.cpp
index 7af2f60a..de110e69 100644
--- a/avstream/avssamp/wave.cpp
+++ b/avstream/avssamp/wave.cpp
@@ -319,7 +319,7 @@ Return Value:
//
if (NT_SUCCESS (Status)) {
m_WaveData = reinterpret_cast <PUCHAR> (
- ExAllocatePoolWithTag (NonPagedPool, DataBlockSize, AVSSMP_POOLTAG)
+ ExAllocatePoolZero (NonPagedPool, DataBlockSize, AVSSMP_POOLTAG)
);
if (!m_WaveData) {
diff --git a/avstream/sampledevicemft/README.md b/avstream/sampledevicemft/README.md
index 640bc061..5bac05a8 100644
--- a/avstream/sampledevicemft/README.md
+++ b/avstream/sampledevicemft/README.md
@@ -5,42 +5,33 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Driver Device Transform Sample
- platform: WDM
- language: cpp
- category: Camera
- description: A driver device transform which loads in a process streaming an Avstream based camera device using Media Foundation.
- samplefwlink: https://go.microsoft.com/fwlink/?linkid=866747
---->
-
# Driver Device Transform Sample
-Illustrative example for a *Driver Device Transform* which loads in a process streaming an Avstream based camera device using Media Foundation.
+Illustrative example for a *Driver Device Transform* which loads in a process streaming an Avstream based camera device using Media Foundation.
-A *Driver Device Transform* is a new kind of a transform that's used with a specific camera when capturing video. The *Driver Device Transform* is also known as DeviceMFT because it is the first Device Transform applied to the video source. This *Driver Device Transform* is an alternative to the Driver MFT i.e. MFT0 in that, it caters to the source rather than the streams . An N stream source supporting DeviceMFT will have a single instance of the *Device Driver Transform* loaded, while MFT0 will have *N* instances for each pipeline process. The DeviceMFT can advertise multiple streams at the output, which can differ from the number of streams advertised by the source. This is analogous to having a user mode driver in the MF pipeline which intercepts and processes commands before they enter/ leave the Kernel mode driver loaded for the streaming source.
+A *Driver Device Transform* is a new kind of a transform that's used with a specific camera when capturing video. The *Driver Device Transform* is also known as DeviceMFT because it is the first Device Transform applied to the video source. This *Driver Device Transform* is an alternative to the Driver MFT, for example, MFT0 in that it caters to the source rather than the streams. An N stream source supporting DeviceMFT will have a single instance of the *Device Driver Transform* loaded, while MFT0 will have *N* instances for each pipeline process. The DeviceMFT can advertise multiple streams at the output, which can differ from the number of streams advertised by the source. This is analogous to having a user mode driver in the MF pipeline which intercepts and processes commands before they enter/ leave the Kernel mode driver loaded for the streaming source.
-In this sample, the Device Transform , when enabled, will replicate a photo sequence in the user mode from a one pin device . It acts as a passthrough for sources exposing more than one pins.
+In this sample, the Device Transform, when enabled, will replicate a photo sequence in the user mode from a one pin device. It acts as a passthrough for sources exposing more than one pins.
This sample is designed to be used with a specific camera. To run the sample, you need the your camera's device ID and device metadata package.
-Related topics
---------------
+## Related topics
-**Concepts**
+### Concepts
-[UWP device apps for cameras](http://go.microsoft.com/fwlink/p/?LinkId=306683)
+[UWP device apps for cameras](https://docs.microsoft.com/windows-hardware/drivers/devapps/uwp-device-apps-for-webcams)
-[Media Foundation Transforms](http://msdn.microsoft.com/en-us/library/windows/hardware/ms703138)
+[Media Foundation Transforms](https://docs.microsoft.com/windows/win32/medfound/media-foundation-transforms)
-[Roadmap for Developing Streaming Media Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff568130)
+[Streaming media device driver design guide](https://docs.microsoft.com/windows-hardware/drivers/stream)
-[Universal camera driver design guide for Windows 10](https://msdn.microsoft.com/en-us/Library/Windows/Hardware/dn937080)
+[Universal camera driver design guide for Windows 10](https://docs.microsoft.com/windows-hardware/drivers/stream/windows-10-technical-preview-camera-drivers-design-guide)
-**Samples**
+### Samples
-[Device app for camera sample](http://go.microsoft.com/fwlink/p/?linkid=249442)
+[Device app for camera sample](https://go.microsoft.com/fwlink/p/?linkid=249442)
-[Camera Capture UI sample](http://go.microsoft.com/fwlink/p/?linkid=249441%20)
+[Camera Capture UI sample](https://go.microsoft.com/fwlink/p/?linkid=249441%20)
diff --git a/avstream/sampledevicemft/basepin.cpp b/avstream/sampledevicemft/basepin.cpp
index d4220397..563ff610 100644
--- a/avstream/sampledevicemft/basepin.cpp
+++ b/avstream/sampledevicemft/basepin.cpp
@@ -3,6 +3,7 @@
#include "multipinmft.h"
#include "multipinmfthelpers.h"
#include "basepin.h"
+#include "contosodevice.h"
#ifdef MF_WPP
#include "basepin.tmh" //--REF_ANALYZER_DONT_REMOVE--
@@ -323,7 +324,7 @@ STDMETHODIMP CInPin::WaitForSetInputPinMediaChange()
if ( dwWait != WAIT_OBJECT_0 )
{
- hr = E_FAIL;
+ hr = HRESULT_FROM_WIN32(GetLastError());
goto done;
}
done:
@@ -384,23 +385,79 @@ HRESULT CInPin::SetInputStreamState(
return hr;
}
-void CInPin::ReleaseConnectedPins()
+STDMETHODIMP_(VOID) CInPin::ShutdownPin()
{
m_spSourceTransform = nullptr;
m_outpin = nullptr;
}
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+//
+// ForwardSecureBuffer()
+//
+// Parameters:
+// sample - The sample to send out for secure processing
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+// This helper function calls back to the AVstream driver for post-processing of a
+// secure buffer. This is done here as an example for simplicity. A more realistic
+// scenario might have you calling into an ISP driver that is not an AVstream driver.
+// To do that you would need to acquire a handle to that device and post an IOCTL.
+// That device would in turn need to have a secure companion driver (trustlet)
+// installed as part of the package to process the buffer.
+//
+HRESULT CInPin::ForwardSecureBuffer(
+ _In_ IMFSample *sample
+)
+{
+ DWORD bytesReturned = 0;
+ CONTOSODEVICE_PROCESSBUFFER_PAYLOAD payload = { 0 };
+ KSPROPERTY property = { 0 };
+
+ wil::com_ptr_nothrow<IMFMediaBuffer> mediaBuffer;
+ wil::com_ptr_nothrow<IMFSecureBuffer> secureBuffer;
+
+ // Set up our private KSPROPERTY to some sample avstream driver.
+ property.Set = PROPSETID_CONTOSODEVICE;
+ property.Id = KSPROPERTY_CONTOSODEVICE_PROCESSBUFFER;
+ property.Flags = KSPROPERTY_TYPE_SET;
+ // Set up the payload for that property. Includes the secure buffer ID and buffer length.
+ RETURN_IF_FAILED(sample->GetBufferByIndex(0, &mediaBuffer));
+ // Forward the buffer if it is secure.
+ if (mediaBuffer.try_query_to(&secureBuffer))
+ {
+ RETURN_IF_FAILED(secureBuffer->GetIdentifier(&payload.identifier));
+ RETURN_IF_FAILED(mediaBuffer->GetMaxLength(&payload.size));
+
+ // Log the buffer's secure ID and size for debugging.
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! identifier=%!GUID!, length=%d", &payload.identifier, payload.size);
+
+ // Send the KSPROPERTY synchronously to the driver.
+ RETURN_IF_FAILED(KsProperty(&property, sizeof(property), &payload, sizeof(payload), &bytesReturned));
+ }
+ return S_OK;
+}
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
//
//Output Pin Implementation
//
COutPin::COutPin(
_In_ ULONG ulPinId,
_In_opt_ CMultipinMft *pparent,
- _In_ IKsControl* pIksControl
+ _In_ IKsControl* pIksControl
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ , _In_ MFSampleAllocatorUsage allocatorUsage
+#endif
)
- : CBasePin( ulPinId, pparent ),
- m_firstSample( false ),
- m_queue(nullptr)
+ : CBasePin(ulPinId, pparent)
+ , m_firstSample(false)
+ , m_queue(nullptr)
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ , m_allocatorUsage(allocatorUsage)
+#endif
{
HRESULT hr = S_OK;
ComPtr<IMFAttributes> spAttributes;
@@ -507,6 +564,14 @@ STDMETHODIMP_(VOID) COutPin::SetFirstSample(
m_firstSample = fisrtSample;
}
+STDMETHODIMP_(VOID) COutPin::SetAllocator(
+ _In_ IMFVideoSampleAllocator* pAllocator
+)
+{
+ CAutoLock Lock(lock());
+ m_spDefaultAllocator = pAllocator;
+}
+
/*++
COutPin::FlushQueues
Description:
@@ -524,7 +589,7 @@ HRESULT COutPin::FlushQueues()
/*++
COutPin::ChangeMediaTypeFromInpin
Description:
-called from the Device Transfrom When the input media type is changed. This will result in
+called from the Device Transform when the input media type is changed. This will result in
the xvp being possibly installed in the queue if the media types set on the input
and the output dont match
--*/
@@ -542,7 +607,11 @@ HRESULT COutPin::ChangeMediaTypeFromInpin(
SetState(DeviceStreamState_Disabled);
DMFTCHECKHR_GOTO(FlushQueues(),done);
DMFTCHECKNULL_GOTO(m_queue,done, E_UNEXPECTED); // The queue should alwaye be set
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ hr = m_queue->RecreateTeeByAllocatorMode(pInMediatype, pOutMediaType, m_spDxgiManager.Get(), m_allocatorUsage, m_spDefaultAllocator.get());
+#else
hr = m_queue->RecreateTee(pInMediatype, pOutMediaType, m_spDxgiManager.Get());
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
if ( SUCCEEDED( hr ) )
{
(VOID)setMediaType( pOutMediaType );
@@ -583,10 +652,10 @@ STDMETHODIMP COutPin::GetOutputStreamInfo(
/*++
COutPin::ProcessOutput
Description:
- called from the Device Transfrom when the transform manager demands output samples..
+ called from the Device Transform when the transform manager demands output samples..
If we have samples we forward it.
- If we are a photo pin then we forward only if trigger is sent. We ask the devicetransform if we have recieved the transform or not.
- If we have recieved the sample and we are passing out a sample we should reset the trigger set on the Device Transform
+ If we are a photo pin then we forward only if trigger is sent. We ask the devicetransform if we have received the transform or not.
+ If we have received the sample and we are passing out a sample we should reset the trigger set on the Device Transform
--*/
STDMETHODIMP COutPin::ProcessOutput(_In_ DWORD dwFlags,
@@ -663,18 +732,9 @@ STDMETHODIMP CAsyncInPin::SendSample(_In_ IMFSample *pSample)
{
HRESULT hr = S_OK;
CAutoLock Lock(lock());
- if (!m_bFlushing)
+ if (SUCCEEDED(Active()))
{
DMFTCHECKHR_GOTO(MFPutWorkItem(m_dwWorkQueueId, static_cast<IMFAsyncCallback*>(m_asyncCallback.Get()), pSample), done);
- if (1 == InterlockedIncrement(&m_dwSamplesInFlight))
- {
- ResetEvent(m_hHandle);
- }
- }
- else
- {
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! 0x%p Pin Flushing %d",this, streamId());
- // Let the sample fall through
}
done:
return hr;
@@ -682,18 +742,20 @@ done:
STDMETHODIMP CAsyncInPin::Init()
{
- m_asyncCallback = new (std::nothrow) CDMFTAsyncCallback<CAsyncInPin, &CAsyncInPin::Invoke>(this);
+ m_asyncCallback = new (std::nothrow) CDMFTAsyncCallback<CAsyncInPin, &CAsyncInPin::Invoke>(this, m_dwWorkQueueId);
if (!m_asyncCallback)
throw bad_alloc();
return S_OK;
}
+// Pass a secure frame buffer to our AVstream driver.
HRESULT CAsyncInPin::Invoke( _In_ IMFAsyncResult* pResult )
{
HRESULT hr = S_OK;
ComPtr<IUnknown> spUnknown;
ComPtr<IMFSample> spSample;
+ DMFTCHECKHR_GOTO(Active(), done);
DMFTCHECKNULL_GOTO(pResult, done, E_UNEXPECTED);
DMFTCHECKHR_GOTO(pResult->GetState(&spUnknown), done);
@@ -701,46 +763,26 @@ HRESULT CAsyncInPin::Invoke( _In_ IMFAsyncResult* pResult )
DMFTCHECKNULL_GOTO(spSample.Get(), done, E_INVALIDARG);
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ //
+ // Do secure buffer post-processing.
+ //
+ RETURN_IF_FAILED(ForwardSecureBuffer(spSample.Get()));
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
COutPin *poPin = static_cast<COutPin*>(m_outpin.Get());
DMFTCHECKHR_GOTO(poPin->AddSample(spSample.Get(), this), done);
-
- if (0 == InterlockedDecrement(&m_dwSamplesInFlight))
- {
- // No samples in flight.. Set the Event
- SetEvent(m_hHandle);
- }
-
done:
return hr;
}
-
-
-STDMETHODIMP CAsyncInPin::FlushQueues()
+STDMETHODIMP_(VOID) CAsyncInPin::ShutdownPin()
{
- HRESULT hr = S_OK;
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Entering ");
- // Flush in async mode else it is a NOOP
- {
- CAutoLock Lock(lock());
- if (m_bFlushing)
- {
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Pin %d Already Flushing ", streamId());
- goto done;
- }
- m_bFlushing = TRUE;
- }
- //
- // Wait for the IOs to drain
- //
- WaitForSingleObject(m_hHandle, INFINITE);
+ CAutoLock Lock(lock());
+ if (m_asyncCallback.Get())
{
- CAutoLock Lock(lock());
- m_bFlushing = FALSE;
+ (VOID)m_asyncCallback->Shutdown(); //Break reference with the parent
}
-done:
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr);
- return hr;
+ CInPin::ShutdownPin();
}
//
@@ -808,6 +850,7 @@ STDMETHODIMP CTranslateOutPin::AddMediaType(
done:
return hr;
}
+
STDMETHODIMP_(BOOL) CTranslateOutPin::IsMediaTypeSupported(
_In_ IMFMediaType *pMediaType,
_When_(ppIMFMediaTypeFull != nullptr, _Outptr_result_maybenull_)
@@ -824,9 +867,10 @@ STDMETHODIMP_(BOOL) CTranslateOutPin::IsMediaTypeSupported(
if (found != m_TranslatedMediaTypes.end())
{
+ ComPtr<IMFMediaType> spMediaType = (*found).second;
if (ppIMFMediaTypeFull)
{
- *ppIMFMediaTypeFull = (*found).second;
+ *ppIMFMediaTypeFull = spMediaType.Detach();
}
return true;
}
@@ -836,3 +880,24 @@ STDMETHODIMP_(BOOL) CTranslateOutPin::IsMediaTypeSupported(
return CBasePin::IsMediaTypeSupported(pMediaType,ppIMFMediaTypeFull);
}
}
+
+HRESULT CTranslateOutPin::ChangeMediaTypeFromInpin(
+ _In_ IMFMediaType *pInMediatype,
+ _In_ IMFMediaType* pOutMediaType,
+ _In_ DeviceStreamState state)
+{
+ CAutoLock Lock(lock());
+ //
+ // Set the state to disabled and while going out we will reset the state back to the requested state
+ // Flush so that we drop any samples we have in store!!
+ //
+ SetState(DeviceStreamState_Disabled);
+ RETURN_IF_FAILED(FlushQueues());
+ RETURN_HR_IF_NULL(E_UNEXPECTED, m_queue); // The queue should always be set
+ RETURN_IF_FAILED(m_queue->RecreateTee(pInMediatype, pOutMediaType, m_spDxgiManager.Get()));
+
+ (VOID)setMediaType(pOutMediaType);
+ (VOID)SetState(state);
+
+ return S_OK;
+}
diff --git a/avstream/sampledevicemft/basepin.h b/avstream/sampledevicemft/basepin.h
index faafd759..cce17d0b 100644
--- a/avstream/sampledevicemft/basepin.h
+++ b/avstream/sampledevicemft/basepin.h
@@ -369,7 +369,7 @@ public:
__requires_lock_held(m_lock)
__inline HRESULT Active()
{
- return (m_state == DeviceStreamState_Run)?S_OK:E_FAIL;
+ return (m_state == DeviceStreamState_Run)?S_OK:HRESULT_FROM_WIN32(ERROR_INVALID_STATE);
}
__inline DWORD streamId()
{
@@ -511,7 +511,7 @@ public:
return m_preferredStreamState;
}
- void ReleaseConnectedPins();
+ STDMETHOD_( VOID, ShutdownPin)();
protected:
ComPtr<IMFTransform> m_spSourceTransform; /*Source Transform i.e. DevProxy*/
@@ -520,15 +520,27 @@ protected:
DeviceStreamState m_preferredStreamState;
ComPtr<IMFMediaType> m_spPrefferedMediaType;
HANDLE m_waitInputMediaTypeWaiter; /*Set when the input media type is changed*/
+
+ // Helper functions
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ HRESULT ForwardSecureBuffer(
+ _In_ IMFSample *sample
+ );
+#endif
};
class COutPin: public CBasePin{
public:
- COutPin( _In_ ULONG id = 0,
+ COutPin(
+ _In_ ULONG id = 0,
_In_opt_ CMultipinMft *pparent = NULL,
- _In_ IKsControl* iksControl=NULL);
+ _In_ IKsControl* iksControl=NULL
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ , _In_ MFSampleAllocatorUsage allocatorUsage = MFSampleAllocatorUsage_DoesNotAllocate
+#endif
+ );
~COutPin();
STDMETHODIMP FlushQueues();
STDMETHODIMP AddPin(
@@ -541,7 +553,7 @@ public:
STDMETHODIMP GetOutputStreamInfo(
_Out_ MFT_OUTPUT_STREAM_INFO *pStreamInfo
);
- STDMETHODIMP ChangeMediaTypeFromInpin(
+ virtual STDMETHODIMP ChangeMediaTypeFromInpin(
_In_ IMFMediaType *pInMediatype,
_In_ IMFMediaType* pOutMediaType,
_In_ DeviceStreamState state );
@@ -560,6 +572,16 @@ public:
STDMETHODIMP_(VOID) SetFirstSample(
_In_ BOOL
);
+
+ STDMETHODIMP_(VOID) SetAllocator(
+ _In_ IMFVideoSampleAllocator* pAllocator
+ );
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ MFSampleAllocatorUsage GetSampleAllocatorUsage()
+ {
+ return m_allocatorUsage;
+ }
+#endif
UINT32 GetMediatypeCount()
{
return (UINT32)m_listOfMediaTypes.size();
@@ -568,13 +590,17 @@ public:
protected:
CPinQueue * m_queue; /* Queue where the sample will be stored*/
BOOL m_firstSample;
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ MFSampleAllocatorUsage m_allocatorUsage;
+#endif
+ wil::com_ptr_nothrow<IMFVideoSampleAllocator> m_spDefaultAllocator;
+
};
class CAsyncInPin: public CInPin {
public:
- STDMETHODIMP FlushQueues();
STDMETHODIMP SendSample(
_In_ IMFSample *
);
@@ -587,30 +613,19 @@ public:
_In_ ULONG ulPinId,
_In_ CMultipinMft *pParent) : CInPin(pAttributes,
ulPinId, pParent)
- , m_dwSamplesInFlight(0)
- , m_hHandle(INVALID_HANDLE_VALUE)
- , m_bFlushing(FALSE)
, m_asyncCallback(nullptr)
{
- m_hHandle = CreateEvent(NULL, TRUE, TRUE, L"Async_Pin Event");
- if (m_hHandle == nullptr)
- throw bad_alloc();
Init();
-
}
+ STDMETHOD_(VOID, ShutdownPin)();
~CAsyncInPin()
{
FlushQueues();
- CloseHandle(m_hHandle);
- m_hHandle = INVALID_HANDLE_VALUE;
}
ComPtr<CDMFTAsyncCallback<CAsyncInPin,&CAsyncInPin::Invoke> > m_asyncCallback; // Callback object
- HANDLE m_hHandle; // Handles to keep flush state
- DWORD m_dwSamplesInFlight; // Samples in flight i.e. waiting for the callback functions to be called
- BOOL m_bFlushing;
////////////////////////////////////////////////////////////////////////////////////////
// End of Asynchronous callback definitions
////////////////////////////////////////////////////////////////////////////////////////
@@ -628,7 +643,12 @@ class CTranslateOutPin : public COutPin {
public:
CTranslateOutPin(_In_ ULONG id = 0,
_In_opt_ CMultipinMft *pparent = NULL,
- _In_ IKsControl* iksControl = NULL) : COutPin(id, pparent, iksControl)
+ _In_ IKsControl* iksControl = NULL)
+ : COutPin(id, pparent, iksControl
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ , MFSampleAllocatorUsage_UsesCustomAllocator
+#endif
+ )
{
SetUINT32(MF_SD_VIDEO_SPHERICAL, TRUE);
}
@@ -639,8 +659,14 @@ public:
_In_ IMFMediaType *pMediaType,
_When_(ppIMFMediaTypeFull != nullptr, _Outptr_result_maybenull_)
IMFMediaType **ppIMFMediaTypeFull);
+ STDMETHOD(ChangeMediaTypeFromInpin)(
+ _In_ IMFMediaType *pInMediatype,
+ _In_ IMFMediaType* pOutMediaType,
+ _In_ DeviceStreamState state);
+
protected:
map<IMFMediaType*, IMFMediaType*> m_TranslatedMediaTypes;
};
+
diff --git a/avstream/sampledevicemft/common.h b/avstream/sampledevicemft/common.h
index 72242fa3..bc6bbf28 100644
--- a/avstream/sampledevicemft/common.h
+++ b/avstream/sampledevicemft/common.h
@@ -291,7 +291,7 @@ HRESULT ExceptionBoundary(Lambda&& lambda)
}
catch (...)
{
- return E_FAIL;
+ return E_UNEXPECTED;
}
}
@@ -581,7 +581,7 @@ public:
pcbBuffer);
if (dwHeightInPixels* abs(*plStride) > *pcbBuffer)
{
- hr = E_FAIL;
+ hr = E_UNEXPECTED;
}
} else if (m_sp2DBuffer)
{
@@ -652,6 +652,13 @@ HRESULT IsDXFormatSupported(
_Outptr_opt_ ID3D11Device** ppDevice,
_In_opt_ PUINT32 pSupportedFormat);
+HRESULT ConfigureAllocator(
+ _In_ IMFMediaType* pOutputMediaType,
+ _In_ GUID streamCategory,
+ _In_ IUnknown* pDeviceManagerUnk,
+ _In_ BOOL &isDxAllocator,
+ _In_ IMFVideoSampleAllocator* pAllocator);
+
HRESULT CreateAllocator( _In_ IMFMediaType* pOutputMediaType,
_In_ GUID streamCategory,
_In_ IUnknown* pDeviceManagerUnk,
diff --git a/avstream/sampledevicemft/contosodevice.h b/avstream/sampledevicemft/contosodevice.h
new file mode 100644
index 00000000..66759f69
--- /dev/null
+++ b/avstream/sampledevicemft/contosodevice.h
@@ -0,0 +1,28 @@
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// The Contoso device comes with an SDK
+// that defines various Contoso-specific types,
+// all of which have CONTOSO in their names.
+
+#pragma once
+
+// This payload is used when sending a KSPROPERTY_CONTOSODEVICE_PROCESSBUFFER.
+struct CONTOSODEVICE_PROCESSBUFFER_PAYLOAD
+{
+ GUID identifier;
+ DWORD size;
+};
+
+// Define a custom property set for driver communications.
+// {C5175EE2-583E-43A2-8C26-765287BCEB9D}
+#define STATIC_PROPSETID_CONTOSODEVICE\
+ 0xc5175ee2, 0x583e, 0x43a2, 0x8c, 0x26, 0x76, 0x52, 0x87, 0xbc, 0xeb, 0x9d
+DEFINE_GUIDSTRUCT("C5175EE2-583E-43A2-8C26-765287BCEB9D", PROPSETID_CONTOSODEVICE);
+#define PROPSETID_CONTOSODEVICE DEFINE_GUIDNAMED(PROPSETID_CONTOSODEVICE)
+#define KSPROPERTY_CONTOSODEVICE_PROCESSBUFFER 0 // Send a frame buffer ID to the driver.
+
diff --git a/avstream/sampledevicemft/custompin.cpp b/avstream/sampledevicemft/custompin.cpp
index 00edb329..edb5fadb 100644
--- a/avstream/sampledevicemft/custompin.cpp
+++ b/avstream/sampledevicemft/custompin.cpp
@@ -35,7 +35,7 @@ STDMETHODIMP CCustomPin::SendSample(
// Log sample and exit.. The pipeline will just keep on churning more samples till
// We go into the stop state
//
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Custom Pin %d recieved Sample %p", streamId(), pSample);
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Custom Pin %d received Sample %p", streamId(), pSample);
return S_OK;
}
diff --git a/avstream/sampledevicemft/dllmain.cpp b/avstream/sampledevicemft/dllmain.cpp
index 6978a9d5..88bfe6ab 100644
--- a/avstream/sampledevicemft/dllmain.cpp
+++ b/avstream/sampledevicemft/dllmain.cpp
@@ -196,13 +196,35 @@ STDMETHODIMP_(BOOL) WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, void *)
DisableThreadLibraryCalls(hInstance);
#ifdef MF_WPP
WPP_INIT_TRACING(L"MultiPinMft");
+
+ // Hook up WIL tracing to our trace provider.
+ wil::SetResultLoggingCallback(
+ [](const wil::FailureInfo &failure)
+ {
+ wchar_t debugString[2048];
+ if (SUCCEEDED(wil::GetFailureLogString(debugString, ARRAYSIZE(debugString), failure)))
+ {
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_ERROR, L"%S", debugString);
+ }
+ else
+ {
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_ERROR,
+ L"File: %s, Line: %u, Error: 0x%08X - %S\n",
+ failure.pszFile,
+ failure.uLineNumber,
+ failure.hr,
+ failure.pszMessage);
+ }
+ }
+ );
#endif
}
else
if (dwReason == DLL_PROCESS_DETACH)
{
#ifdef MF_WPP
- WPP_CLEANUP();
+ wil::SetResultLoggingCallback(nullptr);
+ WPP_CLEANUP();
#endif
}
return TRUE;
diff --git a/avstream/sampledevicemft/multipinmft.cpp b/avstream/sampledevicemft/multipinmft.cpp
index 3467870b..30c0463f 100644
--- a/avstream/sampledevicemft/multipinmft.cpp
+++ b/avstream/sampledevicemft/multipinmft.cpp
@@ -136,6 +136,12 @@ STDMETHODIMP CMultipinMft::QueryInterface(
*ppv = static_cast< IMFGetService* >(this);
}
#endif
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ else if (iid == __uuidof(IMFSampleAllocatorControl))
+ {
+ *ppv = static_cast<IMFSampleAllocatorControl*>(this);
+ }
+#endif
else
{
hr = E_NOINTERFACE;
@@ -1322,6 +1328,54 @@ done:
}
#endif
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+//
+// IMFSampleAllocatorControl Inferface function declarations
+//
+
+STDMETHODIMP CMultipinMft::SetDefaultAllocator(
+ _In_ DWORD dwOutputStreamID,
+ _In_ IUnknown *pAllocator
+)
+{
+ CAutoLock Lock(m_critSec);
+
+ // SetAllocator will be called on the streamId that returns MFSampleAllocatorMode_Default
+ wil::com_ptr_nothrow<COutPin> outPin = GetOutPin(dwOutputStreamID);
+ RETURN_HR_IF_NULL(E_INVALIDARG, outPin);
+ RETURN_HR_IF_NULL(E_INVALIDARG, pAllocator);
+
+ wil::com_ptr_nothrow<IMFVideoSampleAllocator> defaultAllocator;
+ RETURN_IF_FAILED(pAllocator->QueryInterface(&defaultAllocator));
+ outPin->SetAllocator(defaultAllocator.get());
+
+ return S_OK;
+}
+
+STDMETHODIMP CMultipinMft::GetAllocatorUsage(
+ _In_ DWORD dwOutputStreamID,
+ _Out_ DWORD* pdwInputStreamID,
+ _Out_ MFSampleAllocatorUsage* peUsage
+)
+{
+ CAutoLock Lock(m_critSec);
+
+ RETURN_HR_IF_NULL(E_INVALIDARG, peUsage);
+
+ wil::com_ptr_nothrow<COutPin> outPin = GetOutPin(dwOutputStreamID);
+ RETURN_HR_IF_NULL(MF_E_INVALIDSTREAMNUMBER, outPin);
+ *peUsage = outPin->GetSampleAllocatorUsage();
+
+ if (*peUsage == MFSampleAllocatorUsage_DoesNotAllocate)
+ {
+ RETURN_HR_IF_NULL(E_INVALIDARG, pdwInputStreamID);
+ RETURN_IF_FAILED(GetConnectedInpin((ULONG)dwOutputStreamID, *(ULONG*)pdwInputStreamID));
+ }
+
+ return S_OK;
+}
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+
//
// HELPER FUNCTIONS
//
@@ -1513,7 +1567,7 @@ HRESULT CMultipinMft::BridgeInputPinOutputPin(
HRESULT hr = S_OK;
ULONG ulIndex = 0;
ULONG ulAddedMediaTypeCount = 0;
- ComPtr<IMFMediaType> pMediaType = nullptr;
+ ComPtr<IMFMediaType> spMediaType;
DMFTCHECKNULL_GOTO( piPin, done, E_INVALIDARG );
DMFTCHECKNULL_GOTO( poPin, done, E_INVALIDARG );
@@ -1523,19 +1577,17 @@ HRESULT CMultipinMft::BridgeInputPinOutputPin(
// sure any pin advertised supports at least one media type. The pipeline doesn't
// like pins with no media types
//
- while ( SUCCEEDED( hr = piPin->GetMediaTypeAt( ulIndex++, &pMediaType )))
+ while ( SUCCEEDED( hr = piPin->GetMediaTypeAt( ulIndex++, spMediaType.ReleaseAndGetAddressOf() )))
{
GUID subType = GUID_NULL;
- DMFTCHECKHR_GOTO( pMediaType->GetGUID(MF_MT_SUBTYPE,&subType), done );
+ DMFTCHECKHR_GOTO( spMediaType->GetGUID(MF_MT_SUBTYPE,&subType), done );
{
- DMFTCHECKHR_GOTO(hr = poPin->AddMediaType(NULL, pMediaType.Get() ), done );
+ DMFTCHECKHR_GOTO(hr = poPin->AddMediaType(NULL, spMediaType.Get() ), done );
if (hr == S_OK)
{
ulAddedMediaTypeCount++;
}
}
-
- pMediaType = nullptr;
}
if (ulAddedMediaTypeCount == 0)
{
@@ -1679,7 +1731,7 @@ STDMETHODIMP CMultipinMft::Shutdown(
CInPin *pInPin = static_cast<CInPin *>(m_InPins[ulIndex]);
// Deref on the connected outpins to break reference loop
- pInPin->ReleaseConnectedPins();
+ (VOID)pInPin->ShutdownPin();
}
#if defined (MF_DEVICEMFT_ALLOW_MFT0_LOAD) && defined (MFT_UNIQUE_METHOD_NAMES)
for (ULONG ulIndex = 0, ulSize = (ULONG)m_OutPins.size(); ulIndex < ulSize; ulIndex++)
diff --git a/avstream/sampledevicemft/multipinmft.h b/avstream/sampledevicemft/multipinmft.h
index 080f4a7a..70367f1d 100644
--- a/avstream/sampledevicemft/multipinmft.h
+++ b/avstream/sampledevicemft/multipinmft.h
@@ -48,6 +48,9 @@ class CMultipinMft :
, public IMFGetService
#endif
, public CDMFTModuleLifeTimeManager
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ , public IMFSampleAllocatorControl
+#endif
{
friend class CPinCreationFactory;
public:
@@ -275,7 +278,22 @@ public:
}
#endif
-
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ //
+ // IMFSampleAllocatorControl Inferface function declarations
+ //
+
+ STDMETHOD(SetDefaultAllocator)(
+ _In_ DWORD dwOutputStreamID,
+ _In_ IUnknown *pAllocator
+ );
+
+ STDMETHOD(GetAllocatorUsage)(
+ _In_ DWORD dwOutputStreamID,
+ _Out_ DWORD* pdwInputStreamID,
+ _Out_ MFSampleAllocatorUsage* peUsage
+ );
+#endif
static STDMETHODIMP CreateInstance(
REFIID iid, void **ppMFT);
diff --git a/avstream/sampledevicemft/multipinmft.vcxproj b/avstream/sampledevicemft/multipinmft.vcxproj
index 0f560e2c..f13ed67d 100644
--- a/avstream/sampledevicemft/multipinmft.vcxproj
+++ b/avstream/sampledevicemft/multipinmft.vcxproj
@@ -154,17 +154,9 @@
<WppScanConfigurationData>common.h</WppScanConfigurationData>
</ClCompile>
</ItemGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <TargetName>multipinmft</TargetName>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <TargetName>multipinmft</TargetName>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <TargetName>multipinmft</TargetName>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <PropertyGroup>
<TargetName>multipinmft</TargetName>
+ <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\wil\include</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
@@ -261,10 +253,17 @@
<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" />
+ <None Include="Source.def" />
</ItemGroup>
<ItemGroup>
- <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
+ <ClInclude Include="basepin.h" />
+ <ClInclude Include="common.h" />
+ <ClInclude Include="contosodevice.h" />
+ <ClInclude Include="custompin.h" />
+ <ClInclude Include="mftpeventgenerator.h" />
+ <ClInclude Include="multipinmft.h" />
+ <ClInclude Include="multipinmfthelpers.h" />
+ <ClInclude Include="stdafx.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project> \ No newline at end of file
diff --git a/avstream/sampledevicemft/multipinmft.vcxproj.Filters b/avstream/sampledevicemft/multipinmft.vcxproj.Filters
index e06f675d..a4692065 100644
--- a/avstream/sampledevicemft/multipinmft.vcxproj.Filters
+++ b/avstream/sampledevicemft/multipinmft.vcxproj.Filters
@@ -43,4 +43,30 @@
<Filter>Source Files</Filter>
</None>
</ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="basepin.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="common.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="contosodevice.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="custompin.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="mftpeventgenerator.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="multipinmft.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="multipinmfthelpers.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="stdafx.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/avstream/sampledevicemft/multipinmfthelpers.cpp b/avstream/sampledevicemft/multipinmfthelpers.cpp
index 904625ad..34cebe8b 100644
--- a/avstream/sampledevicemft/multipinmfthelpers.cpp
+++ b/avstream/sampledevicemft/multipinmfthelpers.cpp
@@ -16,8 +16,7 @@ class CMediaTypePrinter;
//
CPinQueue::CPinQueue( _In_ DWORD dwPinId ,
_In_ IMFDeviceTransform* pParent)
-: m_teer(0),
- m_dwInPinId(dwPinId),
+ :m_dwInPinId(dwPinId),
m_pTransform(pParent),
m_cRef(1)
@@ -30,6 +29,7 @@ CPinQueue::CPinQueue( _In_ DWORD dwPinId ,
}
CPinQueue::~CPinQueue( )
{
+ Ctee::ReleaseTee(m_spTeer);
}
/*++
@@ -59,10 +59,10 @@ STDMETHODIMP_(VOID) CPinQueue::InsertInternal( _In_ IMFSample *pSample )
STDMETHODIMP CPinQueue::Insert( _In_ IMFSample *pSample )
//
-//m_teer is the wraptee.. this could be a null tee which is a passthrough, an xvp tee which inserts an xvp into the queue etc
+//m_spTeer is the wraptee.. this could be a null tee which is a passthrough, an xvp tee which inserts an xvp into the queue etc
//
{
- return m_teer->PassThrough( pSample );
+ return m_spTeer->PassThrough( pSample );
}
/*++
@@ -97,9 +97,9 @@ VOID CPinQueue::Clear( )
// Stop the tees
// Execute Flush
//
- if (m_teer)
+ if (m_spTeer)
{
- m_teer->Stop();
+ m_spTeer->Stop();
}
while ( !Empty() )
@@ -114,62 +114,99 @@ Description:
RecreateTee creates the underlying Tees in the queue. It accepts the input media type
which is the media type set on the input pin and the output mediatype, which (duh) is the
media type on the output pin
- It also takes an IUnknown which is the D3D Manager. if it is valid we might use it if we
+ It also takes an IUnknown which is the D3D Manager. if it is valid we might use it if we
have an xvp in the path i.e. inputMediatype =! outputMediatype
--*/
-STDMETHODIMP CPinQueue::RecreateTee( _In_ IMFMediaType *inMediatype,
+STDMETHODIMP CPinQueue::RecreateTee(_In_ IMFMediaType *inMediatype,
_In_ IMFMediaType *outMediatype,
- _In_opt_ IUnknown* punkManager )
+ _In_opt_ IUnknown* punkManager)
{
HRESULT hr = S_OK;
DMFT_conversion_type operation = DeviceMftTransformTypeIllegal;
-
- SAFE_DELETE(m_teer); // Should release the reference
- CNullTee *nulltee = new (std::nothrow) CNullTee(this);
- DMFTCHECKNULL_GOTO( nulltee, done, E_OUTOFMEMORY);
+ Ctee::ReleaseTee(m_spTeer);
+
+ ComPtr<CNullTee> spNulltee = new (std::nothrow) CNullTee(this);
+ DMFTCHECKNULL_GOTO(spNulltee.Get(), done, E_OUTOFMEMORY);
DMFTCHECKHR_GOTO(CompareMediaTypesForConverter(inMediatype, outMediatype, &operation), done);
if (operation == DeviceMftTransformTypeDecoder)
{
// Decoder needed
- CDecoderTee* pDecTee = new (std::nothrow) CDecoderTee(nulltee,
+ CDecoderTee* pDecTee = new (std::nothrow) CDecoderTee(spNulltee.Get(),
static_cast<CMultipinMft*>(m_pTransform)->GetQueueId(),
pinCategory());
DMFTCHECKNULL_GOTO(pDecTee, done, E_OUTOFMEMORY);
(void)pDecTee->SetD3DManager(punkManager);
- DMFTCHECKHR_GOTO(pDecTee->SetMediaTypes(inMediatype, outMediatype),done);
- m_teer = dynamic_cast<Ctee*>(pDecTee);
+ DMFTCHECKHR_GOTO(pDecTee->SetMediaTypes(inMediatype, outMediatype), done);
+ m_spTeer = pDecTee;
}
- else if (operation == DeviceMftTransformTypeXVP)
+ else if (operation == DeviceMftTransformTypeXVP)
{
- CXvptee* pXvptee = new (std::nothrow) CXvptee(nulltee, pinCategory());
+ CXvptee* pXvptee = new (std::nothrow) CXvptee(spNulltee.Get(), pinCategory());
DMFTCHECKNULL_GOTO(pXvptee, done, E_OUTOFMEMORY);
- (void)pXvptee->SetD3DManager( punkManager );
- DMFTCHECKHR_GOTO(pXvptee->SetMediaTypes( inMediatype, outMediatype ),done);
- m_teer = dynamic_cast< Ctee* >( pXvptee );
+ (void)pXvptee->SetD3DManager(punkManager);
+ DMFTCHECKHR_GOTO(pXvptee->SetMediaTypes(inMediatype, outMediatype), done);
+ m_spTeer = pXvptee;
}
else
{
- m_teer = nulltee; /*A simple passthrough*/
+ m_spTeer = spNulltee.Get(); /*A simple passthrough*/
}
done:
- DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr );
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr);
if (FAILED(hr))
{
- if (m_teer){
- delete(m_teer);
- m_teer = NULL;
+ Ctee::ReleaseTee(m_spTeer);
+ }
+ return hr;
+}
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+STDMETHODIMP CPinQueue::RecreateTeeByAllocatorMode(
+ _In_ IMFMediaType* inMediatype,
+ _In_ IMFMediaType* outMediatype,
+ _In_opt_ IUnknown* punkManager,
+ _In_ MFSampleAllocatorUsage allocatorUsage,
+ _In_opt_ IMFVideoSampleAllocator* pAllocator)
+{
+ HRESULT hr = S_OK;
+
+ Ctee::ReleaseTee(m_spTeer);// Should release the reference
+
+ wistd::unique_ptr<CNullTee> nulltee = wil::make_unique_nothrow<CNullTee>(this);
+ RETURN_IF_NULL_ALLOC(nulltee);
+
+ if (allocatorUsage == MFSampleAllocatorUsage_DoesNotAllocate)
+ {
+ m_spTeer.Attach(nulltee.release()); /*A simple passthrough*/
+ }
+ else
+ {
+ wistd::unique_ptr<CSampleCopytee> sampleCopytee;
+ RETURN_IF_NULL_ALLOC(sampleCopytee);
+ (void)sampleCopytee->SetD3DManager(punkManager);
+
+ if (allocatorUsage == MFSampleAllocatorUsage_UsesProvidedAllocator)
+ {
+ RETURN_HR_IF_NULL(E_INVALIDARG, pAllocator);
+ sampleCopytee = wil::make_unique_nothrow<CSampleCopytee>(nulltee.release(), pinCategory(), pAllocator);
+ }
+ else
+ {
+ sampleCopytee = wil::make_unique_nothrow<CSampleCopytee>(nulltee.release(), pinCategory(), nullptr);
}
+ RETURN_IF_FAILED(sampleCopytee->SetMediaTypes(inMediatype, outMediatype));
+ m_spTeer.Attach(sampleCopytee.release());
}
+
return hr;
}
-
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
#ifdef MF_DEVICEMFT_ADD_GRAYSCALER_
STDMETHODIMP CPinQueueWithGrayScale::RecreateTee( _In_ IMFMediaType *inMediatype,
_In_ IMFMediaType *outMediatype,
@@ -183,7 +220,7 @@ STDMETHODIMP CPinQueueWithGrayScale::RecreateTee( _In_ IMFMediaType *inMediatyp
DMFTCHECKHR_GOTO(CPinQueue::RecreateTee(inMediatype,
outMediatype,
punkManager),done);
- DMFTCHECKNULL_GOTO(m_teer, done, E_UNEXPECTED);
+ DMFTCHECKNULL_GOTO(m_spTeer, done, E_UNEXPECTED);
// Wrap the media type with Gray scale tee only if the input media type is a YUY2, UYVY, NV12 or RGB32
DMFTCHECKHR_GOTO(inMediatype->GetGUID(MF_MT_SUBTYPE, &gInputSubType), done);
if (IsEqualCLSID(gInputSubType, MFVideoFormat_NV12)
@@ -192,9 +229,9 @@ STDMETHODIMP CPinQueueWithGrayScale::RecreateTee( _In_ IMFMediaType *inMediatyp
||IsEqualCLSID(gInputSubType, MFVideoFormat_RGB32))
{
CGrayTee *pTee = NULL;
- pTee = new (std::nothrow) CGrayTee(m_teer);
+ pTee = new (std::nothrow) CGrayTee(m_spTeer);
DMFTCHECKHR_GOTO(pTee->SetMediaTypes(inMediatype, outMediatype), done);
- m_teer = dynamic_cast< Ctee* >(pTee);
+ m_spTeer = dynamic_cast< Ctee* >(pTee);
}
else
{
@@ -251,9 +288,9 @@ STDMETHODIMP CWrapTee::PassThrough( _In_ IMFSample* pInSample )
DMFTCHECKNULL_GOTO(pInSample, done, S_OK); // pass through for no sample
DMFTCHECKHR_GOTO(Do(pInSample, &pOutSample,newSample),done);
- if (m_objectWrapped)
+ if (m_spObjectWrapped)
{
- if (SUCCEEDED(hr = m_objectWrapped->PassThrough( pOutSample )))
+ if (SUCCEEDED(hr = m_spObjectWrapped->PassThrough( pOutSample )))
{
//@@@@README There is a very bad bug in the pipeline that the device transform manager
// is not releasing the reference on the sample when it is passed to the device MFT so any
@@ -289,7 +326,7 @@ HRESULT CVideoProcTee::SetMediaTypes(_In_ IMFMediaType* pInMediaType, _In_ IMFMe
ComPtr<IMFTransform> spTransform;
DMFTCHECKHR_GOTO(CWrapTee::SetMediaTypes(pInMediaType, pOutMediaType),done);
DMFTCHECKHR_GOTO(Configure(pInMediaType, pOutMediaType, spTransform.GetAddressOf()), done);
- m_videoProcessor = spTransform.Detach();
+ m_spVideoProcessor = spTransform.Detach();
//
// Start streaming
//
@@ -298,6 +335,8 @@ done:
return hr;
}
+
+
HRESULT CVideoProcTee::CreateAllocator()
{
HRESULT hr = S_OK;
@@ -307,18 +346,37 @@ HRESULT CVideoProcTee::CreateAllocator()
return S_OK;
}
- if (m_spAllocator.Get())
+ if (m_spPrivateAllocator)
{
// Release what we have currently
- DMFTCHECKHR_GOTO(m_spAllocator->UninitializeSampleAllocator(), done);
- m_spAllocator = nullptr;
+ RETURN_IF_FAILED(m_spPrivateAllocator->UninitializeSampleAllocator());
+ m_spPrivateAllocator = nullptr;
+ }
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ if (m_spDefaultAllocator)
+ {
+ // Configure default allocator
+ m_spDefaultAllocator->UninitializeSampleAllocator();
+ RETURN_IF_FAILED(::ConfigureAllocator(
+ m_pOutputMediaType.Get(),
+ m_streamCategory,
+ m_spDeviceManagerUnk.Get(),
+ m_fSetD3DManager,
+ m_spDefaultAllocator.Get()));
+ }
+ else
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ {
+ // Create and configure private allocator
+ RETURN_IF_FAILED(MFCreateVideoSampleAllocatorEx(IID_PPV_ARGS(m_spPrivateAllocator.ReleaseAndGetAddressOf())));
+ RETURN_IF_FAILED(::ConfigureAllocator(
+ m_pOutputMediaType.Get(),
+ m_streamCategory,
+ m_spDeviceManagerUnk.Get(),
+ m_fSetD3DManager,
+ m_spPrivateAllocator.Get()));
}
- DMFTCHECKHR_GOTO(::CreateAllocator(m_pOutputMediaType.Get(),
- m_streamCategory, m_spDeviceManagerUnk.Get(),
- m_fSetD3DManager,
- m_spAllocator.GetAddressOf()), done);
-done:
return hr;
}
@@ -342,6 +400,7 @@ CXvptee::~CXvptee()
HRESULT CXvptee::StartStreaming()
{
HRESULT hr = S_OK;
+ CAutoLock Lock(m_Lock);
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0), done); // ulParam set to zero
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0), done); // ulParam set to zero
done:
@@ -351,6 +410,8 @@ done:
HRESULT CXvptee::StopStreaming()
{
HRESULT hr = S_OK;
+ CAutoLock Lock(m_Lock);
+ SetAsyncStatus(MF_E_SHUTDOWN);
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0), done); // Flush the stream
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0), done); // Notify end of stream
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, 0), done); // Notify end of streaming
@@ -374,17 +435,17 @@ STDMETHODIMP CXvptee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** ppOutSamp
MFT_OUTPUT_DATA_BUFFER outputSample;
ComPtr <IMFSample> spXVPOutputSample;
DWORD dwStatus = 0;
+ CAutoLock Lock(m_Lock);
DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! XVP ProcessOutput Processing Sample =%p", pSample);
DMFTCHECKNULL_GOTO(ppOutSample, done, E_INVALIDARG);
-
*ppOutSample = nullptr;
-
+ DMFTCHECKHR_GOTO(GetAsyncStatus(), done);
DMFTCHECKHR_GOTO(Transform()->MFTProcessInput(0, pSample, 0),done);
outputSample.dwStreamID = 0;
outputSample.pSample = NULL;
- DMFTCHECKHR_GOTO(m_spAllocator->AllocateSample(&outputSample.pSample), done);
+ DMFTCHECKHR_GOTO(m_spPrivateAllocator->AllocateSample(&outputSample.pSample), done);
hr = Transform()->MFTProcessOutput(0, 1, &outputSample, &dwStatus);
@@ -492,16 +553,18 @@ done:
CDecoderTee::~CDecoderTee()
{
(VOID)StopStreaming();
- if (m_spAllocator)
+ MFUnlockWorkQueue(m_dwCameraStreamWorkQueueId);
+ if (m_spPrivateAllocator)
{
- m_spAllocator->UninitializeSampleAllocator();
- m_spAllocator = nullptr;
+ m_spPrivateAllocator->UninitializeSampleAllocator();
+ m_spPrivateAllocator = nullptr;
}
}
HRESULT CDecoderTee::StartStreaming()
{
HRESULT hr = S_OK;
+ CAutoLock Lock(&m_Lock);
DMFTCHECKNULL_GOTO(Transform(), done, MF_E_UNEXPECTED);
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0), done);
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0), done);
@@ -512,13 +575,11 @@ HRESULT CDecoderTee::StartStreaming()
HRESULT CDecoderTee::StopStreaming()
{
HRESULT hr = S_OK;
- ComPtr<IMFTransform> spTransform = Transform();
+ ComPtr<IMFTransform> spTransform;
{
- CAutoLock Lock(&m_critSec);
- if (m_hSyncHandle)
- {
- ResetEvent(m_hSyncHandle);
- }
+ CAutoLock Lock(&m_Lock);
+ spTransform = Transform();
+ SetAsyncStatus(MF_E_SHUTDOWN);
}
if (spTransform.Get())
{
@@ -531,15 +592,7 @@ HRESULT CDecoderTee::StopStreaming()
{
(void)spShutdown->Shutdown();
}
- m_critSec.Lock();
- SetAsyncStatus(MF_E_SHUTDOWN);
- MFUnlockWorkQueue(m_dwCameraStreamWorkQueueId);
- if (m_ulProcessOutputsInFlight > 0)
- {
- m_critSec.Unlock();
- WaitForSingleObject(m_hSyncHandle, INFINITE);
-
- }
+
spTransform = nullptr;
}
done:
@@ -553,17 +606,12 @@ STDMETHODIMP CDecoderTee::Configure(_In_opt_ IMFMediaType *inType,
HRESULT hr = S_OK;
ComPtr<IMFTransform> spTransform;
GUID gInSubType = GUID_NULL, gOutSubType = GUID_NULL;
+
DMFTCHECKNULL_GOTO(ppTransform, done, E_INVALIDARG);
DMFTCHECKNULL_GOTO(inType, done, E_INVALIDARG);
DMFTCHECKNULL_GOTO(outType, done, E_INVALIDARG);
*ppTransform = nullptr;
- SAFE_CLOSEHANDLE(m_hSyncHandle);
- m_hSyncHandle = CreateEvent(NULL,
- FALSE,
- TRUE,
- TEXT("SyncDecoderWaiter")
- );
if (!(SUCCEEDED(inType->GetGUID(MF_MT_SUBTYPE, &gInSubType))
&& SUCCEEDED(outType->GetGUID(MF_MT_SUBTYPE, &gOutSubType))))
{
@@ -592,11 +640,6 @@ STDMETHODIMP CDecoderTee::Configure(_In_opt_ IMFMediaType *inType,
}
DMFTCHECKNULL_GOTO(spTransform.Get(), done, E_UNEXPECTED);
- if (m_D3daware && SUCCEEDED(IsDXFormatSupported(reinterpret_cast<IMFDXGIDeviceManager*>(m_spDeviceManagerUnk.Get()), gOutSubType, nullptr, nullptr)))
- {
- DMFTCHECKHR_GOTO(spTransform->MFTProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)m_spDeviceManagerUnk.Get()), done);
- }
-
DMFTCHECKHR_GOTO(spTransform->MFTGetOutputStreamInfo(m_dwMFTOutputId, &outputStreamInfo), done);
m_bProducesSamples = (outputStreamInfo.dwFlags & (MFT_OUTPUT_STREAM_PROVIDES_SAMPLES | MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES));
@@ -608,7 +651,7 @@ STDMETHODIMP CDecoderTee::Configure(_In_opt_ IMFMediaType *inType,
}
// Create a callback for processoutputs to be called on
- m_asyncCallback = new (std::nothrow) CDMFTAsyncCallback<CDecoderTee, &CDecoderTee::Invoke>(this);
+ m_asyncCallback = new (std::nothrow) CDMFTAsyncCallback<CDecoderTee, &CDecoderTee::Invoke>(this, m_dwQueueId);
DMFTCHECKNULL_GOTO(m_asyncCallback.Get(), done, E_OUTOFMEMORY);
if (m_fAsyncMFT)
@@ -636,9 +679,10 @@ STDMETHODIMP CDecoderTee::Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **ppout
{
HRESULT hr = S_OK;
ComPtr<IMFSample> spOutputSample;
+ CAutoLock lock(m_Lock);
ComPtr<IMFTransform> spTransform = Transform();
+
newSample = false;
- CAutoLock lock(m_critSec);
DMFTCHECKNULL_GOTO(ppoutSample, done, E_INVALIDARG);
*ppoutSample = nullptr;
DMFTCHECKHR_GOTO(GetAsyncStatus(), done);
@@ -663,7 +707,6 @@ STDMETHODIMP CDecoderTee::Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **ppout
spInputSample.Detach();
hr = S_OK;
// Queue a work item for process output
- m_ulProcessOutputsInFlight++;
DMFTCHECKHR_GOTO(MFPutWorkItem(m_dwCameraStreamWorkQueueId, m_asyncCallback.Get(), nullptr), done);
break;
}
@@ -720,7 +763,7 @@ HRESULT CDecoderTee::Invoke(_In_ IMFAsyncResult* pResult)
ComPtr<IMFTransform> spDecoderTemp;
ComPtr<IMFSample> spOutputSample;
BOOL bSendSample = FALSE;
- CAutoLock lock(m_critSec);
+ CAutoLock lock(m_Lock);
spDecoderTemp = Transform();
@@ -748,12 +791,12 @@ HRESULT CDecoderTee::Invoke(_In_ IMFAsyncResult* pResult)
case METransformHaveOutput:
{
ComPtr<IMFSample> spDecodedSample;
- m_critSec.Unlock();
+ m_Lock.Unlock();
//
// The processoutput call blocks for H264 sometimes. This call back is serialized
//
hr = ProcessOutputSync(spDecodedSample.GetAddressOf());
- m_critSec.Lock();
+ m_Lock.Lock();
// Did we error out when we released the lock?
DMFTCHECKHR_GOTO(GetAsyncStatus(), done);
if (SUCCEEDED(hr))
@@ -780,13 +823,12 @@ HRESULT CDecoderTee::Invoke(_In_ IMFAsyncResult* pResult)
{
// Synchronous mode. We only need it for processoutputs
ComPtr<IMFSample> spDecodedSample;
- m_ulProcessOutputsInFlight--;
DMFTCHECKHR_GOTO(GetAsyncStatus(), done);
DMFTCHECKNULL_GOTO(pResult, done, E_UNEXPECTED);
DMFTCHECKHR_GOTO(pResult->GetStatus(), done);
- m_critSec.Unlock();
+ m_Lock.Unlock();
hr = ProcessOutputSync(spDecodedSample.GetAddressOf());
- m_critSec.Lock();
+ m_Lock.Lock();
if (SUCCEEDED(hr))
{
// send the sample on its way
@@ -805,9 +847,9 @@ done:
if (bSendSample && spOutputSample.Get())
{
- if (m_objectWrapped)
+ if (m_spObjectWrapped)
{
- hr = m_objectWrapped->PassThrough(spOutputSample.Get());
+ hr = m_spObjectWrapped->PassThrough(spOutputSample.Get());
spOutputSample = nullptr;
}
}
@@ -823,11 +865,6 @@ done:
{
SetAsyncStatus(hr);
}
- if (m_StoppedAndWaiting)
- {
- // Stop is waiting on the threads to run
- SetEvent(m_hSyncHandle);
- }
return hr;
}
@@ -836,11 +873,11 @@ done:
// is holding on to the buffers, could be the xvp then this function will error
// out the pipeline. you should see the ALLOCATOR_E_EMPTY error pop up
//
-_Ret_maybenull_ HRESULT CDecoderTee::GetSample( IMFSample** ppSample )
+HRESULT CDecoderTee::GetSample( IMFSample** ppSample )
{
- if (!m_bProducesSamples && m_spAllocator.Get())
+ if (!m_bProducesSamples && m_spPrivateAllocator.Get())
{
- return m_spAllocator->AllocateSample(ppSample);
+ return m_spPrivateAllocator->AllocateSample(ppSample);
}
return S_OK;
}
@@ -890,7 +927,7 @@ HRESULT CDecoderTee::ProcessFormatChange()
// Also note, The platform doesn't support dynamic media type changes from the stream coming from the
// source.
//
- ComPtr<IMFTransform> spXvp;
+ ComPtr<CXvptee> spXvpTee;
DMFTCHECKHR_GOTO(m_pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidPreviousSubType), done);
for (DWORD i = 0; ; i++)
@@ -918,11 +955,11 @@ HRESULT CDecoderTee::ProcessFormatChange()
//
// Create the XVP and insert it into the chain manually. set the output to the mediatype requested by the platform
//
- CXvptee* pXvpTee = new (std::nothrow) CXvptee(m_objectWrapped ,m_streamCategory);
- DMFTCHECKNULL_GOTO(pXvpTee, done, E_OUTOFMEMORY);
- (VOID)pXvpTee->SetD3DManager(m_spDeviceManagerUnk.Get());
- DMFTCHECKHR_GOTO(pXvpTee->SetMediaTypes(spDecoderOutputMediaType.Get(), m_pOutputMediaType.Get()), done);
- m_objectWrapped = pXvpTee;
+ spXvpTee = new (std::nothrow) CXvptee(m_spObjectWrapped.Get() ,m_streamCategory);
+ DMFTCHECKNULL_GOTO(spXvpTee.Get(), done, E_OUTOFMEMORY);
+ (VOID)spXvpTee->SetD3DManager(m_spDeviceManagerUnk.Get());
+ DMFTCHECKHR_GOTO(spXvpTee->SetMediaTypes(spDecoderOutputMediaType.Get(), m_pOutputMediaType.Get()), done);
+ m_spObjectWrapped = spXvpTee;
spDecoderOutputMediaType = nullptr;
@@ -946,6 +983,7 @@ HRESULT CDecoderTee::ConfigDecoder(_In_ IMFTransform* pTransform, _In_ GUID guid
GUID guidMajorType;
GUID guidSubtype;
DWORD dwMediaTypeIndex = 0;
+ ComPtr<IMFDXGIDeviceManager> spDxgiManager;
UNREFERENCED_PARAMETER(guidSubType);
DMFTCHECKNULL_GOTO(pTransform, done, E_INVALIDARG);
@@ -973,12 +1011,22 @@ HRESULT CDecoderTee::ConfigDecoder(_In_ IMFTransform* pTransform, _In_ GUID guid
(void)ConfigRealTimeMFT(pTransform);
(void)pTransform->MFTGetStreamIDs(1, &m_dwMFTInputId, 1, &m_dwMFTOutputId);
- // Try to set input mediatype on MJPG decoder.
+ DMFTCHECKHR_GOTO(m_pOutputMediaType->GetMajorType(&guidMajorType), done);
+ DMFTCHECKHR_GOTO(m_pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubtype), done);
+
+ if (m_spDeviceManagerUnk.Get())
+ {
+ DMFTCHECKHR_GOTO(m_spDeviceManagerUnk.As(&spDxgiManager), done);
+ if (m_D3daware && SUCCEEDED(IsDXFormatSupported(spDxgiManager.Get(), guidSubtype, nullptr, nullptr)))
+ {
+ // Set the DXGI Manager here, before the input type is set
+ DMFTCHECKHR_GOTO(pTransform->MFTProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)m_spDeviceManagerUnk.Get()), done);
+ }
+ }
DMFTCHECKHR_GOTO(pTransform->MFTSetInputType(m_dwMFTInputId, m_pInputMediaType.Get(), 0), done);
// Find a matching output mediatype that has the same major/Subtype as pOutputType
- DMFTCHECKHR_GOTO(m_pOutputMediaType->GetMajorType(&guidMajorType), done);
- DMFTCHECKHR_GOTO(m_pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubtype), done);
+
while (SUCCEEDED(pTransform->MFTGetOutputAvailableType(m_dwMFTOutputId, dwMediaTypeIndex, &spMediaType)))
{
GUID guidMajorType2;
@@ -1061,6 +1109,18 @@ HRESULT CDecoderTee::ProcessOutputSync(_COM_Outptr_opt_ IMFSample** ppSample)
return hr;
}
+VOID CDecoderTee::ShutdownTee()
+{
+ CAutoLock lock(m_Lock);
+ SetAsyncStatus(MF_E_SHUTDOWN);
+ if (m_asyncCallback.Get())
+ {
+ // Break the circular reference between the
+ // internal async callback and the decoder
+ m_asyncCallback->Shutdown();
+ }
+}
+
#ifdef MF_DEVICEMFT_ADD_GRAYSCALER_
CGrayTee::CGrayTee(_In_ Ctee *tee) : CWrapTee(tee),m_transformfn(nullptr)
{
@@ -1174,6 +1234,122 @@ done:
}
#endif
+// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@//
+// @@@@ README: Sample copy related functions below
+//
+// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@//
+
+CSampleCopytee::CSampleCopytee(_In_ Ctee *tee, GUID category
+ , IMFVideoSampleAllocator* sampleAllocator
+) :
+ CVideoProcTee(tee, category
+ , sampleAllocator
+ )
+{
+
+}
+
+CSampleCopytee::~CSampleCopytee()
+{
+ (VOID)StopStreaming();
+ m_spDeviceManagerUnk = nullptr;
+}
+
+HRESULT CSampleCopytee::StartStreaming()
+{
+ CAutoLock lock(m_Lock);
+ RETURN_IF_FAILED(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0));
+ RETURN_IF_FAILED(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0));
+
+ return S_OK;
+}
+
+HRESULT CSampleCopytee::StopStreaming()
+{
+ CAutoLock lock(m_Lock);
+ SetAsyncStatus(MF_E_SHUTDOWN);
+ RETURN_IF_FAILED(Transform()->MFTProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0)); // Flush the stream
+ RETURN_IF_FAILED(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0)); // Notify end of stream
+ RETURN_IF_FAILED(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, 0)); // Notify end of streaming
+
+ return S_OK;
+}
+
+STDMETHODIMP CSampleCopytee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** ppOutSample, _Inout_ bool &newSample)
+{
+
+ HRESULT hr = S_OK;
+ MFT_OUTPUT_DATA_BUFFER outputSample;
+ ComPtr <IMFSample> spXVPOutputSample;
+ DWORD dwStatus = 0;
+ CAutoLock lock(m_Lock);
+
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Processing Sample =%p", pSample);
+ RETURN_HR_IF_NULL(E_INVALIDARG, ppOutSample);
+
+ *ppOutSample = nullptr;
+ RETURN_IF_FAILED(GetAsyncStatus());
+ RETURN_IF_FAILED(Transform()->MFTProcessInput(0, pSample, 0));
+
+ outputSample.dwStreamID = 0;
+ outputSample.pSample = NULL;
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ if (m_spDefaultAllocator)
+ {
+ RETURN_IF_FAILED(m_spDefaultAllocator->AllocateSample(&outputSample.pSample));
+ }
+ else
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ {
+ RETURN_IF_FAILED(m_spPrivateAllocator->AllocateSample(&outputSample.pSample));
+ }
+
+
+ hr = Transform()->MFTProcessOutput(0, 1, &outputSample, &dwStatus);
+
+ if (SUCCEEDED(hr) && pSample)
+ {
+ spXVPOutputSample.Attach(outputSample.pSample);
+ }
+ else
+ {
+ SAFE_RELEASE(outputSample.pSample);
+ }
+
+ if (spXVPOutputSample.Get())
+ {
+ newSample = true;
+ *ppOutSample = spXVPOutputSample.Detach();
+ }
+
+ return hr;
+}
+
+STDMETHODIMP CSampleCopytee::Configure(
+ _In_opt_ IMFMediaType* inMediaType,
+ _In_opt_ IMFMediaType* outMediaType,
+ _Outptr_ IMFTransform **ppTransform
+)
+{
+ RETURN_HR_IF_NULL(E_INVALIDARG, ppTransform);
+
+ CMediaTypePrinter inType(inMediaType);
+ CMediaTypePrinter outType(outMediaType);
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Input MediaType %s", inType.ToString());
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Output MediaType %s", outType.ToString());
+
+ RETURN_IF_FAILED(MFCreateSampleCopierMFT(ppTransform));
+ RETURN_IF_FAILED(CreateAllocator());
+
+ if (m_fSetD3DManager)
+ {
+ RETURN_IF_FAILED((*ppTransform)->MFTProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, reinterpret_cast<UINT_PTR>(m_spDeviceManagerUnk.Get())));
+ }
+
+ return S_OK;
+}
+
+
/*++
Descrtiption:
Handles events sent by the pipeline
@@ -1256,7 +1432,7 @@ HRESULT CDMFTEventHandler::KSEvent(
for (; it != m_RegularEventList.end(); it++)
{
PDMFTEventEntry pEntry = *it;
- DMFTCHECKNULL_GOTO(pEntry, done, E_FAIL);
+ DMFTCHECKNULL_GOTO(pEntry, done, E_UNEXPECTED);
if (pEntry->m_pEventData == pEventData)
{
break;
@@ -1547,7 +1723,11 @@ HRESULT CPinCreationFactory::CreatePin(_In_ ULONG ulInputStreamId, /* The Input
#if defined MF_DEVICEMFT_DECODING_MEDIATYPE_NEEDED
spOutPin = new (std::nothrow) CTranslateOutPin(ulOutStreamId, m_spDeviceTransform.Get(), spKscontrol.Get()); // Create the output pin
#else
- spOutPin = new (std::nothrow) COutPin(ulOutStreamId, m_spDeviceTransform.Get(), spKscontrol.Get()); // Create the output pin
+ spOutPin = new (std::nothrow) COutPin(ulOutStreamId, m_spDeviceTransform.Get(), spKscontrol.Get()
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ , MFSampleAllocatorUsage_DoesNotAllocate
+#endif
+ ); // Create the output pin
#endif
DMFTCHECKNULL_GOTO(spOutPin.Get(), done, E_OUTOFMEMORY);
@@ -1621,14 +1801,10 @@ done:
return hr;
}
-HRESULT CheckImagePin( _In_ IMFAttributes* pAttributes, _Out_ PBOOL pbIsImagePin )
+BOOL CheckImagePin( _In_ IMFAttributes* pAttributes, _Out_ PBOOL pbIsImagePin )
{
- if ((SUCCEEDED(CheckPinType(pAttributes, PINNAME_IMAGE, pbIsImagePin)) && pbIsImagePin) ||
- (SUCCEEDED(CheckPinType(pAttributes, PINNAME_VIDEO_STILL, pbIsImagePin)) && pbIsImagePin))
- {
- return S_OK;
- }
- return E_FAIL;
+ return ((SUCCEEDED(CheckPinType(pAttributes, PINNAME_IMAGE, pbIsImagePin)) && pbIsImagePin) ||
+ (SUCCEEDED(CheckPinType(pAttributes, PINNAME_VIDEO_STILL, pbIsImagePin)) && pbIsImagePin));
}
HRESULT CheckPreviewPin( _In_ IMFAttributes* pAttributes, _Out_ PBOOL pbIsPreviewPin)
diff --git a/avstream/sampledevicemft/multipinmfthelpers.h b/avstream/sampledevicemft/multipinmfthelpers.h
index bd3f0876..681ca071 100644
--- a/avstream/sampledevicemft/multipinmfthelpers.h
+++ b/avstream/sampledevicemft/multipinmfthelpers.h
@@ -32,9 +32,9 @@ template< typename T , HRESULT ( __stdcall T::*Func) ( IMFAsyncResult* ) >
class CDMFTAsyncCallback : public IMFAsyncCallback
{
public:
- CDMFTAsyncCallback( T* parent ) :
- m_cRef(1),
- m_Parent(parent)
+ CDMFTAsyncCallback( T* parent , DWORD dwWorkQueueId = MFASYNC_CALLBACK_QUEUE_STANDARD) :
+ m_Parent(parent),
+ m_dwQueueId(dwWorkQueueId)
{ }
virtual ~CDMFTAsyncCallback() { }
@@ -77,25 +77,40 @@ public:
STDMETHODIMP GetParameters(DWORD* pdwFlags, DWORD* pdwQueue)
{
- // Implementation of this method is optional.
- UNREFERENCED_PARAMETER(pdwFlags);
- UNREFERENCED_PARAMETER(pdwQueue);
+ *pdwFlags = 0;
+ *pdwQueue = m_dwQueueId;
return E_NOTIMPL;
}
STDMETHODIMP Invoke( IMFAsyncResult* pAsyncResult )
{
- return (m_Parent->*Func)(pAsyncResult);
+ ComPtr<T> spParent;
+ {
+ // Take a reference on the parent so that
+ // shutdown may not yank it from us
+ CAutoLock Lock(&m_Lock);
+ spParent = m_Parent;
+ }
+ if (spParent.Get())
+ {
+ return ((spParent.Get())->*Func)(pAsyncResult);
+ }
+ return MF_E_SHUTDOWN;
+ }
+ VOID Shutdown()
+ {
+ CAutoLock Lock(&m_Lock);
+ m_Parent = nullptr; //Break the reference
}
- // TODO: Implement this method.
-
T GetParent()
{
return m_Parent;
}
protected:
- T* m_Parent; // Weak reference to the parent
- long m_cRef;
+ CCritSec m_Lock;
+ ComPtr<T> m_Parent;
+ long m_cRef = 0;
+ DWORD m_dwQueueId = MFASYNC_CALLBACK_QUEUE_STANDARD;
};
@@ -107,7 +122,18 @@ public:
STDMETHODIMP_(VOID) InsertInternal ( _In_ IMFSample *pSample = nullptr );
STDMETHODIMP Insert ( _In_ IMFSample *pSample );
STDMETHODIMP Remove (_Outptr_result_maybenull_ IMFSample **pSample);
- virtual STDMETHODIMP RecreateTee ( _In_ IMFMediaType *inMediatype, _In_ IMFMediaType *outMediatype, _In_opt_ IUnknown* punkManager );
+ virtual STDMETHODIMP RecreateTee (
+ _In_ IMFMediaType *inMediatype,
+ _In_ IMFMediaType *outMediatype,
+ _In_opt_ IUnknown* punkManager);
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ STDMETHODIMP RecreateTeeByAllocatorMode(
+ _In_ IMFMediaType* inMediatype,
+ _In_ IMFMediaType* outMediatype,
+ _In_opt_ IUnknown* punkManager,
+ _In_ MFSampleAllocatorUsage allocatorUsage,
+ _In_opt_ IMFVideoSampleAllocator* pAllcoator);
+#endif
STDMETHODIMP_(VOID) Clear();
//
@@ -179,7 +205,7 @@ private:
GUID m_streamCategory;
ULONG m_cRef;
protected:
- Ctee* m_teer; /*Tee that acts as a passthrough or an XVP */
+ ComPtr<Ctee> m_spTeer; /*Tee that acts as a passthrough or an XVP */
};
@@ -197,8 +223,20 @@ public:
// The below classes are used to add the
// XVP and the Decoder components.
//
-class Ctee{
+class Ctee: public IUnknown{
public:
+ // This is a helper class to release the interface
+ // It will first call shutdowntee to break any circular
+ // references any components might have with their composed
+ // objects
+ static VOID ReleaseTee( _In_ ComPtr<Ctee> &tee)
+ {
+ if (tee)
+ {
+ tee->ShutdownTee();
+ tee = nullptr;
+ }
+ }
STDMETHOD(Start)()
{
return S_OK;
@@ -208,35 +246,85 @@ public:
return S_OK;
}
virtual STDMETHODIMP PassThrough( _In_ IMFSample * ) = 0;
+
+ STDMETHOD_(VOID, ShutdownTee)()
+ {
+ return; // NOOP
+ }
+ STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
+ {
+ HRESULT hr = S_OK;
+ if (ppv != nullptr)
+ {
+ *ppv = nullptr;
+ if (riid == __uuidof(IUnknown))
+ {
+ AddRef();
+ *ppv = static_cast<IUnknown*>(this);
+ }
+ else
+ {
+ hr = E_NOINTERFACE;
+ }
+ }
+ else
+ {
+ hr = E_POINTER;
+ }
+ return hr;
+ }
+ Ctee()
+ {
+ }
+ virtual ~Ctee()
+ {}
+ STDMETHODIMP_(ULONG) AddRef()
+ {
+ return InterlockedIncrement(&m_cRef);
+ }
+ STDMETHODIMP_(ULONG) Release()
+ {
+ long cRef = InterlockedDecrement(&m_cRef);
+ if (cRef == 0)
+ {
+ delete this;
+ }
+ return cRef;
+ }
+
+protected:
+ ULONG m_cRef = 0;
};
class CNullTee:public Ctee{
public:
- CNullTee(_In_ CPinQueue* q) :m_Queue(q) {}
+ CNullTee(_In_ CPinQueue* q)
+ : m_Queue(q)
+ {
+ }
STDMETHODIMP PassThrough( _In_ IMFSample* );
+
protected:
// Store the queue here for simplicity
ComPtr<CPinQueue> m_Queue;
};
-class CWrapTee : public Ctee{
+class CWrapTee : public Ctee
+{
public:
CWrapTee( _In_ Ctee *tee=nullptr )
-: m_objectWrapped(tee)
+ : m_spObjectWrapped(tee)
, m_pInputMediaType(nullptr)
, m_pOutputMediaType(nullptr)
{
}
- virtual ~CWrapTee()=0
+ virtual ~CWrapTee()
{
- if (m_objectWrapped)
- {
- delete(m_objectWrapped);
- }
}
+
STDMETHODIMP PassThrough ( _In_ IMFSample* );
virtual STDMETHODIMP Do ( _In_ IMFSample* pSample, _Out_ IMFSample ** , _Inout_ bool &newSample) = 0;
STDMETHODIMP SetMediaTypes(_In_ IMFMediaType* pInMediaType, _In_ IMFMediaType* pOutMediaType);
@@ -262,7 +350,7 @@ protected:
ComPtr< IMFMediaType > m_pInputMediaType;
ComPtr< IMFMediaType > m_pOutputMediaType;
- Ctee *m_objectWrapped;
+ ComPtr<Ctee> m_spObjectWrapped;
};
//
@@ -272,20 +360,26 @@ class CVideoProcTee: public CWrapTee
{
public:
- CVideoProcTee( _In_ Ctee* p, _In_ GUID category = PINNAME_PREVIEW ) :CWrapTee(p)
+ CVideoProcTee( _In_ Ctee* p, _In_ GUID category = PINNAME_PREVIEW
+ , _In_ IMFVideoSampleAllocator* sampleAllocator=nullptr
+ )
+ :CWrapTee(p)
, m_bProducesSamples(FALSE)
+ , m_asyncHresult(S_OK)
, m_streamCategory(category)
, m_fSetD3DManager(FALSE)
+ , m_spDefaultAllocator(sampleAllocator)
{}
__inline IMFTransform* Transform()
{
- return m_videoProcessor.Get();
+ return m_spVideoProcessor.Get();
}
VOID SetD3DManager( _In_opt_ IUnknown* pUnk )
{
- m_spDeviceManagerUnk = pUnk;
+ m_spDeviceManagerUnk = pUnk;
}
+
STDMETHODIMP SetMediaTypes(_In_ IMFMediaType* pInMediaType, _In_ IMFMediaType* pOutMediaType);
virtual STDMETHODIMP Configure(_In_ IMFMediaType *, _In_ IMFMediaType *, _Inout_ IMFTransform**) = 0;
STDMETHOD(CreateAllocator)();
@@ -294,19 +388,33 @@ public:
HRESULT hr = S_OK;
if (SUCCEEDED(hr = StopStreaming()))
{
- if (m_objectWrapped)
+ if (m_spObjectWrapped)
{
- hr = m_objectWrapped->Stop();
+ hr = m_spObjectWrapped->Stop();
}
}
return hr;
}
+ virtual ~CVideoProcTee()
+ {}
protected:
+ CCritSec m_Lock;
+ __inline VOID SetAsyncStatus(_In_ HRESULT hrStatus)
+ {
+ InterlockedCompareExchange(&m_asyncHresult, hrStatus, S_OK);
+ }
+ HRESULT GetAsyncStatus()
+ {
+ return InterlockedCompareExchange(&m_asyncHresult, S_OK, S_OK);
+ }
STDMETHOD(StartStreaming)() = 0;
STDMETHOD(StopStreaming)() = 0;
- ComPtr< IMFTransform > m_videoProcessor;
+ HRESULT m_asyncHresult;
+ ComPtr< IMFTransform > m_spVideoProcessor;
ComPtr<IUnknown> m_spDeviceManagerUnk;
- ComPtr<IMFVideoSampleAllocatorEx> m_spAllocator;
+ ComPtr<IMFVideoSampleAllocatorEx> m_spPrivateAllocator;
+ ComPtr<IMFVideoSampleAllocator> m_spDefaultAllocator;
+
BOOL m_bProducesSamples;
GUID m_streamCategory;
BOOL m_fSetD3DManager;
@@ -315,11 +423,12 @@ protected:
class CXvptee :public CVideoProcTee{
public:
CXvptee( _In_ Ctee *, _In_ GUID category = PINNAME_PREVIEW );
- ~CXvptee();
+ virtual ~CXvptee();
STDMETHOD(StartStreaming)();
STDMETHOD(StopStreaming)();
STDMETHODIMP Do ( _In_ IMFSample* pSample, _Outptr_ IMFSample **, _Inout_ bool &newSample);
STDMETHODIMP Configure ( _In_opt_ IMFMediaType *, _In_opt_ IMFMediaType *, _Outptr_ IMFTransform** );
+
};
class CDecoderTee : public CVideoProcTee {
@@ -338,23 +447,11 @@ public:
, m_dwMFTInputId(0)
, m_dwMFTOutputId(0)
, m_dwQueueId(dwQueueId)
- ,m_dwCameraStreamWorkQueueId(0)
- , m_ulProcessOutputsInFlight(0)
- , m_hSyncHandle(INVALID_HANDLE_VALUE)
- , m_StoppedAndWaiting(FALSE)
+ , m_dwCameraStreamWorkQueueId(0)
{
m_streamCategory = category;
}
- ~CDecoderTee();
-
- __inline VOID SetAsyncStatus( _In_ HRESULT hrStatus )
- {
- InterlockedCompareExchange(&m_asyncHresult, hrStatus, S_OK);
- }
- HRESULT GetAsyncStatus()
- {
- return InterlockedCompareExchange(&m_asyncHresult, S_OK, S_OK);
- }
+ virtual ~CDecoderTee();
STDMETHODIMP Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **, _Inout_ bool &newSample);
STDMETHODIMP Configure(_In_opt_ IMFMediaType *, _In_opt_ IMFMediaType *, _Outptr_ IMFTransform**);
@@ -362,16 +459,17 @@ public:
protected:
STDMETHODIMP StartStreaming();
STDMETHODIMP StopStreaming();
- _Ret_maybenull_ HRESULT CDecoderTee::GetSample( _Outptr_ IMFSample**);
+ HRESULT GetSample( _Outptr_result_maybenull_ IMFSample**);
HRESULT ConfigDecoder( _In_ IMFTransform* ,_In_ GUID guidSubType = GUID_NULL);
HRESULT ConfigRealTimeMFT(_In_ IMFTransform* );
HRESULT ProcessOutputSync( _COM_Outptr_opt_ IMFSample** );
HRESULT ProcessFormatChange();
+ STDMETHOD_(VOID, ShutdownTee)();
BOOL m_fAsyncMFT;
BOOL m_D3daware;
BOOL m_hwMFT;
- ComPtr<CDMFTAsyncCallback<CDecoderTee,&CDecoderTee::Invoke> > m_asyncCallback;
+ ComPtr<CDMFTAsyncCallback<CDecoderTee, &CDecoderTee::Invoke> > m_asyncCallback;
HRESULT m_asyncHresult;
DWORD m_lNeedInputRequest;
GUID m_streamCategory; // Needed for bind flags
@@ -381,14 +479,22 @@ protected:
ComPtr<IMFSample> m_spUnprocessedSample;
DWORD m_dwQueueId;
DWORD m_dwCameraStreamWorkQueueId;
- CCritSec m_critSec;
std::deque<ComPtr<IMFSample> > m_InputSampleList;
- ULONG m_ulProcessOutputsInFlight;
- HANDLE m_hSyncHandle;
- BOOL m_StoppedAndWaiting;
};
+class CSampleCopytee :public CVideoProcTee {
+public:
+ CSampleCopytee(_In_ Ctee*, _In_ GUID category = PINNAME_PREVIEW
+ , _In_ IMFVideoSampleAllocator* sampleAllocator = nullptr
+ );
+ ~CSampleCopytee();
+ STDMETHOD(StartStreaming)();
+ STDMETHOD(StopStreaming)();
+ STDMETHODIMP Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **, _Inout_ bool &newSample);
+ STDMETHODIMP Configure(_In_opt_ IMFMediaType *, _In_opt_ IMFMediaType *, _Outptr_ IMFTransform**);
+};
+
#ifdef MF_DEVICEMFT_ADD_GRAYSCALER_
class CGrayTee : public CWrapTee {
public:
@@ -499,6 +605,7 @@ public:
DMFT_PIN_INPUT,
DMFT_PIN_OUTPUT,
DMFT_PIN_CUSTOM,
+ DMFT_PIN_ALLOCATOR_PIN,
DMFT_MAX
}type_pin;
HRESULT CreatePin( _In_ ULONG ulInputStreamId, _In_ ULONG ulOutStreamId, _In_ type_pin type,_Outptr_ CBasePin** ppPin, _In_ BOOL& isCustom);
@@ -506,7 +613,7 @@ public:
}
};
HRESULT CheckPinType(_In_ IMFAttributes* pAttributes, _In_ GUID pinType, _Out_ PBOOL pbIsImagePin);
-HRESULT CheckImagePin(_In_ IMFAttributes* pAttributes, _Out_ PBOOL pbIsImagePin);
+BOOL CheckImagePin(_In_ IMFAttributes* pAttributes, _Out_ PBOOL pbIsImagePin);
HRESULT CheckPreviewPin(_In_ IMFAttributes* pAttributes, _Out_ PBOOL pbIsPreviewPin);
diff --git a/avstream/sampledevicemft/multipinmftutils.cpp b/avstream/sampledevicemft/multipinmftutils.cpp
index d056b364..e4a62d52 100644
--- a/avstream/sampledevicemft/multipinmftutils.cpp
+++ b/avstream/sampledevicemft/multipinmftutils.cpp
@@ -1301,6 +1301,83 @@ done:
const UINT32 ALLOCATOR_MIN_SAMPLES = 10;
const UINT32 ALLOCATOR_MAX_SAMPLES = 50;
+
+HRESULT ConfigureAllocator(
+ _In_ IMFMediaType* pOutputMediaType,
+ _In_ GUID streamCategory,
+ _In_ IUnknown* pDeviceManagerUnk,
+ _In_ BOOL &bDxAllocator,
+ _In_ IMFVideoSampleAllocator* pAllocator)
+{
+ HRESULT hr = S_OK;
+ wil::com_ptr_nothrow<IMFVideoSampleAllocatorEx> spPrivateAllocator;
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ wil::com_ptr_nothrow<IMFVideoCaptureSampleAllocator> spDefaultAllocator;
+#endif
+ wil::com_ptr_nothrow<IMFAttributes> spAllocatorAttributes;
+ GUID guidMajorType = GUID_NULL;
+ GUID guidSubtype = GUID_NULL;
+ BOOL fDXAllocator = FALSE;
+
+ RETURN_HR_IF_NULL(E_INVALIDARG, pAllocator );
+ RETURN_HR_IF_NULL(E_INVALIDARG, pOutputMediaType );
+
+ RETURN_IF_FAILED(pOutputMediaType->GetMajorType(&guidMajorType));
+
+ if (!IsEqualGUID(guidMajorType, MFMediaType_Video))
+ {
+ RETURN_HR(MF_E_INVALIDMEDIATYPE);
+ }
+
+ RETURN_IF_FAILED(pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubtype));
+ //
+ // Set Attributes on the allocator we need. First get the Bind Flags.
+ //
+ RETURN_IF_FAILED(MFCreateAttributes(&spAllocatorAttributes, 8));
+ RETURN_IF_FAILED(spAllocatorAttributes->SetUINT32(MF_SA_BUFFERS_PER_SAMPLE, 1));
+
+ if (pDeviceManagerUnk != nullptr)
+ {
+ if (SUCCEEDED(UpdateAllocatorAttributes(spAllocatorAttributes.get(), streamCategory, guidSubtype, (IMFDXGIDeviceManager*)pDeviceManagerUnk)))
+ {
+ fDXAllocator = TRUE;
+ }
+ }
+
+ if (fDXAllocator)
+ {
+ RETURN_IF_FAILED(pAllocator->SetDirectXManager(pDeviceManagerUnk));
+ }
+
+ if (SUCCEEDED(pAllocator->QueryInterface(IID_PPV_ARGS(&spPrivateAllocator))))
+ {
+ RETURN_IF_FAILED(spPrivateAllocator->InitializeSampleAllocatorEx(
+ ALLOCATOR_MIN_SAMPLES,
+ ALLOCATOR_MAX_SAMPLES,
+ spAllocatorAttributes.get(),
+ pOutputMediaType));
+ }
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ else if (SUCCEEDED(pAllocator->QueryInterface(IID_PPV_ARGS(&spDefaultAllocator))))
+ {
+ RETURN_IF_FAILED(spDefaultAllocator->InitializeCaptureSampleAllocator(
+ 0, /*use sample size by MediaType*/
+ 0, /*metadata size*/
+ 0, /*default alignment*/
+ ALLOCATOR_MIN_SAMPLES,
+ spAllocatorAttributes.get(),
+ pOutputMediaType));
+ }
+#endif
+ else
+ {
+ hr = E_INVALIDARG;
+ }
+
+ bDxAllocator = fDXAllocator;
+
+ return hr;
+}
//
//@@@@ README: Creating an Allocator.. Please don't allocate samples individually using MFCreateSample as that can lead to fragmentation and is
// extremely inefficent. Instead create an Allocator which will create a fixed number of samples which are recycled when the pipeline returns back
@@ -1337,7 +1414,7 @@ HRESULT CreateAllocator( _In_ IMFMediaType* pOutputMediaType,
DMFTCHECKHR_GOTO(MFCreateAttributes(&spAllocatorAttributes, 8), done);
DMFTCHECKHR_GOTO(spAllocatorAttributes->SetUINT32(MF_SA_BUFFERS_PER_SAMPLE, 1), done);
- if (pDeviceManagerUnk != nullptr)
+ if (pDeviceManagerUnk != nullptr)
{
if (SUCCEEDED(UpdateAllocatorAttributes(spAllocatorAttributes.Get(), streamCategory,guidSubtype, (IMFDXGIDeviceManager*)pDeviceManagerUnk)))
{
@@ -1349,6 +1426,7 @@ HRESULT CreateAllocator( _In_ IMFMediaType* pOutputMediaType,
{
DMFTCHECKHR_GOTO(spVideoSampleAllocator->SetDirectXManager(pDeviceManagerUnk), done);
}
+
DMFTCHECKHR_GOTO(spVideoSampleAllocator->InitializeSampleAllocatorEx(ALLOCATOR_MIN_SAMPLES, ALLOCATOR_MAX_SAMPLES, spAllocatorAttributes.Get(), pOutputMediaType), done);
*ppAllocator = spVideoSampleAllocator.Detach();
@@ -1487,16 +1565,16 @@ done:
HRESULT MergeSampleAttributes( _In_ IMFSample* pInSample, _Inout_ IMFSample* pOutSample)
{
HRESULT hr = S_OK;
- DMFTCHECKNULL_GOTO(pInSample, done, E_INVALIDARG);
- DMFTCHECKNULL_GOTO(pOutSample, done, E_INVALIDARG);
UINT32 cAttributes = 0;
GUID guidAttribute;
PROPVARIANT varAttribute;
PROPVARIANT varAttributeExists;
-
PropVariantInit(&varAttribute);
PropVariantInit(&varAttributeExists);
+ DMFTCHECKNULL_GOTO(pInSample, done, E_INVALIDARG);
+ DMFTCHECKNULL_GOTO(pOutSample, done, E_INVALIDARG);
+
DMFTCHECKHR_GOTO(pInSample->GetCount(&cAttributes), done);
for (UINT32 i = 0; i < cAttributes; i++)
{
diff --git a/avstream/sampledevicemft/packages.config b/avstream/sampledevicemft/packages.config
new file mode 100644
index 00000000..26065b14
--- /dev/null
+++ b/avstream/sampledevicemft/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Microsoft.Windows.ImplementationLibrary" version="1.0.210204.1" targetFramework="native" />
+</packages> \ No newline at end of file
diff --git a/avstream/sampledevicemft/stdafx.h b/avstream/sampledevicemft/stdafx.h
index a3cd5354..657208cd 100644
--- a/avstream/sampledevicemft/stdafx.h
+++ b/avstream/sampledevicemft/stdafx.h
@@ -34,12 +34,18 @@
#include <d3d11_4.h>
#include <vector>
#include <map>
+#include <stdexcept>
using namespace std;
#include <Windows.Foundation.h>
#include <wrl\client.h>
using namespace ABI::Windows::Foundation;
using namespace Microsoft::WRL;
+#include <wil\result.h>
+#include <wil\resource.h>
+#include <wil\com.h>
+#include <wil\result_macros.h>
+
// @@@@ README Please check / uncheck various hash defines to enable/ disable features
// MF_DEVICEMFT_ASYNCPIN_NEEDED will show how to use Asynchronous queues
// MF_DEVICEMFT_DECODING_MEDIATYPE_NEEDED will show how to decode a compressed mediatype.. it supports H264 and MJPG
@@ -48,7 +54,7 @@ using namespace Microsoft::WRL;
//
//#define MF_DEVICEMFT_ADD_GRAYSCALER_ 1
#define MF_DEVICEMFT_ASYNCPIN_NEEDED 1
-#define MF_DEVICEMFT_DECODING_MEDIATYPE_NEEDED 1
+//#define MF_DEVICEMFT_DECODING_MEDIATYPE_NEEDED 0
#define MF_DEVICEMFT_SET_SPHERICAL_ATTRIBUTES 1
//#define MF_DEVICEMFT_ENUM_HW_DECODERS 1
diff --git a/avstream/samplemft0/README.md b/avstream/samplemft0/README.md
index 6563e1d0..4ed8adbf 100644
--- a/avstream/samplemft0/README.md
+++ b/avstream/samplemft0/README.md
@@ -5,40 +5,35 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Driver MFT Sample
- platform: WDM
- language: cpp
- category: Camera
- description: A driver MFT for use with a camera's UWP device app.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617126
---->
-
# Driver MFT Sample
Provides a *driver MFT* for use with a camera's UWP device app.A *driver MFT* is a Media Foundation Transform that's used with a specific camera when capturing video. The driver MFT is also known as MFT0 because it is the first MFT applied to the video stream captured from the camera. This MFT can provide a video effect or other processing when capturing photos or video from the camera. It can be distributed along with the driver package for a camera.
-In this sample, the driver MFT, when enabled, replaces a portion of the captured video with a green box. To test this sample, download the [UWP device app for camera sample](http://go.microsoft.com/fwlink/p/?linkid=249442) and the [Camera Capture UI sample](http://go.microsoft.com/fwlink/p/?linkid=249441). The [UWP device app for camera sample](http://go.microsoft.com/fwlink/p/?linkid=249442) provides a *UWP device app* that controls the effect implemented by the driver MFT. The [Camera Capture UI sample](http://go.microsoft.com/fwlink/p/?linkid=249441) provides a way to invoke the *UWP device app*.
+In this sample, the driver MFT, when enabled, replaces a portion of the captured video with a green box. To test this sample, download the [UWP device app for camera sample](https://go.microsoft.com/fwlink/p/?linkid=249442) and the [Camera Capture UI sample](https://go.microsoft.com/fwlink/p/?linkid=249441).
+
+The **UWP device app for camera sample** provides a *UWP device app* that controls the effect implemented by the driver MFT.
+
+The **Camera Capture UI sample** provides a way to invoke the **UWP device app**.
This sample is designed to be used with a specific camera. To run the sample, you need the your camera's device ID and device metadata package.
-Related topics
---------------
+## Related topics
-**Concepts**
+### Concepts
-[UWP device apps for cameras](http://go.microsoft.com/fwlink/p/?LinkId=306683)
+[UWP device apps for cameras](https://docs.microsoft.com/windows-hardware/drivers/devapps/uwp-device-apps-for-webcams)
-[Media Foundation Transforms](http://msdn.microsoft.com/en-us/library/windows/hardware/ms703138)
+[Media Foundation Transforms](https://docs.microsoft.com/windows/win32/medfound/media-foundation-transforms)
-[Roadmap for Developing Streaming Media Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff568130)
+[Streaming media device driver design guide](https://docs.microsoft.com/windows-hardware/drivers/stream)
-[Universal camera driver design guide for Windows 10](https://msdn.microsoft.com/en-us/Library/Windows/Hardware/dn937080)
+[Universal camera driver design guide for Windows 10](https://docs.microsoft.com/windows-hardware/drivers/stream/windows-10-technical-preview-camera-drivers-design-guide)
-**Samples**
+### Samples
-[Device app for camera sample](http://go.microsoft.com/fwlink/p/?linkid=249442)
+[Device app for camera sample](https://go.microsoft.com/fwlink/p/?linkid=249442)
-[Camera Capture UI sample](http://go.microsoft.com/fwlink/p/?linkid=249441%20)
+[Camera Capture UI sample](https://go.microsoft.com/fwlink/p/?linkid=249441%20)
diff --git a/biometrics/README.md b/biometrics/README.md
index 503af294..abf0235e 100644
--- a/biometrics/README.md
+++ b/biometrics/README.md
@@ -5,54 +5,41 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Windows Biometric Driver Samples (UMDF Version 1)
- platform: UMDF1
- language: cpp
- category: Security Biometrics
- description: Contains the Windows Biometric Driver Interface sample and the Windows Biometric Service Adapter samples.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620189
---->
-
# Windows Biometric Driver Samples (UMDF Version 1)
The Windows Biometric Driver Samples contain the Windows Biometric Driver Interface sample and the Windows Biometric Service Adapter samples.
-The following table describes the samples contained in this sample set:
+## Windows Biometric Driver Interface
-*Windows Biometric Driver Interface*
This sample implements the Windows Biometric Driver Interface (WBDI). It contains skeleton code for handling the mandatory IOCTLs necessary to interoperate with the Windows Biometric Framework. A WBDI driver can be deployed in conjunction with an engine adapter DLL to allow a sensor to be exposed from the Windows Biometric Framework. This sample has been written to make use of the UMDF framework, which allows for ease of development and system stability.
-*Windows Biometric Service Adapters*
+## Windows Biometric Service Adapters
+
These samples provide skeleton code that developers can use as a basis for writing Sensor, Engine, and Storage Adapters for the Windows Biometric Service. Note that the stubs in these samples are non-functional, and Adapter writers will need to follow the programming guidelines in the WinBio Service documentation in order produce a working Adapter component.
-Build the sample
-----------------
+## Build the sample
-For information on how to build a driver solution using Microsoft Visual Studio, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644).
+For information on how to build a driver solution using Microsoft Visual Studio, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver).
-**Note** You can obtain the co-installers by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](http://go.microsoft.com/fwlink/p/?LinkID=226396).
+> [!NOTE]
+> You can obtain the co-installers by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](https://go.microsoft.com/fwlink/p/?LinkID=253170).
-Run the sample
---------------
+## Installation
-Installation
-------------
-
-### Windows Biometric Driver Interface
+### Windows Biometric Driver Interface installation
The sample requires the use of a suitable fingerprint sensor. It does not capture real data, but it does create a biometric unit in the Windows Biometric Framework.
-### Windows Biometric Service Adapters
+### Windows Biometric Service Adapters installation
To write and test an Adapter plug-in, it will be necessary to have a biometric device and a working WBDI driver for the device.
Adapters are generally installed along with the WBDI driver for the corresponding device. Consult the WinBio Service documentation for information on the INF file commands used for installing Adapters. Note that Adapters are trusted plug-in components, so they can only be installed using a privileged account.
-Design and Operation
---------------------
+## Design and operation
### Windows Biometric Driver Interface
diff --git a/bluetooth/bthecho/README.md b/bluetooth/bthecho/README.md
index 6558f750..6f7c92c8 100644
--- a/bluetooth/bthecho/README.md
+++ b/bluetooth/bthecho/README.md
@@ -1,17 +1,18 @@
-<!---
- name: Bluetooth Echo L2CAP Profile Driver
- platform: WDM
- language: cpp
- category: Bluetooth
- description: Demonstrates development of Bluetooth L2CAP profile drivers using the Bluetooth L2CAP DDIs.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617640
---->
+---
+page_type: sample
+description: "Demonstrates development of Bluetooth L2CAP profile drivers using the Bluetooth L2CAP DDIs."
+languages:
+- cpp
+products:
+- windows
+- windows-wdk
+---
# Bluetooth Echo L2CAP Profile Driver
-This sample demonstrates developing [Bluetooth L2CAP profile drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff536598) using [Bluetooth L2CAP DDIs](http://msdn.microsoft.com/en-us/library/windows/hardware/ff536585).The sample includes two drivers. One for a device that acts as an L2CAP server and another for a device that acts as an L2CAP client. The server simply echoes back any data that it receives from client on the same L2CA channel. These drivers can be used with devices that can be installed with bth.inf. Such devices get installed as 'Generic Bluetooth Radio'. Examples of such devices are Bluetooth USB dongles such as (but not limited to):
+This sample demonstrates developing [Bluetooth L2CAP profile drivers](https://docs.microsoft.com/windows-hardware/drivers/bluetooth) using [Bluetooth L2CAP DDIs](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/_bltooth).The sample includes two drivers. One for a device that acts as an L2CAP server and another for a device that acts as an L2CAP client. The server simply echoes back any data that it receives from client on the same L2CA channel. These drivers can be used with devices that can be installed with bth.inf. Such devices get installed as 'Generic Bluetooth Radio'. Examples of such devices are Bluetooth USB dongles such as (but not limited to):
-```
+```inf
Generic Bluetooth Radio=\
BthUsb, USB\Vid_0a12&Pid_0001
CSR Nanosira=\
@@ -26,58 +27,58 @@ CSR Nanosira-Multimedia WHQL Reference Radio=\
Please refer to bth.inf for the complete list of devices. The installation steps below describe how to install echo server and client with such a device. Please note that RFCOMM based profiles must be developed and accessed using user-mode socket APIs.
-Build the sample
-----------------
+## Build the sample
You can build the sample in two ways: using the Visual Studio Integrated Development Environment (IDE) or from the command line using the Visual Studio Command Prompt window and the Microsoft Build Engine (MSBuild.exe).
-**Building the sample using Visual Studio**
+### Building the sample using Visual Studio
-1. Open Visual Studio. From the **File** menu, select **Open Project/Solution** and open the bthecho.sln project file.
-2. Right-click the solution in the **Solution Explorer** and select **Configuration Manager**.
-3. From the **Configuration Manager**, select the **Active Solution Configuration** and the **Active Solution Platform** (for example, Win32) that correspond to the type of build you are interested in.
-4. From the **Build** menu, click **Build Solution** (Ctrl+Shift+B).
+1. Open Visual Studio. From the **File** menu, select **Open Project/Solution** and open the bthecho.sln project file.
-**Building the sample using the command line (MSBuild)**
+1. Right-click the solution in the **Solution Explorer** and select **Configuration Manager**.
-1. Open a Visual Studio Command Prompt window. Click **Start** and search for **Developer Command Prompt**. If your project is under %PROGRAMFILES%, you need to open the command prompt window using elevated permissions (**Run as administrator**). From this window you can use MsBuild.exe to build any Visual Studio project by specifying the project (.VcxProj) or solutions (.Sln) file.
-2. Navigate to each of the respective project directories and enter the appropriate **MSbuild** command for your target. For example, to perform a clean build of a Visual Studio driver project called BthEcho.vcxproj, navigate to the samples\\bluetooth\\bthecho\\bthcli\\sys project directory and enter the following MSBuild command: **msbuild /t:clean /t:build .\\BthEchoSampleCli.vcxproj**.
-3. If the build succeeds, you will find the driver (BthEchoSampleCli.sys) in the binary output directory corresponding to the target platform.
+1. From the **Configuration Manager**, select the **Active Solution Configuration** and the **Active Solution Platform** (for example, Win32) that correspond to the type of build you are interested in.
-Run the sample
---------------
+1. From the **Build** menu, click **Build Solution** (Ctrl+Shift+B).
-**INSTALLATION**
+### Building the sample using the command line (MSBuild)
-**Note**: Bluetooth echo server device and echo client device must be installed on two different machines, as described below.
+1. Open a Visual Studio Command Prompt window. Click **Start** and search for **Developer Command Prompt**. If your project is under %PROGRAMFILES%, you need to open the command prompt window using elevated permissions (**Run as administrator**). From this window you can use MsBuild.exe to build any Visual Studio project by specifying the project (.VcxProj) or solutions (.Sln) file.
-**Server Installation**
+1. Navigate to each of the respective project directories and enter the appropriate **MSbuild** command for your target. For example, to perform a clean build of a Visual Studio driver project called BthEcho.vcxproj, navigate to the samples\\bluetooth\\bthecho\\bthcli\\sys project directory and enter the following MSBuild command: **msbuild /t:clean /t:build .\\BthEchoSampleCli.vcxproj**.
+
+1. If the build succeeds, you will find the driver (BthEchoSampleCli.sys) in the binary output directory corresponding to the target platform.
+
+## Run the sample
+
+### Installation
+
+> [!NOTE]
+> Bluetooth echo server device and echo client device must be installed on two different machines, as described below.
+
+#### Server Installation
1. Copy KMDF coinstaller (wdfcoinstallerMMmmm.dll, from redist\\wdf\\ ), BthEchoSampleSrv.Sys, BthEchoSampleSrv.inf and bthsrvinst.exe on a temporary directory on the target machine.
-2. Run bthsrvinst.exe /i to install the echo server device. This enables the Bluetooth Enumerator (BthEnum.sys) to enumerate echo server device and create a PDO for the device (please refer to the device tree below).
+1. Run bthsrvinst.exe /i to install the echo server device. This enables the Bluetooth Enumerator (BthEnum.sys) to enumerate echo server device and create a PDO for the device (please refer to the device tree below).
-3. Step \#2 causes BthEnum.sys to create a PDO. Consequently hardware installation wizard gets launched. Either go through the UI and point it to the temporary directory where you copied the binaries in step \#1, or using devcon.exe from the tools\\devcon folder, run the following command from the temporary directory:
+1. Step \#2 causes BthEnum.sys to create a PDO. Consequently hardware installation wizard gets launched. Either go through the UI and point it to the temporary directory where you copied the binaries in step \#1, or using devcon.exe from the tools\\devcon folder, run the following command from the temporary directory:
- ```
- devcon.exe update BthEchoSampleSrv.inf BTHENUM\{c07508f2-b970-43ca-b5dd-cc4f2391bef4}
- ```
+ `devcon.exe update BthEchoSampleSrv.inf BTHENUM\{c07508f2-b970-43ca-b5dd-cc4f2391bef4}`
If devcon.exe fails check the error level using:
- ```
- echo %errorlevel%
- ```
+ `echo %errorlevel%`
If errorlevel is 1, you need to reboot the machine for KMDF update to take effect. If errorlevel is 2, please make sure that you have the driver files described in \#1 available in the current directory. For more information on installation failure please check setup logs.
-4. Upon successful installation you will see 'Bluetooth Echo Sample Server' in Device Manager under Bluetooth devices.
+1. Upon successful installation you will see 'Bluetooth Echo Sample Server' in Device Manager under Bluetooth devices.
-**Device tree for Echo Server device**
+##### Device tree for Echo Server device
(Drivers for FDOs are shown for each devnode in the tree.)
-```
+```txt
--------------------
|BthEchoSampleSrv.sys|<----Function driver for PDO ejected by BthEnum.sys
--------------------
@@ -105,25 +106,24 @@ Run the sample
----------------------
```
-**Client Installation**
+#### Client Installation
-1. **Important**: This must be done on a separate machine from the one where echo server device was installed.
+> [!IMPORTANT]
+> This must be done on a separate machine from the one where echo server device was installed.
-2. Copy KMDF coinstaller (wdfcoinstallerMMmmm.dll, from redist\\wdf\\), BthEchoSampleCli.Sys, BthEchoSampleCli.inf and bthecho.exe on a temporary directory on the target machine.
+1. Copy KMDF coinstaller (wdfcoinstallerMMmmm.dll, from redist\\wdf\\), BthEchoSampleCli.Sys, BthEchoSampleCli.inf and bthecho.exe on a temporary directory on the target machine.
-3. Run bthprops.cpl from a command line or right click on the Bluetooth icon in the system tray and select 'Show Devices' to bring up a list of installed Bluetooth devices.
+1. Run bthprops.cpl from a command line or right click on the Bluetooth icon in the system tray and select 'Show Devices' to bring up a list of installed Bluetooth devices.
-4. In the **Bluetooth Devices** window, click the **Add a device** button.
+1. In the **Bluetooth Devices** window, click the **Add a device** button.
-5. In the Add a Device wizard select the server machine (the machine where you installed the echo server) as a Bluetooth device. If the server machine does not appear, please check the echo server installation and make sure that you have enabled 'Allow Bluetooth device to find this computer' on the server machine as explained above. When the server machine is correctly displayed, select it and pick 'Next'.
+1. In the Add a Device wizard select the server machine (the machine where you installed the echo server) as a Bluetooth device. If the server machine does not appear, please check the echo server installation and make sure that you have enabled 'Allow Bluetooth device to find this computer' on the server machine as explained above. When the server machine is correctly displayed, select it and pick 'Next'.
-6. The wizard should default to a numeric compare ceremony for pairing the machines. When this happens, ensure the numbers match on both the client and the server, select 'Yes' on both machines to indicate they match, and click 'Next' on both machines to complete the pairing.
+1. The wizard should default to a numeric compare ceremony for pairing the machines. When this happens, ensure the numbers match on both the client and the server, select 'Yes' on both machines to indicate they match, and click 'Next' on both machines to complete the pairing.
-7. Go through Device Manager and update driver software for it. Either point the wizard to the temporary directory created in step \#2, or use devcon.exe from the tools\\devcon folder to install the client device:
+1. Go through Device Manager and update driver software for it. Either point the wizard to the temporary directory created in step \#2, or use devcon.exe from the tools\\devcon folder to install the client device:
- ```
- Devcon.exe update BthEchoSampleCli.inf BTHENUM\{c07508f2-b970-43ca-b5dd-cc4f2391bef4}
- ```
+ `devcon.exe update BthEchoSampleCli.inf BTHENUM\{c07508f2-b970-43ca-b5dd-cc4f2391bef4}`
Check for any error from devcon.exe as described in server installation.
@@ -131,22 +131,21 @@ Run the sample
The device tree for echo client device is similar to the one shown for the echo server device, since both client and server are enumerated by BthEnum.sys (although the installation mechanism and properties of client and server are different).
-**Uninstalling Server**
+#### Uninstalling Server
1. Uninstall the device and delete driver software using the Bluetooth Devices window by running bthprops.cpl, right clicking on the device, and selecting 'Remove Device'
-2. Run bthsrvinst.exe /u to uninstall the echo server. This would make bthenum.sys stop enumerating the echo server. Without this step 'Found New Hardware' wizard will be launched again when you reconnect the device.
+1. Run bthsrvinst.exe /u to uninstall the echo server. This would make bthenum.sys stop enumerating the echo server. Without this step 'Found New Hardware' wizard will be launched again when you reconnect the device.
-**Uninstalling Client**
+#### Uninstalling Client
+Uninstall the device and delete driver software using the Bluetooth Devices window by running bthprops.cpl, right clicking on the device, and selecting 'Remove Device'.
-- Uninstall the device and delete driver software using the Bluetooth Devices window by running bthprops.cpl, right clicking on the device, and selecting 'Remove Device'.
-
-**TESTING**
+### Testing
Run BthEcho.exe on the client machine. You should see client sending data to the server and receiving the same data echoed back. Press Ctrl+c to terminate the application. You will see output similar to below:
-```
+```cmd
D:\bth\wdfcli>BthEcho.exe
DevicePath: \\?\bthenum#{c07508f2-b970-43ca-b5dd-cc4f2391bef4}_localmfg&000a#7&3
62d0a3&0&000c55ff727a_c00000001#{fc71b33d-d528-4763-a86c-78777c7bcd7b}
@@ -165,13 +164,13 @@ Written 26 bytes: WDF Bluetooth Sample Echo
You can launch multiple instances of BthEcho.exe. Each client application would cause echo client device to have an independent connection to the echo server and thereby have an independent echo session. You can also have echo client devices and apps installed on multiple machines and talking to a single echo server.
-**CODE TOUR**
+## CODE TOUR
-**Common code**
+### Common code
**Connection object**: The common code contains implementation of a connection object (in connection.\*) that is utilized by both client and the server. Client uses this object to maintain the information about opened connection and the server uses this object to maintain information about the accepted connection. Connection object also supports continuous reader which is utilized by server to read the data sent by client. Connection object is implemented as a WDF user object. Connection details are maintained in BTHECHO\_CONNECTION structure. This structure is used as the context for WDF user object. Passive dispose is used to make the connection object cleanup wait for disconnect completion and continuous reader rundown. Please see WDF documentation for WDF user object and passive dispose (see WdfObjectCreate).
-**Server**
+### Server
**Startup**: Server registers PSM and L2CA server and published SDP record on startup in BthEchoSrvEvtDeviceSelfManagedIoInit (this callback is invoked by WDF during device start). While registering the L2CA server it passes BthEchoSrvIndicationCallback as the callback for incoming connection notifications.
@@ -183,7 +182,7 @@ You can launch multiple instances of BthEcho.exe. Each client application would
**Connection state machine**:
-```
+```txt
ConnectFailed
^
|
@@ -204,11 +203,12 @@ Uninitialized ----> Connecting -------> Connected
One transition to note here is that if disconnect is received in the connecting state (i.e. when the connection is not completed) we wait for connection to completed (transition to connected state) and then invoke disconnect.
-**Important**: Such state machine is needed only if Disconnect is initiated by something other than Bluetooth stack (for example device removal in our case). Bluetooth stack itself would not send disconnect before connect completion. If you adapt this sample for your device please evaluate whether your driver would require such state machine. For example, the echo client device does not need such state machine (although we use common connection code for client and the server).
+> [!IMPORTANT]
+> Such state machine is needed only if Disconnect is initiated by something other than Bluetooth stack (for example device removal in our case). Bluetooth stack itself would not send disconnect before connect completion. If you adapt this sample for your device please evaluate whether your driver would require such state machine. For example, the echo client device does not need such state machine (although we use common connection code for client and the server).
**Shutdown**: Server removes the SDP record and unregisters L2CAP server and PSM in BthEchoSrvEvtDeviceSelfManagedIoCleanup (this callback is invoked by WDF during device removal). It also disconnects any open connections (see Connection rundown above).
-**Client**
+### Client
**Startup**: Client retrieves local and server Bluetooth address in BthEchoSrvEvtDeviceSelfManagedIoInit (this callback is invoked by WDF during device start). Please note that server Bluetooth address would be available regardless of presence of the server. Thus echo client device start doesn't fail even if echo server is not available.
@@ -217,5 +217,3 @@ One transition to note here is that if disconnect is received in the connecting
**Sending and receiving data from server**: When application writes data to the client, client sends this data to server on the connection opened for the given handle. Server would echo back this data. This data is retrieved by the application using a read operation. Echo Sample Client doesn't do any draining of echoed data on its own. Application read/write are handled using a parallel WDF I/O queue.
**Shutdown**: Client doesn't need any specific shutdown code as connection open/close and read/write are done within the context of application's handle open.
-
-
diff --git a/bluetooth/bthecho/bthsrv/README.md b/bluetooth/bthecho/bthsrv/README.md
deleted file mode 100644
index a2afff2d..00000000
--- a/bluetooth/bthecho/bthsrv/README.md
+++ /dev/null
@@ -1,228 +0,0 @@
----
-page_type: sample
-description: "Demonstrates development of Bluetooth L2CAP profile drivers using the Bluetooth L2CAP DDIs."
-languages:
-- cpp
-products:
-- windows
----
-
-<!---
- name: Bluetooth Echo L2CAP Profile Driver
- platform: WDM
- language: cpp
- category: Bluetooth
- description: Demonstrates development of Bluetooth L2CAP profile drivers using the Bluetooth L2CAP DDIs.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617640
---->
-
-# Bluetooth Echo L2CAP Profile Driver
-
-This sample demonstrates developing [Bluetooth L2CAP profile drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff536598) using [Bluetooth L2CAP DDIs](http://msdn.microsoft.com/en-us/library/windows/hardware/ff536585).The sample includes two drivers. One for a device that acts as an L2CAP server and another for a device that acts as an L2CAP client. The server simply echoes back any data that it receives from client on the same L2CA channel. These drivers can be used with devices that can be installed with bth.inf. Such devices get installed as 'Generic Bluetooth Radio'. Examples of such devices are Bluetooth USB dongles such as (but not limited to):
-
-```
-Generic Bluetooth Radio=\
- BthUsb, USB\Vid_0a12&Pid_0001
-CSR Nanosira=\
- BthUsb, USB\Vid_0a12&Pid_0003
-CSR Nanosira WHQL Reference Radio=\
- BthUsb, USB\Vid_0a12&Pid_0004
-CSR Nanosira-Multimedia=\
- BthUsb, USB\Vid_0a12&Pid_0005
-CSR Nanosira-Multimedia WHQL Reference Radio=\
- BthUsb, USB\Vid_0a12&Pid_0006
-```
-
-Please refer to bth.inf for the complete list of devices. The installation steps below describe how to install echo server and client with such a device. Please note that RFCOMM based profiles must be developed and accessed using user-mode socket APIs.
-
-Build the sample
-----------------
-
-You can build the sample in two ways: using the Visual Studio Integrated Development Environment (IDE) or from the command line using the Visual Studio Command Prompt window and the Microsoft Build Engine (MSBuild.exe).
-
-**Building the sample using Visual Studio**
-
-1. Open Visual Studio. From the **File** menu, select **Open Project/Solution** and open the bthecho.sln project file.
-2. Right-click the solution in the **Solution Explorer** and select **Configuration Manager**.
-3. From the **Configuration Manager**, select the **Active Solution Configuration** and the **Active Solution Platform** (for example, Win32) that correspond to the type of build you are interested in.
-4. From the **Build** menu, click **Build Solution** (Ctrl+Shift+B).
-
-**Building the sample using the command line (MSBuild)**
-
-1. Open a Visual Studio Command Prompt window. Click **Start** and search for **Developer Command Prompt**. If your project is under %PROGRAMFILES%, you need to open the command prompt window using elevated permissions (**Run as administrator**). From this window you can use MsBuild.exe to build any Visual Studio project by specifying the project (.VcxProj) or solutions (.Sln) file.
-2. Navigate to each of the respective project directories and enter the appropriate **MSbuild** command for your target. For example, to perform a clean build of a Visual Studio driver project called BthEcho.vcxproj, navigate to the samples\\bluetooth\\bthecho\\bthcli\\sys project directory and enter the following MSBuild command: **msbuild /t:clean /t:build .\\BthEchoSampleCli.vcxproj**.
-3. If the build succeeds, you will find the driver (BthEchoSampleCli.sys) in the binary output directory corresponding to the target platform.
-
-Run the sample
---------------
-
-**INSTALLATION**
-
-**Note**: Bluetooth echo server device and echo client device must be installed on two different machines, as described below.
-
-**Server Installation**
-
-1. Copy KMDF coinstaller (wdfcoinstallerMMmmm.dll, from redist\\wdf\\ ), BthEchoSampleSrv.Sys, BthEchoSampleSrv.inf and bthsrvinst.exe on a temporary directory on the target machine.
-
-2. Run bthsrvinst.exe /i to install the echo server device. This enables the Bluetooth Enumerator (BthEnum.sys) to enumerate echo server device and create a PDO for the device (please refer to the device tree below).
-
-3. Step \#2 causes BthEnum.sys to create a PDO. Consequently hardware installation wizard gets launched. Either go through the UI and point it to the temporary directory where you copied the binaries in step \#1, or using devcon.exe from the tools\\devcon folder, run the following command from the temporary directory:
-
- ```
- devcon.exe update BthEchoSampleSrv.inf BTHENUM\{c07508f2-b970-43ca-b5dd-cc4f2391bef4}
- ```
-
- If devcon.exe fails check the error level using:
-
- ```
- echo %errorlevel%
- ```
-
- If errorlevel is 1, you need to reboot the machine for KMDF update to take effect. If errorlevel is 2, please make sure that you have the driver files described in \#1 available in the current directory. For more information on installation failure please check setup logs.
-
-4. Upon successful installation you will see 'Bluetooth Echo Sample Server' in Device Manager under Bluetooth devices.
-
-**Device tree for Echo Server device**
-
-(Drivers for FDOs are shown for each devnode in the tree.)
-
-```
- --------------------
-|BthEchoSampleSrv.sys|<----Function driver for PDO ejected by BthEnum.sys
- --------------------
- ^
- | --------------------
- | |Bluetooth Enumerator|
- -----| (BthEnum.SYS) |
- --------------------
- ^
- | (Bth port driver loaded by bthusb.sys)
- | --------------------- ----------------------
- -----| bthport.SYS |<--->| bthusb.SYS |
- --------------------- ----------------------
- ^
- |
- V
- ----------------------
- | USB Stack |
- ----------------------
- ^
- |
- V
- ----------------------
- | USB Bluetooth Dongle |
- ----------------------
-```
-
-**Client Installation**
-
-1. **Important**: This must be done on a separate machine from the one where echo server device was installed.
-
-2. Copy KMDF coinstaller (wdfcoinstallerMMmmm.dll, from redist\\wdf\\), BthEchoSampleCli.Sys, BthEchoSampleCli.inf and bthecho.exe on a temporary directory on the target machine.
-
-3. Run bthprops.cpl from a command line or right click on the Bluetooth icon in the system tray and select 'Show Devices' to bring up a list of installed Bluetooth devices.
-
-4. In the **Bluetooth Devices** window, click the **Add a device** button.
-
-5. In the Add a Device wizard select the server machine (the machine where you installed the echo server) as a Bluetooth device. If the server machine does not appear, please check the echo server installation and make sure that you have enabled 'Allow Bluetooth device to find this computer' on the server machine as explained above. When the server machine is correctly displayed, select it and pick 'Next'.
-
-6. The wizard should default to a numeric compare ceremony for pairing the machines. When this happens, ensure the numbers match on both the client and the server, select 'Yes' on both machines to indicate they match, and click 'Next' on both machines to complete the pairing.
-
-7. Go through Device Manager and update driver software for it. Either point the wizard to the temporary directory created in step \#2, or use devcon.exe from the tools\\devcon folder to install the client device:
-
- ```
- Devcon.exe update BthEchoSampleCli.inf BTHENUM\{c07508f2-b970-43ca-b5dd-cc4f2391bef4}
- ```
-
- Check for any error from devcon.exe as described in server installation.
-
- If the installation is successful, you will see 'Bluetooth Echo Sample Client' in Device Manager under Bluetooth devices.
-
-The device tree for echo client device is similar to the one shown for the echo server device, since both client and server are enumerated by BthEnum.sys (although the installation mechanism and properties of client and server are different).
-
-**Uninstalling Server**
-
-1. Uninstall the device and delete driver software using the Bluetooth Devices window by running bthprops.cpl, right clicking on the device, and selecting 'Remove Device'
-
-2. Run bthsrvinst.exe /u to uninstall the echo server. This would make bthenum.sys stop enumerating the echo server. Without this step 'Found New Hardware' wizard will be launched again when you reconnect the device.
-
-**Uninstalling Client**
-
-
-- Uninstall the device and delete driver software using the Bluetooth Devices window by running bthprops.cpl, right clicking on the device, and selecting 'Remove Device'.
-
-**TESTING**
-
-Run BthEcho.exe on the client machine. You should see client sending data to the server and receiving the same data echoed back. Press Ctrl+c to terminate the application. You will see output similar to below:
-
-```batch
-D:\bth\wdfcli>BthEcho.exe
-DevicePath: \\?\bthenum#{c07508f2-b970-43ca-b5dd-cc4f2391bef4}_localmfg&000a#7&3
-62d0a3&0&000c55ff727a_c00000001#{fc71b33d-d528-4763-a86c-78777c7bcd7b}
-Opened device successfully
-Written 26 bytes: WDF Bluetooth Sample Echo
-Reply from server 26 bytes: WDF Bluetooth Sample Echo
-Written 26 bytes: WDF Bluetooth Sample Echo
-Reply from server 26 bytes: WDF Bluetooth Sample Echo
-Written 26 bytes: WDF Bluetooth Sample Echo
-Reply from server 26 bytes: WDF Bluetooth Sample Echo
-Written 26 bytes: WDF Bluetooth Sample Echo
-Reply from server 26 bytes: WDF Bluetooth Sample Echo
-Written 26 bytes: WDF Bluetooth Sample Echo
-^C
-```
-
-You can launch multiple instances of BthEcho.exe. Each client application would cause echo client device to have an independent connection to the echo server and thereby have an independent echo session. You can also have echo client devices and apps installed on multiple machines and talking to a single echo server.
-
-**CODE TOUR**
-
-**Common code**
-
-**Connection object**: The common code contains implementation of a connection object (in connection.\*) that is utilized by both client and the server. Client uses this object to maintain the information about opened connection and the server uses this object to maintain information about the accepted connection. Connection object also supports continuous reader which is utilized by server to read the data sent by client. Connection object is implemented as a WDF user object. Connection details are maintained in BTHECHO\_CONNECTION structure. This structure is used as the context for WDF user object. Passive dispose is used to make the connection object cleanup wait for disconnect completion and continuous reader rundown. Please see WDF documentation for WDF user object and passive dispose (see WdfObjectCreate).
-
-**Server**
-
-**Startup**: Server registers PSM and L2CA server and published SDP record on startup in BthEchoSrvEvtDeviceSelfManagedIoInit (this callback is invoked by WDF during device start). While registering the L2CA server it passes BthEchoSrvIndicationCallback as the callback for incoming connection notifications.
-
-**Server SDP record creation**: The sample uses dynamic creation of server SDP record using Bluetooth DDIs. Please note that for your particular device you may be able to use static data for the SDP record.
-
-**Incoming connections**: Bluetooth stack invokes BthEchoSrvIndicationCallback for the incoming connections from clients. In response server accepts the connection and passes BthEchoSrvConnectionIndicationCallback callback to Bluetooth stack for disconnect notification. It is possible to use the same indication callback for server and connection but the sample uses different callbacks for clarity. Server adds the accepted connection to the connection list it maintains. Please see below for connection rundown details.
-
-**Connection rundown**: Server maintains a list of all the connections it has accepted. This allows server to properly close down these connections on orderly removal. On surprise removal bthport.sys itself gets removed and takes care of running down the connections, but in case of orderly removal driver has to make sure to rundown the connections.
-
-**Connection state machine**:
-
-```
- ConnectFailed
- ^
- |
- |
- | (connection failure)
-Uninitialized ----> Connecting -------> Connected
- | (disconnect) / ^
- | / /
- | / /
- V V / (connection complete)
- Disconnecting
- | (disconnect complete)
- |
- |
- V
- Disconnected
-```
-
-One transition to note here is that if disconnect is received in the connecting state (i.e. when the connection is not completed) we wait for connection to completed (transition to connected state) and then invoke disconnect.
-
-**Important**: Such state machine is needed only if Disconnect is initiated by something other than Bluetooth stack (for example device removal in our case). Bluetooth stack itself would not send disconnect before connect completion. If you adapt this sample for your device please evaluate whether your driver would require such state machine. For example, the echo client device does not need such state machine (although we use common connection code for client and the server).
-
-**Shutdown**: Server removes the SDP record and unregisters L2CAP server and PSM in BthEchoSrvEvtDeviceSelfManagedIoCleanup (this callback is invoked by WDF during device removal). It also disconnects any open connections (see Connection rundown above).
-
-**Client**
-
-**Startup**: Client retrieves local and server Bluetooth address in BthEchoSrvEvtDeviceSelfManagedIoInit (this callback is invoked by WDF during device start). Please note that server Bluetooth address would be available regardless of presence of the server. Thus echo client device start doesn't fail even if echo server is not available.
-
-**Connecting to server**: Client connects to echo server when application opens a handle to it (BthEchoCliEvtDeviceFileCreate) and closes the connection on file close (BthEchoCliEvtFileClose).
-
-**Sending and receiving data from server**: When application writes data to the client, client sends this data to server on the connection opened for the given handle. Server would echo back this data. This data is retrieved by the application using a read operation. Echo Sample Client doesn't do any draining of echoed data on its own. Application read/write are handled using a parallel WDF I/O queue.
-
-**Shutdown**: Client doesn't need any specific shutdown code as connection open/close and read/write are done within the context of application's handle open.
diff --git a/bluetooth/serialhcibus/README.md b/bluetooth/serialhcibus/README.md
index c42b6dd4..cb7b9378 100644
--- a/bluetooth/serialhcibus/README.md
+++ b/bluetooth/serialhcibus/README.md
@@ -5,38 +5,31 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Bluetooth Serial HCI Bus Driver
- platform: WDM
- language: cpp
- category: Bluetooth
- description: Demonstrates how to implement a basic bus driver to support the new Bluetooth Extensibility transport DDIs over the UART transport.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617641
---->
-
# Bluetooth Serial HCI Bus Driver
-The purpose of this sample is to demonstrate how to implement a basic bus driver to support the new [Bluetooth Extensibility transport DDIs](http://msdn.microsoft.com/en-us/library/windows/hardware/ff536585) over the UART transport. Such a serial bus driver can support a multi-radio device over the UART transport and utilize a common Bluetooth HCI packet for communication. The lower edge of this driver interfaces with a UART controller following the Bluetooth SIG's UART (H4) transport protocol.
+The purpose of this sample is to demonstrate how to implement a basic bus driver to support the new [Bluetooth Extensibility transport DDIs](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/bthxddi/) over the UART transport. Such a serial bus driver can support a multi-radio device over the UART transport and utilize a common Bluetooth HCI packet for communication. The lower edge of this driver interfaces with a UART controller following the Bluetooth SIG's UART (H4) transport protocol.
## Universal Windows Driver Compliant
This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP.
-**Note** This sample driver is generic. It is not designed for a specific device and allows for a vendor to adopt and enhance it for supporting Bluetooth.
+> [!NOTE]
+> This sample driver is generic. It is not designed for a specific device and allows for a vendor to adopt and enhance it for supporting Bluetooth.
This sample driver, as is, may not properly function for a device until all vendor-specific device requirements (for example, device initialization) have been incorporated.
-It is recommended to use the WDK version that matches the target Windows build version or newer for the development of the serial bus driver.
+It is recommended to use the WDK version that matches the target Windows build version or newer for the development of the serial bus driver.
-**FILE MANIFEST**
+## File manifest
-**WDK header file**
+### WDK header file
-BthXDDI.h - this has the constants, struct, and IOCTL definitions for the Bluetooth extensibility transport. This header file is included in WDK.
+Bthxddi.h - contains the constants, struct, and IOCTL definitions for the Bluetooth extensibility transport. This header file is included in WDK.
-**Common code section**
+### Common code section
driver.c - driver initialization
@@ -54,24 +47,24 @@ public.h - header to share with application to support Radio On/Off ("Airplane m
Note: The goal is to keep the common code section the same, so the vendor will only need to update those code sections in the device specific directory.
-**Device-specific code section**
+### Device-specific code section
Debugdef.h - WPP trace GUID; user should use a new GUID (unique per driver)
device.c - device specific functions to implement:
---DeviceInitialize() - to perform UART and Bluetooth device initialization;
+- DeviceInitialize() - to perform UART and Bluetooth device initialization;
---DeviceEnable() - (optional) to bring serial bus device out of disable/reset state.
+- DeviceEnable() - (optional) to bring serial bus device out of disable/reset state.
---DevicePowerOn() - (optional) to power on the device.
+- DevicePowerOn() - (optional) to power on the device.
---DeviceEnableWakeControl() - (optional) to arm for device wake signal
+- DeviceEnableWakeControl() - (optional) to arm for device wake signal
---DeviceDisableWakeControl() - (optional) to disarm for device wake signal
+- DeviceDisableWakeControl() - (optional) to disarm for device wake signal
device.h - header file for device.c
driver.rc - driver version and name
-SerialBusWdk.inx - device specific INF file to install this driver. The vendor will need to add the hardware ID to match the "\_HID" for the Serial Bus Device (Bluetooth) in the DSDT.asl file. For example, in SerialBusWDK.inx, the hardware ID is "ACPI\\<*vendor*\>\_BTH0" where <*vendor*\> could be a 4 digit vendor name.
+SerialBusWdk.inx - device specific INF file to install this driver. The vendor will need to add the hardware ID to match the "\_HID" for the Serial Bus Device (Bluetooth) in the DSCY.asl file. For example, in SerialBusWDK.inx, the hardware ID is "ACPI\\<*vendor*\>\_BTH0" where <*vendor*\> could be a 4 digit vendor name.
diff --git a/bluetooth/serialhcibus/WDK/device.c b/bluetooth/serialhcibus/WDK/device.c
index 11859e9f..a78088cf 100644
--- a/bluetooth/serialhcibus/WDK/device.c
+++ b/bluetooth/serialhcibus/WDK/device.c
@@ -255,3 +255,26 @@ Return Value:
return STATUS_SUCCESS;
}
+_Use_decl_annotations_
+VOID
+DeviceDoPLDR(
+ WDFDEVICE _Fdo
+ )
+/*++
+
+Routine Description:
+
+ This vendor-specific routine takes appropriate actions necessary to fully reset the device.
+
+Arguments:
+
+ _Fdo - Framework device object representing the FDO.
+
+Return Value:
+
+ VOID.
+
+--*/
+{
+ UNREFERENCED_PARAMETER(_Fdo);
+}
diff --git a/bluetooth/serialhcibus/driver.h b/bluetooth/serialhcibus/driver.h
index 4d9decca..bb006ece 100644
--- a/bluetooth/serialhcibus/driver.h
+++ b/bluetooth/serialhcibus/driver.h
@@ -28,6 +28,7 @@ Environment:
#define INITGUID
#include <guiddef.h>
+#include <wdmguid.h>
#include <ntddser.h> // Constants and types for access Serial device
#include <BthXDDI.h> // BT Extensible Transport DDI
@@ -80,6 +81,40 @@ typedef enum _IDLE_CAP_STATE {
IdleCapCanTurnOff = 3 // Can enter D3 (off) and not remote wake to save max power while device is off.
} IDLE_CAP_STATE;
+//
+// Reset recovery support capability. Multiple implementations are provided to choose from and
+// customize as appropriate.
+//
+typedef enum _RESET_RECOVERY_SUPPORT_TYPE {
+ ResetRecoveryTypeNone = 0, // Reset-recovery is not implemented in the driver. This may be
+ // used if the stack does not support reset-recovery at all, or
+ // if ACPI firmware already implements reset-recovery in the context
+ // of the child device stack (i.e., the stack that loads on the
+ // PDO created by this driver). In that case, the bus driver does
+ // not need any additional code to support reset-recovery. However,
+ // it does need to support GUID_REENUMERATE_SELF_INTERFACE_STANDARD,
+ // which is most easily achieved by using WDF dynamic-enumeration
+ // for creating PDOs.
+
+ ResetRecoveryTypeParentResetInterface = 1, // Delegate to GUID_DEVICE_RESET_INTERFACE_STANDARD
+ // support in the parent stack. The parent stack, i.e., the
+ // stack on which this driver loads as the FDO, must have
+ // support for GUID_DEVICE_RESET_INTERFACE_STANDARD. This is
+ // typically provided by the ACPI bus driver, if the ACPI device
+ // supports D3Cold (_PR3) or a power resource for reset (_PRR +
+ // _RST). See the documentation of
+ // GUID_DEVICE_RESET_INTERFACE_STANDARD for more information.
+
+ ResetRecoveryTypeDriverImplemented = 2, // Reset recovery is implemented in the driver.
+ // Hardware-specific techniques are used to power-cycle the controller.
+
+} RESET_RECOVERY_TYPE;
+
+//
+// Driver author may choose whichever reset-recovery strategy works best for their platform.
+//
+#define SUPPORTED_RESET_RECOVERY_TYPE ResetRecoveryTypeDriverImplemented
+
#ifdef DYNAMIC_ENUM
//
// The goal of the identification and address description abstractions is that enough
@@ -304,6 +339,11 @@ typedef struct _PDO_EXTENSION
//
ULONG SerialNo;
+ //
+ // Type of reset-recovery support implemented.
+ //
+ RESET_RECOVERY_TYPE ResetRecoveryType;
+
} PDO_EXTENSION, *PPDO_EXTENSION;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(PDO_EXTENSION, PdoGetExtension)
@@ -383,8 +423,17 @@ EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL FdoIoQuDeviceControl;
// PDO creation
#ifdef DYNAMIC_ENUM
+
+_IRQL_requires_max_(PASSIVE_LEVEL)
+NTSTATUS
+PdoResetHandlerDynamic(_In_ PVOID _InterfaceContext,
+ _In_ DEVICE_RESET_TYPE _ResetType,
+ _In_ ULONG _Flags,
+ _In_opt_ PVOID _ResetParameters);
+
EVT_WDF_CHILD_LIST_CREATE_DEVICE FdoEvtDeviceListCreatePdo;
+_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
PdoCreateDynamic(_In_ WDFDEVICE Device,
_In_ PWDFDEVICE_INIT DeviceInit,
@@ -430,6 +479,13 @@ EVT_WDF_DEVICE_D0_EXIT PdoDevD0Exit;
EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL PdoIoQuDeviceControl;
+_IRQL_requires_max_(PASSIVE_LEVEL)
+NTSTATUS
+PdoResetHandler(_In_ PVOID _InterfaceContext,
+ _In_ DEVICE_RESET_TYPE _ResetType,
+ _In_ ULONG _Flags,
+ _In_opt_ PVOID _ResetParameters);
+
NTSTATUS
PdoCreate(_In_ WDFDEVICE _Device,
_In_ PWSTR _HardwareIds,
@@ -508,6 +564,7 @@ DevicePowerOn(_In_ WDFDEVICE _Device);
NTSTATUS
DevicePowerOff(_In_ WDFDEVICE _Device);
-#endif
-
+VOID
+DeviceDoPLDR(_In_ WDFDEVICE _Fdo);
+#endif
diff --git a/bluetooth/serialhcibus/pdo.c b/bluetooth/serialhcibus/pdo.c
index 74ee6350..48e4abd1 100644
--- a/bluetooth/serialhcibus/pdo.c
+++ b/bluetooth/serialhcibus/pdo.c
@@ -26,21 +26,81 @@ Environment:
#pragma alloc_text(PAGE, PdoDevD0Entry)
#pragma alloc_text(PAGE, PdoDevPrepareHardware)
#pragma alloc_text(PAGE, PdoDevReleaseHardware)
-#endif
+#pragma alloc_text(PAGE, PdoResetHandler)
+#ifdef DYNAMIC_ENUM
+#pragma alloc_text(PAGE, PdoCreateDynamic)
+#pragma alloc_text(PAGE, PdoResetHandlerDynamic)
+#endif // DYNAMIC_ENUM
+#endif // ALLOC_PRAGMA
#define MAX_ID_LEN 80
+#ifdef DYNAMIC_ENUM
+_Use_decl_annotations_
+NTSTATUS
+PdoResetHandlerDynamic(
+ PVOID _InterfaceContext,
+ DEVICE_RESET_TYPE _ResetType,
+ ULONG _Flags,
+ PVOID _ResetParameters
+ )
+/*++
-#ifdef DYNAMIC_ENUM
+Routine Description:
+
+ This is the reset handler invoked by a driver that queries our GUID_DEVICE_RESET_INTERFACE_STANDARD interface.
+ This is the version used if PDOs are created using WDF dynamic enumeration.
+
+Arguments:
+
+ _InterfaceContext - This is expected to be a PPDO_EXTENSION.
+
+ _ResetType - This is expected to be PlatformLevelDeviceReset because that is all we support.
+
+ _Flags - Unused, because no flags are defined currently.
+
+ _ResetParameters - Unused, because it is only used for FunctionLevelDeviceReset.
+
+Return Value:
+
+ NTSTATUS code.
+
+--*/
+{
+ PPDO_EXTENSION PdoExtension = (PPDO_EXTENSION) _InterfaceContext;
+
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(_Flags);
+ UNREFERENCED_PARAMETER(_ResetParameters);
+
+ if (_ResetType != PlatformLevelDeviceReset) {
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ DeviceDoPLDR(PdoExtension->FdoExtension->WdfDevice);
+
+ //
+ // The bus driver is expected to cause the device to be surprise removed as part of PLDR. For
+ // many hardware buses, this happens naturally, but for a software bus like us, we need to do it
+ // ourselves. WDF dynamic enumeration makes this convenient because it already supports
+ // GUID_REENUMERATE_SELF_INTERFACE_STANDARD, so we can simply call WdfDeviceSetFailed to
+ // re-enumerate the device.
+ //
+ WdfDeviceSetFailed((WDFDEVICE) WdfObjectContextGetObject(PdoExtension), WdfDeviceFailedAttemptRestart);
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
NTSTATUS
PdoCreateDynamic(
- _In_ WDFDEVICE _Device,
- _In_ PWDFDEVICE_INIT _DeviceInit,
- _In_ PWCHAR _HardwareIds,
- _In_ ULONG _SerialNo
+ WDFDEVICE _Device,
+ PWDFDEVICE_INIT _DeviceInit,
+ PWCHAR _HardwareIds,
+ ULONG _SerialNo
)
/*++
@@ -56,20 +116,20 @@ Return Value:
--*/
{
- NTSTATUS Status;
- PPDO_EXTENSION PdoExtension = NULL;
- WDFDEVICE ChildDevice = NULL;
- WDF_OBJECT_ATTRIBUTES pdoAttributes;
- WDF_DEVICE_PNP_CAPABILITIES pnpCaps;
- WDF_DEVICE_POWER_CAPABILITIES powerCaps;
- DECLARE_CONST_UNICODE_STRING(compatId, BT_PDO_COMPATIBLE_IDS);
- DECLARE_CONST_UNICODE_STRING(deviceLocation, L"Serial HCI Bus - Bluetooth Function");
- DECLARE_UNICODE_STRING_SIZE(buffer, MAX_ID_LEN);
- DECLARE_UNICODE_STRING_SIZE(deviceId, MAX_ID_LEN);
-
- WDF_IO_QUEUE_CONFIG QueueConfig;
- WDFQUEUE Queue;
-
+ NTSTATUS Status;
+ PPDO_EXTENSION PdoExtension = NULL;
+ WDFDEVICE ChildDevice = NULL;
+ WDF_OBJECT_ATTRIBUTES PdoAttributes;
+ WDF_DEVICE_PNP_CAPABILITIES PnpCaps;
+ WDF_DEVICE_POWER_CAPABILITIES PowerCaps;
+ DECLARE_CONST_UNICODE_STRING( CompatId, BT_PDO_COMPATIBLE_IDS);
+ DECLARE_CONST_UNICODE_STRING( DeviceLocation, L"Serial HCI Bus - Bluetooth Function");
+ DECLARE_UNICODE_STRING_SIZE( Buffer, MAX_ID_LEN);
+ DECLARE_UNICODE_STRING_SIZE( DeviceId, MAX_ID_LEN);
+ WDF_IO_QUEUE_CONFIG QueueConfig;
+ WDFQUEUE Queue;
+ WDF_QUERY_INTERFACE_CONFIG DeviceResetInterfaceConfig;
+ DEVICE_RESET_INTERFACE_STANDARD ResetInterface;
PAGED_CODE();
@@ -85,9 +145,9 @@ Return Value:
//
// Provide DeviceID, HardwareIDs, CompatibleIDs and InstanceId
//
- RtlInitUnicodeString(&deviceId, _HardwareIds);
+ RtlInitUnicodeString(&DeviceId, _HardwareIds);
- Status = WdfPdoInitAssignDeviceID(_DeviceInit, &deviceId);
+ Status = WdfPdoInitAssignDeviceID(_DeviceInit, &DeviceId);
if (!NT_SUCCESS(Status)) {
return Status;
}
@@ -95,22 +155,22 @@ Return Value:
//
// NOTE: same string is used to initialize hardware id too
//
- Status = WdfPdoInitAddHardwareID(_DeviceInit, &deviceId);
+ Status = WdfPdoInitAddHardwareID(_DeviceInit, &DeviceId);
if (!NT_SUCCESS(Status)) {
return Status;
}
- Status = WdfPdoInitAddCompatibleID(_DeviceInit, &compatId );
+ Status = WdfPdoInitAddCompatibleID(_DeviceInit, &CompatId );
if (!NT_SUCCESS(Status)) {
return Status;
}
- Status = RtlUnicodeStringPrintf(&buffer, L"%02d", _SerialNo);
+ Status = RtlUnicodeStringPrintf(&Buffer, L"%02d", _SerialNo);
if (!NT_SUCCESS(Status)) {
return Status;
}
- Status = WdfPdoInitAssignInstanceID(_DeviceInit, &buffer);
+ Status = WdfPdoInitAssignInstanceID(_DeviceInit, &Buffer);
if (!NT_SUCCESS(Status)) {
return Status;
}
@@ -124,7 +184,7 @@ Return Value:
// coinstallers to display in the device manager. FriendlyName takes
// precedence over the DeviceDesc from the INF file.
//
- Status = RtlUnicodeStringPrintf( &buffer,
+ Status = RtlUnicodeStringPrintf( &Buffer,
L"SerialHciBus_%02d",
_SerialNo );
if (!NT_SUCCESS(Status)) {
@@ -140,8 +200,8 @@ Return Value:
// WdfPdoInitSetDefaultLocale.
//
Status = WdfPdoInitAddDeviceText(_DeviceInit,
- &buffer,
- &deviceLocation,
+ &Buffer,
+ &DeviceLocation,
0x409 );
if (!NT_SUCCESS(Status)) {
return Status;
@@ -153,7 +213,7 @@ Return Value:
// Initialize the attributes to specify the size of PDO device extension.
// All the state information private to the PDO will be tracked here.
//
- WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, PDO_EXTENSION);
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&PdoAttributes, PDO_EXTENSION);
//
// Allow to forward requests to its FDO of this bus driver by using
@@ -166,7 +226,7 @@ Return Value:
// to this call, framework creates a WDM deviceobject.
//
Status = WdfDeviceCreate(&_DeviceInit,
- &pdoAttributes,
+ &PdoAttributes,
&ChildDevice);
if (!NT_SUCCESS(Status)) {
@@ -191,7 +251,7 @@ Return Value:
PdoExtension->SerialNo = _SerialNo;
-
+ PdoExtension->ResetRecoveryType = SUPPORTED_RESET_RECOVERY_TYPE;
//
// Set some properties for the child device.
@@ -211,31 +271,31 @@ Return Value:
//
PnpCaps.SurpriseRemovalOK = WdfTrue;
- pnpCaps.Address = _SerialNo;
- pnpCaps.UINumber = _SerialNo;
+ PnpCaps.Address = _SerialNo;
+ PnpCaps.UINumber = _SerialNo;
- WdfDeviceSetPnpCapabilities(ChildDevice, &pnpCaps);
+ WdfDeviceSetPnpCapabilities(ChildDevice, &PnpCaps);
- WDF_DEVICE_POWER_CAPABILITIES_INIT(&powerCaps);
+ WDF_DEVICE_POWER_CAPABILITIES_INIT(&PowerCaps);
- powerCaps.DeviceD1 = WdfFalse;
- powerCaps.DeviceD2 = WdfTrue;
+ PowerCaps.DeviceD1 = WdfFalse;
+ PowerCaps.DeviceD2 = WdfTrue;
- powerCaps.WakeFromD0 = WdfFalse;
- powerCaps.WakeFromD1 = WdfFalse;
- powerCaps.WakeFromD2 = WdfTrue;
- powerCaps.WakeFromD3 = WdfTrue;
+ PowerCaps.WakeFromD0 = WdfFalse;
+ PowerCaps.WakeFromD1 = WdfFalse;
+ PowerCaps.WakeFromD2 = WdfTrue;
+ PowerCaps.WakeFromD3 = WdfTrue;
- powerCaps.DeviceWake = PowerDeviceD2;
+ PowerCaps.DeviceWake = PowerDeviceD2;
- powerCaps.DeviceState[PowerSystemWorking] = PowerDeviceD0;
- powerCaps.DeviceState[PowerSystemSleeping1] = PowerDeviceD2;
- powerCaps.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
- powerCaps.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
- powerCaps.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
- powerCaps.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
+ PowerCaps.DeviceState[PowerSystemWorking] = PowerDeviceD0;
+ PowerCaps.DeviceState[PowerSystemSleeping1] = PowerDeviceD2;
+ PowerCaps.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
+ PowerCaps.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
+ PowerCaps.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
+ PowerCaps.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
- WdfDeviceSetPowerCapabilities(ChildDevice, &powerCaps);
+ WdfDeviceSetPowerCapabilities(ChildDevice, &PowerCaps);
//
@@ -263,7 +323,52 @@ Return Value:
if (!NT_SUCCESS(Status)) {
goto Cleanup;
}
-
+
+ if (PdoExtension->ResetRecoveryType == ResetRecoveryTypeParentResetInterface) {
+
+ //
+ // Instruct WDF to simply forward a request for the reset interface to the parent stack, so
+ // that it reaches the ACPI bus/filter driver. That way when the reset interface is invoked,
+ // it is the parent stack that gets reset and re-enumerated.
+ //
+
+ WDF_QUERY_INTERFACE_CONFIG_INIT(&DeviceResetInterfaceConfig, NULL, &GUID_DEVICE_RESET_INTERFACE_STANDARD, NULL);
+ DeviceResetInterfaceConfig.SendQueryToParentStack = TRUE;
+
+ Status = WdfDeviceAddQueryInterface(ChildDevice, &DeviceResetInterfaceConfig);
+ if (!NT_SUCCESS(Status)) {
+ DoTrace(LEVEL_ERROR, TFLAG_PNP, ("WdfDeviceAddQueryInterface failed, %!STATUS!", Status));
+ goto Cleanup;
+ }
+
+ } else if (PdoExtension->ResetRecoveryType == ResetRecoveryTypeDriverImplemented) {
+
+ RtlZeroMemory(&ResetInterface, sizeof(ResetInterface));
+ ResetInterface.Size = sizeof(ResetInterface);
+ ResetInterface.Version = DEVICE_RESET_INTERFACE_VERSION;
+ ResetInterface.Context = PdoExtension;
+
+ //
+ // Since this interface is expected to be used only by drivers in the same stack, reference
+ // counting is not required. If there is an expectation that drivers may query for the
+ // interface using a remote I/O target to this stack (unusual for this interface), reference
+ // counting must be implemented.
+ //
+ ResetInterface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
+ ResetInterface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
+
+ ResetInterface.SupportedResetTypes = (1 << PlatformLevelDeviceReset);
+ ResetInterface.DeviceReset = PdoResetHandlerDynamic;
+
+ WDF_QUERY_INTERFACE_CONFIG_INIT(&DeviceResetInterfaceConfig, (PINTERFACE) &ResetInterface, &GUID_DEVICE_RESET_INTERFACE_STANDARD, NULL);
+ Status = WdfDeviceAddQueryInterface(ChildDevice, &DeviceResetInterfaceConfig);
+ if (!NT_SUCCESS(Status))
+ {
+ DoTrace(LEVEL_ERROR, TFLAG_PNP, ("WdfDeviceAddQueryInterface failed, %!STATUS!", Status));
+ goto Cleanup;
+ }
+ }
+
Cleanup:
@@ -291,7 +396,62 @@ Cleanup:
#endif
+_Use_decl_annotations_
+NTSTATUS
+PdoResetHandler(
+ PVOID _InterfaceContext,
+ DEVICE_RESET_TYPE _ResetType,
+ ULONG _Flags,
+ PVOID _ResetParameters
+)
+/*++
+
+Routine Description:
+
+ This is the reset handler invoked by a driver that queries our GUID_DEVICE_RESET_INTERFACE_STANDARD interface.
+ This is the version used if PDOs are created using WDF static enumeration.
+
+Arguments:
+
+ _InterfaceContext - This is expected to be a PPDO_EXTENSION.
+
+ _ResetType - This is expected to be PlatformLevelDeviceReset because that is all we support.
+
+ _Flags - Unused, because no flags are defined currently.
+
+ _ResetParameters - Unused, because it is only used for FunctionLevelDeviceReset.
+
+Return Value:
+
+ NTSTATUS code.
+
+--*/
+{
+ PPDO_EXTENSION PdoExtension = (PPDO_EXTENSION) _InterfaceContext;
+ WDFDEVICE Fdo = PdoExtension->FdoExtension->WdfDevice;
+
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(_Flags);
+ UNREFERENCED_PARAMETER(_ResetParameters);
+
+ if (_ResetType != PlatformLevelDeviceReset) {
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ DeviceDoPLDR(Fdo);
+
+ //
+ // The bus driver is expected to cause the device to be surprise removed as part of PLDR. For
+ // many hardware buses, this happens naturally, but for a software bus like us, we need to do it
+ // ourselves.
+ //
+ FdoRemoveOneChildDevice(Fdo, BLUETOOTH_FUNC_IDS);
+ FdoCreateOneChildDevice(Fdo, BT_PDO_HARDWARE_IDS, BLUETOOTH_FUNC_IDS);
+
+ return STATUS_SUCCESS;
+}
NTSTATUS
PdoCreate(
@@ -319,21 +479,23 @@ Return Value:
--*/
{
- NTSTATUS Status;
- PWDFDEVICE_INIT DeviceInit = NULL;
- WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerCallbacks;
- PPDO_EXTENSION PdoExtension = NULL;
- WDFDEVICE ChildDevice = NULL;
- WDF_OBJECT_ATTRIBUTES Attributes;
- WDF_DEVICE_PNP_CAPABILITIES PnpCaps;
- WDF_DEVICE_POWER_CAPABILITIES PowerCaps;
- UNICODE_STRING StaticString = {0};
- UNICODE_STRING DeviceId;
- DECLARE_UNICODE_STRING_SIZE(Buffer, MAX_ID_LEN);
- UNICODE_STRING ContainerID = {0};
- WDF_PDO_EVENT_CALLBACKS Callbacks;
- WDF_IO_QUEUE_CONFIG QueueConfig;
- WDFQUEUE Queue;
+ NTSTATUS Status;
+ PWDFDEVICE_INIT DeviceInit = NULL;
+ WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerCallbacks;
+ PPDO_EXTENSION PdoExtension = NULL;
+ WDFDEVICE ChildDevice = NULL;
+ WDF_OBJECT_ATTRIBUTES Attributes;
+ WDF_DEVICE_PNP_CAPABILITIES PnpCaps;
+ WDF_DEVICE_POWER_CAPABILITIES PowerCaps;
+ UNICODE_STRING StaticString = {0};
+ UNICODE_STRING DeviceId;
+ DECLARE_UNICODE_STRING_SIZE( Buffer, MAX_ID_LEN);
+ UNICODE_STRING ContainerID = {0};
+ WDF_PDO_EVENT_CALLBACKS Callbacks;
+ WDF_IO_QUEUE_CONFIG QueueConfig;
+ WDFQUEUE Queue;
+ WDF_QUERY_INTERFACE_CONFIG DeviceResetInterfaceConfig;
+ DEVICE_RESET_INTERFACE_STANDARD ResetInterface;
DoTrace(LEVEL_INFO, TFLAG_PNP, (" +PdoCreate: HWID(%S), compatID(%S)", _HardwareIds, BT_PDO_COMPATIBLE_IDS));
@@ -524,6 +686,7 @@ Return Value:
PdoExtension->SerialNo = _SerialNo;
+ PdoExtension->ResetRecoveryType = SUPPORTED_RESET_RECOVERY_TYPE;
//
// Set PnP and Power capabilities for this child device.
@@ -593,7 +756,52 @@ Return Value:
DoTrace(LEVEL_INFO, TFLAG_PNP, (" WdfIoQueueCreate (%!STATUS!)", Status));
if (!NT_SUCCESS(Status)) {
goto Cleanup;
- }
+ }
+
+ if (PdoExtension->ResetRecoveryType == ResetRecoveryTypeParentResetInterface) {
+
+ //
+ // Instruct WDF to simply forward a request for the reset interface to the parent stack, so
+ // that it reaches the ACPI bus/filter driver. That way when the reset interface is invoked,
+ // it is the parent stack that gets reset and re-enumerated.
+ //
+
+ WDF_QUERY_INTERFACE_CONFIG_INIT(&DeviceResetInterfaceConfig, NULL, &GUID_DEVICE_RESET_INTERFACE_STANDARD, NULL);
+ DeviceResetInterfaceConfig.SendQueryToParentStack = TRUE;
+
+ Status = WdfDeviceAddQueryInterface(ChildDevice, &DeviceResetInterfaceConfig);
+ if (!NT_SUCCESS(Status)) {
+ DoTrace(LEVEL_ERROR, TFLAG_PNP, ("WdfDeviceAddQueryInterface failed, %!STATUS!", Status));
+ goto Cleanup;
+ }
+
+ } else if (PdoExtension->ResetRecoveryType == ResetRecoveryTypeDriverImplemented) {
+
+ RtlZeroMemory(&ResetInterface, sizeof(ResetInterface));
+ ResetInterface.Size = sizeof(ResetInterface);
+ ResetInterface.Version = DEVICE_RESET_INTERFACE_VERSION;
+ ResetInterface.Context = PdoExtension;
+
+ //
+ // Since this interface is expected to be used only by drivers in the same stack, reference
+ // counting is not required. If there is an expectation that drivers may query for the
+ // interface using a remote I/O target to this stack (unusual for this interface), reference
+ // counting must be implemented.
+ //
+ ResetInterface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
+ ResetInterface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
+
+ ResetInterface.SupportedResetTypes = (1 << PlatformLevelDeviceReset);
+ ResetInterface.DeviceReset = PdoResetHandler;
+
+ WDF_QUERY_INTERFACE_CONFIG_INIT(&DeviceResetInterfaceConfig, (PINTERFACE) &ResetInterface, &GUID_DEVICE_RESET_INTERFACE_STANDARD, NULL);
+ Status = WdfDeviceAddQueryInterface(ChildDevice, &DeviceResetInterfaceConfig);
+ if (!NT_SUCCESS(Status))
+ {
+ DoTrace(LEVEL_ERROR, TFLAG_PNP, ("WdfDeviceAddQueryInterface failed, %!STATUS!", Status));
+ goto Cleanup;
+ }
+ }
//
// Add this device to the FDO's collection of children.
diff --git a/filesys/cdfs/README.md b/filesys/cdfs/README.md
index a835c10f..1c3a374d 100644
--- a/filesys/cdfs/README.md
+++ b/filesys/cdfs/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: CDFS File System Driver
- platform: WDM
- language: cpp
- category: FileSystem
- description: The CD-ROM file system driver (cdfs) sample is a file system driver for removable media.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617642
---->
-
# CDFS File System Driver
The CD-ROM file system driver (cdfs) sample is a sample file system driver that you can use to write new file systems.
diff --git a/filesys/fastfat/README.md b/filesys/fastfat/README.md
index b34679ff..1c409ac7 100644
--- a/filesys/fastfat/README.md
+++ b/filesys/fastfat/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: fastfat File System Driver
- platform: WDM
- language: cpp
- category: FileSystem
- description: A file system driver based on the Windows inbox FastFAT file system used as a model for new file systems.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620305
---->
-
# fastfat File System Driver
The *fastfat* sample is file system driver that you can use as a model to write new file systems.
@@ -26,8 +18,7 @@ The *fastfat* sample is file system driver that you can use as a model to write
This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP.
-Build the sample
-----------------
+## Build the sample
You can build the sample in two ways: using Microsoft Visual Studio or the command line (*MSBuild*).
@@ -37,27 +28,28 @@ You build a driver the same way you build any project or solution in Visual Stud
The default Solution build configuration is **Debug** and **Win32**.
-**To select a configuration and build a driver**
+#### To select a configuration and build a driver
+
+1. Open the driver project or solution in Visual Studio (find fastfat.sln or fastfat.vcxproj).
+
+1. Right-click the solution in the **Solutions Explorer** and select **Configuration Manager**.
-1. Open the driver project or solution in Visual Studio (find fastfat.sln or fastfat.vcxproj).
-2. Right-click the solution in the **Solutions Explorer** and select **Configuration Manager**.
-3. From the **Configuration Manager**, select the **Active Solution Configuration** (for example, Debug or Release) and the **Active Solution Platform** (for example, Win32) that correspond to the type of build you are interested in.
-4. From the Build menu, click **Build Solution** (Ctrl+Shift+B).
+1. From the **Configuration Manager**, select the **Active Solution Configuration** (for example, Debug or Release) and the **Active Solution Platform** (for example, Win32) that correspond to the type of build you are interested in.
+
+1. From the Build menu, click **Build Solution** (Ctrl+Shift+B).
### Building a Driver Using the Command Line (MSBuild)
You can build a driver from the command line using the Visual Studio Command Prompt window and the Microsoft Build Engine (MSBuild.exe) Previous versions of the WDK used the Windows Build utility (Build.exe) and provided separate build environment windows for each of the supported build configurations. You can now use the Visual Studio Command Prompt window for all build configurations.
-**To select a configuration and build a driver or an application**
+#### To select a configuration and build a driver or an application
+
+1. Open a Visual Studio Command Prompt window at the **Start** screen. From this window you can use MsBuild.exe to build any Visual Studio project by specifying the project (.VcxProj) or solutions (.Sln) file.
-1. Open a Visual Studio Command Prompt window at the **Start** screen. From this window you can use MsBuild.exe to build any Visual Studio project by specifying the project (.VcxProj) or solutions (.Sln) file.
-2. Navigate to the project directory and enter the **MSbuild** command for your target. For example, to perform a clean build of a Visual Studio driver project called *filtername*.vcxproj, navigate to the project directory and enter the following MSBuild command:
+1. Navigate to the project directory and enter the **MSbuild** command for your target. For example, to perform a clean build of a Visual Studio driver project called *filtername*.vcxproj, navigate to the project directory and enter the following MSBuild command:
-```bash
-msbuild /t:clean /t:build .\\fastfat.vcxproj
-```
+`msbuild /t:clean /t:build .\\fastfat.vcxproj`
-Installation
-------------
+## Installation
No INF file is provided with this sample because the *fastfat* file system driver (fastfat.sys) is already part of the Windows operating system. You can build a private version of this file system and use it as a replacement for the native driver.
diff --git a/filesys/fastfat/fsctrl.c b/filesys/fastfat/fsctrl.c
index d6bf369b..7371c7fd 100644
--- a/filesys/fastfat/fsctrl.c
+++ b/filesys/fastfat/fsctrl.c
@@ -1411,22 +1411,34 @@ Return Value:
if (Dirent != NULL) {
+ UCHAR OemBuffer[11];
OEM_STRING OemString;
UNICODE_STRING UnicodeString;
+ OemString.Buffer = (PCHAR)&OemBuffer[0];
+ OemString.MaximumLength = 11;
+
+ RtlCopyMemory( OemString.Buffer, Dirent->FileName, 11 );
+
//
- // Compute the length of the volume name
+ // Translate the first character from 0x5 to 0xe5.
//
- OemString.Buffer = (PCHAR)&Dirent->FileName[0];
- OemString.MaximumLength = 11;
+ if (OemString.Buffer[0] == FAT_DIRENT_REALLY_0E5) {
+
+ OemString.Buffer[0] = 0xe5;
+ }
+
+ //
+ // Compute the length of the volume name
+ //
for ( OemString.Length = 11;
OemString.Length > 0;
OemString.Length -= 1) {
- if ( (Dirent->FileName[OemString.Length-1] != 0x00) &&
- (Dirent->FileName[OemString.Length-1] != 0x20) ) { break; }
+ if ( (OemString.Buffer[OemString.Length-1] != 0x00) &&
+ (OemString.Buffer[OemString.Length-1] != 0x20) ) { break; }
}
UnicodeString.MaximumLength = MAXIMUM_VOLUME_LABEL_LENGTH;
@@ -7794,6 +7806,7 @@ Return Value:
PDIRENT Dirent;
PDIRENT TerminationDirent;
ULONG VolumeLabelLength;
+ UCHAR OemBuffer[11];
OEM_STRING OemString;
UNICODE_STRING UnicodeString;
@@ -7840,19 +7853,30 @@ Return Value:
}
+ OemString.Buffer = (PCHAR)&OemBuffer[0];
+ OemString.MaximumLength = 11;
+
+ RtlCopyMemory( OemString.Buffer, Dirent->FileName, 11 );
+
//
- // Compute the length of the volume name
+ // Translate the first character from 0x5 to 0xe5.
//
- OemString.Buffer = (PCHAR)&Dirent->FileName[0];
- OemString.MaximumLength = 11;
+ if (OemString.Buffer[0] == FAT_DIRENT_REALLY_0E5) {
+
+ OemString.Buffer[0] = 0xe5;
+ }
+
+ //
+ // Compute the length of the volume name
+ //
for ( OemString.Length = 11;
OemString.Length > 0;
OemString.Length -= 1) {
- if ( (Dirent->FileName[OemString.Length-1] != 0x00) &&
- (Dirent->FileName[OemString.Length-1] != 0x20) ) { break; }
+ if ( (OemString.Buffer[OemString.Length-1] != 0x00) &&
+ (OemString.Buffer[OemString.Length-1] != 0x20) ) { break; }
}
UnicodeString.MaximumLength = sizeof( UnicodeBuffer );
diff --git a/filesys/fastfat/volinfo.c b/filesys/fastfat/volinfo.c
index 9827ca4b..8bed20dd 100644
--- a/filesys/fastfat/volinfo.c
+++ b/filesys/fastfat/volinfo.c
@@ -1154,6 +1154,15 @@ Return Value:
if (OemLabel.Length > 0) {
//
+ // Translate the first character from 0xe5 to 0x5.
+ //
+
+ if ((UCHAR)OemLabel.Buffer[0] == 0xe5) {
+
+ OemLabel.Buffer[0] = FAT_DIRENT_REALLY_0E5;
+ }
+
+ //
// Locate the volume label if there already is one
//
diff --git a/filesys/miniFilter/MetadataManager/README.md b/filesys/miniFilter/MetadataManager/README.md
index 23196413..aae5ea2c 100644
--- a/filesys/miniFilter/MetadataManager/README.md
+++ b/filesys/miniFilter/MetadataManager/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Metadata Manager File System Minifilter Driver
- platform: WDM
- language: cpp
- category: FileSystem
- description: An example of how to use files for storing metadata that corresponds to minifilters.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617650
---->
-
# Metadata Manager File System Minifilter Driver
The Metadata Manager minifilter sample serves as an example if you want to use files for storing metadata that corresponds to your minifilters. The implementation of this sample depicts scenarios in which modifications to the file might have to be blocked or the minifilter might be required to close the file temporarily.
@@ -34,4 +26,4 @@ Similarly, the minifilter might close its metadata file if it sees an explicit F
The metadata minifilter also handles the case when a snapshot of its volume object is being taken. In this scenario, the minifilter acquires a shared exclusive lock on the metadata resource object while calling the callback that corresponds to the pre-device control operation for IOCTL\_VOLSNAP\_FLUSH\_AND\_HOLD\_WRITES. The lock is later released in the callback that corresponds to the post-device control operation for IOCTL\_VOLSNAP\_FLUSH\_AND\_HOLD\_WRITES. The lock is acquired to prevent any modifications on the metadata file while the snapshot is being taken.
-For more information on file system minifilter design, start with the [File System Minifilter Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff540402) section in the Installable File Systems Design Guide. \ No newline at end of file
+For more information on file system minifilter design, start with the [File System Minifilter Drivers](https://docs.microsoft.com/windows-hardware/drivers/ifs/file-system-minifilter-drivers) section in the Installable File Systems Design Guide.
diff --git a/filesys/miniFilter/NameChanger/README.md b/filesys/miniFilter/NameChanger/README.md
index 871373a2..440cf30d 100644
--- a/filesys/miniFilter/NameChanger/README.md
+++ b/filesys/miniFilter/NameChanger/README.md
@@ -5,84 +5,73 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: NameChanger File System Minifilter Driver
- platform: WDM
- language: cpp
- category: FileSystem
- description: Grafts a directory from one part of a volume's namespace to another part using a mapping.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617652
---->
-
# NameChanger File System Minifilter Driver
The *NameChanger* minifilter grafts a directory from one part of a volume's namespace to another part using a mapping. The minifilter maintains this illusion by acting as a name provider, injecting entries into directory enumerations and forwarding directory change notifications.
-Build the sample
-----------------
+## Build the sample
You can build the sample in two ways: using Microsoft Visual Studio or the command line (*MSBuild*).
-Building a Driver Using Visual Studio
--------------------------------------
+### Building a driver using Visual Studio
You build a driver the same way you build any project or solution in Visual Studio. When you create a new driver project using a Windows driver template, the template defines a default (active) project configuration and a default (active) solution build configuration. When you create a project from existing driver sources or convert existing driver code that was built with previous versions of the WDK, the conversion process preserves the target version information (operating systems and platform).
The default Solution build configuration is Debug and Win32.
-### To select a configuration and build a driver
+#### To select a configuration and build a driver
+
+1. Open the driver project or solution in Visual Studio (find *filtername*.sln or *filtername*.vcxproj).
+
+1. Right-click the solution in the **Solutions Explorer** and select **Configuration Manager**.
+
+1. From the **Configuration Manager**, select the **Active Solution Configuration** (for example, Debug or Release) and the **Active Solution Platform** (for example, Win32) that correspond to the type of build you are interested in.
-1. Open the driver project or solution in Visual Studio (find *filtername*.sln or *filtername*.vcxproj).
-2. Right-click the solution in the **Solutions Explorer** and select **Configuration Manager**.
-3. From the **Configuration Manager**, select the **Active Solution Configuration** (for example, Debug or Release) and the **Active Solution Platform** (for example, Win32) that correspond to the type of build you are interested in.
-4. From the Build menu, click **Build Solution** (Ctrl+Shift+B).
+1. From the Build menu, click **Build Solution** (Ctrl+Shift+B).
-Building a Driver Using the Command Line (MSBuild)
---------------------------------------------------
+### Building a driver from the command line (MSBuild)
You can build a driver from the command line using the Visual Studio Command Prompt window and the Microsoft Build Engine (MSBuild.exe) Previous versions of the WDK used the Windows Build utility (Build.exe) and provided separate build environment windows for each of the supported build configurations. You can now use the Visual Studio Command Prompt window for all build configurations.
-### To select a configuration and build a driver
+#### To select a configuration and build a driver from the command line
-1. Open a Visual Studio Command Prompt window at the **Start** screen. From this window you can use MsBuild.exe to build any Visual Studio project by specifying the project (.VcxProj) or solutions (.Sln) file.
-2. Navigate to the project directory and enter the **MSbuild** command for your target. For example, to perform a clean build of a Visual Studio driver project called *filtername*.vcxproj, navigate to the project directory and enter the following MSBuild command: **msbuild /t:clean /t:build .\\***filtername***.vcxproj**.
+1. Open a Visual Studio Command Prompt window at the **Start** screen. From this window you can use MsBuild.exe to build any Visual Studio project by specifying the project (.VcxProj) or solutions (.Sln) file.
-Run the sample
---------------
+1. Navigate to the project directory and enter the **MSbuild** command for your target. For example, to perform a clean build of a Visual Studio driver project called *filtername*.vcxproj, navigate to the project directory and enter the following MSBuild command: **msbuild /t:clean /t:build .\\***filtername***.vcxproj**.
-Installation
-------------
+## Installation
The minifilter samples come with an INF file that will install the minifilter. To install the minifilter, do the following:
-1. Make sure that *filtername*.sys and *filtername*.inf are in the same directory.
+1. Make sure that *filtername*.sys and *filtername*.inf are in the same directory.
- **Note** This installation will make the necessary registry updates to register the minifilter service and place *filtername*.sys in the %SystemRoot%\\system32\\drivers directory.
+ > [!NOTE]
+ > This installation will make the necessary registry updates to register the minifilter service and place *filtername*.sys in the %SystemRoot%\\system32\\drivers directory.
-2. In Windows Explorer, right-click *filtername*.inf, and click **Install**.
+1. In Windows Explorer, right-click *filtername*.inf, and click **Install**.
-3. To load the minifilter, run **fltmc load** *filtername* or **net start** *filtername*.
+1. To load the minifilter, run **fltmc load** *filtername* or **net start** *filtername*.
-Design and Operation
---------------------
+## Design and operation
The *NameChanger* minifilter illustrates how to make one part of a volume's namespace appear as though it belongs to part of another namespace. It accomplishes this by altering the names of files that reside beneath a particular path (called the "real mapping") to appear as though they actually reside beneath a different path (called the "user mapping"). The .inf file supplied with the sample defines the real and user mappings in the *[Strings]* section. The three strings used for the mappings are:
-String | Description
--------|-------------
-UserMapping | The location where files will appear to be in when the filter is attached
-UserMappingFinalComponentShort | The "short" (DOS-compliant 8.3-format) name for the final component of the UserMapping path.
-RealMapping | The actual location where the files reside.
+| String | Description |
+| --- | --- |
+| UserMapping | The location where files will appear to be in when the filter is attached. |
+| UserMappingFinalComponentShort | The "short" (DOS-compliant 8.3-format) name for the final component of the UserMapping path. |
+| RealMapping | The actual location where the files reside. |
Before attaching the minifilter to a volume, you must set up the user and real paths. By default the .inf defines the mapping paths like in the following manner:
-String | Mapping
--------|--------
-UserMapping | "\X\Y"
-UserMappingFinalComponentShort | "Y"
-RealMapping | "\A\B"
+| String | Mapping |
+| --- | --- |
+| UserMapping | "\X\Y" |
+| UserMappingFinalComponentShort | "Y" |
+| RealMapping | "\A\B" |
To successfully attach the filter to a volume you must first create a couple of directories. For example, to attach the *NameChanger* minifilter to the F: volume, first create the RealMapping directory (the F:\\A\\B directory). Next, create the parent of the UserMapping path (the F:\\X directory). The following directories are be created:
@@ -98,4 +87,4 @@ F:\\X\\Y
After the minifilter attaches, the "B" subdirectory of F:\\A is no longer visible. Its contents now appear under the "Y" subdirectory of F:\\X.
-For more information on file system minifilter design, start with the [File System Minifilter Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff540402) section in the Installable File Systems Design Guide. \ No newline at end of file
+For more information on file system minifilter design, see [File System Minifilter Drivers](https://docs.microsoft.com/windows-hardware/drivers/ifs/file-system-minifilter-drivers).
diff --git a/filesys/miniFilter/avscan/README.md b/filesys/miniFilter/avscan/README.md
index 66f549b6..baca08f9 100644
--- a/filesys/miniFilter/avscan/README.md
+++ b/filesys/miniFilter/avscan/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: AvScan File System Minifilter Driver
- platform: WDM
- language: cpp
- category: FileSystem
- description: This filter is a transaction-aware file scanner that examines data in files.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617644
---->
-
# AvScan File System Minifilter Driver
The AvScan minifilter is a transaction-aware file scanner. This is an example for developers who intend to write filters that examine data in files. Typically, anti-virus products fall into this category.
diff --git a/filesys/miniFilter/cancelSafe/README.md b/filesys/miniFilter/cancelSafe/README.md
index 2abe70f8..67a8ee19 100644
--- a/filesys/miniFilter/cancelSafe/README.md
+++ b/filesys/miniFilter/cancelSafe/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: CancelSafe File System Minifilter Driver
- platform: WDM
- language: cpp
- category: FileSystem
- description: A minifilter demonstrating the use of cancel-safe queues.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617645
---->
-
# CancelSafe File System Minifilter Driver
The CancelSafe filter is a sample minifilter that you use if you want to use cancel-safe queues.
@@ -24,9 +16,8 @@ The CancelSafe filter is a sample minifilter that you use if you want to use can
This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP.
-Design and Operation
---------------------
+## Design and Operation
The *CancelSafe* minifilter initializes a cancel-safe queue when it is attached to a volume. When the minifilter is deployed, it monitors read operations that are passing through the I/O stack. If the read operation is being performed on a file named csqdemo.txt, it is queued onto the cancel-safe queue. Queued operations are completed after a brief pause through a separate worker thread that is running in system context.
-For more information on file system minifilter design, start with the [File System Minifilter Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff540402) section in the Installable File Systems Design Guide.
+For more information on file system minifilter design, start with the [File System Minifilter Drivers](https://docs.microsoft.com/windows-hardware/drivers/ifs/file-system-minifilter-drivers) section in the Installable File Systems Design Guide.
diff --git a/filesys/miniFilter/cdo/README.md b/filesys/miniFilter/cdo/README.md
index 8d577a38..af1bd3f6 100644
--- a/filesys/miniFilter/cdo/README.md
+++ b/filesys/miniFilter/cdo/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: CDO File System Minifilter Driver
- platform: WDM
- language: cpp
- category: FileSystem
- description: An example of using a control device object (CDO) with a minifilter.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617646
---->
-
# CDO File System Minifilter Driver
The CDO minifilter sample is an example if you intend to use a control device object (CDO) with your minifilters.
@@ -26,9 +18,8 @@ Although the filter manager infrastructure provides a message interface for comm
This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP.
-Design and Operation
---------------------
+## Design and Operation
When the CDO minifilter is deployed, it creates a CDO object named "FileSystem\\Filters\\CdoSample" in the Microsoft Windows object namespace and enables applications to open it and perform certain operations on it.
-For more information on file system minifilter design, start with the [File System Minifilter Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff540402) section in the Installable File Systems Design Guide. \ No newline at end of file
+For more information on file system minifilter design, start with the [File System Minifilter Drivers](https://docs.microsoft.com/windows-hardware/drivers/ifs/file-system-minifilter-drivers) section in the Installable File Systems Design Guide.
diff --git a/filesys/miniFilter/change/README.md b/filesys/miniFilter/change/README.md
index 57fa10b4..f7e2be09 100644
--- a/filesys/miniFilter/change/README.md
+++ b/filesys/miniFilter/change/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Change File System Minifilter Driver
- platform: WDM
- language: cpp
- category: FileSystem
- description: A transaction-aware filter that monitors file changes in real time.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617647
---->
-
# Change File System Minifilter Driver
The Change minifilter is a transaction-aware filter that monitors file changes in real time.
@@ -31,4 +23,4 @@ The primary tasks of the filter for tracking a transacted file are the following
## Universal Windows Driver Compliant
-This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP. \ No newline at end of file
+This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP.
diff --git a/filesys/miniFilter/ctx/README.md b/filesys/miniFilter/ctx/README.md
index 4c73e6f2..c428b6ae 100644
--- a/filesys/miniFilter/ctx/README.md
+++ b/filesys/miniFilter/ctx/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Ctx File System Minifilter Driver
- platform: WDM
- language: cpp
- category: FileSystem
- description: Demonstrates how to attach contexts to instances, files, streams, and stream handles in your minifilter.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617648
---->
-
# Ctx File System Minifilter Drive
The Ctx minifilter is an example that demonstrates how to attach contexts to instances, files, streams, and stream handles in your minifilter.
@@ -28,4 +20,4 @@ This sample builds a Universal Windows Driver. It uses only APIs and DDIs that a
The *Ctx* minifilter demonstrates how to attach and remove contexts from instances, files, steams, and stream handles. *Ctx* attaches a context whenever one of these objects is created. While attaching a context to a file, the sample also creates a stream and stream handle context. All contexts are ultimately deleted by the filter manager using the callback function that the *Ctx* minifilter provides.
-For more information on file system minifilter design, start with the [File System Minifilter Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff540402) section in the Installable File Systems Design Guide. \ No newline at end of file
+For more information on file system minifilter design, start with the [File System Minifilter Drivers](https://docs.microsoft.com/windows-hardware/drivers/ifs/file-system-minifilter-drivers) section in the Installable File Systems Design Guide.
diff --git a/filesys/miniFilter/delete/README.md b/filesys/miniFilter/delete/README.md
index c0ddd06b..687a33af 100644
--- a/filesys/miniFilter/delete/README.md
+++ b/filesys/miniFilter/delete/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Delete File System Minifilter Driver
- platform: WDM
- language: cpp
- category: FileSystem
- description: Demonstrates how to detect deletions of files or streams.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617649
---->
-
# Delete File System Minifilter Driver
The Delete minifilter is an example that demonstrates how to detect deletions of files or streams. Deletions are reported as debug output.
@@ -28,6 +20,7 @@ This sample builds a Universal Windows Driver. It uses only APIs and DDIs that a
The *delete* minifilter illustrates how to detect deletion of files and streams. It monitors IRP\_MJ\_CREATE requests for the FILE\_DELETE\_ON\_CLOSE flag. Also, it detects IRP\_MJ\_SET\_INFORMATION requests for setting FileDispositionInformation/FileDispositionInformationEx. The sample also illustrates how to handle racing deletes (in the form of multiple parallel IRP\_MJ\_SET\_INFORMATION operations), and how to distinguish deletion of an entire file from deletion of just one stream of the file.
-**Note** Because of the way in which the Windows operating system deletes files, it is not possible for the minifilter to detect in advance that a file or stream will be deleted. The minifilter can only detect operations that may cause a deletion, and then determine if the deletion took place after the operation completes.
+> [!NOTE]
+> Because of the way in which the Windows operating system deletes files, it is not possible for the minifilter to detect in advance that a file or stream will be deleted. The minifilter can only detect operations that may cause a deletion, and then determine if the deletion took place after the operation completes.
-For more information on file system minifilter design, start with the [File System Minifilter Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff540402) section in the Installable File Systems Design Guide. \ No newline at end of file
+For more information on file system minifilter design, start with the [File System Minifilter Drivers](https://docs.microsoft.com/windows-hardware/drivers/ifs/file-system-minifilter-drivers) section in the Installable File Systems Design Guide.
diff --git a/filesys/miniFilter/minispy/README.md b/filesys/miniFilter/minispy/README.md
index a20e602d..6ff47310 100644
--- a/filesys/miniFilter/minispy/README.md
+++ b/filesys/miniFilter/minispy/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Minispy File System Minifilter Driver
- platform: WDM
- language: cpp
- category: FileSystem
- description: A tool to monitor and log any I/O and transaction activity that occurs in the system.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617651
---->
-
# Minispy File System Minifilter Driver
The Minispy sample is a tool to monitor and log any I/O and transaction activity that occurs in the system. Minispy is implemented as a minifilter.
@@ -30,4 +22,4 @@ Minispy consists of both user-mode and kernel-mode components. The kernel-mode c
To observe I/O activity on a device, you must explicitly attach Minispy to that device by using the Minispy user-mode component. Similarly, you can request Minispy to stop logging data for a particular device.
-For more information on file system minifilter design, start with the [File System Minifilter Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff540402) section in the Installable File Systems Design Guide. \ No newline at end of file
+For more information on file system minifilter design, start with the [File System Minifilter Drivers](https://docs.microsoft.com/windows-hardware/drivers/ifs/file-system-minifilter-drivers) section in the Installable File Systems Design Guide.
diff --git a/filesys/miniFilter/nullFilter/README.md b/filesys/miniFilter/nullFilter/README.md
index adb682c6..204588c1 100644
--- a/filesys/miniFilter/nullFilter/README.md
+++ b/filesys/miniFilter/nullFilter/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: NullFilter File System Minifilter Driver
- platform: WDM
- language: cpp
- category: FileSystem
- description: A minifilter that demonstrates registration with the filter manager.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617653
---->
-
# NullFilter File System Minifilter Driver
The NullFilter minifilter is a sample minifilter that shows how to register a minifilter with the filter manager.
@@ -28,4 +20,4 @@ This sample builds a Universal Windows Driver. It uses only APIs and DDIs that a
The *NullFilter* minifilter is a simple minifilter that registers itself with the filter manager for no callback operations.
-For more information on file system minifilter design, start with the [File System Minifilter Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff540402) section in the Installable File Systems Design Guide. \ No newline at end of file
+For more information on file system minifilter design, start with the [File System Minifilter Drivers](https://docs.microsoft.com/windows-hardware/drivers/ifs/file-system-minifilter-drivers) section in the Installable File Systems Design Guide.
diff --git a/filesys/miniFilter/passThrough/README.md b/filesys/miniFilter/passThrough/README.md
index edd98945..766c1cdf 100644
--- a/filesys/miniFilter/passThrough/README.md
+++ b/filesys/miniFilter/passThrough/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: PassThrough File System Minifilter Driver
- platform: WDM
- language: cpp
- category: FileSystem
- description: Demonstrates how to specify callback functions for different types of I/O requests.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617654
---->
-
# PassThrough File System Minifilter Driver
The PassThrough minifilter demonstrates how to specify callback functions for different types of I/O requests.
@@ -28,4 +20,4 @@ This sample builds a Universal Windows Driver. It uses only APIs and DDIs that a
The *PassThrough* minifilter does not have any real functionality. For each type of I/O operation, the same pre and post callback functions are called. These callback functions simply forward the I/O request to the next filter on the stack.
-For more information on file system minifilter design, start with the [File System Minifilter Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff540402) section in the Installable File Systems Design Guide. \ No newline at end of file
+For more information on file system minifilter design, start with the [File System Minifilter Drivers](https://docs.microsoft.com/windows-hardware/drivers/ifs/file-system-minifilter-drivers) section in the Installable File Systems Design Guide.
diff --git a/filesys/miniFilter/scanner/README.md b/filesys/miniFilter/scanner/README.md
index 3ad528ca..f4e8c8d6 100644
--- a/filesys/miniFilter/scanner/README.md
+++ b/filesys/miniFilter/scanner/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Scanner File System Minifilter Driver
- platform: WDM
- language: cpp
- category: FileSystem
- description: A file data scanner example. Typically, anti-virus filters are of this type.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617655
---->
-
# Scanner File System Minifilter Driver
The Scanner minifilter is an example for developers who intend to write filters that examine data in files. Typically, antivirus products fall into this category.
@@ -30,4 +22,4 @@ The Scanner minifilter comprises both kernel-mode and user-mode components. The
The kernel-mode component scans files with specific extensions only. The file is first scanned on a successful open. If the file was opened with write access, it is scanned again before a close. Scanning is also performed on data that is about to be written to a file. Writes will be rejected if any occurrences of a "foul" string are found in the data. If a "foul" string is detected during the closing of a file, a debug message is printed.
-For more information on file system minifilter design, start with the [File System Minifilter Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff540402) section in the Installable File Systems Design Guide. \ No newline at end of file
+For more information on file system minifilter design, start with the [File System Minifilter Drivers](https://docs.microsoft.com/windows-hardware/drivers/ifs/file-system-minifilter-drivers) section in the Installable File Systems Design Guide.
diff --git a/filesys/miniFilter/simrep/README.md b/filesys/miniFilter/simrep/README.md
index c2b48b0d..4f02ed2b 100644
--- a/filesys/miniFilter/simrep/README.md
+++ b/filesys/miniFilter/simrep/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: SimRep File System Minifilter Driver
- platform: WDM
- language: cpp
- category: FileSystem
- description: Demonstrates how a file system filter can simulate file-system like reparse-point behavior to redirect a file open to an alternate path.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617656
---->
-
# SimRep File System Minifilter Driver
SimRep is a sample filter that demonstrates how a file system filter can simulate file-system like reparse-point behavior to redirect a file open to an alternate path.
@@ -32,4 +24,4 @@ SimRep decides to reparse according to a mapping. The mapping is made up of a "N
It is important to note that SimRep does not take long and short names into account. It literally does a string comparison to detect overlap with the mapping paths. SimRep also handles IRP\_MJ\_NETWORK\_QUERY\_OPEN. Because network query opens are FastIo operations, they cannot be reparsed. This means network query opens which need to be redirected must be failed with FLT\_PREOP\_DISALLOW\_FASTIO. This will cause the Io Manager to reissue the open as a regular IRP based open. To prevent performance regression, SimRep only fails network query opens which need to be reparsed.
-For more information on file system minifilter design, start with the [File System Minifilter Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff540402) section in the Installable File Systems Design Guide.
+For more information on file system minifilter design, start with the [File System Minifilter Drivers](https://docs.microsoft.com/windows-hardware/drivers/ifs/file-system-minifilter-drivers) section in the Installable File Systems Design Guide.
diff --git a/filesys/miniFilter/swapBuffers/README.md b/filesys/miniFilter/swapBuffers/README.md
index 03114011..f427685f 100644
--- a/filesys/miniFilter/swapBuffers/README.md
+++ b/filesys/miniFilter/swapBuffers/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: SwapBuffer File System Minifilter Driver
- platform: WDM
- language: cpp
- category: FileSystem
- description: Demonstrates how to switch buffers between reads and writes of data. This technique is particularly useful for encryption filters.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617657
---->
-
# SwapBuffer File System Minifilter Driver
The SwapBuffers minifilter demonstrates how to switch buffers between reads and writes of data. This technique is particularly useful for encryption filters because they have to encrypt data before writing it to disk and decrypt it after reading it from disk. Because encryption/decryption has to be done transparently, you cannot use system-supplied buffers directly, so intermediate buffers have to be introduced.
@@ -28,4 +20,4 @@ This sample builds a Universal Windows Driver. It uses only APIs and DDIs that a
The *SwapBuffers* minifilter introduces a new buffer before a read/write or directory control operations. The corresponding operation is then performed on the new buffer instead of the buffer that was originally provided. After the operation completes, the contents of the new buffer are copied back in to the original buffer.
-For more information on file system minifilter design, start with the [File System Minifilter Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff540402) section in the Installable File Systems Design Guide.
+For more information on file system minifilter design, start with the [File System Minifilter Drivers](https://docs.microsoft.com/windows-hardware/drivers/ifs/file-system-minifilter-drivers) section in the Installable File Systems Design Guide.
diff --git a/general/DCHU/README.md b/general/DCHU/README.md
index 4f479c96..878d67a1 100644
--- a/general/DCHU/README.md
+++ b/general/DCHU/README.md
@@ -5,32 +5,25 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: DHCU - Driver package installation toolkit for universal drivers
- platform: UMDF2
- language: cpp
- category: General DHCU
- description: Illustrates DCHU principles of universal driver design.
- samplefwlink: https://aka.ms/sceeqq
---->
-
# Driver package installation toolkit for universal drivers
-This sample illustrates the DCHU principles of universal driver design. The sample uses the [OSR FX2 learning kit](http://store.osr.com/product/osr-usb-fx2-learning-kit-v2/). For a detailed code walkthrough, see [Universal Driver Scenarios](https://docs.microsoft.com/windows-hardware/drivers/develop/universal-driver-scenarios).
+This sample illustrates the DCHU principles of universal driver design. The sample uses the [OSR FX2 learning kit](https://osrfx2.sourceforge.net/). For a detailed code walkthrough, see [Universal Driver Scenarios](https://docs.microsoft.com/windows-hardware/drivers/develop/universal-driver-scenarios).
There are three Visual Studio solutions in this sample. Each one represents a single submission on the [Windows Hardware Dev Center dashboard](https://developer.microsoft.com/windows/hardware/dashboard-sign-in). The solutions are split into the following subdirectories:
-* `osrfx2_DCHU_base` : The driver for the OSR FX2 Learning Kit. This includes the device driver, an upper filter driver for the device (a no-op), a Win32 User Service that controls lights on the device, and a console app that can control the device.
+- `osrfx2_DCHU_base` : The driver for the OSR FX2 Learning Kit. This includes the device driver, an upper filter driver for the device (a no-op), a Win32 User Service that controls lights on the device, and a console app that can control the device.
-* `osrfx2_DCHU_extension_loose`: An extension INF for the OSR FX2 device. This extension modifies some registry settings originally specified by the base driver (`osrfx2_DCHU_base`) and also uses AddComponent to create a Software Component. There is also a component INF project that would be a separate submission to DevCenter, which runs some simple software. These two projects are loosely coupled, and can be installed in any order on the machine.
+- `osrfx2_DCHU_extension_loose`: An extension INF for the OSR FX2 device. This extension modifies some registry settings originally specified by the base driver (`osrfx2_DCHU_base`) and also uses AddComponent to create a Software Component. There is also a component INF project that would be a separate submission to DevCenter, which runs some simple software. These two projects are loosely coupled, and can be installed in any order on the machine.
-* `osrfx2_DCHU_extension_tight`: An extension INF for the OSR FX2 device. This extension mimics the behavior of `osrfx2_DCHU_extension_loose`; however, it does so in a tightly coupled manner. Using CopyINF, both the extension and component INF are placed into one driver package (and one submission to DevCenter). Here there is less flexibility with the base/component/extension relationship, but it ensures that the component INF is applied at the same time as the extension.
+- `osrfx2_DCHU_extension_tight`: An extension INF for the OSR FX2 device. This extension mimics the behavior of `osrfx2_DCHU_extension_loose`; however, it does so in a tightly coupled manner. Using CopyINF, both the extension and component INF are placed into one driver package (and one submission to DevCenter). Here there is less flexibility with the base/component/extension relationship, but it ensures that the component INF is applied at the same time as the extension.
-Both `osrfx2_DCHU_extension_loose` and `osrfx2_DCHU_extension_tight` provide the same functionality, so installing both on the same OSR FX2 device is unnecessary. They are intended to show a different way to use extension and component INF's depending on a project's needs.
+Both `osrfx2_DCHU_extension_loose` and `osrfx2_DCHU_extension_tight` provide the same functionality, so installing both on the same OSR FX2 device is unnecessary. They are intended to show a different way to use extension and component INFs depending on a project's needs.
-NOTE: osrfx2_DCHU_extension_tight will not currently build on Windows 10 version 1703. You will see an error saying that the directive CopyINF does not work from extension INFs. This has been fixed for the Windows 10 Fall Creators Update.
+> [!NOTE]
+> osrfx2_DCHU_extension_tight will not currently build on Windows 10 version 1703. You will see an error saying that the directive CopyINF does not work from extension INFs. This has been fixed for the Windows 10 Fall Creators Update.
Each of these solutions can be built with the latest WDK on Visual Studio 2015. Additionally, you can also download a [Universal Windows Platform app (UWP)](https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/CustomCapability) that controls the OSR FX2 Learning Kit's device. To learn how to pair a UWP app with a device, see [Hardware access for Universal Windows Platform apps](https://docs.microsoft.com/windows-hardware/drivers/devapps/hardware-access-for-universal-windows-platform-apps)
@@ -38,11 +31,12 @@ The app and the contents of this sample can coexist, but on Windows 10 version 1
To install these driver packages, make sure that the target machine is in Test Mode, using `bcdedit /set testsigning on`.
-Then, use `pnputil /i /a <PATHTOINF>` to install each of the desired driver packages. They should
-be installed in the following order:
+Then, use `pnputil /i /a <PATHTOINF>` to install each of the desired driver packages. They should be installed in the following order:
+
+- `osrfx2_DCHU_base`
+
+- `osrfx2_DCHU_extension`
-* `osrfx2_DCHU_base`
-* `osrfx2_DCHU_extension`
-* `osrfx2_DCHU_component`
+- `osrfx2_DCHU_component`
-Technically the order of `osrfx2_DCHU_extension` and `osrfx2_DCHU_component` doesn't matter, but the software within `osrfx2_DCHU_component` will read the registry set by the extension to show that an extension INF's settings are applied *after* the base INF's.
+Technically the order of `osrfx2_DCHU_extension` and `osrfx2_DCHU_component` doesn't matter, but the software within `osrfx2_DCHU_component` will read the registry set by the extension to show that an extension's INF settings are applied *after* the base INFs.
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/driver.c b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/driver.c
index 2be5d2ed..9f28204f 100644
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/driver.c
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/driver.c
@@ -120,7 +120,7 @@ DriverEntry(
EventRegisterOSRUSBFX2();
//
- // Initiialize driver config to control the attributes that
+ // Initialize driver config to control the attributes that
// are global to the driver. Note that framework by default
// provides a driver unload routine. If you create any resources
// in the DriverEntry and want to be cleaned in driver unload,
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inx b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inx
index 8271e39d..73b6d10e 100644
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inx
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inx
Binary files differ
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj
index 57439bd9..f78f16b4 100644
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj
@@ -26,7 +26,7 @@
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
<SampleGuid>{F915ED95-7BE9-4CDB-B09A-0D3F4C9657FE}</SampleGuid>
<ProjectName>osrfx2_DCHU_base</ProjectName>
- <WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
+ <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj
index 36d85583..09724ba5 100644
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj
@@ -27,7 +27,7 @@
<Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
<SampleGuid>{1A4A32BA-1596-4F52-BC48-B85A6D8D5D12}</SampleGuid>
- <WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
+ <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
<ProjectName>osrfx2_DCHU_filter</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj
index 225dcde2..bc56feac 100644
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj
@@ -25,7 +25,7 @@
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
<SampleGuid>{F19E45AF-8B05-4204-A66B-9BDBFE333233}</SampleGuid>
<ProjectName>osrfx2_DCHU_testapp</ProjectName>
- <WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
+ <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/CppWindowsService.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/CppWindowsService.cpp
deleted file mode 100644
index 98a3975c..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/CppWindowsService.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation. All rights reserved.
-
- THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
- PURPOSE.
-
-Module Name:
-
- CppWindowsService.cpp
-
-Abstract:
-
- The file defines the entry point of the application. According to the
- arguments in the command line, the function installs or uninstalls or
- starts the service by calling into different routines.
-
-Environment:
-
- User mode
-
---*/
-
-#pragma region Includes
-#include <stdio.h>
-#include <windows.h>
-#include "ServiceBase.h"
-#include "SampleService.h"
-#pragma endregion
-
-//
-// Settings of the service
-//
-
-//
-// Internal name of the service
-//
-#define SERVICE_NAME L"OsrUsbFx2UmUserSvc"
-
-
-/*++
-
-Routine Description:
-
- Entry point for the service.
-
-Arguments:
-
- Argc - The number of command line arguments
-
- Argv - The array of command line arguments
-
-Return Value:
-
- VOID
-
---*/
-INT
-wmain(
- INT Argc,
- WCHAR *Argv[]
- )
-{
- CSampleService service(SERVICE_NAME);
-
- if (!CServiceBase::Run(service))
- {
- wprintf(L"Service failed to run w/err 0x%08lx\n", GetLastError());
- }
-
- return 0;
-} \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.cpp
new file mode 100644
index 00000000..318e0dd5
--- /dev/null
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.cpp
@@ -0,0 +1,856 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ DeviceContext.cpp
+
+Abstract:
+
+ Implements the functions to create/destroy device context by
+ registering/unregistering for device notifications.
+
+Environment:
+
+ User mode
+
+--*/
+
+#include "stdafx.h"
+
+extern HANDLE SvcStopRequestEvent;
+extern HCMNOTIFICATION InterfaceNotificationHandle;
+extern DEVICE_LIST_ENTRY DeviceList;
+extern SRWLOCK DeviceListLock;
+
+//
+// Keep track of running theads for unregistering device notifications
+//
+DWORD RunningUnregistrations = 0;
+SRWLOCK RunningUnregistrationsLock = SRWLOCK_INIT;
+CONDITION_VARIABLE UnregistrationComplete = CONDITION_VARIABLE_INIT;
+
+/*++
+
+Routine Description:
+
+ Setup device interface context by registering for device interface
+ notifications
+
+Arguments:
+
+ NULL
+
+Return Value:
+
+ A Win32 error code.
+
+--*/
+DWORD
+SetupDeviceInterfaceContext(
+ VOID
+ )
+{
+ DWORD Err = ERROR_SUCCESS;
+ CONFIGRET Cr = CR_SUCCESS;
+ PCWSTR DeviceInterface = NULL;
+ PWSTR DeviceInterfaceList = NULL;
+ DWORD DeviceInterfaceListSize = 0;
+
+ //
+ // Register for device interface events to open and close the handle to
+ // the interface.
+ //
+ Err = RegisterInterfaceNotifications(&InterfaceNotificationHandle);
+
+ if (Err != ERROR_SUCCESS)
+ {
+ goto cleanup;
+ }
+
+ //
+ // The interface may already be present on the system. Retrieve a list of
+ // existing interfaces
+ //
+ do
+ {
+ Cr = CM_Get_Device_Interface_List_Size(&DeviceInterfaceListSize,
+ (LPGUID)&GUID_DEVINTERFACE_OSRUSBFX2,
+ NULL,
+ CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
+
+ if (Cr != CR_SUCCESS)
+ {
+ break;
+ }
+
+ if (DeviceInterfaceList != NULL)
+ {
+ free(DeviceInterfaceList);
+ }
+
+ DeviceInterfaceList = (PWSTR)malloc(DeviceInterfaceListSize * sizeof(WCHAR));
+
+ if (DeviceInterfaceList == NULL)
+ {
+ Cr = CR_OUT_OF_MEMORY;
+ break;
+ }
+
+ Cr = CM_Get_Device_Interface_List((LPGUID)&GUID_DEVINTERFACE_OSRUSBFX2,
+ NULL,
+ DeviceInterfaceList,
+ DeviceInterfaceListSize,
+ CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
+ } while (Cr == CR_BUFFER_SMALL);
+
+ if (Cr != CR_SUCCESS)
+ {
+ Err = CM_MapCrToWin32Err(Cr, ERROR_INVALID_DATA);
+ goto cleanup;
+ }
+
+ //
+ // Register for notifications on existing device interfaces
+ //
+ for (DeviceInterface = DeviceInterfaceList;
+ *DeviceInterface != L'\0';
+ DeviceInterface += wcslen(DeviceInterface) + 1)
+ {
+ RegisterDeviceNotifications(DeviceInterface);
+ }
+
+cleanup:
+
+ if (DeviceInterfaceList != NULL)
+ {
+ free(DeviceInterfaceList);
+ }
+
+ return Err;
+}
+
+
+/*++
+
+Routine Description:
+
+ Clean up device interface context
+
+Arguments:
+
+ NULL
+
+Return Value:
+
+ NULL
+
+--*/
+VOID
+CleanupDeviceInterfaceContext(
+ VOID
+ )
+{
+ PDEVICE_CONTEXT Context = NULL;
+ BOOL NeedsUnregister = FALSE;
+
+ //
+ // Unregister from the interface first, so that re-appearance of the
+ // interface does not cause us to register device events again.
+ //
+ if (InterfaceNotificationHandle != NULL)
+ {
+ CM_Unregister_Notification(InterfaceNotificationHandle);
+ InterfaceNotificationHandle = NULL;
+ }
+
+ //
+ // Unregister notifications for device handles.
+ //
+ while (TRUE)
+ {
+ NeedsUnregister = FALSE;
+
+ AcquireSRWLockShared(&DeviceListLock);
+
+ if (IsDeviceListEmpty(&DeviceList))
+ {
+ ReleaseSRWLockShared(&DeviceListLock);
+ break;
+ }
+
+ //
+ // Get next device context
+ //
+ Context = CONTAINING_DEVICE_RECORD(DeviceList.Flink);
+
+ //
+ // The device context can be unregistered either within notification
+ // callbacks or cleanup routines. Synchronize these operations to only
+ // unregister once.
+ //
+ EnterCriticalSection(&Context->ContextLock);
+
+ if (!Context->Unregistered)
+ {
+ Context->Unregistered = TRUE;
+ NeedsUnregister = TRUE;
+ }
+
+ LeaveCriticalSection(&Context->ContextLock);
+
+ ReleaseSRWLockShared(&DeviceListLock);
+
+ if (NeedsUnregister)
+ {
+ //
+ // Remove next device from device list
+ //
+ AcquireSRWLockExclusive(&DeviceListLock);
+ RemoveDeviceListEntry(DeviceList.Flink);
+ ReleaseSRWLockExclusive(&DeviceListLock);
+
+ UnregisterDeviceNotifications(Context);
+ }
+ }
+
+ //
+ // Wait for all other unregistrations for device handle that is not in
+ // device list.
+ //
+ AcquireSRWLockShared(&RunningUnregistrationsLock);
+
+ while (RunningUnregistrations != 0)
+ {
+ SleepConditionVariableSRW(&UnregistrationComplete,
+ &RunningUnregistrationsLock,
+ INFINITE,
+ CONDITION_VARIABLE_LOCKMODE_SHARED);
+ }
+
+ ReleaseSRWLockShared(&RunningUnregistrationsLock);
+}
+
+
+/*++
+
+Routine Description:
+
+ Handles a device query remove notification.
+
+Arguments:
+
+ Context - The callback context
+
+Return Value:
+
+ NULL
+
+--*/
+VOID
+DeviceQueryRemoveAction(
+ _In_ PDEVICE_CONTEXT Context
+ )
+{
+ if (Context->DeviceHandle != INVALID_HANDLE_VALUE)
+ {
+ //
+ // Close open handles to allow the device to be query removed
+ //
+ CloseHandle(Context->DeviceHandle);
+
+ Context->DeviceHandle = INVALID_HANDLE_VALUE;
+ }
+}
+
+
+/*++
+
+Routine Description:
+
+ Handles a device query remove failed notification.
+
+Arguments:
+
+ Context - The callback context
+
+Return Value:
+
+ NULL
+
+--*/
+VOID
+DeviceQueryRemoveFailedAction(
+ _In_ PDEVICE_CONTEXT Context
+ )
+{
+ PWSTR DeviceInterfacePath = NULL;
+ BOOL NeedsUnregister = FALSE;
+
+ //
+ // Keep a record of device symbolic link since the callback context will
+ // be freed up during unregistration
+ //
+ DeviceInterfacePath = Context->SymbolicLink;
+ Context->SymbolicLink = NULL;
+
+ //
+ // The device context can be unregistered either within notification
+ // callbacks or cleanup routines. Synchronize these operations to only
+ // unregister once.
+ //
+ EnterCriticalSection(&Context->ContextLock);
+
+ if (!Context->Unregistered)
+ {
+ Context->Unregistered = TRUE;
+ NeedsUnregister = TRUE;
+ }
+
+ LeaveCriticalSection(&Context->ContextLock);
+
+ //
+ // Remove device from device list if needed
+ //
+ if (NeedsUnregister)
+ {
+ AcquireSRWLockExclusive(&DeviceListLock);
+ RemoveDeviceListEntry(&Context->ListEntry);
+ ReleaseSRWLockExclusive(&DeviceListLock);
+
+ //
+ // Unregister notifications for the old device handle from a deferred
+ // routine since CM_Unregister_Notification can not be called from a
+ // notification callback
+ //
+ AcquireSRWLockExclusive(&RunningUnregistrationsLock);
+ RunningUnregistrations++;
+ ReleaseSRWLockExclusive(&RunningUnregistrationsLock);
+
+ QueueUserWorkItem(UnregisterDeviceNotificationsWorkerThread,
+ Context,
+ WT_EXECUTEDEFAULT);
+ }
+
+ //
+ // Re-register for device notifications on a new device handle
+ //
+ RegisterDeviceNotifications(DeviceInterfacePath);
+
+ //
+ // Free memory that the callback context used to point at but was not freed
+ // during unregistration
+ //
+ free(DeviceInterfacePath);
+}
+
+/*++
+
+Routine Description:
+
+ Handles a device remove complete notification.
+
+Arguments:
+
+ Context - The callback context
+
+Return Value:
+
+ NULL
+
+--*/
+VOID
+DeviceRemoveCompleteAction(
+ _In_ PDEVICE_CONTEXT Context
+ )
+{
+ BOOL NeedsUnregister = FALSE;
+
+ //
+ // The device context can be unregistered either within notification
+ // callbacks or cleanup routines. Synchronize these operations to only
+ // unregister once.
+ //
+ EnterCriticalSection(&Context->ContextLock);
+
+ if (!Context->Unregistered)
+ {
+ Context->Unregistered = TRUE;
+ NeedsUnregister = TRUE;
+ }
+
+ LeaveCriticalSection(&Context->ContextLock);
+
+ //
+ // Remove device from device list if needed
+ //
+ if (NeedsUnregister)
+ {
+ AcquireSRWLockExclusive(&DeviceListLock);
+ RemoveDeviceListEntry(&Context->ListEntry);
+ ReleaseSRWLockExclusive(&DeviceListLock);
+
+ //
+ // Unregister notifications for the old device handle from a deferred
+ // routine since CM_Unregister_Notification can not be called from a
+ // notification callback
+ //
+ AcquireSRWLockExclusive(&RunningUnregistrationsLock);
+ RunningUnregistrations++;
+ ReleaseSRWLockExclusive(&RunningUnregistrationsLock);
+
+ QueueUserWorkItem(UnregisterDeviceNotificationsWorkerThread,
+ Context,
+ WT_EXECUTEDEFAULT);
+ }
+}
+
+/*++
+
+Routine Description:
+
+ Handles device notifications.
+
+Arguments:
+
+ hNotify - The notification that spurred this callback
+
+ hContext - The callback context
+
+ Action - The type of callback
+
+ EventData - Additional information about this callback
+
+ EventDataSize - The size of EventData
+
+Return Value:
+
+ A Win32 error code.
+
+--*/
+DWORD
+WINAPI
+DeviceCallback(
+ _In_ HCMNOTIFICATION hNotify,
+ _In_ PVOID hContext,
+ _In_ CM_NOTIFY_ACTION Action,
+ _In_ PCM_NOTIFY_EVENT_DATA EventData,
+ _In_ DWORD EventDataSize
+ )
+{
+ PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)hContext;
+
+ UNREFERENCED_PARAMETER(EventData);
+ UNREFERENCED_PARAMETER(EventDataSize);
+
+ //
+ // In case this callback fires before the registration call returns, make
+ // sure the notification handle is properly set
+ //
+ Context->DeviceNotificationHandle = hNotify;
+
+ switch (Action)
+ {
+ case CM_NOTIFY_ACTION_DEVICEQUERYREMOVE:
+ DeviceQueryRemoveAction(Context);
+ break;
+
+ case CM_NOTIFY_ACTION_DEVICEQUERYREMOVEFAILED:
+ DeviceQueryRemoveFailedAction(Context);
+ break;
+
+ case CM_NOTIFY_ACTION_DEVICEREMOVEPENDING:
+ case CM_NOTIFY_ACTION_DEVICEREMOVECOMPLETE:
+ DeviceRemoveCompleteAction(Context);
+ break;
+
+ default:
+ break;
+ }
+
+ return ERROR_SUCCESS;
+}
+
+
+/*++
+
+Routine Description:
+
+ Register for device notifications.
+
+Arguments:
+
+ DeviceInterfacePath - The symbolic link path of the device interface
+
+Return Value:
+
+ A Win32 error code.
+
+--*/
+DWORD
+RegisterDeviceNotifications(
+ _In_ PCWSTR DeviceInterfacePath
+ )
+{
+ DWORD Err = ERROR_SUCCESS;
+ CONFIGRET Cr = CR_SUCCESS;
+ PDEVICE_CONTEXT Context = NULL;
+ PDEVICE_LIST_ENTRY Link = NULL;
+ DWORD BufferSize = 0;
+ CM_NOTIFY_FILTER NotifyFilter = {0};
+
+ //
+ // Check whether the device interface has already been registered for device
+ // handle notifications since it can be done either in interface arrival
+ // callback routine or initial device interface setup routine
+ //
+ AcquireSRWLockExclusive(&DeviceListLock);
+
+ for (Link = DeviceList.Flink; Link != &DeviceList; Link = Link->Flink)
+ {
+ Context = CONTAINING_DEVICE_RECORD(Link);
+
+ if (_wcsicmp(DeviceInterfacePath, Context->SymbolicLink) == 0)
+ {
+ break;
+ }
+ }
+
+ if (Link != &DeviceList)
+ {
+ Err = ERROR_SUCCESS;
+ goto cleanup;
+ }
+
+ //
+ // Create a new device context
+ //
+ Context = (PDEVICE_CONTEXT)malloc(sizeof(DEVICE_CONTEXT));
+
+ if (Context == NULL)
+ {
+ Err = ERROR_OUTOFMEMORY;
+ goto cleanup;
+ }
+
+ //
+ // Initialize device context
+ //
+ ZeroMemory(Context, sizeof(DEVICE_CONTEXT));
+ Context->DeviceHandle = INVALID_HANDLE_VALUE;
+ InitializeCriticalSection(&Context->ContextLock);
+
+ //
+ // Fill out the context and register device handle notifications
+ //
+ BufferSize = (DWORD)wcslen(DeviceInterfacePath) + 1;
+ Context->SymbolicLink = (PWSTR)malloc(BufferSize * sizeof(WCHAR));
+
+ if ((Context->SymbolicLink == NULL) ||
+ (FAILED(StringCchCopy(Context->SymbolicLink,
+ BufferSize,
+ DeviceInterfacePath))))
+ {
+ Err = ERROR_OUTOFMEMORY;
+ goto cleanup;
+ }
+
+ Context->DeviceHandle = CreateFile(Context->SymbolicLink,
+ GENERIC_WRITE | GENERIC_READ,
+ FILE_SHARE_WRITE | FILE_SHARE_READ,
+ NULL, // default security
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
+ NULL);
+
+ if (Context->DeviceHandle == INVALID_HANDLE_VALUE)
+ {
+ Err = GetLastError();
+ goto cleanup;
+ }
+
+ NotifyFilter.cbSize = sizeof(NotifyFilter);
+ NotifyFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE;
+ NotifyFilter.u.DeviceHandle.hTarget = Context->DeviceHandle;
+
+ Cr = CM_Register_Notification(&NotifyFilter,
+ (PVOID)Context,
+ (PCM_NOTIFY_CALLBACK)DeviceCallback,
+ &Context->DeviceNotificationHandle);
+
+ if (Cr != CR_SUCCESS)
+ {
+ Err = CM_MapCrToWin32Err(Cr, ERROR_INVALID_DATA);
+ goto cleanup;
+ }
+
+ //
+ // Add the device entry to device list
+ //
+ InsertTailDeviceListEntry(&DeviceList, &Context->ListEntry);
+ Context = NULL;
+
+cleanup:
+
+ ReleaseSRWLockExclusive(&DeviceListLock);
+
+ //
+ // Clean up device context if an error occurred.
+ //
+ if (Context != NULL)
+ {
+ if (Context->SymbolicLink != NULL)
+ {
+ free(Context->SymbolicLink);
+ }
+
+ if (Context->DeviceHandle != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(Context->DeviceHandle);
+ }
+
+ free(Context);
+ }
+
+ return Err;
+}
+
+
+VOID
+UnregisterDeviceNotifications(
+ _Inout_ PDEVICE_CONTEXT Context
+ )
+{
+ if (Context->DeviceNotificationHandle != NULL)
+ {
+ CM_Unregister_Notification(Context->DeviceNotificationHandle);
+ }
+
+ if (Context->DeviceHandle != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(Context->DeviceHandle);
+ }
+
+ if (Context->SymbolicLink != NULL)
+ {
+ free(Context->SymbolicLink);
+ }
+
+ DeleteCriticalSection(&Context->ContextLock);
+
+ free(Context);
+}
+
+
+/*++
+
+Routine Description:
+
+ This worker thread avoids a deadlock when unregistering device notifications.
+ Rather than calling CM_Unregister_Notification from the callback, the
+ callback gives that work to a separate thread to avoid deadlock.
+
+Arguments:
+
+ lpThreadParameter - The thread data passed to the function
+
+Return Value:
+
+ Zero
+
+--*/
+DWORD
+WINAPI
+UnregisterDeviceNotificationsWorkerThread(
+ _In_ PVOID lpThreadParameter
+ )
+{
+ PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)lpThreadParameter;
+
+ UnregisterDeviceNotifications(Context);
+
+ //
+ // Decrease running unregistrations
+ //
+ AcquireSRWLockExclusive(&RunningUnregistrationsLock);
+ RunningUnregistrations--;
+ ReleaseSRWLockExclusive(&RunningUnregistrationsLock);
+
+ WakeAllConditionVariable(&UnregistrationComplete);
+
+ return 0;
+}
+
+
+/*++
+
+Routine Description:
+
+ Handles an interface arrival notification.
+
+Arguments:
+
+ hNotify - The notification that fired the callback
+
+ hContext - The callback context
+
+ Action - The type of notification
+
+ EventData - Additional information about the callback
+
+ EventDataSize - The size of EventData
+
+Return Value:
+
+ Notification callback should return ERROR_SUCCESS.
+
+--*/
+DWORD
+WINAPI
+InterfaceCallback(
+ _In_ HCMNOTIFICATION hNotify,
+ _In_ PVOID hContext,
+ _In_ CM_NOTIFY_ACTION Action,
+ _In_ PCM_NOTIFY_EVENT_DATA EventData,
+ _In_ DWORD EventDataSize
+ )
+{
+ PDEVICE_CONTEXT Context = NULL;
+ PDEVICE_LIST_ENTRY Link = NULL;
+ BOOL NeedsUnregister = FALSE;
+
+ UNREFERENCED_PARAMETER(hNotify);
+ UNREFERENCED_PARAMETER(hContext);
+ UNREFERENCED_PARAMETER(EventDataSize);
+
+ switch (Action)
+ {
+ case CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL:
+ //
+ // Register for device notifications
+ //
+ RegisterDeviceNotifications(EventData->u.DeviceInterface.SymbolicLink);
+ break;
+
+ case CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL:
+ //
+ // The device may still be running in the case where the driver disables
+ // its interfaces. Find whether it is still on the device list and clean
+ // it up.
+ //
+ AcquireSRWLockShared(&DeviceListLock);
+
+ for (Link = DeviceList.Flink; Link != &DeviceList; Link = Link->Flink)
+ {
+ Context = CONTAINING_DEVICE_RECORD(Link);
+
+ if (_wcsicmp(EventData->u.DeviceInterface.SymbolicLink,
+ Context->SymbolicLink) == 0)
+ {
+ //
+ // The device context can be unregistered either within
+ // notification callbacks or cleanup routines. Synchronize these
+ // operations to only unregister once.
+ //
+ EnterCriticalSection(&Context->ContextLock);
+
+ if (!Context->Unregistered)
+ {
+ Context->Unregistered = TRUE;
+ NeedsUnregister = TRUE;
+ }
+
+ LeaveCriticalSection(&Context->ContextLock);
+
+ break;
+ }
+ }
+
+ ReleaseSRWLockShared(&DeviceListLock);
+
+ if (NeedsUnregister)
+ {
+ //
+ // Remove the device from device list
+ //
+ AcquireSRWLockExclusive(&DeviceListLock);
+ RemoveDeviceListEntry(&Context->ListEntry);
+ ReleaseSRWLockExclusive(&DeviceListLock);
+
+ UnregisterDeviceNotifications(Context);
+ }
+
+ //
+ // Notify service to stop if this is the last device interface
+ //
+ AcquireSRWLockShared(&DeviceListLock);
+
+ if (IsDeviceListEmpty(&DeviceList))
+ {
+ SetEvent(SvcStopRequestEvent);
+ }
+
+ ReleaseSRWLockShared(&DeviceListLock);
+ break;
+
+ default:
+ break;
+ }
+
+ return ERROR_SUCCESS;
+}
+
+
+/*++
+
+Routine Description:
+
+ Registers the service for interface notifications
+
+Arguments:
+
+ pInterfaceNotificationHandle - Pointer to receive the HCMNOTIFICATION handle
+
+Return Value:
+
+ A Win32 error code.
+
+--*/
+DWORD
+RegisterInterfaceNotifications(
+ _Out_ PHCMNOTIFICATION pInterfaceNotificationHandle
+ )
+{
+ DWORD Err = ERROR_SUCCESS;
+ CONFIGRET Cr = CR_SUCCESS;
+ CM_NOTIFY_FILTER NotifyFilter = {0};
+
+ NotifyFilter.cbSize = sizeof(NotifyFilter);
+ NotifyFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE;
+ NotifyFilter.u.DeviceInterface.ClassGuid = GUID_DEVINTERFACE_OSRUSBFX2;
+
+ //
+ // Register for device interface events to open and close the handle to
+ // the interface.
+ //
+ Cr = CM_Register_Notification(&NotifyFilter,
+ NULL,
+ (PCM_NOTIFY_CALLBACK)InterfaceCallback,
+ pInterfaceNotificationHandle);
+
+ if (Cr != CR_SUCCESS)
+ {
+ Err = CM_MapCrToWin32Err(Cr, ERROR_INVALID_DATA);
+ goto cleanup;
+ }
+
+cleanup:
+
+ return Err;
+}
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.h
new file mode 100644
index 00000000..4d744989
--- /dev/null
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.h
@@ -0,0 +1,155 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+--*/
+
+#pragma once
+
+//
+// Device list
+//
+typedef struct _DEVICE_LIST_ENTRY {
+ struct _DEVICE_LIST_ENTRY *Flink;
+ struct _DEVICE_LIST_ENTRY *Blink;
+} DEVICE_LIST_ENTRY, *PDEVICE_LIST_ENTRY;
+
+FORCEINLINE
+VOID
+InitializeDeviceListHead(
+ _Out_ PDEVICE_LIST_ENTRY Head
+ )
+{
+ Head->Blink = Head->Flink = Head;
+}
+
+FORCEINLINE
+BOOL
+IsDeviceListEmpty(
+ _In_ const PDEVICE_LIST_ENTRY ListHead
+ )
+
+{
+ return (ListHead->Flink == ListHead);
+}
+
+FORCEINLINE
+VOID
+RemoveDeviceListEntry(
+ _In_ PDEVICE_LIST_ENTRY Entry
+ )
+{
+ PDEVICE_LIST_ENTRY Prev = Entry->Blink;
+ PDEVICE_LIST_ENTRY Next = Entry->Flink;
+
+ Prev->Flink = Next;
+ Next->Blink = Prev;
+}
+
+FORCEINLINE
+VOID
+InsertTailDeviceListEntry(
+ _Inout_ PDEVICE_LIST_ENTRY Head,
+ _Inout_ PDEVICE_LIST_ENTRY Entry
+ )
+{
+ PDEVICE_LIST_ENTRY Tail = Head->Blink;
+
+ Tail->Flink = Entry;
+ Entry->Blink = Tail;
+ Entry->Flink = Head;
+ Head->Blink = Entry;
+}
+
+//
+// Context for device handle
+//
+typedef struct _DEVICE_CONTEXT {
+ PWSTR SymbolicLink;
+ HANDLE DeviceHandle;
+ HCMNOTIFICATION DeviceNotificationHandle;
+ BOOL Unregistered;
+ CRITICAL_SECTION ContextLock;
+ DEVICE_LIST_ENTRY ListEntry;
+} DEVICE_CONTEXT, *PDEVICE_CONTEXT;
+
+#define CONTAINING_DEVICE_RECORD(address) ((PDEVICE_CONTEXT)( \
+ (PCHAR)(address) - \
+ (ULONG_PTR)(&((PDEVICE_CONTEXT)0)->ListEntry)))
+
+//
+// Device interface context
+//
+DWORD
+SetupDeviceInterfaceContext(
+ VOID
+ );
+
+VOID
+CleanupDeviceInterfaceContext(
+ VOID
+ );
+
+//
+// Device notifications related
+//
+VOID
+DeviceQueryRemoveAction(
+ _In_ PDEVICE_CONTEXT Context
+ );
+
+VOID
+DeviceQueryRemoveFailedAction(
+ _In_ PDEVICE_CONTEXT Context
+ );
+
+VOID
+DeviceRemoveCompleteAction(
+ _In_ PDEVICE_CONTEXT Context
+ );
+
+DWORD
+WINAPI
+DeviceCallback(
+ _In_ HCMNOTIFICATION hNotify,
+ _In_ PVOID hContext,
+ _In_ CM_NOTIFY_ACTION Action,
+ _In_ PCM_NOTIFY_EVENT_DATA EventData,
+ _In_ DWORD EventDataSize
+ );
+
+DWORD
+RegisterDeviceNotifications(
+ _In_ PCWSTR DeviceInterfacePath
+ );
+
+VOID
+UnregisterDeviceNotifications(
+ _Inout_ PDEVICE_CONTEXT Context
+ );
+
+DWORD
+WINAPI
+InterfaceCallback(
+ _In_ HCMNOTIFICATION hNotify,
+ _In_ PVOID hContext,
+ _In_ CM_NOTIFY_ACTION Action,
+ _In_ PCM_NOTIFY_EVENT_DATA EventData,
+ _In_ DWORD EventDataSize
+ );
+
+DWORD
+RegisterInterfaceNotifications(
+ _Out_ PHCMNOTIFICATION pInterfaceNotificationHandle
+ );
+
+DWORD
+WINAPI
+UnregisterDeviceNotificationsWorkerThread(
+ _In_ PVOID lpThreadParameter
+ );
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.cpp
new file mode 100644
index 00000000..ced895cc
--- /dev/null
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.cpp
@@ -0,0 +1,192 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ DeviceControl.cpp
+
+Abstract:
+
+ Implements the functions to control the OSR USB FX2 device.
+
+Environment:
+
+ User mode
+
+--*/
+
+#include "stdafx.h"
+
+//
+// Keep track of where the OSRFX2 device's bar graph currently is.
+//
+INT CurrentBar;
+BAR_GRAPH_STATE BarGraphState;
+
+/*++
+
+Routine Description:
+
+ Initialize global variables for OSRFX2 device.
+
+Arguments:
+
+ VOID
+
+Return Value:
+
+ VOID
+
+--*/
+VOID
+OsrFx2InitializeDevice(
+ VOID
+ )
+{
+ CurrentBar = 0;
+}
+
+
+/*++
+
+Routine Description:
+
+ Turns off all of the bar graph lights on the OSR USB FX2 device.
+
+Arguments:
+
+ Context - The callback context
+
+Return Value:
+
+ VOID
+
+--*/
+DWORD
+OsrFx2ClearAllBars(
+ _In_ PDEVICE_CONTEXT Context
+ )
+{
+ DWORD Err = ERROR_SUCCESS;
+ ULONG BytesReturned;
+
+ BarGraphState.BarsAsUChar = 0;
+
+ if (!DeviceIoControl(Context->DeviceHandle,
+ IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
+ &BarGraphState, // Pointer to InBuffer
+ sizeof(BAR_GRAPH_STATE), // Length of InBuffer
+ NULL, // Pointer to OutBuffer
+ 0, // Length of OutBuffer
+ &BytesReturned, // BytesReturned
+ 0)) // Pointer to Overlapped structure
+ {
+ Err = GetLastError();
+ goto cleanup;
+ }
+
+cleanup:
+
+ return Err;
+}
+
+
+/*++
+
+Routine Description:
+
+ Lights the next bar on the OSR USB FX2 device.
+
+Arguments:
+
+ Context - The callback context
+
+Return Value:
+
+ VOID
+
+--*/
+DWORD
+OsrFx2LightNextBar(
+ _In_ PDEVICE_CONTEXT Context
+ )
+{
+ DWORD Err = ERROR_SUCCESS;
+ ULONG BytesReturned;
+
+ //
+ // Normalize to 0-7
+ //
+ CurrentBar += 1;
+
+ if (CurrentBar > 7)
+ {
+ CurrentBar = 0;
+ }
+
+ BarGraphState.BarsAsUChar = 1 << (UCHAR)CurrentBar;
+
+ if (!DeviceIoControl(Context->DeviceHandle,
+ IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
+ &BarGraphState, // Pointer to InBuffer
+ sizeof(BAR_GRAPH_STATE), // Length of InBuffer
+ NULL, // Pointer to OutBuffer
+ 0, // Length of OutBuffer
+ &BytesReturned, // BytesReturned
+ 0)) // Pointer to Overlapped structure
+ {
+ Err = GetLastError();
+ goto cleanup;
+ }
+
+cleanup:
+
+ return Err;
+}
+
+/*++
+
+Routine Description:
+
+ Lights the next bar on the OSRFX2 device.
+
+Arguments:
+
+ Context - The device context
+
+Return Value:
+
+ A Win32 error code.
+
+--*/
+DWORD
+OsrFx2ControlDevice(
+ _In_ PDEVICE_CONTEXT Context
+ )
+{
+ DWORD Err = ERROR_SUCCESS;
+
+ Err = OsrFx2ClearAllBars(Context);
+
+ if (Err != ERROR_SUCCESS)
+ {
+ goto cleanup;
+ }
+
+ Err = OsrFx2LightNextBar(Context);
+
+ if (Err != ERROR_SUCCESS)
+ {
+ goto cleanup;
+ }
+
+cleanup:
+
+ return Err;
+}
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.h
new file mode 100644
index 00000000..235e64ba
--- /dev/null
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.h
@@ -0,0 +1,144 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+--*/
+
+#pragma once
+#pragma warning(disable : 4201) // disable nameless struct/union warning
+
+//
+// {573E8C73-0CB4-4471-A1BF-FAB26C31D384}
+//
+DEFINE_GUID(GUID_DEVINTERFACE_OSRUSBFX2,
+ 0x573e8c73, 0xcb4, 0x4471, 0xa1, 0xbf, 0xfa, 0xb2, 0x6c, 0x31, 0xd3, 0x84);
+
+//
+// Define the structures that will be used by the IOCTL interface to the driver
+//
+
+// BAR_GRAPH_STATE is a bit field structure with each bit corresponding to one
+// of the bar graph on the OSRFX2 Development Board
+//
+typedef struct _BAR_GRAPH_STATE {
+
+ union {
+
+ struct {
+ //
+ // Individual bars starting from the top of the stack of bars
+ //
+ // NOTE: There are actually 10 bars, but the very top two do not
+ // light and are not counted here
+ //
+ UCHAR Bar1 : 1;
+ UCHAR Bar2 : 1;
+ UCHAR Bar3 : 1;
+ UCHAR Bar4 : 1;
+ UCHAR Bar5 : 1;
+ UCHAR Bar6 : 1;
+ UCHAR Bar7 : 1;
+ UCHAR Bar8 : 1;
+ };
+
+ //
+ // The state of all the bar graph as a single
+ // UCHAR
+ //
+ UCHAR BarsAsUChar;
+ };
+
+} BAR_GRAPH_STATE, *PBAR_GRAPH_STATE;
+
+//
+// SWITCH_STATE is a bit field structure with each bit corresponding to one of
+// the switches on the OSRFX2 Development Board
+//
+typedef struct _SWITCH_STATE {
+
+ union {
+ struct {
+ //
+ // Individual switches starting from the left of the set of switches
+ //
+ UCHAR Switch1 : 1;
+ UCHAR Switch2 : 1;
+ UCHAR Switch3 : 1;
+ UCHAR Switch4 : 1;
+ UCHAR Switch5 : 1;
+ UCHAR Switch6 : 1;
+ UCHAR Switch7 : 1;
+ UCHAR Switch8 : 1;
+ };
+
+ //
+ // The state of all the switches as a single
+ // UCHAR
+ //
+ UCHAR SwitchesAsUChar;
+ };
+
+} SWITCH_STATE, *PSWITCH_STATE;
+
+DWORD
+OsrFx2ControlDevice(
+ _In_ PDEVICE_CONTEXT Context
+ );
+
+VOID
+OsrFx2InitializeDevice(
+ VOID
+ );
+
+#define IOCTL_INDEX 0x800
+#define FILE_DEVICE_OSRUSBFX2 65500U
+
+#define IOCTL_OSRUSBFX2_GET_CONFIG_DESCRIPTOR CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS)
+
+#define IOCTL_OSRUSBFX2_RESET_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 1, \
+ METHOD_BUFFERED, \
+ FILE_WRITE_ACCESS)
+
+#define IOCTL_OSRUSBFX2_REENUMERATE_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 3, \
+ METHOD_BUFFERED, \
+ FILE_WRITE_ACCESS)
+
+#define IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 4, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS)
+
+#define IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 5, \
+ METHOD_BUFFERED, \
+ FILE_WRITE_ACCESS)
+
+#define IOCTL_OSRUSBFX2_READ_SWITCHES CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 6, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS)
+
+#define IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 7, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS)
+
+#define IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 8, \
+ METHOD_BUFFERED, \
+ FILE_WRITE_ACCESS)
+
+#define IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE CTL_CODE(FILE_DEVICE_OSRUSBFX2,\
+ IOCTL_INDEX + 9, \
+ METHOD_OUT_DIRECT, \
+ FILE_READ_ACCESS)
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.cpp
deleted file mode 100644
index a02ac24a..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.cpp
+++ /dev/null
@@ -1,1217 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation. All rights reserved.
-
- THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
- PURPOSE.
-
-Module Name:
-
- Main.cpp
-
-Abstract:
-
- Implements the functions to control the OSR USB FX2 device.
-
-Environment:
-
- User mode
-
---*/
-
-#include "Main.h"
-#include "Utils.h"
-
-//
-// Keep track of where the OSRFX2 device's bar graph currently is.
-//
-INT CurrentBar;
-BAR_GRAPH_STATE BarGraphState;
-
-/*++
-
-Routine Description:
-
- Sets the variables in this service to their default values.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-SetVariables()
-{
- CurrentBar = 0;
-}
-
-
-/*++
-
-Routine Description:
-
- Retrieves the device path of a given interface.
-
-Arguments:
-
- InterfaceGuid - The GUID of the interface to search for
-
- DevicePath - The resulting device path
-
- DevicePathLength - The length of DevicePath
-
-Return Value:
-
- TRUE if the function succeeded and FALSE otherwise. Errors
- are logged in the Application event log.
-
---*/
-_Success_(return)
-BOOL
-GetDevicePath(
- _In_ LPGUID InterfaceGuid,
- _Out_writes_z_(DevicePathLength) PWCHAR DevicePath,
- _In_ size_t DevicePathLength
- )
-{
- HRESULT hr = E_FAIL;
- CONFIGRET cr = CR_SUCCESS;
- PWSTR DeviceInterfaceList = NULL;
- ULONG DeviceInterfaceListLength = 0;
- PWSTR NextInterface;
-
- //
- // Determine if there are any interfaces that match the OSRFX2 device.
- //
- cr = CM_Get_Device_Interface_List_Size(&DeviceInterfaceListLength,
- InterfaceGuid,
- NULL,
- CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
-
- if (cr != CR_SUCCESS)
- {
- WriteToErrorLog(L"CM_Get_DeviceInterface_List_Size",
- CM_MapCrToWin32Err(cr, ERROR_FILE_NOT_FOUND));
- goto cleanup;
- }
-
- if (DeviceInterfaceListLength < 1)
- {
- WriteToErrorLog(L"CM_Get_DeviceInterface_List_Size",
- CM_MapCrToWin32Err(cr, ERROR_EMPTY));
- goto cleanup;
- }
-
- DeviceInterfaceList = (PWSTR)malloc(DeviceInterfaceListLength * sizeof(WCHAR));
-
- if (DeviceInterfaceList == NULL)
- {
- WriteToEventLog(L"Failed to allocate memory for the device interface list",
- TRACE_LEVEL_ERROR);
- goto cleanup;
- }
-
- cr = CM_Get_Device_Interface_List(InterfaceGuid,
- NULL,
- DeviceInterfaceList,
- DeviceInterfaceListLength,
- CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
-
- if (cr != CR_SUCCESS)
- {
- WriteToErrorLog(L"CM_Get_Device_Interface_List",
- CM_MapCrToWin32Err(cr, ERROR_FILE_NOT_FOUND));
- goto cleanup;
- }
-
- if (*DeviceInterfaceList == UNICODE_NULL)
- {
- WriteToEventLog(L"CM_Get_Device_Interface_List returned an empty list",
- TRACE_LEVEL_ERROR);
- }
-
- //
- // This sample only expects one interface for the OSRFX2 device. For other
- // devices, though, it maybe necessary to sift through the interfaces
- // from CM_Get_Device_Interface_List in order to find the correct device.
- //
- NextInterface = DeviceInterfaceList + wcslen(DeviceInterfaceList) + 1;
-
- if (*NextInterface != UNICODE_NULL)
- {
- WriteToEventLog(L"More than one device interface instance found. "
- "Selecting first matching device.",
- TRACE_LEVEL_WARNING);
- }
-
- hr = StringCchCopy(DevicePath, DevicePathLength, DeviceInterfaceList);
-
- if (FAILED(hr))
- {
- WriteToErrorLog(L"StringCchCopy", HRESULT_CODE(hr));
- goto cleanup;
- }
-
-cleanup:
-
- if (DeviceInterfaceList != NULL)
- {
- free(DeviceInterfaceList);
- }
-
- return (cr == CR_SUCCESS);
-}
-
-
-/*++
-
-Routine Description:
-
- Opens up the OSR USB FX2 device handle.
-
-Arguments:
-
- Synchronous - Whether or not this device should be opened for syncrhonous
- access
-
-Return Value:
-
- The handle to the OSR USB FX2 device.
-
---*/
-_Check_return_
-_Ret_notnull_
-_Success_(return != INVALID_HANDLE_VALUE)
-HANDLE
-OpenDevice(
- _In_ BOOL Synchronous
- )
-{
- HANDLE DeviceHandle = INVALID_HANDLE_VALUE;
- WCHAR DeviceName[MAX_DEVPATH_LENGTH];
-
- if (!GetDevicePath((LPGUID)&GUID_DEVINTERFACE_OSRUSBFX2,
- DeviceName,
- sizeof(DeviceName) / sizeof(DeviceName[0])))
- {
- goto cleanup;
- }
-
- //
- // Open a handle to the interface.
- //
- if (Synchronous)
- {
- DeviceHandle = CreateFile(DeviceName,
- GENERIC_WRITE | GENERIC_READ,
- FILE_SHARE_WRITE | FILE_SHARE_READ,
- NULL, // default security
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- }
- else
- {
- DeviceHandle = CreateFile(DeviceName,
- GENERIC_WRITE | GENERIC_READ,
- FILE_SHARE_WRITE | FILE_SHARE_READ,
- NULL, // default security
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
- NULL);
- }
-
- if (DeviceHandle == INVALID_HANDLE_VALUE)
- {
- WriteToErrorLog(L"CreateFile", GetLastError());
- }
- else
- {
- WriteToEventLog(L"Opened Device Successfully", TRACE_LEVEL_INFORMATION);
- }
-
-cleanup:
-
- return DeviceHandle;
-}
-
-
-/*++
-
-Routine Description:
-
- Handles an interface arrival notification.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-InterfaceArrivalAction(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
-
- //
- // Now that the interface has arrived, open a handle to it, and then
- // register that handle for device events.
- //
- EnterCriticalSection(&Context->Lock);
-
- if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE)
- {
- //
- // The handle was already retrieved.
- //
- Err = ERROR_SUCCESS;
- goto cleanup;
- }
-
- Context->DeviceInterfaceHandle = OpenDevice(FALSE);
-
- if (Context->DeviceInterfaceHandle == INVALID_HANDLE_VALUE)
- {
- Err = GetLastError();
- WriteToErrorLog(L"Could not open device interface", Err);
- goto cleanup;
- }
-
- Err = RegisterDeviceNotifications(Context);
-
- if (Err != ERROR_SUCCESS)
- {
- WriteToErrorLog(L"Could not register device notifications", Err);
- goto cleanup;
- }
-
-cleanup:
-
- LeaveCriticalSection(&Context->Lock);
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Handles an interface arrival notification.
-
-Arguments:
-
- hNotify - The notification that fired the callback
-
- hContext - The callback context
-
- Action - The type of notification
-
- EventData - Additional information about the callback
-
- EventDataSize - The size of EventData
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-InterfaceCallback(
- _In_ HCMNOTIFICATION hNotify,
- _In_ PVOID hContext,
- _In_ CM_NOTIFY_ACTION Action,
- _In_ PCM_NOTIFY_EVENT_DATA EventData,
- _In_ DWORD EventDataSize
- )
-{
- DWORD Err = ERROR_SUCCESS;
- PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)hContext;
-
- //
- // Validate Context.
- //
- if (Context == NULL)
- {
- goto cleanup;
- }
-
- if (Action == CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL)
- {
- Err = InterfaceArrivalAction(Context);
- }
-
-cleanup:
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Registers the service for notifications using the notification handle in
- Context.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-RegisterInterfaceNotifications(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
- CONFIGRET cr;
- CM_NOTIFY_FILTER NotifyFilter = {0};
-
- if (Context == NULL)
- {
- goto cleanup;
- }
-
- ZeroMemory(&NotifyFilter, sizeof(NotifyFilter));
- NotifyFilter.cbSize = sizeof(NotifyFilter);
- NotifyFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE;
- NotifyFilter.u.DeviceInterface.ClassGuid = GUID_DEVINTERFACE_OSRUSBFX2;
-
- cr = CM_Register_Notification(&NotifyFilter,
- (PVOID)Context,
- (PCM_NOTIFY_CALLBACK)InterfaceCallback,
- &Context->InterfaceNotificationHandle);
-
- if (cr != CR_SUCCESS)
- {
- Err = CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA);
- WriteToErrorLog(L"CM_Register_Notification", Err);
- goto cleanup;
- }
-
-cleanup:
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Unregister for interface notifications. Note, this routine deadlocks
- when called from an interface callback.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-UnregisterInterfaceNotifications(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- CONFIGRET cr;
-
- if (Context->InterfaceNotificationHandle != NULL)
- {
- cr = CM_Unregister_Notification(Context->InterfaceNotificationHandle);
-
- Context->InterfaceNotificationHandle = NULL;
- }
-
- return CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA);
-}
-
-
-/*++
-
-Routine Description:
-
- Callback for when a device is being query removed.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-DeviceQueryRemoveAction(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
-
- EnterCriticalSection(&Context->Lock);
-
- if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE)
- {
- //
- // Close open handles to allow the device to exit
- //
- CloseHandle(Context->DeviceInterfaceHandle);
-
- Context->DeviceInterfaceHandle = INVALID_HANDLE_VALUE;
- }
-
- LeaveCriticalSection(&Context->Lock);
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- This callback avoids a deadlock when unregistering device notifications.
- Rather than calling CM_Unregister_Notification from the callback, the
- callback gives that work to a separate thread to avoid deadlock.
-
-Arguments:
-
- Instance - The thread's callback instance
-
- hContext - The callback context
-
- pWork - The thread handle
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CALLBACK
-UnregisterWorkerThreadCallback(
- _Inout_ PTP_CALLBACK_INSTANCE Instance,
- _Inout_opt_ PVOID hContext,
- _Inout_ PTP_WORK pWork
- )
-{
- PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)hContext;
-
- EnterCriticalSection(&Context->Lock);
-
- UnregisterDeviceNotifications(Context);
-
- //
- // Close the device handle.
- //
- if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE)
- {
- CloseHandle(Context->DeviceInterfaceHandle);
-
- Context->DeviceInterfaceHandle = INVALID_HANDLE_VALUE;
- }
-
- LeaveCriticalSection(&Context->Lock);
-}
-
-
-/*++
-
-Routine Description:
-
- Handles a device query remove failed notification.
-
-Arguments:
-
- hNotify - The notification that spurred this callback
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-DeviceQueryRemoveFailedAction(
- _In_ HCMNOTIFICATION hNotify,
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
-
- EnterCriticalSection(&Context->Lock);
-
- //
- // In case this callback fires before the registration call returns, make
- // sure the notification handle is properly set.
- //
- Context->InterfaceNotificationHandle = hNotify;
-
- //
- // Unregister the device callback, and then close the handle
- //
- if (!Context->Unregister)
- {
- Context->Unregister = TRUE;
- SubmitThreadpoolWork(Context->Work);
- }
-
- LeaveCriticalSection(&Context->Lock);
-
- //
- // Wait for the callback and then re-register the device
- //
- WaitForThreadpoolWorkCallbacks(Context->Work, FALSE);
-
- EnterCriticalSection(&Context->Lock);
-
- if (Context->DeviceInterfaceHandle == INVALID_HANDLE_VALUE)
- {
- Context->DeviceInterfaceHandle = OpenDevice(FALSE);
- }
-
- if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE)
- {
- RegisterDeviceNotifications(Context);
- }
-
- LeaveCriticalSection(&Context->Lock);
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Handles a device remove pending notification.
-
-Arguments:
-
- hNotify - The notification that spurred this callback
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-DeviceRemovePendingAction(
- _In_ HCMNOTIFICATION hNotify,
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
-
- EnterCriticalSection(&Context->Lock);
-
- //
- // In case this callback fires before the registration call returns, make
- // sure the notification handle is properly set.
- //
- Context->InterfaceNotificationHandle = hNotify;
-
- //
- // Unregister the device callback, and then close the handle
- //
- if (!Context->Unregister)
- {
- Context->Unregister = TRUE;
- SubmitThreadpoolWork(Context->Work);
- }
-
- LeaveCriticalSection(&Context->Lock);
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Handles a device remove complete notification.
-
-Arguments:
-
- hNotify - The notification that spurred this callback
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-DeviceRemoveCompleteAction(
- _In_ HCMNOTIFICATION hNotify,
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
-
- EnterCriticalSection(&Context->Lock);
-
- //
- // In case this callback fires before the registration call returns, make
- // sure the notification handle is properly set.
- //
- Context->InterfaceNotificationHandle = hNotify;
-
- //
- // Unregister the device callback, and then close the handle
- //
- if (!Context->Unregister)
- {
- Context->Unregister = TRUE;
- SubmitThreadpoolWork(Context->Work);
- }
-
- LeaveCriticalSection(&Context->Lock);
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Handles device notifications.
-
-Arguments:
-
- hNotify - The notification that spurred this callback
-
- hContext - The callback context
-
- Action - The type of callback
-
- EventData - Additional information about this callback
-
- EventDataSize - The size of EventData
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-DeviceCallback(
- _In_ HCMNOTIFICATION hNotify,
- _In_ PVOID hContext,
- _In_ CM_NOTIFY_ACTION Action,
- _In_ PCM_NOTIFY_EVENT_DATA EventData,
- _In_ DWORD EventDataSize
- )
-{
- DWORD Err = ERROR_SUCCESS;
- PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)hContext;
-
- //
- // Validate Context.
- //
- if (Context == NULL)
- {
- goto cleanup;
- }
-
- switch (Action)
- {
- case CM_NOTIFY_ACTION_DEVICEQUERYREMOVE:
- DeviceQueryRemoveAction(Context);
- break;
-
- case CM_NOTIFY_ACTION_DEVICEQUERYREMOVEFAILED:
- DeviceQueryRemoveFailedAction(hNotify, Context);
- break;
-
- case CM_NOTIFY_ACTION_DEVICEREMOVEPENDING:
- DeviceRemovePendingAction(hNotify, Context);
- break;
-
- case CM_NOTIFY_ACTION_DEVICEREMOVECOMPLETE:
- DeviceRemoveCompleteAction(hNotify, Context);
- break;
- }
-
-cleanup:
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Register for device notifications.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-RegisterDeviceNotifications(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
- CONFIGRET cr;
- CM_NOTIFY_FILTER NotifyFilter = {0};
-
- NotifyFilter.cbSize = sizeof(NotifyFilter);
- NotifyFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE;
- NotifyFilter.u.DeviceHandle.hTarget = Context->DeviceInterfaceHandle;
-
- cr = CM_Register_Notification(&NotifyFilter,
- (PVOID)Context,
- (PCM_NOTIFY_CALLBACK)DeviceCallback,
- &Context->DeviceNotificationHandle);
-
- if (cr != CR_SUCCESS)
- {
- Err = CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA);
- WriteToEventLog(L"Could not register for notifications", TRACE_LEVEL_WARNING);
- goto cleanup;
- }
-
- Context->Unregister = FALSE;
-
-cleanup:
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Unregister for device notifications.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-UnregisterDeviceNotifications(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
- CONFIGRET cr;
-
- if (Context->DeviceNotificationHandle != NULL)
- {
- cr = CM_Unregister_Notification(Context->DeviceNotificationHandle);
-
- if (cr != CR_SUCCESS)
- {
- Err = CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA);
- WriteToEventLog(L"Could not unregister notifications", TRACE_LEVEL_WARNING);
- }
-
- Context->DeviceNotificationHandle = NULL;
- }
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Initialize the given PDEVICE_CONTEXT.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-InitializeContext(
- _Out_ PDEVICE_CONTEXT *Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
- BOOL LockInitialized = FALSE;
- BOOL LockEntered = FALSE;
- BOOL InterfaceNotificationsInitialized = FALSE;
- BOOL DeviceNotificationsInitialized = FALSE;
- PDEVICE_CONTEXT DeviceContext;
-
- DeviceContext = (PDEVICE_CONTEXT)malloc(sizeof(DEVICE_CONTEXT));
-
- if (DeviceContext == NULL)
- {
- Err = ERROR_OUTOFMEMORY;
- goto cleanup;
- }
-
- DeviceContext->DeviceInterfaceHandle = INVALID_HANDLE_VALUE;
- DeviceContext->LockEnabled = FALSE;
- DeviceContext->InterfaceNotificationsEnabled = FALSE;
- DeviceContext->DeviceNotificationsEnabled = FALSE;
-
- InitializeCriticalSection(&DeviceContext->Lock);
- DeviceContext->LockEnabled = TRUE;
-
- DeviceContext->Work = CreateThreadpoolWork(UnregisterWorkerThreadCallback, (PVOID)DeviceContext, NULL);
-
- if (DeviceContext->Work == NULL)
- {
- Err = GetLastError();
- WriteToErrorLog(L"Could not create worker thread callback", Err);
- goto cleanup;
- }
-
- DeviceContext->DeviceNotificationHandle = NULL;
- DeviceContext->InterfaceNotificationHandle = NULL;
-
- //
- // Register for device interface events to open and close the handle to
- // the interface.
- //
- Err = RegisterInterfaceNotifications(DeviceContext);
-
- if (Err != ERROR_SUCCESS)
- {
- WriteToErrorLog(L"Could not register notifications", Err);
- goto cleanup;
- }
-
- DeviceContext->InterfaceNotificationsEnabled = TRUE;
-
- EnterCriticalSection(&DeviceContext->Lock);
- LockEntered = TRUE;
-
- //
- // The interface may already have arrived while registering for
- // notifications. The lock could be moved earlier, but for sample
- // purposes this is the proper way to initialize notifications.
- //
- if (DeviceContext->DeviceInterfaceHandle == INVALID_HANDLE_VALUE)
- {
- DeviceContext->DeviceInterfaceHandle = OpenDevice(FALSE);
- }
-
- if (DeviceContext->DeviceInterfaceHandle != INVALID_HANDLE_VALUE)
- {
- Err = RegisterDeviceNotifications(DeviceContext);
-
- if (Err != ERROR_SUCCESS)
- {
- WriteToErrorLog(L"Could not register device notifications", Err);
- goto cleanup;
- }
-
- DeviceContext->DeviceNotificationsEnabled = TRUE;
- }
-
- //
- // If OpenDevice ends up returning INVALID_HANDLE_VALUE, that's fine
- // since a notification for the interface will arrive later.
- //
-
-cleanup:
-
- if (LockEntered)
- {
- LeaveCriticalSection(&DeviceContext->Lock);
- }
-
- *Context = DeviceContext;
- DeviceContext = NULL;
-
- if (DeviceContext != NULL)
- {
- CloseContext(DeviceContext);
- }
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Clean up the given PDEVICE_CONTEXT.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-CloseContext(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
- BOOL Unregister = FALSE;
-
- if (Context == NULL)
- {
- //
- // Nothing to remove.
- //
- goto cleanup;
- }
-
- EnterCriticalSection(&Context->Lock);
-
- if (!Context->Unregister)
- {
- //
- // Unregister from the callback here.
- //
- Unregister = TRUE;
- Context->Unregister = TRUE;
- }
-
- LeaveCriticalSection(&Context->Lock);
-
- //
- // Unregister from the interface first, so that re-appearance of the interface
- // doesn't cause us to register device events again.
- //
- if (Context->InterfaceNotificationsEnabled)
- {
- Err = UnregisterInterfaceNotifications(Context);
-
- if (Err != ERROR_SUCCESS)
- {
- WriteToErrorLog(L"Could not unregister interface notifications", Err);
- }
- }
-
- if (Unregister)
- {
- if (Context->DeviceNotificationsEnabled)
- {
- Err = UnregisterDeviceNotifications(Context);
-
- if (Err != ERROR_SUCCESS)
- {
- WriteToErrorLog(L"Could not unregister device notifications", Err);
- }
- }
- }
- else
- {
- WaitForThreadpoolWorkCallbacks(Context->Work, FALSE);
- }
-
- //
- // No need to lock here, UnregisterDeviceNotifications will wait for all
- // outstanding callbacks before returning.
- //
- if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE)
- {
- CloseHandle(Context->DeviceInterfaceHandle);
-
- Context->DeviceInterfaceHandle = INVALID_HANDLE_VALUE;
- }
-
- if (Context->Work != NULL)
- {
- CloseThreadpoolWork(Context->Work);
- }
-
- DeleteCriticalSection(&Context->Lock);
-
- free(Context);
-
-cleanup:
-
- return Err;
-}
-
-/*++
-
-Routine Description:
-
- Turns off all of the bar graph lights on the OSR USB FX2 device.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- VOID
-
---*/
-DWORD
-ClearAllBars(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
- ULONG BytesReturned;
-
- BarGraphState.BarsAsUChar = 0;
-
- if (!DeviceIoControl(Context->DeviceInterfaceHandle,
- IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
- &BarGraphState, // Pointer to InBuffer
- sizeof(BAR_GRAPH_STATE), // Length of InBuffer
- NULL, // Pointer to OutBuffer
- 0, // Length of OutBuffer
- &BytesReturned, // BytesReturned
- 0)) // Pointer to Overlapped structure
- {
- Err = GetLastError();
- WriteToErrorLog(L"DeviceIOControl", Err);
- goto cleanup;
- }
-
-cleanup:
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Lights the next bar on the OSR USB FX2 device.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- VOID
-
---*/
-DWORD
-LightNextBar(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
- ULONG BytesReturned;
-
- //
- // Normalize to 0-7
- //
- CurrentBar += 1;
-
- if (CurrentBar > 7)
- {
- CurrentBar = 0;
- }
-
- BarGraphState.BarsAsUChar = 1 << (UCHAR)CurrentBar;
-
- if (!DeviceIoControl(Context->DeviceInterfaceHandle,
- IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
- &BarGraphState, // Pointer to InBuffer
- sizeof(BAR_GRAPH_STATE), // Length of InBuffer
- NULL, // Pointer to OutBuffer
- 0, // Length of OutBuffer
- &BytesReturned, // BytesReturned
- 0)) // Pointer to Overlapped structure
- {
- Err = GetLastError();
- WriteToErrorLog(L"DeviceIOControl", Err);
- goto cleanup;
- }
-
-cleanup:
-
- return Err;
-}
-
-/*++
-
-Routine Description:
-
- Lights the next bar on the OSRFX2 device.
-
-Arguments:
-
- Context - The device context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-ControlDevice(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
-
- EnterCriticalSection(&Context->Lock);
-
- Err = ClearAllBars(Context);
-
- if (Err != ERROR_SUCCESS)
- {
- goto cleanup;
- }
-
- Err = LightNextBar(Context);
-
- if (Err != ERROR_SUCCESS)
- {
- goto cleanup;
- }
-
-cleanup:
-
- LeaveCriticalSection(&Context->Lock);
-
- return Err;
-} \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.h
deleted file mode 100644
index 3b8be711..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.h
+++ /dev/null
@@ -1,328 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation. All rights reserved.
-
- THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
- PURPOSE.
-
-Module Name:
-
- Main.h
-
-Abstract:
-
- Implements the functions to control the OSR USB FX2 device.
-
-Environment:
-
- User mode
-
---*/
-
-#pragma once
-
-#include <Windows.h>
-#include <devioctl.h>
-#include <cfgmgr32.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <strsafe.h>
-#include <driverspecs.h>
-#include <basetyps.h>
-
-#include <initguid.h>
-
-// {573E8C73-0CB4-4471-A1BF-FAB26C31D384}
-DEFINE_GUID(GUID_DEVINTERFACE_OSRUSBFX2,
- 0x573e8c73, 0xcb4, 0x4471, 0xa1, 0xbf, 0xfa, 0xb2, 0x6c, 0x31, 0xd3, 0x84);
-
-//
-// Most device interface paths will fit into a buffer of this size.
-// However, some could be longer, and a larger buffer or dynamically
-// allocated buffer may be needed for robust code.
-//
-#define MAX_DEVPATH_LENGTH 1024
-
-#pragma warning(push)
-#pragma warning(disable:4201) // nameless struct/union
-#pragma warning(disable:4214) // bit field types other than int
-
-typedef struct _DEVICE_CONTEXT {
- HANDLE DeviceInterfaceHandle;
- CRITICAL_SECTION Lock;
- BOOL LockEnabled;
- PTP_WORK Work;
- BOOL Unregister;
- HCMNOTIFICATION InterfaceNotificationHandle;
- BOOL InterfaceNotificationsEnabled;
- HCMNOTIFICATION DeviceNotificationHandle;
- BOOL DeviceNotificationsEnabled;
-} DEVICE_CONTEXT, *PDEVICE_CONTEXT;
-
-//
-// Define the structures that will be used by the IOCTL
-// interface to the driver
-//
-
-//
-// BAR_GRAPH_STATE
-//
-// BAR_GRAPH_STATE is a bit field structure with each
-// bit corresponding to one of the bar graph on the
-// OSRFX2 Development Board
-//
-#include <pshpack1.h>
-typedef struct _BAR_GRAPH_STATE {
-
- union {
-
- struct {
- //
- // Individual bars starting from the
- // top of the stack of bars
- //
- // NOTE: There are actually 10 bars,
- // but the very top two do not light
- // and are not counted here
- //
- UCHAR Bar1 : 1;
- UCHAR Bar2 : 1;
- UCHAR Bar3 : 1;
- UCHAR Bar4 : 1;
- UCHAR Bar5 : 1;
- UCHAR Bar6 : 1;
- UCHAR Bar7 : 1;
- UCHAR Bar8 : 1;
- };
-
- //
- // The state of all the bar graph as a single
- // UCHAR
- //
- UCHAR BarsAsUChar;
-
- };
-
-}BAR_GRAPH_STATE, *PBAR_GRAPH_STATE;
-
-//
-// SWITCH_STATE
-//
-// SWITCH_STATE is a bit field structure with each
-// bit corresponding to one of the switches on the
-// OSRFX2 Development Board
-//
-typedef struct _SWITCH_STATE {
-
- union {
- struct {
- //
- // Individual switches starting from the
- // left of the set of switches
- //
- UCHAR Switch1 : 1;
- UCHAR Switch2 : 1;
- UCHAR Switch3 : 1;
- UCHAR Switch4 : 1;
- UCHAR Switch5 : 1;
- UCHAR Switch6 : 1;
- UCHAR Switch7 : 1;
- UCHAR Switch8 : 1;
- };
-
- //
- // The state of all the switches as a single
- // UCHAR
- //
- UCHAR SwitchesAsUChar;
-
- };
-
-
-}SWITCH_STATE, *PSWITCH_STATE;
-
-#include <poppack.h>
-
-#pragma warning(pop)
-
-#define IOCTL_INDEX 0x800
-#define FILE_DEVICE_OSRUSBFX2 65500U
-
-#define IOCTL_OSRUSBFX2_GET_CONFIG_DESCRIPTOR CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
- IOCTL_INDEX, \
- METHOD_BUFFERED, \
- FILE_READ_ACCESS)
-
-#define IOCTL_OSRUSBFX2_RESET_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
- IOCTL_INDEX + 1, \
- METHOD_BUFFERED, \
- FILE_WRITE_ACCESS)
-
-#define IOCTL_OSRUSBFX2_REENUMERATE_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
- IOCTL_INDEX + 3, \
- METHOD_BUFFERED, \
- FILE_WRITE_ACCESS)
-
-#define IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
- IOCTL_INDEX + 4, \
- METHOD_BUFFERED, \
- FILE_READ_ACCESS)
-
-
-#define IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
- IOCTL_INDEX + 5, \
- METHOD_BUFFERED, \
- FILE_WRITE_ACCESS)
-
-
-#define IOCTL_OSRUSBFX2_READ_SWITCHES CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
- IOCTL_INDEX + 6, \
- METHOD_BUFFERED, \
- FILE_READ_ACCESS)
-
-
-#define IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
- IOCTL_INDEX + 7, \
- METHOD_BUFFERED, \
- FILE_READ_ACCESS)
-
-
-#define IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
- IOCTL_INDEX + 8, \
- METHOD_BUFFERED, \
- FILE_WRITE_ACCESS)
-
-#define IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE CTL_CODE(FILE_DEVICE_OSRUSBFX2,\
- IOCTL_INDEX + 9, \
- METHOD_OUT_DIRECT, \
- FILE_READ_ACCESS)
-
-/*++
-
-Routine Description:
-
-Lights the next bar on the OSRFX2 device.
-
-Arguments:
-
-Context - The device context
-
-Return Value:
-
-A Win32 error code.
-
---*/
-DWORD
-ControlDevice(PDEVICE_CONTEXT Context);
-
-
-/*++
-
-Routine Description:
-
- Sets the variables in this service to their default values.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID SetVariables(VOID);
-
-
-/*++
-
-Routine Description:
-
- Opens up the OSR USB FX2 device handle.
-
-Arguments:
-
- Synchronous - Whether or not this device should be
- opened for synchronous access
-
-Return Value:
-
- The handle to the OSR USB FX2 device.
-
---*/
-HANDLE OpenDevice(_In_ BOOL Synchronous);
-
-
-/*++
-
-Routine Description:
-
-Register for device notifications.
-
-Arguments:
-
-Context - The callback context
-
-Return Value:
-
-A Win32 error code.
-
---*/
-DWORD RegisterDeviceNotifications(PDEVICE_CONTEXT Context);
-
-
-/*++
-
-Routine Description:
-
-Unregister for device notifications.
-
-Arguments:
-
-Context - The callback context
-
-Return Value:
-
-A Win32 error code.
-
---*/
-DWORD UnregisterDeviceNotifications(PDEVICE_CONTEXT Context);
-
-
-/*++
-
-Routine Description:
-
-Initialize the given PDEVICE_CONTEXT.
-
-Arguments:
-
-Context - The callback context
-
-Return Value:
-
-A Win32 error code.
-
---*/
-DWORD InitializeContext(PDEVICE_CONTEXT* Context);
-
-
-/*++
-
-Routine Description:
-
-Clean up the given PDEVICE_CONTEXT.
-
-Arguments:
-
-Context - The callback context
-
-Return Value:
-
-A Win32 error code.
-
---*/
-DWORD CloseContext(PDEVICE_CONTEXT Context); \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.cpp
deleted file mode 100644
index fd3d497f..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation. All rights reserved.
-
- THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
- PURPOSE.
-
-Module Name:
-
- SampleService.cpp
-
-Abstract:
-
- Provides a sample service class that derives from the service base class -
- CServiceBase. The sample service logs the service start and stop
- information to the Application event log, and shows how to run the main
- function of the service in a thread pool worker thread.
-
-Environment:
-
- User mode
-
---*/
-
-#pragma region Includes
-#include "SampleService.h"
-#include "ThreadPool.h"
-#pragma endregion
-
-/*++
-
-Routine Description:
-
- The constructor of CSampleService. It initializes a new instance
- of the CSampleService class. The optional parameters (CanStop,
- CanShutdown and CanPauseContinue) allow you to specify whether the
- service can be stopped, paused and continued, or be notified when system
- shutdown occurs. Inherits properties from the class CServiceBase.
-
-Arguments:
-
- ServiceName - The name of the service
-
- CanStop - The service can be stopped
-
- CanShutdown - The service is notified when system shutdown occurs
-
- CanPauseContinue - The service can be paused and continued
-
-Return Value:
-
- VOID
-
---*/
-CSampleService::CSampleService(
- PWSTR ServiceName,
- BOOL CanStop,
- BOOL CanShutdown,
- BOOL CanPauseContinue
- )
-: CServiceBase(ServiceName, CanStop, CanShutdown, CanPauseContinue)
-{
- m_fStopping = FALSE;
-
- //
- // Create a manual-reset event that is not signaled at first to indicate
- // the stopped signal of the service.
- //
- m_hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-
- if (m_hStoppedEvent == NULL)
- {
- throw GetLastError();
- }
-}
-
-
-/*++
-
-Routine Description:
-
- The virtual destructor of CSampleService.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-CSampleService::~CSampleService()
-{
- if (m_hStoppedEvent)
- {
- CloseHandle(m_hStoppedEvent);
- m_hStoppedEvent = NULL;
- }
-}
-
-
-/*++
-
-Routine Description:
-
- This function is executed when a Start command is sent to the
- service by the SCM or when the operating system starts (for a service
- that starts automatically). It specifies actions to take when the
- service starts. In this code sample, OnStart logs a service-start
- message to the Application log, and queues the main service function for
- execution in a thread pool worker thread.
-
- NOTE: A service application is designed to be long running. Therefore,
- it usually polls or monitors something in the system. The monitoring is
- set up in the OnStart method. However, OnStart does not actually do the
- monitoring. The OnStart method must return to the operating system after
- the service's operation has begun. It must not loop forever or block. To
- set up a simple monitoring mechanism, one general solution is to create
- a timer in OnStart. The timer would then raise events in your code
- periodically, at which time your service could do its monitoring. The
- other solution is to spawn a new thread to perform the main service
- functions, which is demonstrated in this code sample.
-
-Arguments:
-
- Argc - The number of command line arguments
-
- Argv - The array of command line arguments
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CSampleService::OnStart(
- DWORD Argc,
- PWSTR *Argv
- )
-{
- __debugbreak();
-
- //
- // Log a service start message to the Application log.
- //
- WriteToEventLog(L"SampleService in OnStart",
- EVENTLOG_INFORMATION_TYPE);
-
- //
- // Set up any variables the service needs.
- //
- SetVariables();
-
- //
- // Set up the context, and register for notifications.
- //
- InitializeContext(&m_Context);
-
- //
- // Queue the main service function for execution in a worker thread.
- //
- CThreadPool::QueueUserWorkItem(&CSampleService::ServiceWorkerThread, this);
-}
-
-
-/*++
-
-Routine Description:
-
- This method performs the main function of the service. It runs
- on a thread pool worker thread.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CSampleService::ServiceWorkerThread()
-{
- //
- // Periodically check if the service is stopping.
- //
- while (!m_fStopping)
- {
- //
- // Perform main service function here...
- //
-
- ControlDevice(m_Context);
-
- ::Sleep(2000); // Simulate some lengthy operations.
- }
-
- //
- // Signal the stopped event.
- //
- SetEvent(m_hStoppedEvent);
-}
-
-
-/*++
-
-Routine Description:
-
- This function is executed when a Stop command is sent to the service by SCM.
- It specifies actions to take when a service stops running. In this code
- sample, OnStop logs a service-stop message to the Application log, and
- waits for the finish of the main service function.
-
- Be sure to periodically call ReportServiceStatus() with
- SERVICE_STOP_PENDING if the procedure is going to take a long time.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CSampleService::OnStop()
-{
- //
- // Log a service stop message to the Application log.
- //
- WriteToEventLog(L"SampleService in OnStop",
- EVENTLOG_INFORMATION_TYPE);
-
- //
- // Indicate that the service is stopping and wait for the finish of the
- // main service function (ServiceWorkerThread).
- //
- m_fStopping = TRUE;
-
- if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0)
- {
- throw GetLastError();
- }
-
- //
- // Clean up the context after the worker thread has finished.
- //
- CloseContext(m_Context);
-} \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.h
deleted file mode 100644
index 73be42e9..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation. All rights reserved.
-
- THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
- PURPOSE.
-
-Module Name:
-
- SampleService.h
-
-Abstract:
-
- Provides a sample service class that derives from the service base class -
- CServiceBase. The sample service logs the service start and stop
- information to the Application event log, and shows how to run the main
- function of the service in a thread pool worker thread.
-
-Environment:
-
- User mode
-
---*/
-
-#pragma once
-
-#include "ServiceBase.h"
-#include "Main.h"
-
-class CSampleService : public CServiceBase
-{
-public:
-
- /*++
-
- Routine Description:
-
- The constructor of CSampleService. It initializes a new instance
- of the CSampleService class. The optional parameters (CanStop,
- CanShutdown and CanPauseContinue) allow you to specify whether the
- service can be stopped, paused and continued, or be notified when system
- shutdown occurs. Inherits properties from the class CServiceBase.
-
- Arguments:
-
- ServiceName - The name of the service
-
- CanStop - The service can be stopped
-
- CanShutdown - The service is notified when system shutdown occurs
-
- CanPauseContinue - The service can be paused and continued
-
- Return Value:
-
- VOID
-
- --*/
- CSampleService(PWSTR ServiceName,
- BOOL CanStop = TRUE,
- BOOL CanShutdown = TRUE,
- BOOL CanPauseContinue = FALSE);
-
- /*++
-
- Routine Description:
-
- The virtual destructor of CSampleService.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- virtual ~CSampleService();
-
-protected:
-
- /*++
-
- Routine Description:
-
- This function is executed when a Start command is sent to the
- service by the SCM or when the operating system starts (for a service
- that starts automatically). It specifies actions to take when the
- service starts. In this code sample, OnStart logs a service-start
- message to the Application log, and queues the main service function for
- execution in a thread pool worker thread.
-
- NOTE: A service application is designed to be long running. Therefore,
- it usually polls or monitors something in the system. The monitoring is
- set up in the OnStart method. However, OnStart does not actually do the
- monitoring. The OnStart method must return to the operating system after
- the service's operation has begun. It must not loop forever or block. To
- set up a simple monitoring mechanism, one general solution is to create
- a timer in OnStart. The timer would then raise events in your code
- periodically, at which time your service could do its monitoring. The
- other solution is to spawn a new thread to perform the main service
- functions, which is demonstrated in this code sample.
-
- Arguments:
-
- Argc - The number of command line arguments
-
- Argv - The array of command line arguments
-
- Return Value:
-
- VOID
-
- --*/
- virtual VOID OnStart(DWORD Argc, PWSTR *Argv);
-
-
- /*++
-
- Routine Description:
-
- This function is executed when a Stop command is sent to the service by SCM.
- It specifies actions to take when a service stops running. In this code
- sample, OnStop logs a service-stop message to the Application log, and
- waits for the finish of the main service function.
-
- Be sure to periodically call ReportServiceStatus() with
- SERVICE_STOP_PENDING if the procedure is going to take a long time.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- virtual VOID OnStop();
-
-
- /*++
-
- Routine Description:
-
- This method performs the main function of the service. It runs
- on a thread pool worker thread.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- VOID ServiceWorkerThread();
-
-private:
-
- //
- // Determines if the service is currently stopping.
- //
- BOOL m_fStopping;
-
- //
- // The handle to wait for a stop event.
- //
- HANDLE m_hStoppedEvent;
-
- //
- // The device context to manage notifications with.
- //
- // NOTE:
- // Variables used for device notifications should normally be local. However,
- // we must use a global variable here since there is a potential race condition
- // when the service needs to restart during device installation that could
- // cause the service to prevent the device from being restarted. So, this
- // variable is global so that the service's OnStart and OnStart method can
- // handle its creation and destruction.
- //
- PDEVICE_CONTEXT m_Context;
-}; \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.cpp
deleted file mode 100644
index 4c20af2e..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.cpp
+++ /dev/null
@@ -1,794 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation. All rights reserved.
-
- THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
- PURPOSE.
-
-Module Name:
-
- ServiceBase.cpp
-
-Abstract:
-
- Provides a base class for a service that will exist as part of a service
- application. CServiceBase must be derived from when creating a new service
- class.
-
-Environment:
-
- User mode
-
---*/
-
-#pragma region Includes
-#include "ServiceBase.h"
-#include "Main.h"
-#include "Utils.h"
-#include <assert.h>
-#include <strsafe.h>
-#pragma endregion
-
-
-#pragma region Static Members
-
-//
-// Initialize the singleton service instance.
-//
-CServiceBase *CServiceBase::s_service = NULL;
-
-
-/*++
-
-Routine Description:
-
- Register the executable for a service with the Service Control
- Manager (SCM). After you call Run(ServiceBase), the SCM issues a Start
- command, which results in a call to the OnStart method in the service.
- This method blocks until the service has stopped.
-
-Arguments:
-
- Service - The reference to a CServiceBase object. It will become the
- singleton service instance of this service application.
-
-Return Value:
-
- If the function succeeds, the return value is TRUE. If the function
- fails, the return value is FALSE. To get extended error information,
- call GetLastError.
-
---*/
-BOOL
-CServiceBase::Run(
- CServiceBase &Service
- )
-{
- s_service = &Service;
-
- SERVICE_TABLE_ENTRY serviceTable[] =
- {
- { Service.m_name, ServiceMain },
- { NULL, NULL }
- };
-
- //
- // Connects the main thread of a service process to the service control
- // manager, which causes the thread to be the service control dispatcher
- // thread for the calling process. This call returns when the service has
- // stopped. The process should simply terminate when the call returns.
- //
- return StartServiceCtrlDispatcher(serviceTable);
-}
-
-
-/*++
-
-Routine Description:
-
- The entry point for the service. It registers the handler function
- for the service and starts the service.
-
-Arguments:
-
- Argc - The number of command line arguments
-
- Argv - The array of command line arguments
-
-Return Value:
-
- VOID
-
---*/
-VOID
-WINAPI
-CServiceBase::ServiceMain(
- DWORD Argc,
- PWSTR *Argv
- )
-{
- assert(s_service != NULL);
-
- //
- // Register the handler function for the service.
- //
- s_service->m_statusHandle = RegisterServiceCtrlHandler(s_service->m_name,
- ServiceCtrlHandler);
-
- if (s_service->m_statusHandle == NULL)
- {
- throw GetLastError();
- }
-
- //
- // Start the service.
- //
- s_service->Start(Argc, Argv);
-}
-
-
-/*++
-
-Routine Description:
-
- Called by the SCM whenever a control code is sent to the service.
-
-Arguments:
-
- CtrlCode - The control code. This parameter can be one of
- the following values:
-
- SERVICE_CONTROL_CONTINUE
- SERVICE_CONTROL_INTERROGATE
- SERVICE_CONTROL_NETBINDADD
- SERVICE_CONTROL_NETBINDDISABLE
- SERVICE_CONTROL_NETBINDREMOVE
- SERVICE_CONTROL_PARAMCHANGE
- SERVICE_CONTROL_PAUSE
- SERVICE_CONTROL_SHUTDOWN
- SERVICE_CONTROL_STOP
-
- This parameter can also be a user-defined control
- code ranging from 128 to 255.
-
-Return Value:
-
- VOID
-
---*/
-VOID
-WINAPI
-CServiceBase::ServiceCtrlHandler(
- DWORD Ctrl
- )
-{
- switch (Ctrl)
- {
- case SERVICE_CONTROL_STOP:
- s_service->Stop();
- break;
- case SERVICE_CONTROL_PAUSE:
- s_service->Pause();
- break;
- case SERVICE_CONTROL_CONTINUE:
- s_service->Continue();
- break;
- case SERVICE_CONTROL_SHUTDOWN:
- s_service->Shutdown();
- break;
- case SERVICE_CONTROL_INTERROGATE:
- break;
- default:
- break;
- }
-}
-
-#pragma endregion
-
-
-#pragma region Service Constructor and Destructor
-
-/*++
-
-Routine Description:
-
- The constructor of CServiceBase. It initializes a new instance
- of the CServiceBase class. The optional parameters (CanStop,
- CanShutdown and CanPauseContinue) allow you to specify whether the
- service can be stopped, paused and continued, or be notified when system
- shutdown occurs.
-
-Arguments:
-
- ServiceName - The name of the service
-
- CanStop - The service can be stopped
-
- CanShutdown - The service is notified when system shutdown occurs
-
- CanPauseContinue - The service can be paused and continued
-
-Return Value:
-
- VOID
-
---*/
-CServiceBase::CServiceBase(
- PWSTR ServiceName,
- BOOL CanStop,
- BOOL CanShutdown,
- BOOL CanPauseContinue
- )
-{
- //
- // Service name must be a valid string and cannot be NULL.
- //
- m_name = (ServiceName == NULL) ? L"" : ServiceName;
-
- m_statusHandle = NULL;
-
- //
- // The service runs in its own process.
- //
- m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
-
- //
- // The service is starting.
- //
- m_status.dwCurrentState = SERVICE_START_PENDING;
-
- //
- // The accepted commands of the service.
- //
- DWORD dwControlsAccepted = 0;
-
- if (CanStop)
- {
- dwControlsAccepted |= SERVICE_ACCEPT_STOP;
- }
-
- if (CanShutdown)
- {
- dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN;
- }
-
- if (CanPauseContinue)
- {
- dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
- }
-
- m_status.dwControlsAccepted = dwControlsAccepted;
-
- m_status.dwWin32ExitCode = NO_ERROR;
- m_status.dwServiceSpecificExitCode = 0;
- m_status.dwCheckPoint = 0;
- m_status.dwWaitHint = 0;
-
- SetupEvents();
-}
-
-
-/*++
-
-Routine Description:
-
- The virtual destructor of CServiceBase.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-CServiceBase::~CServiceBase()
-{
- DestroyEvents();
-}
-
-#pragma endregion
-
-
-#pragma region Service Start, Stop, Pause, Continue, and Shutdown
-
-/*++
-
-Routine Description:
-
- This function starts the service. It calls the OnStart virtual function
- in which you can specify the actions to take when the service starts. If
- an error occurs during the startup, the error will be logged in the
- Application event log, and the service will be stopped.
-
-Arguments:
-
- Argc - The number of command line arguments
-
- Argv - The array of command line arguments
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::Start(
- DWORD Argc,
- PWSTR *Argv
-)
-{
- try
- {
- //
- // Tell SCM that the service is starting.
- //
- SetServiceStatus(SERVICE_START_PENDING);
-
- //
- // Perform service-specific initialization.
- //
- OnStart(Argc, Argv);
-
- //
- // Tell SCM that the service is started.
- //
- SetServiceStatus(SERVICE_RUNNING);
- }
- catch (DWORD Error)
- {
- //
- // Log the error.
- //
- WriteToErrorLog(L"Service Start", Error);
-
- //
- // Set the service status to be stopped.
- //
- SetServiceStatus(SERVICE_STOPPED, Error);
- }
- catch (...)
- {
- //
- // Log the error.
- //
- WriteToEventLog(L"Service failed to start.", EVENTLOG_ERROR_TYPE);
-
- //
- // Set the service status to be stopped.
- //
- SetServiceStatus(SERVICE_STOPPED);
- }
-}
-
-
-/*++
-
-Routine Description:
-
- When implemented in a derived class, executes when a Start
- command is sent to the service by the SCM or when the operating system
- starts (for a service that starts automatically). Specifies actions to
- take when the service starts. Be sure to periodically call
- CServiceBase::SetServiceStatus() with SERVICE_START_PENDING if the
- procedure is going to take long time. You may also consider spawning a
- new thread in OnStart to perform time-consuming initialization tasks.
-
-Arguments:
-
- Argc - The number of command line arguments
-
- Argv - The array of command line arguments
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::OnStart(
- DWORD Argc,
- PWSTR *Argv
-)
-{
- SetVariables();
-}
-
-
-/*++
-
-Routine Description:
-
- This function stops the service. It calls the OnStop virtual
- function in which you can specify the actions to take when the service
- stops. If an error occurs, the error will be logged in the Application
- event log, and the service will be restored to the original state.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::Stop()
-{
- DWORD OriginalState = m_status.dwCurrentState;
-
- try
- {
- //
- // Tell SCM that the service is stopping.
- //
- SetServiceStatus(SERVICE_STOP_PENDING);
-
- //
- // Perform service-specific stop operations.
- //
- OnStop();
-
- //
- // Tell SCM that the service is stopped.
- //
- SetServiceStatus(SERVICE_STOPPED);
- }
- catch (DWORD Error)
- {
- //
- // Log the error.
- //
- WriteToErrorLog(L"Service Stop", Error);
-
- //
- // Set the orginal service status.
- //
- SetServiceStatus(OriginalState);
- }
- catch (...)
- {
- //
- // Log the error.
- //
- WriteToEventLog(L"Service failed to stop.", EVENTLOG_ERROR_TYPE);
-
- //
- // Set the orginal service status.
- //
- SetServiceStatus(OriginalState);
- }
-}
-
-
-/*++
-
-Routine Description:
-
- When implemented in a derived class, executes when a Stop
- command is sent to the service by the SCM. Specifies actions to take
- when a service stops running. Be sure to periodically call
- CServiceBase::SetServiceStatus() with SERVICE_STOP_PENDING if the
- procedure is going to take long time.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::OnStop()
-{
-}
-
-
-/*++
-
-Routine Description:
-
- The function pauses the service if the service supports pause
- and continue. It calls the OnPause virtual function in which you can
- specify the actions to take when the service pauses. If an error occurs,
- the error will be logged in the Application event log, and the service
- will become running.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::Pause()
-{
- try
- {
- //
- // Tell SCM that the service is pausing.
- //
- SetServiceStatus(SERVICE_PAUSE_PENDING);
-
- //
- // Perform service-specific pause operations.
- //
- OnPause();
-
- //
- // Tell SCM that the service is paused.
- //
- SetServiceStatus(SERVICE_PAUSED);
- }
- catch (DWORD Error)
- {
- //
- // Log the error.
- //
- WriteToErrorLog(L"Service Pause", Error);
-
- //
- // Tell SCM that the service is still running.
- //
- SetServiceStatus(SERVICE_RUNNING);
- }
- catch (...)
- {
- //
- // Log the error.
- //
- WriteToEventLog(L"Service failed to pause.", EVENTLOG_ERROR_TYPE);
-
- //
- // Tell SCM that the service is still running.
- //
- SetServiceStatus(SERVICE_RUNNING);
- }
-}
-
-
-/*++
-
-Routine Description:
-
- When implemented in a derived class, executes when a Pause
- command is sent to the service by the SCM. Specifies actions to take
- when a service pauses.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::OnPause()
-{
-}
-
-
-/*++
-
-Routine Description:
-
- The function resumes normal functioning after being paused if
- the service supports pause and continue. It calls the OnContinue virtual
- function in which you can specify the actions to take when the service
- continues. If an error occurs, the error will be logged in the
- Application event log, and the service will still be paused.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::Continue()
-{
- try
- {
- //
- // Tell SCM that the service is resuming.
- //
- SetServiceStatus(SERVICE_CONTINUE_PENDING);
-
- //
- // Perform service-specific continue operations.
- //
- OnContinue();
-
- //
- // Tell SCM that the service is running.
- //
- SetServiceStatus(SERVICE_RUNNING);
- }
- catch (DWORD Error)
- {
- //
- // Log the error.
- //
- WriteToErrorLog(L"Service Continue", Error);
-
- //
- // Tell SCM that the service is still paused.
- //
- SetServiceStatus(SERVICE_PAUSED);
- }
- catch (...)
- {
- //
- // Log the error.
- //
- WriteToEventLog(L"Service failed to resume.", EVENTLOG_ERROR_TYPE);
-
- //
- // Tell SCM that the service is still paused.
- //
- SetServiceStatus(SERVICE_PAUSED);
- }
-}
-
-
-/*++
-
-Routine Description:
-
- When implemented in a derived class, OnContinue runs when a
- Continue command is sent to the service by the SCM. Specifies actions to
- take when a service resumes normal functioning after being paused.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::OnContinue()
-{
-}
-
-
-/*++
-
-Routine Description:
-
- The function executes when the system is shutting down. It
- calls the OnShutdown virtual function in which you can specify what
- should occur immediately prior to the system shutting down. If an error
- occurs, the error will be logged in the Application event log.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::Shutdown()
-{
- try
- {
- //
- // Perform service-specific shutdown operations.
- //
- OnShutdown();
-
- //
- // Tell SCM that the service is stopped.
- //
- SetServiceStatus(SERVICE_STOPPED);
- }
- catch (DWORD Error)
- {
- //
- // Log the error.
- //
- WriteToErrorLog(L"Service Shutdown", Error);
- }
- catch (...)
- {
- //
- // Log the error.
- //
- WriteToEventLog(L"Service failed to shut down.", EVENTLOG_ERROR_TYPE);
- }
-}
-
-
-/*++
-
-Routine Description:
-
- When implemented in a derived class, executes when the system
- is shutting down. Specifies what should occur immediately prior to the
- system shutting down.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::OnShutdown()
-{
-}
-
-#pragma endregion
-
-
-#pragma region Helper Functions
-
-/*++
-
-Routine Description:
-
- The function sets the service status and reports the status to the SCM.
-
-Arguments:
-
- CurrentState - The current state of the service
-
- Win32ExitCode - The error code to report
-
- WaitHint - The estimated time for pending operation, in milliseconds
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::SetServiceStatus(
- DWORD CurrentState,
- DWORD Win32ExitCode,
- DWORD WaitHint
- )
-{
- static DWORD CheckPoint = 1;
-
- //
- // Fill in the SERVICE_STATUS structure of the service.
- //
-
- m_status.dwCurrentState = CurrentState;
- m_status.dwWin32ExitCode = Win32ExitCode;
- m_status.dwWaitHint = WaitHint;
-
- m_status.dwCheckPoint = ((CurrentState == SERVICE_RUNNING) ||
- (CurrentState == SERVICE_STOPPED)) ? 0 :
- CheckPoint++;
-
- //
- // Report the status of the service to the SCM.
- //
- ::SetServiceStatus(m_statusHandle, &m_status);
-}
-
-#pragma endregion \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.h
deleted file mode 100644
index 106597e1..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.h
+++ /dev/null
@@ -1,423 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation. All rights reserved.
-
- THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
- PURPOSE.
-
-Module Name:
-
- ServiceBase.cpp
-
-Abstract:
-
- Provides a base class for a service that will exist as part of a service
- application. CServiceBase must be derived from when creating a new service
- class.
-
-Environment:
-
- User mode
-
---*/
-
-#pragma once
-
-#include <windows.h>
-#include "Utils.h"
-
-class CServiceBase
-{
-public:
-
- /*++
-
- Routine Description:
-
- Register the executable for a service with the Service Control
- Manager (SCM). After you call Run(ServiceBase), the SCM issues a Start
- command, which results in a call to the OnStart method in the service.
- This method blocks until the service has stopped.
-
- Arguments:
-
- Service - The reference to a CServiceBase object. It will become the
- singleton service instance of this service application.
-
- Return Value:
-
- If the function succeeds, the return value is TRUE. If the function
- fails, the return value is FALSE. To get extended error information,
- call GetLastError.
-
- --*/
- static BOOL Run(CServiceBase &service);
-
-
- /*++
-
- Routine Description:
-
- The constructor of CServiceBase. It initializes a new instance
- of the CServiceBase class. The optional parameters (CanStop,
- CanShutdown and CanPauseContinue) allow you to specify whether the
- service can be stopped, paused and continued, or be notified when system
- shutdown occurs.
-
- Arguments:
-
- ServiceName - The name of the service
-
- CanStop - The service can be stopped
-
- CanShutdown - The service is notified when system shutdown occurs
-
- CanPauseContinue - The service can be paused and continued
-
- Return Value:
-
- VOID
-
- --*/
- CServiceBase(PWSTR ServiceName,
- BOOL CanStop = TRUE,
- BOOL CanShutdown = TRUE,
- BOOL CanPauseContinue = FALSE);
-
-
- /*++
-
- Routine Description:
-
- The virtual destructor of CServiceBase.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- virtual ~CServiceBase();
-
-
- /*++
-
- Routine Description:
-
- This function stops the service. It calls the OnStop virtual
- function in which you can specify the actions to take when the service
- stops. If an error occurs, the error will be logged in the Application
- event log, and the service will be restored to the original state.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- VOID Stop();
-
-protected:
-
- /*++
-
- Routine Description:
-
- When implemented in a derived class, executes when a Start
- command is sent to the service by the SCM or when the operating system
- starts (for a service that starts automatically). Specifies actions to
- take when the service starts. Be sure to periodically call
- CServiceBase::SetServiceStatus() with SERVICE_START_PENDING if the
- procedure is going to take long time. You may also consider spawning a
- new thread in OnStart to perform time-consuming initialization tasks.
-
- Arguments:
-
- Argc - The number of command line arguments
-
- Argv - The array of command line arguments
-
- Return Value:
-
- VOID
-
- --*/
- virtual VOID OnStart(DWORD Argc, PWSTR *Argv);
-
-
- /*++
-
- Routine Description:
-
- When implemented in a derived class, executes when a Stop
- command is sent to the service by the SCM. Specifies actions to take
- when a service stops running. Be sure to periodically call
- CServiceBase::SetServiceStatus() with SERVICE_STOP_PENDING if the
- procedure is going to take long time.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- virtual VOID OnStop();
-
-
- /*++
-
- Routine Description:
-
- When implemented in a derived class, executes when a Pause
- command is sent to the service by the SCM. Specifies actions to take
- when a service pauses.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- virtual VOID OnPause();
-
-
- /*++
-
- Routine Description:
-
- When implemented in a derived class, OnContinue runs when a
- Continue command is sent to the service by the SCM. Specifies actions to
- take when a service resumes normal functioning after being paused.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- virtual VOID OnContinue();
-
-
- /*++
-
- Routine Description:
-
- When implemented in a derived class, executes when the system
- is shutting down. Specifies what should occur immediately prior to the
- system shutting down.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- virtual VOID OnShutdown();
-
-
- /*++
-
- Routine Description:
-
- The function sets the service status and reports the status to the SCM.
-
- Arguments:
-
- CurrentState - The current state of the service
-
- Win32ExitCode - The error code to report
-
- WaitHint - The estimated time for pending operation, in milliseconds
-
- Return Value:
-
- VOID
-
- --*/
- VOID SetServiceStatus(DWORD CurrentState,
- DWORD Win32ExitCode = NO_ERROR,
- DWORD WaitHint = 0);
-
-private:
-
- /*++
-
- Routine Description:
-
- The entry point for the service. It registers the handler function
- for the service and starts the service.
-
- Arguments:
-
- Argc - The number of command line arguments
-
- Argv - The array of command line arguments
-
- Return Value:
-
- VOID
-
- --*/
- static VOID WINAPI ServiceMain(DWORD Argc, PWSTR *Argv);
-
-
- /*++
-
- Routine Description:
-
- Called by the SCM whenever a control code is sent to the service.
-
- Arguments:
-
- CtrlCode - The control code. This parameter can be one of
- the following values:
-
- SERVICE_CONTROL_CONTINUE
- SERVICE_CONTROL_INTERROGATE
- SERVICE_CONTROL_NETBINDADD
- SERVICE_CONTROL_NETBINDDISABLE
- SERVICE_CONTROL_NETBINDREMOVE
- SERVICE_CONTROL_PARAMCHANGE
- SERVICE_CONTROL_PAUSE
- SERVICE_CONTROL_SHUTDOWN
- SERVICE_CONTROL_STOP
-
- This parameter can also be a user-defined control
- code ranging from 128 to 255.
-
- Return Value:
-
- VOID
-
- --*/
- static VOID WINAPI ServiceCtrlHandler(DWORD Ctrl);
-
-
- /*++
-
- Routine Description:
-
- This function starts the service. It calls the OnStart virtual function
- in which you can specify the actions to take when the service starts. If
- an error occurs during the startup, the error will be logged in the
- Application event log, and the service will be stopped.
-
- Arguments:
-
- Argc - The number of command line arguments
-
- Argv - The array of command line arguments
-
- Return Value:
-
- VOID
-
- --*/
- VOID Start(DWORD Argc, PWSTR *Argv);
-
-
- /*++
-
- Routine Description:
-
- The function pauses the service if the service supports pause
- and continue. It calls the OnPause virtual function in which you can
- specify the actions to take when the service pauses. If an error occurs,
- the error will be logged in the Application event log, and the service
- will become running.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- VOID Pause();
-
-
- /*++
-
- Routine Description:
-
- The function resumes normal functioning after being paused if
- the service supports pause and continue. It calls the OnContinue virtual
- function in which you can specify the actions to take when the service
- continues. If an error occurs, the error will be logged in the
- Application event log, and the service will still be paused.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- VOID Continue();
-
-
- /*++
-
- Routine Description:
-
- The function executes when the system is shutting down. It
- calls the OnShutdown virtual function in which you can specify what
- should occur immediately prior to the system shutting down. If an error
- occurs, the error will be logged in the Application event log.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- VOID Shutdown();
-
-
- //
- // The singleton service instance.
- //
- static CServiceBase *s_service;
-
- //
- // The name of the service.
- //
- PWSTR m_name;
-
- //
- // The status of the service.
- //
- SERVICE_STATUS m_status;
-
- //
- // The service status handle.
- //
- SERVICE_STATUS_HANDLE m_statusHandle;
-}; \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.cpp
new file mode 100644
index 00000000..f6616850
--- /dev/null
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.cpp
@@ -0,0 +1,375 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ ServiceWin32API.cpp
+
+Abstract:
+
+ Implements functions to start/run/stop the service.
+
+Environment:
+
+ User mode
+
+--*/
+
+#include "stdafx.h"
+
+//
+// Settings of the service
+//
+#define SERVICE_NAME L"OsrUsbFx2UmUserSvc"
+#define SERVICE_FLAGS_RUNNING 0x1
+
+//
+// Service context
+//
+SERVICE_STATUS_HANDLE SvcStatusHandle = NULL;
+volatile LONG SvcControlFlags = 0;
+HANDLE SvcStoppedEvent = NULL;
+HANDLE SvcStopRequestEvent = NULL;
+HANDLE SvcStopWaitObject = NULL;
+
+//
+// Device interface context
+//
+HCMNOTIFICATION InterfaceNotificationHandle = NULL;
+SRWLOCK DeviceListLock = SRWLOCK_INIT;
+DEVICE_LIST_ENTRY DeviceList;
+
+//
+// Debugging support during development time
+//
+//#define DEBUG_SUPPORT
+
+/*++
+
+Routine Description:
+
+ Entry point for the service.
+
+Arguments:
+
+ Argc - The number of command line arguments
+
+ Argv - The array of command line arguments
+
+Return Value:
+
+ VOID
+
+--*/
+INT
+wmain(
+ INT Argc,
+ WCHAR *Argv[]
+ )
+{
+ UNREFERENCED_PARAMETER(Argc);
+ UNREFERENCED_PARAMETER(Argv);
+
+ SERVICE_TABLE_ENTRY serviceTable[] =
+ {
+ { SERVICE_NAME, ServiceMain },
+ { NULL, NULL }
+ };
+
+ return StartServiceCtrlDispatcher(serviceTable);
+}
+
+VOID WINAPI ServiceMain(
+ DWORD Argc,
+ PWSTR *Argv
+ )
+{
+ DWORD Err = ERROR_SUCCESS;
+
+ UNREFERENCED_PARAMETER(Argc);
+ UNREFERENCED_PARAMETER(Argv);
+
+ //
+ // Initialize global variables
+ //
+ InitializeDeviceListHead(&DeviceList);
+
+#ifdef DEBUG_SUPPORT
+
+ while (!IsDebuggerPresent()) {
+ Sleep(1000);
+ }
+
+ __debugbreak();
+
+#endif
+
+ SvcStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME,
+ ServiceCtrlHandler);
+
+ if (SvcStatusHandle == NULL)
+ {
+ Err = GetLastError();
+ goto cleanup;
+ }
+
+ UpdateServiceStatus(SvcStatusHandle,
+ SERVICE_START_PENDING,
+ ERROR_SUCCESS);
+
+ //
+ // Setup device interface context
+ //
+ Err = SetupDeviceInterfaceContext();
+
+ UpdateServiceStatus(SvcStatusHandle,
+ SERVICE_START_PENDING,
+ ERROR_SUCCESS);
+
+ //
+ // Initialize device control
+ //
+ OsrFx2InitializeDevice();
+
+ //
+ // Register callback function for stop event
+ //
+ SvcStopRequestEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ if (SvcStopRequestEvent == NULL)
+ {
+ Err = GetLastError();
+ goto cleanup;
+ }
+
+ if (!RegisterWaitForSingleObject(&SvcStopWaitObject,
+ SvcStopRequestEvent,
+ ServiceStopCallback,
+ NULL,
+ INFINITE,
+ WT_EXECUTEONLYONCE | WT_EXECUTEINPERSISTENTTHREAD))
+ {
+ Err = GetLastError();
+ goto cleanup;
+ }
+
+ //
+ // Create stopped event for the running worker thread
+ //
+ SvcStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ if (SvcStoppedEvent == NULL)
+ {
+ Err = GetLastError();
+ goto cleanup;
+ }
+
+ UpdateServiceStatus(SvcStatusHandle,
+ SERVICE_START_PENDING,
+ ERROR_SUCCESS);
+
+ //
+ // Queue the main service function for execution in a worker thread.
+ //
+ QueueUserWorkItem(&ServiceRunningWorkerThread,
+ NULL,
+ WT_EXECUTELONGFUNCTION);
+
+ UpdateServiceStatus(SvcStatusHandle,
+ SERVICE_RUNNING,
+ ERROR_SUCCESS);
+
+cleanup:
+
+ if (Err != ERROR_SUCCESS)
+ {
+ ServiceStop(Err);
+ }
+}
+
+VOID
+WINAPI
+ServiceCtrlHandler(
+ DWORD Ctrl
+ )
+{
+ switch (Ctrl)
+ {
+ case SERVICE_CONTROL_STOP:
+ //
+ // Set service stop event
+ //
+ UpdateServiceStatus(SvcStatusHandle, SERVICE_STOP_PENDING, ERROR_SUCCESS);
+ SetEvent(SvcStopRequestEvent);
+ break;
+
+ default:
+ break;
+ }
+}
+
+#define SERVICE_WAIT_HINT_TIME 30000 // 30 seconds
+
+BOOL
+UpdateServiceStatus(
+ __in_opt SERVICE_STATUS_HANDLE hSvcHandle,
+ __in DWORD dwCurrentState,
+ __in DWORD dwWin32ExitCode
+ )
+{
+ SERVICE_STATUS SvcStatus;
+
+ static DWORD dwCheckPoint = 1;
+
+ SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ SvcStatus.dwCurrentState = dwCurrentState;
+ SvcStatus.dwWin32ExitCode = dwWin32ExitCode;
+ SvcStatus.dwServiceSpecificExitCode = ERROR_SUCCESS;
+
+ if (dwCurrentState == SERVICE_START_PENDING)
+ {
+ SvcStatus.dwControlsAccepted = 0;
+ }
+ else
+ {
+ SvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
+ }
+
+ if ((dwCurrentState == SERVICE_RUNNING) ||
+ (dwCurrentState == SERVICE_STOPPED))
+ {
+ SvcStatus.dwCheckPoint = 0;
+ SvcStatus.dwWaitHint = 0;
+ }
+ else
+ {
+ SvcStatus.dwCheckPoint = dwCheckPoint++;
+ SvcStatus.dwWaitHint = SERVICE_WAIT_HINT_TIME;
+ }
+
+ return SetServiceStatus(hSvcHandle, &SvcStatus);
+}
+
+DWORD
+WINAPI
+ServiceRunningWorkerThread(
+ _In_ PVOID lpThreadParameter
+ )
+{
+ PDEVICE_CONTEXT DeviceContext = NULL;
+ PDEVICE_LIST_ENTRY Link = NULL;
+
+ UNREFERENCED_PARAMETER(lpThreadParameter);
+
+ InterlockedOr(&SvcControlFlags, SERVICE_FLAGS_RUNNING);
+
+ //
+ // Periodically check if the service is stopping.
+ //
+ while ((InterlockedOr(&SvcControlFlags, 0) & SERVICE_FLAGS_RUNNING) != 0)
+ {
+ AcquireSRWLockShared(&DeviceListLock);
+
+ for (Link = DeviceList.Flink; Link != &DeviceList; Link = Link->Flink)
+ {
+ DeviceContext = CONTAINING_DEVICE_RECORD(Link);
+
+ OsrFx2ControlDevice(DeviceContext);
+ }
+
+ ReleaseSRWLockShared(&DeviceListLock);
+
+ Sleep(2000); // Simulate some lengthy operations.
+ }
+
+ //
+ // Signal the stopped event.
+ //
+ SetEvent(SvcStoppedEvent);
+
+ return 0;
+}
+
+VOID
+CALLBACK
+ServiceStopCallback(
+ _In_ PVOID lpParameter,
+ _In_ BOOLEAN TimerOrWaitFired
+ )
+{
+ UNREFERENCED_PARAMETER(TimerOrWaitFired);
+
+ //
+ // Since wait object can not be unregistered in callback function, queue
+ // another thread
+ //
+ QueueUserWorkItem(ServiceStopWorkerThread,
+ lpParameter,
+ WT_EXECUTEDEFAULT);
+}
+
+DWORD
+WINAPI
+ServiceStopWorkerThread(
+ _In_ PVOID lpThreadParameter
+ )
+{
+ UNREFERENCED_PARAMETER(lpThreadParameter);
+
+ ServiceStop(ERROR_SUCCESS);
+
+ return 0;
+}
+
+VOID
+ServiceStop(
+ _In_ DWORD ExitCode
+ )
+{
+ if (SvcStatusHandle == NULL)
+ {
+ return;
+ }
+
+ UpdateServiceStatus(SvcStatusHandle, SERVICE_STOP_PENDING, ExitCode);
+
+ //
+ // Notify the working thread to stop
+ //
+ if ((InterlockedOr(&SvcControlFlags, 0) & SERVICE_FLAGS_RUNNING) != 0)
+ {
+ InterlockedAnd(&SvcControlFlags, ~SERVICE_FLAGS_RUNNING);
+ WaitForSingleObject(SvcStoppedEvent, INFINITE);
+ }
+
+ //
+ // Clean up device context after the worker thread has finished.
+ //
+ CleanupDeviceInterfaceContext();
+
+ //
+ // cleanup work
+ //
+ if (SvcStopWaitObject != NULL)
+ {
+ UnregisterWait(SvcStopWaitObject);
+ }
+
+ if (SvcStopRequestEvent != NULL)
+ {
+ CloseHandle(SvcStopRequestEvent);
+ }
+
+ if (SvcStoppedEvent != NULL)
+ {
+ CloseHandle(SvcStoppedEvent);
+ }
+
+ UpdateServiceStatus(SvcStatusHandle, SERVICE_STOPPED, ExitCode);
+}
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.h
new file mode 100644
index 00000000..e469ca9d
--- /dev/null
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.h
@@ -0,0 +1,56 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+--*/
+
+#pragma once
+
+VOID
+WINAPI
+ServiceMain(
+ DWORD Argc,
+ PWSTR *Argv
+ );
+
+VOID
+WINAPI
+ServiceCtrlHandler(
+ DWORD Ctrl
+ );
+
+BOOL
+UpdateServiceStatus(
+ __in_opt SERVICE_STATUS_HANDLE hSvcHandle,
+ __in DWORD dwCurrentState,
+ __in DWORD dwWin32ExitCode
+ );
+
+VOID
+CALLBACK
+ServiceStopCallback(
+ _In_ PVOID lpParameter,
+ _In_ BOOLEAN TimerOrWaitFired
+ );
+
+VOID
+ServiceStop(
+ _In_ DWORD ExitCode
+ );
+
+DWORD
+WINAPI
+ServiceRunningWorkerThread(
+ _In_ PVOID lpThreadParameter
+ );
+
+DWORD
+WINAPI
+ServiceStopWorkerThread(
+ _In_ PVOID lpThreadParameter
+ );
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ThreadPool.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ThreadPool.h
deleted file mode 100644
index 3d851537..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ThreadPool.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/****************************** Module Header ******************************\
-* Module Name: ThreadPool.h
-* Project: CppWindowsService
-* Copyright (c) Microsoft Corporation.
-*
-* The class was designed by Kenny Kerr. It provides the ability to queue
-* simple member functions of a class to the Windows thread pool.
-*
-* Using the thread pool is simple and feels natural in C++.
-*
-* class CSampleService
-* {
-* public:
-*
-* void AsyncRun()
-* {
-* CThreadPool::QueueUserWorkItem(&Service::Run, this);
-* }
-*
-* void Run()
-* {
-* // Some lengthy operation
-* }
-* };
-*
-* Kenny Kerr spends most of his time designing and building distributed
-* applications for the Microsoft Windows platform. He also has a particular
-* passion for C++ and security programming. Reach Kenny at
-* http://weblogs.asp.net/kennykerr/ or visit his Web site:
-* http://www.kennyandkarin.com/Kenny/.
-*
-* This source is subject to the Microsoft Public License.
-* See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
-* All other rights reserved.
-*
-* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
-* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
-* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
-\***************************************************************************/
-
-#pragma once
-
-#include <memory>
-
-
-class CThreadPool
-{
-public:
-
- template <typename T>
- static void QueueUserWorkItem(void (T::*function)(void),
- T *object, ULONG flags = WT_EXECUTELONGFUNCTION)
- {
- typedef std::pair<void (T::*)(), T *> CallbackType;
- std::auto_ptr<CallbackType> p(new CallbackType(function, object));
-
- if (::QueueUserWorkItem(ThreadProc<T>, p.get(), flags))
- {
- // The ThreadProc now has the responsibility of deleting the pair.
- p.release();
- }
- else
- {
- throw GetLastError();
- }
- }
-
-private:
-
- template <typename T>
- static DWORD WINAPI ThreadProc(PVOID context)
- {
- typedef std::pair<void (T::*)(), T *> CallbackType;
-
- std::auto_ptr<CallbackType> p(static_cast<CallbackType *>(context));
-
- (p->second->*p->first)();
- return 0;
- }
-}; \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.cpp
deleted file mode 100644
index e8fc87ee..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation. All rights reserved.
-
- THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
- PURPOSE.
-
-Module Name:
-
- Utils.cpp
-
-Abstract:
-
- Provides utility function to SampleApp.cpp.
-
-Environment:
-
- User mode
-
---*/
-
-#include "Utils.h"
-
-//
-// Service trace event provider
-// {54a25c42-cd91-4210-98cc-c3447b56e447}
-//
-EXTERN_C __declspec(selectany) const GUID SERVICE_PROVIDER_GUID = { 0x54a25c42, 0xcd91, 0x4210,{ 0x98, 0xcc, 0xc3, 0x44, 0x7b, 0x56, 0xe4, 0x47 } };
-
-REGHANDLE m_etwRegHandle;
-
-
-/*++
-
-Routine Description:
-
- Sets up logging.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-SetupEvents()
-{
- NTSTATUS status = EventRegister(&SERVICE_PROVIDER_GUID,
- nullptr,
- nullptr,
- &m_etwRegHandle);
-
- if (status != ERROR_SUCCESS)
- {
- wprintf(L"Provider not registered. EventRegister failed with error: 0x%08X\n", status);
- }
-}
-
-
-/*++
-
-Routine Description:
-
- Destroys logging.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-DestroyEvents()
-{
- if (m_etwRegHandle != NULL)
- {
- EventUnregister(m_etwRegHandle);
- }
-}
-
-
-/*++
-
-Routine Description:
-
- Log a message.
-
-Arguments:
-
- Message - The string message to be logged
-
- Level - The type of event to be logged. This parameter can
- be one of the following values:
-
- TRACE_LEVEL_CRITICAL
- TRACE_LEVEL_ERROR
- TRACE_LEVEL_WARNING
- TRACE_LEVEL_INFORMATION
- TRACE_LEVEL_VERBOSE
-
-Return Value:
-
- VOID
-
---*/
-VOID
-WriteToEventLog(
- PWSTR Message,
- BYTE Level
- )
-{
- if (m_etwRegHandle != NULL)
- {
- EventWriteString(m_etwRegHandle, Level, 0, Message);
- }
-}
-
-
-/*++
-
-Routine Description:
-
- Log an error message.
-
-Arguments:
-
- Function - The function that gives the error
-
- Error - The error code
-
-Return Value:
-
- VOID
-
---*/
-VOID
-WriteToErrorLog(
- PWSTR Function,
- DWORD Error
- )
-{
- WCHAR Message[260];
-
- StringCchPrintf(Message, ARRAYSIZE(Message),
- L"%ws failed with error: 0x%08x", Function, Error);
-
- WriteToEventLog(Message, TRACE_LEVEL_ERROR);
-} \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.h
deleted file mode 100644
index b619f461..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*++
-
-Copyright (c) Microsoft Corporation. All rights reserved.
-
- THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
- PURPOSE.
-
-Module Name:
-
- Utils.cpp
-
-Abstract:
-
- Provides utility function to SampleApp.cpp.
-
-Environment:
-
- User mode
-
---*/
-
-#pragma once
-
-#include <Windows.h>
-#include <strsafe.h>
-#include <evntprov.h>
-#include <evntrace.h>
-
-/*++
-
-Routine Description:
-
- Sets up logging.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID SetupEvents();
-
-
-/*++
-
-Routine Description:
-
- Destroys logging.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID DestroyEvents();
-
-
-/*++
-
-Routine Description:
-
- Log a message.
-
-Arguments:
-
- Message - The string message to be logged
-
- Level - The type of event to be logged. This parameter can
- be one of the following values:
-
- TRACE_LEVEL_CRITICAL
- TRACE_LEVEL_ERROR
- TRACE_LEVEL_WARNING
- TRACE_LEVEL_INFORMATION
- TRACE_LEVEL_VERBOSE
-
-Return Value:
-
- VOID
-
---*/
-VOID WriteToEventLog(PWSTR Message, BYTE Level);
-
-
-/*++
-
-Routine Description:
-
- Log an error message.
-
-Arguments:
-
- Function - The function that gives the error
-
- Error - The error code
-
-Return Value:
-
- VOID
-
---*/
-VOID WriteToErrorLog(PWSTR Function, DWORD Error); \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.inx b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.inx
deleted file mode 100644
index 61e1e958..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.inx
+++ /dev/null
Binary files differ
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj
index 6965d745..60174c56 100644
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj
@@ -23,7 +23,7 @@
<RootNamespace>osrfx2_DCHU_usersvc</RootNamespace>
<Keyword>Win32Proj</Keyword>
<ProjectName>osrfx2_DCHU_usersvc</ProjectName>
- <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
+ <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
@@ -93,14 +93,13 @@
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
- <Optimization>Full</Optimization>
+ <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
- <WarningLevel>Level3</WarningLevel>
+ <WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
<Link>
@@ -108,11 +107,11 @@
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalDependencies>onecoreuap.lib;%(AdditionalDependencies);</AdditionalDependencies>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
- <Optimization>Full</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
@@ -121,6 +120,7 @@
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <Optimization>Full</Optimization>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -138,8 +138,7 @@
<ClCompile>
<Optimization>Full</Optimization>
<PreprocessorDefinitions>WIN32;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <MinimalRebuild>true</MinimalRebuild>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <BasicRuntimeChecks>Default</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
@@ -182,18 +181,15 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
- <ClCompile Include="CppWindowsService.cpp" />
- <ClCompile Include="SampleService.cpp" />
- <ClCompile Include="ServiceBase.cpp" />
- <ClCompile Include="Main.cpp" />
- <ClCompile Include="Utils.cpp" />
+ <ClCompile Include="DeviceControl.cpp" />
+ <ClCompile Include="DeviceContext.cpp" />
+ <ClCompile Include="ServiceWin32API.cpp" />
</ItemGroup>
<ItemGroup>
- <ClInclude Include="SampleService.h" />
- <ClInclude Include="ServiceBase.h" />
- <ClInclude Include="Main.h" />
- <ClInclude Include="ThreadPool.h" />
- <ClInclude Include="Utils.h" />
+ <ClInclude Include="DeviceControl.h" />
+ <ClInclude Include="DeviceContext.h" />
+ <ClInclude Include="stdafx.h" />
+ <ClInclude Include="ServiceWin32API.h" />
</ItemGroup>
<ItemGroup>
<None Include="Documentation\ReadMe.htm">
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/stdafx.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/stdafx.h
new file mode 100644
index 00000000..7bd67951
--- /dev/null
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/stdafx.h
@@ -0,0 +1,26 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+--*/
+
+#pragma once
+
+#include <Windows.h>
+#include <strsafe.h>
+
+//
+// Device context
+//
+#include <cfgmgr32.h>
+
+#include <initguid.h>
+
+#include "ServiceWin32API.h"
+#include "DeviceContext.h"
+#include "DeviceControl.h"
diff --git a/general/PLX9x5x/README.md b/general/PLX9x5x/README.md
index 8f57513e..85997777 100644
--- a/general/PLX9x5x/README.md
+++ b/general/PLX9x5x/README.md
@@ -5,32 +5,24 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: PLX9x5x PCI Driver
- platform: KMDF
- language: cpp
- category: General PCI WDF
- description: Demonstrates how to write a driver for a generic PCI device using Windows Driver Frameworks (WDF).
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617719
---->
-
# PLX9x5x PCI Driver
-This sample demonstrates how to write driver for a generic PCI device using Windows Driver Framework. The target hardware for this driver is PLX9656/9653RDK-LITE board. The product kit and the hardware specification are available at <http://www.plxtech.com>.
+This sample demonstrates how to write driver for a generic PCI device using Windows Driver Framework. The target hardware for this driver is PLX9656/9653RDK-LITE board. The product kit and the hardware specification are available at the [PLX Technology](https://www.plxtech.com) website.
-For more information, see [Peripheral Component Interconnect (PCI) Bus Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff537451).
+For more information, see the [PCI driver programming guide](https://docs.microsoft.com/windows-hardware/drivers/pci/).
-The device is a PCI device with port, memory, interrupt and DMA resources. Device can be stopped and started at run-time and also supports low power states. The driver is capable of doing concurrent read and write operations to the device but it can handle only one read or write request at any time. The following lists the driver framework interfaces demonstrated in this sample:
+The device is a PCI device with port, memory, interrupt and DMA resources. The device can be stopped and started at run-time and also supports low power states. The driver is capable of doing concurrent read and write operations to the device but it can handle only one read or write request at any time. The following driver framework interfaces are demonstrated in this sample:
-- Handling PnP & Power Events
+- Handling PnP and Power Events
- Registering a Device Interface
-- Hardware resource mapping: Port, Memory & Interrupt
+- Hardware resource mapping: Port, Memory, and Interrupt
- DMA Interfaces
- Serialized Default Queue for Write requests
- Serialized custom Queue for Read requests
-- Handling Interrupt & DPC
+- Handling Interrupt and DPC
To test the driver, run the PLX.EXE test application.
diff --git a/general/SimpleMediaSource/README.md b/general/SimpleMediaSource/README.md
index ca8e85da..4467f16b 100644
--- a/general/SimpleMediaSource/README.md
+++ b/general/SimpleMediaSource/README.md
@@ -1,33 +1,32 @@
-<!---
- name: SimpleMediaSource Sample
- platform: UMDF2
- language: cpp
- category: general
- description: Demonstrates how to write a custom media source and driver package.
- samplefwlink:
---->
+---
+page_type: sample
+description: "Demonstrates how to write a custom media source and driver package."
+languages:
+- cpp
+products:
+- windows
+- windows-wdk
+---
-SimpleMediaSource Sample
-========================
-This sample demonstrates how to create a custom media source and driver package that can be installed as a Camera and produce frames.
+# SimpleMediaSource sample
-This sample has accompanying documentation here: https://docs.microsoft.com/en-us/windows-hardware/drivers/stream/frame-server-custom-media-source
+This sample demonstrates how to create a custom media source and driver package that can be installed as a camera and produce frames.
+For more information, see the accompanying documentation at [Frame Server Custom Media Source](https://docs.microsoft.com/windows-hardware/drivers/stream/frame-server-custom-media-source).
-Contents
---------
-MediaSource - COM DLL project for the custom media source
-SimpleMediaSourceDriver - UMDF driver install package
+## Contents
-Installation
-------------------
+- MediaSource - COM DLL project for the custom media source
+- SimpleMediaSourceDriver - UMDF driver install package
+
+## Installation
1. Build the solution.
-2. Navigate to the output folder, e.g. Windows-driver-samples\general\SimpleMediaSource\x64\Release, and the driver package will be in a directory also called SimpleMediaSourceDriver. Check that the folder has `SimpleMediaSource.dll`, `simplemediasourcedriver.cat`, `SimpleMediaSourceDriver.dll`, and `SimpleMediaSourceDriver.inf`.
+1. Navigate to the output folder, e.g. Windows-driver-samples\general\SimpleMediaSource\x64\Release, and the driver package will be in a directory also called SimpleMediaSourceDriver. Check that the folder has `SimpleMediaSource.dll`, `simplemediasourcedriver.cat`, `SimpleMediaSourceDriver.dll`, and `SimpleMediaSourceDriver.inf`.
-3. Deploy the driver package with
+1. Deploy the driver package with the following command:
-`devcon dp_add SimpleMediaSourceDriver.inf`
+ `devcon dp_add SimpleMediaSourceDriver.inf`
-4. In Device Manager, locate **SimpleMediaSource Capture Source**, under the Camera category. Open the Microsoft Camera App, switch cameras if necessary until the camera is streaming from the SimpleMediaSource. You should see a scrolling black and white gradient. \ No newline at end of file
+1. In Device Manager, locate **SimpleMediaSource Capture Source**, under the Camera category. Open the Microsoft Camera App, switch cameras if necessary until the camera is streaming from the SimpleMediaSource. You should see a scrolling black and white gradient.
diff --git a/general/SimpleMediaSource/general-SimpleMediaSource.yaml b/general/SimpleMediaSource/general-SimpleMediaSource.yaml
deleted file mode 100644
index 0a7443ed..00000000
--- a/general/SimpleMediaSource/general-SimpleMediaSource.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-### YamlMime:Sample
-sample:
-- name: SimpleMediaSource Sample
- description: Demonstrates how to write a custom media source and driver package.
- generateZip: true
- author: windows-driver-samples
- languages:
-- cpp
- technologies:
-- windows
diff --git a/general/SystemDma/wdm/README.md b/general/SystemDma/wdm/README.md
index e276d13c..43770319 100644
--- a/general/SystemDma/wdm/README.md
+++ b/general/SystemDma/wdm/README.md
@@ -5,24 +5,17 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: System DMA sample
- platform: WDM
- language: cpp
- category: General
- description: Demonstrates how a driver could use a system DMA controller to write data to a hardware location using V3 System DMA.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617722
---->
-
# System DMA
This sample demonstrates the usage of V3 System DMA. It shows how a driver could use a system DMA controller supported by Windows to write data to a hardware location using DMA.
-The sample consists of a legacy device driver and a Win32 console mode test application. The test application opens a handle to the device exposed by the driver and makes a DeviceIoControl call to initiate the example system DMA. To understand how the V3 system DMA calls are invoked please study SDmaWrite() in SDma.c.
+The sample consists of a legacy device driver and a Win32 console mode test application. The test application opens a handle to the device exposed by the driver and makes a DeviceIoControl call to initiate the example system DMA. To understand how the V3 system DMA calls are invoked, see the SDmaWrite function in sdma.c.
-**Note** This sample driver is not a PnP driver. This is a minimal driver meant to demonstrate an OS feature. Neither it nor its sample programs are intended for use in a production environment. Rather, they are intended for educational purposes and as a skeleton driver.
+> [!NOTE]
+> This sample driver is not a PnP driver. This is a minimal driver meant to demonstrate an OS feature. Neither it nor its sample programs are intended for use in a production environment. Rather, they are intended for educational purposes and as a skeleton driver.
## Run the sample
diff --git a/general/WinHEC 2017 Lab/README.md b/general/WinHEC 2017 Lab/README.md
index af806555..eda72f91 100644
--- a/general/WinHEC 2017 Lab/README.md
+++ b/general/WinHEC 2017 Lab/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: WinHEC 2017 Lab
- platform: KMDF
- language: cpp
- category: Network
- description: WinHEC 2017 Lab
- samplefwlink: https://go.microsoft.com/fwlink/p/?linkid=869054
---->
-
# WinHEC 2017 Lab
-Toaster samples from the WinHEC 2017 Lab: Toaster Driver, PlugInToaster, and Toaster Support App. \ No newline at end of file
+Toaster samples from the WinHEC 2017 Lab: Toaster Driver, PlugInToaster, and Toaster Support App.
diff --git a/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.c b/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.c
index 6ed215db..7b117240 100644
--- a/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.c
+++ b/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.c
@@ -72,7 +72,7 @@ Return Value:
KdPrint(("Toaster Function Driver Sample - Driver Framework Edition.\n"));
//
- // Initiialize driver config to control the attributes that
+ // Initialize driver config to control the attributes that
// are global to the driver. Note that framework by default
// provides a driver unload routine. If DriverEntry creates any resources
// that require clean-up in driver unload,
diff --git a/general/cancel/README.md b/general/cancel/README.md
index 110482d3..a45e145e 100644
--- a/general/cancel/README.md
+++ b/general/cancel/README.md
@@ -5,20 +5,12 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Cancel-Safe IRP Queue Sample
- platform: WDM
- language: cpp
- category: General
- description: Demonstrates the use of the cancel-safe queue routines.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617705
---->
-
# Cancel-Safe IRP Queue Sample
-This sample demonstrates the use of the cancel-safe queue routines [**IoCsqInitialize**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549054), [**IoCsqInsertIrp**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549066), [**IoCsqRemoveIrp**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549070), [**IoCsqRemoveNextIrp**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549072). These routines were introduced in Windows for queuing IRPs in the driver's internal device queue. By using these routines, driver developers do not have to worry about IRP cancellation race conditions. A common problem with cancellation of IRPs in a driver is synchronization between the cancel lock or the InterlockedExchange in the I/O Manager with the driver's queue lock. The **IoCsq*Xxx*** routines abstract the cancel logic while allowing the driver to implement the queue and associated synchronization.
+This sample demonstrates the use of the cancel-safe queue routines [**IoCsqInitialize**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/nf-wdm-iocsqinitialize), [**IoCsqInsertIrp**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/nf-wdm-iocsqinsertirp), [**IoCsqRemoveIrp**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/nf-wdm-iocsqremoveirp), [**IoCsqRemoveNextIrp**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/nf-wdm-iocsqremovenextirp). These routines were introduced in Windows for queuing IRPs in the driver's internal device queue. By using these routines, driver developers do not have to worry about IRP cancellation race conditions. A common problem with cancellation of IRPs in a driver is synchronization between the cancel lock or the InterlockedExchange in the I/O Manager with the driver's queue lock. The **IoCsq*Xxx*** routines abstract the cancel logic while allowing the driver to implement the queue and associated synchronization.
The sample is accompanied by a simple multithreaded Win32 console application to stress-test the driver's cancel and cleanup routines.
@@ -26,9 +18,9 @@ This driver is written for an hypothetical data-acquisition device that requires
This sample driver is not a Plug and Play driver. This is a minimal driver meant to demonstrate a feature of the operating system. Neither this driver nor its sample programs are intended for use in a production environment. Instead, they are intended for educational purposes and as a skeleton driver.
-Look in the Startio directory for another version of the sample driver that shows how to use cancel-safe IRP queues to implement I/O queuing functionality similar to the [**IoStartPacket**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff550370) and [**IoStartNextPacket**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff550358) routines. The same test application works with this driver as well.
+Look in the Startio directory for another version of the sample driver that shows how to use cancel-safe IRP queues to implement I/O queuing functionality similar to the [**IoStartPacket**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ntifs/nf-ntifs-iostartpacket) and [**IoStartNextPacket**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ntifs/nf-ntifs-iostartnextpacket) routines. The same test application works with this driver as well.
-For more information, see [Cancel-Safe IRP Queues](http://msdn.microsoft.com/en-us/library/windows/hardware/ff540755).
+For more information, see [Cancel-Safe IRP Queues](https://docs.microsoft.com/windows-hardware/drivers/kernel/cancel-safe-irp-queues).
## Run the sample
@@ -36,4 +28,5 @@ To test this driver, run Testapp.exe, which is a simple Win32 multithreaded cons
`Usage: testapp <NumberOfThreads>`
-**Note** The `NumberOfThreads` command-line parameter is limited to a maximum of 10 threads; the default value if no parameter is specified is 1. The main thread waits for user input. If you press Q, the application exits gracefully; otherwise, it exits the process abruptly and forces all the threads to be terminated and all pending I/O operations to be canceled. Other threads perform I/O asynchronously in a loop. After every overlapped read, the thread goes into an alertable sleep and wakes as soon as the completion routine runs, which occurs when the driver completes the read IRP. You should run multiple instances of the application to stress test the driver.
+> [!NOTE]
+> The `NumberOfThreads` command-line parameter is limited to a maximum of 10 threads; the default value if no parameter is specified is 1. The main thread waits for user input. If you press Q, the application exits gracefully; otherwise, it exits the process abruptly and forces all the threads to be terminated and all pending I/O operations to be canceled. Other threads perform I/O asynchronously in a loop. After every overlapped read, the thread goes into an alertable sleep and wakes as soon as the completion routine runs, which occurs when the driver completes the read IRP. You should run multiple instances of the application to stress test the driver.
diff --git a/general/echo/kmdf/README.md b/general/echo/kmdf/README.md
index 2827d357..2118e3e5 100644
--- a/general/echo/kmdf/README.md
+++ b/general/echo/kmdf/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: KMDF Echo Sample
- platform: KMDF
- language: cpp
- category: General WDF
- description: Demonstrates how to use a sequential queue to serialize read and write requests presented to the driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617706
---->
-
# KMDF Echo Sample
The ECHO (KMDF) sample demonstrates how to use a sequential queue to serialize read and write requests presented to the driver.
@@ -28,7 +20,7 @@ This sample builds a Universal Windows Driver. It uses only APIs and DDIs that a
## Related technologies
-[Kernel-Mode Driver Framework](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544396)
+[Kernel-Mode Driver Framework](https://docs.microsoft.com/windows-hardware/drivers/kernel/)
## Code Tour
@@ -50,48 +42,29 @@ Since the queue is a sequential queue, only one request is outstanding in the dr
**Usage:**
-Echoapp.exe --- Send single write and read request synchronously
+- Echoapp.exe --- Send single write and read request synchronously
-Echoapp.exe -Async --- Send 100 reads and writes asynchronously
+- Echoapp.exe -Async --- Send 100 reads and writes asynchronously
Exit the app anytime by pressing Ctrl-C
## File Manifest
-File
-
-Description
-
-Echo.htm
-
-Documentation for this sample (this file).
-
-***(The AutoSync and DriverSync versions of the sample each have their own version of the following files)***
+> [!NOTE]
+> The AutoSync and DriverSync versions of the sample each have their own version of the following files:
Driver.h, Driver.c
-DriverEntry and Events on the Driver Object.
+- DriverEntry and Events on the Driver Object.
Device.h, Device.c
-Events on the Device Object.
+- Events on the Device Object.
Queue.h, Queue.c
-Contains Events on the I/O Queue Objects.
+- Contains Events on the I/O Queue Objects.
Echo.inx
-File that describes the installation of this driver. The build process converts this into an INF file.
-
-Makefile.inc
-
-A makefile that defines custom build actions. This includes the conversion of the .INX file into a .INF file
-
-Makefile
-
-This file merely redirects to the real makefile that is shared by all the driver components of the Windows NT DDK.
-
-Sources
-
-Generic file that lists source files and all the build options.
+- File that describes the installation of this driver. The build process converts this into an INF file.
diff --git a/general/echo/kmdf/driver/AutoSync/queue.c b/general/echo/kmdf/driver/AutoSync/queue.c
index d881c003..7e2e915f 100644
--- a/general/echo/kmdf/driver/AutoSync/queue.c
+++ b/general/echo/kmdf/driver/AutoSync/queue.c
@@ -423,7 +423,7 @@ Return Value:
queueContext->Length = 0L;
}
- queueContext->Buffer = ExAllocatePoolWithTag(NonPagedPoolNx, Length, 'sam1');
+ queueContext->Buffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, Length, 'sam1');
if( queueContext->Buffer == NULL ) {
KdPrint(("EchoEvtIoWrite: Could not allocate %Iu byte buffer\n", Length));
WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES);
diff --git a/general/echo/kmdf/driver/DriverSync/queue.c b/general/echo/kmdf/driver/DriverSync/queue.c
index 7835b73b..1b34b616 100644
--- a/general/echo/kmdf/driver/DriverSync/queue.c
+++ b/general/echo/kmdf/driver/DriverSync/queue.c
@@ -649,7 +649,7 @@ Return Value:
queueContext->Length = 0L;
}
- queueContext->Buffer = ExAllocatePoolWithTag(NonPagedPoolNx, Length, 'sam1');
+ queueContext->Buffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, Length, 'sam1');
if( queueContext->Buffer == NULL ) {
KdPrint(("EchoEvtIoWrite: Could not allocate %Iu byte buffer\n",Length));
WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES);
diff --git a/general/echo/umdf/README.md b/general/echo/umdf/README.md
index b4accf05..241e633d 100644
--- a/general/echo/umdf/README.md
+++ b/general/echo/umdf/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Echo Sample (UMDF Version 1)
- platform: UMDF1
- language: cpp
- category: General WDF
- description: Demonstrates how to use UMDF version 1 to write a driver and demonstrates best practices.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617707
---->
-
# Echo Sample (UMDF Version 1)
This sample demonstrates how to use User-Mode Driver Framework (UMDF) version 1 to write a driver and demonstrates best practices.
@@ -24,13 +16,11 @@ It also demonstrates the use of a default Serial Dispatch I/O Queue, its request
This sample driver is a minimal driver meant to demonstrate the usage of the User-Mode Driver Framework. It is not intended for use in a production environment.
-Related technologies
---------------------
+## Related technologies
-[User-Mode Driver Framework](http://msdn.microsoft.com/en-us/library/windows/hardware/ff560456)
+[User-Mode Driver Framework](https://docs.microsoft.com/windows-hardware/drivers/wdf/getting-started-with-umdf-version-2)
-Testing
--------
+## Testing
To test the Echo driver, you can run echoapp.exe which is built from \\echo\\exe.
@@ -42,14 +32,14 @@ Usage:
Echoapp.exe --- Send single write and read request synchronously
Echoapp.exe -Async --- Send 100 reads and writes asynchronously
Exit the app anytime by pressing Ctrl-C
-
+
D:\>echoapp
DevicePath: \\?\root#sample#0000#{cdc35b6e-0be4-4936-bf5f-5537380a7c1a}
Opened device successfully
512 Pattern Bytes Written successfully
512 Pattern Bytes Read successfully
Pattern Verified successfully
-
+
D:\>echoapp -Async
DevicePath: \\?\root#sample#0000#{cdc35b6e-0be4-4936-bf5f-5537380a7c1a}
Opened device successfully
@@ -81,52 +71,50 @@ Number of bytes written by request number 11 is 1024
Note that the reads and writes are performed by independent threads in the echo test application. As a result the order of the output may not exactly match what you see above.
-File Manifest
--------------
+## File Manifest
-**comsup.cpp & comsup.h**
+comsup.cpp and comsup.h
- COM Support code - specifically base classes which provide implementations for the standard COM interfaces IUnknown and IClassFactory which are used throughout this sample.
+
- The implementation of IClassFactory is designed to create instances of the CMyDriver class. If you should change the name of your base driver class, you would also need to modify this file.
-**dllsup.cpp**
+dllsup.cpp
- DLL Support code - provides the DLL's entry point as well as the single required export (DllGetClassObject).
+
- These depend on comsup.cpp to perform the necessary class creation.
-**exports.def**
+exports.def
- This file lists the functions that the driver DLL exports.
-**internal.h**
+internal.h
- This is the main header file for this driver.
-**Driver.cpp and Driver.h**
+Driver.cpp and Driver.h
- DriverEntry and events on the driver object.
-**Device.cpp and Device.h**
+Device.cpp and Device.h
- The Events on the device object.
-**Queue.cpp and Queue.h**
+Queue.cpp and Queue.h
- Contains Events on the I/O Queue Objects.
-**Echo.rc**
+Echo.rc
- Resource file for the driver.
-**WUDFEchoDriver.inx**
+WUDFEchoDriver.inx
- File that describes the installation of this driver. The build process converts this into an INF file.
-**makefile.inc**
-
-- A makefile that defines custom build actions. This includes the conversion of the .INX
-
-**echodriver.ctl**
+echodriver.ctl
- This file lists the WPP trace control GUID(s) for the sample driver. This file can be used with the tracelog command's -guid flag to enable the collection of these trace events within an established trace session.
+
- These GUIDs must remain in sync with the trace control GUIDs defined in internal.h.
diff --git a/general/echo/umdf2/README.md b/general/echo/umdf2/README.md
index efe606f7..6ddc0555 100644
--- a/general/echo/umdf2/README.md
+++ b/general/echo/umdf2/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Echo Sample (UMDF Version 2)
- platform: UMDF2
- language: cpp
- category: General WDF
- description: Demonstrates how to use UMDF 2 to write a driver and to employ best practices.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617708
---->
-
# Echo Sample (UMDF Version 2)
The ECHO (UMDF version 2) sample demonstrates how to use a sequential queue to serialize read and write requests presented to the driver.
@@ -26,28 +18,25 @@ It also shows how to synchronize execution of these events with other asynchrono
This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP.
-Related technologies
---------------------
+## Related technologies
+
+[User-Mode Driver Framework](https://docs.microsoft.com/windows-hardware/drivers/wdf/getting-started-with-umdf-version-2)
-[User-Mode Driver Framework](http://msdn.microsoft.com/en-us/library/windows/hardware/ff560456)
+## Build the sample with Visual Studio
-Open the driver solution in Visual Studio
------------------------------------------
+### Open the driver solution in Visual Studio
In Microsoft Visual Studio, open the solution file (umdf2echo.sln). Choose **Solution Explorer** from the **View** menu. In Solution Explorer, you can see one solution that contains three projects. There is a driver project (Driver-\>AutoSync-\>echo), an application project (Exe-\>echoapp), and a package project named **package** (lower case).
-Set the configuration and platform in Visual Studio
----------------------------------------------------
+### Set the configuration and platform in Visual Studio
In Visual Studio, in Solution Explorer, right click **Solution**, and choose **Configuration Manager**. Set the configuration and the platform. Make sure that the configuration and platform are the same for both the driver project and the package project. Do not check the **Deploy** boxes.
-Locate the built driver package
--------------------------------
+### Locate the built driver package
In File Explorer, navigate to the folder that contains your built driver package. The location of this folder varies depending on what you set for configuration and platform.
-Run the sample
---------------
+## Run the sample
The computer where you install the driver is called the *target computer* or the *test computer*. Typically this is a separate computer from where you develop and build the driver package. The computer where you develop and build the driver is called the *host computer*.
@@ -55,20 +44,23 @@ The process of moving the driver package to the target computer and installing t
### Automatic deployment (root enumerated)
-Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/).
+Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1).
1. On the host computer, in Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
+
1. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Hardware ID Driver Update**, and enter **root\\ECHO** for the hardware ID. Click **OK**.
+
1. On the **Build** menu, choose **Build Solution**.
### Manual deployment (root enumerated)
-Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
+Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](https://docs.microsoft.com/windows-hardware/drivers/devtest/devcon) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\umdf2echoPkg).
+
1. On the target computer, open a Command Prompt window as Administrator. Navigate to your driver package folder, and enter the following command:
- **devcon install echoum.inf root\\ECHO**
+ `devcon install echoum.inf root\\ECHO`
### View the root enumerated driver in Device Manager
@@ -76,11 +68,10 @@ On the target computer, in a Command Prompt window, enter **devmgmt** to open De
In Device Manager, on the **View** menu, choose **Devices by connection**. Locate **Sample WDF ECHO Driver** as a child of the root node of the device tree.
-Build the sample using MSBuild
-------------------------------
+## Build the sample using MSBuild
As an alternative to building the driver sample in Visual Studio, you can build it in a Visual Studio Command Prompt window. In Visual Studio, on the **Tools** menu, choose **Visual Studio Command Prompt**. In the Visual Studio Command Prompt window, navigate to the folder that has the solution file, umdf2echo.sln. Use the MSBuild command to build the solution. Here is an example:
-**msbuild /p:configuration="Release" /p:platform="Win32" umdf2echo.sln**
+`msbuild /p:configuration="Release" /p:platform="Win32" umdf2echo.sln`
-For more information about using MSBuild to build a driver package, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644).
+For more information about using MSBuild to build a driver package, see [MSBuild primer for WDK developers](https://docs.microsoft.com/windows-hardware/drivers/devtest/msbuild-primer-for-wdk-developers).
diff --git a/general/echo/umdfSocketEcho/README.md b/general/echo/umdfSocketEcho/README.md
index 71af4726..d4a6077f 100644
--- a/general/echo/umdfSocketEcho/README.md
+++ b/general/echo/umdfSocketEcho/README.md
@@ -5,41 +5,32 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: UMDF SocketEcho Sample (UMDF Version 1)
- platform: UMDF1
- language: cpp
- category: General WDF
- description: Demonstrates how to use UMDF version 1 to write a driver and demonstrates best practices.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617709
---->
-
# UMDF SocketEcho Sample (UMDF Version 1)
The UMDF SocketEcho sample demonstrates how to use the User-Mode Driver Framework (UMDF) to write a driver and demonstrates best practices.
This sample also demonstrates how to use a default parallel dispatch I/O queue, use a Microsoft Win32 dispatcher, and handle a socket handle by using a Win32 file I/O target.
-Related technologies
---------------------
+## Related technologies
-[User-Mode Driver Framework](http://msdn.microsoft.com/en-us/library/windows/hardware/ff560456)
+[User-Mode Driver Framework](https://docs.microsoft.com/windows-hardware/drivers/wdf/getting-started-with-umdf-version-2)
-Code Tour
----------
+## Code Tour
This sample driver is a minimal driver that is intended to demonstrate how to use UMDF. It is not intended for use in a production environment.
-- **CMyDriver::OnInitialize** in **driver.cpp** is called by the framework when the driver loads. This method initiates use of the Winsock Library.
+- **CMyDriver::OnInitialize** in **driver.cpp** is called by the framework when the driver loads. This method initiates use of the Winsock Library.
+
- **CMyDriver::OnDeviceAdd** in **driver.cpp** is called by the framework to install the driver on a device stack. OnDeviceAdd creates a device callback object, and then calls IWDFDriver::CreateDevice to create an framework device object and to associate the device callback object with the framework device object.
+
- **CMyQueue::OnCreateFile** in **queue.cpp** is called by the framework to create a socket connection, create a file i/o target that is associated with the socket handle for this connection, and store the socket handle in the file object context.
-Installation
-------------
+## Installation
-In Visual Studio, you can press F5 to build the sample and then deploy it to a target machine. For more information, see [Deploying a Driver to a Test Computer](http://msdn.microsoft.com/en-us/library/windows/hardware/hh454834). Alternatively, you can install the sample from the command line.
+In Visual Studio, you can press F5 to build the sample and then deploy it to a target machine. For more information, see [Deploying a Driver to a Test Computer](https://docs.microsoft.com/windows-hardware/drivers/develop/deploying-a-driver-to-a-test-computer). Alternatively, you can install the sample from the command line.
To test this sample, you must have a test computer. This test computer can be a second computer or, if necessary, your development computer.
@@ -49,11 +40,12 @@ To install the UMDF Echo sample driver from the command line, do the following:
1. Copy the UMDF coinstaller, WUDFUpdate\_*MMmmmm*.dll, from the \\redist\\wdf\\\<architecture\> directory to the same directory (for example, C:\\socketechoSample).
- **Note** You can obtain redistributable framework updates by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](http://go.microsoft.com/fwlink/p/?LinkID=226396). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0.
+ > [!NOTE]
+ > You can obtain redistributable framework updates by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](https://go.microsoft.com/fwlink/p/?LinkID=253170). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0.
1. Navigate to the directory that contains the INF file and binaries (for example, cd /d c:\\socketechoSample), and run DevCon.exe as follows:
- `devcon.exe install socketecho.inf WUDF\\socketecho`
+ `devcon.exe install socketecho.inf WUDF\\socketecho`
You can find DevCon.exe in the \\tools directory of the WDK (for example, \\tools\\devcon\\i386\\devcon.exe).
@@ -75,8 +67,7 @@ To test this sample drivers on a checked operating system that you have installe
1. If WdfCoinstaller*MMmmmm*.dll or WinUsbCoinstaller.dll is included in your driver package, repeat step 1 and step 2 for them.
-Testing
--------
+## Testing
To test the SocketEcho driver, you can run socketechoserver.exe, which is built from the \\echo\\umdfSocketEcho\\Exe directory, and echoapp.exe, which is built from the Kernel-Mode Driver Framework (KMDF) samples in the \\echo\\kmdf directory.
@@ -84,94 +75,72 @@ First, you must install the device as described earlier. Then, run socketechoser
`D:\\\>socketechoserver -h`
-Usage
-------
+## Usage
-```cmd
-socketechoserver Display Usage
+socketechoserver usage
-socketechoserver -h Display Usage
+```cmd
+D:\>socketechoserver -h
socketechoserver -p Start the app as server listening on default port
-
socketechoserver -p [port\#] Start the app as server listening on this port
-D:\\\>socketechoserver -p
+D:\>socketechoserver -p
Listening on socket...
+```
In another Command Prompt window, run echoapp.exe.
-D:\\\>echoapp
+```cmd
+D:\>echoapp
DevicePath: \\\\?\\root\#sample\#0000\#{ e5e65b0c-82c8-4689-96d4-f77837971990}
Opened device successfully
512 Pattern Bytes Written successfully
-
512 Pattern Bytes Read successfully
Pattern Verified successfully
-D:\\\>echoapp -Async
+D:\>echoapp -Async
-DevicePath: \\\\?\\root\#sample\#0000\#{cdc35b6e-0be4-4936-bf5f-5537380a7c1a}
+DevicePath: \\?\root\#sample\#0000\#{cdc35b6e-0be4-4936-bf5f-5537380a7c1a}
Opened device successfully
Starting AsyncIo
Number of bytes written by request number 0 is 1024
-
Number of bytes read by request number 0 is 1024
-
+Number of bytes written by request number 1 is 1024
Number of bytes read by request number 1 is 1024
-
Number of bytes written by request number 2 is 1024
-
Number of bytes read by request number 2 is 1024
-
Number of bytes written by request number 3 is 1024
-
Number of bytes read by request number 3 is 1024
-
Number of bytes written by request number 4 is 1024
-
Number of bytes read by request number 4 is 1024
-
Number of bytes written by request number 5 is 1024
-
Number of bytes read by request number 5 is 1024
-
Number of bytes written by request number 6 is 1024
-
Number of bytes read by request number 6 is 1024
-
Number of bytes written by request number 7 is 1024
-
Number of bytes read by request number 7 is 1024
-
Number of bytes written by request number 8 is 1024
-
Number of bytes read by request number 8 is 1024
-
Number of bytes written by request number 9 is 1024
-
Number of bytes read by request number 9 is 1024
-
Number of bytes written by request number 10 is 1024
-
Number of bytes read by request number 10 is 1024
-
Number of bytes written by request number 11 is 1024
-
...
```
-Note that independent threads perform the reads and writes in the echo test application. As a result, the order of the output might not exactly match what you see in the preceding output.
+> [!NOTE]
+> Independent threads perform the reads and writes in the echo test application. As a result, the order of the output might not exactly match what you see in the preceding output example.
-File Manifest
--------------
+## File Manifest
**Dllsup.cpp**: The DLL support code that provides the DLL's entry point and the single required export (DllGetClassObject).
diff --git a/general/event/README.md b/general/event/README.md
index 3488ea5a..37dadcf1 100644
--- a/general/event/README.md
+++ b/general/event/README.md
@@ -5,28 +5,21 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Hardware Event Sample
- platform: WDM
- language: cpp
- category: General
- description: Demonstrates different ways a kernel-mode driver can notify an application about a hardware event.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617711
---->
-
# Hardware Event Sample
This sample demonstrates two different ways a Windows kernel-mode driver can notify an application about a hardware event. One way uses an event-based method, and the other uses an IRP-based method. Because the sample driver is not talking to any real hardware, it uses a timer DPC to simulate hardware events. The test application informs the driver whether it wants to be notified by signaling an event or by completing the pending IRP. Additionally, the test application specifies a relative time at which the DPC timer must fire.
-*Event-based approach:* The application calls the [**CreateEvent**](http://msdn.microsoft.com/en-us/library/windows/hardware/ms682396) function to create an event. It then passes the event handle to the driver in an I/O control request that uses a private IOCTL code, IOCTL\_REGISTER\_EVENT. Because the driver is a monolithic, top-level driver, its IRP dispatch routines run in the application process context and, as a result, the event handle is still valid in the driver. The driver dereferences the user-mode handle into system space and saves the event object pointer for later use. Next, the driver queues a custom timer DPC. When the DPC fires, the driver signals the event by calling the [**KeSetEvent**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff553253) routine at DISPATCH\_LEVEL, and deletes the references to the event object. You can't use this approach if your driver is not a monolithic, top-level driver; that is because a driver can't guarantee the process context in a multi-level driver stack if the driver is not at the top of the stack.
+*Event-based approach:* The application calls the [**CreateEvent**](https://docs.microsoft.com/windows/win32/api/synchapi/nf-synchapi-createeventa) function to create an event. It then passes the event handle to the driver in an I/O control request that uses a private IOCTL code, IOCTL\_REGISTER\_EVENT. Because the driver is a monolithic, top-level driver, its IRP dispatch routines run in the application process context and, as a result, the event handle is still valid in the driver. The driver dereferences the user-mode handle into system space and saves the event object pointer for later use. Next, the driver queues a custom timer DPC. When the DPC fires, the driver signals the event by calling the [**KeSetEvent**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/nf-wdm-kesetevent) routine at DISPATCH\_LEVEL, and deletes the references to the event object. You can't use this approach if your driver is not a monolithic, top-level driver; that is because a driver can't guarantee the process context in a multi-level driver stack if the driver is not at the top of the stack.
*Pending IRP-based approach:* The application makes a synchronous IOCTL\_REGISTER\_EVENT request. The driver sets the status of the device I/O control request to IRP pending, queues a timer DPC, and returns STATUS\_PENDING. When the timer fires to indicate a hardware event, the driver completes the pending IRP to notify the application about the hardware event.
There are two advantages of IRP-based approach over the event-based approach. First, the driver can send a message to the application along with the event notification. Second, the driver routines don't have to run in the context of the process that made the request. Instead, the application can send a synchronous or asynchronous (overlapped) I/O control request to the driver.
-**Note** This sample driver is not a Plug and Play driver. This is a minimal driver meant to demonstrate a feature of the operating system. Neither this driver nor its sample programs are intended for use in a production environment. Rather, they are intended for educational purposes and as a skeleton driver.
+> [!NOTE]
+> This sample driver is not a Plug and Play driver. This is a minimal driver meant to demonstrate a feature of the operating system. Neither this driver nor its sample programs are intended for use in a production environment. Rather, they are intended for educational purposes and as a skeleton driver.
## Run the sample
diff --git a/general/filehistory/README.md b/general/filehistory/README.md
index 5f9fa87c..9cbadf3b 100644
--- a/general/filehistory/README.md
+++ b/general/filehistory/README.md
@@ -5,22 +5,14 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: File History Sample
- platform: WDM
- language: cpp
- category: General
- description: A console application that starts the file history service, if it is stopped, and schedules regular backups.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617712
---->
-
# File History Sample
The FileHistory sample is a console application that starts the file history service, if it is stopped, and schedules regular backups. The application requires, as a command-line parameter, the path name of a storage device to use as the default backup target.
-This sample application uses the [File History API](http://msdn.microsoft.com/en-us/library/windows/hardware/hh829789). The File History API enables third parties to automatically configure the File History feature on a Windows platform and customize it in accordance with their unique needs.
+This sample application uses the [File History API](https://docs.microsoft.com/windows/win32/devnotes/file-history-api). The File History API enables third parties to automatically configure the File History feature on a Windows platform and customize it in accordance with their unique needs.
## Run the sample
diff --git a/general/ioctl/kmdf/README.md b/general/ioctl/kmdf/README.md
index 7f99b367..13afa81c 100644
--- a/general/ioctl/kmdf/README.md
+++ b/general/ioctl/kmdf/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Non-PnP Driver Sample
- platform: KMDF
- language: cpp
- category: General WDF
- description: Demonstrates how to write a non-PnP driver using the Kernel Mode Driver Framework.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620307
---->
-
# Non-PnP Driver Sample
This sample is primarily meant to demonstrate how to write a NON-PNP driver using the Kernel Mode Driver Framework.
@@ -40,23 +32,26 @@ This sample would be useful for writing a driver that does not interact with any
The sample is accompanied by a simple multithreaded Win32 console application to test the driver.
-*Disclaimer*: This is a minimal driver meant to demonstrate an OS feature. Neither it nor its sample programs are intended for use in a production environment. Rather, they are intended for educational purposes and as a skeleton driver.
+> [!CAUTION]
+> This is a minimal driver meant to demonstrate an OS feature. Neither it nor its sample programs are intended for use in a production environment. Rather, they are intended for educational purposes and as a skeleton driver.
## Build the sample
-For information on how to build a driver solution using Microsoft Visual Studio, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644).
+For information on how to build a driver solution using Microsoft Visual Studio, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver).
If the build succeeds, you will find the driver, nonpnp.sys, and the test application, nonpnpapp.exe, in the binary output directory specified for the build environment.
To test this driver, copy the nonpnp.inf into the same folder as the nonpnpapp.exe and the wdfcoinstaller\<version\>.dll .
-**Note** You can obtain redistributable framework updates by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](http://go.microsoft.com/fwlink/p/?LinkID=226396). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0.
+> [!NOTE]
+> You can obtain redistributable framework updates by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](https://go.microsoft.com/fwlink/p/?LinkID=253170). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0.
Next, run nonpnpapp.exe, a simple Win32 multithreaded console mode application. The driver will be automatically loaded and started. When you exit the app, the driver will be stopped and removed.
Usage: nonpnpapp.exe (-l) (-v version)
-**Note** This application first tries to open the device (\\Device\\FileIo). If the device doesn't exist, it takes that as a hint that the driver is not loaded and tries to load the driver using service control manager API. If the service is loaded successfully, it tries to open the device again. If successful, it makes all four different types of DeviceControl calls to the driver. After that it makes a WriteFile call with an arbitrary size buffer. The driver, in response, writes that buffer to a file opened in the Create request. The name of the file was provided by the application as part of the device name and the directory path is hardcoded to %WINDIR%\\temp. When the WriteFile returns, the application makes a ReadFile call to read the file through the driver, and then compares the data returned by the driver with the one it originally wrote. If you specify -l option in command line, the application does this Write and Read operation in an infinite loop. The -v command line option is used to specify the version of the KMDF coinstaller (wdfcoinstaller\<version\>.dll) to load. If none is specified then it loads the coinstaller for v1.0 (wdfcoinstaller01000.dll)
+> [!NOTE]
+> This application first tries to open the device (\\Device\\FileIo). If the device doesn't exist, it takes that as a hint that the driver is not loaded and tries to load the driver using service control manager API. If the service is loaded successfully, it tries to open the device again. If successful, it makes all four different types of DeviceControl calls to the driver. After that it makes a WriteFile call with an arbitrary size buffer. The driver, in response, writes that buffer to a file opened in the Create request. The name of the file was provided by the application as part of the device name and the directory path is hardcoded to %WINDIR%\\temp. When the WriteFile returns, the application makes a ReadFile call to read the file through the driver, and then compares the data returned by the driver with the one it originally wrote. If you specify -l option in command line, the application does this Write and Read operation in an infinite loop. The -v command line option is used to specify the version of the KMDF coinstaller (wdfcoinstaller\<version\>.dll) to load. If none is specified then it loads the coinstaller for v1.0 (wdfcoinstaller01000.dll)
### WDF SECTION
diff --git a/general/ioctl/kmdf/sys/nonpnp.c b/general/ioctl/kmdf/sys/nonpnp.c
index 519ae838..a36c98c1 100644
--- a/general/ioctl/kmdf/sys/nonpnp.c
+++ b/general/ioctl/kmdf/sys/nonpnp.c
@@ -459,10 +459,10 @@ Return Value:
//
length = directory.Length + fileName->Length;
- absFileName.Buffer = ExAllocatePoolWithTag(PagedPool, length, POOL_TAG);
+ absFileName.Buffer = ExAllocatePool2(POOL_FLAG_PAGED, length, POOL_TAG);
if(absFileName.Buffer == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
- TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "ExAllocatePoolWithTag failed");
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "ExAllocatePool2 failed");
goto End;
}
absFileName.Length = 0;
diff --git a/general/ioctl/wdm/README.md b/general/ioctl/wdm/README.md
index 0f1fb3b2..564887ef 100644
--- a/general/ioctl/wdm/README.md
+++ b/general/ioctl/wdm/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: IOCTL
- platform: WDM
- language: cpp
- category: General
- description: Demonstrates usage of four different types of IOCTLs
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617715
---->
-
# IOCTL
This sample demonstrates the usage of four different types of IOCTLs (METHOD\_IN\_DIRECT, METHOD\_OUT\_DIRECT, METHOD\_NEITHER, and METHOD\_BUFFERED).
@@ -24,8 +16,9 @@ The sample shows how the user input and output buffers specified in the **Device
The sample consists of a legacy device driver and a Win32 console test application. The test application opens a handle to the device exposed by the driver and makes all four different **DeviceIoControl** calls, one after another. To understand how the IRP fields are set the I/O manager, you should run the checked build version of the driver and look at the debug output.
-**Note** This sample driver is not a Plug and Play driver. This is a minimal driver meant to demonstrate a feature of the operating system. Neither this driver nor its sample programs are intended for use in a production environment. Instead, they are intended for educational purposes and as a skeleton driver.
+> [!CAUTION]
+> This sample driver is not a Plug and Play driver. This is a minimal driver meant to demonstrate a feature of the operating system. Neither this driver nor its sample programs are intended for use in a production environment. Instead, they are intended for educational purposes and as a skeleton driver.
-# Run the sample
+## Run the sample
To test this driver, copy the test app, Ioctlapp.exe, and the driver to the same directory, and run the application. The application will automatically load the driver, if it's not already loaded, and interact with the driver. When you exit the application, the driver will be stopped, unloaded and removed.
diff --git a/general/obcallback/README.md b/general/obcallback/README.md
index e0efce2c..993b78d6 100644
--- a/general/obcallback/README.md
+++ b/general/obcallback/README.md
@@ -5,28 +5,20 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: ObCallback Callback Registration Driver
- platform: WDM
- language: cpp
- category: General
- description: Demonstrates the use of registered callbacks for process protection.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617716
---->
-
# ObCallback Callback Registration Driver
The ObCallback sample driver demonstrates the use of registered callbacks for process protection. The driver registers control callbacks which are called at process creation.
## Design and Operation
-The sample exercises both the [**PsSetCreateProcessNotifyRoutineEx**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff559951) and the [**ObRegisterCallbacks**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff558692) routines. The first example uses the **ObRegisterCallbacks** routine and a callback to restrict requested access rights during a open process action. The second example uses the **PsSetCreateProcessNotifyRoutineEx** routine to reject a process creation by examining the command line.
+The sample exercises both the [**PsSetCreateProcessNotifyRoutineEx**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ntddk/nf-ntddk-pssetcreateprocessnotifyroutine) and the [**ObRegisterCallbacks**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/nf-wdm-obregistercallbacks) routines. The first example uses the **ObRegisterCallbacks** routine and a callback to restrict requested access rights during a open process action. The second example uses the **PsSetCreateProcessNotifyRoutineEx** routine to reject a process creation by examining the command line.
The following is a command line usage scenario to exercise access restriction:
-```
+```cmd
C:\> obcallbacktestctrl.exe -? (for command line help)
C:\> obcallbacktestctrl.exe -install (installs the kernel driver)
C:\> obcallbacktestctrl.exe -name notepad (specifies that the string "notepad" will be watched as a protected executable)
@@ -46,7 +38,7 @@ C:\> obcallbacktestctrl.exe -uninstall (uninstall the kernel drive
The following is another sample test you can run to prevent a process from being created:
-```
+```cmd
C:\> obcallbacktestctrl.exe -install (installs the kernel driver)
C:\> obcallbacktestctrl.exe -reject notepad (specifies that the string "notepad" will be watched and prevented from starting as a process)
diff --git a/general/pcidrv/README.md b/general/pcidrv/README.md
index 1c68893b..877aa103 100644
--- a/general/pcidrv/README.md
+++ b/general/pcidrv/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: PCIDRV - WDF Driver for PCI Device
- platform: KMDF
- language: cpp
- category: General PCI WDF
- description: Demonstrates how to write a KMDF driver for a PCI device.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617717
---->
-
# PCIDRV - WDF Driver for PCI Device
This sample demonstrates how to write a KMDF driver for a PCI device. The sample works with the Intel 82557/82558 based PCI Ethernet Adapter (10/100) and Intel compatibles.
@@ -50,7 +42,8 @@ The following is a list of key KMDF interfaces demonstrated in this sample:
- Reading & Writing to the registry
-Note: This sample provides an example of a minimal driver intended for educational purposes. Neither the driver nor its sample test programs are intended for use in a production environment.
+> [!NOTE]
+> This sample provides an example of a minimal driver intended for educational purposes. Neither the driver nor its sample test programs are intended for use in a production environment.
As stated earlier, this sample is meant to demonstrate how to write a KMDF driver for a generic PCI device and not for PCI network controllers. For network controllers, you should write a monolithic NDIS miniport driver based on the samples given under the \\network\\ndis directory.
@@ -58,21 +51,21 @@ Note that it is still possible to use a subset of KMDF APIs when writing a NDIS
The sample driver has been tested on the following Intel Ethernet controllers:
-Device Description | Hardware ID
--------------------|------------
-IBM Netfinity 10/100 Ethernet Adapter | PCIVEN_8086&DEV_1229&SUBSYS_005C1014&REV_05
-Intel(R) PRO/100+ Management Adapter with Alert On LAN | PCI\VEN_8086&DEV_1229&SUBSYS_000E8086&REV_08
-Intel 8255x-based PCI Ethernet Adapter (10/100) | PCI\VEN_8086&DEV_1229&SUBSYS_00000000&REV_01
-Intel Pro/100 S Server Adapter | PCI\VEN_8086&DEV_1229&SUBSYS_00508086&REV_0D
-Intel 8255x-based PCI Ethernet Adapter (10/100) | PCI\VEN_8086&DEV_1229&SUBSYS_00031179&REV_08
-Intel(R) PRO/100 VE Network Connection | PCI\VEN_8086&DEV_103D&SUBSYS_00011179&REV_83
-Intel(R) PRO/100 VM Network Connection | PCI\VEN_8086&DEV_1031&REV_42
-Intel(R) PRO/100 VE Network Connection | PCI\VEN_8086&DEV_1038&REV_41
-Intel(R) PRO/100 SR Mobile Adapter | PCI\VEN_8086&DEV_1229
+| Device Description | Hardware ID |
+| --- | --- |
+| IBM Netfinity 10/100 Ethernet Adapter | PCIVEN_8086&DEV_1229&SUBSYS_005C1014&REV_05 |
+| Intel(R) PRO/100+ Management Adapter with Alert On LAN | PCI\VEN_8086&DEV_1229&SUBSYS_000E8086&REV_08 |
+| Intel 8255x-based PCI Ethernet Adapter (10/100) | PCI\VEN_8086&DEV_1229&SUBSYS_00000000&REV_01 |
+| Intel Pro/100 S Server Adapter | PCI\VEN_8086&DEV_1229&SUBSYS_00508086&REV_0D |
+| Intel 8255x-based PCI Ethernet Adapter (10/100) | PCI\VEN_8086&DEV_1229&SUBSYS_00031179&REV_08 |
+| Intel(R) PRO/100 VE Network Connection | PCI\VEN_8086&DEV_103D&SUBSYS_00011179&REV_83 |
+| Intel(R) PRO/100 VM Network Connection | PCI\VEN_8086&DEV_1031&REV_42 |
+| Intel(R) PRO/100 VE Network Connection | PCI\VEN_8086&DEV_1038&REV_41 |
+| Intel(R) PRO/100 SR Mobile Adapter | PCI\VEN_8086&DEV_1229 |
## Using this sample as a standalone driver
-```
+```txt
---------------------
| |
| MYPING | <-- Usermode test application
@@ -102,13 +95,13 @@ You can install the driver as a standalone driver of a custom setup class, calle
The PCIDRV sample acts as a power policy owner of the device and implements all the wait-wake and idle detection logic.
-## INSTALLATION
+## Installation
The driver can be installed as a Net class driver or as a standalone driver (user defined class). The KMDF versions of the INF files are dynamically generated from .INX file. In addition to the driver files, you have to include the WDF coinstaller DLL from the \\redist\\wdf folder of the WDK.
-You can obtain redistributable framework updates by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](http://go.microsoft.com/fwlink/p/?LinkID=226396). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0.
+You can obtain redistributable framework updates by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](https://go.microsoft.com/fwlink/p/?LinkID=253170). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0.
-### TESTING
+### Testing
To test standalone driver configuration: You should use the specially developed ping application, called MYPING that comes with the sample. The Ping.exe provided in the system will not work because in this configuration, the test card is not bound to any network protocol - it's not seen as Net device by the system. Currently the test application doesn't have ability to get an IP address from a network DHCP server. As a result, it is better to connect the network device to a private hub and ping another machine connected to that hub. For example, let us say you have a test machine A and another machine B (development box).
@@ -154,18 +147,19 @@ Other menu options of myping applications are:
- Exit: Terminate the application.
-**Note** You can use this application only on a device installed in the standalone configuration. If you run it on a device that's installed as a miniport, you will get an error message. For such devices, you can use the system provided ping.exe.
+> [!NOTE]
+> You can use this application only on a device installed in the standalone configuration. If you run it on a device that's installed as a miniport, you will get an error message. For such devices, you can use the system provided ping.exe.
-## RESOURCES
+## Resources
For the latest release of the Windows Driver Kit, see [Download the Windows Driver Kit (WDK)](https://docs.microsoft.com/windows-hardware/drivers/download-the-wdk).
If you have questions on using or adapting this sample for your project, you can either contact Microsoft Technical Support or post your questions in the Microsoft driver development newsgroup.
-## FILE MANIFEST
+## File manifest
-File | Description
------|------------
-KMDF | Contains the driver.
-KMDF\HW | Contains hardware specific code.
-TEST | Contains source of test application (MYPING).
+| File | Description |
+| --- | --- |
+| KMDF | Contains the driver |
+| KMDF\HW | Contains hardware specific code |
+| TEST | Contains source of test application (MYPING) |
diff --git a/general/perfcounters/kcs/README.md b/general/perfcounters/kcs/README.md
index 358faa65..10316133 100644
--- a/general/perfcounters/kcs/README.md
+++ b/general/perfcounters/kcs/README.md
@@ -5,23 +5,15 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Kernel Counter Sample (Kcs)
- platform: WDM
- language: cpp
- category: General
- description: Demonstrates the use of the kernel-mode performance library.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617718
---->
-
# Kernel Counter Sample (Kcs)
-The Kcs sample driver demonstrates the use of the [kernel-mode performance library](http://msdn.microsoft.com/en-us/library/windows/hardware/ff548159). The sample driver does not control any hardware; it simply provides example code that demonstrates how to provide counter data from a kernel-mode driver. The code contains comments to explain what each function does. The sample creates geometric wave and trigonometric wave counter sets.
+The Kcs sample driver demonstrates the use of the [kernel-mode performance library](https://docs.microsoft.com/windows-hardware/drivers/devtest/kernel-mode-performance-monitoring). The sample driver does not control any hardware; it simply provides example code that demonstrates how to provide counter data from a kernel-mode driver. The code contains comments to explain what each function does. The sample creates geometric wave and trigonometric wave counter sets.
This module contains sample code to demonstrate how to provide counter data from a kernel driver.
This sample driver should not be used in a production environment.
-The Microsoft Windows operating system allows system components and third parties to expose performance metrics in a standard way by using [Performance Counters](http://msdn.microsoft.com/en-us/library/windows/hardware/aa373083). Kernel-mode PCW providers are installed in the system as Performance Counter Library (PERFLIB) (Version 2 providers), which allows their counters to be browsed, and allows for data collection and instance enumeration. Consumers can query KM PCW providers by using PDH and PERFLIB Version 1 without any modification to the consumer code.
+The Microsoft Windows operating system allows system components and third parties to expose performance metrics in a standard way by using [Performance Counters](https://docs.microsoft.com/windows/win32/perfctrs/performance-counters-portal). Kernel-mode PCW providers are installed in the system as Performance Counter Library (PERFLIB) (Version 2 providers), which allows their counters to be browsed, and allows for data collection and instance enumeration. Consumers can query KM PCW providers by using PDH and PERFLIB Version 1 without any modification to the consumer code.
diff --git a/general/registry/regfltr/README.md b/general/registry/regfltr/README.md
index fafe5dbd..b16d92eb 100644
--- a/general/registry/regfltr/README.md
+++ b/general/registry/regfltr/README.md
@@ -5,33 +5,33 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: RegFltr Sample Driver
- platform: WDM
- language: cpp
- category: General
- description: Demonstrates how to write a registry filter driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617720
---->
-
# RegFltr Sample Driver
-The RegFltr sample shows how to write a [registry filter driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff545879).In addition to providing some basic examples, this sample demonstrates the following:
+The RegFltr sample shows how to write a [registry filter driver](hhttps://docs.microsoft.com/windows-hardware/drivers/kernel/filtering-registry-calls).In addition to providing some basic examples, this sample demonstrates the following:
- How to handle transactional registry operations.
+
- How and when to capture input parameters.
+
- Issues and workarounds for version 1.0 of registry filtering.
+
- Changes in version 1.1 of registry filtering.
-- How to use version 1 of the [**REG\_CREATE\_KEY\_INFORMATION**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff560920) and [**REG\_OPEN\_KEY\_INFORMATION**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff560957) data structures.
+
+- How to use version 1 of the [**REG\_CREATE\_KEY\_INFORMATION**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/ns-wdm-_reg_create_key_information) and [**REG\_OPEN\_KEY\_INFORMATION**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/ns-wdm-_reg_create_key_information) data structures.
The RegFltr sample contains several examples of user-mode and kernel-mode registry-filtering operations. Each example comes with its own corresponding registry callback routine, and performs the following steps:
1. Does some setup work.
+
1. Registers the callback routine.
+
1. Performs one or more registry operations.
+
1. Unregisters the callback routine.
+
1. Verifies that the sample completed correctly.
The sample driver is a minimal driver that is not intended to be used on production systems. To keep the samples simple, the registry callback routines provided do not check for all possible situations and error conditions. This sample is designed to demonstrate typical scenarios and no other registry filtering driver is expected to be active.
diff --git a/general/toaster/toastDrv/README.md b/general/toaster/toastDrv/README.md
index 022a27ca..fc84c39d 100644
--- a/general/toaster/toastDrv/README.md
+++ b/general/toaster/toastDrv/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Toaster Sample Driver
- platform: KMDF UMDF1
- language: cpp
- category: General WDF
- description: An iterative series of samples that demonstrate KDMF and UDMF1 driver development.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620309
---->
-
# Toaster Sample Driver
The Toaster collection is an iterative series of samples that demonstrate fundamental aspects of Windows driver development for both Kernel-Mode Driver Framework (KMDF) and User-Mode Driver Framework (UMDF) version 1.
@@ -26,9 +18,9 @@ The Toaster sample collection comprises driver projects (.vcxproj files) that ar
## Related technologies
-[Windows Driver Frameworks](http://msdn.microsoft.com/en-us/library/windows/hardware/ff557565)
+[Windows Driver Frameworks](https://docs.microsoft.com/windows-hardware/drivers/wdf/)
-For detailed descriptions and code walkthroughs of each project, see [Sample Toaster Driver Programming Tour](http://msdn.microsoft.com/en-us/library/windows/hardware/dn569312). To learn how to build and run the samples, read on.
+For detailed descriptions and code walkthroughs of each project, see [Sample Toaster Driver Programming Tour](https://docs.microsoft.com/windows-hardware/drivers/wdf/sample-toaster-driver-programming-tour). To learn how to build and run the samples, read on.
## Run the sample
@@ -41,26 +33,32 @@ The process of moving the driver package to the target computer and installing t
Before doing this, you should back up your package.vcxproj file, located in your sample directory, for example C:\\Toaster\\C++\\Package.
1. In the Properties for the package project, navigate to **Common Properties \> References**.
+
1. Remove all references except WdfSimple. (Use the **Remove Reference** button at the bottom.)
### Automatic deployment (root enumerated)
-Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/).
+Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1).
1. On the host computer, in Visual Studio, in Solution Explorer, right click the **package** project (within the package folder), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
+
1. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, use the drop down to select the name of a target computer that you provisioned previously. Select **Hardware ID Driver Update**, and enter **{b85b7c50-6a01-11d2-b841-00c04fad5171}\\MsToaster** for the hardware ID. (You can find this value in the WdfSimple.inx file.) Click **Apply** and **OK**.
+
1. Because this solution contains many projects, you may find it easier to remove some of them before you build and deploy a driver package. To do so, right click **package** (lower case), and choose **Properties**. Navigate to **Common Properties-\>References** and click **Remove Reference** to remove projects you don't want. (You can add them back later by using **Add New Reference**.) Click **OK**.
+
1. On the **Build** menu, choose **Build Solution** or **Rebuild Solution** (if you removed references).
+
1. If you removed references and deployment does not succeed, try deleting the contents of the c:\\DriverTest\\Drivers folder on the target machine, and then retry deployment.
### Manual deployment (root enumerated)
-Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
+Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](https://docs.microsoft.com/windows-hardware/drivers/devtest/devcon) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\WdfSimplePackage).
+
1. On the target computer, open a Command Prompt window as Administrator. Navigate to your driver package folder, and enter the following command:
- **devcon install WdfSimple.inf {b85b7c50-6a01-11d2-b841-00c04fad5171}\\MsToaster**
+ `devcon install WdfSimple.inf {b85b7c50-6a01-11d2-b841-00c04fad5171}\\MsToaster`
### View the root enumerated driver in Device Manager
@@ -72,78 +70,95 @@ In Device Manager, on the **View** menu, choose **Devices by connection**. Locat
As an alternative to building the Toaster sample in Visual Studio, you can build it in a Visual Studio Command Prompt window. In Visual Studio, on the **Tools** menu, choose **Visual Studio Command Prompt**. In the Visual Studio Command Prompt window, navigate to the folder that has the solution file, Toaster.sln. Use the MSBuild command to build the solution. Here are some examples:
-**msbuild /p:configuration="Debug" /p:platform="x64" Toaster.sln**
+`msbuild /p:configuration="Debug" /p:platform="x64" Toaster.sln`
-**msbuild /p:configuration="Release" /p:platform="Win32" Toaster.sln**
+`msbuild /p:configuration="Release" /p:platform="Win32" Toaster.sln`
-For more information about using MSBuild to build a driver package, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644).
+For more information about using MSBuild to build a driver package, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver).
## UMDF Toaster File Manifest
-#### WUDFToaster.idl
+### WUDFToaster.idl
+
Component Interface file
-#### WUDFToaster.cpp
+### WUDFToaster.cpp
+
DLL Support code - provides the DLL's entry point as well as the DllGetClassObject export.
-#### WUDFToaster.def
+### WUDFToaster.def
+
This file lists the functions that the driver DLL exports.
-#### stdafx.h
+### stdafx.h
+
This is the main header file for the sample driver.
-#### driver.cpp & driver.h
+### driver.cpp and driver.h (WUDFToaster)
+
Definition and implementation of the IDriverEntry callbacks in CDriver class.
-#### device.cpp & device.h
+### device.cpp and device.h (WUDFToaster)
+
Definition and implementation of various interfaces and their callbacks in CDevice class. Add your PnP and Power interfaces specific for your hardware.
-#### queue.cpp & queue.h
+### queue.cpp and queue.h
+
Definition and implementation of the base queue callback class (CQueue). IQueueCallbackDevicekIoControl, IQueueCallbackRead and IQueueCallBackWrite callbacks are implemented to handle I/O control requests.
-#### WUDFToaster.rc
+### WUDFToaster.rc
+
This file defines resource information for the WUDF Toaster sample driver.
-#### WUDFToaster.inf
+### WUDFToaster.inf
+
Sample INF for installing the sample WUDF Toaster driver under the Toaster class of devices.
-#### WUDFtoaster.ctl, internal.h
+### WUDFtoaster.ctl, internal.h
+
This file lists the WPP trace control GUID(s) for the sample driver. This file can be used with the tracelog command's -guid flag to enable the collection of these trace events within an established trace session.
These GUIDs must remain in sync with the trace control guids defined in internal.h.
## Toastmon File Manifest
-#### comsup.cpp & comsup.h
+### comsup.cpp and comsup.h
+
Boilerplate COM Support code - specifically base classes which provide implementations for the standard COM interfaces IUnknown and IClassFactory which are used throughout the sample.
The implementation of IClassFactory is designed to create instances of the CMyDriver class. If you should change the name of your base driver class, you would also need to modify this file.
-#### dllsup.cpp
+### dllsup.cpp
+
Boilerplate DLL Support code - provides the DLL's entry point as well as the single required export (DllGetClassObject).
These depend on comsup.cpp to perform the necessary class creation.
-#### exports.def
+### exports.def
+
This file lists the functions that the driver DLL exports.
-#### makefile
-This file redirects to the real makefile, which is shared by all the driver components of the Windows Driver Kit.
+### internal.h
-#### internal.h
This is the main header file for the ToastMon driver
-#### driver.cpp & driver.h
+### driver.cpp and driver.h (Toastmon)
+
Definition and implementation of the driver callback class for the ToastMon sample.
-#### device.cpp & device.h
+### device.cpp and device.h (Toastmon)
+
Definition and implementation of the device callback class for the ToastMon sample. This is mostly boilerplate, but also registers for RemoteInterface Arrival notifications. When a RemoteInterface arrival callback occurs, it calls CreateRemoteInterface and creates a CMyRemoteTarget callback object to handle I/O on that RemoteInterface.
-#### RemoteTarget.cpp & RemoteTarget.h
+### RemoteTarget.cpp and RemoteTarget.h
+
Definition and implementation of the remote target callback class for the ToastMon sample.
-#### list.h
+### list.h
+
Doubly-linked-list code
-#### ToastMon.rc
+### ToastMon.rc
+
This file defines resource information for the ToastMon sample driver.
-#### UMDFToastMon.inf
+### UMDFToastMon.inf
+
Sample INF for installing the Skeleton driver to control a root enumerated device with a hardware ID of UMDFSamples\\ToastMon
diff --git a/general/toaster/toastDrv/kmdf/bus/dynamic/busenum.c b/general/toaster/toastDrv/kmdf/bus/dynamic/busenum.c
index 8b79bff1..e8f62064 100644
--- a/general/toaster/toastDrv/kmdf/bus/dynamic/busenum.c
+++ b/general/toaster/toastDrv/kmdf/bus/dynamic/busenum.c
@@ -58,7 +58,7 @@ Return Value:
KdPrint(("WDF Toaster Bus Driver Sample Dynamic Version.\n"));
//
- // Initiialize driver config to control the attributes that
+ // Initialize driver config to control the attributes that
// are global to the driver. Note that framework by default
// provides a driver unload routine. If you create any resources
// in the DriverEntry and want to be cleaned in driver unload,
diff --git a/general/toaster/toastDrv/kmdf/bus/dynamic/buspdo.c b/general/toaster/toastDrv/kmdf/bus/dynamic/buspdo.c
index d7d2cf54..52c847d3 100644
--- a/general/toaster/toastDrv/kmdf/bus/dynamic/buspdo.c
+++ b/general/toaster/toastDrv/kmdf/bus/dynamic/buspdo.c
@@ -82,8 +82,8 @@ Return Value:
return status;
}
- dst->HardwareIds = (PWCHAR) ExAllocatePoolWithTag(
- NonPagedPoolNx,
+ dst->HardwareIds = (PWCHAR) ExAllocatePool2(
+ POOL_FLAG_NON_PAGED,
safeMultResult,
BUS_TAG);
diff --git a/general/toaster/toastDrv/kmdf/bus/static/busenum.c b/general/toaster/toastDrv/kmdf/bus/static/busenum.c
index 41e79f0f..cc54d346 100644
--- a/general/toaster/toastDrv/kmdf/bus/static/busenum.c
+++ b/general/toaster/toastDrv/kmdf/bus/static/busenum.c
@@ -59,7 +59,7 @@ Return Value:
KdPrint(("Toaster Static Bus Driver Sample - Driver Framework Edition.\n"));
//
- // Initiialize driver config to control the attributes that
+ // Initialize driver config to control the attributes that
// are global to the driver. Note that framework by default
// provides a driver unload routine. If you create any resources
// in the DriverEntry and want to be cleaned in driver unload,
diff --git a/general/toaster/toastDrv/kmdf/filter/generic/filter.c b/general/toaster/toastDrv/kmdf/filter/generic/filter.c
index c1dadac2..673f55f7 100644
--- a/general/toaster/toastDrv/kmdf/filter/generic/filter.c
+++ b/general/toaster/toastDrv/kmdf/filter/generic/filter.c
@@ -67,7 +67,7 @@ Return Value:
KdPrint(("Toaster Generic Filter Driver Sample - Driver Framework Edition.\n"));
//
- // Initiialize driver config to control the attributes that
+ // Initialize driver config to control the attributes that
// are global to the driver. Note that framework by default
// provides a driver unload routine. If you create any resources
// in the DriverEntry and want to be cleaned in driver unload,
diff --git a/general/toaster/toastDrv/kmdf/func/featured/toaster.c b/general/toaster/toastDrv/kmdf/func/featured/toaster.c
index be826982..772b0416 100644
--- a/general/toaster/toastDrv/kmdf/func/featured/toaster.c
+++ b/general/toaster/toastDrv/kmdf/func/featured/toaster.c
@@ -113,7 +113,7 @@ Return Value:
KdPrint(("WDF Toaster Function Driver Sample - Featured version\n"));
//
- // Initiialize driver config to control the attributes that
+ // Initialize driver config to control the attributes that
// are global to the driver. Note that framework by default
// provides a driver unload routine. If you create any resources
// in the DriverEntry and want to be cleaned in driver unload,
diff --git a/general/toaster/toastDrv/kmdf/func/featured/wmi.c b/general/toaster/toastDrv/kmdf/func/featured/wmi.c
index e7c76a23..f62eacd3 100644
--- a/general/toaster/toastDrv/kmdf/func/featured/wmi.c
+++ b/general/toaster/toastDrv/kmdf/func/featured/wmi.c
@@ -446,11 +446,9 @@ ToasterFireArrivalEvent(
//
// Allocate memory for the WNODE from NonPagedPoolNx
//
- wnode = ExAllocatePoolWithTag(NonPagedPoolNx, size, TOASTER_POOL_TAG);
+ wnode = ExAllocatePool2(POOL_FLAG_NON_PAGED, size, TOASTER_POOL_TAG);
if (NULL != wnode) {
- RtlZeroMemory(wnode, size);
-
wnode->WnodeHeader.BufferSize = size;
wnode->WnodeHeader.ProviderId =
IoWMIDeviceObjectToProviderId(
diff --git a/general/toaster/toastDrv/kmdf/func/simple/toaster.c b/general/toaster/toastDrv/kmdf/func/simple/toaster.c
index 6ed215db..7b117240 100644
--- a/general/toaster/toastDrv/kmdf/func/simple/toaster.c
+++ b/general/toaster/toastDrv/kmdf/func/simple/toaster.c
@@ -72,7 +72,7 @@ Return Value:
KdPrint(("Toaster Function Driver Sample - Driver Framework Edition.\n"));
//
- // Initiialize driver config to control the attributes that
+ // Initialize driver config to control the attributes that
// are global to the driver. Note that framework by default
// provides a driver unload routine. If DriverEntry creates any resources
// that require clean-up in driver unload,
diff --git a/general/toaster/toastDrv/kmdf/toastmon/toastmon.c b/general/toaster/toastDrv/kmdf/toastmon/toastmon.c
index 44f6f5d2..5967d019 100644
--- a/general/toaster/toastDrv/kmdf/toastmon/toastmon.c
+++ b/general/toaster/toastDrv/kmdf/toastmon/toastmon.c
@@ -77,7 +77,7 @@ Return Value:
KdPrint(("ToastMon Driver Sample - Driver Framework Edition.\n"));
//
- // Initiialize driver config to control the attributes that
+ // Initialize driver config to control the attributes that
// are global to the driver. Note that framework by default
// provides a driver unload routine. If you create any resources
// in the DriverEntry and want to be cleaned in driver unload,
diff --git a/general/toaster/toastpkg/README.md b/general/toaster/toastpkg/README.md
index 0d2b335c..7aceb704 100644
--- a/general/toaster/toastpkg/README.md
+++ b/general/toaster/toastpkg/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Toaster Package Sample Driver
- platform: WDM
- language: cpp
- category: General
- description: Simulates hardware-first and software-first installation of the toaster sample driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617723
---->
-
# Toaster Package Sample Driver
The Toaster collection is an iterative series of samples that demonstrate fundamental aspects of Windows driver development for both Kernel-Mode Driver Framework (KMDF) and User-Mode Driver Framework (UMDF) version 1.
@@ -26,9 +18,9 @@ The Toaster sample collection comprises driver projects (.vcxproj files) that ar
## Related technologies
-[Windows Driver Frameworks](http://msdn.microsoft.com/en-us/library/windows/hardware/ff557565)
+[Windows Driver Frameworks](https://docs.microsoft.com/windows-hardware/drivers/wdf/)
-For detailed descriptions and code walkthroughs of each project, see [Sample Toaster Driver Programming Tour](http://msdn.microsoft.com/en-us/library/windows/hardware/dn569312). To learn how to build and run the samples, read on.
+For detailed descriptions and code walkthroughs of each project, see [Sample Toaster Driver Programming Tour](https://docs.microsoft.com/windows-hardware/drivers/wdf/sample-toaster-driver-programming-tour). To learn how to build and run the samples, read on.
## Run the sample
@@ -41,23 +33,29 @@ The process of moving the driver package to the target computer and installing t
Before doing this, you should back up your package.vcxproj file, located in your sample directory, for example C:\\Toaster\\C++\\Package.
1. In the Properties for the package project, navigate to **Common Properties \> References**.
+
1. Remove all references except WdfSimple. (Use the **Remove Reference** button at the bottom.)
### Automatic deployment (root enumerated)
-Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/).
+Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1).
1. On the host computer, in Visual Studio, in Solution Explorer, right click the **package** project (within the package folder), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
+
1. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, use the drop down to select the name of a target computer that you provisioned previously. Select **Hardware ID Driver Update**, and enter **{b85b7c50-6a01-11d2-b841-00c04fad5171}\\MsToaster** for the hardware ID. (You can find this value in the WdfSimple.inx file.) Click **Apply** and **OK**.
+
1. Because this solution contains many projects, you may find it easier to remove some of them before you build and deploy a driver package. To do so, right click **package** (lower case), and choose **Properties**. Navigate to **Common Properties-\>References** and click **Remove Reference** to remove projects you don't want. (You can add them back later by using **Add New Reference**.) Click **OK**.
+
1. On the **Build** menu, choose **Build Solution** or **Rebuild Solution** (if you removed references).
+
1. If you removed references and deployment does not succeed, try deleting the contents of the c:\\DriverTest\\Drivers folder on the target machine, and then retry deployment.
### Manual deployment (root enumerated)
-Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
+Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](https://docs.microsoft.com/windows-hardware/drivers/devtest/devcon) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\WdfSimplePackage).
+
1. On the target computer, open a Command Prompt window as Administrator. Navigate to your driver package folder, and enter the following command:
**devcon install WdfSimple.inf {b85b7c50-6a01-11d2-b841-00c04fad5171}\\MsToaster**
@@ -72,78 +70,95 @@ In Device Manager, on the **View** menu, choose **Devices by connection**. Locat
As an alternative to building the Toaster sample in Visual Studio, you can build it in a Visual Studio Command Prompt window. In Visual Studio, on the **Tools** menu, choose **Visual Studio Command Prompt**. In the Visual Studio Command Prompt window, navigate to the folder that has the solution file, Toaster.sln. Use the MSBuild command to build the solution. Here are some examples:
-**msbuild /p:configuration="Debug" /p:platform="x64" Toaster.sln**
+`msbuild /p:configuration="Debug" /p:platform="x64" Toaster.sln`
-**msbuild /p:configuration="Release" /p:platform="Win32" Toaster.sln**
+`msbuild /p:configuration="Release" /p:platform="Win32" Toaster.sln`
-For more information about using MSBuild to build a driver package, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644).
+For more information about using MSBuild to build a driver package, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver).
## UMDF Toaster File Manifest
-#### WUDFToaster.idl
+### WUDFToaster.idl
+
Component Interface file
-#### WUDFToaster.cpp
+### WUDFToaster.cpp
+
DLL Support code - provides the DLL's entry point as well as the DllGetClassObject export.
-#### WUDFToaster.def
+### WUDFToaster.def
+
This file lists the functions that the driver DLL exports.
-#### stdafx.h
+### stdafx.h
+
This is the main header file for the sample driver.
-#### driver.cpp & driver.h
+### driver.cpp and driver.h (WUDFToaster)
+
Definition and implementation of the IDriverEntry callbacks in CDriver class.
-#### device.cpp & device.h
+### device.cpp and device.h (WUDFToaster)
+
Definition and implementation of various interfaces and their callbacks in CDevice class. Add your PnP and Power interfaces specific for your hardware.
-#### queue.cpp & queue.h
+### queue.cpp and queue.h
+
Definition and implementation of the base queue callback class (CQueue). IQueueCallbackDevicekIoControl, IQueueCallbackRead and IQueueCallBackWrite callbacks are implemented to handle I/O control requests.
-#### WUDFToaster.rc
+### WUDFToaster.rc
+
This file defines resource information for the WUDF Toaster sample driver.
-#### WUDFToaster.inf
+### WUDFToaster.inf
+
Sample INF for installing the sample WUDF Toaster driver under the Toaster class of devices.
-#### WUDFtoaster.ctl, internal.h
+### WUDFtoaster.ctl, internal.h
+
This file lists the WPP trace control GUID(s) for the sample driver. This file can be used with the tracelog command's -guid flag to enable the collection of these trace events within an established trace session.
These GUIDs must remain in sync with the trace control guids defined in internal.h.
## Toastmon File Manifest
-#### comsup.cpp & comsup.h
+### comsup.cpp and comsup.h
+
Boilerplate COM Support code - specifically base classes which provide implementations for the standard COM interfaces IUnknown and IClassFactory which are used throughout the sample.
The implementation of IClassFactory is designed to create instances of the CMyDriver class. If you should change the name of your base driver class, you would also need to modify this file.
-#### dllsup.cpp
+### dllsup.cpp
+
Boilerplate DLL Support code - provides the DLL's entry point as well as the single required export (DllGetClassObject).
These depend on comsup.cpp to perform the necessary class creation.
-#### exports.def
+### exports.def
+
This file lists the functions that the driver DLL exports.
-#### makefile
-This file redirects to the real makefile, which is shared by all the driver components of the Windows Driver Kit.
+### internal.h
-#### internal.h
This is the main header file for the ToastMon driver
-#### driver.cpp & driver.h
+### driver.cpp and driver.h (Toastmon)
+
Definition and implementation of the driver callback class for the ToastMon sample.
-#### device.cpp & device.h
+### device.cpp and device.h (Toastmon)
+
Definition and implementation of the device callback class for the ToastMon sample. This is mostly boilerplate, but also registers for RemoteInterface Arrival notifications. When a RemoteInterface arrival callback occurs, it calls CreateRemoteInterface and creates a CMyRemoteTarget callback object to handle I/O on that RemoteInterface.
-#### RemoteTarget.cpp & RemoteTarget.h
+### RemoteTarget.cpp and RemoteTarget.h
+
Definition and implementation of the remote target callback class for the ToastMon sample.
-#### list.h
+### list.h
+
Doubly-linked-list code
-#### ToastMon.rc
+### ToastMon.rc
+
This file defines resource information for the ToastMon sample driver.
-#### UMDFToastMon.inf
+### UMDFToastMon.inf
+
Sample INF for installing the Skeleton driver to control a root enumerated device with a hardware ID of UMDFSamples\\ToastMon
diff --git a/general/toaster/umdf2/README.md b/general/toaster/umdf2/README.md
index 3ec98f60..fb3741c6 100644
--- a/general/toaster/umdf2/README.md
+++ b/general/toaster/umdf2/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Toaster Sample (UMDF version 2)
- platform: UMDF2
- language: cpp
- category: General WDF
- description: An iterative series of samples that demonstrate driver development using UMDF version 2.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620310
---->
-
# Toaster Sample (UMDF Version 2)
The Toaster (UMDF version 2) sample is an iterative series of samples that demonstrate fundamental aspects of Windows driver development.
@@ -24,7 +16,7 @@ The Toaster sample collection is comprised of driver projects (.vcxproj files) t
## Related technologies
-[User-Mode Driver Framework](http://msdn.microsoft.com/en-us/library/windows/hardware/ff560456)
+[Windows Driver Frameworks](https://docs.microsoft.com/windows-hardware/drivers/wdf/)
## Run the sample
@@ -34,22 +26,27 @@ The process of moving the driver package to the target computer and installing t
### Automatic deployment (root enumerated)
-Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/).
+Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1).
1. On the host computer, in Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
+
1. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Hardware ID Driver Update**, and enter **root\\toaster** for the hardware ID. Click **OK**.
+
1. Because this solution contains many projects, you may find it easier to remove some of them before you build and deploy a driver package. To do so, right click **package** (lower case), and choose **Properties**. Navigate to **Common Properties-\>References** and click **Remove Reference** to remove projects you don't want. (You can add them back later by using **Add New Reference**.) Click **OK**.
+
1. On the **Build** menu, choose **Build Solution** or **Rebuild Solution** (if you removed references).
+
1. If you removed references and deployment does not succeed, try deleting the contents of the c:\\DriverTest\\Drivers folder on the target machine, and then retry deployment.
### Manual deployment (root enumerated)
-Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
+Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](https://docs.microsoft.com/windows-hardware/drivers/devtest/devcon) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\Umdf2toaster).
+
1. On the target computer, open a Command Prompt window as Administrator. Navigate to your driver package folder, and enter a command such as:
- **devcon install wdfsimpleum.inf root\\toaster**
+ `devcon install wdfsimpleum.inf root\\toaster`
### View the root enumerated driver in Device Manager
@@ -61,6 +58,6 @@ In Device Manager, on the **View** menu, choose **Devices by connection**. Locat
As an alternative to building the driver sample in Visual Studio, you can build it in a Visual Studio Command Prompt window. In Visual Studio, on the **Tools** menu, choose **Visual Studio Command Prompt**. In the Visual Studio Command Prompt window, navigate to the folder that has the solution file, Umdf2toaster.sln. Use the MSBuild command to build the solution. Here is an example:
-**msbuild /p:configuration="Release" /p:platform="Win32" Umdf2toaster.sln**
+`msbuild /p:configuration="Release" /p:platform="Win32" Umdf2toaster.sln`
-For more information about using MSBuild to build a driver package, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644).
+For more information about using MSBuild to build a driver package, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver).
diff --git a/general/toaster/umdf2/filter/generic/filter.c b/general/toaster/umdf2/filter/generic/filter.c
index d245c2ba..b2897dc5 100644
--- a/general/toaster/umdf2/filter/generic/filter.c
+++ b/general/toaster/umdf2/filter/generic/filter.c
@@ -67,7 +67,7 @@ Return Value:
KdPrint(("Toaster Generic Filter Driver Sample - Driver Framework Edition.\n"));
//
- // Initiialize driver config to control the attributes that
+ // Initialize driver config to control the attributes that
// are global to the driver. Note that framework by default
// provides a driver unload routine. If you create any resources
// in the DriverEntry and want to be cleaned in driver unload,
diff --git a/general/toaster/umdf2/func/featured/toaster.c b/general/toaster/umdf2/func/featured/toaster.c
index c25eebd4..157c1843 100644
--- a/general/toaster/umdf2/func/featured/toaster.c
+++ b/general/toaster/umdf2/func/featured/toaster.c
@@ -75,7 +75,7 @@ Return Value:
KdPrint(("WDF Toaster Function Driver Sample - Featured version\n"));
//
- // Initiialize driver config to control the attributes that
+ // Initialize driver config to control the attributes that
// are global to the driver. Note that framework by default
// provides a driver unload routine. If you create any resources
// in the DriverEntry and want to be cleaned in driver unload,
diff --git a/general/toaster/umdf2/func/simple/toaster.c b/general/toaster/umdf2/func/simple/toaster.c
index 6ed215db..7b117240 100644
--- a/general/toaster/umdf2/func/simple/toaster.c
+++ b/general/toaster/umdf2/func/simple/toaster.c
@@ -72,7 +72,7 @@ Return Value:
KdPrint(("Toaster Function Driver Sample - Driver Framework Edition.\n"));
//
- // Initiialize driver config to control the attributes that
+ // Initialize driver config to control the attributes that
// are global to the driver. Note that framework by default
// provides a driver unload routine. If DriverEntry creates any resources
// that require clean-up in driver unload,
diff --git a/general/tracing/SystemTraceControl/README.md b/general/tracing/SystemTraceControl/README.md
index bf94caa7..4a4335f4 100644
--- a/general/tracing/SystemTraceControl/README.md
+++ b/general/tracing/SystemTraceControl/README.md
@@ -5,23 +5,15 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: System Trace Control
- platform: Application
- language: cpp
- category: General Tracing
- description: Demonstrates how to use event tracing control APIs to collect events from the system trace provider.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617725
---->
-
# SystemTraceProvider
This sample application demonstrates how to use event tracing control APIs to collect events from the system trace provider.
-The sample code provided shows how to start an [Event Tracing](http://msdn.microsoft.com/en-us/library/windows/hardware/bb968803) for Windows trace session and how to enable system events with stacks. When you build and run the application, it collects the trace data for 30 seconds and then stops. The sample application writes the results to a file, Systemtrace.etl. For more information, see [Tools for Software Tracing](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552961).
+The sample code provided shows how to start an [Event Tracing](https://docs.microsoft.com/windows/win32/etw/event-tracing-portal) for Windows trace session and how to enable system events with stacks. When you build and run the application, it collects the trace data for 30 seconds and then stops. The sample application writes the results to a file, Systemtrace.etl. For more information, see [Tools for Software Tracing](https://docs.microsoft.com/windows-hardware/drivers/devtest/tools-for-software-tracing).
-You can process the Systemtrace.etl file using Tracerpt.exe, a command-line trace tool included in Windows that formats trace events. It also analyzes the events and generates summary reports. For more information about how to use this tool, see [Tracerpt](http://go.microsoft.com/fwlink/p/?linkid=179389) topic on the TechNet website.
+You can process the Systemtrace.etl file using Tracerpt.exe, a command-line trace tool included in Windows that formats trace events. It also analyzes the events and generates summary reports. For more information about how to use this tool, see [Tracerpt](https://docs.microsoft.com/windows-server/administration/windows-commands/tracerpt_1).
-You can also process the file using the [Windows Performance Toolkit](http://go.microsoft.com/fwlink/p/?linkid=250774) (WPT), which is available in the SDK.
+You can also process the file using the [Windows Performance Toolkit](https://docs.microsoft.com/windows-hardware/test/wpt/) (WPT), which is available in the SDK.
diff --git a/general/tracing/evntdrv/README.md b/general/tracing/evntdrv/README.md
index 588e7894..cf2d5f06 100644
--- a/general/tracing/evntdrv/README.md
+++ b/general/tracing/evntdrv/README.md
@@ -5,36 +5,28 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Eventdrv
- platform: Application
- language: cpp
- category: General Tracing
- description: Demonstrates the use of the Event Tracing for Windows (ETW) API in a driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617724
---->
-
# Eventdrv
-Eventdrv is a sample kernel-mode trace provider and driver. The driver does not control any hardware; it simply generates trace events. It is designed to demonstrate the use of the [Event Tracing for Windows (ETW)](http://msdn.microsoft.com/en-us/library/windows/hardware/ff545699) API in a driver.
+Eventdrv is a sample kernel-mode trace provider and driver. The driver does not control any hardware; it simply generates trace events. It is designed to demonstrate the use of the [Event Tracing for Windows (ETW)](https://docs.microsoft.com/windows-hardware/drivers/devtest/event-tracing-for-windows--etw-) API in a driver.
-Evntdrv registers as a provider by calling the [**EtwRegister**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff545603) API. If the registration is successful, it logs a StartEvent with the device's name, the length of the name, and the status code. Then, when the sample receives a DeviceIOControl call, it logs a SampleEventA event. Finally, when the driver gets unloaded, it logs an UnloadEvent event with a pointer to the device object
+Evntdrv registers as a provider by calling the [**EtwRegister**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/nf-wdm-etwregister) API. If the registration is successful, it logs a StartEvent with the device's name, the length of the name, and the status code. Then, when the sample receives a DeviceIOControl call, it logs a SampleEventA event. Finally, when the driver gets unloaded, it logs an UnloadEvent event with a pointer to the device object
-**Note** The Windows Pre-Processor (WPP) Tracing tools such as TraceView.exe cannot be used to start, stop, or view traces.
+> [!NOTE]
+> The Windows Pre-Processor (WPP) Tracing tools such as TraceView.exe cannot be used to start, stop, or view traces.
## Run the sample
1. Install the manifest (Evntdrv.xml), which is located in the Evntdrv\\Eventdrv folder. Open a Visual Studio Command window (Run as administrator) and use the following command:
- ```
- wevtutil im evntdrv.xml
- ```
+ `wevtutil im evntdrv.xml`
+
+ Installing the manifest creates registry keys that enable tools to find the resource and message files that contain event provider information. For further details, see [wevtutil](https://docs.microsoft.com/windows-server/administration/windows-commands/wevtutil).
- Installing the manifest creates registry keys that enable tools to find the resource and message files that contain event provider information. For further details about the WevtUtil.exe tool, see the MSDN Library.
-
- **Note** Using a Visual Studio Command windows sets up the environment variables you need to run the tracing tools for this sample.
+ > [!NOTE]
+ > Using a Visual Studio Command windows sets up the environment variables you need to run the tracing tools for this sample.
1. Make a folder in the system directory called ETWDriverSample (for example, C:\\ETWDriverSample).
@@ -44,32 +36,24 @@ Evntdrv registers as a provider by calling the [**EtwRegister**](http://msdn.mic
1. Use Tracelog to start a trace session that is called "TestEventdrv." The following command starts the trace session and creates a trace log file, Eventdrv.etl, in the local directory.
- ```
- Tracelog -start TestEventdrv -guid #b5a0bda9-50fe-4d0e-a83d-bae3f58c94d6 -f Eventdrv.etl
- ```
+ `tracelog -start TestEventdrv -guid #b5a0bda9-50fe-4d0e-a83d-bae3f58c94d6 -f Eventdrv.etl`
1. To generate trace messages, run Evntctrl.exe. Each time you type a character other than **Q** or **q**, Evntctrl sends an IOCTL to the driver that signals it to generate trace messages. To stop Evntctrl, type **Q** or **q**.
1. To stop the trace session, run the following command:
- ```
- tracelog -stop TestEventdrv
- ```
+ `tracelog -stop TestEventdrv`
1. To display the traces collected in the Tracedrv.etl file, run the following command:
- ```
- tracerpt Eventdrv.etl
- ```
+ `tracerpt Eventdrv.etl`
This command creates two files: Summary.txt and Dumpfile.xml. Dumpfile.xml will contain the event information in an XML format.
1. To uninstall the manifest, run the following command:
- ```
- wevtutil um evntdrv.xml
- ```
+ `wevtutil um evntdrv.xml`
## Notes
-If you are building the Eventdrv sample to test on a 64-bit version of Windows, you need to sign the driver. All 64-bit versions of Windows require driver code to have a digital signature for the driver to load. See [Signing a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554809) and [Signing a Driver During Development and Testing](http://msdn.microsoft.com/en-us/library/windows/hardware/hh967733). You might also need to configure the test computer so that it can load test-signed kernel mode code, see [The TESTSIGNING Boot Configuration Option](http://msdn.microsoft.com/en-us/library/windows/hardware/ff553484) and [**BCDEdit /set**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff542202).
+If you are building the Eventdrv sample to test on a 64-bit version of Windows, you need to sign the driver. All 64-bit versions of Windows require driver code to have a digital signature for the driver to load. See [Signing a Driver](https://docs.microsoft.com/windows-hardware/drivers/develop/signing-a-driver) and [Signing a Driver During Development and Testing](https://docs.microsoft.com/windows-hardware/drivers/install/signing-drivers-during-development-and-test). You might also need to configure the test computer so that it can load test-signed kernel mode code, see [The TESTSIGNING Boot Configuration Option](https://docs.microsoft.com/windows-hardware/drivers/install/the-testsigning-boot-configuration-option) and [**BCDEdit /set**](https://docs.microsoft.com/windows-hardware/drivers/devtest/bcdedit--set).
diff --git a/general/tracing/tracedriver/README.md b/general/tracing/tracedriver/README.md
index c050eedf..3d32e0b6 100644
--- a/general/tracing/tracedriver/README.md
+++ b/general/tracing/tracedriver/README.md
@@ -5,33 +5,26 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Tracedrv
- platform: Application
- language: cpp
- category: General Tracing
- description: A sample driver instrumented for software tracing.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617726
---->
-
# Tracedrv
Tracedrv is a sample driver instrumented for software tracing. The driver does not control any hardware; it simply generates trace messages. It is designed to show how to use WPP software tracing macros in a driver.
Tracedrv initializes tracing (by using WPP\_INIT\_TRACING) and, when it receives a DeviceIOControl call, it starts a thread that logs 100 trace messages. The WPP software tracing directives, calls, and macros in the code are accompanied by comments that explain their purpose
-While examining Tracedrv, read the [WPP Software Tracing](http://msdn.microsoft.com/en-us/library/windows/hardware/ff556204) in the Windows Driver Kit (WDK). This section includes a reference section that describes the directives, macros, and calls required for WPP software tracing.
+While examining Tracedrv, read the [WPP Software Tracing](https://docs.microsoft.com/windows-hardware/drivers/devtest/wpp-software-tracing) in the Windows Driver Kit (WDK). This section includes a reference section that describes the directives, macros, and calls required for WPP software tracing.
## Run the sample
To test the Tracedrv event tracing provider, use the following procedure.
1. Copy the Tracectl.exe file that was created when you built the Tracedrv solution from the Tracectl directory (for example, \\Documents\\Visual Studio 2015\\Projects\\tracedrv\\tracectl\\*platform*) to the Tracedrv directory (for example, \\Documents\\Visual Studio 2015\\Projects\\tracedrv\\tracedrv\\*platform*).
+
1. Use Tracepdb to create a trace message format (TMF) file and a trace message control (TMC) file from the Tracedrv.pdb file. Tracepdb is located in the C:\\Program Files (x86)\\Windows Kits\\10\\bin\\*platform* directory. The PDB file that is used in this command is created when you the build the solution. Open a Visual Studio Command prompt window and navigate to the target build platform and configuration directory. Type the following command:
- **tracepdb -f tracedrv.pdb**
+ `tracepdb -f tracedrv.pdb`
1. In the same Tracedrv target build directory, create a control GUID file for Tracedrv by opening a text file, adding the following content, and saving the file as Tracedrv.ctl.
@@ -41,26 +34,22 @@ To test the Tracedrv event tracing provider, use the following procedure.
1. Use Tracelog to start a trace session that is called *TestTracedrv*. Tracelog is located in the C:\\Program Files (x86)\\Windows Kits\\10\\bin\\*platform* directory. The Tracedrv.ctl file that is used in this command was created in the previous step. The following command starts a trace session and creates a trace log file, tracedrv.etl, in the local directory.
- ```
- tracelog -start TestTracedrv -guid tracedrv.ctl -f tracedrv.etl -flag 1
- ```
+ `tracelog -start TestTracedrv -guid tracedrv.ctl -f tracedrv.etl -flag 1`
- **Note** Without the -flag parameter, Tracedrv will not generate any trace messages.
+ > [!NOTE]
+ > Without the -flag parameter, Tracedrv will not generate any trace messages.
1. To generate trace messages, run Tracectl.exe. This executable file is built when you build the solution. Each time you type a character, other than **Q** or **q**, Tracectl sends an IOCTL to the driver that signals it to generate trace messages. To stop Tracectl, type **Q** or **q**.
+
1. To stop the trace session, use the following Tracelog command.
- ```
- tracelog -stop TestTracedrv
- ```
+ `tracelog -stop TestTracedrv`
1. To display the trace messages in the Tracedrv.etl file, use Tracefmt.exe. Tracefmt.exe is located in the C:\\Program Files (x86)\\Windows Kits\\10\\bin\\*platform*. The TMF file used in this command was created by Tracepdb.exe in step 2. The **-p** option specifies the directory of the TMF file. In this case, the TMF file is in the current directory. Type the following command:
- ```
- tracefmt tracedrv.etl -p . -o Tracedrv.out
- ```
+ `tracefmt tracedrv.etl -p . -o Tracedrv.out`
-The resulting Tracedrv.out file is a human-readable text file of the Tracedrv trace messages. To interpret the trace messages, in the Tracedrv.c file, search for the [**DoTraceMessage**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544918) macros.
+The resulting Tracedrv.out file is a human-readable text file of the Tracedrv trace messages. To interpret the trace messages, in the Tracedrv.c file, search for the [**DoTraceMessage**](https://docs.microsoft.com/previous-versions/windows/hardware/previsioning-framework/ff544918(v=vs.85)) macros.
## Notes
@@ -68,6 +57,6 @@ This sample driver should not be used in a production environment.
Also, because it is not a Plug and Play driver, Tracedrv does not demonstrate tracing in a Plug and Play environment.
-Tracedrv demonstrates the basic elements required for software tracing. It does not demonstrate more advanced tracing techniques, such as writing customized tracing calls (variations of [**DoTraceMessage**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544918)), or the use of WMI calls for software tracing.
+Tracedrv demonstrates the basic elements required for software tracing. It does not demonstrate more advanced tracing techniques, such as writing customized tracing calls (variations of [**DoTraceMessage**](https://docs.microsoft.com/previous-versions/windows/hardware/previsioning-framework/ff544918(v=vs.85))), or the use of WMI calls for software tracing.
-If you are building the Tracedrv sample to test on a 64-bit version of Windows, you need to sign the driver. All 64-bit versions of Windows require driver code to have a digital signature for the driver to load. See [Signing a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554809) and [Signing a Driver During Development and Testing](http://msdn.microsoft.com/en-us/library/windows/hardware/hh967733). You might also need to configure the test computer so that it can load test-signed kernel mode code, see [The TESTSIGNING Boot Configuration Option](http://msdn.microsoft.com/en-us/library/windows/hardware/ff553484) and [**BCDEdit /set**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff542202).
+If you are building the Tracedrv sample to test on a 64-bit version of Windows, you need to sign the driver. All 64-bit versions of Windows require driver code to have a digital signature for the driver to load. See [Signing a Driver](https://docs.microsoft.com/windows-hardware/drivers/develop/signing-a-driver) and [Signing a Driver During Development and Testing](https://docs.microsoft.com/windows-hardware/drivers/install/signing-drivers-during-development-and-test). You might also need to configure the test computer so that it can load test-signed kernel mode code, see [The TESTSIGNING Boot Configuration Option](https://docs.microsoft.com/windows-hardware/drivers/install/the-testsigning-boot-configuration-option) and [**BCDEdit /set**](https://docs.microsoft.com/windows-hardware/drivers/devtest/bcdedit--set).
diff --git a/general/umdfSkeleton/README.md b/general/umdfSkeleton/README.md
index 05cc5cb6..59a5f25b 100644
--- a/general/umdfSkeleton/README.md
+++ b/general/umdfSkeleton/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: UMDF Driver Skeleton Sample (UMDF version 1)
- platform: UMDF1
- language: cpp
- category: General WDF
- description: Demonstrates how to use UDMF to write a minimal driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617727
---->
-
# UMDF Driver Skeleton Sample (UMDF Version 1)
This sample demonstrates how to use version 1 of the User-Mode Driver Framework to write a minimal driver.
diff --git a/gnss/ReadMe.md b/gnss/ReadMe.md
index 31ba855d..76a5acc8 100644
--- a/gnss/ReadMe.md
+++ b/gnss/ReadMe.md
@@ -1,21 +1,13 @@
---
-topic: sample
+page_type: sample
description: "Provides base sample driver that IHVs and partners can use to extend to build their custom Windows GPS/GNSS drivers."
languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: GPS/GNSS UMDF Sample Driver (UMDF Version 2)
- platform: UMDF2
- language: cpp
- category: GPS/GNSS
- description: Provides base sample driver that IHVs and partners can use to extend to build their custom Windows GPS/GNSS drivers
- samplefwlink: https://go.microsoft.com/fwlink/?linkid=2045369
---->
-
# GNSS UMDF Sample Driver (UMDF Version 2)
Provides a base sample driver that IHVs and partners can use to extend to build their custom Windows GPS/GNSS drivers.
@@ -24,37 +16,51 @@ Provides a base sample driver that IHVs and partners can use to extend to build
### What is covered
-* This is a sample that adheres to GNSS driver design for Windows 10 outlined in the [GNSS driver design guide for Windows 10](https://docs.microsoft.com/windows-hardware/drivers/gnss/gnss-driver-design-guide-for-windows-10).
-* Serves as base sample driver that IHVs and partners can use as a template and guidance to extend to build their custom Windows GNSS drivers.
-* Follows the WDF guidelines and best practices around PnP device arrival/removal, power management and driver installation/uninstallation.
-* Supports the GNSS DDI mandatory requirements.
-* This driver successfully passes HLK tests and WDF tests provided by Visual studio.
+- This is a sample that adheres to GNSS driver design for Windows 10 outlined in the [GNSS driver design guide for Windows 10](https://docs.microsoft.com/windows-hardware/drivers/gnss/gnss-driver-design-guide-for-windows-10).
+
+- Serves as base sample driver that IHVs and partners can use as a template and guidance to extend to build their custom Windows GNSS drivers.
+
+- Follows the WDF guidelines and best practices around PnP device arrival/removal, power management and driver installation/uninstallation.
+
+- Supports the GNSS DDI mandatory requirements.
+
+- This driver successfully passes HLK tests and WDF tests provided by Visual studio.
### What is not covered
-* This sample currently doesn't support Geofence, SUPL, and AGNSS, as this is not mandatory GNSS DDI functionality.
-* SUPL and AGNSS are mandatory only if required by mobile operator, and the sample does not support them currently.
-* Not a production driver.
+- This sample currently doesn't support Geofence, SUPL, and AGNSS, as this is not mandatory GNSS DDI functionality.
+
+- SUPL and AGNSS are mandatory only if required by mobile operator, and the sample does not support them currently.
+
+- Not a production driver.
### What a Partner needs to do
-* Customer can install WDK and run Location HLK tests to validate their driver. All test cases should be either pass or skip without failure.
-* Partner owns the following:
- * Installing the driver.
- * Adding certificate and driver signing.
- * Updating manufacturer name driver version etc. (the code has comments to update).
-* The GNSS sample code has "FIX ME" comments. Partner should update them accordingly.
+- Customer can install WDK and run Location HLK tests to validate their driver. All test cases should be either pass or skip without failure.
+
+- Partner owns the following:
+
+ - Installing the driver.
+
+ - Adding certificate and driver signing.
+
+ - Updating manufacturer name driver version etc. (the code has comments to update).
+
+- The GNSS sample code has "FIX ME" comments. Partner should update them accordingly.
## Design
-* The sample demonstrates a very basic software only driver that meets the minimum requirements from the GNSS DDI.
-* The sample currently always returns a fake hardcoded location. Driver developers can extend this to fetch fake positions from a file or inject through a custom IOCTL or instead implement getting real positions from GNSS hardware.
-* Driver developer can extend this to pull the fake positions from a file or through custom IOCTLs if needed.
+- The sample demonstrates a very basic software only driver that meets the minimum requirements from the GNSS DDI.
+
+- The sample currently always returns a fake hardcoded location. Driver developers can extend this to fetch fake positions from a file or inject through a custom IOCTL or instead implement getting real positions from GNSS hardware.
+
+- Driver developer can extend this to pull the fake positions from a file or through custom IOCTLs if needed.
## Trace Logging
-* The sample code provides Trace logging WPRP file.
-* To capture trace log, copy GnssUmdfSampleDriver.wprp in the solution folder into the device under test. On command line (MyLog.etl is an example file name below):
+- The sample code provides Trace logging WPRP file.
+
+- To capture trace log, copy GnssUmdfSampleDriver.wprp in the solution folder into the device under test. On command line (MyLog.etl is an example file name below):
```cmd
wpr -start GnssUmdfSampleDriver.wprp -filemode
@@ -62,7 +68,7 @@ Provides a base sample driver that IHVs and partners can use to extend to build
wpr -stop MyLog.etl
```
-* Inspect MyLog.etl with trace file analyzer. Note that corresponding PDB file is needed to decode the logging information.
+- Inspect MyLog.etl with trace file analyzer. Note that corresponding PDB file is needed to decode the logging information.
## Test Plan
@@ -70,29 +76,42 @@ Customer should validate their driver after customizing it.
### Test method 1
-* This tests WDF fundamental functionality (PnP etc.), rather than Location-specific features.
-* Run Visual studio built-in run-time test for WDF.
-* General information available at [](https://docs.microsoft.com/windows-hardware/drivers/develop/testing-a-driver-at-runtime).
-* Expected result / Pass criteria: Pass rate 100%
+- This tests WDF fundamental functionality (PnP etc.), rather than Location-specific features.
+
+- Run Visual studio built-in run-time test for WDF.
+
+- General information available at [](https://docs.microsoft.com/windows-hardware/drivers/develop/testing-a-driver-at-runtime).
+
+- Expected result / Pass criteria: Pass rate 100%
### Test method 2
-* This tests Location-specific functionality (Getting fix etc.).
-* Run [HLK](https://docs.microsoft.com/windows-hardware/test/hlk/windows-hardware-lab-kit) tests with existing and standard GNSS driver tests.
-* Run "TE.exe GNSSDriverTest.dll".
-* Expected result / Pass criteria: Pass rate 100%
-* Note that this sample does not support AGNSS, SUPL and Geofencing currently. Based on the capability of driver, HLK skips them automatically.
+- This tests Location-specific functionality (Getting fix etc.).
+
+- Run [HLK](https://docs.microsoft.com/windows-hardware/test/hlk/windows-hardware-lab-kit) tests with existing and standard GNSS driver tests.
+
+- Run "TE.exe GNSSDriverTest.dll".
+
+- Expected result / Pass criteria: Pass rate 100%
+
+- Note that this sample does not support AGNSS, SUPL and Geofencing currently. Based on the capability of driver, HLK skips them automatically.
### Test method 3
-* Test the [Windows Geolocation API](https://docs.microsoft.com/windows/desktop/locationapi/windows-location-api-portal) layer on real apps.
-* Get current location by clicking on "Show my location" from the In-box Windows Maps app.
-* Run the tracking scenario from the [Geolocation Sample app](https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/Geolocation).
-* Get current location by clicking on "Start" from GPS Satellite app in Windows Store.
+- Test the [Windows Geolocation API](https://docs.microsoft.com/windows/desktop/locationapi/windows-location-api-portal) layer on real apps.
+
+- Get current location by clicking on "Show my location" from the In-box Windows Maps app.
+
+- Run the tracking scenario from the [Geolocation Sample app](https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/Geolocation).
+
+- Get current location by clicking on "Start" from GPS Satellite app in Windows Store.
## Resources
-* [GNSS DDI reference](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/gnssdriver/index)
-* [Getting started with Windows drivers](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted)
-* [Windows Driver Kit documentation](https://docs.microsoft.com/windows-hardware/drivers)
-* [NMEA format documentation](http://navspark.mybigcommerce.com/content/NMEA_Format_v0.1.pdf) \ No newline at end of file
+[GNSS DDI reference](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/gnssdriver/index)
+
+[Getting started with Windows drivers](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted)
+
+[Windows Driver Kit documentation](https://docs.microsoft.com/windows-hardware/drivers)
+
+[NMEA format documentation](https://navspark.mybigcommerce.com/content/NMEA_Format_v0.1.pdf)
diff --git a/gpio/samples/README.md b/gpio/samples/README.md
index 57a0170a..b2a8c7b7 100644
--- a/gpio/samples/README.md
+++ b/gpio/samples/README.md
@@ -5,26 +5,18 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: GPIO Sample Drivers
- platform: KMDF UMDF1
- language: cpp
- category: GPIO
- description: Illustrates how to write a GPIO controller driver that works in conjunction with the GPIO framework extension (GpioClx).
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617729
---->
-
# GPIO Sample Drivers
-The GPIO samples contain annotated code to illustrate how to write a [GPIO controller driver](http://msdn.microsoft.com/en-us/library/windows/hardware/hh439509) that works in conjunction with the [GPIO framework extension](http://msdn.microsoft.com/en-us/library/windows/hardware/hh439512) (GpioClx) to handle GPIO I/O control requests, and a peripheral driver that runs in kernel mode and uses GPIO resources. For a sample that shows how to write a GPIO peripheral driver that runs in user mode, please refer to the SPB accelerometer sample driver (SPB\\peripherals\\accelerometer).
+The GPIO samples contain annotated code to illustrate how to write a [GPIO controller driver](https://docs.microsoft.com/windows-hardware/drivers/gpio/index) that works in conjunction with the [GPIO framework extension](https://docs.microsoft.com/windows-hardware/drivers/gpio/gpio-driver-support-overview) (GpioClx) to handle GPIO I/O control requests, and a peripheral driver that runs in kernel mode and uses GPIO resources.
The GPIO sample set contains the following samples:
-Minifilter | Sample Description
------------|-------------------
-SimGpio | The files in this sample contain the source code for a GPIO controller driver that communicates with GpioClx through the GpioClx device driver interface (DDI). The GPIO controller driver is written for a hypothetical memory-mapped GPIO controller (simgpio). The code is meant to be purely instructional. An ASL file illustrates how to specify a GPIO interrupt and I/O descriptor in the ACPI firmware.
-SimGpio_I2C | The files in this sample contain the source code for a GPIO controller driver that communicates with GpioClx through the GpioClx DDI. In contrast to the SimGpio sample, the GPIO controller in this sample is not memory-mapped. The GPIO controller driver is written for a hypothetical GPIO controller that resides on an I2C bus (simgpio_i2c). The code is meant to be purely instructional. An ASL file illustrates how to specify a GPIO interrupt and I/O descriptor in the ACPI firmware.
-SimDevice\kmdf | The purpose of this sample is to show how a driver opens a device and performs I/O operations on a GPIO controller in kernel mode. Additionally, this sample demonstrates how the driver connects to a GPIO interrupt resource. The ASL file illustrates how to specify a GPIO interrupt and I/O descriptor in the ACPI firmware.
-SimDevice\umdf | The purpose of this sample is to show how a driver opens a device and performs I/O operations on a GPIO controller in user mode. Additionally, this sample demonstrates how the driver connects to a GPIO interrupt resource. The ASL file illustrates how to specify a GPIO interrupt and I/O descriptor in the ACPI firmware. \ No newline at end of file
+| Minifilter | Sample description |
+| --- | --- |
+| SimGpio | The files in this sample contain the source code for a GPIO controller driver that communicates with GpioClx through the GpioClx device driver interface (DDI). The GPIO controller driver is written for a hypothetical memory-mapped GPIO controller (simgpio). The code is meant to be purely instructional. An ASL file illustrates how to specify a GPIO interrupt and I/O descriptor in the ACPI firmware. |
+| SimGpio_I2C | The files in this sample contain the source code for a GPIO controller driver that communicates with GpioClx through the GpioClx DDI. In contrast to the SimGpio sample, the GPIO controller in this sample is not memory-mapped. The GPIO controller driver is written for a hypothetical GPIO controller that resides on an I2C bus (simgpio_i2c). The code is meant to be purely instructional. An ASL file illustrates how to specify a GPIO interrupt and I/O descriptor in the ACPI firmware. |
+| SimDevice\kmdf | The purpose of this sample is to show how a driver opens a device and performs I/O operations on a GPIO controller in kernel mode. Additionally, this sample demonstrates how the driver connects to a GPIO interrupt resource. The ASL file illustrates how to specify a GPIO interrupt and I/O descriptor in the ACPI firmware. |
+| SimDevice\umdf | The purpose of this sample is to show how a driver opens a device and performs I/O operations on a GPIO controller in user mode. Additionally, this sample demonstrates how the driver connects to a GPIO interrupt resource. The ASL file illustrates how to specify a GPIO interrupt and I/O descriptor in the ACPI firmware. |
diff --git a/gpio/samples/simdevice/umdf/simdeviceumdf.inx b/gpio/samples/simdevice/umdf/simdeviceumdf.inx
index e19f9f2c..5493ece4 100644
--- a/gpio/samples/simdevice/umdf/simdeviceumdf.inx
+++ b/gpio/samples/simdevice/umdf/simdeviceumdf.inx
Binary files differ
diff --git a/hid/firefly/README.md b/hid/firefly/README.md
index 2b25ff9f..0d89b356 100644
--- a/hid/firefly/README.md
+++ b/hid/firefly/README.md
@@ -5,55 +5,60 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: KMDF filter driver for a HID device
- platform: KMDF
- language: cpp
- category: HID
- description: Illustrates using remote I/O target interfaces to open a HID collection in kernel-mode and send IOCTL requests to set and get feature reports.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620192
---->
-
# KMDF filter driver for a HID device
Firefly is a KMDF-based filter driver for a HID device. Along with illustrating how to write a filter driver, this sample shows how to use remote I/O target interfaces to open a HID collection in kernel-mode and send IOCTL requests to set and get feature reports, as well as how an application can use WMI interfaces to send commands to a filter driver.
## Related topics
-[Human Input Devices Design Guide](http://msdn.microsoft.com/en-us/library/windows/hardware/ff539952)
+[Human Input Devices Design Guide](https://docs.microsoft.com/windows-hardware/drivers/hid)
-[Human Input Devices Reference](http://msdn.microsoft.com/en-us/library/windows/hardware/ff539956)
+[Human Input Devices Reference](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/_hid)
## Related technologies
-[Creating Framework-based HID Minidrivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff540774)
+[Creating Framework-based HID Minidrivers](https://docs.microsoft.com/previous-versions//ff540774(v=vs.85))
## Build the sample
-For information on how to build a driver using Microsoft Visual Studio, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644). When you build the sample, MSBuild.exe creates luminous.lib, firefly.sys, flicker.exe, and sauron.dll. Copy these files as well as the KMDF coinstaller (wdfcoinstallerMMmmm.dll) and the INF file (firefly.inf) to a floppy disk or a temporary directory on the target system.
+For information on how to build a driver using Microsoft Visual Studio, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver). When you build the sample, MSBuild.exe creates luminous.lib, firefly.sys, flicker.exe, and sauron.dll. Copy these files as well as the KMDF coinstaller (wdfcoinstallerMMmmm.dll) and the INF file (firefly.inf) to a floppy disk or a temporary directory on the target system.
-**Note** You can obtain redistributable framework updates by downloading the **wdfcoinstaller.msi** package from [WDK 8 Redistributable Components](http://go.microsoft.com/fwlink/p/?LinkID=226396). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0.
+> [!NOTE]
+> You can obtain redistributable framework updates by downloading the **wdfcoinstaller.msi** package from [WDK 8 Redistributable Components](https://go.microsoft.com/fwlink/p/?LinkID=253170). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0.
## Installation
To install the driver:
1. Plug the Microsoft USB Optical mouse into your target machine and verify that the mouse works. The drivers for this mouse come with the operating system so the device will start working automatically when you plug in.
+
1. You may need to make Group Policy changes in order to replace the existing mouse driver. If you are unable to perform steps 3-9, do the following:
- 1. Open **gpedit.msd**.
- 1. In the Group Policy Object Editor navigation pane, open the Computer Configuration folder. Then open Administrative Templates, open System, open Device Installation, and then open Device Installation Restrictions.
- 1. Enable *Prevent installation of devices not described by other policy settings*. This will prevent Windows from automatically installing the default mouse driver so that you can then install Firefly.
- 1. Enable *Allow administrators to override device installation policy*. This will allow you to bypass the ""The installation of this device is forbidden by system policy" error that you may otherwise receive when you attempt to install Firefly.
- 1. You may need to reboot.
+
+ 1. Open **gpedit.msd**.
+
+ 1. In the Group Policy Object Editor navigation pane, open the Computer Configuration folder. Then open Administrative Templates, open System, open Device Installation, and then open Device Installation Restrictions.
+
+ 1. Enable *Prevent installation of devices not described by other policy settings*. This will prevent Windows from automatically installing the default mouse driver so that you can then install Firefly.
+
+ 1. Enable *Allow administrators to override device installation policy*. This will allow you to bypass the ""The installation of this device is forbidden by system policy" error that you may otherwise receive when you attempt to install Firefly.
+
+ 1. You may need to reboot.
1. Bring up the Device Manager (type **devmgmt.msc** in the Start/Run window and press enter).
+
1. Find the Microsoft Optical mouse under "Mice and other pointing devices"
+
1. Right click on the device and choose "Update Driver Software."
+
1. Select "Browse my computer for driver software."
+
1. Browse to the temporary folder you created earlier. Click Next. Click through the warning.
+
1. You will see "Windows has successfully updated your driver software" for the "Shiny Things Firefly Mouse" device.
+
1. The system will copy all the files and restart the mouse device to install the upper filter. Click Close and you are ready to run the test app.
## Testing the Sample
@@ -73,12 +78,19 @@ Usage: Flicker \<-0 | -1 | -2\>
The following description applies to Windows Media Player 12 running on Windows 7:
1. Copy the sauron.dll to the Windows Media player Visualization directory (C:\\Program Files\\Windows Media Player\\Visualizations).
+
1. Register the DLL with COM by calling "regsvr32 sauron.dll" in command shell.
+
1. Run Windows Media Player *as administrator*.
+
1. Click on the "Switch to Now Playing" button in the lower right of the application.
+
1. Right click, select Visualizations, and you will see a menu item called "Sauron."
+
1. Choose either Firefly Bars or Firefly Flash and play some music.
+
1. You will see the mouse light dancing to the tune of the music.
+
1. You can unregister the DLL by calling "regsvr32 -u sauron.dll".
## Programming Tour
@@ -87,7 +99,10 @@ The Firefly sample is installed as an upper filter driver for the Microsoft USB
The sample consists of:
-- Driver (firefly.sys): The Firefly driver is an upper device filter driver for the mouse driver (mouhid.sys). Firefly is a generic filter driver based on the toaster filter driver sample available in the WDK. During start device, the driver registers a WMI class (FireflyDeviceInformation). The user mode application connects to the WMI namespace (root\\wmi) and opens this class using COM interfaces. Then the application can make requests to read ("get") or change ("set") the current value of the TailLit data value from this class. In response to a set WMI request, the driver opens the HID collection using IoTarget and sends [**IOCTL\_HID\_GET\_COLLECTION\_INFORMATION**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff541092) and [**IOCTL\_HID\_GET\_COLLECTION\_DESCRIPTOR**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff541089) requests to get the preparsed data. The driver then calls [**HidP\_GetCaps**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff539715) using the preparsed data to retrieve the capabilities of the device. After getting the capabilities of the device, the driver creates a feature report to set or clear the feature that causes the light to toggle.
+- Driver (firefly.sys): The Firefly driver is an upper device filter driver for the mouse driver (mouhid.sys). Firefly is a generic filter driver based on the toaster filter driver sample available in the WDK. During start device, the driver registers a WMI class (FireflyDeviceInformation). The user mode application connects to the WMI namespace (root\\wmi) and opens this class using COM interfaces. Then the application can make requests to read ("get") or change ("set") the current value of the TailLit data value from this class. In response to a set WMI request, the driver opens the HID collection using IoTarget and sends [**IOCTL\_HID\_GET\_COLLECTION\_INFORMATION**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/hidclass/ni-hidclass-ioctl_hid_get_collection_information) and [**IOCTL\_HID\_GET\_COLLECTION\_DESCRIPTOR**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/hidclass/ni-hidclass-ioctl_hid_get_collection_descriptor) requests to get the preparsed data. The driver then calls [**HidP\_GetCaps**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/hidpi/nf-hidpi-hidp_getcaps) using the preparsed data to retrieve the capabilities of the device. After getting the capabilities of the device, the driver creates a feature report to set or clear the feature that causes the light to toggle.
+
- Library (luminous.lib): The sources for this file are located in the \\hid\\firefly\\lib folder. You will need to build the library before using it. This library is shared by the WDM and WDF samples. All the interfaces required to access the WMI is defined in this library and exposed as CLuminous class.
+
- Application (flicker.exe): The sources for this file are located in the \\hid\\firefly\\app folder. You will need to build the application before using it. This application is shared by the WDM and WDF samples. The application links to luminous.lib to open the WMI interfaces and send set requests to toggle the light.
+
- Sauron (sauron.dll): The sources for this file are located in the \\hid\\firefly\\sauron folder. You will need to build this dll before using it. The library is shared by the WDM and WDF samples. Sauron is a Windows Media Player visualization DLL, and is based on a sample from the Windows Media Player SDK kit. By using this DLL, you can cause the mouse lights to blink to the beats of the music.
diff --git a/hid/hclient/README.md b/hid/hclient/README.md
index 59b7edd3..591d7cea 100644
--- a/hid/hclient/README.md
+++ b/hid/hclient/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: HClient sample application
- platform: WDM
- language: cpp
- category: HID
- description: Demonstrates how to write a user-mode client application that communicates with HID devices.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617730
---->
-
# HClient sample application
The *HClient* sample demonstrates how to write a user-mode client application that communicates with HID devices. (These are devices that conform to the HID device class specification.)
@@ -24,6 +16,6 @@ You will find this sample useful if you need to develop an application that comm
## Related topics
-[Human Input Devices Design Guide](http://msdn.microsoft.com/en-us/library/windows/hardware/ff539952)
+[Human Input Devices Design Guide](https://docs.microsoft.com/windows-hardware/drivers/hid/)
-[Human Input Devices Reference](http://msdn.microsoft.com/en-us/library/windows/hardware/ff539956)
+[Human Input Devices Reference](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/_hid/)
diff --git a/hid/hclient/report.c b/hid/hclient/report.c
index f1d9ee55..02fb95a9 100644
--- a/hid/hclient/report.c
+++ b/hid/hclient/report.c
@@ -513,7 +513,7 @@ Routine Description:
ULONG i;
ULONG CurrReportID;
BOOLEAN result = FALSE;
-
+ PHID_DATA Head = Data;
/*
// All report buffers that are initially sent need to be zero'd out
*/
@@ -584,6 +584,7 @@ Routine Description:
// having been set.
*/
+ Data = Head;
for (i = 0; i < DataLength; i++, Data++)
{
if (CurrReportID == Data -> ReportID)
diff --git a/hid/hidusbfx2/README.md b/hid/hidusbfx2/README.md
index 3b4a8a24..db66a3be 100644
--- a/hid/hidusbfx2/README.md
+++ b/hid/hidusbfx2/README.md
@@ -5,48 +5,36 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: HIDUSBFX2 sample driver
- platform: KMDF
- language: cpp
- category: HID
- description: Demonstrates mapping of a non-HID USB device to a HID device.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620190
---->
-
# HIDUSBFX2 sample driver
The HIDUSBFX2 sample driver (hidusbfx2.sys) demonstrates how to map a non-HID USB device to a HID device.
-The sample also demonstrates how to write a HID minidriver using Windows Driver Frameworks (WDF). The minidriver is written for the [OSR USB-FX2 Learning Kit](http://www.osronline.com/hardware/OSRFX2_32.pdf). Although the device is not HID-compliant, the sample exposes it as a HID device.
+The sample also demonstrates how to write a HID minidriver using Windows Driver Frameworks (WDF). The minidriver is written for the [OSR USB-FX2 Learning Kit](https://www.osronline.com/hardware/OSRFX2_32.pdf). Although the device is not HID-compliant, the sample exposes it as a HID device.
+
+## Related topics
-Related topics
---------------
+[Human Input Devices Design Guide](https://docs.microsoft.com/windows-hardware/drivers/hid/)
-[Human Input Devices Design Guide](http://msdn.microsoft.com/en-us/library/windows/hardware/ff539952)
-[Human Input Devices Reference](http://msdn.microsoft.com/en-us/library/windows/hardware/ff539956)
+[Human Input Devices Reference](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/_hid/)
-Related technologies
---------------------
+## Related technologies
-[Creating Framework-based HID Minidrivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff540774)
-[Creating UMDF-based HID Minidrivers](http://msdn.microsoft.com/en-us/library/windows/hardware/hh439579)
+[Creating WDF HID Minidrivers](https://docs.microsoft.com/windows-hardware/drivers/wdf/creating-umdf-hid-minidrivers)
-Build the sample
-----------------
+## Build the sample
-For information on how to build a driver solution using Microsoft Visual Studio, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644).
+For information on how to build a driver solution using Microsoft Visual Studio, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver).
-Theory of Operation
--------------------
+## Theory of Operation
A HID USB device provides a HID descriptor (through an interface descriptor) that identifies the device as HID-compliant and enables the system-supplied HID minidriver (**hidusb.sys**) and the HID class driver to load, parse the HID descriptor, and enumerate child HID device stacks. The system provides strong support for HID devices, so you do not typically have to write a HID minidriver. However, there are cases in which you might need to write your own HID minidriver (for example, if it is difficult to make desired changes to HID-compliant device firmware or if you need to make a non-HID compliant device into a HID device without updating the firmware).
-**Overview of the Device**
+### Overview of the Device
-You can view the specification for the device in the [Using the OSR USB FX-2 Learning Kit](http://go.microsoft.com/fwlink/p/?linkid=64091) document.
+You can view the specification for the device in the [Using the OSR USB FX-2 Learning Kit](https://www.osronline.com/hardware/OSRFX2_32.pdf) document.
The device is loosely based on the development board that is supplied with the Cypress EZ-USB FX2 Development Kit (CY3681) and contains one interface and three endpoints (Interrupt IN, Bulk Out, and Bulk IN). The firmware supports vendor commands to query or set the LED bar graph display and 7-segment LED display, and to query toggle switch states.
@@ -54,7 +42,7 @@ The interrupt endpoint sends an 8-bit value that represents the state of the swi
Bulk endpoints are configured for loopback.
-**Overview of the Driver Stack**
+### Overview of the Driver Stack
Kernel-Mode Driver Framework (KMDF) does not support HID minidrivers natively because the HID architecture requires that the HID class driver (**hidclass.sys**) own the driver dispatch table for HID minidrivers. This requirement conflicts with the KMDF requirement that it own the driver dispatch table in order to handle Plug and Play (PnP), power, and I/O requests correctly.
@@ -62,217 +50,223 @@ You can resolve this ownership conflict by using a driver stack that consists of
The minimal function driver code is located in the \\hidusbfx2\\hidkmdf directory (the driver binary is named **hidkmdf.sys**), and the lower filter driver code is located in the \\hidusbfx2\\sys folder (the binary is named **hidusbfx2.sys**). The function driver is a minimal WDM driver and you can reuse it without any modification. Remember to rename the driver binary when you reuse it, to avoid a name conflict. You need to modify the KMDF filter driver according to your device's requirements.
-**Mapping a Non-HID USB Device to HID**
+### Mapping a Non-HID USB Device to HID
When the HIDclass driver queries the minidriver, the minidriver returns a hard-coded report descriptor that enables the HID class driver to create child devices as described by the report descriptor. The report descriptor has three top-level application collections:
-- Consumer control
+ Consumer control
-- System control
+- System control
-- Vendor-defined
+- Vendor-defined
The HID class driver creates a driver stack for each top-level collection. The operating system opens the consumer control and system control collections. These collections have input buttons and obtain data from the interrupt endpoint of the USB device. The vendor-defined collection exposes a feature button to control the 7-segment display and bar graph display. Any client application can open the vendor-defined collection to send feature requests.
-**Switch Pack Mapping**
+### Switch Pack Mapping
The switch pack on the USB device is mapped as hot keys that are commonly found on modern keyboards. This mapping is possible by exposing the switch pack as two system-supported collections: consumer control and system control. The consumer control collection provides a mapping for some application-launch and application-action keys, as shown in the following table. The system control collection provides a mapping for the power sleep function.
-Switch | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8
--------|---|---|---|---|---|---|---|---
-Mapping | Sleep | Calculator | Mail | Favorites | Refresh | Forward | Back | Browser
+| Switch | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- |
+| Mapping | Sleep | Calculator | Mail | Favorites | Refresh | Forward | Back | Browser |
-**Segment Display and Bar Graph**
+### Segment Display and Bar Graph
The segment display and bar graph are mapped as HID feature controls that you can manipulate by using the **HidD\_SetFeature** function from a user-mode application. The feature controls are mapped as vendor-defined usage page 0xff00. The SEVEN\_SEGMENT\_REPORT\_ID and BARGRAPH\_REPORT\_ID usages are listed in the following tables. You can also use **Hidclient.exe**, an application that is available in the Windows Driver Kit (WDK), to manipulate the segment display and bar graph. For more information about this mapping, see the following two tables.
-**Segment Display Mapping**
+### Segment Display Mapping
-Usage ID | 0xD7 | 0x06 | 0xB3 | 0xA7 | 0x66 | 0xE5 | 0xF4 | 0x07 | 0xF7 | 0x67
----------|------|------|------|------|------|------|------|------|------|------
-Mapping | Display 0 | Display 1 | Display 2 | Display 3 | Display 4 | Display 5 | Display 6 | Display 7 | Display 8 | Display 9
+| Usage ID | 0xD7 | 0x06 | 0xB3 | 0xA7 | 0x66 | 0xE5 | 0xF4 | 0x07 | 0xF7 | 0x67 |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
+| Mapping | Display 0 | Display 1 | Display 2 | Display 3 | Display 4 | Display 5 | Display 6 | Display 7 | Display 8 | Display 9 |
-**Bar Graph Mapping**
+### Bar Graph Mapping
Note that you can OR these values to light multiple LEDs.
-Usage ID | 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80 | 0xFF | 0x00
----------|------|------|------|------|------|------|------|------|------|------
-Mapping | LED 1 ON | LED 2 ON | LED 3 ON | LED 4 ON | LED 5 ON | LED 6 ON | LED 7 ON | LED 8 ON | All LEDS ON | All LEDS OFF
+| Usage ID | 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80 | 0xFF | 0x00 |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
+| Mapping | LED 1 ON | LED 2 ON | LED 3 ON | LED 4 ON | LED 5 ON | LED 6 ON | LED 7 ON | LED 8 ON | All LEDS ON | All LEDS OFF |
-**Support for Selective Suspend**
+### Support for Selective Suspend
The HID class driver provides support for selective suspend. The minidriver participates in this feature by handling HID class IOCTLs appropriately. To enable the selective suspend feature for your device, you need to add a "SelectiveSuspend" = 1 value in the registry in the device hardware key through the INF file. For an example, see the**hidusbfx2.inf** file.
-Installing the sample
----------------------
+## Installing the sample
If you adapt this driver for your device, update the INF file to match the hardware ID (VID, PID) and the device description text to match your test board/device.
To start installing the sample, you must:
-1. Build the driver and copy the following files to a folder on your hard drive:
+1. Build the driver and copy the following files to a folder on your hard drive:
- - **hidusbfx2.inf**
- - **hidusbfx2.sys**
- - **Hidkmdf.sys**
- - The WDF coinstaller from the *\<WDK ROOT\>\\redist\\wdf\\\<platform\>* directory.
+ - **hidusbfx2.inf**
- **Note** You can obtain redistributable framework updates by downloading the **wdfcoinstaller.msi** package from [WDK 8 Redistributable Components](http://go.microsoft.com/fwlink/p/?LinkID=226396). This package performs a silent install into the directory of your WDK installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0.
+ - **hidusbfx2.sys**
-2. Plug in the device and follow these steps:
- 1. Launch Device Manager by executing command devmgmt.msc in a command window, or from the **Hardware and Sound** program group in **Control Panel**.
- 2. Select **OSR USB-FX2 device** from **Other Devices** category and select **Update Driver Software...** from the right-click menu.
- 3. Select **Browse my computer for software** and provide the location of the driver files.
- 4. Select **Install this driver software anyway** when the Windows Security dialog box appears.
- 5. After the driver is installed, you should see the device in Device Manager under Human Interface Devices.
+ - **Hidkmdf.sys**
-Testing
--------
+ - The WDF coinstaller from the *\<WDK ROOT\>\\redist\\wdf\\\<platform\>* directory.
-**Testing Switches**
+ > [!NOTE]
+ > You can obtain redistributable framework updates by downloading the **wdfcoinstaller.msi** package from [WDK 8 Redistributable Components](https://go.microsoft.com/fwlink/p/?LinkID=253170). This package performs a silent install into the directory of your WDK installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0.
-- To open a Web browser, toggle switch number 8 on the device board to the On position (toggle down).
+1. Plug in the device and follow these steps:
-- To start the calculator application, toggle switch number 2 on the device board to the On position (toggle down).
+ 1. Launch Device Manager by executing command devmgmt.msc in a command window, or from the **Hardware and Sound** program group in **Control Panel**.
-**Testing Bar Graph and 7-Segment Display**
+ 1. Select **OSR USB-FX2 device** from **Other Devices** category and select **Update Driver Software...** from the right-click menu.
-1. Start the **hidclient.exe** GUI application from the WDK. The application source code is located in the \\hid\\hclient directory, and you build it by using the appropriate build environment.
+ 1. Select **Browse my computer for software** and provide the location of the driver files.
-2. From the **HID Device to examine** menu, select the device that contains "UsagePage 0ff00, Usage 01" as a substring.
+ 1. Select **Install this driver software anyway** when the Windows Security dialog box appears.
-3. Click **Modify Features**. The **Feature Data** dialog box opens.
+ 1. After the driver is installed, you should see the device in Device Manager under Human Interface Devices.
-4. Click **Modify Features**. The **Modify features** dialog box opens.
+## Testing
-5. In the input box, type **7** and click **Send to Device**. You'll see number 7 appear in the 7-segment display.
+### Testing Switches
-6. Type any number from 1-8, and you'll see the respective number displayed in the 7-segment display.
+- To open a Web browser, toggle switch number 8 on the device board to the On position (toggle down).
-7. Type any number from (and including) 9-17, and you will see one of the LEDs on the bar graph turn on. For mapping information, see the previous table.
+- To start the calculator application, toggle switch number 2 on the device board to the On position (toggle down).
-**Report Descriptor**
+### Testing Bar Graph and 7-Segment Display
-```
+1. Start the **hidclient.exe** GUI application from the WDK. The application source code is located in the \\hid\\hclient directory, and you build it by using the appropriate build environment.
+
+1. From the **HID Device to examine** menu, select the device that contains "UsagePage 0ff00, Usage 01" as a substring.
+
+1. Click **Modify Features**. The **Feature Data** dialog box opens.
+
+1. Click **Modify Features**. The **Modify features** dialog box opens.
+
+1. In the input box, type **7** and click **Send to Device**. You'll see number 7 appear in the 7-segment display.
+
+1. Type any number from 1-8, and you'll see the respective number displayed in the 7-segment display.
+
+1. Type any number from (and including) 9-17, and you will see one of the LEDs on the bar graph turn on. For mapping information, see the previous table.
+
+### Report Descriptor
+
+```cpp
// Consumer control collection
-
+
0x05,0x0C, // USAGE_PAGE (Consumer Page)
-
+
0x09,0x01, // USAGE (Consumer Control Usage 0x01)
-
+
0xA1,0x01, // COLLECTION (Application)
-
- 0x85,0x01, // REPORT_ID
-
+
+ 0x85,0x01, // REPORT_ID
+
0x0A, 0x23, 0x02, // USAGE (Usage Browser)
-
+
0x0A, 0x24, 0x02, // USAGE (Usage AC Back)
-
+
0x0A, 0x25, 0x02, // USAGE (Usage AC Forward)
-
+
0x0A, 0x27, 0x02, // USAGE (Usage AC Refresh)
-
+
0x0A, 0x2A, 0x02, // USAGE (Usage AC BookMarks)
-
+
0x0A, 0x8A, 0x01, // USAGE (Usage AL Mail)
-
+
0x0A, 0x92, 0x01, // USAGE (Usage AL Calculator )
-
+
0x15, 0x00, // LOGICAL_MINIMUM(0)
-
+
0x25, 0x01, // LOGICAL_MAXIMUM(1)
-
- 0x75, 0x01, // REPORT_SIZE
-
- 0x95, 0x07, // REPORT_COUNT
-
+
+ 0x75, 0x01, // REPORT_SIZE
+
+ 0x95, 0x07, // REPORT_COUNT
+
0x81, 0x02, // INPUT (Data, Variable,Abs)
-
- 0x75, 0x01, // REPORT_SIZE
-
+
+ 0x75, 0x01, // REPORT_SIZE
+
0x95, 0x01, // REPORT_COUNT
-
+
0x81, 0x07, // INPUT (const)
-
+
0xC0, // END_COLLECTION
-
+
// system control collection
-
+
0x05, 0x01, // Usage Page (Generic Desktop)
-
+
0x09, 0x80, // Usage (System Control)
-
+
0xA1, 0x01, // Collection (Application)
-
- 0x85, 0x02, // Report ID
-
- 0x95, 0x07, // Report Count
-
+
+ 0x85, 0x02, // Report ID
+
+ 0x95, 0x07, // Report Count
+
0x81, 0x07, // Input (Constant)
-
+
0x09, 0x82, // Usage (System Sleep)
-
+
0x95, 0x01, // Report Count (2)
-
+
0x81, 0x06, // Input (Data, Variable, Relative, Preferred)
-
+
0xC0, // End Collection
-
+
// Feature collection
-
+
0x06,0x00, 0xFF, // USAGE_PAGE (Vender Defined Usage Page)
-
+
0x09,0x01, // USAGE (Vendor Usage 0x01)
-
+
0xA1,0x01, // COLLECTION (Application)
-
- 0x85,0x03, // Report ID
-
- 0x19,0x01, // USAGE MINIMUM
-
- 0x29,0x20, // USAGE MAXIMUM
-
+
+ 0x85,0x03, // Report ID
+
+ 0x19,0x01, // USAGE MINIMUM
+
+ 0x29,0x20, // USAGE MAXIMUM
+
0x15,0x00, // LOGICAL_MINIMUM(1)
-
+
0x26,0xff, 0x00, // LOGICAL_MAXIMUM(255)
-
- 0x75,0x08, // REPORT_SIZE
-
- 0x95,0x01, // REPORT_COUNT
-
+
+ 0x75,0x08, // REPORT_SIZE
+
+ 0x95,0x01, // REPORT_COUNT
+
0xB1,0x00, // Feature (Data,Ary,Abs)
-
+
0xC0 // END_COLLECTION </code></pre></td>
```
-Code Tour
----------
+## Code Tour
This section includes a file manifest of the files in the \\hidusbfx2 directory.
### File Manifest
-**\\hidusbfx2\\hidkmdf**
+#### \\hidusbfx2\\hidkmdf
+
+| File | Description |
+| --- | --- |
+| hidkmdf.c | Contains code for driver entry and dispatch |
+| Sources | WDK sources file |
+| Makefile | WDK build environment makefile |
+| hidkmdf.rc | Resource file for the driver |
-File | Description
------|------------
-hidkmdf.c | Contains code for driver entry and dispatch
-Sources | WDK sources file
-Makefile | WDK build environment makefile
-hidkmdf.rc | Resource file for the driver
-
-**\\hidusbfx2\\sys**
+#### \\hidusbfx2\\sys
-File | Description
------|------------
-Driver.c | Contains code for driver entry and dispatch functions
-hid.c | Contains code for handling HID IOCTLS
-usb.c | Contains code for communicating with USB stack
-Trace.h | Contains trace-related definitions
-Hidusbfx2.h | Contains type definitions and function declarations
-Hidusbfx2.rc | Resource file for the driver
-Hidusbfx2.inx | INX file for the driver
-Sources | WDK sources file
-Makefile | WDK build environment make file
-Makefile.inc | A makefile that defines custom build actions, including the conversion of the .INX file into a .INF file
+| File | Description |
+| --- | --- |
+| Driver.c | Contains code for driver entry and dispatch functions |
+| hid.c | Contains code for handling HID IOCTLS |
+| usb.c | Contains code for communicating with USB stack |
+| Trace.h | Contains trace-related definitions |
+| Hidusbfx2.h | Contains type definitions and function declarations |
+| Hidusbfx2.rc | Resource file for the driver |
+| Hidusbfx2.inx | INX file for the driver |
+| Sources | WDK sources file |
+| Makefile | WDK build environment make file |
+| Makefile.inc | A makefile that defines custom build actions, including the conversion of the .INX file into a .INF file |
diff --git a/hid/vhidmini2/README.md b/hid/vhidmini2/README.md
index c069eeff..18ec16a9 100644
--- a/hid/vhidmini2/README.md
+++ b/hid/vhidmini2/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: HID Minidriver Sample (UMDF version 2)
- platform: UMDF2
- language: cpp
- category: HID
- description: Demonstrates how to write a HID minidriver using User-Mode Driver Framework (UMDF).
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617731
---->
-
# HID Minidriver Sample (UMDF version 2)
The *HID minidriver* sample demonstrates how to write a HID minidriver using User-Mode Driver Framework (UMDF).
@@ -24,10 +16,10 @@ The sample demonstrates how to communicate with an HID minidriver from an HID cl
## Related topics
-[Creating UMDF-based HID Minidrivers](http://msdn.microsoft.com/en-us/library/windows/hardware/hh439579)
+[Creating WDF HID Minidrivers](https://docs.microsoft.com/windows-hardware/drivers/wdf/creating-umdf-hid-minidrivers)
-[Human Input Devices Design Guide](http://msdn.microsoft.com/en-us/library/windows/hardware/ff539952)
+[Human Input Devices Design Guide](https://docs.microsoft.com/windows-hardware/drivers/hid/)
-[Human Input Devices Reference](http://msdn.microsoft.com/en-us/library/windows/hardware/ff539956)
+[Human Input Devices Reference](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/_hid/)
-[UMDF HID Minidriver IOCTLs](http://msdn.microsoft.com/en-us/library/windows/hardware/hh463977)
+[UMDF HID Minidriver IOCTLs](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/hidport/)
diff --git a/hid/vhidmini2/inc/common.h b/hid/vhidmini2/inc/common.h
index 1a9eca1a..9b14cc6d 100644
--- a/hid/vhidmini2/inc/common.h
+++ b/hid/vhidmini2/inc/common.h
@@ -37,7 +37,6 @@ Environment:
#define TEST_COLLECTION_REPORT_ID 0x02
#define MAXIMUM_STRING_LENGTH (126 * sizeof(WCHAR))
-#define VHIDMINI_DEVICE_STRING L"UMDF Virtual hidmini device"
#define VHIDMINI_MANUFACTURER_STRING L"UMDF Virtual hidmini device Manufacturer string"
#define VHIDMINI_PRODUCT_STRING L"UMDF Virtual hidmini device Product string"
#define VHIDMINI_SERIAL_NUMBER_STRING L"UMDF Virtual hidmini device Serial Number string"
diff --git a/input/kbfiltr/README.md b/input/kbfiltr/README.md
index b1e00b26..a40b084e 100644
--- a/input/kbfiltr/README.md
+++ b/input/kbfiltr/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Keyboard Input WDF Filter Driver (Kbfiltr)
- platform: KMDF
- language: cpp
- category: HID WDF
- description: A WDF example of a keyboard input filter driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620194
---->
-
# Keyboard Input WDF Filter Driver (Kbfiltr)
The Kbdfltr sample is an example of a keyboard input filter driver.
@@ -27,60 +19,56 @@ This is an upper device filter driver sample for PS/2 keyboard. This driver laye
This sample also creates a raw PDO and registers an interface so that applications can talk to the filter driver directly without going through the PS/2 devicestack. The reason for providing this additional interface is because the keyboard device is an exclusive secure device and it's not possible to open the device from usermode and send custom ioctls through it.
This driver filters input for a particular keyboard on the system. If you want to filter keyboard inputs from all the keyboards plugged into the system, you can install this driver as a class filter below the KbdClass filter driver by adding the service name of this filter driver before the KbdClass filter in the registry at:
+
`HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E96B-E325-11CE-BFC1-08002BE10318}\UpperFilters`
## Universal Windows Driver Compliant
This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP.
-Set the hardware ID in the inx file
------------------------------------
+## Set the hardware ID in the inx file
This step is required for automatic deployment (described later) to work properly. In the kbfiltr.inx file (located with the driver source files), find the [DDK\_Ex.Mfg.NT\$ARCH\$] section. Change the hardware ID in the %DDK\_Ex% entry from the dummy value to the hardware ID of the PS/2 keyboard on the target computer. The following example shows the hardware ID change.
-```
+```inf
; For XP and above
[DDK_Ex.Mfg.NT$ARCH$]
;%DDK_Ex% = kbfiltr, *PNP0BAAD
%DDK_Ex% = kbfiltr, ACPI\VEN_PNP&DEV_0303
```
-Build the sample using Visual Studio
-------------------------------------
+## Build the sample using Visual Studio
In Visual Studio, on the **Build** menu, choose **Build Solution**.
-For more information about using Visual Studio to build a driver package, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644).
+For more information about using Visual Studio to build a driver package, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver).
The test application, *kbftest.exe* is also built as part of the solution under the 'exe' folder.
-Locate the built driver package
--------------------------------
+## Locate the built driver package
In File Explorer, navigate to the folder that contains your built driver package. The location of this folder varies depending on what you set for configuration and platform. For example, if your settings are **Debug** and **x64**, the package is your solution folder under \\Debug\\Package.
The package contains these files:
-File | Description
------|------------
-Kmdfsamples.cat | A signed catalog file, which serves as the signature for the entire package.
-kbfiltr.inf | An information (INF) file that contains information needed to install the driver.
-WdfCoinstaller010xx.dll | The coinstaller for version 1.xx of KMDF.
-kbfiltr.sys | The driver file.
+| File | Description |
+| --- | --- |
+| Kmdfsamples.cat | A signed catalog file, which serves as the signature for the entire package. |
+| kbfiltr.inf | An information (INF) file that contains information needed to install the driver. |
+| WdfCoinstaller010xx.dll | The coinstaller for version 1.xx of KMDF. |
+| kbfiltr.sys | The driver file. |
-Using MSBuild
--------------
+## Using MSBuild
-As an alternative to building the Kbfiltr Filter Driver sample in Visual Studio, you can build it in a Visual Studio Command Prompt window. In Visual Studio, on the **Tools** menu, choose **Visual Studio Command Prompt**. In the Visual Studio Command Prompt window, navigate to the folder that has the solution file, kbfiltr.sln. Use the [MSBuild](http://go.microsoft.com/fwlink/p/?linkID=262804) command to build the solution. Here are some examples:
+As an alternative to building the Kbfiltr Filter Driver sample in Visual Studio, you can build it in a Visual Studio Command Prompt window. In Visual Studio, on the **Tools** menu, choose **Visual Studio Command Prompt**. In the Visual Studio Command Prompt window, navigate to the folder that has the solution file, kbfiltr.sln. Use the [MSBuild](https://docs.microsoft.com/visualstudio/msbuild/msbuild?view=vs-2019) command to build the solution. Here are some examples:
-**msbuild /p:configuration="Debug" /p:platform="x64" kbfiltr.sln**
+- **msbuild /p:configuration="Debug" /p:platform="x64" kbfiltr.sln**
-**msbuild /p:configuration="Release" /p:platform="Win32" kbfiltr.sln**
+- **msbuild /p:configuration="Release" /p:platform="Win32" kbfiltr.sln**
-For more information about using [MSBuild](http://go.microsoft.com/fwlink/p/?linkID=262804) to build a driver package, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644).
+For more information about using [MSBuild](https://docs.microsoft.com/visualstudio/msbuild/msbuild?view=vs-2019) to build a driver package, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver).
-Run the sample
---------------
+## Run the sample
The computer where you install the driver is called the *target computer* or the *test computer*. Typically this is a separate computer from where you develop and build the driver package. The computer where you develop and build the driver is called the *host computer*.
@@ -88,18 +76,21 @@ The process of moving the driver package to the target computer and installing t
### Automatic deployment
-Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/).
+Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1).
-1. On the host computer, in Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
-2. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Install and Verify**, and choose **Default Driver Package Installation Task** in the list. Click **OK**.
-3. On the **Build** menu, choose **Deploy Package** or **Build Solution**.
+1. On the host computer, in Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
+
+1. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Install and Verify**, and choose **Default Driver Package Installation Task** in the list. Click **OK**.
+
+1. On the **Build** menu, choose **Deploy Package** or **Build Solution**.
### Manual deployment
-Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
+Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](https://docs.microsoft.com/windows-hardware/drivers/devtest/devcon) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
+
+1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\KbfiltrDriverPackage).
-1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\KbfiltrDriverPackage).
-2. On the target computer, open a Command Prompt window as Administrator. Navigate to your driver package folder, and enter the Devcon command with the correct hardware ID, such as:
+1. On the target computer, open a Command Prompt window as Administrator. Navigate to your driver package folder, and enter the Devcon command with the correct hardware ID, such as:
**Devcon install kbfiltr.inf ACPI\\VEN\_PNP&DEV\_0303**
@@ -107,14 +98,13 @@ Before you manually deploy a driver, you must turn on test signing and install a
Using Device Manager, update the driver for the PS/2 Keyboard by manually selecting kbfiltr.inf from the location where you copied the driver files.
-View the installed driver in Device Manager
--------------------------------------------
+## View the installed driver in Device Manager
On the target computer, in a Command Prompt window, enter **devmgmt** to open Device Manager. In Device Manager, on the **View** menu, choose **Devices by type**. In the device tree, locate **DDK Example Device that needs filtering** under the **Keyboards** node.
-Testing
--------
+## Testing
To use the test application provided with the sample, it must be copied to the target computer manually. Save the kbftest.exe file from the folder where the build result is placed (for example, exe\\Debug). This file is copied somewhere on the target, possibly where the driver package files are located. The test application is the executed on the target computer in a Command Prompt using **kbftest** as the command.
-**Tip** To avoid DLL dependencies for kbftext.exe, and the need to copy additional files, select the statically linked run-time library when building.
+> [!TIP]
+> Optional information to help a user be more successfulTo avoid DLL dependencies for kbftext.exe, and the need to copy additional files, select the statically linked run-time library when building.
diff --git a/input/kbfiltr/sys/kbfiltr.c b/input/kbfiltr/sys/kbfiltr.c
index e0009172..ddc78326 100644
--- a/input/kbfiltr/sys/kbfiltr.c
+++ b/input/kbfiltr/sys/kbfiltr.c
@@ -80,7 +80,7 @@ Return Value:
DebugPrint(("Built %s %s\n", __DATE__, __TIME__));
//
- // Initiialize driver config to control the attributes that
+ // Initialize driver config to control the attributes that
// are global to the driver. Note that framework by default
// provides a driver unload routine. If you create any resources
// in the DriverEntry and want to be cleaned in driver unload,
diff --git a/input/layout/README.md b/input/layout/README.md
index 15e16a4a..eb654d31 100644
--- a/input/layout/README.md
+++ b/input/layout/README.md
@@ -5,67 +5,62 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Keyboard Layout Samples
- platform: Application
- language: cpp
- category: HID
- description: Demonstrates how to generate layouts for various keyboards and locales.
- samplefwlink: https://aka.ms/rapjms
---->
-
# Keyboard Layout Samples
The keyboard layout samples demonstrate how to generate layouts for various keyboards and locales.
-Build the sample
-----------------
+## Build the sample
Starting in the WDK, you can build the sample in two ways: using the Visual Studio Integrated Development Environment (IDE) or from the command line using the Visual Studio Command Prompt window and the Microsoft Build Engine (MSBuild.exe).
### Building the sample using Visual Studio
-1. Open Visual Studio. From the **File** menu, select **Open Project/Solution**. Within your WDK installation, navigate to src\\input\\layout and open the kbd.sln project file.
-2. Right-click the solution in the **Solution Explorer** and select **Configuration Manager**.
-3. From the **Configuration Manager**, select the **Active Solution Configuration** (for example, Windows 8.1 Debug or Windows 8.1 Release) and the **Active Solution Platform** (for example, Win32) that correspond to the type of build you are interested in.
-4. From the **Build** menu, click **Build Solution** (Ctrl+Shift+B).
+1. Open Visual Studio. From the **File** menu, select **Open Project/Solution**. Within your WDK installation, navigate to src\\input\\layout and open the kbd.sln project file.
+
+1. Right-click the solution in the **Solution Explorer** and select **Configuration Manager**.
+
+1. From the **Configuration Manager**, select the **Active Solution Configuration** (for example, Windows 8.1 Debug or Windows 8.1 Release) and the **Active Solution Platform** (for example, Win32) that correspond to the type of build you are interested in.
+
+1. From the **Build** menu, click **Build Solution** (Ctrl+Shift+B).
Previous versions of the WDK used the Windows Build utility (Build.exe) and provided separate build environment windows for each of the supported build configurations. Starting in the WDK, you can use the Visual Studio Command Prompt window for all build configurations.
### Building the sample using the command line (MSBuild)
-1. Open a Visual Studio Command Prompt window. Click **Start** and search for **Developer Command Prompt**. If your project is under %PROGRAMFILES%, you need to open the command prompt window using elevated permissions (**Run as administrator**). From this window you can use MsBuild.exe to build any Visual Studio project by specifying the project (.VcxProj) or solutions (.Sln) file.
-2. Navigate to the project directory and enter the **MSbuild** command for your target. For example, to perform a clean build of a Visual Studio driver project called kbdus.vcxproj, navigate to the project directory and enter the following MSBuild command: **msbuild /t:clean /t:build .\\kbdus.vcxproj**.
-3. If the build succeeds, you will find the driver (kbdus.dll) in the binary output directory corresponding to the target platform, for example src\\input\\layout\\kbdus\\Windows 8.1 Debug.
+1. Open a Visual Studio Command Prompt window. Click **Start** and search for **Developer Command Prompt**. If your project is under %PROGRAMFILES%, you need to open the command prompt window using elevated permissions (**Run as administrator**). From this window you can use MsBuild.exe to build any Visual Studio project by specifying the project (.VcxProj) or solutions (.Sln) file.
+
+1. Navigate to the project directory and enter the **MSbuild** command for your target. For example, to perform a clean build of a Visual Studio driver project called kbdus.vcxproj, navigate to the project directory and enter the following MSBuild command: **msbuild /t:clean /t:build .\\kbdus.vcxproj**.
+
+1. If the build succeeds, you will find the driver (kbdus.dll) in the binary output directory corresponding to the target platform, for example src\\input\\layout\\kbdus\\Windows 8.1 Debug.
-Design and Operation
---------------------
+## Design and Operation
-### Keyboard Layout Samples
+### Keyboard Layout Samples details
The layout DLL is loaded by the window manager when needed. One of the examples is the logon. The default set of the input locales is set in the HKCU registry, according to user's preference, which can be customized by the Regional and Language Options application in Control Panel. The window manager reads the HKCU registry and loads the keyboard layouts accordingly.
The samples under input/layout include the following keyboard layouts:
-- kbdus
+- kbdus
US-English keyboard layout
-- kbdfr
+- kbdfr
French keyboard layout
-- kbdgr
+- kbdgr
German keyboard layout
-- kbd101
+- kbd101
Japanese 101 keyboard layout
-- kbd106
+- kbd106
Japanese 106 keyboard layout
@@ -85,13 +80,11 @@ The layout DLLs export one or more entry points, which are called by the window
For the East Asian keyboard layouts, the keyboard layout DLL has to provide language-specific entry points. Those additional entries expose the language-specific information, such as the kana conversion table, or the special conversion rule, including the VK\_KANJI generation.
-Installation
-------------
+## Installation
To install a customized version of a layout DLL, it is recommended to substitute the existing DLL installed by the operating system with the customized DLL. The layout DLLs should be installed in the %windir%\\system32 directory (exceptions may apply on 64-bit platforms). You may need to disable the System File Protection (SFP) before replacing the layout DLLs. After the layout DLLs are installed, you may need to reboot the system to ensure the new layouts are used..
-Loading the Sample
-------------------
+## Loading the Sample
In order to load the layout DLLs, you may need to turn to the Regional and Language Options application in Control Panel and add input locales that use the keyboard layouts you installed.
diff --git a/input/moufiltr/README.md b/input/moufiltr/README.md
index 3795c8f3..210a7198 100644
--- a/input/moufiltr/README.md
+++ b/input/moufiltr/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Mouse Input WDF Filter Driver (Moufiltr)
- platform: KMDF
- language: cpp
- category: HID WDF
- description: A WDF example of a mouse input filter driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620195
---->
-
# Mouse Input WDF Filter Driver (Moufiltr)
The Moufiltr sample is an example of a mouse input filter driver.
diff --git a/input/moufiltr/moufiltr.c b/input/moufiltr/moufiltr.c
index 3e97a7a1..84716db2 100644
--- a/input/moufiltr/moufiltr.c
+++ b/input/moufiltr/moufiltr.c
@@ -47,7 +47,7 @@ Routine Description:
DebugPrint(("Mouse Filter Driver Sample - Driver Framework Edition.\n"));
DebugPrint(("Built %s %s\n", __DATE__, __TIME__));
- // Initiialize driver config to control the attributes that
+ // Initialize driver config to control the attributes that
// are global to the driver. Note that framework by default
// provides a driver unload routine. If you create any resources
// in the DriverEntry and want to be cleaned in driver unload,
diff --git a/network/config/bindview/README.md b/network/config/bindview/README.md
index c3220092..7d14682f 100644
--- a/network/config/bindview/README.md
+++ b/network/config/bindview/README.md
@@ -5,19 +5,11 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Bindview Network Configuration Utility
- platform: Application
- language: cpp
- category: Network
- description: An application that demonstrates how to use INetCfg APIs to enumerate, install, uninstall, bind and unbind network components.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617732
---->
-
# Bindview Network Configuration Utility
The Bindview sample demonstrates how to use INetCfg APIs to enumerate, install, uninstall, bind and unbind network components.
-For more information on the INetCfg interface, see [Network Configuration Interfaces](http://msdn.microsoft.com/en-us/library/windows/hardware/ff559080).
+For more information on the INetCfg interface, see [Network Configuration Interfaces](https://docs.microsoft.com/previous-versions/windows/hardware/network/ff559080(v=vs.85)).
diff --git a/network/modem/fakemodem/README.md b/network/modem/fakemodem/README.md
index 0de6d2cd..bdb59305 100644
--- a/network/modem/fakemodem/README.md
+++ b/network/modem/fakemodem/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Fakemodem Driver
- platform: KMDF
- language: cpp
- category: Network
- description: Demonstrates a simple controller-less modem driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617733
---->
-
# Fakemodem Driver
The Fakemodem sample demonstrates a simple controller-less modem driver. This driver supports sending and receiving AT commands using the `ReadFile`/`WriteFile` calls or via a TAPI interface using an application such as *HyperTerminal.*
diff --git a/network/ndis/extension/README.md b/network/ndis/extension/README.md
index 24ffd36d..c6965595 100644
--- a/network/ndis/extension/README.md
+++ b/network/ndis/extension/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Hyper-V Extensible Switch extension filter driver
- platform: WDM
- language: cpp
- category: Network
- description: A base library used to implement a Hyper-V Extensible Switch extension filter driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617913
---->
-
# Hyper-V Extensible Switch extension filter driver
This sample contains a base library used to implement a Hyper-V Extensible Switch extension filter driver. This sample also contains two different extension filter drivers that were developed by using the library.
@@ -32,4 +24,4 @@ MsForwardExt is a basic forwarding extension filter driver that is implemented b
Use the *install.cmd* script provided with each extension filter driver. The *install.cmd* uses **netcfg** to install the extension and **mofcomp** to register any required mof files. The PowerShell cmdlet *Enable-VmSwitchExtension* can then be used to enable the extension filter driver on a Hyper-V Extensible Switch.
-For more information on Hyper-V Extensible Switch extensions, see [Hyper-V Extensible Switch](http://msdn.microsoft.com/en-us/library/windows/hardware/hh598161).
+For more information on Hyper-V Extensible Switch extensions, see [Hyper-V Extensible Switch](https://docs.microsoft.com/windows-hardware/drivers/network/hyper-v-extensible-switch).
diff --git a/network/ndis/filter/README.md b/network/ndis/filter/README.md
index 22acc1e3..e9e34278 100644
--- a/network/ndis/filter/README.md
+++ b/network/ndis/filter/README.md
@@ -5,66 +5,73 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: NDIS 6.0 Filter Driver
- platform: WDM
- language: cpp
- category: Network
- description: A pass-through NDIS 6 filter driver demonstrating the basic principles of an NDIS 6.0 Filter driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617915
---->
-
# NDIS 6.0 Filter Driver
-The Ndislwf sample is a do-nothing pass-through NDIS 6 filter driver that demonstrates the basic principles underlying an NDIS 6.0 Filter driver. The sample replaces the NDIS 5 Sample Intermediate Driver (Passthru driver).
+The Ndislwf sample is a do-nothing pass-through NDIS 6 filter driver that demonstrates the basic principles underlying an NDIS 6.0 Filter driver. The sample replaces the NDIS 5 Sample Intermediate Driver (Passthrough driver).
Although this sample filter driver is installed as a modifying filter driver, it doesn't modify any packets; it only repackages and sends down all OID requests. You can modify this filter driver to change packets before passing them along. Or you can use the filter to originate new packets to send or receive. For example, the filter could encrypt/compress outgoing and decrypt/decompress incoming data.
-For more information, see [NDIS Filter Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff565492) in the network devices design guide.
+For more information, see [NDIS Filter Drivers](https://docs.microsoft.com/windows-hardware/drivers/network/ndis-filter-drivers) in the network devices design guide.
+
+## Automatic deployment
+
+Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1).
+
+After you have provisioned the target computer, continue with these steps:
+
+1. On the host computer, in **Visual Studio**, in **Solution Explorer**, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
+
+1. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Do not install**. Click **OK**.
+
+1. On the **Build** menu, choose **Build Solution**.
+
+1. On the target computer, open **Control Panel**. Click **Network and Internet** and then open **Network and Sharing Center**.
+1. Under **View your active networks**, click the connection listed under **Connections:** and click **Properties**. If you have previously installed this sample, highlight it in the list.
-Automatic deployment
---------------------
+1. Click **Install**, then **Service**, then **Add**.
-Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/). After you have provisioned the target computer, continue with these steps:
+ > [!NOTE]
+ > You may see multiple instances of the **NDIS Sample LightWeight Filter** service. If so, highlight the newest one.
-1. On the host computer, in **Visual Studio**, in **Solution Explorer**, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
-2. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Do not install**. Click **OK**.
-3. On the **Build** menu, choose **Build Solution**.
-4. On the target computer, open **Control Panel**. Click **Network and Internet** and then open **Network and Sharing Center**.
-5. Under **View your active networks**, click the connection listed under **Connections:** and click **Properties**. If you have previously installed this sample, highlight it in the list.
-6. Click **Install**, then **Service**, then **Add**.
- **Note** You may see multiple instances of the **NDIS Sample LightWeight Filter** service. If so, highlight the newest one.
-7. Click **Have Disk**.
-8. In the **Install from Disk** dialog, browse to the DriverTest\\Drivers directory. Highlight the netlwf.inf file and click **Open**, then click OK. This should show **NDIS Sample LightWeight Filter** in a list of **Network Services**. Highlight **NDIS Sample LightWeight Filter** and click **OK**. Click **OK**. Click **Close**. Click **Close**. This installs the Ndislwf filter driver service.
+1. Click **Have Disk**.
-**Note** If you've installed the Ndislwf sample on the target computer before, you can use the [PnPUtil](http://msdn.microsoft.com/en-us/library/windows/hardware/ff550419) tool to delete the older versions from the driver store.
+1. In the **Install from Disk** dialog, browse to the DriverTest\\Drivers directory. Highlight the netlwf.inf file and click **Open**, then click OK. This should show **NDIS Sample LightWeight Filter** in a list of **Network Services**. Highlight **NDIS Sample LightWeight Filter** and click **OK**. Click **OK**. Click **Close**. Click **Close**. This installs the Ndislwf filter driver service.
-Manual deployment
------------------
+> [!NOTE]
+> If you've installed the Ndislwf sample on the target computer before, you can use the [PnPUtil](https://docs.microsoft.com/windows-hardware/drivers/devtest/pnputil) tool to delete the older versions from the driver store.
-Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
+## Manual deployment
+
+Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](https://docs.microsoft.com/windows-hardware/drivers/devtest/devcon) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
Ndislwf is installed as a service (called **NDIS Sample LightWeight Filter** in the supplied INF). To install it, do the following:
-1. Prepare an installation directory on the target computer and copy these files from the host computer into the directory:
-```
- netlwf.cat
- netlwf.inf
- ndislwf.sys
-```
-2. Open **Control Panel**.
-3. Click **Network and Internet** and then open **Network and Sharing Center**. Under **View your active networks**, click the connection listed under **Connections**: and click **Properties**.
-4. If you have previously installed this sample, highlight it in the list.
-5. Click **Install**, then **Service**, then **Add**, then **Have Disk**.
-6. Browse to the installation directory. Highlight the netlwf.inf file and click **Open**, then click OK. This should show **NDIS Sample LightWeight Filter** in a list of Network Services. Highlight this and click OK. Click OK. This installs the Ndislwf filter driver.
+1. Prepare an installation directory on the target computer and copy these files from the host computer into the directory:
+
+ - netlwf.cat
+
+ - netlwf.inf
+
+ - ndislwf.sys
+
+1. Open **Control Panel**.
-**Note** If you've installed the Ndislwf sample on the target computer before, you can use the [PnPUtil](http://msdn.microsoft.com/en-us/library/windows/hardware/ff550419) tool to delete the older versions from the driver store.
+1. Click **Network and Internet** and then open **Network and Sharing Center**. Under **View your active networks**, click the connection listed under **Connections**: and click **Properties**.
-Viewing sample output in the debugger
--------------------------------------
+1. If you have previously installed this sample, highlight it in the list.
+
+1. Click **Install**, then **Service**, then **Add**, then **Have Disk**.
+
+1. Browse to the installation directory. Highlight the netlwf.inf file and click **Open**, then click OK. This should show **NDIS Sample LightWeight Filter** in a list of Network Services. Highlight this and click OK. Click OK. This installs the Ndislwf filter driver.
+
+> [!NOTE]
+> If you've installed the Ndislwf sample on the target computer before, you can use the [PnPUtil](https://docs.microsoft.com/windows-hardware/drivers/devtest/pnputil) tool to delete the older versions from the driver store.
+
+## Viewing sample output in the debugger
### Setting up kernel-mode debugging automatically
@@ -72,32 +79,32 @@ If you chose to deploy your driver automatically, then kernel debugging is alrea
On the host computer, in **Visual Studio**, in the **Debug** menu, choose **Attach to Process**. For **Transport**, choose **Windows Kernel Mode Debugger**. For **Qualifier**, choose the name of your target computer. Click **Attach**.
-**Note** If you see a dialog box that asks you to allow the debugger to communicate through the firewall, click the boxes for all types of networks. Click **Allow Access**.
+> [!NOTE]
+> If you see a dialog box that asks you to allow the debugger to communicate through the firewall, click the boxes for all types of networks. Click **Allow Access**.
-For more information, see [Setting Up Kernel-Mode Debugging in Visual Studio](http://msdn.microsoft.com/en-us/library/windows/hardware/hh439376).
+For more information, see [Setting Up Kernel-Mode Debugging in Visual Studio](https://docs.microsoft.com/windows-hardware/drivers/debugger/setting-up-kernel-mode-debugging-in-visual-studio).
### Setting up kernel-mode debugging manually
-If you chose to deploy your driver manually, then you need to set up kernel debugging manually. For instructions, see [Setting Up Kernel-Mode Debugging Manually](http://msdn.microsoft.com/en-us/library/windows/hardware/hh439378).
+If you chose to deploy your driver manually, then you need to set up kernel debugging manually. For instructions, see [Setting Up Kernel-Mode Debugging Manually](https://docs.microsoft.com/windows-hardware/drivers/debugger/setting-up-kernel-mode-debugging-in-visual-studio).
The kernel-mode debuggers (WinDbg.exe and Kd.exe) are included in the WDK.
-On the host computer, locate and open a kernel-mode debugger (example: c:\\Program Files (x86)\\Windows Kits\\10\\Debuggers\\x64\\windbg.exe). Establish a kernel-mode debugging session between the host and target computers. The details of how to do this depend on the type of debug cable you are using. For information about how to start a debugging session, see [Setting Up Kernel-Mode Debugging Manually](http://msdn.microsoft.com/en-us/library/windows/hardware/hh439378).
+On the host computer, locate and open a kernel-mode debugger (example: c:\\Program Files (x86)\\Windows Kits\\10\\Debuggers\\x64\\windbg.exe). Establish a kernel-mode debugging session between the host and target computers. The details of how to do this depend on the type of debug cable you are using. For information about how to start a debugging session, see [Setting Up Kernel-Mode Debugging Manually](https://docs.microsoft.com/windows-hardware/drivers/debugger/setting-up-a-network-debugging-connection).
-Setting kd\_default\_mask
--------------------------
+## Setting kd\_default\_mask
-This sample calls [**DbgPrint**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff543632) to send trace messages to the kernel-mode debugger. To see the trace messages, you must set the value of the **kd\_default\_mask** variable.
+This sample calls [**DbgPrint**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/nf-wdm-dbgprint) to send trace messages to the kernel-mode debugger. To see the trace messages, you must set the value of the **kd\_default\_mask** variable.
On the host computer, break in to the debugger if you are not already broken in. (In the **Debug** menu, choose **Break** or **Break All**, or press **CTRL-Break**). At the debugger command line, enter this command: **ed kd\_default\_mask 0x8**.
To resume execution of the target computer, enter the **g** command in the debugger. (In the **Debug** menu, choose **Continue**.)
-Viewing trace messages
-----------------------
+## Viewing trace messages
On the host computer, in the kernel-mode debugger, verify that you see trace messages similar to these:
-```
+
+```txt
NDISLWF: ===>DriverEntry...
NDISLWF: ===>FilterRegisterOptions
NDISLWF: <===FilterRegisterOptions
@@ -107,14 +114,21 @@ NDISLWF: <===DriverEntry, Status = 0
NDISLWF: ===>FilterAttach: NdisFilterHandle FFFFE00000F73650
NDISLWF: <===FilterAttach: Status 0
```
-What the Ndislwf sample driver does:
-------------------------------------
-1. During [*DriverEntry*](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544113), the ndislwf driver registers as an NDIS 6 filter driver.
-2. Later on, NDIS calls Ndislwf's [*FilterAttach*](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549905) handler, for each underlying NDIS adapter on which it is configured to attach.
-3. In the context of [*FilterAttach*](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549905) Handler, the filter driver calls [**NdisFSetAttributes**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff562619) to register its filter module context with NDIS. After that, the filter driver can read its own setting in registry by calling [**NdisOpenConfigurationEx**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff563717), and call other `NdisXxx` functions.
-4. After [*FilterAttach*](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549905) successfully returns, NDIS restarts the filter later by calling its [*FilterRestart*](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549962) handler. *FilterRestart* should prepare to handle send/receive data. After restart return successfully, filter driver should be able to process send/receive.
-5. All requests and sends coming from overlying drivers for the Ndislwf filter driver are repackaged if necessary and sent down to NDIS, to be passed to the underlying NDIS driver.
-6. All indications arriving from an underlying NDIS driver are forwarded up by Ndislwf filter driver.
-7. NDIS calls the filter's [*FilterPause*](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549957) handler when NDIS needs to detach the filter from the stack or there is some configuration changes in the stack. In processing the pause request from NDIS, the Ndislwf driver waits for all its own outstanding requests to be completed before it completes the pause request.
-8. NDIS calls the Ndislwf driver's [*FilterDetach*](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549918) entry point when NDIS needs to detach a filter module from NDIS stack. The *FilterDetach* handler should free all the memory allocation done in [*FilterAttach*](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549905), and undo the operations it did in *FilterAttach* Handler.
+## What the Ndislwf sample driver does
+
+1. During [*DriverEntry*](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/nc-wdm-driver_initialize), the ndislwf driver registers as an NDIS 6 filter driver.
+
+1. Later on, NDIS calls Ndislwf's [*FilterAttach*](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ndis/nc-ndis-filter_attach) handler, for each underlying NDIS adapter on which it is configured to attach.
+
+1. In the context of [*FilterAttach*](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ndis/nc-ndis-filter_attach) Handler, the filter driver calls [**NdisFSetAttributes**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ndis/nf-ndis-ndisfsetattributes) to register its filter module context with NDIS. After that, the filter driver can read its own setting in registry by calling [**NdisOpenConfigurationEx**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ndis/nf-ndis-ndisopenconfigurationex), and call other `NdisXxx` functions.
+
+1. After [*FilterAttach*](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ndis/nc-ndis-filter_attach) successfully returns, NDIS restarts the filter later by calling its [*FilterRestart*](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ndis/nc-ndis-filter_restart) handler. *FilterRestart* should prepare to handle send/receive data. After restart return successfully, filter driver should be able to process send/receive.
+
+1. All requests and sends coming from overlying drivers for the Ndislwf filter driver are repackaged if necessary and sent down to NDIS, to be passed to the underlying NDIS driver.
+
+1. All indications arriving from an underlying NDIS driver are forwarded up by Ndislwf filter driver.
+
+1. NDIS calls the filter's [*FilterPause*](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ndis/nc-ndis-filter_pause) handler when NDIS needs to detach the filter from the stack or there is some configuration changes in the stack. In processing the pause request from NDIS, the Ndislwf driver waits for all its own outstanding requests to be completed before it completes the pause request.
+
+1. NDIS calls the Ndislwf driver's [*FilterDetach*](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ndis/nc-ndis-filter_detach) entry point when NDIS needs to detach a filter module from NDIS stack. The *FilterDetach* handler should free all the memory allocation done in [*FilterAttach*](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ndis/nc-ndis-filter_attach), and undo the operations it did in *FilterAttach* Handler.
diff --git a/network/ndis/filter/ndislwf.vcxproj b/network/ndis/filter/ndislwf.vcxproj
index f381ba89..fa4f9d39 100644
--- a/network/ndis/filter/ndislwf.vcxproj
+++ b/network/ndis/filter/ndislwf.vcxproj
@@ -211,6 +211,9 @@
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>SHA256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Link>
@@ -220,6 +223,9 @@
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>SHA256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Link>
@@ -229,6 +235,9 @@
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>SHA256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Link>
@@ -238,6 +247,9 @@
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>SHA256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="device.c">
diff --git a/network/ndis/filter/ndislwf.vcxproj.Filters b/network/ndis/filter/ndislwf.vcxproj.Filters
index 200de09e..fab2d582 100644
--- a/network/ndis/filter/ndislwf.vcxproj.Filters
+++ b/network/ndis/filter/ndislwf.vcxproj.Filters
@@ -37,4 +37,23 @@
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Include="*.inf">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/network/ndis/mux/README.md b/network/ndis/mux/README.md
index 6eea6284..5b784e04 100644
--- a/network/ndis/mux/README.md
+++ b/network/ndis/mux/README.md
@@ -5,22 +5,14 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: NDIS MUX Intermediate Driver and Notify Object
- platform: WDM
- language: cpp
- category: Network
- description: An NDIS 6.0 driver that demonstrates the operation of an N:1 MUX driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617916
---->
-
# NDIS MUX Intermediate Driver and Notify Object
-The MUX Intermediate Miniport (IM) driver is an NDIS 6.0 driver that demonstrates the operation of an "N:1" MUX driver.The sample demonstrates creating multiple virtual network devices on top of a single lower adapter. Protocols bind to these virtual adapters as if they are real adapters. Examples of Intermediate Miniport drivers that can use this framework are Virtual LAN (VLAN) drivers. Included in the project is a sample Notify Object that demonstrates how to write a notify object for installing and configuring an NDIS MUX intermediate miniport (IM) driver that implements an N:1 relationship between upper and lower bindings, for example, it creates multiple virtual network devices on top of a single lower adapter. Protocols bind to these virtual adapters as if they are real adapters. Examples of Intermediate Miniport drivers that can use this type of notify object are Virtual LAN (VLAN) drivers.
+The MUX Intermediate Miniport (IM) driver is an NDIS 6.0 driver that demonstrates the operation of an "N:1" MUX driver. The sample demonstrates creating multiple virtual network devices on top of a single lower adapter. Protocols bind to these virtual adapters as if they are real adapters. Examples of Intermediate Miniport drivers that can use this framework are Virtual LAN (VLAN) drivers. Included in the project is a sample Notify Object that demonstrates how to write a notify object for installing and configuring an NDIS MUX intermediate miniport (IM) driver that implements an N:1 relationship between upper and lower bindings, for example, it creates multiple virtual network devices on top of a single lower adapter.
-For more information, see [NDIS Intermediate Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff565773) in the network devices design guide.
+For more information, see [NDIS Intermediate Drivers](https://docs.microsoft.com/windows-hardware/drivers/network/ndis-intermediate-drivers) in the network devices design guide.
## Installing the sample
@@ -28,17 +20,21 @@ MUX is installed as a protocol (called *Sample Mux-IM Protocol Driver* in the su
To install, follow the steps below:
-1. Prepare an installation directory that contains these files: muxp.inf, mux\_mp.inf, mux.sys and mux.dll (notification object DLL, built in this DDK at network\\ndis\\mux\\notifyob).
-2. On the desktop, right-click the **My Network Places** icon and choose **Properties**.
-3. Right-click on the relevant **Local Area Connection** icon and choose **Properties**.
-4. Click **Install**, then **Protocol**, then **Add**, then **Have Disk**.
-5. Browse to the drive/directory containing the files listed above. Click **OK**. This should show **Sample Mux-IM Protocol Driver** in a list of Network Protocols. Highlight this and click **OK**. This should install the MUX driver.
-6. Click **OK** or **Yes** each time the system prompts with a warning regarding installation of unsigned files. This is necessary because binaries generated via the DDK build environment are not signed.
+1. Prepare an installation directory that contains these files: muxp.inf, mux\_mp.inf, mux.sys and mux.dll (notification object DLL, built in this DDK at network\\ndis\\mux\\notifyob).
+
+1. On the desktop, right-click the **My Network Places** icon and choose **Properties**.
+
+1. Right-click on the relevant **Local Area Connection** icon and choose **Properties**.
+
+1. Click **Install**, then **Protocol**, then **Add**, then **Have Disk**.
+
+1. Browse to the drive/directory containing the files listed above. Click **OK**. This should show **Sample Mux-IM Protocol Driver** in a list of Network Protocols. Highlight this and click **OK**. This should install the MUX driver.
+
+1. Click **OK** or **Yes** each time the system prompts with a warning regarding installation of unsigned files. This is necessary because binaries generated via the DDK build environment are not signed.
Two .INF files are needed rather than one because MUX is installed both as a protocol and a miniport.
-NDIS MUX Intermediate Driver
-----------------------------
+## NDIS MUX Intermediate Driver
The driver binds to Ethernet (NdisMedium802\_3) adapters as a protocol, and exposes one or more virtual Ethernet devices over each lower adapter, based on its configuration. The term "VELAN" is used to denote a Virtual Ethernet LAN adapter implemented by this driver.
@@ -66,13 +62,13 @@ The VLAN ID for each VELAN (virtual miniport) can be configured as follows. Righ
When it loads, i.e. from its DriverEntry function, the MUX driver registers as an Intermediate miniport driver and as a protocol, in that order.
-### Binding and VELAN Creation
+#### Binding and VELAN Creation
NDIS calls MUX's BindAdapter function, `PtBindAdapter`, for each underlying NDIS adapter to which it is configured to bind. This function allocates an `ADAPT` structure to represent the lower adapter, and calls `NdisOpenAdapter` to set up a binding to it. In the context of `BindAdapterHandler`, after successfully opening a binding to the underlying adapter, the driver queries the reserved keyword "UpperBindings" to get a list of device names for the virtual adapters that this particular binding is to expose, see `PtBootStrapVElans` for more details. Note that the MUX driver does not create bindings (for example, call `NdisOpenAdapter`) from any context other than its BindAdapter function. This is recommended behavior for all drivers of this type.
For each device name specified in the "UpperBindings" key, the MUX driver allocates a VELAN data structure to represent the virtual miniport, calls `NdisIMInitializeDeviceInstanceEx`. In response, NDIS eventually calls the MUX miniport's MiniportInitialize entry point, MPInitialize, for each VELAN. After MPInitialize successfully returns, NDIS takes care of getting upper-layer protocols to bind to the newly created virtual adapter(s).
-### Unbinding and Halting
+#### Unbinding and Halting
NDIS calls MUX's `UnbindAdapter` handler, `PtUnbindAdapter`, to request it to unbind from a lower adapter. In processing this, MUX calls `NdisIMDeInitializeDeviceInstance` for each VELAN instantiated on the indicated adapter, see `PtStopVElan` for details. This call results in NDIS first unbinding any protocols bound to the indicated VELAN, and then calling the MiniportHalt routine, `MPHalt`, for that VELAN. `MPHalt` waits for any outstanding receives/sends on the VELAN to finish before unlinking the VELAN from the ADAPT.
@@ -80,11 +76,11 @@ NDIS calls MUX's `UnbindAdapter` handler, `PtUnbindAdapter`, to request it to un
`MPHalt` may also be called if the VELAN device is disabled, e.g. from the Network Connections Folder. There is no special code within `MPHalt` to handle this condition. However, `PtUnbindAdapter` takes care to not attempt to deinitialize a VELAN miniport (via `NdisIMDeInitializeDeviceInstance`) that has already been halted.
-### Handling Queries
+#### Handling Queries
`MPRequest` is the MUX driver's function that handles queries for OID values on VELAN miniports. Most of the "Ethernet" type information for the virtual miniport is stored in the VELAN structure itself, and the driver returns information from this structure. The queries that are forwarded are **OID\_GEN\_MEDIA\_CONNECT\_STATUS**, **OID\_PNP\_CAPABILITIES** and **OID\_PNP\_WAKE\_UP\_PATTERN\_LIST**. See "Handling Power Management" below for more information about the latter two OIDs.
-### Handling Sets
+#### Handling Sets
`MPRequest` handles setting OID values on VELAN miniports. Data management OIDs handled by the MUX driver are **OID\_802\_3\_MULTICAST\_LIST** and **OID\_GEN\_CURRENT\_PACKET\_FILTER**. The multicast list is handled entirely within the MUX driver, it just stores the set of multicast addresses in the VELAN structure, for reference during receive-side data processing. The packet filter is handled in a different way. The MUX driver combines the packet filter settings (bitwise OR) of all VELANs associated with the same lower adapter. If the combined packet filter is non-zero, MUX sends a Set request with a value of **NDIS\_PACKET\_TYPE\_PROMISCUOUS** for **OID\_GEN\_CURRENT\_PACKET\_FILTER** to start receives on the lower adapter. If the combined packet filter is zero, MUX sets the lower adapter's packet filter to 0 (turns off all receives if there aren't any interested protocols).
@@ -92,13 +88,13 @@ Note that setting the lower adapter to promiscuous mode is only done here in ord
Some power management OIDs are forwarded to the lower miniport. See "Handling Power Management" below for details.
-### Sending Data
+#### Sending Data
Data sent down on a VELAN miniport is forwarded to the lower adapter. The MUX driver itself does not generate any data of its own. The MUX driver clones a `NET_BUFFER_LIST` for each `NetBufferList` passed to its `MPSendNetBufferLists` function, and saves a pointer to the original `NET_BUFFER_LIST` in the reserved area of the `NET_BUFFER_LIST` structure. When the lower adapter completes the send (`PtSendNBLComplete`), MUX picks up the original packet and calls `NdisMSendNetBufferListsComplete` to complete the original send request.
If a non-zero VLAN ID is configured for the VELAN, and/or the packet has non-zero Ieee8021QInfo per-packet information, then the MUX driver inserts an NDIS buffer containing a tag header to the front of the packet before sending it down, see function `MPHandleSendTagging` for details.
-### Receiving Data
+#### Receiving Data
Data received from a lower adapter is indicated up on zero or more VELANs. The `PtReceiveNBL` function is called for each `NetBufferList` received from the lower adapter. The received data is checked for matches with the packet filter and multicast list for each VELAN associated with the adapter (see `PtMatchPacketToVElan`). Whenever a match is found, a new `NET_BUFFER_LIST` is allocated and set to point to the received data. A pointer to the original received `NET_BUFFER_LIST` (if any) is also stored in the new `NET_BUFFER_LIST`'s reserved area. This packet is indicated up via `NdisMIndicateReceiveNetBufferLists` to all interested protocols on that VELAN.
@@ -106,15 +102,15 @@ The driver's `MPReturnNetBufferLists` function is called either by NDIS or by MU
The driver indicates up received frames that do not have an IEEE 802.1Q tag header in them, see function **PtHandleRcvTagging**. It always strips off tag headers, if present, on received frames. If a non-zero VLAN ID is configured, then it checks received frames that contain tag headers for matching VLAN Ids, only matching frames are indicated up to protocols. Any VLAN/priority information present in incoming frames is copied to per-packet information fields of indicated `NET_BUFFER_LIST` structures.
-### Status Indications
+#### Status Indications
The only status indications that are forwarded up by MUX are media connect status indications. See `PtStatus` for more details.
-### Handling Power Management
+#### Handling Power Management
During initialization (`MPInitialize`), the MUX miniport sets the attribute **NDIS\_ATTRIBUTE\_NO\_HALT\_ON\_SUSPEND** in its call to `NdisMSetMiniportAttributes`. When the MUX miniport is requested to report its Plug and Play capabilities (**OID\_PNP\_CAPABILITIES**), the MUX miniport forwards the request to the underlying miniport. If this request succeeds, then the MUX miniport overwrites the following fields before successfully completing the original request:
-```
+```txt
NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
NDIS_DEVICE_POWER_STATE MinPatternWakeUp= NdisDeviceStateUnspecified;
NDIS_DEVICE_POWER_STATE MinLinkChangeWakeUp=NdisDeviceStateUnspecified
@@ -128,42 +124,47 @@ NDIS calls the MUX driver's `ProtocolPnPEvent` function (`PtPNPHandler`) wheneve
Queries/sets received on a VELAN miniport that are to be forwarded to the underlying adapter are queued on the VELAN if the underlying adapter is at a low power state. These are picked up for processing on receiving a notification that the underlying adapter is back to a powered-up state.
-### Handling Global Reconfiguration
+#### Handling Global Reconfiguration
All modifications to VELAN configuration are accompanied by PnP reconfigure notifications, for example, `NetEventReconfigure` events passed to the MUX's `PnPEventHandler`, `PtPNPHandler`. This driver takes a broad approach to handling reconfiguration, which is to simply re-examine all the "UpperBindings" keys for all currently bound adapters, and start off VELANs for any that do not exit, see `PtBootStrapVElans` for details.
-### Canceling Sends
+#### Canceling Sends
MUX propagates send cancellations from protocols above it to lower miniports.
-Sample Notify Object
---------------------
+## Sample Notify Object
-### Preprocessor Flags:
+### Preprocessor Flags
-### DISABLE\_PROTOCOLS\_TO\_PHYSICAL
+#### DISABLE\_PROTOCOLS\_TO\_PHYSICAL
When this flag is defined in the Sources file, the notify object disables the bindings of other protocols such as TCP/IP to the physical adapters during the installation. When all the virtual adapters are removed either through the custom property page or as a result of uninstalling the MUX driver, the notify object re-enables those bindings.
-### PASSTHRU\_NOTIFY
+#### PASSTHRU\_NOTIFY
This flag is defined to allow the MUX driver to be used in a passthru mode. When this flag is defined, the notify object:
-1. Creates only one virtual miniport for every physical adapter the MUX protocol edge binds to.
-2. Disables the property page to prevent adding of additional virtual miniports.
-3. Stores the device name of the virtual adapter in REG\_SZ registry value under HKLM\\System\\CurrentControlSet\\Services\\muxp\\Parameters\\Adapters\\{PhysicalAdaptersInstanceGuid}\\UpperBindings, because there is one to one binding. In the MUX mode (when this flag is not defined), the notify object stores the device name in a REG\_MULTI\_SZ registry value as there could be more than one virtual miniports.
+1. Creates only one virtual miniport for every physical adapter the MUX protocol edge binds to.
+
+1. Disables the property page to prevent adding of additional virtual miniports.
+
+1. Stores the device name of the virtual adapter in REG\_SZ registry value under HKLM\\System\\CurrentControlSet\\Services\\muxp\\Parameters\\Adapters\\{PhysicalAdaptersInstanceGuid}\\UpperBindings, because there is one to one binding. In the MUX mode (when this flag is not defined), the notify object stores the device name in a REG\_MULTI\_SZ registry value as there could be more than one virtual miniports.
You can also use this notify object with the Passthru driver by doing the following:
-1. Change the protocol name in file \\ndis\\passthru\\passthru.c from **PASSTHRU** to **MUXP.**
-2. Change the driver name from Passthru to MUX in the sources file.
-3. Rebuild the driver to obtain a mux.sys driver binary.
-4. Build the MUX notify object with **PASSTHRU\_NOTIFY** defined.
-5. Use the MUX inf files, muxp.inf and mux\_mp.inf, to install the driver and dll.
+1. Change the protocol name in file \\ndis\\passthru\\passthru.c from **PASSTHRU** to **MUXP.**
+
+1. Change the driver name from Passthru to MUX in the sources file.
+
+1. Rebuild the driver to obtain a mux.sys driver binary.
+
+1. Build the MUX notify object with **PASSTHRU\_NOTIFY** defined.
+
+1. Use the MUX inf files, muxp.inf and mux\_mp.inf, to install the driver and dll.
The benefit of using techniques in the MUX notify object for a 1:1 intermediate driver (e.g. Passthru) is to be able to exercise higher level of control over the bindings of MUX with other components in the system, which is not possible with the IM filter driver.
-### CUSTOM\_EVENTS
+#### CUSTOM\_EVENTS
When this macro is defined, the notify object shows how to send custom events to the MUX IM driver when a virtual miniport is added or removed.
@@ -171,9 +172,11 @@ When this macro is defined, the notify object shows how to send custom events to
During installation, the notify object performs the following operations:
-- It creates one virtual adapter for each physical adapter the MUX protocol edge binds to.
-- It disables the bindings of other protocols such as TCP/IP to physical adapters if it has been compiled with DISABLE\_PROTOCOLS\_TO\_PHYSICAL defined in the Sources file. This is the most commonly desired behavior for N:1 MUX drivers.
-- It disables the bindings of the protocol edge of the MUX IM driver with all its virtual adapters.
+- It creates one virtual adapter for each physical adapter the MUX protocol edge binds to.
+
+- It disables the bindings of other protocols such as TCP/IP to physical adapters if it has been compiled with DISABLE\_PROTOCOLS\_TO\_PHYSICAL defined in the Sources file. This is the most commonly desired behavior for N:1 MUX drivers.
+
+- It disables the bindings of the protocol edge of the MUX IM driver with all its virtual adapters.
The notify object provides a custom property page for the MUX IM driver. The custom property page allows the user to add one or more virtual adapters on top of a physical adapter or delete an existing virtual adapter.
@@ -181,16 +184,16 @@ When the MUX IM driver is uninstalled, or binding is disabled, or the user delet
### File Manifest
-File | Description
------|------------
-Miniport.c | Miniport related routines for the MUX driver
-Mux.c | DriverEntry routine and any routines common to the MUX miniport and protocol
-Mux.h | Prototypes of all functions and data structures used by the MUX driver
-Mux.rc | Resource file for the MUX driver
-Muxp.inf | Installation INF for the service (protocol side installation)
-Mux_mp.inf | Installation INF for the miniport (virtual device installation)
-Precomp.h | Precompile header file
-Protocol.c | Protocol related routines for the MUX driver
-Public.h | Contains the common declarations shared by driver and user applications
+| File | Description |
+| --- | --- |
+| Miniport.c | Miniport related routines for the MUX driver |
+| Mux.c | DriverEntry routine and any routines common to the MUX miniport and protocol |
+| Mux.h | Prototypes of all functions and data structures used by the MUX driver |
+| Mux.rc | Resource file for the MUX driver |
+| Muxp.inf | Installation INF for the service (protocol side installation) |
+| Mux_mp.inf | Installation INF for the miniport (virtual device installation) |
+| Precomp.h | Precompile header file |
+| Protocol.c | Protocol related routines for the MUX driver |
+| Public.h | Contains the common declarations shared by driver and user applications |
-For more information, see [NDIS Intermediate Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff565773) in the network devices design guide.
+For more information, see [NDIS Intermediate Drivers](https://docs.microsoft.com/windows-hardware/drivers/network/ndis-intermediate-drivers) in the network devices design guide.
diff --git a/network/ndis/ndisprot/6x/README.md b/network/ndis/ndisprot/6x/README.md
index 2efbcc66..8c94783c 100644
--- a/network/ndis/ndisprot/6x/README.md
+++ b/network/ndis/ndisprot/6x/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: NDIS Connection-less Protocol WDM Driver Sample
- platform: WDM
- language: cpp
- category: Network
- description: Demonstrates a connection-less NDIS 6.0 protocol WDM driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617917
---->
-
# NDIS Connection-less Protocol WDM Driver Sample
This sample demonstrates a connection-less NDIS 6.0 protocol WDM driver. The driver supports sending and receiving raw Ethernet frames using `ReadFile`/`WriteFile` calls from user-mode. It only receives frames with a specific EtherType field. As an NDIS protocol, it illustrates how to establish and tear down bindings to Ethernet adapters, i.e. those that export medium type **NdisMedium802\_3**. It shows how to set a packet filter, send and receive data, and handle plug-and-play events.
@@ -30,49 +22,50 @@ Select **Sample NDIS Protocol Driver** and click **OK**. After installing the pr
## Usage
-To start the driver, type **Net start ndisprot**.
+To start the driver, type `Net start ndisprot`.
-To stop the driver, type **Net stop ndisprot**.
+To stop the driver, type `Net stop ndisprot`.
-To test the driver, run **prottest**. For help on usage, run **prottest -?**
+To test the driver, run `prottest`. For help on usage, run `prottest -?`
**usage: PROTTEST [options] \\*devicename***
-options | Description
-----------|------------
--e | Enumerate devices
--r | Read
--w | Write (default)
--l | <length>: length of each packet (default: 100)
--n | <count>: number of packets (defaults to infinity)
--m | <MAC address> (defaults to local MAC)
+| Options | description |
+| --- | --- |
+| -e | Enumerate devices |
+| -r | Read |
+| -w | Write (default) |
+| -l | <length>: length of each packet (default: 100) |
+| -n | <count>: number of packets (defaults to infinity) |
+| -m | <MAC address> (defaults to local MAC) |
Prottest exercises the IOCTLs supported by NDISPROT, and sends and/or receives data on the selected device. In order to use prottest, the user must have administrative privilege. Users should pass down a big enough buffer in order to receive the entire received data. If the length of the buffer passed down is smaller than the length of the received data, NDISPROT will only copy part of the data and discard the rest when the given buffer is full.
Use the **-e** option to enumerate all devices to which NDISPROT is bound:
-**C:\\prot\>prottest -n 2 \\DEVICE\\{9273DA7D-5275-4B9A-AC56-68A49D121F1F}**
-
-**DoWriteProc: finished sending 2 packets of 100 bytes each**
-
-**DoReadProc finished: read 2 packets**
+```cmd
+C:\\prot\>prottest -n 2 \\DEVICE\\{9273DA7D-5275-4B9A-AC56-68A49D121F1F}
+DoWriteProc: finished sending 2 packets of 100 bytes each
+DoReadProc finished: read 2 packets
+```
-**Note** With a checked version of ndisprot.sys, you can control the volume of debug information generated by changing the variable `ndisprotDebugLevel`. Refer to debug.h for more information.
+> [!NOTE]
+> With a checked version of ndisprot.sys, you can control the volume of debug information generated by changing the variable `ndisprotDebugLevel`. Refer to debug.h for more information.
-For more information, see [NDIS Protocol Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff566821) in the network devices design guide.
+For more information, see [NDIS Protocol Drivers](https://docs.microsoft.com/windows-hardware/drivers/network/ndis-protocol-drivers) in the network devices design guide.
## File Manifest
-File | Description
------|------------
-prottest.c | User-mode test application
-debug.c | Routines to aid debugging
-debug.h | Debug macro definitions
-macros.h | Spinlock, event, referencing macros
-ndisbind.c | NDIS protocol entry points to handle binding/unbinding from adapters
-ndisprot.h | Data structure definitions
-ndisprot.inf | INF file for installing NDISPROT
-ntdisp.c | NT Entry points and dispatch routines for NDISPROT
-protuser.h | IOCTL and associated structure definitions
-recv.c | NDIS protocol entry points for receiving data, and IRP_MJ_READ processing
-send.c | NDIS protocol routines for sending data, and IRP_MJ_WRITE processing \ No newline at end of file
+| File | description |
+| --- | --- |
+| prottest.c | User-mode test application |
+| debug.c | Routines to aid debugging |
+| debug.h | Debug macro definitions |
+| macros.h | Spinlock, event, referencing macros |
+| ndisbind.c | NDIS protocol entry points to handle binding/unbinding from adapters |
+| ndisprot.h | Data structure definitions |
+| ndisprot.inf | INF file for installing NDISPROT |
+| ntdisp.c | NT Entry points and dispatch routines for NDISPROT |
+| protuser.h | IOCTL and associated structure definitions |
+| recv.c | NDIS protocol entry points for receiving data, and IRP_MJ_READ processing |
+| send.c | NDIS protocol routines for sending data, and IRP_MJ_WRITE processing |
diff --git a/network/ndis/ndisprot/6x/sys/60/ndisprot60.vcxproj b/network/ndis/ndisprot/6x/sys/60/ndisprot60.vcxproj
index 0f930a7b..da4c5c58 100644
--- a/network/ndis/ndisprot/6x/sys/60/ndisprot60.vcxproj
+++ b/network/ndis/ndisprot/6x/sys/60/ndisprot60.vcxproj
@@ -154,6 +154,9 @@
<Midl>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..</AdditionalIncludeDirectories>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Link>
@@ -170,6 +173,9 @@
<Midl>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..</AdditionalIncludeDirectories>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Link>
@@ -186,6 +192,9 @@
<Midl>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..</AdditionalIncludeDirectories>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Link>
@@ -202,6 +211,9 @@
<Midl>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..</AdditionalIncludeDirectories>
</Midl>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\debug.c">
diff --git a/network/ndis/ndisprot/6x/sys/60/ndisprot60.vcxproj.Filters b/network/ndis/ndisprot/6x/sys/60/ndisprot60.vcxproj.Filters
index fb3baf30..32ecad3d 100644
--- a/network/ndis/ndisprot/6x/sys/60/ndisprot60.vcxproj.Filters
+++ b/network/ndis/ndisprot/6x/sys/60/ndisprot60.vcxproj.Filters
@@ -46,4 +46,9 @@
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
+ <ItemGroup>
+ <Inf Include="*.inf">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/network/ndis/ndisprot_kmdf/README.md b/network/ndis/ndisprot_kmdf/README.md
index 3d9418cb..6f1c66e6 100644
--- a/network/ndis/ndisprot_kmdf/README.md
+++ b/network/ndis/ndisprot_kmdf/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Connection-less NDIS 6.0 Protocol KMDF Sample Driver
- platform: KMDF
- language: cpp
- category: Network
- description: Demonstrates a connection-less NDIS 6.0 protocol KMDF driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620197
---->
-
# Connection-less NDIS 6.0 Protocol KMDF Sample Driver
This sample demonstrates a connection-less NDIS 6.0 protocol KMDF driver.
@@ -24,40 +16,38 @@ The driver supports sending and receiving raw Ethernet frames using ReadFile/Wri
The sample also demonstrates how to write a Notify Object dll. The Notify Object is used for calling into the Wdf Coinstaller to install and load the framework library.
-Related technologies
---------------------
+## Related technologies
-[Creating Framework-based Miniport Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff540778)
+[Creating Framework-based Miniport Drivers](https://docs.microsoft.com/windows-hardware/drivers/wdf/creating-kmdf-miniport-drivers)
-Build the sample
-----------------
+## Build the sample
-For information on how to build a driver solution using Microsoft Visual Studio, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644).
+For information on how to build a driver solution using Microsoft Visual Studio, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver).
The 60 subdirectory (\\ndisprot\_kmdf\\60) indicates that the built sample will be NDIS 6.0 compatible.
-Installation
-------------
+## Installation
Use the following steps to install the sample.
-1. When you build the sample, the build engine produces ndisprot.inf in the build target directory. Copy nprt6wdf.sys, protnotify.dll, and ndisprot.inf to a directory.
-2. Copy the KMDF coinstaller (wdfcoinstaller*MMmmm*.dll) to the same directory.
+1. When you build the sample, the build engine produces ndisprot.inf in the build target directory. Copy nprt6wdf.sys, protnotify.dll, and ndisprot.inf to a directory.
+
+1. Copy the KMDF coinstaller (wdfcoinstaller*MMmmm*.dll) to the same directory.
- **Note** You can obtain redistributable framework updates by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](http://go.microsoft.com/fwlink/p/?LinkID=226396). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0.
+ > [!NOTE]
+ > You can obtain redistributable framework updates by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](https://go.microsoft.com/fwlink/p/?LinkID=253170). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0.
-3. In Control Panel, in the **Network and Internet** group, open **Network Connections**, select an adapter, and then open **Properties**.
+1. In Control Panel, in the **Network and Internet** group, open **Network Connections**, select an adapter, and then open **Properties**.
-4. Click **Install**, and then click **Protocol**.
+1. Click **Install**, and then click **Protocol**.
-5. Click **Add**, and then click **Have disk**.
+1. Click **Add**, and then click **Have disk**.
-6. Point to the location of the INF file and driver, click **Sample NDIS Protocol Driver**, and then click **OK**.
+1. Point to the location of the INF file and driver, click **Sample NDIS Protocol Driver**, and then click **OK**.
-7. After installing the protocol, copy the test application Uiotest.exe to a convenient location. Note that the driver service has been set to manual start in the INF file. As a result, it doesn't get loaded automatically when you install the driver.
+1. After installing the protocol, copy the test application Uiotest.exe to a convenient location. Note that the driver service has been set to manual start in the INF file. As a result, it doesn't get loaded automatically when you install the driver.
-Usage
------
+## Usage
From an administrator command prompt, to start the driver, type **Net start ndisprot**.
@@ -67,7 +57,7 @@ You can build Prottest.exe from source code located in the \\ndisprot\\6x\\test
To test the NDIS 6.0 driver, run prottest. For help on usage, run **prottest -?**.
-```
+```cmd
usage: PROTTEST [options] <devicename>
options:
-e: Enumerate devices
@@ -79,12 +69,11 @@ options:
-f Use a fake address to send out the packets.
```
-
Prottest exercises the IOCTLs supported by NDISPROT, and sends and/or receives data on the selected device. In order to use Prottest, the user must have administrative privilege. Users should pass down a buffer that is large enough to contain the data returned. If the length of the buffer passed down is smaller than the length of the received data, NDISPROT will only copy part of the data and discard the rest when the given buffer is full.
For an NDIS 6.0 driver, use the -e option on prottest to enumerate all devices to which NDISPROT is bound:
-```
+```cmd
C:\prot>prottest -e
0. \DEVICE\{9273DA7D-5275-4B9A-AC56-68A49D121F1F}
- Intel-Based 10/100 Ethernet Card
@@ -92,7 +81,7 @@ C:\prot>prottest -e
The following command sends and receives 2 packets on a device. Since these packets are sent to the local MAC address (default), both packets are received. The device name parameter to prottest is picked up from the output of **prottest -e** (see above).
-```
+```cmd
C:\prot>prottest -n 2 \DEVICE\{9273DA7D-5275-4B9A-AC56-68A49D121F1F}
DoWriteProc: finished sending 2 packets of 100 bytes each
DoReadProc finished: read 2 packets
@@ -102,31 +91,30 @@ For security reasons, this driver does not allow packets with fake MAC addresses
With a checked version of ndisprot.sys, you can control the volume of debug information generated by changing the variable **ndisprotDebugLevel**. Refer to debug.h for more information.
-File Manifest
--------------
+## File Manifest
-**Directory: 60**
+### Directory: 60
-File | Description
------|------------
-debug.c | Routines to aid debugging
-debug.h | Debug macro definitions
-excallbk.c | Handles load order dependency between this sample and NDISWDM sample
-macros.h | Spinlock, event, referencing macros
-ndisbind.c | NDIS protocol entry points to handle binding/unbinding from adapters
-ndisprot.h | Data structure definitions
-precomp.h | Contains the precompiled headers
-protuser.h | Has the definitions of ioctls issued by protuser.exe application used on NDIS 6.0
-nuiouser.h | Has the definitions of ioctls issued by nuiouser.exe application used on NDIS 5.0
-ndisprot.inf | INF file for installing NDISPROT
-ntdisp.c | NT Entry points and dispatch routines for NDISPROT
-recv.c | NDIS protocol entry points for receiving data, and IRP_MJ_READ processing
+| File | description |
+| --- | --- |
+| debug.c | Routines to aid debugging |
+| debug.h | Debug macro definitions |
+| excallbk.c | Handles load order dependency between this sample and NDISWDM sample |
+| macros.h | Spinlock, event, referencing macros |
+| ndisbind.c | NDIS protocol entry points to handle binding/unbinding from adapters |
+| ndisprot.h | Data structure definitions |
+| precomp.h | Contains the precompiled headers |
+| protuser.h | Has the definitions of ioctls issued by protuser.exe application used on NDIS 6.0 |
+| nuiouser.h | Has the definitions of ioctls issued by nuiouser.exe application used on NDIS 5.0 |
+| ndisprot.inf | INF file for installing NDISPROT |
+| ntdisp.c | NT Entry points and dispatch routines for NDISPROT |
+| recv.c | NDIS protocol entry points for receiving data, and IRP_MJ_READ processing |
-**Directory: NotifyOb**
+### Directory: NotifyOb
-File | Description
------|------------
-Common.hpp | Header file containing the common include files for the project
-dllmain.cpp | Handles loading/unloading of Wdf Coinstaller and the notify object dll
-ProtNotify.idl | Defines the interfaces for the notify object dll
-ProtNotify.rc | Resource file for the notify object dll
+| File | description |
+| --- | --- |
+| Common.hpp | Header file containing the common include files for the project |
+| dllmain.cpp | Handles loading/unloading of Wdf Coinstaller and the notify object dll |
+| ProtNotify.idl | Defines the interfaces for the notify object dll |
+| ProtNotify.rc | Resource file for the notify object dll |
diff --git a/network/ndis/netvmini/6x/README.md b/network/ndis/netvmini/6x/README.md
index b631890c..ff122de2 100644
--- a/network/ndis/netvmini/6x/README.md
+++ b/network/ndis/netvmini/6x/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: NDIS Virtual Miniport Driver
- platform: WDM
- language: cpp
- category: Network
- description: Demonstrates the functionality of an NDIS miniport driver without requiring a physical network adapter.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617918
---->
-
# NDIS Virtual Miniport Driver
The NDIS Virtual Miniport Driver sample illustrates the functionality of an NDIS miniport driver without requiring a physical network adapter.
@@ -26,6 +18,7 @@ This sample driver demonstrates an NDIS virtual miniport driver. If a single ins
To test the miniport driver, install more than one miniport driver instance. You can repeat the installation to install more than one instance of the miniport.
-**Note** This sample provides an example of minimal driver intended for education purposes. The driver and its sample test programs are not intended for use in a production environment.
+> [!NOTE]
+> This sample provides an example of minimal driver intended for education purposes. The driver and its sample test programs are not intended for use in a production environment.
-For more information on creating NDIS Miniport Drivers, see [NDIS Miniport Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff565949).
+For more information on creating NDIS Miniport Drivers, see [NDIS Miniport Drivers](https://docs.microsoft.com/windows-hardware/drivers/network/ndis-miniport-drivers).
diff --git a/network/radio/HidSwitchDriverSample/README.md b/network/radio/HidSwitchDriverSample/README.md
index c7b012a7..55ca9daf 100644
--- a/network/radio/HidSwitchDriverSample/README.md
+++ b/network/radio/HidSwitchDriverSample/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Radio Switch Test Driver for OSR USB-FX2 Development Board
- platform: KMDF
- language: cpp
- category: Network Radio
- description: Demonstrates how to structure a HID driver for radio switches for the OSR USB-FX2 Development Board.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617919
---->
-
# Radio Switch Test Driver for OSR USB-FX2 Development Board
This sample demonstrates how to structure a HID driver for radio switches for the OSR USB-FX2 Development Board.
@@ -26,9 +18,9 @@ The hardware switch or button to control wireless transmission and the global so
### Switch Mapping
- 1 | 2 | 3 | 4 | 5 | 7 | 8
----|---|---|---|---|---|---
- Mode Select Bit 3 | Mode Select Bit 2 | Mode Select Bit 1 | - | - | - | Radio Switch
+| 1 | 2 | 3 | 4 | 5 | 7 | 8 |
+| --- | --- | --- | --- | --- | --- | --- |
+| Mode Select Bit 3 | Mode Select Bit 2 | Mode Select Bit 1 | - | - | - | Radio Switch |
## Testing
@@ -38,16 +30,16 @@ The driver supports five modes representing the valid combinations of HID descri
### Switch Mapping Modes
- 1 | 2 | 3 | Mode
----|---|---|-----
- 0 | 0 | 0 | Mode 1
- 0 | 0 | 1 | Mode 1
- 0 | 1 | 0 | Mode 2
- 0 | 1 | 1 | Mode 3
- 1 | 0 | 0 | Mode 4
- 1 | 0 | 1 | Mode 5
- 1 | 1 | 0 | Mode 1
- 1 | 1 | 1 | Mode 1
+| 1 | 2 | 3 | Mode |
+| --- | --- | --- | --- |
+| 0 | 0 | 0 | Mode 1 |
+| 0 | 0 | 1 | Mode 1 |
+| 0 | 1 | 0 | Mode 2 |
+| 0 | 1 | 1 | Mode 3 |
+| 1 | 0 | 0 | Mode 4 |
+| 1 | 0 | 1 | Mode 5 |
+| 1 | 1 | 0 | Mode 1 |
+| 1 | 1 | 1 | Mode 1 |
### Mode 1 Radio Push Button
diff --git a/network/radio/RadioManagerSample/README.md b/network/radio/RadioManagerSample/README.md
index 50b6c917..26c36d42 100644
--- a/network/radio/RadioManagerSample/README.md
+++ b/network/radio/RadioManagerSample/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Windows Radio Management Sample
- platform: WDM
- language: cpp
- category: Network Radio
- description: Demonstrates how to structure a Radio Manager for use with the Windows Radio Management APIs.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617920
---->
-
# Windows Radio Management Sample
The Radio Manager sample demonstrates how to structure a Radio Manager for use with the Windows Radio Management APIs.
@@ -24,64 +16,62 @@ The operating system contains a set of APIs which are used as a software mechani
When the user turns the radio off (either by using the specific radio software switch or the airplane mode switch), radio transmission must be turned off. The device can be powered off as long as the radio switch does not disappear from the UI. It is very important that the radio manager developer ensures that when the device is powered off, the radio switch does not disappear from the UI. If the radio switch disappears from the UI when the radio is turned off by the user, then user has no way to turn the radio back on! If it is desired to conserve power by cutting power to the device when the radio is turned off, but the device cannot be completely powered off because it disappears from the UI, then the solution would be to put the device in a low power state (e.g. D3).
-**Important** The radio manager must be given a name. This is the name of the radio switch that is displayed to the user in the Wireless page of PC Settings. The name must be simple, yet descriptive of what the radio is. For example, for NFC radios, the value of the name field should be "NFC", and for GPS radios, the value of the name field should be "GPS" or "GNSS", whichever is more appropriate. The name must not include the word "radio" or the manufacturer's name or some other word related to the functionality of the radio (e.g. "Location" OR "port").
-
+> [!IMPORTANT]
+> The radio manager must be given a name. This is the name of the radio switch that is displayed to the user in the Wireless page of PC Settings. The name must be simple, yet descriptive of what the radio is. For example, for NFC radios, the value of the name field should be "NFC", and for GPS radios, the value of the name field should be "GPS" or "GNSS", whichever is more appropriate. The name must not include the word "radio" or the manufacturer's name or some other word related to the functionality of the radio (e.g. "Location" OR "port").
-Installation
-------------
+## Installation
The sample contains a script, *install.cmd*, which copies the radio manager DLL to the system directory, registers as a COM component, and configures the registry.
Copy the *install.cmd*, *SampleRM.reg* and *SampleRM.dll* files to a directory. Run *install.cmd*.
-Code Tour
----------
+## Code Tour
-File | Description
------|-----
-install.cmd | Installation script. Copies and registers the dll and executes SampleRM.reg.
-SampleRM.reg | Script to install the Sample Radio Manager into the registry, along with 2 radio instances.
-SampleRM.sln | The Visual Studio solution file for building the Sample Radio Manager dll.
-sampleRM.idl |The interface definition for the Sample Radio Manager.
-RadioMgr.idl | The interface definition for a Windows Radio Manager.
-SampleRadioManager.h | Header file for the functions required for a Radio Manager.
-SampleRadioInstance.h | Header file for the functions required for a Radio Instance.
-SampleInstanceCollection.h | Header file for the functions required for a Collection of Radio Instances.
-precomp.h | Common header file.
-InternalInterfaces.h | Header file for internal interface used for this sample.
-dllmain.cpp | Standard dllmain.
-SampleRadioManager.cpp | Implementation details for the Sample Radio Manager. Important concepts include utilizing [IMediaRadioManagerNotifySink](http://msdn.microsoft.com/en-us/library/windows/hardware/hh406534) for radio instance events, adding/Removing radio instances, and queuing and deploying worker jobs for system events.
-SampleRadioInstance.cpp | Implementation details for the Sample Radio Instance. Important concepts include accessors and modifiers for radio information, and instance change functions.
-SampleInstanceCollection.cpp | Implementation details for the Sample Instance Collection. Important concepts include radio instance discovery and retrieval.
-RadioMgr\_interface.cpp | Helper source file to include the MIDL-generated files.
+| File | description |
+| --- | ---|
+| install.cmd | Installation script. Copies and registers the dll and executes SampleRM.reg. |
+| SampleRM.reg | Script to install the Sample Radio Manager into the registry, along with 2 radio instances. |
+| SampleRM.sln | The Visual Studio solution file for building the Sample Radio Manager dll. |
+| sampleRM.idl |The interface definition for the Sample Radio Manager. |
+| RadioMgr.idl | The interface definition for a Windows Radio Manager. |
+| SampleRadioManager.h | Header file for the functions required for a Radio Manager. |
+| SampleRadioInstance.h | Header file for the functions required for a Radio Instance. |
+| SampleInstanceCollection.h | Header file for the functions required for a Collection of Radio Instances. |
+| precomp.h | Common header file |
+| InternalInterfaces.h | Header file for internal interface used for this sample. |
+| dllmain.cpp | Standard dllmain |
+| Sample Radio Manager. Important concepts include utilizing [IMediaRadioManagerNotifySink](https://docs.microsoft.com/previous-versions/windows/hardware/radio/hh406534(v=vs.85)) for radio instance events, adding/Removing radio instances, and queuing and deploying worker jobs for system events. |
+| SampleRadioInstance.cpp | Implementation details for the Sample Radio Instance. Important concepts include accessors and modifiers for radio information, and instance change functions. |
+| SampleInstanceCollection.cpp | Implementation details for the Sample Instance Collection. Important concepts include radio instance discovery and retrieval. |
+| RadioMgr\_interface.cpp | Helper source file to include the MIDL-generated files. |
-Run the sample
---------------
+## Run the sample
-### Operation ###
+### Operation
This sample Radio Manager does not operate on an actual radio. Instead, it uses registry keys to act as virtual radios.
Each "radio" instance can have the following values:
-Name
+- Name
-RadioState
+- RadioState
-PreviousRadioState
+- PreviousRadioState
-IsMultiComm
+- IsMultiComm
-IsAssociatingDevice
+- IsAssociatingDevice
-**Note** It is required that the registry key has AT LEAST a Name value, otherwise the Sample Radio Manager will fail to initialize.
+> [!NOTE]
+> It is required that the registry key has AT LEAST a Name value, otherwise the Sample Radio Manager will fail to initialize.
-**Important** The radio manager must be given a name and the registry key must have, as a minimum, a Name value. Otherwise, the Sample Radio Manager will fail to initialize. This is the name of the radio switch that is displayed to the user in the Wireless page of PC Settings. The name must be simple, yet descriptive of what the radio is. For example, for NFC radios, the value of the name field should be "NFC", and for GPS radios, the value of the name field should be "GPS" or "GNSS", whichever is more appropriate. The name must not include the word "radio" or the manufacturer's name or some other word related to the functionality of the radio (e.g. "Location" OR "port").
+> [!IMPORTANT]
+> The radio manager must be given a name and the registry key must have, as a minimum, a Name value. Otherwise, the Sample Radio Manager will fail to initialize. This is the name of the radio switch that is displayed to the user in the Wireless page of PC Settings. The name must be simple, yet descriptive of what the radio is. For example, for NFC radios, the value of the name field should be "NFC", and for GPS radios, the value of the name field should be "GPS" or "GNSS", whichever is more appropriate. The name must not include the word "radio" or the manufacturer's name or some other word related to the functionality of the radio (e.g. "Location" OR "port").
When the Radio Manager is initialized, it uses these registry keys to retrieve the "radio" information. The radio state values can be any of the following enum values:
-
-```c_cpp
+```cpp
typedef enum _DEVICE_RADIO_STATE
{
DRS_RADIO_ON = 0,
@@ -97,21 +87,21 @@ typedef enum _DEVICE_RADIO_STATE
For IsMultiComm and IsAssociatingDevice, a value of 0 means 'no' and 1 means 'yes'.
-### Adding and Setting a Radio Instance ###
+### Adding and Setting a Radio Instance
To add a new radio instance, add a new instance key to the registry key like the following entry:
-```
+```inf
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\RadioManagement\Misc\SampleRadioManager\SampleRadioX]
"RadioState"=dword:00000000
"Name"="SampleRadioX"
"IsMultiComm"=dword:00000000
```
-### Editing a Radio Instance ###
+### Editing a Radio Instance
Simply change the values in the registry. For example, change the radio state from DRS\_RADIO\_ON to DRS\_SW\_RADIO\_OFF by changing the 'RadioState' value from 0 to 1.
-### Removing a Radio Instance ###
+### Removing a Radio Instance
Delete the corresponding registry key.
diff --git a/network/trans/WFPSampler/README.md b/network/trans/WFPSampler/README.md
index 6ca2d1f9..1acc1490 100644
--- a/network/trans/WFPSampler/README.md
+++ b/network/trans/WFPSampler/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Windows Filtering Platform Sample
- platform: KMDF
- language: cpp
- category: Network
- description: A sample firewall that has a command-line interface which allows adding filters at various WFP layers.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620198
---->
-
# Windows Filtering Platform Sample
The WFPSampler sample driver is a sample firewall. It has a command-line interface which allows adding filters at various WFP layers with a wide variety of conditions. Additionally it exposes callout functions for injection, basic action, proxying, and stream inspection.
@@ -38,34 +30,33 @@ WFPSamplerSys.Lib is a library of kernel mode helper functions used throughout t
Once you have downloaded the sample, the .mht files in the sample's docs directory describe the various WFP filtering scenarios that you can try.
-For more information about WFP callout drivers, see [Windows Filtering Platform Callout Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff571068).
-
+For more information about WFP callout drivers, see [Windows Filtering Platform Callout Drivers](https://docs.microsoft.com/windows-hardware/drivers/network/windows-filtering-platform-callout-drivers2).
-Open the driver solution in Visual Studio
------------------------------------------
+## Open the driver solution in Visual Studio
Navigate to the folder that contains the sample. Double click the solution file, WFPSampler.sln. In Visual Studio, locate Solution Explorer. (If this is not already open, choose **Solution Explorer** from the **View** menu.) In Solution Explorer, you can see one solution that has these projects:
-- a user-mode application project named **WFPSampler** (under the **Exe** node)
-- a user-mode library project named **WFPSampler** (under the **Lib** node)
-- a user-mode service project named **WFPSamplerService** (under the **Svc** node)
-- a driver project named **WFPSamplerCalloutDriver** (under the **Sys** node)
-- a kernel-mode library project named **WFPSampler** (under the **Syslib** node)
+- a user-mode application project named **WFPSampler** (under the **Exe** node)
+
+- a user-mode library project named **WFPSampler** (under the **Lib** node)
+
+- a user-mode service project named **WFPSamplerService** (under the **Svc** node)
+
+- a driver project named **WFPSamplerCalloutDriver** (under the **Sys** node)
-Set the configuration and platform in Visual Studio
----------------------------------------------------
+- a kernel-mode library project named **WFPSampler** (under the **Syslib** node)
+
+## Set the configuration and platform in Visual Studio
In Visual Studio, in Solution Explorer, right click **Solution 'WFPSampler' (5 projects)**, and choose **Configuration Manager**. Set the configuration and the platform. Make sure that the configuration and platform are the same for all projects. Do not check the **Deploy** boxes.
-Set the runtime library for the user-mode application, library, and service
----------------------------------------------------------------------------
+## Set the runtime library for the user-mode application, library, and service
In Solution Explorer, right-click the **WFPSampler** user-mode application project (under the **Exe** node), and choose **Properties.** Navigate to **Configuration Properties \> C/C++ \> Code Generation**. For **Runtime Library**, select **Multi-threaded Debug (/MTd)**. Click **OK**.
Repeat this process for the **WFPSampler** user-mode library (under the **Lib** node) and the **WFPSampler** user-mode service (under the **Svc** node).
-Edit the restart setting in the sample installation script
-----------------------------------------------------------
+## Edit the restart setting in the sample installation script
Open the WfpSamplerInstall.cmd file (in the scripts folder) in Visual Studio.
@@ -77,98 +68,103 @@ to this:
`RunDLL32.Exe syssetup,SetupInfObjectInstallAction DefaultInstall 132 %WinDir%\System32\Drivers\WFPSamplerCalloutDriver.Inf`
-For more information about this setting, see the Remarks section for the [**InstallHinfSection**](http://msdn.microsoft.com/en-us/library/windows/hardware/aa376957) function.
+For more information about this setting, see the Remarks section for the [**InstallHinfSection**](https://docs.microsoft.com/windows/win32/api/setupapi/nf-setupapi-installhinfsectiona) function.
-Build the sample using Visual Studio
-------------------------------------
+## Build the sample using Visual Studio
In Visual Studio, on the **Build** menu, choose **Build Solution**.
-For more information about using Microsoft Visual Studio to build a driver package, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644).
+For more information about using Microsoft Visual Studio to build a driver package, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver).
-Locate the built driver package
--------------------------------
+## Locate the built driver package
In File Explorer, navigate to the folder that contains your built driver package. The location of this folder varies depending on what you set for configuration and platform. For example, if your settings are Debug and x64, the driver is in your sample folder under **\\Debug**.
The driver folder contains these files:
-File | Description
------|------------
-wfpsamplercalloutdriver.cat | A signed catalog file, which serves as the signature for the entire package.
-WFPSamplerCalloutDriver.inf | An information (INF) file that contains information needed to install the driver.
-WFPSamplerCalloutDriver.sys | The WFPSampler driver.
+| File | Description |
+| --- | --- |
+| wfpsamplercalloutdriver.cat | A signed catalog file, which serves as the signature for the entire package. |
+| WFPSamplerCalloutDriver.inf | An information (INF) file that contains information needed to install the driver. |
+| WFPSamplerCalloutDriver.sys | The WFPSampler driver. |
-**Note** The build process might also put WdfCoinstaller010*xx*.dll in the driver folder, but this file is not really part of the driver package. The INF file does not reference any coinstallers.
+> [!NOTE]
+> The build process might also put WdfCoinstaller010*xx*.dll in the driver folder, but this file is not really part of the driver package. The INF file does not reference any coinstallers.
Because the package does not contain a KMDF coinstaller, it is important that you set the KMDF minor version according to your target operating system when you built the driver.
-Locate the symbol file (PDB) for the driver
--------------------------------------------
+## Locate the symbol file (PDB) for the driver
In **File Explorer**, locate the symbol file, WFPSamplerCalloutDriver.pdb. The location of this file varies depending on what you set for configuration and platform. For example, if your settings are Debug and Win32, the PDB file is in your sample folder under sys\\Debug.
-Locate the user-mode application and its symbol file (PDB)
-----------------------------------------------------------
+## Locate the user-mode application and its symbol file (PDB)
In **File Explorer**, locate the user-mode application (WFPSampler.exe) and its symbol file (WFPSampler.pdb). The location of these files varies depending on what you set for configuration and platform. For example, if your settings are Debug and x64, WFPSampler.exe and WFPSampler.pdb are in your sample folder under exe\\Debug.
-Locate the kernel-mode service and its symbol file (PDB)
---------------------------------------------------------
+## Locate the kernel-mode service and its symbol file (PDB)
In **File Explorer**, locate the kernel-mode library, WFPSamplerService.exe. The location of this file varies depending on what you set for configuration and platform. For example, if your settings are Debug and x64, WFPSamplerService.exe and WFPSamplerService.pdb are in your sample folder under svc\\Debug.
-Run the sample
---------------
+## Run the sample
The computer where you install the driver is called the *target computer* or the *test computer*. Typically this is a separate computer from where you develop and build the driver package. The computer where you develop and build the driver is called the *host computer*.
The process of moving the driver to the target computer and installing the driver is called *deploying the driver*. You can deploy the Windows Filtering Platform Sample driver automatically or manually.
-Automatic deployment
---------------------
+## Automatic deployment
+
+Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1).
+
+After you have provisioned the target computer, continue with these steps:
+
+1. On the host computer, in Visual Studio, in Solution Explorer, right-click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
+
+1. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Do not install**. Click **OK**.
-Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/). After you have provisioned the target computer, continue with these steps:
+1. In the **Build** menu, choose **Build Solution**.
-1. On the host computer, in Visual Studio, in Solution Explorer, right-click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
-2. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Do not install**. Click **OK**.
-3. In the **Build** menu, choose **Build Solution**.
-4. Copy the following files to the DriverTest\\Drivers folder on the target computer:
- - The user-mode application (WFPSampler.exe) file
- - The kernel-mode service (WFPSamplerService.exe) file
+1. Copy the following files to the DriverTest\\Drivers folder on the target computer:
-Manual deployment
------------------
+ - The user-mode application (WFPSampler.exe) file
-Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment). After you have prepared the target computer for manual deployment, copy the following files to a folder on the target computer (for example, c:\\WFPSamplerSamplePackage):
+ - The kernel-mode service (WFPSamplerService.exe) file
-- The 4 files in your driver package folder
-- The user-mode application (WFPSampler.exe) file
-- The kernel-mode service (WFPSamplerService.exe) file
+## Manual deployment
-Copy additional files to the target computer
---------------------------------------------
+Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](https://docs.microsoft.com/windows-hardware/drivers/devtest/devcon) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
+
+After you have prepared the target computer for manual deployment, copy the following files to a folder on the target computer (for example, c:\\WFPSamplerSamplePackage):
+
+- The 4 files in your driver package folder
+
+- The user-mode application (WFPSampler.exe) file
+
+- The kernel-mode service (WFPSamplerService.exe) file
+
+## Copy additional files to the target computer
Copy the driver's PDB file (WFPSamplerCalloutDriver.pdb), the user-mode service's PDB file (WFPSamplerService.pdb) and the user-mode application's PDB file (WFPSampler.pdb) to a folder on the target computer (for example, c:\\Symbols).
-Copy the [**TraceView**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff553872) and [**SignTool**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff551778) tools to a folder on the target computer (for example c:\\Tools).
+Copy the [**TraceView**](https://docs.microsoft.com/windows-hardware/drivers/devtest/traceview) and [**SignTool**](https://docs.microsoft.com/windows-hardware/drivers/devtest/signtool) tools to a folder on the target computer (for example c:\\Tools).
-- [**TraceView**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff553872) comes with the WDK. You can find it in your WDK installation folder under Tools (for example, c:\\Program Files (x86)\\Windows Kits\\10\\Tools\\x64\\TraceView.exe).
-- [**SignTool**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff551778) also comes with the WDK. You can find it in your WDK installation folder under bin (for example, c:\\Program Files (x86)\\Windows Kits\\10\\bin\\x64\\SignTool.exe).
+- [**TraceView**](https://docs.microsoft.com/windows-hardware/drivers/devtest/traceview) comes with the WDK. You can find it in your WDK installation folder under Tools (for example, c:\\Program Files (x86)\\Windows Kits\\10\\Tools\\x64\\TraceView.exe).
-Installing the driver
----------------------
+- [**SignTool**](https://docs.microsoft.com/windows-hardware/drivers/devtest/signtool) also comes with the WDK. You can find it in your WDK installation folder under bin (for example, c:\\Program Files (x86)\\Windows Kits\\10\\bin\\x64\\SignTool.exe).
-1. On the target computer, open a Command Prompt window as Administrator. Navigate to the folder that contains the installation script:
- - For manual deployment, this will be the folder that you copied the driver page files into (for example, c:\\WFPSamplerSamplePackage).
- - For automatic deployment, this will be DriverTest\\Drivers.
+## Installing the driver
-2. Enter **WFPSamplerInstall.cmd** to run the installation script.
+1. On the target computer, open a Command Prompt window as Administrator. Navigate to the folder that contains the installation script:
- **Note** If you need to uninstall a previous version of the driver, enter **WFPSamplerInstall.cmd -r**.
+ - For manual deployment, this will be the folder that you copied the driver page files into (for example, c:\\WFPSamplerSamplePackage).
-Running the user-mode application
----------------------------------
+ - For automatic deployment, this will be DriverTest\\Drivers.
+
+1. Enter **WFPSamplerInstall.cmd** to run the installation script.
+
+ > [!NOTE]
+ > If you need to uninstall a previous version of the driver, enter `WFPSamplerInstall.cmd -r`.
+
+## Running the user-mode application
On the target computer, open a Command Prompt window as Administrator.
@@ -178,20 +174,20 @@ The .mht files in the docs directory describe the various WFP filtering scenario
For example, you can test the basic packet examination scenario by using the following command line:
-**WFPSampler.exe -s BASIC\_PACKET\_EXAMINATION -l FWPM\_LAYER\_INBOUND\_IPPACKET\_V4 -v**
+`WFPSampler.exe -s BASIC\_PACKET\_EXAMINATION -l FWPM\_LAYER\_INBOUND\_IPPACKET\_V4 -v`
This command line adds a dynamic filter (-v) at the FWPM\_LAYER\_INBOUND\_IPPACKET\_V4 layer (-l) which references the appropriate callout driver function. This filter will have no conditions, so it will act on all traffic seen at this layer.
-Start a logging session in TraceView
-------------------------------------
+## Start a logging session in TraceView
On the target computer, open TraceView.exe as Administrator. On the **File** menu, choose **Create New Log Session**. Click **Add Provider**. Select **PDB (Debug Information File)**, and enter the path to your PDB file, WFPSamplerCalloutDriver.pdb. Click **OK** and click **Next**. Click the **\>\>** button next to **Set Flags and Level**, double-click the **L** button next to **Level**, and set the **Level** to **Information**. Click **OK** and click **Finish**.
If you want to test whether your TraceView.exe session is working, you can enter the following commands and see what the trace output looks like:
-- **net stop WFPSamplerCallouts**
-- **net start WFPSamplerCallouts**
+- `net stop WFPSamplerCallouts`
+
+- `net start WFPSamplerCallouts`
-For more information, see [Creating a Trace Session with a PDB File](http://msdn.microsoft.com/en-us/library/windows/hardware/ff543582).
+For more information, see [Creating a Trace Session with a PDB File](https://docs.microsoft.com/windows-hardware/drivers/devtest/creating-a-trace-session-with-a-pdb-file).
Tracing for the sample driver can be started at any time before the driver is started or while the driver is already running.
diff --git a/network/trans/WFPSampler/sys/Framework_Events.cpp b/network/trans/WFPSampler/sys/Framework_Events.cpp
index cd2290f6..baf59cc8 100644
--- a/network/trans/WFPSampler/sys/Framework_Events.cpp
+++ b/network/trans/WFPSampler/sys/Framework_Events.cpp
@@ -104,6 +104,7 @@ VOID EventCleanupDriverObject(_In_ WDFOBJECT driverObject)
Notes: <br>
<br>
MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF540840.aspx <br>
+ HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF549133.aspx <br>
*/
_IRQL_requires_min_(PASSIVE_LEVEL)
_IRQL_requires_max_(PASSIVE_LEVEL)
@@ -159,11 +160,25 @@ VOID EventCleanupDeviceObject(_In_ WDFOBJECT deviceObject)
FwpmBfeStateUnsubscribeChanges(g_bfeSubscriptionHandle);
- UnregisterPowerStateChangeCallback(&g_deviceExtension);
-
if(g_pNDISPoolData)
KrnlHlprNDISPoolDataDestroy(&g_pNDISPoolData);
+ UnregisterPowerStateChangeCallback(&g_deviceExtension);
+
+ if(g_pPowerStateExitIOWorkItem)
+ {
+ IoFreeWorkItem(g_pPowerStateExitIOWorkItem);
+
+ g_pPowerStateExitIOWorkItem = 0;
+ }
+
+ if(g_pPowerStateEnterIOWorkItem)
+ {
+ IoFreeWorkItem(g_pPowerStateEnterIOWorkItem);
+
+ g_pPowerStateEnterIOWorkItem = 0;
+ }
+
#if DBG
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
diff --git a/network/trans/WFPSampler/sys/Framework_PowerStates.cpp b/network/trans/WFPSampler/sys/Framework_PowerStates.cpp
index ed67b11f..c615f8a1 100644
--- a/network/trans/WFPSampler/sys/Framework_PowerStates.cpp
+++ b/network/trans/WFPSampler/sys/Framework_PowerStates.cpp
@@ -20,6 +20,118 @@
#include "Framework_WFPSamplerCalloutDriver.h" /// .
#include "Framework_PowerStates.tmh" /// $(OBJ_PATH)\$(O)\
+KGUARDED_MUTEX guardedMutex = {0};
+
+/**
+ @framework_function="ActOnPowerStateEnter"
+
+ Purpose: Passive function to handle entering a power managed state. Prior to dropping into a power managed <br>
+ state, unregister the callouts. This prevents the driver from potentially taking any more <br>
+ references on NBLs, and instead causes the filters to return BLOCK. This should also allow adequate <br>
+ time to drain currently queued NBLs. <br>
+ <br>
+ Notes: <br>
+ <br>
+ MSDN_Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nc-wdm-io_workitem_routine <br>
+*/
+_IRQL_requires_(PASSIVE_LEVEL)
+_IRQL_requires_same_
+_Function_class_(IO_WORKITEM_ROUTINE)
+VOID ActOnPowerStateEnter(_In_ PDEVICE_OBJECT pDeviceObject,
+ _Inout_opt_ PVOID pContext)
+{
+#if DBG
+
+ DbgPrintEx(DPFLTR_IHVNETWORK_ID,
+ DPFLTR_INFO_LEVEL,
+ " ---> ActOnPowerStateEnter()\n");
+
+#endif /// DBG
+
+ UNREFERENCED_PARAMETER(pDeviceObject);
+ UNREFERENCED_PARAMETER(pContext);
+
+ KeAcquireGuardedMutex(&guardedMutex);
+
+ if(g_calloutsRegistered == TRUE)
+ {
+ NTSTATUS status = STATUS_SUCCESS;
+
+ status = KrnlHlprExposedCalloutsUnregister();
+ HLPR_BAIL_ON_FAILURE(status);
+
+ g_calloutsRegistered = FALSE;
+ }
+
+ HLPR_BAIL_LABEL:
+
+ KeReleaseGuardedMutex(&guardedMutex);
+
+#if DBG
+
+ DbgPrintEx(DPFLTR_IHVNETWORK_ID,
+ DPFLTR_INFO_LEVEL,
+ " <--- ActOnPowerStateEnter()\n");
+
+#endif /// DBG
+
+ return;
+}
+
+/**
+ @framework_function="ActOnPowerStateExit"
+
+ Purpose: Passive function to handle exiting a power managed state. When coming out of a power managed state, <br>
+ register the callouts so normal processing of NBLs will commence. <br>
+ <br>
+ Notes: <br>
+ <br>
+ MSDN_Ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nc-wdm-io_workitem_routine <br>
+*/
+_IRQL_requires_(PASSIVE_LEVEL)
+_IRQL_requires_same_
+_Function_class_(IO_WORKITEM_ROUTINE)
+VOID ActOnPowerStateExit(_In_ PDEVICE_OBJECT pDeviceObject,
+ _Inout_opt_ PVOID pContext)
+{
+#if DBG
+
+ DbgPrintEx(DPFLTR_IHVNETWORK_ID,
+ DPFLTR_INFO_LEVEL,
+ " ---> ActOnPowerStateExit()\n");
+
+#endif /// DBG
+
+ UNREFERENCED_PARAMETER(pDeviceObject);
+ UNREFERENCED_PARAMETER(pContext);
+
+ KeAcquireGuardedMutex(&guardedMutex);
+
+ if(g_calloutsRegistered == FALSE)
+ {
+ NTSTATUS status = STATUS_SUCCESS;
+
+ status = KrnlHlprExposedCalloutsRegister();
+ HLPR_BAIL_ON_FAILURE(status);
+
+ g_calloutsRegistered = TRUE;
+ }
+
+ HLPR_BAIL_LABEL:
+
+ KeReleaseGuardedMutex(&guardedMutex);
+
+#if DBG
+
+ DbgPrintEx(DPFLTR_IHVNETWORK_ID,
+ DPFLTR_INFO_LEVEL,
+ " <--- ActOnPowerStateExit()\n");
+
+#endif /// DBG
+
+ return;
+}
+
/**
@framework_function="PowerStateCallback"
@@ -47,36 +159,23 @@ VOID PowerStateCallback(_In_ VOID* pCallbackContext,
if(pPowerStateEvent == (VOID*)PO_CB_SYSTEM_STATE_LOCK)
{
- NTSTATUS status = STATUS_SUCCESS;
-
if(pEventSpecifics)
{
/// entering the ON state (S0), so return operation to normal
- if(g_calloutsRegistered == FALSE)
- {
- status = KrnlHlprExposedCalloutsRegister();
- HLPR_BAIL_ON_FAILURE(status);
-
- g_calloutsRegistered = TRUE;
- }
+ IoQueueWorkItem(g_pPowerStateExitIOWorkItem,
+ ActOnPowerStateExit,
+ DelayedWorkQueue,
+ 0);
}
else
{
- /// leaving the ON state (S0) to sleep (S1/S2/S3) or hibernate (S4)
- /// Unregister the callouts so no more injection will take place. By default, the filters
- /// invoking the callouts will return block.
- if(g_calloutsRegistered == TRUE)
- {
- status = KrnlHlprExposedCalloutsUnregister();
- HLPR_BAIL_ON_FAILURE(status);
-
- g_calloutsRegistered = FALSE;
- }
+ IoQueueWorkItem(g_pPowerStateEnterIOWorkItem,
+ ActOnPowerStateEnter,
+ DelayedWorkQueue,
+ 0);
}
}
- HLPR_BAIL_LABEL:
-
#if DBG
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
@@ -89,7 +188,7 @@ VOID PowerStateCallback(_In_ VOID* pCallbackContext,
}
/**
- @framework_function="RegisterPowerStateChangeCallback"
+ @framework_function="UnregisterPowerStateChangeCallback"
Purpose: Unregister a callback that handled notifications of power state changes. <br>
<br>
@@ -168,6 +267,8 @@ NTSTATUS RegisterPowerStateChangeCallback(_Inout_ DEVICE_EXTENSION* pDeviceExten
OBJECT_ATTRIBUTES objectAttributes = {0};
UNICODE_STRING unicodeString = {0};
+ KeInitializeGuardedMutex(&guardedMutex);
+
RtlInitUnicodeString(&unicodeString,
L"\\Callback\\PowerState");
diff --git a/network/trans/WFPSampler/sys/Framework_WFPSamplerCalloutDriver.cpp b/network/trans/WFPSampler/sys/Framework_WFPSamplerCalloutDriver.cpp
index 88824779..88369c81 100644
--- a/network/trans/WFPSampler/sys/Framework_WFPSamplerCalloutDriver.cpp
+++ b/network/trans/WFPSampler/sys/Framework_WFPSamplerCalloutDriver.cpp
@@ -32,13 +32,15 @@ extern "C"
DRIVER_INITIALIZE DriverEntry;
};
-PDEVICE_OBJECT g_pWDMDevice = 0;
-NDIS_POOL_DATA* g_pNDISPoolData = 0;
-BOOLEAN g_calloutsRegistered = FALSE;
-HANDLE g_bfeSubscriptionHandle = 0;
-SERIALIZATION_LIST g_bsiSerializationList = {0};
-WFPSAMPLER_DEVICE_DATA g_WFPSamplerDeviceData = {0};
-DEVICE_EXTENSION g_deviceExtension = {0};
+PDEVICE_OBJECT g_pWDMDevice = 0;
+PIO_WORKITEM g_pPowerStateEnterIOWorkItem = 0;
+PIO_WORKITEM g_pPowerStateExitIOWorkItem = 0;
+NDIS_POOL_DATA* g_pNDISPoolData = 0;
+BOOLEAN g_calloutsRegistered = FALSE;
+HANDLE g_bfeSubscriptionHandle = 0;
+SERIALIZATION_LIST g_bsiSerializationList = {0};
+WFPSAMPLER_DEVICE_DATA g_WFPSamplerDeviceData = {0};
+DEVICE_EXTENSION g_deviceExtension = {0};
KSPIN_LOCK g_bpeSpinLock;
WDFDRIVER g_WDFDriver;
WDFDEVICE g_WDFDevice;
@@ -405,6 +407,14 @@ NTSTATUS PrvDriverDeviceAdd(_In_ WDFDRIVER* pWDFDriver)
HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(g_pWDMDevice,
status);
+ g_pPowerStateEnterIOWorkItem = IoAllocateWorkItem(g_pWDMDevice);
+ HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(g_pPowerStateEnterIOWorkItem,
+ status);
+
+ g_pPowerStateExitIOWorkItem = IoAllocateWorkItem(g_pWDMDevice);
+ HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(g_pPowerStateExitIOWorkItem,
+ status);
+
status = RegisterPowerStateChangeCallback(&g_deviceExtension);
HLPR_BAIL_ON_FAILURE(status);
diff --git a/network/trans/WFPSampler/sys/Framework_WFPSamplerCalloutDriver.h b/network/trans/WFPSampler/sys/Framework_WFPSamplerCalloutDriver.h
index 52b03284..b8902383 100644
--- a/network/trans/WFPSampler/sys/Framework_WFPSamplerCalloutDriver.h
+++ b/network/trans/WFPSampler/sys/Framework_WFPSamplerCalloutDriver.h
@@ -77,6 +77,9 @@ typedef struct DEVICE_EXTENSION_
extern PDEVICE_OBJECT g_pWDMDevice;
+extern PIO_WORKITEM g_pPowerStateEnterIOWorkItem;
+extern PIO_WORKITEM g_pPowerStateExitIOWorkItem;
+
extern WDFDRIVER g_WDFDriver;
extern WDFDEVICE g_WDFDevice;
diff --git a/network/trans/WFPSampler/sys/WFPSamplerCalloutDriver.InX b/network/trans/WFPSampler/sys/WFPSamplerCalloutDriver.InX
index 5fe96e36..b101c772 100644
--- a/network/trans/WFPSampler/sys/WFPSamplerCalloutDriver.InX
+++ b/network/trans/WFPSampler/sys/WFPSamplerCalloutDriver.InX
@@ -33,7 +33,7 @@
WFPSamplerCalloutDriver.sys = 1,,
[ClassInstall32.nt$ARCH$]
- AddReg = WFPCalloutClassReg
+ AddReg = WFPCalloutsClassReg
[DestinationDirs]
DefaultDestDir = 12 ;/// %WinDir%\System32\Drivers
@@ -53,8 +53,8 @@
[DefaultUninstall.nt$ARCH$.Services]
DelService = %WFPSamplerCalloutDriverServiceName%,0x200 ;/// SPSVCINST_STOPSERVICE
-[WFPCalloutClassReg]
- HKR,,,0,%WFPCalloutClassName%
+[WFPCalloutsClassReg]
+ HKR,,,0,%WFPCalloutsClassName%
HKR,,Icon,,-5
HKR,,SilentInstall,,1
HKR,,DeviceCharacteristics,0x10001,0x100 ;/// FLG_ADDREG_BINVALUETYPE | FLG_ADDREG_TYPE_MULTI_SZ, FILE_DEVICE_SECURE_OPEN
@@ -85,7 +85,7 @@
[Strings]
ProviderString = "TODO-Set-Provider"
- WFPCalloutClassName = "WFP Callout"
+ WFPCalloutsClassName = "WFP Callout Drivers"
WFPSamplerCalloutDriverDeviceDescription = "WFP Sampler Callout Device"
WFPSamplerCalloutDriverDescription = "WFP Sampler Callout Driver"
WFPSamplerCalloutDriverServiceName = "WFPSamplerCallouts"
diff --git a/network/trans/WFPSampler/syslib/HelperFunctions_Macros.h b/network/trans/WFPSampler/syslib/HelperFunctions_Macros.h
index 36c2ec00..8af997bb 100644
--- a/network/trans/WFPSampler/syslib/HelperFunctions_Macros.h
+++ b/network/trans/WFPSampler/syslib/HelperFunctions_Macros.h
@@ -155,7 +155,7 @@ extern "C"
/**
@macro="HLPR_DELETE"
- Purpose: Free memory allocated with ExAllocatePoolWithTag and set the pointer to 0. <br>
+ Purpose: Free memory allocated with ExAllocatePoolZero and set the pointer to 0. <br>
<br>
Notes: <br>
<br>
@@ -172,7 +172,7 @@ extern "C"
/**
@macro="HLPR_DELETE_ARRAY"
- Purpose: Free memory allocated with ExAllocatePoolWithTag and set the pointer to 0. <br>
+ Purpose: Free memory allocated with ExAllocatePoolZero and set the pointer to 0. <br>
<br>
Notes: <br>
<br>
@@ -184,7 +184,7 @@ extern "C"
/**
@macro="HLPR_NEW"
- Purpose: Allocate memory from NonPaged Pool with ExAllocatePoolWithTag and initialize it's
+ Purpose: Allocate memory from NonPaged Pool with ExAllocatePoolZero and initialize it's
contents with 0's. <br>
<br>
Notes: Caller responsible for freeing allocated memory using macro HLPR_DELETE. <br>
@@ -196,9 +196,9 @@ extern "C"
pPtr == 0; \
) \
{ \
- pPtr = (object*)ExAllocatePoolWithTag(NonPagedPoolNx, \
- sizeof(object), \
- tag); \
+ pPtr = (object*)ExAllocatePoolZero(NonPagedPoolNx, \
+ sizeof(object), \
+ tag); \
if(pPtr) \
RtlSecureZeroMemory(pPtr, \
sizeof(object)); \
@@ -207,7 +207,7 @@ extern "C"
/**
@macro="HLPR_NEW_ARRAY"
- Purpose: Allocate memory from NonPaged Pool with ExAllocatePoolWithTag and initialize it's
+ Purpose: Allocate memory from NonPaged Pool with ExAllocatePoolZero and initialize it's
contents with 0's. <br>
<br>
Notes: Caller responsible for freeing allocated memory using macro HLPR_DELETE_ARRAY. <br>
@@ -226,9 +226,9 @@ extern "C"
&SAFE_SIZE) == STATUS_SUCCESS && \
SAFE_SIZE >= (sizeof(object) * count)) \
{ \
- pPtr = (object*)ExAllocatePoolWithTag(NonPagedPoolNx, \
- SAFE_SIZE, \
- tag); \
+ pPtr = (object*)ExAllocatePoolZero(NonPagedPoolNx, \
+ SAFE_SIZE, \
+ tag); \
if(pPtr) \
RtlZeroMemory(pPtr, \
SAFE_SIZE); \
@@ -243,7 +243,7 @@ extern "C"
/**
@macro="HLPR_NEW_CASTED_ARRAY"
- Purpose: Allocate memory from NonPaged Pool with ExAllocatePoolWithTag and initialize it's
+ Purpose: Allocate memory from NonPaged Pool with ExAllocatePoolZero and initialize it's
contents with 0's. <br>
<br>
Notes: Caller responsible for freeing allocated memory using macro HLPR_DELETE_ARRAY. <br>
@@ -262,9 +262,9 @@ extern "C"
&SAFE_SIZE) == STATUS_SUCCESS && \
SAFE_SIZE >= (sizeof(object) * count)) \
{ \
- pPtr = (CAST_TYPE*)ExAllocatePoolWithTag(NonPagedPoolNx, \
- SAFE_SIZE, \
- tag); \
+ pPtr = (CAST_TYPE*)ExAllocatePoolZero(NonPagedPoolNx, \
+ SAFE_SIZE, \
+ tag); \
if(pPtr) \
RtlZeroMemory(pPtr, \
SAFE_SIZE); \
@@ -279,7 +279,7 @@ extern "C"
/**
@macro="HLPR_NEW"
- Purpose: Allocate memory from NonPaged Pool with ExAllocatePoolWithTag and leave it's
+ Purpose: Allocate memory from NonPaged Pool with ExAllocatePoolZero and leave it's
contents as is. <br>
<br>
Notes: Caller responsible for freeing allocated memory using macro HLPR_DELETE. <br>
@@ -291,9 +291,9 @@ extern "C"
pPtr == 0; \
) \
{ \
- pPtr = (object*)ExAllocatePoolWithTag(NonPagedPoolNx, \
- sizeof(object), \
- tag); \
+ pPtr = (object*)ExAllocatePoolZero(NonPagedPoolNx, \
+ sizeof(object), \
+ tag); \
}
/**
diff --git a/network/trans/WFPSampler/syslib/HelperFunctions_WorkItems.cpp b/network/trans/WFPSampler/syslib/HelperFunctions_WorkItems.cpp
index 4c47f3b3..23f4a6df 100644
--- a/network/trans/WFPSampler/syslib/HelperFunctions_WorkItems.cpp
+++ b/network/trans/WFPSampler/syslib/HelperFunctions_WorkItems.cpp
@@ -843,9 +843,16 @@ NTSTATUS KrnlHlprWorkItemQueue(_In_ PDEVICE_OBJECT pWDMDevice,
HLPR_BAIL_LABEL:
- if(status != STATUS_SUCCESS &&
- pWorkItemData)
- KrnlHlprWorkItemDataDestroy(&pWorkItemData);
+ if(status != STATUS_SUCCESS)
+ {
+ if(pWorkItemData)
+ KrnlHlprWorkItemDataDestroy(&pWorkItemData);
+ else
+ {
+ if(pIOWorkItem)
+ IoFreeWorkItem(pIOWorkItem);
+ }
+ }
#if DBG
@@ -929,9 +936,16 @@ NTSTATUS KrnlHlprWorkItemQueue(_In_ PDEVICE_OBJECT pWDMDevice,
HLPR_BAIL_LABEL:
- if(status != STATUS_SUCCESS &&
- pWorkItemData)
- KrnlHlprWorkItemDataDestroy(&pWorkItemData);
+ if(status != STATUS_SUCCESS)
+ {
+ if(pWorkItemData)
+ KrnlHlprWorkItemDataDestroy(&pWorkItemData);
+ else
+ {
+ if(pIOWorkItem)
+ IoFreeWorkItem(pIOWorkItem);
+ }
+ }
#if DBG
@@ -1015,9 +1029,16 @@ NTSTATUS KrnlHlprWorkItemQueue(_In_ PDEVICE_OBJECT pWDMDevice,
HLPR_BAIL_LABEL:
- if(status != STATUS_SUCCESS &&
- pWorkItemData)
- KrnlHlprWorkItemDataDestroy(&pWorkItemData);
+ if(status != STATUS_SUCCESS)
+ {
+ if(pWorkItemData)
+ KrnlHlprWorkItemDataDestroy(&pWorkItemData);
+ else
+ {
+ if(pIOWorkItem)
+ IoFreeWorkItem(pIOWorkItem);
+ }
+ }
#if DBG
@@ -1098,9 +1119,16 @@ NTSTATUS KrnlHlprWorkItemQueue(_In_ PDEVICE_OBJECT pWDMDevice,
HLPR_BAIL_LABEL:
- if(status != STATUS_SUCCESS &&
- pWorkItemData)
- KrnlHlprWorkItemDataDestroy(&pWorkItemData);
+ if(status != STATUS_SUCCESS)
+ {
+ if(pWorkItemData)
+ KrnlHlprWorkItemDataDestroy(&pWorkItemData);
+ else
+ {
+ if(pIOWorkItem)
+ IoFreeWorkItem(pIOWorkItem);
+ }
+ }
#if DBG
@@ -1181,9 +1209,16 @@ NTSTATUS KrnlHlprWorkItemQueue(_In_ PDEVICE_OBJECT pWDMDevice,
HLPR_BAIL_LABEL:
- if(status != STATUS_SUCCESS &&
- pWorkItemData)
- KrnlHlprWorkItemDataDestroy(&pWorkItemData);
+ if(status != STATUS_SUCCESS)
+ {
+ if(pWorkItemData)
+ KrnlHlprWorkItemDataDestroy(&pWorkItemData);
+ else
+ {
+ if(pIOWorkItem)
+ IoFreeWorkItem(pIOWorkItem);
+ }
+ }
#if DBG
diff --git a/network/trans/ddproxy/README.md b/network/trans/ddproxy/README.md
index 4f46b929..036d21bc 100644
--- a/network/trans/ddproxy/README.md
+++ b/network/trans/ddproxy/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Windows Filtering Platform Packet Modification Sample
- platform: KMDF
- language: cpp
- category: Network
- description: Demonstrates the packet modification capabilities of the Windows Filtering Platform (WFP).
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617930
---->
-
# Windows Filtering Platform Packet Modification Sample
The sample driver demonstrates the packet modification capabilities of the Windows Filtering Platform (WFP).
@@ -24,55 +16,59 @@ The sample driver demonstrates the packet modification capabilities of the Windo
This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP.
-Run the sample
---------------
+## Run the sample
The computer where you install the driver is called the *target computer* or the *test computer*. Typically this is a separate computer from where you develop and build the driver package. The computer where you develop and build the driver is called the *host computer*.
The process of moving the driver package to the target computer and installing the driver is called *deploying the driver*. You can deploy the Windows Filtering Platform Packet Modification Sample driver automatically or manually.
-Automatic deployment
---------------------
+## Automatic deployment
+
+Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1).
+
+After you have provisioned the target computer, continue with these steps:
+
+1. On the host computer, in Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
+
+1. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Do not install**. Click **OK**.
-Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/). After you have provisioned the target computer, continue with these steps:
+1. On the **Build** menu, choose **Build Solution**.
-1. On the host computer, in Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
-2. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Do not install**. Click **OK**.
-3. On the **Build** menu, choose **Build Solution**.
-4. On the target computer, navigate to DriverTest\\Drivers, and locate the file ddproxy.inf. Right click ddproxy.inf, and choose **Install**.
+1. On the target computer, navigate to DriverTest\\Drivers, and locate the file ddproxy.inf. Right click ddproxy.inf, and choose **Install**.
-Manual deployment
------------------
+## Manual deployment
-Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment). After you have prepared the target computer for manual deployment, continue with these steps:
+Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](https://docs.microsoft.com/windows-hardware/drivers/devtest/devcon) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
-1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\WfpPacketModificationSamplePackage).
-2. On the target computer, navigate to your driver package folder. Right click ddproxy.inf, and choose **Install**
+After you have prepared the target computer for manual deployment, continue with these steps:
-Create Registry values
-----------------------
+1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\WfpPacketModificationSamplePackage).
-1. On the target computer, open Regedit, and navigate to this key:
+1. On the target computer, navigate to your driver package folder. Right click ddproxy.inf, and choose **Install**
+
+## Create Registry values
+
+1. On the target computer, open Regedit, and navigate to this key:
**HKLM**\\**System**\\**CurrentControlSet**\\**Services**\\**ddproxy**\\**Parameters**
-2. Create a REG\_SZ entry named **DestinationAddressToIntercept** and set it's value to an IPV4 or IPV6 address (example: 10.0.0.1).
+1. Create a REG\_SZ entry named **DestinationAddressToIntercept** and set it's value to an IPV4 or IPV6 address (example: 10.0.0.1).
-3. Create a REG\_SZ entry named **NewDestinationAddress**, and set it's value to an IPV4 or IPV6 address (example: 10.0.0.2).
+1. Create a REG\_SZ entry named **NewDestinationAddress**, and set it's value to an IPV4 or IPV6 address (example: 10.0.0.2).
You can also create and set values for the following registry entries.
-- **InspectUdp** (REG\_DWORD type): 0 for ICMP and 1 for UDP (default)
-- **DestinationPortToIntercept** (REG\_DWORD type): UDP port number (applicable if InspectUdp is set to 1)
-- **NewDestinationPort** (REG\_DWORD type): UDP port number (applicable if InspectUdp is set to 1)
+- **InspectUdp** (REG\_DWORD type): 0 for ICMP and 1 for UDP (default)
+
+- **DestinationPortToIntercept** (REG\_DWORD type): UDP port number (applicable if InspectUdp is set to 1)
+
+- **NewDestinationPort** (REG\_DWORD type): UDP port number (applicable if InspectUdp is set to 1)
-Start the ddproxy service
--------------------------
+## Start the ddproxy service
-On the target computer, open a Command Prompt window as Administrator, and enter **net start ddproxy**. (To stop the driver, enter **net stop ddproxy**.)
+On the target computer, open a Command Prompt window as Administrator, and enter `net start ddproxy`. (To stop the driver, enter `net stop ddproxy`.)
-Remarks
--------
+## Remarks
This sample driver consists of a kernel-mode Windows Filtering Platform (WFP) callout driver (Ddproxy.sys) that intercepts User Datagram Protocol (UDP) and nonerror Internet Control Message Protocol (ICMP) traffic of interest and acts as a redirector. For outbound traffic, Ddproxy.sys redirects the traffic to a new destination address and, for UDP, a new UDP port. For inbound traffic, Ddproxy.sys redirects the traffic back to the original address and UDP port values. This redirection is transparent to the application.
@@ -80,4 +76,4 @@ Packet modification is done out-of-band by a system worker thread by using the r
Ddproxy.sys acts as a redirector for both Internet Protocol version 4 (IPv4) and Internet Protocol version 6 (IPv6) traffic.
-For more information on creating a Windows Filtering Platform Callout Driver, see [Windows Filtering Platform Callout Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff571068).
+For more information on creating a Windows Filtering Platform Callout Driver, see [Windows Filtering Platform Callout Drivers](https://docs.microsoft.com/windows-hardware/drivers/network/windows-filtering-platform-callout-drivers2).
diff --git a/network/trans/ddproxy/sys/DD_proxy.c b/network/trans/ddproxy/sys/DD_proxy.c
index a75e2cf9..a5901908 100644
--- a/network/trans/ddproxy/sys/DD_proxy.c
+++ b/network/trans/ddproxy/sys/DD_proxy.c
@@ -833,7 +833,7 @@ DDProxyCloneModifyReinjectInbound(
// is contiguous and 2-byte aligned.
_Analysis_assume_(udpHeader != NULL);
- udpHeader->destPort =
+ udpHeader->srcPort =
packet->belongingFlow->toRemotePort;
// This is our new source port -- or
// the destination port of the original
diff --git a/network/trans/inspect/README.md b/network/trans/inspect/README.md
index 8ab7b525..e590e930 100644
--- a/network/trans/inspect/README.md
+++ b/network/trans/inspect/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Windows Filtering Platform Traffic Inspection Sample
- platform: KMDF
- language: cpp
- category: Network
- description: Demonstrates the traffic inspection capabilities of the Windows Filtering Platform (WFP).
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617931
---->
-
# Windows Filtering Platform Traffic Inspection Sample
This sample driver demonstrates the traffic inspection capabilities of the Windows Filtering Platform (WFP).
@@ -32,41 +24,44 @@ Connect/Packet inspection is done out-of-band by a system worker thread by using
This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP.
-Automatic deployment
---------------------
+## Automatic deployment
+
+Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1).
+
+After you have provisioned the target computer, continue with these steps:
+
+1. On the host computer, in Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
+
+1. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Do not install**. Click **OK**.
+
+1. On the **Build** menu, choose **Build Solution**.
+
+1. On the target computer, navigate to DriverTest\\Drivers, and locate the file inspect.inf. Right click inspect.inf, and choose **Install**.
-Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/). After you have provisioned the target computer, continue with these steps:
+## Manual deployment
-1. On the host computer, in Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
-2. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Do not install**. Click **OK**.
-3. On the **Build** menu, choose **Build Solution**.
-4. On the target computer, navigate to DriverTest\\Drivers, and locate the file inspect.inf. Right click inspect.inf, and choose **Install**.
+Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](https://docs.microsoft.com/windows-hardware/drivers/devtest/devcon) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
-Manual deployment
------------------
+After you have prepared the target computer for manual deployment, continue with these steps:
-Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment). After you have prepared the target computer for manual deployment, continue with these steps:
+1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\WfpTrafficInspectionSamplePackage).
-1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\WfpTrafficInspectionSamplePackage).
-2. On the target computer, navigate to your driver package folder. Right click inspect.inf, and choose **Install**
+1. On the target computer, navigate to your driver package folder. Right click inspect.inf, and choose **Install**
-Create Registry values
-----------------------
+## Create Registry values
-1. On the target computer, open Regedit, and navigate to this key:
+1. On the target computer, open Regedit, and navigate to this key:
**HKLM**\\**System**\\**CurrentControlSet**\\**Services**\\**inspect**\\**Parameters**
-2. Create a REG\_DWORD entry named **BlockTraffic** and set it's value to 0 for permit or 1 to block.
+1. Create a REG\_DWORD entry named **BlockTraffic** and set it's value to 0 for permit or 1 to block.
-3. Create a REG\_SZ entry named **RemoteAddressToInspect**, and set it's value to an IPV4 or IPV6 address (example: 10.0.0.2).
+1. Create a REG\_SZ entry named **RemoteAddressToInspect**, and set it's value to an IPV4 or IPV6 address (example: 10.0.0.2).
-Start the inspect service
--------------------------
+## Start the inspect service
-On the target computer, open a Command Prompt window as Administrator, and enter **net start inspect**. (To stop the driver, enter **net stop inspect**.)
+On the target computer, open a Command Prompt window as Administrator, and enter `net start inspect`. (To stop the driver, enter `net stop inspect`.)
-Remarks
--------
+## Remarks
-For more information on creating a Windows Filtering Platform Callout Driver, see [Windows Filtering Platform Callout Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff571068).
+For more information on creating a Windows Filtering Platform Callout Driver, see [Windows Filtering Platform Callout Drivers](https://docs.microsoft.com/windows-hardware/drivers/network/windows-filtering-platform-callout-drivers2).
diff --git a/network/trans/inspect/inspect.sln b/network/trans/inspect/inspect.sln
index 40b0cead..3f3ae438 100644
--- a/network/trans/inspect/inspect.sln
+++ b/network/trans/inspect/inspect.sln
@@ -1,28 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2013
-VisualStudioVersion = 12.0
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 12.0
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "inspect", "sys\inspect.vcxproj", "{5CF7CFC1-02B4-4938-AC5F-47D743D82E8A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
- Release|Win32 = Release|Win32
Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {5CF7CFC1-02B4-4938-AC5F-47D743D82E8A}.Debug|Win32.ActiveCfg = Debug|Win32
- {5CF7CFC1-02B4-4938-AC5F-47D743D82E8A}.Debug|Win32.Build.0 = Debug|Win32
- {5CF7CFC1-02B4-4938-AC5F-47D743D82E8A}.Release|Win32.ActiveCfg = Release|Win32
- {5CF7CFC1-02B4-4938-AC5F-47D743D82E8A}.Release|Win32.Build.0 = Release|Win32
+ {5CF7CFC1-02B4-4938-AC5F-47D743D82E8A}.Debug|Win32.ActiveCfg = Debug|x64
+ {5CF7CFC1-02B4-4938-AC5F-47D743D82E8A}.Debug|Win32.Build.0 = Debug|x64
{5CF7CFC1-02B4-4938-AC5F-47D743D82E8A}.Debug|x64.ActiveCfg = Debug|x64
{5CF7CFC1-02B4-4938-AC5F-47D743D82E8A}.Debug|x64.Build.0 = Debug|x64
+ {5CF7CFC1-02B4-4938-AC5F-47D743D82E8A}.Release|Win32.ActiveCfg = Release|Win32
+ {5CF7CFC1-02B4-4938-AC5F-47D743D82E8A}.Release|Win32.Build.0 = Release|Win32
{5CF7CFC1-02B4-4938-AC5F-47D743D82E8A}.Release|x64.ActiveCfg = Release|x64
{5CF7CFC1-02B4-4938-AC5F-47D743D82E8A}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {F084D2B3-2035-4BCE-A4D1-FA6AE812D7A1}
+ EndGlobalSection
EndGlobal
diff --git a/network/trans/inspect/sys/inspect.c b/network/trans/inspect/sys/inspect.c
index 418daf9a..8dd6b72a 100644
--- a/network/trans/inspect/sys/inspect.c
+++ b/network/trans/inspect/sys/inspect.c
@@ -1278,7 +1278,7 @@ TLInspectWorker(
listEntry
);
- NT_ASSERT((packet->direction == FWP_DIRECTION_INBOUND) ||
+ NT_ASSERT((packet->direction != FWP_DIRECTION_INBOUND) ||
(packet->authConnectDecision == 0));
if (packet->authConnectDecision == 0)
diff --git a/network/trans/inspect/sys/inspect.vcxproj b/network/trans/inspect/sys/inspect.vcxproj
index 2115972e..c154521d 100644
--- a/network/trans/inspect/sys/inspect.vcxproj
+++ b/network/trans/inspect/sys/inspect.vcxproj
@@ -23,14 +23,14 @@
<RootNamespace>$(MSBuildProjectName)</RootNamespace>
<KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
<Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
- <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <Platform>Desktop</Platform>
<SampleGuid>{910EE323-2C33-42E0-B2DD-3C3BB1F4689E}</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>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
<DriverType>KMDF</DriverType>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
@@ -38,7 +38,7 @@
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>True</UseDebugLibraries>
- <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
<DriverType>KMDF</DriverType>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
@@ -46,7 +46,7 @@
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>False</UseDebugLibraries>
- <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
<DriverType>KMDF</DriverType>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
@@ -54,7 +54,7 @@
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>True</UseDebugLibraries>
- <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
<DriverType>KMDF</DriverType>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
@@ -75,7 +75,10 @@
<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" />
+ <ItemGroup Label="WrappedTaskItems">
+ <ClInclude Include="inspect.h" />
+ <ClInclude Include="utils.h" />
+ </ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<TargetName>inspect</TargetName>
</PropertyGroup>
@@ -170,7 +173,6 @@
<ClCompile Include="utils.c" />
</ItemGroup>
<ItemGroup>
- <Inf Exclude="@(Inf)" Include="*.inf" />
<FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
</ItemGroup>
<ItemGroup>
@@ -179,7 +181,7 @@
<None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
</ItemGroup>
<ItemGroup>
- <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
+ <Inf Include="inspect.inf" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project> \ No newline at end of file
diff --git a/network/trans/inspect/sys/inspect.vcxproj.Filters b/network/trans/inspect/sys/inspect.vcxproj.Filters
index 96fc4202..f4a5dbe0 100644
--- a/network/trans/inspect/sys/inspect.vcxproj.Filters
+++ b/network/trans/inspect/sys/inspect.vcxproj.Filters
@@ -29,4 +29,17 @@
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="inspect.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="utils.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Include="inspect.inf">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/network/trans/msnmntr/README.md b/network/trans/msnmntr/README.md
index 37206c7c..e8104c15 100644
--- a/network/trans/msnmntr/README.md
+++ b/network/trans/msnmntr/README.md
@@ -5,24 +5,17 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Windows Filtering Platform MSN Messenger Monitor Sample
- platform: KMDF
- language: cpp
- category: Network
- description: Demonstrates the stream inspection capabilities of the Windows Filtering Platform (WFP).
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617932
---->
-
# Windows Filtering Platform MSN Messenger Monitor Sample
This sample application and driver demonstrate the stream inspection capabilities of the Windows Filtering Platform (WFP).
The sample consists of a user mode application (Monitor.exe) that registers traffic of interest. In this case, all Transmission Control Protocol (TCP) data segments that are sent and received by an application of your choice.
-**Note** Originally this sample was written to monitor the MSN Messenger application. Now it can monitor any application that you specify.
+> [!NOTE]
+> Originally this sample was written to monitor the MSN Messenger application. Now it can monitor any application that you specify.
Monitor.exe adds filters and callouts to Windows through the Windows Filtering Platform (WFP) Win32 API. A kernel-mode WFP callout driver (Msnmntr.sys) intercepts TCP traffic and parses out communication patterns. Monitor.exe controls the operations of the callout driver through I/O controls (IOCTLs).
@@ -32,26 +25,31 @@ Msnmntr.sys registers itself at two different WFP layers: FLOW-ESTABLISHED and S
After the filters and callouts are in place and registered, WFP indicates TCP data segments to the Msnmntr.sys for inspection. As the data flows through Msnmntr.sys, it copies them (described by a chain of NET\_BUFFER\_LIST structures) to a flat buffer, parses out the communication patterns (such as client-to-server/client-to-client), and sends them to the Windows Software Trace Preprocessor (WPP) for tracing.
-Automatic deployment
---------------------
+## Automatic deployment
+
+Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1).
+
+After you have provisioned the target computer, continue with these steps:
+
+1. On the host computer, in Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
-Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/). After you have provisioned the target computer, continue with these steps:
+1. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Do not install**. Click **OK**.
-1. On the host computer, in Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
-2. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Do not install**. Click **OK**.
-3. On the **Build** menu, choose **Build Solution**.
-4. On the target computer, navigate to DriverTest\\Drivers, and locate the file msnmntr.inf. Right click msnmntr.inf, and choose **Install**.
+1. On the **Build** menu, choose **Build Solution**.
-Manual deployment
------------------
+1. On the target computer, navigate to DriverTest\\Drivers, and locate the file msnmntr.inf. Right click msnmntr.inf, and choose **Install**.
-Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment). After you have prepared the target computer for manual deployment, continue with these steps:
+## Manual deployment
-1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\WfpMsnMessengerMonitorSamplePackage).
-2. On the target computer, navigate to your driver package folder. Right click msnmntr.inf, and choose **Install**
+Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](https://docs.microsoft.com/windows-hardware/drivers/devtest/devcon) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
-Copy additional files to the target computer
---------------------------------------------
+After you have prepared the target computer for manual deployment, continue with these steps:
+
+1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\WfpMsnMessengerMonitorSamplePackage).
+
+1. On the target computer, navigate to your driver package folder. Right click msnmntr.inf, and choose **Install**
+
+## Copy additional files to the target computer
Copy the user-mode application, monitor.exe to a folder on the target computer (for example, c:\\WfpMsnMessengerMonitorSampleApp).
@@ -59,37 +57,33 @@ Copy the PDB file, msnmntr.pdb to a folder on the target computer (for example,
Copy the tool TraceView.exe to a folder on the target computer (for example c:\\Tools). TraceView.exe comes with the WDK. You can find it in your WDK installation folder under Tools (for example, c:\\Program Files (x86)\\Windows Kits\\10\\Tools\\x64\\TraceView.exe).
-Start the msnmntr service
--------------------------
+## Start the msnmntr service
-On the target computer, open a Command Prompt window as Administrator, and enter **net start msnmntr**. (To stop the driver, enter **net stop msnmntr**.)
+On the target computer, open a Command Prompt window as Administrator, and enter `net start msnmntr`. (To stop the driver, enter `net stop msnmntr`.)
-Running the user-mode application
----------------------------------
+## Running the user-mode application
-On the target computer, open a Command Prompt window as Administrator, and navigate to the folder that contains monitor.exe. Enter **monitor.exe addcallouts**. Then enter **monitor.exe monitor** *TargetAppPath*, where *TargetAppPath* is the path to the application that you want to monitor. Here is an example that initiates monitoring of Internet Explorer.
+On the target computer, open a Command Prompt window as Administrator, and navigate to the folder that contains monitor.exe. Enter `monitor.exe addcallouts`. Then enter `monitor.exe monitor` *TargetAppPath*, where *TargetAppPath* is the path to the application that you want to monitor. Here is an example that initiates monitoring of Internet Explorer.
-```
+```cmd
monitor.exe addcallouts
monitor.exe monitor "C:\Program Files (x86)\Internet Explorer\iexplore.exe"
```
-Start a logging session in TraceView
-------------------------------------
+## Start a logging session in TraceView
On the target computer, open TraceView.exe as Administrator. On the **File** menu, choose **Create New Log Session**. Click **Add Provider**. Select **PDB (Debug Information File)**, and enter the path to your PDB file, msnmntr.pdb. Click **OK**, and finish working through the setup procedure. Open Internet Explorer, and watch the communication patterns being displayed in the Traceview.exe tool.
Tracing for the sample driver can be started at any time before the driver is started or while the driver is already running.
-For more information on creating a Windows Filtering Platform Callout Driver, see [Windows Filtering Platform Callout Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff571068).
+For more information on creating a Windows Filtering Platform Callout Driver, see [Windows Filtering Platform Callout Drivers](https://docs.microsoft.com/windows-hardware/drivers/network/windows-filtering-platform-callout-drivers2).
-Using MSBuild
--------------
+## Using MSBuild
-As an alternative to building the WFP MSN Messenger Monitor Sample in Visual Studio, you can build it in a Visual Studio Command Prompt window. In Visual Studio, on the **Tools** menu, choose **Visual Studio Command Prompt**. In the Visual Studio Command Prompt window, navigate to the folder that has the solution file, msnmntr.sln. Use the [MSBuild](http://go.microsoft.com/fwlink/p/?linkID=262804) command to build the solution. Here are some examples:
+As an alternative to building the WFP MSN Messenger Monitor Sample in Visual Studio, you can build it in a Visual Studio Command Prompt window. In Visual Studio, on the **Tools** menu, choose **Visual Studio Command Prompt**. In the Visual Studio Command Prompt window, navigate to the folder that has the solution file, msnmntr.sln. Use the [MSBuild](https://go.microsoft.com/fwlink/p/?linkID=262804) command to build the solution. Here are some examples:
-**msbuild /p:configuration="Debug" /p:platform="x64" msnmntr.sln**
+`msbuild /p:configuration="Debug" /p:platform="x64" msnmntr.sln`
-**msbuild /p:configuration="Release" /p:platform="Win32" msnmntr.sln**
+`msbuild /p:configuration="Release" /p:platform="Win32" msnmntr.sln`
-For more information about using [MSBuild](http://go.microsoft.com/fwlink/p/?linkID=262804) to build a driver package, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644).
+For more information about using [MSBuild](https://docs.microsoft.com/visualstudio/msbuild/msbuild?view=vs-2019) to build a driver package, see [Building a Driver Using the Command Line (MSBuild)](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver#building-a-driver-using-the-command-line-msbuild).
diff --git a/network/trans/msnmntr/sys/msnmntr.c b/network/trans/msnmntr/sys/msnmntr.c
index a2c59cf2..214b98be 100644
--- a/network/trans/msnmntr/sys/msnmntr.c
+++ b/network/trans/msnmntr/sys/msnmntr.c
@@ -257,9 +257,9 @@ MonitorCoAllocFlowContext(
*flowContextOut = NULL;
- flowContext = ExAllocatePoolWithTag(NonPagedPool,
- sizeof(FLOW_DATA),
- TAG_NAME_CALLOUT);
+ flowContext = ExAllocatePoolZero(NonPagedPool,
+ sizeof(FLOW_DATA),
+ TAG_NAME_CALLOUT);
if (!flowContext)
{
@@ -271,9 +271,9 @@ MonitorCoAllocFlowContext(
sizeof(FLOW_DATA));
- flowContext->processPath = ExAllocatePoolWithTag(NonPagedPool,
- processPathSize,
- TAG_NAME_CALLOUT);
+ flowContext->processPath = ExAllocatePoolZero(NonPagedPool,
+ processPathSize,
+ TAG_NAME_CALLOUT);
if (!flowContext->processPath)
{
status = STATUS_NO_MEMORY;
diff --git a/network/trans/msnmntr/sys/notify.c b/network/trans/msnmntr/sys/notify.c
index 22253797..935cd161 100644
--- a/network/trans/msnmntr/sys/notify.c
+++ b/network/trans/msnmntr/sys/notify.c
@@ -270,9 +270,9 @@ NTSTATUS MonitorNfNotifyMessage(
if(streamLength == 0)
return status;
- stream = ExAllocatePoolWithTag(NonPagedPool,
- streamLength,
- TAG_NAME_NOTIFY);
+ stream = ExAllocatePoolZero(NonPagedPool,
+ streamLength,
+ TAG_NAME_NOTIFY);
if (!stream)
return STATUS_INSUFFICIENT_RESOURCES;
diff --git a/network/trans/stmedit/README.md b/network/trans/stmedit/README.md
index b8e67df0..f73db081 100644
--- a/network/trans/stmedit/README.md
+++ b/network/trans/stmedit/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Windows Filtering Platform Stream Edit Sample
- platform: KMDF
- language: cpp
- category: Network
- description: Demonstrates replacing a string pattern for a Transmission Control Protocol (TCP) connection using the Windows Filtering Platform (WFP).
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617933
---->
-
# Windows Filtering Platform Stream Edit Sample
This sample driver demonstrates replacing a string pattern for a Transmission Control Protocol (TCP) connection using the Windows Filtering Platform (WFP).
@@ -26,59 +18,69 @@ This sample builds a Universal Windows Driver. It uses only APIs and DDIs that a
The sample consists of a kernel-mode Windows Filtering Platform (WFP) callout driver (Stmedit.sys) that can operate in one of the following modes:
-- Inline editing where all modification is done within the `ClassifyFn` callout function.
-- Out-of-band editing where all modification is done by a worker thread (the default).
+- Inline editing where all modification is done within the `ClassifyFn` callout function.
+
+- Out-of-band editing where all modification is done by a worker thread (the default).
The sample performs inspection for both Internet Protocol version 4 (IPv4) and Internet Protocol version 6 (IPv6) traffic.
Before experimenting with the sample, add an exception for the InspectionPort to your host firewall.
-Automatic deployment
---------------------
+## Automatic deployment
+
+Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1).
+
+After you have provisioned the target computer, continue with these steps:
+
+1. On the host computer, in Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
+
+1. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Do not install**. Click **OK**.
+
+1. On the **Build** menu, choose **Build Solution**.
+
+1. On the target computer, navigate to DriverTest\\Drivers, and locate the file stmedit.inf. Right click stmedit.inf, and choose **Install**.
-Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/). After you have provisioned the target computer, continue with these steps:
+## Manual deployment
-1. On the host computer, in Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
-2. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Do not install**. Click **OK**.
-3. On the **Build** menu, choose **Build Solution**.
-4. On the target computer, navigate to DriverTest\\Drivers, and locate the file stmedit.inf. Right click stmedit.inf, and choose **Install**.
+Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](https://docs.microsoft.com/windows-hardware/drivers/devtest/devcon) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
-Manual deployment
------------------
+After you have prepared the target computer for manual deployment, continue with these steps:
-Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment). After you have prepared the target computer for manual deployment, continue with these steps:
+1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\WfpStreamEditSamplePackage).
-1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\WfpStreamEditSamplePackage).
-2. On the target computer, navigate to your driver package folder. Right click stmedit.inf, and choose **Install**
+1. On the target computer, navigate to your driver package folder. Right click stmedit.inf, and choose **Install**
-Create Registry values
-----------------------
+## Create Registry values
-- On the target computer, open Regedit, and navigate to this key:
+- On the target computer, open Regedit, and navigate to this key:
- **HKLM**\\**System**\\**CurrentControlSet**\\**Services**\\**strmedit**\\**Parameters**
+ **HKLM**\\**System**\\**CurrentControlSet**\\**Services**\\**strmedit**\\**Parameters**
You can create and set values for the following registry entries.
-- **StringToFind** (REG_SZ, default = "rainy")
-- **StringX** (REG_SZ, default = "cloudy")
-- **StringToReplace** (REG_SZ, default = "sunny")
-- **InspectionLocalPort** (REG_DWORD, default = 8888)
-- **InspectionRemotePort** (REG_DWORD, default = 0)
- Note: for this sample, a local or remote port is mandatory. Both cannot be zero.
-- **InspectioDirection** (REG_DWORD, default = 2)
- possible values : 2 (inbound + outbound), 0 (FWP_DIRECTION_OUTBOUND), 1 (FWP_DIRECTION_INBOUND)
-- **MultipleCallouts** (REG_DWORD, default = true/1)
- controls registration of multiple callouts. Set 0 for false, other for TRUE
-- **BusyThreshold** (REG_DWORD, default = 16KB)
- BusyThreshold value is in KBs (e.g. a value of 5 means 5KB)
+- **StringToFind** (REG_SZ, default = "rainy")
+
+- **StringX** (REG_SZ, default = "cloudy")
+
+- **StringToReplace** (REG_SZ, default = "sunny")
+
+- **InspectionLocalPort** (REG_DWORD, default = 8888)
+
+- **InspectionRemotePort** (REG_DWORD, default = 0)
+
+ > [!NOTE]
+ > For this sample, a local or remote port is mandatory. Both cannot be zero.
+
+- **InspectioDirection** (REG_DWORD, default = 2) Possible values : 2 (inbound + outbound), 0 (FWP_DIRECTION_OUTBOUND), 1 (FWP_DIRECTION_INBOUND)
+
+- **MultipleCallouts** (REG_DWORD, default = true/1) Controls registration of multiple callouts. Set 0 for false, other for TRUE
+
+- **BusyThreshold** (REG_DWORD, default = 16KB) BusyThreshold value is in KBs (e.g. a value of 5 means 5KB)
-Start the stmedit service
--------------------------
+## Start the stmedit service
On the target computer, open a Command Prompt window as Administrator, and enter **net start stmedit**. (To stop the driver, enter **net stop stmedit**.)
-Remarks
--------
+## Remarks
-For more information on creating a Windows Filtering Platform Callout Driver, see [Windows Filtering Platform Callout Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff571068).
+For more information on creating a Windows Filtering Platform Callout Driver, see [Windows Filtering Platform Callout Drivers](https://docs.microsoft.com/windows-hardware/drivers/network/windows-filtering-platform-callout-drivers2).
diff --git a/network/wlan/WDI/HAL/phydm/phydm.h b/network/wlan/WDI/HAL/phydm/phydm.h
index 21651973..492a4f2a 100644
--- a/network/wlan/WDI/HAL/phydm/phydm.h
+++ b/network/wlan/WDI/HAL/phydm/phydm.h
@@ -620,7 +620,7 @@ typedef struct DM_Out_Source_Dynamic_Mechanism_Structure
//-----------HOOK BEFORE REG INIT-----------//
// ODM Platform info AP/ADSL/CE/MP = 1/2/3/4
u1Byte SupportPlatform;
- // ODM Support Ability DIG/RATR/TX_PWR_TRACK/ �K�K = 1/2/3/�K
+ // ODM Support Ability DIG/RATR/TX_PWR_TRACK/ ¡K¡K = 1/2/3/¡K
u4Byte SupportAbility;
// ODM PCIE/USB/SDIO = 1/2/3
u1Byte SupportInterface;
@@ -695,7 +695,7 @@ typedef struct DM_Out_Source_Dynamic_Mechanism_Structure
BOOLEAN *pbGetValueFromOtherMac;
PADAPTER *pBuddyAdapter;
- BOOLEAN *pbMasterOfDMSP; //MAC0: master, MAC1: slave
+ BOOLEAN *pbMasterOfDMSP; //MAC0: master, MAC1: subordinate
// Common info for Status
BOOLEAN *pbScanInProcess;
BOOLEAN *pbPowerSaving;
diff --git a/network/wlan/WDI/PLATFORM/NDIS6/SDIO/N6SdioPlatformWindows.c b/network/wlan/WDI/PLATFORM/NDIS6/SDIO/N6SdioPlatformWindows.c
index d48ee104..86a16e03 100644
--- a/network/wlan/WDI/PLATFORM/NDIS6/SDIO/N6SdioPlatformWindows.c
+++ b/network/wlan/WDI/PLATFORM/NDIS6/SDIO/N6SdioPlatformWindows.c
@@ -1006,17 +1006,15 @@ PlatformSdioGetProperty(
PSDBUS_REQUEST_PACKET psdrp = NULL;
NTSTATUS status;
- psdrp = (PSDBUS_REQUEST_PACKET)ExAllocatePoolWithTag(NonPagedPool, sizeof(SDBUS_REQUEST_PACKET), '3278');
+ psdrp = (PSDBUS_REQUEST_PACKET)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(SDBUS_REQUEST_PACKET), '3278');
if(!psdrp)
return STATUS_INSUFFICIENT_RESOURCES;
- RtlZeroMemory(psdrp, sizeof(SDBUS_REQUEST_PACKET));
-
- psdrp->RequestFunction = SDRF_GET_PROPERTY;
- psdrp->Parameters.GetSetProperty.Property = Property;
- psdrp->Parameters.GetSetProperty.Buffer = Buffer;
- psdrp->Parameters.GetSetProperty.Length = Length;
+ psdrp->RequestFunction = SDRF_GET_PROPERTY;
+ psdrp->Parameters.GetSetProperty.Property = Property;
+ psdrp->Parameters.GetSetProperty.Buffer = Buffer;
+ psdrp->Parameters.GetSetProperty.Length = Length;
NdisAcquireSpinLock( &(pDevice->IrpSpinLock) );
RT_SDIO_INC_CMD_REF(pDevice);
@@ -1062,17 +1060,15 @@ PlatformSdioSetProperty(
PSDBUS_REQUEST_PACKET psdrp = NULL;
NTSTATUS status;
- psdrp = (PSDBUS_REQUEST_PACKET)ExAllocatePoolWithTag(NonPagedPool, sizeof(SDBUS_REQUEST_PACKET), '3278');
+ psdrp = (PSDBUS_REQUEST_PACKET)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(SDBUS_REQUEST_PACKET), '3278');
if(!psdrp)
return STATUS_INSUFFICIENT_RESOURCES;
- RtlZeroMemory(psdrp, sizeof(SDBUS_REQUEST_PACKET));
-
- psdrp->RequestFunction = SDRF_SET_PROPERTY;
- psdrp->Parameters.GetSetProperty.Property = Property;
- psdrp->Parameters.GetSetProperty.Buffer = Buffer;
- psdrp->Parameters.GetSetProperty.Length = Length;
+ psdrp->RequestFunction = SDRF_SET_PROPERTY;
+ psdrp->Parameters.GetSetProperty.Property = Property;
+ psdrp->Parameters.GetSetProperty.Buffer = Buffer;
+ psdrp->Parameters.GetSetProperty.Length = Length;
NdisAcquireSpinLock( &(pDevice->IrpSpinLock) );
RT_SDIO_INC_CMD_REF(pDevice);
@@ -1409,14 +1405,12 @@ PlatformSdioCmd53ReadWriteMDL(
//
// Now allocate a request packet for the arguments of the command.
//
- psdrp = ExAllocatePoolWithTag(NonPagedPool, sizeof(SDBUS_REQUEST_PACKET), '3278');
+ psdrp = ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(SDBUS_REQUEST_PACKET), '3278');
if(!psdrp)
{
RT_TRACE(COMP_IO, DBG_SERIOUS, ("PlatformSdioCmd53ReadWriteMDL(): Allocate sdrp fail!!\n"));
return rtstatus;
}
-
- RtlZeroMemory(psdrp, sizeof(SDBUS_REQUEST_PACKET));
psdrp->RequestFunction = SDRF_DEVICE_COMMAND;
psdrp->Parameters.DeviceCommand.Mdl = pmdl;
@@ -2985,7 +2979,7 @@ PrepareSdioAWBs(
//
// Allocate SD Request Packet
//
- device->pAsynIoWriteSdrp = (PSDBUS_REQUEST_PACKET)ExAllocatePoolWithTag(NonPagedPool, sizeof(SDBUS_REQUEST_PACKET), '3278');
+ device->pAsynIoWriteSdrp = (PSDBUS_REQUEST_PACKET)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(SDBUS_REQUEST_PACKET), '3278');
if(device->pAsynIoWriteSdrp == NULL)
goto Error;
diff --git a/network/wlan/WDI/PLATFORM/NDIS6/SDIO/N6Sdio_main.c b/network/wlan/WDI/PLATFORM/NDIS6/SDIO/N6Sdio_main.c
index fb9160a4..1165eed1 100644
--- a/network/wlan/WDI/PLATFORM/NDIS6/SDIO/N6Sdio_main.c
+++ b/network/wlan/WDI/PLATFORM/NDIS6/SDIO/N6Sdio_main.c
@@ -1489,10 +1489,9 @@ N6SdioInitTxQueue(
pDevice->RtNumTxQueue = SDIO_MAX_TX_QUEUE; // TX_HIQ, TX_MIQ and TX_LOQ
// Initialize the contexts in Tx Queue.
- pDevice->RtTxQueue =
- (PRT_SDIO_TX_QUEUE)ExAllocatePoolWithTag(NonPagedPool, SDIO_MAX_TX_QUEUE*sizeof(RT_SDIO_TX_QUEUE), '3278' );
- PlatformZeroMemory(pDevice->RtTxQueue, SDIO_MAX_TX_QUEUE*sizeof(RT_SDIO_TX_QUEUE));
-
+ pDevice->RtTxQueue =
+ (PRT_SDIO_TX_QUEUE)ExAllocatePool2(POOL_FLAG_NON_PAGED, SDIO_MAX_TX_QUEUE*sizeof(RT_SDIO_TX_QUEUE), '3278' );
+
if (pDevice->RtTxQueue != NULL)
{
diff --git a/network/wlan/WDI/PLATFORM/NDIS6/SDIO/sdio.vcxproj b/network/wlan/WDI/PLATFORM/NDIS6/SDIO/sdio.vcxproj
index af48c0a4..a8432de0 100644
--- a/network/wlan/WDI/PLATFORM/NDIS6/SDIO/sdio.vcxproj
+++ b/network/wlan/WDI/PLATFORM/NDIS6/SDIO/sdio.vcxproj
@@ -336,13 +336,9 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Win10 Debug|Win32'">
<Link>
<AdditionalDependencies>$(SolutionDir)COMMON\$(Configuration)\common.lib;$(SolutionDir)PLATFORM\NdisComm\$(Configuration)\NdisComm.lib;$(SolutionDir)\LIB\x86\hal.lib;$(SolutionDir)\LIB\x86\rtklibcom.lib;$(WindowsSDK_LibraryPath_x86)km\x86\ndis.lib;$(WindowsSDK_LibraryPath_x86)km\x86\ntoskrnl.lib;$(WindowsSDK_LibraryPath_x86)km\x86\sdbus.lib;$(WindowsSDK_LibraryPath_x86)km\x86\wlan\1.0\TlvGeneratorParser.lib;</AdditionalDependencies>
- <Driver>
- </Driver>
- <TreatLinkerWarningAsErrors>
- </TreatLinkerWarningAsErrors>
+ <!-- warning LNK4099: PDB 'rtklibcom.pdb' was not found with 'rtklibcom.lib(multichannels.obj)' -->
+ <AdditionalOptions>$(AdditionalOptions) /IGNORE:4099</AdditionalOptions>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
- <LinkStatus>
- </LinkStatus>
</Link>
<ClCompile>
<PreprocessorDefinitions>_X86_;DBG;NDIS60_MINIPORT;USE_KLOCKS=1;BINARY_COMPATIBLE=0;NDIS650_MINIPORT=1;NDIS640_MINIPORT=1;NDIS630_MINIPORT=1;NDIS620_MINIPORT=1;NDIS61_MINIPORT=1;NDIS_MINIPORT_DRIVER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -425,6 +421,8 @@
<DebugInformationFormat>None</DebugInformationFormat>
</ClCompile>
<Link>
+ <!-- warning LNK4099: PDB 'rtklibcom.pdb' was not found with 'rtklibcom.lib(multichannels.obj)' -->
+ <AdditionalOptions>$(AdditionalOptions) /IGNORE:4099</AdditionalOptions>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalDependencies>$(SolutionDir)COMMON\$(Configuration)\common.lib;$(SolutionDir)PLATFORM\NdisComm\$(Configuration)\NdisComm.lib;$(SolutionDir)\LIB\x86\hal.lib;$(SolutionDir)\LIB\x86\rtklibcom.lib;$(WindowsSDK_LibraryPath_x86)km\x86\ndis.lib;$(WindowsSDK_LibraryPath_x86)km\x86\ntoskrnl.lib;$(WindowsSDK_LibraryPath_x86)km\x86\sdbus.lib;$(WindowsSDK_LibraryPath_x86)km\x86\wlan\1.0\TlvGeneratorParser.lib;</AdditionalDependencies>
<GenerateDebugInformation>
@@ -626,6 +624,8 @@
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <!-- warning LNK4099: PDB 'rtklibcom.pdb' was not found with 'rtklibcom.lib(multichannels.obj)' -->
+ <AdditionalOptions>$(AdditionalOptions) /IGNORE:4099</AdditionalOptions>
<AdditionalDependencies>$(SolutionDir)COMMON\$(Configuration)\$(Platform)\common.lib;$(SolutionDir)PLATFORM\NdisComm\$(Configuration)\$(Platform)\NdisComm.lib;$(SolutionDir)\LIB\x64\hal.lib;$(SolutionDir)\LIB\x64\rtklibcom.lib;$(WindowsSDK_LibraryPath_x64)km\x64\ndis.lib;$(WindowsSDK_LibraryPath_x64)km\x64\ntoskrnl.lib;$(WindowsSDK_LibraryPath_x64)km\x64\sdbus.lib;$(WindowsSDK_LibraryPath_x64)km\x64\wlan\1.0\TlvGeneratorParser.lib;</AdditionalDependencies>
</Link>
<ProjectReference>
diff --git a/network/wlan/WDI/PLATFORM/NDIS6/WDI_Cmds.c b/network/wlan/WDI/PLATFORM/NDIS6/WDI_Cmds.c
index ec5cddd6..943038dd 100644
--- a/network/wlan/WDI/PLATFORM/NDIS6/WDI_Cmds.c
+++ b/network/wlan/WDI/PLATFORM/NDIS6/WDI_Cmds.c
@@ -3191,24 +3191,24 @@ Wdi_Set_Add_Pm_Protocol_Offload(
//2 DOT11 RSN REKey Offload
- if(Params->DOT11RSNREKeyOffload.ProtocolOffloadId)
+ if(Params->DOT11RSNREKeyOffload.RsnKeyInfo.ProtocolOffloadId)
{
RT_TRACE(COMP_OID_SET, DBG_LOUD, ("ProtocolOffloadId = %d\n",
- Params->DOT11RSNREKeyOffload.ProtocolOffloadId));
+ Params->DOT11RSNREKeyOffload.RsnKeyInfo.ProtocolOffloadId));
pMgntInfo->PowerSaveControl.PMProtocolOffloadIDs[eGTKOffloadIdx]
- = Params->DOT11RSNREKeyOffload.ProtocolOffloadId;
+ = Params->DOT11RSNREKeyOffload.RsnKeyInfo.ProtocolOffloadId;
//Copy kck, kek
PlatformMoveMemory(&(pMgntInfo->PMDot11RSNRekeyPara.KCK),
- Params->DOT11RSNREKeyOffload.KCK_CONTENT, 32);
+ &Params->DOT11RSNREKeyOffload.RsnKeyInfo.KCK_CONTENT, 32);
RT_PRINT_DATA( COMP_OID_SET, DBG_LOUD, ("KCK_CONTENT:\n"),
pMgntInfo->PMDot11RSNRekeyPara.KCK, 16);
RT_PRINT_DATA( COMP_OID_SET, DBG_LOUD, ("KEK_CONTENT:\n"),
pMgntInfo->PMDot11RSNRekeyPara.KEK, 16);
- pMgntInfo->PMDot11RSNRekeyPara.KeyReplayCounter = Params->DOT11RSNREKeyOffload.ReplayCounter;
+ pMgntInfo->PMDot11RSNRekeyPara.KeyReplayCounter = Params->DOT11RSNREKeyOffload.RsnKeyInfo.ReplayCounter;
if(pPSC->RegGTKOffloadEnable)
pPSC->GTKOffloadEnable = TRUE;
diff --git a/network/wlan/WDI/README.md b/network/wlan/WDI/README.md
index 686d8ca9..4e56f305 100644
--- a/network/wlan/WDI/README.md
+++ b/network/wlan/WDI/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: WDI samples
- platform: KMDF
- language: cpp
- category: Network
- description: WDI samples
- samplefwlink: https://go.microsoft.com/fwlink/p/?linkid=869056
---->
-
# WDI samples
This sample demonstrates use of the WLAN WDI.
diff --git a/network/wlan/ihvsampleui/README.md b/network/wlan/ihvsampleui/README.md
index 04da4172..b0fb161b 100644
--- a/network/wlan/ihvsampleui/README.md
+++ b/network/wlan/ihvsampleui/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: IHV Sample UI
- platform: Application
- language: cpp
- category: Network
- description: IHV Sample UI
- samplefwlink: https://go.microsoft.com/fwlink/p/?linkid=869057
---->
-
# IHV Sample UI
This sample demonstrates the WLAN IHV UI.
diff --git a/network/wsk/echosrv/README.md b/network/wsk/echosrv/README.md
index fd252beb..a7040f45 100644
--- a/network/wsk/echosrv/README.md
+++ b/network/wsk/echosrv/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: WSK TCP Echo Server
- platform: WDM
- language: cpp
- category: Network
- description: A minimal sample driver to demonstrate the usage of the Winsock Kernel (WSK) programming interface.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617935
---->
-
# WSK TCP Echo Server
This sample driver is a minimal driver meant to demonstrate the usage of the Winsock Kernel (WSK) programming interface.
@@ -24,51 +16,52 @@ The sample implements a simple kernel-mode application by using the Winsock Kern
This sample is not intended for use in a production environment.
-
-WPP SOFTWARE TRACING
---------------------
+## WPP SOFTWARE TRACING
This sample driver uses WPP Software Tracing in order to log its actions. You can find detailed information on WPP Software Tracing in the WDK documentation. Here is a quick overview of one way to collect trace logs from the sample driver by using the tracing tools that are available in the \\tools\\tracing directory in the WDK. All code for this sample is located in \\network\\WSK\\echosrv directory.
-1. In a Command Prompt window, copy Echosrv.ctl and Echosrv.pdb into a directory and change to that directory (cd).
-2. Start software tracing for the sample driver by typing the following command:
+1. In a Command Prompt window, copy Echosrv.ctl and Echosrv.pdb into a directory and change to that directory (cd).
+
+1. Start software tracing for the sample driver by typing the following command:
- **tracelog -start echosrvtrace -guid echosrv.ctl -f logfile.etl -flags 0x3**
+ `tracelog -start echosrvtrace -guid echosrv.ctl -f logfile.etl -flags 0x3`
The value that is provided for the -flags option determines which events will be logged by the sample driver. The sample currently has two event types denoted by the TRCERROR and TRCINFO macros where TRCERROR is 0x1 and TRCINFO is 0x2. Thus, a flag value of 0x3 (0x1 combined in a bitwise OR with 0x2) in the previous tracelog command tells the sample driver to log both TRCERROR and TRCINFO events.
-3. In order to stop tracing, type the following command:
+1. In order to stop tracing, type the following command:
tracelog -stop echosrvtrace
-4. Convert the trace logs in Logfile.etl into a human-readable format by typing the following command:
+1. Convert the trace logs in Logfile.etl into a human-readable format by typing the following command:
- **tracefmt -o logfile.txt -f logfile.etl -r . -i \\***full-path***\\ echosrv.sys**
+ `tracefmt -o logfile.txt -f logfile.etl -r . -i \full-path\ echosrv.sys`
-5. Open Logfile.txt to view the trace logs.
+ where \\*full-path*\\ is the directory that contains the Echosrv.sys file.
+
+1. Open Logfile.txt to view the trace logs.
Be aware that tracing for the sample driver can be started at any time before the driver is started or while the driver is already running.
-To run the sample
------------------
+## To run the sample
Install and run this sample driver by using the following steps:
-1. Copy the Echosrv.sys file to a directory on the test machine.
-2. In a Command Prompt window, type the following command:
+1. Copy the Echosrv.sys file to a directory on the test machine.
+
+1. In a Command Prompt window, type the following command:
- **sc create echosrv type= kernel binpath= \\***full-path***\\ echosrv.sys**
+ `sc create echosrv type= kernel binpath= \full-path\ echosrv.sys`
where \\*full-path*\\ is the directory that contains the Echosrv.sys file.
-3. To start the driver, type:
+1. To start the driver, type:
- **sc start echosrv**
+ `sc start echosrv`
-4. To stop the driver, type:
+1. To stop the driver, type:
- **sc stop echosrv**
+ `sc stop echosrv`
After the driver is installed and started, it will listen for incoming TCP connection requests on port 40007 over both IPv4 and IPv6 protocols until the driver is stopped. On each connection, the driver will echo all the received data back to the peer until the connection is closed by the peer.
-For more information on the usage of the Winsock Kernel (WSK) programming interface, see [Winsock Kernel](http://msdn.microsoft.com/en-us/library/windows/hardware/ff571084).
+For more information on the usage of the Winsock Kernel (WSK) programming interface, see [Winsock Kernel](https://docs.microsoft.com/windows-hardware/drivers/network/winsock-kernel).
diff --git a/nfc/NfcCxSample/README.md b/nfc/NfcCxSample/README.md
index c423c365..0d9bd185 100644
--- a/nfc/NfcCxSample/README.md
+++ b/nfc/NfcCxSample/README.md
@@ -5,6 +5,7 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
# NFC CX client driver sample
@@ -27,7 +28,7 @@ This sample builds a Universal Windows Driver. It uses only APIs and DDIs that a
### WDK
-- [NfcCx.h](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/nfccx/) - The NFC CX's client driver API. (This file is included in the WDK.)
+- [NfcCx.h](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/nfccx/) - The NFC CX's client driver API. This file is included in the WDK.
### Project
diff --git a/nfp/net/README.md b/nfp/net/README.md
index 5f9c670b..0df76029 100644
--- a/nfp/net/README.md
+++ b/nfp/net/README.md
@@ -1,21 +1,26 @@
-<!---
- name: Near-Field Proximity Sample Driver (UMDF Version 1)
- platform: UMDF1
- language: cpp
- category: Proximity
- description: Demonstrates how to use UMDF version 1 to write a near-field proximity driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620200
---->
+---
+page_type: sample
+description: "Demonstrates how to use UMDF version 1 to write a near-field proximity driver."
+languages:
+- cpp
+products:
+- windows
+- windows-wdk
+---
+# Near-Field Proximity Sample Driver (UMDF Version 1)
-Near-Field Proximity Sample Driver (UMDF Version 1)
-===================================================
+> [!WARNING]
+> UMDF 2 is the latest version of UMDF and supersedes UMDF 1. All new UMDF drivers should be written using UMDF 2. No new features are being added to UMDF 1 and there is limited support for UMDF 1 on newer versions of Windows 10. Universal Windows drivers must use UMDF 2.
+>
+> For more info, see [Getting Started with UMDF](https://docs.microsoft.com/windows-hardware/drivers/wdf/getting-started-with-umdf-version-2).
This sample demonstrates how to use User-Mode Driver Framework (UMDF) version 1 to write a near-field proximity driver.
Typically, a near-field proximity driver would use near-field technologies such as Near Field Communication (NFC), TransferJet, or Bump. However, this sample uses a TCP/IPv6 network connection and a static configuration between two machines to simulate near-field interaction.
-Related technologies
---------------------
-[User-Mode Driver Framework](http://msdn.microsoft.com/en-us/library/windows/hardware/ff560456)
+## See also
+[Getting Started with UMDF](https://docs.microsoft.com/windows-hardware/drivers/wdf/getting-started-with-umdf-version-2)
+
+[UMDF 1.x Design Guide](https://docs.microsoft.com/windows-hardware/drivers/wdf/user-mode-driver-framework-design-guide)
diff --git a/nfp/net/inc/README.md b/nfp/net/inc/README.md
deleted file mode 100644
index 57c8e274..00000000
--- a/nfp/net/inc/README.md
+++ /dev/null
@@ -1,27 +0,0 @@
----
-page_type: sample
-description: "Demonstrates how to use UMDF version 1 to write a near-field proximity driver."
-languages:
-- cpp
-products:
-- windows
----
-
-<!---
- name: Near-Field Proximity Sample Driver (UMDF Version 1)
- platform: UMDF1
- language: cpp
- category: Proximity
- description: Demonstrates how to use UMDF version 1 to write a near-field proximity driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620200
---->
-
-# Near-Field Proximity Sample Driver (UMDF Version 1)
-
-This sample demonstrates how to use User-Mode Driver Framework (UMDF) version 1 to write a near-field proximity driver.
-
-Typically, a near-field proximity driver would use near-field technologies such as Near Field Communication (NFC), TransferJet, or Bump. However, this sample uses a TCP/IPv6 network connection and a static configuration between two machines to simulate near-field interaction.
-
-## Related technologies
-
-[User-Mode Driver Framework](http://msdn.microsoft.com/en-us/library/windows/hardware/ff560456)
diff --git a/pofx/PEP/README.md b/pofx/PEP/README.md
index e98a2836..9af1699d 100644
--- a/pofx/PEP/README.md
+++ b/pofx/PEP/README.md
@@ -5,23 +5,17 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Power Engine Plugin (PEP) ACPI Sample
- platform: KMDF
- language: cpp
- category: ACPI Power
- description: Demonstrates an interface which allows PEP to implement ACPI runtime methods natively via a driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620311
---->
-
# PEP ACPI Sample
The Power Engine Plugin (PEP) provides interfaces for platform power management including device power management (DPM), processor power management (PPM), and, starting with Windows 10, ACPI runtime methods. This sample documents the latter: an interface which allows a PEP to implement ACPI runtime methods natively via a Windows driver rather than firmware (AML). A PEP using the ACPI interface is often called a Platform Extension. Note that this interface can be used independently or in conjunction with the DPM and/or PPM interfaces as appropriate.
Use the PEP ACPI interface if:
-* You want to write peripheral (off-SoC) device power management in C rather than in ACPI Source Language (ASL).
-* You need to override an ACPI method which exists in a platform's DSDT or SSDT firmware tables.
-* Shipping, maintaining, and updating a driver binary suits your platform better than firmware updates (note that you will still need FADT, MADT, DBG2, and so on in firmware - this interface is only for runtime methods).
+- You want to write peripheral (off-SoC) device power management in C rather than in ACPI Source Language (ASL).
+
+- You need to override an ACPI method which exists in a platform's DSDT or SSDT firmware tables.
+
+- Shipping, maintaining, and updating a driver binary suits your platform better than firmware updates (note that you will still need FADT, MADT, DBG2, and so on in firmware, this interface is only for runtime methods).
diff --git a/pofx/UMDF2/Driver/SingleComp/driver.c b/pofx/UMDF2/Driver/SingleComp/driver.c
index 597c742d..569a1e6a 100644
--- a/pofx/UMDF2/Driver/SingleComp/driver.c
+++ b/pofx/UMDF2/Driver/SingleComp/driver.c
@@ -70,7 +70,7 @@ Return Value:
Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Entry of driver");
//
- // Initiialize driver config to control the attributes that are global to
+ // Initialize driver config to control the attributes that are global to
// the driver. Note that framework by default provides a driver unload
// routine. If DriverEntry creates any resources that require clean-up in
// driver unload, you can manually override the default by supplying a
diff --git a/pofx/UMDF2/README.md b/pofx/UMDF2/README.md
index f775ad53..a8958cc4 100644
--- a/pofx/UMDF2/README.md
+++ b/pofx/UMDF2/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Power Framework (PoFx) Sample (UMDF Version 2)
- platform: UMDF2
- language: cpp
- category: Power
- description: Demonstrates how a UMDF version 2 driver can implement F-state-based power management.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617936
---->
-
# Power Framework (PoFx) Sample (UMDF Version 2)
This solution demonstrates how a User-Mode Driver Framework (UMDF) version 2 driver can implement F-state-based power management. The SingleComp project demonstrates how a UMDF version 2 driver can implement F-state-based power management for a device that has only a single component.
@@ -24,14 +16,13 @@ This solution demonstrates how a User-Mode Driver Framework (UMDF) version 2 dri
This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP.
-Related technologies
---------------------
-For related information, see the [KMDF Power Framework (PoFx) Sample](http://go.microsoft.com/fwlink/p/?LinkId=617937).
+## Related technologies
+
+[KMDF Power Framework (PoFx) Sample](https://docs.microsoft.com/samples/microsoft/windows-driver-samples/kmdf-power-framework-pofx-sample/).
-[User-Mode Driver Framework](http://msdn.microsoft.com/en-us/library/windows/hardware/ff560456)
+[User-Mode Driver Framework](https://docs.microsoft.com/windows-hardware/drivers/wdf/getting-started-with-umdf-version-2)
-Run the sample
---------------
+## Run the sample
The computer where you install the driver is called the *target computer* or the *test computer*. Typically this is a separate computer from where you develop and build the driver package. The computer where you develop and build the driver is called the *host computer*.
@@ -39,20 +30,27 @@ The process of moving the driver package to the target computer and installing t
### Automatic deployment (root enumerated)
-Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/).
+Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1).
+
+After you have provisioned the target computer, continue with these steps:
+
+1. On the host computer, in Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
-1. On the host computer, in Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
-2. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Hardware ID Driver Update**, and enter **root\\SingleComponentSingleState** for the hardware ID. Click **OK**.
-3. On the **Build** menu, choose **Build Solution**.
+1. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Hardware ID Driver Update**, and enter **root\\SingleComponentSingleState** for the hardware ID. Click **OK**.
+
+1. On the **Build** menu, choose **Build Solution**.
### Manual deployment (root enumerated)
-Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
+Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](https://docs.microsoft.com/windows-hardware/drivers/devtest/devcon) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
+
+After you have prepared the target computer for manual deployment, continue with these steps:
+
+1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\PoFx).
-1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\PoFx).
-2. On the target computer, open a Command Prompt window as Administrator. Navigate to your driver package folder, and enter the following command:
+1. On the target computer, open a Command Prompt window as Administrator. Navigate to your driver package folder, and enter the following command:
- **devcon install SingleComponentSingleStateUm.inf root\\SingleComponentSingleState**
+ `devcon install SingleComponentSingleStateUm.inf root\\SingleComponentSingleState`
### View the root enumerated driver in Device Manager
@@ -60,11 +58,10 @@ On the target computer, in a Command Prompt window, enter **devmgmt** to open De
In Device Manager, on the **View** menu, choose **Devices by connection**. Locate **UMDF 2.0 Single Component Single State Device** as a child of the root node of the device tree.
-Build the sample using MSBuild
-------------------------------
+## Build the sample using MSBuild
As an alternative to building the driver sample in Visual Studio, you can build it in a Visual Studio Command Prompt window. In Visual Studio, on the **Tools** menu, choose **Visual Studio Command Prompt**. In the Visual Studio Command Prompt window, navigate to the folder that has the solution file, PoFx.sln. Use the MSBuild command to build the solution. Here is an example:
-**msbuild /p:configuration="Release" /p:platform="Win32" PoFx.sln**
+`msbuild /p:configuration="Release" /p:platform="Win32" PoFx.sln`
-For more information about using MSBuild to build a driver package, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644).
+For more information about using [MSBuild](https://docs.microsoft.com/visualstudio/msbuild/msbuild?view=vs-2019) to build a driver package, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver).
diff --git a/pofx/WDF/Driver/MultiComp/WdfMultiComp.mht b/pofx/WDF/Driver/MultiComp/WdfMultiComp.mht
deleted file mode 100644
index f6dc1775..00000000
--- a/pofx/WDF/Driver/MultiComp/WdfMultiComp.mht
+++ /dev/null
@@ -1,2807 +0,0 @@
-MIME-Version: 1.0
-Content-Type: multipart/related; boundary="----=_NextPart_01CC4DF5.1FA44F90"
-
-This document is a Single File Web Page, also known as a Web Archive file. If you are seeing this message, your browser or editor doesn't support Web Archive files. Please download a browser that supports Web Archive, such as Windows� Internet Explorer�.
-
-------=_NextPart_01CC4DF5.1FA44F90
-Content-Location: file:///C:/EEB34A10/WdfMultiComp.htm
-Content-Transfer-Encoding: quoted-printable
-Content-Type: text/html; charset="us-ascii"
-
-<html xmlns:v=3D"urn:schemas-microsoft-com:vml"
-xmlns:o=3D"urn:schemas-microsoft-com:office:office"
-xmlns:w=3D"urn:schemas-microsoft-com:office:word"
-xmlns:m=3D"http://schemas.microsoft.com/office/2004/12/omml"
-xmlns=3D"http://www.w3.org/TR/REC-html40">
-
-<head>
-<meta http-equiv=3DContent-Type content=3D"text/html; charset=3Dus-ascii">
-<meta name=3DProgId content=3DWord.Document>
-<meta name=3DGenerator content=3D"Microsoft Word 14">
-<meta name=3DOriginator content=3D"Microsoft Word 14">
-<link rel=3DFile-List href=3D"WdfMultiComp_files/filelist.xml">
-<link rel=3DEdit-Time-Data href=3D"WdfMultiComp_files/editdata.mso">
-<link rel=3DOLE-Object-Data href=3D"WdfMultiComp_files/oledata.mso">
-<!--[if !mso]>
-<style>
-v\:* {behavior:url(#default#VML);}
-o\:* {behavior:url(#default#VML);}
-w\:* {behavior:url(#default#VML);}
-.shape {behavior:url(#default#VML);}
-</style>
-<![endif]--><!--[if gte mso 9]><xml>
- <o:DocumentProperties>
- <o:Author>Abhishek Ram</o:Author>
- <o:Template>Normal</o:Template>
- <o:LastAuthor>Abhishek Ram</o:LastAuthor>
- <o:Revision>11</o:Revision>
- <o:TotalTime>589</o:TotalTime>
- <o:Created>2011-06-25T00:43:00Z</o:Created>
- <o:LastSaved>2011-07-29T20:40:00Z</o:LastSaved>
- <o:Pages>1</o:Pages>
- <o:Words>922</o:Words>
- <o:Characters>5261</o:Characters>
- <o:Company>Microsoft Corporation</o:Company>
- <o:Lines>43</o:Lines>
- <o:Paragraphs>12</o:Paragraphs>
- <o:CharactersWithSpaces>6171</o:CharactersWithSpaces>
- <o:Version>14.00</o:Version>
- </o:DocumentProperties>
-</xml><![endif]-->
-<link rel=3DthemeData href=3D"WdfMultiComp_files/themedata.thmx">
-<link rel=3DcolorSchemeMapping href=3D"WdfMultiComp_files/colorschememappin=
-g.xml">
-<!--[if gte mso 9]><xml>
- <w:WordDocument>
- <w:Zoom>125</w:Zoom>
- <w:SpellingState>Clean</w:SpellingState>
- <w:GrammarState>Clean</w:GrammarState>
- <w:TrackMoves>false</w:TrackMoves>
- <w:TrackFormatting/>
- <w:PunctuationKerning/>
- <w:ValidateAgainstSchemas/>
- <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
- <w:IgnoreMixedContent>false</w:IgnoreMixedContent>
- <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
- <w:DoNotPromoteQF/>
- <w:LidThemeOther>EN-US</w:LidThemeOther>
- <w:LidThemeAsian>X-NONE</w:LidThemeAsian>
- <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
- <w:Compatibility>
- <w:BreakWrappedTables/>
- <w:SnapToGridInCell/>
- <w:WrapTextWithPunct/>
- <w:UseAsianBreakRules/>
- <w:DontGrowAutofit/>
- <w:SplitPgBreakAndParaMark/>
- <w:EnableOpenTypeKerning/>
- <w:DontFlipMirrorIndents/>
- <w:OverrideTableStyleHps/>
- </w:Compatibility>
- <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
- <m:mathPr>
- <m:mathFont m:val=3D"Cambria Math"/>
- <m:brkBin m:val=3D"before"/>
- <m:brkBinSub m:val=3D"&#45;-"/>
- <m:smallFrac m:val=3D"off"/>
- <m:dispDef/>
- <m:lMargin m:val=3D"0"/>
- <m:rMargin m:val=3D"0"/>
- <m:defJc m:val=3D"centerGroup"/>
- <m:wrapIndent m:val=3D"1440"/>
- <m:intLim m:val=3D"subSup"/>
- <m:naryLim m:val=3D"undOvr"/>
- </m:mathPr></w:WordDocument>
-</xml><![endif]--><!--[if gte mso 9]><xml>
- <w:LatentStyles DefLockedState=3D"false" DefUnhideWhenUsed=3D"true"
- DefSemiHidden=3D"true" DefQFormat=3D"false" DefPriority=3D"99"
- LatentStyleCount=3D"267">
- <w:LsdException Locked=3D"false" Priority=3D"0" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Normal"/>
- <w:LsdException Locked=3D"false" Priority=3D"9" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"heading 1"/>
- <w:LsdException Locked=3D"false" Priority=3D"9" QFormat=3D"true" Name=3D"=
-heading 2"/>
- <w:LsdException Locked=3D"false" Priority=3D"9" QFormat=3D"true" Name=3D"=
-heading 3"/>
- <w:LsdException Locked=3D"false" Priority=3D"9" QFormat=3D"true" Name=3D"=
-heading 4"/>
- <w:LsdException Locked=3D"false" Priority=3D"9" QFormat=3D"true" Name=3D"=
-heading 5"/>
- <w:LsdException Locked=3D"false" Priority=3D"9" QFormat=3D"true" Name=3D"=
-heading 6"/>
- <w:LsdException Locked=3D"false" Priority=3D"9" QFormat=3D"true" Name=3D"=
-heading 7"/>
- <w:LsdException Locked=3D"false" Priority=3D"9" QFormat=3D"true" Name=3D"=
-heading 8"/>
- <w:LsdException Locked=3D"false" Priority=3D"9" QFormat=3D"true" Name=3D"=
-heading 9"/>
- <w:LsdException Locked=3D"false" Priority=3D"39" Name=3D"toc 1"/>
- <w:LsdException Locked=3D"false" Priority=3D"39" Name=3D"toc 2"/>
- <w:LsdException Locked=3D"false" Priority=3D"39" Name=3D"toc 3"/>
- <w:LsdException Locked=3D"false" Priority=3D"39" Name=3D"toc 4"/>
- <w:LsdException Locked=3D"false" Priority=3D"39" Name=3D"toc 5"/>
- <w:LsdException Locked=3D"false" Priority=3D"39" Name=3D"toc 6"/>
- <w:LsdException Locked=3D"false" Priority=3D"39" Name=3D"toc 7"/>
- <w:LsdException Locked=3D"false" Priority=3D"39" Name=3D"toc 8"/>
- <w:LsdException Locked=3D"false" Priority=3D"39" Name=3D"toc 9"/>
- <w:LsdException Locked=3D"false" Priority=3D"35" QFormat=3D"true" Name=3D=
-"caption"/>
- <w:LsdException Locked=3D"false" Priority=3D"10" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Title"/>
- <w:LsdException Locked=3D"false" Priority=3D"1" Name=3D"Default Paragraph=
- Font"/>
- <w:LsdException Locked=3D"false" Priority=3D"11" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Subtitle"/>
- <w:LsdException Locked=3D"false" Priority=3D"22" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Strong"/>
- <w:LsdException Locked=3D"false" Priority=3D"20" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Emphasis"/>
- <w:LsdException Locked=3D"false" Priority=3D"59" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Table Grid"/>
- <w:LsdException Locked=3D"false" UnhideWhenUsed=3D"false" Name=3D"Placeho=
-lder Text"/>
- <w:LsdException Locked=3D"false" Priority=3D"1" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"No Spacing"/>
- <w:LsdException Locked=3D"false" Priority=3D"60" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light Shading"/>
- <w:LsdException Locked=3D"false" Priority=3D"61" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light List"/>
- <w:LsdException Locked=3D"false" Priority=3D"62" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light Grid"/>
- <w:LsdException Locked=3D"false" Priority=3D"63" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Shading 1"/>
- <w:LsdException Locked=3D"false" Priority=3D"64" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Shading 2"/>
- <w:LsdException Locked=3D"false" Priority=3D"65" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium List 1"/>
- <w:LsdException Locked=3D"false" Priority=3D"66" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium List 2"/>
- <w:LsdException Locked=3D"false" Priority=3D"67" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 1"/>
- <w:LsdException Locked=3D"false" Priority=3D"68" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 2"/>
- <w:LsdException Locked=3D"false" Priority=3D"69" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 3"/>
- <w:LsdException Locked=3D"false" Priority=3D"70" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Dark List"/>
- <w:LsdException Locked=3D"false" Priority=3D"71" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful Shading"/>
- <w:LsdException Locked=3D"false" Priority=3D"72" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful List"/>
- <w:LsdException Locked=3D"false" Priority=3D"73" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful Grid"/>
- <w:LsdException Locked=3D"false" Priority=3D"60" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light Shading Accent 1"/>
- <w:LsdException Locked=3D"false" Priority=3D"61" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light List Accent 1"/>
- <w:LsdException Locked=3D"false" Priority=3D"62" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light Grid Accent 1"/>
- <w:LsdException Locked=3D"false" Priority=3D"63" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Shading 1 Accent 1"/>
- <w:LsdException Locked=3D"false" Priority=3D"64" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Shading 2 Accent 1"/>
- <w:LsdException Locked=3D"false" Priority=3D"65" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium List 1 Accent 1"/>
- <w:LsdException Locked=3D"false" UnhideWhenUsed=3D"false" Name=3D"Revisio=
-n"/>
- <w:LsdException Locked=3D"false" Priority=3D"34" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"List Paragraph"/>
- <w:LsdException Locked=3D"false" Priority=3D"29" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Quote"/>
- <w:LsdException Locked=3D"false" Priority=3D"30" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Intense Quote"/>
- <w:LsdException Locked=3D"false" Priority=3D"66" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium List 2 Accent 1"/>
- <w:LsdException Locked=3D"false" Priority=3D"67" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 1 Accent 1"/>
- <w:LsdException Locked=3D"false" Priority=3D"68" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 2 Accent 1"/>
- <w:LsdException Locked=3D"false" Priority=3D"69" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 3 Accent 1"/>
- <w:LsdException Locked=3D"false" Priority=3D"70" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Dark List Accent 1"/>
- <w:LsdException Locked=3D"false" Priority=3D"71" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful Shading Accent 1"/>
- <w:LsdException Locked=3D"false" Priority=3D"72" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful List Accent 1"/>
- <w:LsdException Locked=3D"false" Priority=3D"73" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful Grid Accent 1"/>
- <w:LsdException Locked=3D"false" Priority=3D"60" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light Shading Accent 2"/>
- <w:LsdException Locked=3D"false" Priority=3D"61" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light List Accent 2"/>
- <w:LsdException Locked=3D"false" Priority=3D"62" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light Grid Accent 2"/>
- <w:LsdException Locked=3D"false" Priority=3D"63" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Shading 1 Accent 2"/>
- <w:LsdException Locked=3D"false" Priority=3D"64" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Shading 2 Accent 2"/>
- <w:LsdException Locked=3D"false" Priority=3D"65" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium List 1 Accent 2"/>
- <w:LsdException Locked=3D"false" Priority=3D"66" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium List 2 Accent 2"/>
- <w:LsdException Locked=3D"false" Priority=3D"67" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 1 Accent 2"/>
- <w:LsdException Locked=3D"false" Priority=3D"68" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 2 Accent 2"/>
- <w:LsdException Locked=3D"false" Priority=3D"69" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 3 Accent 2"/>
- <w:LsdException Locked=3D"false" Priority=3D"70" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Dark List Accent 2"/>
- <w:LsdException Locked=3D"false" Priority=3D"71" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful Shading Accent 2"/>
- <w:LsdException Locked=3D"false" Priority=3D"72" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful List Accent 2"/>
- <w:LsdException Locked=3D"false" Priority=3D"73" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful Grid Accent 2"/>
- <w:LsdException Locked=3D"false" Priority=3D"60" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light Shading Accent 3"/>
- <w:LsdException Locked=3D"false" Priority=3D"61" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light List Accent 3"/>
- <w:LsdException Locked=3D"false" Priority=3D"62" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light Grid Accent 3"/>
- <w:LsdException Locked=3D"false" Priority=3D"63" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Shading 1 Accent 3"/>
- <w:LsdException Locked=3D"false" Priority=3D"64" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Shading 2 Accent 3"/>
- <w:LsdException Locked=3D"false" Priority=3D"65" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium List 1 Accent 3"/>
- <w:LsdException Locked=3D"false" Priority=3D"66" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium List 2 Accent 3"/>
- <w:LsdException Locked=3D"false" Priority=3D"67" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 1 Accent 3"/>
- <w:LsdException Locked=3D"false" Priority=3D"68" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 2 Accent 3"/>
- <w:LsdException Locked=3D"false" Priority=3D"69" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 3 Accent 3"/>
- <w:LsdException Locked=3D"false" Priority=3D"70" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Dark List Accent 3"/>
- <w:LsdException Locked=3D"false" Priority=3D"71" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful Shading Accent 3"/>
- <w:LsdException Locked=3D"false" Priority=3D"72" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful List Accent 3"/>
- <w:LsdException Locked=3D"false" Priority=3D"73" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful Grid Accent 3"/>
- <w:LsdException Locked=3D"false" Priority=3D"60" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light Shading Accent 4"/>
- <w:LsdException Locked=3D"false" Priority=3D"61" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light List Accent 4"/>
- <w:LsdException Locked=3D"false" Priority=3D"62" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light Grid Accent 4"/>
- <w:LsdException Locked=3D"false" Priority=3D"63" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Shading 1 Accent 4"/>
- <w:LsdException Locked=3D"false" Priority=3D"64" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Shading 2 Accent 4"/>
- <w:LsdException Locked=3D"false" Priority=3D"65" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium List 1 Accent 4"/>
- <w:LsdException Locked=3D"false" Priority=3D"66" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium List 2 Accent 4"/>
- <w:LsdException Locked=3D"false" Priority=3D"67" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 1 Accent 4"/>
- <w:LsdException Locked=3D"false" Priority=3D"68" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 2 Accent 4"/>
- <w:LsdException Locked=3D"false" Priority=3D"69" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 3 Accent 4"/>
- <w:LsdException Locked=3D"false" Priority=3D"70" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Dark List Accent 4"/>
- <w:LsdException Locked=3D"false" Priority=3D"71" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful Shading Accent 4"/>
- <w:LsdException Locked=3D"false" Priority=3D"72" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful List Accent 4"/>
- <w:LsdException Locked=3D"false" Priority=3D"73" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful Grid Accent 4"/>
- <w:LsdException Locked=3D"false" Priority=3D"60" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light Shading Accent 5"/>
- <w:LsdException Locked=3D"false" Priority=3D"61" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light List Accent 5"/>
- <w:LsdException Locked=3D"false" Priority=3D"62" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light Grid Accent 5"/>
- <w:LsdException Locked=3D"false" Priority=3D"63" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Shading 1 Accent 5"/>
- <w:LsdException Locked=3D"false" Priority=3D"64" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Shading 2 Accent 5"/>
- <w:LsdException Locked=3D"false" Priority=3D"65" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium List 1 Accent 5"/>
- <w:LsdException Locked=3D"false" Priority=3D"66" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium List 2 Accent 5"/>
- <w:LsdException Locked=3D"false" Priority=3D"67" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 1 Accent 5"/>
- <w:LsdException Locked=3D"false" Priority=3D"68" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 2 Accent 5"/>
- <w:LsdException Locked=3D"false" Priority=3D"69" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 3 Accent 5"/>
- <w:LsdException Locked=3D"false" Priority=3D"70" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Dark List Accent 5"/>
- <w:LsdException Locked=3D"false" Priority=3D"71" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful Shading Accent 5"/>
- <w:LsdException Locked=3D"false" Priority=3D"72" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful List Accent 5"/>
- <w:LsdException Locked=3D"false" Priority=3D"73" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful Grid Accent 5"/>
- <w:LsdException Locked=3D"false" Priority=3D"60" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light Shading Accent 6"/>
- <w:LsdException Locked=3D"false" Priority=3D"61" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light List Accent 6"/>
- <w:LsdException Locked=3D"false" Priority=3D"62" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Light Grid Accent 6"/>
- <w:LsdException Locked=3D"false" Priority=3D"63" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Shading 1 Accent 6"/>
- <w:LsdException Locked=3D"false" Priority=3D"64" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Shading 2 Accent 6"/>
- <w:LsdException Locked=3D"false" Priority=3D"65" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium List 1 Accent 6"/>
- <w:LsdException Locked=3D"false" Priority=3D"66" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium List 2 Accent 6"/>
- <w:LsdException Locked=3D"false" Priority=3D"67" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 1 Accent 6"/>
- <w:LsdException Locked=3D"false" Priority=3D"68" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 2 Accent 6"/>
- <w:LsdException Locked=3D"false" Priority=3D"69" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Medium Grid 3 Accent 6"/>
- <w:LsdException Locked=3D"false" Priority=3D"70" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Dark List Accent 6"/>
- <w:LsdException Locked=3D"false" Priority=3D"71" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful Shading Accent 6"/>
- <w:LsdException Locked=3D"false" Priority=3D"72" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful List Accent 6"/>
- <w:LsdException Locked=3D"false" Priority=3D"73" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" Name=3D"Colorful Grid Accent 6"/>
- <w:LsdException Locked=3D"false" Priority=3D"19" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Subtle Emphasis"/>
- <w:LsdException Locked=3D"false" Priority=3D"21" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Intense Emphasis"/>
- <w:LsdException Locked=3D"false" Priority=3D"31" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Subtle Reference"/>
- <w:LsdException Locked=3D"false" Priority=3D"32" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Intense Reference"/>
- <w:LsdException Locked=3D"false" Priority=3D"33" SemiHidden=3D"false"
- UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Book Title"/>
- <w:LsdException Locked=3D"false" Priority=3D"37" Name=3D"Bibliography"/>
- <w:LsdException Locked=3D"false" Priority=3D"39" QFormat=3D"true" Name=3D=
-"TOC Heading"/>
- </w:LatentStyles>
-</xml><![endif]-->
-<style>
-<!--
- /* Font Definitions */
- @font-face
- {font-family:Wingdings;
- panose-1:5 0 0 0 0 0 0 0 0 0;
- mso-font-charset:2;
- mso-generic-font-family:auto;
- mso-font-pitch:variable;
- mso-font-signature:0 268435456 0 0 -2147483648 0;}
-@font-face
- {font-family:"Cambria Math";
- panose-1:2 4 5 3 5 4 6 3 2 4;
- mso-font-charset:1;
- mso-generic-font-family:roman;
- mso-font-format:other;
- mso-font-pitch:variable;
- mso-font-signature:0 0 0 0 0 0;}
-@font-face
- {font-family:Cambria;
- panose-1:2 4 5 3 5 4 6 3 2 4;
- mso-font-charset:0;
- mso-generic-font-family:roman;
- mso-font-pitch:variable;
- mso-font-signature:-536870145 1073742943 0 0 415 0;}
-@font-face
- {font-family:Tahoma;
- panose-1:2 11 6 4 3 5 4 4 2 4;
- mso-font-charset:0;
- mso-generic-font-family:swiss;
- mso-font-pitch:variable;
- mso-font-signature:-520081665 -1073717157 41 0 66047 0;}
-@font-face
- {font-family:Consolas;
- panose-1:2 11 6 9 2 2 4 3 2 4;
- mso-font-charset:0;
- mso-generic-font-family:modern;
- mso-font-pitch:fixed;
- mso-font-signature:-520092929 1073806591 9 0 415 0;}
- /* Style Definitions */
- p.MsoNormal, li.MsoNormal, div.MsoNormal
- {mso-style-unhide:no;
- mso-style-qformat:yes;
- mso-style-parent:"";
- margin:0in;
- margin-bottom:.0001pt;
- mso-pagination:widow-orphan;
- font-size:12.0pt;
- font-family:"Times New Roman","serif";
- mso-fareast-font-family:"Times New Roman";
- mso-fareast-theme-font:minor-fareast;}
-h1
- {mso-style-priority:9;
- mso-style-unhide:no;
- mso-style-qformat:yes;
- mso-style-link:"Heading 1 Char";
- margin-top:24.0pt;
- margin-right:0in;
- margin-bottom:0in;
- margin-left:0in;
- margin-bottom:.0001pt;
- mso-pagination:widow-orphan;
- page-break-after:avoid;
- mso-outline-level:1;
- font-size:14.0pt;
- font-family:"Cambria","serif";
- mso-fareast-font-family:"Times New Roman";
- mso-fareast-theme-font:minor-fareast;
- mso-bidi-font-family:"Times New Roman";
- color:#365F91;}
-h3
- {mso-style-noshow:yes;
- mso-style-priority:9;
- mso-style-qformat:yes;
- mso-style-link:"Heading 3 Char";
- mso-margin-top-alt:auto;
- margin-right:0in;
- mso-margin-bottom-alt:auto;
- margin-left:0in;
- mso-pagination:widow-orphan;
- mso-outline-level:3;
- font-size:13.5pt;
- font-family:"Times New Roman","serif";
- mso-fareast-font-family:"Times New Roman";
- mso-fareast-theme-font:minor-fareast;}
-p.MsoPlainText, li.MsoPlainText, div.MsoPlainText
- {mso-style-noshow:yes;
- mso-style-priority:99;
- mso-style-link:"Plain Text Char";
- margin:0in;
- margin-bottom:.0001pt;
- mso-pagination:widow-orphan;
- font-size:10.5pt;
- font-family:Consolas;
- mso-fareast-font-family:"Times New Roman";
- mso-fareast-theme-font:minor-fareast;}
-p.MsoAcetate, li.MsoAcetate, div.MsoAcetate
- {mso-style-noshow:yes;
- mso-style-priority:99;
- mso-style-link:"Balloon Text Char";
- margin:0in;
- margin-bottom:.0001pt;
- mso-pagination:widow-orphan;
- font-size:8.0pt;
- font-family:"Tahoma","sans-serif";
- mso-fareast-font-family:"Times New Roman";
- mso-fareast-theme-font:minor-fareast;}
-p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
- {mso-style-priority:34;
- mso-style-unhide:no;
- mso-style-qformat:yes;
- margin-top:0in;
- margin-right:0in;
- margin-bottom:0in;
- margin-left:.5in;
- margin-bottom:.0001pt;
- mso-add-space:auto;
- mso-pagination:widow-orphan;
- font-size:12.0pt;
- font-family:"Times New Roman","serif";
- mso-fareast-font-family:"Times New Roman";
- mso-fareast-theme-font:minor-fareast;}
-p.MsoListParagraphCxSpFirst, li.MsoListParagraphCxSpFirst, div.MsoListParag=
-raphCxSpFirst
- {mso-style-priority:34;
- mso-style-unhide:no;
- mso-style-qformat:yes;
- mso-style-type:export-only;
- margin-top:0in;
- margin-right:0in;
- margin-bottom:0in;
- margin-left:.5in;
- margin-bottom:.0001pt;
- mso-add-space:auto;
- mso-pagination:widow-orphan;
- font-size:12.0pt;
- font-family:"Times New Roman","serif";
- mso-fareast-font-family:"Times New Roman";
- mso-fareast-theme-font:minor-fareast;}
-p.MsoListParagraphCxSpMiddle, li.MsoListParagraphCxSpMiddle, div.MsoListPar=
-agraphCxSpMiddle
- {mso-style-priority:34;
- mso-style-unhide:no;
- mso-style-qformat:yes;
- mso-style-type:export-only;
- margin-top:0in;
- margin-right:0in;
- margin-bottom:0in;
- margin-left:.5in;
- margin-bottom:.0001pt;
- mso-add-space:auto;
- mso-pagination:widow-orphan;
- font-size:12.0pt;
- font-family:"Times New Roman","serif";
- mso-fareast-font-family:"Times New Roman";
- mso-fareast-theme-font:minor-fareast;}
-p.MsoListParagraphCxSpLast, li.MsoListParagraphCxSpLast, div.MsoListParagra=
-phCxSpLast
- {mso-style-priority:34;
- mso-style-unhide:no;
- mso-style-qformat:yes;
- mso-style-type:export-only;
- margin-top:0in;
- margin-right:0in;
- margin-bottom:0in;
- margin-left:.5in;
- margin-bottom:.0001pt;
- mso-add-space:auto;
- mso-pagination:widow-orphan;
- font-size:12.0pt;
- font-family:"Times New Roman","serif";
- mso-fareast-font-family:"Times New Roman";
- mso-fareast-theme-font:minor-fareast;}
-span.Heading1Char
- {mso-style-name:"Heading 1 Char";
- mso-style-priority:9;
- mso-style-unhide:no;
- mso-style-locked:yes;
- mso-style-link:"Heading 1";
- mso-ansi-font-size:14.0pt;
- mso-bidi-font-size:14.0pt;
- font-family:"Cambria","serif";
- mso-ascii-font-family:Cambria;
- mso-fareast-font-family:"Times New Roman";
- mso-fareast-theme-font:minor-fareast;
- mso-hansi-font-family:Cambria;
- mso-bidi-font-family:"Times New Roman";
- color:#365F91;
- mso-font-kerning:18.0pt;
- font-weight:bold;}
-span.Heading3Char
- {mso-style-name:"Heading 3 Char";
- mso-style-noshow:yes;
- mso-style-priority:9;
- mso-style-unhide:no;
- mso-style-locked:yes;
- mso-style-link:"Heading 3";
- mso-ansi-font-size:13.5pt;
- mso-bidi-font-size:13.5pt;
- font-family:"Times New Roman","serif";
- mso-ascii-font-family:"Times New Roman";
- mso-fareast-font-family:"Times New Roman";
- mso-fareast-theme-font:minor-fareast;
- mso-hansi-font-family:"Times New Roman";
- mso-bidi-font-family:"Times New Roman";
- font-weight:bold;}
-span.PlainTextChar
- {mso-style-name:"Plain Text Char";
- mso-style-noshow:yes;
- mso-style-priority:99;
- mso-style-unhide:no;
- mso-style-locked:yes;
- mso-style-link:"Plain Text";
- mso-ansi-font-size:10.5pt;
- mso-bidi-font-size:10.5pt;
- font-family:Consolas;
- mso-ascii-font-family:Consolas;
- mso-hansi-font-family:Consolas;
- mso-bidi-font-family:Consolas;}
-span.BalloonTextChar
- {mso-style-name:"Balloon Text Char";
- mso-style-noshow:yes;
- mso-style-priority:99;
- mso-style-unhide:no;
- mso-style-locked:yes;
- mso-style-link:"Balloon Text";
- mso-ansi-font-size:8.0pt;
- mso-bidi-font-size:8.0pt;
- font-family:"Tahoma","sans-serif";
- mso-ascii-font-family:Tahoma;
- mso-fareast-font-family:"Times New Roman";
- mso-fareast-theme-font:minor-fareast;
- mso-hansi-font-family:Tahoma;
- mso-bidi-font-family:Tahoma;}
-span.SpellE
- {mso-style-name:"";
- mso-spl-e:yes;}
-.MsoChpDefault
- {mso-style-type:export-only;
- mso-default-props:yes;
- font-size:10.0pt;
- mso-ansi-font-size:10.0pt;
- mso-bidi-font-size:10.0pt;
- font-family:"Calibri","sans-serif";
- mso-ascii-font-family:Calibri;
- mso-ascii-theme-font:minor-latin;
- mso-fareast-font-family:Calibri;
- mso-fareast-theme-font:minor-latin;
- mso-hansi-font-family:Calibri;
- mso-hansi-theme-font:minor-latin;
- mso-bidi-font-family:"Times New Roman";
- mso-bidi-theme-font:minor-bidi;}
-@page WordSection1
- {size:8.5in 11.0in;
- margin:1.0in 75.1pt 1.0in 75.05pt;
- mso-header-margin:.5in;
- mso-footer-margin:.5in;
- mso-paper-source:0;}
-div.WordSection1
- {page:WordSection1;}
- /* List Definitions */
- @list l0
- {mso-list-id:557473843;
- mso-list-type:hybrid;
- mso-list-template-ids:-1934189430 -1019988350 67698691 67698693 67698689 6=
-7698691 67698693 67698689 67698691 67698693;}
-@list l0:level1
- {mso-level-start-at:6;
- mso-level-number-format:bullet;
- mso-level-text:-;
- mso-level-tab-stop:none;
- mso-level-number-position:left;
- text-indent:-.25in;
- font-family:"Arial","sans-serif";
- mso-fareast-font-family:"Times New Roman";}
-@list l0:level2
- {mso-level-number-format:bullet;
- mso-level-text:o;
- mso-level-tab-stop:none;
- mso-level-number-position:left;
- text-indent:-.25in;
- font-family:"Courier New";}
-@list l0:level3
- {mso-level-number-format:bullet;
- mso-level-text:\F0A7;
- mso-level-tab-stop:none;
- mso-level-number-position:left;
- text-indent:-.25in;
- font-family:Wingdings;}
-@list l0:level4
- {mso-level-number-format:bullet;
- mso-level-text:\F0B7;
- mso-level-tab-stop:none;
- mso-level-number-position:left;
- text-indent:-.25in;
- font-family:Symbol;}
-@list l0:level5
- {mso-level-number-format:bullet;
- mso-level-text:o;
- mso-level-tab-stop:none;
- mso-level-number-position:left;
- text-indent:-.25in;
- font-family:"Courier New";}
-@list l0:level6
- {mso-level-number-format:bullet;
- mso-level-text:\F0A7;
- mso-level-tab-stop:none;
- mso-level-number-position:left;
- text-indent:-.25in;
- font-family:Wingdings;}
-@list l0:level7
- {mso-level-number-format:bullet;
- mso-level-text:\F0B7;
- mso-level-tab-stop:none;
- mso-level-number-position:left;
- text-indent:-.25in;
- font-family:Symbol;}
-@list l0:level8
- {mso-level-number-format:bullet;
- mso-level-text:o;
- mso-level-tab-stop:none;
- mso-level-number-position:left;
- text-indent:-.25in;
- font-family:"Courier New";}
-@list l0:level9
- {mso-level-number-format:bullet;
- mso-level-text:\F0A7;
- mso-level-tab-stop:none;
- mso-level-number-position:left;
- text-indent:-.25in;
- font-family:Wingdings;}
-@list l1
- {mso-list-id:881289435;
- mso-list-type:hybrid;
- mso-list-template-ids:357181992 67698703 67698713 67698715 67698703 676987=
-13 67698715 67698703 67698713 67698715;}
-@list l1:level1
- {mso-level-tab-stop:none;
- mso-level-number-position:left;
- text-indent:-.25in;}
-@list l1:level2
- {mso-level-number-format:alpha-lower;
- mso-level-tab-stop:none;
- mso-level-number-position:left;
- text-indent:-.25in;}
-@list l1:level3
- {mso-level-number-format:roman-lower;
- mso-level-tab-stop:none;
- mso-level-number-position:right;
- text-indent:-9.0pt;}
-@list l1:level4
- {mso-level-tab-stop:none;
- mso-level-number-position:left;
- text-indent:-.25in;}
-@list l1:level5
- {mso-level-number-format:alpha-lower;
- mso-level-tab-stop:none;
- mso-level-number-position:left;
- text-indent:-.25in;}
-@list l1:level6
- {mso-level-number-format:roman-lower;
- mso-level-tab-stop:none;
- mso-level-number-position:right;
- text-indent:-9.0pt;}
-@list l1:level7
- {mso-level-tab-stop:none;
- mso-level-number-position:left;
- text-indent:-.25in;}
-@list l1:level8
- {mso-level-number-format:alpha-lower;
- mso-level-tab-stop:none;
- mso-level-number-position:left;
- text-indent:-.25in;}
-@list l1:level9
- {mso-level-number-format:roman-lower;
- mso-level-tab-stop:none;
- mso-level-number-position:right;
- text-indent:-9.0pt;}
-ol
- {margin-bottom:0in;}
-ul
- {margin-bottom:0in;}
--->
-</style>
-<!--[if gte mso 10]>
-<style>
- /* Style Definitions */
- table.MsoNormalTable
- {mso-style-name:"Table Normal";
- mso-tstyle-rowband-size:0;
- mso-tstyle-colband-size:0;
- mso-style-noshow:yes;
- mso-style-priority:99;
- mso-style-parent:"";
- mso-padding-alt:0in 5.4pt 0in 5.4pt;
- mso-para-margin:0in;
- mso-para-margin-bottom:.0001pt;
- mso-pagination:widow-orphan;
- font-size:10.0pt;
- font-family:"Calibri","sans-serif";
- mso-ascii-font-family:Calibri;
- mso-ascii-theme-font:minor-latin;
- mso-hansi-font-family:Calibri;
- mso-hansi-theme-font:minor-latin;
- mso-bidi-font-family:"Times New Roman";
- mso-bidi-theme-font:minor-bidi;}
-</style>
-<![endif]--><!--[if gte mso 9]><xml>
- <o:shapedefaults v:ext=3D"edit" spidmax=3D"1026"/>
-</xml><![endif]--><!--[if gte mso 9]><xml>
- <o:shapelayout v:ext=3D"edit">
- <o:idmap v:ext=3D"edit" data=3D"1"/>
- </o:shapelayout></xml><![endif]-->
-</head>
-
-<body lang=3DEN-US style=3D'tab-interval:.5in'>
-
-<div class=3DWordSection1>
-
-<h1><span style=3D'mso-fareast-font-family:"Times New Roman"'>F-state-based=
- power
-management for multi-component device<o:p></o:p></span></h1>
-
-<h3><span style=3D'mso-fareast-font-family:"Times New Roman"'>Summary<o:p><=
-/o:p></span></h3>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif";
-mso-fareast-font-family:"Times New Roman"'>This sample demonstrates how a K=
-MDF
-driver can implement F-state-based power management for a device that has an
-arbitrary number of components that can be individually power-managed.<o:p>=
-</o:p></span></p>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif";
-mso-fareast-font-family:"Times New Roman"'><o:p>&nbsp;</o:p></span></p>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif";
-mso-fareast-font-family:"Times New Roman"'>The sample driver statically lin=
-ks
-to a helper library (WdfPoFx.lib) that encapsulates all of the generic code=
- to
-interact with the power framework. The device-specific code is implemented =
-in
-the driver itself, outside of the helper library. The idea behind this
-organizing the code in this manner is make the helper library reusable by o=
-ther
-drivers. The directory structure for the sample is as follows:<o:p></o:p></=
-span></p>
-
-<p class=3DMsoListParagraphCxSpFirst style=3D'text-indent:-.25in;mso-list:l=
-0 level1 lfo2'><![if !supportLists]><span
-style=3D'font-size:10.0pt;font-family:"Arial","sans-serif";mso-fareast-font=
--family:
-Arial'><span style=3D'mso-list:Ignore'>-<span style=3D'font:7.0pt "Times Ne=
-w Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-</span></span></span><![endif]><span style=3D'font-size:10.0pt;font-family:=
-"Arial","sans-serif";
-mso-fareast-font-family:"Times New Roman"'>The helper library is implemente=
-d in
-the &#8216;lib&#8217; subdirectory<o:p></o:p></span></p>
-
-<p class=3DMsoListParagraphCxSpMiddle style=3D'text-indent:-.25in;mso-list:=
-l0 level1 lfo2'><![if !supportLists]><span
-style=3D'font-size:10.0pt;font-family:"Arial","sans-serif";mso-fareast-font=
--family:
-Arial'><span style=3D'mso-list:Ignore'>-<span style=3D'font:7.0pt "Times Ne=
-w Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-</span></span></span><![endif]><span style=3D'font-size:10.0pt;font-family:=
-"Arial","sans-serif";
-mso-fareast-font-family:"Times New Roman"'>The interface between the helper
-library and the rest of the driver code is defined in the &#8216;<span
-class=3DSpellE>inc</span>&#8217; subdirectory<o:p></o:p></span></p>
-
-<p class=3DMsoListParagraphCxSpLast style=3D'text-indent:-.25in;mso-list:l0=
- level1 lfo2'><![if !supportLists]><span
-style=3D'font-size:10.0pt;font-family:"Arial","sans-serif";mso-fareast-font=
--family:
-Arial'><span style=3D'mso-list:Ignore'>-<span style=3D'font:7.0pt "Times Ne=
-w Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-</span></span></span><![endif]><span style=3D'font-size:10.0pt;font-family:=
-"Arial","sans-serif";
-mso-fareast-font-family:"Times New Roman"'>The driver is implemented in the
-&#8216;driver&#8217; subdirectory<o:p></o:p></span></p>
-
-<h3><span style=3D'mso-fareast-font-family:"Times New Roman"'>Installation<=
-o:p></o:p></span></h3>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'>The
-driver can be installed on a root-enumerated device using the devcon.exe to=
-ol. <o:p></o:p></span></p>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'><o:p>&nbsp;</o:p></span></p>
-
-<p class=3DMsoListParagraphCxSpFirst style=3D'text-indent:-.25in;mso-list:l=
-1 level1 lfo4'><![if !supportLists]><span
-style=3D'font-size:10.0pt;font-family:"Arial","sans-serif";mso-fareast-font=
--family:
-Arial'><span style=3D'mso-list:Ignore'>1.<span style=3D'font:7.0pt "Times N=
-ew Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;
-</span></span></span><![endif]><span style=3D'font-size:10.0pt;font-family:=
-"Arial","sans-serif"'>Obtain
-the devcon.exe tool from the WDK<o:p></o:p></span></p>
-
-<p class=3DMsoListParagraphCxSpMiddle style=3D'text-indent:-.25in;mso-list:=
-l1 level1 lfo4'><![if !supportLists]><span
-style=3D'font-size:10.0pt;font-family:"Arial","sans-serif";mso-fareast-font=
--family:
-Arial'><span style=3D'mso-list:Ignore'>2.<span style=3D'font:7.0pt "Times N=
-ew Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;
-</span></span></span><![endif]><span style=3D'font-size:10.0pt;font-family:=
-"Arial","sans-serif"'>Copy
-the driver binary, INF file and the KMDF <span class=3DSpellE>coinstaller</=
-span>
-to a directory on your test machine.<o:p></o:p></span></p>
-
-<p class=3DMsoListParagraphCxSpLast style=3D'text-indent:-.25in;mso-list:l1=
- level1 lfo4'><![if !supportLists]><span
-style=3D'font-size:10.0pt;font-family:"Arial","sans-serif";mso-fareast-font=
--family:
-Arial'><span style=3D'mso-list:Ignore'>3.<span style=3D'font:7.0pt "Times N=
-ew Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;
-</span></span></span><![endif]><span style=3D'font-size:10.0pt;font-family:=
-"Arial","sans-serif"'>Run
-the command &#8220;devcon.exe install WdfMultiComp.inf WDF\<span class=3DSp=
-ellE>WdfMultiComp</span>&#8221;<o:p></o:p></span></p>
-
-<h3><span style=3D'mso-fareast-font-family:"Times New Roman"'>Testing<o:p><=
-/o:p></span></h3>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'>Use
-the PowerFxApp.exe application to send I/O requests to the driver. Running =
-the
-command &#8220;PowerFxApp.exe /?&#8221; displays detailed usage information=
-.<o:p></o:p></span></p>
-
-<h3><span style=3D'mso-fareast-font-family:"Times New Roman"'>Design overvi=
-ew<o:p></o:p></span></h3>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'>The
-driver controls a device that has more than one component. It needs to acce=
-ss
-one of those components for processing each I/O request that it receives. T=
-he
-specific component that it needs to access depends on the I/O request that =
-it
-receives.<o:p></o:p></span></p>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'><o:p>&nbsp;</o:p></span></p>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'>In
-order to support this, the driver creates one top-level, power-managed queu=
-e to
-receive all its requests. It also creates one secondary, power-managed queue
-for each of its components. These secondary queues are called component que=
-ues.
-This is shown in the diagram below.<o:p></o:p></span></p>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'><!--[if gte vml 1]><v:shapetype
- id=3D"_x0000_t75" coordsize=3D"21600,21600" o:spt=3D"75" o:preferrelative=
-=3D"t"
- path=3D"m@4@5l@4@11@9@11@9@5xe" filled=3D"f" stroked=3D"f">
- <v:stroke joinstyle=3D"miter"/>
- <v:formulas>
- <v:f eqn=3D"if lineDrawn pixelLineWidth 0"/>
- <v:f eqn=3D"sum @0 1 0"/>
- <v:f eqn=3D"sum 0 0 @1"/>
- <v:f eqn=3D"prod @2 1 2"/>
- <v:f eqn=3D"prod @3 21600 pixelWidth"/>
- <v:f eqn=3D"prod @3 21600 pixelHeight"/>
- <v:f eqn=3D"sum @0 0 1"/>
- <v:f eqn=3D"prod @6 1 2"/>
- <v:f eqn=3D"prod @7 21600 pixelWidth"/>
- <v:f eqn=3D"sum @8 21600 0"/>
- <v:f eqn=3D"prod @7 21600 pixelHeight"/>
- <v:f eqn=3D"sum @10 21600 0"/>
- </v:formulas>
- <v:path o:extrusionok=3D"f" gradientshapeok=3D"t" o:connecttype=3D"rect"/>
- <o:lock v:ext=3D"edit" aspectratio=3D"t"/>
-</v:shapetype><v:shape id=3D"_x0000_i1025" type=3D"#_x0000_t75" style=3D'wi=
-dth:588.75pt;
- height:246pt' o:ole=3D"">
- <v:imagedata src=3D"WdfMultiComp_files/image001.emz" o:title=3D""/>
-</v:shape><![endif]--><![if !vml]><img width=3D785 height=3D328
-src=3D"WdfMultiComp_files/image002.gif" v:shapes=3D"_x0000_i1025"><![endif]=
-><!--[if gte mso 9]><xml>
- <o:OLEObject Type=3D"Embed" ProgID=3D"Visio.Drawing.11" ShapeID=3D"_x0000_=
-i1025"
- DrawAspect=3D"Content" ObjectID=3D"_1373452002">
- </o:OLEObject>
-</xml><![endif]--><o:p></o:p></span></p>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'><o:p>&nbsp;</o:p></span></p>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'>When
-the driver&#8217;s dispatch routine for the top-level queue is invoked, it
-examines the request to determine which component it needs to access in ord=
-er
-to process the request. Then, it forwards the request to the component queue
-for the component that it needs to access for that request. When the
-driver&#8217;s dispatch routine for the component queue is invoked, it acce=
-sses
-the component hardware to process the request.<o:p></o:p></span></p>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'><o:p>&nbsp;</o:p></span></p>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'>The
-driver&#8217;s top-level queue and component queues are all power-managed so
-KMDF ensures that the device is in D0 while the queues are in a dispatching
-state. The key point to note is that the driver is designed to maintain a c=
-omponent
-queue in a dispatching state only when the component is active. In order to
-achieve this, the driver stops the component queue when the component becom=
-es
-idle and starts the component queue when the component becomes active. (To =
-be
-precise, this mechanism of stopping and starting queues is encapsulated in =
-the
-power framework helper library used by the driver). Thus, the driver is abl=
-e to
-ensure that when the component queue is in a dispatching state, not only is=
- the
-device in D0 but the component corresponding to that queue is also active. =
-Thus
-it is safe to access the component hardware when the component queue&#8217;s
-dispatch routine is invoked.<o:p></o:p></span></p>
-
-<h3><span style=3D'mso-fareast-font-family:"Times New Roman"'>Implementation
-notes<o:p></o:p></span></h3>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'>The
-driver uses the power framework helper library to manage most of its
-interactions with the power framework. In order to achieve this, during dev=
-ice
-initialization, the driver performs the following tasks in its <span
-class=3DSpellE>EvtDriverDeviceAdd</span> callback:<o:p></o:p></span></p>
-
-<p class=3DMsoListParagraphCxSpFirst style=3D'text-indent:-.25in;mso-list:l=
-0 level1 lfo2'><![if !supportLists]><span
-style=3D'font-size:10.0pt;font-family:"Arial","sans-serif";mso-fareast-font=
--family:
-Arial'><span style=3D'mso-list:Ignore'>-<span style=3D'font:7.0pt "Times Ne=
-w Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-</span></span></span><![endif]><span style=3D'font-size:10.0pt;font-family:=
-"Arial","sans-serif"'>Enables
-the helper library to register its own KMDF callbacks for PNP and
-power-management of the device.<o:p></o:p></span></p>
-
-<p class=3DMsoListParagraphCxSpMiddle style=3D'text-indent:-.25in;mso-list:=
-l0 level1 lfo2'><![if !supportLists]><span
-style=3D'font-size:10.0pt;font-family:"Arial","sans-serif";mso-fareast-font=
--family:
-Arial'><span style=3D'mso-list:Ignore'>-<span style=3D'font:7.0pt "Times Ne=
-w Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-</span></span></span><![endif]><span style=3D'font-size:10.0pt;font-family:=
-"Arial","sans-serif"'>Provides
-the helper library with power-framework-related information about the devic=
-e.<o:p></o:p></span></p>
-
-<p class=3DMsoListParagraphCxSpLast style=3D'text-indent:-.25in;mso-list:l0=
- level1 lfo2'><![if !supportLists]><span
-style=3D'font-size:10.0pt;font-family:"Arial","sans-serif";mso-fareast-font=
--family:
-Arial'><span style=3D'mso-list:Ignore'>-<span style=3D'font:7.0pt "Times Ne=
-w Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-</span></span></span><![endif]><span style=3D'font-size:10.0pt;font-family:=
-"Arial","sans-serif"'>Provides
-the helper library with information about the component queues.<o:p></o:p><=
-/span></p>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'>During
-I/O request processing, the driver uses routines provided by helper library=
- to
-forward requests to component queues and also to complete requests. <o:p></=
-o:p></span></p>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'><o:p>&nbsp;</o:p></span></p>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'>The
-main tasks performed by the power framework helper library on behalf of the
-driver are:<o:p></o:p></span></p>
-
-<p class=3DMsoListParagraphCxSpFirst style=3D'text-indent:-.25in;mso-list:l=
-0 level1 lfo2'><![if !supportLists]><span
-style=3D'font-size:10.0pt;font-family:"Arial","sans-serif";mso-fareast-font=
--family:
-Arial'><span style=3D'mso-list:Ignore'>-<span style=3D'font:7.0pt "Times Ne=
-w Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-</span></span></span><![endif]><span style=3D'font-size:10.0pt;font-family:=
-"Arial","sans-serif"'>Registration
-and <span class=3DSpellE>unregistration</span> with the power framework.<o:=
-p></o:p></span></p>
-
-<p class=3DMsoListParagraphCxSpMiddle style=3D'text-indent:-.25in;mso-list:=
-l0 level1 lfo2'><![if !supportLists]><span
-style=3D'font-size:10.0pt;font-family:"Arial","sans-serif";mso-fareast-font=
--family:
-Arial'><span style=3D'mso-list:Ignore'>-<span style=3D'font:7.0pt "Times Ne=
-w Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-</span></span></span><![endif]><span style=3D'font-size:10.0pt;font-family:=
-"Arial","sans-serif"'>Stopping
-component queues when the corresponding components become idle and starting
-them when the corresponding components become active.<o:p></o:p></span></p>
-
-<p class=3DMsoListParagraphCxSpLast style=3D'text-indent:-.25in;mso-list:l0=
- level1 lfo2'><![if !supportLists]><span
-style=3D'font-size:10.0pt;font-family:"Arial","sans-serif";mso-fareast-font=
--family:
-Arial'><span style=3D'mso-list:Ignore'>-<span style=3D'font:7.0pt "Times Ne=
-w Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-</span></span></span><![endif]><span style=3D'font-size:10.0pt;font-family:=
-"Arial","sans-serif"'>Notifying
-the power framework when the device returns to its working state (D0) in
-response to the system returning from a low-power state to the working state
-(S0).<o:p></o:p></span></p>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'><o:p>&nbsp;</o:p></span></p>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'>The
-power framework helper library does not have any hardware-specific informat=
-ion,
-so any tasks that are specific to the device&#8217;s hardware are performed=
- by
-the driver. In this sample, the device hardware is represented by a very si=
-mple
-simulation. The notable hardware-specific tasks in this sample are:<o:p></o=
-:p></span></p>
-
-<p class=3DMsoListParagraphCxSpFirst style=3D'text-indent:-.25in;mso-list:l=
-0 level1 lfo2'><![if !supportLists]><span
-style=3D'font-size:10.0pt;font-family:"Arial","sans-serif";mso-fareast-font=
--family:
-Arial'><span style=3D'mso-list:Ignore'>-<span style=3D'font:7.0pt "Times Ne=
-w Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-</span></span></span><![endif]><span style=3D'font-size:10.0pt;font-family:=
-"Arial","sans-serif"'>Accessing
-component hardware to process I/O requests.<o:p></o:p></span></p>
-
-<p class=3DMsoListParagraphCxSpLast style=3D'text-indent:-.25in;mso-list:l0=
- level1 lfo2'><![if !supportLists]><span
-style=3D'font-size:10.0pt;font-family:"Arial","sans-serif";mso-fareast-font=
--family:
-Arial'><span style=3D'mso-list:Ignore'>-<span style=3D'font:7.0pt "Times Ne=
-w Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-</span></span></span><![endif]><span style=3D'font-size:10.0pt;font-family:=
-"Arial","sans-serif"'>Accessing
-component hardware to change the component&#8217;s F-state.<o:p></o:p></spa=
-n></p>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'>As
-mentioned earlier, the hardware access shown is this sample is entirely
-simulated in software. This sample does not work with a real device &#8211;=
- it
-installs on a root-enumerated software device.<o:p></o:p></span></p>
-
-<h3><span style=3D'mso-fareast-font-family:"Times New Roman"'>S0-idle power
-management support<o:p></o:p></span></h3>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'>The
-power framework helper library implements support for S0-idle power managem=
-ent
-for the device. Note that this is different from the component power manage=
-ment
-support that is enabled by the power framework. Component power management
-enables individual components of the device to be power-managed by putting =
-them
-in different F-states while the device is in a working state (D0). S0-idle
-power management for the device enables the device as a whole to be
-power-managed by putting it into different D-states while the system is in a
-working state (S0).<o:p></o:p></span></p>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'><o:p>&nbsp;</o:p></span></p>
-
-<p class=3DMsoNormal><span style=3D'font-size:10.0pt;font-family:"Arial","s=
-ans-serif"'>The
-code to implement S0-idle power management support for the device is
-conditionally compiled based on the value of the </span><span style=3D'font=
--size:
-9.0pt;font-family:"Courier New"'>PFH_S0IDLE_SUPPORTED</span><span
-style=3D'font-size:10.0pt;font-family:"Arial","sans-serif"'> compiler switc=
-h. If
-the switch is set to a non-zero value, the code to implement S0-idle power
-management support is included. If set to zero, the code is omitted thereby
-resulting in a smaller binary size. Thus, a driver that requires S0-idle po=
-wer
-management for the device can use the power framework helper library&#8217;s
-support for it but a driver that does not require it can reduce its binary =
-size
-by omitting the code that is specific to S0-idle power management.<o:p></o:=
-p></span></p>
-
-</div>
-
-</body>
-
-</html>
-
-------=_NextPart_01CC4DF5.1FA44F90
-Content-Location: file:///C:/EEB34A10/WdfMultiComp_files/themedata.thmx
-Content-Transfer-Encoding: base64
-Content-Type: application/vnd.ms-officetheme
-
-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
-cmVsc1BLBQYAAAAABQAFAF0BAACtCgAAAAA=
-
-------=_NextPart_01CC4DF5.1FA44F90
-Content-Location: file:///C:/EEB34A10/WdfMultiComp_files/colorschememapping.xml
-Content-Transfer-Encoding: quoted-printable
-Content-Type: text/xml
-
-<?xml version=3D"1.0" encoding=3D"UTF-8" standalone=3D"yes"?>
-<a:clrMap xmlns:a=3D"http://schemas.openxmlformats.org/drawingml/2006/main"=
- bg1=3D"lt1" tx1=3D"dk1" bg2=3D"lt2" tx2=3D"dk2" accent1=3D"accent1" accent=
-2=3D"accent2" accent3=3D"accent3" accent4=3D"accent4" accent5=3D"accent5" a=
-ccent6=3D"accent6" hlink=3D"hlink" folHlink=3D"folHlink"/>
-------=_NextPart_01CC4DF5.1FA44F90
-Content-Location: file:///C:/EEB34A10/WdfMultiComp_files/image001.emz
-Content-Transfer-Encoding: base64
-Content-Type: image/x-emz
-
-H4sIAAAAAAAEC+ydb2wd15neL0VRpCnalERJIWxuaN6SMDeUIkZxDAKWnSvTVFRAiwbbKGBiyVED
-GVULf/CHpFAkVSu1bIlWgLofCLAQKoBYEFDXf4D+2ezqg4sSC6RQ0TgJ2iygdtVWaKOEWBioYsmK
-FVNSf7+Ze4bDu7nk5SWPzNge5NG8Z+7MPM95z5kzcx4PJw2FQuFVsBFsu/vgwSvNhcLmRgrlZePf
-LhSKxULhyZHf21coNBTe/d8NhZ9vKhSawg7l9RmO+zfrC4WWdYVCqWHhj6X/x4//Z32BExR2gCcB
-pxtoYMcu4k1g3aaZv/SwI2W473fAMeC+g6V1yX5QsJz5cndpfaEtiQuFz5aasvh3SoXCVra3AKQU
-9nHSz5Y2ZL+3lgozgfOdd975Azn/rHCq0FkYLPSUj/s2a8/tb0+BznLMqsAxrgp9IOxzgPgo+DNw
-CvwIvJEre/wg+JuFb/JvWM58OUTWZz7+zZHnkO/BgweFXtaC455LVhWx9X4ZfAcYu7j/IPgaeBK4
-9IOWMhqS2s7/5u/5Rd7X2XAQVFuHnMgZYs5/plp+XqPTzdA1zpho+tx/LkwRhCWfk3wcfl+4Dnye
-LsSe1noLNu9NVhWxWkNu/ama1tC27jsIVtKWQR+nOVPkn3K7PrDP94MuYJ/P9+v1pXQ/fkquo5+y
-vgLcr6VUaHya2GO9jppYF0r2xzcLP05wKunjlgsNDQ1n+fmLpcJ6eV1aSg3rSqw9h8ezSvqw6zde
-f/15c5SH28N+XkMtpXXL4m/g+G2l+evZcg9oAd8G6spve7b8W0fut5eIvwrCQv9MFnW2AnMg/rRw
-ErxV+EkC45NZLvK52cO+8g+DwJ/nM7du9/yh/dR4ABwFfwpOgh+DN3Plx4l3g5X0l60cL/cjoLMc
-U9l8336o48BBNFQbA9we8mOuQg6NQzs+QbwJeP1fprG+QTwEwlJuygdcy4WbbZdbZ9tmRPPNtivN
-r2280nx844xoHeV3+2xYwnEb2HB84w9av7vxSiv7t74KjlE+xjHP8NsmcAxuxx7P0Q/CEs7RyIZj
-G99ufnXjZTgvN4fjbtIQl5c47v22y80ftL0NZrLjPuC4Geq6GN8HbT9ofb/tSiv1zHSaoyvl46rV
-NV8/NFPfy9T7cqudogXsKa+fZ90JKvtqaCP7c2g7494yah07Qz99lOMOgKOgkiuUH+e3lV4XQSun
-WjCOFtlAur1XJmNqidjcpWNl43pz4O9hDKOtNz1daky2sbmwvpT+brwPvAuug8XG2u9zRbyT4ETh
-+wXxen6sbZDP5XOlNK9qoEe8kKzS+M//aueXhg/+xe8Ot5TWN3yNbfuBGte7TvZxPP7c2yn++fMH
-DzZ9+ebNm0mXDet7/+Pbf/J3nrrz5bc/2/Qfif/tN//FP3r+v/+z39nTWprn9Xy2b+W5etjWAr4N
-1Os+YdtnidX8fXACvAOoYdZfOO7MU5Tdx2vHBU3JOrST20Ps/l+nPJjskf4Trr0min9SOA6+x31I
-GB9fcGw4D7ue6ecf9Xr+Sg2ck63zvNU0fJ99rNcPwUmQavgevCfhF8bfq0vD/fv3OWNtGuRWw2mQ
-ajgJ72n4hfHJujTcu3ePM9amQW41nAWphtPwnoVfGJ+uS8Pc3BxnrE2D3GoYA6mGs/COwS+Mz9al
-4cMPP+SMtWmQWw3jINUwBu84/MJ4rC4Nv/71rzljbRrkVsM5kGoYh/cc/MJ4vC4Nd+/e5Yy1aZBb
-DedBquEcvOfhF8bn6tLwwQcfcMbaNMithgmQajgP7wT8wvh8XRp+9atfccbaNMithkmQapiAdxJ+
-YTxRl4Y7d+5wxto0yK2GCyDVMAnvBfiF8WRdGt5//33OWJsGudVwEaQaLsB7EX5hfKEuDbdv3+aM
-tWmQWw1TINVwEd4p+IXxxbo03Lp1izPWpmGK/dQwDVINU/BOwy+Mp+rS8N5773HG2jTIrYZLINUw
-De8l+IXxdF0afvnLX3LG2jTIrYY/BqmGS/C+Dr8wvlSThj6ObwPNFc9zPoP9IRgDPoMNlOafz1pK
-TVWe5+Y9oZXMb0ul0oNt8G2Cez1oAL1lIPM5wvIyH/us9i0wBHzecO0S1p7FPLlw/mQd/gk5yD+n
-sG/2rPTv2fE4CPNMz/PVjVOtP2lL0EwsWsN5zGWI2fVMTvteyuVl3htRez+wHdRg7tW9A5j7pby0
-H5e9tHAOzxf4zd0BcBSo/xT4OXgjV+4kHgQrmS97DvX77Jerb9W2epl9vwPU6uIxg+Br4EngYn1a
-yngYXlllfm5SobXqlVVqDeXVaMvQd0j9gjme/dI26QJpv5y/3teX5scH9/spuFLer6X0m70yvaBf
-JDhF3xRvcpk+PK+sGr/XzMPyytJ5zluFWbyy2fK8J+Qin5s9aPJaGAZ0y2RM7MjFtovbq137P+K3
-k+AXgCxzj0jLj7PeDVZy7W/leLkfAZ3l+KMcBw6i4XVQbR36t7kKOTR+FpjjJ8Am4PV/uXVxr+y1
-xy63HntsRjS/9tiVxC/TgwKLemV53+ldvKdZfKhZjnmmzD0L91Je2Sx+17v4Xvh1mef12mNLe2Xf
-fexy8/HH3gbzXtlxjlvKKzv+GP7eY/h7IOg0R1fI0Si6nwZhCb7CBjbk64fmVjTjt1X3ykLfDH01
-tJHXZWg7494yGKb2EpaX+dg2Df3RH0M/fZT4ADgKKrlCeTWui6AVmgXjaJENpC3zyvqJu4Bj6ko9
-Mf2wGwlO4BcJroT5MbVGT+z31rwn9g75OgFuAGqY9Quu31X1xH7Ik98P8aB+nsA4ricW6vUz6uR4
-3QTk/yGlnycwjuuJqUFuNZwGqYaT8J5GgzCO64mpQW41nM00nIb3LPzCOK4npga51TCWaTgL7xj8
-wjiuJ6YGudUwnmkYg3ccfmEc1xNTg9xqOJdpGIf3HPzCOK4npga51XA+03AO3vPwC+O4npga5FbD
-RKbhPLwT8AvjuJ6YGuRWw2SmYQLeSfiFcVxPTA1yq+FCpmES3gvwC+O4npga5FbDxUzDBXgvwi+M
-43piapBbDVMgHScvwjsFvzCO64mpQW41TINUwxS80/AL46kF98c+9vP5g2XR/45TqyemBrnVcAmk
-GqbhvQS/MI7rialBbjUET0z+H/J08PMExiv3xI5z/ldBpSf2dGl+Lvxx8r7+C3W1zr8AbwLbVt/r
-q48laCYWH5n39YsavS/1nwL3wRsglDuJB8FK5r+ew+vpo5zz+gx8EFRbh2veOVGIW7j+D1A+CkI+
-Qn6cR65V76tSayivRluG3JCSBXM2Pa1+0AVWw/vS23mQ4BS5F2/m52nR3xOrxu+8+mF5X+l85i3q
-LdL5TchFPjd70ERfrdv7+jnHngQPAFnmfvCp9+U4EHwV42eBOX4CbAKJj9S6uPd1s533xNp5T6x9
-pvlmO++J4X/pKYFFva+8j/QqXtIxfCX8s8xTOlYee0bR4TUXluApNbLhGP7Vq/hY+G+Z93WzfWnv
-6/123hNr5z0xND/DeTaBDzhuKe/rg3beE2vnPTEQjjNHS3lf+fqhuRXN+GfVva/QN0NfDW3kdRnG
-JuPeMhim9hKWl/nYNu0EbeVftpbjR1kfAI75lVyh/Di/7QYruScGrZxmwThaZIOabMt9rG3fLrAa
-3pe+170EJ/CFBHfDZXtfr6x57+sG+ToB7gFqmPWLFnL9FGXb3WvEZSXvg/2MJ7+f4TXdT2Ac1/sK
-9ZpDt+N1E5D/Z5TuJzCO632pQW41nAaphpPwnkaDMI7rfalBbjWczTSchvcs/MI4rvelBrnVMJZp
-OAvvGPzCOK73pQa51TCeaRiDdxx+YRzX+1KD3Go4l2kYh/cc/MI4rvelBrnVcD7TcA7e8/AL47je
-lxrkVsNEpuE8vBPwC+O43pca5FbDZKZhAt5J+IVxXO9LDXKr4UKmYRLeC/AL47jelxrkVsPFTMMF
-eC/CL4zjel9qkFsNU6AJyP8zSvcTGMf1vm6UudUwnWmYgncaDcI4rvelBrnVcCnTMA3vJfiFcVzv
-Sw1yqyF4X/L/jKeD+wmMP/W+lvve1/8ln8dBeBZvItb3+kl7gmZi8ZF5Xw9q9L7UfwpsZ+LwRrk+
-ln1OHAQrec73HG3gt9n7qsyP88i16n1Vag3l1WjLvnJbslowZ6ucp630byT1dj7TIE5xbYk38/O0
-6N5XNX4uj4fmfaXzmbcKnXhfnXhflkMu8rnZg6YWMAy8ztSY9wT6y9ud74f2c58D4Ci4D5zPfIaN
-ZDkrP0680jn+Vs6hprXy3pdz4YOg2jrkx1yFHBo/C8zxE2ATSHyk1sW9r9c2897XZt772sx7X5t5
-7wv/S08JLOp95X2kd/GSZvGV8M8yT2m2PPaMosO2DUve+5rFv3oXHwv/LfOwXtu8tPf13c2897WZ
-977Q/Awn3gSOc9xS3tfxzbz3tZn3vkA4zhwt5X3l64fmVjTjn1X3vir7amgj+3NoO+PeMlbifVVy
-hfJqXBdBKzIXjKNFNni9xPC+9L22NYgT+EKCq2DZ3tc/XPPel57XCbCNjkANs37B9buq3tccT35z
-eE3bG4RxXO8r1Gsr9XK8bgLyz1Hazv1BHZZD37K+IWbXM44V9q1G8BToLMesCrX+LaQa5FbDadap
-hpPwnoZfGMf1vtQgtxrOZhpOw3sWfmEc1/tSg9xqGMs0nIV3DH5hHNf7UoPcahjPNIzBOw6/MI7r
-falBbjWcyzSMw3sOfmEc1/tSg9xqOJ9pOAfvefiFcVzvSw1yq2Ei03Ae3gn4hXFc70sNcqthMtMw
-Ae8k/MI4rvelBrnVcCHTMAnvBfiFcVzvSw1yq+FipuECvBfhF8ZxvS81yK2GqUzDRXin4BfGcb0v
-NcithulMwxS80/AL47jelxrkVsOlTMM0vJfgF8ZxvS81yK2G4H3JP8fTwXaeh9RhuY99vD8udt8M
-+zRXPLc5/z0OXgWflPe+PizXOcwbmyjre311c4JmYvGReV/3G9bzjDOYzJFsV+dxof3oCvPzXwrr
-KW9jhy+yvl8u+3w0CH7bva+D1MHn4GrrkJN8frwGDnDMURDyEfJzvZu/j2X7GZPIw+Ra+j5YpdZQ
-Xo22DHmy6kX+sU/9pnnaSr2v+w1PF7avE+vJvXg6P0+L7n1V47e5H9Z7X/caGgv3Gr5U+Mw6YdyY
-5SKfmz1ooq/W7X3do1LOh7bT+ckyPGn5ceLdYCXX/laOt4983Lwvr/8hkvYN6jYEwhL8J+6NhSM9
-Q42jPSVBvL9wvXt/Yba7JBpH+d1chyUct4ENs90jjTe69zeyf+M1cJXyVY4JntLV8tjjOfrDCViH
-c9iWV7v3FK51D8E5VAjHHelJtS523Cs9Q4VjPXtAKTvuGMeVOOlixx3rGWl8pWd/I/XMdJqj/eXj
-qtU1Xz80U98h6j3U+Bx1aAGhbz9P3AlC3wx9tYNt9i+67IL7Wi9lwTC1N1lVxHT15Hwe67IVGD8K
-DoCjoJIrlFfjuqg2ji42pq70bx7nGnYXtq4T6wpzDYKre5ne1/vb7w8fPPiVF9byd8Dm6Ay271b+
-oYZZv6A/rar39SE8HzY08MwkjBdy5du4Hx32Ly6Hv+Y7cd2ydf5Y9wnHqvnrlAdBqFcHXO7TBOT/
-kPvCNu4P6rCcPzbE7Loq3pca5FaDY1WqoRHeDfAL48a6NNT6HTA1yK0G7yuphg3wPgK/MN5Ql4Za
-vwOmBrnVYLumGh6Btw1+YfxIXRpq/Q6YGuRWQ3umoQ3edviFcVtdGmr9Dpga5FZDR6ahHd4O+IVx
-e10aav0OmBrkVsP2TEMHvNvhF8YddWmo9TtgapBbDV2Zhu3wdsEvjLfXpaHW74CpQW41cOst98ku
-eLvhF8ZddWmo9TtgapBbDcVMQze8RfiFcXddGmr9Dpga5FaD4196bRbh7YNfGBfr0lDrd8DUILca
-HPtTDX3w9sMvjPvq0lDrd8DUILcadmQa+uHdAb8w7q9LQ61/86gGudWwK9OwA95d8AvjHXVpqPU7
-YGqQWw1fyDTsgnc3/MJ4V00abNM28Kn3VSj8mry6hGdx+/hM95ONpZ4Exkk5n7MQs+uZWp7R889N
-+zhoCNif0r8tW/zb+XoHtXhf6l/POXey/iLrUO4kHgQrmf96DvuLz3i5+jq9KS8Lv832Mlu/A5CS
-LB4zCL4GngQu5qSljFq+93WQfVfifYV8hPw4jyxxzjO2Pw+Da8n7qtQayqvRlvm+W6Tq5Xb9a3+f
-s1LvS2/n8wnWJ/6X5dw8Lbr3VY3f5n5Y3lc6n/lSYRfe165kbtOY5SKfmz1o8loYLreHGn0WtG2M
-vVaMvZ5C+7n9ADgKnLfRhcl36seE8mrM8bdyXrk/bt6X1/9S3tf14lDj1WJJFK4X9yf+l54SWNT7
-yvtIh/CSRvGV8M8yT2kU7hI5HQW2bVjy3tco/tUhfCz8t8zDul5c2vu6URwqzBb3gHnva5bjSnSQ
-xfhmi/h1Rfw68AyCNgFztJT3la8fmhvRjH9W3fsKfTP01Xw/z/ftXvgFI/TeZFUR09WX9L4quUJ5
-Na6LoFWBpDcbR/Ox93rbtwusxt886nvtSLAu8b8s58ZUZsnp8rlSmrvOpDjzQnkzq5k/P7Gx6cW1
-7n3pefE/6hrX+/JZugO/aWeC9Nk6tGsL7RpipJyxHc2v4+xTwNwau9TqfYV6DcDrsU1A/g7uDTsT
-GMf1vtQgtxo2ZBoa4d2ABmEc1/tSg9xq8L6S5mEDvI/AL4zjel9qkFsNtmuq4RF42+AXxnG9LzXI
-rYb2TEMbvO3wC+O43pca5FZDR6ahHd4O+IVxXO9LDXKrYXumoQPe7fAL47jelxrkVkNXpmE7vF3w
-C+O43pca5FZDd6ahC95u+IVxXO9LDXKroZhp6Ia3CL8wjut9qUFuNTgGp9dmEd4++IVxXO9LDXKr
-wbE/1dAHbz/8wjiu96UGudWwI9PQD+8O+IVxXO9LDXKrYVemYQe8u+AXxnG9LzXIrYYvZBp2wbsb
-fmH8qfe13L953EI+XcKzuH281PNk40wxgXFS9jpoA/qFIaYY3fv6fI3el/rXI2iE9RdZh7LPaIPg
-k+59hXyE/DiPLJGXteh9VWoN5dVoy3zfJQVJn3bOvY/YcdZ7b+rJzn/fb30p3Y+fCu73U3AFuF9L
-6Td/615vZ1+C9fRF8XR+nhbd+6rG34Duh+V9pfOZLxW+gvf1lfL8JuQin5s9aGoBw8AxRo0+C4bY
-djHm0k7ux2H7AcpHgX5uI+t9rMlyVl6NOf5Wzief84TOcuxcr5dYcAU9VA/8dRgPgmrr0L/NVcih
-8bPAHD8BNgGv/6W8ryO9vPfVi8/VWyoc6eW9L/wvPSWwqPeV95Gu4SVdxVe6yjHPlLmvwl0iHgW2
-bVi8Dl1sy6v4V9fwsfDfMu/rCAkf4rfFjnull/e+ennvC82B7xjHlTjpYscd6+W9r979jdQz02mO
-lvK+8vVDcyOa8c+qe1+VfTW0kX0+tJ1xrn/tpVhezmTxOrZ0Avumy1ZgnH/vq5IrlFfjughaoTxD
-mhJu2y4f72N7P+gCq+F96Xu9mGAdvpDYnR9Ta/S+Nq5570vPi/9R17jel8/SA3hNIwnSZ+vQri20
-a4iRcsZ2tH95bdbrfYV6DcPreZqA/APcG0YSGMf1vtQgtxo2ZBoa4d2ABmEc1/tSg9xq8L6S5mED
-vI/AL4zjel9qkFsNtmuq4RF42+AXxnG9LzXIrYb2TEMbvO3wC+O43pca5FaDY3Gah3Z4O+AXxnG9
-LzXIrYbtmYYOeLfDL4zjel9qkFsNjtdpHrbD2wW/MI7rfalBbjV0Zxq64O2GXxjH9b7UILcaipmG
-bniL8AvjuN6XGuRWQ1+moQhvH/zCOK73pQa51eDYn/aHPnj74RfGcb0vNcithh2Zhn54d8AvjON6
-X2qQWw27Mg074N0FvzCO632pQW41fCHTsAve3fAL40+9r+V6X58jny5h3mgf1/cq9SYwTspeB23g
-YXtf+2r0vtS/Hn2HWX+RdSh3Eg+CT7r3FfIR8uM8skRe1qL3Vak1lFejLUM/tupF/rFPO2fbx9px
-tgushvelt/NygvX0RfF0fp4W3fuqxu+8+mF5X+l85kuFb+F9fas8vwm5yOdmD5pawDCwPdTos2CI
-bRdjLu3kfhy2H6B8FOjnNrJ+mTVZzsqrMcffyvnkc55g/zOmu+S9iYfqfR2Ev5rv5fbQv81VyKFx
-pfeV+Egk7Rv8NgTC4rXgwjhfuN7He199vPfVVyLen/hfekpgUe8r7yMdwksaxVfCP2t8hnNuAqO9
-6dgzSmzbhiVlTr2vUfyrQ/hY+G+Zh3Wdyql1seNu9PHeVx/vfaE58M1yXIm6LnbcbB/vffXx3hcI
-x5mjpbyvfP3Q3Ihm/LPq3ldlXw1tZJ8PbWcMdQKGqb2E5WU+tk07gf3RJfTTvPdVyRXKq3FdBK1Q
-LxhHi2woXyN/bUxd6d886nsdSrAOX0jszo+pNXpfm9e896XnZfse4h9qmPWLFnL9FGXbne6cLCv5
-1r3P0sN4TYcTpM/WoV3lCjFEZ/r5x3aVt1ID1y1b53W6TzjW83yd8iAI9XoJXvdpAvIPc284nMA4
-rvelBrnVsCHT0AjvBjQI47jelxrkVkPwvuQfxms6nMA4rvelBrnVYLumbfEIvG1oEMZxvS81yK2G
-9kxDG7zt8AvjuN6XGuRWQ0emoR3eDviFcVzvSw1yq2F7pqED3u3wC+O43pca5FZDV6ZhO7xd8Avj
-uN6XGuRWQ3emoQvebviFcVzvSw1yq6GYaeiGtwi/MI7rfalBbjU4jqbXZhHePviFcVzvSw1yq8Gx
-P9XQB28//MI4rvelBrnVsCPT0A/vDviFcVzvSw1yq2FXpmEHvLvgF8ZxvS81yK2GL2QadsG7G35h
-/Kn3tVzv6wXy6RLmjfbxEr7XTF8C46TsddAGmiueiWp5Rs8/N+3jHEPA/pR6DIv/zeP9hlM86w0m
-14D8yg1anCMcAEeB34Q6xXobO7yRK3cSD4Lfdu9rsfnuQeoXcpLPTwttVS0/1xngZ2xMk8jD4Fr6
-m8eYbRnyRK0XzNnsl/bTLrAa3tf9hjf5+z5xir4p3szP06J7X9X4be6H5X3d47vB9/jO/WfWCWO+
-d1/ORT43e9BEXy0MgzagRp8FQ2y7GOf7tvscAF77fsfoJOvt7PBmrrwac/zgKXzcvC+v/8uti3tf
-R3out4728F37npnmIz1Xmq93X2me7Z4Ri37rfrb7B603uq+0sn/rNXCV8lWOeYa22QSulseeUWLb
-Nix57+tq99vN17ovwzn/rXv/BvEyY9Zix73Sc7n5WM/bYP5b937va6lv3R/r+UHrKz1XWqlnptMc
-LfWt+3z90Ex9L1Pv6t+6r+yr+X4exib7di331U7287pwCf00731VcoXyalwXQSvUC8bRIhvUZFtW
-jqkr9b7m+K7r1nXiBN+OEtwV6/ne11/87vBa/97XCduU8YwaZvf2FnJd6TutxPv6sOE43wn5Hs9M
-wvj4Aq58G/eX25VHhbq9L79bYr06qJfjdROQ/0PuC9u4P6jDcuC1viFm1zOLaaj1W/dqkFsNpzMN
-J+E9Db8wjvutezXIrYazmYbT8J6FXxjH/da9GuRWw1im4Sy8Y/AL47N1tcVyvvcltxrGMw1j8I7D
-L4zH6tKwnO99ya2Gc5mGcXjPwS+Mx+vSsJzvfcmthvOZhnPwnodfGMf91r39QW41TGQazsM7Ab8w
-jvutezXIrYbJTMMEvJPwC+OJutpiOd/7klsNFzINk/BegF8YT9alYTnf+5JbDRczDRfgvQi/MI77
-rXvbQm41TGUaLsI7Bb8wjvutezXIrYbpTMMUvNPwC+OputpiOd/7klsNlzIN0/Begl8YT9elYTnf
-+5JbDX+cabgEL/+/PzwPqUM94V652H0z7NNc8dzms9px8Cpw/jtQmn+2fLo0/zdQLaWGdfyUvGOw
-btPMXxIWfuQ/LG+8/vrzSEzmaWHt9rAf3tSDbaV0DrCe7TRv/jn3OYrlZf5vaTzPt8AQ8NnDtUtY
-e5amdFNhud6X3/uyzmHe6HlmuqdaSz0JmonFR/ate72DWrwv9Z9Cu3/X8Ua5PpY7wSD4pHtflflx
-HrlWva9KraG8Gm0Zrn26xII5W+U8beXf+3qTv3MUpxL/S68nN0+L7n3J95v4HW8elveVzmfe4ltf
-Ip3feD1XatuDphYwDNqAGvOeQH95u+NgaD/3OQCOAv3uk6w/z5osZ+XHiXeDlVz7WzleTR837yvx
-kVoX976uFy+3Xi3OiObrxSuJ/6WnBBb1vvI+0iG8pFF8JfyzzFPye1+OPaPk1bYNS977GsW/OoSP
-hf+W/f81Xi8u7X3dKF5uni2+Dea9L7/3tZT3NVvEryvi14Hg0ZmjpbyvfP3Q3Ipm/LPq3ldlX833
-83zf7iUpgmFqb7KqiOnqyb3NvukS+mne+6rkCuXVuC6CVqgXjKOkOpr3pe+1I8GJxP+ynBtTa3zv
-i+99rXHvS8/rBHn0bx2oYTbmMUauqvfVgd/Vgd+0M4FxXO8r1GuAejleNwH5O7g37ExgHNf7UoPc
-atB/SjWchPc0GoRxXO9LDXKr4Wym4TS8Z+EXxnG9LzXIrYaxTMNZeMfgF8ZxvS81yK2G8UzDGLzj
-8AvjuN6XGuRWw7lMwzi85+AXxnG9LzXIrQb9p7RPnoP3PPzCOK73pQa51TCRaTgP7wT8wjiu96UG
-udUwmWmYgHcSfmEc1/tSg9xquJBpmIT3AvzCOK73pQa51RC8L/k78Jt2JjCO632pQW41TGV5uAjv
-FBqEcVzvSw1yq2E60zAF7zT8wjiu96UGudVwKdMwDe8l+IVxXO9LDXKrIXhf8nfw/LMzgfGn3tdy
-va8t5PM4eQ3zRsddfa+ZYoJmYvGReV96B7V4X+o/hfYR1m+U62O5EwyClcx/PYdzDOZmyXykl5jH
-0Ko+5cv8+h2AlGRx/0HwNfAkcOkHLWXU8q17n4EPgmrrPn5To5wh5vzZe1+V+XEeuVa9r0qtoWw7
-DIKVtGXIDadZMGdbbe9L32lfglOJ/2U5N0+L7n1V42+g4g/L+0rnM2/xrS+Rzm+8niu17UGT10K9
-3pd+t/OZfazJMveDtPw48W6wkv6yleO9rj5u3lfiI7Uu7n0d6eW9r158rt6Z5iO9VxL/S08JLOp9
-5X2ka3hJV/GV8M8yT8nvfS3lfV3Fv7qGj4X/lnlfRxhIl3zvq5f3vnp57wvNwcM6xnFLeV/Hennv
-q5f3vkA4zhwt5X3l64fmVjTjn1X3vkLfDH01pvdVyRXKq3FdVBtHSVm4V676e1/6Xi8mOIEvJLgb
-LvO9rxMb+d7XGve+9LxOkMcXWVPDBffzpyh7H2wELit572sAr2sAr2kkgXFc7yvUa5h6OV43AfkH
-uDeMJDCO632pQW416D+lGk7CexoNwjiu96UGudUQvC/5B/CaRhIYx/W+1CC3GsayPJyFdwwNwjiu
-96UGudUwnmkYg3ccfmEc1/tSg9xqOJdpGIf3HPzCOK73pQa51aD/lPbJc/Ceh18Yx/W+1CC3GiYy
-DefhnYBfGMf1vtQgtxomMw0T8E7CL4zjel9qkFsNFzINk/BegF8Yx/W+1CC3GoL3Jf8AXtNIAuO4
-3pca5FbDVJaHi/BOoUEYx/W+1CC3GqYzDVPwTsMvjON6X2qQWw2XMg3T8F6CXxjH9b7UILcagvcl
-/wDPPyMJjD/1vpbrffm9r+PkNTyLO+7qe5V6EzQTi4/M+9pXo/el/lNoP8z6jXJ9LPucOAhWMv/1
-HM5/f5u9r8r8OI9cq95XpdZQXo227Cu3Jauo3pe+18sJTnFtiTfz87To3lc1/ofpfaXzmbf41pdI
-5zchF/nc7KExWkC93pd+t/OZl1mTZe4HH1/vy7nwQVBtHfo3KcjenTN+FpjjJ8AmkPhIrYt7X9f7
-eO+rj/e++maar/fx3hf+l54SWNT7yvtIh/CSRvGVRjkmeEqj5bFnFB39ICwL3vvCvzqEj4X/lnlY
-16ncUt7XjT7e++rjvS80Bz6/97WU9zXbx3tffbz3BcJx5mgp7ytfv9Fe3vvCL9Qz9D+MmO/Qt58n
-7gShb4a+GtP7quQK5cfRsRus5J4Y+hmnWTCOFtnQBmzLfaxt3y7ge/Qr/ZtHfa9DCU7gCwmugmV7
-X3zva417X3peJ8jZIdbUMJr3NYzXNYzXdDiBcVzvK9TrJerleN0E5B/m3nA4gXFc70sNcqtB/ynV
-cBLe02gQxnG9LzXIrYbgfck/jNd0OIFxXO9LDXKrYSzLw1l4x9AgjON6X2qQWw3jmYYxeMfhF8Zx
-vS81yK2Gc5mGcXjPwS+M43pfapBbDfpPaZ88B+95+IVxXO9LDXKrYSLTcB7eCfiFcVzvSw1yq2Ey
-0zAB7yT8wjiu96UGudVwIdMwCe8F+IVxXO9LDXKrIXhf8g/jNR1OYBzX+1KD3GqYyvJwEd4pNAjj
-uN6XGuRWw3SmYQreafiFcVzvSw1yq+FSpmEa3kvwC+O43pca5FZD8L7kH+b553AC40+9r+V6Xy+Q
-z+PkNTyLO+7qe830JWgmFh+Z93W/4TZzhsHkGdpnauRmz4LO4w+Ao8BvRN1mvY0d/gZxKDvfGAQr
-ec73HOXn+UIvseCR3+lNeZmP1fcy+A4wdnH/QfA18CRwcU7QUkYt730dZF+fg6ut+/itMj+cP3vv
-K+Qj5Mdv2ZTa2cEk8h+R19r3vm4jK2gN2m2HQbCStgx54jQL5myV87SV/s3j/Ybehu3rxG36ouil
-mRv4ggb/XwylQnTvqxq/zf2w3vu613CLb3H1NXxmnTC+leUin5s9aPJaqNf78jtGtzh+OxccWU6+
-/2X5cbAbrKS/bOV4r6u18t7XYmOAY0Po3449HWXtxs8Cc/wE2AS8/oe2LO59HekZ2jLaUxLtR3r2
-t1/v3t8+210SW0Y5x9MgLMG32sCG2e6RLTe6929h/y3XwFXKVzkmeEp+78uxx3P0hxOwDudoJL7a
-vaf9WvcQnEPt4bgjPWhe4rhXeobaj/XsAaXsOL/3VaKui/Ed6xnZ8krP/i3UM9NpjvaXj6tW13z9
-0Ex9h6j30JZq3ldlXw1tRLfN2s64twyGqb2E5WU+tk07gX3TJfTTR4kPgKOgkiuUV+O6CP0MmgXj
-aJENaorhfc01FBu2rhPv8a0vUcyPqTX9zeP72+8Pv/FXf7jmv/f1HjncSiNTw6xftJDrp9huu3uN
-uKzkva8PG27ynZBfcp8VxjcXcOXbuB8u21XeSg20NVvndbpPOFbNX6c8CPx+i/XqoF63WDcB+T/k
-vrCN+4M6LOePDTG7nllMw3K+9yW3Gu5kGm7Bewd+YXyrLg337t3jjPN1XywPcqvhLus0D3fgvQu/
-ML5Tl4a5uTklZMcupkFuNXhEquEuvHPwC+O72Xlsx1rbYjnf+5JbDfagVMMcvA/gF8ZzdWlYzve+
-5FZDI/0z1fAA3saGbeuE8YO6NCzne19yq2FDpqGx4cOGDfAL48aGkP/ltMUHH3xA7WrrD3KroS3T
-sAHeNviF8Ya6NPzqV7+qWYPcamjPNLTB2w6/MG6rS8Nyvvcltxq2ZBra4d0CvzBur0vDcr73Jbca
-tmUatsC7DX5hvKUuDbdv3665LeRWQ2emYRu8nfAL4211abh1yxG4tj4ptxq6Mg2d8HbBL4w769Kw
-nO99ya2G7kxDF7zd8Avjrro0LOd7X3KroSfT0A1vEX5h3F2ThjCGNDOeF2kD7+nhWe048avgk/S9
-r5vUN8wbHftnup/cUupJ0E4stuRzFmJ2PVPLM3o/O5pj78P7wBDYAdJvii/+rXu9g1q8L/V7Vft3
-HXpfodzJtkGwkvmv5yj3kfyc5LfK+wr5CPlxHrlWva9KraG8Gm2Z77uV134/7dwF0n45/32/9aW0
-/fkp6b8/ZX0FuF9LqdD4NLHH+k0/r59Cyf7X2/D5BLeJxcP1vqrxc2k8NO8rnc/0NezC+9qVzG1u
-ZbnI52YPmlrAMPA6U2NHLja3bufSzp5B3ecAOAr0SL2b+rexel+hvBpz/K2cV+6Pm/eV+EhbFve+
-rheHtlwtlkT79eL+xP/SUwKLel95H+kQXtIovhL+WeYp+b2vpbyvUfyrQ/hY+G+Zh3W9uLT3daM4
-1D5b3APmva9ZjlvK+5ot4tcV8evAM7T3JmCOlvK+8vVD8xY0459V975C3wx9Nd/Pw9hk3+4tg1vs
-XsLyMh/T1Zf0viq5Qnk1rougFRkLnqFIdbhXrvp7X/peOxK8hy8kisv2vk5sbHpxrXtfel7vkUf/
-1oEaZmMeY+Sqel8d+F0d+E07ExjfXMCVb+MwBjeiq17vK9RrgHo5XnuvlL+De8POBMZxvS81yK0G
-/adUwy1476BBGMf1vtQgtxruZhruwHsXfmEc1/tSg9xqmMs03IV3Dn5hHNf7UoPcagjel/wd+E07
-ExjH9b7UILcagvclfwd+084ExnG9LzXIrYbgfcnfgd+0M4FxXO9LDXKrIXhf8nfgN+1MYBzX+1KD
-3GoI3pf8HfhNOxMYx/W+1CC3GrawTseHdni3oEEYx/W+1CC3GoL3JX8HftPOBMZxvS81yK2G4H3J
-34HftDOBcVzvSw1yqyF4X/J34DftTGAc1/tSg9xqCN6X/B34TTsTGMf1vtQgtxqC9yV/B88/OxMY
-f+p9Lfe9ry3k8yZjf3gW91ov4XvNFBO0E4uPzPv6fI3el/pvo32Etd5XKHeybRB80r2vkI+QH+eR
-a9X7qtQayqvRln30Bb0MlgVztn1s8Pm+C6yG96W3sy/BbfqieLjeVzV+Lo2H5n2l85m+hq/gfX2l
-PL8JucjnZg+aWsAwsG3U2JGLbRe3c2lnczP3OQD0vvRznc/sY633FcqrMcf/uHpfiY+0ZXHv60gv
-73314nP1ltqP9PLeF/6XnhJY1PvK+0jX8JKu4itd5ZjgKV0tpmPPKG1m24ZlwXtf+FfX8LHw3zLv
-6wiG0JLvffXy3lcv732hOfD5va+lvK9jvbz31ct7XyAcZ46W8r7y9bta5L0v/EI9w2rvfYW+Gfpq
-vp+Hscm+jeQEK/G+KrlCeTWui6AVmQvGUVKWXKvhvyXavl3AMXWlf/Oo7/VigvfwhUQ93tfGNe99
-6Xm9R85eZB3T+xrA6xrAaxpJYBzX+wr1GqZejtc+a8o/wL1hJIFxXO9LDXKr4U6m4Ra8d9AgjON6
-X2qQWw36T2ke7sB7F35hHNf7UoPcapjLNNyFdw5+YRzX+1KD3GoI3pf8A3hNIwmM43pfapBbDcH7
-kn8Ar2kkgXFc70sNcqsheF/yD+A1jSQwjut9qUFuNQTvS/4BvKaRBMZxvS81yK2G4H3JP4DXNJLA
-OK73pQa51RC8L/kH8JpGEhjH9b7UILcagvcl/wBe00gC47jelxrkVkPwvuQfwGsaSWAc1/tSg9xq
-CN6X/AN4TSMJjON6X2qQWw3B+5J/AK9pJIFxXO9LDXKrIXhf8g/w/DOSwPhT72u53pff+7rJ2B+e
-xb0P63uVehO0E4uPzPvaV6P3pf7baD/MWu8rlDvZNgg+6d5XyEfIj/PItep9VWoN5dVoy2pztn30
-kfw87bOllb33pbfzcoLb9EXxcL2vavxcGg/N+0rnM30N38L7+lZ5fhNykc/NHjS1gGHQBtSY9wRs
-F7dzaf9G70s/1/nMy6z1vkJ5Neb4W8vcj7C2/6nDv/HJeRNr9v3PkEPzVvk3j17/S/3N4/U+3vvq
-472vPt776uO9L/wvPSWwqPeV95EO4SWN4ivhn2Wekt/7WvK9L/yrQ/hY+G+Zh3Wdi3cp7+tGH+99
-9fHeF5qDh+X3vpbyvmb7eO+rj/e+QDjOHC3lfeXrN9rLe1/4hXqG1byv0DdDXw1tZJ8PY5Nxrn/t
-pVhezmSxbRr6oz9uBfbNR8EBcBRUcoXyalwXQSs0D8370vc6lOA9fCGBM9SQ/R15TX/zeGLj5jXv
-fel5vUdiD7Gmhlm/YIxc1fe+hvG6hvGaDicwjut9hXq9RL0cr5uA/MPcGw4nMI7rfalBbjXoP6Ua
-bsF7Bw3COK73pQa51RC8L/mH8ZoOJzCO632pQW41zGV5uAvvHBqEcVzvSw1yqyF4X/IP4zUdTmAc
-1/tSg9xqCN6X/MN4TYcTGMf1vtQgtxqC9yX/MF7T4QTGcb0vNcithuB9yT+M13Q4gXFc70sNcqsh
-eF/yD+M1HU5gHNf7UoPcatB/SseHdni3oEEYx/W+1CC3GoL3Jf8wXtPhBMZxvS81yK2G4H3JP4zX
-dDiBcVzvSw1yqyF4X/IP4zUdTmAc1/tSg9xqCN6X/MN4TYcTGMf1vtQgtxqC9yX/MM8/hxMYf+p9
-Ldf7eoF83mTsD8/iXuslfK+ZvgTtxGJVva+fwnEFpO/XzP/NY0up0Piv2f6vgH8/tom1y0v7el78
-nxv+195vsn737t/d+w8e9L8488xrpW/8090v/kvWzz2658X9rL/5n4Zf/Hf8/hLr/8r+rv9bxfqn
-5fJLLb0vfJnjjjX+rRcOcZ6/x/o45/37luE5wu/yXmP/QuOC5R9vLRXObELXevDOO+/8QT/rNkAq
-s+dUumo2B/kn/NBIuZ1/vsg6lP2+5RfASny5MOdZK3Pz16nPQVBt3cdvIVcd5dhchbm5xx4CYQnv
-gmxiw+/3/4eG3++fLZQ+91zhj3Y8V1i/6/+3dy7gUVXn3t+zB5KZMTAz4WJUJAGxTgIkIwmKcpuA
-4A1KoGDR46cBscVPUFRabz0YFJUjilFAkKrFitUGLxyPek69HFOvtbWtp4qPVo/FIl6qtiiI4o3v
-99971mSym7kkJGr9up788677+653rbX32uvda89o64P4W+BhX2tcY5PmJ4+fvP5psWtslR1FHTw/
-WGNACTD9EKFfaginy2PklGyDkuDRoxZv0rX41e+qT+2SM32S/hxqeHXFGDCywrrVc+hEIjQ2+4Fc
-77L1pqEBoHzVnfw9stvhfwP4Gs9p/55+A+042icdGmfGrcbaEtsPhlsRv7A/14H9rZ7+AVbAz+kh
-/2Drc3uI9ak91PrYrrS22XHrHftga6s9zHrFrrYesGtAtbWRcBPxt5J+s11l3UTetZRZQ9lV9mDr
-ajtmLbcPsq60v2UttQdalzsosy6zhX2I62NdYfcivdi6yo6SP2I12mFrpd3DWm0XWdfbe1k32CHr
-drvQussusO63u1tP2N2sZ8Gf8L9J3HukfWAHrJ120NpNmUJ/hDZErZC/mPb0BSW0TehHO/2p77yP
-RweaG1JP+hzT2FR8puvmkrTrpuanCV+Jfxj4Jl03dd3LdM1UvJnj0pXRofzmurkf/gg4FqU+hKIP
-SYanEl5FeCZh6ds4Mz79REyNrfJNja0EK3ym3Cwyz8tRblZsnm927HQHptwiyk3MUW5RbILvoiSO
-h/9CIxTUyNUX//rYQN9zMcsXKt9sHVv+S2tF+c+sP5dfZR1aca61omKOtb1iuvXY4DHcC4ZbFw8d
-bU2tnG7dUznH6lF1rjW76irrnqqfWbuqfmkdHv+TdVbc8q2LD/A9GZ/gy6YLpT/lYGJKF1vilnV6
-jjZtiZ/uez0+z4HRxQ7KrchRbkd8pW9HfJUDU+4TyqkPs8n5Cfe8T+L/DR5JySl+b+QotyP+Brze
-BG+lyr1OuZ4Mpmz8Xo/3tLfEww6MnE9RriZHuafiw+0nk8jW1zfHZ9pnxy+0D4//2P6k6hf2PVWb
-7FOq3rN7VPn991Tu7Z9WeZCfPvbfMmSC/7HBo/07Kg7yr6jY2z+iwu//c/l79oryTfak8l/Ye5Xf
-YD8Xu9C+NXa8fVFsuJ2tTUpf5KDGNm2aHWOdlqNNs2Nhe1aspwNTTvPsrRy6nxp7kzn2hgNTTvP1
-kWQ5XeOMM/OggIhjYg/4Jsfup9z9vuNi9/lOiP0XeMgnfcYpa5wpM4GI+tgWX33sNd+CWKF9ZqzA
-XhYbbF8Rq7Dvik2yX46dYReXX2VPLW+y15Q/ab9R/qo9smKHfV1FwP9hRYn/8cFDWTsN9y8eWumf
-Ulniv7sy4A9W7bBPqnrVvrPqSXt7VZM9LL7cPi1+hn1dfLL9YLzCfiA+2H4hXmBvihfaW+Ov+bbG
-t/jeiT8EHsG/Bqz1bYqf43shvtD3QHyK78F4nW91vNJ3WryHrzr+V2tH1bPWnVX3WSdV3WCFqi6z
-7q48x6qrPMVaPHSyRZ9bjw+ebO2sOMW6ruIca2TFZdab5TdYa8rvs6aVP2sVl79nvRLr4bs7NtR3
-RazOtyw2xXdmbCFtPwcdrAVr0NcjzrzPpOMTYo+h2yfR8RPo+gnfMbFf+o5Fx5lsGOZepPWc6jTX
-ZHWHuVbLPyiJPVk7enmZcGfcB42siNlq7TiQCN2bNaYmQhmmqXVktvd362n0dKB1ZCDD89wFvyk7
-4r6m39WK3lB7dO2qJbEjrA1/GXveXsOO2Nj0l7EnXjvyiAj0/GPHHzGb9AugTcoP3eChdyTDR57Q
-b9xJlJs+48hxF1LPDOhq6j0OKj6TSBe9l/ze57nqhJWf3YTyqjeQKPBNRx9HAa1pu4kCuQ1NFQ+5
-eGDsjBndx/I9RmdaGjrv0ti981++f8xh1dXN+P999fX3jf2v+S8/GEq4Y6WEOjTnNXa8dQ0gLgBm
-A/WN8pg4sw5IH4czSD8RGGeuDxEiltj7gh7WLbZtPQ3+Bnr6e4B9PYiRNow8w8g7jDIxp+wo6pAs
-44GRJZ23GVfk6VR7zcUo+mLbh4yC/C3zTbwMX8RqiCVlI1uHz+mbudaDSlRPdyD+F7Om78kaV3Io
-bPi2R4Z8v1GZLoPGhiuDH74F8Bfk93dIhny/USkZxFt60F6DK0MBfIPwF+Qv6JAM+X6jUjKIt2TQ
-mHNlCMK3CP6C/MEOyZDvNyolg3hLhnBKhiL4huEvyF/UIRny/UalZBBvydArJUMYvr3gL8gf7pAM
-+X6jUjKIt2Tom5KhF3z1HCjI36tDMuT7jUrJIN6SoV9Khr7w7Qd/Qf6+HZIh329USgbxlgylKRn6
-wbcU/oL8/TokQ77fqJQM4i0ZBqZkKIXvQPgL8pd2SIZ8v1EpGcRbMuha6M7NgfA9EP6C/AM7JEO+
-36iUDOItGXTtd2U4EL4x+AvyH9ghGfL9RqVkEG/JMCQlQwy+Q+AvyB/rkAz5fqNSMoi3ZKhKyTAE
-vlXwF+Qf0iEZ8v1GpWQQb8lwcEqGKvgOg78gf1VeMqhPi0Bb36hsJH4J0HpzcMLNR9AKJAq7lUBV
-Tms0xSFKpCZR6MQpHEj47AS0Bpg8v8Mvt6GpaQxNcNZ1hire5EskErv7JNw9F63/tBYblARLDz02
-JF2LX/WcDEYAZHEoJEVVi8asHPU71PwzOlA54ydvwwzCJ4KLVTnO7C9H8FfHbvJVx35tDazob10y
-pL+1tbK/9Vz81+AmX2ucbZPmJ4+fvP7q2Nm2yho+0rvxU21DWjtrCSddQ8ovUTQHpHvJOxFIQTsg
-6qeKRMtalzetxynZdc3jLtg+kDX+2kQgESioIVL1ODpfviVNp85YYO1Za01iF3CcNY3/7HklAg1r
-oFcC3G71iRAC460zrfnWAv6fYZ0KFlplVkPz+jFWdPEYq+9jSfqaQ5vHF45VfMPwvkl6oEMTB9W4
-9NvjHGolprr0qRNcajWMhVXStfiLiZEuJEtJ0g9x7l2KV9w0sIAM0pfXNaogrtDqRjtmWfOs03gG
-OJv/HXNLEzO1lEs9s9T/4VWnoplPVTqcIs+4lK8nuJyT4R//4cIxuxgMJn63R1hTTms0OfWf3Nxk
-/e9GPtFjiqMH0aP/x+WbbJ5lyhv69i3dR4mfSTdUZeVM2FDTDlP+N5PeHKny5y2cP9ctwTuBP3Qe
-W1JzSE2YDpaCDQzcntDXoGVQ1dvU9GLtjBmbapW2P2GNpUkg3Znnqnoi2xpnUrYgvRi/KPPXCXeD
-ypk51oM5NpFwA1gIvNe2ikTu+aO5QDbTB6m5oDYdbCWGz8o6Ynn3gny5xqyR1+hQetyMnqTDN6Bl
-0HQdKk06VFwmHdaRdjCQM/UbfWwm7nng1Uf/RH425Jebe42XDfmmiwrGy4Z83+KPxsmGfC9UNuR7
-oLIh/5h02Y7/SP5stK89YLxsyH9sHjxeNmRR2ZCdMHxKSJcNWXy9ew69E+23IV9I23V93wCVPVHh
-ZUD6+ibZQmTvmAEyUTMuUEGrfbeRhAPJsidCjTPzM0LEtNjo4LTY3ECi4uHCnw55uLBb1cOFH8Tn
-Bj6Ijw62RjREWog8IfKGpsWiYHRwFHWIxxhQAkw/ROiXOwj3AkVAY9zIKf+gJJjVtXiTrsWvtqg+
-lZXrDeRn7DtzZQ7U8OqKMWBkhU3DQP6Jt/Sm61AM9AOad9nOhHwVNuSv0ZzuYhvyhey73YldVVjF
-dWAVa+jrsb/+hEXDLdiQ12NDvhUb8s+wId+ODfnn1lZ+B/EVewP24zvABmzITdiQf44N+XZsyLdh
-Q/4ZNuRbsSGvx4Z8CzbhddiQf4KN+CbsxWuxIQtrsB8L1xB3FTbkZaRfgQ3538i/FBvy5diQL8WG
-vAQb8iXYkC/GhnwRNuRF2JD/FRvyj7Ah/wgb8r9iQ16EDfkibMgN2JAXY0Negg15KW34N2zIV9Ce
-5aCRtgkraeeFnWJD1nVSc+YOqJ5LFL4SDAPfpOtmtmumrqVmjutaY65T8pvr5n74I0A2qVEsVg5J
-hqcS7kN4JmFdC4wz11VUiw25T3BqrDfoFTTlZpH53UD2crNi7wZmx95xYMrJhvxkjnKLYk8ELkri
-ePgvNEJBjVx98a+P/TTwXKwhECqvDxxbXhtYUf6twJ/LewQOrfiocEXF64XbK54vfGzwf3MvuK/w
-4qEPF06tfL7wnsrXC3tUfVQ4u6pH4J6qbwV2VdUGDo+fHDgr3hBYF7858GT8icBM6kbMlDM8pQul
-P+XgyYBpk2zI7+Ro05b4O4HX4+86MOVk0+2VQ/c74r2DO+J9HJhysiGrD7PJ+Qn3vE/iY8DYVJ+J
-3/dylNsR/x68vg/mpsrJhrw8R7nX48uDW+JXOzByyoZ8b45yT8XvCz6ZxPFW5r6+Of5i8Oz4p8HD
-4/uFPqk6LHRP1YzQKVXzQz2qLgndU7k6NK3ythB9HLplyBOhxwY/HNpRcVtoRcXq0IiKS0J/Lp8f
-WlE+IzSp/LDQXuX9Qs/FPg3eGnspeFHsvmA2HSp9kYN7U7qQDfnqHG2aHbs6OCu23IHRhebZ3Bzl
-psa+zxz7ngNTTvN1bLJcDfoxzozJAiKOiR0enBw7hHKHBI+LDQ+eEBsBRgWlz7gWKElnykwgXB87
-JVgfmxVcELs8eGbssuCy2IbgFbGm4F2xZ4Ivx/4aLC7vEZpaXhFaUz4x9Eb5SaGRFQtD11UsDX1Y
-sSb0+OA7WTvdF1o89K7QlMo1obsrl4aCVQtDJ1WdFLqzamJoe1VFaFi8Z+i0+F+D18V/G3ww3hR8
-IL4h+EL8suCm+OXBrfFZ4JTgO/FRYCz+ErAvadsDL8R3BB6I/z7wYPzZwOr4XYHT4lcFquNnBHZU
-1QXurBoeOKmqXyBUVRC4u3J7YV3llsLFQ39bSJ8XPj74t4U7K7YUXlexvXBkRUHgzfJ+gTXlwwPT
-yusCxeXzA6/ErgrcHbszcEXs2cCy2O8DZ8Z2BBbEtgfqY/uihxL0NdYZC5l0fEJsPLqdiI4noOsJ
-wWNitcFj0fFodBkAo5LUrB3Nvcjcm8w1uSvWjl5eJtwZ90FzX6F5rdaOA4koAhpTE6EJIN1pHRlI
-BDPszwVTa+BuFFB5OZWvRzH52JaP2xQdL1vvPiu7jZdteUPT9nGyLTdBZVu+HSrbcl/SZVOeofxZ
-6DV9S8fLtjxjU/l4x7YMlW1ZYfFZQbqo+Hqf86oT7bAtU18gEepS27L2LzS+uta2fC3rrEuxF1+A
-3fgC7McXsK67FFzrwTrSmsjTRN4myqwD16bmyXjkVP9L3rbmBnMqZVvuRh457OwONWNS8cav/McR
-jjs53H/meted4MX2eeB8ZBTkP69VWVMPWRu45Dqyqf6DQAkwMlAnoRa+mWQwc1B75FqTujKcD98L
-4S/If36HZPDalvORYVFKhgvhuwj+gvwXdkgGr205mwziLT0sTsmwCL6L4S/Iv6hDMnhty9lkEG/J
-sCQlw2L4LoG/IP/iDsngtS1nk0G8JcPlKRmWwPdy+AvyL+mQDF7bcjYZxFsyLEvJcDl8l8FfkP/y
-DsngtS1nk0G8JcPylAzL4KvnQ0H+ZR2SwWtbziaDeEuGlSkZlsN3JfwF+Zd3SAavbTmbDOItGVan
-ZFgJ39XwF+Rf2SEZvLblbDKIt2RYm5JhNXzXwl+Qf3WHZPDalrPJIN6S4caUDGvheyP8BfnXdkgG
-r205mwziLRnWpWS4Eb7r4C/If2OHZPDalrPJIN6SYX1KhnXwXQ9/Qf51HZLBa1vOJoN4S4bbUjKs
-h+9t8BfkX98hGby25WwyiLdk+HlKhtvg2wR/Qf7b8pLB3NMLuad716vnUfc84LU31CRa1qhfpQ1Z
-+hkB5AzVaknrCLlEIuFQ88+0NV2v5G1lQ1abzf5yBH91rH+wOnZMYGDFTYWXDLmpcGvlTYXPxY8J
-PBfvH2yND4KkhcgTIm+oOvYB5foHDU/p1/iptl02ZMmr9f8zoBmoPyoSuWxgu8b9I9uDja4Y4q3s
-k5cRfs22rDVQrYvT7ZOrCGt9PwmkO7PGrSfy62GfdPsmgTw1ANfKPjmsi+2T0qHsk14dyj4pHUqv
-mXRYR9owIGf6CBuNY6/dTNzzwHu9yNc+ecbmS5P2yUWOffLl5nPGyz75R6jsky9BXfvkIscuOZ/8
-sk9monstvtKxT87ffI1jnxSVfdIJY5csIl32SfH1Prf2TrTfPrmdtuvacQAKlK1KYa3jDgbfpH32
-JtozA2SiZlygglbPrSMJB5JlT4QaZ+ZnhAjOqUY44xrm3GqY86thzrGGOeMKHo60xjVR0orJU0ze
-Ys64RlV2FHWIxxhQAkw/yD45iH7pRVwR0Bg3cso/KAmGci3epGvxqy2qT2XlegP5Gfut7JPq864Y
-A0ZWqv+7+3SMyH5A8+7rZp/8Gs3pLrZPbreW8I27iF/o4QuDnv6oL+Df22f59/N9zvchPrX3931s
-9/dts8t879gDfFv5bsMr9gG+B/gu4APQjYSbiL+V9Jv5lsNN5F1LmTWUXWXv57ua71wst/f2XWn3
-9S3l2x+XO4j4LrOFIHHdfVfwjZgrbdt3le0jv+Vr5Ls1K+3PsU9+hn3yU+yTn2Cf/Aj75E7skx9i
-n9yBfXIH9skPsU/uxD75EfbJj7FP7sI++Rn2SYs2+Hwhv017CkCAtglFtHN7zr0qjU3NE80fM4Y1
-3yaBOUB7QGbOaH6a8JWkDQPfpOvmDNqT6ZqpeKMf6cpcp+Q318398EeA7B0P4TkkGZbdZBXhmYSl
-b+PMddVPBGdcI5xxBSsiptwsMs+LZC/HGdcIZ1wdmHLOGdcc5TjjGuGMqwPZWBYC44xcfYngjGuE
-M64RzriGOeMa5oxrmDOuYc64hjnjGuaMa5gzrtwLhoc5/xjmjGuYM65hzriGOeMa5oxrmDOuYc64
-hjnjGuGMa4QzrJFsulA6Z1zBxJQunDOukey64IxrhDOuDowuZC9ckaMcZ1wjnHF1YMo5Z1xzlOOM
-a4QzruCRlJzi90aOcpxxhdeb4K1UOdkne0azt48zrlHOuDowcjpnXHOU44xrlDOuDrL1NWdco5xx
-jXLGNcoZ1yhnXKOccY1yxrWYM67FnHEtpo+LOe9YzBnXYs64FnPGtZgzrsWccY1yxjXKGdcoZ1yj
-nHGNcsY1yhnWaLa+VjpnXEFN1LRJ9slwjjZxxjXKGVcHppzm2Vs5dM8ZV+bYGw5MOc3XR5LlaqwW
-Z+ZBAVGccY1wxpVy90c44xrhjCt4KJLdPrklwhnXCGdco5xxjXLGNcoZ1yhnXKOccY1yxjXKGdco
-Z1yjnHGNcsY1yhnXYs64FnPGlbXT8GLOuBZzxrWYM67FnHGNcsY1yhnXKGdco5xxjXLGNcoZ1yhn
-XKOccY1yxjXKGdcoZ1wjnHGNcMYVPIJ/DVgb4YxrhDOuEc64RjjjGuGMa4QzrhHOuIY54xrmjGuY
-M65hzriGOeMa5oxrmDOuYfo8zBnXMGdcw5xxDXPGNcwZ1zBnXMOccQ1zxjXMGdcIZ1wjnHGNcMY1
-whlX2n4OOlgL1qCvR5x5n0nHnHFFt0+i4yfQ9RMRzrhGOOMaGY3+A2BUkpq1o7kXaT3X1WtHLy8T
-7oz7oLmv0LxWa8eBRBQBjcOJUIZpah2ZvsfTLdGy7lW+eu7T04HWm4FE298skj3wjr8sceyC+678
-kWOH/O6ms8bLDnkcVHbIGVDZIfcm3TnbqvyEN2SgRy9b5tgh9ZvNskOKyg4pKn7HkG74ep/nqhP5
-2yHd34Teq0vtkHuhR1TYxXbIkG8Ja79b+E7q0+BvoKf/cxBiHZeOEt/fWHs+DW4BS1hnLrFDPjMf
-xiOnxonkNesS+c24Yu50sh1yG/uX7yOnIP+2VrwMX0ToNDvkdirTfqpodyD+F/MN0J6scSWHwoav
-2mv8uWRojx3SyLAzJcN2+O6EvyB/7m+SdqPsQaAEyC/XHjukeEsPu6CuHnbCdxf8Bflzf5O0LRna
-Y4cUb8nwWUqGXfD9DP6C/Lm/SdqWDO2xQ4q3ZJAl29XDZ/DdDX9B/tzfJG1LhvbYIcVbMnDEOinD
-bvj6mbuC/Lm/SdqWDO2xQ4q3ZChIyeD3cc4Z/oL8ub9J2pYM7bFDirdkKErJUADfIvgL8uf+Jmlb
-MrTHDinekiGckqEIvmH4C/Ln/iZpWzK0xw4p3pKhOCVDGL7F8Bfkz/1N0rZkaI8dUrwlg/kmqfhf
-zDdAe/oF+XN/k7QtGdpjhxRvyWC+SSr+F3PP4vtbjhwKm+tze67V7bFDirdk6JfqixJk6Ad/Qf7c
-3yRtSw/tsUOKt2QoTcnQD76l8Bfkz/1N0rZkaI8dUrwlg/kmqfhzzhn+gvy5v0kqGUx//dMOqbWH
-+01Ss48cQT+cR41wljXM+dQw51TDnFcNc5YV3BRpjbOjpBWTp5i8xZxljapsun6Nn2q73A45Y9PC
-8d9EO+QXKE92yAjjn79WdsgeRISImwTSnXneryfy62CHNH2TQJ4agNutthhUd7EdUjqUHdKrQ9kh
-pUPJkUmHdaRVAzkzno0dsjcFzbc8Bydanl0r8A8iv9bGWNLHOSTp/7DvF+P1bSON1eeJ+5WbmNJH
-hHBbfXaW9QPOUwtlbMo+M9oaOHuMFTxgjEtPdunOGxza8NIDSfqiG//wTjd8aXCs8ifOLXHpFwMc
-2jAv5oZPOtShVt1El5473aHNc09x6dVnufF7cP7a6JBLuWNvvwNaQD+MgOqb08dA1R/G3q60IwlH
-QKY+mkdaLp0VkEcIJqkJd0+GdW+AlZNHaSZeVM7Ibfq+gbiFwGuDzrfvE5StAbhU36vdB1vWF+dm
-1XLHzwwfn9TzyW3oWWnSs2TIpOc6Vz7+/70+OjwXeBf7n3Oh9VzYiH41Fx6FeufCI8RFQKY++oea
-C8m+T9CetubCsC6eCxvhq7ng1bPmgvScay4gn+O814aOzgXtB/5zLrSeCzE6QXPhcKh3LhxKRIQe
-+CbMBdP3CdrT1lxgDdKl9wXpWXPBq2fNBelZus+k5zrSMq2RVpK2FLTnPvmXocPH68yP5sJ0yh4F
-cKn7pLt2OJOvzFjzjnVXOGfydRmtiM78iUszrFA6du+sh/mvwEbwEngUSB9mjaI0XS8kVyYdqR3T
-+SrOAqhZW+DtlHVFur4S1NnW+BlqNUx7uAt0o3ZJJxvBK8CrG6Xlcy0dSj4577X0deJeBB0dP+sp
-uwbgUuNHNpF5rKR/COZZZVbL2tp6+Heujn7zskv3+dihDVsDzpqsoWhvl67Y36HNvkFuePswhya2
-1rq0qM6h1hcnubRTx2Mj8kvXG0FPBqJX50qTztXOTONxDmkZdOCsgzVGDbgEtLk2Jvrv+quRuCXA
-21978v62fvtD9r9B1FsC9J0qyWQl2Cfl1MidOjnCb/P1IRwhuhvQ/IyBIqC8ZlwpXjqZA3qCFeBO
-QA2p8Dr8KvNNeieoifbMAJmo0Y/a3QsYvY3EHwD7gQjYBkbwEHUINAKeDbnhmfhrgHFmD0LPUptC
-I4IvhkaBBJgQ3BQ6KvgsMHVsI89R1JmtjnfJ8ZY1ASTAqOC7SLENjKas5BuVpMambvr2LuJXAdMm
-9b9pq/yDkmCLqhZv0rX4pY8SIH3I9Qby8xz4pYwjIyvsnHefpaNJQPPL+77zEOLLgOZHN6iV0Lc4
-Gq3/ZHTfwckm+Zkni3sn2vfO8R1URUnqcc9HmXARYen+//d5kj6m0Idz9lV9YfRk9KY+aQ5ZwQV7
-JYLNoQXAanVuoyvHqFcWEy7qhD5MH6MDqU91tvWuR7Z3hu+lzO1A47o6YXVTHXKBRFGG8+tFqTm5
-J/cWzu7sznRv6WFdyzfArnXmjPfeMkCygdlAsmoMDEqCIaDLUtK1+G1iTgYjgMaCqJyhqqW7G2Uh
-V9LnEqNjlTN+8jZ8l7D46l7fCMy9TLyetcqCG0NlrcaYKUtyQ5q8tYSTrvW1L0as2ie+E8EkkADq
-J+ltCP4ykH7NaeI06X3orcm6Diz/u2uOdG7qzVdvB8GjBCi/nNGPaY/i25o/Adp5HGmSU/c+pEE2
-C8ncNq0LbQ7U7VUWXBeqB5sDpr5CyrVVH8Xy0pt0ZXQjXYUSVnM/4iJAc0PylnNqYwF3kj3VBdVR
-W8u4UN2mHab9ceLKwTJwPVgDuoNGe2Og0W4INgYF+Te20oGph6x5t/sG1QvU7opE5r3w61+dVqtv
-Qug5by75TwS41Dpd8tWyStUa/WirYf2KMdbSwGjr6ntdeuMvXbqBNTvxDZezZld6p6615yGD9HYZ
-OARIb9KvefZT2iogWSeBdKd+lptJZEs73D1mzU8DlTF6Zl3h3OcbiFsIpMPBCXcOErTy1SdFzHos
-pU/JXWVZ//t2F+hpOnUfBqSnMcCrJ6VJT5Ihk57qSEM+x3n1cRQFR4GO6kN2ms/cqlP66EN4ilXG
-F15PTT4DnoPOzyHmezypnw2d4zwlnmadArVe2O3oLdFcPNYZb5X7ODSxzwEuTRzsUGtYwqHNB0xx
-6TH/x6X/d65L38eKwjhtjv6rQ63mxQ4t2/syl66+yqENV17r0HWPrXLDo250qFW33g0/1OSGrbvc
-sP/eZLhhrNtQ/U/3FxMuAqii1Zq2bzK+BGr07sevPn0G6Gamfl0LvP2qtFVAuszUr+eR1g496/vT
-ztzQPac7KEhCfsUZaP5ITqUrTmH5lU9QWFTuQKC2m/nViH8J8I6nPVlLZHtO3du30vrQV4byMz+n
-ql9iQHJKdnPPk1+O+h1q2qJ46XwO6EvhUuhO6Kq08Gv4zwVf9RpdbZMbBOJgOigDcmpzIAmfMzpb
-0pSe7ricZn2O1T3e6Ec8zT1cuvI+y86Pcs0KtjzLTkaBuyg0k7w1wDjnIs4/ja2ppR/5jivd5ZtZ
-+rnvhFKfPbO0wJ5eGkj9rtVC6sz1LLsgekzw9OhRwdOiRwS/H01ARwbnRw/L+Czr7VvTJrXPtFXt
-k24FZn2tQzx+5SkBGl9yvUFyTnwp48jICtsOPctu9/W3vvD1Y4wPsuTP9izr1Y2ZJ9tJ6IcAX0Cl
-KxOWHhgK36h5orkwA2Sipj+kq7bGFHMytXY2ejJ660aZeOlm3+bSZl99acKW39SXae3cWWPUK4sJ
-d0YfmjbQvFZnGCYSEQMaO7pndOxZtkc3M//0vERVun9FahI9UnNyT+4/eq4KZNgn7eO7lrHOBY79
-nz4J9zlEfai+HwDo66/Ns2wvhNofeT6EroRq3NRFy4Lx0m2txlh6X2kuC3RbrUM8ftWh/tMYUbvV
-n5NAAqg/pbch+MtA+rPs+1xvPvPta+3wDbTk915z0p9lPeNbS6Oka70H4L2ve59lVU+u+fg+utmX
-fJ9BB0LVpghzsbl0nS9RWmbLb/STaT5SpCEfvUlX08FRwOiqBr/0KV11h0qR03znW0/4xvA7i8Os
-yb4znDD68i3mZ717J1r2HHU/NX3RUZ1Rhbi2uv9l01mcvJPR1TDoE9DzoZK7rE9jYV2/zf5t+5X5
-n+29uUDhztTbQnjMBdJbRcIdoyWEm2c1jTuw+8GPgnHyf3jdFdg83Wdhspn1R+pZBZH1DDyoqhPW
-+Eb3XHu8v4fRQFTKNYoprrN+D2PzD/ctUH0vPeX+voX5fQzFyTVOd38vww0xOJNhk39bsrzd/1Hn
-9yZMWO2QM+G6/93H4XNBKPSmxpqodl1M/Kz/fGu0+/sabrlkM/+uvMl/72fvOnN5/n4DHlV9Jt7w
-kz7lTPiCkBs2+T985d3RmX4PQ/PKONUtJ3nM/sJUAj8krDhdr9Kdmxt5iDw6mWDGbg/UN5G4BqAx
-qPE3ONGy9tvTsVhlJaYc0glj0cirPpQucunjOyjiB+TLpY8q8siZ+o0+FlBwDuioPuKUHSTmaftU
-+xDI/nx7Shu/itN8bK2rvwHTHZq4ml+30f7VBXNcevPZDq1/mmd44hPjljq0ecbVLt260o3/+fUu
-PewnDq1f8FOHNjz1M5ce6e4PbB71H07YWni/G3/uQy796DGHbv7O7x3a/MwLLp30qkPXPbHVoWUv
-vetQa9oOhzb02eWGW+0x7Ol+Q67+/y66Pwd9qwuyzYcppOsi4O3/BuK6Yj4cbK2b9NlXoI9HUIQu
-Trn0cTB55Lz6aCRuCfDOhz1Zh+baB9nBXojWBd51qLkvaU1g/GqXWS/JL+fdBzFtn0OanpVXQHdA
-4ZIK/wm/6v2q90Ekg9wgEAfTQRmQU5sDSXTmPoh49gJFQH7vPsiCKDaoYMs+SKLUDc8kbw0wztxv
-NK8mlI4IHlU6CiTAhOCE0qOCCXAIaRGgOnPtg8xjD2RudAJIgFHBedERwQVA41l6GJWk2k8uAaZv
-9VywirBpE8HUuJZfuhW4+9U6xOOXDlSf9CHXG8jPPcK5psyBGl5dMY7MHIRNB/dBGtm/WMnz3GrQ
-qLnUbpu+npkp6eyDrIaasPQg3X+T5kkT7ZkBMlHTH+nzJH1MoY9W+yCN1KV9EOmtG4iXWsHNzIN4
-6QLw5dn0TZ8ZWUy4M/rQ6ITmdcE+SM8M+yA9U3NyT+4/ufZBPmAvRHPGe/8ZQGM19mcD6VBjQNcR
-ATXospR0LX6NmZPBCKCxICpnqGrp7kZZ5jk/GUxds1TO6Ju8KZt+LwRoJM1cg8RL+yBlpV++Tf99
-33L2Gq5lD+Q6gBXdc82RzmPI1x69ee/rRj9GF9J/W9f4ADo6jrQhQPsgSOPsg1wHlS4jpZsDzego
-UloPvlyb/lG+ZdZi7iR7qgvutbSkZVxIF0Yvpv1x4mQXlU3/aegaKOPHaui9MdDQG3t+P0H+Pbfp
-L6TeucC7j8FOxjiik645z32MRIT3affYVm907If7NLAAHcjvdY1SHq6r9jHoD+edjvpTT9fSyLlu
-iI568Tf9ze9qJkVw0sw+QTv2Md7S2ot9jLe+zvsYGouX0e6joWuSejD7GEpblYybBE13Zl1ZR+Se
-7GN0ZCxWsRwOd8JYNHNT4296Escm9VHXhj6Ulo8+kM9xpn7WqM6acQHl5wDvc1tFwr1flTilMs/N
-OGUHAVxqj7Fj+xgNh+7r6K+5aKirxwur3fCpo1165bEObVjk7m8kFpzmhBOrOefINWDdvyx2aFnp
-ZS69e5mb/sZyh9aPXuHSh9c6tPked59j89vuPkf9e7e76fM3uulPP+jQdePcfY11j/7aCTeM/IND
-rSkvOXTzU5sdWr/M3d9AsWMdfTj/0v3FxJj7mvQqv1xfIL/iTP+Y/n+duCnoV/PhcegaqNRt5oPS
-1P/Seab50EDaFCvb+ylt7Su5v9mstYLuhd1BQRLyK85AeSSv0hWnsMnP42CqnNJNvPLJHQjUdjMe
-G/AvBB0djwnK1gBcajxKX8OshkffcvutU/tnOnWrX9Q/v4Z6+0dpq0iTDJn6p460YUDOq49G4pYA
-rz72ZF2ba1/lQ18h2waZ91XUlhhQv6mvzfpLfjnvvori1fY5wDwP76QSvUtlwq+R9kPwVT8vqm1y
-g0AcqH/LgJzaHEiiM/dVxLMXMPr07qvoXZD090uml1rWaZHs75fMLD09ckLpgsjM0oWR40rPi0wt
-vSAyGXoIfChq6Z2VXPsqp0Un8l5JLe+VjOY9k8PYUzk0uDDH+yUrqNv0rWmT2mfGtcaCdCtYnbCv
-Ynh15jgyskrAifybCTR+NQfzOSux0+f3feEr8m33hXzye59xNP/M/PHqxswTPYNT0tkfKIKasMaI
-zELfpHmSaT/FxJv+kK7aGlPMydRznNGT9jKkt26UqS+NR3i/JBIvXReR39RXSLm26uusMeqVxYQ7
-ow9NG2heh/dVbqBwI9C4rk60nJWoSXw5+yfbfd2dufGPsn+i/WLujM49T/sn8dK6VmMpvU/yucaZ
-a4DGqK4zmvsJoP4IZHiPZAf35c+4rrzvC/jk915b0vdPPOM4476T9/7t3T9RPW3Nk/R5p/0TpHH2
-T0JQtSlRGonwHkkkUtoQkd/oJ9O8o0hDPnqTrqaDo4DRVQ1+6TP9PZLJvvt5h+R93tN4g3dImnhv
-434J+bV6j0TXOL1H8j60O3i2d/1e2/aLhOv61fcs67MupHBn6m0hPOYC6a0i4d6HSwgn3yNx3iX5
-2rxH8nFy8wr55BrRk1xn7b/U53iPZNt3Wr9HsjkZNu+RLPC8R2LCfldMy4TNex7su7yd3H95O5/9
-F295U0+m90hMfs0DORNu73sk30bPfXbt3n0rE/9FILWb502l/Qdhxel6le46a/+lI2OxK98jqaOx
-fdHH8d1458ijD6XdixJy6WNP9l+y6SMO487Zf/nneyS6DpprrebwdAN0XEL/jyywLH0wQH1t5sN0
-AtxVcvb/FPJQPFXnCZTbjzr/Bfqqp06l/SKPOsvIQ9FUnSdSrh912ozTP3nqVNoDedR5NnnS215P
-uf7U+TF1vuapU2kP5VHnqeTRvc3ocw7lBlDnbup83VOn0h7Jo86zPHWeRrkDqLMbjN7w1Km0X+ZR
-5w88dZ5BuW9RZwF1vu2pU2mP51HnqZ46z6FcjDoTtP0dT51KezKPOs8hD8VT+jyXchXUuYWOe89T
-p9J+lUedC8mT3u8XUG4IdR4Jo7956lTar/Oo0yvnIspVUudF0Pc9dSrtmTzqLCMPRVNtb6BcFXV2
-R84PPHUq7bd51Pk98qS3/RLKxamznn7f7qlTab/Lo84zyUPxlJxLKVdNnZXIudNTp9L+J486zyZP
-upzLKDecOq+EfuypU2nP5VFnGXkompLzKsodQp13IOcuT51Kez6POk8hD8VTdV5DuRHUeQYK+dRT
-p9JeyKNOrz6vo9zh1HkqDxOfe+pU2ot51DmfPIE0OW+i3BjqPBs5fSiaYOo6r7RX8qhzAXnS+/0W
-ytVSZwOR3Tx1Ku1PedTpbfvtlDuCOo+kTn7vqpWcSvtzHnWe4ZHzTspNpM4J1Bn01Km01/Oo81RP
-nf9OuaOps446izx1Ku3NPOr0ynk/5Y6lzoEMsJ6eOpXGwtrRR7a16ULyUDQ1Pn9BucnUKRrx1Km4
-d/Kos4w8cgeCItAee0a29V2CumoArpU9o7oL3xN9iDZ/G31Mpt+iHn0o7V2EgWRd/1dLYpxXH/2I
-iwA9fw5OuLoi6NQ1ByrdqW71w2F4TLh7MlzuvH1FBselW9fS/Sa9NR1IUPXpOWUiNF0WO9EiS0/S
-egO5CJD//wENOK1w7N8BAN==
-
-------=_NextPart_01CC4DF5.1FA44F90
-Content-Location: file:///C:/EEB34A10/WdfMultiComp_files/image002.gif
-Content-Transfer-Encoding: base64
-Content-Type: image/gif
-
-R0lGODlhEQNIAXcAMSH+GlNvZnR3YXJlOiBNaWNyb3NvZnQgT2ZmaWNlACH5BAEAAAAALAwAAQAE
-AzcBhwAAAAAAAAICAgUFBQQEBAMDAwYGBh4eHhISEh8fHwEBAREREScnJygoKDw8PCQkJCUlJTk5
-OSkpKSYmJjs7Oz4+Pj09PTo6OjExMSMjIzIyMl5eXkBAQE1NTUlJSUhISFFRUVBQUFJSUkFBQV9f
-X1lZWVpaWl1dXUZGRk9PT1xcXExMTEdHR05OTlVVVVRUVFdXV1NTU0pKSlhYWFZWVkREREtLS0ND
-Q1tbW0JCQm5ubmBgYHFxcWJiYnNzc3d3d2hoaG9vb3BwcGpqan19fWZmZmlpaWxsbHZ2dnp6emRk
-ZHR0dGtra3h4eHV1dXJycmFhYWNjY3x8fH9/f35+fnt7e21tbWVlZXl5eWdnZ56enp+fn4mJiZSU
-lJqampGRkYCAgIKCgpmZmZWVlY2NjYiIiIyMjIODg5KSkpycnI6Ojpubm4aGhpCQkIGBgY+Pj52d
-nYeHh5OTk4WFhYqKioSEhJaWlpiYmJeXl4uLi6CgoKSkpKqqqrCwsKurq7W1tampqaWlpb6+vrq6
-urGxsaKiora2tq6urq2traysrLu7u6+vr7i4uKampry8vKioqKOjo7m5ubOzs6GhobS0tKenp7Ky
-sr+/v7e3t729vdLS0s3Nzc7Ozs/Pz8jIyNHR0djY2NTU1MHBwdDQ0MzMzMPDw9/f397e3tPT08fH
-x8XFxdvb28TExNzc3Nra2t3d3cbGxsLCwsvLy8rKytfX18nJydXV1dnZ2cDAwNbW1vz8/P7+/ubm
-5uvr6+fn5/39/fj4+Pf39/Ly8vv7++Xl5fr6+uTk5PDw8Ojo6Pn5+e7u7vPz8+np6ePj4+zs7PT0
-9OLi4vb29uHh4fX19eDg4Orq6vHx8e3t7e/v7////wECAwECAwECAwECAwECAwECAwECAwECAwEC
-AwECAwECAwECAwECAwECAwECAwECAwECAwECAwECAwECAwECAwECAwECAwECAwECAwECAwECAwEC
-AwECAwECAwECAwECAwECAwECAwECAwECAwECAwECAwj/AAEIHEiwoMGDCBMqXMiwocOHECNKnEix
-osWLGDNq3Mixo0ePOgDsEElypMmSKEduSMnypEsAK1/KbAmT5syXIT/q3BmSBwCfPnH+HOpjp9Gj
-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
-
-------=_NextPart_01CC4DF5.1FA44F90
-Content-Location: file:///C:/EEB34A10/WdfMultiComp_files/oledata.mso
-Content-Transfer-Encoding: base64
-Content-Type: application/x-mso
-
-0M8R4KGxGuEAAAAAAAAAAAAAAAAAAAAAPgADAP7/CQAGAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAA
-EAAA/v///wAAAAD+////AAAAAAAAAAD/////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////9
-/////v///wMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAAKAAAACwAAAAwAAAANAAAADgAAAA8A
-AAAQAAAAEQAAABIAAAATAAAAFAAAABUAAAAWAAAAFwAAABgAAAAZAAAAGgAAABsAAAAcAAAAHQAA
-AB4AAAAfAAAAIAAAACEAAAAiAAAAIwAAACQAAAAlAAAAJgAAACcAAAAoAAAAKQAAACoAAAArAAAA
-LAAAAC0AAAAuAAAALwAAADAAAAAxAAAAMgAAADMAAAA0AAAANQAAADYAAAA3AAAAOAAAADkAAAA6
-AAAAOwAAADwAAAA9AAAAPgAAAD8AAABAAAAAQQAAAEIAAABDAAAARAAAAEUAAABGAAAARwAAAEgA
-AABJAAAASgAAAEsAAABMAAAATQAAAE4AAABPAAAAUAAAAFEAAABSAAAAUwAAAFQAAABVAAAAVgAA
-AFcAAABYAAAA/v//////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////1IA
-bwBvAHQAIABFAG4AdAByAHkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAWAAUA//////////8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKASDcwvTswB
-/v///wAAAAAAAAAAXwAxADMANwAzADQANQAyADAAMAAyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAABgAAgH///////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAACAAAAta0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////////wAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////
-////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALIC
-AHic7J0NfFxVnffPPVOSdho6bWYSum50yOzMOu2dJuHNjRpg4E5CfGEFFtjKFCxo17CioOCavmwk
-bjS7RqMuwWCW7BPXaLSAL6ywEesSV4txbVd2XXy6a1erNCWP4trSUimkyfP7/+fcm0M2ydxOOZMs
-n4yfHzP/5N75/c59Peeb0+vjP1xz4LNfe8XPxYzXRSIgJqdWiBLtZwHIcovVQkhVT05NTbk/XgYd
-h6aWXv8rXiehZ9U+/GPsTKppn5dCy6EVUBBaCZVBZ0KroFDuEBBroHIoDEWgCqgSOgtaC/0O9Aro
-d6Eq6JXQq6AodDZUDcWg34PiUAL6fejVUBJaB62HbCgFbYBqoFqoDjoHOhc6DzofugB6DfQHUD30
-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
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-
-------=_NextPart_01CC4DF5.1FA44F90
-Content-Location: file:///C:/EEB34A10/WdfMultiComp_files/filelist.xml
-Content-Transfer-Encoding: quoted-printable
-Content-Type: text/xml; charset="utf-8"
-
-<xml xmlns:o=3D"urn:schemas-microsoft-com:office:office">
- <o:MainFile HRef=3D"../WdfMultiComp.htm"/>
- <o:File HRef=3D"themedata.thmx"/>
- <o:File HRef=3D"colorschememapping.xml"/>
- <o:File HRef=3D"image001.emz"/>
- <o:File HRef=3D"image002.gif"/>
- <o:File HRef=3D"oledata.mso"/>
- <o:File HRef=3D"filelist.xml"/>
-</xml>
-------=_NextPart_01CC4DF5.1FA44F90--
diff --git a/pofx/WDF/Driver/SingleComp/driver.c b/pofx/WDF/Driver/SingleComp/driver.c
index cd7b6dd1..ad3b7d43 100644
--- a/pofx/WDF/Driver/SingleComp/driver.c
+++ b/pofx/WDF/Driver/SingleComp/driver.c
@@ -79,7 +79,7 @@ Return Value:
WPP_INIT_TRACING(DriverObject, RegistryPath);
//
- // Initiialize driver config to control the attributes that are global to
+ // Initialize driver config to control the attributes that are global to
// the driver. Note that framework by default provides a driver unload
// routine. If DriverEntry creates any resources that require clean-up in
// driver unload, you can manually override the default by supplying a
diff --git a/pofx/WDF/README.md b/pofx/WDF/README.md
index 1e6a21a9..4c484abb 100644
--- a/pofx/WDF/README.md
+++ b/pofx/WDF/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: KMDF Power Framework (PoFx) Sample
- platform: KMDF
- language: cpp
- category: Power
- description: Demonstrate how a KMDF driver can implement F-state-based power management.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617937
---->
-
# KMDF Power Framework (PoFx) Sample
This solution consists of two samples that demonstrate how a KMDF driver can implement F-state-based power management. The SingleComp sample demonstrates how a KMDF driver can implement F-state-based power management for a device that has only a single component. The MultiComp sample demonstrates how a KMDF driver can implement F-state-based power management for a device that has an arbitrary number of components that can be individually power-managed.
@@ -24,104 +16,110 @@ This solution consists of two samples that demonstrate how a KMDF driver can imp
This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP.
-Related technologies
---------------------
-[Supporting Functional Power States](http://msdn.microsoft.com/en-us/library/windows/hardware/hh451017)
+## Related technologies
+
+[Supporting Functional Power States](https://docs.microsoft.com/windows-hardware/drivers/wdf/supporting-functional-power-states)
-SingleComp Overview
--------------------
+## SingleComp Overview
This sample demonstrates how a KMDF driver can implement F-state-based power management for a device that has only a single component.
-The sample illustrates the use of the [**WdfDeviceWdmAssignPowerFrameworkSettings**](http://msdn.microsoft.com/en-us/library/windows/hardware/hh451097) method to specify power framework settings for the single component that represents the entire device. The power framework settings that can be specified include the F-states for the component and the power framework callbacks that are invoked when the component's active/idle condition or its F-state changes.
+The sample illustrates the use of the [**WdfDeviceWdmAssignPowerFrameworkSettings**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdfdevice/nf-wdfdevice-wdfdevicewdmassignpowerframeworksettings) method to specify power framework settings for the single component that represents the entire device. The power framework settings that can be specified include the F-states for the component and the power framework callbacks that are invoked when the component's active/idle condition or its F-state changes.
-The sample also illustrates the use of the [**WdfDeviceAssignS0IdleSettings**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff545903) method to instruct KMDF to begin power-management of the device (and the component that represents the entire device).
+The sample also illustrates the use of the [**WdfDeviceAssignS0IdleSettings**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdfdevice/nf-wdfdevice-wdfdeviceassigns0idlesettings) method to instruct KMDF to begin power-management of the device (and the component that represents the entire device).
-Installation
-------------
+## Installation (SingleComp)
The driver can be installed on a root-enumerated device using the devcon.exe tool.
-1. Obtain the devcon.exe tool from the WDK
-2. Copy the driver binary, INF file and the KMDF coinstaller to a directory on your test machine.
+1. Obtain the devcon.exe tool from the WDK
- **Note** You can obtain redistributable framework updates by downloading the Wdfcoinstaller.msi package from [WDK 8 Redistributable Components](http://go.microsoft.com/fwlink/p/?LinkID=226396). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0.
+1. Copy the driver binary, INF file and the KMDF coinstaller to a directory on your test machine.
-3. Run the command "devcon.exe install SingleComponentFStateSample.inf root\\SingleComponentFStateDevice".
+ > [!NOTE]
+ > You can obtain redistributable framework updates by downloading the Wdfcoinstaller.msi package from [WDK 8 Redistributable Components](https://go.microsoft.com/fwlink/p/?LinkID=253170). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0.
+
+1. Run the command "devcon.exe install SingleComponentFStateSample.inf root\\SingleComponentFStateDevice".
Use the PowerFxApp.exe application to send I/O requests to the driver. Running the command "PowerFxApp.exe /?" displays detailed usage information.
-For detailed information about implementing F-state-based power management for a single component device, see [Supporting Multiple Functional Power States for Single-Component Devices](http://msdn.microsoft.com/en-us/library/windows/hardware/hh451032).
+For detailed information about implementing F-state-based power management for a single component device, see [Supporting Multiple Functional Power States for Single-Component Devices](https://docs.microsoft.com/windows-hardware/drivers/wdf/supporting-multiple-functional-power-states-for-single-component-devices).
-MultiComp Overview
-------------------
+## MultiComp Overview
This sample demonstrates how a KMDF driver can implement F-state-based power management for a device that has an arbitrary number of components that can be individually power-managed.
The sample driver statically links to a helper library (WdfPoFx.lib) that encapsulates all of the generic code to interact with the power framework. The device-specific code is implemented in the driver itself, outside of the helper library. The idea behind this organizing the code in this manner is make the helper library reusable by other drivers. The directory structure for the sample is as follows:
-- The helper library is implemented in the 'lib' subdirectory.
-- The interface between the helper library and the rest of the driver code is defined in the 'inc' subdirectory.
-- The driver is implemented in the 'driver' subdirectory.
+- The helper library is implemented in the 'lib' subdirectory.
+
+- The interface between the helper library and the rest of the driver code is defined in the 'inc' subdirectory.
-Installation
-------------
+- The driver is implemented in the 'driver' subdirectory.
+
+## Installation (MultiComp)
The driver can be installed on a root-enumerated device using the devcon.exe tool.
-1. Obtain the devcon.exe tool from the WDK
-2. Copy the driver binary, INF file and the KMDF coinstaller to a directory on your test machine.
- **Note** You can obtain the co-installers by downloading theWdfcoinstaller.msi package from [WDK 8 Redistributable Components](http://go.microsoft.com/fwlink/p/?LinkID=226396).
-3. Run the command "devcon.exe install WdfMultiComp.inf WDF\\WdfMultiComp".
+1. Obtain the devcon.exe tool from the WDK
+
+1. Copy the driver binary, INF file and the KMDF coinstaller to a directory on your test machine.
+
+ > [!NOTE]
+ > You can obtain the co-installers by downloading theWdfcoinstaller.msi package from [WDK 8 Redistributable Components](https://go.microsoft.com/fwlink/p/?LinkID=253170).
-Testing
--------
+1. Run the command `devcon.exe install WdfMultiComp.inf WDF\WdfMultiComp`.
+
+## Testing
Use the PowerFxApp.exe application to send I/O requests to the driver. Running the command "PowerFxApp.exe /?" displays detailed usage information.
-Design overview
----------------
+## Design overview
The driver controls a device that has more than one component. It needs to access one of those components for processing each I/O request that it receives. The specific component that it needs to access depends on the I/O request that it receives.
-In order to support this, the driver creates one top-level, power-managed queue to receive all its requests. It also creates one secondary, power-managed queue for each of its components. These secondary queues are called component queues.
+In order to support this, the driver creates one top-level, power-managed queue to receive all its requests. It also creates one secondary, power-managed queue for each of its components. These secondary queues are called component queues. This is shown in the diagram below.
+
+![Overview](WdfMultiComp_overview.svg)
When the driver's dispatch routine for the top-level queue is invoked, it examines the request to determine which component it needs to access in order to process the request. Then, it forwards the request to the component queue for the component that it needs to access for that request. When the driver's dispatch routine for the component queue is invoked, it accesses the component hardware to process the request.
The driver's top-level queue and component queues are all power-managed so KMDF ensures that the device is in D0 while the queues are in a dispatching state. The key point to note is that the driver is designed to maintain a component queue in a dispatching state only when the component is active. In order to achieve this, the driver stops the component queue when the component becomes idle and starts the component queue when the component becomes active. (To be precise, this mechanism of stopping and starting queues is encapsulated in the power framework helper library used by the driver). Thus, the driver is able to ensure that when the component queue is in a dispatching state, not only is the device in D0 but the component corresponding to that queue is also active. Thus it is safe to access the component hardware when the component queue's dispatch routine is invoked.
-Implementation notes
---------------------
+## Implementation notes
+
+The driver uses the power framework helper library to manage most of its interactions with the power framework. In order to achieve this, during device initialization, the driver performs the following tasks in its [*EvtDriverDeviceAdd*](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdfdriver/nc-wdfdriver-evt_wdf_driver_device_add) callback.
+
+- Enables the helper library to register its own KMDF callbacks for PNP and power-management of the device.
-The driver uses the power framework helper library to manage most of its interactions with the power framework. In order to achieve this, during device initialization, the driver performs the following tasks in its [*EvtDriverDeviceAdd*](http://msdn.microsoft.com/en-us/library/windows/hardware/ff541693) callback.
+- Provides the helper library with power-framework-related information about the device.
-- Enables the helper library to register its own KMDF callbacks for PNP and power-management of the device.
-- Provides the helper library with power-framework-related information about the device.
-- Provides the helper library with information about the component queues.
+- Provides the helper library with information about the component queues.
During I/O request processing, the driver uses routines provided by helper library to forward requests to component queues and also to complete requests.
The main tasks performed by the power framework helper library on behalf of the driver are:
-- Registration and unregistration with the power framework.
-- Stopping component queues when the corresponding components become idle and starting them when the corresponding components become active.
-- Notifying the power framework when the device returns to its working state (D0) in response to the system returning from a low-power state to the working state (S0).
+- Registration and unregistration with the power framework.
+
+- Stopping component queues when the corresponding components become idle and starting them when the corresponding components become active.
+
+- Notifying the power framework when the device returns to its working state (D0) in response to the system returning from a low-power state to the working state (S0).
The power framework helper library does not have any hardware-specific information, so any tasks that are specific to the device's hardware are performed by the driver. In this sample, the device hardware is represented by a very simple simulation. The notable hardware-specific tasks in this sample are:
-- Accessing component hardware to process I/O requests.
-- Accessing component hardware to change the component's F-state.
+- Accessing component hardware to process I/O requests.
+
+- Accessing component hardware to change the component's F-state.
As mentioned earlier, the hardware access shown is this sample is entirely simulated in software. This sample does not work with a real device, it installs on a root-enumerated software device.
-S0-idle power management support
---------------------------------
+## S0-idle power management support
The power framework helper library implements support for S0-idle power management for the device. Note that this is different from the component power management support that is enabled by the power framework. Component power management enables individual components of the device to be power-managed by putting them in different F-states while the device is in a working state (D0). S0-idle power management for the device enables the device as a whole to be power-managed by putting it into different D-states while the system is in a working state (S0).
The code to implement S0-idle power management support for the device is conditionally compiled based on the value of the PFH\_S0IDLE\_SUPPORTED compiler switch. If the switch is set to a nonzero value, the code to implement S0-idle power management support is included. If set to zero, the code is omitted thereby resulting in a smaller binary size. Thus, a driver that requires S0-idle power management for the device can use the power framework helper library's support for it but a driver that does not require it can reduce its binary size by omitting the code that is specific to S0-idle power management.
-Additional Information
-----------------------
+## Additional Information
-For detailed information about implementing F-state-based power management for a multiple component device, see [Supporting Multiple Functional Power States for Multiple-Component Devices](http://msdn.microsoft.com/en-us/library/windows/hardware/hh451028).
+For detailed information about implementing F-state-based power management for a multiple component device, see [Supporting Multiple Functional Power States for Multiple-Component Devices](https://docs.microsoft.com/windows-hardware/drivers/wdf/supporting-multiple-functional-power-states-for-multiple-component-devices).
diff --git a/pofx/WDF/WdfMultiComp_overview.svg b/pofx/WDF/WdfMultiComp_overview.svg
new file mode 100644
index 00000000..9a5f72fe
--- /dev/null
+++ b/pofx/WDF/WdfMultiComp_overview.svg
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by Microsoft Visio, SVG Export image003.svg Page-1 -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events"
+ width="8.14513in" height="3.38194in" viewBox="0 0 586.45 243.5" xml:space="preserve" color-interpolation-filters="sRGB"
+ class="st12">
+ <style type="text/css">
+ <![CDATA[
+ .st1 {visibility:visible}
+ .st2 {fill:#cdcdcd;fill-opacity:0.5;stroke:#cdcdcd;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:0.5}
+ .st3 {fill:url(#grad0-6);stroke:#404040;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.25}
+ .st4 {fill:#000000;font-family:Calibri;font-size:0.666664em}
+ .st5 {fill:url(#ptrn2-103);shape-rendering:crispEdges;stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.25}
+ .st6 {marker-end:url(#mrkr13-123);stroke:#cdcdcd;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:0.5;stroke-width:0.25}
+ .st7 {fill:#cdcdcd;fill-opacity:0.5;stroke:#cdcdcd;stroke-opacity:0.5;stroke-width:0.090252707581227}
+ .st8 {marker-end:url(#mrkr13-129);stroke:#404040;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.25}
+ .st9 {fill:#404040;fill-opacity:1;stroke:#404040;stroke-opacity:1;stroke-width:0.090252707581227}
+ .st10 {fill:#ffffff;stroke:none;stroke-linecap:butt;stroke-width:7.2}
+ .st11 {fill:#ffffff;stroke:none;stroke-linecap:butt}
+ .st12 {fill:none;fill-rule:evenodd;font-size:12px;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
+ ]]>
+ </style>
+
+ <defs id="Patterns_And_Gradients">
+ <linearGradient id="grad0-6" x1="0" y1="0" x2="1" y2="0" gradientTransform="rotate(270 0.5 0.5)">
+ <stop offset="0" stop-color="#f0f0f0" stop-opacity="1"/>
+ <stop offset="1" stop-color="#ffffff" stop-opacity="1"/>
+ </linearGradient>
+ <pattern id="ptrn2-103" patternUnits="userSpaceOnUse" width="6" height="6" viewBox="0 0 64 64">
+ <image x="0" y="0" width="64" height="64" image-rendering="optimizeSpeed"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAHYcAAB2HAY/l8WUAAAARSURBVChTY/hPAIwIBf//AwCEtf8BmLK6XAAAAABJRU5ErkJggg=="/>
+ </pattern>
+ </defs>
+ <defs id="Markers">
+ <g id="lend13">
+ <path d="M 3 1 L 0 0 L 3 -1 L 3 1 " style="stroke:none"/>
+ </g>
+ <marker id="mrkr13-123" class="st7" refX="-33.24" orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend13" transform="scale(-11.08,-11.08) "/>
+ </marker>
+ <marker id="mrkr13-129" class="st9" refX="-33.24" orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend13" transform="scale(-11.08,-11.08) "/>
+ </marker>
+ </defs>
+ <g>
+ <title>Page-1</title>
+ <g id="shape1-1" transform="translate(134.76,-117.25)">
+ <title>Rectangle</title>
+ <g id="shadow1-2" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <rect x="0" y="207.5" width="18" height="36" class="st2"/>
+ </g>
+ <rect x="0" y="207.5" width="18" height="36" class="st3"/>
+ </g>
+ <g id="shape2-7" transform="translate(152.76,-117.25)">
+ <title>Rectangle.2</title>
+ <g id="shadow2-8" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <rect x="0" y="207.5" width="18" height="36" class="st2"/>
+ </g>
+ <rect x="0" y="207.5" width="18" height="36" class="st3"/>
+ </g>
+ <g id="shape3-12" transform="translate(170.76,-117.25)">
+ <title>Rectangle.3</title>
+ <g id="shadow3-13" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <rect x="0" y="207.5" width="18" height="36" class="st2"/>
+ </g>
+ <rect x="0" y="207.5" width="18" height="36" class="st3"/>
+ </g>
+ <g id="shape4-17" transform="translate(188.76,-117.25)">
+ <title>Rectangle.4</title>
+ <g id="shadow4-18" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <rect x="0" y="207.5" width="18" height="36" class="st2"/>
+ </g>
+ <rect x="0" y="207.5" width="18" height="36" class="st3"/>
+ </g>
+ <g id="shape5-22" transform="translate(380.01,-207.25)">
+ <title>Rectangle.5</title>
+ <g id="shadow5-23" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <rect x="0" y="207.5" width="18" height="36" class="st2"/>
+ </g>
+ <rect x="0" y="207.5" width="18" height="36" class="st3"/>
+ </g>
+ <g id="shape6-27" transform="translate(398.01,-207.25)">
+ <title>Rectangle.6</title>
+ <g id="shadow6-28" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <rect x="0" y="207.5" width="18" height="36" class="st2"/>
+ </g>
+ <rect x="0" y="207.5" width="18" height="36" class="st3"/>
+ </g>
+ <g id="shape7-32" transform="translate(416.01,-207.25)">
+ <title>Rectangle.7</title>
+ <g id="shadow7-33" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <rect x="0" y="207.5" width="18" height="36" class="st2"/>
+ </g>
+ <rect x="0" y="207.5" width="18" height="36" class="st3"/>
+ </g>
+ <g id="shape8-37" transform="translate(434.01,-207.25)">
+ <title>Rectangle.8</title>
+ <g id="shadow8-38" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <rect x="0" y="207.5" width="18" height="36" class="st2"/>
+ </g>
+ <rect x="0" y="207.5" width="18" height="36" class="st3"/>
+ </g>
+ <g id="shape9-42" transform="translate(380.01,-117.25)">
+ <title>Rectangle.9</title>
+ <g id="shadow9-43" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <rect x="0" y="207.5" width="18" height="36" class="st2"/>
+ </g>
+ <rect x="0" y="207.5" width="18" height="36" class="st3"/>
+ </g>
+ <g id="shape10-47" transform="translate(398.01,-117.25)">
+ <title>Rectangle.10</title>
+ <g id="shadow10-48" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <rect x="0" y="207.5" width="18" height="36" class="st2"/>
+ </g>
+ <rect x="0" y="207.5" width="18" height="36" class="st3"/>
+ </g>
+ <g id="shape11-52" transform="translate(416.01,-117.25)">
+ <title>Rectangle.11</title>
+ <g id="shadow11-53" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <rect x="0" y="207.5" width="18" height="36" class="st2"/>
+ </g>
+ <rect x="0" y="207.5" width="18" height="36" class="st3"/>
+ </g>
+ <g id="shape12-57" transform="translate(434.01,-117.25)">
+ <title>Rectangle.12</title>
+ <g id="shadow12-58" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <rect x="0" y="207.5" width="18" height="36" class="st2"/>
+ </g>
+ <rect x="0" y="207.5" width="18" height="36" class="st3"/>
+ </g>
+ <g id="shape13-62" transform="translate(380.01,-27.25)">
+ <title>Rectangle.13</title>
+ <g id="shadow13-63" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <rect x="0" y="207.5" width="18" height="36" class="st2"/>
+ </g>
+ <rect x="0" y="207.5" width="18" height="36" class="st3"/>
+ </g>
+ <g id="shape14-67" transform="translate(398.01,-27.25)">
+ <title>Rectangle.14</title>
+ <g id="shadow14-68" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <rect x="0" y="207.5" width="18" height="36" class="st2"/>
+ </g>
+ <rect x="0" y="207.5" width="18" height="36" class="st3"/>
+ </g>
+ <g id="shape15-72" transform="translate(416.01,-27.25)">
+ <title>Rectangle.15</title>
+ <g id="shadow15-73" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <rect x="0" y="207.5" width="18" height="36" class="st2"/>
+ </g>
+ <rect x="0" y="207.5" width="18" height="36" class="st3"/>
+ </g>
+ <g id="shape16-77" transform="translate(434.01,-27.25)">
+ <title>Rectangle.16</title>
+ <g id="shadow16-78" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <rect x="0" y="207.5" width="18" height="36" class="st2"/>
+ </g>
+ <rect x="0" y="207.5" width="18" height="36" class="st3"/>
+ </g>
+ <g id="shape17-82" transform="translate(481.26,-207.25)">
+ <title>Ellipse</title>
+ <desc>Component 1</desc>
+ <g id="shadow17-83" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <path d="M0 225.5 A51.75 18 0 0 1 103.5 225.5 A51.75 18 0 1 1 0 225.5 Z" class="st2"/>
+ </g>
+ <path d="M0 225.5 A51.75 18 0 0 1 103.5 225.5 A51.75 18 0 1 1 0 225.5 Z" class="st3"/>
+ <text x="29.64" y="227.9" class="st4">Component 1</text> </g>
+ <g id="shape18-88" transform="translate(481.26,-117.25)">
+ <title>Ellipse.18</title>
+ <desc>Component 2</desc>
+ <g id="shadow18-89" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <path d="M0 225.5 A51.75 18 0 0 1 103.5 225.5 A51.75 18 0 1 1 0 225.5 Z" class="st2"/>
+ </g>
+ <path d="M0 225.5 A51.75 18 0 0 1 103.5 225.5 A51.75 18 0 1 1 0 225.5 Z" class="st3"/>
+ <text x="29.64" y="227.9" class="st4">Component 2</text> </g>
+ <g id="shape19-94" transform="translate(481.26,-27.25)">
+ <title>Ellipse.19</title>
+ <desc>Component 3</desc>
+ <g id="shadow19-95" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <path d="M0 225.5 A51.75 18 0 0 1 103.5 225.5 A51.75 18 0 1 1 0 225.5 Z" class="st2"/>
+ </g>
+ <path d="M0 225.5 A51.75 18 0 0 1 103.5 225.5 A51.75 18 0 1 1 0 225.5 Z" class="st3"/>
+ <text x="29.64" y="227.9" class="st4">Component 3</text> </g>
+ <g id="shape20-100" transform="translate(380.01,-189)">
+ <title>Sheet.20</title>
+ <desc>Component queue 1</desc>
+ <rect x="0" y="228.732" width="75.053" height="14.7677" class="st5"/>
+ <text x="4.22" y="238.52" class="st4">Component queue 1</text> </g>
+ <g id="shape21-105" transform="translate(380.01,-99)">
+ <title>Sheet.21</title>
+ <desc>Component queue 2</desc>
+ <rect x="0" y="228.732" width="75.053" height="14.7677" class="st5"/>
+ <text x="4.22" y="238.52" class="st4">Component queue 2</text> </g>
+ <g id="shape22-109" transform="translate(380.01,-9)">
+ <title>Sheet.22</title>
+ <desc>Component queue 3</desc>
+ <rect x="0" y="228.732" width="75.053" height="14.7677" class="st5"/>
+ <text x="4.22" y="238.52" class="st4">Component queue 3</text> </g>
+ <g id="shape23-113" transform="translate(134.76,-99)">
+ <title>Sheet.23</title>
+ <desc>Top-level queue</desc>
+ <rect x="0" y="228.732" width="70.553" height="14.7677" class="st5"/>
+ <text x="9.08" y="238.52" class="st4">Top-level queue</text> </g>
+ <g id="shape24-117" transform="translate(8.75951,-135.25)">
+ <title>Sheet.24</title>
+ <desc>All I/O requests for device</desc>
+ <g id="shadow24-118" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <path d="M0 243.5 L117.69 243.5" class="st6"/>
+ </g>
+ <path d="M0 243.5 L117.69 243.5" class="st8"/>
+ <rect x="20.7622" y="238.7" width="84.4758" height="9.59985" class="st10"/>
+ <text x="20.76" y="245.9" class="st4">All I/O requests for device</text> </g>
+ <g id="shape25-132" transform="translate(94.5085,-107.833) rotate(-27.451)">
+ <title>Sheet.25</title>
+ <desc>I/O requests for component 1</desc>
+ <g id="shadow25-133" transform="matrix(1,0,0,1,0.614038,1.94169)" class="st1">
+ <path d="M0 243.5 L186.92 243.5" class="st6"/>
+ </g>
+ <path d="M0 243.5 L186.92 243.5" class="st8"/>
+ <rect x="49.2589" y="238.7" width="96.7143" height="9.59985" class="st11"/>
+ <text x="49.26" y="245.9" class="st4">I/O requests for component 1</text> </g>
+ <g id="shape26-145" transform="translate(206.76,-135.25)">
+ <title>Sheet.26</title>
+ <desc>I/O requests for component 2</desc>
+ <g id="shadow26-146" transform="matrix(1,0,0,1,1.44,1.44)" class="st1">
+ <path d="M0 243.5 L164.94 243.5" class="st6"/>
+ </g>
+ <path d="M0 243.5 L164.94 243.5" class="st8"/>
+ <rect x="38.2679" y="238.7" width="96.7143" height="9.59985" class="st10"/>
+ <text x="38.27" y="245.9" class="st4">I/O requests for component 2</text> </g>
+ <g id="shape27-158" transform="translate(319.011,-107.833) rotate(27.451)">
+ <title>Sheet.27</title>
+ <desc>I/O requests for component 3</desc>
+ <g id="shadow27-159" transform="matrix(1,0,0,1,1.94169,0.614038)" class="st1">
+ <path d="M0 243.5 L186.92 243.5" class="st6"/>
+ </g>
+ <path d="M0 243.5 L186.92 243.5" class="st8"/>
+ <rect x="49.2589" y="238.7" width="96.7143" height="9.59985" class="st11"/>
+ <text x="49.26" y="245.9" class="st4">I/O requests for component 3</text> </g>
+ </g>
+</svg>
diff --git a/pos/drivers/MagneticStripeReader/README.md b/pos/drivers/MagneticStripeReader/README.md
index d9867f3b..60f797f5 100644
--- a/pos/drivers/MagneticStripeReader/README.md
+++ b/pos/drivers/MagneticStripeReader/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Magnetic Stripe Reader Driver Sample
- platform: UMDF2
- language: cpp
- category: POS
- description: This UMDF version 2 sample serves as a template for creating a new Magnetic Stripe Reader driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620202
---->
-
# Magnetic Stripe Reader Driver Sample
This sample serves as a template for creating a new Magnetic Stripe Reader driver.
diff --git a/pos/drivers/MagneticStripeReader/SampleMagneticStripeReaderDrv.inf b/pos/drivers/MagneticStripeReader/SampleMagneticStripeReaderDrv.inf
index f3401127..44dead0a 100644
--- a/pos/drivers/MagneticStripeReader/SampleMagneticStripeReaderDrv.inf
+++ b/pos/drivers/MagneticStripeReader/SampleMagneticStripeReaderDrv.inf
@@ -4,25 +4,12 @@
[Version]
Signature="$Windows NT$"
-Class=Sample ;
-ClassGuid={60B92AD1-5773-4FF7-82E3-9F83198325D6} ;
-Provider=Standard,NT$ARCH$
+Class=HidMsr
+ClassGuid={2A9FE532-0CDC-44F9-9827-76192F2CA2FB}
+Provider=%ManufacturerName%
CatalogFile=SampleMagneticStripeReaderDrv.cat
DriverVer=06/25/2015,14.29.18.671
-
-[Manufacturer]
-%ManufacturerName%=Standard,NT$ARCH$
-
-[Standard.NT$ARCH$]
-%DeviceName%=MyDevice_Install, Root\SampleMagneticStripeReaderDrv ;
-
-
-[ClassInstall32]
-AddReg=SampleClass_RegistryAdd
-
-[SampleClass_RegistryAdd]
-HKR,,,,%ClassName%
-HKR,,Icon,,"-10"
+PnpLockdown=1
[SourceDisksFiles]
SampleMagneticStripeReaderDrv.dll=1
@@ -30,6 +17,12 @@ SampleMagneticStripeReaderDrv.dll=1
[SourceDisksNames]
1 = %DiskName%
+[Manufacturer]
+%ManufacturerName%=Standard,NT$ARCH$
+
+[Standard.NT$ARCH$]
+%DeviceName%=MyDevice_Install, Root\SampleMagneticStripeReaderDrv ;
+
; =================== UMDF Device ==================================
[MyDevice_Install.NT]
@@ -71,8 +64,7 @@ SampleMagneticStripeReaderDrv.dll
; =================== Generic ==================================
[Strings]
-ManufacturerName="" ;
-ClassName="Samples" ;
+ManufacturerName="TEST" ; TODO - Update name
DiskName = "SampleMagneticStripeReaderDrv Installation Disk"
WudfRdDisplayName="Windows Driver Foundation - User-mode Driver Framework Reflector"
DeviceName="SampleMagneticStripeReaderDrv Device"
diff --git a/pos/drivers/barcodescanner/README.md b/pos/drivers/barcodescanner/README.md
index f2d841b8..c482a959 100644
--- a/pos/drivers/barcodescanner/README.md
+++ b/pos/drivers/barcodescanner/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Barcode Scanner Driver Sample
- platform: UMDF2
- language: cpp
- category: POS
- description: This UDMF version 2 sample serves as a template for creating a new Barcode Scanner driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620201
---->
-
# Barcode Scanner Driver Sample
This sample serves as a template for creating a new Barcode Scanner driver.
diff --git a/pos/drivers/barcodescanner/SampleBarcodeScannerDrv.inf b/pos/drivers/barcodescanner/SampleBarcodeScannerDrv.inf
index 9d32732f..db0c975f 100644
--- a/pos/drivers/barcodescanner/SampleBarcodeScannerDrv.inf
+++ b/pos/drivers/barcodescanner/SampleBarcodeScannerDrv.inf
@@ -4,25 +4,12 @@
[Version]
Signature="$Windows NT$"
-Class=Sample ;
-ClassGuid={70DF6E9F-68AA-4E29-AF0C-5AE9DB219214} ;
-Provider=Standard,NT$ARCH$
+Class=BarcodeScanner
+ClassGuid={C243FFBD-3AFC-45E9-B3D3-2BA18BC7EBC5}
+Provider=%ManufacturerName%
CatalogFile=SampleBarcodeScannerDrv.cat
DriverVer=06/25/2015,14.29.18.671
-
-[Manufacturer]
-%ManufacturerName%=Standard,NT$ARCH$
-
-[Standard.NT$ARCH$]
-%DeviceName%=MyDevice_Install, Root\SampleBarcodeScannerDrv ;
-
-
-[ClassInstall32]
-AddReg=SampleClass_RegistryAdd
-
-[SampleClass_RegistryAdd]
-HKR,,,,%ClassName%
-HKR,,Icon,,"-10"
+PnpLockdown=1
[SourceDisksFiles]
SampleBarcodeScannerDrv.dll=1
@@ -30,6 +17,12 @@ SampleBarcodeScannerDrv.dll=1
[SourceDisksNames]
1 = %DiskName%
+[Manufacturer]
+%ManufacturerName%=Standard,NT$ARCH$
+
+[Standard.NT$ARCH$]
+%DeviceName%=MyDevice_Install, Root\SampleBarcodeScannerDrv ;
+
; =================== UMDF Device ==================================
[MyDevice_Install.NT]
@@ -71,8 +64,7 @@ SampleBarcodeScannerDrv.dll
; =================== Generic ==================================
[Strings]
-ManufacturerName="" ;
-ClassName="Samples" ;
+ManufacturerName="TEST" ; TODO - Update name
DiskName = "SampleBarcodeScannerDrv Installation Disk"
WudfRdDisplayName="Windows Driver Foundation - User-mode Driver Framework Reflector"
DeviceName="SampleBarcodeScannerDrv Device"
diff --git a/print/OEM Printer Customization Plug-in Samples/README.md b/print/OEM Printer Customization Plug-in Samples/README.md
index 17d7a011..4a5fcf8d 100644
--- a/print/OEM Printer Customization Plug-in Samples/README.md
+++ b/print/OEM Printer Customization Plug-in Samples/README.md
@@ -5,28 +5,20 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: OEM Printer Customization Plug-in Samples
- platform: DLL
- language: cpp
- category: Print
- description: Provides examples of how to build OEM printer customization plug-ins.
- samplefwlink: https://go.microsoft.com/fwlink/?linkid=862105
---->
-
# OEM Printer Customization Plug-in Samples
-The OEMDLL samples are an illustration of OEM customization plug-ins. The BITMAP, OEMPS, OEMUI, OEMUNI, OEMPREAN, CUSTHLP, SyncSet, ThemeUI, PSUIRep, and Watermark samples do not affect the printer output. They are only examples of how to build OEM Customization DLLs of various types.
+The OEMDLL samples are an illustration of OEM customization plug-ins. The BITMAP, OEMPS, OEMUI, OEMUNI, OEMPREAN, CUSTHLP, SyncSet, ThemeUI, PSUIRep, and Watermark samples do not affect the printer output. They are only examples of how to build OEM Customization DLLs of various types.
The following samples are included as part of this sample set:
| Sample | Description |
-|--------|-------------|
-| BITMAP | a Unidrv-based bitmap rendering plug-in. This sample demonstrates how to write a Unidrv-based rendering plug-in that functions as a bitmap driver. The sample is based on the redesigned version of the OEMUNI sample. |
-| CUSTHLP | An OEM help-customization plug-in. This sample demonstrates adding OEM help to your customization plug-in and how to replace standard Microsoft supplied help with customized help. |
-| OEMPREAN | illustrates how you can leverage the pre-analysis feature in Unidrv. This sample is built on the redesigned version of the OEMUNI sample. |
+| --- | --- |
+| BITMAP | A Unidrv-based bitmap rendering plug-in. This sample demonstrates how to write a Unidrv-based rendering plug-in that functions as a bitmap driver. The sample is based on the redesigned version of the OEMUNI sample. |
+| CUSTHLP | An OEM help-customization plug-in. This sample demonstrates adding OEM help to your customization plug-in and how to replace standard Microsoft supplied help with customized help. |
+| OEMPREAN | Illustrates how you can leverage the pre-analysis feature in Unidrv. This sample is built on the redesigned version of the OEMUNI sample. |
| OEMPS | A PostScript rendering plug-in. This sample demonstrates how to write a PostScript-based rendering plug-in. |
| OEMUI | A user interface plug-in (both PostScript and Unidrv flavors are available). The OEMUI sample demonstrates common UI tasks such as adding additional elements to the UI (that is, items and pages). |
| OEMUNI | A user interface plug-in (both PostScript and Unidrv flavors are available). The OEMUI sample demonstrates common UI tasks such as adding additional elements to the UI (that is, items and pages). |
@@ -38,13 +30,15 @@ The following samples are included as part of this sample set:
| WATERMARK | Demonstrates how to produce customizable watermark page simulation by controlling PostScript injected in the printing stream. The components of the sample include a PostScript-based rendering module in conjunction with a UI module. The rendering module is responsible for the injection of the modified PostScript into the printing stream. This sample demonstrates the required COM interfaces, required functions with sample code and how to use the OEM's private DEVMODE section to communicate between the UI and rendering modules. |
| WATERMARKUNI | Demonstrates how to produce customizable watermark page simulation by controlling PCL data injected in the printing stream. The components of the sample include a UNIDRV-based rendering module in conjunction with a UI module. The rendering module is responsible for the injection of the PCL data into the printing stream. This sample demonstrates the required COM interfaces, required functions with sample code and how to use the OEM's private DEVMODE section to communicate between the UI and rendering modules. This sample works only if you have a page printer that has its own fonts. It doesn't download any fonts nor convert fonts to bitmap. |
-For information about how to develop a plug-in for customizing the print driver UI, see [COM Interfaces for UI Plug-Ins](https://docs.microsoft.com/en-us/windows-hardware/drivers/print/com-interfaces-for-ui-plug-ins).
+For information about how to develop a plug-in for customizing the print driver UI, see [COM Interfaces for UI Plug-Ins](https://docs.microsoft.com/windows-hardware/drivers/print/com-interfaces-for-ui-plug-ins).
-**Note** The OEMDLL samples are for the v3 print driver model only.
+> [!NOTE]
+> The OEMDLL samples are for the v3 print driver model only.
-**Note** To build this sample, you can use Microsoft Visual Studio 2017 (Community, Professional, or Enterprise) and Windows Driver Kit (WDK) 10. You can get Visual Studio 2017 [here](https://www.visualstudio.com) and WDK 10 [here](https://developer.microsoft.com/en-us/windows/hardware/download-kits-windows-hardware-development).
+To build this sample, you can use Microsoft Visual Studio 2017 (Community, Professional, or Enterprise) and Windows Driver Kit (WDK) 10. You can get Visual Studio 2017 [here](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) and WDK 10 [here](https://docs.microsoft.com/windows-hardware/drivers/download-the-wdk).
You can also build this sample with Visual Studio 2013 (Professional or Ultimate) and Windows Driver Kit (WDK) 8.1.
+
For Windows Driver Kit (WDK) 8 samples, download the WDK 8 samples pack. The samples in the WDK 8 samples pack will build only with Microsoft Visual Studio Professional 2012 (Professional or Ultimate) and WDK 8.
## Operating system requirements
@@ -57,23 +51,44 @@ Server - Windows Server 2008 R2 or later
To build a driver solution using Windows 10 driver kit (Windows Driver Kit (WDK)) and Visual Studio 2017, perform the following steps:
1. Open the solution file in Visual Studio 2017
+
1. Add all non-binary files (usually located in the \install directory of the sample) to the Package project
- 1. In the **Solution Explorer**, right click **Driver Files**
+
+ 1. In the **Solution Explorer**, right click **Driver Files**. If you can't find **Driver Files** in this step, please change the "Platform Toolset" like below
+
+ a. In the **Solution Explorer**, right click the Package project which you want to build and select **Properties**
+
+ b. Select **General** under the **Configuration Properties**
+
+ c. Change **Platform Toolset** to **WindowsKernelModeDriver10.0** or **WindowsUserModeDriver10.0**
+
1. Select **Add**, then click **Existing Item**
+
1. Navigate to the location to which you downloaded the sample, and select all the files in the install directory, or the equivalent set of non-binary files such as INFs, INIs, GPD, PPD files, etc.
+
1. Click **Add**
+
1. Configure these files to be added into the driver package
+
1. In the **Solution Explorer**, right click the Package project and select **Properties**
+
1. In the left pane, click **Configuration Properties** > **Driver Install** > **Package Files**.
+
1. In the right pane, use the ellipsis button (...) to browse to the set of files that needs to be added to the driver package. All the data files that you added in **Step 2-c**, except the INF file, should be added. This configuration is per-architecture, so this configuration must be repeated for each architecture that will be built.
+
1. Click **OK**
+
1. Open the INF file and edit it to match the built output
+
1. Open the INF file
- 1. In the Version section, add a reference to a catalog file that matches the .INF name like this: CatalogFile=XpsDrvSmpl.cat
+
+ 1. In the Version section, add a reference to a catalog file that matches the .INF name like this: CatalogFile=XpsDrvSmpl.cat
+
1. In the SourceDisksFiles section, change the location of the DLL files you are building, to =1. This indicates that there is no architecture specific directory in this driver. If you ship multiple architectures simultaneously, you will need to collate the driver INF manually.
-At this point, Visual Studio 2017 will be able to build a driver package and output the files to disk. In order to configure driver signing and deployment, see [Developing, Testing, and Deploying Drivers](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/).
-For more information about how to build a driver solution using Microsoft Visual Studio, see [Building a Driver](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/building-a-driver).
+At this point, Visual Studio 2017 will be able to build a driver package and output the files to disk. In order to configure driver signing and deployment, see [Developing, Testing, and Deploying Drivers](https://docs.microsoft.com/windows-hardware/drivers/develop/).
+
+For more information about how to build a driver solution using Microsoft Visual Studio, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver).
## Run the sample
@@ -87,15 +102,20 @@ After building the samples, you can install them by using the Add Printer Wizard
This sample includes the following features:
-- The supported ColorMode options in the bitmap driver's GPD are monochrome, 4bpp, 8bpp, and 24bpp.
-- The bitmap driver implements the IPrintOemUni::ImageProcessing callback to access bitmap data one band at a time. The driver's implementation of ImageProcessing buffers the band data every time it is called. The function is also responsible for filling the BITMAPINFOHEADER and COLORTABLE structures that are necessary for dumping the data out to a bitmap file.
-- The bitmap driver implements the OEMEndDoc DDI hook to dump the buffered bitmap data to the spooler at the end of the print job. The driver's implementation of OEMEndDoc dumps the headers first and then the buffered data.
-- The GrowBuffer helper function is called every time the buffer needs to be enlarged to hold the bitmap data.
+- The supported ColorMode options in the bitmap driver's GPD are monochrome, 4bpp, 8bpp, and 24bpp.
+
+- The bitmap driver implements the IPrintOemUni::ImageProcessing callback to access bitmap data one band at a time. The driver's implementation of ImageProcessing buffers the band data every time it is called. The function is also responsible for filling the BITMAPINFOHEADER and COLORTABLE structures that are necessary for dumping the data out to a bitmap file.
+
+- The bitmap driver implements the OEMEndDoc DDI hook to dump the buffered bitmap data to the spooler at the end of the print job. The driver's implementation of OEMEndDoc dumps the headers first and then the buffered data.
+
+- The GrowBuffer helper function is called every time the buffer needs to be enlarged to hold the bitmap data.
+
- The bitmap driver renders multi-page documents into a single large output bitmap file.
This sample has the following limitations:
-- The plug-in does not support landscape orientation although the option exists in the GPD.
+- The plug-in does not support landscape orientation although the option exists in the GPD.
+
- In 24bpp mode, documents larger than three pages will produce an extremely large bitmap (.bmp) file. Although the output is correct, you might not be able to view it because of memory limitations in the bitmap viewer.
### OEMPREAN
@@ -104,21 +124,23 @@ When preanalysis is enabled in the GPD (for more details about preanalysis, see
In order for plugins to also take part in preanalysis, they can enable OEM preanalysis by specifying the `"*PreAnalysisOptions: 8"` parameter in the GPD. The OEM rendering plug-in must hook both `DrvStartBanding` and `DrvNextBand` when this mode is enabled in the GPD. The OEM rendering plug-in must test the `pptl` parameter of the `OEMStartBanding` call to determine whether preanalysis has been enabled on this page. If the `pptl` parameter is `NULL`, preanalysis has been enabled, and the OEM rendering plug-in should consider all drawing calls up to the first call to `OEMNextBand` to be part of preanalysis.
-During these preanalysis phase drawing calls, the plug-in should not draw on the surface. The plug-in should also not call back into unidrv. You should use this phase only for analysis of the objects on the page. For example, certain printers need to handle black objects that intersect with color objects differently from black objects that appear by themselves. Other printers might need to halftone `StretchBlt` objects differently from `BitBlt` objects.
-You should be aware that after preanalysis, you might get more calls than you saw in the normal rendering, because primitives that cross band boundaries yield two or more DDI calls after the preanalysis pass.
+During these preanalysis phase drawing calls, the plug-in should not draw on the surface. The plug-in should also not call back into unidrv. You should use this phase only for analysis of the objects on the page. For example, certain printers need to handle black objects that intersect with color objects differently from black objects that appear by themselves. Other printers might need to halftone `StretchBlt` objects differently from `BitBlt` objects.
+You should be aware that after preanalysis, you might get more calls than you saw in the normal rendering, because primitives that cross band boundaries yield two or more DDI calls after the preanalysis pass.
The sample uses the `bPreAnalysis` flag in the OEMPDEV structure to denote whether a particular pass is the preanalysis pass or the actual rendering pass. If the `bPreAnalysis` flag is set, it indicates that the current pass is the preanalysis pass. The sample implements all of the drawing function hooks in Ddihook.cpp. The sample uses the `OEMStartBanding` and `OEMNextBand` functions to respectively set and reset the `bPreAnalysis` flag. The sample also uses the `DBG_CLIPOBJ` debug macro function to dump the bounds of the clipping rectangle available for preanalysis in each of the drawing functions during the preanalysis pass. To view all of the debug output in the debugger, you must set the debug level to VERBOSE. The rest of the sample is identical to the Oemuni sample that illustrates a basic OEM rendering plug-in.
-**Note** that the surface used during preanalysis might differ from the surface passed in during the rendering pass.
+> [!NOTE]
+> The surface used during preanalysis might differ from the surface passed in during the rendering pass.
### PTPCPIPR
-This sample is an educational example that illustrates the basic functionality that a Unidrv plug-in for the `IPrintOemPrintTicketProvider` interface should implement.
-The primary functionality of the plug-in is to support the PhotoPrintingIntent PrintSchema keyword. The PhotoPrintingIntent keyword is designed to provide a mechanism for photo printers to support enhancements that are specific to photo printing. An application or the user (through the print UI) can then specify whether a particular print job is a photo-printing job, in which case the device can apply appropriate enhancements.
-The intent setting is communicated to the device driver in a PrintTicket. The actual enhancements made are device-specific, and as such, the driver has to map the high-level intent setting into specific output settings, like resolution or bpp. This plug-in sample demonstrates the conversion.
+This sample is an educational example that illustrates the basic functionality that a Unidrv plug-in for the `IPrintOemPrintTicketProvider` interface should implement.
+The primary functionality of the plug-in is to support the PhotoPrintingIntent PrintSchema keyword. The PhotoPrintingIntent keyword is designed to provide a mechanism for photo printers to support enhancements that are specific to photo printing. An application or the user (through the print UI) can then specify whether a particular print job is a photo-printing job, in which case the device can apply appropriate enhancements.
+The intent setting is communicated to the device driver in a PrintTicket. The actual enhancements made are device-specific, and as such, the driver has to map the high-level intent setting into specific output settings, like resolution or bpp. This plug-in sample demonstrates the conversion.
The plug-in implements the `ExpandIntentOptions` method of the `IPrintOemPrintTicketProvider` interface. This method is called with an input print-ticket. The plug-in checks if the print-ticket contains a photo-printing intent setting, and if so, removes the setting, while instead adding to the print-ticket output settings as mentioned above. The code sample uses MSXML6 for all PrintTicket XML handling.
### UINUIREP
This sample shows how a plug-in for a Unidrv-based driver can replace the default UI. It provides new property sheets for the printer property and printing preferences pages.
Use this sample as an example of implementing full UI replacement in a Unidrv-based plugin. It also demonstrates the use of the new `IPrintCoreHelper` interface.
-This sample is only provided for educational purposes and should not be used in a production environment. \ No newline at end of file
+
+This sample is only provided for educational purposes and should not be used in a production environment.
diff --git a/print/SampleOpenXPS/README.md b/print/SampleOpenXPS/README.md
index e68b97ce..98269683 100644
--- a/print/SampleOpenXPS/README.md
+++ b/print/SampleOpenXPS/README.md
@@ -5,19 +5,11 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: OpenXPS Documents Print Sample
- platform: Application
- language: cpp
- category: Print
- description: Contains a set of documents that exercise a variety of features of OpenXPS.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617941
---->
-
# OpenXPS Documents Print Sample
This sample contains a set of documents that were generated from a variety of sources, including those generated from the Windows Presentation Foundation in the .NET Framework, from Office 2007, and from the Microsoft XPS Document Writer (MXDW). A few of the documents were either hand-built from scratch or hand-modified from another source. They have been included to provide you with a few documents that exercise a variety of features of the XML Paper Specification.
-In addition, a few high-quality documents have been provided in the Showcase directory to highlight some of the XPS advantages in terms of screen-to-print fidelity. We've also created some documents that are intended to fail, by violating at least one conformance rule. These are in the ConformanceViolations directory. For information about OpenXPS in Windows, see [Improvements in XPSDrv](http://msdn.microsoft.com/en-us/library/windows/hardware/jj218730(v=vs.85).aspx) and [OpenXPS Support in Windows](http://msdn.microsoft.com/en-us/library/windows/hardware/br259130.aspx).
+In addition, a few high-quality documents have been provided in the Showcase directory to highlight some of the XPS advantages in terms of screen-to-print fidelity. We've also created some documents that are intended to fail, by violating at least one conformance rule. These are in the ConformanceViolations directory. For information about OpenXPS in Windows, see [Improvements in XPSDrv](https://docs.microsoft.com/windows-hardware/drivers/print/improvements-in-xpsdrv) and [Driver Support for OpenXPS](https://docs.microsoft.com/windows-hardware/drivers/print/driver-support-for-openxps).
diff --git a/print/SampleXPS/README.md b/print/SampleXPS/README.md
index 2d6c57f3..795694d2 100644
--- a/print/SampleXPS/README.md
+++ b/print/SampleXPS/README.md
@@ -5,19 +5,11 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: XPS Documents Print Sample
- platform: Application
- language: cpp
- category: Print
- description: Contains a set of documents that exercise a variety of features of the XML Paper Specification.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617942
---->
-
# XPS Documents Print Sample
This sample is a set of documents that were generated from a variety of sources, including those generated from the Windows Presentation Foundation in the .NET Framework, from Office 2007, and from the Microsoft XPS Document Writer (MXDW). The set of documents also includes documents that were either hand-built from scratch or hand-modified from another source. They have been included to provide you with a few documents that exercise a variety of features of the XML Paper Specification.
-In addition, a few high-quality documents have been provided in the Showcase directory to highlight some of the XPS advantages in terms of screen-to-print fidelity. There are also some documents that are intended to fail by violating at least one conformance rule. These are in the ConformanceViolations directory. For information about XPS in Windows, see [XPS Printing Features](http://msdn.microsoft.com/en-us/library/windows/hardware/ff564299(v=vs.85).aspx).
+In addition, a few high-quality documents have been provided in the Showcase directory to highlight some of the XPS advantages in terms of screen-to-print fidelity. There are also some documents that are intended to fail by violating at least one conformance rule. These are in the ConformanceViolations directory. For information about XPS in Windows, see [XPS Printing Features](https://docs.microsoft.com/windows-hardware/drivers/print/xps-printing-features).
diff --git a/print/SimplePipelineFilter/README.md b/print/SimplePipelineFilter/README.md
index 7c5a0cc5..b3a1567c 100644
--- a/print/SimplePipelineFilter/README.md
+++ b/print/SimplePipelineFilter/README.md
@@ -5,21 +5,15 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Print Pipeline Simple Filter
- platform: DLL
- language: cpp
- category: Print
- description: This sample shows how to use the print pipeline's filter interfaces.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617944
---->
-
# Print Pipeline Simple Filter
The printing system supports a print filter pipeline. The pipeline is run when a print job is consumed by the print spooler and sent to the device.
This sample shows how to use the print pipeline's filter interfaces.
-The filters in the print pipeline consume a certain data type and produce a certain data type. This information is specified in the pipeline configuration file on a per printer driver basis. The WDK print filter sample contains two filter samples: one that consumes and produces XPS data type, and the other one consumes and produces opaque byte stream. For more information, see the [XpsDrv](http://msdn.microsoft.com/en-us/windows/hardware/gg463364) whitepaper.
+The filters in the print pipeline consume a certain data type and produce a certain data type. This information is specified in the pipeline configuration file on a per printer driver basis.
+
+The WDK print filter sample contains two filter samples: one that consumes and produces XPS data type, and the other one consumes and produces opaque byte stream. For more information, see [XPS Printer Driver (XPSDrv)](https://docs.microsoft.com/windows-hardware/drivers/print/xpsdrv-printer-driver).
diff --git a/print/XPSDrvSmpl/README.md b/print/XPSDrvSmpl/README.md
index 64491225..f23f78ad 100644
--- a/print/XPSDrvSmpl/README.md
+++ b/print/XPSDrvSmpl/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: XPSDrv Driver and Filter Sample
- platform: DLL
- language: cpp
- category: Print
- description: Provide a starting point for developing XPSDrv printer drivers and to illustrate the facility and potential of an XPSDrv print driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617950
---->
-
# XPSDrv Driver and Filter Sample
This sample is intended to provide a starting point for developing XPSDrv printer drivers and to illustrate the facility and potential of an XPSDrv print driver. This goal is accomplished by implementing a number of real-world features within a set of XPS print pipeline filters that are configured through a configuration plug-in that supports custom UI content and PrintTicket handling.
@@ -24,38 +16,59 @@ Windows includes a print architecture and a document format known as XPS (XML Pa
This sample is intended to provide a starting point for developing XPSDrv printer drivers and to illustrate the facility and potential of an XPSDrv print driver. This goal is accomplished by implementing a number of real-world features within a set of XPS print pipeline filters that are configured through a configuration plug-in that supports custom UI content and PrintTicket handling.
-The sample broadly consists of three components: a set of filters, a configuration plug-in for handling custom UI content, and a configuration plug-in for handling more advanced PrintTicket features. For more information, see [XPS Printing Features](https://docs.microsoft.com/en-us/windows-hardware/drivers/print/xps-printing-features).
+The sample broadly consists of three components: a set of filters, a configuration plug-in for handling custom UI content, and a configuration plug-in for handling more advanced PrintTicket features. For more information, see [XPS Printing Features](https://docs.microsoft.com/windows-hardware/drivers/print/xps-printing-features).
## Build the sample
To build a driver solution using Windows Driver Kit (WDK) 10 and Visual Studio 2017, perform the following steps.
1. Open the solution file in Visual Studio 2017.
+
1. Add all non-binary files (usually located in the \\install directory of the sample) to the Package project:
+
1. In the **Solution Explorer**, expand the **package** project and right click **Driver Files**
+
1. Select **Add**, then click **Existing Item**
+
1. Navigate to the location to which you downloaded the sample, and select all the files in the **install** directory, or the equivalent set of non-binary files such as INFs, INIs, GPD, PPD files, etc.
+
1. Click **Add**
+
1. Configure these files to be added into the driver package:
+
1. In the **Solution Explorer**, right click on the solution and choose **Add** > **New Project**. Choose **Driver Install Package** under Visual C++/Windows Driver/Package.
+
1. In the **Solution Explorer**, right click the **Driver Package** project and select **Properties**.
+
1. In the left pane, click **Configuration Properties** \> **Driver Install** \> **Package Files**. (If **Package Files** is not available, you may need to re-install the **Windows Driver Kit**.)
+
1. In the right pane, click **<Edit...>** and use the ellipsis button (...) to browse to the set of files that needs to be added to the driver package. All of the data files added in **Step 2.iii**, except the INF file, should be added. This configuration is per architecture, so this configuration must be repeated for each architecture that will be built.
+
1. Click **OK**.
+
1. Add a reference to the driver package.
+
1. In the **Solution Explorer**, right click the **package** project and select **Add Reference**.
+
1. In the right pane, check the **Driver Package** created in step 3.
+
1. Click **OK**.
+
1. Open the INF file and edit it to match the built output.
+
1. Open the INF file.
+
1. In the Version section, add a reference to a catalog file like this: CatalogFile=XpsDrvSmpl.cat.
+
1. In the SourceDisksFiles section, change the location of the DLL files you are building to =1. This indicates that there is no architecture specific directory in this driver. If you ship multiple architectures simultaneously, you will need to collate the driver INF manually.
-At this point, Visual Studio 2017 will be able to build a driver package and output the files to disk. In order to configure driver signing and deployment, see [Developing, Testing, and Deploying Drivers](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/).
+At this point, Visual Studio 2017 will be able to build a driver package and output the files to disk. In order to configure driver signing and deployment, see [Developing, Testing, and Deploying Drivers](https://docs.microsoft.com/windows-hardware/drivers/develop/).
-**Note** If you compile your sample driver with Microsoft Visual Studio version 10, or 11 with the \_DEBUG flag set, then you should not use CComVariant on the following two XPS Print Filter Pipeline properties:
+> [!NOTE]
+> If you compile your sample driver with Microsoft Visual Studio version 10, or 11 with the \_DEBUG flag set, then you should not use CComVariant on the following two XPS Print Filter Pipeline properties:
- XPS\_FP\_USER\_TOKEN
+
- XPS\_FP\_PRINTER\_HANDLE
There is a known issue with the current implementation of the Print Filter Pipeline, where the variant type for these two properties is set to VT\_BYREF. And as a result of this known issue, any filter binary that is compiled with the \_DEBUG flag set will experience the ATLASSERT() failure. This is because when you use the CComVariant, its destructor checks the returned value from the Clear() function, as shown:
@@ -76,6 +89,7 @@ When you compile this sample driver with Visual Studio version 9, you don't expe
The sample has the following prerequisites:
- Microsoft XPS Document Writer print driver and the XPS filter-pipeline infrastructure.
+
- Microsoft MSXML 6.0
Install the driver through the **Add Printer Wizard** by selecting \<driver root\>\\install as the source for the driver install.
@@ -88,11 +102,13 @@ This sample can be used as a basis for implementing a driver based on the new XP
The Page Scaling filter is written by using the stream interface to attempt to demonstrate how to use the stream interface. It thus depends on a ZIP library to handle the PK archive structure. The sample does not include the code for the PK archive handling.
-Two interfaces are defined in *ipkarch.h* and *ipkfile.h* that need support from an additional PK archive handling module called pkarch.dll. Pkarch.dll is a file that is included in the [PKWare SDK](http://www.pkware.com/software/developer-tools/sdk/pkzip-standard-toolkit). If this module is not present, the page scaling filter sample will revert to merely copying the data from the read stream to the write stream. Developers who are using this sample can choose one of the following options:
+Two interfaces are defined in *ipkarch.h* and *ipkfile.h* that need support from an additional PK archive handling module called pkarch.dll. Pkarch.dll is a file that is included in the [PKWare SDK](https://support.pkware.com/pages/viewpage.action?pageId=721433). If this module is not present, the page scaling filter sample will revert to merely copying the data from the read stream to the write stream. Developers who are using this sample can choose one of the following options:
- Simplify the scaling filter to use the XPS interfaces (like the other four filters)
+
- License the third-party zip library that is used in the sample
-- Modify the sample to use another ZIP library. For example, you can modify the sample to use the [Packaging API Reference](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/opc/packaging-programming-reference)
+
+- Modify the sample to use another ZIP library. For example, you can modify the sample to use the [Packaging API Reference](https://docs.microsoft.com/previous-versions/windows/desktop/opc/packaging-programming-reference)
IPKArch defines an interface for initializing, controlling, and accessing the PK archive. IPKFile defines an interface that abstracts the details of a PK archive file header record from the XPS container handling. Access to the files within the archive is provided through a map between the file name and file objects that support the IPKFile interface. This allows the XPS processing code to retrieve file data by name (a convenience as the interaction between parts and relationships between parts is defined using the part name).
@@ -103,8 +119,11 @@ There are five filters that are split into two types: four use the XPS filter in
The four filters that use the XPS interface provide support for the following:
- The Watermark Filter is responsible for adding mark-up to Fixed Page content to express textual, bitmap, and vector-based watermarks.
+
- The Booklet Filter is responsible for page re-ordering and padding page insertion to create booklets from the XPS document. Note that this filter re-uses the NUp filter to provide appropriate page transformation.
+
- The NUp Filter is responsible for transforming and combining logical pages onto physical pages to provide multiple page per sheet support.
+
- The Color Management Filter is responsible for constructing and applying color transforms to Fixed Page content.
The stream interface filter provides Page Scaling support (that is, wrapping content with the appropriate transforms to scale from a source Fixed Page to the destination).
@@ -142,7 +161,9 @@ The Watermark filter is intended to demonstrate adding presentation content to t
The filter is configured by parsing an input PrintTicket by using DOM to extract the relevant features and options. If the functionality is enabled, the filter processes the document as required. The PrintTicket is constructed through the following algorithm to provide settings at the appropriate scope (Fixed Document Sequence, Fixed Document and Fixed Page):
1. Validate and merge the print ticket from the FDS with the default PrintTicket converted from the default DevMode in the property bag. The resultant ticket will be the Job level ticket.
+
1. Validate and merge the print ticket from the current FD with the Job level ticket from step 1. The resultant ticket will be the document level ticket.
+
1. Validate and merge the print ticket from the current FP with the Doc level ticket from step 2. The resultant ticket will be the page level ticket.
When a watermark is enabled in the PrintTicket, the filter creates a watermark of the appropriate type (text, raster, or vector). This is returned as a generic watermark interface that abstracts the watermark type from the filter. The filter then calls the watermark object to send any resources that it may require to the filter pipeline (the font for text, the bitmap for raster, and none for vector). All resources are added through a resource cache that enables the watermark object to ignore any problems with sending repeated resources (the cache checks if the resource is present and only sends it if it has not seen the resource before). With the resource in place, the filter instantiates a SAX handler passing the watermark object. The SAX handler is used to parse the Fixed Page, allowing the filter to control when it inserts the watermark into the Fixed Page; when underlay is required, the mark-up is inserted when the FixedPage start element is encountered and when overlay is required the mark-up is inserted when FixedPage end element is encountered. By passing the abstracted watermark object, the SAX handler can be re-used for any watermark as it merely requests appropriate mark-up from the watermark object and inserts it into the Fixed Page mark-up as appropriate.
@@ -152,14 +173,19 @@ When a watermark is enabled in the PrintTicket, the filter creates a watermark o
XPS documents can contain a range of vector elements that contain color data that describes how the elements should be rendered on a specific device. The following elements support color data:
- Color
+
- Fill
+
- Stroke
When any of these elements are found in a fixed page, the SAX handler passes the associated color data to a color conversion object. This uses the following algorithm to convert the color:
1. The XML mark-up is broken down into color channel values, color channel value types, color format, and any other color details contained in the color mark-up string.
+
1. The resulting values are color transformed in conjunction with preferences defined in the PrintTicket. The result is a new set of color values.
+
1. These new values are used to reconstructs a color reference containing the new color values.
+
1. The newly constructed color reference is used in place of the original color reference, resulting in the transformed color output.
### Bitmap Resources
@@ -173,9 +199,13 @@ After the color managed bitmap object is created, the object is passed to a reso
If a bitmap has not been handled yet, the caching manager calls a write data method in the color bitmap object to indicate that the bitmap should write itself out to the filter pipeline. The write process also includes the application of a color transform to the bitmap. The following steps occur to apply the transform:
1. A stream is created to the bitmap itself and the bitmap is loaded into memory.
+
1. A bitmap codec object is created that takes the bitmap and uses an appropriate codec to decompress the bitmap and present the bitmap data and values.
+
1. The bitmap data is then converted by using a color transform supplied by the color profile management class.
+
1. The bitmap codec object re-encodes the bitmap by using a matching codec to that used to decode the bitmap.
+
1. The encoded bitmap is streamed back out to the container.
### Booklet Filter
@@ -209,11 +239,17 @@ Within the filter, SAX is used to parse the XPS container with each fixed page b
The stream filter is required to handle the Open Packaging conventions that are used by an XPS document. These conventions can be thought of as the document structure above that of the PK archive itself. Sources for a set of classes are provided that support processing of the XPS document in terms of the constituent files in the PK archive. This includes:
- Initiating the document processing based on the root relationships part defined in the package.
+
- Validation of the parts within the package against their content type and usage.
+
- Processing of Fixed Document Sequence and all resources associated with it.
+
- Processing of the Fixed Documents within the Fixed Document Sequence and all resources associated with them.
+
- Processing of the Fixed Page parts with the Fixed Documents and all resources associated with them.
+
- Passing Fixed Page content processing to a registered FP handler for modification.
+
- Passing all parts on to a PK archive handling module with valid ordering.
The XPS processor is not responsible for extracting or decompressing part data from the PK archive. This task is the responsibility of an additional module that implements an interface known to the XPS container handling code.
@@ -223,15 +259,21 @@ The XPS processor is not responsible for extracting or decompressing part data f
The UI Plug-in is intended to demonstrate how to extend the standard Unidrv UI to add additional property sheets and controls and to provide support for custom features that are not supported by the core Unidrv UI. Three new pages have been added that allow control of the sample filters:
- Color--enables configuration of the color conversion filter.
+
- Watermarks--enables a watermark to be selected and enable configuration of its properties for use in the watermark filter.
+
- Features--includes controls to configure the page scaling, booklet, and NUp filters. In addition, the standard driver settings--duplex, intent, and page borders--can also be modified.
Various UI control types have been implemented on these property pages to enable a user to modify settings in the driver. The UI supports the following control types:
- Check-box
+
- Combo-box
+
- List-Box
+
- Edit-Box
+
- Edit number (with buddy up/down control)
The settings that associated with each of these controls are stored as one the following types:
@@ -247,4 +289,4 @@ When a property page receives a message for a control, it looks up the relevant
The sample Print Ticket Provider plug-in is intended to demonstrate how to validate and map driver settings from a DevMode description to a Print Ticket description and back again. The driver allows configuration of custom settings through a custom user interface. These custom settings are represented as either GPD options or in the OEM private DevMode and are mapped to and from the Print Ticket using an XML schema.
-To support Print Ticket handling, the Unidrv UI Plug-in Print Ticket Provider Interface is utilized. The Unidrv UI Plug-in interface includes methods that allow mapping of DevMode to and from a Print Ticket Schema. A collection of feature conversion objects are stored at the plug-in interface level, each of which is responsible for the conversion of a specific feature (Color, Watermark, Booklet, Scaling, and NUp). Whenever the Unidrv core calls through the external interface of the plug-in to convert from DevMode to Print Ticket or Print Ticket to DevMode, the collection is iterated through calling each conversion object in turn; each then perform its own DevMode/Print Ticket mapping via the appropriate get and set functions. The sample get and set functions provide an interface to read and write the GPD options, OEM private DevMode, and Print Ticket keyword value pairs. \ No newline at end of file
+To support Print Ticket handling, the Unidrv UI Plug-in Print Ticket Provider Interface is utilized. The Unidrv UI Plug-in interface includes methods that allow mapping of DevMode to and from a Print Ticket Schema. A collection of feature conversion objects are stored at the plug-in interface level, each of which is responsible for the conversion of a specific feature (Color, Watermark, Booklet, Scaling, and NUp). Whenever the Unidrv core calls through the external interface of the plug-in to convert from DevMode to Print Ticket or Print Ticket to DevMode, the collection is iterated through calling each conversion object in turn; each then perform its own DevMode/Print Ticket mapping via the appropriate get and set functions. The sample get and set functions provide an interface to read and write the GPD options, OEM private DevMode, and Print Ticket keyword value pairs.
diff --git a/print/XpsRasFilter/README.md b/print/XpsRasFilter/README.md
index ccd22b8c..55f637df 100644
--- a/print/XpsRasFilter/README.md
+++ b/print/XpsRasFilter/README.md
@@ -5,38 +5,39 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: XPS Rasterization Filter Service Sample
- platform: DLL
- language: cpp
- category: Print
- description: Implements an XPSDrv filter that rasterizes fixed pages in an XPS document.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617951
---->
-
# XPS Rasterization Filter Service Sample
This sample implements an XPSDrv filter that rasterizes fixed pages in an XPS document. Hardware vendors can modify this sample to build an XPSDrv filter that produces bitmap images for their printers or other display devices. The sample uses the XPS Rasterization Service that creates rasterizer objects for use by XPSDrv filters. A rasterizer object takes an XPS Object Model (XPS OM) page object and creates a bitmap of a specified region of the page. The sample implements an XPSDrv filter (xpsrasfilter.dll) that can be inserted into the XPS Filter Pipeline. For each fixed page in an XPS document, the sample filter does the following:
- Uses the XPS rasterization service to create a rasterizer object for the fixed page.
+
- Partitions the fixed page into several horizontal bands.
+
- Uses the rasterizer object to render each horizontal band as a bitmap image.
-The Print Filter Pipeline is part of the XPS Print Path [Windows Print Path Overview](https://docs.microsoft.com/windows-hardware/drivers/print/windows-print-path-overview). Fixed pages are sent as an XPS data stream from the XPS Spooler to the print filter pipeline. The print filter pipeline manager takes the XPS fixed page, calls each filter in the order defined in the pipeline configuration file, and then sends either Fixed Page OM objects or a data stream to each filter as required. The filters process the data and return either Fixed Page OM objects or a data stream back to the print filter pipeline manager. (See MSDN entry for Filter Pipeline Interfaces items IXpsDocumentProvider, IXpsDocumentConsumer, IPrintWriteStream, and IPrintReadStream.)
+The Print Filter Pipeline is part of the XPS Print Path [Windows Print Path Overview](https://docs.microsoft.com/windows-hardware/drivers/print/windows-print-path-overview). Fixed pages are sent as an XPS data stream from the XPS Spooler to the print filter pipeline. The print filter pipeline manager takes the XPS fixed page, calls each filter in the order defined in the pipeline configuration file, and then sends either Fixed Page OM objects or a data stream to each filter as required. The filters process the data and return either Fixed Page OM objects or a data stream back to the print filter pipeline manager.
+
+For more information, see [IXpsDocumentProvider](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/filterpipeline/nn-filterpipeline-ixpsdocumentprovider), [IXpsDocumentConsumer](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/filterpipeline/nn-filterpipeline-ixpsdocumentconsumer), [IPrintWriteStream](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/filterpipeline/nn-filterpipeline-iprintwritestream), and [IPrintReadStream](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/filterpipeline/nn-filterpipeline-iprintreadstream).
As a print filter pipeline service, the XPS Rasterization Service can be loaded into the filter pipeline when the pipeline is initialized by adding a filter service provider tag to the configuration XML file (for example, \<FilterServiceProvider dll="XpsRasterService.dll"/\>). The service is then available to be called by the filters when they are initialized and called by the print filter pipeline manager.
The XPS Rasterization Service operates as follows:
- The calling filter initializes an instance of the rasterizer by passing in the XPS OM for the fixed page.
+
- The calling filter calls the RasterizeRect method of the rasterizer to render a specified rectangle area of the fixed page.
+
- RasterizeRect writes the WIC (Windows Imaging Component) bitmap data to memory. (The address is specified as a parameter to RasterizeRect.)
The default parameters in this sample are as follows:
- Letter-sized physical page (can override in print ticket).
+
- 0.25-inch margins (creating an 8-inch by 10.5-inch imageable area).
+
- Scaling is set to FitApplicationBleedSizeToImageableSize.
-- Destination resolution set to 96 dpi (can override in print ticket). \ No newline at end of file
+
+- Destination resolution set to 96 dpi (can override in print ticket).
diff --git a/print/autoconfig/README.md b/print/autoconfig/README.md
index 2d53ad2f..a4311618 100644
--- a/print/autoconfig/README.md
+++ b/print/autoconfig/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Print auto-configuration sample
- platform: Utility
- language: cpp
- category: Print
- description: Demonstrates how to implement auto-configuration in v4 print drivers.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617938
---->
-
# Print auto-configuration sample
This sample demonstrates how to implement auto-configuration in v4 print drivers.
@@ -24,30 +16,31 @@ This sample demonstrates how to implement auto-configuration in v4 print drivers
Many printers ship with optional components which are not present in all versions of the printer. For these printers, it's important that the driver only shows options which are enabled by the currently installed hardware. For example, if a stapling unit is optional for a particular printer, then the driver shouldn't expose the stapling feature to the end user if that unit is not installed.
-Windows auto-configuration allows a print driver to specify a mapping between driver installable options and the state of the printer as expressed through the Bidi Schema.
+Windows auto-configuration allows a print driver to specify a mapping between driver installable options and the state of the printer as expressed through the Bidi Schema.
-For more information on auto-configuration, see [Printer Autoconfiguration](http://msdn.microsoft.com/en-us/library/windows/hardware/ff560774(v=vs.85).aspx).
+For more information on auto-configuration, see [Printer Autoconfiguration](https://docs.microsoft.com/windows-hardware/drivers/print/printer-autoconfiguration).
-For more information on the Bidi Schema, see [Bidirectional Communication Schema](https://msdn.microsoft.com/en-us/library/windows/hardware/ff545169(v=vs.85).aspx).
+For more information on the Bidi Schema, see [Bidirectional Communication Schema](https://docs.microsoft.com/windows-hardware/drivers/print/bidirectional-communication-schema).
## Build the sample
The auto-configuration sample doesn't have any binaries to be built. It may be installed by using **Add Printer Wizard** and supplying the AutoCnfg.INF as the INF file.
-But to build a signed driver package using Windows Driver Kit (WDK) 10 and Visual Studio 2015, for the project file (csproj) that ships with the auto-configuration sample, perform the following steps.
+Too build a signed driver package using Windows Driver Kit (WDK) 10 and Visual Studio 2015, for the project file (csproj) that ships with the auto-configuration sample, perform the following steps.
1. Open the solution file in Visual Studio 2015.
-2. On the **Build** menu, select **Configuration Manager...**.
+1. On the **Build** menu, select **Configuration Manager...**.
-3. In **Configuration Manager**, select the **Configuration** and **Platform** that you want to build your driver for.
+1. In **Configuration Manager**, select the **Configuration** and **Platform** that you want to build your driver for.
-**Note** When the driver builds, it will be placed in the output folder for the architecture you selected.
+> [!NOTE]
+> When the driver builds, it will be placed in the output folder for the architecture you selected.
-At this point, Visual Studio will be able to build a driver package and output the files to disk. In order to configure driver signing and deployment, see [Developing, Testing, and Deploying Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554651(v=vs.85).aspx).
+At this point, Visual Studio will be able to build a driver package and output the files to disk. In order to configure driver signing and deployment, see [Developing, Testing, and Deploying Drivers](https://docs.microsoft.com/windows-hardware/drivers/develop/).
-For more information about how to build a driver solution using Microsoft Visual Studio, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644).
+For more information about how to build a driver solution using Microsoft Visual Studio, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver).
## Run the sample
-To run the auto-configuration sample, you must install this driver to support a printer which is installed against either a WSD port, or TCP/IP port. Additionally, USB printers may be supported if the driver is updated to incorporate USB Bidi Javascript, as described here: [Print Driver USB Monitor and Bidi Sample](https://github.com/Microsoft/Windows-driver-samples/tree/master/print/v4PrintDriverSamples/v4PrintDriver-USBMon-Bidi-Extension).
+To run the auto-configuration sample, you must install this driver to support a printer which is installed against either a WSD port, or TCP/IP port. Additionally, USB printers may be supported if the driver is updated to incorporate USB Bidi Javascript, as described here: [Print Driver USB Monitor and Bidi Sample](https://docs.microsoft.com/samples/microsoft/windows-driver-samples/print-driver-usb-monitor-and-bidi-sample/).
diff --git a/print/cpsuisam/README.md b/print/cpsuisam/README.md
index 7f26c060..f43a5020 100644
--- a/print/cpsuisam/README.md
+++ b/print/cpsuisam/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Common Property Sheet User Interface (CPSUI) Sample
- platform: Application
- language: cpp
- category: Print
- description: The CPSUISAM application causes the CPSUI to call the print spooler to create property sheet pages for the default printer.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617940
---->
-
# Common Property Sheet UI Sample
The CPSUISAM application causes the Common Property Sheet User Interface (CPSUI) to call the Windows print spooler to create property sheet pages for the system's default printer.
@@ -26,4 +18,4 @@ The application then creates an additional property sheet page to illustrate som
CPSUI is a user-mode DLL that enables you to create property sheet pages that have a standard appearance.
-CPSUIAM causes CPSUI to call the Windows print spooler to create property sheet pages for the system's default printer. The application then creates an additional property sheet page to illustrate some of the techniques that you can use when you are using CPSUI to create a new page. For more information, see [Common Property Sheet User Interface](http://msdn.microsoft.com/en-us/library/windows/hardware/ff546163(v=vs.85).aspx).
+CPSUIAM causes CPSUI to call the Windows print spooler to create property sheet pages for the system's default printer. The application then creates an additional property sheet page to illustrate some of the techniques that you can use when you are using CPSUI to create a new page. For more information, see [Common Property Sheet User Interface](https://docs.microsoft.com/windows-hardware/drivers/print/common-property-sheet-user-interface).
diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/README.md b/print/v4PrintDriverSamples/PrinterExtensionSample/README.md
index 9fc29ab4..043811a4 100644
--- a/print/v4PrintDriverSamples/PrinterExtensionSample/README.md
+++ b/print/v4PrintDriverSamples/PrinterExtensionSample/README.md
@@ -5,25 +5,18 @@ languages:
- csharp
products:
- windows
+- windows-wdk
---
-<!---
- name: Printer Extension Sample
- platform: Application
- language: cs
- category: Print
- description: Demonstrates how to use .NET to build a customized, desktop UI for a v4 print driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617945
---->
-
# Printer Extension Sample
This sample demonstrates how to use .NET to build a customized, desktop UI for a v4 print driver. This .NET app uses PrintTicket, PrintCapabilities and Bidi in order to communicate with the print system and is suitable for inclusion in a v4 print driver.
-**Note** This sample is for the v4 print driver model.
+> [!NOTE]
+> This sample is for the v4 print driver model.
-# Related topics
+## Related topics
-[Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644)
+[Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver)
-[v4 Print Driver Interfaces and Enumerations](http://msdn.microsoft.com/en-us/library/hh464103(v=vs.85).aspx)
+[v4 Printer Driver](https://docs.microsoft.com/windows-hardware/drivers/print/v4-printer-driver)
diff --git a/print/v4PrintDriverSamples/v4PrintDriver-ConstraintScript/README.md b/print/v4PrintDriverSamples/v4PrintDriver-ConstraintScript/README.md
index d1450b7a..a98abd5f 100644
--- a/print/v4PrintDriverSamples/v4PrintDriver-ConstraintScript/README.md
+++ b/print/v4PrintDriverSamples/v4PrintDriver-ConstraintScript/README.md
@@ -5,34 +5,28 @@ languages:
- javascript
products:
- windows
+- windows-wdk
---
-<!---
- name: Print Driver Constraints Sample
- platform: Utility
- language: js
- category: Print
- description: Demonstrates how to implement advanced constraint handling and PrintTicket/PrintCapabilities handling using JavaScript.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617946
---->
-
# Print Driver Constraints Sample
This sample demonstrates how to implement advanced constraint handling, and also PrintTicket/PrintCapabilities handling using JavaScript.
The Constraints.js file in this sample demonstrates the implementation of JavaScript-based constraints to be used with a v4 print driver. The file implements the following two of the four functions used by JavaScript constraint files, as well as several helper functions:
-- **ValidatePrintTicket** takes a given [IPrintSchemaTicket](http://msdn.microsoft.com/en-us/library/hh451398(v=vs.85).aspx) object and validates it for the current printer. The function may determine that the Print Ticket was already valid, modify the Print Ticket to make it valid, or determine that the Print Ticket is invalid and could not be made valid.
-- **CompletePrintCapabilities** takes a given **IPrintSchemaTicket** object and the [IPrintSchemaCapabilities](http://msdn.microsoft.com/en-us/library/hh451256(v=vs.85).aspx) object that was produced by the configuration module and augments it as needed. This can be used to establish positive constraint situations.
+- **ValidatePrintTicket** takes a given [IPrintSchemaTicket](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/printerextension/nn-printerextension-iprintschematicket) object and validates it for the current printer. The function may determine that the Print Ticket was already valid, modify the Print Ticket to make it valid, or determine that the Print Ticket is invalid and could not be made valid.
+
+- **CompletePrintCapabilities** takes a given **IPrintSchemaTicket** object and the [IPrintSchemaCapabilities](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/printerextension/nn-printerextension-iprintschemacapabilities) object that was produced by the configuration module and augments it as needed. This can be used to establish positive constraint situations.
This sample does not demonstrate **ConvertPrintTicketToDevMode** or **ConvertDevModeToPrintTicket**, which utilize a property bag to store data in the private section of the DEVMODE structure.
-**Note** This sample is for the v4 print driver model.
+> [!NOTE]
+> This sample is for the v4 print driver model.
-# Related topics
+## Related topics
-[Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644)
+[Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver)
-[IPrintSchemaCapabilities](http://msdn.microsoft.com/en-us/library/hh451256(v=vs.85).aspx)
+[IPrintSchemaCapabilities](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/printerextension/nn-printerextension-iprintschemacapabilities)
-[IPrintSchemaTicket](http://msdn.microsoft.com/en-us/library/hh451398(v=vs.85).aspx)
+[IPrintSchemaTicket](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/printerextension/nn-printerextension-iprintschematicket)
diff --git a/print/v4PrintDriverSamples/v4PrintDriver-HostBasedSampleDriver/HostBasedSampleDriver.vcxproj b/print/v4PrintDriverSamples/v4PrintDriver-HostBasedSampleDriver/HostBasedSampleDriver.vcxproj
index 9242769a..6f345409 100644
--- a/print/v4PrintDriverSamples/v4PrintDriver-HostBasedSampleDriver/HostBasedSampleDriver.vcxproj
+++ b/print/v4PrintDriverSamples/v4PrintDriver-HostBasedSampleDriver/HostBasedSampleDriver.vcxproj
@@ -138,36 +138,54 @@
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<ClCompile>
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<ClCompile>
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<Inf Exclude="@(Inf)" Include="*.inf" />
diff --git a/print/v4PrintDriverSamples/v4PrintDriver-HostBasedSampleDriver/Package/package.VcxProj b/print/v4PrintDriverSamples/v4PrintDriver-HostBasedSampleDriver/Package/package.VcxProj
index d68c6610..8bd189b0 100644
--- a/print/v4PrintDriverSamples/v4PrintDriver-HostBasedSampleDriver/Package/package.VcxProj
+++ b/print/v4PrintDriverSamples/v4PrintDriver-HostBasedSampleDriver/Package/package.VcxProj
@@ -92,7 +92,35 @@
<VerifyDrivers />
<VerifyFlags>133563</VerifyFlags>
</PropertyGroup>
- <ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
diff --git a/print/v4PrintDriverSamples/v4PrintDriver-HostBasedSampleDriver/README.md b/print/v4PrintDriverSamples/v4PrintDriver-HostBasedSampleDriver/README.md
index 8eca83ff..3c7bfba2 100644
--- a/print/v4PrintDriverSamples/v4PrintDriver-HostBasedSampleDriver/README.md
+++ b/print/v4PrintDriverSamples/v4PrintDriver-HostBasedSampleDriver/README.md
@@ -6,22 +6,15 @@ languages:
- xml
products:
- windows
+- windows-wdk
---
-<!---
- name: USB Host-Based Print Driver Sample
- platform: Utility
- language: js xml
- category: Print
- description: Demonstrates how to support host-based devices that use the v4 print driver model and are connected via USB.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617947
---->
-
# USB Host-Based Print Driver Sample
This driver sample demonstrates how to support host-based devices that use the v4 print driver model, and are connected via USB.
-**Note** This sample is for the v4 print driver model.
+> [!NOTE]
+> This sample is for the v4 print driver model.
Windows enables manufacturers to support Bidirectional Communication (Bidi) for USB devices, by using a combination of both a Bidi XML file and a Javascript file known as a USB Bidi extender. The *usb\_host\_based\_sample.js* file that is included with the sample, plays the role of the USB Bidi extender.
@@ -31,39 +24,44 @@ By default, Bidi queries and status requests are routed over the USB device inte
In addition to extending Bidi communication, this driver sample also specifies the schema elements that it supports. The *usb\_host\_based\_sample\_extension.xml* file that is included with the sample, provides information about the supported schema elements.
-The Bidi schema is a hierarchy of printer attributes, some of which are properties and others that are values (or value entries).
+The Bidi schema is a hierarchy of printer attributes, some of which are properties and others that are values (or value entries):
-*Property*
+- *Property*
+
+ - A property is a node in the schema hierarchy. A property can have one or more children, and these children can be other properties or values.
-- A property is a node in the schema hierarchy. A property can have one or more children, and these children can be other properties or values.
+- *Value*
-*Value*
+ - A value is a leaf in the schema hierarchy that represents either a single data item or a list of related data items. A value has a name, a data type, and a data value. A value cannot have child elements.
-- A value is a leaf in the schema hierarchy that represents either a single data item or a list of related data items. A value has a name, a data type, and a data value. A value cannot have child elements.
+For more information, see [USB Bidi Extender](https://docs.microsoft.com/windows-hardware/drivers/print/usb-bidi-extender) and [Bidi Communication Schema](https://docs.microsoft.com/windows-hardware/drivers/print/bidirectional-communication-schema).
-For more information, see [USB Bidi Extender](http://msdn.microsoft.com/en-us/library/windows/hardware/jj659903(v=vs.85).aspx) and [Bidi Communication Schema](http://msdn.microsoft.com/en-us/library/windows/hardware/ff545169(v=vs.85).aspx).
+## File manifest
Here are the core files that you will find in this sample:
-**usb\_host\_based\_sample.js**
+### usb\_host\_based\_sample.js
+
+A USB Bidi Extension JavaScript file which includes support for controlling printing for host-based devices. This is the only code in the driver sample. It is invoked by USBMon and it communicates with the device to do the following:
-- A USB Bidi Extension JavaScript file which includes support for controlling printing for host-based devices. This is the only code in the driver sample. It is invoked by USBMon and it communicates with the device to do the following:
- Determine if the device is ready to receive data
- - Check to see if there is an error condition
- - Read the device status
+
+- Check to see if there is an error condition
+
+- Read the device status
-**usb\_host\_based\_sample\_events.xml**
+### usb\_host\_based\_sample\_events.xml
-- A 'driver events' XML file that specifies an event which detects when the user needs to flip over the paper in the tray.
+A 'driver events' XML file that specifies an event which detects when the user needs to flip over the paper in the tray.
-**usb\_host\_based\_sample\_extension.xml**
+### usb\_host\_based\_sample\_extension.xml
-- A USB Bidi Extension XML file that specifies the supported Bidi Schema elements for this driver.
+A USB Bidi Extension XML file that specifies the supported Bidi Schema elements for this driver.
## Build the sample
-For information and instructions about how to test and deploy drivers, see [Developing, Testing, and Deploying Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554651(v=vs.85).aspx).
+For information and instructions about how to test and deploy drivers, see [Developing, Testing, and Deploying Drivers](https://docs.microsoft.com/windows-hardware/drivers/develop/).
## Run the sample
-To understand how to run this sample as a Windows driver, see the [v4 Printer Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/hh706306(v=vs.85).aspx) collection of topics. \ No newline at end of file
+To understand how to run this sample as a Windows driver, see the [v4 Printer Driver](https://docs.microsoft.com/windows-hardware/drivers/print/v4-printer-driver) collection of topics.
diff --git a/print/v4PrintDriverSamples/v4PrintDriver-USBMon-Bidi-Extension/README.md b/print/v4PrintDriverSamples/v4PrintDriver-USBMon-Bidi-Extension/README.md
index d548c589..e68dd7a4 100644
--- a/print/v4PrintDriverSamples/v4PrintDriver-USBMon-Bidi-Extension/README.md
+++ b/print/v4PrintDriverSamples/v4PrintDriver-USBMon-Bidi-Extension/README.md
@@ -6,36 +6,31 @@ languages:
- xml
products:
- windows
+- windows-wdk
---
-<!---
- name: Print Driver USB Monitor and Bidi Sample
- platform: Utility
- language: js xml
- category: Print
- description: Demonstrates how to support bidirectional (Bidi) communication over the USB bus using JavaScript and XML.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617948
---->
-
# Print Driver USB Monitor and Bidi Sample
This sample demonstrates how to support bidirectional (Bidi) communication over the USB bus, using JavaScript and XML. This sample supports bidirectional status while not printing, and unsolicited status from the printer while printing.
+## File manifest
+
The following files are included in the sample:
-**USBMON\_Bidi\_JavaScript\_File.js**
+### USBMON\_Bidi\_JavaScript\_File.js
-- This JavaScript file demonstrates the implementation of a Bidi support for USBMon with a v4 print driver. The JavaScript file supports three functions: getSchemas() is used to make Bidi GET queries to a device, setSchema() is used to make a single Bidi SET query to the device, and getStatus() is called repeatedly during printing in order to retrieve unsolicited status from the printer using the data from the read channel of the device.
+This JavaScript file demonstrates the implementation of a Bidi support for USBMon with a v4 print driver. The JavaScript file supports three functions: getSchemas() is used to make Bidi GET queries to a device, setSchema() is used to make a single Bidi SET query to the device, and getStatus() is called repeatedly during printing in order to retrieve unsolicited status from the printer using the data from the read channel of the device.
-**USBMON\_Bidi\_XML\_File.xml**
+### USBMON\_Bidi\_XML\_File.xml
-- This XML file demonstrates how to build a Bidi Schema extension for USB. It describes the supported schema elements that can be queried or set, along with their restrictions.
+This XML file demonstrates how to build a Bidi Schema extension for USB. It describes the supported schema elements that can be queried or set, along with their restrictions.
-For more information, see [USB Bidi Extender](http://msdn.microsoft.com/en-us/library/windows/hardware/jj659903(v=vs.85).aspx).
+For more information, see [USB Bidi Extender](https://docs.microsoft.com/windows-hardware/drivers/print/usb-bidi-extender).
-**Note** This sample is for the v4 print driver model.
+> [!NOTE]
+> This sample is for the v4 print driver model.
-**Note** When you make calls to printerStream.read() in the sample, the printer returns an array which includes an additional element that represents the array length. The following JavaScript code can be used to copy the returned array into a new array, and also to remove the additional element.
+When you make calls to printerStream.read() in the sample, the printer returns an array which includes an additional element that represents the array length. The following JavaScript code can be used to copy the returned array into a new array, and also to remove the additional element.
```js
var readBuffer = [];
@@ -50,4 +45,4 @@ var cleanArray = [];
for ( i = 0; i < readBytes; i++ ) {
cleanArray[i] = readBuffer.shift();
}
-``` \ No newline at end of file
+```
diff --git a/print/v4PrintDriverSamples/v4PrintDriver-WSDMon-Bidi-Extension/README.md b/print/v4PrintDriverSamples/v4PrintDriver-WSDMon-Bidi-Extension/README.md
index 3b60dea2..a7ed3f9f 100644
--- a/print/v4PrintDriverSamples/v4PrintDriver-WSDMon-Bidi-Extension/README.md
+++ b/print/v4PrintDriverSamples/v4PrintDriver-WSDMon-Bidi-Extension/README.md
@@ -5,24 +5,17 @@ languages:
- xml
products:
- windows
+- windows-wdk
---
-<!---
- name: WSDMon Bidi Extension Sample
- platform: Utility
- language: xml
- category: Print
- description: Demonstrates how to use an XML extension file to support bidirectional (Bidi) communication with a WSD connected printer.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617949
---->
-
# WSDMon Bidi Extension Sample
This sample demonstrates how to use an XML extension file to support bidirectional (Bidi) communication with a WSD connected printer.
The v4 print driver model continues to employ the WSDMon Bidi Extension file format, as well as the SNMP Bidi Extension file format.
-**Note** Third-party port monitors and language monitors are not supported in the v4 driver model or with print class drivers.
+> [!NOTE]
+> Third-party port monitors and language monitors are not supported in the v4 driver model or with print class drivers.
The WSDMON port monitor is a printer port monitor that supports printing to network printers that comply with the Web Services for Devices (WSD) technology. The WSDMON port monitor listens for WSD events and updates the printer status accordingly.
@@ -56,6 +49,7 @@ WSDMON supports the following Xcv commands:
- ServiceID
-**Note** This sample is for the v4 print driver model.
+> [!NOTE]
+> This sample is for the v4 print driver model.
-For more information, see [V4 Driver Connectivity Architecture](http://msdn.microsoft.com/en-us/library/windows/hardware/) and [Bidirectional Communication Schema](http://msdn.microsoft.com/en-us/library/windows/hardware/ff545169(v=vs.85).aspx). \ No newline at end of file
+For more information, see [v4 Driver Connectivity Architecture](https://docs.microsoft.com/windows-hardware/drivers/print/v4-driver-connectivity-architecture) and [Bidirectional Communication Schema](https://docs.microsoft.com/windows-hardware/drivers/print/bidirectional-communication-schema).
diff --git a/sd/miniport/sdhc/README.md b/sd/miniport/sdhc/README.md
index fcf647f8..2872f735 100644
--- a/sd/miniport/sdhc/README.md
+++ b/sd/miniport/sdhc/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Standard SD Host Controller Miniport
- platform: WDM
- language: cpp
- category: Storage
- description: Provides a functional miniport implementation for a standard SD host controller.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617952
---->
-
# Standard SD Host Controller Miniport
This is a sample for a Secure Digital (SD) Host Controller miniport driver. The driver works in conjunction with sdport.sys, which implements SD/SDIO/eMMC protocol and WDM interfaces, to provide the host register interface.
@@ -24,8 +16,12 @@ This is a sample for a Secure Digital (SD) Host Controller miniport driver. The
This sample builds a Windows Universal driver. It uses only APIs and DDIs that are included in Windows Core.
-This driver, sdhc.sys, provides a functional miniport implementation for a standard SD host controller. However, it does not have support for many more recent features such as:
+This driver, sdhc.sys, provides a functional miniport implementation for a standard SD host controller.
+
+However, it does not have support for many more recent features such as:
- UHS-I speed modes.
+
- HS400
-- SD 4.0 \ No newline at end of file
+
+- SD 4.0
diff --git a/security/elam/README.md b/security/elam/README.md
index ee82e0da..e6bf44a6 100644
--- a/security/elam/README.md
+++ b/security/elam/README.md
@@ -5,20 +5,12 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Early Launch Anti-Malware Driver
- platform: KMDF
- language: cpp
- category: Security
- description: Demonstrates how to receive notifications about the initialization of regular boot start drivers in an Early Launch Anti-Malware driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617954
---->
-
# Early Launch Anti-Malware Driver
-This sample demonstrates how to use the [**IoRegisterBootDriverCallback**](http://msdn.microsoft.com/en-us/library/windows/hardware/hh439379) and [**IoUnRegisterBootDriverCallback**](http://msdn.microsoft.com/en-us/library/windows/hardware/hh439394) DDIs from an Early Launch Anti-Malware driver, to receive notifications about the initialization of regular boot start drivers.
+This sample demonstrates how to use the [**IoRegisterBootDriverCallback**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ntddk/nf-ntddk-ioregisterbootdrivercallback) and [**IoUnRegisterBootDriverCallback**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ntddk/nf-ntddk-iounregisterbootdrivercallback) DDIs from an Early Launch Anti-Malware driver, to receive notifications about the initialization of regular boot start drivers.
This sample driver is a minimal driver meant to demonstrate the usage of the APIs mentioned above. It is not intended for use in a production environment.
@@ -32,13 +24,13 @@ Early Launch drivers are required to be signed with a code-signing certificate t
1. Copy the signed elamsample.sys file to the %WINDIR%\\System32\\Drivers directory on your test machine.
-2. Use the sc.exe tool present in Windows to install the driver:
+1. Use the sc.exe tool present in Windows to install the driver:
+
+ `sc create ElamSample binpath=%windir%\\system32\\drivers\\elamsample.sys type=kernel start=boot error=critical group=Early-Launch`
- `sc create ElamSample binpath=%windir%\\system32\\drivers\\elamsample.sys type=kernel start=boot error=critical group=Early-Launch`
-
-3. Enable test signing:
+1. Enable test signing:
- `bcdedit /set testsigning on`
+ `bcdedit /set testsigning on`
## Code tour
@@ -122,4 +114,4 @@ ElamSample: 93 29 d5 f2 e2 7a c9 79 41 b2 6d c0 78 35 2a d3
ElamSample: da 2d 7e 72 f0 05 5f 8b 63 8c 7b a2 6b 37 5c 4f
ElamSample reports that all Boot Start drivers have been initialized and that ElamSample is about to be unloaded ElamSample is being unloaded.
-``` \ No newline at end of file
+```
diff --git a/sensors/ADXL345Acc/ADXL345Acc.vcxproj b/sensors/ADXL345Acc/ADXL345Acc.vcxproj
index 3e04c33b..5e2757dd 100644
--- a/sensors/ADXL345Acc/ADXL345Acc.vcxproj
+++ b/sensors/ADXL345Acc/ADXL345Acc.vcxproj
@@ -121,6 +121,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>ADXL345Acc.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -143,6 +146,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>ADXL345Acc.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -165,6 +171,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>ADXL345Acc.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -187,6 +196,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>ADXL345Acc.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<Inf Exclude="@(Inf)" Include="*.inf" />
diff --git a/sensors/ADXL345Acc/readme.md b/sensors/ADXL345Acc/readme.md
index 69902ce9..2a1fc26b 100644
--- a/sensors/ADXL345Acc/readme.md
+++ b/sensors/ADXL345Acc/readme.md
@@ -1,21 +1,13 @@
---
-topic: sample
+page_type: sample
description: "Demonstrates how to write a UMDF v2 driver to control an ADXL345 accelerometer chip."
languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: ADXL345 Accelerometer Sample Driver
- platform: UMDF2
- language: cpp
- category: Sensors
- description: Demonstrates how to write a UMDF v2 driver to control an ADXL345 accelerometer chip.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617957
---->
-
# ADXL345 Accelerometer Sample Driver
-The ADXL345 accelerometer sample shows how to write a UMDF v2 driver to control an ADXL345 accelerometer chip. \ No newline at end of file
+The ADXL345 accelerometer sample shows how to write a UMDF v2 driver to control an ADXL345 accelerometer chip.
diff --git a/sensors/Activity/Activity.vcxproj b/sensors/Activity/Activity.vcxproj
index 724803cd..bd83ce53 100644
--- a/sensors/Activity/Activity.vcxproj
+++ b/sensors/Activity/Activity.vcxproj
@@ -121,6 +121,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>Activity.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -143,6 +146,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>Activity.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -165,6 +171,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>Activity.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -187,6 +196,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>Activity.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<Inf Exclude="@(Inf)" Include="*.inf" />
diff --git a/sensors/Activity/readme.md b/sensors/Activity/readme.md
index c3e6fa34..e56c65bf 100644
--- a/sensors/Activity/readme.md
+++ b/sensors/Activity/readme.md
@@ -1,21 +1,13 @@
---
-topic: sample
+page_type: sample
description: "Demonstrates how to write a UMDF v2 driver to control an activity sensor."
languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Activity Sensor Driver Sample
- platform: UMDF2
- language: cpp
- category: Sensors
- description: Demonstrates how to write a UMDF v2 driver to control an activity sensor.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617956
---->
-
# Activity Sensor Driver Sample
The activity sample shows how to write a UMDF v2 driver to control an activity sensor.
diff --git a/sensors/CustomSensors/CustomSensors.vcxproj b/sensors/CustomSensors/CustomSensors.vcxproj
index 113ddd23..7e2d3b5a 100644
--- a/sensors/CustomSensors/CustomSensors.vcxproj
+++ b/sensors/CustomSensors/CustomSensors.vcxproj
@@ -121,6 +121,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>CustomSensors.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -143,6 +146,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>CustomSensors.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -165,6 +171,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>CustomSensors.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -187,6 +196,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>CustomSensors.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<Inf Exclude="@(Inf)" Include="*.inf" />
diff --git a/sensors/CustomSensors/readme.md b/sensors/CustomSensors/readme.md
index defd64ba..d97083da 100644
--- a/sensors/CustomSensors/readme.md
+++ b/sensors/CustomSensors/readme.md
@@ -1,21 +1,13 @@
---
-topic: sample
+page_type: sample
description: "Demonstrates how to write a UMDF v2 driver to control a custom sensor."
languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Custom Sensor Driver Sample
- platform: UMDF2
- language: cpp
- category: Sensors
- description: Demonstrates how to write a UMDF v2 driver to control a custom sensor.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617958
---->
-
# Custom Sensor Driver Sample
-The CustomSensor sample shows how to write a UMDF v2 driver to control a custom sensor. \ No newline at end of file
+The CustomSensor sample shows how to write a UMDF v2 driver to control a custom sensor.
diff --git a/sensors/Fusion/FusionSensor.vcxproj b/sensors/Fusion/FusionSensor.vcxproj
index bdcad389..362e350d 100644
--- a/sensors/Fusion/FusionSensor.vcxproj
+++ b/sensors/Fusion/FusionSensor.vcxproj
@@ -121,6 +121,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>FusionSensor.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -142,6 +145,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>FusionSensor.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -163,6 +169,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>FusionSensor.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -184,6 +193,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>FusionSensor.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<Inf Exclude="@(Inf)" Include="*.inf" />
diff --git a/sensors/Fusion/readme.md b/sensors/Fusion/readme.md
index 0aa587e3..7ec75d6b 100644
--- a/sensors/Fusion/readme.md
+++ b/sensors/Fusion/readme.md
@@ -1,21 +1,13 @@
---
-topic: sample
+page_type: sample
description: "Demonstrates how to write a UMDF v2 driver to control a virtual FusionSensor sensor."
languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Fusion Sensor Driver Sample
- platform: UMDF2
- language: cpp
- category: Sensors
- description: Demonstrates how to write a UMDF v2 driver to control a virtual FusionSensor sensor.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=856914
---->
-
# Fusion Sensor Driver Sample
-The FusionSensor sample shows how to write a UMDF v2 driver to control a virtual FusionSensor sensor. \ No newline at end of file
+The FusionSensor sample shows how to write a UMDF v2 driver to control a virtual FusionSensor sensor.
diff --git a/sensors/Pedometer/Pedometer.vcxproj b/sensors/Pedometer/Pedometer.vcxproj
index ee5738d7..3ada5e9d 100644
--- a/sensors/Pedometer/Pedometer.vcxproj
+++ b/sensors/Pedometer/Pedometer.vcxproj
@@ -121,6 +121,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>Pedometer.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -143,6 +146,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>Pedometer.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -165,6 +171,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>Pedometer.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -187,6 +196,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>Pedometer.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<Inf Exclude="@(Inf)" Include="*.inf" />
diff --git a/sensors/Pedometer/readme.md b/sensors/Pedometer/readme.md
index e625e1e2..920a7ace 100644
--- a/sensors/Pedometer/readme.md
+++ b/sensors/Pedometer/readme.md
@@ -1,21 +1,13 @@
---
-topic: sample
-description: "Demonstrates how to write a UMDF v2 driver to control a virtual Pedometer sensor."
+page_type: sample
+description: "Demonstrates how to write a UMDF v2 driver to control a virtual pedometer sensor."
languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Pedometer Sensor Sample
- platform: UMDF2
- language: cpp
- category: Sensors
- description: Demonstrates how to write a UMDF v2 driver to control a virtual Pedometer sensor.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617959
---->
+# Pedometer sensor sample
-# Pedometer Sensor Sample
-
-The Pedometer sample shows how to write a UMDF v2 driver to control a virtual Pedometer sensor.
+The Pedometer sample shows how to write a UMDF v2 driver to control a virtual pedometer sensor.
diff --git a/sensors/SensorsComboDriver/SensorsComboDriver.vcxproj b/sensors/SensorsComboDriver/SensorsComboDriver.vcxproj
index 381f5a03..0871cfc0 100644
--- a/sensors/SensorsComboDriver/SensorsComboDriver.vcxproj
+++ b/sensors/SensorsComboDriver/SensorsComboDriver.vcxproj
@@ -119,6 +119,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -139,6 +142,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -159,6 +165,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -179,6 +188,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<Inf Exclude="@(Inf)" Include="*.inf" />
diff --git a/sensors/SensorsComboDriver/readme.md b/sensors/SensorsComboDriver/readme.md
index d225f38f..44109a0f 100644
--- a/sensors/SensorsComboDriver/readme.md
+++ b/sensors/SensorsComboDriver/readme.md
@@ -1,21 +1,13 @@
---
-topic: sample
+page_type: sample
description: "Demonstrates how to write UMDF v2 drivers to control various types of virtual sensors."
languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Sensors Combo Driver Sample
- platform: UMDF2
- language: cpp
- category: Sensors
- description: Demonstrates how to write UMDF v2 drivers to control various types of virtual sensors.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=856915
---->
-
# Sensors Combo Driver Sample
-The sensors combo driver sensor sample shows how to write UMDF v2 drivers to control various types of virtual sensors such as Ambient Light, Barometer, Gyroscope, Magnetometer, Geomagnetic, Gravity Vector, Proximity, Linear Accelerometer and Relative Fusion. \ No newline at end of file
+The sensors combo driver sensor sample shows how to write UMDF v2 drivers to control various types of virtual sensors such as ambient light, barometer, gyroscope, magnetometer, geomagnetic, gravity vector, proximity, linear accelerometer and relative fusion.
diff --git a/sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.vcxproj b/sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.vcxproj
index ee3d87a3..591fe423 100644
--- a/sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.vcxproj
+++ b/sensors/SimpleDeviceOrientationSensor/SimpleDeviceOrientationSensor.vcxproj
@@ -121,6 +121,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>SimpleDeviceOrientationSensor.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -143,6 +146,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>SimpleDeviceOrientationSensor.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -165,6 +171,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>SimpleDeviceOrientationSensor.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -187,6 +196,9 @@
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\propsys.lib;$(SDK_LIB_PATH)\sensors\1.1\sensorscxstub.lib;$(SDK_LIB_PATH)\sensorsutils.lib</AdditionalDependencies>
<ModuleDefinitionFile>SimpleDeviceOrientationSensor.def</ModuleDefinitionFile>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<Inf Exclude="@(Inf)" Include="*.inf" />
diff --git a/sensors/SimpleDeviceOrientationSensor/readme.md b/sensors/SimpleDeviceOrientationSensor/readme.md
index 26f7a068..c33739c1 100644
--- a/sensors/SimpleDeviceOrientationSensor/readme.md
+++ b/sensors/SimpleDeviceOrientationSensor/readme.md
@@ -1,21 +1,13 @@
---
topic: sample
-description: "Demonstrates how to write a UMDF v2 sensor driver to output Simple Device Orientation values."
+description: "Demonstrates how to write a UMDF v2 sensor driver to output simple device orientation values."
languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Simple Device Orientation Sensor Sample
- platform: UMDF2
- language: cpp
- category: Sensors
- description: Demonstrates how to write a UMDF v2 sensor driver to output Simple Device Orientation values.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617960
---->
+# SimpleDeviceOrientationSensor
-# Simple Device Orientation Sensor Sample
-
-The SimpleDeviceOrientationSensor sample shows how to write a UMDF v2 sensor driver to output Simple Device Orientation values. \ No newline at end of file
+This sample shows you how to write a UMDF v2 sensor driver to output simple device orientation values.
diff --git a/serial/VirtualSerial/README.md b/serial/VirtualSerial/README.md
index b566c2a5..3eeb9764 100644
--- a/serial/VirtualSerial/README.md
+++ b/serial/VirtualSerial/README.md
@@ -5,38 +5,33 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Virtual serial driver sample
- platform: UMDF1
- language: cpp
- category: Serial
- description: Demonstrates a simple virtual serial driver (ComPort) and a controller-less modem driver (FakeModem).
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617963
---->
-
# Virtual serial driver sample
This sample demonstrates these two serial drivers:
- A simple virtual serial driver (ComPort)
+
- A controller-less modem driver (FakeModem).This driver supports sending and receiving AT commands using the ReadFile and WriteFile calls or via a TAPI interface using an application such as, HyperTerminal.
This sample driver is a minimal driver meant to demonstrate the usage of the User-Mode Driver Framework. It is not intended for use in a production environment.
-For more information, see [Serial Controller and Device Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff546939) in the WDK documentation.
+For more information, see the [Serial Controller Driver Design Guide](https://docs.microsoft.com/windows-hardware/drivers/serports/).
## Code tour
-### comsup.cpp & comsup.h
+### comsup.cpp and comsup.h
- COM Support code - specifically base classes which provide implementations for the standard COM interfaces **IUnknown** and **IClassFactory** which are used throughout the sample.
+
- The implementation of **IClassFactory** is designed to create instances of the CMyDriver class. If you should change the name of your base driver class, you would also need to modify this file.
### dllsup.cpp
- DLL Support code - provides the DLL's entry point as well as the single required export (**DllGetClassObject**).
+
- These depend on comsup.cpp to perform the necessary class creation.
### exports.def
@@ -47,15 +42,15 @@ For more information, see [Serial Controller and Device Drivers](http://msdn.mic
- This is the main header file for the sample driver.
-### driver.cpp & driver.h
+### driver.cpp and driver.h
- Definition and implementation of the driver callback class (CMyDriver) for the sample. This includes **DriverEntry** and events on the framework driver object.
-### device.cpp & driver.h
+### device.cpp and driver.h
- Definition and implementation of the device callback class (CMyDriver) for the sample. This includes events on the framework device object.
-### queue.cpp & queue.h
+### queue.cpp and queue.h
- Definition and implementation of the base queue callback class (CMyQueue). This includes events on the framework I/O queue object.
@@ -65,4 +60,4 @@ For more information, see [Serial Controller and Device Drivers](http://msdn.mic
### VirtualSerial.inf / FakeModem.inf
-- INF file that contains installation information for this driver. \ No newline at end of file
+- INF file that contains installation information for this driver.
diff --git a/serial/VirtualSerial2/README.md b/serial/VirtualSerial2/README.md
index 4c87556b..9c743dc5 100644
--- a/serial/VirtualSerial2/README.md
+++ b/serial/VirtualSerial2/README.md
@@ -6,38 +6,33 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Virtual serial driver sample (UMDF version 2)
- platform: UMDF2
- language: cpp
- category: Serial
- description: Demonstrates UMDF version 2 serial drivers and includes a simple virtual serial driver (ComPort) and a controller-less modem driver (FakeModem).
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617965
---->
-
-# Virtual serial driver sample
+# Virtual serial driver sample (V2)
This sample demonstrates these two serial drivers:
- A simple virtual serial driver (ComPort)
+
- A controller-less modem driver (FakeModem).This driver supports sending and receiving AT commands using the ReadFile and WriteFile calls or via a TAPI interface using an application such as, HyperTerminal.
This sample driver is a minimal driver meant to demonstrate the usage of the User-Mode Driver Framework. It is not intended for use in a production environment.
-For more information, see [Serial Controller and Device Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff546939) in the WDK documentation.
+For more information, see the [Serial Controller Driver Design Guide](https://docs.microsoft.com/windows-hardware/drivers/serports/).
## Code tour
-### comsup.cpp & comsup.h
+### comsup.cpp and comsup.h
- COM Support code - specifically base classes which provide implementations for the standard COM interfaces **IUnknown** and **IClassFactory** which are used throughout the sample.
+
- The implementation of **IClassFactory** is designed to create instances of the CMyDriver class. If you should change the name of your base driver class, you would also need to modify this file.
### dllsup.cpp
- DLL Support code - provides the DLL's entry point as well as the single required export (**DllGetClassObject**).
+
- These depend on comsup.cpp to perform the necessary class creation.
### exports.def
@@ -48,15 +43,15 @@ For more information, see [Serial Controller and Device Drivers](http://msdn.mic
- This is the main header file for the sample driver.
-### driver.cpp & driver.h
+### driver.cpp and driver.h
- Definition and implementation of the driver callback class (CMyDriver) for the sample. This includes **DriverEntry** and events on the framework driver object.
-### device.cpp & driver.h
+### device.cpp and driver.h
- Definition and implementation of the device callback class (CMyDriver) for the sample. This includes events on the framework device object.
-### queue.cpp & queue.h
+### queue.cpp and queue.h
- Definition and implementation of the base queue callback class (CMyQueue). This includes events on the framework I/O queue object.
@@ -66,4 +61,4 @@ For more information, see [Serial Controller and Device Drivers](http://msdn.mic
### VirtualSerial.inf / FakeModem.inf
-- INF file that contains installation information for this driver. \ No newline at end of file
+- INF file that contains installation information for this driver.
diff --git a/serial/serenum/README.md b/serial/serenum/README.md
index c7848201..8cb87182 100644
--- a/serial/serenum/README.md
+++ b/serial/serenum/README.md
@@ -5,26 +5,19 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Serenum sample
- platform: WDM
- language: cpp
- category: Serial
- description: Enumerates Plug-n-Play RS-232 devices that are compliant with the current revision of Plug and Play External COM Device.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617961
---->
-
# Serenum sample
Serenum enumerates Plug-n-Play RS-232 devices that are compliant with the current revision of Plug and Play External COM Device. It loads as an upper filter driver to many different RS-232 device drivers that are compliant with its requirements and performs this service for them.
-Serenum implements the Serenum service; its executable image is serenum.sys.
+Serenum implements the Serenum service and its executable image is serenum.sys.
Serenum is an upper-level device filter driver that is used with a serial port function driver to enumerate the following types of devices that are connected to an RS-232 port:
- Plug and Play serial devices that comply with Plug and Play External COM Device Specification, Version 1.00, February 28, 1995.
+
- Pointer devices that comply with legacy mouse detection in Windows.
The combined operation of Serial and Serenum provides the function of a Plug and Play bus driver for an RS-232 port. Serenum supports Plug and Play and power management.
@@ -33,14 +26,14 @@ Windows provides Serenum to support Serial and other serial port function driver
## File Manifest
-File | Description
------|------------
-Enum.c | Functions that enumerate external serial devices (the main purpose of this driver)
-Pnp.c | Plug and Play support code
-Power.c | Power support code
-Serenum.c | Basic driver functionality
-Serenum.h | Local header with defines, prototypes
-String.c | String handling support; mainly ASCII to UNICODE functionality
-Serenum.rc | Resource script
+| File | Description |
+| --- | --- |
+| Enum.c | Functions that enumerate external serial devices (the main purpose of this driver) |
+| Pnp.c | Plug and Play support code |
+| Power.c | Power support code |
+| Serenum.c | Basic driver functionality |
+| Serenum.h | Local header with defines, prototypes |
+| String.c | String handling support, mainly ASCII to UNICODE functionality |
+| Serenum.rc | Resource script |
-For more information, see [Features of Serial and Serenum](http://msdn.microsoft.com/en-us/library/windows/hardware/ff546505). \ No newline at end of file
+For more information, see [Features of Serial and Serenum](https://docs.microsoft.com/windows-hardware/drivers/serports/features-of-serial-and-serenum).
diff --git a/serial/serial/README.md b/serial/serial/README.md
index 7cea010f..7578f9ba 100644
--- a/serial/serial/README.md
+++ b/serial/serial/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Serial Port Driver
- platform: KMDF
- language: cpp
- category: Serial
- description: The Serial (16550-based RS-232) sample driver is a WDF version of the inbox Serial.sys driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617962
---->
-
# Serial Port Driver
The Serial (16550-based RS-232) sample driver is a WDF version of the inbox Serial.sys driver in %WINDIR%\\system32\\drivers.
@@ -24,23 +16,27 @@ The Serial (16550-based RS-232) sample driver is a WDF version of the inbox Seri
This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP.
+## Sample overview
+
This sample driver is functionally equivalent to the inbox driver, with these two exceptions:
1. This sample does not support multi-function serial devices.
-2. This sample does not support legacy serial ports. Legacy ports are not detected by the BIOS, and are, therefore, not enumerated by the operating system.
+
+1. This sample does not support legacy serial ports. Legacy ports are not detected by the BIOS, and are, therefore, not enumerated by the operating system.
The Serial sample driver runs in kernel mode.
This sample driver supports power management. When a serial port is not in use, the driver places the port hardware in a low-power state. When the port is opened, it receives power and wakes up. The driver supports wake-on-ring for platforms that support this function. The driver can be compiled to run on both 32-bit and 64-bit versions of Windows.
-For more information, see [Features of Serial and Serenum](http://msdn.microsoft.com/en-us/library/windows/hardware/ff546505).
+For more information, see [Features of Serial and Serenum](https://docs.microsoft.com/windows-hardware/drivers/serports/features-of-serial-and-serenum).
This sample can be used for these hardware IDs without any modification to the .inx file included in the project.
- PNP0501
+
- PNP0500
-If you have other hardware such as an add-in card, then you must add the hardware ID in the .inx as shown in this example. Then, you must build the project as per the instructions given in the Building the sample section in this readme.
+If you have other hardware such as an add-in card, then you must add the hardware ID in the .inx as shown in this example.
```inf
; For XP and later
@@ -50,4 +46,4 @@ If you have other hardware such as an add-in card, then you must add the hardwar
%PNP0500.DevDesc%= Serial_Inst, *PNP0500, *PNP0501 ; Communications Port
%PNP0501.DevDesc%= Serial_Inst, *PNP0501, *PNP0500 ; Communications Port
%PNP0501.DevDesc%= Serial_Inst, MF\PCI9710_COM ; Communications Port
-``` \ No newline at end of file
+```
diff --git a/serial/serial/ioctl.c b/serial/serial/ioctl.c
index 339cdc6a..192f3955 100644
--- a/serial/serial/ioctl.c
+++ b/serial/serial/ioctl.c
@@ -1297,8 +1297,8 @@ Return Value:
}
reqContext->Type3InputBuffer =
- ExAllocatePoolWithQuotaTag(
- NonPagedPoolNx | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE,
+ ExAllocatePool2(
+ POOL_FLAG_NON_PAGED | POOL_FLAG_USE_QUOTA,
Rs->InSize,
POOL_TAG
);
diff --git a/serial/serial/openclos.c b/serial/serial/openclos.c
index c59439e9..321e5206 100644
--- a/serial/serial/openclos.c
+++ b/serial/serial/openclos.c
@@ -148,8 +148,8 @@ SerialDeviceFileCreateWorker (
case MmLargeSystem: {
extension->BufferSize = 4096;
- extension->InterruptReadBuffer = ExAllocatePoolWithTag(
- NonPagedPoolNx,
+ extension->InterruptReadBuffer = ExAllocatePool2(
+ POOL_FLAG_NON_PAGED,
extension->BufferSize,
POOL_TAG
);
@@ -163,8 +163,8 @@ SerialDeviceFileCreateWorker (
case MmMediumSystem: {
extension->BufferSize = 1024;
- extension->InterruptReadBuffer = ExAllocatePoolWithTag(
- NonPagedPoolNx,
+ extension->InterruptReadBuffer = ExAllocatePool2(
+ POOL_FLAG_NON_PAGED,
extension->BufferSize,
POOL_TAG
);
@@ -178,8 +178,8 @@ SerialDeviceFileCreateWorker (
case MmSmallSystem: {
extension->BufferSize = 128;
- extension->InterruptReadBuffer = ExAllocatePoolWithTag(
- NonPagedPoolNx,
+ extension->InterruptReadBuffer = ExAllocatePool2(
+ POOL_FLAG_NON_PAGED,
extension->BufferSize,
POOL_TAG
);
diff --git a/serial/serial/wdfserial.vcxproj b/serial/serial/wdfserial.vcxproj
index 30db6172..fb761163 100644
--- a/serial/serial/wdfserial.vcxproj
+++ b/serial/serial/wdfserial.vcxproj
@@ -317,6 +317,9 @@
<ResourceCompile>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ResourceCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -330,6 +333,9 @@
<ResourceCompile>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ResourceCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -343,6 +349,9 @@
<ResourceCompile>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ResourceCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -356,6 +365,9 @@
<ResourceCompile>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ResourceCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="precompsrc.c">
diff --git a/setup/devcon/README.md b/setup/devcon/README.md
index 30f772c3..f2cdc6b9 100644
--- a/setup/devcon/README.md
+++ b/setup/devcon/README.md
@@ -5,20 +5,12 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Device Console (DevCon) Tool
- platform: Tool
- language: cpp
- category: Setup
- description: DevCon enables, disables, installs, configures, and removes devices on the local computer and displays detailed information about devices on local and remote computers.
- samplefwlink: https://go.microsoft.com/fwlink/p/?linkid=856741
---->
-
# Device Console (DevCon) Tool
-[DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) is a command-line tool that displays detailed information about devices, and lets you search for and manipulate devices from the command line. DevCon enables, disables, installs, configures, and removes devices on the local computer and displays detailed information about devices on local and remote computers. DevCon is included in the WDK.
+[DevCon](https://docs.microsoft.com/windows-hardware/drivers/devtest/devcon) is a command-line tool that displays detailed information about devices, and lets you search for and manipulate devices from the command line. DevCon enables, disables, installs, configures, and removes devices on the local computer and displays detailed information about devices on local and remote computers. DevCon is included in the WDK.
This document explains the DevCon design, and how to use the SetupAPI and device installation functions to enumerate devices and perform device operations in a console application. For a complete description of DevCon features and instructions for using them, see the DevCon help file included with the WDK documentation in Driver Development Tools/Tools for Testing Drivers/DevCon.
@@ -31,8 +23,11 @@ You can build the sample in two ways: using the Visual Studio Integrated Develop
### Building the sample using Visual Studio
1. Open Visual Studio. From the **File** menu, select **Open Project/Solution**. Navigate to the DevCon sample folder and open the devcon.sln project file.
+
1. Right-click the solution in the **Solution Explorer** and select **Configuration Manager**.
+
1. From the **Configuration Manager**, select the **Active Solution Configuration** (for example, Debug or Release) and the **Active Solution Platform** (for example, Win32) that correspond to the type of build you are interested in.
+
1. From the **Build** menu, click **Build Solution** (Ctrl+Shift+B).
Previous versions of the WDK used the Windows Build utility (Build.exe) and provided separate build environment windows for each of the supported build configurations. You can use the Visual Studio Command Prompt window for all build configurations.
@@ -40,30 +35,32 @@ Previous versions of the WDK used the Windows Build utility (Build.exe) and prov
### Building the sample using the command line (MSBuild)
1. Open a Visual Studio Command Prompt window. Click **Start** and search for **Developer Command Prompt**. If your project is under %PROGRAMFILES%, you need to open the command prompt window using elevated permissions (**Run as administrator**). From this window you can use MsBuild.exe to build any Visual Studio project by specifying the project (.VcxProj) or solutions (.Sln) file.
-1. Navigate to the project directory and enter the **MSbuild** command for your target. For example, to perform a clean build of a Visual Studio driver project called devcon.vcxproj, navigate to the project directory and enter the following MSBuild command: **msbuild /t:clean /t:build .\\devcon.vcxproj**.
+
+1. Navigate to the project directory and enter the **MSbuild** command for your target. For example, to perform a clean build of a Visual Studio driver project called devcon.vcxproj, navigate to the project directory and enter the following MSBuild command: `msbuild /t:clean /t:build .\devcon.vcxproj`.
+
1. If the build succeeds, you will find the tools (devcon.exe) in the binary output directory corresponding to the target platform, for example samples\\setup\\devcon\\Debug.
## Run the sample
-Type "devcon find \*" to list device instances of all present devices on the local machine.
+Type `devcon find *` to list device instances of all present devices on the local machine.
-Type "devcon status @root\\rdp\_mou\\0000" to list status of the terminal server mouse driver.
+Type `devcon status @root\rdp\_mou\0000` to list status of the terminal server mouse driver.
-Type "devcon status \*PNP05\*" to list status of all COM ports.
+Type `devcon status *PNP05*` to list status of all COM ports.
### How DevCon works
-Running "devcon help" will provide a list of commands along with short descriptions of what each command does. "devcon help \<command\>" will give more detailed help on that command. The interpretation of each command is done via a dispatch table "DispatchTable" that is at the bottom of "cmds.cpp". Some of the commands make use of a generic device enumerator "EnumerateDevices". A few of these commands will work when given a remote target computer, and will also work if using the 32-bit devcon on Wow64.
+Running `devcon help` will provide a list of commands along with short descriptions of what each command does. `devcon help <command>` will give more detailed help on that command. The interpretation of each command is done via a dispatch table "DispatchTable" that is at the bottom of "cmds.cpp". Some of the commands make use of a generic device enumerator "EnumerateDevices". A few of these commands will work when given a remote target computer, and will also work if using the 32-bit devcon on Wow64.
A description of some of the more interesting functions and the APIs they use follows:
cmdClasses
-- This command demonstrates the use of [**SetupDiBuildClassInfoListEx**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff550911) to enumerate all device class GUID's. The function [**SetupDiClassNameFromGuidEx**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff550950) and [**SetupDiGetClassDescriptionEx**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff551058) are used to obtain more information about each device class.
+- This command demonstrates the use of [**SetupDiBuildClassInfoListEx**](https://docs.microsoft.com/windows/win32/api/setupapi/nf-setupapi-setupdibuildclassinfolistexa) to enumerate all device class GUIDs. The function [**SetupDiClassNameFromGuidEx**](https://docs.microsoft.com/windows/win32/api/setupapi/nf-setupapi-setupdiclassnamefromguidexa) and [**SetupDiGetClassDescriptionEx**](https://docs.microsoft.com/windows/win32/api/setupapi/nf-setupapi-setupdigetclassdescriptionexa) are used to obtain more information about each device class.
cmdListClass
-- This command demonstrates the use of [**SetupDiClassGuidsFromNameEx**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff550941) to enumerate one or more class GUID's that match the class name. This command also demonstrates the use of [**SetupDiGetClassDevsEx**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff551072) to list all the devices for each class GUID.
+- This command demonstrates the use of [**SetupDiClassGuidsFromNameEx**](https://docs.microsoft.com/windows/win32/api/setupapi/nf-setupapi-setupdiclassguidsfromnameexa) to enumerate one or more class GUIDs that match the class name. This command also demonstrates the use of [**SetupDiGetClassDevsEx**](https://docs.microsoft.com/windows/win32/api/setupapi/nf-setupapi-setupdigetclassdevsexa) to list all the devices for each class GUID.
cmdFind cmdFindAll cmdStatus
@@ -75,7 +72,7 @@ cmdEnable cmdDisable cmdRestart
cmdUpdate
-- This command shows how to use [**UpdateDriverForPlugAndPlayDevices**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff553534) to update the driver for all devices to a specific driver. Normally INSTALLFLAG\_FORCE would not be specified allowing **UpdateDriverForPlugAndPlayDevices** to determine if there is a better match already known. It's specified in DevCon to allow DevCon to be used more effectively as a debugging/testing tool. This cannot be done on a remote machine or in the context of Wow64.
+- This command shows how to use [**UpdateDriverForPlugAndPlayDevices**](https://docs.microsoft.com/windows/win32/api/newdev/nf-newdev-updatedriverforplugandplaydevicesa) to update the driver for all devices to a specific driver. Normally INSTALLFLAG\_FORCE would not be specified allowing **UpdateDriverForPlugAndPlayDevices** to determine if there is a better match already known. It's specified in DevCon to allow DevCon to be used more effectively as a debugging/testing tool. This cannot be done on a remote machine or in the context of Wow64.
cmdInstall
@@ -91,11 +88,11 @@ cmdRescan
cmdDPAdd
-- This command allows you to add a Driver Package to the machine. The main functionality of this command demonstrates the use of [**SetupCopyOEMInf**](http://msdn.microsoft.com/en-us/library/windows/hardware/). Adding a Driver Package to the machine doesn't mean the drivers are installed on devices, it simply means the drivers are available automatically when a new device is plugged in or a existing device is updated.
+- This command allows you to add a Driver Package to the machine. The main functionality of this command demonstrates the use of [**SetupCopyOEMInf**](https://docs.microsoft.com/windows/win32/api/setupapi/nf-setupapi-setupcopyoeminfa). Adding a Driver Package to the machine doesn't mean the drivers are installed on devices, it simply means the drivers are available automatically when a new device is plugged in or a existing device is updated.
cmdDPDelete
-- This command allows you to uninstall a Driver Package from the machine. The main functionality of this command demonstrates the use of [**SetupUninstallOEMInf**](http://msdn.microsoft.com/en-us/library/windows/hardware/). Removing a Driver Package from the machine does not uninstall the drivers associated with a device. If you want to accomplish both then use *cmdRemove* on all the devices using a given Driver Package and then *cmdDPDelete* to remove the Driver Package itself from the machine.
+- This command allows you to uninstall a Driver Package from the machine. The main functionality of this command demonstrates the use of [**SetupUninstallOEMInf**](https://docs.microsoft.com/windows/win32/api/setupapi/nf-setupapi-setupuninstalloeminfa). Removing a Driver Package from the machine does not uninstall the drivers associated with a device. If you want to accomplish both then use *cmdRemove* on all the devices using a given Driver Package and then *cmdDPDelete* to remove the Driver Package itself from the machine.
cmdDPEnum
@@ -107,11 +104,11 @@ Reboot
EnumerateDevices
-- Demonstrates the use of [**SetupDiGetClassDevsEx**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff551072) to enumerate all devices or all present devices, either globally or limited to a specific setup class. Demonstrates the use of [**SetupDiCreateDeviceInfoListEx**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff550958) to create a blank list associated with a class or not (for most cases, a blank list need not be associated with a class). Demonstrates the use of [**SetupDiOpenDeviceInfo**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552071) to add a device instance into a device info list. These last two API's are ideal to obtain a [SP\_DEVINFO\_DATA](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552344) structure from a device instance and machine name when mixing CFGMGR32 API's with SETUPAPI API's. [**SetupDiGetDeviceInfoListDetail**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff551103) is called to obtain a remote machine handle that may be passed into CFGMGR32 API's. [**SetupDiEnumDeviceInfo**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff551010) is called to enumerate each and every device that is in the device info list (either explicitly added, or determined by the call to **SetupDiGetClassDevsEx**). The instance ID is obtained by calling [**CM\_Get\_Device\_ID\_Ex**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff538411), using information in devInfo (obtained from **SetupDiEnumerateDeviceInfo**) and devInfoListDetail (obtained from **SetupDiGetDeviceInfoListDetail**). *GetHwIds* is called to obtain a list of hardware and compatible ID's (explained below). Once an interesting device has been determined (typically by checking hardware ID's) then the callback is called to operate on that individual device.
+- Demonstrates the use of [**SetupDiGetClassDevsEx**](https://docs.microsoft.com/windows/win32/api/setupapi/nf-setupapi-setupdigetclassdevsexa) to enumerate all devices or all present devices, either globally or limited to a specific setup class. Demonstrates the use of [**SetupDiCreateDeviceInfoListEx**](https://docs.microsoft.com/windows/win32/api/setupapi/nf-setupapi-setupdicreatedeviceinfolistexa) to create a blank list associated with a class or not (for most cases, a blank list need not be associated with a class). Demonstrates the use of [**SetupDiOpenDeviceInfo**](hhttps://docs.microsoft.com/windows/win32/api/setupapi/nf-setupapi-setupdiopendeviceinfoa) to add a device instance into a device info list. These last two API's are ideal to obtain a [SP\_DEVINFO\_DATA](https://docs.microsoft.com/windows/win32/api/setupapi/ns-setupapi-sp_devinfo_data) structure from a device instance and machine name when mixing CFGMGR32 API's with SETUPAPI API's. [**SetupDiGetDeviceInfoListDetail**](https://docs.microsoft.com/windows/win32/api/setupapi/nf-setupapi-setupdigetdeviceinfolistdetaila) is called to obtain a remote machine handle that may be passed into CFGMGR32 API's. [**SetupDiEnumDeviceInfo**](https://docs.microsoft.com/windows/win32/api/setupapi/nf-setupapi-setupdienumdeviceinfo) is called to enumerate each and every device that is in the device info list (either explicitly added, or determined by the call to **SetupDiGetClassDevsEx**). The instance ID is obtained by calling [**CM\_Get\_Device\_ID\_Ex**](https://docs.microsoft.com/windows/win32/api/cfgmgr32/nf-cfgmgr32-cm_get_device_id_exw), using information in devInfo (obtained from **SetupDiEnumerateDeviceInfo**) and devInfoListDetail (obtained from **SetupDiGetDeviceInfoListDetail**). *GetHwIds* is called to obtain a list of hardware and compatible ID's (explained below). Once an interesting device has been determined (typically by checking hardware ID's) then the callback is called to operate on that individual device.
GetHwIds
-- Shows how to get the complete list of hardware ID's or compatible ID's for a device using [**SetupDiGetDeviceRegistryProperty**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff551967).
+- Shows how to get the complete list of hardware ID's or compatible ID's for a device using [**SetupDiGetDeviceRegistryProperty**](https://docs.microsoft.com/windows/win32/api/setupapi/nf-setupapi-setupdigetdeviceregistrypropertya).
GetDeviceDescription
@@ -119,11 +116,11 @@ GetDeviceDescription
DumpDeviceWithInfo
-- Shows how to obtain an instance ID (or use any CFGMGR32 API) given HDEVINFO (device info list) and [PSP\_DEVINFO\_DATA](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552344) (device info data).
+- Shows how to obtain an instance ID (or use any CFGMGR32 API) given HDEVINFO (device info list) and [PSP\_DEVINFO\_DATA](https://docs.microsoft.com/windows/win32/api/setupapi/ns-setupapi-sp_devinfo_data) (device info data).
DumpDeviceStatus
-- Shows how to interpret the information returned by [**CM\_Get\_DevNode\_Status\_Ex**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff538517). Refer to *cfg.h* for information returned by this API.
+- Shows how to interpret the information returned by [**CM\_Get\_DevNode\_Status\_Ex**](https://docs.microsoft.com/windows/win32/api/cfgmgr32/nf-cfgmgr32-cm_get_devnode_status_ex). Refer to *cfg.h* for information returned by this API.
DumpDeviceResources
@@ -131,12 +128,12 @@ DumpDeviceResources
DumpDeviceDriverFiles
-- Provided as a debugging aid, obtains information about the files apparently being used for a device. It uses [**SetupDiBuildDriverInfoList**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff550917) to obtain information about the driver being used for the specified device. The driver list associated with a device may be enumerated by calling [**SetupDiEnumDriverInfo**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff551018). In this case, there will be no more than one driver listed. This function proceeds to obtain a list of files that would normally be copied for this driver using DIF\_INSTALLDEVICEFILES. [**SetupScanFileQueue**](http://msdn.microsoft.com/en-us/library/windows/hardware/) is used to enumerate the file queue to display the list of files that are associated with the driver.
+- Provided as a debugging aid, obtains information about the files apparently being used for a device. It uses [**SetupDiBuildDriverInfoList**](https://docs.microsoft.com/windows/win32/api/setupapi/nf-setupapi-setupdibuilddriverinfolist) to obtain information about the driver being used for the specified device. The driver list associated with a device may be enumerated by calling [**SetupDiEnumDriverInfo**](https://docs.microsoft.com/windows/win32/api/setupapi/nf-setupapi-setupdienumdriverinfoa). In this case, there will be no more than one driver listed. This function proceeds to obtain a list of files that would normally be copied for this driver using DIF\_INSTALLDEVICEFILES. [**SetupScanFileQueue**](https://docs.microsoft.com/windows/win32/api/setupapi/nf-setupapi-setupscanfilequeuea) is used to enumerate the file queue to display the list of files that are associated with the driver.
DumpDeviceDriverNodes
-- Provided as a debugging aid, this function determines the list of compatible drivers for a device. It uses [**SetupDiBuildDriverInfoList**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff550917) to obtain the list of compatible drivers. In this case, all drivers are enumerated, however typically DIF\_SELECTBESTCOMPATDRV and [**SetupDiGetSelectedDriver**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552013) would be used together to find which driver the OS would consider to be the best.
+- Provided as a debugging aid, this function determines the list of compatible drivers for a device. It uses [**SetupDiBuildDriverInfoList**](https://docs.microsoft.com/windows/win32/api/setupapi/nf-setupapi-setupdibuilddriverinfolist) to obtain the list of compatible drivers. In this case, all drivers are enumerated, however typically DIF\_SELECTBESTCOMPATDRV and [**SetupDiGetSelectedDriver**](https://docs.microsoft.com/windows/win32/api/setupapi/nf-setupapi-setupdigetselecteddrivera) would be used together to find which driver the OS would consider to be the best.
DumpDeviceStack
-- This function determines class and device upper and lower filters. \ No newline at end of file
+- This function determines class and device upper and lower filters.
diff --git a/simbatt/README.md b/simbatt/README.md
index c999bc12..68a459b3 100644
--- a/simbatt/README.md
+++ b/simbatt/README.md
@@ -5,17 +5,15 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Simulated Battery Driver Sample
- platform: KMDF
- language: cpp
- category: Battery Power
- description: Demonstrates a KMDF-based implementation of Windows battery driver interfaces.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620188
---->
-
# SimBatt: Simulated Battery Driver Sample
-SimBatt is simulated battery device driver, this source code is intended to demonstrate implementation of Windows battery driver interfaces. This is a KMDF based sample. You may use this sample as a starting point to implement a battery miniport specific to your needs. \ No newline at end of file
+SimBatt is simulated battery device driver.
+
+This source code is intended to demonstrate implementation of Windows battery driver interfaces.
+
+This is a KMDF based sample.
+
+You may use this sample as a starting point to implement a battery miniport specific to your needs.
diff --git a/simbatt/func/simbatt.vcxproj b/simbatt/func/simbatt.vcxproj
index 3f0fd780..a9ab3b9b 100644
--- a/simbatt/func/simbatt.vcxproj
+++ b/simbatt/func/simbatt.vcxproj
@@ -108,6 +108,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\battc.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -129,6 +132,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\battc.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -150,6 +156,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\battc.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -171,6 +180,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\battc.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="miniclass.c" />
@@ -190,4 +202,4 @@
<ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-</Project>
+</Project> \ No newline at end of file
diff --git a/simbatt/func/simbatt.vcxproj.Filters b/simbatt/func/simbatt.vcxproj.Filters
index d49b9ea2..42b85d1a 100644
--- a/simbatt/func/simbatt.vcxproj.Filters
+++ b/simbatt/func/simbatt.vcxproj.Filters
@@ -31,4 +31,23 @@
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Include="*.inx">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ <Inf Include="*.inx">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/smartcrd/README.md b/smartcrd/README.md
index aab2982e..a493e66b 100644
--- a/smartcrd/README.md
+++ b/smartcrd/README.md
@@ -5,20 +5,13 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: PCMCIA Smart Card Driver
- platform: KMDF
- language: cpp
- category: SmartCard
- description: Demonstrates how to write a KMDF driver for the SCM Microsystems PCMCIA smart card reader.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617968
---->
-
# PCMCIA Smart Card Driver
-**Warning: This sample and its documentation are known to be out of date. They will be updated soon. Please be aware that some functionality may not work as expected.**
+> [!WARNING]
+> This sample and its documentation are known to be out of date. They will be updated soon. Please be aware that some functionality may not work as expected.
The PCMCIA Smart Card Driver is used for the SCM PCMCIA smart card reader. This driver is written using Kernel-Mode Driver Framework.
@@ -30,9 +23,10 @@ A card reader will not see any card insertion or removal events in these modes,
## Build the sample
-For information on how to build a driver solution using Microsoft Visual Studio, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644).
+For information on how to build a driver solution using Microsoft Visual Studio, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver).
-**Note** You can obtain the co-installers by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](http://go.microsoft.com/fwlink/p/?LinkID=226396).
+> [!NOTE]
+> You can obtain the co-installers by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](https://go.microsoft.com/fwlink/p/?LinkID=253170).
## Run the sample
@@ -50,4 +44,4 @@ The driver will not unload as long as you have Ifdtest.exe running and connected
ISO 7816 Part 3 describes smart cards and smart card protocols in detail. Refer to the PC99 Handbook for smart card reader requirements.
-For more information about Windows smart card reader drivers, see [Smart Card Reader Devices Design Guide](http://msdn.microsoft.com/en-us/library/windows/hardware/). \ No newline at end of file
+For more information about Windows smart card reader drivers, see [Smart Card Reader Devices Design Guide](https://docs.microsoft.com/windows-hardware/drivers/smartcard/).
diff --git a/spb/SkeletonI2C/README.md b/spb/SkeletonI2C/README.md
index c421ff44..1affed0d 100644
--- a/spb/SkeletonI2C/README.md
+++ b/spb/SkeletonI2C/README.md
@@ -5,22 +5,14 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Skeleton I2C Sample Driver
- platform: KMDF
- language: cpp
- category: SimplePeripheralBus
- description: Demonstrates how to design a KMDF controller driver for Windows that conforms to the simple peripheral bus (SPB) device driver interface (DDI).
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617969
---->
-
# Skeleton I2C Sample Driver
-The SkeletonI2C sample demonstrates how to design a KMDF controller driver for Windows that conforms to the [simple peripheral bus](http://msdn.microsoft.com/en-us/library/windows/hardware/hh450903) (SPB) device driver interface (DDI). SPB is an abstraction for low-speed serial buses (for example, I<sup>2</sup>C and SPI) that allows peripheral drivers to be developed for cross-platform use without any knowledge of the underlying bus hardware or device connections. While this sample implements an empty I<sup>2</sup>C driver, it could just as easily be the starting point for an SPI driver with only minor modifications.
+The SkeletonI2C sample demonstrates how to design a KMDF controller driver for Windows that conforms to the [simple peripheral bus](https://docs.microsoft.com/windows-hardware/design/component-guidelines/simple-peripheral-bus--spb-) (SPB) device driver interface (DDI). SPB is an abstraction for low-speed serial buses (for example, I<sup>2</sup>C and SPI) that allows peripheral drivers to be developed for cross-platform use without any knowledge of the underlying bus hardware or device connections. While this sample implements an empty I<sup>2</sup>C driver, it could just as easily be the starting point for an SPI driver with only minor modifications.
-Note that the SkeletonI2C sample is simplified to show the overall structure of an SPB controller, but contains only the code that the driver requires to communicate with the [SPB framework extension (SpbCx)](http://msdn.microsoft.com/en-us/library/windows/hardware/hh406203) and KMDF. The SkeletonI2C sample driver omits all hardware-specific code. It does not simulate data transfers or implement request completion asynchronously. Pay close attention to code comments marked with "TODO" that refer to blocks of code that must be removed or updated.
+Note that the SkeletonI2C sample is simplified to show the overall structure of an SPB controller, but contains only the code that the driver requires to communicate with the [SPB framework extension (SpbCx)](https://docs.microsoft.com/windows-hardware/drivers/spb/spb-framework-extension) and KMDF. The SkeletonI2C sample driver omits all hardware-specific code. It does not simulate data transfers or implement request completion asynchronously. Pay close attention to code comments marked with "TODO" that refer to blocks of code that must be removed or updated.
The simplified structure of the SkeletonI2C sample driver makes it a convenient starting point for development of a real SPB controller driver that manages the hardware functions in an SPB controller.
@@ -29,10 +21,15 @@ The simplified structure of the SkeletonI2C sample driver makes it a convenient
Here are some high-level points to consider when modifying the SkeletonI2C sample for use on real hardware:
- Edit (and likely rename) Skeletoni2c.h to describe your hardware's register set.
+
- Modify Controller.cpp and Device.cpp to translate the SPB DDI and primitives into I<sup>2</sup>C or SPI protocol for your hardware. This includes initialization, I/O configuration, and interrupt processing.
+
- Address any comments marked with "TODO" in the sample, especially those that short circuit the I/O path to complete requests synchronously.
+
- Modify the HWID (`ACPI\skeletoni2c`) in Skeletoni2c.inf to match the device node in your firmware.
+
- Generate and specify a unique trace GUID in I2ctrace.h.
+
- Refactor the driver name, functions, comments, etc., to better describe your implementation.
## Code tour
@@ -41,25 +38,25 @@ Here are some high-level points to consider when modifying the SkeletonI2C sampl
The following are relevant functions in the SkeletonI2C driver for implementing the SPB DDI.
-INITIALIZATION
+#### INITIALIZATION
`OnDeviceAdd`
Within `OnDeviceAdd`, the driver makes several configuration calls for SPB.
-[**SpbDeviceInitConfig**](http://msdn.microsoft.com/en-us/library/windows/hardware/hh450918) must be called before creating the WDFDEVICE. Note that SpbCx sets a default security descriptor on the device object, but the controller driver can override it by calling [**WdfDeviceInitAssignSDDLString**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff546035) after **SpbDeviceInitConfig**.
+[**SpbDeviceInitConfig**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/spbcx/nf-spbcx-spbdeviceinitconfig) must be called before creating the WDFDEVICE. Note that SpbCx sets a default security descriptor on the device object, but the controller driver can override it by calling [**WdfDeviceInitAssignSDDLString**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdfdevice/nf-wdfdevice-wdfdeviceinitassignsddlstring) after **SpbDeviceInitConfig**.
-After creating the WDFDEVICE, the driver configures it appropriately for SPB by calling [**SpbDeviceInitialize**](http://msdn.microsoft.com/en-us/library/windows/hardware/hh450919). Here the driver also sets the target and request attributes.
+After creating the WDFDEVICE, the driver configures it appropriately for SPB by calling [**SpbDeviceInitialize**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/spbcx/nf-spbcx-spbdeviceinitialize). Here the driver also sets the target and request attributes.
Finally the driver configures a WDF system-managed idle time-out.
-TARGET CONNECTION
+#### TARGET CONNECTION
`OnTargetConnect`
Invoked when a client opens a handle to the specified SPB target. Queries the I<sup>2</sup>C connection parameters from the resource hub (via SPB) and initializes the target context.
-SPB I/O CALLBACKS
+#### SPB I/O CALLBACKS
`OnRead`
@@ -89,7 +86,7 @@ Configures the request context for the specified transfer index. This could be a
`PbcRequestComplete`
-Sets the number of bytes completed for a request and invokes the [**SpbRequestComplete**](http://msdn.microsoft.com/en-us/library/windows/hardware/hh450920) method.
+Sets the number of bytes completed for a request and invokes the [**SpbRequestComplete**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/spbcx/nf-spbcx-spbrequestcomplete) method.
\*An atomic transfer in SPB is implemented using Sequence or a Lock/Unlock pair. For I<sup>2</sup>C, this means a set of reads and writes with restarts in between. For SPI, this means a set of reads and writes with the chip select-line asserted throughout.
@@ -97,7 +94,7 @@ Sets the number of bytes completed for a request and invokes the [**SpbRequestCo
The following are relevant functions in the SkeletonI2C driver for implementing controller-specific I2C protocol. For the most part, these are placeholders and must be filled in appropriately.
-INITIALIZATION
+#### INITIALIZATION (controller-specific)
`ControllerInitialize`
@@ -109,7 +106,7 @@ Per-I/O controller configuration. Depending on the type of I/O (and whether its
Additionally, for I<sup>2</sup>C, the driver may need to insert a start, restart, or stop bit as necessary, and for SPI the driver may need to assert or de-assert the chip select line.
-I/O PROCESSING
+#### I/O PROCESSING
`OnInterruptIsr`
@@ -125,4 +122,4 @@ Handles processing for both normal and error condition interrupts. Invokes `Cont
`ControllerCompleteTransfer`
-Invoked when an I/O completes or an error is detected. If this I/O is part of a sequence, `PbcRequestConfigureForIndex`() is called to prepare the next I/O; otherwise, the request is marked for completion. \ No newline at end of file
+Invoked when an I/O completes or an error is detected. If this I/O is part of a sequence, `PbcRequestConfigureForIndex`() is called to prepare the next I/O; otherwise, the request is marked for completion.
diff --git a/spb/SkeletonI2C/internal.h b/spb/SkeletonI2C/internal.h
index 3d102ba4..5ff03af9 100644
--- a/spb/SkeletonI2C/internal.h
+++ b/spb/SkeletonI2C/internal.h
@@ -92,8 +92,8 @@ typedef struct _PNP_I2C_SERIAL_BUS_DESCRIPTOR {
#define MONITOR_POWER_ON 1
#define MONITOR_POWER_OFF 0
-#define IDLE_TIMEOUT_MONITOR_ON 2000
-#define IDLE_TIMEOUT_MONITOR_OFF 50
+#define IDLE_TIMEOUT_MONITOR_ON 1000
+#define IDLE_TIMEOUT_MONITOR_OFF 100
//
// Target settings.
diff --git a/spb/SpbTestTool/README.md b/spb/SpbTestTool/README.md
index 28b8ac1b..e771969b 100644
--- a/spb/SpbTestTool/README.md
+++ b/spb/SpbTestTool/README.md
@@ -5,29 +5,23 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: SpbTestTool sample
- platform: KMDF
- language: cpp
- category: SimplePeripheralBus
- description: Demonstrates how to open a handle to the SPB controller, use the SPB interface from a KMDF driver, and employ GPIO.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617970
---->
-
# SpbTestTool
-The SpbTestTool sample serves two purposes. First, it demonstrates how to open a handle to the [SPB controller](http://msdn.microsoft.com/en-us/library/windows/hardware/hh698220), use the SPB interface from a KMDF driver, and employ GPIO [passive-level interrupts](http://msdn.microsoft.com/en-us/library/windows/hardware/hh451035). Second, it implements a set of commands for communicating with a peripheral device to aid in debugging.
+The SpbTestTool sample serves two purposes. First, it demonstrates how to open a handle to the [SPB controller](https://docs.microsoft.com/windows-hardware/drivers/spb/spb-controller-drivers), use the SPB interface from a KMDF driver, and employ GPIO [passive-level interrupts](https://docs.microsoft.com/windows-hardware/drivers/wdf/supporting-passive-level-interrupts). Second, it implements a set of commands for communicating with a peripheral device to aid in debugging.
-This sample is incomplete as a driver and merely demonstrates use of the [SPB I/O request interface](http://msdn.microsoft.com/en-us/library/windows/hardware/hh698224) and [GPIO interrupts](http://msdn.microsoft.com/en-us/library/windows/hardware/hh406467). It is not intended for use in a production environment.
+This sample is incomplete as a driver and merely demonstrates use of the [SPB I/O request interface](https://docs.microsoft.com/windows-hardware/drivers/spb/using-the-spb-i-o-request-interface) and [GPIO interrupts](https://docs.microsoft.com/windows-hardware/drivers/gpio/gpio-interrupts). It is not intended for use in a production environment.
## Run the sample
To install the SpbTestTool peripheral driver, follow these steps:
1. Ensure that the driver builds without errors.
+
1. Copy the SYS and INF files to a separate folder.
+
1. Run Devcon.exe. You can find this program in the tools\\devcon folder where you installed the WDK. Type the following command in the command window:
`devcon.exe update SpbTestTool.inf ACPI\<hwid>`
@@ -52,74 +46,74 @@ To launch the SpbTestTool application, follow these steps:
The SpbTestTool application loops indefinitely waiting for one of the following commands. The commands are translated to the appropriate SPB I/O request without any state tracking in the driver. Transfer status, buffer contents, and error codes are returned as necessary. Type `help` at any time to display this command list. Press Ctrl-C at any time to cancel the current command and exit the application.
-Command | Description
---------|------------
-open | Open handle to SPB controller.
-close | Close handle to SPB controller.
-lock | Lock the bus for exclusive access.
-unlock | Unlock the bus.
-lockconn | Lock the shared connection for exclusive access. This command is used to synchronize bus transfers by the sample driver with op-region accesses by the ACPI firmware.
-unlockconn | Unlock the shared connection.
-write {} | Write a byte array to the peripheral device. Example: `> write {01, 02, 03}`
-read <*numBytes*> | Read <*numBytes*> from the peripheral device. Example: `> read 5`
-writeread {} <*numBytes*> | Atomically write a byte array to the peripheral device and read <*numBytes*> back. Example: `> writeread {01, 02, 03} 5`
-signal | Inform the SpbTestTool driver that the interrupt has been handled.
-help | Display the list of supported commands.
-Ctrl-C | Press Ctrl-C at any time to cancel the outstanding command and exit the application.
+| Command | Description |
+| --- | --- |
+| open | Open handle to SPB controller. |
+| close | Close handle to SPB controller. |
+| lock | Lock the bus for exclusive access. |
+| unlock | Unlock the bus. |
+| lockconn | Lock the shared connection for exclusive access. This command is used to synchronize bus transfers by the sample driver with op-region accesses by the ACPI firmware. |
+| unlockconn | Unlock the shared connection. |
+| write {} | Write a byte array to the peripheral device. Example: `> write {01, 02, 03}` |
+| read <*numBytes*> | Read <*numBytes*> from the peripheral device. Example: `> read 5` |
+| writeread {} <*numBytes*> | Atomically write a byte array to the peripheral device and read <*numBytes*> back. Example: `> writeread {01, 02, 03} 5` |
+| signal | Inform the SpbTestTool driver that the interrupt has been handled. |
+| help | Display the list of supported commands. |
+| Ctrl-C | Press Ctrl-C at any time to cancel the outstanding command and exit the application. |
## Code tour
The following are the relevant functions in the SpbTestTool peripheral driver for using the SPB interface from a KMDF driver.
-Function | Description
----------|------------
-OnPrepareHardware | Traverses the driver's start resources and caches the connection ID of the I2C or SPI resource. This ID will be used to open the SPB controller later on.
-SpbPeripheralOpen | Opens a handle to the underlying SPB controller via the resource hub. This allows the peripheral driver to be developed without any underlying knowledge of the platform or hardware connections. Instead, the dependency between controller and peripheral is described in ACPI.
-SpbPeripheralClose | Sends IOCTL_SPB_LOCK_CONTROLLER to the SPB controller to lock the bus for exclusive access by this peripheral.
-SpbPeripheralLock | Sends IOCTL_SPB_LOCK_CONTROLLER to the SPB controller to lock the bus for exclusive access by this peripheral.
-SpbPeripheralUnlock | Sends IOCTL_SPB_UNLOCK_CONTROLLER to the SPB controller to unlock the bus from exclusive access by this peripheral.
-SpbPeripheralLockConnection | Sends IOCTL_SPB_LOCK_CONNECTION to the SPB controller to lock the shared connection for exclusive access by this target (file handle).
-SpbPeripheralUnlockConnection | Sends IOCTL_SPB_UNLOCK_CONNECTION to the SPB controller to unlock the shared connection from exclusive access by this target (file handle).
-SpbPeripheralRead | Sends a read request to the SPB controller.
-SpbPeripheralWrite | Sends a write request to the SPB controller.
-SpbPeripheralWriteRead | Builds a write-read sequence and sends IOCTL_SPB_EXECUTE_SEQUENCE to the SPB controller.
-SpbPeripheralOnComplete | Completion callback for all I/O requests.
+| Function | Description |
+| --- | --- |
+| OnPrepareHardware | Traverses the driver's start resources and caches the connection ID of the I2C or SPI resource. This ID will be used to open the SPB controller later on. |
+| SpbPeripheralOpen | Opens a handle to the underlying SPB controller via the resource hub. This allows the peripheral driver to be developed without any underlying knowledge of the platform or hardware connections. Instead, the dependency between controller and peripheral is described in ACPI. |
+| SpbPeripheralClose | Sends IOCTL_SPB_LOCK_CONTROLLER to the SPB controller to lock the bus for exclusive access by this peripheral. |
+| SpbPeripheralLock | Sends IOCTL_SPB_LOCK_CONTROLLER to the SPB controller to lock the bus for exclusive access by this peripheral. |
+| SpbPeripheralUnlock | Sends IOCTL_SPB_UNLOCK_CONTROLLER to the SPB controller to unlock the bus from exclusive access by this peripheral. |
+| SpbPeripheralLockConnection | Sends IOCTL_SPB_LOCK_CONNECTION to the SPB controller to lock the shared connection for exclusive access by this target (file handle). |
+| SpbPeripheralUnlockConnection | Sends IOCTL_SPB_UNLOCK_CONNECTION to the SPB controller to unlock the shared connection from exclusive access by this target (file handle). |
+| SpbPeripheralRead | Sends a read request to the SPB controller. |
+| SpbPeripheralWrite | Sends a write request to the SPB controller. |
+| SpbPeripheralWriteRead | Builds a write-read sequence and sends IOCTL_SPB_EXECUTE_SEQUENCE to the SPB controller. |
+| SpbPeripheralOnComplete | Completion callback for all I/O requests. |
The following are the relevant functions in the SpbTestTool peripheral driver for managing GPIO passive-level interrupts from a KMDF driver.
-Function | Description
----------|------------
-OnPrepareHardware | Traverses the driver's start resources. If "ConnectInterrupt" is set to 1 in the registry, the driver connects the first interrupt resource found and registers an interrupt service routine.
-OnInterruptIsr | The interrupt service routine, which has been configured to run at passive-level. Doing so enables the driver to acknowledge or quiesce the interrupt using the SPB interface, which cannot be called at DIRQL. Typically a driver will clear the hardware interrupt and save any volatile information in its ISR, and then it will queue a workitem to continue processing. Our sample driver instead notifies the SpbTestTool app that an interrupt has occurred and calls KeWaitForSingleObject to wait until the interrupt is handled before returning. A "real" driver should never stall in the ISR like this.
-SpbPeripheralWaitOnInterrupt | Called to pend a WaitOnInterrupt request in the driver, which will be completed when the next interrupt occurs.
-SpbPeripheralInterruptNotify | Completes an outstanding WaitOnInterrupt request to inform the SpbTestTool app that an interrupt has occurred.
-SpbPeripheralSignalInterrupt | Notifies the interrupt service routine that the interrupt has been handled and the ISR should return.
+| Function | Description |
+| --- | --- |
+| OnPrepareHardware | Traverses the driver's start resources. If "ConnectInterrupt" is set to 1 in the registry, the driver connects the first interrupt resource found and registers an interrupt service routine. |
+| OnInterruptIsr | The interrupt service routine, which has been configured to run at passive-level. Doing so enables the driver to acknowledge or quiesce the interrupt using the SPB interface, which cannot be called at DIRQL. Typically a driver will clear the hardware interrupt and save any volatile information in its ISR, and then it will queue a workitem to continue processing. Our sample driver instead notifies the SpbTestTool app that an interrupt has occurred and calls KeWaitForSingleObject to wait until the interrupt is handled before returning. A "real" driver should never stall in the ISR like this. |
+| SpbPeripheralWaitOnInterrupt | Called to pend a WaitOnInterrupt request in the driver, which will be completed when the next interrupt occurs. |
+| SpbPeripheralInterruptNotify | Completes an outstanding WaitOnInterrupt request to inform the SpbTestTool app that an interrupt has occurred. |
+| SpbPeripheralSignalInterrupt | Notifies the interrupt service routine that the interrupt has been handled and the ISR should return. |
## File manifest
The following source files are in the \\SpbTestTool\\sys folder and are used to build the SpbTestTool.sys and SpbTestTool.inf files.
-File | Description
------|------------
-driver.h, driver.cpp | Events on the Device Object, and read, write, and IOCTLs from the SpbTestTool application. Implements the driver's interrupt service routine.
-internal.h | Common includes and typedefs
-makefile | Redirects to the real makefile that is shared by all components of the WDK.
-peripheral.h, peripheral.cpp | Reflection of the SpbTestTool IOCTLs to the SPB API, including opening the controller via the resource hub and using lock, unlock, read, write, and sequence.
-resource.rc | Resource descriptor file used for versioning
-sources | Lists source files and build options.
-sources.dep | Defines build dependencies.
-spbtesttool.asl | Sample ASL file for a peripheral device node. It declares I2C and GPIO interrupt resources. Note each macro specifies an ACPI path to describe direct dependencies.
-spbtesttool.h | Private SpbTestTool IOCTLs for use between the application and peripheral driver, and driver path names.
-spbtesttool.inx | Describes the installation of the driver. The build process converts this into an INF.
-trace.h | Sets up WPP tracing.
+| File | Description |
+| --- | --- |
+| driver.h, driver.cpp | Events on the Device Object, and read, write, and IOCTLs from the SpbTestTool application. Implements the driver's interrupt service routine. |
+| internal.h | Common includes and typedefs |
+| makefile | Redirects to the real makefile that is shared by all components of the WDK. |
+| peripheral.h, peripheral.cpp | Reflection of the SpbTestTool IOCTLs to the SPB API, including opening the controller via the resource hub and using lock, unlock, read, write, and sequence. |
+| resource.rc | Resource descriptor file used for versioning |
+| sources | Lists source files and build options. |
+| sources.dep | Defines build dependencies. |
+| spbtesttool.asl | Sample ASL file for a peripheral device node. It declares I2C and GPIO interrupt resources. Note each macro specifies an ACPI path to describe direct dependencies. |
+| spbtesttool.h | Private SpbTestTool IOCTLs for use between the application and peripheral driver, and driver path names. |
+| spbtesttool.inx | Describes the installation of the driver. The build process converts this into an INF. |
+| trace.h | Sets up WPP tracing. |
The following source files are in the \\SpbTestTool\\exe folder and are used to build the SpbTestTool.exe file.
-File | Description
------|------------
-command.h, command.cpp | Classes respresenting each of the SpbTestTool commands. For the list of commands, see Executing commands.
-internal.h | Common includes and function definitions
-main.cpp | Application entry point, input parsing, and main execution loop. Also contains the interrupt notification thread.
-makefile | Redirects to the real makefile that is shared by all components of the WDK.
-sources | Lists source files and build options.
-util.cpp | Helper functions \ No newline at end of file
+| File | Description |
+| --- | --- |
+| command.h, command.cpp | Classes representing each of the SpbTestTool commands. For the list of commands, see Executing commands. |
+| internal.h | Common includes and function definitions |
+| main.cpp | Application entry point, input parsing, and main execution loop. Also contains the interrupt notification thread. |
+| makefile | Redirects to the real makefile that is shared by all components of the WDK. |
+| sources | Lists source files and build options. |
+| util.cpp | Helper functions |
diff --git a/storage/class/cdrom/README.md b/storage/class/cdrom/README.md
index 34cab42f..4b081014 100644
--- a/storage/class/cdrom/README.md
+++ b/storage/class/cdrom/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: CDROM Storage Class Driver
- platform: KMDF
- language: cpp
- category: Storage
- description: Provide access to CD, DVD and Blu-ray drives, supports Plug and Play, Power Management, and AutoRun (media change notification).
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617971
---->
-
# CDROM Storage Class Driver
The CD ROM driver is used to provide access to CD, DVD and Blu-ray drives. It supports Plug and Play, Power Management, and AutoRun (media change notification).
@@ -23,7 +15,9 @@ The CD ROM driver is used to provide access to CD, DVD and Blu-ray drives. It su
## Build the sample
You can build the sample in two ways: using Microsoft Visual Studio or the command line (*MSBuild*).
-**Note:** When building in Visual Studio, INFVerifer will throw errors. This is intended. Fix those errors with your custom values to build successfully.
+
+> [!NOTE]
+> When building in Visual Studio, INFVerifer will throw errors. This is intended. Fix those errors with your custom values to build successfully.
## Building a Driver Using Visual Studio
@@ -32,8 +26,11 @@ You build a driver the same way you build any project or solution in Visual Stud
The default Solution build configuration is Visual Studio Debug and Win32.
1. Open the driver project or solution in Visual Studio (find *samplename*.sln or *samplename*.vcxproj).
+
1. Right-click the solution in the **Solutions Explorer** and select **Configuration Manager**.
+
1. From the **Configuration Manager**, select the **Active Solution Configuration** (for example, Debug or Release) and the **Active Solution Platform** (for example, Win32) that correspond to the type of build you are interested in.
+
1. From the Build menu, click **Build Solution** (Ctrl+Shift+B).
## Building a Driver Using the Command Line (MSBuild)
@@ -41,25 +38,37 @@ The default Solution build configuration is Visual Studio Debug and Win32.
You can build a driver from the command line using the Visual Studio Command Prompt window and the Microsoft Build Engine (MSBuild.exe) Previous versions of the WDK used the Windows Build utility (Build.exe) and provided separate build environment windows for each of the supported build configurations. You can now use the Visual Studio Command Prompt window for all build configurations.
1. Open a Visual Studio Command Prompt window at the **Start** screen. From this window you can use MsBuild.exe to build any Visual Studio project by specifying the project (.VcxProj) or solutions (.Sln) file.
+
1. Navigate to the project directory and enter the **MSbuild** command for your target. For example, to perform a clean build of a Visual Studio driver project called *filtername*.vcxproj, navigate to the project directory and enter the following MSBuild command:
- **msbuild /t:clean /t:build .\\***samplename***.vcxproj**.
+ `msbuild /t:clean /t:build .\<samplename>.vcxproj`
## Installation and Operation
The in-box CD ROM driver is protected by the system, and thus a normal device driver update attempt through the Device Manager will fail. Users are not encouraged to replace the in-box CD ROM driver. The following work-around is provided in case there is a need, but the users are warned that this may harm the system.
1. Locate the "cdrom.inf" file in the binary output directory, and update the file by replacing all "cdrom.sys" occurrences with "mycdrom.sys".
+
1. Rename the "cdrom.inf" file to "mycdrom.inf".
+
1. Copy "mycdrom.sys" and "mycdrom.inf" from the binary output directory to the test machine, if applicable.
+
1. Launch the Device Manager
+
1. Select the appropriate device under the "DVD/CD-ROM drives" category.
+
1. On the right-click menu, select "Update Driver Software...".
+
1. Select "Browse my computer for driver software".
+
1. Select "Let me pick from a list of device drivers on my computer".
+
1. Click "Have Disk...", and point to the directory that contains "mycdrom.inf" and "mycdrom.sys".
+
1. Click "Next". If you get a warning dialog about installing unsigned driver, click "Yes".
+
1. Click "Next" to complete the driver upgrade.
+
1. After installation completes successfully, "mycdrom.sys" will be the effective driver for the device, "cdrom.sys" will no longer be used.
-For more information, see [CD-ROM Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff551391) in the storage technologies design guide. \ No newline at end of file
+For more information, see [CD-ROM Drivers](https://docs.microsoft.com/windows-hardware/drivers/storage/cd-rom-drivers) in the storage technologies design guide.
diff --git a/storage/class/classpnp/README.md b/storage/class/classpnp/README.md
index 8b74e623..f89e774a 100644
--- a/storage/class/classpnp/README.md
+++ b/storage/class/classpnp/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: ClassPnP Class Driver Library
- platform: WDM
- language: cpp
- category: Storage
- description: A library storage class driver used by disk, CDROM, and the tape class drivers.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617978
---->
-
# ClassPnP Storage Class Driver Library
This is the library for all storage drivers. It simplifies writing a storage class driver by implementing 90 percent of the code that you need to support Plug and Play (PnP), power management, and so on. This library is used by disk, CDROM, and the tape class drivers.
@@ -28,4 +20,4 @@ This sample builds a Universal Windows Driver. It uses only APIs and DDIs that a
The storage class drivers are used to interact with mass storage devices along with appropriate port driver. The class drivers are layered above the port drivers and manage mass storage devices of a specific class, regardless of their bus type. The classpnp sample contains the common routines that are required for all storage class drivers such as PnP and power management. It also provides I/O and error handling support.
-For more information, see [Introduction to Storage Class Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff559215) in the storage technologies design guide. \ No newline at end of file
+For more information, see [Introduction to Storage Class Drivers](https://docs.microsoft.com/windows-hardware/drivers/storage/introduction-to-storage-class-drivers) in the storage technologies design guide.
diff --git a/storage/class/classpnp/src/autorun.c b/storage/class/classpnp/src/autorun.c
index f0a88414..5cb5ca3d 100644
--- a/storage/class/classpnp/src/autorun.c
+++ b/storage/class/classpnp/src/autorun.c
@@ -210,9 +210,9 @@ ClassSendNotification(
return;
}
- notification = ExAllocatePoolWithTag(NonPagedPoolNx,
- requiredSize,
- 'oNcS');
+ notification = ExAllocatePoolZero(NonPagedPoolNx,
+ requiredSize,
+ 'oNcS');
//
// if none allocated, exit
@@ -226,7 +226,6 @@ ClassSendNotification(
// Prepare and send the request!
//
- RtlZeroMemory(notification, requiredSize);
notification->Version = 1;
notification->Size = (USHORT)(requiredSize);
notification->FileObject = NULL;
@@ -1838,13 +1837,11 @@ ClasspInitializePolling(
return STATUS_SUCCESS;
}
- info = ExAllocatePoolWithTag(NonPagedPoolNx,
- sizeof(MEDIA_CHANGE_DETECTION_INFO),
- CLASS_TAG_MEDIA_CHANGE_DETECTION);
+ info = ExAllocatePoolZero(NonPagedPoolNx,
+ sizeof(MEDIA_CHANGE_DETECTION_INFO),
+ CLASS_TAG_MEDIA_CHANGE_DETECTION);
if (info != NULL) {
- RtlZeroMemory(info, sizeof(MEDIA_CHANGE_DETECTION_INFO));
-
FdoExtension->KernelModeMcnContext.FileObject = (PVOID)-1;
FdoExtension->KernelModeMcnContext.DeviceObject = (PVOID)-1;
FdoExtension->KernelModeMcnContext.LockCount = 0;
@@ -1862,10 +1859,10 @@ ClasspInitializePolling(
PVOID buffer;
BOOLEAN GesnSupported = FALSE;
- buffer = ExAllocatePoolWithTag(
- NonPagedPoolNxCacheAligned,
- SENSE_BUFFER_SIZE_EX,
- CLASS_TAG_MEDIA_CHANGE_DETECTION);
+ buffer = ExAllocatePoolZero(
+ NonPagedPoolNxCacheAligned,
+ SENSE_BUFFER_SIZE_EX,
+ CLASS_TAG_MEDIA_CHANGE_DETECTION);
if (buffer != NULL) {
@@ -2032,9 +2029,10 @@ ClasspInitializeGesn(
//
if (Info->Gesn.Buffer == NULL) {
- Info->Gesn.Buffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
- GESN_BUFFER_SIZE,
- '??cS');
+ Info->Gesn.Buffer = ExAllocatePoolZero(
+ NonPagedPoolNxCacheAligned,
+ GESN_BUFFER_SIZE,
+ '??cS');
}
if (Info->Gesn.Buffer == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
@@ -2816,10 +2814,9 @@ ClasspIsMediaChangeDisabledDueToHardwareLimitation(
deviceString.Length = (USHORT)( length );
deviceString.MaximumLength = deviceString.Length + 1;
- deviceString.Buffer = (PCHAR)ExAllocatePoolWithTag( NonPagedPoolNx,
- deviceString.MaximumLength,
- CLASS_TAG_AUTORUN_DISABLE
- );
+ deviceString.Buffer = (PCHAR)ExAllocatePoolZero( NonPagedPoolNx,
+ deviceString.MaximumLength,
+ CLASS_TAG_AUTORUN_DISABLE );
if (deviceString.Buffer == NULL) {
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
"ClassMediaChangeDisabledForHardware: Unable to alloc "
@@ -4277,9 +4274,9 @@ ClassSetFailurePredictionPoll(
if (FailurePredictionMethod != FailurePredictionNone) {
- info = ExAllocatePoolWithTag(NonPagedPoolNx,
- sizeof(FAILURE_PREDICTION_INFO),
- CLASS_TAG_FAILURE_PREDICT);
+ info = ExAllocatePoolZero(NonPagedPoolNx,
+ sizeof(FAILURE_PREDICTION_INFO),
+ CLASS_TAG_FAILURE_PREDICT);
if (info == NULL) {
diff --git a/storage/class/classpnp/src/class.c b/storage/class/classpnp/src/class.c
index 5e7f00f1..58d1835a 100644
--- a/storage/class/classpnp/src/class.c
+++ b/storage/class/classpnp/src/class.c
@@ -222,6 +222,11 @@ ClassInitialize(
PAGED_CODE();
//
+ // Must be called before calling pool allocation functions.
+ //
+ ExInitializeDriverRuntime(0);
+
+ //
// Initialize the security cookie if needed.
//
if (InitSecurityCookie == FALSE) {
@@ -348,9 +353,9 @@ ClassInitialize(
driverExtension->RegistryPath.MaximumLength = RegistryPath->MaximumLength;
driverExtension->RegistryPath.Buffer =
- ExAllocatePoolWithTag(PagedPool,
- RegistryPath->MaximumLength,
- '1CcS');
+ ExAllocatePoolZero(PagedPool,
+ RegistryPath->MaximumLength,
+ '1CcS');
if(driverExtension->RegistryPath.Buffer == NULL) {
@@ -557,10 +562,9 @@ ClassInitializeEx(
}
else
{
- info = ExAllocatePoolWithTag(NonPagedPoolNx,
- sizeof(CLASS_WORKING_SET),
- CLASS_TAG_WORKING_SET
- );
+ info = ExAllocatePoolZero(NonPagedPoolNx,
+ sizeof(CLASS_WORKING_SET),
+ CLASS_TAG_WORKING_SET);
if (info == NULL)
{
status = STATUS_INSUFFICIENT_RESOURCES;
@@ -626,10 +630,9 @@ ClassInitializeEx(
}
else
{
- info = ExAllocatePoolWithTag(NonPagedPoolNx,
- sizeof(CLASS_INTERPRET_SENSE_INFO2),
- CLASS_TAG_SENSE2
- );
+ info = ExAllocatePoolZero(NonPagedPoolNx,
+ sizeof(CLASS_INTERPRET_SENSE_INFO2),
+ CLASS_TAG_SENSE2);
if (info == NULL)
{
status = STATUS_INSUFFICIENT_RESOURCES;
@@ -960,15 +963,12 @@ ClassDispatchPnp(
status = STATUS_INSUFFICIENT_RESOURCES;
- deviceRelations = ExAllocatePoolWithTag(PagedPool,
- sizeof(DEVICE_RELATIONS),
- '2CcS');
+ deviceRelations = ExAllocatePoolZero(PagedPool,
+ sizeof(DEVICE_RELATIONS),
+ '2CcS');
if(deviceRelations != NULL) {
- RtlZeroMemory(deviceRelations,
- sizeof(DEVICE_RELATIONS));
-
Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
deviceRelations->Count = 1;
@@ -1836,10 +1836,10 @@ NTSTATUS ClassPnpStartDevice(IN PDEVICE_OBJECT DeviceObject)
//
if (fdoExtension->PrivateFdoData == NULL) {
- fdoExtension->PrivateFdoData = ExAllocatePoolWithTag(NonPagedPoolNx,
- sizeof(CLASS_PRIVATE_FDO_DATA),
- CLASS_TAG_PRIVATE_DATA
- );
+ fdoExtension->PrivateFdoData = ExAllocatePoolZero(
+ NonPagedPoolNx,
+ sizeof(CLASS_PRIVATE_FDO_DATA),
+ CLASS_TAG_PRIVATE_DATA);
}
if (fdoExtension->PrivateFdoData == NULL) {
@@ -1856,10 +1856,10 @@ NTSTATUS ClassPnpStartDevice(IN PDEVICE_OBJECT DeviceObject)
// This structure's memory is managed by classpnp, so it is more extensible.
//
if (fdoExtension->AdditionalFdoData == NULL) {
- fdoExtension->AdditionalFdoData = ExAllocatePoolWithTag(NonPagedPoolNx,
- sizeof(ADDITIONAL_FDO_DATA),
- CLASSPNP_POOL_TAG_ADDITIONAL_DATA
- );
+ fdoExtension->AdditionalFdoData = ExAllocatePoolZero(
+ NonPagedPoolNx,
+ sizeof(ADDITIONAL_FDO_DATA),
+ CLASSPNP_POOL_TAG_ADDITIONAL_DATA);
}
if (fdoExtension->AdditionalFdoData == NULL) {
@@ -1885,10 +1885,11 @@ NTSTATUS ClassPnpStartDevice(IN PDEVICE_OBJECT DeviceObject)
//
if (fdoExtension->FunctionSupportInfo == NULL) {
- fdoExtension->FunctionSupportInfo = (PCLASS_FUNCTION_SUPPORT_INFO)ExAllocatePoolWithTag(NonPagedPoolNx,
- sizeof(CLASS_FUNCTION_SUPPORT_INFO),
- '3BcS'
- );
+ fdoExtension->FunctionSupportInfo =
+ (PCLASS_FUNCTION_SUPPORT_INFO)ExAllocatePoolZero(
+ NonPagedPoolNx,
+ sizeof(CLASS_FUNCTION_SUPPORT_INFO),
+ '3BcS');
}
if (fdoExtension->FunctionSupportInfo == NULL) {
@@ -3051,9 +3052,9 @@ ClassSendStartUnit(
// Allocate Srb from nonpaged pool.
//
- context = ExAllocatePoolWithTag(NonPagedPoolNx,
- sizeof(COMPLETION_CONTEXT),
- '6CcS');
+ context = ExAllocatePoolZero(NonPagedPoolNx,
+ sizeof(COMPLETION_CONTEXT),
+ '6CcS');
if (context == NULL) {
@@ -4068,9 +4069,9 @@ ClassSendSrbSynchronous(
#endif
- senseInfoBuffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
- senseInfoBufferLength,
- '7CcS');
+ senseInfoBuffer = ExAllocatePoolZero(NonPagedPoolNxCacheAligned,
+ senseInfoBufferLength,
+ '7CcS');
if (senseInfoBuffer == NULL) {
@@ -7443,7 +7444,7 @@ ClassDeviceControl(
break;
}
- valueName = ExAllocatePoolWithTag(
+ valueName = ExAllocatePoolZero(
PagedPool,
commonExtension->DeviceName.Length + sizeof(WCHAR),
'8CcS');
@@ -7561,10 +7562,9 @@ ClassDeviceControl(
sizeNeeded = sizeof(SCSI_REQUEST_BLOCK);
}
- srb = ExAllocatePoolWithTag(NonPagedPoolNx,
- sizeNeeded +
- (sizeof(ULONG_PTR) * 2),
- '9CcS');
+ srb = ExAllocatePoolZero(NonPagedPoolNx,
+ sizeNeeded + (sizeof(ULONG_PTR) * 2),
+ '9CcS');
if (srb == NULL) {
@@ -7593,7 +7593,6 @@ ClassDeviceControl(
goto SetStatusAndReturn;
}
} else {
- RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
srb->Length = sizeof(SCSI_REQUEST_BLOCK);
srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
function = (PULONG_PTR) ((PSCSI_REQUEST_BLOCK) (srb + 1));
@@ -9431,16 +9430,16 @@ ClassQueryTimeOutRegistryValue(
return 0;
}
- parameters = ExAllocatePoolWithTag(NonPagedPoolNx,
- sizeof(RTL_QUERY_REGISTRY_TABLE)*2,
- '1BcS');
+ parameters = ExAllocatePoolZero(NonPagedPoolNx,
+ sizeof(RTL_QUERY_REGISTRY_TABLE) * 2,
+ '1BcS');
if (!parameters) {
return 0;
}
size = registryPath->MaximumLength + sizeof(WCHAR);
- path = ExAllocatePoolWithTag(NonPagedPoolNx, size, '2BcS');
+ path = ExAllocatePoolZero(NonPagedPoolNx, size, '2BcS');
if (!path) {
FREE_POOL(parameters);
@@ -9455,9 +9454,6 @@ ClassQueryTimeOutRegistryValue(
// Check for the Timeout value.
//
- RtlZeroMemory(parameters,
- (sizeof(RTL_QUERY_REGISTRY_TABLE)*2));
-
parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK;
parameters[0].Name = L"TimeOutValue";
parameters[0].EntryContext = &timeOut;
@@ -9625,7 +9621,7 @@ ClassGetDescriptor(
if(!NT_SUCCESS(ioStatus.Status)) {
- TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClassGetDescriptor: error %lx trying to "
+ TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClassGetDescriptor: error %lx trying to "
"query properties #1\n", ioStatus.Status));
return ioStatus.Status;
}
@@ -9651,7 +9647,7 @@ ClassGetDescriptor(
NT_ASSERT(length >= sizeof(STORAGE_PROPERTY_QUERY));
length = max(length, sizeof(STORAGE_PROPERTY_QUERY));
- descriptor = ExAllocatePoolWithTag(NonPagedPoolNx, length, '4BcS');
+ descriptor = ExAllocatePoolZero(NonPagedPoolNx, length, '4BcS');
if(descriptor == NULL) {
@@ -9672,8 +9668,6 @@ ClassGetDescriptor(
// copy the input to the new outputbuffer
//
- RtlZeroMemory(descriptor, length);
-
RtlCopyMemory(descriptor,
&query,
sizeof(STORAGE_PROPERTY_QUERY)
@@ -9989,7 +9983,7 @@ ClassRetrieveDeviceRelations(
relationsSize = (sizeof(DEVICE_RELATIONS) +
(count * sizeof(PDEVICE_OBJECT)));
- deviceRelations = ExAllocatePoolWithTag(PagedPool, relationsSize, '5BcS');
+ deviceRelations = ExAllocatePoolZero(PagedPool, relationsSize, '5BcS');
if (deviceRelations == NULL) {
@@ -10001,8 +9995,6 @@ ClassRetrieveDeviceRelations(
return STATUS_INSUFFICIENT_RESOURCES;
}
- RtlZeroMemory(deviceRelations, relationsSize);
-
if (oldRelations) {
//
@@ -11056,9 +11048,11 @@ ClassSendDeviceIoControlSynchronous(
{
if ((InputBufferLength != 0) || (OutputBufferLength != 0))
{
- irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
- max(InputBufferLength, OutputBufferLength),
- CLASS_TAG_DEVICE_CONTROL);
+ irp->AssociatedIrp.SystemBuffer =
+ ExAllocatePoolZero(NonPagedPoolNxCacheAligned,
+ max(InputBufferLength, OutputBufferLength),
+ CLASS_TAG_DEVICE_CONTROL);
+
if (irp->AssociatedIrp.SystemBuffer == NULL)
{
IoFreeIrp(irp);
@@ -11543,10 +11537,9 @@ ClasspAllocateReleaseQueueIrp(
NT_ASSERT(!(FdoExtension->ReleaseQueueInProgress));
FdoExtension->PrivateFdoData->ReleaseQueueIrp =
- ExAllocatePoolWithTag(NonPagedPoolNx,
- IoSizeOfIrp(lowerStackSize),
- CLASS_TAG_RELEASE_QUEUE
- );
+ ExAllocatePoolZero(NonPagedPoolNx,
+ IoSizeOfIrp(lowerStackSize),
+ CLASS_TAG_RELEASE_QUEUE);
if (FdoExtension->PrivateFdoData->ReleaseQueueIrp == NULL) {
TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: Cannot allocate for "
@@ -11590,10 +11583,10 @@ ClasspAllocatePowerProcessIrp(
stackSize = FdoExtension->CommonExtension.LowerDeviceObject->StackSize + 1;
- FdoExtension->PrivateFdoData->PowerProcessIrp = ExAllocatePoolWithTag(NonPagedPoolNx,
- IoSizeOfIrp(stackSize),
- CLASS_TAG_POWER
- );
+ FdoExtension->PrivateFdoData->PowerProcessIrp =
+ ExAllocatePoolZero(NonPagedPoolNx,
+ IoSizeOfIrp(stackSize),
+ CLASS_TAG_POWER);
if (FdoExtension->PrivateFdoData->PowerProcessIrp == NULL) {
@@ -12824,17 +12817,15 @@ ClasspGetInquiryVpdSupportInfo(
// ARM has specific alignment requirements, although this will not have a functional impact on x86 or amd64
// based platforms. We are taking the conservative approach here.
//
- allocationBufferLength = ALIGN_UP_BY(allocationBufferLength,KeGetRecommendedSharedDataAlignment());
- supportedPages = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
- allocationBufferLength,
- '3CcS'
- );
+ allocationBufferLength = ALIGN_UP_BY(allocationBufferLength , KeGetRecommendedSharedDataAlignment());
+ supportedPages = ExAllocatePoolZero(NonPagedPoolNxCacheAligned,
+ allocationBufferLength,
+ '3CcS');
#else
- supportedPages = ExAllocatePoolWithTag(NonPagedPoolNx,
- bufferLength,
- '3CcS'
- );
+ supportedPages = ExAllocatePoolZero(NonPagedPoolNx,
+ bufferLength,
+ '3CcS');
#endif
if (supportedPages == NULL) {
@@ -12842,8 +12833,6 @@ ClasspGetInquiryVpdSupportInfo(
return;
}
- RtlZeroMemory(supportedPages, allocationBufferLength);
-
// prepare the Srb
if (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
@@ -13006,7 +12995,7 @@ ClasspGetLBProvisioningInfo(
srbSize = sizeof(SCSI_REQUEST_BLOCK);
}
- srb = ExAllocatePoolWithTag(NonPagedPoolNx, srbSize, '0DcS');
+ srb = ExAllocatePoolZero(NonPagedPoolNx, srbSize, '0DcS');
if (srb == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
@@ -13162,7 +13151,7 @@ Return Value:
srbSize = sizeof(SCSI_REQUEST_BLOCK);
}
- srb = ExAllocatePoolWithTag(NonPagedPoolNx, srbSize, CLASSPNP_POOL_TAG_SRB);
+ srb = ExAllocatePoolZero(NonPagedPoolNx, srbSize, CLASSPNP_POOL_TAG_SRB);
if (!srb) {
@@ -13181,9 +13170,13 @@ Return Value:
// based platforms. We are taking the conservative approach here.
//
allocationBufferLength = ALIGN_UP_BY(allocationBufferLength, KeGetRecommendedSharedDataAlignment());
- dataBuffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned, allocationBufferLength, CLASSPNP_POOL_TAG_VPD);
+ dataBuffer = ExAllocatePoolZero(NonPagedPoolNxCacheAligned,
+ allocationBufferLength,
+ CLASSPNP_POOL_TAG_VPD);
#else
- dataBuffer = ExAllocatePoolWithTag(NonPagedPoolNx, bufferLength, CLASSPNP_POOL_TAG_VPD);
+ dataBuffer = ExAllocatePoolZero(NonPagedPoolNx,
+ bufferLength,
+ CLASSPNP_POOL_TAG_VPD);
#endif
if (!dataBuffer) {
@@ -13199,8 +13192,6 @@ Return Value:
operatingParameters = (PVPD_THIRD_PARTY_COPY_PAGE)dataBuffer;
- RtlZeroMemory(dataBuffer, allocationBufferLength);
-
if ((fdoExtension->AdapterDescriptor != NULL) &&
(fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK)) {
status = InitializeStorageRequestBlock((PSTORAGE_REQUEST_BLOCK)srb,
@@ -13230,7 +13221,6 @@ Return Value:
}
} else {
- RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
srb->Length = sizeof(SCSI_REQUEST_BLOCK);
srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
}
@@ -13816,10 +13806,9 @@ Return Value:
allocationSize = sizeof(OFFLOAD_READ_CONTEXT) + bufferLength;
- offloadReadContext = ExAllocatePoolWithTag(
- NonPagedPoolNx,
- allocationSize,
- CLASSPNP_POOL_TAG_TOKEN_OPERATION);
+ offloadReadContext = ExAllocatePoolZero(NonPagedPoolNx,
+ allocationSize,
+ CLASSPNP_POOL_TAG_TOKEN_OPERATION);
if (!offloadReadContext) {
@@ -13832,8 +13821,6 @@ Return Value:
goto __ClasspServicePopulateTokenTransferRequest_ErrorExit;
}
- RtlZeroMemory(offloadReadContext, allocationSize);
-
offloadReadContext->Fdo = Fdo;
offloadReadContext->OffloadReadDsmIrp = Irp;
@@ -14885,10 +14872,9 @@ Return Value:
allocationSize = sizeof(OFFLOAD_WRITE_CONTEXT) + bufferLength;
- offloadWriteContext = ExAllocatePoolWithTag(
- NonPagedPoolNx,
- allocationSize,
- CLASSPNP_POOL_TAG_TOKEN_OPERATION);
+ offloadWriteContext = ExAllocatePoolZero(NonPagedPoolNx,
+ allocationSize,
+ CLASSPNP_POOL_TAG_TOKEN_OPERATION);
if (!offloadWriteContext) {
@@ -14901,12 +14887,6 @@ Return Value:
goto __ClasspServiceWriteUsingTokenTransferRequest_ErrorExit;
}
- //
- // Only zero the context portion here. The buffer portion is zeroed for
- // each sub-request.
- //
- RtlZeroMemory(offloadWriteContext, sizeof(OFFLOAD_WRITE_CONTEXT));
-
offloadWriteContext->Fdo = Fdo;
offloadWriteContext->OffloadWriteDsmIrp = Irp;
offloadWriteContext->OperationStartTime = KeQueryInterruptTime();
@@ -16343,7 +16323,7 @@ Return Value:
srbSize = sizeof(SCSI_REQUEST_BLOCK);
}
- srb = ExAllocatePoolWithTag(NonPagedPoolNx, srbSize, '1DcS');
+ srb = ExAllocatePoolZero(NonPagedPoolNx, srbSize, '1DcS');
if (srb == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
diff --git a/storage/class/classpnp/src/classp.h b/storage/class/classpnp/src/classp.h
index d7d57e9d..1e2331c2 100644
--- a/storage/class/classpnp/src/classp.h
+++ b/storage/class/classpnp/src/classp.h
@@ -26,6 +26,7 @@ Revision History:
--*/
#define RTL_USE_AVL_TABLES 0
+#define POOL_ZERO_DOWN_LEVEL_SUPPORT
#include <stddef.h>
#include <stdarg.h>
diff --git a/storage/class/classpnp/src/classwmi.c b/storage/class/classpnp/src/classwmi.c
index 1b1eeeee..e21ec356 100644
--- a/storage/class/classpnp/src/classwmi.c
+++ b/storage/class/classpnp/src/classwmi.c
@@ -1175,10 +1175,9 @@ ClassWmiFireEvent(
sizeNeeded = sizeof(WNODE_SINGLE_INSTANCE) + EventDataSize;
- event = ExAllocatePoolWithTag(NonPagedPoolNx, sizeNeeded, CLASS_TAG_WMI);
+ event = ExAllocatePoolZero(NonPagedPoolNx, sizeNeeded, CLASS_TAG_WMI);
if (event != NULL)
{
- RtlZeroMemory(event, sizeNeeded);
event->WnodeHeader.Guid = *Guid;
event->WnodeHeader.ProviderId = IoWMIDeviceObjectToProviderId(DeviceObject);
event->WnodeHeader.BufferSize = sizeNeeded;
diff --git a/storage/class/classpnp/src/debug.c b/storage/class/classpnp/src/debug.c
index cc288ec6..b811c6d0 100644
--- a/storage/class/classpnp/src/debug.c
+++ b/storage/class/classpnp/src/debug.c
@@ -165,8 +165,9 @@ Revision History:
"ClassDebugPrint: Allocating %x bytes for "
"classdebugprint buffer\n", (ULONG)bufferSize);
ClasspnpGlobals.Index = (ULONG)-1;
- ClasspnpGlobals.Buffer =
- ExAllocatePoolWithTag(NonPagedPoolNx, bufferSize, 'bDcS');
+ ClasspnpGlobals.Buffer = ExAllocatePoolZero(NonPagedPoolNx,
+ bufferSize,
+ 'bDcS');
DbgPrintEx(DPFLTR_CLASSPNP_ID, DPFLTR_ERROR_LEVEL,
"ClassDebugPrint: Allocated buffer at %p\n",
ClasspnpGlobals.Buffer);
diff --git a/storage/class/classpnp/src/dictlib.c b/storage/class/classpnp/src/dictlib.c
index 90a67117..73a7e5ca 100644
--- a/storage/class/classpnp/src/dictlib.c
+++ b/storage/class/classpnp/src/dictlib.c
@@ -78,15 +78,14 @@ AllocateDictionaryEntry(
*Entry = NULL;
- header = ExAllocatePoolWithTag(NonPagedPoolNx,
- Size + sizeof(DICTIONARY_HEADER),
- Tag);
+ header = ExAllocatePoolZero(NonPagedPoolNx,
+ Size + sizeof(DICTIONARY_HEADER),
+ Tag);
if(header == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
- RtlZeroMemory(header, sizeof(DICTIONARY_HEADER) + Size);
header->Key = Key;
//
diff --git a/storage/class/classpnp/src/lock.c b/storage/class/classpnp/src/lock.c
index 1b5a8862..1d0d240c 100644
--- a/storage/class/classpnp/src/lock.c
+++ b/storage/class/classpnp/src/lock.c
@@ -472,7 +472,9 @@ RemoveTrackingAllocateRoutine(
{
UNREFERENCED_PARAMETER(Table);
- return ExAllocatePoolWithTag(NonPagedPoolNx, ByteSize, CLASS_TAG_LOCK_TRACKING);
+ return ExAllocatePoolZero(NonPagedPoolNx,
+ ByteSize,
+ CLASS_TAG_LOCK_TRACKING);
}
VOID
@@ -496,7 +498,10 @@ ClasspInitializeRemoveTracking(
#if DBG
KeInitializeSpinLock(&commonExtension->RemoveTrackingSpinlock);
- commonExtension->RemoveTrackingList = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(RTL_GENERIC_TABLE), CLASS_TAG_LOCK_TRACKING);
+ commonExtension->RemoveTrackingList =
+ ExAllocatePoolZero(NonPagedPoolNx,
+ sizeof(RTL_GENERIC_TABLE),
+ CLASS_TAG_LOCK_TRACKING);
if (commonExtension->RemoveTrackingList != NULL)
{
diff --git a/storage/class/classpnp/src/power.c b/storage/class/classpnp/src/power.c
index 790dba4a..75a6c05d 100644
--- a/storage/class/classpnp/src/power.c
+++ b/storage/class/classpnp/src/power.c
@@ -2615,7 +2615,9 @@ Return Value:
//
// Put this FDO on the list of devices that are idle power managed.
//
- fdoEntry = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(IDLE_POWER_FDO_LIST_ENTRY), CLASS_TAG_POWER);
+ fdoEntry = ExAllocatePoolZero(NonPagedPoolNx,
+ sizeof(IDLE_POWER_FDO_LIST_ENTRY),
+ CLASS_TAG_POWER);
if (fdoEntry) {
fdoExtension->FunctionSupportInfo->IdlePower.IdlePowerEnabled = TRUE;
diff --git a/storage/class/classpnp/src/srblib.c b/storage/class/classpnp/src/srblib.c
index 64a7ca88..f56ae419 100644
--- a/storage/class/classpnp/src/srblib.c
+++ b/storage/class/classpnp/src/srblib.c
@@ -44,7 +44,7 @@ Return Value:
--*/
{
- return ExAllocatePoolWithTag(NonPagedPoolNx, ByteSize, '+brs');
+ return ExAllocatePoolZero(NonPagedPoolNx, ByteSize, '+brs');
}
diff --git a/storage/class/classpnp/src/utils.c b/storage/class/classpnp/src/utils.c
index 323d7449..120031eb 100644
--- a/storage/class/classpnp/src/utils.c
+++ b/storage/class/classpnp/src/utils.c
@@ -1296,9 +1296,9 @@ NTSTATUS ClasspWriteCacheProperty(
status = STATUS_SUCCESS;
}
- modeData = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
- MODE_PAGE_DATA_SIZE,
- CLASS_TAG_MODE_DATA);
+ modeData = ExAllocatePoolZero(NonPagedPoolNxCacheAligned,
+ MODE_PAGE_DATA_SIZE,
+ CLASS_TAG_MODE_DATA);
if (modeData == NULL) {
TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, "ClasspWriteCacheProperty: Unable to allocate mode data buffer\n"));
@@ -1306,8 +1306,6 @@ NTSTATUS ClasspWriteCacheProperty(
goto WriteCacheExit;
}
- RtlZeroMemory(modeData, MODE_PAGE_DATA_SIZE);
-
length = ClassModeSense(DeviceObject,
(PCHAR) modeData,
MODE_PAGE_DATA_SIZE,
@@ -1598,10 +1596,16 @@ ClassReadCapacity16 (
// ARM has specific alignment requirements, although this will not have a functional impact on x86 or amd64
// based platforms. We are taking the conservative approach here.
//
- allocationBufferLength = ALIGN_UP_BY(allocationBufferLength,KeGetRecommendedSharedDataAlignment());
- dataBuffer = (PREAD_CAPACITY16_DATA)ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned, allocationBufferLength, '4CcS');
+ allocationBufferLength = ALIGN_UP_BY(allocationBufferLength, KeGetRecommendedSharedDataAlignment());
+ dataBuffer = (PREAD_CAPACITY16_DATA)
+ ExAllocatePoolZero(NonPagedPoolNxCacheAligned,
+ allocationBufferLength,
+ '4CcS');
#else
- dataBuffer = (PREAD_CAPACITY16_DATA)ExAllocatePoolWithTag(NonPagedPoolNx, bufferLength, '4CcS');
+ dataBuffer = (PREAD_CAPACITY16_DATA)
+ ExAllocatePoolZero(NonPagedPoolNx,
+ bufferLength,
+ '4CcS');
#endif
if (dataBuffer == NULL) {
@@ -1610,8 +1614,6 @@ ClassReadCapacity16 (
return STATUS_INSUFFICIENT_RESOURCES;
}
- RtlZeroMemory(dataBuffer, allocationBufferLength);
-
//
// Initialize the SRB.
//
@@ -2097,25 +2099,23 @@ Return Value:
// ARM has specific alignment requirements, although this will not have a functional impact on x86 or amd64
// based platforms. We are taking the conservative approach here.
//
- allocationBufferLength = ALIGN_UP_BY(allocationBufferLength,KeGetRecommendedSharedDataAlignment());
- dataBuffer = (PVPD_BLOCK_DEVICE_CHARACTERISTICS_PAGE)ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
- allocationBufferLength,
- '5CcS'
- );
+ allocationBufferLength = ALIGN_UP_BY(allocationBufferLength, KeGetRecommendedSharedDataAlignment());
+ dataBuffer = (PVPD_BLOCK_DEVICE_CHARACTERISTICS_PAGE)
+ ExAllocatePoolZero(NonPagedPoolNxCacheAligned,
+ allocationBufferLength,
+ '5CcS');
#else
- dataBuffer = (PVPD_BLOCK_DEVICE_CHARACTERISTICS_PAGE)ExAllocatePoolWithTag(NonPagedPoolNx,
- bufferLength,
- '5CcS'
- );
+ dataBuffer = (PVPD_BLOCK_DEVICE_CHARACTERISTICS_PAGE)
+ ExAllocatePoolZero(NonPagedPoolNx,
+ bufferLength,
+ '5CcS');
#endif
if (dataBuffer == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto Exit;
}
- RtlZeroMemory(dataBuffer, allocationBufferLength);
-
// prepare the Srb
SrbSetTimeOutValue(Srb, fdoExtension->TimeOutValue);
SrbSetRequestTag(Srb, SP_UNTAGGED);
@@ -2384,10 +2384,14 @@ NTSTATUS ClasspDeviceGetLBProvisioningVPDPage(
// based platforms. We are taking the conservative approach here.
//
//
- allocationBufferLength = ALIGN_UP_BY(allocationBufferLength,KeGetRecommendedSharedDataAlignment());
- dataBuffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned, allocationBufferLength,'0CcS');
+ allocationBufferLength = ALIGN_UP_BY(allocationBufferLength, KeGetRecommendedSharedDataAlignment());
+ dataBuffer = ExAllocatePoolZero(NonPagedPoolNxCacheAligned,
+ allocationBufferLength,
+ '0CcS');
#else
- dataBuffer = ExAllocatePoolWithTag(NonPagedPoolNx, bufferLength,'0CcS');
+ dataBuffer = ExAllocatePoolZero(NonPagedPoolNx,
+ bufferLength,
+ '0CcS');
#endif
if (dataBuffer == NULL) {
// return without updating FdoExtension->FunctionSupportInfo->LBProvisioningData.CommandStatus
@@ -2398,8 +2402,6 @@ NTSTATUS ClasspDeviceGetLBProvisioningVPDPage(
lbProvisioning = (PVPD_LOGICAL_BLOCK_PROVISIONING_PAGE)dataBuffer;
- RtlZeroMemory(dataBuffer, allocationBufferLength);
-
if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
status = InitializeStorageRequestBlock((PSTORAGE_REQUEST_BLOCK)Srb,
STORAGE_ADDRESS_TYPE_BTL8,
@@ -2559,9 +2561,13 @@ NTSTATUS ClasspDeviceGetBlockLimitsVPDPage(
// based platforms. We are taking the conservative approach here.
//
allocationBufferLength = ALIGN_UP_BY(allocationBufferLength, KeGetRecommendedSharedDataAlignment());
- dataBuffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned, allocationBufferLength, '0CcS');
+ dataBuffer = ExAllocatePoolZero(NonPagedPoolNxCacheAligned,
+ allocationBufferLength,
+ '0CcS');
#else
- dataBuffer = ExAllocatePoolWithTag(NonPagedPoolNx, bufferLength, '0CcS');
+ dataBuffer = ExAllocatePoolZero(NonPagedPoolNx,
+ bufferLength,
+ '0CcS');
#endif
if (dataBuffer == NULL)
{
@@ -2573,8 +2579,6 @@ NTSTATUS ClasspDeviceGetBlockLimitsVPDPage(
blockLimits = (PVPD_BLOCK_LIMITS_PAGE)dataBuffer;
- RtlZeroMemory(dataBuffer, allocationBufferLength);
-
if (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
#pragma prefast(suppress:26015, "InitializeStorageRequestBlock ensures buffer access is bounded")
@@ -3305,9 +3309,15 @@ Return Value:
// based platforms. We are taking the conservative approach here.
//
bufferLength = ALIGN_UP_BY(bufferLength,KeGetRecommendedSharedDataAlignment());
- buffer = (PUNMAP_LIST_HEADER)ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned, bufferLength, CLASS_TAG_LB_PROVISIONING);
+ buffer = (PUNMAP_LIST_HEADER)
+ ExAllocatePoolZero(NonPagedPoolNxCacheAligned,
+ bufferLength,
+ CLASS_TAG_LB_PROVISIONING);
#else
- buffer = (PUNMAP_LIST_HEADER)ExAllocatePoolWithTag(NonPagedPoolNx, bufferLength, CLASS_TAG_LB_PROVISIONING);
+ buffer = (PUNMAP_LIST_HEADER)
+ ExAllocatePoolZero(NonPagedPoolNx,
+ bufferLength,
+ CLASS_TAG_LB_PROVISIONING);
#endif
if (buffer == NULL) {
@@ -3315,8 +3325,6 @@ Return Value:
goto Exit;
}
- RtlZeroMemory(buffer, bufferLength);
-
blockDescrPointer = &buffer->Descriptors[0];
allDataSetRangeFullyConverted = FALSE;
@@ -4373,9 +4381,15 @@ Return Value:
// based platforms. We are taking the conservative approach here.
//
lbaStatusSize = ALIGN_UP_BY(lbaStatusSize,KeGetRecommendedSharedDataAlignment());
- lbaStatusListHeader = (PLBA_STATUS_LIST_HEADER)ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned, lbaStatusSize, CLASS_TAG_LB_PROVISIONING);
+ lbaStatusListHeader = (PLBA_STATUS_LIST_HEADER)
+ ExAllocatePoolZero(NonPagedPoolNxCacheAligned,
+ lbaStatusSize,
+ CLASS_TAG_LB_PROVISIONING);
#else
- lbaStatusListHeader = (PLBA_STATUS_LIST_HEADER)ExAllocatePoolWithTag(NonPagedPoolNx, lbaStatusSize, CLASS_TAG_LB_PROVISIONING);
+ lbaStatusListHeader = (PLBA_STATUS_LIST_HEADER)
+ ExAllocatePoolZero(NonPagedPoolNx,
+ lbaStatusSize,
+ CLASS_TAG_LB_PROVISIONING);
#endif
if (lbaStatusListHeader == NULL)
@@ -5032,9 +5046,15 @@ Return Value:
// based platforms. We are taking the conservative approach here.
//
logPageSize = ALIGN_UP_BY(logPageSize, KeGetRecommendedSharedDataAlignment());
- logPage = (PLOG_PAGE_LOGICAL_BLOCK_PROVISIONING)ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned, logPageSize, CLASS_TAG_LB_PROVISIONING);
+ logPage = (PLOG_PAGE_LOGICAL_BLOCK_PROVISIONING)
+ ExAllocatePoolZero(NonPagedPoolNxCacheAligned,
+ logPageSize,
+ CLASS_TAG_LB_PROVISIONING);
#else
- logPage = (PLOG_PAGE_LOGICAL_BLOCK_PROVISIONING)ExAllocatePoolWithTag(NonPagedPoolNx, logPageSize, CLASS_TAG_LB_PROVISIONING);
+ logPage = (PLOG_PAGE_LOGICAL_BLOCK_PROVISIONING)
+ ExAllocatePoolZero(NonPagedPoolNx,
+ logPageSize,
+ CLASS_TAG_LB_PROVISIONING);
#endif
if (logPage != NULL)
{
@@ -5166,9 +5186,9 @@ Arguments:
srbSize = sizeof(SCSI_REQUEST_BLOCK);
}
- srb = ExAllocatePoolWithTag(NonPagedPoolNx,
- srbSize,
- 'ACcS');
+ srb = ExAllocatePoolZero(NonPagedPoolNx,
+ srbSize,
+ 'ACcS');
if (srb != NULL) {
//
@@ -6046,7 +6066,9 @@ Arguments:
}
if (SenseBufferSize) {
- senseData = ExAllocatePoolWithTag(NonPagedPoolNx, SenseBufferSize, CLASSPNP_POOL_TAG_LOG_MESSAGE);
+ senseData = ExAllocatePoolZero(NonPagedPoolNx,
+ SenseBufferSize,
+ CLASSPNP_POOL_TAG_LOG_MESSAGE);
if (senseData) {
senseBufferSize = SenseBufferSize;
}
@@ -6070,7 +6092,11 @@ Arguments:
PIO_RETRIED_LOG_MESSAGE_CONTEXT ioLogMessageContext = NULL;
- ioLogMessageContext = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(IO_RETRIED_LOG_MESSAGE_CONTEXT), CLASSPNP_POOL_TAG_LOG_MESSAGE);
+ ioLogMessageContext =
+ ExAllocatePoolZero(NonPagedPoolNx,
+ sizeof(IO_RETRIED_LOG_MESSAGE_CONTEXT),
+ CLASSPNP_POOL_TAG_LOG_MESSAGE);
+
if (!ioLogMessageContext) {
goto __ClasspQueueLogIOEventWithContextWorker_ExitWithMessage;
}
@@ -7756,7 +7782,9 @@ Return Value:
//
// Allocate the buffer.
//
- buffer = ExAllocatePoolWithTag(NonPagedPoolNx, actualLength, CLASSPNP_POOL_TAG_TOKEN_OPERATION);
+ buffer = ExAllocatePoolZero(NonPagedPoolNx,
+ actualLength,
+ CLASSPNP_POOL_TAG_TOKEN_OPERATION);
if (!buffer) {
TracePrint((TRACE_LEVEL_ERROR,
@@ -7768,8 +7796,6 @@ Return Value:
goto __ClasspBinaryToAscii_Exit;
}
- RtlZeroMemory(buffer, actualLength);
-
for (i = 0, j = 0; i < Length; i++) {
//
@@ -7941,17 +7967,15 @@ Return Value:
PMODE_CONTROL_PAGE pageData = NULL;
ULONG size = 0;
- modeData = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
- MODE_PAGE_DATA_SIZE,
- CLASS_TAG_MODE_DATA);
+ modeData = ExAllocatePoolZero(NonPagedPoolNxCacheAligned,
+ MODE_PAGE_DATA_SIZE,
+ CLASS_TAG_MODE_DATA);
if (modeData == NULL) {
TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_SCSI, "ClasspZeroQERR: Unable to allocate mode data buffer\n"));
goto ClasspZeroQERR_Exit;
}
- RtlZeroMemory(modeData, MODE_PAGE_DATA_SIZE);
-
size = ClassModeSense(DeviceObject,
(PCHAR) modeData,
MODE_PAGE_DATA_SIZE,
@@ -8192,15 +8216,15 @@ ClasspGetHwFirmwareInfo(
//
retry:
- firmwareInfo = ExAllocatePoolWithTag(NonPagedPoolNx, dataLength, CLASSPNP_POOL_TAG_FIRMWARE);
+ firmwareInfo = ExAllocatePoolZero(NonPagedPoolNx,
+ dataLength,
+ CLASSPNP_POOL_TAG_FIRMWARE);
if (firmwareInfo == NULL) {
TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClasspGetHwFirmwareInfo: cannot allocate memory to hold data. \n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
- RtlZeroMemory(firmwareInfo, dataLength);
-
//
// Set up query data, making sure the "Flags" field indicating the request is for device itself.
//
@@ -8705,15 +8729,15 @@ ClassDeviceHwFirmwareDownloadProcess(
lockHeld = FALSE;
#pragma prefast(suppress:6014, "The allocated memory that firmwareImageBuffer points to will be freed in ClassHwFirmwareDownloadComplete().")
- firmwareImageBuffer = ExAllocatePoolWithTag(NonPagedPoolNx, bufferSize, CLASSPNP_POOL_TAG_FIRMWARE);
+ firmwareImageBuffer = ExAllocatePoolZero(NonPagedPoolNx,
+ bufferSize,
+ CLASSPNP_POOL_TAG_FIRMWARE);
if (firmwareImageBuffer == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto Exit_Firmware_Download;
}
- RtlZeroMemory(firmwareImageBuffer, bufferSize);
-
RtlCopyMemory(firmwareImageBuffer, firmwareDownload->ImageBuffer, (ULONG)firmwareDownload->BufferSize);
} else {
diff --git a/storage/class/classpnp/src/xferpkt.c b/storage/class/classpnp/src/xferpkt.c
index 29019140..75300c9a 100644
--- a/storage/class/classpnp/src/xferpkt.c
+++ b/storage/class/classpnp/src/xferpkt.c
@@ -77,9 +77,9 @@ NTSTATUS InitializeTransferPackets(PDEVICE_OBJECT Fdo)
//
arraySize = KeQueryHighestNodeNumber() + 1;
fdoData->FreeTransferPacketsLists =
- ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
- sizeof(PNL_SLIST_HEADER) * arraySize,
- CLASS_TAG_PRIVATE_DATA);
+ ExAllocatePoolZero(NonPagedPoolNxCacheAligned,
+ sizeof(PNL_SLIST_HEADER) * arraySize,
+ CLASS_TAG_PRIVATE_DATA);
if (fdoData->FreeTransferPacketsLists == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
@@ -264,11 +264,12 @@ NTSTATUS InitializeTransferPackets(PDEVICE_OBJECT Fdo)
NT_ASSERT(FALSE);
}
} else {
- fdoData->SrbTemplate = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(SCSI_REQUEST_BLOCK), '-brs');
+ fdoData->SrbTemplate = ExAllocatePoolZero(NonPagedPoolNx,
+ sizeof(SCSI_REQUEST_BLOCK),
+ '-brs');
if (fdoData->SrbTemplate == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
} else {
- RtlZeroMemory(fdoData->SrbTemplate, sizeof(SCSI_REQUEST_BLOCK));
fdoData->SrbTemplate->Length = sizeof(SCSI_REQUEST_BLOCK);
fdoData->SrbTemplate->Function = SRB_FUNCTION_EXECUTE_SCSI;
}
@@ -342,47 +343,51 @@ PTRANSFER_PACKET NewTransferPacket(PDEVICE_OBJECT Fdo)
* Allocate the actual packet.
*/
if (NT_SUCCESS(status)) {
- newPkt = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(TRANSFER_PACKET), 'pnPC');
+ newPkt = ExAllocatePoolZero(NonPagedPoolNx,
+ sizeof(TRANSFER_PACKET),
+ 'pnPC');
if (newPkt == NULL) {
TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_RW, "Failed to allocate transfer packet."));
status = STATUS_INSUFFICIENT_RESOURCES;
} else {
- RtlZeroMemory(newPkt, sizeof(TRANSFER_PACKET));
newPkt->AllocateNode = KeGetCurrentNodeNumber();
if (fdoExt->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
#if (NTDDI_VERSION >= NTDDI_WINBLUE)
if ((fdoExt->MiniportDescriptor != NULL) &&
(fdoExt->MiniportDescriptor->Size >= RTL_SIZEOF_THROUGH_FIELD(STORAGE_MINIPORT_DESCRIPTOR, ExtraIoInfoSupported)) &&
(fdoExt->MiniportDescriptor->ExtraIoInfoSupported == TRUE)) {
- status = CreateStorageRequestBlock((PSTORAGE_REQUEST_BLOCK *)&newPkt->Srb,
- fdoExt->AdapterDescriptor->AddressType,
- DefaultStorageRequestBlockAllocateRoutine,
- NULL,
- 2,
- SrbExDataTypeScsiCdb16,
- SrbExDataTypeIoInfo
- );
+
+ status = CreateStorageRequestBlock(
+ (PSTORAGE_REQUEST_BLOCK *)&newPkt->Srb,
+ fdoExt->AdapterDescriptor->AddressType,
+ DefaultStorageRequestBlockAllocateRoutine,
+ NULL,
+ 2,
+ SrbExDataTypeScsiCdb16,
+ SrbExDataTypeIoInfo);
} else {
- status = CreateStorageRequestBlock((PSTORAGE_REQUEST_BLOCK *)&newPkt->Srb,
- fdoExt->AdapterDescriptor->AddressType,
- DefaultStorageRequestBlockAllocateRoutine,
- NULL,
- 1,
- SrbExDataTypeScsiCdb16
- );
+ status = CreateStorageRequestBlock(
+ (PSTORAGE_REQUEST_BLOCK *)&newPkt->Srb,
+ fdoExt->AdapterDescriptor->AddressType,
+ DefaultStorageRequestBlockAllocateRoutine,
+ NULL,
+ 1,
+ SrbExDataTypeScsiCdb16);
}
#else
- status = CreateStorageRequestBlock((PSTORAGE_REQUEST_BLOCK *)&newPkt->Srb,
- fdoExt->AdapterDescriptor->AddressType,
- DefaultStorageRequestBlockAllocateRoutine,
- NULL,
- 1,
- SrbExDataTypeScsiCdb16
- );
+ status = CreateStorageRequestBlock(
+ (PSTORAGE_REQUEST_BLOCK *)&newPkt->Srb,
+ fdoExt->AdapterDescriptor->AddressType,
+ DefaultStorageRequestBlockAllocateRoutine,
+ NULL,
+ 1,
+ SrbExDataTypeScsiCdb16);
#endif
} else {
#pragma prefast(suppress:6014, "The allocated memory that Pkt->Srb points to will be freed in DestroyTransferPacket().")
- newPkt->Srb = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(SCSI_REQUEST_BLOCK), '-brs');
+ newPkt->Srb = ExAllocatePoolZero(NonPagedPoolNx,
+ sizeof(SCSI_REQUEST_BLOCK),
+ '-brs');
if (newPkt->Srb == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
}
@@ -447,7 +452,9 @@ PTRANSFER_PACKET NewTransferPacket(PDEVICE_OBJECT Fdo)
historyByteCount = sizeof(SRB_HISTORY_ITEM) * fdoData->InterpretSenseInfo->HistoryCount;
historyByteCount += sizeof(SRB_HISTORY) - sizeof(SRB_HISTORY_ITEM);
- newPkt->RetryHistory = (PSRB_HISTORY)ExAllocatePoolWithTag(NonPagedPoolNx, historyByteCount, 'hrPC');
+ newPkt->RetryHistory = (PSRB_HISTORY)ExAllocatePoolZero(NonPagedPoolNx,
+ historyByteCount,
+ 'hrPC');
if (newPkt->RetryHistory == NULL) {
TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_RW, "Failed to allocate MDL for transfer packet."));
diff --git a/storage/class/disk/README.md b/storage/class/disk/README.md
index 98380ef7..d1518c0e 100644
--- a/storage/class/disk/README.md
+++ b/storage/class/disk/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Disk Class Driver
- platform: WDM
- language: cpp
- category: Storage
- description: A class driver for disk devices.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617979
---->
-
# Disk Class Driver
The disk class driver sample is used for managing disk devices
@@ -29,8 +21,11 @@ You build a driver the same way you build any project or solution in Visual Stud
The default Solution build configuration is Debug and Win32.
1. Open the driver project or solution in Visual Studio (find *samplename*.sln or *samplename*.vcxproj).
+
1. Right-click the solution in the **Solutions Explorer** and select **Configuration Manager**.
+
1. From the **Configuration Manager**, select the **Active Solution Configuration** (for example, Debug or Release) and the **Active Solution Platform** (for example, Win32) that correspond to the type of build you are interested in.
+
1. From the Build menu, click **Build Solution** (Ctrl+Shift+B).
## Building a Driver Using the Command Line (MSBuild)
@@ -38,10 +33,13 @@ The default Solution build configuration is Debug and Win32.
You can build a driver from the command line using the Visual Studio Command Prompt window and the Microsoft Build Engine (MSBuild.exe) Previous versions of the WDK used the Windows Build utility (Build.exe) and provided separate build environment windows for each of the supported build configurations. You can now use the Visual Studio Command Prompt window for all build configurations.
1. Open a Visual Studio Command Prompt window at the **Start** screen. From this window you can use MsBuild.exe to build any Visual Studio project by specifying the project (.VcxProj) or solutions (.Sln) file.
-1. Navigate to the project directory and enter the **MSbuild** command for your target. For example, to perform a clean build of a Visual Studio driver project called *filtername*.vcxproj, navigate to the project directory and enter the following MSBuild command: **msbuild /t:clean /t:build .\\***samplename***.vcxproj**.
+
+1. Navigate to the project directory and enter the **MSbuild** command for your target. For example, to perform a clean build of a Visual Studio driver project called *filtername*.vcxproj, navigate to the project directory and enter the following MSBuild command:
+
+ `msbuild /t:clean /t:build .\<samplename>.vcxproj`
## Installation and Operation
The disk class driver is used to interact with disk devices along with the appropriate port driver. The disk class driver is layered above the port driver and manages disk devices regardless of their bus type. This driver attaches to the disk devices that are enumerated by all of the storage port drivers. This driver exposes the required functionality to the file system drivers to access the disk devices.
-For more information, see [Introduction to Storage Class Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff559215) in the storage technologies design guide. \ No newline at end of file
+For more information, see [Introduction to Storage Class Drivers](https://docs.microsoft.com/windows-hardware/drivers/storage/introduction-to-storage-class-drivers) in the storage technologies design guide.
diff --git a/storage/filters/addfilter/README.md b/storage/filters/addfilter/README.md
index af72dddb..149922df 100644
--- a/storage/filters/addfilter/README.md
+++ b/storage/filters/addfilter/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: AddFilter Storage Filter Tool
- platform: Application
- language: cpp
- category: Storage
- description: A command-line application that adds and removes filter drivers for a given drive or volume.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617980
---->
-
# AddFilter Storage Filter Tool
Addfilter is a command-line application that adds and removes filter drivers for a given drive or volume. This application demonstrates how to insert a filter driver into the driver stack of a device. The sample illustrates how to insert such a filter driver by using the SetupDi API.
@@ -26,7 +18,8 @@ This initial sample does not check the filter for validity before it is added to
The minifilter identifies implicit locks when it sees a non-shared write open request on a volume object. In this scenario, the minifilter closes its metadata file and sets a trigger that corresponds to the volume in its instance object. Later, each close operation is examined to identify if the implicit lock on the volume is being released and, if so, a re-open of the minifilter's metadata file is triggered.
-**Important** If you attempt to add a non-existing filter to a boot device and then restart, the system might show the INACCESSIBLE\_BOOT\_DEVICE error message. If this message appears, you will be unable to start the computer. To fix this problem, when the startup menu is displayed when the computer starts up, go to the Advanced Options screen and select **Use Last Known Good Profile**.
+> [!IMPORTANT]
+> If you attempt to add a non-existing filter to a boot device and then restart, the system might show the INACCESSIBLE\_BOOT\_DEVICE error message. If this message appears, you will be unable to start the computer. To fix this problem, when the startup menu is displayed when the computer starts up, go to the Advanced Options screen and select **Use Last Known Good Profile**.
The sample is intended for use with upper filter drivers only.
@@ -36,6 +29,6 @@ Because the sample currently enumerates only disk devices, the sample can operat
The following is the command line usage for addfilter:
- **addfilter [/listdevices] [/device device\_name] [/add filter] [/remove filter]**
+`addfilter [/listdevices] [/device device_name] [/add filter] [/remove filter]`
-If the device name is not supplied, settings will apply to all devices. If there is no /add or /remove argument, a list of currently installed drivers will be printed. \ No newline at end of file
+If the device name is not supplied, settings will apply to all devices. If there is no /add or /remove argument, a list of currently installed drivers will be printed.
diff --git a/storage/iscsi/README.md b/storage/iscsi/README.md
index ff98472f..b219a099 100644
--- a/storage/iscsi/README.md
+++ b/storage/iscsi/README.md
@@ -5,21 +5,13 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: iSCSI WMI Client
- platform: WDM
- language: cpp
- category: Storage
- description: A WMI iSCSI miniport that can be tested using the iSCSICLI.exe tool, the iSCSI Initiator Properties page, the WBEMTEST.exe tool, and customized WMI scripts.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617981
---->
-
# iSCSI WMI Client
WMI Implementation in an iSCSI miniport can be tested using the iSCSICLI.exe tool, the iSCSI Initiator Properties page, the WBEMTEST.exe tool, and customized WMI scripts
## Installation and Operation
-The iSCSI WMI sample uses the iSCSI WMI Class, and MOF definitions described at [iSCSI WMI Classes](http://msdn.microsoft.com/en-us/library/windows/hardware/ff561578) in the storage WMI classes reference. Their corresponding class structure details are described at [iSCSI Structures](http://msdn.microsoft.com/en-us/library/windows/hardware/ff561569). \ No newline at end of file
+The iSCSI WMI sample uses the iSCSI WMI Class, and MOF definitions described at [iSCSI WMI Classes](https://docs.microsoft.com/windows-hardware/drivers/storage/iscsi-wmi-classes) in the storage WMI classes reference. Their corresponding class structure details are described at [iSCSI Structures](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/index).
diff --git a/storage/miniports/lsi_u3/README.md b/storage/miniports/lsi_u3/README.md
index d11cf471..55f16b34 100644
--- a/storage/miniports/lsi_u3/README.md
+++ b/storage/miniports/lsi_u3/README.md
@@ -5,20 +5,14 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: LSI_U3 StorPort Miniport Driver
- platform: WDM
- language: cpp
- category: Storage
- description: An adapter driver for use with Parallel SCSI Host Bus Adapters or on-motherboard solutions that use the LSI 53C1010 SCSI ASIC.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617982
---->
-
# LSI\_U3 StorPort Miniport Driver
-The LSI\_U3 sample is an adapter driver for use with Parallel SCSI Host Bus Adapters or on-motherboard solutions that use the LSI 53C1010 SCSI ASIC.These sources are presented for your education and use with these generally available LSI SCSI-class adapters. The intended use of this sample driver is for this purpose only.
+The LSI\_U3 sample is an adapter driver for use with Parallel SCSI Host Bus Adapters or on-motherboard solutions that use the LSI 53C1010 SCSI ASIC.
+
+These sources are presented for your education and use with these generally available LSI SCSI-class adapters. The intended use of this sample driver is for this purpose only.
## Universal Windows Driver Compliant
@@ -29,6 +23,7 @@ This sample builds a Universal Windows Driver. It uses only APIs and DDIs that a
The operation of this sample requires one of the following hardware items:
- Parallel SCSI Host Bus Adapter
+
- On-motherboard solution that uses the LSI 53C1010 SCSI ASIC
-For more information, see [Storport Miniport Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff567562) in the storage technologies design guide. \ No newline at end of file
+For more information, see [Storport Miniport Drivers](https://docs.microsoft.com/windows-hardware/drivers/storage/storport-miniport-drivers) in the storage technologies design guide.
diff --git a/storage/miniports/storahci/README.md b/storage/miniports/storahci/README.md
index 6f9d8a93..fdfcc176 100644
--- a/storage/miniports/storahci/README.md
+++ b/storage/miniports/storahci/README.md
@@ -5,21 +5,13 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: StorAHCI StorPort Miniport
- platform: WDM
- language: cpp
- category: Storage
- description: A sample Storport ACHI miniport driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617983
---->
-
# StorAhci StorPort Miniport Driver
The StorAhci sample is a Storport ACHI miniport driver.
## Universal Windows Driver Compliant
-This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP. \ No newline at end of file
+This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP.
diff --git a/storage/miniports/storahci/src/ahci.h b/storage/miniports/storahci/src/ahci.h
index 29e29f65..b11c24fe 100644
--- a/storage/miniports/storahci/src/ahci.h
+++ b/storage/miniports/storahci/src/ahci.h
@@ -322,9 +322,9 @@ typedef struct _AHCI_COMMAND_TABLE {
UCHAR CFIS_Padding[44];
UCHAR ACMD[16]; //AHCI1.0 section 4.2.3.2 ATAPI Command (ACMD): This is a software constructed region of 12 or 16 bytes in length that contains the ATAPI command to transmit if the ?A? bit is set in the command header. The ATAPI command must be either 12 or 16 bytes in length. The length transmitted by the HBA is determined by the PIO setup FIS that is sent by the device requesting the ATAPI command.
UCHAR Reserved1[48];
- AHCI_PRDT PRDT[33]; //elements in a sglist are 4K (except for maybe the first and last one). STORAHCI limits transfer size cap to be 128K, therefore no more than 33 PRD entries.
- //if the PRD Table had 32 entries this structure would come out to 640 which has nice 128 byte alignment (required for all instances of these structures),
- UCHAR Reserved2[112];//but since it has 33 entries it comes out to 656. another 112 bytes at the end is needed to restore 128 byte alignment and make the structure 768 bytes
+ AHCI_PRDT PRDT[257]; //elements in a sglist are 4K (except for maybe the first and last one). STORAHCI limits transfer size cap default to be 128K, max to 1M (configure registry MaxTransferSize to 1024), therefore no more than 257 PRD entries.
+ //if the PRD Table had 256 entries this structure would come out to 4224 which has nice 128 byte alignment (required for all instances of these structures),
+ UCHAR Reserved2[112];//but since it has 257 entries it comes out to 4240. another 112 bytes at the end is needed to restore 128 byte alignment and make the structure 4352 bytes
} AHCI_COMMAND_TABLE, *PAHCI_COMMAND_TABLE;
@@ -439,7 +439,7 @@ typedef union _AHCI_INTERRUPT_STATUS {
ULONG UFS :1; //Unknown FIS Interrupt: When set to '1 , indicates that an unknown FIS was received and has been copied into system memory. This bit is cleared to ?0 by software clearing the PxSERR.DIAG.F bit to ?0 . Note that this bit does not directly reflect the PxSERR.DIAG.F bit. PxSERR.DIAG.F is set immediately when an unknown FIS is detected, whereas this bit is set when that FIS is posted to memory. Software should wait to act on an unknown FIS until this bit is set to ?1 or the two bits may become out of sync.
ULONG DPS :1; //Descriptor Processed: A PRD with the 'I' bit set has transferred all of its data. Refer to section 5.3.2.
ULONG PCS :1; //Port Connect Change Status: 1=Change in Current Connect Status. 0=No change in Current Connect Status. This bit reflects the state of PxSERR.DIAG.X. This bit is only cleared when PxSERR.DIAG.X is cleared.
- ULONG DMPS :1; //Device Mechanical Presence Status (DMPS): When set, indicates that a mechanical presence switch attached to this port has been opened or closed, which may lead to a change in the connection state of the device. This bit is only valid if both CAP.SMPS and P0CMD.MPSP are set to �1�.
+ ULONG DMPS :1; //Device Mechanical Presence Status (DMPS): When set, indicates that a mechanical presence switch attached to this port has been opened or closed, which may lead to a change in the connection state of the device. This bit is only valid if both CAP.SMPS and P0CMD.MPSP are set to '1'.
ULONG DW4_Reserved :14;
ULONG PRCS :1; //PhyRdy Change Status: When set to '1 indicates the internal PhyRdy signal changed state. This bit reflects the state of P0SERR.DIAG.N. To clear this bit, software must clear P0SERR.DIAG.N to ?0 .
ULONG IPMS :1; //Incorrect Port Multiplier Status: Indicates that the HBA received a FIS from a device whose Port Multiplier field did not match what was expected. The IPMS bit may be set during enumeration of devices on a Port Multiplier due to the normal Port Multiplier enumeration process. It is recommended that IPMS only be used after enumeration is complete on the Port Multiplier.
@@ -470,7 +470,7 @@ typedef union _AHCI_INTERRUPT_ENABLE {
ULONG UFE :1; // Unknown FIS Interrupt Enable: When set, GHC.IE is set, and P0IS.UFS is set to ?1 , the HBA shall generate an interrupt.
ULONG DPE :1; // Descriptor Processed Interrupt Enable: When set, GHC.IE is set, and P0IS.DPS is set, the HBA shall generate an interrupt.
ULONG PCE :1; // Port Change Interrupt Enable: When set, GHC.IE is set, and P0IS.PCS is set, the HBA shall generate an interrupt.
- ULONG DMPE :1; //Device Mechanical Presence Enable (DMPE): When set, and GHC.IE is set to �1�, and P0IS.DMPS is set, the HBA shall generate an interrupt. For systems that do not support a mechanical presence switch, this bit shall be a read-only �0�.
+ ULONG DMPE :1; //Device Mechanical Presence Enable (DMPE): When set, and GHC.IE is set to '1', and P0IS.DMPS is set, the HBA shall generate an interrupt. For systems that do not support a mechanical presence switch, this bit shall be a read-only '0'.
ULONG DW5_Reserved :14; //
ULONG PRCE :1; // PhyRdy Change Interrupt Enable: When set to ?1 , and GHC.IE is set to ?1 , and P0IS.PRCS is set to ?1 , the HBA shall generate an interrupt.
ULONG IPME :1; // Incorrect Port Multiplier Enable: When set, and GHC.IE and P0IS.IPMS are set, the HBA shall generate an interrupt.
@@ -494,8 +494,8 @@ typedef union _AHCI_COMMAND {
struct {
//LSB
- ULONG ST :1; // Start: When set, the HBA may process the command list. When cleared, the HBA may not process the command list. Whenever this bit is changed from a ?0 to a, the HBA starts processing the command list at entry ?0 . Whenever this bit is changed from a ?1 to a ?0 , the PxCI register is cleared by the HBA upon the HBA putting the controller into an idle state. This bit shall only be set to �1� by software after PxCMD.FRE has been set to �1�. Refer to section 10.3.1 for important restrictions on when ST can be set to ?1 .
- ULONG SUD :1; // Spin-Up Device: This bit is read/write for HBAs that support staggered spin-up via CAP.SSS. This bit is read only ?1 for HBAs that do not support staggered spin-up. On an edge detect from ?0 to ?1 , the HBA shall start a COMRESET initialization sequence to the device. Clearing this bit to �0� does not cause any OOB signal to be sent on the interface. When this bit is cleared to �0� and PxSCTL.DET=0h, the HBA will enter listen mode as detailed in section 10.9.1.
+ ULONG ST :1; // Start: When set, the HBA may process the command list. When cleared, the HBA may not process the command list. Whenever this bit is changed from a ?0 to a, the HBA starts processing the command list at entry ?0 . Whenever this bit is changed from a ?1 to a ?0 , the PxCI register is cleared by the HBA upon the HBA putting the controller into an idle state. This bit shall only be set to '1' by software after PxCMD.FRE has been set to '1'. Refer to section 10.3.1 for important restrictions on when ST can be set to ?1 .
+ ULONG SUD :1; // Spin-Up Device: This bit is read/write for HBAs that support staggered spin-up via CAP.SSS. This bit is read only ?1 for HBAs that do not support staggered spin-up. On an edge detect from ?0 to ?1 , the HBA shall start a COMRESET initialization sequence to the device. Clearing this bit to '0' does not cause any OOB signal to be sent on the interface. When this bit is cleared to '0' and PxSCTL.DET=0h, the HBA will enter listen mode as detailed in section 10.9.1.
ULONG POD :1; // Power On Device: This bit is read/write for HBAs that support cold presence detection on this port as indicated by PxCMD.CPD set to ?1 . This bit is read only ?1 for HBAs that do not support cold presence detect. When set, the HBA sets the state of a pin on the HBA to ?1 so that it may be used to provide power to a cold-presence detectable port.
ULONG CLO :1; // Command List Override: Setting this bit to ?1 causes PxTFD.STS.BSY and PxTFD.STS.DRQ to be cleared to ?0 . This allows a software reset to be transmitted to the device regardless of whether the BSY and DRQ bits are still set in the PxTFD.STS register. The HBA sets this bit to ?0 when PxTFD.STS.BSY and PxTFD.STS.DRQ have been cleared to ?0 . A write to this register with a value of ?0 shall have no effect. This bit shall only be set to ?1 immediately prior to setting the PxCMD.ST bit to ?1 from previous value of ?0 . Setting this bit to ?1 at any other time is not supported and will result in indeterminate behavior.
ULONG FRE :1; // FIS Receive Enable: When set, the HBA may post received FISes into the FIS receive area pointed to by PxFB (and for 64-bit HBAs, PxFBU). When cleared, received FISes are not accepted by the HBA, except for the first D2H register FIS after the initialization sequence, and no FISes are posted to the FIS receive area. System software must not set this bit until PxFB (PxFBU) have been programmed with valid pointer to the FIS receive area, and if software wishes to move the base, this bit must first be cleared, and software must wait for the FR bit in this register to be cleared. Refer to section 10.3.2 for important restrictions on when FRE can be set and cleared.
@@ -508,17 +508,17 @@ typedef union _AHCI_COMMAND {
ULONG CPS :1; // Cold Presence State: The CPS bit reports whether a device is currently detected on this port. If CPS is set to ?1 , then the HBA detects via cold presence that a device is attached to this port. If CPS is cleared to ?0 , then the HBA detects via cold presence that there is no device attached to this port.
ULONG PMA :1; // Port Multiplier Attached: This bit is read/write for HBAs that support a Port Multiplier (CAP.SPM = ?1 ). This bit is read-only for HBAs that do not support a port Multiplier (CAP.SPM = ?0 ). When set to ?1 by software, a Port Multiplier is attached to the HBA for this port. When cleared to ?0 by software, a Port Multiplier is not attached to the HBA for this port. Software is responsible for detecting whether a Port Multiplier is present; hardware does not auto-detect the presence of a Port Multiplier.
- ULONG HPCP :1; // Hot Plug Capable Port: When set to �1�, indicates that this port�s signal and power connectors are externally accessible via a joint signal and power connector for blindmate device hot plug. When cleared to �0�, indicates that this port�s signal and power connectors are not externally accessible via a joint signal and power connector.
+ ULONG HPCP :1; // Hot Plug Capable Port: When set to '1', indicates that this port's signal and power connectors are externally accessible via a joint signal and power connector for blindmate device hot plug. When cleared to '0', indicates that this port's signal and power connectors are not externally accessible via a joint signal and power connector.
ULONG MPSP :1; // Mechanical Presence Switch Attached to Port : If set to ?1 , the platform supports an interlocked switch attached to this port. If cleared to ?0 , the platform does not support an interlocked switch attached to this port. When this bit is set to ?1 , P0CMD.HPCP should also be set to ?1 .
ULONG CPD :1; // Cold Presence Detection: If set to ?1 , the platform supports cold presence detection on this port. If cleared to ?0 , the platform does not support cold presence detection on this port. When this bit is set to ?1 , P0CMD.HPCP should also be set to ?1 .
- ULONG ESP :1; //AHCI 1.1 External SATA Port: When set to '1', indicates that this port�s signal connector is externally accessible on a signal only connector. When set to '1', CAP.SXS shall be set to '1'. When cleared to �0�, indicates that this port�s signal connector is not externally accessible on a signal only connector. ESP is mutually exclusive with the HPCP bit in this register.
- ULONG FBSCP :1; // FIS-based Switching Capable Port (FBSCP): When set to �1�, indicates that this port supports Port Multiplier FIS-based switching. When cleared to �0�, indicates that this port does not support FIS-based switching. This bit may only be set to �1� if both CAP.SPM and CAP.FBSS are set to �1�.
- ULONG APSTE :1; // Automatic Partial to Slumber Transitions Enabled (APSTE): When set to �1�, the HBA may perform Automatic Partial to Slumber Transitions. When cleared to �0� the port shall not perform Automatic Partial to Slumber Transitions. Software shall only set this bit to �1� if CAP2.APST is set to �1�; if CAP2.APST is cleared to �0� software shall treat this bit as reserved.
+ ULONG ESP :1; //AHCI 1.1 External SATA Port: When set to '1', indicates that this port's signal connector is externally accessible on a signal only connector. When set to '1', CAP.SXS shall be set to '1'. When cleared to '0', indicates that this port's signal connector is not externally accessible on a signal only connector. ESP is mutually exclusive with the HPCP bit in this register.
+ ULONG FBSCP :1; // FIS-based Switching Capable Port (FBSCP): When set to '1', indicates that this port supports Port Multiplier FIS-based switching. When cleared to '0', indicates that this port does not support FIS-based switching. This bit may only be set to '1' if both CAP.SPM and CAP.FBSS are set to '1'.
+ ULONG APSTE :1; // Automatic Partial to Slumber Transitions Enabled (APSTE): When set to '1', the HBA may perform Automatic Partial to Slumber Transitions. When cleared to '0' the port shall not perform Automatic Partial to Slumber Transitions. Software shall only set this bit to '1' if CAP2.APST is set to '1'; if CAP2.APST is cleared to '0' software shall treat this bit as reserved.
ULONG ATAPI :1; // Device is ATAPI: When set, the connected device is an ATAPI device. This bit is used by the HBA to control whether or not to generate the desktop LED when commands are active. See section 10.10 for details on the activity LED.
ULONG DLAE :1; // Drive LED on ATAPI Enable: When set, the HBA shall drive the LED pin active for commands regardless of the state of P0CMD.ATAPI. When cleared, the HBA shall only drive the LED pin active for commands if P0CMD.ATAPI set to ?0 . See section 10.10 for details on the activity LED.
- ULONG ALPE :1; // Aggressive Link Power Management Enable: When set to '1', the HBA shall aggressively enter a lower link power state (Partial or Slumber) based upon the setting of the ASP bit. Software shall only set this bit to �1� if CAP.SALP is set to �1�; if CAP.SALP is cleared to �0� software shall treat this bit as reserved. See section 8.3.1.3 for details.
- ULONG ASP :1; // Aggressive Slumber / Partial: When set to '1', and ALPE is set, the HBA shall aggressively enter the Slumber state when it clears the PxCI register and the PxSACT register is cleared or when it clears the PxSACT register and PxCI is cleared. When cleared, and ALPE is set, the HBA shall aggressively enter the Partial state when it clears the PxCI register and the PxSACT register is cleared or when it clears the PxSACT register and PxCI is cleared. If CAP.SALP is cleared to �0� software shall treat this bit as reserved. See section 8.3.1.3 for details.
+ ULONG ALPE :1; // Aggressive Link Power Management Enable: When set to '1', the HBA shall aggressively enter a lower link power state (Partial or Slumber) based upon the setting of the ASP bit. Software shall only set this bit to '1' if CAP.SALP is set to '1'; if CAP.SALP is cleared to '0' software shall treat this bit as reserved. See section 8.3.1.3 for details.
+ ULONG ASP :1; // Aggressive Slumber / Partial: When set to '1', and ALPE is set, the HBA shall aggressively enter the Slumber state when it clears the PxCI register and the PxSACT register is cleared or when it clears the PxSACT register and PxCI is cleared. When cleared, and ALPE is set, the HBA shall aggressively enter the Partial state when it clears the PxCI register and the PxSACT register is cleared or when it clears the PxSACT register and PxCI is cleared. If CAP.SALP is cleared to '0' software shall treat this bit as reserved. See section 8.3.1.3 for details.
ULONG ICC :4; // Interface Communication Control: This field is used to control power management states of the interface. If the Link layer is currently in the L_IDLE state, writes to this field shall cause the HBA to initiate a transition to the interface power management state requested. If the Link layer is not currently in the L_IDLE state, writes to this field shall have no effect.
//MSB
};
@@ -532,12 +532,12 @@ typedef union _AHCI_DEVICE_SLEEP {
struct {
//LSB
- ULONG ADSE :1; // Aggressive Device Sleep Enable (ADSE): When this bit is set to �1�, the HBA shall assert the DEVSLP signal after the port has been idle (PxCI = 0h and PxSACT = 0h) for the amount of time specified by the PxDEVSLP.DITO register. When this bit is set to �1� and CAP2.DESO is set to �1�, the HBA shall assert the DEVSLP signal after the port has been idle (PxCI = 0h and PxSACT = 0h) for the amount of time specified by PxDEVSLP.DITO and the interface is in Slumber (PxSSTS.IPM = 6h).When this bit is cleared to �0�, the HBA does not enter DevSleep unless software directed via PxCMD.ICC. This bit shall only be set to �1� if PxDEVSLP.DSP is set to �1�.
- ULONG DSP :1; // Device Sleep Present (DSP): If set to �1�, the platform supports Device Sleep on this port. If cleared to �0�, the platform does not support Device Sleep on this port. This bit may only be set to �1� if CAP2.SDS is set to �1�. DSP is mutually exclusive with the PxCMD.HPCP bit and PxCMD.ESP bit.
+ ULONG ADSE :1; // Aggressive Device Sleep Enable (ADSE): When this bit is set to '1', the HBA shall assert the DEVSLP signal after the port has been idle (PxCI = 0h and PxSACT = 0h) for the amount of time specified by the PxDEVSLP.DITO register. When this bit is set to '1' and CAP2.DESO is set to '1', the HBA shall assert the DEVSLP signal after the port has been idle (PxCI = 0h and PxSACT = 0h) for the amount of time specified by PxDEVSLP.DITO and the interface is in Slumber (PxSSTS.IPM = 6h).When this bit is cleared to '0', the HBA does not enter DevSleep unless software directed via PxCMD.ICC. This bit shall only be set to '1' if PxDEVSLP.DSP is set to '1'.
+ ULONG DSP :1; // Device Sleep Present (DSP): If set to '1', the platform supports Device Sleep on this port. If cleared to '0', the platform does not support Device Sleep on this port. This bit may only be set to '1' if CAP2.SDS is set to '1'. DSP is mutually exclusive with the PxCMD.HPCP bit and PxCMD.ESP bit.
ULONG DETO :8; // Device Sleep Exit Timeout (DETO): This field specifies the maximum duration (in approximate 1ms granularity) from DEVSLP de-assertion until the device is ready to accept OOB. The nominal value is 20ms while the max value is 255ms depending on device identification information.
ULONG MDAT :5; // Minimum Device Sleep Assertion Time (MDAT): This field specifies the minimum amount of time (in 1ms granularity) that the HBA must assert the DEVSLP signal before it may be de-asserted. The nominal value is 10ms and the minimum is 1ms depending on device identification information.
- ULONG DITO :10; // Device Sleep Idle Timeout (DITO): This field specifies the amount of the time (in approximate 1ms granularity) that the HBA shall wait before driving the DEVSLP signal. Refer to section 8.5.1.1.1 for details. Hardware reloads its port specific Device Sleep timer with this value each time the port transitions out of the DEVSLP state. For example: from DevSleep to active or PxDEVSLP.ADSE transitions from �0� to a �1�.
- ULONG DM :4; // DITO Multiplier (DM): 0�s based value that specifies the DITO multiplier that the HBA applies to the specified DITO value, effectively extending the range of DITO from 1ms to 16368ms. A value of 0h indicates a multiplier of 1. A maximum multiplier of 16 may be applied. The HBA computes the total idle timeout as a product of DM and DITO (i.e. DITOactual = DITO * (DM+1)).
+ ULONG DITO :10; // Device Sleep Idle Timeout (DITO): This field specifies the amount of the time (in approximate 1ms granularity) that the HBA shall wait before driving the DEVSLP signal. Refer to section 8.5.1.1.1 for details. Hardware reloads its port specific Device Sleep timer with this value each time the port transitions out of the DEVSLP state. For example: from DevSleep to active or PxDEVSLP.ADSE transitions from '0' to a '1'.
+ ULONG DM :4; // DITO Multiplier (DM): 0's based value that specifies the DITO multiplier that the HBA applies to the specified DITO value, effectively extending the range of DITO from 1ms to 16368ms. A value of 0h indicates a multiplier of 1. A maximum multiplier of 16 may be applied. The HBA computes the total idle timeout as a product of DM and DITO (i.e. DITOactual = DITO * (DM+1)).
ULONG Reserved :3;
//MSB
@@ -733,10 +733,10 @@ typedef struct _AHCI_PORT {
AHCI_SERIAL_ATA_ERROR SERR;
//Serial ATA Active as defined in AHCI1.0 section 3.3.13
- ULONG SACT; //Device Status: Device Status (DS): This field is bit significant. Each bit corresponds to the TAG and command slot of a native queued command, where bit 0 corresponds to TAG 0 and command slot 0. This field is set by software prior to issuing a native queued command for a particular command slot. Prior to writing PxCI[TAG] to �1�, software will set DS[TAG] to �1� to indicate that a command with that TAG is outstanding. The device clears bits in this field by sending a Set Device Bits FIS to the host. The HBA clears bits in this field that are set to �1� in the SActive field of the Set Device Bits FIS. The HBA only clears bits that correspond to native queued commands that have completed successfully. Software should only write this field when PxCMD.ST is set to �1�. This field is cleared when PxCMD.ST is written from a �1� to a �0� by software. This field is not cleared by a COMRESET or a software reset.
+ ULONG SACT; //Device Status: Device Status (DS): This field is bit significant. Each bit corresponds to the TAG and command slot of a native queued command, where bit 0 corresponds to TAG 0 and command slot 0. This field is set by software prior to issuing a native queued command for a particular command slot. Prior to writing PxCI[TAG] to '1', software will set DS[TAG] to '1' to indicate that a command with that TAG is outstanding. The device clears bits in this field by sending a Set Device Bits FIS to the host. The HBA clears bits in this field that are set to '1' in the SActive field of the Set Device Bits FIS. The HBA only clears bits that correspond to native queued commands that have completed successfully. Software should only write this field when PxCMD.ST is set to '1'. This field is cleared when PxCMD.ST is written from a '1' to a '0' by software. This field is not cleared by a COMRESET or a software reset.
//Command Issue as defined in AHCI1.0 section 3.3.14
- ULONG CI; //Commands Issued: This field is bit significant. Each bit corresponds to a command slot, where bit 0 corresponds to command slot 0. This field is set by software to indicate to the HBA that a command has been built in system memory for a command slot and may be sent to the device. When the HBA receives a FIS which clears the BSY, DRQ, and ERR bits for the command, it clears the corresponding bit in this register for that command slot. Bits in this field shall only be set to �1� by software when PxCMD.ST is set to �1�. This field is also cleared when PxCMD.ST is written from a �1� to a �0� by software.
+ ULONG CI; //Commands Issued: This field is bit significant. Each bit corresponds to a command slot, where bit 0 corresponds to command slot 0. This field is set by software to indicate to the HBA that a command has been built in system memory for a command slot and may be sent to the device. When the HBA receives a FIS which clears the BSY, DRQ, and ERR bits for the command, it clears the corresponding bit in this register for that command slot. Bits in this field shall only be set to '1' by software when PxCMD.ST is set to '1'. This field is also cleared when PxCMD.ST is written from a '1' to a '0' by software.
AHCI_SNOTIFICATION SNTF;
@@ -757,24 +757,24 @@ typedef union _AHCI_HBA_CAPABILITIES {
struct {
//LSB
ULONG NP :5; //Number of Ports: 0 s based value indicating the maximum number of ports supported by the HBA silicon. A maximum of 32 ports can be supported. A value of ?0h?, indicating one port, is the minimum requirement. Note that the number of ports indicated in this field may be more than the number of ports indicated in the GHC.PI register.
- ULONG SXS :1; //AHCI 1.1 Supports External SATA: When set to �1�, indicates that the HBA has one or more Serial ATA ports that has a signal only connector that is externally accessible. If this bit is set, software may refer to the PxCMD.ESP bit to determine whether a specific port has its signal connector externally accessible as a signal only connector (i.e. power is not part of that connector). When the bit is cleared to �0�, indicates that the HBA has no Serial ATA ports that have a signal only connector externally accessible.
- ULONG EMS :1; //AHCI 1.1 Enclosure Management Supported: When set to �1�, indicates that the HBA supports enclosure management as defined in section 12. When enclosure management is supported, the HBA has implemented the EM_LOC and EM_CTL global HBA registers. When cleared to �0�, indicates that the HBA does not support enclosure management and the EM_LOC and EM_CTL global HBA registers are not implemented.
- ULONG CCCS :1; //AHCI 1.1 Command Completion Coalescing Supported: When set to �1�, indicates that the HBA supports command completion coalescing as defined in section 11. When command completion coalescing is supported, the HBA has implemented the CCC_CTL and the CCC_PORTS global HBA registers. When cleared to �0�, indicates that the HBA does not support command completion coalescing and the CCC_CTL and CCC_PORTS global HBA registers are not implemented.
+ ULONG SXS :1; //AHCI 1.1 Supports External SATA: When set to '1', indicates that the HBA has one or more Serial ATA ports that has a signal only connector that is externally accessible. If this bit is set, software may refer to the PxCMD.ESP bit to determine whether a specific port has its signal connector externally accessible as a signal only connector (i.e. power is not part of that connector). When the bit is cleared to '0', indicates that the HBA has no Serial ATA ports that have a signal only connector externally accessible.
+ ULONG EMS :1; //AHCI 1.1 Enclosure Management Supported: When set to '1', indicates that the HBA supports enclosure management as defined in section 12. When enclosure management is supported, the HBA has implemented the EM_LOC and EM_CTL global HBA registers. When cleared to '0', indicates that the HBA does not support enclosure management and the EM_LOC and EM_CTL global HBA registers are not implemented.
+ ULONG CCCS :1; //AHCI 1.1 Command Completion Coalescing Supported: When set to '1', indicates that the HBA supports command completion coalescing as defined in section 11. When command completion coalescing is supported, the HBA has implemented the CCC_CTL and the CCC_PORTS global HBA registers. When cleared to '0', indicates that the HBA does not support command completion coalescing and the CCC_CTL and CCC_PORTS global HBA registers are not implemented.
ULONG NCS :5; //Number of Command Slots: 0 s based value indicating the number of command slots supported by this HBA. A minimum of 1 and maximum of 32 slots can be supported.
ULONG PSC :1; //Partial State Capable: Indicates whether the HBA can support transitions to the Partial state. When cleared to ?0 , software must not allow the HBA to initiate transitions to the Partial state via aggressive link power management nor the PxCMD.ICC field in each port, and the PxSCTL.IPM field in each port must be programmed to disallow device initiated Partial requests. When set to ?1 , HBA and device initiated Partial requests can be supported.
ULONG SSC :1; //Slumber State Capable: Indicates whether the HBA can support transitions to the Slumber state. When cleared to ?0 , software must not allow the HBA to initiate transitions to the Slumber state via aggressive link power management nor the PxCMD.ICC field in each port, and the PxSCTL.IPM field in each port must be programmed to disallow device initiated Slumber requests. When set to ?1 , HBA and device initiated Slumber requests can be supported.
- ULONG PMD :1; //PIO Multiple DRQ Block: If set to �1 , the HBA supports multiple DRQ block data transfers for the PIO command protocol. If cleared to ?0 the HBA only supports single DRQ block data transfers for the PIO command protocol.
- ULONG FBSS :1; //AHCI 1.1 FIS-based Switching Supported: When set to �1�, indicates that the HBA supports Port Multiplier FIS-based switching. When cleared to �0�, indicates that the HBA does not support FIS-based switching. AHCI 1.0 and 1.1 HBAs shall have this bit cleared to �0�.
+ ULONG PMD :1; //PIO Multiple DRQ Block: If set to '1 , the HBA supports multiple DRQ block data transfers for the PIO command protocol. If cleared to ?0 the HBA only supports single DRQ block data transfers for the PIO command protocol.
+ ULONG FBSS :1; //AHCI 1.1 FIS-based Switching Supported: When set to '1', indicates that the HBA supports Port Multiplier FIS-based switching. When cleared to '0', indicates that the HBA does not support FIS-based switching. AHCI 1.0 and 1.1 HBAs shall have this bit cleared to '0'.
ULONG SPM :1; //Supports Port Multiplier: Indicates whether the HBA can support a Port Multiplier. When set, a Port Multiplier using command-based switching is supported. When cleared to ?0 , a Port Multiplier is not supported, and a Port Multiplier may not be attached to this HBA.
ULONG SAM :1; //Supports AHCI mode only: The SATA controller may optionally support AHCI access mechanisms only. A value of '0' indicates that in addition to the native AHCI mechanism (via ABAR), the SATA controller implements a legacy, task-file based register interface such as SFF-8038i. A value of '1' indicates that the SATA controller does not implement a legacy, task-file based register interface.
- ULONG SNZO :1; //Supports Non-Zero DMA Offsets: When set to �1 , indicates that the HBA can support non-zero DMA offsets for DMA Setup FISes. This bit is reserved for future AHCI enhancements. AHCI 1.0 HBAs must have this bit cleared to ?0 .
+ ULONG SNZO :1; //Supports Non-Zero DMA Offsets: When set to '1 , indicates that the HBA can support non-zero DMA offsets for DMA Setup FISes. This bit is reserved for future AHCI enhancements. AHCI 1.0 HBAs must have this bit cleared to ?0 .
ULONG ISS :4; //Interface Speed Support: Indicates the maximum speed the HBA can support on its ports. These encodings match the PxSCTL.DET.SPD field, which is programmable by system software. Values are:
- ULONG SCLO :1; //Supports Command List Override: When set to �1 , indicates that the HBA supports the PxCMD.CLO bit and its associated function. When cleared to ?0 , the HBA is not capable of clearing the BSY and DRQ bits in the Status register in order to issue a software reset if these bits are still set from a previous operation.
- ULONG SAL :1; //Supports Activity LED: When set to �1 , indicates that the HBA supports a single output pin which indicates activity. This pin can be connected to an LED on the platform to indicate device activity on any drive. See section 10.10 for more information.
+ ULONG SCLO :1; //Supports Command List Override: When set to '1 , indicates that the HBA supports the PxCMD.CLO bit and its associated function. When cleared to ?0 , the HBA is not capable of clearing the BSY and DRQ bits in the Status register in order to issue a software reset if these bits are still set from a previous operation.
+ ULONG SAL :1; //Supports Activity LED: When set to '1 , indicates that the HBA supports a single output pin which indicates activity. This pin can be connected to an LED on the platform to indicate device activity on any drive. See section 10.10 for more information.
ULONG SALP :1; //Supports Aggressive Link Power Management: When set to ?1 , indicates that the HBA can support auto-generating link requests to the Partial or Slumber states when there are no commands to process. Refer to section 8.3.1.3.
- ULONG SSS :1; //Supports Staggered Spin-up: When set to �1 , indicates that the HBA supports staggered spin-up on its ports, for use in balancing power spikes. This value is loaded by the BIOS prior to OS initialization.
- ULONG SMPS :1; //Supports Mechanical Presence Switch: ): When set to �1�, the HBA supports mechanical presence switches on its ports for use in hot plug operations. When cleared to �0�, this function is not supported. This value is loaded by the BIOS prior to OS initialization.
- ULONG SSNTF :1; //AHCI 1.1 Supports SNotification Register: When set to �1�, indicates that the HBA supports the PxSNTF (SNotification) register and its associated functionality. When cleared to �0�, the HBA does not support the PxSNTF (SNotification) register and its associated functionality. Refer to section 10.10.1.
+ ULONG SSS :1; //Supports Staggered Spin-up: When set to '1 , indicates that the HBA supports staggered spin-up on its ports, for use in balancing power spikes. This value is loaded by the BIOS prior to OS initialization.
+ ULONG SMPS :1; //Supports Mechanical Presence Switch: ): When set to '1', the HBA supports mechanical presence switches on its ports for use in hot plug operations. When cleared to '0', this function is not supported. This value is loaded by the BIOS prior to OS initialization.
+ ULONG SSNTF :1; //AHCI 1.1 Supports SNotification Register: When set to '1', indicates that the HBA supports the PxSNTF (SNotification) register and its associated functionality. When cleared to '0', the HBA does not support the PxSNTF (SNotification) register and its associated functionality. Refer to section 10.10.1.
ULONG SNCQ :1; //Supports Native Command Queuing: Indicates whether the HBA supports Serial ATA native command queuing. If set to ?1 , an HBA shall handle DMA Setup FISes natively, and shall handle the auto-activate optimization through that FIS. If cleared to ?0 , native command queuing is not supported and software should not issue any native command queuing commands.
ULONG S64A :1; //Supports 64-bit Addressing: Indicates whether the HBA can access 64-bit data structures. If true, the HBA shall make the 32-bit upper bits of the port DMA Descriptor, the PRD Base, and each PRD entry read/write. If cleared, these are read- only and treated as ?0 by the HBA.
//MSB
@@ -791,7 +791,7 @@ typedef union _AHCI_Global_HBA_CONTROL {
//LSB
ULONG HR :1; //HBA Reset: When set by SW, this bit causes an internal reset of the HBA. All state machines that relate to data transfers and queuing shall return to an idle condition, and all ports shall be re-initialized via COMRESET (if staggered spin-up is not supported). If staggered spin-up is supported, then it is the responsibility of software to spin-up each port after the reset has completed. When the HBA has performed the reset action, it shall reset this bit to ?0 . A software write of ?0 shall have no effect. For a description on which bits are reset when this bit is set, see section 10.4.3.
ULONG IE :1; //Interrupt Enable: This global bit enables interrupts from the HBA. When cleared (reset default), all interrupt sources from all ports are disabled. When set, interrupts are enabled.
- ULONG MRSM :1; //MSI Revert to Single Message: When set to �1� by hardware, indicates that the HBA requested more than one MSI vector but has reverted to using the first vector only. When this bit is cleared to �0�, the HBA has not reverted to single MSI mode (i.e. hardware is already in single MSI mode, software has allocated the number of messages requested, or hardware is sharing interrupt vectors if MC.MME < MC.MMC).
+ ULONG MRSM :1; //MSI Revert to Single Message: When set to '1' by hardware, indicates that the HBA requested more than one MSI vector but has reverted to using the first vector only. When this bit is cleared to '0', the HBA has not reverted to single MSI mode (i.e. hardware is already in single MSI mode, software has allocated the number of messages requested, or hardware is sharing interrupt vectors if MC.MME < MC.MMC).
ULONG Reserved :28; //3-30
ULONG AE :1; //AHCI Enable: When set, indicates that communication to the HBA shall be via AHCI mechanisms. This can be used by an HBA that supports both legacy mechanisms (such as SFF-8038i) and AHCI to know when the HBA is running under an AHCI driver. When set, software shall only communicate with the HBA using AHCI. When cleared, software shall only communicate with the HBA using legacy mechanisms. When cleared FISes are not posted to memory and no commands are sent via AHCI mechanisms. Software shall set this bit to ?1 before accessing other AHCI registers. The implementation of this bit is dependent upon the value of the CAP.SAM bit. If CAP.SAM is '0', then GHC.AE shall be read-write and shall have a reset value of '0'. If CAP.SAM is '1', then AE shall be read-only and shall have a reset value of '1'.
//MSB
@@ -820,11 +820,11 @@ typedef union _AHCI_COMMAND_COMPLETION_COALESCING_CONTROL {
struct {
//LSB
- ULONG EN: 1; //Enable: When cleared to �0�, the command completion coalescing feature is disabled and no CCC interrupts are generated. When set to �1�, the command completion coalescing feature is enabled and CCC interrupts may be generated based on timeout or command completion conditions. Software shall only change the contents of the TV and CC fields when EN is cleared to �0�. On transition of this bit from �0� to �1�, any updated values for the TV and CC fields shall take effect.
+ ULONG EN: 1; //Enable: When cleared to '0', the command completion coalescing feature is disabled and no CCC interrupts are generated. When set to '1', the command completion coalescing feature is enabled and CCC interrupts may be generated based on timeout or command completion conditions. Software shall only change the contents of the TV and CC fields when EN is cleared to '0'. On transition of this bit from '0' to '1', any updated values for the TV and CC fields shall take effect.
ULONG Reserved: 2;
- ULONG INT: 5; //Interrupt: Specifies the interrupt used by the CCC feature. This interrupt must be marked as unused in the Ports Implemented (PI) register by the corresponding bit being set to �0�. Thus, the CCC interrupt corresponds to the interrupt for an unimplemented port on the controller. When a CCC interrupt occurs, the IS.IPS[INT] bit shall be asserted to �1�. This field also specifies the interrupt vector used for MSI.
- ULONG CC: 8; //Command Completions: Specifies the number of command completions that are necessary to cause a CCC interrupt. The HBA has an internal command completion counter, hCccComplete. hCccComplete is incremented by one each time a selected port has a command completion. When hCccComplete is equal to the command completions value, a CCC interrupt is signaled. The internal command completion counter is reset to �0� on the assertion of each CCC interrupt. A value of �0� for this field shall disable CCC interrupts being generated based on the number of commands completed, i.e. CCC interrupts are only generated based on the timer in this case.
- ULONG TV: 16; //Timeout Value: The timeout value is specified in 1 millisecond intervals. The timer accuracy shall be within 5%. hCccTimer is loaded with this timeout value. hCccTimer is only decremented when commands are outstanding on selected ports, as defined in section 11.2. The HBA will signal a CCC interrupt when hCccTimer has decremented to �0�. hCccTimer is reset to the timeout value on the assertion of each CCC interrupt. A timeout value of �0� is reserved.
+ ULONG INT: 5; //Interrupt: Specifies the interrupt used by the CCC feature. This interrupt must be marked as unused in the Ports Implemented (PI) register by the corresponding bit being set to '0'. Thus, the CCC interrupt corresponds to the interrupt for an unimplemented port on the controller. When a CCC interrupt occurs, the IS.IPS[INT] bit shall be asserted to '1'. This field also specifies the interrupt vector used for MSI.
+ ULONG CC: 8; //Command Completions: Specifies the number of command completions that are necessary to cause a CCC interrupt. The HBA has an internal command completion counter, hCccComplete. hCccComplete is incremented by one each time a selected port has a command completion. When hCccComplete is equal to the command completions value, a CCC interrupt is signaled. The internal command completion counter is reset to '0' on the assertion of each CCC interrupt. A value of '0' for this field shall disable CCC interrupts being generated based on the number of commands completed, i.e. CCC interrupts are only generated based on the timer in this case.
+ ULONG TV: 16; //Timeout Value: The timeout value is specified in 1 millisecond intervals. The timer accuracy shall be within 5%. hCccTimer is loaded with this timeout value. hCccTimer is only decremented when commands are outstanding on selected ports, as defined in section 11.2. The HBA will signal a CCC interrupt when hCccTimer has decremented to '0'. hCccTimer is reset to the timeout value on the assertion of each CCC interrupt. A timeout value of '0' is reserved.
//MSB
};
@@ -837,7 +837,7 @@ typedef union _AHCI_ENCLOSURE_MANAGEMENT_LOCATION {
struct {
//LSB
- ULONG SZ :16; //Buffer Size: Specifies the size of the transmit message buffer area in Dwords. If both transmit and receive buffers are supported, then the transmit buffer begins at ABAR[EM_LOC.OFST*4] and the receive buffer directly follows it. If both transmit and receive buffers are supported, both buffers are of the size indicated in the Buffer Size field. A value of �0� is invalid.
+ ULONG SZ :16; //Buffer Size: Specifies the size of the transmit message buffer area in Dwords. If both transmit and receive buffers are supported, then the transmit buffer begins at ABAR[EM_LOC.OFST*4] and the receive buffer directly follows it. If both transmit and receive buffers are supported, both buffers are of the size indicated in the Buffer Size field. A value of '0' is invalid.
ULONG OFST :16; //Offset: The offset of the message buffer in Dwords from the beginning of the ABAR.
//MSB
};
@@ -851,20 +851,20 @@ typedef union _AHCI_ENCLOSURE_MANAGEMENT_CONTROL {
struct {
//LSB
- ULONG STS_MR :1; //Message Received: The HBA sets this bit to a �1� when a message is completely received into the message buffer. When software detects this bit is a �1�, software should read the message and perform any actions necessary. When software is finished reading the message in the buffer, software writes a �1� to this bit in order to clear it. A write of �0� to this bit by software shall have no effect.
+ ULONG STS_MR :1; //Message Received: The HBA sets this bit to a '1' when a message is completely received into the message buffer. When software detects this bit is a '1', software should read the message and perform any actions necessary. When software is finished reading the message in the buffer, software writes a '1' to this bit in order to clear it. A write of '0' to this bit by software shall have no effect.
ULONG Reserved0 :7;
- ULONG CTL_TM :1; //Transmit Message: When set to �1� by software, the HBA shall transmit the message contained in the message buffer. When the message is completely sent, the HBA shall clear this bit to �0�. A write of �0� to this bit by software shall have no effect. Software shall not change the contents of the message buffer while CTL.TM is set to �1�.
- ULONG CTL_RST :1; //Reset: When set to �1� by software, the HBA shall reset all enclosure management message logic and the attached enclosure processor (if applicable) and take all appropriate reset actions to ensure messages can be transmitted/received after the reset. After the HBA completes the reset operation, the HBA shall set the value to �0�. A write of �0� by software to this field shall have no effect.
+ ULONG CTL_TM :1; //Transmit Message: When set to '1' by software, the HBA shall transmit the message contained in the message buffer. When the message is completely sent, the HBA shall clear this bit to '0'. A write of '0' to this bit by software shall have no effect. Software shall not change the contents of the message buffer while CTL.TM is set to '1'.
+ ULONG CTL_RST :1; //Reset: When set to '1' by software, the HBA shall reset all enclosure management message logic and the attached enclosure processor (if applicable) and take all appropriate reset actions to ensure messages can be transmitted/received after the reset. After the HBA completes the reset operation, the HBA shall set the value to '0'. A write of '0' by software to this field shall have no effect.
ULONG Reserved1 :6;
- ULONG SUPP_LED :1; //LED Message Types: If set to �1�, the HBA supports the LED message type defined in section 12.2.1.
- ULONG SUPP_SAFTE :1; //SAF-TE Enclosure Management Messages: If set to �1�, the HBA supports the SAF-TE message type.
- ULONG SUPP_SES2 :1; //SES-2 Enclosure Management Messages: If set to �1�, the HBA supports the SES-2 message type.
- ULONG SUPP_SGPIO :1; //SGPIO Enclosure Management Messages: If set to �1�, the HBA supports the SGPIO register interface message type.
+ ULONG SUPP_LED :1; //LED Message Types: If set to '1', the HBA supports the LED message type defined in section 12.2.1.
+ ULONG SUPP_SAFTE :1; //SAF-TE Enclosure Management Messages: If set to '1', the HBA supports the SAF-TE message type.
+ ULONG SUPP_SES2 :1; //SES-2 Enclosure Management Messages: If set to '1', the HBA supports the SES-2 message type.
+ ULONG SUPP_SGPIO :1; //SGPIO Enclosure Management Messages: If set to '1', the HBA supports the SGPIO register interface message type.
ULONG Reserved2 :4;
- ULONG ATTR_SMB :1; //Single Message Buffer: If set to �1�, the HBA has one message buffer that is shared for messages to transmit and messages received. In this case, unsolicited receive messages are not supported and it is software�s responsibility to manage access to this buffer. If cleared to �0�, there are separate receive and transmit buffers such that unsolicited messages could be supported.
- ULONG ATTR_XMT :1; //Transmit Only: If set to �1�, the HBA only supports transmitting messages and does not support receiving messages. If cleared to �0�, the HBA supports transmitting and receiving messages.
- ULONG ATTR_ALHD :1; //Activity LED Hardware Driven: If set to �1�, the HBA drives the activity LED for the LED message type in hardware and does not utilize software settings for this LED. The HBA does not begin transmitting the hardware based activity signal until after software has written CTL.TM=1 after a reset condition.
- ULONG ATTR_PM :1; //Port Multiplier Support: If set to �1�, the HBA supports enclosure management messages for devices attached via a Port Multiplier. If cleared to �0�, the HBA does not support enclosure management messages for devices attached via a Port Multiplier. When cleared to �0�, software should use the Serial ATA enclosure management bridge that is built into many Port Multipliers for enclosure services with these devices. For more information on Serial ATA enclosure management bridges, refer to the Serial ATA Revision 2.5 specification.
+ ULONG ATTR_SMB :1; //Single Message Buffer: If set to '1', the HBA has one message buffer that is shared for messages to transmit and messages received. In this case, unsolicited receive messages are not supported and it is software's responsibility to manage access to this buffer. If cleared to '0', there are separate receive and transmit buffers such that unsolicited messages could be supported.
+ ULONG ATTR_XMT :1; //Transmit Only: If set to '1', the HBA only supports transmitting messages and does not support receiving messages. If cleared to '0', the HBA supports transmitting and receiving messages.
+ ULONG ATTR_ALHD :1; //Activity LED Hardware Driven: If set to '1', the HBA drives the activity LED for the LED message type in hardware and does not utilize software settings for this LED. The HBA does not begin transmitting the hardware based activity signal until after software has written CTL.TM=1 after a reset condition.
+ ULONG ATTR_PM :1; //Port Multiplier Support: If set to '1', the HBA supports enclosure management messages for devices attached via a Port Multiplier. If cleared to '0', the HBA does not support enclosure management messages for devices attached via a Port Multiplier. When cleared to '0', software should use the Serial ATA enclosure management bridge that is built into many Port Multipliers for enclosure services with these devices. For more information on Serial ATA enclosure management bridges, refer to the Serial ATA Revision 2.5 specification.
ULONG Reserved3 :4;
//MSB
};
@@ -878,12 +878,12 @@ typedef union _AHCI_HBA_CAPABILITIES2 {
struct {
//LSB
- ULONG BOH :1; //RO -- BIOS/OS Handoff: When set to �1�, the HBA supports the BIOS/OS handoff mechanism defined in section TBD. When cleared to �0�, the HBA does not support the BIOS/OS handoff mechanism.
- ULONG NVMP :1; //RO -- NVMHCI Present: When set to '1', the HBA includes support for NVMHCI and the registers at offset 60h-9Fh are valid. When cleared to �0�, the HBA does not support NVMHCI.
- ULONG APST :1; //RO -- Automatic Partial to Slumber Transitions (APST): When set to �1�, the HBA supports Automatic Partial to Slumber Transitions. When cleared to �0�, Automatic Partial to Slumber Transitions are not supported.
- ULONG SDS :1; //RO -- Supports Device Sleep (SDS): When set to �1�, the HBA supports the Device Sleep feature. When cleared to �0�, DEVSLP is not supported and software shall not set PxCMD.ICC to �8h�
- ULONG SADM :1; //RO -- Supports Aggressive Device Sleep Management (SADM): When set to �1�, the HBA supports hardware assertion of the DEVSLP signal after the idle timeout expires. When cleared to �0�, this function is not supported and software shall treat the PxDEVSLP.ADSE field as reserved. Refer to section 8.5.1.
- ULONG DESO :1; //RO -- DevSleep Entrance from Slumber Only (DESO): This field specifies that the HBA shall only assert the DEVSLP signal if the interface is in Slumber. When this bit is set to �1�, the HBA shall ignore software directed entrance to DevSleep via PxCMD.ICC unless PxSSTS.IPM = 6h. When this bit is cleared to �0�, the HBA may enter DevSleep from any link state (active, Partial, or Slumber).
+ ULONG BOH :1; //RO -- BIOS/OS Handoff: When set to '1', the HBA supports the BIOS/OS handoff mechanism defined in section TBD. When cleared to '0', the HBA does not support the BIOS/OS handoff mechanism.
+ ULONG NVMP :1; //RO -- NVMHCI Present: When set to '1', the HBA includes support for NVMHCI and the registers at offset 60h-9Fh are valid. When cleared to '0', the HBA does not support NVMHCI.
+ ULONG APST :1; //RO -- Automatic Partial to Slumber Transitions (APST): When set to '1', the HBA supports Automatic Partial to Slumber Transitions. When cleared to '0', Automatic Partial to Slumber Transitions are not supported.
+ ULONG SDS :1; //RO -- Supports Device Sleep (SDS): When set to '1', the HBA supports the Device Sleep feature. When cleared to '0', DEVSLP is not supported and software shall not set PxCMD.ICC to '8h'
+ ULONG SADM :1; //RO -- Supports Aggressive Device Sleep Management (SADM): When set to '1', the HBA supports hardware assertion of the DEVSLP signal after the idle timeout expires. When cleared to '0', this function is not supported and software shall treat the PxDEVSLP.ADSE field as reserved. Refer to section 8.5.1.
+ ULONG DESO :1; //RO -- DevSleep Entrance from Slumber Only (DESO): This field specifies that the HBA shall only assert the DEVSLP signal if the interface is in Slumber. When this bit is set to '1', the HBA shall ignore software directed entrance to DevSleep via PxCMD.ICC unless PxSSTS.IPM = 6h. When this bit is cleared to '0', the HBA may enter DevSleep from any link state (active, Partial, or Slumber).
ULONG Reserved :26;
//MSB
@@ -918,4 +918,3 @@ typedef struct _AHCI_MEMORY_REGISTERS{
#pragma warning(default:4214)
#pragma warning(default:4201)
#endif
-
diff --git a/storage/miniports/storahci/src/common.c b/storage/miniports/storahci/src/common.c
index 2c1dd991..b8aa8667 100644
--- a/storage/miniports/storahci/src/common.c
+++ b/storage/miniports/storahci/src/common.c
@@ -91,10 +91,58 @@ AtaAlwaysSuccessRequestCompletion (
_In_ PSTORAGE_REQUEST_BLOCK Srb
);
+__inline
+BOOLEAN
+IsExceptionCommand(
+ _In_ PCDB Cdb
+ )
+/*
+ Return true for enumeration and power transition related command.
+*/
+{
+ return ((Cdb->CDB10.OperationCode == SCSIOP_REPORT_LUNS) ||
+ (Cdb->CDB10.OperationCode == SCSIOP_INQUIRY) ||
+ (Cdb->CDB10.OperationCode == SCSIOP_START_STOP_UNIT) ||
+ (Cdb->CDB10.OperationCode == SCSIOP_SECURITY_PROTOCOL_OUT) ||
+ (Cdb->CDB10.OperationCode == SCSIOP_SECURITY_PROTOCOL_IN) ||
+ (Cdb->CDB10.OperationCode == SCSIOP_SYNCHRONIZE_CACHE));
+}
+
+__inline
+BOOLEAN
+RetryCommand(
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_ PCDB Cdb
+ )
+/*
+ If initialization triggered by power up in progress, return false;
+ else if port start/init/restore preserved settings command outstanding, and
+ command(e.g. enumeration and power transition related) is not in exception
+ list, return true;
+ Otherwise, return false.
+*/
+{
+ //
+ // If power up in progress, do not retry anything.
+ //
+ if (ChannelExtension->StateFlags.PowerUpInitializationInProgress) {
+ return FALSE;
+ }
+
+ if ((ChannelExtension->StateFlags.ReservedSlotInUse ||
+ ((ChannelExtension->StartState.ChannelNextStartState != StartComplete) &&
+ (ChannelExtension->StartState.ChannelNextStartState != StartFailed))) &&
+ (!IsExceptionCommand(Cdb))) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
ULONG
SCSItoATA(
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
- _In_ PSTORAGE_REQUEST_BLOCK Srb
+ _In_ PSTORAGE_REQUEST_BLOCK Srb
)
/*
Note: If there is a need to send a command to device,
@@ -103,9 +151,9 @@ SCSItoATA(
Not setting this field can cause the Srb being completed earlier than expected.
*/
{
- ULONG status;
- ULONG cdbLength = 0;
- PCDB cdb = RequestGetSrbScsiData(Srb, &cdbLength, NULL, NULL, NULL);
+ ULONG status;
+ ULONG cdbLength = 0;
+ PCDB cdb = RequestGetSrbScsiData(Srb, &cdbLength, NULL, NULL, NULL);
if (cdb != NULL) {
if (IsAtapiDevice(&ChannelExtension->DeviceExtension->DeviceParameters)) {
@@ -114,8 +162,17 @@ SCSItoATA(
} else if (IsAtaDevice(&ChannelExtension->DeviceExtension->DeviceParameters) ||
(cdb->CDB10.OperationCode == SCSIOP_REPORT_LUNS) ||
(cdb->CDB10.OperationCode == SCSIOP_INQUIRY) ) {
- // Ata command, or device enumeration commands.
- status = SrbConvertToATACommand(ChannelExtension, Srb, cdb, cdbLength);
+ //
+ // Fail SRB with busy status to storport if port start is in progress or init/restore
+ // preserved settings command outstanding. Storport will retry these IOs later.
+ //
+ if (RetryCommand(ChannelExtension, cdb)) {
+ Srb->SrbStatus = SRB_STATUS_BUSY;
+ status = STOR_STATUS_BUSY;
+ } else {
+ // Ata command, or device enumeration commands.
+ status = SrbConvertToATACommand(ChannelExtension, Srb, cdb, cdbLength);
+ }
} else {
Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
status = STOR_STATUS_INVALID_DEVICE_REQUEST;
@@ -306,7 +363,7 @@ Return value:
if (Srb->SrbStatus == SRB_STATUS_BUS_RESET) {
if (srbExtension->DataBuffer != NULL) {
- AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, (ULONG_PTR)srbExtension->CompletionContext, srbExtension->DataBuffer);
+ AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, (ULONG_PTR)srbExtension->CompletionContext, srbExtension->DataBuffer, srbExtension->DataBufferPhysicalAddress);
srbExtension->DataBuffer = NULL;
}
return;
@@ -317,7 +374,7 @@ Return value:
(srbExtension->DataTransferLength < sizeof(MODE_PARAMETER_HEADER)) ) {
// free the memory and mark the Srb with error status.
if (srbExtension->DataBuffer != NULL) {
- AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, (ULONG_PTR)srbExtension->CompletionContext, srbExtension->DataBuffer);
+ AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, (ULONG_PTR)srbExtension->CompletionContext, srbExtension->DataBuffer, srbExtension->DataBufferPhysicalAddress);
srbExtension->DataBuffer = NULL;
}
@@ -370,7 +427,7 @@ Return value:
}
if (srbExtension->DataBuffer != NULL) {
- AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, (ULONG_PTR)srbExtension->CompletionContext, srbExtension->DataBuffer);
+ AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, (ULONG_PTR)srbExtension->CompletionContext, srbExtension->DataBuffer, srbExtension->DataBufferPhysicalAddress);
srbExtension->DataBuffer = NULL;
}
@@ -388,9 +445,8 @@ AtapiModeSenseRequest (
{
ULONG status;
ULONG modeSenseBufferSize;
- ULONG tempLength;
PMODE_PARAMETER_HEADER10 modeSenseBuffer;
- STOR_PHYSICAL_ADDRESS modeSensePhysialAddress;
+ STOR_PHYSICAL_ADDRESS modeSensePhysicalAddress = {0};
PUCHAR origBuffer;
UCHAR bytesAdjust;
@@ -432,7 +488,7 @@ AtapiModeSenseRequest (
}
// We need to allocate a new data buffer since the size is different
- status = AhciAllocateDmaBuffer(ChannelExtension->AdapterExtension, modeSenseBufferSize, (PVOID*)&modeSenseBuffer);
+ status = AhciAllocateDmaBuffer(ChannelExtension->AdapterExtension, modeSenseBufferSize, (PVOID*)&modeSenseBuffer, &modeSensePhysicalAddress);
if ( (status != STOR_STATUS_SUCCESS) ||
(modeSenseBuffer == NULL) ) {
// memory allocation failed
@@ -442,7 +498,6 @@ AtapiModeSenseRequest (
}
AhciZeroMemory((PCHAR)modeSenseBuffer, modeSenseBufferSize);
- modeSensePhysialAddress = StorPortGetPhysicalAddress(ChannelExtension->AdapterExtension, NULL, (PVOID)modeSenseBuffer, &tempLength);
// fill information in the new MODE_SENSE10 header
allocationLength = Cdb->MODE_SENSE.AllocationLength;
@@ -472,13 +527,14 @@ AtapiModeSenseRequest (
srbExtension->Flags |= ATA_FLAGS_NEW_CDB;
srbExtension->Flags |= ATA_FLAGS_DATA_IN;
srbExtension->DataBuffer = modeSenseBuffer;
+ srbExtension->DataBufferPhysicalAddress.QuadPart = modeSensePhysicalAddress.QuadPart;
srbExtension->DataTransferLength = modeSenseBufferSize;
srbExtension->CompletionRoutine = AtapiModeCommandRequestCompletion;
srbExtension->CompletionContext = (PVOID)modeSenseBufferSize; // preserve the buffer size, it's needed for freeing the memory
srbExtension->LocalSgl.NumberOfElements = 1;
- srbExtension->LocalSgl.List[0].PhysicalAddress.LowPart = modeSensePhysialAddress.LowPart;
- srbExtension->LocalSgl.List[0].PhysicalAddress.HighPart = modeSensePhysialAddress.HighPart;
+ srbExtension->LocalSgl.List[0].PhysicalAddress.LowPart = modeSensePhysicalAddress.LowPart;
+ srbExtension->LocalSgl.List[0].PhysicalAddress.HighPart = modeSensePhysicalAddress.HighPart;
srbExtension->LocalSgl.List[0].Length = modeSenseBufferSize;
srbExtension->Sgl = &srbExtension->LocalSgl;
@@ -486,7 +542,7 @@ Done:
if (status != STOR_STATUS_SUCCESS) {
if (modeSenseBuffer != NULL) {
- AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, modeSenseBufferSize, modeSenseBuffer);
+ AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, modeSenseBufferSize, modeSenseBuffer, modeSensePhysicalAddress);
}
srbExtension->DataBuffer = NULL;
}
@@ -508,8 +564,7 @@ AtapiModeSelectRequest (
ULONG status;
PVOID modeSelectBuffer;
ULONG modeSelectBufferSize;
- ULONG tempLength;
- STOR_PHYSICAL_ADDRESS modeSelectPhysialAddress;
+ STOR_PHYSICAL_ADDRESS modeSelectPhysicalAddress = {0};
UCHAR bytesToSkip;
PUCHAR origBuffer;
UCHAR bytesAdjust;
@@ -556,7 +611,7 @@ AtapiModeSelectRequest (
modeSelectBufferSize = srbDataBufferLength + bytesAdjust - header->BlockDescriptorLength;
// allocate buffer for the new cdb
- status = AhciAllocateDmaBuffer(ChannelExtension->AdapterExtension, modeSelectBufferSize, (PVOID*)&modeSelectBuffer);
+ status = AhciAllocateDmaBuffer(ChannelExtension->AdapterExtension, modeSelectBufferSize, (PVOID*)&modeSelectBuffer, &modeSelectPhysicalAddress);
if ( (status != STOR_STATUS_SUCCESS) ||
(modeSelectBuffer == NULL) ) {
@@ -567,7 +622,6 @@ AtapiModeSelectRequest (
}
AhciZeroMemory((PCHAR)modeSelectBuffer, modeSelectBufferSize);
- modeSelectPhysialAddress = StorPortGetPhysicalAddress(ChannelExtension->AdapterExtension, NULL, (PVOID)modeSelectBuffer, &tempLength);
header10 = (PMODE_PARAMETER_HEADER10)modeSelectBuffer;
@@ -610,6 +664,7 @@ AtapiModeSelectRequest (
srbExtension->Flags |= ATA_FLAGS_NEW_CDB;
srbExtension->Flags |= ATA_FLAGS_DATA_OUT;
srbExtension->DataBuffer = modeSelectBuffer;
+ srbExtension->DataBufferPhysicalAddress.QuadPart = modeSelectPhysicalAddress.QuadPart;
srbExtension->DataTransferLength = modeSelectBufferSize;
srbExtension->CompletionRoutine = AtapiModeCommandRequestCompletion;
srbExtension->CompletionContext = (PVOID)modeSelectBufferSize; // preserve the buffer size, it's needed for freeing the memory
@@ -626,8 +681,8 @@ AtapiModeSelectRequest (
cdb->MODE_SELECT10.Control = Cdb->MODE_SELECT.Control;
srbExtension->LocalSgl.NumberOfElements = 1;
- srbExtension->LocalSgl.List[0].PhysicalAddress.LowPart = modeSelectPhysialAddress.LowPart;
- srbExtension->LocalSgl.List[0].PhysicalAddress.HighPart = modeSelectPhysialAddress.HighPart;
+ srbExtension->LocalSgl.List[0].PhysicalAddress.LowPart = modeSelectPhysicalAddress.LowPart;
+ srbExtension->LocalSgl.List[0].PhysicalAddress.HighPart = modeSelectPhysicalAddress.HighPart;
srbExtension->LocalSgl.List[0].Length = modeSelectBufferSize; // preserve the buffer size, it's needed for freeing the memory
srbExtension->Sgl = &srbExtension->LocalSgl;
@@ -635,7 +690,7 @@ Done:
if (status != STOR_STATUS_SUCCESS) {
if (modeSelectBuffer != NULL) {
- AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, modeSelectBufferSize, modeSelectBuffer);
+ AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, modeSelectBufferSize, modeSelectBuffer, modeSelectPhysicalAddress);
}
srbExtension->DataBuffer = NULL;
}
@@ -660,7 +715,7 @@ SrbConvertToATACommand(
Not setting this field can cause the Srb being completed earlier than expected.
*/
{
- ULONG status;
+ ULONG status = STOR_STATUS_INVALID_DEVICE_REQUEST;
// translate the cdb to task file register values
switch (Cdb->CDB10.OperationCode) {
@@ -693,11 +748,29 @@ SrbConvertToATACommand(
break;
case SCSIOP_READ_CAPACITY:
- case SCSIOP_READ_CAPACITY16:
status = AtaReadCapacityRequest(ChannelExtension, Srb, Cdb, CdbLength);
break;
+ case SCSIOP_READ_CAPACITY16:
+
+ //
+ // Get physical element status & Remove element and truncate command share the same operation code 0x9e
+ // with read capacity 16 command.
+ //
+
+ if (Cdb->READ_CAPACITY16.ServiceAction == SERVICE_ACTION_READ_CAPACITY16) {
+ status = AtaReadCapacityRequest(ChannelExtension, Srb, Cdb, CdbLength);
+ } else if (Cdb->GET_PHYSICAL_ELEMENT_STATUS.ServiceAction == SERVICE_ACTION_GET_PHYSICAL_ELEMENT_STATUS) {
+ status = AtaGetPhysicalElementStatusRequest(ChannelExtension, Srb, Cdb);
+ } else if (Cdb->REMOVE_ELEMENT_AND_TRUNCATE.ServiceAction == SERVICE_ACTION_REMOVE_ELEMENT_AND_TRUNCATE) {
+ status = AtaRemoveElementAndTruncateRequest(ChannelExtension, Srb, Cdb);
+ } else {
+ Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+ }
+
+ break;
+
case SCSIOP_INQUIRY:
status = AtaInquiryRequest(ChannelExtension, Srb, Cdb);
@@ -746,14 +819,62 @@ SrbConvertToATACommand(
status = AtaWriteBufferRequest(ChannelExtension, Srb, Cdb);
break;
+ case SCSIOP_READ_DATA_BUFF16:
+
+ if (Cdb->READ_BUFFER_16.Mode == READ_BUFFER_MODE_ERROR_HISTORY) {
+ if (Cdb->READ_BUFFER_16.BufferId == BUFFER_ID_RETURN_ERROR_HISTORY_DIRECTORY) {
+ status = AtaGetDeviceCurrentInternalStatusDataHeader(ChannelExtension, Srb, Cdb);
+ } else if((Cdb->READ_BUFFER_16.BufferId >= BUFFER_ID_RETURN_ERROR_HISTORY_MINIMUM_THRESHOLD) &&
+ (Cdb->READ_BUFFER_16.BufferId <= BUFFER_ID_RETURN_ERROR_HISTORY_MAXIMUM_THRESHOLD)) {
+ status = AtaGetDeviceCurrentInternalStatusData(ChannelExtension, Srb, Cdb);
+ } else {
+ Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+ }
+ } else {
+ Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+ }
+
+ break;
default:
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
- status = STOR_STATUS_INVALID_DEVICE_REQUEST;
break;
}
+ if (status != STOR_STATUS_SUCCESS) {
+
+ } else {
+ PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb);
+ AHCI_H2D_REGISTER_FIS cfis = srbExtension->Cfis; // Size is 20 bytes (shares first 16 with TaskFile)
+ // Convert the Cfis to an array of ULONGs to log the struct in pieces
+ PULONG cfisAsUlong = (PULONG)&cfis; // Length is 5 ULONGs
+ StorPortEtwEvent8(ChannelExtension->AdapterExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciEtwEventBuildIO,
+ L"SrbConvertToATACommand finished",
+ STORPORT_ETW_EVENT_KEYWORD_COMMAND_TRACE,
+ StorportEtwLevelInformational,
+ StorportEtwEventOpcodeInfo,
+ (PSCSI_REQUEST_BLOCK)Srb,
+ L"AtaFunction",
+ srbExtension->AtaFunction,
+ L"Cfis 0-7",
+ ((ULONGLONG)cfisAsUlong[0] << 32) + cfisAsUlong[1],
+ L"Cfis 8-15",
+ ((ULONGLONG)cfisAsUlong[2] << 32) + cfisAsUlong[3],
+ L"Cfis 16-20",
+ ((ULONGLONG)cfisAsUlong[4] << 32),
+ L"CDB 0-7",
+ ((ULONGLONG)Cdb->AsUlong[0] << 32) + Cdb->AsUlong[1],
+ L"CDB 8-15",
+ ((ULONGLONG)Cdb->AsUlong[2] << 32) + Cdb->AsUlong[3],
+ NULL,
+ 0,
+ NULL,
+ 0);
+ }
+
return status;
}
@@ -852,7 +973,7 @@ HybridWriteThroughEvictCompletion(
//
// Free DMA buffer that allocated for EVICT command.
//
- AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, ATA_BLOCK_SIZE, srbExtension->DataBuffer);
+ AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, ATA_BLOCK_SIZE, srbExtension->DataBuffer, srbExtension->DataBufferPhysicalAddress);
return;
}
@@ -880,7 +1001,6 @@ Return Value:
--*/
{
ULONG status;
- ULONG i;
PATA_LBA_RANGE buffer = NULL; // DMA buffer allocated for EVICT command
STOR_PHYSICAL_ADDRESS bufferPhysicalAddress;
PAHCI_SRB_EXTENSION srbExtension;
@@ -897,7 +1017,7 @@ Return Value:
//
// allocate DMA buffer, this buffer will be used to store the ATA LBA Range for EVICT command
//
- status = AhciAllocateDmaBuffer((PVOID)ChannelExtension->AdapterExtension, ATA_BLOCK_SIZE, (PVOID*)&buffer);
+ status = AhciAllocateDmaBuffer((PVOID)ChannelExtension->AdapterExtension, ATA_BLOCK_SIZE, (PVOID*)&buffer, &bufferPhysicalAddress);
if ( (status != STOR_STATUS_SUCCESS) || (buffer == NULL) ) {
Srb->SrbStatus = SRB_STATUS_ERROR;
@@ -925,9 +1045,9 @@ Return Value:
srbExtension->AtaFunction = ATA_FUNCTION_ATA_CFIS_PAYLOAD;
srbExtension->Flags |= ATA_FLAGS_DATA_OUT;
srbExtension->DataBuffer = buffer;
+ srbExtension->DataBufferPhysicalAddress.QuadPart = bufferPhysicalAddress.QuadPart;
srbExtension->DataTransferLength = ATA_BLOCK_SIZE;
- bufferPhysicalAddress = StorPortGetPhysicalAddress(ChannelExtension->AdapterExtension, NULL, buffer, &i);
srbExtension->LocalSgl.NumberOfElements = 1;
srbExtension->LocalSgl.List[0].PhysicalAddress.LowPart = bufferPhysicalAddress.LowPart;
srbExtension->LocalSgl.List[0].PhysicalAddress.HighPart = bufferPhysicalAddress.HighPart;
@@ -1164,7 +1284,6 @@ Notes:
}
}
-
return;
}
@@ -1741,9 +1860,9 @@ AtaReadCapacityCompletion (
if (srbDataBuffer != NULL) {
if (cdbLength == 0x10) {
- // 16 byte CDB
+ // 16 byte CDB, set return data length default to sizeof(READ_CAPACITY_DATA_EX).
PREAD_CAPACITY16_DATA readCap16 = (PREAD_CAPACITY16_DATA)srbDataBuffer;
- ULONG returnDataLength = 12; //default to sizeof(READ_CAPACITY_DATA_EX)
+ ULONG returnDataLength = sizeof(READ_CAPACITY_DATA_EX);
if (srbDataBufferLength < sizeof(READ_CAPACITY_DATA_EX)) {
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
@@ -1780,7 +1899,11 @@ AtaReadCapacityCompletion (
readCap16->LBPRZ = 0;
}
- returnDataLength = FIELD_OFFSET(READ_CAPACITY16_DATA, Reserved3);
+ if (srbDataBufferLength >= sizeof(READ_CAPACITY16_DATA)) {
+ returnDataLength = sizeof(READ_CAPACITY16_DATA);
+ } else {
+ returnDataLength = (ULONG)FIELD_OFFSET(READ_CAPACITY16_DATA, Reserved3);
+ }
}
SrbSetDataTransferLength(Srb, returnDataLength);
@@ -1939,7 +2062,7 @@ AtaGenerateInquiryData (
AhciZeroMemory((PCHAR)InquiryData, ATA_INQUIRYDATA_SIZE);
- InquiryData->DeviceType = ChannelExtension->DeviceExtension->DeviceParameters.ScsiDeviceType; //DIRECT_ACCESS_DEVICE;
+ InquiryData->DeviceType = ChannelExtension->DeviceExtension->DeviceParameters.ScsiDeviceType;
InquiryData->RemovableMedia = IsRemovableMedia(&ChannelExtension->DeviceExtension->DeviceParameters) ? 1 : 0;
InquiryData->ResponseDataFormat = 0x2; //data format is defined in SPC standard
InquiryData->CommandQueue = 1; //support NCQ for AHCI controller
@@ -2143,7 +2266,11 @@ AtaInquiryRequest(
_In_ PCDB Cdb
)
/*
- NOTE: the command should be completed after calling this function as no real command will be sent to device.
+ NOTE:
+ In most cases the command should be completed after calling this function as
+ no real command will be sent to device. The exceptions being if we're on the
+ dump stack or if a firmware activate was just performed and the identify data
+ needs to be refreshed.
*/
{
ULONG status = STOR_STATUS_SUCCESS;
@@ -2157,18 +2284,17 @@ AtaInquiryRequest(
status = STOR_STATUS_INVALID_PARAMETER;
} else if (Cdb->CDB6INQUIRY3.EnableVitalProductData == 0) {
- if (IsDumpMode(ChannelExtension->AdapterExtension) && !DeviceIdentificationComplete(ChannelExtension->AdapterExtension)) {
+ if (IsDumpMode(ChannelExtension->AdapterExtension) && !DeviceIdentificationCompletedSuccess(ChannelExtension->AdapterExtension)) {
// the enumeration command from dump stack.
IssueIdentifyCommand(ChannelExtension, Srb);
- } else if (ChannelExtension->DeviceExtension->DeviceParameters.StateFlags.NeedUpdateIdentifyDeviceData == 1) {
- ChannelExtension->DeviceExtension->DeviceParameters.StateFlags.NeedUpdateIdentifyDeviceData = 0;
+ } else if (ChannelExtension->DeviceExtension->DeviceParameters.StateFlags.NeedUpdateIdentifyDeviceData == 1) {
IssueIdentifyCommand(ChannelExtension, Srb);
} else {
status = InquiryComplete(ChannelExtension, Srb);
}
} else {
- PVOID srbDataBuffer = SrbGetDataBuffer(Srb);
- ULONG srbDataBufferLength = SrbGetDataTransferLength(Srb);
+ PVOID srbDataBuffer = SrbGetDataBuffer(Srb);
+ ULONG srbDataBufferLength = SrbGetDataTransferLength(Srb);
if (srbDataBuffer == NULL) {
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
@@ -2184,7 +2310,12 @@ AtaInquiryRequest(
//
// Input buffer should be at least the size of page header plus count of supported pages, each page needs one byte.
//
- ULONG requiredBufferSize = sizeof(VPD_SUPPORTED_PAGES_PAGE) + 6;
+
+ ULONG requiredBufferSize = 0;
+ UCHAR supportedPageCount = 8;
+ ULONG i = 0;
+
+ requiredBufferSize = sizeof(VPD_SUPPORTED_PAGES_PAGE) + supportedPageCount;
if (srbDataBufferLength < requiredBufferSize) {
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
@@ -2192,16 +2323,26 @@ AtaInquiryRequest(
} else {
PVPD_SUPPORTED_PAGES_PAGE outputBuffer = (PVPD_SUPPORTED_PAGES_PAGE)srbDataBuffer;
- outputBuffer->DeviceType = ChannelExtension->DeviceExtension->DeviceParameters.ScsiDeviceType; //DIRECT_ACCESS_DEVICE; ;
+ //
+ // Report supported page in ascending order beginning with page code 00h.
+ //
+ outputBuffer->DeviceType = ChannelExtension->DeviceExtension->DeviceParameters.ScsiDeviceType;
outputBuffer->DeviceTypeQualifier = 0;
outputBuffer->PageCode = VPD_SUPPORTED_PAGES;
- outputBuffer->PageLength = 0x06; // supports 6 VPD pages
- outputBuffer->SupportedPageList[0] = VPD_SUPPORTED_PAGES;
- outputBuffer->SupportedPageList[1] = VPD_SERIAL_NUMBER;
- outputBuffer->SupportedPageList[2] = VPD_ATA_INFORMATION;
- outputBuffer->SupportedPageList[3] = VPD_BLOCK_LIMITS;
- outputBuffer->SupportedPageList[4] = VPD_BLOCK_DEVICE_CHARACTERISTICS;
- outputBuffer->SupportedPageList[5] = VPD_LOGICAL_BLOCK_PROVISIONING;
+ outputBuffer->PageLength = supportedPageCount;
+ outputBuffer->SupportedPageList[i++] = VPD_SUPPORTED_PAGES;
+ outputBuffer->SupportedPageList[i++] = VPD_SERIAL_NUMBER;
+ // Support device identification page(VPD: 0x83) to resolve PCS test failure.
+ outputBuffer->SupportedPageList[i++] = VPD_DEVICE_IDENTIFIERS;
+ // According to SAT4, if the SATL supports the Read Buffer command with mode field set to 0x1C(Error History mode),
+ // then the SATL shall support the Extended Inquiry Data VPD page.
+ outputBuffer->SupportedPageList[i++] = VPD_EXTENDED_INQUIRY_DATA;
+ outputBuffer->SupportedPageList[i++] = VPD_ATA_INFORMATION;
+ outputBuffer->SupportedPageList[i++] = VPD_BLOCK_LIMITS;
+ outputBuffer->SupportedPageList[i++] = VPD_BLOCK_DEVICE_CHARACTERISTICS;
+ outputBuffer->SupportedPageList[i++] = VPD_LOGICAL_BLOCK_PROVISIONING;
+
+ NT_ASSERT(supportedPageCount == i);
SrbSetDataTransferLength(Srb, requiredBufferSize);
@@ -2211,13 +2352,19 @@ AtaInquiryRequest(
break;
}
case VPD_BLOCK_LIMITS: {
- if (srbDataBufferLength < 0x14) {
- Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
- status = STOR_STATUS_INVALID_PARAMETER;
+ if (srbDataBufferLength < sizeof(VPD_BLOCK_LIMITS_PAGE)) {
+ SrbSetSrbStatus(Srb, SRB_STATUS_DATA_OVERRUN);
+ SrbSetDataTransferLength(Srb, 0);
+ status = STOR_STATUS_BUFFER_TOO_SMALL;
} else {
PVPD_BLOCK_LIMITS_PAGE outputBuffer = (PVPD_BLOCK_LIMITS_PAGE)srbDataBuffer;
- outputBuffer->DeviceType = ChannelExtension->DeviceExtension->DeviceParameters.ScsiDeviceType; //DIRECT_ACCESS_DEVICE; ;
+ //
+ // Resetting the VPD page buffer
+ //
+ AhciZeroMemory((PCHAR)outputBuffer, sizeof(VPD_BLOCK_LIMITS_PAGE));
+
+ outputBuffer->DeviceType = ChannelExtension->DeviceExtension->DeviceParameters.ScsiDeviceType;
outputBuffer->DeviceTypeQualifier = 0;
outputBuffer->PageCode = VPD_BLOCK_LIMITS;
@@ -2225,9 +2372,8 @@ AtaInquiryRequest(
// leave outputBuffer->Descriptors[0 : 15] as '0' indicating 'not supported' for those fields.
//
- if ( (srbDataBufferLength >= 0x24) &&
- IsDeviceSupportsTrim(ChannelExtension) ) {
- // not worry about multiply overflow as max of DsmCapBlockCount is min(AHCI_MAX_TRANSFER_LENGTH / ATA_BLOCK_SIZE, 0xFFFF)
+ if ( IsDeviceSupportsTrim(ChannelExtension) ) {
+ // not worry about multiply overflow as max of DsmCapBlockCount is min(AHCI_MAX_TRANSFER_LENGTH_DEFAULT / ATA_BLOCK_SIZE, 0xFFFF)
// calculate how many LBA ranges can be associated with one DSM - Trim command
ULONG maxLbaRangeEntryCountPerCmd = ChannelExtension->DeviceExtension[0].DeviceParameters.DsmCapBlockCount * (ATA_BLOCK_SIZE / sizeof(ATA_LBA_RANGE));
// calculate how many LBA can be associated with one DSM - Trim command
@@ -2250,8 +2396,9 @@ AtaInquiryRequest(
// keep original 'Srb->DataTransferLength' value.
} else {
- outputBuffer->PageLength[1] = 0x10;
- SrbSetDataTransferLength(Srb, 0x14);
+ outputBuffer->PageLength[1] = 0x3C;
+
+ // keep original 'Srb->DataTransferLength' value.
}
Srb->SrbStatus = SRB_STATUS_SUCCESS;
@@ -2266,7 +2413,7 @@ AtaInquiryRequest(
} else {
PVPD_BLOCK_DEVICE_CHARACTERISTICS_PAGE outputBuffer = (PVPD_BLOCK_DEVICE_CHARACTERISTICS_PAGE)srbDataBuffer;
- outputBuffer->DeviceType = ChannelExtension->DeviceExtension->DeviceParameters.ScsiDeviceType; //DIRECT_ACCESS_DEVICE; ;
+ outputBuffer->DeviceType = ChannelExtension->DeviceExtension->DeviceParameters.ScsiDeviceType;
outputBuffer->DeviceTypeQualifier = 0;
outputBuffer->PageCode = VPD_BLOCK_DEVICE_CHARACTERISTICS;
outputBuffer->PageLength = 0x3C; // must be 0x3C per spec
@@ -2286,7 +2433,7 @@ AtaInquiryRequest(
} else {
PVPD_LOGICAL_BLOCK_PROVISIONING_PAGE outputBuffer = (PVPD_LOGICAL_BLOCK_PROVISIONING_PAGE)srbDataBuffer;
- outputBuffer->DeviceType = ChannelExtension->DeviceExtension->DeviceParameters.ScsiDeviceType; //DIRECT_ACCESS_DEVICE; ;
+ outputBuffer->DeviceType = ChannelExtension->DeviceExtension->DeviceParameters.ScsiDeviceType;
outputBuffer->DeviceTypeQualifier = 0;
outputBuffer->PageCode = VPD_LOGICAL_BLOCK_PROVISIONING;
outputBuffer->PageLength[1] = 0x04; // 8 bytes data in total
@@ -2319,7 +2466,7 @@ AtaInquiryRequest(
PVPD_SERIAL_NUMBER_PAGE outputBuffer = (PVPD_SERIAL_NUMBER_PAGE)srbDataBuffer;
UCHAR i;
- outputBuffer->DeviceType = ChannelExtension->DeviceExtension->DeviceParameters.ScsiDeviceType; //DIRECT_ACCESS_DEVICE; ;
+ outputBuffer->DeviceType = ChannelExtension->DeviceExtension->DeviceParameters.ScsiDeviceType;
outputBuffer->DeviceTypeQualifier = 0;
outputBuffer->PageCode = VPD_SERIAL_NUMBER;
outputBuffer->PageLength = 20; // 24 bytes data in total
@@ -2347,7 +2494,7 @@ AtaInquiryRequest(
AhciZeroMemory((PCHAR)outputBuffer, sizeof(VPD_ATA_INFORMATION_PAGE));
- outputBuffer->DeviceType = ChannelExtension->DeviceExtension->DeviceParameters.ScsiDeviceType; //DIRECT_ACCESS_DEVICE; ;
+ outputBuffer->DeviceType = ChannelExtension->DeviceExtension->DeviceParameters.ScsiDeviceType;
outputBuffer->DeviceTypeQualifier = 0;
outputBuffer->PageCode = VPD_ATA_INFORMATION;
outputBuffer->PageLength[0] = 0x02;
@@ -2400,6 +2547,40 @@ AtaInquiryRequest(
break;
}
+ case VPD_EXTENDED_INQUIRY_DATA: {
+ if (srbDataBufferLength < RTL_SIZEOF_THROUGH_FIELD(VPD_EXTENDED_INQUIRY_DATA_PAGE, MaxSupportedSenseDataLength)) {
+ Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+ status = STOR_STATUS_INVALID_PARAMETER;
+ } else {
+ PVPD_EXTENDED_INQUIRY_DATA_PAGE outputBuffer = (PVPD_EXTENDED_INQUIRY_DATA_PAGE)srbDataBuffer;
+
+ AhciZeroMemory((PCHAR)outputBuffer, srbDataBufferLength);
+
+ // Below fields are required for Read Buffer command(Error history mode) support in SAT-4.
+ outputBuffer->DeviceType = ChannelExtension->DeviceExtension->DeviceParameters.ScsiDeviceType;
+ outputBuffer->DeviceTypeQualifier = 0;
+ outputBuffer->PageCode = VPD_EXTENDED_INQUIRY_DATA;
+ outputBuffer->PageLength[0] = 0;
+ outputBuffer->PageLength[1] = 0x3C; // must be 0x3C per spec.
+ outputBuffer->HssRelef = 1;
+
+ // Populate below fields according to SAT-2.
+ if (ChannelExtension->DeviceExtension->IdentifyDeviceData->NVCacheCapabilities.NVCachePowerModeEnabled == 1 ||
+ ChannelExtension->DeviceExtension->IdentifyDeviceData->AdditionalSupported.NonVolatileWriteCache == 1) {
+ outputBuffer->NvSup = 1;
+ }
+ if (ChannelExtension->DeviceExtension->IdentifyDeviceData->CommandSetActive.WriteCache ||
+ ChannelExtension->DeviceExtension->IdentifyDeviceData->CommandSetActive.LookAhead) {
+ outputBuffer->VSup = 1;
+ }
+
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+ status = STOR_STATUS_SUCCESS;
+ }
+
+ break;
+ }
+
default:
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
status = STOR_STATUS_INVALID_PARAMETER;
@@ -2905,7 +3086,7 @@ Return Value:
} else {
if (buffer != NULL) {
- AhciFreeDmaBuffer((PVOID)ChannelExtension->AdapterExtension, trimContext->AllocatedBufferLength, buffer);
+ AhciFreeDmaBuffer((PVOID)ChannelExtension->AdapterExtension, trimContext->AllocatedBufferLength, buffer, srbExtension->DataBufferPhysicalAddress);
}
if (trimContext != NULL) {
@@ -2938,6 +3119,7 @@ AtaUnmapRequest (
PVOID srbDataBuffer = SrbGetDataBuffer(Srb);
ULONG srbDataBufferLength = SrbGetDataTransferLength(Srb);
+ STOR_PHYSICAL_ADDRESS bufferPhysicalAddress = {0};
unmapList = (PUNMAP_LIST_HEADER)srbDataBuffer;
@@ -2957,8 +3139,6 @@ AtaUnmapRequest (
} else {
// some preparation work before actually starting to process the request
ULONG i = 0;
- ULONG length = 0;
- STOR_PHYSICAL_ADDRESS bufferPhysicalAddress;
status = StorPortAllocatePool(ChannelExtension->AdapterExtension, sizeof(ATA_TRIM_CONTEXT), AHCI_POOL_TAG, (PVOID*)&trimContext);
if ( (status != STOR_STATUS_SUCCESS) || (trimContext == NULL) ) {
@@ -3007,7 +3187,7 @@ AtaUnmapRequest (
}
// 1.4 allocate buffer, this buffer will be used to store ATA LBA Ranges for DSM command
- status = AhciAllocateDmaBuffer((PVOID)ChannelExtension->AdapterExtension, trimContext->AllocatedBufferLength, (PVOID*)&buffer);
+ status = AhciAllocateDmaBuffer((PVOID)ChannelExtension->AdapterExtension, trimContext->AllocatedBufferLength, (PVOID*)&buffer, &bufferPhysicalAddress);
if ( (status != STOR_STATUS_SUCCESS) || (buffer == NULL) ) {
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
@@ -3021,10 +3201,10 @@ AtaUnmapRequest (
srbExtension->AtaFunction = ATA_FUNCTION_ATA_COMMAND;
srbExtension->Flags |= ATA_FLAGS_DATA_OUT;
srbExtension->DataBuffer = buffer;
+ srbExtension->DataBufferPhysicalAddress.QuadPart = bufferPhysicalAddress.QuadPart;
srbExtension->DataTransferLength = trimContext->AllocatedBufferLength;
srbExtension->CompletionContext = (PVOID)trimContext;
- bufferPhysicalAddress = StorPortGetPhysicalAddress(ChannelExtension->AdapterExtension, NULL, buffer, &length);
srbExtension->LocalSgl.NumberOfElements = 1;
srbExtension->LocalSgl.List[0].PhysicalAddress.LowPart = bufferPhysicalAddress.LowPart;
srbExtension->LocalSgl.List[0].PhysicalAddress.HighPart = bufferPhysicalAddress.HighPart;
@@ -3039,7 +3219,7 @@ Exit:
// the process failed before DSM command can be sent. Free allocated resources.
if (status != STOR_STATUS_SUCCESS) {
if (buffer != NULL) {
- AhciFreeDmaBuffer((PVOID)ChannelExtension->AdapterExtension, trimContext->AllocatedBufferLength, buffer);
+ AhciFreeDmaBuffer((PVOID)ChannelExtension->AdapterExtension, trimContext->AllocatedBufferLength, buffer, bufferPhysicalAddress);
}
if (trimContext != NULL) {
@@ -3121,6 +3301,111 @@ AtaSecurityProtocolRequest (
}
+VOID UpdateFirmwareIoctlReturnCode(
+ _In_ PSTORAGE_REQUEST_BLOCK Srb
+ )
+{
+ PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb);
+ PSRB_IO_CONTROL srbControl = (PSRB_IO_CONTROL)SrbGetDataBuffer(Srb);
+
+ if (srbControl == NULL) {
+ return;
+ }
+
+ if (srbExtension->AtaError & IDE_ERROR_CRC_ERROR) {
+
+ // bit 7: Interface CRC error.
+ srbControl->ReturnCode = FIRMWARE_STATUS_INTERFACE_CRC_ERROR;
+
+ } else if (srbExtension->AtaError & IDE_ERROR_DATA_ERROR) {
+
+ // bit 6: Uncorrectable Error.
+ srbControl->ReturnCode = FIRMWARE_STATUS_DEVICE_ERROR;
+
+ } else if (srbExtension->AtaError & IDE_ERROR_MEDIA_CHANGE) {
+
+ // bit 5: Media Changed (legacy).
+ srbControl->ReturnCode = FIRMWARE_STATUS_MEDIA_CHANGE;
+
+ } else if (srbExtension->AtaError & IDE_ERROR_ID_NOT_FOUND) {
+
+ // bit 4: ID Not Found.
+ srbControl->ReturnCode = FIRMWARE_STATUS_ID_NOT_FOUND;
+
+ } else if (srbExtension->AtaError & IDE_ERROR_MEDIA_CHANGE_REQ) {
+
+ // bit 3: Media Change Request (legacy).
+ srbControl->ReturnCode = FIRMWARE_STATUS_MEDIA_CHANGE_REQUEST;
+
+ } else if (srbExtension->AtaError & IDE_ERROR_COMMAND_ABORTED) {
+
+ // bit 2: Command Aborted.
+ srbControl->ReturnCode = FIRMWARE_STATUS_COMMAND_ABORT;
+
+ } else if (srbExtension->AtaError & IDE_ERROR_END_OF_MEDIA) {
+
+ // bit 1: End of Media (legacy).
+ srbControl->ReturnCode = FIRMWARE_STATUS_END_OF_MEDIA;
+
+ } else if (srbExtension->AtaError & IDE_ERROR_ILLEGAL_LENGTH) {
+
+ // bit 0: Media Error (legacy).
+ srbControl->ReturnCode = FIRMWARE_STATUS_ILLEGAL_LENGTH;
+
+ } else {
+
+ // Should not be here, need investigation if get here.
+ NT_ASSERT(FALSE);
+ srbControl->ReturnCode = FIRMWARE_STATUS_ERROR;
+ }
+
+ return;
+}
+
+
+VOID
+AtaFirmwareDownloadCompletion (
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_ PSTORAGE_REQUEST_BLOCK Srb
+ )
+{
+ if (Srb->SrbStatus != SRB_STATUS_SUCCESS) {
+
+ PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb);
+ PSRB_IO_CONTROL srbControl = (PSRB_IO_CONTROL)SrbGetDataBuffer(Srb);
+
+ UpdateFirmwareIoctlReturnCode(Srb);
+
+ StorPortEtwEvent8(ChannelExtension->AdapterExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciEtwEventUnitFirmwareDownloadComplete,
+ L"Firmware Download Completion",
+ STORPORT_ETW_EVENT_KEYWORD_IO,
+ StorportEtwLevelError,
+ StorportEtwEventOpcodeInfo,
+ (PSCSI_REQUEST_BLOCK)Srb,
+ L"SrbStatus",
+ Srb->SrbStatus,
+ L"ReturnCode",
+ (srbControl != NULL) ? (srbControl->ReturnCode) : (0),
+ L"FeaturesReg",
+ srbExtension->TaskFile.Current.bFeaturesReg,
+ L"SectorCountReg",
+ srbExtension->TaskFile.Current.bSectorCountReg,
+ L"DriveHeadReg",
+ srbExtension->TaskFile.Current.bDriveHeadReg,
+ L"CommandReg",
+ srbExtension->TaskFile.Current.bCommandReg,
+ NULL,
+ 0,
+ NULL,
+ 0);
+
+ }
+
+ return;
+}
+
VOID
AtaWriteBufferFirmwareDownload (
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
@@ -3128,11 +3413,14 @@ AtaWriteBufferFirmwareDownload (
_In_ PCDB Cdb
)
{
-
PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb);
+ PSRB_IO_CONTROL srbControl = NULL;
ULONG bufferOffset = 0;
ULONG dataLength = 0;
- UCHAR commandReg;
+ UCHAR commandReg = 0;
+ BOOLEAN invalidCommand = FALSE;
+
+ srbControl = (PSRB_IO_CONTROL)SrbGetDataBuffer(Srb);
bufferOffset = (ULONG)Cdb->WRITE_BUFFER.BufferOffset[0] << 16 |
(ULONG)Cdb->WRITE_BUFFER.BufferOffset[1] << 8 |
@@ -3146,6 +3434,8 @@ AtaWriteBufferFirmwareDownload (
((dataLength % ATA_BLOCK_SIZE) != 0)) {
// Report invalid command.
AhciSetSenseData(Srb, SRB_STATUS_INVALID_REQUEST, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_INVALID_CDB, 0);
+ srbControl->ReturnCode = FIRMWARE_STATUS_INVALID_PARAMETER;
+ invalidCommand = TRUE;
goto exit;
}
@@ -3157,6 +3447,8 @@ AtaWriteBufferFirmwareDownload (
(dataLength < ChannelExtension->DeviceExtension->FirmwareUpdate.DmMinTransferBlocks)) {
// Report invalid command.
AhciSetSenseData(Srb, SRB_STATUS_INVALID_REQUEST, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_INVALID_CDB, 0);
+ srbControl->ReturnCode = FIRMWARE_STATUS_INVALID_PARAMETER;
+ invalidCommand = TRUE;
goto exit;
}
@@ -3165,6 +3457,8 @@ AtaWriteBufferFirmwareDownload (
((Cdb->WRITE_BUFFER.ModeSpecific & SCSI_WRITE_BUFFER_MODE_0D_MODE_SPECIFIC_HR_ACT) != 0)) {
// Report invalid command.
AhciSetSenseData(Srb, SRB_STATUS_INVALID_REQUEST, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_INVALID_CDB, 0);
+ srbControl->ReturnCode = FIRMWARE_STATUS_INVALID_PARAMETER;
+ invalidCommand = TRUE;
goto exit;
}
}
@@ -3183,6 +3477,8 @@ AtaWriteBufferFirmwareDownload (
// Set up taskfile in SrbExtension.
srbExtension->AtaFunction = ATA_FUNCTION_ATA_COMMAND;
+ srbExtension->CompletionRoutine = AtaFirmwareDownloadCompletion;
+
SetCommandReg((&srbExtension->TaskFile.Current), commandReg);
SetFeaturesReg((&srbExtension->TaskFile.Current), 0x0E);
@@ -3201,6 +3497,37 @@ exit:
// If the ATA command completes without error and the ATA device returns a COUNT field set to 03h, then the
// SATL shall remember that the new microcode shall be activated by whichever event in table 48 occurs first.
+ if (invalidCommand) {
+
+ StorPortEtwEvent8(ChannelExtension->AdapterExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciEtwEventUnitFirmwareDownload,
+ L"Firmware Download",
+ STORPORT_ETW_EVENT_KEYWORD_IO,
+ StorportEtwLevelError,
+ StorportEtwEventOpcodeInfo,
+ (PSCSI_REQUEST_BLOCK)Srb,
+ L"BufferOffset",
+ bufferOffset,
+ L"DataLength",
+ dataLength,
+ L"MaxTransBlocks",
+ ChannelExtension->DeviceExtension->FirmwareUpdate.DmMaxTransferBlocks,
+ L"MinTransBlocks",
+ ChannelExtension->DeviceExtension->FirmwareUpdate.DmMinTransferBlocks,
+ L"Mode",
+ Cdb->WRITE_BUFFER.Mode,
+ L"ModeSpecific",
+ Cdb->WRITE_BUFFER.ModeSpecific,
+ L"CommandReg",
+ commandReg,
+ L"ReturnCode",
+ srbControl->ReturnCode);
+
+ }
+
+
+
return;
}
@@ -3216,6 +3543,38 @@ AtaFirmwareActivateCompletion (
//
if (Srb->SrbStatus == SRB_STATUS_SUCCESS) {
ChannelExtension->DeviceExtension->DeviceParameters.StateFlags.NeedUpdateIdentifyDeviceData = 1;
+ } else {
+
+ PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb);
+ PSRB_IO_CONTROL srbControl = (PSRB_IO_CONTROL)SrbGetDataBuffer(Srb);
+
+ UpdateFirmwareIoctlReturnCode(Srb);
+
+ StorPortEtwEvent8(ChannelExtension->AdapterExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciEtwEventUnitFirmwareActivateComplete,
+ L"Firmware Activate Completion",
+ STORPORT_ETW_EVENT_KEYWORD_IO,
+ StorportEtwLevelError,
+ StorportEtwEventOpcodeInfo,
+ (PSCSI_REQUEST_BLOCK)Srb,
+ L"SrbStatus",
+ Srb->SrbStatus,
+ L"ReturnCode",
+ (srbControl != NULL) ? (srbControl->ReturnCode) : (0),
+ L"FeaturesReg",
+ srbExtension->TaskFile.Current.bFeaturesReg,
+ L"SectorCountReg",
+ srbExtension->TaskFile.Current.bSectorCountReg,
+ L"DriveHeadReg",
+ srbExtension->TaskFile.Current.bDriveHeadReg,
+ L"CommandReg",
+ srbExtension->TaskFile.Current.bCommandReg,
+ NULL,
+ 0,
+ NULL,
+ 0);
+
}
return;
@@ -3231,6 +3590,9 @@ AtaWriteBufferFirmwareActivate (
{
PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb);
UCHAR commandReg;
+ PSRB_IO_CONTROL srbControl = NULL;
+
+ srbControl = (PSRB_IO_CONTROL)SrbGetDataBuffer(Srb);
if ((Cdb->WRITE_BUFFER.ModeSpecific != 0) ||
(Cdb->WRITE_BUFFER.BufferID != 0) ||
@@ -3243,6 +3605,33 @@ AtaWriteBufferFirmwareActivate (
// Report invalid command.
AhciSetSenseData(Srb, SRB_STATUS_INVALID_REQUEST, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_INVALID_CDB, 0);
+ srbControl->ReturnCode = FIRMWARE_STATUS_INVALID_PARAMETER;
+
+ StorPortEtwEvent8(ChannelExtension->AdapterExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciEtwEventUnitFirmwareActivate,
+ L"Firmware Activate",
+ STORPORT_ETW_EVENT_KEYWORD_IO,
+ StorportEtwLevelError,
+ StorportEtwEventOpcodeInfo,
+ (PSCSI_REQUEST_BLOCK)Srb,
+ L"Operation Code",
+ Cdb->WRITE_BUFFER.ModeSpecific,
+ L"Buffer ID",
+ Cdb->WRITE_BUFFER.BufferID,
+ L"Buffer Offset0",
+ Cdb->WRITE_BUFFER.BufferOffset[0],
+ L"Buffer Offset1",
+ Cdb->WRITE_BUFFER.BufferOffset[1],
+ L"Buffer Offset2",
+ Cdb->WRITE_BUFFER.BufferOffset[2],
+ L"ParaList Len0",
+ Cdb->WRITE_BUFFER.ParameterListLength[0],
+ L"ParaList Len1",
+ Cdb->WRITE_BUFFER.ParameterListLength[1],
+ L"ParaList Len2",
+ Cdb->WRITE_BUFFER.ParameterListLength[2]);
+
} else {
NT_ASSERT((SrbGetSrbFlags(Srb) & SRB_FLAGS_UNSPECIFIED_DIRECTION) == 0);
@@ -3292,6 +3681,716 @@ AtaWriteBufferRequest (
return STOR_STATUS_SUCCESS;
}
+VOID
+AtaGetPhysicalElementStatusCompletion (
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_ PSTORAGE_REQUEST_BLOCK Srb
+ )
+/*++
+ This is the completion point of Get Physical Element Status command for ATA devices.
+
+ This routine translates an ATA output of Get Physical Element Status command into
+ SCSI format if the command is successful.
+
+Arguments:
+
+ ChannelExtension
+ Srb
+
+Return Value:
+ None
+
+--*/
+{
+ PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb);
+
+ if (Srb->SrbStatus == SRB_STATUS_SUCCESS) {
+
+ ULONG srbDataBufferLength = SrbGetDataTransferLength(Srb);
+ ULONG transferLength = RequestGetDataTransferLength(Srb);
+ ULONG tempScsiBufferLength = 0;
+ ULONG tempAtaBufferLength = 0;
+
+ PATA_GET_PHYSICAL_ELEMENT_STATUS_PARAMETER_DATA ataDataBuffer = (PATA_GET_PHYSICAL_ELEMENT_STATUS_PARAMETER_DATA)srbExtension->DataBuffer;
+ PPHYSICAL_ELEMENT_STATUS_PARAMETER_DATA scsiDataBuffer = (PPHYSICAL_ELEMENT_STATUS_PARAMETER_DATA)SrbGetDataBuffer(Srb);
+
+ NT_ASSERT((srbExtension->DataBuffer != NULL) && (transferLength >= sizeof(ATA_GET_PHYSICAL_ELEMENT_STATUS_PARAMETER_DATA)));
+
+ //
+ // Translate ATA get physical element status data to SCSI format.
+ //
+ tempScsiBufferLength = sizeof(PHYSICAL_ELEMENT_STATUS_PARAMETER_DATA);
+ tempAtaBufferLength = sizeof(ATA_GET_PHYSICAL_ELEMENT_STATUS_PARAMETER_DATA);
+
+ REVERSE_BYTES(scsiDataBuffer->DescriptorCount, &ataDataBuffer->NumberOfDescriptors);
+ REVERSE_BYTES(scsiDataBuffer->ReturnedDescriptorCount, &ataDataBuffer->NumberOfDescriptorsReturned);
+ REVERSE_BYTES(scsiDataBuffer->ElementIdentifierBeingDepoped, &ataDataBuffer->ElementIdentifierBeingDepoped);
+
+ for (ULONG i = 0; i < ataDataBuffer->NumberOfDescriptorsReturned; ++i) {
+
+ if ((tempScsiBufferLength > srbDataBufferLength) || (tempAtaBufferLength > transferLength)) {
+ goto Exit;
+ }
+
+ scsiDataBuffer->Descriptors[i].PhysicalElementType = ataDataBuffer->Descriptors[i].PhysicalElementType;
+ scsiDataBuffer->Descriptors[i].PhysicalElementHealth = ataDataBuffer->Descriptors[i].PhysicalElementHealth;
+ REVERSE_BYTES(scsiDataBuffer->Descriptors[i].ElementIdentifier, &ataDataBuffer->Descriptors[i].ElementIdentifier);
+ REVERSE_BYTES_QUAD(scsiDataBuffer->Descriptors[i].AssociatedCapacity, &ataDataBuffer->Descriptors[i].AssociatedCapacity);
+
+ tempScsiBufferLength += sizeof(PHYSICAL_ELEMENT_STATUS_DATA_DESCRIPTOR);
+ tempAtaBufferLength += sizeof(ATA_PHYSICAL_ELEMENT_STATUS_DESCRIPTOR);
+ }
+ }
+
+Exit:
+
+ if (srbExtension->DataBuffer != NULL) {
+
+ // srbExtension->CompletionContext contains the allocated buffer size.
+ AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, (ULONG_PTR)srbExtension->CompletionContext, srbExtension->DataBuffer, srbExtension->DataBufferPhysicalAddress);
+ srbExtension->DataBuffer = NULL;
+ }
+
+ if (Srb->SrbStatus != SRB_STATUS_SUCCESS) {
+ StorPortEtwEvent8(ChannelExtension->AdapterExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciEtwEventUnitGetPhysicalElementStatusComplete,
+ L"Get Physical Element status",
+ STORPORT_ETW_EVENT_KEYWORD_IO,
+ StorportEtwLevelError,
+ StorportEtwEventOpcodeInfo,
+ (PSCSI_REQUEST_BLOCK)Srb,
+ L"SrbStatus",
+ Srb->SrbStatus,
+ L"ErrorReg",
+ ChannelExtension->ReceivedFIS->D2hRegisterFis.Error,
+ L"StatusReg",
+ ChannelExtension->ReceivedFIS->D2hRegisterFis.Status,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 0
+ );
+ }
+
+ return;
+}
+
+ULONG
+AtaGetPhysicalElementStatusRequest (
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_ PSTORAGE_REQUEST_BLOCK Srb,
+ _In_ PCDB Cdb
+ )
+/*++
+ This routine translates a SCSI - Get Physical Element Status command into
+ ATA - Get Physical Element Status command.
+
+Arguments:
+
+ ChannelExtension
+ Srb
+ Cdb
+
+Return Value:
+ ULONG - status
+
+--*/
+{
+ ULONG status = STOR_STATUS_SUCCESS;
+ PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb);
+ PVOID srbDataBuffer = SrbGetDataBuffer(Srb);
+ ULONG srbDataBufferLength = SrbGetDataTransferLength(Srb);
+ PVOID physicalElementStatusBuffer = NULL;
+ ULONG physicalElementStatusBufferSize = 0;
+ STOR_PHYSICAL_ADDRESS physicalElementStatusPhysicalAddress = {0};
+ PAHCI_H2D_REGISTER_FIS cfis = &srbExtension->Cfis;
+ ULONG tempUlong = 0;
+
+ if ((srbDataBuffer == NULL) ||
+ (srbDataBufferLength < sizeof(PHYSICAL_ELEMENT_STATUS_PARAMETER_DATA))) {
+
+ Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+ status = STOR_STATUS_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ srbExtension->AtaFunction = ATA_FUNCTION_ATA_CFIS_PAYLOAD;
+ srbExtension->Flags |= (ATA_FLAGS_48BIT_COMMAND | ATA_FLAGS_DATA_IN | ATA_FLAGS_USE_DMA);
+ srbExtension->CompletionRoutine = AtaGetPhysicalElementStatusCompletion;
+
+ //
+ // Set up ATA command.
+ //
+ cfis->Command = IDE_COMMAND_GET_PHYSICAL_ELEMENT_STATUS;
+
+ cfis->Feature7_0 = 0;
+ cfis->Feature15_8 = (Cdb->GET_PHYSICAL_ELEMENT_STATUS.Filter << 6) | (Cdb->GET_PHYSICAL_ELEMENT_STATUS.ReportType);
+
+ REVERSE_BYTES(&tempUlong, Cdb->GET_PHYSICAL_ELEMENT_STATUS.AllocationLength);
+
+ tempUlong = (tempUlong + (ATA_BLOCK_SIZE - 1)) / ATA_BLOCK_SIZE;
+ physicalElementStatusBufferSize = tempUlong * ATA_BLOCK_SIZE;
+
+ status = AhciAllocateDmaBuffer(ChannelExtension->AdapterExtension, physicalElementStatusBufferSize, (PVOID*)&physicalElementStatusBuffer, &physicalElementStatusPhysicalAddress);
+
+ if ((status != STOR_STATUS_SUCCESS) || (physicalElementStatusBuffer == NULL) ) {
+
+ Srb->SrbStatus = SRB_STATUS_ERROR;
+ status = STOR_STATUS_INSUFFICIENT_RESOURCES;
+ goto Done;
+ }
+
+ AhciZeroMemory((PCHAR)physicalElementStatusBuffer, physicalElementStatusBufferSize);
+
+ srbExtension->DataBuffer = physicalElementStatusBuffer;
+ srbExtension->DataBufferPhysicalAddress.QuadPart = physicalElementStatusPhysicalAddress.QuadPart;
+ srbExtension->DataTransferLength = physicalElementStatusBufferSize;
+ srbExtension->CompletionContext = (PVOID)physicalElementStatusBufferSize; // preserve the buffer size, it's needed for freeing the memory
+
+ srbExtension->LocalSgl.NumberOfElements = 1;
+ srbExtension->LocalSgl.List[0].PhysicalAddress.LowPart = physicalElementStatusPhysicalAddress.LowPart;
+ srbExtension->LocalSgl.List[0].PhysicalAddress.HighPart = physicalElementStatusPhysicalAddress.HighPart;
+ srbExtension->LocalSgl.List[0].Length = physicalElementStatusBufferSize; // preserve the buffer size, it's needed for freeing the memory
+ srbExtension->Sgl = &srbExtension->LocalSgl;
+
+ cfis->Count7_0 = (UCHAR)tempUlong;
+ cfis->Count15_8 = (UCHAR)(tempUlong >> 8);
+
+ REVERSE_BYTES(&tempUlong, Cdb->GET_PHYSICAL_ELEMENT_STATUS.StartingElement);
+ cfis->LBA7_0 = (UCHAR)((tempUlong & 0x000000ff) >> 0);
+ cfis->LBA15_8 = (UCHAR)((tempUlong & 0x0000ff00) >> 8);
+ cfis->LBA23_16 = (UCHAR)((tempUlong & 0x00ff0000) >> 16);
+ cfis->LBA31_24 = (UCHAR)((tempUlong & 0xff000000) >> 24);
+
+Done:
+
+ if (status != STOR_STATUS_SUCCESS) {
+ if (physicalElementStatusBuffer != NULL) {
+ AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, physicalElementStatusBufferSize, physicalElementStatusBuffer, physicalElementStatusPhysicalAddress);
+ }
+ srbExtension->DataBuffer = NULL;
+ }
+
+ return status;
+}
+
+VOID
+AtaRemoveElementAndTruncateCompletion (
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_ PSTORAGE_REQUEST_BLOCK Srb
+ )
+/*++
+ This is the completion point of Remove Element And Truncate command for ATA devices.
+
+Arguments:
+
+ ChannelExtension
+ Srb
+
+Return Value:
+ None
+
+--*/
+{
+ if (Srb->SrbStatus != SRB_STATUS_SUCCESS) {
+
+ StorPortEtwEvent8(ChannelExtension->AdapterExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciEtwEventUnitRemoveElementAndTruncateComplete,
+ L"Remove Element And Truncate",
+ STORPORT_ETW_EVENT_KEYWORD_IO,
+ StorportEtwLevelError,
+ StorportEtwEventOpcodeInfo,
+ (PSCSI_REQUEST_BLOCK)Srb,
+ L"SrbStatus",
+ Srb->SrbStatus,
+ L"ErrorReg",
+ ChannelExtension->ReceivedFIS->D2hRegisterFis.Error,
+ L"StatusReg",
+ ChannelExtension->ReceivedFIS->D2hRegisterFis.Status,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 0
+ );
+ }
+
+ return;
+}
+
+ULONG
+AtaRemoveElementAndTruncateRequest (
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_ PSTORAGE_REQUEST_BLOCK Srb,
+ _In_ PCDB Cdb
+ )
+/*++
+ This routine translates a SCSI - Remove Element and Truncate command into
+ ATA - Remove Element and Truncate command.
+
+Arguments:
+
+ ChannelExtension
+ Srb
+ Cdb
+
+Return Value:
+ ULONG - status
+
+--*/
+{
+ PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb);
+ PAHCI_H2D_REGISTER_FIS cfis = &srbExtension->Cfis;
+ ULONGLONG tempUlonglong = 0;
+
+ UNREFERENCED_PARAMETER(ChannelExtension);
+
+ //
+ // According to SAT-5 Repurposing Depopulation Translation:
+ // - If requested capacity is 0, SATL shall set the ATA REQUESTED MAX field to 0;
+ // - If requested capacity is 1, remove element and truncate command shall be terminated with a checked condition status
+ // with the sense key set to illegal request and additional sense code set to INVALID FIELD IN CDB;
+ // - If requested capacity is greater than 1, SATL shall set ATA REQUESTED MAX field in the ATA REMOVE ELEMENT AND
+ // TRUNCATE command to the value of the REQUESTED CAPACITY field minus 1.
+ //
+ REVERSE_BYTES_QUAD(&tempUlonglong, Cdb->REMOVE_ELEMENT_AND_TRUNCATE.RequestedCapacity);
+ if (tempUlonglong == 1) {
+
+ AhciSetSenseData(Srb, SRB_STATUS_INVALID_REQUEST, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_INVALID_CDB, 0);
+ return STOR_STATUS_INVALID_DEVICE_REQUEST;
+ }
+
+ tempUlonglong = (tempUlonglong == 0) ? (0) : (tempUlonglong - 1);
+ cfis->LBA7_0 = (UCHAR)((tempUlonglong & 0x00000000000000ff) >> 0);
+ cfis->LBA15_8 = (UCHAR)((tempUlonglong & 0x000000000000ff00) >> 8);
+ cfis->LBA23_16 = (UCHAR)((tempUlonglong & 0x0000000000ff0000) >> 16);
+ cfis->LBA31_24 = (UCHAR)((tempUlonglong & 0x00000000ff000000) >> 24);
+ cfis->LBA39_32 = (UCHAR)((tempUlonglong & 0x000000ff00000000) >> 32);
+ cfis->LBA47_40 = (UCHAR)((tempUlonglong & 0x0000ff0000000000) >> 40);
+
+ srbExtension->AtaFunction = ATA_FUNCTION_ATA_CFIS_PAYLOAD;
+ srbExtension->Flags |= ATA_FLAGS_48BIT_COMMAND;
+ srbExtension->CompletionRoutine = AtaRemoveElementAndTruncateCompletion;
+
+ //
+ // Set up ATA command.
+ //
+ cfis->Command = IDE_COMMAND_REMOVE_ELEMENT_AND_TRUNCATE;
+
+ cfis->Feature7_0 = Cdb->REMOVE_ELEMENT_AND_TRUNCATE.ElementIdentifier[1];
+ cfis->Feature15_8 = Cdb->REMOVE_ELEMENT_AND_TRUNCATE.ElementIdentifier[0];
+ cfis->Count7_0 = Cdb->REMOVE_ELEMENT_AND_TRUNCATE.ElementIdentifier[3];
+ cfis->Count15_8 = Cdb->REMOVE_ELEMENT_AND_TRUNCATE.ElementIdentifier[2];
+
+ return STOR_STATUS_SUCCESS;
+}
+
+VOID
+AtaGetDeviceCurrentInternalStatusDataHeaderCompletion(
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_ PSTORAGE_REQUEST_BLOCK Srb
+ )
+/*++
+ This is the completion point of Read Log Ext command that is used to read device
+ internal data header for ATA devices.
+
+Arguments:
+
+ ChannelExtension - Channel Extension.
+
+ Srb - Supplies a pointer to the srb request.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ if (Srb->SrbStatus == SRB_STATUS_SUCCESS) {
+
+ PCURRENT_DEVICE_INTERNAL_STATUS_LOG ataCurrentDeviceInternalStatusDataHeader = NULL;
+ PERROR_HISTORY_DIRECTORY scsiErrorHistoryDirectory = (PERROR_HISTORY_DIRECTORY)SrbGetDataBuffer(Srb);
+
+ ULONG transferLength = RequestGetDataTransferLength(Srb);
+ UCHAR tmpT10VendorId[] = "ATA ";
+
+ NT_ASSERT((scsiErrorHistoryDirectory != NULL) &&
+ (transferLength >= sizeof(CURRENT_DEVICE_INTERNAL_STATUS_LOG)) &&
+ (SrbGetDataTransferLength(Srb) >= sizeof(ERROR_HISTORY_DIRECTORY)));
+
+ AhciZeroMemory((PVOID)scsiErrorHistoryDirectory, sizeof(ERROR_HISTORY_DIRECTORY));
+
+ if (transferLength < sizeof(CURRENT_DEVICE_INTERNAL_STATUS_LOG)) {
+ NT_ASSERT(FALSE);
+ return;
+ }
+
+ //
+ // Parse current device internal status data header(page 0) content.
+ //
+ ataCurrentDeviceInternalStatusDataHeader = (PCURRENT_DEVICE_INTERNAL_STATUS_LOG)ChannelExtension->DeviceExtension->ReadLogExtPageData;
+ NT_ASSERT(ataCurrentDeviceInternalStatusDataHeader->LogAddress == CURRENT_DEVICE_INTERNAL_STATUS_DATA_LOG_ADDRESS);
+
+ NT_ASSERT(sizeof(tmpT10VendorId) >= SCSI_VENDOR_ID_LENGTH);
+ StorPortCopyMemory(scsiErrorHistoryDirectory->T10VendorId, tmpT10VendorId, SCSI_VENDOR_ID_LENGTH);
+
+ if (ataCurrentDeviceInternalStatusDataHeader->Area3LastLogPage > 0) {
+
+ USHORT errorhistoryDirectoryEntryLength = (USHORT)sizeof(ERROR_HISTORY_DIRECTORY_ENTRY);
+ ULONG maxAvailableLength = (ataCurrentDeviceInternalStatusDataHeader->Area3LastLogPage + 1UL) * IDE_GP_LOG_SECTOR_SIZE;
+ REVERSE_BYTES_SHORT(scsiErrorHistoryDirectory->DirectoryLength, &errorhistoryDirectoryEntryLength);
+ scsiErrorHistoryDirectory->ErrorHistoryDirectoryList[0].SupportedBufferId = BUFFER_ID_RETURN_ERROR_HISTORY_MINIMUM_THRESHOLD;
+ scsiErrorHistoryDirectory->ErrorHistoryDirectoryList[0].BufferFormat = BUFFER_FORMAT_CURRENT_INTERNAL_STATUS_DATA;
+ scsiErrorHistoryDirectory->ErrorHistoryDirectoryList[0].BufferSource = BUFFER_SOURCE_CREATED_DUE_TO_CURRENT_COMMAND;
+ REVERSE_BYTES(scsiErrorHistoryDirectory->ErrorHistoryDirectoryList[0].MaxAvailableLength, &maxAvailableLength);
+ }
+
+ SrbSetDataTransferLength(Srb, sizeof(ERROR_HISTORY_DIRECTORY));
+
+ } else {
+
+ PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb);
+
+ StorPortEtwEvent8(ChannelExtension->AdapterExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciEtwEventUnitGetInternalStatusDataHeaderComplete,
+ L"Internal Status Data Header",
+ STORPORT_ETW_EVENT_KEYWORD_IO,
+ StorportEtwLevelError,
+ StorportEtwEventOpcodeInfo,
+ (PSCSI_REQUEST_BLOCK)Srb,
+ L"SrbStatus",
+ Srb->SrbStatus,
+ L"ErrorReg",
+ srbExtension->TaskFile.Current.bFeaturesReg,
+ L"StatusReg",
+ srbExtension->TaskFile.Current.bCommandReg,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 0
+ );
+ }
+
+ return;
+}
+
+ULONG
+AtaGetDeviceCurrentInternalStatusDataHeader(
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_ PSTORAGE_REQUEST_BLOCK Srb,
+ _In_ PCDB Cdb
+ )
+/*++
+ This routine translates a SCSI - Read Buffer command(Mode: 0x1c Error History Directory)
+ into ATA - Read Log Ext command to read device current internal status data header.
+
+Arguments:
+
+ ChannelExtension - Channel Extension.
+
+ Srb - Supplies a pointer to the srb request.
+
+ Cdb - SCSI Command Descriptor Block carried by Srb.
+
+Return Value:
+
+ ULONG - status.
+
+--*/
+{
+ PVOID srbDataBuffer = SrbGetDataBuffer(Srb);
+ ULONG srbDataBufferLength = SrbGetDataTransferLength(Srb);
+
+ UNREFERENCED_PARAMETER(Cdb);
+
+ if ((srbDataBuffer == NULL) || (srbDataBufferLength < sizeof(ERROR_HISTORY_DIRECTORY))) {
+
+ Srb->SrbStatus = SRB_STATUS_BAD_SRB_BLOCK_LENGTH;
+ return STOR_STATUS_INVALID_PARAMETER;
+ }
+
+ IssueReadLogExtCommand(ChannelExtension,
+ Srb,
+ IDE_GP_LOG_CURRENT_DEVICE_INTERNAL_STATUS,
+ 0, // Starting page number
+ 1, // Number of sectors
+ 1, // Features field set to 1
+ &ChannelExtension->DeviceExtension->ReadLogExtPageDataPhysicalAddress,
+ (PVOID)ChannelExtension->DeviceExtension->ReadLogExtPageData,
+ AtaGetDeviceCurrentInternalStatusDataHeaderCompletion
+ );
+
+ return STOR_STATUS_SUCCESS;
+}
+
+VOID
+AtaGetDeviceCurrentInternalStatusDataCompletion(
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_ PSTORAGE_REQUEST_BLOCK Srb
+ )
+/*++
+ This is the completion point of Read Log Ext command that is used to read device
+ internal data for ATA devices.
+
+Arguments:
+
+ ChannelExtension - Channel Extension.
+
+ Srb - Supplies a pointer to the srb request.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb);
+ ULONG_PTR currentLogPageOffset = (ULONG_PTR)srbExtension->CompletionContext;
+ BOOLEAN requestFailed = FALSE;
+
+ if (Srb->SrbStatus == SRB_STATUS_SUCCESS) {
+
+ PCURRENT_DEVICE_INTERNAL_STATUS_LOG ataCurrentDeviceInternalStatusDataHeader = NULL;
+ PCURRENT_INTERNAL_STATUS_PARAMETER_DATA scsiCurrentInternalStatusData = (PCURRENT_INTERNAL_STATUS_PARAMETER_DATA)SrbGetDataBuffer(Srb);
+
+ ULONG srbDataBufferLength = SrbGetDataTransferLength(Srb);
+ ULONG transferLength = RequestGetDataTransferLength(Srb);
+
+ NT_ASSERT((srbExtension->DataBuffer != NULL) &&
+ (srbExtension->DataTransferLength >= sizeof(CURRENT_DEVICE_INTERNAL_STATUS_LOG)) &&
+ (scsiCurrentInternalStatusData != NULL) &&
+ (srbDataBufferLength >= transferLength));
+
+ NT_ASSERT((transferLength % IDE_GP_LOG_SECTOR_SIZE) == 0);
+
+ if (!IsDumpMode(ChannelExtension->AdapterExtension)) {
+ AhciZeroMemory((PVOID)scsiCurrentInternalStatusData, srbDataBufferLength);
+ }
+
+ //
+ // Parse current device internal status data header(page 0) and/or copy other pages back to SRB databuffer.
+ //
+ ataCurrentDeviceInternalStatusDataHeader = (PCURRENT_DEVICE_INTERNAL_STATUS_LOG)srbExtension->DataBuffer;
+
+ if (currentLogPageOffset == 0) {
+
+ if (transferLength >= sizeof(CURRENT_DEVICE_INTERNAL_STATUS_LOG)) {
+
+ NT_ASSERT(ataCurrentDeviceInternalStatusDataHeader->LogAddress == CURRENT_DEVICE_INTERNAL_STATUS_DATA_LOG_ADDRESS);
+ NT_ASSERT((ataCurrentDeviceInternalStatusDataHeader->Area2LastLogPage >= ataCurrentDeviceInternalStatusDataHeader->Area1LastLogPage) &&
+ (ataCurrentDeviceInternalStatusDataHeader->Area3LastLogPage >= ataCurrentDeviceInternalStatusDataHeader->Area2LastLogPage));
+
+ if (!IsDumpMode(ChannelExtension->AdapterExtension)) {
+
+ REVERSE_BYTES(scsiCurrentInternalStatusData->IEEECompanyId, &ataCurrentDeviceInternalStatusDataHeader->OrganizationID);
+ REVERSE_BYTES_SHORT(scsiCurrentInternalStatusData->CurrentInternalStatusDataSetOneLength, &ataCurrentDeviceInternalStatusDataHeader->Area1LastLogPage);
+ REVERSE_BYTES_SHORT(scsiCurrentInternalStatusData->CurrentInternalStatusDataSetTwoLength, &ataCurrentDeviceInternalStatusDataHeader->Area2LastLogPage);
+ REVERSE_BYTES_SHORT(scsiCurrentInternalStatusData->CurrentInternalStatusDataSetThreeLength, &ataCurrentDeviceInternalStatusDataHeader->Area3LastLogPage);
+ scsiCurrentInternalStatusData->NewSavedDataAvailable = ataCurrentDeviceInternalStatusDataHeader->SavedDataAvailable;
+ scsiCurrentInternalStatusData->SavedDataGenerationNumber = ataCurrentDeviceInternalStatusDataHeader->SavedDataGenerationNumber;
+ StorPortCopyMemory(scsiCurrentInternalStatusData->CurrentReasonIdentifier,
+ ataCurrentDeviceInternalStatusDataHeader->ReasonIdentifier,
+ sizeof(scsiCurrentInternalStatusData->CurrentReasonIdentifier)
+ );
+ } else {
+
+ //
+ // Reorder in place if this is dump mode.
+ //
+ REVERSE_LONG(&ataCurrentDeviceInternalStatusDataHeader->OrganizationID);
+ REVERSE_SHORT(&ataCurrentDeviceInternalStatusDataHeader->Area1LastLogPage);
+ REVERSE_SHORT(&ataCurrentDeviceInternalStatusDataHeader->Area2LastLogPage);
+ REVERSE_SHORT(&ataCurrentDeviceInternalStatusDataHeader->Area3LastLogPage);
+ }
+ } else {
+
+ NT_ASSERT(FALSE);
+ requestFailed = TRUE;
+ goto Exit;
+ }
+
+ //
+ // Assume that size of this log hadn't changed since we read the directory.
+ //
+ NT_ASSERT(transferLength <=
+ (sizeof(CURRENT_DEVICE_INTERNAL_STATUS_LOG) + (ULONG)(ataCurrentDeviceInternalStatusDataHeader->Area3LastLogPage) * IDE_GP_LOG_SECTOR_SIZE));
+
+ if ((transferLength > sizeof(CURRENT_DEVICE_INTERNAL_STATUS_LOG)) &&
+ (srbDataBufferLength >= transferLength) &&
+ (!IsDumpMode(ChannelExtension->AdapterExtension))) {
+ StorPortCopyMemory(scsiCurrentInternalStatusData->CurrentInternalStatusData,
+ (PUCHAR)(ataCurrentDeviceInternalStatusDataHeader + 1),
+ (transferLength - IDE_GP_LOG_SECTOR_SIZE));
+ }
+ } else {
+ if ((transferLength > sizeof(CURRENT_DEVICE_INTERNAL_STATUS_LOG)) &&
+ (srbDataBufferLength >= transferLength) &&
+ (!IsDumpMode(ChannelExtension->AdapterExtension))) {
+ StorPortCopyMemory((PUCHAR)scsiCurrentInternalStatusData,
+ (PUCHAR)ataCurrentDeviceInternalStatusDataHeader,
+ transferLength);
+ }
+ }
+
+ SrbSetDataTransferLength(Srb, transferLength);
+ }
+
+Exit:
+
+ if (requestFailed) {
+
+ StorPortEtwEvent8(ChannelExtension->AdapterExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciEtwEventUnitGetInternalStatusDataComplete,
+ L"Internal Status Data",
+ STORPORT_ETW_EVENT_KEYWORD_IO,
+ StorportEtwLevelError,
+ StorportEtwEventOpcodeInfo,
+ (PSCSI_REQUEST_BLOCK)Srb,
+ L"SrbStatus",
+ Srb->SrbStatus,
+ L"ErrorReg",
+ srbExtension->TaskFile.Current.bFeaturesReg,
+ L"StatusReg",
+ srbExtension->TaskFile.Current.bCommandReg,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 0
+ );
+ }
+
+ if ((srbExtension->DataBuffer != NULL) && !IsDumpMode(ChannelExtension->AdapterExtension)) {
+
+ AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, (ULONG_PTR)srbExtension->DataTransferLength, srbExtension->DataBuffer, srbExtension->DataBufferPhysicalAddress);
+ srbExtension->DataBuffer = NULL;
+ }
+
+ return;
+}
+
+ULONG
+AtaGetDeviceCurrentInternalStatusData(
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_ PSTORAGE_REQUEST_BLOCK Srb,
+ _In_ PCDB Cdb
+ )
+/*++
+ This routine translates a SCSI - Read Buffer command(Mode: 0x1c Error History)
+ into ATA - Read Log Ext command to read device current internal status data.
+
+Arguments:
+
+ ChannelExtension - Channel Extension.
+
+ Srb - Supplies a pointer to the srb request.
+
+ Cdb - SCSI Command Descriptor Block carried by Srb.
+
+Return Value:
+
+ ULONG - status.
+
+--*/
+{
+ ULONG status = STOR_STATUS_SUCCESS;
+ PVOID srbDataBuffer = SrbGetDataBuffer(Srb);
+ ULONG srbDataBufferLength = SrbGetDataTransferLength(Srb);
+ PVOID internalStatusBuffer = NULL;
+ STOR_PHYSICAL_ADDRESS internalStatusBufferPhysicalAddress = {0};
+ ULONG bufferSize = 0;
+ ULONG bufferSizeDumpMode = 0;
+ LONGLONG bufferOffset = 0;
+ ULONG tempUlong = 0;
+ PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb);
+
+ if ((srbDataBuffer == NULL) || (srbDataBufferLength < (ULONG)FIELD_OFFSET(CURRENT_INTERNAL_STATUS_PARAMETER_DATA, CurrentInternalStatusData))) {
+
+ Srb->SrbStatus = SRB_STATUS_BAD_SRB_BLOCK_LENGTH;
+ status = STOR_STATUS_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ REVERSE_BYTES(&tempUlong, Cdb->READ_BUFFER_16.AllocationLength);
+ bufferSize = tempUlong * IDE_GP_LOG_SECTOR_SIZE;
+ REVERSE_BYTES_QUAD(&bufferOffset, Cdb->READ_BUFFER_16.BufferOffset);
+
+ if (!IsDumpMode(ChannelExtension->AdapterExtension)) {
+ status = AhciAllocateDmaBuffer(ChannelExtension->AdapterExtension, bufferSize, &internalStatusBuffer, &internalStatusBufferPhysicalAddress);
+ if ((status != STOR_STATUS_SUCCESS) || (internalStatusBuffer == NULL) ) {
+
+ Srb->SrbStatus = SRB_STATUS_ERROR;
+ status = STOR_STATUS_INSUFFICIENT_RESOURCES;
+ goto Done;
+ }
+ } else {
+ internalStatusBufferPhysicalAddress = StorPortGetPhysicalAddress(ChannelExtension->AdapterExtension, NULL, srbDataBuffer, &bufferSizeDumpMode);
+ if ((internalStatusBufferPhysicalAddress.QuadPart == 0) || (bufferSizeDumpMode == 0)) {
+
+ Srb->SrbStatus = SRB_STATUS_ERROR;
+ status = STOR_STATUS_INSUFFICIENT_RESOURCES;
+ goto Done;
+ }
+ internalStatusBuffer = srbDataBuffer;
+ bufferSize = min(bufferSize, bufferSizeDumpMode);
+ bufferSize = ALIGN_DOWN_BY(bufferSize, IDE_GP_LOG_SECTOR_SIZE);
+ }
+
+ AhciZeroMemory((PCHAR)internalStatusBuffer, bufferSize);
+ AhciZeroMemory((PCHAR)srbExtension, sizeof(AHCI_SRB_EXTENSION));
+
+ srbExtension->DataTransferLength = bufferSize;
+ srbExtension->CompletionContext = (PVOID)((ULONG)(bufferOffset / IDE_GP_LOG_SECTOR_SIZE));
+
+ IssueReadLogExtCommand(ChannelExtension,
+ Srb,
+ IDE_GP_LOG_CURRENT_DEVICE_INTERNAL_STATUS,
+ (USHORT)(bufferOffset / IDE_GP_LOG_SECTOR_SIZE), // Starting page number
+ (USHORT)tempUlong, // Number of sectors
+ 1, // Features field set to 1
+ &internalStatusBufferPhysicalAddress,
+ (PVOID)internalStatusBuffer,
+ AtaGetDeviceCurrentInternalStatusDataCompletion
+ );
+
+ return status;
+
+Done:
+
+ if ((internalStatusBuffer != NULL) && !IsDumpMode(ChannelExtension->AdapterExtension)) {
+ AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, bufferSize, internalStatusBuffer, internalStatusBufferPhysicalAddress);
+ internalStatusBuffer = NULL;
+ }
+
+ return status;
+}
+
UCHAR
AtaMapError(
@@ -3884,6 +4983,7 @@ Return Value:
deviceParameters->MaximumLun = 0;
deviceParameters->ScsiDeviceType = DIRECT_ACCESS_DEVICE;
+
deviceParameters->StateFlags.RemovableMedia = identifyDeviceData->GeneralConfiguration.RemovableMedia;
deviceParameters->MaxDeviceQueueDepth = min(ChannelExtension->MaxPortQueueDepth, (UCHAR)identifyDeviceData->QueueDepth);
@@ -3937,15 +5037,15 @@ Return Value:
// Fill some firmware support information.
//
if (identifyDeviceData->MinBlocksPerDownloadMicrocodeMode03 > 0) {
- ChannelExtension->DeviceExtension->FirmwareUpdate.DmMinTransferBlocks = (USHORT)min(identifyDeviceData->MinBlocksPerDownloadMicrocodeMode03, AHCI_MAX_TRANSFER_LENGTH / ATA_BLOCK_SIZE);
+ ChannelExtension->DeviceExtension->FirmwareUpdate.DmMinTransferBlocks = (USHORT)min(identifyDeviceData->MinBlocksPerDownloadMicrocodeMode03, AHCI_MAX_TRANSFER_LENGTH_DEFAULT / ATA_BLOCK_SIZE);
} else {
ChannelExtension->DeviceExtension->FirmwareUpdate.DmMinTransferBlocks = 1;
}
if (identifyDeviceData->MaxBlocksPerDownloadMicrocodeMode03 > 0) {
- ChannelExtension->DeviceExtension->FirmwareUpdate.DmMaxTransferBlocks = (USHORT)min(identifyDeviceData->MaxBlocksPerDownloadMicrocodeMode03, AHCI_MAX_TRANSFER_LENGTH / ATA_BLOCK_SIZE);
+ ChannelExtension->DeviceExtension->FirmwareUpdate.DmMaxTransferBlocks = (USHORT)min(identifyDeviceData->MaxBlocksPerDownloadMicrocodeMode03, AHCI_MAX_TRANSFER_LENGTH_DEFAULT / ATA_BLOCK_SIZE);
} else {
- ChannelExtension->DeviceExtension->FirmwareUpdate.DmMaxTransferBlocks = AHCI_MAX_TRANSFER_LENGTH / ATA_BLOCK_SIZE;
+ ChannelExtension->DeviceExtension->FirmwareUpdate.DmMaxTransferBlocks = AHCI_MAX_TRANSFER_LENGTH_DEFAULT / ATA_BLOCK_SIZE;
}
}
@@ -4062,7 +5162,7 @@ IOCTLtoATA(
nvCacheRequest = (PNVCACHE_REQUEST_BLOCK)(srbControl + 1);
if ( ((srbDataBufferLength - sizeof(SRB_IO_CONTROL) - sizeof(NVCACHE_REQUEST_BLOCK)) < nvCacheRequest->DataBufSize) ||
- (nvCacheRequest->DataBufSize > AHCI_MAX_TRANSFER_LENGTH) ) {
+ (nvCacheRequest->DataBufSize > AHCI_MAX_TRANSFER_LENGTH_DEFAULT) ) {
nvCacheRequest->NRBStatus = NRB_INVALID_PARAMETER;
Srb->SrbStatus = SRB_STATUS_BAD_SRB_BLOCK_LENGTH;
@@ -4073,7 +5173,6 @@ IOCTLtoATA(
// process NVCACHE request according to function
switch (nvCacheRequest->Function) {
-
default:
status = NVCacheGeneric (ChannelExtension, Srb);
break;
@@ -4083,8 +5182,6 @@ IOCTLtoATA(
break;
}
-
-
case IOCTL_SCSI_MINIPORT_DSM_GENERAL:
status = DsmGeneralIoctlProcess(ChannelExtension, Srb);
break;
@@ -4129,6 +5226,19 @@ IOCTLtoATA(
break;
}
+ StorPortEtwEvent2(ChannelExtension->AdapterExtension,
+ (PSTOR_ADDRESS) &(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciEtwEventBuildIO,
+ L"IOCTLtoATA finished",
+ STORPORT_ETW_EVENT_KEYWORD_COMMAND_TRACE,
+ StorportEtwLevelInformational,
+ StorportEtwEventOpcodeInfo,
+ (PSCSI_REQUEST_BLOCK)Srb,
+ L"SrbStatus",
+ Srb->SrbStatus,
+ L"SrbControl",
+ srbControl->ControlCode);
+
return status;
}
@@ -4491,6 +5601,7 @@ NVCacheGeneric(
ULONG srbDataBufferLength = SrbGetDataTransferLength(Srb);
ULONG srbFlags = SrbGetSrbFlags(Srb);
PVOID resultBuffer = NULL;
+ PHYSICAL_ADDRESS resultBufferPhysicalAddress = {0};
srbExtension = GetSrbExtension(Srb);
srbControl = (PSRB_IO_CONTROL)SrbGetDataBuffer(Srb);
@@ -4586,7 +5697,8 @@ NVCacheGeneric(
//
status = AhciAllocateDmaBuffer(ChannelExtension->AdapterExtension,
sizeof(ATA_TASK_FILE),
- &resultBuffer);
+ &resultBuffer,
+ &resultBufferPhysicalAddress);
if ( (status != STOR_STATUS_SUCCESS) ||
(resultBuffer == NULL) ) {
@@ -4599,6 +5711,7 @@ NVCacheGeneric(
AhciZeroMemory((PCHAR)resultBuffer, sizeof(ATA_TASK_FILE));
srbExtension->ResultBuffer = resultBuffer;
+ srbExtension->ResultBufferPhysicalAddress.QuadPart = resultBufferPhysicalAddress.QuadPart;
srbExtension->ResultBufferLength = sizeof(ATA_TASK_FILE);
//
@@ -4697,7 +5810,7 @@ HybridInfoCompletion(
0);
}
- AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, ATA_BLOCK_SIZE, srbExtension->DataBuffer);
+ AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, ATA_BLOCK_SIZE, srbExtension->DataBuffer, srbExtension->DataBufferPhysicalAddress);
StorPortDebugPrint(3, "StorAHCI - Hybrid: Port %02d - Hybrid Info log read failed. \n", ChannelExtension->PortNumber);
return;
}
@@ -4815,7 +5928,7 @@ HybridInfoCompletion(
hybridInfo->Priorities.DirtyThresholdHigh);
}
- AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, ATA_BLOCK_SIZE, srbExtension->DataBuffer);
+ AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, ATA_BLOCK_SIZE, srbExtension->DataBuffer, srbExtension->DataBufferPhysicalAddress);
StorPortDebugPrint(3, "StorAHCI - Hybrid: Port %02d - Hybrid Info log read successfully. \n", ChannelExtension->PortNumber);
@@ -4897,13 +6010,12 @@ Return Value:
} else {
PVOID logPageBuffer = NULL;
- STOR_PHYSICAL_ADDRESS logPagePhysialAddress;
- ULONG tempLength;
+ STOR_PHYSICAL_ADDRESS logPagePhysicalAddress;
//
// We need to allocate a new data buffer for log page
//
- status = AhciAllocateDmaBuffer(ChannelExtension->AdapterExtension, ATA_BLOCK_SIZE, &logPageBuffer);
+ status = AhciAllocateDmaBuffer(ChannelExtension->AdapterExtension, ATA_BLOCK_SIZE, &logPageBuffer, &logPagePhysicalAddress);
if ( (status != STOR_STATUS_SUCCESS) || (logPageBuffer == NULL) ) {
//
@@ -4916,7 +6028,6 @@ Return Value:
}
AhciZeroMemory((PCHAR)logPageBuffer, ATA_BLOCK_SIZE);
- logPagePhysialAddress = StorPortGetPhysicalAddress(ChannelExtension->AdapterExtension, NULL, (PVOID)logPageBuffer, &tempLength);
//
// Note that logPageBuffer will be released in completion routine.
@@ -4927,7 +6038,7 @@ Return Value:
0,
1,
0, // feature field
- &logPagePhysialAddress,
+ &logPagePhysicalAddress,
logPageBuffer,
HybridInfoCompletion
);
@@ -6480,7 +7591,7 @@ Return Value:
}
if (buffer != NULL) {
- AhciFreeDmaBuffer((PVOID)ChannelExtension->AdapterExtension, evictContext->AllocatedBufferLength, buffer);
+ AhciFreeDmaBuffer((PVOID)ChannelExtension->AdapterExtension, evictContext->AllocatedBufferLength, buffer, srbExtension->DataBufferPhysicalAddress);
}
if (evictContext != NULL) {
@@ -6517,7 +7628,7 @@ HybridEvict(
ULONG i;
PVOID buffer = NULL; // DMA buffer allocated for EVICT command
- STOR_PHYSICAL_ADDRESS bufferPhysicalAddress;
+ STOR_PHYSICAL_ADDRESS bufferPhysicalAddress = {0};
logicalSectorSize = BytesPerLogicalSector(&ChannelExtension->DeviceExtension->DeviceParameters);
@@ -6644,7 +7755,7 @@ HybridEvict(
//
// allocate DMA buffer, this buffer will be used to store ATA LBA Ranges for EVICT command
//
- status = AhciAllocateDmaBuffer((PVOID)ChannelExtension->AdapterExtension, evictContext->AllocatedBufferLength, &buffer);
+ status = AhciAllocateDmaBuffer((PVOID)ChannelExtension->AdapterExtension, evictContext->AllocatedBufferLength, &buffer, &bufferPhysicalAddress);
if ( (status != STOR_STATUS_SUCCESS) || (buffer == NULL) ) {
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
@@ -6660,10 +7771,10 @@ HybridEvict(
srbExtension->AtaFunction = ATA_FUNCTION_ATA_CFIS_PAYLOAD;
srbExtension->Flags |= ATA_FLAGS_DATA_OUT;
srbExtension->DataBuffer = buffer;
+ srbExtension->DataBufferPhysicalAddress.QuadPart = bufferPhysicalAddress.QuadPart;
srbExtension->DataTransferLength = evictContext->AllocatedBufferLength;
srbExtension->CompletionContext = (PVOID)evictContext;
- bufferPhysicalAddress = StorPortGetPhysicalAddress(ChannelExtension->AdapterExtension, NULL, buffer, &i);
srbExtension->LocalSgl.NumberOfElements = 1;
srbExtension->LocalSgl.List[0].PhysicalAddress.LowPart = bufferPhysicalAddress.LowPart;
srbExtension->LocalSgl.List[0].PhysicalAddress.HighPart = bufferPhysicalAddress.HighPart;
@@ -6703,7 +7814,7 @@ Exit:
//
if (status != STOR_STATUS_SUCCESS) {
if (buffer != NULL) {
- AhciFreeDmaBuffer((PVOID)ChannelExtension->AdapterExtension, evictContext->AllocatedBufferLength, buffer);
+ AhciFreeDmaBuffer((PVOID)ChannelExtension->AdapterExtension, evictContext->AllocatedBufferLength, buffer, bufferPhysicalAddress);
}
if (evictContext != NULL) {
@@ -6736,9 +7847,9 @@ Return Value:
--*/
{
ULONG status = STOR_STATUS_SUCCESS;
- PSRB_IO_CONTROL srbControl;
- PFIRMWARE_REQUEST_BLOCK firmwareRequest;
- PSTORAGE_FIRMWARE_INFO_V2 firmwareInfo;
+ PSRB_IO_CONTROL srbControl = NULL;
+ PFIRMWARE_REQUEST_BLOCK firmwareRequest = NULL;
+ PSTORAGE_FIRMWARE_INFO_V2 firmwareInfo = NULL;
srbControl = (PSRB_IO_CONTROL)SrbGetDataBuffer(Srb);
@@ -6748,7 +7859,7 @@ Return Value:
srbControl->ReturnCode = FIRMWARE_STATUS_INVALID_PARAMETER;
Srb->SrbStatus = SRB_STATUS_BAD_SRB_BLOCK_LENGTH;
status = STOR_STATUS_INVALID_PARAMETER;
- return status;
+ goto Exit;
}
//
@@ -6764,7 +7875,7 @@ Return Value:
srbControl->ReturnCode = FIRMWARE_STATUS_INVALID_PARAMETER;
Srb->SrbStatus = SRB_STATUS_BAD_SRB_BLOCK_LENGTH;
status = STOR_STATUS_INVALID_PARAMETER;
- return status;
+ goto Exit;
}
AhciZeroMemory((PCHAR)firmwareInfo, firmwareRequest->DataBufferLength);
@@ -6807,6 +7918,37 @@ Return Value:
status = STOR_STATUS_SUCCESS;
}
+Exit:
+
+ if (status != STOR_STATUS_SUCCESS) {
+
+ StorPortEtwEvent8(ChannelExtension->AdapterExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciEtwEventUnitFirmwareInfo,
+ L"Get Firmware Info",
+ STORPORT_ETW_EVENT_KEYWORD_IO,
+ StorportEtwLevelError,
+ StorportEtwEventOpcodeInfo,
+ (PSCSI_REQUEST_BLOCK)Srb,
+ L"SrbStatus",
+ Srb->SrbStatus,
+ L"Status",
+ status,
+ L"DataBufferLen",
+ firmwareRequest->DataBufferLength,
+ L"ReturnCode",
+ srbControl->ReturnCode,
+ L"Version",
+ (firmwareInfo == NULL) ? (0) : (firmwareInfo->Version),
+ L"Size",
+ (firmwareInfo == NULL) ? (0) : (firmwareInfo->Size),
+ L"UpgradeSupport",
+ (firmwareInfo == NULL) ? (0) : (firmwareInfo->UpgradeSupport),
+ NULL,
+ 0);
+
+ }
+
return status;
}
@@ -6830,10 +7972,10 @@ Return Value:
--*/
{
- ULONG status;
+ ULONG status = STOR_STATUS_SUCCESS;
ULONG srbDataBufferLength = 0;
- PSRB_IO_CONTROL srbControl;
- PFIRMWARE_REQUEST_BLOCK firmwareRequest;
+ PSRB_IO_CONTROL srbControl = NULL;
+ PFIRMWARE_REQUEST_BLOCK firmwareRequest = NULL;
srbControl = (PSRB_IO_CONTROL)SrbGetDataBuffer(Srb);
srbDataBufferLength = SrbGetDataTransferLength(Srb);
@@ -6842,8 +7984,10 @@ Return Value:
// A Firmware request must have at least SRB_IO_CONTROL and FIRMWARE_REQUEST_BLOCK in input buffer.
//
if (srbDataBufferLength < (sizeof(SRB_IO_CONTROL) + sizeof(FIRMWARE_REQUEST_BLOCK))) {
+ srbControl->ReturnCode = FIRMWARE_STATUS_INVALID_PARAMETER;
Srb->SrbStatus = SRB_STATUS_BAD_SRB_BLOCK_LENGTH;
- return STOR_STATUS_INVALID_PARAMETER;
+ status = STOR_STATUS_INVALID_PARAMETER;
+ goto Exit;
}
firmwareRequest = (PFIRMWARE_REQUEST_BLOCK)(srbControl + 1);
@@ -6851,13 +7995,15 @@ Return Value:
if ((ULONGLONG)(srbDataBufferLength) < ((ULONGLONG)firmwareRequest->DataBufferOffset + firmwareRequest->DataBufferLength)) {
srbControl->ReturnCode = FIRMWARE_STATUS_INVALID_PARAMETER;
Srb->SrbStatus = SRB_STATUS_BAD_SRB_BLOCK_LENGTH;
- return STOR_STATUS_INVALID_PARAMETER;
+ status = STOR_STATUS_INVALID_PARAMETER;
+ goto Exit;
}
if (firmwareRequest->Version < FIRMWARE_REQUEST_BLOCK_STRUCTURE_VERSION) {
srbControl->ReturnCode = FIRMWARE_STATUS_INVALID_PARAMETER;
Srb->SrbStatus = SRB_STATUS_BAD_SRB_BLOCK_LENGTH;
- return STOR_STATUS_INVALID_PARAMETER;
+ status = STOR_STATUS_INVALID_PARAMETER;
+ goto Exit;
}
//
@@ -6866,7 +8012,8 @@ Return Value:
if (firmwareRequest->DataBufferOffset < ALIGN_UP(sizeof(SRB_IO_CONTROL) + sizeof(FIRMWARE_REQUEST_BLOCK), PVOID)) {
srbControl->ReturnCode = FIRMWARE_STATUS_INVALID_PARAMETER;
Srb->SrbStatus = SRB_STATUS_BAD_SRB_BLOCK_LENGTH;
- return STOR_STATUS_INVALID_PARAMETER;
+ status = STOR_STATUS_INVALID_PARAMETER;
+ goto Exit;
}
//
@@ -6887,6 +8034,37 @@ Return Value:
}
+Exit:
+
+ if (status != STOR_STATUS_SUCCESS) {
+
+ StorPortEtwEvent8(ChannelExtension->AdapterExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciEtwEventUnitFirmwareIoctl,
+ L"Firmware Ioctl",
+ STORPORT_ETW_EVENT_KEYWORD_IO,
+ StorportEtwLevelError,
+ StorportEtwEventOpcodeInfo,
+ (PSCSI_REQUEST_BLOCK)Srb,
+ L"SrbDataBufLen",
+ srbDataBufferLength,
+ L"SrbStatus",
+ Srb->SrbStatus,
+ L"ReturnCode",
+ srbControl->ReturnCode,
+ L"FWReqVersion",
+ (firmwareRequest == NULL) ? (0) : (firmwareRequest->Version),
+ L"FWReqFunction",
+ (firmwareRequest == NULL) ? (0) : (firmwareRequest->Function),
+ L"FWBufOffset",
+ (firmwareRequest == NULL) ? (0) : (firmwareRequest->DataBufferOffset),
+ L"Status",
+ status,
+ NULL,
+ 0);
+
+ }
+
return status;
}
@@ -7543,7 +8721,10 @@ QueryTemperatureInfoCompletion(
NT_ASSERT(FALSE);
}
- srbExtension->DataBuffer = NULL;
+ if (srbExtension->DataBuffer != NULL) {
+ AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, IDE_GP_LOG_SECTOR_SIZE, srbExtension->DataBuffer, srbExtension->DataBufferPhysicalAddress);
+ srbExtension->DataBuffer = NULL;
+ }
srbExtension->CompletionContext = NULL;
srbExtension->CompletionRoutine = NULL;
srbExtension->AtaFunction = 0;
@@ -7581,7 +8762,6 @@ Return Value:
PVOID buffer = NULL;
STOR_PHYSICAL_ADDRESS bufferPhysicalAddress = {0};
- ULONG tempLength = 0;
srbControl = (PSRB_IO_CONTROL)SrbGetDataBuffer(Srb);
srbDataBufferLength = SrbGetDataTransferLength(Srb);
@@ -7616,7 +8796,7 @@ Return Value:
//
// allocate DMA buffer to retrieve temperature statistics log.
//
- status = AhciAllocateDmaBuffer((PVOID)ChannelExtension->AdapterExtension, IDE_GP_LOG_SECTOR_SIZE, (PVOID*)&buffer);
+ status = AhciAllocateDmaBuffer((PVOID)ChannelExtension->AdapterExtension, IDE_GP_LOG_SECTOR_SIZE, (PVOID*)&buffer, &bufferPhysicalAddress);
if ( (status != STOR_STATUS_SUCCESS) || (buffer == NULL) ) {
Srb->SrbStatus = SRB_STATUS_ERROR;
@@ -7626,8 +8806,6 @@ Return Value:
AhciZeroMemory((PCHAR)buffer, IDE_GP_LOG_SECTOR_SIZE);
- bufferPhysicalAddress = StorPortGetPhysicalAddress(ChannelExtension->AdapterExtension, NULL, buffer, &tempLength);
-
IssueReadLogExtCommand(ChannelExtension,
Srb,
IDE_GP_LOG_DEVICE_STATISTICS_ADDRESS,
@@ -7911,8 +9089,6 @@ exit:
return status;
}
-
-
#if _MSC_VER >= 1200
#pragma warning(pop)
#else
@@ -7920,4 +9096,3 @@ exit:
#pragma warning(default:4201)
#pragma warning(default:26015)
#endif
-
diff --git a/storage/miniports/storahci/src/common.h b/storage/miniports/storahci/src/common.h
index 3b066131..7a7b8d9c 100644
--- a/storage/miniports/storahci/src/common.h
+++ b/storage/miniports/storahci/src/common.h
@@ -44,6 +44,7 @@ Revision History:
#define IDE_FEATURE_INVALID 0xFF
+#define SCSI_VENDOR_ID_LENGTH (8)
//
// ATA function code
@@ -84,7 +85,6 @@ Revision History:
#define ATA_FLAGS_ACTIVE_REFERENCE (1 << 10) // indicates Active Reference needs to be acquired before processing the Srb and released after processing the Srb
#define ATA_FLAGS_SENSEDATA_SET (1 << 11) // indicates sense data has been set to the Srb
-
//
// helper macros
//
@@ -114,9 +114,23 @@ typedef enum _AHCI_ETW_EVENT_IDS {
AhciEtwEventUnitHybridEvict = 11,
AhciEtwEventUnitHybridSetDirtyThreshold = 12,
AhciEtwEventUnitHybridWriteThrough = 13,
+ AhciEtwEventUnitFirmwareIoctl = 14,
+ AhciEtwEventUnitFirmwareInfo = 15,
+ AhciEtwEventUnitFirmwareDownload = 16,
+ AhciEtwEventUnitFirmwareDownloadComplete = 17,
+ AhciEtwEventUnitFirmwareActivate = 18,
+ AhciEtwEventUnitFirmwareActivateComplete = 19,
+ AhciEtwEventUnitGetPhysicalElementStatusComplete = 20,
+ AhciEtwEventUnitRemoveElementAndTruncateComplete = 21,
+ AhciEtwEventUnitGetInternalStatusDataHeaderComplete = 22,
+ AhciEtwEventUnitGetInternalStatusDataComplete = 23,
+ AhciEtwEventBuildIO = 24,
+ AhciEtwEventStartIO = 25,
+ AhciEtwEventHandleInterrupt = 26,
+ AhciEtwEventPortReset = 27,
+ AhciEtwEventIOCompletion = 28
} AHCI_ETW_EVENT_IDS, *PAHCI_ETW_EVENT_IDS;
-
//
// task file register contents
//
@@ -312,6 +326,14 @@ typedef struct _HYBRID_EVICT_CONTEXT {
} HYBRID_EVICT_CONTEXT, *PHYBRID_EVICT_CONTEXT;
+__inline
+BOOLEAN
+IsUnknownDevice(
+ _In_ PATA_DEVICE_PARAMETERS DeviceParameters
+ )
+{
+ return (DeviceParameters->AtaDeviceType == DeviceUnknown);
+}
__inline
BOOLEAN
@@ -601,7 +623,8 @@ __inline
AhciAllocateDmaBuffer (
_In_ PVOID AdapterExtension,
_In_ ULONG BufferLength,
- _Post_writable_byte_size_(BufferLength) PVOID* Buffer
+ _Post_writable_byte_size_(BufferLength) PVOID* Buffer,
+ _Out_ PSTOR_PHYSICAL_ADDRESS PhysicalAddress
)
{
ULONG status;
@@ -613,15 +636,16 @@ AhciAllocateDmaBuffer (
maxPhysicalAddress.QuadPart = 0x7FFFFFFF; // (2GB - 1)
boundaryPhysicalAddress.QuadPart = 0;
+ status = StorPortAllocateDmaMemory(AdapterExtension,
+ BufferLength,
+ minPhysicalAddress,
+ maxPhysicalAddress,
+ boundaryPhysicalAddress,
+ MmCached,
+ MM_ANY_NODE_OK,
+ Buffer,
+ PhysicalAddress);
- status = StorPortAllocateContiguousMemorySpecifyCacheNode(AdapterExtension,
- BufferLength,
- minPhysicalAddress,
- maxPhysicalAddress,
- boundaryPhysicalAddress,
- MmCached,
- MM_ANY_NODE_OK,
- Buffer);
return status;
}
@@ -631,14 +655,18 @@ __inline
AhciFreeDmaBuffer (
_In_ PVOID AdapterExtension,
_In_ ULONG_PTR BufferLength,
- _In_reads_bytes_(BufferLength) _Post_invalid_ PVOID Buffer
+ _In_reads_bytes_(BufferLength) _Post_invalid_ PVOID Buffer,
+ _In_opt_ STOR_PHYSICAL_ADDRESS PhysicalAddress
)
{
- ULONG status;
- status = StorPortFreeContiguousMemorySpecifyCache(AdapterExtension,
- Buffer,
- BufferLength,
- MmCached);
+ ULONG status;
+
+ status = StorPortFreeDmaMemory(AdapterExtension,
+ Buffer,
+ BufferLength,
+ MmCached,
+ PhysicalAddress);
+
return status;
}
@@ -862,6 +890,33 @@ AtaReportLunsCommand(
_In_ PVOID Context
);
+ULONG
+AtaGetPhysicalElementStatusRequest (
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_ PSTORAGE_REQUEST_BLOCK Srb,
+ _In_ PCDB Cdb
+ );
+
+ULONG
+AtaRemoveElementAndTruncateRequest (
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_ PSTORAGE_REQUEST_BLOCK Srb,
+ _In_ PCDB Cdb
+ );
+
+ULONG
+AtaGetDeviceCurrentInternalStatusData(
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_ PSTORAGE_REQUEST_BLOCK Srb,
+ _In_ PCDB Cdb
+ );
+
+ULONG
+AtaGetDeviceCurrentInternalStatusDataHeader(
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_ PSTORAGE_REQUEST_BLOCK Srb,
+ _In_ PCDB Cdb
+ );
UCHAR
AtaMapError(
@@ -965,6 +1020,53 @@ FirmwareIoctlProcess(
);
+//
+// AHCI Telemetry event related.
+//
+#define AHCI_TELEMETRY_EVENT_VERSION 0x1
+#define AHCI_TELEMETRY_DRIVER_VERSION 0x1
+
+#define AHCI_TELEMETRY_FLAG_NOT_SUPPRESS_LOGGING 0x1
+
+typedef enum _AHCI_TELEMETRY_EVENT_ID {
+ AhciTelemetryEventIdGeneral = 0,
+ AhciTelemetryEventIdPortReset = 1,
+ AhciTelemetryEventIdPortRunningStartFail = 2,
+ AhciTelemetryEventIdPortErrorRecovery = 3,
+ AhciTelemetryEventIdNonqueuedErrorRecovery = 4,
+ AhciTelemetryEventIdNCQErrorRecovery = 5,
+ AhciTelemetryEventIdNCQErrorRecoveryComplete = 6,
+ AhciTelemetryEventIdResetBus = 7,
+ AhciTelemetryEventIdResetDeviceRequest = 8,
+ AhciTelemetryEventIdSurpriseRemove = 9,
+ AhciTelemetryEventIdLpmAdaptiveSetting = 10,
+ AhciTelemetryEventIdLpmSettingsModes = 11,
+ AhciTelemetryEventIdPortStartSuccess = 12,
+ AhciTelemetryEventIdReservedSlotStuck = 13,
+ AhciTelemetryEventIdMax = 256
+} AHCI_TELEMETRY_EVENT_ID, *PAHCI_TELEMETRY_EVENT_ID;
+
+//
+// AHCI mark device failure related.
+//
+#define AHCI_BUS_CHANGE_WARNING_THROTTLE_MASK (0x1 << 0)
+#define AHCI_BUS_CHANGE_COUNT_WARNING_THRESHOLD (20)
+
+#define AHCI_NCQ_ERROR_WARNING_THROTTLE_MASK (0x1 << 1)
+#define AHCI_NCQ_ERROR_COUNT_WARNING_THRESHOLD (100)
+
+#define AHCI_NON_QUEUED_ERROR_WARNING_THROTTLE_MASK (0x1 << 2)
+#define AHCI_NON_QUEUED_ERROR_COUNT_WARNING_THRESHOLD (100)
+
+#define AHCI_DEVICE_STUCK_WARNING_THROTTLE_MASK (0x1 << 3)
+
+typedef enum _AHCI_DEVICE_FAILURE_REASON {
+ AhciDeviceFailureUnspecific = 0,
+ AhciDeviceFailureTooManyBusChange = 1,
+ AhciDeviceFailureTooManyNCQError = 2,
+ AhciDeviceFailureTooManyNonQueuedError = 3,
+ AhciDeviceFailureDeviceStuck = 4
+} AHCI_DEVICE_FAILURE_REASON, *PAHCI_DEVICE_FAILURE_REASON;
#if _MSC_VER >= 1200
#pragma warning(pop)
@@ -972,4 +1074,3 @@ FirmwareIoctlProcess(
#pragma warning(default:4214)
#pragma warning(default:4201)
#endif
-
diff --git a/storage/miniports/storahci/src/data.h b/storage/miniports/storahci/src/data.h
new file mode 100644
index 00000000..6bec0934
--- /dev/null
+++ b/storage/miniports/storahci/src/data.h
@@ -0,0 +1,96 @@
+/*++
+
+Copyright (c) 2017 Microsoft Corporation
+
+Module Name:
+
+ data.h
+
+Abstract:
+
+ Definitions needed by storahci log/diagnostic function.
+
+Author:
+
+--*/
+
+#pragma once
+
+//
+// Diagnostic data definitions for STORAHCI
+//
+
+#define MAX_EXECUTION_HISTORY_ENTRY_COUNT 200 // 200 entries take up 20KB
+
+typedef struct _SLOT_MANAGER {
+
+ ULONG HighPriorityAttribute;
+
+ ULONG NCQueueSlice;
+ ULONG NormalQueueSlice;
+ ULONG SingleIoSlice;
+
+ ULONG CommandsIssued;
+ ULONG CommandsToComplete;
+
+ //
+ // These issued slices are used to determine the type of command
+ // being programmed to adapter.
+ // They are used instead of reading PxCI and PxSACT.
+ //
+ ULONG NCQueueSliceIssued;
+ ULONG NormalQueueSliceIssued;
+ ULONG SingleIoSliceIssued;
+
+ ULONG Reserved;
+
+} SLOT_MANAGER, *PSLOT_MANAGER;
+
+typedef struct _EXECUTION_HISTORY {
+
+ ULONG Function;
+ ULONG IS;
+ SLOT_MANAGER SlotManager; //SLOT_MANAGER from _AHCI_CHANNEL_EXTENSION
+ ULONG Px[0x10]; //Px registers value, end to AHCI_SNOTIFICATION -- SNTF
+ LARGE_INTEGER TimeStamp;
+
+} EXECUTION_HISTORY, *PEXECUTION_HISTORY;
+
+typedef struct _ATA_IO_RECORD {
+
+ ULONG SuccessCount;
+
+ ULONG CrcErrorCount;
+ ULONG MediaErrorCount;
+ ULONG EndofMediaCount;
+ ULONG IllegalCommandCount;
+ ULONG AbortedCommandCount;
+ ULONG DeviceFaultCount;
+
+ ULONG OtherErrorCount;
+
+ ULONG NcqReadLogErrorCount; // used to record the READ LOG EXT command error count when used for NCQ Error Recovery.
+
+ ULONG PortDriverResetCount;
+ ULONG TotalResetCount;
+
+} ATA_IO_RECORD, *PATA_IO_RECORD;
+
+typedef struct _STORAGE_DIAGNOSTIC_AHCI_EXECUTION_HISTORY {
+
+ ULONG ExecutionHistoryCount;
+ ULONG ExecutionHistoryIndex;
+ EXECUTION_HISTORY History[MAX_EXECUTION_HISTORY_ENTRY_COUNT];
+
+} STORAGE_DIAGNOSTIC_AHCI_EXECUTION_HISTORY, *PSTORAGE_DIAGNOSTIC_AHCI_EXECUTION_HISTORY;
+
+typedef struct _STORAGE_DIAGNOSTIC_AHCI_DATA {
+
+ ULONG Version;
+ ULONG Count;
+ STORAGE_DIAGNOSTIC_AHCI_EXECUTION_HISTORY ExecutionHistory;
+ AHCI_PORT Registers;
+ ATA_IO_RECORD IoRecord;
+
+} STORAGE_DIAGNOSTIC_AHCI_DATA, *PSTORAGE_DIAGNOSTIC_AHCI_DATA;
+
diff --git a/storage/miniports/storahci/src/entrypts.c b/storage/miniports/storahci/src/entrypts.c
index e9c070c8..efbe2279 100644
--- a/storage/miniports/storahci/src/entrypts.c
+++ b/storage/miniports/storahci/src/entrypts.c
@@ -21,11 +21,10 @@ Revision History:
#pragma warning(push)
#endif
-#pragma warning(disable:4152) // nonstandard extension, function/data pointer conversion in expression
+#pragma warning(disable:4152) // nonstandard extension, function/data pointer conversion in expression
#pragma warning(disable:4214) // bit field types other than int
#pragma warning(disable:4201) // nameless struct/union
-
#include "generic.h"
@@ -102,12 +101,12 @@ Return Value:
hwInitializationData.NumberOfAccessRanges = NUM_ACCESS_RANGES;
//
- // TODO : It's not a given that SATA on ARM64 will only ever be ACPI enumerated
- // This is just for the on-board controller. We will have to come up with a
- // solution for PCI bus enuerated on ARM64
+ // Support both PCI/ACPI enumerations on ARM64 platform for SATA device.
+ // Miniport uses flag to indicate storport to query/override the interface type reported here.
//
-#if defined (_ARM64_)
- hwInitializationData.AdapterInterfaceType = ACPIBus;
+#if defined(_ARM_) || defined(_ARM64_)
+ hwInitializationData.FeatureSupport |= STOR_FEATURE_SET_ADAPTER_INTERFACE_TYPE;
+ hwInitializationData.AdapterInterfaceType = InterfaceTypeUndefined;
#else
hwInitializationData.AdapterInterfaceType = PCIBus;
#endif
@@ -122,6 +121,7 @@ Return Value:
hwInitializationData.FeatureSupport |= STOR_FEATURE_DEVICE_DESCRIPTOR_FROM_ATA_INFO_VPD; // indicating that port driver forms STORAGE_DEVICE_DESCRIPTOR from ATA Information VPD page rather than INQUIRY data
hwInitializationData.FeatureSupport |= STOR_FEATURE_EXTRA_IO_INFORMATION; // Indicating that miniport driver wants SRBEX_DATA_IO_INFO in a SRBEX if available
hwInitializationData.FeatureSupport |= STOR_FEATURE_ADAPTER_NOT_REQUIRE_IO_PORT; // Indicating that miniport driver doesn't require IO Port resource for its adapter.
+ hwInitializationData.FeatureSupport |= STOR_FEATURE_DUMP_INFO; // Indicating that the miniport driver supports the dump info SRBs.
// Set required extension sizes.
hwInitializationData.DeviceExtensionSize = sizeof(AHCI_ADAPTER_EXTENSION);
@@ -206,7 +206,6 @@ Return Values:
AdapterExtension->StateFlags.InterruptMessagePerPort = 0;
}
-
StorPortDebugPrint(3, "StorAHCI - Interrupt Mode: Adapter 0x%04X-0x%04X --- %s\n",
AdapterExtension->VendorID,
AdapterExtension->DeviceID,
@@ -242,11 +241,16 @@ AllocateResourcesForAdapter(
Therefore the number of Command Headers must be 256/32 = 8. Round cap.NCS to the next multiple of 8
*/
{
+ ULONG alignment = 0x400; // 1K
+ BOOLEAN dumpMode = IsDumpMode(AdapterExtension);
ULONG paddedNCS = 0;
ULONG paddedSrbExtensionSize = 0;
ULONG nonCachedExtensionSize = 0;
+ ULONG channelExtensionSize = sizeof(AHCI_CHANNEL_EXTENSION);
PVOID portsChannelExtension = NULL;
- PCHAR portsUncachedExtension = NULL;
+ ULONG executionHistorySize = sizeof(EXECUTION_HISTORY) * MAX_EXECUTION_HISTORY_ENTRY_COUNT;
+ PVOID portsExecutionHistory = NULL;
+ ULONG_PTR left = 0;
ULONG i = 0;
ULONG j = 0;
@@ -268,33 +272,40 @@ AllocateResourcesForAdapter(
sizeof(IDENTIFY_DEVICE_DATA) + // 512 bytes
ATA_BLOCK_SIZE + // ReadLogExtPageData --- 512 bytes
INQUIRYDATABUFFERSIZE; // Inquiry Data
+
// round up to KiloBytes if it's not dump mode. this makes sure that NonCachedExtension for next port can align to 1K.
- if (!IsDumpMode(AdapterExtension)) {
- nonCachedExtensionSize = ((nonCachedExtensionSize - 1) / 0x400 + 1) * 0x400;
- // total size for all ports
- nonCachedExtensionSize *= PortCount;
+ if (!dumpMode) {
+ nonCachedExtensionSize = ((nonCachedExtensionSize - 1) / alignment + 1) * alignment;
+
+ AdapterExtension->NonCachedExtension = StorPortGetUncachedExtension(AdapterExtension,
+ ConfigInfo,
+ nonCachedExtensionSize * PortCount);
} else {
// dump mode, address returned from StorPortGetUncachedExtension() is not guaranteed align with 1K.
// adding 1K into length so that we can start from 1K alignment safely.
// NOTE: StorPortAllocatePool is not supported in dump stack, so we allocate ChannelExtension from UnCachedExtension as work around.
- nonCachedExtensionSize += 0x400 + sizeof(AHCI_CHANNEL_EXTENSION);
- }
+ nonCachedExtensionSize += alignment;
- AdapterExtension->NonCachedExtension = StorPortGetUncachedExtension(AdapterExtension, ConfigInfo, nonCachedExtensionSize);
+ AdapterExtension->NonCachedExtension = StorPortGetUncachedExtension(AdapterExtension,
+ ConfigInfo,
+ (nonCachedExtensionSize + channelExtensionSize) * PortCount);
+ }
if (AdapterExtension->NonCachedExtension == NULL) {
- // we cannot continue if cannot get nonCachedMemory for Channels.
+
+ // we cannot continue if cannot get nonCachedMemory for Channels.
+ NT_ASSERT(FALSE);
return FALSE;
}
- AhciZeroMemory((PCHAR)AdapterExtension->NonCachedExtension, nonCachedExtensionSize);
+ AhciZeroMemory((PCHAR)AdapterExtension->NonCachedExtension, nonCachedExtensionSize * PortCount);
// 2.2 allocate resources for Ports which need AHCI_CHANNEL_EXTENSION for each of them.
- if (!IsDumpMode(AdapterExtension)) {
+ if (!dumpMode) {
ULONG status = STOR_STATUS_SUCCESS;
// allocate pool and zero the content
status = StorPortAllocatePool(AdapterExtension,
- PortCount * sizeof(AHCI_CHANNEL_EXTENSION),
+ channelExtensionSize * PortCount,
AHCI_POOL_TAG,
(PVOID*)&portsChannelExtension);
@@ -302,36 +313,49 @@ AllocateResourcesForAdapter(
// we cannot continue if cannot get memory for ChannelExtension.
return FALSE;
}
- AhciZeroMemory((PCHAR)portsChannelExtension, PortCount * sizeof(AHCI_CHANNEL_EXTENSION));
- //get the starting pointer
- portsUncachedExtension = (PCHAR)AdapterExtension->NonCachedExtension;
- } else {
- ULONG_PTR left = 0;
- // get channelExtension
- portsChannelExtension = (PCHAR)AdapterExtension->NonCachedExtension + nonCachedExtensionSize - sizeof(AHCI_CHANNEL_EXTENSION);
- //get the starting pointer; align the starting location to 1K.
- left = ((ULONG_PTR)AdapterExtension->NonCachedExtension) % 1024;
+ status = StorPortAllocatePool(AdapterExtension,
+ (ULONG)(executionHistorySize * PortCount),
+ AHCI_POOL_TAG,
+ (PVOID*)&portsExecutionHistory);
- if (left > 0) {
- portsUncachedExtension = (PCHAR)AdapterExtension->NonCachedExtension + 1024 - left;
- } else {
- portsUncachedExtension = (PCHAR)AdapterExtension->NonCachedExtension;
+ if ((status != STOR_STATUS_SUCCESS) || (portsExecutionHistory == NULL)) {
+ // Continue if cannot get memory for ExecutionHistory.
+ NT_ASSERT(FALSE);
}
+ } else {
+ // get channelExtension from UnCachedExtension
+ portsChannelExtension = (PCHAR)AdapterExtension->NonCachedExtension + (nonCachedExtensionSize * PortCount);
}
- // reset nonCachedExtensionSize to be the size for one Port, it works for dump case also as PortCount is '1'.
- nonCachedExtensionSize /= PortCount;
+ AhciZeroMemory((PCHAR)portsChannelExtension, channelExtensionSize * PortCount);
- // assign allocated memory and uncachedExension into ChannelExtensions
+ // assign allocated uncachedExension into ChannelExtensions
for (i = 0; i <= AdapterExtension->HighestPort; i++) {
if ( (AdapterExtension->PortImplemented & (1 << i)) != 0 ) {
+ PCHAR portsUncachedExtension = (PCHAR)AdapterExtension->NonCachedExtension + nonCachedExtensionSize * j;
+
// this port is implemented, allocate and initialize extension for the port
- AdapterExtension->PortExtension[i] = (PAHCI_CHANNEL_EXTENSION)((PCHAR)portsChannelExtension + sizeof(AHCI_CHANNEL_EXTENSION) * j);
+ AdapterExtension->PortExtension[i] = (PAHCI_CHANNEL_EXTENSION)((PCHAR)portsChannelExtension + channelExtensionSize * j);
AdapterExtension->PortExtension[i]->AdapterExtension = AdapterExtension;
AdapterExtension->PortExtension[i]->PortNumber = i;
// set ChannelExtension fields that use NonCachedExtension
- AdapterExtension->PortExtension[i]->CommandList = (PAHCI_COMMAND_HEADER)(portsUncachedExtension + nonCachedExtensionSize * j);
+ if (!dumpMode) {
+ AdapterExtension->PortExtension[i]->CommandList = (PAHCI_COMMAND_HEADER)(portsUncachedExtension);
+ if (portsExecutionHistory != NULL) {
+ AdapterExtension->PortExtension[i]->ExecutionHistory = (PEXECUTION_HISTORY)((PCHAR)portsExecutionHistory + executionHistorySize * j);
+ }
+ } else {
+ //get the starting pointer; align the starting location to 1K.
+ left = ((ULONG_PTR)portsUncachedExtension) % alignment;
+
+ if (left > 0) {
+ AdapterExtension->PortExtension[i]->CommandList = (PAHCI_COMMAND_HEADER)(portsUncachedExtension + alignment - left);
+ } else {
+ AdapterExtension->PortExtension[i]->CommandList = (PAHCI_COMMAND_HEADER)(portsUncachedExtension);
+ }
+ }
+
AdapterExtension->PortExtension[i]->ReceivedFIS = (PAHCI_RECEIVED_FIS)((PCHAR)AdapterExtension->PortExtension[i]->CommandList + sizeof(AHCI_COMMAND_HEADER) * paddedNCS);
AdapterExtension->PortExtension[i]->Local.SrbExtension = (PAHCI_SRB_EXTENSION)((PCHAR)AdapterExtension->PortExtension[i]->ReceivedFIS + sizeof(AHCI_RECEIVED_FIS));
AdapterExtension->PortExtension[i]->Sense.SrbExtension = (PAHCI_SRB_EXTENSION)((PCHAR)AdapterExtension->PortExtension[i]->Local.SrbExtension + paddedSrbExtensionSize);
@@ -377,7 +401,7 @@ It performs:
2.2 Initialize adapterExtension with version & cap values
3.1 Turn on AE, reset the controller if AE is already set
AHCI 1.1 Section 10.1.2 - 1.
- "Indicate that system software is AHCI aware by setting GHC.AE to �1�."
+ "Indicate that system software is AHCI aware by setting GHC.AE to '1'."
3.2 Determine which ports are implemented by the HBA
AHCI 1.1 Section 10.1.2 - 2.
"Determine which ports are implemented by the HBA, by reading the PI register. This bitmap value will aid software in determining how many ports are available and which port registers need to be initialized."
@@ -387,10 +411,11 @@ It performs:
4.1 Turn on IE, pending interrupts will be cleared when port starts
This has to be done after 3.2 because we need to know the number of channels before we check each PxIS.
Verify that none of the PxIS registers are loaded, but take no action
- Note: Due to the multi-tiered nature of the AHCI HBA�s interrupt architecture, system software must always ensure that the PxIS (clear this first) and IS.IPS (clear this second) registers are cleared to �0� before programming the PxIE and GHC.IE registers. This will prevent any residual bits set in these registers from causing an interrupt to be asserted.
+ Note: Due to the multi-tiered nature of the AHCI HBA's interrupt architecture, system software must always ensure that the PxIS (clear this first) and IS.IPS (clear this second) registers are cleared to '0' before programming the PxIE and GHC.IE registers. This will prevent any residual bits set in these registers from causing an interrupt to be asserted.
However, the interrupt handler hasn't been hooked up by StorPort yet, so no interrupts will be handled by software until that happens.
- 4.2 Allocate resources for both DMA use and all Channel/Port extensions.
- 4.3 Initialize ports and start them. Dump stack will do this when receiving the INQUIRY command
+ 4.2 Initialize the remaining port configuration settings after getting registry settings.
+ 4.3 Allocate resources for both DMA use and all Channel/Port extensions.
+ 4.4 Initialize ports and start them. Dump stack will do this when receiving the INQUIRY command
Affected Variables/Registers:
AdapterExtension->ABAR_Address
@@ -399,7 +424,7 @@ Affected Variables/Registers:
AdapterExtension->Version
GHC.AE, GHC.IE, GHC.HR
- IS and all fields in the HBA�s register memory space except PxFB/PxFBU/PxCLB/PxCLBU that are not HwInit
+ IS and all fields in the HBA's register memory space except PxFB/PxFBU/PxCLB/PxCLBU that are not HwInit
Return Values:
The miniport driver returns TRUE if it successfully execute the whole function.
@@ -421,11 +446,12 @@ Note:
ULONG piMask = 0;
UCHAR numberOfHighestPort = 0;
ULONG portCount = 0;
+ ULONG portNumber;
//Used to enable the AHCI interface
AHCI_Global_HBA_CONTROL ghc = {0};
//guids
GUID powerSettingChangeGuids[2] = {0};
-
+ BOOLEAN dumpMode = FALSE;
PAHCI_DUMP_CONTEXT dumpContext = (PAHCI_DUMP_CONTEXT)ConfigInfo->MiniportDumpData;
UNREFERENCED_PARAMETER(HwContext);
@@ -447,48 +473,54 @@ Note:
adapterExtension->SystemIoBusNumber = ConfigInfo->SystemIoBusNumber;
adapterExtension->SlotNumber = ConfigInfo->SlotNumber;
- //1.1 Get dump mode
+ //1.1 Get dump mode
adapterExtension->DumpMode = ConfigInfo->DumpMode;
+ dumpMode = IsDumpMode(adapterExtension);
- if (IsDumpMode(adapterExtension)) {
+ if (dumpMode) {
if (dumpContext != NULL) {
- // In dump/hibernation mode, need to mark ConfigInfo->MiniportDumpData and any embedded memory buffer(s) in MiniportDumpData
- StorPortMarkDumpMemory(AdapterExtension, dumpContext, sizeof(AHCI_DUMP_CONTEXT), 0);
+ // In dump/hibernation mode, need to mark ConfigInfo->MiniportDumpData
+ // and any embedded memory buffer(s) in MiniportDumpData
+ StorPortMarkDumpMemory(AdapterExtension,
+ dumpContext,
+ FIELD_OFFSET(AHCI_DUMP_CONTEXT, Ports) +
+ (dumpContext->PortCount * sizeof(AHCI_DUMP_PORT_CONTEXT)),
+ 0);
} else {
NT_ASSERT(FALSE);
return SP_RETURN_ERROR;
}
}
- //1.2 Gather Vendor,Device,Revision IDs from PCI
- if (!IsDumpMode(adapterExtension)) {
+ //1.2 Gather Vendor,Device,Revision IDs from PCI
+ if (!dumpMode) {
- //
- // TODO : Ensure that we can enumerate using PCI as well as ACPI
- // right now this code is for ACPI only.
- //
-#if !defined(_ARM64_)
- ULONG pcicfgLen = 0;
- UCHAR pcicfgBuffer[0x30] = {0};
+ //
+ // Enumeration may be via either PCI or ACPI. Bus type is set by storport/miniport.
+ // Check if we are enumerating via PCI, and retrieve the address appropriately.
+ //
+ if (ConfigInfo->AdapterInterfaceType == PCIBus) {
+ ULONG pcicfgLen = 0;
+ UCHAR pcicfgBuffer[0x30] = {0};
- pcicfgLen = StorPortGetBusData(adapterExtension,
- PCIConfiguration,
- ConfigInfo->SystemIoBusNumber,
- (ULONG)ConfigInfo->SlotNumber,
- (PVOID)pcicfgBuffer,
- (ULONG)0x30);
- if (pcicfgLen == 0x30) {
- PPCI_COMMON_CONFIG pciConfigData = (PPCI_COMMON_CONFIG)pcicfgBuffer;
- adapterExtension->VendorID = pciConfigData->VendorID;
- adapterExtension->DeviceID = pciConfigData->DeviceID;
- adapterExtension->RevisionID = pciConfigData->RevisionID;
- // on PCI bus, AHCI Base Address is BAR5. Bits 0-3 defined for other usages, not part of address value.
- adapterExtension->AhciBaseAddress = pciConfigData->u.type0.BaseAddresses[5] & (0xFFFFFFF0);
- } else {
- NT_ASSERT(FALSE);
- return SP_RETURN_ERROR;
+ pcicfgLen = StorPortGetBusData(adapterExtension,
+ PCIConfiguration,
+ ConfigInfo->SystemIoBusNumber,
+ (ULONG)ConfigInfo->SlotNumber,
+ (PVOID)pcicfgBuffer,
+ (ULONG)0x30);
+ if (pcicfgLen == 0x30) {
+ PPCI_COMMON_CONFIG pciConfigData = (PPCI_COMMON_CONFIG)pcicfgBuffer;
+ adapterExtension->VendorID = pciConfigData->VendorID;
+ adapterExtension->DeviceID = pciConfigData->DeviceID;
+ adapterExtension->RevisionID = pciConfigData->RevisionID;
+ // on PCI bus, AHCI Base Address is BAR5. Bits 0-3 defined for other usages, not part of address value.
+ adapterExtension->AhciBaseAddress = pciConfigData->u.type0.BaseAddresses[5] & (0xFFFFFFF0);
+ } else {
+ NT_ASSERT(FALSE);
+ return SP_RETURN_ERROR;
+ }
}
-#endif
} else {
adapterExtension->VendorID = dumpContext->VendorID;
adapterExtension->DeviceID = dumpContext->DeviceID;
@@ -499,22 +531,22 @@ Note:
adapterExtension->LogFlags = dumpContext->LogFlags;
}
- //2.1 Initialize adapterExtension with AHCI abar
+ //2.1 Initialize adapterExtension with AHCI abar
abar = GetABARAddress(adapterExtension, ConfigInfo);
- //2.1.1 If abar is still NULL after all of that, malformed resources. We aren't going to get very far.
+ //2.1.1 If abar is still NULL after all of that, malformed resources. We aren't going to get very far.
if (abar == NULL) {
return SP_RETURN_ERROR;
} else {
adapterExtension->ABAR_Address = abar;
}
- //2.2 Initialize adapterExtension with version & cap values
+ //2.2 Initialize adapterExtension with version & cap values
adapterExtension->Version.AsUlong = StorPortReadRegisterUlong(adapterExtension, &abar->VS.AsUlong);
adapterExtension->CAP.AsUlong = StorPortReadRegisterUlong(adapterExtension, &abar->CAP.AsUlong);
adapterExtension->CAP2.AsUlong = StorPortReadRegisterUlong(adapterExtension, &abar->CAP2.AsUlong);
- //3.1 Turn on AE (AHCI 1.1 Section 10.1.2 - 1)
+ //3.1 Turn on AE (AHCI 1.1 Section 10.1.2 - 1)
ghc.AsUlong = StorPortReadRegisterUlong(adapterExtension, &abar->GHC.AsUlong);
if (ghc.AE == 1) {
if (!AhciAdapterReset(adapterExtension)) {
@@ -527,40 +559,54 @@ Note:
adapterExtension->IS = &abar->IS;
- //3.2 Determine which ports are implemented by the HBA (AHCI 1.1 Section 10.1.2 - 2)
- adapterExtension->PortImplemented = StorPortReadRegisterUlong(adapterExtension, &abar->PI);
+ //3.2 Determine which ports are implemented by the HBA
+ if (!dumpMode) {
+ // Get implemented ports from PI register (AHCI 1.1 Section 10.1.2 - 2)
+ adapterExtension->PortImplemented = StorPortReadRegisterUlong(adapterExtension, &abar->PI);
+ } else {
+ // Get implemented ports from the dump context
+ adapterExtension->PortImplemented = 0;
- //
- // AHCI specification requires that at least one bit is set in PI register.
- // In other words, at least one port must be implemented.
- //
+ for (i = 0; i < dumpContext->PortCount; i++) {
+ adapterExtension->PortImplemented |= 1 << dumpContext->Ports[i].PortNumber;
+ }
+ }
+
+ // At least one port must be implemented
if (adapterExtension->PortImplemented == 0) {
return SP_RETURN_ERROR;
}
- //3.3 Get biggest port number value and implemented port count.
- //3.3.1 get biggest port number value
- numberOfHighestPort = AHCI_MAX_PORT_COUNT;
- //Check from highest bit to lowest bit for the first highest bit set
- for (piMask = (ULONG)(1 << (AHCI_MAX_PORT_COUNT - 1)); piMask != 0; piMask = (ULONG)(piMask >> 1)){
- numberOfHighestPort--;
- if ( (adapterExtension->PortImplemented & piMask) != 0) {
- break;
+ //3.3 Get biggest port number value and implemented port count
+ if (!dumpMode) {
+ numberOfHighestPort = AHCI_MAX_PORT_COUNT;
+ //Check from highest bit to lowest bit for the first highest bit set
+ for (piMask = (ULONG)(1 << (AHCI_MAX_PORT_COUNT - 1)); piMask != 0; piMask = (ULONG)(piMask >> 1)){
+ numberOfHighestPort--;
+ if ((adapterExtension->PortImplemented & piMask) != 0) {
+ break;
+ }
}
- } //numberOfHighestPort now holds the correct value
- //3.3.2 get implemented port count
- if (!IsDumpMode(adapterExtension)) {
for (i = 0; i <= numberOfHighestPort; i++) {
- if ( (adapterExtension->PortImplemented & (1 << i)) != 0 ) {
+ if ((adapterExtension->PortImplemented & (1 << i)) != 0) {
portCount++;
}
}
} else {
- // in dump environment, only use the desired port.
- portCount = 1;
+ numberOfHighestPort = 0;
+ for (i = 0; i < dumpContext->PortCount; i++) {
+ if (dumpContext->Ports[i].PortNumber > numberOfHighestPort) {
+ numberOfHighestPort = (UCHAR)dumpContext->Ports[i].PortNumber;
+ }
+ }
+
+ portCount = dumpContext->PortCount;
}
+ NT_ASSERT(numberOfHighestPort < AHCI_MAX_PORT_COUNT);
+ adapterExtension->HighestPort = numberOfHighestPort;
+
//
// AHCI specification requires that implemented port count (number of bit set in PI register)
// is less than or equal to CAP.NP + 1
@@ -570,8 +616,8 @@ Note:
//
NT_ASSERT(portCount > 0 && portCount <= (adapterExtension->CAP.NP + 1));
- //3.4 Initializing the rest of PORT_CONFIGURATION_INFORMATION
- ConfigInfo->MaximumTransferLength = AHCI_MAX_TRANSFER_LENGTH;
+ //3.4 Initializing the rest of PORT_CONFIGURATION_INFORMATION
+ ConfigInfo->MaximumTransferLength = AHCI_MAX_TRANSFER_LENGTH_DEFAULT;
ConfigInfo->NumberOfPhysicalBreaks = 0x21; // Since "NumberOfPhysicalBreaks" has been used in storage stack as the count of entries, use value of physical breaks plus one.
ConfigInfo->AlignmentMask = 1; // ATA devices need WORD alignment
ConfigInfo->ScatterGather = TRUE;
@@ -584,33 +630,10 @@ Note:
ConfigInfo->BusResetHoldTime = 0; // StorAHCI wait RESET to be completed by itself, no need for port driver to wait.
ConfigInfo->MaxNumberOfIO = portCount * adapterExtension->CAP.NCS;
- if (adapterExtension->CAP.S64A) {
-#if defined (_ARM64_)
- ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_FULL64BIT_NO_BOUNDARY_REQ_SUPPORTED;
-#else
- ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
-#endif
- // increase size of SrbExtension to accommodate 64-bit move commands
- // and 1 extra Scripts instruction (turn off 64-bit mode)
- ConfigInfo->SrbExtensionSize += (ULONG)((ConfigInfo->NumberOfPhysicalBreaks + 2) * 4);
- }
-
ConfigInfo->FeatureSupport |= STOR_ADAPTER_FEATURE_STOP_UNIT_DURING_POWER_DOWN;
ConfigInfo->FeatureSupport |= STOR_ADAPTER_FEATURE_RICH_TEMPERATURE_THRESHOLD;
-
- // 3.4.2 update PortImplemented, HighestPort and portCount if necessary
- if (!IsDumpMode(adapterExtension)) {
- adapterExtension->HighestPort = numberOfHighestPort;
- } else {
-
- if (dumpContext->DumpPortNumber < AHCI_MAX_PORT_COUNT) {
- adapterExtension->PortImplemented = 1 << dumpContext->DumpPortNumber;
- adapterExtension->HighestPort = dumpContext->DumpPortNumber;
- } else {
- NT_ASSERT(FALSE);
- return SP_RETURN_ERROR;
- }
- }
+ ConfigInfo->FeatureSupport |= STOR_ADAPTER_FEATURE_DEVICE_TELEMETRY;
+ ConfigInfo->FeatureSupport |= STOR_ADAPTER_DMA_V3_PREFERRED;
//
// Set interrupt related entry points.
@@ -625,7 +648,7 @@ Note:
//
// Allocate MessageGroupAffinity buffer for later use.
//
- if (!IsDumpMode(adapterExtension)) {
+ if (!dumpMode) {
StorPortAllocatePool(AdapterExtension,
sizeof(GROUP_AFFINITY) * (adapterExtension->HighestPort + 1),
AHCI_POOL_TAG,
@@ -636,8 +659,8 @@ Note:
ConfigInfo->InterruptSynchronizationMode = InterruptSynchronizeAll;
}
- //3.5 Register Power Setting Change Notification Guids
- if (!IsDumpMode(adapterExtension)) {
+ //3.5 Register Power Setting Change Notification Guids
+ if (!dumpMode) {
/* 0b2d69d7-a2a1-449c-9680-f91c70521c60 -DIPM/HIPM */
powerSettingChangeGuids[0].Data1 = 0x0b2d69d7;
powerSettingChangeGuids[0].Data2 = 0xa2a1;
@@ -667,13 +690,25 @@ Note:
StorPortSetPowerSettingNotificationGuids(AdapterExtension, 2, powerSettingChangeGuids);
}
- //4.1 Turn on IE, pending interrupts will be cleared when port starts
+ //4.1 Turn on IE, pending interrupts will be cleared when port starts
adapterExtension->LastInterruptedPort = (ULONG)(-1);
ghc.IE = 1;
StorPortWriteRegisterUlong(adapterExtension, &abar->GHC.AsUlong, ghc.AsUlong);
+ //4.2.2 Configure DMA 64 bit support settings.
+ if (adapterExtension->CAP.S64A) {
+#if defined (_ARM64_)
+ ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_FULL64BIT_NO_BOUNDARY_REQ_SUPPORTED;
+#else
+ ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
+#endif
+
+ // increase size of SrbExtension to accommodate 64-bit move commands
+ // and 1 extra Scripts instruction (turn off 64-bit mode)
+ ConfigInfo->SrbExtensionSize += (ULONG)((ConfigInfo->NumberOfPhysicalBreaks + 2) * 4);
+ }
- //4.2 allocate resources, implemented port information needs to be ready before calling the following routine.
+ //4.3 allocate resources, implemented port information needs to be ready before calling the following routine.
if (adapterExtension->StateFlags.StoppedState == 0) {
if (!AllocateResourcesForAdapter(adapterExtension, ConfigInfo, portCount)) {
return SP_RETURN_ERROR;
@@ -693,8 +728,8 @@ Note:
//
// 3. Currently WorkerTimer is used only for PartialToSlumber during interrupt servicing (not applicable in dump mode)
//
- if (!IsDumpMode(adapterExtension))
- {
+ if (!dumpMode) {
+
for (i = 0; i <= adapterExtension->HighestPort; i++) {
if (adapterExtension->PortExtension[i] != NULL) {
@@ -726,8 +761,8 @@ Note:
// reset "StoppedState". NOTE: This field should not be referenced anymore in this function after following line.
adapterExtension->StateFlags.StoppedState = 0;
- // 4.3 initialize ports and start them.
- //4.3.1 initialize all AHCI ports
+ //4.4 initialize ports and start them.
+ //4.4.1 initialize all AHCI ports
for (i = 0; i <= adapterExtension->HighestPort; i++) {
if (adapterExtension->PortExtension[i] != NULL) {
// in case of PortInitialize fails, ChannelExtension->StateFlags.Initialized will remain as 'FALSE'. there will be not attempt to start the Port.
@@ -735,35 +770,37 @@ Note:
}
}
- if (IsDumpMode(adapterExtension)) {
+ if (dumpMode) {
//
// In dump mode copy registry flags and telemetry configuration from the dump context. If telemetry extends to more than one
// device the logic should cover migration of per device settings, initially we are limited to a single boot device
//
- ULONG Index;
-#pragma warning (suppress: 6385) // dumpContext->DumpPortNumber is guaranteed to be in-bound earlier
- if (adapterExtension->PortExtension[dumpContext->DumpPortNumber] != NULL) {
+ for (i = 0; i < dumpContext->PortCount; i++) {
+ portNumber = dumpContext->Ports[i].PortNumber;
- adapterExtension->PortExtension[dumpContext->DumpPortNumber]->RegistryFlags = dumpContext->PortRegistryFlags;
+ if (adapterExtension->PortExtension[portNumber] != NULL) {
- //
- // If the table in dump context is empty (not filled) - keep static data intact
- //
- if (dumpContext->PublicGPLogTableAddresses[0]) {
- for(Index=0;
- Index < sizeof(AhciPublicGPLogTableAddresses) / sizeof(AhciPublicGPLogTableAddresses[0] );
- Index++) {
- AhciPublicGPLogTableAddresses[Index] = dumpContext->PublicGPLogTableAddresses[Index];
- }
+ adapterExtension->PortExtension[portNumber]->RegistryFlags = dumpContext->Ports[i].PortRegistryFlags;
- AhciGPLogPageIntoPrivate = dumpContext->PrivateGPLogPageAddress;
- }
+ //
+ // If the table in dump context is empty (not filled) - keep static data intact
+ //
+ /*if (dumpContext->PublicGPLogTableAddresses[0]) {
+ for(Index=0;
+ Index < sizeof(AhciPublicGPLogTableAddresses) / sizeof(AhciPublicGPLogTableAddresses[0] );
+ Index++) {
+ AhciPublicGPLogTableAddresses[Index] = dumpContext->PublicGPLogTableAddresses[Index];
+ }
+
+ AhciGPLogPageIntoPrivate = dumpContext->PrivateGPLogPageAddress;
+ }*/
- StorPortMoveMemory((PVOID)&adapterExtension->PortExtension[dumpContext->DumpPortNumber]->DeviceExtension->HybridInfo,
- (PVOID)&dumpContext->HybridInfo,
- sizeof(GP_LOG_HYBRID_INFORMATION_HEADER));
+ StorPortMoveMemory((PVOID)&adapterExtension->PortExtension[portNumber]->DeviceExtension->HybridInfo,
+ (PVOID)&dumpContext->Ports[i].HybridInfo,
+ sizeof(GP_LOG_HYBRID_INFORMATION_HEADER));
+ }
}
}
@@ -797,8 +834,6 @@ AhciHwInitialize (
//
// Turn on DPC Redirection if it's supported.
//
- // TODO : Revisit this : Disable these perf optimizations for now during bringup.
-#if !defined (_ARM64_)
if ((status == STOR_STATUS_SUCCESS) &&
((perfConfigData.Flags & STOR_PERF_DPC_REDIRECTION) != 0)) {
@@ -841,7 +876,6 @@ AhciHwInitialize (
NT_ASSERT(status == STOR_STATUS_SUCCESS);
}
-#endif
//
// async process to get all ports into running state
@@ -876,7 +910,6 @@ AhciHwPassiveInitialize (
// 2. check if ACPI supports turning off power on link
AhciAdapterEvaluateDSMMethod(adapterExtension);
-
//
// Get and cache D3Cold support.
//
@@ -886,8 +919,7 @@ AhciHwPassiveInitialize (
if (status == STOR_STATUS_SUCCESS) {
adapterExtension->StateFlags.D3ColdSupported = d3ColdSupported;
}
-
-
+
if (reportF1State) {
bufferSize += STOR_POFX_COMPONENT_IDLE_STATE_SIZE;
}
@@ -911,8 +943,11 @@ AhciHwPassiveInitialize (
if (IsD3ColdAllowed(adapterExtension)) {
adapterExtension->PoFxDevice->Flags = STOR_POFX_DEVICE_FLAG_ENABLE_D3_COLD;
}
+
+ // Indicate miniport opt-in adapter D3 wake support.
+ adapterExtension->PoFxDevice->Flags |= STOR_POFX_DEVICE_FLAG_ADAPTER_D3_WAKE;
- // indicate dump miniport can't bring adapter to active
+ // Indicate dump miniport can't bring adapter to active
adapterExtension->PoFxDevice->Flags |= STOR_POFX_DEVICE_FLAG_NO_DUMP_ACTIVE;
adapterExtension->PoFxDevice->Components[0].Version = STOR_POFX_COMPONENT_VERSION_V1;
@@ -948,7 +983,6 @@ AhciHwPassiveInitialize (
goto Exit;
}
-
// register success
adapterExtension->StateFlags.PoFxEnabled = TRUE;
adapterExtension->StateFlags.PoFxActive = TRUE;
@@ -983,7 +1017,6 @@ Return Value:
AhciPortAcpiDSMControl(AdapterExtension, (ULONG)-1, FALSE);
}
-
return;
}
@@ -1078,8 +1111,9 @@ AhciAdapterRemoval (
Release resources allocated for the adapter and its managed ports/devices
*/
{
- ULONG i;
- PVOID bufferToFree = NULL;
+ ULONG i;
+ PVOID bufferToFree = NULL;
+ PVOID executionHistoryToFree = NULL;
if (IsDumpMode(AdapterExtension)) {
return;
@@ -1129,6 +1163,13 @@ AhciAdapterRemoval (
AdapterExtension->PortExtension[i]->StateFlags.PoFxActive = FALSE;
}
+ if ((executionHistoryToFree == NULL) && (AdapterExtension->PortExtension[i]->ExecutionHistory != NULL)) {
+ executionHistoryToFree = AdapterExtension->PortExtension[i]->ExecutionHistory;
+ }
+
+ if (AdapterExtension->PortExtension[i]->ExecutionHistory != NULL) {
+ AdapterExtension->PortExtension[i]->ExecutionHistory = NULL;
+ }
AdapterExtension->PortExtension[i] = NULL;
}
@@ -1138,6 +1179,10 @@ AhciAdapterRemoval (
StorPortFreePool(AdapterExtension, bufferToFree);
}
+ if (executionHistoryToFree != NULL) {
+ StorPortFreePool(AdapterExtension, executionHistoryToFree);
+ }
+
return;
}
@@ -1274,7 +1319,8 @@ Return Value:
NT_ASSERT(adapterPower != NULL);
- StorPortDebugPrint(3, "StorAHCI - LPM: Adapter - %s\n", adapterPower->PowerState == StorPowerDeviceD0 ? "D0" : "D3");
+ StorPortDebugPrint(3, "StorAHCI - LPM: Adapter SystemIoBusNumber:%d - %s\n",
+ adapterExtension->SystemIoBusNumber, adapterPower->PowerState == StorPowerDeviceD0 ? "D0" : "D3");
if (adapterPower->PowerState == StorPowerDeviceD0) {
AhciAdapterPowerUp(adapterExtension); //power up
@@ -1296,12 +1342,12 @@ Return Value:
if (powerHints->Size >= sizeof(STOR_SYSTEM_POWER_HINTS)) {
- StorPortDebugPrint(3, "StorAHCI - LPM: Adapter - System Power Hint - State: %u - Latency: %u ms \n", powerHints->SystemPower, powerHints->ResumeLatencyMSec);
+ StorPortDebugPrint(3, "StorAHCI - LPM: Adapter SystemIoBusNumber:%d - System Power Hint - State: %u - Latency: %u ms\n",
+ adapterExtension->SystemIoBusNumber, powerHints->SystemPower, powerHints->ResumeLatencyMSec);
adapterExtension->SystemPowerHintState = powerHints->SystemPower;
adapterExtension->SystemPowerResumeLatencyMSec = powerHints->ResumeLatencyMSec;
-
if (adapterExtension->TracingEnabled) {
StorPortEtwEvent2(AdapterExtension,
NULL,
@@ -1361,6 +1407,15 @@ AhciHwResetBus (
status = AhciPortReset(adapterExtension->PortExtension[PathId], TRUE);
AhciInterruptSpinlockRelease(adapterExtension, MAXULONG, &lockhandle);
adapterExtension->PortExtension[PathId]->DeviceExtension[0].IoRecord.PortDriverResetCount++;
+
+ AhciTelemetryLogResetErrorRecovery(adapterExtension->PortExtension[PathId],
+ (PSTOR_ADDRESS)&(adapterExtension->PortExtension[PathId]->DeviceExtension->DeviceAddress),
+ AhciTelemetryEventIdResetBus,
+ "AhciHwResetBus",
+ 0,
+ "PortResetStatus",
+ status
+ );
}
return status;
@@ -1390,7 +1445,9 @@ AhciHwBuildIo (
NT_ASSERT(Srb->SrbStatus == SRB_STATUS_PENDING);
// SrbExtension is not Null-ed by Storport, so do it here.
- AhciZeroMemory((PCHAR)srbExtension, sizeof(AHCI_SRB_EXTENSION));
+ // Zero PRDT later when elements number in the SGL is available.
+ AhciZeroMemory((PCHAR)(&(srbExtension->AtaFunction)), (sizeof(AHCI_SRB_EXTENSION) - FIELD_OFFSET(AHCI_SRB_EXTENSION, AtaFunction)));
+ AhciZeroMemory((PCHAR)srbExtension, FIELD_OFFSET(AHCI_COMMAND_TABLE, PRDT));
channelExtension = adapterExtension->PortExtension[pathId];
@@ -1409,11 +1466,63 @@ AhciHwBuildIo (
if ( !IsPortValid(adapterExtension, pathId) ) {
Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
+ StorPortEtwChannelEvent2(adapterExtension,
+ NULL,
+ StorportEtwEventOperational,
+ AhciEtwEventBuildIO,
+ L"No device",
+ STORPORT_ETW_EVENT_KEYWORD_COMMAND_TRACE,
+ StorportEtwLevelError,
+ StorportEtwEventOpcodeInfo,
+ Srb,
+ L"function",
+ function,
+ L"srbFlags",
+ srbFlags);
+ goto exit;
+ }
+
+ //
+ // If the adapter was removed, fail this request.
+ // We first check to see if the adapter is removable so that we can
+ // avoid incurring a register access if it is not removable.
+ //
+ if (IsAdapterRemovable(adapterExtension) &&
+ IsAdapterRemoved(adapterExtension)) {
+ Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
+ StorPortEtwChannelEvent2(adapterExtension,
+ (channelExtension != NULL) ? ((PSTOR_ADDRESS) &(channelExtension->DeviceExtension->DeviceAddress)) : (NULL),
+ StorportEtwEventOperational,
+ AhciEtwEventBuildIO,
+ L"Adapter removed during BuildIo",
+ STORPORT_ETW_EVENT_KEYWORD_COMMAND_TRACE,
+ StorportEtwLevelError,
+ StorportEtwEventOpcodeInfo,
+ Srb,
+ L"function",
+ function,
+ L"srbFlags",
+ srbFlags);
goto exit;
}
}
switch (function) {
+ //
+ // Get the flag from Storport that tells us if the adapter is removable or not.
+ //
+ case SRB_FUNCTION_PNP: {
+ PSRBEX_DATA_PNP pnpData = (PSRBEX_DATA_PNP)SrbGetSrbExDataByType((PSTORAGE_REQUEST_BLOCK)Srb, SrbExDataTypePnP);
+ if (((pnpData->SrbPnPFlags & SRB_PNP_FLAGS_ADAPTER_REQUEST)) &&
+ (pnpData->PnPAction == StorQueryCapabilities) &&
+ (SrbGetDataTransferLength(Srb) >= sizeof(STOR_DEVICE_CAPABILITIES_EX))) {
+ PSTOR_DEVICE_CAPABILITIES_EX storCapabilities = (PSTOR_DEVICE_CAPABILITIES_EX)SrbGetDataBuffer(Srb);
+ adapterExtension->StateFlags.Removable = storCapabilities->Removable;
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+ }
+ break;
+ }
+
case SRB_FUNCTION_IO_CONTROL: {
if ((srbFlags & SRB_IOCTL_FLAGS_ADAPTER_REQUEST) == 0) {
@@ -1424,6 +1533,10 @@ AhciHwBuildIo (
if ( ( srbExtension->Sgl == NULL ) && ( IsDataTransferNeeded((PSTORAGE_REQUEST_BLOCK)Srb) ) ) {
srbExtension->Sgl = (PLOCAL_SCATTER_GATHER_LIST)StorPortGetScatterGatherList(adapterExtension, Srb);
}
+ if (srbExtension->Sgl != NULL) {
+ // Zero PRDT according to SGL elements number to avoid unnecessary CPU usage.
+ AhciZeroMemory((PCHAR)(srbExtension->CommandTable.PRDT), (srbExtension->Sgl->NumberOfElements * sizeof(AHCI_PRDT)));
+ }
}
}
@@ -1438,6 +1551,10 @@ AhciHwBuildIo (
if ( ( srbExtension->Sgl == NULL ) && ( IsDataTransferNeeded((PSTORAGE_REQUEST_BLOCK)Srb) ) ) {
srbExtension->Sgl = (PLOCAL_SCATTER_GATHER_LIST)StorPortGetScatterGatherList(adapterExtension, Srb);
}
+ if (srbExtension->Sgl != NULL) {
+ // Zero PRDT according to SGL elements number to avoid unnecessary CPU usage.
+ AhciZeroMemory((PCHAR)(srbExtension->CommandTable.PRDT), (srbExtension->Sgl->NumberOfElements * sizeof(AHCI_PRDT)));
+ }
}
break;
@@ -1475,7 +1592,7 @@ AhciHwStartIo (
)
/*
1. Process Adapter request
- 2. Bail out if it�s adapter request
+ 2. Bail out if it's adapter request
3. Validate Port Number, if not valid, bail out.
4. Process Device/Port request
@@ -1488,7 +1605,7 @@ AhciHwStartIo (
BOOLEAN adapterRequest = FALSE;
BOOLEAN processIO = FALSE;
- //1 Work on Adapter requests
+ //1 Work on Adapter requests
switch (function) {
case SRB_FUNCTION_PNP: {
PSRBEX_DATA_PNP pnpData = (PSRBEX_DATA_PNP)SrbGetSrbExDataByType((PSTORAGE_REQUEST_BLOCK)Srb, SrbExDataTypePnP);
@@ -1509,6 +1626,21 @@ AhciHwStartIo (
} else {
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
}
+
+ StorPortEtwChannelEvent2(adapterExtension,
+ NULL,
+ (Srb->SrbStatus == SRB_STATUS_SUCCESS) ? StorportEtwEventDiagnostic : StorportEtwEventOperational,
+ AhciEtwEventStartIO,
+ L"Processing PNP",
+ STORPORT_ETW_EVENT_KEYWORD_COMMAND_TRACE,
+ (Srb->SrbStatus == SRB_STATUS_SUCCESS) ? StorportEtwLevelInformational : StorportEtwLevelError,
+ StorportEtwEventOpcodeInfo,
+ Srb,
+ L"PnPAction",
+ pnpData->PnPAction,
+ L"SrbStatus",
+ Srb->SrbStatus);
+
//complete all Adapter PnP request
StorPortNotification(RequestComplete, AdapterExtension, Srb);
}
@@ -1563,21 +1695,62 @@ AhciHwStartIo (
// 2.1 All requests reach here should be for devices
if ( !IsPortValid(adapterExtension, pathId) ) {
Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
+
+ StorPortEtwChannelEvent8(adapterExtension,
+ NULL,
+ StorportEtwEventOperational,
+ AhciEtwEventStartIO,
+ L"Port has no device",
+ STORPORT_ETW_EVENT_KEYWORD_COMMAND_TRACE,
+ StorportEtwLevelError,
+ StorportEtwEventOpcodeInfo,
+ Srb,
+ L"AdapterNumber",
+ adapterExtension->AdapterNumber,
+ L"SystemIoBusNumber",
+ adapterExtension->SystemIoBusNumber,
+ L"SlotNumber",
+ adapterExtension->SlotNumber,
+ L"AhciBaseAddress",
+ adapterExtension->AhciBaseAddress,
+ L"PathId",
+ pathId,
+ L"Function",
+ Srb->Function,
+ L"SrbStatus",
+ Srb->SrbStatus,
+ NULL,
+ 0);
+
StorPortNotification(RequestComplete, AdapterExtension, Srb);
return TRUE;
}
- // 2.2 work on device requests
+ // 2.2 work on device requests
+ // Get channelExtension and storAddress to use for ETW Event logging
+ PAHCI_CHANNEL_EXTENSION channelExtension = adapterExtension->PortExtension[pathId];
+ PSTOR_ADDRESS storAddress = (PSTOR_ADDRESS)&(channelExtension->DeviceExtension->DeviceAddress);
+
switch (function) {
case SRB_FUNCTION_RESET_BUS: // this one may come from class driver, not port driver. same as AhciHwResetBus
case SRB_FUNCTION_RESET_DEVICE:
case SRB_FUNCTION_RESET_LOGICAL_UNIT: {
+
// these reset requests target to Port
AhciInterruptSpinlockAcquire(adapterExtension, pathId, &lockhandle);
Srb->SrbStatus = AhciPortReset(adapterExtension->PortExtension[pathId], TRUE) ? SRB_STATUS_SUCCESS : SRB_STATUS_ERROR;
StorPortNotification(RequestComplete, AdapterExtension, Srb);
AhciInterruptSpinlockRelease(adapterExtension, pathId, &lockhandle);
adapterExtension->PortExtension[pathId]->DeviceExtension[0].IoRecord.PortDriverResetCount++;
+
+ AhciTelemetryLogResetErrorRecovery(adapterExtension->PortExtension[pathId],
+ (PSTOR_ADDRESS)&(adapterExtension->PortExtension[pathId]->DeviceExtension->DeviceAddress),
+ AhciTelemetryEventIdResetDeviceRequest,
+ "AhciHwStartIo RESET Request",
+ 0,
+ "PortResetStatus",
+ Srb->SrbStatus
+ );
break;
}
@@ -1612,6 +1785,21 @@ AhciHwStartIo (
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
StorPortNotification(RequestComplete, AdapterExtension, Srb);
}
+
+ StorPortEtwChannelEvent2(adapterExtension,
+ storAddress,
+ (Srb->SrbStatus == SRB_STATUS_SUCCESS) ? StorportEtwEventDiagnostic : StorportEtwEventOperational,
+ AhciEtwEventStartIO,
+ L"Completed PnP request",
+ STORPORT_ETW_EVENT_KEYWORD_COMMAND_TRACE,
+ (Srb->SrbStatus == SRB_STATUS_SUCCESS) ? StorportEtwLevelInformational : StorportEtwLevelError,
+ StorportEtwEventOpcodeInfo,
+ Srb,
+ L"SrbPnPFlags",
+ pnpData->SrbPnPFlags,
+ L"PnPAction",
+ pnpData->PnPAction);
+
break;
}
@@ -1623,20 +1811,38 @@ AhciHwStartIo (
BOOLEAN sendStandby = (IsDumpHiberMode(adapterExtension) || IsDumpCrashMode(adapterExtension));
deviceParameters->StateFlags.SystemPoweringDown = TRUE;
+
+ USHORT *eventDescription;
if (adapterExtension->PortExtension[pathId]->DeviceExtension->SupportedCommands.SetDateAndTime == 0x1) {
IssueSetDateAndTimeCommand(adapterExtension->PortExtension[pathId], Srb, sendStandby);
processIO = TRUE;
+ eventDescription = L"Shutdown set date and time";
} else if (sendStandby) {
//in dump mode, this is the last Srb sent after SYNC CACHE, spin down the disk
PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension((PSTORAGE_REQUEST_BLOCK)Srb);
srbExtension->AtaFunction = ATA_FUNCTION_ATA_COMMAND;
SetCommandReg((&srbExtension->TaskFile.Current), IDE_COMMAND_STANDBY_IMMEDIATE);
processIO = TRUE;
+ eventDescription = L"Shutdown standby immediate";
} else {
Srb->SrbStatus = SRB_STATUS_SUCCESS;
+ eventDescription = L"Shutdown";
StorPortNotification(RequestComplete, AdapterExtension, Srb);
}
+ StorPortEtwEvent2(adapterExtension,
+ storAddress,
+ AhciEtwEventStartIO,
+ eventDescription,
+ STORPORT_ETW_EVENT_KEYWORD_COMMAND_TRACE,
+ StorportEtwLevelInformational,
+ StorportEtwEventOpcodeInfo,
+ Srb,
+ NULL,
+ 0,
+ NULL,
+ 0);
+
break;
}
@@ -1648,38 +1854,56 @@ AhciHwStartIo (
case SRB_FUNCTION_DUMP_POINTERS: {
ULONG status = STOR_STATUS_SUCCESS;
+ ULONG size = 0;
PAHCI_DUMP_CONTEXT dumpContext = NULL;
PMINIPORT_DUMP_POINTERS dumpPointers = (PMINIPORT_DUMP_POINTERS)SrbGetDataBuffer(Srb);
+ USHORT *eventDescription = L"Completed dump pointers";
+
if ( (dumpPointers == NULL) ||
(SrbGetDataTransferLength(Srb) < RTL_SIZEOF_THROUGH_FIELD(MINIPORT_DUMP_POINTERS, MiniportPrivateDumpData)) ) {
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+ eventDescription = L"Invalid dump pointers request";
} else {
+ size = sizeof(AHCI_DUMP_CONTEXT);
+
// allocate pool and zero the content
status = StorPortAllocatePool(AdapterExtension,
- sizeof(AHCI_DUMP_CONTEXT),
+ size,
AHCI_POOL_TAG,
(PVOID*)&dumpContext);
if ((status != STOR_STATUS_SUCCESS) || (dumpContext == NULL)) {
// we cannot continue if cannot get memory for ChannelExtension.
Srb->SrbStatus = SRB_STATUS_ERROR;
+ eventDescription = L"Allocate dump context failed";
} else {
dumpPointers->Version = DUMP_MINIPORT_VERSION_1;
dumpPointers->Size = sizeof(MINIPORT_DUMP_POINTERS);
- dumpPointers->MiniportPrivateDumpData = (PVOID)dumpContext;
+ AhciZeroMemory((PCHAR)dumpContext, size);
- AhciZeroMemory((PCHAR)dumpContext, sizeof(AHCI_DUMP_CONTEXT));
dumpContext->VendorID = adapterExtension->VendorID;
dumpContext->DeviceID = adapterExtension->DeviceID;
dumpContext->RevisionID = adapterExtension->RevisionID;
dumpContext->AhciBaseAddress = adapterExtension->AhciBaseAddress;
dumpContext->LogFlags = adapterExtension->LogFlags;
dumpContext->AdapterRegistryFlags = adapterExtension->RegistryFlags;
- dumpContext->DumpPortNumber = adapterExtension->PortExtension[pathId]->PortNumber;
- dumpContext->PortRegistryFlags = adapterExtension->PortExtension[pathId]->RegistryFlags;
+
+ dumpContext->PortCount = 1;
+
+ dumpContext->Ports[0].PortNumber = adapterExtension->PortExtension[pathId]->PortNumber;
+ dumpContext->Ports[0].PortRegistryFlags = adapterExtension->PortExtension[pathId]->RegistryFlags;
+
+ //
+ // Preserve Hybrid Disk Information.
+ //
+ if (IsDeviceHybridInfoSupported(adapterExtension->PortExtension[pathId])) {
+ StorPortMoveMemory((PVOID)&dumpContext->Ports[0].HybridInfo,
+ (PVOID)&adapterExtension->PortExtension[pathId]->DeviceExtension->HybridInfo,
+ sizeof(GP_LOG_HYBRID_INFORMATION_HEADER));
+ }
//
// Fill telemetry collection context - shared with diskdump.sys stack
@@ -1698,18 +1922,26 @@ AhciHwStartIo (
dumpContext->PrivateGPLogPageAddress = IDE_GP_LOG_CURRENT_DEVICE_INTERNAL_STATUS;
}
- //
- // Preserve Hybrid Disk Information.
- //
- if (IsDeviceHybridInfoSupported(adapterExtension->PortExtension[pathId])) {
- StorPortMoveMemory((PVOID)&dumpContext->HybridInfo,
- (PVOID)&adapterExtension->PortExtension[pathId]->DeviceExtension->HybridInfo,
- sizeof(GP_LOG_HYBRID_INFORMATION_HEADER));
- }
+ dumpPointers->MiniportPrivateDumpData = (PVOID)dumpContext;
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
}
+
+ StorPortEtwChannelEvent2(adapterExtension,
+ storAddress,
+ (Srb->SrbStatus == SRB_STATUS_SUCCESS) ? StorportEtwEventDiagnostic : StorportEtwEventOperational,
+ AhciEtwEventStartIO,
+ eventDescription,
+ STORPORT_ETW_EVENT_KEYWORD_COMMAND_TRACE,
+ (Srb->SrbStatus == SRB_STATUS_SUCCESS) ? StorportEtwLevelInformational : StorportEtwLevelError,
+ StorportEtwEventOpcodeInfo,
+ Srb,
+ L"SrbStatus",
+ Srb->SrbStatus,
+ L"TransferLen",
+ SrbGetDataTransferLength(Srb));
+
StorPortNotification(RequestComplete, AdapterExtension, Srb);
break;
}
@@ -1725,6 +1957,21 @@ AhciHwStartIo (
status = StorPortFreePool(AdapterExtension, dumpPointers->MiniportPrivateDumpData);
Srb->SrbStatus = (status == STOR_STATUS_SUCCESS) ? SRB_STATUS_SUCCESS : SRB_STATUS_ERROR;
}
+
+ StorPortEtwChannelEvent2(adapterExtension,
+ storAddress,
+ (Srb->SrbStatus == SRB_STATUS_SUCCESS) ? StorportEtwEventDiagnostic : StorportEtwEventOperational,
+ AhciEtwEventStartIO,
+ L"Completed free dump pointers",
+ STORPORT_ETW_EVENT_KEYWORD_COMMAND_TRACE,
+ (Srb->SrbStatus == SRB_STATUS_SUCCESS) ? StorportEtwLevelInformational : StorportEtwLevelError,
+ StorportEtwEventOpcodeInfo,
+ Srb,
+ L"SrbStatus",
+ Srb->SrbStatus,
+ L"TransferLen",
+ SrbGetDataTransferLength(Srb));
+
StorPortNotification(RequestComplete, AdapterExtension, Srb);
break;
}
@@ -1732,6 +1979,20 @@ AhciHwStartIo (
default: {
// for unsupported SRB: complete with status: SRB_STATUS_INVALID_REQUEST
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+
+ StorPortEtwEvent2(adapterExtension,
+ storAddress,
+ AhciEtwEventStartIO,
+ L"Invalid request",
+ STORPORT_ETW_EVENT_KEYWORD_COMMAND_TRACE,
+ StorportEtwLevelInformational,
+ StorportEtwEventOpcodeInfo,
+ Srb,
+ L"Function",
+ function,
+ NULL,
+ 0);
+
StorPortNotification(RequestComplete, AdapterExtension, Srb);
break;
}
@@ -1749,7 +2010,6 @@ AhciHwStartIo (
AhciProcessIo(adapterExtension->PortExtension[pathId], (PSTORAGE_REQUEST_BLOCK)Srb, FALSE);
ActivateQueue(adapterExtension->PortExtension[pathId], FALSE);
-
}
return TRUE;
@@ -1769,7 +2029,7 @@ Routine Description:
This routine must attempt one clear the interrupt on the HBA before it returns TRUE.
NOTE:
- The following StorPort routines shall not be called from the AhciHwInterrupt routine � StorPortCompleteAllRequests and StorPortDeviceBusy.
+ The following StorPort routines shall not be called from the AhciHwInterrupt routine - StorPortCompleteAllRequests and StorPortDeviceBusy.
The miniport could however request for a worker routine and make the calls in the worker routine.
Called by:
@@ -1823,7 +2083,6 @@ It performs:
"If there were errors, noted in the PxIS register, software performs error recovery actions (see section 6.2.2)."
AHCI 1.1 Section 6.2.2.1 Non-Queued Error Recovery (this may take a while, better queue a DPC)
Complete further processing in the worker routine and enable interrupts on the channel
- 6.1 Partial to Slumber auto transit
Affected Variables/Registers:
@@ -1872,12 +2131,36 @@ Return Values:
//call the correct error handling based on current hw queue workload type
sact = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SACT);
-
- if ((sact == MAXULONG) && IsAdapterRemoved(ChannelExtension)) {
+ if ((sact == MAXULONG) && IsAdapterRemoved(ChannelExtension->AdapterExtension)) {
// controller has been surprise removed
+ StorPortEtwChannelEvent8(ChannelExtension->AdapterExtension,
+ (ChannelExtension != NULL) ? (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress) : (NULL),
+ StorportEtwEventOperational,
+ AhciEtwEventHandleInterrupt,
+ L"Adapter surprise removed",
+ STORPORT_ETW_EVENT_KEYWORD_COMMAND_TRACE,
+ StorportEtwLevelWarning,
+ StorportEtwEventOpcodeInfo,
+ NULL,
+ L"pxis",
+ pxis.AsUlong,
+ L"ssts",
+ ssts.AsUlong,
+ L"serr",
+ serr.AsUlong,
+ L"cmd",
+ cmd.AsUlong,
+ L"sact",
+ sact,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 0);
return;
} else if (sact != 0) {
- //5.1 NCQ, Handle error processing
+ //5.1 NCQ, Handle error processing
ChannelExtension->StateFlags.CallAhciNcqErrorRecovery = 1;
//Give NCQ one chance
@@ -1903,7 +2186,32 @@ Return Values:
if (pxis.DMPS || pxis.PCS) {
cmd.AsUlong = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->CMD.AsUlong);
- if ((cmd.AsUlong == MAXULONG) && IsAdapterRemoved(ChannelExtension)) {
+ if ((cmd.AsUlong == MAXULONG) && IsAdapterRemoved(ChannelExtension->AdapterExtension)) {
+ StorPortEtwChannelEvent8(ChannelExtension->AdapterExtension,
+ (ChannelExtension != NULL) ? (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress) : (NULL),
+ StorportEtwEventOperational,
+ AhciEtwEventHandleInterrupt,
+ L"Adapter surprise removed",
+ STORPORT_ETW_EVENT_KEYWORD_COMMAND_TRACE,
+ StorportEtwLevelWarning,
+ StorportEtwEventOpcodeInfo,
+ NULL,
+ L"pxis",
+ pxis.AsUlong,
+ L"ssts",
+ ssts.AsUlong,
+ L"serr",
+ serr.AsUlong,
+ L"cmd",
+ cmd.AsUlong,
+ L"sact",
+ sact,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ 0);
return;
}
@@ -1937,13 +2245,13 @@ Return Values:
// PhyRdy Change Status
if (pxis.PRCS) {
//Hot plug removals are detected via the PxIS.PRCS bit that directly reflects the PxSERR.DIAG.N bit.
- //Note that PxSERR.DIAG.N is also set to �1� on insertions and during interface power management entry/exit.
+ //Note that PxSERR.DIAG.N is also set to '1' on insertions and during interface power management entry/exit.
serrMask.DIAG.N = 1;
StorPortWriteRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SERR.AsUlong, serrMask.AsUlong);
ssts.AsUlong = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SSTS.AsUlong);
- if ((ssts.AsUlong == MAXULONG) && IsAdapterRemoved(ChannelExtension)) {
+ if ((ssts.AsUlong == MAXULONG) && IsAdapterRemoved(ChannelExtension->AdapterExtension)) {
// controller has been surprise removed
return;
}
@@ -2053,7 +2361,7 @@ Return Values:
if (pxis.SDBS) {
pxisMask.SDBS = 1;
}
- // Descriptor Processed (A PRD with the �I� bit set has transferred all of its data)
+ // Descriptor Processed (A PRD with the 'I' bit set has transferred all of its data)
if (pxis.DPS) {
pxisMask.DPS = 1;
}
@@ -2066,8 +2374,33 @@ Return Values:
// preserve taskfile for using in command completion process
ChannelExtension->TaskFileData.AsUlong = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->TFD.AsUlong);
- if ((ChannelExtension->TaskFileData.AsUlong == MAXULONG) && IsAdapterRemoved(ChannelExtension)) {
+ if ((ChannelExtension->TaskFileData.AsUlong == MAXULONG) && IsAdapterRemoved(ChannelExtension->AdapterExtension)) {
// controller has been surprise removed
+ StorPortEtwChannelEvent8(ChannelExtension->AdapterExtension,
+ (ChannelExtension != NULL) ? (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress) : (NULL),
+ StorportEtwEventOperational,
+ AhciEtwEventHandleInterrupt,
+ L"Adapter surprise removed",
+ STORPORT_ETW_EVENT_KEYWORD_COMMAND_TRACE,
+ StorportEtwLevelWarning,
+ StorportEtwEventOpcodeInfo,
+ NULL,
+ L"pxis",
+ pxis.AsUlong,
+ L"ssts",
+ ssts.AsUlong,
+ L"serr",
+ serr.AsUlong,
+ L"cmd",
+ cmd.AsUlong,
+ L"sact",
+ sact,
+ L"StateFlags",
+ *(ULONGLONG *)&(ChannelExtension->StateFlags),
+ NULL,
+ 0,
+ NULL,
+ 0);
return;
}
@@ -2086,8 +2419,33 @@ Return Values:
ci = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->CI);
sact = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SACT);
- if (((ci == MAXULONG) || (sact == MAXULONG)) && IsAdapterRemoved(ChannelExtension)) {
+ if (((ci == MAXULONG) || (sact == MAXULONG)) && IsAdapterRemoved(ChannelExtension->AdapterExtension)) {
// controller has been surprise removed
+ StorPortEtwChannelEvent8(ChannelExtension->AdapterExtension,
+ (ChannelExtension != NULL) ? (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress) : (NULL),
+ StorportEtwEventOperational,
+ AhciEtwEventHandleInterrupt,
+ L"Adapter removed: complete cmd",
+ STORPORT_ETW_EVENT_KEYWORD_COMMAND_TRACE,
+ StorportEtwLevelWarning,
+ StorportEtwEventOpcodeInfo,
+ NULL,
+ L"pxis",
+ pxis.AsUlong,
+ L"ssts",
+ ssts.AsUlong,
+ L"serr",
+ serr.AsUlong,
+ L"cmd",
+ cmd.AsUlong,
+ L"is",
+ is,
+ L"ci",
+ ci,
+ L"sact",
+ sact,
+ NULL,
+ 0);
return;
}
@@ -2111,20 +2469,6 @@ Return Values:
RecordInterruptHistory(ChannelExtension, pxis.AsUlong, ssts.AsUlong, serr.AsUlong, ci, sact, 0x20010005); //AhciHwInterrupt No IO completed
}
- //6.1 Partial to Slumber auto transit
- if ((outstanding == 0) &&
- PartialToSlumberTransitionIsAllowed(ChannelExtension, &cmd)) {
-
- ULONG status;
-
- // convert interval value from ms to us. allow 20ms of coalescing with other timers
- status = StorPortRequestTimer(ChannelExtension->AdapterExtension, ChannelExtension->WorkerTimer, AhciAutoPartialToSlumber, ChannelExtension, ChannelExtension->AutoPartialToSlumberInterval * 1000, 20000);
-
- if (status == STOR_STATUS_SUCCESS) {
- StorPortDebugPrint(3, "StorAHCI - LPM: Port %02d - Transit into Slumber from Partial - Scheduled \n", ChannelExtension->PortNumber);
- }
- }
-
if (LogExecuteFullDetail(ChannelExtension->AdapterExtension->LogFlags)) {
RecordExecutionHistory(ChannelExtension, 0x10000005);//Exit AhciInterruptHandler
}
@@ -2356,7 +2700,8 @@ Return Value:
if (IsPortValid(adapterExtension, storAddrBtl8->Path)) {
PAHCI_CHANNEL_EXTENSION channelExtension = adapterExtension->PortExtension[storAddrBtl8->Path];
- StorPortDebugPrint(3, "StorAHCI - LPM: Port %02d - %s\n", storAddrBtl8->Path, unitControlPower->PowerState == StorPowerDeviceD0 ? "D0" : "D3");
+ StorPortDebugPrint(3, "StorAHCI - LPM: SystemIoBusNumber:%d Port:%02d - %s\n",
+ adapterExtension->SystemIoBusNumber, storAddrBtl8->Path, unitControlPower->PowerState == StorPowerDeviceD0 ? "D0" : "D3");
if (unitControlPower->PowerState == StorPowerDeviceD0) {
AhciPortPowerUp(channelExtension);
@@ -2379,16 +2724,15 @@ Return Value:
}
case ScsiUnitPoFxPowerInfo: {
- PSTOR_POFX_UNIT_POWER_INFO unitPowerInfo = (PSTOR_POFX_UNIT_POWER_INFO)Parameters;
- PSTOR_ADDR_BTL8 storAddrBtl8 = (PSTOR_ADDR_BTL8)unitPowerInfo->Header.Address;
- BOOLEAN d3ColdEnabled = FALSE;
+ PSTOR_POFX_UNIT_POWER_INFO unitPowerInfo = (PSTOR_POFX_UNIT_POWER_INFO)Parameters;
+ PSTOR_ADDR_BTL8 storAddrBtl8 = (PSTOR_ADDR_BTL8)unitPowerInfo->Header.Address;
+ BOOLEAN d3ColdEnabled = FALSE;
if (IsPortValid(adapterExtension, storAddrBtl8->Path)) {
- ULONG storStatus = STOR_STATUS_SUCCESS;
- ULONG bufferLength = STOR_POFX_DEVICE_V3_SIZE + STOR_POFX_COMPONENT_V2_SIZE + STOR_POFX_COMPONENT_IDLE_STATE_SIZE;
+ ULONG storStatus = STOR_STATUS_SUCCESS;
+ ULONG bufferLength = STOR_POFX_DEVICE_V3_SIZE + STOR_POFX_COMPONENT_V2_SIZE + STOR_POFX_COMPONENT_IDLE_STATE_SIZE;
PAHCI_CHANNEL_EXTENSION channelExtension = adapterExtension->PortExtension[storAddrBtl8->Path];
- BOOLEAN reportF1State = FALSE;
-
+ BOOLEAN reportF1State = FALSE;
//
// IdlePowerEnabled == TRUE indicates this unit is being
@@ -2417,7 +2761,6 @@ Return Value:
bufferLength,
AHCI_POOL_TAG,
(PVOID*)&channelExtension->PoFxDevice);
-
}
if (storStatus == STOR_STATUS_SUCCESS) {
@@ -2436,10 +2779,34 @@ Return Value:
channelExtension->PoFxDevice->Flags |= STOR_POFX_DEVICE_FLAG_NO_DUMP_ACTIVE;
//
- // If this is a drive with rotational media then enable adaptive D3 idle timeout.
+ // Disable idle debouncing if it's possible for us to
+ // initiate a Slumber transition.
+ // We set the Slumber timer when we get the Idle
+ // condition callback and cancel it when we get the
+ // Active condition callback. The slumber timer is
+ // typically set to 100ms and idle debouncing can add
+ // a bias of up to 1s. Significantly delaying Slumber
+ // entry can have a negative impact on power so we
+ // disable idle debouncing.
+ // CAP.SSC indicates if the HBA supports Slumber.
+ // CAP.SALP indicates if the HBA can automatically
+ // transition to Partial when idle, which is needed for
+ // us to subsequently initiate a Slumber transition.
+ //
+ if ((channelExtension->AdapterExtension->CAP.SSC) &&
+ (channelExtension->AdapterExtension->CAP.SALP) &&
+ IsDeviceSupportsHIPM(channelExtension->DeviceExtension[0].IdentifyDeviceData)) {
+ channelExtension->PoFxDevice->Flags |= STOR_POFX_DEVICE_FLAG_NO_IDLE_DEBOUNCE;
+ }
+
+ //
+ // If this is a drive with rotational media then enable adaptive D3 idle timeout, else if
+ // this is a SSD on an AOAC system, set the idle timeout flag and provide a minimum unit idle timeout.
//
if (DeviceIncursSeekPenalty(channelExtension)) {
channelExtension->PoFxDevice->Flags |= STOR_POFX_DEVICE_FLAG_ADAPTIVE_D3_IDLE_TIMEOUT;
+ } else if (IsReceivingSystemPowerHints(adapterExtension) && DeviceIncursNoSeekPenalty(channelExtension)) {
+ channelExtension->PoFxDevice->Flags |= STOR_POFX_DEVICE_FLAG_IDLE_TIMEOUT;
}
component->Version = STOR_POFX_COMPONENT_VERSION_V2;
@@ -2457,7 +2824,6 @@ Return Value:
component->FStates[0].ResidencyRequirement = 0;
component->FStates[0].NominalPower = STOR_POFX_UNKNOWN_POWER;
-
// registry runtime power management for Unit
storStatus = StorPortInitializePoFxPower(AdapterExtension,
(PSTOR_ADDRESS)storAddrBtl8,
@@ -2504,19 +2870,30 @@ Return Value:
case ScsiUnitPoFxPowerActive: {
PSTOR_POFX_ACTIVE_CONTEXT activeContext = (PSTOR_POFX_ACTIVE_CONTEXT)Parameters;
- PSTOR_ADDR_BTL8 storAddrBtl8 = (PSTOR_ADDR_BTL8)activeContext->Header.Address;
+ PSTOR_ADDR_BTL8 storAddrBtl8 = (PSTOR_ADDR_BTL8)activeContext->Header.Address;
- if ( IsPortValid(adapterExtension, storAddrBtl8->Path) && PortPoFxEnabled(adapterExtension->PortExtension[storAddrBtl8->Path]) ) {
+ if (IsPortValid(adapterExtension, storAddrBtl8->Path) && PortPoFxEnabled(adapterExtension->PortExtension[storAddrBtl8->Path])) {
PAHCI_CHANNEL_EXTENSION channelExtension = adapterExtension->PortExtension[storAddrBtl8->Path];
channelExtension->StateFlags.PoFxActive = activeContext->Active ? 1 : 0;
- StorPortDebugPrint(3, "StorAHCI - LPM: Port %02d - %s\n", channelExtension->PortNumber, activeContext->Active ? "ACTIVE" : "IDLE");
+ StorPortDebugPrint(3, "StorAHCI - LPM: SystemIoBusNumber:%d Port:%02d - %s\n",
+ adapterExtension->SystemIoBusNumber, channelExtension->PortNumber, activeContext->Active ? "ACTIVE" : "IDLE");
if (activeContext->Active) {
- ULONG busChangePending;
- ULONG restorePreservedSettingsPending;
+ ULONG busChangePending;
+ ULONG restorePreservedSettingsPending;
+ //
+ // Cancel the Slumber timer.
+ //
+ StorPortRequestTimer(channelExtension->AdapterExtension,
+ channelExtension->WorkerTimer,
+ AhciAutoPartialToSlumber,
+ channelExtension,
+ 0, 0);
+ StorPortDebugPrint(3, "StorAHCI - LPM: SystemIoBusNumber:%d Port:%02d - Transit into Slumber from Partial - Canceled\n",
+ adapterExtension->SystemIoBusNumber, channelExtension->PortNumber);
busChangePending = InterlockedBitTestAndReset((LONG*)&channelExtension->PoFxPendingWork, 1); //BusChange is at bit 1
restorePreservedSettingsPending = InterlockedBitTestAndReset((LONG*)&channelExtension->PoFxPendingWork, 0); //RestorePreservedSettings is at bit 0
@@ -2529,6 +2906,7 @@ Return Value:
if (restorePreservedSettingsPending == 1) {
// continue on processing RestorePreservedSettings
+ RecordExecutionHistory(channelExtension, 0x10050041); // RestorePreservedSettings continue in Unit Active
// Start the first command
IssuePreservedSettingCommands(channelExtension, NULL);
@@ -2538,10 +2916,30 @@ Return Value:
PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension((PSTORAGE_REQUEST_BLOCK)&channelExtension->Local.Srb);
if (srbExtension->AtaFunction != 0) {
AhciProcessIo(channelExtension, (PSTORAGE_REQUEST_BLOCK)&channelExtension->Local.Srb, FALSE);
+ ActivateQueue(channelExtension, FALSE);
}
}
}
} else {
+ //
+ // Attempt to start the Slumber timer now that we're idle.
+ // Use a tolerable delay of 20ms to allow coalescing with
+ // other timers.
+ //
+ if (PartialToSlumberTransitionIsAllowed(channelExtension, NULL)) {
+
+ status = StorPortRequestTimer(channelExtension->AdapterExtension,
+ channelExtension->WorkerTimer,
+ AhciAutoPartialToSlumber,
+ channelExtension,
+ channelExtension->AutoPartialToSlumberInterval * 1000, 20000);
+
+ if (status == STOR_STATUS_SUCCESS) {
+ StorPortDebugPrint(3, "StorAHCI - LPM: SystemIoBusNumber:%d Port:%02d - Transit into Slumber from Partial - Scheduled\n",
+ adapterExtension->SystemIoBusNumber, channelExtension->PortNumber);
+ }
+ }
+
}
} else {
status = ScsiUnitControlUnsuccessful;
@@ -2552,14 +2950,13 @@ Return Value:
case ScsiUnitPoFxPowerSetFState: {
PSTOR_POFX_FSTATE_CONTEXT fStateContext = (PSTOR_POFX_FSTATE_CONTEXT)Parameters;
- PSTOR_ADDR_BTL8 storAddrBtl8 = (PSTOR_ADDR_BTL8)fStateContext->Header.Address;
- PAHCI_CHANNEL_EXTENSION channelExtension = adapterExtension->PortExtension[storAddrBtl8->Path];
+ PSTOR_ADDR_BTL8 storAddrBtl8 = (PSTOR_ADDR_BTL8)fStateContext->Header.Address;
+ PAHCI_CHANNEL_EXTENSION channelExtension = adapterExtension->PortExtension[storAddrBtl8->Path];
- if ( IsPortValid(adapterExtension, storAddrBtl8->Path) && PortPoFxEnabled(channelExtension) ) {
+ if (IsPortValid(adapterExtension, storAddrBtl8->Path) && PortPoFxEnabled(channelExtension)) {
- StorPortDebugPrint(3, "StorAHCI - LPM: Port %02d - Transition from F%u to F%u\n", channelExtension->PortNumber,
- channelExtension->PoFxFState,
- fStateContext->FState);
+ StorPortDebugPrint(3, "StorAHCI - LPM: SystemIoBusNumber:%d Port:%02d - Transition from F%u to F%u\n",
+ adapterExtension->SystemIoBusNumber, channelExtension->PortNumber, channelExtension->PoFxFState, fStateContext->FState);
channelExtension->PoFxFState = (UCHAR)fStateContext->FState;
@@ -2607,6 +3004,16 @@ Return Value:
AhciPortFailAllIos(channelExtension, SRB_STATUS_NO_DEVICE, TRUE);
AhciInterruptSpinlockRelease(adapterExtension, channelExtension->PortNumber, &lockhandle);
+
+ ++(channelExtension->TotalCountSurpriseRemove);
+ AhciTelemetryLogResetErrorRecovery(channelExtension,
+ (PSTOR_ADDRESS)&(channelExtension->DeviceExtension->DeviceAddress),
+ AhciTelemetryEventIdSurpriseRemove,
+ "ScsiUnitSurpriseRemoval",
+ AHCI_TELEMETRY_FLAG_NOT_SUPPRESS_LOGGING,
+ NULL,
+ 0
+ );
}
break;
@@ -2629,4 +3036,3 @@ Return Value:
#pragma warning(default:4201)
#endif
-
diff --git a/storage/miniports/storahci/src/entrypts.h b/storage/miniports/storahci/src/entrypts.h
index 56adcb0e..df1aa9ea 100644
--- a/storage/miniports/storahci/src/entrypts.h
+++ b/storage/miniports/storahci/src/entrypts.h
@@ -23,6 +23,7 @@ Authors:
#pragma warning(disable:4214) // bit field types other than int
#pragma warning(disable:4201) // nameless struct/union
+#include "data.h"
#define AHCI_POOL_TAG 'ichA' // "Ahci" - StorAHCI miniport driver
@@ -34,10 +35,10 @@ Authors:
#define AHCI_MAX_NCQ_REQUEST_COUNT 32
#define KB (1024)
-#define AHCI_MAX_TRANSFER_LENGTH (128 * KB)
+#define AHCI_MAX_TRANSFER_LENGTH_DEFAULT (128 * KB)
+#define AHCI_MAX_TRANSFER_LENGTH (1024 * KB)
#define MAX_SETTINGS_PRESERVED 32
#define MAX_CRB_LOG_INDEX 64
-#define MAX_EXECUTION_HISTORY_ENTRY_COUNT 100
#define INQUIRYDATABUFFERSIZE 36
@@ -71,22 +72,18 @@ Authors:
// registry flags apply to port or device
typedef struct _CHANNEL_REGISTRY_FLAGS {
-
ULONG Reserved : 20;
-
} CHANNEL_REGISTRY_FLAGS, *PCHANNEL_REGISTRY_FLAGS;
// registry flags apply to the whole adapter
typedef struct _ADAPTER_REGISTRY_FLAGS {
- ULONG Reserved2 : 16;
-
+ ULONG Reserved2 : 13;
} ADAPTER_REGISTRY_FLAGS, *PADAPTER_REGISTRY_FLAGS;
typedef struct _CHANNEL_STATE_FLAGS {
-
ULONG Initialized : 1;
ULONG NoMoreIO : 1;
ULONG QueuePaused : 1;
@@ -112,31 +109,14 @@ typedef struct _CHANNEL_STATE_FLAGS {
ULONG NcqErrorRecoveryInProcess : 1;
ULONG PuisEnabled : 1;
- ULONG Reserved0 : 12;
+ ULONG IdentifyDeviceSuccess : 1;
+ ULONG NeedQDR : 1;
+ ULONG PowerUpInitializationInProgress : 1; //Note: this field indicates that init/preserved settings commands(invoked by power up) are not completed yet.
+ ULONG Reserved0 : 9;
ULONG Reserved1;
} CHANNEL_STATE_FLAGS, *PCHANNEL_STATE_FLAGS;
-typedef struct _ATA_IO_RECORD {
-
- ULONG SuccessCount;
-
- ULONG CrcErrorCount;
- ULONG MediaErrorCount;
- ULONG EndofMediaCount;
- ULONG IllegalCommandCount;
- ULONG AbortedCommandCount;
- ULONG DeviceFaultCount;
-
- ULONG OtherErrorCount;
-
- ULONG NcqReadLogErrorCount; // used to record the READ LOG EXT command error count when used for NCQ Error Recovery.
-
- ULONG PortDriverResetCount;
- ULONG TotalResetCount;
-
-} ATA_IO_RECORD, *PATA_IO_RECORD;
-
//
// Data structure to retrieve a Log Page
//
@@ -234,6 +214,7 @@ typedef struct _AHCI_DEVICE_EXTENSION {
ATA_SUPPORTED_GPL_PAGES SupportedGPLPages;
ATA_COMMAND_SUPPORTED SupportedCommands;
+
GP_LOG_HYBRID_INFORMATION_HEADER HybridInfo;
LONG HybridCachingMediumEnableRefs;
@@ -242,8 +223,21 @@ typedef struct _AHCI_DEVICE_EXTENSION {
PUSHORT ReadLogExtPageData;
STOR_PHYSICAL_ADDRESS ReadLogExtPageDataPhysicalAddress;
+ BOOLEAN UpdateCachedLogPageInfo;
+ UCHAR Reserved[3];
} AHCI_DEVICE_EXTENSION, *PAHCI_DEVICE_EXTENSION;
+typedef struct _AHCI_DEVICE_LOG_PAGE_INFO {
+
+ ATA_GPL_PAGES_TO_QUERY QueryLogPages;
+
+ ATA_SUPPORTED_GPL_PAGES SupportedGPLPages;
+ ATA_COMMAND_SUPPORTED SupportedCommands;
+
+ DOWNLOAD_MICROCODE_CAPABILITIES FirmwareUpdate;
+
+} AHCI_DEVICE_LOG_PAGE_INFO, *PAHCI_DEVICE_LOG_PAGE_INFO;
+
typedef struct _COMMAND_HISTORY {
union { //0x10 bytes
ATA_TASK_FILE InitialTaskFile;
@@ -258,36 +252,6 @@ typedef struct _COMMAND_HISTORY {
ULONG SrbStatus;
} COMMAND_HISTORY, *PCOMMAND_HISTORY;
-typedef struct _SLOT_MANAGER {
- ULONG HighPriorityAttribute;
-
- ULONG NCQueueSlice;
- ULONG NormalQueueSlice;
- ULONG SingleIoSlice;
-
- ULONG CommandsIssued;
- ULONG CommandsToComplete;
-
- //
- // These issued slices are used to determine the type of command
- // being programmed to adapter.
- // They are used instead of reading PxCI and PxSACT.
- //
- ULONG NCQueueSliceIssued;
- ULONG NormalQueueSliceIssued;
- ULONG SingleIoSliceIssued;
-
- ULONG Reserved;
-
-} SLOT_MANAGER, *PSLOT_MANAGER;
-
-typedef struct _EXECUTION_HISTORY {
- ULONG Function;
- ULONG IS;
- SLOT_MANAGER SlotManager; //SLOT_MANAGER from _AHCI_CHANNEL_EXTENSION
- ULONG Px[0x10]; //Px registers value, end to AHCI_SNOTIFICATION -- SNTF
-} EXECUTION_HISTORY, *PEXECUTION_HISTORY;
-
typedef struct _SLOT_STATE_FLAGS {
UCHAR FUA :1;
UCHAR Reserved :7;
@@ -356,9 +320,13 @@ typedef struct _LOCAL_SCATTER_GATHER_LIST {
ULONG NumberOfElements;
ULONG_PTR Reserved;
_Field_size_(NumberOfElements)
- STOR_SCATTER_GATHER_ELEMENT List[33];
+ STOR_SCATTER_GATHER_ELEMENT List[257];
} LOCAL_SCATTER_GATHER_LIST, *PLOCAL_SCATTER_GATHER_LIST;
+//
+// Note: When adding new members to AHCI SRB extension, make sure the uncached extension allocation
+// is successful in dump mode because there is MAX size limitation.
+//
typedef struct _AHCI_SRB_EXTENSION {
AHCI_COMMAND_TABLE CommandTable; // this field MUST to be the first one as it's asked to be 128 aligned
USHORT AtaFunction; // if this field is 0, it means the command does not need to be sent to device
@@ -371,6 +339,7 @@ typedef struct _AHCI_SRB_EXTENSION {
AHCI_H2D_REGISTER_FIS Cfis; // info related to Host to Device FIS (0x27)
};
PVOID DataBuffer; // go with Cdb field when needed.
+ STOR_PHYSICAL_ADDRESS DataBufferPhysicalAddress; // Physical address of DataBuffer.
ULONG DataTransferLength; // go with Cdb field when needed.
PLOCAL_SCATTER_GATHER_LIST Sgl; // pointer to the local or port provided SGL
LOCAL_SCATTER_GATHER_LIST LocalSgl; // local SGL
@@ -381,6 +350,7 @@ typedef struct _AHCI_SRB_EXTENSION {
ULONGLONG StartTime;
PVOID ResultBuffer; // for requests marked with ATA_FLAGS_RETURN_RESULTS
+ STOR_PHYSICAL_ADDRESS ResultBufferPhysicalAddress; // Physical address of ResultBuffer.
ULONG ResultBufferLength;
} AHCI_SRB_EXTENSION, *PAHCI_SRB_EXTENSION;
@@ -411,10 +381,16 @@ typedef struct _STORAHCI_QUEUE {
ULONG DeepestDepth;
ULONG DepthHistoryIndex;
ULONG DepthHistory[100];
+ LARGE_INTEGER LastTimeStampAddQueue;
+ LARGE_INTEGER LastTimeStampRemoveQueue;
} STORAHCI_QUEUE, *PSTORAHCI_QUEUE;
typedef struct _AHCI_ADAPTER_EXTENSION AHCI_ADAPTER_EXTENSION, *PAHCI_ADAPTER_EXTENSION;
+//
+// Note: When adding new members to AHCI channel extension, make sure the uncached extension allocation
+// is successful in dump mode because there is MAX size limitation.
+//
typedef struct _AHCI_CHANNEL_EXTENSION {
//Adapter Characteristics
PAHCI_ADAPTER_EXTENSION AdapterExtension;
@@ -458,6 +434,7 @@ typedef struct _AHCI_CHANNEL_EXTENSION {
} AutoPartialToSlumberDbgStats;
+
struct {
ULONG RestorePreservedSettings :1; //NOTE: this field is accessed in InterlockedBitTestAndReset, bit position (currently: 0) is used there.
ULONG BusChange :1; //NOTE: this field is accessed in InterlockedBitTestAndReset, bit position (currently: 1) is used there.
@@ -498,8 +475,29 @@ typedef struct _AHCI_CHANNEL_EXTENSION {
//Logging
UCHAR CommandHistoryNextAvailableIndex;
COMMAND_HISTORY CommandHistory[64];
+
UCHAR ExecutionHistoryNextAvailableIndex;
- EXECUTION_HISTORY ExecutionHistory[MAX_EXECUTION_HISTORY_ENTRY_COUNT];
+ PEXECUTION_HISTORY ExecutionHistory; // For non-dump mode, contains MAX_EXECUTION_HISTORY_ENTRY_COUNT elements.
+
+//Statistics counters for telemetry event.
+ ULONG TotalCountPortReset;
+ ULONG TotalCountRunningStartFailed;
+ ULONG TotalCountPortErrorRecovery;
+ ULONG TotalCountNonQueuedErrorRecovery;
+ ULONG TotalCountNCQError;
+ ULONG TotalCountNCQErrorRecoveryComplete;
+ ULONG TotalCountSurpriseRemove;
+ ULONG TotalCountPowerSettingNotification;
+ ULONGLONG LastLogResetErrorRecoveryTime;
+ ULONG TotalCountPowerUp;
+ ULONG TotalCountPowerDown;
+ ULONG TotalPortStartTime;
+ ULONG TotalCountBusChange;
+ ULONG DeviceFailureThrottleFlag;
+
+//Statistics for tracking DPC.
+ LARGE_INTEGER LastTimeStampDpcStart;
+ LARGE_INTEGER LastTimeStampDpcCompletion;
} AHCI_CHANNEL_EXTENSION, *PAHCI_CHANNEL_EXTENSION;
@@ -512,13 +510,15 @@ typedef struct _ADAPTER_STATE_FLAGS {
ULONG SupportsAcpiDSM : 1; // indicates if the system has _DSM method implemented to control port/device power. when the value is 1, the _DSM method at least supports powering on all connected devices.
ULONG Removed : 1;
+
ULONG InterruptMessagePerPort : 1;
ULONG D3ColdSupported : 1;
ULONG D3ColdEnabled : 1;
ULONG UseAdapterF1InsteadOfD3 : 1;
+ ULONG Removable : 1;
- ULONG Reserved : 21;
+ ULONG Reserved : 20;
} ADAPTER_STATE_FLAGS, *PADAPTER_STATE_FLAGS;
@@ -595,6 +595,19 @@ typedef struct _AHCI_ADAPTER_EXTENSION {
} AHCI_ADAPTER_EXTENSION, *PAHCI_ADAPTER_EXTENSION;
// information that will be transferred to dump/hibernate environment
+
+typedef struct _AHCI_DUMP_PORT_CONTEXT {
+
+ ULONG PortNumber;
+ CHANNEL_REGISTRY_FLAGS PortRegistryFlags;
+
+ //
+ // Hybrid Disk Information Log
+ //
+ GP_LOG_HYBRID_INFORMATION_HEADER HybridInfo;
+
+} AHCI_DUMP_PORT_CONTEXT, *PAHCI_DUMP_PORT_CONTEXT;
+
typedef struct _AHCI_DUMP_CONTEXT {
// adapter information
USHORT VendorID;
@@ -607,10 +620,6 @@ typedef struct _AHCI_DUMP_CONTEXT {
ADAPTER_LOG_FLAGS LogFlags; // internal log levels
ADAPTER_REGISTRY_FLAGS AdapterRegistryFlags;
- // port information
- ULONG DumpPortNumber;
- CHANNEL_REGISTRY_FLAGS PortRegistryFlags;
-
//
// Device telemetry descriptors for the boot device
//
@@ -618,12 +627,25 @@ typedef struct _AHCI_DUMP_CONTEXT {
ULONG PrivateGPLogPageAddress;
//
- // Hybrid Disk Information Log
+ // Port information of dump devices
//
- GP_LOG_HYBRID_INFORMATION_HEADER HybridInfo;
+ ULONG PortCount;
+ AHCI_DUMP_PORT_CONTEXT Ports[1];
} AHCI_DUMP_CONTEXT, *PAHCI_DUMP_CONTEXT;
+typedef struct _ATA_COMMAND_ERROR_LOG {
+ ULONG Version;
+ ULONG Size;
+ CHANNEL_STATE_FLAGS StateFlags;
+ CHANNEL_START_STATE StartState;
+ STORAGE_REQUEST_BLOCK Srb;
+ CDB Cdb; // To differentiate SRBs if the struct is reused
+ UCHAR Command; // ATA taksfile/AHCI FIS payload
+ UCHAR AtaStatus;
+ UCHAR AtaError;
+} ATA_COMMAND_ERROR, *PATA_COMMAND_ERROR;
+
// Storport miniport driver entry routines, with prefix: "AhciHw"
sp_DRIVER_INITIALIZE DriverEntry;
@@ -669,8 +691,6 @@ AhciDeviceStart (
extern ULONG AhciPublicGPLogTableAddresses[TC_PUBLIC_DEVICEDUMP_CONTENT_GPLOG_MAX];
extern ULONG AhciGPLogPageIntoPrivate;
-
-
#if _MSC_VER >= 1200
#pragma warning(pop)
#else
@@ -678,4 +698,3 @@ extern ULONG AhciGPLogPageIntoPrivate;
#pragma warning(default:4201)
#endif
-
diff --git a/storage/miniports/storahci/src/generic.h b/storage/miniports/storahci/src/generic.h
index 4595820b..1deedeaf 100644
--- a/storage/miniports/storahci/src/generic.h
+++ b/storage/miniports/storahci/src/generic.h
@@ -28,7 +28,6 @@ Revision History:
#include "srbhelper.h"
-
// storahci header files
#include "common.h"
#include "ahci.h"
@@ -168,4 +167,3 @@ typedef struct _SENDCMDOUTPARAMS {
#define DISABLE_SMART 0xD9
#define RETURN_SMART_STATUS 0xDA
#define ENABLE_DISABLE_AUTO_OFFLINE 0xDB
-
diff --git a/storage/miniports/storahci/src/hbastat.c b/storage/miniports/storahci/src/hbastat.c
index fc518675..21c502d5 100644
--- a/storage/miniports/storahci/src/hbastat.c
+++ b/storage/miniports/storahci/src/hbastat.c
@@ -1,4 +1,4 @@
-/*++
+/*++
Copyright (C) Microsoft Corporation, 2009
@@ -12,7 +12,7 @@ Abstract:
Notes:
-Revision History:
+Revision History:
--*/
@@ -92,11 +92,11 @@ Return value:
}
//10.4.3 HBA Reset
- //If the HBA becomes unusable for multiple ports, and a software reset or port reset does not correct the problem, software may reset the entire HBA by setting GHC.HR to �1�. When software sets the GHC.HR bit to �1�, the HBA shall perform an internal reset action.
+ //If the HBA becomes unusable for multiple ports, and a software reset or port reset does not correct the problem, software may reset the entire HBA by setting GHC.HR to ‘1’. When software sets the GHC.HR bit to ‘1’, the HBA shall perform an internal reset action.
ghc.HR = 1;
StorPortWriteRegisterUlong(AdapterExtension, &abar->GHC.AsUlong, ghc.AsUlong);
- //The bit shall be cleared to �0� by the HBA when the reset is complete. A software write of �0� to GHC.HR shall have no effect. To perform the HBA reset, software sets GHC.HR to �1� and may poll until this bit is read to be �0�, at which point software knows that the HBA reset has completed.
+ //The bit shall be cleared to ‘0’ by the HBA when the reset is complete. A software write of ‘0’ to GHC.HR shall have no effect. To perform the HBA reset, software sets GHC.HR to ‘1’ and may poll until this bit is read to be ‘0’, at which point software knows that the HBA reset has completed.
ghc.AsUlong = StorPortReadRegisterUlong(AdapterExtension, &abar->GHC.AsUlong);
//5.2.2.1 H:Init
//5.2.2.2 H:WaitForAhciEnable
@@ -105,13 +105,13 @@ Return value:
ghc.AsUlong = StorPortReadRegisterUlong(AdapterExtension, &abar->GHC.AsUlong);
}
- //If the HBA has not cleared GHC.HR to �0� within 1 second of software setting GHC.HR to �1�, the HBA is in a hung or locked state.
+ //If the HBA has not cleared GHC.HR to ‘0’ within 1 second of software setting GHC.HR to ‘1’, the HBA is in a hung or locked state.
if(i == 50) {
AdapterExtension->ErrorFlags = (1 << 29);
return FALSE;
}
- //When GHC.HR is set to �1�, GHC.AE, GHC.IE, the IS register, and all port register fields (except PxFB/PxFBU/PxCLB/PxCLBU) that are not HwInit in the HBA�s register memory space are reset. The HBA�s configuration space and all other global registers/bits are not affected by setting GHC.HR to �1�. Any HwInit bits in the port specific registers are not affected by setting GHC.HR to �1�. The port specific registers PxFB, PxFBU, PxCLB, and PxCLBU are not affected by setting GHC.HR to �1�. If the HBA supports staggered spin-up, the PxCMD.SUD bit will be reset to �0�; software is responsible for setting the PxCMD.SUD and PxSCTL.DET fields appropriately such that communication can be established on the Serial ATA link. If the HBA does not support staggered spin-up, the HBA reset shall cause a COMRESET to be sent on the port
+ //When GHC.HR is set to ‘1’, GHC.AE, GHC.IE, the IS register, and all port register fields (except PxFB/PxFBU/PxCLB/PxCLBU) that are not HwInit in the HBA’s register memory space are reset. The HBA’s configuration space and all other global registers/bits are not affected by setting GHC.HR to ‘1’. Any HwInit bits in the port specific registers are not affected by setting GHC.HR to ‘1’. The port specific registers PxFB, PxFBU, PxCLB, and PxCLBU are not affected by setting GHC.HR to ‘1’. If the HBA supports staggered spin-up, the PxCMD.SUD bit will be reset to ‘0’; software is responsible for setting the PxCMD.SUD and PxSCTL.DET fields appropriately such that communication can be established on the Serial ATA link. If the HBA does not support staggered spin-up, the HBA reset shall cause a COMRESET to be sent on the port
return TRUE;
}
@@ -124,10 +124,10 @@ AhciCOMRESET(
)
/*
PHY Reset:COMRESET
- SCTL.DET Controls the HBA�s device detection and interface initialization.
+ SCTL.DET Controls the HBA’s device detection and interface initialization.
DET=1 Performs interface communication initialization sequence to establish communication. This is functionally equivalent to a hard reset and results in the interface being reset and communications reinitialized. While this field is 1h, COMRESET is transmitted on the interface.
Software should leave the DET field set to 1h for a minimum of 1 millisecond to ensure that a COMRESET is sent on the interface.
- since we are in 5.3.2.3 P:NotRunning and PxCMD.SUD = �0� does this still take us to P:StartComm?
+ since we are in 5.3.2.3 P:NotRunning and PxCMD.SUD = ‘0’ does this still take us to P:StartComm?
Called By:
AhciPortReset,AhciNonQueuedErrorRecovery,P_Running_WaitWhileDET1,AhciHwControlIdeStart
It assumes:
@@ -191,7 +191,7 @@ Return Values:
StorPortWriteRegisterUlong(ChannelExtension->AdapterExtension, &Px->SCTL.AsUlong, sctl.AsUlong);
//2.2 Wait for DET to be set
- // AHCI 10.4.2 After clearing PxSCTL.DET to 0h, software should wait for communication to be re-established as indicated by bit 0 of PxSSTS.DET being set to �1�.
+ // AHCI 10.4.2 After clearing PxSCTL.DET to 0h, software should wait for communication to be re-established as indicated by bit 0 of PxSSTS.DET being set to ‘1’.
// typically, it will be done in 10ms. max wait 30ms to be safe
StorPortStallExecution(50);
ssts.AsUlong = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &Px->SSTS.AsUlong);
@@ -279,8 +279,8 @@ Return value:
//1.1 Clear CMD.ST
cmd.AsUlong = StorPortReadRegisterUlong(adapterExtension, &Px->CMD.AsUlong);
//AHCI 10.3.2 on FRE it says:
- //Software shall not clear this [FRE] bit while PxCMD.ST remains set to �1�."
- //System software places a port into the idle state by clearing PxCMD.ST and waiting for PxCMD.CR to return �0� when read.
+ //Software shall not clear this [FRE] bit while PxCMD.ST remains set to ‘1’."
+ //System software places a port into the idle state by clearing PxCMD.ST and waiting for PxCMD.CR to return ‘0’ when read.
cmd.ST = 0;
StorPortWriteRegisterUlong(adapterExtension, &Px->CMD.AsUlong, cmd.AsUlong);
@@ -304,7 +304,7 @@ Return value:
tfd.AsUlong = StorPortReadRegisterUlong(adapterExtension, &ChannelExtension->Px->TFD.AsUlong);
if (tfd.STS.BSY) {
- // AHCI 3.3.7 Command List Override (CLO): Setting this bit to �1� causes PxTFD.STS.BSY and PxTFD.STS.DRQ to be cleared to �0�.
+ // AHCI 3.3.7 Command List Override (CLO): Setting this bit to ‘1’ causes PxTFD.STS.BSY and PxTFD.STS.DRQ to be cleared to ‘0’.
// This allows a software reset to be transmitted to the device regardless of whether the BSY and DRQ bits are still set in the PxTFD.STS register.
// Do this to make sure the port can stop
@@ -323,9 +323,9 @@ Return value:
StorPortStallExecution(5000); //5 milliseconds
}
- //AHCI 10.4.2 If PxCMD.CR or PxCMD.FR do not clear to �0� correctly, then software may attempt a port reset or a full HBA reset to recover.
+ //AHCI 10.4.2 If PxCMD.CR or PxCMD.FR do not clear to ‘0’ correctly, then software may attempt a port reset or a full HBA reset to recover.
if (i == 101) {
- RecordExecutionHistory(ChannelExtension, 0x10350011); // P_NotRunning, PxCMD.CR or PxCMD.FR do not clear to �0� correctly
+ RecordExecutionHistory(ChannelExtension, 0x10350011); // P_NotRunning, PxCMD.CR or PxCMD.FR do not clear to ‘0’ correctly
return FALSE;
}
@@ -339,17 +339,17 @@ Return value:
StorPortStallExecution(50); //50 microseconds
}
- //If CI does not clear to �0� correctly abort the stop
+ //If CI does not clear to ‘0’ correctly abort the stop
if (i == 101) {
- RecordExecutionHistory(ChannelExtension, 0x10360011); // P_NotRunning, CI does not clear to �0�
+ RecordExecutionHistory(ChannelExtension, 0x10360011); // P_NotRunning, CI does not clear to ‘0’
return FALSE;
}
//2.1 Clear CMD.FRE
cmd.AsUlong = StorPortReadRegisterUlong(adapterExtension, &Px->CMD.AsUlong);
if( (cmd.FRE | cmd.FR) != 0 ) {
- //If PxCMD.FRE is set to �1�, software should clear it to �0� and wait at least 500 milliseconds for PxCMD.FR to return �0� when read.
- //AHCI 10.3.2 Software shall not clear this bit while PxCMD.ST or PxCMD.CR is set to �1�.
+ //If PxCMD.FRE is set to ‘1’, software should clear it to ‘0’ and wait at least 500 milliseconds for PxCMD.FR to return ‘0’ when read.
+ //AHCI 10.3.2 Software shall not clear this bit while PxCMD.ST or PxCMD.CR is set to ‘1’.
cmd.FRE = 0;
StorPortWriteRegisterUlong(adapterExtension, &Px->CMD.AsUlong, cmd.AsUlong);
@@ -371,18 +371,18 @@ Return value:
StorPortStallExecution(5000); // 5 milliseconds
}
- if ( i == 101 ) { //If PxCMD.CR or PxCMD.FR do not clear to �0� correctly, then software may attempt a port reset or a full HBA reset to recover.
+ if ( i == 101 ) { //If PxCMD.CR or PxCMD.FR do not clear to ‘0’ correctly, then software may attempt a port reset or a full HBA reset to recover.
if (supportsCLO) {
- RecordExecutionHistory(ChannelExtension, 0x10380011); // P_NotRunning, PxCMD.CR or PxCMD.FR do not clear to �0�, CLO enabled
+ RecordExecutionHistory(ChannelExtension, 0x10380011); // P_NotRunning, PxCMD.CR or PxCMD.FR do not clear to ‘0’, CLO enabled
} else {
- RecordExecutionHistory(ChannelExtension, 0x10370011); // P_NotRunning, PxCMD.CR or PxCMD.FR do not clear to �0�, CLO not enabled
+ RecordExecutionHistory(ChannelExtension, 0x10370011); // P_NotRunning, PxCMD.CR or PxCMD.FR do not clear to ‘0’, CLO not enabled
}
return FALSE;
}
}
//2.2 wait for CLO to clear
- // AHCI 3.3.7 Software must wait for CLO to be cleared to �0� before setting PxCMD.ST to �1�.
+ // AHCI 3.3.7 Software must wait for CLO to be cleared to ‘0’ before setting PxCMD.ST to ‘1’.
// register bit CLO might be set in this function, and it should have been cleared before function exit.
if ( supportsCLO && (cmd.CLO == 0) ) {
for (i = 1; i < 101; i++) {
@@ -394,7 +394,7 @@ Return value:
}
if ( i == 101 ) {
- RecordExecutionHistory(ChannelExtension, 0x10390011); // P_NotRunning, PxCMD.CLO not clear to �0�, CLO enabled
+ RecordExecutionHistory(ChannelExtension, 0x10390011); // P_NotRunning, PxCMD.CLO not clear to ‘0’, CLO enabled
return FALSE;
}
}
@@ -464,6 +464,14 @@ RunNextPort(
} else {
//starting all ports process is completed.
adapterExtension->InRunningPortsProcess = FALSE;
+
+ //
+ // Note: If we are at DIRQL when get here, it implies previous port start finishes quickly since no
+ // timer scheduled during port start. Then there is no need to log the port start time.
+ //
+ if (!AtDIRQL) {
+ AhciPortStartTelemetry(adapterExtension);
+ }
}
return;
@@ -588,7 +596,7 @@ It performs:
1.2 Next, is the port somehow already running?
1.3 Make sure the device knows it is supposed to be spun up
1.4 Check to make sure that FR and CR are both 0. Attempt to bring the controller into a consistent state by stopping the controller.
- 1.5 CMD.ST has to be set, when that happens check to see that PxSSTS.DET is not �4h�
+ 1.5 CMD.ST has to be set, when that happens check to see that PxSSTS.DET is not ‘4h’
2.1 Dispatch to the current state (states are responsible for selecting the next state)
@@ -633,7 +641,6 @@ Return Values:
return TRUE;
}
-
//1.3 Make sure the device knows it is supposed to be spun up
cmd.SUD = 1;
StorPortWriteRegisterUlong(adapterExtension, &px->CMD.AsUlong, cmd.AsUlong);
@@ -662,7 +669,7 @@ Return Values:
}
}
- //1.5 CMD.ST has to be set, when that happens check to see that PxSSTS.DET is not �4h�
+ //1.5 CMD.ST has to be set, when that happens check to see that PxSSTS.DET is not ‘4h’
ssts.AsUlong = StorPortReadRegisterUlong(adapterExtension, &px->SSTS.AsUlong);
if( ssts.DET == 0x4) {
P_Running_StartFailed(ChannelExtension, TimerCallbackProcess);
@@ -1088,10 +1095,10 @@ Affected Variables/Registers:
*/
{
- AHCI_COMMAND cmd;
- AHCI_TASK_FILE_DATA tfd;
- AHCI_SERIAL_ATA_ERROR serr;
- USHORT totalstarttime;
+ AHCI_COMMAND cmd;
+ AHCI_TASK_FILE_DATA tfd;
+ AHCI_SERIAL_ATA_ERROR serr;
+ USHORT totalstarttime;
PAHCI_ADAPTER_EXTENSION adapterExtension = ChannelExtension->AdapterExtension;
@@ -1099,7 +1106,7 @@ WaitOnBSYDRQ_Start:
RecordExecutionHistory(ChannelExtension, 0x0000001a);//P_Running_WaitOnBSYDRQ
tfd.AsUlong = StorPortReadRegisterUlong(adapterExtension, &ChannelExtension->Px->TFD.AsUlong);
- //1.1 Enable BSY and DRQ to go to 0
+ //1.1 Enable BSY and DRQ to go to 0
if ( (tfd.STS.BSY) || (tfd.STS.DRQ) ) {
//When [serr.DIAG.X is] set to one this bit indicates a COMINIT signal was received. This bit is reflected in the P0IS.PCS bit.
//to allow the TFD to be updated serr.DIAG.X must be cleared.
@@ -1107,10 +1114,10 @@ WaitOnBSYDRQ_Start:
serr.DIAG.X = 1;
StorPortWriteRegisterUlong(adapterExtension, &ChannelExtension->Px->SERR.AsUlong, serr.AsUlong);
}
- //3.1 Set ST to 1
+ //3.1 Set ST to 1
if ( ( tfd.STS.BSY == 0) && ( tfd.STS.DRQ == 0) ) {
- STOR_LOCK_HANDLE lockhandle = {InterruptLock, 0};
- BOOLEAN needSpinLock;
+ STOR_LOCK_HANDLE lockhandle = { InterruptLock, 0 };
+ BOOLEAN needSpinLock;
if ( TimerCallbackProcess && (ChannelExtension->StartState.DirectStartInProcess == 1) ) {
//This is timer callback and a direct port start process has been started separately, bail out this one.
@@ -1124,11 +1131,11 @@ WaitOnBSYDRQ_Start:
AhciInterruptSpinlockAcquire(ChannelExtension->AdapterExtension, ChannelExtension->PortNumber, &lockhandle);
}
- //3.2 Enable Interrupts on the channel (AHCI 1.1 Section 10.1.2 - 7)
+ //3.2 Enable Interrupts on the channel (AHCI 1.1 Section 10.1.2 - 7)
PortClearPendingInterrupt(ChannelExtension);
Set_PxIE(ChannelExtension, &ChannelExtension->Px->IE);
- //We made it! Set ST and start the IO we have collected!
+ //We made it! Set ST and start the IO we have collected!
cmd.AsUlong = StorPortReadRegisterUlong(adapterExtension, &ChannelExtension->Px->CMD.AsUlong);
cmd.ST = 1;
StorPortWriteRegisterUlong(adapterExtension, &ChannelExtension->Px->CMD.AsUlong, cmd.AsUlong);
@@ -1138,7 +1145,19 @@ WaitOnBSYDRQ_Start:
StorPortDebugPrint(3, "StorAHCI - LPM: Port %02d - Port Started\n", ChannelExtension->PortNumber);
- //Start requests on this Port
+ //
+ // Note: If ChannelStateBSYDRQCount is larger than 50, which implies the other counts are
+ // all cleared to 0 according to port start state machine implementation. But typically
+ // WaitOnBSYDRQ is always the most significant time consuming phase of port start, so the
+ // total port start time here is still able to reflect the rough port start status.
+ //
+ ChannelExtension->TotalPortStartTime = (ULONG)(ChannelExtension->StartState.ChannelStateDETCount +
+ ChannelExtension->StartState.ChannelStateDET1Count +
+ ChannelExtension->StartState.ChannelStateDET3Count +
+ ChannelExtension->StartState.ChannelStateFRECount +
+ (ChannelExtension->StartState.ChannelStateBSYDRQCount * 2)) * 10;
+
+ //Start requests on this Port
ActivateQueue(ChannelExtension, TRUE);
ChannelExtension->StartState.DirectStartInProcess = 0;
@@ -1149,16 +1168,20 @@ WaitOnBSYDRQ_Start:
AhciInterruptSpinlockRelease(ChannelExtension->AdapterExtension, ChannelExtension->PortNumber, &lockhandle);
}
+ if (ChannelExtension->StateFlags.NeedQDR) {
+ StorPortIssueDpc(ChannelExtension->AdapterExtension, &(ChannelExtension->BusChangeDpc), ChannelExtension, NULL);
+ ChannelExtension->StateFlags.NeedQDR = FALSE;
+ }
+
RunNextPort(ChannelExtension, (!TimerCallbackProcess && ChannelExtension->StartState.AtDIRQL));
return;
} else {
- //2.3 After waiting for the remainder of the 60 second maximum Channel Start time for BSY and DRQ to clear, give up
- //Some big HDDs takes close to 20 second to spin up
+ //2.3 After waiting for the remainder of the 60 second maximum Channel Start time for BSY and DRQ to clear, give up
+ //Some big HDDs takes close to 20 second to spin up
ULONG portStartTimeoutIn10MS = (AHCI_PORT_START_TIMEOUT_IN_SECONDS * 100);
-
// calculate the total time in unit of 10 ms.
totalstarttime = ChannelExtension->StartState.ChannelStateDETCount +
ChannelExtension->StartState.ChannelStateDET1Count +
@@ -1170,7 +1193,7 @@ WaitOnBSYDRQ_Start:
P_Running_StartFailed(ChannelExtension, TimerCallbackProcess);
RecordExecutionHistory(ChannelExtension, 0x00ff001a);//P_Running_WaitOnBSYDRQ timed out
return;
- //2.2 After a total amount of 1 second working on the start COMRESET
+ //2.2 After a total amount of 1 second working on the start COMRESET
} else if ( ChannelExtension->StartState.ChannelStateBSYDRQCount == 50 ){
//Stop FRE,FR in preparation for RESET
if ( !P_NotRunning(ChannelExtension, ChannelExtension->Px) ){
@@ -1196,7 +1219,7 @@ WaitOnBSYDRQ_Start:
RecordExecutionHistory(ChannelExtension, 0x00fd001a);//P_Running_WaitOnBSYDRQ crossing 1 second. COMRESET done, going to WaitOnDET3
P_Running_WaitOnDET3(ChannelExtension, TimerCallbackProcess);
return;
- //2.1 Wait for the rest of the 4 seconds for BSY and DRQ to clear
+ //2.1 Wait for the rest of the 4 seconds for BSY and DRQ to clear
} else {
ChannelExtension->StartState.ChannelStateBSYDRQCount++;
RecordExecutionHistory(ChannelExtension, 0x0008001a);//P_Running_WaitOnBSYDRQ still waiting
@@ -1244,8 +1267,21 @@ Affected Variables/Registers:
none
*/
{
- STOR_LOCK_HANDLE lockhandle = {InterruptLock, 0};
- BOOLEAN needSpinLock;
+ STOR_LOCK_HANDLE lockhandle = { InterruptLock, 0 };
+ BOOLEAN needSpinLock;
+
+ ++(ChannelExtension->TotalCountRunningStartFailed);
+ //
+ // Note: If ChannelStateBSYDRQCount is larger than 50, which implies the other counts are
+ // all cleared to 0 according to port start state machine implementation. But typically
+ // WaitOnBSYDRQ is always the most significant time consuming phase of port start, so the
+ // total port start time here is still able to reflect the rough port start status.
+ //
+ ChannelExtension->TotalPortStartTime = (ULONG)(ChannelExtension->StartState.ChannelStateDETCount +
+ ChannelExtension->StartState.ChannelStateDET1Count +
+ ChannelExtension->StartState.ChannelStateDET3Count +
+ ChannelExtension->StartState.ChannelStateFRECount +
+ (ChannelExtension->StartState.ChannelStateBSYDRQCount * 2)) * 10;
if ( TimerCallbackProcess && (ChannelExtension->StartState.DirectStartInProcess == 1) ) {
//This is timer callback and a direct port start process has been started separately, bail out this one.
@@ -1259,7 +1295,7 @@ Affected Variables/Registers:
AhciInterruptSpinlockAcquire(ChannelExtension->AdapterExtension, ChannelExtension->PortNumber, &lockhandle);
}
- //1.1 update state machines
+ //1.1 update state machines
ChannelExtension->StartState.ChannelNextStartState = StartFailed;
ChannelExtension->StateFlags.IgnoreHotplugInterrupt = FALSE;
ChannelExtension->StateFlags.D3ColdEnabled = FALSE; //this flag may be set to "TRUE" for last connected device, clear it when no device connected.
@@ -1281,7 +1317,7 @@ Affected Variables/Registers:
AhciZeroMemory((PCHAR)&ChannelExtension->DeviceExtension->SupportedGPLPages, sizeof(ATA_SUPPORTED_GPL_PAGES));
AhciZeroMemory((PCHAR)&ChannelExtension->DeviceExtension->SupportedCommands, sizeof(ATA_COMMAND_SUPPORTED));
- //1.2 clear out the programmed slots
+ //1.2 clear out the programmed slots
ChannelExtension->SlotManager.CommandsToComplete = GetOccupiedSlots(ChannelExtension);
ChannelExtension->SlotManager.CommandsIssued = 0;
ChannelExtension->SlotManager.NCQueueSliceIssued = 0;
@@ -1292,11 +1328,11 @@ Affected Variables/Registers:
ChannelExtension->SlotManager.SingleIoSlice = 0;
ChannelExtension->SlotManager.HighPriorityAttribute = 0;
- //1.3 Enable Interrupts on the Channel (AHCI 1.1 Section 10.1.2 - 7)
+ //1.3 Enable Interrupts on the Channel (AHCI 1.1 Section 10.1.2 - 7)
PortClearPendingInterrupt(ChannelExtension);
Set_PxIE(ChannelExtension, &ChannelExtension->Px->IE);
- //2.1 Call AhciPortFailAllIos to complete all outstanding commands now that ChannelNextStartState is StartFailed
+ //2.1 Call AhciPortFailAllIos to complete all outstanding commands now that ChannelNextStartState is StartFailed
AhciPortFailAllIos(ChannelExtension, SRB_STATUS_NO_DEVICE, TRUE);
ChannelExtension->StartState.DirectStartInProcess = 0;
@@ -1320,11 +1356,11 @@ AHCI 1.1 Section 6.2.2.1
"The flow for system software to recover from an error when non-queued commands are issued is as follows:
Reads PxCI to see which commands are still outstanding
Reads PxCMD.CCS to determine the slot that the HBA was processing when the error occurred
- Clears PxCMD.ST to �0� to reset the PxCI register, waits for PxCMD.CR to clear to �0�
+ Clears PxCMD.ST to ‘0’ to reset the PxCI register, waits for PxCMD.CR to clear to ‘0’
Clears any error bits in PxSERR to enable capturing new errors.
Clears status bits in PxIS as appropriate
- If PxTFD.STS.BSY or PxTFD.STS.DRQ is set to �1�, issue a COMRESET to the device to put it in an idle state
- Sets PxCMD.ST to �1� to enable issuing new commands
+ If PxTFD.STS.BSY or PxTFD.STS.DRQ is set to ‘1’, issue a COMRESET to the device to put it in an idle state
+ Sets PxCMD.ST to ‘1’ to enable issuing new commands
It assumes:
Called asynchronously
@@ -1343,10 +1379,10 @@ It performs:
1.1 Initialize
1.2 Reads PxCI to see which commands are still outstanding
1.3 Reads PxCMD.CCS to determine the slot that the HBA was processing when the error occurred
- 1.4.1 Clears PxCMD.ST to �0� to reset the PxCI register, waits for PxCMD.CR to clear to �0�
+ 1.4.1 Clears PxCMD.ST to ‘0’ to reset the PxCI register, waits for PxCMD.CR to clear to ‘0’
1.5 Clears any error bits in PxSERR to enable capturing new errors.
1.6 Clears status bits in PxIS as appropriate
- 1.4.2 If PxTFD.STS.BSY or PxTFD.STS.DRQ is set to �1�, issue a COMRESET to the device to put it in an idle state
+ 1.4.2 If PxTFD.STS.BSY or PxTFD.STS.DRQ is set to ‘1’, issue a COMRESET to the device to put it in an idle state
1.4.3 If a COMRESET was issued, restore Preserved Settings
1.4.4 Start the channel
@@ -1374,6 +1410,16 @@ Affected Variables/Registers:
//1.1 Initialize variables
RecordExecutionHistory(ChannelExtension, 0x00000013);//AhciNonQueuedErrorRecovery
+ ++(ChannelExtension->TotalCountNonQueuedErrorRecovery);
+ AhciTelemetryLogResetErrorRecovery(ChannelExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciTelemetryEventIdNonqueuedErrorRecovery,
+ "AhciNonQueuedErrorRecovery",
+ 0,
+ NULL,
+ 0
+ );
+
senseSrb = NULL;
performedCOMRESET = FALSE;
@@ -1383,7 +1429,7 @@ Affected Variables/Registers:
//1.3 Reads PxCMD.CCS to determine the slot that the HBA was processing when the error occurred
cmd.AsUlong = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->CMD.AsUlong);
- //1.4 Clears PxCMD.ST to �0� to reset the PxCI register, waits for PxCMD.CR to clear to �0�
+ //1.4 Clears PxCMD.ST to ‘0’ to reset the PxCI register, waits for PxCMD.CR to clear to ‘0’
if ( !P_NotRunning(ChannelExtension, ChannelExtension->Px) ){ //This clears PxCI
RecordExecutionHistory(ChannelExtension, 0x10160013);//AhciNonQueuedErrorRecovery, Port Stop Failed
AhciPortReset(ChannelExtension, FALSE);
@@ -1434,6 +1480,10 @@ Affected Variables/Registers:
// Keep in mind although Px.CMD.ST was just shut off, we are working with the previous snapshot of ST.
if (cmd.ST == 1) {
+
+ ULONG storStatus = STOR_STATUS_NOT_IMPLEMENTED;
+ STOR_REQUEST_INFO requestInfo = {0};
+
srbExtension = GetSrbExtension(ChannelExtension->Slot[failingCommand].Srb);
// Remove the errant command from the Commands Issued.
ci &= ~(1 << failingCommand);
@@ -1448,7 +1498,16 @@ Affected Variables/Registers:
// Fill in the status of the command
srbExtension->AtaStatus = ChannelExtension->TaskFileData.STS.AsUchar;
srbExtension->AtaError = ChannelExtension->TaskFileData.ERR;
- ChannelExtension->Slot[failingCommand].Srb->SrbStatus = SRB_STATUS_ERROR;
+
+ // Check whether the failed command is paging IO, if so, return busy status to indicate storport to retry it.
+ storStatus = StorPortGetRequestInfo(ChannelExtension, (PSCSI_REQUEST_BLOCK)ChannelExtension->Slot[failingCommand].Srb, &requestInfo);
+ if ((storStatus == STOR_STATUS_SUCCESS) &&
+ (requestInfo.Flags & REQUEST_INFO_PAGING_IO_FLAG)) {
+ ChannelExtension->Slot[failingCommand].Srb->SrbStatus = SRB_STATUS_BUSY;
+ } else {
+ ChannelExtension->Slot[failingCommand].Srb->SrbStatus = SRB_STATUS_ERROR;
+ }
+
// Handle Request Sense if needed
if ( NeedRequestSense(ChannelExtension->Slot[failingCommand].Srb) ) {
// This is for ATAPI device only
@@ -1476,7 +1535,7 @@ Affected Variables/Registers:
//1.6 Clears status bits in PxIS as appropriate
//Handled in the Interrupt routine
- //1.4.2 If PxTFD.STS.BSY or PxTFD.STS.DRQ is set to �1�, issue a COMRESET to the device to put it in an idle state
+ //1.4.2 If PxTFD.STS.BSY or PxTFD.STS.DRQ is set to ‘1’, issue a COMRESET to the device to put it in an idle state
tfd.AsUlong = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->TFD.AsUlong);
if(tfd.STS.BSY || tfd.STS.DRQ) {
@@ -1527,12 +1586,22 @@ NcqErrorRecoveryCompletion (
*/
{
PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb);
- ULONG issuedCommands = (ULONG)(ULONG_PTR)srbExtension->CompletionContext;
- STOR_LOCK_HANDLE lockhandle = {InterruptLock, 0};
- BOOLEAN fallBacktoReset = FALSE;
+ ULONG issuedCommands = (ULONG)(ULONG_PTR)srbExtension->CompletionContext;
+ STOR_LOCK_HANDLE lockhandle = {InterruptLock, 0};
+ BOOLEAN fallBacktoReset = FALSE;
RecordExecutionHistory(ChannelExtension, 0x0000001b); //Enter NcqErrorRecoveryCompletion
+ ++(ChannelExtension->TotalCountNCQErrorRecoveryComplete);
+ AhciTelemetryLogResetErrorRecovery(ChannelExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciTelemetryEventIdNCQErrorRecoveryComplete,
+ "NcqErrorRecoveryCompletion",
+ 0,
+ NULL,
+ 0
+ );
+
//
// In case of reset happened when Read Log command was executing, all requests have been returned back to port driver.
// There is no more recovery work this routine needs to do.
@@ -1553,9 +1622,9 @@ NcqErrorRecoveryCompletion (
// Other commands will be put back into NCQ slices and will be issued again to adapter.
//
PGP_LOG_NCQ_COMMAND_ERROR ncqErrorLog = (PGP_LOG_NCQ_COMMAND_ERROR)ChannelExtension->DeviceExtension->ReadLogExtPageData;
- UCHAR failingCommand;
- PSTORAGE_REQUEST_BLOCK failingSrb = NULL;
- PAHCI_SRB_EXTENSION failingSrbExtension = NULL;
+ UCHAR failingCommand;
+ PSTORAGE_REQUEST_BLOCK failingSrb = NULL;
+ PAHCI_SRB_EXTENSION failingSrbExtension = NULL;
NT_ASSERT(ncqErrorLog->NonQueuedCmd == 0);
NT_ASSERT(ncqErrorLog->NcqTag != 0);
@@ -1569,71 +1638,89 @@ NcqErrorRecoveryCompletion (
if (((1 << failingCommand) & issuedCommands) != 0) {
failingSrb = ChannelExtension->Slot[failingCommand].Srb;
- NT_ASSERT(failingSrb != NULL);
-
- failingSrbExtension = GetSrbExtension(failingSrb);
//
- // Record error and status
- //
- failingSrbExtension->AtaStatus = ncqErrorLog->Status;
- failingSrbExtension->AtaError = ncqErrorLog->Error;
+ // If the surprise remove happens just after the NCQ error handling, then
+ // there is chance that the failingSrb is NULL here.
+ //
+ if (failingSrb != NULL) {
+ failingSrbExtension = GetSrbExtension(failingSrb);
- if( IsReturnResults(failingSrbExtension->Flags) ) {
- SetReturnRegisterValues(ChannelExtension, failingSrb, NULL);
- }
+ //
+ // Record error and status
+ //
+ failingSrbExtension->AtaStatus = ncqErrorLog->Status;
+ failingSrbExtension->AtaError = ncqErrorLog->Error;
- //
- // Get Sense Data from log, or from translation.
- //
- if ((ChannelExtension->DeviceExtension->IdentifyDeviceData->SerialAtaFeaturesSupported.NCQAutosense == 1) &&
- (ncqErrorLog->SenseKey != SCSI_SENSE_NO_SENSE)) {
+ if( IsReturnResults(failingSrbExtension->Flags) ) {
+ SetReturnRegisterValues(ChannelExtension, failingSrb, NULL);
+ }
- StorPortDebugPrint(3, "StorAHCI - Port %02d - NCQ Error Recovery: NCQ Error Log read successfully. Sense Data returned: %02X/%02X/%02X\n",
- ChannelExtension->PortNumber, ncqErrorLog->SenseKey, ncqErrorLog->ASC, ncqErrorLog->ASCQ);
+ //
+ // Get Sense Data from log, or from translation.
+ //
+ if ((ChannelExtension->DeviceExtension->IdentifyDeviceData->SerialAtaFeaturesSupported.NCQAutosense == 1) &&
+ (ncqErrorLog->SenseKey != SCSI_SENSE_NO_SENSE)) {
+
+ StorPortDebugPrint(3, "StorAHCI - Port %02d - NCQ Error Recovery: NCQ Error Log read successfully. Sense Data returned: %02X/%02X/%02X\n",
+ ChannelExtension->PortNumber, ncqErrorLog->SenseKey, ncqErrorLog->ASC, ncqErrorLog->ASCQ);
+
+ AhciSetSenseData(failingSrb, SRB_STATUS_ERROR, ncqErrorLog->SenseKey, ncqErrorLog->ASC, ncqErrorLog->ASCQ);
+ } else {
+ //
+ // Set SrbStatus indicates it's an error condition.
+ // Sense data will be translated from Error register in ReleaseSlottedCommand()
+ //
+ StorPortDebugPrint(3, "StorAHCI - Port %02d - NCQ Error Recovery: NCQ Error Log read successfully. No Sense Data returned\n", ChannelExtension->PortNumber);
+
+ failingSrb->SrbStatus = SRB_STATUS_ERROR;
+ AtaMapError(ChannelExtension, failingSrb, ChannelExtension->Slot[failingCommand].StateFlags.FUA);
+ }
- AhciSetSenseData(failingSrb, SRB_STATUS_ERROR, ncqErrorLog->SenseKey, ncqErrorLog->ASC, ncqErrorLog->ASCQ);
- } else {
//
- // Set SrbStatus indicates it's an error condition.
- // Sense data will be translated from Error register in ReleaseSlottedCommand()
+ // Inform ReleaseSlottedCommand() function that sense data has been set.
//
- StorPortDebugPrint(3, "StorAHCI - Port %02d - NCQ Error Recovery: NCQ Error Log read successfully. No Sense Data returned\n", ChannelExtension->PortNumber);
+ SETMASK(failingSrbExtension->Flags, ATA_FLAGS_SENSEDATA_SET);
- failingSrb->SrbStatus = SRB_STATUS_ERROR;
- AtaMapError(ChannelExtension, failingSrb, ChannelExtension->Slot[failingCommand].StateFlags.FUA);
- }
+ //
+ // Acquire spinlock before touching Slots.
+ //
+ AhciInterruptSpinlockAcquire(ChannelExtension->AdapterExtension, ChannelExtension->PortNumber, &lockhandle);
- //
- // Inform ReleaseSlottedCommand() function that sense data has been set.
- //
- SETMASK(failingSrbExtension->Flags, ATA_FLAGS_SENSEDATA_SET);
+ //
+ // Remove the failing command from NCQ Slice.
+ // Put back other previous outstanding commands.
+ //
+ ChannelExtension->SlotManager.NCQueueSlice &= ~(1 << failingCommand);
- //
- // Acquire spinlock before touching Slots.
- //
- AhciInterruptSpinlockAcquire(ChannelExtension->AdapterExtension, ChannelExtension->PortNumber, &lockhandle);
+ //
+ // Clear the NCQ Error Recovery state flag, so that queue will be resumed in ReleaseSlottedCommand().
+ //
+ ChannelExtension->StateFlags.NcqErrorRecoveryInProcess = 0;
- //
- // Remove the failing command from NCQ Slice.
- // Put back other previous outstanding commands.
- //
- ChannelExtension->SlotManager.NCQueueSlice &= ~(1 << failingCommand);
+ //
+ // Complete the failing command.
+ //
+ ChannelExtension->SlotManager.CommandsToComplete |= (1 << failingCommand);
+ ReleaseSlottedCommand(ChannelExtension, (UCHAR)failingCommand, TRUE);
- //
- // Clear the NCQ Error Recovery state flag, so that queue will be resumed in ReleaseSlottedCommand().
- //
- ChannelExtension->StateFlags.NcqErrorRecoveryInProcess = 0;
+ ActivateQueue(ChannelExtension, TRUE);
- //
- // Complete the failing command.
- //
- ChannelExtension->SlotManager.CommandsToComplete |= (1 << failingCommand);
- ReleaseSlottedCommand(ChannelExtension, (UCHAR)failingCommand, TRUE);
+ AhciInterruptSpinlockRelease(ChannelExtension->AdapterExtension, ChannelExtension->PortNumber, &lockhandle);
- ActivateQueue(ChannelExtension, TRUE);
+ } else {
+ //
+ // If failingSrb is NULL, clear the NCQ Error Recovery state flag.
+ //
+ ChannelExtension->StateFlags.NcqErrorRecoveryInProcess = 0;
- AhciInterruptSpinlockRelease(ChannelExtension->AdapterExtension, ChannelExtension->PortNumber, &lockhandle);
+ StorPortDebugPrint(3, "StorAHCI - Port %02d - NCQ Error Recovery: NCQ Error Log read successfully, but the failing srb is NULL!\n", ChannelExtension->PortNumber);
+
+ //
+ // Capture the scenarios that failing srb is NULL, need investigate cases other than surprise remove.
+ //
+ NT_ASSERT(failingSrb != NULL);
+ }
} else {
StorPortDebugPrint(3, "StorAHCI - Port %02d - NCQ Error Recovery: NCQ Tag doesn't belong to issued commands.\n", ChannelExtension->PortNumber);
@@ -1695,13 +1782,13 @@ AHCI 1.1 Section 6.2.2.2 Native Command Queuing Error Recovery
The flow for system software to recover from an error when native command queuing commands are
issued is as follows:
- � Reads PxSACT to see which commands have not yet completed
- � Clears PxCMD.ST to �0� to reset the PxCI and PxSACT registers, waits for PxCMD.CR to clear to �0�
- � Clears any error bits in PxSERR to enable capturing new errors.
- � Clears status bits in PxIS as appropriate
- � If PxTFD.STS.BSY or PxTFD.STS.DRQ is set to �1�, issue a COMRESET to the device to put it in an idle state
- � Sets PxCMD.ST to �1� to enable issuing new commands
- � Issue READ LOG EXT to determine the cause of the error condition if software did not have to perform a reset (COMRESET or software reset) as part of the error recovery
+ • Reads PxSACT to see which commands have not yet completed
+ • Clears PxCMD.ST to ‘0’ to reset the PxCI and PxSACT registers, waits for PxCMD.CR to clear to ‘0’
+ • Clears any error bits in PxSERR to enable capturing new errors.
+ • Clears status bits in PxIS as appropriate
+ • If PxTFD.STS.BSY or PxTFD.STS.DRQ is set to ‘1’, issue a COMRESET to the device to put it in an idle state
+ • Sets PxCMD.ST to ‘1’ to enable issuing new commands
+ • Issue READ LOG EXT to determine the cause of the error condition if software did not have to perform a reset (COMRESET or software reset) as part of the error recovery
Software then either completes commands that did not finish with error to higher level software, or reissues
them to the device.
@@ -1733,6 +1820,15 @@ Called by:
//
RecordExecutionHistory(ChannelExtension, 0x00000014); //AhciNcqErrorRecovery
+ AhciTelemetryLogResetErrorRecovery(ChannelExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciTelemetryEventIdNCQErrorRecovery,
+ "AhciNcqErrorRecovery Enter",
+ 0,
+ NULL,
+ 0
+ );
+
//
// Reads PxSACT and PxCI to see which commands are still outstanding
//
@@ -1742,7 +1838,7 @@ Called by:
#endif
//
- // Clears PxCMD.ST to �0�, waits for PxCMD.CR to clear to �0�
+ // Clears PxCMD.ST to ‘0’, waits for PxCMD.CR to clear to ‘0’
// If it doesn't succeed, issue COMRESET to recover.
//
if ( !P_NotRunning(ChannelExtension, ChannelExtension->Px) ) {
@@ -1761,7 +1857,7 @@ Called by:
if (needCOMRESET == FALSE) {
//
- // If PxTFD.STS.BSY or PxTFD.STS.DRQ is set to �1�, issue a COMRESET to the device to put it in an idle state
+ // If PxTFD.STS.BSY or PxTFD.STS.DRQ is set to ‘1’, issue a COMRESET to the device to put it in an idle state
// ChannelExtension->TaskFileData has been read from register in ISR.
//
if ((ChannelExtension->TaskFileData.STS.BSY != 0) || (ChannelExtension->TaskFileData.STS.DRQ != 0)) {
@@ -1863,6 +1959,15 @@ Called by:
RecordExecutionHistory(ChannelExtension, 0x10000014); //Exit AhciNcqErrorRecovery
+ AhciTelemetryLogResetErrorRecovery(ChannelExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciTelemetryEventIdNCQErrorRecovery,
+ "AhciNcqErrorRecovery Exit",
+ 0,
+ NULL,
+ 0
+ );
+
return;
}
@@ -1886,6 +1991,44 @@ Return Values:
None
*/
{
+ ++(ChannelExtension->TotalCountPortErrorRecovery);
+ AhciTelemetryLogResetErrorRecovery(ChannelExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciTelemetryEventIdPortErrorRecovery,
+ "AhciPortErrorRecovery",
+ 0,
+ NULL,
+ 0
+ );
+
+ // Log the StateFlags
+ StorPortEtwChannelEvent8(ChannelExtension->AdapterExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ StorportEtwEventOperational,
+ AhciEtwEventHandleInterrupt,
+ L"AhciPortErrorRecovery",
+ STORPORT_ETW_EVENT_KEYWORD_COMMAND_TRACE,
+ StorportEtwLevelError,
+ StorportEtwEventOpcodeInfo,
+ NULL,
+ L"StateFlags",
+ *(ULONGLONG *)&(ChannelExtension->StateFlags),
+ L"PortErrRecovery",
+ ChannelExtension->TotalCountPortErrorRecovery,
+ L"StartState",
+ *(ULONGLONG *)&(ChannelExtension->StartState),
+ L"PortReset",
+ ChannelExtension->TotalCountPortReset,
+ L"RunningStrtFail",
+ ChannelExtension->TotalCountRunningStartFailed,
+ L"NonQ'dErrRecov",
+ ChannelExtension->TotalCountNonQueuedErrorRecovery,
+ L"NCQError|NCQErrorComplete",
+ (((ULONGLONG)ChannelExtension->TotalCountNCQError << 32) |
+ ((ULONGLONG)ChannelExtension->TotalCountNCQErrorRecoveryComplete)),
+ L"BusChange",
+ ChannelExtension->TotalCountBusChange);
+
if (ChannelExtension->StateFlags.CallAhciReportBusChange == 1) {
// Handle AHCI 6.2.2.3 Recovery of Unsolicited COMINIT and hot plug
// AhciPortBusChangeDpcRoutine() will issue RESET, ignore other error recovery marks.
@@ -1894,6 +2037,11 @@ Return Values:
ChannelExtension->StateFlags.CallAhciReset = 0;
ChannelExtension->StateFlags.CallAhciNcqErrorRecovery = 0;
+ ++(ChannelExtension->TotalCountBusChange);
+ if (ChannelExtension->TotalCountBusChange >= AHCI_BUS_CHANGE_COUNT_WARNING_THRESHOLD) {
+ AhciPortMarkDeviceFailed(ChannelExtension, AhciDeviceFailureTooManyBusChange, 0, TRUE);
+ }
+
if (!IsDumpMode(ChannelExtension->AdapterExtension)) {
StorPortIssueDpc(ChannelExtension->AdapterExtension, &ChannelExtension->BusChangeDpc, ChannelExtension, NULL);
} else {
@@ -1910,6 +2058,11 @@ Return Values:
ChannelExtension->StateFlags.CallAhciReset = 0;
ChannelExtension->StateFlags.CallAhciNcqErrorRecovery = 0;
+ ++(ChannelExtension->TotalCountNCQError);
+ if (ChannelExtension->TotalCountNCQError >= AHCI_NCQ_ERROR_COUNT_WARNING_THRESHOLD) {
+ AhciPortMarkDeviceFailed(ChannelExtension, AhciDeviceFailureTooManyNCQError, 0, TRUE);
+ }
+
if (SupportsEnhancedNcqErrorRecovery(ChannelExtension)) {
AhciNcqErrorRecovery(ChannelExtension);
} else {
@@ -1932,6 +2085,10 @@ Return Values:
// Handle AHCI 6.2.2.1 Non-Queued Error Recovery
ChannelExtension->StateFlags.CallAhciNonQueuedErrorRecovery = 0;
+ if (ChannelExtension->TotalCountNonQueuedErrorRecovery >= AHCI_NON_QUEUED_ERROR_COUNT_WARNING_THRESHOLD) {
+ AhciPortMarkDeviceFailed(ChannelExtension, AhciDeviceFailureTooManyNonQueuedError, 0, TRUE);
+ }
+
AhciNonQueuedErrorRecovery(ChannelExtension);
}
@@ -1939,16 +2096,16 @@ Return Values:
}
BOOLEAN
-AhciPortReset (
+AhciPortReset(
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
_In_ BOOLEAN CompleteAllRequests
)
/*++
-AhciPortReset can be called even if the miniport driver is not ready for another request.
-The miniport driver should complete all pending requests and must reset the given channel.
+ AhciPortReset can be called even if the miniport driver is not ready for another request.
+ The miniport driver should complete all pending requests and must reset the given channel.
It assumes:
- nothing
+ DIRQL
Called by:
@@ -1970,16 +2127,106 @@ Return Values:
If the reset failed the routine must return FALSE.
--*/
{
- ULONG commandsToCompleteCount;
+ ULONG commandsToCompleteCount = 0;
+ BOOLEAN isPortStartInProgress = FALSE;
+ BOOLEAN isCompletionDPCQueued = FALSE;
+ BOOLEAN isCompletionDPCInterrupted = FALSE;
+
+ //1.1 Initialize Variables
+ ++(ChannelExtension->TotalCountPortReset);
+
+ if ((CompleteAllRequests) &&
+ (ChannelExtension->StartState.ChannelNextStartState != StartComplete)) {
+
+ NT_ASSERT(FALSE);
+
+ isPortStartInProgress = TRUE;
+ RecordExecutionHistory(ChannelExtension, 0x10040050); //AhciPortReset, Port Start still in progress, device probably hang
+
+ } else {
+ RecordExecutionHistory(ChannelExtension, 0x00000050); //AhciPortReset
+ }
+
+ AhciTelemetryLogResetErrorRecovery(ChannelExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciTelemetryEventIdPortReset,
+ (isPortStartInProgress ? "PortStartTakeTooLong" : "AhciPortReset"),
+ (isPortStartInProgress ? AHCI_TELEMETRY_FLAG_NOT_SUPPRESS_LOGGING : 0),
+ NULL,
+ 0
+ );
+
+ if (ChannelExtension->CompletionQueue.LastTimeStampAddQueue.QuadPart > ChannelExtension->LastTimeStampDpcStart.QuadPart) {
+ isCompletionDPCQueued = TRUE;
+ }
+
+ if (ChannelExtension->LastTimeStampDpcStart.QuadPart > ChannelExtension->LastTimeStampDpcCompletion.QuadPart) {
+ isCompletionDPCInterrupted = TRUE;
+ }
+
+ if (isCompletionDPCQueued || isCompletionDPCInterrupted) {
+
+ LARGE_INTEGER currentTimeStamp;
+ StorPortQuerySystemTime(&currentTimeStamp);
+ ULONGLONG duration = 0;
+
+ NT_ASSERT(FALSE);
+
+ if (isCompletionDPCQueued && isCompletionDPCInterrupted) {
+ if (ChannelExtension->LastTimeStampDpcStart.QuadPart < ChannelExtension->CompletionQueue.LastTimeStampRemoveQueue.QuadPart) {
+ duration = (ULONGLONG)(currentTimeStamp.QuadPart - ChannelExtension->CompletionQueue.LastTimeStampRemoveQueue.QuadPart);
+ } else {
+ duration = (ULONGLONG)(currentTimeStamp.QuadPart - ChannelExtension->LastTimeStampDpcStart.QuadPart);
+ }
+ } else if (isCompletionDPCQueued) {
+ duration = (ULONGLONG)(currentTimeStamp.QuadPart - ChannelExtension->CompletionQueue.LastTimeStampAddQueue.QuadPart);
+ } else if (isCompletionDPCInterrupted) {
+ duration = (ULONGLONG)(currentTimeStamp.QuadPart - ChannelExtension->LastTimeStampDpcStart.QuadPart);
+ }
- //1.1 Initialize Variables
- RecordExecutionHistory(ChannelExtension, 0x00000050);//AhciPortReset
+ RecordExecutionHistory(ChannelExtension, 0x10050050); //AhciPortReset, DPC queued or interrupted
- //2.1 Stop the channel
+ AhciTelemetryLogResetErrorRecovery(ChannelExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciTelemetryEventIdPortReset,
+ "DPC queued or interrupted",
+ AHCI_TELEMETRY_FLAG_NOT_SUPPRESS_LOGGING,
+ "Duration(in 100ns)",
+ duration
+ );
+ }
+
+ StorPortEtwChannelEvent8(ChannelExtension->AdapterExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ StorportEtwEventOperational,
+ AhciEtwEventPortReset,
+ L"Port reset",
+ STORPORT_ETW_EVENT_KEYWORD_COMMAND_TRACE,
+ StorportEtwLevelInformational,
+ StorportEtwEventOpcodeInfo,
+ NULL,
+ L"PortReset",
+ ChannelExtension->TotalCountPortReset,
+ L"RunningStrtFail",
+ ChannelExtension->TotalCountRunningStartFailed,
+ L"PortErrRecovery",
+ ChannelExtension->TotalCountPortErrorRecovery,
+ L"NonQ'dErrRecov",
+ ChannelExtension->TotalCountNonQueuedErrorRecovery,
+ L"NCQErrRecovery",
+ ChannelExtension->TotalCountNCQError,
+ L"NCQErrRecovCmpl",
+ ChannelExtension->TotalCountNCQErrorRecoveryComplete,
+ L"SurpriseRemove",
+ ChannelExtension->TotalCountSurpriseRemove,
+ L"StateFlags",
+ *(ULONGLONG *)&(ChannelExtension->StateFlags));
+
+ //2.1 Stop the channel
P_NotRunning(ChannelExtension, ChannelExtension->Px);
- //2.2 Perform the COMRESET
- // AHCI 10.1.2 - 3: If PxCMD.CR or PxCMD.FR do not clear to �0� correctly, then software may attempt a port reset or a full HBA reset to recover.
+ //2.2 Perform the COMRESET
+ // AHCI 10.1.2 - 3: If PxCMD.CR or PxCMD.FR do not clear to '0' correctly, then software may attempt a port reset or a full HBA reset to recover.
AhciCOMRESET(ChannelExtension, ChannelExtension->Px);
//
@@ -1990,14 +2237,89 @@ Return Values:
ChannelExtension->StateFlags.QueuePaused = 0;
}
- //2.3 If either Init Command or PreservedSettings Command is being processed, reset the command index to start from the first one again.
- // The process will be continued by the Srb's completion routine.
+ if ((CompleteAllRequests) &&
+ (ChannelExtension->StateFlags.QueuePaused == 1) &&
+ (ChannelExtension->SlotManager.CommandsIssued == 0)) {
+
+ //
+ // This should never happen. Resetting state.
+ //
+
+ NT_ASSERT(FALSE);
+
+ ChannelExtension->StateFlags.QueuePaused = 0;
+
+ RecordExecutionHistory(ChannelExtension, 0x10010050); //AhciPortReset, Unpausing queue
+ AhciTelemetryLogResetErrorRecovery(ChannelExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciTelemetryEventIdPortReset,
+ "Unpausing queue",
+ AHCI_TELEMETRY_FLAG_NOT_SUPPRESS_LOGGING,
+ NULL,
+ 0
+ );
+ }
+
+ //2.3 If either Init Command or PreservedSettings Command is being processed, reset the command index to start from the first one again.
+ // The process will be continued by the Srb's completion routine.
if (ChannelExtension->StateFlags.ReservedSlotInUse == 1) {
ChannelExtension->DeviceInitCommands.CommandToSend = 0;
ChannelExtension->PersistentSettings.SlotsToSend = ChannelExtension->PersistentSettings.Slots;
}
- //3.1 Complete all issued commands
+ if ((CompleteAllRequests) &&
+ (ChannelExtension->StateFlags.ReservedSlotInUse == 1) &&
+ (ChannelExtension->SlotManager.SingleIoSliceIssued == 0) &&
+ ((ChannelExtension->SlotManager.SingleIoSlice & 0x1) == 0)) {
+
+ NT_ASSERT(FALSE);
+
+ //
+ // This could happen if init/preserved setting command completed by device, but the completion DPC is queued(or interrupted) for long time.
+ // If there is other scenario, it is needed to further triage.
+ //
+ // Note: Force clear ReservedSlotInUse flag only if corresponding registry key is set.
+ // Otherwise, there maybe add queue issue. E.g. Buggy device repeatedly generate bus change interrupt,
+ // which could result in add queue bugcheck eventually.
+ //
+
+ if (!(isCompletionDPCQueued || isCompletionDPCInterrupted)) {
+ RecordExecutionHistory(ChannelExtension, 0x10020050); //AhciPortReset, ReservedSlotInUse flag maybe stuck
+ //
+ // There maybe possibility that init/restore preserved settings command stuck in device and never complete.
+ //
+ AhciPortMarkDeviceFailed(ChannelExtension, AhciDeviceFailureDeviceStuck, 0, TRUE);
+ } else {
+ RecordExecutionHistory(ChannelExtension, 0x10060050); //AhciPortReset, ReservedSlotInUse flag outstanding
+ }
+
+ }
+
+ if (((ChannelExtension->SlotManager.SingleIoSliceIssued & 0x1) != 0) &&
+ (ChannelExtension->Slot[0].Srb != NULL) &&
+ ((PSTORAGE_REQUEST_BLOCK)&ChannelExtension->Local.Srb == ChannelExtension->Slot[0].Srb)) {
+
+ if ((ChannelExtension->Local.SrbExtension != NULL) &&
+ ((ChannelExtension->Local.SrbExtension->CompletionRoutine == IssuePreservedSettingCommands) ||
+ (ChannelExtension->Local.SrbExtension->CompletionRoutine == IssueInitCommands))) {
+
+ BOOLEAN isInitCommand = (ChannelExtension->Local.SrbExtension->CompletionRoutine == IssueInitCommands) ? (TRUE) : (FALSE);
+
+ NT_ASSERT(FALSE);
+
+ RecordExecutionHistory(ChannelExtension, 0x10030050); //AhciPortReset, Init/Preserved Setting command timeout
+ AhciTelemetryLogResetErrorRecovery(ChannelExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciTelemetryEventIdPortReset,
+ "Slot 0 command timeout",
+ AHCI_TELEMETRY_FLAG_NOT_SUPPRESS_LOGGING,
+ (isInitCommand ? "Init Command" : "Preserved Setting Command"),
+ 0
+ );
+ }
+ }
+
+ //3.1 Complete all issued commands
ChannelExtension->SlotManager.CommandsToComplete = ChannelExtension->SlotManager.CommandsIssued;
ChannelExtension->SlotManager.CommandsIssued = 0;
ChannelExtension->SlotManager.NCQueueSliceIssued = 0;
@@ -2030,17 +2352,17 @@ Return Values:
AhciCompleteIssuedSRBs(ChannelExtension, completeStatus, TRUE); //AhciPortReset is under Interrupt spinlock
}
- //3.2 Complete all other commands miniport own for this device, when it's necessary or when the Reset is requested by Storport
+ //3.2 Complete all other commands miniport own for this device, when it's necessary or when the Reset is requested by Storport
if (CompleteAllRequests) {
AhciPortFailAllIos(ChannelExtension, SRB_STATUS_BUS_RESET, TRUE);
}
- //4.1 Restore device configuration
+ //4.1 Restore device configuration
if (ChannelExtension->StateFlags.ReservedSlotInUse == 0) {
RestorePreservedSettings(ChannelExtension, TRUE);
}
- //2.3 Start the channel
+ //2.3 Start the channel
P_Running_StartAttempt(ChannelExtension, TRUE); //AhciPortReset is under Interrupt spinlock
// record that the channel is reset.
@@ -2057,4 +2379,3 @@ Return Values:
#pragma warning(default:4214)
#pragma warning(default:4201)
#endif
-
diff --git a/storage/miniports/storahci/src/hbastat.h b/storage/miniports/storahci/src/hbastat.h
index 40986668..b401a81e 100644
--- a/storage/miniports/storahci/src/hbastat.h
+++ b/storage/miniports/storahci/src/hbastat.h
@@ -107,4 +107,3 @@ AhciPortErrorRecovery(
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
);
-
diff --git a/storage/miniports/storahci/src/inbox/storahci.vcxproj b/storage/miniports/storahci/src/inbox/storahci.vcxproj
index 7e694879..eb2e4f82 100644
--- a/storage/miniports/storahci/src/inbox/storahci.vcxproj
+++ b/storage/miniports/storahci/src/inbox/storahci.vcxproj
@@ -76,11 +76,6 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
</ImportGroup>
<ItemGroup Label="WrappedTaskItems">
- <ClCompile Include="..\entrypts.c; ..\pnppower.c; ..\hbastat.c; ..\util.c; ..\io.c; ..\common.c">
- <WppEnabled>true</WppEnabled>
- <WppKernelMode>true</WppKernelMode>
- <WppTraceFunction>TracePrint((LEVEL,FLAGS,MSG,...))</WppTraceFunction>
- </ClCompile>
<OtherWpp Include="..\storahci.rc">
<WppEnabled>true</WppEnabled>
<WppKernelMode>true</WppKernelMode>
@@ -186,5 +181,37 @@
<ItemGroup>
<ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
</ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\common.c">
+ <WppEnabled>true</WppEnabled>
+ <WppKernelMode>true</WppKernelMode>
+ <WppTraceFunction>TracePrint((LEVEL,FLAGS,MSG,...))</WppTraceFunction>
+ </ClCompile>
+ <ClCompile Include="..\entrypts.c">
+ <WppEnabled>true</WppEnabled>
+ <WppKernelMode>true</WppKernelMode>
+ <WppTraceFunction>TracePrint((LEVEL,FLAGS,MSG,...))</WppTraceFunction>
+ </ClCompile>
+ <ClCompile Include="..\hbastat.c">
+ <WppEnabled>true</WppEnabled>
+ <WppKernelMode>true</WppKernelMode>
+ <WppTraceFunction>TracePrint((LEVEL,FLAGS,MSG,...))</WppTraceFunction>
+ </ClCompile>
+ <ClCompile Include="..\io.c">
+ <WppEnabled>true</WppEnabled>
+ <WppKernelMode>true</WppKernelMode>
+ <WppTraceFunction>TracePrint((LEVEL,FLAGS,MSG,...))</WppTraceFunction>
+ </ClCompile>
+ <ClCompile Include="..\pnppower.c">
+ <WppEnabled>true</WppEnabled>
+ <WppKernelMode>true</WppKernelMode>
+ <WppTraceFunction>TracePrint((LEVEL,FLAGS,MSG,...))</WppTraceFunction>
+ </ClCompile>
+ <ClCompile Include="..\util.c">
+ <WppEnabled>true</WppEnabled>
+ <WppKernelMode>true</WppKernelMode>
+ <WppTraceFunction>TracePrint((LEVEL,FLAGS,MSG,...))</WppTraceFunction>
+ </ClCompile>
+ </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project> \ No newline at end of file
diff --git a/storage/miniports/storahci/src/io.c b/storage/miniports/storahci/src/io.c
index 3a517854..44913b55 100644
--- a/storage/miniports/storahci/src/io.c
+++ b/storage/miniports/storahci/src/io.c
@@ -44,7 +44,6 @@ Affected Variables/Registers:
Return Value:
--*/
{
-
UCHAR activeCount = 0;
UCHAR emptyCount;
UCHAR requestCount;
@@ -52,26 +51,27 @@ Return Value:
ULONG slotToActivate = 0;
UCHAR i;
- //1 Device's queue depth is smaller than Controller's
+ // 1. Device's queue depth is smaller than Controller's
NT_ASSERT(ChannelExtension->DeviceExtension[0].DeviceParameters.MaxDeviceQueueDepth <= ChannelExtension->AdapterExtension->CAP.NCS);
- //count the number of slots already in use
+ // Count the number of slots already in use
if (ChannelExtension->SlotManager.CommandsIssued > 0) {
activeCount = NumberOfSetBits(ChannelExtension->SlotManager.CommandsIssued);
}
- //1.1 Check if all slots are active.
+
+ // 1.1 Check if all slots are active.
if (activeCount >= ChannelExtension->DeviceExtension[0].DeviceParameters.MaxDeviceQueueDepth) {
- //if all possible slots are full, no matter what, return no work (0)
+ // If all possible slots are full, no matter what, return no work (0)
return 0;
}
- //2 Look for any entry from last active slot
+ // 2. Look for any entry from last active slot
requestCount = NumberOfSetBits(TargetSlots);
lastActiveSlot = ChannelExtension->LastActiveSlot;
emptyCount = ChannelExtension->DeviceExtension[0].DeviceParameters.MaxDeviceQueueDepth - activeCount;
- //3.1 Look for any entry from last active slot
+ // 3.1 Look for any entry from last active slot
for (i = lastActiveSlot; i <= ChannelExtension->AdapterExtension->CAP.NCS; i++) {
if ((TargetSlots & (1 << i)) > 0) {
slotToActivate |= (1 << i);
@@ -84,8 +84,8 @@ Return Value:
}
}
- //3.2 Look for any entry from beginning to last active slot
- //Slot 0 is reserved for internal command
+ // 3.2 Look for any entry from beginning to last active slot
+ // Slot 0 is reserved for internal command
for (i = 1 ; i <= lastActiveSlot; i++) {
if ((TargetSlots & (1 << i)) > 0) {
slotToActivate |= (1 << i);
@@ -138,23 +138,23 @@ Return Value:
PAHCI_ADAPTER_EXTENSION adapterExtension = ChannelExtension->AdapterExtension;
- //1.1 Initialize variables
+ // 1.1 Initialize variables
limit = ChannelExtension->CurrentCommandSlot;
- // if there is internal request pending, always get it first.
- if ( (ChannelExtension->SlotManager.SingleIoSlice & 1) > 0 ) {
+ // if there is internal request pending, always get it first.
+ if ((ChannelExtension->SlotManager.SingleIoSlice & 1) > 0) {
return 0;
}
- //2.1 Chose the slot circularly starting with CCS
+ // 2.1 Chose the slot circularly starting with CCS
for (i = limit; i <= adapterExtension->CAP.NCS; i++) {
- if ( (ChannelExtension->SlotManager.SingleIoSlice & (1 << i)) > 0){
+ if ((ChannelExtension->SlotManager.SingleIoSlice & (1 << i)) > 0) {
return i;
}
}
for (i = 0; i < limit; i++) {
- if ( (ChannelExtension->SlotManager.SingleIoSlice & (1 << i)) > 0){
+ if ((ChannelExtension->SlotManager.SingleIoSlice & (1 << i)) > 0) {
return i;
}
}
@@ -163,7 +163,7 @@ Return Value:
}
VOID
-AddQueue (
+AddQueue(
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
_Inout_ PSTORAHCI_QUEUE Queue,
_In_ PSTORAGE_REQUEST_BLOCK Srb,
@@ -179,10 +179,13 @@ Input Parameters:
Tag: bit 31 ~ 24, Queue->CurrentDepth: bit 23 ~ 0
*/
{
- PVOID tempTail, foundSrb;
- ULONG srbsFound;
+ PVOID tempTail, foundSrb;
+ ULONG srbsFound;
+
UNREFERENCED_PARAMETER(ChannelExtension);
+ StorPortQuerySystemTime(&(Queue->LastTimeStampAddQueue));
+
if (Queue->Tail == NULL) {
Queue->Tail = (PVOID) Srb;
Queue->Head = (PVOID) Srb;
@@ -190,11 +193,14 @@ Input Parameters:
tempTail = Queue->Tail;
if (SrbGetNextSrb(tempTail) == NULL) { //Verify SRBs are not about to be severed from the Queue
SrbSetNextSrb(tempTail, (PVOID)Srb);
+
}
Queue->Tail = (PVOID)Srb;
+
}
Queue->CurrentDepth++;
if (Queue->Head == NULL) { //It is impossible for Head to be NULL here
+
srbsFound = 0;
} else {
foundSrb = Queue->Head;
@@ -209,6 +215,7 @@ Input Parameters:
Queue->DepthHistoryIndex++;
Queue->DepthHistoryIndex %= 100;
Queue->DepthHistory[Queue->DepthHistoryIndex] = Signature;
+
if (Queue->CurrentDepth > Queue->DeepestDepth) {
Queue->DeepestDepth = Queue->CurrentDepth;
}
@@ -217,23 +224,25 @@ Input Parameters:
}
PSTORAGE_REQUEST_BLOCK
-RemoveQueue (
+RemoveQueue(
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
_Inout_ PSTORAHCI_QUEUE Queue,
_In_ ULONG Signature,
_In_ UCHAR Tag
)
{
- PVOID nextSrb, foundSrb;
- ULONG srbsFound;
+ PVOID nextSrb, foundSrb;
+ ULONG srbsFound;
UNREFERENCED_PARAMETER(ChannelExtension);
- //Check to see if the queue is empty
+ // Check to see if the queue is empty
if (Queue->Head == NULL) {
return NULL;
}
+ StorPortQuerySystemTime(&(Queue->LastTimeStampRemoveQueue));
+
//if it is not empty, pop
nextSrb = Queue->Head;
Queue->Head = SrbGetNextSrb(nextSrb);
@@ -258,6 +267,7 @@ RemoveQueue (
Queue->DepthHistoryIndex++;
Queue->DepthHistoryIndex %= 100;
Queue->DepthHistory[Queue->DepthHistoryIndex] = Signature;
+
if (Queue->CurrentDepth > Queue->DeepestDepth) {
Queue->DeepestDepth = Queue->CurrentDepth;
}
@@ -299,20 +309,20 @@ Affected Variables/Registers:
Return Values:
--*/
{
- BOOLEAN status = TRUE;
- ULONG slotsToActivate = 0;
- BOOLEAN activateNcq = FALSE;
- int i;
+ BOOLEAN status = TRUE;
+ ULONG slotsToActivate = 0;
+ BOOLEAN activateNcq = FALSE;
+ int i;
PAHCI_ADAPTER_EXTENSION adapterExtension = ChannelExtension->AdapterExtension;
- STOR_LOCK_HANDLE lockhandle = {InterruptLock, 0};
+ STOR_LOCK_HANDLE lockhandle = { InterruptLock, 0 };
- //1.1 Initialize variables
+ // 1.1 Initialize variables
if (LogExecuteFullDetail(adapterExtension->LogFlags)) {
RecordExecutionHistory(ChannelExtension, 0x00000022);//ActivateQueue
}
- // If the programming should not happen now, leave
+ // If the programming should not happen now, leave
if (ChannelExtension->StartState.ChannelNextStartState != StartComplete) {
RecordExecutionHistory(ChannelExtension, 0x10010022);//ActivateQueue, Channel Not Yet Started
status = FALSE;
@@ -325,13 +335,13 @@ Return Values:
return status;
}
- if ( !IsPortStartCapable(ChannelExtension) ) {
+ if (!IsPortStartCapable(ChannelExtension)) {
RecordExecutionHistory(ChannelExtension, 0x10030022);//ActivateQueue, Channel Not Start Capable
status = FALSE;
return status;
}
- if ( ErrorRecoveryIsPending(ChannelExtension) ) {
+ if (ErrorRecoveryIsPending(ChannelExtension)) {
RecordExecutionHistory(ChannelExtension, 0x10070022);//ActivateQueue, Error Recovery is pending.
status = FALSE;
return status;
@@ -341,10 +351,10 @@ Return Values:
AhciInterruptSpinlockAcquire(ChannelExtension->AdapterExtension, ChannelExtension->PortNumber, &lockhandle);
}
- //1.1.1 If there is no command to program, leave
- if ( (ChannelExtension->SlotManager.SingleIoSlice == 0) &&
- (ChannelExtension->SlotManager.NormalQueueSlice == 0) &&
- (ChannelExtension->SlotManager.NCQueueSlice == 0) ) {
+ // 1.1.1 If there is no command to program, leave
+ if ((ChannelExtension->SlotManager.SingleIoSlice == 0) &&
+ (ChannelExtension->SlotManager.NormalQueueSlice == 0) &&
+ (ChannelExtension->SlotManager.NCQueueSlice == 0)) {
if (LogExecuteFullDetail(adapterExtension->LogFlags)) {
RecordExecutionHistory(ChannelExtension, 0x10040022);//ActivateQueue, No Commands to program
@@ -363,26 +373,60 @@ Return Values:
goto Exit;
}
- //2.1 Choose the Queue with which to program the controller
- //2.1.2 Single IO SRBs have highest priority.
- if(ChannelExtension->SlotManager.SingleIoSlice != 0) {
- if ( (ChannelExtension->SlotManager.NCQueueSliceIssued | ChannelExtension->SlotManager.NormalQueueSliceIssued | ChannelExtension->SlotManager.SingleIoSliceIssued) == 0 ) {
- //Safely get Single IO in round robin fashion
+ // 2.1 Choose the Queue with which to program the controller
+ // 2.1.1 Single IO SRBs have highest priority.
+ if (ChannelExtension->SlotManager.SingleIoSlice != 0) {
+ if ((ChannelExtension->SlotManager.NCQueueSliceIssued | ChannelExtension->SlotManager.NormalQueueSliceIssued | ChannelExtension->SlotManager.SingleIoSliceIssued) == 0) {
+ // Safely get Single IO in round robin fashion
i = GetSingleIo(ChannelExtension);
if (i != 0xff) {
+ PSLOT_CONTENT slotContent = &ChannelExtension->Slot[i];
+
slotsToActivate = (1 << i);
ChannelExtension->SlotManager.SingleIoSlice &= ~slotsToActivate;
ChannelExtension->SlotManager.SingleIoSliceIssued |= slotsToActivate;
ChannelExtension->StateFlags.QueuePaused = TRUE; //and pause the queue so no other IO get programmed
+
+ if (LogExecuteFullDetail(adapterExtension->LogFlags)) {
+ RecordExecutionHistory(ChannelExtension, 0x10090022); //ActivateQueue, Single IO pause queue
+ }
+
+ // 2.1.1.1 Update the Identify command for enumeration. This needs to be here for PxSIG to be accessible.
+ // Accessing PxSIG register here to avoid invalid values from time when the port is being reset or not started, or other scenarios.
+ if (slotContent->Srb != NULL) {
+
+ PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(slotContent->Srb);
+ PAHCI_COMMAND_TABLE cmdTable = (PAHCI_COMMAND_TABLE)srbExtension;
+
+ if ((srbExtension->AtaFunction == ATA_FUNCTION_ATA_IDENTIFY) &&
+ (srbExtension->CompletionRoutine == AhciPortIdentifyDevice) &&
+ (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_NOT_VALID) &&
+ (cmdTable->CFIS.Command == IDE_COMMAND_NOT_VALID) ) {
+
+ // For enumeration command, it's safe now to check the PxSIG register as starting port has been executed.
+ ULONG sig = 0;
+ sig = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SIG.AsUlong);
+
+ if (sig == ATA_DEVICE_SIGNATURE_ATA) { //ATA
+ srbExtension->TaskFile.Current.bCommandReg = IDE_COMMAND_IDENTIFY;
+ cmdTable->CFIS.Command = IDE_COMMAND_IDENTIFY;
+ } else { //ATAPI
+ srbExtension->TaskFile.Current.bCommandReg = IDE_COMMAND_ATAPI_IDENTIFY;
+ cmdTable->CFIS.Command = IDE_COMMAND_ATAPI_IDENTIFY;
+ }
+ }
+ } else {
+ NT_ASSERT(FALSE);
+ }
}
}
- //2.1.2 When there are no Single IO commands, Normal IO get the next highest priority
+ // 2.1.2 When there are no Single IO commands, Normal IO get the next highest priority
} else if (ChannelExtension->SlotManager.NormalQueueSlice != 0) {
// Normal commands can not be sent when NCQ commands are outstanding. When the NCQ commands complete ActivateQueue will get called again.
if (ChannelExtension->SlotManager.NCQueueSliceIssued == 0) {
- //Grab the High Priority Normal IO before the Low Priority Normal IO
+ // Grab the High Priority Normal IO before the Low Priority Normal IO
slotsToActivate = ChannelExtension->SlotManager.HighPriorityAttribute & ChannelExtension->SlotManager.NormalQueueSlice;
- //If there aren't any High Priority, grab everything else
+ // If there aren't any High Priority, grab everything else
if (slotsToActivate > 0) {
ChannelExtension->SlotManager.NormalQueueSlice &= ~slotsToActivate;
} else {
@@ -391,41 +435,41 @@ Return Values:
}
ChannelExtension->SlotManager.NormalQueueSliceIssued |= slotsToActivate;
}
- //2.1.3 When there are no Single or Normal commands, NCQ commands get the next highest priority
+ // 2.1.3 When there are no Single or Normal commands, NCQ commands get the next highest priority
} else if ((ChannelExtension->SlotManager.NCQueueSlice != 0) &&
(ChannelExtension->StateFlags.NcqErrorRecoveryInProcess == 0)) {
// NCQ commands can not be sent when Normal commands are outstanding. When the Normal commands complete, Activate Queue will get called again.
- if ( ( ChannelExtension->SlotManager.SingleIoSliceIssued | ChannelExtension->SlotManager.NormalQueueSliceIssued ) != 0 ) {
+ if ((ChannelExtension->SlotManager.SingleIoSliceIssued | ChannelExtension->SlotManager.NormalQueueSliceIssued ) != 0) {
slotsToActivate = 0;
} else {
- //Grab the High Priority NCQ IO before the Low Priority NCQ IO
+ // Grab the High Priority NCQ IO before the Low Priority NCQ IO
slotsToActivate = ChannelExtension->SlotManager.HighPriorityAttribute & ChannelExtension->SlotManager.NCQueueSlice;
- //If there aren't any High Priority, grab everything else
+ // If there aren't any High Priority, grab everything else
if (slotsToActivate == 0) {
slotsToActivate = ChannelExtension->SlotManager.NCQueueSlice;
}
- //and apply any device outstanding IO limits to filter down which IO to activate
+ // And apply any device outstanding IO limits to filter down which IO to activate
if (slotsToActivate > 0) {
- if (ChannelExtension->DeviceExtension[0].DeviceParameters.MaxDeviceQueueDepth < ChannelExtension->MaxPortQueueDepth ) {
- // get allowed slots if the device queue depth is less than the port can support.
+ if (ChannelExtension->DeviceExtension[0].DeviceParameters.MaxDeviceQueueDepth < ChannelExtension->MaxPortQueueDepth) {
+ // Get allowed slots if the device queue depth is less than the port can support.
slotsToActivate = GetSlotToActivate(ChannelExtension, slotsToActivate);
}
if (slotsToActivate > 0) {
- //and if there are any IO still selected, clear them from the NCQueue
+ // And if there are any IO still selected, clear them from the NCQueue
activateNcq = TRUE; //Remember to program SACT for these commands
ChannelExtension->SlotManager.NCQueueSlice &= ~slotsToActivate;
ChannelExtension->SlotManager.NCQueueSliceIssued |= slotsToActivate;
- //the selected IO will be activated at the end of this function
+ // The selected IO will be activated at the end of this function
}
}
}
- //2.1.4 In the case that no IO is present in any Slices, program nothing
+ // 2.1.4 In the case that no IO is present in any Slices, program nothing
}
- //2.1 Program all the IO from the chosen queue into the controller
+ // 2.1 Program all the IO from the chosen queue into the controller
if (slotsToActivate != 0) {
- //2.2 Get command start time
- if(adapterExtension->TracingEnabled) {
+ // 2.2 Get command start time
+ if (adapterExtension->TracingEnabled) {
LARGE_INTEGER perfCounter = {0};
ULONG pendingProgrammingCommands = slotsToActivate;
@@ -434,9 +478,11 @@ Return Values:
StorPortQueryPerformanceCounter((PVOID)adapterExtension, NULL, &perfCounter);
while (pendingProgrammingCommands) {
- if (pendingProgrammingCommands & 1) {
+ // TODO: there is potential race condition that causes slot flags mismatch and Srb is NULL here.
+ if ((pendingProgrammingCommands & 1) && (ChannelExtension->Slot[i].Srb != NULL)) {
PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(ChannelExtension->Slot[i].Srb);
srbExtension->StartTime = perfCounter.QuadPart;
+
}
i++;
@@ -446,7 +492,7 @@ Return Values:
ChannelExtension->SlotManager.CommandsIssued |= slotsToActivate;
- // program registers
+ // Program registers
if (activateNcq) {
StorPortWriteRegisterUlong(adapterExtension, &ChannelExtension->Px->SACT, slotsToActivate);
}
@@ -486,21 +532,21 @@ CalculateTimeDurationIn100ns (
{
ULONGLONG timeIn100ns = 0;
- // as the counter can hold more than 20,000 years for the same power cycle,
+ // As the counter can hold more than 20,000 years for the same power cycle,
// the situation about the counter start over again is considered an error case of inputs.
if (CounterFrequency > 0) {
- // difference between performance counters, needs to convert to 100ns.
+ // Difference between performance counters, needs to convert to 100ns.
ULONGLONG countersDiff = TimeDuration;
- // get seconds
+ // Get seconds
timeIn100ns = countersDiff / CounterFrequency;
- // get milliseconds
+ // Get milliseconds
countersDiff = (countersDiff % CounterFrequency) * 1000;
timeIn100ns *= 1000;
timeIn100ns += countersDiff / CounterFrequency;
- // get 100 nanoseconds
+ // Get 100 nanoseconds
countersDiff = (countersDiff % CounterFrequency) * 10000;
timeIn100ns *= 10000;
timeIn100ns += countersDiff / CounterFrequency;
@@ -546,35 +592,34 @@ Affected Variables/Registers:
--*/
{
- PSLOT_CONTENT slotContent;
- UCHAR i;
+ PSLOT_CONTENT slotContent;
+ UCHAR i;
PAHCI_ADAPTER_EXTENSION adapterExtension;
- PAHCI_SRB_EXTENSION srbExtension;
-
- LARGE_INTEGER perfCounter = {0};
- LARGE_INTEGER perfFrequency = {0};
+ PAHCI_SRB_EXTENSION srbExtension;
+ LARGE_INTEGER perfCounter = { 0 };
+ LARGE_INTEGER perfFrequency = { 0 };
- //1.1 Initialize variables
+ // 1.1 Initialize variables
adapterExtension = ChannelExtension->AdapterExtension;
if (LogExecuteFullDetail(adapterExtension->LogFlags)) {
RecordExecutionHistory(ChannelExtension, 0x00000046);//AhciCompleteIssuedSRBs
}
- if( adapterExtension->TracingEnabled && (ChannelExtension->SlotManager.CommandsToComplete) ) {
+ if (adapterExtension->TracingEnabled && (ChannelExtension->SlotManager.CommandsToComplete)) {
StorPortQueryPerformanceCounter((PVOID)adapterExtension, &perfFrequency, &perfCounter);
}
- //2.1 For every command marked as completed
+ // 2.1 For every command marked as completed
for (i = 0; i <= (adapterExtension->CAP.NCS); i++) {
- if( ( ChannelExtension->SlotManager.CommandsToComplete & (1 << i) ) > 0) {
+ if ((ChannelExtension->SlotManager.CommandsToComplete & (1 << i)) > 0) {
slotContent = &ChannelExtension->Slot[i];
if (slotContent->Srb == NULL) {
- //This shall never happen.
- //The completed slot has no SRB so it can not be completed back to Storport.
- //Give back the empty slot
+ // This shall never happen.
+ // The completed slot has no SRB so it can not be completed back to Storport.
+ // Give back the empty slot
NT_ASSERT(FALSE);
ChannelExtension->SlotManager.CommandsToComplete &= ~(1 << i);
ChannelExtension->SlotManager.HighPriorityAttribute &= ~(1 << i);
@@ -582,12 +627,12 @@ Affected Variables/Registers:
}
if (slotContent->CmdHeader == NULL) {
- //This shall never happen.
- //Give back the empty slot
+ // This shall never happen.
+ // Give back the empty slot
NT_ASSERT(FALSE);
ChannelExtension->SlotManager.CommandsToComplete &= ~(1 << i);
ChannelExtension->SlotManager.HighPriorityAttribute &= ~(1 << i);
- //It is now impossible to determine if a data transfer completed correctly
+ // It is now impossible to determine if a data transfer completed correctly
slotContent->Srb->SrbStatus = SRB_STATUS_ABORTED;
AhciCompleteRequest(ChannelExtension, slotContent->Srb, AtDIRQL);
continue;
@@ -595,46 +640,45 @@ Affected Variables/Registers:
srbExtension = GetSrbExtension(slotContent->Srb);
- //2.1.2 Log command execution time, if it's allowed
- if ( adapterExtension->TracingEnabled &&
- (srbExtension->StartTime != 0) &&
- (perfCounter.QuadPart != 0) &&
- !IsMiniportInternalSrb(ChannelExtension, slotContent->Srb) ) {
+ // 2.1.2 Log command execution time, if it's allowed
+ if (adapterExtension->TracingEnabled &&
+ (srbExtension->StartTime != 0) &&
+ (perfCounter.QuadPart != 0) &&
+ !IsMiniportInternalSrb(ChannelExtension, slotContent->Srb)) {
ULONGLONG durationTime = CalculateTimeDurationIn100ns((perfCounter.QuadPart - srbExtension->StartTime), perfFrequency.QuadPart);
StorPortNotification(IoTargetRequestServiceTime, (PVOID)adapterExtension, durationTime, slotContent->Srb);
}
- //2.2 Set the status
- if( (SrbStatus == SRB_STATUS_SUCCESS) &&
+ // 2.2 Set the status
+ if ((SrbStatus == SRB_STATUS_SUCCESS) &&
(!IsRequestSenseSrb(srbExtension->AtaFunction)) &&
(srbExtension->AtaFunction != ATA_FUNCTION_ATA_SMART) &&
(!IsNCQCommand(srbExtension)) &&
- (slotContent->CmdHeader->PRDBC != RequestGetDataTransferLength(slotContent->Srb)) ) {
- //
+ (slotContent->CmdHeader->PRDBC != RequestGetDataTransferLength(slotContent->Srb))) {
if (slotContent->CmdHeader->PRDBC < RequestGetDataTransferLength(slotContent->Srb)) {
- //buffer underrun,
+ // Buffer underrun,
RequestSetDataTransferLength(slotContent->Srb, slotContent->CmdHeader->PRDBC);
slotContent->Srb->SrbStatus = SrbStatus;
} else {
- //buffer overrun, return error
+ // Buffer overrun, return error
NT_ASSERT(FALSE);
slotContent->Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
}
} else {
- //If anything has set a STATUS on this SRB, honor that over the one passed in
+ // If anything has set a STATUS on this SRB, honor that over the one passed in
if (slotContent->Srb->SrbStatus == SRB_STATUS_PENDING) {
slotContent->Srb->SrbStatus = SrbStatus;
}
}
- //2.3 Monitor to see that any NCQ commands are completing
- if ( (slotContent->Srb->SrbStatus == SRB_STATUS_SUCCESS) &&
- (IsNCQCommand(srbExtension)) ) {
+ // 2.3 Monitor to see that any NCQ commands are completing
+ if ((slotContent->Srb->SrbStatus == SRB_STATUS_SUCCESS) &&
+ (IsNCQCommand(srbExtension))) {
ChannelExtension->StateFlags.NCQ_Succeeded = TRUE;
}
- //2.4 Give the slot back
+ // 2.4 Give the slot back
ReleaseSlottedCommand(ChannelExtension, i, AtDIRQL); // Request sense is handled here.
if (LogExecuteFullDetail(adapterExtension->LogFlags)) {
@@ -643,7 +687,7 @@ Affected Variables/Registers:
}
}
- //3.1 Start the next IO(s) if any
+ // 3.1 Start the next IO(s) if any
ActivateQueue(ChannelExtension, AtDIRQL);
return;
@@ -677,21 +721,23 @@ Affected Variables/Registers:
UNREFERENCED_PARAMETER(ChannelExtension);
- //1.1 Map SRB fields to CFIS fields
+ // 1.1 Map SRB fields to CFIS fields
cmdTable->CFIS.FisType = 0x27;
cmdTable->CFIS.PMPort = 0; // StorAHCI doesn't support Port Multiplier
cmdTable->CFIS.Reserved1 = 0;
cmdTable->CFIS.C = 1;
cmdTable->CFIS.Command = srbExtension->TaskFile.Current.bCommandReg;
- //1.2 Special case mapping of NCQ
- if( IsNCQCommand(srbExtension) ){
+
+ // 1.2 Special case mapping of NCQ
+ if (IsNCQCommand(srbExtension)) {
+
cmdTable->CFIS.Features = srbExtension->TaskFile.Current.bSectorCountReg;
cmdTable->CFIS.Features_Exp = srbExtension->TaskFile.Previous.bSectorCountReg;
cmdTable->CFIS.SectorCount = (srbExtension->QueueTag << 3);
cmdTable->CFIS.Dev_Head = 0xF & srbExtension->TaskFile.Current.bDriveHeadReg;
cmdTable->CFIS.Dev_Head |= (1 << 6);
- if( SlotContent->StateFlags.FUA ){
+ if (SlotContent->StateFlags.FUA) {
cmdTable->CFIS.Dev_Head |= ATA_NCQ_FUA_BIT;
} else {
cmdTable->CFIS.Dev_Head &= ~ATA_NCQ_FUA_BIT;
@@ -705,7 +751,7 @@ Affected Variables/Registers:
cmdTable->CFIS.Dev_Head = srbExtension->TaskFile.Current.bDriveHeadReg;
}
- //1.1 Map SRB fields to CFIS fields
+ // 1.1 Map SRB fields to CFIS fields
cmdTable->CFIS.SectorNumber = srbExtension->TaskFile.Current.bSectorNumberReg;
cmdTable->CFIS.SecNum_Exp = srbExtension->TaskFile.Previous.bSectorNumberReg;
@@ -749,11 +795,11 @@ Affected Variables/Registers:
Command Table
--*/
{
- //These are used for copying a CDB to ACMD on ATAPI commands.
+ // These are used for copying a CDB to ACMD on ATAPI commands.
ULONG dataLength;
PVOID cdb;
- //1.1 Memcopy CDB into ACMD
+ // 1.1 Memcopy CDB into ACMD
PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(SlotContent->Srb);
PAHCI_COMMAND_TABLE cmdTable = (PAHCI_COMMAND_TABLE)srbExtension;
@@ -768,37 +814,37 @@ Affected Variables/Registers:
NT_ASSERT(cdb != NULL);
}
- //2.1 Put the PACKET Command in the CFIS
+ // 2.1 Put the PACKET Command in the CFIS
cmdTable->CFIS.FisType = 0x27;
cmdTable->CFIS.PMPort = 0; // StorAHCI doesn't support Port Multiplier
cmdTable->CFIS.Reserved1 = 0;
cmdTable->CFIS.C = 1;
cmdTable->CFIS.Command = IDE_COMMAND_ATAPI_PACKET; //A0 is the PACKET command
- //2.2 Populate DMA bit properly, only use it for data transfer
+ // 2.2 Populate DMA bit properly, only use it for data transfer
if (IsDmaCommand(srbExtension->Flags)) {
cmdTable->CFIS.Features = 0x1;
- //If word 62 bit 15 is set to one, then the DMADIR bit in the PACKET command is required by the device for
- //PACKET commands using the DMA data transfer protocol and:
+ // If word 62 bit 15 is set to one, then the DMADIR bit in the PACKET command is required by the device for
+ // PACKET commands using the DMA data transfer protocol and:
// a) word 63 bits (2:0); -- MultiWordDMASupport & 0x7 == 0
// b) word 49 bit 15; -- Capabilities.InterleavedDmaSupported
// c) word 49 bit 8; and -- Capabilities.DmaSupported
// d) word 88 bits (6:0), -- UltraDMASupport & 0x7F == 0
//shall be cleared to zero.
- if ( (ChannelExtension->DeviceExtension[0].IdentifyPacketData->DMADIR.DMADIRBitRequired != 0) &&
- (ChannelExtension->DeviceExtension[0].IdentifyPacketData->Capabilities.DmaSupported != 0) &&
- (ChannelExtension->DeviceExtension[0].IdentifyPacketData->Capabilities.InterleavedDmaSupported == 0) &&
- ((ChannelExtension->DeviceExtension[0].IdentifyPacketData->MultiWordDMASupport & 0x7) == 0) &&
- ((ChannelExtension->DeviceExtension[0].IdentifyPacketData->UltraDMASupport & 0x7F) == 0) ) {
- //bit 0 is DMA, bit 2 is DMADIR. (0 = transfer to the device; 4 = transfer to the host).
+ if ((ChannelExtension->DeviceExtension[0].IdentifyPacketData->DMADIR.DMADIRBitRequired != 0) &&
+ (ChannelExtension->DeviceExtension[0].IdentifyPacketData->Capabilities.DmaSupported != 0) &&
+ (ChannelExtension->DeviceExtension[0].IdentifyPacketData->Capabilities.InterleavedDmaSupported == 0) &&
+ ((ChannelExtension->DeviceExtension[0].IdentifyPacketData->MultiWordDMASupport & 0x7) == 0) &&
+ ((ChannelExtension->DeviceExtension[0].IdentifyPacketData->UltraDMASupport & 0x7F) == 0)) {
+ // Bit 0 is DMA, bit 2 is DMADIR. (0 = transfer to the device; 4 = transfer to the host).
cmdTable->CFIS.Features |= (srbExtension->Flags & ATA_FLAGS_DATA_IN) ? 4 : 0;
}
} else {
cmdTable->CFIS.Features = 0x0;
}
- //2.1 Put the PACKET Command in the CFIS
+ // 2.1 Put the PACKET Command in the CFIS
cmdTable->CFIS.SectorNumber = 0;
cmdTable->CFIS.CylLow = (UCHAR)dataLength; //put the low byte of the in CylLow
dataLength >>= 8;
@@ -841,8 +887,8 @@ Affected Variables/Registers:
Command Table
--*/
{
- PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(SlotContent->Srb);
- PAHCI_COMMAND_TABLE cmdTable = (PAHCI_COMMAND_TABLE)srbExtension;
+ PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(SlotContent->Srb);
+ PAHCI_COMMAND_TABLE cmdTable = (PAHCI_COMMAND_TABLE)srbExtension;
UNREFERENCED_PARAMETER(ChannelExtension);
@@ -865,7 +911,7 @@ Affected Variables/Registers:
//
// Set common data fields.
//
- if( IsNCQCommand(srbExtension) ) {
+ if (IsNCQCommand(srbExtension)) {
cmdTable->CFIS.Count7_0 = (srbExtension->QueueTag << 3);
}
cmdTable->CFIS.FisType = 0x27;
@@ -880,7 +926,6 @@ Affected Variables/Registers:
cmdTable->CFIS.Control = 0; // Device control consists of the 48bit HighOrderByte, SRST and nIEN. None apply here.
}
-
ULONG
SRBtoPRDT(
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
@@ -910,39 +955,39 @@ Return Values:
If the value returned is -1 the PRDT could not be built.
--*/
{
- ULONG i;
- PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(SlotContent->Srb);
- PAHCI_COMMAND_TABLE cmdTable = (PAHCI_COMMAND_TABLE)srbExtension;
- PLOCAL_SCATTER_GATHER_LIST sgl = srbExtension->Sgl;
+ ULONG i;
+ PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(SlotContent->Srb);
+ PAHCI_COMMAND_TABLE cmdTable = (PAHCI_COMMAND_TABLE)srbExtension;
+ PLOCAL_SCATTER_GATHER_LIST sgl = srbExtension->Sgl;
if (sgl == NULL) {
- //return as invalid request in case of cannot get scatter gather list.
+ // Return as invalid request in case of cannot get scatter gather list.
NT_ASSERT(FALSE);
return (ULONG)-1;
}
for (i = 0; i < sgl->NumberOfElements; i++) {
- //1.2 Verify that the DataBuffer is properly aligned
- if ( (sgl->List[i].PhysicalAddress.LowPart & 0x1) == 0) {
- //2.1 Map SGL entries into PRDT entries
+ // 1.2 Verify that the DataBuffer is properly aligned
+ if ((sgl->List[i].PhysicalAddress.LowPart & 0x1) == 0) {
+ // 2.1 Map SGL entries into PRDT entries
if (sgl->List[i].Length != 0x20000) {
cmdTable->PRDT[i].DBA.AsUlong = sgl->List[i].PhysicalAddress.LowPart;
- if( ChannelExtension->AdapterExtension->CAP.S64A) {//If the controller supports 64 bits, write the high part too
+ if (ChannelExtension->AdapterExtension->CAP.S64A) {//If the controller supports 64 bits, write the high part too
cmdTable->PRDT[i].DBAU = sgl->List[i].PhysicalAddress.HighPart;
}
- //2.2 Break up a 128K single entry IO into 2 64K IO entries (128K is max transfer so there can be only 1 in any SGL)
- // although one entry can represent at max 4M length IO, some adapters cannot handle a DBC >= 128K.
+ // 2.2 Break up a 128K single entry IO into 2 64K IO entries (128K is max transfer so there can be only 1 in any SGL)
+ // although one entry can represent at max 4M length IO, some adapters cannot handle a DBC >= 128K.
} else {
// Entry 0
cmdTable->PRDT[0].DBA.AsUlong = sgl->List[0].PhysicalAddress.LowPart;
- if( ChannelExtension->AdapterExtension->CAP.S64A) {//If the controller supports 64 bits, write the high part too
+ if (ChannelExtension->AdapterExtension->CAP.S64A) {//If the controller supports 64 bits, write the high part too
cmdTable->PRDT[0].DBAU = sgl->List[0].PhysicalAddress.HighPart;
}
cmdTable->PRDT[0].DI.DBC = (0x10000 - 1);
// Entry 1
cmdTable->PRDT[1].DBA.AsUlong = (sgl->List[0].PhysicalAddress.LowPart + 0x10000);
- if( ChannelExtension->AdapterExtension->CAP.S64A) {//If the controller supports 64 bits, write the high part too
- if ( (sgl->List[0].PhysicalAddress.LowPart + 0x10000) < sgl->List[0].PhysicalAddress.LowPart) {
+ if (ChannelExtension->AdapterExtension->CAP.S64A) {//If the controller supports 64 bits, write the high part too
+ if ((sgl->List[0].PhysicalAddress.LowPart + 0x10000) < sgl->List[0].PhysicalAddress.LowPart) {
cmdTable->PRDT[1].DBAU = (sgl->List[0].PhysicalAddress.HighPart + 1); //add 1 to the highpart if adding 0x10000 caused a rollover
} else {
cmdTable->PRDT[1].DBAU = sgl->List[0].PhysicalAddress.HighPart;
@@ -956,13 +1001,13 @@ Return Values:
return (ULONG)-1;
}
- //1.3 Verify that the DataLength is even
- // all SATA transfers must be even
- // DBC is a 0 based number (i.e. 0 is 1, 1 is 2, etc.
- // sgl->Elements.Length is not (i.e. 0 is 0, 1 is 1, etc.
- if( (sgl->List[i].Length & 1) == 0 ) { //therefore length must be even here
- //2.3 Set Datalength in the PRDT entries
- cmdTable->PRDT[i].DI.DBC = sgl->List[i].Length - 1; //but it must be odd here
+ // 1.3 Verify that the DataLength is even
+ // all SATA transfers must be even
+ // DBC is a 0 based number (i.e. 0 is 1, 1 is 2, etc.
+ // sgl->Elements.Length is not (i.e. 0 is 0, 1 is 1, etc.
+ if ((sgl->List[i].Length & 1) == 0) { //therefore length must be even here
+ // 2.3 Set Datalength in the PRDT entries
+ cmdTable->PRDT[i].DI.DBC = sgl->List[i].Length - 1; //but it must be odd here
} else if (sgl->List[i].Length <= RequestGetDataTransferLength(SlotContent->Srb)) {
// Storport may send down SCSI commands with odd number of data transfer length, and it builds SGL using that transfer length value.
// we use the length -1 to get as much data as we can. If the data length is over (length - 1), buffer overrun will be reported when the command is completed.
@@ -973,6 +1018,7 @@ Return Values:
return (ULONG)-1;
}
}
+
return sgl->NumberOfElements;
}
@@ -994,32 +1040,32 @@ Affected Variables/Registers:
Command Header
--*/
{
- PAHCI_COMMAND_HEADER cmdHeader = SlotContent->CmdHeader;
- PSTORAGE_REQUEST_BLOCK srb = SlotContent->Srb;
- PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(srb);
+ PAHCI_COMMAND_HEADER cmdHeader = SlotContent->CmdHeader;
+ PSTORAGE_REQUEST_BLOCK srb = SlotContent->Srb;
+ PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(srb);
UNREFERENCED_PARAMETER(ChannelExtension);
-// a. PRDTL containing the number of entries in the PRD table
+ // a. PRDTL containing the number of entries in the PRD table
cmdHeader->DI.PRDTL = Length;
-// b. CFL set to the length of the command in the CFIS area
+ // b. CFL set to the length of the command in the CFIS area
cmdHeader->DI.CFL = 5;
-// c. A bit set if it is an ATAPI command
+ // c. A bit set if it is an ATAPI command
cmdHeader->DI.A = (srbExtension->AtaFunction & ATA_FUNCTION_ATAPI_COMMAND) ? 1 : 0;
-// d. W (Write) bit set if data is going to the device
+ // d. W (Write) bit set if data is going to the device
cmdHeader->DI.W = (srbExtension->Flags & ATA_FLAGS_DATA_OUT) ? 1 : 0;
-// e. P (Prefetch) bit optionally set (see rules in section 5.5.2)
+ // e. P (Prefetch) bit optionally set (see rules in section 5.5.2)
//Some controllers have problems if P is set.
cmdHeader->DI.P = 0;
-// f. If a Port Multiplier is attached, the PMP field set to the correct Port Multiplier port.
+ // f. If a Port Multiplier is attached, the PMP field set to the correct Port Multiplier port.
cmdHeader->DI.PMP = 0;
- //Reset
+ // Reset
cmdHeader->DI.R = Reset;
cmdHeader->DI.B = 0;
cmdHeader->DI.C = Reset;
- //initialize the PRD byte count
+ // Initialize the PRD byte count
cmdHeader->PRDBC = 0;
cmdHeader->Reserved[0] = 0;
@@ -1046,14 +1092,14 @@ Note: This routine can be called even the Port is stopped.
*/
{
PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb);
- UCHAR pathId = 0;
- UCHAR targetId = 0;
- UCHAR lun = 0;
- STOR_LOCK_HANDLE lockHandle = {InterruptLock, 0};
+ UCHAR pathId = 0;
+ UCHAR targetId = 0;
+ UCHAR lun = 0;
+ STOR_LOCK_HANDLE lockHandle = { InterruptLock, 0 };
SrbGetPathTargetLun(Srb, &pathId, &targetId, &lun);
- //1.0 complete Srb if no command should be sent to device.
+ // 1.0 complete Srb if no command should be sent to device.
if (srbExtension->AtaFunction == 0) {
NT_ASSERT(FALSE); // should investigate if this ASSERT fires
Srb->SrbStatus = SRB_STATUS_ERROR;
@@ -1062,7 +1108,7 @@ Note: This routine can be called even the Port is stopped.
return TRUE;
}
- //1.1 Check if command processing should happen
+ // 1.1 Check if command processing should happen
if (ChannelExtension->StartState.ChannelNextStartState == StartFailed) {
Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
MarkSrbToBeCompleted(Srb);
@@ -1070,42 +1116,81 @@ Note: This routine can be called even the Port is stopped.
return TRUE;
}
- //2. central place for command special handling. this part cannot be put in command translation layer, as there might be internal command also needs special handling.
- //2.1 central place for special handling of Enable/Disable WRITE CACHE, update persistent settings command.
- if ( (srbExtension->AtaFunction == ATA_FUNCTION_ATA_COMMAND) &&
- (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_SET_FEATURE) ) {
- ////
+ // 2. central place for command special handling. this part cannot be put in command translation layer, as there might be internal command also needs special handling.
+ // 2.1 central place for special handling of Enable/Disable WRITE CACHE, update persistent settings command.
+ if ((srbExtension->AtaFunction == ATA_FUNCTION_ATA_COMMAND) &&
+ (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_SET_FEATURE)) {
+
if (srbExtension->TaskFile.Current.bFeaturesReg == IDE_FEATURE_DISABLE_WRITE_CACHE) {
- //IDE_FEATURE_DISABLE_WRITE_CACHE => Modify Persistent Settings
+ // IDE_FEATURE_DISABLE_WRITE_CACHE => Modify Persistent Settings
UpdateSetFeatureCommands(ChannelExtension, IDE_FEATURE_ENABLE_WRITE_CACHE, IDE_FEATURE_DISABLE_WRITE_CACHE, 0, 0);
}
+
if (srbExtension->TaskFile.Current.bFeaturesReg == IDE_FEATURE_ENABLE_WRITE_CACHE) {
- //IDE_FEATURE_ENABLE_WRITE_CACHE => Modify Persistent Settings
+ // IDE_FEATURE_ENABLE_WRITE_CACHE => Modify Persistent Settings
UpdateSetFeatureCommands(ChannelExtension, IDE_FEATURE_DISABLE_WRITE_CACHE, IDE_FEATURE_ENABLE_WRITE_CACHE, 0, 0);
}
}
- //2.2 update the Identify command for enumeration. This needs to be here waiting for PxSIG to be accessible.
- if ( (srbExtension->AtaFunction == ATA_FUNCTION_ATA_IDENTIFY) &&
- (srbExtension->CompletionRoutine == AhciPortIdentifyDevice) &&
- (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_NOT_VALID) ) {
- // for enumeration command, it's safe now to check the PxSIG register as starting port has been executed.
- ULONG sig = 0;
+ // 2.2 update the Identify command for enumeration. This needs to be here waiting for PxSIG to be accessible.
+ if ((srbExtension->AtaFunction == ATA_FUNCTION_ATA_IDENTIFY) &&
+ (srbExtension->CompletionRoutine == AhciPortIdentifyDevice) &&
+ (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_NOT_VALID)) {
+ // For enumeration command, it's safe now to check the PxSIG register as starting port has been executed.
+ // Note: there is chance that the signature register is FFFFFFFFh when accessing it here because reset is in progress.
+ // Handle this special case in the follow checking device type code.
+ ULONG sig = 0;
sig = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SIG.AsUlong);
- if (sig == 0x101) { //ATA
+ if (sig == ATA_DEVICE_SIGNATURE_ATA) {
srbExtension->TaskFile.Current.bCommandReg = IDE_COMMAND_IDENTIFY;
- } else { //ATAPI
+ ChannelExtension->DeviceExtension[0].DeviceParameters.AtaDeviceType = DeviceIsAta;
+ } else if (sig == ATA_DEVICE_SIGNATURE_ATAPI) {
srbExtension->TaskFile.Current.bCommandReg = IDE_COMMAND_ATAPI_IDENTIFY;
+ ChannelExtension->DeviceExtension[0].DeviceParameters.AtaDeviceType = DeviceIsAtapi;
+ } else {
+
+ ULONG ssts = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SSTS.AsUlong);
+ RecordExecutionHistory(ChannelExtension, 0x10090020); // Unexpected signature register value
+
+ if ((sig == 0) || ((sig == (ULONG)~0) && (ssts != (ULONG)~0))) {
+
+ // Case 1: A value of 0 is not a valid signature. Some devices
+ // initially report a valid signature but soon after the PxSIG
+ // register becomes 0.
+ // Case 2: A value of FFFFFFFFh is set to signature register during reset according to AHCI 1.3.1 spec,
+ // while the value maybe also FFFFFFFFh when device is removed, because PCI configuration space that mapped with AHCI registers
+ // are FFFFFFFFh. To differentiate whether it is reset or device removed, check Px.SSTS register value(it is 0 during reset).
+ //
+ // If above situations happen, just set the identify command according to the currently known device type.
+ switch (ChannelExtension->DeviceExtension[0].DeviceParameters.AtaDeviceType) {
+ case DeviceIsAta:
+ srbExtension->TaskFile.Current.bCommandReg = IDE_COMMAND_IDENTIFY;
+ break;
+
+ case DeviceIsAtapi:
+ default:
+ srbExtension->TaskFile.Current.bCommandReg = IDE_COMMAND_ATAPI_IDENTIFY;
+ break;
+ }
+
+ } else {
+
+ // Other devices types, such as with signature ATA_DEVICE_SIGNATURE_ENCLOSURE, or
+ // ATA_DEVICE_SIGNATURE_PORT_MULTIPLIER, are not supported.
+ // IDENTIFY PACKET DEVICE command will fail on these devices.
+ srbExtension->TaskFile.Current.bCommandReg = IDE_COMMAND_ATAPI_IDENTIFY;
+ ChannelExtension->DeviceExtension[0].DeviceParameters.AtaDeviceType = DeviceUnknown;
+ }
}
}
- //2.3 this is central place to update this register value in case it's wrongly set.
+ // 2.3 this is central place to update this register value in case it's wrongly set.
if (IsAtaCommand(srbExtension->AtaFunction)) {
SetDeviceReg((&srbExtension->TaskFile.Current), 0); //make sure set to device0
}
- //3 Find an available slot/tag (AHCI 1.1 Section 5.5.1)
+ // 3 Find an available slot/tag (AHCI 1.1 Section 5.5.1)
if (!AtDIRQL) {
AhciInterruptSpinlockAcquire(ChannelExtension->AdapterExtension, ChannelExtension->PortNumber, &lockHandle);
}
@@ -1113,11 +1198,11 @@ Note: This routine can be called even the Port is stopped.
GetAvailableSlot(ChannelExtension, Srb); //srbExtension->QueueTag will be set
// 3.1 If no tag is available, reject the command to be retried later
- if ( srbExtension->QueueTag > ChannelExtension->AdapterExtension->CAP.NCS ) {
- //wait for 8 IO (random picked number) being completed before re-starting sending IO to miniport for this device.
+ if (srbExtension->QueueTag > ChannelExtension->AdapterExtension->CAP.NCS) {
+ // Wait for 8 IO (random picked number) being completed before re-starting sending IO to miniport for this device.
// if filled up,
if (!IsMiniportInternalSrb(ChannelExtension, Srb)) {
- // report busy only for IOs from Storport
+ // Report busy only for IOs from Storport
StorPortDeviceBusy(ChannelExtension->AdapterExtension, pathId, targetId, lun, min(8, ChannelExtension->AdapterExtension->CAP.NCS));
}
Srb->SrbStatus = SRB_STATUS_BUSY;
@@ -1129,19 +1214,19 @@ Note: This routine can be called even the Port is stopped.
#ifdef DBG
{
- ULONG ci;
- ULONG sact;
+ ULONG ci;
+ ULONG sact;
ci = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->CI);
sact = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SACT);
// 3.2 if the tag returned can't be used, something is seriously wrong. Reject the command to be retried later
- if( ( ( (1 << srbExtension->QueueTag) & ci) > 0) || ( ( (1 << srbExtension->QueueTag) & sact) > 0) ) {
+ if ((( (1 << srbExtension->QueueTag) & ci) > 0) || (((1 << srbExtension->QueueTag) & sact) > 0)) {
if (!IsMiniportInternalSrb(ChannelExtension, Srb)) {
// pause device only for IOs from Storport
StorPortPauseDevice(ChannelExtension->AdapterExtension, pathId, targetId, lun, 1); //pause for 1 seconds.
}
// One reason why this can happen is if the adapter was removed.
- if (IsAdapterRemoved(ChannelExtension)) {
+ if (IsAdapterRemoved(ChannelExtension->AdapterExtension)) {
Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
} else {
NT_ASSERT(FALSE); //can this happen? catch it.
@@ -1179,32 +1264,32 @@ AhciFormIo(
Caller: only AhciProcessIo()
*/
{
- PAHCI_SRB_EXTENSION srbExtension;
- PSLOT_CONTENT slotContent;
- PAHCI_COMMAND_TABLE cmdTable;
- PAHCI_COMMAND_HEADER cmdHeader;
+ PAHCI_SRB_EXTENSION srbExtension;
+ PSLOT_CONTENT slotContent;
+ PAHCI_COMMAND_TABLE cmdTable;
+ PAHCI_COMMAND_HEADER cmdHeader;
STOR_PHYSICAL_ADDRESS cmdTablePhysicalAddress;
- ULONG prdtLength = 0;
- PCDB cdb = SrbGetCdb(Srb);
+ ULONG prdtLength = 0;
+ PCDB cdb = SrbGetCdb(Srb);
srbExtension = GetSrbExtension(Srb);
- // command header is allocated in ChannelExtension for all command slots, get the correct one.
+ // Command header is allocated in ChannelExtension for all command slots, get the correct one.
cmdHeader = ChannelExtension->CommandList;
cmdHeader += srbExtension->QueueTag;
slotContent = &ChannelExtension->Slot[srbExtension->QueueTag];
- // 1. setup slot content and log history
+ // 1. setup slot content and log history
slotContent->Srb = Srb;
slotContent->CmdHeader = cmdHeader;
- //1.1 Update FUA tracking flag if needed
- if( !IsReturnResults(srbExtension->Flags) &&
+ // 1.1 Update FUA tracking flag if needed
+ if (!IsReturnResults(srbExtension->Flags) &&
(cdb != NULL) &&
((cdb->CDB10.OperationCode == SCSIOP_WRITE) || (cdb->CDB10.OperationCode == SCSIOP_WRITE16)) &&
(cdb->CDB10.ForceUnitAccess == 1) &&
- IsFuaSupported(ChannelExtension) ) {
+ IsFuaSupported(ChannelExtension)) {
// Keep track of FUA to add it back in when the command is put in the FIS
slotContent->StateFlags.FUA = TRUE;
}
@@ -1245,18 +1330,17 @@ AhciFormIo(
cmdHistory->SrbStatus = 0;
}
- //already get a slot, after this point, any request completion effort needs to release the slot.
+ // Already get a slot, after this point, any request completion effort needs to release the slot.
// just like what's done in: ReleaseSlottedCommand()
- //2. Program the CFIS in the CommandTable (allocated in srbExtension)
+ // 2. Program the CFIS in the CommandTable (allocated in srbExtension)
cmdTable = (PAHCI_COMMAND_TABLE)srbExtension;
- AhciZeroMemory((PCHAR)cmdTable, sizeof(AHCI_COMMAND_TABLE));
- if ( IsAtapiCommand(srbExtension->AtaFunction) ) {
+ if (IsAtapiCommand(srbExtension->AtaFunction)) {
SRBtoATAPI_CFIS(ChannelExtension, slotContent);
- } else if ( IsAtaCfisPayload(srbExtension->AtaFunction) ) {
+ } else if (IsAtaCfisPayload(srbExtension->AtaFunction)) {
CfistoATA_CFIS(ChannelExtension, slotContent);
- } else if ( IsAtaCommand(srbExtension->AtaFunction) ) {
+ } else if (IsAtaCommand(srbExtension->AtaFunction)) {
SRBtoATA_CFIS(ChannelExtension, slotContent);
} else {
NT_ASSERT(FALSE);
@@ -1266,10 +1350,8 @@ AhciFormIo(
return TRUE;
}
-
-
- //3. Build the PRD Table in CommandTable.
- if( IsDataTransferNeeded(slotContent->Srb) ) {
+ // 3. Build the PRD Table in CommandTable.
+ if (IsDataTransferNeeded(slotContent->Srb)) {
prdtLength = SRBtoPRDT(ChannelExtension, slotContent);
if (prdtLength == -1) {
NT_ASSERT(FALSE);
@@ -1280,22 +1362,21 @@ AhciFormIo(
}
}
- //4. Program the Command Header (allocated in ChannelExtension for all command slots)
+ // 4. Program the Command Header (allocated in ChannelExtension for all command slots)
SRBtoCmdHeader(ChannelExtension, slotContent, prdtLength, FALSE);
- //4.1. Get the Command Table's physical address to verify the alignment and program cmdHeader->CTBA
+ // 4.1. Get the Command Table's physical address to verify the alignment and program cmdHeader->CTBA
if ((PSTORAGE_REQUEST_BLOCK)&ChannelExtension->Local.Srb == Srb) {
cmdTablePhysicalAddress = ChannelExtension->Local.SrbExtensionPhysicalAddress;
} else if ((PSTORAGE_REQUEST_BLOCK)&ChannelExtension->Sense.Srb == Srb) {
cmdTablePhysicalAddress = ChannelExtension->Sense.SrbExtensionPhysicalAddress;
} else {
ULONG length;
- cmdTablePhysicalAddress = StorPortGetPhysicalAddress(ChannelExtension->AdapterExtension,
- NULL,
- srbExtension,
- &length);
+ // SRB is needed for StorPortGetPhysicalAddress to calculate logical address when DMAR is enabled.
+ cmdTablePhysicalAddress = StorPortGetPhysicalAddress(ChannelExtension->AdapterExtension, (PSCSI_REQUEST_BLOCK)Srb, srbExtension, &length);
}
- if ((cmdTablePhysicalAddress.LowPart % 128) == 0 ) {
+
+ if ((cmdTablePhysicalAddress.LowPart % 128) == 0) {
cmdHeader->CTBA.AsUlong = cmdTablePhysicalAddress.LowPart;
} else {
slotContent->Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
@@ -1303,28 +1384,29 @@ AhciFormIo(
RecordExecutionHistory(ChannelExtension, 0x10080020);//Invalid PhyscialAddress alignment
return TRUE;
}
- //If the controller supports 64 bits, write the high part too
- if (ChannelExtension->AdapterExtension->CAP.S64A) {
+
+ // If the controller supports 64 bits, write the high part too
+ if (ChannelExtension->AdapterExtension->CAP.S64A) {
cmdHeader->CTBAU = cmdTablePhysicalAddress.HighPart;
}
- //5. Sort it, put request in one of IO Slices.
- //5.1. Keep track of high priority outside of the Slices
- if ( IsHighPriorityCommand(srbExtension->Flags) ){
+ // 5. Sort it, put request in one of IO Slices.
+ // 5.1. Keep track of high priority outside of the Slices
+ if (IsHighPriorityCommand(srbExtension->Flags)) {
ChannelExtension->SlotManager.HighPriorityAttribute |= ( 1 << srbExtension->QueueTag);
}
- //5.2. Put the slot content in the correct Slice
- if ( IsNCQCommand(srbExtension) ) {
+
+ // 5.2. Put the slot content in the correct Slice
+ if (IsNCQCommand(srbExtension)) {
ChannelExtension->SlotManager.NCQueueSlice |= ( 1 << srbExtension->QueueTag);
- } else if ( IsReturnResults(srbExtension->Flags) ) {
+ } else if (IsReturnResults(srbExtension->Flags)) {
ChannelExtension->SlotManager.SingleIoSlice |= ( 1 << srbExtension->QueueTag);
- } else if ( IsNormalCommand(slotContent->Srb) ) {
+ } else if (IsNormalCommand(slotContent->Srb)) {
ChannelExtension->SlotManager.NormalQueueSlice |= ( 1 << srbExtension->QueueTag);
} else {
ChannelExtension->SlotManager.SingleIoSlice |= ( 1 << srbExtension->QueueTag);
}
-
if (LogExecuteFullDetail(ChannelExtension->AdapterExtension->LogFlags)) {
RecordExecutionHistory(ChannelExtension, 0x10000020);//Exit AhciHwStartIo
}
@@ -1340,19 +1422,19 @@ BuildRequestSenseSrb(
_In_ PSTORAGE_REQUEST_BLOCK FailingSrb
)
{
- STOR_PHYSICAL_ADDRESS dataBufferPhysicalAddress;
- ULONG length;
- PCDB cdb;
- PSCSI_REQUEST_BLOCK senseSrb = &ChannelExtension->Sense.Srb;
- PAHCI_SRB_EXTENSION srbExtension = ChannelExtension->Sense.SrbExtension;
- PVOID srbSenseBuffer = NULL;
- UCHAR srbSenseBufferLength = 0;
+ STOR_PHYSICAL_ADDRESS dataBufferPhysicalAddress;
+ ULONG length;
+ PCDB cdb;
+ PSCSI_REQUEST_BLOCK senseSrb = &ChannelExtension->Sense.Srb;
+ PAHCI_SRB_EXTENSION srbExtension = ChannelExtension->Sense.SrbExtension;
+ PVOID srbSenseBuffer = NULL;
+ UCHAR srbSenseBufferLength = 0;
RequestGetSrbScsiData(FailingSrb, NULL, NULL, &srbSenseBuffer, &srbSenseBufferLength);
- //1. validate if senseSrb should be used.
- if ( (srbExtension == NULL) || (srbExtension->AtaFunction != 0) ||
- (srbSenseBuffer == NULL) || (srbSenseBufferLength == 0) ) {
+ // 1. Validate if senseSrb should be used.
+ if ((srbExtension == NULL) || (srbExtension->AtaFunction != 0) ||
+ (srbSenseBuffer == NULL) || (srbSenseBufferLength == 0)) {
// Request Sense is for ATAPI commands which are single IOs. At the same time there should be only one command failed and needs this Srb.
NT_ASSERT(srbExtension && srbExtension->AtaFunction == 0);
return NULL;
@@ -1362,11 +1444,11 @@ BuildRequestSenseSrb(
AhciZeroMemory((PCHAR)srbSenseBuffer, srbSenseBufferLength);
}
- //2. initialize Srb and SrbExtension structures.
+ // 2. Initialize Srb and SrbExtension structures.
AhciZeroMemory((PCHAR)senseSrb, sizeof(SCSI_REQUEST_BLOCK));
AhciZeroMemory((PCHAR)srbExtension, sizeof(AHCI_SRB_EXTENSION));
- //3. setup Srb and CDB. Note that Sense Srb uses SCSI_REQUEST_BLOCK type.
+ // 3. Setup Srb and CDB. Note that Sense Srb uses SCSI_REQUEST_BLOCK type.
senseSrb->Length = sizeof(SCSI_REQUEST_BLOCK);
senseSrb->Function = SRB_FUNCTION_EXECUTE_SCSI;
senseSrb->PathId = (UCHAR)ChannelExtension->PortNumber;
@@ -1383,11 +1465,12 @@ BuildRequestSenseSrb(
cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
cdb->CDB6INQUIRY.AllocationLength = (UCHAR)senseSrb->DataTransferLength;
- //4. fill in the srbExtension fields
+ // 4. Fill in the srbExtension fields
srbExtension->AtaFunction = ATA_FUNCTION_REQUEST_SENSE;
srbExtension->Flags = ATA_FLAGS_DATA_IN;
- dataBufferPhysicalAddress = StorPortGetPhysicalAddress(ChannelExtension->AdapterExtension, NULL, srbSenseBuffer, &length);
+ // SRB is needed for StorPortGetPhysicalAddress to calculate logical address when DMAR is enabled.
+ dataBufferPhysicalAddress = StorPortGetPhysicalAddress(ChannelExtension->AdapterExtension, (PSCSI_REQUEST_BLOCK)FailingSrb, srbSenseBuffer, &length);
if (dataBufferPhysicalAddress.QuadPart == 0) {
NT_ASSERT(FALSE); //Shall Not Pass
return NULL;
@@ -1411,7 +1494,7 @@ AhciPortFailAllIos(
{
UCHAR i;
- // complete all requests in slots
+ // Complete all requests in slots
for (i = 0; i <= ChannelExtension->AdapterExtension->CAP.NCS; i++) {
if (ChannelExtension->Slot[i].Srb != NULL) {
ChannelExtension->Slot[i].Srb->SrbStatus = SrbStatus;
@@ -1419,7 +1502,7 @@ AhciPortFailAllIos(
}
}
- // requests in completion queue will be completed by AhciPortSrbCompletionDpcRoutine.
+ // Requests in completion queue will be completed by AhciPortSrbCompletionDpcRoutine.
return;
}
@@ -1433,12 +1516,13 @@ AhciPortSrbCompletionDpcRoutine(
)
{
PAHCI_CHANNEL_EXTENSION channelExtension = (PAHCI_CHANNEL_EXTENSION)SystemArgument1;
- STOR_LOCK_HANDLE lockhandle = {InterruptLock, 0};
- PSTORAGE_REQUEST_BLOCK srb = NULL;
+ STOR_LOCK_HANDLE lockhandle = { InterruptLock, 0 };
+ PSTORAGE_REQUEST_BLOCK srb = NULL;
PSRB_COMPLETION_ROUTINE completionRoutine = NULL;
- BOOLEAN reservedSlotInUse = FALSE;
- BOOLEAN sendCommand = FALSE;
- ULONGLONG count = 0; // record the number of Srb being completed in this routine. It's for diagnostic purpose.
+ BOOLEAN reservedSlotInUse = FALSE;
+ BOOLEAN sendCommand = FALSE;
+ BOOLEAN sendCommandForLocalSrb = FALSE;
+ ULONGLONG count = 0; // record the number of Srb being completed in this routine. It's for diagnostic purpose.
UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(SystemArgument2);
@@ -1452,6 +1536,8 @@ AhciPortSrbCompletionDpcRoutine(
RecordExecutionHistory(channelExtension, 0x0000001e);//Enter AhciPortSrbCompletionDpcRoutine
}
+ StorPortQuerySystemTime(&(channelExtension->LastTimeStampDpcStart));
+
//
// Preserve the use status about Reserved Slot.
//
@@ -1463,7 +1549,7 @@ AhciPortSrbCompletionDpcRoutine(
AhciInterruptSpinlockRelease(channelExtension->AdapterExtension, channelExtension->PortNumber, &lockhandle);
if (srb != NULL) {
- PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(srb);
+ PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(srb);
BOOLEAN completeSrb = TRUE;
@@ -1476,35 +1562,85 @@ AhciPortSrbCompletionDpcRoutine(
completionRoutine(channelExtension, srb);
- // a request with STATUS_BUS_RESET should be completed after running completion routine.
- if ( (srbExtension->AtaFunction != 0) &&
- (!SrbShouldBeCompleted(srbExtension->Flags)) &&
- (srb->SrbStatus != SRB_STATUS_BUS_RESET) ) {
+ // A request with STATUS_BUS_RESET should be completed after running completion routine.
+ if ((srbExtension->AtaFunction != 0) &&
+ (!SrbShouldBeCompleted(srbExtension->Flags)) &&
+ (srb->SrbStatus != SRB_STATUS_BUS_RESET)) {
// new command associated needs to be processed, do not complete the request.
AhciProcessIo(channelExtension, srb, FALSE);
- // this Srb should not be completed yet
+ // This Srb should not be completed yet
completeSrb = FALSE;
sendCommand = TRUE;
+ if (srb == (PSTORAGE_REQUEST_BLOCK)&channelExtension->Local.Srb) {
+ sendCommandForLocalSrb = TRUE;
+ }
+
} else if (SrbShouldBeCompleted(srbExtension->Flags)) {
- // clear the flag
+ // Clear the flag
CLRMASK(srbExtension->Flags, ATA_FLAGS_COMPLETE_SRB);
}
-
} else {
- // a Srb without completion routine should be completed.
+ // An Srb without completion routine should be completed.
+ }
+
+ if ((srb == (PSTORAGE_REQUEST_BLOCK)&channelExtension->Local.Srb) &&
+ reservedSlotInUse &&
+ channelExtension->StateFlags.ReservedSlotInUse &&
+ (!sendCommandForLocalSrb)) {
+
+ //
+ // This should never happen. ReservedSlotInUse flag will stuck.
+ //
+
+ NT_ASSERT(FALSE);
+
+ RecordExecutionHistory(channelExtension, 0x1001001e); //AhciPortSrbCompletionDpcRoutine, ReservedSlotInUse starts to stuck
+
+ AhciTelemetryLog(channelExtension->AdapterExtension,
+ (PSTOR_ADDRESS)&(channelExtension->DeviceExtension->DeviceAddress),
+ AHCI_TELEMETRY_DRIVER_VERSION,
+ AhciTelemetryEventIdReservedSlotStuck,
+ "Reserved Slot Stuck",
+ AHCI_TELEMETRY_EVENT_VERSION,
+ 0,
+ 0,
+ NULL,
+ "CommandsIssued",
+ channelExtension->SlotManager.CommandsIssued,
+ "NCQueueSlice",
+ channelExtension->SlotManager.NCQueueSlice,
+ "NormalQueueSlice",
+ channelExtension->SlotManager.NormalQueueSlice,
+ "SingleIoSlice",
+ channelExtension->SlotManager.SingleIoSlice,
+ "CommandsToComplete",
+ channelExtension->SlotManager.CommandsToComplete,
+ "StateFlags",
+ *(ULONGLONG *)&(channelExtension->StateFlags),
+ "StartState",
+ *(ULONGLONG *)&(channelExtension->StartState),
+ "Flags|Function|Status",
+ (ULONGLONG)((((ULONGLONG)srbExtension->Flags) << 32) |
+ (((ULONGLONG)srbExtension->AtaFunction) << 16) |
+ (ULONGLONG)(srb->SrbStatus))
+ );
}
if (completeSrb) {
- // release active reference for port/device and adapter.
+ // Release active reference for port/device and adapter.
if ((srbExtension->Flags & ATA_FLAGS_ACTIVE_REFERENCE) != 0) {
PortReleaseActiveReference(channelExtension, srb);
}
if (!IsMiniportInternalSrb(channelExtension, srb)) {
+ if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
+
+ }
+
NT_ASSERT(srb->SrbStatus != SRB_STATUS_PENDING);
StorPortNotification(RequestComplete, AdapterExtension, srb);
}
@@ -1523,9 +1659,11 @@ AhciPortSrbCompletionDpcRoutine(
}
if (sendCommand) {
- ActivateQueue(channelExtension, TRUE);
+ ActivateQueue(channelExtension, (IsDumpMode(channelExtension->AdapterExtension) ? (TRUE) : (FALSE)));
}
+ StorPortQuerySystemTime(&(channelExtension->LastTimeStampDpcCompletion));
+
if (LogExecuteFullDetail(channelExtension->AdapterExtension->LogFlags)) {
RecordExecutionHistory(channelExtension, 0x1000001e);//Exit AhciPortSrbCompletionDpcRoutine
}
@@ -1539,4 +1677,3 @@ AhciPortSrbCompletionDpcRoutine(
#pragma warning(default:4214)
#pragma warning(default:4201)
#endif
-
diff --git a/storage/miniports/storahci/src/io.h b/storage/miniports/storahci/src/io.h
index 00b3a44f..8e9df9b5 100644
--- a/storage/miniports/storahci/src/io.h
+++ b/storage/miniports/storahci/src/io.h
@@ -122,4 +122,3 @@ HW_DPC_ROUTINE AhciPortSrbCompletionDpcRoutine;
HW_DPC_ROUTINE AhciPortBusChangeDpcRoutine;
-
diff --git a/storage/miniports/storahci/src/pnppower.c b/storage/miniports/storahci/src/pnppower.c
index ca9b6ff6..a6b5e3d6 100644
--- a/storage/miniports/storahci/src/pnppower.c
+++ b/storage/miniports/storahci/src/pnppower.c
@@ -1,4 +1,4 @@
-/*++
+/*++
Copyright (C) Microsoft Corporation, 2009
@@ -19,7 +19,7 @@ Revision History:
#pragma warning(push)
#pragma warning(disable:26015) //26015: "Potential overflow using expression 'outParams->DriverStatus.bDriverError'. Buffer access is apparently unbounded by the buffer size.
- //Output buffer cannot be checked for size. ATAport provides this validation check as the input buffer size and output buffer size are 2 of the 4 parameters passed in on the SMART IRP. Storport doesn�t do this and the miniport doesn�t get the IRP so it cannot do this for itself. This is just the condition of a legacy IOCTL.
+ //Output buffer cannot be checked for size. ATAport provides this validation check as the input buffer size and output buffer size are 2 of the 4 parameters passed in on the SMART IRP. Storport doesn’t do this and the miniport doesn’t get the IRP so it cannot do this for itself. This is just the condition of a legacy IOCTL.
//26015: "Potential overflow using expression 'nRB->NRBStatus' Buffer access is apparently unbounded by the buffer size.
//The same is true for the NVCache IOCTL. Instead of the output buffer, this time it is the NVCache_Request_Block.
#pragma warning(disable:4214) // bit field types other than int
@@ -79,13 +79,13 @@ It performs:
3.1 Enable the AHCI interface
AHCI 1.1 Section 10.1.2 - 5.
"For each implemented port, system software shall allocate memory for and program:
- � PxCLB and PxCLBU (if CAP.S64A is set to �1�)
- � PxFB and PxFBU (if CAP.S64A is set to �1�)
- It is good practice for system software to �zero-out� the memory allocated and referenced by PxCLB and PxFB. After setting PxFB and PxFBU to the physical address of the FIS receive area, system software shall set PxCMD.FRE to �1�."
+ • PxCLB and PxCLBU (if CAP.S64A is set to ‘1’)
+ • PxFB and PxFBU (if CAP.S64A is set to ‘1’)
+ It is good practice for system software to ‘zero-out’ the memory allocated and referenced by PxCLB and PxFB. After setting PxFB and PxFBU to the physical address of the FIS receive area, system software shall set PxCMD.FRE to ‘1’."
3.2 Enable Interrupts on the Channel
AHCI 1.1 Section 10.1.2 - 7.
- "Determine which events should cause an interrupt, and set each implemented port�s PxIE register with the appropriate enables."
- Note: Due to the multi-tiered nature of the AHCI HBA�s interrupt architecture, system software must always ensure that the PxIS (clear this first) and IS.IPS (clear this second) registers are cleared to �0� before programming the PxIE and GHC.IE registers. This will prevent any residual bits set in these registers from causing an interrupt to be asserted.
+ "Determine which events should cause an interrupt, and set each implemented port’s PxIE register with the appropriate enables."
+ Note: Due to the multi-tiered nature of the AHCI HBA’s interrupt architecture, system software must always ensure that the PxIS (clear this first) and IS.IPS (clear this second) registers are cleared to ‘0’ before programming the PxIE and GHC.IE registers. This will prevent any residual bits set in these registers from causing an interrupt to be asserted.
4.1 Allocate memory for the CommandList, the Receive FIS buffer and SRB Extension
Now is the time to allocate memory that will be used for controller and per request structures.
@@ -193,7 +193,6 @@ NOTE: as this routine is invoked from FindAdapter where the adapter might not be
ChannelExtension->DeviceExtension[0].IdentifyDataPhysicalAddress = StorPortGetPhysicalAddress(adapterExtension, NULL, (PVOID)ChannelExtension->DeviceExtension[0].IdentifyDeviceData, &mappedLength);
ChannelExtension->DeviceExtension[0].InquiryDataPhysicalAddress = StorPortGetPhysicalAddress(adapterExtension, NULL, (PVOID)ChannelExtension->DeviceExtension[0].InquiryData, &mappedLength);
-
//4.8 Setup STOR_ADDRESS for the device. StorAHCI uses Bus/Target/Lun addressing model, thus uses STOR_ADDRESS_TYPE_BTL8.
// Port - not need to be set by miniport, Storport has this knowledge. miniport can get the value by calling StorPortGetSystemPortNumber().
// Path - StorAHCI reports (highest implemented port number + 1) as bus number, thus "port number" will be "Path" value.
@@ -261,11 +260,11 @@ Affected Variables/Registers:
GHC.AE, GHC.IE
Return Values:
TRUE always.
---*/ //Used to enable the AHCI interface
+--*/
{
- ULONG i;
+ ULONG i;
AHCI_Global_HBA_CONTROL ghc;
- PAHCI_MEMORY_REGISTERS abar = (PAHCI_MEMORY_REGISTERS)AdapterExtension->ABAR_Address;
+ PAHCI_MEMORY_REGISTERS abar = (PAHCI_MEMORY_REGISTERS)AdapterExtension->ABAR_Address;
AdapterExtension->StateFlags.PowerDown = 0;
@@ -286,9 +285,9 @@ Return Values:
// Power up all ports that don't have a device present.
// There is protection method in AhciPortPowerUp() to only allow it run once.
for (i = 0; i <= AdapterExtension->HighestPort; i++) {
- if ( (AdapterExtension->PortExtension[i] != NULL) &&
- (AdapterExtension->PortExtension[i]->StateFlags.PowerDown == TRUE) &&
- (AdapterExtension->PortExtension[i]->DeviceExtension[0].DeviceParameters.AtaDeviceType == DeviceNotExist)) {
+ if ((AdapterExtension->PortExtension[i] != NULL) &&
+ (AdapterExtension->PortExtension[i]->StateFlags.PowerDown == TRUE) &&
+ (AdapterExtension->PortExtension[i]->DeviceExtension[0].DeviceParameters.AtaDeviceType == DeviceNotExist)) {
AhciPortPowerUp(AdapterExtension->PortExtension[i]);
}
}
@@ -310,22 +309,22 @@ Called by:
It performs:
1. Clear GHC.IE
AHCI 1.1 Section 8.3.3
- "Software must disable interrupts (GHC.IE must be cleared to �0�) prior to requesting a transition of the HBA to the D3 state. This precaution by software avoids an interrupt storm if an interrupt occurs during the transition to the D3 state."
+ "Software must disable interrupts (GHC.IE must be cleared to ‘0’) prior to requesting a transition of the HBA to the D3 state. This precaution by software avoids an interrupt storm if an interrupt occurs during the transition to the D3 state."
Affected Variables/Registers:
GHC.IE
Return Values:
TRUE always.
--*/
{
- ULONG i;
+ ULONG i;
AHCI_Global_HBA_CONTROL ghc;
- PAHCI_MEMORY_REGISTERS abar = (PAHCI_MEMORY_REGISTERS)AdapterExtension->ABAR_Address;
+ PAHCI_MEMORY_REGISTERS abar = (PAHCI_MEMORY_REGISTERS)AdapterExtension->ABAR_Address;
// Power down all ports that don't have a device present.
for (i = 0; i <= AdapterExtension->HighestPort; i++) {
- if ( (AdapterExtension->PortExtension[i] != NULL) &&
- (AdapterExtension->PortExtension[i]->StateFlags.PowerDown == FALSE) &&
- (AdapterExtension->PortExtension[i]->DeviceExtension[0].DeviceParameters.AtaDeviceType == DeviceNotExist)) {
+ if ((AdapterExtension->PortExtension[i] != NULL) &&
+ (AdapterExtension->PortExtension[i]->StateFlags.PowerDown == FALSE) &&
+ (AdapterExtension->PortExtension[i]->DeviceExtension[0].DeviceParameters.AtaDeviceType == DeviceNotExist)) {
AhciPortPowerDown(AdapterExtension->PortExtension[i]);
}
}
@@ -382,13 +381,14 @@ Return Values:
if (LogExecuteFullDetail(ChannelExtension->AdapterExtension->LogFlags)) {
RecordExecutionHistory(ChannelExtension, 0x00000025);//AhciPortStop
}
- //1. Stop the channel
+
+ //1. Stop the channel
if ( !P_NotRunning(ChannelExtension, ChannelExtension->Px) ) {
// don't need RESET, the port will be tried to start when processing start device request
RecordExecutionHistory(ChannelExtension, 0xff08); //AhciPortStop Failed
}
- //2. Disable Interrupt and disconnect with Port resources
+ //2. Disable Interrupt and disconnect with Port resources
StorPortWriteRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->IE.AsUlong, 0); //disabling interrupts
PortClearPendingInterrupt(ChannelExtension);
@@ -432,19 +432,25 @@ Return Values:
--*/
AHCI_LPM_POWER_SETTINGS userLpmSettings;
- BOOLEAN portPowerDown;
+ BOOLEAN portPowerDown;
+ AHCI_INTERRUPT_STATUS pxis = { 0 };
RecordExecutionHistory(ChannelExtension, 0x00000026);//Enter AhciPortPowerUp
- //1.0 Reinitialize the StateFlags. e.g. ChannelExtension->StateFlags.PowerDown = FALSE;
+ ++(ChannelExtension->TotalCountPowerUp);
+
+ pxis.AsUlong = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->IS.AsUlong);
+
+ // 1.0 Reinitialize the StateFlags. e.g. ChannelExtension->StateFlags.PowerDown = FALSE;
portPowerDown = InterlockedBitTestAndReset((LONG*)&ChannelExtension->StateFlags, 12); //StateFlags.PownDown field is at bit 12
if (portPowerDown == FALSE) {
+
RecordExecutionHistory(ChannelExtension, 0x00010026);//AhciPortPowerUp: port already powered up.
return;
}
- //1.1 Reload the CLB,CBU,FLB,FBU
+ // 1.1 Reload the CLB,CBU,FLB,FBU
StorPortWriteRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->CLB.AsUlong, ChannelExtension->CommandListPhysicalAddress.LowPart);
if (ChannelExtension->AdapterExtension->CAP.S64A) { //If the controller supports 64 bits, write high part
StorPortWriteRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->CLBU, ChannelExtension->CommandListPhysicalAddress.HighPart);
@@ -454,26 +460,46 @@ Return Values:
StorPortWriteRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->FBU, ChannelExtension->ReceivedFisPhysicalAddress.HighPart);
}
-
//
// If D3 Cold is enabled and we are being powered up from D3, we need to be
// a bit heavy-handed with powering up the port due to loss of context.
//
if (ChannelExtension->DevicePowerState == StorPowerDeviceD3 && IsPortD3ColdEnabled(ChannelExtension)) {
-
+
+ STOR_LOCK_HANDLE lockhandle = { InterruptLock, 0 };
+ BOOLEAN powerUpInitializationInProgress = 0;
+
// 1.4.1 Re-issue init commands (this will also restore preserved settings).
AhciPortIssueInitCommands(ChannelExtension);
-
+
+ // Set PowerUpInitializationInProgress flag, which will be cleared when preserved settings command done.
+ powerUpInitializationInProgress = InterlockedBitTestAndSet((LONG*)&ChannelExtension->StateFlags, 22); //PowerUpInitializationInProgress field is at bit 22
+
+ if (powerUpInitializationInProgress == 1) {
+
+ // PowerUpInitializationInProgress flag was not cleared properly, which is not expected to happen, but not a fatal issue.
+ RecordExecutionHistory(ChannelExtension, 0x10020026); // AhciPortPowerUp: PowerUpInitializationInProgress flag was not cleared properly.
+ }
+
// 1.4.2 Restore LPM settings
userLpmSettings.AsUlong = ChannelExtension->LastUserLpmPowerSetting;
AhciLpmSettingsModes(ChannelExtension, userLpmSettings); //ignore the returned value, IO will be restarted anyway.
-
// 1.5 Start the channel by issuing a reset to restore PHY communication.
+ AhciInterruptSpinlockAcquire(ChannelExtension->AdapterExtension, ChannelExtension->PortNumber, &lockhandle);
AhciPortReset(ChannelExtension, FALSE);
-
+ AhciInterruptSpinlockRelease(ChannelExtension->AdapterExtension, ChannelExtension->PortNumber, &lockhandle);
+
} else {
+ //
+ // If there is change in Current Connect Status(PCS:1), then QDR is needed.
+ //
+ if ((pxis.PCS == 1) &&
+ (ChannelExtension->StartState.ChannelNextStartState == StartFailed)) {
+ ChannelExtension->StateFlags.NeedQDR = TRUE;
+ }
+
// 1.4.1 Restore Preserved Settings
if (NeedToSetTransferMode(ChannelExtension)) {
RestorePreservedSettings(ChannelExtension, FALSE);
@@ -484,6 +510,7 @@ Return Values:
}
RecordExecutionHistory(ChannelExtension, 0x10000026);//Exit AhciPortPowerUp
+
return;
}
@@ -514,6 +541,8 @@ Return Values:
--*/
ChannelExtension->StateFlags.PowerDown = TRUE;
+ ++(ChannelExtension->TotalCountPowerDown);
+
//
// Cancel the StartPortTimer since we're going into a lower power state.
//
@@ -528,6 +557,7 @@ Return Values:
// the link will be inactive, ignore the hot plug noise.
ChannelExtension->StateFlags.IgnoreHotplugInterrupt = TRUE;
}
+
}
RecordExecutionHistory(ChannelExtension, 0x10000027);//Exit AhciPortPowerDown
@@ -564,7 +594,6 @@ ReportLunsComplete(
return;
}
-
Srb->SrbStatus = SRB_STATUS_SUCCESS;
SrbSetScsiStatus(Srb, SCSISTAT_GOOD);
@@ -609,24 +638,181 @@ ReportLunsComplete(
return;
}
+__inline
+VOID
+GetLogInfoRegValueName(
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _Out_writes_(ValueNameLength) PCHAR ValueName,
+ _In_ ULONG ValueNameLength
+ )
+/*++
+
+Routine Description:
+
+ This function append Port Number to "LogPageInfo" as name of registry value.
+ This is a work around as StorAHCI doesn't have access to RtlStringCbPrintfA().
+
+Arguments:
+
+ ChannelExtension - Pointer to the device extension for channel.
+
+ ValueName - Registry name to be written.
+
+ ValueNameLength - Registry name length.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ NT_ASSERT(ChannelExtension->PortNumber <= 255);
+
+ if (ValueNameLength >= 14) {
+
+ ULONG portNumber = ChannelExtension->PortNumber;
+ ULONG remainder = 0;
+
+ StorPortCopyMemory(ValueName, "LogPageInfo", 12);
+ ValueName[13] = '\0';
+
+ remainder = portNumber % 16; // use HEX value, base is 16.
+ ValueName[12] = (CHAR)((remainder < 10) ? (remainder + '0') : (remainder - 10 + 'A'));
+
+ portNumber /= 16;
+ remainder = portNumber % 16;
+ ValueName[11] = (CHAR)((remainder < 10) ? (remainder + '0') : (remainder - 10 + 'A'));
+ }
+
+ return;
+}
+
+_Function_class_(HW_WORKITEM)
+VOID
+AhciRegistryWriteWorker(
+ _In_ PAHCI_ADAPTER_EXTENSION AdapterExtension,
+ _In_ PVOID Context,
+ _In_ PVOID WorkItem
+ )
+/*++
+
+Routine Description:
+
+ This function runs in the context of a work item. It performs writting registry with data
+ from Log Pages that needs to be cached.
+
+Arguments:
+
+ AdapterExtension - Pointer to the device extension for adapter.
+
+ Context - The AHCI_CHANNEL_EXTENSION we specified when we queued this work item.
+
+ WorkItem - The work item object.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PAHCI_CHANNEL_EXTENSION channelExtension = (PAHCI_CHANNEL_EXTENSION)Context;
+ ULONG storStatus;
+ CHAR valueName[16] = { 0 };
+ AHCI_DEVICE_LOG_PAGE_INFO logPageInfo = { 0 };
+
+ NT_ASSERT(Context != NULL);
+ NT_ASSERT(WorkItem != NULL);
+
+ GetLogInfoRegValueName(channelExtension, valueName, sizeof(valueName));
+
+ StorPortCopyMemory((PVOID)&logPageInfo.QueryLogPages, &channelExtension->DeviceExtension[0].QueryLogPages, sizeof(ATA_GPL_PAGES_TO_QUERY));
+ StorPortCopyMemory((PVOID)&logPageInfo.SupportedGPLPages, &channelExtension->DeviceExtension[0].SupportedGPLPages, sizeof(ATA_SUPPORTED_GPL_PAGES));
+ StorPortCopyMemory((PVOID)&logPageInfo.SupportedCommands, &channelExtension->DeviceExtension[0].SupportedCommands, sizeof(ATA_COMMAND_SUPPORTED));
+ StorPortCopyMemory((PVOID)&logPageInfo.FirmwareUpdate, &channelExtension->DeviceExtension[0].FirmwareUpdate, sizeof(DOWNLOAD_MICROCODE_CAPABILITIES));
+
+ storStatus = StorPortRegistryWriteAdapterKey(AdapterExtension,
+ (PUCHAR)"StorAHCI",
+ (PUCHAR)valueName,
+ MINIPORT_REG_BINARY,
+ &logPageInfo,
+ sizeof(AHCI_DEVICE_LOG_PAGE_INFO));
+
+ if (storStatus == STOR_STATUS_SUCCESS) {
+ channelExtension->DeviceExtension[0].UpdateCachedLogPageInfo = FALSE;
+ } else {
+ NT_ASSERT(FALSE);
+ }
+
+ //
+ // Call the callback routine if there is one.
+ //
+
+ if (WorkItem != NULL) {
+ StorPortFreeWorker(AdapterExtension, WorkItem);
+ }
+
+ return;
+}
+
+VOID
+PreserveLogPageInformation(
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
+ )
+/*++
+
+ This routine allocates a work item and schedule it for saving information retrieved from Log Pages.
+
+Parameters:
+
+ ChannelExtension - port and device that log pages are retrieved from.
+
+Return Values:
+
+ None
+
+--*/
+{
+ ULONG storStatus;
+ PVOID workItem = NULL;
+
+ storStatus = StorPortInitializeWorker(ChannelExtension->AdapterExtension, &workItem);
+
+ if (storStatus == STOR_STATUS_SUCCESS) {
+ storStatus = StorPortQueueWorkItem(ChannelExtension->AdapterExtension, AhciRegistryWriteWorker, workItem, ChannelExtension);
+ }
+
+ NT_ASSERT(storStatus == STOR_STATUS_SUCCESS);
+
+ if ((storStatus != STOR_STATUS_SUCCESS) && (workItem != NULL)) {
+ // Free the work item as it cannot be scheduled to run.
+ StorPortFreeWorker(ChannelExtension->AdapterExtension, workItem);
+ }
+
+ return;
+}
+
VOID
-InitQueryLogPages (
+InitQueryLogPages(
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
)
/*++
+
Initialize Log Pages to Read.
Note that this functions should only be called after Identify Device Data is retrieved.
Parameters:
- ChannelExtension - port that log-pages-to-query should be inited.
+
+ ChannelExtension - port that log-pages-to-query should be inited.
Return Values:
+
None
--*/
{
PUSHORT index = &ChannelExtension->DeviceExtension->QueryLogPages.TotalPageCount;
+
//
// Log Page only applies to ATA device; General Purpose Logging feature should be supported;
// 48bit command should be supported as READ LOG EXT is a 48bit command.
@@ -637,7 +823,7 @@ Return Values:
AhciZeroMemory((PCHAR)&ChannelExtension->DeviceExtension->QueryLogPages, sizeof(ATA_GPL_PAGES_TO_QUERY));
- // read Log Directory
+ // Read Log Directory
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].Query = TRUE;
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].LogAddress = IDE_GP_LOG_DIRECTORY_ADDRESS;
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].PageNumber = 0;
@@ -645,7 +831,7 @@ Return Values:
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].FeatureField = 0;
*index = *index + 1;
- // read Device Statistics log - supported page
+ // Read Device Statistics log - supported page
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].Query = TRUE;
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].LogAddress = IDE_GP_LOG_DEVICE_STATISTICS_ADDRESS;
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].PageNumber = IDE_GP_LOG_SUPPORTED_PAGES;
@@ -653,7 +839,7 @@ Return Values:
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].FeatureField = 0;
*index = *index + 1;
- // read Device Statistics log - general page
+ // Read Device Statistics log - general page
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].Query = TRUE;
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].LogAddress = IDE_GP_LOG_DEVICE_STATISTICS_ADDRESS;
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].PageNumber = IDE_GP_LOG_DEVICE_STATISTICS_GENERAL_PAGE;
@@ -661,7 +847,7 @@ Return Values:
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].FeatureField = 0;
*index = *index + 1;
- // read Identify Device Data log - supported page
+ // Read Identify Device Data log - supported page
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].Query = TRUE;
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].LogAddress = IDE_GP_LOG_IDENTIFY_DEVICE_DATA_ADDRESS;
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].PageNumber = IDE_GP_LOG_SUPPORTED_PAGES;
@@ -669,7 +855,7 @@ Return Values:
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].FeatureField = 0;
*index = *index + 1;
- // read Identify Device Data log - Supported Capabilities page
+ // Read Identify Device Data log - Supported Capabilities page
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].Query = TRUE;
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].LogAddress = IDE_GP_LOG_IDENTIFY_DEVICE_DATA_ADDRESS;
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].PageNumber = IDE_GP_LOG_IDENTIFY_DEVICE_DATA_SUPPORTED_CAPABILITIES_PAGE;
@@ -677,7 +863,7 @@ Return Values:
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].FeatureField = 0;
*index = *index + 1;
- // read Identify Device Data log - SATA page
+ // Read Identify Device Data log - SATA page
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].Query = TRUE;
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].LogAddress = IDE_GP_LOG_IDENTIFY_DEVICE_DATA_ADDRESS;
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].PageNumber = IDE_GP_LOG_IDENTIFY_DEVICE_DATA_SATA_PAGE;
@@ -685,7 +871,7 @@ Return Values:
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].FeatureField = 0;
*index = *index + 1;
- // read Saved Device Internal log
+ // Read Saved Device Internal log
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].Query = TRUE;
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].LogAddress = IDE_GP_LOG_SAVED_DEVICE_INTERNAL_STATUS;
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].PageNumber = 0;
@@ -693,7 +879,7 @@ Return Values:
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].FeatureField = 0;
*index = *index + 1;
- // read NCQ non-Data log
+ // Read NCQ non-Data log
if ((ChannelExtension->DeviceExtension->IdentifyDeviceData->SerialAtaCapabilities.NCQ == 1) &&
(ChannelExtension->DeviceExtension->IdentifyDeviceData->SerialAtaCapabilities.NcqQueueMgmt == 1)) {
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].Query = TRUE;
@@ -706,7 +892,7 @@ Return Values:
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].FeatureField = 0;
*index = *index + 1;
- // read NCQ Send Receive log
+ // Read NCQ Send Receive log
if ((ChannelExtension->DeviceExtension->IdentifyDeviceData->SerialAtaCapabilities.NCQ == 1) &&
(ChannelExtension->DeviceExtension->IdentifyDeviceData->SerialAtaCapabilities.NcqReceiveSend == 1)) {
ChannelExtension->DeviceExtension->QueryLogPages.LogPage[*index].Query = TRUE;
@@ -788,18 +974,20 @@ Return Values:
Srb->SrbStatus = SRB_STATUS_PENDING;
srbExtension->DataBuffer = DataBuffer;
+ if ( PhysicalAddress ) {
+ srbExtension->DataBufferPhysicalAddress.QuadPart = PhysicalAddress->QuadPart;
+ }
//setup SGL
if ( PhysicalAddress ) {
srbExtension->LocalSgl.NumberOfElements = 1;
srbExtension->LocalSgl.List[0].PhysicalAddress.LowPart = PhysicalAddress->LowPart;
srbExtension->LocalSgl.List[0].PhysicalAddress.HighPart = PhysicalAddress->HighPart;
- srbExtension->LocalSgl.List[0].Length = ATA_BLOCK_SIZE * BlockCount;
+ srbExtension->LocalSgl.List[0].Length = ATA_BLOCK_SIZE * (ULONG)BlockCount;
srbExtension->Sgl = &srbExtension->LocalSgl;
- srbExtension->DataTransferLength = ATA_BLOCK_SIZE * BlockCount;
+ srbExtension->DataTransferLength = ATA_BLOCK_SIZE * (ULONG)BlockCount;
}
-
return;
}
@@ -845,15 +1033,15 @@ ReadQueryLogPage (
)
{
IssueReadLogExtCommand( ChannelExtension,
- Srb,
- ChannelExtension->DeviceExtension->QueryLogPages.LogPage[Index].LogAddress,
- ChannelExtension->DeviceExtension->QueryLogPages.LogPage[Index].PageNumber,
- ChannelExtension->DeviceExtension->QueryLogPages.LogPage[Index].BlockCount,
- ChannelExtension->DeviceExtension->QueryLogPages.LogPage[Index].FeatureField,
- &ChannelExtension->DeviceExtension->ReadLogExtPageDataPhysicalAddress,
- (PVOID)ChannelExtension->DeviceExtension->ReadLogExtPageData,
- LogPageDiscoveryCompletion
- );
+ Srb,
+ ChannelExtension->DeviceExtension->QueryLogPages.LogPage[Index].LogAddress,
+ ChannelExtension->DeviceExtension->QueryLogPages.LogPage[Index].PageNumber,
+ ChannelExtension->DeviceExtension->QueryLogPages.LogPage[Index].BlockCount,
+ ChannelExtension->DeviceExtension->QueryLogPages.LogPage[Index].FeatureField,
+ &ChannelExtension->DeviceExtension->ReadLogExtPageDataPhysicalAddress,
+ (PVOID)ChannelExtension->DeviceExtension->ReadLogExtPageData,
+ LogPageDiscoveryCompletion
+ );
}
@@ -893,6 +1081,168 @@ Return Values:
return;
}
+VOID
+UpdateDownloadMicrocodeSupport(
+ _Inout_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_ PIDENTIFY_DEVICE_DATA_LOG_PAGE_SUPPORTED_CAPABILITIES Capabilities
+)
+/*++
+
+Routine Description:
+
+ Takes the given Supported Capabilities log page and updates the firmware
+ update (download microcode) support information that is cached in the given
+ Channel Extension.
+
+Arguments:
+
+ Channel Extension
+ Supported Capabilities
+
+--*/
+{
+ NT_ASSERT(Capabilities->Header.RevisionNumber == IDE_GP_LOG_VERSION);
+ NT_ASSERT(Capabilities->Header.PageNumber == IDE_GP_LOG_IDENTIFY_DEVICE_DATA_SUPPORTED_CAPABILITIES_PAGE);
+
+ //
+ // Set it to unsupported by default.
+ //
+ ChannelExtension->DeviceExtension->FirmwareUpdate.DmOffsetsDeferredSupported = 0;
+
+ //
+ // If the Download Microcode capabilites are valid then fill in our cached copy.
+ //
+ if (Capabilities->DownloadMicrocodeCapabilities.Valid == 1) {
+
+ if ((ChannelExtension->DeviceExtension->IdentifyDeviceData->AdditionalSupported.DownloadMicrocodeDmaSupported == 1) ||
+ (ChannelExtension->DeviceExtension->IdentifyDeviceData->CommandSetSupport.DownloadMicrocode == 1)) {
+
+ ChannelExtension->DeviceExtension->FirmwareUpdate.DmOffsetsDeferredSupported = (Capabilities->DownloadMicrocodeCapabilities.DmOffsetsDeferredSupported == 1);
+
+ if (ChannelExtension->DeviceExtension->FirmwareUpdate.DmOffsetsDeferredSupported) {
+
+ if ((Capabilities->DownloadMicrocodeCapabilities.DmMinTransferSize > 0) &&
+ (Capabilities->DownloadMicrocodeCapabilities.DmMinTransferSize < 0xFFFF)) {
+ ChannelExtension->DeviceExtension->FirmwareUpdate.DmMinTransferBlocks = (USHORT)min(Capabilities->DownloadMicrocodeCapabilities.DmMinTransferSize, AHCI_MAX_TRANSFER_LENGTH_DEFAULT / ATA_BLOCK_SIZE);
+ } else {
+ ChannelExtension->DeviceExtension->FirmwareUpdate.DmMinTransferBlocks = 1;
+ }
+
+ if ((Capabilities->DownloadMicrocodeCapabilities.DmMaxTransferSize > 0) &&
+ (Capabilities->DownloadMicrocodeCapabilities.DmMaxTransferSize < 0xFFFF)) {
+ ChannelExtension->DeviceExtension->FirmwareUpdate.DmMaxTransferBlocks = (USHORT)min(Capabilities->DownloadMicrocodeCapabilities.DmMaxTransferSize, AHCI_MAX_TRANSFER_LENGTH_DEFAULT / ATA_BLOCK_SIZE);
+ } else {
+ ChannelExtension->DeviceExtension->FirmwareUpdate.DmMaxTransferBlocks = AHCI_MAX_TRANSFER_LENGTH_DEFAULT / ATA_BLOCK_SIZE;
+ }
+ }
+ }
+ }
+}
+
+VOID
+GetDownloadMicrocodeSupportCompletion(
+ _Inout_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_ PSTORAGE_REQUEST_BLOCK Srb
+)
+/*++
+
+Routine Description:
+
+ Called when the Supported Capabilities log page has been obtained from the
+ device. The log page is parsed for the Download Microcode support and the
+ cached copy of this data is updated in the ChannelExtension.
+
+Arguments:
+
+ Channel Extension
+ SRB
+
+--*/
+{
+ PAHCI_SRB_EXTENSION srbExtension;
+
+ srbExtension = GetSrbExtension(Srb);
+
+ //
+ // If the request succeeded then update the cached copy of the Download
+ // Microcode support information.
+ //
+ if (Srb->SrbStatus == SRB_STATUS_SUCCESS) {
+ UpdateDownloadMicrocodeSupport(ChannelExtension, srbExtension->DataBuffer);
+ }
+
+ AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, IDE_GP_LOG_SECTOR_SIZE, srbExtension->DataBuffer, srbExtension->DataBufferPhysicalAddress);
+
+ //
+ // The SRB will be completed after this completion routine returns so
+ // there's no need to do it here.
+ //
+}
+
+ULONG
+GetDownloadMicrocodeSupport(
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_ PSTORAGE_REQUEST_BLOCK Srb
+)
+/*++
+Routine Description:
+
+ Queries the Download Microcode support from the Identify Log Page and
+ updates our cached copy of it.
+
+Arguments:
+ ChannelExtension
+ SRB
+
+Return Value:
+
+ Status code.
+
+--*/
+{
+ ULONG status = STOR_STATUS_SUCCESS;
+ PVOID buffer = NULL;
+ STOR_PHYSICAL_ADDRESS bufferPhysicalAddress = { 0 };
+
+ //
+ // Fail the request if it's not supported by device.
+ //
+ if (IsDeviceGeneralPurposeLoggingSupported(ChannelExtension) == FALSE) {
+ Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+ return STOR_STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Allocate DMA buffer to the log page.
+ //
+ status = AhciAllocateDmaBuffer((PVOID)ChannelExtension->AdapterExtension, IDE_GP_LOG_SECTOR_SIZE, (PVOID*)&buffer, &bufferPhysicalAddress);
+
+ if ((status != STOR_STATUS_SUCCESS) || (buffer == NULL)) {
+ if (buffer != NULL) {
+ AhciFreeDmaBuffer((PVOID)ChannelExtension->AdapterExtension, IDE_GP_LOG_SECTOR_SIZE, buffer, bufferPhysicalAddress);
+ }
+ Srb->SrbStatus = SRB_STATUS_ERROR;
+ return STOR_STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ AhciZeroMemory((PCHAR)buffer, IDE_GP_LOG_SECTOR_SIZE);
+
+ //
+ // Issue the command. The completion routine will update the cached
+ // firmware update information with the info from the log page.
+ // The completion routine will also free the DMA buffer.
+ //
+ IssueReadLogExtCommand(ChannelExtension,
+ Srb,
+ IDE_GP_LOG_IDENTIFY_DEVICE_DATA_ADDRESS,
+ IDE_GP_LOG_IDENTIFY_DEVICE_DATA_SUPPORTED_CAPABILITIES_PAGE,
+ 1,
+ 0, // feature field
+ &bufferPhysicalAddress,
+ buffer,
+ GetDownloadMicrocodeSupportCompletion);
+ return status;
+}
VOID
LogPageDiscoveryCompletion (
@@ -903,7 +1253,6 @@ LogPageDiscoveryCompletion (
This process is to discover all needed information from general log pages.
The process is initiated by reading log directory when Identify Device command completes.
-
*/
{
USHORT nextPageIndex = ATA_GPL_PAGES_INVALID_INDEX;
@@ -957,7 +1306,6 @@ LogPageDiscoveryCompletion (
ChannelExtension->DeviceExtension->SupportedGPLPages.SinglePage.HybridInfo = (ChannelExtension->DeviceExtension->ReadLogExtPageData[IDE_GP_LOG_HYBRID_INFO_ADDRESS] > 0) ? 1 : 0;
-
} else {
// Log Directory can be optional. Preset supportive info, they will be updated if the actual command fails later.
// In case of the disk doesn't support NCQ and doesn't support Log Directory, still try to discover some log pages.
@@ -1070,31 +1418,10 @@ LogPageDiscoveryCompletion (
// The value of revision number word shall be 0001h.
if ((supportedCapabilities->Header.RevisionNumber == IDE_GP_LOG_VERSION) &&
- (supportedCapabilities->Header.PageNumber == IDE_GP_LOG_IDENTIFY_DEVICE_DATA_SUPPORTED_CAPABILITIES_PAGE) &&
- (supportedCapabilities->DownloadMicrocodeCapabilities.Valid == 1)) {
+ (supportedCapabilities->Header.PageNumber == IDE_GP_LOG_IDENTIFY_DEVICE_DATA_SUPPORTED_CAPABILITIES_PAGE)) {
- if ((ChannelExtension->DeviceExtension->IdentifyDeviceData->AdditionalSupported.DownloadMicrocodeDmaSupported == 1) ||
- (ChannelExtension->DeviceExtension->IdentifyDeviceData->CommandSetSupport.DownloadMicrocode == 1)) {
-
- ChannelExtension->DeviceExtension->FirmwareUpdate.DmOffsetsDeferredSupported = (supportedCapabilities->DownloadMicrocodeCapabilities.DmOffsetsDeferredSupported == 1);
-
- if (ChannelExtension->DeviceExtension->FirmwareUpdate.DmOffsetsDeferredSupported) {
-
- if ((supportedCapabilities->DownloadMicrocodeCapabilities.DmMinTransferSize > 0) &&
- (supportedCapabilities->DownloadMicrocodeCapabilities.DmMinTransferSize < 0xFFFF)) {
- ChannelExtension->DeviceExtension->FirmwareUpdate.DmMinTransferBlocks = (USHORT)min(supportedCapabilities->DownloadMicrocodeCapabilities.DmMinTransferSize, AHCI_MAX_TRANSFER_LENGTH / ATA_BLOCK_SIZE);
- } else {
- ChannelExtension->DeviceExtension->FirmwareUpdate.DmMinTransferBlocks = 1;
- }
-
- if ((supportedCapabilities->DownloadMicrocodeCapabilities.DmMaxTransferSize > 0) &&
- (supportedCapabilities->DownloadMicrocodeCapabilities.DmMaxTransferSize < 0xFFFF)) {
- ChannelExtension->DeviceExtension->FirmwareUpdate.DmMaxTransferBlocks = (USHORT)min(supportedCapabilities->DownloadMicrocodeCapabilities.DmMaxTransferSize, AHCI_MAX_TRANSFER_LENGTH / ATA_BLOCK_SIZE);
- } else {
- ChannelExtension->DeviceExtension->FirmwareUpdate.DmMaxTransferBlocks = AHCI_MAX_TRANSFER_LENGTH / ATA_BLOCK_SIZE;
- }
- }
- }
+ UpdateDownloadMicrocodeSupport(ChannelExtension, supportedCapabilities);
+
}
} else {
@@ -1105,6 +1432,7 @@ LogPageDiscoveryCompletion (
// the issued command was for getting SATA log page of identify device data log
if (Srb->SrbStatus == SRB_STATUS_SUCCESS) {
+
} else {
ChannelExtension->DeviceExtension->SupportedGPLPages.IdentifyDeviceData.SATA = 0;
}
@@ -1153,7 +1481,11 @@ LogPageDiscoveryCompletion (
if (nextPageIndex != ATA_GPL_PAGES_INVALID_INDEX) {
ReadQueryLogPage(ChannelExtension, Srb, nextPageIndex);
} else {
+
ReportLunsComplete(ChannelExtension, Srb);
+
+ // Use a work itme to preserve information from Log Pages into registry.
+ PreserveLogPageInformation(ChannelExtension);
}
return;
@@ -1161,6 +1493,49 @@ LogPageDiscoveryCompletion (
VOID
+UpdateDeviceType(
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
+ )
+/*++
+
+Routine Description:
+
+ Update device type information after device enumeration.
+
+ Assumption - PxSIG is ready to be accessed.
+
+Arguments:
+
+ ChannelExtension
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PATA_DEVICE_PARAMETERS deviceParameters = &ChannelExtension->DeviceExtension->DeviceParameters;
+
+ // There is chance that during device enumeration, port is not started yet and signature register is 0xffffffff,
+ // which will result in the AtaDeviceType is set to DeviceUnknown.
+ // Update it here if above situation is true.
+ if (IsUnknownDevice(deviceParameters)) {
+
+ ULONG sig = 0;
+ sig = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SIG.AsUlong);
+
+ if (sig == ATA_DEVICE_SIGNATURE_ATA) {
+ ChannelExtension->DeviceExtension[0].DeviceParameters.AtaDeviceType = DeviceIsAta;
+ } else if (sig == ATA_DEVICE_SIGNATURE_ATAPI) {
+ ChannelExtension->DeviceExtension[0].DeviceParameters.AtaDeviceType = DeviceIsAtapi;
+ } else {
+ NT_ASSERT(FALSE);
+ }
+ }
+}
+
+
+VOID
AhciPortIdentifyDevice(
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
_In_ PSTORAGE_REQUEST_BLOCK Srb
@@ -1175,18 +1550,16 @@ AhciPortIdentifyDevice(
return;
}
- if (Srb->SrbStatus == SRB_STATUS_SUCCESS) {
- if (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_ATAPI_IDENTIFY) {
- ChannelExtension->DeviceExtension->DeviceParameters.AtaDeviceType = DeviceIsAtapi;
- } else {
- ChannelExtension->DeviceExtension->DeviceParameters.AtaDeviceType = DeviceIsAta;
- }
- } else if (Srb->SrbStatus == SRB_STATUS_NO_DEVICE) {
+ if (Srb->SrbStatus == SRB_STATUS_NO_DEVICE) {
// command failed consider as no device
ChannelExtension->DeviceExtension->DeviceParameters.AtaDeviceType = DeviceNotExist;
}
if (Srb->SrbStatus == SRB_STATUS_SUCCESS) {
+
+ // Update device ata type if it isn't initialized correctly.
+ UpdateDeviceType(ChannelExtension);
+
//Re-initialize device specific information to avoid the values being reused after device switched.
ChannelExtension->StateFlags.NCQ_Activated = 0;
ChannelExtension->StateFlags.NCQ_Succeeded = 0;
@@ -1201,7 +1574,6 @@ AhciPortIdentifyDevice(
// identify completes, digest identify data / inquiry data
UpdateDeviceParameters(ChannelExtension);
-
//
// Cache if PUIS is enabled or not. We'll look at this later when
// powering up the port to determine if we need to send the spin up
@@ -1212,34 +1584,85 @@ AhciPortIdentifyDevice(
// Initialize port properties
ChannelExtension->PortProperties = 0;
+ if (ChannelExtension->StateFlags.IdentifyDeviceSuccess == 0) {
+ ChannelExtension->StateFlags.IdentifyDeviceSuccess = 1;
+ }
+
if (IsExternalPort(ChannelExtension)) {
SETMASK(ChannelExtension->PortProperties, PORT_PROPERTIES_EXTERNAL_PORT);
}
}
// Identify Device can only be triggered from REPORT LUNS command or
- // INQUIRY command (for disk in dump environment)
+ // INQUIRY command (for disk in dump environment)
if ((cdb != NULL) && (cdb->CDB10.OperationCode == SCSIOP_REPORT_LUNS)) {
- if ( (Srb->SrbStatus == SRB_STATUS_SUCCESS) &&
- IsDeviceGeneralPurposeLoggingSupported(ChannelExtension) ) {
+ BOOLEAN cachedLogPageInfoUsable = FALSE;
+
+ if ((Srb->SrbStatus == SRB_STATUS_SUCCESS) &&
+ IsDeviceGeneralPurposeLoggingSupported(ChannelExtension)) {
- // READ LOG EXT command is supported.
- USHORT index;
+ ULONG storStatus;
- InitQueryLogPages(ChannelExtension);
+ //
+ // Check to determine whether use cached device settings.
+ //
+ storStatus = StorPortIsDeviceOperationAllowed(ChannelExtension->AdapterExtension,
+ NULL,
+ &STORPORT_DEVICEOPERATION_CACHED_SETTINGS_INIT_GUID,
+ (PULONG)(&cachedLogPageInfoUsable));
+
+ cachedLogPageInfoUsable = (cachedLogPageInfoUsable && (ChannelExtension->DeviceExtension[0].UpdateCachedLogPageInfo == FALSE));
+
+ if (cachedLogPageInfoUsable) {
+ // In case this is not a newly plugged in device and it's allowed to use cached Log Page Information.
+ CHAR valueName[16] = { 0 };
+ AHCI_DEVICE_LOG_PAGE_INFO logPageInfo = { 0 };
+ PVOID dataBuffer = &logPageInfo;
+ ULONG dataLength = sizeof(AHCI_DEVICE_LOG_PAGE_INFO);
+
+ GetLogInfoRegValueName(ChannelExtension, valueName, sizeof(valueName));
- index = GetNextQueryLogPageIndex(ChannelExtension);
+ storStatus = StorPortRegistryReadAdapterKey(ChannelExtension->AdapterExtension,
+ (PUCHAR)"StorAHCI",
+ (PUCHAR)valueName,
+ MINIPORT_REG_BINARY,
+ &dataBuffer,
+ &dataLength);
- NT_ASSERT(index == 0);
+ if ((storStatus == STOR_STATUS_SUCCESS) && (dataLength == sizeof(AHCI_DEVICE_LOG_PAGE_INFO))) {
- if (index != ATA_GPL_PAGES_INVALID_INDEX) {
- //First page should be log directory. Read it to get pages supported by device.
- ReadQueryLogPage(ChannelExtension, Srb, index);
- } else {
- ReportLunsComplete(ChannelExtension, Srb);
+ StorPortCopyMemory((PVOID)&ChannelExtension->DeviceExtension[0].QueryLogPages, &logPageInfo.QueryLogPages, sizeof(ATA_GPL_PAGES_TO_QUERY));
+ StorPortCopyMemory((PVOID)&ChannelExtension->DeviceExtension[0].SupportedGPLPages, &logPageInfo.SupportedGPLPages, sizeof(ATA_SUPPORTED_GPL_PAGES));
+ StorPortCopyMemory((PVOID)&ChannelExtension->DeviceExtension[0].SupportedCommands, &logPageInfo.SupportedCommands, sizeof(ATA_COMMAND_SUPPORTED));
+ StorPortCopyMemory((PVOID)&ChannelExtension->DeviceExtension[0].FirmwareUpdate, &logPageInfo.FirmwareUpdate, sizeof(DOWNLOAD_MICROCODE_CAPABILITIES));
+
+ ReportLunsComplete(ChannelExtension, Srb);
+ } else {
+ cachedLogPageInfoUsable = FALSE;
+ }
}
+ //
+ // Start log page discovery process if decide not use cached log page data.
+ //
+ if (!cachedLogPageInfoUsable) {
+
+ USHORT index;
+
+ InitQueryLogPages(ChannelExtension);
+
+ index = GetNextQueryLogPageIndex(ChannelExtension);
+
+ NT_ASSERT(index == 0);
+
+ if (index != ATA_GPL_PAGES_INVALID_INDEX) {
+ // First page should be log directory. Read it to get pages supported by device.
+ ReadQueryLogPage(ChannelExtension, Srb, index);
+ } else {
+ ReportLunsComplete(ChannelExtension, Srb);
+ }
+ }
} else {
ReportLunsComplete(ChannelExtension, Srb);
}
@@ -1267,7 +1690,28 @@ AhciPortIdentifyDevice(
} else {
InquiryComplete(ChannelExtension, Srb);
}
+ } else if ((ChannelExtension->DeviceExtension->DeviceParameters.StateFlags.NeedUpdateIdentifyDeviceData == 1) &&
+ (cdb != NULL) && (cdb->CDB10.OperationCode == SCSIOP_INQUIRY)) {
+
+ //
+ // We are refreshing Identify information because of a firmware update.
+ // The firmware update support information is contained in the Supported
+ // Capabilities log page so we need to make sure we query that page as well.
+ //
+ ChannelExtension->DeviceExtension->DeviceParameters.StateFlags.NeedUpdateIdentifyDeviceData = 0;
+
+ //
+ // Finish processing the Inquiry command before re-using the SRB to get
+ // the Supported Capabilities log page.
+ //
+ InquiryComplete(ChannelExtension, Srb);
+
+ if (IsDeviceGeneralPurposeLoggingSupported(ChannelExtension)) {
+ GetDownloadMicrocodeSupport(ChannelExtension, Srb);
+ }
+
}
+
return;
}
@@ -1317,7 +1761,7 @@ AhciPortNVCacheCompletion(
//
// Free the buffer allocated as mode sense info buffer , holding task file
//
- AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, srbExtension->ResultBufferLength, TaskFile);
+ AhciFreeDmaBuffer(ChannelExtension->AdapterExtension, srbExtension->ResultBufferLength, TaskFile, srbExtension->ResultBufferPhysicalAddress);
} else {
// in case TaskFile is not returned in SenseInfoBuffer, use cached ATA Status and Error register values.
@@ -1408,7 +1852,7 @@ Affected Variables/Registers:
srb->SrbExtension = (PVOID)ChannelExtension->Local.SrbExtension;
srb->TimeOutValue = 1; //as it's sent by miniport, no one monitors the timeout value.
- // Fills in the local SRB with the SetFeatures command
+ // Fills in the local SRB with the SetFeatures command
srbExtension = ChannelExtension->Local.SrbExtension;
AhciZeroMemory((PCHAR)srbExtension, sizeof(AHCI_SRB_EXTENSION));
@@ -1448,21 +1892,25 @@ Affected Variables/Registers:
none
--*/
{
- UCHAR i;
- ULONG allocated;
- ATA_TASK_FILE taskFile = {0};
+ UCHAR i;
+ ULONG allocated;
+ ATA_TASK_FILE taskFile = {0};
UNREFERENCED_PARAMETER(Srb);
- //1 Verify local SRB is not in use
+ RecordExecutionHistory(ChannelExtension, 0x00000043); // IssuePreservedSettingCommands
+
+ //1 Verify local SRB is not in use
allocated = GetOccupiedSlots(ChannelExtension);
if ((allocated & (1 << 0)) > 0) {
+
// Already restoring preserved Settings
+ RecordExecutionHistory(ChannelExtension, 0x10010043); // IssuePreservedSettingCommands Slot 0 in use
return;
}
- //2 find the next command to send
+ //2 find the next command to send
for (i = 0; i < MAX_SETTINGS_PRESERVED; i++) {
if ( (ChannelExtension->PersistentSettings.SlotsToSend & (1 << i)) > 0 ) {
ChannelExtension->PersistentSettings.SlotsToSend &= ~(1 << i);
@@ -1470,20 +1918,23 @@ Affected Variables/Registers:
}
}
- //perhaps there is none. Done.
+ // Perhaps there is none. Done.
if ( i >= MAX_SETTINGS_PRESERVED) {
- // release active reference for process of restore preserved settings
+ // Release active reference for process of restore preserved settings
if (ChannelExtension->StateFlags.RestorePreservedSettingsActiveReferenced == 1) {
PortReleaseActiveReference(ChannelExtension, NULL);
ChannelExtension->StateFlags.RestorePreservedSettingsActiveReferenced = 0;
}
- InterlockedBitTestAndReset((LONG*)&ChannelExtension->StateFlags, 3); //ReservedSlotInUse field is at bit 3
+ RecordExecutionHistory(ChannelExtension, 0x10020043); // IssuePreservedSettingCommands done and clear flag
+
+ InterlockedBitTestAndReset((LONG*)&ChannelExtension->StateFlags, 3); //ReservedSlotInUse field is at bit 3
+ InterlockedBitTestAndReset((LONG*)&ChannelExtension->StateFlags, 22); //PowerUpInitializationInProgress field is at bit 22
return;
}
- //3 Otherwise use the LocalSRB to send the command. When it is done, call this routine again
+ //3 Otherwise use the LocalSRB to send the command. When it is done, call this routine again
taskFile.Current.bFeaturesReg = ChannelExtension->PersistentSettings.CommandParams[i].Features;
taskFile.Current.bSectorCountReg = ChannelExtension->PersistentSettings.CommandParams[i].SectorCount;
taskFile.Current.bDriveHeadReg = 0xA0;
@@ -1521,22 +1972,29 @@ Affected Variables/Registers:
UNREFERENCED_PARAMETER(Srb);
- // Verify local SRB is not in use
+ RecordExecutionHistory(ChannelExtension, 0x00000044); // IssueInitCommands
+
+ // Verify local SRB is not in use
allocated = GetOccupiedSlots(ChannelExtension);
if ((allocated & (1 << 0)) > 0) {
+
// Already restoring preserved Settings
+ RecordExecutionHistory(ChannelExtension, 0x10010044); // IssueInitCommands slot 0 in use
return;
}
- // if all Init commands have been sent, send Preserved Setting Commands
+ // if all Init commands have been sent, send Preserved Setting Commands
if (ChannelExtension->DeviceInitCommands.CommandToSend >= ChannelExtension->DeviceInitCommands.ValidCommandCount) {
+
+ RecordExecutionHistory(ChannelExtension, 0x10020044); // IssueInitCommands init commands done, send Preserved Setting Commands
+
ChannelExtension->PersistentSettings.SlotsToSend = ChannelExtension->PersistentSettings.Slots;
IssuePreservedSettingCommands(ChannelExtension, NULL);
return;
}
- // find the next command to send
+ // find the next command to send
taskFile = ChannelExtension->DeviceInitCommands.CommandTaskFile + ChannelExtension->DeviceInitCommands.CommandToSend;
taskFile->Current.bDriveHeadReg = 0xA0;
@@ -1824,7 +2282,6 @@ SetAllowedLpmStates(
lpm = 0x03;
}
-
//Set PxSCTL.IPM to 3h to restrict slumber and partial interface power management state transitions.
sctl.AsUlong = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SCTL.AsUlong);
sctl.IPM = lpm;
@@ -1846,14 +2303,16 @@ Return Value:
*/
{
AHCI_COMMAND cmd;
- BOOLEAN needStartIo = FALSE;
+ BOOLEAN needStartIo = FALSE;
+ UCHAR sctlIpm = 0;
+
+ RecordExecutionHistory(ChannelExtension, 0x00000047); // AhciLpmSettingsModes
//Make sure the configuration supports LPM, otherwise, don't touch anything.
if (NoLpmSupport(ChannelExtension) || !IsLPMCapablePort(ChannelExtension)) {
return needStartIo;
}
-
ChannelExtension->LastUserLpmPowerSetting = (UCHAR)LpmMode.AsUlong;
if (LpmMode.AsUlong == 0) {
@@ -1869,7 +2328,7 @@ Return Value:
}
//Set PxSCTL.IPM to 3h to restrict slumber and partial interface power management state transitions.
- SetAllowedLpmStates(ChannelExtension);
+ sctlIpm = SetAllowedLpmStates(ChannelExtension);
// Disable DIPM
if (IsDeviceSupportsDIPM(ChannelExtension->DeviceExtension[0].IdentifyDeviceData)) {
@@ -1890,7 +2349,7 @@ Return Value:
// link power management is allowed.
//Set PxSCTL.IPM for LPM allowed states.
- UCHAR sctlIpm = SetAllowedLpmStates(ChannelExtension);
+ sctlIpm = SetAllowedLpmStates(ChannelExtension);
// Setting HIPM if it's enabled.
if ( (LpmMode.HipmEnabled > 0) &&
@@ -1954,6 +2413,18 @@ Return Value:
}
+ ++(ChannelExtension->TotalCountPowerSettingNotification);
+ AhciTelemetryLogPowerSettingChange(ChannelExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciTelemetryEventIdLpmSettingsModes,
+ "AhciLpmSettingsModes",
+ 0,
+ sctlIpm,
+ LpmMode.AsUlong
+ );
+
+ RecordExecutionHistory(ChannelExtension, 0x10000047); // AhciLpmSettingsModes Exit
+
return needStartIo;
}
@@ -1963,7 +2434,7 @@ AhciPortPowerSettingNotification(
IN PAHCI_CHANNEL_EXTENSION ChannelExtension,
IN PSTOR_POWER_SETTING_INFO PowerInfo
)
-{
+{
// do nothing if there is no device connected
if ( (ChannelExtension->StartState.ChannelNextStartState == StartFailed) ||
(ChannelExtension->DeviceExtension->DeviceParameters.AtaDeviceType == DeviceNotExist) ) {
@@ -1991,10 +2462,22 @@ AhciPortPowerSettingNotification(
ULONG interval = (ULONG)*((PULONG)PowerInfo->Value);
if (interval <= 300000) {
+ UCHAR sctlIpm = 0;
+
ChannelExtension->AutoPartialToSlumberInterval = interval;
//Set PxSCTL.IPM register for LPM allowed states.
- SetAllowedLpmStates(ChannelExtension);
+ sctlIpm = SetAllowedLpmStates(ChannelExtension);
+
+ ++(ChannelExtension->TotalCountPowerSettingNotification);
+ AhciTelemetryLogPowerSettingChange(ChannelExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ AhciTelemetryEventIdLpmAdaptiveSetting,
+ "LpmAdaptiveSetting",
+ 0,
+ sctlIpm,
+ ChannelExtension->AutoPartialToSlumberInterval
+ );
}
} else if (IsLpmModeSetting(PowerInfo)) {
@@ -2184,7 +2667,6 @@ AhciPortGetInitCommands(
// send SECURE_FREEZE_LOCK by default
BOOLEAN sendSecureFreezeLock = TRUE;
-
// clear Init Commands area. need to do this for device removed previously (StorAHCI only knows about adapter removal, not device removal)
ChannelExtension->DeviceInitCommands.CommandCount = 0;
ChannelExtension->DeviceInitCommands.ValidCommandCount = 0;
@@ -2258,7 +2740,6 @@ AhciPortGetInitCommands(
// Get Init Command count for devices
-
//
// calculate possible command count for memory allocation
// an IDE_FEATURE_DISABLE_REVERT_TO_POWER_ON command will be sent to device anyway.
@@ -2529,6 +3010,7 @@ AhciAdapterEvaluateDSMMethod(
AdapterExtension->StateFlags.SupportsAcpiDSM = TRUE;
}
+
}
Exit:
@@ -2639,4 +3121,3 @@ Exit:
#pragma warning(pop) // un-sets any local warning changes
-
diff --git a/storage/miniports/storahci/src/pnppower.h b/storage/miniports/storahci/src/pnppower.h
index 366c6bb5..ad5e1253 100644
--- a/storage/miniports/storahci/src/pnppower.h
+++ b/storage/miniports/storahci/src/pnppower.h
@@ -41,6 +41,8 @@ Revision History:
#define ACPI_METHOD_DSM_LINKPOWER_REMOVE_POWER 0x00
#define ACPI_METHOD_DSM_LINKPOWER_APPLY_POWER 0x01
+#define AHCI_DEVICE_IO_COALESCING_IDLE_TIMEOUT_MS (1000) // 1s by default
+
//
// When waiting for the link to change power states, don't wait more
// than 100 microseconds.
@@ -130,7 +132,6 @@ AhciPortAcpiDSMControl(
_In_ BOOLEAN Sleep
);
-
VOID
IssuePreservedSettingCommands(
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
@@ -178,4 +179,3 @@ AhciLpmSettingsModes(
#pragma warning(default:4214)
#pragma warning(default:4201)
#endif
-
diff --git a/storage/miniports/storahci/src/util.c b/storage/miniports/storahci/src/util.c
index e7ed0cba..b95c682c 100644
--- a/storage/miniports/storahci/src/util.c
+++ b/storage/miniports/storahci/src/util.c
@@ -1,4 +1,4 @@
-/*++
+/*++
Copyright (C) Microsoft Corporation, 2009
@@ -55,14 +55,23 @@ ReturnValue:
abar = NULL;
- // loop over resource entries
+ // loop over resource entries
if (ConfigInfo->NumberOfAccessRanges > 0) {
for (i = 0; i < ConfigInfo->NumberOfAccessRanges; i++) {
-#if defined (_ARM_) || defined (_ARM64_)
- if ((*(ConfigInfo->AccessRanges))[i].RangeStart.QuadPart != 0) {
-#else
- if ((*(ConfigInfo->AccessRanges))[i].RangeStart.QuadPart == AdapterExtension->AhciBaseAddress) {
-#endif
+ BOOLEAN bAccessRangeFound = FALSE;
+
+ // Test to see if this is the needed resource entry, depending on the interface type
+ if (ConfigInfo->AdapterInterfaceType == PCIBus) {
+ if ((*(ConfigInfo->AccessRanges))[i].RangeStart.QuadPart == AdapterExtension->AhciBaseAddress) {
+ bAccessRangeFound = TRUE;
+ }
+ } else {
+ if ((*(ConfigInfo->AccessRanges))[i].RangeStart.QuadPart != 0) {
+ bAccessRangeFound = TRUE;
+ }
+ }
+
+ if (bAccessRangeFound) {
abar = (PAHCI_MEMORY_REGISTERS)StorPortGetDeviceBase(AdapterExtension,
ConfigInfo->AdapterInterfaceType,
ConfigInfo->SystemIoBusNumber,
@@ -104,9 +113,11 @@ Return Value:
none
--*/
{
- int i;
+ if (ChannelExtension->ExecutionHistory == NULL) {
+ return;
+ }
- //1.1 Select the next available index
+ //1.1 Select the next available index
// Actually, ExecutionHistoryNextAvailableIndex is used for current index.
if (ChannelExtension->ExecutionHistoryNextAvailableIndex >= (MAX_EXECUTION_HISTORY_ENTRY_COUNT - 1)) {
ChannelExtension->ExecutionHistoryNextAvailableIndex = 0;
@@ -114,10 +125,12 @@ Return Value:
ChannelExtension->ExecutionHistoryNextAvailableIndex++;
}
- //2.1 Copy over the Channel Extension header
+ StorPortQuerySystemTime(&(ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].TimeStamp));
+
+ //2.1 Copy over the Channel Extension header
ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Function = Function;
- if(ChannelExtension->AdapterExtension->IS) {
+ if (ChannelExtension->AdapterExtension->IS) {
// Keep using the old field "IS" to save StateFlags information.
StorPortCopyMemory(&ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].IS, &ChannelExtension->StateFlags, sizeof(ULONG));
} else {
@@ -126,8 +139,8 @@ Return Value:
StorPortCopyMemory(&ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].SlotManager, &ChannelExtension->SlotManager, sizeof(SLOT_MANAGER));
- //2.2 Copy over the AHCI registers
- if(ChannelExtension->Px) {
+ //2.2 Copy over the AHCI registers
+ if (ChannelExtension->Px) {
ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[0] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->CLB.AsUlong);
ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[1] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->CLBU);
ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[2] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->FB.AsUlong);
@@ -149,7 +162,7 @@ Return Value:
ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[15] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SNTF.AsUlong);
} else {
- for(i=0; i<0x10; i++) {
+ for(int i = 0; i < 0x10; i++) {
ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[i] = (ULONG)~0;
}
}
@@ -178,7 +191,11 @@ Return Value:
none
--*/
{
- //1. Select the next available index
+ if (ChannelExtension->ExecutionHistory == NULL) {
+ return;
+ }
+
+ //1. Select the next available index
// Actually, ExecutionHistoryNextAvailableIndex is used for current index.
if (ChannelExtension->ExecutionHistoryNextAvailableIndex >= (MAX_EXECUTION_HISTORY_ENTRY_COUNT - 1)) {
ChannelExtension->ExecutionHistoryNextAvailableIndex = 0;
@@ -186,7 +203,9 @@ Return Value:
ChannelExtension->ExecutionHistoryNextAvailableIndex++;
}
- //2. Copy data
+ StorPortQuerySystemTime(&(ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].TimeStamp));
+
+ //2. Copy data
ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Function = Function;
if (ChannelExtension->AdapterExtension->IS) {
@@ -223,22 +242,22 @@ Called by:
PAHCI_ADAPTER_EXTENSION adapterExtension = ChannelExtension->AdapterExtension;
ie.AsUlong = StorPortReadRegisterUlong(adapterExtension, &IE->AsUlong);
- ie.DHRE = 1; //Device to Host Register FIS Interrupt (DHRS): A D2H Register FIS has been received with the �I� bit set, and has been copied into system memory.
- ie.PSE = 1; //PIO Setup FIS Interrupt (PSS): A PIO Setup FIS has been received with the �I� bit set, it has been copied into system memory, and the data related to that FIS has been transferred. This bit shall be set even if the data transfer resulted in an error.
- ie.DSE = 1; //DMA Setup FIS Interrupt (DSS): A DMA Setup FIS has been received with the �I� bit set and has been copied into system memory.
- ie.SDBE = 1; //Set Device Bits Interrupt (SDBS): A Set Device Bits FIS has been received with the �I� bit set and has been copied into system memory.
+ ie.DHRE = 1; //Device to Host Register FIS Interrupt (DHRS): A D2H Register FIS has been received with the �I� bit set, and has been copied into system memory.
+ ie.PSE = 1; //PIO Setup FIS Interrupt (PSS): A PIO Setup FIS has been received with the �I� bit set, it has been copied into system memory, and the data related to that FIS has been transferred. This bit shall be set even if the data transfer resulted in an error.
+ ie.DSE = 1; //DMA Setup FIS Interrupt (DSS): A DMA Setup FIS has been received with the �I� bit set and has been copied into system memory.
+ ie.SDBE = 1; //Set Device Bits Interrupt (SDBS): A Set Device Bits FIS has been received with the �I� bit set and has been copied into system memory.
- ie.UFE = 0; //Unknown FIS Interrupt (UFS): When set to �1�, indicates that an unknown FIS was received and has been copied into system memory. This bit is cleared to �0� by software clearing the PxSERR.DIAG.F bit to �0�. Note that this bit does not directly reflect the PxSERR.DIAG.F bit. PxSERR.DIAG.F is set immediately when an unknown FIS is detected, whereas this bit is set when that FIS is posted to memory. Software should wait to act on an unknown FIS until this bit is set to �1� or the two bits may become out of sync.
- ie.DPE = 0; //Descriptor Processed (DPS): A PRD with the �I� bit set has transferred all of its data. Refer to section 5.4.2.
+ ie.UFE = 0; //Unknown FIS Interrupt (UFS): When set to �1�, indicates that an unknown FIS was received and has been copied into system memory. This bit is cleared to �0� by software clearing the PxSERR.DIAG.F bit to �0�. Note that this bit does not directly reflect the PxSERR.DIAG.F bit. PxSERR.DIAG.F is set immediately when an unknown FIS is detected, whereas this bit is set when that FIS is posted to memory. Software should wait to act on an unknown FIS until this bit is set to �1� or the two bits may become out of sync.
+ ie.DPE = 0; //Descriptor Processed (DPS): A PRD with the �I� bit set has transferred all of its data. Refer to section 5.4.2.
ie.PCE = 1; //Port Connect Change Status (PCS): 1=Change in Current Connect Status. 0=No change in Current Connect Status. This bit reflects the state of PxSERR.DIAG.X. This bit is only cleared when PxSERR.DIAG.X is cleared.
if(adapterExtension->CAP.SMPS) {
- ie.DMPE = 1; //Device Mechanical Presence Status (DMPS): When set, indicates that a mechanical presence switch attached to this port has been opened or closed, which may lead to a change in the connection state of the device. This bit is only valid if both CAP.SMPS and P0CMD.MPSP are set to �1�.
+ ie.DMPE = 1; //Device Mechanical Presence Status (DMPS): When set, indicates that a mechanical presence switch attached to this port has been opened or closed, which may lead to a change in the connection state of the device. This bit is only valid if both CAP.SMPS and P0CMD.MPSP are set to �1�.
} else {
ie.DMPE = 0;
}
//Reserved :14;
- ie.PRCE = 1; //PhyRdy Change Status (PRCS): When set to �1� indicates the internal PhyRdy signal changed state. This bit reflects the state of P0SERR.DIAG.N. To clear this bit, software must clear P0SERR.DIAG.N to �0�.
+ ie.PRCE = 1; //PhyRdy Change Status (PRCS): When set to �1� indicates the internal PhyRdy signal changed state. This bit reflects the state of P0SERR.DIAG.N. To clear this bit, software must clear P0SERR.DIAG.N to �0�.
ie.IPME = 0; //Incorrect Port Multiplier Status (IPMS): Indicates that the HBA received a FIS from a device whose Port Multiplier field did not match what was expected. The IPMS bit may be set during enumeration of devices on a Port Multiplier due to the normal Port Multiplier enumeration process. It is recommended that IPMS only be used after enumeration is complete on the Port Multiplier.
ie.OFE = 1; //Overflow Status (OFS): Indicates that the HBA received more bytes from a device than was specified in the PRD table for the command.
@@ -250,8 +269,8 @@ Called by:
ie.HBFE = 1; //Host Bus Fatal Error Status (HBFS): Indicates that the HBA encountered a host bus error that it cannot recover from, such as a bad software pointer. In PCI, such an indication would be a target or master abort.
ie.TFEE = 1; //Task File Error Status (TFES): This bit is set whenever the status register is updated by the device and the error bit (bit 0) is set.
cmd.AsUlong = StorPortReadRegisterUlong(adapterExtension, &ChannelExtension->Px->CMD.AsUlong);
- if(cmd.CPD) { //check for PxCMD.CPD set to �1� before setting CPDE
- ie.CPDE = 1; //Cold Port Detect Status (CPDS): When set, a device status has changed as detected by the cold presence detect logic. This bit can either be set due to a non-connected port receiving a device, or a connected port having its device removed. This bit is only valid if the port supports cold presence detect as indicated by PxCMD.CPD set to �1�.
+ if(cmd.CPD) { //check for PxCMD.CPD set to �1� before setting CPDE
+ ie.CPDE = 1; //Cold Port Detect Status (CPDS): When set, a device status has changed as detected by the cold presence detect logic. This bit can either be set due to a non-connected port receiving a device, or a connected port having its device removed. This bit is only valid if the port supports cold presence detect as indicated by PxCMD.CPD set to �1�.
} else {
ie.CPDE = 0;
}
@@ -451,7 +470,6 @@ Return Value:
return matches;
}
-
VOID
AhciBusChangeCallback(
_In_ PVOID AdapterExtension,
@@ -494,38 +512,41 @@ PortBusChangeProcess (
)
{
AHCI_SERIAL_ATA_CONTROL sctl;
- STOR_LOCK_HANDLE lockhandle = {InterruptLock, 0};
- ULONG status = STOR_STATUS_UNSUCCESSFUL;
+ STOR_LOCK_HANDLE lockhandle = { InterruptLock, 0 };
+ ULONG status = STOR_STATUS_UNSUCCESSFUL;
- //1 if link speed was limited, restore the supported value.
+ // 1 if link speed was limited, restore the supported value.
sctl.AsUlong = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SCTL.AsUlong);
- if ( (sctl.SPD != 0) &&
- (sctl.SPD != ChannelExtension->AdapterExtension->CAP.ISS) ) {
+ if ((sctl.SPD != 0) &&
+ (sctl.SPD != ChannelExtension->AdapterExtension->CAP.ISS)) {
sctl.SPD = 0; //AHCI 3.3.11 --- 0h No speed negotiation restrictions
StorPortWriteRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SCTL.AsUlong, sctl.AsUlong);
}
- //2 Kicks off the Start Channel state machine
+ // 2 Kicks off the Start Channel state machine
AhciInterruptSpinlockAcquire(ChannelExtension->AdapterExtension, ChannelExtension->PortNumber, &lockhandle);
AhciPortReset(ChannelExtension, TRUE); // all requests should be completed
AhciInterruptSpinlockRelease(ChannelExtension->AdapterExtension, ChannelExtension->PortNumber, &lockhandle);
- //3 Requests rescan on this port. Using STATE_CHANGE_TARGET to make sure a REPORT LUNS command coming from Storport.
+ // Mark that cached Log Page information need to be updated.
+ ChannelExtension->DeviceExtension[0].UpdateCachedLogPageInfo = TRUE;
+
+ // 3 Requests rescan on this port. Using STATE_CHANGE_TARGET to make sure a REPORT LUNS command coming from Storport.
status = StorPortStateChangeDetected(ChannelExtension->AdapterExtension,
- STATE_CHANGE_TARGET,
- (PSTOR_ADDRESS)&ChannelExtension->DeviceExtension[0].DeviceAddress,
- 0,
- AhciBusChangeCallback,
- NULL);
+ STATE_CHANGE_TARGET,
+ (PSTOR_ADDRESS)&ChannelExtension->DeviceExtension[0].DeviceAddress,
+ 0,
+ AhciBusChangeCallback,
+ NULL);
- // if the state change notification fails, set a timer to retry the notification after a delay
+ // If the state change notification fails, set a timer to retry the notification after a delay
if (status == STOR_STATUS_UNSUCCESSFUL) {
if (ChannelExtension->BusChangeTimer == NULL) {
-
StorPortInitializeTimer(ChannelExtension->AdapterExtension, &ChannelExtension->BusChangeTimer);
}
+
status = StorPortRequestTimer(ChannelExtension->AdapterExtension,
ChannelExtension->BusChangeTimer,
AhciBusChangeTimerCallback,
@@ -533,22 +554,19 @@ PortBusChangeProcess (
100000, // 100 milliseconds
0);
- if ( status != STOR_STATUS_SUCCESS ) {
+ if (status != STOR_STATUS_SUCCESS) {
PortReleaseActiveReference(ChannelExtension, NULL);
}
-
} else {
if (ChannelExtension->BusChangeTimer != NULL) {
StorPortFreeTimer(ChannelExtension->AdapterExtension, ChannelExtension->BusChangeTimer);
ChannelExtension->BusChangeTimer = NULL;
- }
-
+ }
+
PortReleaseActiveReference(ChannelExtension, NULL);
-
}
-
}
VOID
@@ -676,6 +694,7 @@ Affected Variables/Registers:
PSTORAGE_REQUEST_BLOCK srbToRelease;
BOOLEAN isSenseSrb;
BOOLEAN retrySrb = FALSE;
+ BOOLEAN isReadLogExtSrbIssuedInNCQErrorRecovery = FALSE;
slotContent = &ChannelExtension->Slot[SlotNumber];
if (slotContent->Srb == NULL) {
@@ -685,6 +704,12 @@ Affected Variables/Registers:
srbExtension = GetSrbExtension(slotContent->Srb);
isSenseSrb = IsRequestSenseSrb(srbExtension->AtaFunction);
+ if ((slotContent->Srb == (PSTORAGE_REQUEST_BLOCK)&ChannelExtension->Sense.Srb) &&
+ (ChannelExtension->StateFlags.NcqErrorRecoveryInProcess == 1)) {
+
+ isReadLogExtSrbIssuedInNCQErrorRecovery = TRUE;
+ }
+
if (LogExecuteFullDetail(ChannelExtension->AdapterExtension->LogFlags)) {
RecordExecutionHistory(ChannelExtension, 0x10000053);//ReleaseSlottedCommand
}
@@ -766,7 +791,6 @@ Affected Variables/Registers:
}
}
-
//3.1 Make the slot available again
slotContent->CmdHeader = NULL;
slotContent->CommandHistoryIndex = 0;
@@ -796,6 +820,21 @@ Affected Variables/Registers:
}
}
+ //
+ // There is a bad timing will break the error recovery and cause IO hang eventually, typically happen in SSD but not limited to.
+ // 1. NCQ error happen first, which will issue the ReadLogExtCommand;
+ // 2. Then Nonqueued error happen before the ReadLogExtCommand complete.
+ // In ReleaseSlottedCommand, ReadLogExtCommand may got chance to be retried, which will result in SingleIoSlice set to 1,
+ // and SingleIoSlice will skip the PreservedSettingCommand(the ReservedSlotInUse is already set).
+ // 3. Then ReservedSlotInUse never got chance to be cleared because it relies on PreservedSettingCommand execution.
+ // ReservedSlotInUse will block the queue activation, finally the IO will hang and AhciPortReset will be repeatedly issued by upper layer.
+ //
+ // Do not retry ReadLogExtCommand when NCQ error recovery in process, which makes sense since ReadLogExtCommand is sense-like command as well.
+ //
+ if (retrySrb && isReadLogExtSrbIssuedInNCQErrorRecovery) {
+ retrySrb = FALSE;
+ }
+
if (retrySrb) {
srbToRelease->SrbStatus = SRB_STATUS_PENDING;
srbExtension->RetryCount++;
@@ -1128,30 +1167,32 @@ Affected Variables/Registers:
{
BOOLEAN reservedSlotInUse = 0;
- if (LogExecuteFullDetail(ChannelExtension->AdapterExtension->LogFlags)) {
- RecordExecutionHistory(ChannelExtension, 0x00000041); //RestorePreservedSettings
- }
+ RecordExecutionHistory(ChannelExtension, 0x00000041); // RestorePreservedSettings
- //1 Reinitialize all the commands to send
+ //1 Reinitialize all the commands to send
ChannelExtension->PersistentSettings.SlotsToSend = ChannelExtension->PersistentSettings.Slots;
reservedSlotInUse = InterlockedBitTestAndSet((LONG*)&ChannelExtension->StateFlags, 3); //ReservedSlotInUse field is at bit 3
if (reservedSlotInUse == 1) {
+
// the process has been started.
+ RecordExecutionHistory(ChannelExtension, 0x10010041); // RestorePreservedSettings process already started
return;
}
- // acquire active reference for process of restore preserved settings
+ // acquire active reference for process of restore preserved settings
if (!AtDIRQL) {
- // this is only needed if function is called at lower level than DIRQL.
- // the places calling this function at DIRQL already made sure the unit is active.
+ // this is only needed if function is called at lower level than DIRQL.
+ // the places calling this function at DIRQL already made sure the unit is active.
ULONG restorePreservedSettingsInProcess;
BOOLEAN portIdle = FALSE;
restorePreservedSettingsInProcess = InterlockedBitTestAndSet((LONG*)&ChannelExtension->PoFxPendingWork, 0); //RestorePreservedSettings is at bit 0
if (restorePreservedSettingsInProcess == 1) {
+
// it's already in process, return from here
+ RecordExecutionHistory(ChannelExtension, 0x10020041); // RestorePreservedSettings already in process
return;
}
@@ -1160,21 +1201,24 @@ Affected Variables/Registers:
}
if (portIdle) {
+
// Unit Active process will continue on RestorePreservedSettings process
+ RecordExecutionHistory(ChannelExtension, 0x10030041); // RestorePreservedSettings will continue in Unit Active
return;
} else {
ULONG restorePreservedSettingsPending;
restorePreservedSettingsPending = InterlockedBitTestAndReset((LONG*)&ChannelExtension->PoFxPendingWork, 0); //RestorePreservedSettings is at bit 0
if (restorePreservedSettingsPending == 0) {
+
// Unit Active process already started on RestorePreservedSettings process
+ RecordExecutionHistory(ChannelExtension, 0x10040041); // RestorePreservedSettings already started in Unit Active
return;
}
}
}
-
//2 Start the first command
IssuePreservedSettingCommands(ChannelExtension, NULL);
@@ -1209,29 +1253,29 @@ Affected Variables/Registers:
{
BOOLEAN reservedSlotInUse = 0;
- if (LogExecuteFullDetail(ChannelExtension->AdapterExtension->LogFlags)) {
- RecordExecutionHistory(ChannelExtension, 0x00000042); //AhciPortIssueInitCommands
- }
+ RecordExecutionHistory(ChannelExtension, 0x00000042); // AhciPortIssueInitCommands
- //1 Reinitialize all the commands to send
+ //1 Reinitialize all the commands to send
ChannelExtension->DeviceInitCommands.CommandToSend = 0;
reservedSlotInUse = InterlockedBitTestAndSet((LONG*)&ChannelExtension->StateFlags, 3); //ReservedSlotInUse field is at bit 3
if (reservedSlotInUse == 1) {
+
// the process has been started.
+ RecordExecutionHistory(ChannelExtension, 0x10010042); // AhciPortIssueInitCommands process already started
return;
}
- // acquire active reference for process of issuing init commands
- // note: Port should be in Active state during device start.
+ // acquire active reference for process of issuing init commands
+ // note: Port should be in Active state during device start.
if (PortAcquireActiveReference(ChannelExtension, NULL, NULL)) {
ChannelExtension->StateFlags.RestorePreservedSettingsActiveReferenced = 1;
}
- //2 Start the first command
+ //2 Start the first command
IssueInitCommands(ChannelExtension, NULL);
- //3 Starts processing the command. Only need to do the first command if it exists. all others will be done by processing completion routine.
+ //3 Starts processing the command. Only need to do the first command if it exists. all others will be done by processing completion routine.
if (ChannelExtension->Local.Srb.SrbExtension != NULL) {
PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension((PSTORAGE_REQUEST_BLOCK)&ChannelExtension->Local.Srb);
if (srbExtension->AtaFunction != 0) {
@@ -1242,6 +1286,164 @@ Affected Variables/Registers:
return;
}
+VOID
+AhciPortStartTelemetry(
+ _In_ PAHCI_ADAPTER_EXTENSION AdapterExtension
+ )
+/*++
+
+Routine Description:
+
+ This function logs telemetry for AHCI port start status.
+
+Arguments:
+
+ AdapterExtension - Pointer to the device extension for adapter.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ NT_ASSERT(AdapterExtension->InRunningPortsProcess == FALSE);
+
+ for (ULONG i = 0; i <= AdapterExtension->HighestPort; ++i) {
+ PAHCI_CHANNEL_EXTENSION channelExtension = AdapterExtension->PortExtension[i];
+ if (channelExtension != NULL) {
+ BOOLEAN portStartSuccess = (channelExtension->StartState.ChannelNextStartState == StartComplete) ? (TRUE) : (FALSE);
+ AhciTelemetryLogPortStart(channelExtension,
+ (PSTOR_ADDRESS)&(channelExtension->DeviceExtension->DeviceAddress),
+ ((portStartSuccess) ? (AhciTelemetryEventIdPortStartSuccess) : (AhciTelemetryEventIdPortRunningStartFail)),
+ ((portStartSuccess) ? ("Port Start Success") : ("Port Start Failed")),
+ ((portStartSuccess) ? (0) : (AHCI_TELEMETRY_FLAG_NOT_SUPPRESS_LOGGING)),
+ NULL,
+ 0
+ );
+ }
+ }
+
+ return;
+}
+
+VOID
+AhciPortMarkDeviceFailed(
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_ AHCI_DEVICE_FAILURE_REASON FailureReason,
+ _In_ ULONG Flags,
+ _In_ BOOLEAN SuppressFailure
+ )
+/*++
+
+Routine Description:
+
+ This function will call storport API to mark failed device.
+
+ When caller passes TRUE for SuppressFailure, this function will
+ only call storport API to mark failed device once; otherwise,
+ this function will always call storport API to mark failed device.
+
+Arguments:
+
+ ChannelExtension - Pointer to the device extension for channel.
+
+ FailureReason - Indicates device failure reason.
+
+ Flags - Indicates whether remove failed device.
+
+ SuppressFailure - Indicates whether suppress failures.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ NT_ASSERT(ChannelExtension != NULL);
+
+ //
+ // Ignore Non-ATA device failures.
+ //
+ if (!IsAtaDevice(&ChannelExtension->DeviceExtension->DeviceParameters)) {
+ return;
+ }
+
+ switch (FailureReason) {
+
+ case AhciDeviceFailureTooManyBusChange: {
+ if ((!SuppressFailure) ||
+ ((ChannelExtension->DeviceFailureThrottleFlag & AHCI_BUS_CHANGE_WARNING_THROTTLE_MASK) == 0)) {
+ StorPortMarkDeviceFailed(ChannelExtension->AdapterExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ Flags,
+ L"Too many bus change");
+ }
+
+ if (SuppressFailure &&
+ ((ChannelExtension->DeviceFailureThrottleFlag & AHCI_BUS_CHANGE_WARNING_THROTTLE_MASK) == 0)) {
+ ChannelExtension->DeviceFailureThrottleFlag |= AHCI_BUS_CHANGE_WARNING_THROTTLE_MASK;
+ }
+
+ break;
+ }
+
+ case AhciDeviceFailureTooManyNCQError: {
+ if ((!SuppressFailure) ||
+ ((ChannelExtension->DeviceFailureThrottleFlag & AHCI_NCQ_ERROR_WARNING_THROTTLE_MASK) == 0)) {
+ StorPortMarkDeviceFailed(ChannelExtension->AdapterExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ Flags,
+ L"Too many NCQ error");
+ }
+
+ if (SuppressFailure &&
+ ((ChannelExtension->DeviceFailureThrottleFlag & AHCI_NCQ_ERROR_WARNING_THROTTLE_MASK) == 0)) {
+ ChannelExtension->DeviceFailureThrottleFlag |= AHCI_NCQ_ERROR_WARNING_THROTTLE_MASK;
+ }
+
+ break;
+ }
+
+ case AhciDeviceFailureTooManyNonQueuedError: {
+ if ((!SuppressFailure) ||
+ ((ChannelExtension->DeviceFailureThrottleFlag & AHCI_NON_QUEUED_ERROR_WARNING_THROTTLE_MASK) == 0)) {
+ StorPortMarkDeviceFailed(ChannelExtension->AdapterExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ Flags,
+ L"Too many NonQueue error");
+ }
+
+ if (SuppressFailure &&
+ ((ChannelExtension->DeviceFailureThrottleFlag & AHCI_NON_QUEUED_ERROR_WARNING_THROTTLE_MASK) == 0)) {
+ ChannelExtension->DeviceFailureThrottleFlag |= AHCI_NON_QUEUED_ERROR_WARNING_THROTTLE_MASK;
+ }
+
+ break;
+ }
+
+ case AhciDeviceFailureDeviceStuck: {
+ if ((!SuppressFailure) ||
+ ((ChannelExtension->DeviceFailureThrottleFlag & AHCI_DEVICE_STUCK_WARNING_THROTTLE_MASK) == 0)) {
+ StorPortMarkDeviceFailed(ChannelExtension->AdapterExtension,
+ (PSTOR_ADDRESS)&(ChannelExtension->DeviceExtension->DeviceAddress),
+ 0,
+ L"Device may stuck");
+ }
+
+ if (SuppressFailure &&
+ ((ChannelExtension->DeviceFailureThrottleFlag & AHCI_DEVICE_STUCK_WARNING_THROTTLE_MASK) == 0)) {
+ ChannelExtension->DeviceFailureThrottleFlag |= AHCI_DEVICE_STUCK_WARNING_THROTTLE_MASK;
+ }
+
+ break;
+ }
+
+ default: {
+ NT_ASSERT(FALSE);
+ break;
+ }
+ }
+}
#if _MSC_VER >= 1200
#pragma warning(pop)
@@ -1251,4 +1453,3 @@ Affected Variables/Registers:
#pragma warning(default:4214)
#pragma warning(default:4201)
#endif
-
diff --git a/storage/miniports/storahci/src/util.h b/storage/miniports/storahci/src/util.h
index c05339b1..249b7547 100644
--- a/storage/miniports/storahci/src/util.h
+++ b/storage/miniports/storahci/src/util.h
@@ -55,6 +55,21 @@ AhciFillMemory(
}
__inline
+VOID
+AhciCopyMemory(
+ _Out_writes_(Length) PCHAR Destination,
+ _In_reads_(Length) PCHAR Source,
+ _In_ ULONG Length
+ )
+{
+ ULONG i;
+
+ for (i = 0; i < Length; i++) {
+ Destination[i] = Source[i];
+ }
+}
+
+__inline
BOOLEAN
IsPortValid(
_In_ PAHCI_ADAPTER_EXTENSION AdapterExtension,
@@ -191,7 +206,7 @@ IsMsnEnabled(
_In_ PAHCI_DEVICE_EXTENSION DeviceExtension
)
{
- return ( (DeviceExtension->DeviceParameters.AtaDeviceType == DeviceIsAta) &&
+ return ( IsAtaDevice(&DeviceExtension->DeviceParameters) &&
(DeviceExtension->IdentifyDeviceData->MsnSupport == 1) );
}
@@ -201,7 +216,7 @@ IsRmfEnabled(
_In_ PAHCI_DEVICE_EXTENSION DeviceExtension
)
{
- return ( (DeviceExtension->DeviceParameters.AtaDeviceType == DeviceIsAta) &&
+ return ( IsAtaDevice(&DeviceExtension->DeviceParameters) &&
(DeviceExtension->IdentifyDeviceData->CommandSetSupport.RemovableMediaFeature == 1) &&
(DeviceExtension->IdentifyDeviceData->GeneralConfiguration.RemovableMedia == 1) );
}
@@ -212,7 +227,7 @@ NoFlushDevice(
_In_ PAHCI_DEVICE_EXTENSION DeviceExtension
)
{
- return ( (DeviceExtension->DeviceParameters.AtaDeviceType == DeviceIsAta) &&
+ return ( IsAtaDevice(&DeviceExtension->DeviceParameters) &&
(DeviceExtension->IdentifyDeviceData->CommandSetSupport.WriteCache == 0) &&
(DeviceExtension->IdentifyDeviceData->CommandSetSupport.FlushCache == 0) &&
(DeviceExtension->IdentifyDeviceData->CommandSetSupport.FlushCacheExt == 0) );
@@ -234,7 +249,7 @@ IsSmartFeatureSupported(
_In_ PAHCI_DEVICE_EXTENSION DeviceExtension
)
{
- return ( (DeviceExtension->DeviceParameters.AtaDeviceType == DeviceIsAta) &&
+ return ( IsAtaDevice(&DeviceExtension->DeviceParameters) &&
(DeviceExtension->IdentifyDeviceData->CommandSetSupport.SmartCommands == 1) );
}
@@ -264,7 +279,7 @@ IsExtendedPowerConditionsFeatureSupported(
_In_ PAHCI_DEVICE_EXTENSION DeviceExtension
)
{
- return ( (DeviceExtension->DeviceParameters.AtaDeviceType == DeviceIsAta) &&
+ return ( IsAtaDevice(&DeviceExtension->DeviceParameters) &&
(DeviceExtension->IdentifyDeviceData->CommandSetSupportExt.ExtendedPowerConditions == 1) );
}
@@ -274,7 +289,7 @@ IsStreamingFeatureSupported(
_In_ PAHCI_DEVICE_EXTENSION DeviceExtension
)
{
- return ( (DeviceExtension->DeviceParameters.AtaDeviceType == DeviceIsAta) &&
+ return ( IsAtaDevice(&DeviceExtension->DeviceParameters) &&
(DeviceExtension->IdentifyDeviceData->CommandSetSupport.StreamingFeature == 1) );
}
@@ -284,7 +299,7 @@ IsNcqFeatureSupported(
_In_ PAHCI_DEVICE_EXTENSION DeviceExtension
)
{
- return ( (DeviceExtension->DeviceParameters.AtaDeviceType == DeviceIsAta) &&
+ return ( IsAtaDevice(&DeviceExtension->DeviceParameters) &&
(DeviceExtension->IdentifyDeviceData->SerialAtaCapabilities.NCQ == 1) );
}
@@ -533,6 +548,7 @@ IsExternalPort(
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
)
{
+
if ( (ChannelExtension->Px->CMD.HPCP) ||
((ChannelExtension->AdapterExtension->CAP.SXS) && (ChannelExtension->Px->CMD.ESP)) ||
((ChannelExtension->AdapterExtension->CAP.SMPS) && (ChannelExtension->Px->CMD.MPSP)) ) {
@@ -551,6 +567,7 @@ IsLPMCapablePort(
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
)
{
+
// if a port is marked eSATA port but not having mechanical switch nor supporting Cold Presence Detection, don't turn on LPM on it.
if ( (ChannelExtension->Px->CMD.HPCP) ||
((ChannelExtension->AdapterExtension->CAP.SXS) && (ChannelExtension->Px->CMD.ESP)) ) {
@@ -570,7 +587,8 @@ IsDeviceHybridInfoSupported(
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
)
{
- if ( (ChannelExtension->DeviceExtension[0].DeviceParameters.AtaDeviceType == DeviceIsAta) &&
+
+ if ( IsAtaDevice(&ChannelExtension->DeviceExtension[0].DeviceParameters) &&
(ChannelExtension->DeviceExtension[0].IdentifyDeviceData->SerialAtaFeaturesSupported.HybridInformation == 1) ) {
return TRUE;
@@ -627,6 +645,7 @@ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
//
return TRUE;
}
+
}
return FALSE;
}
@@ -647,6 +666,7 @@ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
//
return TRUE;
}
+
}
return FALSE;
}
@@ -661,7 +681,6 @@ IsD3ColdAllowed(
UNREFERENCED_PARAMETER(AdapterExtension);
-
return allowed;
}
@@ -671,6 +690,7 @@ IsPortD3ColdEnabled(
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
)
{
+
// if device is D3Cold capable, return TRUE.
if (ChannelExtension->StateFlags.D3ColdEnabled == 1) {
return TRUE;
@@ -688,13 +708,6 @@ IsReceivingSystemPowerHints(
return (AdapterExtension->SystemPowerHintState != RaidSystemPowerUnknown);
}
-
-
-
-
-
-
-
__inline
BOOLEAN
AdapterPoFxEnabled (
@@ -827,15 +840,23 @@ PortReleaseActiveReference (
__inline
BOOLEAN
-DeviceIdentificationComplete(
+DeviceIdentificationCompletedSuccess(
_In_ PAHCI_ADAPTER_EXTENSION AdapterExtension
)
{
ULONG i;
+ //
+ // Note: There is possibility that 1st inquiry/identify will fail, then identify device
+ // data is invalid, but AtaDeviceType is initialized correctly during IO process.
+ // So it is also needed to check IdentifyDeviceSuccess flag to see whether identify
+ // command success.
+ //
+
for (i = 0; i <= AdapterExtension->HighestPort; i++) {
- if ( (AdapterExtension->PortExtension[i] != NULL) &&
- (AdapterExtension->PortExtension[i]->DeviceExtension->DeviceParameters.AtaDeviceType == DeviceUnknown) ) {
+ if ((AdapterExtension->PortExtension[i] != NULL) &&
+ ((AdapterExtension->PortExtension[i]->DeviceExtension->DeviceParameters.AtaDeviceType == DeviceUnknown) ||
+ (AdapterExtension->PortExtension[i]->StateFlags.IdentifyDeviceSuccess == 0))) {
return FALSE;
}
}
@@ -1018,6 +1039,7 @@ IsFuaSupported(
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
)
{
+
return (ChannelExtension->DeviceExtension->DeviceParameters.StateFlags.FuaSupported == 1);
}
@@ -1045,6 +1067,7 @@ NoLpmSupport(
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
)
{
+
if (ChannelExtension->AdapterExtension->StateFlags.StoppedState == 1) {
// adapter is stopped, Px registers are not accessible.
return TRUE;
@@ -1067,6 +1090,7 @@ NeedToSetTransferMode(
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
)
{
+
UNREFERENCED_PARAMETER(ChannelExtension); // make WDK sample build clean
return FALSE;
}
@@ -1077,6 +1101,7 @@ IsSingleIoDevice(
_In_ PAHCI_ADAPTER_EXTENSION AdapterExtension
)
{
+
UNREFERENCED_PARAMETER(AdapterExtension); // make WDK sample build clean
return FALSE;
}
@@ -1087,6 +1112,7 @@ AdapterResetInInit(
_In_ PAHCI_ADAPTER_EXTENSION AdapterExtension
)
{
+
UNREFERENCED_PARAMETER(AdapterExtension); // make WDK sample build clean
return FALSE;
}
@@ -1097,6 +1123,7 @@ IgnoreHotPlug(
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
)
{
+
return (ChannelExtension->StateFlags.IgnoreHotplugInterrupt == 1);
}
@@ -1106,6 +1133,7 @@ AdapterNoNonQueuedErrorRecovery(
_In_ PAHCI_ADAPTER_EXTENSION AdapterExtension
)
{
+
UNREFERENCED_PARAMETER(AdapterExtension); // make WDK sample build clean
return FALSE;
}
@@ -1116,6 +1144,7 @@ CloResetEnabled(
_In_ PAHCI_ADAPTER_EXTENSION AdapterExtension
)
{
+
UNREFERENCED_PARAMETER(AdapterExtension); // make WDK sample build clean
return (AdapterExtension->CAP.SCLO == 1);
}
@@ -1126,6 +1155,7 @@ IsNCQSupported(
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
)
{
+
if ( IsAtaDevice(&ChannelExtension->DeviceExtension->DeviceParameters) &&
(ChannelExtension->AdapterExtension->CAP.SNCQ == 1) &&
(ChannelExtension->DeviceExtension->IdentifyDeviceData->SerialAtaCapabilities.NCQ == 1) &&
@@ -1145,6 +1175,7 @@ IsFirmwareUpdateSupported(
BOOLEAN support;
+
if (ChannelExtension->DeviceExtension->FirmwareUpdate.DmOffsetsDeferredSupported) {
support = TRUE;
} else {
@@ -1252,7 +1283,6 @@ PartialToSlumberTransitionIsAllowed (
return FALSE;
}
-
if ( ((ChannelExtension->LastUserLpmPowerSetting & 0x2) != 0) &&
(ChannelExtension->DeviceExtension->IdentifyDeviceData->SerialAtaCapabilities.DeviceAutoPS == 1) &&
(ChannelExtension->DeviceExtension->IdentifyDeviceData->SerialAtaFeaturesEnabled.DeviceAutoPS == 1) ) {
@@ -1296,6 +1326,7 @@ GetHybridMaxLbaRangeCountForChangeLba (
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
)
{
+
//
// If CacheBehavior is supported, disk doesn't move data from primary medium to caching medium when
// executes HybridChangeByLba command. Use 64 as default MaxLbaRangeCountForChangeLba value.
@@ -1314,17 +1345,52 @@ SupportsEnhancedNcqErrorRecovery (
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
)
{
+
if ((ChannelExtension->DeviceExtension->SupportedGPLPages.SinglePage.NcqCommandError == 1) &&
(ChannelExtension->DeviceExtension->IoRecord.NcqReadLogErrorCount <= 5)) {
return TRUE;
+
} else {
return FALSE;
}
}
__inline
+BOOLEAN
+IsAtaPioDataInCmd(
+ _In_ PSTORAGE_REQUEST_BLOCK Srb
+ )
+{
+ PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb);
+ UCHAR command = IDE_COMMAND_NOT_VALID;
+
+ if (IsAtaCfisPayload(srbExtension->AtaFunction)) {
+ command = srbExtension->Cfis.Command;
+ } else if (IsAtaCommand(srbExtension->AtaFunction)) {
+ command = srbExtension->TaskFile.Current.bCommandReg;
+ }
+
+ //
+ // Only put together some major PIO Data-In commands here, which should be good enough
+ // for the PIO Data-In command return status mismatch issue.
+ //
+ switch (command) {
+ case IDE_COMMAND_READ:
+ case IDE_COMMAND_READ_EXT:
+ case IDE_COMMAND_READ_MULTIPLE_EXT:
+ case IDE_COMMAND_READ_LOG_EXT:
+ case IDE_COMMAND_ATAPI_IDENTIFY:
+ case IDE_COMMAND_READ_MULTIPLE:
+ case IDE_COMMAND_IDENTIFY:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+__inline
VOID
-SetReturnRegisterValues (
+SetReturnRegisterValues(
_In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
_In_ PSTORAGE_REQUEST_BLOCK Srb,
_In_opt_ PGP_LOG_NCQ_COMMAND_ERROR NcqErrorLog
@@ -1332,6 +1398,7 @@ SetReturnRegisterValues (
{
PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb);
PCDB cdb = SrbGetCdb(Srb);
+ BOOLEAN pioDataInCmd = IsAtaPioDataInCmd(Srb);
if ((IsReturnResults(srbExtension->Flags) == FALSE) || (srbExtension->ResultBuffer == NULL)) {
return;
@@ -1354,6 +1421,20 @@ SetReturnRegisterValues (
ataStatus->Header.AdditionalLength = 0x0C;
ataStatus->Extend = Is48BitCommand(srbExtension->Flags) ? 1 : 0;
+ // For PIO Data In command, if it is successful, then the device will not send RD2H FIS.
+ // Only update the ATA status/error without getting the stale copy of information in D2H FIS.
+ if (pioDataInCmd && (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS)) {
+ // According to SATA 3.0 specification 11.7:
+ // - Device will not send a RD2H FIS when PIO data in command success.
+ // According to AHCI 1.3.1 specification 5.3.9:
+ // - Device will report the ATA Status/Error register contents in the E_Status/Error field of the PIO Setup FIS.
+ // For ATA status return descriptor, refer to ATA Pass-Through specification 13.2.4.
+ ataStatus->Status = ChannelExtension->ReceivedFIS->PioSetupFis.E_Status;
+ ataStatus->Error = ChannelExtension->ReceivedFIS->PioSetupFis.Error;
+
+ goto Exit;
+ }
+
if (NcqErrorLog == NULL) {
ataStatus->Error = ChannelExtension->ReceivedFIS->D2hRegisterFis.Error;
ataStatus->SectorCount7_0 = ChannelExtension->ReceivedFIS->D2hRegisterFis.SectorCount;
@@ -1432,6 +1513,7 @@ SetReturnRegisterValues (
}
}
+Exit:
// set flag SRB_STATUS_AUTOSENSE_VALID so that Storport will copy it back to original Sense Buffer
Srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
@@ -1511,18 +1593,27 @@ AtaFormFactorToStorageFormFactor(
__inline
BOOLEAN
+IsAdapterRemovable(
+ _In_ PAHCI_ADAPTER_EXTENSION AdapterExtension
+ )
+{
+ return (BOOLEAN)AdapterExtension->StateFlags.Removable;
+}
+
+__inline
+BOOLEAN
IsAdapterRemoved(
- _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
+ _In_ PAHCI_ADAPTER_EXTENSION AdapterExtension
)
{
//
- // When the adapter is removed, its registers are read as
- // all 0xF's by the PCI bus. We use the PxSSTS register because
- // it has several reserved bits which will unlikely be defined
- // in the lifetime of the spec.
+ // When the adapter is removed, its registers are read as all 0xFs by the
+ // PCI bus. We use the Version register because all 0xFs is not a valid
+ // value and it is unlikely to ever be a valid value for the lifetime of
+ // the AHCI spec.
//
- ULONG ssts = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SSTS.AsUlong);
- return (ssts == MAXULONG);
+ ULONG version = StorPortReadRegisterUlong(AdapterExtension, &AdapterExtension->ABAR_Address->VS.AsUlong);
+ return (version == MAXULONG);
}
@@ -1586,6 +1677,19 @@ AhciPortIssueInitCommands(
PAHCI_CHANNEL_EXTENSION ChannelExtension
);
+VOID
+AhciPortStartTelemetry(
+ _In_ PAHCI_ADAPTER_EXTENSION AdapterExtension
+ );
+
+VOID
+AhciPortMarkDeviceFailed(
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_ AHCI_DEVICE_FAILURE_REASON FailureReason,
+ _In_ ULONG Flags,
+ _In_ BOOLEAN SuppressFailure
+ );
+
_Success_(return != FALSE)
BOOLEAN
CompareId (
@@ -1614,3 +1718,266 @@ AhciUlongIncrement(
}
}
+VOID
+FillAtaCommandErrorStruct(
+ _Out_ PATA_COMMAND_ERROR DataBuffer,
+ _In_ PSTORAGE_REQUEST_BLOCK Srb,
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
+ );
+
+
+VOID
+FORCEINLINE
+AhciTelemetryLog(
+ _In_ PVOID HwDeviceExtension,
+ _In_opt_ PSTOR_ADDRESS Address,
+ _In_ ULONG DriverVersion,
+ _In_ ULONG EventId,
+ _In_reads_or_z_(EVENT_NAME_MAX_LENGTH) PSTR EventName,
+ _In_ ULONG EventVersion,
+ _In_ ULONG Flags,
+ _In_ ULONG EventBufferLength,
+ _In_reads_bytes_opt_(EventBufferLength) PUCHAR EventBuffer,
+ _In_reads_or_z_opt_(EVENT_MAX_PARAM_NAME_LEN) PSTR Parameter0Name,
+ _In_ ULONGLONG Parameter0Value,
+ _In_reads_or_z_opt_(EVENT_MAX_PARAM_NAME_LEN) PSTR Parameter1Name,
+ _In_ ULONGLONG Parameter1Value,
+ _In_reads_or_z_opt_(EVENT_MAX_PARAM_NAME_LEN) PSTR Parameter2Name,
+ _In_ ULONGLONG Parameter2Value,
+ _In_reads_or_z_opt_(EVENT_MAX_PARAM_NAME_LEN) PSTR Parameter3Name,
+ _In_ ULONGLONG Parameter3Value,
+ _In_reads_or_z_opt_(EVENT_MAX_PARAM_NAME_LEN) PSTR Parameter4Name,
+ _In_ ULONGLONG Parameter4Value,
+ _In_reads_or_z_opt_(EVENT_MAX_PARAM_NAME_LEN) PSTR Parameter5Name,
+ _In_ ULONGLONG Parameter5Value,
+ _In_reads_or_z_opt_(EVENT_MAX_PARAM_NAME_LEN) PSTR Parameter6Name,
+ _In_ ULONGLONG Parameter6Value,
+ _In_reads_or_z_opt_(EVENT_MAX_PARAM_NAME_LEN) PSTR Parameter7Name,
+ _In_ ULONGLONG Parameter7Value
+ )
+{
+ STORPORT_TELEMETRY_EVENT event = {0};
+
+ event.DriverVersion = DriverVersion;
+ event.EventId = EventId;
+ StorPortCopyMemory(event.EventName, EventName, GetStringLength(EventName, EVENT_NAME_MAX_LENGTH));
+ event.EventVersion = EventVersion;
+ event.Flags = Flags;
+
+ if ((EventBufferLength > 0) && (EventBuffer != NULL)) {
+ event.EventBuffer = EventBuffer;
+ event.EventBufferLength = min(EventBufferLength, EVENT_BUFFER_MAX_LENGTH);
+ }
+
+ if (Parameter0Name != NULL) {
+ StorPortCopyMemory(event.ParameterName0, Parameter0Name, GetStringLength(Parameter0Name, EVENT_MAX_PARAM_NAME_LEN));
+ event.ParameterValue0 = Parameter0Value;
+ }
+
+ if (Parameter1Name != NULL) {
+ StorPortCopyMemory(event.ParameterName1, Parameter1Name, GetStringLength(Parameter1Name, EVENT_MAX_PARAM_NAME_LEN));
+ event.ParameterValue1 = Parameter1Value;
+ }
+
+ if (Parameter2Name != NULL) {
+ StorPortCopyMemory(event.ParameterName2, Parameter2Name, GetStringLength(Parameter2Name, EVENT_MAX_PARAM_NAME_LEN));
+ event.ParameterValue2 = Parameter2Value;
+ }
+
+ if (Parameter3Name != NULL) {
+ StorPortCopyMemory(event.ParameterName3, Parameter3Name, GetStringLength(Parameter3Name, EVENT_MAX_PARAM_NAME_LEN));
+ event.ParameterValue3 = Parameter3Value;
+ }
+
+ if (Parameter4Name != NULL) {
+ StorPortCopyMemory(event.ParameterName4, Parameter4Name, GetStringLength(Parameter4Name, EVENT_MAX_PARAM_NAME_LEN));
+ event.ParameterValue4 = Parameter4Value;
+ }
+
+ if (Parameter5Name != NULL) {
+ StorPortCopyMemory(event.ParameterName5, Parameter5Name, GetStringLength(Parameter5Name, EVENT_MAX_PARAM_NAME_LEN));
+ event.ParameterValue5 = Parameter5Value;
+ }
+
+ if (Parameter6Name != NULL) {
+ StorPortCopyMemory(event.ParameterName6, Parameter6Name, GetStringLength(Parameter6Name, EVENT_MAX_PARAM_NAME_LEN));
+ event.ParameterValue6 = Parameter6Value;
+ }
+
+ if (Parameter7Name != NULL) {
+ StorPortCopyMemory(event.ParameterName7, Parameter7Name, GetStringLength(Parameter7Name, EVENT_MAX_PARAM_NAME_LEN));
+ event.ParameterValue7 = Parameter7Value;
+ }
+
+ StorPortLogTelemetry(HwDeviceExtension, Address, &event);
+
+ return;
+}
+
+VOID
+FORCEINLINE
+AhciTelemetryLogResetErrorRecovery(
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_opt_ PSTOR_ADDRESS Address,
+ _In_ ULONG EventId,
+ _In_reads_or_z_(EVENT_NAME_MAX_LENGTH) PSTR EventName,
+ _In_ ULONG Flags,
+ _In_reads_or_z_(EVENT_MAX_PARAM_NAME_LEN) PSTR AdditionalParameterName,
+ _In_ ULONGLONG AdditionalParameterValue
+ )
+{
+ LARGE_INTEGER time;
+ ULONGLONG elapsedTime;
+
+ if (ChannelExtension != NULL) {
+
+ StorPortQuerySystemTime(&time);
+ elapsedTime = time.QuadPart - ChannelExtension->LastLogResetErrorRecoveryTime;
+
+ //
+ // If AHCI_TELEMETRY_FLAG_NOT_SUPPRESS_LOGGING is set, always log event;
+ // otherwise, if this is the first time logging or if it has been 1 hour
+ // since the last log, log the current counts of reset and error recovery.
+ //
+ if (((Flags & AHCI_TELEMETRY_FLAG_NOT_SUPPRESS_LOGGING) != 0) ||
+ (ChannelExtension->LastLogResetErrorRecoveryTime == 0) ||
+ (elapsedTime >= MS_TO_100NS(60*60*1000))) {
+
+ ChannelExtension->LastLogResetErrorRecoveryTime = time.QuadPart;
+
+ AhciTelemetryLog(ChannelExtension->AdapterExtension,
+ Address,
+ AHCI_TELEMETRY_DRIVER_VERSION,
+ EventId,
+ EventName,
+ AHCI_TELEMETRY_EVENT_VERSION,
+ Flags,
+ 0,
+ NULL,
+ "PortReset|PortErrorRecovery",
+ (((ULONGLONG)ChannelExtension->TotalCountPortReset << 32) |
+ ((ULONGLONG)ChannelExtension->TotalCountPortErrorRecovery)),
+ "StartFail|NonQErrorRecovery",
+ (((ULONGLONG)ChannelExtension->TotalCountRunningStartFailed << 32) |
+ ((ULONGLONG)ChannelExtension->TotalCountNonQueuedErrorRecovery)),
+ "NCQError|NCQErrorComplete",
+ (((ULONGLONG)ChannelExtension->TotalCountNCQError << 32) |
+ ((ULONGLONG)ChannelExtension->TotalCountNCQErrorRecoveryComplete)),
+ "PortDriverResetCount",
+ ChannelExtension->DeviceExtension[0].IoRecord.PortDriverResetCount,
+ "StateFlags",
+ *(ULONGLONG *)&(ChannelExtension->StateFlags),
+ "StartState",
+ *(ULONGLONG *)&(ChannelExtension->StartState),
+ "TotalCountSurpriseRemove",
+ ChannelExtension->TotalCountSurpriseRemove,
+ AdditionalParameterName,
+ AdditionalParameterValue
+ );
+ }
+ }
+
+ return;
+}
+
+VOID
+FORCEINLINE
+AhciTelemetryLogPowerSettingChange(
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_opt_ PSTOR_ADDRESS Address,
+ _In_ ULONG EventId,
+ _In_reads_or_z_(EVENT_NAME_MAX_LENGTH) PSTR EventName,
+ _In_ ULONG Flags,
+ _In_ ULONG Ipm,
+ _In_ ULONG LpmMode
+ )
+{
+ if (ChannelExtension != NULL) {
+
+ AhciTelemetryLog(ChannelExtension->AdapterExtension,
+ Address,
+ AHCI_TELEMETRY_DRIVER_VERSION,
+ EventId,
+ EventName,
+ AHCI_TELEMETRY_EVENT_VERSION,
+ Flags,
+ 0,
+ NULL,
+ "PowerSettingChangeCount",
+ ChannelExtension->TotalCountPowerSettingNotification,
+ "StateFlags",
+ *(ULONGLONG *)&(ChannelExtension->StateFlags),
+ "LastUserLpmPowerSetting",
+ ChannelExtension->LastUserLpmPowerSetting,
+ "CAP",
+ ChannelExtension->AdapterExtension->CAP.AsUlong,
+ "CAP2",
+ ChannelExtension->AdapterExtension->CAP2.AsUlong,
+ "PxCMD",
+ StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->CMD.AsUlong),
+ "IPM",
+ Ipm,
+ "LpmMode|SlumberInterval",
+ LpmMode
+ );
+ }
+
+ return;
+}
+
+VOID
+FORCEINLINE
+AhciTelemetryLogPortStart(
+ _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
+ _In_opt_ PSTOR_ADDRESS Address,
+ _In_ ULONG EventId,
+ _In_reads_or_z_(EVENT_NAME_MAX_LENGTH) PSTR EventName,
+ _In_ ULONG Flags,
+ _In_reads_or_z_(EVENT_MAX_PARAM_NAME_LEN) PSTR AdditionalParameterName,
+ _In_ ULONGLONG AdditionalParameterValue
+ )
+{
+ if (ChannelExtension != NULL) {
+ //
+ // Log the telemetry event only when at least one of below conditions is true:
+ // 1. AHCI_TELEMETRY_FLAG_NOT_SUPPRESS_LOGGING flag is set;
+ // 2. Current port start time is no less than 1s.
+ //
+ if (((Flags && AHCI_TELEMETRY_FLAG_NOT_SUPPRESS_LOGGING) != 0) ||
+ (ChannelExtension->TotalPortStartTime >= 1000)) {
+
+ AhciTelemetryLog(ChannelExtension->AdapterExtension,
+ Address,
+ AHCI_TELEMETRY_DRIVER_VERSION,
+ EventId,
+ EventName,
+ AHCI_TELEMETRY_EVENT_VERSION,
+ Flags,
+ 0,
+ NULL,
+ "PortReset|PortErrorRecovery",
+ (((ULONGLONG)ChannelExtension->TotalCountPortReset << 32) |
+ ((ULONGLONG)ChannelExtension->TotalCountPortErrorRecovery)),
+ "StartFail|NonQErrorRecovery",
+ (((ULONGLONG)ChannelExtension->TotalCountRunningStartFailed << 32) |
+ ((ULONGLONG)ChannelExtension->TotalCountNonQueuedErrorRecovery)),
+ "NCQError|NCQErrorComplete",
+ (((ULONGLONG)ChannelExtension->TotalCountNCQError << 32) |
+ ((ULONGLONG)ChannelExtension->TotalCountNCQErrorRecoveryComplete)),
+ "PortDriverResetCount",
+ ChannelExtension->DeviceExtension[0].IoRecord.PortDriverResetCount,
+ "StateFlags",
+ *(ULONGLONG *)&(ChannelExtension->StateFlags),
+ "StartState",
+ *(ULONGLONG *)&(ChannelExtension->StartState),
+ "PortStartTime(ms)",
+ ChannelExtension->TotalPortStartTime,
+ AdditionalParameterName,
+ AdditionalParameterValue
+ );
+ }
+ }
+
+ return;
+}
+
diff --git a/storage/msdsm/README.md b/storage/msdsm/README.md
index 88f34d2b..42ba9bc3 100644
--- a/storage/msdsm/README.md
+++ b/storage/msdsm/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Multipath I/O (MPIO) DSM Sample
- platform: WDM
- language: cpp
- category: Storage
- description: Provides a sample for building vendor-specific device-specific modules (DSM), supports iSCSI and Fibre Channel devices.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620203
---->
-
# Multipath I/O (MPIO) DSM Sample
The MPIO DSM Sample is intended to serve as an example to follow when building your own vendor specific device specific modules (DSM). This sample DSM supports iSCSI and Fibre Channel devices.
@@ -29,8 +21,11 @@ You build a driver the same way you build any project or solution in Visual Stud
The default Solution build configuration is **Debug** and **Win32**.
1. Open the driver project or solution in Visual Studio (find *samplename*.sln or *samplename*.vcxproj).
+
1. Right-click the solution in the **Solutions Explorer** and select **Configuration Manager**.
+
1. From the **Configuration Manager**, select the **Active Solution Configuration** (for example, Debug or Release) and the **Active Solution Platform** (for example, Win32) that correspond to the type of build you are interested in.
+
1. From the Build menu, click **Build Solution** (Ctrl+Shift+B).
## Building a Driver Using the Command Line (MSBuild)
@@ -38,9 +33,10 @@ The default Solution build configuration is **Debug** and **Win32**.
You can build a driver from the command line using the Visual Studio Command Prompt window and the Microsoft Build Engine (MSBuild.exe) Previous versions of the WDK used the Windows Build utility (Build.exe) and provided separate build environment windows for each of the supported build configurations. You can now use the Visual Studio Command Prompt window for all build configurations.
1. Open a Visual Studio Command Prompt window at the **Start** screen. From this window you can use MsBuild.exe to build any Visual Studio project by specifying the project (.VcxProj) or solutions (.Sln) file.
+
1. Navigate to the project directory and enter the **MSbuild** command for your target. For example, to perform a clean build of a Visual Studio driver project called *filtername*.vcxproj, navigate to the project directory and enter the following MSBuild command:
- **msbuild /t:clean /t:build .\\<*samplename*>.vcxproj**.
+ `msbuild /t:clean /t:build .\<samplename>.vcxproj`
## Installation and Operation
@@ -102,7 +98,8 @@ AddReg = mydsm_addreg
This next section contains the Hardware ID strings for your devices. You can have more than one. Sample format: "VENDOR PRODUCT " - remember to use spaces in a field (vendor, product ID) to pad this to be eight characters for the vendor name (as registered with STA) and sixteen for the product ID (unless the supported devices share a common prefix, in which case the product ID can be less than 16 characters).
-**Note** Underscores that are part of the inquiry string (applies to vendor ID as well as product ID fields) must NOT be replaced with spaces.
+> [!NOTE]
+> Underscores that are part of the inquiry string (applies to vendor ID as well as product ID fields) must NOT be replaced with spaces.
In this sample, there are two different strings:
@@ -208,6 +205,8 @@ You should be aware of the following when you install the MPIO DSM sample:
It is expected that the adapter that hosts the system volumes (boot/paging) will not restart, but that should not be problem if you are not multipathing the boot volume. However, if you are multipathing the boot volume, you will need to restart the system.
-**Note** Other filter drivers installed as port filters may interfere with the proper operation of the MPIO port filter. Microsoft does not recommend the use of such filter drivers which may be supplied by HBA miniport vendors.
+> [!NOTE]
+> Other filter drivers installed as port filters may interfere with the proper operation of the MPIO port filter. Microsoft does not recommend the use of such filter drivers which may be supplied by HBA miniport vendors.
-**Note** Since your DSM binary is not signed, you will get Unsigned Driver Pop-Ups. Ignore these and accept the installation of the new driver. Once your package has been successfully qualified by WHQL, your binaries will get signed and your customers will not get unsigned driver popups. \ No newline at end of file
+> [!NOTE]
+> Since your DSM binary is not signed, you will get Unsigned Driver Pop-Ups. Ignore these and accept the installation of the new driver. Once your package has been successfully qualified by WHQL, your binaries will get signed and your customers will not get unsigned driver popups.
diff --git a/storage/msdsm/src/SampleDSM.inf b/storage/msdsm/src/SampleDSM.inf
index f632f6e5..5617fa4e 100644
--- a/storage/msdsm/src/SampleDSM.inf
+++ b/storage/msdsm/src/SampleDSM.inf
Binary files differ
diff --git a/storage/msdsm/src/intrface.c b/storage/msdsm/src/intrface.c
index 925252be..b282600f 100644
--- a/storage/msdsm/src/intrface.c
+++ b/storage/msdsm/src/intrface.c
@@ -101,6 +101,11 @@ Return Value:
//
+ // Must call this function before using pool allocation functions.
+ //
+ ExInitializeDriverRuntime(0);
+
+ //
// Initialize the tracing subsystem.
// Any failure is handled by ETW itself.
//
diff --git a/storage/msdsm/src/precomp.h b/storage/msdsm/src/precomp.h
index c199724e..12f1a7aa 100644
--- a/storage/msdsm/src/precomp.h
+++ b/storage/msdsm/src/precomp.h
@@ -18,6 +18,7 @@ Revision History:
#pragma once
#define DEBUG_MAIN_SOURCE 1
+#define POOL_ZERO_DOWN_LEVEL_SUPPORT
#include <stdio.h>
#include <stdarg.h>
diff --git a/storage/msdsm/src/prototypes.h b/storage/msdsm/src/prototypes.h
index 1df58197..371315ba 100644
--- a/storage/msdsm/src/prototypes.h
+++ b/storage/msdsm/src/prototypes.h
@@ -1336,8 +1336,8 @@ Description:
Arguments:
Srb - A pointer to either a STORAGE_REQUEST_BLOCK or a SCSI_REQUEST_BLOCK.
- PoolType - The pool type to use. See documentation for ExAllocatePoolWithTag().
- Tag - The allocation tag to use. See documentation for ExAllocatePoolWithTag().
+ PoolType - The pool type to use. See documentation for ExAllocatePoolZero().
+ Tag - The allocation tag to use. See documentation for ExAllocatePoolZero().
Returns:
NULL, if the copy could not be allocated; or
diff --git a/storage/msdsm/src/utils.c b/storage/msdsm/src/utils.c
index 2f1bcbe1..1d966fd5 100644
--- a/storage/msdsm/src/utils.c
+++ b/storage/msdsm/src/utils.c
@@ -93,10 +93,7 @@ Return Value:
Tag));
#pragma warning(suppress: 28118) // False-positive; PoolType is simply passed through
- Block = ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
- if (Block) {
- RtlZeroMemory(Block, NumberOfBytes);
- }
+ Block = ExAllocatePoolZero(PoolType, NumberOfBytes, Tag);
TracePrint((TRACE_LEVEL_VERBOSE,
TRACE_FLAG_GENERAL,
@@ -176,7 +173,7 @@ Return Value:
if (NT_SUCCESS(status)) {
#pragma warning(suppress: 6014 28118) // Block isn't leaked, this function is marked as an allocator; PoolType is simply passed through
- Block = ExAllocatePoolWithTag(PoolType, totalSize, Tag);
+ Block = ExAllocatePoolZero(PoolType, totalSize, Tag);
if (Block != NULL) {
@@ -194,7 +191,6 @@ __Exit:
if (NT_SUCCESS(status)) {
- RtlZeroMemory(Block, totalSize);
*BytesAllocated = totalSize;
}
diff --git a/storage/sfloppy/README.md b/storage/sfloppy/README.md
index c99d9d6b..d05748df 100644
--- a/storage/sfloppy/README.md
+++ b/storage/sfloppy/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Super Floppy (sfloppy) Storage Class Driver
- platform: WDM
- language: cpp
- category: Storage
- description: A sample class driver for Super Floppy disk drives.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617989
---->
-
# Super Floppy (sfloppy) Storage Class Driver
The sfloppy sample is a super floppy driver. This driver is a class driver for Super Floppy disk drives.
@@ -26,6 +18,6 @@ This sample builds a Universal Windows Driver. It uses only APIs and DDIs that a
## Installation and Operation
-This sample sits a level above the port driver (ATAPI, USB, and so on) in the driver stack and controls communication between the application level and the port driver. The floppy driver takes requests from file system drivers and then sends the appropriate [**SCSI\_REQUEST\_BLOCK**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff565393) (SRB) to the port driver.
+This sample sits a level above the port driver (ATAPI, USB, and so on) in the driver stack and controls communication between the application level and the port driver. The floppy driver takes requests from file system drivers and then sends the appropriate [**SCSI\_REQUEST\_BLOCK**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/srb/ns-srb-_scsi_request_block) (SRB) to the port driver.
-For more information, see [Introduction to Storage Class Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff559215) in the storage technologies design guide. \ No newline at end of file
+For more information, see [Introduction to Storage Class Drivers](https://docs.microsoft.com/windows-hardware/drivers/storage/introduction-to-storage-class-drivers) in the storage technologies design guide.
diff --git a/storage/sfloppy/src/floppy.c b/storage/sfloppy/src/floppy.c
index f4c9634d..fc084f7c 100644
--- a/storage/sfloppy/src/floppy.c
+++ b/storage/sfloppy/src/floppy.c
@@ -649,7 +649,7 @@ Return Value:
DeviceCount++;
status = RtlStringCbPrintfA((PCCHAR) name,
- sizeof(name)/sizeof(UCHAR),
+ sizeof(name),
"\\Device\\Floppy%u",
DeviceCount);
if (NT_SUCCESS(status)) {
@@ -909,7 +909,7 @@ NTSTATUS ScsiFlopStartDevice(
//
RtlStringCbPrintfW(ntNameBuffer,
- sizeof(ntNameBuffer)/sizeof(WCHAR),
+ sizeof(ntNameBuffer),
L"\\Device\\Floppy%u",
fdoExtension->DeviceNumber);
@@ -955,7 +955,7 @@ NTSTATUS ScsiFlopStartDevice(
if (NT_SUCCESS(status)) {
RtlStringCbPrintfW(arcNameBuffer,
- sizeof(arcNameBuffer)/sizeof(WCHAR),
+ sizeof(arcNameBuffer),
L"\\ArcName\\scsi(%u)disk(%u)fdisk(%u)",
scsiAddress.PortNumber,
scsiAddress.TargetId,
@@ -977,7 +977,7 @@ NTSTATUS ScsiFlopStartDevice(
//
RtlStringCbPrintfW(arcNameBuffer,
- sizeof(arcNameBuffer)/sizeof(WCHAR),
+ sizeof(arcNameBuffer),
L"\\ArcName\\multi(%u)disk(%u)fdisk(%u)",
0,
0,
diff --git a/storage/tools/spti/README.md b/storage/tools/spti/README.md
index c89a4a7b..b0d08237 100644
--- a/storage/tools/spti/README.md
+++ b/storage/tools/spti/README.md
@@ -5,23 +5,15 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: SCSI Pass-Through Interface Tool
- platform: Application
- language: cpp
- category: Storage
- description: Demonstrates how to communicate with a SCSI device using pass-through IOCTLs in an application using DeviceIoControl API.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617990
---->
-
# SCSI Pass-Through Interface Tool
The SCSI Pass Through Interface sample demonstrates how to communicate with a SCSI device from Microsoft Win32 applications by using the **DeviceIoControl** API.
## Installation and Operation
-The storage port drivers provide an interface for Win32 applications to send SCSI CBDs (Command Descriptor Block) to SCSI devices. The interfaces are [**IOCTL\_SCSI\_PASS\_THROUGH**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff560519) and [**IOCTL\_SCSI\_PASS\_THROUGH\_DIRECT**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff560521). Applications can build a pass-through request and send it to the device by using this IOCTL.
+The storage port drivers provide an interface for Win32 applications to send SCSI CBDs (Command Descriptor Block) to SCSI devices. The interfaces are [**IOCTL\_SCSI\_PASS\_THROUGH**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ntddscsi/ni-ntddscsi-ioctl_scsi_pass_through) and [**IOCTL\_SCSI\_PASS\_THROUGH\_DIRECT**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ntddscsi/ni-ntddscsi-ioctl_scsi_pass_through_direct). Applications can build a pass-through request and send it to the device by using this IOCTL.
-Two command line parameters can be used with *SPTI.EXE*. The first parameter is mandatory. It is the name of the device to be opened. Typical values for this are drive letters such as "C:", or device names as defined by a class driver such as Scanner0, or the SCSI port driver name, ScsiN:, where N = 0, 1, 2, etc. The second parameter is optional and is used to set the share mode (note that access mode and share mode are different things) and sector size. The default share mode is (FILE\_SHARE\_READ | FILE\_SHARE\_WRITE) and the default sector size is 512. A parameter of "r" changes the share mode to only FILE\_SHARE\_READ. A parameter of "w" changes the share mode to only FILE\_SHARE\_WRITE. A parameter of "c" changes the share mode to only FILE\_SHARE\_READ and also changes the sector size to 2048. Typically, a CD-ROM device would use the "c" parameter. \ No newline at end of file
+Two command line parameters can be used with *SPTI.EXE*. The first parameter is mandatory. It is the name of the device to be opened. Typical values for this are drive letters such as "C:", or device names as defined by a class driver such as Scanner0, or the SCSI port driver name, ScsiN:, where N = 0, 1, 2, etc. The second parameter is optional and is used to set the share mode (note that access mode and share mode are different things) and sector size. The default share mode is (FILE\_SHARE\_READ | FILE\_SHARE\_WRITE) and the default sector size is 512. A parameter of "r" changes the share mode to only FILE\_SHARE\_READ. A parameter of "w" changes the share mode to only FILE\_SHARE\_WRITE. A parameter of "c" changes the share mode to only FILE\_SHARE\_READ and also changes the sector size to 2048. Typically, a CD-ROM device would use the "c" parameter.
diff --git a/thermal/simsensor/README.md b/thermal/simsensor/README.md
index c4847ade..ee308112 100644
--- a/thermal/simsensor/README.md
+++ b/thermal/simsensor/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: SimSensor - Simulated Temperature Sensor Sample Driver
- platform: KMDF
- language: cpp
- category: Thermal Power
- description: Demonstrates a simulated temperature sensor device.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617991
---->
-
# SimSensor - Simulated Temperature Sensor Sample Driver
This sample is a driver for a simulated temperature sensor device.
@@ -24,6 +16,6 @@ This sample is a driver for a simulated temperature sensor device.
This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP.
-A hardware platform designer can strategically place temperature sensors in various thermal zones around the platform. The operating system gets the temperature readings from the temperature sensor drivers and uses these readings to regulate the temperatures across the platform. Regulation can be either passive or active. For more information, see [Device-Level Thermal Management](http://msdn.microsoft.com/en-us/library/windows/hardware/hh698236).
+A hardware platform designer can strategically place temperature sensors in various thermal zones around the platform. The operating system gets the temperature readings from the temperature sensor drivers and uses these readings to regulate the temperatures across the platform. Regulation can be either passive or active. For more information, see [Device-Level Thermal Management](https://docs.microsoft.com/windows-hardware/drivers/kernel/device-level-thermal-management).
-The SimSensor sample provides the source code for a specialized sensor driver that supports platform-wide thermal management by the operating system. This driver does not make the temperature sensor accessible to applications through the [Sensor API](http://msdn.microsoft.com/en-us/library/windows/hardware/dd318953). \ No newline at end of file
+The SimSensor sample provides the source code for a specialized sensor driver that supports platform-wide thermal management by the operating system. This driver does not make the temperature sensor accessible to applications through the [Sensor API](https://docs.microsoft.com/windows/win32/sensorsapi/portal).
diff --git a/thermal/thermalclient/README.md b/thermal/thermalclient/README.md
index 39eb83c7..35405f86 100644
--- a/thermal/thermalclient/README.md
+++ b/thermal/thermalclient/README.md
@@ -5,23 +5,17 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: SimThermalClient - Simulated Thermal Client Sample Driver
- platform: KMDF
- language: cpp
- category: Thermal Power
- description: Simulates a device that is a Windows thermal management client.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617992
---->
-
# SimThermalClient - Simulated Thermal Client Sample Driver
-This sample is a driver for a simulated device that is a client of Windows thermal management. This driver publishes a [GUID\_THERMAL\_COOLING\_INTERFACE](http://msdn.microsoft.com/en-us/library/windows/hardware/hh698265) driver interface. Drivers publish this interface so that they can participate in global thermal management under the coordination of the Windows operating system.
+This sample is a driver for a simulated device that is a client of Windows thermal management. This driver publishes a [GUID\_THERMAL\_COOLING\_INTERFACE](https://docs.microsoft.com/windows-hardware/drivers/kernel/global-thermal-mgmt) driver interface. Drivers publish this interface so that they can participate in global thermal management under the coordination of the Windows operating system.
## Universal Windows Driver Compliant
This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP.
-For more information, see [Device-Level Thermal Management](http://msdn.microsoft.com/en-us/library/windows/hardware/hh698236). \ No newline at end of file
+## See also
+
+[Device-Level Thermal Management](https://docs.microsoft.com/windows-hardware/drivers/kernel/device-level-thermal-management)
diff --git a/tools/dv/samples/DV-FailDriver-WDM/README.md b/tools/dv/samples/DV-FailDriver-WDM/README.md
index 1e2021a5..532071c7 100644
--- a/tools/dv/samples/DV-FailDriver-WDM/README.md
+++ b/tools/dv/samples/DV-FailDriver-WDM/README.md
@@ -5,22 +5,15 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: DV-FailDriver-WDM
- platform: WDM
- language: cpp
- category: DriverVerifier Tools
- description: Demonstrates how Driver Verifier (DV) can find errors in a WDM driver.
- samplefwlink: https://go.microsoft.com/fwlink/p/?linkid=856743
---->
-
# DV-FailDriver-WDM
-The DV-FailDriver-WDM sample driver contains intentional code errors that are designed to show the capabilities and features of [Driver Verifier](https://msdn.microsoft.com/en-us/library/windows/hardware/ff545448) (DV) and the [Device Fundamentals tests](https://msdn.microsoft.com/en-us/library/windows/hardware/jj673011). Driver Verifier is a component of the Windows kernel designed to detect drivers that are behaving poorly and stop their execution via a bugcheck; the Device Fundamentals tests are a series of tests provided in the Windows Driver Kit (WDK) designed to provide a good basic set of tests against a driver.
+The DV-FailDriver-WDM sample driver contains intentional code errors that are designed to show the capabilities and features of [Driver Verifier](https://docs.microsoft.com/windows-hardware/drivers/devtest/driver-verifier) (DV) and the [Device Fundamentals tests](https://docs.microsoft.com/windows-hardware/drivers/devtest/device-fundamentals-tests). Driver Verifier is a component of the Windows kernel designed to detect drivers that are behaving poorly and stop their execution via a bugcheck; the Device Fundamentals tests are a series of tests provided in the Windows Driver Kit (WDK) designed to provide a good basic set of tests against a driver.
-**Caution** This sample driver contains intentional code errors that are designed to show the capabilities and features of DV and SDV. This sample driver is not intended as an example for real driver development projects.
+> [!CAUTION]
+> This sample driver contains intentional code errors that are designed to show the capabilities and features of DV and SDV. This sample driver is not intended as an example for real driver development projects.
## Build the sample for desktop
@@ -30,10 +23,10 @@ The DV-FailDriver-WDM sample driver contains intentional code errors that are de
## Deploy the sample
-See [Deploying a Driver to a Test Computer](https://msdn.microsoft.com/en-us/library/windows/hardware/hh454834) for details on how to deploy the sample.
+See [Deploying a Driver to a Test Computer](https://docs.microsoft.com/windows-hardware/drivers/develop/deploying-a-driver-to-a-test-computer) for details on how to deploy the sample.
## Test the sample
-See [How to test a driver at runtime](https://msdn.microsoft.com/en-us/library/windows/hardware/ff554820) for details on how to run tests on the Toastmon driver.
+See [How to test a driver at runtime](https://docs.microsoft.com/windows-hardware/drivers/develop/how-to-test-a-driver-at-runtime-from-a-command-prompt) for details on how to run tests on the Toastmon driver.
-To observe the injected defect being caught by DV, you should enable DV on the Toastmon driver, and then run the "DF - PNP Surprise Remove (Development and Integration)" test on the Toastmon sample driver and device. \ No newline at end of file
+To observe the injected defect being caught by DV, you should enable DV on the Toastmon driver, and then run the "DF - PNP Surprise Remove (Development and Integration)" test on the Toastmon sample driver and device.
diff --git a/tools/dv/samples/DV-FailDriver-WDM/driver/defect_toastmon.inf b/tools/dv/samples/DV-FailDriver-WDM/driver/defect_toastmon.inf
index 7be4d774..44975b91 100644
--- a/tools/dv/samples/DV-FailDriver-WDM/driver/defect_toastmon.inf
+++ b/tools/dv/samples/DV-FailDriver-WDM/driver/defect_toastmon.inf
@@ -18,6 +18,7 @@ ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318}
Provider="Sample Provider"
DriverVer=12/12/2017,10.0.0.1
CatalogFile=Defect_Toastmon.cat
+PnpLockdown=1
[DestinationDirs]
DefaultDestDir = 12
diff --git a/tools/dv/samples/DV-FailDriver-WDM/driver/defect_toastmon.vcxproj b/tools/dv/samples/DV-FailDriver-WDM/driver/defect_toastmon.vcxproj
index dd677f88..3a8a6d16 100644
--- a/tools/dv/samples/DV-FailDriver-WDM/driver/defect_toastmon.vcxproj
+++ b/tools/dv/samples/DV-FailDriver-WDM/driver/defect_toastmon.vcxproj
@@ -99,6 +99,9 @@
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -107,6 +110,9 @@
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -115,6 +121,9 @@
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -123,6 +132,9 @@
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\defect_toastmon.c" />
diff --git a/tools/sdv/samples/SDV-FailDriver-KMDF/README.md b/tools/sdv/samples/SDV-FailDriver-KMDF/README.md
index 4a18341b..afe148d1 100644
--- a/tools/sdv/samples/SDV-FailDriver-KMDF/README.md
+++ b/tools/sdv/samples/SDV-FailDriver-KMDF/README.md
@@ -5,22 +5,15 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: SDV-FailDriver-KMDF
- platform: KMDF
- language: cpp
- category: StaticDriverVerifier Tools
- description: Demonstrates how Static Driver Verifier (SDV) can find errors in a KMDF driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617993
---->
-
# SDV-FailDriver-KMDF
-The SDV-FailDriver-KMDF sample driver contains intentional code errors that are designed to show the capabilities and features of [Static Driver Verifier](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552808) (SDV). SDV is a static verification tool that systematically analyzes the source code of Windows kernel-mode drivers. SDV is included in the Windows Driver Kit (WDK) and can be run from Microsoft Visual Studio. The sample demonstrates how SDV can find errors in a KMDF driver.
+The SDV-FailDriver-KMDF sample driver contains intentional code errors that are designed to show the capabilities and features of [Static Driver Verifier](https://docs.microsoft.com/windows-hardware/drivers/devtest/static-driver-verifier) (SDV). SDV is a static verification tool that systematically analyzes the source code of Windows kernel-mode drivers. SDV is included in the Windows Driver Kit (WDK) and can be run from Microsoft Visual Studio. The sample demonstrates how SDV can find errors in a KMDF driver.
-**Caution** These sample drivers contain intentional code errors that are designed to show the capabilities and features of SDV. These sample drivers are not functional and are not intended as examples for real driver development projects.
+> [!CAUTION]
+> These sample drivers contain intentional code errors that are designed to show the capabilities and features of SDV. These sample drivers are not functional and are not intended as examples for real driver development projects.
## Run the sample
@@ -32,7 +25,7 @@ The SDV-FailDriver-KMDF sample driver contains intentional code errors that are
1. The fail\_driver1 sample driver includes a library. To add the library, click the **Libraries** tab and click **Add Library**.
- Browse to the sample library directory and select the library project file (fail\_library1.vcxProj). The library must be added before SDV analyzes the driver. For more information, see [Library Processing in Static Driver Verifier](http://msdn.microsoft.com/en-us/library/windows/hardware/ff548182).
+ Browse to the sample library directory and select the library project file (fail\_library1.vcxProj). The library must be added before SDV analyzes the driver. For more information, see [Library Processing in Static Driver Verifier](https://docs.microsoft.com/windows-hardware/drivers/devtest/library-processing-in-static-driver-verifier).
1. Click the **Rules** tab to select which driver DDI usage rules to verify when you start the analysis.
@@ -40,16 +33,23 @@ The SDV-FailDriver-KMDF sample driver contains intentional code errors that are
Use the default rule set, or select **Custom rule selection**, click **Clear All**, and then select the following rules for the KMDF fail\_driver1 sample:
- - [DriverCreate](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544957)
- - [DeviceInitAPI](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544843)
- - [CtlDeviceFinishInitDeviceAdd](http://msdn.microsoft.com/en-us/library/windows/hardware/ff543607)
- - [MdlAfterReqCompletedIoctl](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549047)
- - [MemAfterReqCompletedIntIoctlA](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549090)
- - [MdlAfterReqCompletedIntIoctlA](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549042)
- - [MarkCancOnCancReqLocal](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549011)
- - [StopAckWithinEvtIoStop](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552846)
+ - [DriverCreate](https://docs.microsoft.com/windows-hardware/drivers/devtest/kmdf-drivercreate)
+
+ - [DeviceInitAPI](https://docs.microsoft.com/windows-hardware/drivers/devtest/kmdf-deviceinitapi)
+
+ - [CtlDeviceFinishInitDeviceAdd](https://docs.microsoft.com/windows-hardware/drivers/devtest/kmdf-ctldevicefinishinitdeviceadd)
+
+ - [MdlAfterReqCompletedIoctl](https://docs.microsoft.com/windows-hardware/drivers/devtest/kmdf-mdlafterreqcompletedioctl)
+
+ - [MemAfterReqCompletedIntIoctlA](https://docs.microsoft.com/windows-hardware/drivers/devtest/kmdf-memafterreqcompletedintioctla)
+
+ - [MdlAfterReqCompletedIntIoctlA](https://docs.microsoft.com/windows-hardware/drivers/devtest/kmdf-mdlafterreqcompletedintioctla)
+
+ - [MarkCancOnCancReqLocal](https://docs.microsoft.com/windows-hardware/drivers/devtest/kmdf-markcanconcancreqlocal)
+
+ - [StopAckWithinEvtIoStop](https://docs.microsoft.com/windows-hardware/drivers/devtest/kmdf-stopackwithinevtiostop)
- For information about the rules, see [DDI Compliance Rules](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552840).
+ For information about the rules, see [DDI Compliance Rules](https://docs.microsoft.com/windows-hardware/drivers/devtest/static-driver-verifier-rules).
1. Start the static analysis. Click the **Main** tab, and then click **Start**. When you click **Start**, a message is displayed to let you know that static analysis is scheduled and that the analysis can take a long time to run. Click **OK** to continue.
@@ -57,4 +57,4 @@ The SDV-FailDriver-KMDF sample driver contains intentional code errors that are
As the static analysis proceeds, SDV reports the status of the analysis. When the analysis is complete, SDV reports the results and statistics. If the driver fails to satisfy a DDI usage rule, the result is reported as a defect. SDV finds 8 defects in this sample.
-On the **Main** tab, under **Results**, click the **Rules** tab. This tab displays the name of each rule that was verified in the last run and the results of the analysis. To view the reported defects, click the **Defect** link in the **Results** column. This opens the [Static Driver Verifier Report Page](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552834) and the [Trace Viewer](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544659), which displays a trace of the code path to the rule violation. For more information, see [Interpreting Static Driver Verifier Results](http://msdn.microsoft.com/en-us/library/windows/hardware/ff547228). \ No newline at end of file
+On the **Main** tab, under **Results**, click the **Rules** tab. This tab displays the name of each rule that was verified in the last run and the results of the analysis. To view the reported defects, click the **Defect** link in the **Results** column. This opens the [Static Driver Verifier Report Page](https://docs.microsoft.com/windows-hardware/drivers/devtest/static-driver-verifier-report) and the [Trace Viewer](https://docs.microsoft.com/windows-hardware/drivers/devtest/defect-viewer), which displays a trace of the code path to the rule violation. For more information, see [Interpreting Static Driver Verifier Results](https://docs.microsoft.com/windows-hardware/drivers/devtest/interpreting-static-driver-verifier-results).
diff --git a/tools/sdv/samples/SDV-FailDriver-KMDF/driver/fail_driver1.vcxproj b/tools/sdv/samples/SDV-FailDriver-KMDF/driver/fail_driver1.vcxproj
index d8c4ccaa..912be491 100644
--- a/tools/sdv/samples/SDV-FailDriver-KMDF/driver/fail_driver1.vcxproj
+++ b/tools/sdv/samples/SDV-FailDriver-KMDF/driver/fail_driver1.vcxproj
@@ -106,6 +106,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);.\..\library\$(IntDir)\fail_library1.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -124,6 +127,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);.\..\library\$(IntDir)\fail_library1.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -142,6 +148,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);.\..\library\$(IntDir)\fail_library1.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -160,6 +169,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);.\..\library\$(IntDir)\fail_library1.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="fail_driver1.c" />
diff --git a/tools/sdv/samples/SDV-FailDriver-KMDF/driver/fail_driver1.vcxproj.Filters b/tools/sdv/samples/SDV-FailDriver-KMDF/driver/fail_driver1.vcxproj.Filters
index 217729c9..86ab5d01 100644
--- a/tools/sdv/samples/SDV-FailDriver-KMDF/driver/fail_driver1.vcxproj.Filters
+++ b/tools/sdv/samples/SDV-FailDriver-KMDF/driver/fail_driver1.vcxproj.Filters
@@ -23,4 +23,9 @@
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/tools/sdv/samples/SDV-FailDriver-KMDF/library/fail_library1.vcxproj b/tools/sdv/samples/SDV-FailDriver-KMDF/library/fail_library1.vcxproj
index 49e4a00e..b7458e70 100644
--- a/tools/sdv/samples/SDV-FailDriver-KMDF/library/fail_library1.vcxproj
+++ b/tools/sdv/samples/SDV-FailDriver-KMDF/library/fail_library1.vcxproj
@@ -96,6 +96,9 @@
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -104,6 +107,9 @@
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -112,6 +118,9 @@
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -120,6 +129,9 @@
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="fail_library1.c" />
diff --git a/tools/sdv/samples/SDV-FailDriver-KMDF/library/fail_library1.vcxproj.Filters b/tools/sdv/samples/SDV-FailDriver-KMDF/library/fail_library1.vcxproj.Filters
index 102ff304..6a024601 100644
--- a/tools/sdv/samples/SDV-FailDriver-KMDF/library/fail_library1.vcxproj.Filters
+++ b/tools/sdv/samples/SDV-FailDriver-KMDF/library/fail_library1.vcxproj.Filters
@@ -23,4 +23,9 @@
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/tools/sdv/samples/SDV-FailDriver-NDIS/README.md b/tools/sdv/samples/SDV-FailDriver-NDIS/README.md
index dd9e4da4..43d4a90d 100644
--- a/tools/sdv/samples/SDV-FailDriver-NDIS/README.md
+++ b/tools/sdv/samples/SDV-FailDriver-NDIS/README.md
@@ -5,22 +5,15 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: SDV-FailDriver-NDIS
- platform: WDM
- language: cpp
- category: StaticDriverVerifier Network
- description: Demonstrates how Static Driver Verifier (SDV) can find errors in a NDIS driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617995
---->
-
# SDV-FailDriver-NDIS
-The SDV-FailDriver-NDIS sample driver contains intentional code errors that are designed to show the capabilities and features of [Static Driver Verifier](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552808) (SDV). SDV is a static verification tool that systematically analyzes the source code of Windows kernel-mode drivers. SDV is included in the Windows Driver Kit (WDK) and can be run from Microsoft Visual Studio. The sample demonstrates how SDV can find errors in an NDIS driver.
+The SDV-FailDriver-NDIS sample driver contains intentional code errors that are designed to show the capabilities and features of [Static Driver Verifier](https://docs.microsoft.com/windows-hardware/drivers/devtest/static-driver-verifier) (SDV). SDV is a static verification tool that systematically analyzes the source code of Windows kernel-mode drivers. SDV is included in the Windows Driver Kit (WDK) and can be run from Microsoft Visual Studio. The sample demonstrates how SDV can find errors in an NDIS driver.
-**Caution** These sample drivers contain intentional code errors that are designed to show the capabilities and features of SDV. These sample drivers are not functional and are not intended as examples for real driver development projects.
+> [!CAUTION]
+> These sample drivers contain intentional code errors that are designed to show the capabilities and features of SDV. These sample drivers are not functional and are not intended as examples for real driver development projects.
## Run the sample
@@ -36,13 +29,17 @@ The SDV-FailDriver-NDIS sample driver contains intentional code errors that are
Use the default rule set, or select **Custom rule selection**, click **Clear All**, and then select the following rules for the NDIS sdvmp sample:
- - [NdisAllocateMemoryWithTagPriority](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549326)
- - [Init\_RegisterSG](http://msdn.microsoft.com/en-us/library/windows/hardware/ff547153)
- - [NdisStallExecution\_Delay](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549332)
- - [Flags\_Irql](http://msdn.microsoft.com/en-us/library/windows/hardware/ff546123)
- - [Irql\_Synch\_Function](http://msdn.microsoft.com/en-us/library/windows/hardware/ff548015)
+ - [NdisAllocateMemoryWithTagPriority](https://docs.microsoft.com/windows-hardware/drivers/devtest/ndis-ndisallocatememorywithtagpriority)
+
+ - [Init\_RegisterSG](https://docs.microsoft.com/windows-hardware/drivers/devtest/ndis-init-registersg)
+
+ - [NdisStallExecution\_Delay](https://docs.microsoft.com/windows-hardware/drivers/devtest/ndis-ndisstallexecution-delay)
+
+ - [Flags\_Irql](https://docs.microsoft.com/windows-hardware/drivers/devtest/ndis-flags-irql)
+
+ - [Irql\_Synch\_Function](https://docs.microsoft.com/windows-hardware/drivers/devtest/ndis-irql-synch-function)
- For information about the rules, see [DDI Compliance Rules](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552840).
+ For information about the rules, see [DDI Compliance Rules](https://docs.microsoft.com/windows-hardware/drivers/devtest/static-driver-verifier-rules).
1. Start the static analysis. Click the **Main** tab, and click **Start**. When you click **Start**, a message is displayed to let you know that static analysis is scheduled and that the analysis can take a long time to run. Click **OK** to continue.
@@ -50,4 +47,4 @@ The SDV-FailDriver-NDIS sample driver contains intentional code errors that are
As the static analysis proceeds, SDV reports the status of the analysis. When the analysis is complete, SDV reports the results and statistics. If the driver fails to satisfy a DDI usage rule, the result is reported as a defect. SDV finds 5 defects in this sample.
-On the **Main** tab, under **Results**, click the **Rules** tab. This tab displays the name of each rule that was verified in the last run and the results of the analysis. To view the reported defects, click the **Defect** link in the **Results** column. This opens the [Static Driver Verifier Report Page](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552834) and the [Trace Viewer](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544659), which displays a trace of the code path to the rule violation. For more information, see [Interpreting Static Driver Verifier Results](http://msdn.microsoft.com/en-us/library/windows/hardware/ff547228). \ No newline at end of file
+On the **Main** tab, under **Results**, click the **Rules** tab. This tab displays the name of each rule that was verified in the last run and the results of the analysis. To view the reported defects, click the **Defect** link in the **Results** column. This opens the [Static Driver Verifier Report Page](https://docs.microsoft.com/windows-hardware/drivers/devtest/static-driver-verifier-report) and the [Trace Viewer](https://docs.microsoft.com/windows-hardware/drivers/devtest/defect-viewer), which displays a trace of the code path to the rule violation. For more information, see [Interpreting Static Driver Verifier Results](https://docs.microsoft.com/windows-hardware/drivers/devtest/interpreting-static-driver-verifier-results).
diff --git a/tools/sdv/samples/SDV-FailDriver-NDIS/driver/sdvmp.vcxproj b/tools/sdv/samples/SDV-FailDriver-NDIS/driver/sdvmp.vcxproj
index 102b4763..f89012d1 100644
--- a/tools/sdv/samples/SDV-FailDriver-NDIS/driver/sdvmp.vcxproj
+++ b/tools/sdv/samples/SDV-FailDriver-NDIS/driver/sdvmp.vcxproj
@@ -106,6 +106,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ndis.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -125,6 +128,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ndis.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -144,6 +150,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ndis.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -163,6 +172,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ndis.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.c" />
diff --git a/tools/sdv/samples/SDV-FailDriver-NDIS/driver/sdvmp.vcxproj.Filters b/tools/sdv/samples/SDV-FailDriver-NDIS/driver/sdvmp.vcxproj.Filters
index 790b6262..53ae89f0 100644
--- a/tools/sdv/samples/SDV-FailDriver-NDIS/driver/sdvmp.vcxproj.Filters
+++ b/tools/sdv/samples/SDV-FailDriver-NDIS/driver/sdvmp.vcxproj.Filters
@@ -28,4 +28,9 @@
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/tools/sdv/samples/SDV-FailDriver-STORPORT/README.md b/tools/sdv/samples/SDV-FailDriver-STORPORT/README.md
index 71106508..39770a7f 100644
--- a/tools/sdv/samples/SDV-FailDriver-STORPORT/README.md
+++ b/tools/sdv/samples/SDV-FailDriver-STORPORT/README.md
@@ -5,22 +5,15 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: SDV-FailDriver-STORPORT
- platform: KMDF
- language: cpp
- category: StaticDriverVerifier
- description: Demonstrates how Static Driver Verifier (SDV) can find errors in a Storport driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617997
---->
-
# SDV-FailDriver-STORPORT
-The SDV-FailDriver-Storport sample driver contains intentional code errors that are designed to show the capabilities and features of [Static Driver Verifier](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552808) (SDV). SDV is a static verification tool that systematically analyzes the source code of Windows kernel-mode drivers. SDV is included in the Windows Driver Kit (WDK) and can be run from Microsoft Visual Studio. The sample demonstrates how SDV can find errors in a Storport driver.
+The SDV-FailDriver-Storport sample driver contains intentional code errors that are designed to show the capabilities and features of [Static Driver Verifier](https://docs.microsoft.com/windows-hardware/drivers/devtest/static-driver-verifier) (SDV). SDV is a static verification tool that systematically analyzes the source code of Windows kernel-mode drivers. SDV is included in the Windows Driver Kit (WDK) and can be run from Microsoft Visual Studio. The sample demonstrates how SDV can find errors in a Storport driver.
-**Caution** These sample drivers contain intentional code errors that are designed to show the capabilities and features of SDV. These sample drivers are not functional and are not intended as examples for real driver development projects.
+> [!CAUTION]
+> These sample drivers contain intentional code errors that are designed to show the capabilities and features of SDV. These sample drivers are not functional and are not intended as examples for real driver development projects.
## Run the sample
@@ -36,15 +29,21 @@ The SDV-FailDriver-Storport sample driver contains intentional code errors that
Use the default rule set, or select **Custom rule selection**, click **Clear All**, and then select the following rules for the Storport sample:
- - [StorPortAllocatePool2 Rule (Storport)](http://msdn.microsoft.com/en-us/library/windows/hardware/hh454259)
- - [StorPortDeprecated Rule (Storport)](http://msdn.microsoft.com/en-us/library/windows/hardware/hh454263)
- - [StorPortEnablePassive Rule (Storport)](http://msdn.microsoft.com/en-us/library/windows/hardware/hh454264)
- - [StorPortNotification2 Rule (Storport)](http://msdn.microsoft.com/en-us/library/windows/hardware/hh454268)
- - [StorPortSpinLock Rule (Storport)](http://msdn.microsoft.com/en-us/library/windows/hardware/hh454273)
- - [StorPortStartIo Rule (Storport)](http://msdn.microsoft.com/en-us/library/windows/hardware/hh454274)
- - [StorPortStatusPending Rule (Storport)](http://msdn.microsoft.com/en-us/library/windows/hardware/hh454275)
+ - [StorPortAllocatePool2 Rule (Storport)](https://docs.microsoft.com/windows-hardware/drivers/devtest/storport-storportallocatepool2)
+
+ - [StorPortDeprecated Rule (Storport)](https://docs.microsoft.com/windows-hardware/drivers/devtest/storport-storportdeprecated)
+
+ - [StorPortEnablePassive Rule (Storport)](https://docs.microsoft.com/windows-hardware/drivers/devtest/storport-storportenablepassive)
+
+ - [StorPortNotification2 Rule (Storport)](https://docs.microsoft.com/windows-hardware/drivers/devtest/storport-storportnotification2)
+
+ - [StorPortSpinLock Rule (Storport)](https://docs.microsoft.com/windows-hardware/drivers/devtest/storport-storportspinlock)
+
+ - [StorPortStartIo Rule (Storport)](https://docs.microsoft.com/windows-hardware/drivers/devtest/storport-storportstartio)
+
+ - [StorPortStatusPending Rule (Storport)](https://docs.microsoft.com/windows-hardware/drivers/devtest/storport-storportstatuspending)
- For information about the rules, see [DDI Compliance Rules](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552840).
+ For information about the rules, see [DDI Compliance Rules](https://docs.microsoft.com/windows-hardware/drivers/devtest/static-driver-verifier-rules).
1. Start the static analysis. Click the **Main** tab, and click **Start**. When you click **Start**, a message is displayed to let you know that static analysis is scheduled and that the analysis can take a long time to run. Click **OK** to continue.
@@ -52,4 +51,4 @@ The SDV-FailDriver-Storport sample driver contains intentional code errors that
As the static analysis proceeds, SDV reports the status of the analysis. When the analysis is complete, SDV reports the results and statistics. If the driver fails to satisfy a DDI usage rule, the result is reported as a defect. SDV finds 7 defects in this sample.
-On the **Main** tab, under **Results**, click the **Rules** tab. This tab displays the name of each rule that was verified in the last run and the results of the analysis. To view the reported defects, click the **Defect** link in the **Results** column. This opens the [Static Driver Verifier Report Page](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552834) and the [Trace Viewer](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544659), which displays a trace of the code path to the rule violation. For more information, see [Interpreting Static Driver Verifier Results](http://msdn.microsoft.com/en-us/library/windows/hardware/ff547228). \ No newline at end of file
+On the **Main** tab, under **Results**, click the **Rules** tab. This tab displays the name of each rule that was verified in the last run and the results of the analysis. To view the reported defects, click the **Defect** link in the **Results** column. This opens the [Static Driver Verifier Report Page](https://docs.microsoft.com/windows-hardware/drivers/devtest/static-driver-verifier-report) and the [Trace Viewer](https://docs.microsoft.com/windows-hardware/drivers/devtest/defect-viewer), which displays a trace of the code path to the rule violation. For more information, see [Interpreting Static Driver Verifier Results](https://docs.microsoft.com/windows-hardware/drivers/devtest/interpreting-static-driver-verifier-results).
diff --git a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.c b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.c
index 786994bf..3ce17bf1 100644
--- a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.c
+++ b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.c
@@ -1243,7 +1243,7 @@ Return Value:
// Enable data phase mismatch processing internal to 1010
WRITE_SIOP_UCHAR( CCNTL0, CCNTL0_DISABLE_PIPE_REQ + CCNTL0_ENA_PM_JUMP);
- // Disable 64-bit slave cycles
+ // Disable 64-bit subordinate cycles
WRITE_SIOP_UCHAR( CCNTL1, 0x10);
// Set phase mismatch jump registers
WRITE_SIOP_ULONG( PMJAD1, DeviceExtension->PhaseMisJump1Phys);
diff --git a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.vcxproj b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.vcxproj
index 4a16ad3d..ca461e0a 100644
--- a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.vcxproj
+++ b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.vcxproj
@@ -105,6 +105,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\storport.lib;$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -123,6 +126,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\storport.lib;$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -141,6 +147,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\storport.lib;$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -159,6 +168,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\storport.lib;$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="lsi_u3.c" />
diff --git a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.vcxproj.Filters b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.vcxproj.Filters
index e5753da7..7c3d617d 100644
--- a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.vcxproj.Filters
+++ b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.vcxproj.Filters
@@ -28,4 +28,30 @@
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="*.txt;*.htm;*.html" />
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/tools/sdv/samples/SDV-FailDriver-WDM/README.md b/tools/sdv/samples/SDV-FailDriver-WDM/README.md
index 6ce7b456..33223725 100644
--- a/tools/sdv/samples/SDV-FailDriver-WDM/README.md
+++ b/tools/sdv/samples/SDV-FailDriver-WDM/README.md
@@ -5,22 +5,15 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: SDV-FailDriver-WDM
- platform: WDM
- language: cpp
- category: StaticDriverVerifier
- description: Demonstrates how Static Driver Verifier (SDV) can find errors in a WDM driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617999
---->
-
# SDV-FailDriver-WDM
-The SDV-FailDriver-WDM sample driver contains intentional code errors that are designed to show the capabilities and features of [Static Driver Verifier](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552808) (SDV). SDV is a static verification tool that systematically analyzes the source code of Windows kernel-mode drivers. SDV is included in the Windows Driver Kit (WDK) and can be run from Microsoft Visual Studio. The sample demonstrates how SDV can find errors in a WDM driver.
+The SDV-FailDriver-WDM sample driver contains intentional code errors that are designed to show the capabilities and features of [Static Driver Verifier](https://docs.microsoft.com/windows-hardware/drivers/devtest/static-driver-verifier) (SDV). SDV is a static verification tool that systematically analyzes the source code of Windows kernel-mode drivers. SDV is included in the Windows Driver Kit (WDK) and can be run from Microsoft Visual Studio. The sample demonstrates how SDV can find errors in a WDM driver.
-**Caution** These sample drivers contain intentional code errors that are designed to show the capabilities and features of SDV. These sample drivers are not functional and are not intended as examples for real driver development projects.
+> [!CAUTION]
+> These sample drivers contain intentional code errors that are designed to show the capabilities and features of SDV. These sample drivers are not functional and are not intended as examples for real driver development projects.
## Run the sample
@@ -36,13 +29,17 @@ The SDV-FailDriver-WDM sample driver contains intentional code errors that are d
Use the default rule set, or select **Custom rule selection**, click **Clear All**, and then select the following rules for the WDM fail\_driver1 sample:
- - [CancelSpinLock](http://msdn.microsoft.com/en-us/library/windows/hardware/ff542478)
- - [IrqlIoApcLte](http://msdn.microsoft.com/en-us/library/windows/hardware/ff547759)
- - [IrqlKeSetEvent](http://msdn.microsoft.com/en-us/library/windows/hardware/ff547835)
- - [LowerDriverReturn](http://msdn.microsoft.com/en-us/library/windows/hardware/ff548273)
- - [SpinLock (WDM)](http://msdn.microsoft.com/en-us/library/windows/hardware/ff551861)
+ - [CancelSpinLock](https://docs.microsoft.com/windows-hardware/drivers/devtest/wdm-cancelspinlock)
+
+ - [IrqlIoApcLte](https://docs.microsoft.com/windows-hardware/drivers/devtest/wdm-irqlioapclte)
+
+ - [IrqlKeSetEvent](https://docs.microsoft.com/windows-hardware/drivers/devtest/wdm-irqlkesetevent)
+
+ - [LowerDriverReturn](https://docs.microsoft.com/windows-hardware/drivers/devtest/wdm-lowerdriverreturn)
+
+ - [SpinLock (WDM)](https://docs.microsoft.com/windows-hardware/drivers/devtest/wdm-spinlock)
- For information about the rules, see [DDI Compliance Rules](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552840).
+ For information about the rules, see [DDI Compliance Rules](https://docs.microsoft.com/windows-hardware/drivers/devtest/static-driver-verifier-rules).
1. Start the static analysis. Click the **Main** tab, and click **Start**. When you click **Start**, a message is displayed to let you know that static analysis is scheduled and that the analysis can take a long time to run. Click **OK** to continue.
@@ -50,4 +47,4 @@ The SDV-FailDriver-WDM sample driver contains intentional code errors that are d
As the static analysis proceeds, SDV reports the status of the analysis. When the analysis is complete, SDV reports the results and statistics. If the driver fails to satisfy a DDI usage rule, the result is reported as a defect. SDV finds 5 defects in this sample.
-To view specific defects in the [Static Driver Verifier Report](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552834), click the Defect in the **Results** pane. This opens the [Trace Viewer](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544659), which displays a trace of the code path to the rule violation. For more information, see [Interpreting Static Driver Verifier Results](http://msdn.microsoft.com/en-us/library/windows/hardware/ff547228). \ No newline at end of file
+On the **Main** tab, under **Results**, click the **Rules** tab. This tab displays the name of each rule that was verified in the last run and the results of the analysis. To view the reported defects, click the **Defect** link in the **Results** column. This opens the [Static Driver Verifier Report Page](https://docs.microsoft.com/windows-hardware/drivers/devtest/static-driver-verifier-report) and the [Trace Viewer](https://docs.microsoft.com/windows-hardware/drivers/devtest/defect-viewer), which displays a trace of the code path to the rule violation. For more information, see [Interpreting Static Driver Verifier Results](https://docs.microsoft.com/windows-hardware/drivers/devtest/interpreting-static-driver-verifier-results).
diff --git a/tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.c b/tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.c
index 0aed2564..03087d9f 100644
--- a/tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.c
+++ b/tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.c
@@ -68,6 +68,9 @@ DriverAddDevice(
UNREFERENCED_PARAMETER(PhysicalDeviceObject);
PAGED_CODE();
+
+ // Injected CA defect for C28171
+ PAGED_CODE();
status = IoCreateDevice(DriverObject,
sizeof(DRIVER_DEVICE_EXTENSION),
diff --git a/tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.vcxproj b/tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.vcxproj
index f3a16b7c..5a45eb5b 100644
--- a/tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.vcxproj
+++ b/tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.vcxproj
@@ -120,24 +120,36 @@
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<Inf Exclude="@(Inf)" Include="*.inf" />
diff --git a/tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.vcxproj.Filters b/tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.vcxproj.Filters
index a2daf153..cd74ffa3 100644
--- a/tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.vcxproj.Filters
+++ b/tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.vcxproj.Filters
@@ -23,4 +23,9 @@
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/usb/UcmCxUcsi/Acpi.cpp b/usb/UcmCxUcsi/Acpi.cpp
index ed90260d..33dec487 100644
--- a/usb/UcmCxUcsi/Acpi.cpp
+++ b/usb/UcmCxUcsi/Acpi.cpp
@@ -554,9 +554,9 @@ Acpi_EvaluateUcsiDsm (
FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) +
outputArgumentBufferSize;
- outputBuffer = (PACPI_EVAL_OUTPUT_BUFFER) ExAllocatePoolWithTag(NonPagedPoolNx,
- outputBufferSize,
- TAG_UCSI);
+ outputBuffer = (PACPI_EVAL_OUTPUT_BUFFER) ExAllocatePool2(POOL_FLAG_NON_PAGED,
+ outputBufferSize,
+ TAG_UCSI);
if (outputBuffer == nullptr)
{
@@ -565,8 +565,6 @@ Acpi_EvaluateUcsiDsm (
goto Exit;
}
- RtlZeroMemory(outputBuffer, outputBufferSize);
-
WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&inputMemDesc, inputMemory, NULL);
WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&outputMemDesc, outputBuffer, (ULONG) outputBufferSize);
diff --git a/usb/UcmCxUcsi/README.md b/usb/UcmCxUcsi/README.md
index 9d7cc638..9def204e 100644
--- a/usb/UcmCxUcsi/README.md
+++ b/usb/UcmCxUcsi/README.md
@@ -5,35 +5,30 @@ languages:
- cpp
products:
- windows
+- windows-wdk
urlFragment: ucmtcpcicx-port-controller-client-driver-v2
---
-<!---
- name: UcmTcpciCx Port Controller Client Driver
- platform: KMDF
- language: cpp
- category: USB
- description: Demonstrates how to create a Windows USB Type-C port controller driver using the USB Connector Manager class extension driver (UcmCx).
- samplefwlink: https://go.microsoft.com/fwlink/p/?linkid=856744
---->
+# UcmCxUcsi Port Controller Client Driver
-# UcmTcpciCx Port Controller Client Driver
-
-This is a sample driver that shows how to create a Windows USB Type-C port controller driver using the USB Connector Manager class extension driver (UcmCx). The sample is a driver for an embedded controller which is complient with the [USB Type-C Connector System Software Interface (UCSI)](http://www.intel.com/content/www/us/en/io/universal-serial-bus/usb-type-c-ucsi-spec.html).
+This is a sample driver that shows how to create a Windows USB Type-C port controller driver using the USB Connector Manager class extension driver (UcmCx). The sample is a driver for an embedded controller which is compliant with the [USB Type-C Connector System Software Interface (UCSI)](https://www.intel.com/content/www/us/en/io/universal-serial-bus/usb-type-c-ucsi-spec.html).
## Background reading - UcmCx documentation
-Start at the UcmCx documentation at [USB Type-C connector driver programming reference](https://msdn.microsoft.com/en-us/library/windows/hardware/mt188011(v=vs.85).aspx).
+Start at the UcmCx documentation at [USB Type-C connector driver programming reference](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/_usbref/#type-c-driver-reference).
## Note on UCSI
-Microsoft already provides an inbox UCSI driver, UcmUcsi.sys. This UcmCxUcsi sample driver is not identical to the inbox UCSI driver. Microsoft recommends that you use the inbox UcmUcsi.sys for your UCSI-compliant system rather than writing your own. This sample driver is meant for developers bringing up a UcmCx driver for their own non-UCSI platforms. For more information about the UCSI driver, reference [USB Type-C Connector System Software Interface (UCSI) driver](https://msdn.microsoft.com/en-us/library/windows/hardware/mt710944(v=vs.85).aspx).
+Microsoft already provides an inbox UCSI driver, UcmUcsi.sys. This UcmCxUcsi sample driver is not identical to the inbox UCSI driver. Microsoft recommends that you use the inbox UcmUcsi.sys for your UCSI-compliant system rather than writing your own. This sample driver is meant for developers bringing up a UcmCx driver for their own non-UCSI platforms. For more information about the UCSI driver, reference [USB Type-C Connector System Software Interface (UCSI) driver](https://docs.microsoft.com/windows-hardware/drivers/usbcon/ucsi).
This sample demonstrates the following:
- Registration with the USB Connector Manager (UCM) class extension driver.
+
- Initializing the port controller's Type-C and Power Delivery capabilities.
+
- Performing data and power role swaps requested by UCM
+
- Notifying UCM of Type-C and Power Delivery events on the connector.
## Customizing the sample for your port controller
@@ -49,10 +44,15 @@ In this sample, UCM-specific interactions are split apart from most of the UCSI-
The following files contain methods that interface with UcmCx.
- UcmCallbacks.cpp
- - Contains the implementations [EVT_UCM_CONNECTOR_SET_DATA_ROLE](https://msdn.microsoft.com/en-us/library/windows/hardware/mt187818(v=vs.85).aspx) and [EVT_UCM_CONNECTOR_SET_POWER_ROLE](https://msdn.microsoft.com/en-us/library/windows/hardware/mt187818(v=vs.85).aspx). These are callbacks from UCM which ask the client driver to perform role swaps.
+
+ - Contains the implementations [EVT_UCM_CONNECTOR_SET_DATA_ROLE](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ucmmanager/nc-ucmmanager-evt_ucm_connector_set_data_role) and [EVT_UCM_CONNECTOR_SET_POWER_ROLE](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ucmmanager/nc-ucmmanager-evt_ucm_connector_set_power_role). These are callbacks from UCM which ask the client driver to perform role swaps.
+
- UcmNotifications.cpp
- - Contains methods that communicate with UcmCx using the client driver support methods described in the [USB Type-C connector driver programming reference](https://msdn.microsoft.com/en-us/library/windows/hardware/mt188011(v=vs.85).aspx).
+
+ - Contains methods that communicate with UcmCx using the client driver support methods described in the [USB Type-C connector driver programming reference](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/_usbref/#type-c-driver-reference).
+
- Fdo.cpp
+
- FDO callbacks, functions, and types, most of which do not interface with UCM. However, the method `Fdo_EvtDeviceSelfManagedIoInit` contains the code segment which initializes the device with UCM.
### UCSI and WDF Interactions
@@ -60,12 +60,17 @@ The following files contain methods that interface with UcmCx.
The remainder of the files perform operations for UCSI and WDF, non-specific to UCM.
- Acpi.cpp
+
- ACPI method evaluation helper routines.
+
- Driver.cpp
+
- Entry point to the driver. Initializes the driver with WDF.
+
- Ppm.cpp
+
- Type-C Platform Policy Manager. Main interface to talk to the UCSI-compliant hardware.
## When to write a UcmCx client driver
-UcmCx is intended for system port controller drivers. If you are bringing up a USB Type-C peripheral, you do not need to write a USB Type-C specific driver; a regular USB client driver will suffice. Refer to [Developing Windows client drivers for USB devices](https://msdn.microsoft.com/en-us/library/windows/hardware/hh406260(v=vs.85).aspx) to determine what type of driver, if any, you need to write to make your USB device work with Windows. You may look at [Do I need to write a driver for my USB Type-C hardware?](https://blogs.msdn.microsoft.com/usbcoreblog/2016/06/20/do-i-need-to-write-a-driver-for-my-usb-type-c-hardware/) for a more detailed overview. \ No newline at end of file
+UcmCx is intended for system port controller drivers. If you are bringing up a USB Type-C peripheral, you do not need to write a USB Type-C specific driver; a regular USB client driver will suffice. Refer to [Developing Windows client drivers for USB devices](https://docs.microsoft.com/windows-hardware/drivers/usbcon/usb-driver-development-guide) to determine what type of driver, if any, you need to write to make your USB device work with Windows. You may look at [Do I need to write a driver for my USB Type-C hardware?](https://techcommunity.microsoft.com/t5/Microsoft-USB-Blog/Do-I-need-to-write-a-driver-for-my-USB-Type-C-hardware/ba-p/270876) for a more detailed overview.
diff --git a/usb/UcmCxUcsi/UcmCxUcsi.vcxproj b/usb/UcmCxUcsi/UcmCxUcsi.vcxproj
index c7371dd5..5245ee5d 100644
--- a/usb/UcmCxUcsi/UcmCxUcsi.vcxproj
+++ b/usb/UcmCxUcsi/UcmCxUcsi.vcxproj
@@ -90,13 +90,12 @@
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);.</AdditionalIncludeDirectories>
<WppEnabled>true</WppEnabled>
<WppRecorderEnabled>true</WppRecorderEnabled>
<WppScanConfigurationData>trace.h</WppScanConfigurationData>
<WppAlternateConfigurationFile>
</WppAlternateConfigurationFile>
- <WppAdditionalOptions>-scan:"$(UCM_INC_PATH)\$(UCM_VER_PATH)\UcmTraceEnums.h" -scan:"$(KMDF_INC_PATH)\$(KMDF_VER_PATH)\wdftraceenums.h" %(WppAdditionalOptions)</WppAdditionalOptions>
+ <WppAdditionalOptions>-scan:"$(UCM_INC_PATH)\$(UCM_VER_PATH)\UcmTraceEnums.h" -scan:"$(KMDF_INC_PATH_L)\$(KMDF_VER_PATH)\wdftraceenums.h" %(WppAdditionalOptions)</WppAdditionalOptions>
</ClCompile>
<DriverSign>
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
diff --git a/usb/UcmTcpciCxClientSample/README.md b/usb/UcmTcpciCxClientSample/README.md
index 8856e77f..6b0b602a 100644
--- a/usb/UcmTcpciCxClientSample/README.md
+++ b/usb/UcmTcpciCxClientSample/README.md
@@ -5,31 +5,30 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: UcmTcpciCx Port Controller Client Driver
- platform: KMDF
- language: cpp
- category: USB
- description: Demonstrates how to create a Windows USB Type-C port controller driver using the USB Connector Manager Type-C Port Controller Interface class extension driver (UcmTcpciCx).
- samplefwlink: https://go.microsoft.com/fwlink/p/?linkid=856745
---->
-
# UcmTcpciCx Port Controller Client Driver
-This is a skeleton sample driver that shows how to create a Windows USB Type-C port controller driver using the USB Connector Manager Type-C Port Controller Interface class extension driver (UcmTcpciCx). UcmTcpciCx is currently only availble using the Windows Insider program - documentation for UcmTcpciCx will be available at the next release of Windows.
+This is a skeleton sample driver that shows how to create a Windows USB Type-C port controller driver using the USB Connector Manager Type-C Port Controller Interface class extension driver (UcmTcpciCx). UcmTcpciCx is currently only available using the Windows Insider program - documentation for UcmTcpciCx will be available at the next release of Windows.
This sample demonstrates the following:
-- Registration with the UcmTcpci class extension driver (UcmTcpciCx).
-- Initializing the port controller's Type-C and Power Delivery capabilities.
-- Initializing the I2C communications channel to the port controller hardware.
-- Performing reads/writes over I2C.
-- Handling hardware requests from UcmTcpciCx.
-- Handling alerts from the port controller hardware and notifying UcmTcpciCx of the alert.
-- Power management.
-- Platform-level device reset in the case of an unresponsive I2C controller.
+- Registration with the UcmTcpci class extension driver (UcmTcpciCx)
+
+- Initializing the port controller's Type-C and Power Delivery capabilities
+
+- Initializing the I2C communications channel to the port controller hardware
+
+- Performing reads/writes over I2C
+
+- Handling hardware requests from UcmTcpciCx
+
+- Handling alerts from the port controller hardware and notifying UcmTcpciCx of the alert
+
+- Power management
+
+- Platform-level device reset in the case of an unresponsive I2C controller
## Customizing the sample for your port controller
@@ -37,7 +36,7 @@ The sample contains a number of comments prefaced with `// TODO` - review them a
## Note regarding Type-C port controller hardware
-This sample assumes a device that complies with the USB Type-C Port Controller Interface specification, Revision 1.0 (part of the [USB 3.1 specification download](http://usb.org/developers/docs)). Such a device uses a predefined register layout and an I2C communications channel.
+This sample assumes a device that complies with the USB Type-C Port Controller Interface specification, Revision 1.0 (part of the [USB 3.1 specification download](https://usb.org/documents)). Such a device uses a predefined register layout and an I2C communications channel.
If your port controller hardware is not exactly compliant with the specification, you will need to make additional modifications to the sample.
## Performing read/writes over I2C
@@ -47,7 +46,7 @@ If your port controller hardware is not compliant with the specification and doe
## When to write a UcmTcpciCx client driver
-UcmTcpciCx is intended for system port controller drivers. If you are bringing up a USB Type-C peripheral, you do not need to write a USB Type-C specific driver; a regular USB client driver will suffice. Refer to [Developing Windows client drivers for USB devices](https://msdn.microsoft.com/en-us/library/windows/hardware/hh406260(v=vs.85).aspx) to determine what type of driver, if any, you need to write to make your USB device work with Windows.
+UcmTcpciCx is intended for system port controller drivers. If you are bringing up a USB Type-C peripheral, you do not need to write a USB Type-C specific driver; a regular USB client driver will suffice. Refer to [Developing Windows client drivers for USB devices](https://docs.microsoft.com/windows-hardware/drivers/usbcon/usb-driver-development-guide) to determine what type of driver, if any, you need to write to make your USB device work with Windows.
## Testing Your Type-C Port Controller (TCPC) Implementation on Windows 10 with Raspberry Pi
@@ -55,49 +54,33 @@ UcmTcpciCx is intended for system port controller drivers. If you are bringing u
This section outlines a procedure for installing and testing a TCPCI implementation for Windows 10 on a Raspberry Pi computer running Windows 10 IoT Core. You will need a Raspberry Pi 2 or 3, your TCPC device, a USB-to-Serial converter for debugging, and 7 jumper wires to connect your TCPC to the Raspberry Pi (3 for the debug board, 4 for the TCPC).
-You will also need the Windows 10 IoT Core Insider Preview builds, the IoT tool set and WDK available for download on MSDN, and the UcmTcpciCxClientSample source code.
+You will also need the Windows 10 IoT Core Insider Preview builds, the IoT tool set, the [Windows Driver Kit (WDK)](https://docs.microsoft.com/windows-hardware/drivers/download-the-wdk), and the UcmTcpciCxClientSample source code.
### Setup
#### Operating System
-Download the latest available Windows 10 IoT Core Insider Preview image here:
-
-<https://www.microsoft.com/en-us/software-download/windowsiot>
-
-Install on your Raspberry Pi 2 or 3 per the following instructions:
-
-<https://developer.microsoft.com/en-us/windows/iot/GetStarted>
+Download the latest available [Windows 10 IoT Core Insider Preview](https://www.microsoft.com/software-download/windowsiot) and install on your Raspberry Pi 2 or 3 per the instructions at [Windows for Internet of Things](https://developer.microsoft.com/windows/iot).
Note, you will only need to complete the first two steps, “1 Get the tools” and “2 Setup your device” to proceed with the TCPC validation described here.
#### PowerShell Connection
-Connect to your Raspberry Pi via a PowerShell remote session. You will use this connection to setup the debugger and install your TCPCI driver package.
-
-<https://developer.microsoft.com/en-us/windows/iot/docs/powershell>
+Connect to your Raspberry Pi via a [PowerShell](https://docs.microsoft.com/windows/iot-core/connect-your-device/powershell) remote session. You will use this connection to setup the debugger and install your TCPCI driver package.
#### Windows Device Portal
-Open a connection to the Raspberry Pi via the Windows Device Portal. The portal provides a Device Manager view in which you will be able to inspect your TCPC device, as well as remote shutdown and reboot controls.
-
-<https://developer.microsoft.com/en-us/windows/iot/docs/deviceportal>
+Open a connection to the Raspberry Pi via the Windows [Device Portal](https://docs.microsoft.com/windows/iot-core/manage-your-device/DevicePortal). The portal provides a Device Manager view in which you will be able to inspect your TCPC device, as well as remote shutdown and reboot controls.
#### Kernel Debugger
-Setup the kernel debugger for your Raspberry Pi according to the instructions at the following location:
-
-<https://developer.microsoft.com/en-us/windows/iot/docs/windbg>
+Setup the kernel debugger for your Raspberry Pi according to the instructions at the [Windows Debugger (WinDbg)](https://docs.microsoft.com/windows/iot-core/manage-your-device/windowsdebugger) for IoT.
#### Connect TCPC Hardware
The following assumes an I2C implementation of your TCPC; if your device uses a different transport, ignore the I2C specific references and connect the transport as appropriate.
-First, shutdown and remove power from both the Raspberry Pi and your TCPC hardware. Once both boards are powered down, connect the four pins outlined below. Please refer to the GPIO pinout specification for the version of the Raspberry Pi platform you are using for the specific locations. Pin numbers referenced below are for the Raspberry Pi 2 Model B v1.1.
-
-<img src="https://az835927.vo.msecnd.net/sites/iot/Resources/images/PinMappings/RP2_Pinout.png" width="447" height="305" />
-
-**Figure 1:** Raspberry Pi 2 Model B v1.1 Pinout
+First, shutdown and remove power from both the Raspberry Pi and your TCPC hardware. Once both boards are powered down, connect the four pins outlined below. Please refer to the GPIO pinout specification for the version of the Raspberry Pi platform you are using for the specific locations.
Connect the following pins between your TCPC and the Raspberry Pi:
@@ -123,9 +106,7 @@ Edit the INF to set the device path and strings to desired custom values. Build
#### Install Driver Package
-Follow the instructions at the link below to create a driver package in the form of a CAB file for your custom UcmTcpciCx client driver:
-
-<https://developer.microsoft.com/en-us/windows/iot/docs/installpackage>
+[Create a driver package for IoT](https://docs.microsoft.com/windows-hardware/manufacture/iot/create-install-package) in the form of a CAB file for your custom UcmTcpciCx client driver.
Once you have generated the CAB file, see step 3 for instructions on installing the driver package on your Raspberry Pi via the PowerShell connection established earlier. After the package has been installed and the system has rebooted, there is still one more step to getting your driver to load: updating the ACPI tables to describe the device to the platform.
@@ -141,11 +122,9 @@ Open sample.asl provided in the UcmTcpciCxClientSample driver sample and modify
On a PC with the Windows 10 WDK installed run the following command on your updated ASL file:
-asl.exe sample.asl
+`asl.exe sample.asl`
-This will produce output file ACPITABL.dat. Copy this file to *C:\\Windows\\System32* on your Raspberry Pi device, and reboot. See the “Verification” section in the following link for more information on merging ACPI updates into an IoT image without a full UEFI build:
-
-<https://msdn.microsoft.com/en-us/windows/uwp/devices-sensors/enable-usermode-access>
+This will produce output file ACPITABL.dat. Copy this file to *C:\\Windows\\System32* on your Raspberry Pi device, and reboot. See the [Verification](https://docs.microsoft.com/windows/uwp/devices-sensors/enable-usermode-access#verification) section in *Enable usermode access to GPIO, I2C, and SPI* for more information on merging ACPI updates into an IoT image without a full UEFI build.
Once the Raspberry Pi has rebooted, your driver will load on the newly enumerated ACPI device node.
@@ -153,13 +132,9 @@ Once the Raspberry Pi has rebooted, your driver will load on the newly enumerate
#### USB Type-C Connection Exerciser
-The USB Type-C Connection Exerciser is a tool designed by Microsoft and manufactured by MCCI available for purchase at the link below:
-
-<http://www.mcci.com/mcci-v5/devtools/exerciser-type-c.html>
+The [MCCI Model 3101 Type-C Connection Exerciser](https://www.mcci.com/mcci-v5/devtools/exerciser-type-c.html) is a tool designed by Microsoft and manufactured by MCCI.
-The tools and instructions for deploying testing with this device are available for download on MSDN:
-
-<https://msdn.microsoft.com/en-us/library/windows/hardware/dn376875(v=vs.85).aspx>
+The tools and instructions for deploying testing with this device are available at [Testing USB hardware, drivers, and apps in Windows](https://docs.microsoft.com/windows-hardware/drivers/usbcon/usb-driver-testing-guide).
Suggested testing with the Connection Exerciser device is randomized connect/disconnect for long periods of time.
@@ -167,9 +142,7 @@ Suggested testing with the Connection Exerciser device is randomized connect/dis
The sample driver includes standard WDF logging which can be extracted via the kernel debugger with the following debugger command:
-```cmd
-!wdfkd.wdflogdump <driver name> -d
-```
+`!wdfkd.wdflogdump <driver name> -d`
Other useful driver traces are available from *UcmTcpciCx* and *UcmCx*.
@@ -193,30 +166,14 @@ UcmTcpciCx: 8DEAEA72-4C63-49A4-9B8B-25DA24DAE056
### Resources
-USB Type-C Port Controller Interface Specification (TCPCI), download as part of USB 3.1 Specification:
-
-<http://www.usb.org/developers/docs/>
-
-Raspberry Pi
-
-<https://www.raspberrypi.org/>
-
-<https://developer.microsoft.com/en-us/windows/iot/Docs/PinMappingsRPi.htm>
-
-Windows 10 IoT
-
-<https://www.microsoft.com/en-us/software-download/windowsiot>
-
-<https://developer.microsoft.com/en-us/windows/iot/>
-
-Windows Insider Preview WDK
+[USB Type-C Port Controller Interface Specification (TCPCI)](https://www.usb.org/documents) (download as part of USB 3.1 Specification)
-<https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewWDK>
+[Raspberry Pi](https://www.raspberrypi.org)
-Microsoft USB Test Tools
+[Windows 10 IoT Core Insider Preview](https://www.microsoft.com/software-download/windowsiot)
-<https://msdn.microsoft.com/en-us/library/windows/hardware/dn376873(v=vs.85).aspx>
+[Windows for Internet of Things](https://developer.microsoft.com/windows/iot)
-Tracelog Command Syntax
+[Windows Insider Preview WDK](https://www.microsoft.com/software-download/windowsinsiderpreviewWDK)
-<https://msdn.microsoft.com/en-us/library/windows/hardware/ff553012(v=vs.85).aspx> \ No newline at end of file
+[Tracelog Command Syntax](https://docs.microsoft.com/windows-hardware/drivers/devtest/tracelog-command-syntax)
diff --git a/usb/UcmUcsiAcpiSample/README.md b/usb/UcmUcsiAcpiSample/README.md
index 442ccdd8..a3686133 100644
--- a/usb/UcmUcsiAcpiSample/README.md
+++ b/usb/UcmUcsiAcpiSample/README.md
@@ -5,20 +5,12 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: UcmUcsiCx Client Driver
- platform: KMDF
- language: cpp
- category: USB
- description: Demonstrates how to create a Windows UCSI client UCSI class extension driver (UcmUcsiCx).
- samplefwlink: https://github.com/Microsoft/Windows-driver-samples/tree/master/usb/UcmUcsiAcpiSample
---->
-
# UcmUcsiCx ACPI Client Driver
-This is a sample driver that shows how to create a Windows USB Type-C port controller driver using the USB Connector Manager class extension driver (UcmCx). The sample is a driver for an embedded controller which is compliant with the [USB Type-C Connector System Software Interface (UCSI)](http://www.intel.com/content/www/us/en/io/universal-serial-bus/usb-type-c-ucsi-spec.html).
+This is a sample driver that shows how to create a Windows USB Type-C port controller driver using the USB Connector Manager class extension driver (UcmCx). The sample is a driver for an embedded controller which is compliant with the [USB Type-C Connector System Software Interface (UCSI)](https://www.intel.com/content/www/us/en/io/universal-serial-bus/usb-type-c-ucsi-spec.html).
## Note on UCM UCSI
@@ -27,8 +19,11 @@ Microsoft already provides an inbox UCSI Class extension (UcmUcsiCx.sys) and ACP
This sample demonstrates the following:
- Preparing connector collection with UcmUcsiCx
+
- Initializing Platform Policy Manager (or PPM) object with UcmUcsiCx
+
- Handling IOCTLs from UcmUcsiCx to send or get UCSI block
+
- Delivering PPM notifications to UcmUcsiCx
## Customizing the sample for your UCSI transport
@@ -44,8 +39,11 @@ In this sample, UCMUCSI-specific interactions are split apart from most of the U
The following files contain methods that interface with UcmUcsiCx.
- Ppm.cpp
+
- Contains bulk of interactions with UcmUcsiCx. Ppm::CreateAndInitialize which is called in the context of PrepareHardware PnP callback, creates connector collection with UcmUcsiCx by calling DDI UcmUcsiConnectorCollectionCreate and UcmUcsiConnectorCollectionAddConnector. The collection serves as a parameter to initialize PPM object with the class extension when the DDI UcmUcsiPpmCreate is called. Ppm::PpmNotificationCallback function calls DDI on the event of a PPM notification. Ppm::EvtIoDeviceControl contains the logic of handling IOCTLs from UcmUcsiCx.
+
- Fdo.cpp
+
- FDO callbacks, functions, and types, most of which do not interface with UcmUcsiCx. However, the method Fdo::CreateAndInitialize calls to UcmUcsiCx DDIs UcmUcsiDeviceInitInitialize and UcmUcsiDeviceInitialize.
#### UCSI and WDF Interactions
@@ -53,12 +51,17 @@ The following files contain methods that interface with UcmUcsiCx.
The remainder of the files perform operations for UCSI and WDF, non-specific to UCM.
- Acpi.cpp
+
- ACPI method evaluation helper routines.
+
- Driver.cpp
+
- Entry point to the driver. Initializes the driver with WDF.
+
- Ppm.cpp
+
- Type-C Platform Policy Manager. Main interface to talk to the UCSI-compliant hardware (via ACPI transport in this case).
## When to write a UcmUcsiCx client driver
-UcmUcsiCx is intended to abstract UCSI protocol from UCSI based driver support. If you have a system that implements PPM logic in an Embedded controller which is connected to the system over a non ACPI transport - e.g. USB, PCI, I2C or UART, it is advised that you write a UcmUcsiCx client driver that implements the necessary transport. Ideally, you would just need to replace Acpi class and implement your way to talk to the PPM. Please note, UcmUcsiCx client is the power policy owner. The class extension does handle S0 idling if you chose to enable it in the client driver. \ No newline at end of file
+UcmUcsiCx is intended to abstract UCSI protocol from UCSI based driver support. If you have a system that implements PPM logic in an Embedded controller which is connected to the system over a non ACPI transport - e.g. USB, PCI, I2C or UART, it is advised that you write a UcmUcsiCx client driver that implements the necessary transport. Ideally, you would just need to replace Acpi class and implement your way to talk to the PPM. Please note, UcmUcsiCx client is the power policy owner. The class extension does handle S0 idling if you chose to enable it in the client driver.
diff --git a/usb/UcmUcsiAcpiSample/UcmUcsiAcpiSample/UcmUcsiAcpiSample.vcxproj b/usb/UcmUcsiAcpiSample/UcmUcsiAcpiSample/UcmUcsiAcpiSample.vcxproj
index 879dc85b..d08edaa3 100644
--- a/usb/UcmUcsiAcpiSample/UcmUcsiAcpiSample/UcmUcsiAcpiSample.vcxproj
+++ b/usb/UcmUcsiAcpiSample/UcmUcsiAcpiSample/UcmUcsiAcpiSample.vcxproj
@@ -84,7 +84,7 @@
<ClCompile>
<WppEnabled>true</WppEnabled>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
- <DisableSpecificWarnings>4100;4189;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <DisableSpecificWarnings>4100;4189;5208;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile>
<Link>
@@ -97,7 +97,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WppEnabled>true</WppEnabled>
- <DisableSpecificWarnings>4100;4189;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <DisableSpecificWarnings>4100;4189;5208;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile>
<Link>
@@ -110,7 +110,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WppEnabled>true</WppEnabled>
- <DisableSpecificWarnings>4100;4189;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <DisableSpecificWarnings>4100;4189;5208;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>$(DDK_LIB_PATH)\UcmUcsi\1.0\UcmUcsiCxStub.lib;%(AdditionalDependencies)</AdditionalDependencies>
@@ -122,7 +122,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WppEnabled>true</WppEnabled>
- <DisableSpecificWarnings>4100;4189;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <DisableSpecificWarnings>4100;4189;5208;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>$(DDK_LIB_PATH)\UcmUcsi\1.0\UcmUcsiCxStub.lib;%(AdditionalDependencies)</AdditionalDependencies>
diff --git a/usb/kmdf_enumswitches/README.md b/usb/kmdf_enumswitches/README.md
index f196e2b4..21b460e6 100644
--- a/usb/kmdf_enumswitches/README.md
+++ b/usb/kmdf_enumswitches/README.md
@@ -5,35 +5,32 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Sample KMDF Bus Driver for OSR USB-FX2
- platform: KMDF
- language: cpp
- category: USB
- description: Demonstrates how to use KMDF as a bus driver using the OSR USB-FX2 device.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=618000
---->
-
# Sample KMDF Bus Driver for OSR USB-FX2
The kmdf\_enumswitches sample demonstrates how to use Kernel-Mode Driver Framework (KMDF) as a bus driver using the OSR USB-FX2 device.
-This sample is written for the OSR USB-FX2 Learning Kit. The specification for the device is at <http://www.osronline.com/hardware/OSRFX2_32.pdf>.
+This sample is written for the [OSR USB-FX2 Learning Kit](https://www.osronline.com/hardware/OSRFX2_32.pdf).
## Testing the Device
To test the device, follow these steps:
1. If you test signed your driver package, you must enable installation of test signed drivers on the target machine. To do so, either press F8 as the target machine comes up from a reboot, or specify **Bcdedit.exe -set TESTSIGNING ON** and reboot. If you use F8, the change only applies until the next reboot.
+
1. Plug in the OSR USB-FX-2 Learning Kit (must be version 2.00 or later).
+
1. In Device Manager, select **Update Driver Software**, **Browse my computer for driver software**, **Let me pick from a list of device drivers on my computer**, **Have Disk**. Navigate to the directory that contains your driver package and select the INF file.
+
1. After the driver installs, verify that the device appears under the **Sample Device** node in Device Manager.
+
1. Flip the switches on the OSR USB-FX-2 hardware board and watch the raw PDO entries appear and disappear under **Sample Device** in Device Manager.
+
1. Right-click a raw PDO entry, select **Properties**, and then click the **Events** tab. Under **Information**, examine the hardware ID for the PDO. It should be something like this:
- **6FDE7521-1B65-48ae-B628-80BE62016026}\OsrUsbFxRawPdo\6&227995e2&0&08**
+ `6FDE7521-1B65-48ae-B628-80BE62016026}\OsrUsbFxRawPdo\6&227995e2&0&08`
The last digit matches the number of the switch that you toggled.
@@ -42,20 +39,31 @@ To test the device, follow these steps:
Here is the overview of the device:
- Device is based on the development board supplied with the Cypress EZ-USB FX2 Development Kit (CY3681).
+
- Contains 1 interface and 3 endpoints (Interrupt IN, Bulk Out, Bulk IN).
+
- Firmware supports vendor commands to query or set LED Bar graph display, 7-segment LED display and query toggle switch states.
+
- Interrupt Endpoint:
- Sends an 8-bit value that represents the state of the switches.
+
- Sent on startup, resume from suspend, and whenever the switch pack setting changes.
+
- Firmware does not de-bounce the switch pack.
+
- One switch change can result in multiple bytes being sent.
+
- Bits are in the reverse order of the labels on the pack
For example, bit 0x80 is labeled 1 on the pack
- Bulk Endpoints are configured for loopback:
+
- Device moves data from IN endpoint to OUT endpoint.
+
- Device does not change the values of the data it receives nor does it internally create any data.
+
- Endpoints are always double buffered.
- - Maximum packet size depends on speed (64 Full speed, 512 High speed). \ No newline at end of file
+
+ - Maximum packet size depends on speed (64 Full speed, 512 High speed).
diff --git a/usb/kmdf_enumswitches/sys/driver.c b/usb/kmdf_enumswitches/sys/driver.c
index 275803e6..e9e99054 100644
--- a/usb/kmdf_enumswitches/sys/driver.c
+++ b/usb/kmdf_enumswitches/sys/driver.c
@@ -107,7 +107,7 @@ Return Value:
"OSRUSBFX2 Driver Sample - Driver Framework Edition.\n");
//
- // Initiialize driver config to control the attributes that
+ // Initialize driver config to control the attributes that
// are global to the driver. Note that framework by default
// provides a driver unload routine. If you create any resources
// in the DriverEntry and want to be cleaned in driver unload,
diff --git a/usb/kmdf_enumswitches/sys/kmdf_enumswitches.vcxproj b/usb/kmdf_enumswitches/sys/kmdf_enumswitches.vcxproj
index 883f548c..f8b0392d 100644
--- a/usb/kmdf_enumswitches/sys/kmdf_enumswitches.vcxproj
+++ b/usb/kmdf_enumswitches/sys/kmdf_enumswitches.vcxproj
@@ -99,18 +99,18 @@
<ClCompile>
<TreatWarningAsError>true</TreatWarningAsError>
<WarningLevel>Level4</WarningLevel>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\wdmsec.lib</AdditionalDependencies>
</Link>
<ResourceCompile>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ResourceCompile>
<Midl>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</Midl>
<DriverSign>
@@ -121,18 +121,18 @@
<ClCompile>
<TreatWarningAsError>true</TreatWarningAsError>
<WarningLevel>Level4</WarningLevel>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\wdmsec.lib</AdditionalDependencies>
</Link>
<ResourceCompile>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ResourceCompile>
<Midl>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</Midl>
<DriverSign>
@@ -143,18 +143,18 @@
<ClCompile>
<TreatWarningAsError>true</TreatWarningAsError>
<WarningLevel>Level4</WarningLevel>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\wdmsec.lib</AdditionalDependencies>
</Link>
<ResourceCompile>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ResourceCompile>
<Midl>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</Midl>
<DriverSign>
@@ -165,18 +165,18 @@
<ClCompile>
<TreatWarningAsError>true</TreatWarningAsError>
<WarningLevel>Level4</WarningLevel>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\wdmsec.lib</AdditionalDependencies>
</Link>
<ResourceCompile>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ResourceCompile>
<Midl>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</Midl>
<DriverSign>
diff --git a/usb/kmdf_fx2/README.md b/usb/kmdf_fx2/README.md
index d01e41ee..492cc8cf 100644
--- a/usb/kmdf_fx2/README.md
+++ b/usb/kmdf_fx2/README.md
@@ -5,109 +5,138 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Sample KMDF Function Driver for OSR USB-FX2
- platform: KMDF
- language: cpp
- category: USB
- description: Demonstrates how to use KMDF to perform bulk and interrupt data transfers to a USB device.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620313
---->
-
# Sample KMDF Function Driver for OSR USB-FX2
The kmdf\_fx2 sample is a Kernel-Mode Driver Framework (KMDF) driver for the OSR USB-FX2 device. It includes a test app and sample device metadata.
-In the Windows Driver Kit (WDK), the osrusbfx2 sample demonstrated how to perform bulk and interrupt data transfers to an USB device. The sample was written for the OSR USB-FX2 Learning Kit.
+In the Windows Driver Kit (WDK), the osrusbfx2 sample demonstrates how to perform bulk and interrupt data transfers to an USB device. The sample was written for the [OSR USB-FX2 Learning Kit](https://www.osronline.com/hardware/OSRFX2_32.pdf).
-The specification for the device is at <http://www.osronline.com/hardware/OSRFX2_32.pdf>. The driver and sample device metadata also work with the [Custom driver access](http://go.microsoft.com/fwlink/p/?LinkID=248288) sample.
+The driver and sample device metadata also works with the [Custom driver access](https://go.microsoft.com/fwlink/p/?linkid=2114373) sample.
## Universal Windows Driver Compliant
This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP.
-Overview
---------
+## Overview
Here is the overview of the device:
-- The device is based on the development board supplied with the Cypress EZ-USB FX2 Development Kit (CY3681).
-- It contains 1 interface and 3 endpoints (Interrupt IN, Bulk Out, Bulk IN).
-- Firmware supports vendor commands to query or set LED Bar graph display and 7-segment LED display, and to query toggle switch states.
-- Interrupt endpoint:
- - Sends an 8-bit value that represents the state of the switches.
- - Sent on startup, resume from suspend, and whenever the switch pack setting changes.
- - Firmware does not de-bounce the switch pack.
- - One switch change can result in multiple bytes being sent.
- - Bits are in the reverse order of the labels on the pack (for example, bit 0x80 is labeled 1 on the pack).
-- Bulk endpoints are configured for loopback:
- - The device moves data from IN endpoint to OUT endpoint.
- - The device does not change the values of the data it receives nor does it internally create any data.
- - Endpoints are always double buffered.
- - Maximum packet size depends on speed (64 full speed, 512 high speed).
-- Event Tracing for Windows (ETW) events:
- - Included osrusbfx2.man, which describes events added.
- - Three events are targeted to the event log:
- - Failure during the add device routine.
- - Failure to start the OSR device on a USB 1.1 controller.
- - Invocation of the "re-enumerate device" IOCTL.
- - Read/write start/stop events can be used to measure the time taken.
- - For more information, see Unified Tracing later in this document.
+- The device is based on the development board supplied with the Cypress EZ-USB FX2 Development Kit (CY3681).
+
+- It contains 1 interface and 3 endpoints (Interrupt IN, Bulk Out, Bulk IN).
+
+- Firmware supports vendor commands to query or set LED Bar graph display and 7-segment LED display, and to query toggle switch states.
+
+- Interrupt endpoint:
+
+ - Sends an 8-bit value that represents the state of the switches.
+
+ - Sent on startup, resume from suspend, and whenever the switch pack setting changes.
+
+ - Firmware does not de-bounce the switch pack.
+
+ - One switch change can result in multiple bytes being sent.
+
+ - Bits are in the reverse order of the labels on the pack (for example, bit 0x80 is labeled 1 on the pack).
+
+- Bulk endpoints are configured for loopback:
+
+ - The device moves data from IN endpoint to OUT endpoint.
+
+ - The device does not change the values of the data it receives nor does it internally create any data.
-Code tour
----------------
+ - Endpoints are always double buffered.
-**usb\\kmdf\_fx2\\driver**
+ - Maximum packet size depends on speed (64 full speed, 512 high speed).
+
+- Event Tracing for Windows (ETW) events:
+
+ - Included osrusbfx2.man, which describes events added.
+
+ - Three events are targeted to the event log:
+
+ - Failure during the add device routine.
+
+ - Failure to start the OSR device on a USB 1.1 controller.
+
+ - Invocation of the "re-enumerate device" IOCTL.
+
+ - Read/write start/stop events can be used to measure the time taken.
+
+ - For more information, see Unified Tracing later in this document.
+
+## Code tour
+
+### usb\\kmdf\_fx2\\driver
This directory contains driver code that demonstrates the following functionality:
-- Loads the driver and responds to PnP and Power events. You can install, uninstall, disable, enable, suspend, and resume the system.
-- Creates a context with the WDFDEVICE object.
-- Initializes the USB device by registering a *EvtPrepareHardware* callback.
-- Marks the interface restricted so that it can be accessed by a privileged UWP device app.
-- Creates a default parallel queue to receive an IOCTL request to set bar graph display.
-- Retrieves memory handle from the requests and uses it to send a vendor command to the USB device.
-- Registers read and write events on the default queue.
-- Retrieves memory from read and write requests, formats the requests, and sends it to a USB target.
-- Creates two separate sequential queues and configures them to dispatch read and write requests directly. (*\*kmdf\_fx2 only*)
-- Enables wait-wake and selective suspend support. (*\*kmdf\_fx2 only*)
-- Configures a USB target continuous reader to read toggle switch states asynchronously from the interrupt endpoint. (*\*kmdf\_fx2 only*)
-- Supports additional IOCTLs to get and set the 7-segment display and toggle switches, and to reset and re-enumerate the device. (*\*kmdf\_fx2 only*)
-- Creates ETW provider to log two events to the event log, and read/write start stop events. (*\*kmdf\_fx2 only*)
-- WPP tracing.
+- Loads the driver and responds to PnP and Power events. You can install, uninstall, disable, enable, suspend, and resume the system.
+
+- Creates a context with the WDFDEVICE object.
-**usb\\kmdf\_fx2\\exe**
+- Initializes the USB device by registering a *EvtPrepareHardware* callback.
+
+- Marks the interface restricted so that it can be accessed by a privileged UWP device app.
+
+- Creates a default parallel queue to receive an IOCTL request to set bar graph display.
+
+- Retrieves memory handle from the requests and uses it to send a vendor command to the USB device.
+
+- Registers read and write events on the default queue.
+
+- Retrieves memory from read and write requests, formats the requests, and sends it to a USB target.
+
+- Creates two separate sequential queues and configures them to dispatch read and write requests directly. (*\*kmdf\_fx2 only*)
+
+- Enables wait-wake and selective suspend support. (*\*kmdf\_fx2 only*)
+
+- Configures a USB target continuous reader to read toggle switch states asynchronously from the interrupt endpoint. (*\*kmdf\_fx2 only*)
+
+- Supports additional IOCTLs to get and set the 7-segment display and toggle switches, and to reset and re-enumerate the device. (*\*kmdf\_fx2 only*)
+
+- Creates ETW provider to log two events to the event log, and read/write start stop events. (*\*kmdf\_fx2 only*)
+
+- WPP tracing
+
+### usb\\kmdf\_fx2\\exe
This directory contains a test application that can be used to drive the KMDF driver and FX2 device.
-**usb\\kmdf\_fx2\\deviceMetadata**
+### usb\\kmdf\_fx2\\deviceMetadata
-This directory contains the device metadata package for the sample. You must copy the device metadata to the system before installing the device. For information on how to update and deploy device metadata, see the [Custom driver access sample](http://go.microsoft.com/fwlink/p/?LinkID=248288).
+This directory contains the device metadata package for the sample. You must copy the device metadata to the system before installing the device. For information on how to update and deploy device metadata, see the [Custom driver access](https://go.microsoft.com/fwlink/p/?linkid=2114373) sample.
-Testing the driver
-------------------
+## Testing the driver
-You can use the [Custom driver access](http://go.microsoft.com/fwlink/p/?LinkID=248288) sample as a testing method.
+You can use the [Custom driver access](https://go.microsoft.com/fwlink/p/?linkid=2114373) sample as a testing method.
The sample also includes a test application, osrusbfx2.exe, that you can use to test the device. This console application enumerates the interface registered by the driver and opens the device to send read, write, or IOCTL requests based on the command line options.
Usage for Read/Write test:
-- -r [*n*], where *n* is number of bytes to read.
-- -w [*n*], where *n* is number of bytes to write.
-- -c [*n*], where *n* is number of iterations (default = 1).
-- -v, shows verbose read data.
-- -p, plays with Bar Display, Dip Switch, 7-Segment Display.
-- -a, performs asynchronous I/O operation.
-- -u, dumps USB configuration and pipe information.
+- -r [*n*], where *n* is number of bytes to read.
-**Playing with the 7 segment display, toggle switches, and bar graph display**
+- -w [*n*], where *n* is number of bytes to write.
+
+- -c [*n*], where *n* is number of iterations (default = 1).
+
+- -v, shows verbose read data.
+
+- -p, plays with Bar Display, Dip Switch, 7-Segment Display.
+
+- -a, performs asynchronous I/O operation.
+
+- -u, dumps USB configuration and pipe information.
+
+### Playing with the 7 segment display, toggle switches, and bar graph display
Use the command, **osrusbfx2.exe -p** options 1-9, to set and clear bar graph display, set and get 7 segment state, and read the toggle switch states. The following shows the function options:
-```
+```cmd
1. Light bar
2. Clear bar
3. Light entire bar graph
@@ -125,41 +154,41 @@ Use the command, **osrusbfx2.exe -p** options 1-9, to set and clear bar graph di
Selection:
```
-**Reset and re-enumerate the device**
+### Reset and re-enumerate the device
Use the command, osrusbfx2.exe -p with option 10 and 11, to either reset the device or re-enumerate the device.
-**Read and write to bulk endpoints**
+### Read and write to bulk endpoints
The following commands send read and write requests to the device's bulk endpoint.
-- `osrusbfx2.exe -r 64`
+- `osrusbfx2.exe -r 64`
The preceding command reads 64 bytes to the bulk IN endpoint.
-- `osrusbfx2.exe -w 64 `
+- `osrusbfx2.exe -w 64`
The preceding command writes 64 bytes to the bulk OUT endpoint.
-- `osrusbfx2.exe -r 64 -w 64 -c 100 -v`
+- `osrusbfx2.exe -r 64 -w 64 -c 100 -v`
The preceding command first writes 64 bytes of data to bulk OUT endpoint (Pipe 1), then reads 64 bytes from bulk IN endpoint (Pipe 2), and then compares the read buffer with write buffer to see if they match. If the buffer contents match, it repeats this operation 100 times.
-- `osrusbfx2.exe -a`
+- `osrusbfx2.exe -a`
The preceding command reads and writes to the device asynchronously in an infinite loop.
The bulk endpoints are double buffered. Depending on the operational speed (full or high), the buffer size is either 64 bytes or 512 bytes, respectively. A request to read data does not complete if the buffers are empty. If the buffers are full, a request to write data does not complete until the buffers are emptied. When you are doing a synchronous read, make sure the endpoint buffer has data (for example, when you send a 512 bytes write request to the device operating in full speed mode). Because the endpoints are double buffered, the total buffer capacity is 256 bytes. The first 256 bytes fills the buffer, and the write request waits in the USB stack until the buffers are emptied. If you run another instance of the application to read 512 bytes of data, both write and read requests complete successfully.
-**Displaying descriptors**
+### Displaying descriptors
The following command displays all the descriptors and endpoint information.
-**osrusbfx2.exe -u**
+`osrusbfx2.exe -u`
If the device is operating in high speed mode, you will get the following information:
-```
+```cmd
===================
USB_CONFIGURATION_DESCRIPTOR
@@ -230,9 +259,9 @@ bEndpointAddress= 0x6 ( OUTPUT )
bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )
-wMaxPacketSize= 0x200,
+wMaxPacketSize= 0x200,
-decimal 512 bInterval = 0x0,
+decimal 512 bInterval = 0x0,
decimal 0
@@ -272,7 +301,7 @@ iConfiguration = 0x3, decimal 3
bmAttributes = 0xa0 ( USB_CONFIG_BUS_POWERED )
-MaxPower = 0x32, decimal 50
+MaxPower = 0x32, decimal 50
-----------------------------
@@ -343,8 +372,7 @@ wMaxPacketSize= 0x40, decimal 64
bInterval = 0x0, decimal 0
```
-Unified tracing
----------------
+## Unified tracing
To view events the provider manifest must be installed. As part of the installation, from an elevated prompt run the following: `wevtutil im osrusbfx2.man`
@@ -352,34 +380,36 @@ Registering the manifest sets up the appropriate paths where the system can find
To trace, you can use the in-box tools, logman and tracerpt, or download XPerf (Windows Performance Toolkit) from Microsoft.
-**Using in-box tools**
+### Using in-box tools
+
+#### To start/stop the trace by using logman
+
+1. Start tracing by using the following command:
-**To start/stop the trace by using logman:**
+ `logman start sample -o osrusbfx2.etl -ets -p OSRUSBFX2`
-1. Start tracing by using the following command:
+1. Generate activity through the osrusbfx2 test application, such as `osrusbfx2.exe -a`.
- `logman start sample -o osrusbfx2.etl -ets -p OSRUSBFX2`
+1. Stop tracing by using the following command:
-2. Generate activity through the osrusbfx2 test application, such as `osrusbfx2.exe -a`.
-3. Stop tracing by using the following command:
+ `Logman stop sample`
- `Logman stop sample`
+1. View the trace file using tracerpt:
-4. View the trace file using tracerpt:
+ `tracerpt -of csv OSRUSBFX2.etl`
- `tracerpt -of csv OSRUSBFX2.etl `
+#### To start/stop the trace by using Xperf (Windows Performance Toolkit)
-**To start/stop the trace by using Xperf (Windows Performance Toolkit):**
+1. Start tracing by using the following command:
-1. Start tracing by using the following command:
+ `xperf -start sample -f osrusbfx2.etl -on OSRUSBFX2`
- `xperf -start sample -f osrusbfx2.etl -on OSRUSBFX2`
+1. Generate activity through the osrusbfx2 test application, such as `osrusbfx2.exe -a`.
-2. Generate activity through the osrusbfx2 test application, such as `osrusbfx2.exe -a`.
-3. Stop tracing by using the following command:
+1. Stop tracing by using the following command:
- `xperf -stop sample`
+ `xperf -stop sample`
-4. View the trace file using Xperf:
+1. View the trace file using Xperf:
- `xperfview OSRUSBFX2.etl`
+ `xperfview OSRUSBFX2.etl`
diff --git a/usb/kmdf_fx2/driver/driver.c b/usb/kmdf_fx2/driver/driver.c
index 2c73cab2..25be851e 100644
--- a/usb/kmdf_fx2/driver/driver.c
+++ b/usb/kmdf_fx2/driver/driver.c
@@ -136,7 +136,7 @@ Return Value:
EventRegisterOSRUSBFX2();
//
- // Initiialize driver config to control the attributes that
+ // Initialize driver config to control the attributes that
// are global to the driver. Note that framework by default
// provides a driver unload routine. If you create any resources
// in the DriverEntry and want to be cleaned in driver unload,
diff --git a/usb/kmdf_fx2/driver/osrusbfx2.vcxproj b/usb/kmdf_fx2/driver/osrusbfx2.vcxproj
index 747de89e..3195fa9e 100644
--- a/usb/kmdf_fx2/driver/osrusbfx2.vcxproj
+++ b/usb/kmdf_fx2/driver/osrusbfx2.vcxproj
@@ -115,17 +115,17 @@
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ResourceCompile>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ResourceCompile>
<ClCompile>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<TreatWarningAsError>true</TreatWarningAsError>
<WarningLevel>Level4</WarningLevel>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ClCompile>
<Midl>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</Midl>
<Link>
@@ -137,17 +137,17 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ResourceCompile>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ResourceCompile>
<ClCompile>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<TreatWarningAsError>true</TreatWarningAsError>
<WarningLevel>Level4</WarningLevel>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ClCompile>
<Midl>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</Midl>
<Link>
@@ -159,17 +159,17 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ResourceCompile>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ResourceCompile>
<ClCompile>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<TreatWarningAsError>true</TreatWarningAsError>
<WarningLevel>Level4</WarningLevel>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ClCompile>
<Midl>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</Midl>
<Link>
@@ -181,17 +181,17 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ResourceCompile>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ResourceCompile>
<ClCompile>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<TreatWarningAsError>true</TreatWarningAsError>
<WarningLevel>Level4</WarningLevel>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</ClCompile>
<Midl>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
</Midl>
<Link>
diff --git a/usb/ufxclientsample/README.md b/usb/ufxclientsample/README.md
index a19fc454..1030135c 100644
--- a/usb/ufxclientsample/README.md
+++ b/usb/ufxclientsample/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: USB Function Client Driver
- platform: KMDF
- language: cpp
- category: USB
- description: Demonstrates how to create a Windows USB function controller driver using the USB function class extension driver (UFX).
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620315
---->
-
# USB Function Client Driver
This is a skeleton sample driver that shows how to create a Windows USB function controller driver using the USB function class extension driver (UFX).
@@ -23,10 +15,15 @@ This is a skeleton sample driver that shows how to create a Windows USB function
This sample demonstrates the following:
- Registration with the UFX class extension driver
+
- Handling USB transfers
+
- Handling function controller events
+
- Handling attach and detach notifications
+
- Handling charger/port detection
+
- Power management
## Operating system requirements
@@ -39,4 +36,4 @@ This sample is not a functional driver. It is a skeleton driver intended to illu
## Installation Note
-Installation on Windows 10 Mobile requires the creation of a package. To properly interact with the USB UI on Windows 10 Mobile, the package must include a Security Element that specifies the ID_CAP_USB capability with DEVICE_READ and DEVICE_WRITE rights. \ No newline at end of file
+Installation on Windows 10 Mobile requires the creation of a package. To properly interact with the USB UI on Windows 10 Mobile, the package must include a Security Element that specifies the ID_CAP_USB capability with DEVICE_READ and DEVICE_WRITE rights.
diff --git a/usb/ufxclientsample/device.c b/usb/ufxclientsample/device.c
index 3aa46c4c..8a7580bf 100644
--- a/usb/ufxclientsample/device.c
+++ b/usb/ufxclientsample/device.c
@@ -535,8 +535,8 @@ Arguments:
DeviceContext = UfxDeviceGetContext(ControllerContext->UfxDevice);
#pragma prefast(suppress:6014, "Memory allocation is expected")
- HardwareFailureContext = ExAllocatePoolWithTag(
- NonPagedPoolNx,
+ HardwareFailureContext = ExAllocatePool2(
+ POOL_FLAG_NON_PAGED,
sizeof(HARDWARE_FAILURE_CONTEXT),
UFX_CLIENT_TAG);
diff --git a/usb/umdf2_fx2/README.md b/usb/umdf2_fx2/README.md
index 9868d69e..d93a311a 100644
--- a/usb/umdf2_fx2/README.md
+++ b/usb/umdf2_fx2/README.md
@@ -5,26 +5,18 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Sample Function Driver for OSR USB-FX2 (UMDF Version 2)
- platform: UMDF2
- language: cpp
- category: USB
- description: Demonstrates a UMDF version 2 driver for the OSR USB-FX2 device.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=618003
---->
-
# Sample Function Driver for OSR USB-FX2 (UMDF Version 2)
The umdf2\_fx2 sample is a User-Mode Driver Framework (UMDF) version 2 driver for the OSR USB-FX2 device.
-The specification for the device can be found at <http://www.osronline.com/hardware/OSRFX2_32.pdf>. The driver and sample device metadata also work with the [Custom driver access](http://go.microsoft.com/fwlink/p/?LinkID=248288) sample.
+ For more information, see the specification for the [OSR USB FX-2 Learning Kit](https://www.osronline.com/hardware/OSRFX2_32.pdf). The driver and sample device metadata also work with the [Custom driver access](https://go.microsoft.com/fwlink/p/?linkid=2114373) sample.
## Related technologies
-[User-Mode Driver Framework](http://msdn.microsoft.com/en-us/library/windows/hardware/ff560456)
+[User-Mode Driver Framework](https://docs.microsoft.com/windows-hardware/drivers/wdf/getting-started-with-umdf-version-2)
## Run the sample
@@ -34,26 +26,31 @@ The process of moving the driver package to the target computer and installing t
### Automatic deployment (FX2 board)
-Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/).
+Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Provision a computer for driver deployment and testing (WDK 10)](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1).
1. Plug in the OSR USB-FX2 board to the target computer.
+
1. On the host computer, in Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
+
1. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Install and Verify**. Click **OK**.
+
1. On the **Build** menu, choose **Deploy Package** or **Build Solution**.
### Manual deployment (FX2 board)
-Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
+Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](https://docs.microsoft.com/windows-hardware/drivers/devtest/devcon) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\umdf2\_fx2).
+
1. Plug in the OSR USB-FX2 board to the target computer. Open a Command Prompt window and enter **dvmgmt** to open Device Manager. In Device Manager, locate the node for the OSR USB-FX2 board. Right click the node, and choose **Properties**. In the **Details** tab, under **Properties**, choose **Hardware Ids**. Note the hardware IDs listed for your FX2 board. One of these IDs should match one of the IDs in the osrusbfx2um.inf file. For example, Device Manager might show an ID of USB\\VID\_0547&PID\_1002, which matches one of the IDs in the [Microsoft.*xxx*] section of osrusbfx2um.inf.
+
1. On the target computer, open a Command Prompt window as Administrator. Navigate to your driver package folder, and enter this command:
- **devcon update osrusbfx2um.inf"***HardwareID***"**
+ `devcon update osrusbfx2um.inf"***HardwareID***"`
where *HardwareID* is the hardware ID of your FX2 board. Here is an example:
- **devcon update osrusbfx2um.inf "USB\\VID\_0547&PID\_1002"**
+ `devcon update osrusbfx2um.inf "USB\VID_0547&PID_1002"`
## View the driver for the OSR USB-FX2 board in Device Manager
@@ -65,6 +62,6 @@ In Device Manager, on the **View** menu, choose **Devices by connection**. Locat
As an alternative to building the driver sample in Visual Studio, you can build it in a Visual Studio Command Prompt window. In Visual Studio, on the **Tools** menu, choose **Visual Studio Command Prompt**. In the Visual Studio Command Prompt window, navigate to the folder that has the solution file, umdf2echo.sln. Use the MSBuild command to build the solution. Here is an example:
- **msbuild /p:configuration=Win8 Release /p:platform=Win32 umdf2\_fx2.sln**
+`msbuild /p:configuration=Win8 Release /p:platform=Win32 umdf2_fx2.sln`
-For more information about using MSBuild to build a driver package, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644). \ No newline at end of file
+For more information about using MSBuild to build a driver package, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver).
diff --git a/usb/umdf2_fx2/driver/driver.c b/usb/umdf2_fx2/driver/driver.c
index fb00f9de..7ec5f5df 100644
--- a/usb/umdf2_fx2/driver/driver.c
+++ b/usb/umdf2_fx2/driver/driver.c
@@ -116,7 +116,7 @@ Return Value:
EventRegisterOSRUSBFX2();
//
- // Initiialize driver config to control the attributes that
+ // Initialize driver config to control the attributes that
// are global to the driver. Note that framework by default
// provides a driver unload routine. If you create any resources
// in the DriverEntry and want to be cleaned in driver unload,
diff --git a/usb/umdf2_fx2/driver/osrusbfx2um.vcxproj b/usb/umdf2_fx2/driver/osrusbfx2um.vcxproj
index a4209763..ac9dc9b7 100644
--- a/usb/umdf2_fx2/driver/osrusbfx2um.vcxproj
+++ b/usb/umdf2_fx2/driver/osrusbfx2um.vcxproj
@@ -130,6 +130,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\WppRecorderUM.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -151,6 +154,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\WppRecorderUM.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -172,6 +178,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\WppRecorderUM.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -193,6 +202,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\WppRecorderUM.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<Inf Include="osrusbfx2um.inx" />
@@ -207,4 +219,4 @@
<ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-</Project>
+</Project> \ No newline at end of file
diff --git a/usb/umdf_filter_kmdf/README.md b/usb/umdf_filter_kmdf/README.md
index 3ae7dba5..4f7d0e41 100644
--- a/usb/umdf_filter_kmdf/README.md
+++ b/usb/umdf_filter_kmdf/README.md
@@ -5,59 +5,74 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Sample UMDF Filter above KMDF Function Driver for OSR USB-FX2 (UMDF Version 1)
- platform: KMDF
- language: cpp
- category: USB
- description: Demonstrates how to load a UMDF filter driver as an upper filter driver above the kmdf_fx2 sample driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620316
---->
-
# Sample UMDF Filter above KMDF Function Driver for OSR USB-FX2 (UMDF Version 1)
The umdf\_filter\_kmdf sample demonstrates how to load a UMDF filter driver as an upper filter driver above the kmdf\_fx2 sample driver.
-The sample includes Event Tracing for Windows (ETW) tracing support, and is written for the OSR USB-FX2 Learning Kit. The specification for the device is at <http://www.osronline.com/hardware/OSRFX2_32.pdf>.
+The sample includes Event Tracing for Windows (ETW) tracing support, and is written for the [OSR USB-FX2 Learning Kit](https://www.osronline.com/hardware/OSRFX2_32.pdf0.
## Build the sample
The default Solution build configuration is **Debug** and **Win32**.
1. Open the driver project or solution in Visual Studio (find *filtername*.sln or *filtername*.vcxproj).
+
1. Right-click the solution in the **Solutions Explorer** and select **Configuration Manager**.
+
1. From the **Configuration Manager**, select the **Active Solution Configuration** (for example, Debug or Release) and the **Active Solution Platform** (for example, Win32) that correspond to the type of build you are interested in.
+
1. From the **Build** menu, click **Build Solution** (Ctrl+Shift+B).
## Overview
- The device is based on the development board supplied with the Cypress EZ-USB FX2 Development Kit (CY3681).
+
- It contains 1 interface and 3 endpoints (Interrupt IN, Bulk Out, Bulk IN).
+
- Firmware supports vendor commands to query or set LED Bar graph display and 7-segment LED display, and to query toggle switch states.
+
- Interrupt Endpoint:
-- Sends an 8-bit value that represents the state of the switches.
- - Sent on startup, resume from suspend, and whenever the switch pack setting changes.
- - Firmware does not de-bounce the switch pack.
- - One switch change can result in multiple bytes being sent.
- - Bits are in the reverse order of the labels on the pack (for example, bit 0x80 is labeled 1 on the pack).
+
+ - Sends an 8-bit value that represents the state of the switches.
+
+ - Sent on startup, resume from suspend, and whenever the switch pack setting changes.
+
+ - Firmware does not de-bounce the switch pack.
+
+ - One switch change can result in multiple bytes being sent.
+
+ - Bits are in the reverse order of the labels on the pack (for example, bit 0x80 is labeled 1 on the pack).
+
- Bulk Endpoints are configured for loopback:
-- The device moves data from IN endpoint to OUT endpoint.
- - The device does not change the values of the data it receives nor does it internally create any data.
- - Endpoints are always double buffered.
- - Maximum packet size depends on speed (64 full speed, 512 high speed).
+
+ - The device moves data from IN endpoint to OUT endpoint.
+
+ - The device does not change the values of the data it receives nor does it internally create any data.
+
+ - Endpoints are always double buffered.
+
+ - Maximum packet size depends on speed (64 full speed, 512 high speed).
+
- ETW events:
-- Included osrusbfx2.man, which describes events added.
- - Three events are targeted to the event log:
- - Failure during the add device routine.
- - Failure to start the OSR device on a USB 1.1 controller.
- - Invocation of the "re-enumerate device" IOCTL.
- - Read/write start/stop events can be used to measure the time taken.
+
+ - Included osrusbfx2.man, which describes events added.
+
+ - Three events are targeted to the event log:
+
+ - Failure during the add device routine.
+
+ - Failure to start the OSR device on a USB 1.1 controller.
+
+ - Invocation of the "re-enumerate device" IOCTL.
+
+ - Read/write start/stop events can be used to measure the time taken.
## Testing the driver
-You can test this sample either by using the [Custom driver access](http://go.microsoft.com/fwlink/p/?LinkID=248288) sample application, or by using the osrusbfx2.exe test application. For information on how to build and use the osrusbfx2.exe application, see the test instructions for the [kmdf\_fx2](http://msdn.microsoft.com/en-us/library/windows/hardware/) sample.
+You can test this sample either by using the [Custom driver access](https://go.microsoft.com/fwlink/p/?linkid=2114373) sample application, or by using the osrusbfx2.exe test application. For information on how to build and use the osrusbfx2.exe application, see the test instructions for the [kmdf\_fx2](https://docs.microsoft.com/samples/microsoft/windows-driver-samples/sample-kmdf-function-driver-for-osr-usb-fx2/) sample.
## Code tour
diff --git a/usb/umdf_filter_kmdf/kmdf_driver/driver.c b/usb/umdf_filter_kmdf/kmdf_driver/driver.c
index 2c73cab2..25be851e 100644
--- a/usb/umdf_filter_kmdf/kmdf_driver/driver.c
+++ b/usb/umdf_filter_kmdf/kmdf_driver/driver.c
@@ -136,7 +136,7 @@ Return Value:
EventRegisterOSRUSBFX2();
//
- // Initiialize driver config to control the attributes that
+ // Initialize driver config to control the attributes that
// are global to the driver. Note that framework by default
// provides a driver unload routine. If you create any resources
// in the DriverEntry and want to be cleaned in driver unload,
diff --git a/usb/umdf_filter_umdf/README.md b/usb/umdf_filter_umdf/README.md
index 5d49b79d..b16d8686 100644
--- a/usb/umdf_filter_umdf/README.md
+++ b/usb/umdf_filter_umdf/README.md
@@ -5,47 +5,52 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Sample UMDF Filter above UMDF Function Driver for OSR USB-FX2 (UMDF Version 1)
- platform: UMDF1
- language: cpp
- category: USB
- description: Demonstrates how to load a UMDF filter driver as an upper filter driver above the umdf_fx2 sample driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=618001
---->
-
# Sample UMDF Filter above UMDF Function Driver for OSR USB-FX2 (UMDF Version 1)
The umdf\_filter\_umdf sample demonstrates how to load a User-Mode Driver Framework (UMDF) filter driver as an upper filter driver above the umdf\_fx2 sample driver.
-This sample is written for the OSR USB-FX2 Learning Kit. The specification for the device is at <http://www.osronline.com/hardware/OSRFX2_32.pdf>.
+This sample is written for the [OSR USB-FX2 Learning Kit](https://www.osronline.com/hardware/OSRFX2_32.pdf).
## Overview
- The device is based on the development board supplied with the Cypress EZ-USB FX2 Development Kit (CY3681).
+
- It contains 1 interface and 3 endpoints (Interrupt IN, Bulk Out, Bulk IN).
+
- Firmware supports vendor commands to query or set LED Bar graph display and 7-segment LED display, and to query toggle switch states.
+
- Interrupt Endpoint:
-- Sends an 8-bit value that represents the state of the switches.
- - Sent on startup, resume from suspend, and whenever the switch pack setting changes.
- - Firmware does not de-bounce the switch pack.
- - One switch change can result in multiple bytes being sent.
- - Bits are in the reverse order of the labels on the pack (for example, bit 0x80 is labeled 1 on the pack).
+
+ - Sends an 8-bit value that represents the state of the switches.
+
+ - Sent on startup, resume from suspend, and whenever the switch pack setting changes.
+
+ - Firmware does not de-bounce the switch pack.
+
+ - One switch change can result in multiple bytes being sent.
+
+ - Bits are in the reverse order of the labels on the pack (for example, bit 0x80 is labeled 1 on the pack).
+
- Bulk Endpoints are configured for loopback:
-- The device moves data from IN endpoint to OUT endpoint.
- - The device does not change the values of the data it receives nor does it internally create any data.
- - Endpoints are always double buffered.
- - Maximum packet size depends on speed (64 full speed, 512 high speed).
+
+ - The device moves data from IN endpoint to OUT endpoint.
+
+ - The device does not change the values of the data it receives nor does it internally create any data.
+
+ - Endpoints are always double buffered.
+
+ - Maximum packet size depends on speed (64 full speed, 512 high speed).
## Testing the driver
-You can test this sample either by using the [Custom driver access](http://go.microsoft.com/fwlink/p/?LinkID=248288) sample application, or by using the osrusbfx2.exe test application. For information on how to build and use the osrusbfx2.exe application, see the test instructions for the [umdf\_fx2](http://msdn.microsoft.com/en-us/library/windows/hardware/) sample.
+You can test this sample either by using the [Custom driver access](https://go.microsoft.com/fwlink/p/?linkid=2114373) sample application, or by using the osrusbfx2.exe test application. For information on how to build and use the osrusbfx2.exe application, see the test instructions for the [umdf\_fx2](https://docs.microsoft.com/samples/microsoft/windows-driver-samples/sample-umdf-filter-above-umdf-function-driver-for-osr-usb-fx2-umdf-version-1/) sample.
## Sample Contents
| Folder | Description |
| --- | --- |
| usb\umdf_filter_umdf\umdf_driver | This directory contains source code for the umdf_fx2 sample driver. |
-| usb\umdf_filter_umdf\umdf_filter | This directory contains the UMDF filter driver. | \ No newline at end of file
+| usb\umdf_filter_umdf\umdf_filter | This directory contains the UMDF filter driver. |
diff --git a/usb/umdf_fx2/README.md b/usb/umdf_fx2/README.md
index f653a27c..f95374f2 100644
--- a/usb/umdf_fx2/README.md
+++ b/usb/umdf_fx2/README.md
@@ -5,22 +5,14 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Sample UMDF Function Driver for OSR USB-FX2 (UMDF version 1)
- platform: UMDF1
- language: cpp
- category: USB
- description: A UMDF driver for the OSR USB-FX2 device that includes a test application, sample device metadata, and supports impersonation and idle power down.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=618002
---->
-
# Sample UMDF Function Driver for OSR USB-FX2 (UMDF Version 1)
The umdf\_fx2 sample is a User-Mode Driver Framework (UMDF) driver for the OSR USB-FX2 device. It includes a test app and sample device metadata, and supports impersonation and idle power down.
-The sample can also be used with the CustomDeviceAccess MSDK sample. The sample demonstrates how to perform bulk and interrupt data transfers to an USB device. The specification for the device is at <http://www.osronline.com/hardware/OSRFX2_32.pdf>. The driver and sample device metadata also work with the [Custom driver access](http://go.microsoft.com/fwlink/p/?LinkID=248288) sample.
+The sample can also be used with the CustomDeviceAccess SDK sample. The sample demonstrates how to perform bulk and interrupt data transfers to an USB device. For more information, see the specification for the [OSR USB FX-2 Learning Kit](https://www.osronline.com/hardware/OSRFX2_32.pdf). The driver and sample device metadata also work with the [Custom driver access](https://go.microsoft.com/fwlink/p/?linkid=2114373) sample.
The osrusbfx2 sample is divided into three samples:
@@ -35,48 +27,72 @@ The osrusbfx2 sample is divided into three samples:
The default Solution build configuration is Debug and Win32.
1. Open the driver project or solution in Visual Studio 2015 (find *filtername*.sln or *filtername*.vcxproj).
+
1. Right-click the solution in the **Solutions Explorer** and select **Configuration Manager**.
+
1. From the **Configuration Manager**, select the **Active Solution Configuration** and the **Active Solution Platform** (for example, Win32) that correspond to the type of build you are interested in.
+
1. From the **Build** menu, click **Build Solution** (Ctrl+Shift+B).
## Overview
- The device is based on the development board supplied with the Cypress EZ-USB FX2 Development Kit (CY3681).
+
- It contains 1 interface and 3 endpoints (Interrupt IN, Bulk Out, Bulk IN).
+
- Firmware supports vendor commands to query or set LED Bar graph display and 7-segment LED display, and to query toggle switch states.
+
- Interrupt Endpoint:
-- Sends an 8-bit value that represents the state of the switches.
+
+ - Sends an 8-bit value that represents the state of the switches.
+
- Sent on startup, resume from suspend, and whenever the switch pack setting changes.
+
- Firmware does not de-bounce the switch pack.
+
- One switch change can result in multiple bytes being sent.
+
- Bits are in the reverse order of the labels on the pack (for example, bit 0x80 is labeled 1 on the pack).
+
- Bulk Endpoints are configured for loopback:
-- The device moves data from IN endpoint to OUT endpoint.
+
+ - The device moves data from IN endpoint to OUT endpoint.
+
- The device does not change the values of the data it receives nor does it internally create any data.
+
- Endpoints are always double buffered.
+
- Maximum packet size depends on speed (64 full speed, 512 high speed).
## Testing the driver
-You can use the [Custom driver access](http://go.microsoft.com/fwlink/p/?LinkID=248288) sample to test the umdf\_fx2 sample.
+You can use the [Custom driver access](https://go.microsoft.com/fwlink/p/?linkid=2114373) sample to test the umdf\_fx2 sample.
This sample also includes a test application, osrusbfx2.exe, that you can use to test the device. This console application enumerates the interface registered by the driver and opens the device to send read, write, or IOCTL requests based on the command line options.
Usage for Read/Write test:
- -r [*n*], where *n* is number of bytes to read.
+
- -w [*n*], where *n* is number of bytes to write.
+
- -c [*n*], where *n* is number of iterations (default = 1).
+
- -v, shows verbose read data.
+
- -p, plays with Bar Display, Dip Switch, 7-Segment Display.
+
- -a, performs asynchronous I/O operation.
+
- -u, dumps USB configuration and pipe information.
+
- -f \<*filename*\> [*interval-seconds*], where *interval-seconds* is a delay in milliseconds, to send a text file to the seven-segment display (UMDF only)
-**Playing with the 7 segment display, toggle switches, and bar graph display**
+### Playing with the 7 segment display, toggle switches, and bar graph display
-Use the command **osrusbfx2.exe -p** with options 1 through 9 to set and clear bar graph display, set and get 7 segment state, and read the toggle switch states. The following shows the function options:
+Use the command `osrusbfx2.exe -p` with options 1 through 9 to set and clear bar graph display, set and get 7 segment state, and read the toggle switch states. The following shows the function options:
+```cmd
1. Light Bar
2. Clear Bar
3. Light entire Bar graph
@@ -92,253 +108,266 @@ Use the command **osrusbfx2.exe -p** with options 1 through 9 to set and clear b
0. Exit
Selection:
+```
-**Reset and re-enumerate the device**
+### Reset and re-enumerate the device
-Use the command **osrusbfx2.exe -p** with options 10 and 11 to either reset the device or re-enumerate the device.
+Use the command `osrusbfx2.exe -p` with options 10 and 11 to either reset the device or re-enumerate the device.
-**Read and write to bulk endpoints**
+### Read and write to bulk endpoints
The following commands send read and write requests to the device's bulk endpoint.
-- `osrusbfx2.exe -r 64`
+- `osrusbfx2.exe -r 64`
The preceding command reads 64 bytes to the bulk IN endpoint.
-- `osrusbfx2.exe -w 64 `
+- `osrusbfx2.exe -w 64`
The preceding command writes 64 bytes to the bulk OUT endpoint.
-- `osrusbfx2.exe -r 64 -w 64 -c 100 -v`
+- `osrusbfx2.exe -r 64 -w 64 -c 100 -v`
The preceding command first writes 64 bytes of data to bulk OUT endpoint (Pipe 1), then reads 64 bytes from bulk IN endpoint (Pipe 2), and then compares the read buffer with write buffer to see if they match. If the buffer contents match, it repeats this operation 100 times.
-- `osrusbfx2.exe -a`
+- `osrusbfx2.exe -a`
The preceding command reads and writes to the device asynchronously in an infinite loop.
The bulk endpoints are double buffered. Depending on the operational speed (full or high), the buffer size is either 64 bytes or 512 bytes, respectively. A request to read data does not complete if the buffers are empty. If the buffers are full, a request to write data does not complete until the buffers are emptied. When you are doing a synchronous read, make sure the endpoint buffer has data (for example, when you send 512 bytes write request to the device operating in full speed mode). Because the endpoints are double buffered, the total buffer capacity is 256 bytes. The first 256 bytes fills the buffer and the write request waits in the USB stack until the buffers are emptied. If you run another instance of the application to read 512 bytes of data, both write and read requests complete successfully.
-**Displaying descriptors**
+### Displaying descriptors
The following command displays all the descriptors and endpoint information.
-**osrusbfx2.exe -u**
+`osrusbfx2.exe -u`
If the device is operating in high speed mode, you get the following information:
-`===================`
+```cmd
+===================
-`USB_CONFIGURATION_DESCRIPTOR`
+USB_CONFIGURATION_DESCRIPTOR
-`bLength = 0x9, decimal 9`
+bLength = 0x9, decimal 9
-`bDescriptorType = 0x2 ( USB_CONFIGURATION_DESCRIPTOR_TYPE )`
+bDescriptorType = 0x2 ( USB_CONFIGURATION_DESCRIPTOR_TYPE )
-`wTotalLength = 0x27, decimal 39`
+wTotalLength = 0x27, decimal 39
-`bNumInterfaces = 0x1, decimal 1`
+bNumInterfaces = 0x1, decimal 1
-`bConfigurationValue = 0x1, decimal 1`
+bConfigurationValue = 0x1, decimal 1
-`iConfiguration = 0x4, decimal 4`
+iConfiguration = 0x4, decimal 4
-`bmAttributes = 0xa0 ( USB_CONFIG_BUS_POWERED )`
+bmAttributes = 0xa0 ( USB_CONFIG_BUS_POWERED )
-`MaxPower = 0x32, decimal 50`
+MaxPower = 0x32, decimal 50
-`-----------------------------`
+-----------------------------
-`USB_INTERFACE_DESCRIPTOR #0`
+USB_INTERFACE_DESCRIPTOR #0
-`bLength = 0x9`
+bLength = 0x9
-`bDescriptorType = 0x4 ( USB_INTERFACE_DESCRIPTOR_TYPE )`
+bDescriptorType = 0x4 ( USB_INTERFACE_DESCRIPTOR_TYPE )
-`bInterfaceNumber = 0x0`
+bInterfaceNumber = 0x0
-`bAlternateSetting = 0x0`
+bAlternateSetting = 0x0
-`bNumEndpoints = 0x3`
+bNumEndpoints = 0x3
-`bInterfaceClass = 0xff`
+bInterfaceClass = 0xff
-`bInterfaceSubClass = 0x0`
+bInterfaceSubClass = 0x0
-`bInterfaceProtocol = 0x0`
+bInterfaceProtocol = 0x0
-`bInterface = 0x0`
+bInterface = 0x0
-`------------------------------`
+------------------------------
-`USB_ENDPOINT_DESCRIPTOR for Pipe00`
+USB_ENDPOINT_DESCRIPTOR for Pipe00
-`bLength = 0x7`
+bLength = 0x7
-`bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )`
+bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )
-`bEndpointAddress= 0x81 ( INPUT )`
+bEndpointAddress= 0x81 ( INPUT )
-`bmAttributes= 0x3 ( USB_ENDPOINT_TYPE_INTERRUPT )`
+bmAttributes= 0x3 ( USB_ENDPOINT_TYPE_INTERRUPT )
-`wMaxPacketSize= 0x49, decimal 73`
+wMaxPacketSize= 0x49, decimal 73
-`bInterval = 0x1, decimal 1`
+bInterval = 0x1, decimal 1
-`------------------------------`
+------------------------------
-`USB_ENDPOINT_DESCRIPTOR for Pipe01`
+USB_ENDPOINT_DESCRIPTOR for Pipe01
-`bLength = 0x7`
+bLength = 0x7
-`bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )`
+bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )
-`bEndpointAddress= 0x6 ( OUTPUT )`
+bEndpointAddress= 0x6 ( OUTPUT )
-`bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )`
+bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )
-`wMaxPacketSize= 0x200, `
+wMaxPacketSize= 0x200,
-`decimal 512 bInterval = 0x0, `
+decimal 512 bInterval = 0x0,
-`decimal 0`
+decimal 0
-`------------------------------`
+------------------------------
-`USB_ENDPOINT_DESCRIPTOR for Pipe02`
+USB_ENDPOINT_DESCRIPTOR for Pipe02
-`bLength = 0x7`
+bLength = 0x7
-`bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )`
+bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )
-`bEndpointAddress= 0x88 ( INPUT )`
+bEndpointAddress= 0x88 ( INPUT )
-`bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )`
+bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )
-`wMaxPacketSize= 0x200, decimal 512`
+wMaxPacketSize= 0x200, decimal 512
-`bInterval = 0x0, decimal 0`
+bInterval = 0x0, decimal 0
+```
If the device is operating in low speed mode, you will get the following information:
-`===================`
+```cmd
+===================
-`USB_CONFIGURATION_DESCRIPTOR`
+USB_CONFIGURATION_DESCRIPTOR
-`bLength = 0x9, decimal 9`
+bLength = 0x9, decimal 9
-`bDescriptorType = 0x2 ( USB_CONFIGURATION_DESCRIPTOR_TYPE )`
+bDescriptorType = 0x2 ( USB_CONFIGURATION_DESCRIPTOR_TYPE )
-`wTotalLength = 0x27, decimal 39`
+wTotalLength = 0x27, decimal 39
-`bNumInterfaces = 0x1, decimal 1`
+bNumInterfaces = 0x1, decimal 1
-`bConfigurationValue = 0x1, decimal 1`
+bConfigurationValue = 0x1, decimal 1
-`iConfiguration = 0x3, decimal 3`
+iConfiguration = 0x3, decimal 3
-`bmAttributes = 0xa0 ( USB_CONFIG_BUS_POWERED )`
+bmAttributes = 0xa0 ( USB_CONFIG_BUS_POWERED )
-`MaxPower = 0x32, decimal 50 `
+MaxPower = 0x32, decimal 50
-`-----------------------------`
+-----------------------------
-`USB_INTERFACE_DESCRIPTOR #0`
+USB_INTERFACE_DESCRIPTOR #0
-`bLength = 0x9`
+bLength = 0x9
-`bDescriptorType = 0x4 ( USB_INTERFACE_DESCRIPTOR_TYPE )`
+bDescriptorType = 0x4 ( USB_INTERFACE_DESCRIPTOR_TYPE )
-`bInterfaceNumber = 0x0 bAlternateSetting = 0x0`
+bInterfaceNumber = 0x0 bAlternateSetting = 0x0
-`bNumEndpoints = 0x3`
+bNumEndpoints = 0x3
-`bInterfaceClass = 0xff`
+bInterfaceClass = 0xff
-`bInterfaceSubClass = 0x0`
+bInterfaceSubClass = 0x0
-`bInterfaceProtocol = 0x0`
+bInterfaceProtocol = 0x0
-`bInterface = 0x0`
+bInterface = 0x0
-`------------------------------`
+------------------------------
-`USB_ENDPOINT_DESCRIPTOR for Pipe00`
+USB_ENDPOINT_DESCRIPTOR for Pipe00
-`bLength = 0x7`
+bLength = 0x7
-`bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )`
+bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )
-`bEndpointAddress= 0x81 ( INPUT )`
+bEndpointAddress= 0x81 ( INPUT )
-`bmAttributes= 0x3 ( USB_ENDPOINT_TYPE_INTERRUPT )`
+bmAttributes= 0x3 ( USB_ENDPOINT_TYPE_INTERRUPT )
-`wMaxPacketSize= 0x49, decimal 73`
+wMaxPacketSize= 0x49, decimal 73
-`bInterval = 0x1, decimal 1`
+bInterval = 0x1, decimal 1
-`------- -----------------------`
+------- -----------------------
-`USB_ENDPOINT_DESCRIPTOR for Pipe01`
+USB_ENDPOINT_DESCRIPTOR for Pipe01
-`bLength = 0x7`
+bLength = 0x7
-`bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )`
+bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )
-`bEndpointAddress= 0x6 ( OUTPUT )`
+bEndpointAddress= 0x6 ( OUTPUT )
-`bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )`
+bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )
-`wMaxPacketSize= 0x40, decimal 64`
+wMaxPacketSize= 0x40, decimal 64
-`bInterval = 0x0, decimal 0`
+bInterval = 0x0, decimal 0
-`------------------------------`
+------------------------------
-`USB_ENDPOINT_DESCRIPTOR for Pipe02`
+USB_ENDPOINT_DESCRIPTOR for Pipe02
-`bLength = 0x7`
+bLength = 0x7
-`bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )`
+bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )
-`bEndpointAddress= 0x88 ( INPUT )`
+bEndpointAddress= 0x88 ( INPUT )
-`bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )`
+bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )
-`wMaxPacketSize= 0x40, decimal 64`
+wMaxPacketSize= 0x40, decimal 64
-`bInterval = 0x0, decimal 0 `
+bInterval = 0x0, decimal 0
+```
-Sample Contents
----------------
+## Sample Contents
-Folder
+### usb\\umdf\_fx2\\driver
-Description
+This directory contains driver code that demonstrates the following functionality:
-usb\\umdf\_fx2\\driver
+- Loads the driver and responds to PnP and Power events. You can install, uninstall, disable, enable, suspend, and resume the system.
-This directory contains driver code that demonstrates the following functionality:
+- Registers a PnP device interface so that application can open a handle to the device.
+
+- Implements **IPnpCallbackHardware** interface and initializes USB I/O targets in **IPnpCallbackHardware::OnPrepareHardware** method.
+
+- Creates a sequential queue for handling IOCTL requests.
+
+- Adds code to handle the IOCTL to set bar graph display.
+
+- Creates a parallel queue for handling read and write requests.
+
+- Retrieves memory from read and write requests, format the requests, and sends them to a USB target.
+
+- Supports additional IOCTLs to get and set the 7-segment display, get bar graph display, and get config descriptor.
+
+- Sets power policy for the device.
+
+- Adds code to indicate that the device is ready by lighting up the period on 7-segment display.
+
+- Calls **SetupDi** functions to determine the "BusTypeGUID" of the device, and uses impersonation to access resources that only the caller has access to.
+
+- Shows how to implement idle and wake functionality to make the driver the power policy owner (PPO). The sample achieves this using power-managed queues and UMDF DDIs, AssignS0IdleSettings, and AssignSxWakeSettings.
+
+- Demonstrates implementation of a continuous reader.
-- Loads the driver and responds to PnP and Power events. You can install, uninstall, disable, enable, suspend, and resume the system.
-- Registers a PnP device interface so that application can open a handle to the device.
-- Implements **IPnpCallbackHardware** interface and initializes USB I/O targets in **IPnpCallbackHardware::OnPrepareHardware** method.
-- Creates a sequential queue for handling IOCTL requests.
-- Adds code to handle the IOCTL to set bar graph display.
-- Creates a parallel queue for handling read and write requests.
-- Retrieves memory from read and write requests, format the requests, and sends them to a USB target.
-- Supports additional IOCTLs to get and set the 7-segment display, get bar graph display, and get config descriptor.
-- Sets power policy for the device.
-- Adds code to indicate that the device is ready by lighting up the period on 7-segment display.
-- Calls **SetupDi** functions to determine the "BusTypeGUID" of the device, and uses impersonation to access resources that only the caller has access to.
-- Shows how to implement idle and wake functionality to make the driver the power policy owner (PPO). The sample achieves this using power-managed queues and UMDF DDIs, AssignS0IdleSettings, and AssignSxWakeSettings.
-- Demonstrates implementation of a continuous reader.
-- Demonstrates the use of impersonation.
+- Demonstrates the use of impersonation.
-usb\\umdf\_fx2\\exe
+### usb\\umdf\_fx2\\exe
This directory contains a test application that can be used to drive the UMDF driver and FX2 device. This is a modified version of the test application for the KMDF Fx2 driver.
-usb\\umdf\_fx2\\deviceMetadata
+### usb\\umdf\_fx2\\deviceMetadata
-This directory contains the device metadata package for the sample. You must copy the device metadata to the system before installing the device. For information on how to update and deploy device metadata, see [Custom driver access sample](http://go.microsoft.com/fwlink/p/?LinkID=248288). \ No newline at end of file
+This directory contains the device metadata package for the sample. You must copy the device metadata to the system before installing the device. For information on how to update and deploy device metadata, see [Custom driver access sample](https://go.microsoft.com/fwlink/p/?linkid=2114373).
diff --git a/usb/usbsamp/README.md b/usb/usbsamp/README.md
index ac5fb259..7c695eba 100644
--- a/usb/usbsamp/README.md
+++ b/usb/usbsamp/README.md
@@ -5,24 +5,16 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Usbsamp Generic USB Driver
- platform: KMDF
- language: cpp
- category: USB
- description: Demonstrates how to perform full speed, high speed, and SuperSpeed transfers to and from bulk and isochronous endpoints of a generic USB device.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=618938
---->
-
# Usbsamp Generic USB Driver
-The USBSAMP sample demonstrates how to perform full speed, high speed, and SuperSpeed transfers to and from bulk and isochronous endpoints of a generic USB device. USBSAMP is based on the [Kernel Mode Driver Framework](http://msdn.microsoft.com/en-us/library/windows/hardware/ff557405) (KMDF). Superspeed bulk and isochronous transfers only work when the Microsoft USB 3.0 stack is loaded.
+The USBSAMP sample demonstrates how to perform full speed, high speed, and SuperSpeed transfers to and from bulk and isochronous endpoints of a generic USB device. USBSAMP is based on the [Kernel Mode Driver Framework](https://docs.microsoft.com/windows-hardware/drivers/kernel/) (KMDF). Superspeed bulk and isochronous transfers only work when the Microsoft USB 3.0 stack is loaded.
The sample also contains a console test application that initiates bulk (including stream) and isochronous transfers and obtains data from the device's I/O endpoints. The application also demonstrates how to use GUID-based device names and pipe names generated by the operating system using the **SetupDiXXX** user-mode APIs.
-For information about USB, see [Universal Serial Bus (USB) Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff538930).
+For information about USB, see [Universal Serial Bus (USB) Drivers](https://docs.microsoft.com/windows-hardware/drivers/usbcon/).
## Universal Windows Driver Compliant
@@ -32,8 +24,8 @@ This sample builds a Universal Windows Driver. It uses only APIs and DDIs that a
The sample driver can be loaded as the function driver for any of these devices:
-- OSR FX2 learning kit. You can get the kit from [OSR Online](http://www.osronline.com/).
-- [MUTT devices](http://msdn.microsoft.com/en-us/library/windows/hardware/dn376873). To order those devices, see [How to get MUTT devices](buses.microsoft_usb_test_tool__mutt__devices#howto).
+- OSR FX2 learning kit. You can get the kit from [OSR Online](https://www.osronline.com/). For more information, see the specification for the [OSR USB FX-2 Learning Kit](https://www.osronline.com/hardware/OSRFX2_32.pdf)
+- [MUTT devices](https://docs.microsoft.com/windows-hardware/drivers/usbcon/microsoft-usb-test-tool--mutt--devices). To order those devices, see [How to get MUTT devices](https://docs.microsoft.com/windows-hardware/drivers/usbcon/microsoft-usb-test-tool--mutt--devices#how-to-get-mutt-devices).
- Intel 82930 USB test board.
If you have a different USB device, you can still use the driver by adding the device's hardware ID to the INX file. Note that the data transfer scenarios will work only with the endpoints supported by the device.
@@ -46,7 +38,7 @@ In Visual Studio, in Solution Explorer, right click **Solution 'usbsamp' (3 proj
In Visual Studio, on the **Build** menu, choose **Build Solution**.
-For more information about using Visual Studio to build a driver package, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644).
+For more information about using Visual Studio to build a driver package, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver).
## Locate the built driver
@@ -56,7 +48,7 @@ The driver folder contains these files:
| File | Description |
| --- | --- |
-| usbsamp.sys | The driver file. |
+| usbsamp.sys | The driver file |
| usbsamp.inf | An information (INF) file that contains information needed to install the driver. |
| kmdfsamples.cat | A signed catalog file, which serves as the signature for the entire package. |
@@ -68,20 +60,23 @@ The process of moving the driver package to the target computer and installing t
### Automatic deployment
-Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/).
+Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Provision a computer for driver deployment and testing (WDK 10)](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1).
1. On the host computer, in Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**.
+
1. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Install and Verify**. Click **OK**.
+
1. On the **Build** menu, choose **Deploy Package** or **Build Solution**.
### Manual deployment
-Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
+Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](https://docs.microsoft.com/windows-hardware/drivers/devtest/devcon) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment).
1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\Usbsamp).
+
1. On the target computer, open a Command Prompt window as Administrator. Navigate to your driver package folder, and enter the following command:
- **devcon install usbsamp.inf USB\\VID\_045E&PID\_078F**
+ `devcon install usbsamp.inf USB\VID_045E&PID_078F`
## View the device in Device Manager
@@ -91,64 +86,66 @@ On the target computer, in a Command Prompt window, enter **devmgmt** to open De
As an alternative to building the USBSAMP sample in Visual Studio, you can build it in a Visual Studio Command Prompt window. In Visual Studio, on the **Tools** menu, choose **Visual Studio Command Prompt**. In the Visual Studio Command Prompt window, navigate to the folder that has the solution file, Usbsamp.sln. Use the MSBuild command to build the solution. Here are some examples:
- **msbuild /p:configuration="Debug" /p:platform="x64" Usbsamp.sln**
+ `msbuild /p:configuration="Debug" /p:platform="x64" Usbsamp.sln`
- **msbuild /p:configuration="Release" /p:platform="Win32" Usbsamp.sln**
+ `msbuild /p:configuration="Release" /p:platform="Win32" Usbsamp.sln`
-For more information about using MSBuild to build a driver package, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644).
+For more information about using MSBuild to build a driver package, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver).
## Testing the sample
The sample includes a test application, usbsamp.exe. This console application enumerates the interface registered by the driver and opens the device to send Read, Write, or DeviceIoControl requests based on the command line options. To test the sample,
1. In Visual Studio, choose **Solution Explorer** from the **View** menu. Locate the application project named **usbsamp**, under the **Exe** folder.
+
1. Right-click and choose **Build**. For example, if your settings are Debug and x64, the application executable is in your solution folder under the exe\\Debug\\usbsamp.exe.
+
1. Run the executable on the target machine.
- To view all descriptors and endpoint information, use the following command.
- **usbsamp.exe -u**
+ `usbsamp.exe -u`
You can use the preceding command to view pipe numbers for read and write requests.
- To send a Read-Write request, use the following command.
- **usbsamp.exe -r 1024 -w 1024 -c 100 -v**
+ `usbsamp.exe -r 1024 -w 1024 -c 100 -v`
The preceding command first writes 1024 bytes of data to bulk out endpoint (pipe 1), then reads 1024 bytes from bulk in endpoint (pipe 0), and compares the read buffer with write buffer to see if they match. If the buffer contents match, it performs this operation 100 times.
- To send Read-Write requests to bulk endpoints, use any of the following commands, simultaneously. If Read-Write requests are sent to a SuperSpeed bulk endpoint with streams, the sample driver always uses the first underlying stream associated with that endpoint. The driver is multi-thread safe so it can handle multiple requests at a time.
- **usbsamp.exe -r 65536**
+ `usbsamp.exe -r 65536`
The preceding command reads 65536 bytes from pipe 0.
- **usbsamp.exe -w 65536**
+ `usbsamp.exe -w 65536`
The preceding command writes 65536 bytes to pipe 1.
- **usbsamp.exe -r 65536 -i pipe02**
+ `usbsamp.exe -r 65536 -i pipe02`
The preceding command reads 65536 bytes from pipe 2.
- **usbsamp.exe -w 65536 -o pipe03**
+ `usbsamp.exe -w 65536 -o pipe03`
The preceding command writes 65536 bytes to pipe 3.
- To send Read and Write requests to isochronous endpoints you can use one or more of these commands simultaneously.
- **usbsamp.exe -r 512 -i pipe04**
+ `usbsamp.exe -r 512 -i pipe04`
The preceding command reads 512 bytes from pipe 4.
- **usbsamp.exe -w 512 -o pipe05**
+ `usbsamp.exe -w 512 -o pipe05`
The preceding command writes 512 bytes to pipe 5.
- **usbsamp.exe -w 1024 -o pipe05 -r 1024 -i pipe04 -c 100 -v**
+ `usbsamp.exe -w 1024 -o pipe05 -r 1024 -i pipe04 -c 100 -v`
The preceding command writes 1024 bytes to pipe 5, then reads 1024 bytes from pipe 4, and compares the buffers to see if they match. If the buffer contents match, it performs this operation 100 times.
- To skip validation of the data to be read or written in a particular request, use the command with **-x** option as follows:
- **usbsamp.exe -r 1024 -w 1024 -c 100 -x** \ No newline at end of file
+ usbsamp.exe -r 1024 -w 1024 -c 100 -x
diff --git a/usb/usbsamp/sys/driver.c b/usb/usbsamp/sys/driver.c
index 26d61477..68b717e4 100644
--- a/usb/usbsamp/sys/driver.c
+++ b/usb/usbsamp/sys/driver.c
@@ -72,7 +72,7 @@ Return Value:
UsbSamp_DbgPrint(3, ("Built %s %s\n", __DATE__, __TIME__));
//
- // Initiialize driver config to control the attributes that
+ // Initialize driver config to control the attributes that
// are global to the driver. Note that framework by default
// provides a driver unload routine. If you create any resources
// in the DriverEntry and want to be cleaned in driver unload,
diff --git a/usb/usbsamp/sys/private.h b/usb/usbsamp/sys/private.h
index d6d7898b..def503f5 100644
--- a/usb/usbsamp/sys/private.h
+++ b/usb/usbsamp/sys/private.h
@@ -52,11 +52,6 @@ Environment:
#define DISPATCH_LATENCY_IN_MS 10
-
-#undef ExAllocatePool
-#define ExAllocatePool(type, size) \
- ExAllocatePoolWithTag(type, size, POOL_TAG);
-
#if DBG
#define UsbSamp_DbgPrint(level, _x_) \
diff --git a/usb/usbsamp/sys/stream.c b/usb/usbsamp/sys/stream.c
index ee434b35..d8cc05d9 100644
--- a/usb/usbsamp/sys/stream.c
+++ b/usb/usbsamp/sys/stream.c
@@ -199,8 +199,8 @@ Return Value:
pStreamInfo->NumberOfStreams = supportedStreams;
- pStreamInfo->StreamList = ExAllocatePoolWithTag(
- NonPagedPoolNx,
+ pStreamInfo->StreamList = ExAllocatePool2(
+ POOL_FLAG_NON_PAGED,
supportedStreams * sizeof(USBD_STREAM_INFORMATION),
POOL_TAG);
diff --git a/usb/usbview/README.md b/usb/usbview/README.md
index 7876d9e3..b4bdd2bf 100644
--- a/usb/usbview/README.md
+++ b/usb/usbview/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: USBView sample application
- platform: WDM
- language: cpp
- category: USB
- description: Provides an application that allows you to browse all USB controllers and connected USB devices on your system.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=618004
---->
-
# USBView sample application
Usbview.exe is a Windows GUI application that allows you to browse all USB controllers and connected USB devices on your system. The left pane in the main application window displays a connection-oriented tree view, and the right pane displays the USB data structures pertaining to the selected USB device, such as the Device, Configuration, Interface, and Endpoint Descriptors, as well as the current device configuration.
@@ -24,21 +16,28 @@ This functional application sample demonstrates how a user-mode application can
The IOCTL calls (see the system include file USBIOCTL.H) demonstrated by this sample include:
-- [**IOCTL\_GET\_HCD\_DRIVERKEY\_NAME**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff537236)
-- [**IOCTL\_USB\_GET\_DESCRIPTOR\_FROM\_NODE\_CONNECTION**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff537310)
-- [**IOCTL\_USB\_GET\_NODE\_CONNECTION\_DRIVERKEY\_NAME**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff537317)
-- [**IOCTL\_USB\_GET\_NODE\_CONNECTION\_INFORMATION**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff537319)
-- [**IOCTL\_USB\_GET\_NODE\_CONNECTION\_NAME**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff537323)
-- [**IOCTL\_USB\_GET\_NODE\_INFORMATION**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff537324)
-- [**IOCTL\_USB\_GET\_ROOT\_HUB\_NAME**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff537326)
+- [**IOCTL\_GET\_HCD\_DRIVERKEY\_NAME**](https://docs.microsoft.com/windows/win32/api/usbuser/ni-usbuser-ioctl_get_hcd_driverkey_name)
+
+- [**IOCTL\_USB\_GET\_DESCRIPTOR\_FROM\_NODE\_CONNECTION**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/usbioctl/ni-usbioctl-ioctl_usb_get_descriptor_from_node_connection)
+
+- [**IOCTL\_USB\_GET\_NODE\_CONNECTION\_DRIVERKEY\_NAME**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/usbioctl/ni-usbioctl-ioctl_usb_get_node_connection_driverkey_name)
+
+- [**IOCTL\_USB\_GET\_NODE\_CONNECTION\_INFORMATION**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/usbioctl/ni-usbioctl-ioctl_usb_get_node_connection_information)
+
+- [**IOCTL\_USB\_GET\_NODE\_CONNECTION\_NAME**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/usbioctl/ni-usbioctl-ioctl_usb_get_node_connection_name)
-For information about USB, see [Universal Serial Bus (USB) Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff538930).
+- [**IOCTL\_USB\_GET\_NODE\_INFORMATION**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/usbioctl/ni-usbioctl-ioctl_usb_get_node_information)
+
+- [**IOCTL\_USB\_GET\_ROOT\_HUB\_NAME**](https://docs.microsoft.com/windows/win32/api/usbuser/ni-usbuser-ioctl_usb_get_root_hub_name)
+
+For information about USB, see [Universal Serial Bus (USB) Drivers](https://docs.microsoft.com/windows-hardware/drivers/usbcon/).
## Run the sample
### Local debugging
1. Change **Debugger** to launch to **Local Windows Debugger**.
+
1. On the **Debug** menu, select **Start debugging** or hit **F5**.
### Manual deployment to a remote target computer
@@ -46,14 +45,19 @@ For information about USB, see [Universal Serial Bus (USB) Drivers](http://msdn.
If you want to debug the sample app on a remote computer,
1. Copy the executable to a folder on the remote computer.
-1. Specify project properties as per the instructions given in [Set Up Remote Debugging for a Visual Studio Project](http://msdn.microsoft.com/en-us/library/8x6by8d2.aspx).
+
+1. Specify project properties as per the instructions given in [Remote Debugging](https://docs.microsoft.com/visualstudio/debugger/remote-debugging?view=vs-2015).
+
1. Change **Debugger** to launch to **Remote Windows Debugger**.
+
1. On the **Debug** menu, select **Start debugging** or hit **F5**.
### View a USB device in Usbview
1. Attach a USB device to one of USB ports on the computer that has Usbview running.
+
1. In the device tree, locate the device. For example the device might be under the Intel(R) ICH10 Family USB Universal Host Controller - 3A34 \> Root Hub node.
+
1. View host controller and port properties on the right pane.
## Code tour
@@ -73,7 +77,9 @@ If you want to debug the sample app on a remote computer,
The major topics covered in this tour are:
- GUI handling routines
+
- Device enumeration routines
+
- Device information display routines
The file Usbview.c contains the sample application entry point and GUI handling routines. On entry, the main application window is created, which is actually a dialog box as defined in Usbview.rc. The dialog box consists of a split window with a tree view control on the left side and an edit control on the right side.
@@ -83,7 +89,9 @@ The routine RefreshTree() is called to enumerate USB host controller, hubs, and
The file Enum.c contains the routines that enumerate the USB bus and populate the tree view control. The USB device enumeration and information collection process is the main point of this sample application. The enumeration process starts at EnumerateHostControllers() and goes like this:
1. Enumerate Host Controllers and Root Hubs. Host controllers have symbolic link names of the form HCDx, where x starts at 0. Use CreateFile() to open each host controller symbolic link. Create a node in the tree view to represent each host controller. After a host controller has been opened, send the host controller an IOCTL\_USB\_GET\_ROOT\_HUB\_NAME request to get the symbolic link name of the root hub that is part of the host controller.
+
1. Enumerate Hubs (Root Hubs and External Hubs). Given the name of a hub, use CreateFile() to open the hub. Send the hub an IOCTL\_USB\_GET\_NODE\_INFORMATION request to get info about the hub, such as the number of downstream ports. Create a node in the tree view to represent each hub.
+
1. Enumerate Downstream Ports. Given a handle to an open hub and the number of downstream ports on the hub, send the hub an IOCTL\_USB\_GET\_NODE\_CONNECTION\_INFORMATION request for each downstream port of the hub to get info about the device (if any) attached to each port. If there is a device attached to a port, send the hub an IOCTL\_USB\_GET\_NODE\_CONNECTION\_NAME request to get the symbolic link name of the hub attached to the downstream port. If there is a hub attached to the downstream port, recurse to step (2). Create a node in the tree view to represent each hub port and attached device. USB configuration and string descriptors are retrieved from attached devices in GetConfigDescriptor() and GetStringDescriptor() by sending an IOCTL\_USB\_GET\_DESCRIPTOR\_FROM\_NODE\_CONNECTION() to the hub to which the device is attached.
-The file Display.c contains routines that display information about selected devices in the application edit control. Information about the device was collected during the enumeration of the device tree. This information includes USB device, configuration, and string descriptors and connection and configuration information that is maintained by the USB stack. The routines in this file simply parse and print the data structures for the device that were collected when it was enumerated. The file Dispaud.c parses and prints data structures that are specific to USB audio class devices. \ No newline at end of file
+The file Display.c contains routines that display information about selected devices in the application edit control. Information about the device was collected during the enumeration of the device tree. This information includes USB device, configuration, and string descriptors and connection and configuration information that is maintained by the USB stack. The routines in this file simply parse and print the data structures for the device that were collected when it was enumerated. The file Dispaud.c parses and prints data structures that are specific to USB audio class devices.
diff --git a/usb/wdf_osrfx2_lab/README.md b/usb/wdf_osrfx2_lab/README.md
index bb565a5d..aee7a886 100644
--- a/usb/wdf_osrfx2_lab/README.md
+++ b/usb/wdf_osrfx2_lab/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: WDF Sample Driver Learning Lab for OSR USB-FX2
- platform: UMDF1 KMDF
- language: cpp
- category: USB
- description: Contains a console test application and a series of iterative drivers for both KMDF and UMDF version 1.
- samplefwlink: https://go.microsoft.com/fwlink/?linkid=856746
---->
-
# WDF Sample Driver Learning Lab for OSR USB-FX2
The wdf\_osrfx2\_lab sample contains a console test application and a series of iterative drivers for both Kernel-Mode Driver Framework (KMDF) and User-Mode Driver Framework (UMDF) version 1.
@@ -24,362 +16,350 @@ In the Windows Driver Kit (WDK) for Windows 7 and earlier versions of Windows, t
Starting in Windows 8.1, the osrusbfx2 sample has been divided into these samples:
-- wdf\_osrfx2: This sample is a series of iterative drivers that demonstrate how to write a "Hello World" driver and adds additional features in each step.
-
-- [kmdf\_fx2](gallery_samples.123a_gallery#1): This sample is the final version of kernel-mode wdf\_osrfx2 driver. The sample demonstrates KMDF methods.
+- [wdf\_osrfx2](https://docs.microsoft.com/samples/microsoft/windows-driver-samples/wdf-sample-driver-learning-lab-for-osr-usb-fx2/): This sample is a series of iterative drivers that demonstrate how to write a "Hello World" driver and adds additional features in each step.
-- [umdf\_fx2](http://msdn.microsoft.com/en-us/library/windows/hardware/): This sample is the final version of the user-mode driver wdf\_osrfx2. The sample demonstrates UMDF methods.
+- [kmdf\_fx2](https://docs.microsoft.com/samples/microsoft/windows-driver-samples/sample-kmdf-bus-driver-for-osr-usb-fx2/): This sample is the final version of kernel-mode wdf\_osrfx2 driver. The sample demonstrates KMDF methods.
-This sample is written for the OSR USB-FX2 Learning Kit. The specification for the device is at <http://www.osronline.com/hardware/OSRFX2_32.pdf>.
+- [umdf\_fx2](https://docs.microsoft.com/samples/microsoft/windows-driver-samples/sample-umdf-function-driver-for-osr-usb-fx2-umdf-version-1/): This sample is the final version of the user-mode driver wdf\_osrfx2. The sample demonstrates UMDF methods.
+This sample is written for the OSR USB-FX2 Learning Kit. For more information, see the specification for the [OSR USB FX-2 Learning Kit](https://www.osronline.com/hardware/OSRFX2_32.pdf).
-Related topics
---------------
+## Build the sample
-[kmdf\_fx2](http://msdn.microsoft.com/en-us/library/windows/hardware/)
+The default Solution build configuration is Windows 8.1 Debug and Win32. You can change the default configuration to build for Windows 8 or Windows 7 version of the operating system.
-[umdf\_fx2](http://msdn.microsoft.com/en-us/library/windows/hardware/)
+### To select a configuration and build a driver
+1. Open the driver project or solution in Visual Studio 2013 (find *filtername*.sln or *filtername*.vcxproj).
-Build the sample
-----------------
+1. Right-click the solution in the **Solutions Explorer** and select **Configuration Manager**.
-The default Solution build configuration is Windows 8.1 Debug and Win32. You can change the default configuration to build for Windows 8 or Windows 7 version of the operating system.
+1. From the **Configuration Manager**, select the **Active Solution Configuration** (for example, Windows 8.1 Debug or Windows 8.1 Release) and the **Active Solution Platform** (for example, Win32) that correspond to the type of build you are interested in.
-**To select a configuration and build a driver**
+1. Each driver project in this iterative sample creates a binary with the same name, osrusbfx2.sys. As a result, you can build only the single project you're currently working on, as well as the package project. You can do this by selecting only these two projects in **Configuration Manager**.
-1. Open the driver project or solution in Visual Studio 2013 (find *filtername*.sln or *filtername*.vcxproj).
-2. Right-click the solution in the **Solutions Explorer** and select **Configuration Manager**.
-3. From the **Configuration Manager**, select the **Active Solution Configuration** (for example, Windows 8.1 Debug or Windows 8.1 Release) and the **Active Solution Platform** (for example, Win32) that correspond to the type of build you are interested in.
-4. Each driver project in this iterative sample creates a binary with the same name, osrusbfx2.sys. As a result, you can build only the single project you're currently working on, as well as the package project. You can do this by selecting only these two projects in **Configuration Manager**.
-5. From the **Build** menu, click **Build Solution** (Ctrl+Shift+B).
+1. From the **Build** menu, click **Build Solution** (Ctrl+Shift+B).
-Overview
---------
+## Overview
Here is the overview of the device:
-- The device is based on the development board supplied with the Cypress EZ-USB FX2 Development Kit (CY3681).
-- It contains 1 interface and 3 endpoints (Interrupt IN, Bulk Out, Bulk IN).
-- Firmware supports vendor commands to query or set LED Bar graph display and 7-segment LED display, and to query toggle switch states.
-- Interrupt Endpoint:
- - Sends an 8-bit value that represents the state of the switches.
- - Sent on startup, resume from suspend, and whenever the switch pack setting changes.
- - Firmware does not de-bounce the switch pack.
- - One switch change can result in multiple bytes being sent.
- - Bits are in the reverse order of the labels on the pack (for example, bit 0x80 is labeled 1 on the pack).
-- Bulk Endpoints are configured for loopback:
- - The device moves data from IN endpoint to OUT endpoint.
- - The device does not change the values of the data it receives nor does it internally create any data.
- - Endpoints are always double buffered.
- - Maximum packet size depends on speed (64 full speed, 512 high speed).
+- The device is based on the development board supplied with the Cypress EZ-USB FX2 Development Kit (CY3681).
+
+- It contains 1 interface and 3 endpoints (Interrupt IN, Bulk Out, Bulk IN).
+
+- Firmware supports vendor commands to query or set LED Bar graph display and 7-segment LED display, and to query toggle switch states.
+
+- Interrupt Endpoint:
+
+ - Sends an 8-bit value that represents the state of the switches.
+
+ - Sent on startup, resume from suspend, and whenever the switch pack setting changes.
+
+ - Firmware does not de-bounce the switch pack.
+
+ - One switch change can result in multiple bytes being sent.
+
+ - Bits are in the reverse order of the labels on the pack (for example, bit 0x80 is labeled 1 on the pack).
+
+- Bulk Endpoints are configured for loopback:
+
+ - The device moves data from IN endpoint to OUT endpoint.
+
+ - The device does not change the values of the data it receives nor does it internally create any data.
+
+ - Endpoints are always double buffered.
+
+ - Maximum packet size depends on speed (64 full speed, 512 high speed).
+
+## Sample Contents for KMDF
+
+The KMDF sample contains a console test application and a series of drivers. The driver is iterative as a series of steps, starting with a basic "Hello World" driver.
+
+### usb\wdf_osrfx2_lab\kmdf\step1
+
+The most basic step. The source file contains a minimal amount of code to get the driver loaded in memory and respond to PnP and Power events. You can install, uninstall, disable, enable, suspend, and resume the system.
-Sample Contents for KMDF
-------------------------
+### usb\wdf_osrfx2_lab\kmdf\step2
-The KMDF sample contains a console test application and a series of drivers. The driver is iterative as a series of steps, starting with a basic "Hello World" driver. Each step is describe in the following table.
+- Creates a context with the WDFDEVICE object
-<table>
-<colgroup>
-<col width="50%" />
-<col width="50%" />
-</colgroup>
-<thead>
-<tr class="header">
-<th align="left">Folder
-Description</th>
-</tr>
-</thead>
-<tbody>
-<tr class="odd">
-<td align="left">usb\wdf_osrfx2_lab\kmdf\step1
-The most basic step. The source file contains a minimal amount of code to get the driver loaded in memory and respond to PnP and Power events. You can install, uninstall, disable, enable, suspend, and resume the system.</td>
-<td align="left">usb\wdf_osrfx2_lab\kmdf\step2
-<ol>
-<li>Creates a context with the WDFDEVICE object.</li>
-<li>Initializes the USB device by registering a <em>EvtPrepareHardware</em> callback.</li>
-<li>Registers an interface so that application can open a handle to the device.</li>
-</ol></td>
-</tr>
-</tbody>
-</table>
+- Initializes the USB device by registering a **EvtPrepareHardware** callback
-Testing the driver
-------------------
+- Registers an interface so that application can open a handle to the device
+
+## Testing the driver
The sample includes a test application, osrusbfx2.exe, that you can use to test the device. This console application enumerates the interface registered by the driver and opens the device to send read, write, or IOCTL requests based on the command line options.
Usage for Read/Write test:
-- -r [*n*], where *n* is number of bytes to read.
-- -w [*n*], where *n* is number of bytes to write.
-- -c [*n*], where *n* is number of iterations (default = 1).
-- -v, shows verbose read data.
-- -p, plays with Bar Display, Dip Switch, 7-Segment Display.
-- -a, performs asynchronous I/O operation.
-- -u, dumps USB configuration and pipe information.
+- -r [*n*], where *n* is number of bytes to read.
+
+- -w [*n*], where *n* is number of bytes to write.
+
+- -c [*n*], where *n* is number of iterations (default = 1).
+
+- -v, shows verbose read data.
+
+- -p, plays with Bar Display, Dip Switch, 7-Segment Display.
+
+- -a, performs asynchronous I/O operation.
-**Playing with the 7 segment display, toggle switches and bar graph display**
+- -u, dumps USB configuration and pipe information.
-Use the command **osrusbfx2.exe -p** with options 1-9 to set and clear bar graph display, set and get 7-segment state, and read the toggle switch states. The following list shows the function options:
+### Playing with the 7 segment display, toggle switches and bar graph display
-1. Light bar
-2. Clear bar
-3. Light entire bar graph
-4. Clear entire bar graph
-5. Get bar graph state
-6. Get switch state
-7. Get switch interrupt message
-8. Get 7-segment state
-9. Set 7-segment state
+Use the command `osrusbfx2.exe -p` with options 1-9 to set and clear bar graph display, set and get 7-segment state, and read the toggle switch states. The following list shows the function options:
+
+```cmd
+1. Light bar
+2. Clear bar
+3. Light entire bar graph
+4. Clear entire bar graph
+5. Get bar graph state
+6. Get switch state
+7. Get switch interrupt message
+8. Get 7-segment state
+9. Set 7-segment state
10. Reset the device
11. Re-enumerate the device
0. Exit
Selection:
+```
-**Reset and re-enumerate the device**
+### Reset and re-enumerate the device
Use the command **osrusbfx2.exe -p** with option 10 and 11 to either reset the device or re-enumerate the device.
-**Read and write to bulk endpoints**
+### Read and write to bulk endpoints
The following commands send read and write requests to the device's bulk endpoint.
-- `osrusbfx2.exe -r 64`
+- `osrusbfx2.exe -r 64`
The preceding command reads 64 bytes to the bulk IN endpoint.
-- `osrusbfx2.exe -w 64 `
+- `osrusbfx2.exe -w 64`
The preceding command writes 64 bytes to the bulk OUT endpoint.
-- `osrusbfx2.exe -r 64 -w 64 -c 100 -v`
+- `osrusbfx2.exe -r 64 -w 64 -c 100 -v`
The preceding command first writes 64 bytes of data to bulk OUT endpoint (Pipe 1), then reads 64 bytes from bulk IN endpoint (Pipe 2), and then compares the read buffer with write buffer to see if they match. If the buffer contents match, it repeats this operation 100 times.
-- `osrusbfx2.exe -a`
+- `osrusbfx2.exe -a`
The preceding command reads and writes to the device asynchronously in an infinite loop.
The bulk endpoints are double buffered. Depending on the operational speed (full or high), the buffer size is either 64 bytes or 512 bytes, respectively. A request to read data doesn't complete if the buffers are empty. If the buffers are full, a request to write data does not complete until the buffers are emptied. When you are doing a synchronous read, make sure the endpoint buffer has data (for example, when you send 512 bytes write request to the device operating in full speed mode). Because the endpoints are double buffered, the total buffer capacity is 256 bytes. The first 256 bytes fills the buffer and the write request waits in the USB stack until the buffers are emptied. If you run another instance of the application to read 512 bytes of data, both write and read requests complete successfully.
-**Displaying descriptors**
+### Displaying descriptors
The following command displays all the descriptors and endpoint information.
-**osrusbfx2.exe -u**
+`osrusbfx2.exe -u`
If the device is operating in high speed mode, you get the following information:
-`===================`
+```cmd
+===================
-`USB_CONFIGURATION_DESCRIPTOR`
+USB_CONFIGURATION_DESCRIPTOR
-`bLength = 0x9, decimal 9`
+bLength = 0x9, decimal 9
-`bDescriptorType = 0x2 ( USB_CONFIGURATION_DESCRIPTOR_TYPE )`
+bDescriptorType = 0x2 ( USB_CONFIGURATION_DESCRIPTOR_TYPE )
-`wTotalLength = 0x27, decimal 39`
+wTotalLength = 0x27, decimal 39
-`bNumInterfaces = 0x1, decimal 1`
+bNumInterfaces = 0x1, decimal 1
-`bConfigurationValue = 0x1, decimal 1`
+bConfigurationValue = 0x1, decimal 1
-`iConfiguration = 0x4, decimal 4`
+iConfiguration = 0x4, decimal 4
-`bmAttributes = 0xa0 ( USB_CONFIG_BUS_POWERED )`
+bmAttributes = 0xa0 ( USB_CONFIG_BUS_POWERED )
-`MaxPower = 0x32, decimal 50`
+MaxPower = 0x32, decimal 50
-`-----------------------------`
+-----------------------------
-`USB_INTERFACE_DESCRIPTOR #0`
+USB_INTERFACE_DESCRIPTOR #0
-`bLength = 0x9`
+bLength = 0x9
-`bDescriptorType = 0x4 ( USB_INTERFACE_DESCRIPTOR_TYPE )`
+bDescriptorType = 0x4 ( USB_INTERFACE_DESCRIPTOR_TYPE )
-`bInterfaceNumber = 0x0`
+bInterfaceNumber = 0x0
-`bAlternateSetting = 0x0`
+bAlternateSetting = 0x0
-`bNumEndpoints = 0x3`
+bNumEndpoints = 0x3
-`bInterfaceClass = 0xff`
+bInterfaceClass = 0xff
-`bInterfaceSubClass = 0x0`
+bInterfaceSubClass = 0x0
-`bInterfaceProtocol = 0x0`
+bInterfaceProtocol = 0x0
-`bInterface = 0x0`
+bInterface = 0x0
-`------------------------------`
+------------------------------
-`USB_ENDPOINT_DESCRIPTOR for Pipe00`
+USB_ENDPOINT_DESCRIPTOR for Pipe00
-`bLength = 0x7`
+bLength = 0x7
-`bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )`
+bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )
-`bEndpointAddress= 0x81 ( INPUT )`
+bEndpointAddress= 0x81 ( INPUT )
-`bmAttributes= 0x3 ( USB_ENDPOINT_TYPE_INTERRUPT )`
+bmAttributes= 0x3 ( USB_ENDPOINT_TYPE_INTERRUPT )
-`wMaxPacketSize= 0x49, decimal 73`
+wMaxPacketSize= 0x49, decimal 73
-`bInterval = 0x1, decimal 1`
+bInterval = 0x1, decimal 1
-`------------------------------`
+------------------------------
-`USB_ENDPOINT_DESCRIPTOR for Pipe01`
+USB_ENDPOINT_DESCRIPTOR for Pipe01
-`bLength = 0x7`
+bLength = 0x7
-`bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )`
+bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )
-`bEndpointAddress= 0x6 ( OUTPUT )`
+bEndpointAddress= 0x6 ( OUTPUT )
-`bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )`
+bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )
-`wMaxPacketSize= 0x200, `
+wMaxPacketSize= 0x200,
-`decimal 512 bInterval = 0x0, `
+decimal 512 bInterval = 0x0,
-`decimal 0`
+decimal 0
-`------------------------------`
+------------------------------
-`USB_ENDPOINT_DESCRIPTOR for Pipe02`
+USB_ENDPOINT_DESCRIPTOR for Pipe02
-`bLength = 0x7`
+bLength = 0x7
-`bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )`
+bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )
-`bEndpointAddress= 0x88 ( INPUT )`
+bEndpointAddress= 0x88 ( INPUT )
-`bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )`
+bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )
-`wMaxPacketSize= 0x200, decimal 512`
+wMaxPacketSize= 0x200, decimal 512
-`bInterval = 0x0, decimal 0`
+bInterval = 0x0, decimal 0
+```
If the device is operating in low speed mode, you will get the following information:
-`===================`
+```txt
+===================
+
+USB_CONFIGURATION_DESCRIPTOR
+
+bLength = 0x9, decimal 9
+
+bDescriptorType = 0x2 ( USB_CONFIGURATION_DESCRIPTOR_TYPE )
+
+wTotalLength = 0x27, decimal 39
-`USB_CONFIGURATION_DESCRIPTOR`
+bNumInterfaces = 0x1, decimal 1
-`bLength = 0x9, decimal 9`
+bConfigurationValue = 0x1, decimal 1
-`bDescriptorType = 0x2 ( USB_CONFIGURATION_DESCRIPTOR_TYPE )`
+iConfiguration = 0x3, decimal 3
-`wTotalLength = 0x27, decimal 39`
+bmAttributes = 0xa0 ( USB_CONFIG_BUS_POWERED )
-`bNumInterfaces = 0x1, decimal 1`
+MaxPower = 0x32, decimal 50
-`bConfigurationValue = 0x1, decimal 1`
+-----------------------------
-`iConfiguration = 0x3, decimal 3`
+USB_INTERFACE_DESCRIPTOR #0
-`bmAttributes = 0xa0 ( USB_CONFIG_BUS_POWERED )`
+bLength = 0x9
-`MaxPower = 0x32, decimal 50 `
+bDescriptorType = 0x4 ( USB_INTERFACE_DESCRIPTOR_TYPE )
-`-----------------------------`
+bInterfaceNumber = 0x0 bAlternateSetting = 0x0
-`USB_INTERFACE_DESCRIPTOR #0`
+bNumEndpoints = 0x3
-`bLength = 0x9`
+bInterfaceClass = 0xff
-`bDescriptorType = 0x4 ( USB_INTERFACE_DESCRIPTOR_TYPE )`
+bInterfaceSubClass = 0x0
-`bInterfaceNumber = 0x0 bAlternateSetting = 0x0`
+bInterfaceProtocol = 0x0
-`bNumEndpoints = 0x3`
+bInterface = 0x0
-`bInterfaceClass = 0xff`
+------------------------------
-`bInterfaceSubClass = 0x0`
+USB_ENDPOINT_DESCRIPTOR for Pipe00
-`bInterfaceProtocol = 0x0`
+bLength = 0x7
-`bInterface = 0x0`
+bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )
-`------------------------------`
+bEndpointAddress= 0x81 ( INPUT )
-`USB_ENDPOINT_DESCRIPTOR for Pipe00`
+bmAttributes= 0x3 ( USB_ENDPOINT_TYPE_INTERRUPT )
-`bLength = 0x7`
+wMaxPacketSize= 0x49, decimal 73
-`bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )`
+bInterval = 0x1, decimal 1
-`bEndpointAddress= 0x81 ( INPUT )`
+------------------------------
-`bmAttributes= 0x3 ( USB_ENDPOINT_TYPE_INTERRUPT )`
+USB_ENDPOINT_DESCRIPTOR for Pipe01
-`wMaxPacketSize= 0x49, decimal 73`
+bLength = 0x7
-`bInterval = 0x1, decimal 1`
+bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )
-`------- -----------------------`
+bEndpointAddress= 0x6 ( OUTPUT )
-`USB_ENDPOINT_DESCRIPTOR for Pipe01`
+bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )
-`bLength = 0x7`
+wMaxPacketSize= 0x40, decimal 64
-`bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )`
+bInterval = 0x0, decimal 0
-`bEndpointAddress= 0x6 ( OUTPUT )`
+------------------------------
-`bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )`
+USB_ENDPOINT_DESCRIPTOR for Pipe02
-`wMaxPacketSize= 0x40, decimal 64`
+bLength = 0x7
-`bInterval = 0x0, decimal 0`
+bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )
-`------------------------------`
+bEndpointAddress= 0x88 ( INPUT )
-`USB_ENDPOINT_DESCRIPTOR for Pipe02`
+bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )
-`bLength = 0x7`
+wMaxPacketSize= 0x40, decimal 64
-`bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )`
+bInterval = 0x0, decimal 0
+```
-`bEndpointAddress= 0x88 ( INPUT )`
+## Sample Contents for UMDF
-`bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )`
+The UMDF sample driver is developed as a series of steps, starting with a basic "Hello World" driver. Each step progressively adds functionality to the previous step.
-`wMaxPacketSize= 0x40, decimal 64`
+### usb\wdf_osrfx2_lab\umdf\step1
-`bInterval = 0x0, decimal 0 `
+The most basic step. The source file contains a minimal amount of code to get the driver loaded in memory and respond to PnP and Power events. You can install, uninstall, disable, enable, suspend, and resume the system.
-Sample Contents for UMDF
-------------------------
+### usb\wdf_osrfx2_lab\umdf\step2
-The UMDF sample driver is developed as a series of steps, starting with a basic "Hello World" driver. Each step progressively adds functionality to the previous step. Each step is described in the following table.
+- The device registers a PnP device interface so that application can open a handle to the device.
-<table>
-<colgroup>
-<col width="50%" />
-<col width="50%" />
-</colgroup>
-<thead>
-<tr class="header">
-<th align="left">Folder
-Description</th>
-</tr>
-</thead>
-<tbody>
-<tr class="odd">
-<td align="left">usb\wdf_osrfx2_lab\umdf\step1
-The most basic step. The source file contains a minimal amount of code to get the driver loaded in memory and respond to PnP and Power events. You can install, uninstall, disable, enable, suspend, and resume the system.</td>
-<td align="left">usb\wdf_osrfx2_lab\umdf\step2
-<ol>
-<li>The device registers a PnP device interface so that application can open a handle to the device.</li>
-<li>The device object implements <strong>IPnpCallbackHardware</strong> interface and initializes USB I/O targets in <strong>IPnpCallbackHardware::OnPrepareHardware</strong> method.</li>
-</ol></td>
-</tr>
-</tbody>
-</table> \ No newline at end of file
+- The device object implements **IPnpCallbackHardware** interface and initializes USB I/O targets in **IPnpCallbackHardware::OnPrepareHardware** method.
diff --git a/video/IndirectDisplay/IddSampleApp/IddSampleApp.vcxproj b/video/IndirectDisplay/IddSampleApp/IddSampleApp.vcxproj
new file mode 100644
index 00000000..64eccf0a
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleApp/IddSampleApp.vcxproj
@@ -0,0 +1,276 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|ARM">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|ARM64">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM">
+ <Configuration>Release</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM64">
+ <Configuration>Release</Configuration>
+ <Platform>ARM64</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">
+ <VCProjectVersion>16.0</VCProjectVersion>
+ <ProjectGuid>{ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}</ProjectGuid>
+ <RootNamespace>IddSampleApp</RootNamespace>
+ <WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </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')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </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')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </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')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;swdevice.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;swdevice.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;swdevice.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;swdevice.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;swdevice.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;swdevice.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;swdevice.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;swdevice.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="main.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/video/IndirectDisplay/IddSampleApp/IddSampleApp.vcxproj.filters b/video/IndirectDisplay/IddSampleApp/IddSampleApp.vcxproj.filters
new file mode 100644
index 00000000..a91ad0ed
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleApp/IddSampleApp.vcxproj.filters
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="main.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/video/IndirectDisplay/IddSampleApp/main.cpp b/video/IndirectDisplay/IddSampleApp/main.cpp
new file mode 100644
index 00000000..e1d55ee8
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleApp/main.cpp
@@ -0,0 +1,93 @@
+#include <iostream>
+#include <vector>
+
+#include <windows.h>
+#include <swdevice.h>
+#include <conio.h>
+#include <wrl.h>
+
+VOID WINAPI
+CreationCallback(
+ _In_ HSWDEVICE hSwDevice,
+ _In_ HRESULT hrCreateResult,
+ _In_opt_ PVOID pContext,
+ _In_opt_ PCWSTR pszDeviceInstanceId
+ )
+{
+ HANDLE hEvent = *(HANDLE*) pContext;
+
+ SetEvent(hEvent);
+ UNREFERENCED_PARAMETER(hSwDevice);
+ UNREFERENCED_PARAMETER(hrCreateResult);
+ UNREFERENCED_PARAMETER(pszDeviceInstanceId);
+}
+
+int __cdecl main(int argc, wchar_t *argv[])
+{
+ UNREFERENCED_PARAMETER(argc);
+ UNREFERENCED_PARAMETER(argv);
+
+ HANDLE hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
+ HSWDEVICE hSwDevice;
+ SW_DEVICE_CREATE_INFO createInfo = { 0 };
+ PCWSTR description = L"Idd Sample Driver";
+
+ // These match the Pnp id's in the inf file so OS will load the driver when the device is created
+ PCWSTR instanceId = L"IddSampleDriver";
+ PCWSTR hardwareIds = L"IddSampleDriver\0\0";
+ PCWSTR compatibleIds = L"IddSampleDriver\0\0";
+
+ createInfo.cbSize = sizeof(createInfo);
+ createInfo.pszzCompatibleIds = compatibleIds;
+ createInfo.pszInstanceId = instanceId;
+ createInfo.pszzHardwareIds = hardwareIds;
+ createInfo.pszDeviceDescription = description;
+
+ createInfo.CapabilityFlags = SWDeviceCapabilitiesRemovable |
+ SWDeviceCapabilitiesSilentInstall |
+ SWDeviceCapabilitiesDriverRequired;
+
+ // Create the device
+ HRESULT hr = SwDeviceCreate(L"IddSampleDriver",
+ L"HTREE\\ROOT\\0",
+ &createInfo,
+ 0,
+ nullptr,
+ CreationCallback,
+ &hEvent,
+ &hSwDevice);
+ if (FAILED(hr))
+ {
+ printf("SwDeviceCreate failed with 0x%lx\n", hr);
+ return 1;
+ }
+
+ // Wait for callback to signal that the device has been created
+ printf("Waiting for device to be created....\n");
+ DWORD waitResult = WaitForSingleObject(hEvent, 10*1000);
+ if (waitResult != WAIT_OBJECT_0)
+ {
+ printf("Wait for device creation failed\n");
+ return 1;
+ }
+ printf("Device created\n\n");
+
+ // Now wait for user to indicate the device should be stopped
+ printf("Press 'x' to exit and destory the software device\n");
+ bool bExit = false;
+ do
+ {
+ // Wait for key press
+ int key = _getch();
+
+ if (key == 'x' || key == 'X')
+ {
+ bExit = true;
+ }
+ }while (!bExit);
+
+ // Stop the device, this will cause the sample to be unloaded
+ SwDeviceClose(hSwDevice);
+
+ return 0;
+} \ No newline at end of file
diff --git a/video/IndirectDisplay/IddSampleDriver.sln b/video/IndirectDisplay/IddSampleDriver.sln
new file mode 100644
index 00000000..c075ebc1
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleDriver.sln
@@ -0,0 +1,69 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29728.190
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IddSampleDriver", "IddSampleDriver\IddSampleDriver.vcxproj", "{2D54CB75-8B17-4F11-97DC-847B0244CD46}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IddSampleApp", "IddSampleApp\IddSampleApp.vcxproj", "{ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|ARM64 = Debug|ARM64
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM = Release|ARM
+ Release|ARM64 = Release|ARM64
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM.ActiveCfg = Debug|ARM
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM.Build.0 = Debug|ARM
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM.Deploy.0 = Debug|ARM
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM64.Build.0 = Debug|ARM64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM64.Deploy.0 = Debug|ARM64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x64.ActiveCfg = Debug|x64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x64.Build.0 = Debug|x64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x64.Deploy.0 = Debug|x64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x86.ActiveCfg = Debug|Win32
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x86.Build.0 = Debug|Win32
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x86.Deploy.0 = Debug|Win32
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM.ActiveCfg = Release|ARM
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM.Build.0 = Release|ARM
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM.Deploy.0 = Release|ARM
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM64.ActiveCfg = Release|ARM64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM64.Build.0 = Release|ARM64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM64.Deploy.0 = Release|ARM64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x64.ActiveCfg = Release|x64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x64.Build.0 = Release|x64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x64.Deploy.0 = Release|x64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x86.ActiveCfg = Release|Win32
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x86.Build.0 = Release|Win32
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x86.Deploy.0 = Release|Win32
+ {ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}.Debug|ARM.ActiveCfg = Debug|ARM
+ {ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}.Debug|ARM.Build.0 = Debug|ARM
+ {ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}.Debug|ARM64.Build.0 = Debug|ARM64
+ {ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}.Debug|x64.ActiveCfg = Debug|x64
+ {ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}.Debug|x64.Build.0 = Debug|x64
+ {ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}.Debug|x86.ActiveCfg = Debug|Win32
+ {ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}.Debug|x86.Build.0 = Debug|Win32
+ {ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}.Release|ARM.ActiveCfg = Release|ARM
+ {ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}.Release|ARM.Build.0 = Release|ARM
+ {ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}.Release|ARM64.ActiveCfg = Release|ARM64
+ {ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}.Release|ARM64.Build.0 = Release|ARM64
+ {ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}.Release|x64.ActiveCfg = Release|x64
+ {ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}.Release|x64.Build.0 = Release|x64
+ {ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}.Release|x86.ActiveCfg = Release|Win32
+ {ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {1C92CFF5-AC99-48BC-949B-7E7DD3AA4AD7}
+ EndGlobalSection
+EndGlobal
diff --git a/video/IndirectDisplay/IddSampleDriver/Driver.cpp b/video/IndirectDisplay/IddSampleDriver/Driver.cpp
new file mode 100644
index 00000000..ae060298
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleDriver/Driver.cpp
@@ -0,0 +1,809 @@
+/*++
+
+Copyright (c) Microsoft Corporation
+
+Abstract:
+
+ This module contains a sample implementation of an indirect display driver. See the included README.md file and the
+ various TODO blocks throughout this file and all accompanying files for information on building a production driver.
+
+ MSDN documentation on indirect displays can be found at https://msdn.microsoft.com/en-us/library/windows/hardware/mt761968(v=vs.85).aspx.
+
+Environment:
+
+ User Mode, UMDF
+
+--*/
+
+#include "Driver.h"
+#include "Driver.tmh"
+
+using namespace std;
+using namespace Microsoft::IndirectDisp;
+using namespace Microsoft::WRL;
+
+#pragma region SampleMonitors
+
+static constexpr DWORD IDD_SAMPLE_MONITOR_COUNT = 3; // If monitor count > ARRAYSIZE(s_SampleMonitors), we create edid-less monitors
+
+// Default modes reported for edid-less monitors. The first mode is set as preferred
+static const struct IndirectSampleMonitor::SampleMonitorMode s_SampleDefaultModes[] =
+{
+ { 1920, 1080, 60 },
+ { 1600, 900, 60 },
+ { 1024, 768, 75 },
+};
+
+// FOR SAMPLE PURPOSES ONLY, Static info about monitors that will be reported to OS
+static const struct IndirectSampleMonitor s_SampleMonitors[] =
+{
+ // Modified EDID from Dell S2719DGF
+ {
+ {
+ 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x10,0xAC,0xE6,0xD0,0x55,0x5A,0x4A,0x30,0x24,0x1D,0x01,
+ 0x04,0xA5,0x3C,0x22,0x78,0xFB,0x6C,0xE5,0xA5,0x55,0x50,0xA0,0x23,0x0B,0x50,0x54,0x00,0x02,0x00,
+ 0xD1,0xC0,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x58,0xE3,0x00,
+ 0xA0,0xA0,0xA0,0x29,0x50,0x30,0x20,0x35,0x00,0x55,0x50,0x21,0x00,0x00,0x1A,0x00,0x00,0x00,0xFF,
+ 0x00,0x37,0x4A,0x51,0x58,0x42,0x59,0x32,0x0A,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00,0xFC,0x00,
+ 0x53,0x32,0x37,0x31,0x39,0x44,0x47,0x46,0x0A,0x20,0x20,0x20,0x20,0x00,0x00,0x00,0xFD,0x00,0x28,
+ 0x9B,0xFA,0xFA,0x40,0x01,0x0A,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x2C
+ },
+ {
+ { 2560, 1440, 144 },
+ { 1920, 1080, 60 },
+ { 1024, 768, 60 },
+ },
+ 0
+ },
+ // Modified EDID from Lenovo Y27fA
+ {
+ {
+ 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x30,0xAE,0xBF,0x65,0x01,0x01,0x01,0x01,0x20,0x1A,0x01,
+ 0x04,0xA5,0x3C,0x22,0x78,0x3B,0xEE,0xD1,0xA5,0x55,0x48,0x9B,0x26,0x12,0x50,0x54,0x00,0x08,0x00,
+ 0xA9,0xC0,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x68,0xD8,0x00,
+ 0x18,0xF1,0x70,0x2D,0x80,0x58,0x2C,0x45,0x00,0x53,0x50,0x21,0x00,0x00,0x1E,0x00,0x00,0x00,0x10,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFD,0x00,
+ 0x30,0x92,0xB4,0xB4,0x22,0x01,0x0A,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00,0xFC,0x00,0x4C,
+ 0x45,0x4E,0x20,0x59,0x32,0x37,0x66,0x41,0x0A,0x20,0x20,0x20,0x00,0x11
+ },
+ {
+ { 3840, 2160, 60 },
+ { 1600, 900, 60 },
+ { 1024, 768, 60 },
+ },
+ 0
+ }
+};
+
+#pragma endregion
+
+#pragma region helpers
+
+static inline void FillSignalInfo(DISPLAYCONFIG_VIDEO_SIGNAL_INFO& Mode, DWORD Width, DWORD Height, DWORD VSync, bool bMonitorMode)
+{
+ Mode.totalSize.cx = Mode.activeSize.cx = Width;
+ Mode.totalSize.cy = Mode.activeSize.cy = Height;
+
+ // See https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-displayconfig_video_signal_info
+ Mode.AdditionalSignalInfo.vSyncFreqDivider = bMonitorMode ? 0 : 1;
+ Mode.AdditionalSignalInfo.videoStandard = 255;
+
+ Mode.vSyncFreq.Numerator = VSync;
+ Mode.vSyncFreq.Denominator = 1;
+ Mode.hSyncFreq.Numerator = VSync * Height;
+ Mode.hSyncFreq.Denominator = 1;
+
+ Mode.scanLineOrdering = DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE;
+
+ Mode.pixelRate = ((UINT64) VSync) * ((UINT64) Width) * ((UINT64) Height);
+}
+
+static IDDCX_MONITOR_MODE CreateIddCxMonitorMode(DWORD Width, DWORD Height, DWORD VSync, IDDCX_MONITOR_MODE_ORIGIN Origin = IDDCX_MONITOR_MODE_ORIGIN_DRIVER)
+{
+ IDDCX_MONITOR_MODE Mode = {};
+
+ Mode.Size = sizeof(Mode);
+ Mode.Origin = Origin;
+ FillSignalInfo(Mode.MonitorVideoSignalInfo, Width, Height, VSync, true);
+
+ return Mode;
+}
+
+static IDDCX_TARGET_MODE CreateIddCxTargetMode(DWORD Width, DWORD Height, DWORD VSync)
+{
+ IDDCX_TARGET_MODE Mode = {};
+
+ Mode.Size = sizeof(Mode);
+ FillSignalInfo(Mode.TargetVideoSignalInfo.targetVideoSignalInfo, Width, Height, VSync, false);
+
+ return Mode;
+}
+
+#pragma endregion
+
+extern "C" DRIVER_INITIALIZE DriverEntry;
+
+EVT_WDF_DRIVER_DEVICE_ADD IddSampleDeviceAdd;
+EVT_WDF_DEVICE_D0_ENTRY IddSampleDeviceD0Entry;
+
+EVT_IDD_CX_ADAPTER_INIT_FINISHED IddSampleAdapterInitFinished;
+EVT_IDD_CX_ADAPTER_COMMIT_MODES IddSampleAdapterCommitModes;
+
+EVT_IDD_CX_PARSE_MONITOR_DESCRIPTION IddSampleParseMonitorDescription;
+EVT_IDD_CX_MONITOR_GET_DEFAULT_DESCRIPTION_MODES IddSampleMonitorGetDefaultModes;
+EVT_IDD_CX_MONITOR_QUERY_TARGET_MODES IddSampleMonitorQueryModes;
+
+EVT_IDD_CX_MONITOR_ASSIGN_SWAPCHAIN IddSampleMonitorAssignSwapChain;
+EVT_IDD_CX_MONITOR_UNASSIGN_SWAPCHAIN IddSampleMonitorUnassignSwapChain;
+
+struct IndirectDeviceContextWrapper
+{
+ IndirectDeviceContext* pContext;
+
+ void Cleanup()
+ {
+ delete pContext;
+ pContext = nullptr;
+ }
+};
+
+struct IndirectMonitorContextWrapper
+{
+ IndirectMonitorContext* pContext;
+
+ void Cleanup()
+ {
+ delete pContext;
+ pContext = nullptr;
+ }
+};
+
+// This macro creates the methods for accessing an IndirectDeviceContextWrapper as a context for a WDF object
+WDF_DECLARE_CONTEXT_TYPE(IndirectDeviceContextWrapper);
+
+WDF_DECLARE_CONTEXT_TYPE(IndirectMonitorContextWrapper);
+
+extern "C" BOOL WINAPI DllMain(
+ _In_ HINSTANCE hInstance,
+ _In_ UINT dwReason,
+ _In_opt_ LPVOID lpReserved)
+{
+ UNREFERENCED_PARAMETER(hInstance);
+ UNREFERENCED_PARAMETER(lpReserved);
+ UNREFERENCED_PARAMETER(dwReason);
+
+ return TRUE;
+}
+
+_Use_decl_annotations_
+extern "C" NTSTATUS DriverEntry(
+ PDRIVER_OBJECT pDriverObject,
+ PUNICODE_STRING pRegistryPath
+)
+{
+ WDF_DRIVER_CONFIG Config;
+ NTSTATUS Status;
+
+ WDF_OBJECT_ATTRIBUTES Attributes;
+ WDF_OBJECT_ATTRIBUTES_INIT(&Attributes);
+
+ WDF_DRIVER_CONFIG_INIT(&Config,
+ IddSampleDeviceAdd
+ );
+
+ Status = WdfDriverCreate(pDriverObject, pRegistryPath, &Attributes, &Config, WDF_NO_HANDLE);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ return Status;
+}
+
+_Use_decl_annotations_
+NTSTATUS IddSampleDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT pDeviceInit)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerCallbacks;
+
+ UNREFERENCED_PARAMETER(Driver);
+
+ // Register for power callbacks - in this sample only power-on is needed
+ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerCallbacks);
+ PnpPowerCallbacks.EvtDeviceD0Entry = IddSampleDeviceD0Entry;
+ WdfDeviceInitSetPnpPowerEventCallbacks(pDeviceInit, &PnpPowerCallbacks);
+
+ IDD_CX_CLIENT_CONFIG IddConfig;
+ IDD_CX_CLIENT_CONFIG_INIT(&IddConfig);
+
+ // If the driver wishes to handle custom IoDeviceControl requests, it's necessary to use this callback since IddCx
+ // redirects IoDeviceControl requests to an internal queue. This sample does not need this.
+ // IddConfig.EvtIddCxDeviceIoControl = IddSampleIoDeviceControl;
+
+ IddConfig.EvtIddCxAdapterInitFinished = IddSampleAdapterInitFinished;
+
+ IddConfig.EvtIddCxParseMonitorDescription = IddSampleParseMonitorDescription;
+ IddConfig.EvtIddCxMonitorGetDefaultDescriptionModes = IddSampleMonitorGetDefaultModes;
+ IddConfig.EvtIddCxMonitorQueryTargetModes = IddSampleMonitorQueryModes;
+ IddConfig.EvtIddCxAdapterCommitModes = IddSampleAdapterCommitModes;
+ IddConfig.EvtIddCxMonitorAssignSwapChain = IddSampleMonitorAssignSwapChain;
+ IddConfig.EvtIddCxMonitorUnassignSwapChain = IddSampleMonitorUnassignSwapChain;
+
+ Status = IddCxDeviceInitConfig(pDeviceInit, &IddConfig);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ WDF_OBJECT_ATTRIBUTES Attr;
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&Attr, IndirectDeviceContextWrapper);
+ Attr.EvtCleanupCallback = [](WDFOBJECT Object)
+ {
+ // Automatically cleanup the context when the WDF object is about to be deleted
+ auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(Object);
+ if (pContext)
+ {
+ pContext->Cleanup();
+ }
+ };
+
+ WDFDEVICE Device = nullptr;
+ Status = WdfDeviceCreate(&pDeviceInit, &Attr, &Device);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ Status = IddCxDeviceInitialize(Device);
+
+ // Create a new device context object and attach it to the WDF device object
+ auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(Device);
+ pContext->pContext = new IndirectDeviceContext(Device);
+
+ return Status;
+}
+
+_Use_decl_annotations_
+NTSTATUS IddSampleDeviceD0Entry(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState)
+{
+ UNREFERENCED_PARAMETER(PreviousState);
+
+ // This function is called by WDF to start the device in the fully-on power state.
+
+ auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(Device);
+ pContext->pContext->InitAdapter();
+
+ return STATUS_SUCCESS;
+}
+
+#pragma region Direct3DDevice
+
+Direct3DDevice::Direct3DDevice(LUID AdapterLuid) : AdapterLuid(AdapterLuid)
+{
+
+}
+
+Direct3DDevice::Direct3DDevice()
+{
+ AdapterLuid = LUID{};
+}
+
+HRESULT Direct3DDevice::Init()
+{
+ // The DXGI factory could be cached, but if a new render adapter appears on the system, a new factory needs to be
+ // created. If caching is desired, check DxgiFactory->IsCurrent() each time and recreate the factory if !IsCurrent.
+ HRESULT hr = CreateDXGIFactory2(0, IID_PPV_ARGS(&DxgiFactory));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ // Find the specified render adapter
+ hr = DxgiFactory->EnumAdapterByLuid(AdapterLuid, IID_PPV_ARGS(&Adapter));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ // Create a D3D device using the render adapter. BGRA support is required by the WHQL test suite.
+ hr = D3D11CreateDevice(Adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, D3D11_CREATE_DEVICE_BGRA_SUPPORT, nullptr, 0, D3D11_SDK_VERSION, &Device, nullptr, &DeviceContext);
+ if (FAILED(hr))
+ {
+ // If creating the D3D device failed, it's possible the render GPU was lost (e.g. detachable GPU) or else the
+ // system is in a transient state.
+ return hr;
+ }
+
+ return S_OK;
+}
+
+#pragma endregion
+
+#pragma region SwapChainProcessor
+
+SwapChainProcessor::SwapChainProcessor(IDDCX_SWAPCHAIN hSwapChain, shared_ptr<Direct3DDevice> Device, HANDLE NewFrameEvent)
+ : m_hSwapChain(hSwapChain), m_Device(Device), m_hAvailableBufferEvent(NewFrameEvent)
+{
+ m_hTerminateEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr));
+
+ // Immediately create and run the swap-chain processing thread, passing 'this' as the thread parameter
+ m_hThread.Attach(CreateThread(nullptr, 0, RunThread, this, 0, nullptr));
+}
+
+SwapChainProcessor::~SwapChainProcessor()
+{
+ // Alert the swap-chain processing thread to terminate
+ SetEvent(m_hTerminateEvent.Get());
+
+ if (m_hThread.Get())
+ {
+ // Wait for the thread to terminate
+ WaitForSingleObject(m_hThread.Get(), INFINITE);
+ }
+}
+
+DWORD CALLBACK SwapChainProcessor::RunThread(LPVOID Argument)
+{
+ reinterpret_cast<SwapChainProcessor*>(Argument)->Run();
+ return 0;
+}
+
+void SwapChainProcessor::Run()
+{
+ // For improved performance, make use of the Multimedia Class Scheduler Service, which will intelligently
+ // prioritize this thread for improved throughput in high CPU-load scenarios.
+ DWORD AvTask = 0;
+ HANDLE AvTaskHandle = AvSetMmThreadCharacteristicsW(L"Distribution", &AvTask);
+
+ RunCore();
+
+ // Always delete the swap-chain object when swap-chain processing loop terminates in order to kick the system to
+ // provide a new swap-chain if necessary.
+ WdfObjectDelete((WDFOBJECT)m_hSwapChain);
+ m_hSwapChain = nullptr;
+
+ AvRevertMmThreadCharacteristics(AvTaskHandle);
+}
+
+void SwapChainProcessor::RunCore()
+{
+ // Get the DXGI device interface
+ ComPtr<IDXGIDevice> DxgiDevice;
+ HRESULT hr = m_Device->Device.As(&DxgiDevice);
+ if (FAILED(hr))
+ {
+ return;
+ }
+
+ IDARG_IN_SWAPCHAINSETDEVICE SetDevice = {};
+ SetDevice.pDevice = DxgiDevice.Get();
+
+ hr = IddCxSwapChainSetDevice(m_hSwapChain, &SetDevice);
+ if (FAILED(hr))
+ {
+ return;
+ }
+
+ // Acquire and release buffers in a loop
+ for (;;)
+ {
+ ComPtr<IDXGIResource> AcquiredBuffer;
+
+ // Ask for the next buffer from the producer
+ IDARG_OUT_RELEASEANDACQUIREBUFFER Buffer = {};
+ hr = IddCxSwapChainReleaseAndAcquireBuffer(m_hSwapChain, &Buffer);
+
+ // AcquireBuffer immediately returns STATUS_PENDING if no buffer is yet available
+ if (hr == E_PENDING)
+ {
+ // We must wait for a new buffer
+ HANDLE WaitHandles [] =
+ {
+ m_hAvailableBufferEvent,
+ m_hTerminateEvent.Get()
+ };
+ DWORD WaitResult = WaitForMultipleObjects(ARRAYSIZE(WaitHandles), WaitHandles, FALSE, 16);
+ if (WaitResult == WAIT_OBJECT_0 || WaitResult == WAIT_TIMEOUT)
+ {
+ // We have a new buffer, so try the AcquireBuffer again
+ continue;
+ }
+ else if (WaitResult == WAIT_OBJECT_0 + 1)
+ {
+ // We need to terminate
+ break;
+ }
+ else
+ {
+ // The wait was cancelled or something unexpected happened
+ hr = HRESULT_FROM_WIN32(WaitResult);
+ break;
+ }
+ }
+ else if (SUCCEEDED(hr))
+ {
+ // We have new frame to process, the surface has a reference on it that the driver has to release
+ AcquiredBuffer.Attach(Buffer.MetaData.pSurface);
+
+ // ==============================
+ // TODO: Process the frame here
+ //
+ // This is the most performance-critical section of code in an IddCx driver. It's important that whatever
+ // is done with the acquired surface be finished as quickly as possible. This operation could be:
+ // * a GPU copy to another buffer surface for later processing (such as a staging surface for mapping to CPU memory)
+ // * a GPU encode operation
+ // * a GPU VPBlt to another surface
+ // * a GPU custom compute shader encode operation
+ // ==============================
+
+ // We have finished processing this frame hence we release the reference on it.
+ // If the driver forgets to release the reference to the surface, it will be leaked which results in the
+ // surfaces being left around after swapchain is destroyed.
+ // NOTE: Although in this sample we release reference to the surface here; the driver still
+ // owns the Buffer.MetaData.pSurface surface until IddCxSwapChainReleaseAndAcquireBuffer returns
+ // S_OK and gives us a new frame, a driver may want to use the surface in future to re-encode the desktop
+ // for better quality if there is no new frame for a while
+ AcquiredBuffer.Reset();
+
+ // Indicate to OS that we have finished inital processing of the frame, it is a hint that
+ // OS could start preparing another frame
+ hr = IddCxSwapChainFinishedProcessingFrame(m_hSwapChain);
+ if (FAILED(hr))
+ {
+ break;
+ }
+
+ // ==============================
+ // TODO: Report frame statistics once the asynchronous encode/send work is completed
+ //
+ // Drivers should report information about sub-frame timings, like encode time, send time, etc.
+ // ==============================
+ // IddCxSwapChainReportFrameStatistics(m_hSwapChain, ...);
+ }
+ else
+ {
+ // The swap-chain was likely abandoned (e.g. DXGI_ERROR_ACCESS_LOST), so exit the processing loop
+ break;
+ }
+ }
+}
+
+#pragma endregion
+
+#pragma region IndirectDeviceContext
+
+IndirectDeviceContext::IndirectDeviceContext(_In_ WDFDEVICE WdfDevice) :
+ m_WdfDevice(WdfDevice)
+{
+ m_Adapter = {};
+}
+
+IndirectDeviceContext::~IndirectDeviceContext()
+{
+}
+
+void IndirectDeviceContext::InitAdapter()
+{
+ // ==============================
+ // TODO: Update the below diagnostic information in accordance with the target hardware. The strings and version
+ // numbers are used for telemetry and may be displayed to the user in some situations.
+ //
+ // This is also where static per-adapter capabilities are determined.
+ // ==============================
+
+ IDDCX_ADAPTER_CAPS AdapterCaps = {};
+ AdapterCaps.Size = sizeof(AdapterCaps);
+
+ // Declare basic feature support for the adapter (required)
+ AdapterCaps.MaxMonitorsSupported = IDD_SAMPLE_MONITOR_COUNT;
+ AdapterCaps.EndPointDiagnostics.Size = sizeof(AdapterCaps.EndPointDiagnostics);
+ AdapterCaps.EndPointDiagnostics.GammaSupport = IDDCX_FEATURE_IMPLEMENTATION_NONE;
+ AdapterCaps.EndPointDiagnostics.TransmissionType = IDDCX_TRANSMISSION_TYPE_WIRED_OTHER;
+
+ // Declare your device strings for telemetry (required)
+ AdapterCaps.EndPointDiagnostics.pEndPointFriendlyName = L"IddSample Device";
+ AdapterCaps.EndPointDiagnostics.pEndPointManufacturerName = L"Microsoft";
+ AdapterCaps.EndPointDiagnostics.pEndPointModelName = L"IddSample Model";
+
+ // Declare your hardware and firmware versions (required)
+ IDDCX_ENDPOINT_VERSION Version = {};
+ Version.Size = sizeof(Version);
+ Version.MajorVer = 1;
+ AdapterCaps.EndPointDiagnostics.pFirmwareVersion = &Version;
+ AdapterCaps.EndPointDiagnostics.pHardwareVersion = &Version;
+
+ // Initialize a WDF context that can store a pointer to the device context object
+ WDF_OBJECT_ATTRIBUTES Attr;
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&Attr, IndirectDeviceContextWrapper);
+
+ IDARG_IN_ADAPTER_INIT AdapterInit = {};
+ AdapterInit.WdfDevice = m_WdfDevice;
+ AdapterInit.pCaps = &AdapterCaps;
+ AdapterInit.ObjectAttributes = &Attr;
+
+ // Start the initialization of the adapter, which will trigger the AdapterFinishInit callback later
+ IDARG_OUT_ADAPTER_INIT AdapterInitOut;
+ NTSTATUS Status = IddCxAdapterInitAsync(&AdapterInit, &AdapterInitOut);
+
+ if (NT_SUCCESS(Status))
+ {
+ // Store a reference to the WDF adapter handle
+ m_Adapter = AdapterInitOut.AdapterObject;
+
+ // Store the device context object into the WDF object context
+ auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(AdapterInitOut.AdapterObject);
+ pContext->pContext = this;
+ }
+}
+
+void IndirectDeviceContext::FinishInit(UINT ConnectorIndex)
+{
+ // ==============================
+ // TODO: In a real driver, the EDID should be retrieved dynamically from a connected physical monitor. The EDIDs
+ // provided here are purely for demonstration.
+ // Monitor manufacturers are required to correctly fill in physical monitor attributes in order to allow the OS
+ // to optimize settings like viewing distance and scale factor. Manufacturers should also use a unique serial
+ // number every single device to ensure the OS can tell the monitors apart.
+ // ==============================
+
+ WDF_OBJECT_ATTRIBUTES Attr;
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&Attr, IndirectMonitorContextWrapper);
+
+ // In the sample driver, we report a monitor right away but a real driver would do this when a monitor connection event occurs
+ IDDCX_MONITOR_INFO MonitorInfo = {};
+ MonitorInfo.Size = sizeof(MonitorInfo);
+ MonitorInfo.MonitorType = DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI;
+ MonitorInfo.ConnectorIndex = ConnectorIndex;
+
+ MonitorInfo.MonitorDescription.Size = sizeof(MonitorInfo.MonitorDescription);
+ MonitorInfo.MonitorDescription.Type = IDDCX_MONITOR_DESCRIPTION_TYPE_EDID;
+ if (ConnectorIndex >= ARRAYSIZE(s_SampleMonitors))
+ {
+ MonitorInfo.MonitorDescription.DataSize = 0;
+ MonitorInfo.MonitorDescription.pData = nullptr;
+ }
+ else
+ {
+ MonitorInfo.MonitorDescription.DataSize = IndirectSampleMonitor::szEdidBlock;
+ MonitorInfo.MonitorDescription.pData = const_cast<BYTE*>(s_SampleMonitors[ConnectorIndex].pEdidBlock);
+ }
+
+ // ==============================
+ // TODO: The monitor's container ID should be distinct from "this" device's container ID if the monitor is not
+ // permanently attached to the display adapter device object. The container ID is typically made unique for each
+ // monitor and can be used to associate the monitor with other devices, like audio or input devices. In this
+ // sample we generate a random container ID GUID, but it's best practice to choose a stable container ID for a
+ // unique monitor or to use "this" device's container ID for a permanent/integrated monitor.
+ // ==============================
+
+ // Create a container ID
+ CoCreateGuid(&MonitorInfo.MonitorContainerId);
+
+ IDARG_IN_MONITORCREATE MonitorCreate = {};
+ MonitorCreate.ObjectAttributes = &Attr;
+ MonitorCreate.pMonitorInfo = &MonitorInfo;
+
+ // Create a monitor object with the specified monitor descriptor
+ IDARG_OUT_MONITORCREATE MonitorCreateOut;
+ NTSTATUS Status = IddCxMonitorCreate(m_Adapter, &MonitorCreate, &MonitorCreateOut);
+ if (NT_SUCCESS(Status))
+ {
+ // Create a new monitor context object and attach it to the Idd monitor object
+ auto* pMonitorContextWrapper = WdfObjectGet_IndirectMonitorContextWrapper(MonitorCreateOut.MonitorObject);
+ pMonitorContextWrapper->pContext = new IndirectMonitorContext(MonitorCreateOut.MonitorObject);
+
+ // Tell the OS that the monitor has been plugged in
+ IDARG_OUT_MONITORARRIVAL ArrivalOut;
+ Status = IddCxMonitorArrival(MonitorCreateOut.MonitorObject, &ArrivalOut);
+ }
+}
+
+IndirectMonitorContext::IndirectMonitorContext(_In_ IDDCX_MONITOR Monitor) :
+ m_Monitor(Monitor)
+{
+}
+
+IndirectMonitorContext::~IndirectMonitorContext()
+{
+ m_ProcessingThread.reset();
+}
+
+void IndirectMonitorContext::AssignSwapChain(IDDCX_SWAPCHAIN SwapChain, LUID RenderAdapter, HANDLE NewFrameEvent)
+{
+ m_ProcessingThread.reset();
+
+ auto Device = make_shared<Direct3DDevice>(RenderAdapter);
+ if (FAILED(Device->Init()))
+ {
+ // It's important to delete the swap-chain if D3D initialization fails, so that the OS knows to generate a new
+ // swap-chain and try again.
+ WdfObjectDelete(SwapChain);
+ }
+ else
+ {
+ // Create a new swap-chain processing thread
+ m_ProcessingThread.reset(new SwapChainProcessor(SwapChain, Device, NewFrameEvent));
+ }
+}
+
+void IndirectMonitorContext::UnassignSwapChain()
+{
+ // Stop processing the last swap-chain
+ m_ProcessingThread.reset();
+}
+
+#pragma endregion
+
+#pragma region DDI Callbacks
+
+_Use_decl_annotations_
+NTSTATUS IddSampleAdapterInitFinished(IDDCX_ADAPTER AdapterObject, const IDARG_IN_ADAPTER_INIT_FINISHED* pInArgs)
+{
+ // This is called when the OS has finished setting up the adapter for use by the IddCx driver. It's now possible
+ // to report attached monitors.
+
+ auto* pDeviceContextWrapper = WdfObjectGet_IndirectDeviceContextWrapper(AdapterObject);
+ if (NT_SUCCESS(pInArgs->AdapterInitStatus))
+ {
+ for (DWORD i = 0; i < IDD_SAMPLE_MONITOR_COUNT; i++)
+ {
+ pDeviceContextWrapper->pContext->FinishInit(i);
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+NTSTATUS IddSampleAdapterCommitModes(IDDCX_ADAPTER AdapterObject, const IDARG_IN_COMMITMODES* pInArgs)
+{
+ UNREFERENCED_PARAMETER(AdapterObject);
+ UNREFERENCED_PARAMETER(pInArgs);
+
+ // For the sample, do nothing when modes are picked - the swap-chain is taken care of by IddCx
+
+ // ==============================
+ // TODO: In a real driver, this function would be used to reconfigure the device to commit the new modes. Loop
+ // through pInArgs->pPaths and look for IDDCX_PATH_FLAGS_ACTIVE. Any path not active is inactive (e.g. the monitor
+ // should be turned off).
+ // ==============================
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+NTSTATUS IddSampleParseMonitorDescription(const IDARG_IN_PARSEMONITORDESCRIPTION* pInArgs, IDARG_OUT_PARSEMONITORDESCRIPTION* pOutArgs)
+{
+ // ==============================
+ // TODO: In a real driver, this function would be called to generate monitor modes for an EDID by parsing it. In
+ // this sample driver, we hard-code the EDID, so this function can generate known modes.
+ // ==============================
+
+ pOutArgs->MonitorModeBufferOutputCount = IndirectSampleMonitor::szModeList;
+
+ if (pInArgs->MonitorModeBufferInputCount < IndirectSampleMonitor::szModeList)
+ {
+ // Return success if there was no buffer, since the caller was only asking for a count of modes
+ return (pInArgs->MonitorModeBufferInputCount > 0) ? STATUS_BUFFER_TOO_SMALL : STATUS_SUCCESS;
+ }
+ else
+ {
+ // In the sample driver, we have reported some static information about connected monitors
+ // Check which of the reported monitors this call is for by comparing it to the pointer of
+ // our known EDID blocks.
+
+ if (pInArgs->MonitorDescription.DataSize != IndirectSampleMonitor::szEdidBlock)
+ return STATUS_INVALID_PARAMETER;
+
+ DWORD SampleMonitorIdx = 0;
+ for(; SampleMonitorIdx < ARRAYSIZE(s_SampleMonitors); SampleMonitorIdx++)
+ {
+ if (memcmp(pInArgs->MonitorDescription.pData, s_SampleMonitors[SampleMonitorIdx].pEdidBlock, IndirectSampleMonitor::szEdidBlock) == 0)
+ {
+ // Copy the known modes to the output buffer
+ for (DWORD ModeIndex = 0; ModeIndex < IndirectSampleMonitor::szModeList; ModeIndex++)
+ {
+ pInArgs->pMonitorModes[ModeIndex] = CreateIddCxMonitorMode(
+ s_SampleMonitors[SampleMonitorIdx].pModeList[ModeIndex].Width,
+ s_SampleMonitors[SampleMonitorIdx].pModeList[ModeIndex].Height,
+ s_SampleMonitors[SampleMonitorIdx].pModeList[ModeIndex].VSync,
+ IDDCX_MONITOR_MODE_ORIGIN_MONITORDESCRIPTOR
+ );
+ }
+
+ // Set the preferred mode as represented in the EDID
+ pOutArgs->PreferredMonitorModeIdx = s_SampleMonitors[SampleMonitorIdx].ulPreferredModeIdx;
+
+ return STATUS_SUCCESS;
+ }
+ }
+
+ // This EDID block does not belong to the monitors we reported earlier
+ return STATUS_INVALID_PARAMETER;
+ }
+}
+
+_Use_decl_annotations_
+NTSTATUS IddSampleMonitorGetDefaultModes(IDDCX_MONITOR MonitorObject, const IDARG_IN_GETDEFAULTDESCRIPTIONMODES* pInArgs, IDARG_OUT_GETDEFAULTDESCRIPTIONMODES* pOutArgs)
+{
+ UNREFERENCED_PARAMETER(MonitorObject);
+
+ // ==============================
+ // TODO: In a real driver, this function would be called to generate monitor modes for a monitor with no EDID.
+ // Drivers should report modes that are guaranteed to be supported by the transport protocol and by nearly all
+ // monitors (such 640x480, 800x600, or 1024x768). If the driver has access to monitor modes from a descriptor other
+ // than an EDID, those modes would also be reported here.
+ // ==============================
+
+ if (pInArgs->DefaultMonitorModeBufferInputCount == 0)
+ {
+ pOutArgs->DefaultMonitorModeBufferOutputCount = ARRAYSIZE(s_SampleDefaultModes);
+ }
+ else
+ {
+ for (DWORD ModeIndex = 0; ModeIndex < ARRAYSIZE(s_SampleDefaultModes); ModeIndex++)
+ {
+ pInArgs->pDefaultMonitorModes[ModeIndex] = CreateIddCxMonitorMode(
+ s_SampleDefaultModes[ModeIndex].Width,
+ s_SampleDefaultModes[ModeIndex].Height,
+ s_SampleDefaultModes[ModeIndex].VSync,
+ IDDCX_MONITOR_MODE_ORIGIN_DRIVER
+ );
+ }
+
+ pOutArgs->DefaultMonitorModeBufferOutputCount = ARRAYSIZE(s_SampleDefaultModes);
+ pOutArgs->PreferredMonitorModeIdx = 0;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+NTSTATUS IddSampleMonitorQueryModes(IDDCX_MONITOR MonitorObject, const IDARG_IN_QUERYTARGETMODES* pInArgs, IDARG_OUT_QUERYTARGETMODES* pOutArgs)
+{
+ UNREFERENCED_PARAMETER(MonitorObject);
+
+ vector<IDDCX_TARGET_MODE> TargetModes;
+
+ // Create a set of modes supported for frame processing and scan-out. These are typically not based on the
+ // monitor's descriptor and instead are based on the static processing capability of the device. The OS will
+ // report the available set of modes for a given output as the intersection of monitor modes with target modes.
+
+ TargetModes.push_back(CreateIddCxTargetMode(3840, 2160, 60));
+ TargetModes.push_back(CreateIddCxTargetMode(2560, 1440, 144));
+ TargetModes.push_back(CreateIddCxTargetMode(2560, 1440, 90));
+ TargetModes.push_back(CreateIddCxTargetMode(2560, 1440, 60));
+ TargetModes.push_back(CreateIddCxTargetMode(1920, 1080, 144));
+ TargetModes.push_back(CreateIddCxTargetMode(1920, 1080, 90));
+ TargetModes.push_back(CreateIddCxTargetMode(1920, 1080, 60));
+ TargetModes.push_back(CreateIddCxTargetMode(1600, 900, 60));
+ TargetModes.push_back(CreateIddCxTargetMode(1024, 768, 75));
+ TargetModes.push_back(CreateIddCxTargetMode(1024, 768, 60));
+
+ pOutArgs->TargetModeBufferOutputCount = (UINT) TargetModes.size();
+
+ if (pInArgs->TargetModeBufferInputCount >= TargetModes.size())
+ {
+ copy(TargetModes.begin(), TargetModes.end(), pInArgs->pTargetModes);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+NTSTATUS IddSampleMonitorAssignSwapChain(IDDCX_MONITOR MonitorObject, const IDARG_IN_SETSWAPCHAIN* pInArgs)
+{
+ auto* pMonitorContextWrapper = WdfObjectGet_IndirectMonitorContextWrapper(MonitorObject);
+ pMonitorContextWrapper->pContext->AssignSwapChain(pInArgs->hSwapChain, pInArgs->RenderAdapterLuid, pInArgs->hNextSurfaceAvailable);
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+NTSTATUS IddSampleMonitorUnassignSwapChain(IDDCX_MONITOR MonitorObject)
+{
+ auto* pMonitorContextWrapper = WdfObjectGet_IndirectMonitorContextWrapper(MonitorObject);
+ pMonitorContextWrapper->pContext->UnassignSwapChain();
+ return STATUS_SUCCESS;
+}
+
+#pragma endregion
diff --git a/video/IndirectDisplay/IddSampleDriver/Driver.h b/video/IndirectDisplay/IddSampleDriver/Driver.h
new file mode 100644
index 00000000..373b5a25
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleDriver/Driver.h
@@ -0,0 +1,122 @@
+#pragma once
+
+#define NOMINMAX
+#include <windows.h>
+#include <bugcodes.h>
+#include <wudfwdm.h>
+#include <wdf.h>
+#include <iddcx.h>
+
+#include <dxgi1_5.h>
+#include <d3d11_2.h>
+#include <avrt.h>
+#include <wrl.h>
+
+#include <memory>
+#include <vector>
+
+#include "Trace.h"
+
+namespace Microsoft
+{
+ namespace WRL
+ {
+ namespace Wrappers
+ {
+ // Adds a wrapper for thread handles to the existing set of WRL handle wrapper classes
+ typedef HandleT<HandleTraits::HANDLENullTraits> Thread;
+ }
+ }
+}
+
+namespace Microsoft
+{
+ namespace IndirectDisp
+ {
+ /// <summary>
+ /// Manages the creation and lifetime of a Direct3D render device.
+ /// </summary>
+ struct IndirectSampleMonitor
+ {
+ static constexpr size_t szEdidBlock = 128;
+ static constexpr size_t szModeList = 3;
+
+ const BYTE pEdidBlock[szEdidBlock];
+ const struct SampleMonitorMode {
+ DWORD Width;
+ DWORD Height;
+ DWORD VSync;
+ } pModeList[szModeList];
+ const DWORD ulPreferredModeIdx;
+ };
+
+ /// <summary>
+ /// Manages the creation and lifetime of a Direct3D render device.
+ /// </summary>
+ struct Direct3DDevice
+ {
+ Direct3DDevice(LUID AdapterLuid);
+ Direct3DDevice();
+ HRESULT Init();
+
+ LUID AdapterLuid;
+ Microsoft::WRL::ComPtr<IDXGIFactory5> DxgiFactory;
+ Microsoft::WRL::ComPtr<IDXGIAdapter1> Adapter;
+ Microsoft::WRL::ComPtr<ID3D11Device> Device;
+ Microsoft::WRL::ComPtr<ID3D11DeviceContext> DeviceContext;
+ };
+
+ /// <summary>
+ /// Manages a thread that consumes buffers from an indirect display swap-chain object.
+ /// </summary>
+ class SwapChainProcessor
+ {
+ public:
+ SwapChainProcessor(IDDCX_SWAPCHAIN hSwapChain, std::shared_ptr<Direct3DDevice> Device, HANDLE NewFrameEvent);
+ ~SwapChainProcessor();
+
+ private:
+ static DWORD CALLBACK RunThread(LPVOID Argument);
+
+ void Run();
+ void RunCore();
+
+ IDDCX_SWAPCHAIN m_hSwapChain;
+ std::shared_ptr<Direct3DDevice> m_Device;
+ HANDLE m_hAvailableBufferEvent;
+ Microsoft::WRL::Wrappers::Thread m_hThread;
+ Microsoft::WRL::Wrappers::Event m_hTerminateEvent;
+ };
+
+ /// <summary>
+ /// Provides a sample implementation of an indirect display driver.
+ /// </summary>
+ class IndirectDeviceContext
+ {
+ public:
+ IndirectDeviceContext(_In_ WDFDEVICE WdfDevice);
+ virtual ~IndirectDeviceContext();
+
+ void InitAdapter();
+ void FinishInit(UINT ConnectorIndex);
+
+ protected:
+ WDFDEVICE m_WdfDevice;
+ IDDCX_ADAPTER m_Adapter;
+ };
+
+ class IndirectMonitorContext
+ {
+ public:
+ IndirectMonitorContext(_In_ IDDCX_MONITOR Monitor);
+ virtual ~IndirectMonitorContext();
+
+ void AssignSwapChain(IDDCX_SWAPCHAIN SwapChain, LUID RenderAdapter, HANDLE NewFrameEvent);
+ void UnassignSwapChain();
+
+ private:
+ IDDCX_MONITOR m_Monitor;
+ std::unique_ptr<SwapChainProcessor> m_ProcessingThread;
+ } ;
+ }
+}
diff --git a/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.inf b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.inf
new file mode 100644
index 00000000..d70c8a87
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.inf
Binary files differ
diff --git a/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.rc b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.rc
new file mode 100644
index 00000000..ca2d8226
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.rc
@@ -0,0 +1,10 @@
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "UMDF Indirect Display Driver Sample"
+#define VER_INTERNALNAME_STR "IddSampleDriver"
+#define VER_ORIGINALFILENAME_STR "IddSampleDriver.dll"
+
+#include "common.ver"
diff --git a/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj
new file mode 100644
index 00000000..288dbb03
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj
@@ -0,0 +1,333 @@
+<?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>
+ <ProjectConfiguration Include="Debug|ARM">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM">
+ <Configuration>Release</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|ARM64">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM64">
+ <Configuration>Release</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="Driver.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="Driver.h" />
+ <ClInclude Include="Trace.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Include="IddSampleDriver.inf" />
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{2D54CB75-8B17-4F11-97DC-847B0244CD46}</ProjectGuid>
+ <TemplateGuid>{32909489-7be5-497b-aafa-db6669d9b44b}</TemplateGuid>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
+ <Configuration>Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <RootNamespace>IddSampleDriver</RootNamespace>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR>
+ <IndirectDisplayDriver>true</IndirectDisplayDriver>
+ <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
+ <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR>
+ <IndirectDisplayDriver>true</IndirectDisplayDriver>
+ <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
+ <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR>
+ <IndirectDisplayDriver>true</IndirectDisplayDriver>
+ <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
+ <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR>
+ <IndirectDisplayDriver>true</IndirectDisplayDriver>
+ <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
+ <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR>
+ <IndirectDisplayDriver>true</IndirectDisplayDriver>
+ <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
+ <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR>
+ <IndirectDisplayDriver>true</IndirectDisplayDriver>
+ <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
+ <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR>
+ <IndirectDisplayDriver>true</IndirectDisplayDriver>
+ <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
+ <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR>
+ <IndirectDisplayDriver>true</IndirectDisplayDriver>
+ <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
+ <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <EnablePREfast>true</EnablePREfast>
+ <AdditionalOptions>/DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
+ </Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <EnablePREfast>true</EnablePREfast>
+ <AdditionalOptions>/DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
+ </Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <EnablePREfast>true</EnablePREfast>
+ <PreprocessorDefinitions>_WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalOptions>/D_ATL_NO_WIN_SUPPORT /DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
+ </Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <EnablePREfast>true</EnablePREfast>
+ <PreprocessorDefinitions>_WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalOptions>/D_ATL_NO_WIN_SUPPORT /DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
+ <AdditionalOptions>%(AdditionalOptions)</AdditionalOptions>
+ </Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <EnablePREfast>true</EnablePREfast>
+ <AdditionalOptions>/DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <EnablePREfast>true</EnablePREfast>
+ <AdditionalOptions>/DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <EnablePREfast>true</EnablePREfast>
+ <AdditionalOptions>/DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <EnablePREfast>true</EnablePREfast>
+ <AdditionalOptions>/DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <FilesToPackage Include="$(TargetPath)" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj.filters b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj.filters
new file mode 100644
index 00000000..f47c3804
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj.filters
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ <Filter Include="Driver Files">
+ <UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Include="IddSampleDriver.inf">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="Driver.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Trace.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="Driver.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/video/IndirectDisplay/IddSampleDriver/Trace.h b/video/IndirectDisplay/IddSampleDriver/Trace.h
new file mode 100644
index 00000000..9852bab4
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleDriver/Trace.h
@@ -0,0 +1,63 @@
+/*++
+
+Module Name:
+
+ Internal.h
+
+Abstract:
+
+ This module contains the local type definitions for the
+ driver.
+
+Environment:
+
+ Windows User-Mode Driver Framework 2
+
+--*/
+
+//
+// Define the tracing flags.
+//
+// Tracing GUID - b254994f-46e6-4718-80a0-0a3aa50d6ce4
+//
+
+#define WPP_CONTROL_GUIDS \
+ WPP_DEFINE_CONTROL_GUID( \
+ MyDriver1TraceGuid, (b254994f,46e6,4718,80a0,0a3aa50d6ce4), \
+ \
+ WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \
+ WPP_DEFINE_BIT(TRACE_DRIVER) \
+ WPP_DEFINE_BIT(TRACE_DEVICE) \
+ WPP_DEFINE_BIT(TRACE_QUEUE) \
+ )
+
+#define WPP_FLAG_LEVEL_LOGGER(flag, level) \
+ WPP_LEVEL_LOGGER(flag)
+
+#define WPP_FLAG_LEVEL_ENABLED(flag, level) \
+ (WPP_LEVEL_ENABLED(flag) && \
+ WPP_CONTROL(WPP_BIT_ ## flag).Level >= level)
+
+#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \
+ WPP_LEVEL_LOGGER(flags)
+
+#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \
+ (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)
+
+//
+// This comment block is scanned by the trace preprocessor to define our
+// Trace function.
+//
+// begin_wpp config
+// FUNC Trace{FLAG=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...);
+// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
+// end_wpp
+
+//
+//
+// Driver specific #defines
+//
+
+// TODO: Use a unique driver tracing ID here,
+// see https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/adding-wpp-software-tracing-to-a-windows-driver
+#define MYDRIVER_TRACING_ID L"Microsoft\\UMDF2.25\\IddSampleDriver v1.0"
diff --git a/video/IndirectDisplay/README.md b/video/IndirectDisplay/README.md
new file mode 100644
index 00000000..ac399233
--- /dev/null
+++ b/video/IndirectDisplay/README.md
@@ -0,0 +1,48 @@
+---
+topic: sample
+page_type: sample
+languages:
+- cpp
+products:
+- windows
+- windows-wdk
+name: 'IddSample'
+description: "Implements a sample IddCx 1.4 driver and a sample application that instantiates a software device using it."
+statusNotificationTargets:
+---
+
+# Indirect Display Driver Sample #
+
+This is a sample driver that shows how to create a Windows Indirect Display Driver using IddCx (Indirect Display Driver Class eXtension).
+
+## Background reading ##
+
+Start at the [Indirect Display Driver Model Overview](https://msdn.microsoft.com/en-us/library/windows/hardware/mt761968(v=vs.85).aspx) on MSDN.
+
+## Customizing the sample ##
+
+The sample driver code is very simplistic and does nothing more than enumerate a single monitor when its device enters the D0/started power state. Throughout the code, there are `TODO` blocks with important information on implementing functionality in a production driver.
+
+### Code structure ###
+
+* `Direct3DDevice` class
+ * Contains logic for enumerating the correct render GPU from DXGI and creating a D3D device.
+ * Manages the lifetime of a DXGI factory and a D3D device created for the render GPU the system is using to render frames for your indirect display device's swap-chain.
+* `SwapChainProcessor` class
+ * Processes frames for a swap-chain assigned to the monitor object on a dedicated thread.
+ * The sample code does nothing with the frames, but demonstrates a correct processing loop with error handling and notifying the OS of frame completion.
+* `IndirectDeviceContext` class
+ * Processes device callbacks from IddCx.
+ * Manages the creation and arrival of the sample monitor.
+ * Handles swap-chain arrival and departure by creating a `Direct3DDevice` and handing it off to a `SwapChainProcessor`.
+
+### First steps ###
+
+Consider the capabilities of your device. If the device supports multiple monitors being hotplugged and removed at runtime, you may want to abstract the monitors further from the `IndirectDeviceContext` class.
+
+The INF file included in the sample needs updating for production use. One field, `DeviceGroupId`, controls how the UMDF driver gets pooled with other UMDF drivers in the same process. Since indirect display drivers tend to be more complicated than other driver classes, it's highly recommended that you pick a unique string for this field which will cause instances of your device driver to pool in a dedicated process. This will improve system reliability in case your driver encounters a problem since other drivers will not be affected.
+
+Ensure the device information reported to `IddCxAdapterInitAsync` is accurate. This information determines how the device is reported to the OS and what static features (like support for gamma tables) the device will have available. If some information cannot be known immediately in the `EvtDeviceD0Entry` callback, IddCx allows the driver to call `IddCxAdapterInitAsync` at any point after D0 entry, before D0 exit.
+
+Careful attention should be paid to the frame processing loop. This will directly impact the performance of the user's system, so making use of the [Multimedia Class Scheduler Service](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684247(v=vs.85).aspx) and DXGI's support for [GPU prioritization](https://msdn.microsoft.com/en-us/library/windows/desktop/bb174534(v=vs.85).aspx) should be considered. Any significant work should be performed outside the main processing loop, such as by queuing work in a thread pool. See `SwapChainProcessor::RunCore` for more information. \ No newline at end of file
diff --git a/video/KMDOD/README.md b/video/KMDOD/README.md
index b6f165fa..39d1df7e 100644
--- a/video/KMDOD/README.md
+++ b/video/KMDOD/README.md
@@ -5,22 +5,14 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Kernel mode display-only miniport driver (KMDOD) sample
- platform: WDM
- language: cpp
- category: Video
- description: Implements most DDIs that a display-only miniport driver should provide to the Windows Display Driver Model (WDDM).
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620317
---->
-
# Kernel mode display-only miniport driver (KMDOD) sample
The kernel mode display-only miniport driver (KMDOD) sample implements most of the device driver interfaces (DDIs) that a display-only miniport driver should provide to the Windows Display Driver Model (WDDM). The code is useful to understand how to write a miniport driver for a display-only device, or how to develop a full WDDM driver.
-For more info on how a KMDOD works, see [Kernel Mode Display-Only Driver (KMDOD) Interface](http://msdn.microsoft.com/en-us/library/windows/hardware/jj673962). For more info on WDDM drivers, see [Windows Display Driver Model (WDDM) Design Guide](http://msdn.microsoft.com/en-us/library/windows/hardware/ff570593).
+For more info on WDDM drivers, see [Windows Display Driver Model (WDDM) Design Guide](https://docs.microsoft.com/windows-hardware/drivers/display/windows-vista-display-driver-model-design-guide).
This code can also help you to understand the use and implementation of display-related DDIs. The INF file shows how to make a display miniport driver visible to other WDDM components.
@@ -32,14 +24,18 @@ If the current display driver is not a WDDM 1.2 compliant driver, the sample dri
## Installation
-In Microsoft Visual Studio, press **F5** to build the sample and then deploy it to a target machine. For more info, see [Deploying a Driver to a Test Computer](http://msdn.microsoft.com/en-us/library/windows/hardware/hh454834).
+In Microsoft Visual Studio, press **F5** to build the sample and then deploy it to a target machine. For more info, see [Deploying a Driver to a Test Computer](https://docs.microsoft.com/windows-hardware/drivers/develop/deploying-a-driver-to-a-test-computer).
In some cases you might need to install the driver manually, as follows.
1. Add the following files to the directory given by ...\\[x64]\\C++\\Package:
+
- SampleDriver.cat
+
- SampleDriver.inf
+
- SampleDriver.sys
+
- SampleDriver.cer
1. Unless you've provided a production certificate, you should manually install the SampleDriver.cer digital certificate with the following command:
@@ -50,9 +46,10 @@ In some cases you might need to install the driver manually, as follows.
`Bcdedit.exe -set TESTSIGNING ON`
- **Note** After you change the TESTSIGNING boot configuration option, restart the computer for the change to take effect.
+ > [!NOTE]
+ > After you change the TESTSIGNING boot configuration option, restart the computer for the change to take effect.
- For more info, see [The TESTSIGNING Boot Configuration Option](http://msdn.microsoft.com/en-us/library/windows/hardware/ff553484).
+ For more info, see [The TESTSIGNING Boot Configuration Option](https://docs.microsoft.com/windows-hardware/drivers/install/the-testsigning-boot-configuration-option).
1. Manually install the driver using Device Manager, which is available from Control Panel.
@@ -69,4 +66,4 @@ Text
This new code provides generic identifiers for ACPI hardware.
-You can optionally delete the original lines of code within these sections of the INF file. \ No newline at end of file
+You can optionally delete the original lines of code within these sections of the INF file.
diff --git a/video/KMDOD/Sample/SampleDisplay.vcxproj b/video/KMDOD/Sample/SampleDisplay.vcxproj
index e311f25c..30a147c5 100644
--- a/video/KMDOD/Sample/SampleDisplay.vcxproj
+++ b/video/KMDOD/Sample/SampleDisplay.vcxproj
@@ -149,6 +149,9 @@
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -156,6 +159,9 @@
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -163,6 +169,9 @@
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -170,6 +179,9 @@
<ExceptionHandling>
</ExceptionHandling>
</ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\BDD.cxx" />
diff --git a/video/KMDOD/Sample/SampleDisplay.vcxproj.Filters b/video/KMDOD/Sample/SampleDisplay.vcxproj.Filters
index 05bf803c..22e4ae5a 100644
--- a/video/KMDOD/Sample/SampleDisplay.vcxproj.Filters
+++ b/video/KMDOD/Sample/SampleDisplay.vcxproj.Filters
@@ -46,4 +46,4 @@
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
-</Project> \ No newline at end of file
+</Project>
diff --git a/video/pixlib/README.md b/video/pixlib/README.md
index 288f0da4..4153a4c3 100644
--- a/video/pixlib/README.md
+++ b/video/pixlib/README.md
@@ -5,19 +5,11 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: PixLib sample
- platform: LIB
- language: cpp
- category: Video
- description: Demonstrates how to implement the CPixel class for use by a display driver.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=618005
---->
-
# PixLib sample
The PixLib sample demonstrates how to implement the **CPixel** class for use by a display driver.
-For more information, see the WDK documentation topic, [CPixel Support Methods for Lightweight MIP Maps](http://msdn.microsoft.com/en-us/library/windows/hardware/ff540585). \ No newline at end of file
+For more information, see the WDK documentation topic, [CPixel Support Methods for Lightweight MIP Maps](https://docs.microsoft.com/windows-hardware/drivers/display/cpixel-support-methods-for-lightweight-mip-maps).
diff --git a/wia/README.md b/wia/README.md
index 07f8557a..2a2a8a59 100644
--- a/wia/README.md
+++ b/wia/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: Windows Image Acquisition (WIA) Driver Samples
- platform: WDM
- language: cpp
- category: Image Scan
- description: Contains samples and test tools for Windows Image Acquisition (WIA), a driver architecture and user interface for acquiring images from still image devices such as scanners.
- samplefwlink: https://go.microsoft.com/fwlink/p/?linkid=856747
---->
-
# Windows Image Acquisition (WIA) Driver Samples
The Windows Image Acquisition driver sample set contains samples and test tools for Windows Image Acquisition (WIA), a driver architecture and user interface for acquiring images from still image devices such as scanners.
@@ -28,7 +20,7 @@ The ProdScan directory contains a sample WIA 2.0 mini-driver. This sample shows
The Wiadriverex directory contains a sample WIA 2.0 mini-driver. This sample shows how to write a WIA 2.0 mini-driver that uses the stream-based WIA 2.0 transfer model. It also shows an implementation of a very simple segmentation filter, image processing filter, and error handling extension for the WIA 2.0 mini-driver.
-For more information, see [Introduction to WIA](http://msdn.microsoft.com/en-us/library/windows/hardware/ff542835).
+For more information, see [Introduction to WIA](https://docs.microsoft.com/windows-hardware/drivers/image/introduction-to-wia).
## Build the sample
@@ -56,4 +48,4 @@ Previous versions of the WDK used the Windows Build utility (Build.exe) and prov
## Run the sample
-Run the "copywia.cmd” batch file to gather all of the binaries into a subdirectory named “wiabins”. The WIA driver sample can be installed by using the Add Device icon in the Scanners and Cameras control panel. Use the Have Disk button to point to the wiabins\\drivers or wiabins\\drivers folder. Wiatest.exe (from the WDK Tools\\Wia directory), MS Paint, the Scanner and Camera Wizard, or any TWAIN application (through the WIA TWAIN compatibility layer) can be used to test the samples. \ No newline at end of file
+Run the "copywia.cmd” batch file to gather all of the binaries into a subdirectory named “wiabins”. The WIA driver sample can be installed by using the Add Device icon in the Scanners and Cameras control panel. Use the Have Disk button to point to the wiabins\\drivers or wiabins\\drivers folder. Wiatest.exe (from the WDK Tools\\Wia directory), MS Paint, the Scanner and Camera Wizard, or any TWAIN application (through the WIA TWAIN compatibility layer) can be used to test the samples.
diff --git a/wil b/wil
new file mode 160000
+Subproject 3c00e7f1d8cf9930bbb8e5be3ef0df65c84e892
diff --git a/wmi/wmiacpi/README.md b/wmi/wmiacpi/README.md
index 349c19b8..0afc710f 100644
--- a/wmi/wmiacpi/README.md
+++ b/wmi/wmiacpi/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: WMIACPI Sample
- platform: WDM
- language: cpp
- category: WMI ACPI
- description: Contains ACPI BIOS and WMI sample code that enables instrumentation of the ACPI BIOS from within ACPI Source Language (ASL) code.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=618006
---->
-
# WMI ACPI Sample
The WMIACPI sample contains ACPI BIOS and Microsoft Windows Management Instrumentation (WMI) sample code that enables instrumentation of the ACPI BIOS from within ACPI Source Language (ASL) code. ASL code can expose data blocks, methods, and events through WMI by leveraging the ACPI-WMI mapping driver (Wmiacpi.sys).
@@ -26,12 +18,12 @@ The WMIACPI sample contains files which allow an ACPI BIOS developer to add inst
The following table lists the files included in the sample and their function:
-| File | Description|
+| File | Description |
| --- | --- |
| Device.asl | ASL code that can be included in the ACPI bios that exposes a set of packages, strings, data, methods and events. |
| Acpimof.mof | Managed object format (MOF) file that contains a description of the data blocks, methods, and events that are exposed. This description is required so that WMI can access the data blocks, methods, and events. |
| Acpimof.rc<br>Acpimof.def | Files that are required to build Acpimof.dll, which is a resource-only DLL. |
-| Wmi-Acpi.htm | The *Windows Instrumentation: WMI and ACPI* whitepaper. |
+| Wmi-Acpi.htm | The *Windows Instrumentation: WMI and ACPI* white paper. |
| acpimov.vcxproj | Visual Studio project file for the sample. |
| acpimof.sln | Visual Studio solution file for the sample. |
@@ -40,8 +32,11 @@ The following table lists the files included in the sample and their function:
To add the sample code to your ACPI bios and access through WMI:
1. Include the contents of *Device.asl* to your ASL source and rebuild the DSDT. Update the operating system with the new DSDT through reflashing.
+
1. Build *Acpimof.dll* in the WMIACPI directory. *Acpimof.dll* is a resource-only DLL that contains the compiled MOF in a form that WMI can import into its schema.
+
1. Copy *Acpimof.dll* to %windir%\\system32 and add a value named "MofImagePath" under the HKEY\_LOCAL\_MACHINE\\CurrentControlSet\\Services\\WmiAcpi key. The contents of the value should be a path to the *Acpimof.dll* file.
+
1. Restart your computer. When Plug and Play (PnP) recognizes the new device with a pnpid of pnp0c14, it will install *Wmiacpi.sys* automatically and make the MOF resource in Acpimof.dll available to the WMI schema.
-Note that you do not need an INF file because Windows supplies an INF for the ACPI-WMI mapping driver device as part of the operating system. \ No newline at end of file
+Note that you do not need an INF file because Windows supplies an INF for the ACPI-WMI mapping driver device as part of the operating system.
diff --git a/wmi/wmisamp/README.md b/wmi/wmisamp/README.md
index 6cb95dfb..ae810493 100644
--- a/wmi/wmisamp/README.md
+++ b/wmi/wmisamp/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: WmiSamp WMI Provider
- platform: KMDF
- language: cpp
- category: WMI
- description: Demonstrates how to register WMI providers in KMDF, create provider instances, and handle WMI queries sent to a device.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=618007
---->
-
# Sample KMDF Driver Implementing a WMI Data Provider
WmiSamp WMI Provider is a sample KMDF driver that implements a WMI data provider.
@@ -30,9 +22,10 @@ The **Firefly**, **PCIDRV**, and **Toaster** sample drivers also implement WMI d
## Installation
-In Visual Studio, you can press F5 to build the sample and then deploy it to a target machine. For more information, see [Deploying a Driver to a Test Computer](http://msdn.microsoft.com/en-us/library/windows/hardware/hh454834).
+In Visual Studio, you can press F5 to build the sample and then deploy it to a target machine. For more information, see [Deploying a Driver to a Test Computer](https://docs.microsoft.com/windows-hardware/drivers/develop/deploying-a-driver-to-a-test-computer).
-**Note** You can obtain redistributable framework updates by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](http://go.microsoft.com/fwlink/p/?LinkID=226396). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0.
+> [!NOTE]
+> You can obtain redistributable framework updates by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](https://go.microsoft.com/fwlink/p/?LinkID=253170). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0.
## Testing
@@ -43,8 +36,12 @@ To test the WmiSamp driver, run the generated WmiSamp.vbs script file. This will
WmiMofCk validates that the classes, properties, methods and events specified in a binary mof file (.bmf) are valid for use with WMI. It also generates useful output files needed to build and test the WMI data provider.
- If the -h parameter is specified, a C language header file is created that defines the GUIDs, data structures, and method indices specified in the MOF file.
+
- If the -t parameter is specified, a VBScript applet is created that will query all data blocks and properties specified in the .mof file. This can be useful for testing WMI data providers.
+
- If the -x parameter is specified, a text file is created that contains the text representation of the binary .mof data. This can be included in the source of the driver if the driver supports reporting the binary .mof via a WMI query rather than a resource on the driver image file.
+
- Usage: wmimofck -h\<C Header output file\> -x\<Hexdump output file\> -t\<VBScript test output file\> \<binary mof input file\>
-**Note** A byproduct of compiling the .mof file is a .vbs file. This is a VBScript file that is run from the command line on the target machine running the new device driver. It will cause WMI to query all data blocks and properties, and put the results into a .log file. This can be very useful for testing WMI support in your driver. For more sophisticated testing, the VBScript can be extended by hand. \ No newline at end of file
+> [!NOTE]
+> A byproduct of compiling the .mof file is a .vbs file. This is a VBScript file that is run from the command line on the target machine running the new device driver. It will cause WMI to query all data blocks and properties, and put the results into a .log file. This can be very useful for testing WMI support in your driver. For more sophisticated testing, the VBScript can be extended by hand.
diff --git a/wpd/WpdBasicHardwareDriver/README.md b/wpd/WpdBasicHardwareDriver/README.md
index edde2a04..56414e93 100644
--- a/wpd/WpdBasicHardwareDriver/README.md
+++ b/wpd/WpdBasicHardwareDriver/README.md
@@ -5,17 +5,9 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: WPD Basic Hardware Sample Driver
- platform: UMDF1
- language: cpp
- category: WDP
- description: Supports nine sensor devices that integrate with the Parallax BS2 programmable microcontroller.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620318
---->
-
# WPD Basic Hardware Sample Driver (UMDF Version 1)
The WpdBasicHardwareDriver is a WPD driver that supports nine devices. These devices were selected because of their simplicity. This simplicity allowed the sample to focus on the tasks that are common to portable devices without getting bogged down in hardware complexities.
@@ -30,15 +22,15 @@ The circuit designs are based on the sample circuits provided by Parallax in the
The microcontroller firmware for each of the nine circuits is included in the **\\firmware** subdirectory of this sample.
-For a complete description of this sample and its underlying code and functionality, refer to the [WPD Basic Hardware Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff597697) description in the Windows Driver Kit documentation.
+For a complete description of this sample and its underlying code and functionality, refer to the [WPD Basic Hardware Driver](https://docs.microsoft.com/windows-hardware/drivers/portable/the-wpdbasichardwaredriver-sample) description in the Windows Driver Kit documentation.
## Related topics
-[WPD Design Guide](http://msdn.microsoft.com/en-us/library/windows/hardware/ff597864)
+[WPD Design Guide](https://docs.microsoft.com/windows-hardware/drivers/portable/wpd-design-guide)
-[WPD Driver Development Tools](http://msdn.microsoft.com/en-us/library/windows/hardware/ff597568)
+[WPD Driver Development Tools](https://docs.microsoft.com/windows-hardware/drivers/portable/familiarizing-yourself-with-the-sample-driver)
-[WPD Programming Guide](http://msdn.microsoft.com/en-us/library/windows/hardware/)
+[WPD Programming Guide](https://docs.microsoft.com/windows-hardware/drivers/portable/wpd-programming-guide)
## Installation
@@ -47,10 +39,14 @@ To test this sample, you must have a test computer. This can be a second compute
To install the WpdBasicHardwareDriver sample, do the following:
1. Copy the driver binary and the wpdbasichardwaredriver.inf file to a directory on your test computer (for example, C:\\wpdbasichardwaredriver.)
+
1. Copy the UMDF coinstaller, WUDFUpdate\_*MMmmmm*.dll, from the \\redist\\wdf\\\<architecture\> directory to the same directory (for example, C:\\wpdbasichardwaredriver).
- **Note** You can obtain the co-installers by downloading and installing the "Windows Driver Framework (WDF)" package from [WDK 8 Redistributable Components](http://go.microsoft.com/fwlink/p/?LinkID=226396).
+ > [!NOTE]
+ > You can obtain the co-installers by downloading and installing the "Windows Driver Framework (WDF)" package from [WDK 8 Redistributable Components](https://go.microsoft.com/fwlink/p/?LinkID=253170).
1. Navigate to the directory that contains the INF file and binaries (for example, cd /d c:\\wpdbasichardwaredriver), and run DevCon.exe as follows:
- **devcon.exe install wpdbasichardwaredriver.inf WUDF\\WpdBasicHardware**
- You can find DevCon.exe in the \\tools directory of the WDK (for example, \\tools\\devcon\\i386\\devcon.exe). \ No newline at end of file
+
+ `devcon.exe install wpdbasichardwaredriver.inf WUDF\WpdBasicHardware`
+
+ You can find DevCon.exe in the \\tools directory of the WDK (for example, \\tools\\devcon\\i386\\devcon.exe).
diff --git a/wpd/WpdHelloWorldDriver/README.md b/wpd/WpdHelloWorldDriver/README.md
index 8a480213..6942f4c6 100644
--- a/wpd/WpdHelloWorldDriver/README.md
+++ b/wpd/WpdHelloWorldDriver/README.md
@@ -5,82 +5,74 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: WPD Hello World Sample
- platform: UMDF1
- language: cpp
- category: WPD
- description: Supports four objects: a device object, a storage object, a folder object, and a file object.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=618008
---->
-
# WPDHelloWorld sample driver for portable devices
The WpdHelloWorld sample driver supports four objects: a device object, a storage object, a folder object, and a file object. Each object supports corresponding properties. These properties are defined in the file WpdObjectProperties.h.
The sample driver supports a device object that exposes ten read-only properties. These properties, their types, and their values are listed in the following table.
-Property name | Property type | Value
---------------|---------------|------
-DEVICE_PROTOCOL | String | "Hello World Protocol ver 1.00"
-DEVICE_FIRMWARE_VERSION | String | "1.0.0.0"
-DEVICE_POWER_LEVEL | Integer | 100
-DEVICE_MODEL | String | "Hello World!"
-DEVICE_MANUFACTURER | String | "Windows Portable Devices Group"
-DEVICE_FRIENDLY | String | "Hello World!"
-DEVICE_SERIAL_NUMBER | String | "01234567890123-45676890123456"
-DEVICE_SUPPORTS_NONCONSUMABLE | Bool | True
-WPD_DEVICE_TYPE | Integer | WPD_DEVICE_TYPE_GENERIC
-WPD_FUNCTIONAL_OBJECT_CATEGORY | GUID | WPD_FUNCTIONAL_CATEGORY_STORAGE
+| Property name | Property type | Value |
+| --- | --- | --- |
+| DEVICE_PROTOCOL | String | "Hello World Protocol ver 1.00" |
+| DEVICE_FIRMWARE_VERSION | String | "1.0.0.0" |
+| DEVICE_POWER_LEVEL | Integer | 100 |
+| DEVICE_MODEL | String | "Hello World!" |
+| DEVICE_MANUFACTURER | String | "Windows Portable Devices Group" |
+| DEVICE_FRIENDLY | String | "Hello World!" |
+| DEVICE_SERIAL_NUMBER | String | "01234567890123-45676890123456" |
+| DEVICE_SUPPORTS_NONCONSUMABLE | Bool | True |
+| WPD_DEVICE_TYPE | Integer | WPD_DEVICE_TYPE_GENERIC |
+| WPD_FUNCTIONAL_OBJECT_CATEGORY | GUID | WPD_FUNCTIONAL_CATEGORY_STORAGE |
The driver supports a storage object that exposes seven read-only properties. These properties, their types, and their values are listed in the following table.
-Property name | Property type | Value
---------------|---------------|------
-STORAGE_CAPACITY | 64-bit Integer | 1024 * 1024
-STORAGE_FREE_SPACE_IN_BYTES | 64-bit Integer | 1024 * 1024
-STORAGE_SERIAL_NUMBER | String | 98765432109876-54321098765432
-STORAGE_FILE_SYSTEM_TYPE | String | FAT32
-STORAGE_DESCRIPTION | String | Hello World! Memory Storage System
-WPD_STORAGE_TYPE | Integer | WPD_STORAGE_TYPE_FIXED_ROM
-WPD_FUNCTIONAL_OBJECT_CATEGORY | GUID | WPD_FUNCTIONAL_CATEGORY_STORAGE
+| Property name | Property type | Value |
+| --- | --- | --- |
+| STORAGE_CAPACITY | 64-bit Integer | 1024 * 1024 |
+| STORAGE_FREE_SPACE_IN_BYTES | 64-bit Integer | 1024 * 1024 |
+| STORAGE_SERIAL_NUMBER | String | 98765432109876-54321098765432 |
+| STORAGE_FILE_SYSTEM_TYPE | String | FAT32 |
+| STORAGE_DESCRIPTION | String | Hello World! Memory Storage System |
+| WPD_STORAGE_TYPE | Integer | WPD_STORAGE_TYPE_FIXED_ROM |
+| WPD_FUNCTIONAL_OBJECT_CATEGORY | GUID | WPD_FUNCTIONAL_CATEGORY_STORAGE |
The driver supports a folder object that exposes three read-only properties. These properties, their types, and their values are listed in the following table.
-Property name | Property type | Value
---------------|---------------|------
-WPD_OBJECT_DATE_MODIFIED | Date | 2006/6/26 5:0:0.0
-WPD_OBJECT_DATE_CREATED | Date | 2006/1/25 12:0:0.0
-WPD_OBJECT_ORIGINAL_FILE_NAME_VALUE | String | Documents
+| Property name | Property type | Value |
+| --- | --- | --- |
+| WPD_OBJECT_DATE_MODIFIED | Date | 2006/6/26 5:0:0.0 |
+| WPD_OBJECT_DATE_CREATED | Date | 2006/1/25 12:0:0.0 |
+| WPD_OBJECT_ORIGINAL_FILE_NAME_VALUE | String | Documents |
The driver supports a file object that exposes three read-only properties. These properties, their types, and their values are listed in the following table.
-Property name | Property type | Value
---------------|---------------|------
-WPD_OBJECT_DATE_MODIFIED | Date | 2006/6/26 5:0:0.0
-WPD_OBJECT_DATE_CREATED | Date | 2006/1/25 12:0:0.0
-WPD_OBJECT_ORIGINAL_FILE_NAME | String | Readme.txt
+| Property name | Property type | Value |
+| --- | --- | --- |
+| WPD_OBJECT_DATE_MODIFIED | Date | 2006/6/26 5:0:0.0 |
+| WPD_OBJECT_DATE_CREATED | Date | 2006/1/25 12:0:0.0 |
+| WPD_OBJECT_ORIGINAL_FILE_NAME | String | Readme.txt |
In addition to the above properties, every object (for example, device, storage, folder, or file) also supports seven common WPD object properties. These are read-only properties that contain object-specific values for the most part. These properties, their types, and their values are listed in the following table.
-Property name | Property type | Value
---------------|---------------|------
-WPD_OBJECT_ID | String | Object-specific
-WPD_OBJECT_PERSISTENT_UNIQUE_ID | String | Object-specific
-WPD_OBJECT_PARENT_ID | String | Object-specific
-WPD_OBJECT_NAME | String | Object-specific
-WPD_OBJECT_FORMAT | GUID | Object-specific
-WPD_OBJECT_CONTENT_TYPE | GUID | Object-specific
-WPD_OBJECT_CAN_DELETE | Bool | False
+| Property name | Property type | Value |
+| --- | --- | --- |
+| WPD_OBJECT_ID | String | Object-specific |
+| WPD_OBJECT_PERSISTENT_UNIQUE_ID | String | Object-specific |
+| WPD_OBJECT_PARENT_ID | String | Object-specific |
+| WPD_OBJECT_NAME | String | Object-specific |
+| WPD_OBJECT_FORMAT | GUID | Object-specific |
+| WPD_OBJECT_CONTENT_TYPE | GUID | Object-specific |
+| WPD_OBJECT_CAN_DELETE | Bool | False |
-For a complete description of this sample and its underlying code and functionality, refer to the [WPD HelloWorld Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/) description in the Windows Driver Kit documentation.
+For a complete description of this sample and its underlying code and functionality, refer to the [WPD HelloWorld Driver](https://docs.microsoft.com/windows-hardware/drivers/portable/the-sample-driver-architecture) description in the Windows Driver Kit documentation.
## Related topics
-[WPD Design Guide](http://msdn.microsoft.com/en-us/library/windows/hardware/ff597864)
+[WPD Design Guide](https://docs.microsoft.com/windows-hardware/drivers/portable/wpd-design-guide)
-[WPD Driver Development Tools](http://msdn.microsoft.com/en-us/library/windows/hardware/ff597568)
+[WPD Driver Development Tools](https://docs.microsoft.com/windows-hardware/drivers/portable/familiarizing-yourself-with-the-sample-driver)
-[WPD Programming Guide](https://msdn.microsoft.com/en-us/library/windows/hardware/ff597898) \ No newline at end of file
+[WPD Programming Guide](https://docs.microsoft.com/windows-hardware/drivers/portable/wpd-programming-guide)
diff --git a/wpd/WpdMultiTransportDriver/README.md b/wpd/WpdMultiTransportDriver/README.md
index 33fe6013..3656e8b9 100644
--- a/wpd/WpdMultiTransportDriver/README.md
+++ b/wpd/WpdMultiTransportDriver/README.md
@@ -5,29 +5,21 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: WPD multi-transport sample driver
- platform: UMDF1
- language: cpp
- category: WPD
- description: Demonstrates how to extend the WpdHelloWorldDriver for a device that supports multiple transports.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=618009
---->
-
# WPD multi-transport sample driver
The WpdMultiTransportDriver sample demonstrates how you could extend the WpdHelloWorldDriver for a device that supports multiple transports. A transport is a protocol over which a portable device communicates with a computer. Example transports include Internet Protocol (IP), Bluetooth, and USB.
A number of portable devices now support multiple transports. For example, a number of cell phones support both Bluetooth and USB. Windows supports a multitransport driver model that ensures that only one node appears for each device.
-For a complete description of this sample and its underlying code and functionality, refer to the [WPD MultiTransport Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff597709) description in the Windows Driver Kit documentation.
+For a complete description of this sample and its underlying code and functionality, refer to the [WPD MultiTransport Driver](https://docs.microsoft.com/windows-hardware/drivers/portable/the-wpdmultitransportdriver-sample) description in the Windows Driver Kit documentation.
## Related topics
-[WPD Design Guide](http://msdn.microsoft.com/en-us/library/windows/hardware/ff597864)
+[WPD Design Guide](https://docs.microsoft.com/windows-hardware/drivers/portable/wpd-design-guide)
-[WPD Driver Development Tools](http://msdn.microsoft.com/en-us/library/windows/hardware/ff597568)
+[WPD Driver Development Tools](https://docs.microsoft.com/windows-hardware/drivers/portable/familiarizing-yourself-with-the-sample-driver)
-[WPD Programming Guide](https://msdn.microsoft.com/en-us/library/windows/hardware/ff597898) \ No newline at end of file
+[WPD Programming Guide](https://docs.microsoft.com/windows-hardware/drivers/portable/wpd-programming-guide)
diff --git a/wpd/WpdServiceSampleDriver/README.md b/wpd/WpdServiceSampleDriver/README.md
index 66839ebd..4cd6b4dc 100644
--- a/wpd/WpdServiceSampleDriver/README.md
+++ b/wpd/WpdServiceSampleDriver/README.md
@@ -5,25 +5,17 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: WPD service sample driver
- platform: UMDF1
- language: cpp
- category: WPD
- description: Demonstrates how to extend the WpdHelloWorldDriver sample so that it supports a simulated device with a Contacts device service.
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=618010
---->
-
# WPD service sample driver
Demonstrates how to extend the WpdHelloWorldDriver sample so that it supports a simulated device with a Contacts device service.
## Related topics
-[WPD Design Guide](http://msdn.microsoft.com/en-us/library/windows/hardware/ff597864)
+[WPD Design Guide](https://docs.microsoft.com/windows-hardware/drivers/portable/wpd-design-guide)
-[WPD Driver Development Tools](http://msdn.microsoft.com/en-us/library/windows/hardware/ff597568)
+[WPD Driver Development Tools](https://docs.microsoft.com/windows-hardware/drivers/portable/familiarizing-yourself-with-the-sample-driver)
-[WPD Programming Guide](https://msdn.microsoft.com/en-us/library/windows/hardware/ff597898)
+[WPD Programming Guide](https://docs.microsoft.com/windows-hardware/drivers/portable/wpd-programming-guide)
diff --git a/wpd/WpdWudfSampleDriver/README.md b/wpd/WpdWudfSampleDriver/README.md
index 2072f547..63d7898f 100644
--- a/wpd/WpdWudfSampleDriver/README.md
+++ b/wpd/WpdWudfSampleDriver/README.md
@@ -5,31 +5,23 @@ languages:
- cpp
products:
- windows
+- windows-wdk
---
-<!---
- name: WPD WUDF sample driver
- platform: UMDF1
- language: cpp
- category: WPD
- description: Demonstrates virtually all aspects of the WPD device driver interface (DDI).
- samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=618011
---->
-
# WPD WUDF sample driver
-The comprehensive WPD sample driver (`WpdWudfSampleDriver`) demonstrates virtually all aspects of the Microsoft Windows Portable Devides (WPD) device driver interface (DDI). This driver is built as a normal User-Mode Driver Framework (UMDF) driver that also processes the WPD command set. Although this driver does not interact with actual hardware, it simulates communicating with a device that supports phone contacts, pictures, music, and video.
+The comprehensive WPD sample driver (WpdWudfSampleDriver) demonstrates virtually all aspects of the Microsoft Windows Portable Devices (WPD) device driver interface (DDI). This driver is built as a normal User-Mode Driver Framework (UMDF) driver that also processes the WPD command set. Although this driver does not interact with actual hardware, it simulates communicating with a device that supports phone contacts, pictures, music, and video.
This driver was written in the simplest way to demonstrate concepts. Therefore, the sample driver might perform operations or be structured in a way that are inefficient in a production driver. Additionally, this sample does not use real hardware. Instead, it simulates a device by using data structures in memory. Therefore, the driver might be implemented in a way that is unrealistic for production hardware.
-Some of the tasks that are accomplished by the `WpdWudfSampleDriver` are written for the advanced Windows Portable Devices (WPD) driver developer.
+Some of the tasks that are accomplished by the `WpdWudfSampleDriver` sample are written for the advanced Windows Portable Devices (WPD) driver developer.
-For a complete description of this sample and its underlying code and functionality, refer to the [WPD WUDF Sample Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff597723) description in the Windows Driver Kit documentation.
+For a complete description of this sample and its underlying code and functionality, refer to the [WPD WUDF Sample Driver](https://docs.microsoft.com/windows-hardware/drivers/portable/the-wpdwudfsampledriver-sample) description in the Windows Driver Kit documentation.
## Related topics
-[WPD Design Guide](http://msdn.microsoft.com/en-us/library/windows/hardware/ff597864)
+[WPD Design Guide](https://docs.microsoft.com/windows-hardware/drivers/portable/wpd-design-guide)
-[WPD Driver Development Tools](http://msdn.microsoft.com/en-us/library/windows/hardware/ff597568)
+[WPD Driver Development Tools](https://docs.microsoft.com/windows-hardware/drivers/portable/familiarizing-yourself-with-the-sample-driver)
-[WPD Programming Guide](https://msdn.microsoft.com/en-us/library/windows/hardware/ff597898) \ No newline at end of file
+[WPD Programming Guide](https://docs.microsoft.com/windows-hardware/drivers/portable/wpd-programming-guide)